aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/a2ps/APKBUILD53
-rw-r--r--main/a2ps/a2ps-4.13-manpage-chmod.patch12
-rw-r--r--main/a2ps/a2ps-4.13c-emacs.patch10
-rw-r--r--main/a2ps/a2ps-4.13c-fnmatch-replacement.patch43
-rw-r--r--main/a2ps/a2ps-4.14-check-mempcpy.patch12
-rw-r--r--main/a2ps/a2ps-4.14-fix-stpcpy-proto.patch17
-rw-r--r--main/a52dec/APKBUILD33
-rw-r--r--main/a52dec/a52dec-0.7.4-build.patch27
-rw-r--r--main/abiword/APKBUILD78
-rw-r--r--main/abiword/abiword-png15.patch81
-rw-r--r--main/abuild/0001-abuild-reset-triggers-for-subpackages.patch25
-rw-r--r--main/abuild/APKBUILD42
-rw-r--r--main/abuild/abuild.pre-install6
l---------main/abuild/abuild.pre-upgrade1
-rw-r--r--main/abuildhelper/APKBUILD25
-rw-r--r--main/acct/APKBUILD33
-rw-r--r--main/acf-alpine-baselayout/APKBUILD18
-rw-r--r--main/acf-alpine-conf/APKBUILD17
-rw-r--r--main/acf-amavisd-new/APKBUILD23
-rw-r--r--main/acf-apk-tools/APKBUILD18
-rw-r--r--main/acf-asterisk/APKBUILD23
-rw-r--r--main/acf-chrony/APKBUILD17
-rw-r--r--main/acf-clamav/APKBUILD23
-rw-r--r--main/acf-clamsmtp/APKBUILD23
-rw-r--r--main/acf-core/APKBUILD18
-rw-r--r--main/acf-core/acf-core.post-upgrade16
-rw-r--r--main/acf-dansguardian/APKBUILD23
-rw-r--r--main/acf-dhcp/APKBUILD23
-rw-r--r--main/acf-dnscache/APKBUILD17
-rw-r--r--main/acf-dnsmasq/APKBUILD17
-rw-r--r--main/acf-dovecot/APKBUILD23
-rw-r--r--main/acf-fetchmail/APKBUILD23
-rw-r--r--main/acf-freeswitch-vmail/APKBUILD21
-rw-r--r--main/acf-freeswitch-vmail/acf-freeswitch-vmail.post-upgrade14
-rw-r--r--main/acf-freeswitch/APKBUILD23
-rw-r--r--main/acf-gross/APKBUILD17
-rw-r--r--main/acf-heimdal/APKBUILD23
-rw-r--r--main/acf-iproute2-qos/APKBUILD18
-rw-r--r--main/acf-ipsec-tools/APKBUILD17
-rw-r--r--main/acf-iptables/APKBUILD23
-rw-r--r--main/acf-jquery/APKBUILD18
-rw-r--r--main/acf-kamailio/APKBUILD23
-rw-r--r--main/acf-lib/APKBUILD17
-rw-r--r--main/acf-lvm2/APKBUILD23
-rw-r--r--main/acf-mdadm/APKBUILD23
-rw-r--r--main/acf-opennhrp/APKBUILD17
-rw-r--r--main/acf-openntpd/APKBUILD23
-rw-r--r--main/acf-openssh/APKBUILD17
-rw-r--r--main/acf-openssl/APKBUILD23
-rw-r--r--main/acf-openvpn/APKBUILD23
-rw-r--r--main/acf-pingu/APKBUILD23
-rw-r--r--main/acf-postfix/APKBUILD23
-rw-r--r--main/acf-postgresql/APKBUILD23
-rw-r--r--main/acf-ppp/APKBUILD17
-rw-r--r--main/acf-provisioning/APKBUILD21
-rw-r--r--main/acf-provisioning/acf-provisioning.post-upgrade51
-rw-r--r--main/acf-quagga/APKBUILD17
-rw-r--r--main/acf-samba/APKBUILD23
-rw-r--r--main/acf-shorewall/APKBUILD17
-rw-r--r--main/acf-skins/APKBUILD17
-rw-r--r--main/acf-snort/APKBUILD23
-rw-r--r--main/acf-squid/APKBUILD23
-rw-r--r--main/acf-tcpproxy/APKBUILD23
-rw-r--r--main/acf-tinydns/APKBUILD17
-rw-r--r--main/acf-weblog/APKBUILD21
-rw-r--r--main/acf-weblog/acf-weblog.post-upgrade42
-rw-r--r--main/ack/APKBUILD28
-rw-r--r--main/acl/APKBUILD57
-rw-r--r--main/acl/quote-strchr.patch25
-rw-r--r--main/alpine-base/APKBUILD42
-rw-r--r--main/alpine-baselayout/APKBUILD30
-rw-r--r--main/alpine-baselayout/alpine-baselayout.pre-upgrade15
-rw-r--r--main/alpine-conf/0001-setup-xorg-base-initial-commit.patch74
-rw-r--r--main/alpine-conf/0002-setup-gparted-desktop-new-setup-script.patch75
-rw-r--r--main/alpine-conf/0003-setup-disk-fix-data-only-mode-with-no-lvm-and-no-rai.patch28
-rw-r--r--main/alpine-conf/APKBUILD45
-rw-r--r--main/alpine-desktop/APKBUILD49
-rw-r--r--main/alpine-desktop/alpine-desktop.post-install9
-rw-r--r--main/alpine-mirrors/APKBUILD30
-rw-r--r--main/alpine-mirrors/RELEASES.txt2
-rw-r--r--main/alpine-sdk/APKBUILD14
-rw-r--r--main/alpine/APKBUILD49
-rw-r--r--main/alpine/CVE-2008-5514.patch20
-rw-r--r--main/alpine/all_p84.patch26592
-rw-r--r--main/alsa-lib/APKBUILD34
-rw-r--r--main/alsa-utils/APKBUILD59
-rw-r--r--main/alsa-utils/alsa.confd31
-rw-r--r--main/alsa-utils/alsa.initd218
-rw-r--r--main/alsa-utils/alsaconf.patch12
-rw-r--r--main/alsa-utils/uclibc-exp10.patch25
-rw-r--r--main/amavisd-new/APKBUILD47
-rwxr-xr-xmain/amavisd-new/amavisd-new.post-install5
-rwxr-xr-xmain/amavisd-new/amavisd-new.pre-install6
-rw-r--r--main/amavisd-new/amavisd.init23
-rw-r--r--main/antiword/APKBUILD29
-rw-r--r--main/aoetools/APKBUILD28
-rw-r--r--main/apache-mod-auth-ntlm-winbind/APKBUILD35
-rw-r--r--main/apache-mod-auth-ntlm-winbind/mod-auth-ntlm-winbind.conf1
-rw-r--r--main/apache2/APKBUILD254
-rw-r--r--main/apache2/alpine.layout22
-rw-r--r--main/apache2/apache2-ssl.post-install32
-rw-r--r--main/apache2/apache2.confd54
-rwxr-xr-xmain/apache2/apache2.initd154
-rw-r--r--main/apache2/apache2.logrotate10
-rw-r--r--main/apache2/httpd.conf1026
-rw-r--r--main/apache2/ldap.conf2
-rw-r--r--main/apache2/ssl.conf223
-rw-r--r--main/apcupsd/APKBUILD37
-rw-r--r--main/apcupsd/apcupsd-alpine.patch41
-rw-r--r--main/apcupsd/apcupsd.initd38
-rw-r--r--main/apg/APKBUILD25
-rw-r--r--main/apk-tools/0001-db-remount-read-only-after-the-file-handles-have-bee.patch45
-rw-r--r--main/apk-tools/0002-db-more-fix-for-read-only-cache-remounting.patch91
-rw-r--r--main/apk-tools/APKBUILD55
-rw-r--r--main/apr-util/APKBUILD56
-rw-r--r--main/apr/APKBUILD49
-rw-r--r--main/arpon/APKBUILD42
-rw-r--r--main/arpon/arpon.confd1
-rw-r--r--main/arpon/arpon.initd24
-rw-r--r--main/arpwatch/APKBUILD37
-rw-r--r--main/arpwatch/arpwatch.confd12
-rw-r--r--main/arpwatch/arpwatch.initd38
-rw-r--r--main/asciidoc/APKBUILD42
-rw-r--r--main/asciidoc/vim.patch11
-rw-r--r--main/aspell-en/APKBUILD27
-rw-r--r--main/aspell/APKBUILD35
-rw-r--r--main/aspell/libmath.patch11
-rw-r--r--main/asterisk-audio-konf/APKBUILD70
-rw-r--r--main/asterisk/100-uclibc-daemon.patch44
-rw-r--r--main/asterisk/101-caps-uclibc.patch17
-rw-r--r--main/asterisk/102-gsm-pic.patch54
-rw-r--r--main/asterisk/400-bug-227.patch15
-rw-r--r--main/asterisk/APKBUILD165
-rw-r--r--main/asterisk/asterisk.confd91
-rw-r--r--main/asterisk/asterisk.initd251
-rw-r--r--main/asterisk/asterisk.logrotate17
-rw-r--r--main/asterisk/asterisk.post-install11
-rw-r--r--main/asterisk/asterisk.pre-install12
l---------main/asterisk/asterisk.pre-upgrade1
-rw-r--r--main/aterm/APKBUILD29
-rw-r--r--main/aterm/uclibc.patch16
-rw-r--r--main/atk/APKBUILD29
-rw-r--r--main/atkmm/APKBUILD28
-rw-r--r--main/atop/APKBUILD46
-rw-r--r--main/atop/atop-bb-compat.patch35
-rw-r--r--main/atop/atop.initd21
-rw-r--r--main/attr/APKBUILD69
-rw-r--r--main/attr/attr-2.4.32-build.patch40
-rw-r--r--main/audacious-plugins/APKBUILD87
-rw-r--r--main/audacious-plugins/audacious-plugins-2.5.1-vorbis.patch54
-rw-r--r--main/audacious/APKBUILD24
-rw-r--r--main/augeas/APKBUILD42
-rw-r--r--main/aumix/APKBUILD36
-rw-r--r--main/aumix/aumix.initd42
-rw-r--r--main/autoconf/APKBUILD39
-rw-r--r--main/autoconf2.13/APKBUILD40
-rw-r--r--main/automake/APKBUILD25
-rw-r--r--main/avahi/APKBUILD118
-rw-r--r--main/avahi/avahi.pre-install13
-rw-r--r--main/avahi/gnome-nettool.pngbin0 -> 4509 bytes
-rw-r--r--main/awstats/APKBUILD59
-rw-r--r--main/b43-fwcutter/APKBUILD28
-rw-r--r--main/babl/APKBUILD26
-rw-r--r--main/backuppc/APKBUILD67
-rw-r--r--main/backuppc/backuppc.initd43
-rw-r--r--main/backuppc/backuppc.post-install8
-rw-r--r--main/backuppc/backuppc.pre-install4
-rw-r--r--main/backuppc/configure.pl.patch66
-rw-r--r--main/bacula-client/APKBUILD97
-rw-r--r--main/bacula-client/bacula-5.0.1-dsolink.patch11
-rw-r--r--main/bacula-client/bacula-5.0.2-config.patch12
-rw-r--r--main/bacula-client/bacula-5.0.2-openssl.patch24
-rw-r--r--main/bacula-client/bacula-5.0.2-python27.patch22
-rw-r--r--main/bacula-client/bacula-5.0.3-Makefile.patch26
-rw-r--r--main/bacula-client/bacula-5.0.3-as-needed.patch33
-rw-r--r--main/bacula-client/bacula-5.0.3-dsolink.patch165
-rw-r--r--main/bacula-client/bacula-5.0.3-log-path.patch13
-rw-r--r--main/bacula-client/bacula-5.0.3-mysql55.patch11
-rw-r--r--main/bacula-client/bacula-5.0.3-sqlite-priv.patch9
-rw-r--r--main/bacula-client/bacula-client.post-install2
-rw-r--r--main/bacula-client/bacula-client.pre-install4
-rw-r--r--main/bacula-client/bacula-config.patch115
-rw-r--r--main/bacula-client/bacula-fd-conf4
-rw-r--r--main/bacula-client/bacula-fd-init22
-rw-r--r--main/bacula-client/configure.in.patch23
-rw-r--r--main/bacula-client/cxx.patch13
-rw-r--r--main/bacula-client/os.m4.patch12
-rw-r--r--main/bacula/APKBUILD124
-rw-r--r--main/bacula/bacula-5.0.1-dsolink.patch11
-rw-r--r--main/bacula/bacula-5.0.2-config.patch12
-rw-r--r--main/bacula/bacula-5.0.2-openssl.patch24
-rw-r--r--main/bacula/bacula-5.0.2-python27.patch22
-rw-r--r--main/bacula/bacula-5.0.3-Makefile.patch26
-rw-r--r--main/bacula/bacula-5.0.3-as-needed.patch33
-rw-r--r--main/bacula/bacula-5.0.3-dsolink.patch165
-rw-r--r--main/bacula/bacula-5.0.3-log-path.patch13
-rw-r--r--main/bacula/bacula-5.0.3-mysql55.patch11
-rw-r--r--main/bacula/bacula-5.0.3-sqlite-priv.patch9
-rw-r--r--main/bacula/bacula-config.patch115
-rw-r--r--main/bacula/bacula-dir-conf7
-rw-r--r--main/bacula/bacula-dir-init23
-rw-r--r--main/bacula/bacula-fd-conf4
-rw-r--r--main/bacula/bacula-fd-init22
-rw-r--r--main/bacula/bacula-sd-conf7
-rw-r--r--main/bacula/bacula-sd-init22
-rw-r--r--main/bacula/bacula.post-install11
-rw-r--r--main/bacula/bacula.pre-install4
-rw-r--r--main/bacula/configure.in.patch23
-rw-r--r--main/bacula/cxx.patch13
-rw-r--r--main/bacula/os.m4.patch12
-rw-r--r--main/bash/APKBUILD80
-rw-r--r--main/bash/bash-noinfo.patch12
-rw-r--r--main/bbsuid/APKBUILD20
-rw-r--r--main/bc/APKBUILD28
-rw-r--r--main/bdftopcf/APKBUILD28
-rw-r--r--main/beecrypt/APKBUILD45
-rw-r--r--main/beecrypt/beecrypt-4.1.2-base64.patch11
-rw-r--r--main/beep/APKBUILD32
-rw-r--r--main/bigreqsproto/APKBUILD23
-rw-r--r--main/bind/APKBUILD105
-rw-r--r--main/bind/bind.127.zone11
-rw-r--r--main/bind/bind.conf53
-rw-r--r--main/bind/bind.confd14
-rw-r--r--main/bind/bind.initd25
-rw-r--r--main/bind/bind.localhost.zone11
-rw-r--r--main/bind/bind.named.ca85
-rw-r--r--main/bind/bind.post-install5
-rw-r--r--main/bind/bind.pre-install5
-rw-r--r--main/bind/bind.so_bsdcompat.patch11
-rw-r--r--main/binutils/APKBUILD38
-rw-r--r--main/bison/APKBUILD32
-rw-r--r--main/bitlbee/APKBUILD58
-rw-r--r--main/bitlbee/bitlbee.confd9
-rw-r--r--main/bitlbee/bitlbee.initd29
-rw-r--r--main/bitlbee/bitlbee.post-install4
-rw-r--r--main/bkeymaps/APKBUILD16
-rw-r--r--main/bluez-firmware/APKBUILD23
-rw-r--r--main/bluez-hcidump/APKBUILD37
-rw-r--r--main/bluez/APKBUILD81
-rw-r--r--main/bluez/bluetooth-conf.d7
-rw-r--r--main/bluez/bluetooth-init.d31
-rw-r--r--main/bluez/bluetooth.confd7
-rw-r--r--main/bluez/bluetooth.initd32
-rw-r--r--main/boost/APKBUILD136
-rw-r--r--main/bridge-utils/APKBUILD27
-rw-r--r--main/bsnes/APKBUILD45
-rw-r--r--main/bsnes/nall-strlcpy.patch31
-rw-r--r--main/bsnes/no-pulseaudio.patch11
-rw-r--r--main/build-base/APKBUILD18
-rw-r--r--main/busybox-initscripts/APKBUILD64
-rw-r--r--main/busybox-initscripts/acpid.initd20
-rw-r--r--main/busybox-initscripts/busybox-initscripts.post-install9
-rw-r--r--main/busybox-initscripts/cron.confd3
-rw-r--r--main/busybox-initscripts/cron.initd19
-rw-r--r--main/busybox-initscripts/dnsd.initd18
-rw-r--r--main/busybox-initscripts/dvbdev18
-rw-r--r--main/busybox-initscripts/httpd.initd21
-rw-r--r--main/busybox-initscripts/ide_links23
-rw-r--r--main/busybox-initscripts/inetd.initd19
-rw-r--r--main/busybox-initscripts/klogd.confd1
-rw-r--r--main/busybox-initscripts/klogd.initd21
-rw-r--r--main/busybox-initscripts/mdev-mount.initd64
-rw-r--r--main/busybox-initscripts/mdev.conf110
-rw-r--r--main/busybox-initscripts/mdev.initd33
-rw-r--r--main/busybox-initscripts/rdate.confd2
-rw-r--r--main/busybox-initscripts/rdate.initd17
-rw-r--r--main/busybox-initscripts/syslog.confd1
-rw-r--r--main/busybox-initscripts/syslog.initd19
-rw-r--r--main/busybox-initscripts/usbdev62
-rw-r--r--main/busybox-initscripts/usbdisk_link34
-rw-r--r--main/busybox-initscripts/watchdog.confd3
-rw-r--r--main/busybox-initscripts/watchdog.initd25
-rw-r--r--main/busybox-initscripts/xvd_links12
-rw-r--r--main/busybox/APKBUILD91
-rw-r--r--main/busybox/busybox-1.11.1-bb.patch12
-rw-r--r--main/busybox/busybox-uname-is-not-gnu.patch20
-rw-r--r--main/busybox/busybox.post-install3
l---------main/busybox/busybox.post-upgrade1
-rw-r--r--main/busybox/busybox.trigger20
-rw-r--r--main/busybox/busyboxconfig986
-rw-r--r--main/busybox/loginutils-sha512.patch154
-rw-r--r--main/bwm-ng/APKBUILD27
-rw-r--r--main/byobu/APKBUILD31
-rw-r--r--main/bzip2/APKBUILD74
-rw-r--r--main/bzip2/bzip2-1.0.2-progress.patch175
-rw-r--r--main/bzip2/bzip2-1.0.3-no-test.patch9
-rw-r--r--main/bzip2/bzip2-1.0.4-POSIX-shell.patch21
-rw-r--r--main/bzip2/bzip2-1.0.4-makefile-CFLAGS.patch25
-rw-r--r--main/bzip2/bzip2-1.0.4-man-links.patch12
-rw-r--r--main/bzip2/bzip2-1.0.6-saneso.patch13
-rw-r--r--main/bzip2/bzip2.post-deinstall3
-rw-r--r--main/bzr/APKBUILD29
-rw-r--r--main/c-ares/APKBUILD31
-rw-r--r--main/ca-certificates/APKBUILD29
-rw-r--r--main/ca-certificates/ca-certificates.post-install5
-rw-r--r--main/cabextract/APKBUILD27
-rw-r--r--main/cacti/APKBUILD49
-rw-r--r--main/cairo/APKBUILD50
-rw-r--r--main/cairomm/APKBUILD28
-rw-r--r--main/ccache/APKBUILD37
-rw-r--r--main/cciss_vol_status/APKBUILD36
-rw-r--r--main/cdrkit/APKBUILD35
-rw-r--r--main/cgit/APKBUILD47
-rw-r--r--main/chrony/APKBUILD71
-rw-r--r--main/chrony/chrony-1.20-chrony.conf.example-gentoo.diff46
-rw-r--r--main/chrony/chrony-1.20-conf.c-gentoo.diff11
-rw-r--r--main/chrony/chrony-1.21-makefile.diff15
-rw-r--r--main/chrony/chrony-1.23-reply-ip.diff242
-rw-r--r--main/chrony/chrony-1.23-sources.diff56
-rw-r--r--main/chrony/chrony.conf7
-rw-r--r--main/chrony/chrony.logrotate11
-rw-r--r--main/chrony/chronyd.confd12
-rw-r--r--main/chrony/chronyd.initd69
-rw-r--r--main/cksfv/APKBUILD23
-rw-r--r--main/clamav/APKBUILD158
-rw-r--r--main/clamav/clamav-0.95.1-nls.patch11
-rw-r--r--main/clamav/clamav-daemon.post-install3
-rw-r--r--main/clamav/clamav-daemon.pre-install4
-rw-r--r--main/clamav/clamav-daemon.pre-upgrade11
-rw-r--r--main/clamav/clamav-db.post-install3
-rw-r--r--main/clamav/clamav-db.pre-install4
-rw-r--r--main/clamav/clamav-db.pre-upgrade11
-rw-r--r--main/clamav/clamd.confd6
-rw-r--r--main/clamav/clamd.initd57
-rw-r--r--main/clamav/clamd.logrotate8
-rw-r--r--main/clamav/freshclam.confd3
-rw-r--r--main/clamav/freshclam.initd59
-rw-r--r--main/clamav/freshclam.logrotate7
-rw-r--r--main/clamsmtp/APKBUILD42
-rw-r--r--main/clamsmtp/clamsmtp.post-upgrade17
-rw-r--r--main/clamsmtp/clamsmtp.pre-install4
-rw-r--r--main/clamsmtp/clamsmtp.pre-upgrade14
-rw-r--r--main/clamsmtp/clamsmtpd.confd5
-rw-r--r--main/clamsmtp/clamsmtpd.initd23
-rw-r--r--main/claws-mail/APKBUILD61
-rw-r--r--main/claws-mail/libc-version.patch22
-rw-r--r--main/claws-mail/startup-notification-segfault.patch18
-rw-r--r--main/cmake/APKBUILD46
-rw-r--r--main/cmph/APKBUILD42
-rw-r--r--main/collectd/APKBUILD92
-rw-r--r--main/collectd/collectd-4.10.3-iptc-check.patch20
-rw-r--r--main/collectd/collectd.initd20
-rw-r--r--main/compositeproto/APKBUILD24
-rw-r--r--main/confuse/APKBUILD31
-rw-r--r--main/conky/APKBUILD40
-rw-r--r--main/conntrack-tools/APKBUILD29
-rw-r--r--main/conntrack-tools/conntrackd.confd15
-rw-r--r--main/conntrack-tools/conntrackd.initd100
-rw-r--r--main/consolekit/0001-busybox-reboot-and-poweroff-support.patch41
-rw-r--r--main/consolekit/APKBUILD51
-rw-r--r--main/consolekit/pam-foreground-compat.ck17
-rw-r--r--main/coova-chilli/APKBUILD52
-rwxr-xr-xmain/coova-chilli/chilli.initd42
-rw-r--r--main/coova-chilli/coova-chilli-ssl.patch21
-rw-r--r--main/coreutils/APKBUILD44
-rw-r--r--main/coreutils/coreutils.post-deinstall3
l---------main/coreutils/coreutils.post-upgrade1
-rw-r--r--main/cowdancer/APKBUILD42
-rw-r--r--main/cowdancer/cowdancer-disable-cowbuilder.patch42
-rw-r--r--main/cowdancer/cowdancer-no-vsym.patch33
-rw-r--r--main/cpufreqd/APKBUILD32
-rw-r--r--main/cpufreqd/cpufreqd.initd43
-rw-r--r--main/cpufrequtils/0001-Support-for-Position-Independet-Code-by-aboid-clobbe.patch33
-rw-r--r--main/cpufrequtils/APKBUILD47
-rw-r--r--main/cpufrequtils/cpufrequtils-006-nls.patch75
-rw-r--r--main/cpufrequtils/cpufrequtils.confd7
-rw-r--r--main/cpufrequtils/cpufrequtils.initd22
-rw-r--r--main/cracklib-words/APKBUILD22
-rw-r--r--main/cracklib/APKBUILD45
-rw-r--r--main/cracklib/cracklib-nls.patch12
-rw-r--r--main/cramfs/APKBUILD24
-rw-r--r--main/cryptsetup/APKBUILD36
-rw-r--r--main/ctags/APKBUILD27
-rw-r--r--main/cups/APKBUILD97
-rw-r--r--main/cups/cups.logrotate8
-rw-r--r--main/cups/cupsd.initd20
-rw-r--r--main/curl/APKBUILD42
-rw-r--r--main/cutter/APKBUILD28
-rw-r--r--main/cvs/APKBUILD34
-rw-r--r--main/cyrus-sasl/APKBUILD65
-rw-r--r--main/cyrus-sasl/cyrus-sasl-2.1.19-checkpw.c.patch170
-rw-r--r--main/cyrus-sasl/cyrus-sasl-2.1.23-db5-fix.patch23
-rw-r--r--main/cyrus-sasl/saslauthd.initd22
-rw-r--r--main/dahdi-linux-grsec/APKBUILD82
-rw-r--r--main/dahdi-linux-grsec/dahdi-bri_dchan.patch161
-rw-r--r--main/dahdi-linux-grsec/dahdi-depmod.patch22
-rw-r--r--main/dahdi-linux-grsec/dahdi-zaphfc.patch1429
-rw-r--r--main/dahdi-linux-grsec/zaphfc-dahdi-2.4.0.patch58
-rw-r--r--main/dahdi-linux-grsec/zaphfc-dahdi-flortz.diff1232
-rw-r--r--main/dahdi-linux-vserver/APKBUILD81
-rw-r--r--main/dahdi-linux-vserver/dahdi-bri_dchan.patch161
-rw-r--r--main/dahdi-linux-vserver/dahdi-depmod.patch22
-rw-r--r--main/dahdi-linux-vserver/dahdi-zaphfc.patch1430
-rw-r--r--main/dahdi-linux-vserver/zaphfc-dahdi-2.4.0.patch58
-rw-r--r--main/dahdi-linux-vserver/zaphfc-dahdi-flortz.diff1232
-rw-r--r--main/dahdi-linux/APKBUILD42
-rw-r--r--main/dahdi-tools/APKBUILD39
-rw-r--r--main/dahdi-tools/dahdi-tools.initd21
-rw-r--r--main/damageproto/APKBUILD23
-rw-r--r--main/dansguardian/APKBUILD49
-rw-r--r--main/dansguardian/dansguardian-2.10.1.1-gcc44.patch37
-rw-r--r--main/dansguardian/dansguardian.initd33
-rw-r--r--main/dansguardian/dansguardian.logrotate15
-rw-r--r--main/dansguardian/dansguardian.post-install5
-rw-r--r--main/dansguardian/dansguardian.pre-install5
-rw-r--r--main/dansguardian/ftp-credential.patch41
-rw-r--r--main/daq/APKBUILD45
-rw-r--r--main/db/APKBUILD48
-rw-r--r--main/db/patch.4.7.25.175
-rw-r--r--main/db/patch.4.7.25.271
-rw-r--r--main/db/patch.4.7.25.3314
-rw-r--r--main/db/patch.4.7.25.4183
-rw-r--r--main/dbus-glib/APKBUILD31
-rw-r--r--main/dbus/APKBUILD45
-rw-r--r--main/dbus/dbus.initd51
-rw-r--r--main/dbus/dbus.post-install3
-rw-r--r--main/dbus/dbus.pre-install5
-rw-r--r--main/dbus/dbus.trigger4
-rw-r--r--main/dconf/0001-Avoid-posix_fallocate-so-it-works-on-uClibc.patch36
-rw-r--r--main/dconf/APKBUILD42
-rw-r--r--main/debootstrap/APKBUILD46
-rw-r--r--main/debootstrap/pkgdetails.c209
-rw-r--r--main/desktop-file-utils/APKBUILD26
-rw-r--r--main/desktop-file-utils/desktop-file-utils.trigger3
-rw-r--r--main/dhcp/APKBUILD84
-rw-r--r--main/dhcp/dhcp-3.0-fix-perms.patch15
-rw-r--r--main/dhcp/dhcp.post-install5
-rw-r--r--main/dhcp/dhcp.post-upgrade19
-rw-r--r--main/dhcp/dhcp.pre-install5
-rw-r--r--main/dhcp/dhcp.pre-upgrade8
-rw-r--r--main/dhcp/dhcpd.confd30
-rw-r--r--main/dhcp/dhcpd.initd95
-rw-r--r--main/dhcp/dhcrelay.confd13
-rw-r--r--main/dhcp/dhcrelay.initd33
-rw-r--r--main/dhcp/linux_ipv6_discover.patch50
-rw-r--r--main/dhcpcd-dbus/APKBUILD29
-rw-r--r--main/dhcpcd-ui/APKBUILD26
-rw-r--r--main/dhcpcd/APKBUILD32
-rw-r--r--main/dhcpcd/dhcpcd.initd17
-rw-r--r--main/dialog/APKBUILD31
-rw-r--r--main/diffutils/APKBUILD31
-rw-r--r--main/diffutils/diffutils.post-deinstall2
-rw-r--r--main/dircproxy/1.0.5-CVE-2007-5226.patch12
-rw-r--r--main/dircproxy/1.1.0-less-lag-on-attach.patch53
-rw-r--r--main/dircproxy/APKBUILD41
-rw-r--r--main/dircproxy/dircproxy-gcc4.patch47
-rw-r--r--main/distcc/APKBUILD54
-rw-r--r--main/distcc/distcc-3.1-clone.patch14
-rw-r--r--main/distcc/distcc-hardened.patch24
-rw-r--r--main/distcc/distccd.confd45
-rw-r--r--main/distcc/distccd.initd39
-rw-r--r--main/djbdns/1.05-errno.patch11
-rw-r--r--main/djbdns/1.05-response.patch11
-rw-r--r--main/djbdns/APKBUILD105
-rw-r--r--main/djbdns/djbdns-1.05-jumbo-josb.patch1858
-rw-r--r--main/djbdns/dnscache.confd25
-rwxr-xr-xmain/djbdns/dnscache.initd46
-rwxr-xr-xmain/djbdns/dnscache.monthly46
-rw-r--r--main/djbdns/dnscache.pre-install5
-rw-r--r--main/djbdns/dnsroots.patch20
-rw-r--r--main/djbdns/dnstracesort.patch11
-rw-r--r--main/djbdns/headtail.patch67
-rw-r--r--main/djbdns/tinydns.confd2
-rwxr-xr-xmain/djbdns/tinydns.initd92
-rw-r--r--main/djbdns/tinydns.pre-install5
-rw-r--r--main/dmidecode/APKBUILD37
-rw-r--r--main/dnsmasq/APKBUILD41
-rw-r--r--main/dnsmasq/dnsmasq.confd4
-rw-r--r--main/dnsmasq/dnsmasq.initd38
-rw-r--r--main/docbook-xml/APKBUILD258
-rw-r--r--main/docbook-xml/docbook-xml.post-deinstall5
-rw-r--r--main/docbook-xml/docbook-xml.post-install23
-rw-r--r--main/docbook-xml/docbook-xml.post-upgrade21
-rw-r--r--main/docbook-xsl/APKBUILD42
-rw-r--r--main/docbook-xsl/docbook-xsl.install47
-rw-r--r--main/docbook-xsl/docbook-xsl.post-deinstall10
-rw-r--r--main/docbook-xsl/docbook-xsl.post-install29
-rw-r--r--main/docbook-xsl/docbook-xsl.post-upgrade33
-rw-r--r--main/dosfstools/APKBUILD26
-rw-r--r--main/dovecot/2281223b9cb9.patch21
-rw-r--r--main/dovecot/APKBUILD102
-rw-r--r--main/dovecot/dovecot-sample-config.post-install10
-rw-r--r--main/dovecot/dovecot.initd59
-rw-r--r--main/dovecot/dovecot.logrotate15
-rw-r--r--main/dovecot/dovecot.post-install54
-rw-r--r--main/dovecot/dovecot.pre-install5
-rw-r--r--main/doxygen/APKBUILD46
-rw-r--r--main/dpkg/APKBUILD61
-rw-r--r--main/dri2proto/APKBUILD25
-rw-r--r--main/dropbear/APKBUILD39
-rw-r--r--main/dropbear/dropbear.confd6
-rw-r--r--main/dropbear/dropbear.initd37
-rw-r--r--main/dtach/APKBUILD24
-rw-r--r--main/duplicity/APKBUILD33
-rw-r--r--main/dvgrab/APKBUILD43
-rw-r--r--main/e2fsprogs/0001-implement-com_right_r.patch59
-rw-r--r--main/e2fsprogs/APKBUILD49
-rw-r--r--main/e2fsprogs/e2fsprogs.post-upgrade4
-rw-r--r--main/eboard/APKBUILD44
-rw-r--r--main/eboard/eboard.desktop7
-rw-r--r--main/ebtables/0001-link-with-gcc.patch25
-rw-r--r--main/ebtables/APKBUILD59
-rw-r--r--main/ebtables/ebtables.confd15
-rw-r--r--main/ebtables/ebtables.initd97
-rw-r--r--main/eggdbus/APKBUILD40
-rw-r--r--main/eggdrop/APKBUILD68
-rw-r--r--main/eggdrop/eggdrop-installer84
-rw-r--r--main/eggdrop/eggdrop.post-install6
-rw-r--r--main/eggdrop/gseen.mod.patch5123
-rw-r--r--main/eggdrop/logs2html.mod.patch2404
-rw-r--r--main/elinks/APKBUILD40
-rw-r--r--main/email/APKBUILD30
-rw-r--r--main/email/email-3.1.0-doc.patch10
-rw-r--r--main/email/email-3.1.0-ldflags.patch11
-rw-r--r--main/enca/APKBUILD42
-rw-r--r--main/enchant/APKBUILD26
-rw-r--r--main/encodings/APKBUILD25
-rw-r--r--main/epdfview/APKBUILD56
-rw-r--r--main/epdfview/epdfview.desktop.patch11
-rw-r--r--main/epdfview/fix-scrolling.patch33
-rw-r--r--main/epris/APKBUILD30
-rw-r--r--main/espeak/APKBUILD26
-rw-r--r--main/ethtool/APKBUILD22
-rw-r--r--main/evince/APKBUILD46
-rw-r--r--main/exiv2/APKBUILD28
-rw-r--r--main/exo/APKBUILD34
-rw-r--r--main/expat/APKBUILD43
-rw-r--r--main/expat/CVE-2009-3560.patch13
-rw-r--r--main/expat/CVE-2009-3720.patch12
-rw-r--r--main/ez-ipupdate/APKBUILD49
-rw-r--r--main/ez-ipupdate/errno.patch56
-rw-r--r--main/ez-ipupdate/ez-ipupdate.confd34
-rw-r--r--main/ez-ipupdate/ez-ipupdate.initd52
-rw-r--r--main/ez-ipupdate/ez-ipupdate.post-install5
-rw-r--r--main/ez-ipupdate/ez-ipupdate.pre-install5
-rw-r--r--main/faac/APKBUILD39
-rw-r--r--main/faad2/APKBUILD34
-rw-r--r--main/fail2ban/APKBUILD48
-rw-r--r--main/fail2ban/fail2ban.confd8
-rw-r--r--main/fail2ban/fail2ban.logrotate9
-rw-r--r--main/fail2ban/gentoo-initd_create_run_dir.patch19
-rw-r--r--main/fakeroot/APKBUILD32
-rw-r--r--main/fakeroot/busybox-compat.patch23
-rw-r--r--main/fastjar/APKBUILD43
-rw-r--r--main/fcgi/10-fcgi-2.4.0-Makefile.patch24
-rw-r--r--main/fcgi/20-fcgi-2.4.0-clientdata-pointer.patch96
-rw-r--r--main/fcgi/30-fcgi-2.4.0-html-updates.patch65
-rw-r--r--main/fcgi/APKBUILD48
-rw-r--r--main/feh/APKBUILD27
-rw-r--r--main/ferm/APKBUILD23
-rw-r--r--main/fetchmail/APKBUILD46
-rwxr-xr-xmain/fetchmail/fetchmail.initd34
-rw-r--r--main/fetchmail/fetchmail.post-install3
-rw-r--r--main/fetchmail/fetchmail.pre-install4
-rw-r--r--main/ffmpeg/APKBUILD63
-rw-r--r--main/ffmpeg/configure-dlvsym.patch30
-rw-r--r--main/ffmpeg/pic.patch11
-rw-r--r--main/fftw/APKBUILD38
-rw-r--r--main/file/APKBUILD24
-rw-r--r--main/findutils/APKBUILD28
-rw-r--r--main/firefox/APKBUILD97
-rw-r--r--main/firefox/firefox-safe.desktop11
-rw-r--r--main/firefox/firefox.desktop81
-rw-r--r--main/firefox/mozconfig36
-rw-r--r--main/fixesproto/APKBUILD23
-rw-r--r--main/flac/APKBUILD37
-rw-r--r--main/flashrom/APKBUILD33
-rwxr-xr-xmain/flashrom/flashrom.post-install15
-rw-r--r--main/flex/APKBUILD26
-rw-r--r--main/flite/APKBUILD50
-rw-r--r--main/fluxbox/APKBUILD29
-rw-r--r--main/font-adobe-100dpi/APKBUILD23
-rw-r--r--main/font-adobe-75dpi/APKBUILD23
-rw-r--r--main/font-adobe-utopia-100dpi/APKBUILD23
-rw-r--r--main/font-adobe-utopia-75dpi/APKBUILD23
-rw-r--r--main/font-adobe-utopia-type1/APKBUILD31
-rw-r--r--main/font-alias/APKBUILD21
-rw-r--r--main/font-arabic-misc/APKBUILD23
-rw-r--r--main/font-bh-100dpi/APKBUILD23
-rw-r--r--main/font-bh-75dpi/APKBUILD23
-rw-r--r--main/font-bh-lucidatypewriter-100dpi/APKBUILD23
-rw-r--r--main/font-bh-lucidatypewriter-75dpi/APKBUILD23
-rw-r--r--main/font-bh-ttf/APKBUILD31
-rw-r--r--main/font-bh-type1/APKBUILD31
-rw-r--r--main/font-bitstream-100dpi/APKBUILD23
-rw-r--r--main/font-bitstream-75dpi/APKBUILD23
-rw-r--r--main/font-bitstream-speedo/APKBUILD27
-rw-r--r--main/font-bitstream-type1/APKBUILD31
-rw-r--r--main/font-cronyx-cyrillic/APKBUILD23
-rw-r--r--main/font-cursor-misc/APKBUILD23
-rw-r--r--main/font-daewoo-misc/APKBUILD23
-rw-r--r--main/font-dec-misc/APKBUILD23
-rw-r--r--main/font-ibm-type1/APKBUILD31
-rw-r--r--main/font-isas-misc/APKBUILD23
-rw-r--r--main/font-jis-misc/APKBUILD23
-rw-r--r--main/font-micro-misc/APKBUILD23
-rw-r--r--main/font-misc-cyrillic/APKBUILD23
-rw-r--r--main/font-misc-ethiopic/APKBUILD32
-rw-r--r--main/font-misc-meltho/APKBUILD32
-rw-r--r--main/font-misc-misc/APKBUILD33
-rw-r--r--main/font-mutt-misc/APKBUILD23
-rw-r--r--main/font-schumacher-misc/APKBUILD23
-rw-r--r--main/font-screen-cyrillic/APKBUILD23
-rw-r--r--main/font-sony-misc/APKBUILD23
-rw-r--r--main/font-sun-misc/APKBUILD23
-rw-r--r--main/font-util/APKBUILD26
-rw-r--r--main/font-winitzki-cyrillic/APKBUILD23
-rw-r--r--main/font-xfree86-type1/APKBUILD31
-rw-r--r--main/fontconfig/APKBUILD35
-rw-r--r--main/fontconfig/fontconfig.trigger4
-rw-r--r--main/fontsproto/APKBUILD23
-rw-r--r--main/fping/APKBUILD24
-rw-r--r--main/fprobe/APKBUILD52
-rw-r--r--main/fprobe/fprobe-1.1-pidfile-sanity.patch48
-rw-r--r--main/fprobe/fprobe-1.1-setgroups.patch19
-rw-r--r--main/fprobe/fprobe.confd70
-rw-r--r--main/fprobe/fprobe.initd40
-rw-r--r--main/freeglut/APKBUILD43
-rw-r--r--main/freeradius/0001-Fix-detection-of-TLS-for-uClibc.patch33
-rw-r--r--main/freeradius/APKBUILD154
-rw-r--r--main/freeradius/freeradius-2.1.6-nothreads.patch13
-rw-r--r--main/freeradius/freeradius-2.1.7-pkglibdir.patch63
-rw-r--r--main/freeradius/freeradius.confd5
-rw-r--r--main/freeradius/freeradius.initd70
-rw-r--r--main/freeradius/freeradius.pre-install6
-rw-r--r--main/freerdp/APKBUILD33
-rw-r--r--main/freeswitch-sounds-en-us-callie-32000/APKBUILD27
-rw-r--r--main/freeswitch-sounds-en-us-callie-8000/APKBUILD27
-rw-r--r--main/freeswitch-sounds-music-32000/APKBUILD25
-rw-r--r--main/freeswitch-sounds-music-8000/APKBUILD27
-rw-r--r--main/freeswitch-sounds-ru-RU-elena-32000/APKBUILD25
-rw-r--r--main/freeswitch-sounds-ru-RU-elena-8000/APKBUILD25
-rw-r--r--main/freeswitch/0001-mod_sofia-update-mod_sofia_globals.guess_ip-on-addre.patch27
-rw-r--r--main/freeswitch/0002-mod_lua-alpine-module-search-path.patch37
-rw-r--r--main/freeswitch/0003-mod_conference_no_hangup.patch27
-rw-r--r--main/freeswitch/APKBUILD143
-rw-r--r--main/freeswitch/freeswitch-mod_shout-textrels.patch11
-rw-r--r--main/freeswitch/freeswitch.confd25
-rwxr-xr-xmain/freeswitch/freeswitch.initd63
-rwxr-xr-xmain/freeswitch/freeswitch.post-install5
-rwxr-xr-xmain/freeswitch/freeswitch.pre-install5
-rw-r--r--main/freeswitch/freeswitch.pre-upgrade11
-rw-r--r--main/freeswitch/modules.conf122
-rw-r--r--main/freetds/APKBUILD33
-rw-r--r--main/freetype/20-enable-spr.patch11
-rw-r--r--main/freetype/30-enable-valid.patch20
-rw-r--r--main/freetype/40-memcpy-fix.patch14
-rw-r--r--main/freetype/APKBUILD49
-rw-r--r--main/fribidi/APKBUILD26
-rw-r--r--main/fts/APKBUILD56
-rw-r--r--main/fts/fts-header-correctness.patch20
-rw-r--r--main/fts/fts-uclibc.patch45
-rw-r--r--main/fts/stdint.patch10
-rw-r--r--main/fuse/APKBUILD66
-rw-r--r--main/fuse/fuse-iconv.patch11
-rw-r--r--main/fuse/fuse.initd35
-rw-r--r--main/galculator/APKBUILD24
-rw-r--r--main/gamin/APKBUILD42
-rw-r--r--main/garcon/APKBUILD33
-rw-r--r--main/gawk/APKBUILD36
-rw-r--r--main/gawk/gawk.post-deinstall3
-rw-r--r--main/gc/APKBUILD40
-rw-r--r--main/gc/uclibc-getcontext.patch11
-rw-r--r--main/gcc/09_all_gcc-4.5-Wtrampolines.patch64
-rw-r--r--main/gcc/15_all_gcc-libgomp-no-werror.patch16
-rw-r--r--main/gcc/50_all_pr45312-kernel-miscompile.patch181
-rw-r--r--main/gcc/51_all_gcc-3.4-libiberty-pic.patch10
-rw-r--r--main/gcc/APKBUILD317
-rw-r--r--main/gcc/PR32219.patch101
-rw-r--r--main/gcc/boehem-gc-uclibc.patch11
-rw-r--r--main/gcc/gcc-4.5-dynamic-linker.patch457
-rw-r--r--main/gcc/gcc-pure64.patch12
-rw-r--r--main/gcc/gcc-spec-env.patch41
-rw-r--r--main/gcc/gcc4-stack-protector-uclibc-no_tls.patch84
-rw-r--r--main/gcc/pt_gnu_eh_frame.patch12
-rw-r--r--main/gcc/uclibc-getipinfo.patch19
-rw-r--r--main/gconf/APKBUILD45
-rw-r--r--main/gd/APKBUILD46
-rw-r--r--main/gdb/80_all_gdb-6.5-dwarf-stack-overflow.patch54
-rw-r--r--main/gdb/APKBUILD51
-rw-r--r--main/gdbm/10-gdbm-1.8.3-fix-install-ownership.patch45
-rw-r--r--main/gdbm/20-gdbm-1.8.3-compat-linking.patch19
-rw-r--r--main/gdbm/30-gdbm-1.8.3-build.patch21
-rw-r--r--main/gdbm/APKBUILD46
-rw-r--r--main/gdk-pixbuf/APKBUILD56
-rw-r--r--main/gdk-pixbuf/gdk-pixbuf-libpng15.patch67
-rw-r--r--main/gdk-pixbuf/gdk-pixbuf.pre-deinstall3
-rw-r--r--main/gdk-pixbuf/gdk-pixbuf.trigger3
-rw-r--r--main/gdl/APKBUILD28
-rw-r--r--main/geany/APKBUILD93
-rw-r--r--main/gegl/APKBUILD39
-rw-r--r--main/gegl/gegl-uclibc.patch22
-rw-r--r--main/geh/APKBUILD45
-rw-r--r--main/geoip/APKBUILD40
-rw-r--r--main/gettext/APKBUILD55
-rw-r--r--main/gettext/gettext-0.15-expat-no-dlopen.patch36
-rw-r--r--main/gettext/gettext-0.17-gnuinfo.patch16
-rw-r--r--main/gettext/gettext-0.17-open-args.patch25
-rw-r--r--main/gettext/gettext-uclibc.patch11
-rw-r--r--main/ghostscript-fonts/APKBUILD23
-rw-r--r--main/ghostscript/APKBUILD75
-rw-r--r--main/ghostscript/ghostscript-png15.patch196
-rw-r--r--main/ghostscript/ghostscript-system-jasper.patch26
-rw-r--r--main/giblib/APKBUILD27
-rw-r--r--main/giflib/APKBUILD33
-rw-r--r--main/gimp/APKBUILD57
-rw-r--r--main/gimp/gimp-curl-fix.patch12
-rw-r--r--main/gimp/gimp-libpng1.5-compat.patch379
-rw-r--r--main/git-manpages/APKBUILD19
-rw-r--r--main/git/APKBUILD58
-rw-r--r--main/git/bb-tar.patch8
-rw-r--r--main/git/git-daemon.confd20
-rw-r--r--main/git/git-daemon.initd27
-rw-r--r--main/glade/APKBUILD35
-rw-r--r--main/glade3/APKBUILD39
-rw-r--r--main/glew/APKBUILD34
-rw-r--r--main/glib-networking/APKBUILD48
-rw-r--r--main/glib/APKBUILD48
-rw-r--r--main/glib/glib.trigger13
-rw-r--r--main/glibmm/APKBUILD39
-rw-r--r--main/glproto/APKBUILD23
-rw-r--r--main/gmp5/APKBUILD55
-rw-r--r--main/gmp5/gmp-4.1.4-noexecstack.patch20
-rw-r--r--main/gnats/APKBUILD33
-rw-r--r--main/gnats/gnats.pre-install4
-rw-r--r--main/gnokii/APKBUILD83
-rw-r--r--main/gnokii/gnokii.patch12
-rw-r--r--main/gnome-base/APKBUILD34
-rw-r--r--main/gnome-bluetooth/61-gnome-bluetooth-rfkill.rules11
-rw-r--r--main/gnome-bluetooth/APKBUILD56
-rw-r--r--main/gnome-bluetooth/nogeoclue.patch138
-rw-r--r--main/gnome-control-center/APKBUILD69
-rw-r--r--main/gnome-control-center/gnome-control-center.post-install7
-rw-r--r--main/gnome-control-center/gnome-control-center.post-upgrade7
-rw-r--r--main/gnome-control-center/gnome-control-center.pre-deinstall7
-rw-r--r--main/gnome-desktop/APKBUILD45
-rw-r--r--main/gnome-disk-utility/APKBUILD61
-rw-r--r--main/gnome-disk-utility/exp2.patch16
-rw-r--r--main/gnome-disk-utility/fix-freeze.patch32
-rw-r--r--main/gnome-doc-utils/APKBUILD37
-rw-r--r--main/gnome-doc-utils/xslt.patch17
-rw-r--r--main/gnome-icon-theme/APKBUILD41
-rw-r--r--main/gnome-keyring/APKBUILD60
-rw-r--r--main/gnome-menus/APKBUILD44
-rw-r--r--main/gnome-mime-data/APKBUILD41
-rw-r--r--main/gnome-panel/APKBUILD54
-rw-r--r--main/gnome-panel/gnome-panel.post-install21
-rw-r--r--main/gnome-panel/gnome-panel.post-upgrade21
-rw-r--r--main/gnome-panel/gnome-panel.pre-deinstall21
-rw-r--r--main/gnome-power-manager/APKBUILD66
-rw-r--r--main/gnome-power-manager/execinfo.patch26
-rw-r--r--main/gnome-power-manager/gnome-power-manager.post-install7
-rw-r--r--main/gnome-power-manager/gnome-power-manager.post-upgrade7
-rw-r--r--main/gnome-power-manager/gnome-power-manager.pre-deinstall7
-rw-r--r--main/gnome-screensaver/APKBUILD64
-rw-r--r--main/gnome-screensaver/gnome-screensaver.post-install7
-rw-r--r--main/gnome-screensaver/gnome-screensaver.post-upgrade7
-rw-r--r--main/gnome-screensaver/gnome-screensaver.pre-deinstall7
-rw-r--r--main/gnome-session/APKBUILD53
-rw-r--r--main/gnome-session/gnome-session.post-install7
-rw-r--r--main/gnome-session/gnome-session.post-upgrade7
-rw-r--r--main/gnome-session/gnome-session.pre-deinstall7
-rw-r--r--main/gnome-settings-daemon/APKBUILD64
-rw-r--r--main/gnome-settings-daemon/gnome-settings-daemon.post-install16
-rw-r--r--main/gnome-settings-daemon/gnome-settings-daemon.post-upgrade16
-rw-r--r--main/gnome-settings-daemon/gnome-settings-daemon.pre-deinstall16
-rw-r--r--main/gnome-system-monitor/APKBUILD66
-rw-r--r--main/gnome-system-monitor/gnome-system-monitor.post-install7
-rw-r--r--main/gnome-system-monitor/gnome-system-monitor.post-upgrade7
-rw-r--r--main/gnome-system-monitor/gnome-system-monitor.pre-deinstall7
-rw-r--r--main/gnome-terminal/APKBUILD42
-rw-r--r--main/gnome-terminal/gnome-terminal.post-install7
-rw-r--r--main/gnome-terminal/gnome-terminal.post-upgrade7
-rw-r--r--main/gnome-terminal/gnome-terminal.pre-deinstall7
-rw-r--r--main/gnome-themes/APKBUILD40
-rw-r--r--main/gnome-vfs/APKBUILD45
-rw-r--r--main/gnome-vfs/gnome-vfs.post-install7
-rw-r--r--main/gnome-vfs/gnome-vfs.post-upgrade7
-rw-r--r--main/gnome-vfs/gnome-vfs.pre-deinstall7
-rw-r--r--main/gnuchess/APKBUILD43
-rw-r--r--main/gnumeric/APKBUILD34
-rw-r--r--main/gnupg/APKBUILD28
-rw-r--r--main/gnutls/APKBUILD43
-rw-r--r--main/gobject-introspection/APKBUILD53
-rw-r--r--main/goffice/APKBUILD35
-rw-r--r--main/gparted/APKBUILD37
-rw-r--r--main/gperf/APKBUILD25
-rw-r--r--main/gpicview/APKBUILD23
-rw-r--r--main/gradm/APKBUILD57
-rw-r--r--main/gradm/base.policyd133
-rw-r--r--main/gradm/grsec-rbac.initd14
-rw-r--r--main/gradm/policy211
-rw-r--r--main/grep/APKBUILD32
-rw-r--r--main/groff/APKBUILD24
-rw-r--r--main/gross/APKBUILD53
-rw-r--r--main/gross/gross-1.0.1-default-conf.patch17
-rw-r--r--main/gross/gross.post-install2
-rw-r--r--main/gross/gross.post-upgrade17
-rw-r--r--main/gross/gross.pre-install3
-rw-r--r--main/gross/gross.pre-upgrade12
-rw-r--r--main/gross/grossd.confd6
-rw-r--r--main/gross/grossd.initd36
-rw-r--r--main/gsl/APKBUILD27
-rw-r--r--main/gsm/APKBUILD69
-rw-r--r--main/gsm/gsm-64bit.patch15
-rw-r--r--main/gsm/gsm-makefile.patch115
-rw-r--r--main/gsm/gsm-warnings.patch43
-rw-r--r--main/gst-ffmpeg/APKBUILD40
-rw-r--r--main/gst-ffmpeg/pic.patch11
-rw-r--r--main/gst-plugins-bad/APKBUILD38
-rw-r--r--main/gst-plugins-base/APKBUILD55
-rw-r--r--main/gst-plugins-good/APKBUILD59
-rw-r--r--main/gst-plugins-good/gst-plugins-good-gnome.post-install7
-rw-r--r--main/gst-plugins-good/gst-plugins-good-gnome.post-upgrade7
-rw-r--r--main/gst-plugins-good/gst-plugins-good-gnome.pre-deinstall7
-rw-r--r--main/gst-plugins-ugly/APKBUILD34
-rw-r--r--main/gstreamer/APKBUILD58
-rw-r--r--main/gtk+/APKBUILD24
-rw-r--r--main/gtk+2.0/APKBUILD77
-rw-r--r--main/gtk+2.0/gtk+2.0.post-deinstall5
-rw-r--r--main/gtk+2.0/gtk+2.0.post-install5
l---------main/gtk+2.0/gtk+2.0.post-upgrade1
-rw-r--r--main/gtk+2.0/gtk+2.0.trigger6
-rw-r--r--main/gtk+3.0/APKBUILD70
-rw-r--r--main/gtk+3.0/gtk+3.0.post-deinstall5
-rw-r--r--main/gtk+3.0/gtk+3.0.post-install5
l---------main/gtk+3.0/gtk+3.0.post-upgrade1
-rw-r--r--main/gtk+3.0/gtk+3.0.trigger6
-rw-r--r--main/gtk-doc/APKBUILD24
-rw-r--r--main/gtk-engines/APKBUILD42
-rw-r--r--main/gtk-vnc/APKBUILD37
-rw-r--r--main/gtk-xfce-engine/APKBUILD29
-rw-r--r--main/gtkglext/APKBUILD43
-rw-r--r--main/gtkglext/gtkglext-deprecated.patch76
-rw-r--r--main/gtkman/APKBUILD38
-rw-r--r--main/gtkmm/APKBUILD26
-rw-r--r--main/gtksourceview/APKBUILD29
-rw-r--r--main/gtkspell/APKBUILD27
-rw-r--r--main/gucharmap/APKBUILD40
-rw-r--r--main/guile/APKBUILD44
-rw-r--r--main/guile/guile-1.8.7-gcc45.patch15
-rw-r--r--main/gvfs/APKBUILD101
-rw-r--r--main/gvfs/gvfs.trigger6
-rw-r--r--main/gzip/APKBUILD38
-rw-r--r--main/gzip/gzip.post-deinstall3
-rw-r--r--main/haproxy/APKBUILD29
-rw-r--r--main/haproxy/haproxy.initd45
-rw-r--r--main/haserl/APKBUILD37
-rw-r--r--main/heimdal/001_all_heimdal-no_libedit.patch10
-rw-r--r--main/heimdal/002_all_heimdal-fPIC.patch12
-rw-r--r--main/heimdal/003_all_heimdal-rxapps.patch22
-rw-r--r--main/heimdal/005_all_heimdal-suid_fix.patch20
-rw-r--r--main/heimdal/014_all_heimdal-path.patch50
-rw-r--r--main/heimdal/022_all_heimdal-as-needed.patch22
-rw-r--r--main/heimdal/100-check-com_err-pthread.patch11
-rw-r--r--main/heimdal/APKBUILD175
-rw-r--r--main/heimdal/heimdal-1.4-make.patch88
-rwxr-xr-xmain/heimdal/heimdal-kadmind.init24
-rwxr-xr-xmain/heimdal/heimdal-kdc.init23
-rwxr-xr-xmain/heimdal/heimdal-kpasswdd.init24
-rw-r--r--main/hicolor-icon-theme/APKBUILD23
-rw-r--r--main/hostapd/APKBUILD111
-rw-r--r--main/hostapd/hostapd.confd5
-rw-r--r--main/hostapd/hostapd.initd46
-rw-r--r--main/htop/APKBUILD22
-rw-r--r--main/hunspell/APKBUILD28
-rw-r--r--main/hylafax/APKBUILD92
-rw-r--r--main/hylafax/gcc4.5.1.patch13
-rw-r--r--main/hylafax/hylafax.post-install5
-rw-r--r--main/hypermail/APKBUILD41
-rw-r--r--main/hypermail/mdir2mbox.lua96
-rw-r--r--main/iaxmodem/APKBUILD55
-rw-r--r--main/iaxmodem/iaxmodem.confd7
-rw-r--r--main/iaxmodem/iaxmodem.initd44
-rw-r--r--main/iaxmodem/nocxx.patch15
-rw-r--r--main/iceauth/APKBUILD25
-rw-r--r--main/icecast/APKBUILD49
-rw-r--r--main/icecast/conf-change-owner.patch16
-rw-r--r--main/icecast/icecast.confd1
-rw-r--r--main/icecast/icecast.initd19
-rw-r--r--main/icecast/icecast.pre-install5
-rw-r--r--main/icedtea-web/APKBUILD59
-rw-r--r--main/icon-naming-utils/APKBUILD26
-rw-r--r--main/icu/APKBUILD63
-rw-r--r--main/iftop/APKBUILD24
-rw-r--r--main/igmpproxy/APKBUILD35
-rw-r--r--main/imagemagick/APKBUILD67
-rw-r--r--main/imap/APKBUILD69
-rw-r--r--main/imap/c-client-2006k_GENTOO_amd64-so-fix.patch13
-rw-r--r--main/imap/c-client-2006k_KOLAB_Annotations.patch448
-rw-r--r--main/imap/c-client-2007e-ldflags.patch35
-rw-r--r--main/imlib2/APKBUILD41
-rw-r--r--main/imlib2/imlib2-png15.patch78
-rw-r--r--main/indent/APKBUILD38
-rw-r--r--main/inkscape/APKBUILD60
-rw-r--r--main/inkscape/inkscape-png15.patch33
-rw-r--r--main/inputproto/APKBUILD23
-rw-r--r--main/installkernel/APKBUILD18
-rw-r--r--main/intltool/APKBUILD23
-rw-r--r--main/iperf/APKBUILD31
-rw-r--r--main/iproute2-qos/APKBUILD26
-rw-r--r--main/iproute2-qos/qos.confd314
-rw-r--r--main/iproute2-qos/qos.eth0.sample151
-rw-r--r--main/iproute2-qos/qos.ifb0.sample151
-rw-r--r--main/iproute2-qos/qos.initd463
-rw-r--r--main/iproute2-qos/setup-qos67
-rw-r--r--main/iproute2/APKBUILD42
-rw-r--r--main/iproute2/iproute2.post-deinstall4
-rw-r--r--main/iproute2/iproute2.post-install6
-rw-r--r--main/ipsec-tools/20-grekey-support.patch786
-rw-r--r--main/ipsec-tools/50-reverse-connect.patch197
-rw-r--r--main/ipsec-tools/70-defer-isakmp-ident-handling.patch179
-rw-r--r--main/ipsec-tools/75-racoonctl-rcvbuf.patch33
-rw-r--r--main/ipsec-tools/APKBUILD65
-rw-r--r--main/ipsec-tools/racoon.confd20
-rw-r--r--main/ipsec-tools/racoon.initd60
-rw-r--r--main/iptables/APKBUILD81
-rw-r--r--main/iptables/ip6tables.confd11
-rw-r--r--main/iptables/iptables-1.4.2-include-in.patch12
-rw-r--r--main/iptables/iptables.confd11
-rwxr-xr-xmain/iptables/iptables.initd114
-rw-r--r--main/iptraf/APKBUILD44
-rw-r--r--main/iptraf/iptraf-3.0.0-interface.patch68
-rw-r--r--main/iptraf/iptraf-3.0.0-vlan.patch28
-rw-r--r--main/iputils/APKBUILD28
-rw-r--r--main/iputils/iputils-20070202-no-open-max.patch16
-rw-r--r--main/iputils/iputils.post-install3
-rw-r--r--main/ircii/APKBUILD32
-rw-r--r--main/ircservices/APKBUILD87
-rw-r--r--main/ircservices/ircservices.confd6
-rw-r--r--main/ircservices/ircservices.initd29
-rw-r--r--main/ircservices/ircservices.pre-install5
-rw-r--r--main/irssi/APKBUILD70
-rw-r--r--main/irssi/irssi-italics.patch112
-rw-r--r--main/iscsitarget-grsec/APKBUILD58
-rw-r--r--main/iscsitarget-grsec/iscsitarget-2.6.36.patch11
-rw-r--r--main/iscsitarget-grsec/iscsitarget-2.6.37.patch283
-rw-r--r--main/iscsitarget-grsec/iscsitarget-2.6.38.patch32
-rw-r--r--main/iscsitarget/APKBUILD46
-rw-r--r--main/iscsitarget/ietd.confd30
-rw-r--r--main/iscsitarget/ietd.initd107
-rw-r--r--main/iso-codes/APKBUILD23
-rw-r--r--main/iw/APKBUILD38
-rw-r--r--main/iw/iw-git-version.patch11
-rw-r--r--main/iwlwifi-1000-ucode/APKBUILD30
-rw-r--r--main/iwlwifi-3945-ucode/APKBUILD30
-rw-r--r--main/iwlwifi-4965-ucode/APKBUILD30
-rw-r--r--main/iwlwifi-5000-ucode/APKBUILD30
-rw-r--r--main/iwlwifi-5150-ucode/APKBUILD30
-rw-r--r--main/iwlwifi-6000-ucode/APKBUILD30
-rw-r--r--main/jasper/APKBUILD46
-rw-r--r--main/jasper/jpc_dec.c.patch18
-rw-r--r--main/java-common/APKBUILD24
-rw-r--r--main/java-common/java-common.trigger13
-rw-r--r--main/java-gcj-compat/APKBUILD65
-rw-r--r--main/jfsutils/APKBUILD34
-rw-r--r--main/jpeg/APKBUILD41
-rw-r--r--main/json-glib/APKBUILD27
-rw-r--r--main/jwhois/APKBUILD41
-rw-r--r--main/jwhois/jwhois-libiconv.patch10
-rw-r--r--main/kamailio/0001-utils-Install-the-sqlite-scripts.patch66
-rw-r--r--main/kamailio/0001-utils-add-sqlite-support-to-kamctl-kamdbctl.patch1223
-rw-r--r--main/kamailio/APKBUILD187
-rw-r--r--main/kamailio/kamailio-3.1-backslash.patch44
-rw-r--r--main/kamailio/kamailio.cfg107
-rw-r--r--main/kamailio/kamailio.initd34
-rw-r--r--main/kamailio/kamailio.pre-install6
l---------main/kamailio/kamailio.pre-upgrade1
-rw-r--r--main/kamailio/sqlite.patch712
-rw-r--r--main/kbproto/APKBUILD23
-rw-r--r--main/ksymoops/APKBUILD35
-rw-r--r--main/ksymoops/ksymoops-2.4.11-build.patch12
-rw-r--r--main/lame/APKBUILD62
-rw-r--r--main/lame/lame-3.98.2-ffmpeg-0.5.patch86
-rw-r--r--main/lcms/APKBUILD33
-rw-r--r--main/less/APKBUILD32
-rw-r--r--main/less/less.post-deinstall3
-rw-r--r--main/lftp/APKBUILD35
-rw-r--r--main/lha/APKBUILD27
-rw-r--r--main/libaio/APKBUILD28
-rw-r--r--main/libao/APKBUILD30
-rw-r--r--main/libarchive/APKBUILD34
-rw-r--r--main/libart-lgpl/APKBUILD28
-rw-r--r--main/libass/APKBUILD37
-rw-r--r--main/libassuan/APKBUILD26
-rw-r--r--main/libatasmart/APKBUILD42
-rw-r--r--main/libavc1394/APKBUILD45
-rw-r--r--main/libbluray/APKBUILD38
-rw-r--r--main/libbonobo/APKBUILD43
-rw-r--r--main/libc0.9.32/0001-getaddrinfo-allow-numeric-service-without-any-hints.patch37
-rw-r--r--main/libc0.9.32/0001-ldso-limited-support-for-ORIGIN-in-rpath.patch198
-rw-r--r--main/libc0.9.32/0001-libdl-rudimentary-locking-for-dlopen-dlsym-dlclose.patch152
-rw-r--r--main/libc0.9.32/0001-libm-x86_64-implement-fesetround.patch98
-rw-r--r--main/libc0.9.32/0001-malloc-standard-synchronize-on-fork.patch54
-rw-r--r--main/libc0.9.32/0001-time-fix-parsing-of-tzdata-files-where-off_t-is-64-b.patch32
-rw-r--r--main/libc0.9.32/0002-stdlib-fix-arc4random-return-type-to-u_int32_t.patch61
-rw-r--r--main/libc0.9.32/0003-ldso-support-RTLD_NOLOAD.patch234
-rw-r--r--main/libc0.9.32/APKBUILD150
-rw-r--r--main/libc0.9.32/compat-stack-guard.patch55
-rw-r--r--main/libc0.9.32/sha512-crypt.patch854
-rw-r--r--main/libc0.9.32/uclibc-epoll_pwait-hack.patch20
-rw-r--r--main/libc0.9.32/uclibc-librt-asneeded-fix.patch39
-rw-r--r--main/libc0.9.32/uclibc-resolv-cname-fix.diff19
-rw-r--r--main/libc0.9.32/uclibc-ubacktrace-asneeded-fix.patch22
-rw-r--r--main/libc0.9.32/uclibc-utils.trigger3
-rw-r--r--main/libc0.9.32/uclibcconfig.arm267
l---------main/libc0.9.32/uclibcconfig.i4861
-rw-r--r--main/libc0.9.32/uclibcconfig.powerpc251
-rw-r--r--main/libc0.9.32/uclibcconfig.x86266
-rw-r--r--main/libc0.9.32/uclibcconfig.x86_64248
-rw-r--r--main/libcanberra/APKBUILD39
-rw-r--r--main/libcap-ng/APKBUILD43
-rw-r--r--main/libcap/APKBUILD25
-rw-r--r--main/libcddb/APKBUILD41
-rw-r--r--main/libcdio/APKBUILD43
-rw-r--r--main/libconfig/APKBUILD29
-rw-r--r--main/libcroco/APKBUILD28
-rw-r--r--main/libcue/APKBUILD33
-rw-r--r--main/libdaemon/APKBUILD30
-rw-r--r--main/libdc1394/APKBUILD56
-rw-r--r--main/libdc1394/conditional-dc1394_vloopback.patch36
-rw-r--r--main/libdnet/APKBUILD35
-rw-r--r--main/libdrm/APKBUILD28
-rw-r--r--main/libdv/APKBUILD61
-rw-r--r--main/libdv/libdv-0.104-no-exec-stack.patch137
-rw-r--r--main/libdv/libdv-1.0.0-dso-linking.patch12
-rw-r--r--main/libdv/libdv-1.0.0-gtk2.patch11
-rw-r--r--main/libdv/libdv-1.0.0-pic.patch1634
-rw-r--r--main/libdvbpsi/APKBUILD27
-rw-r--r--main/libelf/APKBUILD27
-rw-r--r--main/libetpan/APKBUILD31
-rw-r--r--main/libev/APKBUILD42
-rw-r--r--main/libevent/APKBUILD26
-rw-r--r--main/libexif/APKBUILD25
-rw-r--r--main/libffi/APKBUILD29
-rw-r--r--main/libfontenc/APKBUILD29
-rw-r--r--main/libgcrypt/APKBUILD33
-rw-r--r--main/libgcrypt/nocxx.patch15
-rw-r--r--main/libgee/APKBUILD27
-rw-r--r--main/libgexiv2/APKBUILD39
-rw-r--r--main/libglade/APKBUILD42
-rw-r--r--main/libglade/libglade-2.0.1-nowarning.patch39
-rw-r--r--main/libglade/libglade.post-deinstall6
-rw-r--r--main/libglade/libglade.post-install13
l---------main/libglade/libglade.post-upgrade1
l---------main/libglade/libglade.pre-upgrade1
-rw-r--r--main/libgnome-keyring/APKBUILD60
-rw-r--r--main/libgnome/APKBUILD44
-rw-r--r--main/libgnome/libgnome.post-install26
-rw-r--r--main/libgnome/libgnome.post-upgrade26
-rw-r--r--main/libgnome/libgnome.pre-deinstall26
-rw-r--r--main/libgnomekbd/APKBUILD53
-rw-r--r--main/libgnomekbd/libgnomekbd.post-install7
-rw-r--r--main/libgnomekbd/libgnomekbd.post-upgrade7
-rw-r--r--main/libgnomekbd/libgnomekbd.pre-deinstall7
-rw-r--r--main/libgpg-error/APKBUILD33
-rw-r--r--main/libgphoto2/APKBUILD48
-rw-r--r--main/libgphoto2/libgphoto2.pre-install6
l---------main/libgphoto2/libgphoto2.pre-upgrade1
-rw-r--r--main/libgsf/APKBUILD36
-rw-r--r--main/libgssglue/APKBUILD29
-rw-r--r--main/libgssglue/gssapi_mech.conf22
-rw-r--r--main/libgtop/APKBUILD42
-rw-r--r--main/libguess/APKBUILD39
-rw-r--r--main/libgweather/APKBUILD43
-rw-r--r--main/libgweather/libgweather.post-install7
-rw-r--r--main/libgweather/libgweather.post-upgrade7
-rw-r--r--main/libgweather/libgweather.pre-deinstall7
-rw-r--r--main/libical/APKBUILD35
-rw-r--r--main/libice/APKBUILD27
-rw-r--r--main/libiconv/APKBUILD35
-rw-r--r--main/libid3tag/APKBUILD33
-rw-r--r--main/libidl/APKBUILD38
-rw-r--r--main/libidn/APKBUILD34
-rw-r--r--main/libiec61883/APKBUILD51
-rw-r--r--main/libksba/APKBUILD25
-rw-r--r--main/liblockfile/APKBUILD38
-rw-r--r--main/libmad/APKBUILD46
-rw-r--r--main/libmad/libmad-0.15.1b-cflags-O2.patch12
-rw-r--r--main/libmad/libmad-0.15.1b-cflags.patch146
-rw-r--r--main/libmad/mad.pc11
-rw-r--r--main/libmcrypt/APKBUILD30
-rw-r--r--main/libmcs/APKBUILD39
-rw-r--r--main/libmicrohttpd/APKBUILD46
-rw-r--r--main/libmikmod/APKBUILD40
-rw-r--r--main/libmms/APKBUILD42
-rw-r--r--main/libmms/libmms-0.5-this-keyword.patch18
-rw-r--r--main/libmng/APKBUILD36
-rw-r--r--main/libmodplug/APKBUILD39
-rw-r--r--main/libmowgli/APKBUILD40
-rw-r--r--main/libmpc/APKBUILD42
-rw-r--r--main/libmpdclient/APKBUILD25
-rw-r--r--main/libmpeg2/APKBUILD36
-rw-r--r--main/libnet/APKBUILD28
-rw-r--r--main/libnetcf/APKBUILD40
-rw-r--r--main/libnetfilter_conntrack/APKBUILD31
-rw-r--r--main/libnfnetlink/APKBUILD30
-rw-r--r--main/libnih/APKBUILD42
-rw-r--r--main/libnl/APKBUILD45
-rw-r--r--main/libnl/libnl-1.1-flags.patch11
-rw-r--r--main/libnl/libnl-1.1-glibc-2.8-ULONG_MAX.patch13
-rw-r--r--main/libnl/libnl-1.1-minor-leaks.patch40
-rw-r--r--main/libnl/libnl-1.1-vlan-header.patch80
-rw-r--r--main/libnotify/APKBUILD28
-rw-r--r--main/libogg/APKBUILD30
-rw-r--r--main/libogg/nocxx.patch15
-rw-r--r--main/liboil/APKBUILD28
-rw-r--r--main/libotr/APKBUILD55
-rw-r--r--main/libowfat/APKBUILD34
-rw-r--r--main/libpaper/APKBUILD29
-rw-r--r--main/libpcap/APKBUILD40
-rw-r--r--main/libpciaccess/APKBUILD26
-rw-r--r--main/libpng/APKBUILD32
-rw-r--r--main/libpri/APKBUILD33
-rw-r--r--main/libpri/libpri-1.4-r1357.patch39961
-rw-r--r--main/libpri/libpri-cflags.patch21
-rw-r--r--main/libproxy/APKBUILD62
-rw-r--r--main/libpthread-stubs/APKBUILD24
-rw-r--r--main/libraw/APKBUILD38
-rw-r--r--main/libraw1394/APKBUILD39
-rw-r--r--main/libresample/APKBUILD44
-rw-r--r--main/librsvg/APKBUILD35
-rw-r--r--main/librsync/APKBUILD31
-rw-r--r--main/libsamplerate/APKBUILD24
-rw-r--r--main/libsexy/APKBUILD28
-rw-r--r--main/libshout/APKBUILD40
-rw-r--r--main/libsigc++/APKBUILD26
-rw-r--r--main/libsm/APKBUILD28
-rw-r--r--main/libsndfile/APKBUILD28
-rw-r--r--main/libsoup/APKBUILD35
-rw-r--r--main/libspf2/0001-provide-dn_skipname.patch120
-rw-r--r--main/libspf2/APKBUILD43
-rw-r--r--main/libspf2/libspf2-localpolicy-fix.patch20
-rw-r--r--main/libspf2/libspf2-res_ninit-uclibc.patch64
-rw-r--r--main/libssh/APKBUILD44
-rw-r--r--main/libtasn1/APKBUILD27
-rw-r--r--main/libtheora/APKBUILD61
-rw-r--r--main/libtheora/enc.patch11
-rw-r--r--main/libtheora/libtheora-flags.patch14
-rw-r--r--main/libtirpc/APKBUILD49
-rw-r--r--main/libtirpc/libtirpc-no-des.patch38
-rw-r--r--main/libtirpc/nis.h542
-rw-r--r--main/libtool/APKBUILD31
-rw-r--r--main/libunique/APKBUILD30
-rw-r--r--main/libusb-compat/APKBUILD26
-rw-r--r--main/libusb/APKBUILD25
-rw-r--r--main/libvdpau/APKBUILD41
-rw-r--r--main/libvirt/APKBUILD48
-rw-r--r--main/libvirt/fix_undefined_symbol_error_when_macvtap_support_is_disabled.patch117
-rw-r--r--main/libvirt/libvirt.confd27
-rw-r--r--main/libvirt/libvirt.initd87
-rw-r--r--main/libvorbis/APKBUILD30
-rw-r--r--main/libvpx/APKBUILD39
-rw-r--r--main/libvpx/git100617.patch27956
-rw-r--r--main/libwebp/APKBUILD34
-rw-r--r--main/libwnck/APKBUILD33
-rw-r--r--main/libx11/APKBUILD31
-rw-r--r--main/libxau/APKBUILD29
-rw-r--r--main/libxcb/APKBUILD29
-rw-r--r--main/libxcomposite/APKBUILD30
-rw-r--r--main/libxcursor/APKBUILD28
-rw-r--r--main/libxdamage/APKBUILD26
-rw-r--r--main/libxdmcp/APKBUILD26
-rw-r--r--main/libxext/APKBUILD26
-rw-r--r--main/libxfce4ui/APKBUILD32
-rw-r--r--main/libxfce4util/APKBUILD30
-rw-r--r--main/libxfcegui4/APKBUILD32
-rw-r--r--main/libxfixes/APKBUILD27
-rw-r--r--main/libxfont/APKBUILD29
-rw-r--r--main/libxft/APKBUILD28
-rw-r--r--main/libxi/APKBUILD36
-rw-r--r--main/libxinerama/APKBUILD26
-rw-r--r--main/libxkbfile/APKBUILD29
-rw-r--r--main/libxkbui/APKBUILD26
-rw-r--r--main/libxklavier/APKBUILD31
-rw-r--r--main/libxml2/APKBUILD58
-rw-r--r--main/libxml2/largefile64.patch12
-rw-r--r--main/libxmu/APKBUILD31
-rw-r--r--main/libxp/APKBUILD45
-rw-r--r--main/libxpm/APKBUILD29
-rw-r--r--main/libxrandr/APKBUILD30
-rw-r--r--main/libxrender/APKBUILD26
-rw-r--r--main/libxres/APKBUILD30
-rw-r--r--main/libxslt/APKBUILD33
-rw-r--r--main/libxt/APKBUILD29
-rw-r--r--main/libxtst/APKBUILD30
-rw-r--r--main/libxv/APKBUILD28
-rw-r--r--main/libxvmc/APKBUILD27
-rw-r--r--main/libxxf86dga/APKBUILD26
-rw-r--r--main/libxxf86misc/APKBUILD27
-rw-r--r--main/libxxf86vm/APKBUILD29
-rw-r--r--main/lighttpd/APKBUILD118
-rw-r--r--main/lighttpd/lighttpd.conf323
-rw-r--r--main/lighttpd/lighttpd.confd12
-rw-r--r--main/lighttpd/lighttpd.initd74
-rw-r--r--main/lighttpd/lighttpd.logrotate17
-rw-r--r--main/lighttpd/lighttpd.post-install4
-rw-r--r--main/lighttpd/lighttpd.pre-install4
-rw-r--r--main/lighttpd/mime-types.conf76
-rw-r--r--main/lighttpd/mod_cgi.conf33
-rw-r--r--main/lighttpd/mod_fastcgi.conf17
-rw-r--r--main/lighttpd/mod_fastcgi_fpm.conf16
-rw-r--r--main/lighttpd/spawn-fcgi.confd35
-rw-r--r--main/lighttpd/spawn-fcgi.initd53
-rw-r--r--main/links/APKBUILD29
-rw-r--r--main/linux-firmware/APKBUILD31
-rw-r--r--main/linux-grsec/0004-arp-flush-arp-cache-on-device-change.patch29
-rw-r--r--main/linux-grsec/APKBUILD145
-rw-r--r--main/linux-grsec/grsecurity-2.2.2-2.6.38.7-201105222331.patch71257
-rw-r--r--main/linux-grsec/kernelconfig.x865157
-rw-r--r--main/linux-grsec/kernelconfig.x86_645111
-rw-r--r--main/linux-grsec/net-gre-provide-multicast-mappings-for-ipv4-and-ipv6.patch98
-rw-r--r--main/linux-headers/APKBUILD46
-rw-r--r--main/linux-scst/0004-arp-flush-arp-cache-on-device-change.patch29
-rw-r--r--main/linux-scst/APKBUILD148
-rw-r--r--main/linux-scst/kernelconfig.x86_644729
-rw-r--r--main/linux-scst/scst-2.0.0.1-2.6.36.patch76096
-rw-r--r--main/linux-scst/setlocalversion.patch11
-rw-r--r--main/linux-scst/unionfs-2.5.7_for_2.6.36.diff11253
-rw-r--r--main/linux-vserver/APKBUILD137
-rw-r--r--main/linux-vserver/kernelconfig.x865047
-rw-r--r--main/linux-vserver/kernelconfig.x86_645004
-rw-r--r--main/live-media/APKBUILD47
-rw-r--r--main/lm_sensors/APKBUILD74
-rw-r--r--main/lm_sensors/fancontrol.initd33
-rw-r--r--main/lm_sensors/lm_sensors-3.1.0-sensors-detect-alpine.patch39
-rw-r--r--main/lm_sensors/lm_sensors.initd105
-rw-r--r--main/lm_sensors/sensord.confd3
-rw-r--r--main/lm_sensors/sensord.initd33
-rw-r--r--main/lm_sensors/sensors.install12
-rw-r--r--main/lockfile-progs/APKBUILD32
-rw-r--r--main/logcheck/APKBUILD30
-rw-r--r--main/logcheck/logcheck.cron.d9
-rw-r--r--main/logcheck/logcheck.post-install3
-rw-r--r--main/logcheck/logcheck.pre-install5
-rw-r--r--main/logrotate/APKBUILD37
-rw-r--r--main/logrotate/logrotate-3.7.9-atomic-create.patch70
-rw-r--r--main/logrotate/logrotate-3.7.9-shred.patch151
-rw-r--r--main/logrotate/logrotate-3.7.9-statefile.patch96
-rw-r--r--main/logrotate/logrotate.conf20
-rw-r--r--main/lsof/APKBUILD38
-rw-r--r--main/lsscsi/APKBUILD36
-rw-r--r--main/lsyncd/APKBUILD52
-rw-r--r--main/lsyncd/lsyncd.initd32
-rw-r--r--main/ltrace/APKBUILD26
-rw-r--r--main/lua-alt-getopt/APKBUILD29
-rw-r--r--main/lua-bitlib/APKBUILD29
-rw-r--r--main/lua-discount/APKBUILD23
-rw-r--r--main/lua-dns/APKBUILD31
-rw-r--r--main/lua-expat/APKBUILD31
-rw-r--r--main/lua-expat/newconfig26
-rw-r--r--main/lua-filesystem/APKBUILD31
-rw-r--r--main/lua-iconv/0001-lua-iconv-make-close-available-from-lua.patch25
-rw-r--r--main/lua-iconv/APKBUILD37
-rw-r--r--main/lua-imlib2/APKBUILD33
-rw-r--r--main/lua-json4/APKBUILD23
-rw-r--r--main/lua-lgob/0001-poppler-reflect-the-poppler_page_get_text-API-change.patch42
-rw-r--r--main/lua-lgob/APKBUILD46
-rw-r--r--main/lua-md5/APKBUILD25
-rw-r--r--main/lua-openrc/APKBUILD33
-rw-r--r--main/lua-pc/APKBUILD25
-rw-r--r--main/lua-penlight/APKBUILD30
-rw-r--r--main/lua-posix/APKBUILD26
-rw-r--r--main/lua-posixtz/APKBUILD38
-rw-r--r--main/lua-pty/APKBUILD33
-rw-r--r--main/lua-rex/APKBUILD48
-rw-r--r--main/lua-sec/APKBUILD40
-rw-r--r--main/lua-socket/APKBUILD28
-rw-r--r--main/lua-sql-mysql/APKBUILD33
-rw-r--r--main/lua-sql-postgres/APKBUILD27
-rw-r--r--main/lua-sql-sqlite3/APKBUILD26
-rw-r--r--main/lua-stdlib/APKBUILD29
-rw-r--r--main/lua-uuid/APKBUILD34
-rw-r--r--main/lua-xctrl/APKBUILD40
-rw-r--r--main/lua-xml/APKBUILD35
-rw-r--r--main/lua-zlib/APKBUILD36
-rw-r--r--main/lua/APKBUILD61
-rw-r--r--main/lua/lua-5.1-make.patch64
-rw-r--r--main/lua/lua-5.1-module_paths.patch30
-rw-r--r--main/lua/lua-5.1-readline.patch10
-rw-r--r--main/lvm2/APKBUILD63
-rw-r--r--main/lvm2/lvm.confd5
-rw-r--r--main/lvm2/lvm.initd38
-rw-r--r--main/lxdm/APKBUILD55
-rw-r--r--main/lxdm/lxdm-execinfo.patch47
-rw-r--r--main/lxdm/lxdm-nopam.patch18
-rwxr-xr-xmain/lxdm/lxdm.initd12
-rw-r--r--main/lynx/APKBUILD44
-rw-r--r--main/lzo/APKBUILD33
-rw-r--r--main/m4/APKBUILD30
-rw-r--r--main/make/APKBUILD28
-rw-r--r--main/makedepend/APKBUILD40
-rw-r--r--main/makekit/APKBUILD45
-rw-r--r--main/man-pages/APKBUILD35
-rw-r--r--main/man/APKBUILD44
-rw-r--r--main/man/man-troff.patch16
-rw-r--r--main/man/test.out289
-rwxr-xr-xmain/man/whatis.periodic.daily9
-rw-r--r--main/mc/APKBUILD43
-rw-r--r--main/mdadm/APKBUILD44
-rw-r--r--main/mdadm/mdadm-raid.initd48
-rw-r--r--main/mdadm/mdadm.confd5
-rw-r--r--main/mdadm/mdadm.initd28
-rw-r--r--main/mdadm/uclibc-bswap.patch18
-rw-r--r--main/memcached/0001-fix-type-punning-issues.patch73
-rw-r--r--main/memcached/APKBUILD50
-rw-r--r--main/memcached/memcached.confd35
-rw-r--r--main/memcached/memcached.initd80
-rw-r--r--main/memcached/memcached.pre-install5
-rw-r--r--main/mercurial/APKBUILD33
-rw-r--r--main/mesa-demos/APKBUILD42
-rw-r--r--main/mesa-demos/sincos.patch32
-rw-r--r--main/mesa/APKBUILD130
-rw-r--r--main/mesa/Mesa-7.10.1-nouveau-compile.patch139
-rw-r--r--main/mesa/fix-glx1.3-crash-xorg19.patch73
-rw-r--r--main/mesa/mesa-7.10-uclibc-gallium.patch20
-rw-r--r--main/mesa/mesa-7.10-uclibc-glsl.patch11
-rw-r--r--main/mesa/mesa-7.10-uclibc.patch13
-rw-r--r--main/metacity/APKBUILD54
-rw-r--r--main/metacity/metacity.post-install7
-rw-r--r--main/metacity/metacity.post-upgrade7
-rw-r--r--main/metacity/metacity.pre-deinstall7
-rw-r--r--main/mg/APKBUILD36
-rw-r--r--main/micro-tetris/APKBUILD31
-rw-r--r--main/midori/APKBUILD51
-rw-r--r--main/midori/midori.post-deinstall5
-rw-r--r--main/midori/midori.post-install4
l---------main/midori/midori.post-upgrade1
-rw-r--r--main/mini_httpd/APKBUILD48
-rw-r--r--main/mini_httpd/mini_httpd.conf.sample52
-rw-r--r--main/mini_httpd/mini_httpd.initd26
-rw-r--r--main/mini_httpd/mini_httpd.logrotate16
-rw-r--r--main/minicom/APKBUILD32
-rw-r--r--main/mkfontdir/APKBUILD26
-rw-r--r--main/mkfontdir/mkfontdir.trigger6
-rw-r--r--main/mkfontscale/APKBUILD26
-rw-r--r--main/mkfontscale/mkfontscale.trigger6
-rw-r--r--main/mkinitfs/0001-init-fix-progressbar-when-not-quiet.patch27
-rw-r--r--main/mkinitfs/APKBUILD48
-rw-r--r--main/mkinitfs/eglibc.patch17
-rw-r--r--main/mkinitfs/mkinitfs.trigger50
-rw-r--r--main/mlmmj/APKBUILD27
-rw-r--r--main/module-init-tools/APKBUILD26
-rw-r--r--main/monkeysphere/APKBUILD36
-rw-r--r--main/mousepad/APKBUILD29
-rw-r--r--main/mpc/APKBUILD24
-rw-r--r--main/mpd/APKBUILD55
-rw-r--r--main/mpd/mpd.confd7
-rw-r--r--main/mpd/mpd.initd44
-rw-r--r--main/mpd/mpd.pre-install4
-rw-r--r--main/mpfr3/APKBUILD34
-rw-r--r--main/mpg123/APKBUILD37
-rw-r--r--main/mplayer/APKBUILD70
-rw-r--r--main/mplayer/liba52_gcc_bug.patch10
-rw-r--r--main/mplayer/mplayer/configure.orig0
-rw-r--r--main/mplayer/mplayer/configure.rej10
-rw-r--r--main/mrtg/APKBUILD35
-rw-r--r--main/mrtg/mrtg.confd17
-rw-r--r--main/mrtg/mrtg.initd53
-rw-r--r--main/mrxvt/APKBUILD54
-rw-r--r--main/mrxvt/mrxvt-0.5.4-002-fix-segfault-when-wd-empty.patch12
-rw-r--r--main/mrxvt/mrxvt.desktop10
-rw-r--r--main/msmtp/APKBUILD43
-rw-r--r--main/mt-st/APKBUILD41
-rw-r--r--main/mt-st/mt-st.post-deinstall3
-rw-r--r--main/mtools/APKBUILD29
-rw-r--r--main/mtx/APKBUILD24
-rw-r--r--main/multipath-tools/APKBUILD47
-rw-r--r--main/multipath-tools/multipath-tools-0.4.8-kparted-ext-partitions.patch28
-rw-r--r--main/multipath-tools/multipath-tools-0.4.9-buffer-overflows.patch22
-rw-r--r--main/multipath-tools/multipath-tools-0.4.9-build.patch138
-rw-r--r--main/multipath-tools/multipath-tools.conf113
-rw-r--r--main/multipath-tools/multipath-tools.initd20
-rw-r--r--main/mutt/APKBUILD45
-rw-r--r--main/mysql/0001-prefer-dynamic-library.patch72
-rw-r--r--main/mysql/APKBUILD191
-rw-r--r--main/mysql/mysql.initd58
-rw-r--r--main/nagios-plugins/APKBUILD55
-rw-r--r--main/nagios/APKBUILD65
-rw-r--r--main/nagios/lighttpd-nagios.conf29
-rw-r--r--main/nagios/nagios.confd9
-rw-r--r--main/nagios/nagios.initd39
-rw-r--r--main/nagios/nagios.pre-install5
-rw-r--r--main/nagiosql/APKBUILD33
-rw-r--r--main/nano/APKBUILD33
-rw-r--r--main/nasm/APKBUILD27
-rw-r--r--main/nautilus/APKBUILD62
-rw-r--r--main/nautilus/nautilus.post-install7
-rw-r--r--main/nautilus/nautilus.post-upgrade7
-rw-r--r--main/nautilus/nautilus.pre-deinstall7
-rw-r--r--main/ncftp/APKBUILD48
-rw-r--r--main/ncftp/ncftp.post-install7
-rw-r--r--main/ncurses/APKBUILD87
-rw-r--r--main/neon/APKBUILD34
-rw-r--r--main/net-snmp/APKBUILD75
-rw-r--r--main/net-snmp/snmpd.confd14
-rw-r--r--main/net-snmp/snmpd.initd31
-rw-r--r--main/net-snmp/snmptrapd.confd12
-rw-r--r--main/net-snmp/snmptrapd.initd23
-rw-r--r--main/netcat-openbsd/APKBUILD49
-rw-r--r--main/netcat-openbsd/netcat-openbsd.post-deinstall2
-rw-r--r--main/netcat-openbsd/netcat-openbsd_1.89-4.diff2793
-rw-r--r--main/newt/APKBUILD49
-rw-r--r--main/nfs-utils/APKBUILD92
-rw-r--r--main/nfs-utils/nfs-utils-mtab-sym.patch38
-rw-r--r--main/nfs-utils/nfs-utils-no-exec.patch13
-rw-r--r--main/nfs-utils/nfs.confd30
-rw-r--r--main/nfs-utils/nfs.exports7
-rw-r--r--main/nfs-utils/nfs.initd154
-rw-r--r--main/nfs-utils/nfsmount.initd42
-rw-r--r--main/nfs-utils/rpc.gssd.initd24
-rw-r--r--main/nfs-utils/rpc.idmapd.initd26
-rw-r--r--main/nfs-utils/rpc.pipefs.initd24
-rw-r--r--main/nfs-utils/rpc.statd.initd33
-rw-r--r--main/nfs-utils/rpc.svcgssd.initd24
-rw-r--r--main/nginx/APKBUILD61
-rw-r--r--main/nginx/nginx.initd72
-rw-r--r--main/nginx/nginx.logrotate12
-rw-r--r--main/ngircd/APKBUILD39
-rw-r--r--main/ngircd/ngircd.initd22
-rw-r--r--main/ngircd/ngircd.pre-install4
-rw-r--r--main/nload/APKBUILD32
-rw-r--r--main/nmap/APKBUILD38
-rw-r--r--main/nmap/nmap-4.53-uclibc++-output.cc.patch11
-rw-r--r--main/nrpe/APKBUILD48
-rw-r--r--main/nrpe/nrpe.confd2
-rw-r--r--main/nrpe/nrpe.initd37
-rw-r--r--main/nrpe/nrpe.pre-install5
-rw-r--r--main/nsd/0010-stop-unlink-pid-error.patch26
-rw-r--r--main/nsd/APKBUILD76
-rw-r--r--main/nsd/nsd.confd15
-rw-r--r--main/nsd/nsd.initd420
-rw-r--r--main/nsd/nsd.post-deinstall4
-rw-r--r--main/nsd/nsd.pre-install4
-rw-r--r--main/nsd/nsdc30
-rw-r--r--main/nspr/APKBUILD74
-rw-r--r--main/nspr/nspr-4.7.0-prtime.patch26
-rw-r--r--main/nspr/nspr-4.8-config.patch47
-rw-r--r--main/nspr/nspr-4.8-pkgconfig-gentoo-3.patch115
-rw-r--r--main/nspr/nspr-4.8-sonames.patch256
-rw-r--r--main/nspr/nspr-bb-shell.patch13
-rw-r--r--main/nss/APKBUILD145
-rw-r--r--main/nss/add_spi+cacert_ca_certs.patch561
-rw-r--r--main/nss/nss-config.in145
-rw-r--r--main/nss/nss-no-rpath.patch14
-rw-r--r--main/nss/nss.pc.in11
-rw-r--r--main/nss/ssl-renegotiate-transitional.patch21
-rw-r--r--main/ntfs-3g/APKBUILD31
-rw-r--r--main/ntfs-3g/nocxx.patch15
-rw-r--r--main/ntop/APKBUILD55
-rw-r--r--main/ntop/ntop-update-geoip-db21
-rw-r--r--main/ntop/ntop.confd9
-rw-r--r--main/ntop/ntop.initd30
-rwxr-xr-xmain/ntop/ntop.post-install3
-rw-r--r--main/obex-data-server/APKBUILD29
-rw-r--r--main/obexd/APKBUILD44
-rw-r--r--main/oidentd/APKBUILD36
-rw-r--r--main/oidentd/oidentd.conf22
-rw-r--r--main/oidentd/oidentd.confd4
-rw-r--r--main/oidentd/oidentd.initd43
-rw-r--r--main/open-iscsi-grsec/APKBUILD54
-rw-r--r--main/open-iscsi-grsec/Makefile.kernel.patch11
-rw-r--r--main/open-iscsi/APKBUILD44
-rw-r--r--main/open-iscsi/iscsid.confd13
-rw-r--r--main/open-iscsi/iscsid.initd124
-rw-r--r--main/open-vm-tools-grsec/APKBUILD64
-rw-r--r--main/open-vm-tools-grsec/vmware-modules.initd25
-rw-r--r--main/open-vm-tools-vserver/APKBUILD63
-rw-r--r--main/open-vm-tools-vserver/vmware-modules.initd25
-rw-r--r--main/open-vm-tools/APKBUILD91
-rw-r--r--main/open-vm-tools/codeset-uclibc.patch20
-rw-r--r--main/open-vm-tools/ecvt.patch205
-rw-r--r--main/open-vm-tools/getloadavg-uclibc.patch19
-rw-r--r--main/open-vm-tools/iconv-uclibc.patch13
-rw-r--r--main/open-vm-tools/libm.patch18
-rw-r--r--main/open-vm-tools/open-vm-tools.initd76
-rw-r--r--main/open-vm-tools/open-vm-tools.pre-install4
-rw-r--r--main/open-vm-tools/procmgrposix.patch11
-rw-r--r--main/openal-soft/APKBUILD45
-rw-r--r--main/openal-soft/openal-fegetround.patch20
-rw-r--r--main/openbox/APKBUILD78
-rw-r--r--main/openjdk6/APKBUILD178
-rw-r--r--main/openjdk6/icedtea-hotspot-uclibc-fixes.patch90
-rw-r--r--main/openjdk6/icedtea-jdk-execinfo.patch40
-rw-r--r--main/openjdk6/icedtea-jdk-iconv-uclibc.patch39
-rw-r--r--main/openjdk6/icedtea-jdk-no-lib-nsl.patch84
-rw-r--r--main/openldap/APKBUILD118
-rw-r--r--main/openldap/openldap-2.4-ppolicy.patch13
-rw-r--r--main/openldap/openldap-2.4.11-libldap_r.patch11
-rw-r--r--main/openldap/openldap-back-sql-fix-64bit.patch82
-rw-r--r--main/openldap/openldap.post-install4
-rw-r--r--main/openldap/openldap.pre-install7
-rw-r--r--main/openldap/slapd.confd9
-rw-r--r--main/openldap/slapd.initd21
-rw-r--r--main/openldap/slurpd.initd23
-rw-r--r--main/opennhrp/0001-netlink-ignore-kernel-routes-for-GRE-interfaces.patch54
-rw-r--r--main/opennhrp/APKBUILD40
-rw-r--r--main/opennhrp/opennhrp-0.9.3-peer-up-bgp.patch11
-rw-r--r--main/opennhrp/opennhrp.confd2
-rwxr-xr-xmain/opennhrp/opennhrp.initd33
-rw-r--r--main/openntpd/APKBUILD47
-rw-r--r--main/openntpd/openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff43
-rw-r--r--main/openntpd/openntpd.confd7
-rw-r--r--main/openntpd/openntpd.initd41
-rw-r--r--main/openntpd/openntpd.pre-install7
-rw-r--r--main/openobex/APKBUILD37
-rw-r--r--main/openrc/0001-Force-root-be-rw-before-localmount.patch26
-rw-r--r--main/openrc/0001-fsck-add-C0-and-T-options-unless-fsck-is-busybox.patch38
-rw-r--r--main/openrc/APKBUILD78
-rw-r--r--main/openrc/command-line-size-fix.patch100
-rw-r--r--main/openrc/dont-provide-ourself.patch14
-rw-r--r--main/openrc/hostname.initd18
-rw-r--r--main/openrc/hwclock-hctosys.patch15
-rw-r--r--main/openrc/hwdrivers.initd27
-rw-r--r--main/openrc/keymaps.initd20
-rw-r--r--main/openrc/modloop.confd3
-rw-r--r--main/openrc/modloop.initd100
-rw-r--r--main/openrc/modules.initd23
-rw-r--r--main/openrc/networking.initd69
-rw-r--r--main/openrc/openrc-0.4.3-command-line-size-fix.patch94
-rw-r--r--main/openrc/openrc-0.4.3-mkmntdirs.patch11
-rw-r--r--main/openrc/openrc-hwclock.patch13
-rw-r--r--main/openrc/openrc.post-install36
-rw-r--r--main/openrc/openrc.post-upgrade28
-rw-r--r--main/openrc/remove-rc_sys-warning.patch10
-rw-r--r--main/openresolv/APKBUILD26
-rw-r--r--main/openssh/APKBUILD92
-rw-r--r--main/openssh/sshd.confd21
-rw-r--r--main/openssh/sshd.initd92
-rw-r--r--main/openssl/0001-crypto-hmac-support-EVP_MD_CTX_FLAG_ONESHOT-and-set-.patch82
-rw-r--r--main/openssl/0002-apps-speed-fix-digest-speed-measurement-and-add-hmac.patch392
-rw-r--r--main/openssl/0003-engines-e_padlock-backport-cvs-head-changes.patch203
-rw-r--r--main/openssl/0004-engines-e_padlock-implement-sha1-sha224-sha256-accel.patch780
-rw-r--r--main/openssl/0005-crypto-engine-autoload-padlock-dynamic-engine.patch33
-rw-r--r--main/openssl/APKBUILD79
-rw-r--r--main/openssl/fix-manpages.patch1329
-rw-r--r--main/openssl/openssl-bb-basename.patch20
-rw-r--r--main/opentracker/APKBUILD36
-rw-r--r--main/opentracker/opentracker.initd38
-rw-r--r--main/opentracker/opentracker.pre-install5
-rw-r--r--main/openvpn-auth-ldap/APKBUILD42
-rw-r--r--main/openvpn/APKBUILD96
-rw-r--r--main/openvpn/openvpn-2.2.0-ipv6-20110522-1.patch4179
-rw-r--r--main/openvpn/openvpn.confd18
-rw-r--r--main/openvpn/openvpn.down33
-rw-r--r--main/openvpn/openvpn.initd133
-rw-r--r--main/openvpn/openvpn.up82
-rw-r--r--main/oprofile/APKBUILD47
-rw-r--r--main/oprofile/oprofile-pic.patch49
-rw-r--r--main/orage/APKBUILD35
-rw-r--r--main/orbit2/APKBUILD41
-rw-r--r--main/orc/APKBUILD57
-rw-r--r--main/osmo/APKBUILD39
-rw-r--r--main/osmo/osmo-0.2.10-build-mo.patch20
-rw-r--r--main/p7zip/APKBUILD35
-rw-r--r--main/p7zip/p7zip-cc-cxx.patch22
-rw-r--r--main/pango/APKBUILD33
-rw-r--r--main/pango/pango.post-install2
-rw-r--r--main/pango/pango.pre-deinstall2
-rw-r--r--main/pangomm/APKBUILD28
-rw-r--r--main/parole/APKBUILD37
-rw-r--r--main/parted/APKBUILD28
-rw-r--r--main/parted/nocxx.patch15
-rw-r--r--main/patch/APKBUILD28
-rw-r--r--main/patch/patch.post-deinstall3
-rw-r--r--main/patch/patch.post-upgrade3
-rw-r--r--main/pax-utils/APKBUILD24
-rw-r--r--main/paxctl/APKBUILD27
-rw-r--r--main/pciutils/APKBUILD41
-rw-r--r--main/pcmciautils/APKBUILD25
-rw-r--r--main/pcre/APKBUILD51
-rw-r--r--main/pcre/uclibc-strtoq.patch18
-rw-r--r--main/pdnsd/APKBUILD101
-rw-r--r--main/pdnsd/pdnsd.conf51
-rw-r--r--main/pdnsd/pdnsd.confd18
-rw-r--r--main/pdnsd/pdnsd.initd25
-rw-r--r--main/pdnsd/pdnsd.post-deinstall4
-rw-r--r--main/pdnsd/pdnsd.pre-install4
-rw-r--r--main/pekwm/APKBUILD37
-rw-r--r--main/perdition/APKBUILD54
-rw-r--r--main/perdition/perdition.confd50
-rw-r--r--main/perdition/perdition.initd76
-rw-r--r--main/perdition/perdition.post-install4
-rw-r--r--main/perl-apache-session/APKBUILD37
-rw-r--r--main/perl-archive-zip/APKBUILD31
-rw-r--r--main/perl-astro-suntime/APKBUILD33
-rw-r--r--main/perl-authen-sasl/APKBUILD26
-rw-r--r--main/perl-cache-cache/APKBUILD37
-rw-r--r--main/perl-cache-simple-timedexpiry/APKBUILD39
-rw-r--r--main/perl-carp-clan/APKBUILD37
-rw-r--r--main/perl-cgi-emulate-psgi/APKBUILD37
-rw-r--r--main/perl-cgi-psgi/APKBUILD37
-rw-r--r--main/perl-cgi-session/APKBUILD27
-rw-r--r--main/perl-class-accessor-chained/APKBUILD37
-rw-r--r--main/perl-class-accessor-lite/APKBUILD37
-rw-r--r--main/perl-class-accessor/APKBUILD39
-rw-r--r--main/perl-class-container/APKBUILD37
-rw-r--r--main/perl-class-data-inheritable/APKBUILD37
-rw-r--r--main/perl-class-inspector/APKBUILD39
-rw-r--r--main/perl-class-load/APKBUILD39
-rw-r--r--main/perl-class-returnvalue/APKBUILD39
-rw-r--r--main/perl-class-singleton/APKBUILD39
-rw-r--r--main/perl-clone/APKBUILD39
-rw-r--r--main/perl-compress-raw-bzip2/APKBUILD33
-rw-r--r--main/perl-compress-raw-zlib/APKBUILD33
-rw-r--r--main/perl-control-x10/APKBUILD28
-rw-r--r--main/perl-convert-binhex/APKBUILD31
-rw-r--r--main/perl-convert-color/APKBUILD37
-rw-r--r--main/perl-convert-tnef/APKBUILD31
-rw-r--r--main/perl-convert-uulib/APKBUILD27
-rw-r--r--main/perl-crypt-openssl-random/APKBUILD27
-rw-r--r--main/perl-crypt-openssl-rsa/APKBUILD27
-rw-r--r--main/perl-css-squish/APKBUILD39
-rw-r--r--main/perl-data-ical/APKBUILD37
-rw-r--r--main/perl-data-optlist/APKBUILD39
-rw-r--r--main/perl-date-calc/APKBUILD30
-rw-r--r--main/perl-date-format/APKBUILD37
-rw-r--r--main/perl-date-manip/APKBUILD35
-rw-r--r--main/perl-datetime-format-mail/APKBUILD39
-rw-r--r--main/perl-datetime-format-w3cdtf/APKBUILD39
-rw-r--r--main/perl-datetime-locale/APKBUILD39
-rw-r--r--main/perl-datetime-timezone/APKBUILD39
-rw-r--r--main/perl-datetime/APKBUILD41
-rw-r--r--main/perl-db/APKBUILD31
-rw-r--r--main/perl-db_file/APKBUILD31
-rw-r--r--main/perl-dbd-mysql/APKBUILD32
-rw-r--r--main/perl-dbd-pg/APKBUILD37
-rw-r--r--main/perl-dbd-sqlite/APKBUILD34
-rw-r--r--main/perl-dbi/APKBUILD35
-rw-r--r--main/perl-dbix-dbschema/APKBUILD39
-rw-r--r--main/perl-dbix-searchbuilder/APKBUILD40
-rw-r--r--main/perl-devel-globaldestruction/APKBUILD39
-rw-r--r--main/perl-devel-stacktrace-ashtml/APKBUILD39
-rw-r--r--main/perl-devel-stacktrace/APKBUILD37
-rw-r--r--main/perl-devel-symdump/APKBUILD37
-rw-r--r--main/perl-device-serialport/APKBUILD33
-rw-r--r--main/perl-digest-hmac/APKBUILD30
-rw-r--r--main/perl-digest-sha1/APKBUILD27
-rw-r--r--main/perl-email-address/APKBUILD39
-rw-r--r--main/perl-email-date-format/APKBUILD37
-rw-r--r--main/perl-encode-locale/APKBUILD32
-rw-r--r--main/perl-error/APKBUILD31
-rw-r--r--main/perl-exception-class/APKBUILD37
-rw-r--r--main/perl-extutils-cchecker/APKBUILD30
-rw-r--r--main/perl-fcgi-procmanager/APKBUILD39
-rw-r--r--main/perl-fcgi/APKBUILD31
-rw-r--r--main/perl-file-listing/APKBUILD40
-rw-r--r--main/perl-file-next/APKBUILD31
-rw-r--r--main/perl-file-rsync/APKBUILD39
-rw-r--r--main/perl-file-rsync/perl-file-rsync-parallell-build-fix.patch20
-rw-r--r--main/perl-file-sharedir/APKBUILD39
-rw-r--r--main/perl-file-slurp/APKBUILD37
-rw-r--r--main/perl-file-tail/APKBUILD37
-rw-r--r--main/perl-filesys-notify-simple/APKBUILD39
-rw-r--r--main/perl-font-afm/APKBUILD37
-rw-r--r--main/perl-getopt-long/APKBUILD31
-rw-r--r--main/perl-hash-multivalue/APKBUILD39
-rw-r--r--main/perl-html-format/APKBUILD37
-rw-r--r--main/perl-html-mason-psgihandler/APKBUILD37
-rw-r--r--main/perl-html-mason/APKBUILD37
-rw-r--r--main/perl-html-parser/APKBUILD27
-rw-r--r--main/perl-html-quoted/APKBUILD39
-rw-r--r--main/perl-html-rewriteattributes/APKBUILD37
-rw-r--r--main/perl-html-scrubber/APKBUILD39
-rw-r--r--main/perl-html-tagset/APKBUILD37
-rw-r--r--main/perl-html-tree/APKBUILD37
-rw-r--r--main/perl-http-body/APKBUILD39
-rw-r--r--main/perl-http-cookies/APKBUILD40
-rw-r--r--main/perl-http-daemon/APKBUILD40
-rw-r--r--main/perl-http-date/APKBUILD33
-rw-r--r--main/perl-http-message/APKBUILD41
-rw-r--r--main/perl-http-negotiate/APKBUILD39
-rw-r--r--main/perl-image-exiftool/APKBUILD48
-rw-r--r--main/perl-inline/APKBUILD31
-rw-r--r--main/perl-io-compress/APKBUILD32
-rw-r--r--main/perl-io-multiplex/APKBUILD27
-rw-r--r--main/perl-io-socket-ssl/APKBUILD31
-rw-r--r--main/perl-io-stringy/APKBUILD27
-rw-r--r--main/perl-ipc-run3/APKBUILD39
-rw-r--r--main/perl-javascript-minifier/APKBUILD37
-rw-r--r--main/perl-json/APKBUILD31
-rw-r--r--main/perl-libwww/APKBUILD34
-rw-r--r--main/perl-list-moreutils/APKBUILD40
-rw-r--r--main/perl-list-utilsby/APKBUILD37
-rw-r--r--main/perl-locale-maketext-fuzzy/APKBUILD39
-rw-r--r--main/perl-locale-maketext-lexicon/APKBUILD39
-rw-r--r--main/perl-log-any/APKBUILD37
-rw-r--r--main/perl-log-dispatch/APKBUILD39
-rw-r--r--main/perl-lwp-mediatypes/APKBUILD33
-rw-r--r--main/perl-lwp-useragent-determined/APKBUILD34
-rw-r--r--main/perl-mail-clamav/APKBUILD38
-rw-r--r--main/perl-mail-dkim/APKBUILD30
-rw-r--r--main/perl-mail-domainkeys/APKBUILD31
-rw-r--r--main/perl-mail-spamassassin/APKBUILD33
-rw-r--r--main/perl-mail-spamassassin/spamassassin-3.2.5-DESTDIR.patch273
-rw-r--r--main/perl-mail-spf/APKBUILD41
-rw-r--r--main/perl-mail-spf/build.patch62
-rw-r--r--main/perl-mail-tools/APKBUILD31
-rw-r--r--main/perl-math-round/APKBUILD39
-rw-r--r--main/perl-mime-lite/APKBUILD34
-rw-r--r--main/perl-mime-tools/APKBUILD31
-rw-r--r--main/perl-mime-types/APKBUILD37
-rw-r--r--main/perl-module-versions-report/APKBUILD39
-rw-r--r--main/perl-net-cidr-lite/APKBUILD27
-rw-r--r--main/perl-net-cidr/APKBUILD39
-rw-r--r--main/perl-net-dns-resolver-programmable/APKBUILD33
-rw-r--r--main/perl-net-dns/APKBUILD31
-rw-r--r--main/perl-net-http/APKBUILD40
-rw-r--r--main/perl-net-ip/APKBUILD31
-rw-r--r--main/perl-net-rblclient/APKBUILD31
-rw-r--r--main/perl-net-server/APKBUILD31
-rw-r--r--main/perl-net-smtp-ssl/APKBUILD31
-rw-r--r--main/perl-net-snpp/APKBUILD33
-rw-r--r--main/perl-net-ssleay/APKBUILD31
-rw-r--r--main/perl-netaddr-ip/APKBUILD36
-rw-r--r--main/perl-parallel-prefork/APKBUILD37
-rw-r--r--main/perl-params-util/APKBUILD41
-rw-r--r--main/perl-params-validate/APKBUILD39
-rw-r--r--main/perl-parse-recdescent/APKBUILD31
-rw-r--r--main/perl-parse-syslog/APKBUILD31
-rw-r--r--main/perl-php-serialization/APKBUILD32
-rw-r--r--main/perl-plack/APKBUILD50
-rw-r--r--main/perl-pod-coverage/APKBUILD37
-rw-r--r--main/perl-proc-wait3/APKBUILD37
-rw-r--r--main/perl-regexp-common-net-cidr/APKBUILD39
-rw-r--r--main/perl-regexp-common/APKBUILD39
-rw-r--r--main/perl-regexp-ipv6/APKBUILD39
-rw-r--r--main/perl-scope-guard/APKBUILD39
-rw-r--r--main/perl-server-starter/APKBUILD37
-rw-r--r--main/perl-snmp-session/APKBUILD26
-rw-r--r--main/perl-socket-getaddrinfo/APKBUILD30
-rw-r--r--main/perl-starlet/APKBUILD37
-rw-r--r--main/perl-sub-exporter/APKBUILD40
-rw-r--r--main/perl-sub-install/APKBUILD39
-rw-r--r--main/perl-sub-uplevel/APKBUILD36
-rw-r--r--main/perl-switch/APKBUILD39
-rw-r--r--main/perl-sys-hostname-long/APKBUILD33
-rw-r--r--main/perl-sys-mmap/APKBUILD29
-rw-r--r--main/perl-term-readkey/APKBUILD37
-rw-r--r--main/perl-test-deep/APKBUILD39
-rw-r--r--main/perl-test-exception/APKBUILD36
-rw-r--r--main/perl-test-fatal/APKBUILD37
-rw-r--r--main/perl-test-inter/APKBUILD37
-rw-r--r--main/perl-test-longstring/APKBUILD39
-rw-r--r--main/perl-test-manifest/APKBUILD39
-rw-r--r--main/perl-test-mockobject/APKBUILD33
-rw-r--r--main/perl-test-nowarnings/APKBUILD39
-rw-r--r--main/perl-test-pod-coverage/APKBUILD37
-rw-r--r--main/perl-test-pod/APKBUILD30
-rw-r--r--main/perl-test-requires/APKBUILD39
-rw-r--r--main/perl-test-sharedfork/APKBUILD39
-rw-r--r--main/perl-test-tcp/APKBUILD39
-rw-r--r--main/perl-test-tester/APKBUILD39
-rw-r--r--main/perl-test-warn/APKBUILD37
-rw-r--r--main/perl-text-autoformat/APKBUILD39
-rw-r--r--main/perl-text-csv/APKBUILD27
-rw-r--r--main/perl-text-password-pronounceable/APKBUILD39
-rw-r--r--main/perl-text-quoted/APKBUILD39
-rw-r--r--main/perl-text-reform/APKBUILD39
-rw-r--r--main/perl-text-template/APKBUILD39
-rw-r--r--main/perl-text-vfile-asdata/APKBUILD37
-rw-r--r--main/perl-text-wikiformat/APKBUILD37
-rw-r--r--main/perl-text-wrapper/APKBUILD39
-rw-r--r--main/perl-time-date/APKBUILD31
-rw-r--r--main/perl-time-hires/APKBUILD32
-rw-r--r--main/perl-time-modules/APKBUILD32
-rw-r--r--main/perl-tree-dag_node/APKBUILD37
-rw-r--r--main/perl-tree-simple/APKBUILD42
-rw-r--r--main/perl-try-tiny/APKBUILD39
-rw-r--r--main/perl-universal-require/APKBUILD39
-rw-r--r--main/perl-unix-syslog/APKBUILD28
-rw-r--r--main/perl-uri-escape/APKBUILD31
-rw-r--r--main/perl-uri/APKBUILD26
-rw-r--r--main/perl-want/APKBUILD39
-rw-r--r--main/perl-www-robotrules/APKBUILD40
-rw-r--r--main/perl-x10/APKBUILD34
-rw-r--r--main/perl-xml-parser/APKBUILD26
-rw-r--r--main/perl-xml-rss/APKBUILD37
-rw-r--r--main/perl-xml-simple/APKBUILD26
-rw-r--r--main/perl-yaml-syck/APKBUILD36
-rw-r--r--main/perl/APKBUILD68
-rw-r--r--main/pflogsumm/APKBUILD26
-rw-r--r--main/pgcluster/APKBUILD56
-rw-r--r--main/pgcluster/pgcluster.confd57
-rw-r--r--main/pgcluster/pgcluster.initd173
-rw-r--r--main/pgpool/APKBUILD36
-rw-r--r--main/pgpool/commit-queue1
-rw-r--r--main/pgpool/pgpool.initd25
-rw-r--r--main/php-apc/APKBUILD33
-rw-r--r--main/php-apc/apc.ini11
-rw-r--r--main/php-mailparse/APKBUILD46
-rw-r--r--main/php-mailparse/mailparse.ini1
-rw-r--r--main/php-pear-mdb2/APKBUILD66
-rw-r--r--main/php/APKBUILD452
-rw-r--r--main/php/php-fpm.initd22
-rw-r--r--main/php/php-install-pear-xml.patch15
-rw-r--r--main/php/php-uclibc.patch11
-rw-r--r--main/php/php.post-upgrade11
-rw-r--r--main/php/php5-module.conf5
-rw-r--r--main/php/suhosin-patch-5.3.6-0.9.10.patch5776
-rw-r--r--main/phpmyadmin/APKBUILD88
-rw-r--r--main/phpmyadmin/phpmyadmin.apache2.conf7
-rw-r--r--main/phpmyadmin/phpmyadmin.post-install16
-rw-r--r--main/pianobar/APKBUILD38
-rw-r--r--main/pidgin/APKBUILD63
-rw-r--r--main/pinentry/APKBUILD42
-rw-r--r--main/pinentry/pinentry-gtk.post-deinstall8
-rw-r--r--main/pinentry/pinentry-gtk.post-install4
-rw-r--r--main/pinentry/pinentry.post-deinstall6
-rw-r--r--main/pinentry/pinentry.post-install6
-rw-r--r--main/pingu/APKBUILD25
-rw-r--r--main/pingu/pingu.initd28
-rw-r--r--main/pixman/APKBUILD26
-rw-r--r--main/pjproject/APKBUILD40
-rw-r--r--main/pkgconfig/APKBUILD20
-rw-r--r--main/pllua/APKBUILD37
-rw-r--r--main/pllua/pllua-01-0.3.1-include.patch14
-rw-r--r--main/pmacct/APKBUILD64
-rw-r--r--main/pmacct/nfacctd.conf11
-rw-r--r--main/pmacct/pmacct.confd7
-rw-r--r--main/pmacct/pmacct.initd30
-rwxr-xr-xmain/pmacct/pmacct.post-deinstall4
-rw-r--r--main/pmacct/pmacct.post-install4
-rw-r--r--main/pmacct/pmacctd.conf11
-rw-r--r--main/pmacct/sfacctd.conf9
-rw-r--r--main/pmacct/uacctd.conf9
-rw-r--r--main/policyd-spf-fs/APKBUILD41
-rw-r--r--main/policyd-spf-fs/policyd-spf-fs-localpolicy-fix.patch10
-rw-r--r--main/polkit/APKBUILD52
-rw-r--r--main/poppler-gtk/APKBUILD58
-rw-r--r--main/poppler/APKBUILD49
-rw-r--r--main/popt/APKBUILD35
-rw-r--r--main/postfix-policyd-spf-perl/APKBUILD21
-rw-r--r--main/postfix/0001-support-for-dynamic-maps.patch1107
-rw-r--r--main/postfix/APKBUILD163
-rw-r--r--main/postfix/dynamicmaps.cf16
-rw-r--r--main/postfix/postfix-ldap.post-install19
-rw-r--r--main/postfix/postfix-mysql.post-install19
-rw-r--r--main/postfix/postfix-pcre.post-install25
-rw-r--r--main/postfix/postfix-pgsql.post-install19
-rw-r--r--main/postfix/postfix-sqlite.post-install19
-rw-r--r--main/postfix/postfix.initd50
-rw-r--r--main/postfix/postfix.post-install6
-rw-r--r--main/postfix/postfix.pre-install7
-rw-r--r--main/postgresql/APKBUILD65
-rw-r--r--main/postgresql/pg-restore.confd16
-rw-r--r--main/postgresql/pg-restore.initd37
-rw-r--r--main/postgresql/postgresql.confd56
-rw-r--r--main/postgresql/postgresql.initd138
-rw-r--r--main/postgresql/postgresql.pre-upgrade31
-rw-r--r--main/postgrey/APKBUILD41
-rw-r--r--main/postgrey/postgrey.confd55
-rw-r--r--main/postgrey/postgrey.initd102
-rw-r--r--main/postgrey/postgrey.pre-install6
-rw-r--r--main/pound/APKBUILD41
-rw-r--r--main/pound/pound-2.5-openssl.patch290
-rw-r--r--main/pound/pound.cfg54
-rw-r--r--main/pound/pound.initd26
-rw-r--r--main/ppp/APKBUILD67
-rw-r--r--main/ppp/ip-down4
-rw-r--r--main/ppp/ip-up4
-rw-r--r--main/ppp/options356
-rw-r--r--main/ppp/plog7
-rw-r--r--main/ppp/poff103
-rw-r--r--main/ppp/pon32
-rw-r--r--main/ppp/pon.1121
-rw-r--r--main/printproto/APKBUILD24
-rw-r--r--main/privoxy/APKBUILD57
-rw-r--r--main/privoxy/privoxy-3.0.16-gentoo.patch108
-rw-r--r--main/privoxy/privoxy.initd32
-rw-r--r--main/privoxy/privoxy.logrotate9
-rw-r--r--main/privoxy/privoxy.pre-install6
-rw-r--r--main/procps/01-fix-install-options-for-busybox.patch65
-rw-r--r--main/procps/APKBUILD42
-rw-r--r--main/psqlodbc/APKBUILD28
-rw-r--r--main/pth/APKBUILD42
-rw-r--r--main/pth/pth-2.0.5-parallelfix.patch15
-rw-r--r--main/pth/pth-2.0.6-ldflags.patch17
-rw-r--r--main/pth/pth-2.0.6-sigstack.patch22
-rw-r--r--main/putty/APKBUILD47
-rw-r--r--main/pwgen/APKBUILD31
-rw-r--r--main/py-boto/APKBUILD51
-rw-r--r--main/py-cairo/APKBUILD37
-rw-r--r--main/py-dbus/APKBUILD26
-rw-r--r--main/py-docutils/APKBUILD55
-rw-r--r--main/py-genshi/APKBUILD27
-rw-r--r--main/py-gobject/APKBUILD38
-rw-r--r--main/py-gst/APKBUILD43
-rw-r--r--main/py-gtk/APKBUILD41
-rw-r--r--main/py-imaging/APKBUILD28
-rw-r--r--main/py-jinja2/APKBUILD66
-rw-r--r--main/py-pygments/APKBUILD60
-rw-r--r--main/py-roman/APKBUILD34
-rw-r--r--main/py-setuptools/APKBUILD30
-rw-r--r--main/py-sphinx/APKBUILD56
-rw-r--r--main/py-sqlite/APKBUILD27
-rw-r--r--main/py-templayer/APKBUILD44
-rw-r--r--main/py-urwid/APKBUILD50
-rw-r--r--main/py-xml/APKBUILD28
-rw-r--r--main/py-xml/fix-python2.6.patch28
-rw-r--r--main/python/APKBUILD78
-rw-r--r--main/qemu/80-kvm.rules1
-rw-r--r--main/qemu/APKBUILD110
-rw-r--r--main/qemu/kqemu.c997
-rw-r--r--main/qemu/qemu-libm.patch11
-rw-r--r--main/qemu/qemu.pre-install6
-rw-r--r--main/qt/APKBUILD236
-rw-r--r--main/qt/PKGBUILD119
-rw-r--r--main/qt/assistant.desktop8
-rw-r--r--main/qt/designer.desktop9
-rw-r--r--main/qt/linguist.desktop9
-rw-r--r--main/qt/qt.install11
-rw-r--r--main/qt/qtconfig.desktop8
-rw-r--r--main/quagga/APKBUILD80
-rw-r--r--main/quagga/bgpd.initd34
-rw-r--r--main/quagga/ospf6d.initd34
-rw-r--r--main/quagga/ospfd.initd34
-rw-r--r--main/quagga/quagga-0.99.11-del-routes.patch44
-rw-r--r--main/quagga/quagga-0.99.11-link-libcap.patch24
-rw-r--r--main/quagga/quagga.post-install6
-rw-r--r--main/quagga/quagga.pre-install7
-rw-r--r--main/quagga/ripd.initd34
-rw-r--r--main/quagga/ripngd.initd34
-rw-r--r--main/quagga/zebra.confd7
-rw-r--r--main/quagga/zebra.initd42
-rw-r--r--main/randrproto/APKBUILD25
-rw-r--r--main/rarian/APKBUILD34
-rw-r--r--main/rarian/user-segfault.patch14
-rw-r--r--main/razor/APKBUILD27
-rw-r--r--main/rdesktop/APKBUILD26
-rw-r--r--main/rdiff-backup/APKBUILD27
-rw-r--r--main/re2c/APKBUILD38
-rw-r--r--main/readline/APKBUILD51
-rw-r--r--main/recordmydesktop/APKBUILD38
-rw-r--r--main/recordmydesktop/recordmydesktop-bitrate.patch50
-rw-r--r--main/recordmydesktop/shmstr-to-shmproto.patch20
-rw-r--r--main/recordproto/APKBUILD24
-rw-r--r--main/redmine/APKBUILD85
-rw-r--r--main/redmine/additional_environment.rb16
-rw-r--r--main/redmine/configuration.yml147
-rw-r--r--main/redmine/database.yml10
-rw-r--r--main/redmine/lighttpd-virtual.conf26
-rw-r--r--main/reiserfsprogs/APKBUILD37
-rw-r--r--main/remmina-plugins/APKBUILD37
-rw-r--r--main/remmina-xfce/APKBUILD30
-rw-r--r--main/remmina/APKBUILD36
-rw-r--r--main/renderproto/APKBUILD21
-rw-r--r--main/resourceproto/APKBUILD23
-rw-r--r--main/rgb/APKBUILD24
-rw-r--r--main/ristretto/APKBUILD28
-rw-r--r--main/roundcubemail/APKBUILD67
-rw-r--r--main/roundcubemail/fix-dirs.patch50
-rw-r--r--main/roundcubemail/roundcubemail.post-upgrade47
-rw-r--r--main/roundcubemail/roundcubemail.pre-upgrade7
-rw-r--r--main/rpcbind/0001-uclibc-nss.patch28
-rw-r--r--main/rpcbind/0002-uclibc-rpcsvc-defines.patch58
-rw-r--r--main/rpcbind/APKBUILD43
-rw-r--r--main/rpcbind/rpcbind.confd4
-rw-r--r--main/rpcbind/rpcbind.initd25
-rw-r--r--main/rrdtool/APKBUILD52
-rw-r--r--main/rsync/APKBUILD42
-rw-r--r--main/rsync/rsyncd.conf10
-rw-r--r--main/rsync/rsyncd.confd5
-rw-r--r--main/rsync/rsyncd.initd24
-rw-r--r--main/rsync/rsyncd.logrotate9
-rw-r--r--main/rt4/APKBUILD127
-rw-r--r--main/rtmpdump/APKBUILD33
-rw-r--r--main/rtpproxy/APKBUILD48
-rw-r--r--main/rtpproxy/rtpproxy.confd8
-rw-r--r--main/rtpproxy/rtpproxy.initd25
-rw-r--r--main/rtpproxy/rtpproxy.pre-install5
-rw-r--r--main/ruby-actionmailer/APKBUILD32
-rw-r--r--main/ruby-actionpack/APKBUILD32
-rw-r--r--main/ruby-activerecord/APKBUILD32
-rw-r--r--main/ruby-activeresource/APKBUILD32
-rw-r--r--main/ruby-activesupport/APKBUILD32
-rw-r--r--main/ruby-fcgi/APKBUILD32
-rw-r--r--main/ruby-i18n/APKBUILD32
-rw-r--r--main/ruby-mysql/APKBUILD32
-rw-r--r--main/ruby-openid/APKBUILD32
-rw-r--r--main/ruby-pg/APKBUILD32
-rw-r--r--main/ruby-rack/APKBUILD31
-rw-r--r--main/ruby-rails/APKBUILD33
-rw-r--r--main/ruby-rake/APKBUILD31
-rw-r--r--main/ruby-rmagick/APKBUILD31
-rw-r--r--main/ruby-sqlite/APKBUILD32
-rw-r--r--main/ruby/APKBUILD56
-rw-r--r--main/rubygems/APKBUILD26
-rw-r--r--main/run-parts/APKBUILD24
-rw-r--r--main/rxmtp/APKBUILD26
-rw-r--r--main/samba/APKBUILD159
-rw-r--r--main/samba/samba-maximum-number-of-winbindd-clients.patch134
-rw-r--r--main/samba/samba-uclibc-fstab.patch15
-rw-r--r--main/samba/samba.confd6
-rw-r--r--main/samba/samba.initd65
-rw-r--r--main/samba/samba.logrotate9
-rw-r--r--main/samba/winbind.post-install6
l---------main/samba/winbind.post-upgrade1
-rw-r--r--main/samba/winbind.pre-install5
l---------main/samba/winbind.pre-upgrade1
-rw-r--r--main/screen/APKBUILD34
-rw-r--r--main/screen/screen-4.0.3.patch272
-rw-r--r--main/scrnsaverproto/APKBUILD25
-rw-r--r--main/scrot/APKBUILD25
-rw-r--r--main/scstadmin/APKBUILD38
-rw-r--r--main/scstadmin/scst-init-ash-comapt.patch35
-rw-r--r--main/sdl/APKBUILD34
-rw-r--r--main/sdl_image/APKBUILD46
-rw-r--r--main/sdl_image/sdl-image-1.2.10-libpng15.patch160
-rw-r--r--main/sdl_mixer/APKBUILD42
-rw-r--r--main/sed/APKBUILD26
-rw-r--r--main/sed/sed.post-deinstall3
-rw-r--r--main/sems/APKBUILD202
-rw-r--r--main/sems/sems-0001-Force-to-use-system-wide-GSM-includes.patch26
-rw-r--r--main/sems/sems-0002-Allow-rewrite-of-custom-makefiles-by-CMake.patch33
-rw-r--r--main/sems/sems-0003-Set-CFG_PREFIX-to-empty-string-by-default.patch26
-rw-r--r--main/sems/sems-0010-Move-CMake-defines.patch66
-rwxr-xr-xmain/sems/sems.initd48
-rw-r--r--main/sems/sems.pre-install10
-rw-r--r--main/sendpage/APKBUILD46
-rw-r--r--main/sessreg/APKBUILD24
-rw-r--r--main/setxkbmap/APKBUILD21
-rw-r--r--main/sfic/APKBUILD37
-rw-r--r--main/sfic/sfic-0.1.7-signal.patch10
-rw-r--r--main/sg3_utils/APKBUILD38
-rw-r--r--main/shared-mime-info/APKBUILD27
-rw-r--r--main/shared-mime-info/shared-mime-info.post-deinstall10
-rw-r--r--main/shared-mime-info/shared-mime-info.trigger7
-rw-r--r--main/shorewall-common/APKBUILD22
-rw-r--r--main/shorewall-common/shorewall.initd80
-rw-r--r--main/shorewall-lite/APKBUILD21
-rwxr-xr-xmain/shorewall-lite/shorewall-lite.initd65
-rw-r--r--main/shorewall-perl/APKBUILD17
-rw-r--r--main/shorewall-shell/APKBUILD30
-rw-r--r--main/shorewall-shell/shorewall-policyrouting.patch47
-rw-r--r--main/shorewall/APKBUILD17
-rw-r--r--main/shotwell/APKBUILD45
-rw-r--r--main/shotwell/shotwell.post-install7
-rw-r--r--main/shotwell/shotwell.post-upgrade7
-rw-r--r--main/shotwell/shotwell.pre-deinstall7
-rw-r--r--main/sic/APKBUILD24
-rw-r--r--main/sircbot/APKBUILD46
-rw-r--r--main/sircbot/sircbot.confd5
-rw-r--r--main/sircbot/sircbot.initd35
-rw-r--r--main/sircbot/sircbot.pre-install5
-rw-r--r--main/slang/APKBUILD39
-rw-r--r--main/slang/slang-2.2.3-slsh-libs.patch11
-rw-r--r--main/slim-themes/APKBUILD65
-rw-r--r--main/slim/APKBUILD66
-rw-r--r--main/slim/slim-1.3.1-gcc4.4.patch17
-rw-r--r--main/slim/slim-png15.patch11
-rw-r--r--main/slim/slim-restart.patch141
-rwxr-xr-xmain/slim/slim.initd18
-rw-r--r--main/slim/slim.install7
-rw-r--r--main/slim/slim.logrotate9
-rw-r--r--main/smokeping/APKBUILD112
-rw-r--r--main/smokeping/smokeping.initd77
-rw-r--r--main/smokeping/smokeping.pre-install5
-rw-r--r--main/snmptt/APKBUILD29
-rw-r--r--main/snort/APKBUILD47
-rw-r--r--main/snort/snort.confd16
-rw-r--r--main/snort/snort.initd32
-rw-r--r--main/snort/snort.pre-install4
-rw-r--r--main/snowfox/APKBUILD101
-rw-r--r--main/snowfox/firefox-agent.patch12
-rw-r--r--main/snowfox/firefox-defaults.patch22
-rw-r--r--main/snowfox/firefox-restore-fx3-tab-behaviour-as-default.patch11
-rw-r--r--main/snowfox/firefox-restore-status-bar.patch37
-rw-r--r--main/snowfox/firefox-safe.desktop11
-rw-r--r--main/snowfox/firefox-version.patch11
-rw-r--r--main/snowfox/firefox.desktop81
-rw-r--r--main/snowfox/mozconfig36
-rw-r--r--main/sntpc/APKBUILD27
-rw-r--r--main/sntpc/sntpc.confd9
-rw-r--r--main/sntpc/sntpc.initd31
-rw-r--r--main/socat/APKBUILD33
-rw-r--r--main/sox/APKBUILD48
-rw-r--r--main/sox/sox-ffmpeg-0.8.patch38
-rw-r--r--main/sox/sox-uclibc.patch22
-rw-r--r--main/spamassassin/APKBUILD43
-rw-r--r--main/spamassassin/spamassassin-3.2.5-DESTDIR.patch273
-rw-r--r--main/spamassassin/spamassassin-3.3.1-PERL-5-12.patch240
-rw-r--r--main/spamassassin/spamd.conf46
-rw-r--r--main/spamassassin/spamd.init39
-rw-r--r--main/spandsp/APKBUILD34
-rw-r--r--main/speedometer/APKBUILD32
-rw-r--r--main/speex/APKBUILD43
-rw-r--r--main/sqlite/APKBUILD78
-rw-r--r--main/sqlite/license.txt33
-rw-r--r--main/sqsh/APKBUILD46
-rw-r--r--main/squark/APKBUILD38
-rw-r--r--main/squashfs-tools/APKBUILD23
-rw-r--r--main/squid/APKBUILD304
-rw-r--r--main/squid/squid-2-heimdal.patch18
-rw-r--r--main/squid/squid-2.7-gentoo.patch298
-rw-r--r--main/squid/squid-2.7-ims-content-type.patch11
-rw-r--r--main/squid/squid-2.7-loggable-urlgroup.patch33
-rw-r--r--main/squid/squid.confd15
-rw-r--r--main/squid/squid.initd115
-rw-r--r--main/squid/squid.logrotate11
-rw-r--r--main/squid/squid.post-install5
-rw-r--r--main/squid/squid.pre-install6
l---------main/squid/squid.pre-upgrade1
-rw-r--r--main/sshfs/APKBUILD26
-rw-r--r--main/ssmtp/APKBUILD41
-rw-r--r--main/ssmtp/CVE-2008-3962.patch14
-rw-r--r--main/ssmtp/generate_config.patch49
-rw-r--r--main/startup-notification/APKBUILD29
-rw-r--r--main/strace/APKBUILD29
-rw-r--r--main/subversion/APKBUILD42
-rw-r--r--main/subversion/subversion.pre-install6
-rw-r--r--main/subversion/svnserve.confd10
-rw-r--r--main/subversion/svnserve.initd45
-rw-r--r--main/sudo/APKBUILD46
-rw-r--r--main/sudo/libcrypt.patch11
-rw-r--r--main/swatch/APKBUILD59
-rw-r--r--main/swatch/swatch.confd8
-rwxr-xr-xmain/swatch/swatch.initd50
-rw-r--r--main/swatch/swatchrc103
-rw-r--r--main/swfdec-mozilla/APKBUILD24
-rw-r--r--main/swfdec/APKBUILD34
-rw-r--r--main/swig/APKBUILD24
-rw-r--r--main/swish-e/APKBUILD32
-rw-r--r--main/sylpheed/APKBUILD27
-rw-r--r--main/sysfsutils/APKBUILD26
-rw-r--r--main/sysklogd/APKBUILD61
-rw-r--r--main/sysklogd/LICENSE16
-rw-r--r--main/sysklogd/ksym-fclose-fix.diff12
-rw-r--r--main/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff162
-rw-r--r--main/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff103
-rw-r--r--main/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff118
-rw-r--r--main/sysklogd/sysklogd-1.5-build.patch20
-rw-r--r--main/sysklogd/sysklogd.confd6
-rwxr-xr-xmain/sysklogd/sysklogd.daily91
-rw-r--r--main/sysklogd/sysklogd.initd80
-rw-r--r--main/sysklogd/sysklogd.logrotate6
-rw-r--r--main/sysklogd/sysklogd.post-install5
-rw-r--r--main/sysklogd/sysklogd.pre-deinstall5
-rw-r--r--main/sysklogd/syslog.conf48
-rw-r--r--main/syslinux/APKBUILD40
-rw-r--r--main/syslinux/extlinux.conf26
-rw-r--r--main/syslinux/syslinux-3.86-nopie.patch11
-rw-r--r--main/syslinux/syslinux.trigger3
-rwxr-xr-xmain/syslinux/update-extlinux89
-rw-r--r--main/sysstat/APKBUILD31
-rw-r--r--main/taglib/APKBUILD25
-rw-r--r--main/talloc/APKBUILD44
-rw-r--r--main/talloc/always-libs.patch10
-rw-r--r--main/tango-icon-theme/APKBUILD25
-rw-r--r--main/tar/APKBUILD31
-rw-r--r--main/tcl/APKBUILD38
-rw-r--r--main/tcpdump/APKBUILD29
-rw-r--r--main/tcpflow/APKBUILD32
-rw-r--r--main/tcpproxy/APKBUILD27
-rw-r--r--main/tcpproxy/tcpproxy.initd14
-rw-r--r--main/terminal/APKBUILD32
-rw-r--r--main/terminal/terminal-dont-die-on-dbus-kill.patch10
-rw-r--r--main/testdisk/APKBUILD36
-rw-r--r--main/texinfo/APKBUILD23
-rw-r--r--main/tftp-hpa/APKBUILD33
-rw-r--r--main/tftp-hpa/in.tftpd.confd15
-rw-r--r--main/tftp-hpa/in.tftpd.initd21
-rw-r--r--main/thunar-archive-plugin/APKBUILD30
-rw-r--r--main/thunar/APKBUILD62
-rw-r--r--main/thunar/thunar-sendto-audacious-playlist.desktop14
-rw-r--r--main/thunar/thunar-sendto-bluetooth.desktop13
l---------main/thunar/thunar.post-deinstall1
-rw-r--r--main/thunar/thunar.post-install5
l---------main/thunar/thunar.post-upgrade1
-rw-r--r--main/tiff/APKBUILD60
-rw-r--r--main/tig/APKBUILD44
-rw-r--r--main/tinc/APKBUILD51
-rw-r--r--main/tinc/tinc.networks13
-rw-r--r--main/tinc/tincd.initd64
-rw-r--r--main/tinc/tincd.lo.initd46
-rw-r--r--main/tinyproxy/APKBUILD41
-rw-r--r--main/tinyproxy/tinyproxy.initd46
-rwxr-xr-xmain/tinyproxy/tinyproxy.post-install6
-rwxr-xr-xmain/tinyproxy/tinyproxy.pre-install6
-rw-r--r--main/tmux/APKBUILD32
-rw-r--r--main/tolua++/APKBUILD38
-rw-r--r--main/trac/APKBUILD36
-rw-r--r--main/trac/trac.pre-install5
-rw-r--r--main/trac/tracd.confd13
-rwxr-xr-xmain/trac/tracd.initd27
-rw-r--r--main/transmission/APKBUILD68
-rw-r--r--main/transmission/transmission-daemon.confd18
-rw-r--r--main/transmission/transmission-daemon.initd22
-rw-r--r--main/transmission/transmission.pre-install5
-rw-r--r--main/ttf-dejavu/APKBUILD36
-rw-r--r--main/ttf-freefont/APKBUILD25
-rw-r--r--main/ttf-linux-libertine/APKBUILD33
-rw-r--r--main/ttf-ubuntu-font-family/APKBUILD29
-rw-r--r--main/tumbler/APKBUILD44
-rw-r--r--main/tzdata/0001-posixtz-fix-up-lseek.patch27
-rw-r--r--main/tzdata/APKBUILD53
-rw-r--r--main/tzdata/Makefile.patch140
-rw-r--r--main/ucarp/APKBUILD38
-rw-r--r--main/ucarp/ucarp.confd13
-rwxr-xr-xmain/ucarp/ucarp.initd67
-rw-r--r--main/uclibc++/001-path_to_make.patch30
-rw-r--r--main/uclibc++/002-no_bash.patch12
-rw-r--r--main/uclibc++/003-cp_command.patch19
-rw-r--r--main/uclibc++/004-ccache_fixes.patch24
-rw-r--r--main/uclibc++/005-wrapper.patch12
-rw-r--r--main/uclibc++/006-eabi_fix.patch42
-rw-r--r--main/uclibc++/007-numeric_limits.patch66
-rw-r--r--main/uclibc++/008-integer_width.patch314
-rw-r--r--main/uclibc++/900-dependent_exception.patch68
-rw-r--r--main/uclibc++/APKBUILD66
-rw-r--r--main/uclibc++/associative_base.patch13
-rw-r--r--main/uclibc++/uclibc++-gcc-4.3.patch73
-rw-r--r--main/uclibc++/uclibc++config54
-rw-r--r--main/udev/APKBUILD75
-rwxr-xr-xmain/udev/move_tmp_persistent_rules.sh25
-rw-r--r--main/udev/udev-mount.initd61
-rw-r--r--main/udev/udev-postmount.initd37
-rw-r--r--main/udev/udev.confd64
-rw-r--r--main/udev/udev.initd238
-rwxr-xr-xmain/udev/write_root_link_rule29
-rw-r--r--main/udisks/APKBUILD48
-rw-r--r--main/ulogd/APKBUILD59
-rw-r--r--main/ulogd/ulogd.confd2
-rw-r--r--main/ulogd/ulogd.initd39
-rw-r--r--main/ulogd/ulogd.logrotate12
-rw-r--r--main/umix/APKBUILD31
-rw-r--r--main/unarj/APKBUILD23
-rw-r--r--main/unfs3/APKBUILD23
-rw-r--r--main/unixodbc/APKBUILD36
-rw-r--r--main/unrar/APKBUILD27
-rw-r--r--main/upower/APKBUILD32
-rw-r--r--main/usbutils/APKBUILD32
-rw-r--r--main/util-linux-ng/APKBUILD105
-rw-r--r--main/util-linux-ng/program-invocation.patch11
-rw-r--r--main/util-macros/APKBUILD24
-rw-r--r--main/util-vserver/APKBUILD79
-rw-r--r--main/util-vserver/alpine.patch26
-rw-r--r--main/util-vserver/bb-grep.patch20
-rw-r--r--main/util-vserver/chmod.patch12
-rw-r--r--main/util-vserver/ensc_pathprog.patch14
-rw-r--r--main/util-vserver/setup-vs-guest306
-rw-r--r--main/util-vserver/setup-vs-template44
-rw-r--r--main/util-vserver/util-vserver.post-install15
l---------main/util-vserver/util-vserver.post-upgrade1
-rw-r--r--main/util-vserver/validate.patch10
-rw-r--r--main/uvncrepeater/APKBUILD44
-rw-r--r--main/uvncrepeater/uvncrepeater.confd4
-rw-r--r--main/uvncrepeater/uvncrepeater.initd32
-rw-r--r--main/uvncrepeater/uvncrepeater.pre-install5
-rw-r--r--main/v4l-utils/APKBUILD54
-rw-r--r--main/v4l-utils/qv4l2.desktop12
-rw-r--r--main/v4l-utils/qv4l2.svg31
-rw-r--r--main/v86d/APKBUILD27
-rw-r--r--main/v86d/modprobe.uvesafb10
-rw-r--r--main/vala/APKBUILD40
-rw-r--r--main/vala/version.patch17
-rw-r--r--main/valgrind/APKBUILD62
-rw-r--r--main/valgrind/valgrind-3.4.0-uclibc.patch12
-rw-r--r--main/vanessa_adt/APKBUILD39
-rw-r--r--main/vanessa_logger/APKBUILD39
-rw-r--r--main/vanessa_socket/APKBUILD39
-rw-r--r--main/vblade/APKBUILD34
-rw-r--r--main/videoproto/APKBUILD23
-rw-r--r--main/vim/APKBUILD272
-rw-r--r--main/vim/vimrc15
-rw-r--r--main/virtinst/APKBUILD33
-rw-r--r--main/vlc/APKBUILD190
-rw-r--r--main/vlc/uclibc-inhibit-spawn.patch32
-rw-r--r--main/vlc/uclibc-libcompat.patch81
-rw-r--r--main/vlc/uclibc3.patch36
-rw-r--r--main/vlc/vlc-1.1.7-disable-cache-gen.patch12
-rw-r--r--main/vlc/vlc-daemon.post-install3
-rw-r--r--main/vlc/vlc.confd11
-rwxr-xr-xmain/vlc/vlc.initd20
-rw-r--r--main/vlc/vlc.trigger4
-rw-r--r--main/vsftpd/APKBUILD49
-rw-r--r--main/vsftpd/vsftpd-enable-ssl.patch11
-rw-r--r--main/vsftpd/vsftpd.confd9
-rw-r--r--main/vsftpd/vsftpd.initd26
-rw-r--r--main/vte/APKBUILD42
-rw-r--r--main/wavpack/APKBUILD45
-rw-r--r--main/webkit/APKBUILD64
-rw-r--r--main/webkit/libpng-1.5.patch48
-rw-r--r--main/wget/APKBUILD28
-rw-r--r--main/wget/wget.post-deinstall3
-rw-r--r--main/wine/APKBUILD52
-rw-r--r--main/wine/dn_skipname.patch38
-rw-r--r--main/wine/uclibc-fmaxf-fminf.patch21
-rw-r--r--main/wireless-tools/APKBUILD33
-rw-r--r--main/wireless-tools/wireless-tools-29-asneeded.patch13
-rw-r--r--main/wireshark/APKBUILD81
-rw-r--r--main/wireshark/wireshark-1.1.2--as-needed.patch20
-rw-r--r--main/wireshark/wireshark.desktop10
-rw-r--r--main/wireshark/wireshark.pngbin0 -> 18535 bytes
-rw-r--r--main/wpa_supplicant/APKBUILD127
-rw-r--r--main/wpa_supplicant/wpa_supplicant.confd6
-rw-r--r--main/wpa_supplicant/wpa_supplicant.initd70
-rw-r--r--main/wv/APKBUILD34
-rw-r--r--main/wv/fix-soname.patch14
-rw-r--r--main/x264/APKBUILD28
-rw-r--r--main/xarchiver/APKBUILD33
-rw-r--r--main/xarchiver/xarchiver-0.5.2-stack-smash.patch20
-rw-r--r--main/xauth/APKBUILD24
-rw-r--r--main/xbacklight/APKBUILD24
-rw-r--r--main/xbitmaps/APKBUILD23
-rw-r--r--main/xcb-proto/APKBUILD25
-rw-r--r--main/xcb-util-image/APKBUILD46
-rw-r--r--main/xcb-util-keysyms/APKBUILD46
-rw-r--r--main/xcb-util-renderutil/APKBUILD46
-rw-r--r--main/xcb-util-wm/APKBUILD46
-rw-r--r--main/xcb-util/APKBUILD26
-rw-r--r--main/xchat/APKBUILD47
-rw-r--r--main/xchat/midori.patch15
-rw-r--r--main/xcmiscproto/APKBUILD23
-rw-r--r--main/xcmsdb/APKBUILD24
-rw-r--r--main/xdelta3/APKBUILD27
-rw-r--r--main/xdelta3/xdelta3-makefile.patch33
-rw-r--r--main/xdg-utils/APKBUILD43
-rw-r--r--main/xdg-utils/xfce.patch13
-rw-r--r--main/xdpyinfo/APKBUILD22
-rw-r--r--main/xdriinfo/APKBUILD22
-rw-r--r--main/xe-guest-utilities/APKBUILD62
-rw-r--r--main/xe-guest-utilities/fix_cflags.patch43
-rw-r--r--main/xe-guest-utilities/identify_alpine.patch43
-rw-r--r--main/xe-guest-utilities/no_bash_dependency.patch8
-rw-r--r--main/xe-guest-utilities/no_hard_links.patch11
-rw-r--r--main/xe-guest-utilities/xe-guest-utilities.initd50
-rw-r--r--main/xen/APKBUILD92
-rw-r--r--main/xen/blktap-write.patch24
-rw-r--r--main/xen/xen-blktap-uclibc.patch11
-rw-r--r--main/xen/xen-blktap2-uclibc.patch22
-rw-r--r--main/xen/xen-disable-firmware.patch10
-rw-r--r--main/xen/xen-dont-use-lib64.patch11
-rw-r--r--main/xen/xen-sed-is-broken-hack.patch11
-rw-r--r--main/xen/xend.initd38
-rw-r--r--main/xen/xendomains.initd63
-rw-r--r--main/xev/APKBUILD22
-rw-r--r--main/xextproto/APKBUILD24
-rw-r--r--main/xf86-input-evdev/APKBUILD27
-rw-r--r--main/xf86-input-keyboard/APKBUILD26
-rw-r--r--main/xf86-input-mouse/APKBUILD26
-rw-r--r--main/xf86-input-synaptics/APKBUILD26
-rw-r--r--main/xf86-input-vmmouse/APKBUILD26
-rw-r--r--main/xf86-video-apm/APKBUILD29
-rw-r--r--main/xf86-video-ark/APKBUILD28
-rw-r--r--main/xf86-video-ast/APKBUILD28
-rw-r--r--main/xf86-video-ati/APKBUILD34
-rw-r--r--main/xf86-video-chips/APKBUILD28
-rw-r--r--main/xf86-video-cirrus/APKBUILD39
-rw-r--r--main/xf86-video-cirrus/qemu.patch25
-rw-r--r--main/xf86-video-dummy/APKBUILD28
-rw-r--r--main/xf86-video-fbdev/APKBUILD28
-rw-r--r--main/xf86-video-geode/APKBUILD28
-rw-r--r--main/xf86-video-glint/APKBUILD29
-rw-r--r--main/xf86-video-i128/APKBUILD28
-rw-r--r--main/xf86-video-i740/APKBUILD28
-rw-r--r--main/xf86-video-intel/APKBUILD32
-rw-r--r--main/xf86-video-mach64/APKBUILD30
-rw-r--r--main/xf86-video-newport/APKBUILD28
-rw-r--r--main/xf86-video-nouveau/APKBUILD39
-rw-r--r--main/xf86-video-nv/APKBUILD28
-rw-r--r--main/xf86-video-openchrome/APKBUILD50
-rw-r--r--main/xf86-video-openchrome/openchrome-0.2.904-fix_tvout_flickering.patch35
-rw-r--r--main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch4427
-rw-r--r--main/xf86-video-openchrome/openchrome.xinf39
-rw-r--r--main/xf86-video-r128/APKBUILD32
-rw-r--r--main/xf86-video-radeonhd/APKBUILD28
-rw-r--r--main/xf86-video-rendition/APKBUILD28
-rw-r--r--main/xf86-video-s3/APKBUILD28
-rw-r--r--main/xf86-video-s3virge/APKBUILD28
-rw-r--r--main/xf86-video-savage/APKBUILD29
-rw-r--r--main/xf86-video-siliconmotion/APKBUILD28
-rw-r--r--main/xf86-video-sis/APKBUILD34
-rw-r--r--main/xf86-video-sis/fix-bios-read-on-650-760.patch23
-rw-r--r--main/xf86-video-sunleo/APKBUILD28
-rw-r--r--main/xf86-video-tdfx/APKBUILD29
-rw-r--r--main/xf86-video-tseng/APKBUILD28
-rw-r--r--main/xf86-video-v4l/APKBUILD28
-rw-r--r--main/xf86-video-vesa/APKBUILD28
-rw-r--r--main/xf86-video-vmware/APKBUILD36
-rw-r--r--main/xf86-video-vmware/abi2.patch38
-rw-r--r--main/xf86bigfontproto/APKBUILD19
-rw-r--r--main/xf86dgaproto/APKBUILD20
-rw-r--r--main/xf86driproto/APKBUILD23
-rw-r--r--main/xf86miscproto/APKBUILD20
-rw-r--r--main/xf86vidmodeproto/APKBUILD23
-rw-r--r--main/xfce-utils/APKBUILD30
-rw-r--r--main/xfce4-appfinder/APKBUILD28
-rw-r--r--main/xfce4-battery-plugin/APKBUILD39
-rw-r--r--main/xfce4-battery-plugin/sysfs-temp.patch66
-rw-r--r--main/xfce4-cpufreq-plugin/APKBUILD30
-rw-r--r--main/xfce4-dev-tools/APKBUILD28
-rw-r--r--main/xfce4-mixer/APKBUILD30
-rw-r--r--main/xfce4-notes-plugin/APKBUILD38
-rw-r--r--main/xfce4-notifyd/APKBUILD31
-rw-r--r--main/xfce4-panel/APKBUILD43
-rw-r--r--main/xfce4-power-manager/APKBUILD45
-rw-r--r--main/xfce4-screenshooter/APKBUILD32
l---------main/xfce4-screenshooter/xfce4-screenshooter.post-deinstall1
-rw-r--r--main/xfce4-screenshooter/xfce4-screenshooter.post-install4
l---------main/xfce4-screenshooter/xfce4-screenshooter.post-upgrade1
-rw-r--r--main/xfce4-session/APKBUILD49
-rw-r--r--main/xfce4-session/busybox-shutdown.patch13
l---------main/xfce4-session/xfce4-session.post-deinstall1
-rw-r--r--main/xfce4-session/xfce4-session.post-install4
-rw-r--r--main/xfce4-settings/APKBUILD47
-rw-r--r--main/xfce4-settings/xfce4-settings-4.7.1-libxklavier.patch27
-rw-r--r--main/xfce4-taskmanager/APKBUILD29
-rw-r--r--main/xfce4-vala/APKBUILD42
-rw-r--r--main/xfce4-wavelan-plugin/APKBUILD30
-rw-r--r--main/xfce4-wavelan-plugin/tooltip.diff19
-rw-r--r--main/xfce4-xkb-plugin/APKBUILD38
-rw-r--r--main/xfce4/APKBUILD42
-rw-r--r--main/xfconf/APKBUILD33
-rw-r--r--main/xfdesktop/APKBUILD41
-rw-r--r--main/xfsprogs/APKBUILD42
-rw-r--r--main/xfwm4-themes/APKBUILD28
-rw-r--r--main/xfwm4/APKBUILD31
l---------main/xfwm4/xfwm4.post-deinstall1
-rw-r--r--main/xfwm4/xfwm4.post-install4
l---------main/xfwm4/xfwm4.post-upgrade1
-rw-r--r--main/xgamma/APKBUILD24
-rw-r--r--main/xhost/APKBUILD24
-rw-r--r--main/xineramaproto/APKBUILD23
-rw-r--r--main/xinit/06_move_serverauthfile_into_tmp.patch20
-rw-r--r--main/xinit/APKBUILD48
-rw-r--r--main/xinit/xinitrc49
-rw-r--r--main/xinit/xserverrc2
-rw-r--r--main/xinit/xsession10
-rw-r--r--main/xkbcomp/APKBUILD29
-rw-r--r--main/xkeyboard-config/APKBUILD30
-rw-r--r--main/xmodmap/APKBUILD24
-rw-r--r--main/xorg-server/APKBUILD157
-rw-r--r--main/xorg-server/bg-none-revert.patch58
-rw-r--r--main/xorg-server/xorg-redhat-die-ugly-pattern-die-die-die.patch16
-rw-r--r--main/xorg-server/xserver-1.10-pointer-barriers.patch1054
-rw-r--r--main/xproto/APKBUILD29
-rw-r--r--main/xrandr/APKBUILD27
-rw-r--r--main/xrandr/xrandr-1.3.0-clone-nameclash.patch29
-rw-r--r--main/xrdb/APKBUILD24
-rw-r--r--main/xrefresh/APKBUILD24
-rw-r--r--main/xscreensaver/APKBUILD40
-rw-r--r--main/xset/APKBUILD24
-rw-r--r--main/xsetmode/APKBUILD24
-rw-r--r--main/xsetroot/APKBUILD24
-rw-r--r--main/xtables-addons-grsec/APKBUILD47
-rw-r--r--main/xtables-addons/APKBUILD30
-rw-r--r--main/xtrans/APKBUILD24
-rw-r--r--main/xulrunner/APKBUILD111
-rw-r--r--main/xulrunner/fix-xulrunner-launcher.patch23
-rw-r--r--main/xulrunner/gecko-c99math.patch11
-rw-r--r--main/xulrunner/mozconfig37
-rw-r--r--main/xulrunner/mozilla-pkgconfig.patch60
-rw-r--r--main/xulrunner/mozjs-c99math.patch33
-rw-r--r--main/xulrunner/xulrunner-jemalloc-aslr.patch54
-rw-r--r--main/xulrunner/xulrunner-mozalloc.patch11
-rw-r--r--main/xvidcore/APKBUILD29
-rw-r--r--main/xvinfo/APKBUILD22
-rw-r--r--main/xwininfo/APKBUILD35
-rw-r--r--main/xz/APKBUILD38
-rw-r--r--main/yaboot/APKBUILD38
-rw-r--r--main/yasm/APKBUILD26
-rw-r--r--main/zabbix/APKBUILD163
-rw-r--r--main/zabbix/zabbix-agent.pre-install6
-rw-r--r--main/zabbix/zabbix-agentd.initd22
-rw-r--r--main/zabbix/zabbix-dn_skipname.patch44
-rw-r--r--main/zabbix/zabbix-getloadavg.patch33
-rw-r--r--main/zabbix/zabbix-proxy.initd21
-rw-r--r--main/zabbix/zabbix-server.initd21
-rw-r--r--main/zabbix/zabbix.pre-install5
-rw-r--r--main/zabbix/zabbix_agentd.conf228
-rw-r--r--main/zabbix/zabbix_proxy.conf175
-rw-r--r--main/zabbix/zabbix_server.conf155
-rw-r--r--main/zabbix/zabbix_trapper.conf44
-rw-r--r--main/zenity/APKBUILD47
-rw-r--r--main/zip/10-zip-3.0-build.patch36
-rw-r--r--main/zip/20-zip-3.0-exec-stack.patch22
-rw-r--r--main/zip/30-zip-3.0-pic.patch15
-rw-r--r--main/zip/APKBUILD31
-rw-r--r--main/zlib/APKBUILD43
-rw-r--r--main/zlib/zlib-1.2.5-lfs-decls.patch13
-rw-r--r--main/znc/APKBUILD109
-rw-r--r--main/znc/libiconv.patch16
-rw-r--r--main/zonenotify/APKBUILD18
-rw-r--r--main/zsh/APKBUILD45
-rw-r--r--main/zsh/zsh.post-install3
-rw-r--r--main/zsh/zsh.post-upgrade3
-rw-r--r--main/zsh/zsh.pre-deinstall3
-rw-r--r--main/zsnes/APKBUILD55
-rw-r--r--main/zsnes/zsnes-1.51-CC-quotes.patch20
-rw-r--r--main/zsnes/zsnes-1.51-depbuild.patch34
-rw-r--r--main/zsnes/zsnes-libpng15.patch10
-rw-r--r--main/zsnes/zsnes.desktop9
-rw-r--r--main/zsnes/zsnes.patch67
-rw-r--r--main/zsnes/zsnes_icon.pngbin0 -> 7301 bytes
2495 files changed, 421675 insertions, 0 deletions
diff --git a/main/a2ps/APKBUILD b/main/a2ps/APKBUILD
new file mode 100644
index 0000000000..2cf3a759bb
--- /dev/null
+++ b/main/a2ps/APKBUILD
@@ -0,0 +1,53 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=a2ps
+pkgver=4.14
+pkgrel=3
+pkgdesc="a2ps is an Any to PostScript filter"
+url="http://www.gnu.org/software/a2ps/"
+arch="all"
+license="GPL3"
+depends="ghostscript imagemagick perl"
+makedepends="gperf autoconf automake libtool"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz
+ $pkgname-4.13c-fnmatch-replacement.patch
+ $pkgname-4.13c-emacs.patch
+ $pkgname-4.13-manpage-chmod.patch
+ $pkgname-$pkgver-check-mempcpy.patch
+ $pkgname-$pkgver-fix-stpcpy-proto.patch
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Apllying $i"
+ patch -p1 -i $i || return 1
+ done
+ sed -i -e 's/__mempcpy/mempcpy/g' lib/strftime.c src/regex.c \
+ || return 1
+ libtoolize --force --copy || return 1
+ autoreconf -I m4 || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/a2ps \
+ --includedir=/usr/include \
+ --disable-nls || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ sed -i "s:^countdictstack: \0:" "$pkgdir"/usr/bin/psset || return 1
+}
+md5sums="781ac3d9b213fa3e1ed0d79f986dc8c7 a2ps-4.14.tar.gz
+93011b58e9f20a7fafa31287a51884a4 a2ps-4.13c-fnmatch-replacement.patch
+2e493d0bc00d71eb3e8a9b6febc52b69 a2ps-4.13c-emacs.patch
+09cc5ed4d3d8ff1b2103e519191e8286 a2ps-4.13-manpage-chmod.patch
+42aa39b74f6da8cf6e94185c4fc3e601 a2ps-4.14-check-mempcpy.patch
+4b4fbc19a6b79fa64df7e26945fcdcf9 a2ps-4.14-fix-stpcpy-proto.patch"
diff --git a/main/a2ps/a2ps-4.13-manpage-chmod.patch b/main/a2ps/a2ps-4.13-manpage-chmod.patch
new file mode 100644
index 0000000000..e0c61124e9
--- /dev/null
+++ b/main/a2ps/a2ps-4.13-manpage-chmod.patch
@@ -0,0 +1,12 @@
+diff -ur a2ps-4.13.orig/man/Makefile.maint a2ps-4.13/man/Makefile.maint
+--- a2ps-4.13.orig/man/Makefile.maint 2002-03-04 20:46:26.000000000 +0200
++++ a2ps-4.13/man/Makefile.maint 2007-02-19 21:50:29.000000000 +0200
+@@ -20,7 +20,7 @@
+ --include=$(basename $@).x \
+ --include=common.x \
+ $(executable) > $@-t || exit 1; \
+- chmod -w $@-t || exit 1; \
++ chmod a-w $@-t || exit 1; \
+ rm -f $@ || exit 1; \
+ mv $@-t $@ || exit 1; \
+ else \
diff --git a/main/a2ps/a2ps-4.13c-emacs.patch b/main/a2ps/a2ps-4.13c-emacs.patch
new file mode 100644
index 0000000000..f1cd5d9ebd
--- /dev/null
+++ b/main/a2ps/a2ps-4.13c-emacs.patch
@@ -0,0 +1,10 @@
+--- a2ps-4.13/contrib/emacs/a2ps-print.el.orig 2005-12-05 08:03:48.000000000 +0100
++++ a2ps-4.13/contrib/emacs/a2ps-print.el 2005-12-06 16:38:14.000000000 +0100
+@@ -93,6 +93,7 @@
+ (concat "--center-title=" name)
+ (concat "--footer=" (concat name " Emacs buffer"))
+ (concat "--pretty-print=" filetype)
++ (concat "-d")
+ ;Uncommenting the following gives a print preview (only):
+ ; (concat "--output=/tmp/foo.ps")
+ )
diff --git a/main/a2ps/a2ps-4.13c-fnmatch-replacement.patch b/main/a2ps/a2ps-4.13c-fnmatch-replacement.patch
new file mode 100644
index 0000000000..c49ab78c93
--- /dev/null
+++ b/main/a2ps/a2ps-4.13c-fnmatch-replacement.patch
@@ -0,0 +1,43 @@
+diff -Naurp a2ps-4.13.orig/lib/fnmatch.c a2ps-4.13/lib/fnmatch.c
+--- a2ps-4.13.orig/lib/fnmatch.c 2002-03-04 12:46:25 -0600
++++ a2ps-4.13/lib/fnmatch.c 2006-05-27 11:41:15 -0500
+@@ -27,18 +27,6 @@
+ #include <fnmatch.h>
+ #include <ctype.h>
+
+-
+-/* Comment out all this code if we are using the GNU C Library, and are not
+- actually compiling the library itself. This code is part of the GNU C
+- Library, but also included in many other GNU distributions. Compiling
+- and linking in this code is a waste when using the GNU C library
+- (especially if it is a shared library). Rather than having every GNU
+- program understand `configure --with-gnu-libc' and omit the object files,
+- it is simpler to just do this in the source for each such file. */
+-
+-#if defined _LIBC || !defined __GNU_LIBRARY__
+-
+-
+ # if defined STDC_HEADERS || !defined isascii
+ # define ISASCII(c) 1
+ # else
+@@ -52,10 +40,13 @@
+ extern int errno;
+ # endif
+
++/* fnmatch replacement taken from the GNU C Library for systems that
++ provide a broken implementation. */
++
+ /* Match STRING against the filename pattern PATTERN, returning zero if
+ it matches, nonzero if not. */
+ int
+-fnmatch (const char *pattern, const char *string, int flags)
++rpl_fnmatch (const char *pattern, const char *string, int flags)
+ {
+ register const char *p = pattern, *n = string;
+ register char c;
+@@ -233,5 +224,3 @@ fnmatch (const char *pattern, const char
+
+ # undef FOLD
+ }
+-
+-#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/main/a2ps/a2ps-4.14-check-mempcpy.patch b/main/a2ps/a2ps-4.14-check-mempcpy.patch
new file mode 100644
index 0000000000..7b820cead0
--- /dev/null
+++ b/main/a2ps/a2ps-4.14-check-mempcpy.patch
@@ -0,0 +1,12 @@
+--- a2ps-4.14-orig/configure.in 2008-04-16 08:36:03.000000000 +0200
++++ a2ps-4.14/configure.in 2008-04-16 08:36:29.000000000 +0200
+@@ -137,7 +137,8 @@
+ ad_REPLACE_FUNC_STRCASECMP
+ ad_REPLACE_FUNC_STRNCASECMP
+ ad_REPLACE_FUNC_RENAME
+-AC_CHECK_FUNCS(uname strchr strerror strerror_r getcwd bcopy bzero tempnam strsignal psignal setlocale)
++AC_CHECK_FUNCS(uname strchr strerror strerror_r getcwd bcopy bzero \
++ tempnam strsignal psignal setlocale mempcpy)
+ ad_FUNC_SYSTEMPAPERNAME
+ ad_FUNC_ATEXIT
+ ad_FUNC_STRFTIME
diff --git a/main/a2ps/a2ps-4.14-fix-stpcpy-proto.patch b/main/a2ps/a2ps-4.14-fix-stpcpy-proto.patch
new file mode 100644
index 0000000000..c5bdfc57cd
--- /dev/null
+++ b/main/a2ps/a2ps-4.14-fix-stpcpy-proto.patch
@@ -0,0 +1,17 @@
+=== modified file 'lib/xstrrpl.c'
+--- a/lib/xstrrpl.c 2008-04-14 18:04:50 +0000
++++ b/lib/xstrrpl.c 2008-04-14 18:20:20 +0000
+@@ -20,12 +20,10 @@
+
+ #include "system.h"
+ #include <assert.h>
+ #include "xstrrpl.h"
+
+-extern char * stpcpy();
+-
+ /* Perform subsitutions in string. Result is malloc'd
+ E.g., result = xstrrrpl ("1234", subst) gives result = "112333"
+ where subst = { {"1", "11"}, {"3", "333"}, { "4", ""}}
+ */
+ char *
+
diff --git a/main/a52dec/APKBUILD b/main/a52dec/APKBUILD
new file mode 100644
index 0000000000..8fbb0b14a6
--- /dev/null
+++ b/main/a52dec/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=a52dec
+pkgver=0.7.4
+pkgrel=4
+pkgdesc="liba52 is a free library for decoding ATSC A/52 streams."
+url="http://liba52.sourceforge.net/"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="autoconf automake libtool"
+source="http://liba52.sourceforge.net/files/$pkgname-$pkgver.tar.gz
+ $pkgname-$pkgver-build.patch"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -Np1 -i "$srcdir"/a52dec-0.7.4-build.patch || return 1
+ ./bootstrap || return 1
+ ./configure --prefix=/usr \
+ --enable-shared \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -m644 liba52/a52_internal.h "$pkgdir"/usr/include/a52dec/ || return 1
+}
+md5sums="caa9f5bc44232dc8aeea773fea56be80 a52dec-0.7.4.tar.gz
+fa16f224a7dceb7613824380abef0052 a52dec-0.7.4-build.patch"
diff --git a/main/a52dec/a52dec-0.7.4-build.patch b/main/a52dec/a52dec-0.7.4-build.patch
new file mode 100644
index 0000000000..f3a29f303c
--- /dev/null
+++ b/main/a52dec/a52dec-0.7.4-build.patch
@@ -0,0 +1,27 @@
+diff -Naur a52dec-0.7.4.orig/liba52/Makefile.am a52dec-0.7.4/liba52/Makefile.am
+--- a52dec-0.7.4.orig/liba52/Makefile.am 2002-01-27 20:36:48.000000000 -0800
++++ a52dec-0.7.4/liba52/Makefile.am 2004-11-05 01:10:21.317401872 -0800
+@@ -1,4 +1,3 @@
+-CFLAGS = @CFLAGS@ @LIBA52_CFLAGS@
+
+ lib_LTLIBRARIES = liba52.la
+
+diff -Naur a52dec-0.7.4.orig/liba52/configure.incl a52dec-0.7.4/liba52/configure.incl
+--- a52dec-0.7.4.orig/liba52/configure.incl 2002-01-27 20:36:48.000000000 -0800
++++ a52dec-0.7.4/liba52/configure.incl 2004-11-05 01:11:38.172672216 -0800
+@@ -2,7 +2,6 @@
+ AC_SUBST([LIBA52_LIBS])
+
+ dnl avoid -fPIC when possible
+-LIBA52_CFLAGS="$LIBA52_CFLAGS -prefer-non-pic"
+
+ AC_ARG_ENABLE([double],
+ [ --enable-double use double-precision samples])
+diff -Naur a52dec-0.7.4.orig/src/Makefile.am a52dec-0.7.4/src/Makefile.am
+--- a52dec-0.7.4.orig/src/Makefile.am 2002-06-22 18:51:57.000000000 -0700
++++ a52dec-0.7.4/src/Makefile.am 2004-11-05 01:10:21.320401375 -0800
+@@ -1,4 +1,3 @@
+-CFLAGS = @A52DEC_CFLAGS@
+
+ bin_PROGRAMS = a52dec extract_a52
+ a52dec_SOURCES = a52dec.c getopt.c gettimeofday.c
diff --git a/main/abiword/APKBUILD b/main/abiword/APKBUILD
new file mode 100644
index 0000000000..7385b64e7a
--- /dev/null
+++ b/main/abiword/APKBUILD
@@ -0,0 +1,78 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=abiword
+pkgver=2.8.6
+pkgrel=5
+pkgdesc="A fully-featured word processor"
+url="http://www.abisource.com"
+arch="all"
+license="GPL"
+makedepends="pkgconfig libglade-dev libgsf-dev enchant-dev fribidi-dev wv-dev
+ popt-dev jpeg-dev librsvg-dev bzip2-dev goffice-dev"
+
+# openxml plugin
+makedepends="$makedepends boost-dev"
+
+# collab plugin
+makedepends="$makedepends gnutls-dev libsoup-dev dbus-glib-dev"
+
+
+subpackages="$pkgname-dev $pkgname-doc $pkgname-plugins"
+
+_plugins="applix babelfish bmp clarisworks collab docbook eml freetranslation
+ garble gdict gimp google hancom hrtext iscii kword loadbindings mht
+ mif mswrite openwriter openxml opml paint passepartout pdb pdf
+ presentation s5 sdw t602 urldict wikipedia wml xslfo"
+
+for _i in $_plugins; do
+ subpackages="$subpackages $pkgname-plugin-$_i:$_i"
+done
+
+source="http://www.abisource.com/downloads/$pkgname/$pkgver/source/$pkgname-$pkgver.tar.gz
+ abiword-png15.patch"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 < "$srcdir"/abiword-png15.patch
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-shared \
+ --disable-static \
+ --enable-plugins \
+ || return 1
+ make || return 1
+}
+
+# ="opendocument goffice latex" \
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/abiword*/plugins/*.la \
+ "$pkgdir"/usr/lib/*.la || return 1
+}
+
+_do_plugin() {
+ local plugin="$1"
+ pkgdesc="Abiword $1 plugin"
+ local dir="usr/lib/abiword-${pkgver%.*}/plugins"
+ mkdir -p "$subpkgdir"/$dir
+ mv "$pkgdir"/$dir/$plugin.so "$subpkgdir"/$dir/
+}
+
+for _i in $_plugins; do
+ eval "$_i() { _do_plugin $_i; }"
+done
+
+plugins() {
+ pkgdesc="Abiword plugins, all of them"
+ depends=
+ for _i in $_plugins; do
+ depends="$depends $pkgname-plugin-$_i"
+ done
+ mkdir -p "$subpkgdir"
+}
+
+md5sums="f883b0a7f26229a9c66fd6a1a94381aa abiword-2.8.6.tar.gz
+1d0bb11ed10b431ab312173de81d12c4 abiword-png15.patch"
diff --git a/main/abiword/abiword-png15.patch b/main/abiword/abiword-png15.patch
new file mode 100644
index 0000000000..b17bb85bff
--- /dev/null
+++ b/main/abiword/abiword-png15.patch
@@ -0,0 +1,81 @@
+diff -Naur abiword-vanilla//src/af/util/xp/ut_png.cpp abiword-2.8.6//src/af/util/xp/ut_png.cpp
+--- abiword-vanilla//src/af/util/xp/ut_png.cpp 2008-02-24 04:33:07.000000000 +0100
++++ abiword-2.8.6//src/af/util/xp/ut_png.cpp 2011-02-24 11:53:18.954524499 +0100
+@@ -71,7 +71,7 @@
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in the png_create_read_struct() earlier.
+ */
+- if (setjmp(png_ptr->jmpbuf))
++ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ /* Free all of the memory associated with the png_ptr and info_ptr */
+ png_destroy_read_struct(&png_ptr, &info_ptr, static_cast<png_infopp>(NULL));
+diff -Naur abiword-vanilla//src/wp/impexp/gtk/ie_impGraphic_GdkPixbuf.cpp abiword-2.8.6//src/wp/impexp/gtk/ie_impGraphic_GdkPixbuf.cpp
+--- abiword-vanilla//src/wp/impexp/gtk/ie_impGraphic_GdkPixbuf.cpp 2009-07-01 06:02:04.000000000 +0200
++++ abiword-2.8.6//src/wp/impexp/gtk/ie_impGraphic_GdkPixbuf.cpp 2011-02-24 11:53:19.039523946 +0100
+@@ -185,7 +185,7 @@
+ /** needed for the stejmp context */
+ UT_Error IE_ImpGraphic_GdkPixbuf::_png_write(GdkPixbuf * pixbuf)
+ {
+- if (setjmp(m_pPNG->jmpbuf))
++ if (setjmp(png_jmpbuf(m_pPNG)))
+ {
+ DELETEP(m_pPngBB);
+ png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
+@@ -446,7 +446,7 @@
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in the png_create_read_struct() earlier.
+ */
+- if (setjmp(m_pPNG->jmpbuf))
++ if (setjmp(png_jmpbuf(m_pPNG)))
+ {
+ /* Free all of the memory associated with the png_ptr and info_ptr */
+ png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
+--- abiword-vanilla/plugins/garble/xp/abiword-garble-png.cpp
++++ abiword-2.8.6/plugins/garble/xp/abiword-garble-png.cpp
+@@ -79,7 +79,7 @@
+ png_set_strip_alpha( png_ptr );
+ png_set_interlace_handling( png_ptr );
+ png_set_bgr( png_ptr );
+- rowbytes = info_ptr->rowbytes;
++ rowbytes = png_get_rowbytes( png_ptr, info_ptr );
+ png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
+ }
+
+--- abiword-vanilla/plugins/bmp/xp/ie_impGraphic_BMP.cpp
++++ abiword-2.8.6/plugins/bmp/xp/ie_impGraphic_BMP.cpp
+@@ -191,7 +191,6 @@
+
+ /* Clean Up Memory Used */
+
+- FREEP(m_pPNGInfo->palette);
+ DELETEP(pBB);
+ png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
+
+@@ -313,7 +312,7 @@
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in the png_create_read_struct() earlier.
+ */
+- if (setjmp(m_pPNG->jmpbuf))
++ if (setjmp(png_jmpbuf(m_pPNG)))
+ {
+ /* Free all of the memory associated with the png_ptr and info_ptr */
+ png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
+@@ -332,7 +331,7 @@
+ UT_Error IE_ImpGraphic_BMP::Convert_BMP_Pallet(UT_ByteBuf* pBB)
+ {
+ /* Reset error handling for libpng */
+- if (setjmp(m_pPNG->jmpbuf))
++ if (setjmp(png_jmpbuf(m_pPNG)))
+ {
+ png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
+ return UT_ERROR;
+@@ -372,7 +371,7 @@
+ UT_Error IE_ImpGraphic_BMP::Convert_BMP(UT_ByteBuf* pBB)
+ {
+ /* Reset error handling for libpng */
+- if (setjmp(m_pPNG->jmpbuf))
++ if (setjmp(png_jmpbuf(m_pPNG)))
+ {
+ png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
+ return UT_ERROR;
diff --git a/main/abuild/0001-abuild-reset-triggers-for-subpackages.patch b/main/abuild/0001-abuild-reset-triggers-for-subpackages.patch
new file mode 100644
index 0000000000..35b18837ca
--- /dev/null
+++ b/main/abuild/0001-abuild-reset-triggers-for-subpackages.patch
@@ -0,0 +1,25 @@
+From 81b439cec2e3459da4afeb1e3cdbbc6f90cda5dc Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Mon, 18 Apr 2011 08:34:56 +0000
+Subject: [PATCH] abuild: reset triggers for subpackages
+
+only main package has the trigger
+---
+ abuild.in | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/abuild.in b/abuild.in
+index 99d9cd0..ed0373c 100755
+--- a/abuild.in
++++ b/abuild.in
+@@ -1428,6 +1428,7 @@ if [ -n "$subpkgname" ]; then
+ origsubpackages="$subpackages"
+ subpackages=
+ install=
++ triggers=
+ fi
+ pkgdir="$pkgbasedir/$pkgname"
+ controldir="$pkgbasedir"/.control.${subpkgname:-$pkgname}
+--
+1.7.4.4
+
diff --git a/main/abuild/APKBUILD b/main/abuild/APKBUILD
new file mode 100644
index 0000000000..91df1371fc
--- /dev/null
+++ b/main/abuild/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgdesc="Script to build Alpine Packages"
+pkgname=abuild
+pkgver=2.9.2
+pkgrel=2
+url=http://git.alpinelinux.org/cgit/abuild/
+source="http://git.alpinelinux.org/cgit/abuild.git/snapshot/abuild-$pkgver.tar.bz2
+ 0001-abuild-reset-triggers-for-subpackages.patch
+ "
+depends="fakeroot file sudo pax-utils openssl apk-tools>=2.0.7-r1 uclibc-utils abuildhelper"
+makedepends="openssl-dev pkgconfig"
+install="$pkgname.pre-install $pkgname.pre-upgrade"
+pkggroups="abuild"
+arch="all"
+license=GPL-2
+
+prepare() {
+ cd "$srcdir/$pkgname-$pkgver"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make install DESTDIR="$pkgdir"
+ install -m 644 abuild.conf "$pkgdir"/etc/abuild.conf
+ install -d -m 775 -g abuild "$pkgdir"/var/cache/distfiles
+}
+
+md5sums="49817d627e9e93455f74b2fa5bb3d66d abuild-2.9.2.tar.bz2
+6e8581db0e79e1f4364b7c846f2d6a17 0001-abuild-reset-triggers-for-subpackages.patch"
diff --git a/main/abuild/abuild.pre-install b/main/abuild/abuild.pre-install
new file mode 100644
index 0000000000..fb2cf9e31d
--- /dev/null
+++ b/main/abuild/abuild.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if ! getent group abuild >/dev/null; then
+ addgroup -S abuild
+fi
+exit 0
diff --git a/main/abuild/abuild.pre-upgrade b/main/abuild/abuild.pre-upgrade
new file mode 120000
index 0000000000..99e4a2144e
--- /dev/null
+++ b/main/abuild/abuild.pre-upgrade
@@ -0,0 +1 @@
+abuild.pre-install \ No newline at end of file
diff --git a/main/abuildhelper/APKBUILD b/main/abuildhelper/APKBUILD
new file mode 100644
index 0000000000..dddd33e008
--- /dev/null
+++ b/main/abuildhelper/APKBUILD
@@ -0,0 +1,25 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer:
+pkgname=abuildhelper
+pkgver=0.0.1
+pkgrel=1
+pkgdesc="aspect-oriented build system for building APK packages inside abuild framework"
+url="http://nenolod.net/projects/abuildhelper"
+arch="noarch"
+license="ISC"
+depends="abuild"
+depends_dev=
+makedepends=
+install=""
+subpackages=
+source="http://git.alpinelinux.org/cgit/nenolod/abuildhelper.git/snapshot/abuildhelper-$pkgver.tar.bz2"
+install_if="abuild"
+
+_builddir="$srcdir"/abuildhelper-$pkgver
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/share
+ cp -R "$_builddir" "$pkgdir"/usr/share/abuildhelper
+}
+md5sums="136616a15c5e63360a3c871d8de773c2 abuildhelper-0.0.1.tar.bz2"
diff --git a/main/acct/APKBUILD b/main/acct/APKBUILD
new file mode 100644
index 0000000000..c1f1a80fc3
--- /dev/null
+++ b/main/acct/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=acct
+pkgver=6.5.5
+pkgrel=0
+pkgdesc="The GNU Accounting Utilities"
+url="http://www.gnu.org/software/acct/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/gnu/acct/${pkgname}-${pkgver}.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ # seems like this makefile does not respect DESTDIR
+ ./configure --prefix=/usr \
+ --mandir="$pkgdir"/usr/share/man \
+ --infodir="$pkgdir"/usr/share/info \
+ --enable-linux-multiformat
+
+ make LDADD="-lm lib/libgnu.la" || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make prefix="$pkgdir/usr" install
+}
+
+md5sums="554a9e9c6aa3482df07e80853eac0350 acct-6.5.5.tar.gz"
diff --git a/main/acf-alpine-baselayout/APKBUILD b/main/acf-alpine-baselayout/APKBUILD
new file mode 100644
index 0000000000..cc71a24ace
--- /dev/null
+++ b/main/acf-alpine-baselayout/APKBUILD
@@ -0,0 +1,18 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-alpine-baselayout
+pkgver=0.8.2
+pkgrel=0
+pkgdesc="A web-based system administration interface for alpine-baselayout"
+url="http://git.alpinelinux.org/cgit/acf-alpine-baselayout"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-json4 lua-posix"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="3c621d2dfbafc11224139083c8be2bdc acf-alpine-baselayout-0.8.2.tar.bz2"
diff --git a/main/acf-alpine-conf/APKBUILD b/main/acf-alpine-conf/APKBUILD
new file mode 100644
index 0000000000..4184857d13
--- /dev/null
+++ b/main/acf-alpine-conf/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-alpine-conf
+pkgver=0.4.1
+pkgrel=0
+pkgdesc="A web-based system administration interface for alpine-conf"
+url="http://git.alpinelinux.org/cgit/acf-alpine-conf"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-posix openssl"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="4907175a7925a57c3f25c7647d3791fd acf-alpine-conf-0.4.1.tar.bz2"
diff --git a/main/acf-amavisd-new/APKBUILD b/main/acf-amavisd-new/APKBUILD
new file mode 100644
index 0000000000..25c3b33d22
--- /dev/null
+++ b/main/acf-amavisd-new/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-amavisd-new
+pkgver=0.1.0
+pkgrel=2
+pkgdesc="ACF module for amavis"
+url="http://git.alpinelinux.org/cgit/acf-amavisd-new"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua amavisd-new"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="54fbe6fc8c0774b470dab1f0bb73c407 acf-amavisd-new-0.1.0.tar.bz2"
diff --git a/main/acf-apk-tools/APKBUILD b/main/acf-apk-tools/APKBUILD
new file mode 100644
index 0000000000..c2c18e4d96
--- /dev/null
+++ b/main/acf-apk-tools/APKBUILD
@@ -0,0 +1,18 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-apk-tools
+pkgver=0.5.0
+pkgrel=3
+pkgdesc="ACF module for apk"
+url="http://git.alpinelinux.org/cgit/acf-apk-tools"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-posix apk-tools"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="fbc4d309af866fe0debd59dd7b58bc3f acf-apk-tools-0.5.0.tar.bz2"
diff --git a/main/acf-asterisk/APKBUILD b/main/acf-asterisk/APKBUILD
new file mode 100644
index 0000000000..f36c20e7c0
--- /dev/null
+++ b/main/acf-asterisk/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-asterisk
+pkgver=0.3.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for asterisk"
+url="http://git.alpinelinux.org/cgit/acf-asterisk"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua asterisk"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="961ce238956562b60d264fdb45355e9f acf-asterisk-0.3.0.tar.bz2"
diff --git a/main/acf-chrony/APKBUILD b/main/acf-chrony/APKBUILD
new file mode 100644
index 0000000000..f152c60a3b
--- /dev/null
+++ b/main/acf-chrony/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-chrony
+pkgver=0.3.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for chrony"
+url="http://git.alpinelinux.org/cgit/acf-chrony"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-posix chrony"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="4a275cad10ff6dbd860fcae7b486223b acf-chrony-0.3.0.tar.bz2"
diff --git a/main/acf-clamav/APKBUILD b/main/acf-clamav/APKBUILD
new file mode 100644
index 0000000000..9844a531ee
--- /dev/null
+++ b/main/acf-clamav/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-clamav
+pkgver=0.3.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for clamav"
+url="http://git.alpinelinux.org/cgit/acf-clamav"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua clamav"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="f0b1ccab057f4731af7854655491547d acf-clamav-0.3.0.tar.bz2"
diff --git a/main/acf-clamsmtp/APKBUILD b/main/acf-clamsmtp/APKBUILD
new file mode 100644
index 0000000000..dd8db1fa08
--- /dev/null
+++ b/main/acf-clamsmtp/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-clamsmtp
+pkgver=0.2.1
+pkgrel=2
+pkgdesc="A web-based system administration interface for clamsmtp"
+url="http://git.alpinelinux.org/cgit/acf-clamsmtp"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua clamsmtp"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="be2bbb86832987e1f78b21c501eddc08 acf-clamsmtp-0.2.1.tar.bz2"
diff --git a/main/acf-core/APKBUILD b/main/acf-core/APKBUILD
new file mode 100644
index 0000000000..2e914de215
--- /dev/null
+++ b/main/acf-core/APKBUILD
@@ -0,0 +1,18 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-core
+pkgver=0.13.2
+pkgrel=0
+pkgdesc="A web-based system administration interface framework"
+url="http://git.alpinelinux.org/cgit/acf-core"
+arch="noarch"
+license="GPL-2"
+install="$pkgname.post-upgrade"
+depends="acf-jquery acf-lib acf-skins haserl lua lua-posix lua-md5"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="120b344ff922d0cd933b2cc9d0b2c656 acf-core-0.13.2.tar.bz2"
diff --git a/main/acf-core/acf-core.post-upgrade b/main/acf-core/acf-core.post-upgrade
new file mode 100644
index 0000000000..1a54c0451e
--- /dev/null
+++ b/main/acf-core/acf-core.post-upgrade
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+new=$1
+old=$2
+
+# if current is not older than 0.10.1 we exit.
+if ! [ "$(apk version -t $old 0.10.1)" = "<" ]; then
+ exit 0
+fi
+
+if [ -e /etc/acf/acf.conf.apk-new ]; then
+ mv /etc/acf/acf.conf /etc/acf/acf.conf.apk-old
+ mv /etc/acf/acf.conf.apk-new /etc/acf/acf.conf
+fi
+
+exit 0
diff --git a/main/acf-dansguardian/APKBUILD b/main/acf-dansguardian/APKBUILD
new file mode 100644
index 0000000000..cdbdc54b78
--- /dev/null
+++ b/main/acf-dansguardian/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-dansguardian
+pkgver=0.4.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for dansguardian"
+url="http://git.alpinelinux.org/cgit/acf-dansguardian"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua dansguardian"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="864ac9cbf48ad1658ca2c1c6ce471799 acf-dansguardian-0.4.0.tar.bz2"
diff --git a/main/acf-dhcp/APKBUILD b/main/acf-dhcp/APKBUILD
new file mode 100644
index 0000000000..37713b7dbf
--- /dev/null
+++ b/main/acf-dhcp/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-dhcp
+pkgver=0.5.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for dhcp"
+url="http://git.alpinelinux.org/cgit/acf-dhcp"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua dhcp"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="adc54102dcae8b1fe7e1a4538ebee94d acf-dhcp-0.5.0.tar.bz2"
diff --git a/main/acf-dnscache/APKBUILD b/main/acf-dnscache/APKBUILD
new file mode 100644
index 0000000000..d593675e13
--- /dev/null
+++ b/main/acf-dnscache/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-dnscache
+pkgver=0.3.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for dnscache"
+url="http://git.alpinelinux.org/cgit/acf-dnscache"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-posix dnscache"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="eec8af4eb887448613626d8b08cdc456 acf-dnscache-0.3.0.tar.bz2"
diff --git a/main/acf-dnsmasq/APKBUILD b/main/acf-dnsmasq/APKBUILD
new file mode 100644
index 0000000000..6b6b03d6bb
--- /dev/null
+++ b/main/acf-dnsmasq/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-dnsmasq
+pkgver=0.3.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for dnsmasq"
+url="http://git.alpinelinux.org/cgit/acf-dnsmasq"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua dnsmasq"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="5c1843623c805fbf9be4dcde32049206 acf-dnsmasq-0.3.0.tar.bz2"
diff --git a/main/acf-dovecot/APKBUILD b/main/acf-dovecot/APKBUILD
new file mode 100644
index 0000000000..9947179015
--- /dev/null
+++ b/main/acf-dovecot/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-dovecot
+pkgver=0.2.1
+pkgrel=2
+pkgdesc="A web-based system administration interface for dovecot"
+url="http://git.alpinelinux.org/cgit/acf-dovecot"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua dovecot"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="4e218a704b4ff3af4765d011787e29f3 acf-dovecot-0.2.1.tar.bz2"
diff --git a/main/acf-fetchmail/APKBUILD b/main/acf-fetchmail/APKBUILD
new file mode 100644
index 0000000000..68f1e79602
--- /dev/null
+++ b/main/acf-fetchmail/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-fetchmail
+pkgver=0.5.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for fetchmail"
+url="http://git.alpinelinux.org/cgit/acf-fetchmail"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua fetchmail"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="41ae8840c5d4cdceb5b21fc9e8debf1b acf-fetchmail-0.5.0.tar.bz2"
diff --git a/main/acf-freeswitch-vmail/APKBUILD b/main/acf-freeswitch-vmail/APKBUILD
new file mode 100644
index 0000000000..9e80dfaf55
--- /dev/null
+++ b/main/acf-freeswitch-vmail/APKBUILD
@@ -0,0 +1,21 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-freeswitch-vmail
+pkgver=0.0.13
+pkgrel=0
+pkgdesc="ACF for a web interface for freeswitch voicemail"
+url="http://git.alpinelinux.org/cgit/$pkgname"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-sql-sqlite3 freeswitch"
+makedepends=""
+install="$pkgname.post-upgrade"
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="b84eac2c278dd3a1e98b4d01941ffd0c acf-freeswitch-vmail-0.0.13.tar.bz2"
diff --git a/main/acf-freeswitch-vmail/acf-freeswitch-vmail.post-upgrade b/main/acf-freeswitch-vmail/acf-freeswitch-vmail.post-upgrade
new file mode 100644
index 0000000000..3b0ff119c8
--- /dev/null
+++ b/main/acf-freeswitch-vmail/acf-freeswitch-vmail.post-upgrade
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+new=$1
+old=$2
+
+# if current is not older than 0.0.11 we exit.
+if ! [ "$(apk version -t $old 0.0.11)" = "<" ]; then
+ exit 0
+fi
+
+sqlite3 /var/lib/freeswitch/db/voicemail_default.db "UPDATE voicemail_params SET descr='Passwords must be all numbers and at least three digits' WHERE name='vm-password'"
+
+exit 0
+
diff --git a/main/acf-freeswitch/APKBUILD b/main/acf-freeswitch/APKBUILD
new file mode 100644
index 0000000000..7a4f23de03
--- /dev/null
+++ b/main/acf-freeswitch/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-freeswitch
+pkgver=0.2.0
+pkgrel=0
+pkgdesc="ACF for freeswitch"
+url="http://git.alpinelinux.org/cgit/acf-freeswitch"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua freeswitch"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="b5e215cb82349d39fc5cb4c5bb602e11 acf-freeswitch-0.2.0.tar.bz2"
diff --git a/main/acf-gross/APKBUILD b/main/acf-gross/APKBUILD
new file mode 100644
index 0000000000..cdb25d9131
--- /dev/null
+++ b/main/acf-gross/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-gross
+pkgver=0.2.1
+pkgrel=2
+pkgdesc="A web-based system administration interface for gross"
+url="http://git.alpinelinux.org/cgit/acf-gross"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua gross"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="cd821881f11059cd1cf002b0b8d37100 acf-gross-0.2.1.tar.bz2"
diff --git a/main/acf-heimdal/APKBUILD b/main/acf-heimdal/APKBUILD
new file mode 100644
index 0000000000..c4caaf9e75
--- /dev/null
+++ b/main/acf-heimdal/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-heimdal
+pkgver=0.2.0
+pkgrel=2
+pkgdesc="ACF module for heimdal"
+url="http://git.alpinelinux.org/cgit/$pkgname"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua heimdal"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="59055e59b190bf8c03ff207435f66b1b acf-heimdal-0.2.0.tar.bz2"
diff --git a/main/acf-iproute2-qos/APKBUILD b/main/acf-iproute2-qos/APKBUILD
new file mode 100644
index 0000000000..8238b5ceb0
--- /dev/null
+++ b/main/acf-iproute2-qos/APKBUILD
@@ -0,0 +1,18 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-iproute2-qos
+pkgver=0.1.2
+pkgrel=2
+pkgdesc="ACF module for iproute2-qos"
+url="http://git.alpinelinux.org/cgit/$pkgname"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua iproute2-qos acf-alpine-baselayout>=0.5.7"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="d40057ae7e74dee618c80b2a7c795fa3 acf-iproute2-qos-0.1.2.tar.bz2"
diff --git a/main/acf-ipsec-tools/APKBUILD b/main/acf-ipsec-tools/APKBUILD
new file mode 100644
index 0000000000..8c02a96227
--- /dev/null
+++ b/main/acf-ipsec-tools/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-ipsec-tools
+pkgver=0.7.1
+pkgrel=0
+pkgdesc="A web-based system administration interface for ipsec-tools"
+url="http://git.alpinelinux.org/cgit/acf-ipsec-tools"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua ipsec-tools"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="3f00bf74cce2d8caa8a0442ea32a025d acf-ipsec-tools-0.7.1.tar.bz2"
diff --git a/main/acf-iptables/APKBUILD b/main/acf-iptables/APKBUILD
new file mode 100644
index 0000000000..66705f8c3c
--- /dev/null
+++ b/main/acf-iptables/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-iptables
+pkgver=0.3.1
+pkgrel=2
+pkgdesc="A web-based system administration interface for iptables"
+url="http://git.alpinelinux.org/cgit/acf-iptables"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua iptables"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="4e7eafa43eebd4dd20502d35c570eb19 acf-iptables-0.3.1.tar.bz2"
diff --git a/main/acf-jquery/APKBUILD b/main/acf-jquery/APKBUILD
new file mode 100644
index 0000000000..70b24aed30
--- /dev/null
+++ b/main/acf-jquery/APKBUILD
@@ -0,0 +1,18 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-jquery
+pkgver=0.2.0
+pkgrel=0
+pkgdesc="jquery libraries for ACF"
+url="http://git.alpinelinux.org/cgit/acf-jquery"
+arch="noarch"
+license="GPL-2"
+depends=""
+replaces="acf-core"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="02bb4e1d0b5d6aebe0aebfc48f65ad05 acf-jquery-0.2.0.tar.bz2"
diff --git a/main/acf-kamailio/APKBUILD b/main/acf-kamailio/APKBUILD
new file mode 100644
index 0000000000..d70ff78308
--- /dev/null
+++ b/main/acf-kamailio/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-kamailio
+pkgver=0.4.1
+pkgrel=0
+pkgdesc="A web-based system administration interface for kamailio"
+url="http://git.alpinelinux.org/cgit/acf-kamailio"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua kamailio lua-sql-postgres"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="24a442bba4f3f609f2b6be82a8da7386 acf-kamailio-0.4.1.tar.bz2"
diff --git a/main/acf-lib/APKBUILD b/main/acf-lib/APKBUILD
new file mode 100644
index 0000000000..4ef0415e32
--- /dev/null
+++ b/main/acf-lib/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-lib
+pkgver=0.2.1
+pkgrel=0
+pkgdesc="Lua libraries for ACF"
+url="http://git.alpinelinux.org/cgit/acf-lib"
+arch="noarch"
+license="GPL-2"
+depends=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="c120e66d542c67c8d9a06dad310f7ccc acf-lib-0.2.1.tar.bz2"
diff --git a/main/acf-lvm2/APKBUILD b/main/acf-lvm2/APKBUILD
new file mode 100644
index 0000000000..fac9539db7
--- /dev/null
+++ b/main/acf-lvm2/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-lvm2
+pkgver=0.3.0
+pkgrel=0
+pkgdesc="ACF module for lvm2"
+url="http://git.alpinelinux.org/cgit/$pkgname"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lvm2"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="a3937d552a277b38d898be3d063b12ee acf-lvm2-0.3.0.tar.bz2"
diff --git a/main/acf-mdadm/APKBUILD b/main/acf-mdadm/APKBUILD
new file mode 100644
index 0000000000..6e073db26e
--- /dev/null
+++ b/main/acf-mdadm/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-mdadm
+pkgver=0.2.1
+pkgrel=2
+pkgdesc="ACF module for mdadm"
+url="http://git.alpinelinux.org/cgit/$pkgname"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua mdadm"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="3e7159843721bf37fb45507bc29c187c acf-mdadm-0.2.1.tar.bz2"
diff --git a/main/acf-opennhrp/APKBUILD b/main/acf-opennhrp/APKBUILD
new file mode 100644
index 0000000000..9f126957c0
--- /dev/null
+++ b/main/acf-opennhrp/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-opennhrp
+pkgver=0.6.1
+pkgrel=2
+pkgdesc="A web-based system administration interface for opennhrp"
+url="http://git.alpinelinux.org/cgit/acf-opennhrp"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-posix opennhrp"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="c4b876489cc9b75edce7793f9f50af79 acf-opennhrp-0.6.1.tar.bz2"
diff --git a/main/acf-openntpd/APKBUILD b/main/acf-openntpd/APKBUILD
new file mode 100644
index 0000000000..66b41b24eb
--- /dev/null
+++ b/main/acf-openntpd/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-openntpd
+pkgver=0.5.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for openntpd"
+url="http://git.alpinelinux.org/cgit/acf-openntpd"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua openntpd"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="9ec8677d8bcdc99624cbf24ba1d3b48d acf-openntpd-0.5.0.tar.bz2"
diff --git a/main/acf-openssh/APKBUILD b/main/acf-openssh/APKBUILD
new file mode 100644
index 0000000000..b5219925cc
--- /dev/null
+++ b/main/acf-openssh/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-openssh
+pkgver=0.5.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for openssh"
+url="http://git.alpinelinux.org/cgit/acf-openssh"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua openssh"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="bcc3639316fb5ad3fa98d396ffee48d7 acf-openssh-0.5.0.tar.bz2"
diff --git a/main/acf-openssl/APKBUILD b/main/acf-openssl/APKBUILD
new file mode 100644
index 0000000000..98669a16d5
--- /dev/null
+++ b/main/acf-openssl/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-openssl
+pkgver=0.3.2
+pkgrel=0
+pkgdesc="A web-based system administration interface for openssl"
+url="http://git.alpinelinux.org/cgit/acf-openssl"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua openssl"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="9f073d837b27450e4ef6bd6478798d46 acf-openssl-0.3.2.tar.bz2"
diff --git a/main/acf-openvpn/APKBUILD b/main/acf-openvpn/APKBUILD
new file mode 100644
index 0000000000..fa3f3feb76
--- /dev/null
+++ b/main/acf-openvpn/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-openvpn
+pkgver=0.6.0
+pkgrel=2
+pkgdesc="A web-based system administration interface for openvpn"
+url="http://git.alpinelinux.org/cgit/acf-openvpn"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua openvpn"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="d1fddc56490f23bdacfd602e2f334ab6 acf-openvpn-0.6.0.tar.bz2"
diff --git a/main/acf-pingu/APKBUILD b/main/acf-pingu/APKBUILD
new file mode 100644
index 0000000000..e1d445c16c
--- /dev/null
+++ b/main/acf-pingu/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-pingu
+pkgver=0.2.1
+pkgrel=2
+pkgdesc="A web-based system administration interface for pingu"
+url="http://git.alpinelinux.org/cgit/acf-pingu"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua pingu"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="0b74aea2e06e157b6a26d52f56e37f89 acf-pingu-0.2.1.tar.bz2"
diff --git a/main/acf-postfix/APKBUILD b/main/acf-postfix/APKBUILD
new file mode 100644
index 0000000000..ead9d80018
--- /dev/null
+++ b/main/acf-postfix/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-postfix
+pkgver=0.4.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for postfix"
+url="http://git.alpinelinux.org/cgit/acf-postfix"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua postfix"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="79c0c0bac5899fc729710e445af29154 acf-postfix-0.4.0.tar.bz2"
diff --git a/main/acf-postgresql/APKBUILD b/main/acf-postgresql/APKBUILD
new file mode 100644
index 0000000000..d90da5ce86
--- /dev/null
+++ b/main/acf-postgresql/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-postgresql
+pkgver=0.5.0
+pkgrel=0
+pkgdesc="ACF module for postgresql"
+url="http://git.alpinelinux.org/cgit/$pkgname"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua postgresql"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="98986ef05d2e5b477385cef519e80bf1 acf-postgresql-0.5.0.tar.bz2"
diff --git a/main/acf-ppp/APKBUILD b/main/acf-ppp/APKBUILD
new file mode 100644
index 0000000000..4b8d570be5
--- /dev/null
+++ b/main/acf-ppp/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-ppp
+pkgver=0.2.0
+pkgrel=2
+pkgdesc="A web-based system administration interface for ppp"
+url="http://git.alpinelinux.org/cgit/acf-ppp"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua ppp"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="95ff9923cefc0cc02b2ca26daf34fe1e acf-ppp-0.2.0.tar.bz2"
diff --git a/main/acf-provisioning/APKBUILD b/main/acf-provisioning/APKBUILD
new file mode 100644
index 0000000000..fe8033caee
--- /dev/null
+++ b/main/acf-provisioning/APKBUILD
@@ -0,0 +1,21 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-provisioning
+pkgver=0.0.9
+pkgrel=0
+pkgdesc="ACF for provisioning templated configs to devices"
+url="http://git.alpinelinux.org/cgit/acf-provisioning"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-sql-postgres postgresql-client lua-posixtz"
+makedepends=""
+install="$pkgname.post-upgrade"
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="f2d1fb7fc15f6b7779c2de986f218050 acf-provisioning-0.0.9.tar.bz2"
diff --git a/main/acf-provisioning/acf-provisioning.post-upgrade b/main/acf-provisioning/acf-provisioning.post-upgrade
new file mode 100644
index 0000000000..53c8726cbf
--- /dev/null
+++ b/main/acf-provisioning/acf-provisioning.post-upgrade
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+new=$1
+old=$2
+
+# if current is older than 0.0.7-r1 we update.
+if [ "$(apk version -t $old 0.0.7-r1)" = "<" ]; then
+
+psql -U postgres -c "INSERT INTO provisioning_classes VALUES(default, (SELECT class_group_id FROM provisioning_class_groups WHERE name='device'), 'Unsupported Phone', '999')"\
+ provisioning
+psql -U postgres -c "INSERT INTO provisioning_groups VALUES(default, 'reg1', 'Registration 1 Unsupported', '10')"\
+ provisioning
+psql -U postgres -c "INSERT INTO classes_to_param_groups VALUES((SELECT class_id FROM provisioning_classes WHERE label='Unsupported Phone'), (SELECT group_id FROM provisioning_groups WHERE label='Registration 1 Unsupported'))"\
+ provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Registration 1 Unsupported'), (SELECT param_id FROM provisioning_params WHERE name='extension'), null, true)"\
+ provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Registration 1 Unsupported'), (SELECT param_id FROM provisioning_params WHERE name='password'), null, true)"\
+ provisioning
+
+fi
+
+# if current is older than 0.0.8 we update.
+if [ "$(apk version -t $old 0.0.8)" = "<" ]; then
+
+psql -U postgres -c "ALTER TABLE provisioning_params ADD COLUMN validate text" provisioning
+
+psql -U postgres -c "UPDATE provisioning_params SET descr='Phone dial pattern based on section 2.1.5 of RFC 3435, plus a comma to turn dialtone back on', regexp='^[*#0-9xT|,.%[%]-]*\$' WHERE name='digitmap'" provisioning
+psql -U postgres -c "UPDATE provisioning_params SET descr='Timeout in seconds for each segment of digit map (separated by ''|'')', regexp='^[0-9|]*\$' WHERE name='digitmaptimeout'" provisioning
+
+psql -U postgres -c "UPDATE provisioning_params SET regexp='^%x%x%x%x%x%x%x%x%x%x%x%x\$', validate='local value, functions, params = ...\nvalue = string.upper(value)\nlocal others = functions.getselectresponse(\"SELECT count(*) FROM provisioning_values WHERE param_id=\\'\"..params.value.device.value.mac.param_id..\"\\' AND device_id!=\\'\"..params.value.device_id.value..\"\\' AND value=\\'\"..value..\"\\'\")\nif tonumber(others[1].count) > 0 then\n\treturn value, \"MAC Address must be unique\"\nend\nreturn value' WHERE name='mac'" provisioning
+
+psql -U postgres -c "INSERT INTO provisioning_params VALUES(default, 'callwaitingenable', 'boolean', 'Call Waiting Enable', '', 'true', '205', '', null)" provisioning
+psql -U postgres -c "INSERT INTO provisioning_params VALUES(default, 'speeddialenable', 'boolean', 'Speed Dial Enable', '', 'true', '206', '', null)" provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Standard Phone'), (SELECT param_id FROM provisioning_params WHERE name='callwaitingenable'), 'true', false)" provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Standard Phone'), (SELECT param_id FROM provisioning_params WHERE name='speeddialenable'), 'true', false)" provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Public Phone'), (SELECT param_id FROM provisioning_params WHERE name='callwaitingenable'), 'true', false)" provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Public Phone'), (SELECT param_id FROM provisioning_params WHERE name='speeddialenable'), 'false', false)" provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Hotline'), (SELECT param_id FROM provisioning_params WHERE name='callwaitingenable'), 'true', false)" provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Hotline'), (SELECT param_id FROM provisioning_params WHERE name='speeddialenable'), 'false', false)" provisioning
+
+fi
+
+# if current is older than 0.0.9 we update.
+if [ "$(apk version -t $old 0.0.9)" = "<" ]; then
+
+psql -U postgres -c "INSERT INTO provisioning_params VALUES(default, 'mailbox', 'text', 'Voice Mailbox', 'Mailbox extension or URL', '', '207', '', null)" provisioning
+psql -U postgres -c "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Standard Phone'), (SELECT param_id FROM provisioning_params WHERE name='mailbox'), '', true)" provisioning
+
+fi
+
+exit 0
diff --git a/main/acf-quagga/APKBUILD b/main/acf-quagga/APKBUILD
new file mode 100644
index 0000000000..1cdb6c10c5
--- /dev/null
+++ b/main/acf-quagga/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-quagga
+pkgver=0.5.0
+pkgrel=2
+pkgdesc="A web-based system administration interface for quagga"
+url="http://git.alpinelinux.org/cgit/acf-quagga"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua quagga"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="6b22ff32cb493a7bd9b8055d75e07a8d acf-quagga-0.5.0.tar.bz2"
diff --git a/main/acf-samba/APKBUILD b/main/acf-samba/APKBUILD
new file mode 100644
index 0000000000..f78d833471
--- /dev/null
+++ b/main/acf-samba/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-samba
+pkgver=0.5.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for samba"
+url="http://git.alpinelinux.org/cgit/acf-samba"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua samba"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="dc9175d5350061803e77addf9cf81600 acf-samba-0.5.0.tar.bz2"
diff --git a/main/acf-shorewall/APKBUILD b/main/acf-shorewall/APKBUILD
new file mode 100644
index 0000000000..c96fc18a83
--- /dev/null
+++ b/main/acf-shorewall/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-shorewall
+pkgver=0.7.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for shorewall"
+url="http://git.alpinelinux.org/cgit/acf-shorewall"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua shorewall"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="190a278c301d0b20afc512b9585148c0 acf-shorewall-0.7.0.tar.bz2"
diff --git a/main/acf-skins/APKBUILD b/main/acf-skins/APKBUILD
new file mode 100644
index 0000000000..88dc980520
--- /dev/null
+++ b/main/acf-skins/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-skins
+pkgver=0.4.1
+pkgrel=0
+pkgdesc="Skins for ACF"
+url="http://git.alpinelinux.org/cgit/acf-skins"
+arch="noarch"
+license="GPL-2"
+depends=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="cbfeab06f1b82d906ac459225d897dd2 acf-skins-0.4.1.tar.bz2"
diff --git a/main/acf-snort/APKBUILD b/main/acf-snort/APKBUILD
new file mode 100644
index 0000000000..a842242ad9
--- /dev/null
+++ b/main/acf-snort/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-snort
+pkgver=0.5.1
+pkgrel=2
+pkgdesc="A web-based system administration interface for snort"
+url="http://git.alpinelinux.org/cgit/acf-snort"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua snort"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="90e96ff148a0448ea1714fd6500be349 acf-snort-0.5.1.tar.bz2"
diff --git a/main/acf-squid/APKBUILD b/main/acf-squid/APKBUILD
new file mode 100644
index 0000000000..4d2ad72a37
--- /dev/null
+++ b/main/acf-squid/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-squid
+pkgver=0.7.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for squid"
+url="http://git.alpinelinux.org/cgit/acf-squid"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua squid"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="61a9f36f393fbc80186300ec93bb1b0c acf-squid-0.7.0.tar.bz2"
diff --git a/main/acf-tcpproxy/APKBUILD b/main/acf-tcpproxy/APKBUILD
new file mode 100644
index 0000000000..70fc8dbd77
--- /dev/null
+++ b/main/acf-tcpproxy/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-tcpproxy
+pkgver=0.2.0
+pkgrel=2
+pkgdesc="A web-based system administration interface for tcpproxy"
+url="http://git.alpinelinux.org/cgit/acf-tcpproxy"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua tcpproxy"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="640ee3a38220df510452da19bacbda26 acf-tcpproxy-0.2.0.tar.bz2"
diff --git a/main/acf-tinydns/APKBUILD b/main/acf-tinydns/APKBUILD
new file mode 100644
index 0000000000..df95195d48
--- /dev/null
+++ b/main/acf-tinydns/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-tinydns
+pkgver=0.7.0
+pkgrel=0
+pkgdesc="A web-based system administration interface for tinydns"
+url="http://git.alpinelinux.org/cgit/acf-tinydns"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua tinydns"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="20597fd493bd37414247abd4b1ae10ed acf-tinydns-0.7.0.tar.bz2"
diff --git a/main/acf-weblog/APKBUILD b/main/acf-weblog/APKBUILD
new file mode 100644
index 0000000000..d08bd81823
--- /dev/null
+++ b/main/acf-weblog/APKBUILD
@@ -0,0 +1,21 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-weblog
+pkgver=0.5.9
+pkgrel=2
+pkgdesc="ACF for web proxy (squid and dansguardian) logfiles"
+url="http://git.alpinelinux.org/cgit/acf-weblog"
+arch="noarch"
+license="GPL-2"
+depends="acf-core lua lua-sql-postgres wget postgresql-client"
+makedepends=""
+install="$pkgname.post-upgrade"
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="bdac4a705b896e78cf68cc498361a335 acf-weblog-0.5.9.tar.bz2"
diff --git a/main/acf-weblog/acf-weblog.post-upgrade b/main/acf-weblog/acf-weblog.post-upgrade
new file mode 100644
index 0000000000..a15590cc73
--- /dev/null
+++ b/main/acf-weblog/acf-weblog.post-upgrade
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+new=$1
+old=$2
+
+# if current is not older than 0.5.4 we exit.
+if ! [ "$(apk version -t $old 0.5.4)" = "<" ]; then
+ exit 0
+fi
+
+psql -U postgres -c "ALTER TABLE weblog ALTER bytes TYPE bigint"\
+ webproxylog
+psql -U postgres -c "ALTER TABLE pubweblog ALTER bytes TYPE bigint"\
+ webproxylog
+psql -U postgres -c "ALTER TABLE blocklog ALTER bytes TYPE bigint"\
+ webproxylog
+psql -U postgres -c "ALTER TABLE pubblocklog ALTER bytes TYPE bigint"\
+ webproxylog
+
+# if current is not older than 0.4.5 we exit.
+if ! [ "$(apk version -t $old 0.4.5)" = "<" ]; then
+ exit 0
+fi
+
+psql -U postgres -c "ALTER TABLE dbhistlog ALTER logdatetime TYPE timestamp(3)"\
+ webproxylog
+
+if ! [ "$(apk version -t $old 0.4.0)" = "<" ]; then
+ exit 0
+fi
+
+psql -U postgres -c "ALTER TABLE weblog ADD COLUMN shortreason text" \
+ webproxylog
+psql -U postgres -c "ALTER TABLE pubweblog ADD COLUMN shortreason text" \
+ webproxylog
+psql -U postgres -c "ALTER TABLE pubblocklog ADD COLUMN shortreason text" \
+ webproxylog
+psql -U postgres -c "ALTER TABLE blocklog ADD COLUMN shortreason text" \
+ webproxylog
+
+exit 0
+
diff --git a/main/ack/APKBUILD b/main/ack/APKBUILD
new file mode 100644
index 0000000000..d68456dde0
--- /dev/null
+++ b/main/ack/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ack
+pkgver=1.94
+pkgrel=1
+pkgdesc="A Perl-powered replacement for grep"
+url="http://betterthangrep.com/"
+arch="noarch"
+license="GPL"
+depends="perl-file-next"
+makedepends="perl-dev"
+source="http://search.cpan.org/CPAN/authors/id/P/PE/PETDANCE/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="dcf68e56bab0d394370fa102c7f08cb0 ack-1.94.tar.gz"
diff --git a/main/acl/APKBUILD b/main/acl/APKBUILD
new file mode 100644
index 0000000000..197b5a2e5b
--- /dev/null
+++ b/main/acl/APKBUILD
@@ -0,0 +1,57 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=acl
+pkgver=2.2.51
+pkgrel=2
+pkgdesc="Access control list utilities"
+url="http://acl.bestbits.at/"
+arch="all"
+license="LGPL"
+depends=
+makedepends="attr-dev gzip"
+subpackages="$pkgname-dev $pkgname-doc libacl"
+source="http://download.savannah.gnu.org/releases-noredirect/acl/acl-$pkgver.src.tar.gz
+ quote-strchr.patch"
+
+prepare() {
+ cd "$srcdir"/acl-$pkgver
+ patch -p1 -i "$srcdir"/quote-strchr.patch || return 1
+ #libtoolize --force && aclocal -I m4 && autoconf && autoheader
+ sed -i \
+ -e '/^as_dummy=/s:=":="$PATH$PATH_SEPARATOR:' \
+ configure # hack PATH with AC_PATH_PROG
+ sed -i \
+ -e "/^PKG_DOC_DIR/s:@pkg_name@:${PF}:" \
+ -e '/HAVE_ZIPPED_MANPAGES/s:=.*:=false:' \
+ include/builddefs.in \
+ || return 1
+}
+
+build() {
+ cd "$srcdir"/acl-$pkgver
+ unset PLATFORM
+ export OPTIMIZER="${CFLAGS}"
+ export DEBUG=-DNDEBUG
+ CONFIG_SHELL=/bin/sh ./configure --prefix=/usr \
+ --libdir=/lib \
+ --libexecdir=/usr/lib \
+ --disable-gettext \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/acl-$pkgver
+ make DIST_ROOT="$pkgdir" install install-lib install-dev || return 1
+ rm "$pkgdir"/usr/lib/*.la "$pkgdir"/lib/*.la || return 1
+ mv "$pkgdir"/lib/libacl.a "$pkgdir"/usr/lib/
+ chown -R root:root "$pkgdir"/*
+}
+
+libacl() {
+ pkgdesc="Dynamic library for access control list support"
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libacl.so.* "$subpkgdir"/lib/
+}
+
+md5sums="3fc0ce99dc5253bdcce4c9cd437bc267 acl-2.2.51.src.tar.gz
+1bef4f022a068ebfeb3b5363dc6ce174 quote-strchr.patch"
diff --git a/main/acl/quote-strchr.patch b/main/acl/quote-strchr.patch
new file mode 100644
index 0000000000..d2510da24e
--- /dev/null
+++ b/main/acl/quote-strchr.patch
@@ -0,0 +1,25 @@
+From 7565e4fcb9209782ed02f3caff246cf5ea816674 Mon Sep 17 00:00:00 2001
+From: Mike Frysinger <vapier@gentoo.org>
+Date: Fri, 8 Jan 2010 21:28:31 -0500
+Subject: [PATCH] quote: pull in string.h for strchr prototype
+
+Signed-off-by: Mike Frysinger <vapier@gentoo.org>
+---
+ libmisc/quote.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/libmisc/quote.c b/libmisc/quote.c
+index f98c887..bf8f9eb 100644
+--- a/libmisc/quote.c
++++ b/libmisc/quote.c
+@@ -20,6 +20,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <ctype.h>
++#include <string.h>
+ #include "misc.h"
+
+ const char *quote(const char *str, const char *quote_chars)
+--
+1.6.6
+
diff --git a/main/alpine-base/APKBUILD b/main/alpine-base/APKBUILD
new file mode 100644
index 0000000000..3190b1e61a
--- /dev/null
+++ b/main/alpine-base/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alpine-base
+pkgver=2.2.0_git20110607
+pkgrel=0
+pkgdesc="Meta package for minimal alpine base"
+url="http://alpinelinux.org"
+arch="noarch"
+license="GPL"
+depends="alpine-baselayout alpine-conf apk-tools busybox busybox-initscripts
+ openrc"
+[ "$ALPINE_LIBC" != "eglibc" ] && depends="$depends uclibc-utils"
+makedepends=
+install=
+subpackages=
+replaces="alpine-baselayout"
+source="http://dev.alpinelinux.org/~ncopa/alpine/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub
+ http://nenolod.net/~nenolod/alpine-keys/alpine-devel@lists.alpinelinux.org-4d07755e.rsa.pub
+ "
+
+build() {
+ return 0
+}
+
+package() {
+ # copy keys for repos
+ mkdir -p "$pkgdir"/etc/apk/keys
+ install -m644 "$srcdir"/*.pub "$pkgdir"/etc/apk/keys/
+
+ # create /etc/alpine-release
+ echo $pkgver > "$pkgdir"/etc/alpine-release
+
+ # create /etc/issue
+ cat >"$pkgdir"/etc/issue<<EOF
+Welcome to Alpine Linux ${pkgver%.*}
+Kernel \\r on an \\m (\\l)
+
+EOF
+}
+
+md5sums="75ee19ea2b03c12bc171647edc677f6f alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub
+ca7d06006181b625cf1ff4aefd51bd08 alpine-devel@lists.alpinelinux.org-4d07755e.rsa.pub"
diff --git a/main/alpine-baselayout/APKBUILD b/main/alpine-baselayout/APKBUILD
new file mode 100644
index 0000000000..25a435f3f7
--- /dev/null
+++ b/main/alpine-baselayout/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alpine-baselayout
+pkgver=2.1.1
+pkgrel=0
+pkgdesc="Alpine base dir structure and init scripts"
+url=http://git.alpinelinux.org/cgit/alpine-baselayout
+depends=
+install="$pkgname.pre-upgrade"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2
+ "
+arch="all"
+license=GPL-2
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ rm -f src/mkmntdirs
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make install PREFIX= DESTDIR="$pkgdir" || return 1
+ rm -f "$pkgdir"/etc/issue
+}
+md5sums="4f47c32a0e88ae0bd4673a07478525c0 alpine-baselayout-2.1.1.tar.bz2"
diff --git a/main/alpine-baselayout/alpine-baselayout.pre-upgrade b/main/alpine-baselayout/alpine-baselayout.pre-upgrade
new file mode 100644
index 0000000000..7ba635eb99
--- /dev/null
+++ b/main/alpine-baselayout/alpine-baselayout.pre-upgrade
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# we need to have our modprobe.d files with .conf suffix
+for i in /etc/modprobe.d/*; do
+ # ignore files that does not exist (i.e if modprobe.d is empty)
+ [ -r "$i" ] || continue
+
+ # ignore files that has an extention
+ case "$i" in
+ *.*) continue;;
+ esac
+
+ # append extension
+ mv "$i" "$i".conf
+done
diff --git a/main/alpine-conf/0001-setup-xorg-base-initial-commit.patch b/main/alpine-conf/0001-setup-xorg-base-initial-commit.patch
new file mode 100644
index 0000000000..301e5777c2
--- /dev/null
+++ b/main/alpine-conf/0001-setup-xorg-base-initial-commit.patch
@@ -0,0 +1,74 @@
+From 049d3ce1efda40a59bd42834d3b8db5cdb0386fa Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Mon, 6 Jun 2011 11:39:45 +0000
+Subject: [PATCH 1/3] setup-xorg-base: initial commit
+
+This script is supposed to help users to quickly get a working xorg server
+running.
+---
+ .gitignore | 1 +
+ Makefile | 1 +
+ setup-xorg-base.in | 29 +++++++++++++++++++++++++++++
+ 3 files changed, 31 insertions(+), 0 deletions(-)
+ create mode 100644 setup-xorg-base.in
+
+diff --git a/.gitignore b/.gitignore
+index c1f3e8e..e0b22b1 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -16,4 +16,5 @@ setup-interfaces
+ setup-keymap
+ setup-mta
+ setup-timezone
++setup-xorg-base
+ update-conf
+diff --git a/Makefile b/Makefile
+index 96ec9cc..91f0835 100644
+--- a/Makefile
++++ b/Makefile
+@@ -24,6 +24,7 @@ SBIN_FILES := lbu\
+ setup-acf\
+ setup-bootable\
+ setup-timezone\
++ setup-xorg-base\
+ update-conf
+
+ BIN_FILES := uniso
+diff --git a/setup-xorg-base.in b/setup-xorg-base.in
+new file mode 100644
+index 0000000..bcdbe77
+--- /dev/null
++++ b/setup-xorg-base.in
+@@ -0,0 +1,29 @@
++#!/bin/sh
++
++# simple script to setup x basic org server
++# you will still need a window manager and login manager or xinit
++
++base_pkgs="xorg-server xf86-video-vesa xf86-input-evdev xf86-input-mouse
++ xf86-input-keyboard udev"
++
++# TODO: detect graphics card and pick proper xf86-video-* driver based on that
++
++# TODO: detect if we need xf86-input-synaptics
++
++# ps mouse
++modprobe psmouse
++grep -q -w psmouse /etc/modules || echo "psmouse" >> /etc/modules
++
++# install packages
++apk add $base_pkgs $@
++
++# setup and start udev
++rc-update -q del mdev sysinit
++rc-update -q add udev sysinit
++rc-update -q add udev-postmount default
++
++if ! rc-service -q udev status; then
++ rc-service udev start
++ rc-service udev-postmount start
++fi
++
+--
+1.7.5.4
+
diff --git a/main/alpine-conf/0002-setup-gparted-desktop-new-setup-script.patch b/main/alpine-conf/0002-setup-gparted-desktop-new-setup-script.patch
new file mode 100644
index 0000000000..6cacebb3b4
--- /dev/null
+++ b/main/alpine-conf/0002-setup-gparted-desktop-new-setup-script.patch
@@ -0,0 +1,75 @@
+From d71205d14c74516925c0e837ba02135f36f084c6 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Mon, 6 Jun 2011 14:55:19 +0000
+Subject: [PATCH 2/3] setup-gparted-desktop: new setup script
+
+The idea is that you quick and dirty can get gparted up and running
+---
+ Makefile | 1 +
+ setup-gparted-desktop.in | 42 ++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 43 insertions(+), 0 deletions(-)
+ create mode 100644 setup-gparted-desktop.in
+
+diff --git a/Makefile b/Makefile
+index 91f0835..0427b1b 100644
+--- a/Makefile
++++ b/Makefile
+@@ -25,6 +25,7 @@ SBIN_FILES := lbu\
+ setup-bootable\
+ setup-timezone\
+ setup-xorg-base\
++ setup-gparted-desktop\
+ update-conf
+
+ BIN_FILES := uniso
+diff --git a/setup-gparted-desktop.in b/setup-gparted-desktop.in
+new file mode 100644
+index 0000000..8bd198e
+--- /dev/null
++++ b/setup-gparted-desktop.in
+@@ -0,0 +1,42 @@
++#!/bin/sh
++
++setup-xorg-base gparted xinit aterm openbox ttf-freefont $@
++
++# create openbox menu
++mkdir -p ~/.config/openbox
++cat >~/.config/openbox/menu.xml<<EOF
++<?xml version="1.0" encoding="UTF-8"?>
++
++<openbox_menu xmlns="http://openbox.org/3.4/menu">
++<menu id="root-menu" label="Openbox 3">
++ <separator label="Applications" />
++ <item label="GParted">
++ <action name="Execute">
++ <command>gparted</command>
++ </action>
++ </item>
++ <item label="aterm">
++ <action name="Execute">
++ <command>aterm</command>
++ </action>
++ </item>
++ <separator />
++ <item label="Log Out">
++ <action name="Exit">
++ <prompt>yes</prompt>
++ </action>
++ </item>
++</menu>
++</openbox_menu>
++EOF
++
++# create xinitrc
++cat >~/.xinitrc <<EOF
++gparted &
++exec openbox-session
++EOF
++
++echo ""
++echo " To start GParted run: startx"
++echo ""
++
+--
+1.7.5.4
+
diff --git a/main/alpine-conf/0003-setup-disk-fix-data-only-mode-with-no-lvm-and-no-rai.patch b/main/alpine-conf/0003-setup-disk-fix-data-only-mode-with-no-lvm-and-no-rai.patch
new file mode 100644
index 0000000000..69fa9a1c2f
--- /dev/null
+++ b/main/alpine-conf/0003-setup-disk-fix-data-only-mode-with-no-lvm-and-no-rai.patch
@@ -0,0 +1,28 @@
+From 6dbbe28a459e79acb9e7ba44d43295df9a0f45f8 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue, 7 Jun 2011 14:17:30 +0000
+Subject: [PATCH 3/3] setup-disk: fix data-only mode with no lvm and no raid
+
+ref #678
+---
+ setup-disk.in | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/setup-disk.in b/setup-disk.in
+index 9d073ec..026e32a 100644
+--- a/setup-disk.in
++++ b/setup-disk.in
+@@ -612,8 +612,8 @@ data_only_disk_install_lvm() {
+
+ data_only_disk_install() {
+ local diskdev=
+- local var_dev=/dev/$vgname/lv_var
+- local var_part_type="8e"
++ local var_dev=
++ local var_part_type="83"
+ local swap_part_type=82
+ local size=
+ local swap_dev= var_dev=
+--
+1.7.5.4
+
diff --git a/main/alpine-conf/APKBUILD b/main/alpine-conf/APKBUILD
new file mode 100644
index 0000000000..bb86f65dad
--- /dev/null
+++ b/main/alpine-conf/APKBUILD
@@ -0,0 +1,45 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alpine-conf
+pkgver=2.8.1
+pkgrel=2
+pkgdesc="Alpine configuration management scripts"
+url=http://git.alpinelinux.org/cgit/$pkgname
+depends="openrc"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2
+ 0001-setup-xorg-base-initial-commit.patch
+ 0002-setup-gparted-desktop-new-setup-script.patch
+ 0003-setup-disk-fix-data-only-mode-with-no-lvm-and-no-rai.patch
+ "
+
+arch="all"
+license="GPL-2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make VERSION=$pkgver-r$pkgrel || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install PREFIX= DESTDIR="$pkgdir"
+ for i in commit exclude include status update; do
+ ln -s lbu "$pkgdir"/sbin/lbu_$i
+ done
+}
+md5sums="a8068da6ae47c1bc567ba215b0da6187 alpine-conf-2.8.1.tar.bz2
+f3bdd33354ae0ab3c70542de33f410d0 0001-setup-xorg-base-initial-commit.patch
+e2903187d61407c997366529ce30ea96 0002-setup-gparted-desktop-new-setup-script.patch
+cff937daddfbb63a921523618ca34da8 0003-setup-disk-fix-data-only-mode-with-no-lvm-and-no-rai.patch"
diff --git a/main/alpine-desktop/APKBUILD b/main/alpine-desktop/APKBUILD
new file mode 100644
index 0000000000..fb934611c8
--- /dev/null
+++ b/main/alpine-desktop/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alpine-desktop
+pkgver=2.0
+pkgrel=7
+pkgdesc="Meta package for Alpine Desktop"
+url="http://alpinelinux.org"
+arch="all"
+license="GPL"
+makedepends=
+depends="
+ udev
+
+ dhcpcd
+ dhcpcd-ui
+ abiword
+ audacious
+ evince
+ gpicview
+ gnumeric
+ firefox
+ lxdm
+ sudo
+ xf86-input-keyboard
+ xf86-input-mouse
+ xf86-video-vesa
+ xfce4
+ xorg-server
+ xscreensaver
+ "
+install=alpine-desktop.post-install
+subpackages=
+source=
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ return 0
+}
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"
+ return 0
+}
+
+md5sums=
diff --git a/main/alpine-desktop/alpine-desktop.post-install b/main/alpine-desktop/alpine-desktop.post-install
new file mode 100644
index 0000000000..0b52acc598
--- /dev/null
+++ b/main/alpine-desktop/alpine-desktop.post-install
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# add mousedev to /etc/modules if not already there
+
+if ! grep -w -q ^mousedev /etc/modules; then
+ echo mousedev >> /etc/modules
+fi
+modprobe mousedev || true
+
diff --git a/main/alpine-mirrors/APKBUILD b/main/alpine-mirrors/APKBUILD
new file mode 100644
index 0000000000..52055c0880
--- /dev/null
+++ b/main/alpine-mirrors/APKBUILD
@@ -0,0 +1,30 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alpine-mirrors
+pkgver=2.1.0_git20110122
+pkgrel=0
+pkgdesc="List of Alpine Linux Mirrors"
+url="http://alpinelinux.org/"
+arch="noarch"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://www.alpinelinux.org/alpine/MIRRORS.txt
+ RELEASES.txt
+ "
+
+build() {
+ return 0
+}
+
+package() {
+ install -D -m644 "$srcdir"/MIRRORS.txt \
+ "$pkgdir"/usr/share/alpine-mirrors/MIRRORS.txt
+ install -D -m644 "$srcdir"/RELEASES.txt \
+ "$pkgdir"/usr/share/alpine-mirrors/RELEASES.txt
+}
+
+md5sums="14a00f625a76ebe8e957d21abdf8b6c2 MIRRORS.txt
+4f1406540f5debe6805c14ebe8da8ca5 RELEASES.txt"
diff --git a/main/alpine-mirrors/RELEASES.txt b/main/alpine-mirrors/RELEASES.txt
new file mode 100644
index 0000000000..ec94b00f2d
--- /dev/null
+++ b/main/alpine-mirrors/RELEASES.txt
@@ -0,0 +1,2 @@
+edge
+v2.1
diff --git a/main/alpine-sdk/APKBUILD b/main/alpine-sdk/APKBUILD
new file mode 100644
index 0000000000..ddb2763140
--- /dev/null
+++ b/main/alpine-sdk/APKBUILD
@@ -0,0 +1,14 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alpine-sdk
+pkgver=0.3
+pkgrel=1
+url=http://dev.alpinelinux.org/cgit
+pkgdesc="Alpine Software Development Kit meta package"
+depends="abuild build-base git cramfs cdrkit acct mkinitfs mtools"
+arch="all"
+license="GPL-2"
+
+build() {
+ # meta package
+ mkdir -p "$pkgdir"
+}
diff --git a/main/alpine/APKBUILD b/main/alpine/APKBUILD
new file mode 100644
index 0000000000..cc2204a354
--- /dev/null
+++ b/main/alpine/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alpine
+pkgver=2.00_p84
+_ver=${pkgver%_p*}
+_pver=${pkgver##*_p}
+pkgrel=1
+pkgdesc="Text-based email client, friendly for novices but powerful"
+url="http://www.washington.edu/alpine/"
+arch="all"
+license="APACHE"
+depends=""
+makedepends="openldap-dev heimdal-dev ncurses-dev openssl-dev"
+subpackages="$pkgname-doc"
+source="ftp://ftp.cac.washington.edu/alpine/alpine.tar.bz2
+ all_p84.patch
+ CVE-2008-5514.patch"
+
+_builddir="$srcdir"/$pkgname-$_ver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --without-passfile \
+ --without-tcl \
+ --disable-shared \
+ --with-system-pinerc=/etc/alpine.d/pine.conf \
+ --with-system-fixed-pinerc=/etc/alpine.d/pine.conf.fixed
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="84e44cbf71ed674800a5d57eed9c1c52 alpine.tar.bz2
+785cea92b11d6655c183f3379468a643 all_p84.patch
+1b52a54a656979116c09fb1d948a4325 CVE-2008-5514.patch"
diff --git a/main/alpine/CVE-2008-5514.patch b/main/alpine/CVE-2008-5514.patch
new file mode 100644
index 0000000000..594bea0b25
--- /dev/null
+++ b/main/alpine/CVE-2008-5514.patch
@@ -0,0 +1,20 @@
+--- alpine-2.00/imap/src/c-client/rfc822.c
++++ alpine-2.00/imap/src/c-client/rfc822.c
+@@ -1351,6 +1351,7 @@
+
+ static long rfc822_output_char (RFC822BUFFER *buf,int c)
+ {
++ if ((buf->cur == buf->end) && !rfc822_output_flush (buf)) return NIL;
+ *buf->cur++ = c; /* add character, soutr buffer if full */
+ return (buf->cur == buf->end) ? rfc822_output_flush (buf) : LONGT;
+ }
+@@ -1374,7 +1375,8 @@
+ len -= i;
+ }
+ /* soutr buffer now if full */
+- if (len && !rfc822_output_flush (buf)) return NIL;
++ if ((len || (buf->cur == buf->end)) && !rfc822_output_flush (buf))
++ return NIL;
+ }
+ return LONGT;
+ }
diff --git a/main/alpine/all_p84.patch b/main/alpine/all_p84.patch
new file mode 100644
index 0000000000..c025fc435d
--- /dev/null
+++ b/main/alpine/all_p84.patch
@@ -0,0 +1,26592 @@
+diff -rc alpine-2.00/alpine/adrbkcmd.c alpine-2.00.I.USE/alpine/adrbkcmd.c
+*** alpine-2.00/alpine/adrbkcmd.c 2008-05-30 09:52:41.000000000 -0700
+--- alpine-2.00.I.USE/alpine/adrbkcmd.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 57,62 ****
+--- 57,64 ----
+ #include "../pith/send.h"
+ #include "../pith/list.h"
+ #include "../pith/busy.h"
++ #include "../pith/icache.h"
++ #include "../pith/osdep/color.h"
+
+
+ /* internal prototypes */
+***************
+*** 1146,1151 ****
+--- 1148,1155 ----
+ q_status_message1(SM_INFO, 0, 2, _("Address book %s cancelled"), cmd);
+ }
+ else if(editor_result & COMP_EXIT){
++ if(pico_usingcolor())
++ clear_index_cache(ps_global->mail_stream, 0);
+ removing_leading_and_trailing_white_space(nick);
+ removing_leading_and_trailing_white_space(full);
+ removing_leading_and_trailing_white_space(fcc);
+***************
+*** 4123,4128 ****
+--- 4127,4134 ----
+ * won't do anything, but will cause compose_mail to think there's
+ * already a role so that it won't try to confirm the default.
+ */
++ if (ps_global->role)
++ fs_give((void **)&ps_global->role);
+ if(role)
+ role = copy_action(role);
+ else{
+***************
+*** 4130,4135 ****
+--- 4136,4142 ----
+ memset((void *)role, 0, sizeof(*role));
+ role->nick = cpystr("Default Role");
+ }
++ ps_global->role = cpystr(role->nick);
+ }
+
+ compose_mail(addr, fcc, role, NULL, NULL);
+diff -rc alpine-2.00/alpine/alpine.c alpine-2.00.I.USE/alpine/alpine.c
+*** alpine-2.00/alpine/alpine.c 2008-06-03 15:31:05.000000000 -0700
+--- alpine-2.00.I.USE/alpine/alpine.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 193,198 ****
+--- 193,199 ----
+ #endif
+
+ status_message_lock_init();
++ inverse_itokens();
+
+ #if HAVE_SRANDOM
+ /*
+***************
+*** 293,298 ****
+--- 294,300 ----
+ exit(-1);
+ }
+
++ mail_parameters(NULL, SET_QUOTA, (void *) pine_parse_quota);
+ /* set some default timeouts in case pinerc is remote */
+ mail_parameters(NULL, SET_OPENTIMEOUT, (void *)(long)30);
+ mail_parameters(NULL, SET_READTIMEOUT, (void *)(long)15);
+***************
+*** 303,308 ****
+--- 305,311 ----
+ mail_parameters(NULL, SET_SENDCOMMAND, (void *) pine_imap_cmd_happened);
+ mail_parameters(NULL, SET_FREESTREAMSPAREP, (void *) sp_free_callback);
+ mail_parameters(NULL, SET_FREEELTSPAREP, (void *) free_pine_elt);
++ mail_parameters(NULL, SET_ERASEPASSWORD, (void *) pine_delete_pwd);
+ #ifdef SMIME
+ mail_parameters(NULL, SET_FREEBODYSPAREP, (void *) free_smime_body_sparep);
+ #endif
+***************
+*** 454,459 ****
+--- 457,467 ----
+
+ convert_args_to_utf8(pine_state, &args);
+
++ if (args.action == aaFolder && !args.data.folder &&
++ ps_global->send_immediately){
++ printf(_("No value for To: field specified\n"));
++ exit(-1);
++ }
+ if(args.action == aaFolder){
+ pine_state->beginning_of_month = first_run_of_month();
+ pine_state->beginning_of_year = first_run_of_year();
+***************
+*** 462,467 ****
+--- 470,476 ----
+ /* Set up optional for user-defined display filtering */
+ pine_state->tools.display_filter = dfilter;
+ pine_state->tools.display_filter_trigger = dfilter_trigger;
++ pine_state->tools.exec_rule = exec_function_rule;
+
+ #ifdef _WINDOWS
+ if(ps_global->install_flag){
+***************
+*** 553,558 ****
+--- 562,572 ----
+ if(F_ON(F_MAILDROPS_PRESERVE_STATE, ps_global))
+ mail_parameters(NULL, SET_SNARFPRESERVE, (void *) TRUE);
+
++ #ifndef _WINDOWS
++ mail_parameters(NULL,SET_COURIERSTYLE,
++ (void *)(F_ON(F_COURIER_FOLDER_LIST, ps_global) ? 1 : 0));
++ #endif
++
+ rvl = 0L;
+ if(pine_state->VAR_NNTPRANGE){
+ if(!SVAR_NNTPRANGE(pine_state, rvl, tmp_20k_buf, SIZEOF_20KBUF))
+***************
+*** 672,677 ****
+--- 686,692 ----
+
+
+ /*--- output side ---*/
++ if (!ps_global->send_immediately){
+ rv = config_screen(&(pine_state->ttyo));
+ #ifndef _WINDOWS /* always succeeds under _WINDOWS */
+ if(rv){
+***************
+*** 712,723 ****
+ /* initialize titlebar in case we use it */
+ set_titlebar("", NULL, NULL, NULL, NULL, 0, FolderName, 0, 0, NULL);
+
+- /*
+- * Prep storage object driver for PicoText
+- */
+- so_register_external_driver(pine_pico_get, pine_pico_give, pine_pico_writec, pine_pico_readc,
+- pine_pico_puts, pine_pico_seek, NULL, NULL);
+-
+ #ifdef DEBUG
+ if(ps_global->debug_imap > 4 || debug > 9){
+ q_status_message(SM_ORDER | SM_DING, 5, 9,
+--- 727,732 ----
+***************
+*** 725,730 ****
+--- 734,752 ----
+ flush_status_messages(0);
+ }
+ #endif
++ }
++ else{
++ fake_config_screen(&(pine_state->ttyo));
++ init_folders(pine_state); /* digest folder spec's */
++ }
++
++ /*
++ * Prep storage object driver for PicoText
++ */
++ so_register_external_driver(pine_pico_get, pine_pico_give,
++ (args.noutf8 == 0 ? pine_pico_writec : pine_pico_writec_noucs),
++ (args.noutf8 == 0 ? pine_pico_readc : pine_pico_readc_noucs),
++ (args.noutf8 == 0 ? pine_pico_puts : pine_pico_puts_noucs), pine_pico_seek, NULL, NULL);
+
+ if(args.action == aaPrcCopy || args.action == aaAbookCopy){
+ int exit_val = -1;
+***************
+*** 900,905 ****
+--- 922,933 ----
+ int len, good_addr = 1;
+ int exit_val = 0;
+ BUILDER_ARG fcc;
++ ACTION_S *role = NULL;
++
++ if (pine_state->in_init_seq && pine_state->send_immediately
++ && (char) *pine_state->initial_cmds++ == '#'
++ && ++pine_state->initial_cmds_offset)
++ role_select_screen(pine_state, &role, 1);
+
+ if(pine_state->in_init_seq){
+ pine_state->in_init_seq = pine_state->save_in_init_seq = 0;
+***************
+*** 938,944 ****
+ memset(&fcc, 0, sizeof(fcc));
+
+ if(good_addr){
+! compose_mail(addr, fcc.tptr, NULL,
+ args.data.mail.attachlist, stdin_getc);
+ }
+ else{
+--- 966,972 ----
+ memset(&fcc, 0, sizeof(fcc));
+
+ if(good_addr){
+! compose_mail(addr, fcc.tptr, role,
+ args.data.mail.attachlist, stdin_getc);
+ }
+ else{
+***************
+*** 972,977 ****
+--- 1000,1006 ----
+
+ pine_state->mail_stream = NULL;
+ pine_state->mangled_screen = 1;
++ pine_state->subject = NULL;
+
+ if(args.action == aaURL){
+ url_tool_t f;
+***************
+*** 1087,1092 ****
+--- 1116,1122 ----
+ }
+ }
+
++ if (!pine_state->send_immediately)
+ fflush(stdout);
+
+ #if !defined(_WINDOWS) && !defined(LEAVEOUTFIFO)
+***************
+*** 2975,2984 ****
+ if(i > 0){
+ ps->initial_cmds = (int *)fs_get((i+1) * sizeof(int));
+ ps->free_initial_cmds = ps->initial_cmds;
+ for(j = 0; j < i; j++)
+! ps->initial_cmds[j] = i_cmds[j];
+!
+! ps->initial_cmds[i] = 0;
+ ps->in_init_seq = ps->save_in_init_seq = 1;
+ }
+ }
+--- 3005,3019 ----
+ if(i > 0){
+ ps->initial_cmds = (int *)fs_get((i+1) * sizeof(int));
+ ps->free_initial_cmds = ps->initial_cmds;
++ ps->initial_cmds_backup = (int *)fs_get((i+1) * sizeof(int));
++ ps->free_initial_cmds_backup = ps->initial_cmds_backup;
+ for(j = 0; j < i; j++)
+! ps->initial_cmds[j] = ps->initial_cmds_backup[j] = i_cmds[j];
+! #define ctrl_x 24
+! if (i > 1)
+! ps->send_immediately = i_cmds[i - 2] == ctrl_x
+! && ((i_cmds[i - 1] == 'y') || (i_cmds[i-1] == 'Y'));
+! ps->initial_cmds[i] = ps->initial_cmds_backup[i] = 0;
+ ps->in_init_seq = ps->save_in_init_seq = 1;
+ }
+ }
+***************
+*** 3134,3139 ****
+--- 3169,3177 ----
+ extern KBESC_T *kbesc;
+
+ dprint((2, "goodnight_gracey:\n"));
++ strncpy(pine_state->cur_folder, pine_state->inbox_name,
++ sizeof(pine_state->cur_folder));
++ pine_state->cur_folder[sizeof(pine_state->cur_folder) - 1] = '\0';
+
+ /* We want to do this here before we close up the streams */
+ trim_remote_adrbks();
+diff -rc alpine-2.00/alpine/arg.c alpine-2.00.I.USE/alpine/arg.c
+*** alpine-2.00/alpine/arg.c 2008-01-04 14:49:15.000000000 -0800
+--- alpine-2.00.I.USE/alpine/arg.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 59,64 ****
+--- 59,65 ----
+ static char args_err_non_abs_passfile[] = N_("argument to \"-passfile\" should be fully-qualified");
+ #endif
+ static char args_err_missing_sort[] = N_("missing argument for option \"-sort\"");
++ static char args_err_missing_thread_sort[] = N_("missing argument for option \"-threadsort\"");
+ static char args_err_missing_flag_arg[] = N_("missing argument for flag \"%c\"");
+ static char args_err_missing_flag_num[] = N_("Non numeric argument for flag \"%c\"");
+ static char args_err_missing_debug_num[] = N_("Non numeric argument for \"%s\"");
+***************
+*** 102,112 ****
+--- 103,115 ----
+ N_(" -z \t\tSuspend - allow use of ^Z suspension"),
+ N_(" -r \t\tRestricted - can only send mail to oneself"),
+ N_(" -sort <sort>\tSort - Specify sort order of folder:"),
++ N_(" -threadsort <sort>\tSort - Specify sort order of thread index screen:"),
+ N_("\t\t\tarrival, subject, threaded, orderedsubject, date,"),
+ N_("\t\t\tfrom, size, score, to, cc, /reverse"),
+ N_(" -i\t\tIndex - Go directly to index, bypassing main menu"),
+ N_(" -I <keystroke_list> Initial keystrokes to be executed"),
+ N_(" -n <number>\tEntry in index to begin on"),
++ N_(" -noutf8\t Warns Alpine that piped input is not encoded in utf-8"),
+ N_(" -o \t\tReadOnly - Open first folder read-only"),
+ N_(" -conf\t\tConfiguration - Print out fresh global configuration. The"),
+ N_("\t\tvalues of your global configuration affect all Alpine users"),
+***************
+*** 191,196 ****
+--- 194,200 ----
+ char *cmd_list = NULL;
+ char *debug_str = NULL;
+ char *sort = NULL;
++ char *threadsort = NULL;
+ char *pinerc_file = NULL;
+ char *lc = NULL;
+ int do_help = 0;
+***************
+*** 362,367 ****
+--- 366,382 ----
+
+ goto Loop;
+ }
++ else if(strcmp(*av, "threadsort") == 0){
++ if(--ac){
++ threadsort = *++av;
++ COM_THREAD_SORT_KEY = cpystr(threadsort);
++ }
++ else{
++ display_args_err(_(args_err_missing_thread_sort), NULL, 1);
++ ++usage;
++ }
++ goto Loop;
++ }
+ else if(strcmp(*av, "url") == 0){
+ if(args->action == aaFolder && !args->data.folder){
+ args->action = aaURL;
+***************
+*** 468,473 ****
+--- 483,492 ----
+
+ goto Loop;
+ }
++ else if(strcmp(*av, "noutf8") == 0){
++ args->noutf8++;
++ goto Loop;
++ }
+ else if(strcmp(*av, "bail") == 0){
+ pine_state->exit_if_no_pinerc = 1;
+ goto Loop;
+***************
+*** 476,481 ****
+--- 495,506 ----
+ do_version = 1;
+ goto Loop;
+ }
++ else if(strcmp(*av, "subject") == 0){
++ if(--ac){
++ pine_state->subject = cpystr(*++av);
++ }
++ goto Loop;
++ }
+ #ifdef _WINDOWS
+ else if(strcmp(*av, "install") == 0){
+ pine_state->install_flag = 1;
+***************
+*** 826,839 ****
+ exit(-1);
+
+ if(do_version){
+! extern char datestamp[], hoststamp[];
+ char rev[128];
+
+! snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Alpine %s (%s %s) built %s on %s",
+ ALPINE_VERSION,
+ SYSTYPE ? SYSTYPE : "?",
+ get_alpine_revision_string(rev, sizeof(rev)),
+! datestamp, hoststamp);
+ tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
+ display_args_err(tmp_20k_buf, NULL, 0);
+ exit(0);
+--- 851,864 ----
+ exit(-1);
+
+ if(do_version){
+! extern char datestamp[], hoststamp[], plevstamp[];
+ char rev[128];
+
+! snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Alpine %s (%s %s) built %s on %s, using patchlevel %s.",
+ ALPINE_VERSION,
+ SYSTYPE ? SYSTYPE : "?",
+ get_alpine_revision_string(rev, sizeof(rev)),
+! datestamp, hoststamp, plevstamp);
+ tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
+ display_args_err(tmp_20k_buf, NULL, 0);
+ exit(0);
+diff -rc alpine-2.00/alpine/arg.h alpine-2.00.I.USE/alpine/arg.h
+*** alpine-2.00/alpine/arg.h 2006-09-22 13:06:05.000000000 -0700
+--- alpine-2.00.I.USE/alpine/arg.h 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 27,32 ****
+--- 27,33 ----
+ typedef struct argdata {
+ enum {aaFolder = 0, aaMore, aaURL, aaMail,
+ aaPrcCopy, aaAbookCopy} action;
++ int noutf8;
+ union {
+ char *folder;
+ char *file;
+diff -rc alpine-2.00/alpine/busy.c alpine-2.00.I.USE/alpine/busy.c
+*** alpine-2.00/alpine/busy.c 2007-10-15 14:02:56.000000000 -0700
+--- alpine-2.00.I.USE/alpine/busy.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 194,200 ****
+
+ add_review_message(buf, -1);
+ }
+! else{
+ q_status_message(SM_ORDER, 0, 1, progress);
+
+ /*
+--- 194,200 ----
+
+ add_review_message(buf, -1);
+ }
+! else if (!ps_global->send_immediately){
+ q_status_message(SM_ORDER, 0, 1, progress);
+
+ /*
+***************
+*** 206,213 ****
+ */
+ display_message('x');
+ }
+!
+! fflush(stdout);
+ }
+
+ /*
+--- 206,213 ----
+ */
+ display_message('x');
+ }
+! if (!ps_global->send_immediately)
+! fflush(stdout);
+ }
+
+ /*
+***************
+*** 255,261 ****
+ (*ap)->cf = done_busy_cue;
+ ap = &(*ap)->next;
+
+! start_after(a); /* launch cue handler */
+
+ #ifdef _WINDOWS
+ mswin_setcursor(MSWIN_CURSOR_BUSY);
+--- 255,262 ----
+ (*ap)->cf = done_busy_cue;
+ ap = &(*ap)->next;
+
+! if(!ps_global->send_immediately)
+! start_after(a); /* launch cue handler */
+
+ #ifdef _WINDOWS
+ mswin_setcursor(MSWIN_CURSOR_BUSY);
+***************
+*** 404,409 ****
+--- 405,415 ----
+ {
+ int space_left, slots_used;
+
++ if (ps_global->send_immediately){
++ mark_status_dirty();
++ return;
++ }
++
+ if(final_message && final_message_pri >= 0){
+ char progress[MAX_SCREEN_COLS+1];
+
+diff -rc alpine-2.00/alpine/colorconf.c alpine-2.00.I.USE/alpine/colorconf.c
+*** alpine-2.00/alpine/colorconf.c 2008-02-08 10:39:55.000000000 -0800
+--- alpine-2.00.I.USE/alpine/colorconf.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 28,33 ****
+--- 28,34 ----
+ #include "../pith/color.h"
+ #include "../pith/icache.h"
+ #include "../pith/mailcmd.h"
++ #include "../pith/mailindx.h"
+ #include "../pith/list.h"
+
+
+***************
+*** 39,45 ****
+ SAVED_CONFIG_S *save_color_config_vars(struct pine *);
+ void free_saved_color_config(struct pine *, SAVED_CONFIG_S **);
+ void color_config_init_display(struct pine *, CONF_S **, CONF_S **);
+! void add_header_color_line(struct pine *, CONF_S **, char *, int);
+ int is_rgb_color(char *);
+ char *new_color_line(char *, int, int, int);
+ int color_text_tool(struct pine *, int, CONF_S **, unsigned);
+--- 40,46 ----
+ SAVED_CONFIG_S *save_color_config_vars(struct pine *);
+ void free_saved_color_config(struct pine *, SAVED_CONFIG_S **);
+ void color_config_init_display(struct pine *, CONF_S **, CONF_S **);
+! void add_header_color_line(struct pine *, CONF_S **, char *, int, int);
+ int is_rgb_color(char *);
+ char *new_color_line(char *, int, int, int);
+ int color_text_tool(struct pine *, int, CONF_S **, unsigned);
+***************
+*** 141,147 ****
+ if((v && v->name &&
+ srchstr(v->name, "-foreground-color") &&
+ pvalfg && pvalfg[0] && pvalbg && pvalbg[0]) ||
+! (v == &ps->vars[V_VIEW_HDR_COLORS] || v == &ps->vars[V_KW_COLORS]))
+ ret = SAMP1;
+
+ return(ret);
+--- 142,149 ----
+ if((v && v->name &&
+ srchstr(v->name, "-foreground-color") &&
+ pvalfg && pvalfg[0] && pvalbg && pvalbg[0]) ||
+! (v == &ps->vars[V_INDEX_TOKEN_COLORS] ||
+! v == &ps->vars[V_VIEW_HDR_COLORS] || v == &ps->vars[V_KW_COLORS]))
+ ret = SAMP1;
+
+ return(ret);
+***************
+*** 486,491 ****
+--- 488,513 ----
+ }
+
+ /*
++ * custom index tokens colors
++ */
++ vtmp = &ps->vars[V_INDEX_TOKEN_COLORS];
++ lval = LVAL(vtmp, ew);
++
++ if(lval && lval[0] && lval[0][0]){
++ for(i = 0; lval && lval[i]; i++)
++ add_header_color_line(ps, ctmp, lval[i], i, V_INDEX_TOKEN_COLORS);
++ }
++ else{
++ new_confline(ctmp); /* Blank line */
++ (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE;
++ new_confline(ctmp);
++ (*ctmp)->help = NO_HELP;
++ (*ctmp)->flags |= CF_NOSELECT;
++ (*ctmp)->value = cpystr(_(ADDINDEXTOKEN_COMMENT));
++ (*ctmp)->valoffset = COLOR_INDENT;
++ }
++
++ /*
+ * custom header colors
+ */
+ new_confline(ctmp); /* Blank line */
+***************
+*** 497,503 ****
+ new_confline(ctmp);
+ (*ctmp)->help = NO_HELP;
+ (*ctmp)->flags |= CF_NOSELECT;
+! (*ctmp)->value = cpystr(_("HEADER COLORS"));
+ new_confline(ctmp);
+ (*ctmp)->help = NO_HELP;
+ (*ctmp)->flags |= CF_NOSELECT;
+--- 519,525 ----
+ new_confline(ctmp);
+ (*ctmp)->help = NO_HELP;
+ (*ctmp)->flags |= CF_NOSELECT;
+! (*ctmp)->value = cpystr(_(HDR_COLORS));
+ new_confline(ctmp);
+ (*ctmp)->help = NO_HELP;
+ (*ctmp)->flags |= CF_NOSELECT;
+***************
+*** 526,532 ****
+
+ if(lval && lval[0] && lval[0][0]){
+ for(i = 0; lval && lval[i]; i++)
+! add_header_color_line(ps, ctmp, lval[i], i);
+ }
+ else{
+ new_confline(ctmp); /* Blank line */
+--- 548,554 ----
+
+ if(lval && lval[0] && lval[0][0]){
+ for(i = 0; lval && lval[i]; i++)
+! add_header_color_line(ps, ctmp, lval[i], i, V_VIEW_HDR_COLORS);
+ }
+ else{
+ new_confline(ctmp); /* Blank line */
+***************
+*** 696,701 ****
+--- 718,724 ----
+ char **lval, *ret = "";
+
+ if(var == &ps_global->vars[V_VIEW_HDR_COLORS]
++ || var == &ps_global->vars[V_INDEX_TOKEN_COLORS]
+ || var == &ps_global->vars[V_KW_COLORS]){
+ norm = (LVAL(var, Main) != NULL);
+ exc = (LVAL(var, ps_global->ew_for_except_vars) != NULL);
+***************
+*** 722,736 ****
+
+
+ void
+! add_header_color_line(struct pine *ps, CONF_S **ctmp, char *val, int which)
+ {
+ struct variable *vtmp;
+ SPEC_COLOR_S *hc;
+ char tmp[100+1];
+ int l;
+
+! vtmp = &ps->vars[V_VIEW_HDR_COLORS];
+! l = strlen(HEADER_WORD);
+
+ /* Blank line */
+ new_confline(ctmp);
+--- 745,765 ----
+
+
+ void
+! add_header_color_line(struct pine *ps, CONF_S **ctmp, char *val, int which, int varnum)
+ {
+ struct variable *vtmp;
+ SPEC_COLOR_S *hc;
+ char tmp[100+1];
+ int l;
+
+! hc = spec_color_from_var(val, 0);
+! if(varnum == V_INDEX_TOKEN_COLORS){
+! if(hc == NULL || hc->spec == NULL
+! || itoktype(hc->spec, FOR_INDEX) == NULL)
+! return;
+! }
+! vtmp = &ps->vars[varnum];
+! l = strlen(varnum == V_VIEW_HDR_COLORS ? HEADER_WORD : TOKEN_WORD);
+
+ /* Blank line */
+ new_confline(ctmp);
+***************
+*** 748,754 ****
+ /* which is an index into the variable list */
+ (*ctmp)->varmem = CFC_SET_COLOR(which, 0);
+
+- hc = spec_color_from_var(val, 0);
+ if(hc && hc->inherit)
+ (*ctmp)->flags = (CF_NOSELECT | CF_INHERIT);
+ else{
+--- 777,782 ----
+***************
+*** 759,765 ****
+ * with all this. It probably doesn't happen in real life.
+ */
+ utf8_snprintf(tmp, sizeof(tmp), "%s%c%.*w Color%*w %s%s",
+! HEADER_WORD,
+ (hc && hc->spec) ? (islower((unsigned char)hc->spec[0])
+ ? toupper((unsigned char)hc->spec[0])
+ : hc->spec[0]) : '?',
+--- 787,793 ----
+ * with all this. It probably doesn't happen in real life.
+ */
+ utf8_snprintf(tmp, sizeof(tmp), "%s%c%.*w Color%*w %s%s",
+! (varnum == V_VIEW_HDR_COLORS ? HEADER_WORD : TOKEN_WORD),
+ (hc && hc->spec) ? (islower((unsigned char)hc->spec[0])
+ ? toupper((unsigned char)hc->spec[0])
+ : hc->spec[0]) : '?',
+***************
+*** 1139,1144 ****
+--- 1167,1173 ----
+ return(var && var->name &&
+ (srchstr(var->name, "-foreground-color") ||
+ srchstr(var->name, "-background-color") ||
++ var == &ps->vars[V_INDEX_TOKEN_COLORS] ||
+ var == &ps->vars[V_VIEW_HDR_COLORS] ||
+ var == &ps->vars[V_KW_COLORS]));
+ }
+***************
+*** 1395,1400 ****
+--- 1424,1430 ----
+ if(hcolors)
+ free_spec_colors(&hcolors);
+
++ fix_side_effects(ps, (*cl)->var, 0);
+ set_current_color_vals(ps);
+ ClearScreen();
+ rv = ps->mangled_screen = 1;
+***************
+*** 1803,1808 ****
+--- 1833,1839 ----
+ /* get rid of all user set colors */
+ for(v = ps->vars; v->name; v++){
+ if(!color_holding_var(ps, v)
++ || v == &ps->vars[V_INDEX_TOKEN_COLORS]
+ || v == &ps->vars[V_VIEW_HDR_COLORS]
+ || v == &ps->vars[V_KW_COLORS])
+ continue;
+***************
+*** 1856,1861 ****
+--- 1887,1930 ----
+ free_spec_colors(&hcolors);
+ }
+
++ /* same for index token colors */
++ alval = ALVAL(&ps->vars[V_INDEX_TOKEN_COLORS], ew);
++ if(alval && *alval){
++ SPEC_COLOR_S *global_hcolors = NULL, *hcg;
++
++ v = &ps->vars[V_INDEX_TOKEN_COLORS];
++ if(v->global_val.l && v->global_val.l[0])
++ global_hcolors = spec_colors_from_varlist(v->global_val.l, 0);
++
++ hcolors = spec_colors_from_varlist(*alval, 0);
++ for(hc = hcolors; hc; hc = hc->next){
++ if(hc->fg)
++ fs_give((void **)&hc->fg);
++ if(hc->bg)
++ fs_give((void **)&hc->bg);
++
++ for(hcg = global_hcolors; hcg; hcg = hcg->next){
++ if(hc->spec && hcg->spec && !strucmp(hc->spec, hcg->spec)){
++ hc->fg = hcg->fg;
++ hcg->fg = NULL;
++ hc->bg = hcg->bg;
++ hcg->bg = NULL;
++ if(hc->val && !hcg->val)
++ fs_give((void **) &hc->val);
++ }
++ }
++
++ if(global_hcolors)
++ free_spec_colors(&global_hcolors);
++ }
++
++ free_list_array(alval);
++ *alval = varlist_from_spec_colors(hcolors);
++
++ if(hcolors)
++ free_spec_colors(&hcolors);
++ }
++
+ /*
+ * Same for keyword colors.
+ */
+***************
+*** 1898,1912 ****
+ rv = 1;
+ break;
+
+ case MC_ADD : /* add custom header color */
+ /* get header field name */
+ help = NO_HELP;
+ while(1){
+ i = optionally_enter(sval, -FOOTER_ROWS(ps), 0, sizeof(sval),
+! _("Enter the name of the header field to be added: "),
+ NULL, help, NULL);
+! if(i == 0)
+ break;
+ else if(i == 1){
+ cmd_cancelled("Add");
+ cancel = 1;
+--- 1967,1989 ----
+ rv = 1;
+ break;
+
++ case MC_ADDHEADER: /* add custom index token color */
+ case MC_ADD : /* add custom header color */
+ /* get header field name */
+ help = NO_HELP;
+ while(1){
+ i = optionally_enter(sval, -FOOTER_ROWS(ps), 0, sizeof(sval),
+! (cmd == MC_ADD ? _("Enter the name of the header field to be added: ")
+! : _("Enter the name of the index token to be added: ")),
+ NULL, help, NULL);
+! if(i == 0){
+! if(cmd == MC_ADDHEADER && itoktype(sval, FOR_INDEX) == NULL){
+! q_status_message1(SM_ORDER, 1, 3,
+! _("token \"%s\" not recognized"), sval);
+! continue;
+! }
+ break;
++ }
+ else if(i == 1){
+ cmd_cancelled("Add");
+ cancel = 1;
+***************
+*** 1937,1943 ****
+ confline = var_from_spec_color(new_hcolor);
+
+ /* add it to end of list */
+! alval = ALVAL(&ps->vars[V_VIEW_HDR_COLORS], ew);
+ if(alval){
+ /* get rid of possible empty value first */
+ if((t = *alval) && t[0] && !t[0][0] && !(t+1)[0])
+--- 2014,2020 ----
+ confline = var_from_spec_color(new_hcolor);
+
+ /* add it to end of list */
+! alval = ALVAL(&ps->vars[(cmd == MC_ADD ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS)], ew);
+ if(alval){
+ /* get rid of possible empty value first */
+ if((t = *alval) && t[0] && !t[0][0] && !(t+1)[0])
+***************
+*** 1962,1968 ****
+ ;
+
+ /* back up to the KEYWORD COLORS title line */
+! for(; ctmp && (!ctmp->value || strcmp(ctmp->value, KW_COLORS_HDR))
+ && ctmp->prev;
+ ctmp = prev_confline(ctmp))
+ ;
+--- 2039,2045 ----
+ ;
+
+ /* back up to the KEYWORD COLORS title line */
+! for(; ctmp && (!ctmp->value || strcmp(ctmp->value, (cmd == MC_ADD ? KW_COLORS_HDR : HDR_COLORS)))
+ && ctmp->prev;
+ ctmp = prev_confline(ctmp))
+ ;
+***************
+*** 2000,2006 ****
+ free_conflines(&beg);
+ }
+
+! add_header_color_line(ps, cl, confline, i);
+
+ /* be sure current is on selectable line */
+ for(; *cl && ((*cl)->flags & CF_NOSELECT); *cl = next_confline(*cl))
+--- 2077,2084 ----
+ free_conflines(&beg);
+ }
+
+! add_header_color_line(ps, cl, confline, i, cmd == MC_ADD
+! ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS);
+
+ /* be sure current is on selectable line */
+ for(; *cl && ((*cl)->flags & CF_NOSELECT); *cl = next_confline(*cl))
+***************
+*** 2012,2024 ****
+ break;
+
+ case MC_DELETE : /* delete custom header color */
+! if((*cl)->var != &ps->vars[V_VIEW_HDR_COLORS]){
+ q_status_message(SM_ORDER, 0, 2,
+ _("Can't delete this color setting"));
+ break;
+ }
+
+! if(want_to(_("Really delete header color from config"),
+ 'y', 'n', NO_HELP, WT_NORM) != 'y'){
+ cmd_cancelled("Delete");
+ return(rv);
+--- 2090,2105 ----
+ break;
+
+ case MC_DELETE : /* delete custom header color */
+! if((*cl)->var != &ps->vars[V_VIEW_HDR_COLORS]
+! && (*cl)->var != &ps->vars[V_INDEX_TOKEN_COLORS]){
+ q_status_message(SM_ORDER, 0, 2,
+ _("Can't delete this color setting"));
+ break;
+ }
+
+! if(want_to(((*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
+! ? _("Really delete header color from config")
+! : _("Really delete index token color from config")),
+ 'y', 'n', NO_HELP, WT_NORM) != 'y'){
+ cmd_cancelled("Delete");
+ return(rv);
+***************
+*** 2054,2072 ****
+ another = 0;
+ /* reset current line */
+ if(end && end->next && end->next->next &&
+! end->next->next->var == &ps->vars[V_VIEW_HDR_COLORS]){
+ *cl = end->next->next; /* next Header Color */
+ another++;
+ }
+ else if(beg && beg->prev &&
+! beg->prev->var == &ps->vars[V_VIEW_HDR_COLORS]){
+ *cl = beg->prev; /* prev Header Color */
+ another++;
+ }
+
+ /* adjust SPEC_COLOR_S index (varmem) values */
+ for(ctmp = end; ctmp; ctmp = next_confline(ctmp))
+! if(ctmp->var == &ps->vars[V_VIEW_HDR_COLORS])
+ ctmp->varmem = CFC_ICUST_DEC(ctmp);
+
+ /*
+--- 2135,2156 ----
+ another = 0;
+ /* reset current line */
+ if(end && end->next && end->next->next &&
+! end->next->next->var == &ps->vars[(*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
+! ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS]){
+ *cl = end->next->next; /* next Header Color */
+ another++;
+ }
+ else if(beg && beg->prev &&
+! beg->prev->var == &ps->vars[(*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
+! ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS]){
+ *cl = beg->prev; /* prev Header Color */
+ another++;
+ }
+
+ /* adjust SPEC_COLOR_S index (varmem) values */
+ for(ctmp = end; ctmp; ctmp = next_confline(ctmp))
+! if(ctmp->var == &ps->vars[(*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
+! ? V_VIEW_HDR_COLORS : V_INDEX_TOKEN_COLORS])
+ ctmp->varmem = CFC_ICUST_DEC(ctmp);
+
+ /*
+***************
+*** 2098,2104 ****
+
+ end->flags = CF_NOSELECT;
+ end->help = NO_HELP;
+! end->value = cpystr(_(ADDHEADER_COMMENT));
+ end->valoffset = COLOR_INDENT;
+ end->varnamep = NULL;
+ end->varmem = 0;
+--- 2182,2189 ----
+
+ end->flags = CF_NOSELECT;
+ end->help = NO_HELP;
+! end->value = cpystr((*cl)->var == &ps->vars[V_VIEW_HDR_COLORS]
+! ? _(ADDHEADER_COMMENT) : _(ADDINDEXTOKEN_COMMENT));
+ end->valoffset = COLOR_INDENT;
+ end->varnamep = NULL;
+ end->varmem = 0;
+***************
+*** 2556,2562 ****
+ OPT_SCREEN_S screen, *saved_screen;
+ CONF_S *ctmp = NULL, *first_line = NULL, *ctmpb;
+ int rv, is_index = 0, is_hdrcolor = 0, indent = 12;
+! int is_general = 0, is_keywordcol = 0;
+ char tmp[1200+1], name[1200], *p;
+ struct variable *vtmp, v;
+ int i, def;
+--- 2641,2647 ----
+ OPT_SCREEN_S screen, *saved_screen;
+ CONF_S *ctmp = NULL, *first_line = NULL, *ctmpb;
+ int rv, is_index = 0, is_hdrcolor = 0, indent = 12;
+! int is_general = 0, is_keywordcol = 0, is_idxtokcol = 0;
+ char tmp[1200+1], name[1200], *p;
+ struct variable *vtmp, v;
+ int i, def;
+***************
+*** 2567,2572 ****
+--- 2652,2659 ----
+ vtmp = (*cl)->var;
+ if(vtmp == &ps->vars[V_VIEW_HDR_COLORS])
+ is_hdrcolor++;
++ else if(vtmp == &ps->vars[V_INDEX_TOKEN_COLORS])
++ is_idxtokcol++;
+ else if(vtmp == &ps->vars[V_KW_COLORS])
+ is_keywordcol++;
+ else if(color_holding_var(ps, vtmp)){
+***************
+*** 2618,2623 ****
+--- 2705,2728 ----
+ name[i] = toupper((unsigned char) name[i]);
+ }
+ }
++ else if(is_idxtokcol){
++ char **lval;
++
++ lval = LVAL(vtmp, ew);
++ hcolors = spec_colors_from_varlist(lval, 0);
++
++ for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
++ if(CFC_ICUST(*cl) == i)
++ break;
++
++ if(hc){
++ snprintf(name, sizeof(name), "%s%s", TOKEN_WORD, hc->spec);
++ name[sizeof(name)-1] = '\0';
++ i = sizeof(TOKEN_WORD) - 1;
++ if(islower((unsigned char) name[i]))
++ name[i] = toupper((unsigned char) name[i]);
++ }
++ }
+ else if(is_keywordcol){
+ char **lval;
+
+***************
+*** 2663,2669 ****
+ ctmp->flags |= (CF_STARTITEM | CF_NOSELECT);
+ ctmp->keymenu = &color_changing_keymenu;
+
+! if(is_hdrcolor){
+ char **apval;
+
+ def = !(hc && hc->fg && hc->fg[0] && hc->bg && hc->bg[0]);
+--- 2768,2774 ----
+ ctmp->flags |= (CF_STARTITEM | CF_NOSELECT);
+ ctmp->keymenu = &color_changing_keymenu;
+
+! if(is_hdrcolor || is_idxtokcol){
+ char **apval;
+
+ def = !(hc && hc->fg && hc->fg[0] && hc->bg && hc->bg[0]);
+diff -rc alpine-2.00/alpine/colorconf.h alpine-2.00.I.USE/alpine/colorconf.h
+*** alpine-2.00/alpine/colorconf.h 2007-08-16 15:25:10.000000000 -0700
+--- alpine-2.00.I.USE/alpine/colorconf.h 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 23,30 ****
+--- 23,33 ----
+
+
+ #define HEADER_WORD "Header "
++ #define TOKEN_WORD "Index Token "
+ #define KW_COLORS_HDR "KEYWORD COLORS"
++ #define HDR_COLORS "HEADER COLORS"
+ #define ADDHEADER_COMMENT N_("[ Use the AddHeader command to add colored headers in MESSAGE TEXT screen ]")
++ #define ADDINDEXTOKEN_COMMENT N_("[ Use the IndxHdr command to add colored tokens in MESSAGE INDEX screen ]")
+ #define EQ_COL 37
+
+ #define SPACE_BETWEEN_DOUBLEVARS 3
+diff -rc alpine-2.00/alpine/confscroll.c alpine-2.00.I.USE/alpine/confscroll.c
+*** alpine-2.00/alpine/confscroll.c 2008-08-21 15:14:45.000000000 -0700
+--- alpine-2.00.I.USE/alpine/confscroll.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 50,55 ****
+--- 50,56 ----
+ #include "../pith/tempfile.h"
+ #include "../pith/pattern.h"
+ #include "../pith/charconv/utf8.h"
++ #include "../pith/rules.h"
+
+
+ #define CONFIG_SCREEN_HELP_TITLE _("HELP FOR SETUP CONFIGURATION")
+***************
+*** 138,144 ****
+ char *radio_pretty_value(struct pine *, CONF_S *);
+ char *sigfile_pretty_value(struct pine *, CONF_S *);
+ char *color_pretty_value(struct pine *, CONF_S *);
+! char *sort_pretty_value(struct pine *, CONF_S *);
+ int longest_feature_name(void);
+ COLOR_PAIR *sample_color(struct pine *, struct variable *);
+ COLOR_PAIR *sampleexc_color(struct pine *, struct variable *);
+--- 139,145 ----
+ char *radio_pretty_value(struct pine *, CONF_S *);
+ char *sigfile_pretty_value(struct pine *, CONF_S *);
+ char *color_pretty_value(struct pine *, CONF_S *);
+! char *sort_pretty_value(struct pine *, CONF_S *, int);
+ int longest_feature_name(void);
+ COLOR_PAIR *sample_color(struct pine *, struct variable *);
+ COLOR_PAIR *sampleexc_color(struct pine *, struct variable *);
+***************
+*** 286,292 ****
+ CONF_S *ctmp;
+
+ if(!(cl && *cl &&
+! ((*cl)->var == &ps->vars[V_SORT_KEY] ||
+ standard_radio_var(ps, (*cl)->var) ||
+ (*cl)->var == startup_ptr)))
+ return;
+--- 287,294 ----
+ CONF_S *ctmp;
+
+ if(!(cl && *cl &&
+! (((*cl)->var == &ps->vars[V_SORT_KEY]) ||
+! ((*cl)->var == &ps->vars[V_THREAD_SORT_KEY]) ||
+ standard_radio_var(ps, (*cl)->var) ||
+ (*cl)->var == startup_ptr)))
+ return;
+***************
+*** 462,468 ****
+ char tmp[MAXPATH+1];
+ char *utf8str;
+ UCS ch = 'x';
+! int cmd, i, j, done = 0, changes = 0;
+ int retval = 0;
+ int km_popped = 0, stay_in_col = 0;
+ struct key_menu *km = NULL;
+--- 464,470 ----
+ char tmp[MAXPATH+1];
+ char *utf8str;
+ UCS ch = 'x';
+! int cmd, i, j, k = 1, done = 0, changes = 0;
+ int retval = 0;
+ int km_popped = 0, stay_in_col = 0;
+ struct key_menu *km = NULL;
+***************
+*** 491,499 ****
+--- 493,504 ----
+
+ opt_screen = screen;
+ ps->mangled_screen = 1;
++ ps->resize_for_pico= 0;
+ ps->redrawer = option_screen_redrawer;
+
+ while(!done){
++ if(ps->resize_for_pico)
++ ps->mangled_screen = ps->resize_for_pico;
+ ps->user_says_cancel = 0;
+ if(km_popped){
+ km_popped--;
+***************
+*** 507,516 ****
+ ps->mangled_header = 1;
+ ps->mangled_footer = 1;
+ ps->mangled_body = 1;
+! ps->mangled_screen = 0;
+ }
+
+ /*----------- Check for new mail -----------*/
+ if(new_mail(0, NM_TIMING(ch), NM_STATUS_MSG | NM_DEFER_SORT) >= 0)
+ ps->mangled_header = 1;
+
+--- 512,522 ----
+ ps->mangled_header = 1;
+ ps->mangled_footer = 1;
+ ps->mangled_body = 1;
+! ps->mangled_screen = ps->resize_for_pico = 0;
+ }
+
+ /*----------- Check for new mail -----------*/
++ if (!ps->send_immediately){
+ if(new_mail(0, NM_TIMING(ch), NM_STATUS_MSG | NM_DEFER_SORT) >= 0)
+ ps->mangled_header = 1;
+
+***************
+*** 540,545 ****
+--- 546,552 ----
+ mark_status_unknown();
+ }
+
++ } /* send_immediately */
+ if(ps->mangled_footer || km != screen->current->keymenu){
+ bitmap_t bitmap;
+
+***************
+*** 611,616 ****
+--- 618,624 ----
+ }
+ }
+
++ if(!ps_global->send_immediately){
+ MoveCursor(cursor_pos.row, cursor_pos.col);
+ #ifdef MOUSE
+ mouse_in_content(KEY_MOUSE, -1, -1, 0, 0); /* prime the handler */
+***************
+*** 629,634 ****
+--- 637,650 ----
+ #ifdef _WINDOWS
+ mswin_setscrollcallback(NULL);
+ #endif
++ } /* send_immediately */
++
++ if (ps->send_immediately){
++ ps_global->dont_use_init_cmds = 0;
++ process_config_input(&ch);
++ if (ch == '\030') /* ^X, bye */
++ goto end;
++ }
+
+ cmd = menu_command(ch, km);
+
+***************
+*** 1382,1388 ****
+ break;
+ }
+ }
+!
+ screen->current = first_confline(screen->current);
+ free_conflines(&screen->current);
+ return(retval);
+--- 1398,1404 ----
+ break;
+ }
+ }
+! end:
+ screen->current = first_confline(screen->current);
+ free_conflines(&screen->current);
+ return(retval);
+***************
+*** 2426,2431 ****
+--- 2442,2450 ----
+ * Now go and set the current_val based on user_val changes
+ * above. Turn off command line settings...
+ */
++ set_current_val((*cl)->var,
++ (strcmp((*cl)->var->name,"key-definition-rules") ? TRUE : FALSE),
++ FALSE);
+ set_current_val((*cl)->var, TRUE, FALSE);
+ fix_side_effects(ps, (*cl)->var, 0);
+
+***************
+*** 2922,2928 ****
+ }
+
+ set_current_val((*cl)->var, TRUE, TRUE);
+! if(decode_sort(ps->VAR_SORT_KEY, &def_sort, &def_sort_rev) != -1){
+ ps->def_sort = def_sort;
+ ps->def_sort_rev = def_sort_rev;
+ }
+--- 2941,2947 ----
+ }
+
+ set_current_val((*cl)->var, TRUE, TRUE);
+! if(decode_sort(ps->VAR_SORT_KEY, &def_sort, &def_sort_rev,0) != -1){
+ ps->def_sort = def_sort;
+ ps->def_sort_rev = def_sort_rev;
+ }
+***************
+*** 2931,2936 ****
+--- 2950,2986 ----
+ ps->mangled_body = 1; /* BUG: redraw it all for now? */
+ rv = 1;
+ }
++ else if((*cl)->var == &ps->vars[V_THREAD_SORT_KEY]){
++ SortOrder thread_def_sort;
++ int thread_def_sort_rev;
++
++ thread_def_sort_rev = (*cl)->varmem >= (short) EndofList;
++ thread_def_sort = (SortOrder) ((*cl)->varmem - (thread_def_sort_rev
++ * EndofList));
++ sprintf(tmp_20k_buf, "%s%s", sort_name(thread_def_sort),
++ (thread_def_sort_rev) ? "/Reverse" : "");
++
++ if((*cl)->var->cmdline_val.p)
++ fs_give((void **)&(*cl)->var->cmdline_val.p);
++
++ if(apval){
++ if(*apval)
++ fs_give((void **)apval);
++
++ *apval = cpystr(tmp_20k_buf);
++ }
++
++ set_current_val((*cl)->var, TRUE, TRUE);
++ if(decode_sort(ps->VAR_THREAD_SORT_KEY, &thread_def_sort,
++ &thread_def_sort_rev, 1) != -1){
++ ps->thread_def_sort = thread_def_sort;
++ ps->thread_def_sort_rev = thread_def_sort_rev;
++ }
++
++ set_radio_pretty_vals(ps, cl);
++ ps->mangled_body = 1; /* BUG: redraw it all for now? */
++ rv = 1;
++ }
+ else
+ q_status_message(SM_ORDER | SM_DING, 3, 6,
+ "Programmer botch! Unknown radiobutton type.");
+***************
+*** 3369,3375 ****
+ ptr = sample;
+
+ /* then the color sample */
+! if(ctmp->var == &ps->vars[V_VIEW_HDR_COLORS]){
+ SPEC_COLOR_S *hc, *hcolors;
+
+ lastc = newc = NULL;
+--- 3419,3426 ----
+ ptr = sample;
+
+ /* then the color sample */
+! if(ctmp->var == &ps->vars[V_VIEW_HDR_COLORS]
+! || ctmp->var == &ps->vars[V_INDEX_TOKEN_COLORS]){
+ SPEC_COLOR_S *hc, *hcolors;
+
+ lastc = newc = NULL;
+***************
+*** 3787,3793 ****
+ else if(standard_radio_var(ps, v) || v == startup_ptr)
+ return(radio_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_SORT_KEY])
+! return(sort_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_SIGNATURE_FILE])
+ return(sigfile_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_USE_ONLY_DOMAIN_NAME])
+--- 3838,3846 ----
+ else if(standard_radio_var(ps, v) || v == startup_ptr)
+ return(radio_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_SORT_KEY])
+! return(sort_pretty_value(ps, cl, 0));
+! else if(v == &ps->vars[V_THREAD_SORT_KEY])
+! return(sort_pretty_value(ps, cl, 1));
+ else if(v == &ps->vars[V_SIGNATURE_FILE])
+ return(sigfile_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_USE_ONLY_DOMAIN_NAME])
+***************
+*** 4318,4331 ****
+
+
+ char *
+! sort_pretty_value(struct pine *ps, CONF_S *cl)
+ {
+! return(generalized_sort_pretty_value(ps, cl, 1));
+ }
+
+
+ char *
+! generalized_sort_pretty_value(struct pine *ps, CONF_S *cl, int default_ok)
+ {
+ char tmp[6*MAXPATH];
+ char *pvalnorm, *pvalexc, *pval;
+--- 4371,4384 ----
+
+
+ char *
+! sort_pretty_value(struct pine *ps, CONF_S *cl, int thread)
+ {
+! return(generalized_sort_pretty_value(ps, cl, 1, thread));
+ }
+
+
+ char *
+! generalized_sort_pretty_value(struct pine *ps, CONF_S *cl, int default_ok, int thread)
+ {
+ char tmp[6*MAXPATH];
+ char *pvalnorm, *pvalexc, *pval;
+***************
+*** 4375,4381 ****
+ }
+ else if(fixed){
+ pval = v->fixed_val.p;
+! decode_sort(pval, &var_sort, &var_sort_rev);
+ is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort);
+
+ utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s",
+--- 4428,4434 ----
+ }
+ else if(fixed){
+ pval = v->fixed_val.p;
+! decode_sort(pval, &var_sort, &var_sort_rev, thread);
+ is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort);
+
+ utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s",
+***************
+*** 4386,4394 ****
+ is_the_one ? " (value is fixed)" : "");
+ }
+ else if(is_set_for_this_level){
+! decode_sort(pval, &var_sort, &var_sort_rev);
+ is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort);
+! decode_sort(pvalexc, &exc_sort, &exc_sort_rev);
+ the_exc_one = (editing_normal_which_isnt_except && pvalexc &&
+ exc_sort_rev == line_sort_rev && exc_sort == line_sort);
+ utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s",
+--- 4439,4447 ----
+ is_the_one ? " (value is fixed)" : "");
+ }
+ else if(is_set_for_this_level){
+! decode_sort(pval, &var_sort, &var_sort_rev, thread);
+ is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort);
+! decode_sort(pvalexc, &exc_sort, &exc_sort_rev, thread);
+ the_exc_one = (editing_normal_which_isnt_except && pvalexc &&
+ exc_sort_rev == line_sort_rev && exc_sort == line_sort);
+ utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s",
+***************
+*** 4406,4412 ****
+ }
+ else{
+ if(pvalexc){
+! decode_sort(pvalexc, &exc_sort, &exc_sort_rev);
+ is_the_one = (exc_sort_rev == line_sort_rev &&
+ exc_sort == line_sort);
+ utf8_snprintf(tmp, sizeof(tmp), "( ) %s%-*w%*s%s",
+--- 4459,4465 ----
+ }
+ else{
+ if(pvalexc){
+! decode_sort(pvalexc, &exc_sort, &exc_sort_rev, thread);
+ is_the_one = (exc_sort_rev == line_sort_rev &&
+ exc_sort == line_sort);
+ utf8_snprintf(tmp, sizeof(tmp), "( ) %s%-*w%*s%s",
+***************
+*** 4417,4423 ****
+ }
+ else{
+ pval = v->current_val.p;
+! decode_sort(pval, &var_sort, &var_sort_rev);
+ is_the_one = ((pval || default_ok) &&
+ var_sort_rev == line_sort_rev &&
+ var_sort == line_sort);
+--- 4470,4476 ----
+ }
+ else{
+ pval = v->current_val.p;
+! decode_sort(pval, &var_sort, &var_sort_rev, thread);
+ is_the_one = ((pval || default_ok) &&
+ var_sort_rev == line_sort_rev &&
+ var_sort == line_sort);
+***************
+*** 5154,5159 ****
+--- 5207,5236 ----
+ var == &ps->vars[V_ABOOK_FORMATS]){
+ addrbook_reset();
+ }
++ else if(var == &ps->vars[V_INDEX_RULES]){
++ if(ps_global->rule_list)
++ free_parsed_rule_list(&ps_global->rule_list);
++ create_rule_list(ps->vars);
++ reset_index_format();
++ clear_index_cache(ps->mail_stream, 0);
++ }
++ else if(var == &ps->vars[V_COMPOSE_RULES] ||
++ var == &ps->vars[V_FORWARD_RULES] ||
++ var == &ps->vars[V_KEY_RULES] ||
++ var == &ps->vars[V_REPLACE_RULES] ||
++ var == &ps->vars[V_REPLY_INDENT_RULES] ||
++ var == &ps->vars[V_REPLY_LEADIN_RULES] ||
++ var == &ps->vars[V_RESUB_RULES] ||
++ var == &ps->vars[V_SAVE_RULES] ||
++ var == &ps->vars[V_SMTP_RULES] ||
++ var == &ps->vars[V_SORT_RULES] ||
++ var == &ps->vars[V_STARTUP_RULES] ||
++ var == &ps->vars[V_THREAD_DISP_STYLE_RULES] ||
++ var == &ps->vars[V_THREAD_INDEX_STYLE_RULES]){
++ if(ps_global->rule_list)
++ free_parsed_rule_list(&ps_global->rule_list);
++ create_rule_list(ps->vars);
++ }
+ else if(var == &ps->vars[V_INDEX_FORMAT]){
+ reset_index_format();
+ clear_index_cache(ps->mail_stream, 0);
+***************
+*** 5176,5181 ****
+--- 5253,5261 ----
+
+ clear_index_cache(ps->mail_stream, 0);
+ }
++ else if(var == &ps->vars[V_SPECIAL_TEXT]){
++ regex_pattern(ps->VAR_SPECIAL_TEXT);
++ }
+ else if(var == &ps->vars[V_INIT_CMD_LIST]){
+ if(!revert)
+ q_status_message(SM_ASYNC, 0, 3,
+***************
+*** 5489,5494 ****
+--- 5569,5580 ----
+ (void *)var->current_val.p);
+ }
+ #endif
++ #ifndef _WINDOWS
++ else if(var == &ps->vars[V_MAILDIR_LOCATION]){
++ if(var->current_val.p && var->current_val.p[0])
++ mail_parameters(NULL, SET_MDINBOXPATH, (void *)var->current_val.p);
++ }
++ #endif
+ else if(revert && standard_radio_var(ps, var)){
+
+ cur_rule_value(var, TRUE, FALSE);
+***************
+*** 5538,5546 ****
+ else if(revert && var == &ps->vars[V_SORT_KEY]){
+ int def_sort_rev;
+
+! decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev);
+ ps->def_sort_rev = def_sort_rev;
+ }
+ else if(var == &ps->vars[V_THREAD_MORE_CHAR] ||
+ var == &ps->vars[V_THREAD_EXP_CHAR] ||
+ var == &ps->vars[V_THREAD_LASTREPLY_CHAR]){
+--- 5624,5638 ----
+ else if(revert && var == &ps->vars[V_SORT_KEY]){
+ int def_sort_rev;
+
+! decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev, 0);
+ ps->def_sort_rev = def_sort_rev;
+ }
++ else if(revert && var == &ps->vars[V_THREAD_SORT_KEY]){
++ int thread_def_sort_rev;
++
++ decode_sort(VAR_THREAD_SORT_KEY, &ps->thread_def_sort, &thread_def_sort_rev, 1);
++ ps->thread_def_sort_rev = thread_def_sort_rev;
++ }
+ else if(var == &ps->vars[V_THREAD_MORE_CHAR] ||
+ var == &ps->vars[V_THREAD_EXP_CHAR] ||
+ var == &ps->vars[V_THREAD_LASTREPLY_CHAR]){
+***************
+*** 5607,5612 ****
+--- 5699,5705 ----
+ }
+ }
+ else if(var == &ps->vars[V_KW_COLORS] ||
++ var == &ps->vars[V_INDEX_TOKEN_COLORS] ||
+ var == &ps->vars[V_IND_PLUS_FORE_COLOR] ||
+ var == &ps->vars[V_IND_IMP_FORE_COLOR] ||
+ var == &ps->vars[V_IND_DEL_FORE_COLOR] ||
+diff -rc alpine-2.00/alpine/confscroll.h alpine-2.00.I.USE/alpine/confscroll.h
+*** alpine-2.00/alpine/confscroll.h 2007-11-09 13:13:47.000000000 -0800
+--- alpine-2.00.I.USE/alpine/confscroll.h 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 94,100 ****
+ int radiobutton_tool(struct pine *, int, CONF_S **, unsigned);
+ int yesno_tool(struct pine *, int, CONF_S **, unsigned);
+ int text_toolit(struct pine *, int, CONF_S **, unsigned, int);
+! char *generalized_sort_pretty_value(struct pine *, CONF_S *, int);
+ int exclude_config_var(struct pine *, struct variable *, int);
+ int config_exit_cmd(unsigned);
+ int simple_exit_cmd(unsigned);
+--- 94,100 ----
+ int radiobutton_tool(struct pine *, int, CONF_S **, unsigned);
+ int yesno_tool(struct pine *, int, CONF_S **, unsigned);
+ int text_toolit(struct pine *, int, CONF_S **, unsigned, int);
+! char *generalized_sort_pretty_value(struct pine *, CONF_S *, int, int);
+ int exclude_config_var(struct pine *, struct variable *, int);
+ int config_exit_cmd(unsigned);
+ int simple_exit_cmd(unsigned);
+diff -rc alpine-2.00/alpine/dispfilt.c alpine-2.00.I.USE/alpine/dispfilt.c
+*** alpine-2.00/alpine/dispfilt.c 2008-03-18 10:24:31.000000000 -0700
+--- alpine-2.00.I.USE/alpine/dispfilt.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 56,68 ****
+ dfilter(char *rawcmd, STORE_S *input_so, gf_io_t output_pc, FILTLIST_S *aux_filters)
+ {
+ char *status = NULL, *cmd, *resultf = NULL, *tmpfile = NULL;
+! int key = 0;
+
+! if((cmd = expand_filter_tokens(rawcmd,NULL,&tmpfile,&resultf,NULL,&key,NULL)) != NULL){
+ suspend_busy_cue();
+ #ifndef _WINDOWS
+! ps_global->mangled_screen = 1;
+! ClearScreen();
+ fflush(stdout);
+ #endif
+
+--- 56,70 ----
+ dfilter(char *rawcmd, STORE_S *input_so, gf_io_t output_pc, FILTLIST_S *aux_filters)
+ {
+ char *status = NULL, *cmd, *resultf = NULL, *tmpfile = NULL;
+! int key = 0, silent = 0;
+
+! if((cmd = expand_filter_tokens(rawcmd,NULL,&tmpfile,&resultf,NULL,&key,NULL, &silent)) != NULL){
+ suspend_busy_cue();
+ #ifndef _WINDOWS
+! if(!silent){
+! ps_global->mangled_screen = 1;
+! ClearScreen();
+! }
+ fflush(stdout);
+ #endif
+
+***************
+*** 99,105 ****
+ /* prepare the terminal in case the filter uses it */
+ if(status == NULL){
+ if((filter_pipe = open_system_pipe(cmd, NULL, NULL,
+! PIPE_USER | PIPE_RESET,
+ 0, pipe_callback, NULL)) != NULL){
+ if(close_system_pipe(&filter_pipe, NULL, pipe_callback) == 0){
+ /* pull result out of tmp file */
+--- 101,108 ----
+ /* prepare the terminal in case the filter uses it */
+ if(status == NULL){
+ if((filter_pipe = open_system_pipe(cmd, NULL, NULL,
+! PIPE_USER | (silent ? PIPE_SILENT :
+! (F_ON(F_DISABLE_TERM_RESET_DISP, ps_global) ? 0 : PIPE_RESET)),
+ 0, pipe_callback, NULL)) != NULL){
+ if(close_system_pipe(&filter_pipe, NULL, pipe_callback) == 0){
+ /* pull result out of tmp file */
+***************
+*** 130,136 ****
+ status = "Can't open display filter tmp file";
+ }
+ else if((status = gf_filter(cmd, key ? filter_session_key() : NULL,
+! input_so, output_pc, aux_filters,
+ F_ON(F_DISABLE_TERM_RESET_DISP, ps_global),
+ pipe_callback)) != NULL){
+ unsigned long ch;
+--- 133,139 ----
+ status = "Can't open display filter tmp file";
+ }
+ else if((status = gf_filter(cmd, key ? filter_session_key() : NULL,
+! input_so, output_pc, aux_filters, silent,
+ F_ON(F_DISABLE_TERM_RESET_DISP, ps_global),
+ pipe_callback)) != NULL){
+ unsigned long ch;
+***************
+*** 150,156 ****
+
+ resume_busy_cue(0);
+ #ifndef _WINDOWS
+! ClearScreen();
+ #endif
+ fs_give((void **)&cmd);
+ }
+--- 153,160 ----
+
+ resume_busy_cue(0);
+ #ifndef _WINDOWS
+! if(!silent)
+! ClearScreen();
+ #endif
+ fs_give((void **)&cmd);
+ }
+***************
+*** 165,171 ****
+ */
+ char *
+ expand_filter_tokens(char *filter, ENVELOPE *env, char **tmpf, char **resultf,
+! char **mtypef, int *key, int *hdrs)
+ {
+ char **array, **q;
+ char *bp, *cmd = NULL, *p = NULL,
+--- 169,175 ----
+ */
+ char *
+ expand_filter_tokens(char *filter, ENVELOPE *env, char **tmpf, char **resultf,
+! char **mtypef, int *key, int *hdrs, int *silent)
+ {
+ char **array, **q;
+ char *bp, *cmd = NULL, *p = NULL,
+***************
+*** 238,243 ****
+--- 242,260 ----
+ fs_give((void **)q);
+ *q = rl ? rl : cpystr("");
+ }
++ else if(!strcmp(*q, "_ADDRESS_")){
++ char *r = NULL;
++
++ if(env && env->from && env->from->mailbox && env->from->host){
++ size_t l;
++ l = strlen(env->from->mailbox) + strlen(env->from->host) + 1;
++ r = (char *) fs_get((l+1) * sizeof(char));
++ snprintf(r, l+1, "%s@%s", env->from->mailbox, env->from->host);
++ }
++
++ fs_give((void **)q);
++ *q = r ? r : cpystr("");
++ }
+ else if(!strcmp(*q, "_TMPFILE_")){
+ if(!tfn){
+ tfn = temp_nam(NULL, "sf"); /* send filter file */
+***************
+*** 312,317 ****
+--- 329,339 ----
+ if(hdrs)
+ *hdrs = 1;
+ }
++ else if(!strcmp(*q, "_SILENT_")){
++ (*q)[0] = '\0';
++ if(silent)
++ *silent = 1;
++ }
+ }
+
+ /* count up required length */
+***************
+*** 451,453 ****
+--- 473,535 ----
+
+ return(passed);
+ }
++
++ char *
++ exec_function_rule(char *rawcmd, gf_io_t input_gc, gf_io_t output_pc)
++ {
++ char *status = NULL, *cmd, *tmpfile = NULL;
++
++ if((cmd = expand_filter_tokens(rawcmd,NULL,&tmpfile,NULL,NULL,NULL,NULL, NULL)) != NULL){
++ suspend_busy_cue();
++ ps_global->mangled_screen = 1;
++ if(tmpfile){
++ PIPE_S *filter_pipe;
++ FILE *fp;
++ gf_io_t gc, pc;
++ STORE_S *tmpf_so;
++
++ /* write the tmp file */
++ if((tmpf_so = so_get(FileStar, tmpfile, WRITE_ACCESS|OWNER_ONLY|WRITE_TO_LOCALE)) != NULL){
++ /* copy input to tmp file */
++ gf_set_so_writec(&pc, tmpf_so);
++ gf_filter_init();
++ status = gf_pipe(input_gc, pc);
++ gf_clear_so_writec(tmpf_so);
++ if(so_give(&tmpf_so) != 0 && status == NULL)
++ status = error_description(errno);
++
++ /* prepare the terminal in case the filter uses it */
++ if(status == NULL){
++ if((filter_pipe = open_system_pipe(cmd, NULL, NULL,
++ PIPE_USER|PIPE_PROT|PIPE_NOSHELL|PIPE_SILENT,
++ 0, pipe_callback, NULL)) != NULL){
++ if(close_system_pipe(&filter_pipe, NULL, pipe_callback) == 0){
++ /* pull result out of tmp file */
++ if((fp = our_fopen(tmpfile, "rb")) != NULL){
++ gf_set_readc(&gc, fp, 0L, FileStar, READ_FROM_LOCALE);
++ gf_filter_init();
++ status = gf_pipe(gc, output_pc);
++ fclose(fp);
++ }
++ else
++ status = "Can't read result of EXEC command";
++ }
++ else
++ status = "EXEC command command returned error.";
++ }
++ else
++ status = "Can't open pipe for EXEC command";
++ }
++
++ our_unlink(tmpfile);
++ }
++ else
++ status = "Can't open EXEC command tmp file";
++ }
++
++ resume_busy_cue(0);
++ fs_give((void **)&cmd);
++ }
++
++ return(status);
++ }
+diff -rc alpine-2.00/alpine/dispfilt.h alpine-2.00.I.USE/alpine/dispfilt.h
+*** alpine-2.00/alpine/dispfilt.h 2006-09-26 12:30:49.000000000 -0700
+--- alpine-2.00.I.USE/alpine/dispfilt.h 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 21,30 ****
+ /* exported protoypes */
+ char *dfilter(char *, STORE_S *, gf_io_t, FILTLIST_S *);
+ char *dfilter_trigger(BODY *, char *, size_t);
+! char *expand_filter_tokens(char *, ENVELOPE *, char **, char **, char **, int *, int *);
+ char *filter_session_key(void);
+ char *filter_data_file(int);
+!
+
+
+ #endif /* PINE_DISPFILT_INCLUDED */
+--- 21,30 ----
+ /* exported protoypes */
+ char *dfilter(char *, STORE_S *, gf_io_t, FILTLIST_S *);
+ char *dfilter_trigger(BODY *, char *, size_t);
+! char *expand_filter_tokens(char *, ENVELOPE *, char **, char **, char **, int *, int *, int *);
+ char *filter_session_key(void);
+ char *filter_data_file(int);
+! char *exec_function_rule(char *, gf_io_t, gf_io_t);
+
+
+ #endif /* PINE_DISPFILT_INCLUDED */
+diff -rc alpine-2.00/alpine/folder.c alpine-2.00.I.USE/alpine/folder.c
+*** alpine-2.00/alpine/folder.c 2008-08-13 17:51:47.000000000 -0700
+--- alpine-2.00.I.USE/alpine/folder.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 77,83 ****
+ #define FLW_LIST 0x04 /* Allow for ListMode for subscribing */
+ #define FLW_UNSEEN 0x08 /* Add (unseen) */
+
+!
+
+ /*----------------------------------------------------------------------
+ The data needed to redraw the folders screen, including the case where the
+--- 77,88 ----
+ #define FLW_LIST 0x04 /* Allow for ListMode for subscribing */
+ #define FLW_UNSEEN 0x08 /* Add (unseen) */
+
+! /* folder colors */
+! #define CLR_UNSEEN 0x01 /* color folder with unseen/new messages */
+! #define CLR_FOLDER 0x02 /* color a name of folder or directory */
+! #define CLR_DIRECT 0x04 /* color a separator of a directory */
+! #define CLR_FLDRLT 0x08 /* color of explanatory text in list scrn*/
+! #define CLR_NORMAL 0x10 /* use normal color */
+
+ /*----------------------------------------------------------------------
+ The data needed to redraw the folders screen, including the case where the
+***************
+*** 173,179 ****
+ int folder_list_write_prefix(FOLDER_S *, int, gf_io_t);
+ int folder_list_write_middle(FOLDER_S *fp, CONTEXT_S *ctxt, gf_io_t pc, HANDLE_S *);
+ int folder_list_write_suffix(FOLDER_S *, int, gf_io_t);
+! int color_monitored_unseen(FOLDER_S *, int);
+ int folder_list_ith(int, CONTEXT_S *);
+ char *folder_list_center_space(char *, int);
+ HANDLE_S *folder_list_handle(FSTATE_S *, HANDLE_S *);
+--- 178,187 ----
+ int folder_list_write_prefix(FOLDER_S *, int, gf_io_t);
+ int folder_list_write_middle(FOLDER_S *fp, CONTEXT_S *ctxt, gf_io_t pc, HANDLE_S *);
+ int folder_list_write_suffix(FOLDER_S *, int, gf_io_t);
+! int color_monitored(FOLDER_S *, int, int);
+! int color_test_for_folder(char *, char *);
+! int color_write_for_folder(gf_io_t pc, int testtype);
+! int use_color_for_folder(FOLDER_S *fp);
+ int folder_list_ith(int, CONTEXT_S *);
+ char *folder_list_center_space(char *, int);
+ HANDLE_S *folder_list_handle(FSTATE_S *, HANDLE_S *);
+***************
+*** 238,244 ****
+ dprint((1, "=== folder_screen called ====\n"));
+ mailcap_free(); /* free resources we won't be using for a while */
+ ps->next_screen = SCREEN_FUN_NULL;
+!
+ /* Initialize folder state and dispatches */
+ memset(&fs, 0, sizeof(FSTATE_S));
+ fs.context = cntxt;
+--- 246,252 ----
+ dprint((1, "=== folder_screen called ====\n"));
+ mailcap_free(); /* free resources we won't be using for a while */
+ ps->next_screen = SCREEN_FUN_NULL;
+! strcpy(ps->screen_name, "folder");
+ /* Initialize folder state and dispatches */
+ memset(&fs, 0, sizeof(FSTATE_S));
+ fs.context = cntxt;
+***************
+*** 335,340 ****
+--- 343,349 ----
+ pine_mail_close(*fs.cache_streamp);
+
+ ps->prev_screen = folder_screen;
++ strcpy(ps->screen_name, "unknown");
+ }
+
+
+***************
+*** 1615,1622 ****
+--- 1624,1633 ----
+ if(c_list->prev)
+ gf_puts("\n", pc); /* blank line */
+
++ color_write_for_folder(pc, CLR_FLDRLT);
+ gf_puts(repeat_char(cols, '-'), pc);
+ gf_puts("\n", pc);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+
+ /* nickname or description */
+***************
+*** 1625,1630 ****
+--- 1636,1642 ----
+ || F_ON(F_CMBND_SUBDIR_DISP, ps_global))){
+ char buf[6*MAX_SCREEN_COLS + 1];
+
++ color_write_for_folder(pc, CLR_FLDRLT);
+ if(cols < 40){
+ snprintf(buf, sizeof(buf), "%.*s", cols,
+ strsquish(tmp_20k_buf, SIZEOF_20KBUF,
+***************
+*** 1651,1656 ****
+--- 1663,1669 ----
+
+ gf_puts(buf, pc);
+ gf_puts("\n", pc);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+ else if(c_list->label){
+ if(utf8_width(c_list->label) > ps_global->ttyo->screen_cols)
+***************
+*** 1660,1668 ****
+--- 1673,1683 ----
+
+ lbuf[sizeof(lbuf)-1] = '\0';
+
++ color_write_for_folder(pc, CLR_FLDRLT);
+ gf_puts(folder_list_center_space(lbuf, cols), pc);
+ gf_puts(lbuf, pc);
+ gf_puts("\n", pc);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+
+ if(c_list->comment){
+***************
+*** 1673,1681 ****
+--- 1688,1698 ----
+
+ lbuf[sizeof(lbuf)-1] = '\0';
+
++ color_write_for_folder(pc, CLR_FLDRLT);
+ gf_puts(folder_list_center_space(lbuf, cols), pc);
+ gf_puts(lbuf, pc);
+ gf_puts("\n", pc);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+
+ if(c_list->dir->desc){
+***************
+*** 1684,1692 ****
+--- 1701,1711 ----
+ strncpy(buf, strsquish(tmp_20k_buf,SIZEOF_20KBUF,c_list->dir->desc,cols),
+ sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
++ color_write_for_folder(pc, CLR_FLDRLT);
+ gf_puts(folder_list_center_space(buf, cols), pc);
+ gf_puts(buf, pc);
+ gf_puts("\n", pc);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+
+ if(c_list->use & CNTXT_ZOOM){
+***************
+*** 1703,1720 ****
+--- 1722,1744 ----
+
+ lbuf[sizeof(lbuf)-1] = '\0';
+
++ color_write_for_folder(pc, CLR_FLDRLT);
+ gf_puts(folder_list_center_space(lbuf, cols), pc);
+ gf_puts(lbuf, pc);
+ gf_puts("\n", pc);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+
++ color_write_for_folder(pc, CLR_FLDRLT);
+ gf_puts(repeat_char(cols, '-'), pc);
+ gf_puts("\n\n", pc);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+
+ if(shown){
+ /* Run thru list formatting as necessary */
+ if((ftotal = folder_total(FOLDERS(c_list))) != 0){
++ int use_color;
+ /* If previously selected, mark members of new list */
+ selected = selected_folders(c_list);
+
+***************
+*** 1729,1738 ****
+ continue;
+
+ fcount++;
+!
+ width = utf8_width(FLDR_NAME(f));
+ if(f->isdir)
+! width += (f->isfolder) ? 3 : 1;
+
+ if(NEWS_TEST(c_list) && (c_list->use & CNTXT_FINDALL))
+ /* assume listmode so we don't have to reformat */
+--- 1753,1762 ----
+ continue;
+
+ fcount++;
+! use_color = use_color_for_folder(f);
+ width = utf8_width(FLDR_NAME(f));
+ if(f->isdir)
+! width += (f->isfolder) ? (use_color ? 1 : 3) : (use_color ? 0 : 1);
+
+ if(NEWS_TEST(c_list) && (c_list->use & CNTXT_FINDALL))
+ /* assume listmode so we don't have to reformat */
+***************
+*** 1866,1874 ****
+--- 1890,1900 ----
+
+ lbuf[sizeof(lbuf)-1] = '\0';
+
++ color_write_for_folder(pc, CLR_FLDRLT);
+ gf_puts(folder_list_center_space(lbuf, cols), pc);
+ (void) folder_list_write(pc, handlesp, c_list, -1, lbuf,
+ (handlesp) ? FLW_LUNK : FLW_NONE);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+ }
+ else if(fp->fs->combined_view
+***************
+*** 1883,1891 ****
+--- 1909,1919 ----
+
+ lbuf[sizeof(lbuf)-1] = '\0';
+
++ color_write_for_folder(pc, CLR_FLDRLT);
+ gf_puts(folder_list_center_space(lbuf, cols), pc);
+ (void) folder_list_write(pc, handlesp, c_list, -1, lbuf,
+ (handlesp) ? FLW_LUNK : FLW_NONE);
++ color_write_for_folder(pc, CLR_NORMAL);
+ }
+
+ gf_puts("\n", pc); /* blank line */
+***************
+*** 1932,1948 ****
+
+ if(h1){
+ /* color unseen? */
+! if(color_monitored_unseen(fp, flags)){
+ h1->color_unseen = 1;
+ if(h2)
+ h2->color_unseen = 1;
+ }
+ }
+
+ /* embed handle pointer */
+! if(((h1 && h1->color_unseen) ?
+! gf_puts(color_embed(ps_global->VAR_INCUNSEEN_FORE_COLOR,
+! ps_global->VAR_INCUNSEEN_BACK_COLOR), pc) : 1)
+ && (h1 ? ((*pc)(TAG_EMBED) && (*pc)(TAG_HANDLE)
+ && (*pc)(strlen(buf)) && gf_puts(buf, pc)) : 1)
+ && (fp ? ((lprefix = folder_list_write_prefix(fp, flags, pc)) >= 0
+--- 1960,1983 ----
+
+ if(h1){
+ /* color unseen? */
+! if(color_monitored(fp, flags, CLR_UNSEEN)){
+ h1->color_unseen = 1;
+ if(h2)
+ h2->color_unseen = 1;
+ }
++ /* color folder? */
++ if(color_monitored(fp, flags, CLR_FOLDER)){
++ h1->color_folder = 1;
++ if(h2)
++ h2->color_folder = 1;
++ }
+ }
+
+ /* embed handle pointer */
+! if(((h1 && h1->color_unseen) ? color_write_for_folder(pc, CLR_UNSEEN)
+! : ((h1 && h1->color_folder)
+! ? color_write_for_folder(pc, fp->isfolder ? CLR_FOLDER : CLR_DIRECT)
+! : 1))
+ && (h1 ? ((*pc)(TAG_EMBED) && (*pc)(TAG_HANDLE)
+ && (*pc)(strlen(buf)) && gf_puts(buf, pc)) : 1)
+ && (fp ? ((lprefix = folder_list_write_prefix(fp, flags, pc)) >= 0
+***************
+*** 1951,1959 ****
+ : (alt_name ? gf_puts(alt_name, pc) : 0))
+ && (h1 ? ((*pc)(TAG_EMBED) && (*pc)(TAG_BOLDOFF)
+ && (*pc)(TAG_EMBED) && (*pc)(TAG_INVOFF)) : 1)
+! && ((h1 && h1->color_unseen) ?
+! gf_puts(color_embed(ps_global->VAR_NORM_FORE_COLOR,
+! ps_global->VAR_NORM_BACK_COLOR), pc) : 1)){
+ if(fp)
+ width = lprefix + lmiddle + lsuffix;
+ else if(alt_name)
+--- 1986,1993 ----
+ : (alt_name ? gf_puts(alt_name, pc) : 0))
+ && (h1 ? ((*pc)(TAG_EMBED) && (*pc)(TAG_BOLDOFF)
+ && (*pc)(TAG_EMBED) && (*pc)(TAG_INVOFF)) : 1)
+! && ((h1 && (h1->color_unseen || h1->color_folder)) ?
+! color_write_for_folder(pc, CLR_NORMAL): 1)){
+ if(fp)
+ width = lprefix + lmiddle + lsuffix;
+ else if(alt_name)
+***************
+*** 1992,2002 ****
+ return(rv);
+ }
+
+-
+ int
+ folder_list_write_middle(FOLDER_S *fp, CONTEXT_S *ctxt, gf_io_t pc, HANDLE_S *h2)
+ {
+! int rv = -1;
+ char buf[256];
+
+ if(h2){
+--- 2026,2035 ----
+ return(rv);
+ }
+
+ int
+ folder_list_write_middle(FOLDER_S *fp, CONTEXT_S *ctxt, gf_io_t pc, HANDLE_S *h2)
+ {
+! int rv = -1, use_color;
+ char buf[256];
+
+ if(h2){
+***************
+*** 2007,2023 ****
+ if(!fp)
+ return(rv);
+
+ if(gf_puts(FLDR_NAME(fp), pc)
+ && (h2 ? ((*pc)(TAG_EMBED) && (*pc)(TAG_BOLDOFF) /* tie off handle 1 */
+ && (*pc)(TAG_EMBED) && (*pc)(TAG_INVOFF)) : 1)
+ && (h2 ? ((*pc)(TAG_EMBED) && (*pc)(TAG_HANDLE) /* start handle 2 */
+ && (*pc)(strlen(buf)) && gf_puts(buf, pc)) : 1)
+! && ((fp->isdir && fp->isfolder) ? (*pc)('[') : 1)
+! && ((fp->isdir) ? (*pc)(ctxt->dir->delim) : 1)
+! && ((fp->isdir && fp->isfolder) ? (*pc)(']') : 1)){
+ rv = utf8_width(FLDR_NAME(fp));
+ if(fp->isdir)
+! rv += (fp->isfolder) ? 3 : 1;
+ }
+
+ return(rv);
+--- 2040,2062 ----
+ if(!fp)
+ return(rv);
+
++ use_color = use_color_for_folder(fp);
++
+ if(gf_puts(FLDR_NAME(fp), pc)
+ && (h2 ? ((*pc)(TAG_EMBED) && (*pc)(TAG_BOLDOFF) /* tie off handle 1 */
+ && (*pc)(TAG_EMBED) && (*pc)(TAG_INVOFF)) : 1)
++ && ((use_color && fp->isdir && fp->isfolder)
++ ? color_write_for_folder(pc, CLR_DIRECT) : 1)
+ && (h2 ? ((*pc)(TAG_EMBED) && (*pc)(TAG_HANDLE) /* start handle 2 */
+ && (*pc)(strlen(buf)) && gf_puts(buf, pc)) : 1)
+! && use_color
+! ? (fp->isdir && fp->isfolder ? (*pc)(ctxt->dir->delim) : 1)
+! : (((fp->isdir && fp->isfolder) ? (*pc)('[') : 1)
+! && ((fp->isdir) ? (*pc)(ctxt->dir->delim) : 1)
+! && ((fp->isdir && fp->isfolder) ? (*pc)(']') : 1))){
+ rv = utf8_width(FLDR_NAME(fp));
+ if(fp->isdir)
+! rv += (fp->isfolder) ? (use_color ? 1 : 3) : (use_color ? 0 : 1);
+ }
+
+ return(rv);
+***************
+*** 2065,2084 ****
+ return(rv);
+ }
+
+
+ int
+! color_monitored_unseen(FOLDER_S *f, int flags)
+ {
+! return((flags & FLW_UNSEEN) && f && f->unseen_valid
+ && ((F_ON(F_INCOMING_CHECKING_RECENT, ps_global) && f->new > 0L)
+ || (F_OFF(F_INCOMING_CHECKING_RECENT, ps_global) && f->unseen > 0L))
+! && pico_usingcolor()
+! && pico_is_good_color(ps_global->VAR_INCUNSEEN_FORE_COLOR)
+! && pico_is_good_color(ps_global->VAR_INCUNSEEN_BACK_COLOR)
+! && (colorcmp(ps_global->VAR_INCUNSEEN_FORE_COLOR,
+! ps_global->VAR_NORM_FORE_COLOR)
+! || colorcmp(ps_global->VAR_INCUNSEEN_BACK_COLOR,
+! ps_global->VAR_NORM_BACK_COLOR)));
+ }
+
+
+--- 2104,2188 ----
+ return(rv);
+ }
+
++ int
++ color_write_for_folder(gf_io_t pc, int testtype)
++ {
++ int rv;
++ if(!pico_usingcolor())
++ return 1;
++ switch (testtype){
++ case CLR_UNSEEN:
++ rv = gf_puts(color_embed(ps_global->VAR_INCUNSEEN_FORE_COLOR,
++ ps_global->VAR_INCUNSEEN_BACK_COLOR), pc);
++ break;
++ case CLR_FOLDER:
++ rv = gf_puts(color_embed(ps_global->VAR_FOLDER_FORE_COLOR,
++ ps_global->VAR_FOLDER_BACK_COLOR ), pc);
++ break;
++ case CLR_FLDRLT:
++ rv = gf_puts(color_embed(ps_global->VAR_FOLDER_LIST_FORE_COLOR,
++ ps_global->VAR_FOLDER_LIST_BACK_COLOR ), pc);
++ break;
++ case CLR_DIRECT:
++ rv = gf_puts(color_embed(ps_global->VAR_DIRECTORY_FORE_COLOR,
++ ps_global->VAR_DIRECTORY_BACK_COLOR), pc);
++ break;
++ case CLR_NORMAL:
++ rv = gf_puts(color_embed(ps_global->VAR_NORM_FORE_COLOR,
++ ps_global->VAR_NORM_BACK_COLOR), pc);
++ break;
++ default:
++ rv = 0; /* fail */
++ break;
++ }
++ return rv;
++ }
++
+
+ int
+! color_test_for_folder(char *color_fore, char *color_back)
+ {
+! return pico_usingcolor()
+! && pico_is_good_color(color_fore)
+! && pico_is_good_color(color_back)
+! && (colorcmp(color_fore, ps_global->VAR_NORM_FORE_COLOR)
+! || colorcmp(color_back,
+! ps_global->VAR_NORM_BACK_COLOR)) ? 1 : 0;
+!
+! }
+!
+!
+! int
+! use_color_for_folder(FOLDER_S *fp)
+! {
+! int test1, test2;
+! if(fp->isdir)
+! test1 = color_test_for_folder(ps_global->VAR_DIRECTORY_FORE_COLOR,
+! ps_global->VAR_DIRECTORY_BACK_COLOR);
+! if(fp->isfolder)
+! test2 = color_test_for_folder(ps_global->VAR_FOLDER_FORE_COLOR,
+! ps_global->VAR_FOLDER_BACK_COLOR);
+! return (fp->isdir && fp->isfolder) ? test1 + test2
+! : (fp->isdir ? test1 : (fp->isfolder? test2 : 0));
+! }
+!
+!
+! int
+! color_monitored(FOLDER_S *f, int flags, int testtype)
+! {
+! int rv;
+! switch(testtype){
+! case CLR_UNSEEN: rv = (flags & FLW_UNSEEN) && f && f->unseen_valid
+ && ((F_ON(F_INCOMING_CHECKING_RECENT, ps_global) && f->new > 0L)
+ || (F_OFF(F_INCOMING_CHECKING_RECENT, ps_global) && f->unseen > 0L))
+! && color_test_for_folder(ps_global->VAR_INCUNSEEN_FORE_COLOR,
+! ps_global->VAR_INCUNSEEN_BACK_COLOR) ? 1 : 0;
+! break;
+! case CLR_FOLDER: rv = f ? use_color_for_folder(f) : 0;
+! break;
+! default: rv = 0;
+! }
+! return rv;
+ }
+
+
+***************
+*** 6223,6233 ****
+ char *
+ next_folder(MAILSTREAM **streamp, char *next, size_t nextlen, char *current, CONTEXT_S *cntxt, long int *find_recent, int *did_cancel)
+ {
+! int index, recent = 0, failed_status = 0, try_fast;
+ char prompt[128];
+ FOLDER_S *f = NULL;
+ char tmp[MAILTMPLEN];
+!
+
+ /* note: find_folders may assign "stream" */
+ build_folder_list(streamp, cntxt, NULL, NULL,
+--- 6327,6343 ----
+ char *
+ next_folder(MAILSTREAM **streamp, char *next, size_t nextlen, char *current, CONTEXT_S *cntxt, long int *find_recent, int *did_cancel)
+ {
+! int index, recent = 0, failed_status = 0, try_fast, done = 0;
+ char prompt[128];
+ FOLDER_S *f = NULL;
+ char tmp[MAILTMPLEN];
+! char *test_current = cpystr(current);
+! int cur_indx = folder_index(ps_global->cur_folder, cntxt, FI_FOLDER);
+! int loop = !strcmp(next, ps_global->cur_folder) ? 0 :
+! (folder_index(test_current, cntxt, FI_FOLDER) <= cur_indx
+! ? 1 : 0);
+! int last = !strcmp(ps_global->cur_folder, ps_global->inbox_name)
+! ? 1 : cur_indx;
+
+ /* note: find_folders may assign "stream" */
+ build_folder_list(streamp, cntxt, NULL, NULL,
+***************
+*** 6238,6244 ****
+ if(find_recent)
+ *find_recent = 0L;
+
+! for(index = folder_index(current, cntxt, FI_FOLDER) + 1;
+ index > 0
+ && index < folder_total(FOLDERS(cntxt))
+ && (f = folder_entry(index, FOLDERS(cntxt)))
+--- 6348,6356 ----
+ if(find_recent)
+ *find_recent = 0L;
+
+!
+! find_new_message:
+! for(index = folder_index(test_current, cntxt, FI_FOLDER) + 1;
+ index > 0
+ && index < folder_total(FOLDERS(cntxt))
+ && (f = folder_entry(index, FOLDERS(cntxt)))
+***************
+*** 6249,6254 ****
+--- 6361,6371 ----
+ int rv, we_cancel = 0, match;
+ char msg_buf[MAX_BM+1];
+
++ if (loop && (index == last)){
++ done++;
++ break;
++ }
++
+ /* must be a folder and it can't be the current one */
+ if(ps_global->context_current == ps_global->context_list
+ && !strcmp(ps_global->cur_folder, FLDR_NAME(f)))
+***************
+*** 6416,6427 ****
+--- 6533,6556 ----
+ if(f && (!find_recent || recent)){
+ strncpy(next, FLDR_NAME(f), nextlen);
+ next[nextlen-1] = '\0';
++ done++;
+ }
+ else if(nextlen > 0)
+ *next = '\0';
+
++ if (!done && F_ON(F_AUTO_CIRCULAR_TAB,ps_global)
++ && strcmp(test_current,ps_global->inbox_name)){
++ done++; loop++;
++ if (test_current)
++ fs_give((void **)&test_current);
++ test_current = cpystr(ps_global->inbox_name);
++ goto find_new_message;
++ }
++
+ /* BUG: how can this be made smarter so we cache the list? */
+ free_folder_list(cntxt);
++ if (test_current)
++ fs_give((void **)&test_current);
+ return((*next) ? next : NULL);
+ }
+
+diff -rc alpine-2.00/alpine/help.c alpine-2.00.I.USE/alpine/help.c
+*** alpine-2.00/alpine/help.c 2008-04-10 09:50:54.000000000 -0700
+--- alpine-2.00.I.USE/alpine/help.c 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 390,395 ****
+--- 390,396 ----
+ {
+ int rv = 0;
+ char message[64];
++ struct help_texts *t;
+
+ switch(cmd){
+ /*----------- Print all the help ------------*/
+***************
+*** 407,412 ****
+--- 408,430 ----
+
+ break;
+
++ case MC_EXPORT: /* reuse old definition, so as not to patch pine.h */
++ {char help_name[40];
++ help_name[0] = '\0';
++ for(t = h_texts; t->help_text != NO_HELP; t++)
++ if(t->help_text == ((HELP_SCROLL_S *)sparms->proc.data.p)->help_source){
++ strcpy(help_name,t->tag);
++ break;
++ }
++ if(help_name[0])
++ q_status_message1(SM_ORDER, 0, 2,
++ "Internal Name: x-alpine-help:%s", help_name);
++ else
++ q_status_message(SM_ORDER|SM_DING, 1, 2,
++ "Can not find link for text help");
++ }
++ break;
++
+ case MC_FINISH :
+ rv = 1;
+ break;
+***************
+*** 572,578 ****
+ int
+ url_local_helper(char *url)
+ {
+! if(!struncmp(url, "x-alpine-help:", 14) && *(url += 14)){
+ char *frag;
+ HelpType newhelp;
+
+--- 590,597 ----
+ int
+ url_local_helper(char *url)
+ {
+! if((!struncmp(url, "x-alpine-help:", 14) && *(url += 14))
+! || (!struncmp(url, "x-pine-help:", 12) && *(url += 12))){
+ char *frag;
+ HelpType newhelp;
+
+diff -rc alpine-2.00/alpine/imap.c alpine-2.00.I.USE/alpine/imap.c
+*** alpine-2.00/alpine/imap.c 2008-04-10 14:26:20.000000000 -0700
+--- alpine-2.00.I.USE/alpine/imap.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 94,100 ****
+ * Internal prototypes
+ */
+ void mm_login_alt_cue(NETMBX *);
+! long pine_tcptimeout_noscreen(long, long);
+ int answer_cert_failure(int, MSGNO_S *, SCROLL_S *);
+
+ #ifdef LOCAL_PASSWD_CACHE
+--- 94,100 ----
+ * Internal prototypes
+ */
+ void mm_login_alt_cue(NETMBX *);
+! long pine_tcptimeout_noscreen(long, long, char *);
+ int answer_cert_failure(int, MSGNO_S *, SCROLL_S *);
+
+ #ifdef LOCAL_PASSWD_CACHE
+***************
+*** 350,355 ****
+--- 350,356 ----
+ HelpType help ;
+ int len, rc, q_line, flags;
+ int oespace, avail, need, save_dont_use;
++ int save_in_init;
+ struct servent *sv;
+ #if defined(_WINDOWS) || defined(LOCAL_PASSWD_CACHE)
+ int preserve_password = -1;
+***************
+*** 364,369 ****
+--- 365,372 ----
+ altuserforcache ? altuserforcache : ""));
+ q_line = -(ps_global->ttyo ? ps_global->ttyo->footer_rows : 3);
+
++ save_in_init = ps_global->in_init_seq;
++ ps_global->in_init_seq = 0;
+ ps_global->no_newmail_check_from_optionally_enter = 1;
+
+ /* make sure errors are seen */
+***************
+*** 440,448 ****
+
+ /* try last working password associated with this host. */
+ if(imap_get_passwd(mm_login_list, pwd, user, hostlist,
+! (mb->sslflag||mb->tlsflag))){
+ dprint((9, "mm_login: found a password to try\n"));
+ ps_global->no_newmail_check_from_optionally_enter = 0;
+ return;
+ }
+
+--- 443,452 ----
+
+ /* try last working password associated with this host. */
+ if(imap_get_passwd(mm_login_list, pwd, user, hostlist,
+! (mb->sslflag||mb->tlsflag)) && pwd[0] != '\0'){
+ dprint((9, "mm_login: found a password to try\n"));
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+
+***************
+*** 456,461 ****
+--- 460,466 ----
+ (mb->sslflag||mb->tlsflag));
+ dprint((9, "mm_login: found a password in passfile to try\n"));
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+ #endif /* LOCAL_PASSWD_CACHE */
+***************
+*** 484,489 ****
+--- 489,495 ----
+ "mm_login: found a password for user=%s to try\n",
+ user ? user : "?"));
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+
+***************
+*** 499,504 ****
+--- 505,511 ----
+ "mm_login: found a password for user=%s in passfile to try\n",
+ user ? user : "?"));
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+ #endif /* LOCAL_PASSWD_CACHE */
+***************
+*** 519,524 ****
+--- 526,532 ----
+ (mb->sslflag||mb->tlsflag))){
+ dprint((9, "mm_login:ui: found a password to try\n"));
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+
+***************
+*** 532,537 ****
+--- 540,546 ----
+ (mb->sslflag||mb->tlsflag));
+ dprint((9, "mm_login:ui: found a password in passfile to try\n"));
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+ #endif /* LOCAL_PASSWD_CACHE */
+***************
+*** 750,755 ****
+--- 759,765 ----
+
+ if(!(user[0] || altuserforcache)){
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+
+***************
+*** 762,767 ****
+--- 772,778 ----
+ if(imap_get_passwd(mm_login_list, pwd, user, hostlist,
+ (mb->sslflag||mb->tlsflag))){
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+
+***************
+*** 771,776 ****
+--- 782,788 ----
+ imap_set_passwd(&mm_login_list, pwd, user,
+ hostlist, (mb->sslflag||mb->tlsflag), 0, 0);
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+ #endif /* LOCAL_PASSWD_CACHE */
+***************
+*** 779,784 ****
+--- 791,797 ----
+ if(imap_get_passwd(mm_login_list, pwd, altuserforcache, hostlist,
+ (mb->sslflag||mb->tlsflag))){
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+
+***************
+*** 788,793 ****
+--- 801,807 ----
+ imap_set_passwd(&mm_login_list, pwd, altuserforcache,
+ hostlist, (mb->sslflag||mb->tlsflag), 0, 0);
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+ #endif /* LOCAL_PASSWD_CACHE */
+***************
+*** 976,981 ****
+--- 990,996 ----
+ ps_global->user_says_cancel = (rc == 1);
+ user[0] = pwd[0] = '\0';
+ ps_global->no_newmail_check_from_optionally_enter = 0;
++ ps_global->in_init_seq = save_in_init;
+ return;
+ }
+
+***************
+*** 1181,1187 ****
+
+
+ long
+! pine_tcptimeout_noscreen(long int elapsed, long int sincelast)
+ {
+ long rv = 1L;
+ char pmt[128];
+--- 1196,1202 ----
+
+
+ long
+! pine_tcptimeout_noscreen(long int elapsed, long int sincelast, char *host)
+ {
+ long rv = 1L;
+ char pmt[128];
+***************
+*** 1192,1199 ****
+
+ if(elapsed >= (long)ps_global->tcp_query_timeout){
+ snprintf(pmt, sizeof(pmt),
+! _("Waited %s seconds for server reply. Break connection to server"),
+! long2string(elapsed));
+ pmt[sizeof(pmt)-1] = '\0';
+ if(want_to(pmt, 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y'){
+ ps_global->user_says_cancel = 1;
+--- 1207,1214 ----
+
+ if(elapsed >= (long)ps_global->tcp_query_timeout){
+ snprintf(pmt, sizeof(pmt),
+! _("No reply in %s seconds from server %s. Break connection"),
+! long2string(elapsed), host);
+ pmt[sizeof(pmt)-1] = '\0';
+ if(want_to(pmt, 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y'){
+ ps_global->user_says_cancel = 1;
+***************
+*** 1216,1222 ****
+ * pine_tcptimeout - C-client callback to handle tcp-related timeouts.
+ */
+ long
+! pine_tcptimeout(long int elapsed, long int sincelast)
+ {
+ long rv = 1L; /* keep trying by default */
+ unsigned long ch;
+--- 1231,1237 ----
+ * pine_tcptimeout - C-client callback to handle tcp-related timeouts.
+ */
+ long
+! pine_tcptimeout(long int elapsed, long int sincelast, char *host)
+ {
+ long rv = 1L; /* keep trying by default */
+ unsigned long ch;
+***************
+*** 1236,1242 ****
+ return(rv);
+
+ if(!ps_global->ttyo)
+! return(pine_tcptimeout_noscreen(elapsed, sincelast));
+
+ suspend_busy_cue();
+
+--- 1251,1257 ----
+ return(rv);
+
+ if(!ps_global->ttyo)
+! return(pine_tcptimeout_noscreen(elapsed, sincelast, host));
+
+ suspend_busy_cue();
+
+***************
+*** 1253,1261 ****
+
+ Writechar(BELL, 0);
+
+! PutLine1(ps_global->ttyo->screen_rows - FOOTER_ROWS(ps_global), 0,
+! _("Waited %s seconds for server reply. Break connection to server? "),
+! long2string(elapsed));
+ CleartoEOLN();
+ fflush(stdout);
+ flush_input();
+--- 1268,1276 ----
+
+ Writechar(BELL, 0);
+
+! PutLine2(ps_global->ttyo->screen_rows - FOOTER_ROWS(ps_global), 0,
+! _("No reply in %s seconds from server %s. Break connection?"),
+! long2string(elapsed), host);
+ CleartoEOLN();
+ fflush(stdout);
+ flush_input();
+***************
+*** 1272,1280 ****
+ }
+
+ if(rv == 1L){ /* just warn 'em something's up */
+! q_status_message1(SM_ORDER, 0, 0,
+! _("Waited %s seconds for server reply. Still Waiting..."),
+! long2string(elapsed));
+ flush_status_messages(0); /* make sure it's seen */
+ }
+
+--- 1287,1295 ----
+ }
+
+ if(rv == 1L){ /* just warn 'em something's up */
+! q_status_message2(SM_ORDER, 0, 0,
+! _("No reply in %s seconds from server %s. Still Waiting..."),
+! long2string(elapsed), host);
+ flush_status_messages(0); /* make sure it's seen */
+ }
+
+***************
+*** 1285,1290 ****
+--- 1300,1335 ----
+ return(rv);
+ }
+
++ QUOTALIST *pine_quotalist_copy (pquota)
++ QUOTALIST *pquota;
++ {
++ QUOTALIST *cquota = NULL;
++
++ if(pquota){
++ cquota = mail_newquotalist();
++ if (pquota->name && *pquota->name){
++ cquota->name = (char *) fs_get((strlen(pquota->name) + 1)*sizeof(char));
++ cquota->name = cpystr(pquota->name);
++ }
++ cquota->usage = pquota->usage;
++ cquota->limit = pquota->limit;
++ if (pquota->next)
++ cquota->next = pine_quotalist_copy(pquota->next);
++ }
++ return cquota;
++ }
++
++
++ /* C-client callback to handle quota */
++
++ void
++ pine_parse_quota (stream, msg, pquota)
++ MAILSTREAM *stream;
++ unsigned char *msg;
++ QUOTALIST *pquota;
++ {
++ ps_global->quota = pine_quotalist_copy (pquota);
++ }
+
+ /*
+ * C-client callback to handle SSL/TLS certificate validation failures
+diff -rc alpine-2.00/alpine/imap.h alpine-2.00.I.USE/alpine/imap.h
+*** alpine-2.00/alpine/imap.h 2008-04-23 19:00:26.000000000 -0700
+--- alpine-2.00.I.USE/alpine/imap.h 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 21,28 ****
+
+
+ /* exported protoypes */
+ void *pine_block_notify(int, void *);
+! long pine_tcptimeout(long, long);
+ long pine_sslcertquery(char *, char *, char *);
+ char *pine_newsrcquery(MAILSTREAM *, char *, char *);
+ int url_local_certdetails(char *);
+--- 21,30 ----
+
+
+ /* exported protoypes */
++ void pine_parse_quota (MAILSTREAM *, unsigned char *, QUOTALIST *);
++ QUOTALIST *pine_quotalist_copy (QUOTALIST *);
+ void *pine_block_notify(int, void *);
+! long pine_tcptimeout(long, long, char *);
+ long pine_sslcertquery(char *, char *, char *);
+ char *pine_newsrcquery(MAILSTREAM *, char *, char *);
+ int url_local_certdetails(char *);
+diff -rc alpine-2.00/alpine/keymenu.c alpine-2.00.I.USE/alpine/keymenu.c
+*** alpine-2.00/alpine/keymenu.c 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/alpine/keymenu.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 314,319 ****
+--- 314,333 ----
+ WHEREIS_MENU};
+ INST_KEY_MENU(c_fcc_km, context_fcc_keys);
+
++ static struct key quota_keys[] =
++ {HELP_MENU,
++ NULL_MENU,
++ {"E","Exit",{MC_EXIT,3,{'e','i',ctrl('C')}},KS_EXITMODE},
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU};
++ INST_KEY_MENU(pine_quota_keymenu, quota_keys);
+
+ struct key folder_keys[] =
+ {HELP_MENU,
+***************
+*** 482,488 ****
+ NEXTPAGE_MENU,
+ PRYNTMSG_MENU,
+ {"Z",N_("Print All"),{MC_PRINTALL,1,{'z'}},KS_NONE},
+! NULL_MENU,
+ WHEREIS_MENU,
+
+ HELP_MENU,
+--- 496,502 ----
+ NEXTPAGE_MENU,
+ PRYNTMSG_MENU,
+ {"Z",N_("Print All"),{MC_PRINTALL,1,{'z'}},KS_NONE},
+! {"N",N_("Name"),{MC_EXPORT,1,{'n'}},KS_NONE},
+ WHEREIS_MENU,
+
+ HELP_MENU,
+***************
+*** 650,661 ****
+ RCOMPOSE_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+! NULL_MENU,
+ /* TRANSLATORS: toggles a collapsed view or an expanded view
+ of a message thread on and off */
+ {"/",N_("Collapse/Expand"),{MC_COLLAPSE,1,{'/'}},KS_NONE},
+! NULL_MENU,
+ NULL_MENU};
+ INST_KEY_MENU(index_keymenu, index_keys);
+
+
+--- 664,691 ----
+ RCOMPOSE_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+! {"K","Sort Thread",{MC_SORTHREAD,1,{'k'}},KS_NONE},
+ /* TRANSLATORS: toggles a collapsed view or an expanded view
+ of a message thread on and off */
+ {"/",N_("Collapse/Expand"),{MC_COLLAPSE,1,{'/'}},KS_NONE},
+! /* TRANSLATORS: Collapse all threads */
+! {"{",N_("Collapse All"),{MC_KOLAPSE,1,{'{'}},KS_NONE},
+! /* TRANSLATORS: Expand all threads */
+! {"}",N_("Expand All"), {MC_EXPTHREAD,1,{'}'}},KS_NONE},
+!
+! HELP_MENU,
+! OTHER_MENU,
+! {")","Next Threa",{MC_NEXTHREAD,1,{')'}},KS_NONE},
+! {"(","Prev Threa",{MC_PRETHREAD,1,{'('}},KS_NONE},
+! {"^D","Delete Thr",{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE},
+! {"^U","Undel Thre",{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE},
+! {"^T","Select Thr",{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE},
+! NULL_MENU,
+! {"[","Close Thre",{MC_CTHREAD,1,{'['}},KS_NONE},
+! {"]","Open Threa",{MC_OTHREAD,1,{']'}},KS_NONE},
+! {"@", N_("Quota"), {MC_QUOTA,1,{'@'}}, KS_NONE},
+ NULL_MENU};
++
+ INST_KEY_MENU(index_keymenu, index_keys);
+
+
+***************
+*** 728,736 ****
+ RCOMPOSE_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+! NULL_MENU,
+ {"/",N_("Collapse/Expand"),{MC_COLLAPSE,1,{'/'}},KS_NONE},
+ NULL_MENU,
+ NULL_MENU};
+ INST_KEY_MENU(thread_keymenu, thread_keys);
+
+--- 758,779 ----
+ RCOMPOSE_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+! {"]",N_("Open Thread"),{MC_OTHREAD,1,{']'}},KS_NONE},
+ {"/",N_("Collapse/Expand"),{MC_COLLAPSE,1,{'/'}},KS_NONE},
++ {")",N_("Next Thread"),{MC_NEXTHREAD,1,{')'}},KS_NONE},
++ {"(",N_("Prev Thread"),{MC_PRETHREAD,1,{'('}},KS_NONE},
++
++ HELP_MENU,
++ OTHER_MENU,
++ {"@", N_("Quota"), {MC_QUOTA,1,{'@'}}, KS_NONE},
++ NULL_MENU,
++ {"^D",N_("Delete Thread"),{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE},
++ {"^U",N_("Undelete Thread"),{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE},
++ {"^T",N_("SelecT Thread"),{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE},
++ NULL_MENU,
++ NULL_MENU,
+ NULL_MENU,
++ {"K","Sort Thread",{MC_SORTHREAD,1,{'k'}},KS_NONE},
+ NULL_MENU};
+ INST_KEY_MENU(thread_keymenu, thread_keys);
+
+***************
+*** 880,886 ****
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+! NULL_MENU};
+ INST_KEY_MENU(view_keymenu, view_keys);
+
+
+--- 923,942 ----
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+! NULL_MENU,
+!
+! HELP_MENU,
+! OTHER_MENU,
+! NULL_MENU,
+! NULL_MENU,
+! NULL_MENU,
+! NULL_MENU,
+! NULL_MENU,
+! {"(",N_("Prev Thread"),{MC_PRETHREAD,1,{'('}},KS_NONE},
+! {")",N_("Next Thread"),{MC_NEXTHREAD,1,{')'}},KS_NONE},
+! {"^D",N_("Delete Thread"),{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE},
+! {"^U",N_("Undelete Thread"),{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE},
+! {"^T",N_("selecT Thread"),{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE}};
+ INST_KEY_MENU(view_keymenu, view_keys);
+
+
+***************
+*** 2452,2458 ****
+
+ HELP_MENU,
+ OTHER_MENU,
+! NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+--- 2508,2514 ----
+
+ HELP_MENU,
+ OTHER_MENU,
+! {"I", N_("IndxHdr"), {MC_ADDHEADER,1,{'i'}}, KS_NONE},
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+***************
+*** 2481,2487 ****
+
+ HELP_MENU,
+ OTHER_MENU,
+! NULL_MENU,
+ NULL_MENU,
+ {"D", N_("DeleteHdr"), {MC_DELETE,1,{'d'}}, KS_NONE},
+ /* TRANSLATORS: shuffle headers (change the order of headers) */
+--- 2537,2543 ----
+
+ HELP_MENU,
+ OTHER_MENU,
+! {"I", N_("IndxHdr"), {MC_ADDHEADER,1,{'i'}}, KS_NONE},
+ NULL_MENU,
+ {"D", N_("DeleteHdr"), {MC_DELETE,1,{'d'}}, KS_NONE},
+ /* TRANSLATORS: shuffle headers (change the order of headers) */
+***************
+*** 2527,2533 ****
+
+ HELP_MENU,
+ OTHER_MENU,
+! NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+--- 2583,2589 ----
+
+ HELP_MENU,
+ OTHER_MENU,
+! {"I", N_("IndxHdr"), {MC_ADDHEADER,1,{'i'}}, KS_NONE},
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+diff -rc alpine-2.00/alpine/keymenu.h alpine-2.00.I.USE/alpine/keymenu.h
+*** alpine-2.00/alpine/keymenu.h 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/alpine/keymenu.h 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 212,218 ****
+ #define MC_COLLAPSE 800
+ #define MC_CHK_RECENT 801
+ #define MC_DECRYPT 802
+!
+
+ /*
+ * Some standard Key/Command Bindings
+--- 212,232 ----
+ #define MC_COLLAPSE 800
+ #define MC_CHK_RECENT 801
+ #define MC_DECRYPT 802
+! #define MC_CTHREAD 803
+! #define MC_OTHREAD 804
+! #define MC_DELTHREAD 805
+! #define MC_UNDTHREAD 806
+! #define MC_SELTHREAD 807
+! #define MC_SSUTHREAD 808
+! #define MC_DSUTHREAD 809
+! #define MC_USUTHREAD 810
+! #define MC_SORTHREAD 811
+! #define MC_NEXTHREAD 812
+! #define MC_KOLAPSE 813
+! #define MC_EXPTHREAD 814
+! #define MC_PRETHREAD 815
+! #define MC_QUOTA 816
+! #define MC_ADDHEADER 817
+
+ /*
+ * Some standard Key/Command Bindings
+***************
+*** 559,564 ****
+--- 573,579 ----
+ c_cfg_km,
+ c_sel_km,
+ c_fcc_km,
++ pine_quota_keymenu,
+ folder_km,
+ folder_sel_km,
+ folder_sela_km,
+diff -rc alpine-2.00/alpine/mailcmd.c alpine-2.00.I.USE/alpine/mailcmd.c
+*** alpine-2.00/alpine/mailcmd.c 2008-08-21 15:14:45.000000000 -0700
+--- alpine-2.00.I.USE/alpine/mailcmd.c 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 72,77 ****
+--- 72,78 ----
+ #include "../pith/tempfile.h"
+ #include "../pith/search.h"
+ #include "../pith/margin.h"
++ #include "../pith/rules.h"
+ #ifdef _WINDOWS
+ #include "../pico/osdep/mswin.h"
+ #endif
+***************
+*** 112,118 ****
+ char *choose_a_rule(int);
+ int select_by_keyword(MAILSTREAM *, SEARCHSET **);
+ char *choose_a_keyword(void);
+! int select_sort(struct pine *, int, SortOrder *, int *);
+ int print_index(struct pine *, MSGNO_S *, int);
+
+
+--- 113,119 ----
+ char *choose_a_rule(int);
+ int select_by_keyword(MAILSTREAM *, SEARCHSET **);
+ char *choose_a_keyword(void);
+! int select_sort(struct pine *, int, SortOrder *, int *, int);
+ int print_index(struct pine *, MSGNO_S *, int);
+
+
+***************
+*** 253,258 ****
+--- 254,260 ----
+ {'r', 'r', "R", N_("Recipient")},
+ {'p', 'p', "P", N_("Participant")},
+ {'b', 'b', "B", N_("Body")},
++ {'h', 'h', "H", N_("Header")},
+ {-1, 0, NULL, NULL}
+ };
+
+***************
+*** 972,978 ****
+ state->context_current, &recent_cnt,
+ F_ON(F_TAB_NO_CONFIRM,state)
+ ? NULL : &did_cancel))){
+! if(!in_inbox){
+ static ESCKEY_S inbox_opt[] = {
+ {'y', 'y', "Y", N_("Yes")},
+ {'n', 'n', "N", N_("No")},
+--- 974,980 ----
+ state->context_current, &recent_cnt,
+ F_ON(F_TAB_NO_CONFIRM,state)
+ ? NULL : &did_cancel))){
+! if(!in_inbox && F_OFF(F_AUTO_CIRCULAR_TAB,state)){
+ static ESCKEY_S inbox_opt[] = {
+ {'y', 'y', "Y", N_("Yes")},
+ {'n', 'n', "N", N_("No")},
+***************
+*** 1333,1339 ****
+ if(any_messages(msgmap, NULL, NULL)){
+ if(any_lflagged(msgmap, MN_SLCT) > 0L){
+ if(apply_command(state, stream, msgmap, 0,
+! AC_NONE, question_line)){
+ if(F_ON(F_AUTO_UNSELECT, state)){
+ agg_select_all(stream, msgmap, NULL, 0);
+ unzoom_index(state, stream, msgmap);
+--- 1335,1341 ----
+ if(any_messages(msgmap, NULL, NULL)){
+ if(any_lflagged(msgmap, MN_SLCT) > 0L){
+ if(apply_command(state, stream, msgmap, 0,
+! AC_NONE, question_line, 1)){
+ if(F_ON(F_AUTO_UNSELECT, state)){
+ agg_select_all(stream, msgmap, NULL, 0);
+ unzoom_index(state, stream, msgmap);
+***************
+*** 1351,1373 ****
+
+ /*-------- Sort command -------*/
+ case MC_SORT :
+ {
+ int were_threading = THREADING();
+ SortOrder sort = mn_get_sort(msgmap);
+ int rev = mn_get_revsort(msgmap);
+
+ dprint((1,"MAIL_CMD: sort\n"));
+! if(select_sort(state, question_line, &sort, &rev)){
+ /* $ command reinitializes threading collapsed/expanded info */
+ if(SORT_IS_THREADED(msgmap) && !SEP_THRDINDX())
+ erase_threading_info(stream, msgmap);
+
+ if(ps_global && ps_global->ttyo){
+ blank_keymenu(ps_global->ttyo->screen_rows - 2, 0);
+ ps_global->mangled_footer = 1;
+ }
+
+! sort_folder(stream, msgmap, sort, rev, SRT_VRB|SRT_MAN);
+ }
+
+ state->mangled_footer = 1;
+--- 1353,1387 ----
+
+ /*-------- Sort command -------*/
+ case MC_SORT :
++ case MC_SORTHREAD:
+ {
+ int were_threading = THREADING();
+ SortOrder sort = mn_get_sort(msgmap);
+ int rev = mn_get_revsort(msgmap);
++ int thread = (command == MC_SORT) ? 0 : 1;
+
+ dprint((1,"MAIL_CMD: sort\n"));
+! if(sort == SortThread)
+! sort = ps_global->thread_cur_sort;
+! if(select_sort(state, question_line, &sort, &rev, thread)){
+ /* $ command reinitializes threading collapsed/expanded info */
+ if(SORT_IS_THREADED(msgmap) && !SEP_THRDINDX())
+ erase_threading_info(stream, msgmap);
+
++ if(command == MC_SORTHREAD){
++ ps_global->thread_cur_sort = sort;
++ sort = SortThread;
++ }
++ else if(sort == SortThread) /* command = MC_SORT */
++ ps_global->thread_cur_sort = F_ON(F_THREAD_SORTS_BY_ARRIVAL, ps_global)
++ ? SortArrival : ps_global->thread_def_sort;
++
+ if(ps_global && ps_global->ttyo){
+ blank_keymenu(ps_global->ttyo->screen_rows - 2, 0);
+ ps_global->mangled_footer = 1;
+ }
+
+! sort_folder(stream, msgmap, sort, rev, SRT_VRB|SRT_MAN, 1);
+ }
+
+ state->mangled_footer = 1;
+***************
+*** 2368,2373 ****
+--- 2382,2388 ----
+
+ dprint((4, "\n - saving message -\n"));
+
++ saved_stream = stream; /* ugly hack! */
+ state->ugly_consider_advancing_bit = 0;
+ if(F_OFF(F_SAVE_PARTIAL_WO_CONFIRM, state)
+ && msgno_any_deletedparts(stream, msgmap)
+***************
+*** 2592,2597 ****
+--- 2607,2615 ----
+ role->nick = cpystr("Default Role");
+ }
+
++ if(state->role)
++ fs_give((void **)&state->role);
++ state->role = cpystr(role->nick); /* remember the role */
+ state->redrawer = NULL;
+ switch(action){
+ case 'c':
+***************
+*** 2642,2653 ****
+ char *nmsgs, ENVELOPE *env, long int rawmsgno, char *section,
+ SaveDel *dela, SavePreserveOrder *prea)
+ {
+! int rc, ku = -1, n, flags, last_rc = 0, saveable_count = 0, done = 0;
+ int delindex, preindex, r;
+ char prompt[6*MAX_SCREEN_COLS+1], *p, expanded[MAILTMPLEN];
+ char *buf = tmp_20k_buf;
+ char shortbuf[200];
+! char *folder;
+ HelpType help;
+ SaveDel del = DontAsk;
+ SavePreserveOrder pre = DontAskPreserve;
+--- 2660,2671 ----
+ char *nmsgs, ENVELOPE *env, long int rawmsgno, char *section,
+ SaveDel *dela, SavePreserveOrder *prea)
+ {
+! int rc, ku = -1, n = 0, flags, last_rc = 0, saveable_count = 0, done = 0;
+ int delindex, preindex, r;
+ char prompt[6*MAX_SCREEN_COLS+1], *p, expanded[MAILTMPLEN];
+ char *buf = tmp_20k_buf;
+ char shortbuf[200];
+! char *folder, folder2[MAXPATH];
+ HelpType help;
+ SaveDel del = DontAsk;
+ SavePreserveOrder pre = DontAskPreserve;
+***************
+*** 2655,2660 ****
+--- 2673,2681 ----
+ static HISTORY_S *history = NULL;
+ CONTEXT_S *tc;
+ ESCKEY_S ekey[10];
++ RULE_RESULT *rule;
++
++ saved_stream = state->mail_stream;
+
+ if(!cntxt)
+ panic("no context ptr in save_prompt");
+***************
+*** 2664,2669 ****
+--- 2685,2699 ----
+ if(!(folder = save_get_default(state, env, rawmsgno, section, cntxt)))
+ return(0); /* message expunged! */
+
++ if (rule = get_result_rule(V_SAVE_RULES, FOR_SAVE, env)){
++ strncpy(folder2,rule->result,sizeof(folder2)-1);
++ folder2[sizeof(folder2)-1] = '\0';
++ folder = folder2;
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++
+ /* how many context's can be saved to... */
+ for(tc = state->context_list; tc; tc = tc->next)
+ if(!NEWS_TEST(tc))
+***************
+*** 3172,3177 ****
+--- 3202,3211 ----
+ if(SORT_IS_THREADED(msgmap))
+ refresh_sort(stream, msgmap, SRT_NON);
+
++ if (msgmap->nmsgs
++ && F_ON(F_ENHANCED_THREAD, state) && COLL_THRDS())
++ kolapse_thread(state, stream, msgmap, '[', 0);
++
+ state->mangled_body = 1;
+ state->mangled_header = 1;
+ q_status_message2(SM_ORDER, 0, 4,
+***************
+*** 3266,3271 ****
+--- 3300,3308 ----
+ */
+ if(SORT_IS_THREADED(msgmap))
+ refresh_sort(stream, msgmap, SRT_NON);
++ if (msgmap->nmsgs
++ && F_ON(F_ENHANCED_THREAD, state) && COLL_THRDS())
++ kolapse_thread(state, stream, msgmap, '[', 0);
+ }
+ else{
+ if(del_count)
+***************
+*** 3347,3352 ****
+--- 3384,3392 ----
+ {-1, 0, NULL, NULL}
+ };
+
++ if(F_ON(F_IGNORE_SIZE, ps_global))
++ return 'y';
++
+ if(flags & SSCP_INIT || flags & SSCP_END){
+ if(flags & SSCP_END && possible_corruption)
+ q_status_message(SM_ORDER, 3, 3, "There is possible data corruption, check the results");
+***************
+*** 6933,6939 ****
+ * Maybe it makes sense to zoom after a select but not after a colon
+ * command even though they are very similar.
+ */
+! thread_command(state, state->mail_stream, msgmap, ':', -FOOTER_ROWS(state));
+ }
+ else{
+ if((all_selected =
+--- 6973,6979 ----
+ * Maybe it makes sense to zoom after a select but not after a colon
+ * command even though they are very similar.
+ */
+! thread_command(state, state->mail_stream, msgmap, ':', -FOOTER_ROWS(state), 1);
+ }
+ else{
+ if((all_selected =
+***************
+*** 6989,6995 ****
+ ----*/
+ int
+ apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
+! UCS preloadkeystroke, int flags, int q_line)
+ {
+ int i = 8, /* number of static entries in sel_opts3 */
+ rv = 0,
+--- 7029,7035 ----
+ ----*/
+ int
+ apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
+! UCS preloadkeystroke, int flags, int q_line, int display)
+ {
+ int i = 8, /* number of static entries in sel_opts3 */
+ rv = 0,
+***************
+*** 7141,7149 ****
+ collapse_or_expand(state, stream, msgmap,
+ F_ON(F_SLASH_COLL_ENTIRE, ps_global)
+ ? 0L
+! : mn_get_cur(msgmap));
+ break;
+
+ case ':' :
+ select_thread_stmp(state, stream, msgmap);
+ break;
+--- 7181,7199 ----
+ collapse_or_expand(state, stream, msgmap,
+ F_ON(F_SLASH_COLL_ENTIRE, ps_global)
+ ? 0L
+! : mn_get_cur(msgmap),
+! display);
+ break;
+
++ case '[' :
++ collapse_this_thread(state, stream, msgmap, display, 0);
++ break;
++
++ case ']' :
++ expand_this_thread(state, stream, msgmap, display, 0);
++ break;
++
++
+ case ':' :
+ select_thread_stmp(state, stream, msgmap);
+ break;
+***************
+*** 7670,7676 ****
+ int not = 0, me = 0;
+ char sstring[80], savedsstring[80], tmp[128];
+ char *p, *sval = NULL;
+! char buftmp[MAILTMPLEN];
+ ESCKEY_S ekey[8];
+ ENVELOPE *env = NULL;
+ HelpType help;
+--- 7720,7726 ----
+ int not = 0, me = 0;
+ char sstring[80], savedsstring[80], tmp[128];
+ char *p, *sval = NULL;
+! char buftmp[MAILTMPLEN], namehdr[80];
+ ESCKEY_S ekey[8];
+ ENVELOPE *env = NULL;
+ HelpType help;
+***************
+*** 7757,7762 ****
+--- 7807,7846 ----
+ sval = "BODYTEXT";
+ break;
+
++ case 'h' :
++ strcpy(tmp, "Name of HEADER to match : ");
++ flags = OE_APPEND_CURRENT;
++ namehdr[0] = '\0';
++ r = 'x';
++ while (r == 'x'){
++ int done = 0;
++
++ r = optionally_enter(namehdr, -FOOTER_ROWS(ps_global), 0,
++ sizeof(namehdr), tmp, ekey, NO_HELP, &flags);
++ if (r == 1){
++ cmd_cancelled("Selection by text");
++ return(1);
++ }
++ removing_leading_white_space(namehdr);
++ while(!done){
++ while ((namehdr[0] != '\0') && /* remove trailing ":" */
++ (namehdr[strlen(namehdr) - 1] == ':'))
++ namehdr[strlen(namehdr) - 1] = '\0';
++ if ((namehdr[0] != '\0')
++ && isspace((unsigned char) namehdr[strlen(namehdr) - 1]))
++ removing_trailing_white_space(namehdr);
++ else
++ done++;
++ }
++ if (strchr(namehdr,' ') || strchr(namehdr,'\t') ||
++ strchr(namehdr,':'))
++ namehdr[0] = '\0';
++ if (namehdr[0] == '\0')
++ r = 'x';
++ }
++ sval = namehdr;
++ break;
++
+ case 'x':
+ break;
+
+***************
+*** 7953,7959 ****
+ flagsforhist = (not ? 0x1 : 0) + (me ? 0x2 : 0);
+ save_hist(history, sstring, flagsforhist, NULL);
+
+! rv = agg_text_select(stream, msgmap, type, not, me, sstring, "utf-8", limitsrch);
+ if(we_cancel)
+ cancel_busy_cue(0);
+
+--- 8037,8043 ----
+ flagsforhist = (not ? 0x1 : 0) + (me ? 0x2 : 0);
+ save_hist(history, sstring, flagsforhist, NULL);
+
+! rv = agg_text_select(stream, msgmap, type, namehdr, not, me, sstring, "utf-8", limitsrch);
+ if(we_cancel)
+ cancel_busy_cue(0);
+
+***************
+*** 8874,8879 ****
+--- 8958,9102 ----
+ return(ret);
+ }
+
++ int process_quota_cmd(int cmd, MSGNO_S *msgmap, SCROLL_S *sparms)
++ {
++ return cmd;
++ }
++
++ void cmd_quota (struct pine *state)
++ {
++ QUOTALIST *imapquota;
++ NETMBX mb;
++ unsigned long len, storageuse, storagelim, messageuse, messagelim;
++ STORE_S *store;
++ SCROLL_S sargs;
++ char *linedata, *storageq = NULL, *messageq = NULL;
++ int storage=0, message=0, other=0, storagelen = 0, messagelen = 0;
++
++ if(!state->mail_stream || !is_imap_stream(state->mail_stream)){
++ q_status_message(SM_ORDER, 1, 5, "Quota only available for IMAP folders");
++ return;
++ }
++
++ if (state->mail_stream
++ && !sp_dead_stream(state->mail_stream)
++ && state->mail_stream->mailbox
++ && *state->mail_stream->mailbox
++ && mail_valid_net_parse(state->mail_stream->mailbox, &mb))
++ imap_getquotaroot(state->mail_stream, mb.mailbox);
++
++ if(!state->quota) /* failed ? */
++ return; /* go back... */
++
++ if(!(store = so_get(CharStar, NULL, EDIT_ACCESS))){
++ q_status_message(SM_ORDER | SM_DING, 3, 3, "Error allocating space.");
++ return;
++ }
++
++ if (state->mail_stream && state->mail_stream->original_mailbox){
++ len = strlen(state->mail_stream->original_mailbox) + 19;
++ linedata = (char *) fs_get(len*sizeof(char));
++ sprintf(linedata,"Quota Report for %s\n",
++ state->mail_stream->original_mailbox);
++ so_puts(store,linedata);
++ if (linedata)
++ fs_give((void **)&linedata);
++ }
++ else
++ so_puts(store,"Quota Report:\n");
++ so_puts(store,"\n");
++
++ for (imapquota = state->quota; imapquota; imapquota = imapquota->next){
++ if(!strucmp(imapquota->name,"STORAGE")){
++ storage++;
++ storagelen = strlen(long2string(imapquota->limit)) + 1+3;
++ storageuse = imapquota->usage;
++ storagelim = imapquota->limit;
++ }
++ if(!strucmp(imapquota->name,"MESSAGE")){
++ message++;
++ messagelen = strlen(long2string(imapquota->limit)) + 1+9;
++ messageuse = imapquota->usage;
++ messagelim = imapquota->limit;
++ }
++ other += strucmp(imapquota->name,"STORAGE") &&
++ strucmp(imapquota->name,"MESSAGE") ? 0 : 1;
++ }
++
++ storageq = (char *) fs_get(storagelen*sizeof(char));
++ if (storage)
++ sprintf(storageq, "%lu KB", storageuse);
++ messageq = (char *) fs_get(messagelen*sizeof(char));
++ if (message)
++ sprintf(messageq, "%lu message%s", messageuse, plural(messageuse));
++ len = strlen("Usage: ") + storagelen + messagelen + 9;
++ linedata = (char *) fs_get(len*sizeof(char));
++ sprintf(linedata,"Usage: %s%s%s%s\n", (storage ? storageq : ""),
++ (message ? (storage ? " (" : "") : ""),
++ (message ? messageq : ""),
++ (message ? (storage ? ")" : "") : ""));
++ so_puts(store, linedata);
++ if (storageq)
++ fs_give((void **)&storageq);
++ if (messageq)
++ fs_give((void **)&messageq);
++ if (linedata)
++ fs_give((void **)&linedata);
++
++ storageq = (char *) fs_get(storagelen*sizeof(char));
++ if (storage)
++ sprintf(storageq, "%lu KB", storagelim);
++ messageq = (char *) fs_get(messagelen*sizeof(char));
++ if (message)
++ sprintf(messageq, "%lu message%s", messagelim, plural(messagelim));
++ len = strlen("Limit: ") + storagelen + messagelen + 9;
++ linedata = (char *) fs_get(len*sizeof(char));
++ sprintf(linedata,"Limit: %s%s%s%s", (storage ? storageq : ""),
++ (message ? (storage ? " (" : "") : ""),
++ (message ? messageq : ""),
++ (message ? (storage ? ")" : "") : ""));
++ so_puts(store, linedata);
++ if (storageq)
++ fs_give((void **)&storageq);
++ if (messageq)
++ fs_give((void **)&messageq);
++ if (linedata)
++ fs_give((void **)&linedata);
++
++ for (imapquota = state->quota; other && imapquota;
++ imapquota = imapquota->next){
++ if (strucmp(imapquota->name,"STORAGE") &&
++ strucmp(imapquota->name,"MESSAGE")){
++ len = (imapquota->name ? strlen(imapquota->name) : strlen("No Name"));
++ linedata = (char *) fs_get(len*sizeof(char));
++ sprintf(linedata,
++ "Resource : %s\nUsage : %lu (%lu%%)\nLimit : %lu\n\n",
++ (imapquota->name ? imapquota->name : "No Name"),
++ imapquota->usage, 100*imapquota->usage/imapquota->limit,
++ imapquota->limit);
++ so_puts(store,linedata);
++ if (linedata)
++ fs_give((void **)&linedata);
++ }
++ }
++
++ memset(&sargs, 0, sizeof(SCROLL_S));
++ sargs.text.text = so_text(store);
++ sargs.text.src = CharStar;
++ sargs.text.desc = _("Quota Resources Summary");
++ sargs.bar.title = _("QUOTA SUMMARY");
++ sargs.proc.tool = process_quota_cmd;
++ sargs.help.text = NO_HELP;
++ sargs.help.title = NULL;
++ sargs.keys.menu = &pine_quota_keymenu;
++ setbitmap(sargs.keys.bitmap);
++
++ scrolltool(&sargs);
++ so_give(&store);
++
++ if (state->quota)
++ mail_free_quotalist(&(state->quota));
++ }
+
+ /*----------------------------------------------------------------------
+ Prompt the user for the type of sort he desires
+***************
+*** 8884,8893 ****
+ Returns 0 if it was cancelled, 1 otherwise.
+ ----*/
+ int
+! select_sort(struct pine *state, int ql, SortOrder *sort, int *rev)
+ {
+ char prompt[200], tmp[3], *p;
+! int s, i;
+ int deefault = 'a', retval = 1;
+ HelpType help;
+ ESCKEY_S sorts[14];
+--- 9107,9116 ----
+ Returns 0 if it was cancelled, 1 otherwise.
+ ----*/
+ int
+! select_sort(struct pine *state, int ql, SortOrder *sort, int *rev, int thread)
+ {
+ char prompt[200], tmp[3], *p;
+! int s, i, j;
+ int deefault = 'a', retval = 1;
+ HelpType help;
+ ESCKEY_S sorts[14];
+***************
+*** 8920,8936 ****
+ strncpy(prompt, _("Choose type of sort, or 'R' to reverse current sort : "),
+ sizeof(prompt));
+
+! for(i = 0; state->sort_types[i] != EndofList; i++) {
+! sorts[i].rval = i;
+! p = sorts[i].label = sort_name(state->sort_types[i]);
+! while(*(p+1) && islower((unsigned char)*p))
+! p++;
+!
+! sorts[i].ch = tolower((unsigned char)(tmp[0] = *p));
+! sorts[i].name = cpystr(tmp);
+!
+! if(mn_get_sort(state->msgmap) == state->sort_types[i])
+! deefault = sorts[i].rval;
+ }
+
+ sorts[i].ch = 'r';
+--- 9143,9168 ----
+ strncpy(prompt, _("Choose type of sort, or 'R' to reverse current sort : "),
+ sizeof(prompt));
+
+! for(i = 0, j = 0; state->sort_types[i] != EndofList; i++) {
+! sorts[i].rval = i;
+! sorts[i].name = cpystr("");
+! sorts[i].label = "";
+! sorts[i].ch = -2;
+! if (!thread || allowed_thread_key(state->sort_types[i])){
+! p = sorts[j].label = sort_name(state->sort_types[i]);
+! while(*(p+1) && islower((unsigned char)*p))
+! p++;
+! sorts[j].ch = tolower((unsigned char)(tmp[0] = *p));
+! sorts[j++].name = cpystr(tmp);
+! }
+!
+! if (thread){
+! if (state->thread_def_sort == state->sort_types[i])
+! deefault = sorts[j-1].rval;
+! }
+! else
+! if(mn_get_sort(state->msgmap) == state->sort_types[i])
+! deefault = sorts[i].rval;
+ }
+
+ sorts[i].ch = 'r';
+***************
+*** 8954,8961 ****
+ state->mangled_body = 1; /* signal screen's changed */
+ if(s == 'r')
+ *rev = !mn_get_revsort(state->msgmap);
+! else
+ *sort = state->sort_types[s];
+
+ if(F_ON(F_SHOW_SORT, ps_global))
+ ps_global->mangled_header = 1;
+--- 9186,9202 ----
+ state->mangled_body = 1; /* signal screen's changed */
+ if(s == 'r')
+ *rev = !mn_get_revsort(state->msgmap);
+! else{
+! if(thread){
+! for(i = 0; state->sort_types[i] != EndofList; i++){
+! if(struncmp(sort_name(state->sort_types[i]),
+! sorts[s].label, strlen(sorts[s].label)) == 0)
+! break;
+! }
+! s = i;
+! }
+ *sort = state->sort_types[s];
++ }
+
+ if(F_ON(F_SHOW_SORT, ps_global))
+ ps_global->mangled_header = 1;
+***************
+*** 9340,9342 ****
+--- 9581,9958 ----
+ }
+
+ #endif /* _WINDOWS */
++
++ void
++ cmd_delete_this_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ unsigned long rawno, top, save_kolapsed;
++ PINETHRD_S *thrd = NULL, *nxthrd;
++
++ if(!stream)
++ return;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_this_thread(stream, msgmap, rawno);
++ top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ save_kolapsed = this_thread_is_kolapsed(state, stream, msgmap, top);
++ collapse_this_thread(state, stream, msgmap, 0, 0);
++ thread_command(state, stream, msgmap, 'd', -FOOTER_ROWS(state), 1);
++ if (!save_kolapsed)
++ expand_this_thread(state, stream, msgmap, 0, 0);
++ }
++
++ void
++ cmd_delete_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ unsigned long rawno, top, orig_top, topnxt, save_kolapsed;
++ PINETHRD_S *thrd = NULL, *nxthrd;
++ int done = 0, count;
++
++ if(!stream)
++ return;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap, rawno);
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ while (!done){
++ cmd_delete_this_thread(state, stream, msgmap);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, rawno));
++ cmd_delete(state, msgmap, MCMD_NONE, cmd_delete_index);
++ count = count_thread(state, stream, msgmap, rawno);
++ q_status_message2(SM_ORDER, 0, 1, "%s message%s marked deleted",
++ int2string(count), plural(count));
++ }
++
++ int
++ collapse_this_thread(state, stream, msgmap, display, special)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ int special;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL, *nthrd;
++ unsigned long rawno, orig, msgno;
++
++ if(!stream)
++ return 0;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return rv;
++
++ collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno);
++
++ if (special && collapsed){
++ expand_this_thread(state, stream, msgmap, 0, 0);
++ collapsed = 0;
++ }
++
++ clear_index_cache_ent(stream, rawno, 0);
++
++ if (!collapsed && thrd->next){
++ if (thrd->rawno == top_thread(stream, thrd->rawno))
++ collapse_or_expand(state, stream, msgmap, mn_get_cur(msgmap), display);
++ else{
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno), MN_COLL, 1);
++ set_thread_subtree(stream, thrd, msgmap, 1, MN_CHID);
++ }
++ }
++ else{
++ if (!collapsed && special
++ && ((F_OFF(F_ENHANCED_THREAD, state) && !thrd->next)
++ || F_ON(F_ENHANCED_THREAD, state))){
++ if (thrd->toploose){
++ if (thrd->rawno != thrd->toploose)
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_CHID,
++ 1);
++ else
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_COLL,
++ 1);
++ }
++ }
++ else{
++ rv = 0;
++ if (display)
++ q_status_message(SM_ORDER, 0, 1, "Thread already collapsed");
++ }
++ }
++ return rv;
++ }
++
++ void
++ collapse_thread(state, stream, msgmap, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL;
++ unsigned long orig, orig_top, top;
++
++ if(!stream)
++ return;
++
++ expand_this_thread(state, stream, msgmap, display, 1);
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap,orig);
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ while (!done){
++ collapse_this_thread(state, stream, msgmap, display, 1);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, orig_top));
++ }
++
++ int
++ expand_this_thread(state, stream, msgmap, display, special)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ int special;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL, *nthrd;
++ unsigned long rawno, orig, msgno;
++
++ if(!stream)
++ return 0;
++
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_this_thread(stream, msgmap,orig);
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return rv;
++
++ collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno);
++
++ if (special && !collapsed){
++ collapse_this_thread(state, stream, msgmap, 0, 0);
++ collapsed = 1;
++ }
++
++ clear_index_cache_ent(stream, rawno, 0);
++
++ if (collapsed && thrd->next){
++ if (thrd->rawno == top_thread(stream, thrd->rawno))
++ collapse_or_expand(state, stream, msgmap, mn_get_cur(msgmap), display);
++ else{
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno), MN_COLL, 0);
++ set_thread_subtree(stream, thrd, msgmap, 0, MN_CHID);
++ }
++ }
++ else{
++ if (collapsed && special
++ && ((F_OFF(F_ENHANCED_THREAD, state) && !thrd->next)
++ || F_ON(F_ENHANCED_THREAD, state))){
++ if (thrd->toploose)
++ if (thrd->rawno != thrd->toploose)
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_CHID, 0);
++ else
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_COLL, 0);
++ }
++ else{
++ rv = 0;
++ if (display)
++ q_status_message(SM_ORDER, 0, 1, "Thread already expanded");
++ }
++ }
++ return rv;
++ }
++
++ void
++ expand_thread(state, stream, msgmap, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL;
++ unsigned long orig, orig_top, top;
++
++ if(!stream)
++ return;
++
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ while (!done){
++ expand_this_thread(state, stream, msgmap, display, 1);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, orig_top));
++ }
++
++
++ void
++ cmd_undelete_this_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ unsigned long rawno;
++ int save_kolapsed;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ save_kolapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno);
++ collapse_this_thread(state, stream, msgmap, 0, 0);
++ thread_command(state, stream, msgmap, 'u', -FOOTER_ROWS(state), 1);
++ if (!save_kolapsed)
++ expand_this_thread(state, stream, msgmap, 0, 0);
++ }
++
++ void
++ cmd_undelete_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno, top, orig_top;
++ int done = 0, count;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap, rawno);
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ while (!done){
++ cmd_undelete_this_thread(state, stream, msgmap);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, rawno));
++ count = count_thread(state, stream, msgmap, rawno);
++ q_status_message2(SM_ORDER, 0, 1, "Deletion mark removed from %s message%s",
++ int2string(count), plural(count));
++ }
++
++ void
++ kolapse_thread(state, stream, msgmap, ch, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ char ch;
++ int display;
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno;
++ int rv = 1, done = 0;
++
++ if(!stream)
++ return;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return;
++
++ clear_index_cache(stream, 0);
++ mn_set_cur(msgmap,1); /* go to the first message */
++ while (!done){
++ if (ch == '[')
++ collapse_thread(state, stream, msgmap, display);
++ else
++ expand_thread(state, stream, msgmap, display);
++ if ((rv = move_next_thread(state, stream, msgmap, 0)) <= 0)
++ done++;
++ }
++
++ if (rv < 0){
++ if (display)
++ q_status_message(SM_ORDER, 0, 1, (ch == '[')
++ ? "Error while collapsing thread"
++ : "Error while expanding thread");
++ }
++ else
++ if(display)
++ q_status_message(SM_ORDER, 0, 1, (ch == '[')
++ ? "All threads collapsed. Use \"}\" to expand them"
++ : "All threads expanded. Use \"{\" to collapse them");
++
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream,rawno)));
++ }
++
++ void
++ cmd_select_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ unsigned long rawno;
++ int save_kolapsed;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ save_kolapsed = thread_is_kolapsed(state, stream, msgmap, rawno);
++ collapse_thread(state, stream, msgmap, 0);
++ thread_command(state, stream, msgmap, ':', -FOOTER_ROWS(state), 1);
++ if (!save_kolapsed)
++ expand_thread(state, stream, msgmap, 0);
++ }
++
+diff -rc alpine-2.00/alpine/mailcmd.h alpine-2.00.I.USE/alpine/mailcmd.h
+*** alpine-2.00/alpine/mailcmd.h 2008-03-19 12:43:03.000000000 -0700
+--- alpine-2.00.I.USE/alpine/mailcmd.h 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 83,89 ****
+ int ask_mailbox_reopen(struct pine *, int *);
+ void visit_folder(struct pine *, char *, CONTEXT_S *, MAILSTREAM *, unsigned long);
+ int select_by_current(struct pine *, MSGNO_S *, CmdWhere);
+! int apply_command(struct pine *, MAILSTREAM *, MSGNO_S *, UCS, int, int);
+ char **choose_list_of_keywords(void);
+ char *choose_a_charset(int);
+ char **choose_list_of_charsets(void);
+--- 83,89 ----
+ int ask_mailbox_reopen(struct pine *, int *);
+ void visit_folder(struct pine *, char *, CONTEXT_S *, MAILSTREAM *, unsigned long);
+ int select_by_current(struct pine *, MSGNO_S *, CmdWhere);
+! int apply_command(struct pine *, MAILSTREAM *, MSGNO_S *, UCS, int, int, int);
+ char **choose_list_of_keywords(void);
+ char *choose_a_charset(int);
+ char **choose_list_of_charsets(void);
+***************
+*** 101,106 ****
+ int flag_callback(int, long);
+ MPopup *flag_submenu(MESSAGECACHE *);
+ #endif
+!
+
+ #endif /* PINE_MAILCMD_INCLUDED */
+--- 101,115 ----
+ int flag_callback(int, long);
+ MPopup *flag_submenu(MESSAGECACHE *);
+ #endif
+! void cmd_delete_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
+! void cmd_delete_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
+! void cmd_undelete_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
+! void cmd_undelete_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
+! void cmd_select_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
+! void kolapse_thread(struct pine *, MAILSTREAM *, MSGNO_S *, char, int);
+! void collapse_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
+! void expand_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
+! int collapse_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int, int);
+! int expand_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int, int);
+
+ #endif /* PINE_MAILCMD_INCLUDED */
+diff -rc alpine-2.00/alpine/mailindx.c alpine-2.00.I.USE/alpine/mailindx.c
+*** alpine-2.00/alpine/mailindx.c 2008-07-09 22:01:13.000000000 -0700
+--- alpine-2.00.I.USE/alpine/mailindx.c 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 228,233 ****
+--- 228,235 ----
+ state->prev_screen = mail_index_screen;
+ state->next_screen = SCREEN_FUN_NULL;
+
++ setup_threading_display_style();
++
+ if(THRD_AUTO_VIEW()
+ && sp_viewing_a_thread(state->mail_stream)
+ && state->view_skipped_index
+***************
+*** 239,248 ****
+--- 241,254 ----
+
+ adjust_cur_to_visible(state->mail_stream, state->msgmap);
+
++ strcpy(state->screen_name,"index");
++
+ if(THRD_INDX())
+ thread_index_screen(state);
+ else
+ index_index_screen(state);
++
++ strcpy(state->screen_name,"unknown");
+ }
+
+
+***************
+*** 560,565 ****
+--- 566,572 ----
+
+ /*---------- Scroll line up ----------*/
+ case MC_CHARUP :
++ previtem:
+ (void) process_cmd(state, stream, msgmap, MC_PREVITEM,
+ (style == MsgIndex
+ || style == MultiMsgIndex
+***************
+*** 577,582 ****
+--- 584,590 ----
+
+ /*---------- Scroll line down ----------*/
+ case MC_CHARDOWN :
++ nextitem:
+ /*
+ * Special Page framing handling here. If we
+ * did something that should scroll-by-a-line, frame
+***************
+*** 794,799 ****
+--- 802,808 ----
+
+
+ case MC_THRDINDX :
++ mc_thrdindx:
+ msgmap->top = msgmap->top_after_thrd;
+ if(unview_thread(state, stream, msgmap)){
+ state->next_screen = mail_index_screen;
+***************
+*** 844,850 ****
+ && mp.col == id.plus_col
+ && style != ThreadIndex){
+ collapse_or_expand(state, stream, msgmap,
+! mn_get_cur(msgmap));
+ }
+ else if (mp.doubleclick){
+ if(mp.button == M_BUTTON_LEFT){
+--- 853,859 ----
+ && mp.col == id.plus_col
+ && style != ThreadIndex){
+ collapse_or_expand(state, stream, msgmap,
+! mn_get_cur(msgmap), 1);
+ }
+ else if (mp.doubleclick){
+ if(mp.button == M_BUTTON_LEFT){
+***************
+*** 923,928 ****
+--- 932,939 ----
+ reset_index_border();
+ break;
+
++ case MC_QUOTA:
++ cmd_quota(state);
+
+ /*---------- Redraw ----------*/
+ case MC_REPAINT :
+***************
+*** 951,959 ****
+
+
+ case MC_COLLAPSE :
+! thread_command(state, stream, msgmap, ch, -FOOTER_ROWS(state));
+ break;
+
+ case MC_DELETE :
+ case MC_UNDELETE :
+ case MC_REPLY :
+--- 962,1066 ----
+
+
+ case MC_COLLAPSE :
+! thread_command(state, stream, msgmap, ch, -FOOTER_ROWS(state), 1);
+ break;
+
++ case MC_CTHREAD :
++ if (SEP_THRDINDX())
++ goto mc_thrdindx;
++ else
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL,
++ "to collapse a thread"))
++ collapse_thread(state, stream,msgmap, 1);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_OTHREAD :
++ if (SEP_THRDINDX())
++ goto view_a_thread;
++ else
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to expand a thread"))
++ expand_thread(state, stream,msgmap, 1);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_NEXTHREAD:
++ case MC_PRETHREAD:
++ if (THRD_INDX()){
++ if (cmd == MC_NEXTHREAD)
++ goto nextitem;
++ else
++ goto previtem;
++ }
++ else
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL,
++ "to move to other thread"))
++ move_thread(state, stream, msgmap,
++ cmd == MC_NEXTHREAD ? 1 : -1);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_KOLAPSE:
++ case MC_EXPTHREAD:
++ if (SEP_THRDINDX()){
++ q_status_message(SM_ORDER, 0, 1,
++ "Command not available in this screen");
++ }
++ else{
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL,
++ cmd == MC_KOLAPSE ? "to collapse" : "to expand"))
++ kolapse_thread(state, stream, msgmap,
++ (cmd == MC_KOLAPSE) ? '[' : ']', 1);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ }
++ break;
++
++ case MC_DELTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to delete"))
++ cmd_delete_thread(state, stream, msgmap);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_UNDTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to undelete"))
++ cmd_undelete_thread(state, stream, msgmap);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_SELTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to undelete"))
++ cmd_select_thread(state, stream, msgmap);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
+ case MC_DELETE :
+ case MC_UNDELETE :
+ case MC_REPLY :
+***************
+*** 974,986 ****
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
+! collapsed = thrd && thrd->next
+! && get_lflag(stream, NULL, rawno, MN_COLL);
+ }
+
+ if(collapsed){
+ thread_command(state, stream, msgmap,
+! ch, -FOOTER_ROWS(state));
+ /* increment current */
+ if(cmd == MC_DELETE){
+ advance_cur_after_delete(state, stream, msgmap,
+--- 1081,1092 ----
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
+! collapsed = thread_is_kolapsed(ps_global, stream, msgmap, rawno);
+ }
+
+ if(collapsed){
+ thread_command(state, stream, msgmap,
+! ch, -FOOTER_ROWS(state),1);
+ /* increment current */
+ if(cmd == MC_DELETE){
+ advance_cur_after_delete(state, stream, msgmap,
+***************
+*** 2672,2677 ****
+--- 2778,2784 ----
+ n = mn_raw2m(msgs, thrd->rawno);
+
+ while(thrd){
++ unsigned long branch;
+ if(!msgline_hidden(stream, msgs, n, 0)
+ && (++m % lines_per_page) == 1L)
+ t = n;
+***************
+*** 2740,2750 ****
+
+ /* n is the end of this thread */
+ while(thrd){
+ n = mn_raw2m(msgs, thrd->rawno);
+! if(thrd->branch)
+! thrd = fetch_thread(stream, thrd->branch);
+! else if(thrd->next)
+! thrd = fetch_thread(stream, thrd->next);
+ else
+ thrd = NULL;
+ }
+--- 2847,2858 ----
+
+ /* n is the end of this thread */
+ while(thrd){
++ unsigned long next = 0L, branch = 0L;
+ n = mn_raw2m(msgs, thrd->rawno);
+! if(branch = get_branch(stream,thrd))
+! thrd = fetch_thread(stream, branch);
+! else if(next = get_next(stream,thrd))
+! thrd = fetch_thread(stream, next);
+ else
+ thrd = NULL;
+ }
+***************
+*** 2852,2858 ****
+
+ void
+ thread_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
+! UCS preloadkeystroke, int q_line)
+ {
+ PINETHRD_S *thrd = NULL;
+ unsigned long rawno, save_branch;
+--- 2960,2966 ----
+
+ void
+ thread_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
+! UCS preloadkeystroke, int q_line, int display)
+ {
+ PINETHRD_S *thrd = NULL;
+ unsigned long rawno, save_branch;
+***************
+*** 2901,2907 ****
+ cancel_busy_cue(0);
+
+ (void ) apply_command(state, stream, msgmap, preloadkeystroke, flags,
+! q_line);
+
+ /* restore the original flags */
+ copy_lflags(stream, msgmap, MN_STMP, MN_SLCT);
+--- 3009,3015 ----
+ cancel_busy_cue(0);
+
+ (void ) apply_command(state, stream, msgmap, preloadkeystroke, flags,
+! q_line, display);
+
+ /* restore the original flags */
+ copy_lflags(stream, msgmap, MN_STMP, MN_SLCT);
+***************
+*** 3395,3401 ****
+ if(set){
+ sort_folder(ps_global->mail_stream, ps_global->msgmap,
+ order & 0x000000ff,
+! (order & 0x00000100) != 0, SRT_VRB);
+ mswin_beginupdate();
+ update_titlebar_message();
+ update_titlebar_status();
+--- 3503,3509 ----
+ if(set){
+ sort_folder(ps_global->mail_stream, ps_global->msgmap,
+ order & 0x000000ff,
+! (order & 0x00000100) != 0, SRT_VRB, 1);
+ mswin_beginupdate();
+ update_titlebar_message();
+ update_titlebar_status();
+diff -rc alpine-2.00/alpine/mailindx.h alpine-2.00.I.USE/alpine/mailindx.h
+*** alpine-2.00/alpine/mailindx.h 2007-10-15 14:02:56.000000000 -0700
+--- alpine-2.00.I.USE/alpine/mailindx.h 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 102,108 ****
+ void paint_index_hline(MAILSTREAM *, long, ICE_S *);
+ void setup_index_state(int);
+ void warn_other_cmds(void);
+! void thread_command(struct pine *, MAILSTREAM *, MSGNO_S *, UCS, int);
+ COLOR_PAIR *apply_rev_color(COLOR_PAIR *, int);
+ #ifdef _WINDOWS
+ int index_sort_callback(int, long);
+--- 102,108 ----
+ void paint_index_hline(MAILSTREAM *, long, ICE_S *);
+ void setup_index_state(int);
+ void warn_other_cmds(void);
+! void thread_command(struct pine *, MAILSTREAM *, MSGNO_S *, UCS, int, int);
+ COLOR_PAIR *apply_rev_color(COLOR_PAIR *, int);
+ #ifdef _WINDOWS
+ int index_sort_callback(int, long);
+diff -rc alpine-2.00/alpine/mailpart.c alpine-2.00.I.USE/alpine/mailpart.c
+*** alpine-2.00/alpine/mailpart.c 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/alpine/mailpart.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 2145,2150 ****
+--- 2145,2155 ----
+ return(1);
+ }
+
++ /* ok, we have a filename. Now check if there is a template, and if
++ * so, rename the file accordingly
++ */
++ filename = mc_template(filename, a->body, a->can_display & MCD_EXT_PROMPT);
++
+ if((store = so_get(FileStar, filename, WRITE_ACCESS|OWNER_ONLY)) == NULL){
+ q_status_message2(SM_ORDER | SM_DING, 3, 5,
+ _("Error \"%s\", Can't write file %s"),
+***************
+*** 3307,3313 ****
+ /*
+ * For consistency, the first question is always "include text?"
+ */
+! if((include_text = reply_text_query(ps_global, 1, &prefix)) >= 0
+ && reply_news_test(a->body->nested.msg->env, outgoing) > 0
+ && reply_harvest(ps_global, msgno, a->number,
+ a->body->nested.msg->env, &saved_from,
+--- 3312,3318 ----
+ /*
+ * For consistency, the first question is always "include text?"
+ */
+! if((include_text = reply_text_query(ps_global, 1, NULL, &prefix)) >= 0
+ && reply_news_test(a->body->nested.msg->env, outgoing) > 0
+ && reply_harvest(ps_global, msgno, a->number,
+ a->body->nested.msg->env, &saved_from,
+diff -rc alpine-2.00/alpine/mailview.c alpine-2.00.I.USE/alpine/mailview.c
+*** alpine-2.00/alpine/mailview.c 2008-08-01 17:32:26.000000000 -0700
+--- alpine-2.00.I.USE/alpine/mailview.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 44,49 ****
+--- 44,50 ----
+ #include "dispfilt.h"
+ #include "busy.h"
+ #include "smime.h"
++ #include "roleconf.h"
+ #include "../pith/conf.h"
+ #include "../pith/filter.h"
+ #include "../pith/msgno.h"
+***************
+*** 129,134 ****
+--- 130,136 ----
+ #define SS_CUR 2
+ #define SS_FREE 3
+
++ static ACTION_S *role_chosen = NULL;
+
+ /*
+ * Handle hints.
+***************
+*** 203,209 ****
+--- 205,219 ----
+ int pcpine_view_cursor(int, long);
+ #endif
+
++ static char *prefix;
++ #define NO_FLOWED 0x0000
++ #define IS_FLOWED 0x0001
++ #define DELETEQUO 0x0010
++ #define COLORAQUO 0x0100
++ #define RAWSTRING 0x1000
+
++ int is_word (char *, int, int);
++ int is_mailbox(char *, int, int);
+
+ /*----------------------------------------------------------------------
+ Format a buffer with the text of the current message for browser
+***************
+*** 242,247 ****
+--- 252,259 ----
+ ps->prev_screen = mail_view_screen;
+ ps->force_prefer_plain = ps->force_no_prefer_plain = 0;
+
++ strcpy(ps->screen_name, "text");
++
+ if(ps->ttyo->screen_rows - HEADER_ROWS(ps) - FOOTER_ROWS(ps) < 1){
+ q_status_message(SM_ORDER | SM_DING, 0, 3,
+ _("Screen too small to view message"));
+***************
+*** 294,299 ****
+--- 306,322 ----
+ else
+ ps->unseen_in_view = !mc->seen;
+
++ prefix = reply_quote_str(env);
++ /* Make sure the prefix is not only made of spaces, so that we do not
++ * paint the screen incorrectly
++ */
++ if (prefix && *prefix){
++ int i;
++ for (i = 0; isspace((unsigned char) prefix[i]); i++);
++ if (i == strlen(prefix))
++ fs_give((void **)&prefix);
++ }
++
+ init_handles(&handles);
+
+ store = so_get(src, NULL, EDIT_ACCESS);
+***************
+*** 478,483 ****
+--- 501,510 ----
+ }
+ while(ps->next_screen == SCREEN_FUN_NULL);
+
++ strcpy(ps->screen_name, "unknown");
++
++ if (prefix && *prefix)
++ fs_give((void **)&prefix);
+ if(we_cancel)
+ cancel_busy_cue(-1);
+
+***************
+*** 732,741 ****
+ {0, 'a', "A", N_("editApp")},
+ {-1, 0, NULL, NULL}};
+
+ if(handle->type == URL){
+ launch_opts[4].ch = 'u';
+
+! if(!(local_h = !struncmp(handle->h.url.path, "x-alpine-", 9))
+ && (handle->h.url.tool
+ || ((local_h = url_local_handler(handle->h.url.path) != NULL)
+ && (handle->h.url.tool = url_external_handler(handle,1)))
+--- 759,771 ----
+ {0, 'a', "A", N_("editApp")},
+ {-1, 0, NULL, NULL}};
+
++ if (role_chosen)
++ free_action(&role_chosen);
+ if(handle->type == URL){
+ launch_opts[4].ch = 'u';
+
+! if((!(local_h = !struncmp(handle->h.url.path, "x-alpine-", 9))
+! || !(local_h = !struncmp(handle->h.url.path, "x-pine-help", 11)))
+ && (handle->h.url.tool
+ || ((local_h = url_local_handler(handle->h.url.path) != NULL)
+ && (handle->h.url.tool = url_external_handler(handle,1)))
+***************
+*** 833,839 ****
+
+ if(force
+ || (handle->type == URL
+! && !struncmp(handle->h.url.path, "x-alpine-", 9)))
+ return(1);
+
+ while(1){
+--- 863,870 ----
+
+ if(force
+ || (handle->type == URL
+! && !struncmp(handle->h.url.path, "x-alpine-", 9)
+! || !struncmp(handle->h.url.path, "x-pine-help", 11)))
+ return(1);
+
+ while(1){
+***************
+*** 844,855 ****
+ * sense if you just say View selected URL ...
+ */
+ if(handle->type == URL &&
+! !struncmp(handle->h.url.path, "mailto:", 7))
+! snprintf(prompt, sizeof(prompt), "Compose mail to \"%.*s%s\" ? ",
+! MIN(MAX(0,sc - 25), sizeof(prompt)-50), handle->h.url.path+7,
+! (strlen(handle->h.url.path+7) > MAX(0,sc-25)) ? "..." : "");
+! else
+! snprintf(prompt, sizeof(prompt), "View selected %s %s%.*s%s ? ",
+ (handle->type == URL) ? "URL" : "Attachment",
+ (handle->type == URL) ? "\"" : "",
+ MIN(MAX(0,sc-27), sizeof(prompt)-50),
+--- 875,916 ----
+ * sense if you just say View selected URL ...
+ */
+ if(handle->type == URL &&
+! !struncmp(handle->h.url.path, "mailto:", 7)){
+! int rolenick = role_chosen ? strlen(role_chosen->nick) : 0;
+! int offset = 25 + (role_chosen ? 20 : 0);
+! int offset2 = max(0, sc - offset) - strlen(handle->h.url.path+7);
+! int offset3 = sc - strlen(handle->h.url.path+7) - rolenick - offset;
+! int laddress = min(max(0,sc - offset), sizeof(prompt)-50);
+! int lrole = rolenick;
+!
+! if (offset3 < 0){
+! lrole = rolenick;
+! laddress = sc - offset - lrole;
+! offset3 = laddress - 20; /* redefine offset3 */
+! if (offset3 < 0){
+! laddress = 20;
+! lrole = sc - offset - laddress;
+! }
+! }
+! launch_opts[2].ch = 'r';
+! launch_opts[2].rval = 'r';
+! launch_opts[2].name = "R";
+! launch_opts[2].label = N_("Set Role");
+! snprintf(prompt, sizeof(prompt), "Compose mail to \"%.*s%s\" %s%.*s%s%s? ",
+! laddress, handle->h.url.path+7,
+! (offset2 < 0 ? "..." : ""),
+! (role_chosen ? "using role \"" : ""),
+! (role_chosen ? lrole : 0),
+! (role_chosen ? role_chosen->nick : ""),
+! (role_chosen ? (rolenick > lrole ? "..." : "") : ""),
+! (role_chosen ? "\" " : ""));
+! }
+! else{
+! launch_opts[2].ch = -2;
+! launch_opts[2].rval = 0;
+! launch_opts[2].name = NULL;
+! launch_opts[2].label = NULL;
+! snprintf(prompt, sizeof(prompt), "View selected %s %s%.*s%s ? ",
+ (handle->type == URL) ? "URL" : "Attachment",
+ (handle->type == URL) ? "\"" : "",
+ MIN(MAX(0,sc-27), sizeof(prompt)-50),
+***************
+*** 857,862 ****
+--- 918,924 ----
+ (handle->type == URL)
+ ? ((strlen(handle->h.url.path) > MAX(0,sc-27))
+ ? "...\"" : "\"") : "");
++ }
+
+ prompt[sizeof(prompt)-1] = '\0';
+
+***************
+*** 865,870 ****
+--- 927,955 ----
+ case 'y' :
+ return(1);
+
++ case 'r':
++ {
++ void (*prev_screen)(struct pine *) = ps_global->prev_screen,
++ (*redraw)(void) = ps_global->redrawer;
++ ps_global->redrawer = NULL;
++ ps_global->next_screen = SCREEN_FUN_NULL;
++ if(role_select_screen(ps_global, &role_chosen, 1) < 0){
++ cmd_cancelled("Compose");
++ ps_global->next_screen = prev_screen;
++ ps_global->redrawer = redraw;
++ if(ps_global->redrawer)
++ (*ps_global->redrawer)();
++ return 0;
++ }
++ ps_global->next_screen = prev_screen;
++ ps_global->redrawer = redraw;
++ if(role_chosen)
++ role_chosen = combine_inherited_role(role_chosen);
++ if(ps_global->redrawer)
++ (*ps_global->redrawer)();
++ break;
++ }
++
+ case 'u' :
+ strncpy(tmp, handle->h.url.path, sizeof(tmp)-1);
+ tmp[sizeof(tmp)-1] = '\0';
+***************
+*** 1697,1702 ****
+--- 1782,1788 ----
+ {"news:", 5, url_local_news},
+ {"x-alpine-gripe:", 15, gripe_gripe_to},
+ {"x-alpine-help:", 14, url_local_helper},
++ {"x-pine-help:", 12, url_local_helper},
+ {"x-alpine-phone-home:", 20, url_local_phone_home},
+ {"x-alpine-config:", 16, url_local_config},
+ {"x-alpine-cert:", 14, url_local_certdetails},
+***************
+*** 1812,1818 ****
+ fs_give((void **) &urlp);
+
+ rflags = ROLE_COMPOSE;
+! if(nonempty_patterns(rflags, &dummy)){
+ role = set_role_from_msg(ps_global, rflags, -1L, NULL);
+ if(confirm_role(rflags, &role))
+ role = combine_inherited_role(role);
+--- 1898,1904 ----
+ fs_give((void **) &urlp);
+
+ rflags = ROLE_COMPOSE;
+! if(!(role = copy_action(role_chosen)) && nonempty_patterns(rflags, &dummy)){
+ role = set_role_from_msg(ps_global, rflags, -1L, NULL);
+ if(confirm_role(rflags, &role))
+ role = combine_inherited_role(role);
+***************
+*** 1888,1893 ****
+--- 1974,1980 ----
+
+ free_redraft_pos(&redraft_pos);
+ free_action(&role);
++ free_action(&role_chosen);
+
+ return(rv);
+ }
+***************
+*** 2603,2608 ****
+--- 2690,2696 ----
+ }
+
+ if(ps_global->noticed_change_in_unseen){
++ ps_global->noticed_change_in_unseen = 0; /* redraw only once */
+ cmd = MC_RESIZE; /* causes cursor to be saved in folder_lister */
+ done = 1;
+ continue;
+***************
+*** 3449,3454 ****
+--- 3537,3588 ----
+ print_to_printer(sparms);
+ break;
+
++ case MC_NEXTHREAD:
++ case MC_PRETHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL,
++ "to move to other thread"))
++ move_thread(ps_global, ps_global->mail_stream, ps_global->msgmap,
++ cmd == MC_NEXTHREAD ? 1 : -1);
++ done = 1;
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_DELTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to delete"))
++ cmd_delete_thread(ps_global, ps_global->mail_stream, ps_global->msgmap);
++ done = 1;
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_UNDTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to undelete"))
++ cmd_undelete_thread(ps_global, ps_global->mail_stream, ps_global->msgmap);
++ done = 1;
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_SELTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to undelete"))
++ cmd_select_thread(ps_global, ps_global->mail_stream, ps_global->msgmap);
++ done = 1;
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
+
+ /* ------- First handle on Line ------ */
+ case MC_GOTOBOL :
+diff -rc alpine-2.00/alpine/Makefile.am alpine-2.00.I.USE/alpine/Makefile.am
+*** alpine-2.00/alpine/Makefile.am 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/alpine/Makefile.am 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 46,48 ****
+--- 46,49 ----
+ date.c:
+ echo "char datestamp[]="\"`date`\"";" > date.c
+ echo "char hoststamp[]="\"`hostname`\"";" >> date.c
++ cat ../patchlevel >> date.c
+diff -rc alpine-2.00/alpine/Makefile.in alpine-2.00.I.USE/alpine/Makefile.in
+*** alpine-2.00/alpine/Makefile.in 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/alpine/Makefile.in 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 724,729 ****
+--- 724,730 ----
+ date.c:
+ echo "char datestamp[]="\"`date`\"";" > date.c
+ echo "char hoststamp[]="\"`hostname`\"";" >> date.c
++ cat ../patchlevel >> date.c
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
+diff -rc alpine-2.00/alpine/osdep/debuging.c alpine-2.00.I.USE/alpine/osdep/debuging.c
+*** alpine-2.00/alpine/osdep/debuging.c 2008-01-04 14:49:15.000000000 -0800
+--- alpine-2.00.I.USE/alpine/osdep/debuging.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 104,109 ****
+--- 104,110 ----
+
+ if(debugfile != NULL){
+ char rev[128];
++ extern char plevstamp[];
+ time_t now = time((time_t *)0);
+ if(ps_global->debug_flush)
+ setvbuf(debugfile, (char *)NULL, _IOLBF, BUFSIZ);
+***************
+*** 126,131 ****
+--- 127,134 ----
+ get_alpine_revision_string(rev, sizeof(rev)),
+ ctime(&now)));
+
++ dprint((0, "This version uses all.patch:\n%s\n\n", plevstamp));
++
+ dprint((0, "Starting after the reading_pinerc calls, the data in this file should\nbe encoded as UTF-8. Before that it will be in the user's native charset.\n"));
+ if(dfile && (debug > DEFAULT_DEBUG ||
+ ps_global->debug_imap > 0 ||
+diff -rc alpine-2.00/alpine/osdep/termin.gen.c alpine-2.00.I.USE/alpine/osdep/termin.gen.c
+*** alpine-2.00/alpine/osdep/termin.gen.c 2008-03-26 10:27:45.000000000 -0700
+--- alpine-2.00.I.USE/alpine/osdep/termin.gen.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 32,37 ****
+--- 32,39 ----
+ #include "../../pith/newmail.h"
+ #include "../../pith/conf.h"
+ #include "../../pith/busy.h"
++ #include "../../pith/list.h"
++ #include "../../pith/rules.h"
+
+ #include "../../pico/estruct.h"
+ #include "../../pico/pico.h"
+***************
+*** 66,77 ****
+ int pcpine_oe_cursor(int, long);
+ #endif
+
+
+ /*
+ * Generic tty input routines
+ */
+
+!
+ /*----------------------------------------------------------------------
+ Read a character from keyboard with timeout
+ Input: none
+--- 68,97 ----
+ int pcpine_oe_cursor(int, long);
+ #endif
+
++ void
++ fake_config_screen(tt)
++ struct ttyo **tt;
++ {
++ struct ttyo *ttyo;
++
++ ttyo = (struct ttyo *)fs_get(sizeof (struct ttyo));
++
++ ttyo->header_rows = 2;
++ ttyo->footer_rows = 3;
++ ttyo->screen_rows = 24;
++ ttyo->screen_cols = 80;
++
++ *tt = ttyo;
++
++ }
++
+
+ /*
+ * Generic tty input routines
+ */
+
+! void process_init_cmds(struct pine *, char **);
+! void queue_init_errors(struct pine *);
+ /*----------------------------------------------------------------------
+ Read a character from keyboard with timeout
+ Input: none
+***************
+*** 113,118 ****
+--- 133,173 ----
+ *utf8str = NULL;
+
+ ucs = read_char(tm);
++ if(!ps_global->initial_cmds){
++ RULE_RESULT *rule;
++ char **list = NULL, *error = NULL;
++ int commas = 0, k; /* From args.c */
++
++ ps_global->pressed_key = cpystr(pretty_command(ucs));
++ rule = (RULE_RESULT *)get_result_rule(V_KEY_RULES, FOR_KEY, NULL);
++ if(ps_global->pressed_key)
++ fs_give((void **)&ps_global->pressed_key);
++ if (rule){
++ for(k = 0; rule->result[k]; k++)
++ if(rule->result[k] == ',') commas++;
++ list = parse_list(rule->result, commas+1, 0, &error);
++ if(error)
++ sprintf(tmp_20k_buf, "Error in parsing command list: %s, %s",
++ rule->result, error);
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ if(error){
++ q_status_message(SM_ORDER | SM_DING, 0, 2, tmp_20k_buf);
++ return (NO_OP_COMMAND);
++ }
++ process_init_cmds(ps_global, list);
++ if(ps_global->init_errs){
++ queue_init_errors(ps_global);
++ return (NO_OP_COMMAND);
++ }
++ ucs = read_char(tm);
++ ps_global->in_init_seq = 1; /* no output please */
++ for(k = 0; k < commas; k++)
++ if(list[k]) fs_give((void **)&list[k]);
++ if (list) fs_give((void **)list);
++ }
++ }
+ if(ucs != NO_OP_COMMAND && ucs != NO_OP_IDLE && ucs != KEY_RESIZE)
+ zero_new_mail_count();
+
+***************
+*** 306,312 ****
+ (escape_list && escape_list[0].ch != -1 && escape_list[0].label)
+ ? escape_list[0].label: ""));
+
+! if(!ps_global->ttyo)
+ return(pre_screen_config_opt_enter(utf8string, utf8string_size, utf8prompt,
+ escape_list, help, flags));
+
+--- 361,367 ----
+ (escape_list && escape_list[0].ch != -1 && escape_list[0].label)
+ ? escape_list[0].label: ""));
+
+! if(!ps_global->ttyo || ps_global->send_immediately)
+ return(pre_screen_config_opt_enter(utf8string, utf8string_size, utf8prompt,
+ escape_list, help, flags));
+
+***************
+*** 1153,1162 ****
+ }
+ }
+ }
+!
+ if(!*ps_global->initial_cmds && ps_global->free_initial_cmds){
+ fs_give((void **) &ps_global->free_initial_cmds);
+ ps_global->initial_cmds = NULL;
+ }
+
+ return(ret);
+--- 1208,1218 ----
+ }
+ }
+ }
+! ps_global->initial_cmds_offset++;
+ if(!*ps_global->initial_cmds && ps_global->free_initial_cmds){
+ fs_give((void **) &ps_global->free_initial_cmds);
+ ps_global->initial_cmds = NULL;
++ firsttime = (char) 1;
+ }
+
+ return(ret);
+diff -rc alpine-2.00/alpine/osdep/termin.gen.h alpine-2.00.I.USE/alpine/osdep/termin.gen.h
+*** alpine-2.00/alpine/osdep/termin.gen.h 2007-12-18 10:29:24.000000000 -0800
+--- alpine-2.00.I.USE/alpine/osdep/termin.gen.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 32,37 ****
+--- 32,38 ----
+ int key_recorder(int);
+ int key_playback(int);
+ int recent_keystroke(int *, char *, size_t);
++ void fake_config_screen(struct ttyo **);
+ int init_tty_driver(struct pine *);
+ void end_tty_driver(struct pine *);
+ int PineRaw(int);
+diff -rc alpine-2.00/alpine/osdep/termin.unx.c alpine-2.00.I.USE/alpine/osdep/termin.unx.c
+*** alpine-2.00/alpine/osdep/termin.unx.c 2008-03-26 10:27:45.000000000 -0700
+--- alpine-2.00.I.USE/alpine/osdep/termin.unx.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 110,115 ****
+--- 110,117 ----
+ int
+ init_tty_driver(struct pine *ps)
+ {
++ if(ps->send_immediately)
++ return 0;
+ #ifdef MOUSE
+ if(F_ON(F_ENABLE_MOUSE, ps_global))
+ init_mouse();
+***************
+*** 676,681 ****
+--- 678,686 ----
+ void
+ init_keyboard(int use_fkeys)
+ {
++ if (ps_global->send_immediately)
++ return;
++
+ if(use_fkeys && (!strucmp(term_name,"vt102")
+ || !strucmp(term_name,"vt100")))
+ printf("\033\133\071\071\150");
+***************
+*** 693,698 ****
+--- 698,706 ----
+ void
+ end_keyboard(int use_fkeys)
+ {
++ if(ps_global->send_immediately)
++ return;
++
+ if(use_fkeys && (!strcmp(term_name, "vt102")
+ || !strcmp(term_name, "vt100"))){
+ printf("\033\133\071\071\154");
+diff -rc alpine-2.00/alpine/osdep/termout.unx.c alpine-2.00.I.USE/alpine/osdep/termout.unx.c
+*** alpine-2.00/alpine/osdep/termout.unx.c 2008-03-04 12:41:47.000000000 -0800
+--- alpine-2.00.I.USE/alpine/osdep/termout.unx.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 205,210 ****
+--- 205,213 ----
+ void
+ init_screen(void)
+ {
++ if(ps_global->send_immediately)
++ return;
++
+ if(_termcap_init) /* init using termcap's rule */
+ tputs(_termcap_init, 1, outchar);
+
+***************
+*** 312,317 ****
+--- 315,323 ----
+ {
+ int footer_rows_was_one = 0;
+
++ if(ps_global->send_immediately)
++ return;
++
+ if(!panicking()){
+
+ dprint((9, "end_screen called\n"));
+***************
+*** 366,372 ****
+ _line = 0; /* clear leaves us at top... */
+ _col = 0;
+
+! if(ps_global->in_init_seq)
+ return;
+
+ mark_status_unknown();
+--- 372,378 ----
+ _line = 0; /* clear leaves us at top... */
+ _col = 0;
+
+! if(ps_global->in_init_seq || ps_global->send_immediately)
+ return;
+
+ mark_status_unknown();
+diff -rc alpine-2.00/alpine/radio.c alpine-2.00.I.USE/alpine/radio.c
+*** alpine-2.00/alpine/radio.c 2007-08-16 15:25:10.000000000 -0700
+--- alpine-2.00.I.USE/alpine/radio.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 121,127 ****
+ int rv, width;
+ size_t len;
+
+! if(!ps_global->ttyo)
+ return(pre_screen_config_want_to(question, dflt, on_ctrl_C));
+ #ifdef _WINDOWS
+ if (mswin_usedialog ()) {
+--- 121,127 ----
+ int rv, width;
+ size_t len;
+
+! if(!ps_global->ttyo || ps_global->send_immediately)
+ return(pre_screen_config_want_to(question, dflt, on_ctrl_C));
+ #ifdef _WINDOWS
+ if (mswin_usedialog ()) {
+diff -rc alpine-2.00/alpine/reply.c alpine-2.00.I.USE/alpine/reply.c
+*** alpine-2.00/alpine/reply.c 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/alpine/reply.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 61,67 ****
+ #include "../pith/tempfile.h"
+ #include "../pith/busy.h"
+ #include "../pith/ablookup.h"
+!
+
+ /*
+ * Internal Prototypes
+--- 61,68 ----
+ #include "../pith/tempfile.h"
+ #include "../pith/busy.h"
+ #include "../pith/ablookup.h"
+! #include "../pith/copyaddr.h"
+! #include "../pith/rules.h"
+
+ /*
+ * Internal Prototypes
+***************
+*** 108,118 ****
+ long msgno, j, totalm, rflags, *seq = NULL;
+ int i, include_text = 0, times = -1, warned = 0, rv = 0,
+ flags = RSF_QUERY_REPLY_ALL, reply_raw_body = 0;
+! int rolemsg = 0, copytomsg = 0;
+ gf_io_t pc;
+ PAT_STATE dummy;
+ REDRAFT_POS_S *redraft_pos = NULL;
+ ACTION_S *role = NULL, *nrole;
+ #if defined(DOS) && !defined(_WINDOWS)
+ char *reserve;
+ #endif
+--- 109,120 ----
+ long msgno, j, totalm, rflags, *seq = NULL;
+ int i, include_text = 0, times = -1, warned = 0, rv = 0,
+ flags = RSF_QUERY_REPLY_ALL, reply_raw_body = 0;
+! int rolemsg = 0, copytomsg = 0, do_role_early = 0;
+ gf_io_t pc;
+ PAT_STATE dummy;
+ REDRAFT_POS_S *redraft_pos = NULL;
+ ACTION_S *role = NULL, *nrole;
++ RULE_RESULT *rule;
+ #if defined(DOS) && !defined(_WINDOWS)
+ char *reserve;
+ #endif
+***************
+*** 138,143 ****
+--- 140,208 ----
+ && F_ON(F_ENABLE_FULL_HDR_AND_TEXT, ps_global))
+ reply_raw_body = 1;
+
++ /* Setup possible role */
++ if(role_arg)
++ role = copy_action(role_arg);
++
++ if(!role && F_ON(F_ENABLE_EDIT_REPLY_INDENT, pine_state)){
++ for(msgno = mn_first_cur(pine_state->msgmap);
++ msgno > 0L; msgno = mn_next_cur(pine_state->msgmap)){
++
++ env = pine_mail_fetchstructure(pine_state->mail_stream,
++ mn_m2raw(pine_state->msgmap, msgno),
++ NULL);
++ if(!env) {
++ q_status_message1(SM_ORDER,3,4,
++ _("Error fetching message %s. Can't reply to it."),
++ long2string(msgno));
++ goto done_early;
++ }
++
++ if(rule = get_result_rule(V_REPLY_INDENT_RULES, FOR_COMPOSE , env)){
++ RULELIST *list = get_rulelist_from_code(V_REPLY_INDENT_RULES,
++ ps_global->rule_list);
++ RULE_S *prule = get_rule(list, rule->number);
++ if(condition_contains_token(prule->condition, ROLE_TOKEN))
++ do_role_early++;
++ if(rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ }
++ }
++
++ if(do_role_early){
++ rflags = ROLE_REPLY;
++ if(!role && nonempty_patterns(rflags, &dummy)){
++ /* setup default role */
++ nrole = NULL;
++ j = mn_first_cur(pine_state->msgmap);
++ do {
++ role = nrole;
++ nrole = set_role_from_msg(pine_state, rflags,
++ mn_m2raw(pine_state->msgmap, j),
++ NULL);
++ } while(nrole && (!role || nrole == role)
++ && (j=mn_next_cur(pine_state->msgmap)) > 0L);
++
++ if(!role || nrole == role)
++ role = nrole;
++ else
++ role = NULL;
++
++ if(confirm_role(rflags, &role))
++ role = combine_inherited_role(role);
++ else{ /* cancel reply */
++ role = NULL;
++ cmd_cancelled("Reply");
++ goto done_early;
++ }
++ }
++ }
++
++ if (role)
++ ps_global->role = cpystr(role->nick); /* remember the role */
++
+ /*
+ * We may have to loop through first to figure out what default
+ * reply-indent-string to offer...
+***************
+*** 229,235 ****
+ if(!times){ /* only first time */
+ char *p = cpystr(prefix);
+
+! if((include_text=reply_text_query(pine_state,totalm,&prefix)) < 0)
+ goto done_early;
+
+ /* edited prefix? */
+--- 294,300 ----
+ if(!times){ /* only first time */
+ char *p = cpystr(prefix);
+
+! if((include_text=reply_text_query(pine_state,totalm,env,&prefix)) < 0)
+ goto done_early;
+
+ /* edited prefix? */
+***************
+*** 285,292 ****
+ outgoing->subject = cpystr("Re: several messages");
+ }
+ }
+! else
+! outgoing->subject = reply_subject(env->subject, NULL, 0);
+ }
+
+ /* fill reply header */
+--- 350,367 ----
+ outgoing->subject = cpystr("Re: several messages");
+ }
+ }
+! else{
+! RULE_RESULT *rule;
+! rule = get_result_rule(V_RESUB_RULES,FOR_RESUB|FOR_TRIM , env);
+! if (rule){
+! outgoing->subject = reply_subject(rule->result, NULL, 0);
+! if (rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! else
+! outgoing->subject = reply_subject(env->subject, NULL, 0);
+! }
+ }
+
+ /* fill reply header */
+***************
+*** 305,315 ****
+ if(sp_expunge_count(pine_state->mail_stream)) /* cur msg expunged */
+ goto done_early;
+
+! /* Setup possible role */
+! if(role_arg)
+! role = copy_action(role_arg);
+
+! if(!role){
+ rflags = ROLE_REPLY;
+ if(nonempty_patterns(rflags, &dummy)){
+ /* setup default role */
+--- 380,392 ----
+ if(sp_expunge_count(pine_state->mail_stream)) /* cur msg expunged */
+ goto done_early;
+
+! if (ps_global->reply.role_chosen){
+! if(role_arg)
+! free_action(&role);
+! role = ps_global->reply.role_chosen;
+! }
+
+! if(!role && !do_role_early){
+ rflags = ROLE_REPLY;
+ if(nonempty_patterns(rflags, &dummy)){
+ /* setup default role */
+***************
+*** 545,553 ****
+ goto done_early;
+ }
+
+! if(orig_body == NULL || orig_body->type == TYPETEXT || reply_raw_body) {
+ reply_delimiter(env, role, pc);
+! if(F_ON(F_INCLUDE_HEADER, pine_state))
+ reply_forward_header(pine_state->mail_stream,
+ mn_m2raw(pine_state->msgmap,msgno),
+ NULL, env, pc, prefix);
+--- 622,631 ----
+ goto done_early;
+ }
+
+! if(orig_body == NULL || orig_body->type == TYPETEXT || reply_raw_body
+! || !ps_global->reply.attach) {
+ reply_delimiter(env, role, pc);
+! if(ps_global->reply.inchdr)
+ reply_forward_header(pine_state->mail_stream,
+ mn_m2raw(pine_state->msgmap,msgno),
+ NULL, env, pc, prefix);
+***************
+*** 566,572 ****
+ && orig_body->nested.part->body.type == TYPETEXT) {
+ /*---- First part of the message is text -----*/
+ reply_delimiter(env, role, pc);
+! if(F_ON(F_INCLUDE_HEADER, pine_state))
+ reply_forward_header(pine_state->mail_stream,
+ mn_m2raw(pine_state->msgmap,
+ msgno),
+--- 644,650 ----
+ && orig_body->nested.part->body.type == TYPETEXT) {
+ /*---- First part of the message is text -----*/
+ reply_delimiter(env, role, pc);
+! if(ps_global->reply.inchdr)
+ reply_forward_header(pine_state->mail_stream,
+ mn_m2raw(pine_state->msgmap,
+ msgno),
+***************
+*** 720,725 ****
+--- 798,806 ----
+ if(prefix)
+ fs_give((void **)&prefix);
+
++ if (ps_global->role)
++ fs_give((void **)&ps_global->role);
++
+ if(fcc)
+ fs_give((void **) &fcc);
+
+***************
+*** 875,881 ****
+
+ prompt[sizeof(prompt)-1] = '\0';
+
+! cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global), ekey,
+ 'y', 'x', help, RB_NORM);
+
+ switch(cmd){
+--- 956,963 ----
+
+ prompt[sizeof(prompt)-1] = '\0';
+
+! cmd = ps_global->send_immediately ? 'n' :
+! radio_buttons(prompt, -FOOTER_ROWS(ps_global), ekey,
+ 'y', 'x', help, RB_NORM);
+
+ switch(cmd){
+***************
+*** 930,937 ****
+ int
+ reply_to_all_query(int *flagp)
+ {
+! switch(want_to("Reply to all recipients",
+! 'n', 'x', NO_HELP, WT_SEQ_SENSITIVE)){
+ case 'x' :
+ return(-1);
+
+--- 1012,1047 ----
+ int
+ reply_to_all_query(int *flagp)
+ {
+! char prompt[80];
+! ESCKEY_S ekey[4];
+! char cmd;
+!
+! ekey[0].name = "Y";
+! ekey[0].ch = 'y';
+! ekey[0].rval = 'y';
+! ekey[0].label = N_("Yes");
+! ekey[1].name = "N";
+! ekey[1].ch = 'n';
+! ekey[1].rval = 'n';
+! ekey[1].label = N_("No");
+! ekey[2].name = "P";
+! ekey[2].ch = 'p';
+! ekey[2].rval = 'p';
+! ekey[3].ch = -1;
+!
+! ps_global->preserve = F_ON(F_PRESERVE_ORIGINAL_FIELD, ps_global);
+!
+!
+! loop:
+! ekey[2].label = ps_global->preserve ? N_("Not Preserve") : N_("Preserve");
+! snprintf(prompt, sizeof(prompt), _("Reply to all recipients%s"),
+! ps_global->preserve ? _(" (preserving fields)? ") : "? ");
+!
+! prompt[sizeof(prompt)-1] = '\0';
+!
+! switch(cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global), ekey,
+! 'n', 'x', h_preserve_field, RB_NORM)){
+!
+ case 'x' :
+ return(-1);
+
+***************
+*** 942,947 ****
+--- 1052,1062 ----
+ case 'n' : /* clear reply-all bit */
+ (*flagp) &= ~RSF_FORCE_REPLY_ALL;
+ break;
++
++ case 'p' :
++ ps_global->preserve = !ps_global->preserve;
++ goto loop; /* ugly, but saves me a variable */
++ break;
+ }
+
+ return(0);
+***************
+*** 969,1016 ****
+ * 0 if we're NOT to include the text
+ * -1 on cancel or error
+ */
+ int
+! reply_text_query(struct pine *ps, long int many, char **prefix)
+ {
+ int ret, edited = 0;
+! static ESCKEY_S rtq_opts[] = {
+! {'y', 'y', "Y", N_("Yes")},
+! {'n', 'n', "N", N_("No")},
+! {-1, 0, NULL, NULL}, /* may be overridden below */
+! {-1, 0, NULL, NULL}
+! };
+
+ if(F_ON(F_AUTO_INCLUDE_IN_REPLY, ps)
+! && F_OFF(F_ENABLE_EDIT_REPLY_INDENT, ps))
+ return(1);
+
+! while(1){
+! if(many > 1L)
+! /* TRANSLATORS: The final three %s's can probably be safely ignored */
+! snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("Include %s original messages in Reply%s%s%s? "),
+! comatose(many),
+! F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? " (using \"" : "",
+! F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? *prefix : "",
+! F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? "\")" : "");
+! else
+! snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("Include original message in Reply%s%s%s? "),
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? " (using \"" : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? *prefix : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? "\")" : "");
+
+! if(F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps)){
+! rtq_opts[2].ch = ctrl('R');
+! rtq_opts[2].rval = 'r';
+! rtq_opts[2].name = "^R";
+! rtq_opts[2].label = N_("Edit Indent String");
+! }
+! else
+! rtq_opts[2].ch = -1;
+
+ switch(ret = radio_buttons(tmp_20k_buf,
+ ps->ttyo->screen_rows > 4
+ ? -FOOTER_ROWS(ps_global) : -1,
+! rtq_opts,
+ (edited || F_ON(F_AUTO_INCLUDE_IN_REPLY, ps))
+ ? 'y' : 'n',
+ 'x', NO_HELP, RB_SEQ_SENSITIVE)){
+--- 1084,1195 ----
+ * 0 if we're NOT to include the text
+ * -1 on cancel or error
+ */
++ #define MAX_REPLY_OPTIONS 8
+ int
+! reply_text_query(struct pine *ps, long int many, ENVELOPE *env, char **prefix)
+ {
+ int ret, edited = 0;
+! static ESCKEY_S compose_style[MAX_REPLY_OPTIONS];
+! int ekey_num;
+! int orig_sf;
+!
+! orig_sf = *prefix && **prefix ? (F_OFF(F_QUELL_FLOWED_TEXT, ps)
+! && F_OFF(F_STRIP_WS_BEFORE_SEND, ps)
+! && (strcmp(*prefix, "> ") == 0
+! || strcmp(*prefix, ">") == 0)) : 0;
+!
+! ps_global->reply.no_send_flowed = !orig_sf;
+! ps_global->reply.role_chosen = NULL;
+! ps_global->reply.strip = ps->full_header == 0
+! && (F_ON(F_ENABLE_STRIP_SIGDASHES, ps)
+! || F_ON(F_ENABLE_SIGDASHES, ps));
+! ps_global->reply.attach = F_ON(F_ATTACHMENTS_IN_REPLY, ps);
+! ps_global->reply.inchdr = F_ON(F_INCLUDE_HEADER, ps);
+
+ if(F_ON(F_AUTO_INCLUDE_IN_REPLY, ps)
+! && F_OFF(F_ENABLE_EDIT_REPLY_INDENT, ps) && F_OFF(F_ALT_REPLY_MENU,ps))
+ return(1);
+
+! while(1){
+! /* TRANSLATORS: The final five %s's can probably be safely ignored */
+! snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("Include %s original messages in Reply%s%s%s%s%s%s%s? "),
+! (many > 1L) ? comatose(many) : "",
+! (many > 1L) ? " " : "",
+! (many > 1L) ? "s" : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? " (using \"" : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? *prefix : "",
++ ps_global->reply.role_chosen ? "\" and role \"" : "",
++ ps_global->reply.role_chosen ? ps_global->reply.role_chosen->nick : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? "\")" : "");
+
+! ekey_num = 0;
+! compose_style[ekey_num].ch = 'y';
+! compose_style[ekey_num].rval = 'y';
+! compose_style[ekey_num].name = "Y";
+! compose_style[ekey_num++].label = N_("Yes");
+!
+! compose_style[ekey_num].ch = 'n';
+! compose_style[ekey_num].rval = 'n';
+! compose_style[ekey_num].name = "N";
+! compose_style[ekey_num++].label = N_("No");
+!
+! if (F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps)){
+! compose_style[ekey_num].ch = ctrl('R');
+! compose_style[ekey_num].rval = 'r';
+! compose_style[ekey_num].name = "^R";
+! compose_style[ekey_num++].label = N_("Edit Indent String");
+! }
+!
+! /***** Alternate Reply Menu ********/
+!
+! if (F_ON(F_ALT_REPLY_MENU, ps)){
+! unsigned which_help;
+!
+! if (F_ON(F_ENABLE_STRIP_SIGDASHES, ps) ||
+! F_ON(F_ENABLE_SIGDASHES, ps)){
+! compose_style[ekey_num].ch = 's';
+! compose_style[ekey_num].rval = 'S';
+! compose_style[ekey_num].name = "S";
+! compose_style[ekey_num++].label = ps_global->reply.strip
+! ? N_("No Strip"): N_("Strip Sig");
+! }
+!
+! compose_style[ekey_num].ch = 'r';
+! compose_style[ekey_num].rval = 'R';
+! compose_style[ekey_num].name = "R";
+! compose_style[ekey_num++].label = N_("Set Role");
+!
+! if(orig_sf){
+! compose_style[ekey_num].ch = 'f';
+! compose_style[ekey_num].rval = 'F';
+! compose_style[ekey_num].name = "F";
+! compose_style[ekey_num++].label = ps_global->reply.no_send_flowed
+! ? N_("Quell Flow") : N_("Send Flowd");
+! }
+!
+! compose_style[ekey_num].ch = 'a';
+! compose_style[ekey_num].rval = 'A';
+! compose_style[ekey_num].name = "A";
+! compose_style[ekey_num++].label = ps_global->reply.attach
+! ? N_("No Attach"): N_("Inc Attac");
+!
+! compose_style[ekey_num].ch = 'h';
+! compose_style[ekey_num].rval = 'H';
+! compose_style[ekey_num].name = "H";
+! compose_style[ekey_num++].label = ps_global->reply.inchdr
+! ? N_("No Header") : N_("Inc Head");
+!
+! }
+! compose_style[ekey_num].ch = -1;
+! compose_style[ekey_num].name = NULL;
+! compose_style[ekey_num].label = NULL;
+!
+! /***** End Alt Reply Menu *********/
+
+ switch(ret = radio_buttons(tmp_20k_buf,
+ ps->ttyo->screen_rows > 4
+ ? -FOOTER_ROWS(ps_global) : -1,
+! compose_style,
+ (edited || F_ON(F_AUTO_INCLUDE_IN_REPLY, ps))
+ ? 'y' : 'n',
+ 'x', NO_HELP, RB_SEQ_SENSITIVE)){
+***************
+*** 1018,1023 ****
+--- 1197,1242 ----
+ cmd_cancelled("Reply");
+ return(-1);
+
++ case 'F':
++ ps_global->reply.no_send_flowed = (ps_global->reply.no_send_flowed + 1) % 2;
++ break;
++
++ case 'S':
++ ps_global->reply.strip = (ps_global->reply.strip + 1) % 2;
++ break;
++
++ case 'A':
++ ps_global->reply.attach = (ps_global->reply.attach + 1) % 2;
++ break;
++
++ case 'H':
++ ps_global->reply.inchdr = (ps_global->reply.inchdr + 1) % 2;
++ break;
++
++
++ case 'R':
++ {
++ void (*prev_screen)(struct pine *) = ps->prev_screen,
++ (*redraw)(void) = ps->redrawer;
++ ps->redrawer = NULL;
++ ps->next_screen = SCREEN_FUN_NULL;
++ if(role_select_screen(ps, &ps_global->reply.role_chosen, 1) < 0){
++ cmd_cancelled("Reply");
++ ps->next_screen = prev_screen;
++ ps->redrawer = redraw;
++ if (ps->redrawer)
++ (*ps->redrawer)();
++ continue;
++ }
++ ps->next_screen = prev_screen;
++ ps->redrawer = redraw;
++ if(ps_global->reply.role_chosen)
++ ps_global->reply.role_chosen = combine_inherited_role(ps_global->reply.role_chosen);
++ }
++ if (ps->redrawer)
++ (*ps->redrawer)();
++ break;
++
+ case 'r':
+ if(prefix && *prefix){
+ int done = 0;
+***************
+*** 1041,1046 ****
+--- 1260,1271 ----
+ if(flags & OE_USER_MODIFIED){
+ fs_give((void **)prefix);
+ *prefix = removing_quotes(cpystr(buf));
++ orig_sf = *prefix && **prefix ?
++ (F_OFF(F_QUELL_FLOWED_TEXT, ps)
++ && F_OFF(F_STRIP_WS_BEFORE_SEND, ps)
++ && (strcmp(*prefix, "> ") == 0
++ || strcmp(*prefix, ">") == 0)) : 0;
++ ps_global->reply.no_send_flowed = !orig_sf;
+ edited = 1;
+ }
+
+***************
+*** 1164,1172 ****
+ }
+ else if(!outgoing->newsgroups)
+ outgoing->newsgroups = cpystr(env->newsgroups);
+- if(!IS_NEWS(ps_global->mail_stream))
+- q_status_message(SM_ORDER, 2, 3,
+- _("Replying to message that MAY or MAY NOT have been posted to newsgroup"));
+ }
+
+ return(ret);
+--- 1389,1394 ----
+***************
+*** 1440,1448 ****
+ }
+ }
+
+! if(role)
+ q_status_message1(SM_ORDER, 3, 4,
+ _("Forwarding using role \"%s\""), role->nick);
+
+ if(role && role->template){
+ char *filtered;
+--- 1662,1675 ----
+ }
+ }
+
+! if (ps_global->role)
+! fs_give((void **)&ps_global->role);
+!
+! if(role){
+ q_status_message1(SM_ORDER, 3, 4,
+ _("Forwarding using role \"%s\""), role->nick);
++ ps_global->role = cpystr(role->nick);
++ }
+
+ if(role && role->template){
+ char *filtered;
+***************
+*** 1674,1679 ****
+--- 1901,1907 ----
+ #if defined(DOS) && !defined(_WINDOWS)
+ free((void *)reserve);
+ #endif
++ outgoing->sparep = env && env->from ? copyaddr(env->from) : NULL;
+ pine_send(outgoing, &body, "FORWARD MESSAGE",
+ role, NULL, &reply, redraft_pos,
+ NULL, NULL, 0);
+***************
+*** 2426,2431 ****
+--- 2654,2661 ----
+ {
+ int rv;
+
++ if(ps_global->send_immediately)
++ return 0;
+ clear_cursor_pos(); /* can't know where cursor is */
+ mark_status_dirty(); /* don't count on cached text */
+ fix_windsize(ps_global);
+***************
+*** 2485,2490 ****
+--- 2715,2721 ----
+ resize_for_pico(void)
+ {
+ fix_windsize(ps_global);
++ ps_global->resize_for_pico = 1;
+ }
+
+
+diff -rc alpine-2.00/alpine/reply.h alpine-2.00.I.USE/alpine/reply.h
+*** alpine-2.00/alpine/reply.h 2006-11-15 20:08:15.000000000 -0800
+--- alpine-2.00.I.USE/alpine/reply.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 28,34 ****
+ int confirm_role(long, ACTION_S **);
+ int reply_to_all_query(int *);
+ int reply_using_replyto_query(void);
+! int reply_text_query(struct pine *, long, char **);
+ int reply_news_test(ENVELOPE *, ENVELOPE *);
+ char *get_signature_file(char *, int, int, int);
+ int forward(struct pine *, ACTION_S *);
+--- 28,34 ----
+ int confirm_role(long, ACTION_S **);
+ int reply_to_all_query(int *);
+ int reply_using_replyto_query(void);
+! int reply_text_query(struct pine *, long, ENVELOPE *, char **);
+ int reply_news_test(ENVELOPE *, ENVELOPE *);
+ char *get_signature_file(char *, int, int, int);
+ int forward(struct pine *, ACTION_S *);
+diff -rc alpine-2.00/alpine/roleconf.c alpine-2.00.I.USE/alpine/roleconf.c
+*** alpine-2.00/alpine/roleconf.c 2008-02-27 17:04:46.000000000 -0800
+--- alpine-2.00.I.USE/alpine/roleconf.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 139,146 ****
+--- 139,151 ----
+
+ if(!(nonempty_patterns(rflags, &pstate) &&
+ first_pattern(&pstate))){
++ if (!ps->send_immediately)
+ q_status_message(SM_ORDER, 0, 3,
+ _("No roles available. Use Setup/Rules to add roles."));
++ else{
++ printf(_("No roles available. Use Setup/Rules to add roles."));
++ exit(-1);
++ }
+ return(ret);
+ }
+
+***************
+*** 4477,4487 ****
+ ctmp->tool = role_sort_tool;
+ ctmp->valoffset = rindent;
+ ctmp->flags |= CF_NOSELECT;
+! ctmp->value = cpystr(set_choose); \
+
+ pval = PVAL(&sort_act_var, ew);
+ if(pval)
+! decode_sort(pval, &def_sort, &def_sort_rev);
+
+ /* allow user to set their default sort order */
+ new_confline(&ctmp)->var = &sort_act_var;
+--- 4482,4492 ----
+ ctmp->tool = role_sort_tool;
+ ctmp->valoffset = rindent;
+ ctmp->flags |= CF_NOSELECT;
+! ctmp->value = cpystr(set_choose);
+
+ pval = PVAL(&sort_act_var, ew);
+ if(pval)
+! decode_sort(pval, &def_sort, &def_sort_rev, 0);
+
+ /* allow user to set their default sort order */
+ new_confline(&ctmp)->var = &sort_act_var;
+***************
+*** 4491,4497 ****
+ ctmp->tool = role_sort_tool;
+ ctmp->valoffset = rindent;
+ ctmp->varmem = -1;
+! ctmp->value = generalized_sort_pretty_value(ps, ctmp, 0);
+
+ for(j = 0; j < 2; j++){
+ for(i = 0; ps->sort_types[i] != EndofList; i++){
+--- 4496,4502 ----
+ ctmp->tool = role_sort_tool;
+ ctmp->valoffset = rindent;
+ ctmp->varmem = -1;
+! ctmp->value = generalized_sort_pretty_value(ps, ctmp, 0, 0);
+
+ for(j = 0; j < 2; j++){
+ for(i = 0; ps->sort_types[i] != EndofList; i++){
+***************
+*** 4503,4509 ****
+ ctmp->valoffset = rindent;
+ ctmp->varmem = i + (j * EndofList);
+ ctmp->value = generalized_sort_pretty_value(ps, ctmp,
+! 0);
+ }
+ }
+
+--- 4508,4514 ----
+ ctmp->valoffset = rindent;
+ ctmp->varmem = i + (j * EndofList);
+ ctmp->value = generalized_sort_pretty_value(ps, ctmp,
+! 0, 0);
+ }
+ }
+
+***************
+*** 5436,5442 ****
+ (*result)->patgrp->stat_boy = PAT_STAT_EITHER;
+
+ if(sort_act){
+! decode_sort(sort_act, &def_sort, &def_sort_rev);
+ (*result)->action->sort_is_set = 1;
+ (*result)->action->sortorder = def_sort;
+ (*result)->action->revsort = (def_sort_rev ? 1 : 0);
+--- 5441,5447 ----
+ (*result)->patgrp->stat_boy = PAT_STAT_EITHER;
+
+ if(sort_act){
+! decode_sort(sort_act, &def_sort, &def_sort_rev, 0);
+ (*result)->action->sort_is_set = 1;
+ (*result)->action->sortorder = def_sort;
+ (*result)->action->revsort = (def_sort_rev ? 1 : 0);
+***************
+*** 7705,7710 ****
+--- 7710,7720 ----
+ if(apval)
+ *apval = (role && role->nick) ? cpystr(role->nick) : NULL;
+
++ if (ps_global->role)
++ fs_give((void **)&ps_global->role);
++ if (role && role->nick)
++ ps_global->role = cpystr(role->nick);
++
+ if((*cl)->value)
+ fs_give((void **)&((*cl)->value));
+
+diff -rc alpine-2.00/alpine/send.c alpine-2.00.I.USE/alpine/send.c
+*** alpine-2.00/alpine/send.c 2008-06-30 15:03:35.000000000 -0700
+--- alpine-2.00.I.USE/alpine/send.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 62,68 ****
+ #include "../pith/mimetype.h"
+ #include "../pith/send.h"
+ #include "../pith/smime.h"
+!
+
+ typedef struct body_particulars {
+ unsigned short type, encoding, had_csp;
+--- 62,68 ----
+ #include "../pith/mimetype.h"
+ #include "../pith/send.h"
+ #include "../pith/smime.h"
+! #include "../pith/rules.h"
+
+ typedef struct body_particulars {
+ unsigned short type, encoding, had_csp;
+***************
+*** 98,103 ****
+--- 98,104 ----
+ void free_body_particulars(BODY_PARTICULARS_S *);
+ long message_format_for_pico(long, int (*)(int));
+ int send_exit_for_pico(struct headerentry *, void (*)(void), int, char **);
++ void new_thread_on_blank_subject(void);
+ char *choose_a_priority(char *);
+ int dont_flow_this_time(void);
+ int mime_type_for_pico(char *);
+***************
+*** 237,242 ****
+--- 238,248 ----
+ role->nick = cpystr("Default Role");
+ }
+
++ if (ps_global->role)
++ fs_give((void **)&ps_global->role);
++
++ ps_global->role = cpystr(role->nick);
++
+ pine_state->redrawer = NULL;
+ compose_mail(NULL, NULL, role, NULL, NULL);
+ free_action(&role);
+***************
+*** 446,453 ****
+
+ ps_global->next_screen = prev_screen;
+ ps_global->redrawer = redraw;
+! if(role)
+ role = combine_inherited_role(role);
+ }
+ break;
+
+--- 452,463 ----
+
+ ps_global->next_screen = prev_screen;
+ ps_global->redrawer = redraw;
+! if (ps_global->role)
+! fs_give((void **)&ps_global->role);
+! if(role){
+ role = combine_inherited_role(role);
++ ps_global->role = cpystr(role->nick);
++ }
+ }
+ break;
+
+***************
+*** 612,617 ****
+--- 622,628 ----
+ if(given_to)
+ rfc822_parse_adrlist(&outgoing->to, given_to, ps_global->maildomain);
+
++ outgoing->subject = cpystr(ps_global->subject);
+ outgoing->message_id = generate_message_id();
+
+ /*
+***************
+*** 642,650 ****
+ }
+ }
+
+! if(role)
+ q_status_message1(SM_ORDER, 3, 4, _("Composing using role \"%s\""),
+ role->nick);
+
+ /*
+ * The type of storage object allocated below is vitally
+--- 653,666 ----
+ }
+ }
+
+! if (ps_global->role)
+! fs_give((void **)&ps_global->role);
+!
+! if(role){
+ q_status_message1(SM_ORDER, 3, 4, _("Composing using role \"%s\""),
+ role->nick);
++ ps_global->role = cpystr(role->nick);
++ }
+
+ /*
+ * The type of storage object allocated below is vitally
+***************
+*** 910,916 ****
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KS_NONE},
+ {"From : ", "From", h_composer_from, 10, 0, NULL,
+ build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL, abook_nickname_complete,
+! 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, KS_TOADDRBOOK},
+ {"Reply-To: ", "Reply To", h_composer_reply_to, 10, 0, NULL,
+ build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL, abook_nickname_complete,
+ 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, KS_TOADDRBOOK},
+--- 926,932 ----
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KS_NONE},
+ {"From : ", "From", h_composer_from, 10, 0, NULL,
+ build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL, abook_nickname_complete,
+! 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, KS_TOADDRBOOK},
+ {"Reply-To: ", "Reply To", h_composer_reply_to, 10, 0, NULL,
+ build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL, abook_nickname_complete,
+ 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, KS_TOADDRBOOK},
+***************
+*** 1780,1785 ****
+--- 1796,1804 ----
+ pbf = &pbuf1;
+ standard_picobuf_setup(pbf);
+
++ pbf->auto_cmds = ps_global->initial_cmds_backup +
++ ps_global->initial_cmds_offset;
++
+ /*
+ * Cancel any pending initial commands since pico uses a different
+ * input routine. If we didn't cancel them, they would happen after
+***************
+*** 1816,1821 ****
+--- 1835,1842 ----
+ pbf->mimetype = mime_type_for_pico;
+ pbf->exittest = send_exit_for_pico;
+ pbf->user_says_noflow = dont_flow_this_time;
++ pbf->newthread = new_thread_on_blank_subject;
++ ps_global->newthread = 0; /* reset this value */
+ if(F_OFF(F_CANCEL_CONFIRM, ps_global))
+ pbf->canceltest = cancel_for_pico;
+
+***************
+*** 2301,2306 ****
+--- 2322,2332 ----
+ he->rich_header = 0;
+ }
+ }
++ if (F_ON(F_ALLOW_CHANGING_FROM, ps_global) &&
++ !ps_global->never_allow_changing_from){
++ he->display_it = 1; /* show it */
++ he->rich_header = 0;
++ }
+
+ he_from = he;
+ break;
+***************
+*** 2410,2415 ****
+--- 2436,2461 ----
+ removing_trailing_white_space(pf->textbuf);
+ (void)removing_double_quotes(pf->textbuf);
+ build_address(pf->textbuf, &addr, NULL, NULL, NULL);
++ if (!strncmp(pf->name,"Lcc",3) && addr && *addr){
++ RULE_RESULT *rule;
++
++ outgoing->date = (unsigned char *) cpystr(addr);
++ ps_global->procid = cpystr("fwd-lcc");
++ rule = get_result_rule(V_FORWARD_RULES,
++ FOR_COMPOSE|FOR_TRIM, outgoing);
++ if (rule){
++ addr = cpystr(rule->result);
++ removing_trailing_white_space(addr);
++ (void)removing_extra_stuff(addr);
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ fs_give((void **)&ps_global->procid);
++ if (outgoing->date)
++ fs_give((void **)&outgoing->date);
++ }
++
+ rfc822_parse_adrlist(pf->addr, addr,
+ ps_global->maildomain);
+ fs_give((void **)&addr);
+***************
+*** 2979,2985 ****
+ #ifdef _WINDOWS
+ mswin_setwindowmenu (MENU_DEFAULT);
+ #endif
+! fix_windsize(ps_global);
+
+ /*
+ * Only reinitialize signals if we didn't receive an interesting
+--- 3025,3036 ----
+ #ifdef _WINDOWS
+ mswin_setwindowmenu (MENU_DEFAULT);
+ #endif
+! if (ps_global->send_immediately){
+! if(ps_global->free_initial_cmds_backup)
+! fs_give((void **)&ps_global->free_initial_cmds_backup);
+! }
+! else
+! fix_windsize(ps_global);
+
+ /*
+ * Only reinitialize signals if we didn't receive an interesting
+***************
+*** 3038,3044 ****
+ if(outgoing->return_path)
+ mail_free_address(&outgoing->return_path);
+
+! outgoing->return_path = rfc822_cpy_adr(outgoing->from);
+
+ /*
+ * Don't ever believe the sender that is there.
+--- 3089,3097 ----
+ if(outgoing->return_path)
+ mail_free_address(&outgoing->return_path);
+
+! outgoing->return_path = F_ON(F_USE_DOMAIN_NAME,ps_global)
+! ? rfc822_cpy_adr(generate_from())
+! : rfc822_cpy_adr(outgoing->from);
+
+ /*
+ * Don't ever believe the sender that is there.
+***************
+*** 3068,3073 ****
+--- 3121,3131 ----
+ outgoing->sender->host = cpystr(ps_global->hostname);
+ }
+
++ if(ps_global->newthread){
++ if(outgoing->in_reply_to) fs_give((void **)&outgoing->in_reply_to);
++ if(outgoing->references) fs_give((void **)&outgoing->references);
++ }
++
+ /*----- Message is edited, now decide what to do with it ----*/
+ if(editor_result & (COMP_SUSPEND | COMP_GOTHUP | COMP_CANCEL)){
+ /*=========== Postpone or Interrupted message ============*/
+***************
+*** 3710,3719 ****
+ if(sending_filter_requested
+ && !filter_message_text(sending_filter_requested, outgoing,
+ *body, &orig_so, &header)){
+! q_status_message1(SM_ORDER, 3, 3,
+ _("Problem filtering! Nothing sent%s."),
+ fcc ? " or saved to fcc" : "");
+! continue;
+ }
+
+ /*------ Actually post -------*/
+--- 3768,3783 ----
+ if(sending_filter_requested
+ && !filter_message_text(sending_filter_requested, outgoing,
+ *body, &orig_so, &header)){
+! if (!ps_global->send_immediately){
+! q_status_message1(SM_ORDER, 3, 3,
+ _("Problem filtering! Nothing sent%s."),
+ fcc ? " or saved to fcc" : "");
+! continue;
+! }
+! else{
+! fprintf(stderr, _("Problem filtering! Nothing sent or saved to Fcc\n"));
+! exit(-1);
+! }
+ }
+
+ /*------ Actually post -------*/
+***************
+*** 3957,3962 ****
+--- 4021,4028 ----
+ /*----- Mail Post FAILED, back to composer -----*/
+ if(result & (P_MAIL_LOSE | P_FCC_LOSE)){
+ dprint((1, "Send failed, continuing\n"));
++ if (ps_global->send_immediately)
++ exit(1);
+
+ if(result & P_FCC_LOSE){
+ /*
+***************
+*** 3991,3996 ****
+--- 4057,4063 ----
+ update_answered_flags(reply);
+
+ /*----- Signed, sealed, delivered! ------*/
++ if (!ps_global->send_immediately)
+ q_status_message(SM_ORDER, 0, 3,
+ pine_send_status(result, fcc, tmp_20k_buf, SIZEOF_20KBUF, NULL));
+
+***************
+*** 4360,4365 ****
+--- 4427,4442 ----
+ return(buf);
+ }
+
++ /* Callback from Pico to set the conditions for Alpine to start a new thread
++ */
++
++ void
++ new_thread_on_blank_subject(void)
++ {
++ ps_global->newthread = F_ON(F_NEW_THREAD_ON_BLANK_SUBJECT, ps_global);
++ }
++
++
+
+ /*----------------------------------------------------------------------
+ Call back for pico to insert the specified message's text
+***************
+*** 4447,4453 ****
+ return(1);
+ }
+
+! if(F_ON(F_SEND_WO_CONFIRM, ps_global)){
+ if(result)
+ *result = NULL;
+
+--- 4524,4530 ----
+ return(1);
+ }
+
+! if(!ps_global->send_immediately && F_ON(F_SEND_WO_CONFIRM, ps_global)){
+ if(result)
+ *result = NULL;
+
+***************
+*** 4627,4633 ****
+
+ opts[i].ch = -1;
+
+! fix_windsize(ps_global);
+
+ while(1){
+ if(filters && filters->filter && (p = strindex(filters->filter, ' ')))
+--- 4704,4711 ----
+
+ opts[i].ch = -1;
+
+! if (!ps_global->send_immediately)
+! fix_windsize(ps_global);
+
+ while(1){
+ if(filters && filters->filter && (p = strindex(filters->filter, ' ')))
+***************
+*** 4809,4815 ****
+ if(double_rad +
+ ((call_mailer_flags & CM_DSN_SHOW)
+ ? 4 : F_ON(F_DSN, ps_global) ? 1 : 0) > 11)
+! rv = double_radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
+ 'y', 'z',
+ (F_ON(F_DSN, ps_global) && allow_flowed)
+ ? h_send_prompt_dsn_flowed :
+--- 4887,4894 ----
+ if(double_rad +
+ ((call_mailer_flags & CM_DSN_SHOW)
+ ? 4 : F_ON(F_DSN, ps_global) ? 1 : 0) > 11)
+! rv = ps_global->send_immediately ? 'y' :
+! double_radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
+ 'y', 'z',
+ (F_ON(F_DSN, ps_global) && allow_flowed)
+ ? h_send_prompt_dsn_flowed :
+***************
+*** 4818,4824 ****
+ h_send_prompt,
+ RB_NORM);
+ else
+! rv = radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
+ 'y', 'z',
+ (double_rad +
+ ((call_mailer_flags & CM_DSN_SHOW)
+--- 4897,4904 ----
+ h_send_prompt,
+ RB_NORM);
+ else
+! rv = ps_global->send_immediately ? 'y' :
+! radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
+ 'y', 'z',
+ (double_rad +
+ ((call_mailer_flags & CM_DSN_SHOW)
+***************
+*** 5155,5165 ****
+--- 5235,5247 ----
+ {'c', 'c', "C", N_("Confirm")},
+ {'n', 'n', "N", N_("No")},
+ {'y', 'y', "", ""},
++ {'t', 't', "T", N_("CounT")},
+ {-1, 0, NULL, NULL}
+ };
+
+ ps_global->redrawer = redraw_pico;
+ fix_windsize(ps_global);
++ pbf->curpos[0] = '\0';
+
+ while(1){
+ rv = radio_buttons(prompt, -FOOTER_ROWS(ps_global), opts,
+***************
+*** 5172,5183 ****
+ q_status_message(SM_INFO, 1, 3, _(" Type \"C\" to cancel message "));
+ display_message('x');
+ }
+ else
+ break;
+ }
+
+ ps_global->redrawer = redraw;
+! return(rstr);
+ }
+
+
+--- 5254,5269 ----
+ q_status_message(SM_INFO, 1, 3, _(" Type \"C\" to cancel message "));
+ display_message('x');
+ }
++ else if(rv == 't'){
++ showcpos(1,0);
++ break;
++ }
+ else
+ break;
+ }
+
+ ps_global->redrawer = redraw;
+! return(pbf->curpos[0] ? pbf->curpos : rstr);
+ }
+
+
+***************
+*** 5204,5210 ****
+
+ if(fcmd
+ && (cmd=expand_filter_tokens(fcmd, outgoing, &tmpf, &resultf, &mtf,
+! &key, &include_hdrs))){
+ if(tmpf){
+ /*
+ * We need WRITE_TO_LOCALE here because the user is going to
+--- 5290,5296 ----
+
+ if(fcmd
+ && (cmd=expand_filter_tokens(fcmd, outgoing, &tmpf, &resultf, &mtf,
+! &key, &include_hdrs, NULL))){
+ if(tmpf){
+ /*
+ * We need WRITE_TO_LOCALE here because the user is going to
+***************
+*** 5281,5289 ****
+ if((tmp_so = so_get(PicoText, NULL, EDIT_ACCESS)) != NULL){
+ gf_set_so_writec(&pc, tmp_so);
+ ps_global->mangled_screen = 1;
+! suspend_busy_cue();
+! ClearScreen();
+! fflush(stdout);
+ if(tmpf){
+ PIPE_S *fpipe;
+
+--- 5367,5377 ----
+ if((tmp_so = so_get(PicoText, NULL, EDIT_ACCESS)) != NULL){
+ gf_set_so_writec(&pc, tmp_so);
+ ps_global->mangled_screen = 1;
+! if (!ps_global->send_immediately){
+! suspend_busy_cue();
+! ClearScreen();
+! fflush(stdout);
+! }
+ if(tmpf){
+ PIPE_S *fpipe;
+
+***************
+*** 5311,5317 ****
+ }
+ else
+ errstr = gf_filter(cmd, key ? filter_session_key() : NULL,
+! readthis_so, pc, NULL, 0,
+ pipe_callback);
+
+ if(our_tmpf_so)
+--- 5399,5405 ----
+ }
+ else
+ errstr = gf_filter(cmd, key ? filter_session_key() : NULL,
+! readthis_so, pc, NULL, 0, 0,
+ pipe_callback);
+
+ if(our_tmpf_so)
+***************
+*** 5395,5402 ****
+ set_mime_type_by_grope(b);
+ }
+
+! ClearScreen();
+! resume_busy_cue(0);
+ }
+ else
+ errstr = "Can't create space for filtered text.";
+--- 5483,5492 ----
+ set_mime_type_by_grope(b);
+ }
+
+! if (!ps_global->send_immediately){
+! ClearScreen();
+! resume_busy_cue(0);
+! }
+ }
+ else
+ errstr = "Can't create space for filtered text.";
+***************
+*** 5427,5436 ****
+ if(tmp_so)
+ so_give(&tmp_so);
+
+! q_status_message1(SM_ORDER | SM_DING, 3, 6, _("Problem filtering: %s"),
+ errstr);
+! dprint((1, "Filter FAILED: %s\n",
+ errstr ? errstr : "?"));
+ }
+
+ return(errstr == NULL);
+--- 5517,5532 ----
+ if(tmp_so)
+ so_give(&tmp_so);
+
+! if (!ps_global->send_immediately){
+! q_status_message1(SM_ORDER | SM_DING, 3, 6, _("Problem filtering: %s"),
+ errstr);
+! dprint((1, "Filter FAILED: %s\n",
+ errstr ? errstr : "?"));
++ }
++ else{
++ fprintf(stderr, _("Filter FAILED: %s\n"), errstr ? errstr : "?");
++ exit(-1);
++ }
+ }
+
+ return(errstr == NULL);
+diff -rc alpine-2.00/alpine/setup.c alpine-2.00.I.USE/alpine/setup.c
+*** alpine-2.00/alpine/setup.c 2008-01-23 11:15:36.000000000 -0800
+--- alpine-2.00.I.USE/alpine/setup.c 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 257,263 ****
+ ctmpa->flags |= CF_NOSELECT;
+ ctmpa->value = cpystr("--- ----------------------");
+
+! decode_sort(pval, &def_sort, &def_sort_rev);
+
+ for(j = 0; j < 2; j++){
+ for(i = 0; ps->sort_types[i] != EndofList; i++){
+--- 257,263 ----
+ ctmpa->flags |= CF_NOSELECT;
+ ctmpa->value = cpystr("--- ----------------------");
+
+! decode_sort(pval, &def_sort, &def_sort_rev, 0);
+
+ for(j = 0; j < 2; j++){
+ for(i = 0; ps->sort_types[i] != EndofList; i++){
+***************
+*** 272,277 ****
+--- 272,326 ----
+ }
+ }
+ }
++ else if(vtmp == &ps->vars[V_THREAD_SORT_KEY]){ /* radio case */
++ SortOrder thread_def_sort;
++ int thread_def_sort_rev, lv;
++
++ ctmpa->flags |= CF_NOSELECT;
++ ctmpa->keymenu = &config_radiobutton_keymenu;
++ ctmpa->tool = NULL;
++
++ /* put a nice delimiter before list */
++ new_confline(&ctmpa)->var = NULL;
++ ctmpa->varnamep = ctmpb;
++ ctmpa->keymenu = &config_radiobutton_keymenu;
++ ctmpa->help = NO_HELP;
++ ctmpa->tool = radiobutton_tool;
++ ctmpa->valoffset = 12;
++ ctmpa->flags |= CF_NOSELECT;
++ ctmpa->value = cpystr("Set Thread Sort Options");
++
++ new_confline(&ctmpa)->var = NULL;
++ ctmpa->varnamep = ctmpb;
++ ctmpa->keymenu = &config_radiobutton_keymenu;
++ ctmpa->help = NO_HELP;
++ ctmpa->tool = radiobutton_tool;
++ ctmpa->valoffset = 12;
++ ctmpa->flags |= CF_NOSELECT;
++ ctmpa->value = cpystr("--- ----------------------");
++
++ /* find longest value's name */
++ for(lv = 0, i = 0; ps->sort_types[i] != EndofList; i++)
++ if(lv < (j = strlen(sort_name(ps->sort_types[i]))))
++ lv = j;
++
++ decode_sort(pval, &thread_def_sort, &thread_def_sort_rev, 1);
++
++ for(j = 0; j < 2; j++){
++ for(i = 0; ps->sort_types[i] != EndofList; i++){
++ if (allowed_thread_key(ps->sort_types[i])){
++ new_confline(&ctmpa)->var = vtmp;
++ ctmpa->varnamep = ctmpb;
++ ctmpa->keymenu = &config_radiobutton_keymenu;
++ ctmpa->help = config_help(vtmp - ps->vars, 0);
++ ctmpa->tool = radiobutton_tool;
++ ctmpa->valoffset = 12;
++ ctmpa->varmem = i + (j * EndofList);
++ ctmpa->value = pretty_value(ps, ctmpa);
++ }
++ }
++ }
++ }
+ else if(vtmp == &ps->vars[V_USE_ONLY_DOMAIN_NAME]){ /* yesno case */
+ ctmpa->keymenu = &config_yesno_keymenu;
+ ctmpa->tool = yesno_tool;
+***************
+*** 463,468 ****
+--- 512,526 ----
+ }
+ }
+
++ pval = PVAL(&ps->vars[V_THREAD_SORT_KEY], ew);
++ if(vsave[V_THREAD_SORT_KEY].saved_user_val.p && pval
++ && strcmp(vsave[V_THREAD_SORT_KEY].saved_user_val.p, pval)){
++ if(!mn_get_mansort(ps_global->msgmap)){
++ clear_index_cache(ps_global->mail_stream, 0);
++ reset_sort_order(SRT_VRB);
++ }
++ }
++
+ treat_color_vars_as_text = 0;
+ free_saved_config(ps, &vsave, expose_hidden_config);
+ #ifdef _WINDOWS
+diff -rc alpine-2.00/alpine/signal.c alpine-2.00.I.USE/alpine/signal.c
+*** alpine-2.00/alpine/signal.c 2008-04-07 15:58:40.000000000 -0700
+--- alpine-2.00.I.USE/alpine/signal.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 819,826 ****
+ #else
+ if(F_ON(F_SUSPEND_SPAWNS, ps_global)){
+ PIPE_S *syspipe;
+
+! if((syspipe = open_system_pipe(NULL, NULL, NULL, PIPE_USER|PIPE_RESET,
+ 0, pipe_callback, pipe_report_error)) != NULL){
+ suspend_notice("exit");
+ #ifndef SIGCHLD
+--- 819,828 ----
+ #else
+ if(F_ON(F_SUSPEND_SPAWNS, ps_global)){
+ PIPE_S *syspipe;
++ int flag = some_stream_is_locked() ? PIPE_NONEWMAIL : 0;
+
+! flag |= PIPE_USER|PIPE_RESET;
+! if((syspipe = open_system_pipe(NULL, NULL, NULL, flag,
+ 0, pipe_callback, pipe_report_error)) != NULL){
+ suspend_notice("exit");
+ #ifndef SIGCHLD
+***************
+*** 867,873 ****
+ _("Error loading \"%s\""), shell);
+ #endif
+
+! if(isremote && !pine_mail_ping(ps_global->mail_stream))
+ q_status_message(SM_ORDER | SM_DING, 4, 9,
+ _("Suspended for too long, IMAP connection broken"));
+
+--- 869,876 ----
+ _("Error loading \"%s\""), shell);
+ #endif
+
+! if(isremote && !ps_global->mail_stream->lock
+! && !pine_mail_ping(ps_global->mail_stream))
+ q_status_message(SM_ORDER | SM_DING, 4, 9,
+ _("Suspended for too long, IMAP connection broken"));
+
+diff -rc alpine-2.00/alpine/status.c alpine-2.00.I.USE/alpine/status.c
+*** alpine-2.00/alpine/status.c 2007-11-28 09:57:15.000000000 -0800
+--- alpine-2.00.I.USE/alpine/status.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 110,115 ****
+--- 110,118 ----
+ char *clean_msg;
+ size_t mlen;
+
++ if (ps_global->send_immediately)
++ return;
++
+ status_message_lock();
+
+ /*
+***************
+*** 604,609 ****
+--- 607,615 ----
+ SMQ_T *q, *copy_of_q;
+ int ding;
+
++ if(ps_global->send_immediately)
++ return;
++
+ start_over:
+ status_message_lock();
+
+diff -rc alpine-2.00/doc/alpine.1 alpine-2.00.I.USE/doc/alpine.1
+*** alpine-2.00/doc/alpine.1 2008-08-22 13:40:16.000000000 -0700
+--- alpine-2.00.I.USE/doc/alpine.1 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 164,169 ****
+--- 164,171 ----
+ .IP \fB-n\ \fInumber\fR 20
+ Start up with current message-number set to
+ .I number.
++ .IP \fB-noutf8\fR 20
++ Warns Alpine that piped input is not encoded in UTF-8.
+ .IP \fB-o\fR 20
+ Open first folder read-only.
+ .IP \fB-p\ \fIconfig-file\fR 20
+diff -rc alpine-2.00/imap/src/c-client/imap4r1.c alpine-2.00.I.USE/imap/src/c-client/imap4r1.c
+*** alpine-2.00/imap/src/c-client/imap4r1.c 2008-06-04 11:39:54.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/c-client/imap4r1.c 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 1121,1126 ****
+--- 1121,1127 ----
+ sprintf (tmp,"Retrying using %s authentication after %.80s",
+ at->name,lsterr);
+ mm_log (tmp,NIL);
++ delete_password(mb, usr);
+ fs_give ((void **) &lsterr);
+ }
+ trial = 0; /* initial trial count */
+***************
+*** 1129,1134 ****
+--- 1130,1136 ----
+ if (lsterr) { /* previous attempt with this one failed? */
+ sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr);
+ mm_log (tmp,WARN);
++ delete_password(mb, usr);
+ fs_give ((void **) &lsterr);
+ }
+ LOCAL->saslcancel = NIL;
+***************
+*** 1166,1171 ****
+--- 1168,1174 ----
+ sprintf (tmp,"Can not authenticate to IMAP server: %.80s",lsterr);
+ mm_log (tmp,ERROR);
+ }
++ delete_password(mb, usr);
+ fs_give ((void **) &lsterr);
+ }
+ return NIL; /* ran out of authenticators */
+***************
+*** 1207,1212 ****
+--- 1210,1216 ----
+ if (imap_OK (stream,reply = imap_send (stream,"LOGIN",args)))
+ ret = LONGT; /* success */
+ else {
++ delete_password(mb, usr);
+ mm_log (reply->text,WARN);
+ if (!LOCAL->referral && (trial == imap_maxlogintrials))
+ mm_log ("Too many login failures",ERROR);
+***************
+*** 4527,4532 ****
+--- 4531,4537 ----
+ if (*env) { /* need to merge this header into envelope? */
+ if (!(*env)->newsgroups) { /* need Newsgroups? */
+ (*env)->newsgroups = nenv->newsgroups;
++ (*env)->ngpathexists = nenv->ngpathexists;
+ nenv->newsgroups = NIL;
+ }
+ if (!(*env)->followup_to) { /* need Followup-To? */
+***************
+*** 4581,4586 ****
+--- 4586,4592 ----
+ if (oenv) { /* need to merge old envelope? */
+ (*env)->newsgroups = oenv->newsgroups;
+ oenv->newsgroups = NIL;
++ (*env)->ngpathexists = oenv->ngpathexists;
+ (*env)->followup_to = oenv->followup_to;
+ oenv->followup_to = NIL;
+ (*env)->references = oenv->references;
+diff -rc alpine-2.00/imap/src/c-client/mail.c alpine-2.00.I.USE/imap/src/c-client/mail.c
+*** alpine-2.00/imap/src/c-client/mail.c 2008-06-04 11:39:54.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/c-client/mail.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 34,39 ****
+--- 34,41 ----
+
+ /* c-client global data */
+
++ static char *pwdfile = NIL; /*password file */
++ static int xlate_key; /* for password file support */
+ /* version of this library */
+ static char *mailcclientversion = CCLIENTVERSION;
+ /* list of mail drivers */
+***************
+*** 52,57 ****
+--- 54,61 ----
+ static rfc822out_t mail822out = NIL;
+ /* RFC-822 output generator (new style) */
+ static rfc822outfull_t mail822outfull = NIL;
++ /* Erase password (client side) */
++ static deletepwd_t erase_password = NIL;
+ /* SMTP verbose callback */
+ static smtpverbose_t mailsmtpverbose = mm_dlog;
+ /* proxy copy routine */
+***************
+*** 544,549 ****
+--- 548,558 ----
+ case GET_SENDCOMMAND:
+ ret = (void *) mailsendcommand;
+ break;
++ case SET_ERASEPASSWORD:
++ erase_password = (deletepwd_t) value;
++ case GET_ERASEPASSWORD:
++ ret = (void *) erase_password;
++ break;
+
+ case SET_SERVICENAME:
+ servicename = (char *) value;
+***************
+*** 640,645 ****
+--- 649,661 ----
+ case GET_SNARFMAILBOXNAME:
+ if (stream) ret = (void *) stream->snarf.name;
+ break;
++ case SET_PASSWORDFILE:
++ if (pwdfile) fs_give ((void **) &pwdfile);
++ pwdfile = cpystr ((char *) value);
++ break;
++ case GET_PASSWORDFILE:
++ ret = (void *) pwdfile;
++ break;
+ default:
+ if (r = smtp_parameters (function,value)) ret = r;
+ if (r = env_parameters (function,value)) ret = r;
+***************
+*** 991,997 ****
+ MAILSTREAM *ts;
+ char *s,*t,tmp[MAILTMPLEN];
+ size_t i;
+! DRIVER *d;
+ /* never allow names with newlines */
+ if (s = strpbrk (mailbox,"\015\012")) {
+ MM_LOG ("Can't create mailbox with such a name",ERROR);
+--- 1007,1013 ----
+ MAILSTREAM *ts;
+ char *s,*t,tmp[MAILTMPLEN];
+ size_t i;
+! DRIVER *d, *md;
+ /* never allow names with newlines */
+ if (s = strpbrk (mailbox,"\015\012")) {
+ MM_LOG ("Can't create mailbox with such a name",ERROR);
+***************
+*** 1015,1020 ****
+--- 1031,1038 ----
+ return NIL;
+ }
+
++ /* Hack, we should do this better, but it works */
++ for (md = maildrivers; md && strcmp (md->name, "md"); md = md->next);
+ /* see if special driver hack */
+ if ((mailbox[0] == '#') && ((mailbox[1] == 'd') || (mailbox[1] == 'D')) &&
+ ((mailbox[2] == 'r') || (mailbox[2] == 'R')) &&
+***************
+*** 1045,1050 ****
+--- 1063,1075 ----
+ (((*mailbox == '{') || (*mailbox == '#')) &&
+ (stream = mail_open (NIL,mailbox,OP_PROTOTYPE | OP_SILENT))))
+ d = stream->dtb;
++ else if(mailbox[0] == '#'
++ && (mailbox[1] == 'm' || mailbox[1] == 'M')
++ && (mailbox[2] == 'd' || mailbox[2] == 'D'
++ || mailbox[2] == 'c' || mailbox[2] == 'C')
++ && mailbox[3] == '/'
++ && mailbox[4] != '\0')
++ return (*md->create)(stream, mailbox);
+ else if ((*mailbox != '{') && (ts = default_proto (NIL))) d = ts->dtb;
+ else { /* failed utterly */
+ sprintf (tmp,"Can't create mailbox %.80s: indeterminate format",mailbox);
+***************
+*** 3352,3364 ****
+ long flags)
+ {
+ STRINGLIST *hdrs;
+! int notfound;
+ unsigned long i;
+ char c,*s,*e,*t,tmp[MAILTMPLEN];
+ char *src = text;
+ char *dst = src;
+ char *end = text + len;
+! text[len] = '\012'; /* guard against running off buffer */
+ while (src < end) { /* process header */
+ /* slurp header line name */
+ for (s = src,e = s + MAILTMPLEN - 1,e = (e < end ? e : end),t = tmp;
+--- 3377,3389 ----
+ long flags)
+ {
+ STRINGLIST *hdrs;
+! int notfound, fix = text[len - 1] == '\0';
+ unsigned long i;
+ char c,*s,*e,*t,tmp[MAILTMPLEN];
+ char *src = text;
+ char *dst = src;
+ char *end = text + len;
+! text[fix ? len - 1 : len] = '\012'; /* guard against running off buffer */
+ while (src < end) { /* process header */
+ /* slurp header line name */
+ for (s = src,e = s + MAILTMPLEN - 1,e = (e < end ? e : end),t = tmp;
+***************
+*** 3397,3402 ****
+--- 3422,3431 ----
+ }
+ }
+ *dst = '\0'; /* tie off destination */
++ if(fix){
++ text[len] = '\012';
++ text[len-1] = '\0';
++ }
+ return dst - text;
+ }
+
+***************
+*** 5108,5114 ****
+ unsigned long msgno)
+ {
+ if (msgno && ov) { /* just in case */
+! MESSAGECACHE telt;
+ SORTCACHE *s = (SORTCACHE *) (*mailcache) (stream,msgno,CH_SORTCACHE);
+ if (!s->subject && ov->subject) {
+ s->refwd = mail_strip_subject (ov->subject,&s->subject);
+--- 5137,5144 ----
+ unsigned long msgno)
+ {
+ if (msgno && ov) { /* just in case */
+! MESSAGECACHE telt, *elt;
+! ENVELOPE *env;
+ SORTCACHE *s = (SORTCACHE *) (*mailcache) (stream,msgno,CH_SORTCACHE);
+ if (!s->subject && ov->subject) {
+ s->refwd = mail_strip_subject (ov->subject,&s->subject);
+***************
+*** 5127,5133 ****
+ s->dirty = T;
+ }
+ if (!s->references &&
+! !(s->references = mail_thread_parse_references (ov->references,T))) {
+ /* don't do In-Reply-To with NNTP mailboxes */
+ s->references = mail_newstringlist ();
+ s->dirty = T;
+--- 5157,5168 ----
+ s->dirty = T;
+ }
+ if (!s->references &&
+! !(s->references = mail_thread_parse_references (ov->references,T))
+! && stream->dtb && !strcmp(stream->dtb->name, "imap")
+! && (elt = mail_elt (stream, msgno)) != NULL
+! && (env = elt->private.msg.env) != NULL
+! && env->in_reply_to
+! && !(s->references = mail_thread_parse_references(env->in_reply_to, NIL))) {
+ /* don't do In-Reply-To with NNTP mailboxes */
+ s->references = mail_newstringlist ();
+ s->dirty = T;
+***************
+*** 6115,6120 ****
+--- 6150,6164 ----
+ return i;
+ return 0;
+ }
++ /* Client side callback warning to delete wrong password
++ *
++ */
++ void delete_password(NETMBX *mb, char *user)
++ {
++ deletepwd_t ep = mail_parameters(NULL, GET_ERASEPASSWORD, NULL);
++ if (ep) (ep)(mb, user);
++ }
++
+
+ /* Standard TCP/IP network driver */
+
+***************
+*** 6329,6331 ****
+--- 6373,6450 ----
+ {
+ return (*stream->dtb->localhost) (stream->stream);
+ }
++
++ /*
++ *
++ * Module to add support for password file to a c-client application
++ *
++ * Written by Eduardo Chappa, based on password file support for Pine
++ *
++ */
++ #ifndef PWDFILE
++ #define PWDFILE 1
++ #endif
++
++ #define FIRSTCH 0x20
++ #define LASTCH 0x7e
++ #define TABSZ (LASTCH - FIRSTCH + 1)
++
++ char mm_xlate_out (char c);
++ void mm_userpwd (NETMBX *mb, char **username, char **password);
++
++ /* function that decodes passwords */
++
++ char mm_xlate_out (char c)
++ {
++ register int dti;
++ register int xch;
++
++ if((c >= FIRSTCH) && (c <= LASTCH)){
++ xch = c - (dti = xlate_key);
++ xch += (xch < FIRSTCH-TABSZ) ? 2*TABSZ : (xch < FIRSTCH) ? TABSZ : 0;
++ dti = (xch - FIRSTCH) + dti;
++ dti -= (dti >= 2*TABSZ) ? 2*TABSZ : (dti >= TABSZ) ? TABSZ : 0;
++ xlate_key = dti;
++ return(xch);
++ }
++ else
++ return(c);
++ }
++
++ void mm_userpwd (NETMBX *mb, char **username, char **password)
++ {
++ char *s;
++ char tmp[MAILTMPLEN], *ui[5];
++ FILE *fp;
++ int i, j, n;
++
++ if (!(pwdfile = env_parameters(GET_PASSWORDFILE, NULL)))
++ return;
++
++ if (fp = fopen(pwdfile, "r")){
++ for(n = 0; fgets(tmp, sizeof(tmp), fp); n++){
++ xlate_key = n;
++ for(i = 0; tmp[i]; i++)
++ tmp[i] = mm_xlate_out(tmp[i]);
++
++ if(i && tmp[i-1] == '\n')
++ tmp[i-1] = '\0';
++
++ ui[0] = ui[1] = ui[2] = ui[3] = ui[4] = NULL;
++ for(i = 0, j = 0; tmp[i] && j < 5; j++){
++ for(ui[j] = &tmp[i]; tmp[i] && tmp[i] != '\t'; i++);
++
++ if(tmp[i])
++ tmp[i++] = '\0';
++ }
++ if (*username && ui[1] && !strcmp(*username, ui[1]) && mb->host
++ && ((ui[2] && !strcmp(mb->host, ui[2]))
++ || (ui[4] && !strcmp(mb->host,ui[4]))
++ || (ui[2] && !strcmp(mb->orighost, ui[2]))
++ || (ui[4] && !strcmp(mb->orighost,ui[4]))))
++ strcpy (*password,ui[0]);
++ }
++ fclose(fp);
++ }
++ }
++
+diff -rc alpine-2.00/imap/src/c-client/mail.h alpine-2.00.I.USE/imap/src/c-client/mail.h
+*** alpine-2.00/imap/src/c-client/mail.h 2008-08-08 10:34:22.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/c-client/mail.h 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 177,182 ****
+--- 177,186 ----
+ #define SET_EXTERNALAUTHID (long) 230
+ #define GET_SSLCAPATH (long) 231
+ #define SET_SSLCAPATH (long) 232
++ #define GET_ERASEPASSWORD (long) 233
++ #define SET_ERASEPASSWORD (long) 234
++ #define SET_PASSWORDFILE (long) 235
++ #define GET_PASSWORDFILE (long) 236
+
+ /* 3xx: TCP/IP */
+ #define GET_OPENTIMEOUT (long) 300
+***************
+*** 353,358 ****
+--- 357,366 ----
+ #define SET_SCANCONTENTS (long) 573
+ #define GET_MHALLOWINBOX (long) 574
+ #define SET_MHALLOWINBOX (long) 575
++ #define GET_COURIERSTYLE (long) 576
++ #define SET_COURIERSTYLE (long) 577
++ #define SET_MDINBOXPATH (long) 578
++ #define GET_MDINBOXPATH (long) 579
+
+ /* Driver flags */
+
+***************
+*** 685,690 ****
+--- 693,699 ----
+ /* Message envelope */
+
+ typedef struct mail_envelope {
++ unsigned int ngpathexists : 1; /* newsgroups may be bogus */
+ unsigned int incomplete : 1; /* envelope may be incomplete */
+ unsigned int imapenvonly : 1; /* envelope only has IMAP envelope */
+ char *remail; /* remail header if any */
+***************
+*** 1302,1308 ****
+ typedef void *(*mailcache_t) (MAILSTREAM *stream,unsigned long msgno,long op);
+ typedef long (*mailproxycopy_t) (MAILSTREAM *stream,char *sequence,
+ char *mailbox,long options);
+! typedef long (*tcptimeout_t) (long overall,long last);
+ typedef void *(*authchallenge_t) (void *stream,unsigned long *len);
+ typedef long (*authrespond_t) (void *stream,char *s,unsigned long size);
+ typedef long (*authcheck_t) (void);
+--- 1311,1317 ----
+ typedef void *(*mailcache_t) (MAILSTREAM *stream,unsigned long msgno,long op);
+ typedef long (*mailproxycopy_t) (MAILSTREAM *stream,char *sequence,
+ char *mailbox,long options);
+! typedef long (*tcptimeout_t) (long overall,long last, char *host);
+ typedef void *(*authchallenge_t) (void *stream,unsigned long *len);
+ typedef long (*authrespond_t) (void *stream,char *s,unsigned long size);
+ typedef long (*authcheck_t) (void);
+***************
+*** 1325,1330 ****
+--- 1334,1340 ----
+ typedef void *(*blocknotify_t) (int reason,void *data);
+ typedef long (*kinit_t) (char *host,char *reason);
+ typedef void (*sendcommand_t) (MAILSTREAM *stream,char *cmd,long flags);
++ typedef void (*deletepwd_t) (NETMBX *mb,char *user);
+ typedef char *(*newsrcquery_t) (MAILSTREAM *stream,char *mulname,char *name);
+ typedef void (*getacl_t) (MAILSTREAM *stream,char *mailbox,ACLLIST *acl);
+ typedef void (*listrights_t) (MAILSTREAM *stream,char *mailbox,char *id,
+***************
+*** 1604,1609 ****
+--- 1614,1621 ----
+ void mm_fatal (char *string);
+ void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op);
+
++ void delete_password (NETMBX *mb, char *user);
++
+ extern STRINGDRIVER mail_string;
+ void mail_versioncheck (char *version);
+ void mail_link (DRIVER *driver);
+diff -rc alpine-2.00/imap/src/c-client/nntp.c alpine-2.00.I.USE/imap/src/c-client/nntp.c
+*** alpine-2.00/imap/src/c-client/nntp.c 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/c-client/nntp.c 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 2031,2036 ****
+--- 2031,2037 ----
+ sprintf (tmp,"Retrying using %s authentication after %.80s",
+ at->name,lsterr);
+ mm_log (tmp,NIL);
++ delete_password(mb, mb ? mb->user : NULL);
+ fs_give ((void **) &lsterr);
+ }
+ trial = 0; /* initial trial count */
+***************
+*** 2039,2044 ****
+--- 2040,2046 ----
+ if (lsterr) {
+ sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr);
+ mm_log (tmp,WARN);
++ delete_password(mb, mb ? mb->user : NULL);
+ fs_give ((void **) &lsterr);
+ }
+ stream->saslcancel = NIL;
+***************
+*** 2064,2069 ****
+--- 2066,2072 ----
+ sprintf (tmp,"Can not authenticate to NNTP server: %.80s",lsterr);
+ mm_log (tmp,ERROR);
+ }
++ delete_password(mb, mb ? mb->user : NULL);
+ fs_give ((void **) &lsterr);
+ }
+ else if (mb->secflag) /* no SASL, can't do /secure */
+***************
+*** 2092,2097 ****
+--- 2095,2102 ----
+ stream->sensitive = T; /* hide this command */
+ if (nntp_send_work (stream,"AUTHINFO PASS",pwd) == NNTPAUTHED)
+ ret = LONGT; /* password OK */
++ else
++ delete_password(mb, mb ? mb->user : NULL);
+ stream->sensitive = NIL; /* unhide */
+ if (ret) break; /* OK if successful */
+ default: /* authentication failed */
+diff -rc alpine-2.00/imap/src/c-client/pop3.c alpine-2.00.I.USE/imap/src/c-client/pop3.c
+*** alpine-2.00/imap/src/c-client/pop3.c 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/c-client/pop3.c 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 615,620 ****
+--- 615,621 ----
+ sprintf (pwd,"Retrying using %.80s authentication after %.80s",
+ at->name,t);
+ mm_log (pwd,NIL);
++ delete_password(mb, usr);
+ fs_give ((void **) &t);
+ }
+ trial = 0; /* initial trial count */
+***************
+*** 622,627 ****
+--- 623,629 ----
+ if (t) {
+ sprintf (pwd,"Retrying %s authentication after %.80s",at->name,t);
+ mm_log (pwd,WARN);
++ delete_password(mb, usr);
+ fs_give ((void **) &t);
+ }
+ LOCAL->saslcancel = NIL;
+***************
+*** 667,672 ****
+--- 669,675 ----
+ LOCAL->sensitive=NIL; /* unhide */
+ }
+ if (!ret) { /* failure */
++ delete_password(mb, usr);
+ mm_log (LOCAL->reply,WARN);
+ if (trial == pop3_maxlogintrials)
+ mm_log ("Too many login failures",ERROR);
+diff -rc alpine-2.00/imap/src/c-client/rfc822.c alpine-2.00.I.USE/imap/src/c-client/rfc822.c
+*** alpine-2.00/imap/src/c-client/rfc822.c 2008-06-04 11:46:10.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/c-client/rfc822.c 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 128,133 ****
+--- 128,134 ----
+ ENVELOPE *env = (*en = mail_newenvelope ());
+ BODY *body = bdy ? (*bdy = mail_newbody ()) : NIL;
+ long MIMEp = -1; /* flag that MIME semantics are in effect */
++ long PathP = NIL; /* flag that a Path: was seen */
+ parseline_t pl = (parseline_t) mail_parameters (NIL,GET_PARSELINE,NIL);
+ if (!host) host = BADHOST; /* make sure that host is non-null */
+ while (i && *s != '\n') { /* until end of header */
+***************
+*** 230,235 ****
+--- 231,239 ----
+ *t++ = '\0';
+ }
+ break;
++ case 'P': /* possible Path: */
++ if (!strcmp (tmp+1,"ATH")) env->ngpathexists = T;
++ break;
+ case 'R': /* possible Reply-To: */
+ if (!strcmp (tmp+1,"EPLY-TO"))
+ rfc822_parse_adrlist (&env->reply_to,d,host);
+diff -rc alpine-2.00/imap/src/osdep/mac/tcp_mac.c alpine-2.00.I.USE/imap/src/osdep/mac/tcp_mac.c
+*** alpine-2.00/imap/src/osdep/mac/tcp_mac.c 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/osdep/mac/tcp_mac.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 383,389 ****
+ if (stream->pb.ioResult) { /* punt if got an error */
+ time_t tc = time (0);
+ if ((stream->pb.ioResult == commandTimeout) && tmoh &&
+! ((*tmoh) (tc - t,tc - tl))) continue;
+ /* nuke connection */
+ stream->pb.csCode = TCPAbort;
+ abortpb->userDataPtr = NIL;
+--- 383,389 ----
+ if (stream->pb.ioResult) { /* punt if got an error */
+ time_t tc = time (0);
+ if ((stream->pb.ioResult == commandTimeout) && tmoh &&
+! ((*tmoh) (tc - t,tc - tl, stream->host))) continue;
+ /* nuke connection */
+ stream->pb.csCode = TCPAbort;
+ abortpb->userDataPtr = NIL;
+diff -rc alpine-2.00/imap/src/osdep/nt/tcp_nt.c alpine-2.00.I.USE/imap/src/osdep/nt/tcp_nt.c
+*** alpine-2.00/imap/src/osdep/nt/tcp_nt.c 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/osdep/nt/tcp_nt.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 430,436 ****
+ SOCKET_ERROR) &&
+ ((errno = WSAGetLastError ()) == WSAEINTR));
+ else if (!i) { /* timeout, ignore if told to resume */
+! if (tmoh && (*tmoh) ((long) (now - t),(long) (now - tl))) continue;
+ /* otherwise punt */
+ if (tcpdebug) mm_log ("TCP buffer read timeout",TCPDEBUG);
+ return tcp_abort (stream);
+--- 430,438 ----
+ SOCKET_ERROR) &&
+ ((errno = WSAGetLastError ()) == WSAEINTR));
+ else if (!i) { /* timeout, ignore if told to resume */
+! if (tmoh && (*tmoh) ((long) (now - t),(long) (now - tl),
+! stream->host))
+! continue;
+ /* otherwise punt */
+ if (tcpdebug) mm_log ("TCP buffer read timeout",TCPDEBUG);
+ return tcp_abort (stream);
+***************
+*** 498,504 ****
+ SOCKET_ERROR) &&
+ ((errno = WSAGetLastError ()) == WSAEINTR));
+ else if (!i) { /* timeout, ignore if told to resume */
+! if (tmoh && (*tmoh) ((long) (now - t),(long) (now - tl))) continue;
+ /* otherwise punt */
+ if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG);
+ return tcp_abort (stream);
+--- 500,507 ----
+ SOCKET_ERROR) &&
+ ((errno = WSAGetLastError ()) == WSAEINTR));
+ else if (!i) { /* timeout, ignore if told to resume */
+! if (tmoh && (*tmoh) ((long) (now - t),(long) (now - tl), stream->host))
+! continue;
+ /* otherwise punt */
+ if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG);
+ return tcp_abort (stream);
+***************
+*** 582,588 ****
+ SOCKET_ERROR) &&
+ ((errno = WSAGetLastError ()) == WSAEINTR));
+ else if (!i) { /* timeout, ignore if told to resume */
+! if (tmoh && (*tmoh) ((long) (now - t),(long) (now - tl))) continue;
+ /* otherwise punt */
+ if (tcpdebug) mm_log ("TCP write timeout",TCPDEBUG);
+ return tcp_abort (stream);
+--- 585,592 ----
+ SOCKET_ERROR) &&
+ ((errno = WSAGetLastError ()) == WSAEINTR));
+ else if (!i) { /* timeout, ignore if told to resume */
+! if (tmoh && (*tmoh) ((long) (now - t),(long) (now - tl), stream->host))
+! continue;
+ /* otherwise punt */
+ if (tcpdebug) mm_log ("TCP write timeout",TCPDEBUG);
+ return tcp_abort (stream);
+diff -rc alpine-2.00/imap/src/osdep/unix/dummy.c alpine-2.00.I.USE/imap/src/osdep/unix/dummy.c
+*** alpine-2.00/imap/src/osdep/unix/dummy.c 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/osdep/unix/dummy.c 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 106,118 ****
+ * Accepts: mailbox name
+ * Returns: our driver if name is valid, NIL otherwise
+ */
+!
+ DRIVER *dummy_valid (char *name)
+ {
+! char *s,tmp[MAILTMPLEN];
+ struct stat sbuf;
+ /* must be valid local mailbox */
+! if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) {
+ /* indeterminate clearbox INBOX */
+ if (!*s) return &dummydriver;
+ else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) {
+--- 106,124 ----
+ * Accepts: mailbox name
+ * Returns: our driver if name is valid, NIL otherwise
+ */
+! char * maildir_remove_root(char *);
+ DRIVER *dummy_valid (char *name)
+ {
+! char *s,tmp[MAILTMPLEN], *rname;
+ struct stat sbuf;
++
++ if(strlen(name) > MAILTMPLEN)
++ name[MAILTMPLEN] = '\0';
++
++ strcpy(tmp, name);
++ rname = maildir_remove_root(tmp);
+ /* must be valid local mailbox */
+! if (rname && *rname && (*rname != '{') && (s = mailboxfile (tmp,rname))) {
+ /* indeterminate clearbox INBOX */
+ if (!*s) return &dummydriver;
+ else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) {
+***************
+*** 121,128 ****
+ return &dummydriver;
+ }
+ /* blackbox INBOX does not exist yet */
+! else if (!compare_cstring (name,"INBOX")) return &dummydriver;
+ }
+ return NIL;
+ }
+
+--- 127,135 ----
+ return &dummydriver;
+ }
+ /* blackbox INBOX does not exist yet */
+! else if (!compare_cstring (rname,"INBOX")) return &dummydriver;
+ }
++ if(rname) fs_give((void **)&rname);
+ return NIL;
+ }
+
+***************
+*** 454,459 ****
+--- 461,468 ----
+ {
+ char *s,tmp[MAILTMPLEN];
+ long ret = NIL;
++ if(!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4))
++ return maildir_create(stream, mailbox);
+ /* validate name */
+ if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) {
+ sprintf (tmp,"Can't create %.80s: invalid name",mailbox);
+***************
+*** 519,524 ****
+--- 528,541 ----
+ {
+ struct stat sbuf;
+ char *s,tmp[MAILTMPLEN];
++ if (!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4)
++ || is_valid_maildir(&mailbox)){
++ char tmp[MAILTMPLEN] = {'\0'};
++ strcpy(tmp, mailbox);
++ if(tmp[strlen(tmp) - 1] != '/')
++ tmp[strlen(tmp)] = '/';
++ return maildir_delete(stream, tmp);
++ }
+ if (!(s = dummy_file (tmp,mailbox))) {
+ sprintf (tmp,"Can't delete - invalid name: %.80s",s);
+ MM_LOG (tmp,ERROR);
+***************
+*** 544,555 ****
+ long dummy_rename (MAILSTREAM *stream,char *old,char *newname)
+ {
+ struct stat sbuf;
+! char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN];
+ /* no trailing / allowed */
+! if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) ||
+ stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] &&
+ ((sbuf.st_mode & S_IFMT) != S_IFDIR))) {
+! sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname);
+ MM_LOG (mbx,ERROR);
+ return NIL;
+ }
+--- 561,583 ----
+ long dummy_rename (MAILSTREAM *stream,char *old,char *newname)
+ {
+ struct stat sbuf;
+! char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN], *rold, *rnewname;
+!
+! if(strlen(old) > MAILTMPLEN)
+! old[MAILTMPLEN] = '\0';
+!
+! if(strlen(newname) > MAILTMPLEN)
+! newname[MAILTMPLEN] = '\0';
+!
+! strcpy(tmp, old);
+! rold = maildir_remove_root(tmp);
+! strcpy(tmp, newname);
+! rnewname = maildir_remove_root(tmp);
+ /* no trailing / allowed */
+! if (!dummy_file (oldname,rold) || !(s = dummy_file (mbx,rnewname)) ||
+ stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] &&
+ ((sbuf.st_mode & S_IFMT) != S_IFDIR))) {
+! sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",rold,rnewname);
+ MM_LOG (mbx,ERROR);
+ return NIL;
+ }
+***************
+*** 565,578 ****
+ }
+ }
+ /* rename of non-ex INBOX creates dest */
+! if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf))
+ return dummy_create (NIL,mbx);
+ if (rename (oldname,mbx)) {
+! sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname,
+ strerror (errno));
+ MM_LOG (tmp,ERROR);
+ return NIL;
+ }
+ return T; /* return success */
+ }
+
+--- 593,608 ----
+ }
+ }
+ /* rename of non-ex INBOX creates dest */
+! if (!compare_cstring (rold,"INBOX") && stat (oldname,&sbuf))
+ return dummy_create (NIL,mbx);
+ if (rename (oldname,mbx)) {
+! sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",rold,rnewname,
+ strerror (errno));
+ MM_LOG (tmp,ERROR);
+ return NIL;
+ }
++ if(rold) fs_give((void **)&rold);
++ if(rnewname) fs_give((void **)&rnewname);
+ return T; /* return success */
+ }
+
+diff -rc alpine-2.00/imap/src/osdep/unix/maildir.c alpine-2.00.I.USE/imap/src/osdep/unix/maildir.c
+*** alpine-2.00/imap/src/osdep/unix/maildir.c 2011-02-07 20:34:02.000000000 -0800
+--- alpine-2.00.I.USE/imap/src/osdep/unix/maildir.c 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 0 ****
+--- 1,2584 ----
++ /*
++ * Maildir driver for Alpine 2.00
++ *
++ * Written by Eduardo Chappa <chappa@washington.edu>
++ * Last Update: November 6, 2010.
++ *
++ */
++
++ #include <stdio.h>
++ #include <ctype.h>
++ #include <errno.h>
++ extern int errno; /* just in case */
++ #include "mail.h"
++ #include <pwd.h>
++ #include <sys/stat.h>
++ #include <sys/time.h>
++ #include "osdep.h"
++ #include "rfc822.h"
++ #include "fdstring.h"
++ #include "misc.h"
++ #include "dummy.h"
++ #include "maildir.h"
++
++ /* Driver dispatch used by MAIL */
++ DRIVER maildirdriver = {
++ "md", /* driver name, yes it's md, not maildir */
++ /* driver flags */
++ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_DIRFMT,
++ (DRIVER *) NIL, /* next driver */
++ maildir_valid, /* mailbox is valid for us */
++ maildir_parameters, /* manipulate parameters */
++ NIL, /* scan mailboxes */
++ maildir_list, /* find mailboxes */
++ maildir_lsub, /* find subscribed mailboxes */
++ maildir_sub, /* subscribe to mailbox */
++ maildir_unsub, /* unsubscribe from mailbox */
++ maildir_create, /* create mailbox */
++ maildir_delete, /* delete mailbox */
++ maildir_rename, /* rename mailbox */
++ mail_status_default, /* status of mailbox */
++ maildir_open, /* open mailbox */
++ maildir_close, /* close mailbox */
++ maildir_fast, /* fetch message "fast" attributes */
++ NIL, /* fetch message flags */
++ NIL, /* fetch overview */
++ NIL, /* fetch message structure */
++ maildir_header, /* fetch message header */
++ maildir_text, /* fetch message body */
++ NIL, /* fetch partial message text */
++ NIL, /* unique identifier */
++ NIL, /* message number */
++ NIL, /* modify flags */
++ maildir_flagmsg, /* per-message modify flags */
++ NIL, /* search for message based on criteria */
++ NIL, /* sort messages */
++ NIL, /* thread messages */
++ maildir_ping, /* ping mailbox to see if still alive */
++ maildir_check, /* check for new messages */
++ maildir_expunge, /* expunge deleted messages */
++ maildir_copy, /* copy messages to another mailbox */
++ maildir_append, /* append string message to mailbox */
++ NIL /* garbage collect stream */
++ };
++
++
++ DRIVER courierdriver = {
++ "mc", /* Why a separate driver? So that
++ createproto will work */
++ /* driver flags */
++ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_DIRFMT,
++ (DRIVER *) NIL, /* next driver */
++ maildir_valid, /* mailbox is valid for us */
++ maildir_parameters, /* manipulate parameters */
++ NIL, /* scan mailboxes */
++ courier_list, /* find mailboxes */
++ maildir_lsub, /* find subscribed mailboxes */
++ maildir_sub, /* subscribe to mailbox */
++ maildir_unsub, /* unsubscribe from mailbox */
++ maildir_create, /* create mailbox */
++ maildir_delete, /* delete mailbox */
++ maildir_rename, /* rename mailbox */
++ mail_status_default, /* status of mailbox */
++ maildir_open, /* open mailbox */
++ maildir_close, /* close mailbox */
++ maildir_fast, /* fetch message "fast" attributes */
++ NIL, /* fetch message flags */
++ NIL, /* fetch overview */
++ NIL, /* fetch message structure */
++ maildir_header, /* fetch message header */
++ maildir_text, /* fetch message body */
++ NIL, /* fetch partial message text */
++ NIL, /* unique identifier */
++ NIL, /* message number */
++ NIL, /* modify flags */
++ maildir_flagmsg, /* per-message modify flags */
++ NIL, /* search for message based on criteria */
++ NIL, /* sort messages */
++ NIL, /* thread messages */
++ maildir_ping, /* ping mailbox to see if still alive */
++ maildir_check, /* check for new messages */
++ maildir_expunge, /* expunge deleted messages */
++ maildir_copy, /* copy messages to another mailbox */
++ maildir_append, /* append string message to mailbox */
++ NIL /* garbage collect stream */
++ };
++
++ MAILSTREAM maildirproto = {&maildirdriver}; /* prototype stream */
++ MAILSTREAM courierproto = {&courierdriver}; /* prototype stream */
++
++ long maildir_dirfmttest (char *name)
++ {
++ int i;
++ for (i = 0; mdstruct[i] && strcmp(name, mdstruct[i]); i++);
++ return (i < EndDir) || !strcmp(name, MDDIR)
++ || !strncmp(name, MDUIDLAST, strlen(MDUIDLAST))
++ || !strncmp(name, MDUIDTEMP, strlen(MDUIDTEMP)) ? LONGT : NIL;
++ }
++
++ void
++ md_domain_name(void)
++ {
++ int i;
++
++ strcpy(mdlocaldomain,mylocalhost ());
++ for (i = 0; mdlocaldomain[i] ; i++)
++ if(mdlocaldomain[i] == '/')
++ mdlocaldomain[i] = '\057';
++ else if (mdlocaldomain[i] == ':')
++ mdlocaldomain[i] = '\072';
++ }
++
++ char *
++ myrootdir(char *name)
++ {
++ return myhomedir();
++ }
++
++ char *
++ mdirpath(void)
++ {
++ char *path = maildir_parameters(GET_MDINBOXPATH,NIL);
++ return path ? (path[0] ? path : ".") : "Maildir";
++ }
++
++ /* remove the "#md/" or "#mc/" part from a folder name */
++ char *
++ maildir_remove_root (char *name)
++ {
++ int courier = IS_COURIER(name), offset;
++ char realname[MAILTMPLEN];
++
++ offset = maildir_valid_name(name) ? (name[3] == '/' ? 4 : 3) : 0;
++ if(courier)
++ courier_realname(name+offset, realname);
++ else
++ strcpy(realname, name+offset);
++ return cpystr(realname);
++ }
++
++
++ /* Check validity of the name, we accept:
++ * a) #md/directory/folder
++ * b) #md/inbox
++ * A few considerations: We can only accept as valid
++ * a) names that start with #md/ and the directory exists or
++ * b) names that do not start with #md/ but are maildir directories (have
++ * the /cur, /tmp and /new structure)
++ */
++ int maildir_valid_name (char *name)
++ {
++ char tmpname[MAILTMPLEN] = {'\0'};
++
++ if (mdfpath)
++ fs_give((void **)&mdfpath);
++ if (name && (name[0] != '#'))
++ sprintf(tmpname,"%s%s",MDPREFIX(CCLIENT), name);
++ mdfpath = cpystr(tmpname[0] ? tmpname : name);
++
++ return IS_CCLIENT(name) || IS_COURIER(name);
++ }
++
++ /* Check if the directory whose path is given by name is a valid maildir
++ * directory (contains /cur, /tmp and /new)
++ */
++ int maildir_valid_dir (char *name)
++ {
++ int len;
++ DirNamesType i;
++ struct stat sbuf;
++ char tmp[MAILTMPLEN];
++
++ if(name[strlen(name) - 1] == '/')
++ name[strlen(name) - 1] = '\0';
++ len = strlen(name);
++ for (i = Cur; i != EndDir; i++){
++ MDFLD(tmp, name, i);
++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode))
++ break;
++ }
++ name[len] = '\0';
++ return (i == EndDir) ? T : NIL;
++ }
++
++ void courier_realname(char *name, char *realname)
++ {
++ int i,j;
++
++ if(!name)
++ return;
++
++ for (i = 0, j = 0; i < MAILTMPLEN && j < strlen(name); j++, i++){
++ realname[i] = name[j];
++ if(name[j] == '/' && name[j+1] != '.' && name[j+1] != '%'
++ && name[j+1] != '*')
++ realname[++i] = '.';
++ }
++ if(realname[i-1] == '.')
++ i--;
++ realname[i] = '\0';
++ }
++
++
++ /* given a maildir folder, return its path. Memory freed by caller. Directory
++ * does not contain the trailing slash "/". On error NULL is returned.
++ */
++ int maildir_file_path (char *name, char *tmp)
++ {
++ char *maildirpath = mdirpath(), *rname;
++ int courier = IS_COURIER(name);
++
++ /* There are several ways in which the path can come, so we will handle
++ them here. First we deal with #mc/ or #md/ prefix by removing the
++ prefix, if any */
++
++ if(strlen(name) >= MAILTMPLEN)
++ name[MAILTMPLEN] = '\0';
++ strcpy(tmp, name);
++ rname = maildir_remove_root(tmp);
++ tmp[0] = '\0'; /* just in case something fails */
++
++ if (strlen(myrootdir(rname)) +
++ max(strlen(rname), strlen(maildirpath)) > MAILTMPLEN){
++ errno = ENAMETOOLONG;
++ sprintf(tmp,"Error opening \"%s\": %s", rname, strerror (errno));
++ mm_log(tmp,ERROR);
++ return NIL;
++ }
++
++ /* There are two ways in which the name can come here, either as a
++ full path or not. If it is not a full path it can come in two ways,
++ either as a file system path (Maildir/.Drafts) or as a maildir path
++ (INBOX.Drafts)
++ */
++
++ if(*rname == '/') /* full path */
++ strcpy(tmp, rname); /* do nothing */
++ else{
++ sprintf (tmp,"%s/%s%s%s", myrootdir (rname),
++ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5)
++ ? rname : maildirpath,
++ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5)
++ ? "" : (courier ? "/" : ""),
++ strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5)
++ ? "" : (*(rname+5) == MDSEPARATOR(courier) ? rname+5 : ""));
++ }
++ if(rname) fs_give((void **)&rname);
++ return tmp[0] ? T : NIL;
++ }
++
++ /* This function is given a full path for a mailbox and returns
++ * if it is a valid maildir transformed to canonical notation
++ */
++ int
++ is_valid_maildir (char **name)
++ {
++ if (!strncmp(*name, myrootdir (*name), strlen(myrootdir(*name)))){
++ (*name) += strlen(myrootdir(*name));
++ if (**name == '/') (*name)++;
++ }
++ return maildir_valid(*name) ? T : NIL;
++ }
++
++ /* Check validity of mailbox. This routine does not send errors to log, other
++ * routines calling this one may do so, though
++ */
++
++ DRIVER *maildir_valid (char *name)
++ {
++ char tmpname[MAILTMPLEN];
++
++ maildir_file_path(name, tmpname);
++
++ return maildir_valid_dir(tmpname)
++ ? (IS_COURIER(name) ? &courierdriver : &maildirdriver) : NIL;
++ }
++
++ void maildir_fast (MAILSTREAM *stream,char *sequence,long flags)
++ {
++ unsigned long i;
++ MESSAGECACHE *elt;
++ /* get sequence */
++ if (stream && LOCAL && ((flags & FT_UID) ?
++ mail_uid_sequence (stream,sequence) :
++ mail_sequence (stream,sequence)))
++ for (i = 1L; i <= stream->nmsgs; i++) {
++ if ((elt = mail_elt (stream,i))->sequence && (elt->valid = T) &&
++ !(elt->day && elt->rfc822_size)) {
++ ENVELOPE **env = NIL;
++ ENVELOPE *e = NIL;
++ if (!stream->scache) env = &elt->private.msg.env;
++ else if (stream->msgno == i) env = &stream->env;
++ else env = &e;
++ if (!*env || !elt->rfc822_size) {
++ STRING bs;
++ unsigned long hs;
++ char *ht = (*stream->dtb->header) (stream,i,&hs,NIL);
++
++ if (!*env) rfc822_parse_msg (env,NIL,ht,hs,NIL,BADHOST,
++ stream->dtb->flags);
++ if (!elt->rfc822_size) {
++ (*stream->dtb->text) (stream,i,&bs,FT_PEEK);
++ elt->rfc822_size = hs + SIZE (&bs) - GETPOS (&bs);
++ }
++ }
++
++ if (!elt->day && *env && (*env)->date)
++ mail_parse_date (elt,(*env)->date);
++
++ if (!elt->day) elt->day = elt->month = 1;
++ mail_free_envelope (&e);
++ }
++ }
++ }
++
++ int
++ maildir_eliminate_duplicate (char *name, struct direct ***flist, unsigned long *nfiles)
++ {
++ int i, j, k, error = 0, scanr;
++ char new[MAILTMPLEN], old[MAILTMPLEN], tmp[MAILTMPLEN], *str;
++ struct direct **names = NIL;
++
++ if((scanr = maildir_doscandir(name, &names, CCLIENT)) < 0)
++ return -1;
++
++ if(nfiles) *nfiles = scanr;
++ for(i = 0, j = 1, k = 0; j < scanr; i++, j++){
++ if(k)
++ names[i] = names[i+k];
++ if(same_maildir_file(names[i]->d_name, names[j]->d_name)){
++ int d, f, r, s;
++ maildir_getflag(names[i]->d_name, &d, &f, &r, &s, NIL);
++ sprintf(old,"%s/%s", name, names[i]->d_name);
++ sprintf(new,"%s/.%s", name, names[i]->d_name);
++ if(rename(old, new) < 0 && errno != EEXIST)
++ error++;
++ if(!error){
++ for(; j < scanr
++ && same_maildir_file(names[i]->d_name, names[j]->d_name)
++ ; j++, k++){
++ maildir_getflag(names[j]->d_name, (d ? NIL : &d),
++ (f ? NIL : &f), (r ? NIL : &r), (s ? NIL : &s), NIL);
++ sprintf(tmp,"%s/%s", name, names[j]->d_name);
++ if(unlink(tmp) < 0){ /* Hmmm... a problem, let's see */
++ struct stat sbuf;
++ if (stat(tmp, &sbuf) == 0 && (sbuf.st_mode & S_IFMT) == S_IFREG)
++ error++;
++ }
++ }
++ if((str = strrchr(names[i]->d_name,FLAGSEP)) != NULL) *str = '\0';
++ sprintf (old,"%s/%s%s%s%s%s%s", name, names[i]->d_name, MDSEP(2),
++ MDFLAG(Draft, d), MDFLAG(Flagged, f), MDFLAG(Replied, r),
++ MDFLAG(Seen, s));
++ if(rename(new, old) < 0)
++ error++;
++ }
++ }
++
++ }
++ if(k > 0)
++ fs_give((void **)&names);
++ else
++ *flist = names;
++ return error ? -1 : k;
++ }
++
++ int
++ maildir_doscandir(char *name, struct direct ***flist, int flag)
++ {
++ return scandir(name, flist,
++ flag == CCLIENT ? maildir_select : courier_dir_select,
++ flag == CCLIENT ? maildir_namesort : courier_dir_sort);
++ }
++
++ /*
++ * return all files in a given directory. This is a separate call
++ * so that if there are warnings during compilation this only appears once.
++ */
++ unsigned long
++ maildir_scandir (char *name, struct direct ***flist,
++ unsigned long *nfiles, int *scand, int flag)
++ {
++ struct stat sbuf;
++ int rv = -2; /* impossible value */
++
++ if (scand)
++ *scand = -1; /* assume error for safety */
++ *nfiles = 0;
++ if((stat(name,&sbuf) < 0)
++ || (flag == CCLIENT
++ && ((rv = maildir_eliminate_duplicate(name, flist, nfiles)) < 0)))
++ return 0L;
++
++ if (scand && (rv > 0 || rv == -2))
++ *nfiles = maildir_doscandir(name, flist, flag);
++
++ if(scand) *scand = *nfiles;
++
++ return (unsigned long) sbuf.st_ctime;
++ }
++
++ /* Does a message with given name exists (or was it removed)?
++ * Returns: 1 - yes, such message exist,
++ * 0 - No, that message does not exist anymore
++ *
++ * Parameters: stream, name of mailbox, new name if his message does not
++ * exist.
++ */
++
++ int maildir_message_exists(MAILSTREAM *stream, char *name, char *newfile)
++ {
++ char tmp[MAILTMPLEN];
++ int gotit = NIL;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++
++ /* First check directly if it exists, if not there, look for it */
++ sprintf(tmp,"%s/%s", LOCAL->curdir, name);
++ if ((stat(tmp, &sbuf) == 0) && ((sbuf.st_mode & S_IFMT) == S_IFREG))
++ return T;
++
++ if (!(dir = opendir (LOCAL->curdir)))
++ return NIL;
++
++ while ((d = readdir(dir)) && gotit == NIL){
++ if (d->d_name[0] == '.')
++ continue;
++ if (same_maildir_file(d->d_name, name)){
++ gotit = T;
++ strcpy(newfile, d->d_name);
++ }
++ }
++ closedir(dir);
++ return gotit;
++ }
++
++ /* Maildir open */
++
++ MAILSTREAM *maildir_open (MAILSTREAM *stream)
++ {
++ char tmp[MAILTMPLEN];
++ struct stat sbuf;
++
++ if (!stream) return &maildirproto;
++ if (stream->local) fatal ("maildir recycle stream");
++ md_domain_name(); /* get domain name for maildir files in mdlocaldomain */
++ if(mypid == (pid_t) 0)
++ mypid = getpid();
++ if (!stream->rdonly){
++ stream->perm_seen = stream->perm_deleted = stream->perm_flagged =
++ stream->perm_answered = stream->perm_draft = T;
++ }
++ stream->local = (MAILDIRLOCAL *) fs_get (sizeof (MAILDIRLOCAL));
++ memset(LOCAL, 0, sizeof(MAILDIRLOCAL));
++ LOCAL->fd = -1;
++
++ LOCAL->courier = IS_COURIER(stream->mailbox);
++ strcpy(tmp, stream->mailbox);
++ if (maildir_file_path (stream->mailbox, tmp))
++ LOCAL->dir = cpystr (tmp);
++ LOCAL->candouid = maildir_can_assign_uid(stream);
++ maildir_read_uid(stream, &stream->uid_last, &stream->uid_validity);
++ if (LOCAL->dir){
++ MDFLD(tmp, LOCAL->dir, Cur);
++ LOCAL->curdir = cpystr (tmp);
++ if (stat (LOCAL->curdir,&sbuf) < 0) {
++ sprintf (tmp,"Can't open folder %s: %s",
++ stream->mailbox,strerror (errno));
++ mm_log (tmp,ERROR);
++ maildir_close(stream, 0);
++ return NIL;
++ }
++ }
++
++ if(maildir_file_path (stream->mailbox, tmp)){
++ fs_give ((void **) &stream->mailbox);
++ stream->mailbox = cpystr(tmp);
++ }
++
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = SENDBUFLEN) + 1);
++ stream->sequence++;
++ stream->nmsgs = stream->recent = 0L;
++
++ maildir_parse_folder(stream, 1);
++
++ return stream;
++ }
++
++ /* Maildir initial parsing of the folder */
++ void
++ maildir_parse_folder (MAILSTREAM *stream, int full)
++ {
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN];
++ struct direct **namescur = NIL, **namesnew = NIL;
++ unsigned long i, nfilescur = 0L, nfilesnew = 0L, oldpos, newpos, total;
++ int scan_err, rescan, loop = 0;
++
++ if (!stream) /* what??? */
++ return;
++
++ MM_CRITICAL(stream);
++
++ MDFLD(tmp, LOCAL->dir, New);
++ maildir_scandir (tmp, &namesnew, &nfilesnew, &scan_err, CCLIENT);
++ if (scan_err < 0)
++ maildir_abort(stream);
++
++ /* Scan old messages first, escoba! */
++ if(stream->rdonly ||
++ (LOCAL && ((maildir_initial_check(stream, Cur) == 0)
++ || nfilesnew > 0L))){
++ MDFLD(tmp, LOCAL->dir, Cur);
++ LOCAL->scantime = maildir_scandir (tmp, &namescur, &nfilescur,
++ &scan_err, CCLIENT);
++ if (scan_err < 0){
++ if(namesnew){
++ for(i = 0L; i < nfilesnew; i++)
++ fs_give((void **)&namesnew[i]);
++ fs_give((void **) &namesnew);
++ }
++ maildir_abort(stream);
++ }
++ }
++ if(LOCAL && (maildir_initial_check(stream, New) == 0)
++ && (nfilescur > 0L)){
++ MDFLD(tmp, LOCAL->dir, New);
++ while(LOCAL && loop < 10){
++ if(nfilesnew == 0L)
++ maildir_scandir (tmp, &namesnew, &nfilesnew, &scan_err, CCLIENT);
++ if (scan_err < 0){
++ if(namesnew){
++ for(i = 0L; i < nfilesnew; i++)
++ fs_give((void **)&namesnew[i]);
++ fs_give((void **) &namesnew);
++ }
++ maildir_abort(stream);
++ break;
++ }
++ for(i = 0L, rescan = 0, newpos = oldpos = 0L;
++ newpos < nfilescur && i < nfilesnew; i++){
++ if(maildir_message_in_list(namesnew[i]->d_name, namescur, oldpos,
++ nfilescur - 1L, &newpos)){
++ oldpos = newpos;
++ sprintf(tmp2,"%s/%s",tmp,namesnew[i]->d_name);
++ if(unlink(tmp2) < 0)
++ scan_err = -1;
++ rescan++;
++ }
++ else
++ newpos = oldpos;
++ }
++ if(scan_err < 0)
++ maildir_abort(stream);
++ if(rescan == 0)
++ break;
++ else{ /* restart */
++ if(namesnew){
++ for(i = 0L; i < nfilesnew; i++)
++ fs_give((void **)&namesnew[i]);
++ fs_give((void **) &namesnew);
++ }
++ nfilesnew = 0L;
++ loop++;
++ }
++ }
++ }
++ if(loop == 10)
++ maildir_abort(stream);
++ if(LOCAL){
++ if(stream->rdonly)
++ stream->recent = 0L;
++ total = namescur || stream->rdonly
++ ? maildir_parse_dir(stream, 0L, Cur, namescur,
++ nfilescur, full) : stream->nmsgs;
++ stream->nmsgs = maildir_parse_dir(stream, total, New, namesnew,
++ nfilesnew, full);
++ }
++ if(namesnew){
++ for(i = 0L; i < nfilesnew; i++)
++ fs_give((void **)&namesnew[i]);
++ fs_give((void **) &namesnew);
++ }
++ if(namescur){
++ for(i = 0L; i < nfilescur; i++)
++ fs_give((void **)&namescur[i]);
++ fs_give((void **) &namescur);
++ }
++ MM_NOCRITICAL(stream);
++ }
++
++ int
++ maildir_initial_check (MAILSTREAM *stream, DirNamesType dirtype)
++ {
++ char tmp[MAILTMPLEN];
++ struct stat sbuf;
++
++ MDFLD(tmp, LOCAL->dir, dirtype);
++ if (access (tmp, R_OK|W_OK|X_OK) != 0){
++ maildir_abort(stream);
++ return -1;
++ }
++
++ MDFLD(tmp, LOCAL->dir, Cur);
++ if (dirtype != New &&
++ (stat(tmp, &sbuf) < 0 || sbuf.st_ctime == LOCAL->scantime))
++ return -1;
++ return 0;
++ }
++
++
++ /* Return the number of messages in the directory, while filling the
++ * elt structure.
++ */
++
++ unsigned long
++ maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs,
++ DirNamesType dirtype, struct direct **names,
++ unsigned long nfiles, int full)
++ {
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], file[MAILTMPLEN],
++ newfile[MAILTMPLEN], *mdstr;
++ struct stat sbuf;
++ unsigned long i, new = 0L, l, uid_last;
++ unsigned long recent = stream ? stream->recent : 0L;
++ int d = 0, f = 0, r = 0, s = 0, t = 0;
++ int we_compute, in_list;
++ int silent = stream ? stream->silent : NIL;
++ MESSAGECACHE *elt;
++
++ MDFLD(tmp, LOCAL->dir, dirtype);
++ if (dirtype == Cur && !stream->rdonly)
++ for (i = 1L; i <= stream->nmsgs;){
++ elt = mail_elt(stream, i);
++ in_list = elt && elt->private.spare.ptr && nfiles > 0L
++ ? (MDPOS(elt) < nfiles
++ ? same_maildir_file(MDFILE(elt), names[MDPOS(elt)]->d_name)
++ : NIL)
++ || maildir_message_in_list(MDFILE(elt), names, 0L,
++ nfiles - 1L, &MDPOS(elt))
++ : NIL;
++ if (!in_list){
++ if (elt->private.spare.ptr)
++ maildir_free_file ((void **) &elt->private.spare.ptr);
++
++ if (elt->recent) --recent;
++ mail_expunged(stream,i);
++ }
++ else i++;
++ }
++
++ stream->silent = T;
++ uid_last = 0L;
++ for (we_compute = 0, i = l = 1L; l <= nfiles; l++){
++ unsigned long pos, uid;
++ if (dirtype == New && !stream->rdonly){ /* move new messages to cur */
++ pos = l - 1L;
++ sprintf (file,"%s/%s", tmp, names[pos]->d_name);
++ if(lstat(file,&sbuf) == 0)
++ switch(sbuf.st_mode & S_IFMT){
++ case S_IFREG:
++ strcpy(tmp2, names[pos]->d_name);
++ if((mdstr = strstr(tmp2,MDSEP(3)))
++ || (mdstr = strstr(tmp2,MDSEP(2))))
++ *(mdstr+1) = '2';
++ else
++ strcat(tmp2, MDSEP(2));
++ sprintf(newfile, "%s/%s",LOCAL->curdir, tmp2);
++ if(rename (file, newfile) != 0){
++ mm_log("Unable to read new mail!", WARN);
++ continue;
++ }
++ unlink (file);
++ new++;
++ break;
++ case S_IFLNK: /* clean up, clean up, everybody, everywhere */
++ if(unlink(file) < 0){
++ if(LOCAL->link == NIL){
++ mm_log("Unable to remove symbolic link", WARN);
++ LOCAL->link = T;
++ }
++ }
++ continue;
++ break;
++ default:
++ if(LOCAL && LOCAL->link == NIL){
++ mm_log("Unrecognized file or link in folder", WARN);
++ LOCAL->link = T;
++ }
++ continue;
++ break;
++ }
++ }
++ mail_exists(stream, i + nmsgs);
++ elt = mail_elt(stream, i + nmsgs);
++ pos = (elt && elt->private.spare.ptr) ? MDPOS(elt) : l - 1L;
++ if (dirtype == New) elt->recent = T;
++ maildir_getflag(names[pos]->d_name, &d, &f, &r ,&s, &t);
++ if (elt->private.spare.ptr)
++ maildir_free_file_only ((void **)&elt->private.spare.ptr);
++ else{
++ maildir_get_file((MAILDIRFILE **)&elt->private.spare.ptr);
++ we_compute++;
++ }
++ MDFILE(elt) = cpystr(names[pos]->d_name);
++ MDPOS(elt) = pos;
++ MDLOC(elt) = dirtype;
++ if (dirtype == Cur){ /* deal with UIDs */
++ if(elt->private.uid == 0L)
++ elt->private.uid = maildir_get_uid(MDFILE(elt));
++ if(elt->private.uid <= uid_last){
++ uid = (we_compute ? uid_last : stream->uid_last) + 1L;
++ if(LOCAL->candouid)
++ maildir_assign_uid(stream, i + nmsgs, uid);
++ else
++ elt->private.uid = uid;
++ }
++ else
++ uid = elt->private.uid;
++ uid_last = uid;
++ if(uid_last > stream->uid_last)
++ stream->uid_last = uid_last;
++ }
++ if(dirtype == New && !stream->rdonly){
++ maildir_free_file_only((void **)&elt->private.spare.ptr);
++ MDFILE(elt) = cpystr(tmp2);
++ MDSIZE(elt) = sbuf.st_size;
++ MDMTIME(elt) = sbuf.st_mtime;
++ MDLOC(elt) = Cur;
++ }
++ if (elt->draft != d || elt->flagged != f ||
++ elt->answered != r || elt->seen != s || elt->deleted != t){
++ elt->draft = d; elt->flagged = f; elt->answered = r;
++ elt->seen = s; elt->deleted = t;
++ if (!we_compute && !stream->rdonly)
++ MM_FLAGS(stream, i+nmsgs);
++ }
++ maildir_get_date(stream, i+nmsgs);
++ elt->valid = T;
++ i++;
++ }
++ stream->silent = silent;
++ if(LOCAL->candouid && dirtype == Cur)
++ maildir_read_uid(stream, NULL, &stream->uid_validity);
++ if (dirtype == New && stream->rdonly)
++ new = nfiles;
++ mail_exists(stream, nmsgs + ((dirtype == New) ? new : nfiles));
++ mail_recent(stream, recent + ((dirtype == New) ? new : 0L));
++
++ return (nmsgs + (dirtype == New ? new : nfiles));
++ }
++
++ long maildir_ping (MAILSTREAM *stream)
++ {
++ maildir_parse_folder(stream, 0);
++ if(stream && LOCAL){
++ if(LOCAL->candouid)
++ maildir_uid_renew_tempfile(stream);
++ else /* try again to get uids */
++ LOCAL->candouid = maildir_can_assign_uid(stream);
++ }
++ return stream && LOCAL ? LONGT : NIL;
++ }
++
++ int maildir_select (const struct direct *name)
++ {
++ return (name->d_name[0] != '.');
++ }
++
++ /*
++ * Unfortunately, there is no way to sort by arrival in this driver, this
++ * means that opening a folder in this driver using the scandir function
++ * will always make this driver slower than any driver that has a natural
++ * way of sorting by arrival (like a flat file format, "mbox", "mbx", etc).
++ */
++ int maildir_namesort (const void *d1, const void *d2)
++ {
++ const struct direct *e1 = *(const struct direct **) d1;
++ const struct direct *e2 = *(const struct direct **) d2;
++
++ return comp_maildir_file((char *) e1->d_name, (char *) e2->d_name);
++ }
++
++ /* Maildir close */
++
++ void maildir_close (MAILSTREAM *stream, long options)
++ {
++ MESSAGECACHE *elt;
++ unsigned long i;
++ int silent = stream ? stream->silent : 0;
++ mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
++
++ if (!stream) return;
++
++ for (i = 1L; i <= stream->nmsgs; i++)
++ if((elt = (MESSAGECACHE *) (*mc)(stream,i,CH_ELT)) && elt->private.spare.ptr)
++ maildir_free_file ((void **) &elt->private.spare.ptr);
++ stream->silent = T;
++ if (options & CL_EXPUNGE) maildir_expunge (stream, NIL, NIL);
++ maildir_abort(stream);
++ if (mdfpath) fs_give((void **)&mdfpath);
++ if (mypid) mypid = (pid_t) 0;
++ stream->silent = silent;
++ }
++
++ void maildir_check (MAILSTREAM *stream)
++ {
++ if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL);
++ }
++
++ long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags)
++ {
++ char tmp[MAILTMPLEN];
++ unsigned long i;
++ MESSAGECACHE *elt;
++ char *s;
++ /* UID call "impossible" */
++ if (flags & FT_UID || !LOCAL) return NIL;
++ elt = mail_elt (stream, msgno);
++
++ if (!(flags & FT_PEEK) && !elt->seen){
++ elt->seen = T;
++ maildir_flagmsg (stream, elt);
++ MM_FLAGS(stream, elt->msgno);
++ }
++
++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt));
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0 && (errno == EACCES || errno == ENOENT)){
++ INIT (bs, mail_string, "", 0);
++ elt->rfc822_size = 0L;
++ return NIL;
++ }
++
++ s = maildir_text_work(stream, elt, &i, flags);
++ INIT (bs, mail_string, s, i);
++ return LONGT;
++ }
++
++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt,
++ unsigned long *length,long flags)
++ {
++ FDDATA d;
++ STRING bs;
++ char *s,tmp[CHUNK];
++ unsigned long msgno = elt->msgno;
++ static int try = 0;
++
++ if (length)
++ *length = 0L;
++ LOCAL->buf[0] = '\0';
++
++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt));
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0){ /* flag change? */
++ if (try < 5){
++ try++;
++ if (maildir_update_elt_maildirp(stream, msgno) > 0)
++ try = 0;
++ return maildir_text_work(stream, mail_elt(stream, msgno),length, flags);
++ }
++ try = 0;
++ return NULL;
++ }
++
++ lseek (LOCAL->fd, elt->private.msg.text.offset,L_SET);
++
++ if (flags & FT_INTERNAL) { /* initial data OK? */
++ if (elt->private.msg.text.text.size > LOCAL->buflen) {
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen =
++ elt->private.msg.text.text.size) + 1);
++ }
++ read (LOCAL->fd,LOCAL->buf,elt->private.msg.text.text.size);
++ LOCAL->buf[*length = elt->private.msg.text.text.size] = '\0';
++ }
++ else {
++ if (elt->rfc822_size > LOCAL->buflen) {
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = elt->rfc822_size) + 1);
++ }
++ d.fd = LOCAL->fd; /* yes, set up file descriptor */
++ d.pos = elt->private.msg.text.offset;
++ d.chunk = tmp; /* initial buffer chunk */
++ d.chunksize = CHUNK;
++ INIT (&bs,fd_string,&d,elt->private.msg.text.text.size);
++ for (s = LOCAL->buf; SIZE (&bs);) switch (CHR (&bs)) {
++ case '\r': /* carriage return seen */
++ *s++ = SNX (&bs); /* copy it and any succeeding LF */
++ if (SIZE (&bs) && (CHR (&bs) == '\n')) *s++ = SNX (&bs);
++ break;
++ case '\n':
++ *s++ = '\r'; /* insert a CR */
++ default:
++ *s++ = SNX (&bs); /* copy characters */
++ }
++ *s = '\0'; /* tie off buffer */
++ *length = s - (char *) LOCAL->buf; /* calculate length */
++ }
++ close(LOCAL->fd); LOCAL->fd = -1;
++ return LOCAL->buf;
++ }
++
++ /* maildir parse, fill the elt structure... well not all of it... */
++ unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno,
++ DirNamesType dirtype)
++ {
++ char *b, *s, *t, c;
++ char tmp[MAILTMPLEN];
++ struct stat sbuf;
++ unsigned long i, len;
++ int d, f, r, se, dt;
++ MESSAGECACHE *elt;
++
++ elt = mail_elt (stream,msgno);
++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype);
++ if(stat(tmp, &sbuf) == 0)
++ MDSIZE(elt) = sbuf.st_size;
++
++ maildir_get_date(stream, msgno);
++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&se, &dt);
++ elt->draft = d; elt->flagged = f; elt->answered = r; elt->seen = se;
++ elt->deleted = dt; elt->valid = T;
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd >= 0){
++ s = (char *) fs_get (MDSIZE(elt) + 1);
++ read (LOCAL->fd,s,MDSIZE(elt));
++ s[MDSIZE(elt)] = '\0';
++ t = s + strlen(s); /* make t point to the end of s */
++ for (i = 0L, b = s; b < t && !(i && (*b == '\n')); i = (*b++ == '\n'));
++ len = (*b ? ++b : b) - s;
++ elt->private.msg.header.text.size =
++ elt->private.msg.text.offset = len;
++ elt->private.msg.text.text.size = MDSIZE(elt) - len;
++ for (i = 0L, b = s, c = *b; b &&
++ ((c < '\016' && ((c == '\012' && ++i)
++ ||(c == '\015' && *(b+1) == '\012' && ++b && (i +=2))))
++ || b < t); i++, c= *++b);
++ elt->rfc822_size = i;
++ fs_give ((void **) &s);
++ close(LOCAL->fd); LOCAL->fd = -1;
++ }
++ return elt->rfc822_size;
++ }
++
++ int
++ maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno)
++ {
++ char tmp[MAILTMPLEN];
++ struct direct **names = NIL;
++ unsigned long i, nfiles, pos;
++ int d = 0, f = 0 , r = 0, s = 0, t = 0, in_list, scan_err;
++ MESSAGECACHE *elt;
++
++ MDFLD(tmp, LOCAL->dir, Cur);
++
++ maildir_scandir (tmp, &names, &nfiles, &scan_err, CCLIENT);
++
++ elt = mail_elt (stream,msgno);
++
++ in_list = nfiles > 0L
++ ? maildir_message_in_list(MDFILE(elt), names, 0L, nfiles - 1L, &pos)
++ : NIL;
++
++ if (in_list && pos >= 0L && pos < nfiles
++ && !strcmp(MDFILE(elt), names[pos]->d_name)){
++ in_list = NIL;
++ maildir_abort(stream);
++ }
++
++ if (in_list && pos >= 0L && pos < nfiles){
++ maildir_free_file_only((void **)&elt->private.spare.ptr);
++ MDFILE(elt) = cpystr(names[pos]->d_name);
++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&s, &t);
++ if (elt->draft != d || elt->flagged != f ||
++ elt->answered != r || elt->seen != s || elt->deleted != t){
++ elt->draft = d; elt->flagged = f; elt->answered = r;
++ elt->seen = s; elt->deleted = t;
++ MM_FLAGS(stream, msgno);
++ }
++ }
++ for (i = 0L; i < nfiles; i++)
++ fs_give((void **) &names[i]);
++ if (names)
++ fs_give((void **) &names);
++ return in_list ? 1 : -1;
++ }
++
++ /* Maildir fetch message header */
++
++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno,
++ unsigned long *length, long flags)
++ {
++ char tmp[MAILTMPLEN], *s;
++ MESSAGECACHE *elt;
++ static int try = 0;
++
++ if (length) *length = 0;
++ if (flags & FT_UID || !LOCAL) return ""; /* UID call "impossible" */
++ elt = mail_elt (stream,msgno);
++ if(elt->private.msg.header.text.size == 0)
++ maildir_parse_message(stream, msgno, MDLOC(elt));
++
++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt));
++ if (LOCAL->fd < 0)
++ LOCAL->fd = open (tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0 && errno == EACCES){
++ mm_log ("Message exists but can not be read. Envelope and body lost!",ERROR);
++ return NULL;
++ }
++
++ if (LOCAL->fd < 0){ /* flag change? */
++ if (try < 5){
++ try++;
++ if (maildir_update_elt_maildirp(stream, msgno) > 0)
++ try = 0;
++ return maildir_header(stream, msgno, length, flags);
++ }
++ try = 0;
++ return NULL;
++ }
++
++ if (flags & FT_INTERNAL){
++ if(elt->private.msg.header.text.size > LOCAL->buflen){
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen =
++ elt->private.msg.header.text.size) + 1);
++ }
++ read (LOCAL->fd, (void *)LOCAL->buf, elt->private.msg.header.text.size);
++ LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0';
++ }
++ else{
++ s = (char *) fs_get(elt->private.msg.header.text.size+1);
++ read (LOCAL->fd, (void *)s, elt->private.msg.header.text.size);
++ s[elt->private.msg.header.text.size] = '\0';
++ *length = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen,s,
++ elt->private.msg.header.text.size);
++ fs_give ((void **) &s);
++ }
++ elt->private.msg.text.offset = elt->private.msg.header.text.size;
++ elt->private.msg.text.text.size = MDSIZE(elt) - elt->private.msg.text.offset;
++ close(LOCAL->fd); LOCAL->fd = -1;
++ return LOCAL->buf;
++ }
++
++ /* Maildir find list of subscribed mailboxes
++ * Accepts: mail stream
++ * pattern to search
++ */
++
++ void maildir_list (MAILSTREAM *stream,char *ref, char *pat)
++ {
++ char *s,test[MAILTMPLEN],file[MAILTMPLEN];
++ long i = 0L;
++
++ if((!pat || !*pat) && maildir_canonicalize (test,ref,"*")
++ && maildir_valid_name(test)){ /* there is a #md/ leading here */
++ for (i = 3L; test[i] && test[i] != '/'; i++);
++ if ((s = strchr (test+i+1,'/')) != NULL) *++s = '\0';
++ else test[0] = '\0';
++ mm_list (stream,'/',test, LATT_NOSELECT);
++ }
++ else if (maildir_canonicalize (test,ref,pat)) {
++ if (test[3] == '/') { /* looking down levels? */
++ /* yes, found any wildcards? */
++ if ((s = strpbrk (test,"%*")) != NULL){
++ /* yes, copy name up to that point */
++ strncpy (file,test+4,i = s - (test+4));
++ file[i] = '\0'; /* tie off */
++ }
++ else strcpy (file,test+4);/* use just that name then */
++ /* find directory name */
++ if ((s = strrchr (file, '/')) != NULL){
++ *s = '\0'; /* found, tie off at that point */
++ s = file;
++ }
++ /* do the work */
++ if(IS_COURIER(test))
++ courier_list_work (stream,s,test,0);
++ else
++ maildir_list_work (stream,s,test,0);
++ }
++ /* always an INBOX */
++ if (!compare_cstring (test,"#MD/INBOX"))
++ mm_list (stream,NIL,"#MD/INBOX",LATT_NOINFERIORS);
++ if (!compare_cstring (test,"#MC/INBOX"))
++ mm_list (stream,NIL,"#MC/INBOX",LATT_NOINFERIORS);
++ }
++ }
++
++ void courier_list (MAILSTREAM *stream,char *ref, char *pat)
++ {
++ /* I am too lazy to do anything. Do you care to ask maildir list, please?
++ The real reason why this is a dummy function is because we do not want to
++ see the same folder listed twice.
++ */
++ }
++
++ /* For those that want to hide things, we give them a chance to do so */
++ void *maildir_parameters (long function, void *value)
++ {
++ void *ret = NIL;
++ switch ((int) function) {
++ case SET_MDINBOXPATH:
++ if(strlen((char *) value ) > 49)
++ strcpy(myMdInboxDir, "Maildir");
++ else
++ strcpy(myMdInboxDir, (char *) value);
++ case GET_MDINBOXPATH:
++ if (myMdInboxDir[0] == '\0') strcpy(myMdInboxDir,"Maildir");
++ ret = (void *) myMdInboxDir;
++ break;
++ case SET_COURIERSTYLE:
++ CourierStyle = (long) value;
++ case GET_COURIERSTYLE:
++ ret = (void *) CourierStyle;
++ break;
++ case GET_DIRFMTTEST:
++ ret = (void *) maildir_dirfmttest;
++ break;
++ default:
++ break;
++ }
++ return ret;
++ }
++
++ int maildir_create_folder(char *mailbox)
++ {
++ char tmp[MAILTMPLEN], err[MAILTMPLEN];
++ int i;
++
++ for (i = Cur; i != EndDir; i++){
++ MDFLD(tmp, mailbox, i);
++ if (mkdir(tmp, 0700) && errno != EEXIST){ /* try to make new dir */
++ sprintf (err, "Can't create %s: %s", tmp, strerror(errno));
++ mm_log (err,ERROR);
++ return NIL;
++ }
++ }
++ return T;
++ }
++
++ int maildir_create_work(char *mailbox, int loop)
++ {
++ char *s, c, err[MAILTMPLEN], tmp[MAILTMPLEN], tmp2[MAILTMPLEN], mbx[MAILTMPLEN];
++ int fnlen, create_dir = 0, courier, mv;
++ struct stat sbuf;
++ long style = (long) maildir_parameters(GET_COURIERSTYLE, NIL);
++
++ courier = IS_COURIER(mailbox);
++ strcpy(mbx, mailbox);
++ mv = maildir_valid(mbx) ? 1 : 0;
++ maildir_file_path(mailbox, tmp);
++ if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){
++ create_dir++;
++ mailbox[strlen(mailbox) - 1] = '\0';
++ }
++
++ if(!loop && courier){
++ if(mv){
++ if(create_dir){
++ if(style == CCLIENT)
++ strcpy (err,"Can not create directory: folder exists. Create subfolder");
++ else
++ strcpy(err,"Folder and Directory already exist");
++ }
++ else
++ strcpy (err, "Can't create mailbox: mailbox already exists");
++ }
++ else{
++ if(create_dir)
++ strcpy(err, "Can not create directory. Cread folder instead");
++ else
++ err[0] = '\0';
++ }
++ if(err[0]){
++ mm_log (err,ERROR);
++ return NIL;
++ }
++ }
++
++ fnlen = strlen(tmp);
++ if ((s = strrchr(mailbox,MDSEPARATOR(courier))) != NULL){
++ c = *++s;
++ *s = '\0';
++ if ((stat(tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&
++ !maildir_create_work (mailbox, ++loop))
++ return NIL;
++ *s = c;
++ }
++ tmp[fnlen] = '\0';
++
++ if (mkdir(tmp,0700) && errno != EEXIST)
++ return NIL;
++
++ if (create_dir)
++ mailbox[fnlen] = '/';
++
++ if (create_dir){
++ if(style == CCLIENT){
++ if(!courier){
++ FILE *fp = NULL;
++ sprintf(tmp2,"%s%s", tmp, MDDIR);
++ if ((fp = fopen(tmp2,"w")) == NULL){
++ sprintf (err,"Problem creating %s: %s", tmp2, strerror(errno));
++ mm_log (err,ERROR);
++ return NIL;
++ }
++ fclose(fp);
++ }
++ }
++ return T;
++ }
++ else
++ return maildir_create_folder(tmp);
++ }
++
++ long maildir_create (MAILSTREAM *stream,char *mailbox)
++ {
++ char tmp[MAILTMPLEN], err[MAILTMPLEN];
++ int rv, create_dir;
++
++ create_dir = mailbox ?
++ (mailbox[strlen(mailbox) - 1] ==
++ MDSEPARATOR(IS_COURIER(mailbox))) : 0;
++ maildir_file_path(mailbox, tmp);
++ strcpy(tmp, mailbox);
++ rv = maildir_create_work(mailbox, 0);
++ strcpy(mailbox, tmp);
++ if (rv == 0){
++ sprintf (err,"Can't create %s %s",
++ (create_dir ? "directory" : "mailbox"), mailbox);
++ mm_log (err,ERROR);
++ }
++ return rv ? LONGT : NIL;
++ }
++
++ #define MAXTRY 10000
++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt)
++ {
++ char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN];
++ char *s;
++ int ren, try = 0;
++
++ if (elt->valid){
++ for (try = 1; try > 0 && try < MAXTRY; try++){
++ /* build the new filename */
++ sprintf (oldfile,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ fn[0] = '\0';
++ if ((ren = maildir_message_exists(stream, MDFILE(elt), fn)) == 0){
++ errno = ENOENT;
++ try = MAXTRY;
++ }
++ if (*fn) /* new oldfile! */
++ sprintf (oldfile,"%s/%s",LOCAL->curdir,fn);
++ if ((s = strrchr (MDFILE(elt), FLAGSEP))) *s = '\0';
++ sprintf (fn,"%s%s%s%s%s%s%s", MDFILE(elt), MDSEP(2),
++ MDFLAG(Draft, elt->draft), MDFLAG(Flagged, elt->flagged),
++ MDFLAG(Replied, elt->answered), MDFLAG(Seen, elt->seen),
++ MDFLAG(Trashed, elt->deleted));
++ sprintf (newfile,"%s/%s",LOCAL->curdir,fn);
++ if (ren != 0 && rename (oldfile,newfile) >= 0)
++ try = -1;
++ }
++
++ if (try > 0){
++ sprintf(oldfile,"Unable to write flags to disk: %s",
++ (errno == ENOENT) ? "message is gone!" : strerror (errno));
++ mm_log(oldfile,ERROR);
++ return;
++ }
++ #ifdef __CYGWIN__
++ utime(LOCAL->curdir, NIL); /* make sure next scan will catch the change */
++ #endif
++ maildir_free_file_only ((void **) &elt->private.spare.ptr);
++ MDFILE(elt) = cpystr (fn);
++ }
++ }
++
++ long maildir_expunge (MAILSTREAM *stream, char *sequence, long options)
++ {
++ long ret;
++ MESSAGECACHE *elt;
++ unsigned long i, n = 0L;
++ unsigned long recent = stream->recent;
++ char tmp[MAILTMPLEN];
++
++ mm_critical (stream); /* go critical */
++ ret = sequence ? ((options & EX_UID) ?
++ mail_uid_sequence (stream,sequence) :
++ mail_sequence (stream,sequence)) : LONGT;
++ if(ret == 0L)
++ return 0L;
++ for (i = 1L; i <= stream->nmsgs;){
++ elt = mail_elt (stream,i);
++ if (elt->deleted && (sequence ? elt->sequence : T)){
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (unlink (tmp) < 0) {/* try to delete the message */
++ sprintf (tmp,"Expunge of message %ld failed, aborted: %s",i,
++ strerror (errno));
++ if (!stream->silent)
++ mm_log (tmp,WARN);
++ break;
++ }
++ if (elt->private.spare.ptr)
++ maildir_free_file ((void **) &elt->private.spare.ptr);
++ if (elt->recent) --recent;/* if recent, note one less recent message */
++ mail_expunged (stream,i); /* notify upper levels */
++ n++; /* count up one more expunged message */
++ }
++ else i++;
++ }
++ if(n){ /* output the news if any expunged */
++ sprintf (tmp,"Expunged %ld messages",n);
++ if (!stream->silent)
++ mm_log (tmp,(long) NIL);
++ }
++ else
++ if (!stream->silent)
++ mm_log ("No messages deleted, so no update needed",(long) NIL);
++ mm_nocritical (stream); /* release critical */
++ /* notify upper level of new mailbox size */
++ mail_exists (stream,stream->nmsgs);
++ mail_recent (stream,recent);
++ return ret;
++ }
++
++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
++ {
++ STRING st;
++ MESSAGECACHE *elt;
++ unsigned long len;
++ int fd;
++ unsigned long i;
++ struct stat sbuf;
++ char tmp[MAILTMPLEN], flags[MAILTMPLEN], path[MAILTMPLEN], *s;
++ /* copy the messages */
++ if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) :
++ mail_sequence (stream,sequence))
++ for (i = 1L; i <= stream->nmsgs; i++)
++ if ((elt = mail_elt (stream,i))->sequence){
++ MSGPATH(path, LOCAL->dir, MDFILE(elt), MDLOC(elt));
++ if (((fd = open (path,O_RDONLY,NIL)) < 0)
++ ||((!elt->rfc822_size &&
++ ((stat(path, &sbuf) < 0) || !S_ISREG (sbuf.st_mode)))))
++ return NIL;
++ if(!elt->rfc822_size)
++ MDSIZE(elt) = sbuf.st_size;
++ s = (char *) fs_get(MDSIZE(elt) + 1);
++ read (fd,s,MDSIZE(elt));
++ s[MDSIZE(elt)] = '\0';
++ close (fd);
++ len = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen, s, MDSIZE(elt));
++ INIT (&st,mail_string, LOCAL->buf, len);
++ elt->rfc822_size = len;
++ fs_give ((void **)&s);
++
++ flags[0] = flags[1] = '\0';
++ if (elt->seen) strcat (flags," \\Seen");
++ if (elt->draft) strcat (flags," \\Draft");
++ if (elt->deleted) strcat (flags," \\Deleted");
++ if (elt->flagged) strcat (flags," \\Flagged");
++ if (elt->answered) strcat (flags," \\Answered");
++ flags[0] = '('; /* open list */
++ strcat (flags,")"); /* close list */
++ mail_date (tmp,elt); /* generate internal date */
++ if (!mail_append_full (NIL,mailbox,flags,tmp,&st))
++ return NIL;
++ if (options & CP_MOVE) elt->deleted = T;
++ }
++ return LONGT; /* return success */
++ }
++
++ long maildir_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
++ {
++ int fd, k;
++ STRING *message;
++ char c,*s, *flags, *date;
++ char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
++ MESSAGECACHE elt;
++ long i, size = 0L, ret = LONGT, f;
++ unsigned long uf, ti;
++ static unsigned int transact = 0;
++
++ if (!maildir_valid(mailbox)) {
++ sprintf (tmp,"Not a valid Maildir mailbox: %s",mailbox);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ if (!*mdlocaldomain)
++ md_domain_name(); /* get domain name for maildir files in mdlocaldomain now! */
++
++ if (mypid == (pid_t) 0)
++ mypid = getpid();
++
++ if (!stream){
++ stream = &maildirproto;
++
++ for (k = 0; k < NUSERFLAGS && stream->user_flags[k]; ++k)
++ fs_give ((void **) &stream->user_flags[k]);
++ }
++
++ if (!(*af) (stream,data,&flags,&date,&message)) return NIL;
++
++ mm_critical (stream); /* go critical */
++ /* call time(0) only once, use transact to distinguish instead */
++ ti = time(0);
++ do {
++ if (!SIZE (message)) { /* guard against zero-length */
++ mm_log ("Append of zero-length message",ERROR);
++ ret = NIL;
++ break;
++ }
++ if (date && !mail_parse_date(&elt,date)){
++ sprintf (tmp,"Bad date in append: %.80s",date);
++ mm_log (tmp,ERROR);
++ ret = NIL;
++ break;
++ }
++ f = mail_parse_flags (stream,flags,&uf);
++ /* build file name we will use */
++ sprintf (file,"%lu.%d_%09u.%s%s%s%s%s%s",
++ ti, mypid, transact++, mdlocaldomain, (f ? MDSEP(2) : ""),
++ MDFLAG(Draft, f&fDRAFT), MDFLAG(Flagged, f&fFLAGGED),
++ MDFLAG(Replied, f&fANSWERED), MDFLAG(Seen, f&fSEEN));
++ /* build tmp file name */
++ if (maildir_file_path(mailbox, tmp))
++ MSGPATH(path1, tmp, file, Tmp);
++
++ if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
++ sprintf (tmp, "Can't open append mailbox: %s", strerror (errno));
++ mm_log (tmp, ERROR);
++ return NIL;
++ }
++ for (size = 0,i = SIZE (message),s = (char *) fs_get (i + 1); i; --i)
++ if ((c = SNX (message)) != '\015') s[size++] = c;
++ if ((write (fd, s, size) < 0) || fsync (fd)) {
++ unlink (path1); /* delete message */
++ sprintf (tmp, "Message append failed: %s", strerror (errno));
++ mm_log (tmp, ERROR);
++ ret = NIL;
++ }
++ fs_give ((void **) &s); /* flush the buffer */
++ close (fd); /* close the file */
++ /* build final filename to use */
++ if (maildir_file_path(mailbox, tmp))
++ MSGPATH(path2, tmp, file, New);
++ if (rename (path1,path2) < 0) {
++ sprintf (tmp, "Message append failed: %s", strerror (errno));
++ mm_log (tmp, ERROR);
++ ret = NIL;
++ }
++ unlink (path1);
++
++ if (ret)
++ if (!(*af) (stream,data,&flags,&date,&message)) ret = NIL;
++
++ } while (ret && message); /* write the data */
++ mm_nocritical (stream); /* release critical */
++ return ret;
++ }
++
++ long maildir_delete (MAILSTREAM *stream,char *mailbox)
++ {
++ DIR *dirp;
++ struct direct *d;
++ int i, remove_dir = 0, mddir = 0, rv, error = 0;
++ char tmp[MAILTMPLEN],tmp2[MAILTMPLEN], realname[MAILTMPLEN];
++ struct stat sbuf;
++ int courier = IS_COURIER(mailbox);
++
++ if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){
++ remove_dir++;
++ mailbox[strlen(mailbox) -1] = '\0';
++ }
++
++ if (!maildir_valid(mailbox)){
++ maildir_file_path(mailbox, tmp);
++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)){
++ sprintf(tmp,"Can not remove %s", mailbox);
++ error++;
++ }
++ }
++
++ if (!error && remove_dir && !maildir_dir_is_empty(mailbox)){
++ sprintf(tmp,"Can not remove directory %s/: directory not empty", mailbox);
++ error++;
++ }
++
++ if(error){
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ maildir_close(stream,0); /* even if stream was NULL */
++
++ maildir_file_path(mailbox, realname);
++
++ if (remove_dir){
++ sprintf(tmp,"%s/%s", realname, MDDIR);
++ if ((rv = stat (tmp,&sbuf)) == 0 && S_ISREG(sbuf.st_mode))
++ rv = unlink(tmp);
++ else if (errno == ENOENT)
++ rv = 0;
++ if (rv != 0){
++ sprintf(tmp,"Can not remove %s/%s: %s", tmp2, MDDIR, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ if (!maildir_valid(realname) && rmdir(realname) != 0){
++ sprintf(tmp,"Can not remove %s/: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return LONGT;
++ }
++ /* else remove just the folder. Remove all hidden files, except MDDIR */
++ for (i = Cur; i != EndDir; i++){
++ MDFLD(tmp, realname, i);
++
++ if (!(dirp = opendir (tmp))){
++ sprintf(tmp,"Can not read %s/: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ while ((d = readdir(dirp)) != NULL){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")){
++ sprintf(tmp2,"%s/%s", tmp, d->d_name);
++ if (unlink(tmp2) != 0){
++ sprintf(tmp2,"Can not remove %s: %s", mailbox, strerror(errno));
++ mm_log (tmp2,ERROR);
++ return NIL;
++ }
++ }
++ }
++ closedir(dirp);
++ if (rmdir(tmp) != 0){
++ sprintf(tmp,"Can not remove %s: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ }
++ /*
++ * ok we have removed all subdirectories of the folder mailbox, Remove the
++ * hidden files.
++ */
++
++ if(!(dirp = opendir (realname))){
++ sprintf(tmp,"Can not read %s/: %s", realname, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ while ((d = readdir(dirp)) != NULL){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && (!strcmp(d->d_name, MDDIR)
++ || !strncmp(d->d_name, MDUIDLAST, strlen(MDUIDLAST))
++ || !strncmp(d->d_name, MDUIDTEMP, strlen(MDUIDTEMP)))){
++ if(strcmp(d->d_name, MDDIR) == 0)
++ mddir++;
++ sprintf(tmp,"%s/%s", realname, d->d_name);
++ if (unlink(tmp) != 0)
++ error++;
++ }
++ }
++ closedir(dirp);
++ if (error ||
++ (maildir_dir_is_empty(mailbox) && mddir == 0 && rmdir(realname) < 0)){
++ sprintf(tmp,"Can not remove folder %s: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return LONGT;
++ }
++
++ long maildir_rename (MAILSTREAM *stream, char *old, char *new)
++ {
++ char tmp[MAILTMPLEN],tmpnew[MAILTMPLEN], realold[MAILTMPLEN];
++ char realnew[MAILTMPLEN];
++ int courier = IS_COURIER(old) && IS_COURIER(new);
++ int i;
++ long rv = LONGT;
++ COURIER_S *cdir;
++
++ if((IS_COURIER(old) || IS_COURIER(new)) && !courier){
++ sprintf (tmp,"Can't rename mailbox %s to %s",old, new);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ if (!maildir_valid(old)){
++ sprintf (tmp,"Can't rename mailbox %s: folder not in maildir format",old);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ maildir_file_path(old, realold);
++ if (!maildir_valid_name(new) && new[0] == '#'){
++ sprintf (tmp,"Can't rename mailbox %s: folder not in maildir format",new);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ maildir_file_path(new, realnew);
++ if (access(tmpnew,F_OK) == 0){ /* new mailbox name must not exist */
++ sprintf (tmp,"Can't rename to mailbox %s: destination already exists",new);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ if(!courier){
++ if (rename (realold,realnew)){ /* try to rename the directory */
++ sprintf (tmp,"Can't rename mailbox %s to %s: %s",old, new,
++ strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return LONGT; /* return success */
++ }
++
++ cdir = courier_list_dir(old);
++ for (i = 0; cdir && i < cdir->total; i++){
++ if(strstr(cdir->data[i]->name, old)){
++ sprintf(tmp,"%s%s", new, cdir->data[i]->name+strlen(old));
++ maildir_file_path(cdir->data[i]->name, realold);
++ maildir_file_path(tmp, realnew);
++ if (rename (realold,realnew)){
++ sprintf (tmp,"Can't rename mailbox %s to %s: %s",old, new,
++ strerror(errno));
++ mm_log (tmp,ERROR);
++ rv = NIL;
++ }
++ }
++ }
++ courier_free_cdir(&cdir);
++ return rv;
++ }
++
++ long maildir_sub (MAILSTREAM *stream,char *mailbox)
++ {
++ return sm_subscribe (mailbox);
++ }
++
++ long maildir_unsub (MAILSTREAM *stream,char *mailbox)
++ {
++ return sm_unsubscribe (mailbox);
++ }
++
++ void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat)
++ {
++ void *sdb = NIL;
++ char *s, test[MAILTMPLEN];
++ /* get canonical form of name */
++ if (maildir_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) {
++ do if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL);
++ while ((s = sm_read (&sdb)) != NULL); /* until no more subscriptions */
++ }
++ }
++
++ long maildir_canonicalize (char *pattern,char *ref,char *pat)
++ {
++ if (ref && *ref) { /* have a reference */
++ strcpy (pattern,ref); /* copy reference to pattern */
++ /* # overrides mailbox field in reference */
++ if (*pat == '#') strcpy (pattern,pat);
++ /* pattern starts, reference ends, with / */
++ else if ((*pat == '/') && (pattern[strlen (pattern) - 1] == '/'))
++ strcat (pattern,pat + 1); /* append, omitting one of the period */
++
++ else strcat (pattern,pat); /* anything else is just appended */
++ }
++ else strcpy (pattern,pat); /* just have basic name */
++ return maildir_valid_name(pattern) ? LONGT : NIL;
++ }
++
++ void maildir_list_work (MAILSTREAM *stream,char *dir,char *pat,long level)
++ {
++ DIR *dp;
++ struct direct *d;
++ struct stat sbuf;
++ char curdir[MAILTMPLEN],name[MAILTMPLEN], tmp[MAILTMPLEN];
++ char realpat[MAILTMPLEN];
++ long i;
++ char *maildirpath = mdirpath();
++
++ sprintf(curdir,"%s/%s/", myrootdir(pat), dir ? dir : maildirpath);
++ if ((dp = opendir (curdir)) != NULL){
++ if (dir) sprintf (name,"%s%s/",MDPREFIX(CCLIENT),dir);
++ else strcpy (name, pat);
++
++ if (level == 0 && !strpbrk(pat,"%*")){
++ if(maildir_valid(pat)){
++ i = maildir_contains_folder(pat, NULL)
++ ? LATT_HASCHILDREN
++ : (maildir_is_dir(pat, NULL)
++ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS);
++ maildir_file_path(pat, realpat);
++ i += maildir_any_new_msgs(realpat)
++ ? LATT_MARKED : LATT_UNMARKED;
++ mm_list (stream,'/', pat, i);
++ }
++ else
++ if(pat[strlen(pat) - 1] == '/')
++ mm_list (stream,'/', pat, LATT_NOSELECT);
++ }
++
++ while ((d = readdir (dp)) != NULL)
++ if(strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))){
++
++ if (dir) sprintf (tmp,"%s%s", name,d->d_name);
++ else strcpy(tmp, d->d_name);
++
++ if(pmatch_full (tmp, pat,'/')){
++ sprintf(tmp,"%s/%s/%s", myrootdir(d->d_name),
++ (dir ? dir : maildirpath), d->d_name);
++ if(stat (tmp,&sbuf) == 0
++ && ((sbuf.st_mode & S_IFMT) == S_IFDIR)){
++ if (dir) sprintf (tmp,"%s%s", name,d->d_name);
++ else strcpy(tmp, d->d_name);
++ i = maildir_valid(tmp)
++ ? (maildir_contains_folder(dir, d->d_name)
++ ? LATT_HASCHILDREN
++ : (maildir_is_dir(dir, d->d_name)
++ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS))
++ : LATT_NOSELECT;
++ i += maildir_any_new_msgs(tmp)
++ ? LATT_MARKED : LATT_UNMARKED;
++ mm_list (stream,'/',tmp, i);
++ strcat (tmp, "/");
++ if(dmatch (tmp, pat,'/') &&
++ (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))){
++ sprintf(tmp,"%s/%s",dir,d->d_name);
++ maildir_list_work (stream,tmp,pat,level+1);
++ }
++ }
++ }
++ }
++ closedir (dp);
++ }
++ }
++
++ void courier_list_work (MAILSTREAM *stream, char *dir, char *pat, long level)
++ {
++ char c, curdir[MAILTMPLEN], tmp[MAILTMPLEN];
++ char realname[MAILTMPLEN], realpat[MAILTMPLEN] = {'\0'};
++ int i, found;
++ long style = (long) maildir_parameters(GET_COURIERSTYLE, NIL), j;
++ char *maildirpath = mdirpath();
++ COURIER_S *cdir;
++
++ if(!strpbrk(pat,"%*")){ /* a mailbox */
++ maildir_file_path(pat, curdir);
++ i = strlen(curdir) - 1;
++ if(curdir[i] == '/')
++ curdir[i] = '\0';
++ cdir = courier_list_dir(curdir);
++ if(cdir){
++ found = 0; j = 0L;
++ if(maildir_valid_name(pat)){
++ for(i = 0; !found && i < cdir->total; i++)
++ if(strstr(curdir, cdir->data[i]->name)){
++ if(strlen(curdir) < strlen(cdir->data[i]->name))
++ found += 2;
++ else if(strlen(curdir) == strlen(cdir->data[i]->name))
++ found -= 1;
++ }
++ if(found > 0)
++ j = LATT_HASCHILDREN;
++ else if(found == 0)
++ j = (style == COURIER) ? LATT_HASNOCHILDREN : LATT_NOINFERIORS;
++ }
++ else
++ j = LATT_NOSELECT;
++ j += maildir_any_new_msgs(curdir) ? LATT_MARKED : LATT_UNMARKED;
++ if (found)
++ mm_list (stream, '.', pat, j);
++ courier_free_cdir(&cdir);
++ }
++ return;
++ }
++
++ strcpy(tmp,pat + 4); /* a directory */
++ j = strlen(pat) - 1;
++ maildir_file_path(pat, realpat);
++ c = pat[j];
++ pat[j] = '\0';
++ realname[0] = '\0';
++ if(dir)
++ maildir_file_path(dir, realname);
++ sprintf(curdir,"%s%s%s/%s", (dir ? "" : myrootdir(pat)), (dir ? "" : "/"),
++ (dir ? realname : maildirpath), (dir ? "" : "."));
++ sprintf(tmp, "%s%s/.", MDPREFIX(COURIER), dir ? dir : maildirpath);
++ if (level == 0 && tmp && pmatch_full (tmp, realpat, '.'))
++ mm_list (stream,'.', tmp, LATT_NOSELECT);
++
++ cdir = courier_list_dir(pat);
++ pat[j] = c;
++ for (i = 0; cdir && i < cdir->total; i++)
++ if(pmatch_full (cdir->data[i]->name, pat, '.')){
++ sprintf(tmp, "%s.", cdir->data[i]->name);
++ courier_list_info(&cdir, tmp, i);
++ mm_list (stream,'.',cdir->data[i]->name, cdir->data[i]->attribute);
++ }
++ courier_free_cdir(&cdir);
++ }
++
++ int
++ same_maildir_file(char *name1, char *name2)
++ {
++ char tmp1[MAILTMPLEN], tmp2[MAILTMPLEN];
++ char *s;
++
++ strcpy(tmp1, name1 ? name1 : "");
++ strcpy(tmp2, name2 ? name2 : "");
++ if ((s = strrchr(tmp1, FLAGSEP)) != NULL)
++ *s = '\0';
++ if (((s = strrchr(tmp1, SIZESEP)) != NULL) && (strchr(s,'.') == NULL))
++ *s = '\0';
++ if ((s = strrchr(tmp2, FLAGSEP)) != NULL)
++ *s = '\0';
++ if (((s = strrchr(tmp2, SIZESEP)) != NULL) && (strchr(s,'.') == NULL))
++ *s = '\0';
++
++ return !strcmp(tmp1, tmp2);
++ }
++
++ unsigned long antoul(char *seed)
++ {
++ int i, error = 0;
++ unsigned long val = 0L, rv1 = 0L, t;
++ char c, *p;
++ if(!seed)
++ return 0L;
++ t = strtoul(seed, &p, 10);
++ if(p && (*p == '.' || *p == '_'))
++ return t;
++ /* else */
++ if((p = strchr(seed,'.')) != NULL)
++ *p = '\0';
++ error = (strlen(seed) > 6); /* too long */
++ for(i= strlen(seed)-1; error == 0 && i >= 0; i--){
++ c = seed[i];
++ if (c >= 'A' && c <= 'Z') val = c - 'A';
++ else if (c >= 'a' && c <= 'z') val = c - 'a' + 26;
++ else if (c >= '0' && c <= '9') val = c - '0' + 26 + 26;
++ else if (c == '-') val = c - '-' + 26 + 26 + 10;
++ else if (c == '_') val = c - '_' + 26 + 26 + 10 + 1;
++ else error++;
++ rv1 = val + (rv1 << 6);
++ }
++ if(p)
++ *p = '.';
++ return error ? 0L : rv1;
++ }
++
++ unsigned long mdfntoul (char *name)
++ {
++ unsigned long t;
++ char *r, last;
++
++ if((*name == '_') && ((r = strpbrk(name,".,%+")) != NULL)){ /* Grrr!!! */
++ last = *r;
++ *r = '\0';
++ t = antoul(r+1);
++ *r = last;
++ }
++ else
++ t = antoul(name);
++ return t;
++ }
++
++ int comp_maildir_file(char *name1, char *name2)
++ {
++ int uset1 = 1, uset2 = 1, i, j, cmp;
++ unsigned long t1, t2;
++ char *s1, *s2;
++
++ if (!(name1 && *name1))
++ return (name2 && *name2) ? (*name2 == FLAGSEP ? 0 : -1) : 0;
++
++ if (!(name2 && *name2))
++ return (name1 && *name1) ? (*name1 == FLAGSEP ? 0 : 1) : 0;
++
++ if((cmp = strcmp(name1,name2)) == 0)
++ return 0;
++
++ t1 = strtoul(name1, &s1, 10);
++ t2 = strtoul(name2, &s2, 10);
++
++ if(!s1 || *s1 != '.')
++ uset1 = 0;
++
++ if(!s2 || *s2 != '.')
++ uset2 = 0;
++
++ if(uset1 && uset2) /* normal sort order */
++ return (t1 < t2) ? -1 : (t1 > t2 ? 1 : (cmp < 0 ? -1 : 1));
++
++ /* If we make it here we say Grrrr.... first, then we try to figure out
++ * how to sort this mess.
++ * These are the rules.
++ * If there is a number at the beginning it is bigger than anything else.
++ * If there are digits, then the number of digits decides which one is bigger.
++ */
++
++ for(i = 0; isdigit(name1[i]); i++);
++ for(j = 0; isdigit(name2[j]); j++);
++
++ return(uset1 ? 1
++ : (uset2 ? -1
++ : (i < j ? -1 : (i > j ? 1 : (cmp < 0 ? -1 : 1)))));
++ }
++
++ void
++ maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t)
++ {
++ char tmp[MAILTMPLEN], *b;
++ int offset = 0;
++ int tmpd, tmpf, tmpr, tmps, tmpt;
++
++ if(d) *d = 0;
++ if(f) *f = 0;
++ if(r) *r = 0;
++ if(s) *s = 0;
++ if(t) *t = 0;
++
++ tmpd = tmpf = tmpr = tmps = tmpt = NIL; /* no flags set by default */
++ strcpy(tmp,name);
++ while ((b = strrchr(tmp+offset, FLAGSEP)) != NULL){
++ char flag,last;
++ int k;
++ if (!++b) break;
++ switch (*b){
++ case '1':
++ case '2':
++ case '3': flag = *b; b += 2;
++ for (k = 0; b[k] && b[k] != FLAGSEP && b[k] != ','; k++);
++ last = b[k];
++ b[k] = '\0';
++ if (flag == '2' || flag == '3'){
++ tmpd = strchr (b, MDFLAGC(Draft)) ? T : NIL;
++ tmpf = strchr (b, MDFLAGC(Flagged)) ? T : NIL;
++ tmpr = strchr (b, MDFLAGC(Replied)) ? T : NIL;
++ tmps = strchr (b, MDFLAGC(Seen)) ? T : NIL;
++ tmpt = strchr (b, MDFLAGC(Trashed)) ? T : NIL;
++ }
++ b[k] = last;
++ b += k;
++ for (; tmp[offset] && tmp[offset] != FLAGSEP; offset++);
++ offset++;
++ break;
++ default: break; /* Should we crash?... Nahhh */
++ }
++ }
++ if(d) *d = tmpd;
++ if(f) *f = tmpf;
++ if(r) *r = tmpr;
++ if(s) *s = tmps;
++ if(t) *t = tmpt;
++ }
++
++ int
++ maildir_message_in_list(char *msgname, struct direct **names,
++ unsigned long bottom, unsigned long top, unsigned long *pos)
++ {
++ unsigned long middle = (bottom + top)/2;
++ int test;
++
++ if (!msgname)
++ return NIL;
++
++ if (pos) *pos = middle;
++
++ if (same_maildir_file(msgname, names[middle]->d_name))
++ return T;
++
++ if (middle == bottom){ /* 0 <= 0 < 1 */
++ int rv = NIL;
++ if (same_maildir_file(msgname, names[middle]->d_name)){
++ rv = T;
++ if (pos) *pos = middle;
++ }
++ else
++ if (same_maildir_file(msgname, names[top]->d_name)){
++ rv = T;
++ if (pos) *pos = top;
++ }
++ return rv;
++ }
++
++ test = comp_maildir_file(msgname, names[middle]->d_name);
++
++ if (top <= bottom)
++ return test ? NIL : T;
++
++ if (test < 0 ) /* bottom < msgname < middle */
++ return maildir_message_in_list(msgname, names, bottom, middle, pos);
++ else if (test > 0) /* middle < msgname < top */
++ return maildir_message_in_list(msgname, names, middle, top, pos);
++ else return T;
++ }
++
++ void
++ maildir_abort(MAILSTREAM *stream)
++ {
++ if (LOCAL){
++ if(LOCAL->candouid)
++ maildir_read_uid(stream, NULL, &stream->uid_validity);
++ if (LOCAL->dir) fs_give ((void **) &LOCAL->dir);
++ if (LOCAL->curdir) fs_give ((void **) &LOCAL->curdir);
++ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);
++ if(LOCAL->uidtempfile){
++ unlink(LOCAL->uidtempfile);
++ fs_give ((void **) &LOCAL->uidtempfile);
++ }
++ fs_give ((void **) &stream->local);
++ }
++ if (mdfpath) fs_give((void **)&mdfpath);
++ stream->dtb = NIL;
++ }
++
++ int
++ maildir_contains_folder(char *dirname, char *name)
++ {
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN];
++ int rv = 0;
++ DIR *dir;
++ struct direct *d;
++
++ maildir_file_path(dirname, tmp2);
++ if(name){
++ strcat(tmp2,"/");
++ strcat(tmp2, name);
++ }
++
++ if (!(dir = opendir (tmp2)))
++ return NIL;
++
++ while ((d = readdir(dir)) != NULL){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))){
++
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if(maildir_valid(tmp)){
++ rv++;
++ break;
++ }
++ }
++ }
++ closedir(dir);
++ return rv;
++ }
++
++ int
++ maildir_is_dir(char *dirname, char *name)
++ {
++ char tmp[MAILTMPLEN];
++ struct stat sbuf;
++
++ maildir_file_path(dirname, tmp);
++ if(name){
++ strcat(tmp,"/");
++ strcat(tmp,name);
++ }
++ strcat(tmp,"/");
++ strcat(tmp,MDDIR);
++
++ return ((stat(tmp, &sbuf) == 0) && S_ISREG (sbuf.st_mode)) ? 1 : 0;
++ }
++
++ int
++ maildir_dir_is_empty(char *mailbox)
++ {
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], tmp3[MAILTMPLEN],*s;
++ int rv = 1, courier = IS_COURIER(mailbox);
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++
++ maildir_file_path(mailbox, tmp2);
++
++ if(courier){
++ strcpy(tmp3, tmp2);
++ if(s = strrchr(tmp2, '/'))
++ *s = '\0';
++ }
++
++ if (!(dir = opendir (tmp2)))
++ return rv;
++
++ if(courier){
++ while((d = readdir(dir)) != NULL){
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if(!strncmp(tmp, tmp3, strlen(tmp3))
++ && tmp[strlen(tmp3)] == '.'){
++ rv = 0;
++ break;
++ }
++ }
++ }
++ else
++ while ((d = readdir(dir)) != NULL){
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if (strcmp(d->d_name, ".")
++ && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))
++ && strcmp(d->d_name, MDDIR)
++ && strcmp(d->d_name, MDUIDVALIDITY)
++ && !(d->d_name[0] == '.'
++ && stat (tmp,&sbuf) == 0
++ && S_ISREG(sbuf.st_mode))){
++ rv = 0;
++ break;
++ }
++ }
++ closedir(dir);
++ return rv;
++ }
++
++ void
++ maildir_get_file (MAILDIRFILE **mdfile)
++ {
++ MAILDIRFILE *md;
++
++ md = (MAILDIRFILE *) fs_get(sizeof(MAILDIRFILE));
++ memset(md, 0, sizeof(MAILDIRFILE));
++ *mdfile = md;
++ }
++
++ void
++ maildir_free_file (void **mdfile)
++ {
++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL;
++
++ if (md){
++ if (md->name) fs_give((void **)&md->name);
++ fs_give((void **)&md);
++ }
++ }
++
++ void
++ maildir_free_file_only (void **mdfile)
++ {
++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL;
++
++ if (md && md->name)
++ fs_give((void **)&md->name);
++ }
++
++ int
++ maildir_any_new_msgs(char *mailbox)
++ {
++ char tmp[MAILTMPLEN];
++ int rv = NIL;
++ DIR *dir;
++ struct direct *d;
++
++ MDFLD(tmp, mailbox, New);
++
++ if (!(dir = opendir (tmp)))
++ return rv;
++
++ while ((d = readdir(dir)) != NULL){
++ if (d->d_name[0] == '.')
++ continue;
++ rv = T;
++ break;
++ }
++ closedir(dir);
++ return rv;
++ }
++
++
++ void
++ maildir_get_date(MAILSTREAM *stream, unsigned long msgno)
++ {
++ MESSAGECACHE *elt;
++ struct tm *t;
++ time_t ti;
++ int i,k;
++
++ elt = mail_elt (stream,msgno);
++ if(elt && elt->year != 0)
++ return;
++ if ((ti = mdfntoul(MDFILE(elt))) > 0L && (t = gmtime(&ti))){
++ i = t->tm_hour * 60 + t->tm_min;
++ k = t->tm_yday;
++ t = localtime(&ti);
++ i = t->tm_hour * 60 + t->tm_min - i;
++ if((k = t->tm_yday - k) != 0)
++ i += ((k < 0) == (abs (k) == 1)) ? -24*60 : 24*60;
++ k = abs (i);
++ elt->hours = t->tm_hour;
++ elt->minutes = t->tm_min;
++ elt->seconds = t->tm_sec;
++ elt->day = t->tm_mday; elt->month = t->tm_mon + 1;
++ elt->year = t->tm_year - (BASEYEAR - 1900);
++ elt->zoccident = (k == i) ? 0 : 1;
++ elt->zhours = k/60;
++ elt->zminutes = k % 60;
++ }
++ }
++
++ /* Support for Courier Style directories
++ When this code is complete there will be two types of support, which
++ will be configurable. The problem is the following: In Courier style
++ folder structure, a "folder" may have a subfolder called
++ "folder.subfolder", which is not natural in the file system in the
++ sense that I can not stat for "folder.subfolder" wihtout knowing what
++ "subfolder" is. It needs to be guessed. Because of this I need to look
++ in the list of folders if there is a folder with a name
++ "folder.subfolder", before I can say if the folder is dual or not. One
++ can avoid this annoyance if one ignores the problem by declaring that
++ every folder is dual. I will however code as the default the more
++ complicated idea of scaning the containing directory each time it is
++ modified and search for subfolders, and list the entries it found.
++ */
++
++ int courier_dir_select (const struct direct *name)
++ {
++ return name->d_name[0] == '.' && (strlen(name->d_name) > 2
++ || (strlen(name->d_name) == 2 && name->d_name[1] != '.'));
++ }
++
++ int courier_dir_sort (const void *d1, const void *d2)
++ {
++ const struct direct *e1 = *(const struct direct **) d1;
++ const struct direct *e2 = *(const struct direct **) d2;
++
++ return strcmp((char *) e1->d_name, (char *) e2->d_name);
++ }
++
++ void courier_free_cdir (COURIER_S **cdir)
++ {
++ int i;
++
++ if (!*cdir)
++ return;
++
++ if ((*cdir)->path) fs_give((void **)&((*cdir)->path));
++ for (i = 0; i < (*cdir)->total; i++)
++ if((*cdir)->data[i]->name) fs_give((void **)&((*cdir)->data[i]->name));
++ fs_give((void **)&((*cdir)->data));
++ fs_give((void **)&(*cdir));
++ }
++
++ COURIER_S *courier_get_cdir (int total)
++ {
++ COURIER_S *cdir;
++
++ cdir = (COURIER_S *)fs_get(sizeof(COURIER_S));
++ memset(cdir, 0, sizeof(COURIER_S));
++ cdir->data = (COURIERLOCAL **) fs_get(total*sizeof(COURIERLOCAL *));
++ memset(cdir->data, 0, sizeof(COURIERLOCAL *));
++ cdir->total = total;
++ return cdir;
++ }
++
++ int courier_search_list(COURIERLOCAL **data, char *name, int first, int last)
++ {
++ int try = (first + last)/2;
++
++ if(!strstr(data[try]->name, name)){
++ if(first == try) /* first == last || first + 1 == last */
++ return strstr(data[last]->name, name) ? 1 : 0;
++ if(strcmp(data[try]->name, name) < 0) /*data[try] < name < data[end] */
++ return courier_search_list(data, name, try, last);
++ else /* data[begin] < name < data[try] */
++ return courier_search_list(data, name, first, try);
++ }
++ return 1;
++ }
++
++ /* Lists all directories that are subdirectories of a given directory */
++
++ COURIER_S *courier_list_dir(char *curdir)
++ {
++ struct direct **names = NIL;
++ struct stat sbuf;
++ unsigned long ndir;
++ COURIER_S *cdir = NULL;
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], pathname[MAILTMPLEN],
++ realname[MAILTMPLEN];
++ int i, j, scand, td;
++
++ /* There are two cases, either curdir is
++ #mc/INBOX. #mc/INBOX.foo
++ or
++ #mc/Maildir/. #mc/Maildir/.foo
++ */
++ strcpy(tmp,curdir + 4);
++ if(!strncmp(ucase(tmp), "INBOX", 5))
++ strcpy(tmp, "#mc/INBOX.");
++ else{
++ strcpy(tmp, curdir);
++ for (i = strlen(tmp) - 1; tmp[i] && tmp[i] != '/'; i--);
++ tmp[i+2] = '\0'; /* keep the last "." intact */
++ }
++ maildir_file_path(tmp, realname);
++ maildir_scandir (realname, &names, &ndir, &scand, COURIER);
++
++ if (scand > 0){
++ cdir = courier_get_cdir(ndir);
++ cdir->path = cpystr(realname);
++ for(i = 0, j = 0; i < ndir; i++){
++ td = realname[strlen(realname) - 1] == '.'
++ && *names[i]->d_name == '.';
++ sprintf(tmp2,"%s%s", tmp, names[i]->d_name+1);
++ sprintf(pathname,"%s%s", realname, names[i]->d_name + td);
++ if(stat(pathname, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)){
++ cdir->data[j] = (COURIERLOCAL *) fs_get(sizeof(COURIERLOCAL));
++ cdir->data[j++]->name = cpystr(tmp2);
++ }
++ fs_give((void **)&names[i]);
++ }
++ cdir->total = j;
++ if(cdir->total == 0)
++ courier_free_cdir(&cdir);
++ }
++ if(names)
++ fs_give((void **) &names);
++ return cdir;
++ }
++
++ void
++ courier_list_info(COURIER_S **cdirp, char *data, int i)
++ {
++ long style = (long) maildir_parameters(GET_COURIERSTYLE, NIL);
++ COURIER_S *cdir = *cdirp;
++
++ if(maildir_valid(cdir->data[i]->name)){
++ if(courier_search_list(cdir->data, data, 0, cdir->total - 1))
++ cdir->data[i]->attribute = LATT_HASCHILDREN;
++ else
++ cdir->data[i]->attribute = (style == COURIER)
++ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS;
++ }
++ else
++ cdir->data[i]->attribute = LATT_NOSELECT;
++ cdir->data[i]->attribute += maildir_any_new_msgs(cdir->data[i]->name)
++ ? LATT_MARKED : LATT_UNMARKED;
++ }
++
++ /* UID Support */
++ /* Yes, I know I procastinated a lot about this, but here it is finally */
++
++ unsigned int
++ maildir_can_assign_uid (MAILSTREAM *stream)
++ {
++ unsigned int rv = 0;
++ int createtemp;
++ unsigned long t;
++ char tmp[MAILTMPLEN], *s;
++ DIR *dir;
++ struct direct *d;
++
++ if(!stream || stream->rdonly
++ || !LOCAL || !LOCAL->dir || !(dir = opendir(LOCAL->dir)))
++ return rv;
++
++ sprintf(tmp, "%s.%d", MDUIDTEMP, mypid);
++ while ((d = readdir(dir)) != NULL){
++ if(!strncmp(d->d_name, tmp, strlen(tmp))
++ || !strncmp(d->d_name, MDUIDTEMP, strlen(MDUIDTEMP)))
++ break;
++ }
++ rv = d ? !strncmp(d->d_name, tmp, strlen(tmp)) : 1;
++ createtemp = d ? 0 : 1;
++ if (d && rv == 0){ /* is there a temp file that is not ours? */
++ s = strrchr(d->d_name, '.');
++ t = strtoul(s+1, &s, 10);
++ if(s != NULL && *s != '\0')
++ createtemp++;
++ if(time(0) > t + MAXTEMPUID){
++ createtemp++;
++ sprintf(tmp,"%s/%s", LOCAL->dir, d->d_name);
++ unlink(tmp);
++ }
++ }
++ closedir(dir);
++ if(createtemp){
++ FILE *fp;
++ sprintf(tmp,"%s/%s.%d.%lu", LOCAL->dir, MDUIDTEMP, mypid, time(0));
++ if(fp = fopen(tmp, "w")){
++ fclose(fp);
++ if(LOCAL->uidtempfile)
++ fs_give((void **)&LOCAL->uidtempfile);
++ LOCAL->uidtempfile = cpystr(tmp);
++ rv++;
++ }
++ }
++ return rv;
++ }
++
++ void
++ maildir_read_uid(MAILSTREAM *stream, unsigned long *uid_last,
++ unsigned long *uid_validity)
++ {
++ int createuid, deleteuid = 0;
++ char tmp[MAILTMPLEN], *s = NULL;
++ DIR *dir;
++ struct direct *d;
++
++ if(uid_last) *uid_last = 0L;
++ if(uid_last && uid_validity) *uid_validity = time(0);
++ if(!stream || !LOCAL || !LOCAL->dir || !(dir = opendir(LOCAL->dir)))
++ return;
++
++ while ((d = readdir(dir)) != NULL){
++ if(!strncmp(d->d_name, MDUIDLAST, strlen(MDUIDLAST)))
++ break;
++ }
++ createuid = d == NULL ? 1 : 0;
++ if(uid_last == NULL)
++ deleteuid++;
++ if(d){
++ if(uid_last){
++ s = d->d_name + strlen(MDUIDLAST) + 1;
++ *uid_last = strtoul(s, &s, 10);
++ if(!s || *s != '.'){
++ deleteuid++;
++ createuid++;
++ *uid_last = 0L;
++ }
++ }
++ if(s && *s == '.'){
++ if(uid_validity){
++ s++;
++ *uid_validity = strtoul(s, &s, 10);
++ if(s && *s != '\0'){
++ *uid_validity = time(0);
++ deleteuid++;
++ createuid++;
++ }
++ }
++ }
++ else{
++ deleteuid++;
++ createuid++;
++ }
++ }
++ if(deleteuid){
++ sprintf(tmp,"%s/%s", LOCAL->dir, d->d_name);
++ unlink(tmp);
++ }
++ if(createuid)
++ maildir_write_uid(stream, (uid_last ? *uid_last : stream->uid_last),
++ uid_validity ? *uid_validity : time(0));
++ closedir(dir);
++ }
++
++ void
++ maildir_write_uid(MAILSTREAM *stream, unsigned long uid_last,
++ unsigned long uid_validity)
++ {
++ char tmp[MAILTMPLEN];
++ FILE *fp;
++
++ if(!stream || stream->rdonly || !LOCAL || !LOCAL->dir)
++ return;
++
++ sprintf(tmp,"%s/%s.%010lu.%010lu", LOCAL->dir, MDUIDLAST,
++ uid_last, uid_validity);
++ if(fp = fopen(tmp, "w"))
++ fclose(fp);
++ }
++
++ unsigned long
++ maildir_get_uid(char *name)
++ {
++ char *s;
++ unsigned long rv = 0L;
++
++ if(!name || (s = strstr(name,MDUIDSEP)) == NULL)
++ return rv;
++
++ s += strlen(MDUIDSEP);
++ rv = strtoul(s, NULL, 10);
++ return rv;
++ }
++
++
++ void
++ maildir_delete_uid(MAILSTREAM *stream, unsigned long msgno)
++ {
++ char old[MAILTMPLEN], new[MAILTMPLEN], *s, *t;
++ MESSAGECACHE *elt;
++
++ elt = mail_elt(stream, msgno);
++ if(!stream || !elt || !elt->private.spare.ptr || !LOCAL || !LOCAL->dir)
++ return;
++
++ sprintf(old, "%s/%s/%s", LOCAL->dir, MDNAME(Cur), MDFILE(elt));
++ t = MDFILE(elt);
++ if(s = strstr(MDFILE(elt), MDUIDSEP)){
++ *s = '\0';
++ s += strlen(MDUIDSEP);
++ strtoul(s, &s, 10);
++ sprintf(new, "%s/%s/%s%s", LOCAL->dir, MDNAME(Cur), t, s);
++ if(rename(old, new) == 0){
++ maildir_free_file_only ((void **)&elt->private.spare.ptr);
++ s = strrchr(new, '/');
++ MDFILE(elt) = cpystr(s+1);
++ }
++ elt->private.uid = 0L;
++ }
++ }
++
++ void
++ maildir_assign_uid(MAILSTREAM *stream, unsigned long msgno, unsigned long uid)
++ {
++ int createuid, deleteuid = 0;
++ char old[MAILTMPLEN], new[MAILTMPLEN], *s, *t;
++ MESSAGECACHE *elt;
++
++ elt = mail_elt(stream, msgno);
++ if(!stream || !elt || !elt->private.spare.ptr || !LOCAL || !LOCAL->dir)
++ return;
++
++ maildir_delete_uid(stream, msgno);
++ sprintf(old, "%s/%s/%s", LOCAL->dir, MDNAME(Cur), MDFILE(elt));
++ t = MDFILE(elt);
++ if((s = strrchr(MDFILE(elt),FLAGSEP)) != NULL){
++ *s++ = '\0';
++ sprintf(new, "%s/%s/%s%s%lu%c%s",
++ LOCAL->dir, MDNAME(Cur), t, MDUIDSEP, uid, FLAGSEP, s);
++ if(rename(old, new) == 0){
++ maildir_free_file_only ((void **)&elt->private.spare.ptr);
++ s = strrchr(new, '/');
++ MDFILE(elt) = cpystr(s+1);
++ stream->uid_validity = time(0);
++ }
++ elt->private.uid = uid;
++ }
++ }
++
++ void
++ maildir_uid_renew_tempfile(MAILSTREAM *stream)
++ {
++ char tmp[MAILTMPLEN];
++
++ if(!stream || stream->rdonly
++ || !LOCAL || !LOCAL->candouid || !LOCAL->dir || !LOCAL->uidtempfile)
++ return;
++
++ sprintf(tmp,"%s/%s.%d.%lu", LOCAL->dir, MDUIDTEMP, mypid, time(0));
++ if(rename(LOCAL->uidtempfile, tmp) == 0){
++ fs_give((void **)&LOCAL->uidtempfile);
++ LOCAL->uidtempfile = cpystr(tmp);
++ }
++ }
+diff -rc alpine-2.00/imap/src/osdep/unix/maildir.h alpine-2.00.I.USE/imap/src/osdep/unix/maildir.h
+*** alpine-2.00/imap/src/osdep/unix/maildir.h 2011-02-07 20:34:02.000000000 -0800
+--- alpine-2.00.I.USE/imap/src/osdep/unix/maildir.h 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 0 ****
+--- 1,226 ----
++ /*
++ * A few definitions that try to make this module portable to other
++ * platforms (e.g. Cygwin). This module is based on the information from
++ * http://cr.yp.to/proto/maildir.html
++ */
++
++ /* First we deal with the separator character */
++ #ifndef FLAGSEP
++ #define FLAGSEP ':'
++ #endif
++ #define SIZESEP ','
++
++ const char sep1[] = {FLAGSEP, '1', ',', '\0'}; /* experimental semantics*/
++ const char sep2[] = {FLAGSEP, '2', ',', '\0'}; /* Flags Information */
++ const char sep3[] = {FLAGSEP, '3', ',', '\0'}; /* Grrrr.... */
++
++ const char *sep[] = { sep1, sep2, sep3, NULL};
++
++ #define MDSEP(i) sep[((i) - 1)]
++
++ /* Now we deal with flags. Woohoo! */
++ typedef enum {Draft, Flagged, Passed, Replied, Seen, Trashed,
++ EmptyFlag, EndFlags} MdFlagNamesType;
++ const int mdimapflags[] = {Draft, Flagged, Replied, Seen, Trashed, EmptyFlag, EndFlags};
++ const int mdkwdflags[] = {Passed, EmptyFlag, EndFlags};
++
++ /* this array lists the codes for mdflgnms (maildir flag names) above */
++ const char *mdflags[] = { "D", "F", "P", "R", "S", "T", "", NULL};
++ /* and as characters too */
++ const char cmdflags[] = { 'D', 'F', 'P', 'R', 'S', 'T', '0', '\0'};
++
++ /* MDFLAG(Seen, elt->seen) */
++ #define MDFLAG(i,j) mdflags[j ? (i) : EmptyFlag]
++ /* MDFLAGC(Seen) */
++ #define MDFLAGC(i) cmdflags[(i)]
++
++ /* Now we deal with the directory structure */
++ typedef enum {Cur, Tmp, New, EndDir} DirNamesType;
++ char *mdstruct[] = {"cur", "tmp", "new", NULL};
++ #define MDNAME(i) mdstruct[(i)]
++ #define MDFLD(tmp, dir, i) sprintf((tmp),"%s/%s", (dir), mdstruct[(i)])
++ #define MSGPATH(tmp, dir, msg,i) sprintf((tmp),"%s/%s/%s", (dir), mdstruct[(i)],(msg))
++
++ /* Files associated to a maildir directory */
++
++ #define MDUIDVALIDITY ".uidvalidity" /* support for old maildirs */
++ #define MDDIR ".mdir" /* this folder is a directory */
++ #define MDUIDLAST ".uidlast" /* last assigned uid */
++ #define MDUIDTEMP ".uidtemp" /* We assign uid's no one else */
++
++
++
++ /* Support of Courier Structure */
++ #define CCLIENT 0
++ #define COURIER 1
++ #define IS_CCLIENT(t) \
++ (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\
++ && ((t)[2] == 'd' || (t)[2] == 'D')\
++ && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0)
++
++ #define IS_COURIER(t) \
++ (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\
++ && ((t)[2] == 'c' || (t)[2] == 'C')\
++ && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0)
++ #define MDPREFIX(s) ((s) ? "#mc/" : "#md/")
++ #define MDSEPARATOR(s) ((s) ? '.' : '/')
++
++ /* UID Support */
++
++ #define MAXTEMPUID (unsigned long) 180L
++ const char mduid[] = {',','u','=','\0'};
++ #define MDUIDSEP mduid
++
++
++ /* Now we deal with messages filenames */
++ char mdlocaldomain[MAILTMPLEN+1] = {'\0'};
++ pid_t mypid = (pid_t) 0;
++ static char *mdfpath = NULL;
++ static char myMdInboxDir[50] = { '\0' };/* Location of the Maildir INBOX */
++ static long CourierStyle = CCLIENT;
++
++ #define CHUNK 16384 /* from unix.h */
++
++ typedef struct courier_local {
++ char *name; /* name of directory/folder */
++ int attribute; /* attributes (children/marked/etc) */
++ } COURIERLOCAL;
++
++ typedef struct courier {
++ char *path; /* Path to collection */
++ time_t scantime; /* time at which information was generated */
++ int total; /* total number of elements in data */
++ COURIERLOCAL **data;
++ } COURIER_S;
++
++ /* In gdb this is the *(struct maildir_local *)stream->local structure */
++ typedef struct maildir_local {
++ unsigned int dirty : 1; /* diskcopy needs updating */
++ unsigned int courier : 1; /* It is Courier style file system */
++ unsigned int link : 1; /* There is a symbolic link */
++ unsigned int candouid; /* we can assign uids and no one else */
++ char *uidtempfile; /* path to uid temp file */
++ int fd; /* fd of open message */
++ char *dir; /* mail directory name */
++ char *curdir; /* mail directory name/cur */
++ unsigned char *buf; /* temporary buffer */
++ unsigned long buflen; /* current size of temporary buffer */
++ time_t scantime; /* last time directory scanned */
++ } MAILDIRLOCAL;
++
++ /* Convenient access to local data */
++ #define LOCAL ((MAILDIRLOCAL *) stream->local)
++
++ typedef struct maildir_file_info {
++ char *name; /* name of the file */
++ DirNamesType loc; /* location of this file */
++ unsigned long pos; /* place in list where this file is listed */
++ off_t size; /* size in bytes, on disk */
++ time_t atime; /* last access time */
++ time_t mtime; /* last modified time */
++ time_t ctime; /* last changed time */
++ } MAILDIRFILE;
++
++ #define MDFILE(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->name)
++ #define MDLOC(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->loc)
++ #define MDPOS(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->pos)
++ #define MDSIZE(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->size)
++ #define MDATIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->atime)
++ #define MDMTIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->mtime)
++ #define MDCTIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->ctime)
++
++ /* Function prototypes */
++
++ DRIVER *maildir_valid (char *name);
++ MAILSTREAM *maildir_open (MAILSTREAM *stream);
++ void maildir_close (MAILSTREAM *stream, long options);
++ long maildir_ping (MAILSTREAM *stream);
++ void maildir_check (MAILSTREAM *stream);
++ long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno,
++ unsigned long *length, long flags);
++ void maildir_list (MAILSTREAM *stream,char *ref,char *pat);
++ void *maildir_parameters (long function,void *value);
++ int maildir_create_folder (char *mailbox);
++ long maildir_create (MAILSTREAM *stream,char *mailbox);
++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt); /*check */
++ long maildir_expunge (MAILSTREAM *stream, char *sequence, long options);
++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
++ long maildir_append (MAILSTREAM *stream,char *mailbox, append_t af, void *data);
++ long maildir_delete (MAILSTREAM *stream,char *mailbox);
++ long maildir_rename (MAILSTREAM *stream,char *old,char *new);
++ long maildir_sub (MAILSTREAM *stream,char *mailbox);
++ long maildir_unsub (MAILSTREAM *stream,char *mailbox);
++ void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat);
++ void courier_list (MAILSTREAM *stream,char *ref, char *pat);
++
++ /* utility functions */
++ void courier_realname (char *name, char *realname);
++ long maildir_dirfmttest (char *name);
++ char *maildir_file (char *dst,char *name);
++ int maildir_select (const struct direct *name);
++ int maildir_namesort (const void *d1, const void *d2);
++ unsigned long antoul (char *seed);
++ unsigned long mdfntoul (char *name);
++ int courier_dir_select (const struct direct *name);
++ int courier_dir_sort (const void *d1, const void *d2);
++ long maildir_canonicalize (char *pattern,char *ref,char *pat);
++ void maildir_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level);
++ void courier_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level);
++ int maildir_file_path(char *name, char *tmp);
++ int maildir_valid_name (char *name);
++ int maildir_valid_dir (char *name);
++ int is_valid_maildir (char **name);
++ int maildir_message_exists(MAILSTREAM *stream,char *name, char *tmp);
++ char *maildir_remove_root(char *name);
++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long *length,long flags);
++ unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno,
++ DirNamesType dirtype);
++ int maildir_eliminate_duplicate (char *name, struct direct ***flist,
++ unsigned long *nfiles);
++ int maildir_doscandir (char *name, struct direct ***flist, int flag);
++ unsigned long maildir_scandir (char *name, struct direct ***flist,
++ unsigned long *nfiles, int *scand, int flag);
++ void maildir_parse_folder (MAILSTREAM *stream, int full);
++ void md_domain_name (void);
++ char *myrootdir (char *name);
++ char *mdirpath (void);
++ int maildir_initial_check (MAILSTREAM *stream, DirNamesType dirtype);
++ unsigned long maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs,
++ DirNamesType dirtype, struct direct **names, unsigned long nfiles, int full);
++ int same_maildir_file(char *name1, char *name2);
++ int comp_maildir_file(char *name1, char *name2);
++ int maildir_message_in_list(char *msgname, struct direct **names,
++ unsigned long bottom, unsigned long top, unsigned long *pos);
++ void maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t);
++ int maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno);
++ void maildir_abort (MAILSTREAM *stream);
++ int maildir_contains_folder(char *dirname, char *name);
++ int maildir_is_dir(char *dirname, char *name);
++ int maildir_dir_is_empty(char *mailbox);
++ int maildir_create_work (char *mailbox, int loop);
++ void maildir_get_file (MAILDIRFILE **mdfile);
++ void maildir_free_file (void **mdfile);
++ void maildir_free_file_only (void **mdfile);
++ int maildir_any_new_msgs(char *mailbox);
++ void maildir_get_date(MAILSTREAM *stream, unsigned long msgno);
++ void maildir_fast (MAILSTREAM *stream,char *sequence,long flags);
++
++ /* Courier server support */
++ void courier_free_cdir (COURIER_S **cdir);
++ COURIER_S *courier_get_cdir (int total);
++ int courier_search_list(COURIERLOCAL **data, char *name, int first, int last);
++ COURIER_S *courier_list_dir(char *curdir);
++ void courier_list_info(COURIER_S **cdirp, char *data, int i);
++
++ /* UID Support */
++ unsigned int maildir_can_assign_uid (MAILSTREAM *stream);
++ void maildir_read_uid(MAILSTREAM *stream, unsigned long *uid_last,
++ unsigned long *uid_validity);
++ void maildir_write_uid(MAILSTREAM *stream, unsigned long uid_last,
++ unsigned long uid_validity);
++ unsigned long maildir_get_uid(char *name);
++ void maildir_delete_uid(MAILSTREAM *stream, unsigned long msgno);
++ void maildir_assign_uid(MAILSTREAM *stream, unsigned long msgno, unsigned long uid);
++ void maildir_uid_renew_tempfile(MAILSTREAM *stream);
++
+diff -rc alpine-2.00/imap/src/osdep/unix/Makefile alpine-2.00.I.USE/imap/src/osdep/unix/Makefile
+*** alpine-2.00/imap/src/osdep/unix/Makefile 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/osdep/unix/Makefile 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 144,150 ****
+ # However, mh needs to be before any sysinbox formats (such as mmdf or unix)
+ # since otherwise INBOX won't work correctly when mh_allow_inbox is set.
+ #
+! DEFAULTDRIVERS=imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile
+ CHUNKSIZE=65536
+
+ # Normally no need to change any of these
+--- 144,150 ----
+ # However, mh needs to be before any sysinbox formats (such as mmdf or unix)
+ # since otherwise INBOX won't work correctly when mh_allow_inbox is set.
+ #
+! DEFAULTDRIVERS=maildir courier imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile
+ CHUNKSIZE=65536
+
+ # Normally no need to change any of these
+***************
+*** 153,159 ****
+ BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o utf8aux.o siglocal.o \
+ dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
+ rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
+! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o
+ CFLAGS=-g
+
+ CAT=cat
+--- 153,159 ----
+ BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o utf8aux.o siglocal.o \
+ dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
+ rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
+! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o maildir.o
+ CFLAGS=-g
+
+ CAT=cat
+***************
+*** 282,288 ****
+
+ cyg: # Cygwin - note that most local file drivers don't work!!
+ $(BUILD) `$(CAT) SPECIALS` OS=$@ \
+! DEFAULTDRIVERS="imap nntp pop3 mbx unix phile" \
+ SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \
+ SPOOLDIR=/var \
+ ACTIVEFILE=/usr/local/news/lib/active \
+--- 282,288 ----
+
+ cyg: # Cygwin - note that most local file drivers don't work!!
+ $(BUILD) `$(CAT) SPECIALS` OS=$@ \
+! DEFAULTDRIVERS="imap nntp pop3 mbx unix maildir phile" \
+ SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \
+ SPOOLDIR=/var \
+ ACTIVEFILE=/usr/local/news/lib/active \
+***************
+*** 892,898 ****
+ unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
+ utf8.o: mail.h misc.h osdep.h utf8.h tmap.c widths.c
+ utf8aux.o: mail.h misc.h osdep.h utf8.h
+!
+
+ # OS-dependent
+
+--- 892,898 ----
+ unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
+ utf8.o: mail.h misc.h osdep.h utf8.h tmap.c widths.c
+ utf8aux.o: mail.h misc.h osdep.h utf8.h
+! maildir.o: mail.h misc.h osdep.h maildir.h dummy.h
+
+ # OS-dependent
+
+diff -rc alpine-2.00/imap/src/osdep/unix/os_cyg.h alpine-2.00.I.USE/imap/src/osdep/unix/os_cyg.h
+*** alpine-2.00/imap/src/osdep/unix/os_cyg.h 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/osdep/unix/os_cyg.h 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 47,52 ****
+--- 47,53 ----
+ #define setpgrp setpgid
+
+ #define SYSTEMUID 18 /* Cygwin returns this for SYSTEM */
++ #define FLAGSEP ';'
+ #define geteuid Geteuid
+ uid_t Geteuid (void);
+
+diff -rc alpine-2.00/imap/src/osdep/unix/ssl_unix.c alpine-2.00.I.USE/imap/src/osdep/unix/ssl_unix.c
+*** alpine-2.00/imap/src/osdep/unix/ssl_unix.c 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/osdep/unix/ssl_unix.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 524,530 ****
+ if (tcpdebug) mm_log ("Successfully read SSL data",TCPDEBUG);
+ }
+ /* timeout, punt unless told not to */
+! else if (!tmoh || !(*tmoh) (now - t,now - tl)) {
+ if (tcpdebug) mm_log ("SSL data read timeout",TCPDEBUG);
+ return ssl_abort (stream);
+ }
+--- 524,530 ----
+ if (tcpdebug) mm_log ("Successfully read SSL data",TCPDEBUG);
+ }
+ /* timeout, punt unless told not to */
+! else if (!tmoh || !(*tmoh) (now - t,now - tl, stream->tcpstream->host)) {
+ if (tcpdebug) mm_log ("SSL data read timeout",TCPDEBUG);
+ return ssl_abort (stream);
+ }
+diff -rc alpine-2.00/imap/src/osdep/unix/tcp_unix.c alpine-2.00.I.USE/imap/src/osdep/unix/tcp_unix.c
+*** alpine-2.00/imap/src/osdep/unix/tcp_unix.c 2008-06-04 11:18:34.000000000 -0700
+--- alpine-2.00.I.USE/imap/src/osdep/unix/tcp_unix.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 585,591 ****
+ if (tcpdebug) mm_log ("Successfully read TCP buffer",TCPDEBUG);
+ }
+ /* timeout, punt unless told not to */
+! else if (!tmoh || !(*tmoh) (now - t,now - tl)) {
+ if (tcpdebug) mm_log ("TCP buffer read timeout",TCPDEBUG);
+ return tcp_abort (stream);
+ }
+--- 585,591 ----
+ if (tcpdebug) mm_log ("Successfully read TCP buffer",TCPDEBUG);
+ }
+ /* timeout, punt unless told not to */
+! else if (!tmoh || !(*tmoh) (now - t,now - tl, stream->host)) {
+ if (tcpdebug) mm_log ("TCP buffer read timeout",TCPDEBUG);
+ return tcp_abort (stream);
+ }
+***************
+*** 645,651 ****
+ if (tcpdebug) mm_log ("Successfully read TCP data",TCPDEBUG);
+ }
+ /* timeout, punt unless told not to */
+! else if (!tmoh || !(*tmoh) (now - t,now - tl)) {
+ if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG);
+ return tcp_abort (stream);/* error or timeout no-continue */
+ }
+--- 645,651 ----
+ if (tcpdebug) mm_log ("Successfully read TCP data",TCPDEBUG);
+ }
+ /* timeout, punt unless told not to */
+! else if (!tmoh || !(*tmoh) (now - t,now - tl, stream->host)) {
+ if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG);
+ return tcp_abort (stream);/* error or timeout no-continue */
+ }
+***************
+*** 716,722 ****
+ if (tcpdebug) mm_log ("successfully wrote to TCP",TCPDEBUG);
+ }
+ /* timeout, punt unless told not to */
+! else if (!tmoh || !(*tmoh) (now - t,now - tl)) {
+ if (tcpdebug) mm_log ("TCP write timeout",TCPDEBUG);
+ return tcp_abort (stream);
+ }
+--- 716,722 ----
+ if (tcpdebug) mm_log ("successfully wrote to TCP",TCPDEBUG);
+ }
+ /* timeout, punt unless told not to */
+! else if (!tmoh || !(*tmoh) (now - t,now - tl, stream->host)) {
+ if (tcpdebug) mm_log ("TCP write timeout",TCPDEBUG);
+ return tcp_abort (stream);
+ }
+diff -rc alpine-2.00/include/general.h alpine-2.00.I.USE/include/general.h
+*** alpine-2.00/include/general.h 2007-01-25 12:29:45.000000000 -0800
+--- alpine-2.00.I.USE/include/general.h 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 32,37 ****
+--- 32,38 ----
+ #undef TRUE
+ #define TRUE 1 /* True, yes, good, etc. */
+ #define ABORT 2 /* Death, ^G, abort, etc. */
++ #define COUNT 3 /* For control-c command */
+
+
+ #undef MIN
+diff -rc alpine-2.00/patchlevel alpine-2.00.I.USE/patchlevel
+*** alpine-2.00/patchlevel 2011-02-07 20:34:02.000000000 -0800
+--- alpine-2.00.I.USE/patchlevel 2011-02-07 20:34:02.000000000 -0800
+***************
+*** 0 ****
+--- 1 ----
++ char plevstamp[]="VERSION=84 created on Mon Feb 07 2011 20:34:02 PST";
+diff -rc alpine-2.00/pico/attach.c alpine-2.00.I.USE/pico/attach.c
+*** alpine-2.00/pico/attach.c 2008-06-11 10:21:24.000000000 -0700
+--- alpine-2.00.I.USE/pico/attach.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 108,115 ****
+ switch(status){
+ case HELPCH:
+ if(Pmaster){
+- VARS_TO_SAVE *saved_state;
+-
+ saved_state = save_pico_state();
+ (*Pmaster->helper)(Pmaster->attach_help, _("Attach Help"), 1);
+ if(saved_state){
+--- 108,113 ----
+diff -rc alpine-2.00/pico/basic.c alpine-2.00.I.USE/pico/basic.c
+*** alpine-2.00/pico/basic.c 2007-11-26 15:45:22.000000000 -0800
+--- alpine-2.00.I.USE/pico/basic.c 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 25,33 ****
+ * framing, are hard.
+ */
+ #include "headers.h"
+!
+ #include "osdep/terminal.h"
+
+
+ /*
+ * Move the cursor to the
+--- 25,34 ----
+ * framing, are hard.
+ */
+ #include "headers.h"
+! #include "../pith/osdep/color.h"
+ #include "osdep/terminal.h"
+
++ int indent_match(char *, LINE *, char *, int, int);
+
+ /*
+ * Move the cursor to the
+***************
+*** 284,290 ****
+ gotobop(int f, int n)
+ {
+ int quoted, qlen;
+! UCS qstr[NLINE], qstr2[NLINE];
+
+ if (n < 0) /* the other way...*/
+ return(gotoeop(f, -n));
+--- 285,291 ----
+ gotobop(int f, int n)
+ {
+ int quoted, qlen;
+! char qstr[NLINE], qstr2[NLINE], ind_str[NLINE], pqstr[NLINE];;
+
+ if (n < 0) /* the other way...*/
+ return(gotoeop(f, -n));
+***************
+*** 296,301 ****
+--- 297,310 ----
+ curwp->w_dotp = lback(curwp->w_dotp);
+ curwp->w_doto = 0;
+ }
++
++ if (indent_match(default_qstr(), curwp->w_dotp,ind_str, NLINE, 0)){
++ if (n){ /* look for another paragraph ? */
++ curwp->w_dotp = lback(curwp->w_dotp);
++ continue;
++ }
++ break;
++ }
+
+ /* scan line by line until we come to a line ending with
+ * a <NL><NL> or <NL><TAB> or <NL><SPACE>
+***************
+*** 303,322 ****
+ * PLUS: if there's a quote string, a quoted-to-non-quoted
+ * line transition.
+ */
+! quoted = glo_quote_str ? quote_match(glo_quote_str, curwp->w_dotp, qstr, NLINE) : 0;
+! qlen = quoted ? ucs4_strlen(qstr) : 0;
+ while(lback(curwp->w_dotp) != curbp->b_linep
+ && llength(lback(curwp->w_dotp)) > qlen
+! && (glo_quote_str
+! ? (quoted == quote_match(glo_quote_str,
+! lback(curwp->w_dotp),
+! qstr2, NLINE)
+! && !ucs4_strcmp(qstr, qstr2))
+! : 1)
+! && lgetc(curwp->w_dotp, qlen).c != TAB
+! && lgetc(curwp->w_dotp, qlen).c != ' ')
+ curwp->w_dotp = lback(curwp->w_dotp);
+
+ if(n){
+ /* keep looking */
+ if(lback(curwp->w_dotp) == curbp->b_linep)
+--- 312,369 ----
+ * PLUS: if there's a quote string, a quoted-to-non-quoted
+ * line transition.
+ */
+! quoted = quote_match(default_qstr(), curwp->w_dotp, qstr, NLINE, 0);
+! qlen = quoted ? strlen(qstr) : 0;
+ while(lback(curwp->w_dotp) != curbp->b_linep
+ && llength(lback(curwp->w_dotp)) > qlen
+! && (quoted == quote_match(default_qstr(),
+! lback(curwp->w_dotp), qstr2, NLINE, 0))
+! && !strcmp(qstr, qstr2) /* processed string */
+! && (quoted == quote_match(default_qstr(),
+! lback(curwp->w_dotp), qstr2, NLINE, 1))
+! && !strcmp(qstr, qstr2) /* raw string */
+! && !indent_match(default_qstr(),
+! lback(curwp->w_dotp),ind_str, NLINE, 0)
+! && !ISspace(lgetc(curwp->w_dotp, qlen).c))
+ curwp->w_dotp = lback(curwp->w_dotp);
+
++ /*
++ * Ok, we made it here and we assume that we are at the begining
++ * of the paragraph. Let's double check this now. In order to do
++ * so we shell check if the first line was indented in a special
++ * way.
++ */
++ if(lback(curwp->w_dotp) == curbp->b_linep)
++ break;
++ else{
++ int i, j;
++
++ /*
++ * First we test if the preceding line is indented.
++ * for the following test we need to have the raw values,
++ * not the processed values
++ */
++ quote_match(default_qstr(), curwp->w_dotp, qstr, NLINE, 1);
++ quote_match(default_qstr(), lback(curwp->w_dotp), qstr2, NLINE, 1);
++ for (i = 0, j = 0;
++ qstr[i] && qstr2[i] && (qstr[i] == qstr2[i]); i++, j++);
++ for (; ISspace(qstr2[i]); i++);
++ for (; ISspace(qstr[j]); j++);
++ if ((indent_match(default_qstr(), lback(curwp->w_dotp),
++ ind_str, NLINE, 1)
++ && (strlenis(qstr2)
++ + strlenis(ind_str) >= strlenis(qstr)))
++ || (lback(curwp->w_dotp) != curbp->b_linep
++ && llength(lback(curwp->w_dotp)) > qlen
++ && (quoted == quote_match(default_qstr(),
++ lback(curwp->w_dotp), pqstr, NLINE, 0))
++ && !strcmp(qstr, pqstr)
++ && !ISspace(lgetc(curwp->w_dotp, qlen).c)
++ && (strlenis(qstr2) > strlenis(qstr)))
++ && !qstr2[i] && !qstr[j])
++ curwp->w_dotp = lback(curwp->w_dotp);
++ }
++
+ if(n){
+ /* keep looking */
+ if(lback(curwp->w_dotp) == curbp->b_linep)
+***************
+*** 329,335 ****
+ else{
+ /* leave cursor on first word in para */
+ curwp->w_doto = 0;
+! while(ucs4_isspace(lgetc(curwp->w_dotp, curwp->w_doto).c))
+ if(++curwp->w_doto >= llength(curwp->w_dotp)){
+ curwp->w_doto = 0;
+ curwp->w_dotp = lforw(curwp->w_dotp);
+--- 376,382 ----
+ else{
+ /* leave cursor on first word in para */
+ curwp->w_doto = 0;
+! while(ISspace(lgetc(curwp->w_dotp, curwp->w_doto).c))
+ if(++curwp->w_doto >= llength(curwp->w_dotp)){
+ curwp->w_doto = 0;
+ curwp->w_dotp = lforw(curwp->w_dotp);
+***************
+*** 343,348 ****
+--- 390,578 ----
+ return(TRUE);
+ }
+
++ unsigned char GetAccent()
++ {
++ UCS c,d;
++ c = GetKey();
++ if ((c == '?') || (c == '!')) {
++ d = c;
++ c = '\\';
++ }
++ else
++ if ((c == 's') || (c == 'S')){
++ c = d = 's';
++ }
++ else
++ if ((c == 'l') || (c == 'L')){
++ c = d = 'l';
++ }
++ else
++ d = GetKey();
++ return accent(c,d);
++ }
++
++ int pineaccent(f,n)
++ int f,n;
++ { unsigned char e;
++
++ if (e = GetAccent())
++ execute(e, 0, 1);
++ return 1;
++ }
++
++ unsigned char accent(f,n)
++ UCS f,n;
++ { UCS c,d;
++
++ c = f;
++ d = n;
++ switch(c){
++ case '~' :
++ switch(d){
++ case 'a' : return '\343';
++ case 'n' : return '\361';
++ case 'o' : return '\365';
++ case 'A' : return '\303';
++ case 'N' : return '\321';
++ case 'O' : return '\325';
++ }
++ break;
++ case '\047' :
++ switch(d){
++ case 'a' : return '\341';
++ case 'e' : return '\351';
++ case 'i' : return '\355';
++ case 'o' : return '\363';
++ case 'u' : return '\372';
++ case 'y' : return '\375';
++ case 'A' : return '\301';
++ case 'E' : return '\311';
++ case 'I' : return '\315';
++ case 'O' : return '\323';
++ case 'U' : return '\332';
++ case 'Y' : return '\335';
++ }
++ break;
++ case '"' :
++ switch(d){
++ case 'a' : return '\344';
++ case 'e' : return '\353';
++ case 'i' : return '\357';
++ case 'o' : return '\366';
++ case 'u' : return '\374';
++ case 'y' : return '\377';
++ case 'A' : return '\304';
++ case 'E' : return '\313';
++ case 'I' : return '\317';
++ case 'O' : return '\326';
++ case 'U' : return '\334';
++ }
++ break;
++ case '^' :
++ switch(d){
++ case 'a' : return '\342';
++ case 'e' : return '\352';
++ case 'i' : return '\356';
++ case 'o' : return '\364';
++ case 'u' : return '\373';
++ case 'A' : return '\302';
++ case 'E' : return '\312';
++ case 'I' : return '\316';
++ case 'O' : return '\324';
++ case 'U' : return '\333';
++ case '0' : return '\260';
++ case '1' : return '\271';
++ case '2' : return '\262';
++ case '3' : return '\263';
++ }
++ break;
++ case '`' :
++ switch(d){
++ case 'a' : return '\340';
++ case 'e' : return '\350';
++ case 'i' : return '\354';
++ case 'o' : return '\362';
++ case 'u' : return '\371';
++ case 'A' : return '\300';
++ case 'E' : return '\310';
++ case 'I' : return '\314';
++ case 'O' : return '\322';
++ case 'U' : return '\331';
++ }
++ break;
++ case 'o' :
++ switch(d){
++ case 'a' : return '\345';
++ case 'A' : return '\305';
++ case '/' : return '\370';
++ case 'r' : return '\256';
++ case 'R' : return '\256';
++ case 'c' : return '\251';
++ case 'C' : return '\251';
++ }
++ break;
++ case '-' :
++ switch(d){
++ case 'o' : return '\272';
++ case 'O' : return '\272';
++ case '0' : return '\272';
++ case 'a' : return '\252';
++ case 'A' : return '\252';
++ case 'l' : return '\243';
++ case 'L' : return '\243';
++ }
++ break;
++ case 'O' :
++ switch(d){
++ case '/' : return '\330';
++ case 'r' : return '\256';
++ case 'R' : return '\256';
++ case 'c' : return '\251';
++ case 'C' : return '\251';
++ }
++ case '/' :
++ switch(d){
++ case 'o' : return '\370';
++ case 'O' : return '\330';
++ }
++ break;
++ case 'a' :
++ switch(d){
++ case 'e' : return '\346';
++ case 'E' : return '\346';
++ }
++ break;
++ case 'A' :
++ switch(d){
++ case 'E' : return '\306';
++ case 'e' : return '\306';
++ }
++ break;
++ case ',' :
++ switch(d){
++ case 'c' : return '\347';
++ case 'C' : return '\307';
++ }
++ break;
++ case '\\' :
++ switch(d){
++ case '?' : return '\277';
++ case '!' : return '\241';
++ }
++ break;
++ case 's' :
++ switch(d){
++ case 's' : return '\337';
++ }
++ break;
++ case 'l' :
++ switch(d){
++ case 'l' : return '\243';
++ }
++ break;
++ }
++ return '\0';
++ }
+
+ /*
+ * go forword to the end of the current paragraph
+***************
+*** 352,359 ****
+ int
+ gotoeop(int f, int n)
+ {
+! int quoted, qlen;
+! UCS qstr[NLINE], qstr2[NLINE];
+
+ if (n < 0) /* the other way...*/
+ return(gotobop(f, -n));
+--- 582,590 ----
+ int
+ gotoeop(int f, int n)
+ {
+! int quoted, qlen, indented, changeqstr = 0;
+! int i,j, fli = 0; /* fli = first line indented a boolean variable */
+! char qstr[NLINE], qstr2[NLINE], ind_str[NLINE];
+
+ if (n < 0) /* the other way...*/
+ return(gotobop(f, -n));
+***************
+*** 366,392 ****
+ break;
+ }
+
+ /* scan line by line until we come to a line ending with
+ * a <NL><NL> or <NL><TAB> or <NL><SPACE>
+ *
+ * PLUS: if there's a quote string, a quoted-to-non-quoted
+ * line transition.
+ */
+! quoted = glo_quote_str
+! ? quote_match(glo_quote_str,
+! curwp->w_dotp, qstr, NLINE) : 0;
+! qlen = quoted ? ucs4_strlen(qstr) : 0;
+
+ while(curwp->w_dotp != curbp->b_linep
+ && llength(lforw(curwp->w_dotp)) > qlen
+! && (glo_quote_str
+! ? (quoted == quote_match(glo_quote_str,
+! lforw(curwp->w_dotp),
+! qstr2, NLINE)
+! && !ucs4_strcmp(qstr, qstr2))
+! : 1)
+! && lgetc(lforw(curwp->w_dotp), qlen).c != TAB
+! && lgetc(lforw(curwp->w_dotp), qlen).c != ' ')
+ curwp->w_dotp = lforw(curwp->w_dotp);
+
+ curwp->w_doto = llength(curwp->w_dotp);
+--- 597,666 ----
+ break;
+ }
+
++ /*
++ * We need to figure out if this line is the first line of
++ * a paragraph that has been indented in a special way. If this
++ * is the case, we advance one more line before we use the
++ * algorithm below
++ */
++
++ if(curwp->w_dotp != curbp->b_linep){
++ quote_match(default_qstr(), curwp->w_dotp, qstr, NLINE, 1);
++ quote_match(default_qstr(), lforw(curwp->w_dotp), qstr2, NLINE, 1);
++ indented = indent_match(default_qstr(), curwp->w_dotp, ind_str,
++ NLINE, 1);
++ if (strlenis(qstr)
++ + strlenis(ind_str) < strlenis(qstr2)){
++ curwp->w_doto = llength(curwp->w_dotp);
++ if(n){ /* this line is a paragraph by itself */
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ continue;
++ }
++ break;
++ }
++ for (i=0,j=0; qstr[i] && qstr2[i] && (qstr[i] == qstr2[i]);i++,j++);
++ for (; ISspace(qstr[i]); i++);
++ for (; ISspace(qstr2[j]); j++);
++ if (!qstr[i] && !qstr2[j] && indented){
++ fli++;
++ if (indent_match(default_qstr(), lforw(curwp->w_dotp),
++ ind_str, NLINE, 0)){
++ if (n){ /* look for another paragraph ? */
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ continue;
++ }
++ }
++ else{
++ if (!lisblank(lforw(curwp->w_dotp)))
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ }
++ }
++ }
++
+ /* scan line by line until we come to a line ending with
+ * a <NL><NL> or <NL><TAB> or <NL><SPACE>
+ *
+ * PLUS: if there's a quote string, a quoted-to-non-quoted
+ * line transition.
+ */
+! /* if the first line is indented (fli == 1), then the test below
+! is on the second line, and in that case we will need the raw
+! string, not the processed string
+! */
+! quoted = quote_match(default_qstr(), curwp->w_dotp, qstr, NLINE, fli);
+! qlen = quoted ? strlen(qstr) : 0;
+
+ while(curwp->w_dotp != curbp->b_linep
+ && llength(lforw(curwp->w_dotp)) > qlen
+! && (quoted == quote_match(default_qstr(),
+! lforw(curwp->w_dotp), qstr2, NLINE, fli))
+! && !strcmp(qstr, qstr2)
+! && (quoted == quote_match(default_qstr(),
+! lforw(curwp->w_dotp), qstr2, NLINE, 1))
+! && !strcmp(qstr, qstr2)
+! && !indent_match(default_qstr(),
+! lforw(curwp->w_dotp), ind_str, NLINE, 0)
+! && !ISspace(lgetc(lforw(curwp->w_dotp), qlen).c))
+ curwp->w_dotp = lforw(curwp->w_dotp);
+
+ curwp->w_doto = llength(curwp->w_dotp);
+***************
+*** 683,689 ****
+--- 957,1013 ----
+ return (scrollforw (1, FALSE));
+ }
+
++ /* deltext deletes from the specified position until the end of the file
++ * or until the signature (when called from Pine), whichever comes first.
++ */
+
++ int
++ deltext (f,n)
++ int f,n;
++ {
++ LINE *currline = curwp->w_dotp;
++ static int firsttime = 0;
++
++ if ((lastflag&CFKILL) == 0)
++ kdelete();
++
++ curwp->w_markp = curwp->w_dotp;
++ curwp->w_marko = curwp->w_doto;
++
++ while (curwp->w_dotp != curbp->b_linep){
++ if ((Pmaster)
++ && (llength(curwp->w_dotp) == 3)
++ && (lgetc(curwp->w_dotp, 0).c == '-')
++ && (lgetc(curwp->w_dotp, 1).c == '-')
++ && (lgetc(curwp->w_dotp, 2).c == ' ')){
++ if (curwp->w_dotp == currline){
++ if (curwp->w_doto)
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ else
++ break;
++ }
++ else{
++ curwp->w_dotp = lback(curwp->w_dotp);
++ curwp->w_doto = llength(curwp->w_dotp);
++ break;
++ }
++ }
++ else{
++ if(lforw(curwp->w_dotp) != curbp->b_linep)
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ else{
++ curwp->w_doto = llength(curwp->w_dotp);
++ break;
++ }
++ }
++ }
++ killregion(FALSE,1);
++ lastflag |= CFKILL;
++ if(firsttime == 0)
++ emlwrite("Deleted text can be recovered with the ^U command", NULL);
++ firsttime = 1;
++ return TRUE;
++ }
+
+ /*
+ * Scroll to a position.
+diff -rc alpine-2.00/pico/bind.c alpine-2.00.I.USE/pico/bind.c
+*** alpine-2.00/pico/bind.c 2007-12-07 15:45:22.000000000 -0800
+--- alpine-2.00.I.USE/pico/bind.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 132,139 ****
+ }
+
+ if(Pmaster){
+- VARS_TO_SAVE *saved_state;
+-
+ saved_state = save_pico_state();
+ (*Pmaster->helper)(Pmaster->composer_help,
+ Pmaster->headents
+--- 132,137 ----
+diff -rc alpine-2.00/pico/blddate.c alpine-2.00.I.USE/pico/blddate.c
+*** alpine-2.00/pico/blddate.c 2006-11-22 14:50:13.000000000 -0800
+--- alpine-2.00.I.USE/pico/blddate.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 19,25 ****
+ char **argv;
+ {
+ struct tm *t;
+! FILE *outfile=stdout;
+ time_t ltime;
+
+ if(argc > 1 && (outfile = fopen(argv[1], "w")) == NULL){
+--- 19,25 ----
+ char **argv;
+ {
+ struct tm *t;
+! FILE *outfile=stdout, *infile;
+ time_t ltime;
+
+ if(argc > 1 && (outfile = fopen(argv[1], "w")) == NULL){
+***************
+*** 46,51 ****
+--- 46,57 ----
+ 1900 + t->tm_year);
+
+ fprintf(outfile, "char hoststamp[]=\"random-pc\";\n");
++ if((infile = fopen("../patchlevel", "r")) != NULL){
++ int c;
++ while ((c = getc(infile)) != EOF) putc(c, outfile);
++ fclose(infile);
++ }
++ else fprintf(outfile, "char plevstamp[]=\"No information available\";\n");
+
+ fclose(outfile);
+
+diff -rc alpine-2.00/pico/browse.c alpine-2.00.I.USE/pico/browse.c
+*** alpine-2.00/pico/browse.c 2008-02-26 15:07:15.000000000 -0800
+--- alpine-2.00.I.USE/pico/browse.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 931,938 ****
+ }
+
+ if(Pmaster){
+- VARS_TO_SAVE *saved_state;
+-
+ saved_state = save_pico_state();
+ (*Pmaster->helper)(Pmaster->browse_help,
+ _("Help for Browsing"), 1);
+--- 931,936 ----
+diff -rc alpine-2.00/pico/composer.c alpine-2.00.I.USE/pico/composer.c
+*** alpine-2.00/pico/composer.c 2008-03-21 14:31:58.000000000 -0700
+--- alpine-2.00.I.USE/pico/composer.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 93,98 ****
+--- 93,103 ----
+ */
+ struct on_display ods; /* global on_display struct */
+
++ /* a pointer to the subject line. This is so that we do not have to compute
++ * the header line in every call. It saves a few CPU cycles
++ */
++
++ struct hdr_line *subject_line = NULL;
+
+ /*
+ * useful macros
+***************
+*** 495,500 ****
+--- 500,510 ----
+ mswin_setscrollrange (0, 0);
+ #endif /* _WINDOWS */
+
++ if(Pmaster)
++ for (subject_line = NULL, i=0; headents[i].name; i++)
++ if(strcmp(headents[i].name, "Subject") == 0)
++ subject_line = headents[i].hd_text;
++
+ /*
+ * Decide where to begin editing. if f == TRUE begin editing
+ * at the bottom. this case results from the cursor backing
+***************
+*** 794,802 ****
+ len += lmp->fname ? strlen(lmp->fname) : 0;
+
+ if(len+3 > sizeof(buf)){
+- bfp = malloc(len+3);
+ space = len+3;
+! if((bfp=malloc(len+3)) == NULL){
+ emlwrite("\007Can't malloc space for filename",
+ NULL);
+ continue;
+--- 804,812 ----
+ len += lmp->fname ? strlen(lmp->fname) : 0;
+
+ if(len+3 > sizeof(buf)){
+ space = len+3;
+! bfp = malloc(space*sizeof(char));
+! if(bfp == NULL){
+ emlwrite("\007Can't malloc space for filename",
+ NULL);
+ continue;
+***************
+*** 1270,1278 ****
+ len += strlen(lmp->size);
+
+ if(len+3 > sizeof(buf)){
+- bfp = malloc(len+3);
+ space = len+3;
+! if((bfp=malloc(len+3)) == NULL){
+ emlwrite("\007Can't malloc space for filename",
+ NULL);
+ continue;
+--- 1280,1288 ----
+ len += strlen(lmp->size);
+
+ if(len+3 > sizeof(buf)){
+ space = len+3;
+! bfp = malloc(space*sizeof(char));
+! if(bfp == NULL){
+ emlwrite("\007Can't malloc space for filename",
+ NULL);
+ continue;
+***************
+*** 1309,1316 ****
+ zotlmlist(lm);
+ } /* else, nothing of interest */
+ } else if (headents[ods.cur_e].selector != NULL) {
+- VARS_TO_SAVE *saved_state;
+-
+ /*---- General selector for non-attachments -----*/
+
+ /*
+--- 1319,1324 ----
+***************
+*** 1485,1491 ****
+ struct hdr_line *line;
+ int sz = 0;
+ char *filename = NULL;
+- VARS_TO_SAVE *saved_state;
+
+ /*
+ * Since the fileedit will make a new call back to pico()
+--- 1493,1498 ----
+***************
+*** 1852,1857 ****
+--- 1859,1866 ----
+ }
+
+ UpdateHeader(0);
++ if(sendnow)
++ return(status !=0);
+ PaintHeader(COMPOSER_TOP_LINE, status != 0);
+ PaintBody(1);
+ return(status != 0);
+***************
+*** 1899,1904 ****
+--- 1908,1918 ----
+
+ while(1){ /* edit the line... */
+
++ if(Pmaster && subject_line != NULL
++ && ods.cur_l == subject_line
++ && ods.cur_l->text[0] == 0)
++ (*Pmaster->newthread)();
++
+ if(skipmove)
+ skipmove = 0;
+ else
+***************
+*** 1990,1996 ****
+ tbufp = &strng[ods.p_len];
+
+ if(VALID_KEY(ch)){ /* char input */
+! /*
+ * if we are allowing editing, insert the new char
+ * end up leaving tbufp pointing to newly
+ * inserted character in string, and offset to the
+--- 2004,2010 ----
+ tbufp = &strng[ods.p_len];
+
+ if(VALID_KEY(ch)){ /* char input */
+! insert_char:/*
+ * if we are allowing editing, insert the new char
+ * end up leaving tbufp pointing to newly
+ * inserted character in string, and offset to the
+***************
+*** 2070,2075 ****
+--- 2084,2096 ----
+ }
+ else { /* interpret ch as a command */
+ switch (ch = normalize_cmd(ch, ckm, 2)) {
++ case (CTRL|'\\') :
++ if (ch = GetAccent())
++ goto insert_char;
++ else
++ clearcursor();
++ break;
++
+ case (CTRL|KEY_LEFT): /* word skip left */
+ if(ods.p_ind > 0) /* Scoot one char left if possible */
+ ods.p_ind--;
+***************
+*** 2937,2943 ****
+ ComposerHelp(int level)
+ {
+ char buf[80];
+- VARS_TO_SAVE *saved_state;
+
+ curwp->w_flag |= WFMODE;
+ sgarbf = TRUE;
+--- 2958,2963 ----
+***************
+*** 3337,3342 ****
+--- 3357,3365 ----
+ {
+ UCS *bufp, *buf;
+
++ if (sendnow)
++ return;
++
+ if(ComposerTopLine - 1 >= BOTTOM()) /* silently forget it */
+ return;
+
+***************
+*** 3393,3398 ****
+--- 3416,3424 ----
+ UCS *end;
+ int i;
+
++ if (sendnow)
++ return(TRUE);
++
+ buf = utf8_to_ucs4_cpystr(headents[entry].prompt); /* fresh prompt paint */
+ if(!buf)
+ return(-1);
+***************
+*** 3606,3612 ****
+ char *tmp;
+ struct headerentry *e;
+ BUILDER_ARG *nextarg, *arg = NULL, *headarg = NULL;
+- VARS_TO_SAVE *saved_state;
+
+ if(!entry->builder)
+ return(0);
+--- 3632,3637 ----
+***************
+*** 3826,3832 ****
+ call_expander(void)
+ {
+ char **s = NULL;
+- VARS_TO_SAVE *saved_state;
+ int expret;
+
+ if(!Pmaster->expander)
+--- 3851,3856 ----
+***************
+*** 4348,4353 ****
+--- 4372,4380 ----
+ void
+ ShowPrompt(void)
+ {
++ if (sendnow)
++ return;
++
+ if(headents[ods.cur_e].key_label){
+ menu_header[TO_KEY].name = "^T";
+ menu_header[TO_KEY].label = headents[ods.cur_e].key_label;
+***************
+*** 4716,4721 ****
+--- 4743,4750 ----
+ free(state->opertree);
+
+ free(state);
++
++ state = NULL;
+ }
+
+
+diff -rc alpine-2.00/pico/display.c alpine-2.00.I.USE/pico/display.c
+*** alpine-2.00/pico/display.c 2008-03-26 10:27:45.000000000 -0700
+--- alpine-2.00.I.USE/pico/display.c 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 386,391 ****
+--- 386,394 ----
+ int scroll = 0;
+ CELL c;
+
++ if (sendnow)
++ return;
++
+ #if TYPEAH
+ if (typahead())
+ return;
+***************
+*** 915,921 ****
+ int nbflag; /* non-blanks to the right flag? */
+ int cleartoeol = 0;
+
+! if(row < 0 || row > term.t_nrow)
+ return;
+
+ /* set up pointers to virtual and physical lines */
+--- 918,924 ----
+ int nbflag; /* non-blanks to the right flag? */
+ int cleartoeol = 0;
+
+! if(row < 0 || row > term.t_nrow || sendnow)
+ return;
+
+ /* set up pointers to virtual and physical lines */
+***************
+*** 1284,1290 ****
+ void
+ mlerase(void)
+ {
+! if (term.t_nrow < term.t_mrow)
+ return;
+
+ movecursor(term.t_nrow - term.t_mrow, 0);
+--- 1287,1293 ----
+ void
+ mlerase(void)
+ {
+! if (term.t_nrow < term.t_mrow || sendnow)
+ return;
+
+ movecursor(term.t_nrow - term.t_mrow, 0);
+***************
+*** 1359,1364 ****
+--- 1362,1371 ----
+ menu_yesno[6].label = N_("Cancel");
+ menu_yesno[7].name = "N";
+ menu_yesno[7].label = (dflt == FALSE) ? "[" N_("No") "]" : N_("No");
++ if(Pmaster && Pmaster->onctrlc){
++ menu_yesno[8].name = "T";
++ menu_yesno[8].label = N_("counT");
++ }
+ wkeyhelp(menu_yesno); /* paint generic menu */
+ sgarbk = TRUE; /* mark menu dirty */
+ if(Pmaster && curwp)
+***************
+*** 1437,1442 ****
+--- 1444,1457 ----
+ km_popped++;
+ break;
+ }
++
++ case 'T':
++ case 't':
++ if(Pmaster && Pmaster->onctrlc){
++ pputs_utf8(_("counT"), 1);
++ rv = COUNT;
++ break;
++ }
+ /* else fall through */
+
+ default:
+***************
+*** 1750,1755 ****
+--- 1765,1775 ----
+ b = &buf[ucs4_strlen(buf)];
+ continue;
+
++ case (CTRL|'\\'):
++ if (c = GetAccent())
++ goto text;
++ continue;
++
+ case (CTRL|'F') : /* CTRL-F forward a char*/
+ case KEY_RIGHT :
+ if(*b == '\0')
+***************
+*** 1759,1764 ****
+--- 1779,1796 ----
+
+ continue;
+
++ case (CTRL|'N'): /* Insert pattern */
++ if (pat[0] != '\0'){
++ ucs4_strncpy(buf+ucs4_strlen(buf), pat, NPAT);
++ pputs(pat,1);
++ b = &buf[ucs4_strlen(buf)];
++ dline.vused += ucs4_strlen(pat);
++ changed = TRUE;
++ }
++ else
++ (*term.t_beep)();
++ continue;
++
+ case (CTRL|'G') : /* CTRL-G help */
+ if(term.t_mrow == 0 && km_popped == 0){
+ movecursor(term.t_nrow-2, 0);
+***************
+*** 1868,1874 ****
+ #endif
+
+ default :
+!
+ /* look for match in extra_v */
+ for(i = 0; i < 12; i++)
+ if(c && c == extra_v[i]){
+--- 1900,1906 ----
+ #endif
+
+ default :
+! text:
+ /* look for match in extra_v */
+ for(i = 0; i < 12; i++)
+ if(c && c == extra_v[i]){
+***************
+*** 1962,1968 ****
+
+ mlerase();
+
+! if(!(message && *message) || term.t_nrow < 2)
+ return; /* nothing to write or no space to write, bag it */
+
+ bufp = message;
+--- 1994,2000 ----
+
+ mlerase();
+
+! if(!(message && *message) || term.t_nrow < 2 || sendnow)
+ return; /* nothing to write or no space to write, bag it */
+
+ bufp = message;
+***************
+*** 2151,2158 ****
+ }
+
+ ret = ttcol;
+! while(ttcol < term.t_ncol)
+! pputc(' ', 0);
+
+ movecursor(term.t_nrow - term.t_mrow, ret);
+
+--- 2183,2191 ----
+ }
+
+ ret = ttcol;
+! if(sendnow == 0)
+! while(ttcol < term.t_ncol)
+! pputc(' ', 0);
+
+ movecursor(term.t_nrow - term.t_mrow, ret);
+
+***************
+*** 2631,2636 ****
+--- 2664,2671 ----
+ {
+ int ind, width, printable_ascii = 0;
+
++ if(sendnow)
++ return;
+ /*
+ * This is necessary but not sufficient to allow us to draw. Note that
+ * ttrow runs from 0 to t_nrow (so total number of rows is t_nrow+1)
+***************
+*** 2685,2690 ****
+--- 2720,2727 ----
+ pputs(UCS *s, /* string to write */
+ int a) /* and its attribute */
+ {
++ if(sendnow)
++ return;
+ while (*s != '\0')
+ pputc(*s++, a);
+ }
+***************
+*** 2695,2700 ****
+--- 2732,2739 ----
+ {
+ UCS *ucsstr = NULL;
+
++ if(sendnow)
++ return;
+ if(s && *s){
+ ucsstr = utf8_to_ucs4_cpystr(s);
+ if(ucsstr){
+***************
+*** 2995,3000 ****
+--- 3034,3042 ----
+ char nbuf[NLINE];
+ #endif
+
++ if(sendnow)
++ return;
++
+ #ifdef _WINDOWS
+ pico_config_menu_items (keymenu);
+ #endif
+diff -rc alpine-2.00/pico/ebind.h alpine-2.00.I.USE/pico/ebind.h
+*** alpine-2.00/pico/ebind.h 2007-11-06 15:51:13.000000000 -0800
+--- alpine-2.00.I.USE/pico/ebind.h 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 61,67 ****
+ #ifdef MOUSE
+ {KEY_MOUSE, mousepress},
+ #ifndef _WINDOWS
+! {CTRL|'\\', toggle_xterm_mouse},
+ #endif
+ #endif
+ {CTRL|'A', gotobol},
+--- 61,67 ----
+ #ifdef MOUSE
+ {KEY_MOUSE, mousepress},
+ #ifndef _WINDOWS
+! {CTRL|'|', toggle_xterm_mouse},
+ #endif
+ #endif
+ {CTRL|'A', gotobol},
+***************
+*** 100,106 ****
+ {CTRL|KEY_HOME, gotobob},
+ {CTRL|KEY_END, gotoeob},
+ {0x7F, backdel},
+! {0, NULL}
+ };
+
+
+--- 100,108 ----
+ {CTRL|KEY_HOME, gotobob},
+ {CTRL|KEY_END, gotoeob},
+ {0x7F, backdel},
+! {CTRL|'\\', pineaccent},
+! {0,
+! NULL}
+ };
+
+
+***************
+*** 123,129 ****
+ #ifdef MOUSE
+ {KEY_MOUSE, mousepress},
+ #ifndef _WINDOWS
+! {CTRL|'\\', toggle_xterm_mouse},
+ #endif
+ #endif
+ {CTRL|'A', gotobol},
+--- 125,131 ----
+ #ifdef MOUSE
+ {KEY_MOUSE, mousepress},
+ #ifndef _WINDOWS
+! {CTRL|'|', toggle_xterm_mouse},
+ #endif
+ #endif
+ {CTRL|'A', gotobol},
+diff -rc alpine-2.00/pico/edef.h alpine-2.00.I.USE/pico/edef.h
+*** alpine-2.00/pico/edef.h 2008-01-04 16:41:49.000000000 -0800
+--- alpine-2.00.I.USE/pico/edef.h 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 32,37 ****
+--- 32,38 ----
+
+ /* initialized global definitions */
+
++ int sendnow = 0; /* should we send now */
+ int fillcol = 72; /* Current fill column */
+ int userfillcol = -1; /* Fillcol set from cmd line */
+ UCS pat[NPAT]; /* Search pattern */
+***************
+*** 55,60 ****
+--- 56,62 ----
+ char *keyboard_character_set = NULL;
+ UCS *glo_wordseps = NULL; /* points to word separators if set */
+ char *glo_wordseps_orig = NULL;
++ VARS_TO_SAVE *saved_state = NULL;
+
+ /* uninitialized global definitions */
+ int currow; /* Cursor row */
+***************
+*** 84,89 ****
+--- 86,92 ----
+
+ /* initialized global external declarations */
+
++ extern int sendnow; /* should we send now */
+ extern int fillcol; /* Fill column */
+ extern int userfillcol; /* Fillcol set from cmd line */
+ extern UCS pat[]; /* Search pattern */
+***************
+*** 149,154 ****
+--- 152,158 ----
+ extern KBESC_T *kbesc; /* keyboard esc sequence trie */
+ #endif /* HAS_TERMCAP/HAS_TERMINFO/VMS */
+ extern void *input_cs; /* passed to mbtow() via kbseq() */
++ extern VARS_TO_SAVE *saved_state;
+
+ #endif /* maindef */
+
+diff -rc alpine-2.00/pico/efunc.h alpine-2.00.I.USE/pico/efunc.h
+*** alpine-2.00/pico/efunc.h 2007-11-06 15:51:13.000000000 -0800
+--- alpine-2.00.I.USE/pico/efunc.h 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 53,60 ****
+--- 53,64 ----
+ extern int backline(int, int);
+ extern int gotobop(int, int);
+ extern int gotoeop(int, int);
++ extern int pineaccent(int, int);
++ extern unsigned char accent(UCS, UCS);
++ extern unsigned char GetAccent(void);
+ extern int forwpage(int, int);
+ extern int backpage(int, int);
++ extern int deltext (int, int);
+ extern int scrollupline(int, int);
+ extern int scrolldownline(int, int);
+ extern int scrollto(int, int);
+***************
+*** 248,257 ****
+ extern int fillpara(int, int);
+ extern int fillbuf(int, int);
+ extern int inword(void);
+! extern int quote_match(UCS *, LINE *, UCS *, size_t);
+ extern int ucs4_isalnum(UCS);
+ extern int ucs4_isalpha(UCS);
+ extern int ucs4_isspace(UCS);
+ extern int ucs4_ispunct(UCS);
+
+ #endif /* EFUNC_H */
+--- 252,268 ----
+ extern int fillpara(int, int);
+ extern int fillbuf(int, int);
+ extern int inword(void);
+! extern int quote_match(char *, LINE *, char *, size_t, int);
+! extern char *default_qstr(void);
+! extern void flatten_qstring(QSTRING_S *, char *, int);
+! extern void free_qs(QSTRING_S **);
+! extern QSTRING_S *do_quote_match (char *, char *, char *, char *, char *, int, int);
+! extern QSTRING_S *do_raw_quote_match(char *, char *, char *, char *, QSTRING_S **, QSTRING_S **);
+! extern int indent_match(char *, LINE *, char *, int, int);
+ extern int ucs4_isalnum(UCS);
+ extern int ucs4_isalpha(UCS);
+ extern int ucs4_isspace(UCS);
+ extern int ucs4_ispunct(UCS);
+
+ #endif /* EFUNC_H */
++
+diff -rc alpine-2.00/pico/file.c alpine-2.00.I.USE/pico/file.c
+*** alpine-2.00/pico/file.c 2008-06-11 10:21:24.000000000 -0700
+--- alpine-2.00.I.USE/pico/file.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 331,338 ****
+ #endif /* !(DOS || MAC) */
+ case HELPCH:
+ if(Pmaster){
+- VARS_TO_SAVE *saved_state;
+-
+ saved_state = save_pico_state();
+ (*Pmaster->helper)(msg ? Pmaster->ins_m_help
+ : Pmaster->ins_help,
+--- 331,336 ----
+diff -rc alpine-2.00/pico/line.c alpine-2.00.I.USE/pico/line.c
+*** alpine-2.00/pico/line.c 2007-08-15 16:07:18.000000000 -0700
+--- alpine-2.00.I.USE/pico/line.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 607,620 ****
+ lisblank(LINE *line)
+ {
+ int n = 0;
+! UCS qstr[NLINE];
+
+! n = (glo_quote_str
+! && quote_match(glo_quote_str, line, qstr, NLINE))
+! ? ucs4_strlen(qstr) : 0;
+
+ for(; n < llength(line); n++)
+! if(!ucs4_isspace(lgetc(line, n).c))
+ return(FALSE);
+
+ return(TRUE);
+--- 607,618 ----
+ lisblank(LINE *line)
+ {
+ int n = 0;
+! char qstr[NLINE];
+
+! n = quote_match(default_qstr(), line, qstr, NLINE, 1);
+
+ for(; n < llength(line); n++)
+! if(!ISspace(lgetc(line, n).c))
+ return(FALSE);
+
+ return(TRUE);
+diff -rc alpine-2.00/pico/main.c alpine-2.00.I.USE/pico/main.c
+*** alpine-2.00/pico/main.c 2008-04-02 15:09:20.000000000 -0700
+--- alpine-2.00.I.USE/pico/main.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 162,167 ****
+--- 162,168 ----
+ char *file_to_edit = NULL;
+ char *display_charmap = NULL;
+ char *keyboard_charmap = NULL;
++ int line_information_on = FALSE;
+ int use_system = 0;
+ char *err = NULL;
+
+***************
+*** 187,193 ****
+ if(display_character_set)
+ display_charmap = cpstr(display_character_set);
+ #if HAVE_LANGINFO_H && defined(CODESET)
+! else
+ display_charmap = cpstr(nl_langinfo_codeset_wrapper());
+ #endif
+
+--- 188,194 ----
+ if(display_character_set)
+ display_charmap = cpstr(display_character_set);
+ #if HAVE_LANGINFO_H && defined(CODESET)
+! else if (nl_langinfo_codeset_wrapper() != NULL)
+ display_charmap = cpstr(nl_langinfo_codeset_wrapper());
+ #endif
+
+***************
+*** 415,420 ****
+--- 416,427 ----
+ emlwrite(_("You may possibly have new mail."), NULL);
+ }
+
++ if (c == (CTRL|'\\')){
++ c = GetAccent();
++ if (!c)
++ c = NODATA;
++ }
++
+ if(km_popped)
+ switch(c){
+ case NODATA:
+***************
+*** 436,449 ****
+ mlerase();
+ }
+
+! f = FALSE;
+ n = 1;
+
+ #ifdef MOUSE
+ clear_mfunc(mouse_in_content);
+ #endif
+ /* Do it. */
+ execute(normalize_cmd(c, fkm, 1), f, n);
+ }
+ }
+
+--- 443,471 ----
+ mlerase();
+ }
+
+! f = (c == (CTRL|'J'));
+ n = 1;
++ if (!line_information_on)
++ line_information_on = (c == (CTRL|'C'));
++ else
++ line_information_on = ((c == KEY_DOWN) || (c == KEY_UP) ||
++ (c == KEY_RIGHT) || (c == KEY_LEFT) ||
++ (c == (CTRL|'V')) || (c == (CTRL|'Y')) ||
++ (c == (CTRL|'D')) || (c == (CTRL|'F')) ||
++ (c == (CTRL|'B')) || (c == (CTRL|'N')) ||
++ (c == (CTRL|'P')) || (c == (CTRL|'A')) ||
++ (c == (CTRL|'E')) || (c == (CTRL|'U')))
++ && (c != (CTRL|'C'));
+
+ #ifdef MOUSE
+ clear_mfunc(mouse_in_content);
+ #endif
+ /* Do it. */
+ execute(normalize_cmd(c, fkm, 1), f, n);
++ if (line_information_on){
++ c = (CTRL|'C');
++ execute(normalize_cmd(c, fkm, 1), f, n);
++ }
+ }
+ }
+
+diff -rc alpine-2.00/pico/osdep/getkey.c alpine-2.00.I.USE/pico/osdep/getkey.c
+*** alpine-2.00/pico/osdep/getkey.c 2007-08-20 12:46:37.000000000 -0700
+--- alpine-2.00.I.USE/pico/osdep/getkey.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 130,135 ****
+--- 130,145 ----
+ {
+ UCS ch, status, cc;
+
++ if(sendnow){
++ ch = Pmaster && Pmaster->auto_cmds && *Pmaster->auto_cmds
++ ? *Pmaster->auto_cmds++ : NODATA;
++
++ if (ch >= 0x00 && ch <= 0x1F)
++ ch = CTRL | (ch+'@');
++
++ return(ch);
++ }
++
+ if(!ReadyForKey(FUDGE-5))
+ return(NODATA);
+
+diff -rc alpine-2.00/pico/osdep/terminal.c alpine-2.00.I.USE/pico/osdep/terminal.c
+*** alpine-2.00/pico/osdep/terminal.c 2008-01-29 15:21:10.000000000 -0800
+--- alpine-2.00.I.USE/pico/osdep/terminal.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 25,30 ****
+--- 25,31 ----
+ #include "../keydefs.h"
+ #include "../pico.h"
+ #include "../mode.h"
++ #include "../edef.h"
+
+ #include "raw.h"
+ #include "color.h"
+***************
+*** 477,482 ****
+--- 478,489 ----
+ {
+ int row, col;
+
++ if (sendnow){
++ term.t_nrow = 23;
++ term.t_ncol = 80;
++ return 0;
++ }
++
+ /*
+ * determine the terminal's communication speed and decide
+ * if we need to do optimization ...
+***************
+*** 1252,1257 ****
+--- 1259,1270 ----
+ {
+ int row, col;
+
++ if (sendnow){
++ term.t_nrow = 23;
++ term.t_ncol = 80;
++ return 0;
++ }
++
+ /*
+ * determine the terminal's communication speed and decide
+ * if we need to do optimization ...
+diff -rc alpine-2.00/pico/osdep/tty.c alpine-2.00.I.USE/pico/osdep/tty.c
+*** alpine-2.00/pico/osdep/tty.c 2007-08-15 16:07:18.000000000 -0700
+--- alpine-2.00.I.USE/pico/osdep/tty.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 223,229 ****
+ int row = -1, col = -1;
+
+ ttgetwinsz(&row, &col);
+! resize_pico(row, col);
+ }
+
+
+--- 223,236 ----
+ int row = -1, col = -1;
+
+ ttgetwinsz(&row, &col);
+! if(saved_state == NULL || wheadp != NULL)
+! resize_pico(row, col);
+! else{ /* this is awkward */
+! restore_pico_state(saved_state);
+! free_pico_state(saved_state);
+! resize_pico(row,col);
+! saved_state = save_pico_state();
+! }
+ }
+
+
+diff -rc alpine-2.00/pico/pico.c alpine-2.00.I.USE/pico/pico.c
+*** alpine-2.00/pico/pico.c 2008-01-30 16:44:12.000000000 -0800
+--- alpine-2.00.I.USE/pico/pico.c 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 137,142 ****
+--- 137,151 ----
+ pico_all_done = 0;
+ km_popped = 0;
+
++ if (pm->auto_cmds){
++ int i;
++ #define CTRL_X 24
++ for (i = 0; pm->auto_cmds[i]; i++);
++ if ((i > 1) && (pm->auto_cmds[i - 2] == CTRL_X) &&
++ ((pm->auto_cmds[i - 1] == 'y') || (pm->auto_cmds[i-1] == 'Y')))
++ sendnow++;
++ }
++
+ if(!vtinit()) /* Init Displays. */
+ return(COMP_CANCEL);
+
+***************
+*** 637,648 ****
+ result = "";
+
+ Pmaster->arm_winch_cleanup++;
+ if(Pmaster->canceltest){
+ if(((Pmaster->pine_flags & MDHDRONLY) && !any_header_changes())
+ || (result = (*Pmaster->canceltest)(redraw_pico_for_callback))){
+- pico_all_done = COMP_CANCEL;
+ emlwrite(result, NULL);
+ Pmaster->arm_winch_cleanup--;
+ return(TRUE);
+ }
+ else{
+--- 646,664 ----
+ result = "";
+
+ Pmaster->arm_winch_cleanup++;
++ Pmaster->onctrlc++;
+ if(Pmaster->canceltest){
+ if(((Pmaster->pine_flags & MDHDRONLY) && !any_header_changes())
+ || (result = (*Pmaster->canceltest)(redraw_pico_for_callback))){
+ emlwrite(result, NULL);
+ Pmaster->arm_winch_cleanup--;
++ if(Pmaster->curpos[0]){
++ curwp->w_flag |= WFMODE; /* and modeline so we */
++ sgarbk = TRUE; /* redraw the keymenu */
++ pclear(term.t_nrow - 1, term.t_nrow + 1);
++ return(FALSE);
++ }
++ pico_all_done = COMP_CANCEL;
+ return(TRUE);
+ }
+ else{
+***************
+*** 671,676 ****
+--- 687,698 ----
+ emlwrite(_("\007Cancel Cancelled"), NULL);
+ break;
+
++ case COUNT:
++ showcpos(1,0);
++ emlwrite(Pmaster->curpos, NULL);
++ Pmaster->onctrlc--;
++ break;
++
+ default:
+ mlerase();
+ }
+***************
+*** 713,718 ****
+--- 735,753 ----
+ return(FALSE);
+ }
+
++ /* When we send a message using the command line we are going to
++ ignore if the user wants to spell check, we assume he already
++ did */
++ if (sendnow){
++ ret = (*Pmaster->exittest)(Pmaster->headents,
++ redraw_pico_for_callback,
++ Pmaster->allow_flowed_text,
++ &result);
++ if (!ret)
++ pico_all_done = COMP_EXIT;
++ return(result ? FALSE : TRUE);
++ }
++
+ #ifdef SPELLER
+ if(Pmaster->always_spell_check)
+ if(spell(0, 0) == -1)
+diff -rc alpine-2.00/pico/pico.h alpine-2.00.I.USE/pico/pico.h
+*** alpine-2.00/pico/pico.h 2008-08-22 13:40:16.000000000 -0700
+--- alpine-2.00.I.USE/pico/pico.h 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 198,208 ****
+--- 198,210 ----
+ PCOLORS *colors; /* colors for titlebar and keymenu */
+ void *input_cs; /* passed to mbtow() via kbseq() */
+ long pine_flags; /* entry mode flags */
++ char curpos[80]; /* where are we now? */
+ /* The next few bits are features that don't fit in pine_flags */
+ /* If we had this to do over, it would probably be one giant bitmap */
+ unsigned always_spell_check:1; /* always spell-checking upon quit */
+ unsigned strip_ws_before_send:1; /* don't default strip bc of flowed */
+ unsigned allow_flowed_text:1; /* clean text when done to keep flowed */
++ unsigned onctrlc; /* are we on ctrl-c command? */
+ int (*helper)(); /* Pine's help function */
+ int (*showmsg)(); /* Pine's display_message */
+ UCS (*suspend)(); /* Pine's suspend */
+***************
+*** 219,225 ****
+--- 221,229 ----
+ int (*user_says_noflow)(); /* callback to tell us we're not flowing */
+ void (*resize)(); /* callback handling screen resize */
+ void (*winch_cleanup)(); /* callback handling screen resize */
++ void (*newthread)(); /* callback to create new thread */
+ int arm_winch_cleanup; /* do the winch_cleanup if resized */
++ int *auto_cmds; /* Initial keystroke commands */
+ HELP_T search_help;
+ HELP_T ins_help;
+ HELP_T ins_m_help;
+diff -rc alpine-2.00/pico/pilot.c alpine-2.00.I.USE/pico/pilot.c
+*** alpine-2.00/pico/pilot.c 2008-04-02 15:09:20.000000000 -0700
+--- alpine-2.00.I.USE/pico/pilot.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 142,148 ****
+ if(display_character_set)
+ display_charmap = cpstr(display_character_set);
+ #if HAVE_LANGINFO_H && defined(CODESET)
+! else
+ display_charmap = cpstr(nl_langinfo_codeset_wrapper());
+ #endif
+
+--- 142,148 ----
+ if(display_character_set)
+ display_charmap = cpstr(display_character_set);
+ #if HAVE_LANGINFO_H && defined(CODESET)
+! else if (nl_langinfo_codeset_wrapper() != NULL)
+ display_charmap = cpstr(nl_langinfo_codeset_wrapper());
+ #endif
+
+diff -rc alpine-2.00/pico/random.c alpine-2.00.I.USE/pico/random.c
+*** alpine-2.00/pico/random.c 2007-08-15 16:07:18.000000000 -0700
+--- alpine-2.00.I.USE/pico/random.c 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 73,79 ****
+ thisline+1, lines+1, (int)((100L*(thisline+1))/(lines+1)),
+ nbc, nch, (nch) ? (int)((100L*nbc)/nch) : 0);
+
+! emlwrite(buffer, NULL);
+ return (TRUE);
+ }
+
+--- 73,82 ----
+ thisline+1, lines+1, (int)((100L*(thisline+1))/(lines+1)),
+ nbc, nch, (nch) ? (int)((100L*nbc)/nch) : 0);
+
+! if(Pmaster)
+! strcpy(Pmaster->curpos, buffer);
+! else
+! emlwrite(buffer, NULL);
+ return (TRUE);
+ }
+
+diff -rc alpine-2.00/pico/search.c alpine-2.00.I.USE/pico/search.c
+*** alpine-2.00/pico/search.c 2008-01-04 14:49:15.000000000 -0800
+--- alpine-2.00.I.USE/pico/search.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 35,41 ****
+ int readpattern(char *, int);
+ int replace_pat(UCS *, int *);
+ int replace_all(UCS *, UCS *);
+!
+
+ #define FWS_RETURN(RV) { \
+ thisflag |= CFSRCH; \
+--- 35,41 ----
+ int readpattern(char *, int);
+ int replace_pat(UCS *, int *);
+ int replace_all(UCS *, UCS *);
+! int deletepara(int, int);
+
+ #define FWS_RETURN(RV) { \
+ thisflag |= CFSRCH; \
+***************
+*** 75,80 ****
+--- 75,84 ----
+ N_("~ Hitting only ~R~e~t~u~r~n or at the prompt will cause the"),
+ N_(" search to be made with the default value."),
+ " ",
++ N_("~ Hitting ~^~N will reinsert the last string you searched for"),
++ N_(" so that you can edit it (in case you made a mistake entering the"),
++ N_(" search pattern the first time)."),
++ " ",
+ N_(" The text search is not case sensitive, and will examine the"),
+ N_(" entire message."),
+ " ",
+***************
+*** 139,146 ****
+
+ case HELPCH: /* help requested */
+ if(Pmaster){
+- VARS_TO_SAVE *saved_state;
+-
+ saved_state = save_pico_state();
+ (*Pmaster->helper)(Pmaster->search_help,
+ _("Help for Searching"), 1);
+--- 143,148 ----
+***************
+*** 231,240 ****
+--- 233,251 ----
+ mlerase();
+ FWS_RETURN(TRUE);
+
++ case (CTRL|'P'):
++ deletepara(0, 1);
++ mlerase();
++ FWS_RETURN(TRUE);
++
+ case (CTRL|'R'): /* toggle replacement option */
+ repl_mode = !repl_mode;
+ break;
+
++ case (CTRL|'X'):
++ deltext(f,n);
++ FWS_RETURN(TRUE);
++
+ default:
+ if(status == ABORT)
+ emlwrite(_("Search Cancelled"), NULL);
+***************
+*** 273,279 ****
+ }
+
+ if(status + curwp->w_doto >= llength(curwp->w_dotp) ||
+! !eq(defpat[status],lgetc(curwp->w_dotp, curwp->w_doto + status).c))
+ break; /* do nothing! */
+ status++;
+ }
+--- 284,290 ----
+ }
+
+ if(status + curwp->w_doto >= llength(curwp->w_dotp) ||
+! !eq((unsigned char)defpat[status],lgetc(curwp->w_dotp, curwp->w_doto + status).c))
+ break; /* do nothing! */
+ status++;
+ }
+***************
+*** 430,437 ****
+
+ case HELPCH: /* help requested */
+ if(Pmaster){
+- VARS_TO_SAVE *saved_state;
+-
+ saved_state = save_pico_state();
+ (*Pmaster->helper)(Pmaster->search_help,
+ _("Help for Searching"), 1);
+--- 441,446 ----
+***************
+*** 463,470 ****
+ break;
+
+ default:
+! if(status == ABORT)
+ emlwrite(_("Replacement Cancelled"), NULL);
+ else{
+ mlerase();
+ chword(defpat, origpat);
+--- 472,481 ----
+ break;
+
+ default:
+! if(status == ABORT){
+ emlwrite(_("Replacement Cancelled"), NULL);
++ pico_refresh(FALSE, 1);
++ }
+ else{
+ mlerase();
+ chword(defpat, origpat);
+***************
+*** 597,603 ****
+ UCS *b;
+ UCS prompt[NPMT];
+ UCS *promptp;
+! EXTRAKEYS menu_pat[8];
+
+ menu_pat[i = 0].name = "^Y";
+ menu_pat[i].label = N_("FirstLine");
+--- 608,614 ----
+ UCS *b;
+ UCS prompt[NPMT];
+ UCS *promptp;
+! EXTRAKEYS menu_pat[10];
+
+ menu_pat[i = 0].name = "^Y";
+ menu_pat[i].label = N_("FirstLine");
+***************
+*** 615,620 ****
+--- 626,636 ----
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
+ if(!repl_mode){
++ menu_pat[++i].name = "^X";
++ menu_pat[i].label = N_("DelEnd");
++ menu_pat[i].key = (CTRL|'X');
++ KS_OSDATASET(&menu_pat[i], KS_NONE);
++
+ menu_pat[++i].name = "^T";
+ menu_pat[i].label = N_("LineNumber");
+ menu_pat[i].key = (CTRL|'T');
+***************
+*** 631,636 ****
+--- 647,657 ----
+ menu_pat[i].key = (CTRL|'O');
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
++ menu_pat[++i].name = "^P";
++ menu_pat[i].label = N_("Delete Para");
++ menu_pat[i].key = (CTRL|'P');
++ KS_OSDATASET(&menu_pat[i], KS_NONE);
++
+ menu_pat[++i].name = "^U";
+ /* TRANSLATORS: Instead of justifying (formatting) just a
+ single paragraph, Full Justify justifies the entire
+***************
+*** 766,772 ****
+ UCS *b;
+ UCS tpat[NPAT+20];
+ UCS *tpatp;
+! EXTRAKEYS menu_pat[7];
+
+ menu_pat[i = 0].name = "^Y";
+ menu_pat[i].label = N_("FirstLine");
+--- 787,793 ----
+ UCS *b;
+ UCS tpat[NPAT+20];
+ UCS *tpatp;
+! EXTRAKEYS menu_pat[9];
+
+ menu_pat[i = 0].name = "^Y";
+ menu_pat[i].label = N_("FirstLine");
+***************
+*** 779,784 ****
+--- 800,810 ----
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
+ if(text_mode){
++ menu_pat[++i].name = "^X";
++ menu_pat[i].label = N_("DelEnd");
++ menu_pat[i].key = (CTRL|'X');
++ KS_OSDATASET(&menu_pat[i], KS_NONE);
++
+ menu_pat[++i].name = "^T";
+ menu_pat[i].label = N_("LineNumber");
+ menu_pat[i].key = (CTRL|'T');
+***************
+*** 794,799 ****
+--- 820,830 ----
+ menu_pat[i].key = (CTRL|'O');
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
++ menu_pat[++i].name = "^P";
++ menu_pat[i].label = N_("Delete Para");
++ menu_pat[i].key = (CTRL|'P');
++ KS_OSDATASET(&menu_pat[i], KS_NONE);
++
+ menu_pat[++i].name = "^U";
+ menu_pat[i].label = N_("FullJustify");
+ menu_pat[i].key = (CTRL|'U');
+***************
+*** 924,930 ****
+ c = lgetc(curline, curoff++).c; /* get the char */
+
+ /* test it against first char in pattern */
+! if (eq(c, patrn[0]) != FALSE) { /* if we find it..*/
+ /* setup match pointers */
+ matchline = curline;
+ matchoff = curoff;
+--- 955,961 ----
+ c = lgetc(curline, curoff++).c; /* get the char */
+
+ /* test it against first char in pattern */
+! if (eq(c, (unsigned char)patrn[0]) != FALSE) { /* if we find it..*/
+ /* setup match pointers */
+ matchline = curline;
+ matchoff = curoff;
+***************
+*** 945,951 ****
+ return(FALSE);
+
+ /* and test it against the pattern */
+! if (eq(*patptr, c) == FALSE)
+ goto fail;
+ }
+
+--- 976,982 ----
+ return(FALSE);
+
+ /* and test it against the pattern */
+! if (eq((unsigned char) *patptr, c) == FALSE)
+ goto fail;
+ }
+
+***************
+*** 1032,1034 ****
+--- 1063,1087 ----
+
+ curwp->w_flag |= WFEDIT;
+ }
++
++ int
++ deletepara(int f, int n) /* Delete the current paragraph */
++ {
++ if(curbp->b_mode&MDVIEW) /* don't allow this command if */
++ return(rdonly()); /* we are in read only mode */
++
++ if(!lisblank(curwp->w_dotp))
++ gotobop(FALSE, 1);
++
++ curwp->w_markp = curwp->w_dotp;
++ curwp->w_marko = 0;
++
++ gotoeop(FALSE, 1);
++ if (curwp->w_dotp != curbp->b_linep){ /* if we are not at the end of buffer */
++ curwp->w_dotp = lforw(curwp->w_dotp); /* get one more line */
++ curwp->w_doto = 0; /* but only the beginning */
++ }
++ killregion(f,n);
++ return(TRUE);
++ }
++
+diff -rc alpine-2.00/pico/word.c alpine-2.00.I.USE/pico/word.c
+*** alpine-2.00/pico/word.c 2007-08-20 12:46:37.000000000 -0700
+--- alpine-2.00.I.USE/pico/word.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 24,33 ****
+ */
+
+ #include "headers.h"
+!
+
+ int fpnewline(UCS *quote);
+! int fillregion(UCS *qstr, REGION *addedregion);
+ int setquotelevelinregion(int quotelevel, REGION *addedregion);
+ int is_user_separator(UCS c);
+
+--- 24,33 ----
+ */
+
+ #include "headers.h"
+! #include "../pith/osdep/color.h"
+
+ int fpnewline(UCS *quote);
+! int fillregion(UCS *qstr, UCS *istr, REGION *addedregion);
+ int setquotelevelinregion(int quotelevel, REGION *addedregion);
+ int is_user_separator(UCS c);
+
+***************
+*** 430,471 ****
+ return 0;
+ }
+
+
+ /*
+ * Return number of quotes if whatever starts the line matches the quote string
+ */
+ int
+! quote_match(UCS *q, LINE *l, UCS *buf, size_t buflen)
+ {
+! register int i, n, j, qb;
+
+! *buf = '\0';
+! if(*q == '\0')
+! return(1);
+!
+! qb = (ucs4_strlen(q) > 1 && q[ucs4_strlen(q)-1] == ' ') ? 1 : 0;
+! for(n = 0, j = 0; ;){
+! for(i = 0; j <= llength(l) && qb ? q[i+1] : q[i]; i++, j++)
+! if(q[i] != lgetc(l, j).c)
+! return(n);
+!
+! n++;
+! if((!qb && q[i] == '\0') || (qb && q[i+1] == '\0')){
+! if(ucs4_strlen(buf) + ucs4_strlen(q) + 1 < buflen){
+! ucs4_strncat(buf, q, buflen-ucs4_strlen(q)-1);
+! buf[buflen-1] = '\0';
+! if(qb && (j > llength(l) || lgetc(l, j).c != ' '))
+! buf[ucs4_strlen(buf)-1] = '\0';
+! }
+! }
+! if(j > llength(l))
+! return(n);
+! else if(qb && lgetc(l, j).c == ' ')
+! j++;
+ }
+! return(n); /* never reached */
+ }
+
+
+ /* Justify the entire buffer instead of just a paragraph */
+ int
+--- 430,600 ----
+ return 0;
+ }
+
++ /* Support of indentation of paragraphs */
++ #define is_indent_char(c) (((c) == '.' || (c) == '}' || (c) == RPAREN || \
++ (c) == '*' || (c) == '+' || is_a_digit(c) || \
++ ISspace(c) || (c) == '-' || \
++ (c) == ']') ? 1 : 0)
++ #define allowed_after_digit(c,word,k) ((((c) == '.' && \
++ allowed_after_period(next((word),(k)))) ||\
++ (c) == RPAREN || (c) == '}' || (c) == ']' ||\
++ ISspace(c) || is_a_digit(c) || \
++ ((c) == '-' ) && \
++ allowed_after_dash(next((word),(k)))) \
++ ? 1 : 0)
++ #define allowed_after_period(c) (((c) == RPAREN || (c) == '}' || (c) == ']' ||\
++ ISspace(c) || (c) == '-' || \
++ is_a_digit(c)) ? 1 : 0)
++ #define allowed_after_parenth(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_space(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_braces(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_star(c) ((ISspace(c) || (c) == RPAREN ||\
++ (c) == ']' || (c) == '}') ? 1 : 0)
++ #define allowed_after_dash(c) ((ISspace(c) || is_a_digit(c)) ? 1 : 0)
++ #define EOLchar(c) (((c) == '.' || (c) == ':' || (c) == '?' ||\
++ (c) == '!') ? 1 : 0)
++
++ int indent_match(char *, LINE *, char *, int, int);
++
++ /* Extended justification support */
++ #define is_cquote(c) ((c) == '>' || (c) == '|' || (c) == ']' || (c) == ':')
++ #define is_cword(c) ((((c) >= 'a') && ((c) <= 'z')) || \
++ (((c) >= 'A') && ((c) <= 'Z')) || \
++ (((c) >= '0') && ((c) <= '9')) || \
++ ((c) == ' ') || ((c) == '?') || \
++ ((c) == '@') || ((c) == '.') || \
++ ((c) == '!') || ((c) == '\'') || \
++ ((c) == ',') || ((c) == '\"') ? 1 : 0)
++ #define isaquote(c) ((c) == '\"' || (c) == '\'')
++ #define is8bit(c) ((((int) (c)) & 0x80) ? 1 : 0)
++ #define iscontrol(c) (iscntrl(((int) (c)) & 0x7f) ? 1 : 0)
++ #define forbidden(c) (((c) == '\"') || ((c) == '\'') || ((c) == '$') ||\
++ ((c) == ',') || ((c) == '.') || ((c) == '-') ||\
++ ((c) == LPAREN) || ((c) == '/')|| ((c) == '`') ||\
++ ((c) == '{') || ((c) == '\\') || (iscontrol((c))) ||\
++ (((c) >= '0') && ((c) <= '9')) || ((c) == '?'))
++ #define is_cletter(c) ((((c) >= 'a') && ((c) <= 'z'))) ||\
++ ((((c) >= 'A') && ((c) <= 'Z'))||\
++ is8bit(c))
++ #define is_cnumber(c) ((c) >= '0' && (c) <= '9')
++ #define allwd_after_word(c) (((c) == ' ') || ((c) == '>') || is_cletter(c))
++ #define allwd_after_qsword(c) (((c) != '\\') && ((c) != RPAREN))
++ #define before(word,i) (((i) > 0) ? (word)[(i) - 1] : 0)
++ #define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0)
++ #define now(w,i) ((w)[(i)])
++ #define is_qsword(c) (((c) == ':') || ((c) == RPAREN) ? 1 : 0)
++ #define is_colon(c) (((c) == ':') ? 1 : 0)
++ #define is_rarrow(c) (((c) == '>') ? 1 : 0)
++ #define is_tilde(c) (((c) == '~') ? 1 : 0)
++ #define is_dash(c) (((c) == '-') ? 1 : 0)
++ #define is_pound(c) (((c) == '#') ? 1 : 0)
++ #define is_a_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
++ #define is_allowed(c) (is_cquote(c) || is_cword(c) || is_dash(c) || \
++ is_pound(c))
++ #define qs_allowed(a) (((a)->qstype != qsGdb) && ((a)->qstype != qsProg))
++
++ /* Internal justification functions */
++ QSTRING_S *qs_quote_match(char *, LINE *, char *, int);
++ int ucs4_strlenis(UCS *);
++ void linencpy(char *, LINE *, int);
++
++
++ char *
++ default_qstr(void)
++ {
++ char *default_qs;
++ static char ucs_def[NSTRING] = {'\0'};
++
++ if(ucs_def[0] == '\0'){
++ default_qs = ucs4_to_utf8_cpystr(glo_quote_str);
++ strncpy(ucs_def, (default_qs ? default_qs : ""), NSTRING);
++ fs_give((void **)&default_qs);
++ }
++
++ return glo_quote_str ? ucs_def : "";
++ }
++
++ void
++ linencpy(word, l, buflen)
++ char word[NSTRING];
++ LINE *l;
++ int buflen;
++ {
++ int i;
++ UCS ucs_word[NSTRING];
++ char *utf_word;
++
++ word[0] = '\0';
++ if(l){
++ for (i = 0; i < buflen && i < llength(l)
++ && (ucs_word[i] = lgetc(l,i).c); i++);
++ ucs_word[i == buflen ? i-1 : i] = '\0';
++ utf_word = ucs4_to_utf8_cpystr(ucs_word);
++ strncpy(word, utf_word, (NSTRING < buflen ? NSTRING : buflen));
++ word[NSTRING-1] = '\0';
++ if(utf_word) fs_give((void **)&utf_word);
++ }
++ }
++
++ /*
++ * This function returns the quote string as a structure. In this way we
++ * have two ways to get the quote string: as a char * or as a QSTRING_S *
++ * directly.
++ */
++ QSTRING_S *
++ qs_quote_match(char *q, LINE *l, char *rqstr, int rqstrlen)
++ {
++ char GLine[NSTRING], NLine[NSTRING], PLine[NSTRING];
++ LINE *nl = l != curbp->b_linep ? lforw(l) : NULL;
++ LINE *pl = lback(l) != curbp->b_linep ? lback(l) : NULL;
++ int plb = 1;
++
++ linencpy(GLine, l, NSTRING);
++ linencpy(NLine, nl, NSTRING);
++
++ if (pl){
++ linencpy(PLine, pl, NSTRING);
++ if(lback(pl) != curbp->b_linep){
++ char PPLine[NSTRING];
++
++ linencpy(PPLine, lback(pl), NSTRING);
++ plb = line_isblank(q, PLine, GLine, PPLine, NSTRING);
++ }
++ }
++ return do_quote_match(q, GLine, NLine, PLine, rqstr, rqstrlen, plb);
++ }
+
+ /*
+ * Return number of quotes if whatever starts the line matches the quote string
++ * rqstring is pointer to raw qstring, buf points to processed qstring
+ */
+ int
+! quote_match(char *q, LINE *l, char *buf, size_t buflen, int raw)
+ {
+! QSTRING_S *qs;
+! char rqstr[NSTRING];
+
+! qs = qs_quote_match(q, l, rqstr, NSTRING);
+! flatten_qstring(qs, buf, buflen);
+! if (qs)
+! free_qs(&qs);
+!
+! if(raw){
+! strncpy(buf, rqstr, buflen < NSTRING ? buflen : NSTRING);
+! buf[buflen-1] = '\0';
+ }
+!
+! return buf && buf[0] ? strlen(buf) : 0;
+ }
+
++ int ucs4_strlenis(UCS *ucs_qstr)
++ {
++ char *str = ucs4_to_utf8_cpystr(ucs_qstr);
++ int i = (int) strlenis(str);
++
++ if(str) fs_give((void **)&str);
++ return i;
++ }
+
+ /* Justify the entire buffer instead of just a paragraph */
+ int
+***************
+*** 720,725 ****
+--- 849,855 ----
+ }
+
+ if(action == 'R' && curwp->w_markp){
++ char qstrfl[NSTRING];
+ /* let yank() know that it may be restoring a paragraph */
+ thisflag |= CFFILL;
+
+***************
+*** 732,752 ****
+
+ /* determine if we're justifying quoted text or not */
+ qstr = (glo_quote_str
+! && quote_match(glo_quote_str,
+! curwp->w_doto > 0 ? curwp->w_dotp->l_fp : curwp->w_dotp,
+! qstr2, NSTRING)
+! && *qstr2) ? qstr2 : NULL;
+!
+
+ /*
+ * Fillregion moves dot to the end of the filled region.
+ */
+! if(!fillregion(qstr, &addedregion))
+ return(FALSE);
+
+ set_last_region_added(&addedregion);
+ }
+ else if(action == 'P'){
+
+ /*
+ * Justfiy the current paragraph.
+--- 862,886 ----
+
+ /* determine if we're justifying quoted text or not */
+ qstr = (glo_quote_str
+! && quote_match(default_qstr(),
+! (curwp->w_doto > 0 ? curwp->w_dotp->l_fp : curwp->w_dotp),
+! qstrfl, NSTRING, 0)
+! && *qstrfl) ? utf8_to_ucs4_cpystr(qstrfl) : NULL;
+
+ /*
+ * Fillregion moves dot to the end of the filled region.
+ */
+! if(!fillregion(qstr, NULL, &addedregion))
+ return(FALSE);
+
+ set_last_region_added(&addedregion);
++
++ if(qstr)
++ fs_give((void **)&qstr);
+ }
+ else if(action == 'P'){
++ char ind_str[NSTRING], qstrfl[NSTRING];
++ UCS *istr;
+
+ /*
+ * Justfiy the current paragraph.
+***************
+*** 758,774 ****
+ if(gotoeop(FALSE, 1) == FALSE)
+ return(FALSE);
+
+- /* determine if we're justifying quoted text or not */
+- qstr = (glo_quote_str
+- && quote_match(glo_quote_str,
+- curwp->w_dotp, qstr2, NSTRING)
+- && *qstr2) ? qstr2 : NULL;
+-
+ setmark(0,0); /* mark last line of para */
+
+ /* jump back to the beginning of the paragraph */
+ gotobop(FALSE, 1);
+
+ /* let yank() know that it may be restoring a paragraph */
+ thisflag |= (CFFILL | CFFLPA);
+
+--- 892,907 ----
+ if(gotoeop(FALSE, 1) == FALSE)
+ return(FALSE);
+
+ setmark(0,0); /* mark last line of para */
+
+ /* jump back to the beginning of the paragraph */
+ gotobop(FALSE, 1);
+
++ istr = indent_match(default_qstr(), curwp->w_dotp, ind_str, NSTRING, 0)
++ && *ind_str ? utf8_to_ucs4_cpystr(ind_str) : NULL;
++ qstr = (quote_match(default_qstr(), curwp->w_dotp, qstrfl, NSTRING, 0)
++ && *qstrfl) ? utf8_to_ucs4_cpystr(qstrfl) : NULL;
++
+ /* let yank() know that it may be restoring a paragraph */
+ thisflag |= (CFFILL | CFFLPA);
+
+***************
+*** 782,790 ****
+ /*
+ * Fillregion moves dot to the end of the filled region.
+ */
+! if(!fillregion(qstr, &addedregion))
+ return(FALSE);
+
+ set_last_region_added(&addedregion);
+
+ /* Leave cursor on first char of first line after justified region */
+--- 915,929 ----
+ /*
+ * Fillregion moves dot to the end of the filled region.
+ */
+! if(!fillregion(qstr, istr, &addedregion))
+ return(FALSE);
+
++ if(qstr)
++ fs_give((void **)&qstr);
++
++ if(istr)
++ fs_give((void **)&istr);
++
+ set_last_region_added(&addedregion);
+
+ /* Leave cursor on first char of first line after justified region */
+***************
+*** 826,841 ****
+ * can delete it and restore the saved part.
+ */
+ int
+! fillregion(UCS *qstr, REGION *addedregion)
+ {
+ long c, sz, last_char = 0;
+! int i, j, qlen, same_word,
+ spaces, word_len, word_ind, line_len, ww;
+ int starts_midline = 0;
+ int ends_midline = 0;
+ int offset_into_start;
+ LINE *line_before_start, *lp;
+! UCS line_last, word[NSTRING];
+ REGION region;
+
+ /* if region starts midline insert a newline */
+--- 965,980 ----
+ * can delete it and restore the saved part.
+ */
+ int
+! fillregion(UCS *qstr, UCS *istr, REGION *addedregion)
+ {
+ long c, sz, last_char = 0;
+! int i, j, qlen, same_word, qi, pqi, qlenis,
+ spaces, word_len, word_ind, line_len, ww;
+ int starts_midline = 0;
+ int ends_midline = 0;
+ int offset_into_start;
+ LINE *line_before_start, *lp;
+! UCS line_last, word[NSTRING], quoid[NSTRING], qstr2[NSTRING];
+ REGION region;
+
+ /* if region starts midline insert a newline */
+***************
+*** 846,851 ****
+--- 985,1019 ----
+ if(curwp->w_marko > 0 && curwp->w_marko < llength(curwp->w_markp))
+ ends_midline++;
+
++ for (i = 0; (i < NSTRING) && qstr && (quoid[i] = qstr[i]); i++);
++ for (j = 0; ((i + j) < NSTRING) && istr && (quoid[i] = istr[j]); i++,j++);
++ quoid[i] = '\0';
++ qi = ucs4_strlen(quoid);
++ if (istr) /* strip trailing spaces */
++ for (;ISspace(quoid[qi - 1]); qi--);
++ quoid[qi] = '\0'; /* we have closed quoid at "X" in the first line */
++
++ if (ucs4_strlenis(quoid) > fillcol)
++ return FALSE; /* Too wide, we can't justify this! */
++
++ if (qstr && istr){
++ for (i = ucs4_strlen(qstr) - 1; ISspace(qstr[i]); i--);
++ qstr[i + 1] = '\0'; /* qstrfl */
++ }
++ qlen = ucs4_strlen(qstr); /* qstrfl*/
++ qlenis = ucs4_strlenis(qstr);
++
++ for(i = 0, qstr2[0] = '\0'; qstr && qstr[i] && (qstr2[i] = qstr[i]); i++);
++
++ if (istr && ((j = ucs4_strlenis(quoid) - ucs4_strlenis(qstr)) > 0)){
++ pqi = ucs4_strlen(qstr);
++ for (i = 0; (i < j) && (qstr2[pqi + i] = ' '); i++);
++ if (ISspace(istr[ucs4_strlen(istr) - 1]))
++ qstr2[pqi + i++] = ' ';
++ qstr2[pqi + i] = '\0';
++ qstr = qstr2;
++ }
++
+ /* cut the paragraph into our fill buffer */
+ fdelete();
+ if(!getregion(&region, curwp->w_markp, curwp->w_marko))
+***************
+*** 862,889 ****
+
+ /* Now insert it back wrapped */
+ spaces = word_len = word_ind = line_len = same_word = 0;
+- qlen = qstr ? ucs4_strlen(qstr) : 0;
+
+ /* Beginning with leading quoting... */
+! if(qstr){
+! i = 0;
+! while(qstr[i]){
+! ww = wcellwidth(qstr[i]);
+! line_len += (ww >= 0 ? ww : 1);
+! linsert(1, qstr[i++]);
+! }
+
+ line_last = ' '; /* no word-flush space! */
+ }
+
+ /* remove first leading quotes if any */
+ if(starts_midline)
+ i = 0;
+! else
+! for(i = qlen; (c = fremove(i)) == ' ' || c == TAB; i++){
+ linsert(1, line_last = (UCS) c);
+ line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
+ }
+
+ /* then digest the rest... */
+ while((c = fremove(i++)) >= 0){
+--- 1030,1065 ----
+
+ /* Now insert it back wrapped */
+ spaces = word_len = word_ind = line_len = same_word = 0;
+
+ /* Beginning with leading quoting... */
+! if(qstr || istr){
+! for(i = 0; quoid[i] != '\0' ; i++)
+! linsert(1, quoid[i]);
+
+ line_last = ' '; /* no word-flush space! */
++ line_len = ucs4_strlenis(quoid); /* we demand a recount! */
+ }
+
+ /* remove first leading quotes if any */
+ if(starts_midline)
+ i = 0;
+! else{
+! if(qstr || istr){
+! for (i = 0; (c = fremove(i)) != '\0'; i++){
+! word[i] = c;
+! word[i+1] = '\0';
+! if(ucs4_strlenis(word) >= ucs4_strlenis(quoid))
+! break;
+! }
+! i++;
+! }
+! else
+! i = 0;
+! for(; ISspace(c = fremove(i)); i++){
+ linsert(1, line_last = (UCS) c);
+ line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
+ }
++ }
+
+ /* then digest the rest... */
+ while((c = fremove(i++)) >= 0){
+***************
+*** 905,925 ****
+
+ case TAB :
+ case ' ' :
+ spaces++;
+ same_word = 0;
+ break;
+
+ default :
+ if(spaces){ /* flush word? */
+! if((line_len - qlen > 0)
+ && line_len + word_len + 1 > fillcol
+! && ((ucs4_isspace(line_last))
+ || (linsert(1, ' ')))
+ && (line_len = fpnewline(qstr)))
+ line_last = ' '; /* no word-flush space! */
+
+ if(word_len){ /* word to write? */
+! if(line_len && !ucs4_isspace(line_last)){
+ linsert(1, ' '); /* need padding? */
+ line_len++;
+ }
+--- 1081,1102 ----
+
+ case TAB :
+ case ' ' :
++ case NBSP:
+ spaces++;
+ same_word = 0;
+ break;
+
+ default :
+ if(spaces){ /* flush word? */
+! if((line_len - qlenis > 0)
+ && line_len + word_len + 1 > fillcol
+! && ((ISspace(line_last))
+ || (linsert(1, ' ')))
+ && (line_len = fpnewline(qstr)))
+ line_last = ' '; /* no word-flush space! */
+
+ if(word_len){ /* word to write? */
+! if(line_len && !ISspace(line_last)){
+ linsert(1, ' '); /* need padding? */
+ line_len++;
+ }
+***************
+*** 941,948 ****
+
+ if(word_ind + 1 >= NSTRING){
+ /* Magic! Fake that we output a wrapped word */
+! if((line_len - qlen > 0) && !same_word++){
+! if(!ucs4_isspace(line_last))
+ linsert(1, ' ');
+ line_len = fpnewline(qstr);
+ }
+--- 1118,1125 ----
+
+ if(word_ind + 1 >= NSTRING){
+ /* Magic! Fake that we output a wrapped word */
+! if((line_len - qlenis > 0) && !same_word++){
+! if(!ISspace(line_last))
+ linsert(1, ' ');
+ line_len = fpnewline(qstr);
+ }
+***************
+*** 964,975 ****
+ }
+
+ if(word_len){
+! if((line_len - qlen > 0) && (line_len + word_len + 1 > fillcol)){
+! if(!ucs4_isspace(line_last))
+ linsert(1, ' ');
+ (void) fpnewline(qstr);
+ }
+! else if(line_len && !ucs4_isspace(line_last))
+ linsert(1, ' ');
+
+ for(j = 0; j < word_ind; j++)
+--- 1141,1152 ----
+ }
+
+ if(word_len){
+! if((line_len - qlenis > 0) && (line_len + word_len + 1 > fillcol)){
+! if(!ISspace(line_last))
+ linsert(1, ' ');
+ (void) fpnewline(qstr);
+ }
+! else if(line_len && !ISspace(line_last))
+ linsert(1, ' ');
+
+ for(j = 0; j < word_ind; j++)
+***************
+*** 1027,1037 ****
+ int len;
+
+ lnewline();
+! for(len = 0; quote && *quote; quote++){
+ int ww;
+
+! ww = wcellwidth(*quote);
+! len += (ww >= 0 ? ww : 1);
+ linsert(1, *quote);
+ }
+
+--- 1204,1214 ----
+ int len;
+
+ lnewline();
+! for(len = ucs4_strlenis(quote); quote && *quote; quote++){
+ int ww;
+
+! /* ww = wcellwidth(*quote);
+! len += (ww >= 0 ? ww : 1);*/
+ linsert(1, *quote);
+ }
+
+***************
+*** 1175,1179 ****
+--- 1352,1396 ----
+ markregion(1);
+ }
+
++ /*
++ * This puts us at the end of the quoted region instead
++ * of on the following line. This makes it convenient
++ * for the user to follow a quotelevel adjustment with
++ * a Justify if desired.
++ */
++ if(backuptoprevline){
++ curwp->w_doto = 0;
++ backchar(0, 1);
++ }
++
++ if(ends_midline){ /* doesn't need fixing otherwise */
++ unmarkbuffer();
++ markregion(1);
++ }
++
+ return (TRUE);
+ }
++
++ /*
++ * If there is an indent string this function returns
++ * its length
++ */
++ int
++ indent_match(char *q, LINE *l, char *buf, int buflen, int raw)
++ {
++ char GLine[NSTRING];
++ int i, k, plb;
++
++ k = quote_match(q,l, buf, buflen, raw);
++ linencpy(GLine, l, NSTRING);
++ plb = (lback(l) != curbp->b_linep) ? lisblank(lback(l)) : 1;
++ if (!plb){
++ i = llength(lback(l)) - 1;
++ for (; i >= 0 && ISspace(lgetc(lback(l), i).c); i--);
++ if (EOLchar(lgetc(lback(l), i).c))
++ plb++;
++ }
++
++ return get_indent_raw_line(q, GLine, buf, buflen, k, plb);
++ }
++
+diff -rc alpine-2.00/pith/adrbklib.c alpine-2.00.I.USE/pith/adrbklib.c
+*** alpine-2.00/pith/adrbklib.c 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/pith/adrbklib.c 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 5119,5126 ****
+ if(as.cur >= as.how_many_personals)
+ pab->type |= GLOBAL;
+
+! pab->access = adrbk_access(pab);
+!
+ /* global address books are forced readonly */
+ if(pab->type & GLOBAL && pab->access != NoAccess)
+ pab->access = ReadOnly;
+--- 5119,5132 ----
+ if(as.cur >= as.how_many_personals)
+ pab->type |= GLOBAL;
+
+! if(ps_global->mail_stream &&
+! ps_global->mail_stream->lock && (pab->type & REMOTE_VIA_IMAP)){
+! as.initialized = 0;
+! pab->access = NoAccess;
+! }
+! else{
+! pab->access = adrbk_access(pab);
+! }
+ /* global address books are forced readonly */
+ if(pab->type & GLOBAL && pab->access != NoAccess)
+ pab->access = ReadOnly;
+diff -rc alpine-2.00/pith/charconv/utf8.c alpine-2.00.I.USE/pith/charconv/utf8.c
+*** alpine-2.00/pith/charconv/utf8.c 2008-04-02 15:09:20.000000000 -0700
+--- alpine-2.00.I.USE/pith/charconv/utf8.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 1048,1053 ****
+--- 1048,1103 ----
+
+
+ /*
++ * Returns the screen cells width of the UTF-8 string argument, treating tabs
++ * in a special way.
++ */
++ unsigned
++ utf8_widthis(char *str)
++ {
++ unsigned width = 0;
++ int this_width;
++ UCS ucs;
++ unsigned long remaining_octets;
++ char *readptr;
++
++ if(!(str && *str))
++ return(width);
++
++ readptr = str;
++ remaining_octets = readptr ? strlen(readptr) : 0;
++
++ while(remaining_octets > 0 && *readptr){
++
++ ucs = (UCS) utf8_get((unsigned char **) &readptr, &remaining_octets);
++
++ if(ucs & U8G_ERROR){
++ /*
++ * This should not happen, but do something to handle it anyway.
++ * Treat each character as a single width character, which is what should
++ * probably happen when we actually go to write it out.
++ */
++ remaining_octets--;
++ readptr++;
++ this_width = 1;
++ }
++ else{
++ this_width = (ucs == TAB) ? ((~width & 0x07) + 1) : wcellwidth(ucs);
++
++ /*
++ * If this_width is -1 that means we can't print this character
++ * with our current locale. Writechar will print a '?'.
++ */
++ if(this_width < 0)
++ this_width = 1;
++ }
++
++ width += (unsigned) this_width;
++ }
++
++ return(width);
++ }
++
++ /*
+ * Copy UTF-8 characters from src into dst.
+ * This is intended to be used if you want to truncate a string at
+ * the start instead of the end. For example, you have a long string
+diff -rc alpine-2.00/pith/charconv/utf8.h alpine-2.00.I.USE/pith/charconv/utf8.h
+*** alpine-2.00/pith/charconv/utf8.h 2008-04-02 15:09:20.000000000 -0700
+--- alpine-2.00.I.USE/pith/charconv/utf8.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 80,85 ****
+--- 80,86 ----
+ UCS *ucs4_strchr(UCS *s, UCS c);
+ UCS *ucs4_strrchr(UCS *s, UCS c);
+ unsigned utf8_width(char *);
++ unsigned utf8_widthis(char *);
+ size_t utf8_to_width_rhs(char *, char *, size_t, unsigned);
+ int utf8_snprintf(char *, size_t, char *, ...);
+ size_t utf8_to_width(char *, char *, size_t, unsigned, unsigned *);
+diff -rc alpine-2.00/pith/color.c alpine-2.00.I.USE/pith/color.c
+*** alpine-2.00/pith/color.c 2007-08-15 13:28:09.000000000 -0700
+--- alpine-2.00.I.USE/pith/color.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 20,26 ****
+ #include "../pith/state.h"
+ #include "../pith/conf.h"
+ #include "../pith/filter.h"
+!
+
+ char *
+ color_embed(char *fg, char *bg)
+--- 20,27 ----
+ #include "../pith/state.h"
+ #include "../pith/conf.h"
+ #include "../pith/filter.h"
+! #include "../pith/mailview.h"
+! #include "../pico/estruct.h"
+
+ char *
+ color_embed(char *fg, char *bg)
+***************
+*** 69,91 ****
+ struct quote_colors *next;
+ };
+
+
+ int
+ color_a_quote(long int linenum, char *line, LT_INS_S **ins, void *is_flowed_msg)
+ {
+! int countem = 0;
+ struct variable *vars = ps_global->vars;
+! char *p;
+ struct quote_colors *colors = NULL, *cp, *next;
+ COLOR_PAIR *col = NULL;
+ int is_flowed = is_flowed_msg ? *((int *)is_flowed_msg) : 0;
+
+ p = line;
+! if(!is_flowed)
+! while(isspace((unsigned char)*p))
+! p++;
+
+! if(p[0] == '>'){
+ struct quote_colors *c;
+
+ /*
+--- 70,179 ----
+ struct quote_colors *next;
+ };
+
++ int
++ is_word (buf, i, j)
++ char buf[NSTRING];
++ int i, j;
++ {
++ return i <= j && is_letter(buf[i]) ?
++ (i < j ? is_word(buf,i+1,j) : 1) : 0;
++ }
++
++ int
++ is_mailbox(buf,i,j)
++ char buf[NSTRING];
++ int i, j;
++ {
++ return i <= j && (is_letter(buf[i]) || is_digit(buf[i]) || buf[i] == '.')
++ ? (i < j ? is_mailbox(buf,i+1,j) : 1) : 0;
++ }
++
++ int
++ next_level_quote(buf, line, i, is_flowed)
++ char *buf;
++ char **line;
++ int i;
++ int is_flowed;
++ {
++ int j;
++
++ if (!single_level(buf[i])){
++ if(is_mailbox(buf,i,i)){
++ for (j = i; buf[j] && !isspace(buf[j]); j++);
++ if (is_word(buf,i,j-1) || is_mailbox(buf,i,j-1))
++ j += isspace(buf[j]) ? 2 : 1;
++ }
++ else{
++ switch(buf[i]){
++ case ':' :
++ if (next(buf,i) != RPAREN)
++ j = i + 1;
++ else
++ j = i + 2;
++ break;
++
++ case '-' :
++ if (next(buf,i) != '-')
++ j = i + 2;
++ else
++ j = i + 3;
++ break;
++
++ case '+' :
++ case '*' :
++ if (next(buf,i) != ' ')
++ j = i + 2;
++ else
++ j = i + 3;
++ break;
++
++ default :
++ for (j = i; buf[j] && !isspace(buf[j])
++ && (!single_level(buf[i]) && !is_letter(buf[j])); j++);
++
++ j += isspace(buf[j]) ? 1 : 0;
++ break;
++ }
++ }
++ if (line && *line)
++ (*line) += j - i;
++ }
++ else{
++ j = i+1;
++ if (line && *line)
++ (*line)++;
++ }
++ if(!is_flowed){
++ if(line && *line)
++ for(; isspace((unsigned char)*(*line)); (*line)++);
++ for (i = j; isspace((unsigned char) buf[i]); i++);
++ }
++ else i = j;
++ if (is_flowed && i != j)
++ buf[i] = '\0';
++ return i;
++ }
+
+ int
+ color_a_quote(long int linenum, char *line, LT_INS_S **ins, void *is_flowed_msg)
+ {
+! int countem = 0, i, j = 0;
+ struct variable *vars = ps_global->vars;
+! char *p, buf[NSTRING] = {'\0'};
+ struct quote_colors *colors = NULL, *cp, *next;
+ COLOR_PAIR *col = NULL;
+ int is_flowed = is_flowed_msg ? *((int *)is_flowed_msg) : 0;
++ int code;
++
++ code = (is_flowed ? IS_FLOWED : NO_FLOWED) | COLORAQUO;
++ select_quote(linenum, line, ins, (void *) &code);
++ strncpy(buf, tmp_20k_buf, NSTRING < SIZEOF_20KBUF ? NSTRING : SIZEOF_20KBUF);
++ buf[sizeof(buf)-1] = '\0';
+
+ p = line;
+! for(i = 0; isspace((unsigned char)buf[i]); i++, p++);
+
+! if(buf[i]){
+ struct quote_colors *c;
+
+ /*
+***************
+*** 134,140 ****
+ free_color_pair(&col);
+
+ cp = NULL;
+! while(*p == '>'){
+ cp = (cp && cp->next) ? cp->next : colors;
+
+ if(countem > 0)
+--- 222,228 ----
+ free_color_pair(&col);
+
+ cp = NULL;
+! while(buf[i]){
+ cp = (cp && cp->next) ? cp->next : colors;
+
+ if(countem > 0)
+***************
+*** 144,153 ****
+
+ countem = (countem == 1) ? 0 : countem;
+
+! p++;
+! if(!is_flowed)
+! for(; isspace((unsigned char)*p); p++)
+! ;
+ }
+
+ if(colors){
+--- 232,240 ----
+
+ countem = (countem == 1) ? 0 : countem;
+
+! i = next_level_quote(buf, &p, i, is_flowed);
+! for (; isspace((unsigned char)*p); p++);
+! for (; isspace((unsigned char)buf[i]); i++);
+ }
+
+ if(colors){
+***************
+*** 210,216 ****
+ }
+ }
+
+! return(0);
+ }
+
+
+--- 297,303 ----
+ }
+ }
+
+! return(1);
+ }
+
+
+diff -rc alpine-2.00/pith/color.h alpine-2.00.I.USE/pith/color.h
+*** alpine-2.00/pith/color.h 2007-05-08 16:38:08.000000000 -0700
+--- alpine-2.00.I.USE/pith/color.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 21,26 ****
+--- 21,44 ----
+ #include "../pith/pattern.h"
+ #include "../pith/osdep/color.h"
+
++ #define NO_FLOWED 0x0000
++ #define IS_FLOWED 0x0001
++ #define DELETEQUO 0x0010
++ #define COLORAQUO 0x0100
++ #define RAWSTRING 0x1000
++
++ /* This is needed for justification, I will move it to a better place later
++ * or maybe not
++ */
++ #define is_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
++
++ #define is_letter(c) (((c) >= 'a' && (c) <= 'z') || \
++ ((c) >= 'A' && (c) <= 'Z'))
++
++ #define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0)
++
++ #define single_level(c) (((c) == '>') || ((c) == '|') || ((c) == '~') || \
++ ((c) == ']'))
+
+ typedef struct spec_color_s {
+ int inherit; /* this isn't a color, it is INHERIT */
+***************
+*** 80,85 ****
+--- 98,104 ----
+ /* exported protoypes */
+ char *color_embed(char *, char *);
+ int colorcmp(char *, char *);
++ int next_level_quote(char *, char **, int, int);
+ int color_a_quote(long, char *, LT_INS_S **, void *);
+ void free_spec_colors(SPEC_COLOR_S **);
+
+diff -rc alpine-2.00/pith/conf.c alpine-2.00.I.USE/pith/conf.c
+*** alpine-2.00/pith/conf.c 2008-08-22 17:07:05.000000000 -0700
+--- alpine-2.00.I.USE/pith/conf.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 28,33 ****
+--- 28,34 ----
+ #include "../pith/remote.h"
+ #include "../pith/keyword.h"
+ #include "../pith/mailview.h"
++ #include "../pith/rules.h"
+ #include "../pith/list.h"
+ #include "../pith/status.h"
+ #include "../pith/ldap.h"
+***************
+*** 197,208 ****
+--- 198,213 ----
+
+ CONF_TXT_T cf_text_view_hdr_color[] = "When viewing messages, these are the header colors";
+
++ CONF_TXT_T cf_text_index_token_color[] = "Colors in which tokens will be displayed in the index screen";
++
+ CONF_TXT_T cf_text_save_msg_name_rule[] = "Determines default folder name for Saves...\n# Choices: default-folder, by-sender, by-from, by-recipient, last-folder-used.\n# Default: \"default-folder\", i.e. \"saved-messages\" (Unix) or \"SAVEMAIL\" (PC).";
+
+ CONF_TXT_T cf_text_fcc_name_rule[] = "Determines default name for Fcc...\n# Choices: default-fcc, by-recipient, last-fcc-used.\n# Default: \"default-fcc\" (see also \"default-fcc=\" variable.)";
+
+ CONF_TXT_T cf_text_sort_key[] = "Sets presentation order of messages in Index. Choices:\n# Subject, From, Arrival, Date, Size, To, Cc, OrderedSubj, Score, and Thread.\n# Order may be reversed by appending /Reverse. Default: \"Arrival\".";
+
++ CONF_TXT_T cf_text_thread_sort_key[] = "#Sets presentation order of threads in thread index. Choices:\n#arrival, and thread.";
++
+ CONF_TXT_T cf_text_addrbook_sort_rule[] = "Sets presentation order of address book entries. Choices: dont-sort,\n# fullname-with-lists-last, fullname, nickname-with-lists-last, nickname\n# Default: \"fullname-with-lists-last\".";
+
+ CONF_TXT_T cf_text_folder_sort_rule[] = "Sets presentation order of folder list entries. Choices: alphabetical,\n# alpha-with-dirs-last, alpha-with-dirs-first.\n# Default: \"alpha-with-directories-last\".";
+***************
+*** 219,230 ****
+--- 224,267 ----
+
+ CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature.";
+
++ CONF_TXT_T cf_text_compose_rules[] = "Allows a user to set rules when composing messages.";
++
++ CONF_TXT_T cf_text_forward_rules[] = "Allows a user to set rules when forwarding messages.";
++
++ CONF_TXT_T cf_text_reply_rules[] = "Allows a user to set rules when replying messages.";
++
++ CONF_TXT_T cf_text_index_rules[] = "Allows a user to supersede global index format variable in designated folders.";
++
++ CONF_TXT_T cf_text_key_def_rules[] = "Allows a user to override keystrokes in certain screens.";
++
++ CONF_TXT_T cf_text_replace_rules[] = "Allows a user to change the form a specify field in the index-format is \n# displayed.";
++
++ CONF_TXT_T cf_text_reply_indent_rules[] = "Allows a user to change the form a specify a reply-indent-string\n# based of rules.";
++
++ CONF_TXT_T cf_text_reply_leadin_rules[] = "Allows a user to replace the reply-leadin message based on different parameters.";
++
++ CONF_TXT_T cf_text_reply_subject_rules[] = "Allows a user to replace the subject of a message in a customs based way";
++
++ CONF_TXT_T cf_text_thread_displaystyle_rule[] = "Allows a user to specify the threading style of specific folders";
++
++ CONF_TXT_T cf_text_thread_indexstyle_rule[] = "Allows a user to specify the threading index style of specific folders";
++
++ CONF_TXT_T cf_text_save_rules[] = "Allows a user to specify a save folder message for specific senders or folders.";
++
++ CONF_TXT_T cf_text_smtp_rules[] = "Allows a user to specify a smtp server to be used when sending e-mail,\n# according to the rules specified here.";
++
++ CONF_TXT_T cf_text_sort_rules[] = "Allows a user to specify the sort default order of a specific folder.";
++
++ CONF_TXT_T cf_text_startup_rules[] = "Allows a user to specify the position of a highlighted message when opening a \n# folder.";
++
+ CONF_TXT_T cf_text_speller[] = "Specifies the program invoked by ^T in the Composer.";
+
+ CONF_TXT_T cf_text_deadlets[] = "Specifies the number of dead letter files to keep when canceling.";
+
+ CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
+
++ CONF_TXT_T cf_special_text_color[] = "Specifies a comma separated list of text and regular expresions that Pine\n# will highlight";
++
+ CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
+
+ CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
+***************
+*** 427,432 ****
+--- 464,472 ----
+
+ CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
+
++ #ifndef _WINDOWS
++ CONF_TXT_T cf_text_maildir_location[] = "Location relative to your HOME directory of the directory where your INBOX\n# for the maildir format is located. Default value is \"Maildir\". If your\n# inbox is located at \"~/Maildir\" you do not need to change this value.\n# A common value is also \".maildir\"";
++ #endif
+
+ /*----------------------------------------------------------------------
+ These are the variables that control a number of pine functions. They
+***************
+*** 517,522 ****
+--- 557,564 ----
+ NULL, cf_text_fcc_name_rule},
+ {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ NULL, cf_text_sort_key},
++ {"thread-sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
++ NULL, cf_text_thread_sort_key},
+ {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ "Address Book Sort Rule", cf_text_addrbook_sort_rule},
+ {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+***************
+*** 539,544 ****
+--- 581,614 ----
+ NULL, cf_text_thread_exp_char},
+ {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ "Threading Last Reply Character", cf_text_thread_lastreply_char},
++ {"threading-display-style-rule", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Threading Display Style Rule", cf_text_thread_displaystyle_rule},
++ {"threading-index-style-rule", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Threading Index Style Rule", cf_text_thread_indexstyle_rule},
++ {"compose-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Compose Rules", cf_text_compose_rules},
++ {"forward-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Forward Rules", cf_text_forward_rules},
++ {"index-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
++ "Index Rules", cf_text_index_rules},
++ {"key-definition-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
++ "Key Definition Rules", cf_text_key_def_rules},
++ {"replace-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
++ "Replace Rules", cf_text_replace_rules},
++ {"reply-indent-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Reply Indent Rules", cf_text_reply_indent_rules},
++ {"reply-leadin-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
++ "Reply Leadin Rules", cf_text_reply_leadin_rules},
++ {"reply-subject-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
++ "Reply Subject Rules", cf_text_reply_subject_rules},
++ {"save-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Save Rules", cf_text_save_rules},
++ {"smtp-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Smtp Rules", cf_text_smtp_rules},
++ {"sort-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Sort Rules", cf_text_sort_rules},
++ {"startup-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ "Startup Rules", cf_text_startup_rules},
+ #ifndef _WINDOWS
+ {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ NULL, cf_text_disp_char_set},
+***************
+*** 557,562 ****
+--- 627,634 ----
+ NULL, cf_text_speller},
+ {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ NULL, cf_text_fillcol},
++ {"special-text-color", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ NULL, cf_special_text_color},
+ {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
+ NULL, cf_text_replystr},
+ {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+***************
+*** 627,632 ****
+--- 699,708 ----
+ NULL, cf_text_news_active},
+ {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ NULL, cf_text_news_spooldir},
++ #ifndef _WINDOWS
++ {"maildir-location", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
++ "Maildir Location", cf_text_maildir_location},
++ #endif
+ {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ NULL, cf_text_upload_cmd},
+ {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+***************
+*** 788,793 ****
+--- 864,875 ----
+ {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+***************
+*** 808,813 ****
+--- 890,897 ----
+ {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"special-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"special-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+***************
+*** 840,845 ****
+--- 924,931 ----
+ {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
+ {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
++ {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
++ NULL, cf_text_index_token_color},
+ {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
+ "Viewer Header Colors", cf_text_view_hdr_color},
+ {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
+***************
+*** 1555,1561 ****
+ register struct variable *vars = ps->vars;
+ int obs_header_in_reply = 0, /* the obs_ variables are to */
+ obs_old_style_reply = 0, /* support backwards compatibility */
+! obs_save_by_sender, i, def_sort_rev;
+ long rvl;
+ PINERC_S *fixedprc = NULL;
+ FeatureLevel obs_feature_level;
+--- 1641,1647 ----
+ register struct variable *vars = ps->vars;
+ int obs_header_in_reply = 0, /* the obs_ variables are to */
+ obs_old_style_reply = 0, /* support backwards compatibility */
+! obs_save_by_sender, i, def_sort_rev, thread_def_sort_rev;
+ long rvl;
+ PINERC_S *fixedprc = NULL;
+ FeatureLevel obs_feature_level;
+***************
+*** 1580,1585 ****
+--- 1666,1672 ----
+ GLO_FEATURE_LEVEL = cpystr("sappling");
+ GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
+ GLO_SORT_KEY = cpystr(DF_SORT_KEY);
++ GLO_THREAD_SORT_KEY = cpystr(DF_THREAD_SORT_KEY);
+ GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
+ GLO_FCC_RULE = cpystr(DF_FCC_RULE);
+ GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
+***************
+*** 1642,1647 ****
+--- 1729,1737 ----
+ GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
+ GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
+ GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
++ GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
++ GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
++ GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
+ GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
+ GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
+ GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
+***************
+*** 1943,1948 ****
+--- 2033,2040 ----
+ set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
+ set_current_val(&vars[V_EDITOR], TRUE, TRUE);
+ set_current_val(&vars[V_SPELLER], TRUE, TRUE);
++ set_current_val(&vars[V_SPECIAL_TEXT], TRUE, TRUE);
++ regex_pattern(VAR_SPECIAL_TEXT);
+ set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
+ set_current_val(&vars[V_BROWSER], TRUE, TRUE);
+ set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
+***************
+*** 2216,2221 ****
+--- 2308,2319 ----
+ mail_parameters(NULL, SET_NEWSSPOOL,
+ (void *)VAR_NEWS_SPOOL_DIR);
+
++ #ifndef _WINDOWS
++ set_current_val(&vars[V_MAILDIR_LOCATION], TRUE, TRUE);
++ if(VAR_MAILDIR_LOCATION && VAR_MAILDIR_LOCATION[0])
++ mail_parameters(NULL, SET_MDINBOXPATH, (void *)VAR_MAILDIR_LOCATION);
++ #endif
++
+ /* guarantee a save default */
+ set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
+ if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
+***************
+*** 2446,2452 ****
+ set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
+! if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
+ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
+ ps->def_sort = SortArrival;
+--- 2544,2550 ----
+ set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
+! if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev,0) == -1){
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
+ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
+ ps->def_sort = SortArrival;
+***************
+*** 2455,2460 ****
+--- 2553,2569 ----
+ else
+ ps->def_sort_rev = def_sort_rev;
+
++ set_current_val(&vars[V_THREAD_SORT_KEY], TRUE, TRUE);
++ if(decode_sort(VAR_THREAD_SORT_KEY, &ps->thread_def_sort,
++ &thread_def_sort_rev, 1) == -1){
++ sprintf(tmp_20k_buf, "Sort type \"%s\" is invalid", VAR_THREAD_SORT_KEY);
++ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
++ ps->thread_def_sort = SortThread;
++ ps->thread_def_sort_rev = 0;
++ }
++ else
++ ps->thread_def_sort_rev = thread_def_sort_rev;
++
+ cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
+ {NAMEVAL_S *v; int i;
+ for(i = 0; (v = save_msg_rules(i)); i++)
+***************
+*** 2541,2546 ****
+--- 2650,2656 ----
+ if(cmds_f)
+ (*cmds_f)(ps, VAR_INIT_CMD_LIST);
+
++ (void)create_rule_list(ps_global->vars);
+ #ifdef _WINDOWS
+ mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
+ #endif /* _WINDOWS */
+***************
+*** 2744,2749 ****
+--- 2854,2861 ----
+ F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
+
+ /* Reply Prefs */
++ {"alternate-reply-menu", NULL,
++ F_ALT_REPLY_MENU, h_config_alt_reply_menu, PREF_RPLY, 0},
+ {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
+ F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
+ {"enable-reply-indent-string-editing", NULL,
+***************
+*** 2762,2767 ****
+--- 2874,2881 ----
+ F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
+ {"forward-as-attachment", "Forward messages as attachments",
+ F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
++ {"preserve-original-fields", NULL,
++ F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
+
+ /* Sending Prefs */
+ {"disable-sender", "Do Not Generate Sender Header",
+***************
+*** 2786,2791 ****
+--- 2900,2907 ----
+ F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
+ {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
+ F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
++ {"return-path-uses-domain-name", NULL,
++ F_USE_DOMAIN_NAME, h_config_use_domain, PREF_SEND, 0},
+ {"mark-fcc-seen", NULL,
+ F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
+ {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
+***************
+*** 2832,2837 ****
+--- 2948,2957 ----
+ F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
+ {"vertical-folder-list", "Use Vertical Folder List",
+ F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
++ #ifndef _WINDOWS
++ {"use-courier-folder-list", "Courier Style Folder List",
++ F_COURIER_FOLDER_LIST, h_config_courier_list, PREF_FLDR, 0},
++ #endif
+
+ /* Addr book */
+ {"combined-addrbook-display", "Combined Address Book Display",
+***************
+*** 2848,2853 ****
+--- 2968,2975 ----
+ /* Index prefs */
+ {"auto-open-next-unread", NULL,
+ F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
++ {"enable-circular-tab", NULL,
++ F_AUTO_CIRCULAR_TAB, h_config_circular_tab, PREF_INDX, 0},
+ {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
+ F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
+ {"convert-dates-to-localtime", NULL,
+***************
+*** 2876,2881 ****
+--- 2998,3005 ----
+ F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
+ {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
+ F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
++ {"enhanced-fancy-thread-support", "Enhanced Fancy Thread Support",
++ F_ENHANCED_THREAD, h_config_enhanced_thread, PREF_INDX, 0},
+
+ /* Viewer prefs */
+ {"enable-msg-view-addresses", "Enable Message View Address Links",
+***************
+*** 2886,2891 ****
+--- 3010,3017 ----
+ F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
+ {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
+ F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
++ {"enable-msg-view-long-url", "Enable Recognition of Long URLS without Delimiter",
++ F_VIEW_LONG_URL, h_config_enable_long_url, PREF_VIEW, 0},
+ {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
+ F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
+ /* set to TRUE for windows */
+***************
+*** 2983,2988 ****
+--- 3109,3116 ----
+ F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
+ {"auto-move-read-msgs", "Auto Move Read Messages",
+ F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
++ {"auto-move-read-msgs-using-rules", "Auto Move Read Messages Using Rules",
++ F_AUTO_READ_MSGS_RULES, h_config_auto_read_msgs_rules, PREF_MISC, 0},
+ {"auto-unselect-after-apply", NULL,
+ F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
+ {"auto-unzoom-after-apply", NULL,
+***************
+*** 3044,3049 ****
+--- 3172,3179 ----
+ F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
+ {"force-arrow-cursor", NULL,
+ F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
++ {"ignore-size-changes", NULL,
++ F_IGNORE_SIZE, h_config_ignore_size, PREF_MISC, 0},
+ {"maildrops-preserve-state", NULL,
+ F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
+ PREF_MISC, 0},
+***************
+*** 3179,3184 ****
+--- 3309,3316 ----
+ F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
+ {"disable-signature-edit-cmd", NULL,
+ F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
++ {"new-thread-on-blank-subject", "New Thread on Blank Subject",
++ F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
+ {"quell-personal-name-prompt", NULL,
+ F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
+ {"quell-user-id-prompt", "Quell User ID Prompt",
+***************
+*** 4734,4750 ****
+ but also after each : in the path.
+
+ ----*/
+
+ char *
+ expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
+ {
+ char *src = linein, *dest = lineout, *p;
+ char *limit = lineout + lineoutlen;
+! int envexpand = 0;
+
+ if(!linein)
+ return(NULL);
+
+ while(*src ){ /* something in input string */
+ if(*src == '$' && *(src+1) == '$'){
+ /*
+--- 4866,4887 ----
+ but also after each : in the path.
+
+ ----*/
++ #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) \
++ : (((C) >= 'a' && (C) <= 'z') \
++ || ((C) >= 'A' && (C) <= 'Z') \
++ || ((C) >= '0' && (C) <= '9')))
+
+ char *
+ expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
+ {
+ char *src = linein, *dest = lineout, *p;
+ char *limit = lineout + lineoutlen;
+! int envexpand = 0, sp;
+
+ if(!linein)
+ return(NULL);
+
++ sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
+ while(*src ){ /* something in input string */
+ if(*src == '$' && *(src+1) == '$'){
+ /*
+***************
+*** 4825,4831 ****
+ src = rbrace + 1;
+ }
+ else{
+! while(*src && !isspace((unsigned char) *src)
+ && (p-word < sizeof(word)-1))
+ *p++ = *src++;
+ }
+--- 4962,4968 ----
+ src = rbrace + 1;
+ }
+ else{
+! while(*src && is_allowed_envchar((unsigned char) *src, sp)
+ && (p-word < sizeof(word)-1))
+ *p++ = *src++;
+ }
+***************
+*** 6356,6361 ****
+--- 6493,6501 ----
+
+ set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
+ set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
++ set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
++ set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
++ set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
+ set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
+ set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
+ set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
+***************
+*** 6379,6385 ****
+--- 6519,6527 ----
+ set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
+ set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
+ set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
++ set_color_val(&vars[V_SPECIAL_TEXT_FORE_COLOR], 0);
+
++ set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
+ set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
+ set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
+ set_custom_spec_colors(ps);
+***************
+*** 6532,6537 ****
+--- 6674,6684 ----
+ void
+ set_custom_spec_colors(struct pine *ps)
+ {
++ if(ps->index_token_colors)
++ free_spec_colors(&ps->index_token_colors);
++
++ ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
++
+ if(ps->hdr_colors)
+ free_spec_colors(&ps->hdr_colors);
+
+***************
+*** 6895,6900 ****
+--- 7042,7053 ----
+
+ break;
+
++ #ifndef _WINDOWS
++ case F_COURIER_FOLDER_LIST:
++ mail_parameters(NULL,SET_COURIERSTYLE,(void *)(F_ON(f->id ,ps)? 1 : 0));
++ break; /* COURIER == 1, CCLIENT == 0, see maildir.h */
++ #endif
++
+ case F_COLOR_LINE_IMPORTANT :
+ case F_DATES_TO_LOCAL :
+ clear_index_cache(ps->mail_stream, 0);
+***************
+*** 7500,7509 ****
+--- 7653,7692 ----
+ return(h_config_fcc_rule);
+ case V_SORT_KEY :
+ return(h_config_sort_key);
++ case V_THREAD_SORT_KEY :
++ return(h_config_thread_sort_key);
+ case V_AB_SORT_RULE :
+ return(h_config_ab_sort_rule);
+ case V_FLD_SORT_RULE :
+ return(h_config_fld_sort_rule);
++ case V_THREAD_DISP_STYLE_RULES:
++ return(h_config_thread_display_style_rule);
++ case V_THREAD_INDEX_STYLE_RULES:
++ return(h_config_thread_index_style_rule);
++ case V_COMPOSE_RULES:
++ return(h_config_compose_rules);
++ case V_FORWARD_RULES:
++ return(h_config_forward_rules);
++ case V_INDEX_RULES:
++ return(h_config_index_rules);
++ case V_KEY_RULES:
++ return(h_config_key_macro_rules);
++ case V_REPLACE_RULES:
++ return(h_config_replace_rules);
++ case V_REPLY_INDENT_RULES:
++ return(h_config_reply_indent_rules);
++ case V_REPLY_LEADIN_RULES:
++ return(h_config_reply_leadin_rules);
++ case V_RESUB_RULES:
++ return(h_config_resub_rules);
++ case V_SAVE_RULES:
++ return(h_config_save_rules);
++ case V_SMTP_RULES:
++ return(h_config_smtp_rules);
++ case V_SORT_RULES:
++ return(h_config_sort_rules);
++ case V_STARTUP_RULES:
++ return(h_config_startup_rules);
+ case V_POST_CHAR_SET :
+ return(h_config_post_char_set);
+ case V_UNK_CHAR_SET :
+***************
+*** 7554,7559 ****
+--- 7737,7744 ----
+ return(h_config_scroll_margin);
+ case V_DEADLETS :
+ return(h_config_deadlets);
++ case V_SPECIAL_TEXT :
++ return(h_config_special_text_to_color);
+ case V_FILLCOL :
+ return(h_config_composer_wrap_column);
+ case V_TCPOPENTIMEO :
+***************
+*** 7676,7681 ****
+--- 7861,7870 ----
+ return(h_config_newmailwidth);
+ case V_NEWSRC_PATH :
+ return(h_config_newsrc_path);
++ #ifndef _WINDOWS
++ case V_MAILDIR_LOCATION :
++ return(h_config_maildir_location);
++ #endif
+ case V_BROWSER :
+ return(h_config_browser);
+ #if defined(DOS) || defined(OS2)
+***************
+*** 7694,7699 ****
+--- 7883,7894 ----
+ case V_TITLECLOSED_FORE_COLOR :
+ case V_TITLECLOSED_BACK_COLOR :
+ return(h_config_titleclosed_color);
++ case V_FOLDER_FORE_COLOR:
++ return(h_config_folder_color);
++ case V_DIRECTORY_FORE_COLOR:
++ return(h_config_directory_color);
++ case V_FOLDER_LIST_FORE_COLOR:
++ return(h_config_folder_list_color);
+ case V_STATUS_FORE_COLOR :
+ case V_STATUS_BACK_COLOR :
+ return(h_config_status_color);
+***************
+*** 7713,7718 ****
+--- 7908,7916 ----
+ case V_SIGNATURE_FORE_COLOR :
+ case V_SIGNATURE_BACK_COLOR :
+ return(h_config_signature_color);
++ case V_SPECIAL_TEXT_FORE_COLOR :
++ case V_SPECIAL_TEXT_BACK_COLOR :
++ return(h_config_special_text_color);
+ case V_PROMPT_FORE_COLOR :
+ case V_PROMPT_BACK_COLOR :
+ return(h_config_prompt_color);
+***************
+*** 7764,7769 ****
+--- 7962,7969 ----
+ return(h_config_metamsg_color);
+ case V_VIEW_HDR_COLORS :
+ return(h_config_customhdr_color);
++ case V_INDEX_TOKEN_COLORS :
++ return(h_config_indextoken_color);
+ case V_PRINTER :
+ return(h_config_printer);
+ case V_PERSONAL_PRINT_CATEGORY :
+***************
+*** 8194,8196 ****
+--- 8394,8397 ----
+ }
+
+ #endif /* _WINDOWS */
++
+diff -rc alpine-2.00/pith/conf.h alpine-2.00.I.USE/pith/conf.h
+*** alpine-2.00/pith/conf.h 2008-08-19 17:27:11.000000000 -0700
+--- alpine-2.00.I.USE/pith/conf.h 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 143,152 ****
+--- 143,195 ----
+ #define VAR_SORT_KEY vars[V_SORT_KEY].current_val.p
+ #define GLO_SORT_KEY vars[V_SORT_KEY].global_val.p
+ #define COM_SORT_KEY vars[V_SORT_KEY].cmdline_val.p
++ #define VAR_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].current_val.p
++ #define GLO_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].global_val.p
++ #define COM_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].cmdline_val.p
+ #define VAR_AB_SORT_RULE vars[V_AB_SORT_RULE].current_val.p
+ #define GLO_AB_SORT_RULE vars[V_AB_SORT_RULE].global_val.p
+ #define VAR_FLD_SORT_RULE vars[V_FLD_SORT_RULE].current_val.p
+ #define GLO_FLD_SORT_RULE vars[V_FLD_SORT_RULE].global_val.p
++ #define VAR_COMPOSE_RULES vars[V_COMPOSE_RULES].current_val.l
++ #define GLO_COMPOSE_RULES vars[V_COMPOSE_RULES].global_val.l
++ #define USR_COMPOSE_RULES vars[V_COMPOSE_RULES].user_val.l
++ #define VAR_FORWARD_RULES vars[V_FORWARD_RULES].current_val.l
++ #define GLO_FORWARD_RULES vars[V_FORWARD_RULES].global_val.l
++ #define USR_FORWARD_RULES vars[V_FORWARD_RULES].user_val.l
++ #define VAR_INDEX_RULES vars[V_INDEX_RULES].current_val.l
++ #define GLO_INDEX_RULES vars[V_INDEX_RULES].global_val.l
++ #define USR_INDEX_RULES vars[V_INDEX_RULES].user_val.l
++ #define VAR_KEY_RULES vars[V_KEY_RULES].current_val.l
++ #define GLO_KEY_RULES vars[V_KEY_RULES].global_val.l
++ #define USR_KEY_RULES vars[V_KEY_RULES].user_val.l
++ #define VAR_REPLACE_RULES vars[V_REPLACE_RULES].current_val.l
++ #define GLO_REPLACE_RULES vars[V_REPLACE_RULES].global_val.l
++ #define USR_REPLACE_RULES vars[V_REPLACE_RULES].user_val.l
++ #define VAR_REPLY_INDENT_RULES vars[V_REPLY_INDENT_RULES].current_val.l
++ #define GLO_REPLY_INDENT_RULES vars[V_REPLY_INDENT_RULES].global_val.l
++ #define USR_REPLY_INDENT_RULES vars[V_REPLY_INDENT_RULES].user_val.l
++ #define VAR_REPLY_LEADIN_RULES vars[V_REPLY_LEADIN_RULES].current_val.l
++ #define GLO_REPLY_LEADIN_RULES vars[V_REPLY_LEADIN_RULES].global_val.l
++ #define USR_REPLY_LEADIN_RULES vars[V_REPLY_LEADIN_RULES].user_val.l
++ #define VAR_RESUB_RULES vars[V_RESUB_RULES].current_val.l
++ #define GLO_RESUB_RULES vars[V_RESUB_RULES].global_val.l
++ #define USR_RESUB_RULES vars[V_RESUB_RULES].user_val.l
++ #define VAR_THREAD_DISP_STYLE_RULES vars[V_THREAD_DISP_STYLE_RULES].current_val.l
++ #define GLO_THREAD_DISP_STYLE_RULES vars[V_THREAD_DISP_STYLE_RULES].global_val.l
++ #define VAR_THREAD_INDEX_STYLE_RULES vars[V_THREAD_INDEX_STYLE_RULES].current_val.l
++ #define GLO_THREAD_INDEX_STYLE_RULES vars[V_THREAD_INDEX_STYLE_RULES].global_val.l
++ #define VAR_SAVE_RULES vars[V_SAVE_RULES].current_val.l
++ #define GLO_SAVE_RULES vars[V_SAVE_RULES].global_val.l
++ #define USR_SAVE_RULES vars[V_SAVE_RULES].user_val.l
++ #define VAR_SMTP_RULES vars[V_SMTP_RULES].current_val.l
++ #define GLO_SMTP_RULES vars[V_SMTP_RULES].global_val.l
++ #define USR_SMTP_RULES vars[V_SMTP_RULES].user_val.l
++ #define VAR_SORT_RULES vars[V_SORT_RULES].current_val.l
++ #define GLO_SORT_RULES vars[V_SORT_RULES].global_val.l
++ #define USR_SORT_RULES vars[V_SORT_RULES].user_val.l
++ #define VAR_STARTUP_RULES vars[V_STARTUP_RULES].current_val.l
++ #define GLO_STARTUP_RULES vars[V_STARTUP_RULES].global_val.l
++ #define USR_STARTUP_RULES vars[V_STARTUP_RULES].user_val.l
+ #ifndef _WINDOWS
+ #define VAR_CHAR_SET vars[V_CHAR_SET].current_val.p
+ #define GLO_CHAR_SET vars[V_CHAR_SET].global_val.p
+***************
+*** 160,165 ****
+--- 203,210 ----
+ #define GLO_EDITOR vars[V_EDITOR].global_val.l
+ #define VAR_SPELLER vars[V_SPELLER].current_val.p
+ #define GLO_SPELLER vars[V_SPELLER].global_val.p
++ #define VAR_SPECIAL_TEXT vars[V_SPECIAL_TEXT].current_val.l
++ #define GLO_SPECIAL_TEXT vars[V_SPECIAL_TEXT].global_val.l
+ #define VAR_FILLCOL vars[V_FILLCOL].current_val.p
+ #define GLO_FILLCOL vars[V_FILLCOL].global_val.p
+ #define VAR_DEADLETS vars[V_DEADLETS].current_val.p
+***************
+*** 249,254 ****
+--- 294,303 ----
+ #define GLO_NEWS_ACTIVE_PATH vars[V_NEWS_ACTIVE_PATH].global_val.p
+ #define VAR_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].current_val.p
+ #define GLO_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].global_val.p
++ #ifndef _WINDOWS
++ #define VAR_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].current_val.p
++ #define GLO_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].global_val.p
++ #endif
+ #define VAR_DISABLE_DRIVERS vars[V_DISABLE_DRIVERS].current_val.l
+ #define VAR_DISABLE_AUTHS vars[V_DISABLE_AUTHS].current_val.l
+ #define VAR_REMOTE_ABOOK_METADATA vars[V_REMOTE_ABOOK_METADATA].current_val.p
+***************
+*** 373,378 ****
+--- 422,439 ----
+ #define GLO_TITLECLOSED_FORE_COLOR vars[V_TITLECLOSED_FORE_COLOR].global_val.p
+ #define VAR_TITLECLOSED_BACK_COLOR vars[V_TITLECLOSED_BACK_COLOR].current_val.p
+ #define GLO_TITLECLOSED_BACK_COLOR vars[V_TITLECLOSED_BACK_COLOR].global_val.p
++ #define VAR_FOLDER_FORE_COLOR vars[V_FOLDER_FORE_COLOR].current_val.p
++ #define GLO_FOLDER_FORE_COLOR vars[V_FOLDER_FORE_COLOR].global_val.p
++ #define VAR_FOLDER_BACK_COLOR vars[V_FOLDER_BACK_COLOR].current_val.p
++ #define GLO_FOLDER_BACK_COLOR vars[V_FOLDER_BACK_COLOR].global_val.p
++ #define VAR_DIRECTORY_FORE_COLOR vars[V_DIRECTORY_FORE_COLOR].current_val.p
++ #define GLO_DIRECTORY_FORE_COLOR vars[V_DIRECTORY_FORE_COLOR].global_val.p
++ #define VAR_DIRECTORY_BACK_COLOR vars[V_DIRECTORY_BACK_COLOR].current_val.p
++ #define GLO_DIRECTORY_BACK_COLOR vars[V_DIRECTORY_BACK_COLOR].global_val.p
++ #define VAR_FOLDER_LIST_FORE_COLOR vars[V_FOLDER_LIST_FORE_COLOR].current_val.p
++ #define GLO_FOLDER_LIST_FORE_COLOR vars[V_FOLDER_LIST_FORE_COLOR].global_val.p
++ #define VAR_FOLDER_LIST_BACK_COLOR vars[V_FOLDER_LIST_BACK_COLOR].current_val.p
++ #define GLO_FOLDER_LIST_BACK_COLOR vars[V_FOLDER_LIST_BACK_COLOR].global_val.p
+ #define VAR_STATUS_FORE_COLOR vars[V_STATUS_FORE_COLOR].current_val.p
+ #define VAR_STATUS_BACK_COLOR vars[V_STATUS_BACK_COLOR].current_val.p
+ #define VAR_HEADER_GENERAL_FORE_COLOR vars[V_HEADER_GENERAL_FORE_COLOR].current_val.p
+***************
+*** 443,451 ****
+--- 504,515 ----
+ #define GLO_SIGNATURE_FORE_COLOR vars[V_SIGNATURE_FORE_COLOR].global_val.p
+ #define VAR_SIGNATURE_BACK_COLOR vars[V_SIGNATURE_BACK_COLOR].current_val.p
+ #define GLO_SIGNATURE_BACK_COLOR vars[V_SIGNATURE_BACK_COLOR].global_val.p
++ #define VAR_SPECIAL_TEXT_FORE_COLOR vars[V_SPECIAL_TEXT_FORE_COLOR].current_val.p
++ #define VAR_SPECIAL_TEXT_BACK_COLOR vars[V_SPECIAL_TEXT_BACK_COLOR].current_val.p
+ #define VAR_PROMPT_FORE_COLOR vars[V_PROMPT_FORE_COLOR].current_val.p
+ #define VAR_PROMPT_BACK_COLOR vars[V_PROMPT_BACK_COLOR].current_val.p
+ #define VAR_VIEW_HDR_COLORS vars[V_VIEW_HDR_COLORS].current_val.l
++ #define VAR_INDEX_TOKEN_COLORS vars[V_INDEX_TOKEN_COLORS].current_val.l
+ #ifdef SMIME
+ #define VAR_PUBLICCERT_DIR vars[V_PUBLICCERT_DIR].current_val.p
+ #define GLO_PUBLICCERT_DIR vars[V_PUBLICCERT_DIR].global_val.p
+diff -rc alpine-2.00/pith/conftype.h alpine-2.00.I.USE/pith/conftype.h
+*** alpine-2.00/pith/conftype.h 2008-08-19 17:27:11.000000000 -0700
+--- alpine-2.00.I.USE/pith/conftype.h 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 58,63 ****
+--- 58,64 ----
+ , V_SAVED_MSG_NAME_RULE
+ , V_FCC_RULE
+ , V_SORT_KEY
++ , V_THREAD_SORT_KEY
+ , V_AB_SORT_RULE
+ , V_FLD_SORT_RULE
+ , V_GOTO_DEFAULT_RULE
+***************
+*** 69,74 ****
+--- 70,89 ----
+ , V_THREAD_MORE_CHAR
+ , V_THREAD_EXP_CHAR
+ , V_THREAD_LASTREPLY_CHAR
++ , V_THREAD_DISP_STYLE_RULES
++ , V_THREAD_INDEX_STYLE_RULES
++ , V_COMPOSE_RULES
++ , V_FORWARD_RULES
++ , V_INDEX_RULES
++ , V_KEY_RULES
++ , V_REPLACE_RULES
++ , V_REPLY_INDENT_RULES
++ , V_REPLY_LEADIN_RULES
++ , V_RESUB_RULES
++ , V_SAVE_RULES
++ , V_SMTP_RULES
++ , V_SORT_RULES
++ , V_STARTUP_RULES
+ #ifndef _WINDOWS
+ , V_CHAR_SET
+ , V_OLD_CHAR_SET
+***************
+*** 79,84 ****
+--- 94,100 ----
+ , V_EDITOR
+ , V_SPELLER
+ , V_FILLCOL
++ , V_SPECIAL_TEXT
+ , V_REPLY_STRING
+ , V_REPLY_INTRO
+ , V_QUOTE_REPLACE_STRING
+***************
+*** 114,119 ****
+--- 130,138 ----
+ , V_NEWSRC_PATH
+ , V_NEWS_ACTIVE_PATH
+ , V_NEWS_SPOOL_DIR
++ #ifndef _WINDOWS
++ , V_MAILDIR_LOCATION
++ #endif
+ , V_UPLOAD_CMD
+ , V_UPLOAD_CMD_PREFIX
+ , V_DOWNLOAD_CMD
+***************
+*** 203,208 ****
+--- 222,233 ----
+ , V_TITLE_BACK_COLOR
+ , V_TITLECLOSED_FORE_COLOR
+ , V_TITLECLOSED_BACK_COLOR
++ , V_FOLDER_FORE_COLOR
++ , V_FOLDER_BACK_COLOR
++ , V_DIRECTORY_FORE_COLOR
++ , V_DIRECTORY_BACK_COLOR
++ , V_FOLDER_LIST_FORE_COLOR
++ , V_FOLDER_LIST_BACK_COLOR
+ , V_STATUS_FORE_COLOR
+ , V_STATUS_BACK_COLOR
+ , V_KEYLABEL_FORE_COLOR
+***************
+*** 223,228 ****
+--- 248,255 ----
+ , V_INCUNSEEN_BACK_COLOR
+ , V_SIGNATURE_FORE_COLOR
+ , V_SIGNATURE_BACK_COLOR
++ , V_SPECIAL_TEXT_FORE_COLOR
++ , V_SPECIAL_TEXT_BACK_COLOR
+ , V_PROMPT_FORE_COLOR
+ , V_PROMPT_BACK_COLOR
+ , V_HEADER_GENERAL_FORE_COLOR
+***************
+*** 255,260 ****
+--- 282,288 ----
+ , V_IND_FROM_BACK_COLOR
+ , V_IND_OP_FORE_COLOR
+ , V_IND_OP_BACK_COLOR
++ , V_INDEX_TOKEN_COLORS
+ , V_VIEW_HDR_COLORS
+ , V_KW_COLORS
+ #if defined(DOS) || defined(OS2)
+***************
+*** 319,324 ****
+--- 347,353 ----
+ F_FULL_AUTO_EXPUNGE,
+ F_EXPUNGE_MANUALLY,
+ F_AUTO_READ_MSGS,
++ F_AUTO_READ_MSGS_RULES,
+ F_AUTO_FCC_ONLY,
+ F_READ_IN_NEWSRC_ORDER,
+ F_SELECT_WO_CONFIRM,
+***************
+*** 334,342 ****
+--- 363,373 ----
+ F_FORCE_ARROW,
+ F_PRUNE_USES_ISO,
+ F_ALT_ED_NOW,
++ F_IGNORE_SIZE,
+ F_SHOW_DELAY_CUE,
+ F_CANCEL_CONFIRM,
+ F_AUTO_OPEN_NEXT_UNREAD,
++ F_AUTO_CIRCULAR_TAB,
+ F_DISABLE_INDEX_LOCALE_DATES,
+ F_SELECTED_SHOWN_BOLD,
+ F_QUOTE_ALL_FROMS,
+***************
+*** 380,389 ****
+--- 411,424 ----
+ F_PASS_C1_CONTROL_CHARS,
+ F_SINGLE_FOLDER_LIST,
+ F_VERTICAL_FOLDER_LIST,
++ #ifndef _WINDOWS
++ F_COURIER_FOLDER_LIST,
++ #endif
+ F_TAB_CHK_RECENT,
+ F_AUTO_REPLY_TO,
+ F_VERBOSE_POST,
+ F_FCC_ON_BOUNCE,
++ F_USE_DOMAIN_NAME,
+ F_SEND_WO_CONFIRM,
+ F_USE_SENDER_NOT_X,
+ F_BLANK_KEYMENU,
+***************
+*** 428,439 ****
+--- 463,476 ----
+ F_TCAP_WINS,
+ F_ENABLE_SIGDASHES,
+ F_ENABLE_STRIP_SIGDASHES,
++ F_NEW_THREAD_ON_BLANK_SUBJECT,
+ F_QUELL_PARTIAL_FETCH,
+ F_QUELL_PERSONAL_NAME_PROMPT,
+ F_QUELL_USER_ID_PROMPT,
+ F_VIEW_SEL_ATTACH,
+ F_VIEW_SEL_URL,
+ F_VIEW_SEL_URL_HOST,
++ F_VIEW_LONG_URL,
+ F_SCAN_ADDR,
+ F_FORCE_ARROWS,
+ F_PREFER_PLAIN_TEXT,
+***************
+*** 492,502 ****
+--- 529,541 ----
+ F_MAILDROPS_PRESERVE_STATE,
+ F_EXPOSE_HIDDEN_CONFIG,
+ F_ALT_COMPOSE_MENU,
++ F_ALT_REPLY_MENU,
+ F_ALT_ROLE_MENU,
+ F_ALWAYS_SPELL_CHECK,
+ F_QUELL_TIMEZONE,
+ F_QUELL_USERAGENT,
+ F_COLOR_LINE_IMPORTANT,
++ F_ENHANCED_THREAD,
+ F_SLASH_COLL_ENTIRE,
+ F_ENABLE_FULL_HDR_AND_TEXT,
+ F_QUELL_FULL_HDR_RESET,
+***************
+*** 514,519 ****
+--- 553,559 ----
+ F_RENDER_HTML_INTERNALLY,
+ F_ENABLE_JUMP_CMD,
+ F_FORWARD_AS_ATTACHMENT,
++ F_PRESERVE_ORIGINAL_FIELD,
+ #ifndef _WINDOWS
+ F_USE_SYSTEM_TRANS,
+ #endif /* ! _WINDOWS */
+***************
+*** 703,707 ****
+--- 743,748 ----
+
+ /* exported protoypes */
+
++ #define DF_THREAD_SORT_KEY "thread"
+
+ #endif /* PITH_CONFTYPE_INCLUDED */
+diff -rc alpine-2.00/pith/detoken.c alpine-2.00.I.USE/pith/detoken.c
+*** alpine-2.00/pith/detoken.c 2007-08-14 12:02:07.000000000 -0700
+--- alpine-2.00.I.USE/pith/detoken.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 24,30 ****
+ #include "../pith/reply.h"
+ #include "../pith/mailindx.h"
+ #include "../pith/options.h"
+!
+
+ /*
+ * Hook to read signature from local file
+--- 24,30 ----
+ #include "../pith/reply.h"
+ #include "../pith/mailindx.h"
+ #include "../pith/options.h"
+! #include "../pith/rules.h"
+
+ /*
+ * Hook to read signature from local file
+***************
+*** 90,95 ****
+--- 90,97 ----
+
+ if(is_sig){
+ /*
++ * First we check if there is a rule about signatures, if there is
++ * use it, otherwise keep going and do the following:
+ * If role->litsig is set, we use it;
+ * Else, if VAR_LITERAL_SIG is set, we use that;
+ * Else, if role->sig is set, we use that;
+***************
+*** 103,116 ****
+ * there is no reason to mix them, so we don't provide support to
+ * do so.
+ */
+! if(role && role->litsig)
+! literal_sig = role->litsig;
+! else if(ps_global->VAR_LITERAL_SIG)
+! literal_sig = ps_global->VAR_LITERAL_SIG;
+! else if(role && role->sig)
+! sigfile = role->sig;
+! else
+! sigfile = ps_global->VAR_SIGNATURE_FILE;
+ }
+ else if(role && role->template)
+ sigfile = role->template;
+--- 105,129 ----
+ * there is no reason to mix them, so we don't provide support to
+ * do so.
+ */
+! { RULE_RESULT *rule;
+! rule = get_result_rule(V_COMPOSE_RULES, FOR_COMPOSE, env);
+! if (rule){
+! sigfile = cpystr(rule->result);
+! if (rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! }
+! if (!sigfile){
+! if(role && role->litsig)
+! literal_sig = role->litsig;
+! else if(ps_global->VAR_LITERAL_SIG)
+! literal_sig = ps_global->VAR_LITERAL_SIG;
+! else if(role && role->sig)
+! sigfile = role->sig;
+! else
+! sigfile = ps_global->VAR_SIGNATURE_FILE;
+! }
+ }
+ else if(role && role->template)
+ sigfile = role->template;
+***************
+*** 301,307 ****
+ }
+ }
+ }
+! else if(pt->what_for & FOR_REPLY_INTRO)
+ repl = get_reply_data(env, role, pt->ctype,
+ subbuf, sizeof(subbuf)-1);
+
+--- 314,320 ----
+ }
+ }
+ }
+! else if(pt->what_for & (FOR_REPLY_INTRO | FOR_RULE))
+ repl = get_reply_data(env, role, pt->ctype,
+ subbuf, sizeof(subbuf)-1);
+
+diff -rc alpine-2.00/pith/filter.c alpine-2.00.I.USE/pith/filter.c
+*** alpine-2.00/pith/filter.c 2008-08-21 16:50:47.000000000 -0700
+--- alpine-2.00.I.USE/pith/filter.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 45,50 ****
+--- 45,51 ----
+ #include "../pith/conf.h"
+ #include "../pith/store.h"
+ #include "../pith/color.h"
++ #include "../pith/osdep/color.h"
+ #include "../pith/escapes.h"
+ #include "../pith/pipe.h"
+ #include "../pith/status.h"
+***************
+*** 1020,1026 ****
+ */
+ char *
+ gf_filter(char *cmd, char *prepend, STORE_S *source_so, gf_io_t pc,
+! FILTLIST_S *aux_filters, int disable_reset,
+ void (*pipecb_f)(PIPE_S *, int, void *))
+ {
+ unsigned char c, obuf[MAX(MB_LEN_MAX,32)];
+--- 1021,1027 ----
+ */
+ char *
+ gf_filter(char *cmd, char *prepend, STORE_S *source_so, gf_io_t pc,
+! FILTLIST_S *aux_filters, int silent, int disable_reset,
+ void (*pipecb_f)(PIPE_S *, int, void *))
+ {
+ unsigned char c, obuf[MAX(MB_LEN_MAX,32)];
+***************
+*** 1057,1064 ****
+ * Spawn filter feeding it data, and reading what it writes.
+ */
+ so_seek(source_so, 0L, 0);
+! flags = PIPE_WRITE | PIPE_READ | PIPE_NOSHELL |
+! (!disable_reset ? PIPE_RESET : 0);
+
+ if((fpipe = open_system_pipe(cmd, NULL, NULL, flags, 0, pipecb_f, pipe_report_error)) != NULL){
+
+--- 1058,1066 ----
+ * Spawn filter feeding it data, and reading what it writes.
+ */
+ so_seek(source_so, 0L, 0);
+! flags = PIPE_WRITE | PIPE_READ | PIPE_NOSHELL
+! | (silent ? PIPE_SILENT : 0)
+! | (!disable_reset ? PIPE_RESET : 0);
+
+ if((fpipe = open_system_pipe(cmd, NULL, NULL, flags, 0, pipecb_f, pipe_report_error)) != NULL){
+
+***************
+*** 1373,1386 ****
+ register unsigned char t = f->t;
+ register int n = (int) f->n;
+ register int state = f->f1;
+
+ while(GF_GETC(f, c)){
+
+ if(state){
+ state = 0;
+ if (c != '=') {
+! gf_error("Illegal '=' in base64 text");
+! /* NO RETURN */
+ }
+ }
+
+--- 1375,1398 ----
+ register unsigned char t = f->t;
+ register int n = (int) f->n;
+ register int state = f->f1;
++ register unsigned char lastc;
+
+ while(GF_GETC(f, c)){
+
++ lastc = c;
++ if(f->f2){
++ GF_PUTC(f->next, c);
++ continue;
++ }
++
+ if(state){
+ state = 0;
+ if (c != '=') {
+! f->f2++;
+! GF_PUTC(f->next, c);
+! q_status_message(SM_ORDER,3,3,
+! _("Warning: Illegal '=' in base64 text"));
+! continue;
+ }
+ }
+
+***************
+*** 1397,1404 ****
+ break;
+
+ default: /* impossible quantum position */
+! gf_error("Internal base64 decoder error");
+! /* NO RETURN */
+ }
+ }
+ }
+--- 1409,1419 ----
+ break;
+
+ default: /* impossible quantum position */
+! f->f2++;
+! GF_PUTC(f->next, lastc);
+! q_status_message(SM_ORDER,3,3,
+! _("Warning: Internal base64 decode error"));
+! break;
+ }
+ }
+ }
+***************
+*** 1439,1444 ****
+--- 1454,1460 ----
+ dprint((9, "-- gf_reset b64_binary\n"));
+ f->n = 0L; /* quantum position */
+ f->f1 = 0; /* state holder: equal seen? */
++ f->f2 = 0; /* No errors when we start */
+ }
+ }
+
+***************
+*** 4979,4984 ****
+--- 4995,5001 ----
+ && p->value
+ && (HANDLES_LOC(hd->html_data)
+ || struncmp(p->value, "x-alpine-", 9)
++ || struncmp(p->value, "x-pine-help", 11)
+ || p->value[0] == '#'))
+ href = p;
+ else if(!strucmp(p->attribute, "NAME"))
+***************
+*** 7587,7592 ****
+--- 7604,7610 ----
+ char *p, buf[MAILTMPLEN];
+ ADDRESS *adr;
+ extern char datestamp[];
++ extern char plevstamp[];
+
+ if(!strcmp(s = removing_quotes(s + 4), "ALPINE_VERSION")){
+ p = ALPINE_VERSION;
+***************
+*** 7600,7605 ****
+--- 7618,7626 ----
+ else if(!strcmp(s, "ALPINE_COMPILE_DATE")){
+ p = datestamp;
+ }
++ else if(!strcmp(s, "ALPINE_PATCHLEVEL")){
++ p = plevstamp;
++ }
+ else if(!strcmp(s, "ALPINE_TODAYS_DATE")){
+ rfc822_date(p = buf);
+ }
+***************
+*** 9155,9160 ****
+--- 9176,9186 ----
+ margin_r,
+ indent;
+ char special[256];
++ long curlinenum; /* current line number */
++ int curqstrpos; /* current position in quote string */
++ long linenum; /* line number */
++ long qstrlen; /* multiples of 100 */
++ char **qstrln; /* qstrln[i] = quote string line i - 1 */
+ } WRAP_S;
+
+ #define WRAP_MARG_L(F) (((WRAP_S *)(F)->opt)->margin_l)
+***************
+*** 9196,9201 ****
+--- 9222,9233 ----
+ #define WRAP_COLOR(F) (((WRAP_S *)(F)->opt)->color)
+ #define WRAP_COLOR_SET(F) ((WRAP_COLOR(F)) && (WRAP_COLOR(F)->fg[0]))
+ #define WRAP_SPACES(F) (((WRAP_S *)(F)->opt)->spaces)
++ #define WRAP_CURLINE(F) (((WRAP_S *)(F)->opt)->curlinenum)
++ #define WRAP_CURPOS(F) (((WRAP_S *)(F)->opt)->curqstrpos)
++ #define WRAP_LINENUM(F) (((WRAP_S *)(F)->opt)->linenum)
++ #define WRAP_QSTRLEN(F) (((WRAP_S *)(F)->opt)->qstrlen)
++ #define WRAP_QSTRN(F) (((WRAP_S *)(F)->opt)->qstrln)
++ #define WRAP_QSTR(F, N) (((WRAP_S *)(F)->opt)->qstrln[(N)])
+ #define WRAP_PUTC(F,C,W) { \
+ if((F)->linep == WRAP_LASTC(F)){ \
+ size_t offset = (F)->linep - (F)->line; \
+***************
+*** 9273,9278 ****
+--- 9305,9312 ----
+ case CCR : /* CRLF or CR in text ? */
+ state = BOL; /* either way, handle start */
+
++ WRAP_CURLINE(f)++;
++ WRAP_CURPOS(f) = 0;
+ if(WRAP_FLOW(f)){
+ /* wrapped line? */
+ if(f->f2 == 0 && WRAP_SPC_LEN(f) && WRAP_TRL_SPC(f)){
+***************
+*** 9366,9372 ****
+
+ case BOL :
+ if(WRAP_FLOW(f)){
+! if(c == '>'){
+ WRAP_FL_QC(f) = 1; /* init it */
+ state = FL_QLEV; /* go collect it */
+ }
+--- 9400,9410 ----
+
+ case BOL :
+ if(WRAP_FLOW(f)){
+! if(WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
+! && WRAP_QSTR(f, WRAP_CURLINE(f))
+! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)]
+! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)] == c){
+! WRAP_CURPOS(f)++;
+ WRAP_FL_QC(f) = 1; /* init it */
+ state = FL_QLEV; /* go collect it */
+ }
+***************
+*** 9380,9386 ****
+ }
+
+ /* quote level change implies new paragraph */
+! if(WRAP_FL_QD(f)){
+ WRAP_FL_QD(f) = 0;
+ if(WRAP_HARD(f) == 0){
+ WRAP_HARD(f) = 1;
+--- 9418,9433 ----
+ }
+
+ /* quote level change implies new paragraph */
+! if (WRAP_CURLINE(f) > 0
+! && WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
+! && (WRAP_QSTR(f, WRAP_CURLINE(f)) != NULL
+! || WRAP_QSTR(f, WRAP_CURLINE(f) - 1) != NULL)
+! && ((WRAP_QSTR(f, WRAP_CURLINE(f)) != NULL &&
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1) == NULL)
+! || (WRAP_QSTR(f, WRAP_CURLINE(f)) == NULL &&
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1) != NULL)
+! || strcmp(WRAP_QSTR(f, WRAP_CURLINE(f)),
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1)))){
+ WRAP_FL_QD(f) = 0;
+ if(WRAP_HARD(f) == 0){
+ WRAP_HARD(f) = 1;
+***************
+*** 9432,9439 ****
+ break;
+
+ case FL_QLEV :
+! if(c == '>'){ /* another level */
+! WRAP_FL_QC(f)++;
+ }
+ else {
+ /* if EMBEDed, process it and return here */
+--- 9479,9490 ----
+ break;
+
+ case FL_QLEV :
+! if(WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
+! && WRAP_QSTR(f, WRAP_CURLINE(f))
+! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)]
+! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)] == c){
+! WRAP_CURPOS(f)++;
+! WRAP_FL_QC(f)++; /* another level */
+ }
+ else {
+ /* if EMBEDed, process it and return here */
+***************
+*** 9445,9451 ****
+ }
+
+ /* quote level change signals new paragraph */
+! if(WRAP_FL_QC(f) != WRAP_FL_QD(f)){
+ WRAP_FL_QD(f) = WRAP_FL_QC(f);
+ if(WRAP_HARD(f) == 0){ /* add hard newline */
+ WRAP_HARD(f) = 1; /* hard newline */
+--- 9496,9511 ----
+ }
+
+ /* quote level change signals new paragraph */
+! if (WRAP_CURLINE(f) > 0
+! && WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
+! && (WRAP_QSTR(f, WRAP_CURLINE(f))
+! || WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
+! && ((WRAP_QSTR(f, WRAP_CURLINE(f)) &&
+! !WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
+! || (!WRAP_QSTR(f, WRAP_CURLINE(f)) &&
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
+! || strcmp(WRAP_QSTR(f, WRAP_CURLINE(f)),
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1)))){
+ WRAP_FL_QD(f) = WRAP_FL_QC(f);
+ if(WRAP_HARD(f) == 0){ /* add hard newline */
+ WRAP_HARD(f) = 1; /* hard newline */
+***************
+*** 9502,9507 ****
+--- 9562,9574 ----
+ state = FL_SIG;
+ break;
+
++ case ' ' : /* what? */
++ if (WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
++ && WRAP_QSTR(f, WRAP_CURLINE(f))){
++ WRAP_SPC_LEN(f)++;
++ so_writec(' ', WRAP_SPACES(f));
++ }
++
+ default : /* something else */
+ state = DFL;
+ goto case_dfl; /* handle c like DFL */
+***************
+*** 9518,9524 ****
+ &eob); /* note any embedded*/
+ wrap_eol(f, 1, &ip, &eib,
+ &op, &eob); /* plunk down newline */
+! wrap_bol(f, 1, 1, &ip, &eib,
+ &op, &eob); /* write any prefix */
+ }
+
+--- 9585,9591 ----
+ &eob); /* note any embedded*/
+ wrap_eol(f, 1, &ip, &eib,
+ &op, &eob); /* plunk down newline */
+! wrap_bol(f, 1, WRAP_FLOW(f), &ip, &eib,
+ &op, &eob); /* write any prefix */
+ }
+
+***************
+*** 10015,10021 ****
+ wrap_flush_embed(f, &ip, &eib, &op, &eob);
+ wrap_eol(f, 1, &ip, &eib, &op,
+ &eob); /* plunk down newline */
+! wrap_bol(f,1,1, &ip, &eib, &op,
+ &eob); /* write any prefix */
+ }
+
+--- 10082,10088 ----
+ wrap_flush_embed(f, &ip, &eib, &op, &eob);
+ wrap_eol(f, 1, &ip, &eib, &op,
+ &eob); /* plunk down newline */
+! wrap_bol(f,1,WRAP_FLOW(f), &ip, &eib, &op,
+ &eob); /* write any prefix */
+ }
+
+***************
+*** 10088,10093 ****
+--- 10155,10167 ----
+ if(WRAP_COLOR(f))
+ free_color_pair(&WRAP_COLOR(f));
+
++ { long i;
++ for (i = 0L; i < WRAP_QSTRLEN(f); i++)
++ if (WRAP_QSTR(f,i))
++ fs_give((void **) &(WRAP_QSTR(f,i)));
++ fs_give((void **)&WRAP_QSTRN(f));
++ }
++
+ fs_give((void **) &f->line); /* free temp line buffer */
+ so_give(&WRAP_SPACES(f));
+ fs_give((void **) &f->opt); /* free wrap widths struct */
+***************
+*** 10438,10444 ****
+ {
+ int j, i;
+ COLOR_PAIR *col = NULL;
+! char *prefix = NULL, *last_prefix = NULL;
+
+ if(ps_global->VAR_QUOTE_REPLACE_STRING){
+ get_pair(ps_global->VAR_QUOTE_REPLACE_STRING, &prefix, &last_prefix, 0, 0);
+--- 10512,10519 ----
+ {
+ int j, i;
+ COLOR_PAIR *col = NULL;
+! char *prefix = NULL, *last_prefix = NULL, *wrap_qstr = NULL;
+! int level = 0, oldj, len;
+
+ if(ps_global->VAR_QUOTE_REPLACE_STRING){
+ get_pair(ps_global->VAR_QUOTE_REPLACE_STRING, &prefix, &last_prefix, 0, 0);
+***************
+*** 10447,10456 ****
+ last_prefix = NULL;
+ }
+ }
+!
+! for(j = 0; j < WRAP_FL_QD(f); j++){
+ if(WRAP_USE_CLR(f)){
+! if((j % 3) == 0
+ && ps_global->VAR_QUOTE1_FORE_COLOR
+ && ps_global->VAR_QUOTE1_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE1_FORE_COLOR,
+--- 10522,10543 ----
+ last_prefix = NULL;
+ }
+ }
+!
+! if(WRAP_CURLINE(f) < WRAP_QSTRLEN(f) && WRAP_QSTR(f, WRAP_CURLINE(f)))
+! wrap_qstr = cpystr(WRAP_QSTR(f, WRAP_CURLINE(f)));
+! len = wrap_qstr ? strlen(wrap_qstr) : 0;
+!
+! for (j = wrap_qstr && *wrap_qstr == ' ' ? 1 : 0;
+! j < len && isspace((unsigned char)wrap_qstr[j]); j++){
+! GF_PUTC_GLO(f->next, wrap_qstr[j]);
+! f->n += ((wrap_qstr[j] == TAB) ? (~f->n & 0x07) + 1 : 1);
+! }
+!
+! for(; j < len && level < len; level++){
+! oldj = j;
+! j = next_level_quote(wrap_qstr, (char **)NULL, j, WRAP_FLOW(f));
+ if(WRAP_USE_CLR(f)){
+! if((level % 3) == 0
+ && ps_global->VAR_QUOTE1_FORE_COLOR
+ && ps_global->VAR_QUOTE1_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE1_FORE_COLOR,
+***************
+*** 10458,10464 ****
+ && pico_is_good_colorpair(col)){
+ GF_COLOR_PUTC(f, col);
+ }
+! else if((j % 3) == 1
+ && ps_global->VAR_QUOTE2_FORE_COLOR
+ && ps_global->VAR_QUOTE2_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE2_FORE_COLOR,
+--- 10545,10551 ----
+ && pico_is_good_colorpair(col)){
+ GF_COLOR_PUTC(f, col);
+ }
+! else if((level % 3) == 1
+ && ps_global->VAR_QUOTE2_FORE_COLOR
+ && ps_global->VAR_QUOTE2_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE2_FORE_COLOR,
+***************
+*** 10466,10472 ****
+ && pico_is_good_colorpair(col)){
+ GF_COLOR_PUTC(f, col);
+ }
+! else if((j % 3) == 2
+ && ps_global->VAR_QUOTE3_FORE_COLOR
+ && ps_global->VAR_QUOTE3_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE3_FORE_COLOR,
+--- 10553,10559 ----
+ && pico_is_good_colorpair(col)){
+ GF_COLOR_PUTC(f, col);
+ }
+! else if((level % 3) == 2
+ && ps_global->VAR_QUOTE3_FORE_COLOR
+ && ps_global->VAR_QUOTE3_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE3_FORE_COLOR,
+***************
+*** 10480,10522 ****
+ }
+ }
+
+ if(!WRAP_LV_FLD(f)){
+ if(!WRAP_FOR_CMPS(f) && ps_global->VAR_QUOTE_REPLACE_STRING && prefix){
+ for(i = 0; prefix[i]; i++)
+ GF_PUTC_GLO(f->next, prefix[i]);
+! f->n += utf8_width(prefix);
+! }
+! else if(ps_global->VAR_REPLY_STRING
+! && (!strcmp(ps_global->VAR_REPLY_STRING, ">")
+! || !strcmp(ps_global->VAR_REPLY_STRING, "\">\""))){
+! GF_PUTC_GLO(f->next, '>');
+! f->n += 1;
+ }
+ else{
+! GF_PUTC_GLO(f->next, '>');
+! GF_PUTC_GLO(f->next, ' ');
+! f->n += 2;
+ }
+ }
+ else{
+! GF_PUTC_GLO(f->next, '>');
+! f->n += 1;
+ }
+ }
+ if(j && WRAP_LV_FLD(f)){
+ GF_PUTC_GLO(f->next, ' ');
+ f->n++;
+ }
+! else if(j && last_prefix){
+ for(i = 0; last_prefix[i]; i++)
+ GF_PUTC_GLO(f->next, last_prefix[i]);
+! f->n += utf8_width(last_prefix);
+ }
+
+ if(prefix)
+ fs_give((void **)&prefix);
+ if(last_prefix)
+ fs_give((void **)&last_prefix);
+
+ return 0;
+ }
+--- 10567,10626 ----
+ }
+ }
+
++ if (j > 1 && wrap_qstr[j-1] == ' ')
++ j -= 1;
++
+ if(!WRAP_LV_FLD(f)){
+ if(!WRAP_FOR_CMPS(f) && ps_global->VAR_QUOTE_REPLACE_STRING && prefix){
+ for(i = 0; prefix[i]; i++)
+ GF_PUTC_GLO(f->next, prefix[i]);
+! f->n += utf8_widthis(prefix);
+ }
+ else{
+! for (i = oldj; i < j; i++)
+! GF_PUTC_GLO(f->next, wrap_qstr[i]);
+! f->n += j - oldj;
+ }
+ }
+ else{
+! for (i = oldj; i < j; i++)
+! GF_PUTC_GLO(f->next, wrap_qstr[i]);
+! f->n += j - oldj;
+! }
+! for (i = j; isspace((unsigned char)wrap_qstr[i]); i++);
+! if(!wrap_qstr[i]){
+! f->n += i - j;
+! for (; j < i; j++)
+! GF_PUTC_GLO(f->next, ' ');
+! }
+! else{
+! if((WRAP_LV_FLD(f)
+! || !ps_global->VAR_QUOTE_REPLACE_STRING || !prefix)
+! || !ps_global->VAR_REPLY_STRING
+! || (strcmp(ps_global->VAR_REPLY_STRING, ">")
+! && strcmp(ps_global->VAR_REPLY_STRING, "\">\""))){
+! GF_PUTC_GLO(f->next, ' ');
+! f->n += 1;
+! }
+ }
++ for (; isspace((unsigned char)wrap_qstr[j]); j++);
+ }
+ if(j && WRAP_LV_FLD(f)){
+ GF_PUTC_GLO(f->next, ' ');
+ f->n++;
+ }
+! else if(j && !value_is_space(wrap_qstr) && last_prefix){
+ for(i = 0; last_prefix[i]; i++)
+ GF_PUTC_GLO(f->next, last_prefix[i]);
+! f->n += utf8_widthis(last_prefix);
+ }
+
+ if(prefix)
+ fs_give((void **)&prefix);
+ if(last_prefix)
+ fs_give((void **)&last_prefix);
++ if (wrap_qstr)
++ fs_give((void **)&wrap_qstr);
+
+ return 0;
+ }
+***************
+*** 10548,10553 ****
+--- 10652,10663 ----
+ wrap->hdr_color = (GFW_HDRCOLOR & flags) == GFW_HDRCOLOR;
+ wrap->for_compose = (GFW_FORCOMPOSE & flags) == GFW_FORCOMPOSE;
+ wrap->handle_soft_hyphen = (GFW_SOFTHYPHEN & flags) == GFW_SOFTHYPHEN;
++ wrap->curlinenum = 0L;
++ wrap->curqstrpos = 0;
++ wrap->linenum = 0L;
++ wrap->qstrlen = 100L;
++ wrap->qstrln = (char **) fs_get(100*sizeof(char *));
++ memset(wrap->qstrln, 0, 100*sizeof(char *));
+
+ return((void *) wrap);
+ }
+***************
+*** 10991,10997 ****
+--- 11101,11315 ----
+ } \
+ }
+
++ #define ADD_QUOTE_STRING(F) { \
++ int len = tmp_20k_buf[0] ? strlen(tmp_20k_buf) + 1 : 0; \
++ FILTER_S *fltr; \
++ \
++ for(fltr = (F); fltr && fltr->f != gf_wrap; fltr = fltr->next); \
++ if (fltr){ \
++ if (WRAP_LINENUM(fltr) >= WRAP_QSTRLEN(fltr)){ \
++ fs_resize((void **)&WRAP_QSTRN(fltr), \
++ (WRAP_QSTRLEN(fltr) + 100) * sizeof(char *)); \
++ memset(WRAP_QSTRN(fltr)+WRAP_QSTRLEN(fltr), 0, \
++ 100*sizeof(char*)); \
++ WRAP_QSTRLEN(fltr) += 100L; \
++ } \
++ if (len){ \
++ WRAP_QSTR(fltr, WRAP_LINENUM(fltr)) = \
++ (char *) fs_get(len*sizeof(char)); \
++ WRAP_QSTR(fltr, WRAP_LINENUM(fltr)) = cpystr(tmp_20k_buf);\
++ } \
++ WRAP_LINENUM(fltr)++; \
++ } \
++ }
++
++ int end_of_line(char *line)
++ {
++ int i;
++
++ for(i= 0; line && line[i]; i++){
++ if((line[i] == '\015' && line[i+1] == '\012') || line[i] == '\012')
++ break;
++ }
++ return i;
++ }
++
++ /* This macro is used in gf_quote_test. It receives a return code
++ from a filter. All filters that will print something must send
++ return code 0, except color_a_quote which must send return code
++ 1
++ */
++
++ #define GF_ADD_QUOTED_LINE(F, line) \
++ { \
++ LT_INS_S *ins = NULL, *insp; \
++ int done; \
++ char *gline, *cline;\
++ unsigned char ch;\
++ register char *cp;\
++ register int l;\
++ \
++ for (gline = cline = line; gline && cline; ){\
++ if(cline = strchr(gline,'\012'))\
++ *cline = '\0';\
++ done = (*((LINETEST_S *) (F)->opt)->f)((F)->n++, gline, &ins,\
++ ((LINETEST_S *) (F)->opt)->local);\
++ if (done < 2){ \
++ if(done == 1)\
++ ADD_QUOTE_STRING((F));\
++ for(insp = ins, cp = gline; *cp ; ){\
++ if(insp && cp == insp->where){\
++ if(insp->len > 0){ \
++ for(l = 0; l < insp->len; l++){\
++ ch = (unsigned char) insp->text[l];\
++ GF_PUTC((F)->next, ch);\
++ }\
++ insp = insp->next;\
++ continue; \
++ } else if(insp->len < 0){ \
++ cp -= insp->len; \
++ insp = insp->next; \
++ continue; \
++ } \
++ }\
++ GF_PUTC((F)->next, *cp);\
++ cp++;\
++ }\
++ while(insp){\
++ for(l = 0; l < insp->len; l++){\
++ ch = (unsigned char) insp->text[l];\
++ GF_PUTC((F)->next, ch);\
++ }\
++ insp = insp->next;\
++ }\
++ gf_line_test_free_ins(&ins);\
++ if(cline){ \
++ *cline = '\012';\
++ gline += cline - gline + 1;\
++ }\
++ GF_PUTC((F)->next, '\015');\
++ GF_PUTC((F)->next, '\012');\
++ }\
++ }\
++ }
++ /* test second line of old line first */
++ #define SECOND_LINE_QUOTE_TEST(line, F) \
++ {\
++ *p = '\0';\
++ i = end_of_line((F)->oldline); \
++ if (((F)->oldline)[i]){\
++ i += (((F)->oldline)[i] == '\015') ? 2 : 1;\
++ line = (F)->oldline + i;\
++ i = end_of_line(line); \
++ if(line[i])\
++ line[i] = '\0'; \
++ }\
++ for (i = 0; ((F)->line) \
++ && (i < LINE_TEST_BLOCK) \
++ && (i < SIZEOF_20KBUF)\
++ && ((F)->line)[i] \
++ && (((F)->line)[i] != '\015')\
++ && (((F)->line)[i] != '\012')\
++ && (tmp_20k_buf[i] = ((F)->line)[i]); i++);\
++ tmp_20k_buf[i] = '\0';\
++ GF_ADD_QUOTED_LINE((F), line);\
++ }
++
++ #define FIRST_LINE_QUOTE_TEST(line, F)\
++ {\
++ *p = '\0';\
++ line = (F)->line;\
++ if ((F)->oldline)\
++ fs_give((void **)&(F)->oldline);\
++ (F)->oldline = cpystr(line);\
++ i = end_of_line(line); \
++ if (line[i]){ \
++ j = (line[i] == '\015') ? 2 : 1;\
++ line[i] = '\0'; \
++ i += j; \
++ }\
++ for (j = 0; ((F)->line) \
++ && ((i + j) < LINE_TEST_BLOCK) \
++ && (j < SIZEOF_20KBUF) \
++ && ((F)->line)[i + j] \
++ && (((F)->line)[i + j] != '\015')\
++ && (((F)->line)[i + j] != '\012')\
++ && (tmp_20k_buf[j] = ((F)->line)[i + j]); j++);\
++ tmp_20k_buf[j] = '\0';\
++ GF_ADD_QUOTED_LINE((F), line);\
++ }
++
++
++ void
++ gf_quote_test(f, flg)
++ FILTER_S *f;
++ int flg;
++ {
++ register char *p = f->linep;
++ register char *eobuf = GF_LINE_TEST_EOB(f);
++ char *line = NULL;
++ int i, j;
++ GF_INIT(f, f->next);
++
++ if(flg == GF_DATA){
++ register unsigned char c;
++ register int state = f->f1;
++
++ while(GF_GETC(f, c)){
++
++ GF_LINE_TEST_ADD(f, c);
++ if(c == '\012')
++ state++;
++ if(state == 2){ /* two full lines read */
++ state = 0;
++
++ /* first process the second line of an old line */
++ if (f->oldline && f->oldline[0])
++ SECOND_LINE_QUOTE_TEST(line, f);
++
++ /* now we process the first line */
++ FIRST_LINE_QUOTE_TEST(line, f);
+
++ p = f->line;
++ }
++ }
++
++ f->f1 = state;
++ GF_END(f, f->next);
++ }
++ else if(flg == GF_EOD){
++ /* first process the second line of an old line */
++ if (f->oldline && f->oldline[0])
++ SECOND_LINE_QUOTE_TEST(line, f);
++
++ /* now we process the first line */
++ FIRST_LINE_QUOTE_TEST(line, f);
++
++ /* We are out of data. In this case we have processed the second
++ * line of an oldline, then the first line of a line, but we need
++ * to process the second line of the given line. We do this by
++ * processing it now!.
++ */
++ if (line[i]){
++ tmp_20k_buf[0] = '\0'; /* No next line */
++ GF_ADD_QUOTED_LINE(f, line+i);
++ }
++
++ fs_give((void **) &f->oldline); /* free old line buffer */
++ fs_give((void **) &f->line); /* free line buffer */
++ fs_give((void **) &f->opt); /* free test struct */
++ GF_FLUSH(f->next);
++ (*f->next->f)(f->next, GF_EOD);
++ }
++ else if(flg == GF_RESET){
++ f->f1 = 0; /* state */
++ f->n = 0L; /* line number */
++ f->f2 = LINE_TEST_BLOCK; /* size of alloc'd line */
++ f->line = p = (char *) fs_get(f->f2 * sizeof(char));
++ }
++
++ f->linep = p;
++ }
+
+ /*
+ * this simple filter accumulates characters until a newline, offers it
+diff -rc alpine-2.00/pith/filter.h alpine-2.00.I.USE/pith/filter.h
+*** alpine-2.00/pith/filter.h 2008-08-22 12:46:13.000000000 -0700
+--- alpine-2.00.I.USE/pith/filter.h 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 175,181 ****
+ char *gf_pipe(gf_io_t, gf_io_t);
+ long gf_bytes_piped(void);
+ char *gf_filter(char *, char *, STORE_S *, gf_io_t, FILTLIST_S *, int,
+! void (*)(PIPE_S *, int, void *));
+ void gf_binary_b64(FILTER_S *, int);
+ void gf_b64_binary(FILTER_S *, int);
+ void gf_qp_8bit(FILTER_S *, int);
+--- 175,181 ----
+ char *gf_pipe(gf_io_t, gf_io_t);
+ long gf_bytes_piped(void);
+ char *gf_filter(char *, char *, STORE_S *, gf_io_t, FILTLIST_S *, int,
+! int, void (*)(PIPE_S *, int, void *));
+ void gf_binary_b64(FILTER_S *, int);
+ void gf_b64_binary(FILTER_S *, int);
+ void gf_qp_8bit(FILTER_S *, int);
+***************
+*** 215,220 ****
+--- 215,221 ----
+ void *gf_prepend_editorial_opt(prepedtest_t, char *);
+ void gf_nvtnl_local(FILTER_S *, int);
+ void gf_local_nvtnl(FILTER_S *, int);
++ void gf_quote_test(FILTER_S *, int);
+ void *gf_url_hilite_opt(URL_HILITE_S *, HANDLE_S **, int);
+
+
+diff -rc alpine-2.00/pith/filttype.h alpine-2.00.I.USE/pith/filttype.h
+*** alpine-2.00/pith/filttype.h 2007-04-25 21:06:02.000000000 -0700
+--- alpine-2.00.I.USE/pith/filttype.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 35,40 ****
+--- 35,42 ----
+ unsigned char t; /* temporary char */
+ char *line; /* place for temporary storage */
+ char *linep; /* pointer into storage space */
++ char *oldline; /* the previous line to "line" */
++ char *oldlinep; /* the previous line to "line" */
+ void *opt; /* optional per instance data */
+ void *data; /* misc internal data pointer */
+ unsigned char queue[1 + GF_MAXBUF];
+diff -rc alpine-2.00/pith/flag.c alpine-2.00.I.USE/pith/flag.c
+*** alpine-2.00/pith/flag.c 2008-07-14 11:01:54.000000000 -0700
+--- alpine-2.00.I.USE/pith/flag.c 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 593,606 ****
+
+ was_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0;
+
+ if((chk_thrd_cnt = ((msgs->visible_threads >= 0L)
+ && THRD_INDX_ENABLED() && (f & MN_HIDE) && (pelt->hidden != v))) != 0){
+ thrd = fetch_thread(stream, rawno);
+ if(thrd && thrd->top){
+! if(thrd->top == thrd->rawno)
+ topthrd = thrd;
+ else
+! topthrd = fetch_thread(stream, thrd->top);
+ }
+
+ if(topthrd){
+--- 593,608 ----
+
+ was_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0;
+
++ thrd = fetch_thread(stream, rawno);
++
+ if((chk_thrd_cnt = ((msgs->visible_threads >= 0L)
+ && THRD_INDX_ENABLED() && (f & MN_HIDE) && (pelt->hidden != v))) != 0){
+ thrd = fetch_thread(stream, rawno);
+ if(thrd && thrd->top){
+! if(top_thread(stream, thrd->top) == thrd->rawno)
+ topthrd = thrd;
+ else
+! topthrd = fetch_thread(stream, top_thread(stream, thrd->top));
+ }
+
+ if(topthrd){
+diff -rc alpine-2.00/pith/handle.h alpine-2.00.I.USE/pith/handle.h
+*** alpine-2.00/pith/handle.h 2007-11-13 16:47:15.000000000 -0800
+--- alpine-2.00.I.USE/pith/handle.h 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 39,44 ****
+--- 39,45 ----
+ unsigned using_is_used:1; /* bit below is being used */
+ unsigned is_used:1; /* if not, remove it from list */
+ unsigned color_unseen:1; /* we're coloring folders with unseen */
++ unsigned color_folder:1; /* and just folders for that matter... */
+ unsigned is_dual_do_open:1; /* choosing this handle means open */
+ union {
+ struct { /* URL corresponding to this handle */
+diff -rc alpine-2.00/pith/imap.c alpine-2.00.I.USE/pith/imap.c
+*** alpine-2.00/pith/imap.c 2008-07-14 11:01:54.000000000 -0700
+--- alpine-2.00.I.USE/pith/imap.c 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 1108,1110 ****
+--- 1108,1172 ----
+
+ return(block);
+ }
++
++
++ void
++ pine_delete_pwd(NETMBX *mb, char *user)
++ {
++ char hostlist0[MAILTMPLEN], hostlist1[MAILTMPLEN];
++ char port[20], non_def_port[20], insecure[20];
++ STRLIST_S hostlist[2];
++ MMLOGIN_S *l;
++ struct servent *sv;
++
++
++ dprint((9, "pine_delete_pwd\n"));
++
++ /* setup hostlist */
++ non_def_port[0] = '\0';
++ if(mb->port && mb->service &&
++ (sv = getservbyname(mb->service, "tcp")) &&
++ (mb->port != ntohs(sv->s_port))){
++ snprintf(non_def_port, sizeof(non_def_port), ":%lu", mb->port);
++ non_def_port[sizeof(non_def_port)-1] = '\0';
++ dprint((9, "mm_login: using non-default port=%s\n",
++ non_def_port ? non_def_port : "?"));
++ }
++
++ if(*non_def_port){
++ strncpy(hostlist0, mb->host, sizeof(hostlist0)-1);
++ hostlist0[sizeof(hostlist0)-1] = '\0';
++ strncat(hostlist0, non_def_port, sizeof(hostlist0)-strlen(hostlist0)-1);
++ hostlist0[sizeof(hostlist0)-1] = '\0';
++ hostlist[0].name = hostlist0;
++ if(mb->orighost && mb->orighost[0] && strucmp(mb->host, mb->orighost)){
++ strncpy(hostlist1, mb->orighost, sizeof(hostlist1)-1);
++ hostlist1[sizeof(hostlist1)-1] = '\0';
++ strncat(hostlist1, non_def_port, sizeof(hostlist1)-strlen(hostlist1)-1);
++ hostlist1[sizeof(hostlist1)-1] = '\0';
++ hostlist[0].next = &hostlist[1];
++ hostlist[1].name = hostlist1;
++ hostlist[1].next = NULL;
++ }
++ else
++ hostlist[0].next = NULL;
++ }
++ else{
++ hostlist[0].name = mb->host;
++ if(mb->orighost && mb->orighost[0] && strucmp(mb->host, mb->orighost)){
++ hostlist[0].next = &hostlist[1];
++ hostlist[1].name = mb->orighost;
++ hostlist[1].next = NULL;
++ }
++ else
++ hostlist[0].next = NULL;
++ }
++
++ for(l = mm_login_list; l; l = l->next)
++ if(imap_same_host(l->hosts, hostlist)
++ && !strcmp(l->user, user ? user : "")
++ && l->passwd){
++ l->passwd[0] = '\0';
++ break;
++ }
++ }
+diff -rc alpine-2.00/pith/imap.h alpine-2.00.I.USE/pith/imap.h
+*** alpine-2.00/pith/imap.h 2008-04-23 19:00:26.000000000 -0700
+--- alpine-2.00.I.USE/pith/imap.h 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 123,129 ****
+ int imap_get_passwd(MMLOGIN_S *, char *, char *, STRLIST_S *, int);
+ void imap_set_passwd(MMLOGIN_S **, char *, char *, STRLIST_S *, int, int, int);
+ void imap_flush_passwd_cache(int);
+!
+
+ /* currently mandatory to implement stubs */
+
+--- 123,129 ----
+ int imap_get_passwd(MMLOGIN_S *, char *, char *, STRLIST_S *, int);
+ void imap_set_passwd(MMLOGIN_S **, char *, char *, STRLIST_S *, int, int, int);
+ void imap_flush_passwd_cache(int);
+! void pine_delete_pwd(NETMBX *mb, char *user);
+
+ /* currently mandatory to implement stubs */
+
+diff -rc alpine-2.00/pith/indxtype.h alpine-2.00.I.USE/pith/indxtype.h
+*** alpine-2.00/pith/indxtype.h 2008-05-28 13:19:56.000000000 -0700
+--- alpine-2.00.I.USE/pith/indxtype.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 75,86 ****
+ iKey, iKeyInit,
+ iPrefDate, iPrefTime, iPrefDateTime,
+ iCurPrefDate, iCurPrefTime, iCurPrefDateTime,
+! iSize, iSizeComma, iSizeNarrow, iDescripSize,
+ iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews,
+ iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips,
+ iCurNews, iArrow,
+ iMailbox, iAddress, iInit, iCursorPos,
+ iDay2Digit, iMon2Digit, iYear2Digit,
+ iSTime, iKSize,
+ iRoleNick, iNewLine,
+ iHeader, iText,
+--- 75,89 ----
+ iKey, iKeyInit,
+ iPrefDate, iPrefTime, iPrefDateTime,
+ iCurPrefDate, iCurPrefTime, iCurPrefDateTime,
+! iSize, iSizeComma, iSizeNarrow, iDescripSize, iSizeThread,
+ iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews,
+ iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips,
+ iCurNews, iArrow,
+ iMailbox, iAddress, iInit, iCursorPos,
+ iDay2Digit, iMon2Digit, iYear2Digit,
++ iFolder, iFlag, iCollection, iRole, iProcid, iScreen, iPkey,
++ iNick, iAddressTo, iAddressCc, iAddressRecip, iBcc, iLcc,
++ iFfrom, iFadd,
+ iSTime, iKSize,
+ iRoleNick, iNewLine,
+ iHeader, iText,
+***************
+*** 102,116 ****
+
+
+ /* these are flags for the what_for field in INDEX_PARSE_T */
+! #define FOR_NOTHING 0x00
+! #define FOR_INDEX 0x01
+! #define FOR_REPLY_INTRO 0x02
+! #define FOR_TEMPLATE 0x04 /* or for signature */
+! #define FOR_FILT 0x08
+! #define DELIM_USCORE 0x10
+! #define DELIM_PAREN 0x20
+! #define DELIM_COLON 0x40
+!
+
+ #define DEFAULT_REPLY_INTRO "default"
+
+--- 105,130 ----
+
+
+ /* these are flags for the what_for field in INDEX_PARSE_T */
+! #define FOR_NOTHING 0x00000
+! #define FOR_INDEX 0x00001
+! #define FOR_REPLY_INTRO 0x00002
+! #define FOR_TEMPLATE 0x00004 /* or for signature */
+! #define FOR_FILT 0x00008
+! #define DELIM_USCORE 0x00010
+! #define DELIM_PAREN 0x00020
+! #define DELIM_COLON 0x00040
+! #define FOR_FOLDER 0x00080 /* for rules */
+! #define FOR_RULE 0x00100 /* for rules */
+! #define FOR_TRIM 0x00200 /* for rules */
+! #define FOR_RESUB 0x00400 /* for rules */
+! #define FOR_REPLACE 0x00800 /* for rules */
+! #define FOR_SORT 0x01000 /* for rules */
+! #define FOR_FLAG 0x02000 /* for rules */
+! #define FOR_COMPOSE 0x04000 /* for rules */
+! #define FOR_THREAD 0x08000 /* for rules */
+! #define FOR_STARTUP 0x10000 /* for rules */
+! #define FOR_KEY 0x20000 /* for rules */
+! #define FOR_SAVE 0x40000 /* for rules */
+
+ #define DEFAULT_REPLY_INTRO "default"
+
+diff -rc alpine-2.00/pith/init.c alpine-2.00.I.USE/pith/init.c
+*** alpine-2.00/pith/init.c 2007-08-16 15:25:10.000000000 -0700
+--- alpine-2.00.I.USE/pith/init.c 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 407,412 ****
+--- 407,415 ----
+ && stricmp(filename, folder_base)){
+ #else
+ if(strncmp(filename, folder_base, folder_base_len) == 0
++ #ifndef _WINDOWS
++ && filename[folder_base_len] != list_cntxt->dir->delim
++ #endif
+ && strcmp(filename, folder_base)){
+ #endif
+ #endif
+diff -rc alpine-2.00/pith/mailcap.c alpine-2.00.I.USE/pith/mailcap.c
+*** alpine-2.00/pith/mailcap.c 2008-03-18 10:24:31.000000000 -0700
+--- alpine-2.00.I.USE/pith/mailcap.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 52,57 ****
+--- 52,58 ----
+ int needsterminal;
+ char *contenttype;
+ char *command;
++ char *nametemplate;
+ char *testcommand;
+ char *label; /* unused */
+ char *printcommand; /* unused */
+***************
+*** 212,217 ****
+--- 213,221 ----
+ if(mc->printcommand)
+ dprint((11, " printcommand: %s",
+ mc->printcommand ? mc->printcommand : "?"));
++ if(mc->nametemplate)
++ dprint((11, " nametemplate: %s",
++ mc->nametemplate ? mc->nametemplate : "?"));
+ dprint((11, " needsterminal %d\n", mc->needsterminal));
+ }
+ }
+***************
+*** 487,492 ****
+--- 491,501 ----
+ dprint((9, "mailcap: printcommand=%s\n",
+ mc->printcommand ? mc->printcommand : "?"));
+ }
++ else if(arg && !strucmp(*tokens, "nametemplate")){
++ mc->nametemplate = arg;
++ dprint((9, "mailcap: nametemplate=%s\n",
++ arg ? arg : "?"));
++ }
+ else if(arg && !strucmp(*tokens, "compose")){
+ /* not used */
+ dprint((9, "mailcap: not using compose=%s\n",
+***************
+*** 973,975 ****
+--- 982,1041 ----
+ mail_free_stringlist(&MailcapData.raw);
+ mc_free_entry(&MailcapData.head);
+ }
++
++ char *
++ mc_template(char *tmp_file, BODY *body, int chk_extension)
++ {
++ MailcapEntry *mc;
++ int quoted = 0;
++ char *s, *to, *namefile = NULL;
++
++ mc = mc_get_command(body->type, body->subtype, body, chk_extension, NULL);
++ if(!mc || !mc->nametemplate || !tmp_file)
++ return tmp_file;
++
++ /* remove extension if requested for a specific extension */
++ if(mc->nametemplate && tmp_file && (s = strrchr(tmp_file, '.')) != NULL
++ && strchr(s, C_FILESEP) == NULL)
++ *s = '\0';
++
++ to = tmp_20k_buf;
++ if((s = strrchr(tmp_file, C_FILESEP)) != NULL){
++ *s++ = '\0';
++ sstrncpy(&to, tmp_file, SIZEOF_20KBUF-(to-tmp_20k_buf));
++ if(to-tmp_20k_buf < SIZEOF_20KBUF)
++ *to++ = C_FILESEP;
++ namefile = s;
++ }
++
++ for(s = mc->nametemplate; *s; s++)
++ if(quoted){
++ quoted = 0;
++ switch(*s){
++ case '%':
++ if(to-tmp_20k_buf < SIZEOF_20KBUF)
++ *to++ = '%';
++ break;
++
++ case 's':
++ sstrncpy(&to, namefile ? namefile : tmp_file, SIZEOF_20KBUF-(to-tmp_20k_buf));
++ break;
++
++ default:
++ dprint((9,
++ "Ignoring unercognized format code in nametemplate: %%%c\n", *s ));
++ break;
++ }
++ }
++ else if(*s == '%')
++ quoted = 1;
++ else if(to-tmp_20k_buf < SIZEOF_20KBUF)
++ *to++ = *s;
++
++ *to++ = '\0';
++
++ fs_give((void **)&tmp_file);
++ tmp_file = cpystr(tmp_20k_buf);
++ return tmp_file;
++ }
++
+diff -rc alpine-2.00/pith/mailcap.h alpine-2.00.I.USE/pith/mailcap.h
+*** alpine-2.00/pith/mailcap.h 2008-03-18 10:24:31.000000000 -0700
+--- alpine-2.00.I.USE/pith/mailcap.h 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 28,33 ****
+--- 28,34 ----
+ int mailcap_can_display(int, char *, BODY *, int);
+ MCAP_CMD_S *mailcap_build_command(int, char *, BODY *, char *, int *, int);
+ void mailcap_free(void);
++ char *mc_template(char *, BODY *, int);
+
+ /* currently mandatory to implement stubs */
+
+diff -rc alpine-2.00/pith/mailcmd.c alpine-2.00.I.USE/pith/mailcmd.c
+*** alpine-2.00/pith/mailcmd.c 2008-07-09 22:01:13.000000000 -0700
+--- alpine-2.00.I.USE/pith/mailcmd.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 38,43 ****
+--- 38,44 ----
+ #include "../pith/ablookup.h"
+ #include "../pith/search.h"
+ #include "../pith/charconv/utf8.h"
++ #include "../pith/rules.h"
+
+ #ifdef _WINDOWS
+ #include "../pico/osdep/mswin.h"
+***************
+*** 659,664 ****
+--- 660,666 ----
+ strncpy(ps_global->cur_folder, p, sizeof(ps_global->cur_folder)-1);
+ ps_global->cur_folder[sizeof(ps_global->cur_folder)-1] = '\0';
+ ps_global->context_current = ps_global->context_list;
++ setup_threading_index_style();
+ reset_index_format();
+ clear_index_cache(ps_global->mail_stream, 0);
+ /* MUST sort before restoring msgno! */
+***************
+*** 771,776 ****
+--- 773,783 ----
+ if(stream)
+ sp_set_first_unseen(stream, 0L);
+
++ /* in case we closed the old stream by cancelling the connection, do
++ * not let that interfere with opening the new stream.
++ */
++ ps_global->user_says_cancel = 0;
++
+ m = context_open((new_context && !open_inbox) ? new_context : NULL,
+ stream,
+ open_inbox ? ps_global->VAR_INBOX_PATH : expanded_file,
+***************
+*** 974,979 ****
+--- 981,987 ----
+
+ clear_index_cache(ps_global->mail_stream, 0);
+ reset_index_format();
++ setup_threading_index_style();
+
+ /*
+ * Start news reading with messages the user's marked deleted
+***************
+*** 1092,1098 ****
+
+ if(!cur_already_set && mn_get_total(ps_global->msgmap) > 0L){
+
+! perfolder_startup_rule = reset_startup_rule(ps_global->mail_stream);
+
+ if(ps_global->start_entry > 0){
+ mn_set_cur(ps_global->msgmap, mn_get_revsort(ps_global->msgmap)
+--- 1100,1109 ----
+
+ if(!cur_already_set && mn_get_total(ps_global->msgmap) > 0L){
+
+! perfolder_startup_rule = get_perfolder_startup_rule(ps_global->mail_stream,
+! V_STARTUP_RULES, newfolder);
+!
+! reset_startup_rule(ps_global->mail_stream);
+
+ if(ps_global->start_entry > 0){
+ mn_set_cur(ps_global->msgmap, mn_get_revsort(ps_global->msgmap)
+***************
+*** 1114,1237 ****
+ else
+ use_this_startup_rule = ps_global->inc_startup_rule;
+
+! switch(use_this_startup_rule){
+! /*
+! * For news in incoming collection we're doing the same thing
+! * for first-unseen and first-recent. In both those cases you
+! * get first-unseen if FAKE_NEW is off and first-recent if
+! * FAKE_NEW is on. If FAKE_NEW is on, first unseen is the
+! * same as first recent because all recent msgs are unseen
+! * and all unrecent msgs are seen (see pine_mail_open).
+! */
+! case IS_FIRST_UNSEEN:
+! first_unseen:
+! mn_set_cur(ps_global->msgmap,
+! (sp_first_unseen(m)
+! && mn_get_sort(ps_global->msgmap) == SortArrival
+! && !mn_get_revsort(ps_global->msgmap)
+! && !get_lflag(ps_global->mail_stream, NULL,
+! sp_first_unseen(m), MN_EXLD)
+! && (n = mn_raw2m(ps_global->msgmap,
+! sp_first_unseen(m))))
+! ? n
+! : first_sorted_flagged(F_UNSEEN | F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! break;
+!
+! case IS_FIRST_RECENT:
+! first_recent:
+! /*
+! * We could really use recent for news but this is the way
+! * it has always worked, so we'll leave it. That is, if
+! * the FAKE_NEW feature is on, recent and unseen are
+! * equivalent, so it doesn't matter. If the feature isn't
+! * on, all the undeleted messages are unseen and we start
+! * at the first one. User controls with the FAKE_NEW feature.
+! */
+! if(IS_NEWS(ps_global->mail_stream)){
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! }
+! else{
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_RECENT | F_UNSEEN
+! | F_UNDEL,
+! m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! }
+! break;
+!
+! case IS_FIRST_IMPORTANT:
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! break;
+!
+! case IS_FIRST_IMPORTANT_OR_UNSEEN:
+!
+! if(IS_NEWS(ps_global->mail_stream))
+! goto first_unseen;
+!
+! {
+! MsgNo flagged, first_unseen;
+!
+! flagged = first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID);
+! first_unseen = (sp_first_unseen(m)
+! && mn_get_sort(ps_global->msgmap) == SortArrival
+! && !mn_get_revsort(ps_global->msgmap)
+! && !get_lflag(ps_global->mail_stream, NULL,
+! sp_first_unseen(m), MN_EXLD)
+! && (n = mn_raw2m(ps_global->msgmap,
+! sp_first_unseen(m))))
+! ? n
+! : first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID);
+! mn_set_cur(ps_global->msgmap,
+! (MsgNo) MIN((int) flagged, (int) first_unseen));
+!
+! }
+!
+! break;
+!
+! case IS_FIRST_IMPORTANT_OR_RECENT:
+!
+! if(IS_NEWS(ps_global->mail_stream))
+! goto first_recent;
+!
+! {
+! MsgNo flagged, first_recent;
+!
+! flagged = first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID);
+! first_recent = first_sorted_flagged(F_RECENT | F_UNSEEN
+! | F_UNDEL,
+! m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID);
+! mn_set_cur(ps_global->msgmap,
+! (MsgNo) MIN((int) flagged, (int) first_recent));
+! }
+!
+! break;
+!
+! case IS_FIRST:
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! break;
+!
+! case IS_LAST:
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_UNDEL, m, pc,
+! FSF_LAST | (THREADING() ? 0 : FSF_SKIP_CHID)));
+! break;
+!
+! default:
+! panic("Unexpected incoming startup case");
+! break;
+!
+! }
+ }
+ else if(IS_NEWS(ps_global->mail_stream)){
+ /*
+--- 1125,1131 ----
+ else
+ use_this_startup_rule = ps_global->inc_startup_rule;
+
+! find_startup_position(use_this_startup_rule, m, pc);
+ }
+ else if(IS_NEWS(ps_global->mail_stream)){
+ /*
+***************
+*** 1409,1417 ****
+ /* Save read messages? */
+ if(VAR_READ_MESSAGE_FOLDER && VAR_READ_MESSAGE_FOLDER[0]
+ && sp_flagged(stream, SP_INBOX)
+! && (seen_not_del = count_flagged(stream, F_SEEN | F_UNDEL))){
+
+ if(F_ON(F_AUTO_READ_MSGS,ps_global)
+ || (pith_opt_read_msg_prompt
+ && (*pith_opt_read_msg_prompt)(seen_not_del, VAR_READ_MESSAGE_FOLDER)))
+ /* move inbox's read messages */
+--- 1303,1313 ----
+ /* Save read messages? */
+ if(VAR_READ_MESSAGE_FOLDER && VAR_READ_MESSAGE_FOLDER[0]
+ && sp_flagged(stream, SP_INBOX)
+! && (F_ON(F_AUTO_READ_MSGS_RULES, ps_global) ||
+! (seen_not_del = count_flagged(stream, F_SEEN | F_UNDEL)))){
+
+ if(F_ON(F_AUTO_READ_MSGS,ps_global)
++ || F_ON(F_AUTO_READ_MSGS_RULES, ps_global)
+ || (pith_opt_read_msg_prompt
+ && (*pith_opt_read_msg_prompt)(seen_not_del, VAR_READ_MESSAGE_FOLDER)))
+ /* move inbox's read messages */
+***************
+*** 1682,1687 ****
+--- 1578,1586 ----
+ char *bufp = NULL;
+ MESSAGECACHE *mc;
+
++ if (F_ON(F_AUTO_READ_MSGS_RULES, ps_global))
++ return move_read_msgs_using_rules(stream, dstfldr, buf);
++
+ if(!is_absolute_path(dstfldr)
+ && !(save_context = default_save_context(ps_global->context_list)))
+ save_context = ps_global->context_list;
+***************
+*** 1721,1728 ****
+ snprintf(buf, buflen, "Moving %s read message%s to \"%s\"",
+ comatose(searched), plural(searched), dstfldr);
+ we_cancel = busy_cue(buf, NULL, 0);
+! if(save(ps_global, stream, save_context, dstfldr, msgmap,
+! SV_DELETE | SV_FIX_DELS | SV_INBOXWOCNTXT) == searched)
+ strncpy(bufp = buf + 1, "Moved", MIN(5,buflen)); /* change Moving to Moved */
+
+ buf[buflen-1] = '\0';
+--- 1620,1628 ----
+ snprintf(buf, buflen, "Moving %s read message%s to \"%s\"",
+ comatose(searched), plural(searched), dstfldr);
+ we_cancel = busy_cue(buf, NULL, 0);
+! ps_global->exiting = 1;
+! if((save(ps_global, stream, save_context, dstfldr, msgmap,
+! SV_DELETE | SV_FIX_DELS | SV_INBOXWOCNTXT) == searched))
+ strncpy(bufp = buf + 1, "Moved", MIN(5,buflen)); /* change Moving to Moved */
+
+ buf[buflen-1] = '\0';
+***************
+*** 1760,1766 ****
+ && ((context_isambig(folder)
+ && folder_is_nick(folder, FOLDERS(context), 0))
+ || folder_index(folder, context, FI_FOLDER) > 0)
+! && (seen_undel = count_flagged(stream, F_SEEN | F_UNDEL))){
+
+ for(; f && *archive; archive++){
+ char *p;
+--- 1660,1668 ----
+ && ((context_isambig(folder)
+ && folder_is_nick(folder, FOLDERS(context), 0))
+ || folder_index(folder, context, FI_FOLDER) > 0)
+! && ((seen_undel = count_flagged(stream, F_SEEN | F_UNDEL))
+! || (F_ON(F_AUTO_READ_MSGS,ps_global) &&
+! F_ON(F_AUTO_READ_MSGS_RULES, ps_global)))){
+
+ for(; f && *archive; archive++){
+ char *p;
+***************
+*** 2158,2165 ****
+
+
+ int
+! agg_text_select(MAILSTREAM *stream, MSGNO_S *msgmap, char type, int not,
+! int check_for_my_addresses,
+ char *sstring, char *charset, SEARCHSET **limitsrch)
+ {
+ int old_imap, we_cancel;
+--- 2060,2067 ----
+
+
+ int
+! agg_text_select(MAILSTREAM *stream, MSGNO_S *msgmap, char type, char *namehdr,
+! int not, int check_for_my_addresses,
+ char *sstring, char *charset, SEARCHSET **limitsrch)
+ {
+ int old_imap, we_cancel;
+***************
+*** 2308,2313 ****
+--- 2210,2219 ----
+
+ if(!mepgm)
+ switch(type){
++ case 'h' : /* Any header */
++ pgm->header = mail_newsearchheader (namehdr, sstring);
++ break;
++
+ case 'r' : /* TO or CC */
+ if(old_imap){
+ /* No OR on old servers */
+***************
+*** 2714,2716 ****
+--- 2620,2921 ----
+
+ return(*target ? target : NULL);
+ }
++
++ char *
++ move_read_msgs_using_rules(MAILSTREAM *stream, char *dstfldr, char *buf)
++ {
++ CONTEXT_S *save_context = NULL;
++ char **folder_to_save = NULL;
++ int num, we_cancel;
++ long i, j, success;
++ MSGNO_S *msgmap = NULL;
++ unsigned long nmsgs = 0L, stream_nmsgs;
++
++ saved_stream = stream; /* horrible hack! */
++ if(!is_absolute_path(dstfldr)
++ && !(save_context = default_save_context(ps_global->context_list)))
++ save_context = ps_global->context_list;
++
++ folder_to_save = (char **)fs_get((stream->nmsgs + 1)*sizeof(char *));
++ folder_to_save[0] = NULL;
++ mn_init(&msgmap, stream->nmsgs);
++ stream_nmsgs = stream->nmsgs;
++ for (i = 1L; i <= stream_nmsgs ; i++){
++ set_lflag(stream, msgmap, i, MN_SLCT, 0);
++ folder_to_save[i] = get_lflag(stream, NULL, i, MN_EXLD)
++ ? NULL : get_folder_to_save(stream, i, dstfldr);
++ }
++ for (i = 1L; i <= stream_nmsgs; i++){
++ num = 0;
++ if (folder_to_save[i]){
++ mn_init(&msgmap, stream_nmsgs);
++ for (j = i; j <= stream_nmsgs ; j++){
++ if (folder_to_save[j]){
++ if (!strcmp(folder_to_save[i], folder_to_save[j])){
++ set_lflag(stream, msgmap, j, MN_SLCT, 1);
++ num++;
++ if (j != i)
++ fs_give((void **)&folder_to_save[j]);
++ }
++ }
++ }
++ pseudo_selected(stream, msgmap);
++ sprintf(buf, "Moving %s read message%s to \"%.45s\"",
++ comatose(num), plural(num), folder_to_save[i]);
++ we_cancel = busy_cue(buf, NULL, 1);
++ ps_global->exiting = 1;
++ if(success = save(ps_global, stream,save_context, folder_to_save[i],
++ msgmap, SV_DELETE | SV_FIX_DELS))
++ nmsgs += success;
++ if(we_cancel)
++ cancel_busy_cue(success ? 0 : -1);
++ for (j = i; j <= stream_nmsgs ; j++)
++ set_lflag(stream, msgmap, j, MN_SLCT, 0);
++ fs_give((void **)&folder_to_save[i]);
++ mn_give(&msgmap);
++ }
++ }
++ ps_global->exiting = 0; /* useful if we call from aggregate operations */
++ sprintf(buf, "Moved automatically %s message%s",
++ comatose(nmsgs), plural(nmsgs));
++ if (folder_to_save)
++ fs_give((void **)folder_to_save);
++ rule_curpos = 0L;
++ return buf;
++ }
++
++ char *
++ get_folder_to_save(MAILSTREAM *stream, long i, char *dstfldr)
++ {
++ MESSAGECACHE *mc = NULL;
++ RULE_RESULT *rule;
++ MSGNO_S *msgmap = NULL;
++ char *folder_to_save = NULL, *save_folder = NULL;
++ int n;
++ long msgno;
++
++ /* The plan is as follows: Select each message of the folder. We
++ * need to set the cursor correctly so that iFlag gets the value
++ * correctly too, otherwise iFlag will get the value of the position
++ * of the cursor. After that we need to look for a rule that applies
++ * to the message and get the saving folder. If we get a saving folder,
++ * and we used the _FLAG_ token, use that folder, if no
++ * _FLAG_ token was used, move only if seen and not deleted, to the
++ * folder specified in the saving rule. If we did not get a saving
++ * folder from the rule, just save in the default folder.
++ */
++ mn_init(&msgmap, stream->nmsgs);
++ rule_curpos = i;
++ msgno = mn_m2raw(msgmap, i);
++ if (msgno > 0L){
++ mc = mail_elt(stream, msgno);
++ rule = (RULE_RESULT *)
++ get_result_rule(V_SAVE_RULES, FOR_SAVE, mc->private.msg.env);
++ if (rule){
++ folder_to_save = cpystr(rule->result);
++ n = rule->number;
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ }
++
++ if (folder_to_save && *folder_to_save){
++ RULELIST *list = get_rulelist_from_code(V_SAVE_RULES,
++ ps_global->rule_list);
++ RULE_S *prule = get_rule(list, n);
++ if (condition_contains_token(prule->condition, "_FLAG_")
++ || (mc->valid && mc->seen && !mc->deleted)
++ || (!mc->valid && mc->searched))
++ save_folder = cpystr(folder_to_save);
++ else
++ save_folder = NULL;
++ }
++ else
++ if (!mc || (mc->seen && !mc->deleted))
++ save_folder = cpystr(dstfldr);
++ mn_give(&msgmap);
++ rule_curpos = 0L;
++ return save_folder;
++ }
++
++ MAILSTREAM *
++ find_open_stream(void)
++ {
++ return saved_stream;
++ }
++
++ unsigned long
++ rules_cursor_pos(MAILSTREAM *stream)
++ {
++ MSGNO_S *msgmap = sp_msgmap(stream);
++ return rule_curpos != 0L ? rule_curpos : mn_m2raw(msgmap,mn_get_cur(msgmap));
++ }
++
++ void
++ setup_threading_index_style(void)
++ {
++ RULE_RESULT *rule;
++ NAMEVAL_S *v;
++ int i;
++
++ rule = get_result_rule(V_THREAD_INDEX_STYLE_RULES, FOR_THREAD, NULL);
++ if (rule || ps_global->VAR_THREAD_INDEX_STYLE){
++ for(i = 0; v = thread_index_styles(i); i++)
++ if(!strucmp(rule ? rule->result : ps_global->VAR_THREAD_INDEX_STYLE,
++ rule ? (v ? v->name : "" ) : S_OR_L(v))){
++ ps_global->thread_index_style = v->value;
++ break;
++ }
++ if (rule){
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ }
++ }
++
++ unsigned
++ get_perfolder_startup_rule(MAILSTREAM *stream, int rule_type, char *folder)
++ {
++ unsigned startup_rule;
++ char *rule_result;
++
++ startup_rule = reset_startup_rule(stream);
++ rule_result = get_rule_result(FOR_STARTUP, folder, rule_type);
++ if (rule_result && *rule_result){
++ int i;
++ NAMEVAL_S *v;
++
++ for(i = 0; v = incoming_startup_rules(i); i++)
++ if(!strucmp(rule_result, v->name)){
++ startup_rule = v->value;
++ break;
++ }
++ fs_give((void **)&rule_result);
++ }
++ return startup_rule;
++ }
++
++ void
++ find_startup_position(int rule, MAILSTREAM *m, long pc)
++ {
++ long n;
++ switch(rule){
++ /*
++ * For news in incoming collection we're doing the same thing
++ * for first-unseen and first-recent. In both those cases you
++ * get first-unseen if FAKE_NEW is off and first-recent if
++ * FAKE_NEW is on. If FAKE_NEW is on, first unseen is the
++ * same as first recent because all recent msgs are unseen
++ * and all unrecent msgs are seen (see pine_mail_open).
++ */
++ case IS_FIRST_UNSEEN:
++ first_unseen:
++ mn_set_cur(ps_global->msgmap,
++ (sp_first_unseen(m)
++ && mn_get_sort(ps_global->msgmap) == SortArrival
++ && !mn_get_revsort(ps_global->msgmap)
++ && !get_lflag(ps_global->mail_stream, NULL,
++ sp_first_unseen(m), MN_EXLD)
++ && (n = mn_raw2m(ps_global->msgmap,
++ sp_first_unseen(m))))
++ ? n
++ : first_sorted_flagged(F_UNSEEN | F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ break;
++
++ case IS_FIRST_RECENT:
++ first_recent:
++ /*
++ * We could really use recent for news but this is the way
++ * it has always worked, so we'll leave it. That is, if
++ * the FAKE_NEW feature is on, recent and unseen are
++ * equivalent, so it doesn't matter. If the feature isn't
++ * on, all the undeleted messages are unseen and we start
++ * at the first one. User controls with the FAKE_NEW feature.
++ */
++ if(IS_NEWS(ps_global->mail_stream)){
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ }
++ else{
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_RECENT | F_UNSEEN
++ | F_UNDEL,
++ m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ }
++ break;
++
++ case IS_FIRST_IMPORTANT:
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ break;
++
++ case IS_FIRST_IMPORTANT_OR_UNSEEN:
++
++ if(IS_NEWS(ps_global->mail_stream))
++ goto first_unseen;
++
++ {
++ MsgNo flagged, first_unseen;
++
++ flagged = first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID);
++ first_unseen = (sp_first_unseen(m)
++ && mn_get_sort(ps_global->msgmap) == SortArrival
++ && !mn_get_revsort(ps_global->msgmap)
++ && !get_lflag(ps_global->mail_stream, NULL,
++ sp_first_unseen(m), MN_EXLD)
++ && (n = mn_raw2m(ps_global->msgmap,
++ sp_first_unseen(m))))
++ ? n
++ : first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID);
++ mn_set_cur(ps_global->msgmap,
++ (MsgNo) MIN((int) flagged, (int) first_unseen));
++
++ }
++
++ break;
++
++ case IS_FIRST_IMPORTANT_OR_RECENT:
++
++ if(IS_NEWS(ps_global->mail_stream))
++ goto first_recent;
++
++ {
++ MsgNo flagged, first_recent;
++
++ flagged = first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID);
++ first_recent = first_sorted_flagged(F_RECENT | F_UNSEEN
++ | F_UNDEL,
++ m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID);
++ mn_set_cur(ps_global->msgmap,
++ (MsgNo) MIN((int) flagged, (int) first_recent));
++ }
++
++ break;
++
++ case IS_FIRST:
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ break;
++
++ case IS_LAST:
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_UNDEL, m, pc,
++ FSF_LAST | (THREADING() ? 0 : FSF_SKIP_CHID)));
++ break;
++
++ default:
++ panic("Unexpected incoming startup case");
++ break;
++
++ }
++ }
+diff -rc alpine-2.00/pith/mailcmd.h alpine-2.00.I.USE/pith/mailcmd.h
+*** alpine-2.00/pith/mailcmd.h 2008-07-09 22:01:13.000000000 -0700
+--- alpine-2.00.I.USE/pith/mailcmd.h 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 41,46 ****
+--- 41,48 ----
+ #define DB_FROMTAB 0x02 /* opening because of TAB command */
+ #define DB_INBOXWOCNTXT 0x04 /* interpret inbox as one true inbox */
+
++ static MAILSTREAM *saved_stream;
++ static unsigned long rule_curpos = 0L;
+
+ /*
+ * generic "is aggregate message command?" test
+***************
+*** 53,58 ****
+--- 55,61 ----
+ void bogus_utf8_command(char *, char *);
+ int can_set_flag(struct pine *, char *, int);
+ void cmd_cancelled(char *);
++ void cmd_quota(struct pine *);
+ int cmd_delete(struct pine *, MSGNO_S *, int, char *(*)(struct pine *, MSGNO_S *));
+ int cmd_undelete(struct pine *, MSGNO_S *, int);
+ int cmd_expunge_work(MAILSTREAM *, MSGNO_S *);
+***************
+*** 61,71 ****
+ void expunge_and_close(MAILSTREAM *, char **, unsigned long);
+ void agg_select_all(MAILSTREAM *, MSGNO_S *, long *, int);
+ char *move_read_msgs(MAILSTREAM *, char *, char *, size_t, long);
+ char *move_read_incoming(MAILSTREAM *, CONTEXT_S *, char *, char **, char *, size_t);
+ void cross_delete_crossposts(MAILSTREAM *);
+ long zoom_index(struct pine *, MAILSTREAM *, MSGNO_S *, int);
+ int unzoom_index(struct pine *, MAILSTREAM *, MSGNO_S *);
+! int agg_text_select(MAILSTREAM *, MSGNO_S *, char, int, int, char *,
+ char *, SEARCHSET **);
+ int agg_flag_select(MAILSTREAM *, int, int, SEARCHSET **);
+ char *get_uname(char *, char *, int);
+--- 64,81 ----
+ void expunge_and_close(MAILSTREAM *, char **, unsigned long);
+ void agg_select_all(MAILSTREAM *, MSGNO_S *, long *, int);
+ char *move_read_msgs(MAILSTREAM *, char *, char *, size_t, long);
++ char *move_read_msgs_using_rules (MAILSTREAM *, char *, char *);
++ unsigned get_perfolder_startup_rule (MAILSTREAM *, int, char *);
++ void setup_threading_index_style (void);
++ void find_startup_position (int, MAILSTREAM *, long);
++ char *get_folder_to_save (MAILSTREAM *, long, char *);
+ char *move_read_incoming(MAILSTREAM *, CONTEXT_S *, char *, char **, char *, size_t);
++ MAILSTREAM *find_open_stream (void);
++ unsigned long rules_cursor_pos (MAILSTREAM *);
+ void cross_delete_crossposts(MAILSTREAM *);
+ long zoom_index(struct pine *, MAILSTREAM *, MSGNO_S *, int);
+ int unzoom_index(struct pine *, MAILSTREAM *, MSGNO_S *);
+! int agg_text_select(MAILSTREAM *, MSGNO_S *, char, char *, int, int, char *,
+ char *, SEARCHSET **);
+ int agg_flag_select(MAILSTREAM *, int, int, SEARCHSET **);
+ char *get_uname(char *, char *, int);
+diff -rc alpine-2.00/pith/mailindx.c alpine-2.00.I.USE/pith/mailindx.c
+*** alpine-2.00/pith/mailindx.c 2008-03-03 09:52:11.000000000 -0800
+--- alpine-2.00.I.USE/pith/mailindx.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 16,21 ****
+--- 16,22 ----
+
+ #include "../pith/headers.h"
+ #include "../pith/mailindx.h"
++ #include "../pith/pineelt.h"
+ #include "../pith/mailview.h"
+ #include "../pith/flag.h"
+ #include "../pith/icache.h"
+***************
+*** 39,44 ****
+--- 40,46 ----
+ #include "../pith/send.h"
+ #include "../pith/options.h"
+ #include "../pith/ablookup.h"
++ #include "../pith/rules.h"
+ #ifdef _WINDOWS
+ #include "../pico/osdep/mswin.h"
+ #endif
+***************
+*** 103,109 ****
+ void set_print_format(IELEM_S *, int, int);
+ void set_ielem_widths_in_field(IFIELD_S *);
+
+-
+ #define BIGWIDTH 2047
+
+
+--- 105,110 ----
+***************
+*** 227,232 ****
+--- 228,234 ----
+ case iSTime:
+ case iKSize:
+ case iSize:
++ case iSizeThread:
+ case iPrioAlpha:
+ (*answer)[column].req_width = 7;
+ break;
+***************
+*** 291,296 ****
+--- 293,301 ----
+ case iSDate:
+ case iSDateTime:
+ case iSDateTime24:
++ case iPrefDate:
++ case iPrefTime:
++ case iPrefDateTime:
+ {
+ /*
+ * Format a date to see how long it is.
+***************
+*** 299,312 ****
+ * of the translated yesterdays and friends but...
+ */
+ struct tm tm;
+ char ss[100];
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_year = 106;
+ tm.tm_mon = 11;
+ tm.tm_mday = 31;
+! our_strftime(ss, sizeof(ss), "%x", &tm);
+! (*answer)[column].req_width = MIN(MAX(9, utf8_width(ss)), 20);
+ }
+
+ (*answer)[column].monabb_width = monabb_width;
+--- 304,332 ----
+ * of the translated yesterdays and friends but...
+ */
+ struct tm tm;
++ int len = 20;
+ char ss[100];
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_year = 106;
+ tm.tm_mon = 11;
+ tm.tm_mday = 31;
+! tm.tm_hour = 3;
+! tm.tm_min = 23;
+! tm.tm_wday = 3;
+! switch((*answer)[column].ctype){
+! case iPrefTime:
+! our_strftime(ss, sizeof(ss), "%X", &tm);
+! break;
+! case iPrefDateTime:
+! our_strftime(ss, sizeof(ss), "%c", &tm);
+! len = 32;
+! break;
+! default:
+! our_strftime(ss, sizeof(ss), "%x", &tm);
+! break;
+! }
+! (*answer)[column].req_width = MIN(MAX(9, utf8_width(ss)), len);
+ }
+
+ (*answer)[column].monabb_width = monabb_width;
+***************
+*** 355,360 ****
+--- 375,387 ----
+ PAT_STATE pstate;
+ PAT_S *pat;
+ int we_set_it = 0;
++ char *rule;
++
++ if(rule = get_rule_result(FOR_INDEX, ps_global->cur_folder, V_INDEX_RULES)){
++ init_index_format(rule, &ps_global->index_disp_format);
++ fs_give((void **)&rule);
++ return;
++ }
+
+ if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){
+ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
+***************
+*** 428,441 ****
+ static INDEX_PARSE_T itokens[] = {
+ {"STATUS", iStatus, FOR_INDEX},
+ {"MSGNO", iMessNo, FOR_INDEX},
+! {"DATE", iDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"FROMORTO", iFromTo, FOR_INDEX},
+ {"FROMORTONOTNEWS", iFromToNotNews, FOR_INDEX},
+ {"SIZE", iSize, FOR_INDEX},
+ {"SIZECOMMA", iSizeComma, FOR_INDEX},
+ {"SIZENARROW", iSizeNarrow, FOR_INDEX},
+ {"KSIZE", iKSize, FOR_INDEX},
+! {"SUBJECT", iSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"FULLSTATUS", iFStatus, FOR_INDEX},
+ {"IMAPSTATUS", iIStatus, FOR_INDEX},
+ {"SHORTIMAPSTATUS", iSIStatus, FOR_INDEX},
+--- 455,469 ----
+ static INDEX_PARSE_T itokens[] = {
+ {"STATUS", iStatus, FOR_INDEX},
+ {"MSGNO", iMessNo, FOR_INDEX},
+! {"DATE", iDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+ {"FROMORTO", iFromTo, FOR_INDEX},
+ {"FROMORTONOTNEWS", iFromToNotNews, FOR_INDEX},
+ {"SIZE", iSize, FOR_INDEX},
+ {"SIZECOMMA", iSizeComma, FOR_INDEX},
++ {"SIZETHREAD", iSizeThread, FOR_INDEX},
+ {"SIZENARROW", iSizeNarrow, FOR_INDEX},
+ {"KSIZE", iKSize, FOR_INDEX},
+! {"SUBJECT", iSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_TRIM},
+ {"FULLSTATUS", iFStatus, FOR_INDEX},
+ {"IMAPSTATUS", iIStatus, FOR_INDEX},
+ {"SHORTIMAPSTATUS", iSIStatus, FOR_INDEX},
+***************
+*** 444,498 ****
+ {"SUBJECTTEXT", iSubjectText, FOR_INDEX},
+ {"SUBJKEYTEXT", iSubjKeyText, FOR_INDEX},
+ {"SUBJKEYINITTEXT", iSubjKeyInitText, FOR_INDEX},
+! {"OPENINGTEXT", iOpeningText, FOR_INDEX},
+! {"OPENINGTEXTNQ", iOpeningTextNQ, FOR_INDEX},
+! {"KEY", iKey, FOR_INDEX},
+! {"KEYINIT", iKeyInit, FOR_INDEX},
+ {"DESCRIPSIZE", iDescripSize, FOR_INDEX},
+ {"ATT", iAtt, FOR_INDEX},
+ {"SCORE", iScore, FOR_INDEX},
+ {"PRIORITY", iPrio, FOR_INDEX},
+ {"PRIORITYALPHA", iPrioAlpha, FOR_INDEX},
+! {"PRIORITY!", iPrioBang, FOR_INDEX},
+! {"LONGDATE", iLDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATE1", iS1Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATE2", iS2Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATE3", iS3Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATE4", iS4Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DATEISO", iDateIso, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATEISO", iDateIsoS, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATE", iSDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTTIME", iSTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATEISO", iSDateIso, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATESHORTISO",iSDateIsoS, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATES1", iSDateS1, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATES2", iSDateS2, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATES3", iSDateS3, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATES4", iSDateS4, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIME", iSDateTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMEISO",iSDateTimeIso, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMESHORTISO",iSDateTimeIsoS,FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMES1", iSDateTimeS1, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMES2", iSDateTimeS2, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMES3", iSDateTimeS3, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMES4", iSDateTimeS4, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIME24", iSDateTime24, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMEISO24", iSDateTimeIso24,FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMESHORTISO24",iSDateTimeIsoS24,FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMES124", iSDateTimeS124, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMES224", iSDateTimeS224, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMES324", iSDateTimeS324, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIMES424", iSDateTimeS424, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"TIME24", iTime24, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"TIME12", iTime12, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"TIMEZONE", iTimezone, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"MONTHABBREV", iMonAbb, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYOFWEEKABBREV", iDayOfWeekAbb, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYOFWEEK", iDayOfWeek, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"FROM", iFrom, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"TO", iTo, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SENDER", iSender, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"CC", iCc, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"RECIPS", iRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"NEWS", iNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"TOANDNEWS", iToAndNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+--- 472,529 ----
+ {"SUBJECTTEXT", iSubjectText, FOR_INDEX},
+ {"SUBJKEYTEXT", iSubjKeyText, FOR_INDEX},
+ {"SUBJKEYINITTEXT", iSubjKeyInitText, FOR_INDEX},
+! {"OPENINGTEXT", iOpeningText, FOR_INDEX|FOR_RULE|FOR_SAVE|FOR_TRIM},
+! {"OPENINGTEXTNQ", iOpeningTextNQ, FOR_INDEX|FOR_RULE|FOR_SAVE|FOR_TRIM},
+! {"KEY", iKey, FOR_INDEX|FOR_RULE|FOR_SAVE|FOR_COMPOSE},
+! {"KEYINIT", iKeyInit, FOR_INDEX|FOR_RULE|FOR_SAVE|FOR_COMPOSE},
+ {"DESCRIPSIZE", iDescripSize, FOR_INDEX},
+ {"ATT", iAtt, FOR_INDEX},
+ {"SCORE", iScore, FOR_INDEX},
+ {"PRIORITY", iPrio, FOR_INDEX},
+ {"PRIORITYALPHA", iPrioAlpha, FOR_INDEX},
+! {"PRIORITY!", iPrioBang, FOR_INDEX},
+! {"LONGDATE", iLDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATE1", iS1Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATE2", iS2Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATE3", iS3Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATE4", iS4Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DATEISO", iDateIso, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATEISO", iDateIsoS, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATE", iSDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTTIME", iSTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATEISO", iSDateIso, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATESHORTISO",iSDateIsoS, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATES1", iSDateS1, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATES2", iSDateS2, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATES3", iSDateS3, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATES4", iSDateS4, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIME", iSDateTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMEISO",iSDateTimeIso, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMESHORTISO",iSDateTimeIsoS,FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMES1", iSDateTimeS1, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMES2", iSDateTimeS2, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMES3", iSDateTimeS3, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMES4", iSDateTimeS4, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIME24", iSDateTime24, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMEISO24", iSDateTimeIso24,FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMESHORTISO24",iSDateTimeIsoS24,FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMES124", iSDateTimeS124, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMES224", iSDateTimeS224, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMES324", iSDateTimeS324, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIMES424", iSDateTimeS424, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"TIME24", iTime24, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"TIME12", iTime12, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"TIMEZONE", iTimezone, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"MONTHABBREV", iMonAbb, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAYOFWEEKABBREV", iDayOfWeekAbb, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAYOFWEEK", iDayOfWeek, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"FROM", iFrom, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_COMPOSE},
+! {"TO", iTo, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_COMPOSE},
+! {"SENDER", iSender, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"CC", iCc, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_SAVE|FOR_SAVE},
+! {"ADDRESSTO", iAddressTo, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"ADDRESSCC", iAddressCc, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"ADDRESSRECIPS", iAddressRecip, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+ {"RECIPS", iRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"NEWS", iNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"TOANDNEWS", iToAndNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+***************
+*** 501,559 ****
+ {"NEWSANDRECIPS", iNewsAndRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"MSGID", iMsgID, FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"CURNEWS", iCurNews, FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYDATE", iRDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"PREFDATE", iPrefDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"PREFTIME", iPrefTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"PREFDATETIME", iPrefDateTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAY", iDay, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYORDINAL", iDayOrdinal, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAY2DIGIT", iDay2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"MONTHLONG", iMonLong, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"MONTH", iMon, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"MONTH2DIGIT", iMon2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"YEAR", iYear, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"YEAR2DIGIT", iYear2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"ADDRESS", iAddress, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"MAILBOX", iMailbox, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"ROLENICK", iRoleNick, FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"INIT", iInit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"CURDATE", iCurDate, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDATEISO", iCurDateIso, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDATEISOS", iCurDateIsoS, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURTIME24", iCurTime24, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURTIME12", iCurTime12, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDAY", iCurDay, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDAY2DIGIT", iCurDay2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDAYOFWEEK", iCurDayOfWeek, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+ {"CURDAYOFWEEKABBREV", iCurDayOfWeekAbb,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURMONTH", iCurMon, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURMONTH2DIGIT", iCurMon2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURMONTHLONG", iCurMonLong, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURMONTHABBREV", iCurMonAbb, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURYEAR", iCurYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURYEAR2DIGIT", iCurYear2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURPREFDATE", iCurPrefDate, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURPREFTIME", iCurPrefTime, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+ {"CURPREFDATETIME", iCurPrefDateTime,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTH", iLstMon, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTH2DIGIT", iLstMon2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTHLONG", iLstMonLong, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTHABBREV", iLstMonAbb, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTHYEAR", iLstMonYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+ {"LASTMONTHYEAR2DIGIT", iLstMonYear2Digit,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTYEAR", iLstYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTYEAR2DIGIT", iLstYear2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+ {"HEADER", iHeader, FOR_INDEX},
+ {"TEXT", iText, FOR_INDEX},
+ {"ARROW", iArrow, FOR_INDEX},
+ {"NEWLINE", iNewLine, FOR_REPLY_INTRO},
+ {"CURSORPOS", iCursorPos, FOR_TEMPLATE},
+ {NULL, iNothing, FOR_NOTHING}
+ };
+
+ INDEX_PARSE_T *
+ itoken(int i)
+ {
+--- 532,613 ----
+ {"NEWSANDRECIPS", iNewsAndRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"MSGID", iMsgID, FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"CURNEWS", iCurNews, FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYDATE", iRDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"PREFDATE", iPrefDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"PREFTIME", iPrefTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"PREFDATETIME", iPrefDateTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAY", iDay, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAYORDINAL", iDayOrdinal, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAY2DIGIT", iDay2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"MONTHLONG", iMonLong, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"MONTH", iMon, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"MONTH2DIGIT", iMon2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"YEAR", iYear, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"YEAR2DIGIT", iYear2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"ADDRESS", iAddress, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE},
+ {"MAILBOX", iMailbox, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"ROLENICK", iRoleNick, FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"INIT", iInit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"CURDATE", iCurDate, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURDATEISO", iCurDateIso, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURDATEISOS", iCurDateIsoS, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURTIME24", iCurTime24, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURTIME12", iCurTime12, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURDAY", iCurDay, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURDAY2DIGIT", iCurDay2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURDAYOFWEEK", iCurDayOfWeek, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+ {"CURDAYOFWEEKABBREV", iCurDayOfWeekAbb,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURMONTH", iCurMon, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURMONTH2DIGIT", iCurMon2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURMONTHLONG", iCurMonLong, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURMONTHABBREV", iCurMonAbb, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURYEAR", iCurYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURYEAR2DIGIT", iCurYear2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURPREFDATE", iCurPrefDate, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"CURPREFTIME", iCurPrefTime, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+ {"CURPREFDATETIME", iCurPrefDateTime,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"LASTMONTH", iLstMon, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"LASTMONTH2DIGIT", iLstMon2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"LASTMONTHLONG", iLstMonLong, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"LASTMONTHABBREV", iLstMonAbb, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"LASTMONTHYEAR", iLstMonYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+ {"LASTMONTHYEAR2DIGIT", iLstMonYear2Digit,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"LASTYEAR", iLstYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+! {"LASTYEAR2DIGIT", iLstYear2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT|FOR_RULE|FOR_SAVE},
+ {"HEADER", iHeader, FOR_INDEX},
+ {"TEXT", iText, FOR_INDEX},
+ {"ARROW", iArrow, FOR_INDEX},
+ {"NEWLINE", iNewLine, FOR_REPLY_INTRO},
+ {"CURSORPOS", iCursorPos, FOR_TEMPLATE},
++ {"NICK", iNick, FOR_RULE|FOR_SAVE},
++ {"FOLDER", iFolder, FOR_RULE|FOR_SAVE|FOR_FOLDER},
++ {"ROLE", iRole, FOR_RULE|FOR_RESUB|FOR_TRIM|FOR_TEMPLATE},
++ {"PROCID", iProcid, FOR_RULE|FOR_RESUB|FOR_FLAG|FOR_COMPOSE|FOR_TRIM|FOR_TEMPLATE},
++ {"PKEY", iPkey, FOR_RULE|FOR_KEY},
++ {"SCREEN", iScreen, FOR_RULE|FOR_KEY},
++ {"FLAG", iFlag, FOR_RULE|FOR_SAVE|FOR_FLAG},
++ {"COLLECTION", iCollection, FOR_RULE|FOR_SAVE|FOR_COMPOSE|FOR_FOLDER},
++ {"BCC", iBcc, FOR_COMPOSE|FOR_RULE},
++ {"LCC", iLcc, FOR_COMPOSE|FOR_RULE},
++ {"FORWARDFROM", iFfrom, FOR_COMPOSE|FOR_RULE},
++ {"FORWARDADDRESS", iFadd, FOR_COMPOSE|FOR_RULE},
+ {NULL, iNothing, FOR_NOTHING}
+ };
+
++ INDEX_PARSE_T itokensinv[sizeof(itokens)/sizeof(itokens[0])];
++
++ void
++ inverse_itokens(void)
++ {
++ INDEX_PARSE_T *pt;
++ for (pt = itokens; pt->name; pt++)
++ itokensinv[pt->ctype].ctype = pt - itokens;
++
++ }
++
+ INDEX_PARSE_T *
+ itoken(int i)
+ {
+***************
+*** 913,919 ****
+ iSDateTimeS1, iSDateTimeS2, iSDateTimeS3, iSDateTimeS4,
+ iSDateTimeIso24, iSDateTimeIsoS24,
+ iSDateTimeS124, iSDateTimeS224, iSDateTimeS324, iSDateTimeS424,
+! iSize, iSizeComma, iSizeNarrow, iKSize, iDescripSize,
+ iPrio, iPrioBang, iPrioAlpha,
+ iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit,
+ iDay2Digit, iMon2Digit, iDayOfWeekAbb, iScore, iMonLong, iDayOfWeek
+--- 967,973 ----
+ iSDateTimeS1, iSDateTimeS2, iSDateTimeS3, iSDateTimeS4,
+ iSDateTimeIso24, iSDateTimeIsoS24,
+ iSDateTimeS124, iSDateTimeS224, iSDateTimeS324, iSDateTimeS424,
+! iSize, iSizeComma, iSizeNarrow, iKSize, iDescripSize, iSizeThread,
+ iPrio, iPrioBang, iPrioAlpha,
+ iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit,
+ iDay2Digit, iMon2Digit, iDayOfWeekAbb, iScore, iMonLong, iDayOfWeek
+***************
+*** 1105,1110 ****
+--- 1159,1165 ----
+ case iTime12:
+ case iSize:
+ case iKSize:
++ case iSizeThread:
+ cdesc->actual_length = 7;
+ cdesc->adjustment = Right;
+ break;
+***************
+*** 1198,1204 ****
+ cdesc->ctype != iNothing;
+ cdesc++)
+ if(cdesc->ctype == iSize || cdesc->ctype == iKSize ||
+! cdesc->ctype == iSizeNarrow ||
+ cdesc->ctype == iSizeComma || cdesc->ctype == iDescripSize){
+ if(cdesc->actual_length == 0){
+ if((fix=cdesc->width) > 0){ /* had this reserved */
+--- 1253,1259 ----
+ cdesc->ctype != iNothing;
+ cdesc++)
+ if(cdesc->ctype == iSize || cdesc->ctype == iKSize ||
+! cdesc->ctype == iSizeNarrow || cdesc->ctype == iSizeThread ||
+ cdesc->ctype == iSizeComma || cdesc->ctype == iDescripSize){
+ if(cdesc->actual_length == 0){
+ if((fix=cdesc->width) > 0){ /* had this reserved */
+***************
+*** 1581,1590 ****
+
+ /* find next thread which is visible */
+ do{
+ if(mn_get_revsort(msgmap) && thrd->prevthd)
+ thrd = fetch_thread(stream, thrd->prevthd);
+! else if(!mn_get_revsort(msgmap) && thrd->nextthd)
+! thrd = fetch_thread(stream, thrd->nextthd);
+ else
+ thrd = NULL;
+ } while(thrd
+--- 1636,1647 ----
+
+ /* find next thread which is visible */
+ do{
++ unsigned long branch;
+ if(mn_get_revsort(msgmap) && thrd->prevthd)
+ thrd = fetch_thread(stream, thrd->prevthd);
+! /*branch = get_branch(stream,thrd)*/
+! else if(!mn_get_revsort(msgmap) && thrd->branch)
+! thrd = fetch_thread(stream, thrd->branch);
+ else
+ thrd = NULL;
+ } while(thrd
+***************
+*** 1970,1975 ****
+--- 2027,2033 ----
+ ICE_S *ice, **icep;
+ IFIELD_S *ifield;
+ IELEM_S *ielem;
++ COLOR_PAIR *color = NULL;
+ struct variable *vars = ps_global->vars;
+
+ dprint((8, "=== format_index_line(msgno=%ld,rawno=%ld) ===\n",
+***************
+*** 1995,2007 ****
+ */
+ ice = copy_ice(ice);
+
+ /* is this a collapsed thread index line? */
+! if(!idata->bogus && THREADING()){
+! thrd = fetch_thread(idata->stream, idata->rawno);
+! collapsed = thrd && thrd->next
+! && get_lflag(idata->stream, NULL,
+! idata->rawno, MN_COLL);
+! }
+
+ /* calculate contents of the required fields */
+ for(cdesc = ps_global->index_disp_format; cdesc->ctype != iNothing; cdesc++)
+--- 2053,2062 ----
+ */
+ ice = copy_ice(ice);
+
++ thrd = fetch_thread(idata->stream, idata->rawno);
+ /* is this a collapsed thread index line? */
+! if(!idata->bogus && THREADING())
+! collapsed = thrd && thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno);
+
+ /* calculate contents of the required fields */
+ for(cdesc = ps_global->index_disp_format; cdesc->ctype != iNothing; cdesc++)
+***************
+*** 2433,2438 ****
+--- 2488,2511 ----
+ from_str(cdesc->ctype, idata, str, sizeof(str), ice);
+ break;
+
++ case iAddressTo:
++ case iAddressCc:
++ case iAddressRecip:
++ {ENVELOPE *env;
++ int we_clear;
++ env = rules_fetchenvelope(idata, &we_clear);
++ sprintf(str, "%-*.*s", ifield->width, ifield->width,
++ detoken_src((cdesc->ctype == iAddressTo
++ ? "_ADDRESSTO_"
++ : (cdesc->ctype == iAddressCc
++ ? "_ADRESSCC_"
++ : "_ADRESSRECIPS_")), FOR_INDEX,
++ env, NULL, NULL, NULL));
++ if(we_clear)
++ mail_free_envelope(&env);
++ }
++ break;
++
+ case iTo:
+ if(((field = ((addr = fetch_to(idata))
+ ? "To"
+***************
+*** 2499,2505 ****
+--- 2572,2601 ----
+
+ break;
+
++ case iSizeThread:
++ if (!THREADING()){
++ goto getsize;
++ } else if (collapsed){
++ l = count_flags_in_thread(idata->stream, thrd, F_NONE);
++ snprintf(str, sizeof(str), "(%lu)", l);
++ }
++ else{
++ thrd = fetch_thread(idata->stream, idata->rawno);
++ if(!thrd)
++ snprintf(str, sizeof(str), "%s", "Error");
++ else{
++ long lengthb;
++ lengthb = get_length_branch(idata->stream, idata->rawno);
++ if (lengthb > 0L)
++ snprintf(str, sizeof(str), "(%lu)", lengthb);
++ else
++ snprintf(str,sizeof(str), "%s", " ");
++ }
++ }
++ break;
++
+ case iSize:
++ getsize:
+ /* 0 ... 9999 */
+ if((l = fetch_size(idata)) < 10*1000L)
+ snprintf(str, sizeof(str), "(%lu)", l);
+***************
+*** 2753,2759 ****
+ if(first_text){
+ strncpy(str, first_text, BIGWIDTH);
+ str[BIGWIDTH] = '\0';
+- fs_give((void **) &first_text);
+ }
+ }
+
+--- 2849,2854 ----
+***************
+*** 2913,2918 ****
+--- 3008,3021 ----
+ if(!ifield->ielem){
+ ielem = new_ielem(&ifield->ielem);
+
++ if(color = hdr_color(itokens[itokensinv[cdesc->ctype].ctype].name, NULL, ps_global->index_token_colors)){
++ if(pico_usingcolor()){
++ ielem->color = new_color_pair(color->fg, color->bg);
++ ielem->type = eTypeCol;
++ }
++ free_color_pair(&color);
++ }
++
+ ielem->freedata = 1;
+ ielem->data = cpystr(str);
+ ielem->datalen = strlen(str);
+***************
+*** 3670,3675 ****
+--- 3773,3829 ----
+ gf_io_t pc;
+ long partial_fetch_len = 0L;
+ SEARCHSET *ss, **sset;
++ MESSAGECACHE *mc;
++ PINELT_S *pelt;
++
++ /* we cache the result we get from this function, so that we do not have to
++ * refetch the text in case there is a change. We could cache in the envelope
++ * but c-client does not have a special field for that, nor we want to use the
++ * sparep pointer, since there could be other uses for sparep later, and even
++ * if we add a pointer to the ENVELOPE structure, we would be caching the same
++ * text twice (one in a private pointer, and the new pointer) and that would
++ * not make sense. Instead we will use an elt for this
++ */
++
++ if((mc = mail_elt(idata->stream, idata->rawno))
++ && ((pelt = (PINELT_S *) mc->sparep) == NULL)){
++ pelt = (PINELT_S *) fs_get(sizeof(PINELT_S));
++ memset(pelt, 0, sizeof(PINELT_S));
++ }
++
++ /* If there were no rules, we would just return the firsttext
++ * as cached in the pelt pointer, but if we are here and there
++ * is a rule, and the firsttext that is cached changes as a
++ * result of the rule, we need to refetch the text and process it
++ * again
++ */
++
++ if(pelt && pelt->firsttextraw != NULL){
++ char buf[4*1024+1], ftext[6*1024+1], *rule_result;
++ strncpy(buf, pelt->firsttextraw, sizeof(buf));
++ buf[sizeof(buf)-1] = '\0';
++ if(rule_result = find_value((delete_quotes
++ ? "_OPENINGTEXTNQ_" : "_OPENINGTEXT_"),
++ buf, PROCESS_SP, idata, 4)){
++ collspaces(rule_result);
++ strncpy(buf, rule_result, sizeof(buf));
++ buf[sizeof(buf) - 1] = '\0';
++ fs_give((void **) &rule_result);
++ }
++ ftext[0] = '\0';
++ iutf8ncpy(ftext, buf, sizeof(ftext));
++ ftext[sizeof(ftext)-1] = '\0';
++ removing_trailing_white_space(ftext);
++ if(!strcmp(ftext, pelt->firsttext)) /* same as last pass */
++ return(pelt->firsttext);
++ if(strlen(pelt->firsttextraw) > 256 /* not the same, but long enough */
++ && utf8_width(ftext) >= 50){
++ fs_give((void **)&pelt->firsttext);
++ pelt->firsttext = cpystr(ftext);
++ return pelt->firsttext;
++ }
++ fs_give((void **)&pelt->firsttext); /* do it again */
++ }
+
+ try_again:
+
+***************
+*** 3706,3712 ****
+ && ALLOWED_SUBTYPE(subtype))){
+
+ if((so = so_get(CharStar, NULL, EDIT_ACCESS)) != NULL){
+! char buf[1025], *p;
+ unsigned char c;
+ int success;
+ int one_space_done = 0;
+--- 3860,3866 ----
+ && ALLOWED_SUBTYPE(subtype))){
+
+ if((so = so_get(CharStar, NULL, EDIT_ACCESS)) != NULL){
+! char buf[4*1024+1], rawbuf[6*1024+1], *p;
+ unsigned char c;
+ int success;
+ int one_space_done = 0;
+***************
+*** 3763,3769 ****
+--- 3917,3939 ----
+
+ if(p > buf){
+ size_t l;
++ ENVELOPE *env;
++ char *rule_result;
+
++ if(pelt && pelt->firsttextraw)
++ fs_give((void **)&pelt->firsttextraw);
++ iutf8ncpy(rawbuf, buf, sizeof(rawbuf));
++ rawbuf[sizeof(rawbuf)-1] = '\0';
++ removing_trailing_white_space(rawbuf);
++ pelt->firsttextraw = cpystr(rawbuf);
++ if(rule_result = find_value((delete_quotes
++ ? "_OPENINGTEXTNQ_" : "_OPENINGTEXT_"),
++ buf, PROCESS_SP, idata, 4)){
++ collspaces(rule_result);
++ strncpy(buf, rule_result, sizeof(buf));
++ buf[sizeof(buf) - 1] = '\0';
++ fs_give((void **) &rule_result);
++ }
+ l = strlen(buf);
+ l += 100;
+ firsttext = fs_get((l+1) * sizeof(char));
+***************
+*** 3787,3792 ****
+--- 3957,3964 ----
+ goto try_again;
+ }
+ }
++ if(mc && pelt)
++ pelt->firsttext = firsttext;
+ }
+ }
+ }
+***************
+*** 4271,4276 ****
+--- 4443,4449 ----
+ tm.tm_mday = MIN(MAX(d.day, 1), 31);
+ tm.tm_hour = MIN(MAX(d.hour, 0), 23);
+ tm.tm_min = MIN(MAX(d.minute, 0), 59);
++ tm.tm_wday = MIN(MAX(d.wkday, 0), 6);
+ tmptr = &tm;
+ }
+
+***************
+*** 5226,5235 ****
+ {
+ char *subject, *origsubj, *origstr, *rawsubj, *sptr = NULL;
+ char *p, *border, *q = NULL, *free_subj = NULL;
+! char *sp;
+ size_t len;
+ int width = -1;
+! int depth = 0, mult = 2;
+ int save;
+ int do_subj = 0, truncated_tree = 0;
+ PINETHRD_S *thd, *thdorig;
+--- 5399,5408 ----
+ {
+ char *subject, *origsubj, *origstr, *rawsubj, *sptr = NULL;
+ char *p, *border, *q = NULL, *free_subj = NULL;
+! char *sp, *rule_result;
+ size_t len;
+ int width = -1;
+! int depth = 0, mult = 2, collapsed, i, we_clear = 0;
+ int save;
+ int do_subj = 0, truncated_tree = 0;
+ PINETHRD_S *thd, *thdorig;
+***************
+*** 5283,5289 ****
+ * origsubj is the original subject but it has been decoded. We need
+ * to free it at the end of this routine.
+ */
+!
+
+ /*
+ * prepend_keyword will put the keyword stuff before the subject
+--- 5456,5468 ----
+ * origsubj is the original subject but it has been decoded. We need
+ * to free it at the end of this routine.
+ */
+! if (rule_result = find_value("_SUBJECT_", origsubj, PROCESS_SP, idata, 4)){
+! if(origsubj)
+! fs_give((void **)&origsubj);
+! we_clear++;
+! origsubj = cpystr(rule_result);
+! fs_give((void **)&rule_result);
+! }
+
+ /*
+ * prepend_keyword will put the keyword stuff before the subject
+***************
+*** 5371,5380 ****
+
+ if(pith_opt_condense_thread_cue)
+ width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width,
+! thd && thd->next
+! && get_lflag(idata->stream,
+! NULL,idata->rawno,
+! MN_COLL));
+
+ /*
+ * width is < available strsize and
+--- 5550,5557 ----
+
+ if(pith_opt_condense_thread_cue)
+ width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width,
+! this_thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno) &&
+! (count_thread(ps_global,idata->stream, ps_global->msgmap, idata->rawno) != 1));
+
+ /*
+ * width is < available strsize and
+***************
+*** 5724,5729 ****
+--- 5901,5909 ----
+
+ if(free_subj)
+ fs_give((void **) &free_subj);
++
++ if (we_clear && origsubj)
++ fs_give((void **)&origsubj);
+ }
+
+
+***************
+*** 6002,6012 ****
+ border = str + width;
+ if(pith_opt_condense_thread_cue)
+ width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width,
+! thd && thd->next
+! && get_lflag(idata->stream,
+! NULL,idata->rawno,
+! MN_COLL));
+!
+ fptr = str;
+
+ if(thd)
+--- 6182,6189 ----
+ border = str + width;
+ if(pith_opt_condense_thread_cue)
+ width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width,
+! this_thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno) &&
+! (count_thread(ps_global,idata->stream, ps_global->msgmap, idata->rawno) != 1));
+ fptr = str;
+
+ if(thd)
+***************
+*** 6092,6107 ****
+ ? "To"
+ : (addr = fetch_cc(idata))
+ ? "Cc"
+! : NULL))
+! && set_index_addr(idata, field, addr, "To: ",
+! strsize-1, fptr))
+! break;
+
+ if(ctype == iFromTo &&
+ (newsgroups = fetch_newsgroups(idata)) &&
+ *newsgroups){
+! snprintf(fptr, strsize, "To: %-*.*s", strsize-1-4, strsize-1-4,
+! newsgroups);
+ break;
+ }
+
+--- 6269,6301 ----
+ ? "To"
+ : (addr = fetch_cc(idata))
+ ? "Cc"
+! : NULL))){
+! char *rule_result;
+! rule_result = find_value("_FROM_", NULL, 0, idata, 1);
+! if (!rule_result)
+! set_index_addr(idata, field, addr, "To: ",
+! strsize-1, fptr);
+! else{
+! sprintf(str, "%-*.*s", strsize-1, strsize-1,
+! rule_result);
+! fs_give((void **)&rule_result);
+! }
+
++ break;
++ }
+ if(ctype == iFromTo &&
+ (newsgroups = fetch_newsgroups(idata)) &&
+ *newsgroups){
+! char *rule_result;
+! rule_result = find_value("_FROM_", NULL, 0, idata, 1);
+! if (!rule_result)
+! sprintf(str, "To: %-*.*s", strsize-1-4,
+! strsize-1-4, newsgroups);
+! else{
+! sprintf(str, "%-*.*s", strsize-1, strsize-1,
+! rule_result);
+! fs_give((void **)&rule_result);
+! }
+ break;
+ }
+
+***************
+*** 6114,6120 ****
+ break;
+
+ case iFrom:
+! set_index_addr(idata, "From", fetch_from(idata), NULL, strsize-1, fptr);
+ break;
+
+ case iAddress:
+--- 6308,6322 ----
+ break;
+
+ case iFrom:
+! { char *rule_result;
+! rule_result = find_value("_FROM_", NULL, 0, idata, 4);
+! if (!rule_result)
+! set_index_addr(idata, "From", fetch_from(idata), NULL, strsize-1, fptr);
+! else{
+! sprintf(str, "%-*.*s", strsize-1, strsize-1, rule_result);
+! fs_give((void **)&rule_result);
+! }
+! }
+ break;
+
+ case iAddress:
+***************
+*** 6411,6413 ****
+--- 6613,6676 ----
+ }
+ }
+ }
++
++ void
++ setup_threading_display_style(void)
++ {
++ RULE_RESULT *rule;
++ NAMEVAL_S *v;
++ int i;
++
++ rule = get_result_rule(V_THREAD_DISP_STYLE_RULES, FOR_THREAD, NULL);
++ if (rule || ps_global->VAR_THREAD_DISP_STYLE){
++ for(i = 0; v = thread_disp_styles(i); i++)
++ if(!strucmp(rule ? rule->result : ps_global->VAR_THREAD_DISP_STYLE,
++ rule ? (v ? v->name : "" ) : S_OR_L(v))){
++ ps_global->thread_disp_style = v->value;
++ break;
++ }
++ if (rule){
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ }
++ }
++
++ char *
++ find_value(char *token, char *use_this, int flag, INDEXDATA_S *idata, int nfcn)
++ {
++ int n = 0, i, rule_context, we_clear;
++ char *rule_result = NULL, **list;
++ ENVELOPE *env;
++ RULELIST *rule;
++ RULE_S *prule;
++
++ env = rules_fetchenvelope(idata, &we_clear);
++ if(env && env->sparep)
++ fs_give((void **)&env->sparep);
++ if(we_clear)
++ mail_free_envelope(&env);
++ if(rule = get_rulelist_from_code(V_REPLACE_RULES, ps_global->rule_list)){
++ list = functions_for_token(token);
++ while(rule_result == NULL && (prule = get_rule(rule,n++))){
++ rule_context = 0;
++ if (prule->action->token && !strcmp(prule->action->token, token)){
++ for (i = 0; i < nfcn; i++)
++ if(list[i+1] && !strcmp(prule->action->function, list[i+1]))
++ rule_context |= context_for_function(list[i+1]);
++ if (rule_context){
++ env = rules_fetchenvelope(idata, &we_clear);
++ if(use_this)
++ env->sparep = get_sparep_for_rule(use_this, flag);
++ rule_result = process_rule(prule, rule_context, env);
++ if(env->sparep)
++ free_sparep_for_rule(&env->sparep);
++ if(we_clear)
++ mail_free_envelope(&env);
++ }
++ }
++ }
++ }
++ return rule_result;
++ }
+diff -rc alpine-2.00/pith/mailindx.h alpine-2.00.I.USE/pith/mailindx.h
+*** alpine-2.00/pith/mailindx.h 2008-02-01 10:42:29.000000000 -0800
+--- alpine-2.00.I.USE/pith/mailindx.h 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 29,34 ****
+--- 29,37 ----
+
+
+ /* exported prototypes */
++ SortOrder translate (char *, int);
++ char *find_value (char *, char *, int, INDEXDATA_S *, int);
++ void setup_threading_display_style (void);
+ int msgline_hidden(MAILSTREAM *, MSGNO_S *, long, int);
+ void adjust_cur_to_visible(MAILSTREAM *, MSGNO_S *);
+ unsigned long line_hash(char *);
+***************
+*** 36,41 ****
+--- 39,45 ----
+ void free_index_format(INDEX_COL_S **);
+ void reset_index_format(void);
+ INDEX_PARSE_T *itoktype(char *, int);
++ void inverse_itokens(void);
+ char *prepend_keyword_subject(MAILSTREAM *, long, char *, SubjKW, IELEM_S **, char *);
+ int get_index_line_color(MAILSTREAM *, SEARCHSET *, PAT_STATE **, COLOR_PAIR **);
+ void setup_for_index_index_screen(void);
+diff -rc alpine-2.00/pith/mailview.c alpine-2.00.I.USE/pith/mailview.c
+*** alpine-2.00/pith/mailview.c 2008-07-11 16:20:32.000000000 -0700
+--- alpine-2.00.I.USE/pith/mailview.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 51,57 ****
+ #include "../pith/escapes.h"
+ #include "../pith/keyword.h"
+ #include "../pith/smime.h"
+!
+
+ #define FBUF_LEN (50)
+
+--- 51,60 ----
+ #include "../pith/escapes.h"
+ #include "../pith/keyword.h"
+ #include "../pith/smime.h"
+! #include "../pith/osdep/color.h"
+! #include "../pico/estruct.h"
+! #include "../pico/pico.h"
+! #include "../pico/efunc.h"
+
+ #define FBUF_LEN (50)
+
+***************
+*** 281,289 ****
+ if((flgs & FM_DISPLAY)
+ && !(flgs & FM_NOCOLOR)
+ && pico_usingcolor()
+ && ps_global->VAR_SIGNATURE_FORE_COLOR
+ && ps_global->VAR_SIGNATURE_BACK_COLOR){
+! gf_link_filter(gf_line_test, gf_line_test_opt(color_signature, &is_in_sig));
+ }
+
+ if((flgs & FM_DISPLAY)
+--- 284,300 ----
+ if((flgs & FM_DISPLAY)
+ && !(flgs & FM_NOCOLOR)
+ && pico_usingcolor()
++ && ps_global->VAR_SPECIAL_TEXT_FORE_COLOR
++ && ps_global->VAR_SPECIAL_TEXT_BACK_COLOR){
++ gf_link_filter(gf_line_test, gf_line_test_opt(color_this_text, NULL));
++ }
++
++ if((flgs & FM_DISPLAY)
++ && !(flgs & FM_NOCOLOR)
++ && pico_usingcolor()
+ && ps_global->VAR_SIGNATURE_FORE_COLOR
+ && ps_global->VAR_SIGNATURE_BACK_COLOR){
+! gf_link_filter(gf_quote_test, gf_line_test_opt(color_signature, &is_in_sig));
+ }
+
+ if((flgs & FM_DISPLAY)
+***************
+*** 291,298 ****
+ && pico_usingcolor()
+ && ps_global->VAR_QUOTE1_FORE_COLOR
+ && ps_global->VAR_QUOTE1_BACK_COLOR){
+! gf_link_filter(gf_line_test, gf_line_test_opt(color_a_quote, NULL));
+ }
+
+ if(!(flgs & FM_NOWRAP)){
+ wrapflags = (flgs & FM_DISPLAY) ? (GFW_HANDLES|GFW_SOFTHYPHEN) : GFW_NONE;
+--- 302,311 ----
+ && pico_usingcolor()
+ && ps_global->VAR_QUOTE1_FORE_COLOR
+ && ps_global->VAR_QUOTE1_BACK_COLOR){
+! gf_link_filter(gf_quote_test, gf_line_test_opt(color_a_quote, NULL));
+ }
++ else
++ gf_link_filter(gf_quote_test,gf_line_test_opt(select_quote, NULL));
+
+ if(!(flgs & FM_NOWRAP)){
+ wrapflags = (flgs & FM_DISPLAY) ? (GFW_HANDLES|GFW_SOFTHYPHEN) : GFW_NONE;
+***************
+*** 1096,1122 ****
+ color_signature(long int linenum, char *line, LT_INS_S **ins, void *is_in_sig)
+ {
+ struct variable *vars = ps_global->vars;
+! int *in_sig_block;
+ COLOR_PAIR *col = NULL;
+
+ if(is_in_sig == NULL)
+ return 0;
+
+ in_sig_block = (int *) is_in_sig;
+
+! if(!strcmp(line, SIGDASHES))
+! *in_sig_block = START_SIG_BLOCK;
+! else if(*line == '\0')
+ /*
+ * Suggested by Eduardo: allow for a blank line right after
+ * the sigdashes.
+ */
+ *in_sig_block = (*in_sig_block == START_SIG_BLOCK)
+ ? IN_SIG_BLOCK : OUT_SIG_BLOCK;
+ else
+ *in_sig_block = (*in_sig_block != OUT_SIG_BLOCK)
+ ? IN_SIG_BLOCK : OUT_SIG_BLOCK;
+
+ if(*in_sig_block != OUT_SIG_BLOCK
+ && VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR
+ && (col = new_color_pair(VAR_SIGNATURE_FORE_COLOR,
+--- 1109,1197 ----
+ color_signature(long int linenum, char *line, LT_INS_S **ins, void *is_in_sig)
+ {
+ struct variable *vars = ps_global->vars;
+! int *in_sig_block, i, j,same_qstr = 0, plb;
+ COLOR_PAIR *col = NULL;
++ static char GLine[NSTRING] = {'\0'};
++ static char PLine[NSTRING] = {'\0'};
++ static char PPLine[NSTRING] = {'\0'};
++ char NLine[NSTRING] = {'\0'};
++ char rqstr[NSTRING] = {'\0'};
++ char *p;
++ static char *buf, buf2[NSTRING] = {'\0'};
++ QSTRING_S *qs;
++ static int qstrlen = 0;
+
+ if(is_in_sig == NULL)
+ return 0;
+
++ if (linenum > 0){
++ strncpy(PLine, GLine, sizeof(PLine));
++ PLine[sizeof(PLine)-1] = '\0';
++ }
++
++ if(p = strchr(tmp_20k_buf, '\015')) *p = '\0';
++ strncpy(NLine, tmp_20k_buf, sizeof(NLine));
++ NLine[sizeof(NLine) - 1] = '\0';
++ if (p) *p = '\015';
++
++ strncpy(GLine, line, sizeof(GLine));
++ GLine[sizeof(GLine) - 1] = '\0';
++
++ plb = line_isblank((ps_global->prefix && *ps_global->prefix
++ ? ps_global->prefix : ">"), PLine, GLine, PPLine, NSTRING);
++ qs = do_quote_match((ps_global->prefix && *ps_global->prefix
++ ? ps_global->prefix : ">"),
++ GLine, NLine, PLine, rqstr, NSTRING, plb);
++ if(linenum > 0)
++ strncpy(PPLine, PLine, NSTRING);
++ strncpy(buf2, rqstr, NSTRING);
++ i = buf2 && buf2[0] ? strlen(buf2) : 0;
++ free_qs(&qs);
++
++ /* determine if buf and buf2 are the same quote string */
++ if (!struncmp(buf, buf2, qstrlen)){
++ for (j = qstrlen; buf2[j] && isspace((unsigned char)buf2[j]); j++);
++ if (!buf2[j] || buf2[j] == '|' || (buf2[j] == '*' && buf2[j+1] != '>'))
++ same_qstr++;
++ }
++
+ in_sig_block = (int *) is_in_sig;
+
+! if (*in_sig_block != OUT_SIG_BLOCK){
+! if (line && *line && (strlen(line) >= qstrlen) && same_qstr)
+! line += qstrlen;
+! else if (strlen(line) < qstrlen)
+! line += i;
+! else if (!same_qstr)
+! *in_sig_block = OUT_SIG_BLOCK;
+! }
+! else
+! line += i;
+!
+! if(!strcmp(line, SIGDASHES) || !strcmp(line, "--")){
+! *in_sig_block = START_SIG_BLOCK;
+! buf = (char *) fs_get((i + 1)*sizeof(char));
+! buf = cpystr(buf2);
+! qstrlen = i;
+! }
+! else if(*line == '\0'){
+ /*
+ * Suggested by Eduardo: allow for a blank line right after
+ * the sigdashes.
+ */
+ *in_sig_block = (*in_sig_block == START_SIG_BLOCK)
+ ? IN_SIG_BLOCK : OUT_SIG_BLOCK;
++ }
+ else
+ *in_sig_block = (*in_sig_block != OUT_SIG_BLOCK)
+ ? IN_SIG_BLOCK : OUT_SIG_BLOCK;
+
++ if (*in_sig_block == OUT_SIG_BLOCK){
++ qstrlen = 0; /* reset back in case there's another paragraph */
++ if (buf)
++ fs_give((void **)&buf);
++ }
++
+ if(*in_sig_block != OUT_SIG_BLOCK
+ && VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR
+ && (col = new_color_pair(VAR_SIGNATURE_FORE_COLOR,
+***************
+*** 1480,1497 ****
+ return(0);
+ }
+
+
+ int
+ url_hilite(long int linenum, char *line, LT_INS_S **ins, void *local)
+ {
+ register char *lp, *up = NULL, *urlp = NULL,
+ *weburlp = NULL, *mailurlp = NULL;
+! int n, n1, n2, n3, l;
+ char buf[256], color[256];
+ HANDLE_S *h;
+ URL_HILITE_S *uh;
+
+! for(lp = line; ; lp = up + n){
+ /* scan for all of them so we can choose the first */
+ if(F_ON(F_VIEW_SEL_URL,ps_global))
+ urlp = rfc1738_scan(lp, &n1);
+--- 1555,1632 ----
+ return(0);
+ }
+
++ int
++ incomplete_url(char *up, int n, int delim)
++ {
++ char *line, *line2;
++ int rv = 0, len;
++
++ if(*(up + n) != '\0')
++ return 0;
++
++ if(delim > 0)
++ return 1;
++
++ if(F_ON(F_VIEW_LONG_URL, ps_global)){
++ line = up;
++ if(!strncmp(line, "http://", 7))
++ line += 7;
++ else if(!strncmp(line, "https://", 8))
++ line += 8;
++ if(strchr(line, '/') != NULL && (line = strrchr(line, '/')) != NULL){
++ line++;
++ line2 = strrchr(line, '.');
++ rv = (strpbrk(line,"+#?=&") != NULL)
++ || (!line2 || line-line2 > 4);
++ }
++ }
++ return rv;
++ }
++
+
+ int
+ url_hilite(long int linenum, char *line, LT_INS_S **ins, void *local)
+ {
+ register char *lp, *up = NULL, *urlp = NULL,
+ *weburlp = NULL, *mailurlp = NULL;
+! char *use_this_line, c, *begin_line, *end_line;
+! static int scannextline, delim = -1;
+! int n, n1, n2, n3, l, len;
+! int we_clear = 0, newhandle = 1, tie_off = 0;
+ char buf[256], color[256];
+ HANDLE_S *h;
+ URL_HILITE_S *uh;
+
+! uh = (URL_HILITE_S *) local;
+! if((uh && uh->handlesp && ((h = *(uh->handlesp)) == NULL) || h->key == 0) ||
+! (!line || !*line) || linenum == 0)
+! scannextline = 0; /* initialize scannextline */
+!
+! if(scannextline != 0){
+! up = rfc1738_scan(line, &n1);
+!
+! /* if we found a url in the current line, but it is not at the beginning of
+! * the next line, or if there is no url in this line, we check if the url
+! * in the previous line continues in this line.
+! */
+!
+! if(line != up){
+! if(*uh->handlesp == NULL)
+! h = new_handle(uh->handlesp);
+! for(h = *uh->handlesp; h->next; h = h->next); /* get last handle */
+! len = h->h.url.path ? strlen(h->h.url.path) : 0;
+! use_this_line = (char *) fs_get((len + strlen(line) + 1)*sizeof(char));
+! sprintf(use_this_line,"%s%s", (h->h.url.path ? h->h.url.path : ""), line);
+! we_clear++;
+! newhandle = 0;
+! }
+! else
+! use_this_line = line;
+! }
+! else
+! use_this_line = line;
+!
+! for(lp = use_this_line; ; lp = up + n){
+ /* scan for all of them so we can choose the first */
+ if(F_ON(F_VIEW_SEL_URL,ps_global))
+ urlp = rfc1738_scan(lp, &n1);
+***************
+*** 1501,1506 ****
+--- 1636,1645 ----
+ mailurlp = mail_addr_scan(lp, &n3);
+
+ if(urlp || weburlp || mailurlp){
++ if(scannextline == 0){
++ newhandle++;
++ delim = -1;
++ }
+ up = urlp ? urlp :
+ weburlp ? weburlp : mailurlp;
+ if(up == urlp && weburlp && weburlp < up)
+***************
+*** 1509,1515 ****
+--- 1648,1663 ----
+ up = mailurlp;
+
+ if(up == urlp){
++ if(delim < 0)
++ delim = up > use_this_line && *(up - 1) == '<';
+ n = n1;
++ if(incomplete_url(up,n, delim))
++ scannextline++;
++ else{
++ if(scannextline)
++ tie_off++;
++ scannextline = 0;
++ }
+ weburlp = mailurlp = NULL;
+ }
+ else if(up == weburlp){
+***************
+*** 1526,1561 ****
+
+ uh = (URL_HILITE_S *) local;
+
+! h = new_handle(uh->handlesp);
+! h->type = URL;
+! h->h.url.path = (char *) fs_get((n + 10) * sizeof(char));
+! snprintf(h->h.url.path, n+10, "%s%.*s",
+ weburlp ? "http://" : (mailurlp ? "mailto:" : ""), n, up);
+! h->h.url.path[n+10-1] = '\0';
+
+ if(handle_start_color(color, sizeof(color), &l, uh->hdr_color))
+! ins = gf_line_test_new_ins(ins, up, color, l);
+ else if(F_OFF(F_SLCTBL_ITEM_NOBOLD, ps_global))
+! ins = gf_line_test_new_ins(ins, up, url_embed(TAG_BOLDON), 2);
+
+ buf[0] = TAG_EMBED;
+ buf[1] = TAG_HANDLE;
+ snprintf(&buf[3], sizeof(buf)-3, "%d", h->key);
+ buf[sizeof(buf)-1] = '\0';
+ buf[2] = strlen(&buf[3]);
+! ins = gf_line_test_new_ins(ins, up, buf, (int) buf[2] + 3);
+
+ /* in case it was the current selection */
+! ins = gf_line_test_new_ins(ins, up + n, url_embed(TAG_INVOFF), 2);
+
+ if(scroll_handle_end_color(color, sizeof(color), &l, uh->hdr_color))
+! ins = gf_line_test_new_ins(ins, up + n, color, l);
+ else
+! ins = gf_line_test_new_ins(ins, up + n, url_embed(TAG_BOLDOFF), 2);
+
+ urlp = weburlp = mailurlp = NULL;
+ }
+
+ return(0);
+ }
+
+--- 1674,1731 ----
+
+ uh = (URL_HILITE_S *) local;
+
+! if(tie_off){
+! tie_off = 0; /* do only once */
+! begin_line = line;
+! end_line = line + n - strlen(h->h.url.path);
+! fs_give((void **)&h->h.url.path);
+! c = *(use_this_line + n);
+! *(use_this_line+n) = '\0';
+! h->h.url.path = cpystr(use_this_line);
+! *(use_this_line+n) = c;
+! }
+! else{
+! if(newhandle){
+! h = new_handle(uh->handlesp);
+! h->type = URL;
+! }
+! begin_line = newhandle ? (we_clear ? line + strlen(line) - strlen(up)
+! : up) : line;
+! end_line = newhandle ? begin_line + n : line + strlen(line);
+! if(scannextline && h->h.url.path)
+! fs_give((void **)&h->h.url.path);
+! h->h.url.path = (char *) fs_get((n + 10) * sizeof(char));
+! snprintf(h->h.url.path, n+10, "%s%.*s",
+ weburlp ? "http://" : (mailurlp ? "mailto:" : ""), n, up);
+! h->h.url.path[n+10-1] = '\0';
+! }
+
+ if(handle_start_color(color, sizeof(color), &l, uh->hdr_color))
+! ins = gf_line_test_new_ins(ins, begin_line, color, l);
+ else if(F_OFF(F_SLCTBL_ITEM_NOBOLD, ps_global))
+! ins = gf_line_test_new_ins(ins, begin_line, url_embed(TAG_BOLDON), 2);
+
+ buf[0] = TAG_EMBED;
+ buf[1] = TAG_HANDLE;
+ snprintf(&buf[3], sizeof(buf)-3, "%d", h->key);
+ buf[sizeof(buf)-1] = '\0';
+ buf[2] = strlen(&buf[3]);
+! ins = gf_line_test_new_ins(ins, begin_line, buf, (int) buf[2] + 3);
+
+ /* in case it was the current selection */
+! ins = gf_line_test_new_ins(ins, end_line, url_embed(TAG_INVOFF), 2);
+
+ if(scroll_handle_end_color(color, sizeof(color), &l, uh->hdr_color))
+! ins = gf_line_test_new_ins(ins, end_line, color, l);
+ else
+! ins = gf_line_test_new_ins(ins, end_line, url_embed(TAG_BOLDOFF), 2);
+
+ urlp = weburlp = mailurlp = NULL;
+ }
+
++ if(we_clear)
++ fs_give((void **)&use_this_line);
++
+ return(0);
+ }
+
+***************
+*** 1676,1681 ****
+--- 1846,1922 ----
+ }
+
+
++ /* This filter gives a quote string of a line. It sends its reply back to the
++ calling filter in the tmp_20k_buf variable. This filter replies with
++ the full quote string including tailing spaces if any. It is the
++ responsibility of the calling filter to figure out if thos spaces are
++ useful for that filter or if they should be removed before doing any
++ useful work. For example, color_a_quote does not require the trailing
++ spaces, but gf_wrap does.
++ */
++ int
++ select_quote(long linenum, char *line, LT_INS_S **ins, void *local)
++ {
++ int i, plb, *code;
++ char rqstr[NSTRING] = {'\0'}, buf[NSTRING] = {'\0'};
++ char GLine[NSTRING] = {'\0'}, PLine[NSTRING] = {'\0'};
++ char PPLine[NSTRING] = {'\0'}, NLine[NSTRING] = {'\0'};
++ static char GLine1[NSTRING] = {'\0'};
++ static char PLine1[NSTRING] = {'\0'};
++ static char PPLine1[NSTRING] = {'\0'};
++ static char GLine2[NSTRING] = {'\0'};
++ static char PLine2[NSTRING] = {'\0'};
++ static char PPLine2[NSTRING] = {'\0'};
++ QSTRING_S *qs;
++ int buflen = NSTRING < SIZEOF_20KBUF ? NSTRING - 1: SIZEOF_20KBUF - 1;
++ int who, raw;
++
++ code = (int *)local;
++ who = code ? (*code & COLORAQUO) : 0; /* may I ask who is calling? */
++ raw = code ? (*code & RAWSTRING) : 0; /* return raw string */
++ strncpy(GLine, (who ? GLine1 : GLine2), buflen);
++ strncpy(PLine, (who ? PLine1 : PLine2), buflen);
++ strncpy(PPLine, (who ? PPLine1 : PPLine2), buflen);
++
++ if (linenum > 0)
++ strncpy(PLine, GLine, buflen);
++
++ strncpy(NLine, tmp_20k_buf, buflen);
++
++ if (line)
++ strncpy(GLine, line, buflen);
++ else
++ GLine[0] = '\0';
++
++
++ plb = line_isblank((ps_global->prefix && *ps_global->prefix
++ ? ps_global->prefix : ">"), PLine, GLine, PPLine, NSTRING);
++
++ qs = do_quote_match((ps_global->prefix && *ps_global->prefix
++ ? ps_global->prefix : ">"), GLine, NLine, PLine,
++ rqstr, NSTRING, plb);
++ if (raw)
++ strncpy(buf, rqstr, NSTRING);
++ else
++ flatten_qstring(qs, buf, NSTRING);
++ free_qs(&qs);
++
++ /* do not paint an extra level for a line with a >From string at the
++ * begining of it
++ */
++ if (buf[0]){
++ i = strlen(buf);
++ if (strlen(line) >= i + 6 && !strncmp(line+i-1,">From ", 6))
++ buf[i - 1] = '\0';
++ }
++ strncpy(tmp_20k_buf, buf, buflen);
++ if (linenum > 0)
++ strncpy((who ? PPLine1 : PPLine2), PLine, buflen);
++ strncpy((who ? GLine1 : GLine2), GLine, buflen);
++ strncpy((who ? PLine1 : PLine2), PLine, buflen);
++ return 1;
++ }
++
+
+ #define UES_LEN 12
+ #define UES_MAX 32
+***************
+*** 2377,2384 ****
+ format_addr_string(s, n, sect, "Return-Path: ", e->return_path,
+ flags, oacs, pc);
+
+! if((which & FE_NEWSGROUPS) && e->newsgroups)
+ format_newsgroup_string("Newsgroups: ", e->newsgroups, flags, pc);
+
+ if((which & FE_FOLLOWUPTO) && e->followup_to)
+ format_newsgroup_string("Followup-To: ", e->followup_to, flags, pc);
+--- 2618,2638 ----
+ format_addr_string(s, n, sect, "Return-Path: ", e->return_path,
+ flags, oacs, pc);
+
+! if((which & FE_NEWSGROUPS) && e->newsgroups){
+! int bogus = NIL;
+ format_newsgroup_string("Newsgroups: ", e->newsgroups, flags, pc);
++ if (!e->ngpathexists && e->message_id &&
++ strncmp (e->message_id,"<alpine.",8) &&
++ strncmp (e->message_id,"<Pine.",6) &&
++ strncmp (e->message_id,"<MS-C.",6) &&
++ strncmp (e->message_id,"<MailManager.",13) &&
++ strncmp (e->message_id,"<EasyMail.",11) &&
++ strncmp (e->message_id,"<ML-",4)) bogus = T;
++
++ if(bogus)
++ q_status_message(SM_ORDER, 0, 3,
++ "Unverified Newsgroup header -- Message MAY or MAY NOT have been posted");
++ }
+
+ if((which & FE_FOLLOWUPTO) && e->followup_to)
+ format_newsgroup_string("Followup-To: ", e->followup_to, flags, pc);
+***************
+*** 2488,2493 ****
+--- 2742,2962 ----
+ return(color_pair);
+ }
+
++ void
++ interval_free(ival)
++ IVAL_S **ival;
++ {
++ if (!(*ival))
++ return;
++
++ if ((*ival)->next)
++ interval_free(&((*ival)->next));
++
++ fs_give((void **)(ival));
++ }
++
++ IVAL_S *
++ compute_interval (string, endm)
++ char *string;
++ int endm;
++ {
++ IVAL_S *ival = NULL, *nextival= NULL, *d;
++ regmatch_t pmatch;
++
++ if(ps_global->paterror == 0)
++ if (regexec(&ps_global->colorpat, string, 1, &pmatch, 0) == 0){
++ ival = (IVAL_S *) fs_get(sizeof(IVAL_S));
++ memset (ival, 0, sizeof(IVAL_S));
++ ival->start = endm + pmatch.rm_so;
++ ival->end = endm + pmatch.rm_eo;
++ nextival = compute_interval(string+pmatch.rm_so+1, ival->start+1);
++ if (nextival){
++ if (nextival->start <= ival->end){
++ ival->end = nextival->end;
++ d = nextival->next;
++ nextival->next = NULL;
++ ival->next = d;
++ interval_free(&nextival);
++ }
++ else
++ ival->next = nextival;
++ }
++ }
++ return ival;
++ }
++
++ void
++ regex_pattern(plist)
++ char **plist;
++ {
++ int i = 0, j = 0, len = 0;
++ char *pattern = NULL;
++ regex_t preg;
++
++ if(ps_global->paterror == 0)
++ regfree(&ps_global->colorpat);
++
++ if(plist && *plist && *plist){
++ for (i = 0; plist[i] && plist[i][0]; i++)
++ len += strlen(plist[i]) + 1;
++ pattern = (char *) fs_get(len * sizeof(char));
++ *pattern = '\0';
++ for (j = 0; j < i; j++){
++ strcat(pattern, plist[j]);
++ strcat(pattern, (j < i - 1) ? "|" : "");
++ }
++ if ((ps_global->paterror = regcomp(&preg, pattern, REG_EXTENDED)) != 0)
++ regfree(&preg);
++ else
++ ps_global->colorpat = preg;
++ }
++ if(pattern)
++ fs_give((void **)&pattern);
++ }
++
++ LT_INS_S **
++ insert_color_special_text(ins, p, ival, last_end, col)
++ LT_INS_S **ins;
++ char **p;
++ IVAL_S *ival;
++ int last_end;
++ COLOR_PAIR *col;
++ {
++ struct variable *vars = ps_global->vars;
++
++ if (ival){
++ *p += ival->start - last_end;
++ ins = gf_line_test_new_ins(ins, *p, color_embed(col->fg, col->bg),
++ (2 * RGBLEN) + 4);
++ *p += ival->end - ival->start;
++ ins = gf_line_test_new_ins(ins, *p, color_embed(VAR_NORM_FORE_COLOR,
++ VAR_NORM_BACK_COLOR), (2 * RGBLEN) + 4);
++ ins = insert_color_special_text(ins, p, ival->next, ival->end, col);
++ }
++ return ins;
++ }
++
++ int
++ length_color(p, begin_color)
++ char *p;
++ int begin_color;
++ {
++ int len = 0, done = begin_color ? 0 : -1;
++ char *orig = p;
++
++ while (*p && done <= 0){
++ switch(*p++){
++ case TAG_HANDLE :
++ p += *p + 1;
++ done++;
++ break;
++
++ case TAG_FGCOLOR :
++ case TAG_BGCOLOR :
++ p += RGBLEN;
++ if (!begin_color)
++ done++;
++ break;
++
++ default :
++ break;
++ }
++ }
++ len = p - orig;
++ return len;
++ }
++
++ int
++ any_color_in_string(p)
++ char *p;
++ {
++ int rv = 0;
++ char *orig = p;
++ while (*p && !rv)
++ if (*p++ == TAG_EMBED)
++ rv = p - orig;
++ return rv;
++ }
++
++ void
++ remove_spaces_ival(ivalp, p)
++ IVAL_S **ivalp;
++ char *p;
++ {
++ IVAL_S *ival;
++ int i;
++ if (!ivalp || !*ivalp)
++ return;
++ ival = *ivalp;
++ for (i = 0; isspace((unsigned char) p[ival->start + i]); i++);
++ if (ival->start + i < ival->end) /* do not do this if match only spaces */
++ ival->start += i;
++ else
++ return;
++ for (i = 0; isspace((unsigned char) p[ival->end - i - 1]); i++);
++ ival->end -= i;
++ if (ival->next)
++ remove_spaces_ival(&(ival->next), p);
++ }
++
++ int
++ color_this_text(linenum, line, ins, local)
++ long linenum;
++ char *line;
++ LT_INS_S **ins;
++ void *local;
++ {
++ struct variable *vars = ps_global->vars;
++ COLOR_PAIR *col = NULL;
++ char *p;
++ int i = 0;
++ static char *pattern = NULL;
++ /* char *buf;
++
++ select_quote(linenum, line, ins, (void *)code);
++ for (i = 0; tmp_20k_buf[i] && (buf[i] = tmp_20k_buf[i]); i++);
++ buf[i] = '\0'; */
++ p = line + i;
++
++ if(VAR_SPECIAL_TEXT_FORE_COLOR && VAR_SPECIAL_TEXT_BACK_COLOR
++ && (col = new_color_pair(VAR_SPECIAL_TEXT_FORE_COLOR,
++ VAR_SPECIAL_TEXT_BACK_COLOR))
++ && !pico_is_good_colorpair(col))
++ free_color_pair(&col);
++
++ if(ps_global->VAR_SPECIAL_TEXT && *ps_global->VAR_SPECIAL_TEXT
++ && **ps_global->VAR_SPECIAL_TEXT && col){
++ IVAL_S *ival;
++ int done = 0, begin_color = 0;
++
++ while (!done){
++ if (i = any_color_in_string(p)){
++ begin_color = (begin_color + 1) % 2;
++ if (begin_color){
++ p[i - 1] = '\0';
++ ival = compute_interval(p, 0);
++ remove_spaces_ival(&ival, p);
++ p[i - 1] = TAG_EMBED;
++ ins = insert_color_special_text(ins, &p, ival, 0, col);
++ }
++ for (;*p++ != TAG_EMBED; );
++ p += length_color(p, begin_color);
++ }
++ else{
++ ival = compute_interval(p, 0);
++ remove_spaces_ival(&ival, p);
++ ins = insert_color_special_text(ins, &p, ival, 0, col);
++ done++;
++ }
++ interval_free(&ival);
++ if (!*p)
++ done++;
++ }
++ free_color_pair(&col);
++ }
++
++ return 0;
++ }
+
+ /*
+ * The argument fieldname is something like "Subject:..." or "Subject".
+diff -rc alpine-2.00/pith/mailview.h alpine-2.00.I.USE/pith/mailview.h
+*** alpine-2.00/pith/mailview.h 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/pith/mailview.h 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 29,34 ****
+--- 29,40 ----
+ #include "../pith/color.h"
+
+
++ typedef struct IVAL {
++ int start;
++ int end;
++ struct IVAL *next;
++ } IVAL_S;
++
+ /* format_message flags */
+ #define FM_DISPLAY 0x0001 /* result is headed for display */
+ #define FM_NEW_MESS 0x0002 /* a new message so zero out attachment descrip */
+***************
+*** 125,130 ****
+--- 131,145 ----
+ int url_hilite(long, char *, LT_INS_S **, void *);
+ int handle_start_color(char *, size_t, int *, int);
+ int handle_end_color(char *, size_t, int *);
++ IVAL_S *compute_interval(char *, int);
++ void remove_spaces_ival(IVAL_S **, char *);
++ void interval_free(IVAL_S **);
++ void regex_pattern(char **);
++ LT_INS_S **insert_color_special_text(LT_INS_S **, char **, IVAL_S *,
++ int, COLOR_PAIR *);
++ int any_color_in_string(char *);
++ int length_color(char *, int);
++ int color_this_text(long, char *, LT_INS_S **, void *);
+
+ /*
+ * BUG: BELOW IS UNIX/PC ONLY since config'd browser means nothing to webpine
+***************
+*** 141,146 ****
+--- 156,162 ----
+ char *display_parameters(PARAMETER *);
+ char *pine_fetch_header(MAILSTREAM *, long, char *, char **, long);
+ int color_signature(long, char *, LT_INS_S **, void *);
++ int select_quote(long, char *, LT_INS_S **, void *);
+ int scroll_handle_start_color(char *, size_t, int *);
+ int scroll_handle_end_color(char *, size_t, int *, int);
+ int width_at_this_position(unsigned char *, unsigned long);
+diff -rc alpine-2.00/pith/Makefile.am alpine-2.00.I.USE/pith/Makefile.am
+*** alpine-2.00/pith/Makefile.am 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/pith/Makefile.am 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 25,31 ****
+ filter.c flag.c folder.c handle.c help.c helpindx.c hist.c icache.c imap.c init.c \
+ keyword.c ldap.c list.c mailcap.c mailcmd.c mailindx.c maillist.c mailview.c \
+ margin.c mimedesc.c mimetype.c msgno.c newmail.c news.c pattern.c pipe.c \
+! readfile.c remote.c reply.c rfc2231.c save.c search.c sequence.c send.c sort.c \
+ state.c status.c store.c stream.c string.c strlst.c takeaddr.c tempfile.c text.c \
+ thread.c adjtime.c url.c util.c helptext.c smkeys.c smime.c
+
+--- 25,31 ----
+ filter.c flag.c folder.c handle.c help.c helpindx.c hist.c icache.c imap.c init.c \
+ keyword.c ldap.c list.c mailcap.c mailcmd.c mailindx.c maillist.c mailview.c \
+ margin.c mimedesc.c mimetype.c msgno.c newmail.c news.c pattern.c pipe.c \
+! readfile.c remote.c reply.c rfc2231.c rules.c save.c search.c sequence.c send.c sort.c \
+ state.c status.c store.c stream.c string.c strlst.c takeaddr.c tempfile.c text.c \
+ thread.c adjtime.c url.c util.c helptext.c smkeys.c smime.c
+
+diff -rc alpine-2.00/pith/Makefile.in alpine-2.00.I.USE/pith/Makefile.in
+*** alpine-2.00/pith/Makefile.in 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/pith/Makefile.in 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 77,83 ****
+ margin.$(OBJEXT) mimedesc.$(OBJEXT) mimetype.$(OBJEXT) \
+ msgno.$(OBJEXT) newmail.$(OBJEXT) news.$(OBJEXT) \
+ pattern.$(OBJEXT) pipe.$(OBJEXT) readfile.$(OBJEXT) \
+! remote.$(OBJEXT) reply.$(OBJEXT) rfc2231.$(OBJEXT) \
+ save.$(OBJEXT) search.$(OBJEXT) sequence.$(OBJEXT) \
+ send.$(OBJEXT) sort.$(OBJEXT) state.$(OBJEXT) status.$(OBJEXT) \
+ store.$(OBJEXT) stream.$(OBJEXT) string.$(OBJEXT) \
+--- 77,83 ----
+ margin.$(OBJEXT) mimedesc.$(OBJEXT) mimetype.$(OBJEXT) \
+ msgno.$(OBJEXT) newmail.$(OBJEXT) news.$(OBJEXT) \
+ pattern.$(OBJEXT) pipe.$(OBJEXT) readfile.$(OBJEXT) \
+! remote.$(OBJEXT) reply.$(OBJEXT) rfc2231.$(OBJEXT) rules.$(OBJEXT) \
+ save.$(OBJEXT) search.$(OBJEXT) sequence.$(OBJEXT) \
+ send.$(OBJEXT) sort.$(OBJEXT) state.$(OBJEXT) status.$(OBJEXT) \
+ store.$(OBJEXT) stream.$(OBJEXT) string.$(OBJEXT) \
+***************
+*** 275,281 ****
+ filter.c flag.c folder.c handle.c help.c helpindx.c hist.c icache.c imap.c init.c \
+ keyword.c ldap.c list.c mailcap.c mailcmd.c mailindx.c maillist.c mailview.c \
+ margin.c mimedesc.c mimetype.c msgno.c newmail.c news.c pattern.c pipe.c \
+! readfile.c remote.c reply.c rfc2231.c save.c search.c sequence.c send.c sort.c \
+ state.c status.c store.c stream.c string.c strlst.c takeaddr.c tempfile.c text.c \
+ thread.c adjtime.c url.c util.c helptext.c smkeys.c smime.c
+
+--- 275,281 ----
+ filter.c flag.c folder.c handle.c help.c helpindx.c hist.c icache.c imap.c init.c \
+ keyword.c ldap.c list.c mailcap.c mailcmd.c mailindx.c maillist.c mailview.c \
+ margin.c mimedesc.c mimetype.c msgno.c newmail.c news.c pattern.c pipe.c \
+! readfile.c remote.c reply.c rfc2231.c rules.c save.c search.c sequence.c send.c sort.c \
+ state.c status.c store.c stream.c string.c strlst.c takeaddr.c tempfile.c text.c \
+ thread.c adjtime.c url.c util.c helptext.c smkeys.c smime.c
+
+***************
+*** 404,409 ****
+--- 404,410 ----
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/url.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
++ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rules.Po@am__quote@
+
+ .c.o:
+ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+diff -rc alpine-2.00/pith/makefile.wnt alpine-2.00.I.USE/pith/makefile.wnt
+*** alpine-2.00/pith/makefile.wnt 2007-10-24 14:58:00.000000000 -0700
+--- alpine-2.00.I.USE/pith/makefile.wnt 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 44,50 ****
+ init.h keyword.h ldap.h list.h mailcap.h mailcmd.h mailindx.h maillist.h \
+ mailpart.h mailview.h margin.h mimedesc.h mimetype.h msgno.h newmail.h news.h \
+ options.h pattern.h pineelt.h pipe.h readfile.h remote.h remtype.h repltype.h reply.h \
+! rfc2231.h save.h savetype.h search.h send.h sequence.h signal.h sort.h sorttype.h \
+ state.h status.h store.h stream.h string.h strlst.h takeaddr.h tempfile.h text.h \
+ thread.h url.h user.h util.h
+
+--- 44,50 ----
+ init.h keyword.h ldap.h list.h mailcap.h mailcmd.h mailindx.h maillist.h \
+ mailpart.h mailview.h margin.h mimedesc.h mimetype.h msgno.h newmail.h news.h \
+ options.h pattern.h pineelt.h pipe.h readfile.h remote.h remtype.h repltype.h reply.h \
+! rfc2231.h rules.h save.h savetype.h search.h send.h sequence.h signal.h sort.h sorttype.h \
+ state.h status.h store.h stream.h string.h strlst.h takeaddr.h tempfile.h text.h \
+ thread.h url.h user.h util.h
+
+***************
+*** 53,59 ****
+ filter.obj flag.obj folder.obj handle.obj help.obj helptext.obj hist.obj icache.obj imap.obj init.obj \
+ keyword.obj ldap.obj list.obj mailcap.obj mailcmd.obj mailindx.obj maillist.obj mailview.obj \
+ margin.obj mimedesc.obj mimetype.obj msgno.obj newmail.obj news.obj pattern.obj pipe.obj \
+! readfile.obj remote.obj reply.obj rfc2231.obj save.obj search.obj sequence.obj send.obj sort.obj state.obj \
+ status.obj store.obj stream.obj string.obj strlst.obj takeaddr.obj tempfile.obj text.obj \
+ thread.obj adjtime.obj url.obj util.obj
+
+--- 53,59 ----
+ filter.obj flag.obj folder.obj handle.obj help.obj helptext.obj hist.obj icache.obj imap.obj init.obj \
+ keyword.obj ldap.obj list.obj mailcap.obj mailcmd.obj mailindx.obj maillist.obj mailview.obj \
+ margin.obj mimedesc.obj mimetype.obj msgno.obj newmail.obj news.obj pattern.obj pipe.obj \
+! readfile.obj remote.obj reply.obj rfc2231.obj rules.obj save.obj search.obj sequence.obj send.obj sort.obj state.obj \
+ status.obj store.obj stream.obj string.obj strlst.obj takeaddr.obj tempfile.obj text.obj \
+ thread.obj adjtime.obj url.obj util.obj
+
+diff -rc alpine-2.00/pith/mimetype.c alpine-2.00.I.USE/pith/mimetype.c
+*** alpine-2.00/pith/mimetype.c 2008-03-06 12:54:01.000000000 -0800
+--- alpine-2.00.I.USE/pith/mimetype.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 178,183 ****
+--- 178,212 ----
+ panic("Unhandled mime type search");
+ }
+
++ /* if we still can not find the type, but it is a .docx (or alike) extension
++ set the type here. Do not use the grope function.
++ */
++ if(rv == 0){
++ rv = 1; /* assume success */
++ mt_map->to.mime.type = TYPEAPPLICATION;
++ if(!strucmp(mt_map->from.ext, "docx"))
++ mt_map->to.mime.subtype = cpystr("VND.OPENXMLFORMATS-OFFICEDOCUMENT.WORDPROCESSINGML.DOCUMENT");
++ else if(!strucmp(mt_map->from.ext, "xslx"))
++ mt_map->to.mime.subtype = cpystr("VND.OPENXMLFORMATS-OFFICEDOCUMENT.SPREADSHEETML.SHEET");
++ else if(!strucmp(mt_map->from.ext, "xltx"))
++ mt_map->to.mime.subtype = cpystr("VND.OPENXMLFORMATS-OFFICEDOCUMENT.SPREADSHEETML.TEMPLATE");
++ else if(!strucmp(mt_map->from.ext, "potx"))
++ mt_map->to.mime.subtype = cpystr("VND.OPENXMLFORMATS-OFFICEDOCUMENT.PRESENTATIONML.TEMPLATE");
++ else if(!strucmp(mt_map->from.ext, "ppsx"))
++ mt_map->to.mime.subtype = cpystr("VND.OPENXMLFORMATS-OFFICEDOCUMENT.PRESENTATIONML.SLIDESHOW");
++ else if(!strucmp(mt_map->from.ext, "pptx"))
++ mt_map->to.mime.subtype = cpystr("VND.OPENXMLFORMATS-OFFICEDOCUMENT.PRESENTATIONML.PRESENTATION");
++ else if(!strucmp(mt_map->from.ext, "sldx"))
++ mt_map->to.mime.subtype = cpystr("VND.OPENXMLFORMATS-OFFICEDOCUMENT.PRESENTATIONML.SLIDE");
++ else if(!strucmp(mt_map->from.ext, "dotx"))
++ mt_map->to.mime.subtype = cpystr("VND.OPENXMLFORMATS-OFFICEDOCUMENT.WORDPROCESSINGML.TEMPLATE");
++ else if(!strucmp(mt_map->from.ext, "xlam"))
++ mt_map->to.mime.subtype = cpystr("VND.MS-EXCEL.ADDIN.MACROENABLED.12");
++ else if(!strucmp(mt_map->from.ext, "xslb"))
++ mt_map->to.mime.subtype = cpystr("VND.MS-EXCEL.SHEET.BINARY.MACROENABLED.12");
++ else rv = 0; /* else, failure */
++ }
++
+
+ return(rv);
+ }
+diff -rc alpine-2.00/pith/msgno.c alpine-2.00.I.USE/pith/msgno.c
+*** alpine-2.00/pith/msgno.c 2007-12-03 16:13:55.000000000 -0800
+--- alpine-2.00.I.USE/pith/msgno.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 932,937 ****
+--- 932,943 ----
+ if((*peltp)->pthrd)
+ fs_give((void **) &(*peltp)->pthrd);
+
++ if((*peltp)->firsttext)
++ fs_give((void **) &(*peltp)->firsttext);
++
++ if((*peltp)->firsttextraw)
++ fs_give((void **) &(*peltp)->firsttextraw);
++
+ if((*peltp)->ice)
+ free_ice(&(*peltp)->ice);
+
+diff -rc alpine-2.00/pith/newmail.c alpine-2.00.I.USE/pith/newmail.c
+*** alpine-2.00/pith/newmail.c 2008-07-14 11:01:54.000000000 -0700
+--- alpine-2.00.I.USE/pith/newmail.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 684,692 ****
+ if(!for_new_mail_win)
+ q_status_message5(SM_ASYNC | SM_DING, 0, 60,
+ "%s%s%s%.80s%.80s", intro,
+! from ? ((number > 1L) ? " Most recent f" : " F") : "",
+! from ? "rom " : "",
+! from ? from : "",
+ subjtext);
+ #if (!defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)) || defined(_WINDOWS)
+ else {
+--- 684,692 ----
+ if(!for_new_mail_win)
+ q_status_message5(SM_ASYNC | SM_DING, 0, 60,
+ "%s%s%s%.80s%.80s", intro,
+! from && from[0] ? ((number > 1L) ? " Most recent f" : " F") : "",
+! from && from[0] ? "rom " : "",
+! from && from[0] ? from : "",
+ subjtext);
+ #if (!defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)) || defined(_WINDOWS)
+ else {
+***************
+*** 724,732 ****
+ }
+ else
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s%.80s", intro,
+! from ? ((number > 1L) ? " Most recent f" : " F") : "",
+! from ? "rom " : "",
+! from ? from : "");
+
+ (*pith_opt_icon_text)(tmp_20k_buf, IT_NEWMAIL);
+ }
+--- 724,732 ----
+ }
+ else
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s%.80s", intro,
+! from && from[0] ? ((number > 1L) ? " Most recent f" : " F") : "",
+! from && from[0] ? "rom " : "",
+! from && from[0] ? from : "");
+
+ (*pith_opt_icon_text)(tmp_20k_buf, IT_NEWMAIL);
+ }
+diff -rc alpine-2.00/pith/osdep/color.c alpine-2.00.I.USE/pith/osdep/color.c
+*** alpine-2.00/pith/osdep/color.c 2006-09-26 12:30:49.000000000 -0700
+--- alpine-2.00.I.USE/pith/osdep/color.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 31,37 ****
+
+ #include <system.h>
+ #include "./color.h"
+!
+
+
+ /*
+--- 31,37 ----
+
+ #include <system.h>
+ #include "./color.h"
+! #include "./collate.h"
+
+
+ /*
+***************
+*** 91,93 ****
+--- 91,1278 ----
+ {
+ return(pico_set_colors(col ? col->fg : NULL, col ? col->bg : NULL, flags));
+ }
++
++
++ /*
++ * Extended Justification support also does not belong here
++ * but otherwise webpine will not build, so we move everything
++ * here. Hopefully this will be the permanent place for these
++ * routines. This routines used to be in pico/word.c
++ */
++ #define NSTRING 256
++ #include "../../include/general.h"
++
++ /* Support of indentation of paragraphs */
++ #define is_indent_char(c) (((c) == '.' || (c) == '}' || (c) == RPAREN || \
++ (c) == '*' || (c) == '+' || is_a_digit(c) || \
++ ISspace(c) || (c) == '-' || \
++ (c) == ']') ? 1 : 0)
++ #define allowed_after_digit(c,word,k) ((((c) == '.' && \
++ allowed_after_period(next((word),(k)))) ||\
++ (c) == RPAREN || (c) == '}' || (c) == ']' ||\
++ ISspace(c) || is_a_digit(c) || \
++ ((c) == '-' ) && \
++ allowed_after_dash(next((word),(k)))) \
++ ? 1 : 0)
++ #define allowed_after_period(c) (((c) == RPAREN || (c) == '}' || (c) == ']' ||\
++ ISspace(c) || (c) == '-' || \
++ is_a_digit(c)) ? 1 : 0)
++ #define allowed_after_parenth(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_space(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_braces(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_star(c) ((ISspace(c) || (c) == RPAREN ||\
++ (c) == ']' || (c) == '}') ? 1 : 0)
++ #define allowed_after_dash(c) ((ISspace(c) || is_a_digit(c)) ? 1 : 0)
++ #define EOLchar(c) (((c) == '.' || (c) == ':' || (c) == '?' ||\
++ (c) == '!') ? 1 : 0)
++
++
++ /* Extended justification support */
++ #define is_cquote(c) ((c) == '>' || (c) == '|' || (c) == ']' || (c) == ':')
++ #define is_cword(c) ((((c) >= 'a') && ((c) <= 'z')) || \
++ (((c) >= 'A') && ((c) <= 'Z')) || \
++ (((c) >= '0') && ((c) <= '9')) || \
++ ((c) == ' ') || ((c) == '?') || \
++ ((c) == '@') || ((c) == '.') || \
++ ((c) == '!') || ((c) == '\'') || \
++ ((c) == ',') || ((c) == '\"') ? 1 : 0)
++ #define isaquote(c) ((c) == '\"' || (c) == '\'')
++ #define is8bit(c) ((((int) (c)) & 0x80) ? 1 : 0)
++ #define iscontrol(c) (iscntrl(((int) (c)) & 0x7f) ? 1 : 0)
++ #define forbidden(c) (((c) == '\"') || ((c) == '\'') || ((c) == '$') ||\
++ ((c) == ',') || ((c) == '.') || ((c) == '-') ||\
++ ((c) == LPAREN) || ((c) == '/')|| ((c) == '`') ||\
++ ((c) == '{') || ((c) == '\\') || (iscontrol((c))) ||\
++ (((c) >= '0') && ((c) <= '9')) || ((c) == '?'))
++ #define is_cletter(c) ((((c) >= 'a') && ((c) <= 'z'))) ||\
++ ((((c) >= 'A') && ((c) <= 'Z'))||\
++ is8bit(c))
++ #define is_cnumber(c) ((c) >= '0' && (c) <= '9')
++ #define allwd_after_word(c) (((c) == ' ') || ((c) == '>') || is_cletter(c))
++ #define allwd_after_qsword(c) (((c) != '\\') && ((c) != RPAREN))
++ #define before(word,i) (((i) > 0) ? (word)[(i) - 1] : 0)
++ #define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0)
++ #define now(w,i) ((w)[(i)])
++ #define is_qsword(c) (((c) == ':') || ((c) == RPAREN) ? 1 : 0)
++ #define is_colon(c) (((c) == ':') ? 1 : 0)
++ #define is_rarrow(c) (((c) == '>') ? 1 : 0)
++ #define is_tilde(c) (((c) == '~') ? 1 : 0)
++ #define is_dash(c) (((c) == '-') ? 1 : 0)
++ #define is_pound(c) (((c) == '#') ? 1 : 0)
++ #define is_a_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
++ #define is_allowed(c) (is_cquote(c) || is_cword(c) || is_dash(c) || \
++ is_pound(c))
++ #define qs_allowed(a) (((a)->qstype != qsGdb) && ((a)->qstype != qsProg))
++
++ /* Internal justification functions */
++ QSTRING_S *is_quote(char *, char *, int);
++ QSTRING_S *qs_normal_part(QSTRING_S *);
++ QSTRING_S *qs_remove_trailing_spaces(QSTRING_S *);
++ QSTRING_S *trim_qs_from_cl(QSTRING_S *, QSTRING_S *, QSTRING_S *);
++ QSTRING_S *fix_qstring(QSTRING_S *, QSTRING_S *, QSTRING_S *);
++ QSTRING_S *fix_qstring_allowed(QSTRING_S *, QSTRING_S *, QSTRING_S *);
++ QSTRING_S *qs_add(char *, char *, QStrType, int, int, int, int);
++ QSTRING_S *remove_qsword(QSTRING_S *);
++ QSTRING_S *do_raw_quote_match(char *, char *, char *, char *, QSTRING_S **, QSTRING_S **);
++ void free_qs(QSTRING_S **);
++ int word_is_prog(char *);
++ int qstring_is_normal(QSTRING_S *);
++ int exists_good_part(QSTRING_S *);
++ int strcmp_qs(char *, char *);
++ int count_levels_qstring(QSTRING_S *);
++ int same_qstring(QSTRING_S *, QSTRING_S *);
++ int advance_quote_string(char *, char *, int);
++ int isaword(char *,int ,int);
++ int isamailbox(char *,int ,int);
++
++
++ int
++ word_is_prog(char *word)
++ {
++ static char *list1[] = {"#include",
++ "#define",
++ "#ifdef",
++ "#ifndef",
++ "#elif",
++ "#if",
++ NULL};
++ static char *list2[] = {"#else",
++ "#endif",
++ NULL};
++ int i, j = strlen(word), k, rv = 0;
++
++ for(i = 0; rv == 0 && list1[i] && (k = strlen(list1[i])) && k < j; i++)
++ if(!strncmp(list1[i], word, k) && ISspace(word[k]))
++ rv++;
++
++ if(rv)
++ return rv;
++
++ for(i = 0; rv == 0 && list2[i] && (k = strlen(list2[i])) && k <= j; i++)
++ if(!strncmp(list2[i], word, k) && (!word[k] || ISspace(word[k])))
++ rv++;
++
++ return rv;
++ }
++
++ /*
++ * This function creates a qstring pointer with the information that
++ * is_quote handles to it.
++ * Parameters:
++ * qs - User supplied quote string
++ * word - The line of text that the user is trying to read/justify
++ * beginw - Where we need to start copying from
++ * endw - Where we end copying
++ * offset - Any offset in endw that we need to account for
++ * typeqs - type of the string to be created
++ * neednext - boolean, indicating if we need to compute the next field
++ * of leave it NULL
++ *
++ * It is a mistake to call this function if beginw >= endw + offset.
++ * Please note the equality sign in the above inequality (this is because
++ * we always assume that qstring->value != "").
++ */
++ QSTRING_S *
++ qs_add(qs, word, typeqs, beginw, endw, offset, neednext)
++ char *qs;
++ char word[NSTRING];
++ QStrType typeqs;
++ int beginw, endw, offset, neednext;
++ {
++ QSTRING_S *qstring, *nextqs;
++ int i;
++
++ qstring = (QSTRING_S *) malloc (sizeof(QSTRING_S));
++ memset (qstring, 0, sizeof(QSTRING_S));
++ qstring->qstype = qsNormal;
++
++ if (beginw == 0){
++ beginw = endw + offset;
++ qstring->qstype = typeqs;
++ }
++
++ nextqs = neednext ? is_quote(qs, word+beginw, 1) : NULL;
++
++ qstring->value = (char *) malloc((beginw+1)*sizeof(char));
++ strncpy(qstring->value, word, beginw);
++ qstring->value[beginw] = '\0';
++
++ qstring->next = nextqs;
++
++ return qstring;
++ }
++
++ int
++ qstring_is_normal(cl)
++ QSTRING_S *cl;
++ {
++ for (;cl && (cl->qstype == qsNormal); cl = cl->next);
++ return cl ? 0 : 1;
++ }
++
++ /*
++ * Given a quote string, this function returns the part that is the leading
++ * normal part of it. (the normal part is the part that is tagged qsNormal,
++ * that is to say, the one that is not controversial at all (like qsString
++ * for example).
++ */
++ QSTRING_S *
++ qs_normal_part(cl)
++ QSTRING_S *cl;
++ {
++
++ if (!cl) /* nothing in, nothing out */
++ return cl;
++
++ if (cl->qstype != qsNormal)
++ free_qs(&cl);
++
++ if (cl)
++ cl->next = qs_normal_part(cl->next);
++
++ return cl;
++ }
++
++ /*
++ * this function removes trailing spaces from a quote string, but leaves the
++ * last one if there are trailing spaces
++ */
++ QSTRING_S *
++ qs_remove_trailing_spaces(cl)
++ QSTRING_S *cl;
++ {
++ QSTRING_S *rl = cl;
++ if (!cl) /* nothing in, nothing out */
++ return cl;
++
++ if (cl->next)
++ cl->next = qs_remove_trailing_spaces(cl->next);
++ else{
++ if (value_is_space(cl->value))
++ free_qs(&cl);
++ else{
++ int i, l;
++ i = l = strlen(cl->value) - 1;
++ while (cl->value && cl->value[i]
++ && ISspace(cl->value[i]))
++ i--;
++ i += (i < l) ? 2 : 1;
++ cl->value[i] = '\0';
++ }
++ }
++ return cl;
++ }
++
++ /*
++ * This function returns if two strings are the same quote string.
++ * The call is not symmetric. cl must preceed the line nl. This function
++ * should be called for comparing the last part of cl and nl.
++ */
++ int
++ strcmp_qs(char *valuecl, char *valuenl)
++ {
++ int j;
++
++ for (j = 0; valuecl[j] && (valuecl[j] == valuenl[j]); j++);
++ return !strcmp(valuecl, valuenl)
++ || (valuenl[j] && value_is_space(valuenl+j)
++ && value_is_space(valuecl+j)
++ && strlenis(valuecl+j) >= strlenis(valuenl+j))
++ || (!valuenl[j] && value_is_space(valuecl+j));
++ }
++
++ int
++ count_levels_qstring(cl)
++ QSTRING_S *cl;
++ {
++ int count;
++ for (count = 0; cl ; count++, cl = cl->next);
++
++ return count;
++ }
++
++ int
++ value_is_space(char *value)
++ {
++ for (; value && *value && ISspace(*value); value++);
++
++ return value && *value ? 0 : 1;
++ }
++
++ void
++ free_qs(QSTRING_S **cl)
++ {
++ if (!(*cl))
++ return;
++
++ if ((*cl)->next)
++ free_qs(&((*cl)->next));
++
++ (*cl)->next = (QSTRING_S *) NULL;
++
++ if ((*cl)->value)
++ free((void *)(*cl)->value);
++ (*cl)->value = (char *) NULL;
++ free((void *)(*cl));
++ *cl = (QSTRING_S *) NULL;
++ }
++
++ /*
++ * This function returns the number of agreements between
++ * cl and nl. The call is not symmetric. cl must be the line
++ * preceding nl.
++ */
++ int
++ same_qstring(QSTRING_S *cl, QSTRING_S *nl)
++ {
++ int same = 0, done = 0;
++
++ for (;cl && nl && !done; cl = cl->next, nl = nl->next)
++ if (cl->qstype == nl->qstype
++ && (!strcmp(cl->value, nl->value)
++ || (!cl->next && strcmp_qs(cl->value, nl->value))))
++ same++;
++ else
++ done++;
++ return same;
++ }
++
++ QSTRING_S *
++ trim_qs_from_cl(QSTRING_S *cl, QSTRING_S *nl, QSTRING_S *pl)
++ {
++ QSTRING_S *cqstring = pl ? pl : nl;
++ QSTRING_S *tl = pl ? pl : nl;
++ int p, c;
++
++ if (qstring_is_normal(tl))
++ return tl;
++
++ p = same_qstring(pl ? pl : cl, pl ? cl : nl);
++
++ for (c = 1; c < p; c++, cl = cl->next, tl = tl->next);
++
++ /*
++ * cl->next and tl->next differ, it may be because cl->next does not
++ * exist or tl->next does not exist or simply both exist but are
++ * different. In this last case, it may be that cl->next->value is made
++ * of spaces. If this is the case, tl advances once more.
++ */
++
++ if (tl->next){
++ if (cl && cl->next && value_is_space(cl->next->value))
++ tl = tl->next;
++ if (tl->next)
++ free_qs(&(tl->next));
++ }
++
++ if (!p)
++ free_qs(&cqstring);
++
++ return cqstring;
++ }
++
++ /* This function trims cl so that it returns a real quote string based
++ * on information gathered from the previous and next lines. pl and cl are
++ * also trimmed, but that is done in another function, not here.
++ */
++ QSTRING_S *
++ fix_qstring(QSTRING_S *cl, QSTRING_S *nl, QSTRING_S *pl)
++ {
++ QSTRING_S *cqstring = cl, *nqstring = nl, *pqstring = pl;
++ int c, n;
++
++ if (qstring_is_normal(cl))
++ return cl;
++
++ c = count_levels_qstring(cl);
++ n = same_qstring(cl,nl);
++
++ if (!n){ /* no next line or no agreement with next line */
++ int p = same_qstring(pl, cl); /* number of agreements between pl and cl */
++ QSTRING_S *tl; /* test line */
++
++ /*
++ * Here p <= c, so either p < c or p == c. If p == c, we are done,
++ * and return cl. If not, there are two cases, either p == 0 or
++ * 0 < p < c. In the first case, we do not have enough evidence
++ * to return anything other than the normal part of cl, in the second
++ * case we can only return p levels of cl.
++ */
++
++ if (p == c)
++ tl = cqstring;
++ else{
++ if (p){
++ for (c = 1; c < p; c++)
++ cl = cl->next;
++ free_qs(&(cl->next));
++ tl = cqstring;
++ }
++ else{
++ int done = 0;
++ QSTRING_S *al = cl; /* another line */
++ /*
++ * Ok, we reaelly don't have enough evidence to return anything,
++ * different from the normal part of cl, but it could be possible
++ * that we may want to accept the not-normal part, so we better
++ * make an extra test to determine what needs to be freed
++ */
++ while (pl && cl && cl->qstype == pl->qstype
++ && !strucmp(cl->value, pl->value)){
++ cl = cl->next;
++ pl = pl->next;
++ }
++ if (pl && cl && cl->qstype == pl->qstype
++ && strcmp_qs(pl->value, cl->value))
++ cl = cl->next; /* next level differs only in spaces */
++ while (!done){
++ while (cl && cl->qstype == qsNormal)
++ cl = cl->next;
++ if (cl){
++ if ((cl->qstype == qsString)
++ && (cl->value[strlen(cl->value) - 1] == '>'))
++ cl = cl->next;
++ else done++;
++ }
++ else done++;
++ }
++ if (al == cl){
++ free_qs(&(cl));
++ tl = cl;
++ }
++ else {
++ while (al && (al->next != cl))
++ al = al->next;
++ cl = al;
++ if (cl && cl->next)
++ free_qs(&(cl->next));
++ tl = cqstring;
++ }
++ }
++ }
++ return tl;
++ }
++ if (n + 1 < c){ /* if there are not enough agreements */
++ int p = same_qstring(pl, cl); /* number of agreement between pl and cl */
++ QSTRING_S *tl; /* test line */
++ /*
++ * There's no way we can use cl in this case, but we can use
++ * part of cl, this is if pl does not have more agreements
++ * with cl.
++ */
++ if (p == c)
++ tl = cqstring;
++ else{
++ int m = p < n ? n : p;
++ for (c = 1; c < m; c++){
++ pl = pl ? pl->next : (QSTRING_S *) NULL;
++ nl = nl ? nl->next : (QSTRING_S *) NULL;
++ cl = cl->next;
++ }
++ if (p == n && pl && pl->next && nl && nl->next
++ && ((cl->next->qstype == pl->next->qstype)
++ || (cl->next->qstype == nl->next->qstype))
++ && (strcmp_qs(cl->next->value, pl->next->value)
++ || strcmp_qs(pl->next->value, cl->next->value)
++ || strcmp_qs(cl->next->value, nl->next->value)
++ || strcmp_qs(nl->next->value, cl->next->value)))
++ cl = cl->next; /* next level differs only in spaces */
++ if (cl->next)
++ free_qs(&(cl->next));
++ tl = cqstring;
++ }
++ return tl;
++ }
++ if (n + 1 == c){
++ int p = same_qstring(pl, cl);
++ QSTRING_S *tl; /* test line */
++
++ /*
++ * p <= c, so p <= n+1, which means p < n + 1 or p == n + 1.
++ * If p < n + 1, then p <= n.
++ * so we have three possibilities:
++ * p == n + 1 or p == n or p < n.
++ * In the first case we copy p == n + 1 == c levels, in the second
++ * and third case we copy n levels, and check if we can copy the
++ * n + 1 == c level.
++ */
++ if (p == n + 1) /* p == c, in the above sense of c */
++ tl = cl; /* use cl, this is enough evidence */
++ else{
++ for (c = 1; c < n; c++)
++ cl = cl->next;
++ /*
++ * Here c == n, we only have one more level of cl, and at least one
++ * more level of nl
++ */
++ if (cl->next->qstype == qsNormal)
++ cl = cl->next;
++ if (cl->next)
++ free_qs(&(cl->next));
++ tl = cqstring;
++ }
++ return tl;
++ }
++ if (n == c) /* Yeah!!! */
++ return cqstring;
++ }
++
++ QSTRING_S *
++ fix_qstring_allowed(QSTRING_S *cl, QSTRING_S *nl, QSTRING_S *pl)
++ {
++ if(!cl)
++ return (QSTRING_S *) NULL;
++
++ if (qs_allowed(cl))
++ cl->next = fix_qstring_allowed(cl->next, (nl ? nl->next : NULL),
++ (pl ? pl->next : NULL));
++ else
++ if((nl && cl->qstype == nl->qstype) || (pl && cl->qstype == pl->qstype)
++ || (!nl && !pl))
++ free_qs(&cl);
++ return cl;
++ }
++
++ /*
++ * This function flattens the quote string returned to us by is_quote. A
++ * crash in this function implies a bug elsewhere.
++ */
++ void
++ flatten_qstring(QSTRING_S *qs, char *buff, int bufflen)
++ {
++ int i, j;
++ if(!buff || bufflen <= 0)
++ return;
++
++ for (i = 0; qs; qs = qs->next)
++ for (j = 0; i < bufflen - 1
++ && (qs->value[j]) && (buff[i++] = qs->value[j]); j++);
++ buff[i] = '\0';
++ }
++
++ /*
++ * Given a string, we return the position where the function thinks that
++ * the quote string is over, if you are ever thinking of fixing something,
++ * you got to the right place. Memory freed by caller. Experience shows
++ * that it only makes sense to initialize memory when we need it, not at
++ * the start of this function.
++ */
++ QSTRING_S *
++ is_quote (char *qs,char *word, int been_here)
++ {
++ int i = 0, j, nxt, prev, finished = 0, offset;
++ unsigned char c;
++ QSTRING_S *qstring = (QSTRING_S *) NULL;
++
++ if (!word || !word[0])
++ return (QSTRING_S *) NULL;
++
++ while (!finished){
++ /*
++ * Before we apply our rules, let's advance past the quote string
++ * given by the user, this will avoid not recognition of the
++ * user's indent string and application of the arbitrary rules
++ * below. Notice that this step may bring bugs into this
++ * procedure, but these bugs will only appear if the indent string
++ * is really really strange and the text to be justified
++ * cooperates a lot too, so in general this will not be a problem.
++ * If you are concerned about this bug, simply remove the
++ * following lines after this comment and before the "switch"
++ * command below and use a more normal quote string!.
++ */
++ i += advance_quote_string(qs, word, i);
++ if (!word[i]) /* went too far? */
++ return qs_add(qs, word, qsNormal, 0, i, 0, 0);
++
++ switch (c = (unsigned char) now(word,i)){
++ case NBSP:
++ case TAB :
++ case ' ' : { QSTRING_S *nextqs, *d;
++
++ for (; ISspace(word[i]); i++); /* FIX ME */
++ nextqs = is_quote(qs,word+i, 1);
++ /*
++ * Merge qstring and nextqs, since this is an artificial
++ * separation, unless nextqs is of different type.
++ * What this means in practice is that if
++ * qs->qstype == qsNormal and qs->next != NULL, then
++ * qs->next->qstype != qsNormal.
++ *
++ * Can't use qs_add to merge because it could lead
++ * to an infinite loop (e.g a line "^ ^").
++ */
++ i += nextqs && nextqs->qstype == qsNormal
++ ? strlen(nextqs->value) : 0;
++ qstring = (QSTRING_S *) malloc (sizeof(QSTRING_S));
++ memset (qstring, 0, sizeof(QSTRING_S));
++ qstring->value = (char *) malloc((i+1)*sizeof(char));
++ strncpy(qstring->value, word, i);
++ qstring->value[i] = '\0';
++ qstring->qstype = qsNormal;
++ if(nextqs && nextqs->qstype == qsNormal){
++ d = nextqs->next;
++ nextqs->next = NULL;
++ qstring->next = d;
++ free_qs(&nextqs);
++ }
++ else
++ qstring->next = nextqs;
++
++ return qstring;
++ }
++ break;
++ case RPAREN: /* parenthesis ')' */
++ if ((i != 0) || ((i == 0) && been_here))
++ i++;
++ else
++ if (i == 0)
++ return qs_add(qs, word, qsChar, i, i, 1, 1);
++ else
++ finished++;
++ break;
++
++ case ':': /* colon */
++ case '~': nxt = next(word,i);
++ if ((is_tilde(c) && (nxt == '/'))
++ || (is_colon(c) && !is_cquote(nxt)
++ && !is_cword(nxt) && nxt != RPAREN))
++ finished++;
++ else if (is_cquote(c)
++ || is_cquote(nxt)
++ || (c != '~' && nxt == RPAREN)
++ || (i != 0 && ISspace(nxt))
++ || is_cquote(prev = before(word,i))
++ || (ISspace(prev) && !is_tilde(c))
++ || (is_tilde(c) && nxt != '/'))
++ i++;
++ else if (i == 0 && been_here)
++ return qs_add(qs, word, qsChar, i, i, 1, 1);
++ else
++ finished++;
++ break;
++
++ case '<' :
++ case '=' :
++ case '-' : offset = is_cquote(nxt = next(word,i)) ? 2
++ : (nxt == c && is_cquote(next(word,i+1))) ? 3 : -1;
++
++ if (offset > 0)
++ return qs_add(qs, word, qsString, i, i, offset, 1);
++ else
++ finished++;
++ break;
++
++ case '[' :
++ case '+' : /* accept +>, *> */
++ case '*' : if (is_rarrow(nxt = next(word, i)) || /* stars */
++ (ISspace(nxt) && is_rarrow(next(word,i+1))))
++ i++;
++ else
++ finished++;
++ break;
++
++ case '^' :
++ case '!' :
++ case '%' : if (next(word,i) != c)
++ return qs_add(qs, word, qsChar, i, i+1, 0, 1);
++ else
++ finished++;
++ break;
++
++ case '_' : if(ISspace(next(word, i)))
++ return qs_add(qs, word, qsChar, i, i+1, 0, 1);
++ else
++ finished++;
++ break;
++
++ case '#' : { QStrType qstype = qsChar;
++ if((nxt = next(word, i)) != c){
++ if(isdigit((int) nxt))
++ qstype = qsGdb;
++ else
++ if(word_is_prog(word))
++ qstype = qsProg;
++ return qs_add(qs, word, qstype, i, i+1, 0, 1);
++ }
++ else
++ finished++;
++ break;
++ }
++
++ default:
++ if (is_cquote(c))
++ i++;
++ else if (is_cletter(c)){
++ for (j = i; (is_cletter(nxt = next(word,j)) || is_cnumber(nxt))
++ && !(ISspace(nxt));j++);
++ /*
++ * The whole reason why we are splitting the quote
++ * string is so that we will be able to accept quote
++ * strings that are strange in some way. Here we got to
++ * a point in which a quote string might exist, but it
++ * could be strange, so we need to create a "next" field
++ * for the quote string to warn us that something
++ * strange is coming. We need to confirm if this is a
++ * good choice later. For now we will let it pass.
++ */
++ if (isaword(word,i,j) || isamailbox(word,i,j)){
++ int offset;
++ QStrType qstype;
++
++ offset = (is_cquote(c = next(word,j))
++ || (c == RPAREN)) ? 2
++ : ((ISspace(c)
++ && is_cquote(next(word,j+1))) ? 3 : -1);
++
++ qstype = (is_cquote(c) || (c == RPAREN))
++ ? (is_qsword(c) ? qsWord : qsString)
++ : ((ISspace(c) && is_cquote(next(word,j+1)))
++ ? (is_qsword(next(word,j+1))
++ ? qsWord : qsString)
++ : qsString);
++
++ /*
++ * qsWords are valid quote strings only when
++ * they are followed by text.
++ */
++ if (offset > 0 && qstype == qsWord &&
++ !allwd_after_qsword(now(word,j + offset)))
++ offset = -1;
++
++ if (offset > 0)
++ return qs_add(qs, word, qstype, i, j, offset, 1);
++ }
++ finished++;
++ }
++ else{
++ if(i > 0)
++ return qs_add(qs, word, qsNormal, 0, i, 0, 1);
++ else if(!forbidden(c))
++ return qs_add(qs, word, qsChar, 0, 1, 0, 1);
++ else /* chao pescao */
++ finished++;
++ }
++ break;
++ } /* End Switch */
++ } /* End while */
++ if (i > 0)
++ qstring = qs_add(qs, word, qsNormal, 0, i, 0, 0);
++ return qstring;
++ }
++
++ int
++ isaword(word,i,j)
++ char word[NSTRING];
++ int i;
++ int j;
++ {
++ return i <= j && is_cletter(word[i]) ?
++ (i < j ? isaword(word,i+1,j) : 1) : 0;
++ }
++
++ int
++ isamailbox(word,i,j)
++ char word[NSTRING];
++ int i, j;
++ {
++ return i <= j && (is_cletter(word[i]) || is_a_digit(word[i])
++ || word[i] == '.')
++ ? (i < j ? isamailbox(word,i+1,j) : 1) : 0;
++ }
++
++ /*
++ This routine removes the last part that is qsword or qschar that is not
++ followed by a normal part. This means that if a qsword or qschar is
++ followed by a qsnormal (or qsstring), we accept the qsword (or qschar)
++ as part of a quote string.
++ */
++ QSTRING_S *
++ remove_qsword(cl)
++ QSTRING_S *cl;
++ {
++ QSTRING_S *np = cl;
++ QSTRING_S *cp = np; /* this variable trails cl */
++
++ while(1){
++ while (cl && cl->qstype == qsNormal)
++ cl = cl->next;
++
++ if (cl){
++ if (((cl->qstype == qsWord) || (cl->qstype == qsChar))
++ && !exists_good_part(cl)){
++ if (np == cl) /* qsword or qschar at the beginning */
++ free_qs(&cp);
++ else{
++ while (np->next != cl)
++ np = np->next;
++ free_qs(&(np->next));
++ }
++ break;
++ }
++ else
++ cl = cl->next;
++ }
++ else
++ break;
++ }
++ return cp;
++ }
++
++ int
++ exists_good_part (cl)
++ QSTRING_S *cl;
++ {
++ return (cl ? (((cl->qstype != qsWord) && (cl->qstype != qsChar)
++ && qs_allowed(cl) && !value_is_space(cl->value))
++ ? 1 : exists_good_part(cl->next))
++ : 0);
++ }
++
++ int
++ line_isblank(char *q, char *GLine, char *NLine, char *PLine, int buflen)
++ {
++ int n = 0;
++ QSTRING_S *cl;
++ char qstr[NSTRING];
++
++ cl = do_raw_quote_match(q, GLine, NLine, PLine, NULL, NULL);
++
++ flatten_qstring(cl, qstr, NSTRING);
++
++ free_qs(&cl);
++
++ for(n = strlen(qstr); n < buflen && GLine[n]; n++)
++ if(!ISspace((unsigned char) GLine[n]))
++ return(FALSE);
++
++ return(TRUE);
++ }
++
++ QSTRING_S *
++ do_raw_quote_match(char *q, char *GLine, char *NLine, char *PLine, QSTRING_S **nlp, QSTRING_S **plp)
++ {
++ QSTRING_S *cl, *nl = NULL, *pl = NULL;
++ char nbuf[NSTRING], pbuf[NSTRING], buf[NSTRING];
++ int emptypl = 0, emptynl = 0;
++
++ if (!(cl = is_quote(q, GLine, 0))) /* if nothing in, nothing out */
++ return cl;
++
++ nl = is_quote(q, NLine, 0); /* Next Line */
++ if (nlp) *nlp = nl;
++ pl = is_quote(q, PLine, 0); /* Previous Line */
++ if (plp) *plp = pl;
++ /*
++ * If there's nothing in the preceeding or following line
++ * there is not enough information to accept it or discard it. In this
++ * case it's likely to be an isolated line, so we better accept it
++ * if it does not look like a word.
++ */
++ flatten_qstring(pl, pbuf, NSTRING);
++ emptypl = (!PLine || !PLine[0] ||
++ (pl && value_is_space(pbuf)) && !PLine[strlen(pbuf)]) ? 1 : 0;
++ if (emptypl){
++ flatten_qstring(nl, nbuf, NSTRING);
++ emptynl = (!NLine || !NLine[0] ||
++ (nl && value_is_space(nbuf) && !NLine[strlen(nbuf)])) ? 1 : 0;
++ if (emptynl){
++ cl = remove_qsword(cl);
++ if((cl = fix_qstring_allowed(cl, NULL, NULL)) != NULL)
++ cl = qs_remove_trailing_spaces(cl);
++ free_qs(&nl);
++ free_qs(&pl);
++ if(nlp) *nlp = NULL;
++ if(plp) *plp = NULL;
++
++ return cl;
++ }
++ }
++
++ /*
++ * If either cl, nl or pl contain suspicious characters that may make
++ * them (or not) be quote strings, we need to fix them, so that the
++ * next pass will be done correctly.
++ */
++
++ cl = fix_qstring(cl, nl, pl);
++ nl = trim_qs_from_cl(cl, nl, NULL);
++ pl = trim_qs_from_cl(cl, NULL, pl);
++ if((cl = fix_qstring_allowed(cl, nl, pl)) != NULL){
++ nl = trim_qs_from_cl(cl, nl, NULL);
++ pl = trim_qs_from_cl(cl, NULL, pl);
++ }
++ else{
++ free_qs(&nl);
++ free_qs(&pl);
++ }
++ if(nlp)
++ *nlp = nl;
++ else
++ free_qs(&nl);
++ if(plp)
++ *plp = pl;
++ else
++ free_qs(&pl);
++ return cl;
++ }
++
++ QSTRING_S *
++ do_quote_match(q, GLine, NLine, PLine, rqstr, rqstrlen, plb)
++ char *q, *GLine, *NLine, *PLine, *rqstr;
++ int rqstrlen, plb;
++ {
++ QSTRING_S *cl, *nl = NULL, *pl = NULL;
++ int c, n, p,i, j, NewP, NewC, NewN, clength, same = 0;
++ char nbuf[NSTRING], pbuf[NSTRING], buf[NSTRING];
++
++ if(rqstr)
++ *rqstr = '\0';
++
++ /* if nothing in, nothing out */
++ cl = do_raw_quote_match(q, GLine, NLine, PLine, &nl, &pl);
++ if(cl == NULL){
++ free_qs(&nl);
++ free_qs(&pl);
++ return cl;
++ }
++
++ flatten_qstring(cl, rqstr, rqstrlen);
++ flatten_qstring(cl, buf, NSTRING);
++ flatten_qstring(nl, nbuf, NSTRING);
++ flatten_qstring(pl, pbuf, NSTRING);
++
++ /*
++ * Once upon a time, is_quote used to return the length of the quote
++ * string that it had found. One day, not long ago, black hand came
++ * and changed all that, and made is_quote return a quote string
++ * divided in several fields, making the algorithm much more
++ * complicated. Fortunately black hand left a few comments in the
++ * source code to make it more understandable. Because of this change
++ * we need to compute the lengths of the quote strings separately
++ */
++ c = buf && buf[0] ? strlen(buf) : 0;
++ n = nbuf && nbuf[0] ? strlen(nbuf) : 0;
++ p = pbuf && pbuf[0] ? strlen(pbuf) : 0;
++ /*
++ * When quote strings contain only blank spaces (ascii code 32) the
++ * above count is equal to the length of the quote string, but if
++ * there are TABS, the length of the quote string as seen by the user
++ * is different than the number that was just computed. Because of
++ * this we demand a recount (hmm.. unless you are in Florida, where
++ * recounts are forbidden)
++ */
++ NewP = strlenis(pbuf);
++ NewC = strlenis(buf);
++ NewN = strlenis(nbuf);
++
++ /*
++ * For paragraphs with spaces in the first line, but no space in the
++ * quote string of the second line, we make sure we choose the quote
++ * string without a space at the end of it.
++ */
++ if ((NLine && !NLine[0])
++ && ((PLine && !PLine[0])
++ || (((same = same_qstring(pl, cl)) != 0)
++ && (same != count_levels_qstring(cl)))))
++ cl = qs_remove_trailing_spaces(cl);
++ else
++ if (NewC > NewN){
++ int agree = 0;
++ for (j = 0; (j < n) && (GLine[j] == NLine[j]); j++);
++ clength = j;
++ /* clength is the common length in which Gline and Nline agree */
++ /* j < n means that they do not agree fully */
++ /* GLine = " \tText"
++ NLine = " Text" */
++ if(j == n)
++ agree++;
++ if (clength < n){ /* see if buf and nbuf are padded with spaces and tabs */
++ for (i = clength; i < n && ISspace(NLine[i]); i++);
++ if (i == n){/* padded NLine until the end of spaces? */
++ for (i = clength; i < c && ISspace(GLine[i]); i++);
++ if (i == c) /* Padded CLine until the end of spaces? */
++ agree++;
++ }
++ }
++ if (agree){
++ for (j = clength; j < c && ISspace(GLine[j]); j++);
++ if (j == c){
++ /*
++ * If we get here, it means that the current line has the same
++ * quote string (visually) than the next line, but both of them
++ * are padded with different amount of TABS or spaces at the end.
++ * The current line (GLine) has more spaces/TABs than the next
++ * line. This is the typical situation that is found at the
++ * begining of a paragraph. We need to check this, however, by
++ * checking the previous line. This avoids that we confuse
++ * ourselves with being in the last line of a paragraph.
++ * Example when it should not free_qs(cl)
++ * " Text in Paragraph 1" (PLine)
++ * " Text in Paragraph 1" (GLine)
++ * " Other Paragraph Number 2" (NLine)
++ *
++ * Example when it should free_qs(cl):
++ * ":) " (PLine) p = 3, j = 3
++ * ":) Text" (GLine) c = 5
++ * ":) More text" (NLine) n = 3
++ *
++ * Example when it should free_qs(cl):
++ * ":) " (PLine) p = 3, j = 3
++ * ":) > > > Text" (GLine) c = 11
++ * ":) > > > More text" (NLine) n = 9
++ *
++ * Example when it should free_qs(cl):
++ * ":) :) " (PLine) p = 6, j = 3
++ * ":) > > > Text" (GLine) c = 11
++ * ":) > > > More text" (NLine) n = 9
++ *
++ * Example when it should free_qs(cl):
++ * ":) > > > " (PLine) p = 13, j = 11
++ * ":) > > > Text" (GLine) c = 11
++ * ":) > > > More text" (NLine) n = 9
++ *
++ * The following example is very interesting. The "Other Text"
++ * line below should free the quote string an make it equal to the
++ * quote string of the line below it, but any algorithm trying
++ * to advance past that line should make it stop there, so
++ * we need one more check, to check the raw quote string and the
++ * processed quote string at the same time.
++ * FREE qs in this example.
++ * " Some Text" (PLine) p = 3, j = 0
++ * "\tOther Text" (GLine) c = 1
++ * " More Text" (NLine) n = 3
++ *
++ */
++ for (j = 0; (j < p) && (GLine[j] == PLine[j]); j++);
++ if ((p != c || j != p) && NLine[n])
++ if(!get_indent_raw_line(q, PLine, nbuf, NSTRING, p, plb)
++ || NewP + strlenis(nbuf) != NewC){
++ free_qs(&cl);
++ free_qs(&pl);
++ return nl;
++ }
++ }
++ }
++ }
++
++ free_qs(&nl);
++ free_qs(&pl);
++
++ return cl;
++ }
++
++ /*
++ * Given a line, an initial position, and a quote string, we advance the
++ * current line past the quote string, including arbitraty spaces
++ * contained in the line, except that it removes trailing spaces. We do
++ * not handle TABs, if any, contained in the quote string. At least not
++ * yet.
++ *
++ * Arguments: q - quote string
++ * l - a line to process
++ * i - position in the line to start processing. i = 0 is the
++ * begining of that line.
++ */
++ int
++ advance_quote_string(q, l, i)
++ char *q;
++ char l[NSTRING];
++ int i;
++ {
++ int n = 0, j = 0, is = 0, es = 0;
++ int k, m, p, adv;
++ char qs[NSTRING] = {'\0'};
++ if(!q || !*q)
++ return(0);
++ for (p = strlen(q); (p > 0) && (q[p - 1] == ' '); p--, es++);
++ if (!p){ /* string contains only spaces */
++ for (k = 0; ISspace(l[i + k]); k++);
++ k -= k % es;
++ return k;
++ }
++ for (is = 0; ISspace(q[is]); is++); /* count initial spaces */
++ for (m = 0 ; is + m < p ; m++)
++ qs[m] = q[is + m]; /* qs = quote string without any space at the end */
++ /* advance as many spaces as there are at the begining */
++ for (k = 0; ISspace(l[i + j]); k++, j++);
++ /* now find the visible string in the line */
++ for (m = 0; qs[m] && l[i + j] == qs[m]; m++, j++);
++ if (!qs[m]){ /* no match */
++ /*
++ * So far we have advanced at least "is" spaces, plus the visible
++ * string "qs". Now we need to advance the trailing number of
++ * spaces "es". If we can do that, we have found the quote string.
++ */
++ for (p = 0; ISspace(l[i + j + p]); p++);
++ adv = advance_quote_string(q, l, i + j + ((p < es) ? p : es));
++ n = ((p < es) ? 0 : es) + k + m + adv;
++ }
++ return n;
++ }
++
++ /*
++ * This function returns the effective length in screen of the quote
++ * string. If the string contains a TAB character, it is added here, if
++ * not, the length returned is the length of the string
++ */
++ int strlenis(char *qstr)
++ {
++ int i, rv = 0;
++ for (i = 0; qstr && qstr[i]; i++)
++ rv += ((qstr[i] == TAB) ? (~rv & 0x07) + 1 : 1);
++ return rv;
++ }
++
++ int
++ is_indent (word, plb)
++ char word[NSTRING];
++ int plb;
++ {
++ int i = 0, finished = 0, c, nxt, j, k, digit = 0, bdigits = -1, alpha = 0;
++
++ if (!word || !word[0])
++ return i;
++
++ for (i = 0, j = 0; ISspace(word[i]); i++, j++);
++ while ((i < NSTRING - 2) && !finished){
++ switch (c = now(word,i)){
++ case NBSP:
++ case TAB :
++ case ' ' : for (; ISspace(word[i]); i++);
++ if (!is_indent_char(now(word,i)))
++ finished++;
++ break;
++
++ case '+' :
++ case '.' :
++ case ']' :
++ case '*' :
++ case '}' :
++ case '-' :
++ case RPAREN:
++ nxt = next(word,i);
++ if ((c == '.' && allowed_after_period(nxt) && alpha)
++ || (c == '*' && allowed_after_star(nxt))
++ || (c == '}' && allowed_after_braces(nxt))
++ || (c == '-' && allowed_after_dash(nxt))
++ || (c == '+' && allowed_after_dash(nxt))
++ || (c == RPAREN && allowed_after_parenth(nxt))
++ || (c == ']' && allowed_after_parenth(nxt)))
++ i++;
++ else
++ finished++;
++ break;
++
++ default : if (is_a_digit(c) && plb){
++ if (bdigits < 0)
++ bdigits = i; /* first digit */
++ for (k = i; is_a_digit(now(word,k)); k++);
++ if (k - bdigits > 2){ /* more than 2 digits? */
++ i = bdigits; /* too many! */
++ finished++;
++ }
++ else{
++ if(allowed_after_digit(now(word,k),word,k)){
++ alpha++;
++ i = k;
++ }
++ else{
++ i = bdigits;
++ finished++;
++ }
++ }
++ }
++ else
++ finished++;
++ break;
++
++ }
++ }
++ if (i == j)
++ i = 0; /* there must be something more than spaces in an indent string */
++ return i;
++ }
++
++ int
++ get_indent_raw_line(char *q, char *GLine, char *buf, int buflen, int k, int plb)
++ {
++ int i, j;
++ char testline[1024];
++
++ if(k > 0){
++ for(j = 0; GLine[j] != '\0'; j++){
++ testline[j] = GLine[j];
++ testline[j+1] = '\0';
++ if(strlenis(testline) >= strlenis(buf))
++ break;
++ }
++ k = ++j; /* reset k */
++ }
++ i = is_indent(GLine+k, plb);
++
++ for (j = 0; j < i && j < buflen && (buf[j] = GLine[j + k]); j++);
++ buf[j] = '\0';
++
++ return i;
++ }
++
+diff -rc alpine-2.00/pith/osdep/color.h alpine-2.00.I.USE/pith/osdep/color.h
+*** alpine-2.00/pith/osdep/color.h 2008-03-24 12:35:31.000000000 -0700
+--- alpine-2.00.I.USE/pith/osdep/color.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 43,48 ****
+--- 43,69 ----
+ #define PSC_REV 0x2
+ #define PSC_RET 0x4 /* return an allocated copy of previous color */
+
++ /*
++ * struct that will help us determine what the quote string of a line
++ * is. The "next" field indicates the presence of a possible continuation.
++ * The idea is that if a continuation fails, we free it and check for the
++ * remaining structure left
++ */
++
++ typedef enum {qsNormal, qsString, qsWord, qsChar,
++ qsGdb, qsProg, qsText} QStrType;
++
++ typedef struct QSTRING {
++ char *value; /* possible quote string */
++ QStrType qstype; /* type of quote string */
++ struct QSTRING *next; /* possible continuation */
++ } QSTRING_S;
++
++ #define UCH(c) ((unsigned char) (c))
++ #define NBSP UCH('\240')
++ #define ISspace(c) (UCH(c) == ' ' || UCH(c) == TAB || UCH(c) == NBSP)
++
++
+
+ /*
+ * MATCH_NORM_COLOR means that the color that is set to this value
+***************
+*** 92,97 ****
+--- 113,123 ----
+ char *pico_get_last_bg_color(void);
+ char *color_to_canonical_name(char *);
+ int pico_count_in_color_table(void);
++ int is_indent(char *, int);
++ int get_indent_raw_line (char *, char *, char *, int, int, int);
++ int line_isblank(char *, char *, char *, char *, int);
++ int strlenis(char *);
++ int value_is_space(char *);
+
+
+ #endif /* PITH_OSDEP_COLOR_INCLUDED */
+diff -rc alpine-2.00/pith/osdep/domnames.c alpine-2.00.I.USE/pith/osdep/domnames.c
+*** alpine-2.00/pith/osdep/domnames.c 2006-11-17 18:46:41.000000000 -0800
+--- alpine-2.00.I.USE/pith/osdep/domnames.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 51,57 ****
+ char **alias;
+ char *maybe = NULL;
+
+! gethostname(hname, MAX_ADDRESS);
+ he = gethostbyname(hname);
+ hostname[0] = '\0';
+
+--- 51,70 ----
+ char **alias;
+ char *maybe = NULL;
+
+! if (gethostname(hname, MAX_ADDRESS)) hname[0] = 0xff;
+! /* sanity check of hostname string */
+! for (dn = hname; (*dn > 0x20) && (*dn < 0x7f); ++dn);
+! if (*dn) { /* only if invalid string returned */
+! #if 0
+! hostname[0] = domainname[0] = '\0';
+! #else
+! /* Contrary to the comments above, the UNIX code does not expect
+! these strings to be blank.
+! */
+! strcpy (hostname, (strcpy (domainname,"unknown")));
+! #endif
+! return;
+! }
+ he = gethostbyname(hname);
+ hostname[0] = '\0';
+
+diff -rc alpine-2.00/pith/osdep/hostname.c alpine-2.00.I.USE/pith/osdep/hostname.c
+*** alpine-2.00/pith/osdep/hostname.c 2006-12-11 10:06:32.000000000 -0800
+--- alpine-2.00.I.USE/pith/osdep/hostname.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 47,53 ****
+ {
+ #if HAVE_GETHOSTNAME
+
+! return(gethostname(hostname, size));
+
+ #elif HAVE_UNAME
+
+--- 47,57 ----
+ {
+ #if HAVE_GETHOSTNAME
+
+! if(gethostname(hostname, size)) return -1;
+! /* sanity check of hostname string */
+! for (*dn = hname; (*dn > 0x20) && (*dn < 0x7f); ++dn);
+! if (*dn) strcpy (hostname,"unknown");
+! return 0;
+
+ #elif HAVE_UNAME
+
+diff -rc alpine-2.00/pith/pattern.c alpine-2.00.I.USE/pith/pattern.c
+*** alpine-2.00/pith/pattern.c 2008-07-14 11:01:54.000000000 -0700
+--- alpine-2.00.I.USE/pith/pattern.c 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 1755,1761 ****
+ SortOrder def_sort;
+ int def_sort_rev;
+
+! if(decode_sort(p, &def_sort, &def_sort_rev) != -1){
+ action->sort_is_set = 1;
+ action->sortorder = def_sort;
+ action->revsort = (def_sort_rev ? 1 : 0);
+--- 1755,1761 ----
+ SortOrder def_sort;
+ int def_sort_rev;
+
+! if(decode_sort(p, &def_sort, &def_sort_rev, 0) != -1){
+ action->sort_is_set = 1;
+ action->sortorder = def_sort;
+ action->revsort = (def_sort_rev ? 1 : 0);
+***************
+*** 5482,5487 ****
+--- 5482,5496 ----
+ break;
+
+ case '#':
++ #ifndef _WINDOWS
++ if(!struncmp(patfolder, "#md/", 4)
++ || !struncmp(patfolder, "#mc/", 4)){
++ maildir_file_path(patfolder, tmp1);
++ if(!strcmp(patfolder, stream->mailbox))
++ match++;
++ break;
++ }
++ #endif
+ if(!strcmp(patfolder, stream->mailbox))
+ match++;
+
+***************
+*** 7894,7900 ****
+ int we_cancel = 0, width;
+ CONTEXT_S *save_context = NULL;
+ char buf[MAX_SCREEN_COLS+1], sbuf[MAX_SCREEN_COLS+1];
+! char *save_ref = NULL;
+ #define FILTMSG_MAX 30
+
+ if(!stream)
+--- 7903,7909 ----
+ int we_cancel = 0, width;
+ CONTEXT_S *save_context = NULL;
+ char buf[MAX_SCREEN_COLS+1], sbuf[MAX_SCREEN_COLS+1];
+! char *save_ref = NULL, *save_dstfldr = NULL, *save_dstfldr2 = NULL;
+ #define FILTMSG_MAX 30
+
+ if(!stream)
+***************
+*** 7928,7933 ****
+--- 7937,7952 ----
+ if(F_OFF(F_QUELL_FILTER_MSGS, ps_global))
+ we_cancel = busy_cue(buf, NULL, 0);
+
++ #ifndef _WINDOWS
++ if(!struncmp(dstfldr, "#md/", 4) || !struncmp(dstfldr, "#mc/", 4)){
++ char tmp1[MAILTMPLEN];
++ maildir_file_path(dstfldr, tmp1);
++ save_dstfldr2 = dstfldr;
++ save_dstfldr = cpystr(tmp1);
++ dstfldr = save_dstfldr;
++ }
++ #endif
++
+ if(!is_absolute_path(dstfldr)
+ && !(save_context = default_save_context(ps_global->context_list)))
+ save_context = ps_global->context_list;
+***************
+*** 7991,7996 ****
+--- 8010,8020 ----
+ if(we_cancel)
+ cancel_busy_cue(buf[0] ? 0 : -1);
+
++ if(save_dstfldr){
++ fs_give((void **)&save_dstfldr);
++ dstfldr = save_dstfldr2;
++ }
++
+ return(buf[0] != '\0');
+ }
+
+diff -rc alpine-2.00/pith/pineelt.h alpine-2.00.I.USE/pith/pineelt.h
+*** alpine-2.00/pith/pineelt.h 2008-07-09 22:01:13.000000000 -0700
+--- alpine-2.00.I.USE/pith/pineelt.h 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 40,45 ****
+--- 40,47 ----
+ PINETHRD_S *pthrd;
+ PARTEX_S *exceptions;
+ ICE_S *ice;
++ char *firsttext;
++ char *firsttextraw;
+ /* per-message pine state bits */
+ unsigned int hidden:1;
+ unsigned int excluded:1;
+diff -rc alpine-2.00/pith/pine.hlp alpine-2.00.I.USE/pith/pine.hlp
+*** alpine-2.00/pith/pine.hlp 2008-08-22 17:07:05.000000000 -0700
+--- alpine-2.00.I.USE/pith/pine.hlp 2011-02-07 20:33:48.000000000 -0800
+***************
+*** 88,93 ****
+--- 88,94 ----
+ ALPINE_VERSION
+ ALPINE_REVISION
+ ALPINE_COMPILE_DATE
++ ALPINE_PATCHLEVEL
+ ALPINE_TODAYS_DATE
+ C_CLIENT_VERSION
+ _LOCAL_FULLNAME_
+***************
+*** 158,163 ****
+--- 159,172 ----
+ </DIV>
+
+ <P>
++ This version was modified from its original source code. More information
++ about some of the patches applied to this version can be found <A HREF="h_patches">here</A>.
++ <!--chtml if pinemode="running"-->
++ The patch level of this version, including creation date of the patch is:
++ <!--#echo var=ALPINE_PATCHLEVEL-->.
++ <!--chtml endif-->
++
++ <P>
+ Alpine is an &quot;Alternatively Licensed Program for Internet
+ News and Email&quot; produced by the University of Washington.
+ It is intended to be an easy-to-use program for
+***************
+*** 919,924 ****
+--- 928,1016 ----
+ &lt;End of Configuration Notes&gt;
+ </BODY>
+ </HTML>
++ ====== h_patches ======
++ <html>
++ <head>
++ <TITLE>Information on patches added to this release</TITLE>
++ </head>
++ <body>
++ <H1>Information on patches added to this release</H1>
++ <P>
++ This version of Alpine has been modified by including patches from
++ <A HREF="http://staff.washington.edu/chappa/alpine/">
++ http://staff.washington.edu/chappa/alpine/</A>. These patches include
++ new features and bug fixes. More complete information on each patch
++ included in this version can be found in the web.
++
++ <P>If you have any problems with this release of Alpine, please contact
++ Eduardo Chappa <A HREF="mailto:chappa@washington.edu">&lt;chappa@washington.edu&gt;</A>.
++
++ <P>The list of patches included in this release are:
++ <P>New Features:
++
++ <UL>
++ <LI> Enhanced Fancy thread interface. <A HREF="http://staff.washington.edu/chappa/alpine/info/fancy.html">(more)</A>
++ <!--chtml if pinemode="os_windows"-->
++
++ <!--chtml else-->
++ <LI> Patch that gives support for the maildir driver in Alpine <A HREF="h_config_maildir">(more)</A>
++ <!--chtml endif-->
++ <LI> Rules patch, to make Alpine flexible. <A HREF="h_config_new_rules">(more)</A>
++ <LI> Send mail from the command Line. <A HREF="http://staff.washington.edu/chappa/alpine/info/outgoing.html">(more)</A>
++ <LI> Add a few more options when replying to a message <A HREF="h_config_alt_reply_menu">(more)</A>
++ <LI> Choose a role when composing a message from a mailto: link <A HREF="http://staff.washington.edu/chappa/alpine/info/composeurl.html">(more)</A>
++ <LI> Alpine justifies paragraphs with more than one level of indentation. <A HREF="h_compose_justify">(more)</A>
++ <LI> Patch to write accents and foreign characters <A HREF="http://staff.washington.edu/chappa/alpine/info/WrtAcc.html">(more)</A>
++ <LI> Change your From Header without any effort! <A HREF="http://staff.washington.edu/chappa/alpine/info/fromheader.html">(more)</A>
++ <LI> Tab checks folders on cycles <A HREF="h_config_circular_tab">(more)</A>
++ <LI> Patch for Pico to update its status line according to cursor movements <A HREF="http://staff.washington.edu/chappa/alpine/info/status.html">(more)</A>
++ <LI> Reuse your old search pattern to create a new one <A HREF="http://staff.washington.edu/chappa/alpine/info/insertpat.html">(more)</A>
++ <LI> Paint special text in the body of a message in any color. <A HREF="h_config_special_text_to_color">(more)</A>
++ <LI> Select messages by the content of an arbitrary header. <A HREF="http://staff.washington.edu/chappa/alpine/info/searchheader.html">(more)</A>
++ <LI> Remove incorrect passwords from memory <A HREF="http://staff.washington.edu/chappa/alpine/info/delpassword.html">(more)</A>
++ <LI> Get the quota report in an IMAP server <A HREF="http://staff.washington.edu/chappa/alpine/info/quota.html">(more)</A>
++ <LI> Remove text until the end of the file or a message <A HREF="http://staff.washington.edu/chappa/alpine/info/DelText.html">(more)</A>
++ <LI> Get the internal name of a help topic to use it with a x-alpine-help or x-pine-help URL scheme. <A HREF="http://staff.washington.edu/chappa/alpine/info/help.html">(more)</A>
++ <LI> Get the number of characters in a composed message <A HREF="http://staff.washington.edu/chappa/alpine/info/count.html">(more)</A>
++ <LI> Configure ignoring change in size of a message <A HREF="h_config_ignore_size">(more)</A>
++ <LI> Add one more token to a sending filter <A HREF="http://staff.washington.edu/chappa/alpine/info/addressfilter.html">(more)</A>
++ <LI> Make Alpine preserve To: and Cc: fields <A HREF="h_config_preserve_field">(more)</A>
++ <LI> Allow non utf-8 piped input in Alpine <A HREF="http://staff.washington.edu/chappa/alpine/info/noutf8.html">(more)</A>
++ <LI> Allow errors in base64 encoding <A HREF="http://staff.washington.edu/chappa/alpine/info/base64errors.html">(more)</A>
++ <LI> Get the name of the slow server <A HREF="http://staff.washington.edu/chappa/alpine/info/streaminfo.html">(more)</A>
++ <LI> Color the text in the folder list screen <A HREF="http://staff.washington.edu/chappa/alpine/info/colorfolder.html">(more)</A>
++ <LI> Color text in the index screen <A HREF="http://staff.washington.edu/chappa/alpine/info/tokencolor.html">(more)</A>
++ <LI> Avoid clearing the screen when executing a display filter <A HREF="http://staff.washington.edu/chappa/alpine/info/silenttoken.html">(more)</A>
++ <LI> Cache OPENINGTEXT information <A HREF="http://staff.washington.edu/chappa/alpine/info/cachefirsttext.html">(more)</A>
++ <LI> Recognize multiline URLs <A HREF="http://staff.washington.edu/chappa/alpine/info/longurl.html">(more)</A>
++ <LI> Recognize the nametemplate token in a mailcap file <A HREF="http://staff.washington.edu/chappa/alpine/info/nametemplate.html">(more)</A>
++ <LI> Create new threads even when replying to a message <A HREF="http://staff.washington.edu/chappa/alpine/info/newthread.html">(more)</A>
++ </UL>
++
++ <P>Bug Fixes:
++
++ <UL>
++ <LI> Fix a bug that makes Alpine not to give a warning if the Newsgroup header is present <A HREF="http://staff.washington.edu/chappa/alpine/info/unverified.html">(more)</A>
++ <LI> Fix a bug in Pico which makes it not update the screen <A HREF="http://staff.washington.edu/chappa/alpine/info/replacebug.html">(more)</A>
++ <LI> Fix a bug in Pico and Pilot that makes them crash for bad locale information <A HREF="http://staff.washington.edu/chappa/alpine/info/nlinfobug.html">(more)</A>
++ <LI> Fix a bug in Alpine that makes it not to set a flag in a filtered message <A HREF="http://staff.washington.edu/chappa/alpine/info/filterflagbug.html">(more)</A>
++ <LI> Fix a bug that makes Alpine crash when suspending it <A HREF="http://staff.washington.edu/chappa/alpine/info/streamlock.html">(more)</A>
++ <LI> Fix a bug that makes Alpine crash when opening a unix type folder <A HREF="http://staff.washington.edu/chappa/alpine/info/unixnullbug.html">(more)</A>
++ <LI> Force update of the index screen after adding an address to the addressbook <A HREF="http://staff.washington.edu/chappa/alpine/info/updateindexcolors.html">(more)</A>
++ <LI> Fix a bug that makes Alpine ignore the week day of a preftime token <A HREF="http://staff.washington.edu/chappa/alpine/info/preftimebug.html">(more)</A>
++ <LI> Fix the type of a .docx document <A HREF="http://staff.washington.edu/chappa/alpine/info/docxmimetype.html">(more)</A>
++ <LI> Parse environment variables correctly <A HREF="http://staff.washington.edu/chappa/alpine/info/envvar.html">(more)</A>
++ <LI> Do not reopen a folder that is meant to be closed <A HREF="http://staff.washington.edu/chappa/alpine/info/closebug.html">(more)</A>
++ <LI> Fix a bug that makes Alpine crash when the screen is resized <A HREF="http://staff.washington.edu/chappa/alpine/info/resizeldap.html">(more)</A>
++ <LI> Fix a bug in the threading algorithm <A HREF="http://staff.washington.edu/chappa/alpine/info/threadbug.html">(more)</A>
++ <LI> Fix a memory leak in Alpine <A HREF="http://staff.washington.edu/chappa/alpine/info/composerleak.html">(more)</A>
++ <LI> Fix a bug that sends Alpine in an infinite loop <A HREF="http://staff.washington.edu/chappa/alpine/info/scrolltool.html">(more)</A>
++ <LI> Fix a bug that makes Alpine not give a correct new mail message <A HREF="http://staff.washington.edu/chappa/alpine/info/newmailmsg.html">(more)</A>
++ <LI> Fix a bug that makes Alpine not show a login prompt <A HREF="http://staff.washington.edu/chappa/alpine/info/loginbug.html">(more)</A>
++ <LI> Patch by Mark Crispin, which fixes a bug which makes Alpine not generate correct headers for servers that return UTF-8 names. <A HREF="http://staff.washington.edu/chappa/alpine/patches/others.html#markhostbug-2.00">(more)</A>
++ </UL>
++ </body>
++ </html>
+ ====== h_news_legal ======
+ <html>
+ <head>
+***************
+*** 3035,3043 ****
+--- 3127,3137 ----
+ <li><a href="h_config_alt_role_menu">FEATURE: <!--#echo var="FEAT_alternate-role-menu"--></a>
+ <li><a href="h_config_force_low_speed">FEATURE: <!--#echo var="FEAT_assume-slow-link"--></a>
+ <li><a href="h_config_auto_read_msgs">FEATURE: <!--#echo var="FEAT_auto-move-read-msgs"--></a>
++ <li><a href="h_config_auto_read_msgs_rules">FEATURE: <!--#echo var="FEAT_auto-move-read-msgs-using-rules"--></a>
+ <li><a href="h_config_auto_open_unread">FEATURE: <!--#echo var="FEAT_auto-open-next-unread"--></a>
+ <li><a href="h_config_auto_unselect">FEATURE: <!--#echo var="FEAT_auto-unselect-after-apply"--></a>
+ <li><a href="h_config_auto_unzoom">FEATURE: <!--#echo var="FEAT_auto-unzoom-after-apply"--></a>
++ <li><a href="h_config_circular_tab">FEATURE: <!--#echo var="FEAT_enable-circular-tab"--></a>
+ <li><a href="h_config_auto_zoom">FEATURE: <!--#echo var="FEAT_auto-zoom-after-select"--></a>
+ <li><a href="h_config_use_boring_spinner">FEATURE: <!--#echo var="FEAT_busy-cue-spinner-only"--></a>
+ <li><a href="h_config_check_mail_onquit">FEATURE: <!--#echo var="FEAT_check-newmail-when-quitting"--></a>
+***************
+*** 3120,3125 ****
+--- 3214,3220 ----
+ <li><a href="h_config_prefix_editing">FEATURE: <!--#echo var="FEAT_enable-reply-indent-string-editing"--></a>
+ <li><a href="h_config_enable_search_and_repl">FEATURE: <!--#echo var="FEAT_enable-search-and-replace"--></a>
+ <li><a href="h_config_sigdashes">FEATURE: <!--#echo var="FEAT_enable-sigdashes"--></a>
++ <li><a href="h_config_new_thread_blank_subject">FEATURE: <!--#echo var="FEAT_new-thread-on-blank-subject"--></a>
+ <li><a href="h_config_can_suspend">FEATURE: <!--#echo var="FEAT_enable-suspend"--></a>
+ <li><a href="h_config_enable_tab_complete">FEATURE: <!--#echo var="FEAT_enable-tab-completion"--></a>
+ <li><a href="h_config_enable_take_export">FEATURE: <!--#echo var="FEAT_enable-take-export"--></a>
+***************
+*** 3136,3142 ****
+--- 3231,3239 ----
+ <li><a href="h_config_full_auto_expunge">FEATURE: <!--#echo var="FEAT_expunge-without-confirm-everywhere"--></a>
+ <li><a href="h_config_no_fcc_attach">FEATURE: <!--#echo var="FEAT_fcc-without-attachments"--></a>
+ <li><a href="h_config_force_arrow">FEATURE: <!--#echo var="FEAT_force-arrow-cursor"--></a>
++ <li><a href="h_config_ignore_size">FEATURE: <!--#echo var="FEAT_ignore-size-changes"--></a>
+ <li><a href="h_config_forward_as_attachment">FEATURE: <!--#echo var="FEAT_forward-as-attachment"--></a>
++ <li><a href="h_config_preserve_field">FEATURE: <!--#echo var="FEAT_preserve-original-fields"--></a>
+ <li><a href="h_config_quell_empty_dirs">FEATURE: <!--#echo var="FEAT_quell-empty-directories"--></a>
+ <li><a href="h_config_hide_nntp_path">FEATURE: <!--#echo var="FEAT_hide-nntp-path"--></a>
+ <li><a href="h_config_attach_in_reply">FEATURE: <!--#echo var="FEAT_include-attachments-in-reply"--></a>
+***************
+*** 3402,3407 ****
+--- 3499,3505 ----
+ <li><a href="h_config_print_cat">OPTION: <!--#echo var="VAR_personal-print-category"--></a>
+ <li><a href="h_config_print_command">OPTION: <!--#echo var="VAR_personal-print-command"--></a>
+ <li><a href="h_config_post_char_set">OPTION: <!--#echo var="VAR_posting-character-set"--></a>
++ <li><a href="h_config_special_text_to_color">OPTION: <!--#echo var="VAR_h_config_special_text_to_color"--></a>
+ <li><a href="h_config_postponed_folder">OPTION: <!--#echo var="VAR_postponed-folder"--></a>
+ <li><a href="h_config_print_font_char_set">OPTION: Print-Font-Char-Set</a>
+ <li><a href="h_config_print_font_name">OPTION: Print-Font-Name</a>
+***************
+*** 3430,3438 ****
+--- 3528,3538 ----
+ <li><a href="h_config_sending_filter">OPTION: <!--#echo var="VAR_sending-filters"--></a>
+ <li><a href="h_config_sendmail_path">OPTION: <!--#echo var="VAR_sendmail-path"--></a>
+ <li><a href="h_config_signature_color">OPTION: Signature Color</a>
++ <li><a href="h_config_special_text_color">OPTION: Special Text Color</a>
+ <li><a href="h_config_signature_file">OPTION: <!--#echo var="VAR_signature-file"--></a>
+ <li><a href="h_config_smtp_server">OPTION: <!--#echo var="VAR_smtp-server"--></a>
+ <li><a href="h_config_sort_key">OPTION: <!--#echo var="VAR_sort-key"--></a>
++ <li><a href="h_config_thread_sort_key">OPTION: <!--#echo var="VAR_thread-sort-key"--></a>
+ <li><a href="h_config_speller">OPTION: <!--#echo var="VAR_speller"--></a>
+ <li><a href="h_config_sshcmd">OPTION: <!--#echo var="VAR_ssh-command"--></a>
+ <li><a href="h_config_ssh_open_timeo">OPTION: <!--#echo var="VAR_ssh-open-timeout"--></a>
+***************
+*** 4058,4063 ****
+--- 4158,4172 ----
+ key will Exit the Help system altogether.
+
+ <P>
++ The "N" command will tell you the internal name of the help text you are
++ reading each time, so that you can send this name in the text of a message
++ and create a direct link to that internal help using the x-pine-help URL
++ scheme. For example, the direct link to this item is
++ x-pine-help:h_special_help_nav. If you add this text to a message, then
++ a person using Pine to read such message would have a direct link to this
++ help text.
++
++ <P>
+ When you are finished reading this help text, you can press the
+ <!--chtml if pinemode="function_key"-->
+ F3 function
+***************
+*** 5316,5321 ****
+--- 5425,5583 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ======= h_thread_index_sort_arrival =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Arrival</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Arrival</H1>
++
++ The <EM>Arrival</EM> sort option arranges threads according to the last
++ time that a message was added to it. In this order the last thread
++ contains the most recent message in the folder.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_date =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Date</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Date</H1>
++
++ The <EM>Date</EM> sort option in the THREAD&nbsp;INDEX screen sorts
++ threads by the date in which messages were sent. The thread containing the
++ last message in this order is displayed last.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_subj =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Subject</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Subject</H1>
++
++ The <EM>Subject</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_ordsubj =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: OrderedSubject</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: OrderedSubject</H1>
++
++ The <EM>OrderedSubject</EM> sort option in the THREAD&nbsp;INDEX screen is
++ the same as sorting by <A HREF="h_thread_index_sort_subj">Subject</A>.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_thread =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Thread</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Thread</H1>
++
++ The <EM>Thread</EM> sort option in the THREAD&nbsp;INDEX screen sorts all
++ messages by the proposed algorithm by Crispin and Murchison. In this
++ method of sorting once threads have been isolated they are sorted by the
++ date of their parents, or if that is missing, the first message in that
++ thread.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_from =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: From</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: From</H1>
++
++ The <EM>From</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_size =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Size</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Size</H1>
++
++ The <EM>Size</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_score =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Score</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Score</H1>
++
++ The <EM>Score</EM> sort option means that threads are sorted according to
++ the maximum score of a message in that thread. A thread all of whose
++ messages contain a smaller score than a message in some other thread is
++ placed in an earlier place in the list of messages for that folder; that
++ is, threads with the highest scores appear at the bottom of the index
++ list.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_to =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: To</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: To</H1>
++
++ The <EM>To</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_cc =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Cc</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Cc</H1>
++
++ The <EM>Cc</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ======= h_index_cmd_whereis =======
+ <HTML>
+ <HEAD>
+***************
+*** 6503,6508 ****
+--- 6765,6810 ----
+ &quot;type the character ^&quot;.
+
+ <P>
++ This version of Alpine contains an enhanced algorithm for justification,
++ which allows you to justify text that contains more complicated quote
++ strings. This algorithm is based on pragmatics, rather than on a theory,
++ and seems to work well with most messages. Below you will find technical
++ information on how this algorithm works.
++
++ <P>
++ When justifying, Alpine goes through each line of the text and tries to
++ determine for each line what the quote string of that line is. The quote
++ string you provided is always recognized. Among other characters
++ recognized is &quot;&gt;&quot;.
++
++ <P>
++ Some other constructions of quote strings are recognized only if they
++ appear enough in the text. For example &quot;Peter :&quot; is only
++ recognized if it appears in two consecutive lines.
++
++ <P>
++ Additionaly, Alpine recognizes indent-strings and justifies text in a
++ paragraph to the right of indent-string, padding with spaces if necessary.
++ An indent string is one which you use to delimit elements of a list. For
++ example, if you were to write a list of groceries, one may write:
++
++ <UL>
++ <LI> Fruit
++ <LI> Bread
++ <LI> Eggs
++ </UL>
++
++ <P>
++ In this case the character &quot;*&quot; is the indent-string. Aline
++ recognizes numbers (0, 1, 2.5, etc) also as indent-strings, and certain
++ combinations of spaces, periods, and parenthesis. In any case, numbers are
++ recognized <B>ONLY</B> if the line preceeding the given line is empty or
++ ends in one of the characters &quot;.&quot; or &quot;:&quot;.
++ In addition to the explanation of what constitutes a paragraph above, a
++ new paragraph is recognized when an indent-string is found in it (and
++ validated according to the above stated rules).
++
++ <P>
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
+***************
+*** 18069,18074 ****
+--- 18371,18377 ----
+ <A HREF="h_config_index_format">&quot;<!--#echo var="VAR_index-format"-->&quot;</A> option,
+ in the <A HREF="h_config_reply_intro">&quot;<!--#echo var="VAR_reply-leadin"-->&quot;</A> option,
+ in signature files,
++ in the <A HREF="h_config_reply_leadin_rules">&quot;new-rules&quot; option</A>,
+ in template files used in
+ <A HREF="h_rules_roles">&quot;roles&quot;</A>, and in the folder name
+ that is the target of a Filter Rule.
+***************
+*** 18081,18087 ****
+ <P>
+ <P>
+
+! <H1><EM>Tokens Available for all Cases (except Filter Rules)</EM></H1>
+
+ <DL>
+ <DT>SUBJECT</DT>
+--- 18384,18390 ----
+ <P>
+ <P>
+
+! <H1><EM>Tokens Available for all Cases (except Filter Rules or in some cases for new-rules)</EM></H1>
+
+ <DL>
+ <DT>SUBJECT</DT>
+***************
+*** 18114,18119 ****
+--- 18417,18431 ----
+ For example, &quot;mailbox@domain&quot;.
+ </DD>
+
++ <DT>ADDRESSTO</DT>
++ <DD>
++ This is similar to the &quot;TO&quot; token, only it is always the
++ email address of all people listed in the TO: field of the messages. Addresses
++ are separated by a blank space. Example, &quot;mailbox@domain&quot; when
++ the e-mail message contains only one person in the To: field, or
++ &quot;peter@flintstones.com president@world.com&quot;.
++ </DD>
++
+ <DT>MAILBOX</DT>
+ <DD>
+ This is the same as the &quot;ADDRESS&quot; except that the
+***************
+*** 18161,18166 ****
+--- 18473,18487 ----
+ message's &quot;Cc:&quot; header field.
+ </DD>
+
++ <DT>ADDRESSCC</DT>
++ <DD>
++ This is similar to the &quot;CC&quot; token, only it is always the
++ email address of all people listed in the Cc: field of the messages. Addresses
++ are separated by a blank space. Example: &quot;mailbox@domain&quot; when
++ the e-mail message contains only one person in the Cc: field, or
++ &quot;peter@flintstones.com president@world.com&quot;.
++ </DD>
++
+ <DT>RECIPS</DT>
+ <DD>
+ This token represents the personal names (or email addresses if the names
+***************
+*** 18169,18174 ****
+--- 18490,18503 ----
+ the message's &quot;Cc:&quot; header field.
+ </DD>
+
++ <DT>ADDRESSRECIPS</DT>
++ <DD>
++ This token represent the e-mail addresses of the people in the To: and
++ Cc: fields, exactly in that order separated by a space. It is almost obtained
++ by concatenating the ADDRESSTO and ADDRESSCC tokens.
++ </DD>
++
++
+ <DT>NEWSANDRECIPS</DT>
+ <DD>
+ This token represents the newsgroups from the
+***************
+*** 18650,18655 ****
+--- 18979,18992 ----
+ <P>
+ </DD>
+
++ <DT>SIZETHREAD</DT>
++ <DD>
++ This token represents the total size of the thread for a collapsed thread
++ or the size of the branch for an expanded thread. The field is omitted for
++ messages that are not top of threads nor branches and it defaults to
++ the SIZE token when your folders is not sorted by thread.
++ </DD>
++
+ <DT>SIZENARROW</DT>
+ <DD>
+ This token represents the total size, in bytes, of the message.
+***************
+*** 19265,19270 ****
+--- 19602,19679 ----
+ </DL>
+
+ <P>
++ <H1><EM>Tokens Available Only for New-Rules</EM></H1>
++
++ <DL>
++ <DT>FOLDER</DT>
++ <DD>
++ Name of the folder where the rule will be applied
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>COLLECTION</DT>
++ <DD>
++ Name of the collection list where the rule will be applied.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>ROLE</DT>
++ <DD>
++ Name of the Role used to reply a message.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>BCC</DT>
++ <DD>
++ Not implemented yet, but it will be implemented in future versions. It will
++ be used for <A HREF="h_config_compose_rules">compose</A>
++ <A HREF="h_config_reply_rules">reply</A>
++ <A HREF="h_config_forward_rules">forward</A>
++ rules.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>LCC</DT>
++ <DD>
++ This is the value of the Lcc: field at the moment that you start the composition.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>FORWARDFROM</DT>
++ <DD>
++ This corresponds to the personal name (or address if there's no personal
++ name) of the person who sent the message that you are forwarding.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>FORWARDADDRESS</DT>
++ <DD>
++ This is the address of the person that sent the message that you
++ are forwarding.
++ </DD>
++ </DL>
++
++
++
++
++ <DL>
++ <DT>FLAG</DT>
++ <DD>
++ A string containing the value of all the flags associated to a specific
++ message. The possible values of allowed flags are "*" for Important, "N"
++ for recent or new, "U" for unseen or unread, "R" for seen or read, "A" for
++ answered and "D" for deleted. See an example of its use in the
++ <A HREF="h_config_new_rules">new rules</A> explanation and example help.
++ </DD>
++ </DL>
++
++ <P>
+ <H1><EM>Token Available Only for Templates and Signatures</EM></H1>
+
+ <DL>
+***************
+*** 21253,21258 ****
+--- 21662,21763 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_maildir_location ======
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_maildir-location"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_maildir-location"--></H1>
++
++ <P>
++ This option should be used only if you have a Maildir folder which you
++ want to use as your INBOX. If this is not your case (or don't know what
++ this is), you can safely ignore this option.
++
++ <P>
++ This option overrides the default directory Pine uses to find the location of
++ your INBOX, in case this is in Maildir format. The default value of this
++ option is "Maildir", but in some systems, this directory could have been
++ renamed (e.g. to ".maildir"). If this is your case use this option to change
++ the default.
++
++ <P>
++ The value of this option is prefixed with the "~/" string to determine the
++ full path to your INBOX.
++
++ <P>
++ You should probably <A HREF="h_config_maildir">read</A> a few tips that
++ teach you how to configure your maildir for optimal performance. This
++ version also has <A HREF="h_config_courier_list">support</A> for the
++ Courier style file system when a maildir collection is accessed locally.
++
++ <P><UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL>
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_maildir =====
++ <HTML>
++ <HEAD>
++ <TITLE>Maildir Support</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>Maildir Support</H1>
++
++ This version of Alpine has been enhanced with Maildir support. This text is
++ intended to be a reference on its support.
++ <P>
++
++ A Maildir folder is a directory that contains three directories called
++ cur, tmp and new. A program that delivers mail (e.g. postfix) will put new
++ mail in the new directory. A program that reads mail will look for for old
++ messages in the cur directory, while it will look for new mail in the new
++ directory.
++ <P>
++
++ In order to use maildir support it is better to set your inbox-path to the
++ value &quot;#md/inbox&quot; (without quotes). This assumes that your mail
++ delivery agent is delivering new mail to ~/Maildir/new. If the directory
++ where new mail is being delivered is not called "Maildir", you can set the
++ name of the subdirectory of home where it is being delivered in the <A
++ HREF="h_config_maildir_location"><!--#echo var="VAR_maildir-location"--></A> configuration
++ variable. Most of the time you will not have to worry about the
++ <!--#echo var="VAR_maildirlocation"--> variable, because it will probably be set by your
++ administrator in the pine.conf configuration file.
++ <P>
++
++ One of the advantages of the Maildir support of this version of Alpine is
++ that you do not have to stop using folders in another styles (mbox, mbx,
++ etc.). This is desirable since the usage of a specific mail storage system
++ is a personal decision. Folders in the maildir format that are part of the
++ Mail collection will be recognized without any extra configuration of your
++ part. If your mail/ collection is located under the mail/ directory, then
++ creating a new maildir folder in this collection is done by pressing "A"
++ and entering the string "#driver.md/mail/newfolder". Observe that adding a
++ new folder as "newfolder" may not create such folder in maildir format.
++
++ <P>
++ If you would like to have all folders created in the maildir format by
++ default, you do so by adding a Maildir Collection. In order to convert
++ your current mail/ collection into a maildir collection, edit the
++ collection and change the path variable from &quot;mail/&quot; to
++ &quot;#md/mail&quot;. In a maildir collection folders of any other format
++ are ignored.
++
++ <P> Finally, This version also has
++ <A HREF="h_config_courier_list">support</A> for the Courier style file system
++ when a maildir collection is accessed locally.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_literal_sig =====
+ <HTML>
+ <HEAD>
+***************
+*** 22015,22020 ****
+--- 22520,22564 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_thread_sort_key =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_thread-sort-key--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_thread-sort-key--></TITLE></H1>
++
++ This option determines the order in which threads will be displayed. You
++ can choose from the options listed below. Each folder is sorted in one of
++ the sort orders displayed below first, then the thread containing the last
++ message of that sorted list is put at the end of the index. All messages
++ of that thread are &quot;removed&quot; from the sorted list and the
++ process is repeated with the remaining messages in that list.
++
++ <P>
++ <UL>
++ <LI> <A HREF="h_thread_index_sort_arrival">Arrival</A>
++ <LI> <A HREF="h_thread_index_sort_date">Date</A>
++ <!-- <LI> <A HREF="h_thread_index_sort_subj">Subject</A>
++ <LI> <A HREF="h_thread_index_sort_ordsubj">OrderedSubj</A>-->
++ <LI> <A HREF="h_thread_index_sort_thread">Thread</A>
++ <!-- <LI> <A HREF="h_thread_index_sort_from">From</A>
++ <LI> <A HREF="h_thread_index_sort_size">Size</A> -->
++ <LI> <A HREF="h_thread_index_sort_score">Score</A>
++ <!-- <LI> <A HREF="h_thread_index_sort_to">To</A>
++ <LI> <A HREF="h_thread_index_sort_cc">Cc</A>-->
++ </UL>
++
++ <P> Each type of sort may also be reversed. Normal default is by
++ &quot;Thread&quot;.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_other_startup =====
+ <HTML>
+ <HEAD>
+***************
+*** 22285,22290 ****
+--- 22829,23726 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_procid =====
++ <HTML>
++ <HEAD>
++ <TITLE>Token: PROCID</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>TOKEN: PROCID explained</H1>
++
++ <P>
++ The PROCID token is a way in which the user and the program can differentiate
++ between different parts of a program. It allows the user to tell the
++ program when to use a specific rule, and only use it at that specific
++ moment.
++
++ <P> The normal way in which this is done is by adding a new configuration
++ variable. The idea behind the PROCID token is that instead of adding a new
++ configuration variable (which means the user has to go through more
++ configuration variables just to tune the program to his liking), we reuse
++ an old variable and let the user look inside that variable for the desired
++ behavior, which is actually set by setting the PROCID token.
++
++ <P>
++ Consider the following examples for forward-rules:
++
++ <P>
++ _ROLE_ == {work} =&gt; _SUBJECT_ := _COPY_{[tag] _SUBJECT_}
++
++ <P>
++ and
++
++ <P>
++ _ROLE_ == {work} =&gt; _LCC_ := _TRIM_{_FORWARDFROM_ &lt;_FORWARDADDRESS_&gt;}
++
++ <P>
++ both are triggered by the same condition. Since both are configured in the
++ same variable, only one of them will be executed all the time (whichever
++ is first). Therefore in order to differentiate, we add a _PROCID_ token.
++ So, for example, the first example above will be executed only when we are
++ determining the subject. In this case, the following rule will accomplish
++ this task
++
++ <P>
++ _PROCID_ == {fwd-subject} && _ROLE_ == {work} =&gt; _SUBJECT_ := _COPY_{[tag] _SUBJECT_}
++
++ <P>
++ In this case, this rule will be tested fully only when we are determining
++ the subject line of a forwarded message, not otherwise.
++
++ <P>
++ It is wise to add the _PROCID_ token as the first condition in a rule, so
++ that other conditions will not be tested in a long list of rules.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_compose_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_compose-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_compose-rules"--></H1>
++
++ <P> At this time, this option is used to generate values for signature
++ files that is not possible to do with the use of
++ <A HREF="h_rules_roles">roles</A>.
++
++ <P> For example, you can have a rule like:<BR>
++ _TO_ >> {Peter Flinstones} => _SIGNATURE_{~/.petersignature}
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_forward_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_forward-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_forward-rules"--></H1>
++
++ <P> This option has several uses. This feature uses the PROCID function
++ to identify different features of forwarding. You can read more about PROCID
++ by following <A HREF="h_config_procid">this link</A>.
++
++ <P> If you want to edit the subject of a forwarded message, use the
++ PROCID <I>fwd-subject</I>. For example you could have a rule like
++
++ <P>
++ _ROLE_ == {admin} && _SUBJECT_ !&gt; {[tag] } =&gt; _COPY_{[tag] _SUBJECT_}
++
++ <P> Another way in which this option can be used, is to trim the values of
++ some fields. For this application the PROCID is <I>fwd-lcc</I>. For
++ example it can be used in the following way:
++
++ <P>
++ _ROLE_ == {work} => _LCC_ := _TRIM_{_FORWARDFROM_ &lt;_FORWARDADDRESS_&gt;}
++
++ <P> Other functions that can be used in this option are _EXEC_ and _REXTRIM_.
++
++ <P> You can also use the _EXEC_ function. The documentation for this function
++ is in the
++ <A HREF="h_config_resub_rules"><!--#echo var="VAR_reply-subject-rules"--></A>
++ help text.
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_index_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_index-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_index-rules"--></H1>
++
++ <P> This option is used to supersede the value of the option <A
++ HREF="h_config_index_format"><!--#echo var="VAR_index-format"--></A> for specific folders. In
++ this form you can have different index-formats for different folders. For
++ example an entry here may be:
++
++ <P>
++ _FOLDER_ == {INBOX} => _INDEX_{IMAPSTATUS DATE FROM(33%) SIZE SUBJECT(67%)}
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_pretty_command =====
++ <HTML>
++ <HEAD>
++ <TITLE>Pretty-Command Explained</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>Pretty Command Explained</H1>
++
++ <P> This text explains how to encode keys so that they will be recognized
++ by Alpine in the _PKEY_ token. Most direct keystrokes are recognized in the
++ same way. For example, the key ~ is recognized by the same character. The
++ issue is how control, or functions keys are recognized. The internal code
++ is most times easy to find out. If the key you want to use is not already
++ recognized by Alpine simply press it. Alpine will print its code. For example,
++ the return key is not recognized in this screen, so if you press it, you
++ will see the following message.
++
++ <P> [Command &quot;RETURN&quot; not defined for this screen. Use ? for help]
++
++ <P> from here you can guess that the code for the return command is
++ RETURN. You can try other commands, like Control-C, the TAB key, F4, etc.
++ to see their codes.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_key_macro_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_key-definition-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_key-definition-rules"--></H1>
++
++ <P> This option can be used to define macros, that is, to define a key that
++ when pressed executes a group of predetermined keystrokes. Since Alpine is
++ a menu driven program, sometimes the same key may have different meanings
++ in different screens, so a global redefinition of a key although possible
++ is not advisable.
++
++ <P> <B>Always use the _SCREEN_ token as defined below.</B>. You have been
++ warned!
++
++ <P> In each screen, every time you press a recognized key a command is
++ activated. In order to understand this feature, think of commands instead
++ of keystrokes. For example, you can think of the sort by thread command.
++ This command is associated to the keystrokes $ and h. You may want to
++ associate this command to a specific keystroke, like ~, so every time you
++ press the ~ key, Alpine understand the $ and h keystrokes, which activates
++ the sort by thread command.
++
++ <P> Therefore, in order to use this option you must think of three
++ components. The screen where you will use the macro, the keystroke you
++ want to use and the set of keystrokes used by Alpine to accomplish the task
++ you want to accomplish. We will talk about these three components in what
++ follows.
++
++ <P> First you must decide in which screen the macro will be used. This
++ feature is currently only available for the screen where your messages
++ are listed in index form (<A HREF="h_mail_index">MESSAGE INDEX</A>),
++ the screen where your message is displayed
++ (<A HREF="h_mail_view">MESSAGE TEXT</A>) and the screen where the list of
++ folders is displayed (<A HREF="h_folder_maint">FOLDER LIST</A>). The
++ internal names of these screens for this patch are &quot;index&quot;,
++ &quot;text&quot; and
++ &quot;folder&quot; respectively. Please note that the internal names are
++ all in lowercase are are case sensitive.
++
++ <P> In order to define the screen, you use the _SCREEN_ token, so for
++ example, you can write _SCREEN_ == {index}.
++
++ <P> Second you must think of which key you will use to activate the macro.
++ Here you can use any key of your choice. The token you use to designate a
++ key is the _PKEY_ token (PKEY stands for &quot;pressed key&quot;). For
++ example you could use _PKEY_ == {~}, to designate the &quot;~&quot;
++ character to activate the command. Some keystrokes (like control, or
++ function keys) are encoded in special ways. You should read the
++ <A HREF="h_config_pretty_command">full explanation</A> on how to find
++ out the encoding for each keystroke.
++
++ <P> Last, you must think of the list of keys you will use to accomplish
++ the task you want Alpine to perform. Say for example you want to have the
++ folder sorted by thread. That means you want Aline to execute the keys
++ &quot;$&quot; and &quot;h&quot;. You use the _COMMAND_ function to specify
++ this. The syntax in this case is _COMMAND_{$,h}.
++
++ <P> Observe that in the above example the different inputs are separated
++ by commas. This is the standard way in which the
++ <A HREF="h_config_init_cmd_list"><!--#echo var="VAR_initial-keystroke-list"--></A> command works from
++ the command line. Due to restrictions in the way Alpine works, a comma is a
++ special character, which when added to a configuration option like this
++ will cause the configuration to split into several lines in the
++ configuration screen. This has the effect of producing several
++ configuration options, all of which are incorrect. This is undesirable
++ because what you want is to have it all in one line. In order to force the
++ configuration into one line you must quote the comma. The best way to
++ accomplish this is by quoting the full definition of the rule. For
++ example.
++
++ <P>
++ &quot;_SCREEN_ == {index} && _PKEY_ == {~} => _COMMAND_{$,h}&quot;
++
++ <P> Another way to accomplish the same effect is by quoting the command and
++ not using quotes for the full command, nor commas to separate the
++ keystrokes in the command, for example
++
++ <P>
++ _SCREEN_ == {index} && _PKEY_ == {~} => _COMMAND_{&quot;$h&quot;}
++
++ <P> For more information on how to define the argument of the _COMMAND_
++ token see the help of
++ <A HREF="h_config_init_cmd_list"><!--#echo var="VAR_initial-keystroke-list"--></A>.
++
++ <P> Because the $ command can also be used as the first character in the
++ definition of an environemnt variable, no expansion of environment variables
++ is done when parsing this variable. The $ character does not need quoting
++ and quoting it will make Alpine fail to produce the correct result.
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_replace_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_replace-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_replace-rules"--></H1>
++
++ <P> This option is used to have Alpine print different values for specific
++ tokens in the <A HREF="h_config_index_format"><!--#echo var="VAR_index-format"--></A>. For example you
++ can replace strings like "To: newsgroup" by your name.
++
++ <P> Here are examples of possible rules:<BR>
++ _FOLDER_ != {sent-mail} && _NICK_ != {} => _FROM_ := _REPLACE_{_FROM_ (_NICK_)}
++
++ <P> or if you receive messages with tags that contain arbitrary numbers, and
++ you want them removed from the index (but not from the subject), use a rule
++ like the following<BR>
++ _FOLDER_ == {INBOX} => _SUBJECT_ := _REXTRIM_{&#92;[some-tag-here #[0-9].*&#92;]}
++
++ <P> You can also use this configuration option to remove specific strings of
++ the index display screen, so that you can trim unnecessary information in
++ your index, like the reply leadin string in the OPENINGTEXTNQ token of the index.
++ <BR>
++ _FOLDER_ == {mailing-list} => _OPENINGTEXTNQ_ := _REXTRIM_{On.*wrote: }
++
++ <P> or if you receive messages with tags that contain arbitrary numbers, and
++ you want them removed from the index (but not from the subject), use a rule
++ like the following<BR>
++
++ <P> You can also use the _EXEC_ function. The documentation for this function
++ is in the
++ <A HREF="h_config_resub_rules"><!--#echo var="VAR_reply-subject-rules"--></A>
++ help text.
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_reply_leadin_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_reply-leadin-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_reply-leadin-rules"--></H1>
++
++ <P> This option is used to have Alpine generate a different
++ <A HREF="h_config_reply_intro"><!--#echo var="VAR_reply-leadin"--></A> string dependent either on
++ the person you are replying to, or the folder where the message is being
++ replied is in, or both.
++
++ <P> Here there are examples of how this can be used. One can use the definition
++ below to post to newsgroups and the pine-info mailing list, say:
++ <P>
++ _FOLDER_ << {pine-info;_NEWS_} => _REPLY_{*** _FROM_ _ADDRESS_("_FROM_" "" "(_ADDRESS_) ")wrote in_NEWS_("" " the" "") _FOLDER_ _NEWS_("" "list " "")_SMARTDATE_("Today" "today" "on _LONGDATE_"):}
++
++ <P> Here there is an example that one can use to change the reply indent string
++ to reply people that speak spanish.
++ <P>
++ _FROM_{Condorito;Quico} => _REPLY_{*** _FROM_ (_ADDRESS_) escribi&oacute; _SMARTDATE_("Today" "hoy" "en _LONGDATE_"):}
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_resub_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_reply-subject-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_reply-subject-rules"--></H1>
++
++ <P> This option is used to have Alpine generate a different subject when
++ replying rather than the one Alpine would generate automatically.
++
++ <P> Here there are a couple of examples about how to use this
++ configuration option:
++
++ <P> In order to have messages with empty subject to be replied with the message
++ "your message" use the rule<BR>
++ <center>_SUBJECT_ == {} => _RESUB_{Re: your message}</center>
++
++ <P> If you want to trim some parts of the subject when you reply use the
++ rule<BR>
++ <center>_SUBJECT_ >> {[one];two} => _SUBJECT_ := _TRIM_{[;];two}</center>
++
++ <P>this rule removes the brackets "[" and "]" whenever the string "[one]"
++ appears in it, it also removes the word "two" from it.
++
++ <P>Another example where you may want to use this rule is when you
++ correspond with people that change the reply string from &quot;Re:&quot;
++ to &quot;AW:&quot; or &quot;Sv:&quot;. In this case a rule like<BR>
++ <center>_SUBJECT_ >> {Sv: ;AW: } => _SUBJECT_ := _TRIM_{Sv: ;AW: }</center>
++ <P>
++ would eliminate undesired strings in replies.
++
++ <P> Another interesting use of this option is the use of the _EXEC_ function.
++ This function takes as an argument a program or a script. This program
++ must take as the input a file, and write its output to that file. For example,
++ below is a sample of a script that removes the letter &quot;a&quot; of a file.
++
++ <PRE>
++ #!/bin/sh
++ sed 's/a//g' $1 > /tmp/mytest
++ mv /tmp/mytest $1
++ </PRE>
++
++ <P>
++ As you can see this script took &quot;$1&quot; as input file, the sed program
++ wrote its output to /tmp/mytest, and then the move program moved the file
++ /tmp/mytest to the input file &quot;$1&quot;. This is the kind of behavior
++ that your program is expected to have.
++
++ <P>
++ The content of the input file (&quot;$1&quot; above) is the value of a token
++ like _SUBJECT_. In order to indicate this, we use the notation
++
++ <P>
++ _SUBJECT_ := _EXEC_{/path/to/script}
++
++ <P> for the action. So for example
++
++ <P>
++ _FOLDER_ := {sent-mail} =&gt; _SUBJECT_ := _EXEC_{/path/to/script}
++
++ <P> is a valid rule.
++
++ <P> You can also use this configuration option to customize reply subjects
++ according to the sender of the message.
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_sort_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_sort-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_sort-rules"--></H1>
++
++ <P> This option is used to have Alpine sort different folders in different orders
++ and thus override the value already set in the
++ <A HREF="h_config_sort_key"><!--#echo var="VAR_sort-key"--></A> configuration option.
++
++ <P> Here's an example of the way it can be used. In this case all incoming
++ folders are mailing lists, except for INBOX, so we sort INBOX by arrival
++ (which is the default type of sort), but we want all the rest of mailing
++ lists and newsgroups to be sorted by thread.
++
++ <P>
++ _COLLECTION_ >> {Incoming-Folders;News} && _FOLDER_ != {INBOX} => _SORT_{tHread}
++
++ <P> Another example could be<BR>
++ _FOLDER_ == {Mailing List} => _SORT_{Reverse tHread}
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++
++ </BODY>
++ </HTML>
++ ====== h_config_save_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_save-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_save-rules"--></H1>
++
++ <P> This option is used to specify which folder should be used to save a
++ message depending either on the folder the message is in, who the message
++ is from, or text that the message contains in specific headers (Cc:,
++ Subject:, etc).
++
++ <P> If this option is set and the
++ <A HREF="h_config_auto_read_msgs"><!--#echo var="FEAT_auto-move-read-msgs"--></A> configuration
++ option is also enabled then these definitions will be used to move messages
++ from your INBOX when exiting Alpine.
++
++ <P>Here there are some examples<BR>
++ _FLAG_ >> {D} -> Trash<BR>
++ _FROM_ == {U2} -> Bono<BR>
++ _FOLDER_ == {comp.mail.pine} -> pine-stuff<BR>
++ _NICK_ != {} -> _NICK_/_NICK_<BR>
++ _DATEISO_ >> {02-10;02-11} -> archive-oct-nov-2002
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++
++ </BODY>
++ </HTML>
++ ====== h_config_reply_indent_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_reply-indent-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_reply-indent-rules"--></H1>
++
++ <P> This option is used to specify which reply-indent-string is to be used
++ when replying to an e-mail. If none of the rules are successful, the result in
++ the variable <a href="h_config_reply_indent_string"><!--#echo var="VAR_reply-indent-string"--></a>
++ is used.
++
++ <P> The associated function to this configuration option is called "RESTR" (for
++ REply STRing). Some examples of its use are:<BR>
++ _FROM_ == {Your Boss} => _RESTR_{"> "}<BR>
++ _FROM_ == {My Wife} => _RESTR_{":* "}<BR>
++ _FROM_ == {Perter Flinstone;Wilma Flinstone} => _RESTR_{"_INIT_ > "}<BR>
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++
++ </BODY>
++ </HTML>
++ ====== h_config_smtp_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_smtp-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_smtp-rules"--></H1>
++
++ <P> This option is used to specify which SMTP server should be used when
++ sending a message, if this rule is not defined, or the execution of the rule
++ results in no server selected, then Alpine will look for
++ the value from the role that is being used to compose the message. If no smtp
++ server is defined in that role or you are not using a role, then Alpine will get
++ the name of the server from the
++ <A HREF="h_config_smtp_server">&quot;<!--#echo var="VAR_smtp-server"-->&quot;</A> configuration
++ option according to the rules used in that variable.
++
++ <P> The function associated to this configuration option is _SMTP_, an example
++ of the use of this function is<BR>
++ _ADDRESSTO_ == {peter@bedrock.com} => _SMTP_{smtp.bedrock.com}
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++
++ </BODY>
++ </HTML>
++ ====== h_config_startup_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_startup-rules"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_startup-rules"--></H1>
++
++ <P> This option is used when a folder is being opened. You can use it to specify its <A
++ HREF="h_config_inc_startup"><!--#echo var="VAR_incoming-startup-rule"--></A> and override
++ Alpine's global value set for all folders.
++
++ <P> An example of the usage of this option is:<BR>
++ _FOLDER_ == {Lynx;pine-info;_NEWS_} => _STARTUP_{first-unseen}
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>&lt;End of help on this topic&gt;
++
++ </BODY>
++ </HTML>
++ ====== h_config_new_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: New Rules Explained</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: New Rules Explained</H1>
++
++ This is a quite powerful option. Here you can define rules that override
++ the values of any other option you have set in Alpine.
++
++ <P>
++ For example, you can set your folders to be sorted in a certain way when
++ you open them (say by Arrival). You may want, however, your newsgroups to
++ be sorted by thread. The set of &quot;rules&quot; options allows you to
++ configure this and many other options, including the index-format for
++ specific folders, the way the subject is displayed in the index screen or
++ the reply-leadin-string, to name a few.
++
++ <P>
++ Every rule has three parts: a condition, a separator and an action. The
++ action is what will happen if the condition of the rule is satisified.
++
++ <P>
++ Here is an example:
++
++ <P>
++ _FROM_ == {Fred Flinstone} =&gt; _SAVE_{Fred}
++
++ <P>
++ Here the separator is "=&gt;". Whatever is to the left of the separator
++ is the condition (that is _FROM_ == {Fred Flinstone}) and to the right is
++ the action (_SAVE_{Fred}). The condition means that the rule will be
++ applied only if the message that you are reading is from &quot;Fred
++ Flinstone&quot;, and the action will be that you will be offered to save
++ it in the folder &quot;Fred&quot;, whenever you press the letter
++ &quot;S&quot; to save a message.
++
++ <P>
++ The separator is always &quot;=&gt;&quot;, with one exception to be seen
++ later. But for the most part this will be the only one you will ever need.
++
++ <P>
++ Now let us see how to do it. There are 13 functions already defined for
++ you. These are: _EXEC_, _INDEX_, _REPLACE_, _REPLY_, _RESUB_, _SAVE_,
++ _SIGNATURE_, _SORT_, _STARTUP_, _TRIM_, _REXTRIM_, _THREADSTYLE and
++ _THREADINDEX_. The parameter of a function has to be enclosed between
++ &quot;{&quot; and &quot;}&quot;, so for example you can specify
++ _SAVE_{saved-messages} as a valid sentence.
++
++ <P>
++ Later in the document you will find examples. Here is a short
++ description of what each function does:
++
++ <P>
++ <UL>
++ <LI> _EXEC_ : This function takes as an argument a program. This program
++ gets as the input a file and must rewrite its output to that file, which
++ is then taken as the value to replace from the contents of that file. You
++ can use this function with
++ <A HREF="h_config_resub_rules"><!--#echo var="VAR_reply-subject-rules"--></A>,
++ <A HREF="h_config_replace_rules"><!--#echo var="VAR_replace-rules"--></A> and
++ <A HREF="h_config_forward_rules"><!--#echo var="VAR_forward-rules"--></A>.
++ See the help of those options for examples of how to use this function
++ and configure these rules.
++ <BR>&nbsp;<BR>
++ <LI> _INDEX_ : This function takes as an argument an index-format, and
++ makes that the index-format for the specified folder.
++ <BR>&nbsp;<BR>
++ <LI> _REPLACE_ : This function replaces the subject/from of the given e-mail by
++ another subject/from only when displaying the index.
++ <BR>&nbsp;<BR>
++ <LI> _REPLY_ : This function takes as an argument a definition of a
++ reply-leadin-string and makes this the reply-leading-string of the
++ specified folder or person.
++ <BR>&nbsp;<BR>
++ <LI> _RESTR_ : This function takes as an argument the value of the
++ reply-indent-string to be used to answer the message being replied to.
++ <BR>&nbsp;<BR>
++ <LI> _RESUB_ : This function replaces the subject of the given e-mail by
++ another subject only when replying to a message.
++ <BR>&nbsp;<BR>
++ <LI> _SAVE_ : The save function takes as an argument the name of a
++ possibly non existing folder, whenever you want to save a message, that
++ folder will be offered for you to save.
++ <BR>&nbsp;<BR>
++ <LI> _SIGNATURE_ : This function takes as an argument a signature file and
++ uses that file as the signature for the message you are about to
++ compose/reply/forward.
++ <BR>&nbsp;<BR>
++ <LI> _SMTP_ : This function takes as an argument the definition of a
++ SMTP server.
++ <BR>&nbsp;<BR>
++ <LI> _SORT_ : This function takes as an argument a Sort Style, and sorts a
++ specified folder in that sort order.
++ <BR>&nbsp;<BR>
++ <LI> _TRIM_ : This function takes as an argument a list of strings that
++ you want removed from another string. At this time this only works for
++ _FROM_ and _SUBJECT_.
++ <BR>&nbsp;<BR>
++ <LI> _REXTRIM_ : Same as _TRIM_ but its argument is one and
++ only one extended regular expression.
++ <BR>&nbsp;<BR>
++ <LI> _STARTUP_ : This function takes as an argument an
++ incoming-startup-rule, and open an specified folder using that rule.
++ <BR>&nbsp;<BR>
++ <LI> _THREADSTYLE_ : This function takes as an argument a
++ threading-display-style and uses it to display threads in a folder.
++ <BR>&nbsp;<BR>
++ <LI> _THREADINDEX_ : This function takes as an argument a
++ threading-index-style and uses it to display threads in a folder.
++ </UL>
++
++ <P>
++ You must me wondering how to define the person/folder over who to apply
++ the action. This is done in the condition. When you specify a rule, the
++ rule is only executed if the condition is satisfied. In another words for
++ the rule:
++
++ <P>
++ _FROM_ == {Fred Flinstone} =&gt; _SAVE_{Fred}
++
++ <P> it will only be applied if the from is &quot;Fred Flinstone&quot;. If
++ the From is &quot;Wilma Flinstone&quot; the rule will be skipped.
++
++ <P> In order to test a condition you can use the following tokens (in
++ alphabetical order): _ADDRESS_, _CC_, _FOLDER_, _FROM_,_NICK_, _ROLE,
++ _SENDER_, _SUBJECT_ and _TO_. The token will always be tested against what
++ it is between &quot;{&quot; and &quot;}&quot; in the condition, this part
++ of the condition is called the &quot;condition set&quot;. The definition
++ of each token can be found <A HREF="h_index_tokens">here</A>.
++
++ <P> A special testing token called _PROCID_ can be used to differentiate
++ inside a rule, between two rules that are triggered by the same condition.
++ A full explanation of the _PROCID_ token can be found in
++ <A HREF="h_config_procid">this link</A>.
++
++ <P> There are two more tokens related to the option
++ <A HREF="h_config_key_macro_rules">key-definition-rules</A>. Those tokens
++ are only specific to that option, and hence are not explained here.
++
++ <P> You can also test in different ways, you can use the following
++ &quot;test operands&quot;: &lt;&lt;, !&lt;, &gt;&gt;, !&gt;, == and !=.
++ All of them are two strings long. Here is the meaning of them:
++
++ <P>
++ <UL>
++ <LI> &lt;&lt; : It tests if the value of the token is contained in
++ the condition set. Here for example if the condition set were equal to
++ &quot;Freddy&quot;, then the condition: _NICK_ &lt;&lt; {Freddy}, would be true if
++ the value of _NICK_ were &quot;Fred&quot;, &quot;red&quot; or &quot;Freddy&quot;. You are just looking
++ for substrings here.
++ <LI> &gt;&gt; : It tests if the value of the token contains the value of
++ the condition set. Here for example if the condittion set were equal to
++ &quot;Fred&quot;, then the condition: _FROM_ &gt;&gt; {Fred}, would be true if
++ the value of _FROM_ were &quot;Fred Flinstone&quot; or &quot;Fred P. Flinstone&quot; or &quot;Freddy&quot;.
++ <LI> == : It tests if the value of the token is exactly equal to the value
++ of the set condition. For example _NICK_ == {Fred} will be false if the value
++ of _NICK_ is &quot;Freddy&quot; or &quot;red&quot;.
++ <LI> !&lt; : This is true only when &lt;&lt; is false and viceversa.
++ <LI> !&gt; : This is true only when &gt;&gt; is false and viceversa.
++ <LI> != : This is true only when == is false and viceversa.
++ </UL>
++
++ <P>
++ Now let us say that you want the same action to be applied to more than
++ one person or folder, say you want &quot;folder1&quot; and &quot;folder2&quot; to be sorted by
++ Ordered Subject upon entering. Then you can list them all of them in the
++ condition part separting them by a &quot;;&quot;. Here is the way to do it.
++
++ <P>
++ _FOLDER_ &lt;&lt; {folder1; folder2} =&gt; _SORT_{OrderedSubj}
++
++ <P>
++ Here is the first subtelty about these definitions. Notice that the
++ following rule:
++
++ <P>
++ _FOLDER_ == {folder1; folder2} =&gt; _SORT_{Reverse OrderedSubj}
++
++ <P> works only for &quot;folder1&quot; but not for &quot;folder2&quot;. This is because the
++ comparison of the name of the folder is done with whatever is in between
++ &quot;{&quot;, &quot;;&quot; or &quot;}&quot;, so in the above rule you would be testing <BR>
++ &quot;folder2&quot; == &quot; folder2&quot;. The extra space makes the difference.
++ The reason why the first rule does not fail is because
++ &quot;folder2&quot; &lt;&lt; &quot; folder2&quot; is actually
++ true. If something ever fails this may be something to look into.
++
++ <P>
++ Here are a few examples of what we have talked about before.
++
++ <P>
++ _NICK_ == {lisa;kika} =&gt; _SAVE_{_NICK_/_NICK_} <BR>
++ This means that if the nick is lisa, it will
++ save the message in the folder &quot;lisa/lisa&quot;, and if the nick
++ is &quot;kika&quot;, it will save the message in the folder &quot;kika/kika&quot;
++
++ <P>
++ _FOLDER_ == {Lynx} -&gt; lynx <BR>
++ This, is an abreviation of the following rule:<BR>
++ _FOLDER_ == {Lynx} =&gt; _SAVE_{lynx} <BR>
++ (note the change in separator from &quot;=&gt;&quot; to &quot;-&gt;&quot;). In the future
++ I will use that abreviation.
++
++ <P> _FOLDER_ &lt;&lt; {comp.mail.pine; pine-info; pine-alpha} -&gt; pine <BR>
++ Any message in the folders &quot;comp.mail.pine&quot;, &quot;pine-info&quot; or &quot;pine-alpha&quot;
++ will be saved to the folder &quot;pine&quot;.
++
++ <P> _FROM_ &lt;&lt; {Pine Master} -&gt; pine <BR>
++ Any message whose From field contains
++ &quot;Pine Master&quot; will be saved in the folder pine.
++
++ <P> _FOLDER_ &lt;&lt; {Lynx; pine-info; comp.mail.pine} =&gt;
++ _INDEX_{IMAPSTATUS MSGNO DATE FROMORTO(33%) SUBJECT(66%)} <BR> Use a
++ different index-format for the folders &quot;Lynx&quot;, &quot;pine-info&quot; and
++ &quot;comp.mail.pine&quot;, where the size is not present.
++
++ <P> _FOLDER_ == {Lynx;pine-info} =&gt; _REPLY_{*** _FROM_ (_ADDRESS_)
++ wrote in the _FOLDER_ list _SMARTDATE_(&quot;Today&quot; &quot;today&quot; &quot;on
++ _LONGDATE_&quot;):}<BR> If a message is in one of the incoming folders &quot;Lynx&quot;
++ or &quot;pine-info&quot;, create a reply-leadin-string that acknowledges that. Note
++ the absence of &quot;,&quot; in the function _SMARTDATE_. For example answering to a
++ message in the pine-info list would look like:
++
++ <P>
++ *** Steve Hubert (hubert@cac.washington.edu) wrote in the pine-info list today:
++
++ <P>
++ However replying for a message in the Lynx list would look:
++
++ <P>
++ *** mattack@area.com (mattack@area.com) wrote in the Lynx list today:
++
++ <P>
++ If you write in more than one language you can use this feature to create
++ Reply-leadin-strings in different languages.
++
++ <P> Note that at least for people you can create particular
++ reply-leadin-string using the role features, but it does not work as this
++ one does. This seems to be the right way to do it.
++
++ <P> _FOLDER_ &lt;&lt; {Lynx; comp.mail.pine; pine_info; pine-alpha} =&gt;
++ _SORT_{OrderedSubj}<BR> This means upon opening, sort the folders &quot;Lynx&quot;,
++ &quot;comp.mail.pine&quot;, etc in ordered subject. All the others use the default
++ sort order. You can not sort in reverse in this form. The possible
++ arguments of this function are listed in the definition of the
++ default-sort-rule (Arrival, scorE, siZe, etc).
++
++ <P> The last examples use the function _TRIM_ which has a special form.
++ This function can only be used in the index list.
++
++ <P> _FOLDER_ &lt;&lt; {Lynx} =&gt; _SUBJECT_ := _TRIM_{lynx-dev }<BR> In
++ the folder &quot;Lynx&quot; eliminate from the subject the string &quot;lynx-dev &quot; (with
++ the space at the end). For example a message whose subject is &quot;Re:
++ lynx-dev unvisited Visited Links&quot;, would be shown in the index with
++ subject: &quot;Re: unvisited Visited Links&quot;, making the subject shorter and
++ giving the same information.
++
++ <P> _FROM_ &gt;&gt; {Name (Comment)} =&gt; _FROM_ :=
++ _TRIM_{ (Comment)}<BR> Remove the part &quot; (Comment)&quot;
++ from the _FROM_, so when displaying in the index the real From &quot;Name&quot;
++ will appear.
++
++ <P> _SUBJECT_ == {} =&gt; _RESUB_{Re: your mail without subject}
++ If there is no subject in the message, use the subject &quot;Re: your mail
++ wiyhout subject&quot; as a subject for the reply message.
++
++ <P> You can add more complexity to your rules by checking more than one
++ conditions before a rule is executed. For example: Assume that you want to
++ answer every email that contains the string &quot;bug report&quot;, with the subject
++ &quot;Re: About your bug report&quot;, you could make
++
++ <P>
++ _SUBJECT_ == {bug report} =&gt; _RESUB_{Re: About your _SUBJECT_}
++
++ <P> The problem with this construction is that if the person emails you
++ back, then the next time you answer the message the subject will be: &quot;Re:
++ About your Re: About your bug report&quot;, so it grew. You may want to avoid
++ this growth by using the following rule:
++
++ <P>
++ _SUBJECT_ &gt;&gt; {bug report} && _SUBJECT_ !&gt; {Re: } =&gt; _RESUB_{Re: About your _SUBJECT_}<BR>
++
++ <P>
++ which will only add the string &quot;Re: About your&quot; only the first time the
++ message is replied.
++
++ <P>
++ Say your personal name is &quot;Fred Flinstones&quot;, and assume that you don't
++ like to see &quot;To: comp.mail.pine&quot; in every post you make to this newsgroup,
++ but instead would like to see it as everyone else sees it. <BR>
++ _FOLDER_ == {comp.mail.pine} && _FROM_ == {Fred Flinstones} => _FROM_ := _REPLACE_{_FROM_}
++
++ <P>
++ You can also list your index by nick, in the following way:<BR>
++ _NICK_ != {} => _FROM_ := _REPLACE_{_NICK_}
++
++ <P>
++ If you want to open the folder &quot;pine-info&quot; in the first non-read message
++ use the rule:<BR>
++ _FOLDER_ == {pine-info} => _STARTUP_{first-unseen}
++
++ <P>
++ If you want to move your deleted messages to a folder, called &quot;Trash&quot;, use
++ the following rule:<BR>
++ _FLAG_ >> {D} -> Trash
++
++ <P>
++ The reason why the above test is not &quot;_FLAG_ == {D}&quot; is because that would mean
++ that this is the only flag set in the message. It's better to test by containment in this case.
++
++ <P> If you want to use a specific signature when you are in a specific collection
++ use the following rule:<BR>
++ _COLLECTION_ == {Mail} => _SIGNATURE_{/full/path/to/.signature}
++
++ <P> Finally about the question of which rule will be executed. Only the
++ first rule that matches will be executed. It is important to notice though
++ that &quot;saving&quot; rules do not compete with &quot;sorting&quot; rules. So the first
++ &quot;saving&quot; rule that matches will be executed in the case of saving and so
++ on.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_char_set =====
+ <HTML>
+ <HEAD>
+***************
+*** 22592,22597 ****
+--- 24028,24070 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_special_text_to_color =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_special-text-color"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_special-text-color"--></H1>
++
++ Use this option to enter patterns (text or regular expressions) that
++ Alpine will highlight in the body of the text that is not part of a handle
++ (an internal or external link that Alpine paints in a different color).
++
++ <P>
++ Enter each pattern in a different line. Pine will internally merge these
++ patterns (by adding a "|" character), or you can add them all in one line
++ by separating them by a "|" character. There is only a <A
++ HREF="h_regex_text">set</A> of regular expressions that are matched.
++
++ <P>
++ Pine will use the colors defined in the
++ <A HREF="h_config_special_text_color">Special Text Color</A> variable.
++ to paint any match.
++
++ <P>
++ If the Special Text Color is not set, setting this variable will not
++ cause that special text to be indicated in any special way. It will look
++ like any normal text. You must set those colors in order to make Pine
++ paint the screen differently when it finds the patterns specified in this
++ variable.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_display_filters =====
+ <HTML>
+ <HEAD>
+***************
+*** 22713,22718 ****
+--- 24186,24198 ----
+ improve security. The number is unique to the current Alpine session
+ and is only generated once per session.
+ </DD>
++
++ <DT>_SILENT_</DT>
++ <DD>When the filter is executed, this token tells Alpine not to repaint
++ the screen while the command is being executed. This can be used with
++ filters that do not interact with the user, and therefore repainting
++ the screen is not necessary.
++ </DD>
+ </DL>
+
+ <P>
+***************
+*** 22749,22754 ****
+--- 24229,24240 ----
+ Command Modifying Tokens:
+
+ <DL>
++ <DT>_ADDRESS_</DT>
++ <DD>When the command is executed, this token is replaced
++ with the address of the person sending the message in the format
++ mailbox@host.
++ </DD>
++
+ <DT>_RECIPIENTS_</DT>
+ <DD>When the command is executed, this token is replaced
+ with the space delimited list of recipients of the
+***************
+*** 25861,25866 ****
+--- 27347,27422 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_thread_display_style_rule =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Threading-Display-Style-Rule</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Threading-Display-Style-Rule</H1>
++
++ This option is very similar to <A HREF="h_config_thread_disp_style">
++ <!--#echo var="VAR_threading-display-style"--></A>, but it is a rule which specifies the
++ display styles for a thread that you want displayed in a specific
++ folder or collection.
++ <P>
++ The token to be used in this function is _THREADSTYLE_. Here there is
++ an example of its use
++ <P>
++ _FOLDER_ == {pine-info} => _THREADSTYLE_{mutt-like}
++ <P>
++ The values that can be given for the _THREADSTYLE_ function are the
++ values of the threading-display-style function, which can be found
++ listed in the <A HREF="h_config_thread_disp_style">threading-display-style</A>
++ configuration option.
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_thread_index_style_rule =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Threading-Index-Style-Rule</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Threading-Index-Style-Rule</H1>
++
++ This option is very similar to <A HREF="h_config_thread_index_style">
++ <!--#echo var="VAR_threading-index-style"--></A>, but it is a rule which specifies the
++ index styles for a thread that you want displayed in a specific
++ folder or collection.
++ <P>
++ The token to be used in this function is _THREADINDEX_. Here there is
++ an example of its use
++ <P>
++ _FOLDER_ == {pine-info} => _THREADINDEX_{regular-index-with-expanded-threads}
++ <P>
++ The values that can be given for the _THREADINDEX_ function are the
++ values of the threading-index-display function, which can be found
++ listed in the <A HREF="h_config_thread_index_style"><!--#echo var="VAR_threading-index-style"--></A>
++ configuration option.
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Alpine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_pruning_rule =====
+ <HTML>
+ <HEAD>
+***************
+*** 27467,27472 ****
+--- 29023,29058 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_new_thread_blank_subject =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_new-thread-on-blank-subject"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_new-thread-on-blank-subject"--></H1>
++
++ When this feature is enabled (the default) Alpine will create a new thread
++ every time that the subject line becomes empty at any time during composition.
++
++ <P>
++ This behavior is particularly useful in case you are replying to a message.
++ Replying to a message causes the message to be in the same thread than the
++ original message that is being replied to. However, many authors want to create
++ a new message (in a different thread) while replying to a message, and they do
++ this by changing the full subject, by first deleting the original subject and
++ typing the new subject of the current message.
++
++ <P>
++ Enabling this feature causes that any time that the subject is deleted, the
++ message being composed will be considered the first message of a new thread.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_strip_sigdashes =====
+ <HTML>
+ <HEAD>
+***************
+*** 27517,27522 ****
+--- 29103,29144 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_preserve_field =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_preserve-original-fields"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_preserve-original-fields"--></H1>
++
++ When you reply to a message that has been sent to several recipients, some of
++ them may have been added in different parts of the headers. For example,
++ some of the recipients will be listed in the To: header, while others will
++ be listed in the Cc: header.
++ <P>
++ If this feature is disabled, the default behavior of Alpine will be used,
++ and that is, that almost all recipients of the message will be
++ listed in the Cc: field. However, if you enable this feature, then,
++ excepting you, recipients originally listed in the Cc: field will be
++ listed again in the Cc: field, and those listed in the To: field in the
++ original message will be listed in the To: field again. The person in the
++ From: field will be added to the To: field.
++ <P>
++ Note that this will cause some messages that you send in Alpine to look
++ different. In particular, the To: field of a message will not be put in the
++ Cc: field, as is normally done. In fact, most people expect this to happen.
++ If you find that this is a problem you should disable this feature. You can
++ still make Alpine have this behavior on a per message basis. In order to do
++ this, you will see a new option in the menu for the &quot;Reply to all
++ recipients?&quot; question. In this case, pressing &quot;p&quot; will make
++ Alpine toggle its question so you can preserve the To: and Cc: fields for that
++ message.
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_sub_lists =====
+ <HTML>
+ <HEAD>
+***************
+*** 27701,27706 ****
+--- 29323,29344 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_use_domain =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_return-path-uses-domain-name"--> </TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_return-path-uses-domain-name"--></H1>
++
++ If you enable this configuration option Pine will use your domain name and your
++ username in that domain name to construct your Return-Path header, if not Pine
++ will use the address that you have set in the From: field to construct it.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_use_sender_not_x =====
+ <HTML>
+ <HEAD>
+***************
+*** 28297,28302 ****
+--- 29935,30005 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_alt_reply_menu =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_alternate-reply-menu"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_alternate-reply-menu"--></H1>
++
++ This feature controls the menu that is displayed when Reply is selected.
++ If set, a list of options will be presented, with each option representing
++ the type of composition that could be used. This feature is most useful
++ for users who want to avoid being prompted with each option separately, or
++ would like to override some defaults set in your configuration for the
++ message that you are replying (e.g. you may have set the option to strip
++ signatures, but for the message you are answering you would like not to do
++ that)
++
++ <P>
++ The way this feature works is as follows. Initially you get the question
++ if you want to include the message, and in the menu you will see several
++ options, each option is accompanied by some text explaining what will
++ happen if you press the associated command. For example, if you read the
++ text &quot;S Strip Sig&quot;, it means that if you press the letter
++ &quot;S&quot; the signature will be stripped off the message you are
++ replying. Observer that the menu will change to
++ &quot;S No Strip&quot;, which means that if you press &quot;S&quot;, the
++ signature will not be stripped off from the message. Your choices are
++ activated when you press RETURN.
++
++ <P>
++ Another way to remember what Pine will do, is that what will be done is
++ exactly the opposite of what you read in the menu.
++
++ <P>
++ The possible options are:
++
++ <OL>
++ <LI> A: This determines if Pine will include or not the attachments sent to
++ you in the message that you are replying. By default Pine will use the value
++ of the configuration option
++ <A HREF="h_config_attach_in_reply"><!--#echo var="FEAT_include-attachments-in-reply"--></A>, but
++ you can use this option to override such behavior in a per message basis.
++
++ <LI> F: To decide if you want to send flowed text or not. This option appears
++ unless you have quelled sending flowed text.
++
++ <LI> H: This option determines if the headers of a message are to be
++ included in the body of the message that is being replied. By default Pine
++ will use the value of the configuration option
++ <A HREF="h_config_include_header"><!--#echo var="FEAT_include-header-in-reply"--></A>, but
++ you can use this option to override such behavior in a per message basis.
++
++ <LI> R: To set a role, if you do not want Pine to set one automatically for you
++ or would like to set one when you can not select any.
++
++ <LI> S: To strip the signature from a message, only available is the feature
++ <a href="h_config_sigdashes"><!--#echo var="FEAT_enable-sigdashes"--></a> or the
++ <a href="h_config_strip_sigdashes"><!--#echo var="FEAT_strip-from-sigdashes-on-reply"--></a> option are
++ enabled.
++
++ </OL>
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_del_from_dot =====
+ <HTML>
+ <HEAD>
+***************
+*** 28820,28825 ****
+--- 30523,30560 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_enable_long_url =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_enable-msg-view-long-url"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_enable-msg-view-long-url"--></H1>
++
++ This feature modifies the behavior of Alpine's MESSAGE TEXT screen. When this feature
++ is set alpine will attempt to recognize long urls (those that spread over several
++ lines in the text) for the HTTP protocol, even when they have not been enclosed between
++ delimiters &quot;&lt;&quot; and &quot;&gt;&quot;.
++
++ <P>The normal behavior in Alpine is that if a URL is preceeded by the &quot;&lt;&quot;
++ character and this URL was not finished before the end of the line, then a
++ continuation of the URL is searched in the following line(s). Normally, this type of
++ URLs will be ended by the &quot;&gt;&quot; character, and if it is not, there is a
++ possibility of including erroneous text into the URL.
++
++ <P>Enabling this feature will make Alpine search for a continuation of certain URLs in
++ lines following its location. This will be of great help most times, but in some cases
++ the algorithm will catch some text into the URL that is not part of the URL.
++
++ <P>If you find that Alpine failed to recognize correctly a URL simply edit the URL before
++ passing it to your browser.
++
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_enable_view_addresses =====
+ <HTML>
+ <HEAD>
+***************
+*** 29127,29132 ****
+--- 30862,30910 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_courier_list =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_courier-folder-list"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_courier-folder-list"--></H1>
++
++ In a maildir collection, a folder could be used as a directory to store
++ folders. In the Courier server if you create a folder, then a directory
++ with the same name is created. If you use this patch to access a
++ collection created by the Courier server, then the display of such
++ collection will look confusing. The best way to access a maildir
++ collection created by the Courier server is by using the &quot;#mc/&quot;
++ prefix instead of the &quot;#md/&quot; prefix. If you use this alternate
++ prefix, then this feature applies to you, otherwise you can safely ignore
++ the text that follows.
++ <P>
++ Depending on if you have enabled the option
++ <a href="h_config_separate_fold_dir_view"><!--#echo var="FEAT_separate-folder-and-directory-entries"--></a>
++ a folder may be listed as &quot;folder[.]&quot;, or as two entries in the
++ list by &quot;folder&quot; and &quot;folder.&quot;.
++ <P>
++ If this option is disabled, Pine will list local folders that are in Courier
++ style format, as &quot;folder&quot;, and those that are also directories as
++ &quot;folder[.]&quot;. This makes the default display cleaner.
++ <P>
++ If this feature is enabled then creating folders in a maildir collection
++ will create a directory with the same name. If this feature is disabled, then
++ a folder is considered a directory only if it contains subfolders, so you can
++ not create a directory with the same name as an exisiting folder unless
++ you create a subfolder of that folder first (e.g. if you have a folder
++ called &quot;foo&quot; simply add &quot;foo.bar&quot; directly. This will
++ create the directory &quot;foo&quot; and the subfolder &quot;bar&quot; of it).
++ <P>
++ Observe that this feature works only for maildir collections that are accessed
++ locally. If a collection is accessed remotely then this feature has no value,
++ as the report is created in a server, and Pine only reports what received
++ from the server in this case.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_verbose_post =====
+ <HTML>
+ <HEAD>
+***************
+*** 29281,29286 ****
+--- 31059,31087 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_auto_read_msgs_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: auto-move-read-msgs-using-rules</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: auto-move-read-msgs-using-rules</H1>
++ This feature controls an aspect of Alpine's behavior upon quitting. If set,
++ and the
++ <A HREF="h_config_read_message_folder">&quot;<!--#echo var="VAR_read-message-folder"-->&quot;</A>
++ option is also set, then Alpine will automatically transfer all read
++ messages to the designated folder using the rules that you have defined in
++ your
++ <A HREF="h_config_save_rules">&quot;<!--#echo var="VAR_save-rules"-->&quot;</A> and mark
++ them as deleted in the INBOX. Messages in the INBOX marked with an
++ &quot;N&quot; (meaning New, or unseen) are not affected.
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_auto_fcc_only =====
+ <HTML>
+ <HEAD>
+***************
+*** 29731,29736 ****
+--- 31532,31554 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_enhanced_thread =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_enhanced-fancy-thread-support"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_enhanced-fancy-thread-support"--></H1>
++
++ If this option is set certain commands in Pine will operate in loose
++ threads too. For example, the command ^D marks a thread deleted, but if
++ this feature is set, it will remove all threads that share the same missing
++ parent with this thread.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_news_cross_deletes =====
+ <HTML>
+ <HEAD>
+***************
+*** 30209,30214 ****
+--- 32027,32066 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_ignore_size =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_ignore-size-changes"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_ignore-size-changes"--></H1>
++
++ When you have an account residing in an IMAP server, Alpine gets the size of
++ each message from the server. However, when Alpine saves a message residing
++ in an IMAP server, Alpine computes the size of the message independently. If
++ these two numbers do not match for a message, Alpine asks you if you still
++ want to take the risk of saving the message, since data corruption or loss
++ of data could result of this save.
++
++ <P>
++ Sometimes the root of this problem is that the server is defective, and
++ there will not be loss of information when saving such message. Enabling
++ this feature will make Aline ignore such error and continue saving the
++ message. If you can determine that this is the case, enable this feature
++ so that the saving operation will succeed. An example of a defective server
++ is the Gmail IMAP server. Another example is some versions of the Exchange
++ server.
++
++ <P>
++ It is recommended that this feature be disabled most of the time and only
++ enabled when you find a server which you can determine that has the above
++ mentioned defect, but be disabled again after making this operation
++ succeed.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_force_low_speed =====
+ <HTML>
+ <HEAD>
+***************
+*** 30479,30484 ****
+--- 32331,32357 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_circular_tab =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: <!--#echo var="FEAT_enable-circular-tab"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: <!--#echo var="FEAT_enable-circular-tab"--></H1>
++
++ <P>
++ This Feature is like
++ <A HREF="h_config_auto_open_unread">&quot;<!--#echo var="FEAT_auto-open-next-unread"-->&quot;</A>,
++ in the sense that you can use TAB to browse through all of your Incoming
++ Folders checking for new mail. Once it gets to the last folder of the
++ collection it goes back to check again until it returns to the original
++ folder where it started.
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_auto_include_reply =====
+ <HTML>
+ <HEAD>
+***************
+*** 31142,31147 ****
+--- 33015,33113 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_folder_color =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Folder Color</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Folder Color</H1>
++
++ Sets the colors Alpine uses for coloring a folder in the FOLDER LIST
++ screen. By default, the Folder Color is the normal text color.
++
++ <P>
++ If you set a color for this feature, other than the normal color
++ (the default), or a color for
++ <A HREF="h_config_directory_color">Directory Color</A>, then directories
++ will be colored according to the color specified in the
++ <A HREF="h_config_directory_color">Directory Color</A> option. In this
++ case, the color will be the only indication that the colored name
++ refers to a directory. The normal behavior is that Alpine
++ indicates that a name refers to a directory by appending a
++ separator (like &quot;/&quot; or &quot;.&quot;) to the name of
++ the folder.
++
++ <P>
++ If a folder is a directory, then the folder name will be painted
++ according to the color defined by this variable, and a separator
++ indicator (like &quot;/&quot; or &quot;.&quot;) will be added
++ to the name. That
++ indicator will be painted according to the color defined in the
++ <A HREF="h_config_directory_color">Directory Color</A> option.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_directory_color =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Directory Color</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Directory Color</H1>
++
++ Sets the colors Alpine uses for coloring a directory in the FOLDER LIST
++ screen. By default, the Folder Color is the normal text color.
++ <P>
++ If you set a color for this feature, other than the normal color
++ (the default), or a color for
++ <A HREF="h_config_folder_color">Folder Color</A>, then folders
++ will be colored according to the color specified in the
++ <A HREF="h_config_folder_color">Folder Color</A> option. In this
++ case, the color will be the only indication that the colored name
++ refers to a directory. The normal behavior is that Alpine
++ indicates that a name refers to a directory by appending a
++ separator (like &quot;/&quot; or &quot;.&quot;) to the name of
++ the folder.
++ <P>
++ If a folder is a directory, then the folder name will be painted
++ according to the color defined by the option
++ <A HREF="h_config_folder_color">Folder Color</A>, and the separator
++ indicator (like &quot;/&quot; or &quot;.&quot;) will be added
++ after the name. That
++ indicator will be painted according to the color defined in this
++ option.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_folder_list_color =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Folder-List Color</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Folder-List Color</H1>
++
++ Sets the colors Alpine uses for coloring normal text in the FOLDER LIST
++ screen. By default, the Folder-List Color is the normal text color.
++ <P>
++ This text refers to the informative text that Alpine displays so you
++ can recognize each collection. The color of the content of each collection
++ is determined by the options <A HREF="h_config_folder_color">Folder Color</A>
++ and <A HREF="h_config_directory_color">Directory Color</A>.
++ <P>
++ Unlike the options
++ <A HREF="h_config_folder_color">Folder Color</A>
++ and <A HREF="h_config_directory_color">Directory Color</A>, configuring
++ this option does not affect the way that it tradinionally reports folders,
++ directories and folders that are directories.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_incunseen_color =====
+ <HTML>
+ <HEAD>
+***************
+*** 31197,31202 ****
+--- 33163,33192 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_special_text_color =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Special Text Color</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Special Text Color</H1>
++
++ Sets the color Pine uses for coloring any text in the body of the message
++ that is not part of a handle (and internal or external link that Pine
++ paints in a different color). By default, this variable is not defined,
++ which means that text that matches the pattern is not painted in any
++ particular way. This variable must be set in a special form if you
++ want text to be painted.
++
++ <P>
++ <A HREF="h_color_setup">Descriptions of the available commands</A>
++ <P>
++ Look <A HREF="h_edit_nav_cmds">here</A>
++ to see the available Editing and Navigation commands.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_prompt_color =====
+ <HTML>
+ <HEAD>
+***************
+*** 31464,31469 ****
+--- 33454,33488 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_indextoken_color =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: <!--#echo var="VAR_index-token-colors"--></TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: <!--#echo var="VAR_index-token-colors"--></H1>
++
++ This option allows you to set up the color in which any token, not specified by the
++ previous options, will be colored in the MESSAGE INDEX screen.
++ <P>
++ In order to use this option, you must press the &quot;I&quot; <B>IndxHdr</B> command, and add
++ a token that can be used in the index format.
++ The list of available tokens is <A HREF="h_index_tokens">here</A>.
++ <P>
++ If you fail to enter a valid token your entry will be ignored, and you will be asked to
++ enter a new one. Once you have entered a valid token, a line will be added to the
++ configuration screen that you can use to set up the colors in which that token will
++ be painted. This is done in the same way that you configure colors for other
++ variables.
++
++ <A HREF="h_color_setup">Descriptions of the available commands</A>
++ <P>
++ Look <A HREF="h_edit_nav_cmds">here</A>
++ to see the available Editing and Navigation commands.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_customhdr_pattern =====
+ <HTML>
+ <HEAD>
+***************
+*** 35075,35077 ****
+--- 37094,37099 ----
+ ========== h_select_by_smaller_size ==========
+ Enter a number or ^C to cancel. All messages less than this many characters
+ in size will be selected. Examples: 2176, 1.53K (1530), or 3M (3000000).
++ ========== h_preserve_field ==========
++ Use 'p' to toggle between preserving or not preserving the original To:
++ and Cc: fields of the message. Enter ^C to cancel message.
+diff -rc alpine-2.00/pith/reply.c alpine-2.00.I.USE/pith/reply.c
+*** alpine-2.00/pith/reply.c 2008-06-03 12:27:23.000000000 -0700
+--- alpine-2.00.I.USE/pith/reply.c 2011-02-07 20:33:44.000000000 -0800
+***************
+*** 45,50 ****
+--- 45,52 ----
+ #include "../pith/ablookup.h"
+ #include "../pith/mailcmd.h"
+ #include "../pith/margin.h"
++ #include "../pith/copyaddr.h"
++ #include "../pith/rules.h"
+
+
+ /*
+***************
+*** 372,391 ****
+ /* Put Reply-To or From in To. */
+ *to_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->to,
+ (ADDRESS *) NULL, saved_from, RCA_ALL);
+- /* and the rest in cc */
+ if(replytoall){
+! *cc_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->cc,
+ outgoing->to, saved_to, RCA_ALL);
+! while(*cc_tail) /* stay on last address */
+! cc_tail = &(*cc_tail)->next;
+
+! *cc_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->cc,
+ outgoing->to, saved_cc, RCA_ALL);
+! while(*cc_tail)
+! cc_tail = &(*cc_tail)->next;
+
+! *cc_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->cc,
+ outgoing->to, saved_resent, RCA_ALL);
+ }
+ }
+ else if(saved_to){
+--- 374,410 ----
+ /* Put Reply-To or From in To. */
+ *to_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->to,
+ (ADDRESS *) NULL, saved_from, RCA_ALL);
+ if(replytoall){
+! if(ps->preserve){
+! while(*to_tail)
+! to_tail = &(*to_tail)->next;
+!
+! *to_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->to,
+! (ADDRESS *) NULL, saved_to, RCA_ALL);
+!
+! while(*to_tail)
+! to_tail = &(*to_tail)->next;
+!
+! *to_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->cc,
+! outgoing->to, saved_resent, RCA_ALL);
+!
+! *cc_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->cc,
+! outgoing->to, saved_cc, RCA_ALL);
+! }
+! else{ /* and the rest in cc */
+! *cc_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->cc,
+ outgoing->to, saved_to, RCA_ALL);
+! while(*cc_tail) /* stay on last address */
+! cc_tail = &(*cc_tail)->next;
+
+! *cc_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->cc,
+ outgoing->to, saved_cc, RCA_ALL);
+! while(*cc_tail)
+! cc_tail = &(*cc_tail)->next;
+
+! *cc_tail = reply_cp_addr(ps, 0, NULL, NULL, outgoing->cc,
+ outgoing->to, saved_resent, RCA_ALL);
++ }
+ }
+ }
+ else if(saved_to){
+***************
+*** 796,803 ****
+ reply_quote_str(ENVELOPE *env)
+ {
+ char *prefix, *repl, *p, buf[MAX_PREFIX+1], pbf[MAX_SUBSTITUTION+1];
+
+! strncpy(buf, ps_global->VAR_REPLY_STRING, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+
+ /* set up the prefix to quote included text */
+--- 815,841 ----
+ reply_quote_str(ENVELOPE *env)
+ {
+ char *prefix, *repl, *p, buf[MAX_PREFIX+1], pbf[MAX_SUBSTITUTION+1];
++ char reply_string[MAX_PREFIX+1];
++
++ { RULE_RESULT *rule;
++ rule = get_result_rule(V_REPLY_INDENT_RULES, FOR_COMPOSE , env);
++ if (rule){
++ strncpy(reply_string,rule->result,sizeof(reply_string));
++ reply_string[sizeof(reply_string)-1] = '\0';
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ else
++ if ((ps_global->VAR_REPLY_STRING) && (ps_global->VAR_REPLY_STRING[0])){
++ strncpy(reply_string,ps_global->VAR_REPLY_STRING, sizeof(reply_string)-1);
++ reply_string[sizeof(reply_string)-1] = '\0';
++ }
++ else
++ strncpy(reply_string,"> ",sizeof("> "));
++ }
+
+! strncpy(buf, reply_string, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+
+ /* set up the prefix to quote included text */
+***************
+*** 849,858 ****
+ int
+ reply_quote_str_contains_tokens(void)
+ {
+! return(ps_global->VAR_REPLY_STRING && ps_global->VAR_REPLY_STRING[0] &&
+! (strstr(ps_global->VAR_REPLY_STRING, from_token) ||
+! strstr(ps_global->VAR_REPLY_STRING, nick_token) ||
+! strstr(ps_global->VAR_REPLY_STRING, init_token)));
+ }
+
+
+--- 887,915 ----
+ int
+ reply_quote_str_contains_tokens(void)
+ {
+! char *reply_string;
+!
+! reply_string = (char *) malloc( 80*sizeof(char));
+! { RULE_RESULT *rule;
+! rule = get_result_rule(V_REPLY_INDENT_RULES, FOR_COMPOSE, NULL);
+! if (rule){
+! reply_string = cpystr(rule->result);
+! if (rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! else
+! if ((ps_global->VAR_REPLY_STRING) && (ps_global->VAR_REPLY_STRING[0])){
+! strncpy(reply_string,ps_global->VAR_REPLY_STRING, sizeof(reply_string)-1);
+! reply_string[sizeof(reply_string)-1] = '\0';
+! }
+! else
+! reply_string = cpystr("> ");
+! }
+! return(reply_string && reply_string[0] &&
+! (strstr(reply_string, from_token) ||
+! strstr(reply_string, nick_token) ||
+! strstr(reply_string, init_token)));
+ }
+
+
+***************
+*** 954,960 ****
+ if(!orig_body
+ || orig_body->type == TYPETEXT
+ || reply_raw_body
+! || F_OFF(F_ATTACHMENTS_IN_REPLY, ps_global)){
+ char *charset = NULL;
+
+ /*------ Simple text-only message ----*/
+--- 1011,1017 ----
+ if(!orig_body
+ || orig_body->type == TYPETEXT
+ || reply_raw_body
+! || !ps_global->reply.attach){
+ char *charset = NULL;
+
+ /*------ Simple text-only message ----*/
+***************
+*** 962,968 ****
+ body->type = TYPETEXT;
+ body->contents.text.data = msgtext;
+ reply_delimiter(env, role, pc);
+! if(F_ON(F_INCLUDE_HEADER, ps_global))
+ reply_forward_header(stream, msgno, sect_prefix,
+ env, pc, prefix);
+
+--- 1019,1025 ----
+ body->type = TYPETEXT;
+ body->contents.text.data = msgtext;
+ reply_delimiter(env, role, pc);
+! if(ps_global->reply.inchdr)
+ reply_forward_header(stream, msgno, sect_prefix,
+ env, pc, prefix);
+
+***************
+*** 1020,1026 ****
+
+ if(reply_body_text(orig_body, &tmp_body)){
+ reply_delimiter(env, role, pc);
+! if(F_ON(F_INCLUDE_HEADER, ps_global))
+ reply_forward_header(stream, msgno, sect_prefix,
+ env, pc, prefix);
+
+--- 1077,1083 ----
+
+ if(reply_body_text(orig_body, &tmp_body)){
+ reply_delimiter(env, role, pc);
+! if(ps_global->reply.inchdr)
+ reply_forward_header(stream, msgno, sect_prefix,
+ env, pc, prefix);
+
+***************
+*** 1058,1064 ****
+ body->nested.part->body.subtype = cpystr("Plain");
+ }
+ reply_delimiter(env, role, pc);
+! if(F_ON(F_INCLUDE_HEADER, ps_global))
+ reply_forward_header(stream, msgno, sect_prefix,
+ env, pc, prefix);
+
+--- 1115,1121 ----
+ body->nested.part->body.subtype = cpystr("Plain");
+ }
+ reply_delimiter(env, role, pc);
+! if(ps_global->reply.inchdr)
+ reply_forward_header(stream, msgno, sect_prefix,
+ env, pc, prefix);
+
+***************
+*** 1081,1087 ****
+ int partnum;
+
+ reply_delimiter(env, role, pc);
+! if(F_ON(F_INCLUDE_HEADER, ps_global))
+ reply_forward_header(stream, msgno, sect_prefix,
+ env, pc, prefix);
+
+--- 1138,1144 ----
+ int partnum;
+
+ reply_delimiter(env, role, pc);
+! if(ps_global->reply.inchdr)
+ reply_forward_header(stream, msgno, sect_prefix,
+ env, pc, prefix);
+
+***************
+*** 1316,1321 ****
+--- 1373,1382 ----
+ buf[0] = '\0';
+
+ switch(type){
++ case iFfrom:
++ addr = env && env->sparep ? env->sparep : NULL;
++ break;
++
+ case iFrom:
+ addr = env ? env->from : NULL;
+ break;
+***************
+*** 1701,1721 ****
+
+ break;
+
+ case iFrom:
+ case iTo:
+ case iCc:
+ case iSender:
+ case iRecips:
+ case iInit:
+ get_addr_data(env, type, buf, maxlen);
+ break;
+
+! case iRoleNick:
+! if(role && role->nick){
+! strncpy(buf, role->nick, maxlen);
+! buf[maxlen] = '\0';
+! }
+! break;
+
+ case iNewLine:
+ if(maxlen >= strlen(NEWLINE)){
+--- 1762,1912 ----
+
+ break;
+
++ case iProcid:
++ if(ps_global->procid){
++ strncpy(buf, ps_global->procid, maxlen);
++ buf[maxlen] = '\0';
++ }
++ break;
++
++ case iRole:
++ if (ps_global->role){
++ strncpy(buf, ps_global->role, maxlen);
++ buf[maxlen] = '\0';
++ }
++ break;
++
++ case iRoleNick:
++ if(role && role->nick){
++ strncpy(buf, role->nick, maxlen);
++ buf[maxlen] = '\0';
++ }
++ break;
++
++ case iPkey:
++ if(ps_global->pressed_key){
++ strcpy(buf, ps_global->pressed_key);
++ buf[maxlen] = '\0';
++ }
++ break;
++
++ case iScreen:
++ if(ps_global->screen_name){
++ strncpy(buf, ps_global->screen_name, maxlen);
++ buf[maxlen] = '\0';
++ }
++ break;
++
++ case iFfrom:
+ case iFrom:
+ case iTo:
+ case iCc:
+ case iSender:
+ case iRecips:
+ case iInit:
++ if (env)
+ get_addr_data(env, type, buf, maxlen);
+ break;
+
+! case iFolder:
+! if(ps_global->cur_folder){
+! strncpy(buf,ps_global->cur_folder, maxlen);
+! buf[maxlen] = '\0';
+! }
+! break;
+!
+! case iCollection:
+! if(ps_global->context_current->nickname){
+! strncpy(buf,ps_global->context_current->nickname, maxlen);
+! buf[maxlen] = '\0';
+! }
+! break;
+!
+! case iFlag:
+! {MAILSTREAM *stream = find_open_stream();
+! MSGNO_S *msgmap = NULL;
+! long msgno;
+! MESSAGECACHE *mc;
+! strncpy(buf, "_FLAG_", maxlen); /* default value */
+! if (stream){
+! mn_init(&msgmap, stream->nmsgs);
+! msgno = mn_m2raw(msgmap, rules_cursor_pos(stream));
+! if (msgno > 0L) mc = stream ? mail_elt(stream, msgno) : NULL;
+! if (mc)
+! sprintf(buf,"%s%s%s%s",mc->flagged ? "*" : "",
+! mc->recent ? (mc->seen ? "R" : "N") : (mc->seen) ? "R" : "U",
+! mc->answered ? "A" : "",
+! mc->deleted ? "D" : "" );
+! mn_give(&msgmap);
+! }
+! buf[maxlen] = '\0';
+! }
+! break;
+!
+! case iNick:
+! {
+! ADDRESS *tmp_adr = NULL;
+! if (env){
+! tmp_adr = env->from ? copyaddr(env->from)
+! : env->sender ? copyaddr(env->sender) : NULL;
+! get_nickname_from_addr(tmp_adr,buf,maxlen);
+! mail_free_address(&tmp_adr);
+! }
+! }
+! break;
+!
+! case iAddressCc:
+! case iAddressRecip:
+! case iAddressTo:
+! case iFadd:
+! {
+! int plen = 0; /* partial length */
+! ADDRESS *sparep2 = (type == iAddressTo || type == iAddressRecip)
+! ? ((env && env->to)
+! ? copyaddrlist(env->to)
+! : NULL)
+! : (type == iAddressCc)
+! ? ((env && env->cc)
+! ? copyaddrlist(env->cc)
+! : NULL)
+! : ((env && env->sparep)
+! ? copyaddr((ADDRESS *)env->sparep)
+! : NULL);
+! ADDRESS *sparep;
+!
+! if (type == iAddressRecip){
+! ADDRESS *last_to = NULL;
+!
+! for(last_to = sparep2;last_to && last_to->next; last_to= last_to->next);
+!
+! /* Make the end of To list point to cc list */
+! if(last_to)
+! last_to->next = (env && env->cc ? copyaddrlist(env->cc) : NULL);
+!
+! }
+! sparep = sparep2;
+! for(; sparep ; sparep = sparep->next)
+! if(sparep && sparep->mailbox && sparep->mailbox[0] &&
+! (plen ? plen + 1 : plen) + strlen(sparep->mailbox) <= maxlen){
+! if (plen == 0)
+! strcpy(buf, sparep->mailbox);
+! else{
+! strcat(buf, " ");
+! strcat(buf, sparep->mailbox);
+! }
+! if(sparep->host &&
+! sparep->host[0] &&
+! sparep->host[0] != '.' &&
+! strlen(buf) + strlen(sparep->host) + 1 <= maxlen){
+! strcat(buf, "@");
+! strcat(buf, sparep->host);
+! }
+! plen = strlen(buf);
+! }
+! mail_free_address(&sparep2);
+! }
+!
+! break;
+
+ case iNewLine:
+ if(maxlen >= strlen(NEWLINE)){
+***************
+*** 1744,1749 ****
+--- 1935,1945 ----
+
+ break;
+
++ case iLcc: /* fake it, there are not enough spare pointers */
++ if (env && env->date)
++ sprintf(buf,"%s",env->date);
++ break;
++
+ case iNews:
+ case iCurNews:
+ get_news_data(env, type, buf, maxlen);
+***************
+*** 1793,1798 ****
+--- 1989,2002 ----
+
+ break;
+
++ case iOpeningText:
++ case iOpeningTextNQ:
++ if(env && env->sparep){
++ strncpy(buf, ((SPAREP_S *)env->sparep)->value, maxlen);
++ buf[maxlen] = '\0';
++ }
++ break;
++
+ case iSubject:
+ if(env && env->subject){
+ size_t n, len;
+***************
+*** 1851,1857 ****
+ if(!env)
+ return;
+
+! strncpy(buf, ps_global->VAR_REPLY_INTRO, MAX_DELIM);
+ buf[MAX_DELIM] = '\0';
+ /* preserve exact default behavior from before */
+ if(!strcmp(buf, DEFAULT_REPLY_INTRO)){
+--- 2055,2072 ----
+ if(!env)
+ return;
+
+! { RULE_RESULT *rule;
+! rule = get_result_rule(V_REPLY_LEADIN_RULES, FOR_REPLY_INTRO, env);
+! if(rule){
+! strncpy(buf, rule->result, MAX_DELIM);
+! if (rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! else
+! strncpy(buf, ps_global->VAR_REPLY_INTRO, MAX_DELIM);
+! }
+!
+ buf[MAX_DELIM] = '\0';
+ /* preserve exact default behavior from before */
+ if(!strcmp(buf, DEFAULT_REPLY_INTRO)){
+***************
+*** 2110,2115 ****
+--- 2325,2331 ----
+ {
+ size_t l;
+ char *p, buftmp[MAILTMPLEN];
++ RULE_RESULT *rule;
+
+ if(!env)
+ return(NULL);
+***************
+*** 2117,2125 ****
+ dprint((9, "checking subject: \"%s\"\n",
+ env->subject ? env->subject : "NULL"));
+
+! if(env->subject && env->subject[0]){ /* add (fwd)? */
+! snprintf(buftmp, sizeof(buftmp), "%s", env->subject);
+! buftmp[sizeof(buftmp)-1] = '\0';
+ /* decode any 8bit (copy to the temp buffer if decoding doesn't) */
+ if(rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf,
+ SIZEOF_20KBUF, buftmp) == (unsigned char *) buftmp)
+--- 2333,2352 ----
+ dprint((9, "checking subject: \"%s\"\n",
+ env->subject ? env->subject : "NULL"));
+
+! buftmp[0] = '\0';
+! ps_global->procid = cpystr("fwd-subject");
+! if (rule = get_result_rule(V_FORWARD_RULES,FOR_COMPOSE, env)){
+! sprintf(buftmp, "%.200s", rule->result);
+! if(rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! else if(env->subject)
+! sprintf(buftmp, "%.200s", env->subject);
+! buftmp[sizeof(buftmp)-1] = '\0';
+! fs_give((void **)&ps_global->procid);
+!
+! if(buftmp[0]){ /* add (fwd)? */
+ /* decode any 8bit (copy to the temp buffer if decoding doesn't) */
+ if(rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf,
+ SIZEOF_20KBUF, buftmp) == (unsigned char *) buftmp)
+***************
+*** 2620,2628 ****
+ * tied our hands, alter the prefix to continue flowed
+ * formatting...
+ */
+! if(flow_res)
+ wrapflags |= GFW_FLOW_RESULT;
+
+ filters[filtcnt].filter = gf_wrap;
+ /*
+ * The 80 will cause longer lines than what is likely
+--- 2847,2858 ----
+ * tied our hands, alter the prefix to continue flowed
+ * formatting...
+ */
+! if(flow_res && !ps_global->reply.no_send_flowed)
+ wrapflags |= GFW_FLOW_RESULT;
+
++ filters[filtcnt].filter = gf_quote_test;
++ filters[filtcnt++].data = gf_line_test_opt(select_quote, NULL);
++
+ filters[filtcnt].filter = gf_wrap;
+ /*
+ * The 80 will cause longer lines than what is likely
+***************
+*** 2656,2664 ****
+ * We also want to fold "> " quotes so we get the
+ * attributions correct.
+ */
+! if(flow_res && prefix && !strucmp(prefix, "> "))
+ *(prefix_p = prefix + 1) = '\0';
+!
+ if(!(wrapflags & GFW_FLOWED)
+ && flow_res){
+ filters[filtcnt].filter = gf_line_test;
+--- 2886,2894 ----
+ * We also want to fold "> " quotes so we get the
+ * attributions correct.
+ */
+! if(flow_res && !ps_global->reply.no_send_flowed && prefix && !strucmp(prefix, "> "))
+ *(prefix_p = prefix + 1) = '\0';
+! ps_global->reply.no_send_flowed = 0; /* reset for next call */
+ if(!(wrapflags & GFW_FLOWED)
+ && flow_res){
+ filters[filtcnt].filter = gf_line_test;
+***************
+*** 2691,2699 ****
+ }
+
+ if(prefix){
+! if(ps_global->full_header != 2
+! && (F_ON(F_ENABLE_SIGDASHES, ps_global)
+! || F_ON(F_ENABLE_STRIP_SIGDASHES, ps_global))){
+ dashdata = 0;
+ filters[filtcnt].filter = gf_line_test;
+ filters[filtcnt++].data = gf_line_test_opt(sigdash_strip, &dashdata);
+--- 2921,2927 ----
+ }
+
+ if(prefix){
+! if(ps_global->reply.strip){
+ dashdata = 0;
+ filters[filtcnt].filter = gf_line_test;
+ filters[filtcnt++].data = gf_line_test_opt(sigdash_strip, &dashdata);
+***************
+*** 2718,2724 ****
+ dq.do_color = 0;
+ dq.delete_all = 1;
+
+! filters[filtcnt].filter = gf_line_test;
+ filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
+ }
+
+--- 2946,2952 ----
+ dq.do_color = 0;
+ dq.delete_all = 1;
+
+! filters[filtcnt].filter = gf_quote_test;
+ filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
+ }
+
+diff -rc alpine-2.00/pith/rules.c alpine-2.00.I.USE/pith/rules.c
+*** alpine-2.00/pith/rules.c 2011-02-07 20:34:02.000000000 -0800
+--- alpine-2.00.I.USE/pith/rules.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 0 ****
+--- 1,1149 ----
++ /* This module was written by
++ *
++ * Eduardo Chappa (chappa@washington.edu)
++ * http://staff.washington.edu/chappa/pine/
++ *
++ * Original Version: November 1999
++ * Last Modified : January 24, 2008
++ *
++ * Send bug reports about this module to the address above.
++ */
++
++ #include "../pith/headers.h"
++ #include "../pith/state.h"
++ #include "../pith/conf.h"
++ #include "../pith/copyaddr.h"
++ #include "../pith/rules.h"
++
++ /* Internal Prototypes */
++
++ int test_condition (CONDITION_S *, int, ENVELOPE *);
++ int test_in (CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int);
++ int test_ni (CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int);
++ int test_not_in (CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int);
++ int test_not_ni (CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int);
++ int test_eq (CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int);
++ int test_not_eq (CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int);
++ int isolate_condition (char *, char **, int *);
++ char *test_rule (RULELIST *, int, ENVELOPE *, int *);
++ char *trim (RULEACTION_S *, int, ENVELOPE *);
++ char *rextrim (RULEACTION_S *, int, ENVELOPE *);
++ char *raw_value (RULEACTION_S *, int, ENVELOPE *);
++ char *extended_value (RULEACTION_S *, int, ENVELOPE *);
++ char *exec_fcn (RULEACTION_S *, int, ENVELOPE *);
++ char *expand (char *, void *);
++ char *get_name_token (char *);
++ char *advance_to_char (char *, char, int, int *);
++ char **functions_for_token (char *);
++ void free_token_value (TOKEN_VALUE **);
++ void free_condition (CONDITION_S **);
++ void free_ruleaction (RULEACTION_S **);
++ void free_rule (RULE_S **);
++ void free_rule_list (RULELIST **);
++ void free_alloc_rule (void **, int);
++ void *alloc_mem (size_t);
++ void add_rule (int, int);
++ void set_rule_list (struct variable *);
++ void parse_patterns_into_action(TOKEN_VALUE **);
++ void free_parsed_value(TOKEN_VALUE **value);
++ RULE_S *parse_rule (char *, int);
++ RULELIST *get_rule_list (char **, int, int);
++ TOKEN_VALUE *parse_group_data (char *,int *);
++ TOKEN_VALUE *copy_parsed_value (TOKEN_VALUE *, int, ENVELOPE *);
++ CONDITION_S *fill_condition (char *);
++ CONDITION_S *parse_condition (char *, int *);
++ PRULELIST_S *add_prule (PRULELIST_S *, PRULELIST_S *);
++ RULEACTION_S *parse_action (char *, int);
++
++ REL_TOKEN rel_rules_test[] = {
++ {EQ_REL, Equal, test_eq},
++ {IN_REL, Subset, test_in},
++ {NI_REL, Includes, test_ni},
++ {NOT_EQ_REL, NotEqual, test_not_eq},
++ {NOT_IN_REL, NotSubset, test_not_in},
++ {NOT_NI_REL, NotIncludes, test_not_ni},
++ {NULL, EndTypes, NULL}
++ };
++
++ #define NREL (sizeof(rel_rules_test)/sizeof(rel_rules_test[0]) - 1)
++
++ RULE_FCN rule_fcns[] = {
++ {COPY_FCN, extended_value, FOR_SAVE|FOR_COMPOSE},
++ {SAVE_FCN, extended_value, FOR_SAVE},
++ {EXEC_FCN, exec_fcn, FOR_REPLACE|FOR_TRIM|FOR_RESUB|FOR_COMPOSE},
++ {REPLY_FCN, extended_value, FOR_REPLY_INTRO},
++ {TRIM_FCN, trim, FOR_TRIM|FOR_RESUB|FOR_COMPOSE},
++ {REPLACE_FCN, extended_value, FOR_REPLACE},
++ {SORT_FCN, raw_value, FOR_SORT},
++ {INDEX_FCN, raw_value, FOR_INDEX},
++ {COMMAND_FCN, raw_value, FOR_KEY},
++ {REPLYSTR_FCN, raw_value, FOR_COMPOSE},
++ {SIGNATURE_FCN, raw_value, FOR_COMPOSE},
++ {RESUB_FCN, extended_value, FOR_RESUB},
++ {STARTUP_FCN, raw_value, FOR_STARTUP},
++ {REXTRIM_FCN, rextrim, FOR_TRIM|FOR_RESUB|FOR_COMPOSE},
++ {THRDSTYLE_FCN, raw_value, FOR_THREAD},
++ {THRDINDEX_FCN, raw_value, FOR_THREAD},
++ {SMTP_FCN, raw_value, FOR_COMPOSE},
++ {NULL, 0, FOR_NOTHING}
++ };
++
++ char* token_rules[] = {
++ FROM_TOKEN,
++ NICK_TOKEN,
++ OTEXT_TOKEN,
++ OTEXTNQ_TOKEN,
++ ROLE_TOKEN,
++ FOLDER_TOKEN,
++ SUBJ_TOKEN,
++ PROCID_TOKEN,
++ THDDSPSTY_TOKEN,
++ THDNDXSTY_TOKEN,
++ FLAG_TOKEN,
++ COLLECT_TOKEN,
++ THDDSPSTY_TOKEN,
++ ADDR_TOKEN,
++ TO_TOKEN,
++ ADDTO_TOKEN,
++ ADDCC_TOKEN,
++ ADDRECIP_TOKEN,
++ SCREEN_TOKEN,
++ KEY_TOKEN,
++ SEND_TOKEN,
++ CC_TOKEN,
++ LCC_TOKEN,
++ BCC_TOKEN,
++ FFROM_TOKEN,
++ FADDRESS_TOKEN,
++ NULL
++ };
++
++ #define NTOKENS (sizeof(token_rules)/sizeof(token_rules[0]) - 1)
++ #define NFCN (sizeof(rule_fcns)/sizeof(rule_fcns[0]) - 1)
++
++ char *subj_fcn[] = {SUBJ_TOKEN, REPLACE_FCN, TRIM_FCN, REXTRIM_FCN, EXEC_FCN};
++ char *from_fcn[] = {FROM_TOKEN, REPLACE_FCN, TRIM_FCN, REXTRIM_FCN, EXEC_FCN};
++ char *otext_fcn[] = {OTEXT_TOKEN, REPLACE_FCN, TRIM_FCN, REXTRIM_FCN, EXEC_FCN};
++ char *otextnq_fcn[] = {OTEXTNQ_TOKEN, REPLACE_FCN, TRIM_FCN, REXTRIM_FCN, EXEC_FCN};
++
++ char *adto_fcn[] = {ADDTO_TOKEN, EXEC_FCN, NULL, NULL, NULL};
++
++ char **fcns_for_index[] = {subj_fcn, from_fcn, otext_fcn, otextnq_fcn};
++
++ #define NFCNFI (sizeof(fcns_for_index)/sizeof(fcns_for_index[0])) /*for idx*/
++ #define NFPT (sizeof(fcns_for_index[0])) /* functions pert token */
++
++ SPAREP_S *
++ get_sparep_for_rule(char *value, int flag)
++ {
++ SPAREP_S *rv;
++ rv = (SPAREP_S *) alloc_mem(sizeof(SPAREP_S));
++ rv->flag = flag;
++ rv->value = value ? cpystr(value) : NULL;
++ return rv;
++ }
++
++ void free_sparep_for_rule(void **sparep)
++ {
++ SPAREP_S *spare = (SPAREP_S *) *sparep;
++ if(!spare) return;
++ if(spare->value)
++ fs_give((void **)&spare->value);
++ fs_give((void **)sparep);
++ }
++
++
++ int context_for_function(char *name)
++ {
++ int i, j;
++ for (i = 0; i < NFCN && strcmp(rule_fcns[i].name, name); i++);
++ return i == NFCN ? 0 : rule_fcns[i].what_for;
++
++ }
++
++ char **functions_for_token(char *name)
++ {
++ int i;
++ for (i = 0; i < NFCNFI && strcmp(fcns_for_index[i][0], name); i++);
++ return i == NFCNFI ? NULL : fcns_for_index[i];
++ }
++
++ void
++ free_alloc_rule (void **voidtext, int code)
++ {
++ switch(code){
++ case FREEREGEX : regfree((regex_t *)*voidtext);
++ break;
++ default: break;
++ }
++ }
++
++
++
++ void free_token_value(TOKEN_VALUE **token)
++ {
++ if(token && *token){
++ if ((*token)->testxt)
++ fs_give((void **)&(*token)->testxt);
++ free_alloc_rule (&(*token)->voidtxt, (*token)->codefcn);
++ if((*token)->next)
++ free_token_value(&(*token)->next);
++ fs_give((void **)token);
++ }
++ }
++
++ void free_condition(CONDITION_S **condition)
++ {
++ if(condition && *condition){
++ if ((*condition)->tname)
++ fs_give((void **)&((*condition)->tname));
++ if ((*condition)->value)
++ free_token_value(&((*condition)->value));
++ if((*condition)->next)
++ free_condition(&((*condition)->next));
++ fs_give((void **)condition);
++ }
++ }
++
++ void free_ruleaction(RULEACTION_S **raction)
++ {
++ if(raction && *raction){
++ if ((*raction)->token)
++ fs_give((void **)&((*raction)->token));
++ if ((*raction)->function)
++ fs_give((void **)&((*raction)->function));
++ if ((*raction)->value)
++ free_token_value(&(*raction)->value);
++ fs_give((void **)raction);
++ }
++ }
++
++ void free_rule(RULE_S **rule)
++ {
++ if(rule && *rule){
++ free_condition(&((*rule)->condition));
++ free_ruleaction(&((*rule)->action));
++ fs_give((void **)rule);
++ }
++ }
++
++ void free_rule_list(RULELIST **rule)
++ {
++ if(!*rule)
++ return;
++
++ if((*rule)->next)
++ free_rule_list(&((*rule)->next));
++
++ if((*rule)->prule)
++ free_rule(&((*rule)->prule));
++
++ fs_give((void **)rule);
++ }
++
++ void
++ free_parsed_rule_list(PRULELIST_S **rule)
++ {
++ if(!*rule)
++ return;
++
++ if((*rule)->next)
++ free_parsed_rule_list(&((*rule)->next));
++
++ if((*rule)->rlist)
++ free_rule_list(&((*rule)->rlist));
++
++ fs_give((void **)rule);
++ }
++
++ void *
++ alloc_mem (size_t amount)
++ {
++ void *genmem;
++ memset(genmem = fs_get(amount), 0, amount);
++ return genmem;
++ }
++
++
++ void
++ parse_patterns_into_action(TOKEN_VALUE **tokenp)
++ {
++ if(!*tokenp)
++ return;
++
++ if((*tokenp)->testxt){
++ regex_t preg;
++
++ (*tokenp)->voidtxt = NULL;
++ (*tokenp)->voidtxt = fs_get(sizeof(regex_t));
++ if (regcomp((regex_t *)(*tokenp)->voidtxt,
++ (*tokenp)->testxt, REG_EXTENDED) != 0){
++ regfree((regex_t *)(*tokenp)->voidtxt);
++ (*tokenp)->voidtxt = NULL;
++ }
++ }
++ if((*tokenp)->voidtxt)
++ (*tokenp)->codefcn = FREEREGEX;
++ if((*tokenp)->next)
++ parse_patterns_into_action(&(*tokenp)->next);
++ }
++
++
++ int
++ isolate_condition (char *data, char **cvalue, int *len)
++ {
++ char *p = data;
++ int done = 0, error = 0, next_condition = 0, l;
++
++ if(*p == '"' && p[strlen(p) - 1] == '"'){
++ p[strlen(p) - 1] = '\0';
++ p++;
++ }
++ *cvalue = NULL;
++ while (*p && !done){
++ switch (*p){
++ case '_': *cvalue = advance_to_char(p,'}', STRICTLY, NULL);
++ if(*cvalue){
++ strcat(*cvalue,"}");
++ p += strlen(*cvalue);
++ }
++ else
++ error++;
++ done++;
++ case ' ': p++;
++ break;
++ case '&': if (*(p+1) == '&'){ /* looking for && */
++ p += 2;
++ next_condition++;
++ }
++ else{
++ error++;
++ done++;
++ }
++ break;
++ case '=': /* looking for => or -> */
++ case '-': if ((*(p+1) == '>') && (!next_condition)){
++ is_save = (*p == '-');
++ p += 2;
++ }
++ else
++ error++;
++ done++;
++ break;
++ default : done++;
++ error++;
++ break;
++ }
++ }
++ *len = p - data;
++ return error ? -1 : (*cvalue ? 1 : 0);
++ }
++
++ TOKEN_VALUE *
++ parse_group_data (char *data, int *error)
++ {
++ TOKEN_VALUE *rvalue;
++ char *p;
++ int offset, err = 0;
++
++ if(error)
++ *error = 0;
++
++ if (!data)
++ return (TOKEN_VALUE *) NULL;
++
++ rvalue = (TOKEN_VALUE *) alloc_mem(sizeof(TOKEN_VALUE));
++ if (p = advance_to_char(data,';', STRICTLY, &offset)){
++ rvalue->testxt = cpystr(p);
++ data += strlen(p) + 1 + offset;
++ rvalue->next = parse_group_data(data, error);
++ }
++ else if (p = advance_to_char(data,'}', STRICTLY, NULL))
++ rvalue->testxt = cpystr(p);
++ else if (data && *data == '}')
++ rvalue->testxt = cpystr("");
++ else{
++ err++;
++ free_token_value(&rvalue);
++ }
++ if (error)
++ *error += err;
++ return(rvalue);
++ }
++
++ CONDITION_S *
++ fill_condition(char *data)
++ {
++ CONDITION_S *condition;
++ int i, done, error = 0;
++ char *group;
++
++ for (i = 0, done = 0; !done && (i < NTOKENS); i++)
++ done = strncmp(data,token_rules[i], strlen(token_rules[i])) ? 0 : 1;
++ if (done){
++ condition = (CONDITION_S *) alloc_mem(sizeof(CONDITION_S));
++ condition->tname = cpystr(token_rules[--i]);
++ }
++ else
++ return (CONDITION_S *)NULL;
++
++ data += strlen(token_rules[i]);
++ for (; *data && *data == ' '; data++);
++ if (*data){
++ for (i = 0, done = 0; !done && (i < NREL); i++)
++ done = strncmp(data, rel_rules_test[i].value, 2) ? 0 : 1;
++ if (done)
++ condition->ttype = rel_rules_test[--i].ttype;
++ else{
++ free_condition(&condition);
++ return (CONDITION_S *) NULL;
++ }
++ }
++ data += 2;
++ for (; *data && *data == ' '; data++);
++ if (*data++ != '{'){
++ free_condition(&condition);
++ return (CONDITION_S *) NULL;
++ }
++ group = advance_to_char(data,'}', STRICTLY, &error);
++ if (group || (!group && error < 0)){
++ condition->value = parse_group_data(data, &error);
++ if(group && error)
++ free_condition(&condition);
++ if(group)
++ fs_give((void **) &group);
++ }
++ else
++ free_condition(&condition);
++ return condition;
++ }
++
++ /* eoc = end of condition, equal to -1 on error */
++ CONDITION_S *
++ parse_condition (char *data, int *eoc)
++ {
++ CONDITION_S *condition = NULL;
++ char *p = data, *cvalue;
++ int len, error = 0, rv;
++
++ if((rv = isolate_condition(data, &cvalue, &len)) > 0){
++ if(condition = fill_condition(cvalue))
++ condition->next = parse_condition(data+len, eoc);
++ else
++ error++;
++ }
++ *eoc += len;
++ if (error)
++ *eoc = -1;
++ return condition;
++ }
++
++ RULEACTION_S *
++ parse_action (char *data, int context)
++ {
++ int i, done;
++ RULEACTION_S *raction = NULL;
++ char *function, *p = data;
++
++ if (!p)
++ return (RULEACTION_S *) NULL;
++
++ for (; *p && *p == ' '; p++);
++ if (!*p)
++ return (RULEACTION_S *) NULL;
++
++ if (is_save){
++ raction = (RULEACTION_S *) alloc_mem(sizeof(RULEACTION_S));
++ raction->function = cpystr("_SAVE_");
++ raction->value = (TOKEN_VALUE *) alloc_mem(sizeof(TOKEN_VALUE));
++ raction->context |= FOR_SAVE;
++ raction->exec = extended_value;
++ raction->value->testxt = cpystr(p);
++ return raction;
++ }
++ for (i = 0, done = 0; !done && (i < NFCN); i++)
++ done = (strstr(p,rule_fcns[i].name) == p);
++ p += done ? strlen(rule_fcns[--i].name) + 1 : 0;
++ if(!*p || (rule_fcns[i].what_for && !(rule_fcns[i].what_for & context)))
++ return (RULEACTION_S *) NULL;
++ if (done){
++ raction = (RULEACTION_S *) alloc_mem(sizeof(RULEACTION_S));
++ /* We assign raction->token to be subject. This is not necessary for
++ most rules. It is done only for rules that need it and will not
++ make any difference in rules that do not need it. It will hopefully
++ reduce complexity in the language
++ */
++ raction->token = cpystr(SUBJ_TOKEN);
++ raction->function = cpystr(rule_fcns[i].name);
++ raction->context = rule_fcns[i].what_for;
++ raction->exec = rule_fcns[i].execute;
++ raction->value = (TOKEN_VALUE *) alloc_mem(sizeof(TOKEN_VALUE));
++ raction->value->testxt = advance_to_char(p,'}', STRICTLY, NULL);
++ if(!raction->value->testxt)
++ free_ruleaction(&raction);
++ return raction;
++ }
++
++ done = (((function = strstr(p, "_TRIM_")) != NULL)
++ ? 1 : ((function = strstr(p, "_COPY_")) != NULL)
++ ? 2 : ((function = strstr(p, "_EXEC_")) != NULL)
++ ? 3 : ((function = strstr(p, "_REXTRIM_")) != NULL)
++ ? 4 : ((function = strstr(p, "_REPLACE_")) != NULL)
++ ? 5 : 0);
++
++ if(!function)
++ return (RULEACTION_S *) NULL;
++
++ *function = '\0';
++ raction = (RULEACTION_S *) alloc_mem(sizeof(RULEACTION_S));
++ raction->token = get_name_token(p);
++ *function = '_';
++ p += strlen(raction->token) + 1;
++ for (; *p && *p == ' '; p++);
++ if (!strncmp(p,":=",2))
++ p += 2;
++ else{
++ free_ruleaction(&raction);
++ return (RULEACTION_S *) NULL;
++ }
++ for (; *p && *p == ' '; p++);
++ if (p != function){
++ free_ruleaction(&raction);
++ return (RULEACTION_S *) NULL;
++ }
++ p += done <= 3 ? 6 : 9; /* 6 = strlen("_EXEC_"), 9 = strlen("_REPLACE_") */
++ if (*p != '{'){
++ free_ruleaction(&raction);
++ return (RULEACTION_S *) NULL;
++ }
++ *p = '\0';
++ for(i = 0; i < NFCN && strcmp(function, rule_fcns[i].name);i++);
++ raction->function = cpystr(function);
++ raction->is_trim = strcmp(function,"_TRIM_") ? 0 : 1;
++ raction->is_rextrim = strcmp(function,"_REXTRIM_") ? 0 : 1;
++ raction->is_replace = strcmp(function,"_REPLACE_") ? 0 : 1;
++ raction->context = rule_fcns[i].what_for;
++ raction->exec = rule_fcns[i].execute;
++ *p++ = '{';
++ if((raction->value = parse_group_data(p, NULL)) == NULL
++ || raction->value->testxt == NULL)
++ free_ruleaction(&raction);
++ if(raction && raction->is_rextrim)
++ parse_patterns_into_action(&raction->value);
++ return raction;
++ }
++
++ RULE_S *
++ parse_rule (char *data, int context)
++ {
++ RULE_S *prule; /*parsed rule */
++ int len = 0;
++
++ if (!(prule = (RULE_S *) alloc_mem(sizeof(RULE_S))) ||
++ !(prule->condition = parse_condition(data, &len)) ||
++ !(prule->action = parse_action(data+len, context)))
++ free_rule(&prule);
++
++ return prule;
++ }
++
++ RULELIST *
++ get_rule_list(char **list, int context, int i)
++ {
++ RULE_S *rule;
++ RULELIST *trulelist = NULL;
++
++ if (list[i] && *list[i]){
++ if(rule = parse_rule(list[i], context)){
++ trulelist = (RULELIST *)alloc_mem(sizeof(RULELIST));
++ trulelist->prule = rule;
++ trulelist->next = get_rule_list(list, context, i+1);
++ }
++ else
++ trulelist = get_rule_list(list, context, i+1);
++ }
++ return trulelist;
++ }
++
++ PRULELIST_S *
++ add_prule(PRULELIST_S *rule_list, PRULELIST_S *rule)
++ {
++ if (!rule_list)
++ rule_list = (PRULELIST_S *) alloc_mem(sizeof(PRULELIST_S));
++
++ if(rule_list->next)
++ rule_list->next = add_prule(rule_list->next, rule);
++ else{
++ if (rule_list->rlist)
++ rule_list->next = rule;
++ else
++ rule_list = rule;
++ }
++ return rule_list;
++ }
++
++ void
++ add_rule(int code, int context)
++ {
++ char **list = ps_global->vars[code].current_val.l;
++ PRULELIST_S *prulelist, *trulelist, *orulelist;
++
++ if (list && *list && **list){
++ trulelist = (PRULELIST_S *)alloc_mem(sizeof(PRULELIST_S));
++ trulelist->varnum = code;
++ if (trulelist->rlist = get_rule_list(list, context, 0))
++ ps_global->rule_list = add_prule(ps_global->rule_list, trulelist);
++ else
++ free_parsed_rule_list(&trulelist);
++ }
++ }
++
++ /* see create_rule_list below */
++ void
++ set_rule_list(struct variable *vars)
++ {
++ set_current_val(&vars[V_THREAD_DISP_STYLE_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_THREAD_INDEX_STYLE_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_COMPOSE_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_FORWARD_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_INDEX_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_KEY_RULES], FALSE, TRUE);
++ set_current_val(&vars[V_REPLACE_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_REPLY_INDENT_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_REPLY_LEADIN_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_RESUB_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_SAVE_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_SMTP_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_SORT_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_STARTUP_RULES], TRUE, TRUE);
++ }
++
++ /* see set_rule_list above */
++ void
++ create_rule_list(struct variable *vars)
++ {
++ set_rule_list(vars);
++ add_rule(V_THREAD_DISP_STYLE_RULES, FOR_THREAD);
++ add_rule(V_THREAD_INDEX_STYLE_RULES, FOR_THREAD);
++ add_rule(V_COMPOSE_RULES, FOR_COMPOSE);
++ add_rule(V_FORWARD_RULES, FOR_COMPOSE);
++ add_rule(V_INDEX_RULES, FOR_INDEX);
++ add_rule(V_KEY_RULES, FOR_KEY);
++ add_rule(V_REPLACE_RULES, FOR_REPLACE);
++ add_rule(V_REPLY_INDENT_RULES, FOR_COMPOSE);
++ add_rule(V_REPLY_LEADIN_RULES, FOR_REPLY_INTRO);
++ add_rule(V_RESUB_RULES, FOR_RESUB|FOR_TRIM);
++ add_rule(V_SAVE_RULES, FOR_SAVE);
++ add_rule(V_SMTP_RULES, FOR_COMPOSE);
++ add_rule(V_SORT_RULES, FOR_SORT);
++ add_rule(V_STARTUP_RULES, FOR_STARTUP);
++ }
++
++ int
++ condition_contains_token(CONDITION_S *condition, char *token)
++ {
++ return condition ? (!strcmp(condition->tname, token)
++ ? 1
++ : condition_contains_token(condition->next, token))
++ : 0;
++ }
++
++ RULELIST *
++ get_rulelist_from_code(int code, PRULELIST_S *list)
++ {
++ return list ? (list->varnum == code ? list->rlist
++ : get_rulelist_from_code(code, list->next))
++ : (RULELIST *) NULL;
++ }
++
++ char *
++ test_rule(RULELIST *rlist, int ctxt, ENVELOPE *env, int *n)
++ {
++ char *result;
++
++ if(!rlist)
++ return NULL;
++
++ if (result = process_rule(rlist->prule, ctxt, env))
++ return result;
++ else{
++ (*n)++;
++ return test_rule(rlist->next, ctxt, env, n);
++ }
++ }
++
++ RULE_S *
++ get_rule (RULELIST *rule, int n)
++ {
++ return rule ? (n ? get_rule(rule->next, n-1) : rule->prule)
++ : (RULE_S *) NULL;
++ }
++
++ /* get_result_rule:
++ * Parameters: list: the list of rules to be passed to the function to check
++ * rule_context: context of the rule
++ * env : envelope used to check the rule, if needed.
++ *
++ * Returns: The value of the first rule that is satisfied in the list, or
++ * NULL if not. This function should be called in the following
++ * way (notice that memory is freed by caller).
++ *
++ * You should use this function to obtain the result of a rule. You can
++ * also call directly "process_rule", but I advice to use this function if
++ * there's no difference on which function to call.
++
++ RULE_RESULT *rule;
++
++ rule = (RULE_RESULT *)
++ get_result_rule(V_SOME_RULE, context, envelope);
++
++ if (rule){
++ assign the value of rule->result;
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ */
++
++ RULE_RESULT *
++ get_result_rule(int code, int rule_context, ENVELOPE *env)
++ {
++ char *rule_result;
++ RULE_RESULT *rule = NULL;
++ RULELIST *rlist;
++ int n = 0;
++
++ if(!(rule_context & FOR_RULE))
++ rule_context |= FOR_RULE;
++ rlist = get_rulelist_from_code(code, ps_global->rule_list);
++ if (rlist){
++ rule_result = test_rule(rlist, rule_context, env, &n);
++ if (rule_result && *rule_result){
++ rule = (RULE_RESULT *) fs_get (sizeof(RULE_RESULT));
++ rule->result = rule_result;
++ rule->number = n;
++ }
++ }
++ return rule;
++ }
++
++ char *get_rule_result(int rule_context, char *newfolder, int code)
++ {
++ char *rule_result = NULL;
++ ENVELOPE *news_envelope;
++ RULE_RESULT *rule;
++
++ if (IS_NEWS(ps_global->mail_stream)){
++ news_envelope = mail_newenvelope();
++ news_envelope->newsgroups = cpystr(newfolder);
++ }
++ else
++ news_envelope = NULL;
++
++ rule = get_result_rule(code, rule_context, news_envelope);
++
++ if (news_envelope)
++ mail_free_envelope (&news_envelope);
++
++ if (rule){
++ rule_result = cpystr(rule->result);
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ return rule_result;
++ }
++
++ /* process_rule:
++ Parameters: rule_data, is a rule. It's obtained as
++ rule_data = ps_global->VAR_SOME_RULE[n], for
++ some integer n
++ rule_context: context of the rule, and
++ env: An envelope if needed.
++
++ Returns : The value of the processed rule_data if the processing was
++ successful and matches context and possibly the envelope, or
++ NULL if there's no match
++ */
++
++ char *
++ process_rule (RULE_S *prule, int rule_context, ENVELOPE *env)
++ {
++ char *result = NULL;
++ int rv;
++ CONDITION_S *condition;
++
++ if(!prule)
++ return NULL;
++
++ if(!(rule_context & FOR_RULE))
++ rule_context |= FOR_RULE;
++
++ for(condition = prule->condition;
++ condition &&
++ (rv = test_condition(condition, rule_context, env));
++ condition = condition->next);
++
++ if(rv && !condition)
++ result = (prule->action->exec)(prule->action, rule_context, env);
++
++ return result;
++ }
++
++ TOKEN_VALUE *
++ copy_parsed_value(TOKEN_VALUE *value, int ctxt, ENVELOPE *env)
++ {
++ TOKEN_VALUE *tval = NULL;
++
++ if(!value)
++ return NULL;
++
++ if(value->testxt){
++ tval = (TOKEN_VALUE *) alloc_mem(sizeof(TOKEN_VALUE));
++ tval->testxt = detoken_src(value->testxt, ctxt, env, NULL, NULL, NULL);
++ tval->voidtxt = value->voidtxt;
++ tval->codefcn = value->codefcn;
++ }
++ if(value->next)
++ tval->next = copy_parsed_value(value->next, ctxt, env);
++
++ return tval;
++ }
++
++ void
++ free_parsed_value(TOKEN_VALUE **value)
++ {
++ TOKEN_VALUE *tval = NULL;
++
++ if(!*value)
++ return;
++
++ if((*value)->testxt)
++ fs_give((void **)&(*value)->testxt);
++
++ if((*value)->next)
++ free_parsed_value(&(*value)->next);
++
++ fs_give((void **)value);
++ }
++
++
++ int
++ test_condition(CONDITION_S *condition, int rule_context, ENVELOPE *env)
++ {
++ int next_step;
++ TOKEN_VALUE *group;
++
++ group = copy_parsed_value(condition->value, rule_context, env);
++ next_step = (*rel_rules_test[condition->ttype].execute)(condition, group, env, rule_context);
++ free_parsed_value(&group);
++ return next_step;
++ }
++
++ /* returns the name of the token it found or NULL if there is no token, the
++ * real value of the token is obtained by calling the detoken_src function.
++ */
++
++ char *
++ get_name_token (char *condition)
++ {
++ char *p = NULL, *q, *s;
++
++ if ((q = strchr(condition,'_')) && (s = strchr(q+1,'_'))){
++ char c = *++s;
++ *s = '\0';
++ p = cpystr(q);
++ *s = c;
++ }
++ return p;
++ }
++
++ /* This function tests if a string contained in the variable "group" is
++ * in the "condition"
++ */
++ int test_in (CONDITION_S *condition, TOKEN_VALUE *group, ENVELOPE *env,
++ int context)
++ {
++ int rv = 0;
++ char *test;
++ TOKEN_VALUE *test_group = group;
++
++ test = env && env->sparep && ((SPAREP_S *)env->sparep)->flag & USE_RAW_SP
++ ? cpystr(((SPAREP_S *)env->sparep)->value)
++ : detoken_src(condition->tname, context, env, NULL, NULL, NULL);
++ if (test){
++ while (rv == 0 && test_group){
++ if(!*test || strstr(test_group->testxt, test))
++ rv++;
++ else
++ test_group = test_group->next;
++ }
++ fs_give((void **)&test);
++ }
++ return rv;
++ }
++
++ int test_ni (CONDITION_S *condition, TOKEN_VALUE *group,
++ ENVELOPE *env, int context)
++ {
++ int rv = 0;
++ char *test;
++ TOKEN_VALUE *test_group = group;
++
++ test = env && env->sparep && ((SPAREP_S *)env->sparep)->flag & USE_RAW_SP
++ ? cpystr(((SPAREP_S *)env->sparep)->value)
++ : detoken_src(condition->tname, context, env, NULL, NULL, NULL);
++ if (test){
++ if(!test_group)
++ rv++;
++ while (rv == 0 && test_group){
++ if(!*test_group->testxt || strstr(test, test_group->testxt))
++ rv++;
++ else
++ test_group = test_group->next;
++ }
++ fs_give((void **)&test);
++ }
++ return rv;
++ }
++
++ int test_not_in (CONDITION_S *condition, TOKEN_VALUE *group,
++ ENVELOPE *env, int context)
++ {
++ return !test_in(condition, group, env, context);
++ }
++
++ int test_not_ni (CONDITION_S *condition, TOKEN_VALUE *group,
++ ENVELOPE *env, int context)
++ {
++ return !test_ni(condition, group, env, context);
++ }
++
++ int test_eq (CONDITION_S *condition, TOKEN_VALUE *group,
++ ENVELOPE *env, int context)
++ {
++ int rv = 0;
++ char *test;
++ TOKEN_VALUE *test_group = group;
++
++ test = env && env->sparep && ((SPAREP_S *)env->sparep)->flag & USE_RAW_SP
++ ? cpystr(((SPAREP_S *)env->sparep)->value)
++ :detoken_src(condition->tname, context, env, NULL, NULL, NULL);
++ if (test){
++ while (rv == 0 && test_group){
++ if((!*test && !*test_group->testxt) || !strcmp(test_group->testxt, test))
++ rv++;
++ else
++ test_group = test_group->next;
++ }
++ fs_give((void **)&test);
++ }
++ return rv;
++ }
++
++ int test_not_eq (CONDITION_S *condition, TOKEN_VALUE *group,
++ ENVELOPE *env, int context)
++ {
++ return !test_eq(condition, group, env, context);
++ }
++
++ char *
++ do_trim (char *test, TOKEN_VALUE *tval)
++ {
++ char *begin_text;
++ int offset = 0;
++
++ if (!tval)
++ return test;
++
++ while(begin_text = strstr(test+offset,tval->testxt)){
++ strcpy(begin_text, begin_text+strlen(tval->testxt));
++ offset = begin_text - test;
++ }
++
++ return do_trim(test, tval->next);
++ }
++
++ char *
++ trim (RULEACTION_S *action, int context, ENVELOPE *env)
++ {
++ char *begin_text, *test;
++ RULEACTION_S *taction = action;
++ int offset;
++
++ if (taction->context & context){
++ if (test = detoken_src(taction->token, context, env, NULL, NULL, NULL))
++ test = do_trim(test, taction->value);
++ return test;
++ }
++ return NULL;
++ }
++
++
++ char *
++ do_rextrim (char *test, TOKEN_VALUE *tval)
++ {
++ char *begin_text, *trim_text;
++ int offset = 0;
++
++ if (!tval)
++ return test;
++
++ trim_text = expand(test, tval->voidtxt);
++ while(trim_text && (begin_text = strstr(test+offset,trim_text))){
++ strcpy(begin_text, begin_text+strlen(trim_text));
++ offset = begin_text - test;
++ }
++
++ return do_rextrim(test, tval->next);
++ }
++
++ char *
++ rextrim (RULEACTION_S *action, int context, ENVELOPE *env)
++ {
++ char *test = NULL;
++ RULEACTION_S *taction = action;
++
++ if (taction->context & context &&
++ (test = detoken_src(taction->token, context, env, NULL, NULL, NULL)))
++ test = do_rextrim(test, taction->value);
++ return test;
++ }
++
++ char *
++ raw_value (RULEACTION_S *action, int context, ENVELOPE *env)
++ {
++ return (action->context & context) ? cpystr(action->value->testxt) : NULL;
++ }
++
++ char *
++ extended_value (RULEACTION_S *action, int ctxt, ENVELOPE *env)
++ {
++ return (action->context & ctxt)
++ ? detoken_src(action->value->testxt, ctxt, env, NULL, NULL, NULL)
++ : NULL;
++ }
++
++ /* advances given_string until it finds given_char */
++ char *
++ advance_to_char(char *given_string, char given_char, int flag, int *error)
++ {
++ char *b, *s, c;
++ int i, err = 0, quoted ;
++
++ if (error)
++ *error = 0;
++
++ if (!given_string || !*given_string)
++ return NULL;
++
++ b = s = cpystr(given_string);
++ for(i = 0, quoted = 0, c = *s; c ; c = *++s){
++ if(c == '\\'){
++ quoted++;
++ continue;
++ }
++ if(quoted){
++ quoted = 0;
++ if (c == given_char){
++ err += flag & STRICTLY ? 0 : 1;
++ err++;
++ break;
++ }
++ b[i++] = '\\';
++ }
++ if(c == given_char){
++ err += flag & STRICTLY ? 0 : 1;
++ break;
++ }
++ b[i++] = c;
++ }
++ b[i] = '\0';
++ if (b && (strlen(b) == strlen(given_string)) && (flag & STRICTLY))
++ return NULL; /* character not found */
++
++ if(b && !*b){
++ fs_give((void **)&b);
++ err = -1;
++ }
++
++ if (error)
++ *error = err;
++
++ return b;
++ }
++
++ /* Regular Expressions Support */
++ char *
++ expand (char *string, void *pattern)
++ {
++ char c, *ret_string = NULL;
++ regmatch_t pmatch;
++
++ if((regex_t *)pattern == NULL)
++ return NULL;
++
++ if(regexec((regex_t *)pattern, string , 1, &pmatch, 0) == 0
++ && pmatch.rm_so < pmatch.rm_eo){
++ c = string[pmatch.rm_eo];
++ string[pmatch.rm_eo] = '\0';
++ ret_string = cpystr(string+pmatch.rm_so);
++ string[pmatch.rm_eo] = c;
++ }
++ return ret_string;
++ }
++
++
++ char *
++ exec_fcn (RULEACTION_S *action, int ctxt, ENVELOPE *env)
++ {
++ STORE_S *output_so;
++ gf_io_t gc, pc;
++ char *status, *rv, *cmd, *test;
++
++ if(!(action->context & ctxt))
++ return NULL;
++
++ if((test = detoken_src(action->token, ctxt, env, NULL, NULL, NULL)) != NULL)
++ gf_set_readc(&gc, test, (unsigned long)strlen(test), CharStar, 0);
++
++ if((output_so = so_get(CharStar, NULL, EDIT_ACCESS)) != NULL)
++ gf_set_so_writec(&pc, output_so);
++
++ cmd = (char *)fs_get((strlen(action->value->testxt) + strlen("_TMPFILE_") + 2)*sizeof(char));
++ sprintf(cmd,"%s _TMPFILE_", action->value->testxt);
++ status = (*ps_global->tools.exec_rule)(cmd, gc, pc);
++
++ so_seek(output_so, 0L, 0);
++ rv = cpystr(output_so->dp);
++ gf_clear_so_writec(output_so);
++ so_give(&output_so);
++ if(test)
++ fs_give((void **)&test);
++
++ return status ? NULL : rv;
++ }
++
++ ENVELOPE *
++ rules_fetchenvelope(INDEXDATA_S *idata, int *we_clear)
++ {
++ ENVELOPE *env;
++
++ if (idata->no_fetch){
++ if(we_clear)
++ *we_clear = 1;
++ env = mail_newenvelope();
++ env->from = copyaddrlist(idata->from);
++ env->to = copyaddrlist(idata->to);
++ env->cc = copyaddrlist(idata->cc);
++ env->sender = copyaddrlist(idata->sender);
++ env->subject = cpystr(idata->subject);
++ env->date = cpystr((unsigned char *) idata->date);
++ env->newsgroups = cpystr(idata->newsgroups);
++ return env;
++ }
++ if(we_clear)
++ *we_clear = 0;
++ env = pine_mail_fetchenvelope(idata->stream, idata->rawno);
++ return env;
++ }
+diff -rc alpine-2.00/pith/rules.h alpine-2.00.I.USE/pith/rules.h
+*** alpine-2.00/pith/rules.h 2011-02-07 20:34:02.000000000 -0800
+--- alpine-2.00.I.USE/pith/rules.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 0 ****
+--- 1,151 ----
++ /* Included file rules.h */
++
++ #ifndef PITH_RULES_INCLUDED
++ #define PITH_RULES_INCLUDED
++
++ #include "../pith/conftype.h"
++ #include "../pith/detoken.h"
++ #include "../pith/indxtype.h"
++ #include "../pith/rulestype.h"
++
++ int is_save; /* this rule has the form condition -> folder */
++
++ /* Exported prototypes */
++
++ void create_rule_list (struct variable *);
++ SPAREP_S *get_sparep_for_rule(char *, int);
++ void free_sparep_for_rule(void **);
++ void free_parsed_rule_list (PRULELIST_S **);
++ RULE_RESULT *get_result_rule (int, int, ENVELOPE *);
++ char *get_rule_result (int , char *, int);
++ char *process_rule (RULE_S *, int, ENVELOPE *);
++ char **functions_for_token (char *);
++ RULELIST *get_rulelist_from_code (int, PRULELIST_S *);
++ RULE_S *get_rule (RULELIST *, int);
++ int condition_contains_token (CONDITION_S *, char *);
++ int context_for_function (char *);
++ ENVELOPE *rules_fetchenvelope(INDEXDATA_S *idata, int *we_clear);
++
++ /* Separators:
++ *
++ * A separator is a string that separates the rule condition with the rule
++ * action. Below is the list of separators
++ *
++ */
++
++ #define SAVE_TO_SEP "->"
++ #define APPLY_SEP "=>"
++
++ /*------- Definitions of tokens -------*/
++ /*------ Keep the list alphabetically sorted, thanks -------*/
++
++ #define ADDR_TOKEN "_ADDRESS_"
++ #define ADDCC_TOKEN "_ADDRESSCC_"
++ #define ADDRECIP_TOKEN "_ADDRESSRECIPS_"
++ #define ADDTO_TOKEN "_ADDRESSTO_"
++ #define BCC_TOKEN "_BCC_"
++ #define CC_TOKEN "_CC_"
++ #define COLLECT_TOKEN "_COLLECTION_"
++ #define FLAG_TOKEN "_FLAG_"
++ #define FOLDER_TOKEN "_FOLDER_"
++ #define FADDRESS_TOKEN "_FORWARDADDRESS_"
++ #define FFROM_TOKEN "_FORWARDFROM_"
++ #define FROM_TOKEN "_FROM_"
++ #define KEY_TOKEN "_PKEY_"
++ #define LCC_TOKEN "_LCC_"
++ #define NICK_TOKEN "_NICK_"
++ #define OTEXT_TOKEN "_OPENINGTEXT_"
++ #define OTEXTNQ_TOKEN "_OPENINGTEXTNQ_"
++ #define PROCID_TOKEN "_PROCID_"
++ #define ROLE_TOKEN "_ROLE_"
++ #define SCREEN_TOKEN "_SCREEN_"
++ #define SEND_TOKEN "_SENDER_"
++ #define SUBJ_TOKEN "_SUBJECT_"
++ #define THDDSPSTY_TOKEN "_THREADSTYLE_"
++ #define THDNDXSTY_TOKEN "_THREADINDEX_"
++ #define TO_TOKEN "_TO_"
++
++ /*------ Definitions of relational operands -------------*/
++
++ typedef struct {
++ char *value;
++ TestType ttype;
++ int (*execute)();
++ } REL_TOKEN;
++
++ /* Relational Operands */
++ #define AND_REL "&&" /* For putting more than one condition */
++ #define IN_REL "<<" /* For belonging relation */
++ #define NI_REL ">>" /* For contain relation */
++ #define NOT_IN_REL "!<" /* Negation of IN_REL */
++ #define NOT_NI_REL "!>" /* Negation of NI_REL */
++ #define EQ_REL "==" /* Test of equality */
++ #define NOT_EQ_REL "!=" /* Test of inequality */
++ #define OPEN_SET "{" /* Braces to open a set */
++ #define CLOSE_SET "}" /* Braces to close a set*/
++
++ /*--- Context in which these variables can be used ---*/
++
++ typedef struct use_context {
++ char *name;
++ int what_for;
++ } USE_IN_CONTEXT;
++
++
++ static USE_IN_CONTEXT tokens_use[] = {
++ {NICK_TOKEN, FOR_SAVE},
++ {FROM_TOKEN, FOR_SAVE},
++ {OTEXT_TOKEN, FOR_SAVE|FOR_FOLDER},
++ {OTEXTNQ_TOKEN, FOR_SAVE|FOR_FOLDER},
++ {ROLE_TOKEN, FOR_COMPOSE},
++ {FOLDER_TOKEN, FOR_SAVE|FOR_FOLDER|FOR_THREAD|FOR_COMPOSE},
++ {SUBJ_TOKEN, FOR_SAVE|FOR_FOLDER|FOR_COMPOSE},
++ {FLAG_TOKEN, FOR_SAVE|FOR_FLAG},
++ {COLLECT_TOKEN, FOR_SAVE|FOR_COMPOSE|FOR_FOLDER|FOR_THREAD},
++ {THDDSPSTY_TOKEN, FOR_THREAD},
++ {THDNDXSTY_TOKEN, FOR_THREAD},
++ {ADDR_TOKEN, FOR_SAVE|FOR_FOLDER},
++ {TO_TOKEN, FOR_SAVE},
++ {ADDTO_TOKEN, FOR_SAVE|FOR_COMPOSE},
++ {ADDCC_TOKEN, FOR_SAVE|FOR_COMPOSE},
++ {ADDRECIP_TOKEN, FOR_SAVE|FOR_COMPOSE},
++ {SCREEN_TOKEN, FOR_KEY},
++ {KEY_TOKEN, FOR_KEY},
++ {SEND_TOKEN, FOR_SAVE},
++ {CC_TOKEN, FOR_SAVE},
++ {BCC_TOKEN, FOR_COMPOSE},
++ {LCC_TOKEN, FOR_COMPOSE},
++ {FFROM_TOKEN, FOR_COMPOSE},
++ {FADDRESS_TOKEN, FOR_COMPOSE},
++ {NULL, FOR_NOTHING}
++ };
++
++
++ typedef struct {
++ char *name;
++ char* (*execute)();
++ int what_for;
++ } RULE_FCN;
++
++ #define COMMAND_FCN "_COMMAND_"
++ #define COPY_FCN "_COPY_"
++ #define EXEC_FCN "_EXEC_"
++ #define INDEX_FCN "_INDEX_"
++ #define REPLACE_FCN "_REPLACE_"
++ #define REPLYSTR_FCN "_RESTR_"
++ #define REPLY_FCN "_REPLY_"
++ #define RESUB_FCN "_RESUB_"
++ #define REXTRIM_FCN "_REXTRIM_"
++ #define SAVE_FCN "_SAVE_"
++ #define SIGNATURE_FCN "_SIGNATURE_"
++ #define SMTP_FCN "_SMTP_"
++ #define SORT_FCN "_SORT_"
++ #define STARTUP_FCN "_STARTUP_"
++ #define THRDSTYLE_FCN "_THREADSTYLE_"
++ #define THRDINDEX_FCN "_THREADINDEX_"
++ #define TRIM_FCN "_TRIM_"
++
++ #define STRICTLY 0x1
++ #define RELAXED 0x2
++
++ #endif /* PITH_RULES_INCLUDED */
+diff -rc alpine-2.00/pith/rulestype.h alpine-2.00.I.USE/pith/rulestype.h
+*** alpine-2.00/pith/rulestype.h 2011-02-07 20:34:02.000000000 -0800
+--- alpine-2.00.I.USE/pith/rulestype.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 0 ****
+--- 1,78 ----
++ #ifndef PITH_RULESTYPE_INCLUDED
++ #define PITH_RULESTYPE_INCLUDED
++
++ typedef struct rule {
++ char *result; /* The result of the rule */
++ int number; /* The number of the rule that succeded, -1 if not */
++ } RULE_RESULT;
++
++ typedef struct {
++ char *value;
++ int type;
++ } RULE_ACTION;
++
++
++ #define TOKEN_VALUE struct tokenvalue_s
++ #define CONDITION_S struct condition_s
++ #define RULEACTION_S struct ruleaction_s
++ #define RULE_S struct rule_s
++ #define RULELIST struct rulelist_s
++ #define PRULELIST_S struct parsedrulelist_s
++
++ #define FREEREGEX 1
++
++ TOKEN_VALUE {
++ char *testxt;
++ void *voidtxt;
++ int codefcn;
++ TOKEN_VALUE *next;
++ };
++
++ typedef enum {Equal, Subset, Includes,
++ NotEqual, NotSubset, NotIncludes,
++ EndTypes} TestType;
++
++ CONDITION_S {
++ char *tname; /* tname ttype {value} */
++ TestType ttype; /* tname ttype {value} */
++ TOKEN_VALUE *value; /* value to check against */
++ CONDITION_S *next; /* next condition to test */
++ };
++
++ RULEACTION_S {
++ char *token; /* token := function{value} or token = null */
++ char *function; /* token := function{value} or simply function{value}*/
++ TOKEN_VALUE *value; /* token := function{value} or simply function{value}*/
++ int context; /* context in which this rule can be used */
++ char* (*exec)();
++ unsigned int is_trim:1;
++ unsigned int is_rextrim:1;
++ unsigned int is_replace:1;
++ };
++
++ RULE_S {
++ CONDITION_S *condition;
++ RULEACTION_S *action;
++ };
++
++ RULELIST {
++ RULE_S *prule;
++ RULELIST *next;
++ };
++
++ PRULELIST_S {
++ int varnum; /* number associated to the variable */
++ RULELIST *rlist;
++ PRULELIST_S *next;
++ };
++
++ #define USE_RAW_SP 0x001
++ #define PROCESS_SP 0x010
++
++ typedef struct sparep {
++ int flag;
++ char *value;
++ } SPAREP_S;
++
++
++ #endif /* PITH_RULESTYPE_INCLUDED */
+diff -rc alpine-2.00/pith/save.c alpine-2.00.I.USE/pith/save.c
+*** alpine-2.00/pith/save.c 2008-05-02 14:58:34.000000000 -0700
+--- alpine-2.00.I.USE/pith/save.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 421,426 ****
+--- 421,427 ----
+ {
+ int rv, rc, j, our_stream = 0, cancelled = 0;
+ int delete, filter, k, worry_about_keywords = 0;
++ int flags_for_save = F_ANS|F_FWD|F_FLAG|F_SEEN|F_KEYWORD;
+ char *save_folder, *seq, *flags = NULL, date[64], tmp[MAILTMPLEN];
+ long i, nmsgs, rawno;
+ size_t len;
+***************
+*** 864,870 ****
+ STRING msg;
+
+ pkg.stream = stream;
+! pkg.flags = NULL;
+ pkg.date = date;
+ pkg.msg = &msg;
+ pkg.msgmap = msgmap;
+--- 865,871 ----
+ STRING msg;
+
+ pkg.stream = stream;
+! pkg.flags = flgs & SV_FIX_DELS ? NULL : cpystr("\\DELETED");
+ pkg.date = date;
+ pkg.msg = &msg;
+ pkg.msgmap = msgmap;
+***************
+*** 938,944 ****
+ mc = (rawno > 0L && stream && rawno <= stream->nmsgs)
+ ? mail_elt(stream, rawno) : NULL;
+
+! flags = flag_string(stream, rawno, F_ANS|F_FWD|F_FLAG|F_SEEN|F_KEYWORD);
+
+ if(mc && mc->day)
+ mail_date(date, mc);
+--- 939,946 ----
+ mc = (rawno > 0L && stream && rawno <= stream->nmsgs)
+ ? mail_elt(stream, rawno) : NULL;
+
+! flags_for_save |= flgs & SV_FIX_DELS ? 0 : F_DEL;
+! flags = flag_string(stream, rawno, flags_for_save);
+
+ if(mc && mc->day)
+ mail_date(date, mc);
+***************
+*** 946,952 ****
+ *date = '\0';
+
+ rv = save_fetch_append(stream, mn_m2raw(msgmap, i),
+! NULL, save_stream, save_folder, context,
+ mc ? mc->rfc822_size : 0L, flags, date, so);
+
+ if(flags)
+--- 948,954 ----
+ *date = '\0';
+
+ rv = save_fetch_append(stream, mn_m2raw(msgmap, i),
+! NULL, save_stream, folder, context,
+ mc ? mc->rfc822_size : 0L, flags, date, so);
+
+ if(flags)
+***************
+*** 1043,1048 ****
+--- 1045,1051 ----
+ MESSAGECACHE *mc;
+ char *fetch;
+ int rc;
++ int flags_for_save = F_ANS|F_FWD|F_FLAG|F_SEEN|F_KEYWORD;
+ unsigned long raw, hlen, tlen, mlen;
+
+ if(pkg->so && (pkg->msgno > 0L)) {
+***************
+*** 1051,1060 ****
+ ? mail_elt(pkg->stream, raw) : NULL;
+ if(mc){
+ size = mc->rfc822_size;
+! if(pkg->flags)
+ fs_give((void **) &pkg->flags);
+!
+! pkg->flags = flag_string(pkg->stream, raw, F_ANS|F_FWD|F_FLAG|F_SEEN|F_KEYWORD);
+ }
+
+ if(mc && mc->day)
+--- 1054,1065 ----
+ ? mail_elt(pkg->stream, raw) : NULL;
+ if(mc){
+ size = mc->rfc822_size;
+! if(pkg->flags){
+! if(strstr(pkg->flags,"\\DELETED"))
+! flags_for_save |= F_DEL;
+ fs_give((void **) &pkg->flags);
+! }
+! pkg->flags = flag_string(pkg->stream, raw, flags_for_save);
+ }
+
+ if(mc && mc->day)
+***************
+*** 1136,1141 ****
+--- 1141,1147 ----
+ snprintf(buf, sizeof(buf),
+ "Message to save shrank: source msg # %ld may be saved incorrectly",
+ mn_raw2m(pkg->msgmap, raw));
++ if(F_OFF(F_IGNORE_SIZE, ps_global))
+ q_status_message(SM_ORDER, 0, 3, buf);
+ }
+ else{
+diff -rc alpine-2.00/pith/send.c alpine-2.00.I.USE/pith/send.c
+*** alpine-2.00/pith/send.c 2008-08-06 11:25:58.000000000 -0700
+--- alpine-2.00.I.USE/pith/send.c 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 43,48 ****
+--- 43,49 ----
+ #include "../pith/ablookup.h"
+ #include "../pith/sort.h"
+ #include "../pith/smime.h"
++ #include "../pith/rules.h"
+
+ #include "../c-client/smtp.h"
+ #include "../c-client/nntp.h"
+***************
+*** 52,58 ****
+ /* name::type::canedit::writehdr::localcopy::rcptto */
+ PINEFIELD pf_template[] = {
+ {"X-Auth-Received", FreeText, 0, 1, 1, 0}, /* N_AUTHRCVD */
+! {"From", Address, 0, 1, 1, 0},
+ {"Reply-To", Address, 0, 1, 1, 0},
+ {TONAME, Address, 1, 1, 1, 1},
+ {CCNAME, Address, 1, 1, 1, 1},
+--- 53,59 ----
+ /* name::type::canedit::writehdr::localcopy::rcptto */
+ PINEFIELD pf_template[] = {
+ {"X-Auth-Received", FreeText, 0, 1, 1, 0}, /* N_AUTHRCVD */
+! {"From", Address, 1, 1, 1, 0},
+ {"Reply-To", Address, 0, 1, 1, 0},
+ {TONAME, Address, 1, 1, 1, 1},
+ {CCNAME, Address, 1, 1, 1, 1},
+***************
+*** 256,261 ****
+--- 257,269 ----
+
+ if(exists & FEX_ISFILE){
+ context_apply(tmp, p_cntxt, mbox, sizeof(tmp));
++ #ifndef _WINDOWS
++ if (!struncmp(tmp, "#md/",4) || !struncmp(tmp, "#mc/", 4)){
++ char tmp2[MAILTMPLEN];
++ maildir_file_path(tmp, tmp2);
++ strcpy(tmp, tmp2);
++ }
++ #endif
+ if(!(IS_REMOTE(tmp) || is_absolute_path(tmp))){
+ /*
+ * The mbox is relative to the home directory.
+***************
+*** 1228,1234 ****
+ *p = *(p+4);
+
+ pf->type = pf_template[i].type;
+! pf->canedit = pf_template[i].canedit;
+ pf->rcptto = pf_template[i].rcptto;
+ pf->writehdr = pf_template[i].writehdr;
+ pf->localcopy = pf_template[i].localcopy;
+--- 1236,1242 ----
+ *p = *(p+4);
+
+ pf->type = pf_template[i].type;
+! pf->canedit = (i == N_FROM) ? CAN_EDIT(ps_global) : pf_template[i].canedit;
+ pf->rcptto = pf_template[i].rcptto;
+ pf->writehdr = pf_template[i].writehdr;
+ pf->localcopy = pf_template[i].localcopy;
+***************
+*** 1737,1745 ****
+ char error_buf[200], *error_mess = NULL, *postcmd;
+ ADDRESS *a;
+ ENVELOPE *fake_env = NULL;
+! int addr_error_count, we_cancel = 0;
+ long smtp_opts = 0L;
+! char *verbose_file = NULL;
+ BODY *bp = NULL;
+ PINEFIELD *pf;
+ BODY *origBody = body;
+--- 1745,1753 ----
+ char error_buf[200], *error_mess = NULL, *postcmd;
+ ADDRESS *a;
+ ENVELOPE *fake_env = NULL;
+! int addr_error_count, we_cancel = 0, choice, num_rules = 0, added_rules = -1;
+ long smtp_opts = 0L;
+! char *verbose_file = NULL, **smtp_list;
+ BODY *bp = NULL;
+ PINEFIELD *pf;
+ BODY *origBody = body;
+***************
+*** 1892,1911 ****
+ * OK, who posts what? We tried an mta_handoff above, but there
+ * was either none specified or we decided not to use it. So,
+ * if there's an smtp-server defined anywhere,
+ */
+! if(alt_smtp_servers && alt_smtp_servers[0] && alt_smtp_servers[0][0]){
+! /*---------- SMTP ----------*/
+! dprint((4, "call_mailer: via TCP (%s)\n",
+! alt_smtp_servers[0]));
+! TIME_STAMP("smtp-open start (tcp)", 1);
+! sending_stream = smtp_open(alt_smtp_servers, smtp_opts);
+! }
+! else if(ps_global->VAR_SMTP_SERVER && ps_global->VAR_SMTP_SERVER[0]
+! && ps_global->VAR_SMTP_SERVER[0][0]){
+! /*---------- SMTP ----------*/
+! dprint((4, "call_mailer: via TCP\n"));
+! TIME_STAMP("smtp-open start (tcp)", 1);
+! sending_stream = smtp_open(ps_global->VAR_SMTP_SERVER, smtp_opts);
+ }
+ else if((postcmd = smtp_command(ps_global->c_client_error, sizeof(ps_global->c_client_error))) != NULL){
+ char *cmdlist[2];
+--- 1900,1948 ----
+ * OK, who posts what? We tried an mta_handoff above, but there
+ * was either none specified or we decided not to use it. So,
+ * if there's an smtp-server defined anywhere,
++ * First we check for rules and make a list using the rules.
+ */
+! if(ps_global->VAR_SMTP_RULES && ps_global->VAR_SMTP_RULES[0]
+! && ps_global->VAR_SMTP_RULES[0][0])
+! while (ps_global->VAR_SMTP_RULES[num_rules]) num_rules++;
+!
+! if(num_rules){
+! int i, j;
+!
+! added_rules = 0;
+! smtp_list = (char **) fs_get ((num_rules + 1)*sizeof(char*));
+! for (i = 0, j = 0; i < num_rules; i++){
+! RULELIST *rule = get_rulelist_from_code(V_SMTP_RULES,
+! ps_global->rule_list);
+! RULE_S *prule = get_rule(rule, i);
+! if(prule){
+! char *rule_result = process_rule(prule, FOR_COMPOSE, header->env);
+! if(rule_result && *rule_result){
+! smtp_list[j++] = cpystr(rule_result);
+! added_rules++;
+! }
+! }
+! }
+! }
+!
+! if (added_rules < 0){
+! smtp_list = (char **) fs_get (sizeof(char*));
+! added_rules = 0;
+! }
+! smtp_list[added_rules] = NULL;
+!
+! choice = smtp_list && smtp_list[0] && smtp_list[0][0] ? 3 :
+! (alt_smtp_servers && alt_smtp_servers[0] && alt_smtp_servers[0][0] ? 2 :
+! (ps_global->VAR_SMTP_SERVER && ps_global->VAR_SMTP_SERVER[0]
+! && ps_global->VAR_SMTP_SERVER[0][0] ? 1 : -1));
+!
+! if(choice > 0){
+! /*---------- SMTP ----------*/
+! dprint((4, "call_mailer: via TCP (%s)\n",smtp_list[0]));
+! TIME_STAMP("smtp-open start (tcp)", 1);
+! sending_stream = smtp_open(choice == 3 ? smtp_list
+! : (choice == 2 ? alt_smtp_servers
+! : ps_global->VAR_SMTP_SERVER), smtp_opts);
+ }
+ else if((postcmd = smtp_command(ps_global->c_client_error, sizeof(ps_global->c_client_error))) != NULL){
+ char *cmdlist[2];
+***************
+*** 2141,2146 ****
+--- 2178,2185 ----
+ if(error_mess){
+ q_status_message(SM_ORDER | SM_DING, 4, 7, error_mess);
+ dprint((1, "call_mailer ERROR: %s\n", error_mess));
++ if (ps_global->send_immediately)
++ printf("%s\n",error_mess);
+ }
+
+ return(-1);
+diff -rc alpine-2.00/pith/send.h alpine-2.00.I.USE/pith/send.h
+*** alpine-2.00/pith/send.h 2008-06-30 15:03:35.000000000 -0700
+--- alpine-2.00.I.USE/pith/send.h 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 158,163 ****
+--- 158,165 ----
+ unsigned text_written:1;
+ };
+
++ #define CAN_EDIT(x) (!((x)->never_allow_changing_from) && \
++ F_ON(F_ALLOW_CHANGING_FROM, (x)))
+
+ #define TONAME "To"
+ #define CCNAME "cc"
+diff -rc alpine-2.00/pith/sort.c alpine-2.00.I.USE/pith/sort.c
+*** alpine-2.00/pith/sort.c 2008-07-09 22:01:13.000000000 -0700
+--- alpine-2.00.I.USE/pith/sort.c 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 29,35 ****
+ #include "../pith/signal.h"
+ #include "../pith/busy.h"
+ #include "../pith/icache.h"
+!
+
+ /*
+ * global place to store mail_sort and mail_thread results
+--- 29,35 ----
+ #include "../pith/signal.h"
+ #include "../pith/busy.h"
+ #include "../pith/icache.h"
+! #include "../pith/rules.h"
+
+ /*
+ * global place to store mail_sort and mail_thread results
+***************
+*** 90,96 ****
+ ----*/
+ void
+ sort_folder(MAILSTREAM *stream, MSGNO_S *msgmap, SortOrder new_sort,
+! int new_rev, unsigned int flags)
+ {
+ long raw_current, i, j;
+ unsigned long *sort = NULL;
+--- 90,96 ----
+ ----*/
+ void
+ sort_folder(MAILSTREAM *stream, MSGNO_S *msgmap, SortOrder new_sort,
+! int new_rev, unsigned int flags, int first)
+ {
+ long raw_current, i, j;
+ unsigned long *sort = NULL;
+***************
+*** 100,105 ****
+--- 100,114 ----
+ int current_rev;
+ MESSAGECACHE *mc;
+
++ if (first){
++ if (new_sort == SortThread)
++ find_msgmap(stream, msgmap, flags,
++ ps_global->thread_cur_sort, new_rev);
++ else
++ sort_folder(stream, msgmap, new_sort, new_rev, flags, 0);
++ return;
++ }
++
+ dprint((2, "Sorting by %s%s\n",
+ sort_name(new_sort), new_rev ? "/reverse" : ""));
+
+***************
+*** 529,548 ****
+ * argument also means arrival/reverse.
+ */
+ int
+! decode_sort(char *sort_spec, SortOrder *def_sort, int *def_sort_rev)
+ {
+ char *sep;
+ char *fix_this = NULL;
+! int x, reverse;
+
+ if(!sort_spec || !*sort_spec){
+! *def_sort = SortArrival;
+ *def_sort_rev = 0;
+ return(0);
+ }
+
+ if(struncmp(sort_spec, "reverse", strlen(sort_spec)) == 0){
+! *def_sort = SortArrival;
+ *def_sort_rev = 1;
+ return(0);
+ }
+--- 538,557 ----
+ * argument also means arrival/reverse.
+ */
+ int
+! decode_sort(char *sort_spec, SortOrder *def_sort, int *def_sort_rev, int thread)
+ {
+ char *sep;
+ char *fix_this = NULL;
+! int x = 0, reverse;
+
+ if(!sort_spec || !*sort_spec){
+! *def_sort = thread ? SortThread : SortArrival;
+ *def_sort_rev = 0;
+ return(0);
+ }
+
+ if(struncmp(sort_spec, "reverse", strlen(sort_spec)) == 0){
+! *def_sort = thread ? SortThread : SortArrival;
+ *def_sort_rev = 1;
+ return(0);
+ }
+***************
+*** 571,577 ****
+ if(ps_global->sort_types[x] == EndofList)
+ return(-1);
+
+! *def_sort = ps_global->sort_types[x];
+ *def_sort_rev = reverse;
+ return(0);
+ }
+--- 580,586 ----
+ if(ps_global->sort_types[x] == EndofList)
+ return(-1);
+
+! *def_sort = ps_global->sort_types[x];
+ *def_sort_rev = reverse;
+ return(0);
+ }
+***************
+*** 685,694 ****
+ PAT_S *pat;
+ SortOrder the_sort_order;
+ int sort_is_rev;
+!
+ /* set default order */
+ the_sort_order = ps_global->def_sort;
+! sort_is_rev = ps_global->def_sort_rev;
+
+ if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){
+ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
+--- 694,719 ----
+ PAT_S *pat;
+ SortOrder the_sort_order;
+ int sort_is_rev;
+! char *rule_result;
+! SortOrder new_sort = EndofList;
+! int is_rev;
+!
+! rule_result = get_rule_result(FOR_SORT, ps_global->cur_folder, V_SORT_RULES);
+! if (rule_result && *rule_result){
+! new_sort = (SortOrder) translate(rule_result, 1);
+! is_rev = (SortOrder) translate(rule_result, 0) == EndofList ? 0 : 1;
+! fs_give((void **)&rule_result);
+! }
+! if (new_sort != EndofList){
+! the_sort_order = new_sort;
+! sort_is_rev = is_rev;
+! }
+! else{
+ /* set default order */
+ the_sort_order = ps_global->def_sort;
+! sort_is_rev = the_sort_order == SortThread
+! ? (ps_global->thread_def_sort_rev + ps_global->def_sort_rev) % 2
+! : ps_global->def_sort_rev;
+
+ if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){
+ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
+***************
+*** 701,709 ****
+ && pat->action->sort_is_set){
+ the_sort_order = pat->action->sortorder;
+ sort_is_rev = pat->action->revsort;
+ }
+ }
+
+ sort_folder(ps_global->mail_stream, ps_global->msgmap,
+! the_sort_order, sort_is_rev, flags);
+ }
+--- 726,776 ----
+ && pat->action->sort_is_set){
+ the_sort_order = pat->action->sortorder;
+ sort_is_rev = pat->action->revsort;
++ sort_is_rev = the_sort_order == SortThread
++ ? (ps_global->thread_def_sort_rev + pat->action->revsort) % 2
++ : pat->action->revsort;
+ }
+ }
++ }
++ if(the_sort_order == SortThread && !(flags & SRT_MAN))
++ ps_global->thread_cur_sort = ps_global->thread_def_sort;
+
+ sort_folder(ps_global->mail_stream, ps_global->msgmap,
+! the_sort_order, sort_is_rev, flags, 1);
+! }
+!
+! SortOrder translate(char *order, int is_rev)
+! {
+! int rev = 0;
+! if (!strncmp(order,"tHread", 6)
+! || (rev = !strncmp(order,"Reverse tHread", 14)))
+! return is_rev || rev ? SortThread : EndofList;
+! if (!strncmp(order,"OrderedSubj", 11)
+! || (rev = !strncmp(order,"Reverse OrderedSubj", 19)))
+! return is_rev || rev ? SortSubject2 : EndofList;
+! if (!strncmp(order,"Subject", 7)
+! || (rev = !strncmp(order,"Reverse SortSubject", 15)))
+! return is_rev || rev ? SortSubject : EndofList;
+! if (!strncmp(order,"Arrival", 7)
+! || (rev = !strncmp(order,"Reverse Arrival", 15)))
+! return is_rev || rev ? SortArrival : EndofList;
+! if (!strncmp(order,"From", 4)
+! || (rev = !strncmp(order,"Reverse From", 12)))
+! return is_rev || rev ? SortFrom : EndofList;
+! if (!strncmp(order,"To", 2)
+! || (rev = !strncmp(order,"Reverse To", 10)))
+! return is_rev || rev ? SortTo : EndofList;
+! if (!strncmp(order,"Cc", 2)
+! || (rev = !strncmp(order,"Reverse Cc", 10)))
+! return is_rev || rev ? SortCc : EndofList;
+! if (!strncmp(order,"Date", 4)
+! || (rev = !strncmp(order,"Reverse Date", 12)))
+! return is_rev || rev ? SortDate : EndofList;
+! if (!strncmp(order,"siZe", 4)
+! || (rev = !strncmp(order,"Reverse siZe", 12)))
+! return is_rev || rev ? SortSize : EndofList;
+! if (!strncmp(order,"scorE", 5)
+! || (rev = !strncmp(order,"Reverse scorE", 13)))
+! return is_rev || rev ? SortScore : EndofList;
+! return EndofList;
+ }
+diff -rc alpine-2.00/pith/sort.h alpine-2.00.I.USE/pith/sort.h
+*** alpine-2.00/pith/sort.h 2006-09-22 13:06:05.000000000 -0700
+--- alpine-2.00.I.USE/pith/sort.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 22,28 ****
+
+
+ #define refresh_sort(S,M,F) sort_folder((S), (M), mn_get_sort(M), \
+! mn_get_revsort(M), (F))
+
+ struct global_sort_data {
+ MSGNO_S *msgmap;
+--- 22,28 ----
+
+
+ #define refresh_sort(S,M,F) sort_folder((S), (M), mn_get_sort(M), \
+! mn_get_revsort(M), (F), 1)
+
+ struct global_sort_data {
+ MSGNO_S *msgmap;
+***************
+*** 41,49 ****
+
+ /* exported protoypes */
+ char *sort_name(SortOrder);
+! void sort_folder(MAILSTREAM *, MSGNO_S *, SortOrder, int, unsigned);
+! int decode_sort(char *, SortOrder *, int *);
+ void reset_sort_order(unsigned);
+!
+
+ #endif /* PITH_SORT_INCLUDED */
+--- 41,49 ----
+
+ /* exported protoypes */
+ char *sort_name(SortOrder);
+! void sort_folder(MAILSTREAM *, MSGNO_S *, SortOrder, int, unsigned, int);
+! int decode_sort(char *, SortOrder *, int *, int);
+ void reset_sort_order(unsigned);
+! SortOrder translate(char *, int);
+
+ #endif /* PITH_SORT_INCLUDED */
+diff -rc alpine-2.00/pith/state.c alpine-2.00.I.USE/pith/state.c
+*** alpine-2.00/pith/state.c 2008-06-03 15:31:05.000000000 -0700
+--- alpine-2.00.I.USE/pith/state.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 32,38 ****
+ #include "../pith/remote.h"
+ #include "../pith/list.h"
+ #include "../pith/smime.h"
+!
+
+ /*
+ * Globals referenced throughout pine...
+--- 32,38 ----
+ #include "../pith/remote.h"
+ #include "../pith/list.h"
+ #include "../pith/smime.h"
+! #include "../pith/rules.h"
+
+ /*
+ * Globals referenced throughout pine...
+***************
+*** 73,78 ****
+--- 73,79 ----
+
+ p = (struct pine *)fs_get(sizeof (struct pine));
+ memset((void *) p, 0, sizeof(struct pine));
++ p->thread_def_sort = SortDate;
+ p->def_sort = SortArrival;
+ p->sort_types[0] = SortSubject;
+ p->sort_types[1] = SortArrival;
+***************
+*** 115,120 ****
+--- 116,124 ----
+ if(!(pps && (*pps)))
+ return;
+
++ if((*pps)->subject != NULL)
++ fs_give((void **)&(*pps)->subject);
++
+ if((*pps)->hostname != NULL)
+ fs_give((void **)&(*pps)->hostname);
+
+***************
+*** 130,135 ****
+--- 134,142 ----
+ if((*pps)->folders_dir != NULL)
+ fs_give((void **)&(*pps)->folders_dir);
+
++ if((*pps)->paterror == 0)
++ regfree(&(*pps)->colorpat);
++
+ if((*pps)->ui.homedir)
+ fs_give((void **)&(*pps)->ui.homedir);
+
+***************
+*** 182,187 ****
+--- 189,197 ----
+ if((*pps)->hdr_colors)
+ free_spec_colors(&(*pps)->hdr_colors);
+
++ if((*pps)->index_token_colors)
++ free_spec_colors(&(*pps)->index_token_colors);
++
+ if((*pps)->keywords)
+ free_keyword_list(&(*pps)->keywords);
+
+***************
+*** 202,207 ****
+--- 212,220 ----
+ if((*pps)->msgmap)
+ msgno_give(&(*pps)->msgmap);
+
++ if((*pps)->rule_list)
++ free_parsed_rule_list(&(*pps)->rule_list);
++
+ free_vars(*pps);
+
+ fs_give((void **) pps);
+diff -rc alpine-2.00/pith/state.h alpine-2.00.I.USE/pith/state.h
+*** alpine-2.00/pith/state.h 2008-06-03 08:54:15.000000000 -0700
+--- alpine-2.00.I.USE/pith/state.h 2011-02-07 20:33:47.000000000 -0800
+***************
+*** 32,38 ****
+ #include "../pith/stream.h"
+ #include "../pith/color.h"
+ #include "../pith/user.h"
+!
+
+ /*
+ * Printing control structure
+--- 32,38 ----
+ #include "../pith/stream.h"
+ #include "../pith/color.h"
+ #include "../pith/user.h"
+! #include "../pith/rulestype.h"
+
+ /*
+ * Printing control structure
+***************
+*** 104,112 ****
+--- 104,118 ----
+ MAILSTREAM *mail_stream; /* ptr to current folder stream */
+ MSGNO_S *msgmap; /* ptr to current message map */
+
++ char screen_name[10]; /* name of current screen */
++ char *role; /* role used when composing */
++ char *procid; /* procedure id when needed */
++ int exiting;
++
+ unsigned read_predicted:1;
+
+ char cur_folder[MAXPATH+1];
++ QUOTALIST *quota;
+ char last_unambig_folder[MAXPATH+1];
+ char last_save_folder[MAXPATH+1];
+ CONTEXT_S *last_save_context;
+***************
+*** 122,127 ****
+--- 128,134 ----
+ unsigned mangled_header:1; /* header needs repainting */
+ unsigned mangled_body:1; /* body of screen needs repainting */
+ unsigned mangled_screen:1; /* whole screen needs repainting */
++ unsigned resize_for_pico:1; /* screen needs repainting due to resizing */
+
+ unsigned in_init_seq:1; /* executing initial cmd list */
+ unsigned save_in_init_seq:1;
+***************
+*** 135,140 ****
+--- 142,149 ----
+ unsigned unseen_in_view:1;
+ unsigned start_in_context:1; /* start fldr_scrn in current cntxt */
+ unsigned def_sort_rev:1; /* true if reverse sort is default */
++ unsigned thread_def_sort_rev:1; /* true if reverse sort is default in thread screen */
++ unsigned msgmap_thread_def_sort_rev:1; /* true if reverse sort is being used in thread screen */
+ unsigned restricted:1;
+
+ unsigned save_msg_rule:5;
+***************
+*** 168,173 ****
+--- 177,183 ----
+ unsigned intr_pending:1; /* received SIGINT and haven't acted */
+ unsigned expunge_in_progress:1; /* don't want to re-enter c-client */
+ unsigned never_allow_changing_from:1; /* not even for roles */
++ unsigned newthread:1; /* start a new thread on composing */
+
+ unsigned readonly_pinerc:1;
+ unsigned view_all_except:1;
+***************
+*** 239,249 ****
+--- 249,272 ----
+ char **feat_list_back_compat;
+
+ SPEC_COLOR_S *hdr_colors; /* list of configed colors for view */
++ SPEC_COLOR_S *index_token_colors; /* list of configed colors for index */
+
++ char *prefix; /* prefix for fillpara */
+ short init_context;
+
++ struct {
++ ACTION_S *role_chosen;
++ int attach;
++ int strip;
++ int no_send_flowed;
++ int inchdr;
++ } reply;
++
+ int *initial_cmds; /* cmds to execute on startup */
+ int *free_initial_cmds; /* used to free when done */
++ int *initial_cmds_backup; /* keep a copy in case they are freed */
++ int *free_initial_cmds_backup; /* free the copy */
++ int initial_cmds_offset; /* how many commands we have executed */
+
+ char c_client_error[300]; /* when nowhow_error is set and PARSE */
+
+***************
+*** 281,288 ****
+--- 304,316 ----
+ EditWhich ew_for_srch_take;
+
+ SortOrder def_sort, /* Default sort type */
++ thread_def_sort, /* Default Sort Type in Thread Screen */
++ thread_cur_sort, /* current sort style for threads */
++ msgmap_thread_sort,
+ sort_types[22];
+
++ int preserve;
++
+ int last_expire_year, last_expire_month;
+
+ int printer_category;
+***************
+*** 295,300 ****
+--- 323,332 ----
+
+ int nmw_width;
+
++ char *subject;
++ int send_immediately;
++ int failed_read;
++
+ int hours_to_timeout;
+
+ int tcp_query_timeout;
+***************
+*** 317,322 ****
+--- 349,356 ----
+ char *display_charmap; /* needs to be freed */
+ char *keyboard_charmap; /* needs to be freed */
+ void *input_cs;
++ regex_t colorpat;
++ int paterror;
+
+ char *posting_charmap; /* needs to be freed */
+
+***************
+*** 328,333 ****
+--- 362,368 ----
+ struct {
+ char *(*display_filter)(char *, STORE_S *, gf_io_t, FILTLIST_S *);
+ char *(*display_filter_trigger)(BODY *, char *, size_t);
++ char *(*exec_rule)(char *, gf_io_t, gf_io_t);
+ } tools;
+
+ KEYWORD_S *keywords;
+***************
+*** 338,343 ****
+--- 373,381 ----
+ char last_error[500];
+ INIT_ERR_S *init_errs;
+
++ PRULELIST_S *rule_list;
++ char *pressed_key;
++
+ PRINT_S *print;
+
+ #ifdef SMIME
+diff -rc alpine-2.00/pith/store.c alpine-2.00.I.USE/pith/store.c
+*** alpine-2.00/pith/store.c 2008-06-03 12:27:23.000000000 -0700
+--- alpine-2.00.I.USE/pith/store.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 170,175 ****
+--- 170,183 ----
+ if(source == TmpFileStar)
+ our_unlink(so->name);
+
++ if (ps_global->send_immediately){
++ ps_global->failed_read++;
++ if(ps_global->failed_read == 5){
++ printf("No configurationf file found. Where is your .pinerc file?\n");
++ exit(1);
++ }
++ }
++
+ fs_give((void **)&so->name);
+ fs_give((void **)&so); /* so freed & set to NULL */
+ }
+diff -rc alpine-2.00/pith/stream.c alpine-2.00.I.USE/pith/stream.c
+*** alpine-2.00/pith/stream.c 2008-03-25 11:57:53.000000000 -0700
+--- alpine-2.00.I.USE/pith/stream.c 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 3318,3323 ****
+--- 3318,3342 ----
+ }
+
+
++ /* Some stream is locked checks to see if there is any stream for which we
++ * are in a callback from c-client
++ */
++
++ int
++ some_stream_is_locked(void)
++ {
++ int rv = 0, i;
++ MAILSTREAM *m;
++
++ for(i = 0; rv == 0 && i < ps_global->s_pool.nstream; i++){
++ m = ps_global->s_pool.streams[i];
++ if(m && m->lock)
++ rv++;
++ }
++
++ return(rv);
++ }
++
+ /*
+ * Very simple version of appenduid_cb until we need something
+ * more complex.
+diff -rc alpine-2.00/pith/stream.h alpine-2.00.I.USE/pith/stream.h
+*** alpine-2.00/pith/stream.h 2007-06-15 16:23:02.000000000 -0700
+--- alpine-2.00.I.USE/pith/stream.h 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 460,465 ****
+--- 460,466 ----
+ int is_imap_stream(MAILSTREAM *);
+ int modern_imap_stream(MAILSTREAM *);
+ int streams_died(void);
++ int some_stream_is_locked(void);
+ void appenduid_cb(char *mailbox,unsigned long uidvalidity, SEARCHSET *set);
+ imapuid_t get_last_append_uid(void);
+ MAILSTREAM *mail_cmd_stream(CONTEXT_S *, int *);
+diff -rc alpine-2.00/pith/string.c alpine-2.00.I.USE/pith/string.c
+*** alpine-2.00/pith/string.c 2008-01-09 12:45:31.000000000 -0800
+--- alpine-2.00.I.USE/pith/string.c 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 19,24 ****
+--- 19,25 ----
+ string.c
+ Misc extra and useful string functions
+ - rplstr replace a substring with another string
++ - collspaces consecutive spaces are reduced to one space.
+ - sqzspaces Squeeze out the extra blanks in a string
+ - sqznewlines Squeeze out \n and \r.
+ - removing_trailing_white_space
+***************
+*** 131,136 ****
+--- 132,162 ----
+ return(x3);
+ }
+
++ /*----------------------------------------------------------------------
++ collapse blank space
++ ----------------------------------------------------------------------*/
++ void
++ collspaces(char *string)
++ {
++ char *p = string;
++ int only_one_space = 0;
++
++ if(!string)
++ return;
++
++ for(;isspace(*p); p++);
++
++ while(*string = *p++)
++ if(!isspace((unsigned char)*string)){
++ only_one_space = 0;
++ string++;
++ }
++ else if(!only_one_space){
++ string++;
++ only_one_space++;
++ }
++ *string = '\0';
++ }
+
+
+ /*----------------------------------------------------------------------
+***************
+*** 2859,2861 ****
+--- 2885,2919 ----
+ fs_give((void **) strp);
+ }
+ }
++
++
++ void
++ removing_extra_stuff(string)
++ char *string;
++ {
++ char *p = NULL;
++ int change = 0, length = 0;
++
++
++ if(!string)
++ return;
++
++ for(; *string; string++, length++)
++ p = ((unsigned char)*string != ',') ? NULL : (!p) ? string : p;
++
++ if(p)
++ *p = '\0';
++
++ string -= length;
++ for (; *string; string++){
++ if (change){
++ *string = ' ';
++ change = 0;
++ }
++ if ((((unsigned char)*string == ' ') ||
++ ((unsigned char)*string == ',')) &&
++ ((unsigned char)*(string + 1) == ','))
++ change++;
++ }
++ }
++
+diff -rc alpine-2.00/pith/string.h alpine-2.00.I.USE/pith/string.h
+*** alpine-2.00/pith/string.h 2007-08-15 13:28:09.000000000 -0700
+--- alpine-2.00.I.USE/pith/string.h 2011-02-07 20:33:42.000000000 -0800
+***************
+*** 85,96 ****
+--- 85,98 ----
+
+ /* exported protoypes */
+ char *rplstr(char *, size_t, int, char *);
++ void collspaces(char *);
+ void sqzspaces(char *);
+ void sqznewlines(char *);
+ void removing_leading_white_space(char *);
+ void removing_trailing_white_space(char *);
+ void removing_leading_and_trailing_white_space(char *);
+ int removing_double_quotes(char *);
++ void removing_extra_stuff (char *);
+ char *skip_white_space(char *);
+ char *skip_to_white_space(char *);
+ char *removing_quotes(char *);
+diff -rc alpine-2.00/pith/text.c alpine-2.00.I.USE/pith/text.c
+*** alpine-2.00/pith/text.c 2008-03-18 10:24:31.000000000 -0700
+--- alpine-2.00.I.USE/pith/text.c 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 91,97 ****
+ char *err, *charset;
+ int filtcnt = 0, error_found = 0, column, wrapit;
+ int is_in_sig = OUT_SIG_BLOCK;
+! int is_flowed_msg = 0;
+ int is_delsp_yes = 0;
+ int filt_only_c0 = 0;
+ char *parmval;
+--- 91,97 ----
+ char *err, *charset;
+ int filtcnt = 0, error_found = 0, column, wrapit;
+ int is_in_sig = OUT_SIG_BLOCK;
+! int is_flowed_msg = 0, add_me = 1, doraw = RAWSTRING;
+ int is_delsp_yes = 0;
+ int filt_only_c0 = 0;
+ char *parmval;
+***************
+*** 170,175 ****
+--- 170,184 ----
+ gf_url_hilite_opt(&uh,handlesp,0));
+ }
+
++ if((flags & FM_DISPLAY)
++ && !(flags & FM_NOCOLOR)
++ && pico_usingcolor()
++ && VAR_SPECIAL_TEXT_FORE_COLOR
++ && VAR_SPECIAL_TEXT_BACK_COLOR){
++ filters[filtcnt].filter = gf_line_test;
++ filters[filtcnt++].data = gf_line_test_opt(color_this_text, NULL);
++ }
++
+ /*
+ * First, paint the signature.
+ * Disclaimers noted below for coloring quotes apply here as well.
+***************
+*** 179,185 ****
+ && pico_usingcolor()
+ && VAR_SIGNATURE_FORE_COLOR
+ && VAR_SIGNATURE_BACK_COLOR){
+! filters[filtcnt].filter = gf_line_test;
+ filters[filtcnt++].data = gf_line_test_opt(color_signature,
+ &is_in_sig);
+ }
+--- 188,194 ----
+ && pico_usingcolor()
+ && VAR_SIGNATURE_FORE_COLOR
+ && VAR_SIGNATURE_BACK_COLOR){
+! filters[filtcnt].filter = gf_quote_test;
+ filters[filtcnt++].data = gf_line_test_opt(color_signature,
+ &is_in_sig);
+ }
+***************
+*** 197,205 ****
+ && pico_usingcolor()
+ && VAR_QUOTE1_FORE_COLOR
+ && VAR_QUOTE1_BACK_COLOR){
+! filters[filtcnt].filter = gf_line_test;
+! filters[filtcnt++].data = gf_line_test_opt(color_a_quote,
+! &is_flowed_msg);
+ }
+ }
+ else if(!strucmp(att->body->subtype, "richtext")){
+--- 206,214 ----
+ && pico_usingcolor()
+ && VAR_QUOTE1_FORE_COLOR
+ && VAR_QUOTE1_BACK_COLOR){
+! add_me = 0;
+! filters[filtcnt].filter = gf_quote_test;
+! filters[filtcnt++].data = gf_line_test_opt(color_a_quote, &is_flowed_msg);
+ }
+ }
+ else if(!strucmp(att->body->subtype, "richtext")){
+***************
+*** 280,285 ****
+--- 289,299 ----
+ }
+ }
+
++ if (add_me){
++ filters[filtcnt].filter = gf_quote_test;
++ filters[filtcnt++].data = gf_line_test_opt(select_quote, &doraw);
++ }
++
+ /*
+ * If the message is not flowed, we do the quote suppression before
+ * the wrapping, because the wrapping does not preserve the quote
+***************
+*** 304,310 ****
+ dq.handlesp = handlesp;
+ dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor());
+
+! filters[filtcnt].filter = gf_line_test;
+ filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
+ }
+ if(ps_global->VAR_QUOTE_REPLACE_STRING
+--- 318,324 ----
+ dq.handlesp = handlesp;
+ dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor());
+
+! filters[filtcnt].filter = gf_quote_test;
+ filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
+ }
+ if(ps_global->VAR_QUOTE_REPLACE_STRING
+***************
+*** 363,369 ****
+ dq.handlesp = handlesp;
+ dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor());
+
+! filters[filtcnt].filter = gf_line_test;
+ filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
+ }
+
+--- 377,383 ----
+ dq.handlesp = handlesp;
+ dq.do_color = (!(flags & FM_NOCOLOR) && pico_usingcolor());
+
+! filters[filtcnt].filter = gf_quote_test;
+ filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
+ }
+
+***************
+*** 568,574 ****
+ {
+ DELQ_S *dq;
+ char *lp;
+! int i, lines, not_a_quote = 0;
+ size_t len;
+
+ dq = (DELQ_S *) local;
+--- 582,588 ----
+ {
+ DELQ_S *dq;
+ char *lp;
+! int i, lines, not_a_quote = 0, code;
+ size_t len;
+
+ dq = (DELQ_S *) local;
+***************
+*** 588,593 ****
+--- 602,609 ----
+ for(i = dq->indent_length; i > 0 && !not_a_quote && *lp; i--)
+ if(*lp++ != SPACE)
+ not_a_quote++;
++ while(isspace((unsigned char) *lp))
++ lp++;
+
+ /* skip over leading tags */
+ while(!not_a_quote
+***************
+*** 627,639 ****
+ }
+ }
+
+! /* skip over whitespace */
+! if(!dq->is_flowed)
+! while(isspace((unsigned char) *lp))
+! lp++;
+!
+! /* check first character to see if it is a quote */
+! if(!not_a_quote && *lp != '>')
+ not_a_quote++;
+
+ if(not_a_quote){
+--- 643,654 ----
+ }
+ }
+
+! len = lp - line;
+! if(strlen(tmp_20k_buf) > len)
+! strcpy(tmp_20k_buf, tmp_20k_buf+len);
+! code = (dq->is_flowed ? IS_FLOWED : NO_FLOWED) | DELETEQUO;
+! select_quote(linenum, lp, ins, &code);
+! if (!not_a_quote && !tmp_20k_buf[0])
+ not_a_quote++;
+
+ if(not_a_quote){
+diff -rc alpine-2.00/pith/thread.c alpine-2.00.I.USE/pith/thread.c
+*** alpine-2.00/pith/thread.c 2008-03-03 09:52:11.000000000 -0800
+--- alpine-2.00.I.USE/pith/thread.c 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 29,40 ****
+ #include "../pith/mailcmd.h"
+ #include "../pith/ablookup.h"
+
+
+ /*
+ * Internal prototypes
+ */
+ long *sort_thread_flatten(THREADNODE *, MAILSTREAM *, long *,
+! char *, long, PINETHRD_S *, unsigned);
+ void make_thrdflags_consistent(MAILSTREAM *, MSGNO_S *, PINETHRD_S *, int);
+ THREADNODE *collapse_threadnode_tree(THREADNODE *);
+ THREADNODE *collapse_threadnode_tree_sorted(THREADNODE *);
+--- 29,41 ----
+ #include "../pith/mailcmd.h"
+ #include "../pith/ablookup.h"
+
++ static int erase_thread_info = 1;
+
+ /*
+ * Internal prototypes
+ */
+ long *sort_thread_flatten(THREADNODE *, MAILSTREAM *, long *,
+! char *, long, PINETHRD_S *, unsigned, int, long, long);
+ void make_thrdflags_consistent(MAILSTREAM *, MSGNO_S *, PINETHRD_S *, int);
+ THREADNODE *collapse_threadnode_tree(THREADNODE *);
+ THREADNODE *collapse_threadnode_tree_sorted(THREADNODE *);
+***************
+*** 94,113 ****
+ set_flags_for_thread(MAILSTREAM *stream, MSGNO_S *msgmap, int f, PINETHRD_S *thrd, int v)
+ {
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!(stream && thrd && msgmap))
+ return;
+
+ set_lflag(stream, msgmap, mn_raw2m(msgmap, thrd->rawno), f, v);
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_flags_for_thread(stream, msgmap, f, nthrd, v);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ set_flags_for_thread(stream, msgmap, f, bthrd, v);
+ }
+--- 95,116 ----
+ set_flags_for_thread(MAILSTREAM *stream, MSGNO_S *msgmap, int f, PINETHRD_S *thrd, int v)
+ {
+ PINETHRD_S *nthrd, *bthrd;
++ unsigned long next = 0L, branch = 0L;
+
+ if(!(stream && thrd && msgmap))
+ return;
+
+ set_lflag(stream, msgmap, mn_raw2m(msgmap, thrd->rawno), f, v);
+
+! if(next = get_next(stream,thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ set_flags_for_thread(stream, msgmap, f, nthrd, v);
+ }
+
+!
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ set_flags_for_thread(stream, msgmap, f, bthrd, v);
+ }
+***************
+*** 121,127 ****
+ MESSAGECACHE *mc;
+ PINELT_S *peltp;
+
+! if(!(stream && stream->spare))
+ return;
+
+ ps_global->view_skipped_index = 0;
+--- 124,130 ----
+ MESSAGECACHE *mc;
+ PINELT_S *peltp;
+
+! if(!(stream && stream->spare) || !erase_thread_info)
+ return;
+
+ ps_global->view_skipped_index = 0;
+***************
+*** 154,160 ****
+ PINETHRD_S *thrd = NULL;
+ unsigned long msgno, rawno;
+ int un_view_thread = 0;
+! long raw_current;
+ char *dup_chk = NULL;
+
+
+--- 157,163 ----
+ PINETHRD_S *thrd = NULL;
+ unsigned long msgno, rawno;
+ int un_view_thread = 0;
+! long raw_current, branch;
+ char *dup_chk = NULL;
+
+
+***************
+*** 167,176 ****
+ * way. If the dummy node is at the top-level, then its children are
+ * promoted to the top-level as separate threads.
+ */
+! if(F_ON(F_THREAD_SORTS_BY_ARRIVAL, ps_global))
+! collapsed_tree = collapse_threadnode_tree_sorted(tree);
+! else
+! collapsed_tree = collapse_threadnode_tree(tree);
+
+ /* dup_chk is like sort with an origin of 1 */
+ dup_chk = (char *) fs_get((mn_get_nmsgs(g_sort.msgmap)+1) * sizeof(char));
+--- 170,180 ----
+ * way. If the dummy node is at the top-level, then its children are
+ * promoted to the top-level as separate threads.
+ */
+! collapsed_tree = F_ON(F_ENHANCED_THREAD, ps_global)
+! ? copy_tree(tree)
+! : (F_ON(F_THREAD_SORTS_BY_ARRIVAL, ps_global)
+! ? collapse_threadnode_tree_sorted(tree)
+! : collapse_threadnode_tree(tree));
+
+ /* dup_chk is like sort with an origin of 1 */
+ dup_chk = (char *) fs_get((mn_get_nmsgs(g_sort.msgmap)+1) * sizeof(char));
+***************
+*** 181,187 ****
+ (void) sort_thread_flatten(collapsed_tree, stream,
+ &g_sort.msgmap->sort[1],
+ dup_chk, mn_get_nmsgs(g_sort.msgmap),
+! NULL, THD_TOP);
+
+ /* reset the inverse array */
+ msgno_reset_isort(g_sort.msgmap);
+--- 185,191 ----
+ (void) sort_thread_flatten(collapsed_tree, stream,
+ &g_sort.msgmap->sort[1],
+ dup_chk, mn_get_nmsgs(g_sort.msgmap),
+! NULL, THD_TOP, 0, 1L, 0L);
+
+ /* reset the inverse array */
+ msgno_reset_isort(g_sort.msgmap);
+***************
+*** 339,350 ****
+ else{
+ thrd = fetch_head_thread(stream);
+ while(thrd){
+ /*
+ * The top-level threads aren't hidden by collapse.
+ */
+ msgno = mn_raw2m(g_sort.msgmap, thrd->rawno);
+! if(msgno)
+! set_lflag(stream, g_sort.msgmap, msgno, MN_CHID, 0);
+
+ if(thrd->next){
+ PINETHRD_S *nthrd;
+--- 343,356 ----
+ else{
+ thrd = fetch_head_thread(stream);
+ while(thrd){
++ unsigned long raw = thrd->rawno;
++ unsigned long top = top_thread(stream, raw);
+ /*
+ * The top-level threads aren't hidden by collapse.
+ */
+ msgno = mn_raw2m(g_sort.msgmap, thrd->rawno);
+! if(msgno && !get_lflag(stream, NULL,thrd->rawno, MN_COLL))
+! set_lflag(stream, g_sort.msgmap, msgno, MN_CHID, 0);
+
+ if(thrd->next){
+ PINETHRD_S *nthrd;
+***************
+*** 358,366 ****
+ MN_COLL));
+ }
+
+! if(thrd->nextthd)
+! thrd = fetch_thread(stream, thrd->nextthd);
+! else
+ thrd = NULL;
+ }
+ }
+--- 364,373 ----
+ MN_COLL));
+ }
+
+! while (thrd && top_thread(stream, thrd->rawno) == top
+! && thrd->nextthd)
+! thrd = fetch_thread(stream, thrd->nextthd);
+! if (!(thrd && thrd->nextthd))
+ thrd = NULL;
+ }
+ }
+***************
+*** 411,417 ****
+ int a_parent_is_collapsed)
+ {
+ PINETHRD_S *nthrd, *bthrd;
+! unsigned long msgno;
+
+ if(!thrd)
+ return;
+--- 418,424 ----
+ int a_parent_is_collapsed)
+ {
+ PINETHRD_S *nthrd, *bthrd;
+! unsigned long msgno, next, branch;
+
+ if(!thrd)
+ return;
+***************
+*** 429,436 ****
+ set_lflag(stream, msgmap, msgno, MN_CHID, 0);
+ }
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ make_thrdflags_consistent(stream, msgmap, nthrd,
+ a_parent_is_collapsed
+--- 436,443 ----
+ set_lflag(stream, msgmap, msgno, MN_CHID, 0);
+ }
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ make_thrdflags_consistent(stream, msgmap, nthrd,
+ a_parent_is_collapsed
+***************
+*** 439,446 ****
+ MN_COLL));
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ make_thrdflags_consistent(stream, msgmap, bthrd,
+ a_parent_is_collapsed);
+--- 446,453 ----
+ MN_COLL));
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ make_thrdflags_consistent(stream, msgmap, bthrd,
+ a_parent_is_collapsed);
+***************
+*** 487,495 ****
+ long *
+ sort_thread_flatten(THREADNODE *node, MAILSTREAM *stream,
+ long *entry, char *dup_chk, long maxno,
+! PINETHRD_S *thrd, unsigned int flags)
+ {
+! PINETHRD_S *newthrd = NULL;
+
+ if(node){
+ if(node->num > 0L && node->num <= maxno){ /* holes happen */
+--- 494,503 ----
+ long *
+ sort_thread_flatten(THREADNODE *node, MAILSTREAM *stream,
+ long *entry, char *dup_chk, long maxno,
+! PINETHRD_S *thrd, unsigned int flags,
+! int adopted, long top, long threadno)
+ {
+! PINETHRD_S *newthrd = NULL, *save_thread = NULL;
+
+ if(node){
+ if(node->num > 0L && node->num <= maxno){ /* holes happen */
+***************
+*** 497,502 ****
+--- 505,513 ----
+ *entry = node->num;
+ dup_chk[node->num] = 1;
+
++ if(adopted == 2)
++ top = node->num;
++
+ /*
+ * Build a richer threading structure that will help us paint
+ * and operate on threads and subthreads.
+***************
+*** 505,524 ****
+ if(newthrd){
+ entry++;
+
+ if(node->next)
+ entry = sort_thread_flatten(node->next, stream,
+ entry, dup_chk, maxno,
+! newthrd, THD_NEXT);
+
+ if(node->branch)
+ entry = sort_thread_flatten(node->branch, stream,
+ entry, dup_chk, maxno,
+ newthrd,
+! (flags == THD_TOP) ? THD_TOP
+! : THD_BRANCH);
+ }
+ }
+ }
+ }
+
+ return(entry);
+--- 516,566 ----
+ if(newthrd){
+ entry++;
+
++ if(adopted == 2)
++ threadno = newthrd->thrdno;
++ if(adopted){
++ newthrd->toploose = top;
++ newthrd->thrdno = threadno;
++ }
++ adopted = adopted ? 1 : 0;
+ if(node->next)
+ entry = sort_thread_flatten(node->next, stream,
+ entry, dup_chk, maxno,
+! newthrd, THD_NEXT, adopted, top, threadno);
+
+ if(node->branch)
+ entry = sort_thread_flatten(node->branch, stream,
+ entry, dup_chk, maxno,
+ newthrd,
+! ((flags == THD_TOP) ? THD_TOP
+! : THD_BRANCH),
+! adopted, top, threadno);
+ }
+ }
+ }
++ else{
++ adopted = 2;
++ if(node->next)
++ entry = sort_thread_flatten(node->next, stream, entry, dup_chk,
++ maxno, thrd, THD_TOP, adopted, top, threadno);
++ adopted = 0;
++ if(node->branch){
++ if(entry){
++ long *last_entry = entry;
++
++ do{
++ last_entry--;
++ save_thread = ((PINELT_S *)mail_elt(stream, *last_entry)->sparep)->pthrd;
++ } while (save_thread->parent != 0L);
++ entry = sort_thread_flatten(node->branch, stream, entry, dup_chk,
++ maxno, save_thread, (flags == THD_TOP ? THD_TOP : THD_BRANCH),
++ adopted, top, threadno);
++ }
++ else
++ entry = sort_thread_flatten(node->branch, stream, entry, dup_chk,
++ maxno, NULL, THD_TOP, adopted, top, threadno);
++ }
++ }
+ }
+
+ return(entry);
+***************
+*** 787,793 ****
+ */
+ void
+ collapse_or_expand(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
+! long unsigned int msgno)
+ {
+ int collapsed, adjust_current = 0;
+ PINETHRD_S *thrd = NULL, *nthrd;
+--- 829,835 ----
+ */
+ void
+ collapse_or_expand(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
+! long unsigned int msgno, int display)
+ {
+ int collapsed, adjust_current = 0;
+ PINETHRD_S *thrd = NULL, *nthrd;
+***************
+*** 840,846 ****
+ if(!thrd)
+ return;
+
+! collapsed = get_lflag(stream, NULL, thrd->rawno, MN_COLL) && thrd->next;
+
+ if(collapsed){
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+--- 882,888 ----
+ if(!thrd)
+ return;
+
+! collapsed = this_thread_is_kolapsed(ps_global, stream, msgmap, thrd->rawno);
+
+ if(collapsed){
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+***************
+*** 858,870 ****
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+ if(msgno > 0L && msgno <= mn_get_total(msgmap)){
+ set_lflag(stream, msgmap, msgno, MN_COLL, 1);
+! if((nthrd = fetch_thread(stream, thrd->next)) != NULL)
+ set_thread_subtree(stream, nthrd, msgmap, 1, MN_CHID);
+
+ clear_index_cache_ent(stream, msgno, 0);
+ }
+ }
+! else
+ q_status_message(SM_ORDER, 0, 1,
+ _("No thread to collapse or expand on this line"));
+
+--- 900,912 ----
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+ if(msgno > 0L && msgno <= mn_get_total(msgmap)){
+ set_lflag(stream, msgmap, msgno, MN_COLL, 1);
+! if((thrd->next) && ((nthrd = fetch_thread(stream, thrd->next)) != NULL))
+ set_thread_subtree(stream, nthrd, msgmap, 1, MN_CHID);
+
+ clear_index_cache_ent(stream, msgno, 0);
+ }
+ }
+! else if(display)
+ q_status_message(SM_ORDER, 0, 1,
+ _("No thread to collapse or expand on this line"));
+
+***************
+*** 951,968 ****
+ unsigned long count = 0;
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ count += count_flags_in_thread(stream, nthrd, flags);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ count += count_flags_in_thread(stream, bthrd, flags);
+ }
+--- 993,1011 ----
+ unsigned long count = 0;
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
++ unsigned long next = 0L, branch = 0L;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ count += count_flags_in_thread(stream, nthrd, flags);
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ count += count_flags_in_thread(stream, bthrd, flags);
+ }
+***************
+*** 1050,1069 ****
+ mark_msgs_in_thread(MAILSTREAM *stream, PINETHRD_S *thrd, MSGNO_S *msgmap)
+ {
+ int count = 0;
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ count += mark_msgs_in_thread(stream, nthrd, msgmap);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ count += mark_msgs_in_thread(stream, bthrd, msgmap);
+ }
+--- 1093,1113 ----
+ mark_msgs_in_thread(MAILSTREAM *stream, PINETHRD_S *thrd, MSGNO_S *msgmap)
+ {
+ int count = 0;
++ long next, branch;
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ count += mark_msgs_in_thread(stream, nthrd, msgmap);
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ count += mark_msgs_in_thread(stream, bthrd, msgmap);
+ }
+***************
+*** 1097,1103 ****
+ /* flags to set or clear */
+ /* set or clear? */
+ {
+! unsigned long msgno;
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+--- 1141,1147 ----
+ /* flags to set or clear */
+ /* set or clear? */
+ {
+! unsigned long msgno, next, branch;
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+***************
+*** 1121,1134 ****
+ if(msgno > 0L && flags == MN_CHID2 && v == 1)
+ clear_index_cache_ent(stream, msgno, 0);
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_thread_lflags(stream, nthrd, msgmap, flags, v);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ set_thread_lflags(stream, bthrd, msgmap, flags, v);
+ }
+--- 1165,1178 ----
+ if(msgno > 0L && flags == MN_CHID2 && v == 1)
+ clear_index_cache_ent(stream, msgno, 0);
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ set_thread_lflags(stream, nthrd, msgmap, flags, v);
+ }
+
+! if(branch = get_branch(stream,thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ set_thread_lflags(stream, bthrd, msgmap, flags, v);
+ }
+***************
+*** 1217,1235 ****
+ char to_us = ' ';
+ char branch_to_us = ' ';
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return to_us;
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ to_us = to_us_symbol_for_thread(stream, nthrd, consider_flagged);
+ }
+
+ if(((consider_flagged && to_us != '*') || (!consider_flagged && to_us != '+'))
+! && thrd->branch){
+ bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ branch_to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged);
+--- 1261,1280 ----
+ char to_us = ' ';
+ char branch_to_us = ' ';
+ PINETHRD_S *nthrd, *bthrd;
++ unsigned long next = 0L, branch = 0L;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return to_us;
+
+! if(next = get_next(stream,thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ to_us = to_us_symbol_for_thread(stream, nthrd, consider_flagged);
+ }
+
+ if(((consider_flagged && to_us != '*') || (!consider_flagged && to_us != '+'))
+! && (branch = get_branch(stream, thrd))){
+ bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ branch_to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged);
+***************
+*** 1279,1285 ****
+ break;
+ }
+
+! if(to_us != '+' && resent_to_us(&idata))
+ to_us = '+';
+
+ if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global))
+--- 1324,1330 ----
+ break;
+ }
+
+! if(to_us != '+' && !idata.bogus && resent_to_us(&idata))
+ to_us = '+';
+
+ if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global))
+***************
+*** 1327,1333 ****
+
+ set_lflag(stream, msgmap, msgno, flags, v);
+
+! if(thrd->next && (hiding || !get_lflag(stream,NULL,thrd->rawno,MN_COLL))){
+ nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_thread_subtree(stream, nthrd, msgmap, v, flags);
+--- 1372,1379 ----
+
+ set_lflag(stream, msgmap, msgno, flags, v);
+
+! if(thrd->next
+! && (hiding || !get_lflag(stream,NULL,thrd->rawno,MN_COLL))){
+ nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_thread_subtree(stream, nthrd, msgmap, v, flags);
+***************
+*** 1367,1374 ****
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
+! if(thrd && thrd->top && thrd->top != thrd->rawno)
+! thrd = fetch_thread(stream, thrd->top);
+
+ if(!thrd)
+ return 0;
+--- 1413,1420 ----
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
+! if(thrd && thrd->top && top_thread(stream,thrd->top) != thrd->rawno)
+! thrd = fetch_thread(stream, top_thread(stream,thrd->top));
+
+ if(!thrd)
+ return 0;
+***************
+*** 1432,1438 ****
+ thrd = fetch_thread(stream, rawno);
+
+ if(thrd && thrd->top)
+! topthrd = fetch_thread(stream, thrd->top);
+
+ if(!topthrd)
+ return 0;
+--- 1478,1484 ----
+ thrd = fetch_thread(stream, rawno);
+
+ if(thrd && thrd->top)
+! topthrd = fetch_thread(stream, top_thread(stream,thrd->top));
+
+ if(!topthrd)
+ return 0;
+***************
+*** 1538,1543 ****
+--- 1584,1590 ----
+ set_search_bit_for_thread(MAILSTREAM *stream, PINETHRD_S *thrd, SEARCHSET **msgset)
+ {
+ PINETHRD_S *nthrd, *bthrd;
++ unsigned long next, branch;
+
+ if(!(stream && thrd))
+ return;
+***************
+*** 1546,1560 ****
+ && (!(msgset && *msgset) || in_searchset(*msgset, thrd->rawno)))
+ mm_searched(stream, thrd->rawno);
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_search_bit_for_thread(stream, nthrd, msgset);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ set_search_bit_for_thread(stream, bthrd, msgset);
+ }
+ }
+--- 1593,2185 ----
+ && (!(msgset && *msgset) || in_searchset(*msgset, thrd->rawno)))
+ mm_searched(stream, thrd->rawno);
+
+! if(next= get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ set_search_bit_for_thread(stream, nthrd, msgset);
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ set_search_bit_for_thread(stream, bthrd, msgset);
+ }
+ }
++
++ /*
++ * Make a copy of c-client's THREAD tree
++ */
++ THREADNODE *
++ copy_tree(THREADNODE *tree)
++ {
++ THREADNODE *newtree = NULL;
++
++ if(tree){
++ newtree = mail_newthreadnode(NULL);
++ newtree->num = tree->num;
++ if(tree->next)
++ newtree->next = copy_tree(tree->next);
++
++ if(tree->branch)
++ newtree->branch = copy_tree(tree->branch);
++ }
++ return(newtree);
++ }
++
++ long
++ top_thread(MAILSTREAM *stream, long rawmsgno)
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno;
++
++ if(!stream)
++ return -1L;
++
++ if(rawmsgno)
++ thrd = fetch_thread(stream, rawmsgno);
++
++ if(!thrd)
++ return -1L;
++
++ return F_ON(F_ENHANCED_THREAD, ps_global)
++ ? (thrd->toploose ? thrd->toploose : thrd->top)
++ : thrd->top;
++ }
++
++ void
++ move_top_thread(MAILSTREAM *stream, MSGNO_S *msgmap, long rawmsgno)
++ {
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream, rawmsgno)));
++ }
++
++ long
++ top_this_thread(MAILSTREAM *stream, long rawmsgno)
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno;
++
++ if(!stream)
++ return -1L;
++
++ if(rawmsgno)
++ thrd = fetch_thread(stream, rawmsgno);
++
++ if(!thrd)
++ return -1L;
++
++ return thrd->top;
++ }
++
++ void
++ move_top_this_thread(MAILSTREAM *stream, MSGNO_S *msgmap, long rawmsgno)
++ {
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top_this_thread(stream, rawmsgno)));
++ }
++
++ int
++ thread_is_kolapsed(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, long rawmsgno)
++ {
++ int collapsed;
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno, orig, orig_rawno;
++
++ if(!stream)
++ return -1;
++
++ orig = mn_get_cur(msgmap);
++ move_top_thread(stream, msgmap, rawmsgno);
++ rawno = orig_rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return -1;
++
++ while(collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno))
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_rawno != top_thread(stream, rawno)))
++ break;
++
++ mn_set_cur(msgmap,orig); /* return home */
++
++ return collapsed;
++ }
++
++ /* this function tells us if the thread (or branch in the case of loose threads)
++ * is collapsed
++ */
++
++ int
++ this_thread_is_kolapsed(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, long rawmsgno)
++ {
++ int collapsed;
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno, orig;
++
++ if(!stream)
++ return -1;
++
++ rawno = rawmsgno;
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return -1;
++
++ collapsed = get_lflag(stream, NULL, rawno, MN_COLL | MN_CHID);
++
++ if (!thrd->next){
++ if (thrd->rawno != top_thread(stream, thrd->rawno))
++ collapsed = get_lflag(stream, NULL, rawno, MN_CHID);
++ else
++ collapsed = get_lflag(stream, NULL, rawno, MN_COLL);
++ }
++
++ return collapsed;
++ }
++
++ /*
++ * This function assumes that it is called at a top of a thread in its
++ * first call
++ */
++
++ int
++ count_this_thread(MAILSTREAM *stream, unsigned long rawno)
++ {
++ unsigned long top, orig_top, topnxt;
++ PINETHRD_S *thrd = NULL;
++ int count = 1;
++
++ if(!stream)
++ return 0;
++
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return 0;
++
++ if (thrd->next)
++ count += count_this_thread(stream, thrd->next);
++
++ if (thrd->branch)
++ count += count_this_thread(stream, thrd->branch);
++
++ return count;
++ }
++
++ int
++ count_thread(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, long rawno)
++ {
++ unsigned long top, orig, orig_top;
++ PINETHRD_S *thrd = NULL;
++ int done = 0, count = 0;
++
++ if(!stream)
++ return 0;
++
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap,rawno);
++ top = orig_top = top_thread(stream, rawno);
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return 0;
++
++ while (!done){
++ count += count_this_thread(stream, top);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, orig));
++ return count;
++ }
++
++ unsigned long
++ get_branch(MAILSTREAM *stream, PINETHRD_S *thrd)
++ {
++ PINETHRD_S *nthrd = NULL;
++ unsigned long top;
++
++ if (thrd->toploose && thrd->nextthd)
++ nthrd = fetch_thread(stream, thrd->nextthd);
++ if (!nthrd)
++ return thrd->branch;
++ top = top_thread(stream, thrd->rawno);
++ return thrd->branch
++ ? thrd->branch
++ : (F_ON(F_ENHANCED_THREAD, ps_global)
++ ? (top == top_thread(stream, nthrd->rawno) ? thrd->nextthd : 0L)
++ : 0L);
++ }
++
++ unsigned long
++ get_next(MAILSTREAM *stream, PINETHRD_S *thrd)
++ {
++ return thrd->next;
++ }
++
++ long
++ get_length_branch(MAILSTREAM *stream, long rawno)
++ {
++ int branchp = 0, done = 0;
++ long top, count = 1L, raw;
++ PINETHRD_S *thrd, *pthrd = NULL, *nthrd;
++
++ thrd = fetch_thread(stream, rawno);
++
++ if (!thrd)
++ return -1L;
++
++ top = thrd->top;
++
++ if (thrd->parent)
++ pthrd = fetch_thread(stream, thrd->parent);
++
++ if (thrd->rawno == top)
++ branchp++;
++
++ if (!branchp && !pthrd){ /* what!!?? */
++ raw = top;
++ while (!done){
++ pthrd = fetch_thread(stream, raw);
++ if ((pthrd->next == rawno) || (pthrd->branch == rawno))
++ done++;
++ else{
++ if (pthrd->next)
++ raw = pthrd->next;
++ else if (pthrd->branch)
++ raw = pthrd->branch;
++ }
++ }
++ }
++
++ if (pthrd && pthrd->next == thrd->rawno && thrd->branch)
++ branchp++;
++
++ if (pthrd && pthrd->next && pthrd->next != thrd->rawno){
++ nthrd = fetch_thread(stream, pthrd->next);
++ while (nthrd && nthrd->branch && nthrd->branch != thrd->rawno)
++ nthrd = fetch_thread(stream, nthrd->branch);
++ if(nthrd && nthrd->branch && nthrd->branch == thrd->rawno)
++ branchp++;
++ }
++
++ if(branchp){
++ int entry = 0;
++ while(thrd && thrd->next){
++ entry = 1;
++ count++;
++ thrd = fetch_thread(stream, thrd->next);
++ if (thrd->branch)
++ break;
++ }
++ if (entry && thrd->branch)
++ count--;
++ }
++ return branchp ? (count ? count : 1L) : 0L;
++ }
++
++ void
++ find_msgmap(MAILSTREAM *stream, MSGNO_S *msgmap, int flags, SortOrder ordersort, unsigned is_rev)
++ {
++ int we_cancel;
++ long *old_arrival,*new_arrival;
++ long init_thread, end_thread, current;
++ long k = 1L, j, last_thread = 0L;
++ long i, tmsg, ntmsg, nthreads;
++ char sort_msg[MAX_SCREEN_COLS+1] = {'\0'};
++ PINETHRD_S *thrd, *tthrd, *nthrd;
++
++ erase_thread_info = 0;
++ current = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ sort_folder(stream, msgmap, ordersort, 0, SRT_VRB, 0);
++
++ tmsg = mn_get_total(msgmap) + 1;
++
++ if (tmsg <= 1)
++ return;
++
++ old_arrival = (long *) fs_get(tmsg * sizeof(long));
++ memset(old_arrival, 0, tmsg*sizeof(long));
++ for (i= 1L;(i <= mn_get_total(msgmap)) && (old_arrival[i] = msgmap->sort[i]); i++);
++
++ /* now sort by thread */
++ sort_folder(stream, msgmap, SortThread, 0, SRT_VRB, 0);
++ ntmsg = mn_get_total(msgmap) + 1;
++
++ if (tmsg != ntmsg){ /* oh oh, something happened,we better try again */
++ fs_give((void **)&old_arrival);
++ find_msgmap(stream, msgmap, flags, ordersort, is_rev);
++ return;
++ }
++
++ /* reconstruct the msgmap */
++
++ new_arrival = (long *) fs_get(tmsg * sizeof(long));
++ memset(new_arrival, 0, tmsg*sizeof(long));
++ i = mn_get_total(msgmap);
++ while (new_arrival[1] == 0){ /* think of this as (tmsg > 0) */
++ int done = 0;
++ long n = mn_get_total(msgmap);
++
++ init_thread = top_thread(stream, old_arrival[i]);
++ thrd = fetch_thread(stream, init_thread);
++ while ((new_arrival[n] != 0) && !done){ /* compare raw numbers */
++ done = (new_arrival[n] == init_thread);
++ n--;
++ }
++ if (!done){
++ k = 1L;
++ mn_set_cur(msgmap, mn_raw2m(msgmap, init_thread));
++ if (move_next_thread(ps_global, stream, msgmap, 0) <= 0)
++ j = mn_get_total(msgmap) - mn_raw2m(msgmap, init_thread) + 1;
++ else
++ j = mn_get_cur(msgmap) - mn_raw2m(msgmap, init_thread);
++ end_thread = mn_raw2m(msgmap, init_thread) + j;
++ while (k <= j){
++ new_arrival[tmsg - k] = msgmap->sort[end_thread - k];
++ k++;
++ }
++ tmsg -= j;
++ }
++ i--;
++ }
++ relink_threads(stream, msgmap, new_arrival);
++ for (i = 1; (i <= mn_get_total(msgmap))
++ && (msgmap->sort[i] = new_arrival[i]); i++);
++ msgno_reset_isort(msgmap);
++
++ fs_give((void **)&new_arrival);
++ fs_give((void **)&old_arrival);
++
++
++ if(is_rev && (mn_get_total(msgmap) > 1L)){
++ long *rev_sort;
++ long i = 1L, l = mn_get_total(msgmap);
++
++ rev_sort = (long *) fs_get((mn_get_total(msgmap)+1L) * sizeof(long));
++ memset(rev_sort, 0, (mn_get_total(msgmap)+1L)*sizeof(long));
++ while (l > 0L){
++ if (top_thread(stream, msgmap->sort[l]) == msgmap->sort[l]){
++ long init_thread = msgmap->sort[l];
++ long j, k;
++
++ mn_set_cur(msgmap, mn_raw2m(msgmap, init_thread));
++ if (move_next_thread(ps_global, stream, msgmap, 0) <= 0)
++ j = mn_get_total(msgmap) - mn_raw2m(msgmap, init_thread) + 1;
++ else
++ j = mn_get_cur(msgmap) - mn_raw2m(msgmap, init_thread);
++ for (k = 0L; (k < j) && (rev_sort[i+k] = msgmap->sort[l+k]); k++);
++ i += j;
++ }
++ l--;
++ }
++ relink_threads(stream, msgmap, rev_sort);
++ for (i = 1L; i <= mn_get_total(msgmap); i++)
++ msgmap->sort[i] = rev_sort[i];
++ msgno_reset_isort(msgmap);
++ fs_give((void **)&rev_sort);
++ }
++ mn_reset_cur(msgmap, first_sorted_flagged(is_rev ? F_NONE : F_SRCHBACK,
++ stream, mn_raw2m(msgmap, current), FSF_SKIP_CHID));
++ msgmap->top = -1L;
++
++ sp_set_unsorted_newmail(ps_global->mail_stream, 0);
++
++ for(i = 1L; i <= ps_global->mail_stream->nmsgs; i++)
++ mail_elt(ps_global->mail_stream, i)->spare7 = 0;
++
++ mn_set_sort(msgmap, SortThread);
++ mn_set_revsort(msgmap, is_rev);
++ erase_thread_info = 1;
++ clear_index_cache(stream, 0);
++ }
++
++ void
++ move_thread(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, int direction)
++ {
++ long new_cursor, old_cursor = mn_get_cur(msgmap);
++ int rv;
++ PINETHRD_S *thrd;
++
++ rv = direction > 0 ? move_next_thread(state, stream, msgmap, 1):
++ move_prev_thread(state, stream, msgmap, 1);
++ if (rv > 0 && THRD_INDX_ENABLED()){
++ new_cursor = mn_get_cur(msgmap);
++ mn_set_cur(msgmap, old_cursor);
++ unview_thread(state, stream, msgmap);
++ thrd = fetch_thread(stream,mn_m2raw(msgmap, new_cursor));
++ mn_set_cur(msgmap, new_cursor);
++ view_thread(state, stream, msgmap, 1);
++ state->next_screen = SCREEN_FUN_NULL;
++ }
++ }
++
++ void
++ relink_threads(MAILSTREAM *stream, MSGNO_S *msgmap, long *new_arrival)
++ {
++ long last_thread = 0L;
++ long i = 0L, j = 1L, k;
++ PINETHRD_S *thrd, *nthrd;
++
++ while (j <= mn_get_total(msgmap)){
++ i++;
++ thrd = fetch_thread(stream, new_arrival[j]);
++ if (!thrd) /* sort failed!, better leave from here now!!! */
++ break;
++ thrd->prevthd = last_thread;
++ thrd->thrdno = i;
++ thrd->head = new_arrival[1];
++ last_thread = thrd->rawno;
++ mn_set_cur(msgmap, mn_raw2m(msgmap,thrd->top));
++ k = mn_get_cur(msgmap);
++ if (move_next_thread(ps_global, stream, msgmap, 0) <= 0)
++ j += mn_get_total(msgmap) + 1 - k;
++ else
++ j += mn_get_cur(msgmap) - k;
++ if (!thrd->toploose)
++ thrd->nextthd = (j <= mn_get_total(msgmap)) ? new_arrival[j] : 0L;
++ else{
++ int done = 0;
++ while(thrd->nextthd && !done){
++ thrd->thrdno = i;
++ thrd->head = new_arrival[1];
++ if (thrd->nextthd)
++ nthrd = fetch_thread(stream, thrd->nextthd);
++ else
++ done++;
++ if(top_thread(stream, thrd->rawno) == top_thread(stream, nthrd->rawno))
++ thrd = nthrd;
++ else
++ done++;
++ }
++ thrd->nextthd = (j <= mn_get_total(msgmap)) ? new_arrival[j] : 0L;
++ last_thread = thrd->rawno;
++ }
++ }
++ }
++
++ int
++ move_next_this_thread(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, int display)
++ {
++ PINETHRD_S *thrd = NULL, *thrdnxt;
++ unsigned long rawno, top;
++ int rv = 1;
++
++ if(!stream)
++ return -1;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return -1;
++
++ top = top_thread(stream, rawno);
++
++ thrdnxt = (top == rawno) ? fetch_thread(stream, top) : thrd;
++ if (thrdnxt->nextthd)
++ mn_set_cur(msgmap,mn_raw2m(msgmap, thrdnxt->nextthd));
++ else{
++ rv = 0;
++ if (display)
++ q_status_message(SM_ORDER, 0, 1, "No more Threads to advance");
++ }
++ return rv;
++ }
++
++ int
++ move_next_thread(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, int display)
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL;
++ unsigned long orig, orig_top, top;
++
++ if(!stream)
++ return 0;
++
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap,orig);
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return 0;
++
++ while (rv > 0 && !done){
++ rv = move_next_this_thread(state, stream, msgmap, display);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ if (display){
++ if (rv > 0 && SEP_THRDINDX())
++ q_status_message(SM_ORDER, 0, 2, "Viewing next thread");
++ if (!rv)
++ q_status_message(SM_ORDER, 0, 2, "No more threads to advance");
++ }
++ if(rv <= 0){
++ rv = 0;
++ mn_set_cur(msgmap, mn_raw2m(msgmap, orig));
++ }
++
++ return rv;
++ }
++
++ int
++ move_prev_thread(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, int display)
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno, top;
++ int rv = 1;
++
++ if(!stream)
++ return -1;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return -1;
++
++ top = top_thread(stream, rawno);
++
++ if (top != rawno)
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top));
++ else if (thrd->prevthd)
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream,thrd->prevthd)));
++ else
++ rv = 0;
++ if (display){
++ if (rv && SEP_THRDINDX())
++ q_status_message(SM_ORDER, 0, 2, "Viewing previous thread");
++ if (!rv)
++ q_status_message(SM_ORDER, 0, 2, "No more threads to go back");
++ }
++
++ return rv;
++ }
++
++ /* add more keys to this list */
++ int
++ allowed_thread_key(SortOrder sort)
++ {
++ return sort == SortArrival
++ || sort == SortDate
++ || sort == SortScore
++ || sort == SortThread;
++ }
++
+diff -rc alpine-2.00/pith/thread.h alpine-2.00.I.USE/pith/thread.h
+*** alpine-2.00/pith/thread.h 2006-09-22 13:06:05.000000000 -0700
+--- alpine-2.00.I.USE/pith/thread.h 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 37,42 ****
+--- 37,43 ----
+ unsigned long nextthd; /* next thread, only tops have this */
+ unsigned long prevthd; /* previous thread, only tops have this */
+ unsigned long top; /* top of this thread */
++ unsigned long toploose; /* top of this thread, if is loose */
+ unsigned long head; /* head of the whole thread list */
+ } PINETHRD_S;
+
+***************
+*** 92,98 ****
+ void sort_thread_callback(MAILSTREAM *, THREADNODE *);
+ void collapse_threads(MAILSTREAM *, MSGNO_S *, PINETHRD_S *);
+ PINETHRD_S *msgno_thread_info(MAILSTREAM *, unsigned long, PINETHRD_S *, unsigned);
+! void collapse_or_expand(struct pine *, MAILSTREAM *, MSGNO_S *, unsigned long);
+ void select_thread_stmp(struct pine *, MAILSTREAM *, MSGNO_S *);
+ unsigned long count_flags_in_thread(MAILSTREAM *, PINETHRD_S *, long);
+ unsigned long count_lflags_in_thread(MAILSTREAM *, PINETHRD_S *, MSGNO_S *, int);
+--- 93,99 ----
+ void sort_thread_callback(MAILSTREAM *, THREADNODE *);
+ void collapse_threads(MAILSTREAM *, MSGNO_S *, PINETHRD_S *);
+ PINETHRD_S *msgno_thread_info(MAILSTREAM *, unsigned long, PINETHRD_S *, unsigned);
+! void collapse_or_expand(struct pine *, MAILSTREAM *, MSGNO_S *, unsigned long, int);
+ void select_thread_stmp(struct pine *, MAILSTREAM *, MSGNO_S *);
+ unsigned long count_flags_in_thread(MAILSTREAM *, PINETHRD_S *, long);
+ unsigned long count_lflags_in_thread(MAILSTREAM *, PINETHRD_S *, MSGNO_S *, int);
+***************
+*** 106,111 ****
+ int unview_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
+ PINETHRD_S *find_thread_by_number(MAILSTREAM *, MSGNO_S *, long, PINETHRD_S *);
+ void set_search_bit_for_thread(MAILSTREAM *, PINETHRD_S *, SEARCHSET **);
+!
+
+ #endif /* PITH_THREAD_INCLUDED */
+--- 107,130 ----
+ int unview_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
+ PINETHRD_S *find_thread_by_number(MAILSTREAM *, MSGNO_S *, long, PINETHRD_S *);
+ void set_search_bit_for_thread(MAILSTREAM *, PINETHRD_S *, SEARCHSET **);
+! void find_msgmap(MAILSTREAM *, MSGNO_S *, int, SortOrder, unsigned);
+! void move_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
+! void relink_threads(MAILSTREAM *, MSGNO_S *, long *);
+! long top_thread(MAILSTREAM *, long);
+! long top_this_thread(MAILSTREAM *, long);
+! long get_length_branch(MAILSTREAM *, long);
+! unsigned long get_next(MAILSTREAM *,PINETHRD_S *);
+! unsigned long get_branch(MAILSTREAM *,PINETHRD_S *);
+! int count_thread(struct pine *, MAILSTREAM *, MSGNO_S *, long);
+! int count_this_thread(MAILSTREAM *, unsigned long);
+! int this_thread_is_kolapsed(struct pine *, MAILSTREAM *, MSGNO_S *, long);
+! int thread_is_kolapsed(struct pine *, MAILSTREAM *, MSGNO_S *, long);
+! int move_prev_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
+! int move_next_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
+! int move_next_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
+! void move_top_thread(MAILSTREAM *, MSGNO_S *, long);
+! void move_top_this_thread(MAILSTREAM *, MSGNO_S *, long);
+! THREADNODE *copy_tree(THREADNODE *);
+! int allowed_thread_key(SortOrder sort);
+
+ #endif /* PITH_THREAD_INCLUDED */
+diff -rc alpine-2.00/pith/url.c alpine-2.00.I.USE/pith/url.c
+*** alpine-2.00/pith/url.c 2007-08-29 15:31:51.000000000 -0700
+--- alpine-2.00.I.USE/pith/url.c 2011-02-07 20:33:45.000000000 -0800
+***************
+*** 52,58 ****
+ rfc1738_scan(char *line, int *len)
+ {
+ char *colon, *start, *end;
+! int n;
+
+ /* process each : in the line */
+ for(; (colon = strindex(line, ':')) != NULL; line = end){
+--- 52,58 ----
+ rfc1738_scan(char *line, int *len)
+ {
+ char *colon, *start, *end;
+! int n, delim;
+
+ /* process each : in the line */
+ for(; (colon = strindex(line, ':')) != NULL; line = end){
+***************
+*** 113,119 ****
+ && !struncmp(start + 1, "elnet", 5))))
+ || (n == 8
+ && (*start == 'P' || *start == 'p')
+! && !struncmp(start + 1, "rospero", 7)))
+ || url_external_specific_handler(start, n))){
+ /*
+ * Second, make sure that everything to the right of the
+--- 113,125 ----
+ && !struncmp(start + 1, "elnet", 5))))
+ || (n == 8
+ && (*start == 'P' || *start == 'p')
+! && !struncmp(start + 1, "rospero", 7))
+! || (n == 11
+! && (*start == 'x' || *start == 'X')
+! && !struncmp(start + 1, "-pine-help", 10))
+! || (n == 13
+! && (*start == 'x' || *start == 'X')
+! && !struncmp(start + 1, "-alpine-help", 12)))
+ || url_external_specific_handler(start, n))){
+ /*
+ * Second, make sure that everything to the right of the
+***************
+*** 130,135 ****
+--- 136,142 ----
+
+ if(i != j){
+ *len = end - start;
++ delim = start > line && *(start - 1) == '<';
+
+ /*
+ * Special case handling for comma.
+***************
+*** 139,146 ****
+ * In most cases any way, that's why we have the
+ * exception.
+ */
+! if(*(end - 1) == ','
+! || (*(end - 1) == '.' && (!*end || *end == ' ')))
+ (*len)--;
+
+ if(*len - (colon - start) > 0)
+--- 146,153 ----
+ * In most cases any way, that's why we have the
+ * exception.
+ */
+! if(delim == 0 && (*(end - 1) == ','
+! || (*(end - 1) == '.' && (!*end || *end == ' '))))
+ (*len)--;
+
+ if(*len - (colon - start) > 0)
+diff -rc alpine-2.00/README.maildir alpine-2.00.I.USE/README.maildir
+*** alpine-2.00/README.maildir 2011-02-07 20:34:02.000000000 -0800
+--- alpine-2.00.I.USE/README.maildir 2011-02-07 20:33:41.000000000 -0800
+***************
+*** 0 ****
+--- 1,153 ----
++ ---------------------------------------
++
++ Maildir Driver for Alpine 1.0
++ By Eduardo Chappa <chappa@washington.edu>
++ http://staff.washington.edu/chappa/alpine/
++
++ ---------------------------------------
++ 1. General Information About This Patch
++ ---------------------------------------
++
++ This patch adds support for the maildir format to Alpine. We take the
++ approach that this patch is one more driver among the number of formats
++ supported by Alpine (more generally c-client). This approach differs from
++ older versions of similar patches, in that once a maildir patch was
++ applied, it was assumed that all your folders would be created in the
++ maildir format.
++
++ This patch does not assume that maildir is a preferred format, instead
++ puts maildir in equal footing with other formats (mbox, mbx, mix, etc),
++ and so a maildir folder in the mail/ collection is treated in the same way
++ as any other folder in any other format. In other words, just by reading
++ the name of a folder, or opening it, or doing any operation with it, you
++ can not know in which format the folder is.
++
++ This implies that if you want to add a folder in the maildir format to the
++ mail/ collection, then you must add by pressing "A" in the folder list
++ collection and enter "#driver.md/mail/name_maildir_folder".
++
++ If you only want to use maildir, however, you can do so too. In this case,
++ you must create a maildir collection. In that collection, only maildir
++ folders will be listed. If there is any folder in any other format, that
++ folder will be ignored. In another words, any folder listed there is in
++ maildir format and can be accessed through that collection, conversely,
++ any folder not listed there is not in maildir format and there is no way
++ to access it using this collection.
++
++ In order to create a maildir collection, you could press M S L, and "A" to
++ add a collection. Fill in the required fields as follows:
++
++ Nickname : Anything
++ Server :
++ Path : #md/relative/path/to/maildir/collection/
++ View :
++
++ For example, if "path" is set to "#md/mail/", then Alpine will look for your
++ maildir folders that are in ~/mail/.
++
++ The code in this patch is mostly based in code for the unix driver plus
++ some combinations of the mh, mbx and nntp drivers for the c-client
++ library. Those drivers were designed by Mark Crispin, and bugs in this
++ code are not his bugs, but my own.
++
++ I got all the specification for this patch from
++ http://cr.yp.to/proto/maildir.html. If you know of a place with a better
++ specification for maildir format please let me know. The method this patch
++ uses to create a unique filename for a message is one of the "old
++ fashioned" methods. I realize that this is old fashioned, but it is
++ portable, and portability is the main reason why I decided to use an old
++ fashioned method (most methods are not portable. See the word
++ "Unfortunately" in that document).
++
++ --------------
++ 2. Other Goals
++ --------------
++
++ It is intended that this code will work well with any application
++ written using the c-client library. Of paramount importance is to make the
++ associated imap server work well when the server accesses a folder in
++ Maildir format. The program mailutil should also work flawlessly with this
++ implemetation of the driver.
++
++ It is intended that this driver be fast and stable. We intend not to
++ patch Alpine to make this driver do its work, unless such patching is for
++ fixing bugs in Alpine or to pass parameters to the driver.
++
++ ------------------------------------------------------------------------
++ 3. What are the known bugs of this implementation of the Maildir driver?
++ ------------------------------------------------------------------------
++
++ I don't know any at this time. There have been bugs before, though, but
++ I try to fix bugs as soon as they are reported. A complete list of updates
++ for this patch, which includes bug fixes, improvements and addition of new
++ features can be found at
++
++ http://staff.washington.edu/chappa/alpine/updates/maildir.html
++
++ ----------
++ 4. On UIDs
++ ----------
++
++ This patch keeps uids in the name of the file that contains the message,
++ by adding a ",u=" string to the file name to save the uid of a message. A
++ file is kept between sessions to save information on the last uid assigned
++ and its time of validity. Only one session with writing access can write
++ uids, all others must wait for the other session to assign them. The
++ session assigning uids creates a ".uidtemp" file which other sessions must
++ not disturb.
++
++ Uid support appeared in Alpine 1.00 (snapshot 925), and is experimental,
++ please report any problems.
++
++ --------------------------------------------
++ 5. Configuring Alpine and Setting up a Maildir
++ --------------------------------------------
++
++ Once this approach was chosen, it implied the following:
++
++ * This patch assumes that your INBOX is located at "$HOME/Maildir".
++ This is a directory which should have three subdirectories "cur",
++ "tmp" and "new". Mail is delivered to 'new' and read from 'cur'. I
++ have added a configuration option "maildir-location" which can be
++ used to tell Alpine where your Maildir inbox is, in case your system
++ do not use the above directory (e.g. your system may use
++ "~/.maildir"). In this case define that variable to be the name of
++ the directory where your e-mail is being delivered (e.g.
++ ".maildir").
++
++ * If you want to use the above configuration as your inbox, you must
++ define your inbox-path as "#md/inbox" (no quotes). You can define
++ the inbox-path like above even if you have changed the
++ maildir-location variable. That's the whole point of that variable.
++
++ -----------------------------------
++ 6. What about Courier file systems?
++ -----------------------------------
++
++ In a courier file system all folders are subfolders of a root folder
++ called INBOX. Normally INBOX is located at ~/Maildir and subfolders are
++ "dot" directories in ~/Maildir. For example ~/Maildir/.Trash is a
++ subfolder of INBOX and is accessed with the nickname "INBOX.Trash".
++
++ You can not access folders in this way unless you preceed them with the
++ string "#mc/". The purpose of the string "#mc/" is to warn Alpine that a
++ collection in the Courier format is going to be accessed, so you can
++ SELECT a folder like "#mc/INBOX.Trash", but not "INBOX.Trash"
++
++ You can access a collection through a server, but if you want to access a
++ collection of folders created using the Courier server, you MUST edit your
++ ".pinerc" file and enter the definition of the collection as follows:
++
++ folder-collections="Anything you want" #mc/INBOX.[]
++
++ You can replace the string "#mc/INBOX." by something different, for example
++ "#mc/Courier/." will make Alpine search for your collection in ~/Courier.
++
++ You can not add this directly into Alpine because Alpine fails to accept this
++ value from its input, but it takes it correctly when it is added through
++ the ".pinerc" file.
++
++ You can access your inbox as "#mc/INBOX" or "#md/INBOX". Both definitions
++ point to the same place.
++
++ Last Updated February 9, 2008
+diff -rc alpine-2.00/web/src/alpined.d/alpined.c alpine-2.00.I.USE/web/src/alpined.d/alpined.c
+*** alpine-2.00/web/src/alpined.d/alpined.c 2008-08-22 13:41:37.000000000 -0700
+--- alpine-2.00.I.USE/web/src/alpined.d/alpined.c 2011-02-07 20:33:43.000000000 -0800
+***************
+*** 2795,2801 ****
+ init_save_defaults();
+ break;
+ case V_SORT_KEY:
+! decode_sort(ps_global->VAR_SORT_KEY, &ps_global->def_sort, &def_sort_rev);
+ break;
+ case V_VIEW_HDR_COLORS :
+ set_custom_spec_colors(ps_global);
+--- 2795,2801 ----
+ init_save_defaults();
+ break;
+ case V_SORT_KEY:
+! decode_sort(ps_global->VAR_SORT_KEY, &ps_global->def_sort, &def_sort_rev, 0);
+ break;
+ case V_VIEW_HDR_COLORS :
+ set_custom_spec_colors(ps_global);
+***************
+*** 6271,6277 ****
+ && mn_get_revsort(sp_msgmap(ps_global->mail_stream)) == reversed))
+ sort_folder(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream),
+ ps_global->sort_types[i],
+! reversed, 0);
+
+ break;
+ }
+--- 6271,6277 ----
+ && mn_get_revsort(sp_msgmap(ps_global->mail_stream)) == reversed))
+ sort_folder(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream),
+ ps_global->sort_types[i],
+! reversed, 0, 1);
+
+ break;
+ }
+***************
+*** 6848,6854 ****
+ /* BUG: fix charset not to be NULL below */
+ if(agg_text_select(ps_global->mail_stream,
+ sp_msgmap(ps_global->mail_stream),
+! field, not, 0, text, NULL, NULL))
+ /* BUG: plug in "charset" above? */
+ return(peSelectError(interp, "programmer botch"));
+ }
+--- 6848,6854 ----
+ /* BUG: fix charset not to be NULL below */
+ if(agg_text_select(ps_global->mail_stream,
+ sp_msgmap(ps_global->mail_stream),
+! field, NULL, not, 0, text, NULL, NULL))
+ /* BUG: plug in "charset" above? */
+ return(peSelectError(interp, "programmer botch"));
+ }
+diff -rc alpine-2.00/web/src/alpined.d/Makefile.am alpine-2.00.I.USE/web/src/alpined.d/Makefile.am
+*** alpine-2.00/web/src/alpined.d/Makefile.am 2008-08-12 13:47:04.000000000 -0700
+--- alpine-2.00.I.USE/web/src/alpined.d/Makefile.am 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 50,52 ****
+--- 50,53 ----
+ debug.c status.c stubs.c alpined.h color.h ldap.h
+ echo "char datestamp[]="\"`date`\"";" > local.c
+ echo "char hoststamp[]="\"`hostname`\"";" >> local.c
++ cat ../../../patchlevel >> local.c
+diff -rc alpine-2.00/web/src/alpined.d/Makefile.in alpine-2.00.I.USE/web/src/alpined.d/Makefile.in
+*** alpine-2.00/web/src/alpined.d/Makefile.in 2008-08-13 08:44:42.000000000 -0700
+--- alpine-2.00.I.USE/web/src/alpined.d/Makefile.in 2011-02-07 20:33:46.000000000 -0800
+***************
+*** 619,624 ****
+--- 619,625 ----
+ debug.c status.c stubs.c alpined.h color.h ldap.h
+ echo "char datestamp[]="\"`date`\"";" > local.c
+ echo "char hoststamp[]="\"`hostname`\"";" >> local.c
++ cat ../../../patchlevel >> local.c
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
diff --git a/main/alsa-lib/APKBUILD b/main/alsa-lib/APKBUILD
new file mode 100644
index 0000000000..077e24762a
--- /dev/null
+++ b/main/alsa-lib/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alsa-lib
+pkgver=1.0.24.1
+pkgrel=1
+pkgdesc="An alternative implementation of Linux sound support"
+url="http://www.alsa-project.org"
+arch="all"
+license="GPL"
+depends=
+subpackages="$pkgname-dev"
+source="ftp://ftp.alsa-project.org/pub/lib/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --disable-python \
+ --disable-static \
+ --disable-resmgr \
+ --enable-rawmidi \
+ --enable-seq \
+ --enable-aload \
+ --disable-dependency-tracking \
+ --without-versioned \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="7cc05f25e1d5b65da8fb3fdcd540f226 alsa-lib-1.0.24.1.tar.bz2"
diff --git a/main/alsa-utils/APKBUILD b/main/alsa-utils/APKBUILD
new file mode 100644
index 0000000000..d9e1826b01
--- /dev/null
+++ b/main/alsa-utils/APKBUILD
@@ -0,0 +1,59 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=alsa-utils
+pkgver=1.0.24.2
+pkgrel=0
+pkgdesc="Advanced Linux Sound Architecture Utils (alsactl, alsamixer, etc.)"
+url="http://www.alsa-project.org"
+arch="all"
+license="GPL"
+makedepends="alsa-lib-dev pciutils-dev ncurses-dev"
+depends="dialog"
+subpackages="$pkgname-doc alsaconf"
+source="ftp://ftp.alsa-project.org/pub/utils/$pkgname-$pkgver.tar.bz2
+ alsaconf.patch
+ uclibc-exp10.patch
+ alsa.initd
+ alsa.confd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-xmlto \
+ --disable-nls \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ install -D -m755 ../alsa.initd "$pkgdir"/etc/init.d/alsa
+ install -D -m644 ../alsa.confd "$pkgdir"/etc/conf.d/alsa
+}
+
+alsaconf() {
+ arch="noarch"
+ depends="alsa-utils bash"
+ cd "$_builddir"
+ install -D -m755 alsaconf/alsaconf "$subpkgdir"/usr/bin/alsaconf
+}
+
+md5sums="8238cd57cb301d1c36bcf0ecb59ce6b2 alsa-utils-1.0.24.2.tar.bz2
+5e65f278b5a77e3ee2821ad955c4cd91 alsaconf.patch
+58c30caa1c47de084e70ca353698e976 uclibc-exp10.patch
+219cd8b7b3e250895550b1d60cfc219f alsa.initd
+85b1f1e759fe5953eca329237f4ac256 alsa.confd"
diff --git a/main/alsa-utils/alsa.confd b/main/alsa-utils/alsa.confd
new file mode 100644
index 0000000000..0a5d58fc1f
--- /dev/null
+++ b/main/alsa-utils/alsa.confd
@@ -0,0 +1,31 @@
+# ENABLE_OSS_EMUL:
+# Do you want to enable in-kernel oss emulation?
+# no - Do not load oss emul drivers
+# yes - Load oss emul drivers if they're found
+
+ENABLE_OSS_EMUL="yes"
+
+# RESTORE_ON_START:
+# Do you want to restore your mixer settings? If not, your cards will be
+# muted.
+# no - Do not restore state
+# yes - Restore state
+
+RESTORE_ON_START="yes"
+
+# SAVE_ON_STOP:
+# Do you want to save changes made to your mixer volumes when alsasound
+# stops?
+# no - Do not save state
+# yes - Save state
+
+SAVE_ON_STOP="yes"
+
+# LOAD_ON_START:
+# Do you want to load sound modules when alsasound starts?
+# Note: The Gentoo ALSA developers encourage you to build your sound
+# drivers into the kernel unless the device is hotpluggable or
+# you need to supply specific options (such as model= to HD-Audio).
+# no - Do not load modules
+# yes - Load modules
+LOAD_ON_START="yes"
diff --git a/main/alsa-utils/alsa.initd b/main/alsa-utils/alsa.initd
new file mode 100644
index 0000000000..19d0e488e3
--- /dev/null
+++ b/main/alsa-utils/alsa.initd
@@ -0,0 +1,218 @@
+#!/sbin/runscript
+# $Header: /var/cvsroot/gentoo-x86/media-sound/alsa-utils/files/alsasound.initd-r4,v 1.1 2009/08/02 11:27:26 ssuominen Exp $
+# Copyright 2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+alsastatedir=/var/lib/alsa
+alsascrdir=/etc/alsa.d
+
+opts="save restore"
+
+depend() {
+ need localmount
+ after bootmisc modules isapnp coldplug hotplug hwdrivers
+}
+
+load_modules() {
+ # List of drivers for each card.
+ local DRIVERS="$(modprobe | sed -n -e 's/^alias \(snd-card-[[:digit:]]\+\) .*/\1/p')"
+
+ # Fall back on the automated aliases if we don't have ALSA configured properly...
+ if [ -z "${DRIVERS}" ] && \
+ ( [ ! -r /proc/asound/cards ] || grep -q ' no soundcards ' /proc/asound/cards 2>/dev/null ) ; then
+ ewarn "Could not detect custom ALSA settings. Loading all detected alsa drivers."
+ DRIVERS="$(modprobe | sed -n -e '/^alias pci:.* snd.*/ s/^alias pci:[^ ]* \(.*\)/\1/p' | sort | uniq)"
+ if [ -z "${DRIVERS}" ] ; then
+ eerror "Unable to find any ALSA drivers. Have you compiled alsa-drivers correctly?"
+ fi
+ fi
+
+ if [ "${ENABLE_OSS_EMUL}" = "yes" ] ; then
+ DRIVERS="${DRIVERS} $(modprobe -l | sed -n -e '/snd.*oss/ s:.*\/\([[:alnum:]_-]\+\).ko:\1:p')"
+ fi
+
+ # We want to ensure snd-seq is loaded as it is needed for things like
+ # timidity even if we don't use a real sequencer.
+ DRIVERS="${DRIVERS} $(modprobe -l | sed -n -e '/snd.seq\./ s:.*\/\([[:alnum:]_-]\+\).ko:\1:p')"
+
+ # We want to ensure snd-ioctl32 is loaded as it is needed for 32bit
+ # compatibility
+ DRIVERS="${DRIVERS} $(modprobe -l | sed -n -e '/snd.ioctl32\./ s:.*\/\([[:alnum:]_-]\+\).ko:\1:p')"
+
+ local DRIVER= DMOD=
+ for DRIVER in ${DRIVERS} ; do
+ [ "${DRIVER}" = "off" ] && continue
+ DMOD="$(echo "${DRIVER}" | sed -e 's/-/_/g')"
+ if ! grep -q "^${DMOD} " /proc/modules ; then
+ ebegin "Loading: ${DRIVER}"
+ modprobe ${DRIVER}
+ eend $?
+ fi
+ done
+
+ if [ -f /proc/asound/seq/drivers ] ; then
+ local SEQUENCERS="$(sed -n -e 's/\([^,]*\),empty,.*/\1/p' /proc/asound/seq/drivers)"
+ local SEQUENCER
+ for SEQUENCER in ${SEQUENCERS} ; do
+ DMOD="$(echo "${SEQUENCER}" | sed -e 's/-/_/g')"
+ if ! grep -q "^${DMOD} " /proc/modules ; then
+ ebegin "Loading: ${SEQUENCER}"
+ modprobe ${SEQUENCER}
+ eend $?
+ fi
+ done
+ fi
+
+ for DRIVER in ${DRIVERS}
+ do
+ local TMP=${DRIVER##snd-}
+ TMP=${TMP##snd_}
+ if [ -x "${alsascrdir}/${TMP}" ] ; then
+ ebegin "Running: ${alsascrdir}/${TMP}"
+ "${alsascrdir}/${TMP}"
+ eend $?
+ fi
+ done
+
+ if [ ! -d /proc/asound ] || grep -q ' no soundcards ' /proc/asound/cards ; then
+ eerror "ERROR: Failed to load necessary drivers"
+ return 1
+ fi
+}
+
+unload_modules_24() {
+ local LOADED_MODULES="$(lsmod | sed -n -e 's/^\(snd[^ ]*\) .*/\1/p')"
+ local MODULE
+ for MODULE in ${LOADED_MODULES} ; do
+ rmmod "${MODULE}"
+ done
+ rmmod soundcore 2>/dev/null
+ rmmod gameport 2>/dev/null
+
+ lsmod | grep -vq '^snd'
+}
+
+unload_modules_recursive() {
+ local revdeps="$(lsmod | sed -n -e "s/,/ /g" -e "s/^$1 *[0-9]* *[0-9]* \(.*\)/\1/p")"
+
+ for module in ${revdeps} ; do
+ unload_modules_recursive "${module}"
+ done
+
+ vebegin "Unloading: $1"
+ rmmod --wait "$1"
+ veend $?
+}
+
+unload_modules_26() {
+ # First of all, remove the snd module and all the modules depending
+ # on it, this should remove already most of ALSA modules.
+ lsmod | grep -q "^snd[[:space:]]" && unload_modules_recursive snd
+
+ # Then find the remaining ones, and handle them too.
+ for module in $(lsmod | sed -n -e 's/^\(snd[^ ]*\) .*/\1/p'); do
+ unload_modules_recursive "${module}"
+ done
+
+ lsmod | grep -vq "^snd"
+}
+
+terminate() {
+ #
+ # Kill processes holding open sound devices
+ #
+ # DEVS=`find /dev/ -follow -type c -maxdepth 1 -print 2>/dev/null | xargs ls -dils | grep "1*1[46]," | cut -d: -f2 | cut -d" " -f2; echo /proc/asound/dev/*`
+ local ossdevs="/dev/admmidi* /dev/adsp* /dev/amidi* /dev/audio* /dev/dmfm* \
+ /dev/dmmidi* /dev/dsp* /dev/dspW* /dev/midi0* /dev/mixer* /dev/music \
+ /dev/patmgr* /dev/sequencer* /dev/sndstat"
+ local alsadevs="/proc/asound/dev/* /dev/sound/* /dev/snd/*"
+ fuser -k ${ossdevs} ${alsadevs} >/dev/null 2>/dev/null
+
+ # remove all sequencer connections if any
+ [ -f /proc/asound/seq/clients ] && type aconnect >/dev/null 2>/dev/null && aconnect --removeall
+}
+
+restore() {
+ ebegin "Restoring Mixer Levels"
+
+ if [ ! -r "${alsastatedir}/asound.state" ] ; then
+ ewarn "No mixer config in ${alsastatedir}/asound.state, you have to unmute your card!"
+ eend 0
+ return 0
+ fi
+
+ local cards="$(sed -n -e 's/ *\([[:digit:]]*\) .*/\1/p' /proc/asound/cards)"
+ local CARDNUM
+ for cardnum in ${cards}; do
+ [ -e /dev/snd/controlC${cardnum} ] || sleep 2
+ [ -e /dev/snd/controlC${cardnum} ] || sleep 2
+ [ -e /dev/snd/controlC${cardnum} ] || sleep 2
+ [ -e /dev/snd/controlC${cardnum} ] || sleep 2
+ alsactl -f "${alsastatedir}/asound.state" restore ${cardnum} \
+ || ewarn "Errors while restoring defaults, ignoring"
+ done
+
+ for ossfile in "${alsastatedir}"/oss/card*_pcm* ; do
+ [ -e "${ossfile}" ] || continue
+ # We use cat because I'm not sure if cp works properly on /proc
+ local procfile=${ossfile##${alsastatedir}/oss}
+ procfile="$(echo "${procfile}" | sed -e 's,_,/,g')"
+ if [ -e /proc/asound/"${procfile}"/oss ] ; then
+ cat "${ossfile}" > /proc/asound/"${procfile}"/oss
+ fi
+ done
+
+ eend 0
+}
+
+save() {
+ ebegin "Storing ALSA Mixer Levels"
+
+ mkdir -p "${alsastatedir}"
+ if ! alsactl -f "${alsastatedir}/asound.state" store; then
+ eerror "Error saving levels."
+ eend 1
+ return 1
+ fi
+
+ for ossfile in /proc/asound/card*/pcm*/oss; do
+ [ -e "${ossfile}" ] || continue
+ local device=${ossfile##/proc/asound/} ; device=${device%%/oss}
+ device="$(echo "${device}" | sed -e 's,/,_,g')"
+ mkdir -p "${alsastatedir}/oss/"
+ cp "${ossfile}" "${alsastatedir}/oss/${device}"
+ done
+
+ eend 0
+}
+
+start() {
+ if [ -f /proc/modules ] && [ "${LOAD_ON_START}" = "yes" ]; then
+ ebegin "Loading ALSA modules"
+ eindent
+ load_modules
+ eoutdent
+ eend $? || return 1
+ fi
+
+ if [ ! -d /proc/asound ]; then
+ eerror "ALSA failed to load."
+ eend 1
+ return 1
+ elif [ "${RESTORE_ON_START}" = "yes" ]; then
+ restore
+ fi
+
+ return 0
+}
+
+stop() {
+ if [ ! -d /proc/asound ] ; then
+ eerror "ALSA is not loaded"
+ return 0
+ fi
+
+ [ "${SAVE_ON_STOP}" = "yes" ] && save
+
+ return 0
+}
diff --git a/main/alsa-utils/alsaconf.patch b/main/alsa-utils/alsaconf.patch
new file mode 100644
index 0000000000..846cf98480
--- /dev/null
+++ b/main/alsa-utils/alsaconf.patch
@@ -0,0 +1,12 @@
+diff -Naur alsa-utils-1.0.9a-orig/alsaconf/alsaconf.in alsa-utils-1.0.9a/alsaconf/alsaconf.in
+--- alsa-utils-1.0.9a-orig/alsaconf/alsaconf.in 2005-03-24 00:24:52.000000000 -0800
++++ alsa-utils-1.0.9a/alsaconf/alsaconf.in 2005-07-18 09:25:02.000000000 -0700
+@@ -58,6 +58,8 @@
+ distribution="redhat"
+ elif test -f /etc/fedora-release && grep -q "Fedora" /etc/fedora-release; then
+ distribution="fedora"
++elif test -f /etc/alpine-release; then
++ distribution="alpine"
+ elif [ -f /etc/slackware-version -o -f /etc/slamd64-version ]; then
+ distribution="slackware"
+ else
diff --git a/main/alsa-utils/uclibc-exp10.patch b/main/alsa-utils/uclibc-exp10.patch
new file mode 100644
index 0000000000..e021374a25
--- /dev/null
+++ b/main/alsa-utils/uclibc-exp10.patch
@@ -0,0 +1,25 @@
+diff --git a/alsamixer/volume_mapping.c b/alsamixer/volume_mapping.c
+index 9cacad8..f08f003 100644
+--- a/alsamixer/volume_mapping.c
++++ b/alsamixer/volume_mapping.c
+@@ -109,9 +109,9 @@ static double get_normalized_volume(snd_mixer_elem_t *elem,
+ if (use_linear_dB_scale(min, max))
+ return (value - min) / (double)(max - min);
+
+- normalized = exp10((value - max) / 6000.0);
++ normalized = exp(M_LN10 * (value - max) / 6000.0);
+ if (min != SND_CTL_TLV_DB_GAIN_MUTE) {
+- min_norm = exp10((min - max) / 6000.0);
++ min_norm = exp(M_LN10 * (min - max) / 6000.0);
+ normalized = (normalized - min_norm) / (1 - min_norm);
+ }
+
+@@ -144,7 +144,7 @@ static int set_normalized_volume(snd_mixer_elem_t *elem,
+ }
+
+ if (min != SND_CTL_TLV_DB_GAIN_MUTE) {
+- min_norm = exp10((min - max) / 6000.0);
++ min_norm = exp(M_LN10 * (min - max) / 6000.0);
+ volume = volume * (1 - min_norm) + min_norm;
+ }
+ value = lrint_dir(6000.0 * log10(volume), dir) + max;
diff --git a/main/amavisd-new/APKBUILD b/main/amavisd-new/APKBUILD
new file mode 100644
index 0000000000..adbf03169e
--- /dev/null
+++ b/main/amavisd-new/APKBUILD
@@ -0,0 +1,47 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=amavisd-new
+pkgver=2.6.4
+pkgrel=3
+pkgdesc="High-performance interface between mailer (MTA) and content checkers"
+url="http://www.ijs.si/software/amavisd"
+arch="all"
+license="GPL-2"
+depends="sed file perl perl-archive-zip perl-convert-tnef
+perl-convert-uulib perl-mime-tools perl-mail-tools perl-net-server
+perl-io-stringy perl-unix-syslog perl-db perl-mail-dkim"
+makedepends=""
+install="$pkgname.post-install $pkgname.pre-install"
+subpackages=""
+source="http://www.ijs.si/software/amavisd/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ (
+ HOME=/var/amavis
+ QUARANTINE=$HOME/quarantine
+ USER=amavis
+ GROUP=amavis
+ DIRS="$HOME $HOME/tmp $HOME/var $HOME/db $HOME/home $QUARANTINE"
+ CONFIG=/etc/amavisd.conf
+
+ for dir in $DIRS
+ do
+ mkdir -p ${pkgdir}$dir
+ done
+
+ install -m 755 -o root -D amavisd $pkgdir/usr/sbin/amavisd
+ install -m 755 -o root -D amavisd-nanny $pkgdir/usr/bin/amavisd-nanny
+ install -m 755 -o root -D amavisd-release $pkgdir/usr/bin/amavisd-release
+ sed -e "s:^.*\$MYHOME = .*$:\$MYHOME = '$HOME';:" \
+ -e 's:^.*\$TEMPBASE = .*$:\$TEMPBASE = "\$MYHOME/tmp";:' \
+ -e 's:^.*\$db_home = .*$:\$db_home = "$MYHOME/db";:' \
+ -e "s:^.*\$QUARANTINEDIR = .*$:\$QUARANTINEDIR = '$QUARANTINE';:" \
+ -e "s:^.*\$daemon_user = 'vscan';\(.*\)$:\$daemon_user = 'amavis';\1:" \
+ -e "s:^.*\$daemon_group = 'vscan';\(.*\)$:\$daemon_group = 'amavis';\1:" < amavisd.conf > amavisd.conf.alpine
+ install -m 640 -o root -D amavisd.conf.alpine ${pkgdir}${CONFIG}
+ install -m 755 -D ../../amavisd.init $pkgdir/etc/init.d/amavisd
+ )
+}
+
+md5sums="03d31657f14cd64c1cb38786214234b4 amavisd-new-2.6.4.tar.gz"
diff --git a/main/amavisd-new/amavisd-new.post-install b/main/amavisd-new/amavisd-new.post-install
new file mode 100755
index 0000000000..2c5ea2cf65
--- /dev/null
+++ b/main/amavisd-new/amavisd-new.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+chown -R amavis:amavis /var/amavis
+chmod -R 750 /var/amavis
+chown root:amavis /etc/amavisd.conf
diff --git a/main/amavisd-new/amavisd-new.pre-install b/main/amavisd-new/amavisd-new.pre-install
new file mode 100755
index 0000000000..167ec16d6d
--- /dev/null
+++ b/main/amavisd-new/amavisd-new.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+addgroup amavis 2>/dev/null
+adduser -D -S -G amavis -h /var/amavis -s /bin/false amavis 2>/dev/null
+exit 0
+
diff --git a/main/amavisd-new/amavisd.init b/main/amavisd-new/amavisd.init
new file mode 100644
index 0000000000..23f92af3f3
--- /dev/null
+++ b/main/amavisd-new/amavisd.init
@@ -0,0 +1,23 @@
+#!/sbin/runscript
+
+PIDFILE="/var/amavis/amavisd.pid"
+
+depend() {
+ need net
+ use logger
+ use antivirus
+ before mta
+}
+
+start() {
+ ebegin "Starting amavisd-new"
+ start-stop-daemon --start --quiet --name amavisd --pidfile ${PIDFILE} \
+ --exec /usr/sbin/amavisd
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping amavisd-new"
+ start-stop-daemon --stop --quiet --pidfile ${PIDFILE}
+ eend $?
+}
diff --git a/main/antiword/APKBUILD b/main/antiword/APKBUILD
new file mode 100644
index 0000000000..21f55ab77e
--- /dev/null
+++ b/main/antiword/APKBUILD
@@ -0,0 +1,29 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=antiword
+pkgver=0.37
+pkgrel=2
+pkgdesc="free MS Word reader"
+url="http://www.winfield.demon.nl"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages=""
+source="http://www.winfield.demon.nl/linux/antiword-0.37.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ install -m755 -D "$srcdir"/"$pkgname-$pkgver"/$pkgname "$pkgdir"/usr/bin/$pkgname
+ mkdir -p "$pkgdir"/usr/share/antiword
+ install -m644 -D "$srcdir"/"$pkgname-$pkgver"/Resources/* "$pkgdir"/usr/share/antiword/
+}
+
+md5sums="f868e2a269edcbc06bf77e89a55898d1 antiword-0.37.tar.gz"
diff --git a/main/aoetools/APKBUILD b/main/aoetools/APKBUILD
new file mode 100644
index 0000000000..22f000c1a5
--- /dev/null
+++ b/main/aoetools/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=aoetools
+pkgver=32
+pkgrel=0
+pkgdesc="tools for managing the linux AoE driver"
+url="http://aoetools.sourceforge.net/"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://downloads.sourceforge.net/aoetools/$pkgname-$pkgver.tar.gz"
+arch="all"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make PREFIX="$pkgdir" install
+}
+
+md5sums="62c8b5664d413019d0008f27ab5dc4d1 aoetools-32.tar.gz"
diff --git a/main/apache-mod-auth-ntlm-winbind/APKBUILD b/main/apache-mod-auth-ntlm-winbind/APKBUILD
new file mode 100644
index 0000000000..abc0a90221
--- /dev/null
+++ b/main/apache-mod-auth-ntlm-winbind/APKBUILD
@@ -0,0 +1,35 @@
+# Contributor: Jeff Bilyk <jbilyk@gmail.com>
+# Maintainer: Natanael Copa <natanael.copa@gmail.com>
+pkgname=apache-mod-auth-ntlm-winbind
+pkgver=0.1
+pkgrel=3
+pkgdesc="Authentication module for Apache using NTLM protocol with winbind helper"
+url="http://samba.org/ftp/unpacked/lorikeet/mod_auth_ntlm_winbind/"
+arch="all"
+license="Apache2"
+depends="apache2 samba winbind"
+makedepends="autoconf apache2-dev apr-util-dev apr-dev"
+source="http://samba.org/ftp/unpacked/lorikeet/mod_auth_ntlm_winbind/mod_auth_ntlm_winbind.c
+http://samba.org/ftp/unpacked/lorikeet/mod_auth_ntlm_winbind/configure.in
+http://samba.org/ftp/unpacked/lorikeet/mod_auth_ntlm_winbind/Makefile.in
+mod-auth-ntlm-winbind.conf"
+
+build() {
+ cd "$srcdir"
+ autoconf
+ ./configure
+ make DESTDIR="$pkgdir" || return 1
+}
+
+package() {
+ cd "$srcdir"
+ mkdir -p "$pkgdir"/etc/apache2/conf.d
+ mkdir -p "$pkgdir"/usr/lib/apache2
+ install mod-auth-ntlm-winbind.conf "$pkgdir"/etc/apache2/conf.d/mod-auth-ntlm-winbind.conf
+ install "$srcdir"/.libs/mod_auth_ntlm_winbind.so "$pkgdir"/usr/lib/apache2/mod_auth_ntlm_winbind.so
+}
+
+md5sums="01d32e311e6a404bcf4179c863081818 mod_auth_ntlm_winbind.c
+e1490dae6e468d4bc56154b16e5d8c24 configure.in
+410de8b0ac7ffe5c44a71d094190187d Makefile.in
+27142b177996bd34c56d4bb60c3991e0 mod-auth-ntlm-winbind.conf"
diff --git a/main/apache-mod-auth-ntlm-winbind/mod-auth-ntlm-winbind.conf b/main/apache-mod-auth-ntlm-winbind/mod-auth-ntlm-winbind.conf
new file mode 100644
index 0000000000..c797f6331b
--- /dev/null
+++ b/main/apache-mod-auth-ntlm-winbind/mod-auth-ntlm-winbind.conf
@@ -0,0 +1 @@
+LoadModule auth_ntlm_winbind_module modules/mod_auth_ntlm_winbind.so
diff --git a/main/apache2/APKBUILD b/main/apache2/APKBUILD
new file mode 100644
index 0000000000..4a883adf97
--- /dev/null
+++ b/main/apache2/APKBUILD
@@ -0,0 +1,254 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=apache2
+pkgver=2.2.17
+pkgrel=5
+pkgdesc="A high performance Unix-based HTTP server"
+url="http://httpd.apache.org/"
+arch="all"
+license="APACHE"
+depends=""
+pkgusers="apache"
+pkggroups="apache"
+makedepends="openssl-dev zlib-dev apr-util-dev apr-dev pcre-dev
+ autoconf automake"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-utils $pkgname-ssl
+ $pkgname-ldap"
+source="http://archive.apache.org/dist/httpd/httpd-$pkgver.tar.bz2
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/02-rename-prefork-to-itk.patch
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/03-add-mpm-to-build-system.patch
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/04-correct-output-makefile-location.patch
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/05-add-copyright.patch
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/06-hook-just-after-merging-perdir-config.patch
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/07-base-functionality.patch
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/08-max-clients-per-vhost.patch
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/09-capabilities.patch
+ http://mpm-itk.sesse.net/apache2.2-mpm-itk-2.2.11-02/10-nice.patch
+ apache2.confd
+ apache2.logrotate
+ apache2.initd
+ httpd.conf
+ ssl.conf
+ ldap.conf
+ alpine.layout"
+
+prepare() {
+ cd "$srcdir"/httpd-$pkgver
+ cat "$srcdir/alpine.layout" >> config.layout
+
+ # create itk directory and apply itk patches
+ mkdir -p server/mpm/experimental/itk
+ cp -r server/mpm/prefork/* \
+ server/mpm/experimental/itk/ || return 1
+ mv server/mpm/experimental/itk/prefork.c \
+ server/mpm/experimental/itk/itk.c || return 1
+ patch -Np1 -i "$srcdir"/02-rename-prefork-to-itk.patch || return 1
+ patch -Np1 -i "$srcdir"/03-add-mpm-to-build-system.patch || return 1
+ patch -Np1 -i "$srcdir"/04-correct-output-makefile-location.patch || return 1
+ patch -Np1 -i "$srcdir"/05-add-copyright.patch || return 1
+ patch -Np1 -i "$srcdir"/06-hook-just-after-merging-perdir-config.patch || return 1
+ patch -Np1 -i "$srcdir"/07-base-functionality.patch || return 1
+ patch -Np1 -i "$srcdir"/08-max-clients-per-vhost.patch || return 1
+ patch -Np1 -i "$srcdir"/09-capabilities.patch || return 1
+ patch -Np1 -i "$srcdir"/10-nice.patch || return 1
+ autoconf || return 1
+}
+
+build() {
+ local _apacheconfig="--prefix=/usr \
+ --enable-layout=Alpine \
+ --enable-so \
+ --enable-suexec \
+ --with-suexec-caller=http \
+ --with-suexec-docroot=/var/www/localhost/htdocs \
+ --with-suexec-logfile=/var/log/httpd/suexec.log \
+ --with-suexec-bin=/usr/sbin/suexec \
+ --with-suexec-uidmin=99 \
+ --with-suexec-gidmin=99 \
+ --with-apr=/usr/bin/apr-1-config \
+ --with-apr-util=/usr/bin/apu-1-config \
+ --with-pcre=/usr \
+ --enable-mods-shared=all \
+ --enable-ssl --with-ssl \
+ --enable-proxy \
+ --enable-cache \
+ --enable-disk-cache \
+ --enable-mem-cache \
+ --enable-file-cache \
+ --enable-ldap --enable-authnz-ldap \
+ --enable-cgid \
+ --enable-authn-anon --enable-authn-alias \
+ --disable-imagemap \
+ --enable-proxy-connect \
+ --enable-proxy-http \
+ --enable-proxy-ftp \
+ --enable-deflate \
+ --enable-dbd \
+ --enable-exception-hook"
+ local _mpm
+
+ _mpm="prefork"
+ cd "$srcdir"/httpd-$pkgver
+ ./configure ${_apacheconfig} --with-mpm=${_mpm} || return 1
+ make || return 1
+
+ _mpm="itk"
+ cp -a "$srcdir"/httpd-$pkgver "$srcdir"/httpd-${_mpm}
+ cd "$srcdir"/httpd-${_mpm}
+ ./configure ${_apacheconfig} --with-mpm=${_mpm} || return 1
+ make || return 1
+
+ _mpm="worker"
+ cp -a "$srcdir"/httpd-$pkgver "$srcdir"/httpd-${_mpm}
+ cd "$srcdir"/httpd-${_mpm}
+ make clean
+ ./configure ${_apacheconfig} --with-mpm=${_mpm} || return 1
+ make || return 1
+}
+
+package() {
+ local _mpm
+
+ # prefork
+ cd "$srcdir"/httpd-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+
+ # itk and worker
+ for _mpm in itk worker; do
+ install -D -m755 "$srcdir"/httpd-${_mpm}/httpd \
+ "$pkgdir"/usr/sbin/httpd.${_mpm} || return 1
+ done
+
+ # config
+ rm -r "$pkgdir"/etc/apache2/httpd.conf \
+ "$pkgdir"/etc/apache2/extra
+ install -D -m644 "$srcdir"/httpd.conf "$pkgdir"/etc/apache2/httpd.conf \
+ || return 1
+ install -d "$pkgdir"/etc/apache2/conf.d || return 1
+
+ # init scripts and logrotate
+ install -D -m755 "$srcdir"/apache2.initd \
+ "$pkgdir"/etc/init.d/apache2 || return 1
+ install -D -m644 "$srcdir"/apache2.logrotate \
+ "$pkgdir"/etc/logrotate.d/apache2 || return 1
+ install -D -m644 "$srcdir"/apache2.confd \
+ "$pkgdir"/etc/conf.d/apache2 || return 1
+
+ install -d "$pkgdir"/var/www || return 1
+ ln -fs /var/log/apache2 "$pkgdir"/var/www/logs
+ ln -fs /var/run/apache2 "$pkgdir"/var/www/run
+ ln -fs /usr/lib/apache2 "$pkgdir"/var/www/modules
+ ln -fs /etc/apache2/conf.d "$pkgdir"/var/www/conf.d
+}
+
+# include the builddir and apxs in -dev package
+dev() {
+ local _mpm
+ local _file
+ default_dev
+ depends="$depends perl apr-util-dev"
+ arch="noarch"
+
+ # install apxs utility
+ install -d "$subpkgdir"/usr/sbin || return 1
+ mv "$pkgdir"/usr/sbin/apxs \
+ "$subpkgdir"/usr/sbin/apxs || return 1
+
+
+ _mpm="prefork"
+ install -d "$subpkgdir"/usr/share/apache2/build-${_mpm} || return 1
+ mv "$pkgdir"/usr/share/apache2/build/* \
+ "$subpkgdir"/usr/share/apache2/build-${_mpm} || return 1
+ rm -rf "$pkgdir"/usr/share/apache2/build
+ ln -s /usr/share/apache2/build-${_mpm} \
+ "$pkgdir"/usr/share/apache2/build || return 1
+
+
+ _mpm="itk"
+ install -d "$subpkgdir"/usr/share/apache2/build-${_mpm} || return 1
+ for _file in `ls -1 "$subpkgdir"/usr/share/apache2/build-prefork | grep -v "config\.nice"`; do
+ mv "$srcdir"/httpd-${_mpm}/build/${_file} \
+ "$subpkgdir"/usr/share/apache2/build-${_mpm}/${_file} \
+ || return 1
+ done
+ cp -a "$subpkgdir"/usr/share/apache2/build-prefork/config.nice \
+ "$subpkgdir"/usr/share/apache2/build-${_mpm}/config.nice \
+ || return 1
+ sed -ri "s/prefork/${_mpm}/g" \
+ "$subpkgdir"/usr/share/apache2/build-${_mpm}/config.nice \
+ || return 1
+
+
+ _mpm="worker"
+ install -d "$subpkgdir"/usr/share/apache2/build-${_mpm} || return 1
+ for _file in `ls -1 "$subpkgdir"/usr/share/apache2/build-prefork | grep -v "config\.nice"`; do
+ mv "$srcdir"/httpd-${_mpm}/build/${_file} \
+ "$subpkgdir"/usr/share/apache2/build-${_mpm}/${_file} \
+ || return 1
+ done
+ cp -a "$subpkgdir"/usr/share/apache2/build-prefork/config.nice \
+ "$subpkgdir"/usr/share/apache2/build-${_mpm}/config.nice \
+ || return 1
+ sed -ri "s/prefork/${_mpm}/g" \
+ "$subpkgdir"/usr/share/apache2/build-${_mpm}/config.nice \
+ || return 1
+}
+
+utils() {
+ local _bin
+ pkgdesc="Apache utility programs for webservers"
+
+ install -d "$subpkgdir"/usr/bin || return 1
+ for _bin in ab dbmmanage htdbm htdigest htpasswd logresolve; do
+ mv "$pkgdir"/usr/sbin/${_bin} \
+ "$subpkgdir"/usr/bin/${_bin} || return 1
+ done
+
+ install -d "$subpkgdir"/usr/sbin || return 1
+ for _bin in checkgid htcacheclean rotatelogs; do
+ mv "$pkgdir"/usr/sbin/${_bin} \
+ "$subpkgdir"/usr/sbin/${_bin} || return 1
+ done
+}
+
+ssl() {
+ pkgdesc="SSL/TLS module for the Apache HTTP Server"
+ install="apache2-ssl.post-install"
+ depends="apache2 openssl"
+
+ install -d "$subpkgdir"/usr/lib/apache2 || return 1
+ mv "$pkgdir"/usr/lib/apache2/mod_ssl.so \
+ "$subpkgdir"/usr/lib/apache2/mod_ssl.so || return 1
+ install -D -m644 "$srcdir"/ssl.conf \
+ "$subpkgdir"/etc/apache2/conf.d/ssl.conf || return 1
+ install -d "$subpkgdir"/etc/ssl/apache2 || return 1
+}
+
+ldap() {
+ pkgdesc="LDAP authentication/authorization module for the Apache HTTP Server"
+ url="http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html"
+ depends="apache2"
+
+ install -d "$subpkgdir"/usr/lib/apache2 || return 1
+ mv "$pkgdir"/usr/lib/apache2/mod_ldap.so \
+ "$subpkgdir"/usr/lib/apache2/mod_ldap.so || return 1
+ install -D -m644 "$srcdir"/ldap.conf \
+ "$subpkgdir"/etc/apache2/conf.d/ldap.conf || return 1
+}
+
+md5sums="16eadc59ea6b38af33874d300973202e httpd-2.2.17.tar.bz2
+db42cfcc18ae1c32aaaff2347e35b79d 02-rename-prefork-to-itk.patch
+131408ad4dc7b18547b4e062e7e495ab 03-add-mpm-to-build-system.patch
+ee488f391054d528547c3a372faa2aa7 04-correct-output-makefile-location.patch
+b202944761b2f0516196488b12504236 05-add-copyright.patch
+78fa15f8ca3a284b7d71f942e24e47fb 06-hook-just-after-merging-perdir-config.patch
+d33e39350e987721d50e6fb8e164ab6b 07-base-functionality.patch
+9f7a8935f9cabc7b46d0052906634cef 08-max-clients-per-vhost.patch
+1b28e3363e1b0d05b738a21e7ddd264f 09-capabilities.patch
+d9667fcd2ffecc63e446edd4d6666731 10-nice.patch
+e322b5211e49511cac6e40c86af1b1da apache2.confd
+75fe4138b98fcffd01b8c8c077b944f3 apache2.logrotate
+0261136ff734c3ae8dcf878a46ed5830 apache2.initd
+749faf0b2916d85d1240bc34f700e5d9 httpd.conf
+5d0d024ca43571b863874ab871b2c109 ssl.conf
+b70fe826486043e3953cfe21f9e6fa16 ldap.conf
+c66ff5f70260d5266e6803a59b39bd7f alpine.layout"
diff --git a/main/apache2/alpine.layout b/main/apache2/alpine.layout
new file mode 100644
index 0000000000..99f20df529
--- /dev/null
+++ b/main/apache2/alpine.layout
@@ -0,0 +1,22 @@
+<Layout Alpine>
+ prefix: /usr
+ exec_prefix: ${prefix}
+ bindir: ${prefix}/bin
+ sbindir: ${prefix}/sbin
+ libdir: ${prefix}/lib
+ libexecdir: ${prefix}/lib+
+ mandir: ${prefix}/share/man
+ sysconfdir: /etc+
+ datadir: ${prefix}/share+
+ installbuilddir: ${datadir}/build
+ errordir: ${datadir}/error
+ iconsdir: ${datadir}/icons
+ htdocsdir: /var/www/localhost/htdocs
+ manualdir: /usr/share/doc/apache2/manual
+ cgidir: /var/www/cgi-bin
+ includedir: /usr/include+
+ localstatedir: /var
+ runtimedir: ${localstatedir}/run+
+ logfiledir: ${localstatedir}/log+
+ proxycachedir: ${localstatedir}/cache+
+</Layout>
diff --git a/main/apache2/apache2-ssl.post-install b/main/apache2/apache2-ssl.post-install
new file mode 100644
index 0000000000..d73b5fc622
--- /dev/null
+++ b/main/apache2/apache2-ssl.post-install
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+ssldir=/etc/ssl/apache2
+sslkey=$ssldir/server.key
+sslcert=$ssldir/server.pem
+
+umask 077
+
+if [ ! -f ${sslkey} ] ; then
+ openssl genrsa -rand /proc/apm:/proc/cpuinfo:/proc/dma:/proc/filesystems:/proc/interrupts:/proc/ioports:/proc/pci:/proc/rtc:/proc/uptime 1024 > ${sslkey} 2> /dev/null
+fi
+
+FQDN=`hostname -f`
+if [ "x${FQDN}" = "x" ]; then
+ FQDN=localhost.localdomain
+fi
+
+if [ ! -f ${sslcert} ] ; then
+cat << EOF | openssl req -new -key ${sslkey} \
+ -x509 -days 365 -set_serial $RANDOM \
+ -out ${sslcert} 2>/dev/null
+--
+SomeState
+SomeCity
+SomeOrganization
+SomeOrganizationalUnit
+${FQDN}
+root@${FQDN}
+EOF
+fi
+
+
diff --git a/main/apache2/apache2.confd b/main/apache2/apache2.confd
new file mode 100644
index 0000000000..faf02fa979
--- /dev/null
+++ b/main/apache2/apache2.confd
@@ -0,0 +1,54 @@
+# /etc/conf.d/apache2: config file for /etc/init.d/apache2
+
+#
+# The default processing model (MPM) is the process-based
+# 'prefork' model. A thread-based model, 'worker', is also
+# available, but does not work with some modules (such as PHP).
+#
+#HTTPD=/usr/sbin/httpd.worker
+
+HTTPD="/usr/sbin/httpd"
+
+#
+# To pass additional options (for instance, -D definitions) to the
+# httpd binary at startup, set HTTPD_OPTS here.
+#
+HTTPD_OPTS=
+
+# Extended options for advanced uses of Apache ONLY
+# You don't need to edit these unless you are doing crazy Apache stuff
+# As not having them set correctly, or feeding in an incorrect configuration
+# via them will result in Apache failing to start
+# YOU HAVE BEEN WARNED.
+
+# PID file
+#PIDFILE=/var/run/apache2/httpd.pid
+
+# timeout for startup/shutdown checks
+#TIMEOUT=10
+
+# ServerRoot setting
+#SERVERROOT=/var/www
+
+# Configuration file location
+# - If this does NOT start with a '/', then it is treated relative to
+# $SERVERROOT by Apache
+#CONFIGFILE=/etc/apache2/httpd.conf
+
+# Location to log startup errors to
+# They are normally dumped to your terminal.
+#STARTUPERRORLOG="/var/log/apache2/startuperror.log"
+
+# A command that outputs a formatted text version of the HTML at the URL
+# of the command line. Designed for lynx, however other programs may work.
+#LYNX="lynx -dump"
+
+# The URL to your server's mod_status status page.
+# Required for status and fullstatus
+#STATUSURL="http://localhost/server-status"
+
+# Method to use when reloading the server
+# Valid options are 'restart' and 'graceful'
+# See http://httpd.apache.org/docs/2.2/stopping.html for information on
+# what they do and how they differ.
+#RELOAD_TYPE="graceful"
diff --git a/main/apache2/apache2.initd b/main/apache2/apache2.initd
new file mode 100755
index 0000000000..03a6d03032
--- /dev/null
+++ b/main/apache2/apache2.initd
@@ -0,0 +1,154 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+opts="configdump configtest fullstatus graceful gracefulstop modules reload virtualhosts"
+
+depend() {
+ need net
+ use mysql dns logger netmount postgresql
+ after sshd
+}
+
+configtest() {
+ ebegin "Checking ${SVCNAME} configuration"
+ checkconfig
+ eend $?
+}
+
+checkconfd() {
+ PIDFILE="${PIDFILE:-/var/run/apache2/httpd.pid}"
+ TIMEOUT=${TIMEOUT:-10}
+
+ SERVERROOT="${SERVERROOT:-/var/www}"
+ if [ ! -d ${SERVERROOT} ]; then
+ eerror "SERVERROOT does not exist: ${SERVERROOT}"
+ return 1
+ fi
+
+ CONFIGFILE="${CONFIGFILE:-/etc/apache2/httpd.conf}"
+ [ "${CONFIGFILE#/}" = "${CONFIGFILE}" ] && CONFIGFILE="${SERVERROOT}/${CONFIGFILE}"
+ if [ ! -r "${CONFIGFILE}" ]; then
+ eerror "Unable to read configuration file: ${CONFIGFILE}"
+ return 1
+ fi
+
+ HTTPD_OPTS="${HTTPD_OPTS} -d ${SERVERROOT}"
+ HTTPD_OPTS="${HTTPD_OPTS} -f ${CONFIGFILE}"
+ [ -n "${STARTUPERRORLOG}" ] && HTTPD_OPTS="${HTTPD_OPTS} -E ${STARTUPERRORLOG}"
+ return 0
+
+}
+
+checkconfig() {
+ checkconfd || return 1
+
+ ${HTTPD} ${HTTPD_OPTS} -t 1>/dev/null 2>&1
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ eerror "${SVCNAME} has detected an error in your setup:"
+ ${HTTPD} ${HTTPD_OPTS} -t
+ fi
+
+ return $ret
+}
+
+start() {
+ checkconfig || return 1
+
+ [ -f /var/log/apache2/ssl_scache ] && rm /var/log/apache2/ssl_scache
+
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start \
+ --pidfile ${PIDFILE} \
+ --exec ${HTTPD} \
+ -- ${HTTPD_OPTS} -k start
+ eend $?
+}
+
+stop() {
+ checkconfd || return 1
+
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --pidfile ${PIDFILE} --exec ${HTTPD} \
+ --retry ${TIMEOUT}
+ eend $?
+}
+
+reload() {
+ RELOAD_TYPE="${RELOAD_TYPE:-graceful}"
+
+ checkconfig || return 1
+ service_started "${SVCNAME}" || return
+
+ if [ "${RELOAD_TYPE}" = "restart" ]; then
+ ebegin "Restarting ${SVCNAME}"
+ ${HTTPD} ${HTTPD_OPTS} -k restart
+ eend $?
+ elif [ "${RELOAD_TYPE}" = "graceful" ]; then
+ ebegin "Gracefully restarting ${SVCNAME}"
+ ${HTTPD} ${HTTPD_OPTS} -k graceful
+ eend $?
+ else
+ eerror "${RELOAD_TYPE} is not a valid RELOAD_TYPE. Please edit /etc/conf.d/${SVCNAME}"
+ fi
+}
+
+graceful() {
+ checkconfig || return 1
+ service_started "${SVCNAME}" || return
+ ebegin "Gracefully restarting ${SVCNAME}"
+ ${HTTPD} ${HTTPD_OPTS} -k graceful
+ eend $?
+}
+
+gracefulstop() {
+ checkconfig || return 1
+ ebegin "Gracefully stopping ${SVCNAME}"
+ start-stop-daemon --stop --pidfile ${PIDFILE} --exec ${HTTPD} \
+ --retry SIGWINCH/${TIMEOUT}
+ eend $?
+}
+
+modules() {
+ checkconfig || return 1
+
+ ${HTTPD} ${HTTPD_OPTS} -M 2>&1
+}
+
+fullstatus() {
+ LYNX="${LYNX:-lynx -dump}"
+ STATUSURL="${STATUSURL:-http://localhost/server-status}"
+
+ if ! service_started "${SVCNAME}"; then
+ eerror "${SVCNAME} not started"
+ elif ! type -p $(set -- ${LYNX}; echo $1) 2>&1 >/dev/null; then
+ eerror "lynx not found! you need to emerge www-client/lynx"
+ else
+ ${LYNX} ${STATUSURL}
+ fi
+}
+
+virtualhosts() {
+ checkconfd || return 1
+ ${HTTPD} ${HTTPD_OPTS} -S
+}
+
+configdump() {
+ LYNX="${LYNX:-lynx -dump}"
+ INFOURL="${INFOURL:-http://localhost/server-info}"
+
+ checkconfd || return 1
+
+ if ! service_started "${SVCNAME}"; then
+ eerror "${SVCNAME} not started"
+ elif ! type -p $(set -- ${LYNX}; echo $1) 2>&1 >/dev/null; then
+ eerror "lynx not found! you need to emerge www-client/lynx"
+ else
+ echo "${HTTPD} started with '${HTTPD_OPTS}'"
+ for i in config server list; do
+ ${LYNX} "${INFOURL}/?${i}" | sed '/Apache Server Information/d;/^[[:space:]]\+[_]\+$/Q'
+ done
+ fi
+}
+
diff --git a/main/apache2/apache2.logrotate b/main/apache2/apache2.logrotate
new file mode 100644
index 0000000000..fe19a4381f
--- /dev/null
+++ b/main/apache2/apache2.logrotate
@@ -0,0 +1,10 @@
+/var/log/apache2/*log {
+ missingok
+ notifempty
+ sharedscripts
+ delaycompress
+ postrotate
+ /sbin/rc-service --quiet apache2 reload > /dev/null 2>/dev/null || true
+ endscript
+}
+
diff --git a/main/apache2/httpd.conf b/main/apache2/httpd.conf
new file mode 100644
index 0000000000..087f3fb8c2
--- /dev/null
+++ b/main/apache2/httpd.conf
@@ -0,0 +1,1026 @@
+#
+# This is the main Apache server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.2/> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.2/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+# The configuration directives are grouped into three basic sections:
+# 1. Directives that control the operation of the Apache server process as a
+# whole (the 'global environment').
+# 2. Directives that define the parameters of the 'main' or 'default' server,
+# which responds to requests that aren't handled by a virtual host.
+# These directives also provide default values for the settings
+# of all virtual hosts.
+# 3. Settings for virtual hosts, which allow Web requests to be sent to
+# different IP addresses or hostnames and have them handled by the
+# same Apache server process.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path. If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"
+# with ServerRoot set to "/etc/httpd" will be interpreted by the
+# server as "/etc/httpd/logs/foo.log".
+#
+
+### Section 1: Global Environment
+#
+# The directives in this section affect the overall operation of Apache,
+# such as the number of concurrent requests it can handle or where it
+# can find its configuration files.
+#
+
+#
+# Don't give away too much information about all the subcomponents
+# we are running. Comment out this line if you don't mind remote sites
+# finding out what major optional modules you are running
+ServerTokens OS
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# NOTE! If you intend to place this on an NFS (or otherwise network)
+# mounted filesystem then please read the LockFile documentation
+# (available at <URL:http://httpd.apache.org/docs/2.2/mod/mpm_common.html#lockfile>);
+# you will save yourself a lot of trouble.
+#
+# Do NOT add a slash at the end of the directory path.
+#
+ServerRoot "/var/www"
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts. Note the PIDFILE variable in
+# /etc/conf.d/apache2 must be set appropriately if this location is
+# changed.
+#
+PidFile run/httpd.pid
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 60
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive Off
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 5
+
+##
+## Server-Pool Size Regulation (MPM specific)
+##
+
+# prefork MPM
+# StartServers: number of server processes to start
+# MinSpareServers: minimum number of server processes which are kept spare
+# MaxSpareServers: maximum number of server processes which are kept spare
+# ServerLimit: maximum value for MaxClients for the lifetime of the server
+# MaxClients: maximum number of server processes allowed to start
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule prefork.c>
+StartServers 8
+MinSpareServers 5
+MaxSpareServers 20
+ServerLimit 256
+MaxClients 256
+MaxRequestsPerChild 4000
+</IfModule>
+
+# itk MPM
+# AssignUserID: takes two parameters, uid and gid (or really, user name and
+# group name); specifies what uid and gid the vhost will run as
+# (after parsing the request etc., of course).
+# MaxClientsVHost: a separate MaxClients for each vhost.
+# NiceValue: lets you nice some requests down, to give them less CPU time.
+#
+# AssignUserID and NiceValue can be set wherever you'd like in the Apache
+# configuration, except in .htaccess. MaxClientsVHost can only be set inside
+# a VirtualHost directive.
+<IfModule itk.c>
+AssignUserID apache apache
+StartServers 8
+MinSpareServers 5
+MaxSpareServers 20
+ServerLimit 256
+MaxClients 256
+MaxRequestsPerChild 4000
+</IfModule>
+
+# worker MPM
+# StartServers: initial number of server processes to start
+# MaxClients: maximum number of simultaneous client connections
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule worker.c>
+StartServers 4
+MaxClients 300
+MinSpareThreads 25
+MaxSpareThreads 75
+ThreadsPerChild 25
+MaxRequestsPerChild 0
+</IfModule>
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, in addition to the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses (0.0.0.0)
+#
+#Listen 12.34.56.78:80
+Listen 80
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+LoadModule auth_basic_module modules/mod_auth_basic.so
+LoadModule auth_digest_module modules/mod_auth_digest.so
+LoadModule authn_file_module modules/mod_authn_file.so
+LoadModule authn_alias_module modules/mod_authn_alias.so
+LoadModule authn_anon_module modules/mod_authn_anon.so
+LoadModule authn_dbm_module modules/mod_authn_dbm.so
+LoadModule authn_default_module modules/mod_authn_default.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_user_module modules/mod_authz_user.so
+LoadModule authz_owner_module modules/mod_authz_owner.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_dbm_module modules/mod_authz_dbm.so
+LoadModule authz_default_module modules/mod_authz_default.so
+LoadModule include_module modules/mod_include.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule logio_module modules/mod_logio.so
+LoadModule env_module modules/mod_env.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+LoadModule mime_magic_module modules/mod_mime_magic.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule deflate_module modules/mod_deflate.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule usertrack_module modules/mod_usertrack.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule dav_module modules/mod_dav.so
+LoadModule status_module modules/mod_status.so
+LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule info_module modules/mod_info.so
+LoadModule dav_fs_module modules/mod_dav_fs.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule speling_module modules/mod_speling.so
+LoadModule userdir_module modules/mod_userdir.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule substitute_module modules/mod_substitute.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule proxy_module modules/mod_proxy.so
+LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
+LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
+LoadModule proxy_http_module modules/mod_proxy_http.so
+LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
+LoadModule proxy_connect_module modules/mod_proxy_connect.so
+LoadModule cache_module modules/mod_cache.so
+LoadModule suexec_module modules/mod_suexec.so
+LoadModule disk_cache_module modules/mod_disk_cache.so
+LoadModule cgi_module modules/mod_cgi.so
+LoadModule version_module modules/mod_version.so
+
+#
+# The following modules are not loaded by default:
+#
+#LoadModule asis_module modules/mod_asis.so
+#LoadModule authn_dbd_module modules/mod_authn_dbd.so
+#LoadModule cern_meta_module modules/mod_cern_meta.so
+#LoadModule cgid_module modules/mod_cgid.so
+#LoadModule dbd_module modules/mod_dbd.so
+#LoadModule dumpio_module modules/mod_dumpio.so
+#LoadModule filter_module modules/mod_filter.so
+#LoadModule ident_module modules/mod_ident.so
+#LoadModule log_forensic_module modules/mod_log_forensic.so
+#LoadModule unique_id_module modules/mod_unique_id.so
+#
+
+#
+# Load config files from the config directory "/etc/apache2/conf.d".
+#
+Include /etc/apache2/conf.d/*.conf
+
+#
+# ExtendedStatus controls whether Apache will generate "full" status
+# information (ExtendedStatus On) or just basic information (ExtendedStatus
+# Off) when the "server-status" handler is called. The default is Off.
+#
+#ExtendedStatus On
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# . On SCO (ODT 3) use "User nouser" and "Group nogroup".
+# . On HPUX you may not be able to use shared memory as nobody, and the
+# suggested workaround is to create a user www and use that user.
+# NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET)
+# when the value of (unsigned)Group is above 60000;
+# don't use Group #-1 on these systems!
+#
+User apache
+Group apache
+
+### Section 2: 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition. These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed. This address appears on some server-generated pages, such
+# as error documents. e.g. admin@your-domain.com
+#
+ServerAdmin root@localhost
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If this is not set to valid DNS name for your host, server-generated
+# redirections will not work. See also the UseCanonicalName directive.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+# You will have to access it by its address anyway, and this will make
+# redirections work in a sensible way.
+#
+#ServerName www.example.com:80
+
+#
+# UseCanonicalName: Determines how Apache constructs self-referencing
+# URLs and the SERVER_NAME and SERVER_PORT variables.
+# When set "Off", Apache will use the Hostname and Port supplied
+# by the client. When set "On", Apache will use the value of the
+# ServerName directive.
+#
+UseCanonicalName Off
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/var/www/localhost/htdocs"
+
+#
+# Each directory to which Apache has access can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories).
+#
+# First, we configure the "default" to be a very restrictive set of
+# features.
+#
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# This should be changed to whatever you set DocumentRoot to.
+#
+<Directory "/var/www/localhost/htdocs">
+
+#
+# Possible values for the Options directive are "None", "All",
+# or any combination of:
+# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+#
+# Note that "MultiViews" must be named *explicitly* --- "Options All"
+# doesn't give it to you.
+#
+# The Options directive is both complicated and important. Please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#options
+# for more information.
+#
+ Options Indexes FollowSymLinks
+
+#
+# AllowOverride controls what directives may be placed in .htaccess files.
+# It can be "All", "None", or any combination of the keywords:
+# Options FileInfo AuthConfig Limit
+#
+ AllowOverride None
+
+#
+# Controls who can get stuff from this server.
+#
+ Order allow,deny
+ Allow from all
+
+</Directory>
+
+#
+# UserDir: The name of the directory that is appended onto a user's home
+# directory if a ~user request is received.
+#
+# The path to the end user account 'public_html' directory must be
+# accessible to the webserver userid. This usually means that ~userid
+# must have permissions of 711, ~userid/public_html must have permissions
+# of 755, and documents contained therein must be world-readable.
+# Otherwise, the client will only receive a "403 Forbidden" message.
+#
+# See also: http://httpd.apache.org/docs/misc/FAQ.html#forbidden
+#
+<IfModule mod_userdir.c>
+ #
+ # UserDir is disabled by default since it can confirm the presence
+ # of a username on the system (depending on home directory
+ # permissions).
+ #
+ UserDir disabled
+
+ #
+ # To enable requests to /~user/ to serve the user's public_html
+ # directory, remove the "UserDir disabled" line above, and uncomment
+ # the following line instead:
+ #
+ #UserDir public_html
+
+</IfModule>
+
+#
+# Control access to UserDir directories. The following is an example
+# for a site where these directories are restricted to read-only.
+#
+#<Directory /home/*/public_html>
+# AllowOverride FileInfo AuthConfig Limit
+# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+# <Limit GET POST OPTIONS>
+# Order allow,deny
+# Allow from all
+# </Limit>
+# <LimitExcept GET POST OPTIONS>
+# Order deny,allow
+# Deny from all
+# </LimitExcept>
+#</Directory>
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+# The index.html.var file (a type-map) is used to deliver content-
+# negotiated documents. The MultiViews Option can be used for the
+# same purpose, but it is much slower.
+#
+DirectoryIndex index.html index.html.var
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<Files ~ "^\.ht">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Files>
+
+#
+# TypesConfig describes where the mime.types file (or equivalent) is
+# to be found.
+#
+TypesConfig /etc/apache2/mime.types
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value. If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+#
+# The mod_mime_magic module allows the server to use various hints from the
+# contents of the file itself to determine its type. The MIMEMagicFile
+# directive tells the module where the hint definitions are located.
+#
+<IfModule mod_mime_magic.c>
+ MIMEMagicFile /etc/apache2/magic
+</IfModule>
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+#
+# EnableMMAP: Control whether memory-mapping is used to deliver
+# files (assuming that the underlying OS supports it).
+# The default is on; turn this off if you serve from NFS-mounted
+# filesystems. On some systems, turning it off (regardless of
+# filesystem) can improve performance; for details, please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#enablemmap
+#
+#EnableMMAP off
+
+#
+# EnableSendfile: Control whether the sendfile kernel support is
+# used to deliver files (assuming that the OS supports it).
+# The default is on; turn this off if you serve from NFS-mounted
+# filesystems. Please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile
+#
+#EnableSendfile off
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog logs/error.log
+
+#
+# LogLevel: Control the number of messages logged to the error.log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# "combinedio" includes actual counts of actual bytes received (%I) and sent (%O); this
+# requires the mod_logio module to be loaded.
+#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+
+#
+# The location and format of the access logfile (Common Logfile Format).
+# If you do not define any access logfiles within a <VirtualHost>
+# container, they will be logged here. Contrariwise, if you *do*
+# define per-<VirtualHost> access logfiles, transactions will be
+# logged therein and *not* in this file.
+#
+#CustomLog logs/access.log common
+
+#
+# If you would like to have separate agent and referer logfiles, uncomment
+# the following directives.
+#
+#CustomLog logs/referer.log referer
+#CustomLog logs/agent.log agent
+
+#
+# For a single logfile with access, agent, and referer information
+# (Combined Logfile Format), use the following directive:
+#
+CustomLog logs/access.log combined
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#
+ServerSignature On
+
+#
+# Aliases: Add here as many aliases as you need (with no limit). The format is
+# Alias fakename realname
+#
+# Note that if you include a trailing / on fakename then the server will
+# require it to be present in the URL. So "/icons" isn't aliased in this
+# example, only "/icons/". If the fakename is slash-terminated, then the
+# realname must also be slash terminated, and if the fakename omits the
+# trailing slash, the realname must also omit it.
+#
+# We include the /icons/ alias for FancyIndexed directory listings. If you
+# do not use FancyIndexing, you may comment this out.
+#
+Alias /icons/ "/usr/share/apache2/icons/"
+
+<Directory "/usr/share/apache2/icons">
+ Options Indexes MultiViews FollowSymLinks
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+</Directory>
+
+#
+# WebDAV module configuration section.
+#
+<IfModule mod_dav_fs.c>
+ # Location of the WebDAV lock database.
+ DAVLockDB /var/lib/dav/lockdb
+</IfModule>
+
+#
+# ScriptAlias: This controls which directories contain server scripts.
+# ScriptAliases are essentially the same as Aliases, except that
+# documents in the realname directory are treated as applications and
+# run by the server when requested rather than as documents sent to the client.
+# The same rules about trailing "/" apply to ScriptAlias directives as to
+# Alias.
+#
+ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+
+#
+# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+<Directory "/var/www/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+</Directory>
+
+#
+# Redirect allows you to tell clients about documents which used to exist in
+# your server's namespace, but do not anymore. This allows you to tell the
+# clients where to look for the relocated document.
+# Example:
+# Redirect permanent /foo http://www.example.com/bar
+
+#
+# Directives controlling the display of server-generated directory listings.
+#
+
+#
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+#
+IndexOptions FancyIndexing VersionSort NameWidth=* HTMLTable Charset=UTF-8
+
+#
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions. These are only displayed for
+# FancyIndexed directories.
+#
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+AddIcon /icons/bomb.gif core
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+#
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+#
+DefaultIcon /icons/unknown.gif
+
+#
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes. These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+#
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+#
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+#
+# HeaderName is the name of a file which should be prepended to
+# directory indexes.
+ReadmeName README.html
+HeaderName HEADER.html
+
+#
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing. Shell-style wildcarding is permitted.
+#
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
+
+#
+# DefaultLanguage and AddLanguage allows you to specify the language of
+# a document. You can then use content negotiation to give a browser a
+# file in a language the user can understand.
+#
+# Specify a default language. This means that all data
+# going out without a specific language tag (see below) will
+# be marked with this one. You probably do NOT want to set
+# this unless you are sure it is correct for all cases.
+#
+# * It is generally better to not mark a page as
+# * being a certain language than marking it with the wrong
+# * language!
+#
+# DefaultLanguage nl
+#
+# Note 1: The suffix does not have to be the same as the language
+# keyword --- those with documents in Polish (whose net-standard
+# language code is pl) may wish to use "AddLanguage pl .po" to
+# avoid the ambiguity with the common suffix for perl scripts.
+#
+# Note 2: The example entries below illustrate that in some cases
+# the two character 'Language' abbreviation is not identical to
+# the two character 'Country' code for its country,
+# E.g. 'Danmark/dk' versus 'Danish/da'.
+#
+# Note 3: In the case of 'ltz' we violate the RFC by using a three char
+# specifier. There is 'work in progress' to fix this and get
+# the reference data for rfc1766 cleaned up.
+#
+# Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl)
+# English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de)
+# Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja)
+# Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn)
+# Norwegian (no) - Polish (pl) - Portugese (pt)
+# Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv)
+# Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW)
+#
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+#
+# LanguagePriority allows you to give precedence to some languages
+# in case of a tie during content negotiation.
+#
+# Just list the languages in decreasing order of preference. We have
+# more or less alphabetized them here. You probably want to change this.
+#
+LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
+
+#
+# ForceLanguagePriority allows you to serve a result page rather than
+# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback)
+# [in case no accepted languages matched the available variants]
+#
+ForceLanguagePriority Prefer Fallback
+
+#
+# Specify a default charset for all content served; this enables
+# interpretation of all content as UTF-8 by default. To use the
+# default browser choice (ISO-8859-1), or to allow the META tags
+# in HTML content to override this choice, comment out this
+# directive:
+#
+AddDefaultCharset UTF-8
+
+#
+# AddType allows you to add to or override the MIME configuration
+# file mime.types for specific file types.
+#
+#AddType application/x-tar .tgz
+
+#
+# AddEncoding allows you to have certain browsers uncompress
+# information on the fly. Note: Not all browsers support this.
+# Despite the name similarity, the following Add* directives have nothing
+# to do with the FancyIndexing customization directives above.
+#
+#AddEncoding x-compress .Z
+#AddEncoding x-gzip .gz .tgz
+
+# If the AddEncoding directives above are commented-out, then you
+# probably should define those extensions to indicate media types:
+#
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+
+#
+# MIME-types for downloading Certificates and CRLs
+#
+AddType application/x-x509-ca-cert .crt
+AddType application/x-pkcs7-crl .crl
+
+#
+# AddHandler allows you to map certain file extensions to "handlers":
+# actions unrelated to filetype. These can be either built into the server
+# or added with the Action directive (see below)
+#
+# To use CGI scripts outside of ScriptAliased directories:
+# (You will also need to add "ExecCGI" to the "Options" directive.)
+#
+#AddHandler cgi-script .cgi
+
+#
+# For files that include their own HTTP headers:
+#
+#AddHandler send-as-is asis
+
+#
+# For type maps (negotiated resources):
+# (This is enabled by default to allow the Apache "It Worked" page
+# to be distributed in multiple languages.)
+#
+AddHandler type-map var
+
+#
+# Filters allow you to process content before it is sent to the client.
+#
+# To parse .shtml files for server-side includes (SSI):
+# (You will also need to add "Includes" to the "Options" directive.)
+#
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
+
+#
+# Action lets you define media types that will execute a script whenever
+# a matching file is called. This eliminates the need for repeated URL
+# pathnames for oft-used CGI file processors.
+# Format: Action media/type /cgi-script/location
+# Format: Action handler-name /cgi-script/location
+#
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# Putting this all together, we can internationalize error responses.
+#
+# We use Alias to redirect any /error/HTTP_<error>.html.var response to
+# our collection of by-error message multi-language collections. We use
+# includes to substitute the appropriate text.
+#
+# You can modify the messages' appearance without changing any of the
+# default HTTP_<error>.html.var files by adding the line:
+#
+# Alias /error/include/ "/your/include/path/"
+#
+# which allows you to create your own set of files by starting with the
+# /var/www/error/include/ files and
+# copying them to /your/include/path/, even on a per-VirtualHost basis.
+#
+
+Alias /error/ "/usr/share/apache2/error/"
+
+<IfModule mod_negotiation.c>
+<IfModule mod_include.c>
+ <Directory "/usr/share/apache2/error">
+ AllowOverride None
+ Options IncludesNoExec
+ AddOutputFilter Includes html
+ AddHandler type-map var
+ Order allow,deny
+ Allow from all
+ LanguagePriority en es de fr
+ ForceLanguagePriority Prefer Fallback
+ </Directory>
+
+# ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
+# ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
+# ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
+# ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
+# ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
+# ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
+# ErrorDocument 410 /error/HTTP_GONE.html.var
+# ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
+# ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
+# ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
+# ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
+# ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
+# ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
+# ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
+# ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
+# ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
+# ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
+
+</IfModule>
+</IfModule>
+
+#
+# The following directives modify normal HTTP response behavior to
+# handle known problems with browser implementations.
+#
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+BrowserMatch "RealPlayer 4\.0" force-response-1.0
+BrowserMatch "Java/1\.0" force-response-1.0
+BrowserMatch "JDK/1\.0" force-response-1.0
+
+#
+# The following directive disables redirects on non-GET requests for
+# a directory that does not include the trailing slash. This fixes a
+# problem with Microsoft WebFolders which does not appropriately handle
+# redirects for folders with DAV methods.
+# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
+#
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "MS FrontPage" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
+BrowserMatch "^gnome-vfs/1.0" redirect-carefully
+BrowserMatch "^XML Spy" redirect-carefully
+BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
+
+#
+# Allow server status reports generated by mod_status,
+# with the URL of http://servername/server-status
+# Change the ".example.com" to match your domain to enable.
+#
+#<Location /server-status>
+# SetHandler server-status
+# Order deny,allow
+# Deny from all
+# Allow from .example.com
+#</Location>
+
+#
+# Allow remote server configuration reports, with the URL of
+# http://servername/server-info (requires that mod_info.c be loaded).
+# Change the ".example.com" to match your domain to enable.
+#
+#<Location /server-info>
+# SetHandler server-info
+# Order deny,allow
+# Deny from all
+# Allow from .example.com
+#</Location>
+
+#
+# Proxy Server directives. Uncomment the following lines to
+# enable the proxy server:
+#
+#<IfModule mod_proxy.c>
+#ProxyRequests On
+#
+#<Proxy *>
+# Order deny,allow
+# Deny from all
+# Allow from .example.com
+#</Proxy>
+
+#
+# Enable/disable the handling of HTTP/1.1 "Via:" headers.
+# ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+# Set to one of: Off | On | Full | Block
+#
+#ProxyVia On
+
+#
+# To enable a cache of proxied content, uncomment the following lines.
+# See http://httpd.apache.org/docs/2.2/mod/mod_cache.html for more details.
+#
+#<IfModule mod_disk_cache.c>
+# CacheEnable disk /
+# CacheRoot "/var/cache/mod_proxy"
+#</IfModule>
+#
+
+#</IfModule>
+# End of proxy directives.
+
+### Section 3: Virtual Hosts
+#
+# VirtualHost: If you want to maintain multiple domains/hostnames on your
+# machine you can setup VirtualHost containers for them. Most configurations
+# use only name-based virtual hosts so the server doesn't need to worry about
+# IP addresses. This is indicated by the asterisks in the directives below.
+#
+# Please see the documentation at
+# <URL:http://httpd.apache.org/docs/2.2/vhosts/>
+# for further details before you try to setup virtual hosts.
+#
+# You may use the command line option '-S' to verify your virtual host
+# configuration.
+
+#
+# Use name-based virtual hosting.
+#
+#NameVirtualHost *:80
+#
+# NOTE: NameVirtualHost cannot be used without a port specifier
+# (e.g. :80) if mod_ssl is being used, due to the nature of the
+# SSL protocol.
+#
+
+#
+# VirtualHost example:
+# Almost any Apache directive may go into a VirtualHost container.
+# The first VirtualHost section is used for requests without a known
+# server name.
+#
+#<VirtualHost *:80>
+# ServerAdmin webmaster@dummy-host.example.com
+# DocumentRoot /var/www/dummy-host.example.com/htdocs
+# ServerName dummy-host.example.com
+# ErrorLog logs/dummy-host.example.com-error.log
+# CustomLog logs/dummy-host.example.com-access.log common
+#</VirtualHost>
diff --git a/main/apache2/ldap.conf b/main/apache2/ldap.conf
new file mode 100644
index 0000000000..81fe42fa0f
--- /dev/null
+++ b/main/apache2/ldap.conf
@@ -0,0 +1,2 @@
+LoadModule ldap_module modules/mod_ldap.so
+LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
diff --git a/main/apache2/ssl.conf b/main/apache2/ssl.conf
new file mode 100644
index 0000000000..8b156ebbc6
--- /dev/null
+++ b/main/apache2/ssl.conf
@@ -0,0 +1,223 @@
+#
+# This is the Apache server configuration file providing SSL support.
+# It contains the configuration directives to instruct the server how to
+# serve pages over an https connection. For detailing information about these
+# directives see <URL:http://httpd.apache.org/docs/2.2/mod/mod_ssl.html>
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+
+LoadModule ssl_module modules/mod_ssl.so
+
+#
+# When we also provide SSL we have to listen to the
+# the HTTPS port in addition.
+#
+Listen 443
+
+##
+## SSL Global Context
+##
+## All SSL configuration in this context applies both to
+## the main server and all SSL-enabled virtual hosts.
+##
+
+# Pass Phrase Dialog:
+# Configure the pass phrase gathering process.
+# The filtering dialog program (`builtin' is a internal
+# terminal dialog) has to provide the pass phrase on stdout.
+SSLPassPhraseDialog builtin
+
+# Inter-Process Session Cache:
+# Configure the SSL Session Cache: First the mechanism
+# to use and second the expiring timeout (in seconds).
+#SSLSessionCache dc:UNIX:/var/cache/mod_ssl/distcache
+SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
+SSLSessionCacheTimeout 300
+
+# Semaphore:
+# Configure the path to the mutual exclusion semaphore the
+# SSL engine uses internally for inter-process synchronization.
+SSLMutex default
+
+# Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the
+# SSL library. The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. This means you then cannot use the /dev/random device
+# because it would lead to very long connection times (as long as
+# it requires to make more entropy available). But usually those
+# platforms additionally provide a /dev/urandom device which doesn't
+# block. So, if available, use this one instead. Read the mod_ssl User
+# Manual for more details.
+SSLRandomSeed startup file:/dev/urandom 256
+SSLRandomSeed connect builtin
+#SSLRandomSeed startup file:/dev/random 512
+#SSLRandomSeed connect file:/dev/random 512
+#SSLRandomSeed connect file:/dev/urandom 512
+
+#
+# Use "SSLCryptoDevice" to enable any supported hardware
+# accelerators. Use "openssl engine -v" to list supported
+# engine names. NOTE: If you enable an accelerator and the
+# server does not start, consult the error logs and ensure
+# your accelerator is functioning properly.
+#
+SSLCryptoDevice builtin
+#SSLCryptoDevice ubsec
+
+##
+## SSL Virtual Host Context
+##
+
+<VirtualHost _default_:443>
+
+# General setup for the virtual host, inherited from global configuration
+#DocumentRoot "/var/www/html"
+#ServerName www.example.com:443
+
+# Use separate log files for the SSL virtual host; note that LogLevel
+# is not inherited from httpd.conf.
+ErrorLog logs/ssl_error.log
+TransferLog logs/ssl_access.log
+LogLevel warn
+
+# SSL Engine Switch:
+# Enable/Disable SSL for this virtual host.
+SSLEngine on
+
+# SSL Protocol support:
+# List the enable protocol levels with which clients will be able to
+# connect. Disable SSLv2 access by default:
+SSLProtocol all -SSLv2
+
+# SSL Cipher Suite:
+# List the ciphers that the client is permitted to negotiate.
+# See the mod_ssl documentation for a complete list.
+SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
+
+# Server Certificate:
+# Point SSLCertificateFile at a PEM encoded certificate. If
+# the certificate is encrypted, then you will be prompted for a
+# pass phrase. Note that a kill -HUP will prompt again. A new
+# certificate can be generated using the genkey(1) command.
+SSLCertificateFile /etc/ssl/apache2/server.pem
+
+# Server Private Key:
+# If the key is not combined with the certificate, use this
+# directive to point at the key file. Keep in mind that if
+# you've both a RSA and a DSA private key you can configure
+# both in parallel (to also allow the use of DSA ciphers, etc.)
+SSLCertificateKeyFile /etc/ssl/apache2/server.key
+
+# Server Certificate Chain:
+# Point SSLCertificateChainFile at a file containing the
+# concatenation of PEM encoded CA certificates which form the
+# certificate chain for the server certificate. Alternatively
+# the referenced file can be the same as SSLCertificateFile
+# when the CA certificates are directly appended to the server
+# certificate for convinience.
+#SSLCertificateChainFile /etc/ssl/apache2/server-chain.crt
+
+# Certificate Authority (CA):
+# Set the CA certificate verification path where to find CA
+# certificates for client authentication or alternatively one
+# huge file containing all of them (file must be PEM encoded)
+#SSLCACertificateFile /etc/ssl/apache2/ca-bundle.crt
+
+# Client Authentication (Type):
+# Client certificate verification type and depth. Types are
+# none, optional, require and optional_no_ca. Depth is a
+# number which specifies how deeply to verify the certificate
+# issuer chain before deciding the certificate is not valid.
+#SSLVerifyClient require
+#SSLVerifyDepth 10
+
+# Access Control:
+# With SSLRequire you can do per-directory access control based
+# on arbitrary complex boolean expressions containing server
+# variable checks and other lookup directives. The syntax is a
+# mixture between C and Perl. See the mod_ssl documentation
+# for more details.
+#<Location />
+#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
+# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
+# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
+# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
+# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
+# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
+#</Location>
+
+# SSL Engine Options:
+# Set various options for the SSL engine.
+# o FakeBasicAuth:
+# Translate the client X.509 into a Basic Authorisation. This means that
+# the standard Auth/DBMAuth methods can be used for access control. The
+# user name is the `one line' version of the client's X.509 certificate.
+# Note that no password is obtained from the user. Every entry in the user
+# file needs this password: `xxj31ZMTZzkVA'.
+# o ExportCertData:
+# This exports two additional environment variables: SSL_CLIENT_CERT and
+# SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
+# server (always existing) and the client (only existing when client
+# authentication is used). This can be used to import the certificates
+# into CGI scripts.
+# o StdEnvVars:
+# This exports the standard SSL/TLS related `SSL_*' environment variables.
+# Per default this exportation is switched off for performance reasons,
+# because the extraction step is an expensive operation and is usually
+# useless for serving static content. So one usually enables the
+# exportation for CGI and SSI requests only.
+# o StrictRequire:
+# This denies access when "SSLRequireSSL" or "SSLRequire" applied even
+# under a "Satisfy any" situation, i.e. when it applies access is denied
+# and no other module can change it.
+# o OptRenegotiate:
+# This enables optimized SSL connection renegotiation handling when SSL
+# directives are used in per-directory context.
+#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+<Files ~ "\.(cgi|shtml|phtml|php3?)$">
+ SSLOptions +StdEnvVars
+</Files>
+<Directory "/var/www/cgi-bin">
+ SSLOptions +StdEnvVars
+</Directory>
+
+# SSL Protocol Adjustments:
+# The safe and default but still SSL/TLS standard compliant shutdown
+# approach is that mod_ssl sends the close notify alert but doesn't wait for
+# the close notify alert from client. When you need a different shutdown
+# approach you can use one of the following variables:
+# o ssl-unclean-shutdown:
+# This forces an unclean shutdown when the connection is closed, i.e. no
+# SSL close notify alert is send or allowed to received. This violates
+# the SSL/TLS standard but is needed for some brain-dead browsers. Use
+# this when you receive I/O errors because of the standard approach where
+# mod_ssl sends the close notify alert.
+# o ssl-accurate-shutdown:
+# This forces an accurate shutdown when the connection is closed, i.e. a
+# SSL close notify alert is send and mod_ssl waits for the close notify
+# alert of the client. This is 100% SSL/TLS standard compliant, but in
+# practice often causes hanging connections with brain-dead browsers. Use
+# this only for browsers where you know that their SSL implementation
+# works correctly.
+# Notice: Most problems of broken clients are also related to the HTTP
+# keep-alive facility, so you usually additionally want to disable
+# keep-alive for those clients, too. Use variable "nokeepalive" for this.
+# Similarly, one has to force some clients to use HTTP/1.0 to workaround
+# their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
+# "force-response-1.0" for this.
+SetEnvIf User-Agent ".*MSIE.*" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+
+# Per-Server Logging:
+# The home of a custom SSL log file. Use this when you want a
+# compact non-error SSL logfile on a virtual host basis.
+CustomLog logs/ssl_request.log \
+ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
+
+</VirtualHost>
+
diff --git a/main/apcupsd/APKBUILD b/main/apcupsd/APKBUILD
new file mode 100644
index 0000000000..596c34abb4
--- /dev/null
+++ b/main/apcupsd/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=apcupsd
+pkgver=3.14.8
+pkgrel=3
+pkgdesc="A Daemon to control APC UPSes"
+subpackages="$pkgname-doc"
+url="http://www.apcupsd.org"
+arch="all"
+license="GPL-2"
+depends="util-linux-ng"
+makedepends="net-snmp-dev man"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ apcupsd.initd
+ apcupsd-alpine.patch
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ patch -p1 < ../apcupsd-alpine.patch || return 1
+
+ ac_cv_path_SHUTDOWN="/sbin/poweroff" \
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --enable-usb \
+ --enable-snmp
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR=$pkgdir install
+ install -D -m755 "$srcdir"/apcupsd.initd "$pkgdir"/etc/init.d/apcupsd
+}
+
+md5sums="cd17f0a903dc2220e55ed54e242359d2 apcupsd-3.14.8.tar.gz
+0798cd407de6f199d4c267036ec54c5b apcupsd.initd
+08d9cc703cdd4275d342882deed1d719 apcupsd-alpine.patch"
diff --git a/main/apcupsd/apcupsd-alpine.patch b/main/apcupsd/apcupsd-alpine.patch
new file mode 100644
index 0000000000..3f5c6965b7
--- /dev/null
+++ b/main/apcupsd/apcupsd-alpine.patch
@@ -0,0 +1,41 @@
+--- a/platforms/apccontrol.in Mon Oct 26 09:12:30 2009
++++ b/platforms/apccontrol.in Mon Oct 26 09:36:47 2009
+@@ -20,11 +20,20 @@
+
+ APCPID=@PIDDIR@/apcupsd.pid
+ APCUPSD=@sbindir@/apcupsd
+-SHUTDOWN=@SHUTDOWN@
++POWEROFF=/sbin/poweroff
++REBOOT=/sbin/reboot
+ SCRIPTSHELL=@SCRIPTSHELL@
+ SCRIPTDIR=@sysconfdir@
+-WALL=wall
++WALL=_wall
+
++_wall() {
++ local i
++ local msg=$(cat)
++ for i in /dev/pts/*; do
++ [ -c "$i" ] && echo "$msg" > $i
++ done
++}
++
+ #
+ # Concatenate all output from this script to the events file
+ # Note, the following kills the script in a power fail situation
+@@ -100,11 +109,13 @@
+ ;;
+ doreboot)
+ echo "UPS ${2} initiating Reboot Sequence" | ${WALL}
+- ${SHUTDOWN} -r now "apcupsd UPS ${2} initiated reboot"
++ echo "apcupsd UPS ${2} initiated reboot" | ${WALL}
++ $REBOOT
+ ;;
+ doshutdown)
+ echo "UPS ${2} initiated Shutdown Sequence" | ${WALL}
+- ${SHUTDOWN} -h now "apcupsd UPS ${2} initiated shutdown"
++ echo "apcupsd UPS ${2} initiated shutdown" | ${WALL}
++ $POWEROFF
+ ;;
+ annoyme)
+ echo "Power problems with UPS ${2}. Please logoff." | ${WALL}
diff --git a/main/apcupsd/apcupsd.initd b/main/apcupsd/apcupsd.initd
new file mode 100644
index 0000000000..5265347f41
--- /dev/null
+++ b/main/apcupsd/apcupsd.initd
@@ -0,0 +1,38 @@
+#!/sbin/runscript
+# Copyright 2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-power/apcupsd/files/apcupsd.init.2,v 1.1 2009/01/15 15:21:11 flameeyes Exp $
+
+INSTANCE="${SVCNAME#*.}"
+if [ -z "${INSTANCE}" ] || [ "${SVCNAME}" = "apcupsd" ]; then
+ INSTANCE="apcupsd"
+fi
+
+depend() {
+ use net
+ after firewall
+}
+
+start() {
+ rm -f /etc/apcupsd/powerfail
+
+ export SERVICE="${SVCNAME}"
+
+ ebegin "Starting APC UPS daemon"
+ start-stop-daemon \
+ --start --pidfile "/var/run/${SVCNAME}.pid" \
+ --exec /sbin/apcupsd -- \
+ -f "/etc/apcupsd/${INSTANCE}.conf" \
+ -P "/var/run/${SVCNAME}.pid"
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping APC UPS daemon"
+ start-stop-daemon \
+ --stop --pidfile "/var/run/${SVCNAME}.pid" \
+ --retry TERM/5/TERM/5 \
+ --exec /sbin/apcupsd
+ eend $?
+}
+
diff --git a/main/apg/APKBUILD b/main/apg/APKBUILD
new file mode 100644
index 0000000000..afbee15d54
--- /dev/null
+++ b/main/apg/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=apg
+pkgver=2.2.3
+pkgrel=2
+pkgdesc="Automated Password Generator."
+url="http://www.adel.nursat.kz/apg/index.shtml"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends=""
+source="http://www.adel.nursat.kz/apg/download/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ sed -i 's:^#\(CS_LIBS = -lnsl\)$:\1:' Makefile
+ make || return 1
+ for i in apg apgbfm; do
+ install -D -m755 $i "$pkgdir"/usr/bin/$i
+ install -D -m644 doc/man/$i.1 "$pkgdir"/usr/man/man1/$i.1
+ done
+ install -D -m 644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="3b3fc4f11e90635519fe627c1137c9ac apg-2.2.3.tar.gz"
diff --git a/main/apk-tools/0001-db-remount-read-only-after-the-file-handles-have-bee.patch b/main/apk-tools/0001-db-remount-read-only-after-the-file-handles-have-bee.patch
new file mode 100644
index 0000000000..45b75a3329
--- /dev/null
+++ b/main/apk-tools/0001-db-remount-read-only-after-the-file-handles-have-bee.patch
@@ -0,0 +1,45 @@
+From 38e54240a38266c0c1864e51e4ca7468a429646e Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Fri, 27 May 2011 11:38:50 +0000
+Subject: [PATCH 1/2] db: remount read-only after the file handles have been
+ closed
+
+The apk cache might be on the readonly media so we need wait with
+remounting til after atleast this filehandle is closed.
+---
+ src/database.c | 12 ++++++------
+ 1 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/database.c b/src/database.c
+index 1d4c573..0fc59df 100644
+--- a/src/database.c
++++ b/src/database.c
+@@ -1397,12 +1397,6 @@ void apk_db_close(struct apk_database *db)
+ struct hlist_node *dc, *dn;
+ int i;
+
+- if (db->cache_remount_dir) {
+- do_remount(db->cache_remount_dir, "ro");
+- free(db->cache_remount_dir);
+- db->cache_remount_dir = NULL;
+- }
+-
+ apk_id_cache_free(&db->id_cache);
+
+ list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
+@@ -1436,6 +1430,12 @@ void apk_db_close(struct apk_database *db)
+ close(db->lock_fd);
+ if (db->root != NULL)
+ free(db->root);
++
++ if (db->cache_remount_dir) {
++ do_remount(db->cache_remount_dir, "ro");
++ free(db->cache_remount_dir);
++ db->cache_remount_dir = NULL;
++ }
+ }
+
+ static int fire_triggers(apk_hash_item item, void *ctx)
+--
+1.7.5.2
+
diff --git a/main/apk-tools/0002-db-more-fix-for-read-only-cache-remounting.patch b/main/apk-tools/0002-db-more-fix-for-read-only-cache-remounting.patch
new file mode 100644
index 0000000000..7fee4d7353
--- /dev/null
+++ b/main/apk-tools/0002-db-more-fix-for-read-only-cache-remounting.patch
@@ -0,0 +1,91 @@
+From 95555ede4d732878d576415e5d338b0104b78ad6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Fri, 27 May 2011 16:49:25 +0300
+Subject: [PATCH 2/2] db: more fix for read-only cache remounting
+
+remount to read-write before trying to create the cache directory
+subdirs. fix a fd leak that might prevent remounting back to rw.
+---
+ src/apk_database.h | 1 -
+ src/database.c | 31 ++++++++++++++-----------------
+ src/url.c | 1 +
+ 3 files changed, 15 insertions(+), 18 deletions(-)
+
+diff --git a/src/apk_database.h b/src/apk_database.h
+index 9b032e7..b28a77b 100644
+--- a/src/apk_database.h
++++ b/src/apk_database.h
+@@ -110,7 +110,6 @@ struct apk_database {
+ apk_blob_t *arch;
+ unsigned int local_repos;
+ int permanent : 1;
+- int ro_cache : 1;
+ int compat_newfeatures : 1;
+ int compat_notinstallable : 1;
+
+diff --git a/src/database.c b/src/database.c
+index 0fc59df..9617b4e 100644
+--- a/src/database.c
++++ b/src/database.c
+@@ -1218,10 +1218,22 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
+
+ db->cache_dir = apk_linked_cache_dir;
+ db->cache_fd = fd;
++ if ((dbopts->open_flags & (APK_OPENF_WRITE | APK_OPENF_CACHE_WRITE)) &&
++ fstatvfs(fd, &stvfs) == 0 && (stvfs.f_flag & ST_RDONLY) != 0) {
++ /* remount cache read-write */
++ db->cache_remount_dir = find_mountpoint(db->root_fd, db->cache_dir);
++ if (db->cache_remount_dir == NULL) {
++ apk_warning("Unable to find cache directory mount point");
++ } else if (do_remount(db->cache_remount_dir, "rw") != 0) {
++ free(db->cache_remount_dir);
++ db->cache_remount_dir = NULL;
++ apk_error("Unable to remount cache read-write");
++ r = EROFS;
++ goto ret_r;
++ }
++ }
+ mkdirat(db->cache_fd, "tmp", 0644);
+ db->cachetmp_fd = openat(db->cache_fd, "tmp", O_RDONLY | O_CLOEXEC);
+- if (fstatvfs(fd, &stvfs) == 0 && (stvfs.f_flag & ST_RDONLY) != 0)
+- db->ro_cache = 1;
+ } else {
+ if (fd >= 0)
+ close(fd);
+@@ -1264,21 +1276,6 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
+ }
+ }
+
+- if ((dbopts->open_flags & (APK_OPENF_WRITE | APK_OPENF_CACHE_WRITE)) &&
+- db->ro_cache) {
+- /* remount cache read-write */
+- db->cache_remount_dir = find_mountpoint(db->root_fd, db->cache_dir);
+- if (db->cache_remount_dir == NULL) {
+- apk_warning("Unable to find cache directory mount point");
+- } else if (do_remount(db->cache_remount_dir, "rw") != 0) {
+- free(db->cache_remount_dir);
+- db->cache_remount_dir = NULL;
+- apk_error("Unable to remount cache read-write");
+- r = EROFS;
+- goto ret_r;
+- }
+- }
+-
+ if (!(dbopts->open_flags & APK_OPENF_NO_SYS_REPOS)) {
+ list_for_each_entry(repo, &dbopts->repository_list, list) {
+ r = apk_db_add_repository(db, APK_BLOB_STR(repo->url));
+diff --git a/src/url.c b/src/url.c
+index 0a17a7a..1fa9d66 100644
+--- a/src/url.c
++++ b/src/url.c
+@@ -136,6 +136,7 @@ int apk_url_download(const char *url, int atfd, const char *file)
+ exit(0);
+ }
+
++ close(fd);
+ waitpid(pid, &status, 0);
+ status = translate_wget(status);
+ if (status != 0) {
+--
+1.7.5.2
+
diff --git a/main/apk-tools/APKBUILD b/main/apk-tools/APKBUILD
new file mode 100644
index 0000000000..33dbef2c16
--- /dev/null
+++ b/main/apk-tools/APKBUILD
@@ -0,0 +1,55 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=apk-tools
+pkgver=2.1.0
+pkgrel=1
+pkgdesc="Alpine Package Keeper - package manager for alpine"
+subpackages="$pkgname-static"
+depends=
+makedepends="zlib-dev openssl-dev pkgconfig"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2
+ 0001-db-remount-read-only-after-the-file-handles-have-bee.patch
+ 0002-db-more-fix-for-read-only-cache-remounting.patch
+ "
+
+url="http://git.alpinelinux.org/cgit/apk-tools/"
+arch="all"
+license=GPL-2
+
+prepare() {
+ cd "$srcdir/$pkgname-$pkgver"
+ sed -i -e 's:-Werror::' Make.rules
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make FULL_VERSION="$pkgver-r$pkgrel" || return 1
+ make FULL_VERSION="$pkgver-r$pkgrel" static || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make FULL_VERSION="$pkgver-r$pkgrel" DESTDIR="$pkgdir" install
+ cd "$pkgdir/sbin"
+ ln -s apk apk_add
+ ln -s apk apk_audit
+ ln -s apk apk_del
+ ln -s apk apk_index
+ ln -s apk apk_info
+ ln -s apk apk_version
+ install -d "$pkgdir"/var/lib/apk "$pkgdir"/var/cache/misc
+}
+
+static() {
+ pkgdesc="Alpine Package Keeper - static binary"
+ install -Dm755 "$srcdir"/$pkgname-$pkgver/src/apk.static \
+ "$subpkgdir"/sbin/apk.static
+}
+
+md5sums="9f6d71c9be814afece7a4b73430bd078 apk-tools-2.1.0.tar.bz2
+6eb78a324be996c831d4850c81ad5821 0001-db-remount-read-only-after-the-file-handles-have-bee.patch
+9ca0a44c17b43e95a7f1bd8107db74da 0002-db-more-fix-for-read-only-cache-remounting.patch"
diff --git a/main/apr-util/APKBUILD b/main/apr-util/APKBUILD
new file mode 100644
index 0000000000..3945b43ceb
--- /dev/null
+++ b/main/apr-util/APKBUILD
@@ -0,0 +1,56 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=apr-util
+pkgver=1.3.12
+pkgrel=1
+pkgdesc="The Apache Portable Runtime Utility Library"
+url="http://apr.apache.org/"
+arch="all"
+license="APACHE"
+depends=
+subpackages="$pkgname-dev $pkgname-dbm_db $pkgname-dbd_pgsql
+ $pkgname-dbd_sqlite3 $pkgname-ldap"
+makedepends="apr-dev expat-dev bash openldap-dev sqlite-dev postgresql-dev
+ db-dev"
+depends_dev="expat-dev apr-dev openldap-dev sqlite-dev postgresql-dev
+ db-dev"
+source="http://www.apache.org/dist/apr/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --with-apr=/usr \
+ --with-ldap \
+ --with-pgsql \
+ --with-sqlite3 \
+ --with-berkeley-db \
+ --without-iconv \
+ --without-sqlite2 \
+ --without-gdbm \
+ || return 1
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/apr-util*/*.la \
+ "$pkgdir"/usr/lib/*.exp \
+ "$pkgdir"/usr/lib/*.la || return 1
+}
+
+_mv_mod() {
+ pkgdesc="The Apache Portable Runtime Utility Library - $2 driver"
+ depends=
+ local _moddir="usr/lib/apr-util-1"
+ mkdir -p "$subpkgdir"/$_moddir
+ mv "$pkgdir"/$_moddir/apr_$1*.so "$subpkgdir"/$_moddir/
+}
+
+dbm_db() { _mv_mod dbm_db "Berkley DB"; }
+dbd_pgsql() { _mv_mod dbd_pgsql "PostgreSQL"; }
+dbd_mysql() { _mv_mod dbd_mysql "MySQL"; }
+dbd_sqlite3() { _mv_mod dbd_sqlite "SQLite3"; }
+ldap() { _mv_mod ldap "LDAP"; }
+
+md5sums="0f671b037ca62751a8a7005578085560 apr-util-1.3.12.tar.bz2"
diff --git a/main/apr/APKBUILD b/main/apr/APKBUILD
new file mode 100644
index 0000000000..b8578da6e3
--- /dev/null
+++ b/main/apr/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=apr
+pkgver=1.4.5
+pkgrel=2
+pkgdesc="The Apache Portable Runtime"
+url="http://apr.apache.org/"
+arch="all"
+license="APACHE"
+depends=
+depends_dev="util-linux-ng-dev bash"
+makedepends="$depends_dev"
+subpackages="$pkgname-dev"
+source="http://www.apache.org/dist/$pkgname/$pkgname-$pkgver.tar.bz2
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --datadir=/usr/share \
+ --enable-nonportable-atomics \
+ --with-devrandom=/dev/urandom
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+# basicly everything thats not a *.so* file belongs to the -dev package
+# we override the pre-defined func.
+dev() {
+ local i
+ depends="$pkgname $depends_dev"
+ mkdir -p "$subpkgdir"
+ mv "$pkgdir"/* "$subpkgdir"/
+ mkdir -p "$pkgdir"/usr/lib
+ mv "$subpkgdir"/usr/lib/*.so* "$pkgdir"/usr/lib/
+ return 0
+}
+
+md5sums="8b53f5a5669d0597f2da889a2f576eb6 apr-1.4.5.tar.bz2"
diff --git a/main/arpon/APKBUILD b/main/arpon/APKBUILD
new file mode 100644
index 0000000000..57e8bfa59e
--- /dev/null
+++ b/main/arpon/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=arpon
+pkgver=2.1
+pkgrel=0
+pkgdesc="Arp handler inspectiON is a handler daemon with tools to handle all ARP aspects"
+url="http://arpon.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="libdnet-dev libpcap-dev libnet-dev cmake"
+install=
+subpackages="$pkgname-doc"
+source="http://arpon.sourceforge.net/tarball/ArpON-$pkgver.tar.gz
+ arpon.initd
+ arpon.confd
+ "
+
+_builddir="$srcdir"/ArpON-$pkgver/build
+
+prepare() {
+ mkdir -p "$_builddir"
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ cmake .. -DCMAKE_C_FLAGS="$CFLAGS"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install DESTDIR="$pkgdir"
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="c5e958af0d7068a12cb1fea656a759bd ArpON-2.1.tar.gz
+4bf2cb423936b1ca84773fe6b7baaa73 arpon.initd
+26986bed19b28cec66ed08447d22efaf arpon.confd"
diff --git a/main/arpon/arpon.confd b/main/arpon/arpon.confd
new file mode 100644
index 0000000000..0b80238a34
--- /dev/null
+++ b/main/arpon/arpon.confd
@@ -0,0 +1 @@
+ARPON_OPTS=
diff --git a/main/arpon/arpon.initd b/main/arpon/arpon.initd
new file mode 100644
index 0000000000..5042501d68
--- /dev/null
+++ b/main/arpon/arpon.initd
@@ -0,0 +1,24 @@
+#!/sbin/runscript
+
+NAME=arpon
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet \
+ --pidfile /var/run/${NAME}.pid \
+ --exec ${DAEMON} -- -d ${ARPON_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --pidfile /var/run/${NAME}.pid
+ eend $?
+}
diff --git a/main/arpwatch/APKBUILD b/main/arpwatch/APKBUILD
new file mode 100644
index 0000000000..c71eb25e06
--- /dev/null
+++ b/main/arpwatch/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=arpwatch
+pkgver=2.1a15
+pkgrel=3
+pkgdesc="Ethernet monitoring program"
+url="http://www-nrg.ee.lbl.gov/"
+arch="all"
+license="GPL"
+depends=
+makedepends="libpcap-dev"
+install=
+subpackages=""
+source="ftp://ftp.ee.lbl.gov/$pkgname.tar.gz
+ arpwatch.confd
+ arpwatch.initd"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make -j1 || return 1
+ #install command wouldn't create directory ?
+ mkdir -p "$pkgdir"/usr/sbin/
+ make -j1 DESTDIR="$pkgdir" install
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+
+}
+
+md5sums="cebfeb99c4a7c2a6cee2564770415fe7 arpwatch.tar.gz
+dc8300ce5f02d6be95899a2982397064 arpwatch.confd
+51ecada198c4f954ac4d5f5903198ebb arpwatch.initd"
diff --git a/main/arpwatch/arpwatch.confd b/main/arpwatch/arpwatch.confd
new file mode 100644
index 0000000000..f44221aa36
--- /dev/null
+++ b/main/arpwatch/arpwatch.confd
@@ -0,0 +1,12 @@
+# Config file for /etc/init.d/arpwatch
+# see arpwatch.8 for more information
+
+#IFACES="eth0 eth1"
+IFACES="eth0"
+
+# Additional options to pass to arpwatch.
+OPTIONS="-N -p"
+
+# Comment this line if you wish arpwatch to run as root user (not recommended)
+ARPUSER="arpwatch"
+
diff --git a/main/arpwatch/arpwatch.initd b/main/arpwatch/arpwatch.initd
new file mode 100644
index 0000000000..b97c25a9c8
--- /dev/null
+++ b/main/arpwatch/arpwatch.initd
@@ -0,0 +1,38 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-analyzer/arpwatch/files/arpwatch.initd,v 1.1 2007/06/02 22:37:16 jokey Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ for IFACE in ${IFACES}
+ do
+ ebegin "Starting arpwatch on ${IFACE}"
+ DATAFILE=/var/lib/arpwatch/${IFACE}.dat
+ [ ! -f ${DATAFILE} ] && touch ${DATAFILE}
+
+ if [ -z ${ARPUSER} ]; then
+ start-stop-daemon --start --quiet --pidfile=/var/run/arpwatch.${IFACE}.pid --exec \
+ /usr/sbin/arpwatch -- -i ${IFACE} -f ${DATAFILE} -P /var/run/arpwatch.${IFACE}.pid ${OPTIONS}
+ else
+ chown ${ARPUSER} ${DATAFILE}
+ start-stop-daemon --start --quiet --pidfile=/var/run/arpwatch.${IFACE}.pid --exec \
+ /usr/sbin/arpwatch -- -i $IFACE -u ${ARPUSER} -f ${DATAFILE} -P /var/run/arpwatch.${IFACE}.pid ${OPTIONS}
+ fi
+ eend $?
+ done
+}
+
+stop() {
+ for IFACE in ${IFACES}
+ do
+ ebegin "Stopping arpwatch on ${IFACE}"
+ start-stop-daemon --stop --quiet --pidfile=/var/run/arpwatch.${IFACE}.pid --exec \
+ /usr/sbin/arpwatch
+ eend $?
+ done
+}
diff --git a/main/asciidoc/APKBUILD b/main/asciidoc/APKBUILD
new file mode 100644
index 0000000000..1fae115b78
--- /dev/null
+++ b/main/asciidoc/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=asciidoc
+pkgver=8.6.5
+pkgrel=0
+pkgdesc="Text based documentation"
+url="http://www.methods.co.nz/asciidoc/"
+arch="noarch"
+license="GPL"
+depends="python libxml2-utils docbook-xsl"
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://sourceforge.net/projects/asciidoc/files/asciidoc/$pkgver/asciidoc-$pkgver.tar.gz
+ vim.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="9247724283501ec1cfb27d5eae9e5eaf asciidoc-8.6.5.tar.gz
+7e98fd7aa3fb61af56814e214bd1ab8a vim.patch"
diff --git a/main/asciidoc/vim.patch b/main/asciidoc/vim.patch
new file mode 100644
index 0000000000..90d098f228
--- /dev/null
+++ b/main/asciidoc/vim.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.in.orig
++++ b/Makefile.in
+@@ -134,7 +134,7 @@
+ done
+
+ install-vim:
+- @for d in $(DESTDIR)/$(vimdir) /etc/vim; do \
++ @for d in $(DESTDIR)/$(vimdir) ; do \
+ if ! test -d $$d; then continue; fi ; \
+ echo "installing Vim files in $$d" ; \
+ $(INSTALL) -d $$d/syntax ; \
diff --git a/main/aspell-en/APKBUILD b/main/aspell-en/APKBUILD
new file mode 100644
index 0000000000..74d4098ebf
--- /dev/null
+++ b/main/aspell-en/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=aspell-en
+pkgver=7.1
+pkgrel=0
+pkgdesc="English dictionary for aspell"
+url="http://aspell.net/"
+arch="noarch"
+license="custom"
+depends="aspell"
+makedepends="aspell-dev"
+source="ftp://ftp.gnu.org/gnu/aspell/dict/en/aspell6-en-$pkgver-0.tar.bz2"
+
+_builddir="$srcdir"/aspell6-en-$pkgver-0
+build () {
+ cd "$_builddir"
+ ./configure || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 Copyright \
+ "$pkgdir"/usr/share/licenses/$pkgname/LICENSE || return 1
+}
+
+md5sums="beba5e8f3afd3ed1644653bb685b2dfb aspell6-en-7.1-0.tar.bz2"
diff --git a/main/aspell/APKBUILD b/main/aspell/APKBUILD
new file mode 100644
index 0000000000..5ef3d24967
--- /dev/null
+++ b/main/aspell/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=aspell
+pkgver=0.60.6
+_pkgmajorver=${pkgver%.*}
+pkgrel=5
+pkgdesc="A spell checker designed to eventually replace Ispell"
+url="http://aspell.net/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="ncurses-dev perl"
+install=
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz
+ libmath.patch"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+
+ # we want add -lm to linker flag for libaspell so wil build that
+ # separately. this is just an ugly workaround
+ make libaspell.la LDFLAGS="$LDFLAGS -lm" || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/aspell*/*.la \
+ "$pkgdir"/usr/lib/*.la || return 1
+ ln -s $pkgname-${_pkgmajorver} "$pkgdir"/usr/lib/$pkgname || return 1
+}
+md5sums="bc80f0198773d5c05086522be67334eb aspell-0.60.6.tar.gz
+715f4e138ab33b27201d90cbc98b4fb3 libmath.patch"
diff --git a/main/aspell/libmath.patch b/main/aspell/libmath.patch
new file mode 100644
index 0000000000..3fad33a5d2
--- /dev/null
+++ b/main/aspell/libmath.patch
@@ -0,0 +1,11 @@
+--- a/Makefile.orig 2009-05-21 08:22:51.000000000 +0000
++++ b/Makefile 2009-05-21 08:23:06.000000000 +0000
+@@ -568,7 +568,7 @@
+ lib/string_list-c.cpp lib/find_speller.cpp lib/speller-c.cpp \
+ lib/string_pair_enumeration-c.cpp lib/new_checker.cpp \
+ modules/filter/url.cpp $(am__append_3)
+-libaspell_la_LIBADD = $(LTLIBINTL) $(PTHREAD_LIB)
++libaspell_la_LIBADD = $(LTLIBINTL) $(PTHREAD_LIB) -lm
+ libaspell_la_LDFLAGS = -version-info 16:4:1 -no-undefined
+ #libaspell_la_LDFLAGS = -version-info 16:4:0 -no-undefined
+ libpspell_la_SOURCES = lib/dummy.cpp
diff --git a/main/asterisk-audio-konf/APKBUILD b/main/asterisk-audio-konf/APKBUILD
new file mode 100644
index 0000000000..9c1030dc28
--- /dev/null
+++ b/main/asterisk-audio-konf/APKBUILD
@@ -0,0 +1,70 @@
+# Contributor:
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=asterisk-audio-konf
+_basever=0
+_gitver=101026
+pkgver=${_basever}_git${_gitver}
+pkgrel=1
+pkgdesc="A fork of AppKonference focused entirely on audio conferencing"
+url="http://github.com/jthomerson/AsteriskAudioKonf/"
+arch="all"
+license="GPL"
+depends=
+makedepends="asterisk-dev"
+install=
+subpackages=
+_snapfile="$pkgname-$pkgver.tar.bz2"
+source="http://dev.alpinelinux.org/~tteras/$_snapfile
+ "
+
+_gitver=101026
+_giturl="git://github.com/jthomerson/AsteriskAudioKonf.git"
+
+
+_builddir="$srcdir"/$pkgname/konference
+
+
+snapshot() {
+ _gitver=$(date +%y%m%d)
+ pkgver=${_basever}_git$_gitver
+ _snapfile="$pkgname-$pkgver.tar.bz2"
+
+ if [ -d "$SRCDEST"/$pkgname ]; then
+ cd "$SRCDEST"/$pkgname
+ git pull --rebase || return 1
+ else
+ cd "$SRCDEST"
+ git clone $_giturl $pkgname
+ fi
+ cd "$SRCDEST"
+ tar -jcf $_snapfile $pkgname
+
+ pkgrel=0
+ sed -i -e "s/^_gitver=.*/_gitver=${_gitver}/" \
+ -e "s/^pkgrel=.*/pkgrel=$pkgrel/" \
+ "$startdir"/APKBUILD
+ checksum
+}
+
+prepare() {
+ cd "$_builddir"
+
+ # Enable Speex16 support
+ sed -e '/CPPFLAGS += -DAC_USE_SPEEX16/s/^\# *//' -i Makefile
+
+ #for i in "$srcdir"/*.patch; do
+ # patch -p1 -i "$i" || return 1
+ #done
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make INSTALL_PREFIX="$pkgdir" install
+}
+
+md5sums="9f560cae3afc363282db60e0d69c6643 asterisk-audio-konf-0_git101026.tar.bz2"
diff --git a/main/asterisk/100-uclibc-daemon.patch b/main/asterisk/100-uclibc-daemon.patch
new file mode 100644
index 0000000000..4956791d4d
--- /dev/null
+++ b/main/asterisk/100-uclibc-daemon.patch
@@ -0,0 +1,44 @@
+diff -Nru asterisk-1.6.1-beta4.org/main/asterisk.c asterisk-1.6.1-beta4/main/asterisk.c
+--- asterisk-1.6.1-beta4.org/main/asterisk.c 2008-12-12 23:05:58.000000000 +0100
++++ asterisk-1.6.1-beta4/main/asterisk.c 2008-12-23 15:28:21.000000000 +0100
+@@ -3295,9 +3295,40 @@
+ #if HAVE_WORKING_FORK
+ if (ast_opt_always_fork || !ast_opt_no_fork) {
+ #ifndef HAVE_SBIN_LAUNCHD
++#ifndef __UCLIBC__
+ if (daemon(1, 0) < 0) {
+ ast_log(LOG_ERROR, "daemon() failed: %s\n", strerror(errno));
+ }
++#else
++ /*
++ * workaround for uClibc-0.9.29 mipsel bug:
++ * recursive mutexes do not work if uClibc daemon() function has been called,
++ * if parent thread locks a mutex
++ * the child thread cannot acquire a lock with the same name
++ * (same code works if daemon() is not called)
++ * but duplication of uClibc daemon.c code in here does work.
++ */
++ int fd;
++ switch (fork()) {
++ case -1:
++ exit(1);
++ case 0:
++ break;
++ default:
++ _exit(0);
++ }
++ if (setsid() == -1)
++ exit(1);
++ if (fork())
++ _exit(0);
++ if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
++ dup2(fd, STDIN_FILENO);
++ dup2(fd, STDOUT_FILENO);
++ dup2(fd, STDERR_FILENO);
++ if (fd > 2)
++ close(fd);
++ }
++#endif
+ ast_mainpid = getpid();
+ /* Blindly re-write pid file since we are forking */
+ unlink(ast_config_AST_PID);
diff --git a/main/asterisk/101-caps-uclibc.patch b/main/asterisk/101-caps-uclibc.patch
new file mode 100644
index 0000000000..bb32d1ece1
--- /dev/null
+++ b/main/asterisk/101-caps-uclibc.patch
@@ -0,0 +1,17 @@
+--- asterisk-1.6.0.18/configure.ac.orig Mon Oct 26 23:13:28 2009
++++ asterisk-1.6.0.18/configure.ac Fri Nov 27 21:42:36 2009
+@@ -627,9 +627,11 @@
+
+ AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h])
+
+-if test "x${OSARCH}" = "xlinux-gnu" ; then
+- AST_EXT_LIB_CHECK([CAP], [cap], [cap_from_text], [sys/capability.h])
+-fi
++case "${OSARCH}" in
++ linux*)
++ AST_EXT_LIB_CHECK([CAP], [cap], [cap_from_text], [sys/capability.h])
++ ;;
++esac
+
+ AST_C_DEFINE_CHECK([DAHDI], [DAHDI_CODE], [dahdi/user.h])
+
diff --git a/main/asterisk/102-gsm-pic.patch b/main/asterisk/102-gsm-pic.patch
new file mode 100644
index 0000000000..71370ec0b7
--- /dev/null
+++ b/main/asterisk/102-gsm-pic.patch
@@ -0,0 +1,54 @@
+--- a/codecs/gsm/Makefile.org 2008-03-29 11:33:09.000000000 +0100
++++ b/codecs/gsm/Makefile 2008-03-29 11:44:40.000000000 +0100
+@@ -37,23 +37,6 @@
+ ######### ppro's, etc, as well as the AMD K6 and K7. The compile will
+ ######### probably require gcc.
+
+-ifeq (, $(findstring $(OSARCH) , Darwin SunOS ))
+-ifeq (, $(findstring $(PROC) , x86_64 amd64 ultrasparc sparc64 arm armv5b armeb ppc powerpc ppc64 ia64 s390 bfin mipsel mips))
+-ifeq (, $(findstring $(shell uname -m) , ppc ppc64 alpha armv4l s390 ))
+-OPTIMIZE+=-march=$(PROC)
+-endif
+-endif
+-endif
+-
+-#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
+-#This works for even old (2.96) versions of gcc and provides a small boost either way.
+-#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it.
+-#So we go lowest common available by gcc and go a step down, still a step up from
+-#the default as we now have a better instruction set to work with. - Belgarath
+-ifeq ($(PROC),ultrasparc)
+-OPTIMIZE+=-mcpu=v8 -mtune=$(PROC) -O3
+-endif
+-
+ PG =
+ #PG = -g -pg
+ ######### Profiling flags. If you don't know what that means, leave it blank.
+@@ -208,12 +191,10 @@
+ # XXX Keep a space after each findstring argument
+ # XXX should merge with GSM_OBJECTS
+ ifeq ($(OSARCH),linux-gnu)
+-ifeq (,$(findstring $(shell uname -m) , x86_64 amd64 ppc ppc64 alpha armv4l sparc64 parisc s390 ))
+-ifeq (,$(findstring $(PROC) , arm armv5b armeb powerpc ia64 s390 bfin mipsel mips ))
++ifneq ($(K6OPT),)
+ GSM_SOURCES+= $(SRC)/k6opt.s
+ endif
+ endif
+-endif
+
+ TOAST_SOURCES = $(SRC)/toast.c \
+ $(SRC)/toast_lin.c \
+@@ -260,12 +241,10 @@
+ $(SRC)/table.o
+
+ ifeq ($(OSARCH),linux-gnu)
+-ifeq (,$(findstring $(shell uname -m) , x86_64 amd64 ppc ppc64 alpha armv4l sparc64 parisc ))
+-ifeq (,$(findstring $(PROC) , arm armv5b armeb powerpc ia64 bfin mipsel mips ))
++ifneq ($(K6OPT),)
+ GSM_OBJECTS+= $(SRC)/k6opt.o
+ endif
+ endif
+-endif
+
+ TOAST_OBJECTS = $(SRC)/toast.o \
+ $(SRC)/toast_lin.o \
diff --git a/main/asterisk/400-bug-227.patch b/main/asterisk/400-bug-227.patch
new file mode 100644
index 0000000000..f8187379e1
--- /dev/null
+++ b/main/asterisk/400-bug-227.patch
@@ -0,0 +1,15 @@
+Index: channels/chan_sip.c
+===================================================================
+--- a/channels/chan_sip.c (revision 212243)
++++ b/channels/chan_sip.c (working copy)
+@@ -3675,8 +3675,8 @@
+ char method_str[31];
+ ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
+ append_history(p, "ReliableXmit", "timeout");
+- if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) {
+- if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
++ if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Init: %30s", method_str) == 1) {
++ if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str) || method_match(SIP_INVITE, method_str)) {
+ pvt_set_needdestroy(p, "autodestruct");
+ }
+ }
diff --git a/main/asterisk/APKBUILD b/main/asterisk/APKBUILD
new file mode 100644
index 0000000000..445b85a029
--- /dev/null
+++ b/main/asterisk/APKBUILD
@@ -0,0 +1,165 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=asterisk
+pkgver=1.8.4.4
+pkgrel=0
+pkgdesc="Asterisk: A Module Open Source PBX System"
+url="http://www.asterisk.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="autoconf automake libtool ncurses-dev popt-dev newt-dev zlib-dev
+ postgresql-dev unixodbc-dev dahdi-tools-dev libpri-dev tar
+ freetds-dev openssl-dev lua-dev alsa-lib-dev spandsp-dev tiff-dev
+ libresample sqlite-dev wget speex-dev"
+install="$pkgname.pre-install $pkgname.pre-upgrade $pkgname.post-install"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-pgsql $pkgname-odbc
+ $pkgname-tds $pkgname-fax $pkgname-sample-config:sample $pkgname-sqlite
+ $pkgname-sounds-moh:sound_moh $pkgname-sounds-en:sound_en"
+source="http://downloads.digium.com/pub/asterisk/releases/$pkgname-$pkgver.tar.gz
+ 100-uclibc-daemon.patch
+ 101-caps-uclibc.patch
+ 400-bug-227.patch
+ asterisk.initd
+ asterisk.confd
+ asterisk.logrotate"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ for i in ../[1-9]*.patch; do
+ msg "Apply $i"
+ patch -p1 < $i || return 1
+ done
+
+ sed -i -e 's:lua5.1/::' pbx/pbx_lua.c
+ sed -i -e 's/PBX_ICONV=1/PBX_ICONV=0/g' configure.ac
+
+ ./bootstrap.sh
+}
+
+build() {
+ cd "$_builddir"
+ SHA1SUM="$PWD"/build_tools/sha1sum-sh ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --libdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-xmldoc --with-gsm=internal \
+ --without-iconv --with-popt --with-z --with-newt \
+ --with-odbc --with-postgres --with-tds \
+ --with-dahdi --with-pri --with-tonezone \
+ --with-resample \
+ --with-sqlite3 \
+ --with-speex \
+ --with-asound \
+ --without-x11 \
+ --with-spandsp \
+ || return 1
+
+ # and figure out which modules to build
+ rm menuselect.makeopts
+ make menuselect.makeopts
+ make ASTLDFLAGS="$LDFLAGS" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+
+ install -d "$pkgdir"/var/run/asterisk
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.logrotate \
+ "$pkgdir"/etc/logrotate.d/$pkgname
+}
+
+_move_dir() {
+ for DIR in "$@"; do
+ local dest=`dirname "$subpkgdir/$DIR"`
+ echo mkdir -p $dest
+ mkdir -p "$dest"
+ echo mv "$pkgdir"/$DIR $dest
+ mv "$pkgdir"/"$DIR" "$dest"
+ done
+}
+
+_find_and_move() {
+ local pattern="$1"
+ cd "$pkgdir" || return 1
+ find -name "$pattern" -type f | while read f; do
+ local dest="$subpkgdir/${f%/*}"
+ mkdir -p "$dest"
+ mv "$f" "$dest"
+ done
+}
+
+doc() {
+ default_doc
+}
+
+dev() {
+ default_dev
+ depends="asterisk"
+}
+
+pgsql() {
+ depends=
+ install=
+ _find_and_move '*_pgsql*'
+}
+
+sqlite() {
+ depends=
+ install=
+ _find_and_move '*_sqlite*'
+}
+
+odbc() {
+ depends=
+ install=
+ _find_and_move '*odbc*'
+}
+
+tds() {
+ depends=
+ install=
+ _find_and_move '*_tds*'
+}
+
+fax() {
+ depends=
+ install=
+ _find_and_move '*_fax*'
+}
+
+sample() {
+ pkgdesc="Sample configuration files for asterisk"
+ cd "$_builddir"
+ mkdir -p "$subpkgdir"/var/lib/asterisk/phoneprov
+ make -j1 samples DESTDIR="$subpkgdir"
+}
+
+sound_moh() {
+ pkgdesc="Default on-hold music files for asterisk"
+ depends=
+ install=
+ _move_dir var/lib/asterisk/moh
+}
+
+sound_en() {
+ pkgdesc="English sound files for asterisk"
+ depends=
+ install=
+ _move_dir var/lib/asterisk/sounds/en
+}
+
+md5sums="bc2a1168603815c23f204927d1e73239 asterisk-1.8.4.4.tar.gz
+b00c9d98ce2ad445501248a197c6e436 100-uclibc-daemon.patch
+6e1129e30c4fd2c25c86c81685a485a9 101-caps-uclibc.patch
+79e9634b5054bceb3b8dc246654bb243 400-bug-227.patch
+0ce3219e05f55af884a7dc6b99c2b276 asterisk.initd
+ed31d7ba37bcf8b0346dcf8593c395f0 asterisk.confd
+3e65172275684373e1a25c8a11224411 asterisk.logrotate"
diff --git a/main/asterisk/asterisk.confd b/main/asterisk/asterisk.confd
new file mode 100644
index 0000000000..fe9f138ab7
--- /dev/null
+++ b/main/asterisk/asterisk.confd
@@ -0,0 +1,91 @@
+#
+# Additional options for asterisk
+#
+# see "asterisk -h" for a list of options
+#
+ASTERISK_OPTS=""
+
+#
+# User and group to run asterisk as
+#
+# Value: double-colon separated list of user and group, or empty to run as root:
+#
+#
+# "asterisk:asterisk" to run as user "asterisk" and group "asterisk"
+# "asterisk" to run as user "asterisk" and all groups that user "asterisk" is a member of
+# ":asterisk" to run as user "root" and group "asterisk"
+# "" to run as user "root" and group "root"
+#
+ASTERISK_USER="asterisk"
+
+#
+# Nicelevel
+#
+# Set the priority of the asterisk process
+#
+# Value: (highest) -20..19 (lowest)
+#
+#ASTERISK_NICE="19"
+
+#
+# Wrapper script
+#
+# Value: yes or no/empty
+#
+ASTERISK_WRAPPER="no"
+
+############# Wrapper script settings #############
+
+#
+# Send crash notifications emails to this address
+# (needs a working mail service and /usr/sbin/sendmail to do so (e.g. ssmtp))
+#
+# Value: Email address or empty to disable
+#
+#ASTERISK_NOTIFY_EMAIL="root"
+
+#
+# Send asterisk's output to this terminal
+#
+# Value: Full path to device node or a number
+#
+#ASTERISK_TTY="/dev/tty9"
+
+#
+# Start an asterisk console on the terminal specified by ASTERISK_TTY
+#
+# Warning! Use only for debugging, this is a potential security issue!
+#
+# Value: yes or no/empty
+#
+ASTERISK_CONSOLE="no"
+
+#
+# Maximum size of core files.
+#
+# Value: Size in bytes, unlimited for no limit or empty to disable.
+#
+#ASTERISK_CORE_SIZE="unlimited"
+
+#
+# ASTERISK_CORE_DIR
+#
+# Value: Directory (will be created if non-existant), default is /tmp
+#
+ASTERISK_CORE_DIR="/var/lib/asterisk/coredump"
+
+#
+# Max number of filedescriptors
+#
+# Value: Number of descriptors
+#
+#ASTERISK_MAX_FD="1024"
+
+#
+# Kill these tasks after asterisk crashed (ASTERISK_WRAPPER=yes only!)
+#
+# Warning! This will kill _ALL_ tasks with the specified names!
+#
+# Value: Space separated list of names in double quotes (e.g. "mpg123 mad")
+#
+#ASTERISK_CLEANUP_ON_CRASH="mpg123 asterisk-mpg123 mad"
diff --git a/main/asterisk/asterisk.initd b/main/asterisk/asterisk.initd
new file mode 100644
index 0000000000..284898ae22
--- /dev/null
+++ b/main/asterisk/asterisk.initd
@@ -0,0 +1,251 @@
+#!/sbin/runscript
+
+opts="${opts} forcestop reload"
+
+depend() {
+ need net
+ after firewall
+ use nscd dns zaptel mysql postgresql slapd capi
+}
+
+is_running() {
+ if [ -z "$(pidof asterisk)" ]; then
+ return 1
+ else
+ PID="$(cat /var/run/asterisk/asterisk.pid 2>/dev/null)"
+ for x in $(pidof asterisk); do
+ if [ "${x}" = "${PID}" ]; then
+ return 0
+ fi
+ done
+ fi
+
+ return 1
+}
+
+asterisk_run_loop() {
+ local OPTS ARGS MSG NICE=""
+ local result=0 signal=0
+
+ # default options
+ OPTS="-f" # don't fork / detach breaks wrapper script...
+
+ # filter (redundant) arguments
+ ARGS="$(echo "${@}" | sed -e "s:-c\|-f::g")"
+
+ # mangle yes/no options
+ ASTERISK_CONSOLE="$(echo ${ASTERISK_CONSOLE} | tr '[:lower:]' '[:upper:]')"
+
+ if [ -n "${ASTERISK_CORE_SIZE}" ] &&
+ [ "${ASTERISK_CORE_SIZE}" != "0" ]; then
+ ulimit -c ${ASTERISK_CORE_SIZE}
+
+ if [ -n "${ASTERISK_CORE_DIR}" ] && \
+ [ ! -d "${ASTERISK_CORE_DIR}" ]
+ then
+ mkdir -m750 -p "${ASTERISK_CORE_DIR}"
+
+ if [ -n "${ASTERISK_USER}" ]; then
+ chown -R "${ASTERISK_USER}" "${ASTERISK_CORE_DIR}"
+ fi
+ fi
+ ASTERISK_CORE_DIR="${ASTERISK_CORE_DIR:-/tmp}"
+
+ cd "${ASTERISK_CORE_DIR}"
+ echo " Core dump size : ${ASTERISK_CORE_SIZE}"
+ echo " Core dump location : ${ASTERISK_CORE_DIR}"
+ fi
+
+ if [ -n "${ASTERISK_MAX_FD}" ]; then
+ ulimit -n ${ASTERISK_MAX_FD}
+ echo " Max open filedescriptors : ${ASTERISK_MAX_FD}"
+ fi
+
+ if [ -n "${ASTERISK_NICE}" ]; then
+ echo " Nice level : ${ASTERISK_NICE}"
+ NICE="nice -n ${ASTERISK_NICE} --"
+ fi
+
+ if [ -n "${ASTERISK_NOTIFY_EMAIL}" ]; then
+ if [ -x /usr/sbin/sendmail ]; then
+ echo " Email notifications go to : ${ASTERISK_NOTIFY_EMAIL}"
+ else
+ echo " Notifications disabled, /usr/sbin/sendmail doesn't exist or is not executable!"
+ unset ASTERISK_NOTIFY_EMAIL
+ fi
+ fi
+
+ if [ -n "${ASTERISK_TTY}" ]; then
+ for x in ${ASTERISK_TTY} \
+ /dev/tty${ASTERISK_TTY} \
+ /dev/vc/${ASTERISK_TTY}
+ do
+ if [ -c "${x}" ]; then
+ TTY="${x}"
+ fi
+ done
+ [ -n "${TTY}" ] && \
+ echo " Messages are sent to : ${TTY}"
+ fi
+
+ if [ "${ASTERISK_CONSOLE}" = "YES" ] && [ -n "${TTY}" ]; then
+ echo " Starting Asterisk console : ${ASTERISK_CONSOLE}"
+ OPTS="${OPTS} -c"
+ fi
+
+ OPTS="${OPTS} ${ARGS}"
+
+ while :; do
+
+ if [ -n "${TTY}" ]; then
+ /usr/bin/stty -F ${TTY} sane
+ ${NICE} /usr/sbin/asterisk ${OPTS} >${TTY} 2>&1 <${TTY}
+ result=$?
+ else
+ ${NICE} /usr/sbin/asterisk ${OPTS} &>/dev/null
+ result=$?
+ fi
+
+ if [ $result -eq 0 ]; then
+ echo "Asterisk terminated normally"
+ break
+ else
+ if [ $result -gt 128 ]; then
+ signal=$((result - 128))
+ MSG="Asterisk terminated with Signal: $signal"
+
+ CORE_TARGET="core-$(date "+%Y%m%d-%h%M%s")"
+
+ local CORE_DUMPED=0
+ if [ -f "${ASTERISK_CORE_DIR}/core" ]; then
+ mv "${ASTERISK_CORE_DIR}/core" \
+ "${ASTERISK_CORE_DIR}/${CORE_TARGET}"
+ CORE_DUMPED=1
+
+ elif [ -f "${ASTERISK_CORE_DIR}/core.${PID}" ]; then
+ mv "${ASTERISK_CORE_DIR}/core.${PID}" \
+ "${ASTERISK_CORE_DIR}/${CORE_TARGET}"
+ CORE_DUMPED=1
+
+ fi
+
+ [ $CORE_DUMPED -eq 1 ] && \
+ MSG="${MSG}\n\rCore dumped: ${ASTERISK_CORE_DIR}/${CORE_TARGET}"
+ else
+ MSG="Asterisk terminated with return code: $result"
+ fi
+
+ # kill left-over tasks
+ for X in ${ASTERISK_CLEANUP_ON_CRASH}; do
+ kill -9 $(pidof ${X});
+ done
+ fi
+
+ [ -n "${TTY}" ] \
+ && echo "${MSG}" >${TTY} \
+ || echo "${MSG}"
+
+
+ if [ -n "${ASTERISK_NOTIFY_EMAIL}" ] && \
+ [ -x /usr/sbin/sendmail ]; then
+ echo -e -n "Subject: Asterisk crashed\n\r${MSG}\n\r" |\
+ /usr/sbin/sendmail "${ASTERISK_NOTIFY_EMAIL}"
+ fi
+ sleep 5
+ echo "Restarting Asterisk..."
+ done
+ return 0
+}
+
+start() {
+ local OPTS USER GROUP PID
+ local tmp x
+
+ if [ -n "${ASTERISK_NICE}" ]; then
+ if [ ${ASTERISK_NICE} -ge -20 ] && \
+ [ ${ASTERISK_NICE} -le 19 ]; then
+ OPTS="--nicelevel ${ASTERISK_NICE}"
+ else
+ eerror "Nice value must be between -20 and 19"
+ return 1
+ fi
+ fi
+
+ if [ -n "${ASTERISK_USER}" ]; then
+ USER=$(echo $ASTERISK_USER | sed 's/:.*//')
+ GROUP=$(echo $ASTERISK_USER | awk -F: '/.*:.*/ { print $2 }')
+ if [ -n "${USER}" ]; then
+ ASTERISK_OPTS="${ASTERISK_OPTS} -U ${USER}"
+ fi
+ if [ -n "${GROUP}" ]; then
+ ASTERISK_OPTS="${ASTERISK_OPTS} -G ${GROUP}"
+ GROUP=":${GROUP}" # make it look nice...
+ fi
+ ebegin "Starting asterisk PBX (as ${USER}${GROUP})"
+ else
+ ebegin "Starting asterisk PBX (as root)"
+ fi
+
+ if [ "$(echo ${ASTERISK_WRAPPER} | tr '[:upper:]' '[:lower:]')" != "yes" ]; then
+ start-stop-daemon --start --exec /usr/sbin/asterisk \
+ ${OPTS} -- ${ASTERISK_OPTS}
+ result=$?
+ else
+ asterisk_run_loop ${ASTERISK_OPTS} 2>/dev/null &
+ result=$?
+ fi
+
+ if [ $result -eq 0 ]; then
+ # 2 seconds should be enough for asterisk to start
+ sleep 2
+ is_running
+ result=$?
+ fi
+
+ eend $result
+}
+
+forcestop() {
+ ebegin "Stopping asterisk PBX"
+ start-stop-daemon --stop --pidfile /var/run/asterisk/asterisk.pid
+ eend $?
+}
+
+stop() {
+ if ! is_running; then
+ eerror "Asterisk is not running!"
+ return 0
+ fi
+
+ ebegin "Stopping asterisk PBX now"
+ /usr/sbin/asterisk -r -x "core stop now" &>/dev/null
+ # Now we have to wait until asterisk has _really_ stopped.
+ sleep 1
+ if is_running; then
+ einfon "Waiting for asterisk to shutdown ."
+ local cnt=0
+ while is_running; do
+ cnt=`expr $cnt + 1`
+ if [ $cnt -gt 60 ] ; then
+ # Waited 120 seconds now. Fail.
+ echo
+ eend 1 "Failed."
+ return
+ fi
+ sleep 2
+ echo -n "."
+ done
+ echo
+ fi
+ eend 0
+}
+
+reload() {
+ if is_running; then
+ ebegin "Forcing asterisk to reload configuration"
+ /usr/sbin/asterisk -r -x "modules reload" &>/dev/null
+ eend $?
+ else
+ eerror "Asterisk is not running!"
+ fi
+}
diff --git a/main/asterisk/asterisk.logrotate b/main/asterisk/asterisk.logrotate
new file mode 100644
index 0000000000..30836c5c11
--- /dev/null
+++ b/main/asterisk/asterisk.logrotate
@@ -0,0 +1,17 @@
+/var/log/asterisk/messages /var/log/asterisk/*log {
+ missingok
+ rotate 5
+ weekly
+ create 0640 asterisk asterisk
+ postrotate
+ /usr/sbin/asterisk -rx 'logger reload' > /dev/null 2> /dev/null
+ endscript
+}
+
+/var/log/asterisk/cdr-csv/*csv {
+ missingok
+ rotate 5
+ monthly
+ create 0640 asterisk asterisk
+}
+
diff --git a/main/asterisk/asterisk.post-install b/main/asterisk/asterisk.post-install
new file mode 100644
index 0000000000..fd51c7fa5d
--- /dev/null
+++ b/main/asterisk/asterisk.post-install
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+chown -R asterisk:asterisk /var/*/asterisk
+chown -R asterisk:asterisk /etc/asterisk
+chmod -R u=rwX,g=rX,o= /etc/asterisk
+
+# set IP ToS
+# iptables -A OUTPUT -t mangle -p udp -m udp --dport 5060 -j DSCP --set-dscp 0x28
+#iptables -A OUTPUT -t mangle -p udp -m udp --sport 10000:20000 -j DSCP --set-dscp 0x28
+# more info: http://www.voip-info.org/wiki-Asterisk+non-root
+
diff --git a/main/asterisk/asterisk.pre-install b/main/asterisk/asterisk.pre-install
new file mode 100644
index 0000000000..09985d7cdb
--- /dev/null
+++ b/main/asterisk/asterisk.pre-install
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+user=asterisk
+home=/var/lib/asterisk
+adduser -h $home -s /bin/false -D $user 2>/dev/null
+mkdir -p $home
+chown $user:$user $home
+
+addgroup dialout 2>/dev/null
+addgroup $user dialout 2>/dev/null
+exit 0
+
diff --git a/main/asterisk/asterisk.pre-upgrade b/main/asterisk/asterisk.pre-upgrade
new file mode 120000
index 0000000000..1765e9ca55
--- /dev/null
+++ b/main/asterisk/asterisk.pre-upgrade
@@ -0,0 +1 @@
+asterisk.pre-install \ No newline at end of file
diff --git a/main/aterm/APKBUILD b/main/aterm/APKBUILD
new file mode 100644
index 0000000000..e6b10ac440
--- /dev/null
+++ b/main/aterm/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=aterm
+pkgver=1.0.1
+pkgrel=2
+pkgdesc="An xterm replacement with transparency support"
+url="http://aterm.sourceforge.net/"
+arch="all"
+license="GPL"
+makedepends="libxext-dev libsm-dev libxt-dev"
+subpackages="$pkgname-doc"
+depends=
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2
+ uclibc.patch"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 < ../uclibc.patch || return 1
+ ./configure --prefix=/usr \
+ --enable-transparency=yes \
+ --enable-background-image \
+ --enable-fading \
+ --enable-menubar \
+ --enable-graphics
+ make || return 1
+ make prefix="$pkgdir"/usr install
+}
+md5sums="c2eede028e1011e0ec7035cf319c9b5a aterm-1.0.1.tar.bz2
+cd942d2639bd32fb9cbf06c94dcd536f uclibc.patch"
diff --git a/main/aterm/uclibc.patch b/main/aterm/uclibc.patch
new file mode 100644
index 0000000000..1c14283457
--- /dev/null
+++ b/main/aterm/uclibc.patch
@@ -0,0 +1,16 @@
+--- aterm-1.0.1/src/command.c.orig 2009-06-12 18:04:43.000000000 +0000
++++ aterm-1.0.1/src/command.c 2009-06-12 18:10:23.000000000 +0000
+@@ -91,7 +91,12 @@
+
+ #if defined (__svr4__) || defined (__lnx21__)
+ # include <sys/resource.h> /* for struct rlimit */
+-# include <sys/stropts.h> /* for I_PUSH */
++# if defined (__UCLIBC__)
++# define __SID ('S' << 8)
++# define I_PUSH (__SID | 2)
++# else
++# include <sys/stropts.h> /* for I_PUSH */
++# endif
+ # define _NEW_TTY_CTRL /* to get proper defines in <termios.h> */
+ #endif
+
diff --git a/main/atk/APKBUILD b/main/atk/APKBUILD
new file mode 100644
index 0000000000..c57f969497
--- /dev/null
+++ b/main/atk/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=atk
+pkgver=2.0.1
+pkgrel=1
+pkgdesc="A library providing a set of interfaces for accessibility"
+url="http://www.gtk.org/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="glib-dev gobject-introspection-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-introspection \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="87f20b78deaedef858ac54358c0786b1 atk-2.0.1.tar.bz2"
diff --git a/main/atkmm/APKBUILD b/main/atkmm/APKBUILD
new file mode 100644
index 0000000000..32c916a5f4
--- /dev/null
+++ b/main/atkmm/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=atkmm
+pkgver=2.22.4
+pkgrel=1
+pkgdesc="C++ bindings for atk"
+url="http://gtkmm.sourceforge.net/"
+arch="all"
+license="LGPL"
+depends=""
+makedepends="atk-dev glibmm-dev libsigc++-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/atkmm/${pkgver%.*}/atkmm-$pkgver.tar.bz2"
+replaces="gtkmm"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="ad1ddcc707bf18a27968838a327195d7 atkmm-2.22.4.tar.bz2"
diff --git a/main/atop/APKBUILD b/main/atop/APKBUILD
new file mode 100644
index 0000000000..949539c82f
--- /dev/null
+++ b/main/atop/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=atop
+pkgver=1.26
+pkgrel=0
+pkgdesc="Resource-specific view of processes"
+url="http://www.atcomputing.nl/Tools/atop"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="zlib-dev ncurses-dev"
+subpackages="$pkgname-doc"
+source="http://www.atoptool.nl/download/atop-$pkgver.tar.gz
+ atop-bb-compat.patch
+ atop.initd"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -p1 -i "$srcdir"/atop-bb-compat.patch || return 1
+ sed -i -e '/^CFLAGS/s: = -O : += :' \
+ -e '/^LDFLAGS/s: = : += :' Makefile
+ cp "$srcdir"/atop.initd atop.init
+ chmod a+rx atop.init
+}
+
+build() {
+ cd "$_builddir"
+ make
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/var/log/atop "$pkgdir"/var/run
+ make DESTDIR="$pkgdir" \
+ INIPATH=/etc/init.d \
+ SCRPATH=/etc/periodic/daily \
+ install
+ rm -f "$pkgdir"/etc/cron.d
+ mv "$pkgdir"/etc/periodic/daily/atop.daily \
+ "$pkgdir"/etc/periodic/daily/atop
+
+}
+
+md5sums="9a72baf4c8f330973f1e2703f5a6c041 atop-1.26.tar.gz
+3b4c7d162eafcd3db6e2647269065823 atop-bb-compat.patch
+06aba14ddeadbb1d0c3594536785213b atop.initd"
diff --git a/main/atop/atop-bb-compat.patch b/main/atop/atop-bb-compat.patch
new file mode 100644
index 0000000000..66e45234ae
--- /dev/null
+++ b/main/atop/atop-bb-compat.patch
@@ -0,0 +1,35 @@
+diff --git a/atop.daily b/atop.daily
+index c72214c..ac4b3b7 100755
+--- a/atop.daily
++++ b/atop.daily
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ CURDAY=`date +%Y%m%d`
+ LOGPATH=/var/log/atop
+ BINPATH=/usr/bin
+@@ -7,15 +7,20 @@ INTERVAL=600 # interval 10 minutes
+
+ # verify if atop still runs for daily logging
+ #
+-if [ -e $PIDFILE ] && ps -p `cat $PIDFILE` | grep 'atop$' > /dev/null
++pid=
++if [ -e $PIDFILE ]; then
++ pid=$(cat $PIDFILE)
++fi
++
++if [ -n "$pid" ] && [ -d /proc/$pid ]
+ then
+- kill -USR2 `cat $PIDFILE` # final sample and terminate
++ kill -USR2 $pid # final sample and terminate
+
+ CNT=0
+
+- while ps -p `cat $PIDFILE` > /dev/null
++ while [ -d /proc/$pid ]
+ do
+- let CNT+=1
++ CNT=$(($CNT + 1))
+
+ if [ $CNT -gt 5 ]
+ then
diff --git a/main/atop/atop.initd b/main/atop/atop.initd
new file mode 100644
index 0000000000..6d471c2721
--- /dev/null
+++ b/main/atop/atop.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-process/atop/files/atop.rc,v 1.1 2005/06/14 23:01:10 vapier Exp $
+
+_daily=/etc/periodic/daily/atop
+start(){
+ ebegin "Starting atop"
+ if [ -f "$_daily" ] ; then
+ start-stop-daemon --start --quiet --exec "$_daily"
+ eend $?
+ else
+ eend 1 "/etc/cron.d/atop doesnt exist!"
+ fi
+}
+
+stop(){
+ ebegin "Stopping atop"
+ start-stop-daemon --stop --pidfile /var/run/atop.pid
+ eend $?
+}
diff --git a/main/attr/APKBUILD b/main/attr/APKBUILD
new file mode 100644
index 0000000000..57ecd12870
--- /dev/null
+++ b/main/attr/APKBUILD
@@ -0,0 +1,69 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=attr
+pkgver=2.4.46
+pkgrel=2
+pkgdesc="Utilities for managing filesystem extended attributes"
+url="http://acl.bestbits.at/"
+arch="all"
+license="LGPL"
+depends=
+makedepends="libtool autoconf automake bash gzip"
+subpackages="$pkgname-dev $pkgname-doc libattr"
+source="http://download.savannah.gnu.org/releases-noredirect/attr/attr-$pkgver.src.tar.gz
+ attr-2.4.32-build.patch
+ "
+
+prepare() {
+ cd "$srcdir"/attr-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ sed -i -e '/HAVE_ZIPPED_MANPAGES/s:=.*:=false:' \
+ include/builddefs.in
+}
+
+build() {
+ cd "$srcdir"/attr-$pkgver
+
+ unset PLATFORM #184564
+ export OPTIMIZER="${CFLAGS}"
+ export DEBUG=-DNDEBUG
+
+ ./configure \
+ --prefix=/ \
+ --exec-prefix=/ \
+ --sbindir=/bin \
+ --bindir=/usr/bin \
+ --libdir=/lib \
+ --libexecdir=/usr/lib \
+ --enable-lib64=yes \
+ --includedir=/usr/include \
+ --mandir=/usr/share/man \
+ --datadir=/usr/share \
+ --disable-gettext || return 1
+ make LIBTOOL="libtool --tag=CC" || return 1
+}
+
+package() {
+ cd "$srcdir"/attr-$pkgver
+ make -j1 LIBTOOL=$PWD/libtool DESTDIR="$pkgdir" \
+ install install-lib install-dev || return 1
+ # provided by man-pages
+ rm -r "$pkgdir"/usr/share/man/man2 \
+ "$pkgdir"/usr/lib/*.a \
+ "$pkgdir"/lib/*.la \
+ "$pkgdir"/usr/lib/*.la || return 1
+}
+
+libattr() {
+ pkgdesc="Dynamic library for extended attribute support"
+ replaces="attr"
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/lib*.so.* "$subpkgdir"/lib/
+}
+
+md5sums="db557c17fdfa4f785333ecda08654010 attr-2.4.46.src.tar.gz
+6d6bd02aca84ec61516d6700a87bbff7 attr-2.4.32-build.patch"
diff --git a/main/attr/attr-2.4.32-build.patch b/main/attr/attr-2.4.32-build.patch
new file mode 100644
index 0000000000..a7c3af20b7
--- /dev/null
+++ b/main/attr/attr-2.4.32-build.patch
@@ -0,0 +1,40 @@
+diff --git a/include/builddefs.in b/include/builddefs.in
+index 6df0f5a..575a6df 100644
+--- a/include/builddefs.in
++++ b/include/builddefs.in
+@@ -40,14 +40,14 @@ PKG_RELEASE = @pkg_release@
+ PKG_VERSION = @pkg_version@
+ PKG_PLATFORM = @pkg_platform@
+ PKG_DISTRIBUTION= @pkg_distribution@
+-PKG_BIN_DIR = @bindir@
+-PKG_SBIN_DIR = @sbindir@
+-PKG_LIB_DIR = @libdir@@libdirsuffix@
+-PKG_DEVLIB_DIR = @libexecdir@@libdirsuffix@
+-PKG_INC_DIR = @includedir@/attr
+-PKG_MAN_DIR = @mandir@
+-PKG_DOC_DIR = @datadir@/doc/@pkg_name@
+-PKG_LOCALE_DIR = @datadir@/locale
++PKG_BIN_DIR = $(DESTDIR)@bindir@
++PKG_SBIN_DIR = $(DESTDIR)@sbindir@
++PKG_LIB_DIR = $(DESTDIR)@libdir@@libdirsuffix@
++PKG_DEVLIB_DIR = $(DESTDIR)@libexecdir@@libdirsuffix@
++PKG_INC_DIR = $(DESTDIR)@includedir@/attr
++PKG_MAN_DIR = $(DESTDIR)@mandir@
++PKG_DOC_DIR = $(DESTDIR)@datadir@/doc/@pkg_name@-@pkg_version@
++PKG_LOCALE_DIR = $(DESTDIR)@datadir@/locale
+
+ CC = @cc@
+ AWK = @awk@
+diff --git a/include/buildmacros b/include/buildmacros
+index ab89182..3118a17 100644
+--- a/include/buildmacros
++++ b/include/buildmacros
+@@ -40,7 +40,7 @@ OBJECTS = $(ASFILES:.s=.o) \
+ $(LFILES:.l=.o) \
+ $(YFILES:%.y=%.tab.o)
+
+-INSTALL = $(TOPDIR)/include/install-sh -o $(PKG_USER) -g $(PKG_GROUP)
++INSTALL = $(TOPDIR)/include/install-sh
+
+ SHELL = /bin/sh
+ IMAGES_DIR = $(TOPDIR)/all-images
diff --git a/main/audacious-plugins/APKBUILD b/main/audacious-plugins/APKBUILD
new file mode 100644
index 0000000000..802ad58cc6
--- /dev/null
+++ b/main/audacious-plugins/APKBUILD
@@ -0,0 +1,87 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=audacious-plugins
+pkgver=2.5.3
+pkgrel=0
+pkgdesc="playlist-oriented media player with multiple interfaces (plugins)"
+url="http://audacious-media-player.org/"
+arch="all"
+license="ISC"
+depends=audacious
+install_if=audacious
+_want_ffmpeg="ffmpeg-dev"
+makedepends="libmowgli-dev
+ libmcs-dev
+ libguess-dev
+ gtk+-dev
+ dbus-glib-dev
+ audacious-dev
+ libxml2-dev
+
+ libcdio-dev
+ libcddb-dev
+
+ libxcomposite-dev
+ libsamplerate-dev
+ libcue-dev
+ libmms-dev
+ libsndfile-dev
+
+ libnotify-dev
+
+ libogg-dev
+ libvorbis-dev
+
+ $_want_ffmpeg
+
+ alsa-lib-dev
+ faad2-dev
+ neon-dev
+ curl-dev
+ wavpack-dev
+ lame-dev
+ flac-dev
+
+ autoconf"
+install=
+subpackages=
+source="http://distfiles.atheme.org/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i..."
+ patch -s -p1 -N -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+
+ msg "Rebuilding configure..."
+ autoconf
+
+ # workaround bug in busybox
+ sed -e "/touch/s/0001010000/200001010000/g" \
+ -i configure
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-chardet
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="a4da732ca92b5c694883758bea925b6b audacious-plugins-2.5.3.tar.gz"
diff --git a/main/audacious-plugins/audacious-plugins-2.5.1-vorbis.patch b/main/audacious-plugins/audacious-plugins-2.5.1-vorbis.patch
new file mode 100644
index 0000000000..0e35adff3d
--- /dev/null
+++ b/main/audacious-plugins/audacious-plugins-2.5.1-vorbis.patch
@@ -0,0 +1,54 @@
+From 6ed2a39924b29f185e5a87bd8dccffaa0f1011ca Mon Sep 17 00:00:00 2001
+From: John Lindgren <john.lindgren@tds.net>
+Date: Wed, 08 Jun 2011 18:49:57 +0000
+Subject: vorbis: Patch from Michael Schwendt to fix crash on 32-bit systems. Closes: AUDPLUG-369.
+
+---
+diff --git a/src/vorbis/vcedit.c b/src/vorbis/vcedit.c
+index 9dd6c01..dc14d2f 100644
+--- a/src/vorbis/vcedit.c
++++ b/src/vorbis/vcedit.c
+@@ -145,7 +145,7 @@ _fetch_next_packet(vcedit_state * s, ogg_packet * p, ogg_page * page)
+ {
+ int result;
+ char *buffer;
+- int bytes;
++ gint64 bytes;
+
+ result = ogg_stream_packetout(s->os, p);
+
+@@ -189,7 +189,7 @@ vcedit_open_callbacks(vcedit_state * state, void *in,
+ vcedit_write_func write_func)
+ {
+ char *buffer;
+- int bytes, i;
++ gint64 bytes, i;
+ ogg_packet *header;
+ ogg_packet header_main;
+ ogg_packet header_comments;
+@@ -317,7 +317,7 @@ vcedit_write(vcedit_state * state, void *out)
+ ogg_int64_t granpos = 0;
+ int result;
+ char *buffer;
+- int bytes;
++ gint64 bytes;
+ int needflush = 0, needout = 0;
+
+ state->eosin = 0;
+diff --git a/src/vorbis/vcedit.h b/src/vorbis/vcedit.h
+index 983a2ee..ea4432f 100644
+--- a/src/vorbis/vcedit.h
++++ b/src/vorbis/vcedit.h
+@@ -19,8 +19,8 @@ extern "C" {
+ #include <vorbis/codec.h>
+ #include <audacious/plugin.h>
+
+-typedef size_t (*vcedit_read_func)(void *, size_t, size_t, void *);
+-typedef size_t (*vcedit_write_func)(const void *, size_t, size_t, void *);
++typedef gint64 (*vcedit_read_func)(void *, gint64, gint64, void *);
++typedef gint64 (*vcedit_write_func)(const void *, gint64, gint64, void *);
+
+ typedef struct {
+ ogg_sync_state *oy;
+--
+cgit v0.8.3.4
diff --git a/main/audacious/APKBUILD b/main/audacious/APKBUILD
new file mode 100644
index 0000000000..921bc97c92
--- /dev/null
+++ b/main/audacious/APKBUILD
@@ -0,0 +1,24 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=audacious
+pkgver=2.5.3
+pkgrel=0
+pkgdesc="playlist-oriented media player with multiple interfaces"
+url="http://audacious-media-player.org/"
+arch="all"
+license="ISC"
+depends=
+makedepends="libmowgli-dev libmcs-dev libguess-dev gtk+-dev dbus-glib-dev libxml2-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://distfiles.atheme.org/$pkgname-$pkgver.tar.gz"
+
+source /usr/share/abuildhelper/rules/base.sh
+
+using autotools
+using makeinstall
+using plugin atheme-buildsys
+
+ac_enable_opt chardet
+
+md5sums="d61b800e2192007e71088afff9927c84 audacious-2.5.3.tar.gz"
diff --git a/main/augeas/APKBUILD b/main/augeas/APKBUILD
new file mode 100644
index 0000000000..d535889caf
--- /dev/null
+++ b/main/augeas/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=augeas
+pkgver=0.8.0
+pkgrel=1
+pkgdesc="a configuration editing tool"
+url="http://augeas.net"
+arch="all"
+license="LGPL"
+depends=
+makedepends="readline-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc $pkgname-tests"
+source="http://augeas.net/download/augeas-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+tests() {
+ pkgdesc="Tests for Augeas lenses"
+ mkdir -p "$subpkgdir"/usr/share/augeas/lenses/dist/
+ mv "$pkgdir"/usr/share/augeas/lenses/dist/tests \
+ "$subpkgdir"/usr/share/augeas/lenses/dist/
+}
+md5sums="e425bcfc46fd5b18473a4ff47c2878d3 augeas-0.8.0.tar.gz"
diff --git a/main/aumix/APKBUILD b/main/aumix/APKBUILD
new file mode 100644
index 0000000000..b7e93b4232
--- /dev/null
+++ b/main/aumix/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=aumix
+pkgver=2.9.1
+pkgrel=0
+pkgdesc="A color text mode sound mixer"
+url="http://www.jpj.net/~trevor/aumix.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+source="http://jpj.net/~trevor/aumix/releases/aumix-$pkgver.tar.bz2
+ aumix.initd
+ "
+
+prepare() {
+ cd "$srcdir"/aumix-$pkgver
+}
+
+build() {
+ cd "$srcdir"/aumix-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --without-gtk1 \
+ --without-gtk \
+ --disable-nls
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/aumix-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ install -Dm755 "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/aumix
+}
+md5sums="34f28ae1c94fc5298e8bb2688c4b3a20 aumix-2.9.1.tar.bz2
+affaa735ad9b65a540842994caba18fd aumix.initd"
diff --git a/main/aumix/aumix.initd b/main/aumix/aumix.initd
new file mode 100644
index 0000000000..2c1741b3b9
--- /dev/null
+++ b/main/aumix/aumix.initd
@@ -0,0 +1,42 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/media-sound/aumix/files/aumix.rc6,v 1.12 2007/03/25 13:05:51 drac Exp $
+
+depend() {
+ use modules hotplug coldplug alsasound
+}
+
+checkconfig() {
+ if ! grep -q -E 'sound|OSS|sparcaudio' /proc/devices && [ ! -d /proc/asound ] ; then
+ eerror "Sound support has not been compiled into the kernel,"
+ eerror "or is disabled. Please check that the correct modules"
+ eerror "is loaded."
+ return 1
+ fi
+ # /dev/mixer can be a symlink
+ if [ ! -e /dev/mixer ] ; then
+ eerror "/dev/mixer does not exist, please create it, or load the"
+ eerror "correct modules to enable your card's mixer"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ if [ -f /etc/aumixrc ] ; then
+ ebegin "Loading Mixer settings"
+ /usr/bin/aumix -f /etc/aumixrc -L >/dev/null 2>&1
+ else
+ ebegin "Setting Mixer settings"
+ /usr/bin/aumix -v75 -c75 -w75 >/dev/null 2>&1
+ fi
+ eend $?
+}
+
+stop() {
+ checkconfig || return 1
+ ebegin "Saving Mixer settings"
+ /usr/bin/aumix -f /etc/aumixrc -S >/dev/null 2>&1
+ eend $?
+}
diff --git a/main/autoconf/APKBUILD b/main/autoconf/APKBUILD
new file mode 100644
index 0000000000..2d22ec8551
--- /dev/null
+++ b/main/autoconf/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=autoconf
+pkgver=2.68
+pkgrel=1
+pkgdesc="A GNU tool for automatically configuring source code"
+arch="noarch"
+license="GPL2 GPL3"
+url="http://www.gnu.org/software/autoconf"
+depends="m4 perl"
+source="ftp://ftp.gnu.org/pub/gnu/${pkgname}/${pkgname}-${pkgver}.tar.gz
+ "
+subpackages="$pkgname-doc"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ M4=/usr/bin/m4 ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/share/info/dir
+ # conflict with bintuils
+ rm -f "$pkgdir"/usr/share/info/standards.info
+}
+
+md5sums="c3b5247592ce694f7097873aa07d66fe autoconf-2.68.tar.gz"
diff --git a/main/autoconf2.13/APKBUILD b/main/autoconf2.13/APKBUILD
new file mode 100644
index 0000000000..0265210f70
--- /dev/null
+++ b/main/autoconf2.13/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer:
+pkgname=autoconf2.13
+pkgver=2.13
+pkgrel=0
+pkgdesc="A GNU tool for automatically configuring source code"
+arch="noarch"
+license="GPL2"
+url="http://www.gnu.org/software/autoconf"
+depends="m4 perl"
+source="ftp://ftp.gnu.org/pub/gnu/autoconf/autoconf-${pkgver}.tar.gz
+ "
+subpackages="$pkgname-doc"
+
+_builddir="${srcdir}/autoconf-${pkgver}"
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ M4=/usr/bin/m4 ./configure --prefix=/usr --program-suffix=-2.13
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make prefix="${pkgdir}/usr" infodir="${pkgdir}/usr/share/info" install || return 1
+
+ rm -f "$pkgdir"/usr/share/info/dir
+ rm -f "$pkgdir"/usr/share/info/standards.info
+}
+
+md5sums="9de56d4a161a723228220b0f425dc711 autoconf-2.13.tar.gz"
diff --git a/main/automake/APKBUILD b/main/automake/APKBUILD
new file mode 100644
index 0000000000..262d1caaa3
--- /dev/null
+++ b/main/automake/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=automake
+pkgver=1.11.1
+pkgrel=0
+pkgdesc="A GNU tool for automatically creating Makefiles"
+arch="noarch"
+license=GPL
+url="http://www.gnu.org/software/automake"
+source=ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz
+depends="perl"
+makedepends="autoconf"
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR=$pkgdir install
+}
+
+md5sums="4ee7f0ff5f0e467d58b6bd5da96b1c74 automake-1.11.1.tar.gz"
diff --git a/main/avahi/APKBUILD b/main/avahi/APKBUILD
new file mode 100644
index 0000000000..0ffbd2075e
--- /dev/null
+++ b/main/avahi/APKBUILD
@@ -0,0 +1,118 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=avahi
+pkgver=0.6.30
+pkgrel=3
+pkgdesc="A multicast/unicast DNS-SD framework"
+url="http://www.avahi.org/"
+arch="all"
+license="LGPL"
+depends=""
+depends_dev="gtk+-dev gdbm-dev"
+makedepends="py-gtk-dev py-dbus-dev intltool gobject-introspection-dev expat-dev
+ libdaemon-dev glib-dev dbus-dev libcap-dev gdbm-dev gtk+-dev py-gdbm"
+install="$pkgname.pre-install"
+pkgusers="avahi"
+pkggroups="avahi"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-tools $pkgname-ui-tools:uitools
+ $pkgname-glib $pkgname-ui $pkgname-libs $pkgname-compat-howl:howl
+ $pkgname-compat-libdns_sd:lidns_sd"
+source="http://www.avahi.org/download/avahi-$pkgver.tar.gz
+ gnome-nettool.png"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build ()
+{
+ cd "$srcdir/$pkgname-$pkgver"
+ # we dont build autoipd since dhcpcd does same job
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-autoipd \
+ --disable-qt3 \
+ --disable-qt4 \
+ --disable-gtk3 \
+ --disable-mono \
+ --disable-monodoc \
+ --disable-doxygen-doc \
+ --disable-xmltoman \
+ --enable-compat-libdns_sd \
+ --enable-compat-howl \
+ --with-distro="gentoo" \
+ --with-systemdsystemunitdir=/lib/systemd/system
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -d -o avahi -g avahi "$pkgdir"/var/run/avahi-daemon
+ ln -s avahi-compat-howl.pc "$pkgdir"/usr/lib/pkgconfig/howl.pc
+ ln -s avahi-compat-libdns_sd.pc \
+ "$pkgdir"/usr/lib/pkgconfig/libdns_sd.pc
+ ln -s avahi-compat-libdns_sd/dns_sd.h "$pkgdir"/usr/include/
+}
+
+dev() {
+ default_dev
+ rm -f "$subpkgdir"/usr/lib/*.la
+}
+
+tools() {
+ pkgdesc="Command line tools for mDNS browsing and publishing"
+ mkdir -p "$subpkgdir"/usr/bin
+ cd "$pkgdir"/usr/bin
+ mv avahi-browse* avahi-publish* avahi-resolve* avahi-set* \
+ "$subpkgdir"/usr/bin/
+}
+
+uitools() {
+ pkgdesc="UI tools for mDNS browsing"
+ depends="py-gtk py-dbus py-gdbm"
+ mkdir -p "$subpkgdir"/usr/bin
+ cd "$pkgdir"/usr/bin
+ mv avahi-bookmarks avahi-discover avahi-discover-standalone b* \
+ "$subpkgdir"/usr/bin/
+ install -D -m 644 "$srcdir"/gnome-nettool.png \
+ "$subpkgdir"/usr/share/pixmaps/gnome-nettool.png
+}
+
+glib() {
+ pkgdesc="Glib libraries and GObject wrapper for avahi"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libavahi-glib.so.* \
+ "$pkgdir"/usr/lib/libavahi-gobject.so.* \
+ "$subpkgdir"/usr/lib/
+}
+
+ui() {
+ pkgdesc="Gtk user interface library for Avahi"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libavahi-ui.so.* \
+ "$subpkgdir"/usr/lib/
+}
+
+libs() {
+ pkgdesc="Libraries for avahi run-time use"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libavahi-common.so.* \
+ "$pkgdir"/usr/lib/libavahi-client.so.* \
+ "$subpkgdir"/usr/lib/
+}
+
+
+howl() {
+ pkgdesc="Libraries for howl compatibility"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libhowl.so.* \
+ "$subpkgdir"/usr/lib/
+}
+
+lidns_sd() {
+ pkgdesc="Libraries for Apple Bonjour mDNSResponder compatibility"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libdns_sd.so.* \
+ "$subpkgdir"/usr/lib/
+}
+
+md5sums="e4db89a2a403ff4c47d66ac66fad1f43 avahi-0.6.30.tar.gz
+42c2905307c7a5dc6ac4b75f4c3d65a3 gnome-nettool.png"
diff --git a/main/avahi/avahi.pre-install b/main/avahi/avahi.pre-install
new file mode 100644
index 0000000000..e982c7d41f
--- /dev/null
+++ b/main/avahi/avahi.pre-install
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+addgroup -S -g 28 netdev 2>/dev/null
+addgroup -S -g 86 avahi 2>/dev/null
+adduser -u 86 \
+ -h /var/run/avahi-daemon \
+ -s /bin/false \
+ -S -D -H \
+ -g "Avahi System User" \
+ -G avahi \
+ avahi 2>/dev/null
+
+exit 0
diff --git a/main/avahi/gnome-nettool.png b/main/avahi/gnome-nettool.png
new file mode 100644
index 0000000000..227d0678a3
--- /dev/null
+++ b/main/avahi/gnome-nettool.png
Binary files differ
diff --git a/main/awstats/APKBUILD b/main/awstats/APKBUILD
new file mode 100644
index 0000000000..6822ce607c
--- /dev/null
+++ b/main/awstats/APKBUILD
@@ -0,0 +1,59 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=awstats
+pkgver=7.0
+pkgrel=0
+pkgdesc="AWStats is short for Advanced Web Statistics."
+url="http://awstats.sourceforge.net/"
+arch="noarch"
+license="GPL-2"
+depends="perl perl-uri"
+subpackages="$pkgname-doc"
+source="http://prdownloads.sourceforge.net/awstats/awstats-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local file
+ cd "$_builddir"
+ for file in tools/* wwwroot/cgi-bin/*; do
+ [ -f "${file}" ] || continue
+ sed -e "s:/usr/local/awstats/wwwroot:/usr/lib/awstats:g" \
+ -i "$file"
+ done
+}
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+# logpath="awstats_log"
+# sed -e "s|^\(LogFile=\).*$|\1\"/var/log/${logpath}\"|" \
+# -e "s|^\(SiteDomain=\).*$|\1\"localhost\"|"
+# -e "s|^\(DirIcons=\).*$|\1\"/awstats/icon\"|"
+# -e "s|^\(DirCgi=\).*$|\1\"/cgi-bin\"|"
+# -i "${S}"/wwwroot/cgi-bin/awstats.model.conf || die "sed failed"
+# if use ipv6; then
+# sed -e "s|^#\(LoadPlugin=\"ipv6\"\)$|\1|" -i "${S}"/wwwroot/cgi-bin/awstats.model.conf || die "sed failed"
+# fi
+
+ install -d "$pkgdir"/usr/share/doc/awstats \
+ "$pkgdir"/var/lib/awstats \
+ "$pkgdir"/usr/lib/awstats \
+ "$pkgdir"/usr/bin \
+ "$pkgdir"/etc/awstats
+ # docs
+ cp -a docs tools/xslt "$pkgdir"/usr/share/doc/awstats || return 1
+
+ # cgi-bin
+ cp -a wwwroot/* "$pkgdir"/usr/lib/awstats
+ mv "$pkgdir"/usr/lib/awstats/cgi-bin/awstats.model.conf \
+ "$pkgdir"/etc/awstats/
+ ln -s /etc/aswtats/awstats \
+ "$pkgdir"/usr/lib/awstats/cgi-bin/awstats.model.conf
+
+ # tools
+ cp tools/*.pl "$pkgdir"/usr/bin/ || return 1
+ ln -s /usr/lib/awstats/cgi-bin/awstats.pl "$pkgdir"/usr/bin/
+}
+md5sums="3e8e09b9ebe74513bb34290dbcd37b45 awstats-7.0.tar.gz"
diff --git a/main/b43-fwcutter/APKBUILD b/main/b43-fwcutter/APKBUILD
new file mode 100644
index 0000000000..e7f1fdb427
--- /dev/null
+++ b/main/b43-fwcutter/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=b43-fwcutter
+pkgver=014
+pkgrel=0
+pkgdesc="Tool to extract firmware from Broadcom drivers"
+url="http://linuxwireless.org/en/users/Drivers/b43"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-doc"
+source="http://bu3sch.de/b43/fwcutter/b43-fwcutter-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make PREFIX="$pkgdir"/usr install
+ mkdir -p "$pkgdir"/usr/share/
+ mv "$pkgdir"/usr/man "$pkgdir"/usr/share/
+}
+
+md5sums="dd63f9149510bd6e01b89314e955083b b43-fwcutter-014.tar.bz2"
diff --git a/main/babl/APKBUILD b/main/babl/APKBUILD
new file mode 100644
index 0000000000..358a89a98d
--- /dev/null
+++ b/main/babl/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=babl
+pkgver=0.1.4
+pkgrel=1
+pkgdesc="Dynamic, any to any, pixel format conversion library"
+url="http://gegl.org/babl/"
+arch="all"
+license="LGPL3"
+depends=
+makedepends=
+subpackages="$pkgname-dev"
+source="ftp://ftp.gimp.org/pub/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/babl*/*.la \
+ "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="1deaf8188b200b10d98a343a7e712b2b babl-0.1.4.tar.bz2"
diff --git a/main/backuppc/APKBUILD b/main/backuppc/APKBUILD
new file mode 100644
index 0000000000..694c0a2f2f
--- /dev/null
+++ b/main/backuppc/APKBUILD
@@ -0,0 +1,67 @@
+# Contributor:
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname="backuppc"
+_realname="BackupPC"
+pkgver="3.2.0"
+_realver="3.2.0"
+pkgrel=3
+pkgdesc="High-performance, enterprise-grade backup system"
+url="http://backuppc.sourceforge.net/"
+arch="noarch"
+license="GPL"
+depends="perl busybox rsync perl-archive-zip perl-io-compress
+ perl-libwww perl-file-rsync"
+makedepends=""
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages=""
+source="http://downloads.sourceforge.net/project/$pkgname/$pkgname/$_realver/$_realname-$_realver.tar.gz
+ configure.pl.patch"
+
+_builddir="$srcdir/$_realname-$_realver"
+
+prepare () {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/etc/BackupPC
+ mkdir -p "$pkgdir"/var/www/cgi-bin
+ patch -p2 < ../../configure.pl.patch
+}
+
+build() {
+ cd "$_builddir"
+ perl configure.pl \
+ --batch \
+ --backuppc-user=backuppc \
+ --bin-path bzip2=/usr/bin/bzip2 \
+ --bin-path cat=/bin/cat \
+ --bin-path df=/bin/df \
+ --bin-path tar=/bin/tar \
+ --bin-path hostname=/bin/hostname \
+ --bin-path nmblookup=/usr/bin/nmblookup \
+ --bin-path perl=/usr/bin/perl \
+ --bin-path ping=/bin/ping \
+ --bin-path rsync=/usr/bin/rsync \
+ --bin-path sendmail=/usr/bin/sendmail \
+ --bin-path smbclient=/usr/bin/smbclient \
+ --bin-path split=/usr/bin/split \
+ --bin-path ssh=/usr/bin/ssh \
+ --compress-level=3 \
+ --dest-dir="$pkgdir" \
+ --config-dir /etc/BackupPC \
+ --cgi-dir /var/www/cgi-bin \
+ --data-dir /var/lib/BackupPC \
+ --hostname backuppc \
+ --html-dir /var/www/htdocs/BackupPC \
+ --html-dir-url /BackupPC \
+ --install-dir /usr/lib/BackupPC \
+ --log-dir /var/log/BackupPC \
+ --uid-ignore \
+ --no-set-perms || return 1
+}
+
+package() {
+ cd $_builddir
+ install -m755 configure.pl $pkgdir/usr/lib/BackupPC/bin/configure.pl
+}
+
+md5sums="4b77610d8d1130daf0892fc7134be985 BackupPC-3.2.0.tar.gz
+f57ad7fdcce804f20f2fe82bee91e813 configure.pl.patch"
diff --git a/main/backuppc/backuppc.initd b/main/backuppc/backuppc.initd
new file mode 100644
index 0000000000..eefdc92c7c
--- /dev/null
+++ b/main/backuppc/backuppc.initd
@@ -0,0 +1,43 @@
+#!/sbin/runscript
+
+depend() {
+ after firewall modules
+}
+
+
+configure () {
+ chown $USER $BACKUPPC_LOGDIR
+ chmod a+x $BACKUPPC_BINDIR/*
+ test -x $BACKUPPC_BINDIR/$DAEMON || exit 0
+}
+
+start() {
+ ebegin "Starting $DAEMON"
+ start-stop-daemon --start --pidfile $BACKUPPC_LOGDIR/BackupPC.pid \
+ -c $USER --exec $BACKUPPC_BINDIR/$DAEMON -- -d
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping $DAEMON"
+ start-stop-daemon --stop --pidfile $BACKUPPC_LOGDIR/BackupPC.pid \
+ --retry 30 -x /usr/bin/perl
+ eend $?
+}
+
+restart () {
+ start-stop-daemon --stop --pidfile $BACKUPPC_LOGDIR/BackupPC.pid \
+ --retry 30 -x /usr/bin/perl
+ start-stop-daemon --start --pidfile $BACKUPPC_LOGDIR/BackupPC.pid \
+ -c $USER --exec $BACKUPPC_BINDIR/$DAEMON -- -d
+}
+
+reload () {
+ start-stop-daemon --stop --pidfile $BACKUPPC_LOGDIR/BackupPC.pid \
+ --signal 1 -x /usr/bin/perl
+}
+
+
+
+
+
diff --git a/main/backuppc/backuppc.post-install b/main/backuppc/backuppc.post-install
new file mode 100644
index 0000000000..abbfeb40d6
--- /dev/null
+++ b/main/backuppc/backuppc.post-install
@@ -0,0 +1,8 @@
+#!/bin/sh
+for dir in /etc /var/log /var/lib
+do
+ chown -R backuppc.backuppc ${dir}/BackupPC &>/dev/null
+done
+
+chmod 774 /usr/lib/BackupPC/bin/* &>/dev/null
+ln -s /var/www/htdocs/BackupPC/index.cgi /var/www/cgi-bin/BackupPC_Admin &>/dev/null
diff --git a/main/backuppc/backuppc.pre-install b/main/backuppc/backuppc.pre-install
new file mode 100644
index 0000000000..04a7ce1919
--- /dev/null
+++ b/main/backuppc/backuppc.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+addgroup -S backuppc &>/dev/null
+adduser -h /var/lib/BackupPC -s /bin/sh -S -D -H -G backuppc -g "BackupPC user" backuppc &>/dev/null
+exit 0
diff --git a/main/backuppc/configure.pl.patch b/main/backuppc/configure.pl.patch
new file mode 100644
index 0000000000..24d5e3bb38
--- /dev/null
+++ b/main/backuppc/configure.pl.patch
@@ -0,0 +1,66 @@
+--- src/BackupPC-3.2.0beta1/configure.pl
++++ configure.pl
+@@ -327,25 +327,8 @@
+
+ EOF
+ my($name, $passwd, $Uid, $Gid);
+-while ( 1 ) {
+- $Conf{BackupPCUser} = prompt("--> BackupPC should run as user",
+- $Conf{BackupPCUser} || "backuppc",
+- "backuppc-user");
+- if ( $opts{"set-perms"} ) {
+ ($name, $passwd, $Uid, $Gid) = getpwnam($Conf{BackupPCUser});
+- last if ( $name ne "" );
+- print <<EOF;
+
+-getpwnam() says that user $Conf{BackupPCUser} doesn't exist. Please
+-check the name and verify that this user is in the passwd file.
+-
+-EOF
+- exit(1) if ( $opts{batch} );
+- } else {
+- last;
+- }
+-}
+-
+ print <<EOF;
+
+ Please specify an install directory for BackupPC. This is where the
+@@ -532,12 +515,6 @@
+ ) ) {
+ next if ( -d "$DestDir$Conf{InstallDir}/$dir" );
+ mkpath("$DestDir$Conf{InstallDir}/$dir", 0, 0755);
+- if ( !-d "$DestDir$Conf{InstallDir}/$dir"
+- || !my_chown($Uid, $Gid, "$DestDir$Conf{InstallDir}/$dir") ) {
+- die("Failed to create or chown $DestDir$Conf{InstallDir}/$dir\n");
+- } else {
+- print("Created $DestDir$Conf{InstallDir}/$dir\n");
+- }
+ }
+
+ #
+@@ -546,11 +523,6 @@
+ foreach my $dir ( ($Conf{CgiImageDir}) ) {
+ next if ( $dir eq "" || -d "$DestDir$dir" );
+ mkpath("$DestDir$dir", 0, 0755);
+- if ( !-d "$DestDir$dir" || !my_chown($Uid, $Gid, "$DestDir$dir") ) {
+- die("Failed to create or chown $DestDir$dir");
+- } else {
+- print("Created $DestDir$dir\n");
+- }
+ }
+
+ #
+@@ -566,12 +538,6 @@
+ "$Conf{LogDir}",
+ ) ) {
+ mkpath("$DestDir$dir", 0, 0750) if ( !-d "$DestDir$dir" );
+- if ( !-d "$DestDir$dir"
+- || !my_chown($Uid, $Gid, "$DestDir$dir") ) {
+- die("Failed to create or chown $DestDir$dir\n");
+- } else {
+- print("Created $DestDir$dir\n");
+- }
+ }
+
+ printf("Installing binaries in $DestDir$Conf{InstallDir}/bin\n");
diff --git a/main/bacula-client/APKBUILD b/main/bacula-client/APKBUILD
new file mode 100644
index 0000000000..55a747db39
--- /dev/null
+++ b/main/bacula-client/APKBUILD
@@ -0,0 +1,97 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname="bacula-client"
+_realname="bacula"
+pkgver=5.0.3
+pkgrel=7
+pkgdesc="Client (File Daemon) of Bacula, a network based backup program"
+url="http://www.bacula.org"
+arch="all"
+license="GPL2"
+depends=""
+makedepends="autoconf automake libstdc++ openssl-dev ncurses-dev zlib-dev"
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/project/$_realname/$_realname/$pkgver/$_realname-$pkgver.tar.gz
+ bacula-fd-init
+ bacula-fd-conf
+ bacula-5.0.1-dsolink.patch
+ bacula-5.0.2-config.patch
+ bacula-5.0.2-openssl.patch
+ bacula-5.0.2-python27.patch
+ bacula-5.0.3-Makefile.patch
+ bacula-5.0.3-as-needed.patch
+ bacula-5.0.3-dsolink.patch
+ bacula-5.0.3-log-path.patch
+ bacula-5.0.3-mysql55.patch
+ bacula-5.0.3-sqlite-priv.patch
+ configure.in.patch
+ cxx.patch
+ os.m4.patch"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare () {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ cd "$_builddir"/autoconf
+ autoconf && cp configure ../
+}
+
+build() {
+ cd "$_builddir"
+ export LDFLAGS=
+ # in order to do not go into an infinite loop
+ aclocal && autoconf && automake
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/bacula \
+ --localstatedir=/var \
+ --mandir=/usr/share/man \
+ --docdir=/usr/share/doc \
+ --infodir=/usr/share/info \
+ --with-pid-dir=/var/run \
+ --with-subsys-dir=/var/lock/subsys \
+ --enable-largefile \
+ --enable-client-only \
+ --enable-smartalloc \
+ --disable-nls \
+ --with-openssl=/usr/include/openssl \
+ --with-scriptdir=/etc/bacula/scripts \
+ --with-working-dir=/var/bacula \
+ --with-fd-user=root \
+ --with-fd-group=root
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ install -Dm755 $srcdir/bacula-fd-init \
+ $pkgdir/etc/init.d/bacula-fd
+ install -Dm644 $srcdir/bacula-fd-conf \
+ $pkgdir/etc/conf.d/bacula-fd
+}
+
+md5sums="9de254ae39cab0587fdb2f5d8d90b03b bacula-5.0.3.tar.gz
+38b0fe78acdc5e65aec3a59578e98a20 bacula-fd-init
+4500ce2d62bf9df33c07f70dc40f7b85 bacula-fd-conf
+eee101f1b7b6b4f2c140898db5f8123b bacula-5.0.1-dsolink.patch
+71f7f9c041eff045b2e97d141316c059 bacula-5.0.2-config.patch
+4e310e84c7aba5b8d043758e0fa0088f bacula-5.0.2-openssl.patch
+13e511698b5dc376e673c963a848d364 bacula-5.0.2-python27.patch
+0ec20df57bb632ed729cfaf5d0a3ee33 bacula-5.0.3-Makefile.patch
+76267747f4d2e85e033cc6793ccb6afa bacula-5.0.3-as-needed.patch
+82d3a5c113c633bf0bd86ac3590baaff bacula-5.0.3-dsolink.patch
+9bde1e9d43146af8985ff62d491d7218 bacula-5.0.3-log-path.patch
+def9da0c090141dcef817d80c1a29fd1 bacula-5.0.3-mysql55.patch
+9def0e68e3eb2f5f8b4c34108a248efd bacula-5.0.3-sqlite-priv.patch
+ebc9c2bbc9be95c920723a3f142d8e19 configure.in.patch
+1bfdbfea7a36d5503753414dffb953eb cxx.patch
+cf7a2a4e972697f54364654c4e282b8b os.m4.patch"
diff --git a/main/bacula-client/bacula-5.0.1-dsolink.patch b/main/bacula-client/bacula-5.0.1-dsolink.patch
new file mode 100644
index 0000000000..1669cecb68
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.1-dsolink.patch
@@ -0,0 +1,11 @@
+--- bacula-5.0.1/src/qt-console/bat.pro.in~ 2010-02-24 09:33:48.000000000 -0600
++++ bacula-5.0.1/src/qt-console/bat.pro.in 2010-03-11 17:12:44.645296544 -0600
+@@ -20,7 +20,7 @@
+ TARGET = bat
+ DEPENDPATH += .
+ INCLUDEPATH += .. . ./console ./restore ./select
+-LIBS += -L../lib -lbaccfg -lbac @OPENSSL_LIBS@
++LIBS += -L../lib -lbaccfg -lbac -ldl @OPENSSL_LIBS@
+ LIBTOOL_LINK = @QMAKE_LIBTOOL@ --silent --tag=CXX --mode=link
+ LIBTOOL_INSTALL = @QMAKE_LIBTOOL@ --silent --mode=install
+ QMAKE_LINK = $${LIBTOOL_LINK} $(CXX)
diff --git a/main/bacula-client/bacula-5.0.2-config.patch b/main/bacula-client/bacula-5.0.2-config.patch
new file mode 100644
index 0000000000..f78c665b70
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.2-config.patch
@@ -0,0 +1,12 @@
+diff -up bacula-5.0.2/bacula-5.0.2/src/dird/bacula-dir.conf.in.config bacula-5.0.2/bacula-5.0.2/src/dird/bacula-dir.conf.in
+--- bacula-5.0.2/src/dird/bacula-dir.conf.in.config 2010-06-03 11:05:07.000000000 +0200
++++ bacula-5.0.2/src/dird/bacula-dir.conf.in 2010-06-03 11:28:26.556782993 +0200
+@@ -15,7 +15,7 @@
+ Director { # define myself
+ Name = bacula-dir
+ DIRport = @dir_port@ # where we listen for UA connections
+- QueryFile = "@scriptdir@/query.sql"
++ QueryFile = "/etc/bacula/query.sql"
+ WorkingDirectory = "@working_dir@"
+ PidDirectory = "@piddir@"
+ Maximum Concurrent Jobs = 1
diff --git a/main/bacula-client/bacula-5.0.2-openssl.patch b/main/bacula-client/bacula-5.0.2-openssl.patch
new file mode 100644
index 0000000000..a71d8d5467
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.2-openssl.patch
@@ -0,0 +1,24 @@
+diff -up bacula-5.0.2/src/lib/crypto.c.openssl bacula-5.0.2/bacula-5.0.2/src/lib/crypto.c
+--- bacula-5.0.2/src/lib/crypto.c.openssl 2010-04-27 21:58:29.000000000 +0200
++++ bacula-5.0.2/src/lib/crypto.c 2010-06-01 17:51:52.846894465 +0200
+@@ -51,7 +51,7 @@
+ * For OpenSSL version 1.x, EVP_PKEY_encrypt no longer
+ * exists. It was not an official API.
+ */
+-#ifdef HAVE_OPENSSLv1
++#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
+ #define EVP_PKEY_encrypt EVP_PKEY_encrypt_old
+ #define EVP_PKEY_decrypt EVP_PKEY_decrypt_old
+ #endif
+diff -up bacula-5.0.2/bacula-5.0.2/src/lib/tls.c.openssl bacula-5.0.2/bacula-5.0.2/src/lib/tls.c
+--- bacula-5.0.2/src/lib/tls.c.openssl 2010-04-27 21:58:29.000000000 +0200
++++ bacula-5.0.2/src/lib/tls.c 2010-06-01 17:52:15.535769446 +0200
+@@ -315,7 +315,7 @@ bool tls_postconnect_verify_host(JCR *jc
+ extname = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
+
+ if (strcmp(extname, "subjectAltName") == 0) {
+-#ifdef HAVE_OPENSSLv1
++#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
+ const X509V3_EXT_METHOD *method;
+ #else
+ X509V3_EXT_METHOD *method;
diff --git a/main/bacula-client/bacula-5.0.2-python27.patch b/main/bacula-client/bacula-5.0.2-python27.patch
new file mode 100644
index 0000000000..36543872e8
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.2-python27.patch
@@ -0,0 +1,22 @@
+--- ./configure~ 2010-04-27 14:58:29.000000000 -0500
++++ ./configure 2010-07-30 11:28:47.494178663 -0500
+@@ -26255,7 +26255,7 @@
+ PYTHON_LIBS=`/usr/bin/python-config --libs`
+ else
+ for python_root in /usr /usr/local /usr/sfw; do
+- for ver in python2.2 python2.3 python2.4 python2.5 python2.6 python3; do
++ for ver in python2.2 python2.3 python2.4 python2.5 python2.6 python2.7 python3; do
+ if test -f $python_root/include/${ver}/Python.h; then
+ PYTHON_INCDIR=-I$python_root/include/${ver}
+ if test -d $python_root/lib64/${ver}/config; then
+--- ./autoconf/configure.in~ 2010-04-27 14:58:29.000000000 -0500
++++ ./autoconf/configure.in 2010-07-30 11:30:22.837182092 -0500
+@@ -963,7 +963,7 @@
+ PYTHON_LIBS=`/usr/bin/python-config --libs`
+ else
+ for python_root in /usr /usr/local /usr/sfw; do
+- for ver in python2.2 python2.3 python2.4 python2.5 python2.6 python3; do
++ for ver in python2.2 python2.3 python2.4 python2.5 python2.6 python2.7 python3; do
+ if test -f $python_root/include/${ver}/Python.h; then
+ PYTHON_INCDIR=-I$python_root/include/${ver}
+ if test -d $python_root/lib64/${ver}/config; then
diff --git a/main/bacula-client/bacula-5.0.3-Makefile.patch b/main/bacula-client/bacula-5.0.3-Makefile.patch
new file mode 100644
index 0000000000..a3f32729d7
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.3-Makefile.patch
@@ -0,0 +1,26 @@
+--- ./Makefile.in.orig 2010-07-20 16:53:44.000000000 +0000
++++ ./Makefile.in 2010-07-20 16:55:50.000000000 +0000
+@@ -44,9 +44,8 @@
+
+ all: Makefile
+ @for I in ${all_subdirs}; \
+- do (cd $$I; echo "==>Entering directory `pwd`"; \
+- $(MAKE) DESTDIR=$(DESTDIR) $@ || (echo ""; echo ""; echo " ====== Error in `pwd` ======"; \
+- echo ""; echo ""; exit 1;)); \
++ do \
++ $(MAKE) DESTDIR=$(DESTDIR) -C $$I $@ || exit 1; \
+ done
+
+ depend:
+@@ -55,9 +54,8 @@
+
+ bacula-fd: Makefile
+ @for I in ${fd_subdirs}; \
+- do (cd $$I; echo "==>Entering directory `pwd`"; \
+- $(MAKE) DESTDIR=$(DESTDIR) all || (echo ""; echo ""; echo " ====== Error in `pwd` ======"; \
+- echo ""; echo ""; exit 1;)); \
++ do \
++ $(MAKE) DESTDIR=$(DESTDIR) -C $$I all || exit 1; \
+ done
+
+ #-------------------------------------------------------------------------
diff --git a/main/bacula-client/bacula-5.0.3-as-needed.patch b/main/bacula-client/bacula-5.0.3-as-needed.patch
new file mode 100644
index 0000000000..3603e936bb
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.3-as-needed.patch
@@ -0,0 +1,33 @@
+diff -urN bacula-5.0.3.orig/src/findlib/Makefile.in bacula-5.0.3/src/findlib/Makefile.in
+--- bacula-5.0.3.orig/src/findlib/Makefile.in 2010-02-24 16:33:48.000000000 +0100
++++ bacula-5.0.3/src/findlib/Makefile.in 2010-03-22 17:37:43.772805754 +0100
+@@ -59,7 +59,7 @@
+
+ libbacfind.la: Makefile $(LIBBACFIND_LOBJS)
+ @echo "Making $@ ..."
+- $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACFIND_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACFIND_LT_RELEASE)
++ $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACFIND_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACFIND_LT_RELEASE) -L../lib -lbac $(LIBS) $(OPENSSL_LIBS)
+
+ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
+ cd $(topdir) \
+diff -urN bacula-5.0.1.orig/src/lib/Makefile.in bacula-5.0.1/src/lib/Makefile.in
+--- bacula-5.0.1.orig/src/lib/Makefile.in 2010-02-24 16:33:48.000000000 +0100
++++ bacula-5.0.1/src/lib/Makefile.in 2010-03-22 17:37:05.352226188 +0100
+@@ -126,7 +126,7 @@
+
+ libbac.la: Makefile $(LIBBAC_LOBJS)
+ @echo "Making $@ ..."
+- $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBAC_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBAC_LT_RELEASE) $(WRAPLIBS) $(CAP_LIBS) $(ZLIBS)
++ $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBAC_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBAC_LT_RELEASE) $(WRAPLIBS) $(CAP_LIBS) $(ZLIBS) $(LIBS) $(OPENSSL_LIBS)
+
+ libbaccfg.a: $(LIBBACCFG_OBJS)
+ @echo "Making $@ ..."
+@@ -135,7 +135,7 @@
+
+ libbaccfg.la: Makefile $(LIBBACCFG_LOBJS)
+ @echo "Making $@ ..."
+- $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACCFG_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACCFG_LT_RELEASE)
++ $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACCFG_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACCFG_LT_RELEASE) $(LIBS) $(OPENSSL_LIBS)
+
+ libbacpy.a: $(LIBBACPY_OBJS)
+ @echo "Making $@ ..."
diff --git a/main/bacula-client/bacula-5.0.3-dsolink.patch b/main/bacula-client/bacula-5.0.3-dsolink.patch
new file mode 100644
index 0000000000..44309dad86
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.3-dsolink.patch
@@ -0,0 +1,165 @@
+--- bacula-5.0.3/src/qt-console/bat.pro.in~ 2010-08-10 11:27:17.000000000 -0500
++++ bacula-5.0.3/src/qt-console/bat.pro.in 2010-08-10 12:32:00.312182153 -0500
+@@ -20,7 +20,7 @@
+ TARGET = bat
+ DEPENDPATH += .
+ INCLUDEPATH += .. . ./console ./restore ./select
+-LIBS += -L../lib -lbaccfg -lbac -ldl @OPENSSL_LIBS@
++LIBS += -L../lib -lbaccfg -lbac -ldl -lz @OPENSSL_LIBS@
+ LIBTOOL_LINK = @QMAKE_LIBTOOL@ --silent --tag=CXX --mode=link
+ LIBTOOL_INSTALL = @QMAKE_LIBTOOL@ --silent --mode=install
+ QMAKE_LINK = $${LIBTOOL_LINK} $(CXX)
+--- bacula-5.0.3/src/tools/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/tools/Makefile.in 2010-08-11 12:54:02.028450916 -0500
+@@ -57,7 +57,7 @@
+ @echo " "
+
+ bsmtp: Makefile bsmtp.o ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+- $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -o $@ bsmtp.o -lbac -lm $(DLIB) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -o $@ bsmtp.o -lbac -lm -lz $(DLIB) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bregtest: Makefile bregtest.o ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -o $@ bregtest.o -lbac -lm $(DLIB) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+--- bacula-5.0.3/src/tools/Makefile.in~ 2010-08-11 12:57:29.000000000 -0500
++++ bacula-5.0.3/src/tools/Makefile.in 2010-08-11 14:10:52.998447849 -0500
+@@ -64,7 +64,7 @@
+
+ dbcheck: Makefile dbcheck.o ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE) $(DIRCONFOBJS)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ dbcheck.o $(DIRCONFOBJS) \
+- -lbacsql -lbaccfg -lbac -lm $(DB_LIBS) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacsql -lbaccfg -lbac -lm -lz $(DB_LIBS) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ fstype: Makefile fstype.o ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -L../findlib -o $@ fstype.o -lbacfind -lbac -lm \
+--- bacula-5.0.3/src/tools/Makefile.in~ 2010-08-11 14:13:51.000000000 -0500
++++ bacula-5.0.3/src/tools/Makefile.in 2010-08-11 15:11:00.309447155 -0500
+@@ -97,7 +97,7 @@
+
+ bwild: Makefile ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) bwild.o
+ $(LIBTOOL_LINK) $(CXX) -g $(LDFLAGS) -L. -L../lib -o $@ bwild.o \
+- $(DLIB) -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ $(DLIB) -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bbatch: Makefile ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE) bbatch.o
+ $(LIBTOOL_LINK) $(CXX) -g $(LDFLAGS) -L../cats -L. -L../lib -o $@ bbatch.o \
+--- bacula-5.0.3/src/tools/Makefile.in~ 2010-08-12 06:57:25.000000000 -0500
++++ bacula-5.0.3/src/tools/Makefile.in 2010-08-12 07:58:13.545781384 -0500
+@@ -93,7 +93,7 @@
+
+ bregex: Makefile ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) bregex.o
+ $(LIBTOOL_LINK) $(CXX) -g $(LDFLAGS) -L. -L../lib -o $@ bregex.o \
+- $(DLIB) -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ $(DLIB) -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bwild: Makefile ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) bwild.o
+ $(LIBTOOL_LINK) $(CXX) -g $(LDFLAGS) -L. -L../lib -o $@ bwild.o \
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 08:56:11.053777811 -0500
+@@ -91,7 +91,7 @@
+ bacula-sd: Makefile $(SDOBJS) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ @echo "Linking $@ ..."
+ $(LIBTOOL_LINK) $(CXX) $(WLDFLAGS) $(LDFLAGS) -L../lib -o $@ $(SDOBJS) $(FDLIBS) \
+- -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(DLIB) $(LIBS) $(WRAPLIBS) \
++ -lbacpy -lbaccfg -lbac -lm -lz $(PYTHON_LIBS) $(DLIB) $(LIBS) $(WRAPLIBS) \
+ $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS)
+
+ static-bacula-sd: Makefile $(SDOBJS) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-12 08:59:17.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 10:24:42.478529732 -0500
+@@ -117,7 +117,7 @@
+ bls: Makefile $(BLSOBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ @echo "Compiling $<"
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BLSOBJS) $(DLIB) \
+- -lbacfind -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacfind -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bextract.o: bextract.c
+ @echo "Compiling $<"
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-12 10:27:36.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 11:45:39.904529074 -0500
+@@ -127,7 +127,7 @@
+ bextract: Makefile $(BEXTOBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ @echo "Compiling $<"
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BEXTOBJS) $(DLIB) $(FDLIBS) \
+- -lbacfind -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacfind -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bscan.o: bscan.c
+ @echo "Compiling $<"
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-12 11:48:22.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 13:21:02.246528324 -0500
+@@ -136,7 +136,7 @@
+
+ bscan: Makefile $(SCNOBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SCNOBJS) \
+- -lbacsql $(DB_LIBS) $(FDLIBS) -lbacfind -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacsql $(DB_LIBS) $(FDLIBS) -lbacfind -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bcopy.o: bcopy.c
+ @echo "Compiling $<"
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-12 13:23:58.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 14:31:11.204777284 -0500
+@@ -107,7 +107,7 @@
+
+ btape: Makefile $(TAPEOBJS) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../cats -o $@ $(TAPEOBJS) \
+- -lbacsql -lbaccfg -lbac $(DLIB) -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacsql -lbaccfg -lbac $(DLIB) -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bls.o: bls.c
+ @echo "Compiling $<"
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-13 07:02:47.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-13 08:25:50.830920608 -0500
+@@ -145,7 +145,7 @@
+
+ bcopy: Makefile $(COPYOBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -o $@ $(COPYOBJS) \
+- -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
+ cd $(topdir) \
+--- bacula-5.0.3/src/dird/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/dird/Makefile.in 2010-08-13 09:25:38.855168511 -0500
+@@ -64,7 +64,7 @@
+ bacula-dir: Makefile $(SVROBJS) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE)
+ @echo "Linking $@ ..."
+ $(LIBTOOL_LINK) $(CXX) $(WLDFLAGS) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SVROBJS) \
+- -lbacfind -lbacsql -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(DLIB) $(DB_LIBS) $(LIBS) \
++ -lbacfind -lbacsql -lbacpy -lbaccfg -lbac -lm -lz $(PYTHON_LIBS) $(DLIB) $(DB_LIBS) $(LIBS) \
+ $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS)
+
+ static-bacula-dir: Makefile $(SVROBJS) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE)
+--- bacula-5.0.3/src/console/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/console/Makefile.in 2010-08-13 10:26:18.001169569 -0500
+@@ -48,7 +48,7 @@
+
+ bconsole: Makefile $(CONSOBJS) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) $(CONS_LDFLAGS) -L../lib -L../cats -o $@ $(CONSOBJS) \
+- $(DLIB) $(CONS_LIBS) -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) \
++ $(DLIB) $(CONS_LIBS) -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) \
+ $(OPENSSL_LIBS)
+
+ static-bconsole: Makefile $(CONSOBJS) ../lib/libbac.a ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE)
+--- bacula-5.0.3/src/wx-console/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/wx-console/Makefile.in 2010-08-13 11:28:43.829917394 -0500
+@@ -83,7 +83,7 @@
+
+ bwx-console: Makefile $(CONSOBJS) @WIN32@ ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(CONSOBJS) $(WIN32RES) -o $@ -L../lib $(CONS_LDFLAGS) \
+- -lbaccfg -lbac $(LIBS) $(OPENSSL_LIBS)
++ -lbaccfg -lbac -lz $(LIBS) $(OPENSSL_LIBS)
+
+ win32: bwx-console_private.res
+
+--- bacula-5.0.3/src/tray-monitor/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/tray-monitor/Makefile.in 2010-08-13 12:34:18.573918720 -0500
+@@ -45,7 +45,7 @@
+
+ bacula-tray-monitor: Makefile $(MONITOROBJS) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) $(MONITOR_LDFLAGS) -L../lib -o $@ \
+- $(MONITOROBJS) $(DLIB) -lbaccfg -lbac -lm $(LIBS) $(OPENSSL_LIBS)
++ $(MONITOROBJS) $(DLIB) -lbaccfg -lbac -lm -lz $(LIBS) $(OPENSSL_LIBS)
+
+ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
+ cd $(topdir) \
diff --git a/main/bacula-client/bacula-5.0.3-log-path.patch b/main/bacula-client/bacula-5.0.3-log-path.patch
new file mode 100644
index 0000000000..15a2fecb5e
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.3-log-path.patch
@@ -0,0 +1,13 @@
+diff --git bacula-5.0.3/src/dird/bacula-dir.conf.in b/bacula-5.0.3/src/dird/bacula-dir.conf.in
+index 922be44..54cca3f 100644
+--- bacula-5.0.3/src/dird/bacula-dir.conf.in
++++ bacula-5.0.3/src/dird/bacula-dir.conf.in
+@@ -273,7 +273,7 @@ Messages {
+ mailcommand = "@sbindir@/bsmtp -h @smtp_host@ -f \"\(Bacula\) \<%r\>\" -s \"Bacula daemon message\" %r"
+ mail = @job_email@ = all, !skipped
+ console = all, !skipped, !saved
+- append = "@working_dir@/log" = all, !skipped
++ append = "/var/log/bacula/bacula.log" = all, !skipped
+ }
+
+ # Default pool definition
diff --git a/main/bacula-client/bacula-5.0.3-mysql55.patch b/main/bacula-client/bacula-5.0.3-mysql55.patch
new file mode 100644
index 0000000000..910ea02302
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.3-mysql55.patch
@@ -0,0 +1,11 @@
+--- ./src/cats/mysql.c~ 2010-08-05 09:29:51.000000000 -0500
++++ ./src/cats/mysql.c 2011-01-06 11:28:59.907306001 -0600
+@@ -292,7 +292,7 @@
+ void db_thread_cleanup()
+ {
+ #ifndef HAVE_WIN32
+- my_thread_end();
++ mysql_thread_end();
+ #endif
+ }
+
diff --git a/main/bacula-client/bacula-5.0.3-sqlite-priv.patch b/main/bacula-client/bacula-5.0.3-sqlite-priv.patch
new file mode 100644
index 0000000000..2738349fcd
--- /dev/null
+++ b/main/bacula-client/bacula-5.0.3-sqlite-priv.patch
@@ -0,0 +1,9 @@
+diff -up src/cats/make_sqlite3_tables.in~ src/cats/make_sqlite3_tables.in
+--- ./src/cats/make_sqlite3_tables.in~ 2010-11-16 17:57:12.705837000 +0100
++++ ./src/cats/make_sqlite3_tables.in 2010-11-16 17:57:12.715837000 +0100
+@@ -426,4 +426,5 @@ PRAGMA synchronous = NORMAL;
+ END-OF-DATA
+
+ chmod 640 ${db_name}.db
++chown bacula:bacula ${db_name}.db
+ exit 0
diff --git a/main/bacula-client/bacula-client.post-install b/main/bacula-client/bacula-client.post-install
new file mode 100644
index 0000000000..51274b5c3f
--- /dev/null
+++ b/main/bacula-client/bacula-client.post-install
@@ -0,0 +1,2 @@
+#!/bin/sh
+chown bacula.bacula /var/bacula
diff --git a/main/bacula-client/bacula-client.pre-install b/main/bacula-client/bacula-client.pre-install
new file mode 100644
index 0000000000..1eba271914
--- /dev/null
+++ b/main/bacula-client/bacula-client.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+addgroup -S bacula 2>/dev/null
+adduser -h /var/lib/bacula/ -s /bin/false -G bacula -S -D bacula 2>/dev/null
+exit 0
diff --git a/main/bacula-client/bacula-config.patch b/main/bacula-client/bacula-config.patch
new file mode 100644
index 0000000000..b6ab5037b4
--- /dev/null
+++ b/main/bacula-client/bacula-config.patch
@@ -0,0 +1,115 @@
+--- bacula-2.4.3/src/dird/bacula-dir.conf.in.orig 2008-12-10 10:17:27.000000000 -0600
++++ bacula-2.4.3/src/dird/bacula-dir.conf.in 2008-12-10 10:17:27.000000000 -0600
+@@ -16 +16 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -30 +30 @@
+- Client = @basename@-fd
++ Client = bacula-fd
+@@ -51 +51 @@
+-# Client = @basename@2-fd
++# Client = bacula2-fd
+@@ -82 +82 @@
+- Client=@basename@-fd
++ Client=bacula-fd
+@@ -157,2 +157,2 @@
+- Name = @basename@-fd
+- Address = @hostname@
++ Name = bacula-fd
++ Address = client.example.com
+@@ -172,2 +172,2 @@
+-# Name = @basename@2-fd
+-# Address = @hostname@2
++# Name = bacula2-fd
++# Address = client2.example.com
+@@ -187 +187 @@
+- Address = @hostname@ # N.B. Use a fully qualified name here
++ Address = storage.example.com # N.B. Use a fully qualified name here
+@@ -200 +200 @@
+-# Address = @hostname@ # N.B. Use a fully qualified name here
++# Address = storage.example.com # N.B. Use a fully qualified name here
+@@ -212 +212 @@
+-# Address = @hostname@ # N.B. Use a fully qualified name here
++# Address = storage.example.com # N.B. Use a fully qualified name here
+@@ -223 +223 @@
+-# Address = @hostname@ # N.B. Use a fully qualified name here
++# Address = storage.example.com # N.B. Use a fully qualified name here
+@@ -299 +299 @@
+- Name = @basename@-mon
++ Name = bacula-mon
+--- bacula-2.4.3/src/filed/bacula-fd.conf.in.orig 2008-12-10 10:19:12.000000000 -0600
++++ bacula-2.4.3/src/filed/bacula-fd.conf.in 2008-12-10 10:19:12.000000000 -0600
+@@ -14 +14 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -23 +23 @@
+- Name = @basename@-mon
++ Name = bacula-mon
+@@ -32 +32 @@
+- Name = @basename@-fd
++ Name = bacula-fd
+@@ -42 +42 @@
+- director = @basename@-dir = all, !skipped, !restored
++ director = bacula-dir = all, !skipped, !restored
+--- bacula-2.4.3/src/stored/bacula-sd.conf.in.orig 2008-12-10 10:21:45.000000000 -0600
++++ bacula-2.4.3/src/stored/bacula-sd.conf.in 2008-12-10 10:21:45.000000000 -0600
+@@ -14 +14 @@
+- Name = @basename@-sd
++ Name = bacula-sd
+@@ -25 +25 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -34 +34 @@
+- Name = @basename@-mon
++ Name = bacula-mon
+@@ -228 +228 @@
+- director = @basename@-dir = all
++ director = bacula-dir = all
+--- bacula-2.4.3/src/wx-console/bwx-console.conf.in.orig 2008-12-10 10:22:23.000000000 -0600
++++ bacula-2.4.3/src/wx-console/bwx-console.conf.in 2008-12-10 10:22:23.000000000 -0600
+@@ -6 +6 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -8 +8 @@
+- address = @hostname@
++ address = server.example.com
+--- bacula-2.4.3/src/tray-monitor/tray-monitor.conf.in.orig 2008-12-10 10:28:02.000000000 -0600
++++ bacula-2.4.3/src/tray-monitor/tray-monitor.conf.in 2008-12-10 10:28:02.000000000 -0600
+@@ -6 +6 @@
+- Name = @basename@-mon
++ Name = bacula-mon
+@@ -12,2 +12,2 @@
+- Name = @basename@-fd
+- Address = @hostname@
++ Name = bacula-fd
++ Address = client.example.com
+@@ -19,2 +19,2 @@
+- Name = @basename@-sd
+- Address = @hostname@
++ Name = bacula-sd
++ Address = storage.example.com
+@@ -26 +26 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -28 +28 @@
+- address = @hostname@
++ Address = director.example.com
+--- bacula-2.4.3/src/qt-console/bat.conf.in.orig 2008-12-10 10:27:02.000000000 -0600
++++ bacula-2.4.3/src/qt-console/bat.conf.in 2008-12-10 10:27:02.000000000 -0600
+@@ -6 +6 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -8 +8 @@
+- address = @hostname@
++ address = server.example.com
+--- bacula-2.4.3/src/stored/stored.conf.in.orig 2008-12-10 10:27:44.000000000 -0600
++++ bacula-2.4.3/src/stored/stored.conf.in 2008-12-10 10:27:44.000000000 -0600
+@@ -11 +11 @@
+- Address = @hostname@
++ Address = storage.example.com
+@@ -22 +22 @@
+- Name = @hostname@-dir
++ Name = bacula-dir
+@@ -54 +54 @@
+- director = @hostname@-dir = all
++ director = bacula-dir = all
diff --git a/main/bacula-client/bacula-fd-conf b/main/bacula-client/bacula-fd-conf
new file mode 100644
index 0000000000..033ef74b4b
--- /dev/null
+++ b/main/bacula-client/bacula-fd-conf
@@ -0,0 +1,4 @@
+# Config file for /etc/init.d/bacula-fd
+
+# Options for the file daemon.
+FD_OPTIONS="-u root -g bacula -c /etc/bacula/bacula-fd.conf"
diff --git a/main/bacula-client/bacula-fd-init b/main/bacula-client/bacula-fd-init
new file mode 100644
index 0000000000..618b3508c7
--- /dev/null
+++ b/main/bacula-client/bacula-fd-init
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/app-backup/bacula/files/3.0.3/bacula-fd-init,v 1.1 2009/11/08 17:14:46 wschlich Exp $
+
+depend() {
+ need net
+ use dns
+}
+
+start() {
+ ebegin "Starting bacula file daemon"
+ start-stop-daemon --start --quiet --exec /usr/sbin/bacula-fd \
+ -- ${FD_OPTIONS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping bacula file daemon"
+ start-stop-daemon --stop --quiet --pidfile /var/run/bacula-fd.*.pid
+ eend $?
+}
diff --git a/main/bacula-client/configure.in.patch b/main/bacula-client/configure.in.patch
new file mode 100644
index 0000000000..cfe2a0b7cf
--- /dev/null
+++ b/main/bacula-client/configure.in.patch
@@ -0,0 +1,23 @@
+--- bacula-3.0.3-orig/autoconf/configure.in Sun Oct 18 09:10:16 2009
++++ bacula-3.0.3/autoconf/configure.in Wed Dec 2 14:13:44 2009
+@@ -2576,6 +2576,20 @@
+ fi
+ TAPEDRIVE="/dev/nrmt0"
+ ;;
++alpine)
++ dnl Make sure hostname is resolved
++ ping -c 1 $hostname 2>&1 1>/dev/null
++ if test ! $? = 0; then
++ hostname="localhost"
++ fi
++ if `test -f /etc/alpine-release && grep -q alpine /etc/alpine-release`; then
++ DISTNAME="alpine"
++ fi
++ DISTVER=`cat /etc/alpine-release`
++ TAPEDRIVE="/dev/nst0"
++ PSCMD="ps -e -o pid,comm"
++ largefile_support="yes"
++ ;;
+ bsdi)
+ DISTVER=`uname -a |awk '{print $3}'`
+ TAPEDRIVE="/dev/nrmt0"
diff --git a/main/bacula-client/cxx.patch b/main/bacula-client/cxx.patch
new file mode 100644
index 0000000000..0af4937ea1
--- /dev/null
+++ b/main/bacula-client/cxx.patch
@@ -0,0 +1,13 @@
+--- ./autoconf/configure.in.orig
++++ ./autoconf/configure.in
+@@ -92,10 +92,6 @@
+ AC_DEFINE(HAVE_GCC)
+ have_gcc=yes
+ fi
+-AC_PATH_PROG(CXX, $CXX, $CXX)
+-if test ! -e $CXX; then
+- AC_MSG_ERROR(Unable to find C++ compiler)
+-fi
+
+ dnl -------------------------------------------------------
+ dnl Check for programs.
diff --git a/main/bacula-client/os.m4.patch b/main/bacula-client/os.m4.patch
new file mode 100644
index 0000000000..95dc5666ad
--- /dev/null
+++ b/main/bacula-client/os.m4.patch
@@ -0,0 +1,12 @@
+--- bacula-3.0.3-orig/autoconf/bacula-macros/os.m4 Sun Oct 18 09:10:16 2009
++++ bacula-3.0.3/autoconf/bacula-macros/os.m4 Wed Dec 2 13:48:30 2009
+@@ -201,6 +201,9 @@
+ elif test -f /etc/gentoo-release
+ then
+ DISTNAME=gentoo
++elif test -f /etc/alpine-release
++then
++ DISTNAME=alpine
+ elif test -f /etc/debian_version
+ then
+ DISTNAME=debian
diff --git a/main/bacula/APKBUILD b/main/bacula/APKBUILD
new file mode 100644
index 0000000000..8a35990750
--- /dev/null
+++ b/main/bacula/APKBUILD
@@ -0,0 +1,124 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname="bacula"
+pkgver=5.0.3
+pkgrel=8
+pkgdesc="Enterprise ready, network based backup program"
+url="http://www.bacula.org"
+arch="all"
+license="AGPL3"
+depends=""
+makedepends="autoconf ncurses-dev openssl-dev postgresql-dev zlib-dev"
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/project/$pkgname/$pkgname/$pkgver/$pkgname-$pkgver.tar.gz
+ bacula-dir-init
+ bacula-dir-conf
+ bacula-sd-init
+ bacula-sd-conf
+ bacula-fd-init
+ bacula-fd-conf
+
+ bacula-5.0.1-dsolink.patch
+ bacula-5.0.2-config.patch
+ bacula-5.0.2-openssl.patch
+ bacula-5.0.2-python27.patch
+ bacula-5.0.3-dsolink.patch
+ bacula-5.0.3-log-path.patch
+ bacula-5.0.3-mysql55.patch
+ bacula-5.0.3-sqlite-priv.patch
+ bacula-config.patch
+ configure.in.patch
+ bacula-5.0.3-Makefile.patch
+ bacula-5.0.3-as-needed.patch
+ os.m4.patch
+ cxx.patch"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare () {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ cd "$_builddir"/autoconf
+ autoconf && cp configure ../
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/bacula \
+ --localstatedir=/var \
+ --mandir=/usr/share/man \
+ --docdir=/usr/share/doc \
+ --infodir=/usr/share/info \
+ --with-pid-dir=/var/run \
+ --with-subsys-dir=/var/lock/subsys \
+ --with-logdir=/var/log \
+ --enable-largefile \
+ --enable-smartalloc \
+ --disable-nls \
+ --with-openssl=/usr/include/openssl \
+ --with-postgresql \
+ --with-scriptdir=/etc/bacula/scripts \
+ --with-working-dir=/var/bacula \
+ --with-dir-user=bacula \
+ --with-dir-group=bacula \
+ --with-sd-user=bacula \
+ --with-sd-group=bacula \
+ --with-fd-user=root \
+ --with-fd-group=root
+
+ make NO_ECHO= || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+
+ for DAEMON in dir sd fd
+ do
+ install -Dm755 "$srcdir"/bacula-${DAEMON}-init \
+ "$pkgdir"/etc/init.d/bacula-${DAEMON}
+ install -Dm644 "$srcdir"/bacula-${DAEMON}-conf \
+ "$pkgdir"/etc/conf.d/bacula-${DAEMON}
+ done
+ install -Dm644 examples/sample-query.sql \
+ "$pkgdir"/etc/bacula/scripts/query.sql
+ mkdir -p "$pkgdir"/var/run/bacula
+ # Fix correct log dir
+ sed -i -e 's%/var/bacula/log%/var/log/bacula%' \
+ "$pkgdir"/etc/bacula/bacula-dir.conf
+ # Install logrotate script
+ install -Dm644 scripts/logrotate $pkgdir/etc/logrotate.d/bacula
+ sed -i -e 's%/var/bacula/log%/var/log/bacula%' \
+ "$pkgdir"/etc/logrotate.d/bacula
+ # Use shell script for catalog backup instead of perl
+ sed -i -e 's/make_catalog_backup.pl/make_catalog_backup/' \
+ "$pkgdir"/etc/bacula/bacula-dir.conf
+}
+
+md5sums="9de254ae39cab0587fdb2f5d8d90b03b bacula-5.0.3.tar.gz
+b1b328013634c98119663730e3e2da7e bacula-dir-init
+20f28a16f34e3f20ed18ed81b010e765 bacula-dir-conf
+5ae1fba6860a320394d65744e5640bdb bacula-sd-init
+afe2f9a4d79d7d96eb9372d003d10f86 bacula-sd-conf
+6ae93e570f95fa845fa534c2d2efaac0 bacula-fd-init
+4500ce2d62bf9df33c07f70dc40f7b85 bacula-fd-conf
+eee101f1b7b6b4f2c140898db5f8123b bacula-5.0.1-dsolink.patch
+71f7f9c041eff045b2e97d141316c059 bacula-5.0.2-config.patch
+4e310e84c7aba5b8d043758e0fa0088f bacula-5.0.2-openssl.patch
+13e511698b5dc376e673c963a848d364 bacula-5.0.2-python27.patch
+82d3a5c113c633bf0bd86ac3590baaff bacula-5.0.3-dsolink.patch
+9bde1e9d43146af8985ff62d491d7218 bacula-5.0.3-log-path.patch
+def9da0c090141dcef817d80c1a29fd1 bacula-5.0.3-mysql55.patch
+9def0e68e3eb2f5f8b4c34108a248efd bacula-5.0.3-sqlite-priv.patch
+5d3c1bf25d50996e0c0c344dc2444014 bacula-config.patch
+ebc9c2bbc9be95c920723a3f142d8e19 configure.in.patch
+0ec20df57bb632ed729cfaf5d0a3ee33 bacula-5.0.3-Makefile.patch
+76267747f4d2e85e033cc6793ccb6afa bacula-5.0.3-as-needed.patch
+cf7a2a4e972697f54364654c4e282b8b os.m4.patch
+1bfdbfea7a36d5503753414dffb953eb cxx.patch"
diff --git a/main/bacula/bacula-5.0.1-dsolink.patch b/main/bacula/bacula-5.0.1-dsolink.patch
new file mode 100644
index 0000000000..1669cecb68
--- /dev/null
+++ b/main/bacula/bacula-5.0.1-dsolink.patch
@@ -0,0 +1,11 @@
+--- bacula-5.0.1/src/qt-console/bat.pro.in~ 2010-02-24 09:33:48.000000000 -0600
++++ bacula-5.0.1/src/qt-console/bat.pro.in 2010-03-11 17:12:44.645296544 -0600
+@@ -20,7 +20,7 @@
+ TARGET = bat
+ DEPENDPATH += .
+ INCLUDEPATH += .. . ./console ./restore ./select
+-LIBS += -L../lib -lbaccfg -lbac @OPENSSL_LIBS@
++LIBS += -L../lib -lbaccfg -lbac -ldl @OPENSSL_LIBS@
+ LIBTOOL_LINK = @QMAKE_LIBTOOL@ --silent --tag=CXX --mode=link
+ LIBTOOL_INSTALL = @QMAKE_LIBTOOL@ --silent --mode=install
+ QMAKE_LINK = $${LIBTOOL_LINK} $(CXX)
diff --git a/main/bacula/bacula-5.0.2-config.patch b/main/bacula/bacula-5.0.2-config.patch
new file mode 100644
index 0000000000..f78c665b70
--- /dev/null
+++ b/main/bacula/bacula-5.0.2-config.patch
@@ -0,0 +1,12 @@
+diff -up bacula-5.0.2/bacula-5.0.2/src/dird/bacula-dir.conf.in.config bacula-5.0.2/bacula-5.0.2/src/dird/bacula-dir.conf.in
+--- bacula-5.0.2/src/dird/bacula-dir.conf.in.config 2010-06-03 11:05:07.000000000 +0200
++++ bacula-5.0.2/src/dird/bacula-dir.conf.in 2010-06-03 11:28:26.556782993 +0200
+@@ -15,7 +15,7 @@
+ Director { # define myself
+ Name = bacula-dir
+ DIRport = @dir_port@ # where we listen for UA connections
+- QueryFile = "@scriptdir@/query.sql"
++ QueryFile = "/etc/bacula/query.sql"
+ WorkingDirectory = "@working_dir@"
+ PidDirectory = "@piddir@"
+ Maximum Concurrent Jobs = 1
diff --git a/main/bacula/bacula-5.0.2-openssl.patch b/main/bacula/bacula-5.0.2-openssl.patch
new file mode 100644
index 0000000000..a71d8d5467
--- /dev/null
+++ b/main/bacula/bacula-5.0.2-openssl.patch
@@ -0,0 +1,24 @@
+diff -up bacula-5.0.2/src/lib/crypto.c.openssl bacula-5.0.2/bacula-5.0.2/src/lib/crypto.c
+--- bacula-5.0.2/src/lib/crypto.c.openssl 2010-04-27 21:58:29.000000000 +0200
++++ bacula-5.0.2/src/lib/crypto.c 2010-06-01 17:51:52.846894465 +0200
+@@ -51,7 +51,7 @@
+ * For OpenSSL version 1.x, EVP_PKEY_encrypt no longer
+ * exists. It was not an official API.
+ */
+-#ifdef HAVE_OPENSSLv1
++#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
+ #define EVP_PKEY_encrypt EVP_PKEY_encrypt_old
+ #define EVP_PKEY_decrypt EVP_PKEY_decrypt_old
+ #endif
+diff -up bacula-5.0.2/bacula-5.0.2/src/lib/tls.c.openssl bacula-5.0.2/bacula-5.0.2/src/lib/tls.c
+--- bacula-5.0.2/src/lib/tls.c.openssl 2010-04-27 21:58:29.000000000 +0200
++++ bacula-5.0.2/src/lib/tls.c 2010-06-01 17:52:15.535769446 +0200
+@@ -315,7 +315,7 @@ bool tls_postconnect_verify_host(JCR *jc
+ extname = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
+
+ if (strcmp(extname, "subjectAltName") == 0) {
+-#ifdef HAVE_OPENSSLv1
++#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
+ const X509V3_EXT_METHOD *method;
+ #else
+ X509V3_EXT_METHOD *method;
diff --git a/main/bacula/bacula-5.0.2-python27.patch b/main/bacula/bacula-5.0.2-python27.patch
new file mode 100644
index 0000000000..36543872e8
--- /dev/null
+++ b/main/bacula/bacula-5.0.2-python27.patch
@@ -0,0 +1,22 @@
+--- ./configure~ 2010-04-27 14:58:29.000000000 -0500
++++ ./configure 2010-07-30 11:28:47.494178663 -0500
+@@ -26255,7 +26255,7 @@
+ PYTHON_LIBS=`/usr/bin/python-config --libs`
+ else
+ for python_root in /usr /usr/local /usr/sfw; do
+- for ver in python2.2 python2.3 python2.4 python2.5 python2.6 python3; do
++ for ver in python2.2 python2.3 python2.4 python2.5 python2.6 python2.7 python3; do
+ if test -f $python_root/include/${ver}/Python.h; then
+ PYTHON_INCDIR=-I$python_root/include/${ver}
+ if test -d $python_root/lib64/${ver}/config; then
+--- ./autoconf/configure.in~ 2010-04-27 14:58:29.000000000 -0500
++++ ./autoconf/configure.in 2010-07-30 11:30:22.837182092 -0500
+@@ -963,7 +963,7 @@
+ PYTHON_LIBS=`/usr/bin/python-config --libs`
+ else
+ for python_root in /usr /usr/local /usr/sfw; do
+- for ver in python2.2 python2.3 python2.4 python2.5 python2.6 python3; do
++ for ver in python2.2 python2.3 python2.4 python2.5 python2.6 python2.7 python3; do
+ if test -f $python_root/include/${ver}/Python.h; then
+ PYTHON_INCDIR=-I$python_root/include/${ver}
+ if test -d $python_root/lib64/${ver}/config; then
diff --git a/main/bacula/bacula-5.0.3-Makefile.patch b/main/bacula/bacula-5.0.3-Makefile.patch
new file mode 100644
index 0000000000..a3f32729d7
--- /dev/null
+++ b/main/bacula/bacula-5.0.3-Makefile.patch
@@ -0,0 +1,26 @@
+--- ./Makefile.in.orig 2010-07-20 16:53:44.000000000 +0000
++++ ./Makefile.in 2010-07-20 16:55:50.000000000 +0000
+@@ -44,9 +44,8 @@
+
+ all: Makefile
+ @for I in ${all_subdirs}; \
+- do (cd $$I; echo "==>Entering directory `pwd`"; \
+- $(MAKE) DESTDIR=$(DESTDIR) $@ || (echo ""; echo ""; echo " ====== Error in `pwd` ======"; \
+- echo ""; echo ""; exit 1;)); \
++ do \
++ $(MAKE) DESTDIR=$(DESTDIR) -C $$I $@ || exit 1; \
+ done
+
+ depend:
+@@ -55,9 +54,8 @@
+
+ bacula-fd: Makefile
+ @for I in ${fd_subdirs}; \
+- do (cd $$I; echo "==>Entering directory `pwd`"; \
+- $(MAKE) DESTDIR=$(DESTDIR) all || (echo ""; echo ""; echo " ====== Error in `pwd` ======"; \
+- echo ""; echo ""; exit 1;)); \
++ do \
++ $(MAKE) DESTDIR=$(DESTDIR) -C $$I all || exit 1; \
+ done
+
+ #-------------------------------------------------------------------------
diff --git a/main/bacula/bacula-5.0.3-as-needed.patch b/main/bacula/bacula-5.0.3-as-needed.patch
new file mode 100644
index 0000000000..3603e936bb
--- /dev/null
+++ b/main/bacula/bacula-5.0.3-as-needed.patch
@@ -0,0 +1,33 @@
+diff -urN bacula-5.0.3.orig/src/findlib/Makefile.in bacula-5.0.3/src/findlib/Makefile.in
+--- bacula-5.0.3.orig/src/findlib/Makefile.in 2010-02-24 16:33:48.000000000 +0100
++++ bacula-5.0.3/src/findlib/Makefile.in 2010-03-22 17:37:43.772805754 +0100
+@@ -59,7 +59,7 @@
+
+ libbacfind.la: Makefile $(LIBBACFIND_LOBJS)
+ @echo "Making $@ ..."
+- $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACFIND_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACFIND_LT_RELEASE)
++ $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACFIND_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACFIND_LT_RELEASE) -L../lib -lbac $(LIBS) $(OPENSSL_LIBS)
+
+ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
+ cd $(topdir) \
+diff -urN bacula-5.0.1.orig/src/lib/Makefile.in bacula-5.0.1/src/lib/Makefile.in
+--- bacula-5.0.1.orig/src/lib/Makefile.in 2010-02-24 16:33:48.000000000 +0100
++++ bacula-5.0.1/src/lib/Makefile.in 2010-03-22 17:37:05.352226188 +0100
+@@ -126,7 +126,7 @@
+
+ libbac.la: Makefile $(LIBBAC_LOBJS)
+ @echo "Making $@ ..."
+- $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBAC_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBAC_LT_RELEASE) $(WRAPLIBS) $(CAP_LIBS) $(ZLIBS)
++ $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBAC_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBAC_LT_RELEASE) $(WRAPLIBS) $(CAP_LIBS) $(ZLIBS) $(LIBS) $(OPENSSL_LIBS)
+
+ libbaccfg.a: $(LIBBACCFG_OBJS)
+ @echo "Making $@ ..."
+@@ -135,7 +135,7 @@
+
+ libbaccfg.la: Makefile $(LIBBACCFG_LOBJS)
+ @echo "Making $@ ..."
+- $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACCFG_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACCFG_LT_RELEASE)
++ $(LIBTOOL_LINK) $(CXX) $(DEFS) $(DEBUG) $(LDFLAGS) -o $@ $(LIBBACCFG_LOBJS) -export-dynamic -rpath $(libdir) -release $(LIBBACCFG_LT_RELEASE) $(LIBS) $(OPENSSL_LIBS)
+
+ libbacpy.a: $(LIBBACPY_OBJS)
+ @echo "Making $@ ..."
diff --git a/main/bacula/bacula-5.0.3-dsolink.patch b/main/bacula/bacula-5.0.3-dsolink.patch
new file mode 100644
index 0000000000..44309dad86
--- /dev/null
+++ b/main/bacula/bacula-5.0.3-dsolink.patch
@@ -0,0 +1,165 @@
+--- bacula-5.0.3/src/qt-console/bat.pro.in~ 2010-08-10 11:27:17.000000000 -0500
++++ bacula-5.0.3/src/qt-console/bat.pro.in 2010-08-10 12:32:00.312182153 -0500
+@@ -20,7 +20,7 @@
+ TARGET = bat
+ DEPENDPATH += .
+ INCLUDEPATH += .. . ./console ./restore ./select
+-LIBS += -L../lib -lbaccfg -lbac -ldl @OPENSSL_LIBS@
++LIBS += -L../lib -lbaccfg -lbac -ldl -lz @OPENSSL_LIBS@
+ LIBTOOL_LINK = @QMAKE_LIBTOOL@ --silent --tag=CXX --mode=link
+ LIBTOOL_INSTALL = @QMAKE_LIBTOOL@ --silent --mode=install
+ QMAKE_LINK = $${LIBTOOL_LINK} $(CXX)
+--- bacula-5.0.3/src/tools/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/tools/Makefile.in 2010-08-11 12:54:02.028450916 -0500
+@@ -57,7 +57,7 @@
+ @echo " "
+
+ bsmtp: Makefile bsmtp.o ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+- $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -o $@ bsmtp.o -lbac -lm $(DLIB) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -o $@ bsmtp.o -lbac -lm -lz $(DLIB) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bregtest: Makefile bregtest.o ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -o $@ bregtest.o -lbac -lm $(DLIB) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+--- bacula-5.0.3/src/tools/Makefile.in~ 2010-08-11 12:57:29.000000000 -0500
++++ bacula-5.0.3/src/tools/Makefile.in 2010-08-11 14:10:52.998447849 -0500
+@@ -64,7 +64,7 @@
+
+ dbcheck: Makefile dbcheck.o ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE) $(DIRCONFOBJS)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ dbcheck.o $(DIRCONFOBJS) \
+- -lbacsql -lbaccfg -lbac -lm $(DB_LIBS) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacsql -lbaccfg -lbac -lm -lz $(DB_LIBS) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ fstype: Makefile fstype.o ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L../lib -L../findlib -o $@ fstype.o -lbacfind -lbac -lm \
+--- bacula-5.0.3/src/tools/Makefile.in~ 2010-08-11 14:13:51.000000000 -0500
++++ bacula-5.0.3/src/tools/Makefile.in 2010-08-11 15:11:00.309447155 -0500
+@@ -97,7 +97,7 @@
+
+ bwild: Makefile ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) bwild.o
+ $(LIBTOOL_LINK) $(CXX) -g $(LDFLAGS) -L. -L../lib -o $@ bwild.o \
+- $(DLIB) -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ $(DLIB) -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bbatch: Makefile ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE) bbatch.o
+ $(LIBTOOL_LINK) $(CXX) -g $(LDFLAGS) -L../cats -L. -L../lib -o $@ bbatch.o \
+--- bacula-5.0.3/src/tools/Makefile.in~ 2010-08-12 06:57:25.000000000 -0500
++++ bacula-5.0.3/src/tools/Makefile.in 2010-08-12 07:58:13.545781384 -0500
+@@ -93,7 +93,7 @@
+
+ bregex: Makefile ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) bregex.o
+ $(LIBTOOL_LINK) $(CXX) -g $(LDFLAGS) -L. -L../lib -o $@ bregex.o \
+- $(DLIB) -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ $(DLIB) -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bwild: Makefile ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) bwild.o
+ $(LIBTOOL_LINK) $(CXX) -g $(LDFLAGS) -L. -L../lib -o $@ bwild.o \
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 08:56:11.053777811 -0500
+@@ -91,7 +91,7 @@
+ bacula-sd: Makefile $(SDOBJS) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ @echo "Linking $@ ..."
+ $(LIBTOOL_LINK) $(CXX) $(WLDFLAGS) $(LDFLAGS) -L../lib -o $@ $(SDOBJS) $(FDLIBS) \
+- -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(DLIB) $(LIBS) $(WRAPLIBS) \
++ -lbacpy -lbaccfg -lbac -lm -lz $(PYTHON_LIBS) $(DLIB) $(LIBS) $(WRAPLIBS) \
+ $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS)
+
+ static-bacula-sd: Makefile $(SDOBJS) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-12 08:59:17.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 10:24:42.478529732 -0500
+@@ -117,7 +117,7 @@
+ bls: Makefile $(BLSOBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ @echo "Compiling $<"
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BLSOBJS) $(DLIB) \
+- -lbacfind -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacfind -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bextract.o: bextract.c
+ @echo "Compiling $<"
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-12 10:27:36.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 11:45:39.904529074 -0500
+@@ -127,7 +127,7 @@
+ bextract: Makefile $(BEXTOBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ @echo "Compiling $<"
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BEXTOBJS) $(DLIB) $(FDLIBS) \
+- -lbacfind -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacfind -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bscan.o: bscan.c
+ @echo "Compiling $<"
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-12 11:48:22.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 13:21:02.246528324 -0500
+@@ -136,7 +136,7 @@
+
+ bscan: Makefile $(SCNOBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SCNOBJS) \
+- -lbacsql $(DB_LIBS) $(FDLIBS) -lbacfind -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacsql $(DB_LIBS) $(FDLIBS) -lbacfind -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bcopy.o: bcopy.c
+ @echo "Compiling $<"
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-12 13:23:58.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-12 14:31:11.204777284 -0500
+@@ -107,7 +107,7 @@
+
+ btape: Makefile $(TAPEOBJS) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../cats -o $@ $(TAPEOBJS) \
+- -lbacsql -lbaccfg -lbac $(DLIB) -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbacsql -lbaccfg -lbac $(DLIB) -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ bls.o: bls.c
+ @echo "Compiling $<"
+--- bacula-5.0.3/src/stored/Makefile.in~ 2010-08-13 07:02:47.000000000 -0500
++++ bacula-5.0.3/src/stored/Makefile.in 2010-08-13 08:25:50.830920608 -0500
+@@ -145,7 +145,7 @@
+
+ bcopy: Makefile $(COPYOBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -o $@ $(COPYOBJS) \
+- -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
++ -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
+ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
+ cd $(topdir) \
+--- bacula-5.0.3/src/dird/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/dird/Makefile.in 2010-08-13 09:25:38.855168511 -0500
+@@ -64,7 +64,7 @@
+ bacula-dir: Makefile $(SVROBJS) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE)
+ @echo "Linking $@ ..."
+ $(LIBTOOL_LINK) $(CXX) $(WLDFLAGS) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SVROBJS) \
+- -lbacfind -lbacsql -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(DLIB) $(DB_LIBS) $(LIBS) \
++ -lbacfind -lbacsql -lbacpy -lbaccfg -lbac -lm -lz $(PYTHON_LIBS) $(DLIB) $(DB_LIBS) $(LIBS) \
+ $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS)
+
+ static-bacula-dir: Makefile $(SVROBJS) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../cats/libbacsql$(DEFAULT_ARCHIVE_TYPE) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE)
+--- bacula-5.0.3/src/console/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/console/Makefile.in 2010-08-13 10:26:18.001169569 -0500
+@@ -48,7 +48,7 @@
+
+ bconsole: Makefile $(CONSOBJS) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) $(CONS_LDFLAGS) -L../lib -L../cats -o $@ $(CONSOBJS) \
+- $(DLIB) $(CONS_LIBS) -lbaccfg -lbac -lm $(LIBS) $(GETTEXT_LIBS) \
++ $(DLIB) $(CONS_LIBS) -lbaccfg -lbac -lm -lz $(LIBS) $(GETTEXT_LIBS) \
+ $(OPENSSL_LIBS)
+
+ static-bconsole: Makefile $(CONSOBJS) ../lib/libbac.a ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE)
+--- bacula-5.0.3/src/wx-console/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/wx-console/Makefile.in 2010-08-13 11:28:43.829917394 -0500
+@@ -83,7 +83,7 @@
+
+ bwx-console: Makefile $(CONSOBJS) @WIN32@ ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(CONSOBJS) $(WIN32RES) -o $@ -L../lib $(CONS_LDFLAGS) \
+- -lbaccfg -lbac $(LIBS) $(OPENSSL_LIBS)
++ -lbaccfg -lbac -lz $(LIBS) $(OPENSSL_LIBS)
+
+ win32: bwx-console_private.res
+
+--- bacula-5.0.3/src/tray-monitor/Makefile.in~ 2010-08-05 09:29:51.000000000 -0500
++++ bacula-5.0.3/src/tray-monitor/Makefile.in 2010-08-13 12:34:18.573918720 -0500
+@@ -45,7 +45,7 @@
+
+ bacula-tray-monitor: Makefile $(MONITOROBJS) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE)
+ $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) $(MONITOR_LDFLAGS) -L../lib -o $@ \
+- $(MONITOROBJS) $(DLIB) -lbaccfg -lbac -lm $(LIBS) $(OPENSSL_LIBS)
++ $(MONITOROBJS) $(DLIB) -lbaccfg -lbac -lm -lz $(LIBS) $(OPENSSL_LIBS)
+
+ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
+ cd $(topdir) \
diff --git a/main/bacula/bacula-5.0.3-log-path.patch b/main/bacula/bacula-5.0.3-log-path.patch
new file mode 100644
index 0000000000..15a2fecb5e
--- /dev/null
+++ b/main/bacula/bacula-5.0.3-log-path.patch
@@ -0,0 +1,13 @@
+diff --git bacula-5.0.3/src/dird/bacula-dir.conf.in b/bacula-5.0.3/src/dird/bacula-dir.conf.in
+index 922be44..54cca3f 100644
+--- bacula-5.0.3/src/dird/bacula-dir.conf.in
++++ bacula-5.0.3/src/dird/bacula-dir.conf.in
+@@ -273,7 +273,7 @@ Messages {
+ mailcommand = "@sbindir@/bsmtp -h @smtp_host@ -f \"\(Bacula\) \<%r\>\" -s \"Bacula daemon message\" %r"
+ mail = @job_email@ = all, !skipped
+ console = all, !skipped, !saved
+- append = "@working_dir@/log" = all, !skipped
++ append = "/var/log/bacula/bacula.log" = all, !skipped
+ }
+
+ # Default pool definition
diff --git a/main/bacula/bacula-5.0.3-mysql55.patch b/main/bacula/bacula-5.0.3-mysql55.patch
new file mode 100644
index 0000000000..910ea02302
--- /dev/null
+++ b/main/bacula/bacula-5.0.3-mysql55.patch
@@ -0,0 +1,11 @@
+--- ./src/cats/mysql.c~ 2010-08-05 09:29:51.000000000 -0500
++++ ./src/cats/mysql.c 2011-01-06 11:28:59.907306001 -0600
+@@ -292,7 +292,7 @@
+ void db_thread_cleanup()
+ {
+ #ifndef HAVE_WIN32
+- my_thread_end();
++ mysql_thread_end();
+ #endif
+ }
+
diff --git a/main/bacula/bacula-5.0.3-sqlite-priv.patch b/main/bacula/bacula-5.0.3-sqlite-priv.patch
new file mode 100644
index 0000000000..2738349fcd
--- /dev/null
+++ b/main/bacula/bacula-5.0.3-sqlite-priv.patch
@@ -0,0 +1,9 @@
+diff -up src/cats/make_sqlite3_tables.in~ src/cats/make_sqlite3_tables.in
+--- ./src/cats/make_sqlite3_tables.in~ 2010-11-16 17:57:12.705837000 +0100
++++ ./src/cats/make_sqlite3_tables.in 2010-11-16 17:57:12.715837000 +0100
+@@ -426,4 +426,5 @@ PRAGMA synchronous = NORMAL;
+ END-OF-DATA
+
+ chmod 640 ${db_name}.db
++chown bacula:bacula ${db_name}.db
+ exit 0
diff --git a/main/bacula/bacula-config.patch b/main/bacula/bacula-config.patch
new file mode 100644
index 0000000000..b6ab5037b4
--- /dev/null
+++ b/main/bacula/bacula-config.patch
@@ -0,0 +1,115 @@
+--- bacula-2.4.3/src/dird/bacula-dir.conf.in.orig 2008-12-10 10:17:27.000000000 -0600
++++ bacula-2.4.3/src/dird/bacula-dir.conf.in 2008-12-10 10:17:27.000000000 -0600
+@@ -16 +16 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -30 +30 @@
+- Client = @basename@-fd
++ Client = bacula-fd
+@@ -51 +51 @@
+-# Client = @basename@2-fd
++# Client = bacula2-fd
+@@ -82 +82 @@
+- Client=@basename@-fd
++ Client=bacula-fd
+@@ -157,2 +157,2 @@
+- Name = @basename@-fd
+- Address = @hostname@
++ Name = bacula-fd
++ Address = client.example.com
+@@ -172,2 +172,2 @@
+-# Name = @basename@2-fd
+-# Address = @hostname@2
++# Name = bacula2-fd
++# Address = client2.example.com
+@@ -187 +187 @@
+- Address = @hostname@ # N.B. Use a fully qualified name here
++ Address = storage.example.com # N.B. Use a fully qualified name here
+@@ -200 +200 @@
+-# Address = @hostname@ # N.B. Use a fully qualified name here
++# Address = storage.example.com # N.B. Use a fully qualified name here
+@@ -212 +212 @@
+-# Address = @hostname@ # N.B. Use a fully qualified name here
++# Address = storage.example.com # N.B. Use a fully qualified name here
+@@ -223 +223 @@
+-# Address = @hostname@ # N.B. Use a fully qualified name here
++# Address = storage.example.com # N.B. Use a fully qualified name here
+@@ -299 +299 @@
+- Name = @basename@-mon
++ Name = bacula-mon
+--- bacula-2.4.3/src/filed/bacula-fd.conf.in.orig 2008-12-10 10:19:12.000000000 -0600
++++ bacula-2.4.3/src/filed/bacula-fd.conf.in 2008-12-10 10:19:12.000000000 -0600
+@@ -14 +14 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -23 +23 @@
+- Name = @basename@-mon
++ Name = bacula-mon
+@@ -32 +32 @@
+- Name = @basename@-fd
++ Name = bacula-fd
+@@ -42 +42 @@
+- director = @basename@-dir = all, !skipped, !restored
++ director = bacula-dir = all, !skipped, !restored
+--- bacula-2.4.3/src/stored/bacula-sd.conf.in.orig 2008-12-10 10:21:45.000000000 -0600
++++ bacula-2.4.3/src/stored/bacula-sd.conf.in 2008-12-10 10:21:45.000000000 -0600
+@@ -14 +14 @@
+- Name = @basename@-sd
++ Name = bacula-sd
+@@ -25 +25 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -34 +34 @@
+- Name = @basename@-mon
++ Name = bacula-mon
+@@ -228 +228 @@
+- director = @basename@-dir = all
++ director = bacula-dir = all
+--- bacula-2.4.3/src/wx-console/bwx-console.conf.in.orig 2008-12-10 10:22:23.000000000 -0600
++++ bacula-2.4.3/src/wx-console/bwx-console.conf.in 2008-12-10 10:22:23.000000000 -0600
+@@ -6 +6 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -8 +8 @@
+- address = @hostname@
++ address = server.example.com
+--- bacula-2.4.3/src/tray-monitor/tray-monitor.conf.in.orig 2008-12-10 10:28:02.000000000 -0600
++++ bacula-2.4.3/src/tray-monitor/tray-monitor.conf.in 2008-12-10 10:28:02.000000000 -0600
+@@ -6 +6 @@
+- Name = @basename@-mon
++ Name = bacula-mon
+@@ -12,2 +12,2 @@
+- Name = @basename@-fd
+- Address = @hostname@
++ Name = bacula-fd
++ Address = client.example.com
+@@ -19,2 +19,2 @@
+- Name = @basename@-sd
+- Address = @hostname@
++ Name = bacula-sd
++ Address = storage.example.com
+@@ -26 +26 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -28 +28 @@
+- address = @hostname@
++ Address = director.example.com
+--- bacula-2.4.3/src/qt-console/bat.conf.in.orig 2008-12-10 10:27:02.000000000 -0600
++++ bacula-2.4.3/src/qt-console/bat.conf.in 2008-12-10 10:27:02.000000000 -0600
+@@ -6 +6 @@
+- Name = @basename@-dir
++ Name = bacula-dir
+@@ -8 +8 @@
+- address = @hostname@
++ address = server.example.com
+--- bacula-2.4.3/src/stored/stored.conf.in.orig 2008-12-10 10:27:44.000000000 -0600
++++ bacula-2.4.3/src/stored/stored.conf.in 2008-12-10 10:27:44.000000000 -0600
+@@ -11 +11 @@
+- Address = @hostname@
++ Address = storage.example.com
+@@ -22 +22 @@
+- Name = @hostname@-dir
++ Name = bacula-dir
+@@ -54 +54 @@
+- director = @hostname@-dir = all
++ director = bacula-dir = all
diff --git a/main/bacula/bacula-dir-conf b/main/bacula/bacula-dir-conf
new file mode 100644
index 0000000000..17a56161f0
--- /dev/null
+++ b/main/bacula/bacula-dir-conf
@@ -0,0 +1,7 @@
+# Config file for /etc/init.d/bacula-dir
+
+# Options for the director daemon.
+# The DIR can be run as a non-root user, however
+# please ensure that this user has proper permissions to
+# access your backup devices.
+DIR_OPTIONS="-u bacula -g bacula -c /etc/bacula/bacula-dir.conf"
diff --git a/main/bacula/bacula-dir-init b/main/bacula/bacula-dir-init
new file mode 100644
index 0000000000..033d72f9a0
--- /dev/null
+++ b/main/bacula/bacula-dir-init
@@ -0,0 +1,23 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/app-backup/bacula/files/3.0.3/bacula-dir-init,v 1.1 2009/11/08 17:14:46 wschlich Exp $
+
+depend() {
+ need net postgresql
+ after firewall
+ use dns bacula-fd bacula-sd
+}
+
+start() {
+ ebegin "Starting bacula director"
+ start-stop-daemon --start --quiet --exec /usr/sbin/bacula-dir \
+ -- ${DIR_OPTIONS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping bacula director"
+ start-stop-daemon --stop --quiet --pidfile /var/run/bacula/bacula-dir.*.pid
+ eend $?
+}
diff --git a/main/bacula/bacula-fd-conf b/main/bacula/bacula-fd-conf
new file mode 100644
index 0000000000..033ef74b4b
--- /dev/null
+++ b/main/bacula/bacula-fd-conf
@@ -0,0 +1,4 @@
+# Config file for /etc/init.d/bacula-fd
+
+# Options for the file daemon.
+FD_OPTIONS="-u root -g bacula -c /etc/bacula/bacula-fd.conf"
diff --git a/main/bacula/bacula-fd-init b/main/bacula/bacula-fd-init
new file mode 100644
index 0000000000..1e36a19479
--- /dev/null
+++ b/main/bacula/bacula-fd-init
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/app-backup/bacula/files/3.0.3/bacula-fd-init,v 1.1 2009/11/08 17:14:46 wschlich Exp $
+
+depend() {
+ need net
+ use dns
+}
+
+start() {
+ ebegin "Starting bacula file daemon"
+ start-stop-daemon --start --quiet --exec /usr/sbin/bacula-fd \
+ -- ${FD_OPTIONS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping bacula file daemon"
+ start-stop-daemon --stop --quiet --pidfile /var/run/bacula/bacula-fd.*.pid
+ eend $?
+}
diff --git a/main/bacula/bacula-sd-conf b/main/bacula/bacula-sd-conf
new file mode 100644
index 0000000000..88e13aa0eb
--- /dev/null
+++ b/main/bacula/bacula-sd-conf
@@ -0,0 +1,7 @@
+# Config file for /etc/init.d/bacula-sd
+
+# Options for the storage daemon.
+# The SD can be run as a non-root user, however
+# please ensure that this user has proper permissions to
+# access your backup devices.
+SD_OPTIONS="-u bacula -g bacula -c /etc/bacula/bacula-sd.conf"
diff --git a/main/bacula/bacula-sd-init b/main/bacula/bacula-sd-init
new file mode 100644
index 0000000000..2375b8e457
--- /dev/null
+++ b/main/bacula/bacula-sd-init
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/app-backup/bacula/files/3.0.3/bacula-sd-init,v 1.1 2009/11/08 17:14:46 wschlich Exp $
+
+depend() {
+ need net
+ use dns
+}
+
+start() {
+ ebegin "Starting bacula storage daemon"
+ start-stop-daemon --start --quiet --exec /usr/sbin/bacula-sd \
+ -- ${SD_OPTIONS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping bacula storage daemon"
+ start-stop-daemon --stop --quiet --pidfile /var/run/bacula/bacula-sd.*.pid
+ eend $?
+}
diff --git a/main/bacula/bacula.post-install b/main/bacula/bacula.post-install
new file mode 100644
index 0000000000..caeda8993f
--- /dev/null
+++ b/main/bacula/bacula.post-install
@@ -0,0 +1,11 @@
+#!/bin/sh
+mkdir /var/lib/bacula /var/log/bacula &>/dev/null
+for dir in /var/bacula /var/log/bacula /var/run/bacula /var/lib/bacula /etc/bacula/scripts/make_catalog_backup* /etc/bacula/scripts/mtx-changer*
+do
+ chown bacula.bacula $dir
+done
+
+for file in create_postgresql_database make_postgresql_tables grant_postgresql_privileges
+do
+ chown postgres /etc/bacula/scripts/$file
+done
diff --git a/main/bacula/bacula.pre-install b/main/bacula/bacula.pre-install
new file mode 100644
index 0000000000..1eba271914
--- /dev/null
+++ b/main/bacula/bacula.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+addgroup -S bacula 2>/dev/null
+adduser -h /var/lib/bacula/ -s /bin/false -G bacula -S -D bacula 2>/dev/null
+exit 0
diff --git a/main/bacula/configure.in.patch b/main/bacula/configure.in.patch
new file mode 100644
index 0000000000..cfe2a0b7cf
--- /dev/null
+++ b/main/bacula/configure.in.patch
@@ -0,0 +1,23 @@
+--- bacula-3.0.3-orig/autoconf/configure.in Sun Oct 18 09:10:16 2009
++++ bacula-3.0.3/autoconf/configure.in Wed Dec 2 14:13:44 2009
+@@ -2576,6 +2576,20 @@
+ fi
+ TAPEDRIVE="/dev/nrmt0"
+ ;;
++alpine)
++ dnl Make sure hostname is resolved
++ ping -c 1 $hostname 2>&1 1>/dev/null
++ if test ! $? = 0; then
++ hostname="localhost"
++ fi
++ if `test -f /etc/alpine-release && grep -q alpine /etc/alpine-release`; then
++ DISTNAME="alpine"
++ fi
++ DISTVER=`cat /etc/alpine-release`
++ TAPEDRIVE="/dev/nst0"
++ PSCMD="ps -e -o pid,comm"
++ largefile_support="yes"
++ ;;
+ bsdi)
+ DISTVER=`uname -a |awk '{print $3}'`
+ TAPEDRIVE="/dev/nrmt0"
diff --git a/main/bacula/cxx.patch b/main/bacula/cxx.patch
new file mode 100644
index 0000000000..0af4937ea1
--- /dev/null
+++ b/main/bacula/cxx.patch
@@ -0,0 +1,13 @@
+--- ./autoconf/configure.in.orig
++++ ./autoconf/configure.in
+@@ -92,10 +92,6 @@
+ AC_DEFINE(HAVE_GCC)
+ have_gcc=yes
+ fi
+-AC_PATH_PROG(CXX, $CXX, $CXX)
+-if test ! -e $CXX; then
+- AC_MSG_ERROR(Unable to find C++ compiler)
+-fi
+
+ dnl -------------------------------------------------------
+ dnl Check for programs.
diff --git a/main/bacula/os.m4.patch b/main/bacula/os.m4.patch
new file mode 100644
index 0000000000..95dc5666ad
--- /dev/null
+++ b/main/bacula/os.m4.patch
@@ -0,0 +1,12 @@
+--- bacula-3.0.3-orig/autoconf/bacula-macros/os.m4 Sun Oct 18 09:10:16 2009
++++ bacula-3.0.3/autoconf/bacula-macros/os.m4 Wed Dec 2 13:48:30 2009
+@@ -201,6 +201,9 @@
+ elif test -f /etc/gentoo-release
+ then
+ DISTNAME=gentoo
++elif test -f /etc/alpine-release
++then
++ DISTNAME=alpine
+ elif test -f /etc/debian_version
+ then
+ DISTNAME=debian
diff --git a/main/bash/APKBUILD b/main/bash/APKBUILD
new file mode 100644
index 0000000000..9e74d229da
--- /dev/null
+++ b/main/bash/APKBUILD
@@ -0,0 +1,80 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+pkgname=bash
+pkgver=4.2.010
+_patchlevel=${pkgver##*.}
+_myver=${pkgver%.*}
+_patchbase=${_myver%.*}${_myver#*.}
+pkgrel=0
+pkgdesc="The GNU Bourne Again shell"
+arch="all"
+license='GPL'
+url="http://www.gnu.org/software/bash/bash.html"
+makedepends="readline-dev ncurses-dev bison flex"
+depends=
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/gnu/bash/bash-${_myver}.tar.gz
+ bash-noinfo.patch
+ "
+# generate url's to patches. note: no forks allowed!
+_i=1
+_pad="00"
+while [ $_i -le $_patchlevel ]; do
+ [ $_i -ge 10 ] && _pad="0"
+ [ $_i -ge 100 ] && _pad=
+ source="$source http://ftp.gnu.org/gnu/bash/bash-$_myver-patches/bash$_patchbase-$_pad$_i"
+ _i=$(( $_i + 1))
+done
+
+# run 'abuild _gensrc >> APKBUILD' to generate the patch list
+#_gensrc() {
+# for _i in $(seq 1 $_patchlevel); do
+# # seq -w unsupported by busybox
+# _p=$(printf "%0.3i" $_i)
+# echo -e "\thttp://ftp.gnu.org/gnu/bash/bash-${_myver}-patches/bash${_patchbase}-$_p"
+# done
+#}
+
+_builddir="$srcdir"/$pkgname-$_myver
+prepare() {
+ local p
+ cd "$_builddir"
+ for p in ../bash${_patchbase}-??? ../*.patch; do
+ msg "applying patch ${p##*/}"
+ patch -p0 -i $p || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-curses \
+ --disable-nls \
+ --enable-readline \
+ --without-bash-malloc \
+ --with-installed-readline \
+ --bindir=/bin \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ || return 1
+ make y.tab.c && make || return 1
+}
+
+package() {
+ cd ${startdir}/src/${pkgname}-${_myver}
+ make DESTDIR=${pkgdir} install
+
+ rm -rf "$pkgdir"/usr/share/locale
+}
+md5sums="3fb927c7c33022f1c327f14a81c0d4b0 bash-4.2.tar.gz
+80fec5f3d60a63756a4999c877e31a8e bash-noinfo.patch
+1100bc1dda2cdc06ac44d7e5d17864a3 bash42-001
+30e7948079921d3261efcc6a40722135 bash42-002
+9ea06decec43a198f3d7cf29acc602f8 bash42-003
+fb48f6134d7b013135929476aa0c250c bash42-004
+e70e45de33426b38153b390be0dbbcd4 bash42-005
+ce4e5c484993705b27daa151eca242c2 bash42-006
+88d1f96db29461767602e2546803bda7 bash42-007
+24c574bf6d6a581e300823d9c1276af6 bash42-008
+4c5835f2fbab36c4292bb334977e5b6d bash42-009
+0a51602b535ef661ee707be6c8bdb373 bash42-010"
diff --git a/main/bash/bash-noinfo.patch b/main/bash/bash-noinfo.patch
new file mode 100644
index 0000000000..dcb598a493
--- /dev/null
+++ b/main/bash/bash-noinfo.patch
@@ -0,0 +1,12 @@
+diff -Naur doc/Makefile.in.orig doc/Makefile.in
+--- doc/Makefile.in.orig 2004-07-27 05:57:48.000000000 -0700
++++ doc/Makefile.in 2005-02-11 22:44:49.000000000 -0800
+@@ -220,7 +220,7 @@
+ $(SHELL) $(SUPPORT_SRCDIR)/mkinstalldirs $(DESTDIR)$(htmldir) ; \
+ fi
+
+-install: info installdirs bash.info
++install: installdirs
+ -$(INSTALL_DATA) $(srcdir)/bash.1 $(DESTDIR)$(man1dir)/bash${man1ext}
+ -$(INSTALL_DATA) $(srcdir)/bashbug.1 $(DESTDIR)$(man1dir)/bashbug${man1ext}
+ # uncomment the next line to install the builtins man page
diff --git a/main/bbsuid/APKBUILD b/main/bbsuid/APKBUILD
new file mode 100644
index 0000000000..06da12d951
--- /dev/null
+++ b/main/bbsuid/APKBUILD
@@ -0,0 +1,20 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bbsuid
+pkgver=0.6
+pkgrel=0
+pkgdesc="Obsolete package that can be removed"
+url="http://git.alpinelinux.org/cgit/bbsuid"
+arch="all"
+license="GPL-2"
+depends="busybox"
+source=""
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"
+}
+
+md5sums=""
diff --git a/main/bc/APKBUILD b/main/bc/APKBUILD
new file mode 100644
index 0000000000..337dbe60a6
--- /dev/null
+++ b/main/bc/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bc
+pkgver=1.06
+pkgrel=3
+pkgdesc="arbitrary precision numeric processing language (calculator)"
+url="http://www.gnu.org/software/bc/bc.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="flex readline-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://mirrors.kernel.org/gnu/bc/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="d44b5dddebd8a7a7309aea6c36fda117 bc-1.06.tar.gz"
diff --git a/main/bdftopcf/APKBUILD b/main/bdftopcf/APKBUILD
new file mode 100644
index 0000000000..64445e269b
--- /dev/null
+++ b/main/bdftopcf/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bdftopcf
+pkgver=1.0.2
+pkgrel=2
+pkgdesc="X.Org font utility"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig libxfont-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://xorg.freedesktop.org//releases/individual/app/bdftopcf-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --with-mapdir=/usr/share/fonts/util || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="148f20d28caaa69bbe7dcca7c2674fb6 bdftopcf-1.0.2.tar.bz2"
diff --git a/main/beecrypt/APKBUILD b/main/beecrypt/APKBUILD
new file mode 100644
index 0000000000..89922c4102
--- /dev/null
+++ b/main/beecrypt/APKBUILD
@@ -0,0 +1,45 @@
+#!/bin/sh
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=beecrypt
+pkgver=4.1.2
+pkgrel=8
+pkgdesc="general-purpose cryptography library"
+url="http://sourceforge.net/projects/beecrypt"
+arch="all"
+license="LGPL"
+depends=
+makedepends="libtool m4"
+
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ $pkgname-4.1.2-base64.patch
+ "
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-threads \
+ --enable-shared \
+ --without-java \
+ --without-python \
+ --with-cplusplus=no
+ make libaltdir=/usr/lib || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make libaltdir=/usr/lib DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="820d26437843ab0a6a8a5151a73a657c beecrypt-4.1.2.tar.gz
+01444edbffee71c2d8818fa66a3a8555 beecrypt-4.1.2-base64.patch"
diff --git a/main/beecrypt/beecrypt-4.1.2-base64.patch b/main/beecrypt/beecrypt-4.1.2-base64.patch
new file mode 100644
index 0000000000..c6c370bd07
--- /dev/null
+++ b/main/beecrypt/beecrypt-4.1.2-base64.patch
@@ -0,0 +1,11 @@
+Fix b64encode() for data starting with NUL from Miloslav Trmac <mitr@redhat.com>
+--- beecrypt-4.1.2/base64.c.b64 2005-04-26 21:46:27.000000000 +0200
++++ beecrypt-4.1.2/base64.c 2005-04-26 21:47:48.000000000 +0200
+@@ -253,7 +253,6 @@
+ unsigned c;
+
+ if (s == NULL) return NULL;
+- if (*s == '\0') return calloc(1, sizeof(*t));
+
+ if (ns == 0) ns = strlen((const char*) s);
+ nt = ((ns + 2) / 3) * 4;
diff --git a/main/beep/APKBUILD b/main/beep/APKBUILD
new file mode 100644
index 0000000000..5f59e17268
--- /dev/null
+++ b/main/beep/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=beep
+pkgver=1.3
+pkgrel=1
+pkgdesc="A terminal bell"
+url="http://johnath.com/beep"
+arch="all"
+license="GPL-2"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://johnath.com/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -m755 -D "$srcdir/$pkgname-$pkgver/beep" "$pkgdir"/usr/bin/beep
+ install -m644 -D "$srcdir/$pkgname-$pkgver/beep.1.gz" "$pkgdir"/usr/share/man/man1/beep.1.gz
+}
+
+md5sums="49c340ceb95dbda3f97b2daafac7892a beep-1.3.tar.gz"
diff --git a/main/bigreqsproto/APKBUILD b/main/bigreqsproto/APKBUILD
new file mode 100644
index 0000000000..00fa31e4e2
--- /dev/null
+++ b/main/bigreqsproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bigreqsproto
+pkgver=1.1.1
+pkgrel=0
+pkgdesc="X11 Big Requests extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="6f6c24436c2b3ab235eb14a85b9aaacf bigreqsproto-1.1.1.tar.bz2"
diff --git a/main/bind/APKBUILD b/main/bind/APKBUILD
new file mode 100644
index 0000000000..d929cad1be
--- /dev/null
+++ b/main/bind/APKBUILD
@@ -0,0 +1,105 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bind
+pkgver=9.8.0_p2
+_ver=${pkgver%_p*}
+_p=${pkgver#*_p}
+[ "$_p" != "$pkgver" ] && _ver="${_ver}-P$_p"
+pkgrel=1
+pkgdesc="BIND - Berkeley Internet Name Domain - Name Server and tools"
+url="http://www.isc.org"
+arch="all"
+license="as-is"
+depends=
+makedepends="openssl-dev perl"
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages="$pkgname-doc $pkgname-dev $pkgname-libs $pkgname-tools"
+source="http://ftp.isc.org/isc/bind9/${_ver}/bind-${_ver}.tar.gz
+ bind.so_bsdcompat.patch
+ $pkgname.initd
+ $pkgname.confd
+ $pkgname.conf
+ $pkgname.127.zone
+ $pkgname.localhost.zone
+ $pkgname.named.ca
+ "
+
+_builddir="$srcdir/bind-${_ver}"
+
+prepare() {
+ cd "$_builddir"
+
+ ### http://bugs.gentoo.org/show_bug.cgi?id=227333
+ export CFLAGS="$CFLAGS -D_GNU_SOURCE"
+
+ # Adjusting PATHs in manpages
+ for i in bin/named/named.8 bin/check/named-checkconf.8 bin/rndc/rndc.8; do
+ sed -i \
+ -e 's:/etc/named.conf:/etc/bind/named.conf:g' \
+ -e 's:/etc/rndc.conf:/etc/bind/rndc.conf:g' \
+ -e 's:/etc/rndc.key:/etc/bind/rndc.key:g' \
+ "${i}" || return 1
+ done
+
+ patch -p0 -i "$srcdir"/bind.so_bsdcompat.patch || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/bind \
+ --localstatedir=/var \
+ --with-openssl=/usr \
+ --disable-linux-caps \
+ --without-libxml2 \
+ --disable-threads \
+ --enable-ipv6 \
+ --enable-shared \
+ --enable-static \
+ --with-libtool \
+ --with-randomdev=/dev/random \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ install -Dm755 "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/named || return 1
+ install -Dm644 "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/named || return 1
+ install -Dm644 "$srcdir"/$pkgname.conf "$pkgdir"/etc/bind/named.conf || return 1
+ install -Dm644 "$srcdir"/$pkgname.named.ca "$pkgdir"/var/bind/named.ca || return 1
+ install -Dm644 "$srcdir"/$pkgname.127.zone "$pkgdir"/var/bind/pri/127.zone || return 1
+ install -Dm644 "$srcdir"/$pkgname.localhost.zone "$pkgdir"/var/bind/pri/localhost.zone || return 1
+ mkdir -p "$pkgdir"/var/bind/sec || return 1
+ cd "$pkgdir"/var/bind
+ ln -s named.ca root.cache || return 1
+}
+
+libs() {
+ install=
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/lib "$subpkgdir"/usr/
+}
+
+tools() {
+ install=
+ depends=
+ mkdir -p "$subpkgdir"/usr/bin
+ for i in dig host nslookup nsupdate; do
+ mv "$pkgdir"/usr/bin/${i} "$subpkgdir"/usr/bin/ || return 1
+ done
+}
+
+md5sums="5f90dcf1730631feacdad3257c465c54 bind-9.8.0-P2.tar.gz
+f270a5b0a28ab6e818840c5c368ddbcc bind.so_bsdcompat.patch
+92914193cc603d8d81ef00534ce9c1c9 bind.initd
+8b05a287976d66d51c18b73ee7523671 bind.confd
+be5fd752bdbd59385f2a559d603098d5 bind.conf
+a7455b009b7fccd74ac6f6eaa6902a00 bind.127.zone
+c3220168fabfb31a25e8c3a545545e34 bind.localhost.zone
+a94e29ac677846f3d4d618c50b7d34f1 bind.named.ca"
diff --git a/main/bind/bind.127.zone b/main/bind/bind.127.zone
new file mode 100644
index 0000000000..2ad28de52c
--- /dev/null
+++ b/main/bind/bind.127.zone
@@ -0,0 +1,11 @@
+$ORIGIN 127.in-addr.arpa.
+$TTL 1W
+@ 1D IN SOA localhost. root.localhost. (
+ 2002081601 ; serial
+ 3H ; refresh
+ 15M ; retry
+ 1W ; expiry
+ 1D ) ; minimum
+
+ 1D IN NS localhost.
+1 1D IN PTR localhost.
diff --git a/main/bind/bind.conf b/main/bind/bind.conf
new file mode 100644
index 0000000000..d58c61bde0
--- /dev/null
+++ b/main/bind/bind.conf
@@ -0,0 +1,53 @@
+options {
+ directory "/var/bind";
+
+ // uncomment the following lines to turn on DNS forwarding,
+ // and change the forwarding ip address(es) :
+ //forward first;
+ //forwarders {
+ // 123.123.123.123;
+ // 123.123.123.123;
+ //};
+
+ listen-on-v6 { none; };
+ listen-on { 127.0.0.1; };
+
+ // to allow only specific hosts to use the DNS server:
+ //allow-query {
+ // 127.0.0.1;
+ //};
+
+ // if you have problems and are behind a firewall:
+ //query-source address * port 53;
+ pid-file "/var/run/named/named.pid";
+};
+
+// Briefly, a zone which has been declared delegation-only will be effectively
+// limited to containing NS RRs for subdomains, but no actual data beyond its
+// own apex (for example, its SOA RR and apex NS RRset). This can be used to
+// filter out "wildcard" or "synthesized" data from NAT boxes or from
+// authoritative name servers whose undelegated (in-zone) data is of no
+// interest.
+// See http://www.isc.org/products/BIND/delegation-only.html for more info
+
+//zone "COM" { type delegation-only; };
+//zone "NET" { type delegation-only; };
+
+zone "." IN {
+ type hint;
+ file "named.ca";
+};
+
+zone "localhost" IN {
+ type master;
+ file "pri/localhost.zone";
+ allow-update { none; };
+ notify no;
+};
+
+zone "127.in-addr.arpa" IN {
+ type master;
+ file "pri/127.zone";
+ allow-update { none; };
+ notify no;
+};
diff --git a/main/bind/bind.confd b/main/bind/bind.confd
new file mode 100644
index 0000000000..82d3763509
--- /dev/null
+++ b/main/bind/bind.confd
@@ -0,0 +1,14 @@
+# Set various named options here.
+OPTS=""
+
+# Set this to the number of processors you have.
+CPU="1"
+
+# User which named should run as
+USER="named"
+
+# Default pid file location
+PIDFILE="/var/run/named/named.pid"
+
+# Scheduling priority: 19 is the lowest and -20 is the highest.
+NICELEVEL="0"
diff --git a/main/bind/bind.initd b/main/bind/bind.initd
new file mode 100644
index 0000000000..3284ec853a
--- /dev/null
+++ b/main/bind/bind.initd
@@ -0,0 +1,25 @@
+#!/sbin/runscript
+
+NAME=named
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ need net
+ after firewall
+ use logger
+ provide dns
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet --background \
+ --exec ${DAEMON} --nicelevel ${NICELEVEL} \
+ -- -u ${USER} -n ${CPU} ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet --pidfile $PIDFILE
+ eend $?
+}
diff --git a/main/bind/bind.localhost.zone b/main/bind/bind.localhost.zone
new file mode 100644
index 0000000000..338d7050ca
--- /dev/null
+++ b/main/bind/bind.localhost.zone
@@ -0,0 +1,11 @@
+$TTL 1W
+@ IN SOA ns.localhost. root.localhost. (
+ 2002081601 ; Serial
+ 28800 ; Refresh
+ 14400 ; Retry
+ 604800 ; Expire - 1 week
+ 86400 ) ; Minimum
+@ IN NS ns
+ns IN A 127.0.0.1
+
+ns IN AAAA ::1
diff --git a/main/bind/bind.named.ca b/main/bind/bind.named.ca
new file mode 100644
index 0000000000..902a7047f9
--- /dev/null
+++ b/main/bind/bind.named.ca
@@ -0,0 +1,85 @@
+; This file holds the information on root name servers needed to
+; initialize cache of Internet domain name servers
+; (e.g. reference this file in the "cache . <file>"
+; configuration file of BIND domain name servers).
+;
+; This file is made available by InterNIC
+; under anonymous FTP as
+; file /domain/named.root
+; on server FTP.INTERNIC.NET
+; -OR- RS.INTERNIC.NET
+;
+; last update: Feb 04, 2008
+; related version of root zone: 2008020400
+;
+; formerly NS.INTERNIC.NET
+;
+. 3600000 IN NS A.ROOT-SERVERS.NET.
+A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4
+A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:BA3E::2:30
+;
+; formerly NS1.ISI.EDU
+;
+. 3600000 NS B.ROOT-SERVERS.NET.
+B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201
+;
+; formerly C.PSI.NET
+;
+. 3600000 NS C.ROOT-SERVERS.NET.
+C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12
+;
+; formerly TERP.UMD.EDU
+;
+. 3600000 NS D.ROOT-SERVERS.NET.
+D.ROOT-SERVERS.NET. 3600000 A 128.8.10.90
+;
+; formerly NS.NASA.GOV
+;
+. 3600000 NS E.ROOT-SERVERS.NET.
+E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10
+;
+; formerly NS.ISC.ORG
+;
+. 3600000 NS F.ROOT-SERVERS.NET.
+F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241
+F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2f::f
+;
+; formerly NS.NIC.DDN.MIL
+;
+. 3600000 NS G.ROOT-SERVERS.NET.
+G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4
+;
+; formerly AOS.ARL.ARMY.MIL
+;
+. 3600000 NS H.ROOT-SERVERS.NET.
+H.ROOT-SERVERS.NET. 3600000 A 128.63.2.53
+H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::803f:235
+;
+; formerly NIC.NORDU.NET
+;
+. 3600000 NS I.ROOT-SERVERS.NET.
+I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17
+;
+; operated by VeriSign, Inc.
+;
+. 3600000 NS J.ROOT-SERVERS.NET.
+J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30
+J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:C27::2:30
+;
+; operated by RIPE NCC
+;
+. 3600000 NS K.ROOT-SERVERS.NET.
+K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129
+K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fd::1
+;
+; operated by ICANN
+;
+. 3600000 NS L.ROOT-SERVERS.NET.
+L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42
+;
+; operated by WIDE
+;
+. 3600000 NS M.ROOT-SERVERS.NET.
+M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33
+M.ROOT-SERVERS.NET. 3600000 AAAA 2001:dc3::35
+; End of File
diff --git a/main/bind/bind.post-install b/main/bind/bind.post-install
new file mode 100644
index 0000000000..7e091c097c
--- /dev/null
+++ b/main/bind/bind.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+install -dD -o named -g named /var/run/named
+chown -R named:named /var/bind
+
diff --git a/main/bind/bind.pre-install b/main/bind/bind.pre-install
new file mode 100644
index 0000000000..c799634502
--- /dev/null
+++ b/main/bind/bind.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /etc/bind -s /bin/false -D named 2>/dev/null
+exit 0
+
diff --git a/main/bind/bind.so_bsdcompat.patch b/main/bind/bind.so_bsdcompat.patch
new file mode 100644
index 0000000000..83120f77de
--- /dev/null
+++ b/main/bind/bind.so_bsdcompat.patch
@@ -0,0 +1,11 @@
+--- lib/isc/unix/socket.c.orig 2005-11-03 17:08:42.000000000 -0600
++++ lib/isc/unix/socket.c 2006-02-18 13:09:15.000000000 -0600
+@@ -245,6 +245,8 @@
+
+ #define SOCK_DEAD(s) ((s)->references == 0)
+
++#undef SO_BSDCOMPAT
++
+ static void
+ manager_log(isc_socketmgr_t *sockmgr,
+ isc_logcategory_t *category, isc_logmodule_t *module, int level,
diff --git a/main/binutils/APKBUILD b/main/binutils/APKBUILD
new file mode 100644
index 0000000000..60f58aecde
--- /dev/null
+++ b/main/binutils/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=binutils
+pkgver=2.21.1
+pkgrel=0
+pkgdesc="Tools necessary to build programs"
+url="http://www.gnu.org/software/binutils/"
+source="http://ftp.gnu.org/gnu/binutils/binutils-$pkgver.tar.bz2"
+depends=
+makedepends="bison flex texinfo zlib-dev"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --mandir /usr/share/man \
+ --build ${CHOST:-i486-alpine-linux-uclibc} \
+ --infodir /usr/share/info \
+ --disable-multilib \
+ --enable-shared \
+ --enable-64-bit-bfd \
+ --disable-werror \
+ --disable-nls
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make install DESTDIR="$pkgdir"
+ if [ -d "$pkgdir"/usr/lib64 ]; then
+ mv "$pkgdir"/usr/lib64/* "$pkgdir"/usr/lib/
+ rmdir "$pkgdir"/usr/lib64
+ fi
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="a22801a9cad45c85e9ff6afc10537d72 binutils-2.21.1.tar.bz2"
diff --git a/main/bison/APKBUILD b/main/bison/APKBUILD
new file mode 100644
index 0000000000..8eb1242407
--- /dev/null
+++ b/main/bison/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bison
+pkgver=2.5
+pkgrel=0
+pkgdesc="The GNU general-purpose parser generator"
+arch="all"
+license="GPL"
+url="http://www.gnu.org/software/bison/bison.html"
+depends="m4"
+source="ftp://ftp.gnu.org/gnu/bison/${pkgname}-${pkgver}.tar.gz"
+subpackages="$pkgname-doc"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --datadir=/usr/share \
+ --infodir=/usr/share/info \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="687e1dcd29452789d34eaeea4c25abe4 bison-2.5.tar.gz"
diff --git a/main/bitlbee/APKBUILD b/main/bitlbee/APKBUILD
new file mode 100644
index 0000000000..e0b35bafdd
--- /dev/null
+++ b/main/bitlbee/APKBUILD
@@ -0,0 +1,58 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+pkgname=bitlbee
+pkgver=3.0.3
+pkgrel=0
+pkgdesc="An IRC to other chat networks gateway"
+url="http://www.bitlbee.org/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="glib-dev openssl-dev libotr-dev"
+install="$pkgname.post-install"
+subpackages="$pkgname-doc $pkgname-otr"
+source="
+ http://get.bitlbee.org/src/$pkgname-$pkgver.tar.gz
+ $pkgname.initd
+ $pkgname.confd
+ $pkgname.post-install
+ "
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --ssl=openssl \
+ --otr=plugin \
+ --prefix=/usr \
+ --etcdir=/etc/bitlbee || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install install-etc || return 1
+
+ install -m755 -D "$srcdir"/$pkgname.initd \
+ "$pkgdir"/etc/init.d/$pkgname || return 1
+ install -m644 -D "$srcdir"/$pkgname.confd \
+ "$pkgdir"/etc/conf.d/$pkgname || return 1
+}
+otr() {
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/bitlbee "$subpkgdir"/usr/lib
+}
+
+md5sums="4fe688e3a80efe011743f4c9265c0310 bitlbee-3.0.3.tar.gz
+6b3c70649ececec230d145b62778ad61 bitlbee.initd
+bf07d39a4b652c63415b411229c5e281 bitlbee.confd
+2d91f7ae46d69560d7f156f282dceaef bitlbee.post-install"
diff --git a/main/bitlbee/bitlbee.confd b/main/bitlbee/bitlbee.confd
new file mode 100644
index 0000000000..99f308cd97
--- /dev/null
+++ b/main/bitlbee/bitlbee.confd
@@ -0,0 +1,9 @@
+# Sample conf.d file for alpine linux
+
+#
+# Specify daemon options here.
+#
+
+PORT="6667"
+OPTS="-F"
+
diff --git a/main/bitlbee/bitlbee.initd b/main/bitlbee/bitlbee.initd
new file mode 100644
index 0000000000..92bab34abd
--- /dev/null
+++ b/main/bitlbee/bitlbee.initd
@@ -0,0 +1,29 @@
+#!/sbin/runscript
+
+name=bitlbee
+daemon=/usr/sbin/$name
+
+. /etc/conf.d/$name
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${name}"
+ start-stop-daemon --start --quiet \
+ --pidfile /var/run/${name}.pid \
+ --chuid nobody:nobody \
+ --exec ${daemon} -- ${PORT} ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${name}"
+ start-stop-daemon --stop --signal 9 --quiet \
+ --pidfile /var/run/$name.pid \
+ --exec ${daemon}
+ eend $?
+}
+
diff --git a/main/bitlbee/bitlbee.post-install b/main/bitlbee/bitlbee.post-install
new file mode 100644
index 0000000000..d962fdcd9a
--- /dev/null
+++ b/main/bitlbee/bitlbee.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+mkdir -p /var/lib/bitlbee
+chown nobody:nobody /var/lib/bitlbee
+
diff --git a/main/bkeymaps/APKBUILD b/main/bkeymaps/APKBUILD
new file mode 100644
index 0000000000..860c639370
--- /dev/null
+++ b/main/bkeymaps/APKBUILD
@@ -0,0 +1,16 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bkeymaps
+pkgver=1.13
+pkgrel=1
+pkgdesc="Binary keymaps for busybox"
+url="http://dev.alpinelinux.org/alpine/bkeymaps"
+arch="noarch"
+license="GPL"
+depends="busybox"
+source="http://dev.alpinelinux.org/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+md5sums="a68058ab4a81cf9a8dcbaaa7a5df5b11 bkeymaps-1.13.tar.gz"
diff --git a/main/bluez-firmware/APKBUILD b/main/bluez-firmware/APKBUILD
new file mode 100644
index 0000000000..70257c3755
--- /dev/null
+++ b/main/bluez-firmware/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bluez-firmware
+pkgver=1.2
+pkgrel=0
+pkgdesc="Firmware for Broadcom BCM203x Blutonium devices"
+url="http://www.bluez.org/"
+arch="all"
+license="GPL2"
+depends=""
+makedepends=""
+source="http://bluez.sf.net/download/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --libdir=/lib || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="1cc3cefad872e937e05de5a0a2b390dd bluez-firmware-1.2.tar.gz"
diff --git a/main/bluez-hcidump/APKBUILD b/main/bluez-hcidump/APKBUILD
new file mode 100644
index 0000000000..08eb229597
--- /dev/null
+++ b/main/bluez-hcidump/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bluez-hcidump
+pkgver=2.1
+pkgrel=0
+pkgdesc="Bluetooth HCI package analyzer"
+url="http://www.bluez.org/"
+arch="all"
+license="GPL2"
+depends=
+makedepends="bluez-dev"
+subpackages="$pkgname-doc"
+source="http://www.kernel.org/pub/linux/bluetooth/bluez-hcidump-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="b160f0672276398344eebe9df1b37a2c bluez-hcidump-2.1.tar.gz"
diff --git a/main/bluez/APKBUILD b/main/bluez/APKBUILD
new file mode 100644
index 0000000000..8ec754dacf
--- /dev/null
+++ b/main/bluez/APKBUILD
@@ -0,0 +1,81 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bluez
+pkgver=4.94
+pkgrel=1
+pkgdesc="Tools for the Bluetooth protocol stack"
+url="http://www.bluez.org/"
+arch="all"
+license="GPL2"
+depends="consolekit"
+replaces="udev"
+makedepends="dbus-dev gst-plugins-base-dev alsa-lib-dev libusb-compat-dev
+ libnl-dev consolekit-dev udev-dev"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-libs $pkgname-alsa
+ $pkgname-cups $pkgname-gstreamer"
+source="http://www.kernel.org/pub/linux/bluetooth/$pkgname-$pkgver.tar.bz2
+ bluetooth.initd
+ bluetooth.confd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --libexecdir=/lib \
+ --mandir=/usr/share/man \
+ --enable-gstreamer \
+ --enable-alsa \
+ --enable-usb \
+ --enable-tools \
+ --enable-bccmd \
+ --enable-hid2hci \
+ --enable-dfutool \
+ --enable-hidd \
+ --enable-pand \
+ --enable-dund \
+ --enable-cups \
+ --enable-configfiles \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install DESTDIR="$pkgdir" || return 1
+ rm "$pkgdir"/usr/lib/*/*.la \
+ "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm755 "$srcdir"/bluetooth.initd "$pkgdir"/etc/init.d/bluetooth
+ install -Dm644 "$srcdir"/bluetooth.confd "$pkgdir"/etc/conf.d/bluetooth
+ install -Dm755 test/simple-agent "$pkgdir"/usr/bin/bluez-simple-agent
+}
+
+libs() {
+ pkgdesc="Libraries for Bluetooth protocol stack"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libbluetooth.so.* "$subpkgdir"/usr/lib/
+}
+
+alsa() {
+ pkgdesc="Bluez plugin for ALSA"
+ mkdir -p "$subpkgdir"/usr/share "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/share/alsa* "$subpkgdir"/usr/share/ || return 1
+ mv "$pkgdir"/usr/lib/alsa* "$subpkgdir"/usr/lib/
+}
+
+cups() {
+ pkgdesc="Bluez backend for CUPS"
+ mkdir -p "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/lib/cups "$subpkgdir"/usr/lib/
+}
+
+gstreamer() {
+ pkgdesc="Bluez plugin for gstreamer"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/gstreamer* \
+ "$subpkgdir"/usr/lib/
+}
+md5sums="1b599892f4c71c0ab6cf0ed4d3cb226a bluez-4.94.tar.bz2
+c511078403d7d27673581a8bb468b90b bluetooth.initd
+a159d897a057f4675548327329c4cc22 bluetooth.confd"
diff --git a/main/bluez/bluetooth-conf.d b/main/bluez/bluetooth-conf.d
new file mode 100644
index 0000000000..b0cc744415
--- /dev/null
+++ b/main/bluez/bluetooth-conf.d
@@ -0,0 +1,7 @@
+# Bluetooth configuraton file
+
+# Bind rfcomm devices (allowed values are "true" and "false")
+RFCOMM_ENABLE=true
+
+# Config file for rfcomm
+RFCOMM_CONFIG="/etc/bluetooth/rfcomm.conf"
diff --git a/main/bluez/bluetooth-init.d b/main/bluez/bluetooth-init.d
new file mode 100644
index 0000000000..111902aaeb
--- /dev/null
+++ b/main/bluez/bluetooth-init.d
@@ -0,0 +1,31 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-wireless/bluez/files/4.60/bluetooth-init.d,v 1.1 2010/02/01 19:47:46 pacho Exp $
+
+depend() {
+ after coldplug
+ need dbus localmount
+}
+
+start() {
+ ebegin "Starting Bluetooth"
+
+ udevadm trigger --subsystem-match=bluetooth
+ eend $?
+
+ if [ "${RFCOMM_ENABLE}" = "true" -a -x /usr/bin/rfcomm ]; then
+ if [ -f "${RFCOMM_CONFIG}" ]; then
+ ebegin " Starting rfcomm"
+ /usr/bin/rfcomm -f "${RFCOMM_CONFIG}" bind all
+ eend $?
+ else
+ ewarn "Not enabling rfcomm because RFCOMM_CONFIG does not exists"
+ fi
+ fi
+}
+
+stop() {
+ ebegin "Shutting down Bluetooth"
+ eend 0
+}
diff --git a/main/bluez/bluetooth.confd b/main/bluez/bluetooth.confd
new file mode 100644
index 0000000000..b0cc744415
--- /dev/null
+++ b/main/bluez/bluetooth.confd
@@ -0,0 +1,7 @@
+# Bluetooth configuraton file
+
+# Bind rfcomm devices (allowed values are "true" and "false")
+RFCOMM_ENABLE=true
+
+# Config file for rfcomm
+RFCOMM_CONFIG="/etc/bluetooth/rfcomm.conf"
diff --git a/main/bluez/bluetooth.initd b/main/bluez/bluetooth.initd
new file mode 100644
index 0000000000..ef25720bf6
--- /dev/null
+++ b/main/bluez/bluetooth.initd
@@ -0,0 +1,32 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-wireless/bluez/files/4.60/bluetooth-init.d,v 1.1 2010/02/01 19:47:46 pacho Exp $
+
+depend() {
+ after coldplug
+ need dbus localmount
+}
+
+start() {
+ ebegin "Starting Bluetooth"
+
+ if [ -x /sbin/udevadm ]; then
+ udevadm trigger --subsystem-match=bluetooth --action=add
+ eend $?
+ fi
+
+ if [ "${RFCOMM_ENABLE}" = "true" -a -x /usr/bin/rfcomm ]; then
+ if [ -f "${RFCOMM_CONFIG}" ]; then
+ /usr/bin/rfcomm -f "${RFCOMM_CONFIG}" bind all
+ else
+ ewarn "Not enabling rfcomm because RFCOMM_CONFIG does not exists"
+ fi
+ fi
+ eend $?
+}
+
+stop() {
+ ebegin "Shutting down Bluetooth"
+ eend 0
+}
diff --git a/main/boost/APKBUILD b/main/boost/APKBUILD
new file mode 100644
index 0000000000..3fbec4ac2b
--- /dev/null
+++ b/main/boost/APKBUILD
@@ -0,0 +1,136 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=boost
+pkgver=1.46.1
+
+_x=${pkgver%%.*} # strip .y.z
+_y=${pkgver%.*} # strip .z
+_y=${_y#*.} # strip x.
+_z=${pkgver##*.} # strip x.y.
+_ver=${_x}_${_y}_${_z}
+
+pkgrel=1
+pkgdesc="Free peer-reviewed portable C++ source libraries"
+url="http://www.boost.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="python-dev>=2.6 flex bison bzip2-dev zlib-dev"
+subpackages="$pkgname-dev $pkgname-doc
+$pkgname-date_time
+$pkgname-filesystem
+$pkgname-graph
+$pkgname-iostreams
+$pkgname-math
+$pkgname-prg_exec_monitor
+$pkgname-program_options
+$pkgname-python:py
+$pkgname-random
+$pkgname-regex
+$pkgname-serialization
+$pkgname-signals
+$pkgname-system
+$pkgname-thread
+$pkgname-unit_test_framework
+$pkgname-wave
+$pkgname-wserialization
+"
+source="http://downloads.sourceforge.net/$pkgname/${pkgname}_$_ver.tar.gz
+ "
+
+_builddir="$srcdir"/${pkgname}_${_ver}
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ [ -r "$i" ] || continue
+ msg "Applying $i"
+ patch -p1 -i "$i" || return 1
+ done
+
+ # create user-config.jam
+ cat > user-config.jam <<__EOF__
+
+using gcc : : $CC : <cxxflags>"${CXXFLAGS}" <linkflags>"${LDFLAGS}" ;
+
+__EOF__
+}
+
+_options="--user-config=\"$_builddir/user-config.jam\"
+ --prefix=\"$pkgdir/usr\"
+ release
+ debug-symbols=off
+ threading=single,multi
+ runtime-link=shared
+ link=shared,static
+ cflags=-fno-strict-aliasing
+ -sPYTHON_ROOT=/usr
+ -sPYTHON_VERSION=2.6
+ -sTOOLS=gcc
+ --layout=tagged
+ -q
+ -j${JOBS:-2}
+"
+
+build() {
+ msg "Building bjam"
+ export BOOST_ROOT="$_builddir"
+ cd "$_builddir"/tools/build/v2/engine/src
+ CC= ./build.sh cc || return 1
+ _bindir="bin.linuxx86"
+ [ "${CARCH}" = "x86_64" ] && _bindir="bin.linuxx86_64"
+ install -m755 -d "$pkgdir"/usr/bin
+ install -m755 ${_bindir}/bjam "$pkgdir"/usr/bin/bjam || return 1
+ _bjam="$pkgdir"/usr/bin/bjam
+
+ msg "Building bcp"
+ cd "${_builddir}"/tools/bcp
+ "${_bjam}" -j${JOBS:-2} || return 1
+ install -m755 "$srcdir"/${pkgname}_${_ver}/dist/bin/bcp \
+ "$pkgdir"/usr/bin/bcp || return 1
+
+ msg "Building boost"
+ cd "$_builddir"
+ "${_bjam}" $_options
+}
+
+package() {
+ cd "$_builddir"
+ export BOOST_ROOT="$_builddir"
+ _bjam="$pkgdir"/usr/bin/bjam
+ "${_bjam}" $_options \
+ --includedir="$pkgdir"/usr/include \
+ --libdir="$pkgdir"/usr/lib \
+ install || return 1
+
+ cd "$srcdir"/${pkgname}_${_ver}/libs/python/pyste/install
+ python setup.py install --root="$pkgdir" || return 1
+ install -m755 -d "$pkgdir"/usr/share/licenses/$pkgname
+ install -m644 "$srcdir"/${pkgname}_${_ver}/LICENSE_1_0.txt \
+ "$pkgdir"/usr/share/licenses/$pkgname/ || return 1
+}
+
+_mvlib() {
+ pkgdesc="Boost $1 library"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libboost_$1* "$subpkgdir"/usr/lib/
+}
+
+date_time() { _mvlib date_time; }
+filesystem() { _mvlib filesystem; }
+graph() { _mvlib graph; }
+iostreams() { _mvlib iostreams; }
+math() { _mvlib math; }
+prg_exec_monitor() { _mvlib prg_exec_monitor; }
+program_options() { _mvlib program_options; }
+py() { _mvlib python; }
+random() { _mvlib random; }
+regex() { _mvlib regex; }
+serialization() { _mvlib serialization; }
+signals() { _mvlib signals; }
+system() { _mvlib system; }
+thread() { _mvlib thread; }
+unit_test_framework() { _mvlib unit_test_framework; }
+wave() { _mvlib wave; }
+wserialization() { _mvlib wserialization; }
+
+
+md5sums="341e5d993b19d099bf1a548495ea91ec boost_1_46_1.tar.gz"
diff --git a/main/bridge-utils/APKBUILD b/main/bridge-utils/APKBUILD
new file mode 100644
index 0000000000..11b7e37efa
--- /dev/null
+++ b/main/bridge-utils/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bridge-utils
+pkgver=1.4
+pkgrel=2
+pkgdesc="Tools for configuring the Linux kernel 802.1d Ethernet Bridge"
+url="http://linux-net.osdl.org/index.php/Bridge"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=""
+makedepends="autoconf"
+source="http://downloads.sourceforge.net/project/bridge/bridge/bridge-utils-$pkgver/bridge-utils-$pkgver.tar.gz"
+#"http://download.sourceforge.net/bridge/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ autoconf
+ # src_compile
+ ./configure --prefix=/ \
+ --mandir=/usr/share/man \
+ --libdir=/usr/lib \
+ --includedir=/usr/include \
+ || return 1
+ make || return 1
+ make install DESTDIR="$pkgdir" || return 1
+}
+md5sums="0182fcac3a2b307113bbec34e5f1c673 bridge-utils-1.4.tar.gz"
diff --git a/main/bsnes/APKBUILD b/main/bsnes/APKBUILD
new file mode 100644
index 0000000000..7b4e8121f8
--- /dev/null
+++ b/main/bsnes/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=bsnes
+pkgver=0.78
+_x=${pkgver%.*}
+_y=${pkgver#*.}
+_pkgver="v${_x}${_y}"
+pkgrel=0
+pkgdesc="high accuracy SNES emulator"
+url="http://byuu.org/bsnes/"
+arch="all"
+license="GPL"
+depends=
+depends_dev="qt-dev openal-soft-dev sdl-dev alsa-lib-dev mesa-dev libao-dev libxv-dev"
+makedepends="$depends_dev"
+install=""
+subpackages=
+source="http://bsnes.googlecode.com/files/${pkgname}_${_pkgver}-source.tar.bz2
+ nall-strlcpy.patch
+ no-pulseaudio.patch"
+
+_builddir="${srcdir}/${pkgname}_${_pkgver}-source/bsnes"
+prepare() {
+ local i
+ cd "$_builddir/.."
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make compiler=gcc prefix=/usr profile=performance || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" prefix=/usr profile=performance install || return 1
+}
+
+md5sums="19c07dc9be18bf3314f4e7122c00f16e bsnes_v078-source.tar.bz2
+d5017142f2cbccac878bbfc799b3445f nall-strlcpy.patch
+07caea846bf49ee6f5deaf999dffbd5f no-pulseaudio.patch"
diff --git a/main/bsnes/nall-strlcpy.patch b/main/bsnes/nall-strlcpy.patch
new file mode 100644
index 0000000000..dd4a005a63
--- /dev/null
+++ b/main/bsnes/nall-strlcpy.patch
@@ -0,0 +1,31 @@
+--- bsnes_v077-source/bsnes/snes/system/serialization.cpp
++++ bsnes_v077-source/bsnes/snes/system/serialization.cpp
+@@ -7,7 +7,7 @@
+ char profile[16], description[512];
+ memset(&profile, 0, sizeof profile);
+ memset(&description, 0, sizeof description);
+- strlcpy(profile, Info::Profile, sizeof profile);
++ nall::strlcpy(profile, Info::Profile, sizeof profile);
+
+ s.integer(signature);
+ s.integer(version);
+--- bsnes_v077-source/bsnes/ui/tools/state-manager.cpp
++++ bsnes_v077-source/bsnes/ui/tools/state-manager.cpp
+@@ -130,7 +130,7 @@
+ string StateManager::slotLoadDescription(unsigned i) {
+ if(slot[i].capacity() == 0) return "(empty)";
+ char text[512];
+- strlcpy(text, (const char*)slot[i].data() + HeaderLength, 512);
++ nall::strlcpy(text, (const char*)slot[i].data() + HeaderLength, 512);
+ return text;
+ }
+
+@@ -138,7 +138,7 @@
+ if(stateList.selected() == false) return;
+ string text = descEdit.text();
+ if(slot[stateList.selection()].capacity() > 0) {
+- strlcpy((char*)slot[stateList.selection()].data() + HeaderLength, (const char*)text, 512);
++ nall::strlcpy((char*)slot[stateList.selection()].data() + HeaderLength, (const char*)text, 512);
+ }
+ refresh();
+ }
diff --git a/main/bsnes/no-pulseaudio.patch b/main/bsnes/no-pulseaudio.patch
new file mode 100644
index 0000000000..5a5dea3e1e
--- /dev/null
+++ b/main/bsnes/no-pulseaudio.patch
@@ -0,0 +1,11 @@
+--- bsnes_v077-source.orig/bsnes/ui/Makefile
++++ bsnes_v077-source/bsnes/ui/Makefile
+@@ -14,7 +14,7 @@
+ link += `pkg-config --libs QtCore QtGui`
+
+ ruby := video.glx video.xv video.sdl
+- ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao
++ ruby += audio.alsa audio.openal audio.oss audio.ao
+ ruby += input.sdl input.x
+
+ link += $(if $(findstring audio.openal,$(ruby)),-lopenal)
diff --git a/main/build-base/APKBUILD b/main/build-base/APKBUILD
new file mode 100644
index 0000000000..28989ea35a
--- /dev/null
+++ b/main/build-base/APKBUILD
@@ -0,0 +1,18 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=build-base
+pkgver=0.2
+pkgrel=2
+url=http://dev.alpinelinux.org/cgit
+pkgdesc="Meta package for build base"
+if [ "$ALPINE_LIBC" = "eglibc" ]; then
+ depends="binutils gcc make patch eglibc-dev g++"
+else
+ depends="binutils gcc make patch uclibc-dev g++"
+fi
+arch="all"
+license=none
+
+build() {
+ # meta package
+ mkdir -p "$pkgdir"
+}
diff --git a/main/busybox-initscripts/APKBUILD b/main/busybox-initscripts/APKBUILD
new file mode 100644
index 0000000000..5d1ebdaf37
--- /dev/null
+++ b/main/busybox-initscripts/APKBUILD
@@ -0,0 +1,64 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=busybox-initscripts
+pkgver=2.2
+pkgrel=2
+pkgdesc="Init scripts for busybox daemons"
+url="http://git.alpinelinux.org/cgit/aports/tree/core/busybox-initscripts"
+arch="noarch"
+license="GPL-2"
+depends="busybox"
+makedepends=
+install=$pkgname.post-install
+subpackages=
+source="acpid.initd cron.initd dnsd.initd httpd.initd inetd.initd klogd.initd
+ mdev-mount.initd mdev.initd rdate.initd syslog.initd watchdog.initd
+ cron.confd klogd.confd rdate.confd syslog.confd watchdog.confd
+ mdev.conf dvbdev ide_links usbdev usbdisk_link xvd_links
+ "
+
+build() {
+ local i
+ cd "$srcdir"
+
+ mkdir -p "$pkgdir"/etc/conf.d "$pkgdir"/etc/init.d "$pkgdir"/lib/mdev\
+ "$pkgdir"/etc/acpi/PWRF
+ for i in *.initd; do
+ install -m755 "$srcdir"/$i "$pkgdir"/etc/init.d/${i%.*} || return 1
+ done
+ for i in *.confd; do
+ install -m644 "$srcdir"/$i "$pkgdir"/etc/conf.d/${i%.*} || return 1
+ done
+ install -m644 mdev.conf "$pkgdir"/etc
+ install -m755 dvbdev ide_links usbdev usbdisk_link xvd_links "$pkgdir"/lib/mdev/
+
+ # poweroff script for acpid
+ cat >"$pkgdir"/etc/acpi/PWRF/00000080 <<EOF
+#!/bin/sh
+poweroff
+EOF
+ chmod +x "$pkgdir"/etc/acpi/PWRF/00000080
+}
+
+md5sums="eba3eab9ace889088e01c6c9e80ae3db acpid.initd
+6db6c6d6a5e0169e54a0e0527d83dfff cron.initd
+dad20779adfb4b85b57b45c7c903a636 dnsd.initd
+56d24c7bd4e5d442c7436b0819017ff3 httpd.initd
+7504e0700dfa85f354d31af7a58663f9 inetd.initd
+b0146b19b828051985377de1e4431a32 klogd.initd
+12379687c0cfb5446e0cfc20bd6992bb mdev-mount.initd
+ef3e93fe17964dd600364b1340654b5b mdev.initd
+c01dc869cbdd68e86e64a35ccc1e885e rdate.initd
+4ef91ad26f5b6e64b5bc545e35f18af1 syslog.initd
+254186e513ff9fb9ede6a2e92257b247 watchdog.initd
+8ddb8d040c9c7a32c63039a2c80ff496 cron.confd
+60bc14cc3163d76f41bcc93dc0f9984b klogd.confd
+22adbf155ffc4595206ded6daad07812 rdate.confd
+77fb31a75511247bf4e3430565a276bc syslog.confd
+0bb55dde32f5e119111fa4938daaef3d watchdog.confd
+a193d4aa411662dd31cd9b68bf38bd8f mdev.conf
+ad1556961294e4aa2abca6be52138b7c dvbdev
+5c8725b4cbdeda23b00f08124a0d20bf ide_links
+c422992ca5bfdfabdbba1f1532bc1358 usbdev
+30b0c85956b6701caf55309a17e537f6 usbdisk_link
+826d85313ca7a4a0205d63bd58b7d01f xvd_links"
diff --git a/main/busybox-initscripts/acpid.initd b/main/busybox-initscripts/acpid.initd
new file mode 100644
index 0000000000..5fbae1e5a3
--- /dev/null
+++ b/main/busybox-initscripts/acpid.initd
@@ -0,0 +1,20 @@
+#!/sbin/runscript
+
+depend() {
+ need dev localmount
+ after hwdrivers modules
+}
+
+start() {
+ ebegin "Starting busybox acpid"
+ start-stop-daemon --start --exec /sbin/acpid \
+ -- $ACPID_OPTS
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping busybox acpid"
+ start-stop-daemon --stop --exec /sbin/acpid
+ eend $?
+}
+
diff --git a/main/busybox-initscripts/busybox-initscripts.post-install b/main/busybox-initscripts/busybox-initscripts.post-install
new file mode 100644
index 0000000000..11575f58b9
--- /dev/null
+++ b/main/busybox-initscripts/busybox-initscripts.post-install
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# this is for upgraders
+if [ -L /etc/runlevels/boot/mdev ]; then
+ mkdir -p /etc/runlevels/sysinit
+ mv /etc/runlevels/boot/mdev /etc/runlevels/sysinit/ 2>/dev/null
+fi
+exit 0
+
diff --git a/main/busybox-initscripts/cron.confd b/main/busybox-initscripts/cron.confd
new file mode 100644
index 0000000000..2f2eb7bb75
--- /dev/null
+++ b/main/busybox-initscripts/cron.confd
@@ -0,0 +1,3 @@
+# enter the cron options
+CRON_OPTS="-c /etc/crontabs"
+
diff --git a/main/busybox-initscripts/cron.initd b/main/busybox-initscripts/cron.initd
new file mode 100644
index 0000000000..8175bdf2d0
--- /dev/null
+++ b/main/busybox-initscripts/cron.initd
@@ -0,0 +1,19 @@
+#!/sbin/runscript
+
+depend() {
+ need localmount
+ need logger
+}
+
+start() {
+ ebegin "Starting busybox cron"
+ start-stop-daemon --start --exec /usr/sbin/crond -- $CRON_OPTS
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping busybox cron"
+ start-stop-daemon --stop --exec /usr/sbin/crond
+ eend $?
+}
+
diff --git a/main/busybox-initscripts/dnsd.initd b/main/busybox-initscripts/dnsd.initd
new file mode 100644
index 0000000000..e11a73d1d6
--- /dev/null
+++ b/main/busybox-initscripts/dnsd.initd
@@ -0,0 +1,18 @@
+#!/sbin/runscript
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting dnsd"
+ start-stop-daemon --start --exec /usr/sbin/dnsd -- -d $DNSD_OPTS
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping dnsd"
+ start-stop-daemon --stop --exec /usr/sbin/dnsd
+ eend $?
+}
diff --git a/main/busybox-initscripts/dvbdev b/main/busybox-initscripts/dvbdev
new file mode 100644
index 0000000000..f0186c176c
--- /dev/null
+++ b/main/busybox-initscripts/dvbdev
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# MDEV=dvb0.demux1 -> ADAPTER=dvb0 -> N=0
+ADAPTER=${MDEV%.*}
+N=${ADAPTER#dvb}
+# MDEV=dvb0.demux1 -> DEVB_DEV=demux1
+DVB_DEV=${MDEV#*.}
+
+case "$ACTION" in
+ add|"")
+ mkdir -p dvb/adapter${N}
+ mv ${MDEV} dvb/adapter${N}/${DVB_DEV}
+ ;;
+ remove)
+ rm -f dvb/adapter${N}/${DVB_DEV}
+ rmdir dvb/adapter${N} 2>/dev/null
+ rmdir dvb/ 2>/dev/null
+esac
diff --git a/main/busybox-initscripts/httpd.initd b/main/busybox-initscripts/httpd.initd
new file mode 100644
index 0000000000..be23a6b3a7
--- /dev/null
+++ b/main/busybox-initscripts/httpd.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+
+DAEMON=/usr/sbin/httpd
+
+depend() {
+ need net localmount
+ after firewall
+}
+
+start() {
+ ebegin "Starting busybox httpd"
+ start-stop-daemon --start --exec $DAEMON -- $HTTPD_OPTS
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping busybox httpd"
+ start-stop-daemon --stop --exec $DAEMON
+ eend $?
+}
+
diff --git a/main/busybox-initscripts/ide_links b/main/busybox-initscripts/ide_links
new file mode 100644
index 0000000000..be0c95aa9c
--- /dev/null
+++ b/main/busybox-initscripts/ide_links
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+[ -f /proc/ide/$MDEV/media ] || exit
+
+media=`cat /proc/ide/$MDEV/media`
+for i in $media $media[0-9]* ; do
+ if [ "`readlink $i 2>/dev/null`" = $MDEV ] ; then
+ LINK=$i
+ break
+ fi
+done
+
+# link exist, remove if necessary and exit
+if [ "$LINK" ] ; then
+ [ "$ACTION" = remove ] && rm $LINK
+ exit
+fi
+
+# create a link
+num=`ls $media[0-9]* 2>/dev/null | wc -l`
+ln -sf $MDEV "$media`echo $num`"
+[ -e "$media" ] || ln -sf $MDEV "$media"
+
diff --git a/main/busybox-initscripts/inetd.initd b/main/busybox-initscripts/inetd.initd
new file mode 100644
index 0000000000..fa1f015b83
--- /dev/null
+++ b/main/busybox-initscripts/inetd.initd
@@ -0,0 +1,19 @@
+#!/sbin/runscript
+
+depend() {
+ need net localmount
+ after firewall
+}
+
+start() {
+ ebegin "Starting busybox inetd"
+ start-stop-daemon --start --exec /usr/sbin/inetd -- $INETD_OPTS
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping busybox inetd"
+ start-stop-daemon --stop --exec /usr/sbin/inetd
+ eend $?
+}
+
diff --git a/main/busybox-initscripts/klogd.confd b/main/busybox-initscripts/klogd.confd
new file mode 100644
index 0000000000..100deedaac
--- /dev/null
+++ b/main/busybox-initscripts/klogd.confd
@@ -0,0 +1 @@
+KLOGD_OPTS=""
diff --git a/main/busybox-initscripts/klogd.initd b/main/busybox-initscripts/klogd.initd
new file mode 100644
index 0000000000..d783bccdc7
--- /dev/null
+++ b/main/busybox-initscripts/klogd.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+
+depend() {
+ need clock hostname localmount
+ before net
+ provide logger
+ keyword novserver
+}
+
+start() {
+ ebegin "Starting busybox kernel logging"
+ start-stop-daemon --start --exec /sbin/klogd -- ${KLOGD_OPTS}
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping busybox kernel logging"
+ start-stop-daemon --stop --exec /sbin/klogd
+ eend $?
+}
+
diff --git a/main/busybox-initscripts/mdev-mount.initd b/main/busybox-initscripts/mdev-mount.initd
new file mode 100644
index 0000000000..c7aaa824c2
--- /dev/null
+++ b/main/busybox-initscripts/mdev-mount.initd
@@ -0,0 +1,64 @@
+#!/sbin/runscript
+# Largely based on Gentoo's udev-mount
+#
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+#
+
+description="Mount tmpfs on /dev"
+
+mount_dev_directory()
+{
+ if [ "$(mountinfo -t /dev)" = "mdev" ]; then
+ # already mounted
+ if fstabinfo --quiet /dev; then
+ mount -o remount -n /dev
+ fi
+ return 0
+ fi
+
+ # No options are processed here as they should all be in /etc/fstab
+ ebegin "Mounting /dev"
+ mkdir -p /dev
+ if fstabinfo --quiet /dev; then
+ mount -n /dev
+ else
+ # Some devices require exec, Bug #92921
+ mount -n -t tmpfs -o "exec,nosuid,mode=0755,size=1M" mdev /dev
+ fi
+ eend $?
+}
+
+seed_dev()
+{
+ # Seed /dev with some things that we know we need
+
+ # creating /dev/console, /dev/tty and /dev/tty1 to be able to write
+ # to $CONSOLE with/without bootsplash before udevd creates it
+ [ -c /dev/console ] || mknod -m 600 /dev/console c 5 1
+ [ -c /dev/tty1 ] || mknod -m 620 /dev/tty1 c 4 1
+ [ -c /dev/tty ] || mknod -m 666 /dev/tty c 5 0
+
+ # udevd will dup its stdin/stdout/stderr to /dev/null
+ # and we do not want a file which gets buffered in ram
+ [ -c /dev/null ] || mknod -m 666 /dev/null c 1 3
+
+ # so udev can add its start-message to dmesg
+ [ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11
+
+ # Not provided by sysfs but needed
+ ln -snf /proc/self/fd /dev/fd
+ ln -snf fd/0 /dev/stdin
+ ln -snf fd/1 /dev/stdout
+ ln -snf fd/2 /dev/stderr
+ [ -e /proc/kcore ] && ln -snf /proc/kcore /dev/core
+
+ # Create problematic directories
+ mkdir -p /dev/pts /dev/shm
+ return 0
+}
+
+start() {
+ mount_dev_directory || return 1
+ seed_dev
+}
diff --git a/main/busybox-initscripts/mdev.conf b/main/busybox-initscripts/mdev.conf
new file mode 100644
index 0000000000..430e306ae7
--- /dev/null
+++ b/main/busybox-initscripts/mdev.conf
@@ -0,0 +1,110 @@
+#
+# This is a sample mdev.conf.
+#
+
+# Devices:
+# Syntax: %s %d:%d %s
+# devices user:group mode
+
+# null does already exist; therefore ownership has to be changed with command
+null root:root 0666 @chmod 666 $MDEV
+zero root:root 0666
+grsec root:root 0660
+full root:root 0666
+
+random root:root 0666
+urandom root:root 0444
+hwrandom root:root 0660
+
+# console does already exist; therefore ownership has to be changed with command
+#console root:tty 0600 @chmod 600 $MDEV && mkdir -p vc && ln -sf ../$MDEV vc/0
+console root:tty 0600 @mkdir -pm 755 fd && cd fd && for x in 0 1 2 3 ; do ln -sf /proc/self/fd/$x $x; done
+# load frambuffer console when first frambuffer is found
+fb0 root:video 0660 @modprobe fbcon
+
+fd0 root:floppy 0660
+kmem root:root 0640
+mem root:root 0640
+port root:root 0640
+ptmx root:tty 0666
+
+# ram.*
+ram([0-9]*) root:disk 0660 >rd/%1
+loop([0-9]+) root:disk 0660 >loop/%1
+sd[a-z].* root:disk 0660 */lib/mdev/usbdisk_link
+hd[a-z][0-9]* root:disk 0660 */lib/mdev/ide_links
+md[0-9] root:disk 0660
+
+tty root:tty 0666
+tty[0-9] root:root 0600
+tty[0-9][0-9] root:tty 0660
+ttyS[0-9]* root:uucp 0660
+pty.* root:tty 0660
+vcs[0-9]* root:tty 0660
+vcsa[0-9]* root:tty 0660
+
+
+ttyLTM[0-9] root:dialout 0660 @ln -sf $MDEV modem
+ttySHSF[0-9] root:dialout 0660 @ln -sf $MDEV modem
+slamr root:dialout 0660 @ln -sf $MDEV slamr0
+slusb root:dialout 0660 @ln -sf $MDEV slusb0
+fuse root:root 0666
+
+# dri device
+card[0-9] root:video 0660 =dri/
+
+# alsa sound devices and audio stuff
+pcm.* root:audio 0660 =snd/
+control.* root:audio 0660 =snd/
+midi.* root:audio 0660 =snd/
+seq root:audio 0660 =snd/
+timer root:audio 0660 =snd/
+
+adsp root:audio 0660 >sound/
+audio root:audio 0660 >sound/
+dsp root:audio 0660 >sound/
+mixer root:audio 0660 >sound/
+sequencer.* root:audio 0660 >sound/
+
+# misc stuff
+agpgart root:root 0660 >misc/
+psaux root:root 0660 >misc/
+rtc root:root 0664 >misc/
+
+# input stuff
+event[0-9]+ root:root 0640 =input/
+mice root:root 0640 =input/
+mouse[0-9] root:root 0640 =input/
+ts[0-9] root:root 0600 =input/
+
+# v4l stuff
+vbi[0-9] root:video 0660 >v4l/
+video[0-9] root:video 0660 >v4l/
+
+# dvb stuff
+dvb.* root:video 0660 */lib/mdev/dvbdev
+
+# load drivers for usb devices
+usbdev[0-9].[0-9] root:root 0660 */lib/mdev/usbdev
+usbdev[0-9].[0-9]_.* root:root 0660
+
+# net devices
+tun[0-9]* root:root 0600 =net/
+tap[0-9]* root:root 0600 =net/
+
+# zaptel devices
+zap(.*) root:dialout 0660 =zap/%1
+dahdi!(.*) root:dialout 0660 =dahdi/%1
+
+# raid controllers
+cciss!(.*) root:disk 0660 =cciss/%1
+ida!(.*) root:disk 0660 =ida/%1
+rd!(.*) root:disk 0660 =rd/%1
+
+sr0 root:cdrom 0660 @ln -sf $MDEV cdrom
+
+# hpilo
+hpilo!(.*) root:root 0660 =hpilo/%1
+
+# xen stuff
+xvd[a-z] root:root 0660 */lib/mdev/xvd_links
diff --git a/main/busybox-initscripts/mdev.initd b/main/busybox-initscripts/mdev.initd
new file mode 100644
index 0000000000..e9309c7006
--- /dev/null
+++ b/main/busybox-initscripts/mdev.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+
+depend() {
+ provide dev
+ need sysfs mdev-mount
+ before checkfs fsck
+ keyword novserver
+}
+
+start() {
+ # check if udev is specified on cmd line
+ if get_bootparam "udev"; then
+ ewarn "Skipping mdev as udev requested in kernel cmdline"
+ return 0
+ fi
+
+ ebegin "Starting busybox mdev"
+ mkdir -p /dev
+
+ # use mdev for hotplug
+ echo "/sbin/mdev" > /proc/sys/kernel/hotplug
+
+ # create devices
+ mdev -s
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping busybox mdev"
+ echo "" > /proc/sys/kernel/hotplug
+ eend
+}
+
diff --git a/main/busybox-initscripts/rdate.confd b/main/busybox-initscripts/rdate.confd
new file mode 100644
index 0000000000..93c6786169
--- /dev/null
+++ b/main/busybox-initscripts/rdate.confd
@@ -0,0 +1,2 @@
+# Set the ntp server here
+NTP_HOST=pool.net.org
diff --git a/main/busybox-initscripts/rdate.initd b/main/busybox-initscripts/rdate.initd
new file mode 100644
index 0000000000..3d31de855d
--- /dev/null
+++ b/main/busybox-initscripts/rdate.initd
@@ -0,0 +1,17 @@
+#!/sbin/runscript
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ if [ -z "$NTP_HOST" ] ; then
+ eerror "Please set NTP_HOST in /etc/conf.d/rdate"
+ return 1
+ fi
+ ebegin "Running busybox rdate"
+ rdate "$NTP_HOST"
+ eend $?
+}
+
diff --git a/main/busybox-initscripts/syslog.confd b/main/busybox-initscripts/syslog.confd
new file mode 100644
index 0000000000..5f23b819d5
--- /dev/null
+++ b/main/busybox-initscripts/syslog.confd
@@ -0,0 +1 @@
+SYSLOGD_OPTS=""
diff --git a/main/busybox-initscripts/syslog.initd b/main/busybox-initscripts/syslog.initd
new file mode 100644
index 0000000000..86050f1afe
--- /dev/null
+++ b/main/busybox-initscripts/syslog.initd
@@ -0,0 +1,19 @@
+#!/sbin/runscript
+
+depend() {
+ need clock hostname klogd localmount
+ provide logger
+}
+
+start() {
+ ebegin "Starting busybox system logging"
+ start-stop-daemon --start --exec /sbin/syslogd -- ${SYSLOGD_OPTS}
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping busybox system logging"
+ start-stop-daemon --stop --exec /sbin/syslogd
+ eend $?
+}
+
diff --git a/main/busybox-initscripts/usbdev b/main/busybox-initscripts/usbdev
new file mode 100644
index 0000000000..ea5b915573
--- /dev/null
+++ b/main/busybox-initscripts/usbdev
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+# script is buggy; until patched just do exit 0
+#exit 0
+
+# add zeros to device or bus
+add_zeros () {
+ case "$(echo $1 | wc -L)" in
+ 1) echo "00$1" ;;
+ 2) echo "0$1" ;;
+ *) echo "$1"
+ esac
+ exit 0
+}
+
+
+# bus and device dirs in /sys
+USB_PATH=$(echo $MDEV | sed -e 's/usbdev\([0-9]\).[0-9]/usb\1/')
+USB_PATH=$(find /sys/devices -type d -name "$USB_PATH")
+USB_DEV_DIR=$(echo $MDEV | sed -e 's/usbdev\([0-9]\).\([0-9]\)/\1-\2/')
+
+# dir names in /dev
+BUS=$(add_zeros $(echo $MDEV | sed -e 's/^usbdev\([0-9]\).[0-9]/\1/'))
+USB_DEV=$(add_zeros $(echo $MDEV | sed -e 's/^usbdev[0-9].\([0-9]\)/\1/'))
+
+
+# try to load the proper driver for usb devices
+case "$ACTION" in
+ add|"")
+ # load usb bus driver
+ for i in $USB_PATH/*/modalias ; do
+ modprobe `cat $i` 2>/dev/null
+ done
+ # load usb device driver if existent
+ if [ -d $USB_PATH/$USB_DEV_DIR ]; then
+ for i in $USB_PATH/$USB_DEV_DIR/*/modalias ; do
+ modprobe `cat $i` 2>/dev/null
+ done
+ fi
+ # move usb device file
+ mkdir -p bus/usb/$BUS
+ mv $MDEV bus/usb/$BUS/$USB_DEV
+ ;;
+ remove)
+ # unload device driver, if device dir is existent
+ if [ -d $USB_PATH/$USB_DEV_DIR ]; then
+ for i in $USB_PATH/$USB_DEV_DIR/*/modalias ; do
+ modprobe -r `cat $i` 2>/dev/null
+ done
+ fi
+ # unload usb bus driver. Does this make sense?
+ # what happens, if two usb devices are plugged in
+ # and one is removed?
+ for i in $USB_PATH/*/modalias ; do
+ modprobe -r `cat $i` 2>/dev/null
+ done
+ # remove device file and possible empty dirs
+ rm -f bus/usb/$BUS/$USB_DEV
+ rmdir bus/usb/$BUS/ 2>/dev/null
+ rmdir bus/usb/ 2>/dev/null
+ rmdir bus/ 2>/dev/null
+esac
diff --git a/main/busybox-initscripts/usbdisk_link b/main/busybox-initscripts/usbdisk_link
new file mode 100644
index 0000000000..750242bb5c
--- /dev/null
+++ b/main/busybox-initscripts/usbdisk_link
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# NOTE: since mdev -s only provide $MDEV, don't depend on any hotplug vars.
+
+current=$(readlink usbdisk)
+
+if [ "$current" = "$MDEV" ] && [ "$ACTION" = "remove" ]; then
+ rm -f usbdisk usba1
+fi
+[ -n "$current" ] && exit
+
+if [ -e /sys/block/$MDEV ]; then
+ SYSDEV=$(readlink -f /sys/block/$MDEV/device)
+ # if /sys device path contains '/usb[0-9]' then we assume its usb
+ # also, if its an usb without partitions we require FAT
+ if [ "${SYSDEV##*/usb[0-9]}" != "$SYSDEV" ]; then
+ # do not create link if there is not FAT
+ dd if=/dev/$MDEV bs=512 count=1 2>/dev/null | strings | grep FAT >/dev/null || exit 0
+
+ ln -sf $MDEV usbdisk
+ # keep this for compat. people have it in fstab
+ ln -sf $MDEV usba1
+ fi
+
+elif [ -e /sys/block/*/$MDEV ] ; then
+ PARENT=$(dirname /sys/block/*/$MDEV)
+ SYSDEV=$(readlink -f $PARENT/device)
+ if [ "${SYSDEV##*/usb[0-9]}" != "$SYSDEV" ]; then
+ ln -sf $MDEV usbdisk
+ # keep this for compat. people have it in fstab
+ ln -sf $MDEV usba1
+ fi
+fi
+
diff --git a/main/busybox-initscripts/watchdog.confd b/main/busybox-initscripts/watchdog.confd
new file mode 100644
index 0000000000..5cfd2c2cc4
--- /dev/null
+++ b/main/busybox-initscripts/watchdog.confd
@@ -0,0 +1,3 @@
+#WATCHDOG_OPTS="-t 30"
+WATCHDOG_DEV=""
+
diff --git a/main/busybox-initscripts/watchdog.initd b/main/busybox-initscripts/watchdog.initd
new file mode 100644
index 0000000000..7363bb7553
--- /dev/null
+++ b/main/busybox-initscripts/watchdog.initd
@@ -0,0 +1,25 @@
+#!/sbin/runscript
+
+depend() {
+ need dev
+ after hwdrivers
+}
+
+start() {
+ if ! [ -n "$WATCHDOG_DEV" ]; then
+ eerror "WATCHDOG_DEV is not set"
+ return 1
+ fi
+
+ ebegin "Starting busybox watchdog"
+ start-stop-daemon --start --exec /sbin/watchdog \
+ -- $WATCHDOG_OPTS $WATCHDOG_DEV
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping busybox watchdog"
+ start-stop-daemon --stop --exec /sbin/watchdog
+ eend $?
+}
+
diff --git a/main/busybox-initscripts/xvd_links b/main/busybox-initscripts/xvd_links
new file mode 100644
index 0000000000..8874d86916
--- /dev/null
+++ b/main/busybox-initscripts/xvd_links
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+[ -f /sys/block/$MDEV/capability ] || exit
+
+caps="0x`cat /sys/block/$MDEV/capability`"
+
+if [ $(($caps & 8)) -gt 0 ]; then
+ case $ACTION in
+ add|"") ln -sf $MDEV cdrom ;;
+ remove) [ "`readlink cdrom 2>/dev/null`" = $MDEV ] && rm -f cdrom ;;
+ esac
+fi
diff --git a/main/busybox/APKBUILD b/main/busybox/APKBUILD
new file mode 100644
index 0000000000..ca08551d19
--- /dev/null
+++ b/main/busybox/APKBUILD
@@ -0,0 +1,91 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=busybox
+pkgver=1.18.4
+pkgrel=4
+_bbsuidver=0.6
+pkgdesc="Size optimized toolbox of many common UNIX utilities"
+url=http://busybox.net
+arch="all"
+license="GPL-2"
+depends=
+install="$pkgname.post-install $pkgname.post-upgrade"
+subpackages="$pkgname-static"
+triggers="busybox.trigger:/bin /usr/bin /sbin /usr/sbin /lib/modules/*"
+source="http://busybox.net/downloads/$pkgname-$pkgver.tar.bz2
+ http://git.alpinelinux.org/cgit/bbsuid.git/snapshot/bbsuid-$_bbsuidver.tar.bz2
+ http://busybox.net/downloads/fixes-1.18.4/busybox-1.18.4-fuser.patch
+ http://busybox.net/downloads/fixes-1.18.4/busybox-1.18.4-hush.patch
+ $pkgname-1.11.1-bb.patch
+ busybox-uname-is-not-gnu.patch
+ loginutils-sha512.patch
+ busyboxconfig"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+_bbsuid="$srcdir"/bbsuid-$_bbsuidver
+_config="$srcdir"/busyboxconfig
+prepare() {
+ cd "$_builddir"
+ #patches
+ for i in ../*.patch; do
+ msg "Applying $i"
+ if ! patch -p1 -i $i; then
+ error "$i failed"
+ return 1
+ fi
+ done
+
+ sed -i -e 's/(ip, _BB_DIR_BIN/(ip, _BB_DIR_SBIN/' \
+ -e 's/(lspci, _BB_DIR_USR_BIN/(lspci, _BB_DIR_USR_SBIN/' \
+ -e 's/(vi, _BB_DIR_BIN/(vi, _BB_DIR_USR_BIN/' \
+ include/applets.src.h || return 1
+}
+
+build() {
+ cd "$_bbsuid"
+ make || return 1
+
+ cd "$_builddir"
+ msg "Building static busybox"
+ sed -e "s/.*CONFIG_PIE.*/\# CONFIG_PIE is not set/" \
+ -e "s/.*CONFIG_STATIC.*/CONFIG_STATIC=y/" \
+ "$_config" > .config
+ make silentoldconfig || return 1
+ make || return 1
+ mv busybox busybox.static
+
+ # build dynamic
+ msg "Building dynamic busybox"
+ cp "$_config" .config
+ make silentoldconfig || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_bbsuid"
+ make install DESTDIR="$pkgdir" || return 1
+
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/sbin "$pkgdir"/usr/bin "$pkgdir"/tmp \
+ "$pkgdir"/var/cache/misc "$pkgdir"/bin "$pkgdir"/sbin
+ chmod 1777 "$pkgdir"/tmp
+ install -m755 busybox "$pkgdir"/bin/busybox
+ # we need /bin/sh to be able to execute post-install
+ ln -s /bin/busybox "$pkgdir"/bin/sh
+}
+
+static() {
+ triggers=
+ mkdir -p "$subpkgdir"/bin
+ install -m755 "$_builddir"/busybox.static \
+ "$subpkgdir"/bin/busybox.static
+
+}
+
+md5sums="b03c5b46ced732679e525a920a1a62f5 busybox-1.18.4.tar.bz2
+968b3a058db04f95e9c4cdb44d7d3ddb bbsuid-0.6.tar.bz2
+67a8bf1b82480bc36768d51c18e5a280 busybox-1.18.4-fuser.patch
+a81f2d7d3bdf1a35ab77c4414a530d38 busybox-1.18.4-hush.patch
+4c0f3b486eaa0674961b7ddcd0c60a9b busybox-1.11.1-bb.patch
+b5375210f13fd6e1ca61a565e8fabd35 busybox-uname-is-not-gnu.patch
+d21d70d590e9e04bfc65ecb23b9d1617 loginutils-sha512.patch
+cf688759721a35137c9654b995b186c5 busyboxconfig"
diff --git a/main/busybox/busybox-1.11.1-bb.patch b/main/busybox/busybox-1.11.1-bb.patch
new file mode 100644
index 0000000000..bb858cacd8
--- /dev/null
+++ b/main/busybox/busybox-1.11.1-bb.patch
@@ -0,0 +1,12 @@
+diff -ru busybox-1.11.1.orig/shell/ash.c busybox-1.11.1/shell/ash.c
+--- busybox-1.11.1.orig/shell/ash.c 2008-07-28 09:04:29 +0000
++++ busybox-1.11.1/shell/ash.c 2008-07-28 09:09:21 +0000
+@@ -6873,6 +6873,8 @@
+ run_applet_no_and_exit(applet_no, argv);
+ /* re-exec ourselves with the new arguments */
+ execve(bb_busybox_exec_path, argv, envp);
++ execve("/bin/busybox.static",argv,envp);
++ execve("/bin/busybox",argv,envp);
+ /* If they called chroot or otherwise made the binary no longer
+ * executable, fall through */
+ }
diff --git a/main/busybox/busybox-uname-is-not-gnu.patch b/main/busybox/busybox-uname-is-not-gnu.patch
new file mode 100644
index 0000000000..95b31394c3
--- /dev/null
+++ b/main/busybox/busybox-uname-is-not-gnu.patch
@@ -0,0 +1,20 @@
+--- busybox-1.18.2.orig/coreutils/uname.c
++++ busybox-1.18.2/coreutils/uname.c
+@@ -56,7 +56,7 @@
+ struct utsname name;
+ char processor[sizeof(((struct utsname*)NULL)->machine)];
+ char platform[sizeof(((struct utsname*)NULL)->machine)];
+- char os[sizeof("GNU/Linux")];
++ char os[sizeof("Linux")];
+ } uname_info_t;
+
+ static const char options[] ALIGN1 = "snrvmpioa";
+@@ -123,7 +123,7 @@
+ #endif
+ strcpy(uname_info.processor, unknown_str);
+ strcpy(uname_info.platform, unknown_str);
+- strcpy(uname_info.os, "GNU/Linux");
++ strcpy(uname_info.os, "Linux");
+ #if 0
+ /* Fedora does something like this */
+ strcpy(uname_info.processor, uname_info.name.machine);
diff --git a/main/busybox/busybox.post-install b/main/busybox/busybox.post-install
new file mode 100644
index 0000000000..8baed730c6
--- /dev/null
+++ b/main/busybox/busybox.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+/bin/busybox --install -s
diff --git a/main/busybox/busybox.post-upgrade b/main/busybox/busybox.post-upgrade
new file mode 120000
index 0000000000..1f4b450e5e
--- /dev/null
+++ b/main/busybox/busybox.post-upgrade
@@ -0,0 +1 @@
+busybox.post-install \ No newline at end of file
diff --git a/main/busybox/busybox.trigger b/main/busybox/busybox.trigger
new file mode 100644
index 0000000000..39cc6b4411
--- /dev/null
+++ b/main/busybox/busybox.trigger
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+do_bb_install=
+
+for i in "$@"; do
+ case "$i" in
+ /lib/modules/*)
+ if [ -d "$i" ]; then
+ /bin/busybox depmod ${i#/lib/modules/}
+ fi
+ ;;
+ *) do_bb_install=yes;;
+ esac
+done
+
+if [ -n "$do_bb_install" ]; then
+ /bin/bbsuid --install
+ /bin/busybox --install -s
+fi
+
diff --git a/main/busybox/busyboxconfig b/main/busybox/busyboxconfig
new file mode 100644
index 0000000000..b55736846d
--- /dev/null
+++ b/main/busybox/busyboxconfig
@@ -0,0 +1,986 @@
+#
+# Automatically generated make config: don't edit
+# Busybox version: 1.18.2
+# Fri Feb 4 18:18:10 2011
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+CONFIG_DESKTOP=y
+CONFIG_EXTRA_COMPAT=y
+# CONFIG_INCLUDE_SUSv2 is not set
+# CONFIG_USE_PORTABLE_CODE is not set
+CONFIG_PLATFORM_LINUX=y
+CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
+# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+CONFIG_SHOW_USAGE=y
+CONFIG_FEATURE_VERBOSE_USAGE=y
+CONFIG_FEATURE_COMPRESS_USAGE=y
+CONFIG_FEATURE_INSTALLER=y
+# CONFIG_INSTALL_NO_USR is not set
+# CONFIG_LOCALE_SUPPORT is not set
+CONFIG_UNICODE_SUPPORT=y
+# CONFIG_UNICODE_USING_LOCALE is not set
+CONFIG_FEATURE_CHECK_UNICODE_IN_ENV=y
+CONFIG_SUBST_WCHAR=63
+CONFIG_LAST_SUPPORTED_WCHAR=767
+# CONFIG_UNICODE_COMBINING_WCHARS is not set
+# CONFIG_UNICODE_WIDE_WCHARS is not set
+# CONFIG_UNICODE_BIDI_SUPPORT is not set
+# CONFIG_UNICODE_NEUTRAL_TABLE is not set
+# CONFIG_UNICODE_PRESERVE_BROKEN is not set
+CONFIG_LONG_OPTS=y
+CONFIG_FEATURE_DEVPTS=y
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_WTMP=y
+CONFIG_FEATURE_UTMP=y
+CONFIG_FEATURE_PIDFILE=y
+CONFIG_FEATURE_SUID=y
+# CONFIG_FEATURE_SUID_CONFIG is not set
+# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
+# CONFIG_SELINUX is not set
+# CONFIG_FEATURE_PREFER_APPLETS is not set
+CONFIG_BUSYBOX_EXEC_PATH="/bin/busybox"
+CONFIG_FEATURE_SYSLOG=y
+# CONFIG_FEATURE_HAVE_RPC is not set
+
+#
+# Build Options
+#
+# CONFIG_STATIC is not set
+CONFIG_PIE=y
+# CONFIG_NOMMU is not set
+# CONFIG_BUILD_LIBBUSYBOX is not set
+# CONFIG_FEATURE_INDIVIDUAL is not set
+# CONFIG_FEATURE_SHARED_BUSYBOX is not set
+CONFIG_LFS=y
+CONFIG_CROSS_COMPILER_PREFIX=""
+CONFIG_EXTRA_CFLAGS=""
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_WERROR is not set
+CONFIG_NO_DEBUG_LIB=y
+# CONFIG_DMALLOC is not set
+# CONFIG_EFENCE is not set
+
+#
+# Installation Options ("make install" behavior)
+#
+# CONFIG_INSTALL_APPLET_SYMLINKS is not set
+# CONFIG_INSTALL_APPLET_HARDLINKS is not set
+# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
+CONFIG_INSTALL_APPLET_DONT=y
+# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
+# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
+# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
+CONFIG_PREFIX="/home/ncopa/aports/main/busybox/pkg/busybox"
+
+#
+# Busybox Library Tuning
+#
+CONFIG_PASSWORD_MINLEN=6
+CONFIG_MD5_SIZE_VS_SPEED=0
+CONFIG_FEATURE_FAST_TOP=y
+# CONFIG_FEATURE_ETC_NETWORKS is not set
+CONFIG_FEATURE_USE_TERMIOS=y
+CONFIG_FEATURE_EDITING=y
+CONFIG_FEATURE_EDITING_MAX_LEN=1024
+CONFIG_FEATURE_EDITING_VI=y
+CONFIG_FEATURE_EDITING_HISTORY=255
+CONFIG_FEATURE_EDITING_SAVEHISTORY=y
+CONFIG_FEATURE_TAB_COMPLETION=y
+CONFIG_FEATURE_USERNAME_COMPLETION=y
+CONFIG_FEATURE_EDITING_FANCY_PROMPT=y
+CONFIG_FEATURE_EDITING_ASK_TERMINAL=y
+CONFIG_FEATURE_NON_POSIX_CP=y
+# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
+CONFIG_FEATURE_COPYBUF_KB=16
+CONFIG_MONOTONIC_SYSCALL=y
+# CONFIG_IOCTL_HEX2STR_ERROR is not set
+CONFIG_FEATURE_HWIB=y
+
+#
+# Applets
+#
+
+#
+# Archival Utilities
+#
+# CONFIG_FEATURE_SEAMLESS_XZ is not set
+CONFIG_FEATURE_SEAMLESS_LZMA=y
+CONFIG_FEATURE_SEAMLESS_BZ2=y
+CONFIG_FEATURE_SEAMLESS_GZ=y
+CONFIG_FEATURE_SEAMLESS_Z=y
+# CONFIG_AR is not set
+# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
+# CONFIG_FEATURE_AR_CREATE is not set
+CONFIG_BUNZIP2=y
+CONFIG_BZIP2=y
+CONFIG_CPIO=y
+CONFIG_FEATURE_CPIO_O=y
+CONFIG_FEATURE_CPIO_P=y
+# CONFIG_DPKG is not set
+# CONFIG_DPKG_DEB is not set
+# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
+CONFIG_GUNZIP=y
+CONFIG_GZIP=y
+# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
+CONFIG_LZOP=y
+# CONFIG_LZOP_COMPR_HIGH is not set
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+CONFIG_TAR=y
+CONFIG_FEATURE_TAR_CREATE=y
+# CONFIG_FEATURE_TAR_AUTODETECT is not set
+CONFIG_FEATURE_TAR_FROM=y
+CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y
+CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y
+CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
+CONFIG_FEATURE_TAR_LONG_OPTIONS=y
+# CONFIG_FEATURE_TAR_TO_COMMAND is not set
+CONFIG_FEATURE_TAR_UNAME_GNAME=y
+CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y
+# CONFIG_FEATURE_TAR_SELINUX is not set
+# CONFIG_UNCOMPRESS is not set
+CONFIG_UNLZMA=y
+CONFIG_FEATURE_LZMA_FAST=y
+CONFIG_LZMA=y
+CONFIG_UNXZ=y
+# CONFIG_XZ is not set
+CONFIG_UNZIP=y
+
+#
+# Coreutils
+#
+CONFIG_BASENAME=y
+CONFIG_CAT=y
+CONFIG_DATE=y
+CONFIG_FEATURE_DATE_ISOFMT=y
+# CONFIG_FEATURE_DATE_NANO is not set
+CONFIG_FEATURE_DATE_COMPAT=y
+CONFIG_TEST=y
+CONFIG_FEATURE_TEST_64=y
+CONFIG_TR=y
+CONFIG_FEATURE_TR_CLASSES=y
+CONFIG_FEATURE_TR_EQUIV=y
+CONFIG_BASE64=y
+CONFIG_CAL=y
+CONFIG_CATV=y
+CONFIG_CHGRP=y
+CONFIG_CHMOD=y
+CONFIG_CHOWN=y
+CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y
+CONFIG_CHROOT=y
+CONFIG_CKSUM=y
+CONFIG_COMM=y
+CONFIG_CP=y
+CONFIG_FEATURE_CP_LONG_OPTIONS=y
+CONFIG_CUT=y
+CONFIG_DD=y
+CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set
+CONFIG_FEATURE_DD_IBS_OBS=y
+CONFIG_DF=y
+CONFIG_FEATURE_DF_FANCY=y
+CONFIG_DIRNAME=y
+CONFIG_DOS2UNIX=y
+CONFIG_UNIX2DOS=y
+CONFIG_DU=y
+CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
+CONFIG_ECHO=y
+CONFIG_FEATURE_FANCY_ECHO=y
+CONFIG_ENV=y
+# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set
+CONFIG_EXPAND=y
+# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set
+CONFIG_EXPR=y
+CONFIG_EXPR_MATH_SUPPORT_64=y
+CONFIG_FALSE=y
+CONFIG_FOLD=y
+CONFIG_FSYNC=y
+CONFIG_HEAD=y
+CONFIG_FEATURE_FANCY_HEAD=y
+CONFIG_HOSTID=y
+CONFIG_ID=y
+CONFIG_INSTALL=y
+# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set
+CONFIG_LENGTH=y
+CONFIG_LN=y
+# CONFIG_LOGNAME is not set
+CONFIG_LS=y
+CONFIG_FEATURE_LS_FILETYPES=y
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+CONFIG_FEATURE_LS_RECURSIVE=y
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+CONFIG_FEATURE_LS_USERNAME=y
+CONFIG_FEATURE_LS_COLOR=y
+CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
+CONFIG_MD5SUM=y
+CONFIG_MKDIR=y
+# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set
+CONFIG_MKFIFO=y
+CONFIG_MKNOD=y
+CONFIG_MV=y
+# CONFIG_FEATURE_MV_LONG_OPTIONS is not set
+CONFIG_NICE=y
+CONFIG_NOHUP=y
+CONFIG_OD=y
+CONFIG_PRINTENV=y
+CONFIG_PRINTF=y
+CONFIG_PWD=y
+CONFIG_READLINK=y
+CONFIG_FEATURE_READLINK_FOLLOW=y
+CONFIG_REALPATH=y
+CONFIG_RM=y
+CONFIG_RMDIR=y
+# CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set
+CONFIG_SEQ=y
+CONFIG_SHA1SUM=y
+CONFIG_SHA256SUM=y
+CONFIG_SHA512SUM=y
+CONFIG_SLEEP=y
+CONFIG_FEATURE_FANCY_SLEEP=y
+CONFIG_FEATURE_FLOAT_SLEEP=y
+CONFIG_SORT=y
+CONFIG_FEATURE_SORT_BIG=y
+CONFIG_SPLIT=y
+# CONFIG_FEATURE_SPLIT_FANCY is not set
+CONFIG_STAT=y
+CONFIG_FEATURE_STAT_FORMAT=y
+CONFIG_STTY=y
+CONFIG_SUM=y
+CONFIG_SYNC=y
+CONFIG_TAC=y
+CONFIG_TAIL=y
+CONFIG_FEATURE_FANCY_TAIL=y
+CONFIG_TEE=y
+CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
+CONFIG_TOUCH=y
+CONFIG_TRUE=y
+CONFIG_TTY=y
+CONFIG_UNAME=y
+CONFIG_UNEXPAND=y
+# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set
+CONFIG_UNIQ=y
+CONFIG_USLEEP=y
+# CONFIG_UUDECODE is not set
+CONFIG_UUENCODE=y
+CONFIG_WC=y
+# CONFIG_FEATURE_WC_LARGE is not set
+CONFIG_WHO=y
+CONFIG_WHOAMI=y
+CONFIG_YES=y
+
+#
+# Common options for cp and mv
+#
+CONFIG_FEATURE_PRESERVE_HARDLINKS=y
+
+#
+# Common options for ls, more and telnet
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+CONFIG_FEATURE_HUMAN_READABLE=y
+
+#
+# Common options for md5sum, sha1sum, sha256sum, sha512sum
+#
+CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
+
+#
+# Console Utilities
+#
+CONFIG_CHVT=y
+# CONFIG_FGCONSOLE is not set
+CONFIG_CLEAR=y
+CONFIG_DEALLOCVT=y
+CONFIG_DUMPKMAP=y
+CONFIG_KBD_MODE=y
+# CONFIG_LOADFONT is not set
+CONFIG_LOADKMAP=y
+CONFIG_OPENVT=y
+CONFIG_RESET=y
+CONFIG_RESIZE=y
+CONFIG_FEATURE_RESIZE_PRINT=y
+CONFIG_SETCONSOLE=y
+# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
+# CONFIG_SETFONT is not set
+# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set
+CONFIG_DEFAULT_SETFONT_DIR=""
+CONFIG_SETKEYCODES=y
+CONFIG_SETLOGCONS=y
+CONFIG_SHOWKEY=y
+# CONFIG_FEATURE_LOADFONT_PSF2 is not set
+# CONFIG_FEATURE_LOADFONT_RAW is not set
+
+#
+# Debian Utilities
+#
+CONFIG_MKTEMP=y
+CONFIG_PIPE_PROGRESS=y
+CONFIG_RUN_PARTS=y
+CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS=y
+# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
+# CONFIG_START_STOP_DAEMON is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
+CONFIG_WHICH=y
+
+#
+# Editors
+#
+CONFIG_PATCH=y
+CONFIG_AWK=y
+CONFIG_FEATURE_AWK_LIBM=y
+CONFIG_CMP=y
+CONFIG_DIFF=y
+# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set
+CONFIG_FEATURE_DIFF_DIR=y
+CONFIG_ED=y
+CONFIG_SED=y
+CONFIG_VI=y
+CONFIG_FEATURE_VI_MAX_LEN=1024
+CONFIG_FEATURE_VI_8BIT=y
+CONFIG_FEATURE_VI_COLON=y
+CONFIG_FEATURE_VI_YANKMARK=y
+CONFIG_FEATURE_VI_SEARCH=y
+CONFIG_FEATURE_VI_USE_SIGNALS=y
+CONFIG_FEATURE_VI_DOT_CMD=y
+CONFIG_FEATURE_VI_READONLY=y
+CONFIG_FEATURE_VI_SETOPTS=y
+CONFIG_FEATURE_VI_SET=y
+CONFIG_FEATURE_VI_WIN_RESIZE=y
+CONFIG_FEATURE_VI_ASK_TERMINAL=y
+CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
+CONFIG_FEATURE_ALLOW_EXEC=y
+
+#
+# Finding Utilities
+#
+CONFIG_FIND=y
+CONFIG_FEATURE_FIND_PRINT0=y
+CONFIG_FEATURE_FIND_MTIME=y
+CONFIG_FEATURE_FIND_MMIN=y
+CONFIG_FEATURE_FIND_PERM=y
+CONFIG_FEATURE_FIND_TYPE=y
+CONFIG_FEATURE_FIND_XDEV=y
+CONFIG_FEATURE_FIND_MAXDEPTH=y
+CONFIG_FEATURE_FIND_NEWER=y
+CONFIG_FEATURE_FIND_INUM=y
+CONFIG_FEATURE_FIND_EXEC=y
+CONFIG_FEATURE_FIND_USER=y
+CONFIG_FEATURE_FIND_GROUP=y
+CONFIG_FEATURE_FIND_NOT=y
+CONFIG_FEATURE_FIND_DEPTH=y
+CONFIG_FEATURE_FIND_PAREN=y
+CONFIG_FEATURE_FIND_SIZE=y
+CONFIG_FEATURE_FIND_PRUNE=y
+CONFIG_FEATURE_FIND_DELETE=y
+CONFIG_FEATURE_FIND_PATH=y
+CONFIG_FEATURE_FIND_REGEX=y
+# CONFIG_FEATURE_FIND_CONTEXT is not set
+CONFIG_FEATURE_FIND_LINKS=y
+CONFIG_GREP=y
+CONFIG_FEATURE_GREP_EGREP_ALIAS=y
+CONFIG_FEATURE_GREP_FGREP_ALIAS=y
+CONFIG_FEATURE_GREP_CONTEXT=y
+CONFIG_XARGS=y
+CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
+CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
+CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
+CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
+
+#
+# Init Utilities
+#
+# CONFIG_BOOTCHARTD is not set
+# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set
+# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set
+CONFIG_HALT=y
+# CONFIG_FEATURE_CALL_TELINIT is not set
+CONFIG_TELINIT_PATH=""
+CONFIG_INIT=y
+CONFIG_FEATURE_USE_INITTAB=y
+CONFIG_FEATURE_KILL_REMOVED=y
+CONFIG_FEATURE_KILL_DELAY=0
+CONFIG_FEATURE_INIT_SCTTY=y
+CONFIG_FEATURE_INIT_SYSLOG=y
+CONFIG_FEATURE_EXTRA_QUIET=y
+# CONFIG_FEATURE_INIT_COREDUMPS is not set
+CONFIG_FEATURE_INITRD=y
+CONFIG_INIT_TERMINAL_TYPE="linux"
+CONFIG_MESG=y
+
+#
+# Login/Password Management Utilities
+#
+CONFIG_ADD_SHELL=y
+CONFIG_REMOVE_SHELL=y
+CONFIG_FEATURE_SHADOWPASSWDS=y
+CONFIG_USE_BB_PWD_GRP=y
+CONFIG_USE_BB_SHADOW=y
+# CONFIG_USE_BB_CRYPT is not set
+# CONFIG_USE_BB_CRYPT_SHA is not set
+CONFIG_ADDUSER=y
+# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
+CONFIG_FEATURE_CHECK_NAMES=y
+CONFIG_FIRST_SYSTEM_ID=100
+CONFIG_LAST_SYSTEM_ID=999
+CONFIG_ADDGROUP=y
+# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set
+CONFIG_FEATURE_ADDUSER_TO_GROUP=y
+CONFIG_DELUSER=y
+CONFIG_DELGROUP=y
+CONFIG_FEATURE_DEL_USER_FROM_GROUP=y
+CONFIG_GETTY=y
+CONFIG_LOGIN=y
+# CONFIG_PAM is not set
+CONFIG_LOGIN_SCRIPTS=y
+CONFIG_FEATURE_NOLOGIN=y
+CONFIG_FEATURE_SECURETTY=y
+CONFIG_PASSWD=y
+CONFIG_FEATURE_PASSWD_WEAK_CHECK=y
+CONFIG_CRYPTPW=y
+CONFIG_CHPASSWD=y
+CONFIG_SU=y
+CONFIG_FEATURE_SU_SYSLOG=y
+CONFIG_FEATURE_SU_CHECKS_SHELLS=y
+# CONFIG_SULOGIN is not set
+CONFIG_VLOCK=y
+
+#
+# Linux Ext2 FS Progs
+#
+# CONFIG_CHATTR is not set
+CONFIG_FSCK=y
+# CONFIG_LSATTR is not set
+# CONFIG_TUNE2FS is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_MODINFO=y
+# CONFIG_MODPROBE_SMALL is not set
+# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set
+# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set
+CONFIG_INSMOD=y
+CONFIG_RMMOD=y
+CONFIG_LSMOD=y
+CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y
+CONFIG_MODPROBE=y
+CONFIG_FEATURE_MODPROBE_BLACKLIST=y
+CONFIG_DEPMOD=y
+
+#
+# Options common to multiple modutils
+#
+# CONFIG_FEATURE_2_4_MODULES is not set
+# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
+# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
+CONFIG_FEATURE_CHECK_TAINTED_MODULE=y
+CONFIG_FEATURE_MODUTILS_ALIAS=y
+CONFIG_FEATURE_MODUTILS_SYMBOLS=y
+CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
+CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
+
+#
+# Linux System Utilities
+#
+CONFIG_BLOCKDEV=y
+CONFIG_REV=y
+CONFIG_ACPID=y
+CONFIG_FEATURE_ACPID_COMPAT=y
+CONFIG_BLKID=y
+CONFIG_DMESG=y
+CONFIG_FEATURE_DMESG_PRETTY=y
+CONFIG_FBSET=y
+CONFIG_FEATURE_FBSET_FANCY=y
+CONFIG_FEATURE_FBSET_READMODE=y
+CONFIG_FDFLUSH=y
+CONFIG_FDFORMAT=y
+CONFIG_FDISK=y
+CONFIG_FDISK_SUPPORT_LARGE_DISKS=y
+CONFIG_FEATURE_FDISK_WRITABLE=y
+CONFIG_FEATURE_AIX_LABEL=y
+CONFIG_FEATURE_SGI_LABEL=y
+CONFIG_FEATURE_SUN_LABEL=y
+CONFIG_FEATURE_OSF_LABEL=y
+CONFIG_FEATURE_GPT_LABEL=y
+CONFIG_FEATURE_FDISK_ADVANCED=y
+CONFIG_FINDFS=y
+CONFIG_FLOCK=y
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+# CONFIG_MKFS_EXT2 is not set
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_FEATURE_MINIX2 is not set
+# CONFIG_MKFS_REISER is not set
+CONFIG_MKFS_VFAT=y
+CONFIG_GETOPT=y
+CONFIG_FEATURE_GETOPT_LONG=y
+CONFIG_HEXDUMP=y
+CONFIG_FEATURE_HEXDUMP_REVERSE=y
+CONFIG_HD=y
+CONFIG_HWCLOCK=y
+CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS=y
+CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS=y
+CONFIG_IPCRM=y
+CONFIG_IPCS=y
+CONFIG_LOSETUP=y
+CONFIG_LSPCI=y
+CONFIG_LSUSB=y
+CONFIG_MDEV=y
+CONFIG_FEATURE_MDEV_CONF=y
+CONFIG_FEATURE_MDEV_RENAME=y
+CONFIG_FEATURE_MDEV_RENAME_REGEXP=y
+CONFIG_FEATURE_MDEV_EXEC=y
+CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y
+CONFIG_MKSWAP=y
+CONFIG_FEATURE_MKSWAP_UUID=y
+CONFIG_MORE=y
+CONFIG_MOUNT=y
+CONFIG_FEATURE_MOUNT_FAKE=y
+CONFIG_FEATURE_MOUNT_VERBOSE=y
+CONFIG_FEATURE_MOUNT_HELPERS=y
+CONFIG_FEATURE_MOUNT_LABEL=y
+# CONFIG_FEATURE_MOUNT_NFS is not set
+CONFIG_FEATURE_MOUNT_CIFS=y
+CONFIG_FEATURE_MOUNT_FLAGS=y
+CONFIG_FEATURE_MOUNT_FSTAB=y
+# CONFIG_PIVOT_ROOT is not set
+CONFIG_RDATE=y
+CONFIG_RDEV=y
+CONFIG_READPROFILE=y
+# CONFIG_RTCWAKE is not set
+# CONFIG_SCRIPT is not set
+# CONFIG_SCRIPTREPLAY is not set
+# CONFIG_SETARCH is not set
+CONFIG_SWAPONOFF=y
+CONFIG_FEATURE_SWAPON_PRI=y
+CONFIG_SWITCH_ROOT=y
+CONFIG_UMOUNT=y
+CONFIG_FEATURE_UMOUNT_ALL=y
+
+#
+# Common options for mount/umount
+#
+CONFIG_FEATURE_MOUNT_LOOP=y
+CONFIG_FEATURE_MOUNT_LOOP_CREATE=y
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+CONFIG_VOLUMEID=y
+
+#
+# Filesystem/Volume identification
+#
+CONFIG_FEATURE_VOLUMEID_EXT=y
+CONFIG_FEATURE_VOLUMEID_BTRFS=y
+CONFIG_FEATURE_VOLUMEID_REISERFS=y
+CONFIG_FEATURE_VOLUMEID_FAT=y
+# CONFIG_FEATURE_VOLUMEID_HFS is not set
+CONFIG_FEATURE_VOLUMEID_JFS=y
+CONFIG_FEATURE_VOLUMEID_XFS=y
+CONFIG_FEATURE_VOLUMEID_NTFS=y
+CONFIG_FEATURE_VOLUMEID_ISO9660=y
+CONFIG_FEATURE_VOLUMEID_UDF=y
+CONFIG_FEATURE_VOLUMEID_LUKS=y
+CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y
+CONFIG_FEATURE_VOLUMEID_CRAMFS=y
+# CONFIG_FEATURE_VOLUMEID_ROMFS is not set
+# CONFIG_FEATURE_VOLUMEID_SYSV is not set
+CONFIG_FEATURE_VOLUMEID_OCFS2=y
+CONFIG_FEATURE_VOLUMEID_LINUXRAID=y
+
+#
+# Miscellaneous Utilities
+#
+CONFIG_CONSPY=y
+CONFIG_NANDWRITE=y
+CONFIG_NANDDUMP=y
+# CONFIG_UBIATTACH is not set
+# CONFIG_UBIDETACH is not set
+CONFIG_ADJTIMEX=y
+CONFIG_BBCONFIG=y
+CONFIG_FEATURE_COMPRESS_BBCONFIG=y
+CONFIG_BEEP=y
+CONFIG_FEATURE_BEEP_FREQ=440
+CONFIG_FEATURE_BEEP_LENGTH_MS=30
+# CONFIG_CHAT is not set
+# CONFIG_FEATURE_CHAT_NOFAIL is not set
+# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
+# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set
+# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set
+# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set
+# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
+# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
+# CONFIG_CHRT is not set
+CONFIG_CROND=y
+CONFIG_FEATURE_CROND_D=y
+CONFIG_FEATURE_CROND_CALL_SENDMAIL=y
+CONFIG_FEATURE_CROND_DIR="/var/spool/cron"
+CONFIG_CRONTAB=y
+CONFIG_DC=y
+CONFIG_FEATURE_DC_LIBM=y
+# CONFIG_DEVFSD is not set
+# CONFIG_DEVFSD_MODLOAD is not set
+# CONFIG_DEVFSD_FG_NP is not set
+# CONFIG_DEVFSD_VERBOSE is not set
+# CONFIG_FEATURE_DEVFS is not set
+# CONFIG_DEVMEM is not set
+CONFIG_EJECT=y
+CONFIG_FEATURE_EJECT_SCSI=y
+CONFIG_FBSPLASH=y
+# CONFIG_FLASHCP is not set
+# CONFIG_FLASH_LOCK is not set
+# CONFIG_FLASH_UNLOCK is not set
+# CONFIG_FLASH_ERASEALL is not set
+CONFIG_IONICE=y
+CONFIG_INOTIFYD=y
+CONFIG_LAST=y
+CONFIG_FEATURE_LAST_SMALL=y
+# CONFIG_FEATURE_LAST_FANCY is not set
+CONFIG_LESS=y
+CONFIG_FEATURE_LESS_MAXLINES=9999999
+CONFIG_FEATURE_LESS_BRACKETS=y
+CONFIG_FEATURE_LESS_FLAGS=y
+CONFIG_FEATURE_LESS_MARKS=y
+CONFIG_FEATURE_LESS_REGEXP=y
+CONFIG_FEATURE_LESS_WINCH=y
+CONFIG_FEATURE_LESS_DASHCMD=y
+CONFIG_FEATURE_LESS_LINENUMS=y
+# CONFIG_HDPARM is not set
+# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
+# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
+# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
+# CONFIG_MAKEDEVS is not set
+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
+# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
+# CONFIG_MAN is not set
+CONFIG_MICROCOM=y
+CONFIG_MOUNTPOINT=y
+# CONFIG_MT is not set
+CONFIG_RAIDAUTORUN=y
+CONFIG_READAHEAD=y
+CONFIG_RFKILL=y
+# CONFIG_RUNLEVEL is not set
+# CONFIG_RX is not set
+CONFIG_SETSID=y
+CONFIG_STRINGS=y
+# CONFIG_TASKSET is not set
+# CONFIG_FEATURE_TASKSET_FANCY is not set
+CONFIG_TIME=y
+CONFIG_TIMEOUT=y
+CONFIG_TTYSIZE=y
+CONFIG_VOLNAME=y
+CONFIG_WALL=y
+CONFIG_WATCHDOG=y
+
+#
+# Networking Utilities
+#
+CONFIG_NBDCLIENT=y
+CONFIG_NC=y
+CONFIG_NC_SERVER=y
+CONFIG_NC_EXTRA=y
+CONFIG_NC_110_COMPAT=y
+CONFIG_FEATURE_IPV6=y
+# CONFIG_FEATURE_UNIX_LOCAL is not set
+CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y
+CONFIG_VERBOSE_RESOLUTION_ERRORS=y
+CONFIG_ARP=y
+CONFIG_ARPING=y
+CONFIG_BRCTL=y
+CONFIG_FEATURE_BRCTL_FANCY=y
+CONFIG_FEATURE_BRCTL_SHOW=y
+CONFIG_DNSD=y
+CONFIG_ETHER_WAKE=y
+CONFIG_FAKEIDENTD=y
+CONFIG_FTPD=y
+CONFIG_FEATURE_FTP_WRITE=y
+CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST=y
+CONFIG_FTPGET=y
+CONFIG_FTPPUT=y
+# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
+CONFIG_HOSTNAME=y
+CONFIG_HTTPD=y
+CONFIG_FEATURE_HTTPD_RANGES=y
+CONFIG_FEATURE_HTTPD_USE_SENDFILE=y
+CONFIG_FEATURE_HTTPD_SETUID=y
+CONFIG_FEATURE_HTTPD_BASIC_AUTH=y
+CONFIG_FEATURE_HTTPD_AUTH_MD5=y
+CONFIG_FEATURE_HTTPD_CGI=y
+CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y
+CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y
+CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y
+CONFIG_FEATURE_HTTPD_ERROR_PAGES=y
+CONFIG_FEATURE_HTTPD_PROXY=y
+CONFIG_FEATURE_HTTPD_GZIP=y
+CONFIG_IFCONFIG=y
+CONFIG_FEATURE_IFCONFIG_STATUS=y
+CONFIG_FEATURE_IFCONFIG_SLIP=y
+CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y
+CONFIG_FEATURE_IFCONFIG_HW=y
+CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y
+CONFIG_IFENSLAVE=y
+# CONFIG_IFPLUGD is not set
+CONFIG_IFUPDOWN=y
+CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate"
+CONFIG_FEATURE_IFUPDOWN_IP=y
+CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN=y
+# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
+CONFIG_FEATURE_IFUPDOWN_IPV4=y
+CONFIG_FEATURE_IFUPDOWN_IPV6=y
+# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
+CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP=y
+CONFIG_INETD=y
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
+# CONFIG_FEATURE_INETD_RPC is not set
+CONFIG_IP=y
+CONFIG_FEATURE_IP_ADDRESS=y
+CONFIG_FEATURE_IP_LINK=y
+CONFIG_FEATURE_IP_ROUTE=y
+CONFIG_FEATURE_IP_TUNNEL=y
+CONFIG_FEATURE_IP_RULE=y
+CONFIG_FEATURE_IP_SHORT_FORMS=y
+CONFIG_FEATURE_IP_RARE_PROTOCOLS=y
+CONFIG_IPADDR=y
+CONFIG_IPLINK=y
+CONFIG_IPROUTE=y
+CONFIG_IPTUNNEL=y
+CONFIG_IPRULE=y
+CONFIG_IPCALC=y
+CONFIG_FEATURE_IPCALC_FANCY=y
+# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
+CONFIG_NAMEIF=y
+CONFIG_FEATURE_NAMEIF_EXTENDED=y
+CONFIG_NETSTAT=y
+CONFIG_FEATURE_NETSTAT_WIDE=y
+CONFIG_FEATURE_NETSTAT_PRG=y
+CONFIG_NSLOOKUP=y
+CONFIG_NTPD=y
+CONFIG_FEATURE_NTPD_SERVER=y
+CONFIG_PING=y
+CONFIG_PING6=y
+CONFIG_FEATURE_FANCY_PING=y
+CONFIG_PSCAN=y
+CONFIG_ROUTE=y
+CONFIG_SLATTACH=y
+# CONFIG_TCPSVD is not set
+CONFIG_TELNET=y
+CONFIG_FEATURE_TELNET_TTYPE=y
+CONFIG_FEATURE_TELNET_AUTOLOGIN=y
+# CONFIG_TELNETD is not set
+# CONFIG_FEATURE_TELNETD_STANDALONE is not set
+# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set
+CONFIG_TFTP=y
+# CONFIG_TFTPD is not set
+
+#
+# Common options for tftp/tftpd
+#
+CONFIG_FEATURE_TFTP_GET=y
+CONFIG_FEATURE_TFTP_PUT=y
+CONFIG_FEATURE_TFTP_BLOCKSIZE=y
+CONFIG_FEATURE_TFTP_PROGRESS_BAR=y
+# CONFIG_TFTP_DEBUG is not set
+CONFIG_TRACEROUTE=y
+CONFIG_TRACEROUTE6=y
+CONFIG_FEATURE_TRACEROUTE_VERBOSE=y
+CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE=y
+CONFIG_FEATURE_TRACEROUTE_USE_ICMP=y
+CONFIG_TUNCTL=y
+CONFIG_FEATURE_TUNCTL_UG=y
+# CONFIG_UDHCPD is not set
+# CONFIG_DHCPRELAY is not set
+# CONFIG_DUMPLEASES is not set
+# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set
+CONFIG_DHCPD_LEASES_FILE=""
+CONFIG_UDHCPC=y
+CONFIG_FEATURE_UDHCPC_ARPING=y
+# CONFIG_FEATURE_UDHCP_PORT is not set
+CONFIG_UDHCP_DEBUG=0
+CONFIG_FEATURE_UDHCP_RFC3397=y
+CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script"
+CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80
+CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="-R -n"
+# CONFIG_UDPSVD is not set
+CONFIG_VCONFIG=y
+CONFIG_WGET=y
+CONFIG_FEATURE_WGET_STATUSBAR=y
+CONFIG_FEATURE_WGET_AUTHENTICATION=y
+# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set
+CONFIG_FEATURE_WGET_TIMEOUT=y
+# CONFIG_ZCIP is not set
+
+#
+# Print Utilities
+#
+# CONFIG_LPD is not set
+# CONFIG_LPR is not set
+# CONFIG_LPQ is not set
+
+#
+# Mail Utilities
+#
+CONFIG_MAKEMIME=y
+CONFIG_FEATURE_MIME_CHARSET="us-ascii"
+# CONFIG_POPMAILDIR is not set
+# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set
+CONFIG_REFORMIME=y
+CONFIG_FEATURE_REFORMIME_COMPAT=y
+CONFIG_SENDMAIL=y
+
+#
+# Process Utilities
+#
+CONFIG_IOSTAT=y
+CONFIG_MPSTAT=y
+CONFIG_PMAP=y
+CONFIG_POWERTOP=y
+CONFIG_SMEMCAP=y
+CONFIG_FREE=y
+CONFIG_FUSER=y
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+CONFIG_KILLALL5=y
+CONFIG_NMETER=y
+CONFIG_PGREP=y
+CONFIG_PIDOF=y
+CONFIG_FEATURE_PIDOF_SINGLE=y
+CONFIG_FEATURE_PIDOF_OMIT=y
+CONFIG_PKILL=y
+CONFIG_PS=y
+CONFIG_FEATURE_PS_WIDE=y
+CONFIG_FEATURE_PS_TIME=y
+CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y
+# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
+CONFIG_RENICE=y
+CONFIG_BB_SYSCTL=y
+CONFIG_TOP=y
+CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
+CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
+CONFIG_FEATURE_TOP_SMP_CPU=y
+# CONFIG_FEATURE_TOP_DECIMALS is not set
+CONFIG_FEATURE_TOP_SMP_PROCESS=y
+CONFIG_FEATURE_TOPMEM=y
+# CONFIG_FEATURE_SHOW_THREADS is not set
+CONFIG_UPTIME=y
+CONFIG_WATCH=y
+
+#
+# Runit Utilities
+#
+# CONFIG_RUNSV is not set
+# CONFIG_RUNSVDIR is not set
+# CONFIG_FEATURE_RUNSVDIR_LOG is not set
+# CONFIG_SV is not set
+CONFIG_SV_DEFAULT_SERVICE_DIR=""
+# CONFIG_SVLOGD is not set
+# CONFIG_CHPST is not set
+# CONFIG_SETUIDGID is not set
+# CONFIG_ENVUIDGID is not set
+# CONFIG_ENVDIR is not set
+# CONFIG_SOFTLIMIT is not set
+# CONFIG_CHCON is not set
+# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
+# CONFIG_GETENFORCE is not set
+# CONFIG_GETSEBOOL is not set
+# CONFIG_LOAD_POLICY is not set
+# CONFIG_MATCHPATHCON is not set
+# CONFIG_RESTORECON is not set
+# CONFIG_RUNCON is not set
+# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
+# CONFIG_SELINUXENABLED is not set
+# CONFIG_SETENFORCE is not set
+# CONFIG_SETFILES is not set
+# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
+# CONFIG_SETSEBOOL is not set
+# CONFIG_SESTATUS is not set
+
+#
+# Shells
+#
+CONFIG_ASH=y
+CONFIG_ASH_BASH_COMPAT=y
+CONFIG_ASH_JOB_CONTROL=y
+CONFIG_ASH_ALIAS=y
+CONFIG_ASH_GETOPTS=y
+CONFIG_ASH_BUILTIN_ECHO=y
+CONFIG_ASH_BUILTIN_PRINTF=y
+CONFIG_ASH_BUILTIN_TEST=y
+CONFIG_ASH_CMDCMD=y
+CONFIG_ASH_MAIL=y
+CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
+CONFIG_ASH_RANDOM_SUPPORT=y
+CONFIG_ASH_EXPAND_PRMT=y
+# CONFIG_CTTYHACK is not set
+# CONFIG_HUSH is not set
+# CONFIG_HUSH_BASH_COMPAT is not set
+# CONFIG_HUSH_BRACE_EXPANSION is not set
+# CONFIG_HUSH_HELP is not set
+# CONFIG_HUSH_INTERACTIVE is not set
+# CONFIG_HUSH_SAVEHISTORY is not set
+# CONFIG_HUSH_JOB is not set
+# CONFIG_HUSH_TICK is not set
+# CONFIG_HUSH_IF is not set
+# CONFIG_HUSH_LOOPS is not set
+# CONFIG_HUSH_CASE is not set
+# CONFIG_HUSH_FUNCTIONS is not set
+# CONFIG_HUSH_LOCAL is not set
+# CONFIG_HUSH_RANDOM_SUPPORT is not set
+# CONFIG_HUSH_EXPORT_N is not set
+# CONFIG_HUSH_MODE_X is not set
+# CONFIG_MSH is not set
+CONFIG_FEATURE_SH_IS_ASH=y
+# CONFIG_FEATURE_SH_IS_HUSH is not set
+# CONFIG_FEATURE_SH_IS_NONE is not set
+# CONFIG_FEATURE_BASH_IS_ASH is not set
+# CONFIG_FEATURE_BASH_IS_HUSH is not set
+CONFIG_FEATURE_BASH_IS_NONE=y
+CONFIG_SH_MATH_SUPPORT=y
+# CONFIG_SH_MATH_SUPPORT_64 is not set
+CONFIG_FEATURE_SH_EXTRA_QUIET=y
+# CONFIG_FEATURE_SH_STANDALONE is not set
+# CONFIG_FEATURE_SH_NOFORK is not set
+
+#
+# System Logging Utilities
+#
+CONFIG_SYSLOGD=y
+CONFIG_FEATURE_ROTATE_LOGFILE=y
+CONFIG_FEATURE_REMOTE_LOG=y
+CONFIG_FEATURE_SYSLOGD_DUP=y
+CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256
+CONFIG_FEATURE_IPC_SYSLOG=y
+CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16
+CONFIG_LOGREAD=y
+CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y
+CONFIG_KLOGD=y
+CONFIG_FEATURE_KLOGD_KLOGCTL=y
+CONFIG_LOGGER=y
diff --git a/main/busybox/loginutils-sha512.patch b/main/busybox/loginutils-sha512.patch
new file mode 100644
index 0000000000..7c5028d374
--- /dev/null
+++ b/main/busybox/loginutils-sha512.patch
@@ -0,0 +1,154 @@
+--- busybox-1.18.3/include/usage.src.h
++++ busybox.mod/include/usage.src.h
+@@ -2798,23 +2798,25 @@
+ "Change USER's password. If no USER is specified,\n" \
+ "changes the password for the current user.\n" \
+ "\nOptions:" \
+- "\n -a ALG Algorithm to use for password (des, md5)" /* ", sha1)" */ \
++ "\n -a ALG Algorithm to use for password (des, md5, sha512)" /* ", sha1)" */ \
+ "\n -d Delete password for the account" \
+ "\n -l Lock (disable) account" \
+ "\n -u Unlock (re-enable) account" \
+
+ #define chpasswd_trivial_usage \
+- IF_LONG_OPTS("[--md5|--encrypted]") IF_NOT_LONG_OPTS("[-m|-e]")
++ IF_LONG_OPTS("[--des|--md5|--encrypted]") IF_NOT_LONG_OPTS("[-d|-m|-e]")
+ #define chpasswd_full_usage "\n\n" \
+ "Read user:password from stdin and update /etc/passwd\n" \
+ "\nOptions:" \
+ IF_LONG_OPTS( \
+ "\n -e,--encrypted Supplied passwords are in encrypted form" \
+- "\n -m,--md5 Use MD5 encryption instead of DES" \
++ "\n -m,--md5 Use MD5 encryption instead of SHA512" \
++ "\n -d,--des Use DES encryption instead of SHA512" \
+ ) \
+ IF_NOT_LONG_OPTS( \
+ "\n -e Supplied passwords are in encrypted form" \
+- "\n -m Use MD5 encryption instead of DES" \
++ "\n -m Use MD5 encryption instead of SHA512" \
++ "\n -d Use DES encryption instead of SHA512" \
+ )
+
+ #define pgrep_trivial_usage \
+--- busybox-1.18.3/loginutils/chpasswd.c
++++ busybox.mod/loginutils/chpasswd.c
+@@ -11,11 +11,13 @@
+ static const char chpasswd_longopts[] ALIGN1 =
+ "encrypted\0" No_argument "e"
+ "md5\0" No_argument "m"
++ "des\0" No_argument "d"
+ ;
+ #endif
+
+-#define OPT_ENC 1
+-#define OPT_MD5 2
++#define OPT_ENC 1
++#define OPT_MD5 2
++#define OPT_DES 4
+
+ int chpasswd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+ int chpasswd_main(int argc UNUSED_PARAM, char **argv)
+@@ -28,9 +30,9 @@
+ if (getuid())
+ bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+
+- opt_complementary = "m--e:e--m";
++ opt_complementary = "m--e:e--m:d--e:e--d:m--d:d--m";
+ IF_LONG_OPTS(applet_long_options = chpasswd_longopts;)
+- opt = getopt32(argv, "em");
++ opt = getopt32(argv, "emd");
+
+ while ((name = xmalloc_fgetline(stdin)) != NULL) {
+ pass = strchr(name, ':');
+@@ -41,9 +43,13 @@
+ xuname2uid(name); /* dies if there is no such user */
+
+ if (!(opt & OPT_ENC)) {
+- rnd = crypt_make_salt(salt, 1, rnd);
+ if (opt & OPT_MD5) {
+ strcpy(salt, "$1$");
++ rnd = crypt_make_salt(salt + 3, 4, rnd);
++ } else if (opt & OPT_DES) {
++ rnd = crypt_make_salt(salt, 1, rnd);
++ } else { // OPT_SHA512
++ strcpy(salt, "$6$");
+ rnd = crypt_make_salt(salt + 3, 4, rnd);
+ }
+ pass = pw_encrypt(pass, salt, 0);
+--- busybox-1.18.3/loginutils/cryptpw.c
++++ busybox.mod/loginutils/cryptpw.c
+@@ -91,7 +91,7 @@
+ *salt_ptr++ = '$';
+ #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
+ if (opt_m[0] == 's') { /* sha */
+- salt[1] = '5' + (strcmp(opt_m, "sha512") == 0);
++ salt[1] = '6' + (strcmp(opt_m, "sha512") == 0);
+ len = 16/2;
+ }
+ #endif
+--- busybox-1.18.3/loginutils/passwd.c
++++ busybox.mod/loginutils/passwd.c
+@@ -12,6 +12,11 @@
+
+ static char* new_password(const struct passwd *pw, uid_t myuid, int algo)
+ {
++ enum {
++ STATE_ALGO_md5 = 0x10,
++ STATE_ALGO_des = 0x20,
++ STATE_ALGO_sha512 = 0x40,
++ };
+ char salt[sizeof("$N$XXXXXXXX")]; /* "$N$XXXXXXXX" or "XX" */
+ char *orig = (char*)"";
+ char *newp = NULL;
+@@ -51,10 +56,14 @@
+ goto err_ret;
+ }
+
+- crypt_make_salt(salt, 1, 0); /* des */
+- if (algo) { /* MD5 */
++ if (algo & STATE_ALGO_md5) { /* md5 */
+ strcpy(salt, "$1$");
+ crypt_make_salt(salt + 3, 4, 0);
++ } else if (algo & STATE_ALGO_des) { /* des */
++ crypt_make_salt(salt, 1, 0);
++ } else if (algo & STATE_ALGO_sha512) { /* sha512 */
++ strcpy(salt, "$6$");
++ crypt_make_salt(salt + 3, 4, 0);
+ }
+ /* pw_encrypt returns malloced str */
+ ret = pw_encrypt(newp, salt, 1);
+@@ -79,7 +88,8 @@
+ OPT_delete = 0x8, /* -d - delete password */
+ OPT_lud = 0xe,
+ STATE_ALGO_md5 = 0x10,
+- //STATE_ALGO_des = 0x20, not needed yet
++ STATE_ALGO_des = 0x20,
++ STATE_ALGO_sha512 = 0x40,
+ };
+ unsigned opt;
+ int rc;
+@@ -104,10 +114,12 @@
+ //argc -= optind;
+ argv += optind;
+
+- if (strcasecmp(opt_a, "des") != 0) /* -a */
++ if (strcasecmp(opt_a, "md5") == 0) /* -a */
+ opt |= STATE_ALGO_md5;
+- //else
+- // opt |= STATE_ALGO_des;
++ else if (strcasecmp(opt_a, "des") == 0)
++ opt |= STATE_ALGO_des;
++ else //if (strcasecmp(opt_a, "sha512") == 0)
++ opt |= STATE_ALGO_sha512;
+ myuid = getuid();
+ /* -l, -u, -d require root priv and username argument */
+ if ((opt & OPT_lud) && (myuid || !argv[0]))
+@@ -158,7 +170,7 @@
+ "locked password for %s", name);
+ }
+ printf("Changing password for %s\n", name);
+- newp = new_password(pw, myuid, opt & STATE_ALGO_md5);
++ newp = new_password(pw, myuid, opt);
+ if (!newp) {
+ logmode = LOGMODE_STDIO;
+ bb_error_msg_and_die("password for %s is unchanged", name);
diff --git a/main/bwm-ng/APKBUILD b/main/bwm-ng/APKBUILD
new file mode 100644
index 0000000000..16ade39aac
--- /dev/null
+++ b/main/bwm-ng/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bwm-ng
+pkgver=0.6
+pkgrel=2
+pkgdesc="A small and simple console-based live bandwidth monitor"
+url="http://www.gropp.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=
+makedepends="ncurses-dev"
+source="http://www.gropp.org/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-libstatgrab \
+ --with-procnetdev \
+ --with-ncurses \
+ --with-partitions
+
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+
+}
+md5sums="d3a02484fb7946371bfb4e10927cebfb bwm-ng-0.6.tar.gz"
diff --git a/main/byobu/APKBUILD b/main/byobu/APKBUILD
new file mode 100644
index 0000000000..263a51cd71
--- /dev/null
+++ b/main/byobu/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor:
+# Maintainer:
+pkgname=byobu
+pkgver=2.64
+pkgrel=1
+pkgdesc="enhancement of the GNU Screen"
+url="https://launchpad.net/byobu"
+arch="all"
+license="GPL-3"
+depends="screen python"
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://launchpad.net/byobu/trunk/$pkgver/+download/byobu_$pkgver.orig.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"
+ cp -a etc usr "$pkgdir"/
+}
+
+md5sums="54a0398ad8134dfb8914c49548be3f4e byobu_2.64.orig.tar.gz"
diff --git a/main/bzip2/APKBUILD b/main/bzip2/APKBUILD
new file mode 100644
index 0000000000..9538224809
--- /dev/null
+++ b/main/bzip2/APKBUILD
@@ -0,0 +1,74 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=bzip2
+pkgver=1.0.6
+pkgrel=1
+pkgdesc="A high-quality data compression program"
+url="http://sources.redhat.com/bzip2"
+arch="all"
+license="BZIP2"
+depends=""
+install="$pkgname.post-deinstall"
+source="http://www.bzip.org/$pkgver/$pkgname-$pkgver.tar.gz
+ bzip2-1.0.4-makefile-CFLAGS.patch
+ bzip2-1.0.6-saneso.patch
+ bzip2-1.0.4-man-links.patch
+ bzip2-1.0.2-progress.patch
+ bzip2-1.0.3-no-test.patch
+ bzip2-1.0.4-POSIX-shell.patch
+ "
+subpackages="$pkgname-dev $pkgname-doc libbz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+
+ # Fix man path
+ # Generate relative symlinks
+ sed -i \
+ -e 's:\$(PREFIX)/man:\$(PREFIX)/share/man:g' \
+ -e 's:ln -s -f $(PREFIX)/bin/:ln -s :' \
+ Makefile || return 1
+
+ # fixup broken version stuff
+ sed -i \
+ -e "s:1\.0\.4:$pkgver:" \
+ bzip2.1 bzip2.txt Makefile-libbz2_so manual.* || return 1
+
+}
+
+build () {
+ cd "$_builddir"
+ make -f Makefile-libbz2_so all || return 1
+ make all || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make PREFIX="$pkgdir"/usr install || return 1
+ install -D libbz2.so.$pkgver "$pkgdir"/usr/lib/libbz2.so.$pkgver
+ ln -s libbz2.so.$pkgver "$pkgdir"/usr/lib/libbz2.so
+ ln -s libbz2.so.$pkgver "$pkgdir"/usr/lib/libbz2.so.${pkgver%%.*}
+}
+
+libbz2() {
+ pkgdesc="Shared library for bz2"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/*.so.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="00b516f4704d4a7cb50a1d97e6e8e15b bzip2-1.0.6.tar.gz
+3675cd4db6affe64e1d7d40bc2ad4f26 bzip2-1.0.4-makefile-CFLAGS.patch
+d47a4aa8f08d101aa5aa0dd2030338d1 bzip2-1.0.6-saneso.patch
+fd13ef6bc55276c7e3adc346bde56cd1 bzip2-1.0.4-man-links.patch
+5f7a98f0aaaed6554126d30e28383ee0 bzip2-1.0.2-progress.patch
+804bd17c96297968a89fc4eddc9a6713 bzip2-1.0.3-no-test.patch
+55ac0e9be7821190b99376e0205707be bzip2-1.0.4-POSIX-shell.patch"
diff --git a/main/bzip2/bzip2-1.0.2-progress.patch b/main/bzip2/bzip2-1.0.2-progress.patch
new file mode 100644
index 0000000000..2f389cfac9
--- /dev/null
+++ b/main/bzip2/bzip2-1.0.2-progress.patch
@@ -0,0 +1,175 @@
+Ripped from Mandrake.
+
+http://bugs.gentoo.org/show_bug.cgi?id=82192
+
+--- bzip2-1.0.2.org/bzip2.1
++++ bzip2-1.0.2/bzip2.1
+@@ -235,6 +235,10 @@
+ Suppress non-essential warning messages. Messages pertaining to
+ I/O errors and other critical events will not be suppressed.
+ .TP
++.B \-p --show-progress
++Show percentage of input-file done and while compressing show the percentage
++of the original file the new file is.
++.TP
+ .B \-v --verbose
+ Verbose mode -- show the compression ratio for each file processed.
+ Further \-v's increase the verbosity level, spewing out lots of
+--- bzip2-1.0.2.org/bzip2.c
++++ bzip2-1.0.2/bzip2.c
+@@ -145,6 +145,7 @@
+ #include <signal.h>
+ #include <math.h>
+ #include <errno.h>
++#include <time.h>
+ #include <ctype.h>
+ #include "bzlib.h"
+
+@@ -301,6 +302,7 @@
+ Char progNameReally[FILE_NAME_LEN];
+ FILE *outputHandleJustInCase;
+ Int32 workFactor;
++Char showProgress;
+
+ static void panic ( Char* ) NORETURN;
+ static void ioError ( void ) NORETURN;
+@@ -425,6 +427,12 @@
+ UInt32 nbytes_in_lo32, nbytes_in_hi32;
+ UInt32 nbytes_out_lo32, nbytes_out_hi32;
+ Int32 bzerr, bzerr_dummy, ret;
++ double fileSize = 0; /* initialized to make the compiler stop crying */
++ /* double because big files might otherwhise give
++ * overflows. not long long since not all compilers
++ * support that one
++ */
++ time_t startTime, currentTime;
+
+ SET_BINARY_MODE(stream);
+ SET_BINARY_MODE(zStream);
+@@ -432,12 +440,21 @@
+ if (ferror(stream)) goto errhandler_io;
+ if (ferror(zStream)) goto errhandler_io;
+
++ if ((srcMode == SM_F2F || srcMode == SM_F2O) && showProgress == True) {
++ (void)fseek(stream, 0, SEEK_END);
++ fileSize = (double)ftell(stream);
++ rewind(stream);
++ if (verbosity >= 1)
++ fprintf(stderr, "Input-file size: %ld\n", (long)fileSize);
++ }
++
+ bzf = BZ2_bzWriteOpen ( &bzerr, zStream,
+ blockSize100k, verbosity, workFactor );
+ if (bzerr != BZ_OK) goto errhandler;
+
+ if (verbosity >= 2) fprintf ( stderr, "\n" );
+
++ time(&startTime);
+ while (True) {
+
+ if (myfeof(stream)) break;
+@@ -446,13 +463,32 @@
+ if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
+ if (bzerr != BZ_OK) goto errhandler;
+
++ if ((srcMode == SM_F2F || srcMode == SM_F2O) && showProgress == True)
++ {
++ time(&currentTime);
++
++ if ((currentTime - startTime) > 1) { /* show progress every 2 seconds */
++ double curInPos = (double)ftell(stream);
++ double curOutPos = (double)ftell(zStream);
++
++ startTime = currentTime;
++
++ fprintf(stderr, "%.2f%% done", (curInPos * 100.0) / fileSize);
++ if (srcMode == SM_F2F)
++ {
++ fprintf(stderr, ", new size: %.2f%%", (curOutPos * 100.0) / curInPos);
++ }
++
++ fprintf(stderr, " \r");
++ }
++ }
+ }
+
+ BZ2_bzWriteClose64 ( &bzerr, bzf, 0,
+ &nbytes_in_lo32, &nbytes_in_hi32,
+ &nbytes_out_lo32, &nbytes_out_hi32 );
+ if (bzerr != BZ_OK) goto errhandler;
+-
++
+ if (ferror(zStream)) goto errhandler_io;
+ ret = fflush ( zStream );
+ if (ret == EOF) goto errhandler_io;
+@@ -526,6 +562,8 @@
+ UChar unused[BZ_MAX_UNUSED];
+ Int32 nUnused;
+ UChar* unusedTmp;
++ double fileSize = 0; /* initialized to make the compiler stop crying */
++ time_t startTime, currentTime;
+
+ nUnused = 0;
+ streamNo = 0;
+@@ -533,9 +571,19 @@
+ SET_BINARY_MODE(stream);
+ SET_BINARY_MODE(zStream);
+
++ if ((srcMode == SM_F2F || srcMode == SM_F2O) && showProgress == True) {
++ long dummy = ftell(zStream);
++ (void)fseek(zStream, 0, SEEK_END);
++ fileSize = (double)ftell(zStream);
++ (void)fseek(zStream, dummy, SEEK_SET);
++ if (verbosity >= 1)
++ fprintf(stderr, "Input-file size: %ld\n", (long)fileSize);
++ }
++
+ if (ferror(stream)) goto errhandler_io;
+ if (ferror(zStream)) goto errhandler_io;
+
++ time(&startTime);
+ while (True) {
+
+ bzf = BZ2_bzReadOpen (
+@@ -551,6 +599,17 @@
+ if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
+ fwrite ( obuf, sizeof(UChar), nread, stream );
+ if (ferror(stream)) goto errhandler_io;
++
++ if ((srcMode == SM_F2F || srcMode == SM_F2O) && showProgress == True) {
++ time(&currentTime);
++ if ((currentTime - startTime) >= 2)
++ {
++ double curInPos = (double)ftell(zStream);
++ startTime = currentTime;
++
++ fprintf(stderr, "%.2f%% done\r", (curInPos * 100.0) / fileSize);
++ }
++ }
+ }
+ if (bzerr != BZ_STREAM_END) goto errhandler;
+
+@@ -1872,6 +1931,7 @@
+ deleteOutputOnInterrupt = False;
+ exitValue = 0;
+ i = j = 0; /* avoid bogus warning from egcs-1.1.X */
++ showProgress = False;
+
+ /*-- Set up signal handlers for mem access errors --*/
+ signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
+@@ -1949,6 +2009,7 @@
+ case 'k': keepInputFiles = True; break;
+ case 's': smallMode = True; break;
+ case 'q': noisy = False; break;
++ case 'p': showProgress = True; break;
+ case '1': blockSize100k = 1; break;
+ case '2': blockSize100k = 2; break;
+ case '3': blockSize100k = 3; break;
+@@ -1985,6 +2046,7 @@
+ if (ISFLAG("--keep")) keepInputFiles = True; else
+ if (ISFLAG("--small")) smallMode = True; else
+ if (ISFLAG("--quiet")) noisy = False; else
++ if (ISFLAG("--show-progress")) showProgress = True; else
+ if (ISFLAG("--version")) license(); else
+ if (ISFLAG("--license")) license(); else
+ if (ISFLAG("--exponential")) workFactor = 1; else
diff --git a/main/bzip2/bzip2-1.0.3-no-test.patch b/main/bzip2/bzip2-1.0.3-no-test.patch
new file mode 100644
index 0000000000..fc876d5044
--- /dev/null
+++ b/main/bzip2/bzip2-1.0.3-no-test.patch
@@ -0,0 +1,9 @@
+--- ./Makefile
++++ ./Makefile
+@@ -23,5 +23,5 @@
+ bzlib.o
+
+-all: libbz2.a bzip2 bzip2recover test
++all: libbz2.a bzip2 bzip2recover
+
+ bzip2: libbz2.a bzip2.o
diff --git a/main/bzip2/bzip2-1.0.4-POSIX-shell.patch b/main/bzip2/bzip2-1.0.4-POSIX-shell.patch
new file mode 100644
index 0000000000..a5916eaff5
--- /dev/null
+++ b/main/bzip2/bzip2-1.0.4-POSIX-shell.patch
@@ -0,0 +1,21 @@
+bzgrep uses !/bin/sh but then uses the bashism ${var//} so replace those
+with calls to sed so POSIX shells work
+
+http://bugs.gentoo.org/193365
+
+--- ./bzgrep
++++ ./bzgrep
+@@ -63,10 +63,9 @@
+ bzip2 -cdfq "$i" | $grep $opt "$pat"
+ r=$?
+ else
+- j=${i//\\/\\\\}
+- j=${j//|/\\|}
+- j=${j//&/\\&}
+- j=`printf "%s" "$j" | tr '\n' ' '`
++ # the backslashes here are doubled up as we have to escape each one for the
++ # shell and then escape each one for the sed expression
++ j=`printf "%s" "${i}" | sed -e 's:\\\\:\\\\\\\\:g' -e 's:[|]:\\\\|:g' -e 's:[&]:\\\\&:g' | tr '\n' ' '`
+ bzip2 -cdfq "$i" | $grep $opt "$pat" | sed "s|^|${j}:|"
+ r=$?
+ fi
diff --git a/main/bzip2/bzip2-1.0.4-makefile-CFLAGS.patch b/main/bzip2/bzip2-1.0.4-makefile-CFLAGS.patch
new file mode 100644
index 0000000000..cf146188c3
--- /dev/null
+++ b/main/bzip2/bzip2-1.0.4-makefile-CFLAGS.patch
@@ -0,0 +1,25 @@
+--- ./Makefile
++++ ./Makefile
+@@ -18,10 +18,9 @@
+ CC=gcc
+ AR=ar
+ RANLIB=ranlib
+-LDFLAGS=
+
+ BIGFILES=-D_FILE_OFFSET_BITS=64
+-CFLAGS=-Wall -Winline -O2 -g $(BIGFILES)
++CFLAGS+=-Wall -Winline $(BIGFILES) $(CPPFLAGS)
+
+ # Where you want it installed when you do 'make install'
+ PREFIX=/usr/local
+--- ./Makefile-libbz2_so
++++ ./Makefile-libbz2_so
+@@ -24,7 +24,7 @@
+ SHELL=/bin/sh
+ CC=gcc
+ BIGFILES=-D_FILE_OFFSET_BITS=64
+-CFLAGS=-fpic -fPIC -Wall -Winline -O2 -g $(BIGFILES)
++CFLAGS+=-fpic -fPIC -Wall -Winline $(BIGFILES) $(CPPFLAGS)
+
+ OBJS= blocksort.o \
+ huffman.o \
diff --git a/main/bzip2/bzip2-1.0.4-man-links.patch b/main/bzip2/bzip2-1.0.4-man-links.patch
new file mode 100644
index 0000000000..2427d6a7fb
--- /dev/null
+++ b/main/bzip2/bzip2-1.0.4-man-links.patch
@@ -0,0 +1,12 @@
+http://bugs.gentoo.org/172986
+
+--- bzip2-1.0.4/Makefile
++++ bzip2-1.0.4/Makefile
+@@ -85,4 +85,7 @@
+ cp -f bzip2.1 $(PREFIX)/share/man/man1
+ chmod a+r $(PREFIX)/share/man/man1/bzip2.1
++ ln -s bzip2.1 $(PREFIX)/share/man/man1/bunzip2.1
++ ln -s bzip2.1 $(PREFIX)/share/man/man1/bzcat.1
++ ln -s bzip2.1 $(PREFIX)/share/man/man1/bzip2recover.1
+ cp -f bzlib.h $(PREFIX)/include
+ chmod a+r $(PREFIX)/include/bzlib.h
diff --git a/main/bzip2/bzip2-1.0.6-saneso.patch b/main/bzip2/bzip2-1.0.6-saneso.patch
new file mode 100644
index 0000000000..1968a63bf1
--- /dev/null
+++ b/main/bzip2/bzip2-1.0.6-saneso.patch
@@ -0,0 +1,13 @@
+--- ./Makefile-libbz2_so
++++ ./Makefile-libbz2_so
+@@ -35,8 +35,8 @@
+ bzlib.o
+
+ all: $(OBJS)
+- $(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.6 $(OBJS)
+- $(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.1.0.6
++ $(CC) $(LDFLAGS) -shared -Wl,-soname -Wl,libbz2.so.1 -o libbz2.so.1.0.6 $(OBJS)
++ $(CC) $(LDFLAGS) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.1.0.6
+ rm -f libbz2.so.1.0
+ ln -s libbz2.so.1.0.6 libbz2.so.1.0
+
diff --git a/main/bzip2/bzip2.post-deinstall b/main/bzip2/bzip2.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/bzip2/bzip2.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/bzr/APKBUILD b/main/bzr/APKBUILD
new file mode 100644
index 0000000000..37ec6d5f1d
--- /dev/null
+++ b/main/bzr/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=bzr
+pkgver=2.3.0
+pkgrel=1
+pkgdesc="A scalable distributed SCM tool"
+url="http://bazaar.canonical.com/"
+arch="all"
+license="GPL"
+depends="python"
+makedepends="python-dev"
+subpackages="$pkgname-doc"
+source="http://launchpad.net/${pkgname}/${pkgver%.*}/${pkgver}/+download/${pkgname}-${pkgver}.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ python setup.py build
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ python setup.py install --root="$pkgdir" || return 1
+}
+
+doc() {
+ mkdir -p "$subpkgdir"/usr/share
+ mv "$pkgdir"/usr/man "$subpkgdir"/usr/share/man
+}
+
+md5sums="2d8bc55d43209189a209361178d9d372 bzr-2.3.0.tar.gz"
diff --git a/main/c-ares/APKBUILD b/main/c-ares/APKBUILD
new file mode 100644
index 0000000000..80e6e2dd03
--- /dev/null
+++ b/main/c-ares/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=c-ares
+pkgver=1.7.4
+pkgrel=2
+pkgdesc="An asynchronously DNS/names resolver library"
+url="http://c-ares.haxx.se/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://c-ares.haxx.se/${pkgname}-${pkgver}.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-shared
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="dd71e8f07d9f3c837e12a5416d1b7f73 c-ares-1.7.4.tar.gz"
diff --git a/main/ca-certificates/APKBUILD b/main/ca-certificates/APKBUILD
new file mode 100644
index 0000000000..148573aee6
--- /dev/null
+++ b/main/ca-certificates/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ca-certificates
+pkgver=20090814
+pkgrel=2
+pkgdesc="Common CA certificates PEM files"
+url="http://packages.debian.org/sid/ca-certificates"
+arch="all"
+license="MPL GPL"
+depends="run-parts openssl"
+install=ca-certificates.post-install
+source="http://ftp.no.debian.org/debian/pool/main/c/$pkgname/${pkgname}_${pkgver}+nmu2_all.deb
+ "
+
+build () {
+ cd "$srcdir"
+ ar x "$srcdir"/${pkgname}_${pkgver}+nmu2_all.deb || return 1
+ tar -zxf ./data.tar.gz
+
+ mkdir -p "$pkgdir"
+ cp -Ra usr etc "$pkgdir"/
+ (
+ echo "# Automatically generated by ${pkgname}-${pkgver}-${pkgrel}"
+ echo "# $(date -u)"
+ echo "# Do not edit."
+ cd "$pkgdir"/usr/share/ca-certificates
+ find . -name '*.crt' | sort | cut -b3-
+ ) > "$pkgdir"/etc/ca-certificates.conf
+}
+md5sums="b633433e748279c6412f2ffe7e614303 ca-certificates_20090814+nmu2_all.deb"
diff --git a/main/ca-certificates/ca-certificates.post-install b/main/ca-certificates/ca-certificates.post-install
new file mode 100644
index 0000000000..439cfca52e
--- /dev/null
+++ b/main/ca-certificates/ca-certificates.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+/usr/sbin/update-ca-certificates --fresh &> /dev/null
+
+exit 0;
diff --git a/main/cabextract/APKBUILD b/main/cabextract/APKBUILD
new file mode 100644
index 0000000000..f759888f1b
--- /dev/null
+++ b/main/cabextract/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=cabextract
+pkgver=1.3
+pkgrel=1
+pkgdesc="Tool for extracting Microsoft cabinet files"
+url="http://www.cabextract.org.uk/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=""
+makedepends=""
+install=
+source="http://www.cabextract.org.uk/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/${pkgname}-${pkgver}
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="cb9a4a38470d2a71a0275968e7eb64d3 cabextract-1.3.tar.gz"
diff --git a/main/cacti/APKBUILD b/main/cacti/APKBUILD
new file mode 100644
index 0000000000..33fc7e72c3
--- /dev/null
+++ b/main/cacti/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Jeff Bilyk <jbilyk@gmail.com>
+pkgname=cacti
+pkgver=0.8.7g
+pkgrel=1
+pkgdesc="Network monitoring tool based on RRDtool"
+url="http://www.cacti.net"
+arch="noarch"
+license="GPL"
+depends="mysql php php-mysql php-snmp rrdtool net-snmp php-sockets php-xml php-gd"
+makedepends=
+source="http://www.cacti.net/downloads/$pkgname-$pkgver.tar.gz
+http://www.cacti.net/downloads/patches/$pkgver/data_source_deactivate.patch
+http://www.cacti.net/downloads/patches/$pkgver/graph_list_view.patch
+http://www.cacti.net/downloads/patches/$pkgver/html_output.patch
+http://www.cacti.net/downloads/patches/$pkgver/ldap_group_authenication.patch
+http://www.cacti.net/downloads/patches/$pkgver/script_server_command_line_parse.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ msg "Applying $i"
+ if ! patch -p1 -i $i; then
+ error "$i failed"
+ return 1
+ fi
+ done
+ # Update syntax to be compatible with MySQL 5.5
+ msg "Updating syntax for MySQL 5.5.x"
+ sed -i 's/TYPE/ENGINE/g' cacti.sql
+}
+
+build() {
+ cd "$_builddir"
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"/usr/share/webapps/cacti
+ mv "$srcdir"/$pkgname-$pkgver/* "$pkgdir"/usr/share/webapps/cacti/ || return 1
+
+}
+md5sums="268421cb1a58d3444f7ecbddb4c4b016 cacti-0.8.7g.tar.gz
+d39570fd2e2b5c7f9aa47000b8a28c42 data_source_deactivate.patch
+6c2f7db4af48e59323c5e8b25a34866b graph_list_view.patch
+134d120930e4f2211f017f5b71d9280a html_output.patch
+5bb62cc6fde7c99f0c29cab869412f73 ldap_group_authenication.patch
+e14edee082d1250e3946c3caa58a40b4 script_server_command_line_parse.patch"
diff --git a/main/cairo/APKBUILD b/main/cairo/APKBUILD
new file mode 100644
index 0000000000..f5dee05013
--- /dev/null
+++ b/main/cairo/APKBUILD
@@ -0,0 +1,50 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cairo
+pkgver=1.10.2
+pkgrel=9
+pkgdesc="Cairo vector graphics library"
+url="http://cairographics.org/"
+arch="all"
+license="LGPL MPL"
+depends=
+depends_dev="fontconfig-dev freetype-dev libpng-dev libxrender-dev pixman-dev
+ xcb-util-dev glib-dev"
+makedepends="$depends_dev zlib-dev expat-dev"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-gobject $pkgname-tools"
+source="http://cairographics.org/releases/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ sed -i -e 's/libpng13/libpng14/g' configure || return 1
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --enable-xcb \
+ --enable-gobject \
+ --enable-tee \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+gobject() {
+ pkgdesc="GObject bindings for cairo"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libcairo-gobject.so.* "$subpkgdir"/usr/lib/
+}
+
+tools() {
+ pkgdesc="Development tools for cairo"
+ mkdir -p "$subpkgdir"/usr/lib/cairo
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/ || return 1
+ mv "$pkgdir"/usr/lib/cairo/libcairo-trace.* \
+ "$subpkgdir"/usr/lib/cairo/
+}
+
+md5sums="f101a9e88b783337b20b2e26dfd26d5f cairo-1.10.2.tar.gz"
diff --git a/main/cairomm/APKBUILD b/main/cairomm/APKBUILD
new file mode 100644
index 0000000000..3fd3bc2831
--- /dev/null
+++ b/main/cairomm/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cairomm
+pkgver=1.10.0
+pkgrel=1
+pkgdesc="C++ bindings to Cairo vector graphics library"
+url="http://www.cairographics.org"
+arch="all"
+license="LGPL MPL"
+depends=""
+makedepends="cairo-dev libsigc++-dev perl"
+depends_dev="$makedepends"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.cairographics.org/releases/cairomm-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="9c63fb1c04c8ecd3c5e6473075b8c39f cairomm-1.10.0.tar.gz"
diff --git a/main/ccache/APKBUILD b/main/ccache/APKBUILD
new file mode 100644
index 0000000000..89ea14bc46
--- /dev/null
+++ b/main/ccache/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ccache
+pkgver=3.1.5
+pkgrel=0
+pkgdesc="ccache is a compiler cache"
+url="http://ccache.samba.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=""
+makedepends=""
+source="http://samba.org/ftp/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ install -Dm 755 ccache "$pkgdir"/usr/bin/ccache
+ install -Dm 644 ccache.1 "$pkgdir"/usr/share/man/man1/ccache.1
+ mkdir -p "$pkgdir"/usr/lib/ccache/bin
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/cc
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/gcc
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/g++
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/cpp
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/c++
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/${CHOST}-cc
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/${CHOST}-gcc
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/${CHOST}-g++
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/${CHOST}-cpp
+ ln -sf /usr/bin/ccache "$pkgdir"/usr/lib/ccache/bin/${CHOST}-c++
+}
+md5sums="b1a9684828eae68382d6afc98ce80d24 ccache-3.1.5.tar.gz"
diff --git a/main/cciss_vol_status/APKBUILD b/main/cciss_vol_status/APKBUILD
new file mode 100644
index 0000000000..4260569b17
--- /dev/null
+++ b/main/cciss_vol_status/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa
+pkgname=cciss_vol_status
+pkgver=1.09
+pkgrel=1
+pkgdesc="Drivers for the HP (previously Compaq) Smart Array controllers which provide hardware RAID capability."
+url="http://cciss.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/cciss/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="2d94cb0c6abc217de95ade6c66d14132 cciss_vol_status-1.09.tar.gz"
diff --git a/main/cdrkit/APKBUILD b/main/cdrkit/APKBUILD
new file mode 100644
index 0000000000..ea5954d675
--- /dev/null
+++ b/main/cdrkit/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cdrkit
+pkgver=1.1.11
+pkgrel=1
+pkgdesc="Suite of programs for CD/DVD recording, ISO image creation, and audio CD extraction"
+url="http://cdrkit.org/"
+arch="all"
+license="GPL2"
+depends="file bzip2"
+makedepends="cmake libcap-dev bzip2-dev zlib-dev !libiconv"
+source="http://$pkgname.org/releases/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/cdrkit-$pkgver"
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/cdrkit-$pkgver"
+ make PREFIX="$pkgdir/usr" install || return 1
+ cd "$pkgdir/usr/bin"
+ ln -s wodim cdrecord || return 1
+ ln -s readom readcd || return 1
+ ln -s genisoimage mkisofs || return 1
+ ln -s genisoimage mkhybrid || return 1
+ ln -s icedax cdda2wav || return 1
+ cd "$pkgdir/usr/share/man/man1"
+ ln -s wodim.1 cdrecord.1 || return 1
+ ln -s readom.1 readcd.1 || return 1
+ ln -s genisoimage.1 mkisofs.1 || return 1
+ ln -s genisoimage.1 mkhybrid.1 || return 1
+ ln -s icedax.1 cdda2wav.1 || return 1
+}
+md5sums="efe08e2f3ca478486037b053acd512e9 cdrkit-1.1.11.tar.gz"
diff --git a/main/cgit/APKBUILD b/main/cgit/APKBUILD
new file mode 100644
index 0000000000..333abc14c3
--- /dev/null
+++ b/main/cgit/APKBUILD
@@ -0,0 +1,47 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cgit
+pkgver=0.9.0.1
+pkgrel=0
+_gitver=1.7.4
+pkgdesc="a fast webinterface for git"
+url="http://hjemli.net/git/cgit"
+arch="all"
+license=GPL-2
+makedepends="openssl-dev zlib-dev"
+depends=
+source="
+ http://hjemli.net/git/cgit/snapshot/$pkgname-$pkgver.tar.bz2
+ http://www.kernel.org/pub/software/scm/git/git-$_gitver.tar.bz2
+ "
+
+_makeopts="NO_ICONV=YesPlease
+ NO_TCLTK=YesPlease
+ NO_SVN_TESTS=YesPlease"
+
+prepare() {
+ cd "$srcdir/$pkgname-$pkgver"
+ # check that upstream git ver corresponds with our
+ local _ver=$(awk -F'[ \t]*=[ \t]*' '/^GIT_VER/ { print $2 }' Makefile)
+ if [ "$_ver" != "$_gitver" ]; then
+ error "Please set _gitver in APKBUILD to $_ver"
+ return 1
+ fi
+ rm -rf git
+ ln -s ../git-$_gitver git
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make $_makeopts
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make $_makeopts DESTDIR="$pkgdir" \
+ CGIT_SCRIPT_PATH=/usr/share/webapps/cgit \
+ install
+ ln -s cgit.cgi "$pkgdir"/usr/share/webapps/cgit/cgit
+}
+
+md5sums="dddae5bcfc1eeb469fc2b95531a75c1c cgit-0.9.0.1.tar.bz2
+fa24dc1ef0b663327ea0fe1981365b39 git-1.7.4.tar.bz2"
diff --git a/main/chrony/APKBUILD b/main/chrony/APKBUILD
new file mode 100644
index 0000000000..bfe76062bb
--- /dev/null
+++ b/main/chrony/APKBUILD
@@ -0,0 +1,71 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=chrony
+pkgver=1.23
+pkgrel=8
+pkgdesc="NTP client and server programs"
+url="http://chrony.tuxfamily.org/"
+arch="all"
+license="GPL-2"
+depends="logrotate"
+makedepends="texinfo"
+subpackages="$pkgname-doc"
+source="http://download.tuxfamily.org/chrony/$pkgname-$pkgver.tar.gz
+ $pkgname-1.20-conf.c-gentoo.diff
+ $pkgname-1.20-chrony.conf.example-gentoo.diff
+ $pkgname-1.21-makefile.diff
+ $pkgname-1.23-sources.diff
+ $pkgname-1.23-reply-ip.diff
+ chronyd.confd
+ chronyd.initd
+ chrony.logrotate
+ chrony.conf
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+
+ for i in ../*.diff; do
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+ sed -i "s:/etc/chrony:/etc/chrony/chrony:g" \
+ chrony*.[158] faq.txt chrony.texi || die "sed failed"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --infodir=/usr/share/info \
+ --mandir=/usr/share/man \
+ --disable-readline
+
+ make all docs || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ mv "$pkgdir"/usr/doc "$pkgdir"/usr/share/
+ install -D -m644 examples/*.example "$pkgdir"/usr/share/doc/chrony/
+
+ install -m755 -D "$srcdir"/chronyd.initd "$pkgdir"/etc/init.d/chronyd
+ install -m644 -D "$srcdir"/chronyd.confd "$pkgdir"/etc/conf.d/chronyd
+ mkdir -p "$pkgdir"/var/lib/chrony \
+ "$pkgdir"/var/log/chrony \
+ "$pkgdir"/etc/chrony
+ touch "$pkgdir"/etc/chrony/chrony.drift
+ install -m644 "$srcdir"/chrony.conf "$pkgdir"/etc/chrony/chrony.conf
+}
+md5sums="ffce77695e55d8efda19ab0b78309c23 chrony-1.23.tar.gz
+bd6bd57363865d3ed0c3187d0c9f7151 chrony-1.20-conf.c-gentoo.diff
+b2a23e02f7af50bebdd5d18bccdedbf0 chrony-1.20-chrony.conf.example-gentoo.diff
+d47015a34b6b2f9eebca77ef939cec72 chrony-1.21-makefile.diff
+39cbce9f66638b67623e1ee6bb0f943f chrony-1.23-sources.diff
+caa6589a1a1cd56f64957e312d1ef84c chrony-1.23-reply-ip.diff
+d62521b4c8837e15262c47ac88359307 chronyd.confd
+f0c73948224cc1706cf9c94e4d2d7b69 chronyd.initd
+468eaf2b5465d60b3ee021ce3f948ab1 chrony.logrotate
+46f42c52953d398ca44d6baa449618d7 chrony.conf"
diff --git a/main/chrony/chrony-1.20-chrony.conf.example-gentoo.diff b/main/chrony/chrony-1.20-chrony.conf.example-gentoo.diff
new file mode 100644
index 0000000000..498b241750
--- /dev/null
+++ b/main/chrony/chrony-1.20-chrony.conf.example-gentoo.diff
@@ -0,0 +1,46 @@
+--- a/examples/chrony.conf.example.orig 2003-06-16 11:59:01.000000000 -0400
++++ b/examples/chrony.conf.example 2003-06-16 12:00:13.000000000 -0400
+@@ -3,5 +3,5 @@
+ #
+ # This is an example chrony configuration file. You should copy it to
+-# /etc/chrony.conf after uncommenting and editing the options that you
++# /etc/chrony/chrony.conf after uncommenting and editing the options that you
+ # want to enable. I have not included the more obscure options. Refer
+ # to the documentation for these.
+@@ -91,5 +91,5 @@
+ # generally want this, so it is uncommented.
+
+-driftfile /etc/chrony.drift
++driftfile /etc/chrony/chrony.drift
+
+ # If you want to use the program called chronyc to configure aspects of
+@@ -100,5 +100,5 @@
+ # assumed by default.
+
+-keyfile /etc/chrony.keys
++keyfile /etc/chrony/chrony.keys
+
+ # Tell chronyd which numbered key in the file is used as the password
+@@ -158,6 +158,6 @@
+ ! log measurements statistics tracking
+
+-If you have real time clock support enabled (see below), you might want
+-this line instead:
++# If you have real time clock support enabled (see below), you might want
++# this line instead:
+
+ ! log measurements statistics tracking rtc
+@@ -269,5 +269,5 @@
+ # kernel. (Note, these options apply only to Linux.)
+
+-! rtcfile /etc/chrony.rtc
++! rtcfile /etc/chrony/chrony.rtc
+
+ # Your RTC can be set to keep Universal Coordinated Time (UTC) or local
+@@ -285,5 +285,5 @@
+ # using devfs), uncomment and edit the following line.
+
+-! rtcdevice /dev/misc/rtc
++rtcdevice /dev/misc/rtc
+
+ #######################################################################
diff --git a/main/chrony/chrony-1.20-conf.c-gentoo.diff b/main/chrony/chrony-1.20-conf.c-gentoo.diff
new file mode 100644
index 0000000000..4917d445be
--- /dev/null
+++ b/main/chrony/chrony-1.20-conf.c-gentoo.diff
@@ -0,0 +1,11 @@
+--- a/conf.c.orig Sun May 12 14:07:31 2002
++++ b/conf.c Sun May 12 14:07:52 2002
+@@ -45,7 +45,7 @@
+
+ /* ================================================== */
+
+-#define DEFAULT_CONF_FILE "/etc/chrony.conf"
++#define DEFAULT_CONF_FILE "/etc/chrony/chrony.conf"
+
+ /* ================================================== */
+ /* Forward prototypes */
diff --git a/main/chrony/chrony-1.21-makefile.diff b/main/chrony/chrony-1.21-makefile.diff
new file mode 100644
index 0000000000..2eec4e8428
--- /dev/null
+++ b/main/chrony/chrony-1.21-makefile.diff
@@ -0,0 +1,15 @@
+--- a/Makefile.in_old 2006-08-12 17:42:57.000000000 +0200
++++ b/Makefile.in 2006-08-12 17:44:35.000000000 +0200
+@@ -68,10 +68,10 @@
+ all : chronyd chronyc
+
+ chronyd : $(OBJS) $(EXTRA_OBJS)
+- $(CC) $(OPTFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LIBS) $(EXTRA_LIBS)
++ $(CC) $(OPTFLAGS) $(LDFLAGS) -o chronyd $(OBJS) $(EXTRA_OBJS) $(LIBS) $(EXTRA_LIBS)
+
+ chronyc : $(CLI_OBJS)
+- $(CC) $(OPTFLAGS) -o chronyc $(CLI_OBJS) @READLINE_LINK@ $(LIBS) $(EXTRA_CLI_LIBS)
++ $(CC) $(OPTFLAGS) $(LDFLAGS) -o chronyc $(CLI_OBJS) @READLINE_LINK@ $(LIBS) $(EXTRA_CLI_LIBS)
+
+ client.o : client.c
+ $(CC) $(CFLAGS) $(DEFS) @READLINE_COMPILE@ -c $<
diff --git a/main/chrony/chrony-1.23-reply-ip.diff b/main/chrony/chrony-1.23-reply-ip.diff
new file mode 100644
index 0000000000..f4e5d8eff4
--- /dev/null
+++ b/main/chrony/chrony-1.23-reply-ip.diff
@@ -0,0 +1,242 @@
+
+Currently, on multihomed host, when chrony is not bound to a specific
+IP address, a query is sent to an interface and the default source IP
+hint for the back route differs, the reply will have a source IP
+different than where the query was destinied to. This will cause
+problems because connection tracking firewalls will drop the replies
+and most likely the client program will get confused too.
+
+This patch uses the IP_PKTINFO mechanism to get the IP address where
+received packets where targetted to and use that IP address as source
+hint when sending a reply.
+---
+ addressing.h | 1 +
+ broadcast.c | 1 +
+ cmdmon.c | 3 ++
+ conf.c | 1 +
+ ntp_io.c | 92 +++++++++++++++++++++++++++++++++++++++++----------------
+ 5 files changed, 72 insertions(+), 26 deletions(-)
+
+diff --git a/addressing.h b/addressing.h
+index aa20ed9..05152f4 100644
+--- a/addressing.h
++++ b/addressing.h
+@@ -36,6 +36,7 @@
+ typedef struct {
+ unsigned long ip_addr;
+ unsigned short port;
++ unsigned long local_ip_addr;
+ } NTP_Remote_Address;
+
+ #if 0
+diff --git a/broadcast.c b/broadcast.c
+index be217e7..c979741 100644
+--- a/broadcast.c
++++ b/broadcast.c
+@@ -146,6 +146,7 @@ BRD_AddDestination(unsigned long addr, unsigned short port, int interval)
+
+ destinations[n_destinations].addr.ip_addr = addr;
+ destinations[n_destinations].addr.port = port;
++ destinations[n_destinations].addr.local_ip_addr = 0;
+ destinations[n_destinations].interval = interval;
+
+ SCH_AddTimeoutInClass((double) interval, 1.0,
+diff --git a/cmdmon.c b/cmdmon.c
+index 819977c..8affb0b 100644
+--- a/cmdmon.c
++++ b/cmdmon.c
+@@ -1097,6 +1097,7 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
+
+ rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
+ rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
++ rem_addr.local_ip_addr = 0;
+ params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
+ params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
+ params.presend_minpoll = ntohl(rx_message->data.ntp_source.presend_minpoll);
+@@ -1133,6 +1134,7 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
+
+ rem_addr.ip_addr = ntohl(rx_message->data.ntp_source.ip_addr);
+ rem_addr.port = (unsigned short)(ntohl(rx_message->data.ntp_source.port));
++ rem_addr.local_ip_addr = 0;
+ params.minpoll = ntohl(rx_message->data.ntp_source.minpoll);
+ params.maxpoll = ntohl(rx_message->data.ntp_source.maxpoll);
+ params.presend_minpoll = ntohl(rx_message->data.ntp_source.presend_minpoll);
+@@ -1167,6 +1169,7 @@ handle_del_source(CMD_Request *rx_message, CMD_Reply *tx_message)
+
+ rem_addr.ip_addr = ntohl(rx_message->data.del_source.ip_addr);
+ rem_addr.port = 0;
++ rem_addr.local_ip_addr = 0;
+
+ status = NSR_RemoveSource(&rem_addr);
+ switch (status) {
+diff --git a/conf.c b/conf.c
+index e34927e..ddd13f1 100644
+--- a/conf.c
++++ b/conf.c
+@@ -949,6 +949,7 @@ CNF_AddSources(void) {
+ for (i=0; i<n_ntp_sources; i++) {
+ server.ip_addr = ntp_sources[i].ip_addr;
+ server.port = ntp_sources[i].port;
++ server.local_ip_addr = 0;
+
+ switch (ntp_sources[i].type) {
+ case SERVER:
+diff --git a/ntp_io.c b/ntp_io.c
+index afb6ad1..db89758 100644
+--- a/ntp_io.c
++++ b/ntp_io.c
+@@ -118,6 +118,12 @@ NIO_Initialise(void)
+ LOG(LOGS_ERR, LOGF_NtpIO, "Could not set broadcast socket options");
+ /* Don't quit - we might survive anyway */
+ }
++ /* We want the local IP info too */
++ if (setsockopt(sock_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on_off, sizeof(on_off)) < 0) {
++ LOG(LOGS_ERR, LOGF_NtpIO, "Could not request packet info using socket option");
++ /* Don't quit - we might survive anyway */
++ }
++
+
+ /* Bind the port */
+ my_addr.sin_family = AF_INET;
+@@ -182,22 +188,30 @@ read_from_socket(void *anything)
+
+ int status;
+ ReceiveBuffer message;
+- int message_length;
+ struct sockaddr_in where_from;
+- socklen_t from_length;
+ unsigned int flags = 0;
+ struct timeval now;
+ NTP_Remote_Address remote_addr;
+ double local_clock_err;
++ char cmsgbuf[256];
++ struct cmsghdr *cmsg;
++ struct msghdr msg;
++ struct iovec iov;
+
+ assert(initialised);
+
+- from_length = sizeof(where_from);
+- message_length = sizeof(message);
++ iov.iov_base = message.arbitrary;
++ iov.iov_len = sizeof(message);
++ msg.msg_name = &where_from;
++ msg.msg_namelen = sizeof(where_from);
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++ msg.msg_control = (void *) cmsgbuf;
++ msg.msg_controllen = sizeof(cmsgbuf);
++ msg.msg_flags = 0;
+
+ LCL_ReadCookedTime(&now, &local_clock_err);
+- status = recvfrom(sock_fd, (char *)&message, message_length, flags,
+- (struct sockaddr *)&where_from, &from_length);
++ status = recvmsg(sock_fd, &msg, flags);
+
+ /* Don't bother checking if read failed or why if it did. More
+ likely than not, it will be connection refused, resulting from a
+@@ -209,6 +223,13 @@ read_from_socket(void *anything)
+ if (status > 0) {
+ remote_addr.ip_addr = ntohl(where_from.sin_addr.s_addr);
+ remote_addr.port = ntohs(where_from.sin_port);
++ remote_addr.local_ip_addr = 0;
++
++ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
++ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
++ remote_addr.local_ip_addr =
++ ntohl(((struct in_pktinfo *) CMSG_DATA(cmsg))->ipi_spec_dst.s_addr);
++ }
+
+ if (status == NTP_NORMAL_PACKET_SIZE) {
+
+@@ -229,21 +250,45 @@ read_from_socket(void *anything)
+ }
+
+ /* ================================================== */
+-/* Send an unauthenticated packet to a given address */
++/* Send a packet to given address */
+
+-void
+-NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
++static void
++NIO_SendPacket(NTP_Packet *packet, int packetlen, NTP_Remote_Address *remote_addr)
+ {
+ struct sockaddr_in remote;
++ struct msghdr msg;
++ struct iovec iov;
++ struct {
++ struct cmsghdr cm;
++ struct in_pktinfo ipi;
++ } cmsg;
+
+ assert(initialised);
+
+ remote.sin_family = AF_INET;
+ remote.sin_port = htons(remote_addr->port);
+ remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
++ iov.iov_base = (void *) packet;
++ iov.iov_len = packetlen;
++ msg.msg_name = &remote;
++ msg.msg_namelen = sizeof(remote);
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++ if (remote_addr->local_ip_addr) {
++ cmsg.cm.cmsg_len = sizeof(cmsg);
++ cmsg.cm.cmsg_level = IPPROTO_IP;
++ cmsg.cm.cmsg_type = IP_PKTINFO;
++ memset(&cmsg.ipi, 0, sizeof(cmsg.ipi));
++ cmsg.ipi.ipi_spec_dst.s_addr = htonl(remote_addr->local_ip_addr);
++ msg.msg_control = (void *) &cmsg;
++ msg.msg_controllen = sizeof(cmsg);
++ } else {
++ msg.msg_control = NULL;
++ msg.msg_controllen = 0;
++ }
++ msg.msg_flags = 0;
+
+- if (sendto(sock_fd, (void *) packet, NTP_NORMAL_PACKET_SIZE, 0,
+- (struct sockaddr *) &remote, sizeof(remote)) < 0) {
++ if (sendmsg(sock_fd, &msg, 0) < 0) {
+ LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
+ UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
+ }
+@@ -252,26 +297,21 @@ NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
+ }
+
+ /* ================================================== */
+-/* Send an authenticated packet to a given address */
++/* Send an unauthenticated packet to a given address */
+
+ void
+-NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
++NIO_SendNormalPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
+ {
+- struct sockaddr_in remote;
+-
+- assert(initialised);
+-
+- remote.sin_family = AF_INET;
+- remote.sin_port = htons(remote_addr->port);
+- remote.sin_addr.s_addr = htonl(remote_addr->ip_addr);
++ NIO_SendPacket(packet, NTP_NORMAL_PACKET_SIZE, remote_addr);
++}
+
+- if (sendto(sock_fd, (void *) packet, sizeof(NTP_Packet), 0,
+- (struct sockaddr *) &remote, sizeof(remote)) < 0) {
+- LOG(LOGS_WARN, LOGF_NtpIO, "Could not send to %s:%d : %s",
+- UTI_IPToDottedQuad(remote_addr->ip_addr), remote_addr->port, strerror(errno));
+- }
++/* ================================================== */
++/* Send an authenticated packet to a given address */
+
+- return;
++void
++NIO_SendAuthenticatedPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr)
++{
++ NIO_SendPacket(packet, sizeof(NTP_Packet), remote_addr);
+ }
+
+ /* ================================================== */
+--
+1.5.6.3
+
diff --git a/main/chrony/chrony-1.23-sources.diff b/main/chrony/chrony-1.23-sources.diff
new file mode 100644
index 0000000000..5f39ca3321
--- /dev/null
+++ b/main/chrony/chrony-1.23-sources.diff
@@ -0,0 +1,56 @@
+commit 2f2446c7dc074b2d1728a5e3f7a600c10cea2425
+Author: Goswin Brederlow <brederlo@informatik.uni-tuebingen.de>
+Date: Sat Mar 29 20:49:59 2008 +0000
+
+ Fix for chronyc "sources" command on 64 bit machines
+
+ (Taken from
+ http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=348412
+ )
+
+ Attached is a patchlet to make the "sources" command of chrony output properly
+ signed numbers. The chronyd code (see e.g. ntp.h) properly uses int32_t and
+ friends to get the right number of bits per datatype while client.c just uses
+ short, int, long. But long will be 64 bit or 32 bit depending on the cpu.
+
+diff --git a/client.c b/client.c
+index b7e5bcb..85d6e84 100644
+--- a/client.c
++++ b/client.c
+@@ -45,6 +45,12 @@
+ #include <readline/history.h>
+ #endif
+
++#ifdef HAS_STDINT_H
++#include <stdint.h>
++#elif defined(HAS_INTTYPES_H)
++#include <inttypes.h>
++#endif
++
+ /* ================================================== */
+
+ static int sock_fd;
+@@ -1383,16 +1389,16 @@ process_cmd_sources(char *line)
+ int n_sources, i;
+ int verbose = 0;
+
+- long orig_latest_meas, latest_meas, est_offset;
+- unsigned long ip_addr;
+- unsigned long latest_meas_err, est_offset_err;
+- unsigned long latest_meas_ago;
+- unsigned short poll, stratum;
+- unsigned short state, mode;
++ int32_t orig_latest_meas, latest_meas, est_offset;
++ uint32_t ip_addr;
++ uint32_t latest_meas_err, est_offset_err;
++ uint32_t latest_meas_ago;
++ uint16_t poll, stratum;
++ uint16_t state, mode;
+ double resid_freq, resid_skew;
+ const char *dns_lookup;
+ char hostname_buf[32];
+- unsigned short status;
++ uint16_t status;
+
+ /* Check whether to output verbose headers */
+ verbose = check_for_verbose_flag(line);
diff --git a/main/chrony/chrony.conf b/main/chrony/chrony.conf
new file mode 100644
index 0000000000..d99b1e01d4
--- /dev/null
+++ b/main/chrony/chrony.conf
@@ -0,0 +1,7 @@
+# default config
+
+server pool.ntp.org
+initstepslew 10 pool.ntp.org
+commandkey 10
+keyfile /etc/chrony/chrony.keys
+driftfile /etc/chrony/chrony.drift
diff --git a/main/chrony/chrony.logrotate b/main/chrony/chrony.logrotate
new file mode 100644
index 0000000000..1b7b589a9f
--- /dev/null
+++ b/main/chrony/chrony.logrotate
@@ -0,0 +1,11 @@
+/var/log/chrony/*.log
+ sharedscripts
+ postrotate
+ PASSWORD=`awk '$1 ~ /^1$/ {print $2; exit}' /etc/chrony/chrony.keys`
+ cat << EOF | /usr/bin/chronyc | sed '/^200 OK$/d'
+ password $PASSWORD
+ cyclelogs
+ EOF
+ endscript
+}
+
diff --git a/main/chrony/chronyd.confd b/main/chrony/chronyd.confd
new file mode 100644
index 0000000000..fc43a95c40
--- /dev/null
+++ b/main/chrony/chronyd.confd
@@ -0,0 +1,12 @@
+# /etc/conf.d/chronyd
+
+CFGFILE="/etc/chrony/chrony.conf"
+
+# Configuration dependant options :
+# -s - Set system time from RTC if rtcfile directive present
+# -r - Reload sample histories if dumponexit directive present
+#
+# The combination of "-s -r" allows chronyd to perform long term averaging of
+# the gain or loss rate across system reboots and shutdowns.
+
+ARGS=""
diff --git a/main/chrony/chronyd.initd b/main/chrony/chronyd.initd
new file mode 100644
index 0000000000..4fe5135615
--- /dev/null
+++ b/main/chrony/chronyd.initd
@@ -0,0 +1,69 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/chrony/files/chronyd.rc,v 1.8 2007/03/22 14:32:09 tove Exp $
+
+depend() {
+ need net
+ after firewall
+ provide ntp-client ntp-server
+ use dns
+}
+
+checkconfig() {
+ # Note that /etc/chrony/chrony.keys is *NOT* checked. This
+ # is because the user may have specified another key
+ # file, and we don't want to force the user to use that
+ # exact name for the key file.
+ if [ ! -f "${CFGFILE}" ] ; then
+ eerror "Please create ${CFGFILE} and the"
+ eerror "chrony key file (usually /etc/chrony/chrony.keys)"
+ eerror "by using the"
+ eerror ""
+ eerror " chrony.conf.example"
+ eerror " chrony.keys.example"
+ eerror ""
+ eerror "files (from the documentation directory)"
+ eerror "as templates."
+ return 1
+ else
+ # Actually, I tried it, and chrony seems to ignore the pidfile
+ # option. I'm going to leave it here anyway, since you never
+ # know if it might be handy
+ PIDFILE=`awk '/^ *pidfile/{print $2}' "${CFGFILE}"`
+ fi
+ return 0
+}
+
+setxtrarg() {
+ if [ -c /dev/rtc ]; then
+ grep -q '^rtcfile' "${CFGFILE}" && ARGS="${ARGS} -s"
+ fi
+ grep -q '^dumponexit$' "${CFGFILE}" && ARGS="${ARGS} -r"
+ return 0
+}
+
+start() {
+ checkconfig || return $?
+ setxtrarg
+
+ [ -n "${PIDFILE}" ] || PIDFILE=/var/run/chronyd.pid
+
+ ebegin "Starting chronyd"
+ start-stop-daemon --start --quiet \
+ --exec /usr/sbin/chronyd \
+ --pidfile "${PIDFILE}" \
+ -- -f "${CFGFILE}" ${ARGS}
+ eend $? "Failed to start chronyd"
+}
+
+stop() {
+ checkconfig || return $?
+
+ [ -n "${PIDFILE}" ] || PIDFILE=/var/run/chronyd.pid
+
+ ebegin "Stopping chronyd"
+ start-stop-daemon --stop --quiet \
+ --pidfile "${PIDFILE}"
+ eend $? "Failed to stop chronyd"
+}
diff --git a/main/cksfv/APKBUILD b/main/cksfv/APKBUILD
new file mode 100644
index 0000000000..cdf651fa99
--- /dev/null
+++ b/main/cksfv/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=cksfv
+pkgver=1.3.14
+pkgrel=2
+pkgdesc="Simple File Verification"
+url="http://zakalwe.fi/~shd/foss/cksfv"
+arch="all"
+license="GPL"
+depends=
+subpackages="$pkgname-doc"
+source="http://zakalwe.fi/~shd/foss/cksfv/files/${pkgname}-${pkgver}.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr
+ make || return 1
+ install -cD src/cksfv "$pkgdir"/usr/bin/cksfv
+ install -cD cksfv.1 "$pkgdir"/usr/share/man/man1/cksfv.1
+}
+
+md5sums="138bff42ab23fbba8cca0ae14b2d9e52 cksfv-1.3.14.tar.bz2"
diff --git a/main/clamav/APKBUILD b/main/clamav/APKBUILD
new file mode 100644
index 0000000000..22fcda7f9c
--- /dev/null
+++ b/main/clamav/APKBUILD
@@ -0,0 +1,158 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=clamav
+pkgver=0.97
+pkgrel=4
+pkgusers=clamav
+pkggroups=clamav
+pkgdesc="An anti-virus toolkit for UNIX"
+url="http://www.clamav.net/"
+arch="all"
+license="GPL"
+depends="$pkgname-scanner $pkgname-daemon"
+install=""
+makedepends="ncurses-dev zlib-dev"
+subpackages="$pkgname-doc $pkgname-dev $pkgname-lib $pkgname-libunrar
+ $pkgname-daemon $pkgname-scanner $pkgname-db"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ clamd.initd
+ clamd.confd
+ freshclam.initd
+ freshclam.confd
+ clamav-0.95.1-nls.patch
+ clamd.logrotate
+ freshclam.logrotate
+ "
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ patch -p0 -i "$srcdir/clamav-0.95.1-nls.patch" || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --libdir=/usr/lib \
+ --sysconfdir=/etc/clamav \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --without-iconv \
+ --disable-llvm \
+ --with-dbdir=/var/lib/clamav \
+ --enable-clamdtop
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+lib() {
+ pkgdesc="ClamAV library"
+ depends=""
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libclamav.so.* \
+ "$subpkgdir"/usr/lib/
+}
+
+libunrar() {
+ pkgdesc="ClamAV unrar libraries"
+ depends=""
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libclamunrar* \
+ "$subpkgdir"/usr/lib/
+}
+
+db() {
+ pkgdesc="ClamAV virus database and update program"
+ depends="logrotate"
+ install="$subpkgname.pre-install $subpkgname.post-install $subpkgname.pre-upgrade"
+ mkdir -p "$subpkgdir"/var/lib/ \
+ "$subpkgdir"/usr/bin \
+ "$subpkgdir"/etc/clamav \
+ "$subpkgdir"/var/run/clamav \
+ "$subpkgdir"/var/log/clamav
+ mv "$pkgdir"/var/lib/clamav \
+ "$subpkgdir"/var/lib/ || return 1
+ mv "$pkgdir"/usr/bin/freshclam \
+ "$subpkgdir"/usr/bin || return 1
+ install -m755 -D "$srcdir"/freshclam.initd \
+ "$subpkgdir"/etc/init.d/freshclam || return 1
+ install -m644 -D "$srcdir"/freshclam.confd \
+ "$subpkgdir"/etc/conf.d/freshclam || return 1
+ mv "$pkgdir"/etc/clamav/freshclam.conf \
+ "$subpkgdir"/etc/clamav/ || return 1
+ # set proper defaults
+ sed -i -e "s:^\(Example\):\# \1:" \
+ -e "s:.*\(PidFile\) .*:\1 /var/run/clamav/freshclam.pid:" \
+ -e "s:.*\(DatabaseOwner\) .*:\1 clamav:" \
+ -e "s:^\#\(UpdateLogFile\) .*:\1 /var/log/clamav/freshclam.log:" \
+ -e "s:^\#\(NotifyClamd\).*:\1 /etc/clamav/clamd.conf:" \
+ -e "s:^\#\(ScriptedUpdates\).*:\1 yes:" \
+ -e "s:^\#\(AllowSupplementaryGroups\).*:\1 yes:" \
+ "$subpkgdir"/etc/clamav/freshclam.conf
+ install -m644 -D "$srcdir"/freshclam.logrotate \
+ "$subpkgdir"/etc/logrotate.d/freshclam || return 1
+}
+
+scanner() {
+ pkgdesc="ClamAV command-line scanner and utils"
+ depends="$pkgname-db"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/clamscan \
+ "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/usr/bin/sigtool \
+ "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/usr/bin/clambc \
+ "$subpkgdir"/usr/bin/ || return 1
+
+}
+
+daemon() {
+ pkgdesc="ClamAV daemon scanner"
+ depends="$pkgname-db logrotate"
+ install="$subpkgname.pre-install $subpkgname.post-install $subpkgname.pre-upgrade"
+ mkdir -p "$subpkgdir"/usr/bin \
+ "$subpkgdir"/usr/sbin \
+ "$subpkgdir"/etc/clamav \
+ "$subpkgdir"/var/run/clamav \
+ "$subpkgdir"/var/log/clamav
+ mv "$pkgdir"/usr/bin/clamconf \
+ "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/usr/sbin/clamd \
+ "$subpkgdir"/usr/sbin/ || return 1
+ mv "$pkgdir"/usr/bin/clamdtop \
+ "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/usr/bin/clamdscan \
+ "$subpkgdir"/usr/bin/ || return 1
+ install -m755 -D "$srcdir"/clamd.initd \
+ "$subpkgdir"/etc/init.d/clamd || return 1
+ install -m644 -D "$srcdir"/clamd.confd \
+ "$subpkgdir"/etc/conf.d/clamd || return 1
+ mv "$pkgdir"/etc/clamav/clamd.conf \
+ "$subpkgdir"/etc/clamav/ || return 1
+ # set proper defaults
+ sed -i -e "s:^\(Example\):\# \1:" \
+ -e "s:.*\(PidFile\) .*:\1 /var/run/clamav/clamd.pid:" \
+ -e "s:.*\(LocalSocket\) .*:\1 /var/run/clamav/clamd.sock:" \
+ -e "s:.*\(User\) .*:\1 clamav:" \
+ -e "s:^\#\(LogFile\) .*:\1 /var/log/clamav/clamd.log:" \
+ -e "s:^\#\(LogTime\).*:\1 yes:" \
+ -e "s:^\#\(AllowSupplementaryGroups\).*:\1 yes:" \
+ "$subpkgdir"/etc/clamav/clamd.conf
+ install -m644 -D "$srcdir"/clamd.logrotate \
+ "$subpkgdir"/etc/logrotate.d/clamd || return 1
+}
+
+md5sums="605ed132b2f8e89df11064adea2b183b clamav-0.97.tar.gz
+d64432c463850663c5041c3097f3e903 clamd.initd
+567bc32b657dd7031b9b7beaa946203a clamd.confd
+f4d1f415322905128dc27135566ad136 freshclam.initd
+e48466ddfb56f66c623b83e58777b778 freshclam.confd
+0d08fd29656bd4b018ecf8ce9706ac55 clamav-0.95.1-nls.patch
+ae1e48ab56a0fff1acdde023c1f6f350 clamd.logrotate
+226824214c021b2366f0be1289561d17 freshclam.logrotate"
diff --git a/main/clamav/clamav-0.95.1-nls.patch b/main/clamav/clamav-0.95.1-nls.patch
new file mode 100644
index 0000000000..82ae88f576
--- /dev/null
+++ b/main/clamav/clamav-0.95.1-nls.patch
@@ -0,0 +1,11 @@
+--- shared/output.c-orig 2009-04-04 10:17:42 +0000
++++ shared/output.c 2009-04-04 10:18:30 +0000
+@@ -67,7 +67,7 @@
+ pthread_mutex_t logg_mutex = PTHREAD_MUTEX_INITIALIZER;
+ #endif
+
+-#ifdef C_LINUX
++#if defined(C_LINUX) && defined(HAVE_LIBINTL_H)
+ #include <libintl.h>
+ #include <locale.h>
+
diff --git a/main/clamav/clamav-daemon.post-install b/main/clamav/clamav-daemon.post-install
new file mode 100644
index 0000000000..e40badb09b
--- /dev/null
+++ b/main/clamav/clamav-daemon.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+chown -R clamav:clamav /var/run/clamav /var/log/clamav
diff --git a/main/clamav/clamav-daemon.pre-install b/main/clamav/clamav-daemon.pre-install
new file mode 100644
index 0000000000..59ac60a44d
--- /dev/null
+++ b/main/clamav/clamav-daemon.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -H -s /bin/false -D clamav 2>/dev/null
+exit 0
diff --git a/main/clamav/clamav-daemon.pre-upgrade b/main/clamav/clamav-daemon.pre-upgrade
new file mode 100644
index 0000000000..c8f82dacd4
--- /dev/null
+++ b/main/clamav/clamav-daemon.pre-upgrade
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# make sure we don't lose our config
+mkdir -p /etc/clamav
+if [ -f /etc/clamav.conf ]; then
+ mv /etc/clamav.conf /etc/clamav/
+ ln -s clamav/clamav.conf /etc/clamav.conf
+fi
+
+exit 0
+
diff --git a/main/clamav/clamav-db.post-install b/main/clamav/clamav-db.post-install
new file mode 100644
index 0000000000..b43342f31a
--- /dev/null
+++ b/main/clamav/clamav-db.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+chown -R clamav:clamav /var/lib/clamav /var/run/clamav /var/log/clamav
diff --git a/main/clamav/clamav-db.pre-install b/main/clamav/clamav-db.pre-install
new file mode 100644
index 0000000000..59ac60a44d
--- /dev/null
+++ b/main/clamav/clamav-db.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -H -s /bin/false -D clamav 2>/dev/null
+exit 0
diff --git a/main/clamav/clamav-db.pre-upgrade b/main/clamav/clamav-db.pre-upgrade
new file mode 100644
index 0000000000..47230e16b2
--- /dev/null
+++ b/main/clamav/clamav-db.pre-upgrade
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# make sure we don't lose our config
+mkdir -p /etc/clamav
+if [ -f /etc/freshclam.conf ]; then
+ mv /etc/freshclam.conf /etc/clamav/
+ ln -s clamav/freshclam.conf /etc/freshclam.conf
+fi
+
+exit 0
+
diff --git a/main/clamav/clamd.confd b/main/clamav/clamd.confd
new file mode 100644
index 0000000000..bc8072aead
--- /dev/null
+++ b/main/clamav/clamd.confd
@@ -0,0 +1,6 @@
+
+CLAMD_NICELEVEL=0
+
+# make sure we also start freshclam
+# comment out if you dont want start freshclam
+rc_need="freshclam"
diff --git a/main/clamav/clamd.initd b/main/clamav/clamd.initd
new file mode 100644
index 0000000000..2864267e1e
--- /dev/null
+++ b/main/clamav/clamd.initd
@@ -0,0 +1,57 @@
+#!/sbin/runscript
+
+opts="logfix reload"
+NAME=clamd
+CONF=/etc/clamav/clamd.conf
+
+depend() {
+ need net
+ after firewall
+ provide antivirus
+}
+
+start() {
+ local clamd_socket=$(awk '$1 == "LocalSocket" { print $2 }' $CONF)
+
+ logfix
+
+ if [ -S "${clamd_socket:=/tmp/clamd}" ]; then
+ rm -f ${clamd_socket}
+ fi
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet \
+ --nicelevel ${CLAMD_NICELEVEL:-0} \
+ --exec /usr/sbin/clamd
+ eend $? "Failed to start ${NAME}"
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/clamd
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading ${NAME}"
+ if ! service_started "${NAME}" ; then
+ eend 1 "${NAME} is not started"
+ return 1
+ fi
+ start-stop-daemon --stop --oknodo --signal HUP \
+ --exec /usr/sbin/clamd
+ eend $?
+}
+
+logfix() {
+ # fix clamd log permissions
+ # (might be clobbered by logrotate or something)
+ local logfile=`awk '$1 == "LogFile" { print $2 }' $CONF`
+ local clamav_user=`awk '$1 == "User" { print $2 }' $CONF`
+ if [ -n "${logfile}" ] && [ -n "${clamav_user}" ]; then
+ if [ ! -f "${logfile}" ]; then
+ touch ${logfile}
+ fi
+ chown ${clamav_user} ${logfile}
+ chmod 640 ${logfile}
+ fi
+}
diff --git a/main/clamav/clamd.logrotate b/main/clamav/clamd.logrotate
new file mode 100644
index 0000000000..3d7fc79cad
--- /dev/null
+++ b/main/clamav/clamd.logrotate
@@ -0,0 +1,8 @@
+/var/log/clamav/clamd.log {
+ missingok
+ postrotate
+ /etc/init.d/clamd logfix
+ /bin/kill -HUP `cat /var/run/clamav/clamd.pid 2> /dev/null` 2>/dev/null || true
+ endscript
+}
+
diff --git a/main/clamav/freshclam.confd b/main/clamav/freshclam.confd
new file mode 100644
index 0000000000..17559037da
--- /dev/null
+++ b/main/clamav/freshclam.confd
@@ -0,0 +1,3 @@
+
+FRESHCLAM_NICELEVEL=0
+
diff --git a/main/clamav/freshclam.initd b/main/clamav/freshclam.initd
new file mode 100644
index 0000000000..f25fec434d
--- /dev/null
+++ b/main/clamav/freshclam.initd
@@ -0,0 +1,59 @@
+#!/sbin/runscript
+
+opts="logfix reload"
+
+NAME=freshclam
+DAEMON=/usr/bin/$NAME
+CONF=/etc/clamav/freshclam.conf
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting freshclam"
+ start-stop-daemon --start --quiet \
+ --nicelevel ${FRESHCLAM_NICELEVEL:-0} \
+ --exec /usr/bin/freshclam -- -d
+ retcode=$?
+ if [ ${retcode} = 1 ]; then
+ eend 0
+ einfo "Virus databases are already up to date."
+ else
+ eend ${retcode} "Failed to start freshclam"
+ fi
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet --name ${NAME}
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading ${NAME}"
+ if ! service_started "${NAME}" ; then
+ eend 1 "${NAME} is not started"
+ return 1
+ fi
+ start-stop-daemon --stop --oknodo --signal HUP \
+ --exec ${DAEMON} --name $NAME
+ eend $?
+}
+
+
+logfix() {
+ # fix freshclam log permissions
+ # (might be clobbered by logrotate or something)
+ logfile=$(awk '$1 == "UpdateLogFile" { print $2 }' $CONF)
+ local freshclam_user=$(awk '$1 == "DatabaseOwner" { print $2 }' $CONF)
+ if [ -n "${logfile}" -a -n "${clamav_user}" ]; then
+ if [ ! -f "${logfile}" ]; then
+ touch ${logfile}
+ fi
+ chown ${freshclam_user} ${logfile}
+ chmod 640 ${logfile}
+ fi
+}
+
diff --git a/main/clamav/freshclam.logrotate b/main/clamav/freshclam.logrotate
new file mode 100644
index 0000000000..df42d6084f
--- /dev/null
+++ b/main/clamav/freshclam.logrotate
@@ -0,0 +1,7 @@
+/var/log/clamav/freshclam.log {
+ missingok
+ postrotate
+ /etc/init.d/freshclam logfix
+ /bin/kill -HUP `cat /var/run/clamav/freshclam.pid 2> /dev/null` 2>/dev/null || true
+ endscript
+}
diff --git a/main/clamsmtp/APKBUILD b/main/clamsmtp/APKBUILD
new file mode 100644
index 0000000000..372ed1a43f
--- /dev/null
+++ b/main/clamsmtp/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=clamsmtp
+pkgver=1.10
+pkgrel=9
+pkgdesc="An SMTP Virus Filter"
+url="http://memberwebs.com/stef/software/clamsmtp/"
+arch="all"
+license="as-is"
+depends=
+makedepends=
+install="$pkgname.pre-install $pkgname.pre-upgrade $pkgname.post-upgrade"
+subpackages="$pkgname-doc"
+source="http://memberwebs.com/stef/software/clamsmtp/${pkgname}-${pkgver}.tar.gz
+ clamsmtpd.confd
+ clamsmtpd.initd
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+
+ # set default clam address and user
+ sed -e 's|^\#ClamAddress:.*|ClamAddress: /var/run/clamav/clamd.sock|'\
+ -e 's|^\#User:.*|User: clamav|' \
+ -i doc/clamsmtpd.conf
+
+ install -Dm644 doc/clamsmtpd.conf "$pkgdir"/etc/clamsmtpd.conf
+ install -Dm755 "$srcdir"/clamsmtpd.initd "$pkgdir"/etc/init.d/clamsmtpd
+ install -Dm644 "$srcdir"/clamsmtpd.confd "$pkgdir"/etc/conf.d/clamsmtpd
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+md5sums="b068ba6e444859782bbdd88f290c1abf clamsmtp-1.10.tar.gz
+e84205681f64c07af9ec5b6a3dd8bc38 clamsmtpd.confd
+d34b382f2b4b3bc2497eb05f16cfc1ba clamsmtpd.initd"
diff --git a/main/clamsmtp/clamsmtp.post-upgrade b/main/clamsmtp/clamsmtp.post-upgrade
new file mode 100644
index 0000000000..2dbccbb22a
--- /dev/null
+++ b/main/clamsmtp/clamsmtp.post-upgrade
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+moved=
+for i in /etc/runlevels/*/clamsmtp; do
+ if [ -L $i ]; then
+ rm $i
+ ln -s /etc/init.d/clamsmtpd ${i}d
+ moved=1
+ fi
+done
+
+if [ -n "$moved" ]; then
+ echo " *"
+ echo " * NOTICE: /etc/init.d/clamsmtp is renamed to /etc/init.d/clamsmtpd"
+ echo " *"
+fi
+
diff --git a/main/clamsmtp/clamsmtp.pre-install b/main/clamsmtp/clamsmtp.pre-install
new file mode 100644
index 0000000000..59ac60a44d
--- /dev/null
+++ b/main/clamsmtp/clamsmtp.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -H -s /bin/false -D clamav 2>/dev/null
+exit 0
diff --git a/main/clamsmtp/clamsmtp.pre-upgrade b/main/clamsmtp/clamsmtp.pre-upgrade
new file mode 100644
index 0000000000..97d90817be
--- /dev/null
+++ b/main/clamsmtp/clamsmtp.pre-upgrade
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+old=/etc/conf.d/clamsmtp
+new=/etc/conf.d/clamsmtpd
+
+if [ -f "$old" ] && [ ! -f "$new" ]; then
+ mv "$old" "$new"
+ echo " *"
+ echo " * NOTICE: $old was renamed to $new"
+ echo " *"
+fi
+
+adduser -H -s /bin/false -D clamav 2>/dev/null
+exit 0
diff --git a/main/clamsmtp/clamsmtpd.confd b/main/clamsmtp/clamsmtpd.confd
new file mode 100644
index 0000000000..8d08b6868c
--- /dev/null
+++ b/main/clamsmtp/clamsmtpd.confd
@@ -0,0 +1,5 @@
+#
+# Specify daemon $OPTS here.
+#
+
+OPTS=""
diff --git a/main/clamsmtp/clamsmtpd.initd b/main/clamsmtp/clamsmtpd.initd
new file mode 100644
index 0000000000..9be17d0959
--- /dev/null
+++ b/main/clamsmtp/clamsmtpd.initd
@@ -0,0 +1,23 @@
+#!/sbin/runscript
+
+NAME=clamsmtpd
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet \
+ --exec ${DAEMON} -- ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --exec ${DAEMON}
+ eend $?
+}
diff --git a/main/claws-mail/APKBUILD b/main/claws-mail/APKBUILD
new file mode 100644
index 0000000000..ce1e0d34d4
--- /dev/null
+++ b/main/claws-mail/APKBUILD
@@ -0,0 +1,61 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=claws-mail
+pkgver=3.7.9
+pkgrel=2
+pkgdesc="A GTK+ based e-mail client."
+url="http://www.claws-mail.org"
+arch="all"
+license="GPL3"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="gtk+-dev openssl-dev startup-notification-dev enchant-dev
+ libsm-dev gnutls-dev curl-dev dbus-glib-dev libetpan-dev openldap-dev"
+depends=
+install=
+source="http://downloads.sourceforge.net/sourceforge/sylpheed-claws/$pkgname-$pkgver.tar.bz2
+ libc-version.patch
+ startup-notification-segfault.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1 ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-static \
+ --enable-enchant \
+ --enable-gnutls \
+ --enable-ldap \
+ --disable-dillo-viewer-plugin \
+ --disable-crash-dialog \
+ --enable-pgpmime-plugin \
+ --enable-spamassassin-plugin \
+ --enable-bogofilter-plugin \
+ --disable-jpilot \
+ || return 1
+
+ # force disabling of backtrace. the core dump was more useful
+ sed -i -e '/HAVE_BACKTRACE/d' config.h
+
+ make || return 1
+ cd tools
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ find tools -maxdepth 1 -type f -and -perm /111 -or -name '*.conf' | while read i; do
+ install -D -m755 ${i} "$pkgdir"/usr/lib/claws-mail/tools/${i}
+ done
+}
+md5sums="2f9d2dcabf84e312cfeb56efa799b5b3 claws-mail-3.7.9.tar.bz2
+f3416743b5d8ff97b5a3cc2f7efc2dc1 libc-version.patch
+1f0773ab009c966dd8b587422890247e startup-notification-segfault.patch"
diff --git a/main/claws-mail/libc-version.patch b/main/claws-mail/libc-version.patch
new file mode 100644
index 0000000000..c55c007baf
--- /dev/null
+++ b/main/claws-mail/libc-version.patch
@@ -0,0 +1,22 @@
+--- a/src/crash.c.orig 2009-09-05 22:12:33.000000000 +0000
++++ b/src/crash.c 2009-09-05 22:14:34.000000000 +0000
+@@ -42,7 +42,7 @@
+ # include <sys/utsname.h>
+ #endif
+
+-#if defined(__GNU_LIBRARY__)
++#if defined(__GNU_LIBRARY__) && !defined(__UCLIBC__)
+ # include <gnu/libc-version.h>
+ #endif
+
+@@ -446,7 +446,9 @@
+ */
+ static const gchar *get_lib_version(void)
+ {
+-#if defined(__GNU_LIBRARY__)
++#if defined(__UCLIBC__)
++ return g_strdup_printf("uClibc");
++#elif defined(__GNU_LIBRARY__)
+ return g_strdup_printf("GNU libc %s", gnu_get_libc_version());
+ #else
+ return g_strdup(_("Unknown"));
diff --git a/main/claws-mail/startup-notification-segfault.patch b/main/claws-mail/startup-notification-segfault.patch
new file mode 100644
index 0000000000..ef36e42fae
--- /dev/null
+++ b/main/claws-mail/startup-notification-segfault.patch
@@ -0,0 +1,18 @@
+Index: src/main.c
+===================================================================
+RCS file: //claws/src/main.c,v
+retrieving revision 1.115.2.237
+retrieving revision 1.115.2.238
+diff -u -r1.115.2.237 -r1.115.2.238
+--- ./src/main.c 10 Apr 2011 17:19:04 -0000 1.115.2.237
++++ ./src/main.c 30 Apr 2011 19:27:15 -0000 1.115.2.238
+@@ -331,7 +331,7 @@
+ gtk_widget_show(hack);
+ }
+
+- xdisplay = gdk_display_get_default();
++ xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+ sn_display = sn_display_new(xdisplay,
+ sn_error_trap_push,
+ sn_error_trap_pop);
+
diff --git a/main/cmake/APKBUILD b/main/cmake/APKBUILD
new file mode 100644
index 0000000000..bb42f41d8e
--- /dev/null
+++ b/main/cmake/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cmake
+pkgver=2.8.4
+pkgrel=0
+pkgdesc="CMake is a cross-platform open-source make system"
+url="http://www.cmake.org"
+arch="all"
+license="CMake"
+depends=
+makedepends="ncurses-dev"
+source="http://www.$pkgname.org/files/v${pkgver%.*}/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-doc"
+
+
+parallel_opt() {
+ local i n
+ for i in $MAKEOPTS; do
+ case "$i" in
+ -j*) n=${i#-j};;
+ esac;
+ done
+ [ -n "$n" ] && echo "--parallel $n"
+}
+
+build ()
+{
+ cd $startdir/src/$pkgname-$pkgver
+ # bug in cmake.
+ # http://www.mail-archive.com/cmake@cmake.org/msg09515.html
+# export CC="gcc"
+# export CXX="g++"
+
+ ./bootstrap --prefix=/usr \
+ --mandir=/share/man \
+ --docdir=/share/cmake-${pkgver%.*}/doc \
+ $(parallel_opt)
+
+ make || return 1
+}
+
+package() {
+ cd $startdir/src/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="209b7d1d04b2e00986538d74ba764fcf cmake-2.8.4.tar.gz"
diff --git a/main/cmph/APKBUILD b/main/cmph/APKBUILD
new file mode 100644
index 0000000000..93a7887989
--- /dev/null
+++ b/main/cmph/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor:
+# Maintainer:
+pkgname=cmph
+pkgver=0.9
+pkgrel=2
+pkgdesc="minimal perfect hash C library - utility application"
+url="http://cmph.sourceforge.net/"
+arch="all"
+license="LGPL MPL-1.1"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev $pkgname-doc libcmph:lib"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+lib() {
+ pkgdesc="minimal perfect hash C library - utility application"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libcmph*.so.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="14c17e3058174e9333936caa8e18ed28 cmph-0.9.tar.gz"
diff --git a/main/collectd/APKBUILD b/main/collectd/APKBUILD
new file mode 100644
index 0000000000..6d0a512584
--- /dev/null
+++ b/main/collectd/APKBUILD
@@ -0,0 +1,92 @@
+# Contributor:
+# Maintainer:
+pkgname=collectd
+pkgver=5.0.0
+pkgrel=2
+pkgdesc="The system statistics collection daemon"
+url="http://collectd.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="pkgconfig curl-dev net-snmp-dev postgresql-dev perl-dev
+ libgcrypt-dev mysql-dev zlib-dev openssl-dev iptables-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc $pkgname-perl $pkgname-snmp $pkgname-curl
+ $pkgname-write_http $pkgname-nginx $pkgname-apache $pkgname-postgresql
+ $pkgname-mysql $pkgname-network"
+
+source="http://collectd.org/files/collectd-$pkgver.tar.bz2
+ collectd-4.10.3-iptc-check.patch
+ collectd.initd"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ # we need -lm
+ sed -i -e 's/^collectd_LDADD = \(.*\)/collectd_LDADD = -lm \1/' \
+ -e 's/^collectd_nagios_LDADD = \(.*\)/collectd_nagios_LDADD = -lm \1/' \
+ src/Makefile.in || return 1
+ sed -i -e 's/_LIBADD =/_LIBADD = -lm/' \
+ src/libcollectdclient/Makefile.in || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/collectd \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstate=/var \
+ || return 1
+ make LDADD='-lm' || return 1
+ # disable network plugin by default since its in a subpackage
+ sed -i -e 's/^LoadPlugin network/#LoadPlugin network/' \
+ src/collectd.conf
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/collectd/*.la || return 1
+
+ find "$pkgdir" -name perllocal.pod -delete
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+
+perl() {
+ pkgdesc="perl bindings to collectd"
+ depends="perl"
+ arch="noarch"
+ install -d "$subpkgdir"/usr/lib/ "$subpkgdir"/usr/share
+ mv "$pkgdir"/usr/lib/perl* "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/share/perl* "$subpkgdir"/usr/share/
+}
+
+_plugin() {
+ local mod=$1
+ local desc=${2:-$mod}
+ pkgdesc="$desc pluin for collectd"
+ depends="collectd"
+ install -d "$subpkgdir"/usr/lib/collectd
+ mv "$pkgdir"/usr/lib/collectd/$mod.so "$subpkgdir"/usr/lib/collectd/
+}
+
+snmp() { _plugin snmp; }
+curl() { _plugin curl; }
+write_http() { _plugin write_http; }
+nginx() { _plugin nginx; }
+apache() { _plugin apache; }
+postgresql() { _plugin postgresql; }
+mysql() { _plugin mysql; }
+network() { _plugin network; }
+
+md5sums="7bfea6e82d35b36f16d1da2c71397213 collectd-5.0.0.tar.bz2
+38f2ac1754e0dc0fcc70a04574cc7437 collectd-4.10.3-iptc-check.patch
+13a36ae2f92634b5619ab94224e1b77d collectd.initd"
diff --git a/main/collectd/collectd-4.10.3-iptc-check.patch b/main/collectd/collectd-4.10.3-iptc-check.patch
new file mode 100644
index 0000000000..4358e7f094
--- /dev/null
+++ b/main/collectd/collectd-4.10.3-iptc-check.patch
@@ -0,0 +1,20 @@
+--- ./configure.orig 2011-03-26 17:09:34.000000000 +0100
++++ ./configure 2011-03-29 14:23:54.647074988 +0200
+@@ -36343,13 +36343,13 @@
+ # Check for the iptc_init symbol in the library.
+ if test "x$with_libiptc" = "xyes" && test "x$with_own_libiptc" = "xno"
+ then
+- { echo "$as_me:$LINENO: checking for iptc_init in -liptc" >&5
+-echo $ECHO_N "checking for iptc_init in -liptc... $ECHO_C" >&6; }
+-if test "${ac_cv_lib_iptc_iptc_init+set}" = set; then
++ { echo "$as_me:$LINENO: checking for iptc_init in -lip4tc" >&5
++echo $ECHO_N "checking for iptc_init in -lip4tc... $ECHO_C" >&6; }
++if test "${ac_cv_lib_ip4tc_iptc_init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ ac_check_lib_save_LIBS=$LIBS
+-LIBS="-liptc $LIBS"
++LIBS="-liptc -lip6tc -lip4tc $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h. */
+ _ACEOF
diff --git a/main/collectd/collectd.initd b/main/collectd/collectd.initd
new file mode 100644
index 0000000000..de5705a032
--- /dev/null
+++ b/main/collectd/collectd.initd
@@ -0,0 +1,20 @@
+#!/sbin/runscript
+
+DAEMON=/usr/sbin/collectd
+
+depend() {
+ need net
+}
+
+start() {
+ ebegin "Starting collectd"
+ start-stop-daemon --start --exec $DAEMON -- $collectd_options
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping collectd"
+ start-stop-daemon --stop --exec $DAEMON
+ eend $?
+}
+
diff --git a/main/compositeproto/APKBUILD b/main/compositeproto/APKBUILD
new file mode 100644
index 0000000000..efbcc51422
--- /dev/null
+++ b/main/compositeproto/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=compositeproto
+pkgver=0.4.2
+pkgrel=0
+pkgdesc="X11 Composite extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="fixesproto"
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+md5sums="98482f65ba1e74a08bf5b056a4031ef0 compositeproto-0.4.2.tar.bz2"
diff --git a/main/confuse/APKBUILD b/main/confuse/APKBUILD
new file mode 100644
index 0000000000..c815c7aba3
--- /dev/null
+++ b/main/confuse/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=confuse
+pkgver=2.7
+pkgrel=2
+pkgdesc="C-library for parsing configuration files"
+url="http://www.nongnu.org/confuse"
+arch="all"
+license="LGPL"
+depends=
+makedepends="flex bison pkgconfig"
+subpackages="$pkgname-dev"
+source="http://savannah.nongnu.org/download/confuse/confuse-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ # drop -Werror
+ sed -i -e 's/-Werror//' */Makefile.* || die
+
+ ./configure --prefix=/usr \
+ --enable-shared \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 libconfuse.pc "$pkgdir"/usr/lib/pkgconfig/libconfuse.pc
+}
+md5sums="45932fdeeccbb9ef4228f1c1a25e9c8f confuse-2.7.tar.gz"
diff --git a/main/conky/APKBUILD b/main/conky/APKBUILD
new file mode 100644
index 0000000000..0ff7ecf0d3
--- /dev/null
+++ b/main/conky/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=conky
+pkgver=1.8.1
+pkgrel=1
+pkgdesc="An advanced, highly configurable system monitor for X based on torsmo"
+url="http://conky.sourceforge.net/"
+arch="all"
+license="custom"
+depends=""
+makedepends="pkgconfig alsa-lib-dev libxml2-dev curl-dev wireless-tools-dev
+ libxft-dev glib-dev libxdamage-dev libxext-dev imlib2-dev lua-dev
+ cairo-dev tolua++ ncurses-dev
+ "
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://downloads.sourceforge.net/project/conky/conky/$pkgver/conky-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build ()
+{
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-wlan \
+ --enable-rss \
+ --enable-ibm \
+ --enable-imlib2 \
+ --enable-lua \
+ --enable-lua-cairo \
+ --enable-lua-imlib2 \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 COPYING $pkgdir/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="366dc6a5c2ebebfbe6f53da25061b5d6 conky-1.8.1.tar.bz2"
diff --git a/main/conntrack-tools/APKBUILD b/main/conntrack-tools/APKBUILD
new file mode 100644
index 0000000000..5d9c445e5c
--- /dev/null
+++ b/main/conntrack-tools/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=conntrack-tools
+pkgver=0.9.13
+pkgrel=3
+pkgdesc="Connection tracking userspace tools"
+url="http://conntrack-tools.netfilter.org"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libnfnetlink-dev libnetfilter_conntrack-dev bison flex"
+source="http://www.netfilter.org/projects/conntrack-tools/files/$pkgname-$pkgver.tar.bz2
+ conntrackd.initd
+ conntrackd.confd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+
+ install -Dm755 ../conntrackd.initd "$pkgdir"/etc/init.d/conntrackd
+ install -Dm644 ../conntrackd.confd "$pkgdir"/etc/conf.d/conntrackd
+ install -Dm644 doc/stats/conntrackd.conf "$pkgdir"/etc/conntrackd
+}
+md5sums="bd0e2149a1626071db83c4f9714e0556 conntrack-tools-0.9.13.tar.bz2
+a97e0b7f1339d93caf929fb4767141e1 conntrackd.initd
+8ebf3838b69d20e6bb4a173844502039 conntrackd.confd"
diff --git a/main/conntrack-tools/conntrackd.confd b/main/conntrack-tools/conntrackd.confd
new file mode 100644
index 0000000000..7c937cbd9e
--- /dev/null
+++ b/main/conntrack-tools/conntrackd.confd
@@ -0,0 +1,15 @@
+# conntrackd config file
+# default: /etc/conntrackd/conntrackd.conf
+#CONNTRACKD_CFG=/etc/conntrackd/conntrackd.conf
+
+# conntrackd lockfile (must match the "LockFile" entry
+# from the "General" section in the config file)
+# default: /var/lock/conntrack.lock
+#CONNTRACKD_LOCK=/var/lock/conntrack.lock
+
+# extra options for conntrackd
+#CONNTRACKD_OPTS="" # you must NOT use -C here!
+
+# depend on a specific network interface
+#RC_NEED="net.eth1" # baselayout-1
+#rc_need="net.eth1" # baselayout-2/OpenRC
diff --git a/main/conntrack-tools/conntrackd.initd b/main/conntrack-tools/conntrackd.initd
new file mode 100644
index 0000000000..e307a347ec
--- /dev/null
+++ b/main/conntrack-tools/conntrackd.initd
@@ -0,0 +1,100 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+CONNTRACKD_BIN="/usr/sbin/conntrackd"
+CONNTRACKD_CFG=${CONNTRACKD_CFG:-/etc/conntrackd/conntrackd.conf}
+CONNTRACKD_LOCK=${CONNTRACKD_LOCK:-/var/lock/conntrack.lock}
+
+depend() {
+ use logger
+ need net
+ after firewall
+}
+
+checkconfig() {
+ # check for netfilter conntrack kernel support
+ local nf_ct_available=0
+ for k in net.netfilter.nf_conntrack_max \
+ net.ipv4.netfilter.ip_conntrack_max \
+ net.nf_conntrack_max; do
+ if sysctl -e -n ${k} &>/dev/null; then
+ nf_ct_available=1 # sysctl key found
+ break
+ fi
+ done
+ if [ ${nf_ct_available} -eq 0 ]; then
+ eerror
+ eerror "Your kernel is missing netfilter conntrack support!"
+ eerror "Make sure your kernel was compiled with netfilter conntrack support."
+ eerror
+ eerror "If it was compiled as a module you need to ensure the module is being"
+ eerror "loaded before starting conntrackd."
+ eerror "Either add an entry to /etc/modules.autoload/[...] (for baselayout-1)"
+ eerror "or /etc/conf.d/modules (for baselayout-2/OpenRC) or load the module"
+ eerror "by hand like this, depending on your kernel version:"
+ eerror
+ eerror " modprobe nf_conntrack # (for newer kernels)"
+ eerror " modprobe ip_conntrack # (for older kernels)"
+ eerror
+ return 1
+ fi
+ # check if netfilter conntrack TCP window tracking is disabled
+ local nf_ct_tcp_be_liberal=0
+ for k in net.netfilter.nf_conntrack_tcp_be_liberal \
+ net.ipv4.netfilter.ip_conntrack_tcp_be_liberal; do
+ nf_ct_tcp_be_liberal=$(sysctl -e -n ${k} 2>/dev/null)
+ if [ ${?} -ne 0 ]; then
+ continue # sysctl key not found
+ else
+ break # sysctl key found
+ fi
+ done
+ if [ ${nf_ct_tcp_be_liberal} -ne 1 ]; then
+ eerror
+ eerror "You need to disable TCP window tracking!"
+ eerror "Add the following line to your /etc/sysctl.conf:"
+ eerror
+ eerror " ${k} = 1"
+ eerror
+ eerror "...and run this to activate the setting: sysctl -q -p"
+ eerror
+ return 1
+ fi
+ # check for config file
+ if [ ! -e "${CONNTRACKD_CFG}" ]; then
+ eerror
+ eerror "The conntrackd config file (${CONNTRACKD_CFG})"
+ eerror "is missing!"
+ eerror
+ return 1
+ fi
+ # check for leftover lockfile
+ if [ -f "${CONNTRACKD_LOCK}" ]; then
+ ewarn
+ ewarn "The conntrackd lockfile (${CONNTRACKD_LOCK})"
+ ewarn "exists although the service is not marked as started."
+ ewarn "Will remove the lockfile and start the service in 10s"
+ ewarn "if not interrupted..."
+ ewarn
+ sleep 10
+ if ! rm -f "${CONNTRACKD_LOCK}"; then
+ eerror "Failed to remove the conntrackd lockfile (${CONNTRACKD_LOCK})"
+ return 1
+ fi
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting conntrackd"
+ start-stop-daemon --start --exec "${CONNTRACKD_BIN}" \
+ -- -d -C "${CONNTRACKD_CFG}" ${CONNTRACKD_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping conntrackd"
+ start-stop-daemon --stop --exec "${CONNTRACKD_BIN}"
+ eend $?
+}
diff --git a/main/consolekit/0001-busybox-reboot-and-poweroff-support.patch b/main/consolekit/0001-busybox-reboot-and-poweroff-support.patch
new file mode 100644
index 0000000000..7fa0e35759
--- /dev/null
+++ b/main/consolekit/0001-busybox-reboot-and-poweroff-support.patch
@@ -0,0 +1,41 @@
+From 5e557dd212657f7e75a0c4bd70d11ca06ccb3f84 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Mon, 4 Apr 2011 18:46:25 +0000
+Subject: [PATCH] busybox reboot and poweroff support
+
+---
+ tools/linux/ck-system-restart | 3 +++
+ tools/linux/ck-system-stop | 3 +++
+ 2 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/tools/linux/ck-system-restart b/tools/linux/ck-system-restart
+index 8e0664e..5cabb3d 100755
+--- a/tools/linux/ck-system-restart
++++ b/tools/linux/ck-system-restart
+@@ -7,6 +7,9 @@ if [ -x "/sbin/shutdown" ] ; then
+ elif [ -x "/usr/sbin/shutdown" ] ; then
+ /usr/sbin/shutdown -r now
+ exit $?
++elif [ -x "/sbin/reboot" ]; then
++ /sbin/reboot
++ exit $?
+ else
+ exit 1
+ fi
+diff --git a/tools/linux/ck-system-stop b/tools/linux/ck-system-stop
+index e26bca3..a0be3ac 100755
+--- a/tools/linux/ck-system-stop
++++ b/tools/linux/ck-system-stop
+@@ -7,6 +7,9 @@ if [ -x "/sbin/shutdown" ] ; then
+ elif [ -x "/usr/sbin/shutdown" ] ; then
+ /usr/sbin/shutdown -h now
+ exit $?
++elif [ -x "/sbin/poweroff" ] ; then
++ /sbin/poweroff
++ exit $?
+ else
+ exit 1
+ fi
+--
+1.7.4.2
+
diff --git a/main/consolekit/APKBUILD b/main/consolekit/APKBUILD
new file mode 100644
index 0000000000..7f38f2a68c
--- /dev/null
+++ b/main/consolekit/APKBUILD
@@ -0,0 +1,51 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=consolekit
+pkgver=0.4.5
+pkgrel=1
+pkgdesc="Framework for defining and tracking users, login sessions, and seats"
+url="http://www.freedesktop.org/wiki/Software/ConsoleKit"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="polkit-dev zlib-dev libx11-dev dbus-glib-dev"
+depends_dev="dbus-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.freedesktop.org/software/ConsoleKit/dist/ConsoleKit-$pkgver.tar.bz2
+ 0001-busybox-reboot-and-poweroff-support.patch
+ pam-foreground-compat.ck
+ "
+
+_builddir="$srcdir"/ConsoleKit-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -m 755 "$srcdir"/pam-foreground-compat.ck \
+ "$pkgdir"/usr/lib/ConsoleKit/run-session.d/
+}
+
+md5sums="f2657f93761206922d558471a936fbc3 ConsoleKit-0.4.5.tar.bz2
+acc4f44190cd677f95fd529d528c9cef 0001-busybox-reboot-and-poweroff-support.patch
+d75ed3438dab01552304c06fd9a967b1 pam-foreground-compat.ck"
diff --git a/main/consolekit/pam-foreground-compat.ck b/main/consolekit/pam-foreground-compat.ck
new file mode 100644
index 0000000000..ce221c9749
--- /dev/null
+++ b/main/consolekit/pam-foreground-compat.ck
@@ -0,0 +1,17 @@
+#!/bin/sh
+TAGDIR=/var/run/console
+
+[ -n "$CK_SESSION_USER_UID" ] || exit 1
+[ "$CK_SESSION_IS_LOCAL" = "true" ] || exit 0
+
+TAGFILE="$TAGDIR/`getent passwd $CK_SESSION_USER_UID | cut -f 1 -d:`"
+
+if [ "$1" = "session_added" ]; then
+ mkdir -p "$TAGDIR"
+ echo "$CK_SESSION_ID" >> "$TAGFILE"
+fi
+
+if [ "$1" = "session_removed" ] && [ -e "$TAGFILE" ]; then
+ sed -i "\%^$CK_SESSION_ID\$%d" "$TAGFILE"
+ [ -s "$TAGFILE" ] || rm -f "$TAGFILE"
+fi
diff --git a/main/coova-chilli/APKBUILD b/main/coova-chilli/APKBUILD
new file mode 100644
index 0000000000..a66870f628
--- /dev/null
+++ b/main/coova-chilli/APKBUILD
@@ -0,0 +1,52 @@
+# Contributor: grharry
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=coova-chilli
+pkgver=1.2.7
+pkgrel=1
+pkgdesc="CoovaChilli is an open source access controller for wireless LAN"
+url="http://www.coova.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="perl openssl-dev autoconf automake libtool"
+install=
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://ap.coova.org/chilli/coova-chilli-$pkgver.tar.gz
+ coova-chilli-ssl.patch"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd $_builddir
+# patch -p1 -i ../coova-chilli-ssl.patch || return 1
+ sed -i 's/-Werror//g' src/Makefile.am || return 1
+ sed -i 's/-Werror//g' src/Makefile.in || return 1
+ sed -i 's%(localstatedir)/run%(localstatedir)%' src/Makefile.am || return 1
+ sed -i 's%(localstatedir)/run%(localstatedir)%' src/Makefile.in || return 1
+ aclocal && autoconf && automake && libtoolize || return 1
+}
+
+build() {
+ cd $_builddir
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var/run/chilli \
+ --libdir=/usr/lib \
+ --sysconfdir=/etc \
+ --with-openssl \
+ --enable-dhcpopt
+ make -j1 || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m755 ../../chilli.initd $pkgdir/etc/init.d/chilli
+ mkdir -p $pkgdir/var/run/chilli
+}
+
+md5sums="4c069e254aa7d5329eb18e1fe204b694 coova-chilli-1.2.7.tar.gz
+4135e6e19bafdad777b8ca7388ff4101 coova-chilli-ssl.patch"
diff --git a/main/coova-chilli/chilli.initd b/main/coova-chilli/chilli.initd
new file mode 100755
index 0000000000..fe6ec72d5e
--- /dev/null
+++ b/main/coova-chilli/chilli.initd
@@ -0,0 +1,42 @@
+#!/sbin/runscript
+
+depend() {
+ use net
+ after firewall
+ provide chilli
+}
+
+
+checkconfig() {
+ if [ -f /etc/chilli.conf ]; then
+ return 0;
+ else
+ eerror "Error starting CoovaChilli. Please create /etc/chilli.conf before."
+ return 1;
+ fi
+
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting CoovaChilli Captive Portal"
+
+ echo 1 > /proc/sys/net/ipv4/ip_forward
+ lsmod | grep tun >& /dev/null
+
+ if [ $? -ne 0 ]; then
+ modprobe tun >& /dev/null
+ fi
+
+ start-stop-daemon --start --pidfile /var/run/chilli/chilli.pid --quiet \
+ --exec /usr/sbin/chilli -- --pidfile=/var/run/chilli/chilli.pid
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping CoovaChilli Captive Portal"
+ start-stop-daemon --stop --pidfile /var/run/chilli.pid --quiet
+ eend $?
+}
+
+
diff --git a/main/coova-chilli/coova-chilli-ssl.patch b/main/coova-chilli/coova-chilli-ssl.patch
new file mode 100644
index 0000000000..1567c96cb3
--- /dev/null
+++ b/main/coova-chilli/coova-chilli-ssl.patch
@@ -0,0 +1,21 @@
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -13,7 +13,8 @@
+ chilli.h options.h util.c garden.c garden.h ssl.h ssl.c \
+ dns.c dns.h session.c session.h limits.h pkt.h pkt.c \
+ chksum.c net.h net.c ms_chap.c options.c statusfile.c \
+-conn.h conn.c
++conn.h conn.c
++libchilli_la_LIBADD = $(LIBOPENSSL)
+
+ AM_CFLAGS = -D_GNU_SOURCE -Wall -fno-builtin -fno-strict-aliasing \
+ -O2 -fomit-frame-pointer -funroll-loops -pipe \
+@@ -33,7 +34,7 @@
+ #test_radius_SOURCES = test-radius.c
+ #test_dhcp_SOURCES = test-dhcp.c
+
+-LDADD = libchilli.la $(top_builddir)/bstring/libbstring.la ${LIBRT}
++LDADD = libchilli.la $(top_builddir)/bstring/libbstring.la $(LIBOPENSSL)
+
+ if WITH_OPENSSL
+ LDADD += ${LIBSSL}
diff --git a/main/coreutils/APKBUILD b/main/coreutils/APKBUILD
new file mode 100644
index 0000000000..82e0ed5c5f
--- /dev/null
+++ b/main/coreutils/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=coreutils
+pkgver=8.12
+pkgrel=0
+pkgdesc="The basic file, shell and text manipulation utilities"
+url="http://www.gnu.org/software/coreutils/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install="$pkgname.post-deinstall $pkgname.post-upgrade"
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/gnu/coreutils/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls \
+ --without-gmp \
+ --enable-no-install-program=arch,hostname,su,kill,uptime \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ install -d "$pkgdir"/bin "$pkgdir"/usr/sbin
+ cd "$pkgdir"/usr/bin/
+
+ # binaries that busybox puts in /bin
+ mv base64 cat chgrp chmod chown cp date dd df 'echo' false ln ls \
+ mkdir mknod mktemp mv nice printenv pwd rm rmdir sleep stat \
+ stty sync touch true uname \
+ "$pkgdir"/bin
+
+ mv chroot "$pkgdir"/usr/sbin/
+}
+
+md5sums="fce7999953a67243d00d75cc86dbcaa6 coreutils-8.12.tar.gz"
diff --git a/main/coreutils/coreutils.post-deinstall b/main/coreutils/coreutils.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/coreutils/coreutils.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/coreutils/coreutils.post-upgrade b/main/coreutils/coreutils.post-upgrade
new file mode 120000
index 0000000000..3e2b3c2a22
--- /dev/null
+++ b/main/coreutils/coreutils.post-upgrade
@@ -0,0 +1 @@
+coreutils.post-deinstall \ No newline at end of file
diff --git a/main/cowdancer/APKBUILD b/main/cowdancer/APKBUILD
new file mode 100644
index 0000000000..a741014fde
--- /dev/null
+++ b/main/cowdancer/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=cowdancer
+pkgver=0.63
+pkgrel=0
+pkgdesc="userland copy-on-write filesystem"
+url="http://www.netfort.gr.jp/~dancer/software/cowdancer.html"
+arch="all"
+license="GPL"
+depends=
+depends_dev=
+makedepends="bash $depends_dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://ftp.de.debian.org/debian/pool/main/c/cowdancer/cowdancer_${pkgver}.tar.gz
+ cowdancer-disable-cowbuilder.patch
+ cowdancer-no-vsym.patch"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="8632184e830a041e1a3319d1ed39e31d cowdancer_0.63.tar.gz
+6b59f89cc093670950a3bc00df19d10f cowdancer-disable-cowbuilder.patch
+da87422b0350bcba5bd79cae8b4da596 cowdancer-no-vsym.patch"
diff --git a/main/cowdancer/cowdancer-disable-cowbuilder.patch b/main/cowdancer/cowdancer-disable-cowbuilder.patch
new file mode 100644
index 0000000000..5f76cad31d
--- /dev/null
+++ b/main/cowdancer/cowdancer-disable-cowbuilder.patch
@@ -0,0 +1,42 @@
+--- cowdancer-0.63.orig/Makefile
++++ cowdancer-0.63/Makefile
+@@ -1,5 +1,5 @@
+ SHELL=/bin/bash
+-BINARY=libcowdancer.so cow-shell cowbuilder qemubuilder cowdancer-ilistcreate \
++BINARY=libcowdancer.so cow-shell cowdancer-ilistcreate \
+ cowdancer-ilistdump
+ INSTALL_DIR=install -d -o root -g root -m 755
+ INSTALL_FILE=install -o root -g root -m 644
+@@ -23,19 +23,11 @@
+ $(INSTALL_FILE) cow-shell.1 $(DESTDIR)/usr/share/man/man1/cow-shell.1
+ $(INSTALL_FILE) cowdancer-ilistcreate.1 $(DESTDIR)/usr/share/man/man1/cowdancer-ilistcreate.1
+ $(INSTALL_FILE) cowdancer-ilistdump.1 $(DESTDIR)/usr/share/man/man1/cowdancer-ilistdump.1
+- $(INSTALL_FILE) cowbuilder.8 $(DESTDIR)/usr/share/man/man8/cowbuilder.8
+- $(INSTALL_FILE) qemubuilder.8 $(DESTDIR)/usr/share/man/man8/qemubuilder.8
+ $(INSTALL_FILE) libcowdancer.so $(DESTDIR)${LIBDIR}/cowdancer/libcowdancer.so
+ $(INSTALL_PROGRAM) cow-shell $(DESTDIR)/usr/bin/cow-shell
+- $(INSTALL_PROGRAM) cowbuilder $(DESTDIR)/usr/sbin/cowbuilder
+- $(INSTALL_PROGRAM) qemubuilder $(DESTDIR)/usr/sbin/qemubuilder
+ $(INSTALL_PROGRAM) cowdancer-ilistcreate $(DESTDIR)/usr/bin/cowdancer-ilistcreate
+ $(INSTALL_PROGRAM) cowdancer-ilistdump $(DESTDIR)/usr/bin/cowdancer-ilistdump
+
+- $(INSTALL_DIR) $(DESTDIR)/etc/bash_completion.d
+- $(INSTALL_FILE) bash_completion.qemubuilder $(DESTDIR)/etc/bash_completion.d/qemubuilder
+- $(INSTALL_FILE) bash_completion.cowbuilder $(DESTDIR)/etc/bash_completion.d/cowbuilder
+-
+ libcowdancer.so: cowdancer.lo ilistcreate.lo
+ $(CC) $(CFLAGS) -ldl -shared -o $@ $^
+
+@@ -43,12 +35,6 @@
+ $(CC) $(CFLAGS) -o $@ $^
+
+ cowdancer-ilistcreate: cowdancer-ilistcreate.o ilistcreate.o
+- $(CC) $(CFLAGS) -o $@ $^
+-
+-cowbuilder: cowbuilder.o parameter.o forkexec.o ilistcreate.o main.o
+- $(CC) $(CFLAGS) -o $@ $^
+-
+-qemubuilder: qemubuilder.lfso parameter.lfso forkexec.lfso qemuipsanitize.lfso qemuarch.lfso file.lfso main.lfso
+ $(CC) $(CFLAGS) -o $@ $^
+
+ %.lo: %.c
diff --git a/main/cowdancer/cowdancer-no-vsym.patch b/main/cowdancer/cowdancer-no-vsym.patch
new file mode 100644
index 0000000000..b244fc930c
--- /dev/null
+++ b/main/cowdancer/cowdancer-no-vsym.patch
@@ -0,0 +1,33 @@
+--- cowdancer-0.63.orig/cowdancer.c
++++ cowdancer-0.63/cowdancer.c
+@@ -174,29 +174,7 @@
+ origlibc_fopen = dlsym(RTLD_NEXT, "fopen64");
+ origlibc_fopen64 = dlsym(RTLD_NEXT, "fopen64");
+ dlerror();
+- if (!(origlibc_chown = dlvsym(RTLD_NEXT, "chown", "GLIBC_2.1")))
+- {
+- /* I should really check dlerror, but due to a possible bug in glibc,
+- dlerror doesn't seem to work at all.
+- */
+- const char* d=dlerror();
+- if(!d)
+- {
+- debug_cowdancer("dlerror does not return anything, chown returned NULL but OK");
+- /* success */
+- }
+- else
+- {
+- debug_cowdancer(d);
+- }
+-
+-
+- /* fallback to loading unversioned symbol doing it anyway
+- since glibc does not seem to set dlerror on dlsym failure.
+- */
+- origlibc_chown = dlsym(RTLD_NEXT, "chown");
+-
+- }
++ origlibc_chown = dlsym(RTLD_NEXT, "chown");
+ origlibc_fchown = dlsym(RTLD_NEXT, "fchown");
+ origlibc_lchown = dlsym(RTLD_NEXT, "lchown");
+ origlibc_chmod = dlsym(RTLD_NEXT, "chmod");
diff --git a/main/cpufreqd/APKBUILD b/main/cpufreqd/APKBUILD
new file mode 100644
index 0000000000..803914dd2c
--- /dev/null
+++ b/main/cpufreqd/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cpufreqd
+pkgver=2.4.2
+pkgrel=2
+pkgdesc="A small daemon to adjust cpu speed (and indeed voltage)"
+url="http://sourceforge.net/projects/cpufreqd"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-doc"
+depends=
+makedepends="cpufrequtils-dev sysfsutils-dev"
+install=
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2
+ cpufreqd.initd"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc
+ make LIBS=-lpthread || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm 755 ../cpufreqd.initd "$pkgdir"/etc/init.d/cpufreqd \
+ || return 1
+}
+md5sums="2ca80a77849c9a69b81e27c1843c97f5 cpufreqd-2.4.2.tar.bz2
+4c3298abc888ac4f688249ee542ce784 cpufreqd.initd"
diff --git a/main/cpufreqd/cpufreqd.initd b/main/cpufreqd/cpufreqd.initd
new file mode 100644
index 0000000000..fbacebad75
--- /dev/null
+++ b/main/cpufreqd/cpufreqd.initd
@@ -0,0 +1,43 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-power/cpufreqd/files/cpufreqd-init.d,v 1.1 2007/05/17 08:51:45 phreak Exp $
+
+CONFIGFILE=/etc/cpufreqd.conf
+
+depend() {
+ need localmount
+ use logger lm_sensors
+}
+
+checkconfig() {
+ if [ ! -f ${CONFIGFILE} ]; then
+ eerror "Configuration file ${CONFIGFILE} not found"
+ return 1
+ fi
+
+ if [ ! -e /proc/cpufreq ] ; then
+ for cpu in /sys/devices/system/cpu/cpu[0-9]* ; do
+ # We need just one cpu supporting freq scaling.
+ [ -e ${cpu}/cpufreq ] && return 0
+ done
+ eerror "cpufreqd requires the kernel to be configured with CONFIG_CPU_FREQ"
+ eerror "Make sure that the appropiate drivers for your CPU are available."
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting CPU Frequency Daemon"
+ start-stop-daemon --start --exec /usr/sbin/cpufreqd -- \
+ -f ${CONFIGFILE}
+ eend ${?}
+}
+
+stop() {
+ ebegin "Stopping CPU Frequency Daemon"
+ start-stop-daemon --stop --exec /usr/sbin/cpufreqd
+ eend ${?}
+}
diff --git a/main/cpufrequtils/0001-Support-for-Position-Independet-Code-by-aboid-clobbe.patch b/main/cpufrequtils/0001-Support-for-Position-Independet-Code-by-aboid-clobbe.patch
new file mode 100644
index 0000000000..b10d2e5635
--- /dev/null
+++ b/main/cpufrequtils/0001-Support-for-Position-Independet-Code-by-aboid-clobbe.patch
@@ -0,0 +1,33 @@
+From 4c6552d2df2912a710cab6acf476347a7fbf15a0 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Wed, 1 Sep 2010 09:12:44 +0000
+Subject: [PATCH] Support for Position Independet Code by aboid clobbering PIC register
+
+Do not use the PIC register (ebx)
+See http://www.gentoo.org/proj/en/hardened/pic-fix-guide.xml#doc_chap5
+---
+ utils/cpuid.h | 7 +++++--
+ 1 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/utils/cpuid.h b/utils/cpuid.h
+index 2bac69a..ebcec7c 100644
+--- a/utils/cpuid.h
++++ b/utils/cpuid.h
+@@ -5,9 +5,12 @@ static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+ {
+ /* ecx is often an input as well as an output. */
+- asm volatile("cpuid"
++ asm volatile(
++ "movl %%ebx, %%esi;"
++ "cpuid;"
++ "xchg %%ebx, %%esi;"
+ : "=a" (*eax),
+- "=b" (*ebx),
++ "=S" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (*eax), "2" (*ecx));
+--
+1.7.2.2
+
diff --git a/main/cpufrequtils/APKBUILD b/main/cpufrequtils/APKBUILD
new file mode 100644
index 0000000000..2c3d32a048
--- /dev/null
+++ b/main/cpufrequtils/APKBUILD
@@ -0,0 +1,47 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cpufrequtils
+pkgver=008
+pkgrel=1
+pkgdesc="Userspace tools for the kernel cpufreq subsystem"
+url="http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="sysfsutils"
+makedepends="sysfsutils-dev libtool"
+source="http://www.kernel.org/pub/linux/utils/kernel/cpufreq/$pkgname-$pkgver.tar.bz2
+ cpufrequtils-006-nls.patch
+ 0001-Support-for-Position-Independet-Code-by-aboid-clobbe.patch
+ $pkgname.initd
+ $pkgname.confd"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
+ # distcc and ccache makes libtool confused about the tag.
+ # we save 4k by disabling the 2.4 kernel support (PROC=false)
+ make -j1 LIBTOOL_OPT="--tag=CC --silent" \
+ NLS=false \
+ PROC=false \
+ || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make mandir=/usr/share/man \
+ NLS=false \
+ INSTALL=install \
+ DESTDIR="$pkgdir" \
+ install || return 1
+ install -D -m755 ../$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -D -m644 ../$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+md5sums="c59b71c044d463896f3247e8dd83dd7e cpufrequtils-008.tar.bz2
+aa4c6f19766a741a68ae1ad352c6bad9 cpufrequtils-006-nls.patch
+9f999b70138d84580894df48340e50cc 0001-Support-for-Position-Independet-Code-by-aboid-clobbe.patch
+b9b80ef2f1b6c5e7ce0476037a8bce6b cpufrequtils.initd
+d47ff635eef03248c633486eaeec191d cpufrequtils.confd"
diff --git a/main/cpufrequtils/cpufrequtils-006-nls.patch b/main/cpufrequtils/cpufrequtils-006-nls.patch
new file mode 100644
index 0000000000..7d1c24dbd5
--- /dev/null
+++ b/main/cpufrequtils/cpufrequtils-006-nls.patch
@@ -0,0 +1,75 @@
+diff --git a/Makefile b/Makefile
+index 19f3dd6..b7f1e56 100644
+--- a/Makefile
++++ b/Makefile
+@@ -147,6 +147,7 @@ endif
+ ifeq ($(strip $(NLS)),true)
+ INSTALL_NLS += install-gmo
+ COMPILE_NLS += update-gmo
++ CFLAGDEF += -DNLS
+ endif
+
+ ifeq ($(strip $(CPUFRQ_BENCH)),true)
+diff --git a/utils/info.c b/utils/info.c
+index 38d906a..155e604 100644
+--- a/utils/info.c
++++ b/utils/info.c
+@@ -10,7 +10,6 @@
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <libintl.h>
+ #include <locale.h>
+
+ #include <getopt.h>
+@@ -18,9 +17,18 @@
+ #include "cpufreq.h"
+
+
++#ifdef NLS
++#include <libintl.h>
+ #define _(String) gettext (String)
+ #define gettext_noop(String) String
+ #define N_(String) gettext_noop (String)
++#else
++#define gettext_noop(String) String
++#define _(String) gettext_noop (String)
++#define gettext(String) gettext_noop (String)
++#define N_(String) gettext_noop (String)
++#define textdomain(String)
++#endif
+
+ #define LINE_LEN 10
+
+diff --git a/utils/set.c b/utils/set.c
+index 2ece47e..312cc8c 100644
+--- a/utils/set.c
++++ b/utils/set.c
+@@ -12,16 +12,24 @@
+ #include <limits.h>
+ #include <string.h>
+ #include <ctype.h>
+-#include <libintl.h>
+ #include <locale.h>
+
+ #include <getopt.h>
+
+ #include "cpufreq.h"
+
+-#define _(String) gettext(String)
++#ifdef NLS
++#include <libintl.h>
++#define _(String) gettext (String)
++#define gettext_noop(String) String
++#define N_(String) gettext_noop (String)
++#else
+ #define gettext_noop(String) String
+-#define N_(String) gettext_noop(String)
++#define _(String) gettext_noop (String)
++#define gettext(String) gettext_noop (String)
++#define N_(String) gettext_noop (String)
++#define textdomain(String)
++#endif
+
+ #define NORM_FREQ_LEN 32
+
diff --git a/main/cpufrequtils/cpufrequtils.confd b/main/cpufrequtils/cpufrequtils.confd
new file mode 100644
index 0000000000..68f5b7594c
--- /dev/null
+++ b/main/cpufrequtils/cpufrequtils.confd
@@ -0,0 +1,7 @@
+# /etc/conf.d/cpufrequtils: config file for /etc/init.d/cpufrequtils
+
+# Options when starting cpufreq (given to the `cpufreq-set` program)
+START_OPTS="--governor ondemand"
+
+# Options when stopping cpufreq (given to the `cpufreq-set` program)
+STOP_OPTS="--governor performance"
diff --git a/main/cpufrequtils/cpufrequtils.initd b/main/cpufrequtils/cpufrequtils.initd
new file mode 100644
index 0000000000..9aadd94c10
--- /dev/null
+++ b/main/cpufrequtils/cpufrequtils.initd
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-power/cpufrequtils/files/cpufrequtils-init.d-005,v 1.2 2008/10/21 21:20:59 vapier Exp $
+
+affect_change() {
+ local c ret=0
+ ebegin "Running cpufreq-set $*"
+ for c in $(cpufreq-info -o | awk '$1 == "CPU" { print $2 }') ; do
+ cpufreq-set -c ${c} $*
+ : $((ret+=$?))
+ done
+ eend ${ret}
+}
+
+start() {
+ affect_change ${START_OPTS}
+}
+
+stop() {
+ affect_change ${STOP_OPTS}
+}
diff --git a/main/cracklib-words/APKBUILD b/main/cracklib-words/APKBUILD
new file mode 100644
index 0000000000..5fc2de7864
--- /dev/null
+++ b/main/cracklib-words/APKBUILD
@@ -0,0 +1,22 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer:
+pkgname=cracklib-words
+pkgver=20080507
+pkgrel=1
+pkgdesc="Large list of words for crack/craclib"
+url="http://sourceforge.net/projects/cracklib"
+arch="all"
+license="public domain"
+depends=""
+makedepends=""
+install=
+subpackages=""
+source="http://downloads.sourceforge.net/cracklib/$pkgname-$pkgver.gz"
+
+build() {
+ cd "$srcdir"
+ gunzip "$pkgname-$pkgver".gz
+ install -m644 -D "$pkgname-$pkgver" "$pkgdir"/usr/share/dict/cracklib-words
+}
+
+md5sums="7fa6ba0cd50e7f9ccaf4707c810b14f1 cracklib-words-20080507.gz"
diff --git a/main/cracklib/APKBUILD b/main/cracklib/APKBUILD
new file mode 100644
index 0000000000..323a429fca
--- /dev/null
+++ b/main/cracklib/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=cracklib
+pkgver=2.8.16
+pkgrel=2
+pkgdesc="A library used to enforce strong passwords"
+url="http://sourceforge.net/projects/cracklib"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ cracklib-nls.patch
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 -i "$srcdir"/cracklib-nls.patch
+}
+
+build() {
+
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --without-python \
+ --disable-nls \
+ --with-default-dict
+ make -j1 all || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+}
+
+md5sums="3bfb22db8fcffd019463ee415a1b25b7 cracklib-2.8.16.tar.gz
+239b1b7b59bee4dee7577aa9df18ba46 cracklib-nls.patch"
diff --git a/main/cracklib/cracklib-nls.patch b/main/cracklib/cracklib-nls.patch
new file mode 100644
index 0000000000..3792b741c4
--- /dev/null
+++ b/main/cracklib/cracklib-nls.patch
@@ -0,0 +1,12 @@
+--- ./util/check.c.orig
++++ ./util/check.c
+@@ -22,7 +22,9 @@
+ int i;
+
+ setlocale(LC_ALL, "");
++#if defined(ENABLE_NLS)
+ textdomain(PACKAGE);
++#endif
+
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ while (((i = strlen(buf)) > 0) && (i > 0)) {
diff --git a/main/cramfs/APKBUILD b/main/cramfs/APKBUILD
new file mode 100644
index 0000000000..b4e5d83ab3
--- /dev/null
+++ b/main/cramfs/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cramfs
+pkgver=1.1
+pkgrel=2
+pkgdesc="Linux filesystem designed to be simple, small, and to compress things well"
+arch="all"
+url="http://sourceforge.net/projects/cramfs/"
+license='GPL'
+depends=
+makedepends="zlib-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make CFLAGS="$CFLAGS" || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ install -d "$pkgdir"/sbin
+ install mkcramfs cramfsck "$pkgdir"/sbin
+}
+
+md5sums="d3912b9f7bf745fbfea68f6a9b9de30f cramfs-1.1.tar.gz"
diff --git a/main/cryptsetup/APKBUILD b/main/cryptsetup/APKBUILD
new file mode 100644
index 0000000000..ff6d5c2df6
--- /dev/null
+++ b/main/cryptsetup/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cryptsetup
+pkgver=1.3.1
+pkgrel=1
+pkgdesc="Userspace setup tool for transparent encryption of block devices using the Linux 2.6 cryptoapi"
+url="http://code.google.com/p/cryptsetup/"
+arch="all"
+license="GPL"
+depends=
+makedepends="lvm2-dev openssl-dev popt-dev util-linux-ng-dev !libiconv-dev"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-libs"
+source="http://$pkgname.googlecode.com/files/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --libdir=/lib \
+ --sbindir=/sbin \
+ --disable-static \
+ --with-crypto_backend=openssl \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR=$pkgdir install
+}
+
+libs() {
+ pkgdesc="Cryptsetup shared library"
+ mkdir -p "$subpkgdir"
+ mv "$pkgdir"/lib "$subpkgdir"/
+}
+
+md5sums="1f5b5a9d538e8a3c191fb7dd85b9b013 cryptsetup-1.3.1.tar.bz2"
diff --git a/main/ctags/APKBUILD b/main/ctags/APKBUILD
new file mode 100644
index 0000000000..49cd2225c9
--- /dev/null
+++ b/main/ctags/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+pkgname=ctags
+pkgver=5.8
+pkgrel=2
+pkgdesc="Generator of tags for all types of C/C++ languages"
+url="http://ctags.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages=""
+source="http://prdownloads.sourceforge.net/ctags/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+
+ install -m755 -D $pkgname "$pkgdir"/usr/bin/$pkgname
+}
+
+md5sums="c00f82ecdcc357434731913e5b48630d ctags-5.8.tar.gz"
diff --git a/main/cups/APKBUILD b/main/cups/APKBUILD
new file mode 100644
index 0000000000..a4610613a6
--- /dev/null
+++ b/main/cups/APKBUILD
@@ -0,0 +1,97 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cups
+pkgver=1.4.7
+pkgrel=0
+pkgdesc="The CUPS Printing System"
+url="http://www.cups.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc libcups $pkgname-client"
+makedepends="openssl-dev libpaper-dev dbus-dev jpeg-dev>=8 zlib-dev"
+depends="cups-client poppler-utils"
+install=
+pkggroups="lp lpadmin"
+pkgusers="lp"
+source="ftp://ftp.easysw.com/pub/$pkgname/$pkgver/$pkgname-$pkgver-source.tar.bz2
+ $pkgname.logrotate
+ cupsd.initd
+ "
+
+depends_dev="openssl-dev zlib-dev"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --with-logdir=/var/log/cups \
+ --with-docdir=/usr/share/cups/doc \
+ --with-cups-user=lp \
+ --with-cups-group=lp \
+ --with-system-groups=lpadmin \
+ --without-php \
+ --disable-pam \
+ --disable-ldap \
+ --libdir=/usr/lib \
+ --enable-raw-printing \
+ --enable-dbus \
+ --with-dbusdir=/etc/dbus-1 \
+ --enable-libpaper \
+ --enable-ssl=yes \
+ --enable-gnutls \
+ --enable-pdftops \
+ --with-pdftops=pdftops \
+ --with-optim="$CFLAGS"
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make BUILDROOT="$pkgdir" install
+ rm -rf "$pkgdir"/etc/init.d "$pkgdir"/etc/rc*
+
+ install -D -m644 ../cups.logrotate "$pkgdir"/etc/logrotate.d/cups
+ install -D -m755 ../cupsd.initd "$pkgdir"/etc/init.d/cupsd
+
+ sed -i 's|^Exec=htmlview http://localhost:631/|Exec=xdg-open http://localhost:631/|g' "$pkgdir"/usr/share/applications/cups.desktop
+ find "$pkgdir"/usr/share/cups/model -name "*.ppd" | xargs gzip -n9f
+}
+
+_mv() {
+ for i in "$@"; do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/${i%/*}/ || return 1
+ done
+}
+
+libcups() {
+ pkgdesc="CUPS libraries"
+ depends=
+ _mv usr/lib/*.so*
+ install -d "$pkgdir"/etc/cups
+}
+
+client() {
+ pkgdesc="CUPS client"
+ depends=
+ _mv usr/bin \
+ usr/share/cups/charsets \
+ usr/share/cups/charmaps \
+ usr/sbin/accept \
+ usr/sbin/cupsaddsmb \
+ usr/sbin/cupsctl \
+ usr/sbin/cupsdisable \
+ usr/sbin/cupsenable \
+ usr/sbin/lpadmin \
+ usr/sbin/lpc \
+ usr/sbin/lpinfo \
+ usr/sbin/lpmove \
+ usr/sbin/reject
+ touch "$subpkgdir"/usr/share/cups/charmaps/us-ascii.txt
+}
+
+md5sums="1590033ab4c739b859aeb672fe849089 cups-1.4.7-source.tar.bz2
+f861b18f4446c43918c8643dcbbd7f6d cups.logrotate
+1154ed66fdcfa0523f929a369079f43c cupsd.initd"
diff --git a/main/cups/cups.logrotate b/main/cups/cups.logrotate
new file mode 100644
index 0000000000..9c49bbdaff
--- /dev/null
+++ b/main/cups/cups.logrotate
@@ -0,0 +1,8 @@
+/var/log/cups/*log {
+ missingok
+ notifempty
+ delaycompress
+ postrotate
+ /bin/kill -HUP `cat /var/run/cups.pid 2>/dev/null` 2>/dev/null || true
+ endscript
+}
diff --git a/main/cups/cupsd.initd b/main/cups/cupsd.initd
new file mode 100644
index 0000000000..f59e27b4c4
--- /dev/null
+++ b/main/cups/cupsd.initd
@@ -0,0 +1,20 @@
+#!/sbin/runscript
+
+depend() {
+ use net
+ need dbus
+ before nfs
+ after logger
+}
+
+start() {
+ ebegin "Starting cupsd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/cupsd
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping cupsd"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/cupsd
+ eend $?
+}
diff --git a/main/curl/APKBUILD b/main/curl/APKBUILD
new file mode 100644
index 0000000000..f020b9766f
--- /dev/null
+++ b/main/curl/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=curl
+pkgver=7.21.7
+pkgrel=1
+pkgdesc="An URL retrival utility and library"
+url="http://curl.haxx.se"
+arch="all"
+license="MIT"
+depends=
+depends_dev="zlib-dev openssl-dev"
+makedepends="$depends_dev"
+source="http://curl.haxx.se/download/curl-$pkgver.tar.bz2"
+subpackages="$pkgname-doc $pkgname-dev"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --without-libidn \
+ --enable-ipv6 \
+ --disable-ldap
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="5f6d50c4d4ee38c57fe37e3cff75adbd curl-7.21.7.tar.bz2"
diff --git a/main/cutter/APKBUILD b/main/cutter/APKBUILD
new file mode 100644
index 0000000000..d4701a8f06
--- /dev/null
+++ b/main/cutter/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=cutter
+pkgver=1.03
+pkgrel=3
+pkgdesc="A program that allows firewall administrators to abort TCP/IP connections."
+url="http://www.lowth.com/cutter"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages=""
+source="http://www.lowth.com/cutter/software/$pkgname-$pkgver.tgz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ #no make install and no configure script
+
+ make || return 1
+
+ mkdir -p "$pkgdir"/usr/sbin/
+
+ install -m755 -D cutter "$pkgdir"/usr/sbin/cutter
+
+}
+
+md5sums="50093db9b64277643969ee75b83ebbd1 cutter-1.03.tgz"
diff --git a/main/cvs/APKBUILD b/main/cvs/APKBUILD
new file mode 100644
index 0000000000..03c7b8f55c
--- /dev/null
+++ b/main/cvs/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cvs
+pkgver=1.12.13
+pkgrel=1
+pkgdesc="Concurrent Versions System"
+url="http://www.nongnu.org/cvs/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="zlib-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/non-gnu/cvs/source/feature/$pkgver/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-external-zlib \
+ --with-tmpdir=/tmp \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+}
+
+md5sums="7a71a2e7a64973ecf255965956a1d338 cvs-1.12.13.tar.gz"
diff --git a/main/cyrus-sasl/APKBUILD b/main/cyrus-sasl/APKBUILD
new file mode 100644
index 0000000000..fb1f52a681
--- /dev/null
+++ b/main/cyrus-sasl/APKBUILD
@@ -0,0 +1,65 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=cyrus-sasl
+pkgver=2.1.23
+pkgrel=8
+pkgdesc="Cyrus Simple Authentication Service Layer (SASL)"
+url="http://cyrusimap.web.cmu.edu/downloads.html#sasl"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc libsasl"
+depends=
+makedepends="db-dev openssl-dev"
+source="ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/$pkgname-$pkgver.tar.gz
+ saslauthd.initd
+ cyrus-sasl-2.1.19-checkpw.c.patch
+ cyrus-sasl-2.1.23-db5-fix.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-anon \
+ --disable-cram \
+ --disable-digest \
+ --disable-gssapi \
+ --enable-login \
+ --disable-otp \
+ --enable-plain \
+ --with-devrandom=/dev/urandom \
+ --mandir=/usr/share/man || return 1
+ # parallell buildds is broken
+ make -j1 || return 1
+}
+
+package() {
+ cd "$srcdir"/cyrus-sasl-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+
+ install -Dm755 ../saslauthd.initd "$pkgdir"/etc/init.d/saslauthd
+}
+
+libsasl() {
+ depends=
+ pkgdesc="Cyrus Simple Authentication and Security Layer (SASL) library"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/lib "$subpkgdir"/usr/
+}
+
+md5sums="2eb0e48106f0e9cd8001e654f267ecbc cyrus-sasl-2.1.23.tar.gz
+ba499a13d8d08d1b97bb0d5cb0b01bcc saslauthd.initd
+e27ddff076342e7a3041c4759817d04b cyrus-sasl-2.1.19-checkpw.c.patch
+b60db0033f61106f8eb7740fa12feba5 cyrus-sasl-2.1.23-db5-fix.patch"
diff --git a/main/cyrus-sasl/cyrus-sasl-2.1.19-checkpw.c.patch b/main/cyrus-sasl/cyrus-sasl-2.1.19-checkpw.c.patch
new file mode 100644
index 0000000000..f7bf44b794
--- /dev/null
+++ b/main/cyrus-sasl/cyrus-sasl-2.1.19-checkpw.c.patch
@@ -0,0 +1,170 @@
+diff -ur ../cyrus-sasl-2.1.19.orig/lib/Makefile.in ./lib/Makefile.in
+--- ../cyrus-sasl-2.1.19.orig/lib/Makefile.in 2004-07-02 21:40:15.000000000 +0200
++++ ./lib/Makefile.in 2004-09-07 13:21:22.746680576 +0200
+@@ -120,7 +120,7 @@
+ JAVA_TRUE = @JAVA_TRUE@
+ LDFLAGS = @LDFLAGS@
+ LIBOBJS = @LIBOBJS@
+-LIBS = @LIBS@
++LIBS = -lcrypt @LIBS@
+ LIBTOOL = @LIBTOOL@
+ LIB_CRYPT = @LIB_CRYPT@
+ LIB_DES = @LIB_DES@
+diff -ur ../cyrus-sasl-2.1.19.orig/lib/checkpw.c ./lib/checkpw.c
+--- ../cyrus-sasl-2.1.19.orig/lib/checkpw.c 2004-03-17 14:58:13.000000000 +0100
++++ ./lib/checkpw.c 2004-09-07 13:21:12.645916147 +0200
+@@ -94,6 +94,23 @@
+ # endif
+ #endif
+
++/******************************
++ * crypt(3) patch start *
++ ******************************/
++char *crypt(const char *key, const char *salt);
++
++/* cleartext password formats */
++#define PASSWORD_FORMAT_CLEARTEXT 1
++#define PASSWORD_FORMAT_CRYPT 2
++#define PASSWORD_FORMAT_CRYPTTRAD 3
++#define PASSWORD_SALT_BUF_LEN 22
++
++/* weeds out crypt(3) password's salt */
++int _sasl_get_salt (char *dest, char *src, int format);
++
++/******************************
++ * crypt(3) patch stop *
++ ******************************/
+
+ /* we store the following secret to check plaintext passwords:
+ *
+@@ -143,7 +160,51 @@
+ "*cmusaslsecretPLAIN",
+ NULL };
+ struct propval auxprop_values[3];
+-
++
++ /******************************
++ * crypt(3) patch start *
++ * for password format check *
++ ******************************/
++ sasl_getopt_t *getopt;
++ void *context;
++ const char *p = NULL;
++ /**
++ * MD5: 12 char salt
++ * BLOWFISH: 16 char salt
++ */
++ char salt[PASSWORD_SALT_BUF_LEN];
++ int password_format;
++
++ /* get password format from auxprop configuration */
++ if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) {
++ getopt(context, NULL, "password_format", &p, NULL);
++ }
++
++ /* set password format */
++ if (p) {
++ /*
++ memset(pass_format_str, '\0', PASSWORD_FORMAT_STR_LEN);
++ strncpy(pass_format_str, p, (PASSWORD_FORMAT_STR_LEN - 1));
++ */
++ /* modern, modular crypt(3) */
++ if (strncmp(p, "crypt", 11) == 0)
++ password_format = PASSWORD_FORMAT_CRYPT;
++ /* traditional crypt(3) */
++ else if (strncmp(p, "crypt_trad", 11) == 0)
++ password_format = PASSWORD_FORMAT_CRYPTTRAD;
++ /* cleartext password */
++ else
++ password_format = PASSWORD_FORMAT_CLEARTEXT;
++ } else {
++ /* cleartext password */
++ password_format = PASSWORD_FORMAT_CLEARTEXT;
++ }
++
++ /******************************
++ * crypt(3) patch stop *
++ * for password format check *
++ ******************************/
++
+ if (!conn || !userstr)
+ return SASL_BADPARAM;
+
+@@ -180,14 +241,31 @@
+ goto done;
+ }
+
+- /* At the point this has been called, the username has been canonified
+- * and we've done the auxprop lookup. This should be easy. */
+- if(auxprop_values[0].name
+- && auxprop_values[0].values
+- && auxprop_values[0].values[0]
+- && !strcmp(auxprop_values[0].values[0], passwd)) {
+- /* We have a plaintext version and it matched! */
+- return SASL_OK;
++
++ /******************************
++ * crypt(3) patch start *
++ ******************************/
++
++ /* get salt */
++ _sasl_get_salt(salt, (char *) auxprop_values[0].values[0], password_format);
++
++ /* crypt(3)-ed password? */
++ if (password_format != PASSWORD_FORMAT_CLEARTEXT) {
++ /* compare password */
++ if (auxprop_values[0].name && auxprop_values[0].values && auxprop_values[0].values[0] && strcmp(crypt(passwd, salt), auxprop_values[0].values[0]) == 0)
++ return SASL_OK;
++ else
++ ret = SASL_BADAUTH;
++ }
++ else if (password_format == PASSWORD_FORMAT_CLEARTEXT) {
++ /* compare passwords */
++ if (auxprop_values[0].name && auxprop_values[0].values && auxprop_values[0].values[0] && strcmp(auxprop_values[0].values[0], passwd) == 0)
++ return SASL_OK;
++ else
++ ret = SASL_BADAUTH;
++ /******************************
++ * crypt(3) patch stop *
++ ******************************/
+ } else if(auxprop_values[1].name
+ && auxprop_values[1].values
+ && auxprop_values[1].values[0]) {
+@@ -975,3 +1053,37 @@
+ #endif
+ { NULL, NULL }
+ };
++
++/* weeds out crypt(3) password's salt */
++int _sasl_get_salt (char *dest, char *src, int format) {
++ int num; /* how many characters is salt long? */
++ switch (format) {
++ case PASSWORD_FORMAT_CRYPT:
++ /* md5 crypt */
++ if (src[1] == '1')
++ num = 12;
++ /* blowfish crypt */
++ else if (src[1] == '2')
++ num = (src[1] == '2' && src[2] == 'a') ? 17 : 16;
++ /* traditional crypt */
++ else
++ num = 2;
++ break;
++
++ case PASSWORD_FORMAT_CRYPTTRAD:
++ num = 2;
++ break;
++
++ default:
++ return 1;
++ }
++
++ /* destroy destination */
++ memset(dest, '\0', (num + 1));
++
++ /* copy salt to destination */
++ strncpy(dest, src, num);
++
++ return 1;
++}
++
diff --git a/main/cyrus-sasl/cyrus-sasl-2.1.23-db5-fix.patch b/main/cyrus-sasl/cyrus-sasl-2.1.23-db5-fix.patch
new file mode 100644
index 0000000000..d9437d0912
--- /dev/null
+++ b/main/cyrus-sasl/cyrus-sasl-2.1.23-db5-fix.patch
@@ -0,0 +1,23 @@
+--- ./sasldb/db_berkeley.c.orig 2010-10-04 21:11:15.044010468 -0400
++++ ./sasldb/db_berkeley.c 2010-10-04 21:12:18.921998718 -0400
+@@ -100,7 +100,7 @@
+ ret = db_create(mbdb, NULL, 0);
+ if (ret == 0 && *mbdb != NULL)
+ {
+-#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1
++#if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) || DB_VERSION_MAJOR == 5
+ ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, flags, 0660);
+ #else
+ ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, flags, 0660);
+
+--- ./utils/dbconverter-2.c.orig 2010-10-04 21:23:39.778000256 -0400
++++ ./utils/dbconverter-2.c 2010-10-04 21:24:50.384999893 -0400
+@@ -214,7 +214,7 @@
+ ret = db_create(mbdb, NULL, 0);
+ if (ret == 0 && *mbdb != NULL)
+ {
+-#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1
++#if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) || DB_VERSION_MAJOR == 5
+ ret = (*mbdb)->open(*mbdb, NULL, path, NULL, DB_HASH, DB_CREATE, 0664);
+ #else
+ ret = (*mbdb)->open(*mbdb, path, NULL, DB_HASH, DB_CREATE, 0664);
diff --git a/main/cyrus-sasl/saslauthd.initd b/main/cyrus-sasl/saslauthd.initd
new file mode 100644
index 0000000000..f06161eb96
--- /dev/null
+++ b/main/cyrus-sasl/saslauthd.initd
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-libs/cyrus-sasl/files/saslauthd2.rc6,v 1.7 2007/04/07 13:03:55 chtekk Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting saslauthd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/saslauthd \
+ -- ${SASLAUTHD_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping saslauthd"
+ start-stop-daemon --stop --quiet --pidfile /var/lib/sasl2/saslauthd.pid
+ eend $?
+}
diff --git a/main/dahdi-linux-grsec/APKBUILD b/main/dahdi-linux-grsec/APKBUILD
new file mode 100644
index 0000000000..d11ebe14da
--- /dev/null
+++ b/main/dahdi-linux-grsec/APKBUILD
@@ -0,0 +1,82 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+
+_flavor=grsec
+
+# source the kernel version
+if [ -f ../linux-${_flavor}/APKBUILD ]; then
+ . ../linux-${_flavor}/APKBUILD
+fi
+
+_kernelver="$pkgver-r$pkgrel"
+_abi_release=${pkgver}-${_flavor}
+_kpkgrel=$pkgrel
+_realname=dahdi-linux
+
+pkgname=${_realname}-${_flavor}
+pkgver=$pkgver
+# when chaning _dahdiver we *must* bump _mypkgrel
+_dahdiver=2.4.1.2
+_mypkgrel=2
+pkgrel=$(( $_kpkgrel + $_mypkgrel ))
+pkgdesc="Digium Asterisk Hardware Device Interface drivers $_dahdiver"
+url="http://www.asterisk.org"
+arch="all"
+license="GPL"
+depends="dahdi-linux linux-${_flavor}=${_kernelver}"
+# we need wget and tar because make install downloads firmware and uses fancy
+# options for tar and wget.
+makedepends="linux-${_flavor}-dev=${_kernelver} wget tar perl"
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.digium.com/pub/telephony/dahdi-linux/releases/${_realname}-$_dahdiver.tar.gz
+ dahdi-depmod.patch
+ dahdi-bri_dchan.patch
+ dahdi-zaphfc.patch
+ zaphfc-dahdi-flortz.diff
+ zaphfc-dahdi-2.4.0.patch
+ "
+
+prepare() {
+ cd "$srcdir/$_realname-$_dahdiver"
+ for i in $source; do
+ case $i in
+ *.patch|*.diff)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir/$_realname-$_dahdiver"
+ make KVERS="${_abi_release}" DYNFS="yes" MODULES_EXTRA="zaphfc" \
+ || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$_dahdiver"
+ make KVERS="${_abi_release}" DYNFS="yes" MODULES_EXTRA="zaphfc" \
+ DESTDIR="$pkgdir" install-modules || return 1
+ rm -rf "$pkgdir"/lib/firmware "$pkgdir"/usr/lib/hotplug/firmware \
+ "$pkgdir"/usr/include
+}
+
+# since we sourced the APKBUILD above we got the dev() function there to
+# so we override it again.
+depends_dev="dahdi-linux-dev"
+dev() {
+ default_dev
+ local dir="$subpkgdir"/usr/src/dahdi-headers-${_abi_release}
+ install -D "$srcdir"/$_realname-$_dahdiver/drivers/dahdi/Module.symvers \
+ "$dir"/drivers/dahdi/Module.symvers
+ ln -s /usr/include "$dir"/include
+}
+
+md5sums="81b232a47693f4adac90c569e446f88f dahdi-linux-2.4.1.2.tar.gz
+c78fb8d80f9efdffd950297c88ff9273 dahdi-depmod.patch
+4b41a82ff390ac64c08092c5a3eab6a8 dahdi-bri_dchan.patch
+a822c092f0548cd13f5e8d8cba053af6 dahdi-zaphfc.patch
+291c5c44c86ab02443a742415461ddca zaphfc-dahdi-flortz.diff
+0fdcd8c8c93bc1fe33c0af12b6cc6b05 zaphfc-dahdi-2.4.0.patch"
diff --git a/main/dahdi-linux-grsec/dahdi-bri_dchan.patch b/main/dahdi-linux-grsec/dahdi-bri_dchan.patch
new file mode 100644
index 0000000000..d7a3fe859b
--- /dev/null
+++ b/main/dahdi-linux-grsec/dahdi-bri_dchan.patch
@@ -0,0 +1,161 @@
+# Translate the D channels to a standard channel data.
+# The HFC chipset provides us the D channel as data, but
+# Zaptel expects it as a standard channel with 1000 samples
+# per second.
+
+--- a/include/dahdi/kernel.h
++++ b/include/dahdi/kernel.h
+@@ -132,6 +132,13 @@ struct dahdi_chan {
+ int do_ppp_error;
+ struct sk_buff_head ppp_rq;
+ #endif
++#ifdef CONFIG_DAHDI_BRI_DCHANS
++ int bytes2receive;
++ int maxbytes2transmit; /* size of the tx buffer in the card driver */
++ int bytes2transmit;
++ int eofrx;
++ int eoftx;
++#endif
+ spinlock_t lock;
+ char name[40];
+ /* Specified by DAHDI */
+@@ -462,6 +469,9 @@ enum {
+ DAHDI_FLAGBIT_LOOPED = 18, /*!< Loopback the receive data from the channel to the transmit */
+ DAHDI_FLAGBIT_MTP2 = 19, /*!< Repeats last message in buffer and also discards repeating messages sent to us */
+ DAHDI_FLAGBIT_HDLC56 = 20, /*!< Sets the given channel (if in HDLC mode) to use 56K HDLC instead of 64K */
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ DAHDI_FLAGBIT_BRIDCHAN = 21, /*!< hardhdlc-like handling of the D channel */
++#endif
+ };
+
+ /* map flagbits to flag masks */
+@@ -500,6 +510,7 @@ enum {
+ #define DAHDI_FLAG_LOOPED DAHDI_FLAG(LOOPED)
+ #define DAHDI_FLAG_MTP2 DAHDI_FLAG(MTP2)
+ #define DAHDI_FLAG_HDLC56 DAHDI_FLAG(HDLC56)
++#define DAHDI_FLAG_BRIDCHAN DAHDI_FLAG(BRIDCHAN)
+
+ struct dahdi_span {
+ spinlock_t lock;
+--- a/include/dahdi/dahdi_config.h
++++ b/include/dahdi/dahdi_config.h
+@@ -174,4 +174,10 @@
+ */
+ /* #define OPTIMIZE_CHANMUTE */
+
++/*
++ * Uncomment the following for BRI D channels
++ *
++ */
++#define CONFIG_DAHDI_BRI_DCHANS
++
+ #endif
+--- a/drivers/dahdi/dahdi-base.c
++++ b/drivers/dahdi/dahdi-base.c
+@@ -5907,11 +5907,40 @@ static inline void __dahdi_getbuf_chunk(
+ *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc);
+ }
+ bytes -= left;
++#ifdef CONFIG_DAHDI_BRI_DCHANS
++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ /*
++ * Let's get this right, we want to transmit complete frames only.
++ * The card driver will do the dirty HDLC work for us.
++ * txb (transmit buffer) is supposed to be big enough to store one frame
++ * we will make this as big as the D fifo (1KB or 2KB)
++ */
++
++ /* there are 'left' bytes in the user buffer left to transmit */
++ left = ms->writen[ms->outwritebuf] - ms->writeidx[ms->outwritebuf] - 2;
++ if (left > ms->maxbytes2transmit) {
++ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], ms->maxbytes2transmit);
++ ms->writeidx[ms->outwritebuf] += ms->maxbytes2transmit;
++ txb += ms->maxbytes2transmit;
++ ms->bytes2transmit = ms->maxbytes2transmit;
++ ms->eoftx = 0;
++ } else {
++ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left);
++ ms->writeidx[ms->outwritebuf] += left + 2;
++ txb += left + 2;
++ ms->bytes2transmit = left;
++ ms->eoftx = 1;
++ }
++ bytes = 0;
++#endif
+ } else {
+ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left);
+ ms->writeidx[ms->outwritebuf]+=left;
+ txb += left;
+ bytes -= left;
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ ms->bytes2transmit=DAHDI_CHUNKSIZE;
++#endif
+ }
+ /* Check buffer status */
+ if (ms->writeidx[ms->outwritebuf] >= ms->writen[ms->outwritebuf]) {
+@@ -5968,6 +5997,17 @@ out in the later versions, and is put ba
+ /* Transmit a flag if this is an HDLC channel */
+ if (ms->flags & DAHDI_FLAG_HDLC)
+ fasthdlc_tx_frame_nocheck(&ms->txhdlc);
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ // if (ms->bytes2transmit > 0) {
++ // txb += 2;
++ // ms->bytes2transmit -= 2;
++ bytes=0;
++ ms->eoftx = 1;
++// printk(KERN_CRIT "zaptel EOF(%d) bytes2transmit %d\n",ms->eoftx,ms->bytes2transmit);
++ // }
++ }
++#endif
+ #ifdef CONFIG_DAHDI_NET
+ if (ms->flags & DAHDI_FLAG_NETDEV)
+ netif_wake_queue(ztchan_to_dev(ms));
+@@ -6028,6 +6068,12 @@ out in the later versions, and is put ba
+ memset(txb, 0xFF, bytes);
+ }
+ bytes = 0;
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ ms->bytes2transmit = 0;
++ ms->eoftx = 0;
++ bytes = 0;
++#endif
+ } else {
+ memset(txb, DAHDI_LIN2X(0, ms), bytes); /* Lastly we use silence on telephony channels */
+ bytes = 0;
+@@ -6840,6 +6886,14 @@ static inline void __putbuf_chunk(struct
+ int res;
+ int left, x;
+
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ bytes = ms->bytes2receive;
++ if (bytes < 1) return;
++// printk(KERN_CRIT "bytes2receive %d\n",ms->bytes2receive);
++ }
++#endif
++
+ while(bytes) {
+ #if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP)
+ skb = NULL;
+@@ -6897,6 +6951,19 @@ static inline void __putbuf_chunk(struct
+ }
+ }
+ }
++#ifdef CONFIG_DAHDI_BRI_DCHANS
++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left);
++ rxb += left;
++ ms->readidx[ms->inreadbuf] += left;
++ bytes -= left;
++ if (ms->eofrx == 1) {
++ eof=1;
++ }
++// printk(KERN_CRIT "receiving %d bytes\n",ms->bytes2receive);
++ ms->bytes2receive = 0;
++ ms->eofrx = 0;
++#endif
+ } else {
+ /* Not HDLC */
+ memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left);
diff --git a/main/dahdi-linux-grsec/dahdi-depmod.patch b/main/dahdi-linux-grsec/dahdi-depmod.patch
new file mode 100644
index 0000000000..289aad403b
--- /dev/null
+++ b/main/dahdi-linux-grsec/dahdi-depmod.patch
@@ -0,0 +1,22 @@
+Index: dahdi-linux-2.0.0-rc4/Makefile
+===================================================================
+--- dahdi-linux-2.0.0-rc4.orig/Makefile 2008-09-09 14:07:23.000000000 +0300
++++ dahdi-linux-2.0.0-rc4/Makefile 2008-09-09 14:12:31.000000000 +0300
+@@ -190,7 +190,7 @@
+ build_tools/uninstall-modules dahdi $(KVERS)
+ endif
+ $(KMAKE) INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=dahdi modules_install
+- [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || :
++ [ -z "$(DESTDIR)" -a `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || :
+
+ uninstall-modules:
+ ifdef DESTDIR
+@@ -203,7 +203,7 @@
+ rm -rf /lib/modules/$(KVERS)/dahdi; \
+ echo "done."; \
+ fi
+- [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || :
++ [ -z "$(DESTDIR)" -a `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || :
+ endif
+
+ update:
diff --git a/main/dahdi-linux-grsec/dahdi-zaphfc.patch b/main/dahdi-linux-grsec/dahdi-zaphfc.patch
new file mode 100644
index 0000000000..b711c07ff9
--- /dev/null
+++ b/main/dahdi-linux-grsec/dahdi-zaphfc.patch
@@ -0,0 +1,1429 @@
+Index: dahdi-linux-2.1.0/drivers/dahdi/zaphfc.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ dahdi-linux-2.1.0/drivers/dahdi/zaphfc.c 2008-12-10 12:46:14.000000000 +0200
+@@ -0,0 +1,1129 @@
++/*
++ * zaphfc.c - Zaptel driver for HFC-S PCI A based ISDN BRI cards
++ *
++ * kernel module inspired by HFC PCI ISDN4Linux and Zaptel drivers
++ *
++ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
++ * This program is free software and may be modified and
++ * distributed under the terms of the GNU Public License.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#ifdef RTAITIMING
++#include <asm/io.h>
++#include <rtai.h>
++#include <rtai_sched.h>
++#include <rtai_fifos.h>
++#endif
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <dahdi/kernel.h>
++#include "zaphfc.h"
++
++#include <linux/moduleparam.h>
++
++#if CONFIG_PCI
++
++#define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
++#define CLKDEL_NT 0x6c /* CLKDEL in NT mode */
++
++typedef struct {
++ int vendor_id;
++ int device_id;
++ char *vendor_name;
++ char *card_name;
++} PCI_ENTRY;
++
++static const PCI_ENTRY id_list[] =
++{
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, "CCD/Billion/Asuscom", "2BD0"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, "Billion", "B000"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, "Billion", "B006"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, "Billion", "B007"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, "Billion", "B008"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, "Billion", "B009"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, "Billion", "B00A"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"},
++ {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, "Abocom/Magitek", "2BD1"},
++ {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"},
++ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"},
++ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, "German telekom", "A1T"},
++ {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, "Motorola MC145575", "MC145575"},
++ {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, "Zoltrix", "2BD0"},
++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"},
++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
++ {0x182d, 0x3069,"Sitecom","Isdn 128 PCI"},
++ {0, 0, NULL, NULL},
++};
++
++static struct hfc_card *hfc_dev_list = NULL;
++static int hfc_dev_count = 0;
++static int modes = 0; // all TE
++static int debug = 0;
++static struct pci_dev *multi_hfc = NULL;
++static spinlock_t registerlock = SPIN_LOCK_UNLOCKED;
++
++void hfc_shutdownCard(struct hfc_card *hfctmp) {
++ unsigned long flags;
++
++ if (hfctmp == NULL) {
++ return;
++ }
++
++ if (hfctmp->pci_io == NULL) {
++ return;
++ }
++
++ spin_lock_irqsave(&hfctmp->lock,flags);
++
++ printk(KERN_INFO "zaphfc: shutting down card at %p.\n",hfctmp->pci_io);
++
++ /* Clear interrupt mask */
++ hfctmp->regs.int_m2 = 0;
++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
++
++ /* Reset pending interrupts */
++ hfc_inb(hfctmp, hfc_INT_S1);
++
++ /* Wait for interrupts that might still be pending */
++ spin_unlock_irqrestore(&hfctmp->lock, flags);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((30 * HZ) / 1000); // wait 30 ms
++ spin_lock_irqsave(&hfctmp->lock,flags);
++
++ /* Remove interrupt handler */
++ if (hfctmp->irq) {
++ free_irq(hfctmp->irq, hfctmp);
++ }
++
++ /* Soft-reset the card */
++ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on
++
++ spin_unlock_irqrestore(&hfctmp->lock, flags);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((30 * HZ) / 1000); // wait 30 ms
++ spin_lock_irqsave(&hfctmp->lock,flags);
++
++ hfc_outb(hfctmp,hfc_CIRM,0); // softreset off
++
++ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, 0); // disable memio and bustmaster
++
++ if (hfctmp->fifomem != NULL) {
++ kfree(hfctmp->fifomem);
++ }
++ iounmap((void *) hfctmp->pci_io);
++ hfctmp->pci_io = NULL;
++ if (hfctmp->pcidev != NULL) {
++ pci_disable_device(hfctmp->pcidev);
++ }
++ spin_unlock_irqrestore(&hfctmp->lock,flags);
++ if (hfctmp->ztdev != NULL) {
++ dahdi_unregister(&hfctmp->ztdev->span);
++ kfree(hfctmp->ztdev);
++ printk(KERN_INFO "unregistered from DAHDI.\n");
++ }
++}
++
++void hfc_resetCard(struct hfc_card *hfctmp) {
++ unsigned long flags;
++
++ spin_lock_irqsave(&hfctmp->lock,flags);
++ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio
++ hfctmp->regs.int_m2 = 0;
++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
++
++// printk(KERN_INFO "zaphfc: resetting card.\n");
++ pci_set_master(hfctmp->pcidev);
++ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on
++ spin_unlock_irqrestore(&hfctmp->lock, flags);
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((30 * HZ) / 1000); // wait 30 ms
++ hfc_outb(hfctmp, hfc_CIRM, 0); // softreset off
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((20 * HZ) / 1000); // wait 20 ms
++ if (hfc_inb(hfctmp,hfc_STATUS) & hfc_STATUS_PCI_PROC) {
++ printk(KERN_WARNING "zaphfc: hfc busy.\n");
++ }
++
++// hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
++// hfctmp->regs.fifo_en = hfc_FIFOEN_D; /* only D fifos enabled */
++ hfctmp->regs.fifo_en = 0; /* no fifos enabled */
++ hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
++
++ hfctmp->regs.trm = 2;
++ hfc_outb(hfctmp, hfc_TRM, hfctmp->regs.trm);
++
++ if (hfctmp->regs.nt_mode == 1) {
++ hfc_outb(hfctmp, hfc_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */
++ } else {
++ hfc_outb(hfctmp, hfc_CLKDEL, CLKDEL_TE); /* ST-Bit delay for TE-Mode */
++ }
++ hfctmp->regs.sctrl_e = hfc_SCTRL_E_AUTO_AWAKE;
++ hfc_outb(hfctmp, hfc_SCTRL_E, hfctmp->regs.sctrl_e); /* S/T Auto awake */
++ hfctmp->regs.bswapped = 0; /* no exchange */
++
++ hfctmp->regs.ctmt = hfc_CTMT_TRANSB1 | hfc_CTMT_TRANSB2; // all bchans are transparent , no freaking hdlc
++ hfc_outb(hfctmp, hfc_CTMT, hfctmp->regs.ctmt);
++
++ hfctmp->regs.int_m1 = 0;
++ hfc_outb(hfctmp, hfc_INT_M1, hfctmp->regs.int_m1);
++
++#ifdef RTAITIMING
++ hfctmp->regs.int_m2 = 0;
++#else
++ hfctmp->regs.int_m2 = hfc_M2_PROC_TRANS;
++#endif
++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
++
++ /* Clear already pending ints */
++ hfc_inb(hfctmp, hfc_INT_S1);
++
++ if (hfctmp->regs.nt_mode == 1) {
++ hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_NT; /* set tx_lo mode, error in datasheet ! */
++ } else {
++ hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_TE; /* set tx_lo mode, error in datasheet ! */
++ }
++
++ hfctmp->regs.mst_mode = hfc_MST_MODE_MASTER; /* HFC Master Mode */
++ hfc_outb(hfctmp, hfc_MST_MODE, hfctmp->regs.mst_mode);
++
++ hfc_outb(hfctmp, hfc_SCTRL, hfctmp->regs.sctrl);
++ hfctmp->regs.sctrl_r = 3;
++ hfc_outb(hfctmp, hfc_SCTRL_R, hfctmp->regs.sctrl_r);
++
++ hfctmp->regs.connect = 0;
++ hfc_outb(hfctmp, hfc_CONNECT, hfctmp->regs.connect);
++
++ hfc_outb(hfctmp, hfc_CIRM, 0x80 | 0x40); // bit order
++
++ /* Finally enable IRQ output */
++#ifndef RTAITIMING
++ hfctmp->regs.int_m2 |= hfc_M2_IRQ_ENABLE;
++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
++#endif
++
++ /* clear pending ints */
++ hfc_inb(hfctmp, hfc_INT_S1);
++ hfc_inb(hfctmp, hfc_INT_S2);
++}
++
++void hfc_registerCard(struct hfc_card *hfccard) {
++ spin_lock(&registerlock);
++ if (hfccard != NULL) {
++ hfccard->cardno = hfc_dev_count++;
++ hfccard->next = hfc_dev_list;
++ hfc_dev_list = hfccard;
++ }
++ spin_unlock(&registerlock);
++}
++
++static void hfc_btrans(struct hfc_card *hfctmp, char whichB) {
++ // we are called with irqs disabled from the irq handler
++ int count, maxlen, total;
++ unsigned char *f1, *f2;
++ unsigned short *z1, *z2, newz1;
++ int freebytes;
++
++ if (whichB == 1) {
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z2 + (*f1 * 4));
++ } else {
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z2 + (*f1 * 4));
++ }
++
++ freebytes = *z2 - *z1;
++ if (freebytes <= 0) {
++ freebytes += hfc_B_FIFO_SIZE;
++ }
++ count = DAHDI_CHUNKSIZE;
++
++ total = count;
++ if (freebytes < count) {
++ hfctmp->clicks++;
++ /* only spit out this warning once per second to not make things worse! */
++ if (hfctmp->clicks > 100) {
++ printk(KERN_CRIT "zaphfc: bchan tx fifo full, dropping audio! (z1=%d, z2=%d)\n",*z1,*z2);
++ hfctmp->clicks = 0;
++ }
++ return;
++ }
++
++ maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z1;
++ if (maxlen > count) {
++ maxlen = count;
++ }
++ newz1 = *z1 + total;
++ if (newz1 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { newz1 -= hfc_B_FIFO_SIZE; }
++
++ if (whichB == 1) {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + *z1),hfctmp->ztdev->chans[0].writechunk, maxlen);
++ } else {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + *z1),hfctmp->ztdev->chans[1].writechunk, maxlen);
++ }
++
++ count -= maxlen;
++ if (count > 0) {
++ // Buffer wrap
++ if (whichB == 1) {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[0].writechunk+maxlen, count);
++ } else {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[1].writechunk+maxlen, count);
++ }
++ }
++
++ *z1 = newz1; /* send it now */
++
++// if (count > 0) printk(KERN_CRIT "zaphfc: bchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
++ return;
++}
++
++static void hfc_brec(struct hfc_card *hfctmp, char whichB) {
++ // we are called with irqs disabled from the irq handler
++ int count, maxlen, drop;
++ volatile unsigned char *f1, *f2;
++ volatile unsigned short *z1, *z2, newz2;
++ int bytes = 0;
++
++ if (whichB == 1) {
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
++ } else {
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
++ }
++
++ bytes = *z1 - *z2;
++ if (bytes < 0) {
++ bytes += hfc_B_FIFO_SIZE;
++ }
++ count = DAHDI_CHUNKSIZE;
++
++ if (bytes < DAHDI_CHUNKSIZE) {
++#ifndef RTAITIMING
++ printk(KERN_CRIT "zaphfc: bchan rx fifo not enough bytes to receive! (z1=%d, z2=%d, wanted %d got %d), probably a buffer overrun.\n",*z1,*z2,DAHDI_CHUNKSIZE,bytes);
++#endif
++ return;
++ }
++
++ /* allowing the buffering of hfc_BCHAN_BUFFER bytes of audio data works around irq jitter */
++ if (bytes > hfc_BCHAN_BUFFER + DAHDI_CHUNKSIZE) {
++ /* if the system is too slow to handle it, we will have to drop it all (except 1 DAHDI chunk) */
++ drop = bytes - DAHDI_CHUNKSIZE;
++ hfctmp->clicks++;
++ /* only spit out this warning once per second to not make things worse! */
++ if (hfctmp->clicks > 100) {
++ printk(KERN_CRIT "zaphfc: dropped audio (z1=%d, z2=%d, wanted %d got %d, dropped %d).\n",*z1,*z2,count,bytes,drop);
++ hfctmp->clicks = 0;
++ }
++ /* hm, we are processing the b chan data tooooo slowly... let's drop the lost audio */
++ newz2 = *z2 + drop;
++ if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
++ newz2 -= hfc_B_FIFO_SIZE;
++ }
++ *z2 = newz2;
++ }
++
++
++ maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z2;
++ if (maxlen > count) {
++ maxlen = count;
++ }
++ if (whichB == 1) {
++ memcpy(hfctmp->ztdev->chans[0].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + *z2), maxlen);
++ } else {
++ memcpy(hfctmp->ztdev->chans[1].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + *z2), maxlen);
++ }
++ newz2 = *z2 + count;
++ if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
++ newz2 -= hfc_B_FIFO_SIZE;
++ }
++ *z2 = newz2;
++
++ count -= maxlen;
++ if (count > 0) {
++ // Buffer wrap
++ if (whichB == 1) {
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
++ memcpy(hfctmp->ztdev->chans[0].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + hfc_B_SUB_VAL), count);
++ } else {
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
++ memcpy(hfctmp->ztdev->chans[1].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + hfc_B_SUB_VAL), count);
++ }
++ newz2 = *z2 + count;
++ if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
++ newz2 -= hfc_B_FIFO_SIZE;
++ }
++ }
++
++
++ if (whichB == 1) {
++ dahdi_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk);
++ } else {
++ dahdi_ec_chunk(&hfctmp->ztdev->chans[1], hfctmp->ztdev->chans[1].readchunk, hfctmp->ztdev->chans[1].writechunk);
++ }
++ return;
++}
++
++
++static void hfc_dtrans(struct hfc_card *hfctmp) {
++ // we are called with irqs disabled from the irq handler
++ int x;
++ int count, maxlen, total;
++ unsigned char *f1, *f2, newf1;
++ unsigned short *z1, *z2, newz1;
++ int frames, freebytes;
++
++ if (hfctmp->ztdev->chans[2].bytes2transmit == 0) {
++ return;
++ }
++
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z2 + (*f1 * 4));
++
++ frames = (*f1 - *f2) & hfc_FMASK;
++ if (frames < 0) {
++ frames += hfc_MAX_DFRAMES + 1;
++ }
++
++ if (frames >= hfc_MAX_DFRAMES) {
++ printk(KERN_CRIT "zaphfc: dchan tx fifo total number of frames exceeded!\n");
++ return;
++ }
++
++ freebytes = *z2 - *z1;
++ if (freebytes <= 0) {
++ freebytes += hfc_D_FIFO_SIZE;
++ }
++ count = hfctmp->ztdev->chans[2].bytes2transmit;
++
++ total = count;
++ if (freebytes < count) {
++ printk(KERN_CRIT "zaphfc: dchan tx fifo not enough free bytes! (z1=%d, z2=%d)\n",*z1,*z2);
++ return;
++ }
++
++ newz1 = (*z1 + count) & hfc_ZMASK;
++ newf1 = ((*f1 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); // next frame
++
++ if (count > 0) {
++ if (debug) {
++ printk(KERN_CRIT "zaphfc: card %d TX [ ", hfctmp->cardno);
++ for (x=0; x<count; x++) {
++ printk("%#2x ",hfctmp->dtransbuf[x]);
++ }
++ if (hfctmp->ztdev->chans[2].eoftx == 1) {
++ printk("] %d bytes\n", count);
++ } else {
++ printk("..] %d bytes\n", count);
++ }
++ }
++ maxlen = hfc_D_FIFO_SIZE - *z1;
++ if (maxlen > count) {
++ maxlen = count;
++ }
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF + *z1),hfctmp->ztdev->chans[2].writechunk, maxlen);
++ count -= maxlen;
++ if (count > 0) {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF),(char *)(hfctmp->ztdev->chans[2].writechunk + maxlen), count);
++ }
++ }
++
++ *z1 = newz1;
++
++ if (hfctmp->ztdev->chans[2].eoftx == 1) {
++ *f1 = newf1;
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
++ *z1 = newz1;
++ hfctmp->ztdev->chans[2].eoftx = 0;
++ }
++// printk(KERN_CRIT "zaphfc: dchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
++ return;
++}
++
++/* receive a complete hdlc frame, skip broken or short frames */
++static void hfc_drec(struct hfc_card *hfctmp) {
++ int count=0, maxlen=0, framelen=0;
++ unsigned char *f1, *f2, *crcstat;
++ unsigned short *z1, *z2, oldz2, newz2;
++
++ hfctmp->ztdev->chans[2].bytes2receive=0;
++ hfctmp->ztdev->chans[2].eofrx = 0;
++
++ /* put the received data into the DAHDI buffer
++ we'll call dahdi_receive() later when the timer fires. */
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F2);
++
++ if (*f1 == *f2) return; /* nothing received, strange eh? */
++
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z1 + (*f2 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
++
++ /* calculate length of frame, including 2 bytes CRC and 1 byte STAT */
++ count = *z1 - *z2;
++
++ if (count < 0) {
++ count += hfc_D_FIFO_SIZE; /* ring buffer wrapped */
++ }
++ count++;
++ framelen = count;
++
++ crcstat = (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z1);
++
++ if ((framelen < 4) || (*crcstat != 0x0)) {
++ /* the frame is too short for a valid HDLC frame or the CRC is borked */
++ printk(KERN_CRIT "zaphfc: empty HDLC frame or bad CRC received (framelen = %d, stat = %#x, card = %d).\n", framelen, *crcstat, hfctmp->cardno);
++ oldz2 = *z2;
++ *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */
++ // recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!!
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
++ *z2 = (oldz2 + framelen) & hfc_ZMASK;
++ hfctmp->drecinframe = 0;
++ hfctmp->regs.int_drec--;
++ /* skip short or broken frames */
++ hfctmp->ztdev->chans[2].bytes2receive = 0;
++ return;
++ }
++
++ count -= 1; /* strip STAT */
++ hfctmp->ztdev->chans[2].eofrx = 1;
++
++ if (count + *z2 <= hfc_D_FIFO_SIZE) {
++ maxlen = count;
++ } else {
++ maxlen = hfc_D_FIFO_SIZE - *z2;
++ }
++
++ /* copy first part */
++ memcpy(hfctmp->drecbuf, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z2), maxlen);
++ hfctmp->ztdev->chans[2].bytes2receive += maxlen;
++
++ count -= maxlen;
++ if (count > 0) {
++ /* ring buffer wrapped, copy rest from start of d fifo */
++ memcpy(hfctmp->drecbuf + maxlen, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF), count);
++ hfctmp->ztdev->chans[2].bytes2receive += count;
++ }
++
++ /* frame read */
++ oldz2 = *z2;
++ newz2 = (oldz2 + framelen) & hfc_ZMASK;
++ *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */
++ /* recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! */
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
++ *z2 = newz2;
++ hfctmp->drecinframe = 0;
++ hfctmp->regs.int_drec--;
++}
++
++#ifndef RTAITIMING
++DAHDI_IRQ_HANDLER(hfc_interrupt) {
++ struct hfc_card *hfctmp = dev_id;
++ unsigned long flags = 0;
++ unsigned char stat;
++#else
++static void hfc_service(struct hfc_card *hfctmp) {
++#endif
++ struct dahdi_hfc *zthfc;
++ unsigned char s1, s2, l1state;
++ int x;
++
++ if (!hfctmp) {
++#ifndef RTAITIMING
++ return IRQ_NONE;
++#else
++ /* rtai */
++ return;
++#endif
++ }
++
++ if (!hfctmp->pci_io) {
++ printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n",
++ __FUNCTION__);
++#ifndef RTAITIMING
++ return IRQ_NONE;
++#else
++ /* rtai */
++ return;
++#endif
++ }
++
++ /* we assume a few things in this irq handler:
++ - the hfc-pci will only generate "timer" irqs (proc/non-proc)
++ - we need to use every 8th IRQ (to generate 1khz timing)
++ OR
++ - if we use rtai for timing the hfc-pci will not generate ANY irq,
++ instead rtai will call this "fake" irq with a 1khz realtime timer. :)
++ - rtai will directly service the card, not like it used to by triggering
++ the linux irq
++ */
++
++#ifndef RTAITIMING
++ spin_lock_irqsave(&hfctmp->lock, flags);
++ stat = hfc_inb(hfctmp, hfc_STATUS);
++
++ if ((stat & hfc_STATUS_ANYINT) == 0) {
++ // maybe we are sharing the irq
++ spin_unlock_irqrestore(&hfctmp->lock,flags);
++ return IRQ_NONE;
++ }
++#endif
++
++ s1 = hfc_inb(hfctmp, hfc_INT_S1);
++ s2 = hfc_inb(hfctmp, hfc_INT_S2);
++ if (s1 != 0) {
++ if (s1 & hfc_INTS_TIMER) {
++ // timer (bit 7)
++ // printk(KERN_CRIT "timer %d %d %d.\n", stat, s1, s2);
++ }
++ if (s1 & hfc_INTS_L1STATE) {
++ // state machine (bit 6)
++ // printk(KERN_CRIT "zaphfc: layer 1 state machine interrupt\n");
++ zthfc = hfctmp->ztdev;
++ l1state = hfc_inb(hfctmp,hfc_STATES) & hfc_STATES_STATE_MASK;
++ if (hfctmp->regs.nt_mode == 1) {
++ if (debug) {
++ printk(KERN_CRIT "zaphfc: card %d layer 1 state = G%d\n", hfctmp->cardno, l1state);
++ }
++ switch (l1state) {
++ case 3:
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d)", hfctmp->cardno, l1state);
++#endif
++ break;
++ default:
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d)", hfctmp->cardno, l1state);
++#endif
++ }
++ if (l1state == 2) {
++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_ACTIVATE | hfc_STATES_DO_ACTION | hfc_STATES_NT_G2_G3);
++ } else if (l1state == 3) {
++ // fix to G3 state (see specs)
++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_LOAD_STATE | 3);
++ }
++ } else {
++ if (debug) {
++ printk(KERN_CRIT "zaphfc: card %d layer 1 state = F%d\n", hfctmp->cardno, l1state);
++ }
++ switch (l1state) {
++ case 7:
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d)", hfctmp->cardno, l1state);
++#endif
++ break;
++ default:
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d)", hfctmp->cardno, l1state);
++#endif
++ }
++ if (l1state == 3) {
++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
++ }
++ }
++
++ }
++ if (s1 & hfc_INTS_DREC) {
++ // D chan RX (bit 5)
++ hfctmp->regs.int_drec++;
++ // mr. zapata there is something for you!
++ // printk(KERN_CRIT "d chan rx\n");
++ }
++ if (s1 & hfc_INTS_B2REC) {
++ // B2 chan RX (bit 4)
++ }
++ if (s1 & hfc_INTS_B1REC) {
++ // B1 chan RX (bit 3)
++ }
++ if (s1 & hfc_INTS_DTRANS) {
++ // D chan TX (bit 2)
++// printk(KERN_CRIT "zaphfc: dchan frame transmitted.\n");
++ }
++ if (s1 & hfc_INTS_B2TRANS) {
++ // B2 chan TX (bit 1)
++ }
++ if (s1 & hfc_INTS_B1TRANS) {
++ // B1 chan TX (bit 0)
++ }
++ }
++#ifdef RTAITIMING
++ /* fake an irq */
++ s2 |= hfc_M2_PROC_TRANS;
++#endif
++ if (s2 != 0) {
++ if (s2 & hfc_M2_PMESEL) {
++ // kaboom irq (bit 7)
++ printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n");
++ }
++ if (s2 & hfc_M2_GCI_MON_REC) {
++ // RxR monitor channel (bit 2)
++ }
++ if (s2 & hfc_M2_GCI_I_CHG) {
++ // GCI I-change (bit 1)
++ }
++ if (s2 & hfc_M2_PROC_TRANS) {
++ // processing/non-processing transition (bit 0)
++ hfctmp->ticks++;
++#ifndef RTAITIMING
++ if (hfctmp->ticks > 7) {
++ // welcome to DAHDI timing :)
++#endif
++ hfctmp->ticks = 0;
++
++ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
++ // clear dchan buffer
++ hfctmp->ztdev->chans[2].bytes2transmit = 0;
++ hfctmp->ztdev->chans[2].maxbytes2transmit = hfc_D_FIFO_SIZE;
++
++ dahdi_transmit(&(hfctmp->ztdev->span));
++
++ hfc_btrans(hfctmp,1);
++ hfc_btrans(hfctmp,2);
++ hfc_dtrans(hfctmp);
++ }
++
++ hfc_brec(hfctmp,1);
++ hfc_brec(hfctmp,2);
++ if (hfctmp->regs.int_drec > 0) {
++ // dchan data to read
++ hfc_drec(hfctmp);
++ if (hfctmp->ztdev->chans[2].bytes2receive > 0) {
++ if (debug) {
++ printk(KERN_CRIT "zaphfc: card %d RX [ ", hfctmp->cardno);
++ if (hfctmp->ztdev->chans[2].eofrx) {
++ /* dont output CRC == less user confusion */
++ for (x=0; x < hfctmp->ztdev->chans[2].bytes2receive - 2; x++) {
++ printk("%#2x ", hfctmp->drecbuf[x]);
++ }
++ printk("] %d bytes\n", hfctmp->ztdev->chans[2].bytes2receive - 2);
++ } else {
++ for (x=0; x < hfctmp->ztdev->chans[2].bytes2receive; x++) {
++ printk("%#2x ", hfctmp->drecbuf[x]);
++ }
++ printk("..] %d bytes\n", hfctmp->ztdev->chans[2].bytes2receive);
++ }
++ }
++ }
++ } else {
++ // hmm....ok, let DAHDI receive nothing
++ hfctmp->ztdev->chans[2].bytes2receive = 0;
++ }
++ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
++ dahdi_receive(&(hfctmp->ztdev->span));
++ }
++
++#ifndef RTAITIMING
++ }
++#endif
++ }
++
++ }
++#ifndef RTAITIMING
++ spin_unlock_irqrestore(&hfctmp->lock,flags);
++ return IRQ_RETVAL(1);
++#endif
++}
++
++
++static int zthfc_open(struct dahdi_chan *chan) {
++ struct dahdi_hfc *zthfc = chan->pvt;
++ struct hfc_card *hfctmp = zthfc->card;
++
++ if (!hfctmp) {
++ return 0;
++ }
++ try_module_get(THIS_MODULE);
++ return 0;
++}
++
++static int zthfc_close(struct dahdi_chan *chan) {
++ struct dahdi_hfc *zthfc = chan->pvt;
++ struct hfc_card *hfctmp = zthfc->card;
++
++ if (!hfctmp) {
++ return 0;
++ }
++
++ module_put(THIS_MODULE);
++ return 0;
++}
++
++static int zthfc_rbsbits(struct dahdi_chan *chan, int bits) {
++ return 0;
++}
++
++static int zthfc_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) {
++ switch(cmd) {
++ default:
++ return -ENOTTY;
++ }
++ return 0;
++}
++
++static int zthfc_startup(struct dahdi_span *span) {
++ struct dahdi_hfc *zthfc = span->pvt;
++ struct hfc_card *hfctmp = zthfc->card;
++ int alreadyrunning;
++
++ if (hfctmp == NULL) {
++ printk(KERN_INFO "zaphfc: no card for span at startup!\n");
++ }
++ alreadyrunning = span->flags & DAHDI_FLAG_RUNNING;
++
++ if (!alreadyrunning) {
++ span->chans[2]->flags &= ~DAHDI_FLAG_HDLC;
++ span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN;
++
++ span->flags |= DAHDI_FLAG_RUNNING;
++
++ hfctmp->ticks = -2;
++ hfctmp->clicks = 0;
++ hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
++ hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
++ } else {
++ return 0;
++ }
++
++ // drivers, start engines!
++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
++ return 0;
++}
++
++static int zthfc_shutdown(struct dahdi_span *span) {
++ return 0;
++}
++
++static int zthfc_maint(struct dahdi_span *span, int cmd) {
++ return 0;
++}
++
++static int zthfc_chanconfig(struct dahdi_chan *chan, int sigtype) {
++// printk(KERN_CRIT "chan_config sigtype=%d\n", sigtype);
++ return 0;
++}
++
++static int zthfc_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) {
++ span->lineconfig = lc->lineconfig;
++ return 0;
++}
++
++static int zthfc_initialize(struct dahdi_hfc *zthfc) {
++ struct hfc_card *hfctmp = zthfc->card;
++ int i;
++
++ memset(&zthfc->span, 0x0, sizeof(struct dahdi_span)); // you never can tell...
++
++ sprintf(zthfc->span.name, "ZTHFC%d", hfc_dev_count + 1);
++ if (hfctmp->regs.nt_mode == 1) {
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] [realtime]", hfc_dev_count + 1);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1);
++#endif
++ } else {
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] [realtime]", hfc_dev_count + 1);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1);
++#endif
++ }
++
++ zthfc->span.spanconfig = zthfc_spanconfig;
++ zthfc->span.chanconfig = zthfc_chanconfig;
++ zthfc->span.startup = zthfc_startup;
++ zthfc->span.shutdown = zthfc_shutdown;
++ zthfc->span.maint = zthfc_maint;
++ zthfc->span.rbsbits = zthfc_rbsbits;
++ zthfc->span.open = zthfc_open;
++ zthfc->span.close = zthfc_close;
++ zthfc->span.ioctl = zthfc_ioctl;
++
++ zthfc->span.channels = 3;
++ zthfc->span.chans = zthfc->_chans;
++ for (i = 0; i < zthfc->span.channels; i++)
++ zthfc->_chans[i] = &zthfc->chans[i];
++
++ zthfc->span.deflaw = DAHDI_LAW_ALAW;
++ zthfc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS; // <--- this is really BS
++ zthfc->span.offset = 0;
++ init_waitqueue_head(&zthfc->span.maintq);
++ zthfc->span.pvt = zthfc;
++
++ for (i = 0; i < zthfc->span.channels; i++) {
++ memset(&(zthfc->chans[i]), 0x0, sizeof(struct dahdi_chan));
++ sprintf(zthfc->chans[i].name, "ZTHFC%d/%d/%d", hfc_dev_count + 1,0,i + 1);
++ zthfc->chans[i].pvt = zthfc;
++ zthfc->chans[i].sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_SF;
++ zthfc->chans[i].chanpos = i + 1;
++ }
++
++ if (dahdi_register(&zthfc->span,0)) {
++ printk(KERN_CRIT "unable to register DAHDI device!\n");
++ return -1;
++ }
++// printk(KERN_CRIT "zaphfc: registered DAHDI device!\n");
++ return 0;
++}
++
++#ifdef RTAITIMING
++#define TICK_PERIOD 1000000
++#define TICK_PERIOD2 1000000000
++#define TASK_PRIORITY 1
++#define STACK_SIZE 10000
++
++static RT_TASK rt_task;
++static struct hfc_card *rtai_hfc_list[hfc_MAX_CARDS];
++static unsigned char rtai_hfc_counter = 0;
++
++static void rtai_register_hfc(struct hfc_card *hfctmp) {
++ rtai_hfc_list[rtai_hfc_counter++] = hfctmp;
++}
++
++static void rtai_loop(int t) {
++ int i=0;
++ for (;;) {
++ for (i=0; i < rtai_hfc_counter; i++) {
++ if (rtai_hfc_list[i] != NULL)
++ hfc_service(rtai_hfc_list[i]);
++ }
++ rt_task_wait_period();
++ }
++}
++#endif
++
++int hfc_findCards(int pcivendor, int pcidevice, char *vendor_name, char *card_name) {
++ struct pci_dev *tmp;
++ struct hfc_card *hfctmp = NULL;
++ struct dahdi_hfc *zthfc = NULL;
++
++ tmp = pci_get_device(pcivendor, pcidevice, multi_hfc);
++ while (tmp != NULL) {
++ multi_hfc = tmp; // skip this next time.
++
++ if (pci_enable_device(tmp)) {
++ multi_hfc = NULL;
++ return -1;
++ }
++ pci_set_master(tmp);
++
++ hfctmp = kmalloc(sizeof(struct hfc_card), GFP_KERNEL);
++ if (!hfctmp) {
++ printk(KERN_WARNING "zaphfc: unable to kmalloc!\n");
++ pci_disable_device(tmp);
++ multi_hfc = NULL;
++ return -ENOMEM;
++ }
++ memset(hfctmp, 0x0, sizeof(struct hfc_card));
++ spin_lock_init(&hfctmp->lock);
++
++ hfctmp->pcidev = tmp;
++ hfctmp->pcibus = tmp->bus->number;
++ hfctmp->pcidevfn = tmp->devfn;
++
++ if (!tmp->irq) {
++ printk(KERN_WARNING "zaphfc: no irq!\n");
++ } else {
++ hfctmp->irq = tmp->irq;
++ }
++
++ hfctmp->pci_io = (char *) tmp->resource[1].start;
++ if (!hfctmp->pci_io) {
++ printk(KERN_WARNING "zaphfc: no iomem!\n");
++ kfree(hfctmp);
++ pci_disable_device(tmp);
++ multi_hfc = NULL;
++ return -1;
++ }
++
++ hfctmp->fifomem = kmalloc(65536, GFP_KERNEL);
++ if (!hfctmp->fifomem) {
++ printk(KERN_WARNING "zaphfc: unable to kmalloc fifomem!\n");
++ kfree(hfctmp);
++ pci_disable_device(tmp);
++ multi_hfc = NULL;
++ return -ENOMEM;
++ } else {
++ memset(hfctmp->fifomem, 0x0, 65536);
++ hfctmp->fifos = (void *)(((ulong) hfctmp->fifomem) & ~0x7FFF) + 0x8000;
++ pci_write_config_dword(hfctmp->pcidev, 0x80, (u_int) virt_to_bus(hfctmp->fifos));
++ hfctmp->pci_io = ioremap((ulong) hfctmp->pci_io, 256);
++ }
++
++#ifdef RTAITIMING
++ /* we need no stinking irq */
++ hfctmp->irq = 0;
++#else
++ if (request_irq(hfctmp->irq, &hfc_interrupt, DAHDI_IRQ_SHARED, "zaphfc", hfctmp)) {
++ printk(KERN_WARNING "zaphfc: unable to register irq\n");
++ kfree(hfctmp->fifomem);
++ kfree(hfctmp);
++ iounmap((void *) hfctmp->pci_io);
++ pci_disable_device(tmp);
++ multi_hfc = NULL;
++ return -EIO;
++ }
++#endif
++
++#ifdef RTAITIMING
++ rtai_register_hfc(hfctmp);
++#endif
++ printk(KERN_INFO
++ "zaphfc: %s %s configured at mem %lx fifo %lx(%#x) IRQ %d HZ %d\n",
++ vendor_name, card_name,
++ (unsigned long) hfctmp->pci_io,
++ (unsigned long) hfctmp->fifos,
++ (u_int) virt_to_bus(hfctmp->fifos),
++ hfctmp->irq, HZ);
++ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio
++ hfctmp->regs.int_m1 = 0; // no ints
++ hfctmp->regs.int_m2 = 0; // not at all
++ hfc_outb(hfctmp,hfc_INT_M1,hfctmp->regs.int_m1);
++ hfc_outb(hfctmp,hfc_INT_M2,hfctmp->regs.int_m2);
++
++ if ((modes & (1 << hfc_dev_count)) != 0) {
++ printk(KERN_INFO "zaphfc: Card %d configured for NT mode\n",hfc_dev_count);
++ hfctmp->regs.nt_mode = 1;
++ } else {
++ printk(KERN_INFO "zaphfc: Card %d configured for TE mode\n",hfc_dev_count);
++ hfctmp->regs.nt_mode = 0;
++ }
++
++ zthfc = kmalloc(sizeof(struct dahdi_hfc),GFP_KERNEL);
++ if (!zthfc) {
++ printk(KERN_CRIT "zaphfc: unable to kmalloc!\n");
++ hfc_shutdownCard(hfctmp);
++ kfree(hfctmp);
++ multi_hfc = NULL;
++ return -ENOMEM;
++ }
++ memset(zthfc, 0x0, sizeof(struct dahdi_hfc));
++
++ zthfc->card = hfctmp;
++ zthfc_initialize(zthfc);
++ hfctmp->ztdev = zthfc;
++
++ memset(hfctmp->drecbuf, 0x0, sizeof(hfctmp->drecbuf));
++ hfctmp->ztdev->chans[2].readchunk = hfctmp->drecbuf;
++
++ memset(hfctmp->dtransbuf, 0x0, sizeof(hfctmp->dtransbuf));
++ hfctmp->ztdev->chans[2].writechunk = hfctmp->dtransbuf;
++
++ memset(hfctmp->brecbuf[0], 0x0, sizeof(hfctmp->brecbuf[0]));
++ hfctmp->ztdev->chans[0].readchunk = hfctmp->brecbuf[0];
++ memset(hfctmp->btransbuf[0], 0x0, sizeof(hfctmp->btransbuf[0]));
++ hfctmp->ztdev->chans[0].writechunk = hfctmp->btransbuf[0];
++
++ memset(hfctmp->brecbuf[1], 0x0, sizeof(hfctmp->brecbuf[1]));
++ hfctmp->ztdev->chans[1].readchunk = hfctmp->brecbuf[1];
++ memset(hfctmp->btransbuf[1], 0x0, sizeof(hfctmp->btransbuf[1]));
++ hfctmp->ztdev->chans[1].writechunk = hfctmp->btransbuf[1];
++
++
++ hfc_registerCard(hfctmp);
++ hfc_resetCard(hfctmp);
++ tmp = pci_get_device(pcivendor, pcidevice, multi_hfc);
++ }
++ return 0;
++}
++
++
++
++int init_module(void) {
++ int i = 0;
++#ifdef RTAITIMING
++ RTIME tick_period;
++ for (i=0; i < hfc_MAX_CARDS; i++) {
++ rtai_hfc_list[i] = NULL;
++ }
++ rt_set_periodic_mode();
++#endif
++ i = 0;
++ while (id_list[i].vendor_id) {
++ multi_hfc = NULL;
++ hfc_findCards(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_name, id_list[i].card_name);
++ i++;
++ }
++#ifdef RTAITIMING
++ for (i=0; i < hfc_MAX_CARDS; i++) {
++ if (rtai_hfc_list[i]) {
++ printk(KERN_INFO
++ "zaphfc: configured %d at mem %#x fifo %#x(%#x) for realtime servicing\n",
++ rtai_hfc_list[i]->cardno,
++ (u_int) rtai_hfc_list[i]->pci_io,
++ (u_int) rtai_hfc_list[i]->fifos,
++ (u_int) virt_to_bus(rtai_hfc_list[i]->fifos));
++
++ }
++ }
++ rt_task_init(&rt_task, rtai_loop, 1, STACK_SIZE, TASK_PRIORITY, 0, 0);
++ tick_period = start_rt_timer(nano2count(TICK_PERIOD));
++ rt_task_make_periodic(&rt_task, rt_get_time() + tick_period, tick_period);
++#endif
++ printk(KERN_INFO "zaphfc: %d hfc-pci card(s) in this box.\n", hfc_dev_count);
++ return 0;
++}
++
++void cleanup_module(void) {
++ struct hfc_card *tmpcard;
++#ifdef RTAITIMING
++ stop_rt_timer();
++ rt_task_delete(&rt_task);
++#endif
++ printk(KERN_INFO "zaphfc: stop\n");
++// spin_lock(&registerlock);
++ while (hfc_dev_list != NULL) {
++ if (hfc_dev_list == NULL) break;
++ hfc_shutdownCard(hfc_dev_list);
++ tmpcard = hfc_dev_list;
++ hfc_dev_list = hfc_dev_list->next;
++ if (tmpcard != NULL) {
++ kfree(tmpcard);
++ tmpcard = NULL;
++ printk(KERN_INFO "zaphfc: freed one card.\n");
++ }
++ }
++// spin_unlock(&registerlock);
++}
++#endif
++
++
++module_param(modes, int, 0600);
++module_param(debug, int, 0600);
++
++MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver");
++MODULE_AUTHOR("Klaus-Peter Junghanns <kpj@junghanns.net>");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
+Index: dahdi-linux-2.1.0/drivers/dahdi/zaphfc.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ dahdi-linux-2.1.0/drivers/dahdi/zaphfc.h 2008-12-10 12:46:14.000000000 +0200
+@@ -0,0 +1,290 @@
++/*
++ * zaphfc.h - Zaptel driver for HFC-S PCI A based ISDN BRI cards
++ *
++ * kernel module based on HFC PCI ISDN4Linux and Zaptel drivers
++ *
++ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
++ * This program is free software and may be modified and
++ * distributed under the terms of the GNU Public License.
++ *
++ */
++
++/* HFC register addresses - accessed using memory mapped I/O */
++/* For a list, see datasheet section 3.2.1 at page 21 */
++
++#define hfc_outb(a,b,c) (writeb((c),(a)->pci_io+(b)))
++#define hfc_inb(a,b) (readb((a)->pci_io+(b)))
++
++/* GCI/IOM bus monitor registers */
++
++#define hfc_C_I 0x08
++#define hfc_TRxR 0x0C
++#define hfc_MON1_D 0x28
++#define hfc_MON2_D 0x2C
++
++
++/* GCI/IOM bus timeslot registers */
++
++#define hfc_B1_SSL 0x80
++#define hfc_B2_SSL 0x84
++#define hfc_AUX1_SSL 0x88
++#define hfc_AUX2_SSL 0x8C
++#define hfc_B1_RSL 0x90
++#define hfc_B2_RSL 0x94
++#define hfc_AUX1_RSL 0x98
++#define hfc_AUX2_RSL 0x9C
++
++/* GCI/IOM bus data registers */
++
++#define hfc_B1_D 0xA0
++#define hfc_B2_D 0xA4
++#define hfc_AUX1_D 0xA8
++#define hfc_AUX2_D 0xAC
++
++/* GCI/IOM bus configuration registers */
++
++#define hfc_MST_EMOD 0xB4
++#define hfc_MST_MODE 0xB8
++#define hfc_CONNECT 0xBC
++
++
++/* Interrupt and status registers */
++
++#define hfc_FIFO_EN 0x44
++#define hfc_TRM 0x48
++#define hfc_B_MODE 0x4C
++#define hfc_CHIP_ID 0x58
++#define hfc_CIRM 0x60
++#define hfc_CTMT 0x64
++#define hfc_INT_M1 0x68
++#define hfc_INT_M2 0x6C
++#define hfc_INT_S1 0x78
++#define hfc_INT_S2 0x7C
++#define hfc_STATUS 0x70
++
++/* S/T section registers */
++
++#define hfc_STATES 0xC0
++#define hfc_SCTRL 0xC4
++#define hfc_SCTRL_E 0xC8
++#define hfc_SCTRL_R 0xCC
++#define hfc_SQ 0xD0
++#define hfc_CLKDEL 0xDC
++#define hfc_B1_REC 0xF0
++#define hfc_B1_SEND 0xF0
++#define hfc_B2_REC 0xF4
++#define hfc_B2_SEND 0xF4
++#define hfc_D_REC 0xF8
++#define hfc_D_SEND 0xF8
++#define hfc_E_REC 0xFC
++
++/* Bits and values in various HFC PCI registers */
++
++/* bits in status register (READ) */
++#define hfc_STATUS_PCI_PROC 0x02
++#define hfc_STATUS_NBUSY 0x04
++#define hfc_STATUS_TIMER_ELAP 0x10
++#define hfc_STATUS_STATINT 0x20
++#define hfc_STATUS_FRAMEINT 0x40
++#define hfc_STATUS_ANYINT 0x80
++
++/* bits in CTMT (Write) */
++#define hfc_CTMT_CLTIMER 0x80
++#define hfc_CTMT_TIM3_125 0x04
++#define hfc_CTMT_TIM25 0x10
++#define hfc_CTMT_TIM50 0x14
++#define hfc_CTMT_TIM400 0x18
++#define hfc_CTMT_TIM800 0x1C
++#define hfc_CTMT_AUTO_TIMER 0x20
++#define hfc_CTMT_TRANSB2 0x02
++#define hfc_CTMT_TRANSB1 0x01
++
++/* bits in CIRM (Write) */
++#define hfc_CIRM_AUX_MSK 0x07
++#define hfc_CIRM_RESET 0x08
++#define hfc_CIRM_B1_REV 0x40
++#define hfc_CIRM_B2_REV 0x80
++
++/* bits in INT_M1 and INT_S1 */
++#define hfc_INTS_B1TRANS 0x01
++#define hfc_INTS_B2TRANS 0x02
++#define hfc_INTS_DTRANS 0x04
++#define hfc_INTS_B1REC 0x08
++#define hfc_INTS_B2REC 0x10
++#define hfc_INTS_DREC 0x20
++#define hfc_INTS_L1STATE 0x40
++#define hfc_INTS_TIMER 0x80
++
++/* bits in INT_M2 */
++#define hfc_M2_PROC_TRANS 0x01
++#define hfc_M2_GCI_I_CHG 0x02
++#define hfc_M2_GCI_MON_REC 0x04
++#define hfc_M2_IRQ_ENABLE 0x08
++#define hfc_M2_PMESEL 0x80
++
++/* bits in STATES */
++#define hfc_STATES_STATE_MASK 0x0F
++#define hfc_STATES_LOAD_STATE 0x10
++#define hfc_STATES_ACTIVATE 0x20
++#define hfc_STATES_DO_ACTION 0x40
++#define hfc_STATES_NT_G2_G3 0x80
++
++/* bits in HFCD_MST_MODE */
++#define hfc_MST_MODE_MASTER 0x01
++#define hfc_MST_MODE_SLAVE 0x00
++/* remaining bits are for codecs control */
++
++/* bits in HFCD_SCTRL */
++#define hfc_SCTRL_B1_ENA 0x01
++#define hfc_SCTRL_B2_ENA 0x02
++#define hfc_SCTRL_MODE_TE 0x00
++#define hfc_SCTRL_MODE_NT 0x04
++#define hfc_SCTRL_LOW_PRIO 0x08
++#define hfc_SCTRL_SQ_ENA 0x10
++#define hfc_SCTRL_TEST 0x20
++#define hfc_SCTRL_NONE_CAP 0x40
++#define hfc_SCTRL_PWR_DOWN 0x80
++
++/* bits in SCTRL_E */
++#define hfc_SCTRL_E_AUTO_AWAKE 0x01
++#define hfc_SCTRL_E_DBIT_1 0x04
++#define hfc_SCTRL_E_IGNORE_COL 0x08
++#define hfc_SCTRL_E_CHG_B1_B2 0x80
++
++/* bits in FIFO_EN register */
++#define hfc_FIFOEN_B1TX 0x01
++#define hfc_FIFOEN_B1RX 0x02
++#define hfc_FIFOEN_B2TX 0x04
++#define hfc_FIFOEN_B2RX 0x08
++#define hfc_FIFOEN_DTX 0x10
++#define hfc_FIFOEN_DRX 0x20
++
++#define hfc_FIFOEN_B1 (hfc_FIFOEN_B1TX|hfc_FIFOEN_B1RX)
++#define hfc_FIFOEN_B2 (hfc_FIFOEN_B2TX|hfc_FIFOEN_B2RX)
++#define hfc_FIFOEN_D (hfc_FIFOEN_DTX|hfc_FIFOEN_DRX)
++
++/* bits in the CONNECT register */
++#define hfc_CONNECT_B1_shift 0
++#define hfc_CONNECT_B2_shift 3
++
++#define hfc_CONNECT_HFC_from_ST 0x0
++#define hfc_CONNECT_HFC_from_GCI 0x1
++#define hfc_CONNECT_ST_from_HFC 0x0
++#define hfc_CONNECT_ST_from_GCI 0x2
++#define hfc_CONNECT_GCI_from_HFC 0x0
++#define hfc_CONNECT_GCI_from_ST 0x4
++
++/* bits in the __SSL and __RSL registers */
++#define hfc_SRSL_STIO 0x40
++#define hfc_SRSL_ENABLE 0x80
++#define hfc_SRCL_SLOT_MASK 0x1f
++
++/* FIFO memory definitions */
++
++#define hfc_FMASK 0x000f
++#define hfc_ZMASK 0x01ff
++#define hfc_ZMASKB 0x1fff
++
++#define hfc_D_FIFO_SIZE 0x0200
++#define hfc_B_SUB_VAL 0x0200
++#define hfc_B_FIFO_SIZE 0x1E00
++#define hfc_MAX_DFRAMES 0x000f
++
++#define hfc_FIFO_DTX_Z1 0x2080
++#define hfc_FIFO_DTX_Z2 0x2082
++#define hfc_FIFO_DTX_F1 0x20a0
++#define hfc_FIFO_DTX_F2 0x20a1
++#define hfc_FIFO_DTX 0x0000
++#define hfc_FIFO_DTX_ZOFF 0x000
++
++#define hfc_FIFO_DRX_Z1 0x6080
++#define hfc_FIFO_DRX_Z2 0x6082
++#define hfc_FIFO_DRX_F1 0x60a0
++#define hfc_FIFO_DRX_F2 0x60a1
++#define hfc_FIFO_DRX 0x4000
++#define hfc_FIFO_DRX_ZOFF 0x4000
++
++#define hfc_FIFO_B1TX_Z1 0x2000
++#define hfc_FIFO_B1TX_Z2 0x2002
++#define hfc_FIFO_B1RX_Z1 0x6000
++#define hfc_FIFO_B1RX_Z2 0x6002
++
++#define hfc_FIFO_B1TX_F1 0x2080
++#define hfc_FIFO_B1TX_F2 0x2081
++#define hfc_FIFO_B1RX_F1 0x6080
++#define hfc_FIFO_B1RX_F2 0x6081
++
++#define hfc_FIFO_B1RX_ZOFF 0x4000
++#define hfc_FIFO_B1TX_ZOFF 0x0000
++
++#define hfc_FIFO_B2TX_Z1 0x2100
++#define hfc_FIFO_B2TX_Z2 0x2102
++#define hfc_FIFO_B2RX_Z1 0x6100
++#define hfc_FIFO_B2RX_Z2 0x6102
++
++#define hfc_FIFO_B2TX_F1 0x2180
++#define hfc_FIFO_B2TX_F2 0x2181
++#define hfc_FIFO_B2RX_F1 0x6180
++#define hfc_FIFO_B2RX_F2 0x6181
++
++#define hfc_FIFO_B2RX_ZOFF 0x6000
++#define hfc_FIFO_B2TX_ZOFF 0x2000
++
++#define hfc_BTRANS_THRESHOLD 128
++#define hfc_BTRANS_THRESMASK 0x00
++
++/* Structures */
++
++typedef struct hfc_regs {
++ unsigned char fifo_en;
++ unsigned char ctmt;
++ unsigned char int_m1;
++ unsigned char int_m2;
++ unsigned char sctrl;
++ unsigned char sctrl_e;
++ unsigned char sctrl_r;
++ unsigned char connect;
++ unsigned char trm;
++ unsigned char mst_mode;
++ unsigned char bswapped;
++ unsigned char nt_mode;
++ unsigned char int_drec;
++} hfc_regs;
++
++typedef struct hfc_card {
++ spinlock_t lock;
++ unsigned int irq;
++ unsigned int iomem;
++ int ticks;
++ int clicks;
++ unsigned char *pci_io;
++ void *fifomem; // start of the shared mem
++ volatile void *fifos; // 32k aligned mem for the fifos
++ struct hfc_regs regs;
++ unsigned int pcibus;
++ unsigned int pcidevfn;
++ struct pci_dev *pcidev;
++ struct dahdi_hfc *ztdev;
++ int drecinframe;
++ unsigned char drecbuf[hfc_D_FIFO_SIZE];
++ unsigned char dtransbuf[hfc_D_FIFO_SIZE];
++ unsigned char brecbuf[2][DAHDI_CHUNKSIZE];
++ unsigned char btransbuf[2][DAHDI_CHUNKSIZE];
++ unsigned char cardno;
++ struct hfc_card *next;
++} hfc_card;
++
++typedef struct dahdi_hfc {
++ unsigned int usecount;
++ struct dahdi_span span;
++ struct dahdi_chan chans[3];
++ struct dahdi_chan *_chans[3];
++ struct hfc_card *card;
++} dahdi_hfc;
++
++/* tune this */
++#define hfc_BCHAN_BUFFER 8
++#define hfc_MAX_CARDS 8
diff --git a/main/dahdi-linux-grsec/zaphfc-dahdi-2.4.0.patch b/main/dahdi-linux-grsec/zaphfc-dahdi-2.4.0.patch
new file mode 100644
index 0000000000..80500a574a
--- /dev/null
+++ b/main/dahdi-linux-grsec/zaphfc-dahdi-2.4.0.patch
@@ -0,0 +1,58 @@
+Index: dahdi-linux-2.4.0/drivers/dahdi/zaphfc.c
+===================================================================
+--- dahdi-linux-2.4.0.orig/drivers/dahdi/zaphfc.c 2010-10-26 14:41:21.000000000 +0300
++++ dahdi-linux-2.4.0/drivers/dahdi/zaphfc.c 2010-10-26 14:50:14.000000000 +0300
+@@ -617,7 +617,7 @@
+ }
+
+ static int zthfc_startup(struct dahdi_span *span) {
+- struct dahdi_hfc *zthfc = span->pvt;
++ struct dahdi_hfc *zthfc = container_of(span, struct dahdi_hfc, span);
+ struct hfc_card *hfctmp = zthfc->card;
+ int alreadyrunning;
+
+@@ -663,6 +663,19 @@
+ return 0;
+ }
+
++static const struct dahdi_span_ops zaphfc_span_ops = {
++ .owner = THIS_MODULE,
++ .spanconfig = zthfc_spanconfig,
++ .chanconfig = zthfc_chanconfig,
++ .startup = zthfc_startup,
++ .shutdown = zthfc_shutdown,
++ .maint = zthfc_maint,
++ .rbsbits = zthfc_rbsbits,
++ .open = zthfc_open,
++ .close = zthfc_close,
++ .ioctl = zthfc_ioctl,
++};
++
+ static int zthfc_initialize(struct dahdi_hfc *zthfc) {
+ struct hfc_card *hfctmp = zthfc->card;
+ int i;
+@@ -676,15 +689,7 @@
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1);
+ }
+
+- zthfc->span.spanconfig = zthfc_spanconfig;
+- zthfc->span.chanconfig = zthfc_chanconfig;
+- zthfc->span.startup = zthfc_startup;
+- zthfc->span.shutdown = zthfc_shutdown;
+- zthfc->span.maint = zthfc_maint;
+- zthfc->span.rbsbits = zthfc_rbsbits;
+- zthfc->span.open = zthfc_open;
+- zthfc->span.close = zthfc_close;
+- zthfc->span.ioctl = zthfc_ioctl;
++ zthfc->span.ops = &zaphfc_span_ops;
+
+ zthfc->span.channels = 3;
+ zthfc->span.chans = zthfc->_chans;
+@@ -695,7 +700,6 @@
+ zthfc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS; // <--- this is really BS
+ zthfc->span.offset = 0;
+ init_waitqueue_head(&zthfc->span.maintq);
+- zthfc->span.pvt = zthfc;
+
+ for (i = 0; i < zthfc->span.channels; i++) {
+ memset(&(zthfc->chans[i]), 0x0, sizeof(struct dahdi_chan));
diff --git a/main/dahdi-linux-grsec/zaphfc-dahdi-flortz.diff b/main/dahdi-linux-grsec/zaphfc-dahdi-flortz.diff
new file mode 100644
index 0000000000..719accdc69
--- /dev/null
+++ b/main/dahdi-linux-grsec/zaphfc-dahdi-flortz.diff
@@ -0,0 +1,1232 @@
+Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h
+===================================================================
+--- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.h 2009-03-17 18:13:54.000000000 +0200
++++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h 2009-03-17 18:14:44.000000000 +0200
+@@ -135,8 +135,12 @@
+ /* bits in HFCD_MST_MODE */
+ #define hfc_MST_MODE_MASTER 0x01
+ #define hfc_MST_MODE_SLAVE 0x00
++#define hfc_MST_MODE_F0_LONG_DURATION 0x08
+ /* remaining bits are for codecs control */
+
++/* bits in HFCD_MST_EMOD */
++#define hfc_MST_EMOD_SLOW_CLOCK_ADJ 0x01
++
+ /* bits in HFCD_SCTRL */
+ #define hfc_SCTRL_B1_ENA 0x01
+ #define hfc_SCTRL_B2_ENA 0x02
+@@ -236,6 +240,9 @@
+ #define hfc_BTRANS_THRESHOLD 128
+ #define hfc_BTRANS_THRESMASK 0x00
+
++#define hfc_FIFO_MEM_SIZE_BYTES (32*1024)
++#define hfc_FIFO_MEM_SIZE_PAGES ((hfc_FIFO_MEM_SIZE_BYTES+PAGE_SIZE-1)/PAGE_SIZE)
++
+ /* Structures */
+
+ typedef struct hfc_regs {
+@@ -249,20 +256,67 @@
+ unsigned char connect;
+ unsigned char trm;
+ unsigned char mst_mode;
++ unsigned char mst_emod;
+ unsigned char bswapped;
+ unsigned char nt_mode;
+ unsigned char int_drec;
+ } hfc_regs;
+
++struct bch {
++ int fill_fifo,checkcnt,initialized;
++ struct {
++ u16 z2;
++ struct {
++ volatile u16 *z1p;
++ volatile u8 *fifo_base;
++ int filled;
++ } c[2];
++ int diff;
++ } rx;
++ struct {
++ u16 z1;
++ struct {
++ volatile u16 *z1p,*z2p;
++ volatile u8 *fifo_base;
++ int filled;
++ } c[2];
++ int diff;
++ } tx;
++};
++
++struct dch {
++ struct {
++ struct {
++ volatile u8 *p;
++ } f1;
++ struct {
++ u8 v;
++ struct {
++ u16 v;
++ } z2;
++ } f2;
++ } rx;
++ struct {
++ struct {
++ u8 v;
++ volatile u8 *p;
++ struct {
++ u16 v;
++ } z1;
++ } f1;
++ struct {
++ volatile u8 *p;
++ } f2;
++ } tx;
++};
++
+ typedef struct hfc_card {
+ spinlock_t lock;
+ unsigned int irq;
+ unsigned int iomem;
+ int ticks;
+- int clicks;
+ unsigned char *pci_io;
+- void *fifomem; // start of the shared mem
+- volatile void *fifos; // 32k aligned mem for the fifos
++ void *fifos; // 32k aligned mem for the fifos
+ struct hfc_regs regs;
+ unsigned int pcibus;
+ unsigned int pcidevfn;
+@@ -274,6 +328,9 @@
+ unsigned char brecbuf[2][DAHDI_CHUNKSIZE];
+ unsigned char btransbuf[2][DAHDI_CHUNKSIZE];
+ unsigned char cardno;
++ int active;
++ struct bch bch;
++ struct dch dch;
+ struct hfc_card *next;
+ } hfc_card;
+
+@@ -285,6 +342,3 @@
+ struct hfc_card *card;
+ } dahdi_hfc;
+
+-/* tune this */
+-#define hfc_BCHAN_BUFFER 8
+-#define hfc_MAX_CARDS 8
+Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c
+===================================================================
+--- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.c 2009-03-17 18:52:47.000000000 +0200
++++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c 2009-03-17 18:53:43.000000000 +0200
+@@ -7,19 +7,21 @@
+ *
+ * Klaus-Peter Junghanns <kpj@junghanns.net>
+ *
++ * Copyright (C) 2004, 2005, 2006 Florian Zumbiehl <florz@gmx.de>
++ * - support for slave mode of the HFC-S chip which allows it to
++ * sync its sample clock to an external source/another HFC chip
++ * - support for "interrupt bundling" (let only one card generate
++ * 8 kHz timing interrupt no matter how many cards there are
++ * in the system)
++ * - interrupt loss tolerant b channel handling
++ *
+ * This program is free software and may be modified and
+- * distributed under the terms of the GNU Public License.
++ * distributed under the terms of the GNU General Public License.
+ *
+ */
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+-#ifdef RTAITIMING
+-#include <asm/io.h>
+-#include <rtai.h>
+-#include <rtai_sched.h>
+-#include <rtai_fifos.h>
+-#endif
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+@@ -29,6 +31,8 @@
+
+ #include <linux/moduleparam.h>
+
++#define log2(n) ffz(~(n))
++
+ #if CONFIG_PCI
+
+ #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
+@@ -70,42 +74,31 @@
+ static struct hfc_card *hfc_dev_list = NULL;
+ static int hfc_dev_count = 0;
+ static int modes = 0; // all TE
++static int sync_slave = 0; // all master
++static int timer_card = 0;
++static int jitterbuffer = 1;
+ static int debug = 0;
+ static struct pci_dev *multi_hfc = NULL;
+ static spinlock_t registerlock = SPIN_LOCK_UNLOCKED;
+
+-void hfc_shutdownCard(struct hfc_card *hfctmp) {
+- unsigned long flags;
+-
+- if (hfctmp == NULL) {
+- return;
+- }
+-
+- if (hfctmp->pci_io == NULL) {
+- return;
+- }
+-
+- spin_lock_irqsave(&hfctmp->lock,flags);
+-
++void hfc_shutdownCard1(struct hfc_card *hfctmp) {
+ printk(KERN_INFO "zaphfc: shutting down card at %p.\n",hfctmp->pci_io);
+
+ /* Clear interrupt mask */
+ hfctmp->regs.int_m2 = 0;
+ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+
+- /* Reset pending interrupts */
+- hfc_inb(hfctmp, hfc_INT_S1);
++ /* Remove interrupt handler */
++ free_irq(hfctmp->irq,hfctmp);
++}
++
++void hfc_shutdownCard2(struct hfc_card *hfctmp) {
++ unsigned long flags;
+
+- /* Wait for interrupts that might still be pending */
+- spin_unlock_irqrestore(&hfctmp->lock, flags);
+- set_current_state(TASK_UNINTERRUPTIBLE);
+- schedule_timeout((30 * HZ) / 1000); // wait 30 ms
+ spin_lock_irqsave(&hfctmp->lock,flags);
+
+- /* Remove interrupt handler */
+- if (hfctmp->irq) {
+- free_irq(hfctmp->irq, hfctmp);
+- }
++ /* Reset pending interrupts */
++ hfc_inb(hfctmp, hfc_INT_S1);
+
+ /* Soft-reset the card */
+ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on
+@@ -119,8 +112,8 @@
+
+ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, 0); // disable memio and bustmaster
+
+- if (hfctmp->fifomem != NULL) {
+- kfree(hfctmp->fifomem);
++ if (hfctmp->fifos != NULL) {
++ free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES));
+ }
+ iounmap((void *) hfctmp->pci_io);
+ hfctmp->pci_io = NULL;
+@@ -130,11 +123,24 @@
+ spin_unlock_irqrestore(&hfctmp->lock,flags);
+ if (hfctmp->ztdev != NULL) {
+ dahdi_unregister(&hfctmp->ztdev->span);
+- kfree(hfctmp->ztdev);
++ vfree(hfctmp->ztdev);
+ printk(KERN_INFO "unregistered from DAHDI.\n");
+ }
+ }
+
++void hfc_shutdownCard(struct hfc_card *hfctmp) {
++ if (hfctmp == NULL) {
++ return;
++ }
++
++ if (hfctmp->pci_io == NULL) {
++ return;
++ }
++
++ hfc_shutdownCard1(hfctmp);
++ hfc_shutdownCard2(hfctmp);
++}
++
+ void hfc_resetCard(struct hfc_card *hfctmp) {
+ unsigned long flags;
+
+@@ -178,14 +184,14 @@
+ hfctmp->regs.ctmt = hfc_CTMT_TRANSB1 | hfc_CTMT_TRANSB2; // all bchans are transparent , no freaking hdlc
+ hfc_outb(hfctmp, hfc_CTMT, hfctmp->regs.ctmt);
+
+- hfctmp->regs.int_m1 = 0;
++ hfctmp->regs.int_m1=hfc_INTS_L1STATE;
++ if(hfctmp->cardno==timer_card){
++ hfctmp->regs.int_m2=hfc_M2_PROC_TRANS;
++ }else{
++ hfctmp->regs.int_m1|=hfc_INTS_DREC;
++ hfctmp->regs.int_m2=0;
++ }
+ hfc_outb(hfctmp, hfc_INT_M1, hfctmp->regs.int_m1);
+-
+-#ifdef RTAITIMING
+- hfctmp->regs.int_m2 = 0;
+-#else
+- hfctmp->regs.int_m2 = hfc_M2_PROC_TRANS;
+-#endif
+ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+
+ /* Clear already pending ints */
+@@ -197,8 +203,8 @@
+ hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_TE; /* set tx_lo mode, error in datasheet ! */
+ }
+
+- hfctmp->regs.mst_mode = hfc_MST_MODE_MASTER; /* HFC Master Mode */
+ hfc_outb(hfctmp, hfc_MST_MODE, hfctmp->regs.mst_mode);
++ hfc_outb(hfctmp, hfc_MST_EMOD, hfctmp->regs.mst_emod);
+
+ hfc_outb(hfctmp, hfc_SCTRL, hfctmp->regs.sctrl);
+ hfctmp->regs.sctrl_r = 3;
+@@ -210,10 +216,8 @@
+ hfc_outb(hfctmp, hfc_CIRM, 0x80 | 0x40); // bit order
+
+ /* Finally enable IRQ output */
+-#ifndef RTAITIMING
+ hfctmp->regs.int_m2 |= hfc_M2_IRQ_ENABLE;
+ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+-#endif
+
+ /* clear pending ints */
+ hfc_inb(hfctmp, hfc_INT_S1);
+@@ -230,368 +234,210 @@
+ spin_unlock(&registerlock);
+ }
+
+-static void hfc_btrans(struct hfc_card *hfctmp, char whichB) {
+- // we are called with irqs disabled from the irq handler
+- int count, maxlen, total;
+- unsigned char *f1, *f2;
+- unsigned short *z1, *z2, newz1;
+- int freebytes;
+-
+- if (whichB == 1) {
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z2 + (*f1 * 4));
+- } else {
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z2 + (*f1 * 4));
+- }
+-
+- freebytes = *z2 - *z1;
+- if (freebytes <= 0) {
+- freebytes += hfc_B_FIFO_SIZE;
+- }
+- count = DAHDI_CHUNKSIZE;
+-
+- total = count;
+- if (freebytes < count) {
+- hfctmp->clicks++;
+- /* only spit out this warning once per second to not make things worse! */
+- if (hfctmp->clicks > 100) {
+- printk(KERN_CRIT "zaphfc: bchan tx fifo full, dropping audio! (z1=%d, z2=%d)\n",*z1,*z2);
+- hfctmp->clicks = 0;
+- }
+- return;
+- }
+-
+- maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z1;
+- if (maxlen > count) {
+- maxlen = count;
+- }
+- newz1 = *z1 + total;
+- if (newz1 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { newz1 -= hfc_B_FIFO_SIZE; }
++/*===========================================================================*/
+
+- if (whichB == 1) {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + *z1),hfctmp->ztdev->chans[0].writechunk, maxlen);
+- } else {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + *z1),hfctmp->ztdev->chans[1].writechunk, maxlen);
+- }
+-
+- count -= maxlen;
+- if (count > 0) {
+- // Buffer wrap
+- if (whichB == 1) {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[0].writechunk+maxlen, count);
+- } else {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[1].writechunk+maxlen, count);
+- }
+- }
++#if hfc_B_FIFO_SIZE%DAHDI_CHUNKSIZE
++#error hfc_B_FIFO_SIZE is not a multiple of DAHDI_CHUNKSIZE even though the code assumes this
++#endif
++
++static void hfc_dch_init(struct hfc_card *hfctmp){
++ struct dch *chtmp=&hfctmp->dch;
+
+- *z1 = newz1; /* send it now */
++ chtmp->rx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DRX_F1);
++ chtmp->rx.f2.v=0x1f;
++ chtmp->rx.f2.z2.v=0x1ff;
+
+-// if (count > 0) printk(KERN_CRIT "zaphfc: bchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
+- return;
++ chtmp->tx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F1);
++ chtmp->tx.f1.v=0x1f;
++ chtmp->tx.f1.z1.v=0x1ff;
++ chtmp->tx.f2.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F2);
+ }
+
+-static void hfc_brec(struct hfc_card *hfctmp, char whichB) {
+- // we are called with irqs disabled from the irq handler
+- int count, maxlen, drop;
+- volatile unsigned char *f1, *f2;
+- volatile unsigned short *z1, *z2, newz2;
+- int bytes = 0;
+-
+- if (whichB == 1) {
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
+- } else {
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
+- }
++static void hfc_bch_init(struct hfc_card *hfctmp){
++ struct bch *chtmp=&hfctmp->bch;
+
+- bytes = *z1 - *z2;
+- if (bytes < 0) {
+- bytes += hfc_B_FIFO_SIZE;
+- }
+- count = DAHDI_CHUNKSIZE;
+-
+- if (bytes < DAHDI_CHUNKSIZE) {
+-#ifndef RTAITIMING
+- printk(KERN_CRIT "zaphfc: bchan rx fifo not enough bytes to receive! (z1=%d, z2=%d, wanted %d got %d), probably a buffer overrun.\n",*z1,*z2,DAHDI_CHUNKSIZE,bytes);
+-#endif
+- return;
+- }
++ chtmp->checkcnt=0;
++ chtmp->fill_fifo=0;
+
+- /* allowing the buffering of hfc_BCHAN_BUFFER bytes of audio data works around irq jitter */
+- if (bytes > hfc_BCHAN_BUFFER + DAHDI_CHUNKSIZE) {
+- /* if the system is too slow to handle it, we will have to drop it all (except 1 DAHDI chunk) */
+- drop = bytes - DAHDI_CHUNKSIZE;
+- hfctmp->clicks++;
+- /* only spit out this warning once per second to not make things worse! */
+- if (hfctmp->clicks > 100) {
+- printk(KERN_CRIT "zaphfc: dropped audio (z1=%d, z2=%d, wanted %d got %d, dropped %d).\n",*z1,*z2,count,bytes,drop);
+- hfctmp->clicks = 0;
+- }
+- /* hm, we are processing the b chan data tooooo slowly... let's drop the lost audio */
+- newz2 = *z2 + drop;
+- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
+- newz2 -= hfc_B_FIFO_SIZE;
+- }
+- *z2 = newz2;
+- }
++ chtmp->rx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1RX_Z1+0x1f*4);
++ chtmp->rx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1RX_ZOFF);
++ chtmp->rx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2RX_Z1+0x1f*4);
++ chtmp->rx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2RX_ZOFF);
++ chtmp->rx.z2=hfc_B_SUB_VAL;
++ chtmp->rx.diff=0;
+
+-
+- maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z2;
+- if (maxlen > count) {
+- maxlen = count;
+- }
+- if (whichB == 1) {
+- memcpy(hfctmp->ztdev->chans[0].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + *z2), maxlen);
+- } else {
+- memcpy(hfctmp->ztdev->chans[1].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + *z2), maxlen);
+- }
+- newz2 = *z2 + count;
+- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
+- newz2 -= hfc_B_FIFO_SIZE;
++ chtmp->tx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z1+0x1f*4);
++ chtmp->tx.c[0].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z2+0x1f*4);
++ chtmp->tx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1TX_ZOFF);
++ chtmp->tx.c[0].filled=0;
++ chtmp->tx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z1+0x1f*4);
++ chtmp->tx.c[1].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z2+0x1f*4);
++ chtmp->tx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2TX_ZOFF);
++ chtmp->tx.c[1].filled=0;
++ chtmp->tx.z1=hfc_B_SUB_VAL;
++ chtmp->tx.diff=0;
++
++ hfc_dch_init(hfctmp);
++
++ chtmp->initialized=0;
++}
++
++static int hfc_bch_check(struct hfc_card *hfctmp){
++ struct bch *chtmp=&hfctmp->bch;
++ int x,r;
++
++ for(x=0;x<2;x++){
++ chtmp->tx.c[x].filled=(chtmp->tx.z1-*chtmp->tx.c[x].z2p+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE;
++ chtmp->rx.c[x].filled=(*chtmp->rx.c[x].z1p-chtmp->rx.z2+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE;
+ }
+- *z2 = newz2;
+-
+- count -= maxlen;
+- if (count > 0) {
+- // Buffer wrap
+- if (whichB == 1) {
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
+- memcpy(hfctmp->ztdev->chans[0].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + hfc_B_SUB_VAL), count);
+- } else {
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
+- memcpy(hfctmp->ztdev->chans[1].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + hfc_B_SUB_VAL), count);
+- }
+- newz2 = *z2 + count;
+- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
+- newz2 -= hfc_B_FIFO_SIZE;
++ if(chtmp->fill_fifo){
++ chtmp->checkcnt++;
++ chtmp->checkcnt%=DAHDI_CHUNKSIZE;
++ r=!chtmp->checkcnt;
++ }else{
++ x=chtmp->tx.c[0].filled-chtmp->tx.c[1].filled;
++ if(abs(x-chtmp->tx.diff)>1){
++ printk(KERN_CRIT "zaphfc[%d]: tx sync changed: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled);
++ chtmp->tx.diff=x;
+ }
++ r=chtmp->tx.c[0].filled<=DAHDI_CHUNKSIZE*jitterbuffer&&chtmp->tx.c[1].filled<=DAHDI_CHUNKSIZE*jitterbuffer;
+ }
++ return(r);
++}
+
++#define hfc_bch_inc_z(a,b) (a)=((a)-hfc_B_SUB_VAL+(b))%hfc_B_FIFO_SIZE+hfc_B_SUB_VAL
+
+- if (whichB == 1) {
+- dahdi_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk);
+- } else {
+- dahdi_ec_chunk(&hfctmp->ztdev->chans[1], hfctmp->ztdev->chans[1].readchunk, hfctmp->ztdev->chans[1].writechunk);
++static void hfc_bch_tx(struct hfc_card *hfctmp){
++ struct bch *chtmp=&hfctmp->bch;
++ int x;
++
++ for(x=0;x<2;x++)
++ memcpy((void *)(chtmp->tx.c[x].fifo_base+chtmp->tx.z1),hfctmp->ztdev->chans[x].writechunk,DAHDI_CHUNKSIZE);
++ hfc_bch_inc_z(chtmp->tx.z1,DAHDI_CHUNKSIZE);
++ if(chtmp->fill_fifo){
++ chtmp->fill_fifo--;
++ }else if(chtmp->tx.c[0].filled<=1||chtmp->tx.c[1].filled<=1){
++ chtmp->fill_fifo=jitterbuffer;
++ if(chtmp->initialized)
++ printk(KERN_CRIT "zaphfc[%d]: b channel buffer underrun: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled);
+ }
+- return;
++ if(!chtmp->fill_fifo)
++ for(x=0;x<2;x++)*chtmp->tx.c[x].z1p=chtmp->tx.z1;
+ }
+
+-
+-static void hfc_dtrans(struct hfc_card *hfctmp) {
+- // we are called with irqs disabled from the irq handler
++static void hfc_bch_rx(struct hfc_card *hfctmp){
++ struct bch *chtmp=&hfctmp->bch;
+ int x;
+- int count, maxlen, total;
+- unsigned char *f1, *f2, newf1;
+- unsigned short *z1, *z2, newz1;
+- int frames, freebytes;
+
+- if (hfctmp->ztdev->chans[2].bytes2transmit == 0) {
+- return;
++ x=chtmp->rx.c[0].filled-chtmp->rx.c[1].filled;
++ if(abs(x-chtmp->rx.diff)>1){
++ printk(KERN_CRIT "zaphfc[%d]: rx sync changed: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled);
++ chtmp->rx.diff=x;
+ }
+-
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z2 + (*f1 * 4));
+-
+- frames = (*f1 - *f2) & hfc_FMASK;
+- if (frames < 0) {
+- frames += hfc_MAX_DFRAMES + 1;
++ if(chtmp->rx.c[0].filled>=DAHDI_CHUNKSIZE&&chtmp->rx.c[1].filled>=DAHDI_CHUNKSIZE){
++ if((chtmp->rx.c[0].filled>=DAHDI_CHUNKSIZE*(jitterbuffer+2)&&chtmp->rx.c[1].filled>=DAHDI_CHUNKSIZE*(jitterbuffer+2))||!chtmp->initialized){
++ if(chtmp->initialized)
++ printk(KERN_CRIT "zaphfc[%d]: b channel buffer overflow: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled);
++ hfc_bch_inc_z(chtmp->rx.z2,chtmp->rx.c[0].filled-chtmp->rx.c[0].filled%DAHDI_CHUNKSIZE-DAHDI_CHUNKSIZE);
++ chtmp->initialized=1;
++ }
++ for(x=0;x<2;x++){
++ memcpy(hfctmp->ztdev->chans[x].readchunk,(void *)(chtmp->rx.c[x].fifo_base+chtmp->rx.z2),DAHDI_CHUNKSIZE);
++ dahdi_ec_chunk(&hfctmp->ztdev->chans[x],hfctmp->ztdev->chans[x].readchunk,hfctmp->ztdev->chans[x].writechunk);
++ }
++ hfc_bch_inc_z(chtmp->rx.z2,DAHDI_CHUNKSIZE);
+ }
++}
+
+- if (frames >= hfc_MAX_DFRAMES) {
+- printk(KERN_CRIT "zaphfc: dchan tx fifo total number of frames exceeded!\n");
+- return;
+- }
++/*===========================================================================*/
+
+- freebytes = *z2 - *z1;
+- if (freebytes <= 0) {
+- freebytes += hfc_D_FIFO_SIZE;
+- }
+- count = hfctmp->ztdev->chans[2].bytes2transmit;
+-
+- total = count;
+- if (freebytes < count) {
+- printk(KERN_CRIT "zaphfc: dchan tx fifo not enough free bytes! (z1=%d, z2=%d)\n",*z1,*z2);
+- return;
+- }
+-
+- newz1 = (*z1 + count) & hfc_ZMASK;
+- newf1 = ((*f1 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); // next frame
+-
+- if (count > 0) {
+- if (debug) {
+- printk(KERN_CRIT "zaphfc: card %d TX [ ", hfctmp->cardno);
+- for (x=0; x<count; x++) {
++static void hfc_dch_tx(struct hfc_card *hfctmp){
++ struct dch *chtmp=&hfctmp->dch;
++ u8 tx_f2_v;
++ u16 x;
++
++ if(hfctmp->ztdev->chans[2].bytes2transmit){
++ if(debug){
++ printk(KERN_CRIT "zaphfc[%d]: card TX [ ",hfctmp->cardno);
++ for(x=0;x<hfctmp->ztdev->chans[2].bytes2transmit;x++){
+ printk("%#2x ",hfctmp->dtransbuf[x]);
+ }
+- if (hfctmp->ztdev->chans[2].eoftx == 1) {
+- printk("] %d bytes\n", count);
+- } else {
+- printk("..] %d bytes\n", count);
+- }
+- }
+- maxlen = hfc_D_FIFO_SIZE - *z1;
+- if (maxlen > count) {
+- maxlen = count;
++ printk("] %d bytes\n",hfctmp->ztdev->chans[2].bytes2transmit);
+ }
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF + *z1),hfctmp->ztdev->chans[2].writechunk, maxlen);
+- count -= maxlen;
+- if (count > 0) {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF),(char *)(hfctmp->ztdev->chans[2].writechunk + maxlen), count);
++ tx_f2_v=*chtmp->tx.f2.p;
++ if(!(tx_f2_v-chtmp->tx.f1.v+hfc_MAX_DFRAMES+1-1)&(hfc_MAX_DFRAMES+1-1)){
++ printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo total number of frames exceeded!\n",hfctmp->cardno);
++ }else{
++ if(((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+tx_f2_v*4)-chtmp->tx.f1.z1.v+hfc_D_FIFO_SIZE-1)&(hfc_D_FIFO_SIZE-1))<hfctmp->ztdev->chans[2].bytes2transmit){
++ printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo not enough space for frame!\n",hfctmp->cardno);
++ }else{
++ chtmp->tx.f1.v=((chtmp->tx.f1.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1);
++ x=min(hfctmp->ztdev->chans[2].bytes2transmit,hfc_D_FIFO_SIZE-chtmp->tx.f1.z1.v);
++ memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF+chtmp->tx.f1.z1.v,hfctmp->ztdev->chans[2].writechunk,x);
++ memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF,hfctmp->ztdev->chans[2].writechunk+x,hfctmp->ztdev->chans[2].bytes2transmit-x);
++ *(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v;
++ chtmp->tx.f1.z1.v=(chtmp->tx.f1.z1.v+hfctmp->ztdev->chans[2].bytes2transmit+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1);
++ *(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z1+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v;
++ *chtmp->tx.f1.p=chtmp->tx.f1.v;
++ }
+ }
+ }
+-
+- *z1 = newz1;
+-
+- if (hfctmp->ztdev->chans[2].eoftx == 1) {
+- *f1 = newf1;
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
+- *z1 = newz1;
+- hfctmp->ztdev->chans[2].eoftx = 0;
+- }
+-// printk(KERN_CRIT "zaphfc: dchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
+- return;
+ }
+
+-/* receive a complete hdlc frame, skip broken or short frames */
+-static void hfc_drec(struct hfc_card *hfctmp) {
+- int count=0, maxlen=0, framelen=0;
+- unsigned char *f1, *f2, *crcstat;
+- unsigned short *z1, *z2, oldz2, newz2;
++static void hfc_dch_rx(struct hfc_card *hfctmp){
++ struct dch *chtmp=&hfctmp->dch;
++ u16 size;
+
+ hfctmp->ztdev->chans[2].bytes2receive=0;
+- hfctmp->ztdev->chans[2].eofrx = 0;
+-
+- /* put the received data into the DAHDI buffer
+- we'll call dahdi_receive() later when the timer fires. */
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F2);
+-
+- if (*f1 == *f2) return; /* nothing received, strange eh? */
+-
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z1 + (*f2 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+-
+- /* calculate length of frame, including 2 bytes CRC and 1 byte STAT */
+- count = *z1 - *z2;
+-
+- if (count < 0) {
+- count += hfc_D_FIFO_SIZE; /* ring buffer wrapped */
+- }
+- count++;
+- framelen = count;
+-
+- crcstat = (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z1);
+-
+- if ((framelen < 4) || (*crcstat != 0x0)) {
+- /* the frame is too short for a valid HDLC frame or the CRC is borked */
+- printk(KERN_CRIT "zaphfc: empty HDLC frame or bad CRC received (framelen = %d, stat = %#x, card = %d).\n", framelen, *crcstat, hfctmp->cardno);
+- oldz2 = *z2;
+- *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */
+- // recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!!
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+- *z2 = (oldz2 + framelen) & hfc_ZMASK;
+- hfctmp->drecinframe = 0;
+- hfctmp->regs.int_drec--;
+- /* skip short or broken frames */
+- hfctmp->ztdev->chans[2].bytes2receive = 0;
+- return;
+- }
+-
+- count -= 1; /* strip STAT */
+- hfctmp->ztdev->chans[2].eofrx = 1;
+-
+- if (count + *z2 <= hfc_D_FIFO_SIZE) {
+- maxlen = count;
+- } else {
+- maxlen = hfc_D_FIFO_SIZE - *z2;
++ hfctmp->ztdev->chans[2].eofrx=0;
++ if(*chtmp->rx.f1.p==chtmp->rx.f2.v){
++ hfctmp->regs.int_drec=0;
++ }else{
++ size=((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DRX_Z1+chtmp->rx.f2.v*4)-chtmp->rx.f2.z2.v+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1))+1;
++ if(size<4){
++ printk(KERN_CRIT "zaphfc[%d]: empty HDLC frame received.\n",hfctmp->cardno);
++ }else{
++ u16 x=min(size,(u16)(hfc_D_FIFO_SIZE-chtmp->rx.f2.z2.v));
++ memcpy(hfctmp->drecbuf,hfctmp->fifos+hfc_FIFO_DRX_ZOFF+chtmp->rx.f2.z2.v,x);
++ memcpy(hfctmp->drecbuf+x,hfctmp->fifos+hfc_FIFO_DRX_ZOFF,size-x);
++ if(hfctmp->drecbuf[size-1]){
++ printk(KERN_CRIT "zaphfc[%d]: received d channel frame with bad CRC.\n",hfctmp->cardno);
++ }else{
++ hfctmp->ztdev->chans[2].bytes2receive=size-1;
++ hfctmp->ztdev->chans[2].eofrx=1;
++ }
++ }
++ chtmp->rx.f2.z2.v=(chtmp->rx.f2.z2.v+size)&(hfc_D_FIFO_SIZE-1);
++ chtmp->rx.f2.v=((chtmp->rx.f2.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1);
+ }
+-
+- /* copy first part */
+- memcpy(hfctmp->drecbuf, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z2), maxlen);
+- hfctmp->ztdev->chans[2].bytes2receive += maxlen;
+-
+- count -= maxlen;
+- if (count > 0) {
+- /* ring buffer wrapped, copy rest from start of d fifo */
+- memcpy(hfctmp->drecbuf + maxlen, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF), count);
+- hfctmp->ztdev->chans[2].bytes2receive += count;
+- }
+-
+- /* frame read */
+- oldz2 = *z2;
+- newz2 = (oldz2 + framelen) & hfc_ZMASK;
+- *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */
+- /* recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! */
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+- *z2 = newz2;
+- hfctmp->drecinframe = 0;
+- hfctmp->regs.int_drec--;
+ }
+
+-#ifndef RTAITIMING
+ DAHDI_IRQ_HANDLER(hfc_interrupt) {
+ struct hfc_card *hfctmp = dev_id;
+- unsigned long flags = 0;
+- unsigned char stat;
+-#else
+-static void hfc_service(struct hfc_card *hfctmp) {
+-#endif
++ struct hfc_card *hfctmp2;
+ struct dahdi_hfc *zthfc;
+- unsigned char s1, s2, l1state;
++ unsigned char stat, s1, s2, l1state;
++ unsigned long flags = 0;
++ unsigned long flags2 = 0;
+ int x;
+
+ if (!hfctmp) {
+-#ifndef RTAITIMING
+- return IRQ_NONE;
+-#else
+- /* rtai */
+- return;
+-#endif
++ return IRQ_NONE;
+ }
+
+ if (!hfctmp->pci_io) {
+ printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n",
+ __FUNCTION__);
+-#ifndef RTAITIMING
+ return IRQ_NONE;
+-#else
+- /* rtai */
+- return;
+-#endif
+ }
+
+- /* we assume a few things in this irq handler:
+- - the hfc-pci will only generate "timer" irqs (proc/non-proc)
+- - we need to use every 8th IRQ (to generate 1khz timing)
+- OR
+- - if we use rtai for timing the hfc-pci will not generate ANY irq,
+- instead rtai will call this "fake" irq with a 1khz realtime timer. :)
+- - rtai will directly service the card, not like it used to by triggering
+- the linux irq
+- */
+-
+-#ifndef RTAITIMING
+ spin_lock_irqsave(&hfctmp->lock, flags);
+ stat = hfc_inb(hfctmp, hfc_STATUS);
+-
+ if ((stat & hfc_STATUS_ANYINT) == 0) {
+ // maybe we are sharing the irq
+ spin_unlock_irqrestore(&hfctmp->lock,flags);
+ return IRQ_NONE;
+ }
+-#endif
+
+ s1 = hfc_inb(hfctmp, hfc_INT_S1);
+ s2 = hfc_inb(hfctmp, hfc_INT_S2);
+@@ -611,18 +457,10 @@
+ }
+ switch (l1state) {
+ case 3:
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d)", hfctmp->cardno, l1state);
+-#endif
+ break;
+ default:
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d)", hfctmp->cardno, l1state);
+-#endif
+ }
+ if (l1state == 2) {
+ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_ACTIVATE | hfc_STATES_DO_ACTION | hfc_STATES_NT_G2_G3);
+@@ -636,18 +474,10 @@
+ }
+ switch (l1state) {
+ case 7:
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d)", hfctmp->cardno, l1state);
+-#endif
+ break;
+ default:
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d)", hfctmp->cardno, l1state);
+-#endif
+ }
+ if (l1state == 3) {
+ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
+@@ -657,7 +487,7 @@
+ }
+ if (s1 & hfc_INTS_DREC) {
+ // D chan RX (bit 5)
+- hfctmp->regs.int_drec++;
++ hfctmp->regs.int_drec = 1;
+ // mr. zapata there is something for you!
+ // printk(KERN_CRIT "d chan rx\n");
+ }
+@@ -678,14 +508,10 @@
+ // B1 chan TX (bit 0)
+ }
+ }
+-#ifdef RTAITIMING
+- /* fake an irq */
+- s2 |= hfc_M2_PROC_TRANS;
+-#endif
+ if (s2 != 0) {
+ if (s2 & hfc_M2_PMESEL) {
+ // kaboom irq (bit 7)
+- printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n");
++ //printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n");
+ }
+ if (s2 & hfc_M2_GCI_MON_REC) {
+ // RxR monitor channel (bit 2)
+@@ -693,32 +519,31 @@
+ if (s2 & hfc_M2_GCI_I_CHG) {
+ // GCI I-change (bit 1)
+ }
+- if (s2 & hfc_M2_PROC_TRANS) {
++ if((s2&hfc_M2_PROC_TRANS)&&(hfctmp->cardno==timer_card)){
+ // processing/non-processing transition (bit 0)
+- hfctmp->ticks++;
+-#ifndef RTAITIMING
+- if (hfctmp->ticks > 7) {
+- // welcome to DAHDI timing :)
+-#endif
+- hfctmp->ticks = 0;
+-
+- if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
++ hfctmp2=hfctmp;
++ hfctmp=hfc_dev_list;
++ while(hfctmp){
++ if(hfctmp->active){
++ if(hfctmp!=hfctmp2)spin_lock_irqsave(&hfctmp->lock, flags2);
++ if(hfc_bch_check(hfctmp)){
++ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
+ // clear dchan buffer
++ // memset(hfctmp->drecbuf, 0x0, sizeof(hfctmp->drecbuf));
++
+ hfctmp->ztdev->chans[2].bytes2transmit = 0;
+ hfctmp->ztdev->chans[2].maxbytes2transmit = hfc_D_FIFO_SIZE;
+
+ dahdi_transmit(&(hfctmp->ztdev->span));
+
+- hfc_btrans(hfctmp,1);
+- hfc_btrans(hfctmp,2);
+- hfc_dtrans(hfctmp);
++ hfc_bch_tx(hfctmp);
++ hfc_dch_tx(hfctmp);
+ }
+
+- hfc_brec(hfctmp,1);
+- hfc_brec(hfctmp,2);
+- if (hfctmp->regs.int_drec > 0) {
++ hfc_bch_rx(hfctmp);
++ if (hfctmp->regs.int_drec) {
+ // dchan data to read
+- hfc_drec(hfctmp);
++ hfc_dch_rx(hfctmp);
+ if (hfctmp->ztdev->chans[2].bytes2receive > 0) {
+ if (debug) {
+ printk(KERN_CRIT "zaphfc: card %d RX [ ", hfctmp->cardno);
+@@ -743,17 +568,16 @@
+ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
+ dahdi_receive(&(hfctmp->ztdev->span));
+ }
+-
+-#ifndef RTAITIMING
+ }
+-#endif
++ if(hfctmp!=hfctmp2)spin_unlock_irqrestore(&hfctmp->lock,flags2);
++ }
++ hfctmp=hfctmp->next;
++ }
++ hfctmp=hfctmp2;
+ }
+-
+ }
+-#ifndef RTAITIMING
+ spin_unlock_irqrestore(&hfctmp->lock,flags);
+- return IRQ_RETVAL(1);
+-#endif
++ return IRQ_RETVAL(1);
+ }
+
+
+@@ -802,22 +626,22 @@
+ }
+ alreadyrunning = span->flags & DAHDI_FLAG_RUNNING;
+
+- if (!alreadyrunning) {
+- span->chans[2]->flags &= ~DAHDI_FLAG_HDLC;
+- span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN;
+-
+- span->flags |= DAHDI_FLAG_RUNNING;
++ if (alreadyrunning) return 0;
+
+- hfctmp->ticks = -2;
+- hfctmp->clicks = 0;
+- hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
+- hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
+- } else {
+- return 0;
+- }
++ span->chans[2]->flags &= ~DAHDI_FLAG_HDLC;
++ span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN;
++
++ span->flags |= DAHDI_FLAG_RUNNING;
++
++ hfctmp->ticks = -2;
++ hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
++ hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
++
++ hfc_bch_init(hfctmp);
+
+ // drivers, start engines!
+ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
++ hfctmp->active=1;
+ return 0;
+ }
+
+@@ -847,17 +671,9 @@
+
+ sprintf(zthfc->span.name, "ZTHFC%d", hfc_dev_count + 1);
+ if (hfctmp->regs.nt_mode == 1) {
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] [realtime]", hfc_dev_count + 1);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1);
+-#endif
+ } else {
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] [realtime]", hfc_dev_count + 1);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1);
+-#endif
+ }
+
+ zthfc->span.spanconfig = zthfc_spanconfig;
+@@ -897,32 +713,6 @@
+ return 0;
+ }
+
+-#ifdef RTAITIMING
+-#define TICK_PERIOD 1000000
+-#define TICK_PERIOD2 1000000000
+-#define TASK_PRIORITY 1
+-#define STACK_SIZE 10000
+-
+-static RT_TASK rt_task;
+-static struct hfc_card *rtai_hfc_list[hfc_MAX_CARDS];
+-static unsigned char rtai_hfc_counter = 0;
+-
+-static void rtai_register_hfc(struct hfc_card *hfctmp) {
+- rtai_hfc_list[rtai_hfc_counter++] = hfctmp;
+-}
+-
+-static void rtai_loop(int t) {
+- int i=0;
+- for (;;) {
+- for (i=0; i < rtai_hfc_counter; i++) {
+- if (rtai_hfc_list[i] != NULL)
+- hfc_service(rtai_hfc_list[i]);
+- }
+- rt_task_wait_period();
+- }
+-}
+-#endif
+-
+ int hfc_findCards(int pcivendor, int pcidevice, char *vendor_name, char *card_name) {
+ struct pci_dev *tmp;
+ struct hfc_card *hfctmp = NULL;
+@@ -938,9 +728,9 @@
+ }
+ pci_set_master(tmp);
+
+- hfctmp = kmalloc(sizeof(struct hfc_card), GFP_KERNEL);
++ hfctmp = vmalloc(sizeof(struct hfc_card));
+ if (!hfctmp) {
+- printk(KERN_WARNING "zaphfc: unable to kmalloc!\n");
++ printk(KERN_WARNING "zaphfc: unable to vmalloc!\n");
+ pci_disable_device(tmp);
+ multi_hfc = NULL;
+ return -ENOMEM;
+@@ -948,6 +738,7 @@
+ memset(hfctmp, 0x0, sizeof(struct hfc_card));
+ spin_lock_init(&hfctmp->lock);
+
++ hfctmp->active=0;
+ hfctmp->pcidev = tmp;
+ hfctmp->pcibus = tmp->bus->number;
+ hfctmp->pcidevfn = tmp->devfn;
+@@ -961,49 +752,39 @@
+ hfctmp->pci_io = (char *) tmp->resource[1].start;
+ if (!hfctmp->pci_io) {
+ printk(KERN_WARNING "zaphfc: no iomem!\n");
+- kfree(hfctmp);
++ vfree(hfctmp);
+ pci_disable_device(tmp);
+ multi_hfc = NULL;
+ return -1;
+ }
+-
+- hfctmp->fifomem = kmalloc(65536, GFP_KERNEL);
+- if (!hfctmp->fifomem) {
+- printk(KERN_WARNING "zaphfc: unable to kmalloc fifomem!\n");
+- kfree(hfctmp);
++
++ hfctmp->fifos=(void *)__get_free_pages(GFP_KERNEL,log2(hfc_FIFO_MEM_SIZE_PAGES));
++ if (!hfctmp->fifos) {
++ printk(KERN_WARNING "zaphfc: unable to __get_free_pages fifomem!\n");
++ vfree(hfctmp);
+ pci_disable_device(tmp);
+ multi_hfc = NULL;
+ return -ENOMEM;
+ } else {
+- memset(hfctmp->fifomem, 0x0, 65536);
+- hfctmp->fifos = (void *)(((ulong) hfctmp->fifomem) & ~0x7FFF) + 0x8000;
+ pci_write_config_dword(hfctmp->pcidev, 0x80, (u_int) virt_to_bus(hfctmp->fifos));
+ hfctmp->pci_io = ioremap((ulong) hfctmp->pci_io, 256);
+ }
+
+-#ifdef RTAITIMING
+- /* we need no stinking irq */
+- hfctmp->irq = 0;
+-#else
+ if (request_irq(hfctmp->irq, &hfc_interrupt, DAHDI_IRQ_SHARED, "zaphfc", hfctmp)) {
+ printk(KERN_WARNING "zaphfc: unable to register irq\n");
+- kfree(hfctmp->fifomem);
+- kfree(hfctmp);
++ free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES));
++ vfree(hfctmp);
+ iounmap((void *) hfctmp->pci_io);
+ pci_disable_device(tmp);
+ multi_hfc = NULL;
+ return -EIO;
+ }
+-#endif
+
+-#ifdef RTAITIMING
+- rtai_register_hfc(hfctmp);
+-#endif
+ printk(KERN_INFO
+- "zaphfc: %s %s configured at mem %lx fifo %lx(%#x) IRQ %d HZ %d\n",
++ "zaphfc: %s %s configured at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
+ vendor_name, card_name,
+- (unsigned long) hfctmp->pci_io,
+- (unsigned long) hfctmp->fifos,
++ (u_int) hfctmp->pci_io,
++ (u_int) hfctmp->fifos,
+ (u_int) virt_to_bus(hfctmp->fifos),
+ hfctmp->irq, HZ);
+ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio
+@@ -1020,11 +801,21 @@
+ hfctmp->regs.nt_mode = 0;
+ }
+
+- zthfc = kmalloc(sizeof(struct dahdi_hfc),GFP_KERNEL);
++ if(sync_slave&(1<<hfc_dev_count)){
++ printk(KERN_INFO "zaphfc: Card %d configured for slave mode\n",hfc_dev_count);
++ hfctmp->regs.mst_mode=hfc_MST_MODE_SLAVE|hfc_MST_MODE_F0_LONG_DURATION;
++ hfctmp->regs.mst_emod=hfc_MST_EMOD_SLOW_CLOCK_ADJ;
++ }else{
++ printk(KERN_INFO "zaphfc: Card %d configured for master mode\n",hfc_dev_count);
++ hfctmp->regs.mst_mode=hfc_MST_MODE_MASTER|hfc_MST_MODE_F0_LONG_DURATION;
++ hfctmp->regs.mst_emod=0;
++ }
++
++ zthfc = vmalloc(sizeof(struct dahdi_hfc));
+ if (!zthfc) {
+- printk(KERN_CRIT "zaphfc: unable to kmalloc!\n");
++ printk(KERN_CRIT "zaphfc: unable to vmalloc!\n");
+ hfc_shutdownCard(hfctmp);
+- kfree(hfctmp);
++ vfree(hfctmp);
+ multi_hfc = NULL;
+ return -ENOMEM;
+ }
+@@ -1050,7 +841,6 @@
+ memset(hfctmp->btransbuf[1], 0x0, sizeof(hfctmp->btransbuf[1]));
+ hfctmp->ztdev->chans[1].writechunk = hfctmp->btransbuf[1];
+
+-
+ hfc_registerCard(hfctmp);
+ hfc_resetCard(hfctmp);
+ tmp = pci_get_device(pcivendor, pcidevice, multi_hfc);
+@@ -1058,58 +848,42 @@
+ return 0;
+ }
+
+-
+-
+ int init_module(void) {
+ int i = 0;
+-#ifdef RTAITIMING
+- RTIME tick_period;
+- for (i=0; i < hfc_MAX_CARDS; i++) {
+- rtai_hfc_list[i] = NULL;
++ if(jitterbuffer<1){
++ printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to minimum of 1\n",jitterbuffer);
++ jitterbuffer=1;
++ }else if(jitterbuffer>500){
++ printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to maximum of 500\n",jitterbuffer);
++ jitterbuffer=500;
+ }
+- rt_set_periodic_mode();
+-#endif
+- i = 0;
++ printk(KERN_INFO "zaphfc: jitterbuffer size: %d\n",jitterbuffer);
+ while (id_list[i].vendor_id) {
+ multi_hfc = NULL;
+ hfc_findCards(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_name, id_list[i].card_name);
+ i++;
+ }
+-#ifdef RTAITIMING
+- for (i=0; i < hfc_MAX_CARDS; i++) {
+- if (rtai_hfc_list[i]) {
+- printk(KERN_INFO
+- "zaphfc: configured %d at mem %#x fifo %#x(%#x) for realtime servicing\n",
+- rtai_hfc_list[i]->cardno,
+- (u_int) rtai_hfc_list[i]->pci_io,
+- (u_int) rtai_hfc_list[i]->fifos,
+- (u_int) virt_to_bus(rtai_hfc_list[i]->fifos));
+-
+- }
+- }
+- rt_task_init(&rt_task, rtai_loop, 1, STACK_SIZE, TASK_PRIORITY, 0, 0);
+- tick_period = start_rt_timer(nano2count(TICK_PERIOD));
+- rt_task_make_periodic(&rt_task, rt_get_time() + tick_period, tick_period);
+-#endif
+ printk(KERN_INFO "zaphfc: %d hfc-pci card(s) in this box.\n", hfc_dev_count);
+ return 0;
+ }
+
+ void cleanup_module(void) {
+ struct hfc_card *tmpcard;
+-#ifdef RTAITIMING
+- stop_rt_timer();
+- rt_task_delete(&rt_task);
+-#endif
++
+ printk(KERN_INFO "zaphfc: stop\n");
+ // spin_lock(&registerlock);
++ tmpcard=hfc_dev_list;
++ while(tmpcard){
++ hfc_shutdownCard1(tmpcard);
++ tmpcard=tmpcard->next;
++ }
+ while (hfc_dev_list != NULL) {
+ if (hfc_dev_list == NULL) break;
+- hfc_shutdownCard(hfc_dev_list);
++ hfc_shutdownCard2(hfc_dev_list);
+ tmpcard = hfc_dev_list;
+ hfc_dev_list = hfc_dev_list->next;
+ if (tmpcard != NULL) {
+- kfree(tmpcard);
++ vfree(tmpcard);
+ tmpcard = NULL;
+ printk(KERN_INFO "zaphfc: freed one card.\n");
+ }
+@@ -1119,8 +893,11 @@
+ #endif
+
+
+-module_param(modes, int, 0600);
++module_param(modes, int, 0400);
+ module_param(debug, int, 0600);
++module_param(sync_slave, int, 0400);
++module_param(timer_card, int, 0400);
++module_param(jitterbuffer, int, 0400);
+
+ MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver");
+ MODULE_AUTHOR("Klaus-Peter Junghanns <kpj@junghanns.net>");
diff --git a/main/dahdi-linux-vserver/APKBUILD b/main/dahdi-linux-vserver/APKBUILD
new file mode 100644
index 0000000000..5fec0b5090
--- /dev/null
+++ b/main/dahdi-linux-vserver/APKBUILD
@@ -0,0 +1,81 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+
+_flavor=${FLAVOR:-vserver}
+
+# source the kernel version
+if [ -f ../linux-${_flavor}/APKBUILD ]; then
+ . ../linux-${_flavor}/APKBUILD
+fi
+
+_kernelver="$pkgver-r$pkgrel"
+_kpkgrel=$pkgrel
+_realname=dahdi-linux
+
+pkgname=${_realname}-${_flavor}
+pkgver=$pkgver
+# when bumping _dahdiver we *must* bump _mypkgrel
+_dahdiver=2.4.1.2
+_mypkgrel=0
+pkgrel=$(( $_kpkgrel + $_mypkgrel ))
+pkgdesc="Digium Asterisk Hardware Device Interface drivers $_dahdiver"
+url="http://www.asterisk.org"
+arch="all"
+license="GPL"
+depends="dahdi-linux linux-${_flavor}=${_kernelver}"
+# we need wget and tar because make install downloads firmware and uses fancy
+# options for tar and wget.
+makedepends="linux-${_flavor}-dev=${_kernelver} wget tar perl"
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.digium.com/pub/telephony/dahdi-linux/releases/${_realname}-$_dahdiver.tar.gz
+ dahdi-depmod.patch
+ dahdi-bri_dchan.patch
+ dahdi-zaphfc.patch
+ zaphfc-dahdi-flortz.diff
+ zaphfc-dahdi-2.4.0.patch
+ "
+
+prepare() {
+ cd "$srcdir/$_realname-$_dahdiver"
+ for i in $source; do
+ case $i in
+ *.patch|*.diff)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir/$_realname-$_dahdiver"
+ make KVERS="${_abi_release}" DYNFS="yes" MODULES_EXTRA="zaphfc" \
+ || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$_dahdiver"
+ make KVERS="${_abi_release}" DYNFS="yes" MODULES_EXTRA="zaphfc" \
+ DESTDIR="$pkgdir" install-modules
+ rm -rf "$pkgdir"/lib/firmware "$pkgdir"/usr/lib/hotplug/firmware \
+ "$pkgdir"/usr/include
+}
+
+# since we sourced the APKBUILD above we got the dev() function there to
+# so we override it again.
+depends_dev="dahdi-linux-dev"
+dev() {
+ default_dev
+ local dir="$subpkgdir"/usr/src/dahdi-headers-${_abi_release}
+ install -D "$srcdir"/$_realname-$_dahdiver/drivers/dahdi/Module.symvers \
+ "$dir"/drivers/dahdi/Module.symvers
+ ln -s /usr/include "$dir"/include
+}
+
+md5sums="81b232a47693f4adac90c569e446f88f dahdi-linux-2.4.1.2.tar.gz
+c78fb8d80f9efdffd950297c88ff9273 dahdi-depmod.patch
+4b41a82ff390ac64c08092c5a3eab6a8 dahdi-bri_dchan.patch
+3be420539f5e2e2b94a1bf3d711ec630 dahdi-zaphfc.patch
+291c5c44c86ab02443a742415461ddca zaphfc-dahdi-flortz.diff
+0fdcd8c8c93bc1fe33c0af12b6cc6b05 zaphfc-dahdi-2.4.0.patch"
diff --git a/main/dahdi-linux-vserver/dahdi-bri_dchan.patch b/main/dahdi-linux-vserver/dahdi-bri_dchan.patch
new file mode 100644
index 0000000000..d7a3fe859b
--- /dev/null
+++ b/main/dahdi-linux-vserver/dahdi-bri_dchan.patch
@@ -0,0 +1,161 @@
+# Translate the D channels to a standard channel data.
+# The HFC chipset provides us the D channel as data, but
+# Zaptel expects it as a standard channel with 1000 samples
+# per second.
+
+--- a/include/dahdi/kernel.h
++++ b/include/dahdi/kernel.h
+@@ -132,6 +132,13 @@ struct dahdi_chan {
+ int do_ppp_error;
+ struct sk_buff_head ppp_rq;
+ #endif
++#ifdef CONFIG_DAHDI_BRI_DCHANS
++ int bytes2receive;
++ int maxbytes2transmit; /* size of the tx buffer in the card driver */
++ int bytes2transmit;
++ int eofrx;
++ int eoftx;
++#endif
+ spinlock_t lock;
+ char name[40];
+ /* Specified by DAHDI */
+@@ -462,6 +469,9 @@ enum {
+ DAHDI_FLAGBIT_LOOPED = 18, /*!< Loopback the receive data from the channel to the transmit */
+ DAHDI_FLAGBIT_MTP2 = 19, /*!< Repeats last message in buffer and also discards repeating messages sent to us */
+ DAHDI_FLAGBIT_HDLC56 = 20, /*!< Sets the given channel (if in HDLC mode) to use 56K HDLC instead of 64K */
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ DAHDI_FLAGBIT_BRIDCHAN = 21, /*!< hardhdlc-like handling of the D channel */
++#endif
+ };
+
+ /* map flagbits to flag masks */
+@@ -500,6 +510,7 @@ enum {
+ #define DAHDI_FLAG_LOOPED DAHDI_FLAG(LOOPED)
+ #define DAHDI_FLAG_MTP2 DAHDI_FLAG(MTP2)
+ #define DAHDI_FLAG_HDLC56 DAHDI_FLAG(HDLC56)
++#define DAHDI_FLAG_BRIDCHAN DAHDI_FLAG(BRIDCHAN)
+
+ struct dahdi_span {
+ spinlock_t lock;
+--- a/include/dahdi/dahdi_config.h
++++ b/include/dahdi/dahdi_config.h
+@@ -174,4 +174,10 @@
+ */
+ /* #define OPTIMIZE_CHANMUTE */
+
++/*
++ * Uncomment the following for BRI D channels
++ *
++ */
++#define CONFIG_DAHDI_BRI_DCHANS
++
+ #endif
+--- a/drivers/dahdi/dahdi-base.c
++++ b/drivers/dahdi/dahdi-base.c
+@@ -5907,11 +5907,40 @@ static inline void __dahdi_getbuf_chunk(
+ *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc);
+ }
+ bytes -= left;
++#ifdef CONFIG_DAHDI_BRI_DCHANS
++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ /*
++ * Let's get this right, we want to transmit complete frames only.
++ * The card driver will do the dirty HDLC work for us.
++ * txb (transmit buffer) is supposed to be big enough to store one frame
++ * we will make this as big as the D fifo (1KB or 2KB)
++ */
++
++ /* there are 'left' bytes in the user buffer left to transmit */
++ left = ms->writen[ms->outwritebuf] - ms->writeidx[ms->outwritebuf] - 2;
++ if (left > ms->maxbytes2transmit) {
++ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], ms->maxbytes2transmit);
++ ms->writeidx[ms->outwritebuf] += ms->maxbytes2transmit;
++ txb += ms->maxbytes2transmit;
++ ms->bytes2transmit = ms->maxbytes2transmit;
++ ms->eoftx = 0;
++ } else {
++ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left);
++ ms->writeidx[ms->outwritebuf] += left + 2;
++ txb += left + 2;
++ ms->bytes2transmit = left;
++ ms->eoftx = 1;
++ }
++ bytes = 0;
++#endif
+ } else {
+ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left);
+ ms->writeidx[ms->outwritebuf]+=left;
+ txb += left;
+ bytes -= left;
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ ms->bytes2transmit=DAHDI_CHUNKSIZE;
++#endif
+ }
+ /* Check buffer status */
+ if (ms->writeidx[ms->outwritebuf] >= ms->writen[ms->outwritebuf]) {
+@@ -5968,6 +5997,17 @@ out in the later versions, and is put ba
+ /* Transmit a flag if this is an HDLC channel */
+ if (ms->flags & DAHDI_FLAG_HDLC)
+ fasthdlc_tx_frame_nocheck(&ms->txhdlc);
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ // if (ms->bytes2transmit > 0) {
++ // txb += 2;
++ // ms->bytes2transmit -= 2;
++ bytes=0;
++ ms->eoftx = 1;
++// printk(KERN_CRIT "zaptel EOF(%d) bytes2transmit %d\n",ms->eoftx,ms->bytes2transmit);
++ // }
++ }
++#endif
+ #ifdef CONFIG_DAHDI_NET
+ if (ms->flags & DAHDI_FLAG_NETDEV)
+ netif_wake_queue(ztchan_to_dev(ms));
+@@ -6028,6 +6068,12 @@ out in the later versions, and is put ba
+ memset(txb, 0xFF, bytes);
+ }
+ bytes = 0;
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ ms->bytes2transmit = 0;
++ ms->eoftx = 0;
++ bytes = 0;
++#endif
+ } else {
+ memset(txb, DAHDI_LIN2X(0, ms), bytes); /* Lastly we use silence on telephony channels */
+ bytes = 0;
+@@ -6840,6 +6886,14 @@ static inline void __putbuf_chunk(struct
+ int res;
+ int left, x;
+
++#if defined(CONFIG_DAHDI_BRI_DCHANS)
++ if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ bytes = ms->bytes2receive;
++ if (bytes < 1) return;
++// printk(KERN_CRIT "bytes2receive %d\n",ms->bytes2receive);
++ }
++#endif
++
+ while(bytes) {
+ #if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP)
+ skb = NULL;
+@@ -6897,6 +6951,19 @@ static inline void __putbuf_chunk(struct
+ }
+ }
+ }
++#ifdef CONFIG_DAHDI_BRI_DCHANS
++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) {
++ memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left);
++ rxb += left;
++ ms->readidx[ms->inreadbuf] += left;
++ bytes -= left;
++ if (ms->eofrx == 1) {
++ eof=1;
++ }
++// printk(KERN_CRIT "receiving %d bytes\n",ms->bytes2receive);
++ ms->bytes2receive = 0;
++ ms->eofrx = 0;
++#endif
+ } else {
+ /* Not HDLC */
+ memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left);
diff --git a/main/dahdi-linux-vserver/dahdi-depmod.patch b/main/dahdi-linux-vserver/dahdi-depmod.patch
new file mode 100644
index 0000000000..289aad403b
--- /dev/null
+++ b/main/dahdi-linux-vserver/dahdi-depmod.patch
@@ -0,0 +1,22 @@
+Index: dahdi-linux-2.0.0-rc4/Makefile
+===================================================================
+--- dahdi-linux-2.0.0-rc4.orig/Makefile 2008-09-09 14:07:23.000000000 +0300
++++ dahdi-linux-2.0.0-rc4/Makefile 2008-09-09 14:12:31.000000000 +0300
+@@ -190,7 +190,7 @@
+ build_tools/uninstall-modules dahdi $(KVERS)
+ endif
+ $(KMAKE) INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=dahdi modules_install
+- [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || :
++ [ -z "$(DESTDIR)" -a `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || :
+
+ uninstall-modules:
+ ifdef DESTDIR
+@@ -203,7 +203,7 @@
+ rm -rf /lib/modules/$(KVERS)/dahdi; \
+ echo "done."; \
+ fi
+- [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || :
++ [ -z "$(DESTDIR)" -a `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || :
+ endif
+
+ update:
diff --git a/main/dahdi-linux-vserver/dahdi-zaphfc.patch b/main/dahdi-linux-vserver/dahdi-zaphfc.patch
new file mode 100644
index 0000000000..735d1c5a3f
--- /dev/null
+++ b/main/dahdi-linux-vserver/dahdi-zaphfc.patch
@@ -0,0 +1,1430 @@
+Index: dahdi-linux-2.1.0/drivers/dahdi/zaphfc.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ dahdi-linux-2.1.0/drivers/dahdi/zaphfc.c 2008-12-10 12:46:14.000000000 +0200
+@@ -0,0 +1,1130 @@
++/*
++ * zaphfc.c - Zaptel driver for HFC-S PCI A based ISDN BRI cards
++ *
++ * kernel module inspired by HFC PCI ISDN4Linux and Zaptel drivers
++ *
++ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
++ * This program is free software and may be modified and
++ * distributed under the terms of the GNU Public License.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#ifdef RTAITIMING
++#include <asm/io.h>
++#include <rtai.h>
++#include <rtai_sched.h>
++#include <rtai_fifos.h>
++#endif
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <dahdi/kernel.h>
++#include "zaphfc.h"
++
++#include <linux/moduleparam.h>
++
++#if CONFIG_PCI
++
++#define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
++#define CLKDEL_NT 0x6c /* CLKDEL in NT mode */
++
++typedef struct {
++ int vendor_id;
++ int device_id;
++ char *vendor_name;
++ char *card_name;
++} PCI_ENTRY;
++
++static const PCI_ENTRY id_list[] =
++{
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, "CCD/Billion/Asuscom", "2BD0"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, "Billion", "B000"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, "Billion", "B006"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, "Billion", "B007"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, "Billion", "B008"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, "Billion", "B009"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, "Billion", "B00A"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"},
++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"},
++ {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, "Abocom/Magitek", "2BD1"},
++ {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"},
++ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"},
++ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, "German telekom", "A1T"},
++ {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, "Motorola MC145575", "MC145575"},
++ {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, "Zoltrix", "2BD0"},
++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"},
++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
++ {0x182d, 0x3069,"Sitecom","Isdn 128 PCI"},
++ {0, 0, NULL, NULL},
++};
++
++static struct hfc_card *hfc_dev_list = NULL;
++static int hfc_dev_count = 0;
++static int modes = 0; // all TE
++static int debug = 0;
++static struct pci_dev *multi_hfc = NULL;
++static spinlock_t registerlock = SPIN_LOCK_UNLOCKED;
++
++void hfc_shutdownCard(struct hfc_card *hfctmp) {
++ unsigned long flags;
++
++ if (hfctmp == NULL) {
++ return;
++ }
++
++ if (hfctmp->pci_io == NULL) {
++ return;
++ }
++
++ spin_lock_irqsave(&hfctmp->lock,flags);
++
++ printk(KERN_INFO "zaphfc: shutting down card at %p.\n",hfctmp->pci_io);
++
++ /* Clear interrupt mask */
++ hfctmp->regs.int_m2 = 0;
++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
++
++ /* Reset pending interrupts */
++ hfc_inb(hfctmp, hfc_INT_S1);
++
++ /* Wait for interrupts that might still be pending */
++ spin_unlock_irqrestore(&hfctmp->lock, flags);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((30 * HZ) / 1000); // wait 30 ms
++ spin_lock_irqsave(&hfctmp->lock,flags);
++
++ /* Remove interrupt handler */
++ if (hfctmp->irq) {
++ free_irq(hfctmp->irq, hfctmp);
++ }
++
++ /* Soft-reset the card */
++ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on
++
++ spin_unlock_irqrestore(&hfctmp->lock, flags);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((30 * HZ) / 1000); // wait 30 ms
++ spin_lock_irqsave(&hfctmp->lock,flags);
++
++ hfc_outb(hfctmp,hfc_CIRM,0); // softreset off
++
++ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, 0); // disable memio and bustmaster
++
++ if (hfctmp->fifomem != NULL) {
++ kfree(hfctmp->fifomem);
++ }
++ iounmap((void *) hfctmp->pci_io);
++ hfctmp->pci_io = NULL;
++ if (hfctmp->pcidev != NULL) {
++ pci_disable_device(hfctmp->pcidev);
++ }
++ spin_unlock_irqrestore(&hfctmp->lock,flags);
++ if (hfctmp->ztdev != NULL) {
++ dahdi_unregister(&hfctmp->ztdev->span);
++ kfree(hfctmp->ztdev);
++ printk(KERN_INFO "unregistered from DAHDI.\n");
++ }
++}
++
++void hfc_resetCard(struct hfc_card *hfctmp) {
++ unsigned long flags;
++
++ spin_lock_irqsave(&hfctmp->lock,flags);
++ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio
++ hfctmp->regs.int_m2 = 0;
++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
++
++// printk(KERN_INFO "zaphfc: resetting card.\n");
++ pci_set_master(hfctmp->pcidev);
++ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on
++ spin_unlock_irqrestore(&hfctmp->lock, flags);
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((30 * HZ) / 1000); // wait 30 ms
++ hfc_outb(hfctmp, hfc_CIRM, 0); // softreset off
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout((20 * HZ) / 1000); // wait 20 ms
++ if (hfc_inb(hfctmp,hfc_STATUS) & hfc_STATUS_PCI_PROC) {
++ printk(KERN_WARNING "zaphfc: hfc busy.\n");
++ }
++
++// hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
++// hfctmp->regs.fifo_en = hfc_FIFOEN_D; /* only D fifos enabled */
++ hfctmp->regs.fifo_en = 0; /* no fifos enabled */
++ hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
++
++ hfctmp->regs.trm = 2;
++ hfc_outb(hfctmp, hfc_TRM, hfctmp->regs.trm);
++
++ if (hfctmp->regs.nt_mode == 1) {
++ hfc_outb(hfctmp, hfc_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */
++ } else {
++ hfc_outb(hfctmp, hfc_CLKDEL, CLKDEL_TE); /* ST-Bit delay for TE-Mode */
++ }
++ hfctmp->regs.sctrl_e = hfc_SCTRL_E_AUTO_AWAKE;
++ hfc_outb(hfctmp, hfc_SCTRL_E, hfctmp->regs.sctrl_e); /* S/T Auto awake */
++ hfctmp->regs.bswapped = 0; /* no exchange */
++
++ hfctmp->regs.ctmt = hfc_CTMT_TRANSB1 | hfc_CTMT_TRANSB2; // all bchans are transparent , no freaking hdlc
++ hfc_outb(hfctmp, hfc_CTMT, hfctmp->regs.ctmt);
++
++ hfctmp->regs.int_m1 = 0;
++ hfc_outb(hfctmp, hfc_INT_M1, hfctmp->regs.int_m1);
++
++#ifdef RTAITIMING
++ hfctmp->regs.int_m2 = 0;
++#else
++ hfctmp->regs.int_m2 = hfc_M2_PROC_TRANS;
++#endif
++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
++
++ /* Clear already pending ints */
++ hfc_inb(hfctmp, hfc_INT_S1);
++
++ if (hfctmp->regs.nt_mode == 1) {
++ hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_NT; /* set tx_lo mode, error in datasheet ! */
++ } else {
++ hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_TE; /* set tx_lo mode, error in datasheet ! */
++ }
++
++ hfctmp->regs.mst_mode = hfc_MST_MODE_MASTER; /* HFC Master Mode */
++ hfc_outb(hfctmp, hfc_MST_MODE, hfctmp->regs.mst_mode);
++
++ hfc_outb(hfctmp, hfc_SCTRL, hfctmp->regs.sctrl);
++ hfctmp->regs.sctrl_r = 3;
++ hfc_outb(hfctmp, hfc_SCTRL_R, hfctmp->regs.sctrl_r);
++
++ hfctmp->regs.connect = 0;
++ hfc_outb(hfctmp, hfc_CONNECT, hfctmp->regs.connect);
++
++ hfc_outb(hfctmp, hfc_CIRM, 0x80 | 0x40); // bit order
++
++ /* Finally enable IRQ output */
++#ifndef RTAITIMING
++ hfctmp->regs.int_m2 |= hfc_M2_IRQ_ENABLE;
++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
++#endif
++
++ /* clear pending ints */
++ hfc_inb(hfctmp, hfc_INT_S1);
++ hfc_inb(hfctmp, hfc_INT_S2);
++}
++
++void hfc_registerCard(struct hfc_card *hfccard) {
++ spin_lock(&registerlock);
++ if (hfccard != NULL) {
++ hfccard->cardno = hfc_dev_count++;
++ hfccard->next = hfc_dev_list;
++ hfc_dev_list = hfccard;
++ }
++ spin_unlock(&registerlock);
++}
++
++static void hfc_btrans(struct hfc_card *hfctmp, char whichB) {
++ // we are called with irqs disabled from the irq handler
++ int count, maxlen, total;
++ unsigned char *f1, *f2;
++ unsigned short *z1, *z2, newz1;
++ int freebytes;
++
++ if (whichB == 1) {
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z2 + (*f1 * 4));
++ } else {
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z2 + (*f1 * 4));
++ }
++
++ freebytes = *z2 - *z1;
++ if (freebytes <= 0) {
++ freebytes += hfc_B_FIFO_SIZE;
++ }
++ count = DAHDI_CHUNKSIZE;
++
++ total = count;
++ if (freebytes < count) {
++ hfctmp->clicks++;
++ /* only spit out this warning once per second to not make things worse! */
++ if (hfctmp->clicks > 100) {
++ printk(KERN_CRIT "zaphfc: bchan tx fifo full, dropping audio! (z1=%d, z2=%d)\n",*z1,*z2);
++ hfctmp->clicks = 0;
++ }
++ return;
++ }
++
++ maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z1;
++ if (maxlen > count) {
++ maxlen = count;
++ }
++ newz1 = *z1 + total;
++ if (newz1 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { newz1 -= hfc_B_FIFO_SIZE; }
++
++ if (whichB == 1) {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + *z1),hfctmp->ztdev->chans[0].writechunk, maxlen);
++ } else {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + *z1),hfctmp->ztdev->chans[1].writechunk, maxlen);
++ }
++
++ count -= maxlen;
++ if (count > 0) {
++ // Buffer wrap
++ if (whichB == 1) {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[0].writechunk+maxlen, count);
++ } else {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[1].writechunk+maxlen, count);
++ }
++ }
++
++ *z1 = newz1; /* send it now */
++
++// if (count > 0) printk(KERN_CRIT "zaphfc: bchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
++ return;
++}
++
++static void hfc_brec(struct hfc_card *hfctmp, char whichB) {
++ // we are called with irqs disabled from the irq handler
++ int count, maxlen, drop;
++ volatile unsigned char *f1, *f2;
++ volatile unsigned short *z1, *z2, newz2;
++ int bytes = 0;
++
++ if (whichB == 1) {
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
++ } else {
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
++ }
++
++ bytes = *z1 - *z2;
++ if (bytes < 0) {
++ bytes += hfc_B_FIFO_SIZE;
++ }
++ count = DAHDI_CHUNKSIZE;
++
++ if (bytes < DAHDI_CHUNKSIZE) {
++#ifndef RTAITIMING
++ printk(KERN_CRIT "zaphfc: bchan rx fifo not enough bytes to receive! (z1=%d, z2=%d, wanted %d got %d), probably a buffer overrun.\n",*z1,*z2,DAHDI_CHUNKSIZE,bytes);
++#endif
++ return;
++ }
++
++ /* allowing the buffering of hfc_BCHAN_BUFFER bytes of audio data works around irq jitter */
++ if (bytes > hfc_BCHAN_BUFFER + DAHDI_CHUNKSIZE) {
++ /* if the system is too slow to handle it, we will have to drop it all (except 1 DAHDI chunk) */
++ drop = bytes - DAHDI_CHUNKSIZE;
++ hfctmp->clicks++;
++ /* only spit out this warning once per second to not make things worse! */
++ if (hfctmp->clicks > 100) {
++ printk(KERN_CRIT "zaphfc: dropped audio (z1=%d, z2=%d, wanted %d got %d, dropped %d).\n",*z1,*z2,count,bytes,drop);
++ hfctmp->clicks = 0;
++ }
++ /* hm, we are processing the b chan data tooooo slowly... let's drop the lost audio */
++ newz2 = *z2 + drop;
++ if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
++ newz2 -= hfc_B_FIFO_SIZE;
++ }
++ *z2 = newz2;
++ }
++
++
++ maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z2;
++ if (maxlen > count) {
++ maxlen = count;
++ }
++ if (whichB == 1) {
++ memcpy(hfctmp->ztdev->chans[0].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + *z2), maxlen);
++ } else {
++ memcpy(hfctmp->ztdev->chans[1].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + *z2), maxlen);
++ }
++ newz2 = *z2 + count;
++ if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
++ newz2 -= hfc_B_FIFO_SIZE;
++ }
++ *z2 = newz2;
++
++ count -= maxlen;
++ if (count > 0) {
++ // Buffer wrap
++ if (whichB == 1) {
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
++ memcpy(hfctmp->ztdev->chans[0].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + hfc_B_SUB_VAL), count);
++ } else {
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
++ memcpy(hfctmp->ztdev->chans[1].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + hfc_B_SUB_VAL), count);
++ }
++ newz2 = *z2 + count;
++ if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
++ newz2 -= hfc_B_FIFO_SIZE;
++ }
++ }
++
++
++ if (whichB == 1) {
++ dahdi_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk);
++ } else {
++ dahdi_ec_chunk(&hfctmp->ztdev->chans[1], hfctmp->ztdev->chans[1].readchunk, hfctmp->ztdev->chans[1].writechunk);
++ }
++ return;
++}
++
++
++static void hfc_dtrans(struct hfc_card *hfctmp) {
++ // we are called with irqs disabled from the irq handler
++ int x;
++ int count, maxlen, total;
++ unsigned char *f1, *f2, newf1;
++ unsigned short *z1, *z2, newz1;
++ int frames, freebytes;
++
++ if (hfctmp->ztdev->chans[2].bytes2transmit == 0) {
++ return;
++ }
++
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F2);
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z2 + (*f1 * 4));
++
++ frames = (*f1 - *f2) & hfc_FMASK;
++ if (frames < 0) {
++ frames += hfc_MAX_DFRAMES + 1;
++ }
++
++ if (frames >= hfc_MAX_DFRAMES) {
++ printk(KERN_CRIT "zaphfc: dchan tx fifo total number of frames exceeded!\n");
++ return;
++ }
++
++ freebytes = *z2 - *z1;
++ if (freebytes <= 0) {
++ freebytes += hfc_D_FIFO_SIZE;
++ }
++ count = hfctmp->ztdev->chans[2].bytes2transmit;
++
++ total = count;
++ if (freebytes < count) {
++ printk(KERN_CRIT "zaphfc: dchan tx fifo not enough free bytes! (z1=%d, z2=%d)\n",*z1,*z2);
++ return;
++ }
++
++ newz1 = (*z1 + count) & hfc_ZMASK;
++ newf1 = ((*f1 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); // next frame
++
++ if (count > 0) {
++ if (debug) {
++ printk(KERN_CRIT "zaphfc: card %d TX [ ", hfctmp->cardno);
++ for (x=0; x<count; x++) {
++ printk("%#2x ",hfctmp->dtransbuf[x]);
++ }
++ if (hfctmp->ztdev->chans[2].eoftx == 1) {
++ printk("] %d bytes\n", count);
++ } else {
++ printk("..] %d bytes\n", count);
++ }
++ }
++ maxlen = hfc_D_FIFO_SIZE - *z1;
++ if (maxlen > count) {
++ maxlen = count;
++ }
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF + *z1),hfctmp->ztdev->chans[2].writechunk, maxlen);
++ count -= maxlen;
++ if (count > 0) {
++ memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF),(char *)(hfctmp->ztdev->chans[2].writechunk + maxlen), count);
++ }
++ }
++
++ *z1 = newz1;
++
++ if (hfctmp->ztdev->chans[2].eoftx == 1) {
++ *f1 = newf1;
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
++ *z1 = newz1;
++ hfctmp->ztdev->chans[2].eoftx = 0;
++ }
++// printk(KERN_CRIT "zaphfc: dchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
++ return;
++}
++
++/* receive a complete hdlc frame, skip broken or short frames */
++static void hfc_drec(struct hfc_card *hfctmp) {
++ int count=0, maxlen=0, framelen=0;
++ unsigned char *f1, *f2, *crcstat;
++ unsigned short *z1, *z2, oldz2, newz2;
++
++ hfctmp->ztdev->chans[2].bytes2receive=0;
++ hfctmp->ztdev->chans[2].eofrx = 0;
++
++ /* put the received data into the DAHDI buffer
++ we'll call dahdi_receive() later when the timer fires. */
++ f1 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F1);
++ f2 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F2);
++
++ if (*f1 == *f2) return; /* nothing received, strange eh? */
++
++ z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z1 + (*f2 * 4));
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
++
++ /* calculate length of frame, including 2 bytes CRC and 1 byte STAT */
++ count = *z1 - *z2;
++
++ if (count < 0) {
++ count += hfc_D_FIFO_SIZE; /* ring buffer wrapped */
++ }
++ count++;
++ framelen = count;
++
++ crcstat = (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z1);
++
++ if ((framelen < 4) || (*crcstat != 0x0)) {
++ /* the frame is too short for a valid HDLC frame or the CRC is borked */
++ printk(KERN_CRIT "zaphfc: empty HDLC frame or bad CRC received (framelen = %d, stat = %#x, card = %d).\n", framelen, *crcstat, hfctmp->cardno);
++ oldz2 = *z2;
++ *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */
++ // recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!!
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
++ *z2 = (oldz2 + framelen) & hfc_ZMASK;
++ hfctmp->drecinframe = 0;
++ hfctmp->regs.int_drec--;
++ /* skip short or broken frames */
++ hfctmp->ztdev->chans[2].bytes2receive = 0;
++ return;
++ }
++
++ count -= 1; /* strip STAT */
++ hfctmp->ztdev->chans[2].eofrx = 1;
++
++ if (count + *z2 <= hfc_D_FIFO_SIZE) {
++ maxlen = count;
++ } else {
++ maxlen = hfc_D_FIFO_SIZE - *z2;
++ }
++
++ /* copy first part */
++ memcpy(hfctmp->drecbuf, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z2), maxlen);
++ hfctmp->ztdev->chans[2].bytes2receive += maxlen;
++
++ count -= maxlen;
++ if (count > 0) {
++ /* ring buffer wrapped, copy rest from start of d fifo */
++ memcpy(hfctmp->drecbuf + maxlen, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF), count);
++ hfctmp->ztdev->chans[2].bytes2receive += count;
++ }
++
++ /* frame read */
++ oldz2 = *z2;
++ newz2 = (oldz2 + framelen) & hfc_ZMASK;
++ *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */
++ /* recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! */
++ z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
++ *z2 = newz2;
++ hfctmp->drecinframe = 0;
++ hfctmp->regs.int_drec--;
++}
++
++#ifndef RTAITIMING
++DAHDI_IRQ_HANDLER(hfc_interrupt) {
++ struct hfc_card *hfctmp = dev_id;
++ unsigned long flags = 0;
++ unsigned char stat;
++#else
++static void hfc_service(struct hfc_card *hfctmp) {
++#endif
++ struct dahdi_hfc *zthfc;
++ unsigned char s1, s2, l1state;
++ int x;
++
++ if (!hfctmp) {
++#ifndef RTAITIMING
++ return IRQ_NONE;
++#else
++ /* rtai */
++ return;
++#endif
++ }
++
++ if (!hfctmp->pci_io) {
++ printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n",
++ __FUNCTION__);
++#ifndef RTAITIMING
++ return IRQ_NONE;
++#else
++ /* rtai */
++ return;
++#endif
++ }
++
++ /* we assume a few things in this irq handler:
++ - the hfc-pci will only generate "timer" irqs (proc/non-proc)
++ - we need to use every 8th IRQ (to generate 1khz timing)
++ OR
++ - if we use rtai for timing the hfc-pci will not generate ANY irq,
++ instead rtai will call this "fake" irq with a 1khz realtime timer. :)
++ - rtai will directly service the card, not like it used to by triggering
++ the linux irq
++ */
++
++#ifndef RTAITIMING
++ spin_lock_irqsave(&hfctmp->lock, flags);
++ stat = hfc_inb(hfctmp, hfc_STATUS);
++
++ if ((stat & hfc_STATUS_ANYINT) == 0) {
++ // maybe we are sharing the irq
++ spin_unlock_irqrestore(&hfctmp->lock,flags);
++ return IRQ_NONE;
++ }
++#endif
++
++ s1 = hfc_inb(hfctmp, hfc_INT_S1);
++ s2 = hfc_inb(hfctmp, hfc_INT_S2);
++ if (s1 != 0) {
++ if (s1 & hfc_INTS_TIMER) {
++ // timer (bit 7)
++ // printk(KERN_CRIT "timer %d %d %d.\n", stat, s1, s2);
++ }
++ if (s1 & hfc_INTS_L1STATE) {
++ // state machine (bit 6)
++ // printk(KERN_CRIT "zaphfc: layer 1 state machine interrupt\n");
++ zthfc = hfctmp->ztdev;
++ l1state = hfc_inb(hfctmp,hfc_STATES) & hfc_STATES_STATE_MASK;
++ if (hfctmp->regs.nt_mode == 1) {
++ if (debug) {
++ printk(KERN_CRIT "zaphfc: card %d layer 1 state = G%d\n", hfctmp->cardno, l1state);
++ }
++ switch (l1state) {
++ case 3:
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d)", hfctmp->cardno, l1state);
++#endif
++ break;
++ default:
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d)", hfctmp->cardno, l1state);
++#endif
++ }
++ if (l1state == 2) {
++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_ACTIVATE | hfc_STATES_DO_ACTION | hfc_STATES_NT_G2_G3);
++ } else if (l1state == 3) {
++ // fix to G3 state (see specs)
++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_LOAD_STATE | 3);
++ }
++ } else {
++ if (debug) {
++ printk(KERN_CRIT "zaphfc: card %d layer 1 state = F%d\n", hfctmp->cardno, l1state);
++ }
++ switch (l1state) {
++ case 7:
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d)", hfctmp->cardno, l1state);
++#endif
++ break;
++ default:
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d)", hfctmp->cardno, l1state);
++#endif
++ }
++ if (l1state == 3) {
++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
++ }
++ }
++
++ }
++ if (s1 & hfc_INTS_DREC) {
++ // D chan RX (bit 5)
++ hfctmp->regs.int_drec++;
++ // mr. zapata there is something for you!
++ // printk(KERN_CRIT "d chan rx\n");
++ }
++ if (s1 & hfc_INTS_B2REC) {
++ // B2 chan RX (bit 4)
++ }
++ if (s1 & hfc_INTS_B1REC) {
++ // B1 chan RX (bit 3)
++ }
++ if (s1 & hfc_INTS_DTRANS) {
++ // D chan TX (bit 2)
++// printk(KERN_CRIT "zaphfc: dchan frame transmitted.\n");
++ }
++ if (s1 & hfc_INTS_B2TRANS) {
++ // B2 chan TX (bit 1)
++ }
++ if (s1 & hfc_INTS_B1TRANS) {
++ // B1 chan TX (bit 0)
++ }
++ }
++#ifdef RTAITIMING
++ /* fake an irq */
++ s2 |= hfc_M2_PROC_TRANS;
++#endif
++ if (s2 != 0) {
++ if (s2 & hfc_M2_PMESEL) {
++ // kaboom irq (bit 7)
++ printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n");
++ }
++ if (s2 & hfc_M2_GCI_MON_REC) {
++ // RxR monitor channel (bit 2)
++ }
++ if (s2 & hfc_M2_GCI_I_CHG) {
++ // GCI I-change (bit 1)
++ }
++ if (s2 & hfc_M2_PROC_TRANS) {
++ // processing/non-processing transition (bit 0)
++ hfctmp->ticks++;
++#ifndef RTAITIMING
++ if (hfctmp->ticks > 7) {
++ // welcome to DAHDI timing :)
++#endif
++ hfctmp->ticks = 0;
++
++ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
++ // clear dchan buffer
++ hfctmp->ztdev->chans[2].bytes2transmit = 0;
++ hfctmp->ztdev->chans[2].maxbytes2transmit = hfc_D_FIFO_SIZE;
++
++ dahdi_transmit(&(hfctmp->ztdev->span));
++
++ hfc_btrans(hfctmp,1);
++ hfc_btrans(hfctmp,2);
++ hfc_dtrans(hfctmp);
++ }
++
++ hfc_brec(hfctmp,1);
++ hfc_brec(hfctmp,2);
++ if (hfctmp->regs.int_drec > 0) {
++ // dchan data to read
++ hfc_drec(hfctmp);
++ if (hfctmp->ztdev->chans[2].bytes2receive > 0) {
++ if (debug) {
++ printk(KERN_CRIT "zaphfc: card %d RX [ ", hfctmp->cardno);
++ if (hfctmp->ztdev->chans[2].eofrx) {
++ /* dont output CRC == less user confusion */
++ for (x=0; x < hfctmp->ztdev->chans[2].bytes2receive - 2; x++) {
++ printk("%#2x ", hfctmp->drecbuf[x]);
++ }
++ printk("] %d bytes\n", hfctmp->ztdev->chans[2].bytes2receive - 2);
++ } else {
++ for (x=0; x < hfctmp->ztdev->chans[2].bytes2receive; x++) {
++ printk("%#2x ", hfctmp->drecbuf[x]);
++ }
++ printk("..] %d bytes\n", hfctmp->ztdev->chans[2].bytes2receive);
++ }
++ }
++ }
++ } else {
++ // hmm....ok, let DAHDI receive nothing
++ hfctmp->ztdev->chans[2].bytes2receive = 0;
++ }
++ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
++ dahdi_receive(&(hfctmp->ztdev->span));
++ }
++
++#ifndef RTAITIMING
++ }
++#endif
++ }
++
++ }
++#ifndef RTAITIMING
++ spin_unlock_irqrestore(&hfctmp->lock,flags);
++ return IRQ_RETVAL(1);
++#endif
++}
++
++
++static int zthfc_open(struct dahdi_chan *chan) {
++ struct dahdi_hfc *zthfc = chan->pvt;
++ struct hfc_card *hfctmp = zthfc->card;
++
++ if (!hfctmp) {
++ return 0;
++ }
++ try_module_get(THIS_MODULE);
++ return 0;
++}
++
++static int zthfc_close(struct dahdi_chan *chan) {
++ struct dahdi_hfc *zthfc = chan->pvt;
++ struct hfc_card *hfctmp = zthfc->card;
++
++ if (!hfctmp) {
++ return 0;
++ }
++
++ module_put(THIS_MODULE);
++ return 0;
++}
++
++static int zthfc_rbsbits(struct dahdi_chan *chan, int bits) {
++ return 0;
++}
++
++static int zthfc_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) {
++ switch(cmd) {
++ default:
++ return -ENOTTY;
++ }
++ return 0;
++}
++
++static int zthfc_startup(struct dahdi_span *span) {
++ struct dahdi_hfc *zthfc = span->pvt;
++ struct hfc_card *hfctmp = zthfc->card;
++ int alreadyrunning;
++
++ if (hfctmp == NULL) {
++ printk(KERN_INFO "zaphfc: no card for span at startup!\n");
++ }
++ alreadyrunning = span->flags & DAHDI_FLAG_RUNNING;
++
++ if (!alreadyrunning) {
++ span->chans[2]->flags &= ~DAHDI_FLAG_HDLC;
++ span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN;
++
++ span->flags |= DAHDI_FLAG_RUNNING;
++
++ hfctmp->ticks = -2;
++ hfctmp->clicks = 0;
++ hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
++ hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
++ } else {
++ return 0;
++ }
++
++ // drivers, start engines!
++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
++ return 0;
++}
++
++static int zthfc_shutdown(struct dahdi_span *span) {
++ return 0;
++}
++
++static int zthfc_maint(struct dahdi_span *span, int cmd) {
++ return 0;
++}
++
++static int zthfc_chanconfig(struct dahdi_chan *chan, int sigtype) {
++// printk(KERN_CRIT "chan_config sigtype=%d\n", sigtype);
++ return 0;
++}
++
++static int zthfc_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) {
++ span->lineconfig = lc->lineconfig;
++ return 0;
++}
++
++static int zthfc_initialize(struct dahdi_hfc *zthfc) {
++ struct hfc_card *hfctmp = zthfc->card;
++ int i;
++
++ memset(&zthfc->span, 0x0, sizeof(struct dahdi_span)); // you never can tell...
++
++ sprintf(zthfc->span.name, "ZTHFC%d", hfc_dev_count + 1);
++ if (hfctmp->regs.nt_mode == 1) {
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] [realtime]", hfc_dev_count + 1);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1);
++#endif
++ } else {
++#ifdef RTAITIMING
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] [realtime]", hfc_dev_count + 1);
++#else
++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1);
++#endif
++ }
++
++ zthfc->span.spanconfig = zthfc_spanconfig;
++ zthfc->span.chanconfig = zthfc_chanconfig;
++ zthfc->span.startup = zthfc_startup;
++ zthfc->span.shutdown = zthfc_shutdown;
++ zthfc->span.maint = zthfc_maint;
++ zthfc->span.rbsbits = zthfc_rbsbits;
++ zthfc->span.open = zthfc_open;
++ zthfc->span.close = zthfc_close;
++ zthfc->span.ioctl = zthfc_ioctl;
++
++ zthfc->span.channels = 3;
++ zthfc->span.chans = zthfc->_chans;
++ for (i = 0; i < zthfc->span.channels; i++)
++ zthfc->_chans[i] = &zthfc->chans[i];
++
++ zthfc->span.deflaw = DAHDI_LAW_ALAW;
++ zthfc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS; // <--- this is really BS
++ zthfc->span.offset = 0;
++ init_waitqueue_head(&zthfc->span.maintq);
++ zthfc->span.pvt = zthfc;
++
++ for (i = 0; i < zthfc->span.channels; i++) {
++ memset(&(zthfc->chans[i]), 0x0, sizeof(struct dahdi_chan));
++ sprintf(zthfc->chans[i].name, "ZTHFC%d/%d/%d", hfc_dev_count + 1,0,i + 1);
++ zthfc->chans[i].pvt = zthfc;
++ zthfc->chans[i].sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_SF;
++ zthfc->chans[i].chanpos = i + 1;
++ }
++
++ if (dahdi_register(&zthfc->span,0)) {
++ printk(KERN_CRIT "unable to register DAHDI device!\n");
++ return -1;
++ }
++// printk(KERN_CRIT "zaphfc: registered DAHDI device!\n");
++ return 0;
++}
++
++#ifdef RTAITIMING
++#define TICK_PERIOD 1000000
++#define TICK_PERIOD2 1000000000
++#define TASK_PRIORITY 1
++#define STACK_SIZE 10000
++
++static RT_TASK rt_task;
++static struct hfc_card *rtai_hfc_list[hfc_MAX_CARDS];
++static unsigned char rtai_hfc_counter = 0;
++
++static void rtai_register_hfc(struct hfc_card *hfctmp) {
++ rtai_hfc_list[rtai_hfc_counter++] = hfctmp;
++}
++
++static void rtai_loop(int t) {
++ int i=0;
++ for (;;) {
++ for (i=0; i < rtai_hfc_counter; i++) {
++ if (rtai_hfc_list[i] != NULL)
++ hfc_service(rtai_hfc_list[i]);
++ }
++ rt_task_wait_period();
++ }
++}
++#endif
++
++int hfc_findCards(int pcivendor, int pcidevice, char *vendor_name, char *card_name) {
++ struct pci_dev *tmp;
++ struct hfc_card *hfctmp = NULL;
++ struct dahdi_hfc *zthfc = NULL;
++
++ tmp = pci_get_device(pcivendor, pcidevice, multi_hfc);
++ while (tmp != NULL) {
++ multi_hfc = tmp; // skip this next time.
++
++ if (pci_enable_device(tmp)) {
++ multi_hfc = NULL;
++ return -1;
++ }
++ pci_set_master(tmp);
++
++ hfctmp = kmalloc(sizeof(struct hfc_card), GFP_KERNEL);
++ if (!hfctmp) {
++ printk(KERN_WARNING "zaphfc: unable to kmalloc!\n");
++ pci_disable_device(tmp);
++ multi_hfc = NULL;
++ return -ENOMEM;
++ }
++ memset(hfctmp, 0x0, sizeof(struct hfc_card));
++ spin_lock_init(&hfctmp->lock);
++
++ hfctmp->pcidev = tmp;
++ hfctmp->pcibus = tmp->bus->number;
++ hfctmp->pcidevfn = tmp->devfn;
++
++ if (!tmp->irq) {
++ printk(KERN_WARNING "zaphfc: no irq!\n");
++ } else {
++ hfctmp->irq = tmp->irq;
++ }
++
++ hfctmp->pci_io = (char *) tmp->resource[1].start;
++ if (!hfctmp->pci_io) {
++ printk(KERN_WARNING "zaphfc: no iomem!\n");
++ kfree(hfctmp);
++ pci_disable_device(tmp);
++ multi_hfc = NULL;
++ return -1;
++ }
++
++ hfctmp->fifomem = kmalloc(65536, GFP_KERNEL);
++ if (!hfctmp->fifomem) {
++ printk(KERN_WARNING "zaphfc: unable to kmalloc fifomem!\n");
++ kfree(hfctmp);
++ pci_disable_device(tmp);
++ multi_hfc = NULL;
++ return -ENOMEM;
++ } else {
++ memset(hfctmp->fifomem, 0x0, 65536);
++ hfctmp->fifos = (void *)(((ulong) hfctmp->fifomem) & ~0x7FFF) + 0x8000;
++ pci_write_config_dword(hfctmp->pcidev, 0x80, (u_int) virt_to_bus(hfctmp->fifos));
++ hfctmp->pci_io = ioremap((ulong) hfctmp->pci_io, 256);
++ }
++
++#ifdef RTAITIMING
++ /* we need no stinking irq */
++ hfctmp->irq = 0;
++#else
++ if (request_irq(hfctmp->irq, &hfc_interrupt, DAHDI_IRQ_SHARED, "zaphfc", hfctmp)) {
++ printk(KERN_WARNING "zaphfc: unable to register irq\n");
++ kfree(hfctmp->fifomem);
++ kfree(hfctmp);
++ iounmap((void *) hfctmp->pci_io);
++ pci_disable_device(tmp);
++ multi_hfc = NULL;
++ return -EIO;
++ }
++#endif
++
++#ifdef RTAITIMING
++ rtai_register_hfc(hfctmp);
++#endif
++ printk(KERN_INFO
++ "zaphfc: %s %s configured at mem %lx fifo %lx(%#x) IRQ %d HZ %d\n",
++ vendor_name, card_name,
++ (unsigned long) hfctmp->pci_io,
++ (unsigned long) hfctmp->fifos,
++ (u_int) virt_to_bus(hfctmp->fifos),
++ hfctmp->irq, HZ);
++ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio
++ hfctmp->regs.int_m1 = 0; // no ints
++ hfctmp->regs.int_m2 = 0; // not at all
++ hfc_outb(hfctmp,hfc_INT_M1,hfctmp->regs.int_m1);
++ hfc_outb(hfctmp,hfc_INT_M2,hfctmp->regs.int_m2);
++
++ if ((modes & (1 << hfc_dev_count)) != 0) {
++ printk(KERN_INFO "zaphfc: Card %d configured for NT mode\n",hfc_dev_count);
++ hfctmp->regs.nt_mode = 1;
++ } else {
++ printk(KERN_INFO "zaphfc: Card %d configured for TE mode\n",hfc_dev_count);
++ hfctmp->regs.nt_mode = 0;
++ }
++
++ zthfc = kmalloc(sizeof(struct dahdi_hfc),GFP_KERNEL);
++ if (!zthfc) {
++ printk(KERN_CRIT "zaphfc: unable to kmalloc!\n");
++ hfc_shutdownCard(hfctmp);
++ kfree(hfctmp);
++ multi_hfc = NULL;
++ return -ENOMEM;
++ }
++ memset(zthfc, 0x0, sizeof(struct dahdi_hfc));
++
++ zthfc->card = hfctmp;
++ zthfc_initialize(zthfc);
++ hfctmp->ztdev = zthfc;
++
++ memset(hfctmp->drecbuf, 0x0, sizeof(hfctmp->drecbuf));
++ hfctmp->ztdev->chans[2].readchunk = hfctmp->drecbuf;
++
++ memset(hfctmp->dtransbuf, 0x0, sizeof(hfctmp->dtransbuf));
++ hfctmp->ztdev->chans[2].writechunk = hfctmp->dtransbuf;
++
++ memset(hfctmp->brecbuf[0], 0x0, sizeof(hfctmp->brecbuf[0]));
++ hfctmp->ztdev->chans[0].readchunk = hfctmp->brecbuf[0];
++ memset(hfctmp->btransbuf[0], 0x0, sizeof(hfctmp->btransbuf[0]));
++ hfctmp->ztdev->chans[0].writechunk = hfctmp->btransbuf[0];
++
++ memset(hfctmp->brecbuf[1], 0x0, sizeof(hfctmp->brecbuf[1]));
++ hfctmp->ztdev->chans[1].readchunk = hfctmp->brecbuf[1];
++ memset(hfctmp->btransbuf[1], 0x0, sizeof(hfctmp->btransbuf[1]));
++ hfctmp->ztdev->chans[1].writechunk = hfctmp->btransbuf[1];
++
++
++ hfc_registerCard(hfctmp);
++ hfc_resetCard(hfctmp);
++ tmp = pci_get_device(pcivendor, pcidevice, multi_hfc);
++ }
++ return 0;
++}
++
++
++
++int init_module(void) {
++ int i = 0;
++#ifdef RTAITIMING
++ RTIME tick_period;
++ for (i=0; i < hfc_MAX_CARDS; i++) {
++ rtai_hfc_list[i] = NULL;
++ }
++ rt_set_periodic_mode();
++#endif
++ i = 0;
++ while (id_list[i].vendor_id) {
++ multi_hfc = NULL;
++ hfc_findCards(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_name, id_list[i].card_name);
++ i++;
++ }
++#ifdef RTAITIMING
++ for (i=0; i < hfc_MAX_CARDS; i++) {
++ if (rtai_hfc_list[i]) {
++ printk(KERN_INFO
++ "zaphfc: configured %d at mem %#x fifo %#x(%#x) for realtime servicing\n",
++ rtai_hfc_list[i]->cardno,
++ (u_int) rtai_hfc_list[i]->pci_io,
++ (u_int) rtai_hfc_list[i]->fifos,
++ (u_int) virt_to_bus(rtai_hfc_list[i]->fifos));
++
++ }
++ }
++ rt_task_init(&rt_task, rtai_loop, 1, STACK_SIZE, TASK_PRIORITY, 0, 0);
++ tick_period = start_rt_timer(nano2count(TICK_PERIOD));
++ rt_task_make_periodic(&rt_task, rt_get_time() + tick_period, tick_period);
++#endif
++ printk(KERN_INFO "zaphfc: %d hfc-pci card(s) in this box.\n", hfc_dev_count);
++ return 0;
++}
++
++void cleanup_module(void) {
++ struct hfc_card *tmpcard;
++#ifdef RTAITIMING
++ stop_rt_timer();
++ rt_task_delete(&rt_task);
++#endif
++ printk(KERN_INFO "zaphfc: stop\n");
++// spin_lock(&registerlock);
++ while (hfc_dev_list != NULL) {
++ if (hfc_dev_list == NULL) break;
++ hfc_shutdownCard(hfc_dev_list);
++ tmpcard = hfc_dev_list;
++ hfc_dev_list = hfc_dev_list->next;
++ if (tmpcard != NULL) {
++ kfree(tmpcard);
++ tmpcard = NULL;
++ printk(KERN_INFO "zaphfc: freed one card.\n");
++ }
++ }
++// spin_unlock(&registerlock);
++}
++#endif
++
++
++module_param(modes, int, 0600);
++module_param(debug, int, 0600);
++
++MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver");
++MODULE_AUTHOR("Klaus-Peter Junghanns <kpj@junghanns.net>");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
+Index: dahdi-linux-2.1.0/drivers/dahdi/zaphfc.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ dahdi-linux-2.1.0/drivers/dahdi/zaphfc.h 2008-12-10 12:46:14.000000000 +0200
+@@ -0,0 +1,290 @@
++/*
++ * zaphfc.h - Zaptel driver for HFC-S PCI A based ISDN BRI cards
++ *
++ * kernel module based on HFC PCI ISDN4Linux and Zaptel drivers
++ *
++ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
++ *
++ * Klaus-Peter Junghanns <kpj@junghanns.net>
++ *
++ * This program is free software and may be modified and
++ * distributed under the terms of the GNU Public License.
++ *
++ */
++
++/* HFC register addresses - accessed using memory mapped I/O */
++/* For a list, see datasheet section 3.2.1 at page 21 */
++
++#define hfc_outb(a,b,c) (writeb((c),(a)->pci_io+(b)))
++#define hfc_inb(a,b) (readb((a)->pci_io+(b)))
++
++/* GCI/IOM bus monitor registers */
++
++#define hfc_C_I 0x08
++#define hfc_TRxR 0x0C
++#define hfc_MON1_D 0x28
++#define hfc_MON2_D 0x2C
++
++
++/* GCI/IOM bus timeslot registers */
++
++#define hfc_B1_SSL 0x80
++#define hfc_B2_SSL 0x84
++#define hfc_AUX1_SSL 0x88
++#define hfc_AUX2_SSL 0x8C
++#define hfc_B1_RSL 0x90
++#define hfc_B2_RSL 0x94
++#define hfc_AUX1_RSL 0x98
++#define hfc_AUX2_RSL 0x9C
++
++/* GCI/IOM bus data registers */
++
++#define hfc_B1_D 0xA0
++#define hfc_B2_D 0xA4
++#define hfc_AUX1_D 0xA8
++#define hfc_AUX2_D 0xAC
++
++/* GCI/IOM bus configuration registers */
++
++#define hfc_MST_EMOD 0xB4
++#define hfc_MST_MODE 0xB8
++#define hfc_CONNECT 0xBC
++
++
++/* Interrupt and status registers */
++
++#define hfc_FIFO_EN 0x44
++#define hfc_TRM 0x48
++#define hfc_B_MODE 0x4C
++#define hfc_CHIP_ID 0x58
++#define hfc_CIRM 0x60
++#define hfc_CTMT 0x64
++#define hfc_INT_M1 0x68
++#define hfc_INT_M2 0x6C
++#define hfc_INT_S1 0x78
++#define hfc_INT_S2 0x7C
++#define hfc_STATUS 0x70
++
++/* S/T section registers */
++
++#define hfc_STATES 0xC0
++#define hfc_SCTRL 0xC4
++#define hfc_SCTRL_E 0xC8
++#define hfc_SCTRL_R 0xCC
++#define hfc_SQ 0xD0
++#define hfc_CLKDEL 0xDC
++#define hfc_B1_REC 0xF0
++#define hfc_B1_SEND 0xF0
++#define hfc_B2_REC 0xF4
++#define hfc_B2_SEND 0xF4
++#define hfc_D_REC 0xF8
++#define hfc_D_SEND 0xF8
++#define hfc_E_REC 0xFC
++
++/* Bits and values in various HFC PCI registers */
++
++/* bits in status register (READ) */
++#define hfc_STATUS_PCI_PROC 0x02
++#define hfc_STATUS_NBUSY 0x04
++#define hfc_STATUS_TIMER_ELAP 0x10
++#define hfc_STATUS_STATINT 0x20
++#define hfc_STATUS_FRAMEINT 0x40
++#define hfc_STATUS_ANYINT 0x80
++
++/* bits in CTMT (Write) */
++#define hfc_CTMT_CLTIMER 0x80
++#define hfc_CTMT_TIM3_125 0x04
++#define hfc_CTMT_TIM25 0x10
++#define hfc_CTMT_TIM50 0x14
++#define hfc_CTMT_TIM400 0x18
++#define hfc_CTMT_TIM800 0x1C
++#define hfc_CTMT_AUTO_TIMER 0x20
++#define hfc_CTMT_TRANSB2 0x02
++#define hfc_CTMT_TRANSB1 0x01
++
++/* bits in CIRM (Write) */
++#define hfc_CIRM_AUX_MSK 0x07
++#define hfc_CIRM_RESET 0x08
++#define hfc_CIRM_B1_REV 0x40
++#define hfc_CIRM_B2_REV 0x80
++
++/* bits in INT_M1 and INT_S1 */
++#define hfc_INTS_B1TRANS 0x01
++#define hfc_INTS_B2TRANS 0x02
++#define hfc_INTS_DTRANS 0x04
++#define hfc_INTS_B1REC 0x08
++#define hfc_INTS_B2REC 0x10
++#define hfc_INTS_DREC 0x20
++#define hfc_INTS_L1STATE 0x40
++#define hfc_INTS_TIMER 0x80
++
++/* bits in INT_M2 */
++#define hfc_M2_PROC_TRANS 0x01
++#define hfc_M2_GCI_I_CHG 0x02
++#define hfc_M2_GCI_MON_REC 0x04
++#define hfc_M2_IRQ_ENABLE 0x08
++#define hfc_M2_PMESEL 0x80
++
++/* bits in STATES */
++#define hfc_STATES_STATE_MASK 0x0F
++#define hfc_STATES_LOAD_STATE 0x10
++#define hfc_STATES_ACTIVATE 0x20
++#define hfc_STATES_DO_ACTION 0x40
++#define hfc_STATES_NT_G2_G3 0x80
++
++/* bits in HFCD_MST_MODE */
++#define hfc_MST_MODE_MASTER 0x01
++#define hfc_MST_MODE_SLAVE 0x00
++/* remaining bits are for codecs control */
++
++/* bits in HFCD_SCTRL */
++#define hfc_SCTRL_B1_ENA 0x01
++#define hfc_SCTRL_B2_ENA 0x02
++#define hfc_SCTRL_MODE_TE 0x00
++#define hfc_SCTRL_MODE_NT 0x04
++#define hfc_SCTRL_LOW_PRIO 0x08
++#define hfc_SCTRL_SQ_ENA 0x10
++#define hfc_SCTRL_TEST 0x20
++#define hfc_SCTRL_NONE_CAP 0x40
++#define hfc_SCTRL_PWR_DOWN 0x80
++
++/* bits in SCTRL_E */
++#define hfc_SCTRL_E_AUTO_AWAKE 0x01
++#define hfc_SCTRL_E_DBIT_1 0x04
++#define hfc_SCTRL_E_IGNORE_COL 0x08
++#define hfc_SCTRL_E_CHG_B1_B2 0x80
++
++/* bits in FIFO_EN register */
++#define hfc_FIFOEN_B1TX 0x01
++#define hfc_FIFOEN_B1RX 0x02
++#define hfc_FIFOEN_B2TX 0x04
++#define hfc_FIFOEN_B2RX 0x08
++#define hfc_FIFOEN_DTX 0x10
++#define hfc_FIFOEN_DRX 0x20
++
++#define hfc_FIFOEN_B1 (hfc_FIFOEN_B1TX|hfc_FIFOEN_B1RX)
++#define hfc_FIFOEN_B2 (hfc_FIFOEN_B2TX|hfc_FIFOEN_B2RX)
++#define hfc_FIFOEN_D (hfc_FIFOEN_DTX|hfc_FIFOEN_DRX)
++
++/* bits in the CONNECT register */
++#define hfc_CONNECT_B1_shift 0
++#define hfc_CONNECT_B2_shift 3
++
++#define hfc_CONNECT_HFC_from_ST 0x0
++#define hfc_CONNECT_HFC_from_GCI 0x1
++#define hfc_CONNECT_ST_from_HFC 0x0
++#define hfc_CONNECT_ST_from_GCI 0x2
++#define hfc_CONNECT_GCI_from_HFC 0x0
++#define hfc_CONNECT_GCI_from_ST 0x4
++
++/* bits in the __SSL and __RSL registers */
++#define hfc_SRSL_STIO 0x40
++#define hfc_SRSL_ENABLE 0x80
++#define hfc_SRCL_SLOT_MASK 0x1f
++
++/* FIFO memory definitions */
++
++#define hfc_FMASK 0x000f
++#define hfc_ZMASK 0x01ff
++#define hfc_ZMASKB 0x1fff
++
++#define hfc_D_FIFO_SIZE 0x0200
++#define hfc_B_SUB_VAL 0x0200
++#define hfc_B_FIFO_SIZE 0x1E00
++#define hfc_MAX_DFRAMES 0x000f
++
++#define hfc_FIFO_DTX_Z1 0x2080
++#define hfc_FIFO_DTX_Z2 0x2082
++#define hfc_FIFO_DTX_F1 0x20a0
++#define hfc_FIFO_DTX_F2 0x20a1
++#define hfc_FIFO_DTX 0x0000
++#define hfc_FIFO_DTX_ZOFF 0x000
++
++#define hfc_FIFO_DRX_Z1 0x6080
++#define hfc_FIFO_DRX_Z2 0x6082
++#define hfc_FIFO_DRX_F1 0x60a0
++#define hfc_FIFO_DRX_F2 0x60a1
++#define hfc_FIFO_DRX 0x4000
++#define hfc_FIFO_DRX_ZOFF 0x4000
++
++#define hfc_FIFO_B1TX_Z1 0x2000
++#define hfc_FIFO_B1TX_Z2 0x2002
++#define hfc_FIFO_B1RX_Z1 0x6000
++#define hfc_FIFO_B1RX_Z2 0x6002
++
++#define hfc_FIFO_B1TX_F1 0x2080
++#define hfc_FIFO_B1TX_F2 0x2081
++#define hfc_FIFO_B1RX_F1 0x6080
++#define hfc_FIFO_B1RX_F2 0x6081
++
++#define hfc_FIFO_B1RX_ZOFF 0x4000
++#define hfc_FIFO_B1TX_ZOFF 0x0000
++
++#define hfc_FIFO_B2TX_Z1 0x2100
++#define hfc_FIFO_B2TX_Z2 0x2102
++#define hfc_FIFO_B2RX_Z1 0x6100
++#define hfc_FIFO_B2RX_Z2 0x6102
++
++#define hfc_FIFO_B2TX_F1 0x2180
++#define hfc_FIFO_B2TX_F2 0x2181
++#define hfc_FIFO_B2RX_F1 0x6180
++#define hfc_FIFO_B2RX_F2 0x6181
++
++#define hfc_FIFO_B2RX_ZOFF 0x6000
++#define hfc_FIFO_B2TX_ZOFF 0x2000
++
++#define hfc_BTRANS_THRESHOLD 128
++#define hfc_BTRANS_THRESMASK 0x00
++
++/* Structures */
++
++typedef struct hfc_regs {
++ unsigned char fifo_en;
++ unsigned char ctmt;
++ unsigned char int_m1;
++ unsigned char int_m2;
++ unsigned char sctrl;
++ unsigned char sctrl_e;
++ unsigned char sctrl_r;
++ unsigned char connect;
++ unsigned char trm;
++ unsigned char mst_mode;
++ unsigned char bswapped;
++ unsigned char nt_mode;
++ unsigned char int_drec;
++} hfc_regs;
++
++typedef struct hfc_card {
++ spinlock_t lock;
++ unsigned int irq;
++ unsigned int iomem;
++ int ticks;
++ int clicks;
++ unsigned char *pci_io;
++ void *fifomem; // start of the shared mem
++ volatile void *fifos; // 32k aligned mem for the fifos
++ struct hfc_regs regs;
++ unsigned int pcibus;
++ unsigned int pcidevfn;
++ struct pci_dev *pcidev;
++ struct dahdi_hfc *ztdev;
++ int drecinframe;
++ unsigned char drecbuf[hfc_D_FIFO_SIZE];
++ unsigned char dtransbuf[hfc_D_FIFO_SIZE];
++ unsigned char brecbuf[2][DAHDI_CHUNKSIZE];
++ unsigned char btransbuf[2][DAHDI_CHUNKSIZE];
++ unsigned char cardno;
++ struct hfc_card *next;
++} hfc_card;
++
++typedef struct dahdi_hfc {
++ unsigned int usecount;
++ struct dahdi_span span;
++ struct dahdi_chan chans[3];
++ struct dahdi_chan *_chans[3];
++ struct hfc_card *card;
++} dahdi_hfc;
++
++/* tune this */
++#define hfc_BCHAN_BUFFER 8
++#define hfc_MAX_CARDS 8
diff --git a/main/dahdi-linux-vserver/zaphfc-dahdi-2.4.0.patch b/main/dahdi-linux-vserver/zaphfc-dahdi-2.4.0.patch
new file mode 100644
index 0000000000..80500a574a
--- /dev/null
+++ b/main/dahdi-linux-vserver/zaphfc-dahdi-2.4.0.patch
@@ -0,0 +1,58 @@
+Index: dahdi-linux-2.4.0/drivers/dahdi/zaphfc.c
+===================================================================
+--- dahdi-linux-2.4.0.orig/drivers/dahdi/zaphfc.c 2010-10-26 14:41:21.000000000 +0300
++++ dahdi-linux-2.4.0/drivers/dahdi/zaphfc.c 2010-10-26 14:50:14.000000000 +0300
+@@ -617,7 +617,7 @@
+ }
+
+ static int zthfc_startup(struct dahdi_span *span) {
+- struct dahdi_hfc *zthfc = span->pvt;
++ struct dahdi_hfc *zthfc = container_of(span, struct dahdi_hfc, span);
+ struct hfc_card *hfctmp = zthfc->card;
+ int alreadyrunning;
+
+@@ -663,6 +663,19 @@
+ return 0;
+ }
+
++static const struct dahdi_span_ops zaphfc_span_ops = {
++ .owner = THIS_MODULE,
++ .spanconfig = zthfc_spanconfig,
++ .chanconfig = zthfc_chanconfig,
++ .startup = zthfc_startup,
++ .shutdown = zthfc_shutdown,
++ .maint = zthfc_maint,
++ .rbsbits = zthfc_rbsbits,
++ .open = zthfc_open,
++ .close = zthfc_close,
++ .ioctl = zthfc_ioctl,
++};
++
+ static int zthfc_initialize(struct dahdi_hfc *zthfc) {
+ struct hfc_card *hfctmp = zthfc->card;
+ int i;
+@@ -676,15 +689,7 @@
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1);
+ }
+
+- zthfc->span.spanconfig = zthfc_spanconfig;
+- zthfc->span.chanconfig = zthfc_chanconfig;
+- zthfc->span.startup = zthfc_startup;
+- zthfc->span.shutdown = zthfc_shutdown;
+- zthfc->span.maint = zthfc_maint;
+- zthfc->span.rbsbits = zthfc_rbsbits;
+- zthfc->span.open = zthfc_open;
+- zthfc->span.close = zthfc_close;
+- zthfc->span.ioctl = zthfc_ioctl;
++ zthfc->span.ops = &zaphfc_span_ops;
+
+ zthfc->span.channels = 3;
+ zthfc->span.chans = zthfc->_chans;
+@@ -695,7 +700,6 @@
+ zthfc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS; // <--- this is really BS
+ zthfc->span.offset = 0;
+ init_waitqueue_head(&zthfc->span.maintq);
+- zthfc->span.pvt = zthfc;
+
+ for (i = 0; i < zthfc->span.channels; i++) {
+ memset(&(zthfc->chans[i]), 0x0, sizeof(struct dahdi_chan));
diff --git a/main/dahdi-linux-vserver/zaphfc-dahdi-flortz.diff b/main/dahdi-linux-vserver/zaphfc-dahdi-flortz.diff
new file mode 100644
index 0000000000..719accdc69
--- /dev/null
+++ b/main/dahdi-linux-vserver/zaphfc-dahdi-flortz.diff
@@ -0,0 +1,1232 @@
+Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h
+===================================================================
+--- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.h 2009-03-17 18:13:54.000000000 +0200
++++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h 2009-03-17 18:14:44.000000000 +0200
+@@ -135,8 +135,12 @@
+ /* bits in HFCD_MST_MODE */
+ #define hfc_MST_MODE_MASTER 0x01
+ #define hfc_MST_MODE_SLAVE 0x00
++#define hfc_MST_MODE_F0_LONG_DURATION 0x08
+ /* remaining bits are for codecs control */
+
++/* bits in HFCD_MST_EMOD */
++#define hfc_MST_EMOD_SLOW_CLOCK_ADJ 0x01
++
+ /* bits in HFCD_SCTRL */
+ #define hfc_SCTRL_B1_ENA 0x01
+ #define hfc_SCTRL_B2_ENA 0x02
+@@ -236,6 +240,9 @@
+ #define hfc_BTRANS_THRESHOLD 128
+ #define hfc_BTRANS_THRESMASK 0x00
+
++#define hfc_FIFO_MEM_SIZE_BYTES (32*1024)
++#define hfc_FIFO_MEM_SIZE_PAGES ((hfc_FIFO_MEM_SIZE_BYTES+PAGE_SIZE-1)/PAGE_SIZE)
++
+ /* Structures */
+
+ typedef struct hfc_regs {
+@@ -249,20 +256,67 @@
+ unsigned char connect;
+ unsigned char trm;
+ unsigned char mst_mode;
++ unsigned char mst_emod;
+ unsigned char bswapped;
+ unsigned char nt_mode;
+ unsigned char int_drec;
+ } hfc_regs;
+
++struct bch {
++ int fill_fifo,checkcnt,initialized;
++ struct {
++ u16 z2;
++ struct {
++ volatile u16 *z1p;
++ volatile u8 *fifo_base;
++ int filled;
++ } c[2];
++ int diff;
++ } rx;
++ struct {
++ u16 z1;
++ struct {
++ volatile u16 *z1p,*z2p;
++ volatile u8 *fifo_base;
++ int filled;
++ } c[2];
++ int diff;
++ } tx;
++};
++
++struct dch {
++ struct {
++ struct {
++ volatile u8 *p;
++ } f1;
++ struct {
++ u8 v;
++ struct {
++ u16 v;
++ } z2;
++ } f2;
++ } rx;
++ struct {
++ struct {
++ u8 v;
++ volatile u8 *p;
++ struct {
++ u16 v;
++ } z1;
++ } f1;
++ struct {
++ volatile u8 *p;
++ } f2;
++ } tx;
++};
++
+ typedef struct hfc_card {
+ spinlock_t lock;
+ unsigned int irq;
+ unsigned int iomem;
+ int ticks;
+- int clicks;
+ unsigned char *pci_io;
+- void *fifomem; // start of the shared mem
+- volatile void *fifos; // 32k aligned mem for the fifos
++ void *fifos; // 32k aligned mem for the fifos
+ struct hfc_regs regs;
+ unsigned int pcibus;
+ unsigned int pcidevfn;
+@@ -274,6 +328,9 @@
+ unsigned char brecbuf[2][DAHDI_CHUNKSIZE];
+ unsigned char btransbuf[2][DAHDI_CHUNKSIZE];
+ unsigned char cardno;
++ int active;
++ struct bch bch;
++ struct dch dch;
+ struct hfc_card *next;
+ } hfc_card;
+
+@@ -285,6 +342,3 @@
+ struct hfc_card *card;
+ } dahdi_hfc;
+
+-/* tune this */
+-#define hfc_BCHAN_BUFFER 8
+-#define hfc_MAX_CARDS 8
+Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c
+===================================================================
+--- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.c 2009-03-17 18:52:47.000000000 +0200
++++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c 2009-03-17 18:53:43.000000000 +0200
+@@ -7,19 +7,21 @@
+ *
+ * Klaus-Peter Junghanns <kpj@junghanns.net>
+ *
++ * Copyright (C) 2004, 2005, 2006 Florian Zumbiehl <florz@gmx.de>
++ * - support for slave mode of the HFC-S chip which allows it to
++ * sync its sample clock to an external source/another HFC chip
++ * - support for "interrupt bundling" (let only one card generate
++ * 8 kHz timing interrupt no matter how many cards there are
++ * in the system)
++ * - interrupt loss tolerant b channel handling
++ *
+ * This program is free software and may be modified and
+- * distributed under the terms of the GNU Public License.
++ * distributed under the terms of the GNU General Public License.
+ *
+ */
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+-#ifdef RTAITIMING
+-#include <asm/io.h>
+-#include <rtai.h>
+-#include <rtai_sched.h>
+-#include <rtai_fifos.h>
+-#endif
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+@@ -29,6 +31,8 @@
+
+ #include <linux/moduleparam.h>
+
++#define log2(n) ffz(~(n))
++
+ #if CONFIG_PCI
+
+ #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
+@@ -70,42 +74,31 @@
+ static struct hfc_card *hfc_dev_list = NULL;
+ static int hfc_dev_count = 0;
+ static int modes = 0; // all TE
++static int sync_slave = 0; // all master
++static int timer_card = 0;
++static int jitterbuffer = 1;
+ static int debug = 0;
+ static struct pci_dev *multi_hfc = NULL;
+ static spinlock_t registerlock = SPIN_LOCK_UNLOCKED;
+
+-void hfc_shutdownCard(struct hfc_card *hfctmp) {
+- unsigned long flags;
+-
+- if (hfctmp == NULL) {
+- return;
+- }
+-
+- if (hfctmp->pci_io == NULL) {
+- return;
+- }
+-
+- spin_lock_irqsave(&hfctmp->lock,flags);
+-
++void hfc_shutdownCard1(struct hfc_card *hfctmp) {
+ printk(KERN_INFO "zaphfc: shutting down card at %p.\n",hfctmp->pci_io);
+
+ /* Clear interrupt mask */
+ hfctmp->regs.int_m2 = 0;
+ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+
+- /* Reset pending interrupts */
+- hfc_inb(hfctmp, hfc_INT_S1);
++ /* Remove interrupt handler */
++ free_irq(hfctmp->irq,hfctmp);
++}
++
++void hfc_shutdownCard2(struct hfc_card *hfctmp) {
++ unsigned long flags;
+
+- /* Wait for interrupts that might still be pending */
+- spin_unlock_irqrestore(&hfctmp->lock, flags);
+- set_current_state(TASK_UNINTERRUPTIBLE);
+- schedule_timeout((30 * HZ) / 1000); // wait 30 ms
+ spin_lock_irqsave(&hfctmp->lock,flags);
+
+- /* Remove interrupt handler */
+- if (hfctmp->irq) {
+- free_irq(hfctmp->irq, hfctmp);
+- }
++ /* Reset pending interrupts */
++ hfc_inb(hfctmp, hfc_INT_S1);
+
+ /* Soft-reset the card */
+ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on
+@@ -119,8 +112,8 @@
+
+ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, 0); // disable memio and bustmaster
+
+- if (hfctmp->fifomem != NULL) {
+- kfree(hfctmp->fifomem);
++ if (hfctmp->fifos != NULL) {
++ free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES));
+ }
+ iounmap((void *) hfctmp->pci_io);
+ hfctmp->pci_io = NULL;
+@@ -130,11 +123,24 @@
+ spin_unlock_irqrestore(&hfctmp->lock,flags);
+ if (hfctmp->ztdev != NULL) {
+ dahdi_unregister(&hfctmp->ztdev->span);
+- kfree(hfctmp->ztdev);
++ vfree(hfctmp->ztdev);
+ printk(KERN_INFO "unregistered from DAHDI.\n");
+ }
+ }
+
++void hfc_shutdownCard(struct hfc_card *hfctmp) {
++ if (hfctmp == NULL) {
++ return;
++ }
++
++ if (hfctmp->pci_io == NULL) {
++ return;
++ }
++
++ hfc_shutdownCard1(hfctmp);
++ hfc_shutdownCard2(hfctmp);
++}
++
+ void hfc_resetCard(struct hfc_card *hfctmp) {
+ unsigned long flags;
+
+@@ -178,14 +184,14 @@
+ hfctmp->regs.ctmt = hfc_CTMT_TRANSB1 | hfc_CTMT_TRANSB2; // all bchans are transparent , no freaking hdlc
+ hfc_outb(hfctmp, hfc_CTMT, hfctmp->regs.ctmt);
+
+- hfctmp->regs.int_m1 = 0;
++ hfctmp->regs.int_m1=hfc_INTS_L1STATE;
++ if(hfctmp->cardno==timer_card){
++ hfctmp->regs.int_m2=hfc_M2_PROC_TRANS;
++ }else{
++ hfctmp->regs.int_m1|=hfc_INTS_DREC;
++ hfctmp->regs.int_m2=0;
++ }
+ hfc_outb(hfctmp, hfc_INT_M1, hfctmp->regs.int_m1);
+-
+-#ifdef RTAITIMING
+- hfctmp->regs.int_m2 = 0;
+-#else
+- hfctmp->regs.int_m2 = hfc_M2_PROC_TRANS;
+-#endif
+ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+
+ /* Clear already pending ints */
+@@ -197,8 +203,8 @@
+ hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_TE; /* set tx_lo mode, error in datasheet ! */
+ }
+
+- hfctmp->regs.mst_mode = hfc_MST_MODE_MASTER; /* HFC Master Mode */
+ hfc_outb(hfctmp, hfc_MST_MODE, hfctmp->regs.mst_mode);
++ hfc_outb(hfctmp, hfc_MST_EMOD, hfctmp->regs.mst_emod);
+
+ hfc_outb(hfctmp, hfc_SCTRL, hfctmp->regs.sctrl);
+ hfctmp->regs.sctrl_r = 3;
+@@ -210,10 +216,8 @@
+ hfc_outb(hfctmp, hfc_CIRM, 0x80 | 0x40); // bit order
+
+ /* Finally enable IRQ output */
+-#ifndef RTAITIMING
+ hfctmp->regs.int_m2 |= hfc_M2_IRQ_ENABLE;
+ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+-#endif
+
+ /* clear pending ints */
+ hfc_inb(hfctmp, hfc_INT_S1);
+@@ -230,368 +234,210 @@
+ spin_unlock(&registerlock);
+ }
+
+-static void hfc_btrans(struct hfc_card *hfctmp, char whichB) {
+- // we are called with irqs disabled from the irq handler
+- int count, maxlen, total;
+- unsigned char *f1, *f2;
+- unsigned short *z1, *z2, newz1;
+- int freebytes;
+-
+- if (whichB == 1) {
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z2 + (*f1 * 4));
+- } else {
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z2 + (*f1 * 4));
+- }
+-
+- freebytes = *z2 - *z1;
+- if (freebytes <= 0) {
+- freebytes += hfc_B_FIFO_SIZE;
+- }
+- count = DAHDI_CHUNKSIZE;
+-
+- total = count;
+- if (freebytes < count) {
+- hfctmp->clicks++;
+- /* only spit out this warning once per second to not make things worse! */
+- if (hfctmp->clicks > 100) {
+- printk(KERN_CRIT "zaphfc: bchan tx fifo full, dropping audio! (z1=%d, z2=%d)\n",*z1,*z2);
+- hfctmp->clicks = 0;
+- }
+- return;
+- }
+-
+- maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z1;
+- if (maxlen > count) {
+- maxlen = count;
+- }
+- newz1 = *z1 + total;
+- if (newz1 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { newz1 -= hfc_B_FIFO_SIZE; }
++/*===========================================================================*/
+
+- if (whichB == 1) {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + *z1),hfctmp->ztdev->chans[0].writechunk, maxlen);
+- } else {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + *z1),hfctmp->ztdev->chans[1].writechunk, maxlen);
+- }
+-
+- count -= maxlen;
+- if (count > 0) {
+- // Buffer wrap
+- if (whichB == 1) {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[0].writechunk+maxlen, count);
+- } else {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[1].writechunk+maxlen, count);
+- }
+- }
++#if hfc_B_FIFO_SIZE%DAHDI_CHUNKSIZE
++#error hfc_B_FIFO_SIZE is not a multiple of DAHDI_CHUNKSIZE even though the code assumes this
++#endif
++
++static void hfc_dch_init(struct hfc_card *hfctmp){
++ struct dch *chtmp=&hfctmp->dch;
+
+- *z1 = newz1; /* send it now */
++ chtmp->rx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DRX_F1);
++ chtmp->rx.f2.v=0x1f;
++ chtmp->rx.f2.z2.v=0x1ff;
+
+-// if (count > 0) printk(KERN_CRIT "zaphfc: bchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
+- return;
++ chtmp->tx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F1);
++ chtmp->tx.f1.v=0x1f;
++ chtmp->tx.f1.z1.v=0x1ff;
++ chtmp->tx.f2.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F2);
+ }
+
+-static void hfc_brec(struct hfc_card *hfctmp, char whichB) {
+- // we are called with irqs disabled from the irq handler
+- int count, maxlen, drop;
+- volatile unsigned char *f1, *f2;
+- volatile unsigned short *z1, *z2, newz2;
+- int bytes = 0;
+-
+- if (whichB == 1) {
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
+- } else {
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
+- }
++static void hfc_bch_init(struct hfc_card *hfctmp){
++ struct bch *chtmp=&hfctmp->bch;
+
+- bytes = *z1 - *z2;
+- if (bytes < 0) {
+- bytes += hfc_B_FIFO_SIZE;
+- }
+- count = DAHDI_CHUNKSIZE;
+-
+- if (bytes < DAHDI_CHUNKSIZE) {
+-#ifndef RTAITIMING
+- printk(KERN_CRIT "zaphfc: bchan rx fifo not enough bytes to receive! (z1=%d, z2=%d, wanted %d got %d), probably a buffer overrun.\n",*z1,*z2,DAHDI_CHUNKSIZE,bytes);
+-#endif
+- return;
+- }
++ chtmp->checkcnt=0;
++ chtmp->fill_fifo=0;
+
+- /* allowing the buffering of hfc_BCHAN_BUFFER bytes of audio data works around irq jitter */
+- if (bytes > hfc_BCHAN_BUFFER + DAHDI_CHUNKSIZE) {
+- /* if the system is too slow to handle it, we will have to drop it all (except 1 DAHDI chunk) */
+- drop = bytes - DAHDI_CHUNKSIZE;
+- hfctmp->clicks++;
+- /* only spit out this warning once per second to not make things worse! */
+- if (hfctmp->clicks > 100) {
+- printk(KERN_CRIT "zaphfc: dropped audio (z1=%d, z2=%d, wanted %d got %d, dropped %d).\n",*z1,*z2,count,bytes,drop);
+- hfctmp->clicks = 0;
+- }
+- /* hm, we are processing the b chan data tooooo slowly... let's drop the lost audio */
+- newz2 = *z2 + drop;
+- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
+- newz2 -= hfc_B_FIFO_SIZE;
+- }
+- *z2 = newz2;
+- }
++ chtmp->rx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1RX_Z1+0x1f*4);
++ chtmp->rx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1RX_ZOFF);
++ chtmp->rx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2RX_Z1+0x1f*4);
++ chtmp->rx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2RX_ZOFF);
++ chtmp->rx.z2=hfc_B_SUB_VAL;
++ chtmp->rx.diff=0;
+
+-
+- maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z2;
+- if (maxlen > count) {
+- maxlen = count;
+- }
+- if (whichB == 1) {
+- memcpy(hfctmp->ztdev->chans[0].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + *z2), maxlen);
+- } else {
+- memcpy(hfctmp->ztdev->chans[1].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + *z2), maxlen);
+- }
+- newz2 = *z2 + count;
+- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
+- newz2 -= hfc_B_FIFO_SIZE;
++ chtmp->tx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z1+0x1f*4);
++ chtmp->tx.c[0].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z2+0x1f*4);
++ chtmp->tx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1TX_ZOFF);
++ chtmp->tx.c[0].filled=0;
++ chtmp->tx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z1+0x1f*4);
++ chtmp->tx.c[1].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z2+0x1f*4);
++ chtmp->tx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2TX_ZOFF);
++ chtmp->tx.c[1].filled=0;
++ chtmp->tx.z1=hfc_B_SUB_VAL;
++ chtmp->tx.diff=0;
++
++ hfc_dch_init(hfctmp);
++
++ chtmp->initialized=0;
++}
++
++static int hfc_bch_check(struct hfc_card *hfctmp){
++ struct bch *chtmp=&hfctmp->bch;
++ int x,r;
++
++ for(x=0;x<2;x++){
++ chtmp->tx.c[x].filled=(chtmp->tx.z1-*chtmp->tx.c[x].z2p+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE;
++ chtmp->rx.c[x].filled=(*chtmp->rx.c[x].z1p-chtmp->rx.z2+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE;
+ }
+- *z2 = newz2;
+-
+- count -= maxlen;
+- if (count > 0) {
+- // Buffer wrap
+- if (whichB == 1) {
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
+- memcpy(hfctmp->ztdev->chans[0].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + hfc_B_SUB_VAL), count);
+- } else {
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
+- memcpy(hfctmp->ztdev->chans[1].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + hfc_B_SUB_VAL), count);
+- }
+- newz2 = *z2 + count;
+- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) {
+- newz2 -= hfc_B_FIFO_SIZE;
++ if(chtmp->fill_fifo){
++ chtmp->checkcnt++;
++ chtmp->checkcnt%=DAHDI_CHUNKSIZE;
++ r=!chtmp->checkcnt;
++ }else{
++ x=chtmp->tx.c[0].filled-chtmp->tx.c[1].filled;
++ if(abs(x-chtmp->tx.diff)>1){
++ printk(KERN_CRIT "zaphfc[%d]: tx sync changed: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled);
++ chtmp->tx.diff=x;
+ }
++ r=chtmp->tx.c[0].filled<=DAHDI_CHUNKSIZE*jitterbuffer&&chtmp->tx.c[1].filled<=DAHDI_CHUNKSIZE*jitterbuffer;
+ }
++ return(r);
++}
+
++#define hfc_bch_inc_z(a,b) (a)=((a)-hfc_B_SUB_VAL+(b))%hfc_B_FIFO_SIZE+hfc_B_SUB_VAL
+
+- if (whichB == 1) {
+- dahdi_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk);
+- } else {
+- dahdi_ec_chunk(&hfctmp->ztdev->chans[1], hfctmp->ztdev->chans[1].readchunk, hfctmp->ztdev->chans[1].writechunk);
++static void hfc_bch_tx(struct hfc_card *hfctmp){
++ struct bch *chtmp=&hfctmp->bch;
++ int x;
++
++ for(x=0;x<2;x++)
++ memcpy((void *)(chtmp->tx.c[x].fifo_base+chtmp->tx.z1),hfctmp->ztdev->chans[x].writechunk,DAHDI_CHUNKSIZE);
++ hfc_bch_inc_z(chtmp->tx.z1,DAHDI_CHUNKSIZE);
++ if(chtmp->fill_fifo){
++ chtmp->fill_fifo--;
++ }else if(chtmp->tx.c[0].filled<=1||chtmp->tx.c[1].filled<=1){
++ chtmp->fill_fifo=jitterbuffer;
++ if(chtmp->initialized)
++ printk(KERN_CRIT "zaphfc[%d]: b channel buffer underrun: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled);
+ }
+- return;
++ if(!chtmp->fill_fifo)
++ for(x=0;x<2;x++)*chtmp->tx.c[x].z1p=chtmp->tx.z1;
+ }
+
+-
+-static void hfc_dtrans(struct hfc_card *hfctmp) {
+- // we are called with irqs disabled from the irq handler
++static void hfc_bch_rx(struct hfc_card *hfctmp){
++ struct bch *chtmp=&hfctmp->bch;
+ int x;
+- int count, maxlen, total;
+- unsigned char *f1, *f2, newf1;
+- unsigned short *z1, *z2, newz1;
+- int frames, freebytes;
+
+- if (hfctmp->ztdev->chans[2].bytes2transmit == 0) {
+- return;
++ x=chtmp->rx.c[0].filled-chtmp->rx.c[1].filled;
++ if(abs(x-chtmp->rx.diff)>1){
++ printk(KERN_CRIT "zaphfc[%d]: rx sync changed: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled);
++ chtmp->rx.diff=x;
+ }
+-
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F2);
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z2 + (*f1 * 4));
+-
+- frames = (*f1 - *f2) & hfc_FMASK;
+- if (frames < 0) {
+- frames += hfc_MAX_DFRAMES + 1;
++ if(chtmp->rx.c[0].filled>=DAHDI_CHUNKSIZE&&chtmp->rx.c[1].filled>=DAHDI_CHUNKSIZE){
++ if((chtmp->rx.c[0].filled>=DAHDI_CHUNKSIZE*(jitterbuffer+2)&&chtmp->rx.c[1].filled>=DAHDI_CHUNKSIZE*(jitterbuffer+2))||!chtmp->initialized){
++ if(chtmp->initialized)
++ printk(KERN_CRIT "zaphfc[%d]: b channel buffer overflow: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled);
++ hfc_bch_inc_z(chtmp->rx.z2,chtmp->rx.c[0].filled-chtmp->rx.c[0].filled%DAHDI_CHUNKSIZE-DAHDI_CHUNKSIZE);
++ chtmp->initialized=1;
++ }
++ for(x=0;x<2;x++){
++ memcpy(hfctmp->ztdev->chans[x].readchunk,(void *)(chtmp->rx.c[x].fifo_base+chtmp->rx.z2),DAHDI_CHUNKSIZE);
++ dahdi_ec_chunk(&hfctmp->ztdev->chans[x],hfctmp->ztdev->chans[x].readchunk,hfctmp->ztdev->chans[x].writechunk);
++ }
++ hfc_bch_inc_z(chtmp->rx.z2,DAHDI_CHUNKSIZE);
+ }
++}
+
+- if (frames >= hfc_MAX_DFRAMES) {
+- printk(KERN_CRIT "zaphfc: dchan tx fifo total number of frames exceeded!\n");
+- return;
+- }
++/*===========================================================================*/
+
+- freebytes = *z2 - *z1;
+- if (freebytes <= 0) {
+- freebytes += hfc_D_FIFO_SIZE;
+- }
+- count = hfctmp->ztdev->chans[2].bytes2transmit;
+-
+- total = count;
+- if (freebytes < count) {
+- printk(KERN_CRIT "zaphfc: dchan tx fifo not enough free bytes! (z1=%d, z2=%d)\n",*z1,*z2);
+- return;
+- }
+-
+- newz1 = (*z1 + count) & hfc_ZMASK;
+- newf1 = ((*f1 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); // next frame
+-
+- if (count > 0) {
+- if (debug) {
+- printk(KERN_CRIT "zaphfc: card %d TX [ ", hfctmp->cardno);
+- for (x=0; x<count; x++) {
++static void hfc_dch_tx(struct hfc_card *hfctmp){
++ struct dch *chtmp=&hfctmp->dch;
++ u8 tx_f2_v;
++ u16 x;
++
++ if(hfctmp->ztdev->chans[2].bytes2transmit){
++ if(debug){
++ printk(KERN_CRIT "zaphfc[%d]: card TX [ ",hfctmp->cardno);
++ for(x=0;x<hfctmp->ztdev->chans[2].bytes2transmit;x++){
+ printk("%#2x ",hfctmp->dtransbuf[x]);
+ }
+- if (hfctmp->ztdev->chans[2].eoftx == 1) {
+- printk("] %d bytes\n", count);
+- } else {
+- printk("..] %d bytes\n", count);
+- }
+- }
+- maxlen = hfc_D_FIFO_SIZE - *z1;
+- if (maxlen > count) {
+- maxlen = count;
++ printk("] %d bytes\n",hfctmp->ztdev->chans[2].bytes2transmit);
+ }
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF + *z1),hfctmp->ztdev->chans[2].writechunk, maxlen);
+- count -= maxlen;
+- if (count > 0) {
+- memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF),(char *)(hfctmp->ztdev->chans[2].writechunk + maxlen), count);
++ tx_f2_v=*chtmp->tx.f2.p;
++ if(!(tx_f2_v-chtmp->tx.f1.v+hfc_MAX_DFRAMES+1-1)&(hfc_MAX_DFRAMES+1-1)){
++ printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo total number of frames exceeded!\n",hfctmp->cardno);
++ }else{
++ if(((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+tx_f2_v*4)-chtmp->tx.f1.z1.v+hfc_D_FIFO_SIZE-1)&(hfc_D_FIFO_SIZE-1))<hfctmp->ztdev->chans[2].bytes2transmit){
++ printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo not enough space for frame!\n",hfctmp->cardno);
++ }else{
++ chtmp->tx.f1.v=((chtmp->tx.f1.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1);
++ x=min(hfctmp->ztdev->chans[2].bytes2transmit,hfc_D_FIFO_SIZE-chtmp->tx.f1.z1.v);
++ memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF+chtmp->tx.f1.z1.v,hfctmp->ztdev->chans[2].writechunk,x);
++ memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF,hfctmp->ztdev->chans[2].writechunk+x,hfctmp->ztdev->chans[2].bytes2transmit-x);
++ *(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v;
++ chtmp->tx.f1.z1.v=(chtmp->tx.f1.z1.v+hfctmp->ztdev->chans[2].bytes2transmit+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1);
++ *(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z1+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v;
++ *chtmp->tx.f1.p=chtmp->tx.f1.v;
++ }
+ }
+ }
+-
+- *z1 = newz1;
+-
+- if (hfctmp->ztdev->chans[2].eoftx == 1) {
+- *f1 = newf1;
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
+- *z1 = newz1;
+- hfctmp->ztdev->chans[2].eoftx = 0;
+- }
+-// printk(KERN_CRIT "zaphfc: dchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
+- return;
+ }
+
+-/* receive a complete hdlc frame, skip broken or short frames */
+-static void hfc_drec(struct hfc_card *hfctmp) {
+- int count=0, maxlen=0, framelen=0;
+- unsigned char *f1, *f2, *crcstat;
+- unsigned short *z1, *z2, oldz2, newz2;
++static void hfc_dch_rx(struct hfc_card *hfctmp){
++ struct dch *chtmp=&hfctmp->dch;
++ u16 size;
+
+ hfctmp->ztdev->chans[2].bytes2receive=0;
+- hfctmp->ztdev->chans[2].eofrx = 0;
+-
+- /* put the received data into the DAHDI buffer
+- we'll call dahdi_receive() later when the timer fires. */
+- f1 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F1);
+- f2 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F2);
+-
+- if (*f1 == *f2) return; /* nothing received, strange eh? */
+-
+- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z1 + (*f2 * 4));
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+-
+- /* calculate length of frame, including 2 bytes CRC and 1 byte STAT */
+- count = *z1 - *z2;
+-
+- if (count < 0) {
+- count += hfc_D_FIFO_SIZE; /* ring buffer wrapped */
+- }
+- count++;
+- framelen = count;
+-
+- crcstat = (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z1);
+-
+- if ((framelen < 4) || (*crcstat != 0x0)) {
+- /* the frame is too short for a valid HDLC frame or the CRC is borked */
+- printk(KERN_CRIT "zaphfc: empty HDLC frame or bad CRC received (framelen = %d, stat = %#x, card = %d).\n", framelen, *crcstat, hfctmp->cardno);
+- oldz2 = *z2;
+- *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */
+- // recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!!
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+- *z2 = (oldz2 + framelen) & hfc_ZMASK;
+- hfctmp->drecinframe = 0;
+- hfctmp->regs.int_drec--;
+- /* skip short or broken frames */
+- hfctmp->ztdev->chans[2].bytes2receive = 0;
+- return;
+- }
+-
+- count -= 1; /* strip STAT */
+- hfctmp->ztdev->chans[2].eofrx = 1;
+-
+- if (count + *z2 <= hfc_D_FIFO_SIZE) {
+- maxlen = count;
+- } else {
+- maxlen = hfc_D_FIFO_SIZE - *z2;
++ hfctmp->ztdev->chans[2].eofrx=0;
++ if(*chtmp->rx.f1.p==chtmp->rx.f2.v){
++ hfctmp->regs.int_drec=0;
++ }else{
++ size=((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DRX_Z1+chtmp->rx.f2.v*4)-chtmp->rx.f2.z2.v+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1))+1;
++ if(size<4){
++ printk(KERN_CRIT "zaphfc[%d]: empty HDLC frame received.\n",hfctmp->cardno);
++ }else{
++ u16 x=min(size,(u16)(hfc_D_FIFO_SIZE-chtmp->rx.f2.z2.v));
++ memcpy(hfctmp->drecbuf,hfctmp->fifos+hfc_FIFO_DRX_ZOFF+chtmp->rx.f2.z2.v,x);
++ memcpy(hfctmp->drecbuf+x,hfctmp->fifos+hfc_FIFO_DRX_ZOFF,size-x);
++ if(hfctmp->drecbuf[size-1]){
++ printk(KERN_CRIT "zaphfc[%d]: received d channel frame with bad CRC.\n",hfctmp->cardno);
++ }else{
++ hfctmp->ztdev->chans[2].bytes2receive=size-1;
++ hfctmp->ztdev->chans[2].eofrx=1;
++ }
++ }
++ chtmp->rx.f2.z2.v=(chtmp->rx.f2.z2.v+size)&(hfc_D_FIFO_SIZE-1);
++ chtmp->rx.f2.v=((chtmp->rx.f2.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1);
+ }
+-
+- /* copy first part */
+- memcpy(hfctmp->drecbuf, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z2), maxlen);
+- hfctmp->ztdev->chans[2].bytes2receive += maxlen;
+-
+- count -= maxlen;
+- if (count > 0) {
+- /* ring buffer wrapped, copy rest from start of d fifo */
+- memcpy(hfctmp->drecbuf + maxlen, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF), count);
+- hfctmp->ztdev->chans[2].bytes2receive += count;
+- }
+-
+- /* frame read */
+- oldz2 = *z2;
+- newz2 = (oldz2 + framelen) & hfc_ZMASK;
+- *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */
+- /* recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! */
+- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+- *z2 = newz2;
+- hfctmp->drecinframe = 0;
+- hfctmp->regs.int_drec--;
+ }
+
+-#ifndef RTAITIMING
+ DAHDI_IRQ_HANDLER(hfc_interrupt) {
+ struct hfc_card *hfctmp = dev_id;
+- unsigned long flags = 0;
+- unsigned char stat;
+-#else
+-static void hfc_service(struct hfc_card *hfctmp) {
+-#endif
++ struct hfc_card *hfctmp2;
+ struct dahdi_hfc *zthfc;
+- unsigned char s1, s2, l1state;
++ unsigned char stat, s1, s2, l1state;
++ unsigned long flags = 0;
++ unsigned long flags2 = 0;
+ int x;
+
+ if (!hfctmp) {
+-#ifndef RTAITIMING
+- return IRQ_NONE;
+-#else
+- /* rtai */
+- return;
+-#endif
++ return IRQ_NONE;
+ }
+
+ if (!hfctmp->pci_io) {
+ printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n",
+ __FUNCTION__);
+-#ifndef RTAITIMING
+ return IRQ_NONE;
+-#else
+- /* rtai */
+- return;
+-#endif
+ }
+
+- /* we assume a few things in this irq handler:
+- - the hfc-pci will only generate "timer" irqs (proc/non-proc)
+- - we need to use every 8th IRQ (to generate 1khz timing)
+- OR
+- - if we use rtai for timing the hfc-pci will not generate ANY irq,
+- instead rtai will call this "fake" irq with a 1khz realtime timer. :)
+- - rtai will directly service the card, not like it used to by triggering
+- the linux irq
+- */
+-
+-#ifndef RTAITIMING
+ spin_lock_irqsave(&hfctmp->lock, flags);
+ stat = hfc_inb(hfctmp, hfc_STATUS);
+-
+ if ((stat & hfc_STATUS_ANYINT) == 0) {
+ // maybe we are sharing the irq
+ spin_unlock_irqrestore(&hfctmp->lock,flags);
+ return IRQ_NONE;
+ }
+-#endif
+
+ s1 = hfc_inb(hfctmp, hfc_INT_S1);
+ s2 = hfc_inb(hfctmp, hfc_INT_S2);
+@@ -611,18 +457,10 @@
+ }
+ switch (l1state) {
+ case 3:
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d)", hfctmp->cardno, l1state);
+-#endif
+ break;
+ default:
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d)", hfctmp->cardno, l1state);
+-#endif
+ }
+ if (l1state == 2) {
+ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_ACTIVATE | hfc_STATES_DO_ACTION | hfc_STATES_NT_G2_G3);
+@@ -636,18 +474,10 @@
+ }
+ switch (l1state) {
+ case 7:
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d)", hfctmp->cardno, l1state);
+-#endif
+ break;
+ default:
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d)", hfctmp->cardno, l1state);
+-#endif
+ }
+ if (l1state == 3) {
+ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
+@@ -657,7 +487,7 @@
+ }
+ if (s1 & hfc_INTS_DREC) {
+ // D chan RX (bit 5)
+- hfctmp->regs.int_drec++;
++ hfctmp->regs.int_drec = 1;
+ // mr. zapata there is something for you!
+ // printk(KERN_CRIT "d chan rx\n");
+ }
+@@ -678,14 +508,10 @@
+ // B1 chan TX (bit 0)
+ }
+ }
+-#ifdef RTAITIMING
+- /* fake an irq */
+- s2 |= hfc_M2_PROC_TRANS;
+-#endif
+ if (s2 != 0) {
+ if (s2 & hfc_M2_PMESEL) {
+ // kaboom irq (bit 7)
+- printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n");
++ //printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n");
+ }
+ if (s2 & hfc_M2_GCI_MON_REC) {
+ // RxR monitor channel (bit 2)
+@@ -693,32 +519,31 @@
+ if (s2 & hfc_M2_GCI_I_CHG) {
+ // GCI I-change (bit 1)
+ }
+- if (s2 & hfc_M2_PROC_TRANS) {
++ if((s2&hfc_M2_PROC_TRANS)&&(hfctmp->cardno==timer_card)){
+ // processing/non-processing transition (bit 0)
+- hfctmp->ticks++;
+-#ifndef RTAITIMING
+- if (hfctmp->ticks > 7) {
+- // welcome to DAHDI timing :)
+-#endif
+- hfctmp->ticks = 0;
+-
+- if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
++ hfctmp2=hfctmp;
++ hfctmp=hfc_dev_list;
++ while(hfctmp){
++ if(hfctmp->active){
++ if(hfctmp!=hfctmp2)spin_lock_irqsave(&hfctmp->lock, flags2);
++ if(hfc_bch_check(hfctmp)){
++ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
+ // clear dchan buffer
++ // memset(hfctmp->drecbuf, 0x0, sizeof(hfctmp->drecbuf));
++
+ hfctmp->ztdev->chans[2].bytes2transmit = 0;
+ hfctmp->ztdev->chans[2].maxbytes2transmit = hfc_D_FIFO_SIZE;
+
+ dahdi_transmit(&(hfctmp->ztdev->span));
+
+- hfc_btrans(hfctmp,1);
+- hfc_btrans(hfctmp,2);
+- hfc_dtrans(hfctmp);
++ hfc_bch_tx(hfctmp);
++ hfc_dch_tx(hfctmp);
+ }
+
+- hfc_brec(hfctmp,1);
+- hfc_brec(hfctmp,2);
+- if (hfctmp->regs.int_drec > 0) {
++ hfc_bch_rx(hfctmp);
++ if (hfctmp->regs.int_drec) {
+ // dchan data to read
+- hfc_drec(hfctmp);
++ hfc_dch_rx(hfctmp);
+ if (hfctmp->ztdev->chans[2].bytes2receive > 0) {
+ if (debug) {
+ printk(KERN_CRIT "zaphfc: card %d RX [ ", hfctmp->cardno);
+@@ -743,17 +568,16 @@
+ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) {
+ dahdi_receive(&(hfctmp->ztdev->span));
+ }
+-
+-#ifndef RTAITIMING
+ }
+-#endif
++ if(hfctmp!=hfctmp2)spin_unlock_irqrestore(&hfctmp->lock,flags2);
++ }
++ hfctmp=hfctmp->next;
++ }
++ hfctmp=hfctmp2;
+ }
+-
+ }
+-#ifndef RTAITIMING
+ spin_unlock_irqrestore(&hfctmp->lock,flags);
+- return IRQ_RETVAL(1);
+-#endif
++ return IRQ_RETVAL(1);
+ }
+
+
+@@ -802,22 +626,22 @@
+ }
+ alreadyrunning = span->flags & DAHDI_FLAG_RUNNING;
+
+- if (!alreadyrunning) {
+- span->chans[2]->flags &= ~DAHDI_FLAG_HDLC;
+- span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN;
+-
+- span->flags |= DAHDI_FLAG_RUNNING;
++ if (alreadyrunning) return 0;
+
+- hfctmp->ticks = -2;
+- hfctmp->clicks = 0;
+- hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
+- hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
+- } else {
+- return 0;
+- }
++ span->chans[2]->flags &= ~DAHDI_FLAG_HDLC;
++ span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN;
++
++ span->flags |= DAHDI_FLAG_RUNNING;
++
++ hfctmp->ticks = -2;
++ hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
++ hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
++
++ hfc_bch_init(hfctmp);
+
+ // drivers, start engines!
+ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
++ hfctmp->active=1;
+ return 0;
+ }
+
+@@ -847,17 +671,9 @@
+
+ sprintf(zthfc->span.name, "ZTHFC%d", hfc_dev_count + 1);
+ if (hfctmp->regs.nt_mode == 1) {
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] [realtime]", hfc_dev_count + 1);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1);
+-#endif
+ } else {
+-#ifdef RTAITIMING
+- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] [realtime]", hfc_dev_count + 1);
+-#else
+ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1);
+-#endif
+ }
+
+ zthfc->span.spanconfig = zthfc_spanconfig;
+@@ -897,32 +713,6 @@
+ return 0;
+ }
+
+-#ifdef RTAITIMING
+-#define TICK_PERIOD 1000000
+-#define TICK_PERIOD2 1000000000
+-#define TASK_PRIORITY 1
+-#define STACK_SIZE 10000
+-
+-static RT_TASK rt_task;
+-static struct hfc_card *rtai_hfc_list[hfc_MAX_CARDS];
+-static unsigned char rtai_hfc_counter = 0;
+-
+-static void rtai_register_hfc(struct hfc_card *hfctmp) {
+- rtai_hfc_list[rtai_hfc_counter++] = hfctmp;
+-}
+-
+-static void rtai_loop(int t) {
+- int i=0;
+- for (;;) {
+- for (i=0; i < rtai_hfc_counter; i++) {
+- if (rtai_hfc_list[i] != NULL)
+- hfc_service(rtai_hfc_list[i]);
+- }
+- rt_task_wait_period();
+- }
+-}
+-#endif
+-
+ int hfc_findCards(int pcivendor, int pcidevice, char *vendor_name, char *card_name) {
+ struct pci_dev *tmp;
+ struct hfc_card *hfctmp = NULL;
+@@ -938,9 +728,9 @@
+ }
+ pci_set_master(tmp);
+
+- hfctmp = kmalloc(sizeof(struct hfc_card), GFP_KERNEL);
++ hfctmp = vmalloc(sizeof(struct hfc_card));
+ if (!hfctmp) {
+- printk(KERN_WARNING "zaphfc: unable to kmalloc!\n");
++ printk(KERN_WARNING "zaphfc: unable to vmalloc!\n");
+ pci_disable_device(tmp);
+ multi_hfc = NULL;
+ return -ENOMEM;
+@@ -948,6 +738,7 @@
+ memset(hfctmp, 0x0, sizeof(struct hfc_card));
+ spin_lock_init(&hfctmp->lock);
+
++ hfctmp->active=0;
+ hfctmp->pcidev = tmp;
+ hfctmp->pcibus = tmp->bus->number;
+ hfctmp->pcidevfn = tmp->devfn;
+@@ -961,49 +752,39 @@
+ hfctmp->pci_io = (char *) tmp->resource[1].start;
+ if (!hfctmp->pci_io) {
+ printk(KERN_WARNING "zaphfc: no iomem!\n");
+- kfree(hfctmp);
++ vfree(hfctmp);
+ pci_disable_device(tmp);
+ multi_hfc = NULL;
+ return -1;
+ }
+-
+- hfctmp->fifomem = kmalloc(65536, GFP_KERNEL);
+- if (!hfctmp->fifomem) {
+- printk(KERN_WARNING "zaphfc: unable to kmalloc fifomem!\n");
+- kfree(hfctmp);
++
++ hfctmp->fifos=(void *)__get_free_pages(GFP_KERNEL,log2(hfc_FIFO_MEM_SIZE_PAGES));
++ if (!hfctmp->fifos) {
++ printk(KERN_WARNING "zaphfc: unable to __get_free_pages fifomem!\n");
++ vfree(hfctmp);
+ pci_disable_device(tmp);
+ multi_hfc = NULL;
+ return -ENOMEM;
+ } else {
+- memset(hfctmp->fifomem, 0x0, 65536);
+- hfctmp->fifos = (void *)(((ulong) hfctmp->fifomem) & ~0x7FFF) + 0x8000;
+ pci_write_config_dword(hfctmp->pcidev, 0x80, (u_int) virt_to_bus(hfctmp->fifos));
+ hfctmp->pci_io = ioremap((ulong) hfctmp->pci_io, 256);
+ }
+
+-#ifdef RTAITIMING
+- /* we need no stinking irq */
+- hfctmp->irq = 0;
+-#else
+ if (request_irq(hfctmp->irq, &hfc_interrupt, DAHDI_IRQ_SHARED, "zaphfc", hfctmp)) {
+ printk(KERN_WARNING "zaphfc: unable to register irq\n");
+- kfree(hfctmp->fifomem);
+- kfree(hfctmp);
++ free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES));
++ vfree(hfctmp);
+ iounmap((void *) hfctmp->pci_io);
+ pci_disable_device(tmp);
+ multi_hfc = NULL;
+ return -EIO;
+ }
+-#endif
+
+-#ifdef RTAITIMING
+- rtai_register_hfc(hfctmp);
+-#endif
+ printk(KERN_INFO
+- "zaphfc: %s %s configured at mem %lx fifo %lx(%#x) IRQ %d HZ %d\n",
++ "zaphfc: %s %s configured at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
+ vendor_name, card_name,
+- (unsigned long) hfctmp->pci_io,
+- (unsigned long) hfctmp->fifos,
++ (u_int) hfctmp->pci_io,
++ (u_int) hfctmp->fifos,
+ (u_int) virt_to_bus(hfctmp->fifos),
+ hfctmp->irq, HZ);
+ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio
+@@ -1020,11 +801,21 @@
+ hfctmp->regs.nt_mode = 0;
+ }
+
+- zthfc = kmalloc(sizeof(struct dahdi_hfc),GFP_KERNEL);
++ if(sync_slave&(1<<hfc_dev_count)){
++ printk(KERN_INFO "zaphfc: Card %d configured for slave mode\n",hfc_dev_count);
++ hfctmp->regs.mst_mode=hfc_MST_MODE_SLAVE|hfc_MST_MODE_F0_LONG_DURATION;
++ hfctmp->regs.mst_emod=hfc_MST_EMOD_SLOW_CLOCK_ADJ;
++ }else{
++ printk(KERN_INFO "zaphfc: Card %d configured for master mode\n",hfc_dev_count);
++ hfctmp->regs.mst_mode=hfc_MST_MODE_MASTER|hfc_MST_MODE_F0_LONG_DURATION;
++ hfctmp->regs.mst_emod=0;
++ }
++
++ zthfc = vmalloc(sizeof(struct dahdi_hfc));
+ if (!zthfc) {
+- printk(KERN_CRIT "zaphfc: unable to kmalloc!\n");
++ printk(KERN_CRIT "zaphfc: unable to vmalloc!\n");
+ hfc_shutdownCard(hfctmp);
+- kfree(hfctmp);
++ vfree(hfctmp);
+ multi_hfc = NULL;
+ return -ENOMEM;
+ }
+@@ -1050,7 +841,6 @@
+ memset(hfctmp->btransbuf[1], 0x0, sizeof(hfctmp->btransbuf[1]));
+ hfctmp->ztdev->chans[1].writechunk = hfctmp->btransbuf[1];
+
+-
+ hfc_registerCard(hfctmp);
+ hfc_resetCard(hfctmp);
+ tmp = pci_get_device(pcivendor, pcidevice, multi_hfc);
+@@ -1058,58 +848,42 @@
+ return 0;
+ }
+
+-
+-
+ int init_module(void) {
+ int i = 0;
+-#ifdef RTAITIMING
+- RTIME tick_period;
+- for (i=0; i < hfc_MAX_CARDS; i++) {
+- rtai_hfc_list[i] = NULL;
++ if(jitterbuffer<1){
++ printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to minimum of 1\n",jitterbuffer);
++ jitterbuffer=1;
++ }else if(jitterbuffer>500){
++ printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to maximum of 500\n",jitterbuffer);
++ jitterbuffer=500;
+ }
+- rt_set_periodic_mode();
+-#endif
+- i = 0;
++ printk(KERN_INFO "zaphfc: jitterbuffer size: %d\n",jitterbuffer);
+ while (id_list[i].vendor_id) {
+ multi_hfc = NULL;
+ hfc_findCards(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_name, id_list[i].card_name);
+ i++;
+ }
+-#ifdef RTAITIMING
+- for (i=0; i < hfc_MAX_CARDS; i++) {
+- if (rtai_hfc_list[i]) {
+- printk(KERN_INFO
+- "zaphfc: configured %d at mem %#x fifo %#x(%#x) for realtime servicing\n",
+- rtai_hfc_list[i]->cardno,
+- (u_int) rtai_hfc_list[i]->pci_io,
+- (u_int) rtai_hfc_list[i]->fifos,
+- (u_int) virt_to_bus(rtai_hfc_list[i]->fifos));
+-
+- }
+- }
+- rt_task_init(&rt_task, rtai_loop, 1, STACK_SIZE, TASK_PRIORITY, 0, 0);
+- tick_period = start_rt_timer(nano2count(TICK_PERIOD));
+- rt_task_make_periodic(&rt_task, rt_get_time() + tick_period, tick_period);
+-#endif
+ printk(KERN_INFO "zaphfc: %d hfc-pci card(s) in this box.\n", hfc_dev_count);
+ return 0;
+ }
+
+ void cleanup_module(void) {
+ struct hfc_card *tmpcard;
+-#ifdef RTAITIMING
+- stop_rt_timer();
+- rt_task_delete(&rt_task);
+-#endif
++
+ printk(KERN_INFO "zaphfc: stop\n");
+ // spin_lock(&registerlock);
++ tmpcard=hfc_dev_list;
++ while(tmpcard){
++ hfc_shutdownCard1(tmpcard);
++ tmpcard=tmpcard->next;
++ }
+ while (hfc_dev_list != NULL) {
+ if (hfc_dev_list == NULL) break;
+- hfc_shutdownCard(hfc_dev_list);
++ hfc_shutdownCard2(hfc_dev_list);
+ tmpcard = hfc_dev_list;
+ hfc_dev_list = hfc_dev_list->next;
+ if (tmpcard != NULL) {
+- kfree(tmpcard);
++ vfree(tmpcard);
+ tmpcard = NULL;
+ printk(KERN_INFO "zaphfc: freed one card.\n");
+ }
+@@ -1119,8 +893,11 @@
+ #endif
+
+
+-module_param(modes, int, 0600);
++module_param(modes, int, 0400);
+ module_param(debug, int, 0600);
++module_param(sync_slave, int, 0400);
++module_param(timer_card, int, 0400);
++module_param(jitterbuffer, int, 0400);
+
+ MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver");
+ MODULE_AUTHOR("Klaus-Peter Junghanns <kpj@junghanns.net>");
diff --git a/main/dahdi-linux/APKBUILD b/main/dahdi-linux/APKBUILD
new file mode 100644
index 0000000000..632851ee13
--- /dev/null
+++ b/main/dahdi-linux/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+
+pkgname=dahdi-linux
+pkgver=2.4.1.2
+pkgrel=0
+pkgdesc="Firmware for Digium Asterisk Hardware Device Interface drivers"
+url="http://www.asterisk.org"
+arch="all"
+license="GPL"
+depends=
+# we need wget and tar because make install downloads firmware and uses fancy
+# options for tar and wget.
+makedepends="wget tar"
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.digium.com/pub/telephony/dahdi-linux/releases/$pkgname-$pkgver.tar.gz"
+
+# We online install the firmwares in this package since those are common for all
+# kernel flavors. We also install the headers for the -dev package.
+#
+# The kernel drivers themselves are built from separate build recipe.
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch ../*.diff; do
+ [ -f "$i" ] || continue
+ msg "Applying $i"
+ patch -p1 < $i || return 1;
+ done
+}
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" HOTPLUG_FIRMWARE=yes \
+ install-include install-firmware
+}
+
+md5sums="81b232a47693f4adac90c569e446f88f dahdi-linux-2.4.1.2.tar.gz"
diff --git a/main/dahdi-tools/APKBUILD b/main/dahdi-tools/APKBUILD
new file mode 100644
index 0000000000..6770d78e4b
--- /dev/null
+++ b/main/dahdi-tools/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=dahdi-tools
+pkgver=2.4.1
+pkgrel=0
+pkgdesc="Digium Asterisk Hardware Device Interface management utilities"
+url="http://www.asterisk.org"
+arch="all"
+license="GPL"
+depends="dahdi-linux"
+depends_dev="dahdi-linux-dev newt-dev"
+makedepends="dahdi-linux-dev perl newt-dev"
+install=
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://downloads.digium.com/pub/telephony/dahdi-tools/releases/$pkgname-$pkgver.tar.gz
+ $pkgname.initd"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ || return 1
+ sed -i -e 's/$(CC) $(LDFLAGS) -o $@ $^/$(CC) $^ $(LDFLAGS) -o $@/' \
+ Makefile
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/dahdi
+}
+
+md5sums="a06cf7c68b0b9fbb61f5804abd1a05e9 dahdi-tools-2.4.1.tar.gz
+d9702271dba6ff250f4d9a252f4dbf4c dahdi-tools.initd"
diff --git a/main/dahdi-tools/dahdi-tools.initd b/main/dahdi-tools/dahdi-tools.initd
new file mode 100644
index 0000000000..5e99122a5a
--- /dev/null
+++ b/main/dahdi-tools/dahdi-tools.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+
+conf=/etc/dahdi/system.conf
+
+depend() {
+ before asterisk
+ after hwdrivers modules
+ keyword novserver
+}
+
+start() {
+ ebegin "Starting dahdi"
+ /usr/sbin/dahdi_cfg
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping dahdi"
+ /usr/sbin/dahdi_cfg -s
+ eend $?
+}
diff --git a/main/damageproto/APKBUILD b/main/damageproto/APKBUILD
new file mode 100644
index 0000000000..aba84f41e7
--- /dev/null
+++ b/main/damageproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=damageproto
+pkgver=1.2.1
+pkgrel=0
+pkgdesc="X11 Damage extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="998e5904764b82642cc63d97b4ba9e95 damageproto-1.2.1.tar.bz2"
diff --git a/main/dansguardian/APKBUILD b/main/dansguardian/APKBUILD
new file mode 100644
index 0000000000..6d3b97f80c
--- /dev/null
+++ b/main/dansguardian/APKBUILD
@@ -0,0 +1,49 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dansguardian
+pkgver=2.10.1.1
+pkgrel=7
+pkgdesc="Web content filter"
+url="http://dansguardian.org"
+arch="all"
+license="GPL"
+depends="logrotate"
+makedepends="zlib-dev pcre-dev pkgconfig libiconv-dev"
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages="$pkgname-doc"
+source="http://dansguardian.org/downloads/2/Stable/$pkgname-$pkgver.tar.gz
+ dansguardian.initd
+ dansguardian.logrotate
+ ftp-credential.patch
+ dansguardian-2.10.1.1-gcc44.patch
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ patch -p1 -i ../ftp-credential.patch || return 1
+ patch -p1 -i ../dansguardian-2.10.1.1-gcc44.patch || return 1
+
+ # do not block "microsoft...clustimg=..." and similar
+ sed -e 's:\.\*:.{1,10}:g' configs/lists/bannedregexpurllist
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-proxyuser=dansguar \
+ --with-proxygroup=dansguar \
+ --with-logdir=/var/log/dansguardian \
+ --with-piddir=/var/run/ \
+ --enable-ntlm
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+ install -D -m 755 ../dansguardian.initd "$pkgdir"/etc/init.d/dansguardian
+ install -D -m 644 ../dansguardian.logrotate "$pkgdir"/etc/logrotate.d/dansguardian
+}
+
+md5sums="0987a1c9bfbdf398118386f10279611a dansguardian-2.10.1.1.tar.gz
+c307df7e0aba114cb6199bad48a0416a dansguardian.initd
+85b6de01c9508e8ceff5ebb55752f8d3 dansguardian.logrotate
+475c46026e8553181d293d5a4feaf6d9 ftp-credential.patch
+2c78b5c7346b8fcb3dee352e0c53cb5a dansguardian-2.10.1.1-gcc44.patch"
diff --git a/main/dansguardian/dansguardian-2.10.1.1-gcc44.patch b/main/dansguardian/dansguardian-2.10.1.1-gcc44.patch
new file mode 100644
index 0000000000..4ea4ff9ef6
--- /dev/null
+++ b/main/dansguardian/dansguardian-2.10.1.1-gcc44.patch
@@ -0,0 +1,37 @@
+diff -Nru dansguardian-2.10.1.1.orig/src/ConnectionHandler.cpp dansguardian-2.10.1.1/src/ConnectionHandler.cpp
+--- dansguardian-2.10.1.1.orig/src/ConnectionHandler.cpp 2009-02-25 12:36:22.000000000 +0100
++++ dansguardian-2.10.1.1/src/ConnectionHandler.cpp 2009-07-05 01:15:52.000000000 +0200
+@@ -44,6 +44,7 @@
+ #include <istream>
+
+ #ifdef ENABLE_ORIG_IP
++#include <limits.h>
+ #include <linux/types.h>
+ #include <linux/netfilter_ipv4.h>
+ #endif
+diff -Nru dansguardian-2.10.1.1.orig/src/downloadmanagers/fancy.cpp dansguardian-2.10.1.1/src/downloadmanagers/fancy.cpp
+--- dansguardian-2.10.1.1.orig/src/downloadmanagers/fancy.cpp 2008-11-18 12:27:04.000000000 +0100
++++ dansguardian-2.10.1.1/src/downloadmanagers/fancy.cpp 2009-07-05 01:15:12.000000000 +0200
+@@ -26,6 +26,7 @@
+ #include "../HTMLTemplate.hpp"
+ #include "../ConnectionHandler.hpp"
+
++#include <stdio.h>
+ #include <syslog.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+diff -Nru dansguardian-2.10.1.1.orig/src/String.cpp dansguardian-2.10.1.1/src/String.cpp
+--- dansguardian-2.10.1.1.orig/src/String.cpp 2009-01-16 11:44:28.000000000 +0100
++++ dansguardian-2.10.1.1/src/String.cpp 2009-07-05 01:15:12.000000000 +0200
+@@ -164,9 +164,9 @@
+ return 0;
+ off_t t = 0;
+ if (sizeof(off_t) == 4)
+- sscanf(this->c_str(), "%d", &t);
++ sscanf(this->c_str(), "%d", (long *)&t);
+ else if (sizeof(off_t) == 8)
+- sscanf(this->c_str(), "%lld", &t);
++ sscanf(this->c_str(), "%lld", (long long*)&t);
+ return t;
+ }
+
diff --git a/main/dansguardian/dansguardian.initd b/main/dansguardian/dansguardian.initd
new file mode 100644
index 0000000000..565c1632a7
--- /dev/null
+++ b/main/dansguardian/dansguardian.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-proxy/dansguardian/files/dansguardian.init,v 1.2 2005/12/08 22:15:11 mrness Exp $
+
+opts="{$opts} reload"
+
+depend() {
+ need net
+ after firewall
+ use dns \
+ squid apache2 bfilter mman junkbuster oops polipo privoxy tinyproxy wwwoffled
+}
+
+start() {
+ ebegin "Starting DansGuardian"
+ start-stop-daemon --start --quiet --pidfile /var/run/dansguardian.pid \
+ --exec /usr/sbin/dansguardian
+eend 0
+}
+
+stop() {
+ ebegin "Stopping DansGuardian"
+ start-stop-daemon --stop --quiet --pidfile /var/run/dansguardian.pid
+eend 0
+}
+
+reload() {
+ ebegin "Reloading DansGuardian"
+ /usr/sbin/dansguardian -g
+eend 0
+}
+
diff --git a/main/dansguardian/dansguardian.logrotate b/main/dansguardian/dansguardian.logrotate
new file mode 100644
index 0000000000..001d955450
--- /dev/null
+++ b/main/dansguardian/dansguardian.logrotate
@@ -0,0 +1,15 @@
+/var/log/dansguardian/*.log {
+ rotate 4
+ weekly
+ missingok
+ notifempty
+ nocreate
+ nocopy
+ nocopytruncate
+ compress
+
+ postrotate
+ /usr/sbin/dansguardian -r
+ endscript
+}
+
diff --git a/main/dansguardian/dansguardian.post-install b/main/dansguardian/dansguardian.post-install
new file mode 100644
index 0000000000..8d7feafb41
--- /dev/null
+++ b/main/dansguardian/dansguardian.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+chown dansguar:dansguar var/log/dansguardian
+exit 0
+
diff --git a/main/dansguardian/dansguardian.pre-install b/main/dansguardian/dansguardian.pre-install
new file mode 100644
index 0000000000..2d06f3a6f6
--- /dev/null
+++ b/main/dansguardian/dansguardian.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /var/log/dansguardian -s /bin/false -D dansguar 2>/dev/null
+exit 0
+
diff --git a/main/dansguardian/ftp-credential.patch b/main/dansguardian/ftp-credential.patch
new file mode 100644
index 0000000000..cfe472909a
--- /dev/null
+++ b/main/dansguardian/ftp-credential.patch
@@ -0,0 +1,41 @@
+If anyone is interested I updated the workaround ftp credential patch
+for 2.10.1.1. The previous one bombed on urls with email addresses in them.
+
+This one will probably bomb someplace else :)
+
+7/9/2009 ftp patch:
+
+--- a/src/HTTPHeader.cpp 2009-06-13 14:10:15.000000000 -0500
++++ b/src/HTTPHeader.cpp 2009-07-09 17:29:16.000000000 -0500
+@@ -402,7 +402,7 @@
+ // modifies the URL in all relevant header lines after a regexp search and replace
+ // setURL Code originally from from Ton Gorter 2004
+ void HTTPHeader::setURL(String &url) {
+- String hostname;
++ String hostname,credentials;
+ bool https = (url.before("://") == "https");
+ int port = (https ? 443 : 80);
+
+@@ -420,12 +420,18 @@
+ }
+ hostname = hostname.before(":"); // chop off the port bit
+ }
++ //Restore stripped credentials
++ credentials="";
++ if (header.front().after("://").before(hostname.toCharArray()).contains("@")) { // Contains a username:password combo
++ credentials = header.front().after("://").before(hostname.toCharArray());
++ }
++
+
+ #ifdef DGDEBUG
+ std::cout << "setURL: header.front() changed from: " << header.front() << std::endl;
+ #endif
+ if (!https)
+- header.front() = header.front().before(" ") + " " + url + " " + header.front().after(" ").after(" ");
++ header.front() = header.front().before(" ") + " " + url.before("://") + "://" + credentials + url.after("://") + " " + header.front().after(" ").after(" ");
+ else
+ // Should take form of "CONNECT example.com:443 HTTP/1.0" for SSL
+ header.front() = header.front().before(" ") + " " + hostname + ":" + String(port) + " " + header.front().after(" ").after(" ");
+
+
+
diff --git a/main/daq/APKBUILD b/main/daq/APKBUILD
new file mode 100644
index 0000000000..303c7359bb
--- /dev/null
+++ b/main/daq/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=daq
+pkgver=0.5
+pkgrel=1
+pkgdesc="Data Acquisition library - packet I/O library"
+url="http://www.snort.org/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="libpcap-dev flex bison"
+install=""
+subpackages="$pkgname-dev"
+source="http://www.snort.org/dl/snort-current/daq-$pkgver.tar.gz"
+
+_builddir="$srcdir"/daq-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/daq/*.la || return 1
+}
+
+md5sums="ea9d8147f39c44ce00dd2d7eb19ce0ea daq-0.5.tar.gz"
diff --git a/main/db/APKBUILD b/main/db/APKBUILD
new file mode 100644
index 0000000000..e245e03cb6
--- /dev/null
+++ b/main/db/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=db
+pkgver=5.1.25
+_ver=${pkgver}
+pkgrel=1
+pkgdesc="The Berkeley DB embedded database system 4.8"
+url="http://www.oracle.com/technology/software/products/berkeley-db/index.html"
+arch="all"
+license="custom"
+depends=
+makedepends=
+subpackages="$pkgname-dev $pkgname-doc"
+# Patches were found here:
+# http://www.oracle.com/technology/products/berkeley-db/db/update/4.7.25/patch.4.7.25.html
+source="http://download-uk.oracle.com/berkeley-db/db-$_ver.tar.gz
+ "
+
+build () {
+ cd "$srcdir"/db-$_ver
+ for i in ../patch.*; do
+ [ -r "$i" ] || continue
+ msg "Applying $i..."
+ patch -p0 < $i || return 1
+ done
+
+ cd build_unix
+ ../dist/configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --enable-compat185 \
+ --enable-shared \
+ --disable-static \
+ --disable-cxx
+ make LIBSO_LIBS=-lpthread || return 1
+}
+
+package() {
+ cd "$srcdir"/db-$_ver/build_unix
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ mkdir -p "$pkgdir"/usr/share/doc
+ mv "$pkgdir"/usr/docs "$pkgdir"/usr/share/doc/$pkgname
+
+ install -D -m644 "$srcdir"/db-$_ver/LICENSE \
+ "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="06656429bfc1abb6c0498eaeff70cd04 db-5.1.25.tar.gz"
diff --git a/main/db/patch.4.7.25.1 b/main/db/patch.4.7.25.1
new file mode 100644
index 0000000000..3c7e23ce07
--- /dev/null
+++ b/main/db/patch.4.7.25.1
@@ -0,0 +1,75 @@
+*** sequence/sequence.c.orig 2008-05-05 13:25:09.000000000 -0700
+--- sequence/sequence.c 2008-08-15 09:58:46.000000000 -0700
+***************
+*** 187,193 ****
+ if ((ret = __db_get_flags(dbp, &tflags)) != 0)
+ goto err;
+
+! if (DB_IS_READONLY(dbp)) {
+ ret = __db_rdonly(dbp->env, "DB_SEQUENCE->open");
+ goto err;
+ }
+--- 187,197 ----
+ if ((ret = __db_get_flags(dbp, &tflags)) != 0)
+ goto err;
+
+! /*
+! * We can let replication clients open sequences, but must
+! * check later that they do not update them.
+! */
+! if (F_ISSET(dbp, DB_AM_RDONLY)) {
+ ret = __db_rdonly(dbp->env, "DB_SEQUENCE->open");
+ goto err;
+ }
+***************
+*** 244,249 ****
+--- 248,258 ----
+ if ((ret != DB_NOTFOUND && ret != DB_KEYEMPTY) ||
+ !LF_ISSET(DB_CREATE))
+ goto err;
++ if (IS_REP_CLIENT(env) &&
++ !F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
++ ret = __db_rdonly(env, "DB_SEQUENCE->open");
++ goto err;
++ }
+ ret = 0;
+
+ rp = &seq->seq_record;
+***************
+*** 296,302 ****
+ */
+ rp = seq->seq_data.data;
+ if (rp->seq_version == DB_SEQUENCE_OLDVER) {
+! oldver: rp->seq_version = DB_SEQUENCE_VERSION;
+ if (!F_ISSET(env, ENV_LITTLEENDIAN)) {
+ if (IS_DB_AUTO_COMMIT(dbp, txn)) {
+ if ((ret =
+--- 305,316 ----
+ */
+ rp = seq->seq_data.data;
+ if (rp->seq_version == DB_SEQUENCE_OLDVER) {
+! oldver: if (IS_REP_CLIENT(env) &&
+! !F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
+! ret = __db_rdonly(env, "DB_SEQUENCE->open");
+! goto err;
+! }
+! rp->seq_version = DB_SEQUENCE_VERSION;
+ if (!F_ISSET(env, ENV_LITTLEENDIAN)) {
+ if (IS_DB_AUTO_COMMIT(dbp, txn)) {
+ if ((ret =
+***************
+*** 707,712 ****
+--- 721,733 ----
+
+ MUTEX_LOCK(env, seq->mtx_seq);
+
++ if (handle_check && IS_REP_CLIENT(env) &&
++ !F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
++ ret = __db_rdonly(env, "DB_SEQUENCE->get");
++ goto err;
++ }
++
++
+ if (rp->seq_min + delta > rp->seq_max) {
+ __db_errx(env, "Sequence overflow");
+ ret = EINVAL;
diff --git a/main/db/patch.4.7.25.2 b/main/db/patch.4.7.25.2
new file mode 100644
index 0000000000..1f42dcec71
--- /dev/null
+++ b/main/db/patch.4.7.25.2
@@ -0,0 +1,71 @@
+Index: lock/lock.c
+===================================================================
+RCS file: /a/CVSROOT/db/lock/lock.c,v
+retrieving revision 12.61
+diff -c -r12.61 lock.c
+*** lock/lock.c 22 Jul 2008 12:08:53 -0000 12.61
+--- lock/lock.c 19 Aug 2008 17:28:24 -0000
+***************
+*** 1278,1287 ****
+ SH_TAILQ_REMOVE(
+ &lt->obj_tab[obj_ndx], sh_obj, links, __db_lockobj);
+ if (sh_obj->lockobj.size > sizeof(sh_obj->objdata)) {
+! LOCK_REGION_LOCK(env);
+ __env_alloc_free(&lt->reginfo,
+ SH_DBT_PTR(&sh_obj->lockobj));
+! LOCK_REGION_UNLOCK(env);
+ }
+ SH_TAILQ_INSERT_HEAD(
+ &FREE_OBJS(lt, part_id), sh_obj, links, __db_lockobj);
+--- 1278,1289 ----
+ SH_TAILQ_REMOVE(
+ &lt->obj_tab[obj_ndx], sh_obj, links, __db_lockobj);
+ if (sh_obj->lockobj.size > sizeof(sh_obj->objdata)) {
+! if (region->part_t_size != 1)
+! LOCK_REGION_LOCK(env);
+ __env_alloc_free(&lt->reginfo,
+ SH_DBT_PTR(&sh_obj->lockobj));
+! if (region->part_t_size != 1)
+! LOCK_REGION_UNLOCK(env);
+ }
+ SH_TAILQ_INSERT_HEAD(
+ &FREE_OBJS(lt, part_id), sh_obj, links, __db_lockobj);
+***************
+*** 1470,1484 ****
+ if (obj->size <= sizeof(sh_obj->objdata))
+ p = sh_obj->objdata;
+ else {
+! LOCK_REGION_LOCK(env);
+ if ((ret =
+ __env_alloc(&lt->reginfo, obj->size, &p)) != 0) {
+ __db_errx(env,
+ "No space for lock object storage");
+! LOCK_REGION_UNLOCK(env);
+ goto err;
+ }
+! LOCK_REGION_UNLOCK(env);
+ }
+
+ memcpy(p, obj->data, obj->size);
+--- 1472,1492 ----
+ if (obj->size <= sizeof(sh_obj->objdata))
+ p = sh_obj->objdata;
+ else {
+! /*
+! * If we have only one partition, the region is locked.
+! */
+! if (region->part_t_size != 1)
+! LOCK_REGION_LOCK(env);
+ if ((ret =
+ __env_alloc(&lt->reginfo, obj->size, &p)) != 0) {
+ __db_errx(env,
+ "No space for lock object storage");
+! if (region->part_t_size != 1)
+! LOCK_REGION_UNLOCK(env);
+ goto err;
+ }
+! if (region->part_t_size != 1)
+! LOCK_REGION_UNLOCK(env);
+ }
+
+ memcpy(p, obj->data, obj->size);
diff --git a/main/db/patch.4.7.25.3 b/main/db/patch.4.7.25.3
new file mode 100644
index 0000000000..b58a43074f
--- /dev/null
+++ b/main/db/patch.4.7.25.3
@@ -0,0 +1,314 @@
+*** lock/lock_deadlock.c 2008-03-11 00:31:33.000000000 +1100
+--- lock/lock_deadlock.c 2008-12-16 21:54:18.000000000 +1100
+***************
+*** 121,127 ****
+ DB_LOCKTAB *lt;
+ db_timespec now;
+ locker_info *idmap;
+! u_int32_t *bitmap, *copymap, **deadp, **free_me, *tmpmap;
+ u_int32_t i, cid, keeper, killid, limit, nalloc, nlockers;
+ u_int32_t lock_max, txn_max;
+ int ret, status;
+--- 121,127 ----
+ DB_LOCKTAB *lt;
+ db_timespec now;
+ locker_info *idmap;
+! u_int32_t *bitmap, *copymap, **deadp, **deadlist, *tmpmap;
+ u_int32_t i, cid, keeper, killid, limit, nalloc, nlockers;
+ u_int32_t lock_max, txn_max;
+ int ret, status;
+***************
+*** 133,139 ****
+ if (IS_REP_CLIENT(env))
+ atype = DB_LOCK_MINWRITE;
+
+! free_me = NULL;
+
+ lt = env->lk_handle;
+ if (rejectp != NULL)
+--- 133,140 ----
+ if (IS_REP_CLIENT(env))
+ atype = DB_LOCK_MINWRITE;
+
+! copymap = tmpmap = NULL;
+! deadlist = NULL;
+
+ lt = env->lk_handle;
+ if (rejectp != NULL)
+***************
+*** 179,189 ****
+ memcpy(copymap, bitmap, nlockers * sizeof(u_int32_t) * nalloc);
+
+ if ((ret = __os_calloc(env, sizeof(u_int32_t), nalloc, &tmpmap)) != 0)
+! goto err1;
+
+ /* Find a deadlock. */
+ if ((ret =
+! __dd_find(env, bitmap, idmap, nlockers, nalloc, &deadp)) != 0)
+ return (ret);
+
+ /*
+--- 180,190 ----
+ memcpy(copymap, bitmap, nlockers * sizeof(u_int32_t) * nalloc);
+
+ if ((ret = __os_calloc(env, sizeof(u_int32_t), nalloc, &tmpmap)) != 0)
+! goto err;
+
+ /* Find a deadlock. */
+ if ((ret =
+! __dd_find(env, bitmap, idmap, nlockers, nalloc, &deadlist)) != 0)
+ return (ret);
+
+ /*
+***************
+*** 204,211 ****
+ txn_max = TXN_MAXIMUM;
+
+ killid = BAD_KILLID;
+! free_me = deadp;
+! for (; *deadp != NULL; deadp++) {
+ if (rejectp != NULL)
+ ++*rejectp;
+ killid = (u_int32_t)(*deadp - bitmap) / nalloc;
+--- 205,211 ----
+ txn_max = TXN_MAXIMUM;
+
+ killid = BAD_KILLID;
+! for (deadp = deadlist; *deadp != NULL; deadp++) {
+ if (rejectp != NULL)
+ ++*rejectp;
+ killid = (u_int32_t)(*deadp - bitmap) / nalloc;
+***************
+*** 342,352 ****
+ __db_msg(env,
+ "Aborting locker %lx", (u_long)idmap[killid].id);
+ }
+! __os_free(env, tmpmap);
+! err1: __os_free(env, copymap);
+!
+! err: if (free_me != NULL)
+! __os_free(env, free_me);
+ __os_free(env, bitmap);
+ __os_free(env, idmap);
+
+--- 342,353 ----
+ __db_msg(env,
+ "Aborting locker %lx", (u_long)idmap[killid].id);
+ }
+! err: if(copymap != NULL)
+! __os_free(env, copymap);
+! if (deadlist != NULL)
+! __os_free(env, deadlist);
+! if(tmpmap != NULL)
+! __os_free(env, tmpmap);
+ __os_free(env, bitmap);
+ __os_free(env, idmap);
+
+***************
+*** 360,365 ****
+--- 361,377 ----
+
+ #define DD_INVALID_ID ((u_int32_t) -1)
+
++ /*
++ * __dd_build --
++ * Build the lock dependency bit maps.
++ * Notes on syncronization:
++ * LOCK_SYSTEM_LOCK is used to hold objects locked when we have
++ * a single partition.
++ * LOCK_LOCKERS is held while we are walking the lockers list and
++ * to single thread the use of lockerp->dd_id.
++ * LOCK_DD protects the DD list of objects.
++ */
++
+ static int
+ __dd_build(env, atype, bmp, nlockers, allocp, idmap, rejectp)
+ ENV *env;
+***************
+*** 393,398 ****
+--- 405,411 ----
+ * In particular we do not build the conflict array and our caller
+ * needs to expect this.
+ */
++ LOCK_SYSTEM_LOCK(lt, region);
+ if (atype == DB_LOCK_EXPIRE) {
+ skip: LOCK_DD(env, region);
+ op = SH_TAILQ_FIRST(&region->dd_objs, __db_lockobj);
+***************
+*** 430,446 ****
+ OBJECT_UNLOCK(lt, region, indx);
+ }
+ UNLOCK_DD(env, region);
+ goto done;
+ }
+
+ /*
+! * We'll check how many lockers there are, add a few more in for
+! * good measure and then allocate all the structures. Then we'll
+! * verify that we have enough room when we go back in and get the
+! * mutex the second time.
+ */
+! retry: count = region->stat.st_nlockers;
+ if (count == 0) {
+ *nlockers = 0;
+ return (0);
+ }
+--- 443,460 ----
+ OBJECT_UNLOCK(lt, region, indx);
+ }
+ UNLOCK_DD(env, region);
++ LOCK_SYSTEM_UNLOCK(lt, region);
+ goto done;
+ }
+
+ /*
+! * Allocate after locking the region
+! * to make sure the structures are large enough.
+ */
+! LOCK_LOCKERS(env, region);
+! count = region->stat.st_nlockers;
+ if (count == 0) {
++ UNLOCK_LOCKERS(env, region);
+ *nlockers = 0;
+ return (0);
+ }
+***************
+*** 448,497 ****
+ if (FLD_ISSET(env->dbenv->verbose, DB_VERB_DEADLOCK))
+ __db_msg(env, "%lu lockers", (u_long)count);
+
+- count += 20;
+ nentries = (u_int32_t)DB_ALIGN(count, 32) / 32;
+
+! /*
+! * Allocate enough space for a count by count bitmap matrix.
+! *
+! * XXX
+! * We can probably save the malloc's between iterations just
+! * reallocing if necessary because count grew by too much.
+! */
+ if ((ret = __os_calloc(env, (size_t)count,
+! sizeof(u_int32_t) * nentries, &bitmap)) != 0)
+ return (ret);
+
+ if ((ret = __os_calloc(env,
+ sizeof(u_int32_t), nentries, &tmpmap)) != 0) {
+ __os_free(env, bitmap);
+ return (ret);
+ }
+
+ if ((ret = __os_calloc(env,
+ (size_t)count, sizeof(locker_info), &id_array)) != 0) {
+ __os_free(env, bitmap);
+ __os_free(env, tmpmap);
+ return (ret);
+ }
+
+ /*
+- * Now go back in and actually fill in the matrix.
+- */
+- if (region->stat.st_nlockers > count) {
+- __os_free(env, bitmap);
+- __os_free(env, tmpmap);
+- __os_free(env, id_array);
+- goto retry;
+- }
+-
+- /*
+ * First we go through and assign each locker a deadlock detector id.
+ */
+ id = 0;
+- LOCK_LOCKERS(env, region);
+ SH_TAILQ_FOREACH(lip, &region->lockers, ulinks, __db_locker) {
+ if (lip->master_locker == INVALID_ROFF) {
+ lip->dd_id = id++;
+ id_array[lip->dd_id].id = lip->id;
+ switch (atype) {
+--- 462,498 ----
+ if (FLD_ISSET(env->dbenv->verbose, DB_VERB_DEADLOCK))
+ __db_msg(env, "%lu lockers", (u_long)count);
+
+ nentries = (u_int32_t)DB_ALIGN(count, 32) / 32;
+
+! /* Allocate enough space for a count by count bitmap matrix. */
+ if ((ret = __os_calloc(env, (size_t)count,
+! sizeof(u_int32_t) * nentries, &bitmap)) != 0) {
+! UNLOCK_LOCKERS(env, region);
+ return (ret);
++ }
+
+ if ((ret = __os_calloc(env,
+ sizeof(u_int32_t), nentries, &tmpmap)) != 0) {
++ UNLOCK_LOCKERS(env, region);
+ __os_free(env, bitmap);
+ return (ret);
+ }
+
+ if ((ret = __os_calloc(env,
+ (size_t)count, sizeof(locker_info), &id_array)) != 0) {
++ UNLOCK_LOCKERS(env, region);
+ __os_free(env, bitmap);
+ __os_free(env, tmpmap);
+ return (ret);
+ }
+
+ /*
+ * First we go through and assign each locker a deadlock detector id.
+ */
+ id = 0;
+ SH_TAILQ_FOREACH(lip, &region->lockers, ulinks, __db_locker) {
+ if (lip->master_locker == INVALID_ROFF) {
++ DB_ASSERT(env, id < count);
+ lip->dd_id = id++;
+ id_array[lip->dd_id].id = lip->id;
+ switch (atype) {
+***************
+*** 510,516 ****
+ lip->dd_id = DD_INVALID_ID;
+
+ }
+- UNLOCK_LOCKERS(env, region);
+
+ /*
+ * We only need consider objects that have waiters, so we use
+--- 511,516 ----
+***************
+*** 669,675 ****
+ * status after building the bit maps so that we will not detect
+ * a blocked transaction without noting that it is already aborting.
+ */
+- LOCK_LOCKERS(env, region);
+ for (id = 0; id < count; id++) {
+ if (!id_array[id].valid)
+ continue;
+--- 669,674 ----
+***************
+*** 738,743 ****
+--- 737,743 ----
+ id_array[id].in_abort = 1;
+ }
+ UNLOCK_LOCKERS(env, region);
++ LOCK_SYSTEM_UNLOCK(lt, region);
+
+ /*
+ * Now we can release everything except the bitmap matrix that we
+***************
+*** 839,844 ****
+--- 839,845 ----
+ ret = 0;
+
+ /* We must lock so this locker cannot go away while we abort it. */
++ LOCK_SYSTEM_LOCK(lt, region);
+ LOCK_LOCKERS(env, region);
+
+ /*
+***************
+*** 895,900 ****
+--- 896,902 ----
+ done: OBJECT_UNLOCK(lt, region, info->last_ndx);
+ err:
+ out: UNLOCK_LOCKERS(env, region);
++ LOCK_SYSTEM_UNLOCK(lt, region);
+ return (ret);
+ }
+
diff --git a/main/db/patch.4.7.25.4 b/main/db/patch.4.7.25.4
new file mode 100644
index 0000000000..7a55340023
--- /dev/null
+++ b/main/db/patch.4.7.25.4
@@ -0,0 +1,183 @@
+*** dbinc/repmgr.h.orig 2009-05-04 10:33:55.000000000 -0400
+--- dbinc/repmgr.h 2009-05-04 10:27:26.000000000 -0400
+***************
+*** 374,379 ****
+--- 374,380 ----
+ #define SITE_FROM_EID(eid) (&db_rep->sites[eid])
+ #define EID_FROM_SITE(s) ((int)((s) - (&db_rep->sites[0])))
+ #define IS_VALID_EID(e) ((e) >= 0)
++ #define IS_KNOWN_REMOTE_SITE(e) ((e) >= 0 && ((u_int)(e)) < db_rep->site_cnt)
+ #define SELF_EID INT_MAX
+
+ #define IS_PEER_POLICY(p) ((p) == DB_REPMGR_ACKS_ALL_PEERS || \
+*** rep/rep_elect.c.orig 2009-05-04 10:35:50.000000000 -0400
+--- rep/rep_elect.c 2009-05-04 10:31:24.000000000 -0400
+***************
+*** 33,39 ****
+ static int __rep_fire_elected __P((ENV *, REP *, u_int32_t));
+ static void __rep_elect_master __P((ENV *, REP *));
+ static int __rep_tally __P((ENV *, REP *, int, u_int32_t *, u_int32_t, roff_t));
+! static int __rep_wait __P((ENV *, db_timeout_t *, int *, int, u_int32_t));
+
+ /*
+ * __rep_elect --
+--- 33,39 ----
+ static int __rep_fire_elected __P((ENV *, REP *, u_int32_t));
+ static void __rep_elect_master __P((ENV *, REP *));
+ static int __rep_tally __P((ENV *, REP *, int, u_int32_t *, u_int32_t, roff_t));
+! static int __rep_wait __P((ENV *, db_timeout_t *, int, u_int32_t));
+
+ /*
+ * __rep_elect --
+***************
+*** 55,61 ****
+ ENV *env;
+ LOG *lp;
+ REP *rep;
+! int done, eid, elected, full_elect, locked, in_progress, need_req;
+ int ret, send_vote, t_ret;
+ u_int32_t ack, ctlflags, egen, nsites, orig_tally, priority, realpri;
+ u_int32_t tiebreaker;
+--- 55,61 ----
+ ENV *env;
+ LOG *lp;
+ REP *rep;
+! int done, elected, full_elect, locked, in_progress, need_req;
+ int ret, send_vote, t_ret;
+ u_int32_t ack, ctlflags, egen, nsites, orig_tally, priority, realpri;
+ u_int32_t tiebreaker;
+***************
+*** 181,188 ****
+ REP_SYSTEM_UNLOCK(env);
+ (void)__rep_send_message(env, DB_EID_BROADCAST,
+ REP_MASTER_REQ, NULL, NULL, 0, 0);
+! ret = __rep_wait(env, &to, &eid,
+! 0, REP_F_EPHASE0);
+ REP_SYSTEM_LOCK(env);
+ F_CLR(rep, REP_F_EPHASE0);
+ switch (ret) {
+--- 181,187 ----
+ REP_SYSTEM_UNLOCK(env);
+ (void)__rep_send_message(env, DB_EID_BROADCAST,
+ REP_MASTER_REQ, NULL, NULL, 0, 0);
+! ret = __rep_wait(env, &to, 0, REP_F_EPHASE0);
+ REP_SYSTEM_LOCK(env);
+ F_CLR(rep, REP_F_EPHASE0);
+ switch (ret) {
+***************
+*** 286,296 ****
+ REP_SYSTEM_LOCK(env);
+ goto vote;
+ }
+! ret = __rep_wait(env, &to, &eid, full_elect, REP_F_EPHASE1);
+ switch (ret) {
+ case 0:
+ /* Check if election complete or phase complete. */
+! if (eid != DB_EID_INVALID && !IN_ELECTION(rep)) {
+ RPRINT(env, DB_VERB_REP_ELECT,
+ (env, "Ended election phase 1"));
+ goto edone;
+--- 285,295 ----
+ REP_SYSTEM_LOCK(env);
+ goto vote;
+ }
+! ret = __rep_wait(env, &to, full_elect, REP_F_EPHASE1);
+ switch (ret) {
+ case 0:
+ /* Check if election complete or phase complete. */
+! if (!IN_ELECTION(rep)) {
+ RPRINT(env, DB_VERB_REP_ELECT,
+ (env, "Ended election phase 1"));
+ goto edone;
+***************
+*** 398,412 ****
+ REP_SYSTEM_LOCK(env);
+ goto i_won;
+ }
+! ret = __rep_wait(env, &to, &eid, full_elect, REP_F_EPHASE2);
+ RPRINT(env, DB_VERB_REP_ELECT,
+ (env, "Ended election phase 2 %d", ret));
+ switch (ret) {
+ case 0:
+! if (eid != DB_EID_INVALID)
+! goto edone;
+! ret = DB_REP_UNAVAIL;
+! break;
+ case DB_REP_EGENCHG:
+ if (to > timeout)
+ to = timeout;
+--- 397,408 ----
+ REP_SYSTEM_LOCK(env);
+ goto i_won;
+ }
+! ret = __rep_wait(env, &to, full_elect, REP_F_EPHASE2);
+ RPRINT(env, DB_VERB_REP_ELECT,
+ (env, "Ended election phase 2 %d", ret));
+ switch (ret) {
+ case 0:
+! goto edone;
+ case DB_REP_EGENCHG:
+ if (to > timeout)
+ to = timeout;
+***************
+*** 1050,1062 ****
+ ENV *env;
+ REP *rep;
+ {
+- /*
+- * We often come through here twice, sometimes even more. We mustn't
+- * let the redundant calls affect stats counting. But rep_elect relies
+- * on this first part for setting eidp.
+- */
+- rep->master_id = rep->eid;
+-
+ if (F_ISSET(rep, REP_F_MASTERELECT | REP_F_MASTER)) {
+ /* We've been through here already; avoid double counting. */
+ return;
+--- 1046,1051 ----
+***************
+*** 1093,1102 ****
+ (timeout > 5000000) ? 500000 : ((timeout >= 10) ? timeout / 10 : 1);
+
+ static int
+! __rep_wait(env, timeoutp, eidp, full_elect, flags)
+ ENV *env;
+ db_timeout_t *timeoutp;
+! int *eidp, full_elect;
+ u_int32_t flags;
+ {
+ DB_REP *db_rep;
+--- 1082,1091 ----
+ (timeout > 5000000) ? 500000 : ((timeout >= 10) ? timeout / 10 : 1);
+
+ static int
+! __rep_wait(env, timeoutp, full_elect, flags)
+ ENV *env;
+ db_timeout_t *timeoutp;
+! int full_elect;
+ u_int32_t flags;
+ {
+ DB_REP *db_rep;
+***************
+*** 1174,1180 ****
+ F_CLR(rep, REP_F_EGENUPDATE);
+ ret = DB_REP_EGENCHG;
+ } else if (phase_over) {
+- *eidp = rep->master_id;
+ done = 1;
+ ret = 0;
+ }
+--- 1163,1168 ----
+*** repmgr/repmgr_net.c.orig 2009-05-04 10:34:46.000000000 -0400
+--- repmgr/repmgr_net.c 2009-05-04 10:27:26.000000000 -0400
+***************
+*** 100,105 ****
+--- 100,107 ----
+ control, rec, &nsites_sent, &npeers_sent)) != 0)
+ goto out;
+ } else {
++ DB_ASSERT(env, IS_KNOWN_REMOTE_SITE(eid));
++
+ /*
+ * If this is a request that can be sent anywhere, then see if
+ * we can send it to our peer (to save load on the master), but
diff --git a/main/dbus-glib/APKBUILD b/main/dbus-glib/APKBUILD
new file mode 100644
index 0000000000..849d19c3bd
--- /dev/null
+++ b/main/dbus-glib/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dbus-glib
+pkgver=0.92
+pkgrel=2
+pkgdesc="GLib bindings for DBUS"
+url="http://www.freedesktop.org/wiki/Software/DBusBindings"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig dbus-dev glib-dev libiconv-dev gettext-dev expat-dev"
+source="http://dbus.freedesktop.org/releases/$pkgname/$pkgname-$pkgver.tar.gz"
+depends_dev="glib-dev dbus-dev"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --enable-static=no \
+ --enable-bash-completion=no || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="b595b36890c4f9f8f5d5dec131c495f8 dbus-glib-0.92.tar.gz"
diff --git a/main/dbus/APKBUILD b/main/dbus/APKBUILD
new file mode 100644
index 0000000000..4b01961559
--- /dev/null
+++ b/main/dbus/APKBUILD
@@ -0,0 +1,45 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dbus
+pkgver=1.4.8
+pkgrel=1
+pkgdesc="Freedesktop.org message bus system"
+url="http://www.freedesktop.org/Software/dbus"
+pkggroups="messagebus"
+arch="all"
+license="GPL custom"
+subpackages="$pkgname-dev $pkgname-doc"
+triggers="$pkgname.trigger:/etc/dbus-1/system.d"
+depends=
+makedepends="expat-dev libx11-dev pkgconfig util-linux-ng-dev"
+depends_dev="util-linux-ng-dev"
+install="$pkgname.pre-install $pkgname.post-install"
+source="http://dbus.freedesktop.org/releases/dbus/dbus-$pkgver.tar.gz
+ $pkgname.initd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --with-xml=expat \
+ --with-dbus-user=messagebus \
+ --with-system-pid-file=/var/run/dbus.pid \
+ --disable-verbose-mode \
+ --disable-static \
+ --enable-inotify \
+ --disable-dnotify \
+ --disable-tests \
+ --disable-asserts \
+ --with-x || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm755 "$srcdir"/dbus.initd "$pkgdir"/etc/init.d/dbus
+}
+md5sums="e30253e15f0f4e6c5ee9e6f0eba5046c dbus-1.4.8.tar.gz
+58356b4db650a89312a670c02804c540 dbus.initd"
diff --git a/main/dbus/dbus.initd b/main/dbus/dbus.initd
new file mode 100644
index 0000000000..e96ea05cd1
--- /dev/null
+++ b/main/dbus/dbus.initd
@@ -0,0 +1,51 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/sys-apps/dbus/files/dbus.init-1.0,v 1.4 2007/04/04 13:35:25 cardoe Exp $
+
+opts="reload"
+
+depend() {
+ need localmount
+ after bootmisc
+}
+
+start() {
+ ebegin "Starting D-BUS system messagebus"
+
+ /usr/bin/dbus-uuidgen --ensure
+
+ # We need to test if /var/run/dbus exists, since script will fail if it does not
+ [ ! -e /var/run/dbus ] && mkdir /var/run/dbus
+
+ start-stop-daemon --start --pidfile /var/run/dbus.pid --exec /usr/bin/dbus-daemon -- --system
+ eend $?
+}
+
+stop() {
+ local retval
+
+ ebegin "Stopping D-BUS system messagebus"
+
+ start-stop-daemon --stop --pidfile /var/run/dbus.pid
+ retval=$?
+
+ eend ${retval}
+
+ [ -S /var/run/dbus/system_bus_socket ] && rm -f /var/run/dbus/system_bus_socket
+
+ return ${retval}
+}
+
+reload() {
+ local retval
+
+ ebegin "Reloading D-BUS messagebus config"
+
+ /usr/bin/dbus-send --print-reply --system --type=method_call \
+ --dest=org.freedesktop.DBus \
+ / org.freedesktop.DBus.ReloadConfig > /dev/null
+ retval=$?
+ eend ${retval}
+ return ${retval}
+}
diff --git a/main/dbus/dbus.post-install b/main/dbus/dbus.post-install
new file mode 100644
index 0000000000..305297a482
--- /dev/null
+++ b/main/dbus/dbus.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec dbus-uuidgen --ensure
diff --git a/main/dbus/dbus.pre-install b/main/dbus/dbus.pre-install
new file mode 100644
index 0000000000..91cde9c960
--- /dev/null
+++ b/main/dbus/dbus.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup messagebus 2>/dev/null
+adduser -H -h /dev/null -s /bin/false -D messagebus -G messagebus 2>/dev/null
+exit 0
diff --git a/main/dbus/dbus.trigger b/main/dbus/dbus.trigger
new file mode 100644
index 0000000000..a537bd8dfc
--- /dev/null
+++ b/main/dbus/dbus.trigger
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+dbus-send --system --type=method_call --dest=org.freedesktop.DBus / \
+ org.freedesktop.DBUS.ReloadConfig >/dev/null 2>&1 || :
diff --git a/main/dconf/0001-Avoid-posix_fallocate-so-it-works-on-uClibc.patch b/main/dconf/0001-Avoid-posix_fallocate-so-it-works-on-uClibc.patch
new file mode 100644
index 0000000000..5317b39c96
--- /dev/null
+++ b/main/dconf/0001-Avoid-posix_fallocate-so-it-works-on-uClibc.patch
@@ -0,0 +1,36 @@
+From e6d875ff19ba7f23e68a2131d9abe2de3f39d001 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Sat, 9 Oct 2010 20:34:08 +0000
+Subject: [PATCH] Avoid posix_fallocate() so it works on uClibc
+
+It seems like the possix_fallocate() does not need to be provided on
+all implementations (see "Application Usage" in
+http://www.opengroup.org/onlinepubs/009695399/functions/posix_fallocate.html )
+
+I'm not too familiar with the code but it looks like _DConfEngine->shm
+is a mmap to a file with 1 char size. If thats the case then something
+like this would work:
+---
+ engine/dconf-engine.c | 6 +++++-
+ 1 files changed, 5 insertions(+), 1 deletions(-)
+
+diff --git a/engine/dconf-engine.c b/engine/dconf-engine.c
+index cf57431..8eb3fa7 100644
+--- a/engine/dconf-engine.c
++++ b/engine/dconf-engine.c
+@@ -144,7 +144,11 @@ dconf_engine_setup_user (DConfEngine *engine)
+
+ if (fd >= 0)
+ {
+- if (posix_fallocate (fd, 0, 1) == 0)
++ struct stat st;
++ int r = fstat(fd, &st);
++ if (r == 0 && st.st_size == 0)
++ r = write(fd, "", 1);
++ if (r == 0)
+ {
+ engine->shm = mmap (NULL, 1, PROT_READ, MAP_SHARED, fd, 0);
+
+--
+1.7.3.1
+
diff --git a/main/dconf/APKBUILD b/main/dconf/APKBUILD
new file mode 100644
index 0000000000..812b03c7be
--- /dev/null
+++ b/main/dconf/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dconf
+pkgver=0.5.1
+pkgrel=0
+pkgdesc="A low-level configuration system."
+url="http://live.gnome.org/dconf"
+arch="all"
+license="LGPL2.1"
+depends=""
+makedepends="vala gobject-introspection-dev gtk+-dev glib-dev libxml2-dev"
+install=
+source="http://download.gnome.org/sources/dconf/0.5/dconf-$pkgver.tar.bz2
+ 0001-Avoid-posix_fallocate-so-it-works-on-uClibc.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ patch -p1 -i "$srcdir/$i" || return 1
+ ;;
+ esac
+ done
+}
+
+build ()
+{
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --libexecdir=/usr/lib/dconf
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="c905497d0255fe2ba58564f9655908ab dconf-0.5.1.tar.bz2
+750788f7fa6ff128ecdf7639ffff8b78 0001-Avoid-posix_fallocate-so-it-works-on-uClibc.patch"
diff --git a/main/debootstrap/APKBUILD b/main/debootstrap/APKBUILD
new file mode 100644
index 0000000000..246fc75074
--- /dev/null
+++ b/main/debootstrap/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=debootstrap
+pkgver=1.0.32
+pkgrel=0
+pkgdesc="Debian/Ubuntu bootstrap scripts"
+url="http://packages.qa.debian.org/d/debootstrap.html"
+arch="all"
+license="GPL-2"
+depends="dpkg"
+source="http://ftp.de.debian.org/debian/pool/main/d/debootstrap/debootstrap_$pkgver.tar.gz
+ pkgdetails.c"
+
+_builddir="$srcdir"/$pkgname
+build() {
+ cd "$_builddir"
+ gcc $CFLAGS $LDFLAGS -o pkgdetails "$srcdir"/pkgdetails.c
+}
+
+package() {
+ cd "$_builddir"
+ # create devices.tar.gz
+ rm -rf dev
+ mkdir -p dev
+ chown 0:0 dev
+ chmod 755 dev
+ ( cd dev
+ ln -s /proc/self/fd fd
+ ln -s fd/0 stdin
+ ln -s fd/1 stdout
+ ln -s fd/2 stderr
+ mknod full c 1 7
+ mknod null c 1 3
+ mknod ptmx c 5 2
+ mkdir pts shm
+ mknod random c 1 8
+ mknod tty c 5 0
+ mknod urandom c 1 9
+ mknod zero c 1 5
+ )
+ tar -czf devices.tar.gz dev
+ rm -rf dev
+ make DESTDIR="$pkgdir" install || return
+ install -Dm755 pkgdetails "$pkgdir"/usr/lib/debootstrap/pkgdetails
+}
+md5sums="3538ffa710f0d365dcbdc0dc18af2d4c debootstrap_1.0.32.tar.gz
+cff11c88c5176c0ccb714e2d378f4d35 pkgdetails.c"
diff --git a/main/debootstrap/pkgdetails.c b/main/debootstrap/pkgdetails.c
new file mode 100644
index 0000000000..8403afb4c8
--- /dev/null
+++ b/main/debootstrap/pkgdetails.c
@@ -0,0 +1,209 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define MAX_LINE 1000
+#define MAX_PKGS 100
+
+static char *fieldcpy(char *dst, char *fld) {
+ while (*fld && *fld != ':')
+ fld++;
+ if (!*(fld++))
+ return NULL;
+ while (isspace(*fld)) fld++;
+ return strcpy(dst, fld);
+}
+
+static void dogetdeps(char *pkgsfile, char **in_pkgs, int pkgc) {
+ char buf[MAX_LINE];
+ char cur_pkg[MAX_LINE];
+ char cur_deps[MAX_LINE];
+ char *pkgs[MAX_PKGS];
+ int i;
+ int skip;
+ FILE *f;
+
+ cur_pkg[0] = cur_deps[0] = '\0';
+
+ for (i = 0; i < pkgc; i++) pkgs[i] = in_pkgs[i];
+
+ f = fopen(pkgsfile, "r");
+ if (f == NULL) {
+ perror(pkgsfile);
+ exit(1);
+ }
+
+ skip = 1;
+ while (fgets(buf, sizeof(buf), f)) {
+ if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
+ if (strncasecmp(buf, "Package:", 8) == 0) {
+ skip = 1;
+ fieldcpy(cur_pkg, buf);
+ int any = 0;
+ for (i = 0; i < pkgc; i++) {
+ if (!pkgs[i]) continue;
+ any = 1;
+ if (strcmp(cur_pkg, pkgs[i]) == 0) {
+ skip = 0;
+ pkgs[i] = NULL;
+ break;
+ }
+ }
+ if (!any) break;
+ } else if (!skip &&
+ (strncasecmp(buf, "Depends:", 8) == 0 ||
+ strncasecmp(buf, "Pre-Depends:", 12) == 0))
+ {
+ char *pch;
+ fieldcpy(cur_deps, buf);
+ pch = cur_deps;
+ while (1) {
+ while (isspace(*pch)) pch++;
+ if (!*pch) break;
+
+ while (*pch && *pch != '(' && *pch != '|' && *pch != ','
+ && !isspace(*pch))
+ {
+ fputc(*pch++, stdout);
+ }
+ fputc('\n', stdout);
+ while (*pch && *pch++ != ',') (void)NULL;
+ }
+ }
+ }
+ fclose(f);
+}
+
+static void dopkgmirrorpkgs(int uniq, char *mirror, char *pkgsfile,
+ char *fieldname, char **in_pkgs, int pkgc)
+{
+ char buf[MAX_LINE];
+ char cur_field[MAX_LINE];
+ char cur_pkg[MAX_LINE];
+ char cur_ver[MAX_LINE];
+ char cur_arch[MAX_LINE];
+ char cur_size[MAX_LINE];
+ char cur_md5[MAX_LINE];
+ char cur_filename[MAX_LINE];
+ char *pkgs[MAX_PKGS];
+ int i;
+ FILE *f;
+
+ cur_pkg[0] = cur_ver[0] = cur_arch[0] = cur_filename[0] = '\0';
+
+ for (i = 0; i < pkgc; i++) pkgs[i] = in_pkgs[i];
+
+ f = fopen(pkgsfile, "r");
+ if (f == NULL) {
+ perror(pkgsfile);
+ exit(1);
+ }
+ while (fgets(buf, sizeof(buf), f)) {
+ if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
+ if (strncasecmp(buf, fieldname, strlen(fieldname)) == 0) {
+ fieldcpy(cur_field, buf);
+ }
+ if (strncasecmp(buf, "Package:", 8) == 0) {
+ fieldcpy(cur_pkg, buf);
+ } else if (strncasecmp(buf, "Version:", 8) == 0) {
+ fieldcpy(cur_ver, buf);
+ } else if (strncasecmp(buf, "Architecture:", 13) == 0) {
+ fieldcpy(cur_arch, buf);
+ } else if (strncasecmp(buf, "Size:", 5) == 0) {
+ fieldcpy(cur_size, buf);
+ } else if (strncasecmp(buf, "MD5sum:", 7) == 0) {
+ fieldcpy(cur_md5, buf);
+ } else if (strncasecmp(buf, "Filename:", 9) == 0) {
+ fieldcpy(cur_filename, buf);
+ } else if (!*buf) {
+ int any = 0;
+ for (i = 0; i < pkgc; i++) {
+ if (!pkgs[i]) continue;
+ any = 1;
+ if (strcmp(cur_field, pkgs[i]) == 0) {
+ printf("%s %s %s %s %s %s %s\n", cur_pkg, cur_ver, cur_arch, mirror, cur_filename, cur_md5, cur_size);
+ if (uniq) pkgs[i] = NULL;
+ break;
+ }
+ }
+ if (!any) break;
+ }
+ }
+ fclose(f);
+
+ /* any that weren't found are returned as "pkg -" */
+ if (uniq) {
+ for (i = 0; i < pkgc; i++) {
+ if (pkgs[i]) {
+ printf("%s -\n", pkgs[i]);
+ }
+ }
+ }
+}
+
+static int dotranslatewgetpercent(int low, int high, int end, char *str) {
+ int ch;
+ int val, lastval;
+
+ /* print out anything that looks like a % on its own line, appropriately
+ * scaled */
+
+ lastval = val = 0;
+ while ( (ch = getchar()) != EOF ) {
+ if (isdigit(ch)) {
+ val *= 10; val += ch - '0';
+ } else if (ch == '%') {
+ float f = (float) val / 100.0 * (high - low) + low;
+ if (str) {
+ printf("P: %d %d %s\n", (int) f, end, str);
+ } else {
+ printf("P: %d %d\n", (int) f, end);
+ }
+ lastval = val;
+ } else {
+ val = 0;
+ }
+ }
+ return lastval == 100;
+}
+
+int main(int argc, char *argv[]) {
+ if ((argc == 6 || argc == 5) && strcmp(argv[1], "WGET%") == 0) {
+ if (dotranslatewgetpercent(atoi(argv[2]), atoi(argv[3]),
+ atoi(argv[4]), argc == 6 ? argv[5] : NULL))
+ {
+ exit(0);
+ } else {
+ exit(1);
+ }
+ } else if (argc >= 4 && strcmp(argv[1], "GETDEPS") == 0) {
+ int i;
+ for (i = 3; argc - i > MAX_PKGS; i += MAX_PKGS) {
+ dogetdeps(argv[2], argv+i, MAX_PKGS);
+ }
+ dogetdeps(argv[2], argv+i, argc-i);
+ exit(0);
+ } else if (argc >= 5 && strcmp(argv[1], "PKGS") == 0) {
+ int i;
+ for (i = 4; argc - i > MAX_PKGS; i += MAX_PKGS) {
+ dopkgmirrorpkgs(1, argv[2], argv[3], "Package:", argv+i, MAX_PKGS);
+ }
+ dopkgmirrorpkgs(1, argv[2], argv[3], "Package:", argv+i, argc-i);
+ exit(0);
+ } else if (argc >= 6 && strcmp(argv[1], "FIELD") == 0) {
+ int i;
+ for (i = 5; argc - i > MAX_PKGS; i += MAX_PKGS) {
+ dopkgmirrorpkgs(0, argv[3], argv[4], argv[2], argv+i, MAX_PKGS);
+ }
+ dopkgmirrorpkgs(0, argv[3], argv[4], argv[2], argv+i, argc-i);
+ exit(0);
+ } else {
+ fprintf(stderr, "usage: %s PKGS mirror packagesfile pkgs..\n", argv[0]);
+ fprintf(stderr, " or: %s FIELD field mirror packagesfile pkgs..\n",
+ argv[0]);
+ fprintf(stderr, " or: %s GETDEPS packagesfile pkgs..\n", argv[0]);
+ fprintf(stderr, " or: %s WGET%% low high end reason\n", argv[0]);
+ exit(1);
+ }
+}
diff --git a/main/desktop-file-utils/APKBUILD b/main/desktop-file-utils/APKBUILD
new file mode 100644
index 0000000000..9a74a7f210
--- /dev/null
+++ b/main/desktop-file-utils/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=desktop-file-utils
+pkgver=0.18
+pkgrel=0
+pkgdesc="Command line utilities for working with desktop entries"
+url="http://www.freedesktop.org/wiki/Software/desktop-file-utils"
+arch="all"
+license="GPL"
+depends=
+makedepends="glib-dev libiconv-dev gettext-dev pkgconfig"
+triggers="$pkgname.trigger:/usr/share/applications"
+source="http://www.freedesktop.org/software/$pkgname/releases/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/desktop-file-utils-$pkgver
+
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/desktop-file-utils-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="d966b743eb394650f98d5dd56b9aece1 desktop-file-utils-0.18.tar.bz2"
diff --git a/main/desktop-file-utils/desktop-file-utils.trigger b/main/desktop-file-utils/desktop-file-utils.trigger
new file mode 100644
index 0000000000..0400e9a2b9
--- /dev/null
+++ b/main/desktop-file-utils/desktop-file-utils.trigger
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+update-desktop-database -q
diff --git a/main/dhcp/APKBUILD b/main/dhcp/APKBUILD
new file mode 100644
index 0000000000..94f7f9c1dc
--- /dev/null
+++ b/main/dhcp/APKBUILD
@@ -0,0 +1,84 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dhcp
+pkgver=4.2.1_p1
+_realver=${pkgver/_p/-P}
+pkgrel=1
+pkgdesc="ISC Dynamic Host Configuration Protocol (DHCP)"
+url="https://www.isc.org/"
+arch="all"
+license="ISC"
+depends=
+makedepends="perl"
+install="dhcp.pre-install dhcp.post-install dhcp.pre-upgrade dhcp.post-upgrade"
+subpackages="$pkgname-doc $pkgname-dev dhclient dhcrelay"
+source="http://ftp.isc.org/isc/dhcp/$pkgname-$_realver.tar.gz
+ linux_ipv6_discover.patch
+ dhcp-3.0-fix-perms.patch
+ dhcrelay.initd
+ dhcrelay.confd
+ dhcpd.confd
+ dhcpd.initd"
+
+prepare() {
+ cd "$srcdir/$pkgname-$_realver"
+ patch -p1 -i "$srcdir"/dhcp-3.0-fix-perms.patch || return 1
+ # patch -p1 -i ../linux_ipv6_discover.patch || return 1
+}
+
+build() {
+ cd "$srcdir/$pkgname-$_realver"
+ # fix ipv6
+ export CFLAGS="$CFLAGS -D_GNU_SOURCE"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/dhcp \
+ --with-cli-pid-file=/var/run/dhcp/dhclient.pid \
+ --with-cli-lease-file=/var/lib/dhcp/dhclient.leases \
+ --with-srv-pid-file=/var/run/dhcp/dhcpd.pid \
+ --with-srv-lease-file=/var/lib/dhcp/dhcpd.leases \
+ --with-relay-pid-file=/var/run/dhcp/dhcrelay.pid \
+ --enable-dhcpv6 \
+ --enable-paranoia \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$_realver"
+ make DESTDIR="$pkgdir" install
+
+ install -m755 -D "$srcdir"/dhcpd.initd "$pkgdir"/etc/init.d/dhcpd
+ install -m644 -D "$srcdir"/dhcpd.confd "$pkgdir"/etc/conf.d/dhcpd
+ install -d "$pkgdir"/var/lib/dhcp
+ install -d "$pkgdir"/var/run/dhcp
+}
+
+dhclient() {
+ pkgdesc="ISC dhcp client"
+ install -d "$subpkgdir"/var/lib/dhcp
+ install -d "$subpkgdir"/var/run/dhcp
+ install -d "$subpkgdir"/usr/sbin
+ install -d "$subpkgdir"/etc/dhcp
+ mv "$pkgdir"/usr/sbin/dhclient "$subpkgdir"/usr/sbin/
+ mv "$pkgdir"/etc/dhcp/dhclient.conf "$subpkgdir"/etc/dhcp/
+}
+
+dhcrelay() {
+ pkgdesc="ISC dhcp relay server"
+ replaces="dhcp"
+ install -d "$pkgdir"/var/run/dhcp
+ install -d "$subpkgdir"/usr/sbin
+ mv "$pkgdir"/usr/sbin/dhcrelay "$subpkgdir"/usr/sbin/
+ install -m755 -D "$srcdir"/dhcrelay.initd \
+ "$subpkgdir"/etc/init.d/dhcrelay
+ install -m644 -D "$srcdir"/dhcrelay.confd \
+ "$subpkgdir"/etc/conf.d/dhcrelay
+}
+
+md5sums="22e6f1eff6d5cfe2621a06cc62ba5b70 dhcp-4.2.1-P1.tar.gz
+37abf1fb047a353e91b022fafdabf39a linux_ipv6_discover.patch
+a9eaf182dae3984670da52f20ae10fba dhcp-3.0-fix-perms.patch
+1597c012bb1a2c0828254c87f0a904ad dhcrelay.initd
+db84514fe15fd7d81136afbaae738f55 dhcrelay.confd
+df32707f5bbe5363306420b5dc6e6b40 dhcpd.confd
+be2259371681bd4ab8a577b1b1a989ae dhcpd.initd"
diff --git a/main/dhcp/dhcp-3.0-fix-perms.patch b/main/dhcp/dhcp-3.0-fix-perms.patch
new file mode 100644
index 0000000000..78725c2c79
--- /dev/null
+++ b/main/dhcp/dhcp-3.0-fix-perms.patch
@@ -0,0 +1,15 @@
+--- a/server/dhcpd.c 2003-11-05 14:08:09.000000000 -0800
++++ b/server/dhcpd.c 2003-11-05 14:15:32.000000000 -0800
+@@ -602,6 +602,12 @@
+ if (lftest)
+ exit (0);
+
++#if defined (PARANOIA)
++ /* Set proper permissions... */
++ if (lchown (path_dhcpd_db, set_uid, set_gid))
++ log_fatal ("lchown(%s, %d, %d): %m", path_dhcpd_db, (int) set_uid, (int) set_gid);
++#endif /* PARANOIA */
++
+ /* Discover all the network interfaces and initialize them. */
+ discover_interfaces (DISCOVER_SERVER);
+
diff --git a/main/dhcp/dhcp.post-install b/main/dhcp/dhcp.post-install
new file mode 100644
index 0000000000..01195dbd34
--- /dev/null
+++ b/main/dhcp/dhcp.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+chown dhcp:dhcp var/run/dhcp var/lib/dhcp
+exit 0
+
diff --git a/main/dhcp/dhcp.post-upgrade b/main/dhcp/dhcp.post-upgrade
new file mode 100644
index 0000000000..19df74a47b
--- /dev/null
+++ b/main/dhcp/dhcp.post-upgrade
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# we have renamed dhcp to dhcpd. Try cleanup for users
+
+moved=
+for i in /etc/runlevel/*/dhcp; do
+ if [ -L "$i" ]; then
+ rm $i
+ ln -s /etc/init.d/clamsmtpd ${i}d
+ moved=1
+ fi
+done
+
+if [ -n "$moved" ]; then
+ echo " *"
+ echo " * NOTICE: the /etc/init.d/dhcp script have been renamed to /etc/init.d/dhcpd"
+ echo " *"
+fi
+
diff --git a/main/dhcp/dhcp.pre-install b/main/dhcp/dhcp.pre-install
new file mode 100644
index 0000000000..9c623bfb9e
--- /dev/null
+++ b/main/dhcp/dhcp.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /var/lib/dhcp -s /bin/false -D dhcp 2>/dev/null
+exit 0
+
diff --git a/main/dhcp/dhcp.pre-upgrade b/main/dhcp/dhcp.pre-upgrade
new file mode 100644
index 0000000000..090f654b9a
--- /dev/null
+++ b/main/dhcp/dhcp.pre-upgrade
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# script renamed. Try save users settings if needed
+
+if [ -f /etc/conf.d/dhcp ] && [ ! -f /etc/conf.d/dhcpd ]; then
+ mv /etc/conf.d/dhcp /etc/conf.d/dhcpd
+fi
+
diff --git a/main/dhcp/dhcpd.confd b/main/dhcp/dhcpd.confd
new file mode 100644
index 0000000000..df09ec7082
--- /dev/null
+++ b/main/dhcp/dhcpd.confd
@@ -0,0 +1,30 @@
+# /etc/conf.d/dhcpd: config file for /etc/init.d/dhcpd
+
+# If you require more than one instance of dhcpd you can create symbolic
+# links to dhcpd service like so
+# cd /etc/init.d
+# ln -s dhcpd dhcpd.foo
+# cd ../conf.d
+# cp dhcpd dhcpd.foo
+# Now you can edit dhcpd.foo and specify a different configuration file.
+# You'll also need to specify a pidfile in that dhcpd.conf file.
+# See the pid-file-name option in the dhcpd.conf man page for details.
+
+# If you wish to run dhcpd in a chroot, uncomment the following line
+# DHCPD_CHROOT="/chroot/dhcp"
+
+# Then run emerge dhcp --config
+# All file paths below are relative to the chroot.
+# You can specify a different chroot directory but MAKE SURE it's empty.
+
+# Specify a configuration file - the default is /etc/dhcp/dhcpd.conf
+# DHCPD_CONF="/etc/dhcp/dhcpd.conf"
+
+# Configure which interface or interfaces to for dhcpd to listen on.
+# List all interfaces space separated. If this is not specified then
+# we listen on all interfaces.
+# DHCPD_IFACE=""
+
+# Insert any other dhcpd options - see the man page for a full list.
+# DHCPD_OPTS=""
+
diff --git a/main/dhcp/dhcpd.initd b/main/dhcp/dhcpd.initd
new file mode 100644
index 0000000000..447578c907
--- /dev/null
+++ b/main/dhcp/dhcpd.initd
@@ -0,0 +1,95 @@
+#!/sbin/runscript
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/dhcp/files/dhcpd.init2,v 1.1 2009/07/09 14:45:22 chainsaw Exp $
+
+opts="configtest"
+
+DHCPD_CONF=${DHCPD_CONF:-/etc/dhcp/dhcpd.conf}
+
+depend() {
+ need net
+ after firewall
+ use logger dns
+}
+
+get_var() {
+ sed -n 's/^[[:blank:]]\?'"$1"' "*\([^#";]\+\).*/\1/p' \
+ "${DHCPD_CHROOT}/${DHCPD_CONF}"
+}
+
+checkconfig() {
+ /usr/sbin/dhcpd -cf ${DHCPD_CHROOT}/${DHCPD_CONF} -t 1>/dev/null 2>&1
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ eerror "${SVCNAME} has detected a syntax error in your configuration files:"
+ /usr/sbin/dhcpd -cf ${DHCPD_CHROOT}/${DHCPD_CONF} -t
+ fi
+
+ return $ret
+}
+
+configtest() {
+ ebegin "Checking ${SVCNAME} configuration"
+ checkconfig
+ eend $?
+}
+
+start() {
+ # Work out our cffile if it's on our DHCPD_OPTS
+ case " ${DHCPD_OPTS} " in
+ *" -cf "*)
+ DHCPD_CONF=" ${DHCPD_OPTS} "
+ DHCPD_CONF="${DHCPD_CONF##* -cf }"
+ DHCPD_CONF="${DHCPD_CONF%% *}"
+ ;;
+ *) DHCPD_OPTS="${DHCPD_OPTS} -cf ${DHCPD_CONF}"
+ ;;
+ esac
+
+ if [ ! -f "${DHCPD_CHROOT}/${DHCPD_CONF}" ] ; then
+ eerror "${DHCPD_CHROOT}/${DHCPD_CONF} does not exist"
+ return 1
+ fi
+
+ checkconfig || return 1
+
+ local leasefile="$(get_var lease-file-name)"
+ leasefile="${DHCPD_CHROOT}/${leasefile:-/var/lib/dhcp/dhcpd.leases}"
+ if [ ! -f "${leasefile}" ] ; then
+ ebegin "Creating ${leasefile}"
+ touch "${leasefile}"
+ chown dhcp:dhcp "${leasefile}"
+ eend $? || return 1
+ fi
+
+ # Setup LD_PRELOAD so name resolution works in our chroot.
+ if [ -n "${DHCPD_CHROOT}" ] ; then
+ LD_PRELOAD="${LD_PRELOAD} /usr/lib/libresolv.so"
+ export LD_PRELOAD="${LD_PRELOAD} /usr/lib/libnss_dns.so"
+ fi
+
+ local pidfile="$(get_var pid-file-name)"
+ pidfile="${pidfile:-/var/run/dhcp/dhcpd.pid}"
+
+ ebegin "Starting ${DHCPD_CHROOT:+chrooted }${SVCNAME}"
+ start-stop-daemon --start --exec /usr/sbin/dhcpd \
+ --pidfile "${DHCPD_CHROOT}/${pidfile}" \
+ -- ${DHCPD_OPTS} -q -pf "${pidfile}" \
+ -user dhcp -group dhcp \
+ ${DHCPD_CHROOT:+-chroot} ${DHCPD_CHROOT} ${DHCPD_IFACE}
+ eend $? \
+ && save_options chroot "${DHCPD_CHROOT}" \
+ && save_options pidfile "${pidfile}"
+}
+
+stop() {
+ local chroot="$(get_options chroot)"
+
+ checkconfig || return 1
+
+ ebegin "Stopping ${chroot:+chrooted }${SVCNAME}"
+ start-stop-daemon --stop --exec /usr/sbin/dhcpd \
+ --pidfile "${chroot}/$(get_options pidfile)"
+ eend $?
+}
diff --git a/main/dhcp/dhcrelay.confd b/main/dhcp/dhcrelay.confd
new file mode 100644
index 0000000000..1102d3a41b
--- /dev/null
+++ b/main/dhcp/dhcrelay.confd
@@ -0,0 +1,13 @@
+# /etc/conf.d/dhcrelay: config file for /etc/init.d/dhcrelay
+
+# Configure which interface or interfaces to for dhcrelay to listen on
+# and send to.
+# List all interfaces space separated. If this is not specified then
+# we use all interfaces.
+#IFACE=""
+
+# Insert any other options needed. See dhcrelay(8) for details.
+#DHCRELAY_OPTS=""
+
+# Space separated list of IPs to forward BOOTP/DHCP packets to.
+DHCRELAY_SERVERS=""
diff --git a/main/dhcp/dhcrelay.initd b/main/dhcp/dhcrelay.initd
new file mode 100644
index 0000000000..2be915f313
--- /dev/null
+++ b/main/dhcp/dhcrelay.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/dhcp/files/dhcrelay.init,v 1.2 2007/03/22 15:36:59 uberlord Exp $
+
+depend() {
+ need net
+ use logger
+ after firewall
+}
+
+start() {
+ if [ -z "${DHCRELAY_SERVERS}" ]; then
+ eerror "No DHCRELAY_SERVERS specified in /etc/conf.d/dhcrelay"
+ return 1
+ fi
+
+ local IFACES= i=
+ for i in ${IFACE} ; do
+ IFACES="${IFACES} -i ${i}"
+ done
+
+ ebegin "Starting dhcrelay"
+ start-stop-daemon --start --exec /usr/sbin/dhcrelay \
+ -- -q ${IFACES} ${DHCRELAY_OPTS} ${DHCRELAY_SERVERS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping dhcrelay"
+ start-stop-daemon --stop --pidfile /var/run/dhcp/dhcrelay.pid
+ eend $?
+}
diff --git a/main/dhcp/linux_ipv6_discover.patch b/main/dhcp/linux_ipv6_discover.patch
new file mode 100644
index 0000000000..ebf3865e6a
--- /dev/null
+++ b/main/dhcp/linux_ipv6_discover.patch
@@ -0,0 +1,50 @@
+diff -Naur dhcp-4.1.0a2/common/discover.c dhcp-4.1.0a2-mcn/common/discover.c
+--- dhcp-4.1.0a2/common/discover.c 2008-08-29 18:48:57.000000000 +0100
++++ dhcp-4.1.0a2-mcn/common/discover.c 2008-10-02 13:02:06.000000000 +0100
+@@ -443,15 +443,17 @@
+ }
+
+ #ifdef DHCPv6
+- ifaces->fp6 = fopen("/proc/net/if_inet6", "r");
+- if (ifaces->fp6 == NULL) {
+- log_error("Error opening '/proc/net/if_inet6' to "
+- "list IPv6 interfaces; %m");
+- close(ifaces->sock);
+- ifaces->sock = -1;
+- fclose(ifaces->fp);
+- ifaces->fp = NULL;
+- return 0;
++ if (local_family == AF_INET6) {
++ ifaces->fp6 = fopen("/proc/net/if_inet6", "r");
++ if (ifaces->fp6 == NULL) {
++ log_error("Error opening '/proc/net/if_inet6' to "
++ "list IPv6 interfaces; %m");
++ close(ifaces->sock);
++ ifaces->sock = -1;
++ fclose(ifaces->fp);
++ ifaces->fp = NULL;
++ return 0;
++ }
+ }
+ #endif
+
+@@ -720,7 +722,8 @@
+ }
+ #ifdef DHCPv6
+ if (!(*err)) {
+- return next_iface6(info, err, ifaces);
++ if (local_family == AF_INET6)
++ return next_iface6(info, err, ifaces);
+ }
+ #endif
+ return 0;
+@@ -736,7 +739,8 @@
+ close(ifaces->sock);
+ ifaces->sock = -1;
+ #ifdef DHCPv6
+- fclose(ifaces->fp6);
++ if (local_family == AF_INET6)
++ fclose(ifaces->fp6);
+ ifaces->fp6 = NULL;
+ #endif
+ }
diff --git a/main/dhcpcd-dbus/APKBUILD b/main/dhcpcd-dbus/APKBUILD
new file mode 100644
index 0000000000..848f5036e8
--- /dev/null
+++ b/main/dhcpcd-dbus/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dhcpcd-dbus
+pkgver=0.5.2
+pkgrel=1
+pkgdesc="DBUS binding to dhcpcd"
+url="http://roy.marples.name/projects/dhcpcd-dbus"
+arch="all"
+license="BSD"
+depends=""
+makedepends="dbus-dev pkgconfig"
+install=
+subpackages=
+source="http://roy.marples.name/downloads/dhcpcd/dhcpcd-dbus-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/$pkgname \
+ || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="29ab75851bc907d698add2087b0d28d3 dhcpcd-dbus-0.5.2.tar.bz2"
diff --git a/main/dhcpcd-ui/APKBUILD b/main/dhcpcd-ui/APKBUILD
new file mode 100644
index 0000000000..56441cefd0
--- /dev/null
+++ b/main/dhcpcd-ui/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dhcpcd-ui
+pkgver=0.5.1
+pkgrel=1
+pkgdesc="A GTK+ monitor and configuration GUI for dhcpcd"
+url="http://roy.marples.name/projects/dhcpcd-ui"
+arch="all"
+license="BSD-2"
+depends="dhcpcd-dbus hicolor-icon-theme"
+makedepends="glib-dev gtk+-dev dbus-dev libnotify-dev pkgconfig"
+install=
+subpackages="$pkgname-doc"
+source="http://roy.marples.name/downloads/dhcpcd/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" AUTOSTARTDIR=/etc/xdg/autostart install
+}
+
+md5sums="a42b15650de093bcd3dd60fb94a483f7 dhcpcd-ui-0.5.1.tar.bz2"
diff --git a/main/dhcpcd/APKBUILD b/main/dhcpcd/APKBUILD
new file mode 100644
index 0000000000..7c6885dc11
--- /dev/null
+++ b/main/dhcpcd/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dhcpcd
+pkgver=5.2.12
+pkgrel=0
+pkgdesc="RFC2131 compliant DHCP client"
+url="http://roy.marples.name/projects/dhcpcd/"
+arch="all"
+license="BSD-2"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://roy.marples.name/downloads/dhcpcd/$pkgname-$pkgver.tar.bz2
+ dhcpcd.initd"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --libexecdir=/lib/dhcpcd \
+ --dbdir=/var/lib/dhcpcd \
+ || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ install -Dm755 "$srcdir"/dhcpcd.initd "$pkgdir"/etc/init.d/dhcpcd
+}
+
+md5sums="832e3cd6bfcaff64e9476e0ff7849e8f dhcpcd-5.2.12.tar.bz2
+ecbd807cf3f87d7c5b6095bf63f26894 dhcpcd.initd"
diff --git a/main/dhcpcd/dhcpcd.initd b/main/dhcpcd/dhcpcd.initd
new file mode 100644
index 0000000000..d88b0610dd
--- /dev/null
+++ b/main/dhcpcd/dhcpcd.initd
@@ -0,0 +1,17 @@
+#!/sbin/runscript
+# Copyright 2007-2008 Roy Marples <roy@marples.name>
+# All rights reserved. Released under the 2-clause BSD license.
+
+command=/sbin/dhcpcd
+pidfile=/var/run/dhcpcd.pid
+command_args=-q
+name="DHCP Client Daemon"
+
+depend()
+{
+ provide net
+ need localmount
+ use logger network
+ after bootmisc modules
+ before dns
+}
diff --git a/main/dialog/APKBUILD b/main/dialog/APKBUILD
new file mode 100644
index 0000000000..4522069d10
--- /dev/null
+++ b/main/dialog/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dialog
+pkgver=1.1.20100428
+_pkgver=1.1-20100428
+pkgrel=2
+pkgdesc="A script-interpreter which provides a set of curses"
+url="http://invisible-island.net/dialog/dialog.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc"
+source="ftp://ftp.us.debian.org/debian/pool/main/d/$pkgname/dialog_$_pkgver.orig.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$_pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$_pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="519c0a0cbac28ddb992111ec2c3f82aa dialog_1.1-20100428.orig.tar.gz"
diff --git a/main/diffutils/APKBUILD b/main/diffutils/APKBUILD
new file mode 100644
index 0000000000..252be266f6
--- /dev/null
+++ b/main/diffutils/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=diffutils
+pkgver=3.0
+pkgrel=1
+pkgdesc="Show differences among files"
+subpackages="$pkgname-doc"
+url="http://www.gnu.org/software/diffutils/"
+arch="all"
+license="GPL2"
+depends=""
+makedepends=""
+install="$pkgname.post-deinstall"
+source="http://ftp.gnu.org/pub/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir=$srcdir/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install DESTDIR=$pkgdir
+}
+
+md5sums="684aaba1baab743a2a90e52162ff07da diffutils-3.0.tar.gz"
diff --git a/main/diffutils/diffutils.post-deinstall b/main/diffutils/diffutils.post-deinstall
new file mode 100644
index 0000000000..c59247ad41
--- /dev/null
+++ b/main/diffutils/diffutils.post-deinstall
@@ -0,0 +1,2 @@
+#!/bin/sh
+busybox --install -s
diff --git a/main/dircproxy/1.0.5-CVE-2007-5226.patch b/main/dircproxy/1.0.5-CVE-2007-5226.patch
new file mode 100644
index 0000000000..1d9994228b
--- /dev/null
+++ b/main/dircproxy/1.0.5-CVE-2007-5226.patch
@@ -0,0 +1,12 @@
+diff -u dircproxy-1.0.5/src/irc_server.c dircproxy-1.0.5/src/irc_server.c
+--- dircproxy-1.0.5/src/irc_server.c
++++ dircproxy-1.0.5/src/irc_server.c
+@@ -1078,7 +1078,7 @@
+
+ if (!strcmp(cmsg.cmd, "ACTION")) {
+ if (p->conn_class->log_events & IRC_LOG_ACTION)
+- irclog_ctcp(p, msg.params[0], msg.src.orig, "%s", cmsg.orig);
++ irclog_ctcp(p, (msg.params != NULL ) ? msg.params[0]: "none", msg.src.orig, "%s", cmsg.orig);
+
+ } else if (!strcmp(cmsg.cmd, "DCC")
+ && p->conn_class->dcc_proxy_incoming) {
diff --git a/main/dircproxy/1.1.0-less-lag-on-attach.patch b/main/dircproxy/1.1.0-less-lag-on-attach.patch
new file mode 100644
index 0000000000..2eb3998db1
--- /dev/null
+++ b/main/dircproxy/1.1.0-less-lag-on-attach.patch
@@ -0,0 +1,53 @@
+--- a/src/irc_client.c 2005-01-06 02:48:12.964637427 +0100
++++ b/src/irc_client.c.lessflood 2005-01-06 02:47:50.433376383 +0100
+@@ -1910,13 +1910,34 @@
+ /* Recall channel log files, and get channel topic and members from server */
+ if (p->channels) {
+ struct ircchannel *c;
++ unsigned int cnames_length = 0;
++ char *cnames = 0;
++
++ c = p->channels;
++ while (c) {
++ if (!c->inactive && !c->unjoined) {
++ cnames_length += strlen(c->name) + 1; // +1 to hold comma
++ }
++
++ c = c->next;
++ }
++
++ if(cnames_length)
++ {
++ cnames = (char *)malloc(cnames_length + 1);
++ memset(cnames, 0, cnames_length + 1);
++ }
+
+ c = p->channels;
+ while (c) {
+ if (!c->inactive && !c->unjoined) {
+ ircclient_send_selfcmd(p, "JOIN", ":%s", c->name);
+- ircserver_send_command(p, "TOPIC", ":%s", c->name);
+- ircserver_send_command(p, "NAMES", ":%s", c->name);
++ if(cnames_length) {
++ if(c == p->channels) // first channel in list
++ sprintf(cnames, "%s", c->name);
++ else
++ sprintf(cnames, "%s,%s", cnames, c->name);
++ }
+
+ if (p->conn_class->chan_log_enabled) {
+ irclog_autorecall(p, c->name);
+@@ -1926,6 +1948,13 @@
+
+ c = c->next;
+ }
++
++ if(cnames_length)
++ {
++ ircserver_send_command(p, "TOPIC", ":%s", cnames);
++ ircserver_send_command(p, "NAMES", ":%s", cnames);
++ free(cnames);
++ }
+ }
+
+ /* Recall private log file */
diff --git a/main/dircproxy/APKBUILD b/main/dircproxy/APKBUILD
new file mode 100644
index 0000000000..1bdbecf45e
--- /dev/null
+++ b/main/dircproxy/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dircproxy
+pkgver=1.1.0
+pkgrel=2
+pkgdesc="IRC proxy server designed for people who use IRC from lots of different workstations or clients"
+url="http://code.google.com/p/dircproxy/"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-doc"
+source="http://dircproxy.googlecode.com/files/$pkgname-$pkgver.tar.gz
+ 1.0.5-CVE-2007-5226.patch
+ 1.1.0-less-lag-on-attach.patch
+ dircproxy-gcc4.patch
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 -i $i || return 1
+ done
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+ # install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ # install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="066bd39d80f286ae5ce69a2adbbd01e4 dircproxy-1.1.0.tar.gz
+fdd98d0bad6ef36afba7fa2604c43520 1.0.5-CVE-2007-5226.patch
+a83ab2a3bce526ba0d8f8a05c88f9a47 1.1.0-less-lag-on-attach.patch
+3b70d62b2eb88013548871e634e33c43 dircproxy-gcc4.patch"
diff --git a/main/dircproxy/dircproxy-gcc4.patch b/main/dircproxy/dircproxy-gcc4.patch
new file mode 100644
index 0000000000..727d8db2b4
--- /dev/null
+++ b/main/dircproxy/dircproxy-gcc4.patch
@@ -0,0 +1,47 @@
+--- a/src/dcc_net.c 2001-12-21 21:15:55.000000000 +0100
++++ b/src/dcc_net.c 2004-12-14 15:40:45.976549384 +0100
+@@ -364,7 +364,8 @@
+ n = p->next;
+ _dccnet_free(p);
+
+- p = (l ? l->next : proxies) = n;
++ if (l) l->next = n; else proxies = n;
++ p = n;
+ } else {
+ l = p;
+ p = p->next;
+diff -urN a/src/irc_server.c ./src/irc_server.c
+--- a/src/irc_server.c 2002-01-31 15:56:37.000000000 +0100
++++ b/src/irc_server.c 2004-12-14 15:39:49.163186328 +0100
+@@ -700,7 +700,8 @@
+ free(s);
+
+ /* Was in the squelch list, so remove it and stop looking */
+- s = (l ? l->next : p->squelch_modes) = n;
++ if (l) l->next = n; else p->squelch_modes = n;
++ s = n;
+ squelch = 1;
+ break;
+ } else {
+@@ -741,7 +742,8 @@
+ free(s);
+
+ /* Was in the squelch list, so remove it and stop looking */
+- s = (l ? l->next : p->squelch_modes) = n;
++ if (l) l->next = n; else p->squelch_modes = n;
++ s = n;
+ squelch = 1;
+ break;
+ } else {
+diff -urN ../tmp-orig/dircproxy-1.0.5/src/net.c ./src/net.c
+--- a/src/net.c 2002-01-01 18:55:23.000000000 +0100
++++ b/src/net.c 2004-12-14 15:41:43.499804520 +0100
+@@ -459,7 +459,7 @@
+ return 0;
+ }
+
+- l = &(buff == SB_IN ? s->in_buff_last : s->out_buff_last);
++ l = (buff == SB_IN) ? &s->in_buff_last : &s->out_buff_last;
+
+ /* Check whether we can just add to the existing buffer */
+ if ((mode == SM_RAW) && *l && ((*l)->mode == mode)) {
diff --git a/main/distcc/APKBUILD b/main/distcc/APKBUILD
new file mode 100644
index 0000000000..8d2212c0c6
--- /dev/null
+++ b/main/distcc/APKBUILD
@@ -0,0 +1,54 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=distcc
+pkgver=3.1
+pkgrel=6
+pkgdesc="A distributed C, C++, Obj C compiler"
+url="http://distcc.org"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="popt-dev python-dev"
+source="http://$pkgname.googlecode.com/files/$pkgname-$pkgver.tar.bz2
+ distcc-3.1-clone.patch
+ distcc-hardened.patch
+ distccd.initd distccd.confd"
+subpackages="$pkgname-doc $pkgname-pump"
+
+build ()
+{
+ cd "$srcdir/$pkgname-$pkgver"
+ for i in ../*.patch; do
+ msg "applying $i"
+ patch -p1 < $i || return 1
+ done
+ ./configure --prefix=/usr \
+ --without-gtk \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man
+
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+ install -D -m644 ../distccd.confd "$pkgdir"/etc/conf.d/distccd
+ install -D -m755 ../distccd.initd "$pkgdir"/etc/init.d/distccd
+
+ local d="$pkgdir/usr/lib/$pkgname/bin"
+ mkdir -p "$d"
+ ln -sf /usr/bin/$pkgname "$d"/cc
+ ln -sf /usr/bin/$pkgname "$d"/gcc
+ ln -sf /usr/bin/$pkgname "$d"/g++
+ ln -sf /usr/bin/$pkgname "$d"/cpp
+}
+
+pump() {
+ pkgdesc="pump mode for distcc a distributed compiler client and server"
+ mkdir -p "$subpkgdir"/usr/lib "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/pump "$subpkgdir"/usr/bin/
+ mv "$pkgdir"/usr/lib/python* "$subpkgdir"/usr/lib/
+}
+
+md5sums="a1a9d3853df7133669fffec2a9aab9f3 distcc-3.1.tar.bz2
+29fe296aa2985eea7af7402f421db187 distcc-3.1-clone.patch
+351ca958ff4869f8a2795d8ca6647de1 distcc-hardened.patch
+a0dc869866f17054142c964d29925e70 distccd.initd
+e9e0ccc9f5813b9c3c88c8687b2ebc73 distccd.confd"
diff --git a/main/distcc/distcc-3.1-clone.patch b/main/distcc/distcc-3.1-clone.patch
new file mode 100644
index 0000000000..70e8f8351f
--- /dev/null
+++ b/main/distcc/distcc-3.1-clone.patch
@@ -0,0 +1,14 @@
+--- distcc-3.1.orig/lzo/minilzo.c Mon Jan 12 09:05:53 2009
++++ distcc-3.1/lzo/minilzo.c Mon Jan 12 10:27:02 2009
+@@ -1298,9 +1298,9 @@
+ #if defined(__LZO_CHECKER)
+ return 0;
+ #else
+- const int clone[] = {1, 2, 0};
++ const int _clone[] = {1, 2, 0};
+ const int *q;
+- q = clone;
++ q = _clone;
+ return (*q) ? 0 : 1;
+ #endif
+ }
diff --git a/main/distcc/distcc-hardened.patch b/main/distcc/distcc-hardened.patch
new file mode 100644
index 0000000000..69b3a65169
--- /dev/null
+++ b/main/distcc/distcc-hardened.patch
@@ -0,0 +1,24 @@
+From: Gordon Malm <gengor@gentoo.org>
+
+Make distcc client pass -D__KERNEL__ macro. Hardened GCC uses this
+macro to determine if code intended to be run in-kernel is being compiled.
+If the code is kernel code, certain compile flags are not applied.
+
+When using distcc to build kernel code (modules, etc.) without this patch,
+the distccd host doesn't get passed -D__KERNEL__. Consequently, gcc on
+the distccd host applies all kinds of flags that it shouldn't.
+
+--- distcc-2.18.3/src/strip.c
++++ distcc-2.18.3-hardened/src/strip.c
+@@ -73,7 +73,10 @@ int dcc_strip_local_args(char **from, ch
+ /* skip through argv, copying all arguments but skipping ones that
+ * ought to be omitted */
+ for (from_i = to_i = 0; from[from_i]; from_i++) {
+- if (str_equal("-D", from[from_i])
++ if (str_equal("-D__KERNEL__", from[from_i])) {
++ to[to_i++] = from[from_i];
++ }
++ else if (str_equal("-D", from[from_i])
+ || str_equal("-I", from[from_i])
+ || str_equal("-U", from[from_i])
+ || str_equal("-L", from[from_i])
diff --git a/main/distcc/distccd.confd b/main/distcc/distccd.confd
new file mode 100644
index 0000000000..b4e72b6c15
--- /dev/null
+++ b/main/distcc/distccd.confd
@@ -0,0 +1,45 @@
+# /etc/conf.d/distccd: config file for /etc/init.d/distccd
+
+DISTCCD_OPTS=""
+
+# this is the distccd executable
+DISTCCD_EXEC="/usr/bin/distccd"
+
+# this is where distccd will store its pid file
+DISTCCD_PIDFILE="/var/run/distccd/distccd.pid"
+
+# set this option to run distccd with extra parameters
+# Default port is 3632. For most people the default is okay.
+DISTCCD_OPTS="${DISTCCD_OPTS} --port 3632"
+
+# Logging
+# You can change some logging options here:
+# --log-file FILE
+# --log-level LEVEL [critical,error,warning, notice, info, debug]
+#
+# Leaving --log-file blank will log to syslog
+# example: --log-file /dev/null --log-level warning
+# example: --log-level critical
+
+DISTCCD_OPTS="${DISTCCD_OPTS} --log-level critical"
+
+# SECURITY NOTICE:
+# It is HIGHLY recomended that you use the --listen option
+# for increased security. You can specify an IP to permit connections
+# from or a CIDR mask
+# --listen accepts only a single IP
+# --allow is now mandatory as of distcc-2.18.
+# example: --allow 192.168.0.0/24
+# example: --allow 192.168.0.5 --allow 192.168.0.150
+# example: --listen 192.168.0.2
+DISTCCD_OPTS="${DISTCCD_OPTS} --allow 192.168.0.0/24"
+#DISTCCD_OPTS="${DISTCCD_OPTS} --listen 192.168.0.2"
+
+# set this for niceness
+# Default is 15
+DISTCCD_NICE="15"
+
+#ifdef AVAHI
+# Enable zeroconf support in distccd
+DISTCCD_AVAHI="no"
+#endif
diff --git a/main/distcc/distccd.initd b/main/distcc/distccd.initd
new file mode 100644
index 0000000000..5d90cfb9b9
--- /dev/null
+++ b/main/distcc/distccd.initd
@@ -0,0 +1,39 @@
+#!/sbin/runscript
+# $Header: /var/cvsroot/gentoo-x86/sys-devel/distcc/files/2.18-r1/init,v 1.1 2008/01/04 03:53:15 betelgeuse Exp $
+
+depend() {
+ local avahi
+#ifdef AVAHI
+ [ ${DISTCCD_AVAHI} = yes ] && avahi="avahi-daemon"
+#endif
+ need net ${avahi}
+ after firewall
+ use ypbind
+}
+
+start() {
+ [ -e "${DISTCCD_PIDFILE}" ] && rm -f ${DISTCCD_PIDFILE} &>/dev/null
+
+ local args
+#ifdef AVAHI
+ [ ${DISTCCD_AVAHI} = yes ] && args="--zeroconf"
+#endif
+
+ ebegin "Starting distccd"
+ chown distcc `dirname ${DISTCCD_PIDFILE}` >/dev/null 2>&1
+ TMPDIR="${TMPDIR}" \
+ /sbin/start-stop-daemon --start --quiet --exec ${DISTCCD_EXEC} \
+ --pidfile ${DISTCCD_PIDFILE} -- \
+ --pid-file ${DISTCCD_PIDFILE} -N ${DISTCCD_NICE} --user distcc \
+ ${args} ${DISTCCD_OPTS}
+
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping distccd"
+ start-stop-daemon --stop --quiet --pidfile "${DISTCCD_PIDFILE}" \
+ && rm -f "${DISTCCD_PIDFILE}"
+ eend $?
+}
+
diff --git a/main/djbdns/1.05-errno.patch b/main/djbdns/1.05-errno.patch
new file mode 100644
index 0000000000..58f2f4b6c9
--- /dev/null
+++ b/main/djbdns/1.05-errno.patch
@@ -0,0 +1,11 @@
+--- a/error.h 2001-02-11 15:11:45.000000000 -0600
++++ b/error.h 2003-02-26 02:10:21.000000000 -0600
+@@ -1,7 +1,7 @@
+ #ifndef ERROR_H
+ #define ERROR_H
+
+-extern int errno;
++#include <errno.h>
+
+ extern int error_intr;
+ extern int error_nomem;
diff --git a/main/djbdns/1.05-response.patch b/main/djbdns/1.05-response.patch
new file mode 100644
index 0000000000..eb6ae59049
--- /dev/null
+++ b/main/djbdns/1.05-response.patch
@@ -0,0 +1,11 @@
+--- a/response.c.orig 2009-02-24 21:04:06.000000000 -0800
++++ b/response.c 2009-02-24 21:04:25.000000000 -0800
+@@ -34,7 +34,7 @@
+ uint16_pack_big(buf,49152 + name_ptr[i]);
+ return response_addbytes(buf,2);
+ }
+- if (dlen <= 128)
++ if ((dlen <= 128) && (response_len < 16384))
+ if (name_num < NAMES) {
+ byte_copy(name[name_num],dlen,d);
+ name_ptr[name_num] = response_len;
diff --git a/main/djbdns/APKBUILD b/main/djbdns/APKBUILD
new file mode 100644
index 0000000000..7e116f20b3
--- /dev/null
+++ b/main/djbdns/APKBUILD
@@ -0,0 +1,105 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=djbdns
+pkgver=1.05
+pkgrel=38
+pkgdesc="Excellent high-performance DNS services"
+url="http://cr.yp.to/djbdns.html"
+arch="all"
+license="public-domain"
+depends=
+subpackages="djbdns-common tinydns dnscache"
+source="http://cr.yp.to/djbdns/$pkgname-$pkgver.tar.gz
+ headtail.patch
+ dnsroots.patch
+ dnstracesort.patch
+ djbdns-1.05-jumbo-josb.patch
+ $pkgver-errno.patch
+ $pkgver-response.patch
+ tinydns.pre-install
+ tinydns.initd
+ tinydns.confd
+ dnscache.pre-install
+ dnscache.initd
+ dnscache.confd
+ dnscache.monthly
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
+ echo "${CC:-"gcc"} ${CFLAGS}" > conf-cc
+ echo "${CC:-"gcc"} ${LDFLAGS}" > conf-ld
+ echo "/usr" > conf-home
+ make -j1 || return 1
+
+ mkdir -p "$pkgdir"/etc/
+ cp dnsroots.global "$pkgdir"/etc/
+ mkdir -p "$pkgdir"/usr/bin
+ cp *-conf dnscache tinydns walldns rbldns pickdns axfrdns \
+ *-get *-data *-edit dnsip dnsipq dnsname dnstxt dnsmx \
+ dnsfilter random-ip dnsqr dnsq dnstrace dnstracesort \
+ "$pkgdir"/usr/bin/
+ mkdir -p "$pkgdir"/usr/share/doc/djbdns
+}
+
+common() {
+ pkgdesc="Base utilities of djbdns"
+ replaces="djbdns"
+
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/dnsqr "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/dnsip "$subpkgdir"/usr/bin
+}
+
+tinydns() {
+ pkgdesc="A small and secure DNS server"
+ install=tinydns.pre-install
+
+ mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/etc/tinydns \
+ "$subpkgdir"/var/cache/tinydns
+ mv "$pkgdir"/usr/bin/tinydns* "$subpkgdir"/usr/bin
+ install -D -m755 "$srcdir"/tinydns.initd \
+ "$subpkgdir"/etc/init.d/tinydns
+ install -D -m644 "$srcdir"/tinydns.confd \
+ "$subpkgdir"/etc/conf.d/tinydns
+}
+
+dnscache() {
+ pkgdesc="A recursive resolver"
+ install=dnscache.pre-install
+ depends=djbdns-common
+
+ mkdir -p "$subpkgdir"/usr/bin \
+ "$subpkgdir"/etc/dnscache/ip \
+ "$subpkgdir"/etc/dnscache/servers
+
+ cp "$pkgdir"/etc/dnsroots.global "$subpkgdir"/etc/dnscache/servers/@
+ touch "$subpkgdir"/etc/dnscache/ip/127 || return 1
+
+ mv "$pkgdir"/usr/bin/dnscache* "$subpkgdir"/usr/bin
+ install -D -m755 "$srcdir"/dnscache.initd \
+ "$subpkgdir"/etc/init.d/dnscache
+ install -D -m644 "$srcdir"/dnscache.confd \
+ "$subpkgdir"/etc/conf.d/dnscache
+ install -D -m755 "$srcdir"/dnscache.monthly \
+ "$subpkgdir"/etc/periodic/monthly/dnscache-hints-refresh
+}
+
+md5sums="3147c5cd56832aa3b41955c7a51cbeb2 djbdns-1.05.tar.gz
+0d2adaf9f1626043e8702b825cdccdd6 headtail.patch
+7565048ebc981238879122c7f88cc143 dnsroots.patch
+6fe7f473233f1c86b76261afd8345bf0 dnstracesort.patch
+adb6745606cae593eb5ea6870fc27bd4 djbdns-1.05-jumbo-josb.patch
+c7be73fe2fb4ae02d5096fa2c1f55a68 1.05-errno.patch
+1292500c04baba3995d9753fe40fdc94 1.05-response.patch
+7695bf50559c09798ec852b578ac8698 tinydns.pre-install
+fe48165a920cf843ceb9a4ee50bf74c0 tinydns.initd
+7dcf6674c07d46c736b3c25d9c92384a tinydns.confd
+e09c3a6ba6917e16f4736ab5c070dbe9 dnscache.pre-install
+e5cada3b032da84c4a0e41ef8b3108cb dnscache.initd
+2b3d02e88f70603c760bf368ab3ed636 dnscache.confd
+8173f85e0d9b4496de389d1b43993d95 dnscache.monthly"
diff --git a/main/djbdns/djbdns-1.05-jumbo-josb.patch b/main/djbdns/djbdns-1.05-jumbo-josb.patch
new file mode 100644
index 0000000000..c1a685aef4
--- /dev/null
+++ b/main/djbdns/djbdns-1.05-jumbo-josb.patch
@@ -0,0 +1,1858 @@
+Downloaded from:
+http://lizzy.dyndns.org/~jos/djbdns-1.05-jumbo-josb.patch
+
+This patch combines the following patches:
+- Claudiu Costin's jumbo-p13.patch
+ http://www.ro.kde.org/djbdns/mywork/jumbo/jumbo-p13.patch.gz
+- Guilherme Balena Versiani's djbdns SRV+NAPTR combined patch
+ http://mywebpage.netscape.com/guibv/djbdns-1.05-srvnaptr.diff
+
+diff -ruN djbdns-1.05-dist/CHANGES djbdns-1.05/CHANGES
+--- djbdns-1.05-dist/CHANGES 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/CHANGES 2008-08-11 19:33:30.000000000 -0700
+@@ -374,3 +374,5 @@
+ ui: servers print starting message.
+ internal: some respond() declarations.
+ version: djbdns 1.05.
++20010313
++ patch: to dump and reload the cache
+diff -ruN djbdns-1.05-dist/Makefile djbdns-1.05/Makefile
+--- djbdns-1.05-dist/Makefile 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/Makefile 2008-08-11 19:33:30.000000000 -0700
+@@ -4,6 +4,8 @@
+
+ default: it
+
++include Makefile.sig
++
+ alloc.a: \
+ makelib alloc.o alloc_re.o getln.o getln2.o stralloc_cat.o \
+ stralloc_catb.o stralloc_cats.o stralloc_copy.o stralloc_eady.o \
+@@ -149,13 +151,13 @@
+
+ cache.o: \
+ compile cache.c alloc.h byte.h uint32.h exit.h tai.h uint64.h cache.h \
+-uint32.h uint64.h
++uint32.h uint64.h env.h error.h open.h openreadclose.h
+ ./compile cache.c
+
+ cachetest: \
+-load cachetest.o cache.o libtai.a buffer.a alloc.a unix.a byte.a
+- ./load cachetest cache.o libtai.a buffer.a alloc.a unix.a \
+- byte.a
++load cachetest.o cache.o libtai.a buffer.a alloc.a unix.a byte.a env.a
++ ./load cachetest cache.o libtai.a buffer.a unix.a env.a \
++ alloc.a byte.a dns.a
+
+ cachetest.o: \
+ compile cachetest.c buffer.h exit.h cache.h uint32.h uint64.h str.h
+@@ -228,11 +230,11 @@
+ dns.a: \
+ makelib dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o dns_mx.o \
+ dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o \
+-dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o
++dns_resolve.o dns_rotateip.o dns_sortip.o dns_transmit.o dns_txt.o
+ ./makelib dns.a dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o \
+ dns_ipq.o dns_mx.o dns_name.o dns_nd.o dns_packet.o \
+ dns_random.o dns_rcip.o dns_rcrw.o dns_resolve.o \
+- dns_sortip.o dns_transmit.o dns_txt.o
++ dns_rotateip.o dns_sortip.o dns_transmit.o dns_txt.o
+
+ dns_dfd.o: \
+ compile dns_dfd.c error.h alloc.h byte.h dns.h stralloc.h gen_alloc.h \
+@@ -301,6 +303,10 @@
+ dns.h stralloc.h gen_alloc.h iopause.h taia.h
+ ./compile dns_resolve.c
+
++dns_rotateip.o: \
++compile dns_rotateip.c byte.h dns.h stralloc.h gen_alloc.h
++ ./compile dns_rotateip.c
++
+ dns_sortip.o: \
+ compile dns_sortip.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \
+ taia.h tai.h uint64.h taia.h
+@@ -320,10 +326,10 @@
+ dnscache: \
+ load dnscache.o droproot.o okclient.o log.o cache.o query.o \
+ response.o dd.o roots.o iopause.o prot.o dns.a env.a alloc.a buffer.a \
+-libtai.a unix.a byte.a socket.lib
++libtai.a unix.a byte.a sig.a socket.lib
+ ./load dnscache droproot.o okclient.o log.o cache.o \
+ query.o response.o dd.o roots.o iopause.o prot.o dns.a \
+- env.a alloc.a buffer.a libtai.a unix.a byte.a `cat \
++ env.a alloc.a buffer.a libtai.a unix.a byte.a sig.a `cat \
+ socket.lib`
+
+ dnscache-conf: \
+@@ -626,9 +632,9 @@
+ ./compile parsetype.c
+
+ pickdns: \
+-load pickdns.o server.o response.o droproot.o qlog.o prot.o dns.a \
++load pickdns.o server.o iopause.o response.o droproot.o qlog.o prot.o dns.a \
+ env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
+- ./load pickdns server.o response.o droproot.o qlog.o \
++ ./load pickdns server.o iopause.o response.o droproot.o qlog.o \
+ prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
+ byte.a `cat socket.lib`
+
+@@ -704,9 +710,9 @@
+ ./compile random-ip.c
+
+ rbldns: \
+-load rbldns.o server.o response.o dd.o droproot.o qlog.o prot.o dns.a \
++load rbldns.o server.o iopause.o response.o dd.o droproot.o qlog.o prot.o dns.a \
+ env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
+- ./load rbldns server.o response.o dd.o droproot.o qlog.o \
++ ./load rbldns server.o iopause.o response.o dd.o droproot.o qlog.o \
+ prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
+ byte.a `cat socket.lib`
+
+@@ -774,7 +780,7 @@
+ compile server.c byte.h case.h env.h buffer.h strerr.h ip4.h uint16.h \
+ ndelay.h socket.h uint16.h droproot.h qlog.h uint16.h response.h \
+ uint32.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h uint64.h \
+-taia.h
++taia.h iopause.h alloc.h
+ ./compile server.c
+
+ setup: \
+@@ -979,10 +985,10 @@
+ ./compile timeoutwrite.c
+
+ tinydns: \
+-load tinydns.o server.o droproot.o tdlookup.o response.o qlog.o \
++load tinydns.o server.o iopause.o droproot.o tdlookup.o response.o qlog.o \
+ prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
+ socket.lib
+- ./load tinydns server.o droproot.o tdlookup.o response.o \
++ ./load tinydns server.o iopause.o droproot.o tdlookup.o response.o \
+ qlog.o prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \
+ unix.a byte.a `cat socket.lib`
+
+@@ -1084,10 +1090,10 @@
+ ./compile utime.c
+
+ walldns: \
+-load walldns.o server.o response.o droproot.o qlog.o prot.o dd.o \
++load walldns.o server.o iopause.o response.o droproot.o qlog.o prot.o dd.o \
+ dns.a env.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
+- ./load walldns server.o response.o droproot.o qlog.o \
+- prot.o dd.o dns.a env.a cdb.a alloc.a buffer.a unix.a \
++ ./load walldns server.o iopause.o response.o droproot.o qlog.o \
++ prot.o dd.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a \
+ byte.a `cat socket.lib`
+
+ walldns-conf: \
+diff -ruN djbdns-1.05-dist/Makefile.sig djbdns-1.05/Makefile.sig
+--- djbdns-1.05-dist/Makefile.sig 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/Makefile.sig 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,27 @@
++sig.o: \
++compile sig.c sig.h
++ ./compile sig.c
++
++sig_block.o: \
++compile sig_block.c sig.h hassgprm.h
++ ./compile sig_block.c
++
++sig_catch.o: \
++compile sig_catch.c sig.h hassgact.h
++ ./compile sig_catch.c
++
++sig_pause.o: \
++compile sig_pause.c sig.h hassgprm.h
++ ./compile sig_pause.c
++
++sig.a: \
++makelib sig.o sig_block.o sig_catch.o sig_pause.o
++ ./makelib sig.a sig.o sig_block.o sig_catch.o sig_pause.o
++
++hassgact.h: \
++choose compile load trysgact.c hassgact.h1 hassgact.h2
++ ./choose cl trysgact hassgact.h1 hassgact.h2 > hassgact.h
++
++hassgprm.h: \
++choose compile load trysgprm.c hassgprm.h1 hassgprm.h2
++ ./choose cl trysgprm hassgprm.h1 hassgprm.h2 > hassgprm.h
+diff -ruN djbdns-1.05-dist/README djbdns-1.05/README
+--- djbdns-1.05-dist/README 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/README 2008-08-11 19:33:30.000000000 -0700
+@@ -1,3 +1,9 @@
++patchlevel fg1
++20010313
++by Florent Guillaume <florent.guillaume@mail.com>
++patch home page: http://mapage.noos.fr/efgeor/djbdns/index.html
++Uses parts of Felix von Leitner's djb-0.5.2 package: http://www.fefe.de/djb/
++
+ djbdns 1.05
+ 20010211
+ Copyright 2001
+diff -ruN djbdns-1.05-dist/SYSDEPS djbdns-1.05/SYSDEPS
+--- djbdns-1.05-dist/SYSDEPS 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/SYSDEPS 2008-08-11 19:33:30.000000000 -0700
+@@ -7,4 +7,6 @@
+ direntry.h
+ hasshsgr.h
+ hasdevtcp.h
++hassgact.h
++hassgprm.h
+ socket.lib
+diff -ruN djbdns-1.05-dist/TARGETS djbdns-1.05/TARGETS
+--- djbdns-1.05-dist/TARGETS 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/TARGETS 2008-08-11 19:33:30.000000000 -0700
+@@ -214,3 +214,10 @@
+ it
+ setup
+ check
++sig.o
++sig.a
++sig_catch.o
++sig_block.o
++hassgact.h
++hassgprm.h
++sig_pause.o
+diff -ruN djbdns-1.05-dist/VERSION djbdns-1.05/VERSION
+--- djbdns-1.05-dist/VERSION 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/VERSION 2008-08-11 19:33:30.000000000 -0700
+@@ -1 +1 @@
+-djbdns 1.05
++djbdns 1.05-fg1
+diff -ruN djbdns-1.05-dist/auto_home.c djbdns-1.05/auto_home.c
+--- djbdns-1.05-dist/auto_home.c 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/auto_home.c 2008-08-12 09:17:21.000000000 -0700
+@@ -0,0 +1,3 @@
++const char auto_home[] = "\
++\057\165\163\162\057\154\157\143\141\154\
++";
+diff -ruN djbdns-1.05-dist/axfr-get.c djbdns-1.05/axfr-get.c
+--- djbdns-1.05-dist/axfr-get.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/axfr-get.c 2008-08-11 22:49:05.000000000 -0700
+@@ -209,6 +209,57 @@
+ if (!stralloc_cats(&line,".:")) return 0;
+ if (!stralloc_catulong0(&line,dist,0)) return 0;
+ }
++ else if (byte_equal(data,2,DNS_T_SRV)) {
++ uint16 priority, weight, port;
++ if (!stralloc_copys(&line,"S")) return 0;
++ if (!dns_domain_todot_cat(&line,d1)) return 0;
++ if (!stralloc_cats(&line,"::")) return 0;
++ pos = x_copy(buf,len,pos,data,2);
++ uint16_unpack_big(data,&priority);
++ pos = x_copy(buf,len,pos,data,2);
++ uint16_unpack_big(data,&weight);
++ pos = x_copy(buf,len,pos,data,2);
++ uint16_unpack_big(data,&port);
++ x_getname(buf,len,pos,&d1);
++ if (!dns_domain_todot_cat(&line,d1)) return 0;
++ if (!stralloc_cats(&line,".:")) return 0;
++ if (!stralloc_catulong0(&line,port,0)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ if (!stralloc_catulong0(&line,priority,0)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ if (!stralloc_catulong0(&line,weight,0)) return 0;
++ }
++ else if (byte_equal(data,2,DNS_T_NAPTR)) {
++ uint16 order, preference;
++ char flags[255], service[255], regexp[255];
++ char fs, ss, rs;
++ if (!stralloc_copys(&line,"N")) return 0;
++ if (!dns_domain_todot_cat(&line,d1)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ pos = x_copy(buf,len,pos,data,2);
++ uint16_unpack_big(data,&order);
++ pos = x_copy(buf,len,pos,data,2);
++ uint16_unpack_big(data,&preference);
++ pos = x_copy(buf,len,pos,&fs,1);
++ pos = x_copy(buf,len,pos,flags,fs);
++ pos = x_copy(buf,len,pos,&ss,1);
++ pos = x_copy(buf,len,pos,service,ss);
++ pos = x_copy(buf,len,pos,&rs,1);
++ pos = x_copy(buf,len,pos,regexp,rs);
++ x_getname(buf,len,pos,&d1);
++ if (!stralloc_catulong0(&line,order,0)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ if (!stralloc_catulong0(&line,preference,0)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ if (!stralloc_catb(&line,flags,fs)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ if (!stralloc_catb(&line,service,ss)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ if (!stralloc_catb(&line,regexp,rs)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ if (!dns_domain_todot_cat(&line,d1)) return 0;
++ if (!stralloc_cats(&line,".")) return 0;
++ }
+ else if (byte_equal(data,2,DNS_T_A) && (dlen == 4)) {
+ char ipstr[IP4_FMT];
+ if (!stralloc_copys(&line,"+")) return 0;
+@@ -217,6 +268,14 @@
+ x_copy(buf,len,pos,data,4);
+ if (!stralloc_catb(&line,ipstr,ip4_fmt(ipstr,data))) return 0;
+ }
++ else if (byte_equal(data,2,DNS_T_PTR)) {
++ if (!stralloc_copys(&line,"^")) return 0;
++ if (!dns_domain_todot_cat(&line,d1)) return 0;
++ if (!stralloc_cats(&line,":")) return 0;
++ x_getname(buf,len,pos,&d1);
++ if (!dns_domain_todot_cat(&line,d1)) return 0;
++ if (!stralloc_cats(&line,".")) return 0;
++ }
+ else {
+ unsigned char ch;
+ unsigned char ch2;
+diff -ruN djbdns-1.05-dist/cache.c djbdns-1.05/cache.c
+--- djbdns-1.05-dist/cache.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/cache.c 2008-08-11 19:33:30.000000000 -0700
+@@ -1,12 +1,23 @@
++#ifdef DUMPCACHE
++#include <stdio.h>
++#include <unistd.h>
++#include "env.h"
++#include "error.h"
++#include "open.h"
++#include "openreadclose.h"
++#endif
+ #include "alloc.h"
+ #include "byte.h"
+ #include "uint32.h"
+ #include "exit.h"
+ #include "tai.h"
+ #include "cache.h"
++#include "dns.h"
++#include "buffer.h"
+
+ uint64 cache_motion = 0;
+
++static char *rrobin;
+ static char *x = 0;
+ static uint32 size;
+ static uint32 hsize;
+@@ -87,6 +98,12 @@
+ uint32 u;
+ unsigned int loop;
+ double d;
++ static int trigger=0;
++
++ if (!trigger) {
++ rrobin = env_get("ROUNDROBIN");
++ trigger++;
++ }
+
+ if (!x) return 0;
+ if (keylen > MAXKEYLEN) return 0;
+@@ -111,7 +128,11 @@
+ u = get4(pos + 8);
+ if (u > size - pos - 20 - keylen) cache_impossible();
+ *datalen = u;
+-
++ if (byte_equal(key,2,DNS_T_A)) {
++ if (rrobin) {
++ dns_rotateip(x + pos + 20 + keylen,u);
++ }
++ }
+ return x + pos + 20 + keylen;
+ }
+ }
+@@ -205,3 +226,97 @@
+
+ return 1;
+ }
++
++#ifdef DUMPCACHE
++static int fd;
++
++static int cache_writeline(const char *buf, unsigned int len)
++{
++ int w;
++
++ while (len) {
++ w = write(fd,buf,len);
++ if (w == -1) {
++ if (errno == error_intr) continue;
++ close(fd);
++ return -1;
++ }
++ buf += w;
++ len -= w;
++ }
++ return 0;
++}
++
++int cache_dump(void)
++{
++ static char *fn;
++ static char *fntmp;
++ uint32 pos;
++ unsigned int len;
++
++ fn = env_get("DUMPCACHE");
++ if (!fn) return 999;
++ fntmp = env_get("DUMPCACHETMP");
++ if (!fntmp) return 999;
++ fd = open_trunc(fntmp);
++ if (fd == -1) return -1;
++
++ pos = oldest;
++ while (pos < unused) {
++ len = get4(pos + 4) + get4(pos + 8) + 16;
++ if (cache_writeline(x + pos + 4, len)) return -1;
++ pos += 4 + len;
++ }
++ pos = hsize;
++ while (pos < writer) {
++ len = get4(pos + 4) + get4(pos + 8) + 16;
++ if (cache_writeline(x + pos + 4, len)) return -1;
++ pos += 4 + len;
++ }
++
++ if (fsync(fd) == -1) return -1;
++ if (close(fd) == -1) return -1;
++ if (rename(fntmp,fn) == -1) return -1;
++ return 0;
++}
++
++int cache_slurp(const char *fn)
++{
++ static stralloc buf = {0};
++ char *p;
++ uint32 pos;
++ unsigned int len;
++ uint32 keylen;
++ uint32 datalen;
++ struct tai now;
++ struct tai expire;
++ int nb;
++
++ if (openreadclose(fn,&buf,16384) != 1) goto DIE;
++ tai_now(&now);
++ p = buf.s;
++ pos = 0;
++ len = buf.len;
++ nb = 0;
++ while (pos + 16 <= len) {
++ uint32_unpack(p + pos, &keylen);
++ uint32_unpack(p + pos + 4, &datalen);
++ tai_unpack(p + pos + 8, &expire);
++ pos += 16;
++ if (pos + keylen + datalen > len) break; /* missing data */
++ if (!tai_less(&expire,&now)) {
++ tai_sub(&expire,&expire,&now);
++ cache_set(p + pos, keylen, p + pos + keylen, datalen, (unsigned int)expire.x);
++ }
++ pos += keylen + datalen;
++ nb++;
++ }
++ alloc_free(buf.s); buf.s = 0;
++ return nb;
++
++ DIE:
++ alloc_free(buf.s); buf.s = 0;
++ if (errno == error_noent) return 0;
++ return -1;
++}
++#endif
+diff -ruN djbdns-1.05-dist/cache.h djbdns-1.05/cache.h
+--- djbdns-1.05-dist/cache.h 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/cache.h 2008-08-11 19:33:30.000000000 -0700
+@@ -8,5 +8,9 @@
+ extern int cache_init(unsigned int);
+ extern void cache_set(const char *,unsigned int,const char *,unsigned int,uint32);
+ extern char *cache_get(const char *,unsigned int,unsigned int *,uint32 *);
++#ifdef DUMPCACHE
++extern int cache_dump(void);
++extern int cache_slurp(const char *);
++#endif
+
+ #endif
+diff -ruN djbdns-1.05-dist/chkshsgr.c djbdns-1.05/chkshsgr.c
+--- djbdns-1.05-dist/chkshsgr.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/chkshsgr.c 2008-08-11 19:33:30.000000000 -0700
+@@ -1,4 +1,6 @@
+ #include "exit.h"
++#include <grp.h>
++#include <unistd.h>
+
+ int main()
+ {
+diff -ruN djbdns-1.05-dist/direntry.h djbdns-1.05/direntry.h
+--- djbdns-1.05-dist/direntry.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/direntry.h 2008-08-11 22:55:14.000000000 -0700
+@@ -0,0 +1,10 @@
++#ifndef DIRENTRY_H
++#define DIRENTRY_H
++
++/* sysdep: +dirent */
++
++#include <sys/types.h>
++#include <dirent.h>
++#define direntry struct dirent
++
++#endif
+diff -ruN djbdns-1.05-dist/dns.h djbdns-1.05/dns.h
+--- djbdns-1.05-dist/dns.h 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/dns.h 2008-08-11 22:49:25.000000000 -0700
+@@ -20,6 +20,8 @@
+ #define DNS_T_SIG "\0\30"
+ #define DNS_T_KEY "\0\31"
+ #define DNS_T_AAAA "\0\34"
++#define DNS_T_SRV "\0\41"
++#define DNS_T_NAPTR "\0\43"
+ #define DNS_T_AXFR "\0\374"
+ #define DNS_T_ANY "\0\377"
+
+@@ -43,6 +45,7 @@
+ extern unsigned int dns_random(unsigned int);
+
+ extern void dns_sortip(char *,unsigned int);
++extern void dns_rotateip(char *,unsigned int);
+
+ extern void dns_domain_free(char **);
+ extern int dns_domain_copy(char **,const char *);
+diff -ruN djbdns-1.05-dist/dns_rotateip.c djbdns-1.05/dns_rotateip.c
+--- djbdns-1.05-dist/dns_rotateip.c 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/dns_rotateip.c 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,15 @@
++#include "byte.h"
++
++void dns_rotateip(char *s, unsigned int n)
++{
++ unsigned int i;
++ char tmp[4];
++
++ i = n >> 2;
++ while (i > 1) {
++ --i;
++ byte_copy(tmp,4,s + (i << 2));
++ byte_copy(s + (i << 2),4,s);
++ byte_copy(s,4,tmp);
++ }
++}
+diff -ruN djbdns-1.05-dist/dnscache-conf.c djbdns-1.05/dnscache-conf.c
+--- djbdns-1.05-dist/dnscache-conf.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/dnscache-conf.c 2008-08-11 19:33:30.000000000 -0700
+@@ -32,6 +32,10 @@
+ char *user;
+ char *loguser;
+ struct passwd *pw;
++#ifdef DUMPCACHE
++int useruid;
++int usergid;
++#endif
+ const char *myip;
+
+ uint32 seed[32];
+@@ -81,6 +85,14 @@
+ myip = argv[4];
+ if (!myip) myip = "127.0.0.1";
+
++#ifdef DUMPCACHE
++ pw = getpwnam(user);
++ seed_addtime();
++ if (!pw)
++ strerr_die3x(111,FATAL,"unknown account ",user);
++ useruid = pw->pw_uid;
++ usergid = pw->pw_gid;
++#endif
+ pw = getpwnam(loguser);
+ seed_addtime();
+ if (!pw)
+@@ -120,6 +132,14 @@
+ seed_addtime(); perm(0644);
+ seed_addtime(); start("env/DATALIMIT"); outs("3000000\n"); finish();
+ seed_addtime(); perm(0644);
++#ifdef DUMPCACHE
++ seed_addtime(); start("env/SLURPCACHE"); outs("dump/slurpcache\n"); finish();
++ seed_addtime(); perm(0644);
++ seed_addtime(); start("env/DUMPCACHE"); outs("dump/dumpcache\n"); finish();
++ seed_addtime(); perm(0644);
++ seed_addtime(); start("env/DUMPCACHETMP"); outs("dump/dumpcache.tmp\n"); finish();
++ seed_addtime(); perm(0644);
++#endif
+ seed_addtime(); start("run");
+ outs("#!/bin/sh\nexec 2>&1\nexec <seed\nexec envdir ./env sh -c '\n exec envuidgid "); outs(user);
+ outs(" softlimit -o250 -d \"$DATALIMIT\" ");
+@@ -131,6 +151,11 @@
+ seed_addtime(); perm(0755);
+ seed_addtime(); makedir("root");
+ seed_addtime(); perm(02755);
++#ifdef DUMPCACHE
++ seed_addtime(); makedir("root/dump");
++ seed_addtime(); owner(useruid,usergid);
++ seed_addtime(); perm(02755);
++#endif
+ seed_addtime(); makedir("root/ip");
+ seed_addtime(); perm(02755);
+ seed_addtime(); start("root/ip/127.0.0.1"); finish();
+diff -ruN djbdns-1.05-dist/dnscache.c djbdns-1.05/dnscache.c
+--- djbdns-1.05-dist/dnscache.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/dnscache.c 2008-08-11 19:33:30.000000000 -0700
+@@ -5,6 +5,7 @@
+ #include "strerr.h"
+ #include "error.h"
+ #include "ip4.h"
++#include "str.h"
+ #include "uint16.h"
+ #include "uint64.h"
+ #include "socket.h"
+@@ -22,6 +23,7 @@
+ #include "log.h"
+ #include "okclient.h"
+ #include "droproot.h"
++#include "sig.h"
+
+ static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2])
+ {
+@@ -47,12 +49,20 @@
+
+
+ static char myipoutgoing[4];
+-static char myipincoming[4];
+ static char buf[1024];
+ uint64 numqueries = 0;
+
++struct interf {
++ char ip[4];
++ int udp53;
++ int tcp53;
++ iopause_fd *udp53io;
++ iopause_fd *tcp53io;
++
++ struct interf *next;
++} ;
+
+-static int udp53;
++struct interf *interhead = 0;
+
+ #define MAXUDP 200
+ static struct udpclient {
+@@ -60,6 +70,7 @@
+ struct taia start;
+ uint64 active; /* query number, if active; otherwise 0 */
+ iopause_fd *io;
++ int fd;
+ char ip[4];
+ uint16 port;
+ char id[2];
+@@ -78,12 +89,12 @@
+ if (!u[j].active) return;
+ response_id(u[j].id);
+ if (response_len > 512) response_tc();
+- socket_send4(udp53,response,response_len,u[j].ip,u[j].port);
++ socket_send4(u[j].fd,response,response_len,u[j].ip,u[j].port);
+ log_querydone(&u[j].active,response_len);
+ u[j].active = 0; --uactive;
+ }
+
+-void u_new(void)
++void u_new(int fd)
+ {
+ int j;
+ int i;
+@@ -108,8 +119,9 @@
+
+ x = u + j;
+ taia_now(&x->start);
++ x->fd = fd;
+
+- len = socket_recv4(udp53,buf,sizeof buf,x->ip,&x->port);
++ len = socket_recv4(x->fd,buf,sizeof buf,x->ip,&x->port);
+ if (len == -1) return;
+ if (len >= sizeof buf) return;
+ if (x->port < 1024) if (x->port != 53) return;
+@@ -129,8 +141,6 @@
+ }
+
+
+-static int tcp53;
+-
+ #define MAXTCP 20
+ struct tcpclient {
+ struct query q;
+@@ -138,6 +148,7 @@
+ struct taia timeout;
+ uint64 active; /* query number or 1, if active; otherwise 0 */
+ iopause_fd *io;
++ int fd;
+ char ip[4]; /* send response to this address */
+ uint16 port; /* send response to this port */
+ char id[2];
+@@ -266,7 +277,7 @@
+ x->state = 0;
+ }
+
+-void t_new(void)
++void t_new(int fd)
+ {
+ int i;
+ int j;
+@@ -290,8 +301,9 @@
+
+ x = t + j;
+ taia_now(&x->start);
++ x->fd = fd;
+
+- x->tcp = socket_accept4(tcp53,x->ip,&x->port);
++ x->tcp = socket_accept4(x->fd,x->ip,&x->port);
+ if (x->tcp == -1) return;
+ if (x->port < 1024) if (x->port != 53) { close(x->tcp); return; }
+ if (!okclient(x->ip)) { close(x->tcp); return; }
+@@ -304,19 +316,44 @@
+ log_tcpopen(x->ip,x->port);
+ }
+
++#ifdef DUMPCACHE
++static void do_dump(void)
++{
++ int r;
++ r = cache_dump();
++ if (r < 0)
++ r = errno;
++ log_dump(r);
++}
++#endif
++
++#define FATAL "dnscache: fatal: "
++
++iopause_fd *io = 0;
++int numio;
++
++void hup_me()
++{
++ if (!roots_init())
++ strerr_die2sys(111,FATAL,"unable to read servers: ");
++
++ log_reread();
++}
+
+-iopause_fd io[3 + MAXUDP + MAXTCP];
+-iopause_fd *udp53io;
+-iopause_fd *tcp53io;
+
+ static void doit(void)
+ {
+ int j;
+ struct taia deadline;
+ struct taia stamp;
++ struct interf *inter;
+ int iolen;
+ int r;
+
++ io = (iopause_fd *) alloc((numio + 1 + MAXUDP + MAXTCP) * sizeof(iopause_fd));
++ if (!io)
++ strerr_die2sys(111,FATAL,"unable to alloc io: ");
++
+ for (;;) {
+ taia_now(&stamp);
+ taia_uint(&deadline,120);
+@@ -324,13 +361,15 @@
+
+ iolen = 0;
+
+- udp53io = io + iolen++;
+- udp53io->fd = udp53;
+- udp53io->events = IOPAUSE_READ;
+-
+- tcp53io = io + iolen++;
+- tcp53io->fd = tcp53;
+- tcp53io->events = IOPAUSE_READ;
++ for (inter = interhead; inter != 0; inter = inter->next) {
++ inter->udp53io = io + iolen++;
++ inter->udp53io->fd = inter->udp53;
++ inter->udp53io->events = IOPAUSE_READ;
++
++ inter->tcp53io = io + iolen++;
++ inter->tcp53io->fd = inter->tcp53;
++ inter->tcp53io->events = IOPAUSE_READ;
++ }
+
+ for (j = 0;j < MAXUDP;++j)
+ if (u[j].active) {
+@@ -372,46 +411,83 @@
+ t_rw(j);
+ }
+
+- if (udp53io)
+- if (udp53io->revents)
+- u_new();
+-
+- if (tcp53io)
+- if (tcp53io->revents)
+- t_new();
++ for (inter = interhead; inter != 0; inter = inter->next) {
++ if (inter->udp53io)
++ if (inter->udp53io->revents)
++ u_new(inter->udp53);
++
++ if (inter->tcp53io)
++ if (inter->tcp53io->revents)
++ t_new(inter->tcp53);
++ }
+ }
+ }
+
+-#define FATAL "dnscache: fatal: "
+-
+ char seed[128];
+
+ int main()
+ {
+ char *x;
++ char nxdip[4];
++ int len;
++ int pos;
++ int oldpos;
++ char iptmp[4];
++ char iperr[IP4_FMT];
++ struct interf *inter;
++ struct interf *itmp;
+ unsigned long cachesize;
+
+ x = env_get("IP");
+ if (!x)
+ strerr_die2x(111,FATAL,"$IP not set");
+- if (!ip4_scan(x,myipincoming))
+- strerr_die3x(111,FATAL,"unable to parse IP address ",x);
+
+- udp53 = socket_udp();
+- if (udp53 == -1)
+- strerr_die2sys(111,FATAL,"unable to create UDP socket: ");
+- if (socket_bind4_reuse(udp53,myipincoming,53) == -1)
+- strerr_die2sys(111,FATAL,"unable to bind UDP socket: ");
+-
+- tcp53 = socket_tcp();
+- if (tcp53 == -1)
+- strerr_die2sys(111,FATAL,"unable to create TCP socket: ");
+- if (socket_bind4_reuse(tcp53,myipincoming,53) == -1)
+- strerr_die2sys(111,FATAL,"unable to bind TCP socket: ");
++ len = str_len(x);
++ numio = pos = oldpos = 0;
++
++ while (pos < len) {
++ if (pos) oldpos = pos + 1;
++ pos = oldpos + str_chr(x + oldpos,'/');
++ x[pos] = 0;
++ if (!str_len(x + oldpos)) continue;
++
++ if (!ip4_scan(x + oldpos,iptmp))
++ strerr_die3x(111,FATAL,"unable to parse IP address ",x + oldpos);
++
++ inter = (struct interf *) alloc(sizeof(struct interf));
++
++ if (interhead == 0) interhead = inter;
++ else if (interhead->next == 0) interhead->next = inter;
++ else {
++ for (itmp = interhead; itmp->next != 0; itmp = itmp->next);
++ itmp->next = inter;
++ }
++
++ inter->next = 0;
++
++ inter->udp53 = socket_udp();
++ if (inter->udp53 == -1)
++ strerr_die4sys(111,FATAL,"unable to create UDP socket for IP address ",x + oldpos,": ");
++ if (socket_bind4_reuse(inter->udp53,iptmp,53) == -1)
++ strerr_die4sys(111,FATAL,"unable to bind UDP socket for IP address ",x + oldpos,": ");
++
++ inter->tcp53 = socket_tcp();
++ if (inter->tcp53 == -1)
++ strerr_die4sys(111,FATAL,"unable to create TCP socket for IP address ",x + oldpos,": ");
++ if (socket_bind4_reuse(inter->tcp53,iptmp,53) == -1)
++ strerr_die4sys(111,FATAL,"unable to bind TCP socket for IP address ",x + oldpos,": ");
++
++ numio++;
++ log_listen(iptmp);
++ }
++
++ if (interhead == 0)
++ strerr_die2x(111,FATAL,"no interfaces to listen on");
+
+ droproot(FATAL);
+
+- socket_tryreservein(udp53,131072);
++ for (inter = interhead; inter != 0; inter = inter->next)
++ socket_tryreservein(inter->udp53,131072);
+
+ byte_zero(seed,sizeof seed);
+ read(0,seed,sizeof seed);
+@@ -430,17 +506,42 @@
+ scan_ulong(x,&cachesize);
+ if (!cache_init(cachesize))
+ strerr_die3x(111,FATAL,"not enough memory for cache of size ",x);
++#ifdef DUMPCACHE
++ x = env_get("SLURPCACHE");
++ if (x) {
++ int nb = cache_slurp(x);
++ if (nb < 0)
++ strerr_die4sys(111,FATAL,"unable to slurp cache ",x," : ");
++ else
++ log_slurp(nb);
++ }
++#endif
+
+ if (env_get("HIDETTL"))
+ response_hidettl();
+ if (env_get("FORWARDONLY"))
+ query_forwardonly();
+
++ x = env_get("NXDSPECIAL");
++ if (x) {
++ if (!ip4_scan(x,nxdip))
++ strerr_die3x(111,FATAL,"unable to parse NXDSPECIAL IP address ",x);
++ query_nxdspecial(nxdip);
++ }
++
+ if (!roots_init())
+ strerr_die2sys(111,FATAL,"unable to read servers: ");
+
+- if (socket_listen(tcp53,20) == -1)
+- strerr_die2sys(111,FATAL,"unable to listen on TCP socket: ");
++ for (inter = interhead; inter != 0; inter = inter->next)
++ if (socket_listen(inter->tcp53,20) == -1) {
++ iperr[ip4_fmt(iperr,inter->ip)] = 0;
++ strerr_die4sys(111,FATAL,"unable to listen on TCP socket for IP ",iperr,": ");
++ }
++
++#ifdef DUMPCACHE
++ sig_catch(sig_alarm,do_dump);
++#endif
++ sig_catch(sig_hangup, hup_me);
+
+ log_startup();
+ doit();
+diff -ruN djbdns-1.05-dist/dnsfilter.c djbdns-1.05/dnsfilter.c
+--- djbdns-1.05-dist/dnsfilter.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/dnsfilter.c 2008-08-11 19:33:30.000000000 -0700
+@@ -41,6 +41,7 @@
+ iopause_fd *inio;
+ int flag0 = 1;
+
++int opt_replace = 0;
+ iopause_fd *io;
+ int iolen;
+
+@@ -51,12 +52,16 @@
+ void errout(int i)
+ {
+ int j;
+-
+- if (!stralloc_copys(&x[i].middle,":")) nomem();
+- if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
+- for (j = 0;j < x[i].middle.len;++j)
+- if (x[i].middle.s[j] == ' ')
+- x[i].middle.s[j] = '-';
++
++ if (opt_replace)
++ x[i].middle.len=0;
++ else {
++ if (!stralloc_copys(&x[i].middle,":")) nomem();
++ if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
++ for (j = 0;j < x[i].middle.len;++j)
++ if (x[i].middle.s[j] == ' ')
++ x[i].middle.s[j] = '-';
++ }
+ }
+
+ int main(int argc,char **argv)
+@@ -69,7 +74,7 @@
+ int j;
+ int r;
+
+- while ((opt = getopt(argc,argv,"c:l:")) != opteof)
++ while ((opt = getopt(argc,argv,"c:l:r")) != opteof)
+ switch(opt) {
+ case 'c':
+ scan_ulong(optarg,&u);
+@@ -83,8 +88,11 @@
+ if (u > 1000000) u = 1000000;
+ xmax = u;
+ break;
++ case 'r':
++ opt_replace = 1;
++ break;
+ default:
+- strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ]");
++ strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ] [-r]");
+ }
+
+ x = (struct line *) alloc(xmax * sizeof(struct line));
+@@ -140,8 +148,13 @@
+ else if (r == 1) {
+ if (dns_name_packet(&x[i].middle,x[i].dt.packet,x[i].dt.packetlen) == -1)
+ errout(i);
+- if (x[i].middle.len)
+- if (!stralloc_cats(&x[i].left,"=")) nomem();
++ if (x[i].middle.len) {
++ if (opt_replace) {
++ if (!stralloc_copys(&x[i].left, "")) nomem();
++ } else {
++ if (!stralloc_cats(&x[i].left, "=")) nomem();
++ }
++ }
+ x[i].flagactive = 0;
+ --numactive;
+ }
+diff -ruN djbdns-1.05-dist/hasdevtcp.h djbdns-1.05/hasdevtcp.h
+--- djbdns-1.05-dist/hasdevtcp.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/hasdevtcp.h 2008-08-11 22:55:09.000000000 -0700
+@@ -0,0 +1 @@
++/* sysdep: -devtcp */
+diff -ruN djbdns-1.05-dist/hassgact.h djbdns-1.05/hassgact.h
+--- djbdns-1.05-dist/hassgact.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/hassgact.h 2008-08-11 22:55:16.000000000 -0700
+@@ -0,0 +1,2 @@
++/* sysdep: +sigaction */
++#define HASSIGACTION 1
+diff -ruN djbdns-1.05-dist/hassgact.h1 djbdns-1.05/hassgact.h1
+--- djbdns-1.05-dist/hassgact.h1 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/hassgact.h1 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1 @@
++/* sysdep: -sigaction */
+diff -ruN djbdns-1.05-dist/hassgact.h2 djbdns-1.05/hassgact.h2
+--- djbdns-1.05-dist/hassgact.h2 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/hassgact.h2 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,2 @@
++/* sysdep: +sigaction */
++#define HASSIGACTION 1
+diff -ruN djbdns-1.05-dist/hassgprm.h djbdns-1.05/hassgprm.h
+--- djbdns-1.05-dist/hassgprm.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/hassgprm.h 2008-08-11 22:55:15.000000000 -0700
+@@ -0,0 +1,2 @@
++/* sysdep: +sigprocmask */
++#define HASSIGPROCMASK 1
+diff -ruN djbdns-1.05-dist/hassgprm.h1 djbdns-1.05/hassgprm.h1
+--- djbdns-1.05-dist/hassgprm.h1 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/hassgprm.h1 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1 @@
++/* sysdep: -sigprocmask */
+diff -ruN djbdns-1.05-dist/hassgprm.h2 djbdns-1.05/hassgprm.h2
+--- djbdns-1.05-dist/hassgprm.h2 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/hassgprm.h2 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,2 @@
++/* sysdep: +sigprocmask */
++#define HASSIGPROCMASK 1
+diff -ruN djbdns-1.05-dist/hasshsgr.h djbdns-1.05/hasshsgr.h
+--- djbdns-1.05-dist/hasshsgr.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/hasshsgr.h 2008-08-12 09:17:24.000000000 -0700
+@@ -0,0 +1 @@
++/* sysdep: -shortsetgroups */
+diff -ruN djbdns-1.05-dist/iopause.h djbdns-1.05/iopause.h
+--- djbdns-1.05-dist/iopause.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/iopause.h 2008-08-11 22:55:12.000000000 -0700
+@@ -0,0 +1,18 @@
++#ifndef IOPAUSE_H
++#define IOPAUSE_H
++
++/* sysdep: +poll */
++#define IOPAUSE_POLL
++
++#include <sys/types.h>
++#include <poll.h>
++
++typedef struct pollfd iopause_fd;
++#define IOPAUSE_READ POLLIN
++#define IOPAUSE_WRITE POLLOUT
++
++#include "taia.h"
++
++extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *);
++
++#endif
+diff -ruN djbdns-1.05-dist/log.c djbdns-1.05/log.c
+--- djbdns-1.05-dist/log.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/log.c 2008-08-11 19:33:30.000000000 -0700
+@@ -88,12 +88,39 @@
+ }
+ }
+
++void log_reread(void)
++{
++ string("rereading servers configuration");
++ line();
++}
++
+ void log_startup(void)
+ {
+ string("starting");
+ line();
+ }
+
++void log_listen(const char addr[4])
++{
++ string("listening on ");
++ ip(addr);
++ line();
++}
++
++#ifdef DUMPCACHE
++void log_slurp(int nb)
++{
++ string("slurp "); number(nb);
++ line();
++}
++
++void log_dump(int err)
++{
++ string("dump err "); number(err);
++ line();
++}
++#endif
++
+ void log_query(uint64 *qnum,const char client[4],unsigned int port,const char id[2],const char *q,const char qtype[2])
+ {
+ string("query "); number(*qnum); space();
+diff -ruN djbdns-1.05-dist/log.h djbdns-1.05/log.h
+--- djbdns-1.05-dist/log.h 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/log.h 2008-08-11 19:33:30.000000000 -0700
+@@ -4,6 +4,12 @@
+ #include "uint64.h"
+
+ extern void log_startup(void);
++extern void log_listen(const char *);
++#ifdef DUMPCACHE
++extern void log_slurp(int);
++extern void log_dump(int);
++#endif
++extern void log_reread(void);
+
+ extern void log_query(uint64 *,const char *,unsigned int,const char *,const char *,const char *);
+ extern void log_querydrop(uint64 *);
+diff -ruN djbdns-1.05-dist/okclient.c djbdns-1.05/okclient.c
+--- djbdns-1.05-dist/okclient.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/okclient.c 2008-08-11 19:33:30.000000000 -0700
+@@ -1,5 +1,6 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include "env.h"
+ #include "str.h"
+ #include "ip4.h"
+ #include "okclient.h"
+@@ -10,6 +11,14 @@
+ {
+ struct stat st;
+ int i;
++ static int init_done=0;
++ if (!init_done) {
++ if (env_get("OKCLIENT")) {
++ init_done=1;
++ } else
++ init_done=2;
++ }
++ if (init_done==1) return 1;
+
+ fn[0] = 'i';
+ fn[1] = 'p';
+diff -ruN djbdns-1.05-dist/parsetype.c djbdns-1.05/parsetype.c
+--- djbdns-1.05-dist/parsetype.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/parsetype.c 2008-08-11 22:49:52.000000000 -0700
+@@ -24,6 +24,8 @@
+ else if (case_equals(s,"key")) byte_copy(type,2,DNS_T_KEY);
+ else if (case_equals(s,"aaaa")) byte_copy(type,2,DNS_T_AAAA);
+ else if (case_equals(s,"axfr")) byte_copy(type,2,DNS_T_AXFR);
++ else if (case_equals(s,"srv")) byte_copy(type,2,DNS_T_SRV);
++ else if (case_equals(s,"naptr")) byte_copy(type,2,DNS_T_NAPTR);
+ else
+ return 0;
+
+diff -ruN djbdns-1.05-dist/printrecord.c djbdns-1.05/printrecord.c
+--- djbdns-1.05-dist/printrecord.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/printrecord.c 2008-08-11 23:10:20.000000000 -0700
+@@ -82,6 +82,56 @@
+ if (!stralloc_catulong0(out,ch,0)) return 0;
+ }
+ }
++ else if (byte_equal(misc,2,DNS_T_SRV)) {
++ if (!stralloc_cats(out," SRV ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0;
++ uint16_unpack_big(misc,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0;
++ uint16_unpack_big(misc,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0;
++ uint16_unpack_big(misc,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
++ if (!dns_domain_todot_cat(out,d)) return 0;
++ }
++ else if (byte_equal(misc,2,DNS_T_NAPTR)) {
++ char str[255];
++ unsigned int oldpos;
++ if (!stralloc_cats(out," NAPTR ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0;
++ uint16_unpack_big(misc,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0;
++ uint16_unpack_big(misc,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,&ch,1); if (!pos) return 0;
++ pos = dns_packet_copy(buf,len,pos,str,ch); if (!pos) return 0;
++ if (!stralloc_cats(out,"\"")) return 0;
++ if (!stralloc_catb(out,str,ch)) return 0;
++ if (!stralloc_cats(out,"\" ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,&ch,1); if (!pos) return 0;
++ pos = dns_packet_copy(buf,len,pos,str,ch); if (!pos) return 0;
++ if (!stralloc_cats(out,"\"")) return 0;
++ if (!stralloc_catb(out,str,ch)) return 0;
++ if (!stralloc_cats(out,"\" ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,&ch,1); if (!pos) return 0;
++ pos = dns_packet_copy(buf,len,pos,str,ch); if (!pos) return 0;
++ if (!stralloc_cats(out,"\"")) return 0;
++ if (!stralloc_catb(out,str,ch)) return 0;
++ if (!stralloc_cats(out,"\" ")) return 0;
++ pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
++ oldpos = out->len;
++ if (!dns_domain_todot_cat(out,d)) return 0;
++ if (out->len == oldpos)
++ if (!stralloc_cats(out,".")) return 0;
++ }
+ else {
+ if (!stralloc_cats(out," ")) return 0;
+ uint16_unpack_big(misc,&u16);
+diff -ruN djbdns-1.05-dist/prot.c djbdns-1.05/prot.c
+--- djbdns-1.05-dist/prot.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/prot.c 2008-08-11 19:33:30.000000000 -0700
+@@ -1,5 +1,7 @@
+ #include "hasshsgr.h"
+ #include "prot.h"
++#include <grp.h>
++#include <unistd.h>
+
+ int prot_gid(int gid)
+ {
+diff -ruN djbdns-1.05-dist/query.c djbdns-1.05/query.c
+--- djbdns-1.05-dist/query.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/query.c 2008-08-11 19:33:30.000000000 -0700
+@@ -20,6 +20,15 @@
+ flagforwardonly = 1;
+ }
+
++static int flagnxdspecial = 0;
++static char nxdip[4];
++
++void query_nxdspecial(const char ip[4])
++{
++ byte_copy(nxdip,4,ip);
++ flagnxdspecial = 1;
++}
++
+ static void cachegeneric(const char type[2],const char *d,const char *data,unsigned int datalen,uint32 ttl)
+ {
+ unsigned int len;
+@@ -246,6 +255,7 @@
+ case_lowerb(key + 2,dlen);
+ cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+ if (cached) {
++ soattl = rcode = 0;
+ log_cachednxdomain(d);
+ goto NXDOMAIN;
+ }
+@@ -695,7 +705,12 @@
+ NXDOMAIN:
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+- response_nxdomain();
++ if (flagnxdspecial && typematch(DNS_T_A,dtype)) {
++ if (!response_rstart(d,DNS_T_A,rcode == 3 ? soattl : ttl)) goto DIE;
++ if (!response_addbytes(nxdip,4)) goto DIE;
++ response_rfinish(RESPONSE_ANSWER);
++ } else
++ response_nxdomain();
+ cleanup(z);
+ return 1;
+ }
+diff -ruN djbdns-1.05-dist/query.h djbdns-1.05/query.h
+--- djbdns-1.05-dist/query.h 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/query.h 2008-08-11 19:33:30.000000000 -0700
+@@ -28,5 +28,6 @@
+ extern int query_get(struct query *,iopause_fd *,struct taia *);
+
+ extern void query_forwardonly(void);
++extern void query_nxdspecial(const char *);
+
+ #endif
+diff -ruN djbdns-1.05-dist/seek_set.c djbdns-1.05/seek_set.c
+--- djbdns-1.05-dist/seek_set.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/seek_set.c 2008-08-11 19:33:30.000000000 -0700
+@@ -1,4 +1,5 @@
+ #include <sys/types.h>
++#include <unistd.h>
+ #include "seek.h"
+
+ #define SET 0 /* sigh */
+diff -ruN djbdns-1.05-dist/select.h djbdns-1.05/select.h
+--- djbdns-1.05-dist/select.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/select.h 2008-08-11 22:55:14.000000000 -0700
+@@ -0,0 +1,11 @@
++#ifndef SELECT_H
++#define SELECT_H
++
++/* sysdep: +sysselect */
++
++#include <sys/types.h>
++#include <sys/time.h>
++#include <sys/select.h>
++extern int select();
++
++#endif
+diff -ruN djbdns-1.05-dist/server.c djbdns-1.05/server.c
+--- djbdns-1.05-dist/server.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/server.c 2008-08-11 19:33:30.000000000 -0700
+@@ -11,6 +11,8 @@
+ #include "qlog.h"
+ #include "response.h"
+ #include "dns.h"
++#include "alloc.h"
++#include "iopause.h"
+
+ extern char *fatal;
+ extern char *starting;
+@@ -25,6 +27,44 @@
+
+ static char *q;
+
++
++static void hex(unsigned char c)
++{
++ buffer_put(buffer_2,"0123456789abcdef" + (c >> 4),1);
++ buffer_put(buffer_2,"0123456789abcdef" + (c & 15),1);
++}
++
++static void put_ip(const char i[4])
++{
++ hex(i[0]);
++ hex(i[1]);
++ hex(i[2]);
++ hex(i[3]);
++}
++
++static void string(const char *s)
++{
++ buffer_puts(buffer_2,s);
++}
++
++static void line(void)
++{
++ string("\n");
++ buffer_flush(buffer_2);
++}
++
++void log_listen(const char addr[4])
++{
++ string("listening on ");
++ put_ip(addr);
++ line();
++}
++
++void nomem()
++{
++ strerr_die2x(111,fatal,"out of memory");
++}
++
+ static int doit(void)
+ {
+ unsigned int pos;
+@@ -51,6 +91,13 @@
+ response[3] &= ~128;
+ if (!(header[2] & 1)) response[2] &= ~1;
+
++ if ((header[2] & 126) == 0x24) /* NOTIFY + AA */
++ if (byte_equal(qtype,2,DNS_T_SOA)) {
++ response[2] |= 0x20; /* NOTIFY */
++ qlog(ip,port,header,q,qtype," N ");
++ return 1;
++ }
++
+ if (header[2] & 126) goto NOTIMP;
+ if (byte_equal(qtype,2,DNS_T_AXFR)) goto NOTIMP;
+
+@@ -59,7 +106,12 @@
+ qlog(ip,port,header,q,qtype," - ");
+ return 0;
+ }
+- qlog(ip,port,header,q,qtype," + ");
++
++ if ((response[2] & 4) && (response[3] & 3))
++ qlog(ip,port,header,q,qtype," X ");
++ else
++ qlog(ip,port,header,q,qtype," + ");
++
+ return 1;
+
+ NOTIMP:
+@@ -82,35 +134,75 @@
+ int main()
+ {
+ char *x;
+- int udp53;
++ int *udp53;
++ unsigned int off;
++ unsigned int cnt;
++ iopause_fd *iop;
+
+ x = env_get("IP");
+ if (!x)
+ strerr_die2x(111,fatal,"$IP not set");
+- if (!ip4_scan(x,ip))
+- strerr_die3x(111,fatal,"unable to parse IP address ",x);
+-
+- udp53 = socket_udp();
+- if (udp53 == -1)
+- strerr_die2sys(111,fatal,"unable to create UDP socket: ");
+- if (socket_bind4_reuse(udp53,ip,53) == -1)
+- strerr_die2sys(111,fatal,"unable to bind UDP socket: ");
++ off=0;
++ cnt=0;
++ while (x[off]) {
++ unsigned int l;
++ char dummy[4];
++ l=ip4_scan(x+off,dummy);
++ if (!l)
++ strerr_die3x(111,fatal,"unable to parse IP address ",x+off);
++ cnt++;
++ if (!x[off+l]) break;
++ if (x[off+l]!='/')
++ strerr_die3x(111,fatal,"unable to parse IP address ",x+off);
++ off+=l+1;
++ }
++ udp53=(int *) alloc(sizeof(int) *cnt);
++ if (!udp53) nomem();
++ iop=(iopause_fd *) alloc(sizeof(*iop) * cnt);
++ if (!iop) nomem();
++
++ off=0;
++ cnt=0;
++ while (x[off]) {
++ unsigned int l;
++ l=ip4_scan(x+off,ip);
++ udp53[cnt] = socket_udp();
++ if (udp53[cnt] == -1)
++ strerr_die2sys(111,fatal,"unable to create UDP socket: ");
++ if (socket_bind4_reuse(udp53[cnt],ip,53) == -1)
++ strerr_die2sys(111,fatal,"unable to bind UDP socket: ");
++ ndelay_off(udp53[cnt]);
++ socket_tryreservein(udp53[cnt],65536);
++ iop[cnt].fd=udp53[cnt];
++ iop[cnt].events=IOPAUSE_READ;
++ log_listen(ip);
++ cnt++;
++ if (!x[off+l]) break;
++ off+=l+1;
++ }
+
+ droproot(fatal);
+
+ initialize();
+-
+- ndelay_off(udp53);
+- socket_tryreservein(udp53,65536);
+
+ buffer_putsflush(buffer_2,starting);
+-
++
+ for (;;) {
+- len = socket_recv4(udp53,buf,sizeof buf,ip,&port);
+- if (len < 0) continue;
+- if (!doit()) continue;
+- if (response_len > 512) response_tc();
+- socket_send4(udp53,response,response_len,ip,port);
+- /* may block for buffer space; if it fails, too bad */
++ struct taia stamp;
++ struct taia deadline;
++ unsigned int i;
++ taia_now(&stamp);
++ taia_uint(&deadline,300);
++ taia_add(&deadline,&deadline,&stamp);
++ iopause(iop,cnt,&deadline,&stamp);
++ for (i=0;i<cnt;i++)
++ if (iop[i].revents) {
++ len = socket_recv4(udp53[i],buf,sizeof buf,ip,&port);
++ if (len < 0) continue;
++ if (!doit()) continue;
++ if (response_len > 512) response_tc();
++ socket_send4(udp53[i],response,response_len,ip,port);
++ /* may block for buffer space; if it fails, too bad */
++ }
+ }
+ }
+diff -ruN djbdns-1.05-dist/sig.c djbdns-1.05/sig.c
+--- djbdns-1.05-dist/sig.c 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/sig.c 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,12 @@
++#include <signal.h>
++#include "sig.h"
++
++int sig_alarm = SIGALRM;
++int sig_child = SIGCHLD;
++int sig_cont = SIGCONT;
++int sig_hangup = SIGHUP;
++int sig_pipe = SIGPIPE;
++int sig_term = SIGTERM;
++
++void (*sig_defaulthandler)() = SIG_DFL;
++void (*sig_ignorehandler)() = SIG_IGN;
+diff -ruN djbdns-1.05-dist/sig.h djbdns-1.05/sig.h
+--- djbdns-1.05-dist/sig.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/sig.h 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,25 @@
++#ifndef SIG_H
++#define SIG_H
++
++extern int sig_alarm;
++extern int sig_child;
++extern int sig_cont;
++extern int sig_hangup;
++extern int sig_pipe;
++extern int sig_term;
++
++extern void (*sig_defaulthandler)();
++extern void (*sig_ignorehandler)();
++
++extern void sig_catch(int,void (*)());
++#define sig_ignore(s) (sig_catch((s),sig_ignorehandler))
++#define sig_uncatch(s) (sig_catch((s),sig_defaulthandler))
++
++extern void sig_block(int);
++extern void sig_unblock(int);
++extern void sig_blocknone(void);
++extern void sig_pause(void);
++
++extern void sig_dfl(int);
++
++#endif
+diff -ruN djbdns-1.05-dist/sig_block.c djbdns-1.05/sig_block.c
+--- djbdns-1.05-dist/sig_block.c 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/sig_block.c 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,38 @@
++#include <signal.h>
++#include "sig.h"
++#include "hassgprm.h"
++
++void sig_block(int sig)
++{
++#ifdef HASSIGPROCMASK
++ sigset_t ss;
++ sigemptyset(&ss);
++ sigaddset(&ss,sig);
++ sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0);
++#else
++ sigblock(1 << (sig - 1));
++#endif
++}
++
++void sig_unblock(int sig)
++{
++#ifdef HASSIGPROCMASK
++ sigset_t ss;
++ sigemptyset(&ss);
++ sigaddset(&ss,sig);
++ sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0);
++#else
++ sigsetmask(sigsetmask(~0) & ~(1 << (sig - 1)));
++#endif
++}
++
++void sig_blocknone(void)
++{
++#ifdef HASSIGPROCMASK
++ sigset_t ss;
++ sigemptyset(&ss);
++ sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
++#else
++ sigsetmask(0);
++#endif
++}
+diff -ruN djbdns-1.05-dist/sig_catch.c djbdns-1.05/sig_catch.c
+--- djbdns-1.05-dist/sig_catch.c 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/sig_catch.c 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,16 @@
++#include <signal.h>
++#include "sig.h"
++#include "hassgact.h"
++
++void sig_catch(int sig,void (*f)())
++{
++#ifdef HASSIGACTION
++ struct sigaction sa;
++ sa.sa_handler = f;
++ sa.sa_flags = 0;
++ sigemptyset(&sa.sa_mask);
++ sigaction(sig,&sa,(struct sigaction *) 0);
++#else
++ signal(sig,f); /* won't work under System V, even nowadays---dorks */
++#endif
++}
+diff -ruN djbdns-1.05-dist/sig_pause.c djbdns-1.05/sig_pause.c
+--- djbdns-1.05-dist/sig_pause.c 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/sig_pause.c 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,14 @@
++#include <signal.h>
++#include "sig.h"
++#include "hassgprm.h"
++
++void sig_pause(void)
++{
++#ifdef HASSIGPROCMASK
++ sigset_t ss;
++ sigemptyset(&ss);
++ sigsuspend(&ss);
++#else
++ sigpause(0);
++#endif
++}
+diff -ruN djbdns-1.05-dist/tinydns-data.c djbdns-1.05/tinydns-data.c
+--- djbdns-1.05-dist/tinydns-data.c 2008-08-11 19:32:53.000000000 -0700
++++ djbdns-1.05/tinydns-data.c 2008-08-11 22:56:09.000000000 -0700
+@@ -159,11 +159,7 @@
+ die_datatmp();
+ }
+
+-buffer b;
+-char bspace[1024];
+-
+ static stralloc line;
+-int match = 1;
+ unsigned long linenum = 0;
+
+ #define NUMFIELDS 15
+@@ -171,6 +167,8 @@
+
+ static char *d1;
+ static char *d2;
++static char *contact;
++
+ char dptr[DNS_NAME4_DOMAIN];
+
+ char strnum[FMT_ULONG];
+@@ -181,7 +179,7 @@
+ strerr_die4x(111,FATAL,"unable to parse data line ",strnum,why);
+ }
+
+-int main()
++int load(const char *fname)
+ {
+ int fddata;
+ int i;
+@@ -196,20 +194,20 @@
+ char type[2];
+ char soa[20];
+ char buf[4];
++ char naptr[4];
++ char srv[6];
++ int match;
++ buffer b;
++ char bspace[1024];
+
+- umask(022);
+-
+- fddata = open_read("data");
++ fddata = open_read(fname);
+ if (fddata == -1)
+- strerr_die2sys(111,FATAL,"unable to open data: ");
++ strerr_die4sys(111,FATAL,"unable to open ",fname,": ");
+ defaultsoa_init(fddata);
+
+ buffer_init(&b,buffer_unixread,fddata,bspace,sizeof bspace);
+
+- fdcdb = open_trunc("data.tmp");
+- if (fdcdb == -1) die_datatmp();
+- if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
+-
++ match = 1;
+ while (match) {
+ ++linenum;
+ if (getln(&b,&line,&match,'\n') == -1)
+@@ -247,6 +245,11 @@
+ die_datatmp();
+ break;
+
++ case 'D':
++ if (!dns_domain_fromdot(&contact,f[0].s,f[0].len)) nomem();
++ if (f[0].len == 0) contact = NULL;
++ break;
++
+ case 'Z':
+ if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+
+@@ -298,8 +301,13 @@
+ if (line.s[0] == '.') {
+ rr_start(DNS_T_SOA,ttl ? TTL_NEGATIVE : 0,ttd,loc);
+ rr_addname(d2);
+- rr_add("\12hostmaster",11);
+- rr_addname(d1);
++ if (!contact) {
++ rr_add("\12hostmaster",11);
++ rr_addname(d1);
++ } else {
++ rr_addname(contact);
++ }
++
+ rr_add(defaultsoa,20);
+ rr_finish(d1);
+ }
+@@ -369,6 +377,43 @@
+ rr_finish(d2);
+ }
+ break;
++
++ case 'S':
++ if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
++ if (!stralloc_0(&f[6])) nomem();
++ if (!scan_ulong(f[6].s,&ttl)) ttl = TTL_POSITIVE;
++ ttdparse(&f[7],ttd);
++ locparse(&f[8],loc);
++
++ if (!stralloc_0(&f[1])) nomem();
++
++ if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) {
++ if (!stralloc_cats(&f[2],".srv.")) nomem();
++ if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem();
++ }
++ if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem();
++
++ if (!stralloc_0(&f[4])) nomem();
++ if (!scan_ulong(f[4].s,&u)) u = 0;
++ uint16_pack_big(srv,u);
++ if (!stralloc_0(&f[5])) nomem();
++ if (!scan_ulong(f[5].s,&u)) u = 0;
++ uint16_pack_big(srv + 2,u);
++ if (!stralloc_0(&f[3])) nomem();
++ if (!scan_ulong(f[3].s,&u)) nomem();
++ uint16_pack_big(srv + 4,u);
++
++ rr_start(DNS_T_SRV,ttl,ttd,loc);
++ rr_add(srv,6);
++ rr_addname(d2);
++ rr_finish(d1);
++
++ if (ip4_scan(f[1].s,ip)) {
++ rr_start(DNS_T_A,ttl,ttd,loc);
++ rr_add(ip,4);
++ rr_finish(d2);
++ }
++ break;
+
+ case '^': case 'C':
+ if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+@@ -441,10 +486,61 @@
+ rr_finish(d1);
+ break;
+
++ case 'N':
++ if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
++ if (!dns_domain_fromdot(&d2,f[6].s,f[6].len)) nomem();
++ if (!stralloc_0(&f[7])) nomem();
++ if (!scan_ulong(f[7].s,&ttl)) ttl = TTL_POSITIVE;
++ ttdparse(&f[8],ttd);
++ locparse(&f[9],loc);
++
++ if (!stralloc_0(&f[1])) nomem();
++ if (!scan_ulong(f[1].s,&u)) u = 0;
++ uint16_pack_big(naptr,u);
++ if (!stralloc_0(&f[2])) nomem();
++ if (!scan_ulong(f[2].s,&u)) u = 0;
++ uint16_pack_big(naptr + 2,u);
++
++ txtparse(&f[3]); if (f[3].len > 255)
++ syntaxerror(": it is not allowed more than 255 chars in a label");
++ txtparse(&f[4]); if (f[4].len > 255)
++ syntaxerror(": it is not allowed more than 255 chars in a label");
++ txtparse(&f[5]); if (f[5].len > 255)
++ syntaxerror(": it is not allowed more than 255 chars in a label");
++
++ rr_start(DNS_T_NAPTR,ttl,ttd,loc);
++ rr_add(naptr,4);
++
++ ch = f[3].len; rr_add(&ch,1);
++ rr_add(f[3].s, f[3].len);
++ ch = f[4].len; rr_add(&ch,1);
++ rr_add(f[4].s, f[4].len);
++ ch = f[5].len; rr_add(&ch,1);
++ rr_add(f[5].s, f[5].len);
++
++ rr_addname(d2);
++ rr_finish(d1);
++ break;
++
+ default:
+ syntaxerror(": unrecognized leading character");
+ }
+ }
++ close(fddata);
++}
++
++int main(int argc, char **argv)
++{
++ umask(022);
++ fdcdb = open_trunc("data.tmp");
++ if (fdcdb == -1) die_datatmp();
++ if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
++
++ if (argc == 1)
++ load("data");
++ while(--argc) {
++ load(argv[argc]);
++ }
+
+ if (cdb_make_finish(&cdb) == -1) die_datatmp();
+ if (fsync(fdcdb) == -1) die_datatmp();
+diff -ruN djbdns-1.05-dist/trysgact.c djbdns-1.05/trysgact.c
+--- djbdns-1.05-dist/trysgact.c 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/trysgact.c 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,10 @@
++#include <signal.h>
++
++main()
++{
++ struct sigaction sa;
++ sa.sa_handler = 0;
++ sa.sa_flags = 0;
++ sigemptyset(&sa.sa_mask);
++ sigaction(0,&sa,(struct sigaction *) 0);
++}
+diff -ruN djbdns-1.05-dist/trysgprm.c djbdns-1.05/trysgprm.c
+--- djbdns-1.05-dist/trysgprm.c 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/trysgprm.c 2008-08-11 19:33:30.000000000 -0700
+@@ -0,0 +1,10 @@
++#include <signal.h>
++
++main()
++{
++ sigset_t ss;
++
++ sigemptyset(&ss);
++ sigaddset(&ss,SIGCHLD);
++ sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
++}
+diff -ruN djbdns-1.05-dist/uint32.h djbdns-1.05/uint32.h
+--- djbdns-1.05-dist/uint32.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/uint32.h 2008-08-11 22:55:10.000000000 -0700
+@@ -0,0 +1,11 @@
++#ifndef UINT32_H
++#define UINT32_H
++
++typedef unsigned long uint32;
++
++extern void uint32_pack(char *,uint32);
++extern void uint32_pack_big(char *,uint32);
++extern void uint32_unpack(const char *,uint32 *);
++extern void uint32_unpack_big(const char *,uint32 *);
++
++#endif
+diff -ruN djbdns-1.05-dist/uint64.h djbdns-1.05/uint64.h
+--- djbdns-1.05-dist/uint64.h 1969-12-31 16:00:00.000000000 -0800
++++ djbdns-1.05/uint64.h 2008-08-11 22:55:10.000000000 -0700
+@@ -0,0 +1,8 @@
++#ifndef UINT64_H
++#define UINT64_H
++
++/* sysdep: -ulong64 */
++
++typedef unsigned long long uint64;
++
++#endif
diff --git a/main/djbdns/dnscache.confd b/main/djbdns/dnscache.confd
new file mode 100644
index 0000000000..e5312812cd
--- /dev/null
+++ b/main/djbdns/dnscache.confd
@@ -0,0 +1,25 @@
+# DNSCACHE configuration variables:
+
+# IPSEND - ip address to use for requests use 0.0.0.0 for default route
+IPSEND=0.0.0.0
+
+# CACHESIZE - Num bytes to use for the cache
+CACHESIZE=1000000
+
+# IP - IP addr to listen on
+IP=127.0.0.1
+
+#------------------------------------------------------------------------
+# The following are flags. Setting them to ANY value
+# (even "false" or "off") will turn the feature on.
+#------------------------------------------------------------------------
+
+# HIDETTL - always return TTL as 0
+#HIDETTL=
+
+# FORWARDONLY - servers/@ are parent caches, not root servers
+#FORWARDONLY=
+
+# UPDATEHINTS - refresh zone hints
+UPDATEHINTS=1
+
diff --git a/main/djbdns/dnscache.initd b/main/djbdns/dnscache.initd
new file mode 100755
index 0000000000..37d9d9ba73
--- /dev/null
+++ b/main/djbdns/dnscache.initd
@@ -0,0 +1,46 @@
+#!/sbin/runscript
+# control n instances of dnscache, without daemontools
+# written for alpine linux - NBA April 2007
+
+# -- Statrup variables
+ROOT=/etc/dnscache
+DAEMON=/usr/bin/dnscache
+PIDFILE=/var/run/dnscache.pid
+
+depend() {
+ need net
+ after firewall
+ provide dns
+}
+
+#-----------------------------------------------------------------
+# Main program
+
+start() {
+ UID=$(id -u dnscache)
+ GID=$(id -g dnscache)
+
+ ebegin "Starting dnscache"
+ if [ -z "$UID" ] || [ -z "$GID" ]; then
+ eend 1 "dnscache user or group missing"
+ return 1
+ fi
+
+ OPTS=""
+ [ "$FORWARDONLY" ] && OPTS="$OPTS --env FORWARDONLY=$FORWARDONLY"
+ [ "$HIDETTL" ] && OPTS="$OPTS --env HIDETTL=$HIDETTL"
+ [ "$CACHESIZE" ] && OPTS="$OPTS --env CACHESIZE=$CACHESIZE"
+
+ start-stop-daemon --start --env "UID=$UID" --env "GID=$GID" \
+ --env "ROOT=$ROOT" --env "IP=$IP" --env "IPSEND=$IPSEND" \
+ $OPTS --pidfile $PIDFILE \
+ --background --make-pidfile --exec $DAEMON -- < /dev/urandom
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping dnscache"
+ start-stop-daemon --stop --pidfile $PIDFILE --exec $DAEMON
+ eend $?
+}
+
diff --git a/main/djbdns/dnscache.monthly b/main/djbdns/dnscache.monthly
new file mode 100755
index 0000000000..574d56f01d
--- /dev/null
+++ b/main/djbdns/dnscache.monthly
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+if [ -f /etc/conf.d/dnscache ]; then
+ . /etc/conf.d/dnscache
+fi
+
+if [ -z "$UPDATEHINTS" ]; then
+ exit 0
+fi
+
+cd /etc/dnscache/servers
+NEEDRESTART=
+ZONES=`ls /etc/dnscache/servers`
+for ZONEFILE in $ZONES; do
+ # Convert symlinks to copies, so we can update it
+ ZONE="$ZONEFILE"
+ if [ -L $ZONEFILE ]; then
+ DST="`readlink "$ZONEFILE"`"
+ cp -f "$DST" "$ZONEFILE"
+ fi
+
+ if [ "$ZONE" = "@" ]; then
+ ZONE="."
+ fi
+
+ if [ "$ZONE" != "." -o "$FORWARDONLY" = "" ]; then
+ TMPF=`mktemp -t`
+
+ # Refresh zone info
+ dnsqr ns $ZONE | awk '/^answer: ./ { print $5 }' | sort -u | xargs dnsip > $TMPF
+ if egrep -q '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' $TMPF; then
+ cmp -s $ZONEFILE $TMPF
+ if [ "$?" != 0 ]; then
+ NEEDRESTART=yes
+ cat $TMPF > $ZONEFILE
+ fi
+ fi
+ rm $TMPF
+ fi
+done
+
+if [ "$NEEDRESTART" ] && /etc/init.d/dnscache --quiet status; then
+ /etc/init.d/dnscache --quiet restart
+fi
+
+exit 0
diff --git a/main/djbdns/dnscache.pre-install b/main/djbdns/dnscache.pre-install
new file mode 100644
index 0000000000..061b8f0280
--- /dev/null
+++ b/main/djbdns/dnscache.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /etc/dnscache -g dnscache -s /bin/false -H -D dnscache 2>/dev/null
+exit 0
+
diff --git a/main/djbdns/dnsroots.patch b/main/djbdns/dnsroots.patch
new file mode 100644
index 0000000000..1b3045853e
--- /dev/null
+++ b/main/djbdns/dnsroots.patch
@@ -0,0 +1,20 @@
+diff -ur a/dnsroots.global b/dnsroots.global
+--- a/dnsroots.global 2009-09-15 12:31:25.000000000 +0000
++++ b/dnsroots.global 2009-09-15 12:31:51.000000000 +0000
+@@ -1,5 +1,5 @@
+ 198.41.0.4
+-128.9.0.107
++192.228.79.201
+ 192.33.4.12
+ 128.8.10.90
+ 192.203.230.10
+@@ -7,7 +7,7 @@
+ 192.112.36.4
+ 128.63.2.53
+ 192.36.148.17
+-198.41.0.10
++192.58.128.30
+ 193.0.14.129
+-198.32.64.12
++199.7.83.42
+ 202.12.27.33
diff --git a/main/djbdns/dnstracesort.patch b/main/djbdns/dnstracesort.patch
new file mode 100644
index 0000000000..3bf56f5a1c
--- /dev/null
+++ b/main/djbdns/dnstracesort.patch
@@ -0,0 +1,11 @@
+--- djbdns-1.05/dnstracesort.sh.orig 2006-04-26 21:52:54.000000000 +0200
++++ djbdns-1.05/dnstracesort.sh 2006-04-26 21:53:02.000000000 +0200
+@@ -12,7 +12,7 @@
+ }
+ print
+ }
+-' | sort -t: +0 -2 +4 +3 -4 +2 -3 | uniq | awk -F: '
++' | sort -t: -k 1,3 -k 5 -k 4,5 -k 3,4 | uniq | awk -F: '
+ {
+ type = $1
+ q = $2
diff --git a/main/djbdns/headtail.patch b/main/djbdns/headtail.patch
new file mode 100644
index 0000000000..31854803ba
--- /dev/null
+++ b/main/djbdns/headtail.patch
@@ -0,0 +1,67 @@
+diff -Naur /tmp/djbdns-1.05/Makefile djbdns-1.05/Makefile
+--- a/Makefile 2003-11-16 20:33:41.000000000 +0100
++++ b/Makefile 2003-11-16 20:35:15.000000000 +0100
+@@ -31,7 +31,7 @@
+
+ auto_home.c: \
+ auto-str conf-home
+- ./auto-str auto_home `head -1 conf-home` > auto_home.c
++ ./auto-str auto_home `head -n 1 conf-home` > auto_home.c
+
+ auto_home.o: \
+ compile auto_home.c
+@@ -205,14 +205,14 @@
+ choose: \
+ warn-auto.sh choose.sh conf-home
+ cat warn-auto.sh choose.sh \
+- | sed s}HOME}"`head -1 conf-home`"}g \
++ | sed s}HOME}"`head -n 1 conf-home`"}g \
+ > choose
+ chmod 755 choose
+
+ compile: \
+ warn-auto.sh conf-cc
+ ( cat warn-auto.sh; \
+- echo exec "`head -1 conf-cc`" '-c $${1+"$$@"}' \
++ echo exec "`head -n 1 conf-cc`" '-c $${1+"$$@"}' \
+ ) > compile
+ chmod 755 compile
+
+@@ -449,7 +449,7 @@
+ dnstracesort: \
+ warn-auto.sh dnstracesort.sh conf-home
+ cat warn-auto.sh dnstracesort.sh \
+- | sed s}HOME}"`head -1 conf-home`"}g \
++ | sed s}HOME}"`head -n 1 conf-home`"}g \
+ > dnstracesort
+ chmod 755 dnstracesort
+
+@@ -570,7 +570,7 @@
+ warn-auto.sh conf-ld
+ ( cat warn-auto.sh; \
+ echo 'main="$$1"; shift'; \
+- echo exec "`head -1 conf-ld`" \
++ echo exec "`head -n 1 conf-ld`" \
+ '-o "$$main" "$$main".o $${1+"$$@"}' \
+ ) > load
+ chmod 755 load
+@@ -758,7 +758,7 @@
+ rts: \
+ warn-auto.sh rts.sh conf-home
+ cat warn-auto.sh rts.sh \
+- | sed s}HOME}"`head -1 conf-home`"}g \
++ | sed s}HOME}"`head -n 1 conf-home`"}g \
+ > rts
+ chmod 755 rts
+
+@@ -901,8 +901,8 @@
+ systype: \
+ find-systype.sh conf-cc conf-ld trycpp.c x86cpuid.c
+ ( cat warn-auto.sh; \
+- echo CC=\'`head -1 conf-cc`\'; \
+- echo LD=\'`head -1 conf-ld`\'; \
++ echo CC=\'`head -n 1 conf-cc`\'; \
++ echo LD=\'`head -n 1 conf-ld`\'; \
+ cat find-systype.sh; \
+ ) | sh > systype
+
diff --git a/main/djbdns/tinydns.confd b/main/djbdns/tinydns.confd
new file mode 100644
index 0000000000..840570a63c
--- /dev/null
+++ b/main/djbdns/tinydns.confd
@@ -0,0 +1,2 @@
+# IP is the ip address to listen on
+IP=127.0.0.1
diff --git a/main/djbdns/tinydns.initd b/main/djbdns/tinydns.initd
new file mode 100755
index 0000000000..8dfc539307
--- /dev/null
+++ b/main/djbdns/tinydns.initd
@@ -0,0 +1,92 @@
+#!/sbin/runscript
+# control an instance of tinydns, without daemontools
+# written for alpine linux - NBA April 2007
+
+opts="reload"
+
+depend() {
+ need net
+ after firewall
+}
+
+# -- Statrup variables
+DAEMON=/usr/bin/tinydns
+COMPILER=/usr/bin/tinydns-data
+
+IFACE="${SVCNAME#*.}"
+if [ -n "$IFACE" ] && [ "${SVCNAME}" != "tinydns" ]; then
+ ROOT=${ROOT:-/var/cache/tinydns.$IFACE}
+ VARRUN=${VARRUN:-/var/run/tinydns.$IFACE}
+ DATADIR=${DATADIR:-/etc/tinydns.$IFACE}
+else
+ ROOT=${ROOT:-/var/cache/tinydns}
+ VARRUN=${VARRUN:-/var/run/tinydns}
+ DATADIR=${DATADIR:-/etc/tinydns}
+fi
+
+
+#-----------------------------------------------------------------
+# Main program
+reload() {
+ local rc opwd="$opwd"
+ UID=$(id -u tinydns)
+ GID=$(id -g tinydns)
+
+ # Create the $ROOT directory if necessary
+ if [ ! -d "$ROOT" ]; then
+ mkdir -p "$ROOT"
+ chown $UID:$GID "$ROOT"
+ fi
+
+ # If a file named "data" exists in the $ROOT dir
+ # Then we just use it and ignore anything else
+ # If the "data" file does not exist, we attempt
+ # to build one out of the "zone files".
+ ebegin "Generating tinydns cache"
+ rm -f "$ROOT/data"
+ if [ -e $DATADIR/data ]; then
+ ln -sf "$DATADIR/data" "$ROOT/data"
+ else
+ set -- $( find $DATADIR -type f )
+ if [ $# -eq 0 ]; then
+ eend 1 "Missing data or zone files in $DATADIR"
+ return 1
+ fi
+ cat "$@" > "$ROOT/data"
+ fi
+ cd "$ROOT" || return 1
+ [ -e data ] || rm -f data.cdb
+ $COMPILER
+ rc=$?
+ cd "$opwd"
+ eend $rc
+ return $rc
+}
+
+start() {
+ # Always do a reload on start
+ reload || return 1
+
+ ebegin "Starting tinydns"
+ if [ -z "$UID" ] || [ -z "$GID" ]; then
+ eend 1 "tinydns user or group missing"
+ return 1
+ fi
+
+ if [ -z "$IP" ]; then
+ eend 1 "IP is not specified in /etc/conf.d/$SVCNAME"
+ return 1
+ fi
+
+ start-stop-daemon --start --env "UID=$UID" --env "GID=$GID" \
+ --env "ROOT=$ROOT" --env "IP=$IP" --pidfile ${VARRUN}.pid \
+ --background --make-pidfile --exec $DAEMON
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping tinydns"
+ start-stop-daemon --stop --pidfile ${VARRUN}.pid --exec $DAEMON
+ eend $?
+}
+
diff --git a/main/djbdns/tinydns.pre-install b/main/djbdns/tinydns.pre-install
new file mode 100644
index 0000000000..11ea87abcb
--- /dev/null
+++ b/main/djbdns/tinydns.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /etc/tinydns -g tinydns -s /bin/false -H -D tinydns 2>/dev/null
+exit 0
+
diff --git a/main/dmidecode/APKBUILD b/main/dmidecode/APKBUILD
new file mode 100644
index 0000000000..6b270905cc
--- /dev/null
+++ b/main/dmidecode/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Nathan Angelacos <nangel@alpinelinux.org>
+pkgname=dmidecode
+pkgver=2.11
+pkgrel=0
+pkgdesc="A utility for reporting system hardware as described by BIOS"
+url="http://www.nongnu.org/dmidecode"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+subpackages="$pkgname-doc"
+source="http://mirror.its.uidaho.edu/pub/savannah/dmidecode/dmidecode-${pkgver}.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+ for i in "$srcdir"/*.patch; do
+ [ -f "$i" ] || continue
+ msg "Applying $i"
+ patch -p1 -i "$i" || return 1
+ done
+ sed '/^PROGRAMS !=/d' -i Makefile
+}
+
+build() {
+ cd "$_builddir"
+ make prefix=/usr || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make prefix=/usr DESTDIR="${pkgdir}" install
+}
+
+md5sums="9fddbbc3e330bee5950b8b5d424a57cb dmidecode-2.11.tar.gz"
diff --git a/main/dnsmasq/APKBUILD b/main/dnsmasq/APKBUILD
new file mode 100644
index 0000000000..e1437e004d
--- /dev/null
+++ b/main/dnsmasq/APKBUILD
@@ -0,0 +1,41 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dnsmasq
+pkgver=2.57
+pkgrel=0
+pkgdesc="Small forwarding DNS server"
+url="http://www.thekelleys.org.uk/dnsmasq/"
+arch="all"
+license="GPL-2"
+depends=
+subpackages="$pkgname-doc"
+source="http://www.thekelleys.org.uk/dnsmasq/$pkgname-$pkgver.tar.gz
+ $pkgname.initd
+ $pkgname.confd
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ sed -i -e 's/^AWK.*/AWK = awk/' Makefile
+ make PREFIX=/usr \
+ CFLAGS="$CFLAGS" \
+ DBUS_LIBS= \
+ DBUS_CFLAGS= \
+ DBUS_MINOR= \
+ all || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make PREFIX=/usr \
+ DESTDIR="$pkgdir" \
+ DBUS_LIBS= \
+ DBUS_CFLAGS= \
+ DBUS_MINOR= \
+ install
+ install -D -m755 "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -D -m644 "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ install dnsmasq.conf.example "$pkgdir"/etc/dnsmasq.conf
+}
+md5sums="d10faeb409717eae94718d7716ca63a4 dnsmasq-2.57.tar.gz
+db46459322a0c7d9ce4f68251fd265c4 dnsmasq.initd
+5990c2d2cb92209feacf8f3a5a7d0831 dnsmasq.confd"
diff --git a/main/dnsmasq/dnsmasq.confd b/main/dnsmasq/dnsmasq.confd
new file mode 100644
index 0000000000..47826dd508
--- /dev/null
+++ b/main/dnsmasq/dnsmasq.confd
@@ -0,0 +1,4 @@
+# /etc/conf.d/dnsmasq: config file for /etc/init.d/dnsmasq
+
+# See the dnsmasq(8) man page for possible options to put here.
+DNSMASQ_OPTS=""
diff --git a/main/dnsmasq/dnsmasq.initd b/main/dnsmasq/dnsmasq.initd
new file mode 100644
index 0000000000..3f33d89865
--- /dev/null
+++ b/main/dnsmasq/dnsmasq.initd
@@ -0,0 +1,38 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-dns/dnsmasq/files/dnsmasq-init,v 1.13 2008/01/29 15:06:30 flameeyes Exp $
+
+opts="reload"
+
+depend() {
+ provide dns
+ need localmount net
+ after bootmisc firewall
+}
+
+start() {
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start --exec /usr/sbin/dnsmasq \
+ --pidfile /var/run/dnsmasq.pid \
+ -- -x /var/run/dnsmasq.pid ${DNSMASQ_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --exec /usr/sbin/dnsmasq \
+ --pidfile /var/run/dnsmasq.pid
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading ${SVCNAME}"
+ if ! service_started "${SVCNAME}" ; then
+ eend 1 "${SVCNAME} is not started"
+ return 1
+ fi
+ start-stop-daemon --stop --oknodo --signal HUP \
+ --exec /usr/sbin/dnsmasq --pidfile /var/run/dnsmasq.pid
+ eend $?
+}
diff --git a/main/docbook-xml/APKBUILD b/main/docbook-xml/APKBUILD
new file mode 100644
index 0000000000..0233b965c8
--- /dev/null
+++ b/main/docbook-xml/APKBUILD
@@ -0,0 +1,258 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=docbook-xml
+pkgver=4.5
+pkgrel=3
+pkgdesc="A widely used XML scheme for writing documentation and help"
+url="http://scrollkeeper.sourceforge.net/docbook.shtml"
+arch="all"
+license="MIT"
+depends="libxml2-utils"
+makedepends=
+install="$pkgname.post-install $pkgname.post-upgrade $pkgname.post-deinstall"
+source="http://www.docbook.org/xml/$pkgver/$pkgname-$pkgver.zip
+ http://www.docbook.org/xml/4.4/$pkgname-4.4.zip
+ http://www.docbook.org/xml/4.3/$pkgname-4.3.zip
+ http://www.docbook.org/xml/4.2/$pkgname-4.2.zip
+ http://www.docbook.org/xml/4.1.2/docbkx412.zip
+ "
+
+unpack() {
+ # we unpack the zip's in subdirs in build()
+ :
+}
+
+build ()
+{
+ for ver in 4.1.2 4.2 4.3 4.4 4.5; do
+ case $ver in
+ 4.1.2) _pv=412;;
+ *) _pv=$ver;;
+ esac
+ mkdir -p "$srcdir"/docbook-xml-${ver}
+ cd "$srcdir"/docbook-xml-${ver}
+ unzip "$srcdir"/docbook-xml-${_pv}.zip
+ mkdir -p "$pkgdir"/usr/share/xml/docbook/xml-dtd-${ver}
+ cp -af docbook.cat *.dtd ent/ *.mod "$pkgdir"/usr/share/xml/docbook/xml-dtd-${ver}/
+ done
+ mkdir -p "$pkgdir"/etc/xml
+ xmlcatalog --noout --create "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add \
+ "public" \
+ "-//OASIS//DTD DocBook XML V4.1.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook XML CALS Table Model V4.1.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/calstblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook XML CALS Table Model V4.1.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/calstblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD XML Exchange Table Model 19990315//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/soextblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook XML Information Pool V4.1.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/dbpoolx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook XML Document Hierarchy V4.1.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/dbhierx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook XML Additional General Entities V4.1.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/dbgenent.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook XML Notations V4.1.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/dbnotnx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook XML Character Entities V4.1.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2/dbcentx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteSystem" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.1.2" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteURI" \
+ "http://www.oasis-open.org/docbook/xml/4.1.2" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.1.2" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook XML V4.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook CALS Table Model V4.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.2/calstblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD XML Exchange Table Model 19990315//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.2/soextblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook Information Pool V4.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.2/dbpoolx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook Document Hierarchy V4.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.2/dbhierx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Additional General Entities V4.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.2/dbgenent.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Notations V4.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.2/dbnotnx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Character Entities V4.2//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.2/dbcentx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteSystem" \
+ "http://www.oasis-open.org/docbook/xml/4.2" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.2" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteURI" \
+ "http://www.oasis-open.org/docbook/xml/4.2" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.2" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook XML V4.3//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook CALS Table Model V4.3//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.3/calstblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD XML Exchange Table Model 19990315//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.3/soextblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook Information Pool V4.3//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.3/dbpoolx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook Document Hierarchy V4.3//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.3/dbhierx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Additional General Entities V4.3//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.3/dbgenent.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Notations V4.3//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.3/dbnotnx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Character Entities V4.3//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.3/dbcentx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteSystem" \
+ "http://www.oasis-open.org/docbook/xml/4.3" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.3" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteURI" \
+ "http://www.oasis-open.org/docbook/xml/4.3" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.3" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook XML V4.4//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook CALS Table Model V4.4//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/calstblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook XML HTML Tables V4.4//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/htmltblx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD XML Exchange Table Model 19990315//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/soextblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook Information Pool V4.4//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/dbpoolx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook Document Hierarchy V4.4//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/dbhierx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Additional General Entities V4.4//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/dbgenent.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Notations V4.4//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/dbnotnx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook Character Entities V4.4//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.4/dbcentx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteSystem" \
+ "http://www.oasis-open.org/docbook/xml/4.4" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.4" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteURI" \
+ "http://www.oasis-open.org/docbook/xml/4.4" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.4" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook XML V4.5//EN" \
+ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD DocBook XML CALS Table Model V4.5//EN" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5/calstblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//DTD XML Exchange Table Model 19990315//EN" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5/soextblx.dtd" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook XML Information Pool V4.5//EN" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5/dbpoolx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook XML Document Hierarchy V4.5//EN" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5/dbhierx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ELEMENTS DocBook XML HTML Tables V4.5//EN" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5/htmltblx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook XML Notations V4.5//EN" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5/dbnotnx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook XML Character Entities V4.5//EN" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5/dbcentx.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "public" \
+ "-//OASIS//ENTITIES DocBook XML Additional General Entities V4.5//EN" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5/dbgenent.mod" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteSystem" \
+ "http://www.oasis-open.org/docbook/xml/4.5" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5" \
+ "$pkgdir"/etc/xml/docbook-xml
+ xmlcatalog --noout --add "rewriteURI" \
+ "http://www.oasis-open.org/docbook/xml/4.5" \
+ "file:///usr/share/xml/docbook/xml-dtd-4.5" \
+ "$pkgdir"/etc/xml/docbook-xml
+}
+md5sums="03083e288e87a7e829e437358da7ef9e docbook-xml-4.5.zip
+cbb04e9a700955d88c50962ef22c1634 docbook-xml-4.4.zip
+ab200202b9e136a144db1e0864c45074 docbook-xml-4.3.zip
+73fe50dfe74ca631c1602f558ed8961f docbook-xml-4.2.zip
+900d7609fb7e6d78901b357e4acfbc17 docbkx412.zip"
diff --git a/main/docbook-xml/docbook-xml.post-deinstall b/main/docbook-xml/docbook-xml.post-deinstall
new file mode 100644
index 0000000000..ed0157da7a
--- /dev/null
+++ b/main/docbook-xml/docbook-xml.post-deinstall
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if which xmlcatalog >/dev/null; then
+ xmlcatalog --noout --del file:///etc/xml/docbook-xml etc/xml/catalog
+fi
diff --git a/main/docbook-xml/docbook-xml.post-install b/main/docbook-xml/docbook-xml.post-install
new file mode 100644
index 0000000000..fa5f2a997b
--- /dev/null
+++ b/main/docbook-xml/docbook-xml.post-install
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+if [ ! -e etc/xml/catalog ]; then
+ xmlcatalog --noout --create etc/xml/catalog
+fi
+
+xmlcatalog --noout --add "delegatePublic" \
+ "-//OASIS//ENTITIES DocBook XML" \
+ "file:///etc/xml/docbook-xml" \
+ etc/xml/catalog
+xmlcatalog --noout --add "delegatePublic" \
+ "-//OASIS//DTD DocBook XML" \
+ "file:///etc/xml/docbook-xml" \
+ etc/xml/catalog
+xmlcatalog --noout --add "delegateSystem" \
+ "http://www.oasis-open.org/docbook/" \
+ "file:///etc/xml/docbook-xml" \
+ etc/xml/catalog
+xmlcatalog --noout --add "delegateURI" \
+ "http://www.oasis-open.org/docbook/" \
+ "file:///etc/xml/docbook-xml" \
+ etc/xml/catalog
+
diff --git a/main/docbook-xml/docbook-xml.post-upgrade b/main/docbook-xml/docbook-xml.post-upgrade
new file mode 100644
index 0000000000..79bb90e7c3
--- /dev/null
+++ b/main/docbook-xml/docbook-xml.post-upgrade
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+xmlcatalog --noout --del file:///etc/xml/docbook-xml etc/xml/catalog
+
+xmlcatalog --noout --add "delegatePublic" \
+ "-//OASIS//ENTITIES DocBook XML" \
+ "file:///etc/xml/docbook-xml" \
+ etc/xml/catalog
+xmlcatalog --noout --add "delegatePublic" \
+ "-//OASIS//DTD DocBook XML" \
+ "file:///etc/xml/docbook-xml" \
+ etc/xml/catalog
+xmlcatalog --noout --add "delegateSystem" \
+ "http://www.oasis-open.org/docbook/" \
+ "file:///etc/xml/docbook-xml" \
+ etc/xml/catalog
+xmlcatalog --noout --add "delegateURI" \
+ "http://www.oasis-open.org/docbook/" \
+ "file:///etc/xml/docbook-xml" \
+ etc/xml/catalog
+
diff --git a/main/docbook-xsl/APKBUILD b/main/docbook-xsl/APKBUILD
new file mode 100644
index 0000000000..67eb8d0b9d
--- /dev/null
+++ b/main/docbook-xsl/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=docbook-xsl
+pkgver=1.76.1
+pkgrel=0
+pkgdesc="XML stylesheets for Docbook-xml transformations."
+url="http://scrollkeeper.sourceforge.net/docbook.shtml"
+arch="all"
+license="custom"
+depends="libxml2-utils libxslt docbook-xml"
+makedepends=""
+install="$pkgname.post-install $pkgname.post-upgrade $pkgname.post-deinstall"
+source="http://downloads.sourceforge.net/sourceforge/docbook/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ _dest="$pkgdir"/usr/share/xml/docbook/xsl-stylesheets-$pkgver
+ mkdir -p "$_dest"/common
+ for i in xml xsl dtd ent; do
+ install -m644 common/*.$i "$_dest"/common/
+ done
+ mkdir -p "$_dest"/params
+ install -m644 params/*.xml "$_dest"/params/
+ for fn in fo highlighting html roundtrip; do
+ mkdir -p "$_dest"/$fn
+ install -m644 ${fn}/*.xml "$_dest"/$fn/
+ install -m644 ${fn}/*.xsl "$_dest"/$fn/
+ done
+ for fn in eclipse htmlhelp javahelp lib manpages profiling template website xhtml; do
+ mkdir -p "$_dest"/$fn
+ install -m644 ${fn}/*.xsl "$_dest"/$fn/
+ done
+ mkdir -p "$pkgdir"/etc/xml
+ install -m644 VERSION "$_dest"/
+ install -m644 -D COPYING \
+ "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+md5sums="b5340507cb240cc7ce00632b9c40bff5 docbook-xsl-1.76.1.tar.bz2"
diff --git a/main/docbook-xsl/docbook-xsl.install b/main/docbook-xsl/docbook-xsl.install
new file mode 100644
index 0000000000..a8ea3e72b2
--- /dev/null
+++ b/main/docbook-xsl/docbook-xsl.install
@@ -0,0 +1,47 @@
+post_install() {
+ if [ ! -f /etc/xml/catalog ]; then
+ xmlcatalog --noout --create /etc/xml/catalog
+ fi
+ _NEW=`echo $1 | sed 's|\(.*\)\-.*|\1|'`
+
+ xmlcatalog --noout --add "rewriteSystem" \
+ "http://docbook.sourceforge.net/release/xsl/${_NEW}" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog
+
+ xmlcatalog --noout --add "rewriteURI" \
+ "http://docbook.sourceforge.net/release/xsl/${_NEW}" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog &&
+
+ xmlcatalog --noout --add "rewriteSystem" \
+ "http://docbook.sourceforge.net/release/xsl/current" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog &&
+
+ xmlcatalog --noout --add "rewriteURI" \
+ "http://docbook.sourceforge.net/release/xsl/current" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog
+}
+
+post_upgrade() {
+ post_remove $2
+ post_install $1
+}
+
+post_remove() {
+ _OLD=`echo $1 | sed 's|\(.*\)\-.*|\1|'`
+ xmlcatalog --noout --del "/usr/share/xml/docbook/xsl-stylesheets-${_OLD}" etc/xml/catalog
+
+ if [ $(vercmp $1 1.72.0-3) -lt 0 ]; then
+ xmlcatalog --noout --del "/usr/share/xml/docbook" etc/xml/catalog
+ xmlcatalog --noout --del "file:///etc/xml/docbook" etc/xml/catalog
+ fi
+}
+
+op=$1
+shift
+
+$op $*
+
diff --git a/main/docbook-xsl/docbook-xsl.post-deinstall b/main/docbook-xsl/docbook-xsl.post-deinstall
new file mode 100644
index 0000000000..2b9f0d4a15
--- /dev/null
+++ b/main/docbook-xsl/docbook-xsl.post-deinstall
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+_OLD=${1%-r[0-9]*}
+
+if which xmlcatalog > /dev/null; then
+ xmlcatalog --noout --del \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_OLD}" \
+ etc/xml/catalog
+fi
+
diff --git a/main/docbook-xsl/docbook-xsl.post-install b/main/docbook-xsl/docbook-xsl.post-install
new file mode 100644
index 0000000000..6afae6abe6
--- /dev/null
+++ b/main/docbook-xsl/docbook-xsl.post-install
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+if [ ! -f /etc/xml/catalog ]; then
+ xmlcatalog --noout --create /etc/xml/catalog
+fi
+
+
+_NEW=${1%-r[0-9]*}
+
+xmlcatalog --noout --add "rewriteSystem" \
+ "http://docbook.sourceforge.net/release/xsl/${_NEW}" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog
+
+xmlcatalog --noout --add "rewriteURI" \
+ "http://docbook.sourceforge.net/release/xsl/${_NEW}" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog &&
+
+xmlcatalog --noout --add "rewriteSystem" \
+ "http://docbook.sourceforge.net/release/xsl/current" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog &&
+
+xmlcatalog --noout --add "rewriteURI" \
+ "http://docbook.sourceforge.net/release/xsl/current" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog
+
diff --git a/main/docbook-xsl/docbook-xsl.post-upgrade b/main/docbook-xsl/docbook-xsl.post-upgrade
new file mode 100644
index 0000000000..d481480fc2
--- /dev/null
+++ b/main/docbook-xsl/docbook-xsl.post-upgrade
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+if [ ! -f /etc/xml/catalog ]; then
+ xmlcatalog --noout --create /etc/xml/catalog
+fi
+
+_NEW=${1%-r[0-9]*}
+_OLD=${2%-r[0-9]*}
+
+xmlcatalog --noout --del \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_OLD}" \
+ etc/xml/catalog
+
+xmlcatalog --noout --add "rewriteSystem" \
+ "http://docbook.sourceforge.net/release/xsl/${_NEW}" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog
+
+xmlcatalog --noout --add "rewriteURI" \
+ "http://docbook.sourceforge.net/release/xsl/${_NEW}" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog
+
+xmlcatalog --noout --add "rewriteSystem" \
+ "http://docbook.sourceforge.net/release/xsl/current" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog
+
+xmlcatalog --noout --add "rewriteURI" \
+ "http://docbook.sourceforge.net/release/xsl/current" \
+ "/usr/share/xml/docbook/xsl-stylesheets-${_NEW}" \
+ etc/xml/catalog
+
diff --git a/main/dosfstools/APKBUILD b/main/dosfstools/APKBUILD
new file mode 100644
index 0000000000..4c2eada096
--- /dev/null
+++ b/main/dosfstools/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dosfstools
+pkgver=3.0.11
+pkgrel=0
+pkgdesc="DOS filesystem utilities"
+url="http://www.daniel-baumann.ch/software/dosfstools/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends=""
+subpackages="$pkgname-doc"
+source="http://www.daniel-baumann.ch/software/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make PREFIX="$pkgdir" \
+ MANDIR="$pkgdir"/usr/share/man \
+ DOCDIR="$pkgdir"/usr/share/doc \
+ install
+}
+md5sums="8d2211d5bd813164e20740e7c852aa06 dosfstools-3.0.11.tar.bz2"
diff --git a/main/dovecot/2281223b9cb9.patch b/main/dovecot/2281223b9cb9.patch
new file mode 100644
index 0000000000..4eb9c01f85
--- /dev/null
+++ b/main/dovecot/2281223b9cb9.patch
@@ -0,0 +1,21 @@
+
+# HG changeset patch
+# User Timo Sirainen <tss@iki.fi>
+# Date 1281449944 -3600
+# Node ID 2281223b9cb99357a89971b64680530813d22a81
+# Parent 367ce71922bfc95ec1faad91cd47f1c758cd2d50
+master: Don't crash on config reload when using dict processes.
+
+--- a/src/master/dict-process.c Wed Aug 04 16:54:17 2010 +0100
++++ b/src/master/dict-process.c Tue Aug 10 15:19:04 2010 +0100
+@@ -214,7 +214,8 @@
+ struct dict_listener *listener = process->listener;
+
+ dict_process_deinit(process);
+- if (listener->processes == NULL && listener->fd != -1) {
++ if (listener->processes == NULL && listener->fd != -1 &&
++ listener->io == NULL) {
+ /* last listener died, create new ones */
+ listener->io = io_add(listener->fd, IO_READ,
+ dict_listener_input, listener);
+
diff --git a/main/dovecot/APKBUILD b/main/dovecot/APKBUILD
new file mode 100644
index 0000000000..90528e8b65
--- /dev/null
+++ b/main/dovecot/APKBUILD
@@ -0,0 +1,102 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dovecot
+pkgver=2.0.13
+pkgrel=0
+pkgdesc="IMAP and POP3 server"
+url="http://www.dovecot.org/"
+arch="all"
+license="LGPL-2.1"
+depends="openssl logrotate"
+pkgusers="dovecot dovenull"
+pkggroups="dovecot dovenull"
+makedepends="libcap-dev zlib-dev openssl-dev bzip2-dev postgresql-dev
+ mysql-dev sqlite-dev"
+install="dovecot.pre-install dovecot.post-install"
+subpackages="$pkgname-sample-config:config $pkgname-doc $pkgname-dev
+ $pkgname-pgsql $pkgname-mysql $pkgname-sqlite"
+source="http://www.dovecot.org/releases/2.0/$pkgname-$pkgver.tar.gz
+ dovecot.logrotate
+ dovecot.initd
+ dovecot-sample-config.post-install
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --localstatedir=/var \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-sql=plugin \
+ --with-mysql \
+ --with-sqlite \
+ --with-pgsql \
+ --with-ssl=openssl || return 1
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ install -d "$pkgdir"/var/run/dovecot \
+ "$pkgdir"/etc/ssl/dovecot
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -D "$srcdir"/dovecot.logrotate "$pkgdir"/etc/logrotate.d/dovecot
+
+ # default config
+ install doc/dovecot-openssl.cnf "$pkgdir"/etc/dovecot/
+ cp "$pkgdir"/usr/share/doc/dovecot/example-config/dovecot.conf \
+ "$pkgdir"/etc/dovecot/dovecot.conf || return 1
+ mkdir -p "$pkgdir"/etc/dovecot/conf.d
+
+ # fix ssl dirs in defautl config and set defautl passdb to passwd
+ sed -i -e 's,^ssl_cert =.*,ssl_cert = </etc/ssl/dovecot/server.pem,' \
+ -e 's,^ssl_key =.*,ssl_key = </etc/ssl/dovecot/server.key,' \
+ "$pkgdir"/usr/share/doc/dovecot/example-config/conf.d/10-ssl.conf\
+ || return 1
+}
+
+_mv() {
+ local i
+ while [ $# -gt 0 ]; do
+ local dir=${1%/*}
+ mkdir -p "$subpkgdir"/$dir
+ mv "$pkgdir/$1" "$subpkgdir/$dir/"
+ shift
+ done
+}
+
+
+pgsql() {
+ pkgdesc="postgresql driver for dovecot"
+ _mv $(cd "$pkgdir" && find usr -name '*pgsql.so')
+}
+
+mysql() {
+ pkgdesc="mysql driver for dovecot"
+ _mv $(cd "$pkgdir" && find usr -name '*mysql.so')
+}
+
+sqlite() {
+ pkgdesc="sqlite driver for dovecot"
+ _mv $(cd "$pkgdir" && find usr -name '*sqlite.so')
+}
+
+config() {
+ pkgdesc="Sample configuration files for dovecot"
+ install="dovecot-sample-config.post-install"
+ _mv usr/share/doc/dovecot/example-config
+ mkdir -p "$subpkgdir"/etc/dovecot/conf.d
+}
+
+md5sums="fd8a0702275a61332db7353dadff0f92 dovecot-2.0.13.tar.gz
+aec5cc797ab2acf72ce3b6bb1030345f dovecot.logrotate
+01067b40dfd74dfb79b946af1e680745 dovecot.initd
+95cf57ecc835882228bbbb019ce3abf8 dovecot-sample-config.post-install"
diff --git a/main/dovecot/dovecot-sample-config.post-install b/main/dovecot/dovecot-sample-config.post-install
new file mode 100644
index 0000000000..7f1a204fab
--- /dev/null
+++ b/main/dovecot/dovecot-sample-config.post-install
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+cd /usr/share/doc/dovecot/example-config || exit 0
+
+for i in dovecot.conf conf.d/*; do
+ if ! [ -e /etc/dovecot/$i ]; then
+ cp $i /etc/dovecot/$i
+ fi
+done
+
diff --git a/main/dovecot/dovecot.initd b/main/dovecot/dovecot.initd
new file mode 100644
index 0000000000..8e2075d5a6
--- /dev/null
+++ b/main/dovecot/dovecot.initd
@@ -0,0 +1,59 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-mail/dovecot/files/dovecot.init-r2,v 1.3 2010/05/19 13:26:56 patrick Exp $
+
+opts="${opts} reload"
+
+depend() {
+ need localmount net
+ before postfix
+ after bootmisc firewall ldap mysql ntp-client ntpd postgresql \
+ saslauthd slapd
+ use logger
+}
+
+checkconfig() {
+ DOVECOT_INSTANCE=${SVCNAME##*.}
+ if [ -n "${DOVECOT_INSTANCE}" -a "${SVCNAME}" != "dovecot" ]; then
+ DOVECOT_CONF=/etc/dovecot/dovecot.${DOVECOT_INSTANCE}.conf
+ else
+ DOVECOT_CONF=/etc/dovecot/dovecot.conf
+ fi
+ if [ ! -e ${DOVECOT_CONF} ]; then
+ eerror "You will need an ${DOVECOT_CONF} first"
+ return 1
+ fi
+ if [ -x /usr/sbin/dovecot ]; then
+ DOVECOT_BASEDIR=$(/usr/sbin/dovecot -c ${DOVECOT_CONF} -a | grep '^base_dir = ' | sed 's/^base_dir = //')
+ else
+ eerror "dovecot not executable"
+ return 1
+ fi
+ DOVECOT_BASEDIR=${DOVECOT_BASEDIR:-/var/run/dovecot}
+ DOVECOT_PIDFILE=${DOVECOT_BASEDIR}/master.pid
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start --exec /usr/sbin/dovecot \
+ --pidfile "${DOVECOT_PIDFILE}" -- -c "${DOVECOT_CONF}"
+ eend $?
+}
+
+stop() {
+ checkconfig || return 1
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --exec /usr/sbin/dovecot \
+ --pidfile "${DOVECOT_PIDFILE}"
+ eend $?
+}
+
+reload() {
+ checkconfig || return 1
+ ebegin "Reloading ${SVCNAME} configs and restarting auth/login processes"
+ start-stop-daemon --stop --oknodo --exec /usr/sbin/dovecot \
+ --pidfile "${DOVECOT_PIDFILE}" --signal HUP
+ eend $?
+}
diff --git a/main/dovecot/dovecot.logrotate b/main/dovecot/dovecot.logrotate
new file mode 100644
index 0000000000..7bd0003f7f
--- /dev/null
+++ b/main/dovecot/dovecot.logrotate
@@ -0,0 +1,15 @@
+/var/log/dovecot*.log {
+ daily
+ missingok
+ copytruncate
+ rotate 7
+ compress
+ notifempty
+ sharedscripts
+ postrotate
+ if /etc/init.d/dovecot -q status ; then \
+ /etc/init.d/dovecot reload > /dev/null 2>&1 || true ; \
+ fi;
+ endscript
+}
+
diff --git a/main/dovecot/dovecot.post-install b/main/dovecot/dovecot.post-install
new file mode 100644
index 0000000000..e4d6bb281b
--- /dev/null
+++ b/main/dovecot/dovecot.post-install
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# based on doc/mkcert.sh
+
+# if ssl disabled then lets just exit
+doveconf ssl | grep -q 'yes' || exit 0
+# Generates a self-signed certificate.
+
+OPENSSL=${OPENSSL-openssl}
+SSLDIR=${SSLDIR-/etc/ssl/dovecot}
+OPENSSLCONFIG=${OPENSSLCONFIG-/etc/dovecot/dovecot-openssl.cnf}
+
+CERTDIR=$SSLDIR
+KEYDIR=$SSLDIR
+
+# parse cert and key file from dovecot.conf (1.2) for upgraders
+dovecot_conf=/etc/dovecot/dovecot.conf
+ssl_cert_file=
+ssl_key_file=
+if [ -r "$dovecot_conf" ]; then
+ ssl_cert_file=$(awk -F'[[:space:]]*=[[:space:]]*' '/^ssl_cert_file/ { print $2}' $dovecot_conf)
+ ssl_key_file=$(awk -F'[[:space:]]*=[[:space:]]*' '/^ssl_key_file/ { print $2}' $dovecot_conf)
+fi
+
+# check if we have ssl_cert and/or key (for dovecot-2.0+)
+# try expand the cert/key itself and if found, lets just keep it
+[ -n "$(doveconf -x ssl_cert 2>/dev/null)" ] && exit 0
+[ -n "$(doveconf -x ssl_cert 2>/dev/null)" ] && exit 0
+
+[ -z "$ssl_cert_file" ] && ssl_cert_file=$(doveconf ssl_cert | sed 's/.*= <//')
+[ -z "$ssl_key_file" ] && ssl_key_file=$(doveconf ssl_key | sed 's/.*= <//')
+
+CERTFILE=${ssl_cert_file:-$CERTDIR/server.pem}
+KEYFILE=${ssl_key_file:-$KEYDIR/server.key}
+
+if [ -e "$CERTFILE" ]; then
+ echo "Keeping existing $CERTFILE"
+ exit 0
+fi
+
+if [ -e "$KEYFILE" ]; then
+ echo "Keeping existing $KEYFILE"
+ exit 0
+fi
+
+if [ ! -c /dev/urandom ] && [ ! -c /dev/random ]; then
+ echo "No /dev/urandom or /dev/random so ssl cert not created"
+ exit 1
+fi
+
+$OPENSSL req -new -x509 -nodes -config $OPENSSLCONFIG -out $CERTFILE -keyout $KEYFILE -days 365 || exit 2
+chmod 0600 $KEYFILE
+echo
+$OPENSSL x509 -subject -fingerprint -noout -in $CERTFILE || exit 2
diff --git a/main/dovecot/dovecot.pre-install b/main/dovecot/dovecot.pre-install
new file mode 100644
index 0000000000..05f207f6fb
--- /dev/null
+++ b/main/dovecot/dovecot.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -H -h /dev/null -s /bin/false -D dovecot 2>/dev/null
+adduser -H -h /dev/null -s /bin/false -D dovenull 2>/dev/null
+exit 0
diff --git a/main/doxygen/APKBUILD b/main/doxygen/APKBUILD
new file mode 100644
index 0000000000..716db23ebf
--- /dev/null
+++ b/main/doxygen/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=doxygen
+pkgver=1.7.4
+pkgrel=0
+pkgdesc="A documentation system for C++, C, Java, IDL and PHP"
+url="http://www.doxygen.org/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="flex bison coreutils perl libiconv-dev"
+subpackages="$pkgname-doc"
+source="ftp://ftp.stack.nl/pub/users/dimitri/doxygen-$pkgver.src.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+
+ sed -i -e 's:^\(TMAKE_CFLAGS_RELEASE\t*\)= .*$:\1= $(ECFLAGS):' \
+ -e 's:^\(TMAKE_CXXFLAGS_RELEASE\t*\)= .*$:\1= $(ECXXFLAGS):' \
+ -e 's:^\(TMAKE_LFLAGS_RELEASE\s*\)=.*$:\1= $(ELDFLAGS):' \
+ tmake/lib/*/tmake.conf \
+ || return 1
+
+ # Ensure we link to -liconv
+ for pro in */*.pro.in */*/*.pro.in; do
+ echo "unix:LIBS += -liconv" >> "${pro}"
+ done
+
+ # fix final DESTDIR issue
+ sed -i -e "s:\$(INSTALL):\$(DESTDIR)/\$(INSTALL):g" \
+ addon/doxywizard/Makefile.in || return 1
+}
+
+build() {
+ cd "$_builddir"
+ export ECFLAGS="$CFLAGS" ECXXFLAGS="$CXXFLAGS" ELDFLAGS="$LDFLAGS"
+ ./configure --prefix /usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" MAN1DIR=share/man/man1 install
+}
+
+md5sums="ff908759ff7cd9464424b04ae6c68e48 doxygen-1.7.4.src.tar.gz"
diff --git a/main/dpkg/APKBUILD b/main/dpkg/APKBUILD
new file mode 100644
index 0000000000..5eff274521
--- /dev/null
+++ b/main/dpkg/APKBUILD
@@ -0,0 +1,61 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dpkg
+pkgver=1.15.8.10
+pkgrel=0
+pkgdesc="The Debian Package Manager"
+url="http://packages.debian.org/dpkg"
+arch="all"
+license="GPL"
+makedepends="bzip2-dev zlib-dev perl"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://ftp.de.debian.org/debian/pool/main/d/$pkgname/${pkgname}_$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ sed -i "s|<ncursesw/curses.h>|<curses.h>|g" dselect/dselect.h \
+ dselect/Makefile.in || return 1
+ sed -i "s|<ncursesw/term.h>|<term.h>|g" dselect/main.cc || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-zlib \
+ --without-dselect \
+ --without-start-stop-daemon \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+dev() {
+ pkgdesc="Debian package development tools"
+ depends="perl"
+ mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/usr/share \
+ "$subpkgdir"/usr/lib/dpkg
+
+ mv "$pkgdir"/usr/bin/dpkg-architecture \
+ "$pkgdir"/usr/bin/dpkg-buildpackage \
+ "$pkgdir"/usr/bin/dpkg-checkbuilddeps \
+ "$pkgdir"/usr/bin/dpkg-distaddfile \
+ "$pkgdir"/usr/bin/dpkg-genchanges \
+ "$pkgdir"/usr/bin/dpkg-gencontrol \
+ "$pkgdir"/usr/bin/dpkg-gensymbols \
+ "$pkgdir"/usr/bin/dpkg-name \
+ "$pkgdir"/usr/bin/dpkg-parsechangelog \
+ "$pkgdir"/usr/bin/dpkg-scanpackages \
+ "$pkgdir"/usr/bin/dpkg-scansources \
+ "$pkgdir"/usr/bin/dpkg-shlibdeps \
+ "$pkgdir"/usr/bin/dpkg-source \
+ "$pkgdir"/usr/bin/dpkg-vendor \
+ "$subpkgdir"/usr/bin/
+ mv "$pkgdir"/usr/share/perl* "$subpkgdir"/usr/share/
+ mv "$pkgdir"/usr/lib/dpkg/parsechangelog "$subpkgdir"/usr/lib/dpkg/
+}
+
+md5sums="bce745c7083ace01da1df6cdcad35f9a dpkg_1.15.8.10.tar.bz2"
diff --git a/main/dri2proto/APKBUILD b/main/dri2proto/APKBUILD
new file mode 100644
index 0000000000..23d9138eb9
--- /dev/null
+++ b/main/dri2proto/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dri2proto
+pkgver=2.3
+pkgrel=1
+pkgdesc="X11 DRI protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="3407b494d5e90d584c9af52aa8f9f028 dri2proto-2.3.tar.bz2"
diff --git a/main/dropbear/APKBUILD b/main/dropbear/APKBUILD
new file mode 100644
index 0000000000..308b3d2d8a
--- /dev/null
+++ b/main/dropbear/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Carlo Landmeter <clandmeter at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dropbear
+pkgver=0.52
+pkgrel=4
+pkgdesc="small SSH 2 client/server designed for small memory environments"
+url="http://matt.ucc.asn.au/dropbear/dropbear.html"
+arch="all"
+license='MIT'
+depends=
+makedepends="zlib-dev"
+source="http://matt.ucc.asn.au/dropbear/releases/${pkgname}-${pkgver}.tar.bz2
+dropbear.initd
+dropbear.confd"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --disable-lastlog
+ progs="dbclient dropbearkey dropbearconvert scp"
+ make PROGRAMS="dropbear ${progs}" MULTI=1 || return 1
+ install -Dm755 "$srcdir/$pkgname-$pkgver"/dropbearmulti "$pkgdir"/usr/bin/dropbearmulti || return 1
+ cd "$pkgdir/usr/bin" || return 1
+ for i in ${progs}; do
+ msg "linking ${i##*/}"
+ ln -s dropbearmulti $i || return 1
+ done
+ msg "linking dropbear"
+ mkdir -p "$pkgdir"/usr/sbin || return 1
+ cd "$pkgdir/usr/sbin" || return 1
+ ln -s ../bin/dropbearmulti dropbear || return 1
+ install -D -m755 "$srcdir"/dropbear.initd "$pkgdir"/etc/init.d/dropbear || return 1
+ install -D -m644 "$srcdir"/dropbear.confd "$pkgdir"/etc/conf.d/dropbear || return 1
+}
+
+md5sums="a1fc7adf601bca53330a792a9c873439 dropbear-0.52.tar.bz2
+d181e2234f34ae5b1e45f8ebf5f14e07 dropbear.initd
+af73c487e2be37d65d0e8bf80489357e dropbear.confd"
diff --git a/main/dropbear/dropbear.confd b/main/dropbear/dropbear.confd
new file mode 100644
index 0000000000..555f275d99
--- /dev/null
+++ b/main/dropbear/dropbear.confd
@@ -0,0 +1,6 @@
+# /etc/conf.d/dropbear: config file for /etc/init.d/dropbear
+
+# see `dropbear -h` for more information
+# -w disables root logins
+# -p # changes the port number to listen on
+DROPBEAR_OPTS=""
diff --git a/main/dropbear/dropbear.initd b/main/dropbear/dropbear.initd
new file mode 100644
index 0000000000..652a5464be
--- /dev/null
+++ b/main/dropbear/dropbear.initd
@@ -0,0 +1,37 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/dropbear/files/dropbear.init.d,v 1.2 2004/07/14 23:57:35 agriffis Exp $
+
+depend() {
+ use logger dns
+ need net
+ after firewall
+}
+
+check_config() {
+ if [ ! -e /etc/dropbear/ ] ; then
+ mkdir /etc/dropbear/
+ fi
+ if [ ! -e /etc/dropbear/dropbear_dss_host_key ] ; then
+ einfo "Generating DSS-Hostkey..."
+ /usr/bin/dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
+ fi
+ if [ ! -e /etc/dropbear/dropbear_rsa_host_key ] ; then
+ einfo "Generating RSA-Hostkey..."
+ /usr/bin/dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
+ fi
+}
+
+start() {
+ check_config || return 1
+ ebegin "Starting dropbear"
+ /usr/sbin/dropbear ${DROPBEAR_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping dropbear"
+ start-stop-daemon --stop --pidfile /var/run/dropbear.pid
+ eend $?
+}
diff --git a/main/dtach/APKBUILD b/main/dtach/APKBUILD
new file mode 100644
index 0000000000..46cc03515d
--- /dev/null
+++ b/main/dtach/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=dtach
+pkgver=0.8
+pkgrel=3
+pkgdesc="A program that emulates the detach feature of screen"
+url="http://dtach.sourceforge.net"
+arch="all"
+license='GPL'
+depends=""
+makedepends=""
+source="http://surfnet.dl.sourceforge.net/sourceforge/dtach/dtach-0.8.tar.gz"
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr
+ make || return 1
+ install -Dm755 "$srcdir"/dtach-0.8/dtach "$pkgdir"/usr/bin/dtach
+ install -Dm644 "$srcdir"/dtach-0.8/dtach.1 "$pkgdir"/usr/share/man/man1/dtach.1
+ install -Dm644 "$srcdir"/dtach-0.8/README "$pkgdir"/usr/share/doc/README
+}
+
+md5sums="ec5999f3b6bb67da19754fcb2e5221f3 dtach-0.8.tar.gz"
diff --git a/main/duplicity/APKBUILD b/main/duplicity/APKBUILD
new file mode 100644
index 0000000000..e12da493a3
--- /dev/null
+++ b/main/duplicity/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=duplicity
+pkgver=0.6.13
+pkgrel=1
+pkgdesc="Encrypted bandwidth-efficient backup using the rsync algorithm"
+url="http://duplicity.nongnu.org/"
+arch="all"
+license="GPL"
+depends="python py-boto ncftp librsync gnupg"
+makedepends="wget python-dev py-setuptools librsync-dev"
+install=
+subpackages="$pkgname-doc"
+source="https://code.launchpad.net/$pkgname/${pkgver:0:3}-series/$pkgver/+download/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir"
+}
+
+md5sums="b3d627f35fc527b00121925840d5cca7 duplicity-0.6.13.tar.gz"
diff --git a/main/dvgrab/APKBUILD b/main/dvgrab/APKBUILD
new file mode 100644
index 0000000000..8e2f3537e5
--- /dev/null
+++ b/main/dvgrab/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=dvgrab
+pkgver=3.5
+pkgrel=0
+pkgdesc="Utility to capture video from a DV camera"
+url="http://www.kinodv.org/"
+arch="all"
+license="GPLv2+"
+depends=
+makedepends="libraw1394-dev libavc1394-dev libdv-dev libiec61883-dev jpeg-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://prdownloads.sourceforge.net/kino/dvgrab-$pkgver.tar.gz"
+
+_builddir="$srcdir"/dvgrab-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="b39a242ce63e80fc347ab59931f75649 dvgrab-3.5.tar.gz"
diff --git a/main/e2fsprogs/0001-implement-com_right_r.patch b/main/e2fsprogs/0001-implement-com_right_r.patch
new file mode 100644
index 0000000000..dc285d9acd
--- /dev/null
+++ b/main/e2fsprogs/0001-implement-com_right_r.patch
@@ -0,0 +1,59 @@
+From 527d258d605e5a1dd841bccc6091c0b894a10411 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Wed, 27 Jan 2010 16:02:08 +0000
+Subject: [PATCH] implement com_right_r()
+
+For heimdal compat
+---
+ lib/et/com_err.h | 2 ++
+ lib/et/com_right.c | 14 ++++++++++++++
+ 2 files changed, 16 insertions(+), 0 deletions(-)
+
+diff --git a/lib/et/com_err.h b/lib/et/com_err.h
+index de0146e..eb2106f 100644
+--- a/lib/et/com_err.h
++++ b/lib/et/com_err.h
+@@ -16,6 +16,7 @@
+ #define COM_ERR_ATTR(x)
+ #endif
+
++#include <stddef.h>
+ #include <stdarg.h>
+
+ typedef long errcode_t;
+@@ -49,6 +50,7 @@ extern void add_to_error_table(struct et_list *new_table);
+
+ /* Provided for Heimdall compatibility */
+ extern const char *com_right(struct et_list *list, long code);
++extern const char *com_right_r(struct et_list *list, long code, char *str, size_t len);
+ extern void initialize_error_table_r(struct et_list **list,
+ const char **messages,
+ int num_errors,
+diff --git a/lib/et/com_right.c b/lib/et/com_right.c
+index 173fd1a..dbc1e41 100644
+--- a/lib/et/com_right.c
++++ b/lib/et/com_right.c
+@@ -55,6 +55,20 @@ com_right(struct et_list *list, long code)
+ return NULL;
+ }
+
++const char *
++com_right_r(struct et_list *list, long code, char *str, size_t len)
++{
++ struct et_list *p;
++ for (p = list; p; p = p->next) {
++ if (code >= p->table->base && code < p->table->base + p->table->n_msgs) {
++ strlcpy(str, p->table->msgs[code - p->table->base], len);
++ return str;
++ }
++ }
++ return NULL;
++}
++
++
+ struct foobar {
+ struct et_list etl;
+ struct error_table tab;
+--
+1.6.6.1
+
diff --git a/main/e2fsprogs/APKBUILD b/main/e2fsprogs/APKBUILD
new file mode 100644
index 0000000000..970a5efaa5
--- /dev/null
+++ b/main/e2fsprogs/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=e2fsprogs
+pkgver=1.41.14
+pkgrel=0
+pkgdesc="Standard Ext2/3/4 filesystem utilities"
+url="http://e2fsprogs.sourceforge.net"
+arch="all"
+license="GPL LGPL MIT"
+depends=
+install="$pkgname.post-upgrade"
+makedepends="util-linux-ng-dev pkgconfig"
+subpackages="$pkgname-dev $pkgname-doc libcom_err"
+source="http://downloads.sourceforge.net/sourceforge/e2fsprogs/e2fsprogs-$pkgver.tar.gz"
+
+depends_dev="util-linux-ng-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build () {
+ cd "$_builddir"
+ ./configure \
+ --mandir=/usr/share/man \
+ --enable-elf-shlibs \
+ --disable-fsck \
+ --disable-uuidd \
+ --disable-libuuid \
+ --disable-libblkid \
+ --disable-tls \
+ --disable-nls
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 LDCONFIG=: DESTDIR="${pkgdir}" install install-libs || return 1
+}
+
+libcom_err() {
+ depends=
+ replaces="e2fsprogs"
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libcom_err* "$subpkgdir"/lib/
+}
+
+md5sums="05f70470aea2ef7efbb0845b2b116720 e2fsprogs-1.41.14.tar.gz"
diff --git a/main/e2fsprogs/e2fsprogs.post-upgrade b/main/e2fsprogs/e2fsprogs.post-upgrade
new file mode 100644
index 0000000000..d7062db5a7
--- /dev/null
+++ b/main/e2fsprogs/e2fsprogs.post-upgrade
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# we no longer provide fsck. restore bb link.
+busybox --install -s
diff --git a/main/eboard/APKBUILD b/main/eboard/APKBUILD
new file mode 100644
index 0000000000..9d832bb860
--- /dev/null
+++ b/main/eboard/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=eboard
+pkgver=1.1.1
+pkgrel=0
+pkgdesc="Chess board interface for ICS"
+url="http://www.bergo.eng.br/eboard"
+arch="all"
+license="GPLv2+"
+depends=
+makedepends="gtk+2.0-dev perl"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://prdownloads.sourceforge.net/eboard/eboard-$pkgver.tar.bz2
+ eboard.desktop"
+
+_builddir="$srcdir"/eboard-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --man-prefix=/usr/share/man \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 "$srcdir"/eboard.desktop \
+ "$pkgdir"/usr/share/applications/eboard.desktop
+}
+
+md5sums="03dcdaa2bc85218b1b18c4bee276fea7 eboard-1.1.1.tar.bz2
+70f985b6841c2e6374555a5a4c0cca79 eboard.desktop"
diff --git a/main/eboard/eboard.desktop b/main/eboard/eboard.desktop
new file mode 100644
index 0000000000..28d0b2fee7
--- /dev/null
+++ b/main/eboard/eboard.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Eboard
+Comment=Play chess against an engine, on a LAN or on the Internet
+Exec=eboard
+Terminal=false
+Type=Application
+Categories=Game;BoardGame;
diff --git a/main/ebtables/0001-link-with-gcc.patch b/main/ebtables/0001-link-with-gcc.patch
new file mode 100644
index 0000000000..88aba09f3f
--- /dev/null
+++ b/main/ebtables/0001-link-with-gcc.patch
@@ -0,0 +1,25 @@
+--- a/Makefile Sun Jun 21 13:13:25 2009
++++ b/Makefile Wed Oct 28 02:42:43 2009
+@@ -85,7 +85,7 @@
+
+ .PHONY: libebtc
+ libebtc: $(OBJECTS2)
+- $(LD) -shared -soname libebtc.so -o libebtc.so -lc $(OBJECTS2)
++ $(CC) -shared -Wl,-soname,libebtc.so -o libebtc.so -lc $(OBJECTS2)
+
+ ebtables: $(OBJECTS) ebtables-standalone.o libebtc
+ $(CC) $(CFLAGS) $(CFLAGS_SH_LIB) -o $@ ebtables-standalone.o -I$(KERNEL_INCLUDES) -L. -Lextensions -lebtc $(EXT_LIBSI) \
+@@ -153,10 +153,13 @@
+ tmp3:=$(shell printf $(PIPE) | sed 's/\//\\\//g')
+ .PHONY: scripts
+ scripts: ebtables-save ebtables.sysv ebtables-config
++ mkdir -p $(DESTDIR)$(BINDIR)
+ cat ebtables-save | sed 's/__EXEC_PATH__/$(tmp1)/g' > ebtables-save_
+ install -m 0755 -o root -g root ebtables-save_ $(DESTDIR)$(BINDIR)/ebtables-save
++ mkdir -p $(DESTDIR)$(INITDIR)
+ cat ebtables.sysv | sed 's/__EXEC_PATH__/$(tmp1)/g' | sed 's/__SYSCONFIG__/$(tmp2)/g' > ebtables.sysv_
+ install -m 0755 -o root -g root ebtables.sysv_ $(DESTDIR)$(INITDIR)/ebtables
++ mkdir -p $(DESTDIR)$(SYSCONFIGDIR)
+ cat ebtables-config | sed 's/__SYSCONFIG__/$(tmp2)/g' > ebtables-config_
+ install -m 0600 -o root -g root ebtables-config_ $(DESTDIR)$(SYSCONFIGDIR)/ebtables-config
+ rm -f ebtables-save_ ebtables.sysv_ ebtables-config_
diff --git a/main/ebtables/APKBUILD b/main/ebtables/APKBUILD
new file mode 100644
index 0000000000..c7ae555f26
--- /dev/null
+++ b/main/ebtables/APKBUILD
@@ -0,0 +1,59 @@
+# Contributor: Andrew Manison <amanison@anselsystems.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ebtables
+pkgver=2.0.9.1
+_realver=v2.0.9-1
+pkgrel=3
+pkgdesc="Ethernet bridge tables - Linux Ethernet filter for the Linux bridge."
+url="http://ebtables.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$_realver.tar.gz
+ 0001-link-with-gcc.patch
+ ebtables.initd
+ ebtables.confd"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$_realver
+ # patches
+ for i in ../*.patch; do
+ msg "Applying $i"
+ if ! patch --verbose -p1 -i $i; then
+ error "$i failed"
+ return 1
+ fi
+ done
+
+ sed -i -e "s,^MANDIR:=.*,MANDIR:=/usr/share/man," \
+ -e "s,^BINDIR:=.*,BINDIR:=/sbin," \
+ -e "s,^INITDIR:=.*,INITDIR:=/usr/share/doc/ebtables," \
+ -e "s,^SYSCONFIGDIR:=.*,SYSCONFIGDIR:=/usr/share/doc/ebtables,"\
+ -e "s,^LIBDIR:=.*,LIBDIR:=/usr/lib/\$(PROGNAME)," \
+ -e "s/^CFLAGS:=/CFLAGS+=/" \
+ -e "s,^CC:=,CC?=," Makefile
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$_realver
+
+ # This package uses _init functions to initialise extensions. With
+ # --as-needed this will not work.
+ export LDFLAGS="$LDFLAGS -Wl,--no-as-needed"
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$_realver
+ make DESTDIR="$pkgdir" install
+ install -D -m755 ../ebtables.initd "$pkgdir"/etc/init.d/ebtables
+ install -D -m644 ../ebtables.confd "$pkgdir"/etc/conf.d/ebtables
+}
+
+md5sums="0e0c20adf2bba6d91dbd0b74a1a38c33 ebtables-v2.0.9-1.tar.gz
+91a565a5906dc1fd4103f03c6a88e0e1 0001-link-with-gcc.patch
+92e13b3bc1d47d7c00636ebb78c905d5 ebtables.initd
+285089ba2d846e72e321a12e3da3cc96 ebtables.confd"
diff --git a/main/ebtables/ebtables.confd b/main/ebtables/ebtables.confd
new file mode 100644
index 0000000000..db46ffb587
--- /dev/null
+++ b/main/ebtables/ebtables.confd
@@ -0,0 +1,15 @@
+# /etc/conf.d/ebtables
+
+# Location in which ebtables initscript will save set rules on
+# service shutdown
+EBTABLES_SAVE="/var/lib/ebtables/rules-save"
+
+# Options to pass to ebtables-save and ebtables-restore
+SAVE_RESTORE_OPTIONS=""
+
+# Save state on stopping ebtables
+SAVE_ON_STOP="yes"
+
+# Tables to be saved and restored. If you have built ebtables as modules, you
+# may leave it blank. Otherwise, you MUST define which to control.
+TABLE_NAMES="filter nat broute"
diff --git a/main/ebtables/ebtables.initd b/main/ebtables/ebtables.initd
new file mode 100644
index 0000000000..27c743c910
--- /dev/null
+++ b/main/ebtables/ebtables.initd
@@ -0,0 +1,97 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-firewall/ebtables/files/ebtables.initd,v 1.2 2007/09/28 19:22:14 pva Exp $
+
+opts="save reload panic"
+
+ebtables_bin="/sbin/ebtables"
+ebtables_save=${EBTABLES_SAVE}
+ebtables_tables=$(grep -E '^ebtable_' /proc/modules | cut -f1 -d' ' | sed s/ebtable_//)
+if [ "$ebtables_tables" == "" ] ; then
+ ebtables_tables=${TABLE_NAMES}
+fi
+
+depend() {
+ before net
+ use logger
+}
+
+set_table_policy() {
+ local chains table=$1 policy=$2
+ case ${table} in
+ nat) chains="PREROUTING POSTROUTING OUTPUT";;
+ broute) chains="BROUTING";;
+ filter) chains="INPUT FORWARD OUTPUT";;
+ *) chains="";;
+ esac
+ local chain
+ for chain in ${chains} ; do
+ ${ebtables_bin} -t ${table} -P ${chain} ${policy}
+ done
+}
+
+checkconfig() {
+ if [ ! -f ${ebtables_save} ] ; then
+ eerror "Not starting ebtables. First create some rules then run:"
+ eerror "/etc/init.d/ebtables save"
+ return 1
+ fi
+ return 0
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Loading ebtables state and starting bridge firewall"
+ ${ebtables_bin}-restore ${SAVE_RESTORE_OPTIONS} < "${ebtables_save}"
+ eend $?
+}
+
+stop() {
+ if [ "${SAVE_ON_STOP}" = "yes" ] ; then
+ save || return 1
+ fi
+ ebegin "Stopping bridge firewall"
+ local a
+ for a in ${ebtables_tables}; do
+ set_table_policy $a ACCEPT
+
+ ${ebtables_bin} -t $a -F
+ ${ebtables_bin} -t $a -X
+ done
+ eend $?
+}
+
+reload() {
+ ebegin "Flushing bridge firewall"
+ local a
+ for a in ${ebtables_tables}; do
+ ${ebtables_bin} -t $a -F
+ ${ebtables_bin} -t $a -X
+ done
+ eend $?
+
+ start
+}
+
+save() {
+ ebegin "Saving ebtables state"
+ touch "${ebtables_save}"
+ chmod 0600 "${ebtables_save}"
+ ${ebtables_bin}-save ${ebtables_tables} ${SAVE_RESTORE_OPTIONS} > "${ebtables_save}"
+ eend $?
+}
+
+panic() {
+ service_started ebtables && svc_stop
+
+ local a
+ ebegin "Dropping all packets forwarded on bridges"
+ for a in ${ebtables_tables}; do
+ ${ebtables_bin} -t $a -F
+ ${ebtables_bin} -t $a -X
+
+ set_table_policy $a DROP
+ done
+ eend $?
+}
diff --git a/main/eggdbus/APKBUILD b/main/eggdbus/APKBUILD
new file mode 100644
index 0000000000..5e81a45867
--- /dev/null
+++ b/main/eggdbus/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=eggdbus
+pkgver=0.6
+pkgrel=2
+pkgdesc="Experimental D-Bus bindings for GObject"
+url="http://www.freedesktop.org/wiki/Software/Policykit"
+arch="all"
+license="GPL"
+depends=""
+makedepends="glib-dev dbus-glib-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://hal.freedesktop.org/releases/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-static
+
+ make -j1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="b43d2a6c523fcb8b9d0b0300c4222386 eggdbus-0.6.tar.gz"
diff --git a/main/eggdrop/APKBUILD b/main/eggdrop/APKBUILD
new file mode 100644
index 0000000000..842b9a6d83
--- /dev/null
+++ b/main/eggdrop/APKBUILD
@@ -0,0 +1,68 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=eggdrop
+pkgver=1.6.20
+pkgrel=0
+pkgdesc="World's most popular Open Source IRC bot"
+url="http://www.eggheads.org/"
+arch="all"
+license='GPL-2'
+depends="tcl"
+makedepends="tcl-dev !bind-libs"
+install="$pkgname.post-install"
+subpackages="$pkgname-logs2html $pkgname-gseen"
+source="ftp://ftp.eggheads.org/pub/eggdrop/GNU/1.6/${pkgname}${pkgver}.tar.bz2
+eggdrop-installer
+gseen.mod.patch
+logs2html.mod.patch"
+
+build() {
+ cd "$srcdir/${pkgname}${pkgver}"
+
+ for i in "$srcdir"/*.patch; do
+ msg "Applying ${i}"
+ patch -p0 -i $i || return 1
+ done
+
+ ./configure --prefix=/usr
+ make config || return 1
+ make || return 1
+ mkdir -p $pkgdir/opt/eggdrop
+ make -j1 DEST="$pkgdir/opt/eggdrop" install
+ install -Dm755 "$srcdir"/eggdrop-installer "$pkgdir"/usr/bin/eggdrop-installer || return 1
+}
+
+logs2html() {
+ install=""
+ cd "$srcdir/${pkgname}${pkgver}"
+
+ for dirs in language help; do
+ mkdir -p "$subpkgdir"/opt/eggdrop/${dirs}
+ mv "$pkgdir"/opt/eggdrop/${dirs}/logs2html.* "$subpkgdir"/opt/eggdrop/${dirs}/ || return 1
+ done
+
+ mkdir -p "$subpkgdir"/opt/eggdrop/modules/
+ mv "$pkgdir"/opt/eggdrop/modules/logs2html.so "$subpkgdir"/opt/eggdrop/modules/ || return 1
+ mkdir -p "$subpkgdir"/opt/eggdrop/log2html
+
+ for files in logs2html.conf top100.tpl user.css readme.txt chan.list; do
+ cp src/mod/logs2html.mod/${files} "$subpkgdir"/opt/eggdrop/log2html/ || return 1
+ done
+}
+
+
+gseen() {
+ install=""
+ cd "$srcdir/${pkgname}${pkgver}"
+ mkdir -p "$subpkgdir"/opt/eggdrop/language
+ mv "$pkgdir"/opt/eggdrop/language/gseen.* "$subpkgdir"/opt/eggdrop/language/ || return 1
+ mkdir -p "$subpkgdir"/opt/eggdrop/modules/
+ mv "$pkgdir"/opt/eggdrop/modules/gseen.so "$subpkgdir"/opt/eggdrop/modules/ || return 1
+ mkdir -p "$subpkgdir"/opt/eggdrop/gseen
+ cp src/mod/gseen.mod/gseen.conf "$subpkgdir"/opt/eggdrop/gseen/ || return 1
+ cp src/mod/gseen.mod/README "$subpkgdir"/opt/eggdrop/gseen/ || return 1
+}
+
+md5sums="f6887c045dba11fa2755a6a9e40380a3 eggdrop1.6.20.tar.bz2
+d5214dc16c07c55edff22f495c9c367b eggdrop-installer
+37b82f60413913758cd4161dbc2e7849 gseen.mod.patch
+490ffd522d5058413c96b8325d19b838 logs2html.mod.patch"
diff --git a/main/eggdrop/eggdrop-installer b/main/eggdrop/eggdrop-installer
new file mode 100644
index 0000000000..69faa00dca
--- /dev/null
+++ b/main/eggdrop/eggdrop-installer
@@ -0,0 +1,84 @@
+#!/bin/sh
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-irc/eggdrop/files/eggdrop-installer,v 1.10 2007/03/14 17:52:24 drac Exp $
+
+source /sbin/functions.sh || {
+ echo "${0}: Could not source /etc/init.d/functions.sh!"
+ exit 1
+}
+
+# Checks to see if user is trying to install eggdrop as root.
+root_check() {
+ if [ "${HOME}" = "/root" ] || [ "$(whoami)" = "root" ]
+ then
+ ewarn "You should not be installing eggdrop as root."
+ ewarn
+ ewarn "Installing eggdrop as root leaves your computer vulnerable"
+ ewarn "to attack from other irc clients. Please use the eggdrop-installer"
+ ewarn "script as the user who you wish to run eggdrop with"
+ exit 1
+ fi
+}
+
+# Usage information
+usage() {
+ cat <<USAGE_END
+Usage: eggdrop-installer <bot-name>
+Install eggdrop for a specific user, creating the directories and files
+needed for eggdrop to run securely and safely.
+USAGE_END
+ exit 1
+}
+
+# Install eggdrop
+install_eggdrop() {
+ einfo "Installing Eggdrop"
+ einfo
+
+ root_check
+
+ if [ -d "${bot_dir}" ]
+ then
+ einfo "Already found a bot home directory for ${bot_name}"
+ exit 1
+ fi
+
+ einfo "Creating directories for your eggdrop..."
+ for dir in logs filesys/incoming text tmp scripts var
+ do
+ mkdir -p "${bot_dir}/${dir}"
+ done
+
+ einfo "Creating symlinks to required files for your bot to run..."
+ for file in help language modules eggdrop
+ do
+ ln -s "/opt/eggdrop/${file}" "${bot_dir}/${file}"
+ done
+
+ einfo "Copying motd, banner, scripts and config file..."
+ cp /opt/eggdrop/text/* "${bot_dir}/text"
+ cp /opt/eggdrop/scripts/* "${bot_dir}/scripts"
+ cp /opt/eggdrop/eggdrop.conf "${bot_dir}/eggdrop.conf"
+
+ einfo "Finished..."
+ einfo
+ einfo "Please edit your ${bot_dir}/eggdrop.conf!"
+ einfo
+ einfo "The bot needs to be run from the ${bot_dir} directory."
+ einfo "Run 'cd ${bot_dir} && ./eggdrop -m eggdrop.conf'"
+ einfo "to create the user file and then remove the -m command line option"
+ einfo "to start your eggdrop bot."
+ einfo
+ einfo "If you need any help please refer to the man page, or"
+ einfo "eggdrop website at http://www.egghelp.org/"
+}
+
+if [ -z "${1}" ]
+then
+ usage
+else
+ bot_name="${1}"
+ bot_dir="${HOME}/.eggdrop/${bot_name}"
+ install_eggdrop
+fi
diff --git a/main/eggdrop/eggdrop.post-install b/main/eggdrop/eggdrop.post-install
new file mode 100644
index 0000000000..44b43cf34e
--- /dev/null
+++ b/main/eggdrop/eggdrop.post-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+echo "*"
+echo "* Please run /usr/bin/eggdrop-installer to install your eggdrop bot."
+echo "*"
+exit 0
+
diff --git a/main/eggdrop/gseen.mod.patch b/main/eggdrop/gseen.mod.patch
new file mode 100644
index 0000000000..e70aef8873
--- /dev/null
+++ b/main/eggdrop/gseen.mod.patch
@@ -0,0 +1,5123 @@
+diff -Nur src/mod/gseen.mod/Makefile src/mod/gseen.mod/Makefile
+--- src/mod/gseen.mod/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/Makefile 2002-10-26 13:17:44.000000000 +0200
+@@ -0,0 +1,28 @@
++# Makefile for src/mod/gseen.mod/
++
++doofus:
++ @echo ""
++ @echo "Let's try this from the right directory..."
++ @echo ""
++ @cd ../../../; make
++
++clean:
++ @rm -f *.o *.$(MOD_EXT) *~
++
++static: ../gseen.o
++
++modules: ../../../gseen.$(MOD_EXT)
++
++../gseen.o: ../module.h ../modvals.h ../../eggdrop.h datahandling.c \
++ gseen.c sensors.c gseencmds.c gseencmds.c do_seen.c ai.c tclcmds.c \
++ misc.c seentree.c generic_binary_tree.c slang_gseen_commands.c \
++ slang.c slang_text.c slang_ids.c slang_chanlang.c seenlang.h \
++ slang_multitext.c gseen.h
++ $(CC) $(CFLAGS) $(CPPFLAGS) -DMAKING_MODS -c gseen.c
++ rm -f ../gseen.o
++ mv gseen.o ../
++
++../../../gseen.$(MOD_EXT): ../gseen.o
++ $(LD) -o ../../../gseen.$(MOD_EXT) ../gseen.o $(XLIBS)
++
++#safety hash
+diff -Nur src/mod/gseen.mod/README src/mod/gseen.mod/README
+--- src/mod/gseen.mod/README 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/README 2002-10-26 13:17:45.000000000 +0200
+@@ -0,0 +1,140 @@
++Description:
++------------
++
++gseen.mod is a seen module for eggdrop that tracks not only the users in the
++bot's userfile, but everyone who enters one of the bots channels.
++It does pretty much the same as the popular script bseen and has a few
++additional features like AI-seen and seen-notification.
++It's also way faster than any corresponding script because scripts are always
++much slower than modules. Especially scripts that deal with large amount of
++data often become incredible slow.
++
++Installation:
++-------------
++
++gseen.mod is written for eggdrop1.6, but it should also work with eggdrop 1.4.
++
++You need the eggdrop source to compile the module.
++
++The following instructions assume, ~/eggdrop1.6.2/ is the directory
++where you installed your eggdrop from. (of course, other source dirs
++will work as well)
++
++Put gseen.mod.1.1.0.tar.gz in ~/eggdrop1.6.2/src/mod/,
++and unpack it (tar xfz gseen.mod.1.1.0.tar.gz). Change directory
++back to ~/eggdrop1.6.2/.
++
++Now just do what you've done when you compiled your bot:
++"./configure"
++"make config" (you can skip this command on eggdrop 1.4)
++"make"
++"make install"
++
++Don't forget to copy the langfiles from eggdrop1.6.2/src/mod/gseen.mod/ to
++eggdrop/language.
++
++All settings can be found in ~/eggdrop1.6.2/src/mod/gseen.mod/gseen.conf
++Copy it to your eggdrop directory, edit it to fit your needs and put
++"source gseen.conf" at the end of your eggdrop config file. The last thing
++to do is to .rehash your bot.
++
++
++Public commands:
++----------------
++
++!seen <nick>
++ I think this command doesn't need an explanation. ^_^
++!seen <mask>
++ Searches the database for entries that match <mask>
++ for example "!seen *!user@dialin-*.isp.com"
++!seennick <nick>
++ !seen also checks if a user was online later with a
++ different nick. !seennick only seens for <nick>
++!seenstats
++ just a little report on how many nicks are tracked
++
++All commands are also accessible via /msg.
++("/msg <bot> seen <nick>", for example)
++
++
++AI seen:
++--------
++
++This module has a simple built in AI routine.
++A short example:
++
++<G`Quann> Argo: have you seen Fabian recently?
++<|Argo|> G`Quann, fabian (~fabian@dns.gifs.de) was last seen quitting
++from #eggdev 1 week 4 days 9 hours 40 minutes 56 seconds ago
++(20.02. 01:39) stating ".....zzzzZZZzzZZZzZZZZZZZZZZzzz..".
++
++Well, it's not a very intelligent AI, it's rather brute-force. So don't
++forget to use the ai-seen-ignore setting.
++I know that's not coded very elegant, but if you configure it correctly,
++the failure-rate is way lower than with other AI scripts...
++
++DCC commands:
++-------------
++
++.seen
++.seennick
++.seenstats
++ just the same as the public versions
++.purgeseens
++ deletes expired data (this also happens automatically once a day)
++ (m)
++
++Channel Settings:
++-----------------
++
++ +noseendata
++ don't log any seen data in this channel
++ +quietseens
++ send answers directly via notice to the person who asked and
++ don't bother the rest of the channel with the reply
++ +quietaiseens
++ same as +quietseens, but for AI seens
++ +nopubseens
++ ignore every seen-command in this channel
++
++TCL commands:
++-------------
++
++There are no special tcl commands, only the usual bind procs.
++
++The only one that should be mentioned is:
++
++*pubm:seen <nick> <uhost> <hand> <chan> <text>
++ triggers the AI seen
++ returns: 1 if a reply was sent, 0 otherwise
++
++So if you're using another AI script on your bot, you can modify it to
++use this proc and avoid doubled replies this way.
++
++Other:
++------
++
++There is absolutely NO WARRANTY on this module. I do my best to make it
++work properly, but if anything gets screwed up, I'm not responsible. Use
++this module at your own risk.
++
++Feedback:
++---------
++
++Feel free to send feedback and bugreports (I hope there won't be any<g>) to
++gseen.mod@visions-of-fantasy.de
++
++The newest gseen version can always be found at:
++http://www.visions-of-fantasy.de/gseen.mod/
++
++Thanks to:
++----------
++
++- Fabian for teaching me plenty of things
++- everyone who tested the many buggy development versions :)
++- the eggdev team for developing eggdrop
++
++Most of all, I would like to thank Bass for writing bseen.tcl because alot
++of the ideas for this module came from using that tcl script. It's still the
++most powerful seen script, so if you want something that's easier to use than
++a module, get a copy of bseen.tcl.
+diff -Nur src/mod/gseen.mod/UPDATES src/mod/gseen.mod/UPDATES
+--- src/mod/gseen.mod/UPDATES 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/UPDATES 2002-10-26 13:17:46.000000000 +0200
+@@ -0,0 +1,55 @@
++Changes in gseen.mod: (since v1.0.0)
++--------------------
++
++1.1.1
++- fixed "no newline" compilation warnings that appeared on some systems.
++- fixed uninitialized "li" variable in do_seen()
++- fixed lacking compatibility to eggdrop1.4 (confirmation anyone?)
++- new option: hide-secret-chans
++
++1.1.0 (15.6.2001)
++- added multilang support
++- removed static buffers
++- organized data in a binary search tree (much faster)
++- optimized a few other things
++- added settings:
++ - fuzzy-search
++ - max-matches
++ - wildcard-search
++
++1.0.8
++- quiet-seens wasn't working for !seennick
++- added quiet-ai-seens
++- renamed nopub to nopubseens and nolog to noseendata and
++ quietseen to quietseens
++
++1.0.7
++- added compatibility to !channels
++- fixed a bug relating strict-host 0 had some strange effects on
++ !seen requests for users with ~ in their ident
++
++1.0.6
++- fixed a very evil bug that allowed anyone to crash the bot, sorry
++
++1.0.5
++- quietseens wasn't working correctly
++- added support for egg1.5's udef chansets
++
++1.0.4
++- added GPL stuff
++- changed error msg that appears if no gseen file exists
++
++1.0.3
++- readme updates
++- fixed a grammatical error in do_seen
++
++1.0.2
++- bot wanted to free a NULL pointer sometimes
++
++1.0.1
++- !seen without parameter returned stupid results :)
++- fixed little typo in .purgeseens
++- "I found 1 matches..." -> "I found 1 match..."
++
++1.0.0
++- release :)
+diff -Nur src/mod/gseen.mod/addons/gseen.selectlang.1.0.0.tcl src/mod/gseen.mod/addons/gseen.selectlang.1.0.0.tcl
+--- src/mod/gseen.mod/addons/gseen.selectlang.1.0.0.tcl 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/addons/gseen.selectlang.1.0.0.tcl 2002-10-26 13:18:14.000000000 +0200
+@@ -0,0 +1,80 @@
++#####################################################################
++#
++# gseen.selectlang v1.0.0
++#
++# This is a simple script which selects a language based on the
++# user's host.
++#
++# It only works for /msg commands.
++#
++# If the user is in a channel which has a language defined, gseen's
++# internal functions will override this selection and use the language
++# of the channel instead.
++#
++#####################################################################
++
++
++# Here you can define which language to use for which host.
++# The first part is the mask for the host, and the second part
++# is the language which should be used for this host.
++
++set tld-langs {
++ {"*.de" "de"}
++ {"*.at" "de"}
++ {"*.ch" "de"}
++ {"*.t-dialin.net" "de"}
++ {"*.t-ipconnect.net" "de"}
++ {"*.pl" "pl"}
++ {"*.jp" "ja"}
++}
++
++#################################################
++
++
++proc selectlang:getlang {uhost} {
++ global tld-langs
++
++ foreach tld ${tld-langs} {
++ if {[string match [lindex $tld 0] $uhost]} {
++ return [lindex $tld 1]
++ }
++ }
++ return ""
++}
++
++proc sl:rebind {oldtarget newtarget} {
++ foreach binding [binds msg] {
++ if {[lindex $binding 4] == $oldtarget} {
++ unbind [lindex $binding 0] [lindex $binding 1] [lindex $binding 2] [lindex $binding 4]
++ bind [lindex $binding 0] [lindex $binding 1] [lindex $binding 2] $newtarget
++ }
++ }
++}
++
++proc sl:msg:trigger {nick uhost hand rest target} {
++ global default-slang
++
++ set lang [selectlang:getlang $uhost]
++ set old-slang ${default-slang}
++ if {$lang != ""} {
++ set default-slang $lang
++ putlog "using '$lang'..."
++ }
++ $target $nick $uhost $hand $rest
++ set default-slang ${old-slang}
++}
++
++sl:rebind *msg:seen sl:msg:seen
++proc sl:msg:seen {nick uhost hand rest} {
++ sl:msg:trigger $nick $uhost $hand $rest *msg:seen
++}
++
++sl:rebind *msg:seenstats sl:msg:seenstats
++proc sl:msg:seenstats {nick uhost hand rest} {
++ sl:msg:trigger $nick $uhost $hand $rest *msg:seenstats
++}
++
++sl:rebind *msg:seennick sl:msg:seennick
++proc sl:msg:seennick {nick uhost hand rest} {
++ sl:msg:trigger $nick $uhost $hand $rest *msg:seennick
++}
+\ No newline at end of file
+diff -Nur src/mod/gseen.mod/ai.c src/mod/gseen.mod/ai.c
+--- src/mod/gseen.mod/ai.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/ai.c 2002-10-26 13:17:47.000000000 +0200
+@@ -0,0 +1,151 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++static int quietaiseens(char *chan)
++{
++ char buf[121], *b;
++
++ Context;
++ strncpy(buf, quiet_ai_seen, 120);
++ buf[120] = 0;
++ b = buf;
++ while (b[0])
++ if (!strcasecmp(chan, newsplit(&b)))
++ return 1;
++#if EGG_IS_MIN_VER(10503)
++ if (ngetudef("quietaiseens", chan))
++ return 1;
++#endif
++ return 0;
++}
++
++static int tcl_pubmseen STDVAR
++{
++ char *nick, *uhost, *hand, *chan, *text;
++ char buf[1024];
++ char *words, *word;
++ seendat *l;
++ int i;
++
++ Context;
++ BADARGS(6, 6, " nick uhost hand chan text");
++ nick = argv[1];
++ uhost = argv[2];
++ hand = argv[3];
++ chan = argv[4];
++ text = argv[5];
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, chan));
++ glob_nick = nick;
++ for (i = 0; i < strlen(text); i++)
++ if (strchr("!?.,\"", text[i]))
++ text[i] = ' ';
++ strncpy(buf, ignore_words, 1023);
++ buf[1023] = 0;
++ words = buf;
++ while (words[0])
++ add_ignoredword(newsplit(&words));
++ strncpy(buf, text, 1023);
++ buf[1023] = 0;
++ words = buf;
++ while (words[0]) {
++ word = newsplit(&words);
++ if (word_is_ignored(word))
++ continue;
++ l = findseen(word);
++ if (l) {
++ if (quietaiseens(chan)) {
++ set_prefix(SLNOTPREFIX);
++ dprintf(DP_HELP, "NOTICE %s :%s%s\n", nick, reply_prefix,
++ do_seen(word, nick, uhost, chan, 0));
++ } else {
++ set_prefix(SLPUBPREFIX);
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s\n", chan, reply_prefix,
++ do_seen(word, nick, uhost, chan, 0));
++ }
++ add_seenreq(word, nick, uhost, chan, now);
++ free_ignoredwords();
++ Tcl_AppendResult(irp, "1", NULL);
++ return TCL_OK;
++ }
++ }
++ free_ignoredwords();
++ Tcl_AppendResult(irp, "0", NULL);
++ return TCL_OK;
++}
++
++static tcl_cmds mytcls[] =
++{
++ {"*pubm:seen", tcl_pubmseen},
++ {"*chjn:gseen", gseen_chjn},
++ {"*chpt:gseen", gseen_chpt},
++ {0, 0}
++};
++
++static void add_ignoredword(char *word)
++{
++ ignoredword *l, *nl;
++
++ l = ignoredwords;
++ while (l && l->next)
++ l = l->next;
++ nl = nmalloc(sizeof(ignoredword));
++ nl->word = nmalloc(strlen(word) + 1);
++ strcpy(nl->word, word);
++ nl->next = NULL;
++ if (ignoredwords)
++ l->next = nl;
++ else
++ ignoredwords = nl;
++}
++
++static void free_ignoredwords()
++{
++ ignoredword *l, *ll;
++
++ l = ignoredwords;
++ while (l) {
++ ll = l->next;
++ nfree(l->word);
++ nfree(l);
++ l = ll;
++ }
++ ignoredwords = NULL;
++}
++
++static int expmem_ignoredwords()
++{
++ ignoredword *l;
++ int size = 0;
++
++ for (l = ignoredwords; l; l = l->next) {
++ size += sizeof(ignoredword);
++ size += strlen(l->word) + 1;
++ }
++ return size;
++}
++
++static int word_is_ignored(char *word)
++{
++ ignoredword *l;
++
++ for (l = ignoredwords; l; l = l->next)
++ if (!strcasecmp(l->word, word))
++ return 1;
++ return 0;
++}
+diff -Nur src/mod/gseen.mod/datahandling.c src/mod/gseen.mod/datahandling.c
+--- src/mod/gseen.mod/datahandling.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/datahandling.c 2002-10-26 13:17:48.000000000 +0200
+@@ -0,0 +1,151 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++
++static void write_seens()
++{
++ seenreq *r;
++ seenreq_by *b;
++ FILE *f;
++ char s[125];
++
++ Context;
++ /* putlog(LOG_MISC, "*", "Saving seen data..."); */
++ if (!gseenfile[0])
++ return;
++ sprintf(s, "%s~new", gseenfile);
++ f = fopen(s, "w");
++ chmod(s, 0600);
++ if (f == NULL) {
++ putlog(LOG_MISC, "*", "ERROR writing gseen file.");
++ return;
++ }
++ fprintf(f, "# gseen data file v1.\n");
++ write_seen_tree_target = f;
++ btree_getall(&seentree, write_seen_tree);
++ for (r = requests; r; r = r->next)
++ for (b = r->by; b; b = b->next)
++ /* @ nick by host chan when */
++ fprintf(f, "@ %s %s %s %s %lu\n", r->nick, b->who, b->host, b->chan,
++ b->when);
++ fclose(f);
++ unlink(gseenfile);
++ movefile(s, gseenfile);
++ /* putlog(LOG_MISC, "*", "Done."); */
++ return;
++}
++
++static void read_seens()
++{
++ FILE *f;
++ char buf[512], *s, *type, *nick, *host, *chan, *msg, *by;
++ time_t when;
++ int spent, iType, i;
++
++ Context;
++ f = fopen(gseenfile, "r");
++ if (f == NULL) {
++ putlog(LOG_MISC, "*", "Can't open gseen file, creating new database...");
++ return;
++ }
++ while (!feof(f)) {
++ buf[0] = 0;
++ s = buf;
++ fgets(s, 511, f);
++ i = strlen(buf);
++ if (buf[i - 1] == '\n')
++ buf[i - 1] = 0;
++ if ((buf[0] == 0) || (buf[0] == '#'))
++ continue;
++ type = newsplit(&s);
++ if (!strcmp(type, "!")) {
++ nick = newsplit(&s);
++ host = newsplit(&s);
++ chan = newsplit(&s);
++ iType = atoi(newsplit(&s));
++ when = (time_t) atoi(newsplit(&s));
++ spent = atoi(newsplit(&s));
++ msg = s;
++ add_seen(iType, nick, host, chan, msg, when, spent);
++ } else if (!strcmp(type, "@")) {
++ nick = newsplit(&s);
++ by = newsplit(&s);
++ host = newsplit(&s);
++ chan = newsplit(&s);
++ when = (time_t) atoi(newsplit(&s));
++ add_seenreq(nick, by, host, chan, when);
++ }
++ }
++ fclose(f);
++ Context;
++ return;
++}
++
++static void purge_seens()
++{
++ seenreq *r, *rr;
++ seenreq_by *b, *bb;
++
++ Context;
++ if (!expire_seens)
++ return;
++ btree_getall_expanded(&seentree, purge_seen_tree);
++ debug0("purge done");
++ r = requests;
++ rr = NULL;
++ while (r) {
++ b = r->by;
++ bb = NULL;
++ while (b) {
++ if ((now - b->when) > (expire_seens * 86400)) {
++ debug2("request for %s from %s has expired.", r->nick, b->who);
++ nfree(b->who);
++ nfree(b->host);
++ nfree(b->chan);
++ if (bb) {
++ bb->next = b->next;
++ nfree(b);
++ b = bb->next;
++ } else {
++ r->by = b->next;
++ nfree(b);
++ b = r->by;
++ }
++ } else {
++ bb = b;
++ b = b->next;
++ }
++ }
++ if (!r->by) {
++ debug1("no further seen requests for %s, deleting", r->nick);
++ nfree(r->nick);
++ if (rr) {
++ rr->next = r->next;
++ nfree(r);
++ r = rr->next;
++ } else {
++ requests = r->next;
++ nfree(r);
++ r = requests;
++ }
++ } else {
++ rr = r;
++ r = r->next;
++ }
++ }
++}
+diff -Nur src/mod/gseen.mod/do_seen.c src/mod/gseen.mod/do_seen.c
+--- src/mod/gseen.mod/do_seen.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/do_seen.c 2002-10-26 13:17:50.000000000 +0200
+@@ -0,0 +1,840 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++/* do_seen(): Checks if someone matches the mask, and returns the reply
++ * mask : first paramater (e.g. "G`Quann", "G`Quann", "*!*@*.isp.de", ...)
++ * nick : nick of the one, who triggered the command
++ * uhost: user@host of nick
++ * chan : chan, where the command was triggered
++ * bns :
++ * 1 : do a botnet-seen if no matches are found
++ * 0 : don't do a botnet-seen
++ * -1 : return NULL instead of text, if no matches were found
++ * (necessary for botnet seen)
++ */
++static char *do_seen(char *mask, char *nick, char *uhost, char *chan, int bns)
++{
++ char hostbuf[UHOSTLEN + 1], *host, *newhost, *tmp, *dur;
++ seendat *l;
++ gseenres *r;
++ int wild, nr;
++ char bnquery[256];
++ struct userrec *u;
++ struct laston_info *li;
++ struct chanset_t *ch;
++
++ Context;
++ start_seentime_calc();
++ if (seen_reply) {
++ nfree(seen_reply);
++ seen_reply = NULL;
++ }
++ l = NULL;
++ li = NULL;
++ host = hostbuf;
++ newhost = NULL;
++ mask = newsplit(&mask);
++ glob_query = mask;
++ while (mask[0] == ' ')
++ mask++;
++ if (!mask[0]) {
++ return SLNOPARAM;
++ }
++ if (strchr(mask, '?') || strchr(mask, '*')) {
++ // if wildcard-searches ares not allowed, then either return
++ // NULL (for botnet-seen), or a appropriate warning
++ if (!wildcard_search) {
++ if (bns == -1)
++ return NULL;
++ else
++ return SLNOWILDCARDS;
++ } else
++ wild = 1;
++ } else {
++ if (strlen(mask) > seen_nick_len) // don't process if requested nick is too long
++ return SLTOOLONGNICK; // (e.g. stop stupid jokes)
++ if (!strcasecmp(mask, nick)) {
++ return SLMIRROR;
++ }
++ // check if the nick is on the current channel
++ if (onchan(mask, chan))
++ return SLONCHAN;
++ if ((glob_othernick = handonchan(mask, chan)))
++ return SLHANDONCHAN;
++ // check if it is on any other channel
++ if ((ch = onanychan(mask))) {
++#if EGG_IS_MIN_VER(10500)
++ if (!secretchan(ch->dname)) {
++ glob_otherchan = ch->dname;
++ return SLONOTHERCHAN;
++ }
++#else
++ if (!secretchan(ch->name)) {
++ glob_otherchan = ch->name;
++ return SLONOTHERCHAN;
++ }
++#endif
++ }
++ // check if the user who uses this handle is on the channel under
++ // a different nick
++ if ((ch = handonanychan(mask))) {
++#if EGG_IS_MIN_VER(10500)
++ if (!secretchan(ch->dname)) {
++ glob_otherchan = ch->dname;
++ return SLONOTHERCHAN;
++ }
++#else
++ if (!secretchan(ch->name)) {
++ glob_otherchan = ch->name;
++ return SLONOTHERCHAN;
++ }
++#endif
++ }
++ add_seenreq(mask, nick, uhost, chan, now);
++ wild = 0;
++ l = findseen(mask);
++ // if there's a result, and if we don't want to search for the same user
++ // under a different nick, just make a do_seennick on the result
++ if (l && !fuzzy_search) {
++ tmp = do_seennick(l);
++ end_seentime_calc();
++ return tmp;
++ }
++ if (!l) {
++ u = get_user_by_handle(userlist, mask);
++ if (u) {
++ li = get_user(&USERENTRY_LASTON, u);
++ }
++ if (!u || !li) {
++ if (bns == -1) { // if bns is 0, then do_seen() was triggered by
++ end_seentime_calc(); // a botnet seen function, which needs a clear
++ return NULL; // NULL to detect if there was a result or not
++ }
++ tmp = SLNOTSEEN;
++ if (bns && ((strlen(mask) + strlen(nick) + strlen(uhost)
++ + strlen(chan) + 20) < 255)) {
++ debug0("trying botnet seen");
++ if (bnsnick)
++ nfree(bnsnick);
++ if (bnschan)
++ nfree(bnschan);
++ bnsnick = nmalloc(strlen(nick) + 1);
++ strcpy(bnsnick, nick);
++ bnschan = nmalloc(strlen(chan) + 1);
++ strcpy(bnschan, chan);
++ sprintf(bnquery, "gseen_req %s %s %s %s", mask, nick, uhost, chan);
++ botnet_send_zapf_broad(-1, botnetnick, NULL, bnquery);
++ }
++ } else {
++ // we have a matching handle, no seen-entry, but a laston entry
++ // in the userbase, so let's just return that one.
++ dur = gseen_duration(now - li->laston);
++ glob_laston = dur;
++ tmp = SLPOORSEEN;
++ seen_reply = nmalloc(strlen(tmp) + 1);
++ strcpy(seen_reply, tmp);
++ end_seentime_calc();
++ return seen_reply;
++ }
++ end_seentime_calc();
++ return tmp;
++ }
++ // now prepare the host for fuzzy-search
++ if (strlen(l->host) < UHOSTLEN) {
++ maskstricthost(l->host, host);
++ host = strchr(host, '!') + 1; // strip nick from host for faster search
++ } else {
++ end_seentime_calc();
++ return "error, too long host";
++ }
++ }
++ if (l && (l->type == SEEN_CHPT)) {
++ tmp = do_seennick(l);
++ end_seentime_calc();
++ return tmp;
++ }
++ numresults = 0;
++ // wildmatch_seens uses a global var to store hosts in it
++ // (to prevent massive nmalloc/nfree-usage), so don't forget
++ // to initialize and free it
++ temp_wildmatch_host = my_malloc(1);
++ wildmatch_seens(host, mask, wild);
++ my_free(temp_wildmatch_host);
++ temp_wildmatch_host = NULL;
++ if (!results) {
++ end_seentime_calc();
++ if (bns == -1)
++ return NULL; // let the botnet seen function know, that seen failed
++ return SLNOMATCH;
++ }
++ if (numresults >= max_matches) {
++ end_seentime_calc();
++ free_seenresults();
++ return SLTOOMANYMATCHES;
++ }
++ sortresults();
++ if (strcasecmp(results->seen->nick, mask)) {
++ // if the user's latest nick is not the nick for which we were searching,
++ // say that there were multiple matches and display the latest one
++ if (numresults == 1)
++ tmp = SLONEMATCH;
++ else if (numresults <= 5)
++ tmp = SLLITTLEMATCHES;
++ else
++ tmp = SLMANYMATCHES;
++ seen_reply = nmalloc(strlen(tmp) + 1);
++ strcpy(seen_reply, tmp);
++ nr = 0;
++ for (r = results; (r && (nr < 5)); r = r->next) {
++ nr++;
++ if (nr > 1) {
++ seen_reply = nrealloc(seen_reply, 1 + strlen(seen_reply) + 1 + strlen(r->seen->nick) + 1);
++ strcat(seen_reply, ", ");
++ } else {
++ seen_reply = nrealloc(seen_reply, 1 + strlen(seen_reply) + strlen(r->seen->nick) + 1);
++ strcat(seen_reply, " ");
++ }
++ strcat(seen_reply, r->seen->nick);
++ }
++ tmp = do_seennick(results->seen);
++ seen_reply = nrealloc(seen_reply, 2 + strlen(seen_reply) + strlen(tmp) + 1);
++ sprintf(seen_reply, "%s. %s", seen_reply, tmp);
++ } else { // first result is the nick which we were searching for
++ // just return the info for this nick and don't care about other results
++ tmp = do_seennick(results->seen);
++ seen_reply = nmalloc(strlen(tmp) + 1);
++ strcpy(seen_reply, tmp);
++ }
++ free_seenresults();
++ end_seentime_calc();
++ return seen_reply;
++}
++
++/* do_seennick():
++ * takes a seen-dataset and produces the corresponding reply basically
++ * by referencing to the lang entry with the same number as the seen-type.
++ */
++static char *do_seennick(seendat *l)
++{
++// char buf[256], *msg;
++ int stype;
++
++ Context;
++ if (!l) {
++ debug0("ERROR! Tryed to do a seennick on a NULL pointer!");
++ return "ERROR! seendat == NULL!!!";
++ }
++ glob_seendat = l;
++ // l->type is the basic language-entry-number
++ stype = l->type + 100;
++ // in some cases, we might need a special reply, so modify the
++ // number if neccessary
++ switch (l->type) {
++ case SEEN_JOIN:
++ if (!onchan(l->nick, l->chan))
++ stype += 20;
++ break;
++ case SEEN_PART:
++ /* nothing to do here */
++ break;
++ case SEEN_SIGN:
++ /* nothing again */
++ break;
++ case SEEN_NICK:
++ if (!onchan(l->msg, l->chan))
++ stype += 20;
++ break;
++ case SEEN_NCKF:
++ if (!onchan(l->nick, l->chan))
++ stype += 20;
++ break;
++ case SEEN_KICK:
++/* msg = buf;
++ strncpy(buf, l->msg, 255);
++ msg[255] = 0;
++ sglobpunisher = newsplit(&msg);
++ sglobreason = msg; */
++ break;
++ case SEEN_SPLT:
++ /* nothing to do here */
++ break;
++ case SEEN_REJN:
++ if (!onchan(l->nick, l->chan))
++ stype += 20;
++ break;
++ case SEEN_CHJN:
++ case SEEN_CHPT:
++ if (!strcmp(l->chan, "0"))
++ stype += 20;
++ break;
++ default:
++ stype = 140;
++ }
++ return getslang(stype);
++}
++
++/* findseens():
++ * interface for webseen.mod
++ * find all results for a query and return a pointer to this list
++ * (basically the core of do_seen())
++ */
++static gseenres *findseens(char *mask, int *ret, int fuzzy)
++{
++ char hostbuf[UHOSTLEN + 1], *host, *newhost;
++ seendat *l;
++ int wild;
++
++ Context;
++ start_seentime_calc();
++ *ret = WS_OK;
++ l = NULL;
++ host = hostbuf;
++ newhost = NULL;
++ mask = newsplit(&mask);
++ while (mask[0] == ' ')
++ mask++;
++ if (!mask[0]) {
++ *ret = WS_NOPARAM;
++ return NULL;
++ }
++ if (strchr(mask, '?') || strchr(mask, '*')) {
++ // if wildcard-searches ares not allowed, then either return
++ // NULL (for botnet-seen), or a appropriate warning
++ if (!wildcard_search) {
++ *ret = WS_NOWILDCARDS;
++ return NULL;
++ }
++ wild = 1;
++ } else {
++ if (strlen(mask) > seen_nick_len) { // don't process if requested nick is too long
++ *ret = WS_TOOLONGNICK; // (e.g. stop stupid jokes)
++ return NULL;
++ }
++ add_seenreq(mask, "www-user", "unknown_host", "webinterface", now);
++ wild = 0;
++ l = findseen(mask);
++ // if there's a result, and if we don't want to search for the same user
++ // under a different nick, just return this result
++ if (l && (!fuzzy_search || !fuzzy)) {
++ numresults = 1;
++ add_seenresult(l);
++ end_seentime_calc();
++ return results;
++ }
++ if (!l) {
++ // no matching user was found :(
++ *ret = WS_NORESULT;
++ end_seentime_calc();
++ return NULL;
++ }
++ // now prepare the host for fuzzy-search
++ if (strlen(l->host) < UHOSTLEN) {
++ maskstricthost(l->host, host);
++ host = strchr(host, '!') + 1; // strip nick from host for faster search
++ } else {
++ *ret = WS_TOOLONGHOST;
++ end_seentime_calc();
++ return NULL;
++ }
++ }
++ if (l && (l->type == SEEN_CHPT)) {
++ numresults = 1;
++ add_seenresult(l);
++ end_seentime_calc();
++ return results;
++ }
++ numresults = 0;
++ // wildmatch_seens uses a global var to store hosts in it
++ // (to prevent massive nmalloc/nfree-usage), so don't forget
++ // to initialize and free it
++ temp_wildmatch_host = my_malloc(1);
++ wildmatch_seens(host, mask, wild);
++ my_free(temp_wildmatch_host);
++ temp_wildmatch_host = NULL;
++ if (!results) {
++ // no match :(
++ *ret = WS_NORESULT;
++ end_seentime_calc();
++ return NULL;
++ }
++ if (numresults >= max_matches) {
++ free_seenresults();
++ *ret = WS_TOOMANYMATCHES;
++ end_seentime_calc();
++ return NULL;
++ }
++ sortresults();
++ *ret = 0;
++ end_seentime_calc();
++ return results;
++}
++
++
++char seenstats_reply[512];
++static char *do_seenstats()
++{
++ glob_totalnicks = count_seens();
++ glob_totalbytes = gseen_expmem();
++ sprintf(seenstats_reply, "%s", SLSEENSTATS);
++ return seenstats_reply;
++}
++
++// add an seen result (to the top of the list)
++static void add_seenresult(seendat *seen)
++{
++ gseenres *nl;
++
++ numresults++;
++ if (numresults > max_matches)
++ return;
++ nl = nmalloc(sizeof(gseenres));
++ nl->seen = seen;
++ nl->next = results;
++ results = nl;
++}
++
++static int expmem_seenresults()
++{
++ int bytes = 0;
++ gseenres *l;
++
++ for (l = results; l; l = l->next)
++ bytes += sizeof(gseenres);
++ return bytes;
++}
++
++static void free_seenresults()
++{
++ gseenres *l, *ll;
++
++ l = results;
++ while (l) {
++ ll = l->next;
++ nfree(l);
++ l = ll;
++ }
++ results = NULL;
++}
++
++static void sortresults()
++{
++ int again = 1;
++ gseenres *last, *p, *c, *n;
++ int a, b;
++
++ Context;
++ again = 1;
++ last = NULL;
++ while ((results != last) && (again)) {
++ p = NULL;
++ c = results;
++ n = c->next;
++ again = 0;
++ while (n != last) {
++ if (!c || !n)
++ a = b = 0;
++ else
++ a = c->seen->when;
++ b = n->seen->when;
++ if (a < b) {
++ again = 1;
++ c->next = n->next;
++ n->next = c;
++ if (p == NULL)
++ results = n;
++ else
++ p->next = n;
++ }
++ p = c;
++ c = n;
++ n = n->next;
++ }
++ last = c;
++ }
++ Context;
++ return;
++}
++
++static void sortrequests(seenreq *l)
++{
++ int again = 1;
++ seenreq_by *last, *p, *c, *n;
++ int a, b;
++
++ Context;
++ again = 1;
++ last = NULL;
++ while ((l->by != last) && (again)) {
++ p = NULL;
++ c = l->by;
++ n = c->next;
++ again = 0;
++ while (n != last) {
++ if (!c || !n)
++ a = b = 0;
++ else
++ a = c->when;
++ b = n->when;
++ if (a < b) {
++ again = 1;
++ c->next = n->next;
++ n->next = c;
++ if (p == NULL)
++ l->by = n;
++ else
++ p->next = n;
++ }
++ p = c;
++ c = n;
++ n = n->next;
++ }
++ last = c;
++ }
++ Context;
++ return;
++}
++
++/* stolen from tcl_duration in tclmisc.c */
++char gs_duration_temp[256];
++static char *gseen_duration(int seconds)
++{
++ char s[256];
++ time_t sec;
++
++ sec = seconds;
++ s[0] = 0;
++ if (sec < 1) {
++ snprintf(gs_duration_temp, sizeof(gs_duration_temp), "%s", SLSOMETIME);
++ return gs_duration_temp;
++ }
++ if (sec < 60) {
++ sprintf(gs_duration_temp, "%d %s", (int) (sec / 1),
++ ((int) (sec / 1) > 1) ? SLSECONDS : SLSECOND);
++ return gs_duration_temp;
++ }
++ if (sec >= 31536000) {
++ sprintf(s, "%d %s ", (int) (sec / 31536000),
++ ((int) (sec / 31536000) > 1) ? SLYEARS : SLYEAR);
++ sec -= (((int) (sec / 31536000)) * 31536000);
++ }
++ if (sec >= 604800) {
++ sprintf(&s[strlen(s)], "%d %s ", (int) (sec / 604800),
++ ((int) (sec / 604800) > 1) ? SLWEEKS : SLWEEK);
++ sec -= (((int) (sec / 604800)) * 604800);
++ }
++ if (sec >= 86400) {
++ sprintf(&s[strlen(s)], "%d %s ", (int) (sec / 86400),
++ ((int) (sec / 86400) > 1) ? SLDAYS : SLDAY);
++ sec -= (((int) (sec / 86400)) * 86400);
++ }
++ if (sec >= 3600) {
++ sprintf(&s[strlen(s)], "%d %s ", (int) (sec / 3600),
++ ((int) (sec / 3600) > 1) ? SLHOURS : SLHOUR);
++ sec -= (((int) (sec / 3600)) * 3600);
++ }
++ if (sec >= 60) {
++ sprintf(&s[strlen(s)], "%d %s ", (int) (sec / 60),
++ ((int) (sec / 60) > 1) ? SLMINUTES : SLMINUTE);
++ sec -= (((int) (sec / 60)) * 60);
++ }
++ strcpy(gs_duration_temp, s);
++ if (gs_duration_temp[strlen(gs_duration_temp) - 1] == ' ')
++ gs_duration_temp[strlen(gs_duration_temp) - 1] = 0;
++ return gs_duration_temp;
++}
++
++static int onchan(char *nick, char *chan)
++{
++ struct chanset_t *ch;
++ memberlist *m;
++
++ ch = findchan_by_dname(chan);
++ if (!ch)
++ return 0;
++ m = ismember(ch, nick);
++ if (!m)
++ return 0;
++ else if (chan_issplit(m))
++ return 0;
++ else
++ return 1;
++}
++
++/* handonchan():
++ * checks if the given user is on the channel and returns its nick
++ */
++static char *handonchan(char *hand, char *chan)
++{
++ struct chanset_t *ch;
++ memberlist *m;
++
++ ch = findchan_by_dname(chan);
++ if (!ch)
++ return 0;
++ if (ch->channel.members > 0) {
++ for (m = ch->channel.member; m; m = m->next) {
++ if (m->user) {
++ if (m->user->handle && !rfc_casecmp(m->user->handle, hand))
++ return m->nick;
++ }
++ }
++ }
++ return NULL;
++}
++
++/* onanychan():
++ * checks if the given nickname is on any of the bot's chans.
++ */
++static struct chanset_t *onanychan(char *nick)
++{
++ struct chanset_t *ch;
++ memberlist *m;
++
++ for (ch = chanset; ch; ch = ch->next) {
++ m = ismember(ch, nick);
++ if (m && !chan_issplit(m))
++ return ch;
++ }
++ return NULL;
++}
++
++/* handonanychan():
++ * checks if the given user is on any channel (no matter under which nick)
++ */
++static struct chanset_t *handonanychan(char *hand)
++{
++ struct chanset_t *ch;
++ memberlist *m;
++
++ for (ch = chanset; ch; ch = ch->next) {
++ if (ch->channel.members > 0) {
++ for (m = ch->channel.member; m; m = m->next) {
++ if (m->user) {
++ if (m->user->handle && !rfc_casecmp(m->user->handle, hand))
++ return ch;
++ }
++ }
++ }
++ }
++ return NULL;
++}
++
++static void add_seenreq(char *nick, char *from, char *host, char *chan,
++ time_t when)
++{
++ seenreq *l, *nl;
++ seenreq_by *b, *nb;
++ char buf[10] = "[secret]";
++
++ Context;
++ if (!tell_seens)
++ return;
++ if (strcmp(chan, "[partyline]") && secretchan(chan))
++ chan = buf;
++ for (l = requests; l; l = l->next) {
++ if (!strcasecmp(nick, l->nick)) {
++ for (b = l->by; b; b = b->next) {
++ if (!strcasecmp(from, b->who)) {
++ nfree(b->chan);
++ b->chan = nmalloc(strlen(chan) + 1);
++ strcpy(b->chan, chan);
++ b->when = when;
++ return;
++ }
++ }
++ b = l->by;
++ while (b && b->next)
++ b = b->next;
++ nb = nmalloc(sizeof(seenreq_by));
++ nb->who = nmalloc(strlen(from) + 1);
++ strcpy(nb->who, from);
++ nb->host = nmalloc(strlen(host) + 1);
++ strcpy(nb->host, host);
++ nb->chan = nmalloc(strlen(chan) + 1);
++ strcpy(nb->chan, chan);
++ nb->when = when;
++ nb->next = NULL;
++ if (l->by)
++ b->next = nb;
++ else
++ l->by = nb;
++ return;
++ }
++ }
++ nb = nmalloc(sizeof(seenreq_by));
++ nb->who = nmalloc(strlen(from) + 1);
++ strcpy(nb->who, from);
++ nb->host = nmalloc(strlen(host) + 1);
++ strcpy(nb->host, host);
++ nb->chan = nmalloc(strlen(chan) + 1);
++ strcpy(nb->chan, chan);
++ nb->when = when;
++ nb->next = NULL;
++ l = requests;
++ while (l && l->next)
++ l = l->next;
++ nl = nmalloc(sizeof(seenreq));
++ nl->nick = nmalloc(strlen(nick) + 1);
++ strcpy(nl->nick, nick);
++ nl->by = nb;
++ nl->next = NULL;
++ if (requests)
++ l->next = nl;
++ else
++ requests = nl;
++}
++
++static int expmem_seenreq()
++{
++ seenreq *l;
++ seenreq_by *b;
++ int size;
++
++ size = 0;
++ for (l = requests; l; l = l->next) {
++ size += sizeof(seenreq);
++ size += strlen(l->nick) + 1;
++ for (b = l->by; b; b = b->next) {
++ size += sizeof(seenreq_by);
++ size += strlen(b->who) + 1;
++ size += strlen(b->host) + 1;
++ size += strlen(b->chan) + 1;
++ }
++ }
++ return size;
++}
++
++static int count_seenreq(seenreq_by *b)
++{
++ seenreq_by *l;
++ int nr;
++
++ nr = 0;
++ for (l = b; l; l = l->next)
++ nr++;
++ return nr;
++}
++
++static void free_seenreq()
++{
++ seenreq *l, *ll;
++ seenreq_by *b, *bb;
++
++ Context;
++ l = requests;
++ while (l) {
++ b = l->by;
++ while (b) {
++ bb = b->next;
++ nfree(b->who);
++ nfree(b->host);
++ nfree(b->chan);
++ nfree(b);
++ b = bb;
++ }
++ ll = l->next;
++ nfree(l->nick);
++ nfree(l);
++ l = ll;
++ }
++ requests = NULL;
++}
++
++static void report_seenreq(char *channel, char *nick)
++{
++ seenreq *l, *ll;
++ seenreq_by *b, *bb;
++ char *reply, *tmp;
++ int nr;
++
++ if (!tell_seens)
++ return;
++ ll = NULL;
++ l = requests;
++ reply = NULL;
++ while (l) {
++ if (!strcasecmp(l->nick, nick)) {
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
++ glob_nick = nick;
++ nr = count_seenreq(l->by);
++ if (nr == 1) {
++ glob_seenrequest = l;
++ dprintf(DP_HELP, "NOTICE %s :%s\n", l->nick, SLONELOOK);
++ } else {
++ sortrequests(l);
++ glob_seenrequest = l;
++ glob_seenrequests = nr;
++ tmp = SLMORELOOKS;
++ reply = nmalloc(strlen(tmp) + 1);
++ strcpy(reply, tmp);
++ nr = 0;
++ for (b = l->by; b; b = b->next) {
++ nr++;
++ reply = nrealloc(reply, strlen(reply) + ((nr == 1) ? 1 : 2) + strlen(b->who) + 1);
++ sprintf(reply, "%s%s%s", reply, (nr == 1) ? " " : ", ", b->who);
++ }
++ tmp = SLLASTLOOK;
++ reply = nrealloc(reply, strlen(reply) + 2 + strlen(tmp) + 1);
++ sprintf(reply, "%s. %s", reply, tmp);
++ dprintf(DP_HELP, "NOTICE %s :%s\n", l->nick, reply);
++ nfree(reply);
++ }
++ b = l->by;
++ while (b) {
++ bb = b->next;
++ nfree(b->who);
++ nfree(b->host);
++ nfree(b->chan);
++ nfree(b);
++ b = bb;
++ }
++ nfree(l->nick);
++ if (ll)
++ ll->next = l->next;
++ else
++ requests = l->next;
++ nfree(l);
++ if (ll)
++ l = ll->next;
++ else
++ l = requests;
++ } else {
++ ll = l;
++ l = l->next;
++ }
++ }
++}
++
++static void start_seentime_calc()
++{
++ struct timeval t;
++
++ gettimeofday(&t, NULL);
++ glob_presearch = (float) t.tv_sec + (((float) t.tv_usec) / 1000000);
++}
++
++static void end_seentime_calc()
++{
++ struct timeval t;
++
++ gettimeofday(&t, NULL);
++ glob_aftersearch = (float) t.tv_sec + (((float) t.tv_usec) / 1000000);
++ glob_total_searchtime += glob_aftersearch - glob_presearch;
++ glob_total_queries++;
++}
+diff -Nur src/mod/gseen.mod/generic_binary_tree.c src/mod/gseen.mod/generic_binary_tree.c
+--- src/mod/gseen.mod/generic_binary_tree.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/generic_binary_tree.c 2002-10-26 13:17:51.000000000 +0200
+@@ -0,0 +1,311 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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 GENERIC_BINARY_TREE 1
++
++struct generic_binary_tree {
++ void *root;
++ int (*comparedata) (void *data1, void *data2);
++ int (*expmemdata) (void *data);
++ void (*freedata) (void *data);
++};
++
++struct generic_binary_tree_node {
++ void *data;
++ void *left;
++ void *right;
++};
++
++static void btree_add(struct generic_binary_tree *, void *);
++static int btree_expmem(struct generic_binary_tree *);
++static int btree_recursive_expmem(struct generic_binary_tree *, struct generic_binary_tree_node *);
++static void *btree_get(struct generic_binary_tree *, void *t);
++static void btree_freetree(struct generic_binary_tree *);
++static void btree_recursive_free(struct generic_binary_tree *,
++ struct generic_binary_tree_node *);
++static void btree_getall(struct generic_binary_tree *, void (*) (void *));
++static void btree_recursive_getall(struct generic_binary_tree_node *,
++ void (*) (void *));
++static void btree_getall_expanded(struct generic_binary_tree *tree, void (*) (void *));
++static void btree_recursive_getall_expanded(struct generic_binary_tree_node *,
++ void (*) (void *));
++static void btree_remove(struct generic_binary_tree *, void *);
++
++static void btree_add(struct generic_binary_tree *tree, void *data)
++{
++ struct generic_binary_tree_node *node, *lastnode;
++ int cmp, lastcmp;
++
++ Assert(tree);
++ Assert(data);
++ cmp = lastcmp = 0;
++ node = tree->root;
++ lastnode = NULL;
++ while (node) {
++ cmp = tree->comparedata(node->data, data);
++ if (!cmp) {
++ // item is identical -> free old data and insert new
++ tree->freedata(node->data);
++ node->data = data;
++ return;
++ }
++ lastnode = node;
++ lastcmp = cmp;
++ if (cmp < 0)
++ node = node->left;
++ else
++ node = node->right;
++ }
++ node = nmalloc(sizeof(struct generic_binary_tree_node));
++ node->left = NULL;
++ node->right = NULL;
++ node->data = data;
++ if (!lastnode)
++ tree->root = node;
++ else {
++ Assert(lastcmp);
++ if (lastcmp < 0) {
++ Assert(!lastnode->left);
++ lastnode->left = node;
++ } else {
++ Assert(!lastnode->right);
++ lastnode->right = node;
++ }
++ }
++}
++
++static int btree_expmem(struct generic_binary_tree *tree)
++{
++ int size = 0;
++
++ Assert(tree);
++ size += btree_recursive_expmem(tree, tree->root);
++ return size;
++}
++
++static int btree_recursive_expmem(struct generic_binary_tree *tree, struct generic_binary_tree_node *node)
++{
++ int size = 0;
++
++ if (!node)
++ return 0;
++ size += sizeof(struct generic_binary_tree_node);
++ size += tree->expmemdata(node->data);
++ size += btree_recursive_expmem(tree, node->left);
++ size += btree_recursive_expmem(tree, node->right);
++ return size;
++}
++
++static void *btree_get(struct generic_binary_tree *tree, void *what)
++{
++ struct generic_binary_tree_node *node;
++ int cmp;
++
++ node = tree->root;
++ while (node) {
++ cmp = tree->comparedata(node->data, what);
++ if (!cmp)
++ return node->data;
++ if (cmp < 0)
++ node = node->left;
++ else
++ node = node->right;
++ }
++ return NULL;
++}
++
++static void btree_freetree(struct generic_binary_tree *tree)
++{
++ btree_recursive_free(tree, tree->root);
++}
++
++static void btree_recursive_free(struct generic_binary_tree *tree,
++ struct generic_binary_tree_node *node)
++{
++ if (!node)
++ return;
++ btree_recursive_free(tree, node->left);
++ btree_recursive_free(tree, node->right);
++ tree->freedata(node->data);
++ nfree(node);
++}
++
++/* btree_getall():
++ * calls the specified function for each item in the tree.
++ * NOTE: getall() calls the proc _before_ it proceeds into recursion. This way,
++ * one can savely store the tree into a file without mixing up its form.
++ * But if you delete an item from the called prcedure, this function
++ * WILL crash. Use btree_getall() expanded instead.
++ */
++static void btree_getall(struct generic_binary_tree *tree, void (*func) (void *))
++{
++ Assert(tree);
++ btree_recursive_getall(tree->root, func);
++}
++
++static void btree_recursive_getall(struct generic_binary_tree_node *node,
++ void (*func) (void *))
++{
++ if (!node)
++ return;
++ // first call the function, then proceed into recursion
++ // this way, the tree keeps in form if its saved to a file, for example
++ Assert(func);
++ func(node->data);
++
++ btree_recursive_getall(node->left, func);
++ btree_recursive_getall(node->right, func);
++}
++
++/* btree_getall_expanded():
++ * the same as btree_getall(), but calls the function after the greatest level of recursion
++ * has been reached. The node-pointers won't be accessed anymore when the first function
++ * gets called. You can savely use this to free items.
++ */
++static void btree_getall_expanded(struct generic_binary_tree *tree, void (*func) (void *))
++{
++ Assert(tree);
++ btree_recursive_getall_expanded(tree->root, func);
++}
++
++static void btree_recursive_getall_expanded(struct generic_binary_tree_node *node,
++ void (*func) (void *))
++{
++ if (!node)
++ return;
++ btree_recursive_getall_expanded(node->left, func);
++ btree_recursive_getall_expanded(node->right, func);
++
++ Assert(func);
++ func(node->data);
++}
++
++static void btree_remove(struct generic_binary_tree *tree, void *data)
++{
++ struct generic_binary_tree_node *node, *last, *largenode, *lastlarge;
++ int ret, lastret;
++
++ Assert(tree);
++ Assert(data);
++ last = NULL;
++ lastret = 0;
++ node = tree->root;
++ while (node) {
++ ret = tree->comparedata(node->data, data);
++ if (ret == 0)
++ break;
++ last = node;
++ lastret = ret;
++ if (ret < 0)
++ node = node->left;
++ else
++ node = node->right;
++ }
++ if (!node) // oops, item not found
++ return;
++ if (!node->left && !node->right) {
++ // *freu* no sub-branches! We can easily delete this item.
++ if (last) {
++ if (lastret < 0)
++ last->left = NULL;
++ else
++ last->right = NULL;
++ } else
++ tree->root = NULL;
++ } else if (!node->left) {
++ // also pretty easy. Just connect the child to the parent.
++ if (last) {
++ if (lastret < 0)
++ last->left = node->right;
++ else
++ last->right = node->right;
++ } else
++ tree->root = node->right;
++ } else if (!node->right) {
++ // same as above, but mirrored
++ if (last) {
++ if (lastret < 0)
++ last->left = node->left;
++ else
++ last->right = node->left;
++ } else
++ tree->root = node->left;
++ } else {
++ // aaargh... two sub-trees! The world is not fair... *sigh*
++ debug0("argl... worst case, two subtrees. :( Let's pray...");
++ // now we take the largest item from the left subtree and replace the
++ // doomed node with it.
++ // since it is the largest val, the tree remains valid and doesn't
++ // get deformed too much.
++
++ // at first, we have to find this node and cut it from the tree
++ largenode = node->left;
++ lastlarge = NULL;
++ while (largenode && largenode->right) {
++ lastlarge = largenode;
++ largenode = largenode->right;
++ }
++
++ // only set largenode->left to node->left if largenode exists.
++ // otherwise node->left points to largenode, which would result
++ // in a nice short-circuit
++ // If it does not exist, just leave largenode->left as it is because we just
++ // move largenode one level up, so it can keep its left subtree.
++ if (lastlarge) {
++ lastlarge->right = largenode->left;
++ largenode->left = node->left;
++ }
++
++ // now connect node's subtrees to it
++ largenode->right = node->right;
++
++ // and finally replace node with largenode
++ if (last) {
++ if (lastret < 0)
++ last->left = largenode;
++ else
++ last->right = largenode;
++ } else
++ tree->root = largenode;
++ }
++ // finally kill the node... we shouldn't need it anymore
++ tree->freedata(node->data);
++ nfree(node);
++ node = NULL;
++}
++
++#ifdef BTREE_WITHOPTIMIZE
++static void btree_optimize(struct generic_binary_tree *tree,
++ struct generic_binary_tree_node *node,
++ struct generic_binary_tree_node *last,
++ int limit)
++{
++/* int leftdepth, rightdepth;
++
++ if (!node)
++ return;
++ btree_optimize(tree, node->left, node, last, limit);
++ btree_optimize(tree, node->right, node, last, limit);
++ leftdepth = btree_depth(node->left);
++ rightdepth = btree_depth(node->right);
++ if ((leftdepth - rightdepth) > limit) {
++
++ }
++*/
++}
++#endif
+diff -Nur src/mod/gseen.mod/global_vars.c src/mod/gseen.mod/global_vars.c
+--- src/mod/gseen.mod/global_vars.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/global_vars.c 2002-10-26 13:18:09.000000000 +0200
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++static char *glob_query, *glob_laston, *glob_otherchan, *glob_othernick;
++static char *glob_remotebot, *glob_nick;
++static struct slang_header *glob_slang;
++static seendat *glob_seendat;
++static seenreq *glob_seenrequest;
++static int glob_seenrequests, glob_totalnicks, glob_totalbytes;
++
++static void reset_global_vars()
++{
++ glob_query = glob_laston = glob_otherchan = glob_othernick = NULL;
++ glob_remotebot = glob_nick = NULL;
++ glob_seendat = NULL;
++ glob_slang = NULL;
++ glob_seenrequest = NULL;
++ glob_seenrequests = glob_totalnicks = glob_totalbytes = 0;
++}
+diff -Nur src/mod/gseen.mod/gseen.c src/mod/gseen.mod/gseen.c
+--- src/mod/gseen.mod/gseen.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/gseen.c 2002-10-26 14:24:48.000000000 +0200
+@@ -0,0 +1,328 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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 MAKING_GSEEN
++#define MODULE_NAME "gseen"
++#define MODULE_VERSION "1.1.1 dev3"
++#define MODULE_NUMVERSION 10100
++#include "../module.h"
++#include "../irc.mod/irc.h"
++#include "../server.mod/server.h"
++#include "../channels.mod/channels.h"
++#include <stdlib.h>
++#include <sys/stat.h>
++#include <time.h> /* for time_t */
++
++#undef global
++static Function *global = NULL, *irc_funcs = NULL, *server_funcs = NULL, *channels_funcs = NULL;
++
++#ifndef EGG_IS_MIN_VER
++#define EGG_IS_MIN_VER(ver) ((ver) <= 10400)
++#endif
++
++#ifndef EGG_IS_MAX_VER
++#define EGG_IS_MAX_VER(ver) ((ver) >= 10400)
++#endif
++
++#ifndef Context
++#define Context context
++#endif
++
++#ifndef findchan_by_dname
++#define findchan_by_dname findchan
++#endif
++
++#include "gseen.h"
++#include "seenlang.h"
++
++static struct slang_header *coreslangs = NULL;
++static gseenres *results = NULL;
++static seenreq *requests = NULL;
++static ignoredword *ignoredwords = NULL;
++static char *bnsnick = NULL;
++static char *bnschan = NULL;
++static char *seen_reply = NULL;
++static char *temp_wildmatch_host;
++static int numresults = 0;
++static double glob_presearch, glob_aftersearch;
++int numseens, glob_total_queries;
++double glob_total_searchtime;
++
++static char gseenfile[121] = "gseen.dat";
++static char no_pub[121];
++static char quiet_seen[121];
++static char quiet_ai_seen[121];
++static char no_log[121];
++static char ignore_words[1024];
++static char default_slang[21] = "eng";
++static int gseen_numversion = MODULE_NUMVERSION;
++static int save_seens = 60;
++static int save_seens_temp = 1;
++static int expire_seens = 60;
++static int maxseen_thr = 0;
++static int maxseen_time = 0;
++static int seenflood_thr = 0;
++static time_t seenflood_time = 0;
++static int use_handles = 0;
++static int tell_seens = 1;
++static int botnet_seen = 1;
++int fuzzy_search = 1; // search for the same user under a differnt nick
++static int wildcard_search = 1;// allow wildcard seaching? ("*!*@*.isp.de")
++static int max_matches = 500; // break if there are more than X matches
++static int hide_secret_chans = 1; // #chan (+secret) => [secret]
++static int seen_nick_len = 32;
++
++#include "global_vars.c"
++#define SLANG_NOTYPES 1
++#define SLANG_NOFACTS 1
++#define SLANG_NOGETALL 1
++#define SLANG_NOVALIDATE 1
++#include "slang.c"
++#include "slang_gseen_commands.c"
++#include "generic_binary_tree.c"
++#include "seentree.c"
++#include "datahandling.c"
++#include "sensors.c"
++#include "do_seen.c"
++#include "gseencmds.c"
++#include "ai.c"
++#include "misc.c"
++#include "tclcmds.c"
++
++static int gseen_expmem()
++{
++ int size = 0;
++
++ size += seentree_expmem();
++ size += expmem_seenresults();
++ size += expmem_seenreq();
++ size += expmem_ignoredwords();
++ size += slang_expmem(coreslangs);
++ size += slang_glob_expmem();
++ size += slang_chanlang_expmem(chanlangs);
++ if (bnsnick)
++ size += strlen(bnsnick) + 1;
++ if (bnschan)
++ size += strlen(bnschan) + 1;
++ if (seen_reply) {
++ size += strlen(seen_reply) + 1;
++ }
++ return size;
++}
++
++static void free_gseen()
++{
++ seentree_free();
++ slang_free(coreslangs);
++ slang_chanlang_free(chanlangs);
++ if (seen_reply)
++ nfree(seen_reply);
++ return;
++}
++
++/* a report on the module status */
++static void gseen_report(int idx, int details)
++{
++ int size = 0;
++
++ Context;
++ if (details) {
++ size = gseen_expmem();
++ dprintf(idx, " using %d bytes\n", size);
++ }
++}
++
++static void gseen_minutely ()
++{
++ if (save_seens_temp >= save_seens) {
++ write_seens();
++ save_seens_temp = 1;
++ } else
++ save_seens_temp++;
++}
++
++static void gseen_daily ()
++{
++ Context;
++ purge_seens();
++}
++
++static tcl_strings my_tcl_strings[] =
++{
++ {"gseenfile", gseenfile, 121, 0},
++ {"ai-seen-ignore", ignore_words, 1024, 0},
++ {"no-pub-seens", no_pub, 121, 0},
++ {"quiet-seens", quiet_seen, 121, 0},
++ {"quiet-ai-seens", quiet_ai_seen, 121, 0},
++ {"no-log", no_log, 121, 0},
++ {"no-seendata", no_log, 121, 0},
++ {"default-slang", default_slang, 20, 0},
++ {0, 0, 0, 0}
++};
++
++static tcl_ints my_tcl_ints[] =
++{
++ {"save-seens", &save_seens, 0},
++ {"expire-seens", &expire_seens, 0},
++ {"use-handles", &use_handles, 0},
++ {"tell-seens", &tell_seens, 0},
++ {"botnet-seens", &botnet_seen, 0},
++ {"max-matches", &max_matches, 0},
++ {"fuzzy-search", &fuzzy_search, 0},
++ {"wildcard-search", &wildcard_search, 0},
++ {"hide-secret-chans", &hide_secret_chans, 0},
++ {"seen-nick-len", &seen_nick_len, 0},
++ {0, 0, 0}
++};
++
++static tcl_coups my_tcl_coups[] =
++{
++ {"max-seens", &maxseen_thr, &maxseen_time},
++ {0, 0, 0},
++};
++
++static char *gseen_close()
++{
++ Context;
++ write_seens();
++ slang_glob_free();
++ free_gseen();
++ free_seenreq();
++ free_seenresults();
++ free_ignoredwords();
++ if (bnsnick)
++ nfree(bnsnick);
++ if (bnschan)
++ nfree(bnschan);
++ rem_tcl_strings(my_tcl_strings);
++ rem_tcl_ints(my_tcl_ints);
++ rem_tcl_coups(my_tcl_coups);
++ rem_tcl_commands(mytcls);
++ rem_tcl_commands(gseentcls);
++ rem_tcl_commands(seendebugtcls);
++ rem_tcl_commands(gseentcls);
++ rem_builtins(H_dcc, mydcc);
++ rem_builtins(H_join, seen_join);
++ rem_builtins(H_kick, seen_kick);
++ rem_builtins(H_nick, seen_nick);
++ rem_builtins(H_part, seen_part);
++ rem_builtins(H_sign, seen_sign);
++ rem_builtins(H_splt, seen_splt);
++ rem_builtins(H_rejn, seen_rejn);
++ rem_builtins(H_pub, seen_pub);
++ rem_builtins(H_msg, seen_msg);
++ rem_builtins(H_bot, seen_bot);
++ del_hook(HOOK_MINUTELY, (Function) gseen_minutely);
++ del_hook(HOOK_DAILY, (Function) gseen_daily);
++ module_undepend(MODULE_NAME);
++ return NULL;
++}
++
++char *gseen_start();
++
++static Function gseen_table[] =
++{
++ (Function) gseen_start,
++ (Function) gseen_close,
++ (Function) gseen_expmem,
++ (Function) gseen_report,
++ /* 4 - 7 */
++ (Function) findseens,
++ (Function) free_seenresults,
++ (Function) gseen_duration,
++ (Function) & glob_seendat,
++ (Function) & numresults,
++ (Function) & fuzzy_search,
++ (Function) & numseens,
++ (Function) & glob_total_queries,
++ (Function) & glob_total_searchtime,
++ (Function) & gseen_numversion,
++};
++
++char *gseen_start(Function * global_funcs)
++{
++ global = global_funcs;
++ Context;
++ module_register(MODULE_NAME, gseen_table, 1, 1);
++ if (!(irc_funcs = module_depend(MODULE_NAME, "irc", 1, 0)))
++ return "You need the irc module to use the gseen module.";
++ if (!(server_funcs = module_depend(MODULE_NAME, "server", 1, 0)))
++ return "You need the server module to use the gseen module.";
++ if (!(channels_funcs = module_depend(MODULE_NAME, "channels", 1, 0)))
++ return "You need the channels module to use the gseen module.";
++ if (!module_depend(MODULE_NAME, "eggdrop", 107, 0)) {
++ if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
++ if (!module_depend(MODULE_NAME, "eggdrop", 105, 0)) {
++ if (!module_depend(MODULE_NAME, "eggdrop", 104, 0)) {
++ module_undepend(MODULE_NAME);
++ return "This module requires eggdrop1.4.0 or later";
++ }
++ }
++ }
++ }
++ chanlangs = NULL;
++ coreslangs = NULL;
++ slang_glob_init();
++
++ results = NULL;
++ requests = NULL;
++ ignoredwords = NULL;
++ bnsnick = NULL;
++ bnschan = NULL;
++ seen_reply = NULL;
++
++ numresults = 0;
++ numseens = 0;
++ glob_total_queries = 0;
++ glob_total_searchtime = 0.0;
++ ignore_words[0] = 0;
++ no_pub[0] = 0;
++ quiet_seen[0] = 0;
++ no_log[0] = 0;
++ seentree_init();
++ add_tcl_strings(my_tcl_strings);
++ add_tcl_ints(my_tcl_ints);
++ add_tcl_coups(my_tcl_coups);
++ add_tcl_commands(mytcls);
++ add_tcl_commands(seendebugtcls);
++ add_tcl_commands(gseentcls);
++ add_builtins(H_dcc, mydcc);
++ add_builtins(H_join, seen_join);
++ add_builtins(H_kick, seen_kick);
++ add_builtins(H_nick, seen_nick);
++ add_builtins(H_part, seen_part);
++ add_builtins(H_sign, seen_sign);
++ add_builtins(H_sign, seen_sign);
++ add_builtins(H_splt, seen_splt);
++ add_builtins(H_rejn, seen_rejn);
++ add_builtins(H_pub, seen_pub);
++ add_builtins(H_msg, seen_msg);
++ add_builtins(H_bot, seen_bot);
++ read_seens();
++ add_hook(HOOK_MINUTELY, (Function) gseen_minutely);
++ add_hook(HOOK_DAILY, (Function) gseen_daily);
++#if EGG_IS_MIN_VER(10503)
++ initudef(1, "noseendata", 1);
++ initudef(1, "quietseens", 1);
++ initudef(1, "quietaiseens", 1);
++ initudef(1, "nopubseens", 1);
++#endif
++ glob_slang_cmd_list = slang_commands_list_add(glob_slang_cmd_list, slang_text_gseen_command_table);
++ putlog(LOG_MISC, "*", "gseen.mod v%s loaded.", MODULE_VERSION);
++ return NULL;
++}
+diff -Nur src/mod/gseen.mod/gseen.conf src/mod/gseen.mod/gseen.conf
+--- src/mod/gseen.mod/gseen.conf 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/gseen.conf 2002-10-26 13:17:54.000000000 +0200
+@@ -0,0 +1,147 @@
++
++######
++#####
++### General Settings
++#####
++######
++
++# the file where the seen data will be backuped.
++# WARNING: set this _before_ the module is loaded.
++set gseenfile "gseen.dat"
++
++# now load the module
++loadmodule gseen
++
++# load the English language file
++loadseenslang "en" "English" language/gseen.en.lang
++
++# load the German language file
++loadseenslang "de" "Deutsch" language/gseen.de.lang
++
++# set the default language to english...
++set default-slang "en"
++
++# ... but let #xwp use the german langfile
++setchanseenlang #xwp "de"
++
++# the char that marks public commands (!seen, etc...)
++# "" is a valid option
++set cmdchar "!"
++
++# delete data sets that are older than x days
++set expire-seens 60
++
++# only answer x seen requests in y seconds to prevent flooding
++set max-seens 7:60
++
++# tell users if someone was !seen'ing for them
++set tell-seens 1
++
++# check if the user was online under a different nick
++set fuzzy-search 1
++
++# allow user to include wildcards in the search?
++set wildcard-search 1
++
++# break search if there are more than x matches
++set max-matches 250
++
++# forward a request to other bots, if a !seen returned no result?
++set botnet-seens 1
++
++# store channels, which are +secret on the bot as [secret]?
++set hide-secret-chans 1
++
++# backup the seen data every x minutes
++set save-seens 60
++
++######
++#####
++### AI Settings
++#####
++######
++
++# this setting configures on which sentences your bot should
++# attempt to do an ai-seen. Each of them is a simple wildcard
++# mask. Set this to "" if you want to deactivate ai-seens or
++# create more precise masks if the bots reacts too often.
++set ai-seen-binds {
++ "${nick}*seen*"
++ "${botnet-nick}*seen*"
++ "${nick}*gesehen*"
++ "${botnet-nick}*gesehen*"
++}
++
++# this is just the same as above, but if triggered it will
++# not do an ai-seen, but display its seen-stats.
++set ai-seenstats-binds {
++ "${nick}*seenstats*"
++ "${botnet-nick}*seenstats*"
++}
++
++# when doing an AI seen, ignore the following words (otherwise
++# the bot might give weird answers like "<bot> nick, bot was last seen..." :)
++set ai-seen-ignore "$nick ${botnet-nick} seen"
++
++######
++#####
++### special stuff (can be ignored in most cases)
++#####
++######
++
++# if the user is known by the bot, log their handle instead of the nick
++# (not recommended, might cause confusion by the users)
++set use-handles 0
++
++######
++#####
++### outdated settings (only important for eggdropv1.4 users)
++#####
++######
++
++# channels where you do not want your bot to reply to public queries
++set no-pub-seens ""
++
++# channels where you want your bot to send replies via notice to the user and
++# not to the channel
++set quiet-seens ""
++
++# same as quiet-seens but for AI seen
++set quiet-ai-seens ""
++
++# channels where you do not want your bot to log seen data
++set no-seendata ""
++
++
++###############################################################################
++# end of configuration
++# just ignore everything below ^_^
++###############################################################################
++
++bind chjn - * *chjn:gseen
++bind chpt - * *chpt:gseen
++
++catch "unbind pub - !seen *pub:!seen"
++catch "unbind pub - !seennick *pub:!seennick"
++catch "unbind pub - !seenstats *pub:!seenstats"
++bind pub - ${cmdchar}seen *pub:!seen
++bind pub - ${cmdchar}seennick *pub:!seennick
++bind pub - ${cmdchar}seenstats *pub:!seenstats
++
++foreach bnd [binds pubm] {
++ if {([lindex $bnd 2] == "*pubm:seen") || ([lindex $bnd 2] == "*pub:!seenstats")} {
++ unbind [lindex $bnd 0] [lindex $bnd 1] [lindex $bnd 2] [lindex $bnd 4]
++ }
++}
++
++if {${ai-seen-binds} != ""} {
++ foreach mask ${ai-seen-binds} {
++ bind pubm -|- "% [subst $mask]" *pubm:seen
++ }
++}
++
++if {${ai-seenstats-binds} != ""} {
++ foreach mask ${ai-seenstats-binds} {
++ bind pubm -|- "% [subst $mask]" *pub:!seenstats
++ }
++}
+diff -Nur src/mod/gseen.mod/language/gseen.de.lang src/mod/gseen.mod/language/gseen.de.lang
+--- src/mod/gseen.mod/language/gseen.de.lang 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/language/gseen.de.lang 2002-10-26 13:18:12.000000000 +0200
+@@ -0,0 +1,131 @@
++#####################################################################
++#
++# Deutsche Sprachdatei für GSeen.Mod v1.1.0
++#
++# Der Text in dieser Datei kann nach belieben verändert werden. Du
++# kannst Tags hinzufügen oder entfernen, wie es Dir gefällt. Die Tags
++# müssen nicht in einer bestimmten Reihenfolge oder Anzahl vorkommen.
++#
++# Wenn Du mehr als eine Zeile pro ID angibst, dann wird bei der
++# Antwort per Zufall eine daraus ausgewählt. (das funktioniert nicht
++# bei den Zeiteinheiten)
++#
++# Falls Du denkst, daß hier noch ein paar wichtige Tags fehlen, dann
++# schick mir einfach eine email. Vielleicht füge ich sie dann in der
++# nächsten Version hinzu.
++#
++# Eine komplette Liste der Verfügbaren Tags befindet sich am Ende von
++# slang_gseen_commands.c (leider ohne Erklährungen)
++#
++#####################################################################
++
++#
++## Zeiteinheiten
++#
++# jeweils in Singular und Plural
++#
++D 0 Jahr
++D 1 Jahre
++D 2 Woche
++D 3 Wochen
++D 4 Tag
++D 5 Tage
++D 6 Stunde
++D 7 Stunden
++D 8 Minute
++D 9 Minuten
++D 10 Sekunde
++D 11 Sekunden
++# falls ein üngültiger Zeitwert angegeben war, dann wird dieser Text ausgegeben:
++D 12 einiger Zeit
++
++
++#
++## Präfixe
++#
++# Dieses Fragment wird jeweils vor eine Antwort gesetzt. Dadurch
++# ist beispielsweise bei öffentlichen Anfragen ersichtlich, für
++# wen die Antwort ist.
++# Achtung: Die Nummer muss auf jeden Fall definiert werden. Sie muss
++# zwar keinen Text beinhalten, aber wenn sie nicht vorhanden
++# ist, dann gibt es eine Fehlermeldung
++
++# für Antworten, die in den Channel geschrieben werden:
++10 <?nick/?>,
++# für Antworten, die per NOTICE an den User geschickt werden:
++11
++# für Antworten auf Anfragen, die per "/msg <bot> seen" erfolgt sind:
++12
++# und für Antworten auf der Partyline:
++13
++
++#
++## Fehlermeldungen
++#
++54 weißt Du was ein Parameter ist? ^_^
++54 ich würde Dir ja gerne helfen, aber solange Du nicht sagst, nach wem Du suchst, kann ich nicht viel tun.
++54 meinst Du nicht, es wäre geschickter zu sagen, nach wem Du überhaupt suchst?
++54 42.
++55 sehe ich etwa wie ein Spiegel aus? ^_^
++55 Spieglein, Spieglein an der Wand...
++55 leidest Du etwa unter multiplen Persönlichkeiten? *eg*
++56 also wenn Du <?query/?> jetzt hier nicht sehen kannst, dann brauchst Du sicherlich eine neue Brille ^_^
++56 ich muss mir unbedingt mal die Tarnkappe von <?query/?> ausleihen. Scheint ja prima zu funktioneren.
++56 schau Dir bitte nochmal ganz genau an, wer grade alles im Channel ist.
++57 Tut mir leid, aber Wildcards ('?', oder '*') sind bei der Suche nicht erlaubt.
++58 Öhm... naja... etwas arg lang, dieser Nick... :)
++
++#
++## Kein Ergebnis
++#
++65 Ich kann mich nicht daran erinnern, <?query/?> gesehen zu haben...
++65 <?query/?>? Hmm... ich bin mir nicht sicher... vielleicht... eventuell... nein, kenne ich nicht.
++65 der Name sagt mir nichts. Hast Du Dich vielleicht vertippt?
++66 Ich hab' <?query/?> seit <?laston/?> nicht mehr gesehen.
++67 Sorry, aber zu deiner Anfrage passt nichts in meiner Datenbank :(
++68 Autschi, das gab viel zu viele Ergebnisse. Bitte formuliere deine Suche etwas genauer.
++
++73 <?query/?> ist grade unter dem Nick "<?othernick/?>" in diesem Channel zu finden.
++74 <?query/?> ist gerade in <?otherchan/?>.
++75 Deine Anfrage führte zu genau einem Ergebnis:
++76 Immerhin <?numresults/?> Treffer ergab deine Anfrage:
++77 Wow, auf deine Anfrage passen sogar <?numresults/?> Einträge in meiner Datenbank! Dies sind die 5 aktuellsten:
++
++#
++## falls ein anderer Bot etwas gefunden hat:
++#
++85 <?remotebot/?> sagt:
++
++#
++## die eigentliche Information
++#
++101 Ich habe <?snick/?> (<?shost/?>) zuletzt <?schan/?> vor <?swhen/?> betreten sehen (<?stime/?>). <?snick/?> ist noch immer da.
++121 Ich habe <?snick/?> (<?shost/?>) zuletzt <?schan/?> vor <?swhen/?> betreten sehen (<?stime/?>), aber <?snick/?> verschwand mysteriöserweise.
++102 Ich habe <?snick/?> (<?shost/?>) zuletzt <?schan/?> vor <?swhen/?> nach <?spent/?> verchatteter Zeit verlassen sehen (<?stime/?>)
++103 Ich habe <?snick/?> (<?shost/?>) zuletzt in <?schan/?> gesehen, als er/sie vor <?swhen/?> (<?stime/?>) nach <?spent/?> das IRC verließ ("<?smsg/?>").
++104 Zuletzt habe ich <?snick/?> (<?shost/?>) vor <?swhen/?> in <?schan/?> gesehen, den Nick zu <?snick2/?> wechselnd. <?snick2/?> ist noch immer dort.
++124 <?snick/?> (<?shost/?>) was last seen changing his/her nick to <?snick2/?> on <?schan/?> <?swhen/?> ago (<?stime/?>), but <?snick2/?> mysteriously dematerialized.
++105 Zuletzt habe ich <?snick/?> (<?shost/?>) vor <?swhen/?> in <?schan/?> gesehen, den Nick von <?snick2/?> wechselnd. <?snick/?> ist noch immer dort.
++125 <?snick/?> (<?shost/?>) was last seen changing his/her nick from <?snick2/?> on <?schan/?> <?swhen/?> ago (<?stime/?>), but <?snick/?> mysteriously dematerialized.
++106 Zuletzt habe ich <?snick/?> (<?shost/?>) gesehen, als er vor <?swhen/?> (<?stime/?>) von <?punisher/?> aus <?schan/?> gejagt wurde. (<?kickreason/?>)
++107 <?snick/?> (<?shost/?>) habe ich zuletzt vor <?swhen/?> gesehen, als er/sie von <?schan/?> aus in einem Netsplit verschwand.
++108 <?snick/?> (<?shost/?>) habe ich zuletzt vor <?swhen/?> gesehen, als er/sie nach einem Netsplit in <?schan/?> zurück kam. <?snick/?> ist noch immer dort.
++128 <?snick/?> (<?shost/?>) habe ich zuletzt vor <?swhen/?> gesehen, als er/sie nach einem Netsplit in <?schan/?> zurück kam. Allerdings konnte <?snick/?> dem Gott der Netsplits nicht endgültig entkommen und ist wieder verschollen...
++109 <?snick/?> was last seen joining the botnet channel <?schan/?> on <?bnbot/?> <?swhen/?> ago (<?stime/?>).
++129 <?snick/?> was last seen joining the partyline on <?bnbot/?> <?swhen/?> ago (<?stime/?>).
++110 <?snick/?> was last seen leaving the botnet channel <?schan/?> from <?bnbot/?> <?swhen/?> ago (<?stime/?>).
++130 <?snick/?> was last seen leaving the partyline from <?bnbot/?> <?swhen/?> ago (<?stime/?>).
++140 <?snick/?> (<?shost/?>) was last seen on <?schan/?> <?swhen/?> ago (<?stime/?>).
++
++#
++## Seen-Mitteilungen
++#
++170 <?rnick/?> (<?rhost/?>) scheint vor <?rwhen/?> (<?rtime/?>) in <?rchan/?> auf der Suche nach Dir gewesen zu sein.
++171 <?requests/?> Leute haben sich nach Dir erkundigt:
++172 Der/die letzte war <?rnick/?> (<?rhost/?>) in <?rchan/?> vor <?rwhen/?> (<?rtime/?>).
++
++#
++## Statistiken
++#
++180 Momentan sind <?totalnicks/?> Nicks in meiner Datenbank. Gesamter Speicherverbrauch: <?totalbytes/?> Bytes
++180 In meiner Datenbank befinden sich <?totalnicks/?> Nicks und verbrauchen <?totalbytes/?> Bytes Speicher.
+diff -Nur src/mod/gseen.mod/language/gseen.en.lang src/mod/gseen.mod/language/gseen.en.lang
+--- src/mod/gseen.mod/language/gseen.en.lang 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/language/gseen.en.lang 2002-10-26 13:18:13.000000000 +0200
+@@ -0,0 +1,131 @@
++#####################################################################
++#
++# Default English langfile for GSeen.Mod v1.1.0
++#
++# Just edit the text below to fit your needs. You can add or remove
++# any tag just like you want, they do not need to appear in a special
++# order (or number).
++#
++# If you enter more than one line per ID, then a random one will be
++# chosen for each reply. (this does not work for the time strings)
++#
++# If you think you need more tags, just email me and maybe I'll add
++# them in the next release.
++#
++# A complete list of available Tags can be found at the end of the
++# file slang_gseen_commands.c (unfortunately, it does not contain any
++# descriptions for the tags)
++#
++#####################################################################
++
++#
++## time string
++#
++# each time string in singular and plural
++#
++D 0 year
++D 1 years
++D 2 week
++D 3 weeks
++D 4 day
++D 5 days
++D 6 hour
++D 7 hours
++D 8 minute
++D 9 minutes
++D 10 second
++D 11 seconds
++# if an invalid time value was supplied, output the following string
++D 12 some time
++
++#
++## Prefixes
++#
++# These are the prefixes of the replies. By default, there's only
++# a prefix for public requests (so you know for whom the answer is),
++# but you can also define prefixes for other requests.
++
++# for replies in the channel:
++10 <?nick/?>,
++# for replies via notice:
++11
++# for replies via PRIVMSG
++12
++# for replies on the partyline
++13
++
++#
++## error messages
++#
++54 do you know what a parameter is?
++54 don't you think it would be more reasonable to say for whom you are searching?
++54 42.
++55 do I look like a mirror? ^_^
++55 mirror mirror on the wall...
++55 do you have a split personality? *eg*
++56 if you can't see <?query/?> here right now, you probably need new glasses. ^_^
++56 please look a bit closer at the memberlist of this channel.
++57 I'm sorry, but wildcards ('?' or '*') are not allowed in a search.
++58 Hum... don't you think this nick is a bit long? ^_^
++58 you know that the length of nicks is limited, don't you?
++
++#
++## no result
++#
++65 I don't remember seeing <?query/?>.
++65 <?query/?>? hmm... I'm trying to remember... maybe... I'm not sure... no. I don't remember <?query/?>.
++66 I haven't seen <?query/?> for <?laston/?>.
++67 I found no matches to your query.
++67 I'm sorry, but your search didn't return any results.
++68 Ouch, your search returned way too many matches. Please refine it.
++
++#
++## victim is online
++#
++73 <?query/?> is <?othernick/?>, who is on this channel right now.
++74 <?query/?> is on <?otherchan/?> right now.
++
++#
++## results found
++#
++75 I found one match to your query:
++76 I found <?numresults/?> matches to your query:
++77 I found <?numresults/?> matches to your query. These are the 5 most recent ones:
++
++#
++## results found by another bot in the botnet
++#
++85 <?remotebot/?> says:
++
++#
++## the core info
++#
++101 <?snick/?> (<?shost/?>) was last seen joining <?schan/?> <?swhen/?> ago (<?stime/?>). <?snick/?> is still there.
++121 <?snick/?> (<?shost/?>) was last seen joining <?schan/?> <?swhen/?> ago (<?stime/?>), but <?snick/?> mysteriously dematerialized.
++102 <?snick/?> (<?shost/?>) was last seen parting <?schan/?> <?swhen/?> ago (<?stime/?>), after spending <?spent/?> there.
++103 <?snick/?> (<?shost/?>) was last seen quitting <?schan/?> <?swhen/?> ago (<?stime/?>) stating "<?smsg/?>" after spending <?spent/?> there.
++104 <?snick/?> (<?shost/?>) was last seen changing his/her nick to <?snick2/?> on <?schan/?> <?swhen/?> ago (<?stime/?>). <?snick2/?> is still there.
++124 <?snick/?> (<?shost/?>) was last seen changing his/her nick to <?snick2/?> on <?schan/?> <?swhen/?> ago (<?stime/?>), but <?snick2/?> mysteriously dematerialized.
++105 <?snick/?> (<?shost/?>) was last seen changing his/her nick from <?snick2/?> on <?schan/?> <?swhen/?> ago (<?stime/?>). <?snick/?> is still there.
++125 <?snick/?> (<?shost/?>) was last seen changing his/her nick from <?snick2/?> on <?schan/?> <?swhen/?> ago (<?stime/?>), but <?snick/?> mysteriously dematerialized.
++106 <?snick/?> (<?shost/?>) was last seen being kicked from <?schan/?> by <?punisher/?> (<?kickreason/?>) <?swhen/?> ago (<?stime/?>), after spending <?spent/?> there.
++107 <?snick/?> (<?shost/?>) was last seen splitting from <?schan/?> <?swhen/?> ago (<?stime/?>), after spending <?spent/?> there.
++108 <?snick/?> (<?shost/?>) was last seen rejoining <?schan/?> from a netsplit <?swhen/?> ago (<?stime/?>) <?snick/?> is still there.
++128 <?snick/?> (<?shost/?>) was last seen rejoining <?schan/?> from a netsplit <?swhen/?> ago (<?stime/?>), but the god of netsplits didn't let him escape, so he's not here now.
++109 <?snick/?> was last seen joining the botnet channel <?schan/?> on <?bnbot/?> <?swhen/?> ago (<?stime/?>).
++129 <?snick/?> was last seen joining the partyline on <?bnbot/?> <?swhen/?> ago (<?stime/?>).
++110 <?snick/?> was last seen leaving the botnet channel <?schan/?> from <?bnbot/?> <?swhen/?> ago (<?stime/?>).
++130 <?snick/?> was last seen leaving the partyline from <?bnbot/?> <?swhen/?> ago (<?stime/?>).
++140 <?snick/?> (<?shost/?>) was last seen on <?schan/?> <?swhen/?> ago (<?stime/?>).
++
++#
++## seen notification
++#
++170 <?rnick/?> (<?rhost/?>) was looking for you on <?rchan/?> <?rwhen/?> ago (<?rtime/?>).
++171 There have been <?requests/?> users looking for you:
++172 The last one was <?rnick/?> (<?rhost/?>) on <?rchan/?> <?rwhen/?> ago (<?rtime/?>).
++
++#
++## seen stats
++#
++180 I'm currently tracking <?totalnicks/?> nicks using <?totalbytes/?> bytes.
+diff -Nur src/mod/gseen.mod/gseen.h src/mod/gseen.mod/gseen.h
+--- src/mod/gseen.mod/gseen.h 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/gseen.h 2002-10-26 13:17:55.000000000 +0200
+@@ -0,0 +1,157 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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 USE_MEMDEBUG 1 */
++
++#define SEEN_JOIN 1
++#define SEEN_PART 2
++#define SEEN_SIGN 3
++#define SEEN_NICK 4
++#define SEEN_NCKF 5
++#define SEEN_KICK 6
++#define SEEN_SPLT 7
++#define SEEN_REJN 8
++#define SEEN_CHPT 9
++#define SEEN_CHJN 10
++
++typedef struct gseen_data {
++ int type;
++ char *nick;
++ char *host;
++ char *chan;
++ char *msg;
++ time_t when;
++ int spent;
++} seendat;
++
++typedef struct gseen_result {
++ struct gseen_result *next;
++ seendat *seen;
++} gseenres;
++
++typedef struct gseen_requests {
++ struct gseen_requests *next;
++ char *who;
++ char *host;
++ char *chan;
++ time_t when;
++} seenreq_by;
++
++typedef struct gseen_request {
++ struct gseen_request *next;
++ char *nick;
++ struct gseen_requests *by;
++} seenreq;
++
++typedef struct gseen_ignorewords {
++ struct gseen_ignorewords *next;
++ char *word;
++} ignoredword;
++
++#ifdef MAKING_GSEEN
++static int gseen_expmem();
++static void free_gseen();
++static int get_spent(char *, char *);
++static void write_seens();
++static void read_seens();
++static char *do_seen(char *, char *, char *, char *, int);
++static void add_seenresult(seendat *);
++static int expmem_seenresults();
++static void free_seenresults();
++static void sortresults();
++static char *do_seennick(seendat *);
++static int onchan(char *, char *);
++static char *handonchan(char *, char *);
++static struct chanset_t *onanychan(char *);
++static struct chanset_t *handonanychan(char *);
++static char *do_seenstats();
++static void add_seenreq(char *, char *, char *, char *, time_t);
++static int expmem_seenreq();
++static void free_seenreq();
++static void sortrequests(seenreq *);
++static void report_seenreq(char *, char *);
++static int count_seenreq(seenreq_by *b);
++static int expmem_ignoredwords();
++static void free_ignoredwords();
++static void add_ignoredword(char *word);
++static int word_is_ignored(char *word);
++static void purge_seens();
++static int seenflood();
++static int secretchan(char *);
++static int nopub(char *);
++static int quietseen(char *);
++static int quietaiseens(char *);
++static int nolog(char *);
++static void start_seentime_calc();
++static void end_seentime_calc();
++#endif
++
++
++#ifdef MAKING_GSEEN
++
++// tree stuff
++static void maskstricthost(const char *, char *);
++#endif
++
++// interface for webseen
++#define WS_OK 0
++#define WS_NORESULT 1
++#define WS_NOPARAM 2
++#define WS_NOWILDCARDS 3
++#define WS_TOOLONGNICK 4
++#define WS_TOOMANYMATCHES 5
++#define WS_TOOLONGHOST 6
++
++#ifndef MAKING_GSEEN
++#define findseens ((gseenres *(*)(char *, int *, int))gseen_funcs[4])
++#define free_seenresults ((void (*)())gseen_funcs[5])
++#define gseen_duration ((char *(*)(int))gseen_funcs[6])
++#define numresults (*(int *)(gseen_funcs[12]))
++#define fuzzy_search (*(int *)(gseen_funcs[13]))
++#define numseens (*(int *)(gseen_funcs[15]))
++#define glob_total_queries (*(int *)(gseen_funcs[16]))
++#define glob_total_searchtime (*(double *)(gseen_funcs[17]))
++#define gseen_numversion (*(int *)(gseen_funcs[19]))
++#else
++static gseenres *findseens(char *, int *, int);
++static char *gseen_duration(int);
++#endif
++
++#ifdef MAKING_GSEEN
++
++#ifdef malloc
++#undef malloc
++#endif
++#ifdef free
++#undef free
++#endif
++#ifdef realloc
++#undef realloc
++#endif
++
++#ifdef USE_MEMDEBUG
++#define my_malloc nmalloc
++#define my_free nfree
++#define my_realloc nrealloc
++#else
++#define my_malloc malloc
++#define my_free free
++#define my_realloc realloc
++#endif
++
++#endif
+diff -Nur src/mod/gseen.mod/gseencmds.c src/mod/gseen.mod/gseencmds.c
+--- src/mod/gseen.mod/gseencmds.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/gseencmds.c 2002-10-26 13:17:56.000000000 +0200
+@@ -0,0 +1,420 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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 PREFIX_LENGTH 20
++
++static char reply_prefix[PREFIX_LENGTH + 1];
++#define set_prefix(x) strncpy(reply_prefix, x, PREFIX_LENGTH); \
++ reply_prefix[PREFIX_LENGTH] = 0;
++
++static int seenflood()
++{
++ if (!maxseen_thr || !maxseen_time)
++ return 0;
++ if ((now - seenflood_time) > maxseen_time) {
++ seenflood_time = now;
++ seenflood_thr = 0;
++ }
++ seenflood_thr++;
++ if (seenflood_thr > maxseen_thr)
++ return 1;
++ else
++ return 0;
++}
++
++static int nopub(char *chan)
++{
++ char buf[121], *b;
++
++ Context;
++ strncpy(buf, no_pub, 120);
++ buf[120] = 0;
++ b = buf;
++ while (b[0])
++ if (!strcasecmp(chan, newsplit(&b)))
++ return 1;
++#if EGG_IS_MIN_VER(10503)
++ if (ngetudef("nopubseens", chan))
++ return 1;
++#endif
++ return 0;
++}
++
++static int quietseen(char *chan)
++{
++ char buf[121], *b;
++
++ Context;
++ strncpy(buf, quiet_seen, 120);
++ buf[120] = 0;
++ b = buf;
++ while (b[0])
++ if (!strcasecmp(chan, newsplit(&b)))
++ return 1;
++#if EGG_IS_MIN_VER(10503)
++ if (ngetudef("quietseens", chan))
++ return 1;
++#endif
++ return 0;
++}
++
++static int cmd_seen(struct userrec *u, int idx, char *par)
++{
++ char *query;
++
++ Context;
++ if (seenflood())
++ return 0;
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, default_slang);
++ glob_nick = dcc[idx].nick;
++ query = newsplit(&par);
++ glob_query = query;
++ set_prefix(SLDCCPREFIX);
++ putlog(LOG_CMDS, "*", "#%s# seen %s", dcc[idx].nick, par);
++ dprintf(idx, "%s%s\n", reply_prefix, do_seen(query, dcc[idx].nick,
++ dcc[idx].host, "[partyline]", botnet_seen));
++ return 0;
++}
++
++static int cmd_seenstats(struct userrec *u, int idx, char *par)
++{
++ Context;
++ if (seenflood())
++ return 0;
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, default_slang);
++ glob_nick = dcc[idx].nick;
++ set_prefix(SLDCCPREFIX);
++ putlog(LOG_CMDS, "*", "#%s# seenstats", dcc[idx].nick);
++ dprintf(idx, "%s%s\n", reply_prefix, do_seenstats());
++ return 0;
++}
++
++static int cmd_purgeseens(struct userrec *u, int idx, char *par)
++{
++ Context;
++ purge_seens();
++ putlog(LOG_CMDS, "*", "#%s# purgeseens", dcc[idx].nick);
++ return 0;
++}
++
++static int pub_seen(char *nick, char *host, char *hand,
++ char *channel, char *text)
++{
++ char *dest;
++#if EGG_IS_MIN_VER(10500)
++ struct chanset_t *chan;
++#endif
++
++ Context;
++ if (seenflood() || nopub(channel))
++ return 0;
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
++ glob_nick = nick;
++ putlog(LOG_CMDS, "*", "<<%s>> !%s! seen %s", nick, hand, text);
++ if (quietseen(channel)) {
++ set_prefix(SLNOTPREFIX);
++ dprintf(DP_HELP, "NOTICE %s :%s%s\n", nick, reply_prefix,
++ do_seen(newsplit(&text), nick, host, channel, botnet_seen));
++ return 0;
++ }
++#if EGG_IS_MIN_VER(10500)
++ chan = findchan_by_dname(channel);
++ if (chan)
++ dest = chan->name;
++ else
++ dest = channel;
++#else
++ dest = channel;
++#endif
++ set_prefix(SLPUBPREFIX);
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s\n", dest, reply_prefix,
++ do_seen(newsplit(&text), nick, host, channel, botnet_seen));
++ return 0;
++}
++
++static int pub_seenstats(char *nick, char *host, char *hand,
++ char *channel, char *text)
++{
++ char *dest;
++#if EGG_IS_MIN_VER(10500)
++ struct chanset_t *chan;
++#endif
++
++ Context;
++ if (seenflood())
++ return 0;
++ if (nopub(channel))
++ return 0;
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
++ glob_nick = nick;
++ putlog(LOG_CMDS, "*", "<<%s>> !%s! seenstats", nick, hand);
++ if (quietseen(channel)) {
++ set_prefix(SLNOTPREFIX);
++ dprintf(DP_HELP, "NOTICE %s :%s%s\n", nick, reply_prefix, do_seenstats());
++ return 0;
++ }
++#if EGG_IS_MIN_VER(10500)
++ chan = findchan_by_dname(channel);
++ if (chan)
++ dest = chan->name;
++ else
++ dest = channel;
++#else
++ dest = channel;
++#endif
++ set_prefix(SLPUBPREFIX);
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s\n", dest, reply_prefix, do_seenstats());
++ return 1;
++}
++
++static int msg_seen(char *nick, char *uhost, struct userrec *u, char *text)
++{
++ Context;
++ if (seenflood())
++ return 0;
++ reset_global_vars();
++ glob_slang = slang_getbynick(coreslangs, nick);
++ glob_nick = nick;
++ putlog(LOG_CMDS, "*", "(%s!%s) !%s! seen %s", nick, uhost, u ? u->handle : "*", text);
++ set_prefix(SLMSGPREFIX);
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s\n", nick, reply_prefix,
++ do_seen(newsplit(&text), nick, uhost, "[/msg]", botnet_seen));
++ return 1;
++}
++
++static int pub_seennick(char *nick, char *host, char *hand,
++ char *channel, char *text)
++{
++ seendat *l;
++ char *dest;
++#if EGG_IS_MIN_VER(10500)
++ struct chanset_t *chan;
++#endif
++
++ Context;
++ if (seenflood())
++ return 0;
++ if (nopub(channel))
++ return 0;
++ putlog(LOG_CMDS, "*", "<<%s>> !%s! seennick %s", nick, hand, text);
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, channel));
++ glob_nick = nick;
++#if EGG_IS_MIN_VER(10500)
++ chan = findchan_by_dname(channel);
++ if (chan)
++ dest = chan->name;
++ else
++ dest = channel;
++#else
++ dest = channel;
++#endif
++ text = newsplit(&text);
++ l = findseen(text);
++ if (!l) {
++ glob_query = text;
++ if (quietseen(channel)) {
++ set_prefix(SLNOTPREFIX);
++ dprintf(DP_HELP, "NOTICE %s :%s%s\n", nick, reply_prefix, SLNOTSEEN);
++ } else {
++ set_prefix(SLPUBPREFIX);
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s\n", dest, reply_prefix, SLNOTSEEN);
++ }
++ return 0;
++ }
++ if (quietseen(channel)) {
++ set_prefix(SLNOTPREFIX);
++ dprintf(DP_HELP, "NOTICE %s :%s%s\n", nick, reply_prefix, do_seennick(l));
++ } else {
++ set_prefix(SLPUBPREFIX);
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s\n", dest, reply_prefix, do_seennick(l));
++ }
++ return 0;
++}
++
++static int msg_seennick(char *nick, char *uhost, struct userrec *u, char *text)
++{
++ seendat *l;
++
++ Context;
++ if (seenflood())
++ return 0;
++ putlog(LOG_CMDS, "*", "(%s!%s) !%s! seennick %s", nick, uhost, u ? u->handle : "*", text);
++ reset_global_vars();
++ glob_slang = slang_getbynick(coreslangs, nick);
++ glob_nick = nick;
++ set_prefix(SLMSGPREFIX);
++ text = newsplit(&text);
++ l = findseen(text);
++ if (!l) {
++ glob_query = text;
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s\n", nick, reply_prefix, SLNOTSEEN);
++ return 0;
++ }
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s\n", nick, reply_prefix, do_seennick(l));
++ return 0;
++}
++
++static int cmd_seennick(struct userrec *u, int idx, char *text)
++{
++ seendat *l;
++
++ Context;
++ if (seenflood())
++ return 0;
++ putlog(LOG_CMDS, "*", "#%s# seennick %s", dcc[idx].nick, text);
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, default_slang);
++ glob_nick = dcc[idx].nick;
++ set_prefix(SLMSGPREFIX);
++ text = newsplit(&text);
++ l = findseen(text);
++ if (!l) {
++ glob_query = text;
++ dprintf(idx, "%s%s\n", reply_prefix, SLNOTSEEN);
++ return 0;
++ }
++ dprintf(idx, "%s%s\n", reply_prefix, do_seennick(l));
++ return 0;
++}
++
++static int bot_gseen_req(char *bot, char *code, char *par)
++{
++ char *mask, *nick, *uhost, *chan, *reply;
++ char tosend[256];
++ int i;
++
++ Context;
++ if (seenflood())
++ return 0;
++ i = nextbot(bot);
++ if (i < 0) {
++ debug1("Couldn't answer botnet-seen-request from %s: no such bot", bot);
++ return 0;
++ }
++ mask = newsplit(&par);
++ nick = newsplit(&par);
++ uhost = newsplit(&par);
++ chan = newsplit(&par);
++ reset_global_vars();
++ glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, chan));
++ glob_nick = nick;
++ reply = do_seen(mask, nick, uhost, chan, -1);
++ if (!reply)
++ return 0;
++ if ((strlen(nick) + strlen(chan) + strlen(reply)) < 255) {
++ sprintf(tosend, "gseen_rep %s %s %s", nick, chan, reply);
++ botnet_send_zapf(i, botnetnick, bot, tosend);
++ }
++ return 0;
++}
++
++static int bot_gseen_rep(char *bot, char *code, char *par)
++{
++ char *nick, *chan, *reply;
++ int i;
++
++ Context;
++ if (seenflood())
++ return 0;
++ if (!bnsnick || !bnschan) {
++ if (bnsnick)
++ nfree(bnsnick);
++ if (bnschan)
++ nfree(bnschan);
++ bnsnick = bnschan = NULL;
++ return 0;
++ }
++ nick = newsplit(&par);
++ chan = newsplit(&par);
++ reset_global_vars();
++ glob_remotebot = bot;
++ glob_slang = slang_find(coreslangs, slang_chanlang_get(chanlangs, chan));
++ glob_nick = nick;
++ reply = par;
++ if (strcmp(nick, bnsnick) || strcmp(chan, bnschan))
++ return 0; /* unwanted reply */
++ if (findchan(chan)) {
++ if (nopub(chan)) {
++ nfree(bnsnick);
++ nfree(bnschan);
++ bnsnick = bnschan = NULL;
++ debug1("%s is nopub, bns-reply dropped", chan);
++ return 0;
++ }
++ if (quietseen(chan)) {
++ set_prefix(SLNOTPREFIX);
++ dprintf(DP_HELP, "NOTICE %s :%s%s%s\n", nick, reply_prefix, SLRBOTSAYS, reply);
++ } else {
++ set_prefix(SLPUBPREFIX);
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s%s\n", chan, reply_prefix, SLRBOTSAYS, reply);
++ }
++ } else if (!strcmp(chan, "[/msg]")) {
++ set_prefix(SLMSGPREFIX);
++ dprintf(DP_HELP, "PRIVMSG %s :%s%s%s\n", nick, reply_prefix, SLRBOTSAYS, reply);
++ } else if (!strcmp(chan, "[partyline]")) {
++ for (i = 0; i < dcc_total; i++) {
++ if ((!strcasecmp(nick, dcc[i].nick)) &&
++ (dcc[i].type->flags & DCT_SIMUL)) {
++ set_prefix(SLDCCPREFIX);
++ dprintf(i, "%s%s%s\n", reply_prefix, SLRBOTSAYS, reply);
++ break;
++ }
++ }
++ } else
++ debug1("Couldn't send received bns answer, no such chan %s", chan);
++ nfree(bnsnick);
++ nfree(bnschan);
++ bnsnick = bnschan = NULL;
++ return 0;
++}
++
++static cmd_t mydcc[] =
++{
++ {"seen", "-|-", cmd_seen, NULL},
++ {"seenstats", "-|-", cmd_seenstats, NULL},
++ {"purgeseens", "m", cmd_purgeseens, NULL},
++ {"seennick", "-|-", cmd_seennick, NULL},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_pub[] =
++{
++ {"!seen", "", pub_seen, 0},
++ {"!seenstats", "", pub_seenstats, 0},
++ {"!seennick", "", pub_seennick, 0},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_msg[] =
++{
++ {"seen", "", msg_seen, 0},
++ {"seennick", "", msg_seennick, 0},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_bot[] =
++{
++ {"gseen_req", "", bot_gseen_req, 0},
++ {"gseen_rep", "", bot_gseen_rep, 0},
++ {0, 0, 0, 0}
++};
+diff -Nur src/mod/gseen.mod/misc.c src/mod/gseen.mod/misc.c
+--- src/mod/gseen.mod/misc.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/misc.c 2002-10-26 13:17:57.000000000 +0200
+@@ -0,0 +1,116 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++/* maskstricthost():
++ * basically the same as maskhost() from src/misc.c, but _never_ stripts
++ * "~+-^=" off the host
++ * maskhost() version: * $Id: misc.c,v 1.30 2000/10/27 19:27:32 fabian Exp $
++ */
++static void maskstricthost(const char *s, char *nw)
++{
++ register const char *p, *q, *e, *f;
++ int i;
++
++ *nw++ = '*';
++ *nw++ = '!';
++ p = (q = strchr(s, '!')) ? q + 1 : s;
++ /* Strip of any nick, if a username is found, use last 8 chars */
++ if ((q = strchr(p, '@'))) {
++ int fl = 0;
++
++ if ((q - p) > 9) {
++ nw[0] = '*';
++ p = q - 7;
++ i = 1;
++ } else
++ i = 0;
++ while (*p != '@') {
++ if (!fl && strchr("~+-^=", *p)) {
++// if (strict_host)
++ nw[i] = '?';
++// else
++// i--;
++ } else
++ nw[i] = *p;
++ fl++;
++ p++;
++ i++;
++ }
++ nw[i++] = '@';
++ q++;
++ } else {
++ nw[0] = '*';
++ nw[1] = '@';
++ i = 2;
++ q = s;
++ }
++ nw += i;
++ e = NULL;
++ /* Now q points to the hostname, i point to where to put the mask */
++ if ((!(p = strchr(q, '.')) || !(e = strchr(p + 1, '.'))) && !strchr(q, ':'))
++ /* TLD or 2 part host */
++ strcpy(nw, q);
++ else {
++ if (e == NULL) { /* IPv6 address? */
++ const char *mask_str;
++
++ f = strrchr(q, ':');
++ if (strchr(f, '.')) { /* IPv4 wrapped in an IPv6? */
++ f = strrchr(f, '.');
++ mask_str = ".*";
++ } else /* ... no, true IPv6. */
++ mask_str = ":*";
++ strncpy(nw, q, f - q);
++ /* No need to nw[f-q] = 0 here, as the strcpy below will
++ * terminate the string for us.
++ */
++ nw += (f - q);
++ strcpy(nw, mask_str);
++ } else {
++ for (f = e; *f; f++);
++ f--;
++ if (*f >= '0' && *f <= '9') { /* Numeric IP address */
++ while (*f != '.')
++ f--;
++ strncpy(nw, q, f - q);
++ /* No need to nw[f-q] = 0 here, as the strcpy below will
++ * terminate the string for us.
++ */
++ nw += (f - q);
++ strcpy(nw, ".*");
++ } else { /* Normal host >= 3 parts */
++ /* a.b.c -> *.b.c
++ * a.b.c.d -> *.b.c.d if tld is a country (2 chars)
++ * OR *.c.d if tld is com/edu/etc (3 chars)
++ * a.b.c.d.e -> *.c.d.e etc
++ */
++ const char *x = strchr(e + 1, '.');
++
++ if (!x)
++ x = p;
++ else if (strchr(x + 1, '.'))
++ x = e;
++ else if (strlen(x) == 3)
++ x = p;
++ else
++ x = e;
++ sprintf(nw, "*%s", x);
++ }
++ }
++ }
++}
+diff -Nur src/mod/gseen.mod/seenlang.h src/mod/gseen.mod/seenlang.h
+--- src/mod/gseen.mod/seenlang.h 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/seenlang.h 2002-10-26 13:17:58.000000000 +0200
+@@ -0,0 +1,61 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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 SLPUBPREFIX getslang(10)
++#define SLNOTPREFIX getslang(11)
++#define SLMSGPREFIX getslang(12)
++#define SLDCCPREFIX getslang(13)
++
++#define SLNOPARAM getslang(54)
++#define SLMIRROR getslang(55)
++#define SLONCHAN getslang(56)
++#define SLNOWILDCARDS getslang(57)
++#define SLTOOLONGNICK getslang(58)
++
++#define SLNOTSEEN getslang(65)
++#define SLPOORSEEN getslang(66)
++#define SLNOMATCH getslang(67)
++#define SLTOOMANYMATCHES getslang(68)
++
++#define SLHANDONCHAN getslang(73)
++#define SLONOTHERCHAN getslang(74)
++#define SLONEMATCH getslang(75)
++#define SLLITTLEMATCHES getslang(76)
++#define SLMANYMATCHES getslang(77)
++
++#define SLRBOTSAYS getslang(85)
++
++#define SLYEAR getdur(0)
++#define SLYEARS getdur(1)
++#define SLWEEK getdur(2)
++#define SLWEEKS getdur(3)
++#define SLDAY getdur(4)
++#define SLDAYS getdur(5)
++#define SLHOUR getdur(6)
++#define SLHOURS getdur(7)
++#define SLMINUTE getdur(8)
++#define SLMINUTES getdur(9)
++#define SLSECOND getdur(10)
++#define SLSECONDS getdur(11)
++#define SLSOMETIME getdur(12)
++
++#define SLONELOOK getslang(170)
++#define SLMORELOOKS getslang(171)
++#define SLLASTLOOK getslang(172)
++
++#define SLSEENSTATS getslang(180)
+diff -Nur src/mod/gseen.mod/seentree.c src/mod/gseen.mod/seentree.c
+--- src/mod/gseen.mod/seentree.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/seentree.c 2002-10-26 13:18:10.000000000 +0200
+@@ -0,0 +1,213 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++static struct generic_binary_tree seentree;
++
++static void seentree_init();
++static int seentree_expmem();
++static void seentree_free();
++static int compareseens(void *, void *);
++static int expmemseen(void *);
++static void add_seen(int, char *, char *, char *, char *,
++ time_t, int);
++static void freeseen(void *);
++static seendat *findseen(char *);
++static void wildmatch_seens(char *, char *, int);
++static void process_wildmatch_seens(void *);
++static void write_seen_tree(void *);
++static void purge_seen_tree(void *);
++static int count_seens();
++static void _count_seens(void *);
++
++
++static void seentree_init()
++{
++ seentree.root = NULL;
++ seentree.comparedata = compareseens;
++ seentree.expmemdata = expmemseen;
++ seentree.freedata = freeseen;
++}
++
++static int seentree_expmem()
++{
++ return btree_expmem(&seentree);
++}
++
++static void seentree_free()
++{
++ btree_freetree(&seentree);
++ seentree.root = NULL;
++}
++
++static int compareseens(void *first, void *second)
++{
++ return rfc_casecmp(((seendat *) first)->nick, ((seendat *) second)->nick);
++}
++
++// add another entry to the tree
++static void add_seen(int type, char *nick, char *host, char *chan, char *msg,
++ time_t when, int spent)
++{
++ seendat *newseen;
++
++ newseen = nmalloc(sizeof(seendat));
++ newseen->type = type;
++ newseen->nick = nmalloc(strlen(nick) + 1);
++ strcpy(newseen->nick, nick);
++ newseen->host = nmalloc(strlen(host) + 1);
++ strcpy(newseen->host, host);
++ newseen->chan = nmalloc(strlen(chan) + 1);
++ strcpy(newseen->chan, chan);
++ newseen->msg = nmalloc(strlen(msg) + 1);
++ strcpy(newseen->msg, msg);
++ newseen->when = when;
++ newseen->spent = spent;
++ btree_add(&seentree, newseen);
++}
++
++static void freeseen(void *what)
++{
++ seendat *s = (seendat *) what;
++
++ Assert(s);
++ Assert(s->nick);
++ Assert(s->host);
++ Assert(s->chan);
++ Assert(s->msg);
++
++ nfree(s->nick);
++ nfree(s->host);
++ nfree(s->chan);
++ nfree(s->msg);
++ nfree(s);
++}
++
++static int expmemseen(void *what)
++{
++ int size = 0;
++ seendat *d = (seendat *) what;
++
++ size += sizeof(seendat);
++ size += strlen(d->nick) + 1;
++ size += strlen(d->host) + 1;
++ size += strlen(d->chan) + 1;
++ size += strlen(d->msg) + 1;
++ return size;
++}
++
++// finds a seen entry in the tree
++seendat findseen_temp;
++static seendat *findseen(char *nick)
++{
++ findseen_temp.nick = nick;
++ return btree_get(&seentree, &findseen_temp);
++}
++
++// function to find all nicks that match a host
++// (calls btree_getall() which calls a target function for each item)
++// host: user's hostmask (used if search query doesn't contain any wildcards)
++// mask: search mask
++// wild: defines if we want to use the mask, or host for the search
++static char *wildmatch_host, *wildmatch_mask;
++int wildmatch_wild;
++static void wildmatch_seens(char *host, char *mask, int wild)
++{
++ wildmatch_host = host;
++ wildmatch_mask = mask;
++ wildmatch_wild = wild;
++ btree_getall(&seentree, process_wildmatch_seens);
++}
++
++/* process_wildmatch_seens():
++ * gets called from the binary tree for each existing item.
++ */
++static void process_wildmatch_seens(void *data)
++{
++ seendat *s = (seendat *) data;
++
++ if ((numresults > max_matches) && (max_matches > 0)) // Don't return too many
++ return; // matches...
++ if (!wildmatch_wild) {
++ if (wild_match(wildmatch_host, s->host))
++ add_seenresult(s);
++ } else {
++ temp_wildmatch_host = my_realloc(temp_wildmatch_host, strlen(s->nick) + 1 + strlen(s->host) + 1);
++ strcpy(temp_wildmatch_host, s->nick);
++ strcat(temp_wildmatch_host, "!");
++ strcat(temp_wildmatch_host, s->host);
++ if (wild_match(wildmatch_mask, s->nick) || wild_match(wildmatch_mask, temp_wildmatch_host))
++ add_seenresult(s);
++ }
++}
++
++// write seendata in the datafile
++FILE *write_seen_tree_target;
++static void write_seen_tree(void *data)
++{
++ seendat *node = (seendat *) data;
++
++ /* format: "! nick host chan type when spent msg" */
++ fprintf(write_seen_tree_target, "! %s %s %s %d %lu %d %s\n", node->nick,
++ node->host, node->chan, node->type, node->when, node->spent,
++ node->msg);
++}
++
++// recursive function to remove old data
++// QUESTION: What happens if one of the nodes get moved by killseen()?
++// Possible bug/crash?
++// I think it should not be a problem. When killseen() is called the
++// first time, recursion already reached its end and no pointers
++// are accessed anymore. But I'm not sure... maybe I'm wrong.
++static void purge_seen_tree(void *data)
++{
++ seendat *node = (seendat *) data;
++
++ if ((now - node->when) > (expire_seens * 86400)) {
++ debug1("seen data for %s has expired.", node->nick);
++ btree_remove(&seentree, node);
++ }
++}
++
++// counts the number of nicks in the database
++static int count_seens_temp;
++static int count_seens()
++{
++ count_seens_temp = 0;
++ btree_getall(&seentree, _count_seens);
++ return count_seens_temp;
++}
++
++static void _count_seens(void *node)
++{
++ count_seens_temp++;
++}
++
++static int tcl_killseen STDVAR
++{
++ Context;
++ BADARGS(2, 2, " nick");
++ findseen_temp.nick = argv[1];
++ btree_remove(&seentree, &findseen_temp);
++ return TCL_OK;
++}
++
++static tcl_cmds seendebugtcls[] =
++{
++ {"killseen", tcl_killseen},
++ {0, 0}
++};
+diff -Nur src/mod/gseen.mod/sensors.c src/mod/gseen.mod/sensors.c
+--- src/mod/gseen.mod/sensors.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/sensors.c 2002-10-26 13:18:00.000000000 +0200
+@@ -0,0 +1,273 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++static int get_spent(char *nick, char *chan)
++{
++ struct chanset_t *ch = NULL;
++ memberlist *m = NULL;
++
++ int spent;
++ ch = findchan_by_dname(chan);
++ if (ch)
++ m = ismember(ch, nick);
++ if (m && m->joined)
++ spent = now - m->joined;
++ else
++ spent = -1;
++ return spent;
++}
++
++static int secretchan(char *chan)
++{
++ struct chanset_t *ch;
++
++ ch = findchan_by_dname(chan);
++ if (!ch)
++ return 0;
++ if (ch->status & CHAN_SECRET)
++ return 1;
++ return 0;
++}
++
++static int nolog(char *chan)
++{
++ char buf[121], *b;
++
++ Context;
++ strncpy(buf, no_log, 120);
++ buf[120] = 0;
++ b = buf;
++ while (b[0])
++ if (!strcasecmp(chan, newsplit(&b)))
++ return 1;
++#if EGG_IS_MIN_VER(10503)
++ if (ngetudef("noseendata", chan))
++ return 1;
++#endif
++ return 0;
++}
++
++static int gseen_join(char *nick, char *uhost, char *hand, char *chan)
++{
++ char buf[10] = "[secret]";
++
++ Context;
++ if (nolog(chan))
++ return 0;
++ if (use_handles && (hand[0] != '*'))
++ nick = hand;
++ if (secretchan(chan))
++ chan = buf;
++ add_seen(SEEN_JOIN, nick, uhost, chan, "", now, get_spent(nick, chan));
++ report_seenreq(chan, nick);
++ if ((hand[0] == '*') && strcasecmp(nick, hand))
++ report_seenreq(chan, hand);
++ return 0;
++}
++
++static int gseen_kick(char *nick, char *uhost, char *hand, char *chan,
++ char *victim, char *reason)
++{
++ struct chanset_t *ch = NULL;
++ memberlist *m = NULL;
++ char msg[1024], *s;
++ char buf[10] = "[secret]";
++
++ Context;
++ if (nolog(chan))
++ return 0;
++ if (use_handles && (hand[0] != '*'))
++ nick = hand;
++ ch = findchan_by_dname(chan);
++ if (!ch) {
++ debug2("Unable to seen %s getting kicked from %s", victim, chan);
++ return 0;
++ }
++ if (secretchan(chan))
++ chan = buf;
++ s = msg;
++ s[0] = 0;
++ m = ismember(ch, victim);
++ if (!m) {
++ debug2("Unable to seen %s getting kicked from %s", victim, chan);
++ return 0;
++ }
++ if ((strlen(nick) + strlen(reason) + 2) < 1024)
++ sprintf(s, "%s %s", nick, reason);
++ add_seen(SEEN_KICK, victim, m->userhost, chan, s, now,
++ get_spent(victim, chan));
++ return 0;
++}
++
++static int gseen_nick(char *nick, char *uhost, char *hand, char *chan,
++ char *newnick)
++{
++ char buf[10] = "[secret]";
++
++ Context;
++ if (nolog(chan))
++ return 0;
++ if (use_handles && (hand[0] != '*'))
++ nick = hand;
++ if (secretchan(chan))
++ chan = buf;
++ add_seen(SEEN_NICK, nick, uhost, chan, newnick, now, get_spent(nick, chan));
++ if (!(use_handles && (hand[0] != '*')))
++ add_seen(SEEN_NCKF, newnick, uhost, chan, nick, now, get_spent(nick, chan));
++ report_seenreq(chan, newnick);
++ if ((hand[0] != '*') && strcasecmp(newnick, hand))
++ report_seenreq(chan, hand);
++ return 0;
++}
++
++#if EGG_IS_MIN_VER(10502)
++static int gseen_part(char *nick, char *uhost, char *hand, char *chan,
++ char *reason)
++{
++ char buf[10] = "[secret]";
++
++ Context;
++ if (nolog(chan))
++ return 0;
++ if (use_handles && (hand[0] != '*'))
++ nick = hand;
++ if (secretchan(chan))
++ chan = buf;
++ add_seen(SEEN_PART, nick, uhost, chan, reason, now, get_spent(nick, chan));
++ return 0;
++}
++#else
++static int gseen_part(char *nick, char *uhost, char *hand, char *chan)
++{
++ char buf[10] = "[secret]";
++
++ Context;
++ if (nolog(chan))
++ return 0;
++ if (use_handles && (hand[0] != '*'))
++ nick = hand;
++ if (secretchan(chan))
++ chan = buf;
++ add_seen(SEEN_PART, nick, uhost, chan, "", now, get_spent(nick, chan));
++ return 0;
++}
++#endif
++
++static int gseen_sign(char *nick, char *uhost, char *hand, char *chan,
++ char *reason)
++{
++ char buf[10] = "[secret]";
++
++ Context;
++ if (nolog(chan))
++ return 0;
++ if (use_handles && (hand[0] != '*'))
++ nick = hand;
++ if (secretchan(chan))
++ chan = buf;
++ add_seen(SEEN_SIGN, nick, uhost, chan, reason, now, get_spent(nick, chan));
++ return 0;
++}
++
++static int gseen_splt(char *nick, char *uhost, char *hand, char *chan)
++{
++ char buf[10] = "[secret]";
++
++ Context;
++ if (nolog(chan))
++ return 0;
++ if (use_handles && (hand[0] != '*'))
++ nick = hand;
++ if (secretchan(chan))
++ chan = buf;
++ add_seen(SEEN_SPLT, nick, uhost, chan, "", now, get_spent(nick, chan));
++ return 0;
++}
++
++static int gseen_rejn(char *nick, char *uhost, char *hand, char *chan)
++{
++ char buf[10] = "[secret]";
++
++ Context;
++ if (nolog(chan))
++ return 0;
++ if (use_handles && (hand[0] != '*'))
++ nick = hand;
++ if (secretchan(chan))
++ chan = buf;
++ add_seen(SEEN_REJN, nick, uhost, chan, "", now, get_spent(nick, chan));
++ return 0;
++}
++
++static int gseen_chjn STDVAR
++{
++ Context;
++ BADARGS(7, 7, " bot hand chan flag idx host");
++ add_seen(SEEN_CHJN, argv[2], argv[6], argv[3], argv[1], now, -1);
++ return 0;
++}
++
++static int gseen_chpt STDVAR
++{
++ Context;
++ BADARGS(5, 5, " bot hand idx chan");
++ add_seen(SEEN_CHPT, argv[2], "unknown", argv[4], argv[1], now, -1);
++ return 0;
++}
++
++static cmd_t seen_kick[] =
++{
++ {"*", "", (Function) gseen_kick, "gseen"},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_nick[] =
++{
++ {"*", "", (Function) gseen_nick, "gseen"},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_join[] =
++{
++ {"*", "", (Function) gseen_join, "gseen"},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_part[] =
++{
++ {"*", "", (Function) gseen_part, "gseen"},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_sign[] =
++{
++ {"*", "", (Function) gseen_sign, "gseen"},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_splt[] =
++{
++ {"*", "", (Function) gseen_splt, "gseen"},
++ {0, 0, 0, 0}
++};
++
++static cmd_t seen_rejn[] =
++{
++ {"*", "", (Function) gseen_rejn, "gseen"},
++ {0, 0, 0, 0}
++};
+diff -Nur src/mod/gseen.mod/slang.c src/mod/gseen.mod/slang.c
+--- src/mod/gseen.mod/slang.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/slang.c 2002-10-26 13:18:03.000000000 +0200
+@@ -0,0 +1,309 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++static struct slang_header *slang_find(struct slang_header *, char *);
++
++#include "slang_text.c"
++#include "slang_multitext.c"
++#include "slang_ids.c"
++#ifndef SLANG_NOTYPES
++#include "slang_types.c"
++#endif
++#include "slang_duration.c"
++#ifndef SLANG_NOFACTS
++#include "slang_facts_places.c"
++#include "slang_facts.c"
++#endif
++#include "slang_chanlang.c"
++
++
++struct slang_header {
++ struct slang_header *next;
++ char *lang;
++ char *desc;
++ struct slang_id *ids;
++#ifndef SLANG_NOTYPES
++ struct slang_type *types;
++#endif
++ struct slang_duration *durations;
++};
++
++static void slang_glob_init()
++{
++ glob_slang_cmd_list = NULL;
++}
++
++static int slang_glob_expmem()
++{
++ return slang_commands_list_expmem(glob_slang_cmd_list);
++}
++
++static void slang_glob_free()
++{
++ slang_commands_list_free(glob_slang_cmd_list);
++ glob_slang_cmd_list = NULL;
++}
++
++static struct slang_header *slang_create(struct slang_header *list, char *lang, char *desc)
++{
++ struct slang_header *nslang, *l;
++
++ Assert(lang);
++ debug2("Creating language '%s' starting by %d", lang, (int) list);
++ for (nslang = list; nslang; nslang = nslang->next)
++ if (!strcasecmp(nslang->lang, lang))
++ return list;
++ nslang = nmalloc(sizeof(struct slang_header));
++ nslang->next = NULL;
++ nslang->desc = NULL;
++ nslang->lang = nmalloc(strlen(lang) + 1);
++ strcpy(nslang->lang, lang);
++ nslang->desc = nmalloc(strlen(desc) + 1);
++ strcpy(nslang->desc, desc);
++ nslang->ids = NULL;
++#ifndef SLANG_NOTYPES
++ nslang->types = NULL;
++#endif
++ nslang->durations = NULL;
++ for (l = list; l && l->next; l = l->next);
++ if (l)
++ l->next = nslang;
++ else {
++ Assert(!list);
++ list = nslang;
++ }
++ return list;
++}
++
++static int slang_expmem(struct slang_header *what)
++{
++ int size = 0;
++
++ while (what) {
++ size += sizeof(struct slang_header);
++ size += strlen(what->lang) + 1;
++ size += strlen(what->desc) + 1;
++ size += slang_id_expmem(what->ids);
++#ifndef SLANG_NOTYPES
++ size += slang_type_expmem(what->types);
++#endif
++ size += slang_duration_expmem(what->durations);
++ what = what->next;
++ }
++ return size;
++}
++
++static void slang_free(struct slang_header *what)
++{
++ struct slang_header *next;
++
++ while (what) {
++ next = what->next;
++ slang_id_free(what->ids);
++#ifndef SLANG_NOTYPES
++ slang_type_free(what->types);
++#endif
++ slang_duration_free(what->durations);
++ nfree(what->lang);
++ nfree(what->desc);
++ nfree(what);
++ what = next;
++ }
++}
++
++static int slang_load(struct slang_header *slang, char *filename)
++{
++ FILE *f;
++ char *buffer, *s;
++ char *cmd, *sid, *strtol_ret;
++#ifndef SLANG_NOTYPES
++ char *type;
++#endif
++ int line, id;
++
++ Assert(slang);
++ putlog(LOG_MISC, "*", "Loading language \"%s\" from %s...", slang->lang, filename);
++ f = fopen(filename, "r");
++ if (!f) {
++ putlog(LOG_MISC, "*", "Couldn't open slangfile \"%s\"!", filename);
++ return 0;
++ }
++ buffer = nmalloc(2000);
++ line = 0;
++ while (!feof(f)) {
++ s = buffer;
++ if (fgets(s, 2000, f)) {
++ line++;
++ // at first, kill those stupid line feeds and carriage returns...
++ if (s[strlen(s) - 1] == '\n')
++ s[strlen(s) - 1] = 0;
++ if (s[strlen(s) - 1] == '\r')
++ s[strlen(s) - 1] = 0;
++ if (!s[0])
++ continue;
++ cmd = newsplit(&s);
++
++ if (!strcasecmp(cmd, "T")) {
++#ifndef SLANG_NOTYPES
++ type = newsplit(&s);
++ slang->types = slang_type_add(slang->types, type, s);
++#endif
++ } else if (!strcasecmp(cmd, "D")) {
++ sid = newsplit(&s);
++ id = strtol(sid, &strtol_ret, 10);
++ if (strtol_ret == sid) {
++ putlog(LOG_MISC, "*", "ERROR in slangfile \"%s\", line %d: %s is not a valid "
++ "duration index!", filename, line, sid);
++ continue;
++ }
++ slang->durations = slang_duration_add(slang->durations, id, s);
++ } else {
++ id = strtol(cmd, &strtol_ret, 10);
++ if (strtol_ret == cmd)
++ continue;
++ slang->ids = slang_id_add(slang->ids, id, s);
++ }
++ }
++ }
++ fclose(f);
++ nfree(buffer);
++ return 1;
++}
++
++static struct slang_header *slang_find(struct slang_header *where, char *language)
++{
++ struct slang_header *slang = NULL;
++
++ // at first, search for the specified language
++ for (slang = where; slang; slang = slang->next)
++ if (!strcasecmp(slang->lang, language))
++ return slang;
++ // oops... language seems to be invalid. Let's find the default.
++ Assert(default_slang);
++ for (slang = where; slang; slang = slang->next)
++ if (!strcasecmp(slang->lang, default_slang))
++ return slang;
++ // default_slang wasn't found either? *sigh*
++ // Let's return the first known language then.
++ return where;
++}
++
++#ifndef SLANG_NOVALIDATE
++/* slang_valid():
++ * check if the given language is a valid one
++ */
++static int slang_valid(struct slang_header *where, char *language)
++{
++ struct slang_header *slang = NULL;
++
++ for (slang = where; slang; slang = slang->next)
++ if (!strcasecmp(slang->lang, language))
++ return 1;
++ return 0;
++}
++#endif
++
++static char getslang_error[12];
++static char *getslang(int id)
++{
++ char *text;
++
++ if (!glob_slang) {
++ putlog(LOG_MISC, "*", "WARNING! No language selected! (getslang())");
++ return "NOLANG";
++ }
++ text = slang_id_get(glob_slang->ids, id);
++ if (!text) {
++ snprintf(getslang_error, sizeof(getslang_error), "SLANG%d", id);
++ return getslang_error;
++ }
++ return text;
++}
++
++static char *getdur(int idx)
++{
++ char *text;
++
++ Assert((idx >= 0) && (idx < DURATIONS));
++ if (!glob_slang) {
++ putlog(LOG_MISC, "*", "WARNING! No language selected! (getdur())");
++ return "NOLANG";
++ }
++ text = slang_duration_get(glob_slang->durations, idx);
++ if (!text) {
++ snprintf(getslang_error, sizeof(getslang_error), "DUR%d", idx);
++ return getslang_error;
++ }
++ return text;
++}
++
++#ifndef SLANG_NOTYPES
++static char *getslangtype(char *type)
++{
++ char *stype;
++
++ if (!glob_slang) {
++ putlog(LOG_MISC, "*", "WARNING! No language selected! (getslangtype())");
++ return "NOLANG";
++ }
++ stype = slang_type_get(glob_slang->types, type);
++ if (stype)
++ return stype;
++ else
++ return type;
++}
++
++static int slangtypetoi(char *slangtype)
++{
++ char *type;
++
++ if (!glob_slang) {
++ putlog(LOG_MISC, "*", "WARNING! No language selected! (slangtypetoi())");
++ return T_ERROR;
++ }
++ type = slang_type_slang2type(glob_slang->types, slangtype);
++ if (type) {
++ debug1("type: %s", type);
++ return typetoi(type);
++ } else
++ return typetoi(slangtype);
++}
++#endif
++
++#ifndef SLANG_NOGETALL
++static char *getslang_first(int id)
++{
++ char *text;
++
++ if (!glob_slang) {
++ putlog(LOG_MISC, "*", "WARNING! No language selected! (getslang())");
++ return "NOLANG";
++ }
++ text = slang_id_get_first(glob_slang->ids, id);
++ if (!text) {
++ snprintf(getslang_error, sizeof(getslang_error), "SLANG%d", id);
++ return getslang_error;
++ }
++ return text;
++}
++
++static char *getslang_next()
++{
++ return slang_id_get_next();
++}
++#endif
+diff -Nur src/mod/gseen.mod/slang_chanlang.c src/mod/gseen.mod/slang_chanlang.c
+--- src/mod/gseen.mod/slang_chanlang.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/slang_chanlang.c 2002-10-26 13:18:02.000000000 +0200
+@@ -0,0 +1,113 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++struct slang_chanlang {
++ struct slang_chanlang *next;
++ char *chan;
++ char *lang;
++};
++
++static struct slang_chanlang *chanlangs = NULL;
++
++static struct slang_chanlang *slang_chanlang_add(struct slang_chanlang *, char *, char *);
++static int slang_chanlang_expmem(struct slang_chanlang *);
++static void slang_chanlang_free(struct slang_chanlang *);
++static char *slang_chanlang_get(struct slang_chanlang *, char *);
++
++static struct slang_chanlang *slang_chanlang_add(struct slang_chanlang *where, char *chan, char *lang)
++{
++ struct slang_chanlang *item;
++
++ for (item = where; item; item = item->next)
++ if (!rfc_casecmp(item->chan, chan))
++ break;
++ if (!item) {
++ item = nmalloc(sizeof(struct slang_chanlang));
++ item->chan = nmalloc(strlen(chan) + 1);
++ strcpy(item->chan, chan);
++ item->lang = nmalloc(strlen(lang) + 1);
++ strcpy(item->lang, lang);
++ item->next = where;
++ where = item;
++ } else {
++ Assert(item->lang);
++ item->lang = nrealloc(item->lang, strlen(lang) + 1);
++ strcpy(item->lang, lang);
++ }
++ return where;
++}
++
++static int slang_chanlang_expmem(struct slang_chanlang *what)
++{
++ int size = 0;
++
++ while (what) {
++ Assert(what);
++ Assert(what->chan);
++ Assert(what->lang);
++ size += sizeof(struct slang_chanlang);
++ size += strlen(what->chan) + 1;
++ size += strlen(what->lang) + 1;
++ what = what->next;
++ }
++ return size;
++}
++
++static void slang_chanlang_free(struct slang_chanlang *what)
++{
++ struct slang_chanlang *next;
++
++ while (what) {
++ Assert(what);
++ Assert(what->chan);
++ Assert(what->lang);
++ next = what->next;
++ nfree(what->chan);
++ nfree(what->lang);
++ nfree(what);
++ what = next;
++ }
++}
++
++static char *slang_chanlang_get(struct slang_chanlang *where, char *chan)
++{
++ while (where) {
++ if (!rfc_casecmp(where->chan, chan))
++ return where->lang;
++ where = where->next;
++ }
++ return default_slang;
++}
++
++/* slang_getbynick():
++ * tries to find an appropriate language for nick by searching
++ * him on a channel and using the language of this channel.
++ */
++static struct slang_header *slang_getbynick(struct slang_header *where, char *nick)
++{
++ struct chanset_t *chan;
++
++ for (chan = chanset; chan; chan = chan->next)
++ if (ismember(chan, nick))
++#if EGG_IS_MIN_VER(10500)
++ return slang_find(where, slang_chanlang_get(chanlangs, chan->dname));
++#else
++ return slang_find(where, slang_chanlang_get(chanlangs, chan->name));
++#endif
++ return slang_find(where, default_slang);
++}
+diff -Nur src/mod/gseen.mod/slang_duration.c src/mod/gseen.mod/slang_duration.c
+--- src/mod/gseen.mod/slang_duration.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/slang_duration.c 2002-10-26 13:18:01.000000000 +0200
+@@ -0,0 +1,82 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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 DURATIONS 13
++
++struct slang_duration {
++ char *durs[DURATIONS];
++};
++
++static struct slang_duration *slang_duration_add(struct slang_duration *where, int idx, char *text)
++{
++ int i;
++
++ if ((idx < 0) || (idx >= DURATIONS)) {
++ putlog(LOG_MISC, "*", "Warning: Invalid duration index \"%d\".", idx);
++ return where;
++ }
++ debug2("Adding duration[%d]: %s", idx, text);
++ if (!where) {
++ where = nmalloc(sizeof(struct slang_duration));
++ for (i = 0; i < DURATIONS; i++)
++ where->durs[i] = NULL;
++ }
++ if (where->durs[idx])
++ nfree(where->durs[idx]);
++ where->durs[idx] = nmalloc(strlen(text) + 1);
++ strcpy(where->durs[idx], text);
++ return where;
++}
++
++static int slang_duration_expmem(struct slang_duration *what)
++{
++ int i, size = 0;
++
++ if (!what)
++ return 0;
++ size += sizeof(struct slang_duration);
++ for (i = 0; i < DURATIONS; i++)
++ if (what->durs[i])
++ size += strlen(what->durs[i]) + 1;
++ return size;
++}
++
++static void slang_duration_free(struct slang_duration *what)
++{
++ int i;
++
++ if (what) {
++ for (i = 0; i < DURATIONS; i++)
++ if (what->durs[i])
++ nfree(what->durs[i]);
++ nfree(what);
++ }
++}
++
++static char *slang_duration_get(struct slang_duration *where, int idx)
++{
++ if (!where) {
++ debug0("no where");
++ return NULL;
++ }
++ if ((idx < 0) || (idx >= DURATIONS)) {
++ debug1("invalid duration index: %d", idx);
++ return NULL;
++ }
++ return where->durs[idx];
++}
+diff -Nur src/mod/gseen.mod/slang_gseen_commands.c src/mod/gseen.mod/slang_gseen_commands.c
+--- src/mod/gseen.mod/slang_gseen_commands.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/slang_gseen_commands.c 2002-10-26 13:18:06.000000000 +0200
+@@ -0,0 +1,235 @@
++static void slang_send_botnick()
++{
++ strncat(slang_text_buf, botname, sizeof(slang_text_buf));
++}
++
++static void slang_send_query()
++{
++ if (glob_query)
++ strncat(slang_text_buf, glob_query, sizeof(slang_text_buf));
++}
++
++static void slang_send_laston()
++{
++ if (glob_laston)
++ strncat(slang_text_buf, glob_laston, sizeof(slang_text_buf));
++}
++
++static void slang_send_otherchan()
++{
++ if (glob_otherchan)
++ strncat(slang_text_buf, glob_otherchan, sizeof(slang_text_buf));
++}
++
++static void slang_send_othernick()
++{
++ if (glob_othernick)
++ strncat(slang_text_buf, glob_othernick, sizeof(slang_text_buf));
++}
++
++static void slang_send_remotebot()
++{
++ if (glob_remotebot)
++ strncat(slang_text_buf, glob_remotebot, sizeof(slang_text_buf));
++}
++
++static void slang_send_snick()
++{
++ if (glob_seendat)
++ strncat(slang_text_buf, glob_seendat->nick, sizeof(slang_text_buf));
++}
++
++static void slang_send_shost()
++{
++ if (glob_seendat)
++ strncat(slang_text_buf, glob_seendat->host, sizeof(slang_text_buf));
++}
++
++static void slang_send_schan()
++{
++ if (glob_seendat)
++ strncat(slang_text_buf, glob_seendat->chan, sizeof(slang_text_buf));
++}
++
++static void slang_send_swhen()
++{
++ char *dur;
++
++ if (glob_seendat) {
++ dur = gseen_duration(now - glob_seendat->when);
++ strncat(slang_text_buf, dur, sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_stime()
++{
++ time_t tt;
++ char t[20];
++
++ if (glob_seendat) {
++ tt = glob_seendat->when;
++ strftime(t, 19, "%d.%m. %H:%M", localtime(&tt));
++ strncat(slang_text_buf, t, sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_spent()
++{
++ char *dur;
++
++ if (glob_seendat) {
++ dur = gseen_duration(glob_seendat->spent);
++ strncat(slang_text_buf, dur, sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_smsg()
++{
++ if (glob_seendat)
++ strncat(slang_text_buf, glob_seendat->msg, sizeof(slang_text_buf));
++}
++
++static void slang_send_numresults()
++{
++ char buf[7];
++
++ snprintf(buf, sizeof(buf), "%d", numresults);
++ strncat(slang_text_buf, buf, sizeof(slang_text_buf));
++}
++
++static void slang_send_punisher()
++{
++ char *reason;
++ int len;
++
++ if (glob_seendat) {
++ reason = strchr(glob_seendat->msg, ' ');
++ if (!reason)
++ strncat(slang_text_buf, glob_seendat->msg, sizeof(slang_text_buf));
++ else {
++ len = (int) reason - (int) glob_seendat->msg;
++ strncat(slang_text_buf, glob_seendat->msg, (sizeof(slang_text_buf) < len) ? sizeof(slang_text_buf) : len);
++ }
++ }
++}
++
++static void slang_send_kickreason()
++{
++ char *reason;
++
++ if (glob_seendat) {
++ reason = strchr(glob_seendat->msg, ' ');
++ if (reason)
++ strncat(slang_text_buf, reason, sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_rnick()
++{
++ if (glob_seenrequest) {
++ Assert(glob_seenrequest->by);
++ Assert(glob_seenrequest->by->who);
++ strncat(slang_text_buf, glob_seenrequest->by->who, sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_rchan()
++{
++ if (glob_seenrequest) {
++ Assert(glob_seenrequest->by);
++ Assert(glob_seenrequest->by->chan);
++ strncat(slang_text_buf, glob_seenrequest->by->chan, sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_rhost()
++{
++ if (glob_seenrequest) {
++ Assert(glob_seenrequest->by);
++ Assert(glob_seenrequest->by->host);
++ strncat(slang_text_buf, glob_seenrequest->by->host, sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_rtime()
++{
++ time_t tt;
++ char t[20];
++
++ if (glob_seenrequest) {
++ Assert(glob_seenrequest->by);
++ tt = glob_seenrequest->by->when;
++ strftime(t, sizeof(t), "%d.%m. %H:%M", localtime(&tt));
++ strncat(slang_text_buf, t, sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_rwhen()
++{
++ if (glob_seenrequest) {
++ Assert(glob_seenrequest->by);
++ strncat(slang_text_buf, gseen_duration(now - glob_seenrequest->by->when), sizeof(slang_text_buf));
++ }
++}
++
++static void slang_send_requests()
++{
++ char buf[7];
++
++ snprintf(buf, sizeof(buf), "%d", glob_seenrequests);
++ strncat(slang_text_buf, buf, sizeof(slang_text_buf));
++}
++
++static void slang_send_totalnicks()
++{
++ char buf[7];
++
++ snprintf(buf, sizeof(buf), "%d", glob_totalnicks);
++ strncat(slang_text_buf, buf, sizeof(slang_text_buf));
++}
++
++static void slang_send_totalbytes()
++{
++ char buf[20];
++
++ snprintf(buf, sizeof(buf), "%d", glob_totalbytes);
++ strncat(slang_text_buf, buf, sizeof(slang_text_buf));
++}
++
++static void slang_send_nick()
++{
++ if (glob_nick)
++ strncat(slang_text_buf, glob_nick, sizeof(slang_text_buf));
++}
++
++struct slang_text_commands slang_text_gseen_command_table[] =
++{
++ {"botnick", slang_send_botnick},
++ {"query", slang_send_query},
++ {"laston", slang_send_laston},
++ {"otherchan", slang_send_otherchan},
++ {"othernick", slang_send_othernick},
++ {"remotebot", slang_send_remotebot},
++ {"snick", slang_send_snick},
++ {"swhen", slang_send_swhen},
++ {"stime", slang_send_stime},
++ {"shost", slang_send_shost},
++ {"schan", slang_send_schan},
++ {"spent", slang_send_spent},
++ {"smsg", slang_send_smsg},
++ {"numresults", slang_send_numresults},
++ {"snick2", slang_send_smsg},
++ {"bnbot", slang_send_smsg},
++ {"punisher", slang_send_punisher},
++ {"kickreason", slang_send_kickreason},
++ {"rnick", slang_send_rnick},
++ {"rchan", slang_send_rchan},
++ {"rhost", slang_send_rhost},
++ {"rtime", slang_send_rtime},
++ {"rwhen", slang_send_rwhen},
++ {"requests", slang_send_requests},
++ {"totalnicks", slang_send_totalnicks},
++ {"totalbytes", slang_send_totalbytes},
++ {"nick", slang_send_nick},
++ {0, 0}
++};
+diff -Nur src/mod/gseen.mod/slang_ids.c src/mod/gseen.mod/slang_ids.c
+--- src/mod/gseen.mod/slang_ids.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/slang_ids.c 2002-10-26 13:18:04.000000000 +0200
+@@ -0,0 +1,104 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++struct slang_id {
++ struct slang_id *next;
++ int id;
++ struct slang_multitext *mtext;
++};
++
++static struct slang_id* slang_id_add(struct slang_id *, int, char *);
++static int slang_id_expmem(struct slang_id *);
++static void slang_id_free(struct slang_id *);
++static char *slang_id_get(struct slang_id *, int);
++
++static struct slang_id* slang_id_add(struct slang_id *where, int id, char *text)
++{
++ struct slang_id *newitem;
++
++ newitem = NULL;
++ if (where) {
++ for (newitem = where; newitem; newitem = newitem->next)
++ if (newitem->id == id)
++ break;
++ }
++ if (!newitem) {
++ newitem = nmalloc(sizeof(struct slang_id));
++ newitem->next = NULL;
++ newitem->id = id;
++ newitem->mtext = NULL;
++ if (where)
++ newitem->next = where;
++ else
++ newitem->next = NULL;
++ where = newitem;
++ }
++ newitem->mtext = slang_mtext_add(newitem->mtext, text);
++ return where;
++}
++
++static int slang_id_expmem(struct slang_id *what)
++{
++ int size = 0;
++
++ for (; what; what = what->next) {
++ size += sizeof(struct slang_id);
++ size += slang_multitext_expmem(what->mtext);
++ }
++ return size;
++}
++
++static void slang_id_free(struct slang_id *what)
++{
++ struct slang_id *next;
++
++ while (what) {
++ next = what->next;
++ slang_multitext_free(what->mtext);
++ nfree(what);
++ what = next;
++ }
++}
++
++static char *slang_id_get(struct slang_id *where, int i)
++{
++ while (where) {
++ if (where->id == i)
++ return slang_multitext_getrandomtext(where->mtext);
++ where = where->next;
++ }
++ return NULL;
++}
++
++#ifndef SLANG_NOGETALL
++static char *slang_id_get_first(struct slang_id *where, int id)
++{
++ while (where) {
++ if (where->id == id) {
++ return slang_multitext_get_first(where->mtext);
++ }
++ where = where->next;
++ }
++ return NULL;
++}
++
++static char *slang_id_get_next()
++{
++ return slang_multitext_get_next();
++}
++#endif
+diff -Nur src/mod/gseen.mod/slang_multitext.c src/mod/gseen.mod/slang_multitext.c
+--- src/mod/gseen.mod/slang_multitext.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/slang_multitext.c 2002-10-26 13:18:05.000000000 +0200
+@@ -0,0 +1,151 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++struct slang_mt_content {
++ struct slang_mt_content *next;
++ struct slang_text *text;
++};
++
++struct slang_multitext {
++ int nr;
++ struct slang_mt_content *contents;
++};
++
++static struct slang_multitext *slang_mtext_add(struct slang_multitext *, char *);
++static int slang_multitext_expmem(struct slang_multitext *);
++static void slang_multitext_free(struct slang_multitext *);
++static char *slang_multitext_getrandomtext(struct slang_multitext *);
++#ifndef SLANG_NOTYPES
++static struct slang_text *slang_multitext_find(struct slang_multitext *, char *);
++#endif
++#ifndef SLANG_NOGETALL
++static char *slang_multitext_get_first(struct slang_multitext *);
++static char *slang_multitext_get_next();
++#endif
++
++static struct slang_multitext *slang_mtext_add(struct slang_multitext *where, char *text)
++{
++ struct slang_mt_content *oc, *nc;
++
++ if (!where) {
++ where = nmalloc(sizeof(struct slang_multitext));
++ where->nr = 0;
++ where->contents = NULL;
++ }
++ nc = nmalloc(sizeof(struct slang_mt_content));
++ nc->next = NULL;
++ nc->text = slang_text_parse(text);
++ for (oc = where->contents; oc && oc->next; oc = oc->next);
++ if (oc) {
++ Assert(!oc->next);
++ oc->next = nc;
++ } else
++ where->contents = nc;
++ where->nr++;
++ return where;
++}
++
++static int slang_multitext_expmem(struct slang_multitext *what)
++{
++ struct slang_mt_content *content;
++ int size = 0;
++
++ if (!what) {
++ debug0("WARNING! slang_multitext_expmem() called with NULL pointer!");
++ return 0;
++ }
++ size += sizeof(struct slang_multitext);
++ for (content = what->contents; content; content = content->next) {
++ size += sizeof(struct slang_mt_content);
++ size += slang_text_expmem(content->text);
++ }
++ return size;
++}
++
++static void slang_multitext_free(struct slang_multitext *what)
++{
++ struct slang_mt_content *content, *next;
++
++ if (!what) {
++ debug0("WARNING! slang_multitext_free() called with NULL pointer!");
++ return;
++ }
++ content = what->contents;
++ while (content) {
++ next = content->next;
++ slang_text_free(content->text);
++ nfree(content);
++ content = next;
++ }
++ nfree(what);
++}
++
++static char *slang_multitext_getrandomtext(struct slang_multitext *where)
++{
++ struct slang_mt_content *content;
++ unsigned long x;
++
++ if (!where)
++ return NULL;
++ x = random() % where->nr;
++ for (content = where->contents; content; content = content->next)
++ if (!x)
++ return slang_text_get(content->text);
++ else
++ x--;
++ // we should never reach this part
++ debug0("warning: getrandomtext didn't find anything!");
++ return NULL;
++}
++
++#ifndef SLANG_NOTYPES
++static struct slang_text *slang_multitext_find(struct slang_multitext *where, char *what)
++{
++ struct slang_mt_content *content;
++
++ Assert(where);
++ for (content = where->contents; content; content = content->next) {
++ Assert(content->text);
++ if (!slang_text_strcasecmp(content->text, what))
++ return content->text;
++ }
++ return NULL;
++}
++#endif
++
++#ifndef SLANG_NOGETALL
++static struct slang_mt_content *glob_mtext_content;
++static char *slang_multitext_get_first(struct slang_multitext *where)
++{
++ Assert(where);
++ glob_mtext_content = where->contents;
++ if (glob_mtext_content)
++ return slang_text_get(glob_mtext_content->text);
++ else
++ return NULL;
++}
++
++static char *slang_multitext_get_next()
++{
++ glob_mtext_content = glob_mtext_content->next;
++ if (glob_mtext_content)
++ return slang_text_get(glob_mtext_content->text);
++ else
++ return NULL;
++}
++#endif
+diff -Nur src/mod/gseen.mod/slang_text.c src/mod/gseen.mod/slang_text.c
+--- src/mod/gseen.mod/slang_text.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/slang_text.c 2002-10-26 13:18:07.000000000 +0200
+@@ -0,0 +1,200 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++struct slang_text {
++ struct slang_text *next;
++ char *string;
++ void (*command) ();
++};
++
++struct slang_text_commands {
++ char *command;
++ void (*targetfunc) ();
++};
++
++struct slang_command_list {
++ struct slang_command_list *next;
++ struct slang_text_commands *commands;
++};
++
++static struct slang_text *slang_text_parse(char *);
++static struct slang_text *slang_text_create(struct slang_text *);
++static void slang_text_add_string(struct slang_text *, char *);
++static void slang_text_add_command(struct slang_text *, char *);
++static void slang_text_free(struct slang_text *);
++static int slang_text_expmem(struct slang_text *);
++static char *slang_text_get(struct slang_text *);
++#ifndef SLANG_NOTYPES
++static int slang_text_strcasecmp(struct slang_text *, char *);
++#endif
++
++static struct slang_text *slang_text_parse(char *text)
++{
++ char *cmdstart, *cmdend;
++ struct slang_text *firstitem, *item;
++
++ firstitem = slang_text_create(NULL);
++ item = firstitem;
++ while ((cmdstart = strstr(text, "<?"))) {
++ cmdstart[0] = 0;
++ slang_text_add_string(item, text);
++ item = slang_text_create(item);
++ text += 2;
++ cmdstart += 2;
++ cmdend = strstr(cmdstart, "/?>");
++ if (!cmdend) {
++ putlog(LOG_MISC, "*", "ERROR parsing slang text: unterminated command \"%s\"!", cmdstart);
++ break;
++ }
++ cmdend[0] = 0;
++ slang_text_add_command(item, cmdstart);
++ item = slang_text_create(item);
++ text = cmdend + 3;
++ }
++ slang_text_add_string(item, text);
++ return firstitem;
++}
++
++static struct slang_text *slang_text_create(struct slang_text *where)
++{
++ struct slang_text *newpart;
++
++ newpart = nmalloc(sizeof(struct slang_text));
++ newpart->next = NULL;
++ newpart->string = NULL;
++ newpart->command = NULL;
++ while (where && where->next)
++ where = where->next;
++ if (where)
++ where->next = newpart;
++ return newpart;
++}
++
++static void slang_text_add_string(struct slang_text *item, char *s)
++{
++ Assert(item);
++ Assert(!item->string);
++ item->string = nmalloc(strlen(s) + 1);
++ strcpy(item->string, s);
++}
++
++static void slang_text_free(struct slang_text *item)
++{
++ if (!item)
++ return;
++ slang_text_free(item->next);
++ if (item->string)
++ nfree(item->string);
++ nfree(item);
++}
++
++static int slang_text_expmem(struct slang_text *item)
++{
++ int size = 0;
++
++ while (item) {
++ size += sizeof(struct slang_text);
++ if (item->string)
++ size += strlen(item->string) + 1;
++ item = item->next;
++ }
++ return size;
++}
++
++#ifndef SLANG_NOTYPES
++static int slang_text_strcasecmp(struct slang_text *item, char *text)
++{
++ Assert(item);
++ debug2("s_t_sc: '%s', '%s'", text, item->string);
++ if (item->command || item->next)
++ return 1;
++ return strcasecmp(item->string, text);
++}
++#endif
++
++static char slang_text_buf[500];
++static char *slang_text_get(struct slang_text *item)
++{
++ slang_text_buf[0] = 0;
++ while (item) {
++ if (item->string)
++ strncat(slang_text_buf, item->string, sizeof(slang_text_buf));
++ else if (item->command)
++ item->command();
++ item = item->next;
++ }
++ return slang_text_buf;
++}
++
++/*****************************************************/
++
++
++static struct slang_command_list *glob_slang_cmd_list;
++
++static struct slang_command_list *slang_commands_list_add(struct slang_command_list *where, struct slang_text_commands *what)
++{
++ struct slang_command_list *newcommandlist;
++
++ newcommandlist = nmalloc(sizeof(struct slang_command_list));
++ newcommandlist->commands = what;
++ newcommandlist->next = where;
++ return newcommandlist;
++}
++
++static int slang_commands_list_expmem(struct slang_command_list *what)
++{
++ int size = 0;
++
++ while (what) {
++ size += sizeof(struct slang_command_list);
++ what = what->next;
++ }
++ return size;
++}
++
++static void slang_commands_list_free(struct slang_command_list *what)
++{
++ struct slang_command_list *next;
++
++ while (what) {
++ next = what->next;
++ nfree(what);
++ what = next;
++ }
++}
++
++static void slang_text_add_command(struct slang_text *item, char *s)
++{
++ struct slang_command_list *cmdlist;
++ char *cmd;
++ int i;
++
++ cmd = newsplit(&s);
++ i = 0;
++ for (cmdlist = glob_slang_cmd_list; cmdlist; cmdlist = cmdlist->next) {
++ for (i = 0; 1; i++) {
++ if (!cmdlist->commands[i].command)
++ break;
++ if (!strcasecmp(cmdlist->commands[i].command, cmd)) {
++ item->command = cmdlist->commands[i].targetfunc;
++ return;
++ }
++ }
++ }
++ putlog(LOG_MISC, "*", "ERROR! Unknown slang-command: '%s'", cmd);
++}
+diff -Nur src/mod/gseen.mod/tclcmds.c src/mod/gseen.mod/tclcmds.c
+--- src/mod/gseen.mod/tclcmds.c 1970-01-01 01:00:00.000000000 +0100
++++ src/mod/gseen.mod/tclcmds.c 2002-10-26 13:18:08.000000000 +0200
+@@ -0,0 +1,53 @@
++/*
++ * Copyright (C) 2000,2001 Florian Sander
++ *
++ * 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.
++ */
++
++static int tcl_setchanseenlang STDVAR
++{
++ Context;
++ BADARGS(3, 3, " channel language");
++ chanlangs = slang_chanlang_add(chanlangs, argv[1], argv[2]);
++ return TCL_OK;
++}
++
++static int tcl_loadseenslang STDVAR
++{
++// int ret = 0;
++ char *shortname, *longname, *filename;
++ struct slang_header *slang;
++
++ Context;
++ BADARGS(4, 4, " language description langfile");
++ shortname = argv[1];
++ longname = argv[2];
++ filename = argv[3];
++ coreslangs = slang_create(coreslangs, shortname, longname);
++ slang = slang_find(coreslangs, shortname);
++ Assert(slang);
++ if (!slang_load(slang, filename)) {
++ Tcl_AppendResult(irp, "Couldn't open seenslang file!!!", NULL);
++ return TCL_ERROR;
++ }
++ return TCL_OK;
++}
++
++static tcl_cmds gseentcls[] =
++{
++ {"loadseenslang", tcl_loadseenslang},
++ {"setchanseenlang", tcl_setchanseenlang},
++ {0, 0}
++};
diff --git a/main/eggdrop/logs2html.mod.patch b/main/eggdrop/logs2html.mod.patch
new file mode 100644
index 0000000000..8ea2e94e62
--- /dev/null
+++ b/main/eggdrop/logs2html.mod.patch
@@ -0,0 +1,2404 @@
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/Makefile eggdrop1.6.19/src/mod/logs2html.mod/Makefile
+--- src/mod/logs2html.mod/Makefile 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/Makefile 2009-03-28 01:32:21.000000000 +0000
+@@ -0,0 +1,42 @@
++# Makefile for src/mod/logs2html.mod/
++
++srcdir = .
++
++
++doofus:
++ @echo ""
++ @echo "Let's try this from the right directory..."
++ @echo ""
++ @cd ../../../ && make
++
++static: ../logs2html.o
++
++modules: ../../../logs2html.$(MOD_EXT)
++
++../logs2html.o:
++ $(CC) $(CFLAGS) $(CPPFLAGS) -DMAKING_MODS -c $(srcdir)/logs2html.c
++ @rm -f ../logs2html.o
++ mv logs2html.o ../
++
++../../../logs2html.$(MOD_EXT): ../logs2html.o
++ $(LD) -o ../../../logs2html.$(MOD_EXT) ../logs2html.o
++ $(STRIP) ../../../logs2html.$(MOD_EXT)
++
++depend:
++ $(CC) $(CFLAGS) $(CPPFLAGS) -MM $(srcdir)/logs2html.c > .depend
++
++clean:
++ @rm -f .depend *.o *.$(MOD_EXT) *~
++distclean: clean
++
++#safety hash
++../logs2html.o: .././logs2html.mod/logs2html.c \
++ ../../../src/mod/module.h ../../../src/main.h ../../../src/lang.h \
++ ../../../src/eggdrop.h ../../../src/flags.h ../../../src/proto.h \
++ ../../../lush.h ../../../src/misc_file.h ../../../src/cmdt.h \
++ ../../../src/tclegg.h ../../../src/tclhash.h ../../../src/chan.h \
++ ../../../src/users.h ../../../src/compat/compat.h \
++ ../../../src/compat/inet_aton.h \
++ ../../../src/compat/snprintf.h ../../../src/compat/memset.h \
++ ../../../src/compat/memcpy.h ../../../src/compat/strcasecmp.h \
++ ../../../src/compat/strftime.h ../../../src/mod/modvals.h
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/chan.list eggdrop1.6.19/src/mod/logs2html.mod/chan.list
+--- src/mod/logs2html.mod/chan.list 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/chan.list 2009-03-28 01:43:40.000000000 +0000
+@@ -0,0 +1,22 @@
++# Add your channels here. The format is:
++# addlogs2htmlchan channel output-path main-page-name main-page-title logs-page-prefix logs-page-title
++# channel - your channel which logs you want to convert
++# output-path - your ftp path, where converted files will be put
++# (don't forget to check settings to be sure bot have
++# permision write to the path you specify)
++# main-page-name - name of your mainpage (i.e. page with calendar) for
++# this channel
++# main-page-title - your mainpage title for this channel (will be shown
++# as the caption of the web page in your browser and as
++# the title of calendar)
++# logs-page-prefix - your logs page name (prefix) for this channel.
++# Resulting name'll be 'logs-page-prefixYYmmdd'
++# logs-page-title - your logs page title for this channel (will be shown
++# as the caption of the web page in your browser)
++# Example:
++# addlogs2htmlchan "#MyChan" "logs" "index" "Logs of MyChan" "mychan" "Log of MyChan"
++#
++# Note: expression "logs2html" MUST be one line (i.e. without linefeeds
++# and carrige returns) and every parameter in the expression MUST be enclosed
++# with ".
++
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/fileoperations.c eggdrop1.6.19/src/mod/logs2html.mod/fileoperations.c
+--- src/mod/logs2html.mod/fileoperations.c 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/fileoperations.c 2009-03-28 01:45:19.000000000 +0000
+@@ -0,0 +1,142 @@
++/*
++ * fileoperations.c -- part of logs2html.mod
++ *
++ * Written by Fedotov Alexander aka Gray_Angel aka Shmupsik <shurikvz@mail.ru>
++ *
++ * 2004-2005 year
++ */
++/*
++ * 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 <stdarg.h>
++
++/****************************************************************************/
++/*
++ * function FILE *openfile(char *newfilename, const char *mode, bool silent)
++ *
++ * Input:
++ * newfilename - èìÿ ôàéëà, êîòîðûé íåîáõîäèìî ñîçäàòü
++ * mode - ðåæèì îòêðûòèÿ ôàéëà
++ *
++ * Output:
++ * óêàçàòåëü íà ôàéë
++ *
++ * Discription:
++ * ôóíêöèÿ îñóùåñòâëÿåò ñîçäàíèå è îòêðûòèå ôàéëà â óêàçàííîì ðåæèìå
++ * è âîçâðàùàåò óêàçàòåëü íà ñîçäàííûé ôàéë
++ */
++static FILE *openfile(char *newfilename, const char *mode, bool silent) {
++ FILE *file;
++ static char *filename = NULL;
++
++ Context;
++
++ filename = (char *)nmalloc(sizeof(char) * (strlen(newfilename) + 1));
++
++ if (filename == NULL) {
++ putlog(LOG_MISC, "*", "logs2html: ERROR! Can't allocate enough space for filename.");
++ return NULL;
++ }
++
++ sprintf(filename, "%s", newfilename);
++ file = fopen(filename, mode);
++ if ((file == NULL) && (!silent)) {
++ putlog(LOG_MISC, "*", "logs2html: Warning! Can't open file \"%s\".", filename);
++ }
++
++ nfree(filename); filename = NULL;
++
++ return file;
++} /* openfile() */
++/****************************************************************************/
++
++
++/****************************************************************************/
++/*
++ * function void writefromexfile(FILE *dst_file, char *exfilename)
++ *
++ * Input:
++ *
++ *
++ *
++ *
++ * Output:
++ *
++ *
++ * Discription:
++ *
++ *
++ */
++static void writefromexfile(FILE *dst_file, char *exfilename) {
++ FILE *addfile;
++ char buffer[512];
++ size_t n;
++
++ if (strlen(exfilename) > 0) {
++ if ((addfile = openfile(exfilename, "r", false)) != NULL) {
++ while(!feof(addfile)) {
++ n = fread(buffer, sizeof(char), sizeof buffer, addfile);
++ fwrite(buffer, sizeof(char), n, dst_file);
++ }
++ fclose(addfile);
++ }
++ }
++
++ return;
++} /* writefromexfile() */
++/****************************************************************************/
++
++
++/****************************************************************************/
++/*
++ * function void str_write(FILE *file, char *fmt, ... )
++ *
++ * Input:
++ * file - ôàéë â êîòîðûé ïèøåì äàííûå
++ * fmt - ñòðîêà äëÿ çàïèñè ñî ñïåöèôèêàòîðàìè ôîðìàòà
++ * ... - äàííûå äëÿ çàïèñè â ñòðîêó
++ *
++ * Output:
++ * íè÷åãî
++ *
++ * Discription:
++ * ôóíêöèÿ îñóùåñòâëÿåò çàïèñü ïåðåäàííîé ñòðîêè â óêàçàííûé ôàéë,
++ * ïðîèçâîäÿ ñîîòâåòñòâóþùåå åå ôîðìàòèðîâàíèå
++ */
++static void str_write(FILE *file, char *fstr, ... ) {
++ va_list ap;
++ int nchars;
++ int size = 256;
++ static char *buffer = NULL;
++
++ Context;
++ buffer = (char *)nmalloc(size);
++
++ va_start(ap, fstr);
++ while (true) {
++ nchars = egg_vsnprintf(buffer, size, fstr, ap);
++ if (nchars < size) break;
++ size *= 2;
++ buffer = (char *)nrealloc(buffer, size);
++ }
++ va_end(ap);
++ fwrite(buffer, sizeof(char), strlen(buffer), file);
++ nfree(buffer); buffer = NULL;
++
++ return;
++} /* str_write() */
++/****************************************************************************/
++
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/help/logs2html.help eggdrop1.6.19/src/mod/logs2html.mod/help/logs2html.help
+--- src/mod/logs2html.mod/help/logs2html.help 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/help/logs2html.help 2009-03-28 01:32:21.000000000 +0000
+@@ -0,0 +1,22 @@
++%{help=convertalllogs}%{+n}
++### %bconvertalllogs%b
++ Reconverts all your logs.
++
++See also: makemainpage
++%{help=makemainpage}%{+n}
++### %bmakemainpage%b
++ Redraws your mainpages.
++
++See also: convertalllogs
++%{help=logs2html module}%{+n}
++### %blogs2html module%b
++ This module convert all existing log files of your eggdrop for giving
++ channels to their html representation.
++
++ The following commands are provided by the logs2html module:
++%{+n}
++ %bconvertalllogs makemainpage%b
++%{help=all}%{+n}
++### %blogs2html module%b commands
++%{+n}
++ %bconvertalllogs makemainpage%b
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/language/logs2html.english.lang eggdrop1.6.19/src/mod/logs2html.mod/language/logs2html.english.lang
+--- src/mod/logs2html.mod/language/logs2html.english.lang 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/language/logs2html.english.lang 2009-03-28 01:32:53.000000000 +0000
+@@ -0,0 +1,38 @@
++# logs2html.english.lang
++# language messages for the logs2html module
++
++# Year
++0xe000,year
++
++# Back to mainpage link
++0xe001,Main page
++
++# Up link
++0xe002,up
++
++# Backward, forward link
++0xe003,back
++0xe004,next
++
++# Month names
++0xe005,January
++0xe006,February
++0xe007,March
++0xe008,April
++0xe009,May
++0xe010,June
++0xe011,July
++0xe012,August
++0xe013,September
++0xe014,October
++0xe015,November
++0xe016,December
++
++# Days of week names
++0xe017,Su
++0xe018,Mo
++0xe019,Tu
++0xe020,Wn
++0xe021,Th
++0xe022,Fr
++0xe023,St
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/language/logs2html.french.lang eggdrop1.6.19/src/mod/logs2html.mod/language/logs2html.french.lang
+--- src/mod/logs2html.mod/language/logs2html.french.lang 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/language/logs2html.french.lang 2009-03-28 01:32:53.000000000 +0000
+@@ -0,0 +1,38 @@
++# logs2html.french.lang
++# language messages for the logs2html module
++
++# Year
++0xe000,Année
++
++# Back to mainpage link
++0xe001,Page principale
++
++# Up link
++0xe002,haut
++
++# Backward, forward link
++0xe003,Précédente
++0xe004,Suivante
++
++# Month names
++0xe005,Janvier
++0xe006,Février
++0xe007,Mars
++0xe008,Avril
++0xe009,Mai
++0xe010,Juin
++0xe011,Juillet
++0xe012,Août
++0xe013,Septembre
++0xe014,Octobre
++0xe015,Novembre
++0xe016,Décembre
++
++# Days of week names
++0xe017,Di
++0xe018,Lu
++0xe019,Ma
++0xe020,Me
++0xe021,Je
++0xe022,Ve
++0xe023,Sa
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/language/logs2html.russian.lang eggdrop1.6.19/src/mod/logs2html.mod/language/logs2html.russian.lang
+--- src/mod/logs2html.mod/language/logs2html.russian.lang 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/language/logs2html.russian.lang 2009-03-28 01:32:21.000000000 +0000
+@@ -0,0 +1,38 @@
++# logs2html.ru.lang
++# language messages for the logs2html module
++
++# Year
++0xe000,ãîä
++
++# Back to mainpage link
++0xe001,Íà ãëàâíóþ ñòðàíèöó
++
++# Up link
++0xe002,íàâåðõ
++
++# Backward, forward link
++0xe003,ïðåäûäóùàÿ
++0xe004,ñëåäóþùàÿ
++
++# Month names
++0xe005,ßíâàðü
++0xe006,Ôåâðàëü
++0xe007,Ìàðò
++0xe008,Àïðåëü
++0xe009,Ìàé
++0xe010,Èþíü
++0xe011,Èþëü
++0xe012,Àâãóñò
++0xe013,Ñåíòÿáðü
++0xe014,Îêòÿáðü
++0xe015,Íîÿáðü
++0xe016,Äåêàáðü
++
++# Days of week names
++0xe017,Âñ
++0xe018,Ïí
++0xe019,Âò
++0xe020,Ñð
++0xe021,×ò
++0xe022,Ïò
++0xe023,Ñá
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/language.h eggdrop1.6.19/src/mod/logs2html.mod/language.h
+--- src/mod/logs2html.mod/language.h 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/language.h 2009-03-28 01:32:21.000000000 +0000
+@@ -0,0 +1,51 @@
++/*
++ * language.h -- part of logs2html.mod
++ *
++ * Written by Fedotov Alexander aka Gray_Angel aka Shmupsik <shurikvz@mail.ru>
++ *
++ * 2004-2005 year
++ */
++/*
++ * 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 LOGS2HTML_YEAR get_language(0xe000)
++#define LOGS2HTML_MAINPAGE get_language(0xe001)
++#define LOGS2HTML_UP get_language(0xe002)
++#define LOGS2HTML_BACK get_language(0xe003)
++#define LOGS2HTML_NEXT get_language(0xe004)
++
++#define LOGS2HTML_JANUARY get_language(0xe005)
++#define LOGS2HTML_FEBRIARY get_language(0xe006)
++#define LOGS2HTML_MARCH get_language(0xe007)
++#define LOGS2HTML_APRIL get_language(0xe008)
++#define LOGS2HTML_MAY get_language(0xe009)
++#define LOGS2HTML_JUNE get_language(0xe010)
++#define LOGS2HTML_JULY get_language(0xe011)
++#define LOGS2HTML_AUGUST get_language(0xe012)
++#define LOGS2HTML_SEPTEMBER get_language(0xe013)
++#define LOGS2HTML_OCTOBER get_language(0xe014)
++#define LOGS2HTML_NOVEMBER get_language(0xe015)
++#define LOGS2HTML_DECEMBER get_language(0xe016)
++
++#define LOGS2HTML_SUNDAY get_language(0xe017)
++#define LOGS2HTML_MONDAY get_language(0xe018)
++#define LOGS2HTML_TUESDAY get_language(0xe019)
++#define LOGS2HTML_WEDNESDAY get_language(0xe020)
++#define LOGS2HTML_THURSDAY get_language(0xe021)
++#define LOGS2HTML_FRIDAY get_language(0xe022)
++#define LOGS2HTML_SATURDAY get_language(0xe023)
++
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/logs2html.c eggdrop1.6.19/src/mod/logs2html.mod/logs2html.c
+--- src/mod/logs2html.mod/logs2html.c 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/logs2html.c 2009-03-28 01:32:53.000000000 +0000
+@@ -0,0 +1,1572 @@
++/*
++ * logs2html.c -- part of logs2html.mod
++ *
++ * Written by Fedotov Alexander aka Gray_Angel aka Shmupsik <shurikvz@mail.ru>
++ *
++ * 2004-2005 year
++ */
++/*
++ * 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 MODULE_NAME "logs2html"
++#define MAKING_LOGS2HTML
++#include "src/mod/module.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <time.h>
++#include <ctype.h>
++#include <sys/types.h>
++#include <math.h>
++#include "logs2html.h"
++#include "language.h"
++
++#undef global
++
++#define MODULE_MAJOR 2
++#define MODULE_MINOR 3
++#define MODULE_SUBMINOR 4
++
++static Function *global = NULL;
++
++#include "fileoperations.c"
++
++
++static int shtime;
++static int keep_all_logs;
++static char logfile_suffix[21];
++static char configfile[121];
++static int lines_per_page;
++
++static int days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
++
++static int month_cols_count = 3;
++static int month_rows_count = 4;
++
++static char mainpage_top_filename[257] = "\0";
++static char mainpage_bottom_filename[257] = "\0";
++static char logspage_top_filename[257] = "\0";
++static char logspage_bottom_filename[257] = "\0";
++static char chanlist_filename[257] = "\0";
++static char userstyle_filename[257] = "\0";
++static char encoding_string[31] = "\0";
++
++static logs2htmlchan *logs2htmlchanlist = NULL;
++
++/* for language file */
++static char month_names[12][21];
++static char days_names[7][21];
++
++static void logs2html_hook_5minutely(void);
++static void logs2html_hook_daily(void);
++static void logs2html_hook_pre_rehash(void);
++static void logs2html_hook_rehash(void);
++
++
++/* Calculate the memory we keep allocated.
++ */
++static int logs2html_expmem()
++{
++ logs2htmlchan *p;
++ int size = 0;
++
++ Context;
++ p = logs2htmlchanlist;
++ while (p != NULL) {
++ size++;
++ p = p->next;
++ }
++
++ size *= sizeof(struct logs2html_data);
++
++ return size;
++}
++
++
++/****************************************************************************/
++/*
++ * function int convertalllogs(struct userrec *u, int idx, char *par)
++ *
++ * Input:
++ *
++ *
++ *
++ * Output:
++ *
++ *
++ * Discription:
++ *
++ */
++static int cmd_convertalllogs(struct userrec *u, int idx, char *par) {
++ int add_day;
++ logs2htmlchan *p;
++ int i, j, k;
++ struct tm tblock;
++ time_t t = time(NULL);
++ struct tm *st = localtime(&t);
++
++ tblock.tm_year = st->tm_year;
++ tblock.tm_isdst = st->tm_isdst;
++ tblock.tm_hour = 0;
++ tblock.tm_min = 0;
++ tblock.tm_sec = 1;
++ /* Other fields not necessary here
++ tblock.tm_mday = st->tm_mday;
++ tblock.tm_mon = st->tm_mon;
++ tblock.tm_wday = st->tm_wday;
++ tblock.tm_yday = st->tm_yday;
++ */
++
++ putlog(LOG_CMDS, "*", "#%s# start converting all log files.", dcc[idx].nick);
++ for (i = 0; i < 12; i++) {
++ add_day = ((i == 1) && isleap(tblock.tm_year)) ? 1 : 0;
++ for (j = 0; j < ((days_in_month[i]) + add_day); j++) {
++ tblock.tm_mon = i; tblock.tm_mday = j + 1;
++
++ tblock.tm_wday = (getdayofweek(tblock.tm_year + 1900, tblock.tm_mon + 1, tblock.tm_mday) + 1) % 7;
++ tblock.tm_yday = 0;
++ for (k = 0; k < tblock.tm_mon; k++) tblock.tm_yday += days_in_month[k];
++ tblock.tm_yday += tblock.tm_mday - 1;
++
++ p = logs2htmlchanlist;
++ while (p != NULL) {
++ convertfile(&tblock, p);
++ p = p->next;
++ }
++ }
++ }
++ putlog(LOG_CMDS, "*", "#%s# converting of all log files done.", dcc[idx].nick);
++
++ return 0;
++} /* convertalllogs() */
++/****************************************************************************/
++
++
++/****************************************************************************/
++/*
++ * function int cmd_makemainpage(struct userrec *u, int idx, char *par)
++ *
++ * Input:
++ *
++ *
++ *
++ * Output:
++ *
++ *
++ * Discription:
++ *
++ */
++static int cmd_makemainpage(struct userrec *u, int idx, char *par) {
++ logs2htmlchan *p;
++
++ putlog(LOG_CMDS, "*", "#%s# starting making mainpages.", dcc[idx].nick);
++ p = logs2htmlchanlist;
++ while (p != NULL) {
++ dprintf(idx, "Making mainpage for channel '%s'...\n", p->channame);
++ makemainpage(p);
++ p = p->next;
++ }
++ putlog(LOG_CMDS, "*", "#%s# making of mainpages done.", dcc[idx].nick);
++
++ return 0;
++} /* convertalllogs() */
++/****************************************************************************/
++
++
++/****************************************************************************/
++/*
++ * function bool isvalidlink(char *link)
++ *
++ * Input:
++ * link - ñòðîêà óêàçûâàþùàÿ íà ññûëêó
++ *
++ *
++ * Output:
++ *
++ *
++ * Discription:
++ * Ôóíêöèÿ ïðîâåðÿåò ÿâëÿþòñÿ ëè ïåðåäàííûå â ñòðîêå ñèìâîëû - ñèìâîëàìè
++ * äîïóñòèìûìè â ññûëêàõ
++ */
++static patternkind whatisit(char *pattern) {
++ char alpha_common[] = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789._-";
++ char alpha_http[] = "=?&/:%";
++ char *p;
++
++ if (strstr(pattern, "..") != NULL) {
++ return ITS_NOTHING;
++ }
++
++ p = strchr(pattern, '@');
++ if (p) {
++ /* it's can't be www link */
++
++ /* well, i can't imagine e-mail shorter than i@m.ru */
++ /* let's check it */
++ *p = '\0';
++ if (strlen(pattern) < 1) {
++ *p = '@';
++ return ITS_NOTHING;
++ }
++ while (*pattern) {
++ if (strchr(alpha_common, *pattern) == NULL) {
++ *p = '@';
++ return ITS_NOTHING;
++ }
++ pattern++;
++ }
++ *p = '@';
++ p++;
++ if (strlen(p) < 4) {
++ return ITS_NOTHING;
++ }
++ while (*p) {
++ if (strchr(alpha_common, *p) == NULL) return ITS_NOTHING;
++ p++;
++ }
++
++ return ITS_EMAIL;
++ } else {
++ if ((strncmp(pattern, "http://", 7) != 0) && (strncmp(pattern, "ftp://", 6) != 0)) {
++ if (strncmp(pattern, "www.", 4) != 0) {
++ return ITS_NOTHING;
++ } else {
++ while (*pattern) {
++ if ((strchr(alpha_common, *pattern) == NULL) && (strchr(alpha_http, *pattern) == NULL)) return ITS_NOTHING;
++ pattern++;
++ }
++
++ return ITS_TRUNKLINK;
++ }
++ }
++
++ while (*pattern) {
++ if ((strchr(alpha_common, *pattern) == NULL) && (strchr(alpha_http, *pattern) == NULL)) return ITS_NOTHING;
++ pattern++;
++ }
++
++ return ITS_LINK;
++ }
++
++ return ITS_NOTHING;
++} /* whatisit() */
++/****************************************************************************/
++
++
++/* A report on the module status.
++ *
++ * details is either 0 or 1:
++ * 0 - `.status'
++ * 1 - `.status all' or `.module woobie'
++ */
++static void logs2html_report(int idx, int details)
++{
++ if (details) {
++ int size = logs2html_expmem();
++
++ dprintf(idx, " Using %d byte%s of memory\n", size,
++ (size != 1) ? "s" : "");
++ }
++}
++
++static cmd_t mydcc[] = {
++ {"convertalllogs", "n", cmd_convertalllogs, NULL},
++ {"makemainpage", "n", cmd_makemainpage, NULL},
++ {NULL, NULL, NULL, NULL} /* Mark end. */
++};
++
++static tcl_strings my_tcl_strings[] = {
++ {"logfile-suffix", logfile_suffix, 20, STR_PROTECT},
++ {"config", configfile, 121, STR_PROTECT},
++ {"mainpage-top", mainpage_top_filename, 256, 0},
++ {"mainpage-bottom", mainpage_bottom_filename, 256, 0},
++ {"logspage-top", logspage_top_filename, 256, 0},
++ {"logspage-bottom", logspage_bottom_filename, 256, 0},
++ {"channels-list", chanlist_filename, 256, 0},
++ {"user-style", userstyle_filename, 256, 0},
++ {"insert-encoding-str", encoding_string, 30, 0},
++ {NULL, NULL, 0, 0} /* Mark end. */
++};
++
++static tcl_ints my_tcl_ints[] = {
++ {"col-count", &month_cols_count, 0},
++ {"lines-per-page", &lines_per_page, 0},
++ {"log-time", &shtime, 1},
++ {"keep-all-logs", &keep_all_logs, 1},
++ {NULL, NULL, 0} /* Mark end. */
++};
++
++static char *logs2html_close()
++{
++ logs2htmlchan *p, *q;
++
++ Context;
++ q = p = logs2htmlchanlist;
++ while (q != NULL) {
++ q = p->next;
++ nfree(p);
++ p = q;
++ }
++ logs2htmlchanlist = p = q = NULL;
++
++ del_lang_section(MODULE_NAME);
++ rem_help_reference(MODULE_NAME ".help");
++
++ del_hook(HOOK_DAILY, (Function)logs2html_hook_daily);
++ del_hook(HOOK_5MINUTELY, (Function)logs2html_hook_5minutely);
++ del_hook(HOOK_PRE_REHASH, (Function)logs2html_hook_pre_rehash);
++ del_hook(HOOK_REHASH, (Function)logs2html_hook_rehash);
++
++ rem_builtins(H_dcc, mydcc);
++ rem_tcl_ints(my_tcl_ints);
++ rem_tcl_strings(my_tcl_strings);
++
++ module_undepend(MODULE_NAME);
++ return NULL;
++}
++
++EXPORT_SCOPE char *logs2html_start();
++
++static Function logs2html_table[] = {
++ (Function) logs2html_start,
++ (Function) logs2html_close,
++ (Function) logs2html_expmem,
++ (Function) logs2html_report,
++};
++
++char *logs2html_start(Function *global_funcs)
++{
++ logs2htmlchan *ptr;
++
++ global = global_funcs;
++
++ Context;
++ /* Register the module. */
++ module_register(MODULE_NAME, logs2html_table, MODULE_MAJOR, MODULE_MINOR);
++
++ if (!module_depend(MODULE_NAME, "eggdrop", 106, 15)) {
++ module_undepend(MODULE_NAME);
++ return "This module requires Eggdrop 1.6.15 or later.";
++ }
++
++ add_tcl_ints(my_tcl_ints);
++
++ if (!keep_all_logs) {
++ rem_tcl_ints(my_tcl_ints);
++ module_undepend(MODULE_NAME);
++ return "This module requires \"keep-all-logs\" set to \"1\". Please check settings in your config file.";
++ }
++ logs2htmlchanlist = NULL; if (lines_per_page < 0) lines_per_page = 0;
++
++ add_tcl_strings(my_tcl_strings);
++
++ if (addchannels()) {
++ ptr = logs2htmlchanlist;
++ while (ptr != NULL) {
++ putlog(LOG_CMDS, "*", "logs2html: added channel %s, with path to logfiles \"%s\"...\n", ptr->channame, ptr->logfilename);
++ ptr = ptr->next;
++ }
++ } else {
++ rem_tcl_strings(my_tcl_strings);
++ rem_tcl_ints(my_tcl_ints);
++ module_undepend(MODULE_NAME);
++ return "No channels added. Please check settings in your eggdrop config file to be sure there is logfiles with mode set to \"p\".";
++ }
++
++ add_builtins(H_dcc, mydcc);
++
++ add_hook(HOOK_5MINUTELY, (Function)logs2html_hook_5minutely); //Äëÿ îáíîâëåíèÿ ëîãà çà òåêóùèé äåíü
++ add_hook(HOOK_DAILY, (Function)logs2html_hook_daily); //Ïîñëåäíèå 5 ìèíóò çà ïðîøëûé äåíü
++ add_hook(HOOK_PRE_REHASH, (Function)logs2html_hook_pre_rehash);
++ add_hook(HOOK_REHASH, (Function)logs2html_hook_rehash);
++
++ add_lang_section(MODULE_NAME);
++ add_help_reference(MODULE_NAME ".help");
++
++ month_names[0][0] = month_names[1][0] = month_names[2][0] = month_names[3][0] =
++ month_names[4][0] = month_names[5][0] = month_names[6][0] = month_names[7][0] =
++ month_names[8][0] = month_names[9][0] = month_names[10][0] = month_names[11][0] =
++ days_names[0][0] = days_names[1][0] = days_names[2][0] = days_names[3][0] =
++ days_names[4][0] = days_names[5][0] = days_names[6][0] = '\0';
++
++ strncpyz(month_names[0], LOGS2HTML_JANUARY, sizeof month_names[0]);
++ strncpyz(month_names[1], LOGS2HTML_FEBRIARY, sizeof month_names[1]);
++ strncpyz(month_names[2], LOGS2HTML_MARCH, sizeof month_names[2]);
++ strncpyz(month_names[3], LOGS2HTML_APRIL, sizeof month_names[3]);
++ strncpyz(month_names[4], LOGS2HTML_MAY, sizeof month_names[4]);
++ strncpyz(month_names[5], LOGS2HTML_JUNE, sizeof month_names[5]);
++ strncpyz(month_names[6], LOGS2HTML_JULY, sizeof month_names[6]);
++ strncpyz(month_names[7], LOGS2HTML_AUGUST, sizeof month_names[7]);
++ strncpyz(month_names[8], LOGS2HTML_SEPTEMBER, sizeof month_names[8]);
++ strncpyz(month_names[9], LOGS2HTML_OCTOBER, sizeof month_names[9]);
++ strncpyz(month_names[10], LOGS2HTML_NOVEMBER, sizeof month_names[10]);
++ strncpyz(month_names[11], LOGS2HTML_DECEMBER, sizeof month_names[11]);
++ strncpyz(days_names[0], LOGS2HTML_MONDAY, sizeof days_names[0]);
++ strncpyz(days_names[1], LOGS2HTML_TUESDAY, sizeof days_names[1]);
++ strncpyz(days_names[2], LOGS2HTML_WEDNESDAY, sizeof days_names[2]);
++ strncpyz(days_names[3], LOGS2HTML_THURSDAY, sizeof days_names[3]);
++ strncpyz(days_names[4], LOGS2HTML_FRIDAY, sizeof days_names[4]);
++ strncpyz(days_names[5], LOGS2HTML_SATURDAY, sizeof days_names[5]);
++ strncpyz(days_names[6], LOGS2HTML_SUNDAY, sizeof days_names[6]);
++
++ return NULL;
++}
++
++/*
++ * Code starts here
++ */
++
++/*
++ * getdayofweek()
++ * Input:
++ * year - ãîä
++ * month - ìåñÿö
++ * day - äåíü
++ *
++ * Output:
++ * 0 - Ïîíåäåëüíèê, 1 - Âòîðíèê, 2 - Ñðåäà è.ò.ä.
++ *
++ * Description:
++ * Ôóíêöèÿ âû÷èñëÿåò íà êàêîé äåíü íåäåëè ïðèõîäèòñÿ ïåðåäàííàÿ äàòà
++ */
++static int getdayofweek(int year, int month, int day)
++{
++ long int d1, d2, d3;
++
++ long int tdays = year * 12 + month - 3;
++ month = tdays % 12;
++ year = (tdays - month) / 12;
++
++ d1 = ((146097 * (year - (year % 100)) / 100) - ((146097 * (year - (year % 100)) / 100) % 4)) / 4;
++ d2 = ((1461 * (year % 100)) - ((1461 * (year % 100)) % 4)) / 4;
++ d3 = ((153 * month + 2) - ((153 * month + 2) % 5)) / 5 + day + 1721119;
++
++ return (d1 + d2 + d3) % 7;
++} /* getdayofweek() */
++/****************************************************************************/
++
++
++/****************************************************************************/
++/*
++ * function static int addchannels() {
++ *
++ * Input:
++ *
++ *
++ *
++ *
++ * Output:
++ *
++ *
++ * Discription:
++ *
++ *
++ */
++static int addchannels() {
++ char buffer[512];
++ char *buf_ptr, *p;
++ logs2htmlchan *newchan, *ptr;
++ FILE *src_file;
++ int field_num;
++ int filelineread;
++ int channels_count = 0;
++
++
++ Context;
++ filelineread = 0;
++ if ((src_file = openfile(chanlist_filename, "r", true)) == NULL) return 0;
++ while (!feof(src_file)) {
++ buf_ptr = fgets(buffer, sizeof(buffer)-1, src_file);
++ if (buf_ptr == NULL) break;
++ filelineread++;
++
++ p = strrchr(buf_ptr, '\n');
++ if (p) *p = '\0';
++ p = strrchr(buf_ptr, '\r');
++ if (p) *p = '\0';
++ if (strlen(buf_ptr) == 0) continue;
++ while (isspace(*buf_ptr)) buf_ptr++;
++/* while (egg_isspace(*buf_ptr)) buf_ptr++; */
++ if (strncmp(buf_ptr, "addlogs2htmlchan", 16) == 0) p = buf_ptr += 16; else continue;
++ while (*p++) if (isspace(*p)) *p = ' ';
++/* while (*p++) if (egg_isspace(*p)) *p = ' '; */
++ if (!isspace(*buf_ptr)) continue;
++/* if (!egg_isspace(*buf_ptr)) continue; */
++ /*
++ At that point we have string of params of command "addlogs2htmlchan"
++ pointed by buf_ptr, with leading ' ';
++ */
++
++ newchan = (logs2htmlchan *)nmalloc(sizeof(logs2htmlchan) * 1);
++ if (newchan == NULL) {
++ nfree(newchan); newchan = NULL;
++ fclose(src_file);
++ putlog(LOG_MISC, "*", "Can't allocate enough space to add new channel!");
++ break;
++ }
++
++ newchan->next = NULL;
++ newchan->logfilename[0] = '\0';
++ newchan->channame[0] = '\0';
++ newchan->outputpath[0] = '\0';
++ newchan->mainpagename[0] = '\0';
++ newchan->mainpagetitle[0] = '\0';
++ newchan->logspagename[0] = '\0';
++ newchan->logspagetitle[0] = '\0';
++
++ field_num = 0;
++ while (*buf_ptr) {
++ while ((*buf_ptr) && (*buf_ptr == ' ')) buf_ptr++;
++ p = ++buf_ptr;
++ while ((*p) && (*p != '"')) p++;
++ *p = '\0';
++ switch (field_num) {
++ case 0: /* newchan->channame */
++ strncpyz(newchan->channame, buf_ptr, sizeof newchan->channame);
++ field_num = 1;
++ break;
++ case 1: /* newchan->outputpath */
++ strncpyz(newchan->outputpath, buf_ptr, sizeof newchan->outputpath);
++ field_num = 2;
++ break;
++ case 2: /* newchan->mainpagename */
++ strncpyz(newchan->mainpagename, buf_ptr, sizeof newchan->mainpagename);
++ field_num = 3;
++ break;
++ case 3: /* newchan->mainpagetitle */
++ strncpyz(newchan->mainpagetitle, buf_ptr, sizeof newchan->mainpagetitle);
++ field_num = 4;
++ break;
++ case 4: /* newchan->logspagename */
++ strncpyz(newchan->logspagename, buf_ptr, sizeof newchan->logspagename);
++ field_num = 5;
++ break;
++ case 5: /* newchan->logspagetitle */
++ strncpyz(newchan->logspagetitle, buf_ptr, sizeof newchan->logspagetitle);
++ field_num = 6;
++ break;
++ }
++ buf_ptr = ++p;
++ }
++
++
++ if (field_num != 6) {
++ nfree(newchan); newchan = NULL;
++ putlog(LOG_MISC, "*", "Error in file %s. String %d. Invalid expression \"addlogs2htmlchan\".", chanlist_filename, filelineread);
++ continue;
++ }
++
++ ptr = logs2htmlchanlist;
++ if (ptr == NULL) {
++ logs2htmlchanlist = newchan;
++ } else {
++ while (ptr->next != NULL) {
++ ptr = ptr->next;
++ }
++ ptr->next = newchan;
++ }
++ newchan = NULL;
++
++ }
++ fclose(src_file);
++
++ if ((src_file = openfile(configfile, "r", true)) == NULL) return 0;
++ while (!feof(src_file)) {
++ buf_ptr = fgets(buffer, sizeof(buffer)-1, src_file);
++ if (buf_ptr == NULL) break;
++
++ p = strrchr(buf_ptr, '\n');
++ if (p) *p = '\0';
++ p = strrchr(buf_ptr, '\r');
++ if (p) *p = '\0';
++ if (strlen(buf_ptr) == 0) continue;
++ while (isspace(*buf_ptr)) buf_ptr++;
++/* while (egg_isspace(*buf_ptr)) buf_ptr++; */
++ if (strncmp(buf_ptr, "logfile", 7) == 0) p = buf_ptr += 7; else continue;
++ while (*p++) if (isspace(*p)) *p = ' ';
++/* while (*p++) if (egg_isspace(*p)) *p = ' '; */
++ if (!isspace(*buf_ptr)) continue;
++/* if (!egg_isspace(*buf_ptr)) continue; */
++ /*
++ At that point we have string of params of command "logfile"
++ pointed by buf_ptr, with leading ' ';
++ */
++
++ p = newsplit(&buf_ptr);
++ if (logmodes(p) & LOG_PUBLIC) {
++ p = newsplit(&buf_ptr);
++ /*
++ At that point we have channel of command "logfile" pointed by p,
++ and the rest of the string (path to file), pointed by buf_ptr and enclosed with "
++ */
++ buf_ptr++; buf_ptr[strlen(buf_ptr)-1] = '\0';
++
++ ptr = logs2htmlchanlist;
++ while (ptr != NULL) {
++ if ((*p == '*') || (!rfc_casecmp(ptr->channame, p))) {
++ egg_snprintf(ptr->logfilename, sizeof ptr->logfilename, "%s", buf_ptr);
++ }
++ ptr = ptr->next;
++ }
++ }
++
++
++ }
++ fclose(src_file);
++
++
++ while (logs2htmlchanlist != NULL) {
++ if (strlen(logs2htmlchanlist->logfilename) == 0) {
++ ptr = logs2htmlchanlist;
++ logs2htmlchanlist = logs2htmlchanlist->next;
++ nfree(ptr);
++ } else {
++ ptr = logs2htmlchanlist;
++ while (ptr->next != NULL) {
++ if (strlen(ptr->next->logfilename) == 0) {
++ newchan = ptr->next;
++ ptr->next = ptr->next->next;
++ nfree(newchan);
++ } else {
++ ptr = ptr->next;
++ }
++ }
++ break;
++ }
++ }
++
++ ptr = logs2htmlchanlist;
++ while (ptr != NULL) {
++ channels_count++;
++ ptr = ptr->next;
++ }
++
++ ptr = newchan = NULL;
++
++ return channels_count;
++} /* addchannels() */
++/****************************************************************************/
++
++
++/****************************************************************************/
++/*
++ * function int convertfile(int year, int month, int day, bool convertifexists)
++ *
++ * Input:
++ *
++ *
++ *
++ * Output:
++ *
++ *
++ * Discription:
++ * ïåðåâîäèò ôàéëû èç òåêñòîâîãî âèäà â ôîðìàò HTML
++ */
++static void convertfile(struct tm *t, logs2htmlchan *ch) {
++ char *buf_ptr, *p, *q, *r;
++ char buffer[LOGLINELEN], data[LOGLINELEN], ct[81], stamp[33];
++ char f_color[3], bg_color[3], text_style[6];
++ int mc_openteg_count = 0, pages_count = 0;
++ int i, j, k, lines_count, tsl;
++ char src_filename[257], dst_filename[257];
++ FILE *src_file, *dst_file;
++ bool bold_isopen, underline_isopen;
++ bool noneedtoclose, skipemail, linkfound;
++ char openspace[3] = " ( ";
++ char closespace[3] = " ),";
++ char *cuted_string = NULL;
++ int cuted_string_len, old_cuted_string_len, delta_cuted_string_len;
++ int r_offset, q_offset;
++ int *original_idx = NULL;
++
++ Context;
++ /* Let first write our default CSS file */
++ egg_snprintf(dst_filename, sizeof dst_filename, "%s%sdefault.css", ch->outputpath, SEP);
++ if ((dst_file = openfile(dst_filename, "wb", false)) != NULL) {
++ str_write(dst_file, "BODY {\n");
++ str_write(dst_file, "font-family: serif;\n");
++ str_write(dst_file, "font-style: normal\n");
++ str_write(dst_file, "font-variant: normal;\n");
++ str_write(dst_file, "font-weight: normal;\n");
++ str_write(dst_file, "font-stretch: normal;\n");
++ str_write(dst_file, "font-size: 12pt;\n");
++ str_write(dst_file, "text-align: left;\n");
++ str_write(dst_file, "color: rgb(0,0,0);\n");
++ str_write(dst_file, "background-color: transparent;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "BODY.mainpage {\n");
++ str_write(dst_file, "background-color: whitesmoke;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "BODY.logspage {\n");
++ str_write(dst_file, "background-color: lightyellow;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "TD {\n");
++ str_write(dst_file, "width: %d%%;\n", (int)floor(100.0/((double)month_cols_count * 8)));
++ str_write(dst_file, "background-color: lavender;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "TD.space {\n");
++ str_write(dst_file, "width: auto;\n");
++ str_write(dst_file, "background-color: whitesmoke;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "TD.dayname {\n");
++ str_write(dst_file, "width: auto;\n");
++ str_write(dst_file, "font-weight: bold;\n");
++ str_write(dst_file, "text-align: right;\n");
++ str_write(dst_file, "background-color: lightskyblue;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "TD.weekend {\n");
++ str_write(dst_file, "width: auto;\n");
++ str_write(dst_file, "font-weight: bold;\n");
++ str_write(dst_file, "text-align: right;\n");
++ str_write(dst_file, "color: red;\n");
++ str_write(dst_file, "background-color: lightskyblue;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "TH {\n");
++ str_write(dst_file, "font-weight: bold;\n");
++ str_write(dst_file, "text-align: center;\n");
++ str_write(dst_file, "background-color: lavender;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "SPAN.time {\n");
++ str_write(dst_file, "color: silver;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "SPAN.nick {\n");
++ str_write(dst_file, "color: mediumblue;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "SPAN.else {\n");
++ str_write(dst_file, "color: green;\n");
++ str_write(dst_file, "font-style: italic;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "SPAN.action {\n");
++ str_write(dst_file, "color: violet;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "#footer {\n");
++ str_write(dst_file, " font-size: 10px;\n");
++ str_write(dst_file, " text-align: center;\n");
++ str_write(dst_file, " border-top-width: 1px;\n");
++ str_write(dst_file, " border-top-style: solid;\n");
++ str_write(dst_file, " border-color: #CCCCCC;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "h1 {\n");
++ str_write(dst_file, " text-align: center;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "#calendar {\n");
++ str_write(dst_file, " margin-right: auto;\n");
++ str_write(dst_file, " margin-left: auto;\n");
++ str_write(dst_file, " width: 90%;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "#navtop {\n");
++ str_write(dst_file, " text-align: center;\n");
++ str_write(dst_file, " margin-top: 10px;\n");
++ str_write(dst_file, " margin-bottom: 10px;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "#navbottom {\n");
++ str_write(dst_file, " text-align: center;\n");
++ str_write(dst_file, " margin-top: 10px;\n");
++ str_write(dst_file, " margin-bottom: 5px;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "#totop {\n");
++ str_write(dst_file, " text-align: center;\n");
++ str_write(dst_file, " margin-top: 5px;\n");
++ str_write(dst_file, " margin-bottom: 10px;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "#log {\n");
++ str_write(dst_file, " margin-top: 10px;\n");
++ str_write(dst_file, " margin-bottom: 10px;\n");
++ str_write(dst_file, " padding-top: 10px;\n");
++ str_write(dst_file, " padding-bottom: 10px;\n");
++ str_write(dst_file, " border-width: thin;\n");
++ str_write(dst_file, " border-top-style: solid;\n");
++ str_write(dst_file, " border-bottom-style: solid;\n");
++ str_write(dst_file, " border-color: #CCCCCC;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, ".mainpage #title {\n");
++ str_write(dst_file, " font-size: 36px;\n");
++ str_write(dst_file, " text-align: center;\n");
++ str_write(dst_file, " margin-bottom: 20px;\n");
++ str_write(dst_file, " border-width: thin;\n");
++ str_write(dst_file, " border-color: #CCCCCC;\n");
++ str_write(dst_file, " border-bottom-style: solid;\n");
++ str_write(dst_file, "}\n");
++ str_write(dst_file, "SPAN.c0000, SPAN.c0100, SPAN.c0200, SPAN.c0300, SPAN.c0400, SPAN.c0500, SPAN.c0600, SPAN.c0700, SPAN.c0800, SPAN.c0900, SPAN.c1000, SPAN.c1100, SPAN.c1200, SPAN.c1300, SPAN.c1400, SPAN.c1500 {background-color: white;}\n");
++ str_write(dst_file, "SPAN.c0001, SPAN.c0101, SPAN.c0201, SPAN.c0301, SPAN.c0401, SPAN.c0501, SPAN.c0601, SPAN.c0701, SPAN.c0801, SPAN.c0901, SPAN.c1001, SPAN.c1101, SPAN.c1201, SPAN.c1301, SPAN.c1401, SPAN.c1501 {background-color: black;}\n");
++ str_write(dst_file, "SPAN.c0002, SPAN.c0102, SPAN.c0202, SPAN.c0302, SPAN.c0402, SPAN.c0502, SPAN.c0602, SPAN.c0702, SPAN.c0802, SPAN.c0902, SPAN.c1002, SPAN.c1102, SPAN.c1202, SPAN.c1302, SPAN.c1402, SPAN.c1502 {background-color: navy;}\n");
++ str_write(dst_file, "SPAN.c0003, SPAN.c0103, SPAN.c0203, SPAN.c0303, SPAN.c0403, SPAN.c0503, SPAN.c0603, SPAN.c0703, SPAN.c0803, SPAN.c0903, SPAN.c1003, SPAN.c1103, SPAN.c1203, SPAN.c1303, SPAN.c1403, SPAN.c1503 {background-color: green;}\n");
++ str_write(dst_file, "SPAN.c0004, SPAN.c0104, SPAN.c0204, SPAN.c0304, SPAN.c0404, SPAN.c0504, SPAN.c0604, SPAN.c0704, SPAN.c0804, SPAN.c0904, SPAN.c1004, SPAN.c1104, SPAN.c1204, SPAN.c1304, SPAN.c1404, SPAN.c1504 {background-color: red;}\n");
++ str_write(dst_file, "SPAN.c0005, SPAN.c0105, SPAN.c0205, SPAN.c0305, SPAN.c0405, SPAN.c0505, SPAN.c0605, SPAN.c0705, SPAN.c0805, SPAN.c0905, SPAN.c1005, SPAN.c1105, SPAN.c1205, SPAN.c1305, SPAN.c1405, SPAN.c1505 {background-color: maroon;}\n");
++ str_write(dst_file, "SPAN.c0006, SPAN.c0106, SPAN.c0206, SPAN.c0306, SPAN.c0406, SPAN.c0506, SPAN.c0606, SPAN.c0706, SPAN.c0806, SPAN.c0906, SPAN.c1006, SPAN.c1106, SPAN.c1206, SPAN.c1306, SPAN.c1406, SPAN.c1506 {background-color: purple;}\n");
++ str_write(dst_file, "SPAN.c0007, SPAN.c0107, SPAN.c0207, SPAN.c0307, SPAN.c0407, SPAN.c0507, SPAN.c0607, SPAN.c0707, SPAN.c0807, SPAN.c0907, SPAN.c1007, SPAN.c1107, SPAN.c1207, SPAN.c1307, SPAN.c1407, SPAN.c1507 {background-color: orange;}\n");
++ str_write(dst_file, "SPAN.c0008, SPAN.c0108, SPAN.c0208, SPAN.c0308, SPAN.c0408, SPAN.c0508, SPAN.c0608, SPAN.c0708, SPAN.c0808, SPAN.c0908, SPAN.c1008, SPAN.c1108, SPAN.c1208, SPAN.c1308, SPAN.c1408, SPAN.c1508 {background-color: yellow;}\n");
++ str_write(dst_file, "SPAN.c0009, SPAN.c0109, SPAN.c0209, SPAN.c0309, SPAN.c0409, SPAN.c0509, SPAN.c0609, SPAN.c0709, SPAN.c0809, SPAN.c0909, SPAN.c1009, SPAN.c1109, SPAN.c1209, SPAN.c1309, SPAN.c1409, SPAN.c1509 {background-color: lime;}\n");
++ str_write(dst_file, "SPAN.c0010, SPAN.c0110, SPAN.c0210, SPAN.c0310, SPAN.c0410, SPAN.c0510, SPAN.c0610, SPAN.c0710, SPAN.c0810, SPAN.c0910, SPAN.c1010, SPAN.c1110, SPAN.c1210, SPAN.c1310, SPAN.c1410, SPAN.c1510 {background-color: teal;}\n");
++ str_write(dst_file, "SPAN.c0011, SPAN.c0111, SPAN.c0211, SPAN.c0311, SPAN.c0411, SPAN.c0511, SPAN.c0611, SPAN.c0711, SPAN.c0811, SPAN.c0911, SPAN.c1011, SPAN.c1111, SPAN.c1211, SPAN.c1311, SPAN.c1411, SPAN.c1511 {background-color: cyan;}\n");
++ str_write(dst_file, "SPAN.c0012, SPAN.c0112, SPAN.c0212, SPAN.c0312, SPAN.c0412, SPAN.c0512, SPAN.c0612, SPAN.c0712, SPAN.c0812, SPAN.c0912, SPAN.c1012, SPAN.c1112, SPAN.c1212, SPAN.c1312, SPAN.c1412, SPAN.c1512 {background-color: blue;}\n");
++ str_write(dst_file, "SPAN.c0013, SPAN.c0113, SPAN.c0213, SPAN.c0313, SPAN.c0413, SPAN.c0513, SPAN.c0613, SPAN.c0713, SPAN.c0813, SPAN.c0913, SPAN.c1013, SPAN.c1113, SPAN.c1213, SPAN.c1313, SPAN.c1413, SPAN.c1513 {background-color: magenta;}\n");
++ str_write(dst_file, "SPAN.c0014, SPAN.c0114, SPAN.c0214, SPAN.c0314, SPAN.c0414, SPAN.c0514, SPAN.c0614, SPAN.c0714, SPAN.c0814, SPAN.c0914, SPAN.c1014, SPAN.c1114, SPAN.c1214, SPAN.c1314, SPAN.c1414, SPAN.c1514 {background-color: silver;}\n");
++ str_write(dst_file, "SPAN.c0015, SPAN.c0115, SPAN.c0215, SPAN.c0315, SPAN.c0415, SPAN.c0515, SPAN.c0615, SPAN.c0715, SPAN.c0815, SPAN.c0915, SPAN.c1015, SPAN.c1114, SPAN.c1215, SPAN.c1315, SPAN.c1415, SPAN.c1515 {background-color: gray;}\n");
++ str_write(dst_file, "SPAN.c0000, SPAN.c0001, SPAN.c0002, SPAN.c0003, SPAN.c0004, SPAN.c0005, SPAN.c0006, SPAN.c0007, SPAN.c0008, SPAN.c0009, SPAN.c0010, SPAN.c0011, SPAN.c0012, SPAN.c0013, SPAN.c0014, SPAN.c0015 {color: white;}\n");
++ str_write(dst_file, "SPAN.c0100, SPAN.c0101, SPAN.c0102, SPAN.c0103, SPAN.c0104, SPAN.c0105, SPAN.c0106, SPAN.c0107, SPAN.c0108, SPAN.c0109, SPAN.c0110, SPAN.c0111, SPAN.c0112, SPAN.c0113, SPAN.c0114, SPAN.c0115 {color: black;}\n");
++ str_write(dst_file, "SPAN.c0200, SPAN.c0201, SPAN.c0202, SPAN.c0203, SPAN.c0204, SPAN.c0205, SPAN.c0206, SPAN.c0207, SPAN.c0208, SPAN.c0209, SPAN.c0210, SPAN.c0211, SPAN.c0212, SPAN.c0213, SPAN.c0214, SPAN.c0215 {color: navy;}\n");
++ str_write(dst_file, "SPAN.c0300, SPAN.c0301, SPAN.c0302, SPAN.c0303, SPAN.c0304, SPAN.c0305, SPAN.c0306, SPAN.c0307, SPAN.c0308, SPAN.c0309, SPAN.c0310, SPAN.c0311, SPAN.c0312, SPAN.c0313, SPAN.c0314, SPAN.c0315 {color: green;}\n");
++ str_write(dst_file, "SPAN.c0400, SPAN.c0401, SPAN.c0402, SPAN.c0403, SPAN.c0404, SPAN.c0405, SPAN.c0406, SPAN.c0407, SPAN.c0408, SPAN.c0409, SPAN.c0410, SPAN.c0411, SPAN.c0412, SPAN.c0413, SPAN.c0414, SPAN.c0415 {color: red;}\n");
++ str_write(dst_file, "SPAN.c0500, SPAN.c0501, SPAN.c0502, SPAN.c0503, SPAN.c0504, SPAN.c0505, SPAN.c0506, SPAN.c0507, SPAN.c0508, SPAN.c0509, SPAN.c0510, SPAN.c0511, SPAN.c0512, SPAN.c0513, SPAN.c0514, SPAN.c0515 {color: maroon;}\n");
++ str_write(dst_file, "SPAN.c0600, SPAN.c0601, SPAN.c0602, SPAN.c0603, SPAN.c0604, SPAN.c0605, SPAN.c0606, SPAN.c0607, SPAN.c0608, SPAN.c0609, SPAN.c0610, SPAN.c0611, SPAN.c0612, SPAN.c0613, SPAN.c0614, SPAN.c0615 {color: purple;}\n");
++ str_write(dst_file, "SPAN.c0700, SPAN.c0701, SPAN.c0702, SPAN.c0703, SPAN.c0704, SPAN.c0705, SPAN.c0706, SPAN.c0707, SPAN.c0708, SPAN.c0709, SPAN.c0710, SPAN.c0711, SPAN.c0712, SPAN.c0713, SPAN.c0714, SPAN.c0715 {color: orange;}\n");
++ str_write(dst_file, "SPAN.c0800, SPAN.c0801, SPAN.c0802, SPAN.c0803, SPAN.c0804, SPAN.c0805, SPAN.c0806, SPAN.c0807, SPAN.c0808, SPAN.c0809, SPAN.c0810, SPAN.c0811, SPAN.c0812, SPAN.c0813, SPAN.c0814, SPAN.c0815 {color: yellow;}\n");
++ str_write(dst_file, "SPAN.c0900, SPAN.c0901, SPAN.c0902, SPAN.c0903, SPAN.c0904, SPAN.c0905, SPAN.c0906, SPAN.c0907, SPAN.c0908, SPAN.c0909, SPAN.c0910, SPAN.c0911, SPAN.c0912, SPAN.c0913, SPAN.c0914, SPAN.c0915 {color: lime;}\n");
++ str_write(dst_file, "SPAN.c1000, SPAN.c1001, SPAN.c1002, SPAN.c1003, SPAN.c1004, SPAN.c1005, SPAN.c1006, SPAN.c1007, SPAN.c1008, SPAN.c1009, SPAN.c1010, SPAN.c1011, SPAN.c1012, SPAN.c1013, SPAN.c1014, SPAN.c1015 {color: teal;}\n");
++ str_write(dst_file, "SPAN.c1100, SPAN.c1101, SPAN.c1102, SPAN.c1103, SPAN.c1104, SPAN.c1105, SPAN.c1106, SPAN.c1107, SPAN.c1108, SPAN.c1109, SPAN.c1110, SPAN.c1111, SPAN.c1112, SPAN.c1113, SPAN.c1114, SPAN.c1115 {color: cyan;}\n");
++ str_write(dst_file, "SPAN.c1200, SPAN.c1201, SPAN.c1202, SPAN.c1203, SPAN.c1204, SPAN.c1205, SPAN.c1206, SPAN.c1207, SPAN.c1208, SPAN.c1209, SPAN.c1210, SPAN.c1211, SPAN.c1212, SPAN.c1213, SPAN.c1214, SPAN.c1215 {color: blue;}\n");
++ str_write(dst_file, "SPAN.c1300, SPAN.c1301, SPAN.c1302, SPAN.c1303, SPAN.c1304, SPAN.c1305, SPAN.c1306, SPAN.c1307, SPAN.c1308, SPAN.c1309, SPAN.c1310, SPAN.c1311, SPAN.c1312, SPAN.c1313, SPAN.c1314, SPAN.c1315 {color: magenta;}\n");
++ str_write(dst_file, "SPAN.c1400, SPAN.c1401, SPAN.c1402, SPAN.c1403, SPAN.c1404, SPAN.c1405, SPAN.c1406, SPAN.c1407, SPAN.c1408, SPAN.c1409, SPAN.c1410, SPAN.c1411, SPAN.c1412, SPAN.c1413, SPAN.c1414, SPAN.c1415 {color: silver;}\n");
++ str_write(dst_file, "SPAN.c1500, SPAN.c1501, SPAN.c1502, SPAN.c1503, SPAN.c1504, SPAN.c1505, SPAN.c1506, SPAN.c1507, SPAN.c1508, SPAN.c1509, SPAN.c1510, SPAN.c1511, SPAN.c1512, SPAN.c1513, SPAN.c1514, SPAN.c1515 {color: gray;}\n");
++ str_write(dst_file, "SPAN.f00 {color: white;}\n");
++ str_write(dst_file, "SPAN.f01 {color: black;}\n");
++ str_write(dst_file, "SPAN.f02 {color: navy;}\n");
++ str_write(dst_file, "SPAN.f03 {color: green;}\n");
++ str_write(dst_file, "SPAN.f04 {color: red;}\n");
++ str_write(dst_file, "SPAN.f05 {color: maroon;}\n");
++ str_write(dst_file, "SPAN.f06 {color: purple;}\n");
++ str_write(dst_file, "SPAN.f07 {color: orange;}\n");
++ str_write(dst_file, "SPAN.f08 {color: yellow;}\n");
++ str_write(dst_file, "SPAN.f09 {color: lime;}\n");
++ str_write(dst_file, "SPAN.f10 {color: teal;}\n");
++ str_write(dst_file, "SPAN.f11 {color: cyan;}\n");
++ str_write(dst_file, "SPAN.f12 {color: blue;}\n");
++ str_write(dst_file, "SPAN.f13 {color: magenta;}\n");
++ str_write(dst_file, "SPAN.f14 {color: silver;}\n");
++ str_write(dst_file, "SPAN.f15 {color: gray;}\n");
++ str_write(dst_file, "SPAN.b00 {background-color: white;}\n");
++ str_write(dst_file, "SPAN.b01 {background-color: black;}\n");
++ str_write(dst_file, "SPAN.b02 {background-color: navy;}\n");
++ str_write(dst_file, "SPAN.b03 {background-color: green;}\n");
++ str_write(dst_file, "SPAN.b04 {background-color: red;}\n");
++ str_write(dst_file, "SPAN.b05 {background-color: maroon;}\n");
++ str_write(dst_file, "SPAN.b06 {background-color: purple;}\n");
++ str_write(dst_file, "SPAN.b07 {background-color: orange;}\n");
++ str_write(dst_file, "SPAN.b08 {background-color: yellow;}\n");
++ str_write(dst_file, "SPAN.b09 {background-color: lime;}\n");
++ str_write(dst_file, "SPAN.b10 {background-color: teal;}\n");
++ str_write(dst_file, "SPAN.b11 {background-color: cyan;}\n");
++ str_write(dst_file, "SPAN.b12 {background-color: blue;}\n");
++ str_write(dst_file, "SPAN.b13 {background-color: magenta;}\n");
++ str_write(dst_file, "SPAN.b14 {background-color: silver;}\n");
++ str_write(dst_file, "SPAN.b15 {background-color: gray;}\n");
++ fclose(dst_file);
++ }
++ /* Now write user CSS file */
++ egg_snprintf(dst_filename, sizeof dst_filename, "%s%suser.css", ch->outputpath, SEP);
++ if ((dst_file = openfile(dst_filename, "wb", false)) != NULL) {
++ writefromexfile(dst_file, userstyle_filename);
++ fclose(dst_file);
++ }
++
++ if (!logfile_suffix[0])
++ egg_strftime(ct, 12, ".%d%b%Y", t);
++ else
++ egg_strftime(ct, 80, logfile_suffix, t);
++ ct[80] = '\0';
++
++ egg_snprintf(src_filename, sizeof src_filename, "%s%s", ch->logfilename, ct);
++ if ((src_file = openfile(src_filename, "r", true)) == NULL) return;
++
++ while(!feof(src_file)) {
++ lines_count = lines_per_page; pages_count++;
++
++ egg_snprintf(dst_filename, sizeof dst_filename, "%s%s%s%d%02d%02d_pg%d.html", ch->outputpath, SEP, ch->logspagename, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, pages_count);
++ if ((dst_file = openfile(dst_filename, "wb", false)) == NULL) {
++ fclose(src_file);
++ putlog(LOG_MISC, "*", "logs2html: Error occured on converting %d page of file \"%s\"!", pages_count, dst_filename);
++ return;
++ }
++
++ str_write(dst_file, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n");
++ str_write(dst_file, "<html>\n");
++ str_write(dst_file, "<head>\n");
++ if (strlen(encoding_string) > 0) {
++ str_write(dst_file, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n", encoding_string);
++ }
++ str_write(dst_file, "<meta name=\"title\" content=\"%s\">\n", ch->logspagetitle);
++ str_write(dst_file, "<meta name=\"Description\" content=\"%s\">\n", ch->logspagetitle);
++ str_write(dst_file, "<meta name=\"Generator\" content=\"logs2html module for Eggdrop v.%d.%d.%d\">\n", MODULE_MAJOR, MODULE_MINOR, MODULE_SUBMINOR);
++ str_write(dst_file, "<meta name=\"Author\" content=\"Fedotov Alexander aka Gray_Angel\">\n");
++ str_write(dst_file, "<meta name=\"Keywords\" content=\"logs, logging, channel, irc, bot, eggdrop, windrop, module, logs2html\">\n");
++ str_write(dst_file, "<meta name=\"robots\" content= \"index,all\">\n");
++ str_write(dst_file, "<link rel=stylesheet type=\"text/css\" href=\"default.css\">\n");
++ if (strlen(userstyle_filename) > 0) str_write(dst_file, "<link rel=stylesheet type=\"text/css\" href=\"user.css\">\n");
++ str_write(dst_file, "<title>%s. %d/%d/%d</title>\n", ch->logspagetitle, t->tm_mday, t->tm_mon + 1, t->tm_year + 1900);
++ str_write(dst_file, "</head>\n");
++ str_write(dst_file, "<body class=\"logspage\">\n");
++
++ writefromexfile(dst_file, logspage_top_filename);
++
++ str_write(dst_file, "<a name=\"top\"></a>\n");
++ str_write(dst_file, "<div id=\"navtop\"><a href=\"%s.html\">%s</a></div>\n", ch->mainpagename, LOGS2HTML_MAINPAGE);
++ str_write(dst_file, "<div id=\"log\">\n");
++
++ while ((lines_count > 0) || (lines_per_page == 0)) {
++ lines_count--;
++
++ buf_ptr = fgets(buffer, sizeof buffer, src_file);
++ if (buf_ptr == NULL) break;
++
++ p = strrchr(buf_ptr, '\n');
++ if (p) *p = '\0';
++ p = strrchr(buf_ptr, '\r');
++ if (p) *p = '\0';
++ if (!buf_ptr[0]) continue;
++
++ /* if timestamp exist cut time from string */
++ data[0] = '\0';
++ if (shtime) {
++ egg_strftime(stamp, sizeof(stamp) - 1, LOG_TS, t); /* Print dummy time */
++ tsl = strlen(stamp);
++ strncat(data, buf_ptr, tsl);
++ buf_ptr += (++tsl);
++ }
++ if (strncmp(buf_ptr, "--- ", 4) == 0) { /* we don't really need this string I think */
++ continue;
++ }
++ if (data && data[0]) {
++ str_write(dst_file, "<span class=\"time\">%s</span>", data);
++ }
++
++ data[0] = '\0'; noneedtoclose = false; skipemail = false;
++ if (strncmp(buf_ptr, "Action: ", 8) == 0) { /* command: /me */
++ buf_ptr += 7;
++ str_write(dst_file, "<span class=\"action\"> ***");
++ } else { /* nick */
++ p = strstr(buf_ptr, "> ");
++ if ((strncmp(buf_ptr, "<", 1) == 0) && (p != NULL)) {
++ buf_ptr++;
++ strncat(data, buf_ptr, p - buf_ptr);
++ str_write(dst_file, "<span class=\"nick\"> &lt;%s&gt;</span>", data);
++ buf_ptr += (p - buf_ptr + 1);
++ noneedtoclose = true;
++ } else {
++ str_write(dst_file, "<span class=\"else\"> ");
++ skipemail = true;
++ }
++ }
++
++ cuted_string_len = strlen(buf_ptr) + 2;
++ original_idx = (int *)nmalloc(sizeof(int) * (cuted_string_len + 1));
++ for (i = 0; i < cuted_string_len; i++) original_idx[i] = i - 1; original_idx[cuted_string_len] = -1;
++
++ cuted_string = (char *)nmalloc(cuted_string_len + 1);
++ egg_memset(cuted_string, 0, cuted_string_len + 1);
++ snprintf(cuted_string, cuted_string_len + 1, " %s ", buf_ptr);
++ q = r = cuted_string + 1;
++ /*
++ * Code copied from Eggdrop's src/dcc.c and then modified...
++ * Copyright (C) 1997 Robey Pointer
++ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Eggheads Development Team
++ */
++ while (*r) {
++ switch (*r) {
++ case 0xf:
++ case 3: /* mIRC colors? */
++ if (isdigit(r[1])) { /* Is the first char a number? */
++ r += 2; /* Skip over the ^C and the first digit */
++ if (isdigit(*r)) r++; /* Is this a double digit number? */
++ if (*r == ',') { /* Do we have a background color next? */
++ if (isdigit(r[1])) r += 2; /* Skip over the first background digit */
++ if (isdigit(*r)) r++; /* Is it a double digit? */
++ }
++ } else {
++ r++;
++ }
++ continue;
++ case 2: /* Bold text */
++ case 7:
++ case 0x16: /* Reverse video */
++ case 0x1f: /* Underlined text */
++ case 0x3c: /* < */
++ case 0x3e: /* > */
++ r++;
++ continue;
++ case 033:
++ r++;
++ if (*r == '[') {
++ r++;
++ while ((*r == ';') || isdigit(*r)) r++;
++ if (*r) r++; /* also kill the following char */
++ }
++ continue;
++ }
++ original_idx[q - cuted_string] = r - cuted_string - 1;
++ *q++ = *r++; /* Move on to the next char */
++ }
++ *q = '\0';
++ /*
++ * Ends here...
++ */
++
++ linkfound = false;
++ q = cuted_string;
++ while (*q) {
++ for (k = 0; k < MIN(sizeof openspace, sizeof closespace); k++) {
++ if (openspace[k] == *q) {
++ r = q + 1;
++ while (*r) {
++ if (closespace[k] == *r) {
++ *r = '\0';
++ p = q + 1;
++ switch (whatisit(p)) {
++ case ITS_NOTHING:
++ break;
++ case ITS_EMAIL:
++ if (!skipemail) { /* If class = "else", lets skip mail, because it ident@host */
++ egg_memset(data, 0, sizeof data);
++ sprintf(data, "<a href=\"mailto:%s\">", p);
++ linkfound = true;
++ }
++ break;
++ case ITS_LINK:
++ egg_memset(data, 0, sizeof data);
++ sprintf(data, "<a href=\"%s\">", p);
++ linkfound = true;
++ break;
++ case ITS_TRUNKLINK:
++ egg_memset(data, 0, sizeof data);
++ sprintf(data, "<a href=\"http://%s\">", p);
++ linkfound = true;
++ break;
++ }
++ *r = closespace[k];
++ if (linkfound) {
++ /* will after reallocation r & q pointers be aviable?
++ * i.e. will cuted_string begin with the same adress?
++ * to make them aviable let's count offset.
++ */
++ r_offset = r - cuted_string; q_offset = q - cuted_string;
++ old_cuted_string_len = strlen(cuted_string); delta_cuted_string_len = strlen(data) + strlen(T_LINKC);
++ cuted_string = (char *)nrealloc(cuted_string, old_cuted_string_len + delta_cuted_string_len + 1);
++ original_idx = (int *)nrealloc(original_idx, sizeof(int) * (old_cuted_string_len + delta_cuted_string_len + 1));
++ r = cuted_string + r_offset; q = cuted_string + q_offset;
++ for (i = old_cuted_string_len; i < (old_cuted_string_len + delta_cuted_string_len + 1); i++) {
++ original_idx[i] = -1; cuted_string[i] = '\0';
++ }
++ for (i = old_cuted_string_len - 1; i >= r_offset; i--) {
++ cuted_string[i + delta_cuted_string_len] = cuted_string[i];
++ original_idx[i + delta_cuted_string_len] = original_idx[i]; original_idx[i] = -1;
++ }
++ for (i = strlen(T_LINKC); i--; ) {
++ cuted_string[r_offset + delta_cuted_string_len - strlen(T_LINKC) + i] = T_LINKC[i];
++ }
++ for (i = r_offset - 1; i > q_offset; i--) {
++ cuted_string[i + delta_cuted_string_len - strlen(T_LINKC)] = cuted_string[i];
++ original_idx[i + delta_cuted_string_len - strlen(T_LINKC)] = original_idx[i]; original_idx[i] = -1;
++ }
++ for (i = 0; i < strlen(data); i++) {
++ cuted_string[q_offset + i + 1] = data[i];
++ original_idx[q_offset + i + 1] = -1;
++ }
++ }
++ if (linkfound) q = r - 1;
++ break;
++ }
++ r++;
++ }
++ }
++ if (linkfound) {
++ linkfound = false;
++ break;
++ }
++ }
++ q++;
++ }
++
++ cuted_string[strlen(cuted_string) - 1] = '\0';
++ egg_memset(data, 0, sizeof data);
++ bold_isopen = false; underline_isopen = false;
++ p = cuted_string + 1; /* Don't need first char cause it = ' ' */
++ q = buf_ptr;
++ while (*p) {
++ if ((original_idx[p - cuted_string] == -1) || (original_idx[p - cuted_string] == (q - buf_ptr))) {
++ if ((strlen(data) + 1) > (sizeof data - 1)) {
++ str_write(dst_file, "%s", data);
++ egg_memset(data, 0, sizeof data);
++ }
++ strncat(data, p, 1);
++ p++;
++ if (original_idx[p - cuted_string] != -1) q++;
++ } else {
++ /*
++ * Code copied from Eggdrop's src/dcc.c and then modified...
++ * Copyright (C) 1997 Robey Pointer
++ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Eggheads Development Team
++ */
++ switch (*q) {
++ case 2: /* Bold text */
++ if (bold_isopen) {
++ bold_isopen = false;
++ str_write(dst_file, "%s%s", data, T_BOLDC);
++ egg_memset(data, 0, sizeof data);
++ } else {
++ bold_isopen = true;
++ str_write(dst_file, "%s%s", data, T_BOLDO);
++ egg_memset(data, 0, sizeof data);
++ }
++ q++;
++ break;
++ case 3: /* mIRC colors? */
++ case 0xf: /* don't know, maybe broken client? but also mIRC colors */
++ egg_memset(f_color, 0, sizeof f_color); egg_memset(bg_color, 0, sizeof bg_color);
++ if (isdigit(q[1])) { /* Is the first char a number? */
++ f_color[0] = q[1];
++ if (isdigit(q[2])) {f_color[1] = q[2]; q++;}
++ q += 2;
++ if (*q == ',') {
++ if (isdigit(q[1])) { /* Is the first char a number? */
++ bg_color[0] = q[1];
++ if (isdigit(q[2])) {bg_color[1] = q[2]; q++;}
++ q += 2;
++ }
++ }
++ if (strlen(bg_color) > 0) {
++ /* If we have background color - let's close all previous "SPAN" */
++ for (mc_openteg_count++; --mc_openteg_count; ) {
++ if ((strlen(data) + strlen(T_SPANC)) > (sizeof data - 1)) {
++ str_write(dst_file, "%s", data);
++ egg_memset(data, 0, sizeof data);
++ }
++ strncat(data, T_SPANC, strlen(T_SPANC));
++ }
++ str_write(dst_file, "%s", data);
++ egg_memset(data, 0, sizeof data);
++ }
++
++ if ((strlen(f_color) > 0) && ((atoi(f_color) < 0) || (atoi(f_color) > 15))) {
++ egg_memset(f_color, 0, sizeof f_color);
++ }
++ if ((strlen(bg_color) > 0) && ((atoi(bg_color) < 0) || (atoi(bg_color) > 15))) {
++ egg_memset(bg_color, 0, sizeof bg_color);
++ }
++ if ((strlen(f_color) > 0) || (strlen(bg_color) > 0)) {
++ mc_openteg_count++;
++ text_style[0] = '\0';
++ if ((strlen(f_color) > 0) && (strlen(bg_color) > 0)) egg_snprintf(text_style, sizeof text_style, "c%02.2d%02.2d", atoi(f_color), atoi(bg_color));
++ if (strlen(bg_color) == 0) egg_snprintf(text_style, sizeof text_style, "f%02.2d", atoi(f_color));
++ if (strlen(f_color) == 0) egg_snprintf(text_style, sizeof text_style, "b%02.2d", atoi(bg_color));
++ str_write(dst_file, "%s<span class=\"%s\">", data, text_style);
++ egg_memset(data, 0, sizeof data);
++ }
++ } else {
++ /* It was "close-color" tag -> let's close all "SPAN" */
++ for (mc_openteg_count++; --mc_openteg_count; ) {
++ if ((strlen(data) + strlen(T_SPANC)) > (sizeof data - 1)) {
++ str_write(dst_file, "%s", data);
++ egg_memset(data, 0, sizeof data);
++ }
++ strncat(data, T_SPANC, strlen(T_SPANC));
++ }
++ str_write(dst_file, "%s", data);
++ egg_memset(data, 0, sizeof data);
++ q++;
++ }
++ break;
++ case 7: /* Bells */
++ q++;
++ break;
++ case 0x16: /* Reverse video */
++ q++;
++ break;
++ case 0x1f: /* Underlined text */
++ if (underline_isopen) {
++ underline_isopen = false;
++ str_write(dst_file, "%s%s", data, T_UNDERLINEC);
++ egg_memset(data, 0, sizeof data);
++ } else {
++ underline_isopen = true;
++ str_write(dst_file, "%s%s", data, T_UNDERLINEO);
++ egg_memset(data, 0, sizeof data);
++ }
++ q++;
++ break;
++ case 0x3c: /* < */
++ str_write(dst_file, "%s%s", data, T_LT);
++ egg_memset(data, 0, sizeof data);
++ q++;
++ break;
++ case 0x3e: /* > */
++ str_write(dst_file, "%s%s", data, T_GT);
++ egg_memset(data, 0, sizeof data);
++ q++;
++ break;
++ case 033:
++ q++;
++ if (*q == '[') {
++ q++;
++ while ((*q == ';') || isdigit(*q)) q++;
++ if (*q) q++; /* also kill the following char */
++ }
++ break;
++ default:
++ /* I think we should never get here, but if so... */
++ strncat(data, q, 1);
++ q++;
++ break;
++ }
++ /*
++ * Ends here...
++ */
++ }
++ }
++ str_write(dst_file, "%s", data);
++ egg_memset(data, 0, sizeof data);
++ if (bold_isopen) str_write(dst_file, "%s", T_BOLDC);
++ if (underline_isopen) str_write(dst_file, "%s", T_UNDERLINEC);
++ for (mc_openteg_count++; --mc_openteg_count; ) {
++ if ((strlen(data) + strlen(T_SPANC)) > (sizeof data - 1)) {
++ str_write(dst_file, "%s", data);
++ egg_memset(data, 0, sizeof data);
++ }
++ strncat(data, T_SPANC, strlen(T_SPANC));
++ }
++ str_write(dst_file, "%s", data);
++ egg_memset(data, 0, sizeof data);
++
++ nfree(original_idx); original_idx = NULL;
++ nfree(cuted_string); cuted_string = NULL;
++
++ str_write(dst_file, "%s", data); data[0] = '\0';
++ str_write(dst_file, noneedtoclose ? "<br />\n":"</span><br />\n");
++ }
++ fclose(dst_file);
++ }
++ fclose(src_file);
++
++ for (i = 1; i <= pages_count; i++) {
++ egg_snprintf(dst_filename, sizeof dst_filename, "%s%s%s%d%02d%02d_pg%d.html", ch->outputpath, SEP, ch->logspagename, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, i);
++ if ((dst_file = openfile(dst_filename, "ab", false)) == NULL) {
++ putlog(LOG_MISC, "*", "logs2html: Error occured on converting %d page of file \"%s\"!", i, dst_filename);
++ return;
++ }
++ str_write(dst_file, "</div>\n");
++ if (pages_count > 1) {
++ str_write(dst_file, "<div id=\"navbottom\">");
++ if (i == 1) {
++ str_write(dst_file, LOGS2HTML_BACK);
++ } else {
++ egg_snprintf(dst_filename, sizeof dst_filename, "%s%d%02d%02d_pg%d.html", ch->logspagename, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, i-1);
++ str_write(dst_file, "<span>&larr;</span>&nbsp;<a href=\"%s\">%s</a>", dst_filename, LOGS2HTML_BACK);
++ }
++ str_write(dst_file, "&nbsp;");
++ if (i == pages_count) {
++ str_write(dst_file, LOGS2HTML_NEXT);
++ } else {
++ egg_snprintf(dst_filename, sizeof dst_filename, "%s%d%02d%02d_pg%d.html", ch->logspagename, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, i+1);
++ str_write(dst_file, "<a href=\"%s\">%s</a>&nbsp;<span>&rarr;</span>", dst_filename, LOGS2HTML_NEXT);
++ }
++ str_write(dst_file, "<br />");
++ for (j = 1; j <= pages_count; j++) {
++ egg_snprintf(dst_filename, sizeof dst_filename, "%s%d%02d%02d_pg%d.html", ch->logspagename, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, j);
++ if (j != i) {
++ str_write(dst_file, "<span> <a href=\"%s\">%d</a> </span>", dst_filename, j);
++ } else {
++ str_write(dst_file, "<b>%d</b>", j);
++ }
++ }
++ str_write(dst_file, "</div>\n");
++ }
++
++ str_write(dst_file, "<div id=\"totop\"><a href=\"#top\">%s</a></div>\n", LOGS2HTML_UP);
++
++ writefromexfile(dst_file, logspage_bottom_filename);
++
++ str_write(dst_file, "<div id=\"footer\">\nGenerated by logs2html module for eggdrop v.%d.%d.%d<br />\n", MODULE_MAJOR, MODULE_MINOR, MODULE_SUBMINOR);
++ str_write(dst_file, "Find latest version at <a href=\"http://sourceforge.net/projects/logs2html\">http://sourceforge.net/projects/logs2html</a> or <a href=\"http://shmupsik.osetia.org\">http://shmupsik.osetia.org</a>\n</div>\n");
++
++ str_write(dst_file, "</body>\n");
++ str_write(dst_file, "</html>");
++
++ fclose(dst_file);
++ }
++
++ return;
++} /* convertfile() */
++/****************************************************************************/
++
++
++/****************************************************************************/
++/*
++ * function void makemainpage(logs2htmlchan *ch)
++ *
++ * Input:
++ * íè÷åãî
++ *
++ * Output:
++ * íè÷åãî
++ *
++ * Discription:
++ * Ãåíåðàöèÿ îñíîâíîé ñòðàíèöû (êàëåíäàðÿ)
++ * + âûçûâàåòñÿ ïðîöåäóðà äëÿ êîíâåðòèðîâàíèÿ ëîãîâ â ôîðìàò HTML
++ */
++static void makemainpage(logs2htmlchan *ch) {
++ int i, j, k, m, l;
++ int add_day;
++ FILE *file;
++ char filename[256];
++ bool endofyear;
++ struct tm tblock;
++ int delta_day = 0;
++ time_t t = time(NULL);
++ struct tm *st = localtime(&t);
++
++ tblock.tm_year = st->tm_year;
++ tblock.tm_isdst = st->tm_isdst;
++ tblock.tm_hour = 0;
++ tblock.tm_min = 0;
++ tblock.tm_sec = 1;
++ /* Other fields not necessary here
++ tblock.tm_mday = st->tm_mday;
++ tblock.tm_mon = st->tm_mon;
++ tblock.tm_wday = st->tm_wday;
++ tblock.tm_yday = st->tm_yday;
++ */
++
++ egg_snprintf(filename, sizeof filename, "%s%s%s.html", ch->outputpath, SEP, ch->mainpagename);
++ if ((file = openfile(filename, "wb", false)) == NULL) return;
++
++ str_write(file, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n");
++ str_write(file, "<html>\n");
++ str_write(file, "<head>\n");
++ if (strlen(encoding_string) > 0) {
++ str_write(file, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n", encoding_string);
++ }
++ str_write(file, "<meta name=\"title\" content=\"%s\">\n", ch->mainpagetitle);
++ str_write(file, "<meta name=\"Description\" content=\"%s\">\n", ch->mainpagetitle);
++ str_write(file, "<meta name=\"Generator\" content=\"logs2html module for Eggdrop v.%d.%d.%d\">\n", MODULE_MAJOR, MODULE_MINOR, MODULE_SUBMINOR);
++ str_write(file, "<meta name=\"Author\" content=\"Fedotov Alexander aka Gray_Angel\">\n");
++ str_write(file, "<meta name=\"Keywords\" content=\"logs, logging, channel, irc, bot, eggdrop, windrop, module, logs2html\">\n");
++ str_write(file, "<meta name=\"robots\" content= \"index,all\">\n");
++ str_write(file, "<link rel=stylesheet type=\"text/css\" href=\"default.css\">\n");
++ if (strlen(userstyle_filename) > 0) str_write(file, "<link rel=stylesheet type=\"text/css\" href=\"user.css\">\n");
++ str_write(file, "<title>%s %d %s</title>\n", ch->mainpagetitle, tblock.tm_year + 1900, LOGS2HTML_YEAR);
++ str_write(file, "</head>\n");
++ str_write(file, "<body class=\"mainpage\">\n");
++
++ writefromexfile(file, mainpage_top_filename);
++
++ str_write(file, "<div id=\"title\">%s<br />%d %s</div>\n", ch->mainpagetitle, tblock.tm_year + 1900, LOGS2HTML_YEAR);
++ str_write(file, "<div id=\"calendar\">\n");
++
++
++ /* Âû÷èñëÿåì ñêîëüêî ðÿäîâ ïîòðåáóåòñÿ äëÿ ðàçìåùåíèÿ 12 ìåñÿöåâ ïðè çàäàííîì ÷èñëå ñòîëáöîâ */
++ month_rows_count = (int)ceil(12.0 / (double)month_cols_count);
++
++ str_write(file, "<table width=\"100%%\" cellspacing=\"2\" cellpadding=\"1\" border=\"0\">\n");
++
++ /* öèêë ïî ðÿäàì ìåñÿöåâ */
++ for(i = 0; i < month_rows_count; i++) {
++
++ /* â êàæäîì ðÿäó: 1 ñòðîêà (íàçâàíèå ìåñÿöà) + 7 ñòðîê (äíè íåäåëè) */
++ for (j = 0; j < 8; j++) {
++ str_write(file, "<tr align=center>\n");
++
++ /* öèêë ïî ñòîëáöàì ìåñÿöåâ */
++ for (k = 0; k < month_cols_count; k++) {
++ tblock.tm_mon = i * month_cols_count + k;
++ endofyear = (tblock.tm_mon > 11 ) ? true : false;
++
++ if (j == 0) {
++ str_write(file, "<td class=\"space\"></td>");
++ str_write(file, "<th colspan=7>%s</th>\n", endofyear ? "&nbsp;": month_names[tblock.tm_mon]);
++ continue;
++ }
++
++ /* Åñëè ãîä âèñîêîñíûé, òî äîáàâëÿåì ê ôåâðàëþ 1 äåíü */
++ add_day = ((tblock.tm_mon == 1) && isleap(tblock.tm_year)) ? 1 : 0;
++
++ /* Äëÿ äàííîãî ìåñÿöà äàííîãî ãîäà âû÷èñëÿåì íà êàêîé äåíü íåäåëè ïðèõîäèòñÿ 1 ÷èñëî */
++ if (!endofyear) {
++ delta_day = getdayofweek(tblock.tm_year + 1900, tblock.tm_mon + 1, 1);
++ }
++
++ /* â êàæäîì ìåñÿöå: 2 ñòîëáöà (íàçâàíèå äíåé íåäåëè) + 6 ñòîëáöîâ (íåäåëè) */
++ for (m = 0; m < 7; m++) {
++ if (endofyear) {
++ str_write(file, "<td>&nbsp;</td>\n");
++ continue;
++ }
++ if (m == 0) {
++ str_write(file, "<td class=\"space\"></td>");
++ switch (j)
++ {
++ case 1:
++ case 2:
++ case 3:
++ case 4:
++ case 5:
++ case 6:
++ str_write(file, "<td class=\"dayname\">%s</td>\n", days_names[j-1]);
++ break;
++ case 7:
++ str_write(file, "<td class=\"weekend\">%s</td>\n", days_names[j-1]);
++ break;
++ default:
++ /* Uuups.. We should never get to this point.. and if it so, that mean's something wrong...:( */
++ str_write(file, "<td>&nbsp;</td>\n");
++ }
++ continue;
++ }
++ tblock.tm_mday = (m - 1) * 7 + j - delta_day;
++ if ((tblock.tm_mday >= 1) && (tblock.tm_mday <= (days_in_month[tblock.tm_mon] + add_day))) {
++ tblock.tm_wday = (getdayofweek(tblock.tm_year + 1900, tblock.tm_mon + 1, tblock.tm_mday) + 1) % 7;
++ tblock.tm_yday = 0;
++ for (l = 0; l < tblock.tm_mon; l++) tblock.tm_yday += days_in_month[l];
++ tblock.tm_yday += tblock.tm_mday - 1;
++
++ egg_snprintf(filename, sizeof filename, "%s%s%s%d%02d%02d_pg%d.html", ch->outputpath, SEP, ch->logspagename, tblock.tm_year + 1900, tblock.tm_mon + 1, tblock.tm_mday, 1);
++ if (!file_readable(filename)) convertfile(&tblock, ch);
++ if (file_readable(filename)) {
++ /* let write withount full path */
++ egg_snprintf(filename, sizeof filename, "%s%d%02d%02d_pg%d.html", ch->logspagename, tblock.tm_year + 1900, tblock.tm_mon + 1, tblock.tm_mday, 1);
++ str_write(file, "<td><a href=\"%s\">%d</A></td>\n", filename, tblock.tm_mday);
++ } else {
++ str_write(file, "<td>%d</td>\n", tblock.tm_mday);
++ }
++ } else {
++ str_write(file, "<td>&nbsp;</td>\n");
++ }
++ }
++ }
++ str_write(file, "</tr>\n");
++ }
++ str_write(file, "<tr><td class=\"space\" colspan=%d>&nbsp;</td></tr>\n", month_cols_count * 8);
++ }
++
++ str_write(file, "</table>\n");
++ str_write(file, "</div>\n");
++
++ writefromexfile(file, mainpage_bottom_filename);
++
++ str_write(file, "<div id=\"footer\">\nGenerated by logs2html module for eggdrop v.%d.%d.%d<br />\n", MODULE_MAJOR, MODULE_MINOR, MODULE_SUBMINOR);
++ str_write(file, "Find latest version at <a href=\"http://sourceforge.net/projects/logs2html\">http://sourceforge.net/projects/logs2html</a> or <a href=\"http://shmupsik.osetia.org\">http://shmupsik.osetia.org</a>\n</div>\n");
++
++ str_write(file, "</body>\n");
++ str_write(file, "</html>");
++
++ fclose(file);
++
++ return;
++} /* makemainpage() */
++/****************************************************************************/
++
++
++/****************************************************************************/
++static void logs2html_hook_5minutely(void)
++{
++ logs2htmlchan *p;
++ struct tm tblock;
++ time_t t = time(NULL);
++ struct tm *st = localtime(&t);
++
++ tblock.tm_year = st->tm_year;
++ tblock.tm_isdst = st->tm_isdst;
++ tblock.tm_mday = st->tm_mday;
++ tblock.tm_mon = st->tm_mon;
++ tblock.tm_wday = st->tm_wday;
++ tblock.tm_yday = st->tm_yday;
++ tblock.tm_hour = 0;
++ tblock.tm_min = 0;
++ tblock.tm_sec = 1;
++
++ p = logs2htmlchanlist;
++ while (p != NULL) {
++ convertfile(&tblock, p);
++ makemainpage(p);
++ p = p->next;
++ }
++
++ return;
++}
++/****************************************************************************/
++
++/****************************************************************************/
++static void logs2html_hook_daily(void)
++{
++ logs2htmlchan *p;
++ struct tm tblock;
++ time_t t = time(NULL);
++ struct tm *st = localtime(&t);
++
++ tblock.tm_year = st->tm_year;
++ tblock.tm_isdst = st->tm_isdst;
++ tblock.tm_mday = st->tm_mday;
++ tblock.tm_mon = st->tm_mon;
++ tblock.tm_wday = st->tm_wday;
++ tblock.tm_yday = st->tm_yday;
++ tblock.tm_hour = 0;
++ tblock.tm_min = 0;
++ tblock.tm_sec = 1;
++
++ if (!--tblock.tm_mday) {
++ if (!tblock.tm_mon) {
++ /* it's 1st January; lets go one day before */
++ tblock.tm_year--;
++ tblock.tm_mon = 11;
++ tblock.tm_mday = 31;
++ tblock.tm_yday = 364 + isleap(tblock.tm_year) ? 1 : 0;
++ } else {
++ tblock.tm_mon--;
++ tblock.tm_mday = days_in_month[tblock.tm_mon] + ((tblock.tm_mon == 1) && isleap(tblock.tm_year)) ? 1 : 0;
++ tblock.tm_yday--;
++ }
++ } else {
++ tblock.tm_yday--;
++ }
++ tblock.tm_wday = (tblock.tm_wday + 6) % 7;
++
++ p = logs2htmlchanlist;
++ while (p != NULL) {
++ convertfile(&tblock, p);
++ makemainpage(p);
++ p = p->next;
++ }
++
++ return;
++}
++/****************************************************************************/
++
++
++/****************************************************************************/
++static void logs2html_hook_pre_rehash(void)
++{
++ logs2htmlchan *p, *q;
++
++ q = p = logs2htmlchanlist;
++ while (q != NULL) {
++ q = p->next;
++ nfree(p);
++ p = q;
++ }
++ logs2htmlchanlist = p = q = NULL;
++
++ return;
++}
++/****************************************************************************/
++
++/****************************************************************************/
++static void logs2html_hook_rehash(void)
++{
++ if (lines_per_page < 0) lines_per_page = 0;
++
++ return;
++}
++/****************************************************************************/
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/logs2html.conf eggdrop1.6.19/src/mod/logs2html.mod/logs2html.conf
+--- src/mod/logs2html.mod/logs2html.conf 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/logs2html.conf 2009-03-28 01:43:58.000000000 +0000
+@@ -0,0 +1,38 @@
++######
++#####
++### General Settings
++#####
++######
++
++# number of rows the month'll put out
++set col-count 3
++
++# set how many lines there'll be on one page of converted logfile. If it
++# set to 0 then all converted log will dispalay as one page.
++set lines-per-page 200
++
++# Here specify file with "addlogs2html" expressions.
++set channels-list chan.list
++
++# Uncomment line if you want specify file with your color settings for
++# generated pages
++#set user-style user.css
++
++# This setting allows you to insert meta tag
++# <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=..."> in your
++# HTML files. You can comment next line, that will mean that this tag'll not
++# be insert in the resulting page.
++set insert-encoding-str "windows-1251"
++
++# Here you can specify path to files which content will be put to converted
++# logfile (or mainpage). Uncomment the line you need and put there
++# filename with path for example: set mainpage-top "top100.tpl"
++# Note: the content of specified file puts to the resulting file "as is",
++# without any transformation
++#set mainpage-top ""
++#set mainpage-bottom ""
++#set logspage-top ""
++#set logspage-bottom ""
++
++# now load the module
++loadmodule logs2html
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/logs2html.h eggdrop1.6.19/src/mod/logs2html.mod/logs2html.h
+--- src/mod/logs2html.mod/logs2html.h 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/logs2html.h 2009-03-28 01:46:28.000000000 +0000
+@@ -0,0 +1,76 @@
++/*
++ * logs2html.h -- part of logs2html.mod
++ *
++ * Written by Fedotov Alexander aka Gray_Angel aka Shmupsik <shurikvz@mail.ru>
++ *
++ * 2004-2005 year
++ */
++/*
++ * 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 "src/lang.h"
++
++#define SEP "/"
++
++#undef false
++#undef true
++typedef enum {false = 0, true} bool;
++
++#ifdef MIN
++# undef MIN
++#endif
++#define MIN(p,q) ((p < q) ? p : q)
++
++#ifndef isleap
++ /* Nonzero if YEAR is a leap year (every 4 years,
++ except every 100th isn't, and every 400th is). */
++#define isleap(year) \
++ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
++#endif
++
++#define T_LT "&lt;"
++#define T_GT "&gt;"
++#define T_BOLDO "<B>"
++#define T_BOLDC "</B>"
++#define T_UNDERLINEO "<U>"
++#define T_UNDERLINEC "</U>"
++#define T_SPANC "</SPAN>"
++#define T_LINKC "</A>"
++
++typedef struct logs2html_data {
++ struct logs2html_data *next;
++ char channame[81]; /* Èìÿ êàíàëà äëÿ êîòîðîãî êîíâåðòèðîâàòü ëîãè */
++ char logfilename[128]; /* Èìÿ (ïðåôèêñ) äàííîãî êàíàëà (âû÷èñëÿåòñÿ èç âûðàæåíèÿ logfile â êîíôèãå áîòà) */
++ char outputpath[128]; /* Êóäà âûâîäèòü êîíâåðòèðîâàííûå ëîãè */
++ char mainpagename[61]; /* Èìÿ ãëàâíîé ñòðàíèöû */
++ char mainpagetitle[256]; /* Çàãîëîâîê íà ãëàâíîé ñòðàíèöå */
++ char logspagename[61]; /* Èìÿ (ïðåôèêñ) ñòðàíèöû ïåðåêîíâåðòèðîâàííîãî ëîãôàéëà */
++ char logspagetitle[256]; /* Çàãîëîâîê ñòðàíèöû ëîãôàéëà */
++} logs2htmlchan;
++
++typedef enum {ITS_NOTHING, ITS_EMAIL, ITS_LINK, ITS_TRUNKLINK} patternkind;
++
++static int cmd_convertalllogs(struct userrec *u, int idx, char *par);
++static int cmd_makemainpage(struct userrec *u, int idx, char *par);
++static int getdayofweek(int year, int month, int day);
++static FILE *openfile(char *newfilename, const char *mode, bool silent);
++static void str_write(FILE *file, char *fstr, ... );
++static void makemainpage(logs2htmlchan *ch);
++static void convertfile(struct tm *t, logs2htmlchan *ch);
++static void writefromexfile(FILE *dst_file, char *exfilename);
++static int addchannels(void);
++static patternkind whatisit(char *pattern);
++
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/logs2html.mod.desc eggdrop1.6.19/src/mod/logs2html.mod/logs2html.mod.desc
+--- src/mod/logs2html.mod/logs2html.mod.desc 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/logs2html.mod.desc 2009-03-28 01:46:37.000000000 +0000
+@@ -0,0 +1 @@
++This module convert all existing log files (and those, that will be created after module installation) of your eggdrop for givving channel to their html representation to be show in the web. and also the calendar page with links to that converted files.
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/modinfo eggdrop1.6.19/src/mod/logs2html.mod/modinfo
+--- src/mod/logs2html.mod/modinfo 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/modinfo 2009-03-28 01:32:21.000000000 +0000
+@@ -0,0 +1,4 @@
++DESC:This module convert all existing log files (and those, that will be
++DESC:created after module installation) of your eggdrop for givving channel
++DESC:to their html representation to be show in the web. and also the
++DESC:calendar page with links to that converted files.
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/readme.txt eggdrop1.6.19/src/mod/logs2html.mod/readme.txt
+--- src/mod/logs2html.mod/readme.txt 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/readme.txt 2009-03-28 01:44:20.000000000 +0000
+@@ -0,0 +1,85 @@
++logs2html.mod v.2.3.4 by Alexander Fedotov aka Gray_Angel aka Shmupsik #ircnet.ru
++e-mail: shurikvz@mail.ru
++
++This module convert all existing log files (and those, that will be created after module installation) of your eggdrop for giving channels to their html representation to be show in the web. and also the calendar page with links to that converted files.
++
++*******************************************************************************
++To install this module:
++ - copy the contents of "language" directory to your eggdrops "language" directory
++ - copy the contents of "help" directory to your eggdrops "help" directory
++ - copy *.dll (for windows) or *.so (for unix/linux) module to your eggdrops "modules" directory (only if you have download an arhive file with precompiled modules)
++ - copy logs2html.conf, chan.list files to your eggdrop directory
++ - if you decide to use your own style for pages copy user.css file to your eggdrop directory
++ - (Of course don't forget to edit logs2html.conf, chan.list and user.css files)
++ - put "source logs2html.conf" into your eggdrop config file and restart your bot
++
++Module has 2 commands, which you can use from dcc chat:
++ - convertalllogs - reconverts ALL your logs for current year (you'll need it for example if you decided to change style of your output logs even those which was created before your decision)
++ - makemainpage - redraws mainpages
++*******************************************************************************
++
++
++
++*******************************************************************************
++You can see the example of output on http://www.osetia.org/logs
++You can try to find latest version on http://sourceforge.net/projects/logs2html or http://shmupsik.osetia.org
++*******************************************************************************
++
++
++
++*******************************************************************************
++So, if you want to make a donation (for some strange reason I probably will never understand...) to me,
++you can do it using WebMoney (http://www.webmoney.ru).
++And here (http://webmoney.ru/wminouttrans1.shtml) a list of sites where you can exchange your money if you are not using WebMoney system.. :)
++
++My cash number: WMID:215902813411
++ U838552550724
++ E023251651728
++ R735356625383
++*******************************************************************************
++
++
++
++*******************************************************************************
++Version history:
++15.10.05 - version 2.3.4
++ - added setting in config file, which allow to change value of meta tag <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=..."> in generated HTML files.
++
++
++04.10.05 - version 2.3.3
++ - fixed bug with broken e-mail (strings with broken e-mails were truncated)
++
++
++ 24.09.05 - version 2.3.2
++ - added support for <B> and <U> tags
++ - fixed bug with [%H:%M:%S] timestamp (I hope.. :-))
++
++
++ 26.07.05 - version 2.3.1
++ - bug fixed
++
++
++ 24.07.05 - version 2.3.0
++ - page style discriptions moved to CSS file
++ - no need for tcl now
++ - small bugs fixed
++
++
++ 25.04.05 - version 2.1.0
++ - added support for http links and e-mail.
++
++
++ 27.02.05 - version 2.0
++ - converting logs for multiply channels
++ - possibility to change colors of HTML pages
++ - now you can aim number of lines on the one generated HTML page
++
++
++ 16.12.04 - version 1.0
++ - initial realise
++*******************************************************************************
++
++
++
++P.S. Sorry for my bad english
++
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/top100.tpl eggdrop1.6.19/src/mod/logs2html.mod/top100.tpl
+--- src/mod/logs2html.mod/top100.tpl 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/top100.tpl 2009-03-28 01:43:24.000000000 +0000
+@@ -0,0 +1,50 @@
++
++<p align="center">
++<!--Rating@Mail.ru COUNTER--><script language="JavaScript"><!--
++d=document;a='';a+=';r='+escape(d.referrer)
++js=10//--></script><script language="JavaScript1.1"><!--
++a+=';j='+navigator.javaEnabled()
++js=11//--></script><script language="JavaScript1.2"><!--
++s=screen;a+=';s='+s.width+'*'+s.height
++a+=';d='+(s.colorDepth?s.colorDepth:s.pixelDepth)
++js=12//--></script><script language="JavaScript1.3"><!--
++js=13//--></script><script language="JavaScript"><!--
++d.write('<img src="http://top.list.ru/counter'+'?id=606627;js='+js+a+';rand='+Math.random()+'" height=1 width=1>')
++if(js>11)d.write('<'+'!-- ')//--></script><noscript><img
++src="http://top.list.ru/counter?js=na;id=606627"
++height=1 width=1 alt=""></noscript><script language="JavaScript"><!--
++if(js>11)d.write('--'+'>')//--></script><!--/COUNTER-->
++<!-- SpyLOG f:0210 -->
++<script language="javascript"><!--
++Mu="u5131.64.spylog.com";Md=document;Mnv=navigator;Mp=1;
++Mn=(Mnv.appName.substring(0,2)=="Mi")?0:1;Mrn=Math.random();
++Mt=(new Date()).getTimezoneOffset();
++Mz="p="+Mp+"&rn="+Mrn+"&tl=0&ls=0&ln=0&t="+Mt;
++My="";
++My+="<img src='http://"+Mu+"/cnt?cid=513164&"+Mz+"&r="+escape(Md.referrer)+"&pg="+escape(window.location.href)+"'border=0 width=1 height=1 alt='SpyLOG'>";
++Md.write(My);//--></script><noscript>
++<img src="http://u5131.64.spylog.com/cnt?cid=513164&p=1" alt='SpyLOG' border='0' width=1
++height=1 >
++</noscript>
++<!-- SpyLOG -->
++<!--begin of Top100 logo-->
++<a href="http://top100.rambler.ru/top100/">
++<img src="http://top100-images.rambler.ru/top100/banner-88x31-rambler-blue.gif" alt="Rambler's Top100" width=88 height=31 border=0></a>
++<!--end of Top100 logo -->
++<script language="javascript"><!--
++Mrn=Math.random();Mz="";
++My="<a href='http://u5131.64.spylog.com/cnt?cid=513164&f=3&rn="+Mrn+"' target='_blank'><img src='http://u5131.64.spylog.com/cnt?cid=513164&";
++My+="p=1&f=4&rn="+Mrn+Mz+"' border=0 width=88 height=31 alt='SpyLOG'></a>";Md.write(My);
++//--></script><noscript>
++<a href="http://u5131.64.spylog.com/cnt?cid=513164&f=3&p=1" target="_blank">
++<img src="http://u5131.64.spylog.com/cnt?cid=513164&p=1&f=4" alt='SpyLOG' border='0' width=88 height=31 ></a>
++</noscript>
++<!--Rating@Mail.ru LOGO--><a target=_top
++href="http://top.mail.ru/jump?from=606627"><img src="http://top.list.ru/counter?id=606627;t=231;l=1"
++border=0 height=31 width=88
++alt="Ðåéòèíã@Mail.ru"></a><!--/LOGO-->
++<!--begin of Rambler's Top100 code -->
++<a href="http://top100.rambler.ru/top100/">
++<img src="http://counter.rambler.ru/top100.cnt?503447" alt="" width=1 height=1 border=0></a>
++<!--end of Top100 code-->
++</p>
+diff -urpN eggdrop1.6.19-orig/src/mod/logs2html.mod/user.css eggdrop1.6.19/src/mod/logs2html.mod/user.css
+--- src/mod/logs2html.mod/user.css 1970-01-01 00:00:00.000000000 +0000
++++ src/mod/logs2html.mod/user.css 2009-03-28 01:32:53.000000000 +0000
+@@ -0,0 +1,121 @@
++BODY {
++font-family: serif;
++font-style: normal
++font-variant: normal;
++font-weight: normal;
++font-stretch: normal;
++font-size: 12pt;
++text-align: left;
++color: rgb(0,0,0);
++background-color: transparent;
++}
++BODY.mainpage {
++background-color: whitesmoke;
++}
++BODY.logspage {
++background-color: lightyellow;
++}
++TD {
++width: 4%;
++background-color: lavender;
++}
++TD.space {
++width: auto;
++background-color: whitesmoke;
++}
++TD.dayname {
++width: auto;
++font-weight: bold;
++text-align: right;
++background-color: lightskyblue;
++}
++TD.weekend {
++color: red;
++width: auto;
++font-weight: bold;
++text-align: right;
++width: auto;
++background-color: lightskyblue;
++}
++TH {
++font-weight: bold;
++text-align: center;
++background-color: lavender;
++}
++SPAN.time {
++color: silver;
++}
++SPAN.nick {
++color: mediumblue;
++}
++SPAN.else {
++color: green;
++font-style: italic;
++}
++SPAN.action {
++color: violet;
++}
++SPAN.c0000, SPAN.c0100, SPAN.c0200, SPAN.c0300, SPAN.c0400, SPAN.c0500, SPAN.c0600, SPAN.c0700, SPAN.c0800, SPAN.c0900, SPAN.c1000, SPAN.c1100, SPAN.c1200, SPAN.c1300, SPAN.c1400, SPAN.c1500 {background-color: white;}
++SPAN.c0001, SPAN.c0101, SPAN.c0201, SPAN.c0301, SPAN.c0401, SPAN.c0501, SPAN.c0601, SPAN.c0701, SPAN.c0801, SPAN.c0901, SPAN.c1001, SPAN.c1101, SPAN.c1201, SPAN.c1301, SPAN.c1401, SPAN.c1501 {background-color: black;}
++SPAN.c0002, SPAN.c0102, SPAN.c0202, SPAN.c0302, SPAN.c0402, SPAN.c0502, SPAN.c0602, SPAN.c0702, SPAN.c0802, SPAN.c0902, SPAN.c1002, SPAN.c1102, SPAN.c1202, SPAN.c1302, SPAN.c1402, SPAN.c1502 {background-color: navy;}
++SPAN.c0003, SPAN.c0103, SPAN.c0203, SPAN.c0303, SPAN.c0403, SPAN.c0503, SPAN.c0603, SPAN.c0703, SPAN.c0803, SPAN.c0903, SPAN.c1003, SPAN.c1103, SPAN.c1203, SPAN.c1303, SPAN.c1403, SPAN.c1503 {background-color: green;}
++SPAN.c0004, SPAN.c0104, SPAN.c0204, SPAN.c0304, SPAN.c0404, SPAN.c0504, SPAN.c0604, SPAN.c0704, SPAN.c0804, SPAN.c0904, SPAN.c1004, SPAN.c1104, SPAN.c1204, SPAN.c1304, SPAN.c1404, SPAN.c1504 {background-color: red;}
++SPAN.c0005, SPAN.c0105, SPAN.c0205, SPAN.c0305, SPAN.c0405, SPAN.c0505, SPAN.c0605, SPAN.c0705, SPAN.c0805, SPAN.c0905, SPAN.c1005, SPAN.c1105, SPAN.c1205, SPAN.c1305, SPAN.c1405, SPAN.c1505 {background-color: maroon;}
++SPAN.c0006, SPAN.c0106, SPAN.c0206, SPAN.c0306, SPAN.c0406, SPAN.c0506, SPAN.c0606, SPAN.c0706, SPAN.c0806, SPAN.c0906, SPAN.c1006, SPAN.c1106, SPAN.c1206, SPAN.c1306, SPAN.c1406, SPAN.c1506 {background-color: purple;}
++SPAN.c0007, SPAN.c0107, SPAN.c0207, SPAN.c0307, SPAN.c0407, SPAN.c0507, SPAN.c0607, SPAN.c0707, SPAN.c0807, SPAN.c0907, SPAN.c1007, SPAN.c1107, SPAN.c1207, SPAN.c1307, SPAN.c1407, SPAN.c1507 {background-color: orange;}
++SPAN.c0008, SPAN.c0108, SPAN.c0208, SPAN.c0308, SPAN.c0408, SPAN.c0508, SPAN.c0608, SPAN.c0708, SPAN.c0808, SPAN.c0908, SPAN.c1008, SPAN.c1108, SPAN.c1208, SPAN.c1308, SPAN.c1408, SPAN.c1508 {background-color: yellow;}
++SPAN.c0009, SPAN.c0109, SPAN.c0209, SPAN.c0309, SPAN.c0409, SPAN.c0509, SPAN.c0609, SPAN.c0709, SPAN.c0809, SPAN.c0909, SPAN.c1009, SPAN.c1109, SPAN.c1209, SPAN.c1309, SPAN.c1409, SPAN.c1509 {background-color: lime;}
++SPAN.c0010, SPAN.c0110, SPAN.c0210, SPAN.c0310, SPAN.c0410, SPAN.c0510, SPAN.c0610, SPAN.c0710, SPAN.c0810, SPAN.c0910, SPAN.c1010, SPAN.c1110, SPAN.c1210, SPAN.c1310, SPAN.c1410, SPAN.c1510 {background-color: teal;}
++SPAN.c0011, SPAN.c0111, SPAN.c0211, SPAN.c0311, SPAN.c0411, SPAN.c0511, SPAN.c0611, SPAN.c0711, SPAN.c0811, SPAN.c0911, SPAN.c1011, SPAN.c1111, SPAN.c1211, SPAN.c1311, SPAN.c1411, SPAN.c1511 {background-color: cyan;}
++SPAN.c0012, SPAN.c0112, SPAN.c0212, SPAN.c0312, SPAN.c0412, SPAN.c0512, SPAN.c0612, SPAN.c0712, SPAN.c0812, SPAN.c0912, SPAN.c1012, SPAN.c1112, SPAN.c1212, SPAN.c1312, SPAN.c1412, SPAN.c1512 {background-color: blue;}
++SPAN.c0013, SPAN.c0113, SPAN.c0213, SPAN.c0313, SPAN.c0413, SPAN.c0513, SPAN.c0613, SPAN.c0713, SPAN.c0813, SPAN.c0913, SPAN.c1013, SPAN.c1113, SPAN.c1213, SPAN.c1313, SPAN.c1413, SPAN.c1513 {background-color: magenta;}
++SPAN.c0014, SPAN.c0114, SPAN.c0214, SPAN.c0314, SPAN.c0414, SPAN.c0514, SPAN.c0614, SPAN.c0714, SPAN.c0814, SPAN.c0914, SPAN.c1014, SPAN.c1114, SPAN.c1214, SPAN.c1314, SPAN.c1414, SPAN.c1514 {background-color: silver;}
++SPAN.c0015, SPAN.c0115, SPAN.c0215, SPAN.c0315, SPAN.c0415, SPAN.c0515, SPAN.c0615, SPAN.c0715, SPAN.c0815, SPAN.c0915, SPAN.c1015, SPAN.c1114, SPAN.c1215, SPAN.c1315, SPAN.c1415, SPAN.c1515 {background-color: gray;}
++SPAN.c0000, SPAN.c0001, SPAN.c0002, SPAN.c0003, SPAN.c0004, SPAN.c0005, SPAN.c0006, SPAN.c0007, SPAN.c0008, SPAN.c0009, SPAN.c0010, SPAN.c0011, SPAN.c0012, SPAN.c0013, SPAN.c0014, SPAN.c0015 {color: white;}
++SPAN.c0100, SPAN.c0101, SPAN.c0102, SPAN.c0103, SPAN.c0104, SPAN.c0105, SPAN.c0106, SPAN.c0107, SPAN.c0108, SPAN.c0109, SPAN.c0110, SPAN.c0111, SPAN.c0112, SPAN.c0113, SPAN.c0114, SPAN.c0115 {color: black;}
++SPAN.c0200, SPAN.c0201, SPAN.c0202, SPAN.c0203, SPAN.c0204, SPAN.c0205, SPAN.c0206, SPAN.c0207, SPAN.c0208, SPAN.c0209, SPAN.c0210, SPAN.c0211, SPAN.c0212, SPAN.c0213, SPAN.c0214, SPAN.c0215 {color: navy;}
++SPAN.c0300, SPAN.c0301, SPAN.c0302, SPAN.c0303, SPAN.c0304, SPAN.c0305, SPAN.c0306, SPAN.c0307, SPAN.c0308, SPAN.c0309, SPAN.c0310, SPAN.c0311, SPAN.c0312, SPAN.c0313, SPAN.c0314, SPAN.c0315 {color: green;}
++SPAN.c0400, SPAN.c0401, SPAN.c0402, SPAN.c0403, SPAN.c0404, SPAN.c0405, SPAN.c0406, SPAN.c0407, SPAN.c0408, SPAN.c0409, SPAN.c0410, SPAN.c0411, SPAN.c0412, SPAN.c0413, SPAN.c0414, SPAN.c0415 {color: red;}
++SPAN.c0500, SPAN.c0501, SPAN.c0502, SPAN.c0503, SPAN.c0504, SPAN.c0505, SPAN.c0506, SPAN.c0507, SPAN.c0508, SPAN.c0509, SPAN.c0510, SPAN.c0511, SPAN.c0512, SPAN.c0513, SPAN.c0514, SPAN.c0515 {color: maroon;}
++SPAN.c0600, SPAN.c0601, SPAN.c0602, SPAN.c0603, SPAN.c0604, SPAN.c0605, SPAN.c0606, SPAN.c0607, SPAN.c0608, SPAN.c0609, SPAN.c0610, SPAN.c0611, SPAN.c0612, SPAN.c0613, SPAN.c0614, SPAN.c0615 {color: purple;}
++SPAN.c0700, SPAN.c0701, SPAN.c0702, SPAN.c0703, SPAN.c0704, SPAN.c0705, SPAN.c0706, SPAN.c0707, SPAN.c0708, SPAN.c0709, SPAN.c0710, SPAN.c0711, SPAN.c0712, SPAN.c0713, SPAN.c0714, SPAN.c0715 {color: orange;}
++SPAN.c0800, SPAN.c0801, SPAN.c0802, SPAN.c0803, SPAN.c0804, SPAN.c0805, SPAN.c0806, SPAN.c0807, SPAN.c0808, SPAN.c0809, SPAN.c0810, SPAN.c0811, SPAN.c0812, SPAN.c0813, SPAN.c0814, SPAN.c0815 {color: yellow;}
++SPAN.c0900, SPAN.c0901, SPAN.c0902, SPAN.c0903, SPAN.c0904, SPAN.c0905, SPAN.c0906, SPAN.c0907, SPAN.c0908, SPAN.c0909, SPAN.c0910, SPAN.c0911, SPAN.c0912, SPAN.c0913, SPAN.c0914, SPAN.c0915 {color: lime;}
++SPAN.c1000, SPAN.c1001, SPAN.c1002, SPAN.c1003, SPAN.c1004, SPAN.c1005, SPAN.c1006, SPAN.c1007, SPAN.c1008, SPAN.c1009, SPAN.c1010, SPAN.c1011, SPAN.c1012, SPAN.c1013, SPAN.c1014, SPAN.c1015 {color: teal;}
++SPAN.c1100, SPAN.c1101, SPAN.c1102, SPAN.c1103, SPAN.c1104, SPAN.c1105, SPAN.c1106, SPAN.c1107, SPAN.c1108, SPAN.c1109, SPAN.c1110, SPAN.c1111, SPAN.c1112, SPAN.c1113, SPAN.c1114, SPAN.c1115 {color: cyan;}
++SPAN.c1200, SPAN.c1201, SPAN.c1202, SPAN.c1203, SPAN.c1204, SPAN.c1205, SPAN.c1206, SPAN.c1207, SPAN.c1208, SPAN.c1209, SPAN.c1210, SPAN.c1211, SPAN.c1212, SPAN.c1213, SPAN.c1214, SPAN.c1215 {color: blue;}
++SPAN.c1300, SPAN.c1301, SPAN.c1302, SPAN.c1303, SPAN.c1304, SPAN.c1305, SPAN.c1306, SPAN.c1307, SPAN.c1308, SPAN.c1309, SPAN.c1310, SPAN.c1311, SPAN.c1312, SPAN.c1313, SPAN.c1314, SPAN.c1315 {color: magenta;}
++SPAN.c1400, SPAN.c1401, SPAN.c1402, SPAN.c1403, SPAN.c1404, SPAN.c1405, SPAN.c1406, SPAN.c1407, SPAN.c1408, SPAN.c1409, SPAN.c1410, SPAN.c1411, SPAN.c1412, SPAN.c1413, SPAN.c1414, SPAN.c1415 {color: silver;}
++SPAN.c1500, SPAN.c1501, SPAN.c1502, SPAN.c1503, SPAN.c1504, SPAN.c1505, SPAN.c1506, SPAN.c1507, SPAN.c1508, SPAN.c1509, SPAN.c1510, SPAN.c1511, SPAN.c1512, SPAN.c1513, SPAN.c1514, SPAN.c1515 {color: gray;}
++SPAN.f00 {color: white;}
++SPAN.f01 {color: black;}
++SPAN.f02 {color: navy;}
++SPAN.f03 {color: green;}
++SPAN.f04 {color: red;}
++SPAN.f05 {color: maroon;}
++SPAN.f06 {color: purple;}
++SPAN.f07 {color: orange;}
++SPAN.f08 {color: yellow;}
++SPAN.f09 {color: lime;}
++SPAN.f10 {color: teal;}
++SPAN.f11 {color: cyan;}
++SPAN.f12 {color: blue;}
++SPAN.f13 {color: magenta;}
++SPAN.f14 {color: silver;}
++SPAN.f15 {color: gray;}
++SPAN.b00 {background-color: white;}
++SPAN.b01 {background-color: black;}
++SPAN.b02 {background-color: navy;}
++SPAN.b03 {background-color: green;}
++SPAN.b04 {background-color: red;}
++SPAN.b05 {background-color: maroon;}
++SPAN.b06 {background-color: purple;}
++SPAN.b07 {background-color: orange;}
++SPAN.b08 {background-color: yellow;}
++SPAN.b09 {background-color: lime;}
++SPAN.b10 {background-color: teal;}
++SPAN.b11 {background-color: cyan;}
++SPAN.b12 {background-color: blue;}
++SPAN.b13 {background-color: magenta;}
++SPAN.b14 {background-color: silver;}
++SPAN.b15 {background-color: gray;}
diff --git a/main/elinks/APKBUILD b/main/elinks/APKBUILD
new file mode 100644
index 0000000000..e32388b1a4
--- /dev/null
+++ b/main/elinks/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=elinks
+pkgver=0.11.7
+pkgrel=3
+pkgdesc="a text mode web browser"
+url="http://elinks.or.cz/"
+arch="all"
+license="GPL"
+depends=
+makedepends="bzip2-dev zlib-dev openssl-dev expat-dev libiconv-dev gettext-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://elinks.or.cz/download/elinks-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ # we should not link lua with -llualib
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --without-included-gettext
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ #fix conflict with gettext
+ rm "$pkgdir"/usr/share/locale/locale.alias
+}
+
+md5sums="fcd087a6d2415cd4c6fd1db53dceb646 elinks-0.11.7.tar.bz2"
diff --git a/main/email/APKBUILD b/main/email/APKBUILD
new file mode 100644
index 0000000000..9f184840cd
--- /dev/null
+++ b/main/email/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=email
+pkgver=3.1.3
+pkgrel=2
+pkgdesc="A command line SMTP client that's simple"
+url="http://www.cleancode.org/projects/email"
+arch="all"
+license="GPL"
+depends="openssl"
+makedepends="openssl-dev"
+source="http://www.cleancode.org/downloads/email/email-$pkgver.tar.bz2"
+
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="a6f55ad946b4492b9ad05af0d5e4f1fe email-3.1.3.tar.bz2"
diff --git a/main/email/email-3.1.0-doc.patch b/main/email/email-3.1.0-doc.patch
new file mode 100644
index 0000000000..d7467844f0
--- /dev/null
+++ b/main/email/email-3.1.0-doc.patch
@@ -0,0 +1,10 @@
+--- email-3.1.0.orig/configure.in Thu Jan 1 12:00:53 2009
++++ email-3.1.0/configure.in Thu Jan 1 12:01:16 2009
+@@ -65,7 +65,6 @@
+ CFLAGS="$CFLAGS -DUSE_GNU_STRFTIME"
+ fi
+
+-AC_SUBST(docdir, ["\${prefix}/doc/email-${version}"])
+ AC_SUBST(ver, ["$version"])
+
+ CFLAGS="$CFLAGS -I$cwd -I$cwd/src -I$cwd/include -I../include -I$cwd/dlib/include"
diff --git a/main/email/email-3.1.0-ldflags.patch b/main/email/email-3.1.0-ldflags.patch
new file mode 100644
index 0000000000..d08896ee3a
--- /dev/null
+++ b/main/email/email-3.1.0-ldflags.patch
@@ -0,0 +1,11 @@
+--- email-3.1.0.orig/src/Makefile.in Tue Dec 30 13:16:08 2008
++++ email-3.1.0/src/Makefile.in Tue Dec 30 13:17:00 2008
+@@ -18,7 +18,7 @@
+ remotesmtp.o sig_file.o smtpcommands.o utils.o
+
+ all: $(FILES)
+- $(CC) $(CFLAGS) -o email $(FILES) $(OTHER_FILES) $(LDFLAGS) $(LIBS) $(DLIB)
++ $(CC) $(CFLAGS) -o email $(FILES) $(OTHER_FILES) $(DLIB) $(LDFLAGS) $(LIBS)
+
+ clean:
+ rm -f *.o *.d email
diff --git a/main/enca/APKBUILD b/main/enca/APKBUILD
new file mode 100644
index 0000000000..cf7c90527d
--- /dev/null
+++ b/main/enca/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=enca
+pkgver=1.13
+pkgrel=2
+pkgdesc="Charset analyser and converter"
+url="http://freshmeat.net/projects/enca/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://dl.cihar.com/${pkgname}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --libexecdir=/usr/lib \
+ --enable-external \
+ --without-libiconv
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="762bead5d9a0a5e55024e1102baaa89d enca-1.13.tar.bz2"
diff --git a/main/enchant/APKBUILD b/main/enchant/APKBUILD
new file mode 100644
index 0000000000..9c22931e8f
--- /dev/null
+++ b/main/enchant/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=enchant
+pkgver=1.6.0
+pkgrel=5
+pkgdesc="A wrapper library for generic spell checking"
+url="http://www.abisource.com/enchant/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+depends_dev="glib-dev"
+makedepends="aspell-dev dbus-glib-dev hunspell-dev libiconv-dev gettext-dev"
+source="http://www.abisource.com/downloads/$pkgname/$pkgver/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="de11011aff801dc61042828041fb59c7 enchant-1.6.0.tar.gz"
diff --git a/main/encodings/APKBUILD b/main/encodings/APKBUILD
new file mode 100644
index 0000000000..06b883e895
--- /dev/null
+++ b/main/encodings/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=encodings
+pkgver=1.0.3
+pkgrel=1
+pkgdesc="X.org font encoding files"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig mkfontscale"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/encodings-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/encodings-$pkgver
+ ./configure --prefix=/usr \
+ --with-encodingsdir=/usr/share/fonts/encodings
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/encodings-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="29637480e7ce12546668631067c19ced encodings-1.0.3.tar.bz2"
diff --git a/main/epdfview/APKBUILD b/main/epdfview/APKBUILD
new file mode 100644
index 0000000000..4a2ad979b5
--- /dev/null
+++ b/main/epdfview/APKBUILD
@@ -0,0 +1,56 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=epdfview
+pkgver=0.1.8
+pkgrel=0
+pkgdesc="A free lightweight PDF document viewer."
+url="http://www.emma-soft.com/projects/epdfview/"
+arch="all"
+license="GPL"
+depends="desktop-file-utils hicolor-icon-theme"
+makedepends="poppler-gtk-dev cups-dev autoconf automake"
+source="http://www.emma-soft.com/projects/$pkgname/chrome/site/releases/$pkgname-$pkgver.tar.bz2
+ $pkgname.desktop.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "$i"
+ patch -p0 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ # make automake happy
+ touch ChangeLog
+
+ aclocal -I m4 && autoconf && automake && autoheader
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ for i in 24 32 48; do
+ install -d "$pkgdir"/usr/share/icons/hicolor/${i}x${i}/apps \
+ || return 1
+ done
+ install -m644 data/icon_epdfview-24.png \
+ "$pkgdir"/usr/share/icons/hicolor/24x24/apps/epdfview.png
+ install -m644 data/icon_epdfview-32.png \
+ "$pkgdir"/usr/share/icons/hicolor/32x32/apps/epdfview.png
+ install -m644 data/icon_epdfview-48.png \
+ "$pkgdir"/usr/share/icons/hicolor/48x48/apps/epdfview.png
+}
+
+md5sums="e50285b01612169b2594fea375f53ae4 epdfview-0.1.8.tar.bz2
+fbf22bbabdbb7544db615ac5775d57e2 epdfview.desktop.patch"
diff --git a/main/epdfview/epdfview.desktop.patch b/main/epdfview/epdfview.desktop.patch
new file mode 100644
index 0000000000..d86fc30883
--- /dev/null
+++ b/main/epdfview/epdfview.desktop.patch
@@ -0,0 +1,11 @@
+--- data/epdfview.desktop.bak 2009-04-05 16:55:56.000000000 -0700
++++ data/epdfview.desktop 2009-04-05 16:56:33.000000000 -0700
+@@ -7,7 +7,7 @@
+ GenericName=PDF Viewer
+ GenericName[ca]=Visor PDF
+ GenericName[es]=Visor PDF
+-Icon=icon_epdfview-48
++Icon=epdfview
+ Name=ePDFViewer
+ Name[ca]=ePDFViewer
+ Name[es]=ePDFViewer
diff --git a/main/epdfview/fix-scrolling.patch b/main/epdfview/fix-scrolling.patch
new file mode 100644
index 0000000000..828bf12587
--- /dev/null
+++ b/main/epdfview/fix-scrolling.patch
@@ -0,0 +1,33 @@
+--- ./src/gtk/MainView.cxx.old 2009-02-28 22:00:55.000000000 +0100
++++ ./src/gtk/MainView.cxx 2009-03-20 03:12:10.000000000 +0100
+@@ -77,7 +77,7 @@
+ static void main_window_zoom_out_cb (GtkWidget *, gpointer);
+ static void main_window_zoom_width_cb (GtkToggleAction *, gpointer);
+ static void main_window_set_page_mode (GtkRadioAction *, GtkRadioAction *, gpointer);
+-static void main_window_page_scrolled_cb (GtkWidget *widget, GdkEventScroll *event, gpointer data);
++static gboolean main_window_page_scrolled_cb (GtkWidget *widget, GdkEventScroll *event, gpointer data);
+
+ #if defined (HAVE_CUPS)
+ static void main_window_print_cb (GtkWidget *, gpointer);
+@@ -1479,18 +1479,19 @@
+ pter->setPageMode (mode);
+ }
+
+-void
++gboolean
+ main_window_page_scrolled_cb (GtkWidget *widget, GdkEventScroll *event, gpointer data)
+ {
+ g_assert ( NULL != data && "The data parameter is NULL.");
+
+ MainPter *pter = (MainPter *)data;
+ // Only zoom when the CTRL-Button is down...
+- if ( !(event->state & GDK_CONTROL_MASK) ) return;
++ if ( !(event->state & GDK_CONTROL_MASK) ) return FALSE;
+ if ( event->direction == GDK_SCROLL_UP ) {
+ pter->zoomInActivated ();
+ } else if ( event->direction == GDK_SCROLL_DOWN ) {
+ pter->zoomOutActivated ();
+ }
++ return TRUE;
+ }
+
diff --git a/main/epris/APKBUILD b/main/epris/APKBUILD
new file mode 100644
index 0000000000..5087b3cedd
--- /dev/null
+++ b/main/epris/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=epris
+pkgver=0.2
+pkgrel=2
+pkgdesc="Small audio player using GStreamer and DBus"
+url="http://code.google.com/p/epris/"
+arch="all"
+license="LGPL"
+depends=""
+makedepends="gstreamer-dev dbus-glib-dev"
+install=
+subpackages=
+source="http://epris.googlecode.com/files/epris-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="94ec5123207d34834eaa345435964f99 epris-0.2.tar.gz"
diff --git a/main/espeak/APKBUILD b/main/espeak/APKBUILD
new file mode 100644
index 0000000000..54357a2383
--- /dev/null
+++ b/main/espeak/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=espeak
+pkgver=1.45.04
+pkgrel=0
+pkgdesc="Speech synthesizer for English and other languages"
+url="http://espeak.sourceforge.net/"
+arch="all"
+license="GPL-3"
+subpackages="$pkgname-dev"
+depends=
+makedepends=
+source="http://downloads.sourceforge.net/project/espeak/espeak/espeak-${pkgver%.*}/espeak-$pkgver-source.zip"
+
+_builddir="$srcdir"/$pkgname-$pkgver-source
+
+build() {
+ cd "$_builddir"/src
+ make AUDIO=none || return 1
+}
+
+package() {
+ cd "$_builddir"/src
+ make AUDIO=none DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="6e810d2786b55cddb34f31b3eb813507 espeak-1.45.04-source.zip"
diff --git a/main/ethtool/APKBUILD b/main/ethtool/APKBUILD
new file mode 100644
index 0000000000..fc23e4a0ca
--- /dev/null
+++ b/main/ethtool/APKBUILD
@@ -0,0 +1,22 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ethtool
+pkgver=6
+pkgrel=2
+pkgdesc="gkernel ethtool"
+url="http://sourceforge.net/projects/gkernel/"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+source="http://easynews.dl.sf.net/sourceforge/gkernel/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-doc"
+
+build ()
+{
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+ make DESTDIR="$pkgdir" install
+}
+md5sums="3b721ec27f17ebf320ba8c505cf66d9c ethtool-6.tar.gz"
diff --git a/main/evince/APKBUILD b/main/evince/APKBUILD
new file mode 100644
index 0000000000..671720ec60
--- /dev/null
+++ b/main/evince/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=evince
+pkgver=2.32.0
+pkgrel=3
+pkgdesc="simple document viewer for GTK+"
+url="http://projects.gnome.org/evince/"
+arch="all"
+license="GPL"
+depends="gnome-icon-theme"
+depends_dev="gtk+-dev poppler-gtk-dev libsm-dev libevent-dev libxrandr-dev libx11-dev libxcursor-dev libxcomposite-dev libxi-dev util-linux-ng-dev"
+makedepends="$depends_dev intltool gnome-doc-utils"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-nautilus \
+ --disable-scrollkeeper \
+ --enable-pixbuf \
+ --without-gconf \
+ --without-keyring || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="ebc3ce6df8dcbf29cb9492f8dd031319 evince-2.32.0.tar.bz2"
diff --git a/main/exiv2/APKBUILD b/main/exiv2/APKBUILD
new file mode 100644
index 0000000000..32e24dc547
--- /dev/null
+++ b/main/exiv2/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=exiv2
+pkgver=0.21.1
+pkgrel=1
+pkgdesc="Exif and Iptc metadata manipulation library and tools."
+url="http://exiv2.org"
+arch="all"
+license="GPL2"
+depends=""
+depends_dev="expat-dev zlib-dev"
+makedepends="zlib-dev expat-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.exiv2.org/exiv2-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="5c99bbcaa998f6b200b92f2bf0ac4f9e exiv2-0.21.1.tar.gz"
diff --git a/main/exo/APKBUILD b/main/exo/APKBUILD
new file mode 100644
index 0000000000..27c1c80492
--- /dev/null
+++ b/main/exo/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=exo
+pkgver=0.6.2
+pkgrel=0
+pkgdesc="Extensions to Xfce by os-cillation"
+url="http://www.os-cillation.com/article.php?sid=40"
+arch="all"
+license="GPL-2 LGPL-2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="hicolor-icon-theme"
+makedepends="libxfce4util-dev perl perl-uri gtk+-dev libnotify-dev"
+install=
+source="http://archive.xfce.org/src/xfce/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="gtk+-dev libxfce4util-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static \
+ --disable-python \
+ --enable-notifications \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+md5sums="e25333df350abc30999cd16fe96ab690 exo-0.6.2.tar.bz2"
diff --git a/main/expat/APKBUILD b/main/expat/APKBUILD
new file mode 100644
index 0000000000..8ffc997804
--- /dev/null
+++ b/main/expat/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=expat
+pkgver=2.0.1
+pkgrel=6
+pkgdesc="An XML Parser library written in C"
+url="http://www.libexpat.org/"
+arch="all"
+license='AS IS'
+depends=
+makedepends=
+source="http://surfnet.dl.sourceforge.net/sourceforge/expat/expat-2.0.1.tar.gz
+ CVE-2009-3560.patch
+ CVE-2009-3720.patch
+ "
+subpackages="$pkgname-dev $pkgname-doc"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ [ -f "$i" ] || continue
+ msg "Applying $i"
+ patch -p1 -i "$i" || return 1
+ done
+
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir/" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="ee8b492592568805593f81f8cdf2a04c expat-2.0.1.tar.gz
+50603cac0f03aabc7087415251f592be CVE-2009-3560.patch
+f3eeb796f28945899216b815e5901996 CVE-2009-3720.patch"
diff --git a/main/expat/CVE-2009-3560.patch b/main/expat/CVE-2009-3560.patch
new file mode 100644
index 0000000000..5fe9c36c82
--- /dev/null
+++ b/main/expat/CVE-2009-3560.patch
@@ -0,0 +1,13 @@
+diff -urNad trunk~/lib/xmlparse.c trunk/lib/xmlparse.c
+--- trunk~/lib/xmlparse.c 2007-05-08 04:25:35.000000000 +0200
++++ trunk/lib/xmlparse.c 2009-12-29 21:57:22.141732904 +0100
+@@ -3703,6 +3703,9 @@
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
++ case -XML_TOK_PROLOG_S:
++ tok = -tok;
++ break;
+ case XML_TOK_NONE:
+ #ifdef XML_DTD
+ /* for internal PE NOT referenced between declarations */
diff --git a/main/expat/CVE-2009-3720.patch b/main/expat/CVE-2009-3720.patch
new file mode 100644
index 0000000000..65d16431f4
--- /dev/null
+++ b/main/expat/CVE-2009-3720.patch
@@ -0,0 +1,12 @@
+diff -urNad trunk~/lib/xmltok_impl.c trunk/lib/xmltok_impl.c
+--- trunk~/lib/xmltok_impl.c 2006-11-26 18:34:46.000000000 +0100
++++ trunk/lib/xmltok_impl.c 2009-10-22 21:42:41.000000000 +0200
+@@ -1744,7 +1744,7 @@
+ const char *end,
+ POSITION *pos)
+ {
+- while (ptr != end) {
++ while (ptr < end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ #define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
diff --git a/main/ez-ipupdate/APKBUILD b/main/ez-ipupdate/APKBUILD
new file mode 100644
index 0000000000..3529150396
--- /dev/null
+++ b/main/ez-ipupdate/APKBUILD
@@ -0,0 +1,49 @@
+# Contributor: Jeremy Thomerson <jeremy@thomersonfamily.com>
+# Maintainer: Jeremy Thomerson <jeremy@thomersonfamily.com>
+pkgname=ez-ipupdate
+pkgver=3.0.10
+pkgrel=2
+pkgdesc="utility for updating your host name for many of the dynamic DNS services (ez-ip.net, dyndns.org, etc)"
+url="http://ez-ipupdate.com/"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages=""
+source="http://ez-ipupdate.com/dist/$pkgname-$pkgver.tar.gz
+ ez-ipupdate.confd
+ ez-ipupdate.initd
+ errno.patch
+ "
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for A in ../*.patch ; do
+ patch -p1 < $A
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ install -d "$pkgdir"/var/lib/$pkgname
+ install -d "$pkgdir"/var/run/$pkgname
+}
+
+md5sums="6505c9d18ef6b5ce13fe2a668eb5724b ez-ipupdate-3.0.10.tar.gz
+e6e06780b1896f2250132cc16cd10710 ez-ipupdate.confd
+6b9ce71b7b6b739794f003b2ebbf66ed ez-ipupdate.initd
+1fede0dcb5d9ca108855df0a9d213413 errno.patch"
diff --git a/main/ez-ipupdate/errno.patch b/main/ez-ipupdate/errno.patch
new file mode 100644
index 0000000000..fea5258072
--- /dev/null
+++ b/main/ez-ipupdate/errno.patch
@@ -0,0 +1,56 @@
+# --- T2-COPYRIGHT-NOTE-BEGIN ---
+# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
+#
+# T2 SDE: package/.../ezipupdate/errno.patch
+# Copyright (C) 2004 - 2005 The T2 SDE Project
+# Copyright (C) 1998 - 2003 ROCK Linux Project
+#
+# More information can be found in the files COPYING and README.
+#
+# This patch file is dual-licensed. It is available under the license the
+# patched project is licensed under, as long as it is an OpenSource license
+# as defined at http://www.opensource.org/ (e.g. BSD, X11) or 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.
+# --- T2-COPYRIGHT-NOTE-END ---
+
+--- ./conf_file.c.orig 2000-10-23 04:36:18.000000000 +0200
++++ ./conf_file.c 2003-05-28 08:42:42.000000000 +0200
+@@ -1,4 +1,4 @@
+-/* ============================================================================
++ /* ============================================================================
+ * Copyright (C) 1999 Angus Mackay. All rights reserved;
+ *
+ * This program is free software; you can redistribute it and/or modify
+@@ -37,13 +37,16 @@
+
+ #include <conf_file.h>
+
+-#if HAVE_STRERROR
++#if HAVE_ERRNO_H
++# include <errno.h>
++#elif HAVE_STRERROR
+ extern int errno;
+ # define error_string strerror(errno)
+-#elif HAVE_SYS_ERRLIST
+-extern const char *const sys_errlist[];
+-extern int errno;
+-# define error_string (sys_errlist[errno])
++#endif
++
++#if HAVE_SYS_ERRLIST
++//extern char *const strerror[];
++# define error_string (strerror[errno])
+ #else
+ # define error_string "error message not found"
+ #endif
+@@ -85,7 +88,7 @@ int parse_conf_file(char *fname, struct
+ {
+ if((in=fopen(fname, "r")) == NULL)
+ {
+- fprintf(stderr, "could not open config file \"%s\": %s\n", fname, error_string);
++ fprintf(stderr, "could not open config file \"%s\"\n", fname);
+ return(-1);
+ }
+ }
diff --git a/main/ez-ipupdate/ez-ipupdate.confd b/main/ez-ipupdate/ez-ipupdate.confd
new file mode 100644
index 0000000000..10349cff45
--- /dev/null
+++ b/main/ez-ipupdate/ez-ipupdate.confd
@@ -0,0 +1,34 @@
+# conf.d file for ez-ipupdate
+
+# NOTE: all of the options defined in this configuration file need
+# to remain in the file (do not remove them). modify them as needed
+# or leave them at the default
+
+# the type of service that you are using
+# try one of: ezip, pgpow, dhs, dyndns,
+# dyndns-static, ods, tzo, gnudip, easydns,
+# justlinux, dyns, hn, zoneedit
+SERVICE=""
+
+# What hostname are you updating?
+HOST=your-domain.service-domain.tld
+
+# Credentials used to update the service
+USER=yourusername
+PASS=yourpassword
+
+# Which interface has the IP to be updated?
+IFACE="eth0"
+
+# If you want your domain to have a wildcard alias, set this to 1
+WILDCARD=0
+
+# If you need to override the server to send updates to, do it here.
+# You can also specify the port, in this format: server[:port]
+SERVER=
+
+# max time in between updates (seconds - must be 86400 or larger)
+MAX_INTERVAL=86400
+
+# I/O timeout (seconds.millis)
+TIMEOUT=45.0
diff --git a/main/ez-ipupdate/ez-ipupdate.initd b/main/ez-ipupdate/ez-ipupdate.initd
new file mode 100644
index 0000000000..4ec662694a
--- /dev/null
+++ b/main/ez-ipupdate/ez-ipupdate.initd
@@ -0,0 +1,52 @@
+#!/sbin/runscript
+
+# init.d file for ez-ipupdate
+
+NAME=ez-ipupdate
+DAEMON=/usr/bin/$NAME
+DAEMON_GROUP=ipupdate
+DAEMON_USER=ipupdate
+
+# now convert it into command line options
+OPTS="-d -S ${SERVICE} -h ${HOST} -u \"${USER}:${PASS}\" -i ${IFACE}"
+if [ "$WILDCARD" == 1 ]; then
+ OPTS="${OPTS} -w"
+fi
+if [ "$SERVER" != "" ]; then
+ OPTS="${OPTS} -s \"${SERVER}\""
+fi
+OPTS="${OPTS} -t ${TIMEOUT} -M ${MAX_INTERVAL}"
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet \
+ --pidfile /var/run/${NAME}/${NAME}.pid \
+ --chuid ${DAEMON_USER}:${DAEMON_GROUP} \
+ --exec ${DAEMON} -- ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --pidfile /var/run/${NAME}/${NAME}.pid \
+ --exec ${DAEMON}
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading ${NAME}"
+ if ! service_started "${NAME}" ; then
+ eend 1 "${NAME} is not started"
+ return 1
+ fi
+ start-stop-daemon --stop --oknodo --signal HUP \
+ --exec ${DAEMON} --pidfile /var/run/${NAME}.pid
+ eend $?
+}
+
diff --git a/main/ez-ipupdate/ez-ipupdate.post-install b/main/ez-ipupdate/ez-ipupdate.post-install
new file mode 100644
index 0000000000..846c21102b
--- /dev/null
+++ b/main/ez-ipupdate/ez-ipupdate.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+chown ipupdate:ipupdate var/run/ez-ipupdate var/lib/ez-ipupdate
+exit 0
+
diff --git a/main/ez-ipupdate/ez-ipupdate.pre-install b/main/ez-ipupdate/ez-ipupdate.pre-install
new file mode 100644
index 0000000000..a8d0c4791c
--- /dev/null
+++ b/main/ez-ipupdate/ez-ipupdate.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /var/lib/ez-ipupdate -s /bin/false -D ipupdate 2>/dev/null
+exit 0
+
diff --git a/main/faac/APKBUILD b/main/faac/APKBUILD
new file mode 100644
index 0000000000..11dc6ab21e
--- /dev/null
+++ b/main/faac/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=faac
+pkgver=1.28
+pkgrel=7
+pkgdesc="FAAC is an AAC audio encoder."
+url="http://www.audiocoding.com/"
+arch="all"
+license="GPL custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="autoconf automake libtool"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.gz
+"
+
+prepare() {
+ cd "$srcdir/$pkgname-$pkgver"
+ #taken from http://bugs.sourcemage.org/show_bug.cgi?id=15263
+ if [ "$ALPINE_LIBC" = "eglibc" ]; then
+ sed -i \
+ "s/^\(.*strcasestr\)/\/\/ This is in libc and conflicts: \1 /" \
+ common/mp4v2/mpeg4ip.h
+ fi
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./bootstrap
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 "$srcdir"/$pkgname-$pkgver/libfaac/kiss_fft/COPYING \
+ "$pkgdir"/usr/share/licenses/faac/COPYING.kiss_fft
+}
+md5sums="80763728d392c7d789cde25614c878f6 faac-1.28.tar.gz"
diff --git a/main/faad2/APKBUILD b/main/faad2/APKBUILD
new file mode 100644
index 0000000000..7a9fa614b0
--- /dev/null
+++ b/main/faad2/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=faad2
+pkgver=2.7
+pkgrel=5
+pkgdesc="ISO AAC audio decoder"
+url="http://www.audiocoding.com/"
+arch="all"
+license="custom:GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="autoconf automake libtool"
+source="http://downloads.sourceforge.net/sourceforge/faac/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+
+ # manfile has bad name
+ mv frontend/faad.man frontend/faad.1 && \
+ sed -i -e 's:faad\.man:faad.1:' frontend/Makefile.am \
+ || return 1
+
+ sh bootstrap
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -m644 common/mp4ff/mp4ff_int_types.h "$pkgdir"/usr/include/mp4ff_int_types.h || return 1
+}
+md5sums="4c332fa23febc0e4648064685a3d4332 faad2-2.7.tar.bz2"
diff --git a/main/fail2ban/APKBUILD b/main/fail2ban/APKBUILD
new file mode 100644
index 0000000000..170032b4e1
--- /dev/null
+++ b/main/fail2ban/APKBUILD
@@ -0,0 +1,48 @@
+# Contributor: Jeff Bilyk <jbilyk@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fail2ban
+pkgver=0.8.4
+pkgrel=2
+pkgdesc="Scans log files for login failures then updates iptables to reject originating ip address"
+url="http://www.fail2ban.org"
+arch="noarch"
+license="GPLv2"
+depends="python iptables logrotate"
+makedepends="python-dev"
+install=""
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2
+ gentoo-initd_create_run_dir.patch
+ fail2ban.confd
+ fail2ban.logrotate
+ "
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir" || return 1
+ install -Dm755 files/gentoo-initd "$pkgdir"/etc/init.d/fail2ban \
+ || return 1
+ install -Dm644 "$srcdir"/fail2ban.confd "$pkgdir"/etc/conf.d/fail2ban \
+ || return 1
+ install -Dm644 "$srcdir"/fail2ban.logrotate \
+ "$pkgdir"/etc/logrotate.d/fail2ban || return 1
+}
+
+md5sums="df94335a5d12b4750869e5fe350073fa fail2ban-0.8.4.tar.bz2
+61580eb6d8d9a4d187e97bc27f2fcb1e gentoo-initd_create_run_dir.patch
+b209a04f9314dd064a4aa0ee505c8a4d fail2ban.confd
+6d1af6ceebd15c8ae3938bc675efe553 fail2ban.logrotate"
diff --git a/main/fail2ban/fail2ban.confd b/main/fail2ban/fail2ban.confd
new file mode 100644
index 0000000000..3c957b9221
--- /dev/null
+++ b/main/fail2ban/fail2ban.confd
@@ -0,0 +1,8 @@
+# Config file for /etc/init.d/fail2ban
+
+# For information on options, see "/usr/bin/fail2ban-client -h".
+
+FAIL2BAN_OPTIONS=""
+
+# Force execution of the server even if the socket already exists:
+#FAIL2BAN_OPTIONS="-x"
diff --git a/main/fail2ban/fail2ban.logrotate b/main/fail2ban/fail2ban.logrotate
new file mode 100644
index 0000000000..5d22bd0395
--- /dev/null
+++ b/main/fail2ban/fail2ban.logrotate
@@ -0,0 +1,9 @@
+/var/log/fail2ban.log {
+ daily
+ rotate 7
+ missingok
+ compress
+ postrotate
+ /usr/bin/fail2ban-client set logtarget /var/log/fail2ban.log 1>/dev/null || true
+ endscript
+}
diff --git a/main/fail2ban/gentoo-initd_create_run_dir.patch b/main/fail2ban/gentoo-initd_create_run_dir.patch
new file mode 100644
index 0000000000..79a947956e
--- /dev/null
+++ b/main/fail2ban/gentoo-initd_create_run_dir.patch
@@ -0,0 +1,19 @@
+Index: fail2ban-0.8.4/files/gentoo-initd
+===================================================================
+--- fail2ban-0.8.4.orig/files/gentoo-initd
++++ fail2ban-0.8.4/files/gentoo-initd
+@@ -31,6 +31,14 @@ depend() {
+
+ start() {
+ ebegin "Starting fail2ban"
++ if [ ! -d /var/run/fail2ban ]; then
++ mkdir /var/run/fail2ban || return 1
++ fi
++ if [ -e /var/run/fail2ban/fail2ban.sock ]; then
++ # remove stalled sock file after system crash
++ # bug 347477
++ rm -rf /var/run/fail2ban/fail2ban.sock || return 1
++ fi
+ ${FAIL2BAN} start &> /dev/null
+ eend $? "Failed to start fail2ban"
+ }
diff --git a/main/fakeroot/APKBUILD b/main/fakeroot/APKBUILD
new file mode 100644
index 0000000000..5e062ebffd
--- /dev/null
+++ b/main/fakeroot/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fakeroot
+pkgver=1.15.1
+pkgrel=0
+pkgdesc="Gives a fake root environment, useful for building packages as a non-privileged user"
+arch="all"
+license='GPL'
+url="http://packages.debian.org/fakeroot"
+depends=
+subpackages="$pkgname-doc"
+source="http://ftp.debian.org/debian/pool/main/f/$pkgname/${pkgname}_${pkgver}.orig.tar.bz2
+ busybox-compat.patch"
+
+prepare() {
+ cd $startdir/src/$pkgname-$pkgver
+ patch -p1 < ../busybox-compat.patch
+}
+
+build() {
+ cd $startdir/src/$pkgname-$pkgver
+ CONFIG_SHELL=/bin/sh ./configure --prefix=/usr --disable-static
+ make || return 1
+}
+
+package() {
+ cd $startdir/src/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="248c408b1e06e776c5739871b49bd968 fakeroot_1.15.1.orig.tar.bz2
+ea7b7e3065090d72804cdf4719dd5832 busybox-compat.patch"
diff --git a/main/fakeroot/busybox-compat.patch b/main/fakeroot/busybox-compat.patch
new file mode 100644
index 0000000000..1d07d0d31a
--- /dev/null
+++ b/main/fakeroot/busybox-compat.patch
@@ -0,0 +1,23 @@
+--- fakeroot-1.10.1.orig/scripts/fakeroot.in Wed Nov 5 19:48:00 2008
++++ fakeroot-1.10.1/scripts/fakeroot.in Wed Nov 5 19:49:12 2008
+@@ -28,7 +28,7 @@
+
+ libfound=no
+
+-GETOPTEST=`getopt --version`
++GETOPTEST=`getopt --version 2>/dev/null`
+ case $GETOPTEST in
+ getopt*) # GNU getopt
+ TEMP=`getopt -l lib: -l faked: -l unknown-is-real -l fd-base: -l version -l help -- +l:f:i:s:ub:vh "$@"`
+@@ -133,9 +133,9 @@
+ PID=`echo $KEY_PID|cut -d: -f2`
+
+ if [ "$WAITINTRAP" -eq 0 ]; then
+- trap "kill -s @signal@ $PID" EXIT INT
++ trap "kill -@signal@ $PID" EXIT INT
+ else
+- trap 'FAKEROOTKEY=$FAKEROOTKEY LD_LIBRARY_PATH="$PATHS" LD_PRELOAD="$LIB" /bin/ls -l / >/dev/null 2>&1; while kill -s @signal@ $PID 2>/dev/null; do sleep 0.1; done' EXIT INT
++ trap 'FAKEROOTKEY=$FAKEROOTKEY LD_LIBRARY_PATH="$PATHS" LD_PRELOAD="$LIB" /bin/ls -l / >/dev/null 2>&1; while kill -@signal@ $PID 2>/dev/null; do sleep 0.1; done' EXIT INT
+ fi
+
+ if test -z "$FAKEROOTKEY" || test -z "$PID"; then
diff --git a/main/fastjar/APKBUILD b/main/fastjar/APKBUILD
new file mode 100644
index 0000000000..59ce15d07d
--- /dev/null
+++ b/main/fastjar/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=fastjar
+pkgver=0.98
+pkgrel=0
+pkgdesc="A fast implementation of Java Archiver"
+url="http://savannah.nongnu.org/projects/fastjar"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="zlib-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://download.savannah.gnu.org/releases/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir=$srcdir/$pkgname-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="d2d264d343d4d0e1575832cc1023c3bf fastjar-0.98.tar.gz"
diff --git a/main/fcgi/10-fcgi-2.4.0-Makefile.patch b/main/fcgi/10-fcgi-2.4.0-Makefile.patch
new file mode 100644
index 0000000000..dad4cd6e02
--- /dev/null
+++ b/main/fcgi/10-fcgi-2.4.0-Makefile.patch
@@ -0,0 +1,24 @@
+Index: fcgi-2.4.0/cgi-fcgi/Makefile.am
+===================================================================
+--- fcgi-2.4.0.orig/cgi-fcgi/Makefile.am
++++ fcgi-2.4.0/cgi-fcgi/Makefile.am
+@@ -11,5 +11,5 @@ INCLUDE_FILES = $(INCLUDEDIR)/fastcgi.
+ LIBDIR = ../libfcgi
+ LIBFCGI = $(LIBDIR)/libfcgi.la
+
+-LDADD = $(LIBFCGI)
++LDADD = $(LIBFCGI) -lm
+ cgi_fcgi_SOURCES = $(INCLUDE_FILES) cgi-fcgi.c
+Index: fcgi-2.4.0/examples/Makefile.am
+===================================================================
+--- fcgi-2.4.0.orig/examples/Makefile.am
++++ fcgi-2.4.0/examples/Makefile.am
+@@ -21,7 +21,7 @@ INCLUDE_FILES = $(INCLUDEDIR)/fastcgi.
+ LIBDIR = ../libfcgi
+ LIBFCGI = $(LIBDIR)/libfcgi.la
+
+-LDADD = $(LIBFCGI)
++LDADD = $(LIBFCGI) -lm
+
+ echo_SOURCES = $(INCLUDE_FILES) echo.c
+ echo_x_SOURCES = $(INCLUDE_FILES) echo-x.c
diff --git a/main/fcgi/20-fcgi-2.4.0-clientdata-pointer.patch b/main/fcgi/20-fcgi-2.4.0-clientdata-pointer.patch
new file mode 100644
index 0000000000..ba4793765d
--- /dev/null
+++ b/main/fcgi/20-fcgi-2.4.0-clientdata-pointer.patch
@@ -0,0 +1,96 @@
+Index: fcgi-2.4.0/cgi-fcgi/cgi-fcgi.c
+===================================================================
+--- fcgi-2.4.0.orig/cgi-fcgi/cgi-fcgi.c
++++ fcgi-2.4.0/cgi-fcgi/cgi-fcgi.c
+@@ -21,6 +21,7 @@ static const char rcsid[] = "$Id: cgi-fc
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <sys/types.h>
+
+ #include "fcgi_config.h"
+
+@@ -145,7 +146,7 @@ static FCGI_BeginRequestBody MakeBeginRe
+
+
+ static int bytesToRead; /* number of bytes to read from Web Server */
+-static int appServerSock = -1; /* Socket connected to FastCGI application,
++static size_t appServerSock = -1; /* Socket connected to FastCGI application,
+ * used by AppServerReadHandler and
+ * AppServerWriteHandler. */
+ static Buffer fromAS; /* Bytes read from the FCGI application server. */
+@@ -640,7 +641,7 @@ static int ParseArgs(int argc, char *arg
+ }
+ if((av[ac] = (char *)malloc(strlen(tp1)+1)) == NULL) {
+ fprintf(stderr, "Cannot allocate %d bytes\n",
+- strlen(tp1)+1);
++ (int)strlen(tp1)+1);
+ exit(-1);
+ }
+ strcpy(av[ac++], tp1);
+Index: fcgi-2.4.0/examples/threaded.c
+===================================================================
+--- fcgi-2.4.0.orig/examples/threaded.c
++++ fcgi-2.4.0/examples/threaded.c
+@@ -24,7 +24,7 @@ static int counts[THREAD_COUNT];
+
+ static void *doit(void *a)
+ {
+- int rc, i, thread_id = (int)a;
++ size_t rc, i, thread_id = (size_t)a;
+ pid_t pid = getpid();
+ FCGX_Request request;
+ char *server_name;
+@@ -53,7 +53,7 @@ static void *doit(void *a)
+ "<h1>FastCGI Hello! (multi-threaded C, fcgiapp library)</h1>"
+ "Thread %d, Process %ld<p>"
+ "Request counts for %d threads running on host <i>%s</i><p><code>",
+- thread_id, pid, THREAD_COUNT, server_name ? server_name : "?");
++ (int)thread_id, pid, THREAD_COUNT, server_name ? server_name : "?");
+
+ sleep(2);
+
+@@ -71,7 +71,7 @@ static void *doit(void *a)
+
+ int main(void)
+ {
+- int i;
++ size_t i;
+ pthread_t id[THREAD_COUNT];
+
+ FCGX_Init();
+Index: fcgi-2.4.0/include/fcgios.h
+===================================================================
+--- fcgi-2.4.0.orig/include/fcgios.h
++++ fcgi-2.4.0/include/fcgios.h
+@@ -93,7 +93,7 @@ extern "C" {
+ # if defined(__STDC__) || defined(__cplusplus)
+ typedef void *ClientData;
+ # else
+- typedef int *ClientData;
++ typedef size_t *ClientData;
+ # endif /* __STDC__ */
+ #define _CLIENTDATA
+ #endif
+Index: fcgi-2.4.0/libfcgi/os_unix.c
+===================================================================
+--- fcgi-2.4.0.orig/libfcgi/os_unix.c
++++ fcgi-2.4.0/libfcgi/os_unix.c
+@@ -1155,7 +1155,7 @@ int OS_Accept(int listen_sock, int fail_
+
+ for (;;) {
+ do {
+-#ifdef HAVE_SOCKLEN
++#ifdef HAVE_SYS_SOCKET_H
+ socklen_t len = sizeof(sa);
+ #else
+ int len = sizeof(sa);
+@@ -1255,7 +1255,7 @@ int OS_IsFcgi(int sock)
+ struct sockaddr_in in;
+ struct sockaddr_un un;
+ } sa;
+-#ifdef HAVE_SOCKLEN
++#ifdef HAVE_SYS_SOCKET_H
+ socklen_t len = sizeof(sa);
+ #else
+ int len = sizeof(sa);
diff --git a/main/fcgi/30-fcgi-2.4.0-html-updates.patch b/main/fcgi/30-fcgi-2.4.0-html-updates.patch
new file mode 100644
index 0000000000..ca10a6a603
--- /dev/null
+++ b/main/fcgi/30-fcgi-2.4.0-html-updates.patch
@@ -0,0 +1,65 @@
+Index: fcgi-2.4.0/doc/fcgi-devel-kit.htm
+===================================================================
+--- fcgi-2.4.0.orig/doc/fcgi-devel-kit.htm
++++ fcgi-2.4.0/doc/fcgi-devel-kit.htm
+@@ -19,7 +19,7 @@
+ </HEAD>
+ <BODY>
+ <P CLASS="c1">
+- <IMG BORDER="0" SRC="../images/fcgi-hd.gif" ALT="[[FastCGI]]"><BR CLEAR="all">
++ <IMG BORDER="0" SRC="images/fcgi-hd.gif" ALT="[[FastCGI]]"><BR CLEAR="all">
+ </P>
+ <H3 CLASS="c2">
+ FastCGI Developer&#39;s Kit
+Index: fcgi-2.4.0/doc/fcgi-java.htm
+===================================================================
+--- fcgi-2.4.0.orig/doc/fcgi-java.htm
++++ fcgi-2.4.0/doc/fcgi-java.htm
+@@ -20,7 +20,7 @@
+ </HEAD>
+ <BODY>
+ <DIV CLASS="c1">
+- <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="../images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
++ <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
+ </DIV>
+ <BR CLEAR="all">
+ <DIV CLASS="c1">
+Index: fcgi-2.4.0/doc/fcgi-perf.htm
+===================================================================
+--- fcgi-2.4.0.orig/doc/fcgi-perf.htm
++++ fcgi-2.4.0/doc/fcgi-perf.htm
+@@ -19,7 +19,7 @@
+ </HEAD>
+ <BODY>
+ <DIV CLASS="c1">
+- <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="../images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
++ <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
+ </DIV>
+ <BR CLEAR="all">
+ <DIV CLASS="c1">
+Index: fcgi-2.4.0/doc/fcgi-perl.htm
+===================================================================
+--- fcgi-2.4.0.orig/doc/fcgi-perl.htm
++++ fcgi-2.4.0/doc/fcgi-perl.htm
+@@ -19,7 +19,7 @@
+ </HEAD>
+ <BODY>
+ <DIV CLASS="c1">
+- <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="../images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
++ <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
+ </DIV>
+ <BR CLEAR="all">
+
+Index: fcgi-2.4.0/doc/fcgi-tcl.htm
+===================================================================
+--- fcgi-2.4.0.orig/doc/fcgi-tcl.htm
++++ fcgi-2.4.0/doc/fcgi-tcl.htm
+@@ -19,7 +19,7 @@
+ </HEAD>
+ <BODY>
+ <DIV CLASS="c1">
+- <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="../images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
++ <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
+ </DIV>
+ <BR CLEAR="all">
+ <DIV CLASS="c1">
diff --git a/main/fcgi/APKBUILD b/main/fcgi/APKBUILD
new file mode 100644
index 0000000000..2b30b364fe
--- /dev/null
+++ b/main/fcgi/APKBUILD
@@ -0,0 +1,48 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=fcgi
+pkgver=2.4.0
+pkgrel=5
+pkgdesc="FAST CGI(fcgi) is a language independent, high performant extension to CGI"
+url="http://www.fastcgi.com"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+subpackages="$pkgname-dev"
+source="http://www.fastcgi.com/dist/${pkgname}-${pkgver}.tar.gz
+20-fcgi-2.4.0-clientdata-pointer.patch
+30-fcgi-2.4.0-html-updates.patch"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+
+ export LIBS="$LIBS -lm"
+
+ # seems like there is no way to disable c++ from configure script
+ # the row below helps us to build even if g++ is installed on system
+ export CXX=false
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-shared
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+}
+
+md5sums="d15060a813b91383a9f3c66faf84867e fcgi-2.4.0.tar.gz
+d2654525f06451c99b8cdd4cc00a963b 20-fcgi-2.4.0-clientdata-pointer.patch
+f26b536786f70b30a2d91c83d56e944c 30-fcgi-2.4.0-html-updates.patch"
diff --git a/main/feh/APKBUILD b/main/feh/APKBUILD
new file mode 100644
index 0000000000..9588bea379
--- /dev/null
+++ b/main/feh/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=feh
+pkgver=1.14.1
+pkgrel=0
+pkgdesc="feh is a fast, lightweight image viewer which uses imlib2"
+url="http://www.linuxbrit.co.uk/feh/"
+arch="all"
+license="MIT"
+subpackages="$pkgname-doc"
+depends=
+makedepends="libxt-dev libpng-dev giblib-dev imlib2-dev jpeg-dev
+ libxinerama-dev wget curl-dev"
+source="https://derf.homelinux.org/~derf/projects/${pkgname}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ sed -i -e "s:/usr/local:/usr:g" config.mk
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR=$pkgdir docsdir=/usr/share/doc/feh install || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+md5sums="88817761f2fa55629f4826528df3b9e5 feh-1.14.1.tar.bz2"
diff --git a/main/ferm/APKBUILD b/main/ferm/APKBUILD
new file mode 100644
index 0000000000..48ab66ef43
--- /dev/null
+++ b/main/ferm/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=ferm
+pkgver=2.0.5
+pkgrel=1
+pkgdesc="firewall configuration tool"
+url="http://ferm.foo-projects.org/"
+arch="all"
+license="GPL"
+depends="perl iptables"
+makedepends=""
+install=
+subpackages=""
+source="http://ferm.foo-projects.org/download/2.0/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ install -m755 -D "$srcdir"/"$pkgname-$pkgver"/src/ferm "$pkgdir"/usr/sbin/"$pkgname"
+ install -m755 -D "$srcdir"/"$pkgname-$pkgver"/src/import-ferm "$pkgdir"/usr/sbin/import-ferm
+}
+
+md5sums="e77db05360877299cb6fa8c5b51a5e77 ferm-2.0.5.tar.gz"
diff --git a/main/fetchmail/APKBUILD b/main/fetchmail/APKBUILD
new file mode 100644
index 0000000000..c18f2e382a
--- /dev/null
+++ b/main/fetchmail/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fetchmail
+pkgver=6.3.20
+pkgrel=1
+pkgdesc="A remote-mail retrieval and forwarding utility"
+url="http://fetchmail.berlios.de/"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev python"
+install="fetchmail.pre-install fetchmail.post-install"
+subpackages="$pkgname-doc fetchmailconf"
+source="http://download.berlios.de/fetchmail/$pkgname-$pkgver.tar.bz2
+ fetchmail.initd"
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-ssl \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ install -Dm755 "$srcdir"/fetchmail.initd "$pkgdir"/etc/init.d/fetchmail
+ install -d "$pkgdir"/var/lib/fetchmail "$pkgdir"/var/run/fetchmail
+}
+
+fetchmailconf() {
+ depends="python"
+ pkgdesc="A GUI for generating fetchmail configuration files"
+ install=
+ mkdir -p "$subpkgdir"/usr/bin
+ cd "$pkgdir"
+ mv usr/bin/fetchmailconf "$subpkgdir"/usr/bin/
+ mv usr/lib "$subpkgdir"/usr/
+}
+
+md5sums="9176a9005a816946f766774bc4cbc642 fetchmail-6.3.20.tar.bz2
+b27fe01a7c25534d62d175c8ba22fc48 fetchmail.initd"
diff --git a/main/fetchmail/fetchmail.initd b/main/fetchmail/fetchmail.initd
new file mode 100755
index 0000000000..73286c4e70
--- /dev/null
+++ b/main/fetchmail/fetchmail.initd
@@ -0,0 +1,34 @@
+#!/sbin/runscript
+
+pidfile=/var/run/fetchmail/fetchmail.pid
+
+depend() {
+ need net
+ after firewall
+ use mta
+}
+
+checkconfig() {
+ if [ ! -f /etc/fetchmailrc ]; then
+ eerror "Configuration file /etc/fetchmailrc not found"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting fetchmail"
+ start-stop-daemon --start --quiet \
+ --chuid fetchmail --exec /usr/bin/fetchmail \
+ -- -d ${polling_period:-300} -f /etc/fetchmailrc \
+ --pidfile ${pidfile} -i /var/lib/fetchmail/.fetchids
+ eend ${?}
+}
+
+stop() {
+ ebegin "Stopping fetchmail"
+ start-stop-daemon --stop --quiet --pidfile ${pidfile}
+ eend ${?}
+}
+
diff --git a/main/fetchmail/fetchmail.post-install b/main/fetchmail/fetchmail.post-install
new file mode 100644
index 0000000000..b16bfcc3e4
--- /dev/null
+++ b/main/fetchmail/fetchmail.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+chown fetchmail:fetchmail /var/*/fetchmail
diff --git a/main/fetchmail/fetchmail.pre-install b/main/fetchmail/fetchmail.pre-install
new file mode 100644
index 0000000000..4a1b630e00
--- /dev/null
+++ b/main/fetchmail/fetchmail.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -H -h /var/lib/fetchmail -s /bin/false -D fetchmail 2>/dev/null
+exit 0
diff --git a/main/ffmpeg/APKBUILD b/main/ffmpeg/APKBUILD
new file mode 100644
index 0000000000..5e5cb410f6
--- /dev/null
+++ b/main/ffmpeg/APKBUILD
@@ -0,0 +1,63 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ffmpeg
+pkgver=0.8
+pkgrel=0
+pkgdesc="Complete and free Internet live audio and video broadcasting solution for Linux/Unix"
+url="http://ffmpeg.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="lame-dev libvorbis-dev faac-dev xvidcore-dev zlib-dev
+ imlib2-dev x264-dev libtheora-dev coreutils bzip2-dev perl libvpx-dev
+ libvpx-dev sdl-dev"
+depends=
+source="http://ffmpeg.org/releases/ffmpeg-$pkgver.tar.bz2
+ configure-dlvsym.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ local _dbg="--disable-debug"
+ [ -n "$DEBUG" ] && _dbg="--enable-debug"
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --enable-gpl \
+ --enable-libmp3lame \
+ --enable-libvorbis \
+ --enable-libfaac \
+ --enable-libvpx \
+ --enable-libxvid \
+ --enable-libx264 \
+ --enable-libtheora \
+ --enable-nonfree \
+ --enable-postproc \
+ --enable-pic \
+ --enable-pthreads \
+ --enable-shared \
+ --enable-x11grab \
+ --disable-mmx \
+ --disable-mmx2 \
+ --disable-stripping \
+ $_dbg \
+ || return 1
+ make || return 1
+ ${CC:-gcc} -o tools/qt-faststart $CFLAGS tools/qt-faststart.c || return 1
+ make doc/ffmpeg.1 doc/ffplay.1 doc/ffserver.1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install install-man || return 1
+ install -D -m755 tools/qt-faststart "$pkgdir/usr/bin/qt-faststart" || return 1
+# strip --strip-debug "$pkgdir"/usr/lib/*.a || return 1
+}
+md5sums="7e9b8c8a6952de0c477027e48249f3ed ffmpeg-0.8.tar.bz2
+2cdc11a99bf97c63c7cca27b073cb47c configure-dlvsym.patch"
diff --git a/main/ffmpeg/configure-dlvsym.patch b/main/ffmpeg/configure-dlvsym.patch
new file mode 100644
index 0000000000..b48a8e7883
--- /dev/null
+++ b/main/ffmpeg/configure-dlvsym.patch
@@ -0,0 +1,30 @@
+diff --git a/configure b/configure
+index c54706a..b5b3225 100755
+--- a/configure
++++ b/configure
+@@ -1053,6 +1053,7 @@ HAVE_LIST="
+ dev_video_bktr_ioctl_bt848_h
+ dlfcn_h
+ dlopen
++ dlvsym
+ dos_paths
+ ebp_available
+ ebx_available
+@@ -3053,14 +3054,15 @@ check_ldflags -Wl,--warn-common
+ check_ldflags '-Wl,-rpath-link,\$(BUILD_ROOT)/libpostproc -Wl,-rpath-link,\$(BUILD_ROOT)/libswscale -Wl,-rpath-link,\$(BUILD_ROOT)/libavfilter -Wl,-rpath-link,\$(BUILD_ROOT)/libavdevice -Wl,-rpath-link,\$(BUILD_ROOT)/libavformat -Wl,-rpath-link,\$(BUILD_ROOT)/libavcodec -Wl,-rpath-link,\$(BUILD_ROOT)/libavutil'
+ test_ldflags -Wl,-Bsymbolic && append SHFLAGS -Wl,-Bsymbolic
+
++check_func dlvsym -lld
+ echo "X{};" > $TMPV
+ if test_ldflags -Wl,--version-script,$TMPV; then
+ append SHFLAGS '-Wl,--version-script,\$(SUBDIR)lib\$(NAME).ver'
+- check_cc <<EOF && enable symver_asm_label
++ enabled dlvsym && check_cc <<EOF && enable symver_asm_label
+ void ff_foo(void) __asm__ ("av_foo@VERSION");
+ void ff_foo(void) { ${inline_asm+__asm__($quotes);} }
+ EOF
+- check_cc <<EOF && enable symver_gnu_asm
++ enabled dlvsym && check_cc <<EOF && enable symver_gnu_asm
+ __asm__(".symver ff_foo,av_foo@VERSION");
+ void ff_foo(void) {}
+ EOF
diff --git a/main/ffmpeg/pic.patch b/main/ffmpeg/pic.patch
new file mode 100644
index 0000000000..737e30ddeb
--- /dev/null
+++ b/main/ffmpeg/pic.patch
@@ -0,0 +1,11 @@
+--- ./libswscale/rgb2rgb.c.orig
++++ ./libswscale/rgb2rgb.c
+@@ -159,7 +159,7 @@
+ #define RENAME(a) a ## _C
+ #include "rgb2rgb_template.c"
+
+-#if ARCH_X86
++#if ARCH_X86 && !defined(PIC)
+
+ //MMX versions
+ #undef RENAME
diff --git a/main/fftw/APKBUILD b/main/fftw/APKBUILD
new file mode 100644
index 0000000000..955a390994
--- /dev/null
+++ b/main/fftw/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=fftw
+pkgver=3.2.2
+pkgrel=1
+pkgdesc="fastest fourier transform in the west"
+url="http://www.fftw.org/"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.fftw.org/$pkgname-$pkgver.tar.gz"
+arch="all"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-single
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="b616e5c91218cc778b5aa735fefb61ae fftw-3.2.2.tar.gz"
diff --git a/main/file/APKBUILD b/main/file/APKBUILD
new file mode 100644
index 0000000000..20f55d14ae
--- /dev/null
+++ b/main/file/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=file
+pkgver=5.07
+pkgrel=1
+pkgdesc="File type identification utility"
+url="http://www.darwinsys.com/file/"
+arch="all"
+license="custom"
+depends=
+source="ftp://ftp.astron.com/pub/file/file-$pkgver.tar.gz"
+subpackages="$pkgname-dev $pkgname-doc"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --datadir=/usr/share/misc
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="b8d1f9a8a644067bd0a703cebf3f4858 file-5.07.tar.gz"
diff --git a/main/findutils/APKBUILD b/main/findutils/APKBUILD
new file mode 100644
index 0000000000..90a6c25d00
--- /dev/null
+++ b/main/findutils/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=findutils
+pkgver=4.4.2
+pkgrel=2
+pkgdesc="GNU utilities for finding files"
+url="http://www.gnu.org/software/findutils/"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/pub/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="351cc4adb07d54877fa15f75fb77d39f findutils-4.4.2.tar.gz"
diff --git a/main/firefox/APKBUILD b/main/firefox/APKBUILD
new file mode 100644
index 0000000000..8b77f07412
--- /dev/null
+++ b/main/firefox/APKBUILD
@@ -0,0 +1,97 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=firefox
+pkgver=4.0.1
+_pkgver=4.0.1
+_xulver=2.0.1
+pkgrel=2
+pkgdesc="firefox web browser"
+url="http://www.firefox.com"
+arch="all"
+license="GPL LGPL MPL"
+depends="xulrunner"
+makedepends="xulrunner-dev>=${_xulver}
+
+ nspr-dev
+ nss-dev
+ gtk+-dev
+ dbus-glib-dev
+ alsa-lib-dev
+ libvorbis-dev
+ libogg-dev
+ libtheora-dev
+ wireless-tools-dev
+ libnotify-dev
+ libevent-dev
+ libxt-dev
+ jpeg-dev
+ bzip2-dev
+ hunspell-dev
+ startup-notification-dev
+ sqlite-dev
+ libidl-dev
+
+ autoconf2.13
+
+ python
+ zip
+ yasm
+
+ autoconf
+ automake
+ libtool
+
+ paxctl"
+install=""
+subpackages=""
+source="http://releases.mozilla.org/pub/mozilla.org/${pkgname}/releases/${pkgver}/source/${pkgname}-${_pkgver}.source.tar.bz2
+ mozconfig
+
+ firefox.desktop
+ firefox-safe.desktop"
+
+_xulrunner_version="2.0"
+_builddir="${srcdir}/mozilla-${_xulrunner_version}"
+prepare() {
+ local i
+
+ cd "$_builddir"
+
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ cp "${srcdir}/mozconfig" .mozconfig
+}
+
+build() {
+ cd "$_builddir"
+
+ # mozilla's buildsystem is on drugs, so we just kill our CFLAGS and hope
+ # for the best. --nenolod
+ unset CFLAGS
+ unset CXXFLAGS
+
+ make -j1 -f client.mk build MOZ_MAKE_FLAGS="$MAKEFLAGS" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" -f client.mk install || return 1
+
+ install -m755 -d ${pkgdir}/usr/share/applications
+ install -m755 -d ${pkgdir}/usr/share/pixmaps
+ install -m644 ${srcdir}/mozilla-2.0/other-licenses/branding/firefox/default48.png ${pkgdir}/usr/share/pixmaps/firefox.png
+ install -m644 ${srcdir}/firefox.desktop ${pkgdir}/usr/share/applications/firefox.desktop
+ install -m644 ${srcdir}/firefox-safe.desktop ${pkgdir}/usr/share/applications/firefox-safe.desktop
+
+ # firefox currently does not work with mprotect. disable it for now
+ paxctl -c -m "$pkgdir"/usr/lib/firefox-$pkgver/firefox
+}
+
+md5sums="9abda7d23151e97913c8555a64c13f34 firefox-4.0.1.source.tar.bz2
+0b341845d311fe6b49f74751e4841ee6 mozconfig
+ba96924ece1d77453e462429037a2ce5 firefox.desktop
+6f38a5899034b7786cb1f75ad42032b8 firefox-safe.desktop"
diff --git a/main/firefox/firefox-safe.desktop b/main/firefox/firefox-safe.desktop
new file mode 100644
index 0000000000..1538fc6748
--- /dev/null
+++ b/main/firefox/firefox-safe.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+Exec=firefox -safe-mode %u
+Icon=firefox
+Type=Application
+Terminal=false
+MultipleArgs=false
+Name=Firefox - Safe Mode
+GenericName=Web Browser - Safe Mode
+StartupNotify=false
+Categories=Network;WebBrowser;
diff --git a/main/firefox/firefox.desktop b/main/firefox/firefox.desktop
new file mode 100644
index 0000000000..d048ce46c3
--- /dev/null
+++ b/main/firefox/firefox.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Exec=firefox %u
+Icon=firefox
+Type=Application
+Terminal=false
+Name=Firefox
+Name[bn]=ফায়ারফকà§à¦¸3
+Name[eo]=Fajrovulpo3
+Name[fi]=Firefox3
+Name[pa]=ਫਾਇਰਫੋਕਸ3
+Name[tg]=Рӯбоҳи оташин3
+GenericName=Web Browser
+GenericName[af]=Web Blaaier
+GenericName[ar]=متصÙØ­ ويب
+GenericName[az]=Veb Səyyahı
+GenericName[bg]=Браузър
+GenericName[bn]=ওয়েব বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°
+GenericName[br]=Furcher ar Gwiad
+GenericName[bs]=WWW Preglednik
+GenericName[ca]=Fullejador web
+GenericName[cs]=WWW prohlížeÄ
+GenericName[cy]=Porydd Gwe
+GenericName[da]=Browser
+GenericName[de]=Web-Browser
+GenericName[el]=ΠεÏιηγητής ΙστοÏ
+GenericName[eo]=TTT-legilo
+GenericName[es]=Navegador web
+GenericName[et]=Veebilehitseja
+GenericName[eu]=Web arakatzailea
+GenericName[fa]=مرورگر وب
+GenericName[fi]=WWW-selain
+GenericName[fo]=Alnótsfar
+GenericName[fr]=Navigateur web
+GenericName[gl]=Navegador Web
+GenericName[he]=דפדפן ×ינטרנט
+GenericName[hi]=वेब बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤°
+GenericName[hr]=Web preglednik
+GenericName[hu]=Webböngésző
+GenericName[is]=Vafri
+GenericName[it]=Browser Web
+GenericName[ja]=ウェブブラウザ
+GenericName[ko]=웹 브ë¼ìš°ì €
+GenericName[lo]=ເວັບບຣາວເຊີ
+GenericName[lt]=Žiniatinklio naršyklė
+GenericName[lv]=Web PÄrlÅ«ks
+GenericName[mk]=ПрелиÑтувач на Интернет
+GenericName[mn]=Веб-Хөтөч
+GenericName[nb]=Nettleser
+GenericName[nds]=Nettkieker
+GenericName[nl]=Webbrowser
+GenericName[nn]=Nettlesar
+GenericName[nso]=Seinyakisi sa Web
+GenericName[pa]=ਵੈਬ à¨à¨²à¨•à¨¾à¨°à¨¾
+GenericName[pl]=PrzeglÄ…darka WWW
+GenericName[pt]=Navegador Web
+GenericName[pt_BR]=Navegador Web
+GenericName[ro]=Navigator de web
+GenericName[ru]=Веб-браузер
+GenericName[se]=Fierpmádatlogan
+GenericName[sk]=Webový prehliadaÄ
+GenericName[sl]=Spletni brskalnik
+GenericName[sr]=Веб претраживач
+GenericName[sr@Latn]=Veb pretraživaÄ
+GenericName[ss]=Ibrawuza yeWeb
+GenericName[sv]=Webbläsare
+GenericName[ta]=வலை உலாவி
+GenericName[tg]=ТафÑиргари вÑб
+GenericName[th]=เว็บบราวเซอร์
+GenericName[tr]=Web Tarayıcı
+GenericName[uk]=Ðавігатор Тенет
+GenericName[uz]=Веб-браузер
+GenericName[ven]=Buronza ya Webu
+GenericName[vi]=Trình duyệt Web
+GenericName[wa]=Betchteu waibe
+GenericName[xh]=Umkhangeli zincwadi we Web
+GenericName[zh_CN]=网页æµè§ˆå™¨
+GenericName[zh_TW]=網é ç€è¦½å™¨
+GenericName[zu]=Umcingi we-Web
+MimeType=text/html;
+StartupNotify=true
+Categories=Network;WebBrowser;
diff --git a/main/firefox/mozconfig b/main/firefox/mozconfig
new file mode 100644
index 0000000000..1ec6b90b30
--- /dev/null
+++ b/main/firefox/mozconfig
@@ -0,0 +1,36 @@
+. $topsrcdir/browser/config/mozconfig
+
+ac_add_options --prefix=/usr
+ac_add_options --libdir=/usr/lib
+ac_add_options --with-system-nspr
+ac_add_options --with-system-nss
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-zlib
+ac_add_options --with-pthreads
+ac_add_options --disable-tests
+ac_add_options --disable-debug
+ac_add_options --enable-optimize
+ac_add_options --disable-installer
+ac_add_options --enable-xinerama
+ac_add_options --enable-default-toolkit=cairo-gtk2
+ac_add_options --disable-xprint
+ac_add_options --enable-strip
+ac_add_options --enable-pango
+ac_add_options --enable-svg
+ac_add_options --enable-canvas
+ac_add_options --enable-startup-notification
+ac_add_options --enable-libxul
+ac_add_options --disable-crashreporter
+ac_add_options --disable-updater
+ac_add_options --with-libxul-sdk=/usr/lib/xulrunner-devel-2.0.1
+ac_add_options --enable-safe-browsing
+ac_add_options --with-branding=other-licenses/branding/firefox
+ac_add_options --enable-chrome-format=jar
+
+export BUILD_OFFICIAL=1
+export MOZILLA_OFFICIAL=1
+export USE_SHORT_LIBNAME=1
+
+mk_add_options BUILD_OFFICIAL=1
+mk_add_options MOZILLA_OFFICIAL=1
+mk_add_options USE_SHORT_LIBNAME=1
diff --git a/main/fixesproto/APKBUILD b/main/fixesproto/APKBUILD
new file mode 100644
index 0000000000..2db32801e5
--- /dev/null
+++ b/main/fixesproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fixesproto
+pkgver=5.0
+pkgrel=0
+pkgdesc="X11 Fixes extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="xextproto"
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="e7431ab84d37b2678af71e29355e101d fixesproto-5.0.tar.bz2"
diff --git a/main/flac/APKBUILD b/main/flac/APKBUILD
new file mode 100644
index 0000000000..b846f072fe
--- /dev/null
+++ b/main/flac/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=flac
+pkgver=1.2.1
+pkgrel=6
+pkgdesc="Free Lossless Audio Codec"
+url="http://flac.sourceforge.net/"
+arch="all"
+license="custom:Xiph LGPL GPL FDL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="libogg-dev !libiconv"
+source="http://downloads.sf.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.gz
+ "
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver || return 1
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --enable-shared \
+ --enable-ogg \
+ --disable-sse \
+ --disable-rpath \
+ --disable-cpplibs \
+ --with-pic || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -Dm0644 COPYING.Xiph \
+ "$pkgdir"/usr/share/licenses/$pkgname/COPYING.Xiph
+}
+md5sums="153c8b15a54da428d1f0fadc756c22c7 flac-1.2.1.tar.gz"
diff --git a/main/flashrom/APKBUILD b/main/flashrom/APKBUILD
new file mode 100644
index 0000000000..a295501406
--- /dev/null
+++ b/main/flashrom/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor:
+# Maintainer: Nathan Angelacos <nangel@alpinelinux.org>
+pkgname=flashrom
+pkgver=0.9.3
+pkgrel=0
+pkgdesc="A utility for identifying, reading, writing, verifying and erasing flash chips"
+url="http://www.flashrom.org/Flashrom"
+arch="all"
+license="GPL"
+depends=dmidecode
+makedepends=pciutils-dev
+subpackages="$pkgname-doc"
+install="$pkgname.post-install"
+source="http://qa.coreboot.org/releases/flashrom-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ make PREFIX=/usr/ || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make PREFIX="$pkgdir/usr/" install
+}
+
+md5sums="eccdec2764223f5d2839bf577380eaa9 flashrom-0.9.3.tar.bz2"
diff --git a/main/flashrom/flashrom.post-install b/main/flashrom/flashrom.post-install
new file mode 100755
index 0000000000..b7919f5fd1
--- /dev/null
+++ b/main/flashrom/flashrom.post-install
@@ -0,0 +1,15 @@
+#!/bin/sh
+if [ -e /proc/sys/kernel/grsecurity/ ]; then
+cat - <<EOF
+
+ ************[ flashrom package installation notice ]****************
+
+ You appear to be running a grsec enabled kernel.
+ flashrom needs write access to /dev/mem and will likely not work
+
+ *********************************************************************
+
+EOF
+fi
+exit 0
+
diff --git a/main/flex/APKBUILD b/main/flex/APKBUILD
new file mode 100644
index 0000000000..7bb369ae6e
--- /dev/null
+++ b/main/flex/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncop@alpinelinux.org>
+pkgname=flex
+pkgver=2.5.35
+pkgrel=4
+pkgdesc="A tool for generating text-scanning programs"
+url="http://flex.sourceforge.net"
+arch="all"
+license=custom
+depends='m4'
+makedepends=m4
+source="http://downloads.sourceforge.net/sourceforge/flex/flex-$pkgver.tar.bz2"
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --build=${CBUILD} \
+ --host=${CHOST} \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make install DESTDIR="$pkgdir"
+}
+
+md5sums="10714e50cea54dc7a227e3eddcd44d57 flex-2.5.35.tar.bz2"
diff --git a/main/flite/APKBUILD b/main/flite/APKBUILD
new file mode 100644
index 0000000000..dad4703025
--- /dev/null
+++ b/main/flite/APKBUILD
@@ -0,0 +1,50 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=flite
+pkgver=1.4
+pkgrel=1
+pkgdesc="Small, fast speech synthesis engine (text-to-speech)"
+url="http://www.speech.cs.cmu.edu/flite/"
+arch="all"
+license="MIT"
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev"
+source="http://www.speech.cs.cmu.edu/flite/packed/flite-1.4/flite-$pkgver-release.tar.bz2"
+
+_builddir="$srcdir"/flite-$pkgver-release
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ CFLAGS="$CFLAGS -fPIC" ./configure --prefix=/usr \
+ --enable-shared \
+ --localstatedir=/var \
+ || return 1
+ # work around parallel build issue
+ make -C include
+ make -C src
+ make -C lang
+ make -C tools
+ make -j1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install INSTALLBINDIR="$pkgdir"/usr/bin \
+ INSTALLLIBDIR="$pkgdir"/usr/lib \
+ INSTALLINCDIR="$pkgdir"/usr/include/flite \
+ || return 1
+}
+
+md5sums="b7c3523b3bbc6f29ce61e6650cd9a428 flite-1.4-release.tar.bz2"
diff --git a/main/fluxbox/APKBUILD b/main/fluxbox/APKBUILD
new file mode 100644
index 0000000000..32e3ade7f7
--- /dev/null
+++ b/main/fluxbox/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fluxbox
+pkgver=1.3.1
+pkgrel=0
+pkgdesc="A lightweight and highly-configurable window manager"
+url="http://www.fluxbox.org"
+arch="all"
+license="MIT"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libxinerama-dev libxpm-dev libxrandr imlib2-dev
+ libxrender-dev libxrandr-dev libxinerama-dev freetype-dev libiconv-dev"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-kde \
+ --disable-gnome \
+ --enable-imlib2 \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="0eaa940a69c0a876a520bb85d67b8bec fluxbox-1.3.1.tar.bz2"
diff --git a/main/font-adobe-100dpi/APKBUILD b/main/font-adobe-100dpi/APKBUILD
new file mode 100644
index 0000000000..2057abcff1
--- /dev/null
+++ b/main/font-adobe-100dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-adobe-100dpi
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org adobe 100dpi font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/100dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="443acfe70e26716282f9068730fe92c4 font-adobe-100dpi-1.0.0.tar.bz2"
diff --git a/main/font-adobe-75dpi/APKBUILD b/main/font-adobe-75dpi/APKBUILD
new file mode 100644
index 0000000000..081e5ba5ec
--- /dev/null
+++ b/main/font-adobe-75dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-adobe-75dpi
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org adobe 75dpi font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/75dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="813b5d3723c84388a938ab6732e1329c font-adobe-75dpi-1.0.0.tar.bz2"
diff --git a/main/font-adobe-utopia-100dpi/APKBUILD b/main/font-adobe-utopia-100dpi/APKBUILD
new file mode 100644
index 0000000000..3ca2381ab7
--- /dev/null
+++ b/main/font-adobe-utopia-100dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-adobe-utopia-100dpi
+pkgver=1.0.1
+pkgrel=3
+pkgdesc="X.org adobe 100dpi font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/100dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="5d28a30efef966f8dbbaff9a6619f01a font-adobe-utopia-100dpi-1.0.1.tar.bz2"
diff --git a/main/font-adobe-utopia-75dpi/APKBUILD b/main/font-adobe-utopia-75dpi/APKBUILD
new file mode 100644
index 0000000000..f2429974fe
--- /dev/null
+++ b/main/font-adobe-utopia-75dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-adobe-utopia-75dpi
+pkgver=1.0.1
+pkgrel=3
+pkgdesc="X.org adobe 75dpi font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/75dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="dd912284e4750023f9682812532fa033 font-adobe-utopia-75dpi-1.0.1.tar.bz2"
diff --git a/main/font-adobe-utopia-type1/APKBUILD b/main/font-adobe-utopia-type1/APKBUILD
new file mode 100644
index 0000000000..ed40e552ba
--- /dev/null
+++ b/main/font-adobe-utopia-type1/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-adobe-utopia-type1
+pkgver=1.0.1
+pkgrel=2
+pkgdesc="X.org adobe utopia-type1 fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/utopia-type1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ FCCACHE=: \
+ install || return 1
+}
+
+md5sums="aa7ff4bd20b961afda9c15d103b972a5 font-adobe-utopia-type1-1.0.1.tar.bz2"
diff --git a/main/font-alias/APKBUILD b/main/font-alias/APKBUILD
new file mode 100644
index 0000000000..83fc28f0e9
--- /dev/null
+++ b/main/font-alias/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-alias
+pkgver=1.0.1
+pkgrel=1
+pkgdesc="X.org font alias files"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-top-fontdir=/usr/share/fonts
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="c4776b6f0f2ecdb7670b6fe64b5d2a2d font-alias-1.0.1.tar.bz2"
diff --git a/main/font-arabic-misc/APKBUILD b/main/font-arabic-misc/APKBUILD
new file mode 100644
index 0000000000..a68d08d625
--- /dev/null
+++ b/main/font-arabic-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-arabic-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="81595016e2ff859716fc256ebb136ba6 font-arabic-misc-1.0.0.tar.bz2"
diff --git a/main/font-bh-100dpi/APKBUILD b/main/font-bh-100dpi/APKBUILD
new file mode 100644
index 0000000000..0133f31d25
--- /dev/null
+++ b/main/font-bh-100dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bh-100dpi
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.Org Bigelow & Holmes bitmap fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/100dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="e5592de74a5c04e3a2608800dd079197 font-bh-100dpi-1.0.0.tar.bz2"
diff --git a/main/font-bh-75dpi/APKBUILD b/main/font-bh-75dpi/APKBUILD
new file mode 100644
index 0000000000..62a4f66b3a
--- /dev/null
+++ b/main/font-bh-75dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bh-75dpi
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.Org Bigelow & Holmes bitmap fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/75dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="6e51cd02f4ce32e1393e34ab17a9b211 font-bh-75dpi-1.0.0.tar.bz2"
diff --git a/main/font-bh-lucidatypewriter-100dpi/APKBUILD b/main/font-bh-lucidatypewriter-100dpi/APKBUILD
new file mode 100644
index 0000000000..ddae97e87b
--- /dev/null
+++ b/main/font-bh-lucidatypewriter-100dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bh-lucidatypewriter-100dpi
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.Org Bigelow & Holmes Lucida bitmap fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/100dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="c44d3f730564da465993e9292a33c235 font-bh-lucidatypewriter-100dpi-1.0.0.tar.bz2"
diff --git a/main/font-bh-lucidatypewriter-75dpi/APKBUILD b/main/font-bh-lucidatypewriter-75dpi/APKBUILD
new file mode 100644
index 0000000000..6fde0c80e7
--- /dev/null
+++ b/main/font-bh-lucidatypewriter-75dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bh-lucidatypewriter-75dpi
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.Org Bigelow & Holmes Lucida bitmap fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/75dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="fdd9be5b9db94ef363a33e39b7977e2b font-bh-lucidatypewriter-75dpi-1.0.0.tar.bz2"
diff --git a/main/font-bh-ttf/APKBUILD b/main/font-bh-ttf/APKBUILD
new file mode 100644
index 0000000000..a8f7bf2a77
--- /dev/null
+++ b/main/font-bh-ttf/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bh-ttf
+pkgver=1.0.1
+pkgrel=0
+pkgdesc="X.org bh TTF fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/TTF
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ FCCACHE=: \
+ install || return 1
+}
+
+md5sums="664df71cb510b744b4a10e778445c37b font-bh-ttf-1.0.1.tar.bz2"
diff --git a/main/font-bh-type1/APKBUILD b/main/font-bh-type1/APKBUILD
new file mode 100644
index 0000000000..a5e718744a
--- /dev/null
+++ b/main/font-bh-type1/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bh-type1
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org bh Type1 fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/Type1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ FCCACHE=: \
+ install || return 1
+}
+
+md5sums="46588b22678e440741d6220bc3945cbf font-bh-type1-1.0.0.tar.bz2"
diff --git a/main/font-bitstream-100dpi/APKBUILD b/main/font-bitstream-100dpi/APKBUILD
new file mode 100644
index 0000000000..8adf9ea7e3
--- /dev/null
+++ b/main/font-bitstream-100dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bitstream-100dpi
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.Org Bitstream bitmap fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/100dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="173352ddec3d26e2b91df1edcf1ae85b font-bitstream-100dpi-1.0.0.tar.bz2"
diff --git a/main/font-bitstream-75dpi/APKBUILD b/main/font-bitstream-75dpi/APKBUILD
new file mode 100644
index 0000000000..2182946be0
--- /dev/null
+++ b/main/font-bitstream-75dpi/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bitstream-75dpi
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.Org Bitstream bitmap fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/75dpi
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="beb476657d50d07d17eef7c325a5ed08 font-bitstream-75dpi-1.0.0.tar.bz2"
diff --git a/main/font-bitstream-speedo/APKBUILD b/main/font-bitstream-speedo/APKBUILD
new file mode 100644
index 0000000000..0c0aa99cc6
--- /dev/null
+++ b/main/font-bitstream-speedo/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bitstream-speedo
+pkgver=1.0.1
+pkgrel=0
+pkgdesc="X.org bitstream Speedo fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/Speedo
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="5b1856a24b1b46414950febc63880307 font-bitstream-speedo-1.0.1.tar.bz2"
diff --git a/main/font-bitstream-type1/APKBUILD b/main/font-bitstream-type1/APKBUILD
new file mode 100644
index 0000000000..4f54e8b73a
--- /dev/null
+++ b/main/font-bitstream-type1/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-bitstream-type1
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org bitstream Type1 fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/Type1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ FCCACHE=: \
+ install || return 1
+}
+
+md5sums="6610475e2e231242f8f2122a709c3695 font-bitstream-type1-1.0.0.tar.bz2"
diff --git a/main/font-cronyx-cyrillic/APKBUILD b/main/font-cronyx-cyrillic/APKBUILD
new file mode 100644
index 0000000000..31a610489e
--- /dev/null
+++ b/main/font-cronyx-cyrillic/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-cronyx-cyrillic
+pkgver=1.0.0
+pkgrel=2
+pkgdesc="X.org cronyx cyrillic fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/cyrillic
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="22b451e7230b8c003cfc496ee2d360cc font-cronyx-cyrillic-1.0.0.tar.bz2"
diff --git a/main/font-cursor-misc/APKBUILD b/main/font-cursor-misc/APKBUILD
new file mode 100644
index 0000000000..0a344b2454
--- /dev/null
+++ b/main/font-cursor-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-cursor-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="305fa22cdfefb8f80babd711051a534b font-cursor-misc-1.0.0.tar.bz2"
diff --git a/main/font-daewoo-misc/APKBUILD b/main/font-daewoo-misc/APKBUILD
new file mode 100644
index 0000000000..8d99f6f066
--- /dev/null
+++ b/main/font-daewoo-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-daewoo-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="61f9eab48c619af5494d3e384d8d7d79 font-daewoo-misc-1.0.0.tar.bz2"
diff --git a/main/font-dec-misc/APKBUILD b/main/font-dec-misc/APKBUILD
new file mode 100644
index 0000000000..3d56bfba75
--- /dev/null
+++ b/main/font-dec-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-dec-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="284e554db1c64fb7580a06df01444a2b font-dec-misc-1.0.0.tar.bz2"
diff --git a/main/font-ibm-type1/APKBUILD b/main/font-ibm-type1/APKBUILD
new file mode 100644
index 0000000000..b278e73695
--- /dev/null
+++ b/main/font-ibm-type1/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-ibm-type1
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org ibm Type1 fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/Type1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ FCCACHE=: \
+ install || return 1
+}
+
+md5sums="8e8733051371e2b51123376b49f5d3ea font-ibm-type1-1.0.0.tar.bz2"
diff --git a/main/font-isas-misc/APKBUILD b/main/font-isas-misc/APKBUILD
new file mode 100644
index 0000000000..b6da30844c
--- /dev/null
+++ b/main/font-isas-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-isas-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="ec709a96b64b497a5cb5658c93bd38dc font-isas-misc-1.0.0.tar.bz2"
diff --git a/main/font-jis-misc/APKBUILD b/main/font-jis-misc/APKBUILD
new file mode 100644
index 0000000000..7367ae5dee
--- /dev/null
+++ b/main/font-jis-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-jis-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="61febb49a71065723a1fba17cbf23c67 font-jis-misc-1.0.0.tar.bz2"
diff --git a/main/font-micro-misc/APKBUILD b/main/font-micro-misc/APKBUILD
new file mode 100644
index 0000000000..a2d6a83aec
--- /dev/null
+++ b/main/font-micro-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-micro-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="8c8bffd7540f05caa0dbb4e6e1d6c58e font-micro-misc-1.0.0.tar.bz2"
diff --git a/main/font-misc-cyrillic/APKBUILD b/main/font-misc-cyrillic/APKBUILD
new file mode 100644
index 0000000000..7f69e82d86
--- /dev/null
+++ b/main/font-misc-cyrillic/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-misc-cyrillic
+pkgver=1.0.0
+pkgrel=2
+pkgdesc="X.org misc cyrillic fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/cyrillic
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="3596907d7a2a99c81d8de99bc4552b6a font-misc-cyrillic-1.0.0.tar.bz2"
diff --git a/main/font-misc-ethiopic/APKBUILD b/main/font-misc-ethiopic/APKBUILD
new file mode 100644
index 0000000000..eb3eb11c84
--- /dev/null
+++ b/main/font-misc-ethiopic/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-misc-ethiopic
+pkgver=1.0.1
+pkgrel=0
+pkgdesc="X.org misc ethiopic fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/ethiopic
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" \
+ FCCACHE=: \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ install || return 1
+}
+
+md5sums="4c88c79b8e5d47af90b21e948d42755f font-misc-ethiopic-1.0.1.tar.bz2"
diff --git a/main/font-misc-meltho/APKBUILD b/main/font-misc-meltho/APKBUILD
new file mode 100644
index 0000000000..3d1dc5e81e
--- /dev/null
+++ b/main/font-misc-meltho/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-misc-meltho
+pkgver=1.0.1
+pkgrel=0
+pkgdesc="X.org misc meltho fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/meltho
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" \
+ FCCACHE=: \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ install || return 1
+}
+
+md5sums="345f1a78312e30cd2c41d24ea3f3276f font-misc-meltho-1.0.1.tar.bz2"
diff --git a/main/font-misc-misc/APKBUILD b/main/font-misc-misc/APKBUILD
new file mode 100644
index 0000000000..b4e86369b0
--- /dev/null
+++ b/main/font-misc-misc/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-misc-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 \
+ DESTDIR="$pkgdir" \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ FCCACHE=: \
+ install || return 1
+}
+
+md5sums="2a57f6188c41d4bc1b88ca3d08ad011d font-misc-misc-1.0.0.tar.bz2"
diff --git a/main/font-mutt-misc/APKBUILD b/main/font-mutt-misc/APKBUILD
new file mode 100644
index 0000000000..14f321e4c4
--- /dev/null
+++ b/main/font-mutt-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-mutt-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="648b409b7eb78ad1cd5f6d7fac3eef88 font-mutt-misc-1.0.0.tar.bz2"
diff --git a/main/font-schumacher-misc/APKBUILD b/main/font-schumacher-misc/APKBUILD
new file mode 100644
index 0000000000..67705d3bff
--- /dev/null
+++ b/main/font-schumacher-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-schumacher-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="f1c6063d2fadc57e696a0aab69afd6e0 font-schumacher-misc-1.0.0.tar.bz2"
diff --git a/main/font-screen-cyrillic/APKBUILD b/main/font-screen-cyrillic/APKBUILD
new file mode 100644
index 0000000000..9f5c643cb0
--- /dev/null
+++ b/main/font-screen-cyrillic/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-screen-cyrillic
+pkgver=1.0.1
+pkgrel=2
+pkgdesc="X.org screen cyrillic fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/cyrillic
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="c8d5aef01c906c7aaea329702a8b1b63 font-screen-cyrillic-1.0.1.tar.bz2"
diff --git a/main/font-sony-misc/APKBUILD b/main/font-sony-misc/APKBUILD
new file mode 100644
index 0000000000..708ecbad7f
--- /dev/null
+++ b/main/font-sony-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-sony-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="0dfddd1a946e4497f009094c0ae1bdd5 font-sony-misc-1.0.0.tar.bz2"
diff --git a/main/font-sun-misc/APKBUILD b/main/font-sun-misc/APKBUILD
new file mode 100644
index 0000000000..dc13429422
--- /dev/null
+++ b/main/font-sun-misc/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-sun-misc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="X.org misc font"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/misc
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="e17d43a7c6c0d862cfba0908ff132ffa font-sun-misc-1.0.0.tar.bz2"
diff --git a/main/font-util/APKBUILD b/main/font-util/APKBUILD
new file mode 100644
index 0000000000..16d914132d
--- /dev/null
+++ b/main/font-util/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-util
+pkgver=1.1.1
+pkgrel=2
+pkgdesc="X.org font utilities"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="perl"
+makedepends="pkgconfig"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+}
+md5sums="5c735ae6916b65186f3c876d76c27ce3 font-util-1.1.1.tar.bz2"
diff --git a/main/font-winitzki-cyrillic/APKBUILD b/main/font-winitzki-cyrillic/APKBUILD
new file mode 100644
index 0000000000..4fe93fadbe
--- /dev/null
+++ b/main/font-winitzki-cyrillic/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-winitzki-cyrillic
+pkgver=1.0.0
+pkgrel=2
+pkgdesc="X.org winitzki cyrillic fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/cyrillic
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" MKFONTDIR=: MKFONTSCALE=: install || return 1
+}
+
+md5sums="b99b02aff36a88ca3379715423c60303 font-winitzki-cyrillic-1.0.0.tar.bz2"
diff --git a/main/font-xfree86-type1/APKBUILD b/main/font-xfree86-type1/APKBUILD
new file mode 100644
index 0000000000..b1e0897399
--- /dev/null
+++ b/main/font-xfree86-type1/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=font-xfree86-type1
+pkgver=1.0.1
+pkgrel=4
+pkgdesc="X.org xfree86 Type1 fonts"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends="encodings font-alias mkfontscale mkfontdir fontconfig"
+makedepends="pkgconfig font-util-dev bdftopcf"
+install=
+source="http://xorg.freedesktop.org/releases/individual/font/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-mapfiles=/usr/share/fonts/util \
+ --with-fontdir=/usr/share/fonts/Type1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" \
+ MKFONTDIR=: \
+ MKFONTSCALE=: \
+ FCCACHE=: \
+ install || return 1
+}
+
+md5sums="d7e965776c7f0c30b0f09742176fb77a font-xfree86-type1-1.0.1.tar.bz2"
diff --git a/main/fontconfig/APKBUILD b/main/fontconfig/APKBUILD
new file mode 100644
index 0000000000..84d6765d85
--- /dev/null
+++ b/main/fontconfig/APKBUILD
@@ -0,0 +1,35 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fontconfig
+pkgver=2.8.0
+pkgrel=5
+pkgdesc="The Fontconfig package is a library for configuring and customizing font access."
+url="http://fontconfig.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="pkgconfig freetype-dev expat-dev zlib-dev"
+install=
+triggers="$pkgname.trigger:/usr/share/fonts/*"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://fontconfig.org/release/${pkgname}-${pkgver}.tar.gz"
+depends_dev="freetype-dev expat-dev"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-docs
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -m644 -D COPYING "$pkgdir"/usr/share/licenses/"${pkgname}"/COPYING
+}
+
+md5sums="77e15a92006ddc2adbb06f840d591c0e fontconfig-2.8.0.tar.gz"
diff --git a/main/fontconfig/fontconfig.trigger b/main/fontconfig/fontconfig.trigger
new file mode 100644
index 0000000000..35f3d37ebf
--- /dev/null
+++ b/main/fontconfig/fontconfig.trigger
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+fc-cache -f > /dev/null
+
diff --git a/main/fontsproto/APKBUILD b/main/fontsproto/APKBUILD
new file mode 100644
index 0000000000..7c4d1cea83
--- /dev/null
+++ b/main/fontsproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fontsproto
+pkgver=2.1.1
+pkgrel=0
+pkgdesc="X11 font extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="37102ffcaa73f77d700acd6f7a25d8f0 fontsproto-2.1.1.tar.bz2"
diff --git a/main/fping/APKBUILD b/main/fping/APKBUILD
new file mode 100644
index 0000000000..dbb311294f
--- /dev/null
+++ b/main/fping/APKBUILD
@@ -0,0 +1,24 @@
+pkgname=fping
+pkgver=2.4_beta2
+_myver=2.4b2_to
+pkgrel=3
+pkgdesc="A utility to ping multiple hosts at once"
+url="http://www.fping.com/"
+arch="all"
+license="fping"
+depends=""
+subpackages="$pkgname-doc"
+
+# what happened to upstream download? use gentoo distfiles meanwhile
+#source="http://www.$pkgname.com/download/$pkgname-${myver}.tar.gz"
+source=http://distfiles.gentoo.org/distfiles/fping-${_myver}.tar.gz
+
+
+build () {
+ cd $startdir/src/$pkgname-${_myver}
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+ make install DESTDIR="$pkgdir"
+}
+md5sums="d5e8be59e307cef76bc479e1684df705 fping-2.4b2_to.tar.gz"
diff --git a/main/fprobe/APKBUILD b/main/fprobe/APKBUILD
new file mode 100644
index 0000000000..a3cb020877
--- /dev/null
+++ b/main/fprobe/APKBUILD
@@ -0,0 +1,52 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=fprobe
+pkgver=1.1
+pkgrel=5
+pkgdesc="libpcap-based tool that collect network traffic"
+url="http://fprobe.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends="libpcap-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2
+ fprobe-1.1-pidfile-sanity.patch
+ fprobe-1.1-setgroups.patch
+ $pkgname.initd
+ $pkgname.confd"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd $_builddir
+ for i in ../*.patch
+ do
+ msg "Applying $i"
+ patch -p1 < ../$i || exit 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="65850d0470078269b33eee58cba77ac2 fprobe-1.1.tar.bz2
+265c9d9c434df46fc224a1ce7051e27a fprobe-1.1-pidfile-sanity.patch
+ba8632d883fb49e83ea16db67c50a69b fprobe-1.1-setgroups.patch
+41810a73503624de2c27809e34ed80b4 fprobe.initd
+ba9c9327456e4db897b60481705df282 fprobe.confd"
diff --git a/main/fprobe/fprobe-1.1-pidfile-sanity.patch b/main/fprobe/fprobe-1.1-pidfile-sanity.patch
new file mode 100644
index 0000000000..e7c10bd98d
--- /dev/null
+++ b/main/fprobe/fprobe-1.1-pidfile-sanity.patch
@@ -0,0 +1,48 @@
+If we are using the chroot() option or the setuid options, we must create the
+pidfile before doing the chroot OR the setreuid. It's actually best for
+start-stop-daemon if we create the pidfile from the master side of the fork()
+before it exits, since most of the startup checks happen after the chroot()
+unfortunetly.
+
+Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
+
+diff -Nuar fprobe-1.1.orig/src/fprobe.c fprobe-1.1/src/fprobe.c
+--- fprobe-1.1.orig/src/fprobe.c 2005-01-30 08:43:35.000000000 +0000
++++ fprobe-1.1/src/fprobe.c 2008-03-16 20:51:24.000000000 +0000
+@@ -1379,7 +1379,8 @@
+
+ my_log_open(ident, verbosity, log_dest);
+ if (!(log_dest & 2)) {
+- switch (fork()) {
++ pid_t childpid = fork();
++ switch (childpid) {
+ case -1:
+ fprintf(stderr, "fork(): %s", strerror(errno));
+ exit(1);
+@@ -1392,6 +1393,12 @@
+ break;
+
+ default:
++ if (!(pidfile = fopen(pidfilepath, "w")))
++ my_log(LOG_ERR, "Can't create pid file. fopen(): %s", strerror(errno));
++ else {
++ fprintf(pidfile, "%ld\n", (long) childpid);
++ fclose(pidfile);
++ }
+ exit(0);
+ }
+ } else {
+@@ -1548,13 +1555,6 @@
+ }
+ }
+
+- if (!(pidfile = fopen(pidfilepath, "w")))
+- my_log(LOG_ERR, "Can't create pid file. fopen(): %s", strerror(errno));
+- else {
+- fprintf(pidfile, "%ld\n", (long) pid);
+- fclose(pidfile);
+- }
+-
+ my_log(LOG_INFO, "pid: %d", pid);
+ my_log(LOG_INFO, "interface: %s, datalink: %s (%d)",
+ dev, dlt[link_type_idx].descr, link_type);
diff --git a/main/fprobe/fprobe-1.1-setgroups.patch b/main/fprobe/fprobe-1.1-setgroups.patch
new file mode 100644
index 0000000000..9696812437
--- /dev/null
+++ b/main/fprobe/fprobe-1.1-setgroups.patch
@@ -0,0 +1,19 @@
+This seems to fail after the chroot(), so just squelch the exit for now.
+
+Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
+
+diff -Nuar fprobe-1.1/src/fprobe.c fprobe-1.1.new/src/fprobe.c
+--- fprobe-1.1/src/fprobe.c 2008-03-17 00:06:43.000000000 +0000
++++ fprobe-1.1.new/src/fprobe.c 2008-03-17 00:07:30.000000000 +0000
+@@ -1541,10 +1541,10 @@
+ }
+
+ if (pw) {
+ if (setgroups(0, NULL) < 0) {
+ my_log(LOG_CRIT, "setgroups: %s", strerror(errno));
+- exit(1);
++ //exit(1);
+ }
+ if (setregid(pw->pw_gid, pw->pw_gid)) {
+ my_log(LOG_CRIT, "setregid(%u): %s", pw->pw_gid, strerror(errno));
+ exit(1);
diff --git a/main/fprobe/fprobe.confd b/main/fprobe/fprobe.confd
new file mode 100644
index 0000000000..1c444f554e
--- /dev/null
+++ b/main/fprobe/fprobe.confd
@@ -0,0 +1,70 @@
+# Config file for /etc/init.d/fprobe
+
+# Do we want the interface in promiscous mode [yes/no]
+#PROMISC=no
+
+# Interface
+IFACE=eth0
+
+# If configured, only capture packets matching this tcpdump expression
+#FILTER=""
+
+# Flow state timers
+#TIMER_EXPIRED=5
+#TIMER_FRAGMENTED=30
+#TIMER_IDLE=60
+#TIMER_ACTIVE=300
+
+# This is the default and should be left unless you know what you are doing
+#FLOW_VER=5
+
+# local ip. if configured fprobe will use this as the source IP for sending ALL flow data
+# If you want to specify a specific source address per collecter, customize it below
+#LOCALIP=
+
+# SNMP iface id
+SNMP_IFACE="${IFACE//eth}"
+
+# Maximum number of concurrent flows to track
+# using a specified amount of memory
+#MEMBULK=10000
+#MEMLIMIT=
+
+# Pending queue
+#PENDING=100
+
+# Kernel capture buffer size (kB)
+#KERNBUF=1024
+
+# Realtime priority [0=disabled, 1..99]
+#RTPRIO=0
+
+# Delay N nanoseconds after each B bytes
+#DELAY="0:0"
+
+# How much of the start of each packet to grab
+#SNAPLEN=256
+
+# chroot() to this location after startup
+CHROOT="/var/empty"
+
+# User to run as. must have perms to the pidfile directory /var/run/fprobe/
+USER=nobody
+
+# logging level for syslog (0=EMERG, ..., 6=INFO, 7=DEBUG)
+#LOGLEVEL=6
+
+# If you want to run multiple instances of fprobe,
+# You MUST set this variable to a unique INTEGER for each one!
+PIDFILE_ID=''
+
+# remote ip. this is where we send flows
+REMOTEIP=127.0.0.1
+# port to listen on
+PORT=2055
+# Collector type, see the manpage for valid types
+TYPE=''
+
+# If you want multiple collectors, just specify each one here
+COLLECTORS="${REMOTEIP}:${PORT}/${LOCALIP}/${TYPE}"
+
diff --git a/main/fprobe/fprobe.initd b/main/fprobe/fprobe.initd
new file mode 100644
index 0000000000..a14f1e6bcc
--- /dev/null
+++ b/main/fprobe/fprobe.initd
@@ -0,0 +1,40 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+depend() {
+ need net
+ after firewall
+}
+
+BIN=/usr/sbin/fprobe
+PIDFILE_EXTRA=""
+[ -n "$PIDFILE_ID" ] && PIDFILE_EXTRA="[$PIDFILE_ID]"
+PIDFILE="/var/run/fprobe$PIDFILE_EXTRA.pid"
+
+start() {
+ ebegin "Starting fprobe"
+ local OPTS=""
+ [ "${PROMISC}" == "yes" ] || OPTS="${OPTS} -p"
+ [ -n "${FILTER}" ] && OPTS="${OPTS} -f '${FILTER}'"
+ for optname in i:IFACE s:TIMER_EXPIRED g:TIME_FRAGMENTED d:TIMER_IDLE \
+ e:TIMER_ACTIVE n:FLOW_VER a:LOCALIP x:SNMP_IFACE b:MEMBULK \
+ m:MEMLIMIT q:PENDING B:KERNBUF r:RTPRIO t:DELAY S:SNAPLEN \
+ c:CHROOT u:USER v:LOGLEVEL ; do
+ opt="${optname/:*}" optvar="${optname/*:}"
+ eval optvalue="\$$optvar"
+ [ -n "$optvalue" ] && OPTS="${OPTS} -${opt} ${optvalue}"
+ done
+ OPTS="${OPTS} -l 1:${PIDFILE_ID} ${COLLECTORS}"
+ start-stop-daemon --start --exec $BIN \
+ --pidfile ${PIDFILE} \
+ -- ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping fprobe"
+ start-stop-daemon --stop --quiet --exec $BIN \
+ --pidfile ${PIDFILE}
+ eend $?
+}
diff --git a/main/freeglut/APKBUILD b/main/freeglut/APKBUILD
new file mode 100644
index 0000000000..45e109fc97
--- /dev/null
+++ b/main/freeglut/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=freeglut
+pkgver=2.6.0
+pkgrel=1
+pkgdesc="free reimplementation of OpenGL Utility Toolkit (GLUT) library"
+url="http://freeglut.sourceforge.net/"
+arch="all"
+license="Custom"
+depends=
+depends_dev="mesa-dev libx11-dev libice-dev libxxf86vm-dev libxi-dev"
+makedepends="$depends_dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ install -m644 -D COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+md5sums="39f0f2de89f399529d2b981188082218 freeglut-2.6.0.tar.gz"
diff --git a/main/freeradius/0001-Fix-detection-of-TLS-for-uClibc.patch b/main/freeradius/0001-Fix-detection-of-TLS-for-uClibc.patch
new file mode 100644
index 0000000000..e76571a21c
--- /dev/null
+++ b/main/freeradius/0001-Fix-detection-of-TLS-for-uClibc.patch
@@ -0,0 +1,33 @@
+From 51cb058c6a9472585622582d16e01c5540627c25 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue, 13 Oct 2009 12:53:38 +0000
+Subject: [PATCH] Fix detection of TLS for uClibc
+
+On uClibc the configure script will wrongly detect that TLS is
+available. This happends becuase the variable val in the test program
+is optimized away and missing during link time.
+
+This patch make sure that the variable val is not optimized away so
+configure correctly will detect that TLS is missing on uClibc.
+
+Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
+---
+ acinclude.m4 | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/acinclude.m4 b/acinclude.m4
+index 6025474..100e5b0 100644
+--- a/acinclude.m4
++++ b/acinclude.m4
+@@ -382,7 +382,7 @@ m4_pushdef([AC_OUTPUT],
+ AC_DEFUN([FR_TLS],
+ [
+ AC_MSG_CHECKING(for TLS)
+- AC_RUN_IFELSE([AC_LANG_SOURCE([[ static __thread int val; int main() { return 0; } ]])],[have_tls=yes],[have_tls=no],[have_tls=no ])
++ AC_RUN_IFELSE([AC_LANG_SOURCE([[ static __thread int val; int main(int argc, char *argv[]) { return val = argc; } ]])],[have_tls=yes],[have_tls=no],[have_tls=no ])
+ AC_MSG_RESULT($have_tls)
+ if test "$have_tls" = "yes"; then
+ AC_DEFINE([HAVE_THREAD_TLS],[1],[Define if the compiler supports __thread])
+--
+1.6.4.4
+
diff --git a/main/freeradius/APKBUILD b/main/freeradius/APKBUILD
new file mode 100644
index 0000000000..b2c33908bf
--- /dev/null
+++ b/main/freeradius/APKBUILD
@@ -0,0 +1,154 @@
+# Contributor:
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=freeradius
+pkgver=2.1.10
+pkgrel=20
+pkgdesc="RADIUS (Remote Authentication Dial-In User Service) server"
+url="http://freeradius.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev pth-dev mysql-dev postgresql-dev gdbm-dev readline-dev
+ bash libtool autoconf automake perl-dev python-dev openldap-dev unixodbc-dev"
+pkggroups="radiusd"
+pkgusers="radiusd"
+install="freeradius.pre-install"
+subpackages="$pkgname-doc $pkgname-dev $pkgname-ldap $pkgname-mssql \
+ $pkgname-mysql $pkgname-oracle $pkgname-perl $pkgname-postgresql \
+ $pkgname-python $pkgname-unixodbc"
+source="ftp://ftp.freeradius.org/pub/freeradius/$pkgname-server-$pkgver.tar.gz
+ freeradius.confd
+ freeradius.initd
+ "
+
+_builddir="$srcdir"/$pkgname-server-$pkgver
+
+prepare() {
+ cd "$_builddir"
+# for i in ../*.patch; do
+# msg "Applying $i"
+# patch -p1 -i $i || return 1
+# done
+
+ # we dont have libnsl
+ sed -i 's/-lnsl //g' configure || return 1
+ sed -i 's/nsl, //g' configure.in || return 1
+
+ # Fix compilation with heimdal >= 1.3.1
+ sed -i 's/ -DKRB5_DEPRECATED//' src/modules/rlm_krb5/Makefile.in || return 1
+
+ # Fix default config
+ sed -i 's%run_dir = .*%run_dir = \$\{localstatedir\}/run/radius%' \
+ raddb/radiusd.conf.in || return 1
+
+ rm -f libtool.m4
+ libtoolize --force -c || return 1
+ aclocal && ./autogen.sh || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ --libdir=/usr/lib/freeradius \
+ --disable-static \
+ --enable-shared \
+ --disable-ltdl-install \
+ --with-system-libtool \
+ --with-system-libltdl \
+ --with-udpfromto \
+ || return 1
+
+ # * workaround parallel build issue
+ # * add -lssl to fix:
+ # radiusd: symbol 'SSL_set_ex_data': can't resolve symbol in lib
+ # '/usr/lib/freeradius/libfreeradius-eap-2.1.10.so'.
+ make LDFLAGS="$LDFLAGS -lssl" -j1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -d -m0750 -o root -g radiusd "$pkgdir"/etc/raddb
+ install -d -m0770 -o root -g radiusd "$pkgdir"/var/run/radius
+ install -d -m0750 -o root -g radiusd "$pkgdir"/var/log/radius
+ install -d -m0750 -o root -g radiusd "$pkgdir"/var/log/radius/radacct
+
+ make -j1 R="$pkgdir" install
+ sed -i -e 's:^#user *= *nobody:user = radiusd:;s:^#group *= *nobody:group = radiusd:' \
+ "$pkgdir"/etc/raddb/radiusd.conf
+ chown -R root:radiusd "$pkgdir"/etc/raddb/*
+ rm -f "$pkgdir/usr/sbin/rc.radiusd"
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/radiusd
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/radiusd
+ install -m644 -D scripts/logrotate.freeradius "$pkgdir"/etc/lorotate.d/$pkgname
+}
+
+ldap() {
+ depends="freeradius"
+ mkdir -p $subpkgdir/etc/raddb
+ mv $pkgdir/etc/raddb/ldap.attrmap $subpkgdir/etc/raddb
+ mkdir -p $subpkgdir/etc/raddb/modules
+ mv $pkgdir/etc/raddb/modules/ldap $subpkgdir/etc/raddb/modules
+ mkdir -p $subpkgdir/usr/lib/freeradius
+ mv $pkgdir/usr/lib/freeradius/rlm_ldap* $subpkgdir/usr/lib/freeradius
+}
+
+mysql() {
+ depends="freeradius"
+ mkdir -p $subpkgdir/etc/raddb/sql
+ mv $pkgdir/etc/raddb/sql/mysql $subpkgdir/etc/raddb/sql
+ mv $pkgdir/etc/raddb/sql/ndb $subpkgdir/etc/raddb/sql
+ mkdir -p $subpkgdir/usr/lib/freeradius
+ mv $pkgdir/usr/lib/freeradius/rlm_sql_mysql* $subpkgdir/usr/lib/freeradius
+}
+
+mssql() {
+ depends="freeradius"
+ arch="noarch"
+ mkdir -p $subpkgdir/etc/raddb/sql
+ mv $pkgdir/etc/raddb/sql/mssql $subpkgdir/etc/raddb/sql
+}
+
+oracle() {
+ depends="freeradius"
+ arch="noarch"
+ mkdir -p $subpkgdir/etc/raddb/sql
+ mv $pkgdir/etc/raddb/sql/oracle $subpkgdir/etc/raddb/sql
+}
+
+perl() {
+ depends="freeradius perl"
+ mkdir -p $subpkgdir/usr/lib/freeradius
+ mv $pkgdir/usr/lib/freeradius/rlm_perl* $subpkgdir/usr/lib/freeradius
+ mkdir -p $subpkgdir/usr/bin
+ mv $pkgdir/usr/sbin/checkrad $subpkgdir/usr/bin/checkrad
+ mkdir -p $subpkgdir/etc/raddb/modules
+ mv $pkgdir/etc/raddb/modules/perl $subpkgdir/etc/raddb/modules/perl
+}
+
+postgresql() {
+ depends="freeradius"
+ mkdir -p $subpkgdir/etc/raddb/sql
+ mv $pkgdir/etc/raddb/sql/postgresql $subpkgdir/etc/raddb/sql
+ mkdir -p $subpkgdir/usr/lib/freeradius
+ mv $pkgdir/usr/lib/freeradius/rlm_sql_postgresql* $subpkgdir/usr/lib/freeradius
+}
+
+python() {
+ depends="freeradius python"
+ mkdir -p $subpkgdir/usr/lib/freeradius
+ mv $pkgdir/usr/lib/freeradius/rlm_python* $subpkgdir/usr/lib/freeradius
+}
+
+unixodbc() {
+ depends="freeradius"
+ mkdir -p $subpkgdir/usr/lib/freeradius
+ mv $pkgdir/usr/lib/freeradius/rlm_sql_unixodbc* $subpkgdir/usr/lib/freeradius
+}
+
+md5sums="e552704fc1b46d51176e575afa96dcc6 freeradius-server-2.1.10.tar.gz
+fc6693f3df5a0694610110287a28568a freeradius.confd
+7c14a0bc0ada858a08235d7a1d1f2d4c freeradius.initd"
diff --git a/main/freeradius/freeradius-2.1.6-nothreads.patch b/main/freeradius/freeradius-2.1.6-nothreads.patch
new file mode 100644
index 0000000000..41a41c8d6e
--- /dev/null
+++ b/main/freeradius/freeradius-2.1.6-nothreads.patch
@@ -0,0 +1,13 @@
+diff -Nru freeradius-server-2.1.6.orig/src/main/event.c freeradius-server-2.1.6/src/main/event.c
+--- freeradius-server-2.1.6.orig/src/main/event.c 2009-05-18 13:13:55.000000000 +0200
++++ freeradius-server-2.1.6/src/main/event.c 2009-09-05 07:52:42.000000000 +0200
+@@ -1667,7 +1667,9 @@
+ */
+ request->num_proxied_requests = 1;
+ request->num_proxied_responses = 0;
++#ifdef HAVE_PTHREAD_H
+ request->child_pid = NO_SUCH_CHILD_PID;
++#endif
+
+ update_event_timestamp(request->proxy, request->proxy_when.tv_sec);
+
diff --git a/main/freeradius/freeradius-2.1.7-pkglibdir.patch b/main/freeradius/freeradius-2.1.7-pkglibdir.patch
new file mode 100644
index 0000000000..d5767fbd02
--- /dev/null
+++ b/main/freeradius/freeradius-2.1.7-pkglibdir.patch
@@ -0,0 +1,63 @@
+diff -ru freeradius-server-2.1.7.orig/Make.inc.in freeradius-server-2.1.7/Make.inc.in
+--- freeradius-server-2.1.7.orig/Make.inc.in 2009-10-09 08:38:58.000000000 +0000
++++ freeradius-server-2.1.7/Make.inc.in 2009-10-09 08:39:15.000000000 +0000
+@@ -10,6 +10,7 @@
+ sysconfdir = @sysconfdir@
+ localstatedir = @localstatedir@
+ libdir = @libdir@
++pkglibdir = @libdir@/freeradius
+ bindir = @bindir@
+ sbindir = @sbindir@
+ docdir = @docdir@
+diff -ru freeradius-server-2.1.7.orig/raddb/radiusd.conf.in freeradius-server-2.1.7/raddb/radiusd.conf.in
+--- freeradius-server-2.1.7.orig/raddb/radiusd.conf.in 2009-10-09 08:38:58.000000000 +0000
++++ freeradius-server-2.1.7/raddb/radiusd.conf.in 2009-10-09 08:39:15.000000000 +0000
+@@ -103,7 +103,7 @@
+ # make
+ # make install
+ #
+-libdir = @libdir@
++libdir = @libdir@/freeradius
+
+ # pidfile: Where to place the PID of the RADIUS server.
+ #
+diff -ru freeradius-server-2.1.7.orig/src/modules/Makefile freeradius-server-2.1.7/src/modules/Makefile
+--- freeradius-server-2.1.7.orig/src/modules/Makefile 2009-10-09 08:38:58.000000000 +0000
++++ freeradius-server-2.1.7/src/modules/Makefile 2009-10-09 08:39:15.000000000 +0000
+@@ -12,7 +12,7 @@
+ @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+
+ install:
+- $(INSTALL) -d -m 755 $(R)$(libdir)
++ $(INSTALL) -d -m 755 $(R)$(pkglibdir)
+ @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+
+ clean:
+diff -ru freeradius-server-2.1.7.orig/src/modules/rules.mak freeradius-server-2.1.7/src/modules/rules.mak
+--- freeradius-server-2.1.7.orig/src/modules/rules.mak 2009-10-09 08:38:58.000000000 +0000
++++ freeradius-server-2.1.7/src/modules/rules.mak 2009-10-09 08:40:56.000000000 +0000
+@@ -123,7 +123,7 @@
+ $(TARGET).la: $(LT_OBJS)
+ $(LIBTOOL) --mode=link $(CC) -release $(RADIUSD_VERSION) \
+ -module $(LINK_MODE) $(LDFLAGS) $(RLM_LDFLAGS) -o $@ \
+- -rpath $(libdir) $^ $(LIBRADIUS) $(RLM_LIBS) $(LIBS)
++ -rpath $(pkglibdir) $^ $(LIBRADIUS) $(RLM_LIBS) $(LIBS)
+
+ #######################################################################
+ #
+@@ -164,13 +164,13 @@
+ # Do any module-specific installation.
+ #
+ # If there isn't a TARGET defined, then don't do anything.
+-# Otherwise, install the libraries into $(libdir)
++# Otherwise, install the libraries into $(pkglibdir)
+ #
+ install:
+ @[ "x$(RLM_INSTALL)" = "x" ] || $(MAKE) $(MFLAGS) $(RLM_INSTALL)
+ if [ "x$(TARGET)" != "x" ]; then \
+ $(LIBTOOL) --mode=install $(INSTALL) -c \
+- $(TARGET).la $(R)$(libdir)/$(TARGET).la || exit $$?; \
++ $(TARGET).la $(R)$(pkglibdir)/$(TARGET).la || exit $$?; \
+ rm -f $(R)$(libdir)/$(TARGET)-$(RADIUSD_VERSION).la; \
+ ln -s $(TARGET).la $(R)$(libdir)/$(TARGET)-$(RADIUSD_VERSION).la || exit $$?; \
+ fi
diff --git a/main/freeradius/freeradius.confd b/main/freeradius/freeradius.confd
new file mode 100644
index 0000000000..9811289ba4
--- /dev/null
+++ b/main/freeradius/freeradius.confd
@@ -0,0 +1,5 @@
+# Config file for /etc/init.d/radiusd
+
+# see man pages for radiusd run `radiusd -h`
+# for valid cmdline options
+#RADIUSD_OPTS=""
diff --git a/main/freeradius/freeradius.initd b/main/freeradius/freeradius.initd
new file mode 100644
index 0000000000..03a0c584a6
--- /dev/null
+++ b/main/freeradius/freeradius.initd
@@ -0,0 +1,70 @@
+#!/sbin/runscript
+
+opts="${opts} reload"
+
+depend() {
+ need net
+ after firewall
+ use dns
+}
+
+checkconfig() {
+ #set the location of log files, including startup.log created by check-radiusd-config
+ if ! cd /var/log/radius ; then
+ eerror "Failed to change current directory to /var/log/radius"
+ return 1
+ fi
+
+ if [ ! -d /var/run/radiusd ] && ! mkdir /var/run/radiusd ; then
+ eerror "Failed to create /var/run/radiusd"
+ return 1
+ fi
+
+ if [ ! -f /etc/raddb/radiusd.conf ] ; then
+ eerror "No /etc/raddb/radiusd.conf file exists!"
+ return 1
+ fi
+
+ if [ "`/usr/sbin/radiusd -C >/dev/null 2>&1; echo $?`" != "0" ] ; then
+ eerror "Config not ok! (try /usr/sbin/radiusd -C )"
+ return 1
+ fi
+
+ RADIUSD_USER=`grep '^ *user *=' /etc/raddb/radiusd.conf | cut -d ' ' -f 3`
+ RADIUSD_GROUP=`grep '^ *group *=' /etc/raddb/radiusd.conf | cut -d ' ' -f 3`
+ if [ -n "${RADIUSD_USER}" ] && ! getent passwd ${RADIUSD_USER} > /dev/null ; then
+ eerror "${RADIUSD_USER} user missing!"
+ return 1
+ fi
+ if [ -n "${RADIUSD_GROUP}" ] && ! getent group ${RADIUSD_GROUP} > /dev/null ; then
+ eerror "${RADIUSD_GROUP} group missing!"
+ return 1
+ fi
+
+ #radius.log is created before privileges drop; we need to set proper permissions on it
+ [ -f radius.log ] || touch radius.log || return 1
+
+ chown -R "${RADIUSD_USER:-root}:${RADIUSD_GROUP:-root}" . /var/run/radiusd && \
+ chmod -R u+rwX,g+rX . /var/run/radiusd || return 1
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting radiusd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/radiusd -- ${RADIUSD_OPTS} >/dev/null
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping radiusd"
+ start-stop-daemon --stop --quiet --pidfile=/var/run/radius/radiusd.pid
+ eend $?
+}
+
+reload () {
+ ebegin "Reloading radiusd"
+ kill -HUP `</var/run/radiusd/radiusd.pid`
+ eend $?
+}
+
diff --git a/main/freeradius/freeradius.pre-install b/main/freeradius/freeradius.pre-install
new file mode 100644
index 0000000000..04c48bb3fe
--- /dev/null
+++ b/main/freeradius/freeradius.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+addgroup radiusd 2>/dev/null
+adduser -S -G radiusd -h /var/log/radius -s /bin/false -D radiusd 2>/dev/null
+exit 0
+
diff --git a/main/freerdp/APKBUILD b/main/freerdp/APKBUILD
new file mode 100644
index 0000000000..dfd5099dfe
--- /dev/null
+++ b/main/freerdp/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=freerdp
+pkgver=0.8.2
+pkgrel=2
+pkgdesc="Free RDP client"
+url="http://freerdp.sourceforge.net"
+arch="all"
+license="GPL"
+depends=""
+subpackages="$pkgname-dev $pkgname-doc libfreerdp"
+makedepends="openssl-dev libxcursor-dev cups-dev alsa-lib-dev"
+source="http://downloads.sourceforge.net/project/freerdp/${pkgver%.*}/freerdp-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+libfreerdp() {
+ pkgdesc="Free RDP client - Libraries"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/share "$pkgdir"/usr/lib "$subpkgdir"/usr/
+}
+
+md5sums="cde590336292c977dfc1b4b7badf24d2 freerdp-0.8.2.tar.gz"
diff --git a/main/freeswitch-sounds-en-us-callie-32000/APKBUILD b/main/freeswitch-sounds-en-us-callie-32000/APKBUILD
new file mode 100644
index 0000000000..fb0409f337
--- /dev/null
+++ b/main/freeswitch-sounds-en-us-callie-32000/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=freeswitch-sounds-en-us-callie-32000
+pkgver=1.0.16
+pkgrel=0
+pkgdesc="Sounds for freeswitch English"
+url="http://files.freeswitch.org/"
+arch="noarch"
+license="unknown"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://files.freeswitch.org/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"/usr/sounds/
+ cp -ra "$srcdir"/en "$pkgdir"/usr/sounds
+ chown -R root:root "$pkgdir"/usr/sounds
+}
+
+md5sums="d508c4725e1600dd8520b99ae9ed89e8 freeswitch-sounds-en-us-callie-32000-1.0.16.tar.gz"
diff --git a/main/freeswitch-sounds-en-us-callie-8000/APKBUILD b/main/freeswitch-sounds-en-us-callie-8000/APKBUILD
new file mode 100644
index 0000000000..dd7a9c8551
--- /dev/null
+++ b/main/freeswitch-sounds-en-us-callie-8000/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=freeswitch-sounds-en-us-callie-8000
+pkgver=1.0.16
+pkgrel=0
+pkgdesc="Sounds for freeswitch English"
+url="http://files.freeswitch.org/"
+arch="noarch"
+license="unknown"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://files.freeswitch.org/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"/usr/sounds/
+ cp -ra "$srcdir"/en "$pkgdir"/usr/sounds
+ chown -R root:root "$pkgdir"/usr/sounds
+}
+
+md5sums="bde0883eb75fe06f39bde11f50a1f858 freeswitch-sounds-en-us-callie-8000-1.0.16.tar.gz"
diff --git a/main/freeswitch-sounds-music-32000/APKBUILD b/main/freeswitch-sounds-music-32000/APKBUILD
new file mode 100644
index 0000000000..2293c096f7
--- /dev/null
+++ b/main/freeswitch-sounds-music-32000/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=freeswitch-sounds-music-32000
+pkgver=1.0.8
+pkgrel=0
+pkgdesc="Sounds for freeswitch English"
+url="http://files.freeswitch.org/"
+arch="noarch"
+license="unknown"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://files.freeswitch.org/$pkgname-$pkgver.tar.gz"
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"/usr/sounds/
+ cp -ra "$srcdir"/music "$pkgdir"/usr/sounds
+ chown -R root:root "$pkgdir"/usr/sounds
+}
+
+md5sums="7e03932ea81b8d0bf6d686f838b060b4 freeswitch-sounds-music-32000-1.0.8.tar.gz"
diff --git a/main/freeswitch-sounds-music-8000/APKBUILD b/main/freeswitch-sounds-music-8000/APKBUILD
new file mode 100644
index 0000000000..7f57a5bf64
--- /dev/null
+++ b/main/freeswitch-sounds-music-8000/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=freeswitch-sounds-music-8000
+pkgver=1.0.8
+pkgrel=0
+pkgdesc="Music for freeswitch"
+url="http://files.freeswitch.org/"
+arch="noarch"
+license="unknown"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://files.freeswitch.org/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"/usr/sounds/
+ cp -ra "$srcdir"/music "$pkgdir"/usr/sounds
+ chown -R root:root "$pkgdir"/usr/sounds
+}
+
+md5sums="f63ef3cc3507af079ae5c7b8b8a01e42 freeswitch-sounds-music-8000-1.0.8.tar.gz"
diff --git a/main/freeswitch-sounds-ru-RU-elena-32000/APKBUILD b/main/freeswitch-sounds-ru-RU-elena-32000/APKBUILD
new file mode 100644
index 0000000000..3d60268946
--- /dev/null
+++ b/main/freeswitch-sounds-ru-RU-elena-32000/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=freeswitch-sounds-ru-RU-elena-32000
+pkgver=1.0.12
+pkgrel=0
+pkgdesc="Sounds for freeswitch English"
+url="http://files.freeswitch.org/"
+arch="noarch"
+license="unknown"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://files.freeswitch.org/$pkgname-$pkgver.tar.gz"
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"/usr/sounds/
+ cp -ra "$srcdir"/ru "$pkgdir"/usr/sounds
+ chown -R root:root "$pkgdir"/usr/sounds
+}
+
+md5sums="827af236dd34faff857d7aefb169e196 freeswitch-sounds-ru-RU-elena-32000-1.0.12.tar.gz"
diff --git a/main/freeswitch-sounds-ru-RU-elena-8000/APKBUILD b/main/freeswitch-sounds-ru-RU-elena-8000/APKBUILD
new file mode 100644
index 0000000000..d62e75c970
--- /dev/null
+++ b/main/freeswitch-sounds-ru-RU-elena-8000/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=freeswitch-sounds-ru-RU-elena-8000
+pkgver=1.0.12
+pkgrel=0
+pkgdesc="Sounds for freeswitch English"
+url="http://files.freeswitch.org/"
+arch="noarch"
+license="unknown"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://files.freeswitch.org/$pkgname-$pkgver.tar.gz"
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir"/usr/sounds/
+ cp -ra "$srcdir"/ru "$pkgdir"/usr/sounds
+ chown -R root:root "$pkgdir"/usr/sounds
+}
+
+md5sums="f2f94b605ecc05300883703af92a32b3 freeswitch-sounds-ru-RU-elena-8000-1.0.12.tar.gz"
diff --git a/main/freeswitch/0001-mod_sofia-update-mod_sofia_globals.guess_ip-on-addre.patch b/main/freeswitch/0001-mod_sofia-update-mod_sofia_globals.guess_ip-on-addre.patch
new file mode 100644
index 0000000000..ccf4e5c6e9
--- /dev/null
+++ b/main/freeswitch/0001-mod_sofia-update-mod_sofia_globals.guess_ip-on-addre.patch
@@ -0,0 +1,27 @@
+From 67a60b5bf50fbfdf184dc4cb20a88d8d88ff59ad Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Fri, 10 Jun 2011 11:58:19 +0300
+Subject: [PATCH 1/2] mod_sofia: update mod_sofia_globals.guess_ip on address change
+
+So that we rebind to the new IP-address after reloading
+configuration. Fixes FS-3336.
+---
+ src/mod/endpoints/mod_sofia/mod_sofia.c | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
+index 86fa140..b06eacb 100644
+--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
++++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
+@@ -4889,6 +4889,8 @@ static void general_event_handler(switch_event_t *event)
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "EVENT_TRAP: IP change detected\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IP change detected [%s]->[%s] [%s]->[%s]\n", old_ip4, new_ip4, old_ip6, new_ip6);
+
++ strncpy(mod_sofia_globals.guess_ip, new_ip4, sizeof(mod_sofia_globals.guess_ip));
++
+ switch_mutex_lock(mod_sofia_globals.hash_mutex);
+ if (mod_sofia_globals.profile_hash) {
+ for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+--
+1.7.1
+
diff --git a/main/freeswitch/0002-mod_lua-alpine-module-search-path.patch b/main/freeswitch/0002-mod_lua-alpine-module-search-path.patch
new file mode 100644
index 0000000000..c83cfd58be
--- /dev/null
+++ b/main/freeswitch/0002-mod_lua-alpine-module-search-path.patch
@@ -0,0 +1,37 @@
+From ab10000fddd6735ff986d3b0f8092bc733bf5267 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Fri, 10 Jun 2011 13:06:35 +0300
+Subject: [PATCH 2/2] mod_lua: alpine module search path
+
+---
+ src/mod/languages/mod_lua/lua/luaconf.h | 9 +++++++--
+ 1 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/src/mod/languages/mod_lua/lua/luaconf.h b/src/mod/languages/mod_lua/lua/luaconf.h
+index ca2849b..bc8c17b 100644
+--- a/src/mod/languages/mod_lua/lua/luaconf.h
++++ b/src/mod/languages/mod_lua/lua/luaconf.h
+@@ -95,13 +95,18 @@
+
+ #else
+ #define LUA_ROOT "/usr/local/"
++#define LUA_ROOT2 "/usr/"
+ #define LUA_LDIR LUA_ROOT "share/lua/5.1/"
++#define LUA_LDIR2 LUA_ROOT2 "share/lua/5.1/"
+ #define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
++#define LUA_CDIR2 LUA_ROOT2 "lib/lua/5.1/"
+ #define LUA_PATH_DEFAULT \
+ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
+- LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
++ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
++ LUA_LDIR2"?.lua;" LUA_LDIR2"?/init.lua"
+ #define LUA_CPATH_DEFAULT \
+- "./?.so;" "./lib?51.so;" LUA_CDIR"?.so;" LUA_CDIR"lib?51.so;" LUA_CDIR"loadall.so"
++ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR2"?.so;" LUA_CDIR"loadall.so"
++
+ #endif
+
+
+--
+1.7.1
+
diff --git a/main/freeswitch/0003-mod_conference_no_hangup.patch b/main/freeswitch/0003-mod_conference_no_hangup.patch
new file mode 100644
index 0000000000..577ca8e1a4
--- /dev/null
+++ b/main/freeswitch/0003-mod_conference_no_hangup.patch
@@ -0,0 +1,27 @@
+diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
+index 572fdf0..d62d114 100644
+--- a/src/mod/applications/mod_conference/mod_conference.c
++++ b/src/mod/applications/mod_conference/mod_conference.c
+@@ -1482,13 +1482,15 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
+ if (!switch_test_flag(imember, MFLAG_NOCHANNEL)) {
+ channel = switch_core_session_get_channel(imember->session);
+
+- /* add this little bit to preserve the bridge cause code in case of an early media call that */
+- /* never answers */
+- if (switch_test_flag(conference, CFLAG_ANSWERED)) {
+- switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+- } else {
+- /* put actual cause code from outbound channel hangup here */
+- switch_channel_hangup(channel, conference->bridge_hangup_cause);
++ if (!switch_false(switch_channel_get_variable(channel, "hangup_after_conference"))) {
++ /* add this little bit to preserve the bridge cause code in case of an early media call that */
++ /* never answers */
++ if (switch_test_flag(conference, CFLAG_ANSWERED)) {
++ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
++ } else {
++ /* put actual cause code from outbound channel hangup here */
++ switch_channel_hangup(channel, conference->bridge_hangup_cause);
++ }
+ }
+ }
+
diff --git a/main/freeswitch/APKBUILD b/main/freeswitch/APKBUILD
new file mode 100644
index 0000000000..6958119263
--- /dev/null
+++ b/main/freeswitch/APKBUILD
@@ -0,0 +1,143 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=freeswitch
+pkgver=1.0.7_p20110602
+_ver=${pkgver%_p*}
+_snapshot=${pkgver#*_p}
+pkgrel=3
+pkgdesc="A communications platform written in C from the ground up"
+url="http://www.freeswitch.org"
+arch="all"
+license="GPL"
+depends=""
+makedepends="curl-dev unixodbc-dev zlib-dev openssl-dev ncurses-dev
+ autoconf automake libtool libpri-dev bash net-snmp-dev postgresql-dev
+ libiconv-dev subversion flac-dev libogg-dev libvorbis-dev
+ jpeg-dev"
+install="$pkgname.pre-install $pkgname.post-install $pkgname.pre-upgrade"
+subpackages="$pkgname-dev $pkgname-flite $pkgname-sample-config:conf $pkgname-freetdm"
+source="saveas-http://latest.freeswitch.org/freeswitch-$_ver.tar.gz/freeswitch-$pkgver.tar.gz
+ freeswitch-mod_shout-textrels.patch
+ 0001-mod_sofia-update-mod_sofia_globals.guess_ip-on-addre.patch
+ 0002-mod_lua-alpine-module-search-path.patch
+ 0003-mod_conference_no_hangup.patch
+ modules.conf
+ freeswitch.confd
+ freeswitch.initd
+ "
+
+_builddir="$srcdir/$pkgname-$_ver"
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ sed -i 's,freetdm.h,../src/include/freetdm.h,' libs/freetdm/mod_freetdm/mod_freetdm.c
+}
+
+build() {
+ cd "$_builddir"
+
+ # i think our max cmd len is 32768
+ # by specifying it here we save our selves from some CPU cycles
+ export lt_cv_sys_max_cmd_len=8192
+
+ sed -i -e 's#^dbdir="${prefix}/db"#dbdir="/var/lib/freeswitch"#' configure.in || return 1
+ ./bootstrap.sh
+
+ cp -f "$srcdir/modules.conf" modules.conf || return 1
+
+ # remove -Werror since gcc-4.5 is more strict
+ sed -i -e 's/-Werror//g' configure || return 1
+ CFLAGS="-Wno-unused-but-set-variable" ./configure --prefix=/usr \
+ --sysconfdir=/etc/freeswitch \
+ --with-modinstdir=/usr/lib/freeswitch \
+ --with-rundir=/var/run/freeswitch \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-devrandom=/dev/urandom \
+ --with-libpri \
+ --disable-debug \
+ || return 1
+
+ # first build libfreeswitch (in parallel)
+ make src/include/switch_version.h src/include/switch_swigable_cpp.h
+ make libfreeswitch.la || return 1
+ # finally we build the rest
+ make -j1 all || return 1
+}
+package(){
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+
+ # we need to do some moving/cleanup to allow some... kind of FHS
+ mkdir -p "$pkgdir"/var/run/freeswitch
+ mkdir -p "$pkgdir"/var/lib/freeswitch
+ mkdir -p "$pkgdir"/var/log
+ mkdir -p "$pkgdir"/usr/share/freeswitch
+ mv "$pkgdir"/usr/db "$pkgdir"/var/lib/freeswitch/
+ mv "$pkgdir"/usr/grammar "$pkgdir"/var/lib/freeswitch/
+ mv "$pkgdir"/usr/htdocs "$pkgdir"/usr/share/freeswitch/
+ mv "$pkgdir"/usr/recordings "$pkgdir"/var/lib/freeswitch/
+ mv "$pkgdir"/usr/scripts "$pkgdir"/etc/freeswitch/
+ mv "$pkgdir"/usr/log "$pkgdir"/var/log/freeswitch
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+
+_mv_mod() {
+ local moddir=usr/lib/freeswitch i=
+ mkdir -p "$subpkgdir"/$moddir
+ for i in $@; do
+ mv "$pkgdir"/$moddir/$i.so "$subpkgdir"/$moddir/ || return 1
+ done
+}
+
+
+flite() {
+ pkgdesc="Freeswitch Text To Speech Module"
+ install=
+ _mv_mod mod_flite
+##
+## The mod_say_xx modules can be used with out flite (for numbers, etc using
+## sound files). So they shouldn't be in the flite package -cB
+##
+# _mv_mod mod_say_de mod_say_en mod_say_es mod_say_fr \
+# mod_say_it mod_say_nl mod_say_zh mod_say_hu mod_say_ru \
+# mod_say_th mod_say_he
+}
+
+freetdm() {
+ pkgdesc="Freeswitch FreeTDM Module"
+ install=
+ _mv_mod mod_freetdm ftmod_analog ftmod_analog_em ftmod_libpri \
+ ftmod_skel ftmod_zt
+ mv "$pkgdir"/usr/lib/libfreetdm.so* "$subpkgdir"/usr/lib/
+}
+
+conf() {
+ pkgdesc="Freeswitch sample configureation"
+ arch="noarch"
+ install=
+ mkdir -p "$subpkgdir"/etc/freeswitch
+ # move all configs except freeswitch.xml
+ for i in "$pkgdir"/etc/freeswitch/*; do
+ [ "$i" = "$pkgdir"/etc/freeswitch/freeswitch.xml ] && continue
+ mv "$i" "$subpkgdir"/etc/freeswitch/ || return 1
+ done
+ mkdir -p "$pkgdir"/etc/freeswitch/scripts
+}
+
+md5sums="813edb2192d1cc0fe224d9ef0492de4f freeswitch-1.0.7_p20110602.tar.gz
+11883affe0839a8e15fe680aeb11b86e freeswitch-mod_shout-textrels.patch
+5aed9ec61d7ac1f3758a89db159328c4 0001-mod_sofia-update-mod_sofia_globals.guess_ip-on-addre.patch
+769eaa127d4dbae687dc4aa961a8cc70 0002-mod_lua-alpine-module-search-path.patch
+74c3cdd3ce8474e8d084f475fa4f92c1 0003-mod_conference_no_hangup.patch
+691fa3aca967203848bbb2a617545265 modules.conf
+c608cca8ad773acebf201f581438c7e7 freeswitch.confd
+aa358c9ca0d8b93fabb6a36a5ed4c469 freeswitch.initd"
diff --git a/main/freeswitch/freeswitch-mod_shout-textrels.patch b/main/freeswitch/freeswitch-mod_shout-textrels.patch
new file mode 100644
index 0000000000..7cc7e3fa7a
--- /dev/null
+++ b/main/freeswitch/freeswitch-mod_shout-textrels.patch
@@ -0,0 +1,11 @@
+--- ./src/mod/formats/mod_shout/Makefile.orig
++++ ./src/mod/formats/mod_shout/Makefile
+@@ -30,7 +30,7 @@
+
+ $(MPG123_BUILDDIR)/Makefile: $(MPG123_DIR)
+ mkdir -p $(MPG123_BUILDDIR)
+- cd $(MPG123_BUILDDIR) && $(DEFAULT_VARS) $(MPG123_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(MPG123_DIR) CPPFLAGS= LDFLAGS=
++ cd $(MPG123_BUILDDIR) && $(DEFAULT_VARS) $(MPG123_DIR)/configure $(DEFAULT_ARGS) --with-cpu=i386_fpu --srcdir=$(MPG123_DIR) CPPFLAGS= LDFLAGS=
+ $(TOUCH_TARGET)
+
+ $(MPG123LA): $(MPG123_BUILDDIR)/Makefile
diff --git a/main/freeswitch/freeswitch.confd b/main/freeswitch/freeswitch.confd
new file mode 100644
index 0000000000..378e4b41f4
--- /dev/null
+++ b/main/freeswitch/freeswitch.confd
@@ -0,0 +1,25 @@
+#
+# FreeSWITCH startup configuration
+#
+
+# freeswitch will be running with this userid
+FREESWITCH_USER="freeswitch"
+
+
+# optional: group the freeswitch process should be running with
+#
+# (note: without this option freeswitch will be using all groups
+# the user in FREESWITCH_USER is a member of)
+#
+#FREESWITCH_GROUP="freeswitch"
+
+
+
+# optional: other options, e.g.
+#
+# -hp Use realtime priority and protect freeswitch
+# process from being swapped to disk
+# (warning: dangerous on machines with little ram!)
+#
+#FREESWITCH_OPTS=""
+
diff --git a/main/freeswitch/freeswitch.initd b/main/freeswitch/freeswitch.initd
new file mode 100755
index 0000000000..3fc9ee449a
--- /dev/null
+++ b/main/freeswitch/freeswitch.initd
@@ -0,0 +1,63 @@
+#!/sbin/runscript
+# Copyright 2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: $
+
+depend() {
+ need net
+}
+
+opts="reload"
+pidfile=/var/run/freeswitch/freeswitch.pid
+
+start() {
+ local OPTS
+
+ [ -n "${FREESWITCH_USER}" ] && \
+ OPTS="${OPTS} -u ${FREESWITCH_USER}"
+
+ [ -n "${FREESWITCH_GROUP}" ] && \
+ OPTS="${OPTS} -g ${FREESWITCH_GROUP}"
+
+ [ -n "${FREESWITCH_OPTS}" ] && \
+ OPTS="${OPTS} ${FREESWITCH_OPTS}"
+
+ ebegin "Starting Freeswitch"
+ limits
+ start-stop-daemon --start --quiet --exec /usr/bin/freeswitch \
+ -- \
+ -nc -conf /etc/freeswitch -log /var/log/freeswitch \
+ -run /var/run/freeswitch -db /var/lib/freeswitch/db \
+ -htdocs /usr/share/freeswitch/htdocs \
+ -scripts /etc/freeswitch/scripts ${OPTS}
+ eend $?
+}
+
+# Recomended ULIMIT settings
+# http://tinyurl.com/2dr467l (i,q,u,x not suppoted)
+
+limits() {
+ ulimit -c unlimited
+ ulimit -d unlimited
+ ulimit -f unlimited
+ ulimit -n 999999
+ ulimit -v unlimited
+ ulimit -s 244
+ ulimit -l unlimited
+}
+
+stop() {
+ ebegin "Stopping Freeswitch"
+ start-stop-daemon --quiet --stop \
+ --pidfile $pidfile \
+ --retry 10 \
+ --exec /usr/bin/freeswitch
+ eend $?
+}
+
+reload() {
+ start-stop-daemon --stop --signal 1 --quiet \
+ --pidfile $pidfile --name freeswitch
+ return 0
+}
+
diff --git a/main/freeswitch/freeswitch.post-install b/main/freeswitch/freeswitch.post-install
new file mode 100755
index 0000000000..fef23caef1
--- /dev/null
+++ b/main/freeswitch/freeswitch.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+chown -R freeswitch:freeswitch /var/*/freeswitch
+
+exit 0
diff --git a/main/freeswitch/freeswitch.pre-install b/main/freeswitch/freeswitch.pre-install
new file mode 100755
index 0000000000..043b963bbd
--- /dev/null
+++ b/main/freeswitch/freeswitch.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -H -h /var/run/freeswitch -s /bin/false -D freeswitch 2>/dev/null
+
+exit 0
diff --git a/main/freeswitch/freeswitch.pre-upgrade b/main/freeswitch/freeswitch.pre-upgrade
new file mode 100644
index 0000000000..b2c361bed2
--- /dev/null
+++ b/main/freeswitch/freeswitch.pre-upgrade
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+olddir=/usr/share/freeswitch/scripts
+if [ -d "$olddir" ] && ! [ -d /etc/freeswitch/scripts ]; then
+ echo "NOTE: Moving scripts to /etc/freeswitch/scripts"
+ mkdir -p /etc/freeswitch
+ mv "$olddir" /etc/freeswitch
+fi
+
+# ignore errors
+exit 0
diff --git a/main/freeswitch/modules.conf b/main/freeswitch/modules.conf
new file mode 100644
index 0000000000..b87e6786cf
--- /dev/null
+++ b/main/freeswitch/modules.conf
@@ -0,0 +1,122 @@
+loggers/mod_console
+loggers/mod_logfile
+loggers/mod_syslog
+#applications/mod_cidlookup
+applications/mod_commands
+applications/mod_conference
+applications/mod_dptools
+applications/mod_enum
+#applications/mod_osp
+applications/mod_fifo
+applications/mod_curl
+applications/mod_db
+applications/mod_hash
+#applications/mod_redis
+applications/mod_voicemail
+applications/mod_directory
+#applications/mod_lcr
+applications/mod_expr
+applications/mod_esf
+#applications/mod_easyroute
+applications/mod_fsv
+#applications/mod_nibblebill
+#applications/mod_soundtouch
+#applications/mod_rss
+applications/mod_spandsp
+#applications/mod_snom
+#applications/mod_vmd
+#applications/mod_avmd
+#applications/mod_memcache
+#applications/mod_spy
+applications/mod_cluechoo
+applications/mod_valet_parking
+applications/mod_distributor
+#applications/mod_stress
+#applications/mod_snapshot
+#applications/mod_snipe_hunt
+applications/mod_callcenter
+#applications/mod_fsk
+#applications/mod_ladspa
+#applications/mod_mongo
+codecs/mod_g723_1
+codecs/mod_amr
+#codecs/mod_amrwb
+#codecs/mod_silk
+#codecs/mod_codec2
+codecs/mod_g729
+#codecs/mod_com_g729
+codecs/mod_h26x
+codecs/mod_bv
+codecs/mod_ilbc
+codecs/mod_speex
+codecs/mod_siren
+#codecs/mod_celt
+#codecs/mod_opus
+#codecs/mod_sangoma_codec
+#codecs/mod_dahdi_codec
+#dialplans/mod_dialplan_directory
+dialplans/mod_dialplan_xml
+dialplans/mod_dialplan_asterisk
+#directories/mod_ldap
+#endpoints/mod_dingaling
+#endpoints/mod_portaudio
+endpoints/mod_sofia
+endpoints/mod_loopback
+#endpoints/mod_alsa
+#endpoints/mod_opal
+#endpoints/mod_skinny
+#endpoints/mod_skypopen
+#endpoints/mod_h323
+#endpoints/mod_khomp
+#endpoints/mod_gsmopen
+#../../libs/openzap/mod_openzap
+../../libs/freetdm/mod_freetdm
+#asr_tts/mod_unimrcp
+asr_tts/mod_flite
+#asr_tts/mod_pocketsphinx
+#asr_tts/mod_cepstral
+#asr_tts/mod_tts_commandline
+#event_handlers/mod_event_multicast
+event_handlers/mod_event_socket
+#event_handlers/mod_event_zmq
+event_handlers/mod_cdr_csv
+event_handlers/mod_cdr_sqlite
+event_handlers/mod_cdr_pg_csv
+#event_handlers/mod_radius_cdr
+#event_handlers/mod_erlang_event
+event_handlers/mod_snmp
+formats/mod_native_file
+formats/mod_sndfile
+formats/mod_shout
+formats/mod_local_stream
+formats/mod_tone_stream
+#formats/mod_portaudio_stream
+#formats/mod_shell_stream
+#languages/mod_python
+#languages/mod_spidermonkey
+languages/mod_lua
+#languages/mod_perl
+#languages/mod_yaml
+#languages/mod_java
+#languages/mod_managed
+xml_int/mod_xml_rpc
+xml_int/mod_xml_curl
+xml_int/mod_xml_cdr
+#xml_int/mod_xml_ldap
+say/mod_say_en
+say/mod_say_de
+say/mod_say_es
+say/mod_say_fr
+say/mod_say_it
+say/mod_say_nl
+say/mod_say_pt
+say/mod_say_ru
+say/mod_say_zh
+say/mod_say_hu
+say/mod_say_th
+say/mod_say_he
+timers/mod_timerfd
+
+## Experimental Modules (don't cry if they're broken)
+#../../contrib/mod/xml_int/mod_xml_odbc
+
diff --git a/main/freetds/APKBUILD b/main/freetds/APKBUILD
new file mode 100644
index 0000000000..0475ff86dc
--- /dev/null
+++ b/main/freetds/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=freetds
+pkgver=0.82
+pkgrel=9
+pkgdesc="Tabular Datastream Library"
+url="http://www.freetds.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="unixodbc-dev readline-dev libiconv-dev libtool"
+install=
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-msdblib
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="3df6b2e83fd420e90f1becbd1162990a freetds-0.82.tar.gz"
diff --git a/main/freetype/20-enable-spr.patch b/main/freetype/20-enable-spr.patch
new file mode 100644
index 0000000000..217912aa1f
--- /dev/null
+++ b/main/freetype/20-enable-spr.patch
@@ -0,0 +1,11 @@
+--- include/freetype/config/ftoption.h.spf 2007-01-18 14:27:34.000000000 -0500
++++ include/freetype/config/ftoption.h 2007-01-18 14:27:48.000000000 -0500
+@@ -92,7 +92,7 @@
+ /* This is done to allow FreeType clients to run unmodified, forcing */
+ /* them to display normal gray-level anti-aliased glyphs. */
+ /* */
+-/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
++#define FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+
+ /*************************************************************************/
diff --git a/main/freetype/30-enable-valid.patch b/main/freetype/30-enable-valid.patch
new file mode 100644
index 0000000000..b61a792219
--- /dev/null
+++ b/main/freetype/30-enable-valid.patch
@@ -0,0 +1,20 @@
+--- modules.cfg.orig 2006-07-07 21:01:09.000000000 -0400
++++ modules.cfg 2006-07-07 21:01:54.000000000 -0400
+@@ -110,7 +110,7 @@
+ AUX_MODULES += cache
+
+ # TrueType GX/AAT table validation. Needs ftgxval.c below.
+-# AUX_MODULES += gxvalid
++AUX_MODULES += gxvalid
+
+ # Support for streams compressed with gzip (files with suffix .gz).
+ #
+@@ -124,7 +124,7 @@
+
+ # OpenType table validation. Needs ftotval.c below.
+ #
+-# AUX_MODULES += otvalid
++AUX_MODULES += otvalid
+
+ # Auxiliary PostScript driver component to share common code.
+ #
diff --git a/main/freetype/40-memcpy-fix.patch b/main/freetype/40-memcpy-fix.patch
new file mode 100644
index 0000000000..95c1cd6430
--- /dev/null
+++ b/main/freetype/40-memcpy-fix.patch
@@ -0,0 +1,14 @@
+--- src/psaux/psobjs.c~ 2006-04-26 16:38:17.000000000 +0200
++++ src/psaux/psobjs.c 2006-09-10 15:01:13.000000000 +0200
+@@ -165,6 +165,11 @@
+ return PSaux_Err_Invalid_Argument;
+ }
+
++ if ( length < 0 ) {
++ FT_ERROR(( "ps_table_add: invalid length\n" ));
++ return PSaux_Err_Invalid_Argument;
++ }
++
+ /* grow the base block if needed */
+ if ( table->cursor + length > table->capacity )
+ {
diff --git a/main/freetype/APKBUILD b/main/freetype/APKBUILD
new file mode 100644
index 0000000000..1ec5bc3d71
--- /dev/null
+++ b/main/freetype/APKBUILD
@@ -0,0 +1,49 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=freetype
+pkgver=2.4.5
+pkgrel=1
+pkgdesc="TrueType font rendering library"
+url="http://freetype.sourceforge.net"
+arch="all"
+license="GPL"
+depends=
+depends_dev="zlib-dev"
+makedepends="$depends_dev"
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+20-enable-spr.patch
+30-enable-valid.patch
+40-memcpy-fix.patch
+"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ msg "Applying ${i}"
+ patch -p0 -i $i || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="0e67460b312df905dc1cc1586690e7b2 freetype-2.4.5.tar.gz
+376b94c06b113a62a3437e4130bb3fc3 20-enable-spr.patch
+3f6c5739843dcbc110ee0f243c4f6bdb 30-enable-valid.patch
+bd2d808a0c00dcf9f1d1c0a9a8227ad9 40-memcpy-fix.patch"
diff --git a/main/fribidi/APKBUILD b/main/fribidi/APKBUILD
new file mode 100644
index 0000000000..7a9eeb870c
--- /dev/null
+++ b/main/fribidi/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fribidi
+pkgver=0.19.2
+pkgrel=5
+pkgdesc="A Free Implementation of the Unicode Bidirectional Algorithm"
+url="http://fribidi.org"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends=
+source="http://$pkgname.org/download/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="626db17d2d99b43615ad9d12500f568a fribidi-0.19.2.tar.gz"
diff --git a/main/fts/APKBUILD b/main/fts/APKBUILD
new file mode 100644
index 0000000000..e6f2850ec7
--- /dev/null
+++ b/main/fts/APKBUILD
@@ -0,0 +1,56 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=fts
+pkgver=0
+pkgrel=3
+pkgdesc="keith bostic's POSIX file tree stream operations library"
+url="http://bostic.com/"
+arch="all"
+license="BSD"
+depends=
+depends_dev=
+makedepends="$depends_dev wget"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+replaces_doc="man-pages"
+source="saveas-https://sites.google.com/a/bostic.com/keithbostic/files/fts.tar.gz?attredirects=0/fts.tar.gz
+ fts-uclibc.patch
+ fts-header-correctness.patch
+ stdint.patch"
+
+_builddir="${srcdir}/${pkgname}"
+prepare() {
+ local i
+ cd "$_builddir"
+ chmod +w *.c
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ gcc -I. -fPIC -shared -o libfts.so -Wl,-soname,libfts.so.${pkgver} fts.c
+}
+
+package() {
+ cd "$_builddir"
+
+ install -d "$pkgdir"/usr/lib
+
+ install -m 755 libfts.so "$pkgdir"/usr/lib/libfts.so.${pkgver}
+ ln -sf libfts.so.${pkgver} "$pkgdir"/usr/lib/libfts.so
+
+ install -d "$pkgdir"/usr/include
+ install -m 644 fts.h "$pkgdir"/usr/include/fts.h
+
+ install -d "$pkgdir"/usr/share/man/man3
+ install -m 644 fts.3 "$pkgdir"/usr/share/man/man3/fts.3
+}
+
+md5sums="120c14715485ec6ced14f494d059d20a fts.tar.gz
+588fead4044bf535ff97298651aaab8f fts-uclibc.patch
+b197744ece4ef9a5fa52692acf9b6666 fts-header-correctness.patch
+a8a5a8e81e1c67738aef00f3f13a718b stdint.patch"
diff --git a/main/fts/fts-header-correctness.patch b/main/fts/fts-header-correctness.patch
new file mode 100644
index 0000000000..59061bfc95
--- /dev/null
+++ b/main/fts/fts-header-correctness.patch
@@ -0,0 +1,20 @@
+--- fts.orig/fts.h
++++ fts/fts.h
+@@ -38,6 +38,17 @@
+ #ifndef _FTS_H_
+ #define _FTS_H_
+
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/stat.h>
++
++#include <dirent.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
+ typedef struct {
+ struct _ftsent *fts_cur; /* current node */
+ struct _ftsent *fts_child; /* linked list of children */
diff --git a/main/fts/fts-uclibc.patch b/main/fts/fts-uclibc.patch
new file mode 100644
index 0000000000..3593530396
--- /dev/null
+++ b/main/fts/fts-uclibc.patch
@@ -0,0 +1,45 @@
+--- fts.orig/fts.c
++++ fts/fts.c
+@@ -31,6 +31,10 @@
+ * SUCH DAMAGE.
+ */
+
++#define alignof(TYPE) ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
++#define ALIGNBYTES (alignof(long double) - 1)
++#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
++
+ #if defined(LIBC_SCCS) && !defined(lint)
+ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
+ #endif /* LIBC_SCCS and not lint */
+@@ -652,10 +656,10 @@
+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+ continue;
+
+- if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen)) == NULL)
++ if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_reclen)) == NULL)
+ goto mem1;
+- if (dp->d_namlen > maxlen) {
+- if (fts_palloc(sp, (size_t)dp->d_namlen)) {
++ if (dp->d_reclen > maxlen) {
++ if (fts_palloc(sp, (size_t)dp->d_reclen)) {
+ /*
+ * No more memory for path or structures. Save
+ * errno, free up the current structure and the
+@@ -675,7 +679,7 @@
+ maxlen = sp->fts_pathlen - sp->fts_cur->fts_pathlen - 1;
+ }
+
+- p->fts_pathlen = len + dp->d_namlen + 1;
++ p->fts_pathlen = len + dp->d_reclen + 1;
+ p->fts_parent = sp->fts_cur;
+ p->fts_level = level;
+
+@@ -784,7 +788,7 @@
+ /* If user needs stat info, stat buffer already allocated. */
+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+-#ifdef DT_WHT
++#ifdef S_IFWHT
+ /*
+ * Whited-out files don't really exist. However, there's stat(2) file
+ * mask for them, so we set it so that programs (i.e., find) don't have
diff --git a/main/fts/stdint.patch b/main/fts/stdint.patch
new file mode 100644
index 0000000000..1ad7157e58
--- /dev/null
+++ b/main/fts/stdint.patch
@@ -0,0 +1,10 @@
+--- ./fts.c.orig
++++ ./fts.c
+@@ -46,6 +46,7 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <fts.h>
++#include <stdint.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
diff --git a/main/fuse/APKBUILD b/main/fuse/APKBUILD
new file mode 100644
index 0000000000..5d492b4e7f
--- /dev/null
+++ b/main/fuse/APKBUILD
@@ -0,0 +1,66 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=fuse
+pkgver=2.8.5
+pkgrel=2
+pkgdesc="A library that makes it possible to implement a filesystem in a userspace program."
+url="http://fuse.sourceforge.net/"
+arch="all"
+license="GPL2"
+depends=
+makedepends="pkgconfig libiconv-dev gettext-dev
+ autoconf automake libtool"
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ fuse-iconv.patch
+ fuse.initd"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ patch -p1 -i "$srcdir"/fuse-iconv.patch || return 1
+ aclocal -I m4 && libtoolize && autoconf && automake
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-static \
+ --enable-shared \
+ --disable-example \
+ --enable-lib \
+ --enable-util \
+ --bindir=/bin \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm -r "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/dev \
+ "$pkgdir"/etc/init.d || return 1
+
+ install -Dm755 "$srcdir"/fuse.initd "$pkgdir"/etc/init.d/fuse
+ # create config
+ install -d "$pkgdir"/etc
+ cat >"$pkgdir"/etc/fuse.conf << _EOF_
+# Set the maximum number of FUSE mounts allowed to non-root users.
+# The default is 1000.
+#
+#mount_max = 1000
+
+# Allow non-root users to specify the 'allow_other' or 'allow_root'
+# mount options.
+#
+#user_allow_other
+_EOF_
+
+}
+
+md5sums="8aa2fd689de00b73963620483084ae3b fuse-2.8.5.tar.gz
+1583e4e6f2213290ba47055c41114371 fuse-iconv.patch
+5983726cfabf0830dffbbbf9a3abcddc fuse.initd"
diff --git a/main/fuse/fuse-iconv.patch b/main/fuse/fuse-iconv.patch
new file mode 100644
index 0000000000..521dbbf73b
--- /dev/null
+++ b/main/fuse/fuse-iconv.patch
@@ -0,0 +1,11 @@
+--- ./configure.in.orig
++++ ./configure.in
+@@ -71,7 +71,7 @@
+ done
+ ])
+ AM_ICONV
+-libfuse_libs="$libfuse_libs $LIBICONV"
++libfuse_libs="$libfuse_libs $LTLIBICONV"
+ AM_CONDITIONAL(ICONV, test "$am_cv_func_iconv" = yes)
+ AC_SUBST(libfuse_libs)
+
diff --git a/main/fuse/fuse.initd b/main/fuse/fuse.initd
new file mode 100644
index 0000000000..30b512e8dc
--- /dev/null
+++ b/main/fuse/fuse.initd
@@ -0,0 +1,35 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+MOUNTPOINT=/sys/fs/fuse/connections
+
+depend() {
+ need localmount
+}
+
+start() {
+
+ ebegin "Starting fuse"
+ if ! grep -qw fuse /proc/filesystems; then
+ modprobe fuse >/dev/null 2>&1 || eerror $? "Error loading fuse module"
+ fi
+ if grep -qw fusectl /proc/filesystems && \
+ ! grep -qw $MOUNTPOINT /proc/mounts; then
+ mount -t fusectl none $MOUNTPOINT >/dev/null 2>&1 || \
+ eerror $? "Error mounting control filesystem"
+ fi
+ eend ${?}
+
+}
+
+stop() {
+
+ ebegin "Stopping fuse"
+ if grep -qw $MOUNTPOINT /proc/mounts; then
+ umount $MOUNTPOINT >/dev/null 2>&1 || \
+ eerror $? "Error unmounting control filesystem"
+ fi
+ eend ${?}
+
+}
diff --git a/main/galculator/APKBUILD b/main/galculator/APKBUILD
new file mode 100644
index 0000000000..1bfff07d46
--- /dev/null
+++ b/main/galculator/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=galculator
+pkgver=1.3.4
+pkgrel=2
+pkgdesc="GTK+ based scientific calculator"
+url="http://galculator.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends="intltool libglade-dev gtk+-dev"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/galculator-$pkgver"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/galculator-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="d30e6fbf5947bb1c873bc9d5a21046f1 galculator-1.3.4.tar.bz2"
diff --git a/main/gamin/APKBUILD b/main/gamin/APKBUILD
new file mode 100644
index 0000000000..5e790d6057
--- /dev/null
+++ b/main/gamin/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gamin
+pkgver=0.1.10
+pkgrel=7
+pkgdesc="Gamin is a file and directory monitoring system defined to be a subset of the FAM (File Alteration Monitor) system."
+url="http://www.gnome.org/~veillard/gamin"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev py-$pkgname:py"
+depends=
+makedepends="pkgconfig glib-dev python-dev"
+source="http://www.gnome.org/~veillard/$pkgname/sources/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-static \
+ --with-threads \
+ --disable-debug-api \
+ --disable-debug \
+ --disable-dnotify \
+ --libexecdir=/usr/lib/gamin
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ # some kinde of race in the make install which is not solved with -j || return 1
+ export MKDIRPROG="mkdir -p"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/python*/site-packages/*.la \
+ "$pkgdir"/usr/lib/*.la || return 1
+}
+
+py() {
+ pkgdesc="Python bindings for the gamin library"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/python* "$subpkgdir"/usr/lib/
+}
+
+md5sums="b4ec549e57da470c04edd5ec2876a028 gamin-0.1.10.tar.gz"
diff --git a/main/garcon/APKBUILD b/main/garcon/APKBUILD
new file mode 100644
index 0000000000..18b3516d8a
--- /dev/null
+++ b/main/garcon/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=garcon
+pkgver=0.1.7
+pkgrel=1
+pkgdesc="a freedesktop.org compliant menu implementation based on GLib and GIO"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="glib-dev intltool"
+install=
+source="http://archive.xfce.org/src/libs/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+depends_dev="glib-dev"
+replaces="xfdesktop"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="8990668e4f2fecffe124f613b6e1e01f garcon-0.1.7.tar.bz2"
diff --git a/main/gawk/APKBUILD b/main/gawk/APKBUILD
new file mode 100644
index 0000000000..0734cdaff5
--- /dev/null
+++ b/main/gawk/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gawk
+pkgver=3.1.8
+pkgrel=1
+pkgdesc="GNU awk pattern-matching language"
+url="http://www.gnu.org/software/gawk/gawk.html"
+arch="all"
+license="GPL"
+depends=
+makedepends=""
+install=
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz
+ $install"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --build=${CBUILD} \
+ --host=${CHOST} \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="35937a0f83f0efe7a8c2dee635624784 gawk-3.1.8.tar.gz"
diff --git a/main/gawk/gawk.post-deinstall b/main/gawk/gawk.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/gawk/gawk.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/gc/APKBUILD b/main/gc/APKBUILD
new file mode 100644
index 0000000000..28ce62c36a
--- /dev/null
+++ b/main/gc/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gc
+pkgver=7.1
+pkgrel=2
+pkgdesc="A garbage collector for C and C++"
+url="http://www.hpl.hp.com/personal/Hans_Boehm/gc/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+subpackages="$pkgname-dev $pkgname-doc libgc++:libgccpp"
+source="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc-$pkgver.tar.gz
+ uclibc-getcontext.patch"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 -i "$srcdir"/uclibc-getcontext.patch || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --datadir=/usr/share/doc/gc \
+ --enable-cplusplus || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+libgccpp() {
+ install -d "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libgccpp.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="2ff9924c7249ef7f736ecfe6f08f3f9b gc-7.1.tar.gz
+bce75c75bf0cdb295ac0bf7ba0f6e267 uclibc-getcontext.patch"
diff --git a/main/gc/uclibc-getcontext.patch b/main/gc/uclibc-getcontext.patch
new file mode 100644
index 0000000000..de48fc0183
--- /dev/null
+++ b/main/gc/uclibc-getcontext.patch
@@ -0,0 +1,11 @@
+--- ./mach_dep.c.orig
++++ ./mach_dep.c
+@@ -175,7 +175,7 @@
+ # if defined(HAVE_PUSH_REGS)
+ GC_push_regs();
+ # elif defined(UNIX_LIKE) && !defined(DARWIN) && !defined(ARM32) && \
+- !defined(HURD)
++ !defined(HURD) && !defined(__UCLIBC__)
+ /* Older versions of Darwin seem to lack getcontext(). */
+ /* ARM Linux often doesn't support a real getcontext(). */
+ ucontext_t ctxt;
diff --git a/main/gcc/09_all_gcc-4.5-Wtrampolines.patch b/main/gcc/09_all_gcc-4.5-Wtrampolines.patch
new file mode 100644
index 0000000000..9c95c1e940
--- /dev/null
+++ b/main/gcc/09_all_gcc-4.5-Wtrampolines.patch
@@ -0,0 +1,64 @@
+2010-07-15 Magnus Granberg <zorry@gentoo.org>
+ Kevin F. Quinn <kevquinn@gentoo.org>
+
+ * builtins.c (expand_builtin_init_trampoline): If
+ -Wtrampolines make a warning.
+ * common.opt: Add -Wtrampolines.
+ * doc/invoke.texi: Add -Wtrampolines.
+
+2010-07-31 Magnus Granberg <zorry@gentoo.org>
+
+ #328451 set -Wtrampolines as default
+
+http://gcc.gnu.org/viewcvs?view=revision&revision=162205
+
+--- a/gcc/builtins.c
++++ b/gcc/builtins.c
+@@ -5155,6 +5155,10 @@ expand_builtin_init_trampoline (tree exp)
+ targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
+
+ trampolines_created = 1;
++
++ warning_at (DECL_SOURCE_LOCATION (t_func), OPT_Wtrampolines,
++ "trampoline generated for nested function %qD", t_func);
++
+ return const0_rtx;
+ }
+
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -192,6 +192,10 @@ Wsystem-headers
+ Common Var(warn_system_headers) Warning
+ Do not suppress warnings from system headers
+
++Wtrampolines
++Common Var(warn_trampolines) Init(1) Warning
++Warn whenever a trampoline is generated
++
+ Wtype-limits
+ Common Var(warn_type_limits) Init(-1) Warning
+ Warn if a comparison is always true or always false due to the limited range of the data type
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -3611,6 +3611,21 @@ code. However, note that using @option{-Wall} in conjunction with this
+ option will @emph{not} warn about unknown pragmas in system
+ headers---for that, @option{-Wunknown-pragmas} must also be used.
+
++@item -Wtrampolines
++@opindex Wtrampolines
++@opindex Wno-trampolines
++ Warn about trampolines generated for pointers to nested functions.
++
++ NOTE: In Gentoo, @option{-Wtrampolines} is set by default.
++ To disable, specify @option{-Wno-trampolines}
++
++ A trampoline is a small piece of data or code that is created at run
++ time on the stack when the address of a nested function is taken, and
++ is used to call the nested function indirectly. For some targets, it
++ is made up of data only and thus requires no special treatment. But,
++ for most targets, it is made up of code and thus requires the stack
++ to be made executable in order for the program to work properly.
++
+ @item -Wfloat-equal
+ @opindex Wfloat-equal
+ @opindex Wno-float-equal
diff --git a/main/gcc/15_all_gcc-libgomp-no-werror.patch b/main/gcc/15_all_gcc-libgomp-no-werror.patch
new file mode 100644
index 0000000000..1c3ec3a1e5
--- /dev/null
+++ b/main/gcc/15_all_gcc-libgomp-no-werror.patch
@@ -0,0 +1,16 @@
+libgomp does not respect --disable-werror
+
+http://bugs.gentoo.org/229059
+http://gcc.gnu.org/PR38436
+
+--- gcc-4.3.2/libgomp/configure
++++ gcc-4.3.2/libgomp/configure
+@@ -3297,7 +3297,7 @@
+
+ # Add -Wall -Werror if we are using GCC.
+ if test "x$GCC" = "xyes"; then
+- XCFLAGS="$XCFLAGS -Wall -Werror"
++ XCFLAGS="$XCFLAGS -Wall"
+ fi
+
+ # Find other programs we need.
diff --git a/main/gcc/50_all_pr45312-kernel-miscompile.patch b/main/gcc/50_all_pr45312-kernel-miscompile.patch
new file mode 100644
index 0000000000..b9b1a7d7f0
--- /dev/null
+++ b/main/gcc/50_all_pr45312-kernel-miscompile.patch
@@ -0,0 +1,181 @@
+GCC 4.4.4 miscompiles the Linux kernel
+http://gcc.gnu.org/PR45312
+https://bugzilla.kernel.org/show_bug.cgi?id=16612
+https://bugs.gentoo.org/334269
+
+--- a/gcc/reload1.c
++++ b/gcc/reload1.c
+@@ -431,7 +431,6 @@ static void failed_reload (rtx, int);
+ static int set_reload_reg (int, int);
+ static void choose_reload_regs_init (struct insn_chain *, rtx *);
+ static void choose_reload_regs (struct insn_chain *);
+-static void merge_assigned_reloads (rtx);
+ static void emit_input_reload_insns (struct insn_chain *, struct reload *,
+ rtx, int);
+ static void emit_output_reload_insns (struct insn_chain *, struct reload *,
+@@ -4215,12 +4214,6 @@ reload_as_needed (int live_known)
+ Record the choices of reload reg in reload_reg_rtx. */
+ choose_reload_regs (chain);
+
+- /* Merge any reloads that we didn't combine for fear of
+- increasing the number of spill registers needed but now
+- discover can be safely merged. */
+- if (SMALL_REGISTER_CLASSES)
+- merge_assigned_reloads (insn);
+-
+ /* Generate the insns to reload operands into or out of
+ their reload regs. */
+ emit_reload_insns (chain);
+@@ -6598,152 +6591,6 @@ deallocate_reload_reg (int r)
+ reload_spill_index[r] = -1;
+ }
+
+-/* If SMALL_REGISTER_CLASSES is nonzero, we may not have merged two
+- reloads of the same item for fear that we might not have enough reload
+- registers. However, normally they will get the same reload register
+- and hence actually need not be loaded twice.
+-
+- Here we check for the most common case of this phenomenon: when we have
+- a number of reloads for the same object, each of which were allocated
+- the same reload_reg_rtx, that reload_reg_rtx is not used for any other
+- reload, and is not modified in the insn itself. If we find such,
+- merge all the reloads and set the resulting reload to RELOAD_OTHER.
+- This will not increase the number of spill registers needed and will
+- prevent redundant code. */
+-
+-static void
+-merge_assigned_reloads (rtx insn)
+-{
+- int i, j;
+-
+- /* Scan all the reloads looking for ones that only load values and
+- are not already RELOAD_OTHER and ones whose reload_reg_rtx are
+- assigned and not modified by INSN. */
+-
+- for (i = 0; i < n_reloads; i++)
+- {
+- int conflicting_input = 0;
+- int max_input_address_opnum = -1;
+- int min_conflicting_input_opnum = MAX_RECOG_OPERANDS;
+-
+- if (rld[i].in == 0 || rld[i].when_needed == RELOAD_OTHER
+- || rld[i].out != 0 || rld[i].reg_rtx == 0
+- || reg_set_p (rld[i].reg_rtx, insn))
+- continue;
+-
+- /* Look at all other reloads. Ensure that the only use of this
+- reload_reg_rtx is in a reload that just loads the same value
+- as we do. Note that any secondary reloads must be of the identical
+- class since the values, modes, and result registers are the
+- same, so we need not do anything with any secondary reloads. */
+-
+- for (j = 0; j < n_reloads; j++)
+- {
+- if (i == j || rld[j].reg_rtx == 0
+- || ! reg_overlap_mentioned_p (rld[j].reg_rtx,
+- rld[i].reg_rtx))
+- continue;
+-
+- if (rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+- && rld[j].opnum > max_input_address_opnum)
+- max_input_address_opnum = rld[j].opnum;
+-
+- /* If the reload regs aren't exactly the same (e.g, different modes)
+- or if the values are different, we can't merge this reload.
+- But if it is an input reload, we might still merge
+- RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_OTHER_ADDRESS reloads. */
+-
+- if (! rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx)
+- || rld[j].out != 0 || rld[j].in == 0
+- || ! rtx_equal_p (rld[i].in, rld[j].in))
+- {
+- if (rld[j].when_needed != RELOAD_FOR_INPUT
+- || ((rld[i].when_needed != RELOAD_FOR_INPUT_ADDRESS
+- || rld[i].opnum > rld[j].opnum)
+- && rld[i].when_needed != RELOAD_FOR_OTHER_ADDRESS))
+- break;
+- conflicting_input = 1;
+- if (min_conflicting_input_opnum > rld[j].opnum)
+- min_conflicting_input_opnum = rld[j].opnum;
+- }
+- }
+-
+- /* If all is OK, merge the reloads. Only set this to RELOAD_OTHER if
+- we, in fact, found any matching reloads. */
+-
+- if (j == n_reloads
+- && max_input_address_opnum <= min_conflicting_input_opnum)
+- {
+- gcc_assert (rld[i].when_needed != RELOAD_FOR_OUTPUT);
+-
+- for (j = 0; j < n_reloads; j++)
+- if (i != j && rld[j].reg_rtx != 0
+- && rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx)
+- && (! conflicting_input
+- || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+- || rld[j].when_needed == RELOAD_FOR_OTHER_ADDRESS))
+- {
+- rld[i].when_needed = RELOAD_OTHER;
+- rld[j].in = 0;
+- reload_spill_index[j] = -1;
+- transfer_replacements (i, j);
+- }
+-
+- /* If this is now RELOAD_OTHER, look for any reloads that
+- load parts of this operand and set them to
+- RELOAD_FOR_OTHER_ADDRESS if they were for inputs,
+- RELOAD_OTHER for outputs. Note that this test is
+- equivalent to looking for reloads for this operand
+- number.
+-
+- We must take special care with RELOAD_FOR_OUTPUT_ADDRESS;
+- it may share registers with a RELOAD_FOR_INPUT, so we can
+- not change it to RELOAD_FOR_OTHER_ADDRESS. We should
+- never need to, since we do not modify RELOAD_FOR_OUTPUT.
+-
+- It is possible that the RELOAD_FOR_OPERAND_ADDRESS
+- instruction is assigned the same register as the earlier
+- RELOAD_FOR_OTHER_ADDRESS instruction. Merging these two
+- instructions will cause the RELOAD_FOR_OTHER_ADDRESS
+- instruction to be deleted later on. */
+-
+- if (rld[i].when_needed == RELOAD_OTHER)
+- for (j = 0; j < n_reloads; j++)
+- if (rld[j].in != 0
+- && rld[j].when_needed != RELOAD_OTHER
+- && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS
+- && rld[j].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
+- && rld[j].when_needed != RELOAD_FOR_OPERAND_ADDRESS
+- && (! conflicting_input
+- || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+- || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
+- && reg_overlap_mentioned_for_reload_p (rld[j].in,
+- rld[i].in))
+- {
+- int k;
+-
+- rld[j].when_needed
+- = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+- || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
+- ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
+-
+- /* Check to see if we accidentally converted two
+- reloads that use the same reload register with
+- different inputs to the same type. If so, the
+- resulting code won't work. */
+- if (rld[j].reg_rtx)
+- for (k = 0; k < j; k++)
+- gcc_assert (rld[k].in == 0 || rld[k].reg_rtx == 0
+- || rld[k].when_needed != rld[j].when_needed
+- || !rtx_equal_p (rld[k].reg_rtx,
+- rld[j].reg_rtx)
+- || rtx_equal_p (rld[k].in,
+- rld[j].in));
+- }
+- }
+- }
+-}
+-
+ /* These arrays are filled by emit_reload_insns and its subroutines. */
+ static rtx input_reload_insns[MAX_RECOG_OPERANDS];
+ static rtx other_input_address_reload_insns = 0;
diff --git a/main/gcc/51_all_gcc-3.4-libiberty-pic.patch b/main/gcc/51_all_gcc-3.4-libiberty-pic.patch
new file mode 100644
index 0000000000..d9a95a21b1
--- /dev/null
+++ b/main/gcc/51_all_gcc-3.4-libiberty-pic.patch
@@ -0,0 +1,10 @@
+--- gcc-4.1.0-orig/libiberty/Makefile.in 2006-03-01 15:49:14.000000000 -0500
++++ gcc-4.1.0/libiberty/Makefile.in 2006-03-01 18:10:46.000000000 -0500
+@@ -232,6 +232,7 @@
+ $(AR) $(AR_FLAGS) $(TARGETLIB) \
+ $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS); \
+ $(RANLIB) $(TARGETLIB); \
++ cp $(TARGETLIB) ../ ; \
+ cd ..; \
+ else true; fi
+
diff --git a/main/gcc/APKBUILD b/main/gcc/APKBUILD
new file mode 100644
index 0000000000..1c2c0d72f1
--- /dev/null
+++ b/main/gcc/APKBUILD
@@ -0,0 +1,317 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gcc
+pkgver=4.5.3
+_piepatchver=0.4.5
+_specs_ver=0.2.0
+_specs_gcc_ver=4.4.3
+
+_uclibc_abiver=0.9.32
+
+pkgrel=0
+pkgdesc="The GNU Compiler Collection"
+url="http://gcc.gnu.org"
+arch="all"
+license="GPL LGPL"
+depends="binutils libgcc libgomp libobjc"
+makedepends="bison flex gmp-dev mpfr-dev texinfo libmpc-dev gawk zlib-dev zip"
+subpackages="$pkgname-doc libstdc++:libcxx g++:gpp libgcc libgomp"
+replaces="libstdc++"
+
+if [ "$LANG_OBJC" != "off" ]; then
+ subpackages="$subpackages libobjc"
+fi
+if [ "$LANG_JAVA" != "off" ]; then
+ subpackages="$subpackages $pkgname-java libgcj"
+fi
+
+source="ftp://gcc.gnu.org/pub/gcc/releases/gcc-$pkgver/gcc-core-$pkgver.tar.bz2
+ ftp://gcc.gnu.org/pub/gcc/releases/gcc-$pkgver/gcc-g++-$pkgver.tar.bz2
+ ftp://gcc.gnu.org/pub/gcc/releases/gcc-$pkgver/gcc-objc-$pkgver.tar.bz2
+ ftp://gcc.gnu.org/pub/gcc/releases/gcc-$pkgver/gcc-java-$pkgver.tar.bz2
+ http://distfiles.gentoo.org/distfiles/gcc-4.5.1-piepatches-v${_piepatchver}.tar.bz2
+ http://distfiles.gentoo.org/distfiles/gcc-$_specs_gcc_ver-specs-$_specs_ver.tar.bz2
+ ftp://sourceware.org/pub/java/ecj-latest.jar
+
+ 09_all_gcc-4.5-Wtrampolines.patch
+ 15_all_gcc-libgomp-no-werror.patch
+ 51_all_gcc-3.4-libiberty-pic.patch
+
+ gcc-spec-env.patch
+ pt_gnu_eh_frame.patch
+ uclibc-getipinfo.patch
+ gcc-4.5-dynamic-linker.patch
+ PR32219.patch
+ boehem-gc-uclibc.patch
+ gcc-pure64.patch
+ "
+
+# we build out-of-tree
+_gccdir="$srcdir"/gcc-$pkgver
+_builddir="$srcdir/build"
+
+prepare() {
+ cd "$_gccdir"
+ # verify we have set CHOST
+ if [ -z "$CHOST" ]; then
+ error "CHOST not set"
+ return 1
+ fi
+
+ # PIE patches from gentoo
+ # thanks to Zorry for hard work on those patches
+ for i in "$srcdir"/piepatch/*.patch; do
+ msg "Applying $i"
+ patch -p0 -i $i || return 1
+ done
+
+ # Gentoo and uclibc patches
+ for i in $source; do
+ case "$i" in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+
+ #PR33200
+ sed -i 's/use_fixproto=yes/:/' gcc/config.gcc || return 1
+
+ # enable hardened cflags by default
+ # building gcc wih PIE seem to hit some strange bug. we probably run
+ # out of some resource. so we disable PIE for gcc while enabling it
+ # by default for everything else.
+ local _hard_cflags="-DEFAULT_PIE_SSP -DEFAULT_RELRO -DEFAULT_BIND_NOW"
+ sed -e "/^ALL_CFLAGS/iHARD_CFLAGS = ${_hard_cflags}" \
+ -e 's|^ALL_CFLAGS = |ALL_CFLAGS = $(HARD_CFLAGS) -fno-PIE |' \
+ -i gcc/Makefile.in || return 1
+ sed -e "/stage1_cflags=/s/-fno-stack-protector/-fno-stack-protector -fno-PIE/" \
+ -i configure
+
+ # see http://gcc.gnu.org/ml/java/2008-04/msg00027.html
+ mv "$srcdir"/ecj-latest.jar ecj.jar
+
+ echo ${pkgver} > gcc/BASE-VER
+}
+
+build() {
+ local _languages= _dynamic_linker=
+ cd "$_gccdir"
+ export CFLAGS="-fno-stack-protector"
+ [ -z "$CBUILD" ] && CBUILD="$CHOST"
+ [ -z "$CTARGET" ] && CTARGET="$CHOST"
+
+ case "$CHOST" in
+ x86_64-*-uclibc)
+ _dynamic_linker="--with-dynamic-linker=ld64-uClibc.so.$_uclibc_abiver"
+ ;;
+ *-uclibc)
+ _dynamic_linker="--with-dynamic-linker=ld-uClibc.so.$_uclibc_abiver"
+ ;;
+ *) _dynamic_linker=
+ ;;
+ esac
+
+ _languages=c,c++
+ # we can disable OBJC with LANG_OBJC=off
+ if [ "$LANG_OBJC" != "off" ]; then
+ _languages=$_languages,objc
+ fi
+
+ # and disable java with LANG_JAVA=off
+ if [ "$LANG_JAVA" != "off" ]; then
+ _languages="$_languages,java"
+ fi
+
+ # --enable-target-optspace is broken on powerpc
+ if [ "$CARCH" != "powerpc" ]; then
+ _target_optspace="--enable-target-optspace"
+ fi
+
+ msg "Building the following:"
+ echo ""
+ echo " CBUILD=$CBUILD"
+ echo " CHOST=$CHOST"
+ echo " CTARGET=$CTARGET"
+ echo " languages=$_languages"
+ echo " dynamic_linker=$_dynamic_linker"
+ echo " target_optspace=$_target_optspace"
+ echo ""
+
+ mkdir -p "$_builddir"
+ cd "$_builddir"
+ "$_gccdir"/configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --build=${CBUILD} \
+ --host=${CHOST} \
+ --target=${CTARGET} \
+ --with-pkgversion='Alpine' \
+ --disable-altivec \
+ --disable-checking \
+ --disable-fixed-point \
+ --disable-libssp \
+ --disable-libstdcxx-pch \
+ --disable-multilib \
+ --disable-nls \
+ --disable-werror \
+ --enable-__cxa_atexit \
+ --enable-cld \
+ --enable-esp \
+ --enable-languages=$_languages \
+ --enable-shared \
+ $_target_optspace \
+ --enable-tls \
+ --enable-threads \
+ $_dynamic_linker \
+ --with-dynamic-linker-prefix=/lib \
+ --with-system-zlib \
+ --without-system-libunwind
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="${pkgdir}" install || return 1
+ ln -s gcc "$pkgdir"/usr/bin/cc
+
+ # binutils provides libiberty.a
+ rm -f "$pkgdir"/usr/lib/libiberty.a
+
+ # install the specs
+ cd "$srcdir"/specs
+ install -d "$pkgdir"/usr/share/gcc
+ for i in *.specs; do
+ install -m644 $i "$pkgdir"/usr/share/gcc/$i || return 1
+ done
+
+ # we dont support gcj -static
+ # and saving 35MB is not bad.
+ find "$pkgdir" -name libgcj.a -o -name libgtkpeer.a \
+ -o -name libgjsmalsa.a -o -name libgcj-tools.a \
+ -o -name libjvm.a -o -name libgij.a -o -name libgcj_bc.a \
+ -o -name libjavamath.a \
+ | xargs rm -f \
+ || return 1
+
+ [ "$LANG_JAVA" = "on" ] && \
+ sed -i -e 's/lib: /&%{static:%eJava programs cannot be linked statically}/' \
+ "$pkdir"/usr/lib/libgcj.spec
+
+ # remove ffi
+ rm "$pkgdir"/usr/lib/libffi*
+ find "$pkgdir" -name 'ffi*.h' | xargs rm -f
+
+ mkdir -p "$pkgdir"/usr/share/gdb/python/auto-load/usr/lib
+ mv "$pkgdir"/usr/lib/*-gdb.py \
+ "$pkgdir"/usr/share/gdb/python/auto-load/usr/lib/
+}
+
+libcxx() {
+ pkgdesc="GNU C++ standard runtime library"
+ depends=
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libstdc++.so.* "$subpkgdir"/usr/lib/
+}
+
+gpp() {
+ pkgdesc="GNU C++ standard library and compiler"
+ depends="libstdc++"
+ local libexec=usr/libexec/gcc/${CHOST:-$_chost}/$pkgver
+ mkdir -p "$subpkgdir/$libexec" \
+ "$subpkgdir"/usr/bin \
+ "$subpkgdir"/usr/include \
+ "$subpkgdir"/usr/lib \
+
+ mv "$pkgdir/$libexec/cc1plus" "$subpkgdir/$libexec/"
+ mv "$pkgdir"/usr/lib/*++* "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/include/c++ "$subpkgdir"/usr/include/
+ mv "$pkgdir"/usr/bin/*++ "$subpkgdir"/usr/bin/
+}
+
+libobjc() {
+ pkgdesc="GNU ObjectiveC library"
+ replaces="objc"
+ mkdir -p "$subpkgdir"/usr/lib
+
+ mv "$pkgdir"/usr/lib/*objc* "$subpkgdir"/usr/lib/
+}
+
+libgcc() {
+ pkgdesc="GNU C compiler runtime libraries"
+ depends=
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libgcc_s.so.* "$subpkgdir"/usr/lib/
+}
+
+libgomp() {
+ pkgdesc="GCC shared-memory parallel programming API library"
+ depends=
+ replaces="gcc"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libgomp.so.* "$subpkgdir"/usr/lib/
+}
+
+java() {
+ pkgdesc="Java support for GCC"
+ mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/usr/lib
+ cd "$pkgdir"/usr/bin
+ mv gcj gcj-dbtool gjavah gcjh jcf-dump "$subpkgdir"/usr/bin/
+ cd "$pkgdir"
+ for i in $(find usr/ -name ecj1 -o -name jc1 -o -name jvgenmain); do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i || return 1
+ done
+ mv \
+ "$pkgdir"/usr/lib/libgcj*.so \
+ "$pkgdir"/usr/lib/libgcj*.la \
+ "$pkgdir"/usr/lib/libgij.so \
+ "$pkgdir"/usr/lib/libgij.la \
+ "$pkgdir"/usr/lib/libgcj.spec \
+ "$subpkgdir"/usr/lib/
+}
+
+libgcj() {
+ pkgdesc="Java runtime library for gcc"
+ mkdir -p "$subpkgdir"/usr/bin
+ cd "$pkgdir"/usr/bin
+ mv aot-compile gappletviewer gc-analyze gij gjar gjarsigner gkeytool\
+ gnative2ascii gorbd grmic grmid grmiregistry gserialver \
+ gtnameserv i486-alpine-linux-uclibc-gcj jv-convert \
+ rebuild-gcj-db \
+ "$subpkgdir"/usr/bin/
+ cd "$pkgdir"
+ for i in $(find usr/lib -name jc1 -o -name jvgenmain); do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i || return 1
+ done
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/gcj-* \
+ "$pkgdir"/usr/lib/libgcj*.so.* \
+ "$pkgdir"/usr/lib/libgij.so.* \
+ "$pkgdir"/usr/lib/logging.properties \
+ "$pkgdir"/usr/lib/security \
+ "$subpkgdir"/usr/lib/
+
+ mkdir -p "$subpkgdir"/usr/share/
+ mv "$pkgdir"/usr/share/java "$subpkgdir"/usr/share/
+}
+
+md5sums="98be5094b5b5a7b9087494291bc7f522 gcc-core-4.5.3.tar.bz2
+2c78bf1d5f08a0b116f280de88d3ffe7 gcc-g++-4.5.3.tar.bz2
+9bb53e37e589515ba55979a19be9c036 gcc-objc-4.5.3.tar.bz2
+08e045fdbdc22ac9af3aec3b8d16dbab gcc-java-4.5.3.tar.bz2
+1f86fe5dc7d506b7fc04fcd8b7d2693c gcc-4.5.1-piepatches-v0.4.5.tar.bz2
+441c76504e1d97170117c294e65c7a72 gcc-4.4.3-specs-0.2.0.tar.bz2
+d7cd6a27c8801e66cbaa964a039ecfdb ecj-latest.jar
+ab090760506eb70aa4436a349c6bd788 09_all_gcc-4.5-Wtrampolines.patch
+1c00bd9d12891a3e2311b32b98deb6fa 15_all_gcc-libgomp-no-werror.patch
+45951dd3bbc979c9e043c7203745cf31 51_all_gcc-3.4-libiberty-pic.patch
+c4045bfa85d8be780affd465be9d8ca8 gcc-spec-env.patch
+2db1e3482c5dd59dab70f701afa2ca80 pt_gnu_eh_frame.patch
+6cc2385c5bbd6d0da6eaedd53c8bf547 uclibc-getipinfo.patch
+7f35da0f88f4d9c3d3839498bbda0eb3 gcc-4.5-dynamic-linker.patch
+6c866c7fb8d56deb8f6d652bee64e228 PR32219.patch
+2c6cb49bb9bfd8b6e690222e66ccc901 boehem-gc-uclibc.patch
+d1d3ad2b0c185b5548125a1b81bee154 gcc-pure64.patch"
diff --git a/main/gcc/PR32219.patch b/main/gcc/PR32219.patch
new file mode 100644
index 0000000000..b926e941fc
--- /dev/null
+++ b/main/gcc/PR32219.patch
@@ -0,0 +1,101 @@
+From gcc-patches-return-258497-listarch-gcc-patches=gcc dot gnu dot org at gcc dot gnu dot org Tue Mar 16 13:32:55 2010
+Return-Path: <gcc-patches-return-258497-listarch-gcc-patches=gcc dot gnu dot org at gcc dot gnu dot org>
+Delivered-To: listarch-gcc-patches at gcc dot gnu dot org
+Received: (qmail 25550 invoked by alias); 16 Mar 2010 13:32:54 -0000
+Received: (qmail 25534 invoked by uid 22791); 16 Mar 2010 13:32:53 -0000
+X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL,BAYES_00,SUBJ_ALL_CAPS
+X-Spam-Check-By: sourceware.org
+Received: from mail-bw0-f210.google.com (HELO mail-bw0-f210.google.com) (209.85.218.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 16 Mar 2010 13:32:48 +0000
+Received: by bwz2 with SMTP id 2so4002140bwz.30 for <multiple recipients>; Tue, 16 Mar 2010 06:32:45 -0700 (PDT)
+Received: by 10.204.14.84 with SMTP id f20mr2900449bka.209.1268746365293; Tue, 16 Mar 2010 06:32:45 -0700 (PDT)
+Received: from s42.loc (85-127-85-230.dynamic.xdsl-line.inode.at [85.127.85.230]) by mx.google.com with ESMTPS id 14sm3626793bwz.14.2010.03.16.06.32.43 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 16 Mar 2010 06:32:44 -0700 (PDT)
+Received: from cow by s42.loc with local (Exim 4.71) (envelope-from <rep.dot.nop@gmail.com>) id 1NrX2W-0008Nj-5o; Tue, 16 Mar 2010 14:42:32 +0100
+From: Bernhard Reutner-Fischer <rep dot dot dot nop at gmail dot com>
+To: gcc-patches at gcc dot gnu dot org
+Cc: rguenth at gcc dot gnu dot org, Bernhard Reutner-Fischer <rep dot dot dot nop at gmail dot com>
+Subject: [PATCH] PR32219
+Date: Tue, 16 Mar 2010 14:42:27 +0100
+Message-Id: <1268746947-32108-1-git-send-email-rep.dot.nop@gmail.com>
+Mailing-List: contact gcc-patches-help at gcc dot gnu dot org; run by ezmlm
+Precedence: bulk
+List-Id: <gcc-patches.gcc.gnu.org>
+List-Archive: <http://gcc.gnu.org/ml/gcc-patches/>
+List-Post: <mailto:gcc-patches at gcc dot gnu dot org>
+List-Help: <mailto:gcc-patches-help at gcc dot gnu dot org>
+Sender: gcc-patches-owner at gcc dot gnu dot org
+Delivered-To: mailing list gcc-patches at gcc dot gnu dot org
+
+Hi,
+
+As suggested by richi.
+regtested on i686-linux-gnu with all default languages and no regressions.
+Ok for trunk?
+
+gcc/ChangeLog
+2010-03-15 Bernhard Reutner-Fischer <aldot@gcc.gnu.org>
+
+ PR target/32219
+ * varasm.c (default_binds_local_p_1): Weak data is not local.
+
+gcc/testsuite/ChangeLog
+2010-03-15 Bernhard Reutner-Fischer <aldot@gcc.gnu.org>
+
+ PR target/32219
+ * gcc.dg/visibility-21.c: New test.
+
+Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
+---
+ gcc/testsuite/gcc.dg/visibility-21.c | 14 ++++++++++++++
+ gcc/varasm.c | 8 ++++----
+ 2 files changed, 18 insertions(+), 4 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/visibility-21.c
+
+diff --git a/gcc/testsuite/gcc.dg/visibility-21.c b/gcc/testsuite/gcc.dg/visibility-21.c
+new file mode 100644
+index 0000000..be7deda
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/visibility-21.c
+@@ -0,0 +1,14 @@
++/* PR target/32219 */
++/* { dg-do run } */
++/* { dg-require-visibility "" } */
++/* { dg-options "-fPIC" { target fpic } } */
++
++extern void f() __attribute__((weak,visibility("hidden")));
++extern int puts( char const* );
++int main()
++{
++ if (f)
++ f();
++ return 0;
++}
++
+diff --git a/gcc/varasm.c b/gcc/varasm.c
+index 6b8222f..6b9269a 100644
+--- a/gcc/varasm.c
++++ b/gcc/varasm.c
+@@ -6613,6 +6613,10 @@ default_binds_local_p_1 (const_tree exp, int shlib)
+ /* Static variables are always local. */
+ else if (! TREE_PUBLIC (exp))
+ local_p = true;
++ /* Weak data can be overridden by a strong symbol
++ in another module and so are not local. */
++ else if (DECL_WEAK (exp))
++ local_p = false;
+ /* A variable is local if the user has said explicitly that it will
+ be. */
+ else if (DECL_VISIBILITY_SPECIFIED (exp)
+@@ -6625,10 +6629,6 @@ default_binds_local_p_1 (const_tree exp, int shlib)
+ local. */
+ else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+ local_p = true;
+- /* Default visibility weak data can be overridden by a strong symbol
+- in another module and so are not local. */
+- else if (DECL_WEAK (exp))
+- local_p = false;
+ /* If PIC, then assume that any global name can be overridden by
+ symbols resolved from other modules, unless we are compiling with
+ -fwhole-program, which assumes that names are local. */
+--
+1.7.0
+
diff --git a/main/gcc/boehem-gc-uclibc.patch b/main/gcc/boehem-gc-uclibc.patch
new file mode 100644
index 0000000000..0fa6884105
--- /dev/null
+++ b/main/gcc/boehem-gc-uclibc.patch
@@ -0,0 +1,11 @@
+--- ./boehm-gc/include/gc.h.orig
++++ ./boehm-gc/include/gc.h
+@@ -503,7 +503,7 @@
+ #if defined(__linux__) || defined(__GLIBC__)
+ # include <features.h>
+ # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
+- && !defined(__ia64__)
++ && !defined(__ia64__) && !defined(__UCLIBC__)
+ # ifndef GC_HAVE_BUILTIN_BACKTRACE
+ # define GC_HAVE_BUILTIN_BACKTRACE
+ # endif
diff --git a/main/gcc/gcc-4.5-dynamic-linker.patch b/main/gcc/gcc-4.5-dynamic-linker.patch
new file mode 100644
index 0000000000..a11c7f934e
--- /dev/null
+++ b/main/gcc/gcc-4.5-dynamic-linker.patch
@@ -0,0 +1,457 @@
+commit d929f627aba264e63cf779cd4ca51af97b076445
+Author: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue Sep 28 09:45:17 2010 +0000
+
+ Submitted By: Kevin Day <thekevinday AT gmail DOT com>
+ Date: 2008-12-19
+ Initial Package Version: 4.3.2
+ Upstream Status: Not submitted
+ Description: Why not just be able to define the prefix of the dynamic linker instead of hardcoding it..
+ This includes the --nostdinc patch as well, so think of this as a specs-3 patch
+ This also allows for specifying the dynamic-linker as well
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index ae2416b..b0b9b2c 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -971,7 +971,7 @@ INTERNAL_CFLAGS = -DIN_GCC @CROSS@
+ # This is the variable actually used when we compile. If you change this,
+ # you probably want to update BUILD_CFLAGS in configure.ac
+ ALL_CFLAGS = $(T_CFLAGS) \
+- $(CFLAGS) $(INTERNAL_CFLAGS) $(COVERAGE_FLAGS) $(WARN_CFLAGS) @DEFS@
++ $(CFLAGS) $(INTERNAL_CFLAGS) $(COVERAGE_FLAGS) $(WARN_CFLAGS) @DEFS@ @NOSTDINC@
+
+ # The C++ version.
+ ALL_CXXFLAGS = $(T_CFLAGS) $(CXXFLAGS) $(INTERNAL_CFLAGS) \
+@@ -2105,6 +2105,8 @@ DRIVER_DEFINES = \
+ -DSTANDARD_STARTFILE_PREFIX=\"$(unlibsubdir)/\" \
+ -DSTANDARD_EXEC_PREFIX=\"$(libdir)/gcc/\" \
+ -DSTANDARD_LIBEXEC_PREFIX=\"$(libexecdir)/gcc/\" \
++ -DDYNAMIC_LINKER_PREFIX=\"@DYNAMICLINKERPREFIX@\" \
++ -DDYNAMIC_LINKER=\"@DYNAMICLINKER@\" \
+ -DDEFAULT_TARGET_VERSION=\"$(version)\" \
+ -DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" \
+ -DSTANDARD_BINDIR_PREFIX=\"$(bindir)/\" \
+diff --git a/gcc/config/alpha/gnu.h b/gcc/config/alpha/gnu.h
+index f98c3e7..bd16dcf 100644
+--- a/gcc/config/alpha/gnu.h
++++ b/gcc/config/alpha/gnu.h
+@@ -34,7 +34,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ } while (0)
+
+ #undef ELF_DYNAMIC_LINKER
+-#define ELF_DYNAMIC_LINKER "/lib/ld.so"
++#define ELF_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef STARTFILE_SPEC
+ #define STARTFILE_SPEC \
+diff --git a/gcc/config/alpha/linux-elf.h b/gcc/config/alpha/linux-elf.h
+index c48fc93..3068717 100644
+--- a/gcc/config/alpha/linux-elf.h
++++ b/gcc/config/alpha/linux-elf.h
+@@ -27,8 +27,8 @@ along with GCC; see the file COPYING3. If not see
+ #define EXTRA_SPECS \
+ { "elf_dynamic_linker", ELF_DYNAMIC_LINKER },
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+-#define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define UCLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+ #if UCLIBC_DEFAULT
+ #define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:%{muclibc:%e-mglibc and -muclibc used together}" G ";:" U "}"
+ #else
+diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h
+index fce1ed1..c3bcd50 100644
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -61,7 +61,7 @@
+ /* Use ld-linux.so.3 so that it will be possible to run "classic"
+ GNU/Linux binaries on an EABI system. */
+ #undef GLIBC_DYNAMIC_LINKER
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.3"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ /* At this point, bpabi.h will have clobbered LINK_SPEC. We want to
+ use the GNU/Linux version, not the generic BPABI version. */
+diff --git a/gcc/config/arm/linux-elf.h b/gcc/config/arm/linux-elf.h
+index 9fdca41..65b0a5a 100644
+--- a/gcc/config/arm/linux-elf.h
++++ b/gcc/config/arm/linux-elf.h
+@@ -62,7 +62,7 @@
+
+ #define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc"
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #define LINUX_TARGET_LINK_SPEC "%{h*} %{version:-v} \
+ %{b} \
+diff --git a/gcc/config/bfin/linux.h b/gcc/config/bfin/linux.h
+index 5c716cd..b5e464e 100644
+--- a/gcc/config/bfin/linux.h
++++ b/gcc/config/bfin/linux.h
+@@ -45,7 +45,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ %{shared:-G -Bdynamic} \
+ %{!shared: %{!static: \
+ %{rdynamic:-export-dynamic} \
+- %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++ %{!dynamic-linker:-dynamic-linker DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER}} \
+ %{static}} -init __init -fini __fini"
+
+ #define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h"
+diff --git a/gcc/config/cris/linux.h b/gcc/config/cris/linux.h
+index 38f0a7e..6893407 100644
+--- a/gcc/config/cris/linux.h
++++ b/gcc/config/cris/linux.h
+@@ -103,7 +103,7 @@ along with GCC; see the file COPYING3. If not see
+ #undef CRIS_DEFAULT_CPU_VERSION
+ #define CRIS_DEFAULT_CPU_VERSION CRIS_CPU_NG
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ /* We need an -rpath-link to ld.so.1, and presumably to each directory
+ specified with -B. */
+diff --git a/gcc/config/freebsd-spec.h b/gcc/config/freebsd-spec.h
+index 84d8127..fb3e79a 100644
+--- a/gcc/config/freebsd-spec.h
++++ b/gcc/config/freebsd-spec.h
+@@ -144,9 +144,9 @@ is built with the --enable-threads configure-time option.} \
+ #endif
+
+ #if FBSD_MAJOR < 6
+-#define FBSD_DYNAMIC_LINKER "/usr/libexec/ld-elf.so.1"
++#define FBSD_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+ #else
+-#define FBSD_DYNAMIC_LINKER "/libexec/ld-elf.so.1"
++#define FBSD_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+ #endif
+
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+diff --git a/gcc/config/frv/linux.h b/gcc/config/frv/linux.h
+index 71cd094..221d01d 100644
+--- a/gcc/config/frv/linux.h
++++ b/gcc/config/frv/linux.h
+@@ -35,7 +35,7 @@
+ #define ENDFILE_SPEC \
+ "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef LINK_SPEC
+ #define LINK_SPEC "\
+diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h
+index 2a31880..9c08adb 100644
+--- a/gcc/config/i386/linux.h
++++ b/gcc/config/i386/linux.h
+@@ -100,7 +100,7 @@ along with GCC; see the file COPYING3. If not see
+
+ /* These macros may be overridden in k*bsd-gnu.h and i386/k*bsd-gnu.h. */
+ #define LINK_EMULATION "elf_i386"
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef ASM_SPEC
+ #define ASM_SPEC \
+diff --git a/gcc/config/i386/linux64.h b/gcc/config/i386/linux64.h
+index 867de59..274acca 100644
+--- a/gcc/config/i386/linux64.h
++++ b/gcc/config/i386/linux64.h
+@@ -58,8 +58,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ When the -shared link option is used a final link is not being
+ done. */
+
+-#define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2"
+-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux-x86-64.so.2"
++#define GLIBC_DYNAMIC_LINKER32 "/" DYNAMIC_LINKER
++#define GLIBC_DYNAMIC_LINKER64 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #if TARGET_64BIT_DEFAULT
+ #define SPEC_32 "m32"
+diff --git a/gcc/config/ia64/linux.h b/gcc/config/ia64/linux.h
+index 587a4f4..450fcb5 100644
+--- a/gcc/config/ia64/linux.h
++++ b/gcc/config/ia64/linux.h
+@@ -61,7 +61,7 @@ do { \
+ /* Define this for shared library support because it isn't in the main
+ linux.h file. */
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-ia64.so.2"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef LINK_SPEC
+ #define LINK_SPEC "\
+diff --git a/gcc/config/knetbsd-gnu.h b/gcc/config/knetbsd-gnu.h
+index 4cc8eb7..bb7a063 100644
+--- a/gcc/config/knetbsd-gnu.h
++++ b/gcc/config/knetbsd-gnu.h
+@@ -34,5 +34,5 @@ along with GCC; see the file COPYING3. If not see
+
+ #ifdef GLIBC_DYNAMIC_LINKER
+ #undef GLIBC_DYNAMIC_LINKER
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+ #endif
+diff --git a/gcc/config/linux.h b/gcc/config/linux.h
+index e567e9a..c052fd0 100644
+--- a/gcc/config/linux.h
++++ b/gcc/config/linux.h
+@@ -117,9 +117,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ GLIBC_DYNAMIC_LINKER must be defined for each target using them, or
+ GLIBC_DYNAMIC_LINKER32 and GLIBC_DYNAMIC_LINKER64 for targets
+ supporting both 32-bit and 64-bit compilation. */
+-#define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
+-#define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
+-#define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
++#define UCLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define UCLIBC_DYNAMIC_LINKER32 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define UCLIBC_DYNAMIC_LINKER64 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+ #define LINUX_DYNAMIC_LINKER \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER)
+ #define LINUX_DYNAMIC_LINKER32 \
+@@ -135,3 +135,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ #define TARGET_HAS_SINCOS (OPTION_GLIBC)
+
+ #define TARGET_POSIX_IO
++
++#ifdef NOSTDINC
++#undef STANDARD_INCLUDE_DIR
++#define STANDARD_INCLUDE_DIR 0
++#endif
+diff --git a/gcc/config/m32r/linux.h b/gcc/config/m32r/linux.h
+index 0515e5b..019e850 100644
+--- a/gcc/config/m32r/linux.h
++++ b/gcc/config/m32r/linux.h
+@@ -58,7 +58,7 @@
+
+ /* If ELF is the default format, we should not use /lib/elf. */
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef LINK_SPEC
+ #if TARGET_LITTLE_ENDIAN
+diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h
+index 1d73ee0..e57cf50 100644
+--- a/gcc/config/m68k/linux.h
++++ b/gcc/config/m68k/linux.h
+@@ -84,7 +84,7 @@ along with GCC; see the file COPYING3. If not see
+
+ /* If ELF is the default format, we should not use /lib/elf. */
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef LINK_SPEC
+ #define LINK_SPEC "-m m68kelf %{shared} \
+diff --git a/gcc/config/mips/linux.h b/gcc/config/mips/linux.h
+index 0512ef7..7efe2fd 100644
+--- a/gcc/config/mips/linux.h
++++ b/gcc/config/mips/linux.h
+@@ -64,7 +64,7 @@ along with GCC; see the file COPYING3. If not see
+ #undef MIPS_DEFAULT_GVALUE
+ #define MIPS_DEFAULT_GVALUE 0
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ /* Borrowed from sparc/linux.h */
+ #undef LINK_SPEC
+diff --git a/gcc/config/mips/linux64.h b/gcc/config/mips/linux64.h
+index 2f24dfa..850cb22 100644
+--- a/gcc/config/mips/linux64.h
++++ b/gcc/config/mips/linux64.h
+@@ -35,10 +35,10 @@ along with GCC; see the file COPYING3. If not see
+ %{!shared: \
+ %{profile:-lc_p} %{!profile:-lc}}"
+
+-#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
+-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld.so.1"
+-#define GLIBC_DYNAMIC_LINKERN32 "/lib32/ld.so.1"
+-#define UCLIBC_DYNAMIC_LINKERN32 "/lib32/ld-uClibc.so.0"
++#define GLIBC_DYNAMIC_LINKER32 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define GLIBC_DYNAMIC_LINKER64 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define GLIBC_DYNAMIC_LINKERN32 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define UCLIBC_DYNAMIC_LINKERN32 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+ #define LINUX_DYNAMIC_LINKERN32 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32)
+
+diff --git a/gcc/config/mn10300/linux.h b/gcc/config/mn10300/linux.h
+index ac9f8c5..8ab78b1 100644
+--- a/gcc/config/mn10300/linux.h
++++ b/gcc/config/mn10300/linux.h
+@@ -32,7 +32,7 @@
+ #undef ASM_SPEC
+ #define ASM_SPEC "%{Wa,*:%*}"
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef LINK_SPEC
+ #define LINK_SPEC "%{mrelax:--relax} %{shared:-shared} \
+diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
+index da7bca3..c36e7d6 100644
+--- a/gcc/config/rs6000/linux64.h
++++ b/gcc/config/rs6000/linux64.h
+@@ -348,10 +348,10 @@ extern int dot_symbols;
+ #undef LINK_OS_DEFAULT_SPEC
+ #define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
+
+-#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
+-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld64.so.1"
+-#define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
+-#define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
++#define GLIBC_DYNAMIC_LINKER32 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define GLIBC_DYNAMIC_LINKER64 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define UCLIBC_DYNAMIC_LINKER32 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define UCLIBC_DYNAMIC_LINKER64 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+ #if UCLIBC_DEFAULT
+ #define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:%{muclibc:%e-mglibc and -muclibc used together}" G ";:" U "}"
+ #else
+diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h
+index ddbcfa9..59bfd28 100644
+--- a/gcc/config/s390/linux.h
++++ b/gcc/config/s390/linux.h
+@@ -72,8 +72,8 @@ along with GCC; see the file COPYING3. If not see
+ #define MULTILIB_DEFAULTS { "m31" }
+ #endif
+
+-#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
+-#define GLIBC_DYNAMIC_LINKER64 "/lib/ld64.so.1"
++#define GLIBC_DYNAMIC_LINKER32 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define GLIBC_DYNAMIC_LINKER64 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef LINK_SPEC
+ #define LINK_SPEC \
+diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h
+index d513af8..2ad27a7 100644
+--- a/gcc/config/sh/linux.h
++++ b/gcc/config/sh/linux.h
+@@ -47,7 +47,7 @@ along with GCC; see the file COPYING3. If not see
+
+ #define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef SUBTARGET_LINK_EMUL_SUFFIX
+ #define SUBTARGET_LINK_EMUL_SUFFIX "_linux"
+diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h
+index b12c881..83bdd8e 100644
+--- a/gcc/config/sparc/linux.h
++++ b/gcc/config/sparc/linux.h
+@@ -83,7 +83,7 @@ along with GCC; see the file COPYING3. If not see
+
+ /* If ELF is the default format, we should not use /lib/elf. */
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef LINK_SPEC
+ #define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
+diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h
+index c2e78d7..8481a34 100644
+--- a/gcc/config/sparc/linux64.h
++++ b/gcc/config/sparc/linux64.h
+@@ -109,8 +109,8 @@ along with GCC; see the file COPYING3. If not see
+
+ /* If ELF is the default format, we should not use /lib/elf. */
+
+-#define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2"
+-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux.so.2"
++#define GLIBC_DYNAMIC_LINKER32 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
++#define GLIBC_DYNAMIC_LINKER64 DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #ifdef SPARC_BI_ARCH
+
+diff --git a/gcc/config/xtensa/linux.h b/gcc/config/xtensa/linux.h
+index 69ab626..ebc8e0b 100644
+--- a/gcc/config/xtensa/linux.h
++++ b/gcc/config/xtensa/linux.h
+@@ -43,7 +43,7 @@ along with GCC; see the file COPYING3. If not see
+ %{mlongcalls:--longcalls} \
+ %{mno-longcalls:--no-longcalls}"
+
+-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
++#define GLIBC_DYNAMIC_LINKER DYNAMIC_LINKER_PREFIX "/" DYNAMIC_LINKER
+
+ #undef LINK_SPEC
+ #define LINK_SPEC \
+diff --git a/gcc/configure b/gcc/configure
+index b623a4a..230719b 100755
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -757,6 +757,9 @@ AWK
+ SET_MAKE
+ REPORT_BUGS_TEXI
+ REPORT_BUGS_TO
++DYNAMICLINKER
++DYNAMICLINKERPREFIX
++NOSTDINC
+ PKGVERSION
+ onestep
+ CONFIGURE_SPECS
+@@ -1657,6 +1660,14 @@ Optional Packages:
+ --with-gc={page,zone} choose the garbage collection mechanism to use
+ with the compiler
+ --with-system-zlib use installed libz
++ --with-dynamic-linker=PATH
++ specifies path to dynamic linker.
++ example: "/lib/ld-linux.so.2", where this defines "ld-linux.so.2"
++ --with-dynamic-linker-prefix=PATH
++ specifies path to dynamic linker.
++ example: "/lib/ld-linux.so.2", where this defines "/lib"
++ --with-nostdinc build gcc to ignore standard include directories.
++ You will have to use --with-local-prefix with this option.
+ --with-slibdir=DIR shared libraries in DIR [LIBDIR]
+
+ Some influential environment variables:
+@@ -6065,6 +6076,47 @@ fi
+
+
+
++# Check whether --with-dynamic-linker was given.
++
++DYNAMICLINKER="ld-linux.so.2" ;
++if test "${with_dynamic_linker+set}" = set; then
++ withval="$with_dynamic_linker"
++ case "${withval}" in
++yes) { { echo "$as_me:$LINENO: error: bad value "${withval}". Use something like --with-dynamic-linker=$DYNAMICLINKER" >&5
++echo "$as_me: error: bad value "${withval}". Use something like --with-dynamic-linker=$DYNAMICLINKER" >&2;}
++ { (exit 1); exit 1; }; } ;;
++no) ;;
++*) DYNAMICLINKER=$withval ;;
++esac
++fi;
++
++# Check whether --with-dynamic-linker-prefix= was given.
++
++DYNAMICLINKERPREFIX="/lib" ;
++if test "${with_dynamic_linker_prefix+set}" = set; then
++ withval="$with_dynamic_linker_prefix"
++ case "${withval}" in
++yes) { { echo "$as_me:$LINENO: error: bad value "${withval}". Use --with-dynamic-linker-prefix=/path/to/lib/" >&5
++echo "$as_me: error: bad value "${withval}". Use --with-dynamic-linker-prefix=/path/to/lib/" >&2;}
++ { (exit 1); exit 1; }; } ;;
++no) ;;
++*) DYNAMICLINKERPREFIX=$withval ;;
++esac
++
++fi;
++
++# Check whether --with-nostdinc was given.
++
++if test "${with_nostdinc+set}" = set; then
++ withval="$with_nostdinc"
++ case "${withval}" in
++yes) NOSTDINC="-DNOSTDINC" ;;
++no) ;;
++*) NOSTDINC="-DNOSTDINC" ;;
++esac
++fi;
++
++
+
+ # ---------------------
+ # Warnings and checking
diff --git a/main/gcc/gcc-pure64.patch b/main/gcc/gcc-pure64.patch
new file mode 100644
index 0000000000..f9ab69326e
--- /dev/null
+++ b/main/gcc/gcc-pure64.patch
@@ -0,0 +1,12 @@
+diff -Naur gcc-4.2.0.orig/gcc/config/i386/t-linux64 gcc-4.2.0/gcc/config/i386/t-linux64
+--- gcc-4.2.0.orig/gcc/config/i386/t-linux64 2007-05-16 19:21:19.000000000 -0400
++++ gcc-4.2.0/gcc/config/i386/t-linux64 2007-05-18 17:04:36.000000000 -0400
+@@ -6,7 +6,7 @@
+
+ MULTILIB_OPTIONS = m64/m32
+ MULTILIB_DIRNAMES = 64 32
+-MULTILIB_OSDIRNAMES = ../lib64 $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)
++MULTILIB_OSDIRNAMES = ../lib ../lib32
+
+ LIBGCC = stmp-multilib
+ INSTALL_LIBGCC = install-multilib
diff --git a/main/gcc/gcc-spec-env.patch b/main/gcc/gcc-spec-env.patch
new file mode 100644
index 0000000000..9d5e666a54
--- /dev/null
+++ b/main/gcc/gcc-spec-env.patch
@@ -0,0 +1,41 @@
+ Add support for external spec file via the GCC_SPECS env var. This
+ allows us to easily control pie/ssp defaults with gcc-config profiles.
+
+ Original patch by Rob Holland. Extended to support multiple
+ entries separated by ':' by Kevin F. Quinn
+
+--- gcc-4/gcc/gcc.c
++++ gcc-4/gcc/gcc.c
+@@ -6482,6 +6482,32 @@
+
+ /* Process any user specified specs in the order given on the command
+ line. */
++#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS) || defined (WIN32))
++ /* Add specs listed in GCC_SPECS. Note; in the process of separating
++ * each spec listed, the string is overwritten at token boundaries
++ * (':') with '\0', an effect of strtok_r().
++ */
++ GET_ENVIRONMENT (specs_file, "GCC_SPECS");
++ if (specs_file && (strlen(specs_file) > 0))
++ {
++ char *spec, *saveptr;
++ for (spec=strtok_r(specs_file,":",&saveptr);
++ spec!=NULL;
++ spec=strtok_r(NULL,":",&saveptr))
++ {
++ struct user_specs *user = (struct user_specs *)
++ xmalloc (sizeof (struct user_specs));
++
++ user->next = (struct user_specs *) 0;
++ user->filename = spec;
++ if (user_specs_tail)
++ user_specs_tail->next = user;
++ else
++ user_specs_head = user;
++ user_specs_tail = user;
++ }
++ }
++#endif
+ for (uptr = user_specs_head; uptr; uptr = uptr->next)
+ {
+ char *filename = find_a_file (&startfile_prefixes, uptr->filename,
diff --git a/main/gcc/gcc4-stack-protector-uclibc-no_tls.patch b/main/gcc/gcc4-stack-protector-uclibc-no_tls.patch
new file mode 100644
index 0000000000..c9b54adbe1
--- /dev/null
+++ b/main/gcc/gcc4-stack-protector-uclibc-no_tls.patch
@@ -0,0 +1,84 @@
+diff -u gcc/config/i386/linux.h gcc/config/i386/linux.h
+--- a/gcc/config/i386/linux.h 2 Jul 2005 08:52:20 -0000 1.60
++++ b/gcc/config/i386/linux.h 2 Jul 2005 08:52:20 -0000 1.60
+@@ -186,7 +186,7 @@
+ /* This macro may be overridden in i386/k*bsd-gnu.h. */
+ #define REG_NAME(reg) reg
+
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if defined TARGET_LIBC_PROVIDES_SSP && !defined __UCLIBC__
+ /* i386 glibc provides __stack_chk_guard in %gs:0x14. */
+ #define TARGET_THREAD_SSP_OFFSET 0x14
+ #endif
+diff -u gcc/config/i386/linux64.h gcc/config/i386/linux64.h
+--- a/gcc/config/i386/linux64.h 2 Jul 2005 08:52:20 -0000 1.33
++++ b/gcc/config/i386/linux64.h 2 Jul 2005 08:52:20 -0000 1.33
+@@ -74,7 +74,7 @@
+ /* This macro may be overridden in i386/k*bsd-gnu.h. */
+ #define REG_NAME(reg) reg
+
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if defined TARGET_LIBC_PROVIDES_SSP && !defined __UCLIBC__
+ /* i386 glibc provides __stack_chk_guard in %gs:0x14,
+ x86_64 glibc provides it in %fs:0x28. */
+ #define TARGET_THREAD_SSP_OFFSET (TARGET_64BIT ? 0x28 : 0x14)
+diff -u gcc/config/rs6000/linux.h gcc/config/rs6000/linux.h
+--- a/gcc/config/rs6000/linux.h 2 Jul 2005 08:52:11 -0000 1.53
++++ b/gcc/config/rs6000/linux.h 2 Jul 2005 08:52:11 -0000 1.53
+@@ -114,7 +114,7 @@
+
+ #define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"
+
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if defined TARGET_LIBC_PROVIDES_SSP && !defined __UCLIBC__
+ /* ppc32 glibc provides __stack_chk_guard in -0x7008(2). */
+ #define TARGET_THREAD_SSP_OFFSET -0x7008
+ #endif
+diff -u gcc/config/rs6000/linux64.h gcc/config/rs6000/linux64.h
+--- a/gcc/config/rs6000/linux64.h 2 Jul 2005 08:52:15 -0000 1.81
++++ b/gcc/config/rs6000/linux64.h 2 Jul 2005 08:52:15 -0000 1.81
+@@ -548,7 +548,7 @@
+
+ #define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"
+
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if defined TARGET_LIBC_PROVIDES_SSP && !defined __UCLIBC__
+ /* ppc32 glibc provides __stack_chk_guard in -0x7008(2),
+ ppc64 glibc provides it at -0x7010(13). */
+ #define TARGET_THREAD_SSP_OFFSET (TARGET_64BIT ? -0x7010 : -0x7008)
+diff -u gcc/config/s390/linux.h gcc/config/s390/linux.h
+--- a/gcc/config/s390/linux.h 2005-08-22 15:53:01.000000000 +0200 1.40
++++ b/gcc/config/s390/linux.h 2005-08-22 15:53:01.000000000 +0200 1.40
+@@ -94,7 +94,7 @@
+
+ #define MD_UNWIND_SUPPORT "config/s390/linux-unwind.h"
+
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if defined TARGET_LIBC_PROVIDES_SSP && !defined __UCLIBC__
+ /* s390 glibc provides __stack_chk_guard in 0x14(tp),
+ s390x glibc provides it at 0x28(tp). */
+ #define TARGET_THREAD_SSP_OFFSET (TARGET_64BIT ? 0x28 : 0x14)
+diff -u gcc/config/sparc/linux.h gcc/config/sparc/linux.h
+--- a/gcc/config/sparc/linux.h 6 Jul 2005 07:48:57 -0000 1.72
++++ b/gcc/config/sparc/linux.h 6 Jul 2005 07:48:57 -0000 1.72
+@@ -230,7 +230,7 @@
+ #undef NEED_INDICATE_EXEC_STACK
+ #define NEED_INDICATE_EXEC_STACK 1
+
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if defined TARGET_LIBC_PROVIDES_SSP && !defined __UCLIBC__
+ /* sparc glibc provides __stack_chk_guard in [%g7 + 0x14]. */
+ #define TARGET_THREAD_SSP_OFFSET 0x14
+ #endif
+diff -u gcc/config/sparc/linux64.h gcc/config/sparc/linux64.h
+--- a/gcc/config/sparc/linux64.h 6 Jul 2005 07:48:57 -0000 1.95
++++ b/gcc/config/sparc/linux64.h 6 Jul 2005 07:48:57 -0000 1.95
+@@ -364,7 +364,7 @@
+ #undef NEED_INDICATE_EXEC_STACK
+ #define NEED_INDICATE_EXEC_STACK 1
+
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if defined TARGET_LIBC_PROVIDES_SSP && !defined __UCLIBC__
+ /* sparc glibc provides __stack_chk_guard in [%g7 + 0x14],
+ sparc64 glibc provides it at [%g7 + 0x28]. */
+ #define TARGET_THREAD_SSP_OFFSET (TARGET_ARCH64 ? 0x28 : 0x14)
diff --git a/main/gcc/pt_gnu_eh_frame.patch b/main/gcc/pt_gnu_eh_frame.patch
new file mode 100644
index 0000000000..3e029104aa
--- /dev/null
+++ b/main/gcc/pt_gnu_eh_frame.patch
@@ -0,0 +1,12 @@
+--- gcc-4.3.2/gcc/crtstuff.c.orig Mon Nov 17 16:02:38 2008
++++ gcc-4.3.2/gcc/crtstuff.c Mon Nov 17 16:02:52 2008
+@@ -94,8 +94,7 @@
+ #include <link.h>
+ /* uClibc pretends to be glibc 2.2 and DT_CONFIG is defined in its link.h.
+ But it doesn't use PT_GNU_EH_FRAME ELF segment currently. */
+-# if !defined(__UCLIBC__) \
+- && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
++# if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
+ # define USE_PT_GNU_EH_FRAME
+ # endif
diff --git a/main/gcc/uclibc-getipinfo.patch b/main/gcc/uclibc-getipinfo.patch
new file mode 100644
index 0000000000..3abbbdd7ae
--- /dev/null
+++ b/main/gcc/uclibc-getipinfo.patch
@@ -0,0 +1,19 @@
+--- a/libstdc++-v3/configure 2009-08-04 15:41:02.000000000 +0000
++++ b/libstdc++-v3/configure 2009-08-04 15:46:20.000000000 +0000
+@@ -113523,14 +113523,14 @@
+ # Based on system-libunwind and target, do we have ipinfo?
+ if test x$with_system_libunwind = xyes; then
+ case ${target} in
+- ia64-*-*) have_unwind_getipinfo=no ;;
++ ia64-*-*|*-uclibc*) have_unwind_getipinfo=no ;;
+ *) have_unwind_getipinfo=yes ;;
+ esac
+ else
+ # Darwin before version 9 does not have _Unwind_GetIPInfo.
+
+ case ${target} in
+- *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;
++ *-*-darwin[3-8]|*-*-darwin[3-8].*|*-uclibc*) have_unwind_getipinfo=no ;;
+ *) have_unwind_getipinfo=yes ;;
+ esac
+
diff --git a/main/gconf/APKBUILD b/main/gconf/APKBUILD
new file mode 100644
index 0000000000..579e7ac61a
--- /dev/null
+++ b/main/gconf/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer:
+pkgname=gconf
+pkgver=2.32.4
+pkgrel=1
+pkgdesc="GNOME configuration system"
+url="http://projects.gnome.org/gconf"
+arch="all"
+license="GPL"
+depends=
+depends_dev="orbit2-dev libxml2-dev gtk+-dev polkit-dev"
+makedepends="$depends_dev
+
+ gobject-introspection-dev
+ gnome-doc-utils"
+install=""
+subpackages="$pkgname-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/GConf/${pkgver%.*}/GConf-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/GConf-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --with-gtk=2.0 || return 0
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="b4475bb58c51ca59c7781cd95b302c13 GConf-2.32.4.tar.bz2"
diff --git a/main/gd/APKBUILD b/main/gd/APKBUILD
new file mode 100644
index 0000000000..df9fce4ec5
--- /dev/null
+++ b/main/gd/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=gd
+pkgver=2.0.36_rc1
+_myver=2.0.36RC1
+pkgrel=7
+pkgdesc="Library for the dynamic creation of images by programmers"
+url="http://www.libgd.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="libpng-dev jpeg-dev freetype-dev zlib-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.libgd.org/releases/${pkgname}-${_myver}.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$_myver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-png \
+ --with-freetype \
+ --with-jpeg \
+ --without-xpm \
+ --without-fontconfig
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+dev() {
+ default_dev
+ rm -r "$subpkgdir"/usr/lib/libgd.la
+}
+
+md5sums="e876979ca3130623a4e7866d9579171a gd-2.0.36RC1.tar.bz2"
diff --git a/main/gdb/80_all_gdb-6.5-dwarf-stack-overflow.patch b/main/gdb/80_all_gdb-6.5-dwarf-stack-overflow.patch
new file mode 100644
index 0000000000..2c3c2cbae6
--- /dev/null
+++ b/main/gdb/80_all_gdb-6.5-dwarf-stack-overflow.patch
@@ -0,0 +1,54 @@
+http://bugs.gentoo.org/144833
+
+for gdb/ChangeLog:
+2006-08-22 Will Drewry <wad@google.com>
+ Tavis Ormandy <taviso@google.com>
+
+ * dwarf2read.c (decode_locdesc): Enforce location description stack
+ boundaries.
+ * dwarfread.c (locval): Likewise.
+
+2007-10-15 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ Port to GDB-6.7.
+
+Index: gdb-6.7/gdb/dwarf2read.c
+===================================================================
+--- gdb-6.7.orig/gdb/dwarf2read.c 2007-10-15 00:08:30.000000000 +0200
++++ gdb-6.7/gdb/dwarf2read.c 2007-10-15 21:42:43.000000000 +0200
+@@ -9070,8 +9070,7 @@ dwarf2_fundamental_type (struct objfile
+ callers will only want a very basic result and this can become a
+ complaint.
+
+- Note that stack[0] is unused except as a default error return.
+- Note that stack overflow is not yet handled. */
++ Note that stack[0] is unused except as a default error return. */
+
+ static CORE_ADDR
+ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
+@@ -9088,7 +9087,7 @@ decode_locdesc (struct dwarf_block *blk,
+
+ i = 0;
+ stacki = 0;
+- stack[stacki] = 0;
++ stack[++stacki] = 0;
+
+ while (i < size)
+ {
+@@ -9270,6 +9269,16 @@ decode_locdesc (struct dwarf_block *blk,
+ dwarf_stack_op_name (op));
+ return (stack[stacki]);
+ }
++ /* Enforce maximum stack depth of size-1 to avoid ++stacki writing
++ outside of the allocated space. Also enforce minimum > 0.
++ -- wad@google.com 14 Aug 2006 */
++ if (stacki >= sizeof (stack) / sizeof (*stack) - 1)
++ internal_error (__FILE__, __LINE__,
++ _("location description stack too deep: %d"),
++ stacki);
++ if (stacki <= 0)
++ internal_error (__FILE__, __LINE__,
++ _("location description stack too shallow"));
+ }
+ return (stack[stacki]);
+ }
diff --git a/main/gdb/APKBUILD b/main/gdb/APKBUILD
new file mode 100644
index 0000000000..b53a2b13e4
--- /dev/null
+++ b/main/gdb/APKBUILD
@@ -0,0 +1,51 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gdb
+pkgver=7.2
+pkgrel=1
+pkgdesc="The GNU Debugger"
+url="http://sources.redhat.com/gdb/"
+arch="all"
+license="GPL3"
+depends=
+makedepends="ncurses-dev expat-dev"
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.bz2
+ 80_all_gdb-6.5-dwarf-stack-overflow.patch
+ "
+# patches were found here:
+# http://distfiles.gentoo.org/distfiles/gdb-7.2-patches-1.tar.xz
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build () {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-nls \
+ --without-system-readline \
+ --disable-werror \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/share/info/dir
+ # those are provided by binutils
+ rm -rf "$pkgdir"/usr/include
+ rm -rf "$pkgdir"/usr/lib
+}
+
+md5sums="64260e6c56979ee750a01055f16091a5 gdb-7.2.tar.bz2
+eb81ee111ba23682d4257dad50e01de0 80_all_gdb-6.5-dwarf-stack-overflow.patch"
diff --git a/main/gdbm/10-gdbm-1.8.3-fix-install-ownership.patch b/main/gdbm/10-gdbm-1.8.3-fix-install-ownership.patch
new file mode 100644
index 0000000000..139ef99d7e
--- /dev/null
+++ b/main/gdbm/10-gdbm-1.8.3-fix-install-ownership.patch
@@ -0,0 +1,45 @@
+Install with proper ownership.
+
+http://bugs.gentoo.org/24178
+
+--- Makefile.in
++++ Makefile.in
+@@ -14,10 +14,6 @@
+ INSTALL_PROGRAM = @INSTALL_PROGRAM@
+ INSTALL_DATA = @INSTALL_DATA@
+
+-# File ownership and group
+-BINOWN = bin
+-BINGRP = bin
+-
+ MAKEINFO = makeinfo
+ TEXI2DVI = texi2dvi
+
+@@ -131,22 +127,17 @@
+ $(INSTALL_ROOT)$(includedir) $(INSTALL_ROOT)$(man3dir) \
+ $(INSTALL_ROOT)$(infodir)
+ $(LIBTOOL) $(INSTALL) -c libgdbm.la $(INSTALL_ROOT)$(libdir)/libgdbm.la
+- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) gdbm.h \
+- $(INSTALL_ROOT)$(includedir)/gdbm.h
+- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) $(srcdir)/gdbm.3 \
+- $(INSTALL_ROOT)$(man3dir)/gdbm.3
+- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) $(srcdir)/gdbm.info \
+- $(INSTALL_ROOT)$(infodir)/gdbm.info
++ $(INSTALL_DATA) gdbm.h $(INSTALL_ROOT)$(includedir)/gdbm.h
++ $(INSTALL_DATA) $(srcdir)/gdbm.3 $(INSTALL_ROOT)$(man3dir)/gdbm.3
++ $(INSTALL_DATA) $(srcdir)/gdbm.info $(INSTALL_ROOT)$(infodir)/gdbm.info
+
+ install-compat:
+ $(srcdir)/mkinstalldirs $(INSTALL_ROOT)$(libdir) \
+ $(INSTALL_ROOT)$(includedir)
+ $(LIBTOOL) $(INSTALL) -c libgdbm_compat.la \
+ $(INSTALL_ROOT)$(libdir)/libgdbm_compat.la
+- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) $(srcdir)/dbm.h \
+- $(INSTALL_ROOT)$(includedir)/dbm.h
+- $(INSTALL_DATA) -o $(BINOWN) -g $(BINGRP) $(srcdir)/ndbm.h \
+- $(INSTALL_ROOT)$(includedir)/ndbm.h
++ $(INSTALL_DATA) $(srcdir)/dbm.h $(INSTALL_ROOT)$(includedir)/dbm.h
++ $(INSTALL_DATA) $(srcdir)/ndbm.h $(INSTALL_ROOT)$(includedir)/ndbm.h
+
+ #libgdbm.a: $(OBJS) gdbm.h
+ # rm -f libgdbm.a
diff --git a/main/gdbm/20-gdbm-1.8.3-compat-linking.patch b/main/gdbm/20-gdbm-1.8.3-compat-linking.patch
new file mode 100644
index 0000000000..1337d08f5b
--- /dev/null
+++ b/main/gdbm/20-gdbm-1.8.3-compat-linking.patch
@@ -0,0 +1,19 @@
+Since libgdbm_compat uses libgdbm, make sure we link it in.
+
+http://bugs.gentoo.org/165263
+
+--- Makefile.in
++++ Makefile.in
+@@ -161,10 +161,10 @@
+ $(LIBTOOL) --mode=link $(CC) -o libgdbm.la -rpath $(libdir) \
+ -version-info $(SHLIB_VER) $(LOBJS)
+
+-libgdbm_compat.la: $(C_LOBJS) gdbm.h
++libgdbm_compat.la: $(C_LOBJS) gdbm.h libgdbm.la
+ rm -f libgdbm_compat.la
+ $(LIBTOOL) --mode=link $(CC) -o libgdbm_compat.la -rpath $(libdir) \
+- -version-info $(SHLIB_VER) $(C_LOBJS)
++ -version-info $(SHLIB_VER) $(C_LOBJS) libgdbm.la
+
+ gdbm.h: gdbm.proto gdbmerrno.h gdbm.proto2
+ rm -f gdbm.h
diff --git a/main/gdbm/30-gdbm-1.8.3-build.patch b/main/gdbm/30-gdbm-1.8.3-build.patch
new file mode 100644
index 0000000000..084f5a1d24
--- /dev/null
+++ b/main/gdbm/30-gdbm-1.8.3-build.patch
@@ -0,0 +1,21 @@
+Respect system LDFLAGS when generating gdbm libs
+
+http://bugs.gentoo.org/209730
+
+--- Makefile.in
++++ Makefile.in
+@@ -146,12 +146,12 @@
+
+ libgdbm.la: $(LOBJS) gdbm.h
+ rm -f libgdbm.la
+- $(LIBTOOL) --mode=link $(CC) -o libgdbm.la -rpath $(libdir) \
++ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o libgdbm.la -rpath $(libdir) \
+ -version-info $(SHLIB_VER) $(LOBJS)
+
+ libgdbm_compat.la: $(C_LOBJS) gdbm.h libgdbm.la
+ rm -f libgdbm_compat.la
+- $(LIBTOOL) --mode=link $(CC) -o libgdbm_compat.la -rpath $(libdir) \
++ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o libgdbm_compat.la -rpath $(libdir) \
+ -version-info $(SHLIB_VER) $(C_LOBJS) libgdbm.la
+
+ gdbm.h: gdbm.proto gdbmerrno.h gdbm.proto2
diff --git a/main/gdbm/APKBUILD b/main/gdbm/APKBUILD
new file mode 100644
index 0000000000..f967552d36
--- /dev/null
+++ b/main/gdbm/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=gdbm
+pkgver=1.8.3
+pkgrel=5
+pkgdesc="GNU dbm is a set of database routines that use extensible hashing"
+url="http://www.gnu.org/software/gdbm/"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-dev $pkgname-dev"
+source="ftp://ftp.nluug.nl/pub/gnu/gdbm/gdbm-1.8.3.tar.gz
+30-gdbm-1.8.3-build.patch
+20-gdbm-1.8.3-compat-linking.patch
+10-gdbm-1.8.3-fix-install-ownership.patch"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p0 < $i || return 1
+ done
+
+ ./configure --prefix=/usr \
+ --includedir=/usr/include/gdbm \
+ --disable-dependency-tracking \
+ --enable-fast-install
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make INSTALL_ROOT="$pkgdir" install || return 1
+ make INSTALL_ROOT="$pkgdir" install-compat || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ mv "${pkgdir}"/usr/include/gdbm/gdbm.h "${pkgdir}"/usr/include/
+
+}
+
+md5sums="1d1b1d5c0245b1c00aff92da751e9aa1 gdbm-1.8.3.tar.gz
+5e76bc4f51640434e4279e940f6c73fb 30-gdbm-1.8.3-build.patch
+c8e2323a9e075d5c947cb7c7aeae5384 20-gdbm-1.8.3-compat-linking.patch
+4c7b88079898d7cb380e95c8ae99a9f9 10-gdbm-1.8.3-fix-install-ownership.patch"
diff --git a/main/gdk-pixbuf/APKBUILD b/main/gdk-pixbuf/APKBUILD
new file mode 100644
index 0000000000..1643de1fd5
--- /dev/null
+++ b/main/gdk-pixbuf/APKBUILD
@@ -0,0 +1,56 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gdk-pixbuf
+pkgver=2.22.1
+pkgrel=3
+pkgdesc="GDK Pixbuf library"
+url="http://www.gtk.org/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev=
+makedepends="tiff-dev libpng-dev glib-dev jpeg-dev gobject-introspection-dev"
+install="$pkgname.pre-deinstall"
+triggers="$pkgname.trigger:/usr/lib/gdk-pixbuf-2.0/*/loaders"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/${pkgver%.*}/gdk-pixbuf-$pkgver.tar.bz2
+ gdk-pixbuf-libpng15.patch"
+replaces="gtk+"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+doc() {
+ replaces="gtk+-doc"
+ default_doc
+}
+
+dev() {
+ replaces="gtk+-dev"
+ default_dev
+}
+
+md5sums="716c4593ead3f9c8cca63b8b1907a561 gdk-pixbuf-2.22.1.tar.bz2
+7153731aba3204b4e7173581360ddf37 gdk-pixbuf-libpng15.patch"
diff --git a/main/gdk-pixbuf/gdk-pixbuf-libpng15.patch b/main/gdk-pixbuf/gdk-pixbuf-libpng15.patch
new file mode 100644
index 0000000000..424938e815
--- /dev/null
+++ b/main/gdk-pixbuf/gdk-pixbuf-libpng15.patch
@@ -0,0 +1,67 @@
+From e6a5b2472a4a5d554b587dfcb798b95035caa6fd Mon Sep 17 00:00:00 2001
+From: Maarten Bosmans <mkbosmans@gmail.com>
+Date: Mon, 24 Jan 2011 10:39:22 +0000
+Subject: Use png_jmpbuf macro
+
+This makes the png loader compatible with libpng 1.5
+---
+diff --git a/gdk-pixbuf/io-png.c b/gdk-pixbuf/io-png.c
+index 79c81fd..76f3304 100644
+--- a/gdk-pixbuf/io-png.c
++++ b/gdk-pixbuf/io-png.c
+@@ -183,7 +183,7 @@ png_simple_error_callback(png_structp png_save_ptr,
+ error_msg);
+ }
+
+- longjmp (png_save_ptr->jmpbuf, 1);
++ longjmp (png_jmpbuf(png_save_ptr), 1);
+ }
+
+ static void
+@@ -287,7 +287,7 @@ gdk_pixbuf__png_image_load (FILE *f, GError **error)
+ return NULL;
+ }
+
+- if (setjmp (png_ptr->jmpbuf)) {
++ if (setjmp (png_jmpbuf(png_ptr))) {
+ g_free (rows);
+
+ if (pixbuf)
+@@ -459,7 +459,7 @@ gdk_pixbuf__png_image_begin_load (GdkPixbufModuleSizeFunc size_func,
+ return NULL;
+ }
+
+- if (setjmp (lc->png_read_ptr->jmpbuf)) {
++ if (setjmp (png_jmpbuf(lc->png_read_ptr))) {
+ if (lc->png_info_ptr)
+ png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL);
+ g_free(lc);
+@@ -531,7 +531,7 @@ gdk_pixbuf__png_image_load_increment(gpointer context,
+ lc->error = error;
+
+ /* Invokes our callbacks as needed */
+- if (setjmp (lc->png_read_ptr->jmpbuf)) {
++ if (setjmp (png_jmpbuf(lc->png_read_ptr))) {
+ lc->error = NULL;
+ return FALSE;
+ } else {
+@@ -769,7 +769,7 @@ png_error_callback(png_structp png_read_ptr,
+ error_msg);
+ }
+
+- longjmp (png_read_ptr->jmpbuf, 1);
++ longjmp (png_jmpbuf(png_read_ptr), 1);
+ }
+
+ static void
+@@ -978,7 +978,7 @@ static gboolean real_save_png (GdkPixbuf *pixbuf,
+ success = FALSE;
+ goto cleanup;
+ }
+- if (setjmp (png_ptr->jmpbuf)) {
++ if (setjmp (png_jmpbuf(png_ptr))) {
+ success = FALSE;
+ goto cleanup;
+ }
+--
+cgit v0.9
diff --git a/main/gdk-pixbuf/gdk-pixbuf.pre-deinstall b/main/gdk-pixbuf/gdk-pixbuf.pre-deinstall
new file mode 100644
index 0000000000..d7497db4bb
--- /dev/null
+++ b/main/gdk-pixbuf/gdk-pixbuf.pre-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+rm -f /usr/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
diff --git a/main/gdk-pixbuf/gdk-pixbuf.trigger b/main/gdk-pixbuf/gdk-pixbuf.trigger
new file mode 100644
index 0000000000..b97f005f02
--- /dev/null
+++ b/main/gdk-pixbuf/gdk-pixbuf.trigger
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+gdk-pixbuf-query-loaders --update-cache
diff --git a/main/gdl/APKBUILD b/main/gdl/APKBUILD
new file mode 100644
index 0000000000..ec846a9934
--- /dev/null
+++ b/main/gdl/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gdl
+pkgver=2.30.1
+pkgrel=3
+pkgdesc="Gnome Devtool Libraries"
+url="http://www.gnome.org/"
+arch="all"
+license="GPL"
+makedepends="gtk+-dev libxml2-dev intltool"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+md5sums="4af16be490b47ce4e828a2fb93633856 gdl-2.30.1.tar.bz2"
diff --git a/main/geany/APKBUILD b/main/geany/APKBUILD
new file mode 100644
index 0000000000..22156a1623
--- /dev/null
+++ b/main/geany/APKBUILD
@@ -0,0 +1,93 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=geany
+pkgver=0.20
+pkgrel=2
+pkgdesc="A fast and lightweight IDE"
+url="http://www.geany.org"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="gtk+-dev intltool perl-xml-parser vte-dev"
+depends=
+depends_dev="gtk+-dev"
+install=
+source="http://download.$pkgname.org/$pkgname-$pkgver.tar.gz
+ http://download.geany.org/contrib/tags/dbus-glib-0.76.c.tags
+ http://download.geany.org/contrib/tags/drupal.php.tags
+ http://download.geany.org/contrib/tags/ethos-1.0.c.tags
+ http://download.geany.org/contrib/tags/geany-api-0.19.c.tags
+ http://download.geany.org/contrib/tags/gladeui-1.0.c.tags
+ http://download.geany.org/contrib/tags/gnt.c.tags
+ http://download.geany.org/contrib/tags/gtk220.c.tags
+ http://download.geany.org/contrib/tags/gtkscintilla-2.0.c.tags
+ http://download.geany.org/contrib/tags/gtksourceview-3.0.c.tags
+ http://download.geany.org/contrib/tags/libdevhelp-2.0.c.tags
+ http://download.geany.org/contrib/tags/libgdl-3.0.c.tags
+ http://download.geany.org/contrib/tags/libxml-2.0.c.tags
+ http://download.geany.org/contrib/tags/sqlite3.c.tags
+ http://download.geany.org/contrib/tags/standard.css.tags
+ http://download.geany.org/contrib/tags/std.glsl.tags
+ http://download.geany.org/contrib/tags/std.latex.tags
+ http://download.geany.org/contrib/tags/std.vala.tags
+ http://download.geany.org/contrib/tags/v4l2.c.tags
+ http://download.geany.org/contrib/tags/webkit-1.0.c.tags
+ http://download.geany.org/contrib/tags/wordpress.php.tags
+ http://download.geany.org/contrib/tags/xfce46.c.tags
+ http://advamacs.com/pub/tcl.tcl.tags
+"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ # set default terminal to Terminal
+ sed -e 's/xterm/Terminal/g' \
+ -i src/keyfile.c
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ sed -i 's|MimeType=text/plain;|MimeType=|' geany.desktop || return 1
+ sed -i 's|Sh=|Sh=APKBUILD;|' data/filetype_extensions.conf || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+
+ # install the tags
+ local _tags=
+ for i in $source; do
+ case $i in
+ *.tags) _tags="$_tags $srcdir/${i##*/}";;
+ esac
+ done
+ mkdir -p "$pkgdir"/usr/share/$pkgname/tags
+ install -p $_tags "$pkgdir"/usr/share/$pkgname/tags/
+ install -p $_tags "$pkgdir"/usr/share/$pkgname/tags
+}
+md5sums="7e7d6e4a40e04ecacb9bc317f97becfb geany-0.20.tar.gz
+a3f52be1523faacbd8496409051ed598 dbus-glib-0.76.c.tags
+33bd4e563c52e1286324b81601a77995 drupal.php.tags
+95221e92a942928569f23ef03c7f5dc8 ethos-1.0.c.tags
+9a69cab6ea545b42cf47c5d4eb2003f2 geany-api-0.19.c.tags
+037e3fc18636f435219e7f1f444c21c6 gladeui-1.0.c.tags
+6e7def475cffccc1bf79da98518309ae gnt.c.tags
+0da3e49a2f4288e8d0a55e5ac1b57a30 gtk220.c.tags
+5daa5d0465a5a6d58093b59e69fce758 gtkscintilla-2.0.c.tags
+e934ead8f360a0908429a653b1bde54b gtksourceview-3.0.c.tags
+a5d3d36719bdb5d51ebd81130ea84992 libdevhelp-2.0.c.tags
+adc3b47ffea5badb846507fff1d8a961 libgdl-3.0.c.tags
+94f765658c159b7c196b96f26aaca11d libxml-2.0.c.tags
+6d3b51dd8e99a82c8c055804319f5c97 sqlite3.c.tags
+676ae1e2f01b1baf716e11700a05d94e standard.css.tags
+5f8f1dec5d3afa0105c7d760be0932f3 std.glsl.tags
+d45fae42c5733e081a745fcbb31d5f23 std.latex.tags
+764e506272214ac75d55a224afca1e01 std.vala.tags
+faa05eceb4d806e0c9f7476e4644a65b v4l2.c.tags
+d046ab5c4e7ab2a6ba8961285edc4b2d webkit-1.0.c.tags
+0e51399cc03d094d15b389a2f89dea51 wordpress.php.tags
+8f873570cc244b9185ae26e560887490 xfce46.c.tags
+4821553235a2b6752356229ba64631b6 tcl.tcl.tags"
diff --git a/main/gegl/APKBUILD b/main/gegl/APKBUILD
new file mode 100644
index 0000000000..b5f936069d
--- /dev/null
+++ b/main/gegl/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gegl
+pkgver=0.1.6
+pkgrel=1
+pkgdesc="Graph based image processing framework"
+url="http://www.gegl.org/"
+arch="all"
+license="GPL3 LGPL3"
+makedepends="babl-dev libpng-dev jpeg-dev gtk+-dev librsvg-dev lua-dev"
+subpackages="$pkgname-dev"
+source="ftp://ftp.gimp.org/pub/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2
+ "
+
+depends_dev="babl-dev glib-dev"
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir/$i" || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-librsvg \
+ --disable-docs \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="af5e5a7d3c7ddfaa2b3414de2a7e9113 gegl-0.1.6.tar.bz2"
diff --git a/main/gegl/gegl-uclibc.patch b/main/gegl/gegl-uclibc.patch
new file mode 100644
index 0000000000..cb93f0fec7
--- /dev/null
+++ b/main/gegl/gegl-uclibc.patch
@@ -0,0 +1,22 @@
+--- ./gegl/buffer/gegl-buffer.c.orig
++++ ./gegl/buffer/gegl-buffer.c
+@@ -80,7 +80,7 @@
+ /* #define GEGL_BUFFER_DEBUG_ALLOCATIONS to print allocation stack
+ * traces for leaked GeglBuffers using GNU C libs backtrace_symbols()
+ */
+-#ifndef G_OS_WIN32
++#if !defined(G_OS_WIN32) && !defined(__UCLIBC__)
+ #include <execinfo.h>
+ #endif
+
+@@ -876,8 +876,8 @@
+ gegl_buffer_get_alloc_stack (void)
+ {
+ char *result = NULL;
+-#ifdef G_OS_WIN32
+- result = g_strdup ("backtrack not available on win32\n");
++#if defined(G_OS_WIN32) || defined(__UCLIBC__)
++ result = g_strdup ("backtrack not available\n");
+ #else
+ void *functions[MAX_N_FUNCTIONS];
+ int n_functions = 0;
diff --git a/main/geh/APKBUILD b/main/geh/APKBUILD
new file mode 100644
index 0000000000..ab3eb656e4
--- /dev/null
+++ b/main/geh/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor:
+# Maintainer:
+pkgname=geh
+pkgver=0.2.0
+pkgrel=1
+pkgdesc="a simple commandline image viewer written in C/Gtk+"
+url="https://projects.pekdon.net/projects/geh"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+-dev intltool"
+install=
+subpackages="$pkgname-doc"
+source="http://projects.pekdon.net/projects/geh/files/geh-$pkgver.tar.gz"
+
+# append extra dependencies to -dev subpackage
+# remove if not used.
+# depends_dev="somepackage-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ # remove the 2 lines below (and this) if there is no init.d script
+ # install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ # install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="2349b774e7f0c288061fcfc8c296f20d geh-0.2.0.tar.gz"
diff --git a/main/geoip/APKBUILD b/main/geoip/APKBUILD
new file mode 100644
index 0000000000..c3b72a2727
--- /dev/null
+++ b/main/geoip/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor:
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname="geoip"
+_realname="GeoIP"
+pkgver=1.4.7
+pkgrel=1
+pkgdesc="Lookup countries by IP addresses"
+url="http://www.maxmind.com/app/ip-location"
+arch="all"
+license="GPL"
+depends=
+makedepends="zlib-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.maxmind.com/download/geoip/api/c/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/geoip \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make check || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="a802175d5b7e2b57b540a7dd308d9205 GeoIP-1.4.7.tar.gz"
diff --git a/main/gettext/APKBUILD b/main/gettext/APKBUILD
new file mode 100644
index 0000000000..b5f8307027
--- /dev/null
+++ b/main/gettext/APKBUILD
@@ -0,0 +1,55 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=gettext
+pkgver=0.18.1.1
+pkgrel=6
+pkgdesc="GNU locale utilities"
+url="http://www.gnu.org/software/gettext/gettext.html"
+arch="all"
+license='GPL'
+depends=
+depends_dev="libiconv-dev expat-dev ncurses-dev libxml2-dev"
+makedepends="$depends_dev bash"
+source="ftp://ftp.mirror.nl/pub/mirror/gnu/gettext/gettext-$pkgver.tar.gz
+ gettext-uclibc.patch
+ "
+subpackages="$pkgname-doc $pkgname-dev libintl"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ [ -r "$i" ] || continue
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ # http://bugs.gentoo.org/show_bug.cgi?id=81628
+ export CPPFLAGS="$CPPFLAGS -I/usr/include/libxml2"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --enable-threads=posix \
+ --disable-java \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir/" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+libintl() {
+ replaces="gettext"
+ mkdir -p "$subpkgdir"/usr/lib
+
+ mv "$pkgdir"/usr/lib/libintl.so.* "$subpkgdir"/usr/lib
+}
+
+md5sums="3dd55b952826d2b32f51308f2f91aa89 gettext-0.18.1.1.tar.gz
+cbf6444e7c8ad3aa70b2b80f8fcb6016 gettext-uclibc.patch"
diff --git a/main/gettext/gettext-0.15-expat-no-dlopen.patch b/main/gettext/gettext-0.15-expat-no-dlopen.patch
new file mode 100644
index 0000000000..4630d1dd92
--- /dev/null
+++ b/main/gettext/gettext-0.15-expat-no-dlopen.patch
@@ -0,0 +1,36 @@
+Add support for expat-2 to xgettext by linking it at build time rather than
+at runtime using dlopen
+
+http://bugs.gentoo.org/146211
+
+--- gettext-0.15/gettext-tools/configure
++++ gettext-0.15/gettext-tools/configure
+@@ -44267,19 +44266,6 @@
+
+
+
+-case "$host_os" in
+- linux*)
+-
+-cat >>confdefs.h <<\_ACEOF
+-#define DYNLOAD_LIBEXPAT 1
+-_ACEOF
+-
+- LIBEXPAT="-ldl"
+- LTLIBEXPAT="-ldl"
+-
+-
+- ;;
+- *)
+
+
+
+@@ -44786,8 +44772,6 @@
+
+
+
+- ;;
+-esac
+
+ # If set to t, that means we are running in a shell under Emacs.
+ # If you have an Emacs named "t", then use the full path.
diff --git a/main/gettext/gettext-0.17-gnuinfo.patch b/main/gettext/gettext-0.17-gnuinfo.patch
new file mode 100644
index 0000000000..243916636f
--- /dev/null
+++ b/main/gettext/gettext-0.17-gnuinfo.patch
@@ -0,0 +1,16 @@
+Fix broken Info file produced by texinfo 4.11
+http://bugs.gentoo.org/249167
+
+--- gettext-0.17/gettext-tools/doc/gettext.info
++++ gettext-0.17/gettext-tools/doc/gettext.info
+@@ -1,7 +1,8 @@
++This is gettext.info, produced by makeinfo version 4.13 from
++gettext.texi.
++
+ INFO-DIR-SECTION GNU Gettext Utilities
+ START-INFO-DIR-ENTRY
+-This is gettext.info, produced by makeinfo version 4.11 from gettext.texi.
+-
+ * gettext: (gettext). GNU gettext utilities.
+ * autopoint: (gettext)autopoint Invocation. Copy gettext infrastructure.
+ * envsubst: (gettext)envsubst Invocation. Expand environment variables.
diff --git a/main/gettext/gettext-0.17-open-args.patch b/main/gettext/gettext-0.17-open-args.patch
new file mode 100644
index 0000000000..6291f00493
--- /dev/null
+++ b/main/gettext/gettext-0.17-open-args.patch
@@ -0,0 +1,25 @@
+2007-11-07 Jim Meyering <meyering@redhat.com>
+ Bruno Haible <bruno@clisp.org>
+
+ * write-catalog.c (msgdomain_list_print): Fix open() call.
+
+--- a/gettext-tools/src/write-catalog.c 7 Oct 2007 19:35:31 -0000 1.4
++++ b/gettext-tools/src/write-catalog.c 7 Nov 2007 11:43:15 -0000
+@@ -1,5 +1,5 @@
+ /* GNU gettext - internationalization aids
+- Copyright (C) 1995-1998, 2000-2006 Free Software Foundation, Inc.
++ Copyright (C) 1995-1998, 2000-2007 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+@@ -220,7 +220,9 @@
+ /* Open the output file. */
+ if (!to_stdout)
+ {
+- fd = open (filename, O_WRONLY | O_CREAT);
++ fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC,
++ /* 0666 in portable POSIX notation: */
++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ if (fd < 0)
+ {
+ const char *errno_description = strerror (errno);
diff --git a/main/gettext/gettext-uclibc.patch b/main/gettext/gettext-uclibc.patch
new file mode 100644
index 0000000000..d797c1cd9e
--- /dev/null
+++ b/main/gettext/gettext-uclibc.patch
@@ -0,0 +1,11 @@
+--- ./gettext-tools/gnulib-lib/spawn.in.h.orig
++++ ./gettext-tools/gnulib-lib/spawn.in.h
+@@ -31,7 +31,7 @@
+
+ /* Get definitions of 'struct sched_param' and 'sigset_t'.
+ But avoid namespace pollution on glibc systems. */
+-#ifndef __GLIBC__
++#if !defined(__GLIBC__) || defined(__UCLIBC__)
+ # include <sched.h>
+ # include <signal.h>
+ #endif
diff --git a/main/ghostscript-fonts/APKBUILD b/main/ghostscript-fonts/APKBUILD
new file mode 100644
index 0000000000..38a0f84662
--- /dev/null
+++ b/main/ghostscript-fonts/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Cameron Banta <cbanta@gmail.com>
+# Maintainer: Cameron Banta <cbanta@gmail.com>
+pkgname=ghostscript-fonts
+_pkgname=ghostscript-fonts-std
+pkgver=8.11
+pkgrel=1
+pkgdesc="Fonts and font metrics distributed with Ghostscript"
+url="http://gs-fonts.sourceforge.net/"
+arch="all"
+license="GPL"
+source="http://downloads.sourceforge.net/gs-fonts/$_pkgname-$pkgver.tar.gz"
+
+build(){
+ echo
+}
+
+package() {
+ cd "$srcdir/fonts"
+ mkdir -p "$pkgdir/usr/share/fonts/Type1/"
+ cp * "$pkgdir/usr/share/fonts/Type1/"
+}
+
+md5sums="6865682b095f8c4500c54b285ff05ef6 ghostscript-fonts-std-8.11.tar.gz"
diff --git a/main/ghostscript/APKBUILD b/main/ghostscript/APKBUILD
new file mode 100644
index 0000000000..95582ff8f8
--- /dev/null
+++ b/main/ghostscript/APKBUILD
@@ -0,0 +1,75 @@
+# Contributor: Cameron Banta <cbanta@gmail.com>
+# Maintainer: Cameron Banta <cbanta@gmail.com>
+pkgname=ghostscript
+pkgver=9.00
+pkgrel=2
+pkgdesc="An interpreter for the PostScript language and for PDF"
+url="http://ghostscript.com/"
+arch="all"
+license="GPL"
+makedepends="autoconf automake jpeg-dev libpng-dev jasper-dev expat-dev zlib-dev tiff-dev libiconv-dev"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://ghostscript.com/releases/$pkgname-$pkgver.tar.gz
+ ghostscript-system-jasper.patch
+ ghostscript-png15.patch"
+
+prepare() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ # force it to use system-libs
+ rm -rf jpeg libpng jasper expat tiff zlib
+
+ # fix build with systems jasper
+ patch -Np1 -i "${srcdir}"/ghostscript-system-jasper.patch || return 1
+ patch -Np0 -i "${srcdir}"/ghostscript-png15.patch || return 1
+
+ # fix parallel builds
+ sed -i -e 's/ECHO_XE/ECHOGS_XE/g' \
+ -e 's/^\($(GLOBJ)md5.$(OBJ) :.*\)/\1 $(ECHOGS_XE)/' \
+ base/lib.mak || return 1
+
+ ./autogen.sh \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --docdir=/usr/share/doc/"$pkgname" \
+ --enable-dynamic \
+ --with-system-libtiff \
+ --without-ijs --without-x \
+ --with-jbig2dec \
+ --without-omni \
+ --with-drivers=FILES \
+ --with-fontpath=/usr/share/fonts/Type1:/usr/share/fonts \
+ --disable-cups --disable-gtk --disable-cairo \
+ --disable-compile-inits # needed for linking with system-zlib
+}
+
+build(){
+ cd "$srcdir/$pkgname-$pkgver"
+ make so all || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="${pkgdir}" install soinstall || return 1
+
+ #create empty dir for future fonts
+ mkdir -p "${pkgdir}"/usr/share/fonts/Type1
+
+ # license and copying
+ install -m644 -D "$srcdir/$pkgname-$pkgver/LICENSE" \
+ "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
+ install -m644 -D "$srcdir/$pkgname-$pkgver/doc/COPYING" \
+ "$pkgdir/usr/share/licenses/$pkgname/COPYING"
+
+ # make the doc and examples more alpine like
+ # (the --docdir above doesn't seem to work so good)
+ mkdir -p "$pkgdir/usr/share/doc/$pkgname"
+ mv "$pkgdir/usr/share/$pkgname/$pkgver/doc" "$pkgdir/usr/share/doc/$pkgname"
+ mv "$pkgdir/usr/share/$pkgname/$pkgver/examples" "$pkgdir/usr/share/doc/$pkgname"
+}
+
+md5sums="a402462478b4cdda3e1816899227b845 ghostscript-9.00.tar.gz
+f5bc029b0ed05ac8d602bff0e1c021bd ghostscript-system-jasper.patch
+020ebbd97bb3dd226660bc03ce08293c ghostscript-png15.patch"
diff --git a/main/ghostscript/ghostscript-png15.patch b/main/ghostscript/ghostscript-png15.patch
new file mode 100644
index 0000000000..dca4f07607
--- /dev/null
+++ b/main/ghostscript/ghostscript-png15.patch
@@ -0,0 +1,196 @@
+$NetBSD: patch-ak,v 1.5 2011/01/15 14:08:10 wiz Exp $
+
+Fix build with png-1.5. From John Bowler.
+
+--- base/gdevpng.c.orig 2008-07-17 02:34:01.000000000 +0000
++++ base/gdevpng.c
+@@ -36,12 +36,14 @@
+ #include "gdevpccm.h"
+ #include "gscdefs.h"
+
+-#define PNG_INTERNAL
+ /*
+ * libpng versions 1.0.3 and later allow disabling access to the stdxxx
+ * files while retaining support for FILE * I/O.
++ *
++ * This is a misunderstanding - this is a build time option for libpng,
++ * it has no effect on a user of libpng.
+ */
+-#define PNG_NO_CONSOLE_IO
++/*#define PNG_NO_CONSOLE_IO*/
+ /*
+ * Earlier libpng versions require disabling FILE * I/O altogether.
+ * This produces a compiler warning about no prototype for png_init_io.
+@@ -280,7 +282,7 @@ png_print_page(gx_device_printer * pdev,
+ goto done;
+ }
+ /* set error handling */
+- if (setjmp(png_ptr->jmpbuf)) {
++ if (setjmp(png_jmpbuf(png_ptr))) {
+ /* If we get here, we had a problem reading the file */
+ code = gs_note_error(gs_error_VMerror);
+ goto done;
+@@ -290,19 +292,12 @@ png_print_page(gx_device_printer * pdev,
+ png_init_io(png_ptr, file);
+
+ /* set the file information here */
+- info_ptr->width = pdev->width;
+- info_ptr->height = pdev->height;
+- /* resolution is in pixels per meter vs. dpi */
+- info_ptr->x_pixels_per_unit =
+- (png_uint_32) (pdev->HWResolution[0] * (100.0 / 2.54));
+- info_ptr->y_pixels_per_unit =
+- (png_uint_32) (pdev->HWResolution[1] * (100.0 / 2.54));
+- info_ptr->phys_unit_type = PNG_RESOLUTION_METER;
+- info_ptr->valid |= PNG_INFO_pHYs;
+ switch (depth) {
+ case 32:
+- info_ptr->bit_depth = 8;
+- info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
++ png_set_IHDR(png_ptr, info_ptr, pdev->width, pdev->height,
++ 8, PNG_COLOR_TYPE_RGB_ALPHA,
++ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
++ PNG_FILTER_TYPE_DEFAULT);
+ png_set_invert_alpha(png_ptr);
+ { gx_device_pngalpha *ppdev = (gx_device_pngalpha *)pdev;
+ png_color_16 background;
+@@ -315,57 +310,69 @@ png_print_page(gx_device_printer * pdev,
+ }
+ break;
+ case 48:
+- info_ptr->bit_depth = 16;
+- info_ptr->color_type = PNG_COLOR_TYPE_RGB;
++ png_set_IHDR(png_ptr, info_ptr, pdev->width, pdev->height,
++ 16, PNG_COLOR_TYPE_RGB,
++ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
++ PNG_FILTER_TYPE_DEFAULT);
+ #if defined(ARCH_IS_BIG_ENDIAN) && (!ARCH_IS_BIG_ENDIAN)
+ png_set_swap(png_ptr);
+ #endif
+ break;
+ case 24:
+- info_ptr->bit_depth = 8;
+- info_ptr->color_type = PNG_COLOR_TYPE_RGB;
++ png_set_IHDR(png_ptr, info_ptr, pdev->width, pdev->height,
++ 8, PNG_COLOR_TYPE_RGB,
++ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
++ PNG_FILTER_TYPE_DEFAULT);
+ break;
+ case 8:
+- info_ptr->bit_depth = 8;
+- if (gx_device_has_color(pdev))
+- info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
+- else
+- info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
++ png_set_IHDR(png_ptr, info_ptr, pdev->width, pdev->height,
++ 8, gx_device_has_color(pdev) ?
++ PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY,
++ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
++ PNG_FILTER_TYPE_DEFAULT);
+ break;
+ case 4:
+- info_ptr->bit_depth = 4;
+- info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
++ png_set_IHDR(png_ptr, info_ptr, pdev->width, pdev->height,
++ 4, PNG_COLOR_TYPE_PALETTE,
++ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
++ PNG_FILTER_TYPE_DEFAULT);
+ break;
+ case 1:
+- info_ptr->bit_depth = 1;
+- info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
++ png_set_IHDR(png_ptr, info_ptr, pdev->width, pdev->height,
++ 1, PNG_COLOR_TYPE_GRAY,
++ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
++ PNG_FILTER_TYPE_DEFAULT);
+ /* invert monocrome pixels */
+ png_set_invert_mono(png_ptr);
+ break;
++ default:
++ png_error(png_ptr, "invalid bit depth");
+ }
+
++ /* resolution is in pixels per meter vs. dpi */
++ png_set_pHYs(png_ptr, info_ptr,
++ (png_uint_32) (pdev->HWResolution[0] * (100.0 / 2.54)),
++ (png_uint_32) (pdev->HWResolution[1] * (100.0 / 2.54)),
++ PNG_RESOLUTION_METER);
++
+ /* set the palette if there is one */
+- if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
++ if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
+ int i;
+ int num_colors = 1 << depth;
+ gx_color_value rgb[3];
++ png_color palette[256];
++
++ if (num_colors > 256)
++ num_colors = 256;
+
+- info_ptr->palette =
+- (void *)gs_alloc_bytes(mem, 256 * sizeof(png_color),
+- "png palette");
+- if (info_ptr->palette == 0) {
+- code = gs_note_error(gs_error_VMerror);
+- goto done;
+- }
+- info_ptr->num_palette = num_colors;
+- info_ptr->valid |= PNG_INFO_PLTE;
+ for (i = 0; i < num_colors; i++) {
+ (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev,
+ (gx_color_index) i, rgb);
+- info_ptr->palette[i].red = gx_color_value_to_byte(rgb[0]);
+- info_ptr->palette[i].green = gx_color_value_to_byte(rgb[1]);
+- info_ptr->palette[i].blue = gx_color_value_to_byte(rgb[2]);
++ palette[i].red = gx_color_value_to_byte(rgb[0]);
++ palette[i].green = gx_color_value_to_byte(rgb[1]);
++ palette[i].blue = gx_color_value_to_byte(rgb[2]);
+ }
++ png_set_PLTE(png_ptr, info_ptr, palette, num_colors);
+ }
+ /* add comment */
+ strncpy(software_key, "Software", sizeof(software_key));
+@@ -375,15 +382,14 @@ png_print_page(gx_device_printer * pdev,
+ text_png.key = software_key;
+ text_png.text = software_text;
+ text_png.text_length = strlen(software_text);
+- info_ptr->text = &text_png;
+- info_ptr->num_text = 1;
++ png_set_text(png_ptr, info_ptr, &text_png, 1);
+
+ /* write the file information */
+ png_write_info(png_ptr, info_ptr);
+
+ /* don't write the comments twice */
+- info_ptr->num_text = 0;
+- info_ptr->text = NULL;
++ /*info_ptr->num_text = 0;*/
++ /*info_ptr->text = NULL;*/
+
+ /* Write the contents of the image. */
+ for (y = 0; y < height; y++) {
+@@ -395,7 +401,7 @@ png_print_page(gx_device_printer * pdev,
+ png_write_end(png_ptr, info_ptr);
+
+ /* if you alloced the palette, free it here */
+- gs_free_object(mem, info_ptr->palette, "png palette");
++ /*gs_free_object(mem, info_ptr->palette, "png palette");*/
+
+ done:
+ /* free the structures */
+@@ -405,6 +411,7 @@ png_print_page(gx_device_printer * pdev,
+ return code;
+ }
+
++#if 0 /* not required in 1.5 */
+ /*
+ * Patch around a static reference to a never-used procedure.
+ * This could be avoided if we were willing to edit pngconf.h to
+@@ -422,6 +429,7 @@ png_push_fill_buffer(png_structp png_ptr
+ {
+ }
+ #endif
++#endif
+
+ static int
+ pngalpha_open(gx_device * pdev)
diff --git a/main/ghostscript/ghostscript-system-jasper.patch b/main/ghostscript/ghostscript-system-jasper.patch
new file mode 100644
index 0000000000..dc704468cb
--- /dev/null
+++ b/main/ghostscript/ghostscript-system-jasper.patch
@@ -0,0 +1,26 @@
+diff -up ghostscript-9.00/base/sjpx.c.system-jasper ghostscript-9.00/base/sjpx.c
+--- ghostscript-9.00/base/sjpx.c.system-jasper 2010-08-17 15:31:58.000000000 +0100
++++ ghostscript-9.00/base/sjpx.c 2010-09-23 09:59:46.747467642 +0100
+@@ -33,14 +33,6 @@ static void s_jpxd_set_defaults(stream_s
+ private_st_jpxd_state(); /* creates a gc object for our state,
+ defined in sjpx.h */
+
+-/* error reporting callback for the jpx library */
+-static void
+-s_jpx_jas_error_cb(jas_error_t err, char *msg)
+-{
+- dprintf2("jasper (code %d) %s", (int)err, msg);
+-}
+-
+-
+ /* initialize the steam.
+ this involves allocating the stream and image structures, and
+ initializing the decoder.
+@@ -56,7 +48,6 @@ s_jpxd_init(stream_state * ss)
+ }
+
+ status = jas_init();
+- jas_set_error_cb(s_jpx_jas_error_cb);
+ #ifdef JPX_DEBUG
+ /* raise the error reporting threshold from the default (0) */
+ jas_setdbglevel(1);
diff --git a/main/giblib/APKBUILD b/main/giblib/APKBUILD
new file mode 100644
index 0000000000..f14b62abf0
--- /dev/null
+++ b/main/giblib/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=giblib
+pkgver=1.2.4
+pkgrel=7
+pkgdesc="Giblib is a library that feh uses as a wrapper to imlib2"
+url="http://linuxbrit.co.uk/giblib/"
+arch="all"
+license="MIT"
+subpackages="$pkgname-doc $pkgname-dev"
+depends=
+makedepends="imlib2-dev libxext-dev libx11-dev freetype-dev zlib-dev"
+source="http://linuxbrit.co.uk/downloads/$pkgname-$pkgver.tar.gz"
+
+depends_dev="imlib2-dev freetype-dev zlib-dev libx11-dev libxext-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" docsdir=/usr/share/doc/giblib install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+ install -Dm644 COPYING $pkgdir/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="c810ef5389baf24882a1caca2954385e giblib-1.2.4.tar.gz"
diff --git a/main/giflib/APKBUILD b/main/giflib/APKBUILD
new file mode 100644
index 0000000000..bf68275f35
--- /dev/null
+++ b/main/giflib/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=giflib
+pkgver=4.1.6
+pkgrel=6
+pkgdesc="A library for reading and writing gif images"
+url="http://sourceforge.net/projects/giflib/"
+arch="all"
+license="MIT"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="libx11-dev libsm-dev util-linux-ng-dev"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+ MAJOR=`echo $pkgver | sed 's/\([0-9]\+\)\..*/\1/'`
+ gcc -shared -Wl,-soname,libungif.so.${MAJOR} -Llib/.libs -lgif -o libungif.so.$pkgver || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING \
+ || return 1
+
+ install -m755 libungif.so.$pkgver "$pkgdir"/usr/lib/ || return 1
+ ln -sf libungif.so.$pkgver "$pkgdir"/usr/lib/libungif.so.4 || return 1
+ ln -sf libungif.so.4 "$pkgdir"/usr/lib/libungif.so || return 1
+}
+md5sums="7125644155ae6ad33dbc9fc15a14735f giflib-4.1.6.tar.bz2"
diff --git a/main/gimp/APKBUILD b/main/gimp/APKBUILD
new file mode 100644
index 0000000000..b70fd01744
--- /dev/null
+++ b/main/gimp/APKBUILD
@@ -0,0 +1,57 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gimp
+pkgver=2.6.11
+pkgrel=3
+pkgdesc="GNU Image Manipulation Program"
+url="http://www.gimp.org/"
+arch="all"
+license="GPL"
+makedepends="gtk+-dev libxpm-dev libxmu-dev librsvg-dev dbus-glib-dev
+ libexif-dev desktop-file-utils intltool gegl-dev tiff-dev
+ jpeg-dev libpng-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.$pkgname.org/pub/$pkgname/v2.6/$pkgname-$pkgver.tar.bz2
+ gimp-libpng1.5-compat.patch
+ gimp-curl-fix.patch"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ cd "$_builddir"
+
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i..."
+ patch -s -p1 -N -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-mp \
+ --enable-gimp-console \
+ --enable-gimp-remote \
+ --disable-devel-docs \
+ --disable-python \
+ --without-gvfs \
+ --without-gnomevfs \
+ --with-gif-compression=lzw \
+ --without-aa || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ ln -s gimptool-2.0 "$pkgdir/usr/bin/gimptool" || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="bb2939fe13e54fc7255cef5d097bb5dd gimp-2.6.11.tar.bz2
+7dfc4006676fdea887f1883ccc6c7772 gimp-libpng1.5-compat.patch
+678010acec374e06140e65f7de24ff69 gimp-curl-fix.patch"
diff --git a/main/gimp/gimp-curl-fix.patch b/main/gimp/gimp-curl-fix.patch
new file mode 100644
index 0000000000..ea8935d008
--- /dev/null
+++ b/main/gimp/gimp-curl-fix.patch
@@ -0,0 +1,12 @@
+diff --git a/plug-ins/file-uri/uri-backend-libcurl.c b/plug-ins/file-uri/uri-backend-libcurl.c
+index a566966..747dca7 100644
+--- a/plug-ins/file-uri/uri-backend-libcurl.c
++++ b/plug-ins/file-uri/uri-backend-libcurl.c
+@@ -24,7 +24,6 @@
+ #include <errno.h>
+
+ #include <curl/curl.h>
+-#include <curl/types.h>
+ #include <curl/easy.h>
+
+ #include <glib/gstdio.h>
diff --git a/main/gimp/gimp-libpng1.5-compat.patch b/main/gimp/gimp-libpng1.5-compat.patch
new file mode 100644
index 0000000000..e3429e314c
--- /dev/null
+++ b/main/gimp/gimp-libpng1.5-compat.patch
@@ -0,0 +1,379 @@
+From 2a53e15a7a373c13dec4333c5dd8d2cfde9ebd40 Mon Sep 17 00:00:00 2001
+From: Thomas Klausner <wiz@danbala.tuwien.ac.at>
+Date: Mon, 24 Jan 2011 18:06:50 +0100
+Subject: [PATCH] Bug 640409 - png-1.5 compatibility fixes
+
+---
+ plug-ins/common/file-png.c | 138 +++++++++++++++++++++++++++-----------------
+ 1 files changed, 84 insertions(+), 54 deletions(-)
+
+diff --git a/plug-ins/common/file-png.c b/plug-ins/common/file-png.c
+index be3b4c6..2ccd0e5 100644
+--- a/plug-ins/common/file-png.c
++++ b/plug-ins/common/file-png.c
+@@ -652,7 +652,11 @@ on_read_error (png_structp png_ptr, png_const_charp error_msg)
+ error_data->drawable->width, num);
+ }
+
++#if (PNG_LIBPNG_VER < 10500)
+ longjmp (png_ptr->jmpbuf, 1);
++#else
++ png_longjmp (png_ptr, 1);
++#endif
+ }
+
+ /*
+@@ -696,7 +700,7 @@ load_image (const gchar *filename,
+ pp = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ info = png_create_info_struct (pp);
+
+- if (setjmp (pp->jmpbuf))
++ if (setjmp (png_jmpbuf(pp)))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Error while reading '%s'. File corrupted?"),
+@@ -737,17 +741,19 @@ load_image (const gchar *filename,
+ * Latest attempt, this should be my best yet :)
+ */
+
+- if (info->bit_depth == 16)
++ if (png_get_bit_depth(pp, info) == 16)
+ {
+ png_set_strip_16 (pp);
+ }
+
+- if (info->color_type == PNG_COLOR_TYPE_GRAY && info->bit_depth < 8)
++ if (png_get_color_type(pp, info) == PNG_COLOR_TYPE_GRAY &&
++ png_get_bit_depth(pp, info) < 8)
+ {
+ png_set_expand (pp);
+ }
+
+- if (info->color_type == PNG_COLOR_TYPE_PALETTE && info->bit_depth < 8)
++ if (png_get_color_type(pp, info) == PNG_COLOR_TYPE_PALETTE &&
++ png_get_bit_depth(pp, info) < 8)
+ {
+ png_set_packing (pp);
+ }
+@@ -756,8 +762,8 @@ load_image (const gchar *filename,
+ * Expand G+tRNS to GA, RGB+tRNS to RGBA
+ */
+
+- if (info->color_type != PNG_COLOR_TYPE_PALETTE &&
+- (info->valid & PNG_INFO_tRNS))
++ if (png_get_color_type(pp, info) != PNG_COLOR_TYPE_PALETTE &&
++ png_get_valid(pp, info, PNG_INFO_tRNS) != 0)
+ {
+ png_set_expand (pp);
+ }
+@@ -774,7 +780,7 @@ load_image (const gchar *filename,
+ */
+
+ if (png_get_valid (pp, info, PNG_INFO_tRNS) &&
+- info->color_type == PNG_COLOR_TYPE_PALETTE)
++ png_get_color_type(pp, info) == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_get_tRNS (pp, info, &alpha_ptr, &num, NULL);
+ /* Copy the existing alpha values from the tRNS chunk */
+@@ -796,7 +802,7 @@ load_image (const gchar *filename,
+
+ png_read_update_info (pp, info);
+
+- switch (info->color_type)
++ switch (png_get_color_type(pp, info))
+ {
+ case PNG_COLOR_TYPE_RGB: /* RGB */
+ bpp = 3;
+@@ -835,7 +841,9 @@ load_image (const gchar *filename,
+ return -1;
+ }
+
+- image = gimp_image_new (info->width, info->height, image_type);
++ image = gimp_image_new (png_get_image_width(pp, info),
++ png_get_image_height(pp, info),
++ image_type);
+ if (image == -1)
+ {
+ g_set_error (error, 0, 0,
+@@ -848,7 +856,9 @@ load_image (const gchar *filename,
+ * Create the "background" layer to hold the image...
+ */
+
+- layer = gimp_layer_new (image, _("Background"), info->width, info->height,
++ layer = gimp_layer_new (image, _("Background"),
++ png_get_image_width(pp, info),
++ png_get_image_height(pp, info),
+ layer_type, 100, GIMP_NORMAL_MODE);
+ gimp_image_insert_layer (image, layer, -1, 0);
+
+@@ -882,7 +892,8 @@ load_image (const gchar *filename,
+
+ gimp_layer_set_offsets (layer, offset_x, offset_y);
+
+- if ((abs (offset_x) > info->width) || (abs (offset_y) > info->height))
++ if ((abs (offset_x) > png_get_image_width(pp, info)) ||
++ (abs (offset_y) > png_get_image_height(pp, info)))
+ {
+ if (interactive)
+ g_message (_("The PNG file specifies an offset that caused "
+@@ -937,23 +948,27 @@ load_image (const gchar *filename,
+
+ empty = 0; /* by default assume no full transparent palette entries */
+
+- if (info->color_type & PNG_COLOR_MASK_PALETTE)
++ if (png_get_color_type(pp, info) & PNG_COLOR_MASK_PALETTE)
+ {
++ png_colorp palette;
++ int num_palette;
++ png_get_PLTE(pp, info, &palette, &num_palette);
++
+ if (png_get_valid (pp, info, PNG_INFO_tRNS))
+ {
+ for (empty = 0; empty < 256 && alpha[empty] == 0; ++empty)
+ /* Calculates number of fully transparent "empty" entries */;
+
+ /* keep at least one entry */
+- empty = MIN (empty, info->num_palette - 1);
++ empty = MIN (empty, num_palette - 1);
+
+- gimp_image_set_colormap (image, (guchar *) (info->palette + empty),
+- info->num_palette - empty);
++ gimp_image_set_colormap (image, (guchar *) (palette + empty),
++ num_palette - empty);
+ }
+ else
+ {
+- gimp_image_set_colormap (image, (guchar *) info->palette,
+- info->num_palette);
++ gimp_image_set_colormap (image, (guchar *) palette,
++ num_palette);
+ }
+ }
+
+@@ -971,18 +986,20 @@ load_image (const gchar *filename,
+ */
+
+ tile_height = gimp_tile_height ();
+- pixel = g_new0 (guchar, tile_height * info->width * bpp);
++ pixel = g_new0 (guchar, tile_height * png_get_image_width(pp, info) * bpp);
+ pixels = g_new (guchar *, tile_height);
+
+ for (i = 0; i < tile_height; i++)
+- pixels[i] = pixel + info->width * info->channels * i;
++ pixels[i] = pixel + (png_get_image_width(pp, info) *
++ png_get_channels(pp, info) *
++ i);
+
+ /* Install our own error handler to handle incomplete PNG files better */
+ error_data.drawable = drawable;
+ error_data.pixel = pixel;
+ error_data.tile_height = tile_height;
+- error_data.width = info->width;
+- error_data.height = info->height;
++ error_data.width = png_get_image_width(pp, info);
++ error_data.height = png_get_image_height(pp, info);
+ error_data.bpp = bpp;
+ error_data.pixel_rgn = &pixel_rgn;
+
+@@ -995,10 +1012,11 @@ load_image (const gchar *filename,
+ */
+
+ for (begin = 0, end = tile_height;
+- begin < info->height; begin += tile_height, end += tile_height)
++ begin < png_get_image_height(pp, info);
++ begin += tile_height, end += tile_height)
+ {
+- if (end > info->height)
+- end = info->height;
++ if (end > png_get_image_height(pp, info))
++ end = png_get_image_height(pp, info);
+
+ num = end - begin;
+
+@@ -1015,10 +1033,11 @@ load_image (const gchar *filename,
+ gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0, begin,
+ drawable->width, num);
+
+- memset (pixel, 0, tile_height * info->width * bpp);
++ memset (pixel, 0, tile_height * png_get_image_width(pp, info) * bpp);
+
+ gimp_progress_update (((gdouble) pass +
+- (gdouble) end / (gdouble) info->height) /
++ (gdouble) end /
++ (gdouble) png_get_image_height(pp, info)) /
+ (gdouble) num_passes);
+ }
+ }
+@@ -1071,7 +1090,8 @@ load_image (const gchar *filename,
+
+ {
+ png_uint_32 proflen;
+- png_charp profname, profile;
++ png_charp profname;
++ png_bytep profile;
+ int profcomp;
+
+ if (png_get_iCCP (pp, info, &profname, &profcomp, &profile, &proflen))
+@@ -1199,6 +1219,8 @@ save_image (const gchar *filename,
+ guchar red, green, blue; /* Used for palette background */
+ time_t cutime; /* Time since epoch */
+ struct tm *gmt; /* GMT broken down */
++ int color_type; /* type of colors in image */
++ int bit_depth; /* width of colors in bit */
+
+ guchar remap[256]; /* Re-mapping for the palette */
+
+@@ -1207,7 +1229,9 @@ save_image (const gchar *filename,
+ if (pngvals.comment)
+ {
+ GimpParasite *parasite;
++#ifndef PNG_iTXt_SUPPORTED
+ gsize text_length = 0;
++#endif
+
+ parasite = gimp_image_parasite_find (orig_image_ID, "gimp-comment");
+ if (parasite)
+@@ -1248,7 +1272,7 @@ save_image (const gchar *filename,
+ pp = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ info = png_create_info_struct (pp);
+
+- if (setjmp (pp->jmpbuf))
++ if (setjmp (png_jmpbuf(pp)))
+ {
+ g_set_error (error, 0, 0,
+ _("Error while saving '%s'. Could not save image."),
+@@ -1290,11 +1314,6 @@ save_image (const gchar *filename,
+
+ png_set_compression_level (pp, pngvals.compression_level);
+
+- info->width = drawable->width;
+- info->height = drawable->height;
+- info->bit_depth = 8;
+- info->interlace_type = pngvals.interlaced;
+-
+ /*
+ * Initialise remap[]
+ */
+@@ -1308,37 +1327,36 @@ save_image (const gchar *filename,
+ switch (type)
+ {
+ case GIMP_RGB_IMAGE:
+- info->color_type = PNG_COLOR_TYPE_RGB;
++ color_type = PNG_COLOR_TYPE_RGB;
+ bpp = 3;
+ break;
+
+ case GIMP_RGBA_IMAGE:
+- info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
++ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ bpp = 4;
+ break;
+
+ case GIMP_GRAY_IMAGE:
+- info->color_type = PNG_COLOR_TYPE_GRAY;
++ color_type = PNG_COLOR_TYPE_GRAY;
+ bpp = 1;
+ break;
+
+ case GIMP_GRAYA_IMAGE:
+- info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
++ color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+ bpp = 2;
+ break;
+
+ case GIMP_INDEXED_IMAGE:
+ bpp = 1;
+- info->color_type = PNG_COLOR_TYPE_PALETTE;
+- info->valid |= PNG_INFO_PLTE;
+- info->palette =
+- (png_colorp) gimp_image_get_colormap (image_ID, &num_colors);
+- info->num_palette = num_colors;
++ color_type = PNG_COLOR_TYPE_PALETTE;
++ png_set_PLTE(pp, info,
++ (png_colorp) gimp_image_get_colormap (image_ID, &num_colors),
++ num_colors);
+ break;
+
+ case GIMP_INDEXEDA_IMAGE:
+ bpp = 2;
+- info->color_type = PNG_COLOR_TYPE_PALETTE;
++ color_type = PNG_COLOR_TYPE_PALETTE;
+ /* fix up transparency */
+ respin_cmap (pp, info, remap, image_ID, drawable);
+ break;
+@@ -1352,17 +1370,28 @@ save_image (const gchar *filename,
+ * Fix bit depths for (possibly) smaller colormap images
+ */
+
+- if (info->valid & PNG_INFO_PLTE)
++ bit_depth = 8;
++
++ if (png_get_valid(pp, info, PNG_INFO_PLTE))
+ {
+- if (info->num_palette <= 2)
+- info->bit_depth = 1;
+- else if (info->num_palette <= 4)
+- info->bit_depth = 2;
+- else if (info->num_palette <= 16)
+- info->bit_depth = 4;
++ png_colorp palette;
++ int num_palette;
++ png_get_PLTE(pp, info, &palette, &num_palette);
++
++ if (num_palette <= 2)
++ bit_depth = 1;
++ else if (num_palette <= 4)
++ bit_depth = 2;
++ else if (num_palette <= 16)
++ bit_depth = 4;
+ /* otherwise the default is fine */
+ }
+
++ png_set_IHDR(pp, info,
++ drawable->width, drawable->height, bit_depth, color_type,
++ pngvals.interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
++ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
++
+ /* All this stuff is optional extras, if the user is aiming for smallest
+ possible file size she can turn them all off */
+
+@@ -1476,7 +1505,8 @@ save_image (const gchar *filename,
+ * Convert unpacked pixels to packed if necessary
+ */
+
+- if (info->color_type == PNG_COLOR_TYPE_PALETTE && info->bit_depth < 8)
++ if (png_get_color_type(pp, info) ==
++ PNG_COLOR_TYPE_PALETTE && png_get_bit_depth(pp, info) < 8)
+ png_set_packing (pp);
+
+ /*
+@@ -1528,7 +1558,7 @@ save_image (const gchar *filename,
+
+ /* If we're dealing with a paletted image with
+ * transparency set, write out the remapped palette */
+- if (info->valid & PNG_INFO_tRNS)
++ if (png_get_valid(pp, info, PNG_INFO_tRNS))
+ {
+ guchar inverse_remap[256];
+
+@@ -1548,7 +1578,7 @@ save_image (const gchar *filename,
+ }
+ /* Otherwise if we have a paletted image and transparency
+ * couldn't be set, we ignore the alpha channel */
+- else if (info->valid & PNG_INFO_PLTE && bpp == 2)
++ else if (png_get_valid(pp, info, PNG_INFO_PLTE) && bpp == 2)
+ {
+ for (i = 0; i < num; ++i)
+ {
+@@ -1563,7 +1593,7 @@ save_image (const gchar *filename,
+ png_write_rows (pp, pixels, num);
+
+ gimp_progress_update (((double) pass + (double) end /
+- (double) info->height) /
++ (double) png_get_image_height(pp, info)) /
+ (double) num_passes);
+ }
+ }
+--
+1.7.3.4
+
diff --git a/main/git-manpages/APKBUILD b/main/git-manpages/APKBUILD
new file mode 100644
index 0000000000..ab19a73a92
--- /dev/null
+++ b/main/git-manpages/APKBUILD
@@ -0,0 +1,19 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+pkgname=git-manpages
+pkgver=1.7.4.1
+pkgrel=0
+pkgdesc="Manuals for git"
+url="http://www.git-scm.com"
+arch="noarch"
+license="GPL2"
+depends=
+depends_dev=
+source="http://www.kernel.org/pub/software/scm/git/$pkgname-$pkgver.tar.bz2"
+
+package() {
+ mkdir -p "$pkgdir"/usr/man
+ cp -r "$srcdir"/man* "$pkgdir"/usr/man
+}
+
+md5sums="ac3e15c568e887af4517a01e16671947 git-manpages-1.7.4.1.tar.bz2"
diff --git a/main/git/APKBUILD b/main/git/APKBUILD
new file mode 100644
index 0000000000..b3e0e316e5
--- /dev/null
+++ b/main/git/APKBUILD
@@ -0,0 +1,58 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=git
+pkgver=1.7.6
+pkgrel=0
+pkgdesc="GIT - the stupid content tracker"
+url="http://git.or.cz/"
+arch="all"
+license="GPL2"
+depends=
+replaces="git-perl"
+subpackages="$pkgname-doc $pkgname-perl"
+makedepends="zlib-dev openssl-dev curl-dev expat-dev perl-dev python-dev"
+source="http://kernel.org/pub/software/scm/git/git-$pkgver.tar.bz2
+ bb-tar.patch
+ git-daemon.initd
+ git-daemon.confd
+ "
+
+_makeopts="NO_ICONV=YesPlease
+ NO_NSEC=YesPlease
+ NO_TCLTK=YesPlease
+ NO_SVN_TESTS=YesPlease"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 -i "$srcdir"/bb-tar.patch || return 1
+ make prefix=/usr DESTDIR="$pkgdir" $_makeopts || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make prefix=/usr DESTDIR="$pkgdir" $_makeopts install
+ mkdir -p "$pkgdir"/var/git
+ install -Dm755 "$srcdir"/git-daemon.initd \
+ "$pkgdir"/etc/init.d/git-daemon
+ install -Dm644 "$srcdir"/git-daemon.confd \
+ "$pkgdir"/etc/conf.d/git-daemon
+}
+
+perl() {
+ depends="perl git perl-net-smtp-ssl perl-authen-sasl"
+ pkgdesc="Perl scripts for git"
+ arch="noarch"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/perl* "$subpkgdir"/usr/lib/
+ cd "$pkgdir"
+ find -type f | xargs file --mime-type | grep perl | cut -d: -f1| while read f; do
+ mkdir -p "$subpkgdir"/${f%/*}
+ mv "$f" "$subpkgdir"/${f%/*}
+ done
+ find "$subpkgdir" -name perllocal.pod -delete
+}
+
+
+md5sums="9e0a438eb71e89eedb61f89470ed32a0 git-1.7.6.tar.bz2
+e63a201556c4f089de790805c09a2e5b bb-tar.patch
+3f0bdf6ca73bf4f015bc8565ab787969 git-daemon.initd
+2258e95d389ccc6de0b5111d53d9eed6 git-daemon.confd"
diff --git a/main/git/bb-tar.patch b/main/git/bb-tar.patch
new file mode 100644
index 0000000000..6acfa99170
--- /dev/null
+++ b/main/git/bb-tar.patch
@@ -0,0 +1,8 @@
+--- a/templates/Makefile Mon Oct 26 02:57:33 2009
++++ b/templates/Makefile Mon Nov 9 14:56:27 2009
+@@ -50,4 +50,4 @@
+ install: all
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(template_instdir_SQ)'
+ (cd blt && $(TAR) cf - .) | \
+- (cd '$(DESTDIR_SQ)$(template_instdir_SQ)' && umask 022 && $(TAR) xof -)
++ (cd '$(DESTDIR_SQ)$(template_instdir_SQ)' && umask 022 && $(TAR) xf -)
diff --git a/main/git/git-daemon.confd b/main/git/git-daemon.confd
new file mode 100644
index 0000000000..6369053fc9
--- /dev/null
+++ b/main/git/git-daemon.confd
@@ -0,0 +1,20 @@
+# conf.d file for git-daemon
+#
+# Please check man 1 git-daemon for more information about the options
+# git-daemon accepts. You MUST edit this to include your repositories you wish
+# to serve.
+#
+# Some of the meaningful options are:
+# --syslog --- Enables syslog logging
+# --verbose --- Enables verbose logging
+# --export-all --- Exports all repositories
+# --port=XXXX --- Starts in port XXXX instead of 9418
+#
+GITDAEMON_REPO="/var/git"
+GITDAEMON_OPTS="--syslog --base-path=${GITDAEMON_REPO} ${GITDAEMON_REPO}"
+
+# To run an anonymous git safely, the following user should be able to only
+# read your Git repositories. It should not able able to write to anywhere on
+# your system, esp. not the repositories.
+GIT_USER="nobody"
+GIT_GROUP="nobody"
diff --git a/main/git/git-daemon.initd b/main/git/git-daemon.initd
new file mode 100644
index 0000000000..cb26b512f1
--- /dev/null
+++ b/main/git/git-daemon.initd
@@ -0,0 +1,27 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-vcs/git/files/git-daemon.initd,v 1.1 2010/03/17 15:13:27 sping Exp $
+
+PIDFILE=/var/run/git-daemon.pid
+
+depend() {
+ need net
+ use logger
+}
+
+start() {
+ ebegin "Starting git-daemon"
+ /usr/bin/git daemon --detach \
+ --pid-file=${PIDFILE} \
+ --user=${GIT_USER} --group=${GIT_GROUP} \
+ ${GITDAEMON_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping git-daemon"
+ start-stop-daemon --stop --quiet \
+ --pidfile ${PIDFILE}
+ eend $?
+}
diff --git a/main/glade/APKBUILD b/main/glade/APKBUILD
new file mode 100644
index 0000000000..e30addc1cf
--- /dev/null
+++ b/main/glade/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=glade
+pkgver=3.10.0
+pkgrel=2
+pkgdesc="User Interface Designer for GTK+ and GNOME"
+url="http://glade.gnome.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+3.0-dev libxml2-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/glade/${pkgver%.*}/glade-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="70c61582bdc6e9a852b29f3d172ddd4e glade-3.10.0.tar.bz2"
diff --git a/main/glade3/APKBUILD b/main/glade3/APKBUILD
new file mode 100644
index 0000000000..3290b0d33c
--- /dev/null
+++ b/main/glade3/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=glade3
+pkgver=3.8.0
+pkgrel=3
+pkgdesc="a RAD tool to enable quick & easy development of user interfaces for GTK+"
+url="http://glade.gnome.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+2.0-dev libxml2-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/glade3/${pkgver%.*}/glade3-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-scrollkeeper \
+ --disable-gnome \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/glade3/modules/*.la
+}
+
+md5sums="42f8b2dd01b9bfb8860bb3a5d978e1a2 glade3-3.8.0.tar.bz2"
diff --git a/main/glew/APKBUILD b/main/glew/APKBUILD
new file mode 100644
index 0000000000..26511a6e2c
--- /dev/null
+++ b/main/glew/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=glew
+pkgver=1.6.0
+pkgrel=0
+pkgdesc="A cross-platform C/C++ extension loading library"
+url="http://glew.sourceforge.net"
+arch="all"
+license="GPL"
+depends=
+makedepends="libxmu-dev libxi-dev mesa-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tgz"
+replaces="mesa-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ sed -i 's|lib64|lib|' config/Makefile.linux || return 1
+}
+
+build() {
+ cd "$_builddir"
+ make CFLAGS.EXTRA="$CFLAGS" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make GLEW_DEST="${pkgdir}/usr" install
+ install -D -m644 LICENSE.txt "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
+}
+
+md5sums="7dfbb444b5a4e125bc5dba0aef403082 glew-1.6.0.tgz"
diff --git a/main/glib-networking/APKBUILD b/main/glib-networking/APKBUILD
new file mode 100644
index 0000000000..076332fab4
--- /dev/null
+++ b/main/glib-networking/APKBUILD
@@ -0,0 +1,48 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=glib-networking
+pkgver=2.28.7
+_maj=${pkgver%%.*}
+_min=${pkgver#${_maj}.}
+_min=${_min%%.*}
+_ver=$_maj.$_min
+pkgrel=0
+pkgdesc="Networking support for GLib"
+url="http://www.gnome.org"
+arch="all"
+license="LGPLv2+"
+depends="ca-certificates"
+depends_dev="glib-dev gnutls-dev libproxy-dev intltool"
+makedepends="$depends_dev bash"
+install=
+subpackages=
+source="http://download.gnome.org/sources/glib-networking/$_ver/glib-networking-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ CONFIG_SHELL=/bin/bash ./configure --prefix=/usr \
+ --with-libproxy \
+ --with-gnutls \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/gio/modules/*.a \
+ "$pkgdir"/usr/lib/gio/modules/*.la
+}
+
+md5sums="c10e51571d03c10111a37bcd21fbf777 glib-networking-2.28.7.tar.bz2"
diff --git a/main/glib/APKBUILD b/main/glib/APKBUILD
new file mode 100644
index 0000000000..dec3ec3355
--- /dev/null
+++ b/main/glib/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=glib
+pkgver=2.28.0
+pkgrel=1
+pkgdesc="Common C routines used by Gtk+ and other libs"
+url="http://www.gtk.org"
+arch="all"
+license='GPL'
+depends=
+triggers="$pkgname.trigger:/usr/share/glib-2.0/schemas /usr/lib/gio/modules"
+makedepends="gettext-dev libiconv-dev zlib-dev bzip2-dev pkgconfig"
+source="http://ftp.gnome.org/pub/gnome/sources/glib/${pkgver%.*}/glib-$pkgver.tar.bz2"
+subpackages="$pkgname-doc $pkgname-dev"
+
+depends_dev="perl gettext-dev libiconv-dev zlib-dev bzip2-dev pkgconfig"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ # busybox env does not handle the -w after perl. we remove it for now
+ sed -i -e '1,1s/ -w//' gobject/glib-mkenums.in
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir/" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+# move the stuff in /usr/bin to the glib-dev package
+dev() {
+ default_dev
+ mkdir -p "$subpkgdir"/usr/bin/
+ cd "$pkgdir"/usr/bin
+ mv glib-genmarshal glib-gettextize glib-mkenums gobject-query \
+ gtester gtester-report \
+ "$subpkgdir"/usr/bin/
+}
+
+md5sums="51dbe36bc03a29a1f9bf6b74fb4a6926 glib-2.28.0.tar.bz2"
diff --git a/main/glib/glib.trigger b/main/glib/glib.trigger
new file mode 100644
index 0000000000..04b9f5bd42
--- /dev/null
+++ b/main/glib/glib.trigger
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+for i in "$@"; do
+ case "$i" in
+ */modules)
+ /usr/bin/gio-querymodules "$i"
+ ;;
+ */schemas)
+ /usr/bin/glib-compile-schemas "$i"
+ ;;
+ esac
+done
+
diff --git a/main/glibmm/APKBUILD b/main/glibmm/APKBUILD
new file mode 100644
index 0000000000..e7ca08598b
--- /dev/null
+++ b/main/glibmm/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=glibmm
+pkgver=2.28.2
+pkgrel=1
+pkgdesc="C++ wrapper for the GLib toolkit"
+url="http://gtkmm.sourceforge.net/"
+arch="all"
+license="LGPL"
+depends=
+makedepends="glib-dev libsigc++-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+depends_dev="libsigc++-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+dev() {
+ mkdir -p "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/lib/glibmm-2.4 "$subpkgdir"/usr/lib/
+ default_dev
+}
+
+doc() {
+ default_doc
+ mkdir -p "$subpkgdir"/usr/share/
+ mv "$pkgdir"/usr/share/devhelp "$subpkgdir"/usr/share/
+}
+
+md5sums="cf33d1861d09fb2952a6a1d69e0502e3 glibmm-2.28.2.tar.bz2"
diff --git a/main/glproto/APKBUILD b/main/glproto/APKBUILD
new file mode 100644
index 0000000000..d389e92a39
--- /dev/null
+++ b/main/glproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=glproto
+pkgver=1.4.12
+pkgrel=1
+pkgdesc="X11 OpenGL extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="55edc5ff2efb734215c868f72f7cf27e glproto-1.4.12.tar.bz2"
diff --git a/main/gmp5/APKBUILD b/main/gmp5/APKBUILD
new file mode 100644
index 0000000000..d7dc51b351
--- /dev/null
+++ b/main/gmp5/APKBUILD
@@ -0,0 +1,55 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+_name=gmp
+pkgname=${_name}5
+
+pkgver=5.0.1
+pkgrel=3
+pkgdesc="A free library for arbitrary precision arithmetic"
+url="http://gmplib.org/"
+arch="all"
+license="LGPL3"
+makedepends="m4 texinfo"
+depends=
+subpackages="$pkgname-doc gmp-dev libgmpxx"
+source="ftp://ftp.gnu.org/gnu/gmp/gmp-$pkgver.tar.bz2
+ gmp-4.1.4-noexecstack.patch
+ "
+
+_builddir="$srcdir"/$_name-$pkgver
+build() {
+ cd "$_builddir"
+ patch -p1 < "$srcdir"/gmp-4.1.4-noexecstack.patch || return 1
+
+ ./configure --prefix=/usr \
+ --build=${CBUILD} \
+ --host=${CHOST} \
+ --infodir=/usr/share/info \
+ --mandir=/usr/share/man \
+ --localstatedir=/var/state/gmp \
+ --enable-mpbsd \
+ --enable-cxx \
+ --with-pic \
+ || return 1
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="${pkgdir}" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+dev() {
+ replaces="gmp gmp5-dev"
+ default_dev
+}
+
+libgmpxx() {
+ pkgdesc="C++ support for gmp"
+ mkdir -p "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/lib/libgmpxx.so.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="6bac6df75c192a13419dfd71d19240a7 gmp-5.0.1.tar.bz2
+13c34f00e77ded6673270cfea06c35c3 gmp-4.1.4-noexecstack.patch"
diff --git a/main/gmp5/gmp-4.1.4-noexecstack.patch b/main/gmp5/gmp-4.1.4-noexecstack.patch
new file mode 100644
index 0000000000..093bec1a5d
--- /dev/null
+++ b/main/gmp5/gmp-4.1.4-noexecstack.patch
@@ -0,0 +1,20 @@
+fixed executable stack
+
+http://bugs.gentoo.org/115038
+
+--- gmp-4.1.4/configure
++++ gmp-4.1.4/configure
+@@ -21689,6 +21689,13 @@
+ fi
+ echo "')" >> $gmp_configm4
+ echo "define(\`__CONFIG_M4_INCLUDED__')" >> $gmp_configm4
++# Gentoo hack
++case $host_os in
++ *linux*)
++ echo '.section .note.GNU-stack,"",%progbits' >> $gmp_configm4
++ echo '.previous' >> $gmp_configm4
++ ;;
++esac
+
+ # Create Makefiles
+ # FIXME: Upcoming version of autoconf/automake may not like broken lines.
diff --git a/main/gnats/APKBUILD b/main/gnats/APKBUILD
new file mode 100644
index 0000000000..9b4460809e
--- /dev/null
+++ b/main/gnats/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnats
+pkgver=4.1.0
+pkgrel=4
+pkgdesc="The GNU Bug Tracking System"
+url="http://www.gnu.org/software/gnats/"
+arch="all"
+license="GPL-2"
+depends="postfix"
+makedepends="texinfo"
+install="gnats.pre-install"
+source="http://ftp.gnu.org/pub/gnu/$pkgname/$pkgname-$pkgver.tar.gz
+ $install"
+subpackages="$pkgname-doc"
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ # make install needs gnats user
+ sudo sh $srcdir/$install pre_install || return 1
+
+ AWK=awk ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --sharedstatedir=/var/lib \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+
+ make || return 1
+ make DESTDIR="$pkgdir/" install
+ rm -f "$pkgdir"/gnats.el
+}
+
+md5sums="2add3df79336f2e193c8a9a513aefe22 gnats-4.1.0.tar.gz
+4ccae685ca8d5ed857c2a26f1e2fbc7c gnats.pre-install"
diff --git a/main/gnats/gnats.pre-install b/main/gnats/gnats.pre-install
new file mode 100644
index 0000000000..0a2e5a589b
--- /dev/null
+++ b/main/gnats/gnats.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -h /var/lib/gnatsdb -D gnats 2>/dev/null
+exit 0
diff --git a/main/gnokii/APKBUILD b/main/gnokii/APKBUILD
new file mode 100644
index 0000000000..8691b7a138
--- /dev/null
+++ b/main/gnokii/APKBUILD
@@ -0,0 +1,83 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnokii
+pkgver=0.6.30
+pkgrel=3
+pkgdesc="Tools and user space driver for use with mobile phones"
+url="http://www.gnokii.org/"
+arch="all"
+license="GPL"
+depends=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-libs xgnokii $pkgname-smsd
+ $pkgname-smsd-pgsql:pgsql $pkgname-smsd-mysql:mysql
+ $pkgname-smsd-sqlite:sqlite"
+
+makedepends="gtk+-dev mysql-dev intltool libusb-compat-dev libxpm-dev
+ bluez-dev libical-dev postgresql-dev sqlite-dev"
+source="http://www.gnokii.org/download/gnokii/gnokii-$pkgver.tar.bz2
+ gnokii.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ sed -i 's|cellphone|phone|' xgnokii/xgnokii.desktop.in
+ patch -Np1 -i "$srcdir/gnokii.patch"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-security \
+ --disable-unix98test \
+ --disable-phonet \
+ || return 1
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+libs() {
+ pkgdesc="gnokii shared libraries"
+ replaces="libgnokii"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libgnokii.so.* "$subpkgdir"/usr/lib/
+}
+
+xgnokii() {
+ pkgdesk="Gtk+ gnokii application"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/xgnokii "$subpkgdir"/usr/bin/
+}
+
+smsd() {
+ pkgdesc="SMS Daemon for mobile phones"
+ mkdir -p "$subpkgdir"/usr/bin/
+ mv "$pkgdir"/usr/bin/smsd "$subpkgdir"/usr/bin/
+}
+
+pgsql() {
+ pkgdesc="SMSD plugin for PostgreSQL storage backend"
+ depends="gnokii-smsd"
+ mkdir -p "$subpkgdir"/usr/lib/smsd
+ mv "$pkgdir"/usr/lib/smsd/*pq.so "$subpkgdir"/usr/lib/smsd/
+}
+
+mysql() {
+ pkgdesc="SMSD plugin for MySQL storage backend"
+ depends="gnokii-smsd"
+ mkdir -p "$subpkgdir"/usr/lib/smsd
+ mv "$pkgdir"/usr/lib/smsd/*mysql.so "$subpkgdir"/usr/lib/smsd/
+}
+
+sqlite() {
+ pkgdesc="SMSD plugin for SQLite storage backend"
+ depends="gnokii-smsd"
+ mkdir -p "$subpkgdir"/usr/lib/smsd
+ mv "$pkgdir"/usr/lib/smsd/*sqlite*.so "$subpkgdir"/usr/lib/smsd/
+}
+md5sums="c90137d403febbc16712d64f0eb196de gnokii-0.6.30.tar.bz2
+4d764727686ee34bc73489c8b1321c82 gnokii.patch"
diff --git a/main/gnokii/gnokii.patch b/main/gnokii/gnokii.patch
new file mode 100644
index 0000000000..e64d81aa12
--- /dev/null
+++ b/main/gnokii/gnokii.patch
@@ -0,0 +1,12 @@
+diff -ur gnokii-0.6.7-old/Docs/sample/gnokiirc gnokii-0.6.7/Docs/sample/gnokiirc
+--- gnokii-0.6.7-old/Docs/sample/gnokiirc 2005-05-16 20:55:13.000000000 +0200
++++ gnokii-0.6.7/Docs/sample/gnokiirc 2005-06-03 10:49:42.000000000 +0200
+@@ -112,7 +112,7 @@
+ # permissions 4750, owned by root, group gnokii. Ensure you
+ # are in the gnokii group and that the group exists...
+ [gnokiid]
+-bindir = /usr/local/sbin/
++bindir = /usr/sbin/
+
+ # Any entries in the following two sections will be set as environment
+ # variables when running the scripts.
diff --git a/main/gnome-base/APKBUILD b/main/gnome-base/APKBUILD
new file mode 100644
index 0000000000..18f690bbc6
--- /dev/null
+++ b/main/gnome-base/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-base
+pkgver=2.32.0
+pkgrel=0
+pkgdesc="GNOME metapackage (base)"
+url="http://www.gnome.org/"
+arch="noarch"
+license="GPL"
+depends="metacity
+ nautilus
+
+ gnome-session
+ gnome-themes
+ gnome-screensaver
+ gnome-power-manager
+ gnome-settings-daemon
+ gnome-control-center
+ gnome-desktop
+
+ gnome-system-monitor
+ gnome-panel
+ gnome-terminal"
+depends_dev=
+makedepends=
+install=""
+subpackages=
+source=""
+
+build() {
+ mkdir -p "$pkgdir"
+}
+
+md5sums=""
diff --git a/main/gnome-bluetooth/61-gnome-bluetooth-rfkill.rules b/main/gnome-bluetooth/61-gnome-bluetooth-rfkill.rules
new file mode 100644
index 0000000000..a76c1e73cf
--- /dev/null
+++ b/main/gnome-bluetooth/61-gnome-bluetooth-rfkill.rules
@@ -0,0 +1,11 @@
+# Get access to /dev/rfkill for users
+# See https://bugzilla.redhat.com/show_bug.cgi?id=514798
+#
+# Updated for udev >= 154
+# http://bugs.debian.org/582188
+# https://bugzilla.redhat.com/show_bug.cgi?id=588660
+
+ENV{ACL_MANAGE}=="0", GOTO="gnome_bluetooth_end"
+ACTION!="add|change", GOTO="gnome_bluetooth_end"
+KERNEL=="rfkill", TAG+="udev-acl"
+LABEL="gnome_bluetooth_end"
diff --git a/main/gnome-bluetooth/APKBUILD b/main/gnome-bluetooth/APKBUILD
new file mode 100644
index 0000000000..72e3f960b9
--- /dev/null
+++ b/main/gnome-bluetooth/APKBUILD
@@ -0,0 +1,56 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnome-bluetooth
+pkgver=2.32.0
+pkgrel=2
+pkgdesc="The GNOME Bluetooth Subsystem"
+url="http://live.gnome.org/GnomeBluetooth"
+arch="all"
+license="GPL LGPL"
+depends="hicolor-icon-theme obexd-client obex-data-server"
+makedepends="intltool py-gtk gobject-introspection-dev libunique-dev libnotify-dev
+ libxi-dev libxslt py-libxml2 gnome-doc-utils"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/gnome-bluetooth/${pkgver%.*}/gnome-bluetooth-$pkgver.tar.bz2
+ nogeoclue.patch
+ 61-gnome-bluetooth-rfkill.rules"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-desktop-update \
+ --disable-icon-update \
+ --disable-nautilus-sendto \
+ --disable-schemas-compile \
+ --disable-introspection \
+ --disable-scrollkeeper \
+ || return 1
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+ install -m644 -D "$srcdir/61-gnome-bluetooth-rfkill.rules" \
+ "$pkgdir/lib/udev/rules.d/61-gnome-bluetooth-rfkill.rules"
+}
+
+md5sums="f129686fe46c4c98eb70a0cc85d59cae gnome-bluetooth-2.32.0.tar.bz2
+5ed6f59d02b45573a08155fca8f0d300 nogeoclue.patch
+9fb6c8dcb5a3de3a953bf2ef42063e6e 61-gnome-bluetooth-rfkill.rules"
diff --git a/main/gnome-bluetooth/nogeoclue.patch b/main/gnome-bluetooth/nogeoclue.patch
new file mode 100644
index 0000000000..2892bee0ca
--- /dev/null
+++ b/main/gnome-bluetooth/nogeoclue.patch
@@ -0,0 +1,138 @@
+--- gnome-bluetooth-2.32.0.orig/configure
++++ gnome-bluetooth-2.32.0/configure
+@@ -638,8 +638,6 @@
+ MOBLIN_CFLAGS
+ PLUGINS_LIBS
+ PLUGINS_CFLAGS
+-GEOCLUE_LIBS
+-GEOCLUE_CFLAGS
+ COMMON_LIBS
+ COMMON_CFLAGS
+ LIBGNOMEBT_LIBS
+@@ -899,8 +897,6 @@
+ LIBGNOMEBT_LIBS
+ COMMON_CFLAGS
+ COMMON_LIBS
+-GEOCLUE_CFLAGS
+-GEOCLUE_LIBS
+ PLUGINS_CFLAGS
+ PLUGINS_LIBS
+ MOBLIN_CFLAGS
+@@ -13662,106 +13658,6 @@
+
+ fi
+
+-
+-pkg_failed=no
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GEOCLUE" >&5
+-$as_echo_n "checking for GEOCLUE... " >&6; }
+-
+-if test -n "$GEOCLUE_CFLAGS"; then
+- pkg_cv_GEOCLUE_CFLAGS="$GEOCLUE_CFLAGS"
+- elif test -n "$PKG_CONFIG"; then
+- if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gconf-2.0
+- dbus-glib-1\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "gconf-2.0
+- dbus-glib-1") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; then
+- pkg_cv_GEOCLUE_CFLAGS=`$PKG_CONFIG --cflags "gconf-2.0
+- dbus-glib-1" 2>/dev/null`
+-else
+- pkg_failed=yes
+-fi
+- else
+- pkg_failed=untried
+-fi
+-if test -n "$GEOCLUE_LIBS"; then
+- pkg_cv_GEOCLUE_LIBS="$GEOCLUE_LIBS"
+- elif test -n "$PKG_CONFIG"; then
+- if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gconf-2.0
+- dbus-glib-1\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "gconf-2.0
+- dbus-glib-1") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; then
+- pkg_cv_GEOCLUE_LIBS=`$PKG_CONFIG --libs "gconf-2.0
+- dbus-glib-1" 2>/dev/null`
+-else
+- pkg_failed=yes
+-fi
+- else
+- pkg_failed=untried
+-fi
+-
+-
+-
+-if test $pkg_failed = yes; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-
+-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+- _pkg_short_errors_supported=yes
+-else
+- _pkg_short_errors_supported=no
+-fi
+- if test $_pkg_short_errors_supported = yes; then
+- GEOCLUE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gconf-2.0
+- dbus-glib-1" 2>&1`
+- else
+- GEOCLUE_PKG_ERRORS=`$PKG_CONFIG --print-errors "gconf-2.0
+- dbus-glib-1" 2>&1`
+- fi
+- # Put the nasty error message in config.log where it belongs
+- echo "$GEOCLUE_PKG_ERRORS" >&5
+-
+- as_fn_error $? "Package requirements (gconf-2.0
+- dbus-glib-1) were not met:
+-
+-$GEOCLUE_PKG_ERRORS
+-
+-Consider adjusting the PKG_CONFIG_PATH environment variable if you
+-installed software in a non-standard prefix.
+-
+-Alternatively, you may set the environment variables GEOCLUE_CFLAGS
+-and GEOCLUE_LIBS to avoid the need to call pkg-config.
+-See the pkg-config man page for more details." "$LINENO" 5
+-
+-elif test $pkg_failed = untried; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+-as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+-is in your PATH or set the PKG_CONFIG environment variable to the full
+-path to pkg-config.
+-
+-Alternatively, you may set the environment variables GEOCLUE_CFLAGS
+-and GEOCLUE_LIBS to avoid the need to call pkg-config.
+-See the pkg-config man page for more details.
+-
+-To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+-See \`config.log' for more details" "$LINENO" 5; }
+-
+-else
+- GEOCLUE_CFLAGS=$pkg_cv_GEOCLUE_CFLAGS
+- GEOCLUE_LIBS=$pkg_cv_GEOCLUE_LIBS
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-$as_echo "yes" >&6; }
+-
+-fi
+
+
+ pkg_failed=no
+--- gnome-bluetooth-2.32.0.orig/lib/Makefile.in
++++ gnome-bluetooth-2.32.0/lib/Makefile.in
+@@ -383,7 +383,7 @@
+ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+-SUBDIRS = plugins
++SUBDIRS =
+ EXTRA_DIST = $(am__append_2) marshal.list bluetooth-client.xml \
+ bluetooth-agent.xml obex-agent.xml gnome-bluetooth.symbols
+ BUILT_GIRSOURCES = $(am__append_1)
diff --git a/main/gnome-control-center/APKBUILD b/main/gnome-control-center/APKBUILD
new file mode 100644
index 0000000000..a288d3e61a
--- /dev/null
+++ b/main/gnome-control-center/APKBUILD
@@ -0,0 +1,69 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-control-center
+pkgver=2.32.1
+pkgrel=3
+pkgdesc="GNOME configuration applets"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ gnome-desktop-dev
+ libwnck-dev
+ librsvg-dev
+ libunique-dev
+
+ gnome-menus-dev
+ gnome-settings-daemon-dev
+ metacity-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev
+
+ libgnomekbd-dev
+ libxklavier-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev desktop-file-utils"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+
+ rm -rf ${pkgdir}/usr/share/mime
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="b4e8ab5c7556ae07addbfcfb4fa2f761 gnome-control-center-2.32.1.tar.bz2"
diff --git a/main/gnome-control-center/gnome-control-center.post-install b/main/gnome-control-center/gnome-control-center.post-install
new file mode 100644
index 0000000000..98f2aac0e9
--- /dev/null
+++ b/main/gnome-control-center/gnome-control-center.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in control-center.schemas fontilus.schemas gnome-control-center.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-control-center/gnome-control-center.post-upgrade b/main/gnome-control-center/gnome-control-center.post-upgrade
new file mode 100644
index 0000000000..98f2aac0e9
--- /dev/null
+++ b/main/gnome-control-center/gnome-control-center.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in control-center.schemas fontilus.schemas gnome-control-center.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-control-center/gnome-control-center.pre-deinstall b/main/gnome-control-center/gnome-control-center.pre-deinstall
new file mode 100644
index 0000000000..9b03979ce7
--- /dev/null
+++ b/main/gnome-control-center/gnome-control-center.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in control-center.schemas fontilus.schemas gnome-control-center.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-desktop/APKBUILD b/main/gnome-desktop/APKBUILD
new file mode 100644
index 0000000000..fd4e2cb527
--- /dev/null
+++ b/main/gnome-desktop/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-desktop
+pkgver=2.32.1
+pkgrel=5
+pkgdesc="GNOME deskop framework"
+url="http://projects.gnome.org/gnome-panel"
+arch="all"
+license="GPL"
+depends="python py-gtk"
+depends_dev="gtk+-dev gconf-dev libx11-dev gnome-doc-utils libgnome-dev python-dev libxrandr-dev"
+makedepends="$depends_dev intltool"
+install=
+subpackages="$pkgname-doc $pkgname-dev"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --with-gnome-distributor=Alpine \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="5c80d628a240eb9d9ff78913b31f2f67 gnome-desktop-2.32.1.tar.bz2"
diff --git a/main/gnome-disk-utility/APKBUILD b/main/gnome-disk-utility/APKBUILD
new file mode 100644
index 0000000000..30c145aeb0
--- /dev/null
+++ b/main/gnome-disk-utility/APKBUILD
@@ -0,0 +1,61 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnome-disk-utility
+pkgver=2.32.0
+pkgrel=1
+pkgdesc="GNOME libraries and applications for dealing with storage devices"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+depends=""
+makedepends="gnome-doc-utils intltool dbus-glib-dev libunique-dev avahi-dev
+ udisks-dev libnotify-dev hicolor-icon-theme libatasmart-dev
+ rarian-dev libxslt"
+install=
+subpackages="$pkgname-dev $pkgname-libs $pkgname-ui-libs:uilibs"
+source="http://ftp.gnome.org/pub/GNOME/sources/gnome-disk-utility/${pkgver%.*}/gnome-disk-utility-$pkgver.tar.bz2
+ fix-freeze.patch
+ exp2.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -Np1 -i "$srcdir/fix-freeze.patch"
+ patch -Np1 -i "$srcdir/exp2.patch"
+}
+
+build ()
+{
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --libexecdir=/usr/lib/gnome-disk-utility \
+ --disable-scrollkeeper \
+ --disable-nautilus \
+ --disable-gtk-doc
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+libs() {
+ pkgdesc="Shared libraries used by Palimpsest"
+ mkdir -p "$subpkgdir"/usr/lib \
+ "$subpkgdir"/usr/share
+ mv "$pkgdir"/usr/lib/libgdu.so.* "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/share/icons "$subpkgdir"/usr/share/
+}
+
+uilibs() {
+ pkgdesc="Shared libraries used by Palimpsest"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libgdu-gtk.so.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="f0366c8baebca0404d190b2d78f3582d gnome-disk-utility-2.32.0.tar.bz2
+c0161b09b620ef9c3975db400518eb1f fix-freeze.patch
+ac7d749bb6fa2e31bffb1f47822bc22b exp2.patch"
diff --git a/main/gnome-disk-utility/exp2.patch b/main/gnome-disk-utility/exp2.patch
new file mode 100644
index 0000000000..4499803628
--- /dev/null
+++ b/main/gnome-disk-utility/exp2.patch
@@ -0,0 +1,16 @@
+--- ./src/gdu-gtk/gdu-size-widget.c.orig
++++ ./src/gdu-gtk/gdu-size-widget.c
+@@ -564,11 +564,11 @@
+
+ shown_extent = extent / unit_factor;
+
+- increment = (exp10 (floor (log10 (shown_extent))) / 10.0) * unit_factor;
++ increment = (exp2 (floor (log2 (shown_extent))) / 2.0) * unit_factor;
+
+ gtk_range_set_increments (GTK_RANGE (widget->priv->hscale),
+ increment,
+- increment * 10.0);
++ increment * 2.0);
+ }
+
+
diff --git a/main/gnome-disk-utility/fix-freeze.patch b/main/gnome-disk-utility/fix-freeze.patch
new file mode 100644
index 0000000000..262748bfb6
--- /dev/null
+++ b/main/gnome-disk-utility/fix-freeze.patch
@@ -0,0 +1,32 @@
+From 82489b51443e1280dfb9fb251ea2693df1809aec Mon Sep 17 00:00:00 2001
+From: Pascal Terjan <pterjan@mandriva.com>
+Date: Mon, 3 May 2010 14:01:22 +0200
+Subject: [PATCH] Force GduPresentable ids to be UTF-8 (#616198)
+
+GduPresentable created in gdu pool include intheir id some strings
+in local encoding like _("Peripheral Devices"). This patch
+enforces them to be UTF-8.
+
+This fixes a crash of gvfs-gdu-volume-monitor when USB devices are
+available on a non UTF-8 system.
+---
+ src/gdu/gdu-pool.c | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/src/gdu/gdu-pool.c b/src/gdu/gdu-pool.c
+index bd5eccf..cf6be53 100644
+--- a/src/gdu/gdu-pool.c
++++ b/src/gdu/gdu-pool.c
+@@ -473,6 +473,9 @@ gdu_pool_class_init (GduPoolClass *klass)
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GDU_TYPE_PRESENTABLE);
++#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
++ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
++#endif
+ }
+
+ static void
+--
+1.7.1
+
diff --git a/main/gnome-doc-utils/APKBUILD b/main/gnome-doc-utils/APKBUILD
new file mode 100644
index 0000000000..2f293f1d74
--- /dev/null
+++ b/main/gnome-doc-utils/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnome-doc-utils
+pkgver=0.20.6
+pkgrel=1
+pkgdesc="Documentation utilities for Gnome"
+url="http://www.gnome.org"
+arch="all"
+license="GPL LGPL"
+depends="python docbook-xml rarian py-libxml2 libxslt"
+makedepends="libxslt-dev libxml2-dev perl-xml-parser rarian-dev pkgconfig
+ gettext-dev intltool"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2
+ xslt.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -p1 -i "$srcdir"/xslt.patch
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --localstatedir=/var \
+ --disable-scrollkeeper || return 1
+ # broken with parallell builds
+ make -j1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="8f6e05071599bc073007830ea0a68391 gnome-doc-utils-0.20.6.tar.bz2
+6aa99cdd5dec2eb887f7ca4976ec840e xslt.patch"
diff --git a/main/gnome-doc-utils/xslt.patch b/main/gnome-doc-utils/xslt.patch
new file mode 100644
index 0000000000..bc9784fdf9
--- /dev/null
+++ b/main/gnome-doc-utils/xslt.patch
@@ -0,0 +1,17 @@
+--- gnome-doc-utils-0.18.1/doc/xslt/Makefile.in.orig
++++ gnome-doc-utils-0.18.1/doc/xslt/Makefile.in
+@@ -947,11 +947,11 @@
+ all: $(xsldoc_docs) $(xsldoc_xmls)
+
+ $(xsldoc_docs): $(xsldoc_xsls) xsldoc.awk xsldoc-fill.xsl
+- $(GDU_AWK) -f "$(srcdir)/xsldoc.awk" "$(filter %/$(basename $(notdir $@)).xsl,$(xsldoc_xsls))" \
+- | xsltproc -o "$@" \
++ $(GDU_AWK) -f "$(srcdir)/xsldoc.awk" "$(filter %/$(basename $(notdir $@)).xsl,$(xsldoc_xsls))" > $@.tmp
++ xsltproc -o "$@" \
+ --stringparam basename "$(basename $(notdir $@))" \
+ --stringparam xsl_file "$(filter %/$(basename $(notdir $@)).xsl,$(xsldoc_xsls))" \
+- "$(srcdir)/xsldoc-fill.xsl" -
++ "$(srcdir)/xsldoc-fill.xsl" $@.tmp && rm -f $@.tmp
+
+ $(xsldoc_xmls): xsldoc-docbook.xsl
+ $(xsldoc_xmls): C/%.xml : C/%.xsldoc
diff --git a/main/gnome-icon-theme/APKBUILD b/main/gnome-icon-theme/APKBUILD
new file mode 100644
index 0000000000..b401a3aff8
--- /dev/null
+++ b/main/gnome-icon-theme/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-icon-theme
+pkgver=2.31.0
+pkgrel=0
+pkgdesc="icons for GNOME desktop environment"
+url="http://art.gnome.org/"
+arch="noarch"
+license="GPL"
+depends=
+depends_dev=
+makedepends="intltool icon-naming-utils"
+install=
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="8e727703343d4c18c73c79dd2009f8ed gnome-icon-theme-2.31.0.tar.bz2"
diff --git a/main/gnome-keyring/APKBUILD b/main/gnome-keyring/APKBUILD
new file mode 100644
index 0000000000..3fe0a221f1
--- /dev/null
+++ b/main/gnome-keyring/APKBUILD
@@ -0,0 +1,60 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-keyring
+pkgver=2.32.1
+pkgrel=1
+pkgdesc="GNOME keyring"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ libwnck-dev
+
+ libgcrypt-dev
+ libtasn1-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install=
+subpackages="$pkgname-dev"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="9a8aa74e03361676f29d6e73155786fc gnome-keyring-2.32.1.tar.bz2"
diff --git a/main/gnome-menus/APKBUILD b/main/gnome-menus/APKBUILD
new file mode 100644
index 0000000000..0488fd0103
--- /dev/null
+++ b/main/gnome-menus/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-menus
+pkgver=2.30.5
+pkgrel=4
+pkgdesc="freedesktop.org XDG menu specification for GNOME"
+url="http://projects.gnome.org/gnome-menus"
+arch="all"
+license="GPL"
+depends="python"
+depends_dev="libgnome-dev python-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install=
+subpackages="$pkgname-dev"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="caa6772e63ed5870cf43dc3d354e0624 gnome-menus-2.30.5.tar.bz2"
diff --git a/main/gnome-mime-data/APKBUILD b/main/gnome-mime-data/APKBUILD
new file mode 100644
index 0000000000..ab4a86e39b
--- /dev/null
+++ b/main/gnome-mime-data/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-mime-data
+pkgver=2.18.0
+pkgrel=0
+pkgdesc="MIME data for GNOME environment"
+url="http://www.gnome.org/"
+arch="noarch"
+license="LGPL"
+depends=
+depends_dev=
+makedepends="glib-dev intltool"
+install=""
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="541858188f80090d12a33b5a7c34d42c gnome-mime-data-2.18.0.tar.bz2"
diff --git a/main/gnome-panel/APKBUILD b/main/gnome-panel/APKBUILD
new file mode 100644
index 0000000000..92db6be88f
--- /dev/null
+++ b/main/gnome-panel/APKBUILD
@@ -0,0 +1,54 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-panel
+pkgver=2.32.1
+pkgrel=9
+pkgdesc="GNOME Panel"
+url="http://projects.gnome.org/gnome-panel"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ gnome-desktop-dev
+ gnome-menus-dev
+ libwnck-dev
+ librsvg-dev
+ libgweather-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages="$pkgname-dev"
+replaces_dev="$pkgname"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="a228035e1f7026abf296b797f1f7d2f9 gnome-panel-2.32.1.tar.bz2"
diff --git a/main/gnome-panel/gnome-panel.post-install b/main/gnome-panel/gnome-panel.post-install
new file mode 100644
index 0000000000..06060f9059
--- /dev/null
+++ b/main/gnome-panel/gnome-panel.post-install
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+for i in \
+ clock.schemas \
+ fish.schemas \
+ panel-compatibility.schemas \
+ panel-general.schemas \
+ panel-global.schemas \
+ panel-object.schemas \
+ panel-toplevel.schemas \
+ window-list.schemas \
+ workspace-switcher.schemas \
+; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
+
+GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source`
+echo "Installing GConf2 default entries to ${GCONF_CONFIG_SOURCE}"
+/usr/bin/gconftool-2 --config-source="${GCONF_CONFIG_SOURCE}" --direct --load /etc/gconf/schemas/panel-default-setup.entries >/dev/null
diff --git a/main/gnome-panel/gnome-panel.post-upgrade b/main/gnome-panel/gnome-panel.post-upgrade
new file mode 100644
index 0000000000..06060f9059
--- /dev/null
+++ b/main/gnome-panel/gnome-panel.post-upgrade
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+for i in \
+ clock.schemas \
+ fish.schemas \
+ panel-compatibility.schemas \
+ panel-general.schemas \
+ panel-global.schemas \
+ panel-object.schemas \
+ panel-toplevel.schemas \
+ window-list.schemas \
+ workspace-switcher.schemas \
+; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
+
+GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source`
+echo "Installing GConf2 default entries to ${GCONF_CONFIG_SOURCE}"
+/usr/bin/gconftool-2 --config-source="${GCONF_CONFIG_SOURCE}" --direct --load /etc/gconf/schemas/panel-default-setup.entries >/dev/null
diff --git a/main/gnome-panel/gnome-panel.pre-deinstall b/main/gnome-panel/gnome-panel.pre-deinstall
new file mode 100644
index 0000000000..96aa7274d4
--- /dev/null
+++ b/main/gnome-panel/gnome-panel.pre-deinstall
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+for i in \
+ clock.schemas \
+ fish.schemas \
+ panel-compatibility.schemas \
+ panel-general.schemas \
+ panel-global.schemas \
+ panel-object.schemas \
+ panel-toplevel.schemas \
+ window-list.schemas \
+ workspace-switcher.schemas \
+; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
+
+GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source`
+echo "Uninstalling GConf2 default entries from ${GCONF_CONFIG_SOURCE}"
+/usr/bin/gconftool-2 --config-source="${GCONF_CONFIG_SOURCE}" --direct --unload /etc/gconf/schemas/panel-default-setup.entries >/dev/null
diff --git a/main/gnome-power-manager/APKBUILD b/main/gnome-power-manager/APKBUILD
new file mode 100644
index 0000000000..090587235d
--- /dev/null
+++ b/main/gnome-power-manager/APKBUILD
@@ -0,0 +1,66 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-power-manager
+pkgver=2.32.0
+pkgrel=0
+pkgdesc="GNOME power manager"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ libwnck-dev
+ libnotify-dev
+ libunique-dev
+
+ upower-dev
+ libgnome-keyring-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev
+ libxrender-dev
+ libxrandr-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2
+ execinfo.patch"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-applets \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="9a08e85dce3ffb90775f15e3bda4adda gnome-power-manager-2.32.0.tar.bz2
+f7500645244232328869d303cc6860aa execinfo.patch"
diff --git a/main/gnome-power-manager/execinfo.patch b/main/gnome-power-manager/execinfo.patch
new file mode 100644
index 0000000000..c9def1be10
--- /dev/null
+++ b/main/gnome-power-manager/execinfo.patch
@@ -0,0 +1,26 @@
+--- gnome-power-manager-2.32.0.orig/src/egg-debug.c
++++ gnome-power-manager-2.32.0/src/egg-debug.c
+@@ -39,7 +39,6 @@
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <time.h>
+-#include <execinfo.h>
+
+ #include "egg-debug.h"
+
+@@ -78,6 +77,7 @@
+ void
+ egg_debug_backtrace (void)
+ {
++#if 0
+ void *call_stack[512];
+ int call_stack_size;
+ char **symbols;
+@@ -95,6 +95,7 @@
+ pk_set_console_mode (CONSOLE_RESET);
+ free (symbols);
+ }
++#endif
+ }
+
+ /**
diff --git a/main/gnome-power-manager/gnome-power-manager.post-install b/main/gnome-power-manager/gnome-power-manager.post-install
new file mode 100644
index 0000000000..8d6b50a50e
--- /dev/null
+++ b/main/gnome-power-manager/gnome-power-manager.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-power-manager.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-power-manager/gnome-power-manager.post-upgrade b/main/gnome-power-manager/gnome-power-manager.post-upgrade
new file mode 100644
index 0000000000..8d6b50a50e
--- /dev/null
+++ b/main/gnome-power-manager/gnome-power-manager.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-power-manager.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-power-manager/gnome-power-manager.pre-deinstall b/main/gnome-power-manager/gnome-power-manager.pre-deinstall
new file mode 100644
index 0000000000..ed1e2c420a
--- /dev/null
+++ b/main/gnome-power-manager/gnome-power-manager.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-power-manager.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-screensaver/APKBUILD b/main/gnome-screensaver/APKBUILD
new file mode 100644
index 0000000000..1b675a89ca
--- /dev/null
+++ b/main/gnome-screensaver/APKBUILD
@@ -0,0 +1,64 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-screensaver
+pkgver=2.30.2
+pkgrel=0
+pkgdesc="GNOME screensaver collection"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ libwnck-dev
+ libnotify-dev
+ libunique-dev
+
+ gnome-desktop-dev
+ gnome-menus-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev
+ libxrender-dev
+ libxrandr-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-applets \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="0fbe6e610e6847ac1e69d49b1e1f0582 gnome-screensaver-2.30.2.tar.bz2"
diff --git a/main/gnome-screensaver/gnome-screensaver.post-install b/main/gnome-screensaver/gnome-screensaver.post-install
new file mode 100644
index 0000000000..49ca99c158
--- /dev/null
+++ b/main/gnome-screensaver/gnome-screensaver.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-screensaver.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-screensaver/gnome-screensaver.post-upgrade b/main/gnome-screensaver/gnome-screensaver.post-upgrade
new file mode 100644
index 0000000000..49ca99c158
--- /dev/null
+++ b/main/gnome-screensaver/gnome-screensaver.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-screensaver.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-screensaver/gnome-screensaver.pre-deinstall b/main/gnome-screensaver/gnome-screensaver.pre-deinstall
new file mode 100644
index 0000000000..1aebff8243
--- /dev/null
+++ b/main/gnome-screensaver/gnome-screensaver.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-screensaver.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-session/APKBUILD b/main/gnome-session/APKBUILD
new file mode 100644
index 0000000000..b450f97e8c
--- /dev/null
+++ b/main/gnome-session/APKBUILD
@@ -0,0 +1,53 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-session
+pkgver=2.32.1
+pkgrel=0
+pkgdesc="GNOME session manager"
+url="http://www.gnome.org/"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ gnome-desktop-dev
+ libwnck-dev
+ librsvg-dev
+ libxcomposite-dev
+ upower-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-compositor \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="222bad6b446cb19a6b9028ea24538002 gnome-session-2.32.1.tar.bz2"
diff --git a/main/gnome-session/gnome-session.post-install b/main/gnome-session/gnome-session.post-install
new file mode 100644
index 0000000000..b64d264717
--- /dev/null
+++ b/main/gnome-session/gnome-session.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-session.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-session/gnome-session.post-upgrade b/main/gnome-session/gnome-session.post-upgrade
new file mode 100644
index 0000000000..b64d264717
--- /dev/null
+++ b/main/gnome-session/gnome-session.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-session.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-session/gnome-session.pre-deinstall b/main/gnome-session/gnome-session.pre-deinstall
new file mode 100644
index 0000000000..59f0672e52
--- /dev/null
+++ b/main/gnome-session/gnome-session.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-session.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-settings-daemon/APKBUILD b/main/gnome-settings-daemon/APKBUILD
new file mode 100644
index 0000000000..943a0fe521
--- /dev/null
+++ b/main/gnome-settings-daemon/APKBUILD
@@ -0,0 +1,64 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-settings-daemon
+pkgver=2.32.1
+pkgrel=2
+pkgdesc="GNOME settings daemon"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ gnome-desktop-dev
+ libwnck-dev
+ librsvg-dev
+ libunique-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev
+
+ libgnomekbd-dev
+ libxklavier-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages="$pkgname-dev"
+replaces_dev="$pkgname"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="6420706542e8fb959acba7e2a69ee35f gnome-settings-daemon-2.32.1.tar.bz2"
diff --git a/main/gnome-settings-daemon/gnome-settings-daemon.post-install b/main/gnome-settings-daemon/gnome-settings-daemon.post-install
new file mode 100644
index 0000000000..0a7432db11
--- /dev/null
+++ b/main/gnome-settings-daemon/gnome-settings-daemon.post-install
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+for i in \
+ apps_gnome_settings_daemon_housekeeping.schemas \
+ apps_gnome_settings_daemon_keybindings.schemas \
+ apps_gnome_settings_daemon_xrandr.schemas \
+ desktop_gnome_font_rendering.schemas \
+ desktop_gnome_keybindings.schemas \
+ desktop_gnome_peripherals_smartcard.schemas \
+ desktop_gnome_peripherals_touchpad.schemas \
+ gnome-settings-daemon.schemas \
+; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-settings-daemon/gnome-settings-daemon.post-upgrade b/main/gnome-settings-daemon/gnome-settings-daemon.post-upgrade
new file mode 100644
index 0000000000..0a7432db11
--- /dev/null
+++ b/main/gnome-settings-daemon/gnome-settings-daemon.post-upgrade
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+for i in \
+ apps_gnome_settings_daemon_housekeeping.schemas \
+ apps_gnome_settings_daemon_keybindings.schemas \
+ apps_gnome_settings_daemon_xrandr.schemas \
+ desktop_gnome_font_rendering.schemas \
+ desktop_gnome_keybindings.schemas \
+ desktop_gnome_peripherals_smartcard.schemas \
+ desktop_gnome_peripherals_touchpad.schemas \
+ gnome-settings-daemon.schemas \
+; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-settings-daemon/gnome-settings-daemon.pre-deinstall b/main/gnome-settings-daemon/gnome-settings-daemon.pre-deinstall
new file mode 100644
index 0000000000..19cf86965f
--- /dev/null
+++ b/main/gnome-settings-daemon/gnome-settings-daemon.pre-deinstall
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+for i in \
+ apps_gnome_settings_daemon_housekeeping.schemas \
+ apps_gnome_settings_daemon_keybindings.schemas \
+ apps_gnome_settings_daemon_xrandr.schemas \
+ desktop_gnome_font_rendering.schemas \
+ desktop_gnome_keybindings.schemas \
+ desktop_gnome_peripherals_smartcard.schemas \
+ desktop_gnome_peripherals_touchpad.schemas \
+ gnome-settings-daemon.schemas \
+; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-system-monitor/APKBUILD b/main/gnome-system-monitor/APKBUILD
new file mode 100644
index 0000000000..5419b692ca
--- /dev/null
+++ b/main/gnome-system-monitor/APKBUILD
@@ -0,0 +1,66 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-system-monitor
+pkgver=2.28.2
+pkgrel=0
+pkgdesc="GNOME system monitor"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ gnome-desktop-dev
+ libwnck-dev
+ librsvg-dev
+ libunique-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev
+
+ libgtop-dev
+ libgnomekbd-dev
+ libxklavier-dev
+
+ gtkmm-dev
+ glibmm-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev desktop-file-utils gnome-icon-theme"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="3f0bca9b0ebc7a365466851cd580d167 gnome-system-monitor-2.28.2.tar.bz2"
diff --git a/main/gnome-system-monitor/gnome-system-monitor.post-install b/main/gnome-system-monitor/gnome-system-monitor.post-install
new file mode 100644
index 0000000000..8c003fa132
--- /dev/null
+++ b/main/gnome-system-monitor/gnome-system-monitor.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-system-monitor.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-system-monitor/gnome-system-monitor.post-upgrade b/main/gnome-system-monitor/gnome-system-monitor.post-upgrade
new file mode 100644
index 0000000000..8c003fa132
--- /dev/null
+++ b/main/gnome-system-monitor/gnome-system-monitor.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-system-monitor.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-system-monitor/gnome-system-monitor.pre-deinstall b/main/gnome-system-monitor/gnome-system-monitor.pre-deinstall
new file mode 100644
index 0000000000..92d7db79c6
--- /dev/null
+++ b/main/gnome-system-monitor/gnome-system-monitor.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-system-monitor.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-terminal/APKBUILD b/main/gnome-terminal/APKBUILD
new file mode 100644
index 0000000000..ca5ba597fc
--- /dev/null
+++ b/main/gnome-terminal/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-terminal
+pkgver=2.33.4
+pkgrel=3
+pkgdesc="GNOME terminal emulator"
+url="http://projects.gnome.org/gnome-terminal"
+arch="all"
+license="GPL"
+depends="libgnome"
+makedepends="gtk+-dev vte-dev gconf-dev libx11-dev gnome-doc-utils libsm-dev ncurses-dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/gnome-terminal/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="1293d90f7cf4dd041596501ef53fc5e1 gnome-terminal-2.33.4.tar.bz2"
diff --git a/main/gnome-terminal/gnome-terminal.post-install b/main/gnome-terminal/gnome-terminal.post-install
new file mode 100644
index 0000000000..7da0a45406
--- /dev/null
+++ b/main/gnome-terminal/gnome-terminal.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-terminal.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-terminal/gnome-terminal.post-upgrade b/main/gnome-terminal/gnome-terminal.post-upgrade
new file mode 100644
index 0000000000..7da0a45406
--- /dev/null
+++ b/main/gnome-terminal/gnome-terminal.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-terminal.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-terminal/gnome-terminal.pre-deinstall b/main/gnome-terminal/gnome-terminal.pre-deinstall
new file mode 100644
index 0000000000..b888a3f330
--- /dev/null
+++ b/main/gnome-terminal/gnome-terminal.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gnome-terminal.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gnome-themes/APKBUILD b/main/gnome-themes/APKBUILD
new file mode 100644
index 0000000000..c348113596
--- /dev/null
+++ b/main/gnome-themes/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gnome-themes
+pkgver=2.32.1
+pkgrel=0
+pkgdesc="themes for GNOME desktop environment"
+url="http://art.gnome.org/"
+arch="noarch"
+license="GPL"
+depends="gtk-engines"
+makedepends="intltool icon-naming-utils gtk+-dev gdk-pixbuf-dev gawk sed"
+install=
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="41db9e3cb25d35af2675c599e67944d1 gnome-themes-2.32.1.tar.bz2"
diff --git a/main/gnome-vfs/APKBUILD b/main/gnome-vfs/APKBUILD
new file mode 100644
index 0000000000..3b361eb3c9
--- /dev/null
+++ b/main/gnome-vfs/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnome-vfs
+pkgver=2.24.4
+pkgrel=1
+pkgdesc="GNOME virtual filesystem subsystem"
+url="http://projects.gnome.org/gnome-vfs"
+arch="all"
+license="LGPL"
+depends="gnome-mime-data"
+depends_dev="gconf-dev libxml2-dev dbus-glib-dev gamin-dev"
+makedepends="$depends_dev intltool"
+install="$pkgname.post-install $pkgname.post-upgrade $pkgname.pre-deinstall"
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/gnome-vfs*/modules/*.la
+}
+
+md5sums="a05fab03eeef10a47dd156b758982f2e gnome-vfs-2.24.4.tar.bz2"
diff --git a/main/gnome-vfs/gnome-vfs.post-install b/main/gnome-vfs/gnome-vfs.post-install
new file mode 100644
index 0000000000..00ff29a655
--- /dev/null
+++ b/main/gnome-vfs/gnome-vfs.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in desktop_default_applications.schemas system_http_proxy.schemas desktop_gnome_url_handlers.schemas system_smb.schemas system_dns_sd.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i > /dev/null
+done
diff --git a/main/gnome-vfs/gnome-vfs.post-upgrade b/main/gnome-vfs/gnome-vfs.post-upgrade
new file mode 100644
index 0000000000..00ff29a655
--- /dev/null
+++ b/main/gnome-vfs/gnome-vfs.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in desktop_default_applications.schemas system_http_proxy.schemas desktop_gnome_url_handlers.schemas system_smb.schemas system_dns_sd.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i > /dev/null
+done
diff --git a/main/gnome-vfs/gnome-vfs.pre-deinstall b/main/gnome-vfs/gnome-vfs.pre-deinstall
new file mode 100644
index 0000000000..3cd527cfa3
--- /dev/null
+++ b/main/gnome-vfs/gnome-vfs.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in desktop_default_applications.schemas system_http_proxy.schemas desktop_gnome_url_handlers.schemas system_smb.schemas system_dns_sd.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i > /dev/null
+done
diff --git a/main/gnuchess/APKBUILD b/main/gnuchess/APKBUILD
new file mode 100644
index 0000000000..b0cca224a4
--- /dev/null
+++ b/main/gnuchess/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnuchess
+pkgver=6.0.0
+pkgrel=0
+pkgdesc="The GNU chess program"
+url="http://www.gnu.org/software/chess/"
+arch="all"
+license="GPLv3+"
+depends=
+makedepends=
+install=""
+subpackages="$pkgname-doc"
+source="ftp://ftp.gnu.org/pub/gnu/chess/gnuchess-$pkgver.tar.gz"
+
+_builddir="$srcdir"/gnuchess-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="1a7a46188dab76f4339d22ff47c31515 gnuchess-6.0.0.tar.gz"
diff --git a/main/gnumeric/APKBUILD b/main/gnumeric/APKBUILD
new file mode 100644
index 0000000000..8ab075d932
--- /dev/null
+++ b/main/gnumeric/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnumeric
+pkgver=1.10.16
+pkgrel=2
+pkgdesc="A GNOME Spreadsheet Program"
+url="http://www.gnome.org/projects/gnumeric/"
+arch="all"
+license="GPL"
+makedepends="gtk+-dev intltool desktop-file-utils libglade-dev goffice-dev
+ rarian"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/1.10/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-schemas-install \
+ --disable-static \
+ --enable-ssindex || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/*/*/plugins/*/*.la
+}
+
+md5sums="c79a7c4b6d2080d249c63a5045b78af3 gnumeric-1.10.16.tar.bz2"
diff --git a/main/gnupg/APKBUILD b/main/gnupg/APKBUILD
new file mode 100644
index 0000000000..694524d6e5
--- /dev/null
+++ b/main/gnupg/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnupg
+pkgver=2.0.17
+pkgrel=0
+pkgdesc="GNU Privacy Guard 2 - a PGP replacement tool"
+url="http://www.gnupg.org/"
+arch="all"
+license="GPL"
+depends="pinentry"
+makedepends="curl-dev libassuan libksba-dev libgcrypt-dev libgpg-error-dev
+ pth-dev zlib-dev libiconv-dev libassuan-dev"
+subpackages="$pkgname-doc"
+source="ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # compat symlink
+ ln -s gpg2 "$pkgdir"/usr/bin/gpg
+}
+md5sums="123af099740fd159c73a0352a274ec81 gnupg-2.0.17.tar.bz2"
diff --git a/main/gnutls/APKBUILD b/main/gnutls/APKBUILD
new file mode 100644
index 0000000000..81ae97ee68
--- /dev/null
+++ b/main/gnutls/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gnutls
+pkgver=2.12.6.1
+pkgrel=0
+pkgdesc="A TLS protocol implementation"
+url="http://www.gnu.org/software/gnutls/"
+arch="all"
+license="GPL"
+depends=
+depends_dev="libgcrypt-dev libgpg-error-dev zlib-dev libtasn1-dev"
+makedepends="$depends_dev"
+install=
+subpackages="$pkgname-doc $pkgname-dev $pkgname-utils"
+source="http://ftp.gnu.org/pub/gnu/gnutls/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-included-libcfg \
+ --with-libgcrypt \
+ --disable-rpath \
+ --disable-static \
+ || return 1
+ make
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+utils() {
+ pkgdesc="Command line tools for TLS protocol"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+md5sums="e724e37f96984f3b0a215c11f03729bd gnutls-2.12.6.1.tar.bz2"
diff --git a/main/gobject-introspection/APKBUILD b/main/gobject-introspection/APKBUILD
new file mode 100644
index 0000000000..ec2d44235d
--- /dev/null
+++ b/main/gobject-introspection/APKBUILD
@@ -0,0 +1,53 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gobject-introspection
+pkgver=0.10.8
+pkgrel=2
+pkgdesc="Introspection system for GObject-based libraries"
+url="http://live.gnome.org/GObjectInstrospection"
+arch="all"
+license="LGPL GPL"
+depends_dev="python glib-dev libffi-dev cairo-dev"
+makedepends="$depends_dev flex bison python-dev libtool"
+depends=
+replaces="libgirepository"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+# since this is a dev package by definition we dont bother separate -dev
+subpackages="$pkgname-doc $pkgname-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+dev() {
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/share "$subpkgdir"/usr/ || return 1
+ mv "$pkgdir"/usr/lib/gobject-introspection "$subpkgdir"/usr/lib/ \
+ || return 1
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/ || return 1
+ default_dev
+ replaces="gobject-introspection"
+}
+
+md5sums="b5da58a5327d13b4d1e08b8e42b2456d gobject-introspection-0.10.8.tar.bz2"
diff --git a/main/goffice/APKBUILD b/main/goffice/APKBUILD
new file mode 100644
index 0000000000..72290c07c1
--- /dev/null
+++ b/main/goffice/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=goffice
+pkgver=0.8.15
+pkgrel=1
+_maj=${pkgver%%.*}
+_min=${pkgver#${_maj}.}
+_min=${_min%%.*}
+pkgdesc="A library of document-centric objects and utilities built on top of GLib and Gtk+"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+makedepends="libgsf-dev intltool cairo-dev gtk+-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/$_maj.$_min/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev libgsf-dev cairo-dev libxml2-dev"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --without-gconf \
+ --disable-static \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.la "$pkgdir"/usr/lib/goffice/*/plugins/*/*.la
+}
+
+md5sums="eab1841ad021f5cf909c33ef21e43db6 goffice-0.8.15.tar.bz2"
diff --git a/main/gparted/APKBUILD b/main/gparted/APKBUILD
new file mode 100644
index 0000000000..35b98acdbb
--- /dev/null
+++ b/main/gparted/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gparted
+pkgver=0.8.1
+pkgrel=1
+pkgdesc="a graphical partition editor for creating, reorganizing, and deleting disk partitions"
+url="http://gparted.sourceforge.net/"
+arch="all"
+license="GPL"
+depends="e2fsprogs"
+makedepends="gtkmm-dev parted-dev util-linux-ng-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://sourceforge.net/projects/gparted/files/gparted/gparted-$pkgver/gparted-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-doc \
+ --disable-scrollkeeper
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="ba3a434a259ae2ddcfc7f7488ee648ef gparted-0.8.1.tar.bz2"
diff --git a/main/gperf/APKBUILD b/main/gperf/APKBUILD
new file mode 100644
index 0000000000..6cad51f78e
--- /dev/null
+++ b/main/gperf/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gperf
+pkgver=3.0.4
+pkgrel=2
+pkgdesc="Perfect hash function generator."
+url="http://www.gnu.org/software/gperf/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=
+makedepends=
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+md5sums="c1f1db32fb6598d6a93e6e88796a8632 gperf-3.0.4.tar.gz"
diff --git a/main/gpicview/APKBUILD b/main/gpicview/APKBUILD
new file mode 100644
index 0000000000..dbb9ac0ba3
--- /dev/null
+++ b/main/gpicview/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gpicview
+pkgver=0.2.1
+pkgrel=3
+pkgdesc="Picture viewer of the LXDE Desktop"
+url="http://wiki.lxde.org/en/GPicView"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="gtk+-dev intltool jpeg-dev"
+source="http://downloads.sourceforge.net/sourceforge/lxde/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --sysconfdir=/etc --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="a2de255bf9bdc40746c0dc89b3454a10 gpicview-0.2.1.tar.gz"
diff --git a/main/gradm/APKBUILD b/main/gradm/APKBUILD
new file mode 100644
index 0000000000..c78402297d
--- /dev/null
+++ b/main/gradm/APKBUILD
@@ -0,0 +1,57 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gradm
+pkgver=2.2.2
+pkgrel=0
+pkgdesc="administrative utility for grsecurity kernels"
+url="http://www.grsecurity.org/"
+arch="all"
+license="GPL"
+makedepends="bison flex"
+install=""
+subpackages="$pkgname-doc"
+source="http://grsecurity.net/test/gradm-2.2.2-201103262019.tar.gz
+ policy
+ base.policyd
+ grsec-rbac.initd"
+
+_builddir="$srcdir/gradm2"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make INSTALL=install DESTDIR="$pkgdir" install || return 1
+
+ # we don't want the grsecurity-recommended policy as it's old
+ # and non-modular.
+ rm "$pkgdir"/etc/grsec/policy
+
+ # install the base policy file which pulls in everything else.
+ install -m644 "$srcdir"/policy "$pkgdir"/etc/grsec/policy
+
+ # prepare and install base policy to /var/lib/grsec/policy.d
+ install -d -D "$pkgdir"/var/lib/grsec/policy.d
+ install -m644 "$srcdir"/base.policyd "$pkgdir"/var/lib/grsec/policy.d/00-base
+
+ # install grsec-rbac into initd
+ install -d -D "$pkgdir"/etc/init.d
+ install -m755 "$srcdir"/grsec-rbac.initd "$pkgdir"/etc/init.d/grsec-rbac
+}
+
+md5sums="72c5bce632fb40dff814e0f1f955cab7 gradm-2.2.2-201103262019.tar.gz
+38ee3aef884bdcfe6a5b925760f6220b policy
+1d4a2c2e522b7124ad901ae102181e72 base.policyd
+2fc5d055dd43a2d9e1bed378dcab8641 grsec-rbac.initd"
diff --git a/main/gradm/base.policyd b/main/gradm/base.policyd
new file mode 100644
index 0000000000..cf66e7301e
--- /dev/null
+++ b/main/gradm/base.policyd
@@ -0,0 +1,133 @@
+role admin sA
+subject / rvka
+ / rwcdmlxi
+
+role default G
+role_transitions admin
+subject / dpo
+ / r
+ /opt rx
+ /home rwxcd
+ /mnt rw
+ /dev
+ /dev/grsec h
+ /dev/urandom r
+ /dev/random r
+ /dev/zero rw
+ /dev/input rw
+ /dev/psaux rw
+ /dev/null rw
+ /dev/tty? rw
+ /dev/hvc? rw
+ /dev/console rw
+ /dev/tty rw
+ /dev/pts rw
+ /dev/ptmx rw
+ /dev/dsp rw
+ /dev/mixer rw
+ /dev/initctl rw
+ /dev/fd0 r
+ /dev/cdrom r
+ /dev/mem h
+ /dev/kmem h
+ /dev/port h
+ /bin rx
+ /sbin rx
+ /lib rx
+ /usr rx
+ /etc rx
+ /proc rwx
+ /proc/slabinfo h
+ /proc/kcore h
+ /proc/kallsyms h
+ /proc/modules h
+ /proc/sys r
+ /root r
+ /tmp rwcd
+ /var rwxcd
+ /var/tmp rwcd
+ /var/log r
+ /boot h
+ /lib/modules h
+ /etc/grsec h
+ /var/lib/grsec h
+
+ -CAP_KILL
+ -CAP_SYS_TTY_CONFIG
+ -CAP_LINUX_IMMUTABLE
+ -CAP_NET_RAW
+ -CAP_MKNOD
+ -CAP_SYS_ADMIN
+ -CAP_SYS_RAWIO
+ -CAP_SYS_MODULE
+ -CAP_SYS_PTRACE
+ -CAP_NET_ADMIN
+ -CAP_NET_BIND_SERVICE
+ -CAP_NET_RAW
+ -CAP_SYS_CHROOT
+ -CAP_SYS_BOOT
+ -CAP_SETFCAP
+
+# the d flag protects /proc fd and mem entries for sshd
+# all daemons should have 'p' in their subject mode to prevent
+# an attacker from killing the service (and restarting it with trojaned
+# config file or taking the port it reserved to run a trojaned service)
+subject /usr/sbin/sshd dpo
+ / h
+ /bin/sh x
+ /bin/bash x
+ /dev h
+ /dev/log rw
+ /dev/random r
+ /dev/urandom r
+ /dev/null rw
+ /dev/ptmx rw
+ /dev/pts rw
+ /dev/tty rw
+ /dev/tty? rw
+ /etc r
+ /etc/passwd r
+ /etc/shadow r
+ /etc/grsec h
+ /home rwcd
+ /lib rx
+ /root
+ /proc r
+ /proc/*/oom_adj w
+ /proc/kcore h
+ /proc/sys h
+ /usr/lib rx
+ /usr/share/zoneinfo r
+ /var/log
+ /var/mail
+ /var/log/lastlog rw
+ /var/log/wtmp w
+ /var/run/sshd
+ /var/run/utmp rw
+ /var/empty rw
+
+ -CAP_ALL
+ +CAP_CHOWN
+ +CAP_SETGID
+ +CAP_SETUID
+ +CAP_SYS_CHROOT
+ +CAP_SYS_RESOURCE
+ +CAP_SYS_TTY_CONFIG
+
+subject /usr/bin/ssh
+ /etc/ssh/ssh_config r
+
+subject /bin/busybox
+ +CAP_SYS_ADMIN
+ +CAP_SYS_BOOT
+ /root/.ash_history rw
+ /dev/log rwc
+ /var/log rwc
+ /var/log/messages rwc
+ /var/log/wtmp w
+ /var/log/faillog rwcd
+
+subject /usr/bin/sudo
+ +CAP_SYS_ADMIN
+ /dev/log rw
+
diff --git a/main/gradm/grsec-rbac.initd b/main/gradm/grsec-rbac.initd
new file mode 100644
index 0000000000..fe0eec55cc
--- /dev/null
+++ b/main/gradm/grsec-rbac.initd
@@ -0,0 +1,14 @@
+#!/sbin/runscript
+
+start() {
+ ebegin "Enabling grsecurity RBAC policy"
+ gradm -E
+ eend $?
+}
+
+stop() {
+ ebegin "Disabling grsecurity RBAC policy"
+ gradm -D
+ eend $?
+}
+
diff --git a/main/gradm/policy b/main/gradm/policy
new file mode 100644
index 0000000000..e5a3df439c
--- /dev/null
+++ b/main/gradm/policy
@@ -0,0 +1,211 @@
+# Base grsecurity policy for Alpine.
+#
+# If you want to use a custom policy, or add on local modifications to
+# the system policy, edit below the include line or remove the include
+# line to completely remove the system policy entirely from your setup.
+#
+# Documentation on the file format as provided in the sample policy file
+# follow below for your reference:
+## Role flags:
+# A -> This role is an administrative role, thus it has special privilege normal
+# roles do not have. In particular, this role bypasses the
+# additional ptrace restrictions
+# N -> Don't require authentication for this role. To access
+# the role, use gradm -n <rolename>
+# s -> This role is a special role, meaning it does not belong to a
+# user or group, and does not require an enforced secure policy
+# base to be included in the ruleset
+# u -> This role is a user role
+# g -> This role is a group role
+# G -> This role can use gradm to authenticate to the kernel
+# A policy for gradm will automatically be added to the role
+# T -> Enable TPE for this role
+# l -> Enable learning for this role
+# P -> Use PAM authentication for this role.
+#
+# a role can only be one of user, group, or special
+#
+# role_allow_ip IP/optional netmask
+# eg: role_allow_ip 192.168.1.0/24
+# You can have as many of these per role as you want
+# They restrict the use of a role to a list of IPs. If a user
+# is on the system that would normally get the role does not
+# belong to those lists of IPs, the system falls back through
+# its method of determining a role for the user
+#
+# Role hierarchy
+# user -> group -> default
+# First a user role attempts to match, if one is not found,
+# a group role attempts to match, if one is not found,
+# the default role is used.
+#
+# role_transitions <special role 1> <special role 2> ... <special role n>
+# eg: role_transitions www_admin dns_admin
+#
+# role transitions specify which special roles a given role is allowed
+# to authenticate to. This applies to special roles that do not
+# require password authentication as well. If a user tries to
+# authenticate to a role that is not within his transition table, he
+# will receive a permission denied error
+#
+# Nested subjects
+# subject /bin/su:/bin/bash:/bin/cat
+# / rwx
+# +CAP_ALL
+# grant privilege to specific processes if they are executed
+# within a trusted path. In this case, privilege is
+# granted if /bin/cat is executed from /bin/bash, which is
+# executed from /bin/su.
+#
+# Configuration inheritance on nested subjects
+# nested subjects inherit rules from their parents. In the
+# example above, the nested subject would inherit rules
+# from the nested subject for /bin/su:/bin/bash,
+# and the subject /bin/su
+# View the 1.9.x documentation for more information on
+# configuration inheritance
+#
+# new object modes:
+# m -> allow creation of setuid/setgid files/directories
+# and modification of files/directories to be setuid/setgid
+# M -> audit the setuid/setgid creation/modification
+# c -> allow creation of the file/directory
+# C -> audit the creation
+# d -> allow deletion of the file/directory
+# D -> audit the deletion
+# p -> reject all ptraces to this object
+# l -> allow a hardlink at this path
+# (hardlinking requires at a minimum c and l modes, and the target
+# link cannot have any greater permission than the source file)
+# L -> audit link creation
+# new subject modes:
+# O -> disable "writable library" restrictions for this task
+# t -> allow this process to ptrace any process (use with caution)
+# r -> relax ptrace restrictions (allows process to ptrace processes
+# other than its own descendants)
+# i -> enable inheritance-based learning for this subject, causing
+# all accesses of this subject and anything it executes to be placed
+# in this subject, and inheritance flags added to executable objects
+# in this subject
+# a -> allow this process to talk to the /dev/grsec device
+#
+# user/group transitions:
+# You may now specify what users and groups a given subject can
+# transition to. This can be done on an inclusive or exclusive basis.
+# Omitting these rules allows a process with proper privilege granted by
+# capabilities to transition to any user/group.
+#
+# Examples:
+# subject /bin/su
+# user_transition_allow root spender
+# group_transition_allow root spender
+# subject /bin/su
+# user_transition_deny evilhacker
+# subject /bin/su
+# group_transition_deny evilhacker1 evilhacker2
+#
+# Domains:
+# With domains you can combine users that don't share a common
+# GID as well as groups so that they share a single policy
+# Domains work just like roles, with the only exception being that
+# the line starting with "role" is replaced with one of the following:
+# domain somedomainname u user1 user2 user3 user4 ... usern
+# domain somedomainname g group1 group2 group3 group4 ... groupn
+#
+# Inverted socket policies:
+# Rules such as
+# connect ! www.google.com:80 stream tcp
+# are now allowed, which allows you to specify that a process can connect to anything
+# except to port 80 of www.google.com with a stream tcp socket
+# the inverted socket matching also works on bind rules
+#
+# INADDR_ANY overriding
+# You can now force a given subject to bind to a particular IP address on the machine
+# This is useful for some chrooted environments, to ensure that the source IP they
+# use is one of your choosing
+# to use, add a line like:
+# ip_override 192.168.0.1
+#
+# Per-interface socket policies:
+# Rules such as
+# bind eth1:80 stream tcp
+# bind eth0#1:22 stream tcp
+# are now allowed, giving you the ability to tie specific socket rules
+# to a single interface (or by using the inverted rules, all but one
+# interface). Virtual interfaces are specified by the <ifname>#<vindex>
+# syntax. If an interface is specified, no IP/netmask or host may be
+# specified for the rule.
+#
+# New learning system:
+# To learn on a given subject: add l (the letter l, not the number 1)
+# to the subject mode
+# If you want to learn with the most restrictive policy, use the
+# following:
+# subject /path/to/bin lo
+# / h
+# -CAP_ALL
+# connect disabled
+# bind disabled
+# Resource learning is also supported, so lines like
+# RES_AS 0 0
+# can be used to learn a particular resource
+#
+# To learn on a given role, add l to the role mode
+# For both of these, to enable learning, enable the system like:
+# gradm -L /etc/grsec/learning.logs -E
+# and then generate the rules after disabling the system after the
+# learning phase with:
+# gradm -L /etc/grsec/learning.logs -O /etc/grsec/policy
+# To use full system learning, enable the system like:
+# gradm -F -L /etc/grsec/learning.logs
+# and then generate the rules after disabling the system after the
+# learning phase with:
+# gradm -F -L /etc/grsec/learning.logs -O /etc/grsec/policy
+#
+# New PaX flag format (replaces PaX subject flags):
+# PaX flags can be forced on or off, regardless of the flags on the
+# binary, by using + or - before the following PaX flag names:
+# PAX_SEGMEXEC
+# PAX_PAGEEXEC
+# PAX_MPROTECT
+# PAX_RANDMMAP
+# PAX_EMUTRAMP
+#
+# New feature for easier policy maintenance:
+# replace <variable name> <replace string>
+# e.g.:
+# replace CVSROOT /home/cvs
+# now $(CVSROOT) can be used in any subject or object pathname, like:
+# $(CVSROOT)/grsecurity r
+# This will translate to /home/cvs/grsecurity r
+# This feature makes it easier to update policies by naming specific
+# paths by their function, then only having to update those paths once
+# to have it affect a large number of subjects/objects.
+#
+# capability auditing / log suppression
+# use of a capability can be audited by adding "audit" to the line, eg:
+# +CAP_SYS_RAWIO audit
+# log suppression for denial of a capbility can be done by adding "suppress":
+# -CAP_SYS_RAWIO suppress
+#
+# Note that the omission of any feature of a role or subject
+# results in a default-allow
+# For instance, if no capability rules are added, an implicit +CAP_ALL is used
+#
+
+#
+# Default security policy provided by packages in Alpine are installed into
+# /var/lib/grsec/policy.d as /var/lib/grsec/policy.d/$pkgname where $pkgname
+# is the package name. It is not recommended that you edit those definitions
+# unless you know what you're doing, as the Alpine system may depend on the
+# presence of those definitions.
+#
+
+include </var/lib/grsec/policy.d>
+
+#
+# If you wish to add any additions to the system policy, you may do so below
+# this line. As the configuration is read top-to-bottom, any changes you make
+# here may override the default security policy.
+#
+
diff --git a/main/grep/APKBUILD b/main/grep/APKBUILD
new file mode 100644
index 0000000000..6f40772cdf
--- /dev/null
+++ b/main/grep/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer:
+pkgname=grep
+pkgver=2.8
+pkgrel=0
+pkgdesc="Searches input files for lines containing a match to a specified pattern"
+url="http://www.gnu.org/software/grep/grep.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="pcre-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://mirrors.kernel.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="cb2dfc502c5afc7a4a6e5f6cefd6850e grep-2.8.tar.gz"
diff --git a/main/groff/APKBUILD b/main/groff/APKBUILD
new file mode 100644
index 0000000000..01f2708719
--- /dev/null
+++ b/main/groff/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=groff
+pkgver=1.21
+pkgrel=0
+pkgdesc="GNU troff text-formatting system"
+url="http://www.gnu.org/software/groff/groff.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="perl texinfo"
+subpackages="$pkgname-doc"
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build () {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr --without-x
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="8b8cd29385b97616a0f0d96d0951c5bf groff-1.21.tar.gz"
diff --git a/main/gross/APKBUILD b/main/gross/APKBUILD
new file mode 100644
index 0000000000..e1f304d8ac
--- /dev/null
+++ b/main/gross/APKBUILD
@@ -0,0 +1,53 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gross
+pkgver=1.0.2
+pkgrel=3
+pkgdesc="Greylisting of suspicious sources"
+url="http://code.google.com/p/gross/"
+arch="all"
+license="BSD"
+depends=
+makedepends="c-ares-dev autoconf automake libtool sed"
+install="$pkgname.pre-install $pkgname.post-install $pkgname.pre-upgrade
+ $pkgname.post-upgrade"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://gross.googlecode.com/files/$pkgname-$pkgver.tar.gz
+ grossd.initd
+ grossd.confd
+ gross-1.0.1-default-conf.patch
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ for _i in ../*.patch; do
+ msg "Applying $_i..."
+ patch -p1 < $_i || return 1
+ done
+
+ export lt_SED='/bin/sed'
+ export lt_cv_path_SED='/bin/sed'
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+
+ make -j1 || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -dD "$pkgdir"/var/run/gross
+ install -m755 -D "$srcdir"/grossd.initd "$pkgdir"/etc/init.d/grossd
+ install -m644 -D "$srcdir"/grossd.confd "$pkgdir"/etc/conf.d/grossd
+}
+
+md5sums="cb88d88553161c01e9bed7a74c3e9263 gross-1.0.2.tar.gz
+6e8a2626c0c9f0e98e950a67a55a7040 grossd.initd
+5ca1c6e51c3243236e6564480b20279b grossd.confd
+7c504b653c71dcf7b192bc487b3516fd gross-1.0.1-default-conf.patch"
diff --git a/main/gross/gross-1.0.1-default-conf.patch b/main/gross/gross-1.0.1-default-conf.patch
new file mode 100644
index 0000000000..39cd90709d
--- /dev/null
+++ b/main/gross/gross-1.0.1-default-conf.patch
@@ -0,0 +1,17 @@
+diff -ru gross-1.0.1.orig/doc/examples/grossd.conf gross-1.0.1/doc/examples/grossd.conf
+--- gross-1.0.1.orig/doc/examples/grossd.conf 2008-06-03 09:27:37 +0000
++++ gross-1.0.1/doc/examples/grossd.conf 2008-06-03 09:31:33 +0000
+@@ -71,11 +71,13 @@
+ # 'statefile' is the full path of the file that the server will use to
+ # store the state information.
+ # statefile = /var/db/grossd.state
++statefile = /var/db/gross/state
+
+ # 'pidfile' is the full path of the file grossd writes its pid into.
+ # You can set parameter 'check', if you want to keep grossd
+ # from starting if pidfile already exists.
+ # pidfile = /var/run/grossd.pid;check
++pidfile = /var/run/gross/grossd.pid
+
+ # 'log_method' is used to list all the possible logging facilities.
+ # currently only syslog is implemented
diff --git a/main/gross/gross.post-install b/main/gross/gross.post-install
new file mode 100644
index 0000000000..df06670a41
--- /dev/null
+++ b/main/gross/gross.post-install
@@ -0,0 +1,2 @@
+#!/bin/sh
+chown -R gross:gross /var/run/gross
diff --git a/main/gross/gross.post-upgrade b/main/gross/gross.post-upgrade
new file mode 100644
index 0000000000..ff1c806dcf
--- /dev/null
+++ b/main/gross/gross.post-upgrade
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+moved=
+for i in /etc/runlevels/*/gross; do
+ if [ -L $i ]; then
+ rm ${i}
+ ln -s /etc/init.d/grossd ${i}d
+ moved=1
+ fi
+done
+
+if [ -n "$moved" ]; then
+ echo " *"
+ echo " * NOTICE: /etc/init.d/gross is renamed to /etc/init.d/grossd"
+ echo " *"
+fi
+
diff --git a/main/gross/gross.pre-install b/main/gross/gross.pre-install
new file mode 100644
index 0000000000..c3844d7a5e
--- /dev/null
+++ b/main/gross/gross.pre-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+adduser -H -s /bin/false -D gross 2>/dev/null
+exit 0
diff --git a/main/gross/gross.pre-upgrade b/main/gross/gross.pre-upgrade
new file mode 100644
index 0000000000..90361bcc65
--- /dev/null
+++ b/main/gross/gross.pre-upgrade
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+old=/etc/conf.d/gross
+new=/etc/conf.d/grossd
+
+if [ -f "$old" ] && [ ! -f "$new" ]; then
+ mv "$old" "$new"
+ echo " *"
+ echo " * NOTICE: $old was renamed to $new"
+ echo " *"
+fi
+
diff --git a/main/gross/grossd.confd b/main/gross/grossd.confd
new file mode 100644
index 0000000000..646e12f9d7
--- /dev/null
+++ b/main/gross/grossd.confd
@@ -0,0 +1,6 @@
+#
+# Specify daemon $OPTS here.
+#
+
+OPTS=""
+
diff --git a/main/gross/grossd.initd b/main/gross/grossd.initd
new file mode 100644
index 0000000000..c300ac4982
--- /dev/null
+++ b/main/gross/grossd.initd
@@ -0,0 +1,36 @@
+#!/sbin/runscript
+
+NAME="grossd"
+DAEMON="/usr/sbin/$NAME"
+DAEMON_USER="gross"
+DAEMON_GROUP="gross"
+pidfile=/var/run/gross/$NAME.pid
+
+depend() {
+ need net
+ after firewall
+}
+
+check_config() {
+ if [ ! -f /var/db/gross/state ] ; then
+ einfo "Generating Gross database..."
+ install -dD -o${DAEMON_USER} -g${DAEMON_GROUP} /var/db/gross
+ ${DAEMON} -Cu ${DAEMON_USER} > /dev/null
+ fi
+}
+
+start() {
+ check_config || return 1
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet --pidfile ${pidfile} \
+ --exec ${DAEMON} -- \
+ -p ${pidfile} -u ${DAEMON_USER} ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --exec ${DAEMON}
+ eend $?
+}
+
diff --git a/main/gsl/APKBUILD b/main/gsl/APKBUILD
new file mode 100644
index 0000000000..f721011aeb
--- /dev/null
+++ b/main/gsl/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gsl
+pkgver=1.14
+pkgrel=2
+pkgdesc="The GNU Scientific Library (GSL) is a modern numerical library for C and C++ programmers"
+url="http://www.gnu.org/software/gsl/gsl.html"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.belnet.be/mirror/ftp.gnu.org/gnu/gsl/gsl-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="d55e7b141815412a072a3f0e12442042 gsl-1.14.tar.gz"
diff --git a/main/gsm/APKBUILD b/main/gsm/APKBUILD
new file mode 100644
index 0000000000..e2548140fd
--- /dev/null
+++ b/main/gsm/APKBUILD
@@ -0,0 +1,69 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gsm
+pkgver=1.0.13
+pkgrel=0
+_soname=1.0.12
+pkgdesc="Shared libraries for GSM speech compressor"
+url="http://www.quut.com/gsm/"
+arch="all"
+license="MIT"
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-tools"
+source="http://www.quut.com/gsm/gsm-$pkgver.tar.gz
+ gsm-64bit.patch
+ gsm-makefile.patch
+ gsm-warnings.patch
+ "
+
+_builddir="$srcdir"/gsm-1.0-pl13
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ export RPM_OPT_FLAGS="$CFLAGS -fPIC"
+ make all || return 1
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/bin \
+ "$pkgdir"/usr/include/gsm \
+ "$pkgdir"/usr/lib \
+ "$pkgdir"/usr/share/man/man1 \
+ "$pkgdir"/usr/share/man/man3
+
+ make install \
+ INSTALL_ROOT="$pkgdir"/usr \
+ GSM_INSTALL_INC="$pkgdir"/usr/include/gsm \
+ GSM_INSTALL_LIB="$pkgdir"/usr/lib \
+ || return 1
+ cp -p lib/libgsm.so.$_soname "$pkgdir"/usr/lib/ || return 1
+ ln -s libgsm.so.$_soname "$pkgdir"/usr/lib/libgsm.so.1 || return 1
+ ln -s libgsm.so.$_soname "$pkgdir"/usr/lib/libgsm.so || return 1
+
+ ln -s gsm/gsm.h "$pkgdir"/usr/include/
+ rm -f "$pkgdir"/usr/lib/lib*.a
+}
+
+tools() {
+ pkgdesc="GSM speech compressor tools"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr
+}
+
+md5sums="c1ba392ce61dc4aff1c29ea4e92f6df4 gsm-1.0.13.tar.gz
+1e4f975729e58fe309bda013b26020d9 gsm-64bit.patch
+5d7da37bbc094b392c406df24a15958b gsm-makefile.patch
+a04797e67d809de42c77f9bd0027eb34 gsm-warnings.patch"
diff --git a/main/gsm/gsm-64bit.patch b/main/gsm/gsm-64bit.patch
new file mode 100644
index 0000000000..195ed31fae
--- /dev/null
+++ b/main/gsm/gsm-64bit.patch
@@ -0,0 +1,15 @@
+--- gsm-1.0-pl12/inc/private.h.64bit 2006-04-26 21:17:01.000000000 +0200
++++ gsm-1.0-pl12/inc/private.h 2007-05-11 00:25:23.000000000 +0200
+@@ -10,10 +10,10 @@
+ #define PRIVATE_H
+
+ typedef short word; /* 16 bit signed int */
+-typedef long longword; /* 32 bit signed int */
++typedef int longword; /* 32 bit signed int */
+
+ typedef unsigned short uword; /* unsigned word */
+-typedef unsigned long ulongword; /* unsigned longword */
++typedef unsigned int ulongword; /* unsigned longword */
+
+ struct gsm_state {
+
diff --git a/main/gsm/gsm-makefile.patch b/main/gsm/gsm-makefile.patch
new file mode 100644
index 0000000000..cf3e99bc9c
--- /dev/null
+++ b/main/gsm/gsm-makefile.patch
@@ -0,0 +1,115 @@
+--- gsm-1.0-pl12/Makefile.mk 2006-04-26 21:14:26.000000000 +0200
++++ gsm-1.0-pl12/Makefile 2007-05-13 13:03:32.000000000 +0200
+@@ -30,6 +30,10 @@
+ ######### define this, and read about the GSM_OPT_WAV49 option in the
+ ######### manual page on gsm_option(3).
+
++PG =
++#PG = -g -pg
++######### Profiling flags. If you don't know what that means, leave it blank
++
+ # Choose a compiler. The code works both with ANSI and K&R-C.
+ # Use -DNeedFunctionPrototypes to compile with, -UNeedFunctionPrototypes to
+ # compile without, function prototypes in the header files.
+@@ -44,7 +48,7 @@
+ # CCFLAGS = -c -O
+
+ CC = gcc -ansi -pedantic
+-CCFLAGS = -c -O2 -DNeedFunctionPrototypes=1
++CCFLAGS = -c $(RPM_OPT_FLAGS) -D_REENTRANT -DNeedFunctionPrototypes=1
+
+ LD = $(CC)
+
+@@ -81,7 +85,7 @@
+ GSM_INSTALL_ROOT = $(INSTALL_ROOT)
+ GSM_INSTALL_LIB = $(GSM_INSTALL_ROOT)/lib
+ GSM_INSTALL_INC = $(GSM_INSTALL_ROOT)/inc
+-GSM_INSTALL_MAN = $(GSM_INSTALL_ROOT)/man/man3
++GSM_INSTALL_MAN = $(GSM_INSTALL_ROOT)/share/man/man3
+
+
+ # Where do you want to install the toast binaries and their manpage?
+@@ -91,16 +95,16 @@
+
+ TOAST_INSTALL_ROOT = $(INSTALL_ROOT)
+ TOAST_INSTALL_BIN = $(TOAST_INSTALL_ROOT)/bin
+-TOAST_INSTALL_MAN = $(TOAST_INSTALL_ROOT)/man/man1
++TOAST_INSTALL_MAN = $(TOAST_INSTALL_ROOT)/share/man/man1
+
+ # Other tools
+
+ SHELL = /bin/sh
+-LN = ln
++LN = ln -s
+ BASENAME = basename
+ AR = ar
+ ARFLAGS = cr
+-RMFLAGS =
++RMFLAGS = -f
+ FIND = find
+ COMPRESS = compress
+ COMPRESSFLAGS =
+@@ -129,17 +133,18 @@
+ # DEBUG = -DNDEBUG
+ ######### Remove -DNDEBUG to enable assertions.
+
+-CFLAGS = $(CCFLAGS) $(SASR) $(DEBUG) $(MULHACK) $(FAST) $(LTP_CUT) \
++CFLAGS = $(PG) $(CCFLAGS) $(SASR) $(DEBUG) $(MULHACK) $(FAST) $(LTP_CUT) \
+ $(WAV49) $(CCINC) -I$(INC)
+ ######### It's $(CC) $(CFLAGS)
+
+-LFLAGS = $(LDFLAGS) $(LDINC)
++LFLAGS = $(PG) $(LDFLAGS) $(LDINC)
+ ######### It's $(LD) $(LFLAGS)
+
+
+ # Targets
+
+ LIBGSM = $(LIB)/libgsm.a
++LIBGSMSO = $(LIB)/libgsm.so
+
+ TOAST = $(BIN)/toast
+ UNTOAST = $(BIN)/untoast
+@@ -279,7 +284,7 @@
+
+ # Target rules
+
+-all: $(LIBGSM) $(TOAST) $(TCAT) $(UNTOAST)
++all: $(LIBGSM) $(LIBGSMSO) $(TOAST) $(TCAT) $(UNTOAST)
+ @-echo $(ROOT): Done.
+
+ tst: $(TST)/lin2cod $(TST)/cod2lin $(TOAST) $(TST)/test-result
+@@ -299,24 +304,28 @@
+
+ # The basic API: libgsm
+
++$(LIBGSMSO): $(LIB) $(GSM_OBJECTS)
++ $(LD) -o $@.1.0.12 -shared -Xlinker -soname -Xlinker libgsm.so.1 $(GSM_OBJECTS) -lc
++ ln -fs libgsm.so.1.0.12 lib/libgsm.so.1
++ ln -fs libgsm.so.1.0.12 lib/libgsm.so
++
+ $(LIBGSM): $(LIB) $(GSM_OBJECTS)
+ -rm $(RMFLAGS) $(LIBGSM)
+ $(AR) $(ARFLAGS) $(LIBGSM) $(GSM_OBJECTS)
+ $(RANLIB) $(LIBGSM)
+
+-
+ # Toast, Untoast and Tcat -- the compress-like frontends to gsm.
+
+-$(TOAST): $(BIN) $(TOAST_OBJECTS) $(LIBGSM)
+- $(LD) $(LFLAGS) -o $(TOAST) $(TOAST_OBJECTS) $(LIBGSM) $(LDLIB)
++$(TOAST): $(BIN) $(TOAST_OBJECTS) $(LIBGSM) $(LIBGSMSO)
++ $(LD) $(LFLAGS) -o $(TOAST) $(TOAST_OBJECTS) $(LIBGSMSO) $(LDLIB)
+
+ $(UNTOAST): $(BIN) $(TOAST)
+ -rm $(RMFLAGS) $(UNTOAST)
+- $(LN) $(TOAST) $(UNTOAST)
++ $(LN) toast $(UNTOAST)
+
+ $(TCAT): $(BIN) $(TOAST)
+ -rm $(RMFLAGS) $(TCAT)
+- $(LN) $(TOAST) $(TCAT)
++ $(LN) toast $(TCAT)
+
+
+ # The local bin and lib directories
diff --git a/main/gsm/gsm-warnings.patch b/main/gsm/gsm-warnings.patch
new file mode 100644
index 0000000000..8bec416adf
--- /dev/null
+++ b/main/gsm/gsm-warnings.patch
@@ -0,0 +1,43 @@
+--- gsm-1.0-pl12/src/code.c.warn 2006-04-26 21:16:50.000000000 +0200
++++ gsm-1.0-pl12/src/code.c 2007-05-11 00:26:52.000000000 +0200
+@@ -9,8 +9,8 @@
+ #include "config.h"
+
+
+-#ifdef HAS_STDLIB_H
+-#include <stdlib.h>
++#ifdef HAS_STRING_H
++#include <string.h>
+ #else
+ # include "proto.h"
+ extern char * memcpy P((char *, char *, int));
+--- gsm-1.0-pl12/src/toast.c.warn 2006-04-26 21:14:26.000000000 +0200
++++ gsm-1.0-pl12/src/toast.c 2007-05-11 00:26:52.000000000 +0200
+@@ -6,6 +6,8 @@
+
+ /* $Header: /home/fedora/jkeating/pkgs/rpms/gsm/devel/gsm-warnings.patch,v 1.1 2007/05/11 23:18:21 rathann Exp $ */
+
++#include <stdio.h>
++#include <getopt.h>
+ #include "toast.h"
+
+ /* toast -- lossy sound compression using the gsm library.
+--- gsm-1.0-pl12/add-test/add_test.c.warn 2006-04-26 21:14:25.000000000 +0200
++++ gsm-1.0-pl12/add-test/add_test.c 2007-05-11 00:28:03.000000000 +0200
+@@ -9,6 +9,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <unistd.h>
+
+ #include "gsm.h"
+
+@@ -29,7 +30,7 @@
+ longword M_gsm_L_mult P((word op1, word op2));
+ longword M_gsm_L_add P((longword op1, longword op2));
+
+-help()
++void help(void)
+ {
+ puts( " add a b sub a b mult a b div a b" );
+ puts( "L_add A B L_sub A B L_mult A B mult_r a b" );
diff --git a/main/gst-ffmpeg/APKBUILD b/main/gst-ffmpeg/APKBUILD
new file mode 100644
index 0000000000..090b036855
--- /dev/null
+++ b/main/gst-ffmpeg/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gst-ffmpeg
+pkgver=0.10.11
+pkgrel=3
+pkgdesc="Gstreamer FFMpeg Plugin"
+url="http://www.gstreamer.net"
+arch="all"
+license="GPL"
+makedepends="gstreamer-dev gst-plugins-base-dev liboil-dev coreutils orc-dev"
+source="http://gstreamer.freedesktop.org/src/gst-ffmpeg/gst-ffmpeg-$pkgver.tar.bz2
+ pic.patch"
+
+_builddir="$srcdir"/gst-ffmpeg-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+build() {
+ cd "$_builddir"
+ export CFLAGS="$CFLAGS -fno-strict-aliasing"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --with-ffmpeg-extra-configure="--enable-pic --disable-mmx --disable-mmx2" || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir"/usr/lib/ -name '*.la' -o -name '*.a' \
+ | xargs rm -f
+}
+
+md5sums="0d23197ba7ac06ea34fa66d38469ebe5 gst-ffmpeg-0.10.11.tar.bz2
+154fa474ee135ff709bc76a761477da4 pic.patch"
diff --git a/main/gst-ffmpeg/pic.patch b/main/gst-ffmpeg/pic.patch
new file mode 100644
index 0000000000..3a7268e61b
--- /dev/null
+++ b/main/gst-ffmpeg/pic.patch
@@ -0,0 +1,11 @@
+--- ./gst-libs/ext/ffmpeg/libswscale/rgb2rgb.c.orig
++++ ./gst-libs/ext/ffmpeg/libswscale/rgb2rgb.c
+@@ -159,7 +159,7 @@
+ #define RENAME(a) a ## _C
+ #include "rgb2rgb_template.c"
+
+-#if ARCH_X86
++#if ARCH_X86 && !defined(PIC)
+
+ //MMX versions
+ #undef RENAME
diff --git a/main/gst-plugins-bad/APKBUILD b/main/gst-plugins-bad/APKBUILD
new file mode 100644
index 0000000000..e5022f5b74
--- /dev/null
+++ b/main/gst-plugins-bad/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gst-plugins-bad
+pkgver=0.10.22
+pkgrel=0
+pkgdesc="GStreamer bad plugins"
+url="http://gstreamer.freedesktop.org/"
+arch="all"
+license="LGPL GPL"
+depends=""
+makedepends="gst-plugins-base-dev gstreamer-dev xvidcore-dev bzip2-dev
+ neon-dev faac-dev libexif-dev faad2-dev glib-dev liboil-dev
+ alsa-lib-dev libx11-dev sdl-dev libvpx-dev libdc1394-dev
+ libmms-dev libmodplug-dev gsm-dev flite-dev orc-dev jasper-dev
+ librsvg-dev"
+
+#'libdca>=0.0.5' 'exempi>=2.1.0' 'jack-audio-connection-kit>=0.116.2' 'musicbrainz>=2.1.5' 'libcdaudio>=0.99.12' 'libmpcdec>=1.2.6' 'mjpegtools>=1.9.0' 'libdvdnav>=4.1.3' 'liblrdf>=0.4.0' 'libofa>=0.9.3')
+source="http://gstreamer.freedesktop.org//src/gst-plugins-bad/gst-plugins-bad-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/gst-plugins-bad-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-experimental \
+ --with-package-name="GStreamer Bad Plugins (Alpine Linux)" \
+ --with-package-origin="http://www.alpinelinux.org/" \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/gst-plugins-bad-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="9a2acee1f386f71247003d0d7090fb1c gst-plugins-bad-0.10.22.tar.bz2"
diff --git a/main/gst-plugins-base/APKBUILD b/main/gst-plugins-base/APKBUILD
new file mode 100644
index 0000000000..4c921a33c3
--- /dev/null
+++ b/main/gst-plugins-base/APKBUILD
@@ -0,0 +1,55 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gst-plugins-base
+pkgver=0.10.35
+pkgrel=0
+pkgdesc="GStreamer Multimedia Framework Base Plugins"
+url="http://gstreamer.freedesktop.org/"
+arch="all"
+license="GPL LGPL"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-gnome"
+depends=
+makedepends="pkgconfig gstreamer-dev alsa-lib-dev libvorbis-dev liboil-dev
+ perl libogg-dev gtk+-dev libtheora-dev libice-dev libsm-dev libxv-dev
+ util-linux-ng-dev expat-dev gconf-dev gnome-vfs-dev"
+# cdparanoia>=10.2 libvisual libtheora"
+source="http://gstreamer.freedesktop.org/src/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="gstreamer-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # fix building with gnu make 3.82
+ find -name Makefile.in | xargs sed -i -e "s/^ /\t/" || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --disable-experimental \
+ --with-default-audiosink=osssink \
+ --with-package-name="GStreamer Base Plugins (Alpine Linux)" \
+ --with-package-origin="http://www.alpinelinux.org/" \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/*.a \
+ "$pkgdir"/usr/lib/gstreamer*/*.la \
+ "$pkgdir"/usr/lib/gstreamer*/*.a
+}
+
+gnome() {
+ mkdir -p "$subpkgdir"/usr/lib/gstreamer-0.10
+ mv "$pkgdir"/usr/lib/gstreamer-0.10/libgstgnomevfs.so "$subpkgdir"/usr/lib/gstreamer-0.10/libgstgnomevfs.so
+}
+
+md5sums="1d300983525f4f09030eb3ba47cb04b0 gst-plugins-base-0.10.35.tar.bz2"
diff --git a/main/gst-plugins-good/APKBUILD b/main/gst-plugins-good/APKBUILD
new file mode 100644
index 0000000000..041f9d08b7
--- /dev/null
+++ b/main/gst-plugins-good/APKBUILD
@@ -0,0 +1,59 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gst-plugins-good
+pkgver=0.10.30
+pkgrel=0
+pkgdesc="GStreamer Multimedia Framework Good Plugins"
+url="http://gstreamer.freedesktop.org/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-gnome"
+depends=
+makedepends="gstreamer-dev glib-dev liboil-dev gst-plugins-base-dev
+ libsoup-dev flac-dev libogg-dev taglib-dev jpeg-dev zlib-dev gconf-dev
+ wavpack-dev libavc1394-dev libiec61883-dev libshout-dev libdv-dev
+ orc-dev"
+replaces="gst-plugins-bad"
+
+source="http://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-$pkgver.tar.bz2"
+
+depends_dev="gstreamer-dev gst-plugins-base-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # fix building with gnu make 3.82
+ find -name Makefile.in | xargs sed -i -e "s/^ /\t/" || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-experimental \
+ --with-package-name="GStreamer Good Plugins (Alpine Linux)" \
+ --with-package-origin="http://www.alpinelinux.org/" \
+ || return 1
+ make
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+gnome() {
+ depends="gst-plugins-base-gnome"
+ install="$subpkgname.post-install $subpkgname.pre-deinstall $subpkgname.post-upgrade"
+ mkdir -p "$subpkgdir"/usr/lib/gstreamer-0.10
+
+ mv "$pkgdir"/etc "$subpkgdir"/etc
+ mv "$pkgdir"/usr/lib/gstreamer-0.10/libgstgconfelements.so "$subpkgdir"/usr/lib/gstreamer-0.10/libgstgconfelements.so
+}
+
+md5sums="62fd7a3ef187c4f99b3d7c352d58dae9 gst-plugins-good-0.10.30.tar.bz2"
diff --git a/main/gst-plugins-good/gst-plugins-good-gnome.post-install b/main/gst-plugins-good/gst-plugins-good-gnome.post-install
new file mode 100644
index 0000000000..35c28f3eba
--- /dev/null
+++ b/main/gst-plugins-good/gst-plugins-good-gnome.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gstreamer-0.10.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gst-plugins-good/gst-plugins-good-gnome.post-upgrade b/main/gst-plugins-good/gst-plugins-good-gnome.post-upgrade
new file mode 100644
index 0000000000..35c28f3eba
--- /dev/null
+++ b/main/gst-plugins-good/gst-plugins-good-gnome.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gstreamer-0.10.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gst-plugins-good/gst-plugins-good-gnome.pre-deinstall b/main/gst-plugins-good/gst-plugins-good-gnome.pre-deinstall
new file mode 100644
index 0000000000..5facd9964d
--- /dev/null
+++ b/main/gst-plugins-good/gst-plugins-good-gnome.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gstreamer-0.10.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/gst-plugins-ugly/APKBUILD b/main/gst-plugins-ugly/APKBUILD
new file mode 100644
index 0000000000..a37cd825ee
--- /dev/null
+++ b/main/gst-plugins-ugly/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gst-plugins-ugly
+pkgver=0.10.18
+pkgrel=2
+pkgdesc="GStreamer Multimedia Framework Ugly Plugins (gst-plugins-ugly)"
+url="http://gstreamer.freedesktop.org/"
+arch="all"
+license="LGPL"
+depends= # libdvdread>=4.1.3 libsidplay>=1.36.59 "
+makedepends="pkgconfig lame-dev libmpeg2-dev a52dec-dev libid3tag-dev
+ libmad-dev glib-dev liboil-dev gstreamer-dev gst-plugins-base-dev
+ x264-dev libcdio-dev libid3tag-dev orc-dev"
+source="http://gstreamer.freedesktop.org/src/gst-plugins-ugly/gst-plugins-ugly-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-experimental \
+ --with-package-name="GStreamer Ugly Plugins (Alpine Linux)" \
+ --with-package-origin="http://www.alpinelinux.org/" || return 1
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="04a7009a4efea2844075949c111f5e4d gst-plugins-ugly-0.10.18.tar.bz2"
diff --git a/main/gstreamer/APKBUILD b/main/gstreamer/APKBUILD
new file mode 100644
index 0000000000..790c7c85d3
--- /dev/null
+++ b/main/gstreamer/APKBUILD
@@ -0,0 +1,58 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gstreamer
+pkgver=0.10.35
+pkgrel=0
+pkgdesc="GStreamer Multimedia Framework"
+url="http://gstreamer.freedesktop.org/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-tools"
+depends=
+makedepends="pkgconfig libxml2-dev glib-dev bison flex gettext-dev libiconv-dev"
+source="http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-$pkgver.tar.bz2
+ "
+
+depends_dev="glib-dev libxml2-dev"
+_builddir="$srcdir"/gstreamer-$pkgver
+prepare() {
+ cd "$_builddir"
+ # fix building with gnu make 3.82
+ find -name Makefile.in | xargs sed -i -e "s/^ /\t/" || return 1
+
+ for i in $source; do
+ case "$i" in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/gstreamer-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-docs-build || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/gstreamer-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/*.a \
+ "$pkgdir"/usr/lib/gstreamer*/*.la \
+ "$pkgdir"/usr/lib/gstreamer*/*.a
+}
+
+tools() {
+ pkgdesc="common tools and files for GStreamer streaming media framework"
+ # gst-feedback needs this
+ depends="pkgconfig"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="4a0a00edad7a2c83de5211ca679dfaf9 gstreamer-0.10.35.tar.bz2"
diff --git a/main/gtk+/APKBUILD b/main/gtk+/APKBUILD
new file mode 100644
index 0000000000..4a08b4b473
--- /dev/null
+++ b/main/gtk+/APKBUILD
@@ -0,0 +1,24 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtk+
+pkgver=2.24
+pkgrel=0
+pkgdesc="metapackage for GTK+ runtime and development"
+url=""
+arch="all"
+license="LGPL"
+depends="gtk+2.0>=$pkgver"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev"
+url="http://www.gtk.org/"
+
+dev() {
+ depends="gtk+2.0-dev"
+ mkdir -p "$subpkgdir"
+}
+
+package() {
+ mkdir -p "$pkgdir"
+}
+
diff --git a/main/gtk+2.0/APKBUILD b/main/gtk+2.0/APKBUILD
new file mode 100644
index 0000000000..4214afc57d
--- /dev/null
+++ b/main/gtk+2.0/APKBUILD
@@ -0,0 +1,77 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtk+2.0
+pkgver=2.24.5
+pkgrel=5
+pkgdesc="The GTK+ Toolkit (v2)"
+url="http://www.gtk.org/"
+install="$pkgname.post-install $pkgname.post-upgrade $pkgname.post-deinstall"
+triggers="$pkgname.trigger:/usr/share/icons/*"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="shared-mime-info"
+
+replaces="gtk+"
+replaces_dev="gtk+-dev"
+replaces_doc="gtk+-doc"
+
+depends_dev="
+ atk-dev
+ cairo-dev
+ gdk-pixbuf-dev
+ glib-dev
+ intltool
+ libxdamage-dev
+ pango-dev
+ "
+makedepends="pkgconfig
+ $depends_dev
+ cups-dev
+ expat-dev
+ gettext-dev
+ gnutls-dev
+ gobject-introspection-dev
+ libice-dev
+ libiconv-dev
+ jpeg-dev>=8
+ libx11-dev
+ libxcomposite-dev
+ libxcursor-dev
+ libxext-dev
+ libxfixes-dev
+ libxrandr-dev
+ libxi-dev
+ tiff-dev
+ zlib-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/gtk+/${pkgver%.*}/gtk+-$pkgver.tar.bz2"
+
+
+_builddir="$srcdir"/gtk+-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --with-xinput=yes \
+ --without-libjasper \
+ --with-included-loaders=png || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+dev() {
+ mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/usr/share/
+ mv "$pkgdir"/usr/share/gtk-2.0 "$subpkgdir"/usr/share/ || return 1
+ default_dev
+ replaces="gtk+2.0"
+ mv "$pkgdir"/usr/bin/gtk-builder-convert \
+ "$pkgdir"/usr/bin/gtk-demo \
+ "$subpkgdir"/usr/bin || return 1
+}
+
+md5sums="aebeb2e9efc2e541dc9631546aed7900 gtk+-2.24.5.tar.bz2"
diff --git a/main/gtk+2.0/gtk+2.0.post-deinstall b/main/gtk+2.0/gtk+2.0.post-deinstall
new file mode 100644
index 0000000000..e7ee2a1517
--- /dev/null
+++ b/main/gtk+2.0/gtk+2.0.post-deinstall
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rm -f etc/gtk-2.0/gtk.immodules
+rm -f etc/gtk-2.0/gdk-pixbuf.loaders
+
diff --git a/main/gtk+2.0/gtk+2.0.post-install b/main/gtk+2.0/gtk+2.0.post-install
new file mode 100644
index 0000000000..80444cfb93
--- /dev/null
+++ b/main/gtk+2.0/gtk+2.0.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+usr/bin/gtk-query-immodules-2.0 > etc/gtk-2.0/gtk.immodules
+usr/bin/gdk-pixbuf-query-loaders > etc/gtk-2.0/gdk-pixbuf.loaders
+
diff --git a/main/gtk+2.0/gtk+2.0.post-upgrade b/main/gtk+2.0/gtk+2.0.post-upgrade
new file mode 120000
index 0000000000..5bd77f90db
--- /dev/null
+++ b/main/gtk+2.0/gtk+2.0.post-upgrade
@@ -0,0 +1 @@
+gtk+2.0.post-install \ No newline at end of file
diff --git a/main/gtk+2.0/gtk+2.0.trigger b/main/gtk+2.0/gtk+2.0.trigger
new file mode 100644
index 0000000000..adaf66bf68
--- /dev/null
+++ b/main/gtk+2.0/gtk+2.0.trigger
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+for i in "$@"; do
+ gtk-update-icon-cache -q -t -f $i
+done
+
diff --git a/main/gtk+3.0/APKBUILD b/main/gtk+3.0/APKBUILD
new file mode 100644
index 0000000000..001341f0c8
--- /dev/null
+++ b/main/gtk+3.0/APKBUILD
@@ -0,0 +1,70 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtk+3.0
+pkgver=3.0.11
+pkgrel=3
+pkgdesc="The GTK+ Toolkit (v3)"
+url="http://www.gtk.org/"
+install="$pkgname.post-install $pkgname.post-upgrade $pkgname.post-deinstall"
+triggers="$pkgname.trigger:/usr/share/icons/*"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="shared-mime-info"
+
+replaces="gtk+"
+replaces_dev="gtk+-dev"
+replaces_doc="gtk+-doc"
+
+# depend on gtk+2.0 for update-icon-cache
+depends="gtk+2.0"
+
+makedepends="pkgconfig
+ atk-dev
+ cairo-dev
+ cups-dev
+ expat-dev
+ gdk-pixbuf-dev
+ gettext-dev
+ glib-dev
+ gnutls-dev
+ gobject-introspection-dev
+ libice-dev
+ libiconv-dev
+ jpeg-dev>=8
+ libx11-dev
+ libxcomposite-dev
+ libxcursor-dev
+ libxdamage-dev
+ libxext-dev
+ libxfixes-dev
+ libxrandr-dev
+ libxi-dev
+ pango-dev
+ tiff-dev
+ zlib-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/gtk+/${pkgver%.*}/gtk+-$pkgver.tar.bz2"
+
+depends_dev="atk-dev pango-dev cairo-dev glib-dev intltool gdk-pixbuf-dev"
+
+_builddir="$srcdir"/gtk+-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --with-xinput=yes \
+ --without-libjasper \
+ --with-included-loaders=png || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+
+ # use gtk+2.0's for now
+ rm "$pkgdir"/usr/bin/gtk-update-icon-cache
+ find "$pkgdir" -name *.la -delete
+}
+
+md5sums="9792d52737b05227659b75eea770fbdf gtk+-3.0.11.tar.bz2"
diff --git a/main/gtk+3.0/gtk+3.0.post-deinstall b/main/gtk+3.0/gtk+3.0.post-deinstall
new file mode 100644
index 0000000000..b1e3f7a683
--- /dev/null
+++ b/main/gtk+3.0/gtk+3.0.post-deinstall
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rm -f etc/gtk-3.0/gtk.immodules
+rm -f etc/gtk-3.0/gdk-pixbuf.loaders
+
diff --git a/main/gtk+3.0/gtk+3.0.post-install b/main/gtk+3.0/gtk+3.0.post-install
new file mode 100644
index 0000000000..0570816c75
--- /dev/null
+++ b/main/gtk+3.0/gtk+3.0.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+usr/bin/gtk-query-immodules-3.0 > etc/gtk-3.0/gtk.immodules
+usr/bin/gdk-pixbuf-query-loaders > etc/gtk-3.0/gdk-pixbuf.loaders
+
diff --git a/main/gtk+3.0/gtk+3.0.post-upgrade b/main/gtk+3.0/gtk+3.0.post-upgrade
new file mode 120000
index 0000000000..f313df3d11
--- /dev/null
+++ b/main/gtk+3.0/gtk+3.0.post-upgrade
@@ -0,0 +1 @@
+gtk+3.0.post-install \ No newline at end of file
diff --git a/main/gtk+3.0/gtk+3.0.trigger b/main/gtk+3.0/gtk+3.0.trigger
new file mode 100644
index 0000000000..adaf66bf68
--- /dev/null
+++ b/main/gtk+3.0/gtk+3.0.trigger
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+for i in "$@"; do
+ gtk-update-icon-cache -q -t -f $i
+done
+
diff --git a/main/gtk-doc/APKBUILD b/main/gtk-doc/APKBUILD
new file mode 100644
index 0000000000..cd434296bb
--- /dev/null
+++ b/main/gtk-doc/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtk-doc
+pkgver=1.17
+pkgrel=0
+pkgdesc="Documentation tool for public library API"
+url="http://www.gtk.org/gtk-doc/"
+arch="all"
+license="GPL FDL"
+depends="docbook-xsl gnome-doc-utils perl pkgconfig"
+makedepends="rarian-dev py-libxml2 gettext"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/$pkgver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="ca52ca10845089da6966d810709d4ee3 gtk-doc-1.17.tar.bz2"
diff --git a/main/gtk-engines/APKBUILD b/main/gtk-engines/APKBUILD
new file mode 100644
index 0000000000..e4b2362913
--- /dev/null
+++ b/main/gtk-engines/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer:
+pkgname=gtk-engines
+pkgver=2.20.2
+pkgrel=2
+pkgdesc="collection of gtk+ engines"
+url="http://www.gtk.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+-dev intltool"
+install=
+subpackages=
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-animation \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="5deb287bc6075dc21812130604c7dc4f gtk-engines-2.20.2.tar.bz2"
diff --git a/main/gtk-vnc/APKBUILD b/main/gtk-vnc/APKBUILD
new file mode 100644
index 0000000000..4be0e9cca6
--- /dev/null
+++ b/main/gtk-vnc/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtk-vnc
+pkgver=0.4.3
+pkgrel=2
+pkgdesc="A VNC viewer widget for GTK"
+url="http://live.gnome.org/gtk-vnc"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev gvncviewer"
+makedepends="gnutls-dev gtk+-dev libiconv-dev gettext-dev intltool expat-dev
+ libgcrypt-dev libgpg-error-dev cyrus-sasl-dev perl-text-csv"
+depends_dev="gtk+-dev gnutls-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --without-python \
+ --with-examples \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+gvncviewer() {
+ pkgdesc="Demo application for gtk-vnc"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="38d3fbacb5d00e630f939e88858206f1 gtk-vnc-0.4.3.tar.bz2"
diff --git a/main/gtk-xfce-engine/APKBUILD b/main/gtk-xfce-engine/APKBUILD
new file mode 100644
index 0000000000..1f7e2cd2a2
--- /dev/null
+++ b/main/gtk-xfce-engine/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtk-xfce-engine
+pkgver=2.8.1
+pkgrel=1
+pkgdesc="A port of Xfce engine to GTK+-2.0"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="pkgconfig gtk+-dev libiconv-dev gettext-dev expat-dev"
+source="http://archive.xfce.org/src/xfce/gtk-xfce-engine/${pkgver%.*}/gtk-xfce-engine-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir"/ -name '*.la' -delete
+}
+md5sums="8a6527b61b0554cda11d06f66a567314 gtk-xfce-engine-2.8.1.tar.bz2"
diff --git a/main/gtkglext/APKBUILD b/main/gtkglext/APKBUILD
new file mode 100644
index 0000000000..9682b6ee89
--- /dev/null
+++ b/main/gtkglext/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=gtkglext
+pkgver=1.2.0
+pkgrel=4
+pkgdesc="GTK+ OpenGL Extension"
+url="http://projects.gnome.org/gtkglext/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="gtk+-dev mesa-dev libice-dev libxxf86vm-dev libxi-dev libx11-dev libxt-dev"
+makedepends="$depends_dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ gtkglext-deprecated.patch"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure \
+ --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="5c3240bfc1b21becd33ce35c5abe6f8d gtkglext-1.2.0.tar.gz
+6305d2938e4084bd9f5221c9459f8bc8 gtkglext-deprecated.patch"
diff --git a/main/gtkglext/gtkglext-deprecated.patch b/main/gtkglext/gtkglext-deprecated.patch
new file mode 100644
index 0000000000..997bc804ac
--- /dev/null
+++ b/main/gtkglext/gtkglext-deprecated.patch
@@ -0,0 +1,76 @@
+--- gtkglext-1.2.0.orig/gtk/gtkglwidget.c
++++ gtkglext-1.2.0/gtk/gtkglwidget.c
+@@ -127,7 +127,7 @@
+ * Synchronize OpenGL and window resizing request streams.
+ */
+
+- if (GTK_WIDGET_REALIZED (widget) && private->is_realized)
++ if (gtk_widget_get_realized (widget) && private->is_realized)
+ {
+ gldrawable = gdk_window_get_gl_drawable (widget->window);
+ gdk_gl_drawable_wait_gdk (gldrawable);
+@@ -154,7 +154,7 @@
+ * Remove OpenGL-capability from widget->window.
+ */
+
+- if (GTK_WIDGET_REALIZED (widget))
++ if (gtk_widget_get_realized (widget))
+ gdk_window_unset_gl_capability (widget->window);
+
+ private->is_realized = FALSE;
+@@ -174,7 +174,7 @@
+ */
+
+ toplevel = gtk_widget_get_toplevel (widget);
+- if (GTK_WIDGET_TOPLEVEL (toplevel) && !GTK_WIDGET_REALIZED (toplevel))
++ if (gtk_widget_is_toplevel (toplevel) && !gtk_widget_get_realized (toplevel))
+ {
+ GTK_GL_NOTE (MISC,
+ g_message (" - Install colormap to the top-level window."));
+@@ -194,7 +194,7 @@
+ * Set a background of "None" on window to avoid AIX X server crash.
+ */
+
+- if (GTK_WIDGET_REALIZED (widget))
++ if (gtk_widget_get_realized (widget))
+ {
+ GTK_GL_NOTE (MISC,
+ g_message (" - window->bg_pixmap = %p",
+@@ -250,8 +250,8 @@
+ GTK_GL_NOTE_FUNC ();
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+- g_return_val_if_fail (!GTK_WIDGET_NO_WINDOW (widget), FALSE);
+- g_return_val_if_fail (!GTK_WIDGET_REALIZED (widget), FALSE);
++ g_return_val_if_fail (gtk_widget_get_has_window (widget), FALSE);
++ g_return_val_if_fail (!gtk_widget_get_realized (widget), FALSE);
+ g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), FALSE);
+
+ /*
+@@ -432,7 +432,7 @@
+ GTK_GL_NOTE_FUNC ();
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+- g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL);
++ g_return_val_if_fail (gtk_widget_get_realized (widget), NULL);
+
+ gldrawable = gdk_window_get_gl_drawable (widget->window);
+ if (gldrawable == NULL)
+@@ -474,7 +474,7 @@
+ GLWidgetPrivate *private;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+- g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL);
++ g_return_val_if_fail (gtk_widget_get_realized (widget), NULL);
+
+ private = g_object_get_qdata (G_OBJECT (widget), quark_gl_private);
+ if (private == NULL)
+@@ -501,7 +501,7 @@
+ gtk_widget_get_gl_window (GtkWidget *widget)
+ {
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+- g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL);
++ g_return_val_if_fail (gtk_widget_get_realized (widget), NULL);
+
+ return gdk_window_get_gl_window (widget->window);
+ }
diff --git a/main/gtkman/APKBUILD b/main/gtkman/APKBUILD
new file mode 100644
index 0000000000..85dd18a989
--- /dev/null
+++ b/main/gtkman/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtkman
+pkgver=0.3
+pkgrel=0
+pkgdesc="GTK+2 manual page viewer"
+url="http://www.salixos.org/wiki/index.php/GTKMan"
+arch="noarch"
+license="GPLv3"
+depends="py-gtk"
+depends_dev=
+makedepends="gettext intltool"
+install=""
+subpackages=
+source="http://people.salixos.org/gapan/gtkman/gtkman-$pkgver.tar.gz"
+
+_builddir="$srcdir"/gtkman
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./compile.sh || return 1
+}
+
+package() {
+ cd "$_builddir"
+ DESTDIR="$pkgdir" ./install.sh || return 1
+}
+
+md5sums="2441a347fb29a5f3d744000c01b4b42e gtkman-0.3.tar.gz"
diff --git a/main/gtkmm/APKBUILD b/main/gtkmm/APKBUILD
new file mode 100644
index 0000000000..e3cdd35881
--- /dev/null
+++ b/main/gtkmm/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtkmm
+pkgver=2.24.0
+pkgrel=2
+pkgdesc="C++ wrappers for GTK+"
+url="http://gtkmm.sourceforge.net/"
+arch="all"
+license="LGPL"
+depends=""
+makedepends="gtk+-dev intltool glibmm-dev pangomm-dev atkmm-dev"
+depends_dev="atkmm-dev gtk+-dev glibmm-dev pangomm-dev"
+subpackages="$pkgname-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/gtkmm-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/gtkmm-$pkgver
+ make install DESTDIR="$pkgdir" || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="d0413781fdb884e0ccba52844c94485f gtkmm-2.24.0.tar.bz2"
diff --git a/main/gtksourceview/APKBUILD b/main/gtksourceview/APKBUILD
new file mode 100644
index 0000000000..93342ad2e2
--- /dev/null
+++ b/main/gtksourceview/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtksourceview
+pkgver=2.10.4
+pkgrel=3
+pkgdesc="A text widget adding syntax highlighting and more to GNOME"
+url="http://live.gnome.org/GtkSourceView"
+arch="all"
+license="GPL"
+depends=
+depends_dev="gtk+-dev libxml2-dev"
+makedepends="$depends_dev gobject-introspection-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/gnome/sources/gtksourceview/${pkgver%.*}/gtksourceview-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/gtksourceview-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/gtksourceview-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="342666cba9eb2643e5166a0cb58203d2 gtksourceview-2.10.4.tar.bz2"
diff --git a/main/gtkspell/APKBUILD b/main/gtkspell/APKBUILD
new file mode 100644
index 0000000000..e0ad7431ba
--- /dev/null
+++ b/main/gtkspell/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gtkspell
+pkgver=2.0.16
+pkgrel=3
+pkgdesc="GtkSpell provides word-processor-style highlighting and replacement of misspelled words in a GtkTextView widget"
+url="http://gtkspell.sourceforge.net/"
+arch="all"
+license="GPL"
+makedepends="gtk+-dev enchant-dev intltool"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://$pkgname.sourceforge.net/download/$pkgname-$pkgver.tar.gz"
+
+depends_dev="gtk+-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="f75dcc9338f182c571b321d37c606a94 gtkspell-2.0.16.tar.gz"
diff --git a/main/gucharmap/APKBUILD b/main/gucharmap/APKBUILD
new file mode 100644
index 0000000000..c341f502fd
--- /dev/null
+++ b/main/gucharmap/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor:
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gucharmap
+pkgver=2.33.2
+pkgrel=1
+pkgdesc="the GNOME Character Map, based on the Unicode Character Database"
+url="http://live.gnome.org/Gucharmap"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/gucharmap/${pkgver%.*}/gucharmap-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-gconf \
+ --disable-scrollkeeper \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="56af6fb2ced601c26f63b804c64ba065 gucharmap-2.33.2.tar.bz2"
diff --git a/main/guile/APKBUILD b/main/guile/APKBUILD
new file mode 100644
index 0000000000..f3fb25372a
--- /dev/null
+++ b/main/guile/APKBUILD
@@ -0,0 +1,44 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=guile
+pkgver=1.8.8
+pkgrel=1
+pkgdesc="Guile is a portable, embeddable Scheme implementation written in C"
+url="http://www.gnu.org/software/guile/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="gmp-dev libtool ncurses-dev texinfo"
+depends=
+install=
+source="ftp://ftp.gnu.org/pub/gnu/$pkgname/$pkgname-$pkgver.tar.gz
+ guile-1.8.7-gcc45.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case "$i" in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-error-on-warning || return 1
+ make LDFLAGS+="-lpthread" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="18661a8fdfef13e2fcb7651720aa53f3 guile-1.8.8.tar.gz
+608a4d2d7bc072d5edc34aa2be1f609f guile-1.8.7-gcc45.patch"
diff --git a/main/guile/guile-1.8.7-gcc45.patch b/main/guile/guile-1.8.7-gcc45.patch
new file mode 100644
index 0000000000..6c9c2cd443
--- /dev/null
+++ b/main/guile/guile-1.8.7-gcc45.patch
@@ -0,0 +1,15 @@
+Fixing docs build with gcc-4.5
+
+http://bugs.gentoo.org/317175
+
+Patch scavenged from
+http://lists.gnu.org/archive/html/guile-devel/2009-11/msg00078.html
+
+--- ./libguile/guile-snarf-docs.in
++++ ./libguile/guile-snarf-docs.in
+@@ -23,4 +23,4 @@
+ ## Let the user override the preprocessor autoconf found.
+ test -n "${CPP+set}" || CPP="@CPP@"
+
+-${CPP} -DSCM_MAGIC_SNARF_DOCS "$@"
++${CPP} -P -DSCM_MAGIC_SNARF_DOCS "$@"
diff --git a/main/gvfs/APKBUILD b/main/gvfs/APKBUILD
new file mode 100644
index 0000000000..70c894574d
--- /dev/null
+++ b/main/gvfs/APKBUILD
@@ -0,0 +1,101 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gvfs
+pkgver=1.9.0
+pkgrel=1
+pkgdesc="Backends for the gio framework in GLib"
+url="http://ftp.gnome.org/pub/gnome/sources/gvfs/${pkgver%.*}/"
+arch="all"
+license="GPL"
+depends=
+triggers="$pkgname.trigger:/usr/lib/gvfs"
+makedepends="dbus-glib-dev intltool fuse-dev udev-dev bluez-dev expat-dev
+ samba-dev libsoup-dev avahi-dev libarchive-dev gnome-disk-utility-dev
+ libgphoto2-dev libcdio-dev"
+install=
+subpackages="$pkgname-dev $pkgname-fuse $pkgname-smb $pkgname-archive
+ $pkgname-obexftp $pkgname-gphoto2"
+source="http://ftp.gnome.org/pub/gnome/sources/gvfs/${pkgver%.*}/gvfs-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/gvfs \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-gdu \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm -f "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/gio/modules/*.la
+}
+
+_mv_files() {
+ local i
+ for i in "$@"; do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i || return 1
+ done
+}
+
+fuse() {
+ pkgdesc="FUSE support for gvfs"
+ triggers=
+ cd "$pkgdir"
+ _mv_files usr/lib/gvfs/gvfs-fuse-daemon
+}
+
+smb() {
+ pkgdesc="Windows fileshare support for gvfs"
+ triggers=
+ cd "$pkgdir"
+ _mv_files \
+ usr/lib/gvfs/gvfsd-smb* \
+ usr/share/gvfs/mounts/smb*
+}
+
+archive() {
+ pkgdesc="Archiving support for gvfs"
+ triggers=
+ cd "$pkgdir"
+ _mv_files \
+ usr/lib/gvfs/gvfsd-archive* \
+ usr/share/gvfs/mounts/archive*
+}
+
+obexftp() {
+ pkgdesc="ObexFTP support for gvfs"
+ triggers=
+ cd "$pkgdir"
+ _mv_files \
+ usr/lib/gvfs/gvfsd-obex* \
+ usr/share/gvfs/mounts/obex*
+}
+
+gphoto2() {
+ pkgdesc="gphoto2 support for gvfs"
+ triggers=
+ cd "$pkgdir"
+ _mv_files \
+ usr/lib/gvfs/gvfs*gphoto* \
+ usr/share/gvfs/*/gphoto* \
+ usr/share/dbus*/services/*GPhoto*
+}
+
+#
+#afc() {
+# pkgdesc="AFC support for gvfs"
+#}
+
+md5sums="c8e44a42819453f6ef78974c568e5460 gvfs-1.9.0.tar.bz2"
diff --git a/main/gvfs/gvfs.trigger b/main/gvfs/gvfs.trigger
new file mode 100644
index 0000000000..e1d7906823
--- /dev/null
+++ b/main/gvfs/gvfs.trigger
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Reload .mount files
+killall -USR1 gvfsd >&/dev/null
+exit 0
+
diff --git a/main/gzip/APKBUILD b/main/gzip/APKBUILD
new file mode 100644
index 0000000000..3b8567b36b
--- /dev/null
+++ b/main/gzip/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gzip
+pkgver=1.4
+pkgrel=2
+pkgdesc="A popular data compression program"
+subpackages="$pkgname-doc"
+url="http://www.gnu.org/software/gzip/"
+arch="all"
+license="GPL2"
+depends=
+makedepends=
+install="$pkgname.post-deinstall"
+source="http://ftp.gnu.org/gnu/gzip/gzip-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+
+ # avoid text relocation
+ export DEFS="NO_ASM"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --disable-nls \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR=$pkgdir install
+
+ mkdir -p "$pkgdir"/bin
+ mv "$pkgdir"/usr/bin/gzip "$pkgdir"/usr/bin/gunzip "$pkgdir"/bin/
+ ln -s /bin/gzip "$pkgdir"/usr/bin/gzip
+ ln -s /bin/gunzip "$pkgdir"/usr/bin/gunzip
+}
+md5sums="e381b8506210c794278f5527cba0e765 gzip-1.4.tar.gz"
diff --git a/main/gzip/gzip.post-deinstall b/main/gzip/gzip.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/gzip/gzip.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/haproxy/APKBUILD b/main/haproxy/APKBUILD
new file mode 100644
index 0000000000..38c43b1c4b
--- /dev/null
+++ b/main/haproxy/APKBUILD
@@ -0,0 +1,29 @@
+# Contributor: Jeff Bilyk <jbilyk@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=haproxy
+pkgver=1.4.11
+pkgrel=0
+pkgdesc="A TCP/HTTP reverse proxy for high availability environments"
+url="http://haproxy.1wt.eu"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages=""
+source="http://haproxy.1wt.eu/download/1.4/src/$pkgname-$pkgver.tar.gz
+ haproxy.initd"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make TARGET=linux26 || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" PREFIX=/usr install
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+
+md5sums="4f0638652d7800860838dc195da335d8 haproxy-1.4.11.tar.gz
+cce88addaac6ee8065633b94c404300d haproxy.initd"
diff --git a/main/haproxy/haproxy.initd b/main/haproxy/haproxy.initd
new file mode 100644
index 0000000000..68b7e0fefb
--- /dev/null
+++ b/main/haproxy/haproxy.initd
@@ -0,0 +1,45 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-proxy/haproxy/files/haproxy.initd,v 1.3 2007/10/27 10:42:32 mrness Exp $
+
+opts="${opts} reload"
+
+CONFFILE=/etc/${SVCNAME}.cfg
+PIDFILE=/var/run/${SVCNAME}.pid
+
+checkconfig() {
+ if [ ! -f "${CONFFILE}" ]; then
+ eerror "${CONFFILE} does not exist!"
+ return 1
+ fi
+ /usr/sbin/haproxy -c -f "${CONFFILE}" >/dev/null
+}
+
+depend() {
+ need net
+ after firewall
+ use dns logger
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start --quiet \
+ --exec /usr/sbin/haproxy \
+ -- -D -p "${PIDFILE}" -f "${CONFFILE}"
+ eend ${?}
+}
+
+stop() {
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --quiet --pidfile "${PIDFILE}"
+ eend ${?}
+}
+
+reload() {
+ ebegin "Reloading ${SVCNAME}"
+ /usr/sbin/haproxy -D -p "${PIDFILE}" -f "${CONFFILE}" -sf $(cat "${PIDFILE}")
+ eend ${?}
+}
diff --git a/main/haserl/APKBUILD b/main/haserl/APKBUILD
new file mode 100644
index 0000000000..e58045d891
--- /dev/null
+++ b/main/haserl/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=haserl
+pkgver=0.9.29
+pkgrel=0
+pkgdesc="Html And Shell Embedded Report Language"
+url="http://haserl.sourceforge.net/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="lua-dev automake autoconf"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ "
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ sed -i -e 's/^ /\t/' src/Makefile.am || return 1
+ rm -f src/haserl_lualib.inc
+
+ aclocal && autoconf && automake --add-missing || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-lua || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir/" install
+ chmod 4111 "$pkgdir"/usr/bin/haserl
+}
+
+md5sums="4cac9409530200b4a7a82a48ec174800 haserl-0.9.29.tar.gz"
diff --git a/main/heimdal/001_all_heimdal-no_libedit.patch b/main/heimdal/001_all_heimdal-no_libedit.patch
new file mode 100644
index 0000000000..a551bdce15
--- /dev/null
+++ b/main/heimdal/001_all_heimdal-no_libedit.patch
@@ -0,0 +1,10 @@
+--- cf/krb-readline.m4 2005-06-16 18:28:32.000000000 +0200
++++ cf/krb-readline.m4 2005-06-27 23:17:06.000000000 +0200
+@@ -6,7 +6,6 @@
+ dnl el_init
+
+ AC_DEFUN([KRB_READLINE],[
+-AC_FIND_FUNC_NO_LIBS(el_init, edit, [], [], [$LIB_tgetent])
+ if test "$ac_cv_func_el_init" = yes ; then
+ AC_CACHE_CHECK(for four argument el_init, ac_cv_func_el_init_four,[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
diff --git a/main/heimdal/002_all_heimdal-fPIC.patch b/main/heimdal/002_all_heimdal-fPIC.patch
new file mode 100644
index 0000000000..c67dbae764
--- /dev/null
+++ b/main/heimdal/002_all_heimdal-fPIC.patch
@@ -0,0 +1,12 @@
+--- lib/editline/Makefile.am 2005-06-16 18:28:44.000000000 +0200
++++ lib/editline/Makefile.am 2005-06-27 23:21:02.000000000 +0200
+@@ -41,6 +41,9 @@
+
+ EXTRA_DIST = $(man_MANS)
+
++$(libeditline_la_OBJECTS): %.lo: %.c
++ $(LTCOMPILE) -fPIC -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
++
+ snprintf.c:
+ $(LN_S) $(srcdir)/../roken/snprintf.c .
+ strdup.c:
diff --git a/main/heimdal/003_all_heimdal-rxapps.patch b/main/heimdal/003_all_heimdal-rxapps.patch
new file mode 100644
index 0000000000..40fc05f083
--- /dev/null
+++ b/main/heimdal/003_all_heimdal-rxapps.patch
@@ -0,0 +1,22 @@
+--- appl/kx/rxtelnet.in 2005-06-16 18:29:10.000000000 +0200
++++ appl/kx/rxtelnet.in 2005-06-27 23:21:34.000000000 +0200
+@@ -2,7 +2,7 @@
+ # $Id: rxtelnet.in,v 1.31 2004/03/07 17:22:06 lha Exp $
+ #
+ usage="Usage: $0 [-l username] [-k] [-fF] [-t args_to_telnet] [-x args_to_xterm] [-K args_to_kx] [-w term_emulator] [-b telnet_binary] [-n] [-v] [-h | --help] [--version] host [port]"
+-binary=telnet
++binary=ktelnet
+ term=
+ kx_args=-P
+ while true
+--- appl/kx/rxterm.in 2005-06-16 18:29:10.000000000 +0200
++++ appl/kx/rxterm.in 2005-06-27 23:21:55.000000000 +0200
+@@ -2,7 +2,7 @@
+ # $Id: rxterm.in,v 1.23 2002/03/18 17:37:34 joda Exp $
+ #
+ usage="Usage: $0 [-l username] [-k] [-f] [-r rsh_args] [-x xterm_args] [-K kx_args] [-w term_emulator] [-b rsh_binary][-v] [-h | --help] [--version] host"
+-binary=rsh
++binary=krsh
+ term=xterm
+ while true
+ do
diff --git a/main/heimdal/005_all_heimdal-suid_fix.patch b/main/heimdal/005_all_heimdal-suid_fix.patch
new file mode 100644
index 0000000000..35a9ed9f6b
--- /dev/null
+++ b/main/heimdal/005_all_heimdal-suid_fix.patch
@@ -0,0 +1,20 @@
+--- appl/su/Makefile.am 2005-06-16 18:27:46.000000000 +0200
++++ appl/su/Makefile.am 2005-06-27 23:25:21.000000000 +0200
+@@ -7,6 +7,7 @@
+ bin_PROGRAMS = su
+ bin_SUIDS = su
+ su_SOURCES = su.c supaths.h
++su_LDFLAGS = -Wl,-z,now
+ man_MANS = su.1
+
+ LDADD = $(LIB_kafs) \
+--- appl/otp/Makefile.am 2005-06-16 18:28:46.000000000 +0200
++++ appl/otp/Makefile.am 2005-06-27 23:25:40.000000000 +0200
+@@ -8,6 +8,7 @@
+ bin_SUIDS = otp
+ otp_SOURCES = otp.c otp_locl.h
+ otpprint_SOURCES = otpprint.c otp_locl.h
++otp_LDFLAGS = -Wl,-z,now
+
+ man_MANS = otp.1 otpprint.1
+
diff --git a/main/heimdal/014_all_heimdal-path.patch b/main/heimdal/014_all_heimdal-path.patch
new file mode 100644
index 0000000000..36a86f1f93
--- /dev/null
+++ b/main/heimdal/014_all_heimdal-path.patch
@@ -0,0 +1,50 @@
+--- appl/rcp/rcp.c.old 2006-05-03 13:31:59.398493625 +0200
++++ appl/rcp/rcp.c 2006-05-03 13:32:04.494485981 +0200
+@@ -34,7 +34,7 @@
+ #include "rcp_locl.h"
+ #include <getarg.h>
+
+-#define RSH_PROGRAM "rsh"
++#define RSH_PROGRAM "krsh"
+
+ struct passwd *pwd;
+ uid_t userid;
+--- appl/rcp/rcp_locl.h.old 2006-05-03 02:30:31.602025409 +0200
++++ appl/rcp/rcp_locl.h 2006-05-03 02:30:35.886018983 +0200
+@@ -64,4 +64,4 @@
+ #define _PATH_CP "/bin/cp"
+ #endif
+ #undef _PATH_RSH
+-#define _PATH_RSH BINDIR "/rsh"
++#define _PATH_RSH BINDIR "/krsh"
+--- appl/telnet/telnetd/telnetd.h.old 2006-05-03 02:23:14.582680939 +0200
++++ appl/telnet/telnetd/telnetd.h 2006-05-03 02:23:23.746667193 +0200
+@@ -192,7 +192,7 @@
+ #endif
+
+ #undef _PATH_LOGIN
+-#define _PATH_LOGIN BINDIR "/login"
++#define _PATH_LOGIN BINDIR "/klogin"
+
+ /* fallbacks */
+
+--- appl/login/shadow.c.old 2006-05-05 06:31:29.517138115 +0200
++++ appl/login/shadow.c 2006-05-05 06:32:26.433052741 +0200
+@@ -38,7 +38,7 @@
+ #ifdef HAVE_SHADOW_H
+
+ #ifndef _PATH_CHPASS
+-#define _PATH_CHPASS "/usr/bin/passwd"
++#define _PATH_CHPASS "/usr/bin/kpasswd"
+ #endif
+
+ static int
+@@ -52,7 +52,7 @@
+ printf("fork /bin/passwd");
+ exit(1);
+ case 0:
+- execlp(_PATH_CHPASS, "passwd", who->pw_name, (char *) 0);
++ execlp(_PATH_CHPASS, "kpasswd", who->pw_name, (char *) 0);
+ exit(1);
+ default:
+ waitpid(pid, &status, 0);
diff --git a/main/heimdal/022_all_heimdal-as-needed.patch b/main/heimdal/022_all_heimdal-as-needed.patch
new file mode 100644
index 0000000000..69c791778a
--- /dev/null
+++ b/main/heimdal/022_all_heimdal-as-needed.patch
@@ -0,0 +1,22 @@
+--- lib/roken/Makefile.am.old 2007-11-05 19:42:53.000000000 +0100
++++ lib/roken/Makefile.am 2007-11-05 19:43:12.000000000 +0100
+@@ -107,7 +107,7 @@
+ ifaddrs.hin \
+ vis.hin
+
+-libroken_la_LIBADD = @LTLIBOBJS@
++libroken_la_LIBADD = @LTLIBOBJS@ $(LIB_crypt)
+
+ $(LTLIBOBJS) $(libroken_la_OBJECTS): roken.h $(XHEADERS)
+
+--- lib/editline/Makefile.am.old 2007-11-05 19:46:08.000000000 +0100
++++ lib/editline/Makefile.am 2007-11-05 20:06:54.000000000 +0100
+@@ -36,6 +36,8 @@
+ unix.h \
+ $(EXTRA_SOURCE)
+
++libeditline_la_LIBADD = $(LIB_tgetent)
++
+ EXTRA_SOURCE = $(ES)
+
+ libel_compat_la_SOURCES = edit_compat.c edit_compat.h
diff --git a/main/heimdal/100-check-com_err-pthread.patch b/main/heimdal/100-check-com_err-pthread.patch
new file mode 100644
index 0000000000..f2a4b637b0
--- /dev/null
+++ b/main/heimdal/100-check-com_err-pthread.patch
@@ -0,0 +1,11 @@
+--- heimdal-1.3.1/cf/check-compile-et.m4.orig
++++ heimdal-1.3.1/cf/check-compile-et.m4
+@@ -61,7 +61,7 @@
+ elif test "${krb_cv_compile_et}" = "yes"; then
+ dnl Since compile_et seems to work, let's check libcom_err
+ krb_cv_save_LIBS="${LIBS}"
+- LIBS="${LIBS} -lcom_err"
++ LIBS="${LIBS} -lcom_err -lpthread"
+ AC_MSG_CHECKING(for com_err)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <com_err.h>]],[[
+ const char *p;
diff --git a/main/heimdal/APKBUILD b/main/heimdal/APKBUILD
new file mode 100644
index 0000000000..eb3e460260
--- /dev/null
+++ b/main/heimdal/APKBUILD
@@ -0,0 +1,175 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=heimdal
+pkgver=1.4
+pkgrel=8
+pkgdesc="An implementation of Kerberos 5"
+arch="all"
+url="http://www.h5l.org/"
+license="BSD"
+depends=
+depends_dev="openssl-dev e2fsprogs-dev db-dev"
+makedepends="autoconf automake db-dev e2fsprogs-dev>=1.41.9-r2 gawk libtool
+ openssl-dev pkgconfig readline-dev sqlite-dev"
+install=
+subpackages="$pkgname-doc $pkgname-dev $pkgname-ftp $pkgname-telnet \
+$pkgname-su $pkgname-rsh $pkgname-rcp $pkgname-pagsh $pkgname-kf"
+source="http://ftp4.de.freesbie.org/pub/misc/heimdal/src/$pkgname-$pkgver.tar.gz
+001_all_heimdal-no_libedit.patch
+002_all_heimdal-fPIC.patch
+003_all_heimdal-rxapps.patch
+005_all_heimdal-suid_fix.patch
+014_all_heimdal-path.patch
+heimdal-1.4-make.patch
+"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ [ -e /usr/lib/libasn1.so ] && echo "## remove old heimdal pkg first ##" && return 1
+
+ cd "$_builddir"
+
+ for i in ../*.patch
+ do
+ msg "Applying patch $i"
+ patch -p0 -i $i || return 1
+ done
+
+ # name clash with ruserpass in netdb.h
+ sed -i -e 's/ruserpass/ruserpw/g' appl/ftp/ftp/*.[ch] || return 1
+
+# sed -i -e 's|var/heimdal|var/lib/heimdal|g' configure.in \
+# doc/setup.texi doc/heimdal.info kadmin/kadmind.8 kdc/kdc.8 \
+# lib/hdb/hdb.h lib/krb5/krb5.conf.5 lib/krb5/krb5.conf.cat5 || return 1
+
+ sh ./autogen.sh || return 1
+}
+
+build() {
+ cd "$_builddir"
+ export LDFLAGS="${LDFLAGS} -Wl,--as-needed"
+ export LIBS="-ldb"
+
+ ./configure --prefix=/usr \
+ --enable-shared=yes \
+ --without-x \
+ --with-berkeley-db \
+ --with-readline-lib=/usr/lib \
+ --with-readline-include=/usr/include/readline \
+ --with-openssl=/usr
+ # workarount a parallell build issue
+ make -C lib/kadm5 kadm5_err.h || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" exec_prefix=/usr sysconfdir=/etc \
+ mandir=/usr/share/man infodir=/usr/share/info datadir=/var/lib/heimdal \
+ localstatedir=/var/lib/heimdal libexecdir=/usr/sbin install
+
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -m644 -D krb5.conf ${pkgdir}/etc/krb5.conf || return 1
+ install -m755 -D ../../heimdal-kadmind.init ${pkgdir}/etc/init.d/heimdal-kadmind
+ install -m755 -D ../../heimdal-kdc.init ${pkgdir}/etc/init.d/heimdal-kdc
+ install -m755 -D ../../heimdal-kpasswdd.init ${pkgdir}/etc/init.d/heimdal-kpasswdd
+
+ # Remove editline, we use libreadline
+ #rm ${pkgdir}/usr/lib/libeditline.* || return 1
+ #rm ${pkgdir}/usr/include/editline.h || return 1
+ #rm ${pkgdir}/usr/share/man/man3/editline.* || return 1
+
+ # Rename daemons and their manpages
+ for i in telnetd ftpd rshd; do
+ mv ${pkgdir}/usr/share/man/man8/${i}.8 ${pkgdir}/usr/share/man/man8/k${i}.8 || return 1
+ mv ${pkgdir}/usr/sbin/${i} ${pkgdir}/usr/sbin/k${i} || return 1
+ done
+
+ # Rename clients and their manpages
+ for i in rcp rsh telnet ftp su login; do
+ if [ -f ${pkgdir}/usr/share/man/man1/${i}.1 ]; then
+ mv ${pkgdir}/usr/share/man/man1/${i}.1 ${pkgdir}/usr/share/man/man1/k${i}.1 || return 1
+ fi
+ mv ${pkgdir}/usr/bin/${i} ${pkgdir}/usr/bin/k${i} || return 1
+ done
+ for i in 1 3 5 8; do
+ rm -rf "$pkgdir"/usr/share/man/cat$i
+ done
+
+ # Remove conflicts
+ # e2fsprogs
+ rm -f "$pkgdir"/usr/bin/compile_et \
+ "$pkgdir"/usr/share/man/man1/compile_et.1
+ # man-page
+ rm "$pkgdir"/usr/share/man/man5/ftpusers.5*
+ # openssl
+ rm "$pkgdir"/usr/share/man/man3/DES*
+ rm "$pkgdir"/usr/share/man/man3/DH*
+ rm "$pkgdir"/usr/share/man/man3/EVP*
+ rm "$pkgdir"/usr/share/man/man3/OpenSSL*
+ rm "$pkgdir"/usr/share/man/man3/RAND*
+ rm "$pkgdir"/usr/share/man/man3/RSA*
+ # erlang
+ rm "$pkgdir"/usr/share/man/man3/os.3*
+
+ # Compress info pages
+ for page in heimdal hx509; do
+ gzip -9 "$pkgdir"/usr/share/info/${page}.info
+ done
+
+ # Install the license
+ install -d "$pkgdir"/usr/share/licenses/$pkgname
+ install -D -m644 "$srcdir"/$pkgname-$pkgver/LICENSE \
+ "$pkgdir"/usr/share/licenses/$pkgname/ || return 1
+}
+
+ftp() {
+ mkdir -p $subpkgdir/usr/bin/
+ mv $pkgdir/usr/bin/kftp $subpkgdir/usr/bin/kftp
+ mkdir -p $subpkgdir/usr/sbin/
+ mv $pkgdir/usr/sbin/kftpd $subpkgdir/usr/sbin/kftpd
+}
+
+telnet() {
+ mkdir -p $subpkgdir/usr/bin/
+ mv $pkgdir/usr/bin/ktelnet $subpkgdir/usr/bin/ktelnet
+ mkdir -p $subpkgdir/usr/sbin/
+ mv $pkgdir/usr/sbin/ktelnetd $subpkgdir/usr/sbin/ktelnetd
+}
+
+su() {
+ mkdir -p $subpkgdir/usr/bin/
+ mv $pkgdir/usr/bin/ksu $subpkgdir/usr/bin/ksu
+}
+
+rsh() {
+ mkdir -p $subpkgdir/usr/bin/
+ mv $pkgdir/usr/bin/krsh $subpkgdir/usr/bin/krsh
+ mkdir -p $subpkgdir/usr/sbin/
+ mv $pkgdir/usr/sbin/krshd $subpkgdir/usr/sbin/krshd
+}
+
+rcp() {
+ mkdir -p $subpkgdir/usr/bin/
+ mv $pkgdir/usr/bin/krcp $subpkgdir/usr/bin/krcp
+}
+
+pagsh() {
+ mkdir -p $subpkgdir/usr/bin/
+ mv $pkgdir/usr/bin/pagsh $subpkgdir/usr/bin/pagsh
+}
+
+kf() {
+ mkdir -p $subpkgdir/usr/bin/
+ mv $pkgdir/usr/bin/kf $subpkgdir/usr/bin/kf
+}
+
+md5sums="31d08bbf47a77827fe97ef3f52b4c9c4 heimdal-1.4.tar.gz
+98e28f11f906c967aac22d6184102c9e 001_all_heimdal-no_libedit.patch
+6d5571bdedba2e2423b90bccdbac2c0a 002_all_heimdal-fPIC.patch
+2feec3924ee5230b54175b4d4000c872 003_all_heimdal-rxapps.patch
+45aeb207f360f9f4e9e0fabc8bfeecbc 005_all_heimdal-suid_fix.patch
+8208ae8c0b6ff5ab4f64af1693e9e396 014_all_heimdal-path.patch
+fa1753ec676029cd59a3ef24da55c144 heimdal-1.4-make.patch"
diff --git a/main/heimdal/heimdal-1.4-make.patch b/main/heimdal/heimdal-1.4-make.patch
new file mode 100644
index 0000000000..e49903f27f
--- /dev/null
+++ b/main/heimdal/heimdal-1.4-make.patch
@@ -0,0 +1,88 @@
+--- lib/asn1/Makefile.am~ 2010-09-13 09:23:34.000000000 +0200
++++ lib/asn1/Makefile.am 2010-10-02 12:08:31.833815205 +0200
+@@ -641,16 +641,16 @@
+
+ asn1parse.h: asn1parse.c
+
+-$(gen_files_krb5) krb5_asn1.hx krb5_asn1-priv.hx: krb5_asn1_files
+-$(gen_files_pkinit) pkinit_asn1.hx pkinit_asn1-priv.hx: pkinit_asn1_files
+-$(gen_files_pkcs8) pkcs8_asn1.hx pkcs8_asn1-priv.hx: pkcs8_asn1_files
+-$(gen_files_pkcs9) pkcs9_asn1.hx pkcs9_asn1-priv.hx: pkcs9_asn1_files
+-$(gen_files_pkcs12) pkcs12_asn1.hx pkcs12_asn1-priv.hx: pkcs12_asn1_files
+-$(gen_files_digest) digest_asn1.hx digest_asn1-priv.hx: digest_asn1_files
+-$(gen_files_kx509) kx509_asn1.hx kx509_asn1-priv.hx: kx509_asn1_files
+-$(gen_files_rfc2459) rfc2459_asn1.hx rfc2459_asn1-priv.hx: rfc2459_asn1_files
+-$(gen_files_cms) cms_asn1.hx cms_asn1-priv.hx: cms_asn1_files
+-$(gen_files_test) test_asn1.hx test_asn1-priv.hx: test_asn1_files
++$(gen_files_krb5) krb5_asn1.hx krb5_asn1-priv.hx krb5_asn1-template.c: krb5_asn1_files
++$(gen_files_pkinit) pkinit_asn1.hx pkinit_asn1-priv.hx pkinit_asn1-template.c: pkinit_asn1_files
++$(gen_files_pkcs8) pkcs8_asn1.hx pkcs8_asn1-priv.hx pkcs8_asn1-template.c: pkcs8_asn1_files
++$(gen_files_pkcs9) pkcs9_asn1.hx pkcs9_asn1-priv.hx pkcs9_asn1-template.c: pkcs9_asn1_files
++$(gen_files_pkcs12) pkcs12_asn1.hx pkcs12_asn1-priv.hx pkcs12_asn1-template.c: pkcs12_asn1_files
++$(gen_files_digest) digest_asn1.hx digest_asn1-priv.hx digest_asn1-template.c: digest_asn1_files
++$(gen_files_kx509) kx509_asn1.hx kx509_asn1-priv.hx kx509_asn1-template.c: kx509_asn1_files
++$(gen_files_rfc2459) rfc2459_asn1.hx rfc2459_asn1-priv.hx rfc2459_asn1-template.c: rfc2459_asn1_files
++$(gen_files_cms) cms_asn1.hx cms_asn1-priv.hx cms_asn1-template.c: cms_asn1_files
++$(gen_files_test) test_asn1.hx test_asn1-priv.hx test_asn1-template.c: test_asn1_files
+
+ rfc2459_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1
+ $(ASN1_COMPILE) --preserve-binary=TBSCertificate --preserve-binary=TBSCRLCertList --preserve-binary=Name --sequence=GeneralNames --sequence=Extensions --sequence=CRLDistributionPoints $(srcdir)/rfc2459.asn1 rfc2459_asn1 || (rm -f rfc2459_asn1_files ; exit 1)
+--- lib/kadm5/Makefile.am~ 2010-10-14 12:25:00.959390842 +0200
++++ lib/kadm5/Makefile.am 2010-10-14 14:14:14.533473440 +0200
+@@ -159,6 +159,8 @@
+
+ kadm5_err.h: kadm5_err.et
+
++$(dist_libkadm5clnt_la_SOURCES): $(nodist_libkadm5clnt_la_SOURCES)
++
+ $(libkadm5clnt_la_OBJECTS) $(libkadm5srv_la_OBJECTS): $(srcdir)/kadm5-protos.h $(srcdir)/kadm5-private.h
+
+ proto_opts = -q -R '^(_|kadm5_c_|kadm5_s_|kadm5_log)' -P comment
+--- lib/otp/Makefile.am~ 2010-10-02 12:17:36.532815203 +0200
++++ lib/otp/Makefile.am 2010-10-02 12:29:52.970815205 +0200
+@@ -74,3 +74,5 @@
+ strlcpy.c \
+ strlwr.c \
+ strncasecmp.c
++
++EXTRA_DIST = version-script.map
+--- /dev/null 2010-10-02 12:15:38.061000000 +0200
++++ lib/otp/version-script.map 2010-10-02 12:18:06.229815205 +0200
+@@ -0,0 +1,25 @@
++HEIMDAL_OTP_1.0 {
++ global:
++ otp_challenge;
++ otp_checksum;
++ otp_db_close;
++ otp_db_open;
++ otp_delete;
++ otp_error;
++ otp_find_alg;
++ otp_get;
++ otp_parse;
++ otp_parse_altdict;
++ otp_parse_hex;
++ otp_parse_stddict;
++ otp_print_hex;
++ otp_print_hex_extended;
++ otp_print_stddict;
++ otp_print_stddict_extended;
++ otp_put;
++ otp_simple_get;
++ otp_verify_user;
++ otp_verify_user_1;
++ local:
++ *;
++};
+diff --git lib/krb5/version-script.map b/lib/krb5/version-script.map
+index f31620c..39f5146 100644
+--- lib/krb5/version-script.map
++++ lib/krb5/version-script.map
+@@ -105,6 +105,7 @@ HEIMDAL_KRB5_2.0 {
+ krb5_cc_get_type;
+ krb5_cc_get_version;
+ krb5_cc_initialize;
++ krb5_cc_last_change_time;
+ krb5_cc_move;
+ krb5_cc_new_unique;
+ krb5_cc_next_cred;
diff --git a/main/heimdal/heimdal-kadmind.init b/main/heimdal/heimdal-kadmind.init
new file mode 100755
index 0000000000..b58ac994df
--- /dev/null
+++ b/main/heimdal/heimdal-kadmind.init
@@ -0,0 +1,24 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/app-crypt/heimdal/files/heimdal-kadmind,v 1.3 2004/09/13 22:44:54 solar Exp $
+
+depend() {
+ need net
+ use heimdal-kdc
+ after logger
+}
+
+start() {
+ ebegin "Starting heimdal kadmind"
+ /usr/sbin/kadmind &
+ echo $! > /var/run/heimdal-kadmind.pid
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping heimdal kadmind"
+ start-stop-daemon --stop --quiet --exec \
+ /usr/sbin/kadmind
+ eend $?
+}
diff --git a/main/heimdal/heimdal-kdc.init b/main/heimdal/heimdal-kdc.init
new file mode 100755
index 0000000000..753a101c30
--- /dev/null
+++ b/main/heimdal/heimdal-kdc.init
@@ -0,0 +1,23 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/app-crypt/heimdal/files/heimdal-kdc,v 1.2 2004/09/13 15:40:34 dragonheart Exp $
+
+depend() {
+ need net
+ after logger
+}
+
+start() {
+ ebegin "Starting heimdal kdc"
+ start-stop-daemon --start --quiet --exec \
+ /usr/sbin/kdc -- --detach
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping heimdal kdc"
+ start-stop-daemon --stop --quiet --exec \
+ /usr/sbin/kdc
+ eend $?
+}
diff --git a/main/heimdal/heimdal-kpasswdd.init b/main/heimdal/heimdal-kpasswdd.init
new file mode 100755
index 0000000000..517cb86210
--- /dev/null
+++ b/main/heimdal/heimdal-kpasswdd.init
@@ -0,0 +1,24 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/app-crypt/heimdal/files/heimdal-kpasswdd,v 1.3 2004/09/13 22:44:54 solar Exp $
+
+depend() {
+ need net
+ use heimdal-kdc
+ after logger
+}
+
+start() {
+ ebegin "Starting heimdal kpasswdd"
+ start-stop-daemon --background --start --quiet --exec \
+ /usr/sbin/kpasswdd
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping heimdal kpasswdd"
+ start-stop-daemon --stop --quiet --exec \
+ /usr/sbin/kpasswdd
+ eend $?
+}
diff --git a/main/hicolor-icon-theme/APKBUILD b/main/hicolor-icon-theme/APKBUILD
new file mode 100644
index 0000000000..17eb2982d7
--- /dev/null
+++ b/main/hicolor-icon-theme/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=hicolor-icon-theme
+pkgver=0.12
+pkgrel=0
+pkgdesc="Freedesktop.org Hicolor icon theme"
+url="http://icon-theme.freedesktop.org/wiki/HicolorTheme"
+arch="noarch"
+license="GPL2"
+depends=""
+makedepends=""
+source="http://icon-theme.freedesktop.org/releases/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="55cafbcef8bcf7107f6d502149eb4d87 hicolor-icon-theme-0.12.tar.gz"
diff --git a/main/hostapd/APKBUILD b/main/hostapd/APKBUILD
new file mode 100644
index 0000000000..cf8b875648
--- /dev/null
+++ b/main/hostapd/APKBUILD
@@ -0,0 +1,111 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=hostapd
+pkgver=0.7.3
+pkgrel=1
+pkgdesc="daemon for wireless software access points"
+url="http://hostap.epitest.fi/hostapd/"
+arch="all"
+license="custom"
+depends=
+makedepends="openssl-dev libnl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://hostap.epitest.fi/releases/$pkgname-$pkgver.tar.gz
+ $pkgname.initd
+ $pkgname.confd"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver/hostapd
+
+prepare() {
+ local conf="$_builddir/.config"
+
+ cd "$_builddir"
+ sed -i -e "s:/etc/hostapd:/etc/hostapd/hostapd:g" \
+ hostapd.conf
+
+ # toolchain setup
+ echo "CC = $CC" > $conf
+
+ # EAP authentication methods
+ echo "CONFIG_EAP=y" >> $conf
+ echo "CONFIG_EAP_MD5=y" >> $conf
+
+ # SSL authentication methods
+ echo "CONFIG_EAP_TLS=y" >> $conf
+ echo "CONFIG_EAP_TTLS=y" >> $conf
+ echo "CONFIG_EAP_MSCHAPV2=y" >> $conf
+ echo "CONFIG_EAP_PEAP=y" >> $conf
+
+ # Enable Wi-Fi Protected Setup
+ echo "CONFIG_WPS=y" >> $conf
+ echo "CONFIG_WPS_UPNP=y" >> $conf
+
+ echo "CONFIG_EAP_GTC=y" >> $conf
+ echo "CONFIG_EAP_SIM=y" >> $conf
+ echo "CONFIG_EAP_AKA=y" >> $conf
+ echo "CONFIG_EAP_PAX=y" >> $conf
+ echo "CONFIG_EAP_PSK=y" >> $conf
+ echo "CONFIG_EAP_SAKE=y" >> $conf
+ echo "CONFIG_EAP_GPSK=y" >> $conf
+ echo "CONFIG_EAP_GPSK_SHA256=y" >> $conf
+
+ # drivers
+ echo "CONFIG_DRIVER_HOSTAP=y" >> $conf
+ echo "CONFIG_DRIVER_WIRED=y" >> $conf
+ echo "CONFIG_DRIVER_PRISM54=y" >> $conf
+
+ # Add include path for madwifi-driver headers
+# echo "CFLAGS += -I/usr/include/madwifi" >> $conf
+# echo "CONFIG_DRIVER_MADWIFI=y" >> $conf
+
+ # enable nl80211 driver"
+ echo "CONFIG_DRIVER_NL80211=y" >> $conf
+ echo "CFLAGS += -I/usr/include/netlink" >> $conf
+ echo "LIBS += -L/usr/lib" >> $conf
+
+ # misc
+ echo "CONFIG_PKCS12=y" >> $conf
+ echo "CONFIG_RADIUS_SERVER=y" >> $conf
+ echo "CONFIG_IAPP=y" >> $conf
+ echo "CONFIG_IEEE80211R=y" >> $conf
+ echo "CONFIG_IEEE80211W=y" >> $conf
+ echo "CONFIG_IEEE80211N=y" >> $conf
+ echo "CONFIG_PEERKEY=y" >> $conf
+ echo "CONFIG_RSN_PREAUTH=y" >> $conf
+
+ # IPv6 support
+ echo "CONFIG_IPV6=y" >> $conf
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+
+ make nt_password_hash || return 1
+ make hlr_auc_gw || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/etc/hostapd
+ install hostapd.conf hostapd.accept hostapd.deny hostapd.eap_user \
+ hostapd.radius_clients hostapd.sim_db hostapd.wpa_psk \
+ "$pkgdir"/etc/hostapd/
+
+ install -Dm755 hostapd "$pkgdir"/usr/sbin/hostapd
+ install -Dm755 hostapd_cli "$pkgdir"/usr/bin/hostapd_cli
+
+ install -Dm755 nt_password_hash "$pkgdir"/usr/bin/nt_password_hash
+ install -Dm755 hlr_auc_gw "$pkgdir"/usr/bin/hlr_auc_gw
+
+ install -Dm755 "$srcdir"/hostapd.initd "$pkgdir"/etc/init.d/hostapd
+ install -Dm644 "$srcdir"/hostapd.confd "$pkgdir"/etc/conf.d/hostapd
+
+ install -Dm644 hostapd.8 "$pkgdir"/usr/share/man/man8/hostapd.8
+ install -Dm644 hostapd_cli.1 "$pkgdir"/usr/share/man/man1/hostapd_cli
+}
+
+md5sums="91a7c8d0f090b7104152d3455a84c112 hostapd-0.7.3.tar.gz
+fdbc94a99eca18f51294b5a96136ffdf hostapd.initd
+c91382209042defa04e79d0ae841a29e hostapd.confd"
diff --git a/main/hostapd/hostapd.confd b/main/hostapd/hostapd.confd
new file mode 100644
index 0000000000..60381153aa
--- /dev/null
+++ b/main/hostapd/hostapd.confd
@@ -0,0 +1,5 @@
+# Space separated list of configuration files
+CONFIGS="/etc/hostapd/hostapd.conf"
+
+# Extra options to pass to hostapd, see hostapd(8)
+OPTIONS=""
diff --git a/main/hostapd/hostapd.initd b/main/hostapd/hostapd.initd
new file mode 100644
index 0000000000..cbf962d8d1
--- /dev/null
+++ b/main/hostapd/hostapd.initd
@@ -0,0 +1,46 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-wireless/hostapd/files/hostapd-0.6.9-init.d,v 1.2 2009/05/17 10:18:18 gurligebis Exp $
+
+opts="start stop reload"
+
+depend() {
+ need net
+ after firewall
+ use logger
+}
+
+checkconfig() {
+ local file
+
+ for file in ${CONFIGS}; do
+ if [ ! -r "${file}" ]; then
+ eerror "hostapd configuration file (${CONFIG}) not found"
+ return 1
+ fi
+ done
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start --exec /usr/sbin/hostapd \
+ -- -B ${OPTIONS} ${CONFIGS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --exec /usr/sbin/hostapd
+ eend $?
+}
+
+reload() {
+ checkconfig || return 1
+
+ ebegin "Reloading ${SVCNAME} configuration"
+ kill -HUP $(pidof /usr/sbin/hostapd) > /dev/null 2>&1
+ eend $?
+}
diff --git a/main/htop/APKBUILD b/main/htop/APKBUILD
new file mode 100644
index 0000000000..cefb719969
--- /dev/null
+++ b/main/htop/APKBUILD
@@ -0,0 +1,22 @@
+# Maintainer:Carlo Landmeter
+pkgname=htop
+pkgver=0.8.3
+pkgrel=2
+pkgdesc="An interactive process viewer for Linux"
+url="http://htop.sourceforge.net"
+arch="all"
+license='GPL'
+depends=
+makedepends="ncurses-dev"
+source="http://surfnet.dl.sourceforge.net/sourceforge/htop/$pkgname-$pkgver.tar.gz"
+
+subpackages="$pkgname-doc"
+
+build() {
+ cd $startdir/src/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man
+ make || return 1
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="5c9f093f9eaddf6e77aa6d54c2116d0c htop-0.8.3.tar.gz"
diff --git a/main/hunspell/APKBUILD b/main/hunspell/APKBUILD
new file mode 100644
index 0000000000..a8409b8b46
--- /dev/null
+++ b/main/hunspell/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=hunspell
+pkgver=1.3.2
+pkgrel=1
+pkgdesc="Spell checker and morphological analyzer library and program"
+url="http://hunspell.sourceforge.net/"
+arch="all"
+license="GPL LGPL MPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="gettext-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/hunspell-$pkgver"
+ ./configure --prefix=/usr \
+ --disable-static \
+ --without-included-gettext || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/hunspell-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="3121aaf3e13e5d88dfff13fb4a5f1ab8 hunspell-1.3.2.tar.gz"
diff --git a/main/hylafax/APKBUILD b/main/hylafax/APKBUILD
new file mode 100644
index 0000000000..a4317908df
--- /dev/null
+++ b/main/hylafax/APKBUILD
@@ -0,0 +1,92 @@
+# Contributor: Cameron Banta <cbanta@gmail.com>
+# Maintainer: Cameron Banta <cbanta@gmail.com>
+pkgname=hylafax
+pkgver=6.0.5
+pkgrel=2
+pkgdesc="Sends and receives faxes"
+url="http://www.hylafax.org/"
+arch="all"
+license="custom"
+#depends on gcc for libgcc_s.so, it's scripts are hardcoded to bash
+depends="ghostscript bash tiff-tools"
+makedepends="zlib-dev tiff-dev"
+install="hylafax.post-install"
+subpackages="$pkgname-doc"
+source="ftp://ftp.hylafax.org/source/$pkgname-$pkgver.tar.gz
+ gcc4.5.1.patch
+ $install
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ patch -p1 < $startdir/gcc4.5.1.patch
+}
+
+build() {
+ cd "$_builddir"
+
+ # the configure script does not handle ccache or distcc
+ export CC=gcc
+ export CXX=g++
+ ./configure --nointeractive --disable-pam \
+ --with-DIR_BIN=/usr/bin \
+ --with-DIR_SBIN=/usr/sbin \
+ --with-DIR_LIB=/usr/lib \
+ --with-DIR_LIBEXEC=/usr/sbin \
+ --with-DIR_LIBDATA=/var/spool/"$pkgname"/lib \
+ --with-DIR_LOCKS=/var/lock \
+ --with-DIR_MAN=/usr/share/man \
+ --with-DIR_SPOOL=/var/spool/"$pkgname" \
+ --with-DIR_HTML=/usr/share/doc/"$pkgname"/html \
+ --with-PATH_IMPRIP="" \
+ --with-SYSVINIT=no \
+ --with-REGEX=yes \
+ --with-LIBTIFF="-ltiff -lz" \
+ --with-DSO=auto \
+ --with-PATH_EGETTY=/bin/false \
+ --with-PATH_VGETTY=/bin/false \
+ || return 1
+ make || return 1
+}
+
+package(){
+ cd "$_builddir"
+
+ # this makefile has issues installing, it doesn't use the standard
+ # install - but the following seems to work
+ mkdir -p "${pkgdir}"/usr/bin "${pkgdir}"/usr/sbin
+ mkdir -p "${pkgdir}"/usr/lib/"$pkgname" "${pkgdir}"/usr/share/man
+ mkdir -p "${pkgdir}"/var/spool/"$pkgname"
+ mkdir -p "${pkgdir}"/var/spool/"$pkgname"/lib
+ touch "${pkgdir}"/var/spool/"$pkgname"/lib/pagesizes
+ chown uucp:uucp "${pkgdir}"/var/spool/"$pkgname"
+ chmod 0600 "${pkgdir}"/var/spool/"$pkgname"
+
+ make \
+ BIN="${pkgdir}/usr/bin" \
+ SBIN="${pkgdir}/usr/sbin" \
+ LIBDIR="${pkgdir}/usr/lib" \
+ LIB="${pkgdir}/usr/lib" \
+ LIBEXEC="${pkgdir}/usr/sbin" \
+ LIBDATA="${pkgdir}/var/spool/$pkgname"/lib \
+ MAN="${pkgdir}/usr/share/man" \
+ SPOOL="${pkgdir}/var/spool/$pkgname" \
+ HTMLDIR="${pkgdir}/usr/share/doc/$pkgname/html" \
+ install || return 1
+
+
+ install -m644 -D "$srcdir/$pkgname-$pkgver/COPYRIGHT" \
+ "$pkgdir"/usr/share/licenses/$pkgname/COPYRIGHT
+ install -m644 -D "$srcdir/$pkgname-$pkgver/README" \
+ "$pkgdir"/usr/share/doc/$pkgname/README
+
+
+ # init.d script is created by faxsetup
+ # - which the user runs after install
+}
+
+md5sums="eb9ac942354ad708e20e4583cec6615f hylafax-6.0.5.tar.gz
+bca78921c75448f63b451098528f5296 gcc4.5.1.patch
+a3553e6fc4de30e80759abe5c663c85b hylafax.post-install"
diff --git a/main/hylafax/gcc4.5.1.patch b/main/hylafax/gcc4.5.1.patch
new file mode 100644
index 0000000000..0ac556a3ca
--- /dev/null
+++ b/main/hylafax/gcc4.5.1.patch
@@ -0,0 +1,13 @@
+diff --git a/configure b/configure
+index e49c08f..c6976fd 100755
+--- a/configure
++++ b/configure
+@@ -2882,7 +2882,7 @@ BuildPortDotH()
+ echo '#define HAS_FCHMOD 1'
+ Note "... configure use of fchmod"
+ CheckFuncDecl fchmod 'extern int fchmod(int, mode_t);' \
+- unistd.h libc.h $OSFCNH sys/stat.h
++ unistd.h $OSFCNH sys/stat.h libc.h
+ }
+ CheckFuncDecl mknod 'extern int mknod(const char*, mode_t, dev_t);' \
+ unistd.h sys/stat.h
diff --git a/main/hylafax/hylafax.post-install b/main/hylafax/hylafax.post-install
new file mode 100644
index 0000000000..839f96f543
--- /dev/null
+++ b/main/hylafax/hylafax.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo " *"
+echo " * Please run faxsetup to configure hylafax"
+echo " *"
diff --git a/main/hypermail/APKBUILD b/main/hypermail/APKBUILD
new file mode 100644
index 0000000000..0ea60140ae
--- /dev/null
+++ b/main/hypermail/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+pkgname=hypermail
+pkgver=2.3.0
+pkgrel=1
+pkgdesc="Mail Archiver"
+url="http://www.hypermail-project.org"
+arch="all"
+license="GPL"
+depends="lua"
+makedepends="pcre-dev bison gdbm-dev"
+install=
+subpackages=""
+source="http://www.hypermail-project.org/$pkgname-$pkgver.tar.gz
+ mdir2mbox.lua"
+_builddir="$srcdir"/hypermail
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-httpddir=/var/www \
+ --with-cgidir=/var/www/cgi-bin
+ make || return 1
+}
+package() {
+ cd "$_builddir"
+
+ #does not understand DESTDIR so going to install ourselves
+ #make DESTDIR="$pkgdir" install
+
+ install -m755 -D archive/rdmsg "$pkgdir"/usr/bin/rdmsg
+ install -m755 -D archive/msg2archive "$pkgdir"/usr/bin/msgarchive
+ install -m755 -D src/hypermail "$pkgdir"/usr/bin/hypermail
+ install -m755 -D "$srcdir"/mdir2mbox.lua "$pkgdir"/usr/bin/mdir2mbox.lua
+}
+
+md5sums="510c46b98314f4e98796719f27865846 hypermail-2.3.0.tar.gz
+079b00d4ea667a0efd6fd370b1a4d5d8 mdir2mbox.lua"
diff --git a/main/hypermail/mdir2mbox.lua b/main/hypermail/mdir2mbox.lua
new file mode 100644
index 0000000000..dd883e02db
--- /dev/null
+++ b/main/hypermail/mdir2mbox.lua
@@ -0,0 +1,96 @@
+#!/usr/bin/lua
+-- This script takes a mlmmj archive "maildir format" directory and
+-- writes out an mbox formatted file to stdout
+-- Copyright (c) 2009 N. Angelacos under the GPL 2 License
+
+require "posix"
+
+-- command line parser, or exit
+check_command_line = function ()
+ local source_dir = arg[1]
+ local source_time = arg[2]
+
+ if (source_dir == nil ) then
+ io.stderr:write("mdir2mbox source_dir [hours]\n" ..
+ "Writes an mbox formatted file to stdout from the files in source_dir\n" ..
+ "If [hours] is given, then only files newer then [hours] are processed\n")
+ os.exit(-1)
+ end
+
+ if (posix.stat(source_dir, "type") ~= "directory") then
+ io.stderr:write(source_dir .. " is not a directory\n")
+ os.exit(-1)
+ end
+
+ return source_dir, source_time
+end
+
+-- Get candidates
+get_candidates = function (source, hours)
+ local all = posix.dir(source)
+ local candidates = {}
+ local timestamp = 0
+
+ if (hours) then
+ timestamp = os.time() - hours * 3600
+ end
+
+ for k,v in ipairs(all) do
+ local st = posix.stat(source .. "/" .. v)
+ if (st) and (st.type == "regular") and (st.mtime > timestamp) then
+ table.insert(candidates,source .. "/" .. v)
+ end
+ end
+
+ return candidates
+end
+
+file_to_mbox = function (path)
+ local fh = io.open(path)
+ if (fh == nil) then
+ return
+ end
+ local headers = ""
+ local l = ""
+ -- get headers
+ repeat
+ headers = headers .. l
+ l = (fh:read("*l") or "" ) .. "\n"
+ until (#l == 1)
+
+ local from = string.match("\n" .. headers, "\nFrom: ([^\n]*)")
+ if from == nil then
+ from = string.match("\n" .. headers, "\nReply-To: ([^\n]*)")
+ end
+ if from == nil then
+ from = "<nobody@nowhere.com>"
+ end
+ from = string.match(from, "<([^>]*)>") or string.match(from, "([^ ]*)")
+
+
+ local date = string.match("\n" .. headers, "\nDate: ([^\n]*)")
+ if date == nil then
+ date = os.date ("%c", posix.stat(path, "mtime"))
+ end
+ local weekday,day,month,year,time,offset = string.match(date, "([^,]*), +(%d+) (%a+) (%d+) ([%d:]*) ([%d]*)")
+
+ print ("From " .. from .. " " .. string.format("%s %s %s %s %s", weekday, month, day, time, year, offset ))
+ print (headers)
+
+ -- get rest of message
+ repeat
+ local foo = fh:read("*l")
+ if foo then
+ print(foo)
+ end
+ until (foo == nil)
+
+fh:close()
+end
+
+candidates = get_candidates(check_command_line ())
+
+for k,v in ipairs(candidates) do
+ file_to_mbox(v)
+end
+print ("")
diff --git a/main/iaxmodem/APKBUILD b/main/iaxmodem/APKBUILD
new file mode 100644
index 0000000000..650004c412
--- /dev/null
+++ b/main/iaxmodem/APKBUILD
@@ -0,0 +1,55 @@
+# Contributor: Cameron Banta <cbanta@gmail.com>
+# Maintainer: Cameron Banta <cbanta@gmail.com>
+pkgname=iaxmodem
+pkgver=1.2.0
+pkgrel=4
+pkgdesc="Softmodem for hylafax that connects to VOIP gateway with IAX"
+url="http://iaxmodem.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends="tiff-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ nocxx.patch"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ # purge usless C++ check
+ patch lib/libiax2/configure < ../nocxx.patch || return 1
+
+ ./configure
+ make || return 1
+ install -m755 -s -D "$srcdir/$pkgname-$pkgver/iaxmodem" \
+ "$pkgdir/usr/sbin/iaxmodem"
+ mkdir -p "$pkgdir/etc/iaxmodem"
+ mkdir -p "$pkgdir/var/log/iaxmodem"
+
+ #library licenses
+ install -m644 -D "$srcdir/$pkgname-$pkgver/lib/libiax2/COPYING" \
+ "$pkgdir"/usr/share/licenses/$pkgname/libiax2.COPYING
+ install -m644 -D "$srcdir/$pkgname-$pkgver/lib/libiax2/COPYING.LIB" \
+ "$pkgdir"/usr/share/licenses/$pkgname/libiax2.COPYING.LIB
+
+ install -m644 -D "$srcdir/$pkgname-$pkgver/lib/spandsp/COPYING" \
+ "$pkgdir"/usr/share/licenses/$pkgname/libspandsp.COPYING
+
+ #docs
+ install -m644 -D "$srcdir/$pkgname-$pkgver/README" \
+ "$pkgdir/usr/share/doc/$pkgname/README"
+ install -m644 -D "$srcdir/$pkgname-$pkgver/FAQ" \
+ "$pkgdir/usr/share/doc/$pkgname/FAQ"
+
+ install -m644 -D "$srcdir/$pkgname-$pkgver/iaxmodem-cfg.ttyIAX" \
+ "$pkgdir/usr/share/doc/$pkgname/iaxmodem-cfg.ttyIAX"
+ install -m644 -D "$srcdir/$pkgname-$pkgver/iaxmodem.init.debian" \
+ "$pkgdir/usr/share/doc/$pkgname/iaxmodem.init.debian"
+ install -m644 -D "$srcdir/$pkgname-$pkgver/config.ttyIAX" \
+ "$pkgdir/usr/share/doc/$pkgname/config.ttyIAX"
+
+}
+
+md5sums="f8b26cfeed188e5c1dcbc5ae5ef923b3 iaxmodem-1.2.0.tar.gz
+28513788ba4d556ccd538867dc6205ab nocxx.patch"
diff --git a/main/iaxmodem/iaxmodem.confd b/main/iaxmodem/iaxmodem.confd
new file mode 100644
index 0000000000..082a920e0b
--- /dev/null
+++ b/main/iaxmodem/iaxmodem.confd
@@ -0,0 +1,7 @@
+# Configfile for /etc/init.d/iaxmodem
+
+# Set the priority of the iaxmodem process
+# Value: (highest) -20..19 (lowest)
+#
+#IAXMODEM_NICE="-5"
+
diff --git a/main/iaxmodem/iaxmodem.initd b/main/iaxmodem/iaxmodem.initd
new file mode 100644
index 0000000000..7f072e6c26
--- /dev/null
+++ b/main/iaxmodem/iaxmodem.initd
@@ -0,0 +1,44 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-misc/iaxmodem/files/iaxmodem.initd,v 1.1 2008/10/14 23:53:39 sbriesen Exp $
+
+description="IAXmodem"
+description_reload="Reread configuration file and make the appropriate changes"
+extra_started_commands="reload"
+command="/usr/sbin/iaxmodem"
+pidfile="/var/run/iaxmodem.pid"
+name="iaxmodem"
+
+depend() {
+ use asterisk
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${description}"
+ start-stop-daemon --start --quiet --pidfile "${pidfile}" \
+ --env TMPDIR="/tmp" --nice ${IAXMODEM_NICE:-0} --exec "${command}"
+ eend ${?}
+}
+
+stop() {
+ local childs=""
+ ebegin "Stopping ${description}"
+ # start-stop-daemon doesn't kill childs reliable, so we
+ # use a combination of pgrep + start-stop-daemon + kill
+ [ -s "${pidfile}" ] && childs=$(pgrep -P $(cat "${pidfile}"))
+ start-stop-daemon --stop --quiet --pidfile "${pidfile}" --retry TERM/10/KILL/5
+ if eend ${?}; then
+ # if there're still childs running, kill them!
+ [ -n "${childs}" ] && kill -KILL ${childs} 2>/dev/null
+ return 0
+ fi
+}
+
+reload() {
+ ebegin "Reloading ${description} configuration"
+ start-stop-daemon --stop --signal HUP --pidfile "${pidfile}"
+ eend ${?}
+}
diff --git a/main/iaxmodem/nocxx.patch b/main/iaxmodem/nocxx.patch
new file mode 100644
index 0000000000..beb1ab9006
--- /dev/null
+++ b/main/iaxmodem/nocxx.patch
@@ -0,0 +1,15 @@
+--- a/configure 2004-12-07 21:34:23.205172545 +0000
++++ b/configure 2004-12-07 21:37:17.726654782 +0000
+@@ -5148,10 +5148,8 @@
+ :
+ else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&5
+-echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&2;}
+- { (exit 1); exit 1; }; }
++See \`config.log' for more details." >&5;}
++ { echo "C++ sucks, ignoring ..." >&5; }; }
+ fi
+
+ ac_ext=cc
diff --git a/main/iceauth/APKBUILD b/main/iceauth/APKBUILD
new file mode 100644
index 0000000000..42712528df
--- /dev/null
+++ b/main/iceauth/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iceauth
+pkgver=1.0.3
+pkgrel=2
+pkgdesc="X.Org ICE authority file utility"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libice-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/iceauth-$pkgver.tar.bz2"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="975ade3f238c1eb10705da0a91e6e8e7 iceauth-1.0.3.tar.bz2"
diff --git a/main/icecast/APKBUILD b/main/icecast/APKBUILD
new file mode 100644
index 0000000000..80e23f14c5
--- /dev/null
+++ b/main/icecast/APKBUILD
@@ -0,0 +1,49 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=icecast
+pkgver=2.3.2
+pkgrel=5
+pkgdesc="Open source media server"
+url="http://www.icecast.org"
+arch="all"
+license="GPL"
+depends=
+install="$pkgname.pre-install"
+pkgusers="icecast"
+pkggroups="icecast"
+makedepends="libxslt-dev libxml2-dev libogg-dev libvorbis-dev libtheora-dev openssl-dev"
+subpackages="$pkgname-doc"
+source="http://downloads.xiph.org/releases/$pkgname/$pkgname-$pkgver.tar.gz
+ conf-change-owner.patch
+ icecast.initd
+ icecast.confd"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 -i "$srcdir"/conf-change-owner.patch
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --localstatedir=/var \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ install -D -m755 ../icecast.initd "$pkgdir"/etc/init.d/icecast
+ install -D -m755 ../icecast.confd "$pkgdir"/etc/conf.d/icecast
+ install -d -D -o icecast -g icecast "$pkgdir"/var/log/icecast
+}
+
+md5sums="ff516b3ccd2bcc31e68f460cd316093f icecast-2.3.2.tar.gz
+d65fe756a3811e21fd8327ec599206c8 conf-change-owner.patch
+9860c914e30d0cfac45eef4cc4e81535 icecast.initd
+37ceeb26f61551e712364a2dffa8c208 icecast.confd"
diff --git a/main/icecast/conf-change-owner.patch b/main/icecast/conf-change-owner.patch
new file mode 100644
index 0000000000..5c87c1f0d0
--- /dev/null
+++ b/main/icecast/conf-change-owner.patch
@@ -0,0 +1,16 @@
+--- icecast-2.3.2/conf/icecast.xml.in.orig
++++ icecast-2.3.2/conf/icecast.xml.in
+@@ -164,11 +164,9 @@
+
+ <security>
+ <chroot>0</chroot>
+- <!--
+ <changeowner>
+- <user>nobody</user>
+- <group>nogroup</group>
++ <user>icecast</user>
++ <group>icecast</group>
+ </changeowner>
+- -->
+ </security>
+ </icecast>
diff --git a/main/icecast/icecast.confd b/main/icecast/icecast.confd
new file mode 100644
index 0000000000..80cdfc57fb
--- /dev/null
+++ b/main/icecast/icecast.confd
@@ -0,0 +1 @@
+ICEC_OPTS="-b -c ${icecast_conf:-/etc/icecast.xml}"
diff --git a/main/icecast/icecast.initd b/main/icecast/icecast.initd
new file mode 100644
index 0000000000..b30027b2fe
--- /dev/null
+++ b/main/icecast/icecast.initd
@@ -0,0 +1,19 @@
+#!/sbin/runscript
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting Icecast 2"
+ start-stop-daemon --start --exec /usr/bin/icecast \
+ -- ${ICEC_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping Icecast 2"
+ start-stop-daemon --stop --exec /usr/bin/icecast
+ eend $?
+}
diff --git a/main/icecast/icecast.pre-install b/main/icecast/icecast.pre-install
new file mode 100644
index 0000000000..7149ba7232
--- /dev/null
+++ b/main/icecast/icecast.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /var/log/icecast -s /bin/false -D icecast 2>/dev/null
+
+exit 0
diff --git a/main/icedtea-web/APKBUILD b/main/icedtea-web/APKBUILD
new file mode 100644
index 0000000000..3a9898816d
--- /dev/null
+++ b/main/icedtea-web/APKBUILD
@@ -0,0 +1,59 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=icedtea-web
+pkgver=1.0.2
+pkgrel=0
+pkgdesc="web integration packages for icedtea"
+url="http://icedtea.classpath.org/wiki/IcedTea-Web"
+arch="all"
+license="GPL"
+depends=openjdk6-jre
+depends_dev="xulrunner-dev openjdk6 gtk+-dev nspr-dev"
+makedepends="tar zip $depends_dev"
+install=""
+subpackages="$pkgname-mozilla $pkgname-doc"
+source="http://icedtea.classpath.org/download/source/icedtea-web-$pkgver.tar.gz"
+
+CPU=`uname -m | sed -e 's/i.86/i386/g' -e 's/x86_64/amd64/g'`
+
+_builddir="$srcdir"/icedtea-web-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr/lib/jvm/java-1.6-openjdk \
+ --datarootdir=/usr/share \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ --with-jdk-home=/usr/lib/jvm/java-1.6-openjdk \
+ --with-pkgversion=Alpine \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+mozilla() {
+ mkdir -p "$subpkgdir"/usr/lib/mozilla/plugins
+ mkdir -p "$subpkgdir"/usr/lib/jvm/java-1.6-openjdk/jre/lib/$CPU
+ mv "$pkgdir"/usr/lib/jvm/java-1.6-openjdk/jre/lib/$CPU/IcedTeaPlugin.so \
+ "$subpkgdir"/usr/lib/jvm/java-1.6-openjdk/jre/lib/$CPU
+ ln -sf /usr/lib/jvm/java-1.6-openjdk/jre/lib/$CPU/IcedTeaPlugin.so \
+ "$subpkgdir"/usr/lib/mozilla/plugins/libjavaplugin.so
+ return 0
+}
+
+md5sums="4b5d80f4b82e53f4947e6782a0472d54 icedtea-web-1.0.2.tar.gz"
diff --git a/main/icon-naming-utils/APKBUILD b/main/icon-naming-utils/APKBUILD
new file mode 100644
index 0000000000..c55416924e
--- /dev/null
+++ b/main/icon-naming-utils/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=icon-naming-utils
+pkgver=0.8.90
+pkgrel=1
+pkgdesc="Maps the new names of icons for Tango to the legacy names used by the GNOME and KDE desktops."
+url="http://tango.freedesktop.org/"
+arch="all"
+license="GPL"
+depends="perl-xml-simple"
+makedepends=""
+source="http://tango.freedesktop.org/releases/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/icon-naming-utils \
+ --localstatedir=/var || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ mv "$pkgdir"/usr/share/pkgconfig "$pkgdir"/usr/lib/pkgconfig || return 1
+ chmod +x "$pkgdir"/usr/lib/icon-naming-utils/icon-name-mapping
+}
+
+md5sums="dd8108b56130b9eedc4042df634efa66 icon-naming-utils-0.8.90.tar.bz2"
diff --git a/main/icu/APKBUILD b/main/icu/APKBUILD
new file mode 100644
index 0000000000..64b09c0964
--- /dev/null
+++ b/main/icu/APKBUILD
@@ -0,0 +1,63 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=icu
+pkgver=4.8
+
+# convert x.y.z to x_y_z
+_x=${pkgver%%.*}
+_y=${pkgver#$_x.}
+_y=${_y%%.*}
+_z=${pkgver#*.*.}
+if [ "$_z" = "$pkgver" ]; then
+ _ver=${_x}_${_y}
+else
+ _ver=${_x}_${_y}_${_z}
+fi
+
+pkgrel=0
+pkgdesc="International Components for Unicode library"
+url="http://www.icu-project.org/"
+arch="all"
+license="custom:icu"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends=
+source="http://download.icu-project.org/files/icu4c/${pkgver}/${pkgname}4c-$_ver-src.tgz
+ "
+
+_builddir="$srcdir"/icu/source
+
+prepare() {
+ cd "$_builddir"
+ local x
+ # https://bugs.icu-project.org/trac/ticket/6102
+ for x in ARFLAGS CFLAGS CPPFLAGS CXXFLAGS FFLAGS LDFLAGS; do
+ sed -i -e "/^${x} =.*/s:@${x}@::" "config/Makefile.inc.in" \
+ || return 1
+ done
+
+ for i in $source; do
+ case "$i" in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ chmod +x "$pkgdir"/usr/bin/icu-config
+ install -Dm644 "$srcdir"/icu/license.html \
+ "$pkgdir"/usr/share/licenses/icu/license.html
+}
+md5sums="e78194c49d7fd8131353aa180d11b789 icu4c-4_8-src.tgz"
diff --git a/main/iftop/APKBUILD b/main/iftop/APKBUILD
new file mode 100644
index 0000000000..c0161cdc9c
--- /dev/null
+++ b/main/iftop/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iftop
+pkgver=0.17
+pkgrel=2
+pkgdesc="iftop does for network usage what top(1) does for CPU usage"
+url="http://www.ex-parrot.com/~pdw/iftop/"
+arch="all"
+license="GPL"
+depends=
+makedepends="libpcap-dev>=1 ncurses-dev"
+subpackages="$pkgname-doc"
+source="http://www.ex-parrot.com/~pdw/$pkgname/download/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr --mandir=/usr/share/man
+ make
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="062bc8fb3856580319857326e0b8752d iftop-0.17.tar.gz"
diff --git a/main/igmpproxy/APKBUILD b/main/igmpproxy/APKBUILD
new file mode 100644
index 0000000000..c0a8b9a5b0
--- /dev/null
+++ b/main/igmpproxy/APKBUILD
@@ -0,0 +1,35 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=igmpproxy
+pkgver=0.1
+pkgrel=2
+pkgdesc="a simple dynamic Multicast Routing Daemon using only IGMP signalling"
+url="http://sourceforge.net/projects/igmpproxy/"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ # our kernel have a patch that changes MAXVIFS
+ # note that this is ABI incompatible
+ sed -i -e 's:^#define MAX_MC_VIFS.*:#define MAX_MC_VIFS MAXVIFS:' \
+ src/igmpproxy.h
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+ # install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ # install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="c56f41ec195bc1fe016369bf74efc5a1 igmpproxy-0.1.tar.gz"
diff --git a/main/imagemagick/APKBUILD b/main/imagemagick/APKBUILD
new file mode 100644
index 0000000000..19fe7b5612
--- /dev/null
+++ b/main/imagemagick/APKBUILD
@@ -0,0 +1,67 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=imagemagick
+pkgver=6.7.0.9
+_pkgver=${pkgver%.*}-${pkgver##*.}
+pkgrel=0
+pkgdesc="A collection of tools and libraries for many image formats"
+url="http://www.imagemagick.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="zlib-dev libpng-dev jpeg-dev freetype-dev perl-dev ghostscript-dev
+ libwebp-dev"
+subpackages="$pkgname-doc $pkgname-dev $pkgname-c++:_cxx"
+source="ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick-$_pkgver.tar.gz"
+
+prepare() {
+ cd "$srcdir/ImageMagick-${_pkgver}"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir/ImageMagick-${_pkgver}"
+
+ # fix doc dir, Gentoo bug 91911
+ sed -i -e \
+ 's:DOCUMENTATION_PATH="${DATA_DIR}/doc/${DOCUMENTATION_RELATIVE_PATH}":DOCUMENTATION_PATH="/usr/share/doc/imagemagick":g' \
+ configure || die
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --without-threads \
+ --without-x \
+ --with-gslib \
+ --with-gs-font-dir=/usr/share/fonts/Type1 \
+ --with-modules
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/ImageMagick-${_pkgver}"
+ make -j1 DESTDIR="$pkgdir" install
+ find "$pkgdir" -name '.packlist' -o -name 'perllocal.pod' \
+ -o -name '*.bs' -delete
+}
+
+dev() {
+ default_dev
+ # we need the plugin .la files in main package since those are
+ # used internally
+ mv "$subpkgdir"/usr/lib/Image*/modules*/coders/*.la \
+ "$pkgdir"/usr/lib/Image*/modules*/coders/
+}
+
+_cxx() {
+ pkgdesc="ImageMagick Magick++ library (C++ bindings)"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libMagick++.so.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="f686d9fa0523f705ee19e9cb518ff10c ImageMagick-6.7.0-9.tar.gz"
diff --git a/main/imap/APKBUILD b/main/imap/APKBUILD
new file mode 100644
index 0000000000..464aed05d1
--- /dev/null
+++ b/main/imap/APKBUILD
@@ -0,0 +1,69 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+# at this point its only php who wants this for imap support
+# if more packages needs the c-client lib we might want to
+# build it shared
+pkgname=imap
+pkgver=2007e
+pkgrel=8
+pkgdesc="An IMAP/POP server"
+url="http://www.washington.edu/imap"
+arch="all"
+license="APACHE"
+subpackages="$pkgname-dev c-client:cclient"
+depends=
+makedepends="openssl-dev"
+source="ftp://ftp.cac.washington.edu/$pkgname/$pkgname-$pkgver.tar.gz
+ c-client-2006k_GENTOO_amd64-so-fix.patch
+ c-client-2006k_KOLAB_Annotations.patch
+ c-client-2007e-ldflags.patch
+ "
+
+prepare() {
+ cd $srcdir/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p1 -i $i || return 1
+ done
+ sed -e "s:-g -fno-omit-frame-pointer -O6:\${CFLAGS}:" \
+ -e "s:SSLDIR=/usr/local/ssl:SSLDIR=/usr:" \
+ -e "s:SSLCERTS=\$(SSLDIR)/certs:SSLCERTS=/etc/ssl/certs:" \
+ -e "s:^CC=.*:CC=${CC:-cc}:" \
+ -i src/osdep/unix/Makefile || return 1
+}
+
+build() {
+ cd $srcdir/$pkgname-$pkgver
+
+ export GCCCFLAGS="$CFLAGS"
+ make slx SPECIALAUTHENTICATORS=ssl EXTRACFLAGS="$CFLAGS -fPIC" \
+ EXTRALDFLAGS="$LDFLAGS" \
+ || return 1
+}
+
+package() {
+ cd $srcdir/$pkgname-$pkgver
+ mkdir -p $pkgdir/usr/sbin
+ install -D -m755 imapd/imapd $pkgdir/usr/sbin/imapd
+ install -D -m755 ipopd/ipop2d $pkgdir/usr/sbin/ipop2d
+ install -D -m755 ipopd/ipop3d $pkgdir/usr/sbin/ipop3d
+ for i in c-client mail imap4r1 rfc822 linkage misc smtp nntp osdep \
+ env_unix env fs ftl nl tcp sslio utf8 utf8aux; do
+ install -D -m644 c-client/$i.h \
+ "$pkgdir"/usr/include/imap/$i.h
+ done
+}
+
+cclient() {
+ pkgdesc="UW IMAP c-client library"
+ cd "$srcdir"/$pkgname-$pkgver
+ install -Dm755 c-client/libc-client.so.1.0.0 \
+ "$subpkgdir"/usr/lib/libc-client.so.1.0.0
+ cd "$subpkgdir"/usr/lib
+ ln -s libc-client.so.1.0.0 libc-client.so.1
+ ln -s libc-client.so.1.0.0 libc-client.so
+}
+md5sums="7903800dc2604000016de070e0c55840 imap-2007e.tar.gz
+7f3937a871edd54203fe51f91423e204 c-client-2006k_GENTOO_amd64-so-fix.patch
+c50f734aa18019ecebfc8737ca27cc22 c-client-2006k_KOLAB_Annotations.patch
+d28962ed76df636ff666c09d420e1451 c-client-2007e-ldflags.patch"
diff --git a/main/imap/c-client-2006k_GENTOO_amd64-so-fix.patch b/main/imap/c-client-2006k_GENTOO_amd64-so-fix.patch
new file mode 100644
index 0000000000..79b067d21f
--- /dev/null
+++ b/main/imap/c-client-2006k_GENTOO_amd64-so-fix.patch
@@ -0,0 +1,13 @@
+diff -r 7c3e6c6ef2ba src/osdep/unix/Makefile
+--- a/src/osdep/unix/Makefile Thu Feb 21 18:51:32 2008 +0100
++++ b/src/osdep/unix/Makefile Thu Feb 21 18:53:15 2008 +0100
+@@ -962,6 +962,9 @@ onceenv:
+ -DRSHPATH=\"$(RSHPATH)\" -DLOCKPGM=\"$(LOCKPGM)\" > OSCFLAGS
+ echo $(BASELDFLAGS) $(EXTRALDFLAGS) > LDFLAGS
+ echo "$(ARRC) $(ARCHIVE) $(BINARIES);$(RANLIB) $(ARCHIVE)" > ARCHIVE
++ echo "`$(CAT) CCTYPE` `$(CAT) CFLAGS` `$(CAT) OSFLAGS` -shared \
++ -Wl,-soname,libc-client.so.1 -o libc-client.so.1.0.0 $(BINARIES)" \
++ >> ARCHIVE
+ echo $(OS) > OSTYPE
+ ./drivers $(EXTRADRIVERS) $(DEFAULTDRIVERS) dummy
+ ./mkauths $(EXTRAAUTHENTICATORS) $(DEFAULTAUTHENTICATORS)
diff --git a/main/imap/c-client-2006k_KOLAB_Annotations.patch b/main/imap/c-client-2006k_KOLAB_Annotations.patch
new file mode 100644
index 0000000000..8eec02d029
--- /dev/null
+++ b/main/imap/c-client-2006k_KOLAB_Annotations.patch
@@ -0,0 +1,448 @@
+Provides get/set ANNOTATIONS support to the c-client library. [Version: 2006k]
+
+diff -r 217555555c77 src/c-client/imap4r1.c
+--- a/src/c-client/imap4r1.c Thu Feb 21 17:37:37 2008 +0100
++++ b/src/c-client/imap4r1.c Thu Feb 21 17:38:15 2008 +0100
+@@ -135,7 +135,8 @@ typedef struct imap_argument {
+ #define MULTIAPPEND 13
+ #define SNLIST 14
+ #define MULTIAPPENDREDO 15
+-
++#define QLIST 16
++#define QSTRING 17
+
+ /* Append data */
+
+@@ -205,12 +206,15 @@ void imap_gc_body (BODY *body);
+ void imap_gc_body (BODY *body);
+ void imap_capability (MAILSTREAM *stream);
+ long imap_acl_work (MAILSTREAM *stream,char *command,IMAPARG *args[]);
++long imap_annotation_work (MAILSTREAM *stream,char *command,IMAPARG *args[]);
+
+ IMAPPARSEDREPLY *imap_send (MAILSTREAM *stream,char *cmd,IMAPARG *args[]);
+ IMAPPARSEDREPLY *imap_sout (MAILSTREAM *stream,char *tag,char *base,char **s);
+ long imap_soutr (MAILSTREAM *stream,char *string);
+ IMAPPARSEDREPLY *imap_send_astring (MAILSTREAM *stream,char *tag,char **s,
+ SIZEDTEXT *as,long wildok,char *limit);
++IMAPPARSEDREPLY *imap_send_qstring (MAILSTREAM *stream,char *tag,char **s,
++ SIZEDTEXT *as,char *limit);
+ IMAPPARSEDREPLY *imap_send_literal (MAILSTREAM *stream,char *tag,char **s,
+ STRING *st);
+ IMAPPARSEDREPLY *imap_send_spgm (MAILSTREAM *stream,char *tag,char *base,
+@@ -2753,6 +2757,84 @@ long imap_getacl (MAILSTREAM *stream,cha
+ args[0] = &ambx; args[1] = NIL;
+ return imap_acl_work (stream,"GETACL",args);
+ }
++
++/* IMAP set annotation
++ * Accepts: mail stream
++ * annotation struct
++ * Returns: T on success, NIL on failure
++ */
++
++long imap_setannotation (MAILSTREAM *stream,ANNOTATION *annotation)
++{
++ IMAPARG *args[4],ambx,apth,aval;
++ long ret;
++
++ ambx.type = ASTRING;
++ ambx.text = (void *) annotation->mbox;
++ args[0] = &ambx;
++
++ apth.type = QSTRING;
++ apth.text = (void *) annotation->entry;
++ args[1] = &apth;
++
++ STRINGLIST *st,*l;
++ ANNOTATION_VALUES *v;
++
++ l = st = mail_newstringlist();
++ v = annotation->values;
++ while(v){
++ l->text.size = strlen((char *) (l->text.data = (unsigned char*)cpystr(v->attr)));
++ l->next = mail_newstringlist();
++ l = l->next;
++ l->text.size = strlen((char *) (l->text.data = (unsigned char*)cpystr(v->value)));
++ if(v->next){
++ l->next = mail_newstringlist();
++ l = l->next;
++ }
++ v = v->next;
++ }
++
++ aval.type = QLIST;
++ aval.text = (void *)st;
++ args[2] = &aval;
++ args[3] = NIL;
++
++ ret = imap_annotation_work(stream, "SETANNOTATION",args);
++ mail_free_stringlist(&st);
++ return ret;
++}
++
++
++
++/* IMAP get annotation
++ * Accepts: mail stream
++ * mailbox name
++ * annotation entry list
++ * annotation attribute list
++ * Returns: T on success with data returned via callback, NIL on failure
++ */
++
++long imap_getannotation (MAILSTREAM *stream,char *mailbox,STRINGLIST *entries, STRINGLIST *attributes)
++{
++ IMAPARG *args[4],ambx,apth,aattr;
++ long ret;
++ ambx.type = ASTRING;
++ ambx.text = (void*) mailbox;
++ args[0] = &ambx;
++
++
++ apth.type = QLIST;
++ apth.text = (void*) entries;
++ args[1] = &apth;
++
++ aattr.type = QLIST;
++ aattr.text = (void*) attributes;
++ args[2] = &aattr;
++
++ args[3] = NIL;
++ ret = imap_annotation_work(stream, "GETANNOTATION",args);
++ return ret;
++}
+
+ /* IMAP list rights
+ * Accepts: mail stream
+@@ -2805,6 +2887,16 @@ long imap_acl_work (MAILSTREAM *stream,c
+ else mm_log ("ACL not available on this IMAP server",ERROR);
+ return ret;
+ }
++ long imap_annotation_work(MAILSTREAM *stream, char *command,IMAPARG *args[])
++{
++ long ret = NIL;
++ IMAPPARSEDREPLY *reply;
++ if (imap_OK (stream,reply = imap_send (stream,command,args)))
++ ret = LONGT;
++ else mm_log (reply->text,ERROR);
++ return ret;
++}
++
+
+ /* IMAP set quota
+ * Accepts: mail stream
+@@ -2937,6 +3029,11 @@ IMAPPARSEDREPLY *imap_send (MAILSTREAM *
+ if (reply = imap_send_astring (stream,tag,&s,&st,NIL,CMDBASE+MAXCOMMAND))
+ return reply;
+ break;
++ case QSTRING: /* atom or string, must be literal? */
++ st.size = strlen ((char *) (st.data = (unsigned char *) arg->text));
++ if (reply = imap_send_qstring (stream,tag,&s,&st,CMDBASE+MAXCOMMAND))
++ return reply;
++ break;
+ case LITERAL: /* literal, as a stringstruct */
+ if (reply = imap_send_literal (stream,tag,&s,arg->text)) return reply;
+ break;
+@@ -2947,6 +3044,18 @@ IMAPPARSEDREPLY *imap_send (MAILSTREAM *
+ do { /* for each list item */
+ *s++ = c; /* write prefix character */
+ if (reply = imap_send_astring (stream,tag,&s,&list->text,NIL,
++ CMDBASE+MAXCOMMAND)) return reply;
++ c = ' '; /* prefix character for subsequent strings */
++ }
++ while (list = list->next);
++ *s++ = ')'; /* close list */
++ break;
++ case QLIST: /* list of strings */
++ list = (STRINGLIST *) arg->text;
++ c = '('; /* open paren */
++ do { /* for each list item */
++ *s++ = c; /* write prefix character */
++ if (reply = imap_send_qstring (stream,tag,&s,&list->text,
+ CMDBASE+MAXCOMMAND)) return reply;
+ c = ' '; /* prefix character for subsequent strings */
+ }
+@@ -3119,6 +3228,32 @@ IMAPPARSEDREPLY *imap_send (MAILSTREAM *
+ reply = imap_sout (stream,tag,CMDBASE,&s);
+ mail_unlock (stream); /* unlock stream */
+ return reply;
++}
++
++/* IMAP send quoted-string
++ * Accepts: MAIL stream
++ * reply tag
++ * pointer to current position pointer of output bigbuf
++ * atom-string to output
++ * maximum to write as atom or qstring
++ * Returns: error reply or NIL if success
++ */
++
++IMAPPARSEDREPLY *imap_send_qstring (MAILSTREAM *stream,char *tag,char **s,
++ SIZEDTEXT *as,char *limit)
++{
++ unsigned long j;
++ char c;
++ STRING st;
++ /* in case needed */
++ INIT (&st,mail_string,(void *) as->data,as->size);
++ /* always write literal if no space */
++ if ((*s + as->size) > limit) return imap_send_literal (stream,tag,s,&st);
++
++ *(*s)++ = '"'; /* write open quote */
++ for (j = 0; j < as->size; j++) *(*s)++ = as->data[j];
++ *(*s)++ = '"'; /* write close quote */
++ return NIL;
+ }
+
+ /* IMAP send atom-string
+@@ -4049,6 +4184,50 @@ void imap_parse_unsolicited (MAILSTREAM
+ }
+ }
+
++ else if (!strcmp (reply->key,"ANNOTATION") && (s = reply->text)){
++ char * mbox;
++ /* response looks like ANNOTATION "mailbox" "entry" ("attr" "value" ["attr" "value"]) ["entry" ("attr "value" ["attr" "value"] )]*/
++ getannotation_t an = (getannotation_t) mail_parameters (NIL,GET_ANNOTATION,NIL);
++
++ mbox = imap_parse_astring (stream, &s, reply,NIL);
++
++ while(*s){
++ ANNOTATION * al = mail_newannotation();
++ al->mbox = cpystr(mbox);
++ t = imap_parse_astring (stream, &s, reply,NIL);
++ al->entry = t;
++ STRINGLIST *strlist;
++ if (s){while (*s == ' ')s++;}
++
++ strlist = imap_parse_stringlist(stream, &s,reply);
++
++ ANNOTATION_VALUES *vlIter, *vlBegin;
++ vlIter = vlBegin = NIL;
++ if (strlist) {
++ while(strlist){
++ if(vlIter){
++ vlIter->next = mail_newannotationvalue();
++ vlIter = vlIter->next;
++ }else{
++ vlIter = mail_newannotationvalue();
++ vlBegin = vlIter;
++ }
++ if ( strlist->text.size )
++ vlIter->attr = cpystr (strlist->text.data);
++ strlist = strlist->next;
++ if(!strlist) continue;
++ if ( strlist->text.size )
++ vlIter->value = cpystr (strlist->text.data);
++ strlist = strlist->next;
++ }
++ }
++ al->values = vlBegin;
++ if (an)
++ (*an) (stream,al);
++ mail_free_annotation(&al);
++ }
++ fs_give ((void **)&mbox);
++ }
+ else if (!strcmp (reply->key,"ACL") && (s = reply->text) &&
+ (t = imap_parse_astring (stream,&s,reply,NIL))) {
+ getacl_t ar = (getacl_t) mail_parameters (NIL,GET_ACL,NIL);
+diff -r 217555555c77 src/c-client/imap4r1.h
+--- a/src/c-client/imap4r1.h Thu Feb 21 17:37:37 2008 +0100
++++ b/src/c-client/imap4r1.h Thu Feb 21 17:38:15 2008 +0100
+@@ -279,3 +279,5 @@ long imap_setquota (MAILSTREAM *stream,c
+ long imap_setquota (MAILSTREAM *stream,char *qroot,STRINGLIST *limits);
+ long imap_getquota (MAILSTREAM *stream,char *qroot);
+ long imap_getquotaroot (MAILSTREAM *stream,char *mailbox);
++long imap_getannotation (MAILSTREAM *stream,char *mailbox,STRINGLIST *entries,STRINGLIST *attributes);
++long imap_setannotation (MAILSTREAM *stream,ANNOTATION *annotation);
+diff -r 217555555c77 src/c-client/mail.c
+--- a/src/c-client/mail.c Thu Feb 21 17:37:37 2008 +0100
++++ b/src/c-client/mail.c Thu Feb 21 17:38:15 2008 +0100
+@@ -69,6 +69,7 @@ static newsrcquery_t mailnewsrcquery = N
+ static newsrcquery_t mailnewsrcquery = NIL;
+ /* ACL results callback */
+ static getacl_t mailaclresults = NIL;
++static getannotation_t mailannotationresults = NIL;
+ /* list rights results callback */
+ static listrights_t maillistrightsresults = NIL;
+ /* my rights results callback */
+@@ -598,6 +599,11 @@ void *mail_parameters (MAILSTREAM *strea
+ ret = (void *) (debugsensitive ? VOIDT : NIL);
+ break;
+
++ case SET_ANNOTATION:
++ mailannotationresults = (getannotation_t) value;
++ case GET_ANNOTATION:
++ ret = (void *) mailannotationresults;
++ break;
+ case SET_ACL:
+ mailaclresults = (getacl_t) value;
+ case GET_ACL:
+@@ -5701,7 +5707,15 @@ ACLLIST *mail_newacllist (void)
+ return (ACLLIST *) memset (fs_get (sizeof (ACLLIST)),0,sizeof (ACLLIST));
+ }
+
+-
++ANNOTATION *mail_newannotation (void)
++{
++ return (ANNOTATION *) memset (fs_get (sizeof (ANNOTATION)),0,sizeof(ANNOTATION));
++}
++
++ANNOTATION_VALUES *mail_newannotationvalue (void)
++{
++ return (ANNOTATION_VALUES *) memset (fs_get (sizeof (ANNOTATION_VALUES)),0,sizeof(ANNOTATION_VALUES));
++}
+ /* Mail instantiate new quotalist
+ * Returns: new quotalist
+ */
+@@ -6024,6 +6038,25 @@ void mail_free_acllist (ACLLIST **al)
+ }
+ }
+
++static void mail_free_annotation_values(ANNOTATION_VALUES **val)
++{
++ if (*val) {
++ if ((*val)->attr) fs_give ((void**) &(*val)->attr);
++ if ((*val)->value) fs_give ((void**) &(*val)->value);
++ mail_free_annotation_values (&(*val)->next);
++ fs_give ((void **) val);
++ }
++}
++void mail_free_annotation(ANNOTATION **al)
++{
++ if (*al) {
++ if((*al)->mbox) fs_give ((void**) &(*al)->mbox);
++ if((*al)->entry) fs_give ((void**) &(*al)->entry);
++ if((*al)->values)
++ mail_free_annotation_values(&(*al)->values);
++ fs_give ((void **) al);
++ }
++}
+
+ /* Mail garbage collect quotalist
+ * Accepts: pointer to quotalist pointer
+diff -r 217555555c77 src/c-client/mail.h
+--- a/src/c-client/mail.h Thu Feb 21 17:37:37 2008 +0100
++++ b/src/c-client/mail.h Thu Feb 21 17:38:15 2008 +0100
+@@ -351,6 +351,8 @@
+ #define SET_SCANCONTENTS (long) 573
+ #define GET_MHALLOWINBOX (long) 574
+ #define SET_MHALLOWINBOX (long) 575
++#define GET_ANNOTATION (long) 576
++#define SET_ANNOTATION (long) 577
+
+ /* Driver flags */
+
+@@ -1043,6 +1045,24 @@ ACLLIST {
+ char *identifier; /* authentication identifier */
+ char *rights; /* access rights */
+ ACLLIST *next;
++};
++
++/* ANNOTATION Response */
++
++#define ANNOTATION_VALUES struct annotation_value_list
++
++ANNOTATION_VALUES {
++ char *attr;
++ char *value;
++ ANNOTATION_VALUES *next;
++};
++
++#define ANNOTATION struct annotation
++
++ANNOTATION {
++ char *mbox;
++ char *entry;
++ ANNOTATION_VALUES * values;
+ };
+
+ /* Quota resource list */
+@@ -1353,6 +1373,7 @@ typedef void (*logouthook_t) (void *data
+ typedef void (*logouthook_t) (void *data);
+ typedef char *(*sslclientcert_t) (void);
+ typedef char *(*sslclientkey_t) (void);
++typedef void (*getannotation_t) (MAILSTREAM *stream,ANNOTATION* annot);
+
+ /* Globals */
+
+@@ -1771,7 +1792,10 @@ SORTPGM *mail_newsortpgm (void);
+ SORTPGM *mail_newsortpgm (void);
+ THREADNODE *mail_newthreadnode (SORTCACHE *sc);
+ ACLLIST *mail_newacllist (void);
++ANNOTATION* mail_newannotation(void);
++ANNOTATION_VALUES* mail_newannotationvalue(void);
+ QUOTALIST *mail_newquotalist (void);
++void mail_free_annotation(ANNOTATION **a);
+ void mail_free_body (BODY **body);
+ void mail_free_body_data (BODY *body);
+ void mail_free_body_parameter (PARAMETER **parameter);
+diff -r 217555555c77 src/mtest/mtest.c
+--- a/src/mtest/mtest.c Thu Feb 21 17:37:37 2008 +0100
++++ b/src/mtest/mtest.c Thu Feb 21 17:38:15 2008 +0100
+@@ -145,6 +145,8 @@ int main ()
+ #endif
+ return NIL;
+ }
++
++void mm_annotation (MAILSTREAM *stream, ANNOTATION *a);
+
+ /* MM command loop
+ * Accepts: MAIL stream
+@@ -195,6 +197,28 @@ void mm (MAILSTREAM *stream,long debug)
+ mail_setflag (stream,arg,"\\DELETED");
+ else puts ("?Bad message number");
+ break;
++ case 'A':
++ {
++ char parms[MAILTMPLEN];
++ prompt("Annotation: ",parms);
++ if (parms) {
++ mail_parameters(stream,SET_ANNOTATION,mm_annotation);
++ STRINGLIST *entries = mail_newstringlist();
++ STRINGLIST *cur = entries;
++ cur->text.size = strlen((char *) (cur->text.data = (unsigned char*)cpystr (parms)));
++ cur->next = NIL;
++
++ STRINGLIST *attributes = mail_newstringlist();
++ cur = attributes;
++ cur->text.size = strlen((char *) (cur->text.data = (unsigned char*)cpystr ("*")));
++ cur->next = NIL;
++
++ imap_getannotation(stream,"INBOX",entries,attributes);
++ mail_free_stringlist(&entries);
++ mail_free_stringlist(&attributes);
++ }
++ }
++ break;
+ case 'E': /* Expunge command */
+ mail_expunge (stream);
+ last = 0;
+@@ -347,7 +371,7 @@ void mm (MAILSTREAM *stream,long debug)
+ case '?': /* ? command */
+ puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Literal,");
+ puts (" MailboxStatus, New Mailbox, Overview, Ping, Quit, Send, Type,");
+- puts ("Undelete, Xit, +, -, or <RETURN> for next message");
++ puts ("Undelete, Xit,Annotation, +, -, or <RETURN> for next message");
+ break;
+ default: /* bogus command */
+ printf ("?Unrecognized command: %s\n",cmd);
+@@ -600,6 +624,18 @@ void prompt (char *msg,char *txt)
+
+ /* Interfaces to C-client */
+
++void mm_annotation (MAILSTREAM *stream, ANNOTATION *a)
++{
++ if(a){
++ fprintf(stderr,"mailbox: %s\nentry: %s\n",a->mbox,a->entry);
++ ANNOTATION_VALUES * v = a->values;
++ while(v){
++ fprintf(stderr,"attr: %s, value: %s\n",v->attr,v->value);
++ v = v->next;
++ }
++ }
++}
++
+
+ void mm_searched (MAILSTREAM *stream,unsigned long number)
+ {
diff --git a/main/imap/c-client-2007e-ldflags.patch b/main/imap/c-client-2007e-ldflags.patch
new file mode 100644
index 0000000000..f341cea39b
--- /dev/null
+++ b/main/imap/c-client-2007e-ldflags.patch
@@ -0,0 +1,35 @@
+--- a/src/osdep/unix/Makefile~ 2010-08-08 02:30:48.000000000 -0400
++++ b/src/osdep/unix/Makefile 2010-08-08 02:31:08.758000018 -0400
+@@ -959,17 +959,17 @@
+ onceenv:
+ @echo Once-only environment setup...
+ echo $(CC) > CCTYPE
+- echo $(BASECFLAGS) '$(EXTRACFLAGS)' -DCHUNKSIZE=$(CHUNKSIZE) > CFLAGS
++ echo `$(CAT) CFLAGS` $(BASECFLAGS) '$(EXTRACFLAGS)' -DCHUNKSIZE=$(CHUNKSIZE) > CFLAGS
+- echo -DCREATEPROTO=$(CREATEPROTO) -DEMPTYPROTO=$(EMPTYPROTO) \
++ echo `$(CAT) OSCFLAGS` -DCREATEPROTO=$(CREATEPROTO) -DEMPTYPROTO=$(EMPTYPROTO) \
+ -DMD5ENABLE=\"$(MD5PWD)\" -DMAILSPOOL=\"$(MAILSPOOL)\" \
+ -DANONYMOUSHOME=\"$(MAILSPOOL)/anonymous\" \
+ -DACTIVEFILE=\"$(ACTIVEFILE)\" -DNEWSSPOOL=\"$(NEWSSPOOL)\" \
+ -DRSHPATH=\"$(RSHPATH)\" -DLOCKPGM=\"$(LOCKPGM)\" \
+ -DLOCKPGM1=\"$(LOCKPGM1)\" -DLOCKPGM2=\"$(LOCKPGM2)\" \
+ -DLOCKPGM3=\"$(LOCKPGM3)\" > OSCFLAGS
+- echo $(BASELDFLAGS) $(EXTRALDFLAGS) > LDFLAGS
++ echo `$(CAT) LDFLAGS` -lcrypt $(BASELDFLAGS) $(EXTRALDFLAGS) > LDFLAGS
+ echo "$(ARRC) $(ARCHIVE) $(BINARIES);$(RANLIB) $(ARCHIVE)" > ARCHIVE
+- echo "`$(CAT) CCTYPE` `$(CAT) CFLAGS` `$(CAT) OSFLAGS` -shared \
++ echo "`$(CAT) CCTYPE` `$(CAT) LDFLAGS` `$(CAT) CFLAGS` `$(CAT) OSFLAGS` -shared \
+ -Wl,-soname,libc-client.so.1 -o libc-client.so.1.0.0 $(BINARIES)" \
+ >> ARCHIVE
+ echo $(OS) > OSTYPE
+--- a/src/osdep/unix/Makefile~ 2010-08-08 04:25:00.000000000 -0400
++++ b/src/osdep/unix/Makefile 2010-08-08 04:36:49.720000021 -0400
+@@ -954,7 +954,7 @@
+
+ # Once-only environment setup
+
+-once: onceenv ckp$(PASSWDTYPE) ssl$(SSLTYPE) osdep.c
++once: ssl$(SSLTYPE) onceenv ckp$(PASSWDTYPE) osdep.c
+
+ onceenv:
+ @echo Once-only environment setup...
diff --git a/main/imlib2/APKBUILD b/main/imlib2/APKBUILD
new file mode 100644
index 0000000000..127b193020
--- /dev/null
+++ b/main/imlib2/APKBUILD
@@ -0,0 +1,41 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=imlib2
+pkgver=1.4.4
+pkgrel=6
+pkgdesc="Library that does image file loading and saving as well as rendering, manipulation, arbitrary polygon support"
+url="http://sourceforge.net/projects/enlightenment/"
+arch="all"
+license="BSD"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="tiff-dev giflib-dev bzip2-dev freetype-dev libxext-dev
+ libpng-dev libid3tag-dev jpeg-dev libsm-dev zlib-dev util-linux-ng-dev"
+source="http://downloads.sourceforge.net/enlightenment/$pkgname-$pkgver.tar.bz2
+ imlib2-png15.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -p0 < "$srcdir"/imlib2-png15.patch
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/imlib2 \
+ --x-libraries=/usr/lib \
+ --disable-mmx \
+ --disable-amd64 \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR=$pkgdir install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/imlib2/*/*.la || return 1
+ install -Dm644 COPYING $pkgdir/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="b6de51879502e857d5b1f7622267a030 imlib2-1.4.4.tar.bz2
+8222a87235e8e0a17c01b81ea12c5184 imlib2-png15.patch"
diff --git a/main/imlib2/imlib2-png15.patch b/main/imlib2/imlib2-png15.patch
new file mode 100644
index 0000000000..d66b918000
--- /dev/null
+++ b/main/imlib2/imlib2-png15.patch
@@ -0,0 +1,78 @@
+# http://sourceforge.net/mailarchive/message.php?msg_id=26972342
+
+$NetBSD: patch-af,v 1.4 2011/01/14 10:02:54 wiz Exp $
+
+Fix build with png-1.5.
+
+--- src/modules/loaders/loader_png.c.orig 2010-02-08 00:29:06.000000000 -0800
++++ src/modules/loaders/loader_png.c 2010-02-08 00:34:14.000000000 -0800
+@@ -58,7 +58,7 @@
+ fclose(f);
+ return 0;
+ }
+- if (setjmp(png_ptr->jmpbuf))
++ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ fclose(f);
+@@ -238,7 +238,7 @@
+ png_structp png_ptr;
+ png_infop info_ptr;
+ DATA32 *ptr;
+- int x, y, j;
++ int x, y, j, interlace;
+ png_bytep row_ptr, data = NULL;
+ png_color_8 sig_bit;
+ int pl = 0;
+@@ -265,7 +265,7 @@
+ png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
+ return 0;
+ }
+- if (setjmp(png_ptr->jmpbuf))
++ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ fclose(f);
+ png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr);
+@@ -274,11 +274,11 @@
+ }
+
+ /* check whether we should use interlacing */
++ interlace = PNG_INTERLACE_NONE;
+ if ((tag = __imlib_GetTag(im, "interlacing")) && tag->val)
+ {
+ #ifdef PNG_WRITE_INTERLACING_SUPPORTED
+- png_ptr->interlaced = PNG_INTERLACE_ADAM7;
+- num_passes = png_set_interlace_handling(png_ptr);
++ interlace = PNG_INTERLACE_ADAM7;
+ #endif
+ }
+
+@@ -286,7 +286,7 @@
+ if (im->flags & F_HAS_ALPHA)
+ {
+ png_set_IHDR(png_ptr, info_ptr, im->w, im->h, 8,
+- PNG_COLOR_TYPE_RGB_ALPHA, png_ptr->interlaced,
++ PNG_COLOR_TYPE_RGB_ALPHA, interlace,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+ #ifdef WORDS_BIGENDIAN
+ png_set_swap_alpha(png_ptr);
+@@ -297,7 +297,7 @@
+ else
+ {
+ png_set_IHDR(png_ptr, info_ptr, im->w, im->h, 8, PNG_COLOR_TYPE_RGB,
+- png_ptr->interlaced, PNG_COMPRESSION_TYPE_BASE,
++ interlace, PNG_COMPRESSION_TYPE_BASE,
+ PNG_FILTER_TYPE_BASE);
+ data = malloc(im->w * 3 * sizeof(char));
+ }
+@@ -344,6 +344,10 @@
+ png_set_shift(png_ptr, &sig_bit);
+ png_set_packing(png_ptr);
+
++#ifdef PNG_WRITE_INTERLACING_SUPPORTED
++ num_passes = png_set_interlace_handling(png_ptr);
++#endif
++
+ for (pass = 0; pass < num_passes; pass++)
+ {
+ ptr = im->data;
diff --git a/main/indent/APKBUILD b/main/indent/APKBUILD
new file mode 100644
index 0000000000..a4d1e95892
--- /dev/null
+++ b/main/indent/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=indent
+pkgver=2.2.10
+pkgrel=4
+pkgdesc="indenting utility"
+url="http://www.gnu.org/software/indent/"
+license="GPL"
+depends=
+makedepends="gettext-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://astromirror.uchicago.edu/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+arch="all"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --without-included-gettext \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="be35ea62705733859fbf8caf816d8959 indent-2.2.10.tar.gz"
diff --git a/main/inkscape/APKBUILD b/main/inkscape/APKBUILD
new file mode 100644
index 0000000000..158cdd0f2b
--- /dev/null
+++ b/main/inkscape/APKBUILD
@@ -0,0 +1,60 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=inkscape
+pkgver=0.48.1
+pkgrel=3
+pkgdesc="A vector-based drawing program - svg compliant"
+url="http://inkscape.sourceforge.net/"
+arch="all"
+license="GPL LGPL"
+makedepends="
+poppler-gtk-dev
+imagemagick-dev
+gtkspell-dev
+gc-dev
+gtkmm-dev
+libxslt-dev
+gsl-dev
+py-xml
+popt-dev
+lcms-dev
+libxml2-dev
+boost-dev
+autoconf automake
+"
+depends="desktop-file-utils"
+install=
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.gz
+ inkscape-png15.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg "$i"; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ aclocal -I m4 && autoconf && automake -a && autoheader
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-python \
+ --with-perl \
+ --without-gnome-vfs \
+ --with-xft \
+ --enable-lcms \
+ --enable-poppler-cairo \
+ --disable-dependency-tracking \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="3c179eb998d49d1c312822e15773bf6d inkscape-0.48.1.tar.gz
+c2d1392e6489af822cb4b41ce3af877b inkscape-png15.patch"
diff --git a/main/inkscape/inkscape-png15.patch b/main/inkscape/inkscape-png15.patch
new file mode 100644
index 0000000000..7318adc5d6
--- /dev/null
+++ b/main/inkscape/inkscape-png15.patch
@@ -0,0 +1,33 @@
+--- inkscape-0.48.1.orig/src/sp-image.cpp
++++ inkscape-0.48.1/src/sp-image.cpp
+@@ -388,7 +388,7 @@
+ {
+ char* name = 0;
+ int compression_type = 0;
+- char* profile = 0;
++ png_byte* profile = 0;
+ png_uint_32 proflen = 0;
+ if ( png_get_iCCP(pngPtr, infoPtr, &name, &compression_type, &profile, &proflen) ) {
+ // g_message("Found an iCCP chunk named [%s] with %d bytes and comp %d", name, proflen, compression_type);
+--- inkscape-0.48.1.orig/src/helper/png-write.cpp
++++ inkscape-0.48.1/src/helper/png-write.cpp
+@@ -165,7 +165,7 @@
+ /* Set error handling. REQUIRED if you aren't supplying your own
+ * error hadnling functions in the png_create_write_struct() call.
+ */
+- if (setjmp(png_ptr->jmpbuf)) {
++ if (setjmp(png_jmpbuf(png_ptr))) {
+ /* If we get here, we had a problem reading the file */
+ fclose(fp);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+--- inkscape-0.48.1.orig/src/extension/internal/pdfinput/svg-builder.cpp
++++ inkscape-0.48.1/src/extension/internal/pdfinput/svg-builder.cpp
+@@ -1443,7 +1443,7 @@
+ return NULL;
+ }
+ // Set error handler
+- if (setjmp(png_ptr->jmpbuf)) {
++ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ return NULL;
+ }
diff --git a/main/inputproto/APKBUILD b/main/inputproto/APKBUILD
new file mode 100644
index 0000000000..2cd469843e
--- /dev/null
+++ b/main/inputproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=inputproto
+pkgver=2.0.2
+pkgrel=0
+pkgdesc="X11 Input extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -m755 -d "$pkgdir"/usr/share/licenses/$pkgname
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="07d54ae098ed4e6dce472f6ef3de05ce inputproto-2.0.2.tar.bz2"
diff --git a/main/installkernel/APKBUILD b/main/installkernel/APKBUILD
new file mode 100644
index 0000000000..e8ca3e1a10
--- /dev/null
+++ b/main/installkernel/APKBUILD
@@ -0,0 +1,18 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=installkernel
+pkgver=3.4
+pkgrel=1
+pkgdesc="Kernel install script from debianutils"
+url="http://packages.qa.debian.org/d/debianutils.html"
+arch="all"
+license="BSD GPL-2 SMAIL"
+subpackages="$pkgname-doc"
+depends=""
+source="http://ftp.debian.org/debian/pool/main/d/debianutils/debianutils_$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/debianutils-$pkgver
+ install -Dm755 installkernel "$pkgdir"/sbin/installkernel
+ install -Dm644 installkernel.8 "$pkgdir"/usr/share/man/man8/installkernel.8
+}
+md5sums="0b37e6a6f318f146741a229ab4bfe93b debianutils_3.4.tar.gz"
diff --git a/main/intltool/APKBUILD b/main/intltool/APKBUILD
new file mode 100644
index 0000000000..adb21f812d
--- /dev/null
+++ b/main/intltool/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=intltool
+pkgver=0.41.1
+pkgrel=0
+pkgdesc="The internationalization tool collection"
+url="http://freedesktop.org/wiki/Software/intltool"
+arch="noarch"
+license="GPL"
+depends="perl perl-xml-parser gettext"
+subpackages="$pkgname-doc"
+source="http://edge.launchpad.net/intltool/trunk/${pkgver}/+download/${pkgname}-${pkgver}.tar.gz"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="d6c91bf06681919ccfdf3624035b75dc intltool-0.41.1.tar.gz"
diff --git a/main/iperf/APKBUILD b/main/iperf/APKBUILD
new file mode 100644
index 0000000000..fea017fa2a
--- /dev/null
+++ b/main/iperf/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iperf
+pkgver=2.0.5
+pkgrel=1
+pkgdesc="tool to measure IP bandwidth using UDP or TCP"
+url="http://iperf.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="44b5536b67719f4250faed632a3cd016 iperf-2.0.5.tar.gz"
diff --git a/main/iproute2-qos/APKBUILD b/main/iproute2-qos/APKBUILD
new file mode 100644
index 0000000000..7c65ac0714
--- /dev/null
+++ b/main/iproute2-qos/APKBUILD
@@ -0,0 +1,26 @@
+# Contributor: Ilya Strelkin <iilluzion@gmail.com>
+# Maintainer: Ilya Strelkin <iilluzion@gmail.com>
+pkgname=iproute2-qos
+pkgver=0.4
+pkgrel=2
+pkgdesc="Scripts to set up quality of service with iproute2"
+url="http://git.alpinelinux.org/cgit/aports"
+arch="all"
+license="GPL"
+depends="iproute2"
+makedepends=""
+source="qos.initd qos.eth0.sample qos.ifb0.sample setup-qos"
+
+build() {
+ install -m755 -D "$srcdir"/setup-qos "$pkgdir"/usr/sbin/setup-qos
+ install -m755 -D "$srcdir"/qos.initd "$pkgdir"/etc/init.d/qos
+ install -m644 -D "$srcdir"/qos.eth0.sample \
+ "$pkgdir"/etc/conf.d/qos.eth0.sample
+ install -m644 -D "$srcdir"/qos.ifb0.sample \
+ "$pkgdir"/etc/conf.d/qos.ifb0.sample
+}
+
+md5sums="13d9c58253905f349b953593036b8134 qos.initd
+79cecb47b3d1f623d2f6790044b3afee qos.eth0.sample
+f1233d4e7e728f16b26302ecb03e418e qos.ifb0.sample
+785aff5d4284c47038a009797c576e34 setup-qos"
diff --git a/main/iproute2-qos/qos.confd b/main/iproute2-qos/qos.confd
new file mode 100644
index 0000000000..60d4093726
--- /dev/null
+++ b/main/iproute2-qos/qos.confd
@@ -0,0 +1,314 @@
+###########################################################################################################
+#
+# Traffic Control configuration
+#
+# Copyright (c) 2009 iilluzion
+#
+# Distributed under GPL-2
+#
+###########################################################################################################
+##### MAIN CONFIGURATION PARAMETERS
+####
+### uplink and downlink rates should be set very precisely
+## RATE_SUB_PERCENT should be set to allow the Router to control a queue
+#
+###########################################################################################################
+# Specify the upload speed of your internet connection (kbit, mbit).
+# Since ISPs tend to overestimate the speeds they offer, it would
+# probably be best if you measure this on a free line.
+#
+### UPLINK_RATE=128kbit
+### UPLINK_RATE=256kbit
+UPLINK_RATE=512kbit
+
+
+###########################################################################################################
+# Specify the download speed of your internet connection (kbit, mbit).
+#
+### DOWNLINK_RATE=256kbit
+### DOWNLINK_RATE=512kbit
+DOWNLINK_RATE=1024kbit
+
+
+###########################################################################################################
+# In order to prevent traffic queuing at the ISP side or in your modem,
+# we shape to a slightly lower rate. This way the bottleneck is the router,
+# not the ISP or modem, which allows us more direct control of shaping.
+#
+### RATE_SUB_PERCENT=20
+### RATE_SUB_PERCENT=15
+RATE_SUB_PERCENT=10
+
+
+###########################################################################################################
+# Specify the local network speed (kbit, mbit)
+#
+LAN_RATE=9mbit
+
+
+###########################################################################################################
+##### ADVANCED CONFIGURATION PARAMETERS
+####
+###
+##
+#
+###########################################################################################################
+# Helper Functions
+#
+# Convert rate to bites per second format (bits)
+bits()
+{
+ RATE=0
+ R_RATE=$1
+ R_NUMBER=`echo "$R_RATE" | sed -e "s/[^0-9]//g"`
+ R_UNIT=`echo "$R_RATE" | sed -e "s/[0-9]//g"`
+
+ if [ "$R_UNIT" == "" ]; then
+ R_UNIT="kbit"
+ fi
+
+ if [ "$R_UNIT" == "kbps" ]; then R_RATE=$(($R_NUMBER * 1024 * 8))
+ elif [ "$R_UNIT" == "mbps" ]; then R_RATE=$(($R_NUMBER * 1024 * 1024 * 8))
+ elif [ "$R_UNIT" == "mbit" ]; then R_RATE=$(($R_NUMBER * 1024 * 1024))
+ elif [ "$R_UNIT" == "kbit" ]; then R_RATE=$(($R_NUMBER * 1024))
+ elif [ "$R_UNIT" == "bps" ]; then R_RATE=$(($R_NUMBER * 8))
+ else
+ echo "Unknown unit '$R_UNIT' (mbps, mbit, kbit, bps)"
+ fi
+
+ echo "$R_RATE"
+}
+
+###########################################################################################################
+# Define supported Queuing Disciplines
+#
+QDISCS="prio|tbf|htb|hfsc|sfq|red|pfifo"
+
+
+###########################################################################################################
+# Traffic Control parameters will be calculated depending on link directions
+#
+DIRECTION=$1
+
+
+###########################################################################################################
+# Specify the network devices that are connected to the internet.
+# If you are a dialup or PPPoE user, you have to re-run the QoS script
+# every time you connect.
+#
+### WAN_DEVICES="ppp0"
+WAN_DEVICES="$(ip route show 0.0.0.0/0 | grep dev | sed 's/.*dev //' | awk '{print $1}')"
+ WAN_DEVICES="$WAN_DEVICES $(ip addr | grep gre | egrep -v "gre0" | awk '/^[0-9]/ { gsub(":", ""i, $2); print $2}' | cut -f 1 -d'@')"
+
+
+###########################################################################################################
+# Specify the network devices which are connected with your local network segments.
+#
+### LAN_DEVICES="eth1"
+LAN_DEVICES=`awk -F: 'NR > 2 { print $1 }' /proc/net/dev | egrep -v "lo|gre0|$(echo $WAN_DEVICES | sed s/" "/"|"/g)"`
+
+
+###########################################################################################################
+# Calculaton of WAN up/down link rates
+#
+DIRECTION=${DIRECTION:-ALL}
+ if [ $DIRECTION = "ALL" ]; then
+ DEVICES="$WAN_DEVICES $LAN_DEVICES"
+ fi
+
+ if [ $DIRECTION = "UP" ]; then
+ WAN_RATE=`bits $UPLINK_RATE`
+ DEVICES=$WAN_DEVICES
+ fi
+
+ if [ $DIRECTION = "DOWN" ]; then
+ WAN_RATE=`bits $DOWNLINK_RATE`
+ DEVICES=$LAN_DEVICES
+ fi
+
+ WAN_SUB_RATE=$((WAN_RATE - (RATE_SUB_PERCENT * WAN_RATE / 100)))
+ INTERACTIVE_RATE=$((WAN_SUB_RATE / 5))
+ PRIVILEGED_RATE=$((WAN_SUB_RATE / 2))
+ BESTEFFORT_RATE=$((WAN_SUB_RATE / 3))
+
+ OUT_OF_WAN_RATE=`bits $LAN_RATE`
+ OUT_OF_WAN_RATE=$((OUT_OF_WAN_RATE - WAN_RATE))
+
+
+###########################################################################################################
+# Specify root Queuing Disciplines
+#
+# Recommendations:
+# htb: if link is not congested or you want to control busrts of traffic; recommended for downstream.
+# hfsc: if link is congested and you need to control guarantees of delay; recommended for upstream.
+# dmax = 50-100 [ms] = 50000-100000 [microsec]
+# umax = MIN (rate * (dmax / 1000), 1500) [b]
+# prio: if rate is variable and you want to be sure that interactive traffic has ultimate priority
+# none: if no egress shaping is desired
+# (in this case you may want to setup only ingress policing)
+#
+DOWNLINK_QDISC=htb
+### DOWNLINK_QDISC=hfsc
+### DOWNLINK_QDISC=prio
+### DOWNLINK_QDISC=none
+#
+UPLINK_QDISC=hfsc
+### UPLINK_QDISC=htb
+### UPLINK_QDISC=prio
+### UPLINK_QDISC=none
+
+
+###########################################################################################################
+# Calculation of Queuing Discipline parameters
+#
+INTERACTIVE_PRIO_LATENCY=50000
+INTERACTIVE_PRIO_BURST=$((INTERACTIVE_RATE / 100 / 8))
+#
+INTERACTIVE_HFSC_DMAX=50000
+INTERACTIVE_HFSC_UMAX=$((INTERACTIVE_RATE * INTERACTIVE_HFSC_DMAX / 1000 / 1000))
+ [ $INTERACTIVE_HFSC_UMAX -gt 1500 ] && INTERACTIVE_HFSC_UMAX=1500
+#
+PRIVILEGED_HFSC_DMAX=100000
+PRIVILEGED_HFSC_UMAX=$((PRIVILEGED_RATE * PRIVILEGED_HFSC_DMAX / 1000 / 1000))
+ [ $PRIVILEGED_HFSC_UMAX -gt 1500 ] && PRIVILEGED_HFSC_UMAX=1500
+
+
+###########################################################################################################
+# Specify INGRESS policing
+#
+# Recommendations:
+# none: if link is not congested
+# police: if link is constantly congested
+#
+### DOWNLINK_INGRESS=police
+DOWNLINK_INGRESS=none
+### UPLINK_INGRESS=police
+UPLINK_INGRESS=none
+
+
+###########################################################################################################
+# Calculation of policing bursts
+# burst = rate / 17 (taken basing on experemental results)
+#
+POLICE_BURST_SCALE=17
+ INTERACTIVE_POLICE_BURST=$((INTERACTIVE_RATE / POLICE_BURST_SCALE))
+ PRIVILEGED_POLICE_BURST=$((PRIVILEGED_RATE / POLICE_BURST_SCALE))
+ BESTEFFORT_POLICE_BURST=$((BESTEFFORT_RATE / POLICE_BURST_SCALE))
+
+
+###########################################################################################################
+# Specify leaf Queuing Disciplines
+# Recommendations:
+# "pfifo limit 5": Interactive, Priviledged (real-time streams, IPSEC)
+# "sfq perturb 10": Best-Effort (TCP sessions or best-effort class traffic)
+# "red <parameters>": Best-Effort (hightly congested links or high-speed Internet [> 10Mbit/sec])
+# Random Early Detect (RED) parameters calculation:
+# min = maximum delay * rate (dalay ~ 200ms = 0.2sec) [b]
+# max = 3 * min [b]
+# avpkt = 1000 (MTU 1500)
+# limit = 8 * max [b]
+# burst = (min + min + max)/(3 * avpkt) [b]
+# probability = 0.02
+INTERACTIVE_LEAF_QDISC="pfifo limit 5"
+PRIVILEGED_LEAF_QDISC="pfifo limit 5"
+### BESTEFFORT_LEAF_QDISC="sfq perturb 10"
+#
+RED_DELAY=200
+RED_MIN=$((RED_DELAY * BESTEFFORT_RATE / 1000 / 8)) # devided on 8 since rate given in bit/s so we get bytes
+RED_MAX=$((3 * RED_MIN))
+RED_AVPKT=1000
+RED_PROB=0.02
+RED_BURST=$(((RED_MIN + RED_MIN + RED_MAX) / (3 * RED_AVPKT)))
+RED_LIMIT=$((8 * RED_MAX))
+#
+ BESTEFFORT_LEAF_QDISC="red min $RED_MIN max $RED_MAX burst $RED_BURST limit $RED_LIMIT probability $RED_PROB avpkt $RED_AVPKT"
+#
+LAN_LEAF_QDISC="sfq perturb 10"
+
+
+###########################################################################################################
+# Specify filter rules (see tc, tc-filters man page).
+# You may have multiple <CLASS-NAME>_FILTER_<n> items.
+# Maximum 100 filter items are allowed for each class
+#
+# Interactive Class Traffic Filters
+#
+# UDP
+#
+INTERACTIVE_FILTER_1="protocol ip prio 100 u32 match ip protocol 0x11 0xff"
+#
+# ICMP
+#
+INTERACTIVE_FILTER_2="protocol ip prio 100 u32 match ip protocol 0x1 0xff"
+#
+# ACK with payload < 64 bytes (32-bit version)
+#
+INTERACTIVE_FILTER_3="protocol ip prio 100 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33"
+#
+# ACK with payload < 64 bytes
+#
+INTERACTIVE_FILTER_4="protocol ip prio 100 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2"
+#
+# TOS: 0x10, 0x18, 0xb8(ef)
+#
+INTERACTIVE_FILTER_5="protocol ip prio 100 u32 match ip tos 0x10 0xff"
+INTERACTIVE_FILTER_6="protocol ip prio 100 u32 match ip tos 0x18 0xff"
+INTERACTIVE_FILTER_7="protocol ip prio 100 u32 match ip tos 0xb8 0xff"
+
+
+###########################################################################################################
+# Priviledged Class Traffic Filters
+#
+# SSH
+#
+PRIVILEGED_FILTER_1="protocol ip prio 100 u32 match ip dport 22 0xffff"
+PRIVILEGED_FILTER_2="protocol ip prio 100 u32 match ip sport 22 0xffff"
+#
+# Remote Desktop
+#
+PRIVILEGED_FILTER_3="protocol ip prio 100 u32 match ip dport 3389 0xffff"
+PRIVILEGED_FILTER_4="protocol ip prio 100 u32 match ip sport 3389 0xffff"
+#
+# ESP
+#
+PRIVILEGED_FILTER_5="protocol ip prio 100 u32 match ip protocol 0x32 0xff"
+#
+# AH
+#
+PRIVILEGED_FILTER_6="protocol ip prio 100 u32 match ip protocol 0x33 0xff"
+#
+# TOS: 0x88(af41)
+#
+PRIVILEGED_FILTER_7="protocol ip prio 100 u32 match ip tos 0x88 0xff"
+#
+# IPSEC-NAT
+#
+PRIVILEGED_FILTER_8="protocol ip prio 90 u32 match ip protocol 0x11 0xff match ip dport 4500 0xffff"
+PRIVILEGED_FILTER_9="protocol ip prio 90 u32 match ip protocol 0x11 0xff match ip sport 4500 0xffff"
+
+
+###########################################################################################################
+# Best-Effort Class Traffic Filters
+# By default ALL unclassified traffic is being assined to Best-Effort class
+# You may specify additional filters here
+#
+# Examples: Any traffic from/to 192.168.1.0/24 network will be unconditionally classified as best-effort
+#
+### BESTEFFORT_FILTER_1="protocol ip prio 3 u32 match ip src 192.168.1.0/24"
+### BESTEFFORT_FILTER_2="protocol ip prio 4 u32 match ip dst 192.168.1.0/24"
+#
+
+###########################################################################################################
+# LAN Class Traffic Filters
+#
+# Traffic Originated from router
+#
+# Example:
+###LAN_FILTER_1="protocol ip prio 10 u32 match ip src 192.168.1.10"
+
+#
+##
+###
+####
+##### END OF GENERIC ALPINE SETUP
+###########################################################################################################
diff --git a/main/iproute2-qos/qos.eth0.sample b/main/iproute2-qos/qos.eth0.sample
new file mode 100644
index 0000000000..1578dfa572
--- /dev/null
+++ b/main/iproute2-qos/qos.eth0.sample
@@ -0,0 +1,151 @@
+# Device being configured
+DEV=eth0
+
+# IFB device is used to mirror ingress traffic from $DEV (see INGRESS_ALG)
+IFB_DEV=ifb0 # Leave blank if $DEV is ifbX
+
+# Internet EGRESS/INGRES rates in kbit or mbit. Measure this on a free line to gain precise value
+EGRESS_RATE=512kbit # 128kbit, 256kbit, 512kbit
+INGRESS_RATE=2048kbit # 256kbit, 512kbit, 1024kbit
+
+# In order to control a queue at the router/bridge side we will downgrade a real link speed on purpose
+RATE_SUB_PERCENT=5 # 20, 10
+
+# Device physical speed in kbit or mbit
+DEV_RATE=50mbit
+
+# EGRESS root Classfull Disciplins
+#
+# htb: if link is not congested or you want to control busrts of traffic; recommended for downstream.
+# hfsc: if link is congested and you need to control guarantees of delay; recommended for upstream.
+# dmax = 50-100 [ms] = 50000-100000 [microsec]
+# umax = MIN (rate * (dmax / 1000), 1500) [b]
+# prio: if rate is variable and you want to be sure that interactive traffic has ultimate priority
+# none: if link is not congested
+#
+EGRESS_ALG=htb
+
+# EGRESS leaf Queuing Disciplines
+#
+# pfifo: real-time streams or IPSEC
+# sfq: TCP sessions or best-effort class traffic
+# red: hightly congested links or high-speed Internet [> 10Mbit/sec])
+#
+INTERACTIVE_LEAF_QDISC=pfifo
+PRIVILEGED_LEAF_QDISC=pfifo
+BESTEFFORT_LEAF_QDISC=red
+LAN_LEAF_QDISC=sfq
+
+# INGRESS treatment
+#
+# police: if link is constantly heavy congested set simple traffic policing
+# cpolice: if link is constantly heavy congested but you need certain dedicated rates then set classfull traffic policiing
+# ifb: shape INGRESS traffic as EGRESS of intermediate IFB device (aka imq)
+# none: if link is not congested
+#
+INGRESS_ALG=ifb
+
+# Filter rules (see tc, tc-filters man pages).
+# You may have multiple <CLASS-NAME>_FILTER_<n> items.
+# Maximum 100 filter items are allowed for each class.
+# By default ALL unclassified traffic is being assined to Best-Effort class.
+
+###################################
+### INTERACTIVE FILTERING RULES ###
+###################################
+
+# ACK with payload < 64 bytes (32-bit version)
+INTERACTIVE_FILTER_10="protocol ip prio 10 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33"
+
+# ACK with payload < 64 bytes
+INTERACTIVE_FILTER_11="protocol ip prio 11 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2"
+
+# PHB TOS HEX NOTES
+# ----------------------------------------------
+# 0x10 SSH, IAX2
+# 0x18
+# CS1 PRIORITY 0x20
+# AF11 0x28
+# AF12 0x30
+# AF13 0x38
+#
+# CS2 IMMEDIATE 0x40
+# AF21 0x48
+# AF22 0x50
+# AF23 0x58
+#
+# CS5 CRITICAL 0xA0
+# EF 0xB8 IAX2, SIP Voice
+#
+# CS6 INTERNETWORKCNTRL 0xC0 BGP (by default)
+# CS7 NETWORKCONTROL 0xE0
+
+INTERACTIVE_FILTER_30="protocol ip prio 30 u32 match ip tos 0xb8 0xff"
+INTERACTIVE_FILTER_31="protocol ip prio 31 u32 match ip tos 0x10 0xff"
+INTERACTIVE_FILTER_32="protocol ip prio 32 u32 match ip tos 0x18 0xff"
+INTERACTIVE_FILTER_33="protocol ip prio 33 u32 match ip tos 0xa0 0xff"
+
+# UDP
+INTERACTIVE_FILTER_90="protocol ip prio 90 u32 match ip protocol 0x11 0xff"
+
+# ICMP
+INTERACTIVE_FILTER_91="protocol ip prio 91 u32 match ip protocol 0x1 0xff"
+
+##################################
+### PRIVILEGED FILTERING RULES ###
+##################################
+
+# SSH
+PRIVILEGED_FILTER_20="protocol ip prio 20 u32 match ip dport 22 0xffff"
+PRIVILEGED_FILTER_21="protocol ip prio 21 u32 match ip sport 22 0xffff"
+
+# Remote Desktop
+PRIVILEGED_FILTER_22="protocol ip prio 22 u32 match ip dport 3389 0xffff"
+PRIVILEGED_FILTER_23="protocol ip prio 23 u32 match ip sport 3389 0xffff"
+
+# ESP
+PRIVILEGED_FILTER_50="protocol ip prio 50 u32 match ip protocol 0x32 0xff"
+
+# AH
+PRIVILEGED_FILTER_51="protocol ip prio 51 u32 match ip protocol 0x33 0xff"
+
+# IPSEC-NAT
+PRIVILEGED_FILTER_52="protocol ip prio 52 u32 match ip protocol 0x11 0xff match ip dport 4500 0xffff"
+PRIVILEGED_FILTER_53="protocol ip prio 53 u32 match ip protocol 0x11 0xff match ip sport 4500 0xffff"
+
+# PHB TOS HEX NOTES
+# --------------------------------------
+# CS3 FLASH 0x60 SIP signaling
+# AF31 0x68
+# AF32 0x70
+# AF33 0x78
+#
+# CS4 FLASHOVERRIDE 0x80
+# AF41 0x88 SIP Video
+# AF42 0x90
+# AF43 0x98
+
+PRIVILEGED_FILTER_80="protocol ip prio 80 u32 match ip tos 0x60 0xff"
+PRIVILEGED_FILTER_81="protocol ip prio 81 u32 match ip tos 0x88 0xff"
+
+###################################
+### BEST-EFFORT FILTERING RULES ###
+###################################
+
+BESTEFFORT_FILTER_85="protocol ip prio 85 u32 match ip tos 0x4 0xff"
+BESTEFFORT_FILTER_86="protocol ip prio 86 u32 match ip tos 0x6 0xff"
+BESTEFFORT_FILTER_87="protocol ip prio 87 u32 match ip tos 0x90 0xff"
+BESTEFFORT_FILTER_88="protocol ip prio 88 u32 match ip tos 0x98 0xff"
+
+# Example: Any traffic from/to 192.168.1.0/24 network will be classified as best-effort
+#
+### BESTEFFORT_FILTER_5="protocol ip prio 10 u32 match ip src 192.168.1.0/24"
+### BESTEFFORT_FILTER_6="protocol ip prio 11 u32 match ip dst 192.168.1.0/24"
+
+###########################
+### LAN FILTERING RULES ###
+###########################
+
+# Example: Traffic Originated from router
+#
+###LAN_FILTER_10="protocol ip prio 10 u32 match ip src 192.168.1.10"
diff --git a/main/iproute2-qos/qos.ifb0.sample b/main/iproute2-qos/qos.ifb0.sample
new file mode 100644
index 0000000000..f1740f0970
--- /dev/null
+++ b/main/iproute2-qos/qos.ifb0.sample
@@ -0,0 +1,151 @@
+# Device being configured
+DEV=ifb0
+
+# IFB device is used to mirror ingress traffic from $DEV (see INGRESS_ALG)
+IFB_DEV= # Leave it blank if $DEV is ifbX
+
+# Internet EGRESS/INGRES rates in kbit or mbit. Measure this on a free line to gain precise value
+EGRESS_RATE=2048kbit # 256kbit, 512kbit, 1024kbit
+INGRESS_RATE=512kbit # 128kbit, 256kbit, 512kbit
+
+# In order to control a queue at the router/bridge side we will downgrade a real link speed on purpose
+RATE_SUB_PERCENT=5 # 20, 10
+
+# Device physical speed in kbit or mbit.
+DEV_RATE=50mbit
+
+# EGRESS root Classfull Disciplins
+#
+# htb: if link is not congested or you want to control busrts of traffic; recommended for downstream.
+# hfsc: if link is congested and you need to control guarantees of delay; recommended for upstream.
+# dmax = 50-100 [ms] = 50000-100000 [microsec]
+# umax = MIN (rate * (dmax / 1000), 1500) [b]
+# prio: if rate is variable and you want to be sure that interactive traffic has ultimate priority
+# none: if link is not congested
+#
+EGRESS_ALG=htb
+
+# EGRESS leaf Queuing Disciplines
+#
+# pfifo: real-time streams or IPSEC
+# sfq: TCP sessions or best-effort class traffic
+# red: hightly congested links or high-speed Internet [> 10Mbit/sec])
+#
+INTERACTIVE_LEAF_QDISC=pfifo
+PRIVILEGED_LEAF_QDISC=pfifo
+BESTEFFORT_LEAF_QDISC=red
+LAN_LEAF_QDISC=sfq
+
+# INGRESS treatment
+#
+# police: if link is constantly heavy congested set simple traffic policing
+# cpolice: if link is constantly heavy congested but you need certain dedicated rates then set classfull traffic policiing
+# ifb: shape INGRESS traffic as EGRESS of intermediate IFB device (aka imq)
+# none: if INGRESS traffic already is being shaped or if IFB device is being configured
+#
+INGRESS_ALG=none
+
+# Filter rules (see tc, tc-filters man pages).
+# You may have multiple <CLASS-NAME>_FILTER_<n> items.
+# Maximum 100 filter items are allowed for each class.
+# By default ALL unclassified traffic is being assined to Best-Effort class.
+
+###################################
+### INTERACTIVE FILTERING RULES ###
+###################################
+
+# ACK with payload < 64 bytes (32-bit version)
+INTERACTIVE_FILTER_10="protocol ip prio 10 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33"
+
+# ACK with payload < 64 bytes
+INTERACTIVE_FILTER_11="protocol ip prio 11 u32 match ip protocol 6 0xff match u8 0x10 0xff at nexthdr+13 match u16 0x0000 0xffc0 at 2"
+
+# PHB TOS HEX NOTES
+# ----------------------------------------------
+# 0x10 SSH, IAX2
+# 0x18
+# CS1 PRIORITY 0x20
+# AF11 0x28
+# AF12 0x30
+# AF13 0x38
+#
+# CS2 IMMEDIATE 0x40
+# AF21 0x48
+# AF22 0x50
+# AF23 0x58
+#
+# CS5 CRITICAL 0xA0
+# EF 0xB8 IAX2, SIP Voice
+#
+# CS6 INTERNETWORKCNTRL 0xC0 BGP (by default)
+# CS7 NETWORKCONTROL 0xE0
+
+INTERACTIVE_FILTER_30="protocol ip prio 30 u32 match ip tos 0xb8 0xff"
+INTERACTIVE_FILTER_31="protocol ip prio 31 u32 match ip tos 0x10 0xff"
+INTERACTIVE_FILTER_32="protocol ip prio 32 u32 match ip tos 0x18 0xff"
+INTERACTIVE_FILTER_33="protocol ip prio 33 u32 match ip tos 0xa0 0xff"
+
+# UDP
+INTERACTIVE_FILTER_90="protocol ip prio 90 u32 match ip protocol 0x11 0xff"
+
+# ICMP
+INTERACTIVE_FILTER_91="protocol ip prio 91 u32 match ip protocol 0x1 0xff"
+
+##################################
+### PRIVILEGED FILTERING RULES ###
+##################################
+
+# SSH
+PRIVILEGED_FILTER_20="protocol ip prio 20 u32 match ip dport 22 0xffff"
+PRIVILEGED_FILTER_21="protocol ip prio 21 u32 match ip sport 22 0xffff"
+
+# Remote Desktop
+PRIVILEGED_FILTER_22="protocol ip prio 22 u32 match ip dport 3389 0xffff"
+PRIVILEGED_FILTER_23="protocol ip prio 23 u32 match ip sport 3389 0xffff"
+
+# ESP
+PRIVILEGED_FILTER_50="protocol ip prio 50 u32 match ip protocol 0x32 0xff"
+
+# AH
+PRIVILEGED_FILTER_51="protocol ip prio 51 u32 match ip protocol 0x33 0xff"
+
+# IPSEC-NAT
+PRIVILEGED_FILTER_52="protocol ip prio 52 u32 match ip protocol 0x11 0xff match ip dport 4500 0xffff"
+PRIVILEGED_FILTER_53="protocol ip prio 53 u32 match ip protocol 0x11 0xff match ip sport 4500 0xffff"
+
+# PHB TOS HEX NOTES
+# --------------------------------------
+# CS3 FLASH 0x60 SIP signaling
+# AF31 0x68
+# AF32 0x70
+# AF33 0x78
+#
+# CS4 FLASHOVERRIDE 0x80
+# AF41 0x88 SIP Video
+# AF42 0x90
+# AF43 0x98
+
+PRIVILEGED_FILTER_80="protocol ip prio 80 u32 match ip tos 0x60 0xff"
+PRIVILEGED_FILTER_81="protocol ip prio 81 u32 match ip tos 0x88 0xff"
+
+###################################
+### BEST-EFFORT FILTERING RULES ###
+###################################
+
+BESTEFFORT_FILTER_85="protocol ip prio 85 u32 match ip tos 0x4 0xff"
+BESTEFFORT_FILTER_86="protocol ip prio 86 u32 match ip tos 0x6 0xff"
+BESTEFFORT_FILTER_87="protocol ip prio 87 u32 match ip tos 0x90 0xff"
+BESTEFFORT_FILTER_88="protocol ip prio 88 u32 match ip tos 0x98 0xff"
+
+# Example: Any traffic from/to 192.168.1.0/24 network will be classified as best-effort
+#
+### BESTEFFORT_FILTER_5="protocol ip prio 10 u32 match ip src 192.168.1.0/24"
+### BESTEFFORT_FILTER_6="protocol ip prio 11 u32 match ip dst 192.168.1.0/24"
+
+###########################
+### LAN FILTERING RULES ###
+###########################
+
+# Example: Traffic Originated from router
+#
+###LAN_FILTER_10="protocol ip prio 10 u32 match ip src 192.168.1.10"
diff --git a/main/iproute2-qos/qos.initd b/main/iproute2-qos/qos.initd
new file mode 100644
index 0000000000..09677353a9
--- /dev/null
+++ b/main/iproute2-qos/qos.initd
@@ -0,0 +1,463 @@
+#!/sbin/runscript
+#
+###########################################################################################################
+# Traffic Control startup script
+#
+# Copyright (c) 2009 iilluzion
+#
+# Distributed under GPL-2
+###########################################################################################################
+
+PROGRAM=$SVCNAME
+CONFIG=/etc/conf.d/$SVCNAME
+DEBUG=0 #1
+
+opts="describe compile"
+
+###########################################################################################################
+#
+#
+depend()
+{
+ need net
+ after firewall
+}
+
+###########################################################################################################
+#
+#
+checkconfig() {
+ if [ ! -e $CONFIG ] ; then
+ eerror "You need to create $CONFIG first."
+ return 1
+ fi
+}
+
+###########################################################################################################
+#
+#
+bits()
+{
+ RATE=0
+ R_RATE=$1
+
+ R_NUMBER=`echo "$R_RATE" | sed -e "s/[^0-9]//g"`
+ R_UNIT=`echo "$R_RATE" | sed -e "s/[0-9]//g"`
+
+ if [ "$R_UNIT" == "" ]; then
+ R_UNIT="kbit"
+ fi
+
+ if [ "$R_UNIT" == "kbps" ]; then R_RATE=$(($R_NUMBER * 1024 * 8))
+ elif [ "$R_UNIT" == "mbps" ]; then R_RATE=$(($R_NUMBER * 1024 * 1024 * 8))
+ elif [ "$R_UNIT" == "mbit" ]; then R_RATE=$(($R_NUMBER * 1024 * 1024))
+ elif [ "$R_UNIT" == "kbit" ]; then R_RATE=$(($R_NUMBER * 1024))
+ elif [ "$R_UNIT" == "bps" ]; then R_RATE=$(($R_NUMBER * 8))
+ else
+ echo "Unknown unit '$R_UNIT' (mbps, mbit, kbit, kbps, bps)"
+ fi
+
+ echo "$R_RATE"
+}
+
+###########################################################################################################
+#
+#
+expand_leaf_qdisc()
+{
+ case "$1" in
+ pfifo) echo "pfifo limit 5";;
+ sfq) echo "sfq perturb 10";;
+ red) echo "red min $RED_MIN max $RED_MAX burst $RED_BURST limit $RED_LIMIT probability $RED_PROB avpkt $RED_AVPKT";;
+ esac
+}
+
+###########################################################################################################
+#
+#
+configure()
+{
+ if [ ! -z $1 ]; then
+ eval WAN_RATE="\$$1"_RATE
+ WAN_RATE=`bits $WAN_RATE`
+
+ # Calculaton of WAN classes rates
+ WAN_SUB_RATE=$((WAN_RATE - (RATE_SUB_PERCENT * WAN_RATE / 100)))
+ INTERACTIVE_RATE=$((WAN_SUB_RATE / 5))
+ if [ $INTERACTIVE_RATE -lt 75000 ]; then
+ INTERACTIVE_RATE=75000
+ PRIVILEGED_RATE=$(((WAN_SUB_RATE - 75000) / 2))
+ BESTEFFORT_RATE=$(((WAN_SUB_RATE - 75000) / 2))
+ else
+ PRIVILEGED_RATE=$((WAN_SUB_RATE / 2))
+ BESTEFFORT_RATE=$((WAN_SUB_RATE / 3))
+ fi
+
+ DEV_RATE=${DEV_RATE:-$EGRESS_RATE}
+ DEV_RATE=`bits $DEV_RATE`
+ if [ $DEV_RATE -lt $WAN_RATE ]; then
+ DEV_RATE=$WAN_RATE
+ fi
+ OUT_OF_WAN_RATE=$((DEV_RATE - WAN_RATE))
+
+ # Calculation of Queuing Discipline parameters
+ INTERACTIVE_PRIO_LATENCY=50000
+ INTERACTIVE_PRIO_BURST=$((INTERACTIVE_RATE / 100 / 8))
+
+ INTERACTIVE_HFSC_DMAX=50000
+ INTERACTIVE_HFSC_UMAX=1500
+
+ PRIVILEGED_HFSC_DMAX=100000
+ PRIVILEGED_HFSC_UMAX=1500
+
+ # Random Early Detect (RED) parameters calculation:
+ # min = maximum delay * rate (dalay ~ 200ms = 0.2sec) [b]
+ # max = 3 * min [b]
+ # avpkt = 1000 (MTU 1500)
+ # limit = 8 * max [b]
+ # burst = (min + min + max)/(3 * avpkt) [b]
+ # probability = 0.02
+
+ RED_DELAY=200
+ RED_MIN=$((RED_DELAY * BESTEFFORT_RATE / 1000 / 8)) # devided on 8 since rate given in bit/s so we get bytes
+ RED_MAX=$((3 * RED_MIN))
+ RED_AVPKT=1000
+ RED_PROB=0.02
+ RED_BURST=$(((RED_MIN + RED_MIN + RED_MAX) / (3 * RED_AVPKT)))
+ RED_LIMIT=$((8 * RED_MAX))
+
+ # Setting leaf Queuing Disciplines parameters
+ INTERACTIVE_LEAF_QDISC=pfifo
+ INTERACTIVE_LEAF_QDISC=`expand_leaf_qdisc $INTERACTIVE_LEAF_QDISC`
+ PRIVILEGED_LEAF_QDISC=pfifo
+ PRIVILEGED_LEAF_QDISC=`expand_leaf_qdisc $PRIVILEGED_LEAF_QDISC`
+
+ # Force using SFQ in case rate is less than 2mbit
+ if [ $BESTEFFORT_RATE -lt 2097152 ]; then
+ BESTEFFORT_LEAF_QDISC=sfq
+ fi
+ BESTEFFORT_LEAF_QDISC=`expand_leaf_qdisc $BESTEFFORT_LEAF_QDISC`
+
+ LAN_LEAF_QDISC=sfq
+ LAN_LEAF_QDISC=`expand_leaf_qdisc $LAN_LEAF_QDISC`
+ fi
+}
+
+###########################################################################################################
+#
+#
+reset()
+{
+ # Supported Queuing Disciplines
+ QDISCS="prio|tbf|htb|hfsc|sfq|red|pfifo"
+
+ tc qdisc show dev $DEV | grep -v "pfifo_fast" | egrep -q "$QDISCS" && $ECHO tc qdisc del dev $DEV root
+ tc qdisc show dev $DEV | grep -v "pfifo_fast" | grep -q ingress && $ECHO tc qdisc del dev $DEV ingress
+
+ if [ "$INGRESS_ALG" = "ifb" ] && [ ! -z $IFB_DEV ]; then
+ $ECHO ip link set dev $IFB_DEV down
+ fi
+}
+
+###########################################################################################################
+#
+#
+set_leaf_qdisc()
+{
+ PARENT_CLASSID=$1
+ PARENT_CLASSID=${PARENT_CLASSID:-1}
+
+ if [ ! "$QDISC_CMD" = "prio" ]; then
+ $ECHO tc qdisc add dev $DEV parent $PARENT_CLASSID:40 handle 40 $INTERACTIVE_LEAF_QDISC
+ fi
+
+ $ECHO tc qdisc add dev $DEV parent $PARENT_CLASSID:50 handle 50 $PRIVILEGED_LEAF_QDISC
+ $ECHO tc qdisc add dev $DEV parent $PARENT_CLASSID:60 handle 60 $BESTEFFORT_LEAF_QDISC
+
+ if [ $OUT_OF_WAN_RATE -gt 0 ]; then
+ $ECHO tc qdisc add dev $DEV parent $PARENT_CLASSID:70 handle 70 $LAN_LEAF_QDISC
+ fi
+
+ $ECHO
+}
+
+###########################################################################################################
+#
+#
+set_filters()
+{
+ CLASS_TYPES="INTERACTIVE PRIVILEGED BESTEFFORT"
+ if [ $OUT_OF_WAN_RATE -gt 0 ]; then
+ CLASS_TYPES=$CLASS_TYPES" LAN"
+ fi
+
+ PRIVILEGED_FILTER_FLOWID=50
+ BESTEFFORT_FILTER_FLOWID=60
+ LAN_FILTER_FLOWID=70
+
+ {
+ for CLASS_TYPE in $CLASS_TYPES; do
+ if [ "$QDISC_CMD" = "prio" -a "$CLASS_TYPE" = "INTERACTIVE" ]; then
+ PARENT_CLASSID=1
+ INTERACTIVE_FILTER_FLOWID=1
+ else
+ PARENT_CLASSID=$1
+ PARENT_CLASSID=${PARENT_CLASSID:-1}
+ INTERACTIVE_FILTER_FLOWID=40
+ fi
+
+ for FILTER_NUM in `seq 1 100`; do
+ eval FILTER="\$$CLASS_TYPE"_FILTER_$FILTER_NUM
+ if [ ! -z "$FILTER" ]; then
+ eval FILTER_FLOWID="\$$CLASS_TYPE"_FILTER_FLOWID
+ $ECHO tc filter add dev $DEV parent $PARENT_CLASSID:0 $FILTER flowid $PARENT_CLASSID:$FILTER_FLOWID
+ fi
+ done
+ done
+ } | sort -g
+
+ $ECHO
+}
+
+###########################################################################################################
+#
+#
+set_htb()
+{
+ $ECHO tc qdisc add dev $DEV root handle 1 htb default 60
+ $ECHO tc class add dev $DEV parent 1: classid 1:2 htb rate $DEV_RATE burst $(($DEV_RATE*5/4))
+ $ECHO tc class add dev $DEV parent 1:2 classid 1:30 htb rate $WAN_SUB_RATE burst $(($WAN_SUB_RATE*5/4))
+ $ECHO tc class add dev $DEV parent 1:30 classid 1:40 htb rate $INTERACTIVE_RATE ceil $WAN_SUB_RATE prio 1
+ $ECHO tc class add dev $DEV parent 1:30 classid 1:50 htb rate $PRIVILEGED_RATE ceil $WAN_SUB_RATE prio 3 burst $(($WAN_SUB_RATE*5/4))
+ $ECHO tc class add dev $DEV parent 1:30 classid 1:60 htb rate $BESTEFFORT_RATE ceil $WAN_SUB_RATE prio 6 burst $(($WAN_SUB_RATE*5/4))
+
+ if [ $OUT_OF_WAN_RATE -gt 0 ]; then
+ $ECHO tc class add dev $DEV parent 1:2 classid 1:70 htb rate $OUT_OF_WAN_RATE prio 7
+ fi
+
+ set_leaf_qdisc
+
+ $ECHO
+
+ set_filters
+}
+
+###########################################################################################################
+#
+#
+set_hfsc()
+{
+ $ECHO tc qdisc add dev $DEV root handle 1 hfsc default 60
+ $ECHO tc class add dev $DEV parent 1: classid 1:2 hfsc sc rate $DEV_RATE ul rate $DEV_RATE
+ $ECHO tc class add dev $DEV parent 1:2 classid 1:30 hfsc sc rate $WAN_SUB_RATE ul rate $WAN_SUB_RATE
+ $ECHO tc class add dev $DEV parent 1:30 classid 1:40 hfsc sc umax $INTERACTIVE_HFSC_UMAX dmax $INTERACTIVE_HFSC_DMAX rate $INTERACTIVE_RATE ul rate $WAN_SUB_RATE
+ $ECHO tc class add dev $DEV parent 1:30 classid 1:50 hfsc sc umax $PRIVILEGED_HFSC_UMAX dmax $PRIVILEGED_HFSC_DMAX rate $PRIVILEGED_RATE ul rate $WAN_SUB_RATE
+ $ECHO tc class add dev $DEV parent 1:30 classid 1:60 hfsc sc rate $BESTEFFORT_RATE ul rate $WAN_SUB_RATE
+
+ if [ $OUT_OF_WAN_RATE -gt 0 ]; then
+ $ECHO tc class add dev $DEV parent 1:2 classid 1:70 hfsc sc rate $OUT_OF_WAN_RATE ul rate $OUT_OF_WAN_RATE
+ fi
+
+ set_leaf_qdisc
+
+ $ECHO
+
+ set_filters
+}
+
+###########################################################################################################
+#
+#
+set_prio()
+{
+ PARENT_CLASSID=10
+ $ECHO tc qdisc add dev $DEV root handle 1 prio bands 2 priomap 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 # by default unclassified traffic goes to flowid 1:2
+ $ECHO tc qdisc add dev $DEV parent 1:1 handle 40: tbf rate $INTERACTIVE_RATE burst $WAN_SUB_RATE latency $INTERACTIVE_PRIO_LATENCY
+ $ECHO tc qdisc add dev $DEV parent 1:2 handle $PARENT_CLASSID: htb default 60
+ $ECHO tc class add dev $DEV parent $PARENT_CLASSID: classid $PARENT_CLASSID:30 htb rate $WAN_SUB_RATE
+ $ECHO tc class add dev $DEV parent $PARENT_CLASSID:30 classid $PARENT_CLASSID:50 htb rate $PRIVILEGED_RATE ceil $WAN_SUB_RATE prio 3
+ $ECHO tc class add dev $DEV parent $PARENT_CLASSID:30 classid $PARENT_CLASSID:60 htb rate $BESTEFFORT_RATE ceil $WAN_SUB_RATE prio 6
+
+ if [ $OUT_OF_WAN_RATE -gt 0 ]; then
+ $ECHO tc class add dev $DEV parent 10:1 classid $PARENT_CLASSID:70 htb rate $OUT_OF_WAN_RATE prio 7
+ fi
+
+ set_leaf_qdisc $PARENT_CLASSID
+
+ $ECHO
+
+ set_filters $PARENT_CLASSID
+}
+
+###########################################################################################################
+#
+#
+set_ifb()
+{
+ $ECHO ip link set dev $IFB_DEV up
+ $ECHO tc qdisc add dev $DEV ingress handle ffff:
+ $ECHO tc filter add dev $DEV parent ffff: protocol ip prio 10 u32 match u32 0 0 action mirred egress redirect dev $IFB_DEV > /dev/null 2>&1
+}
+
+###########################################################################################################
+#
+#
+set_police()
+{
+
+# Calculation of policing bursts
+# burst = rate / 17 (taken basing on experemental results)
+
+ POLICE_BURST_SCALE=17
+ WAN_POLICE_BURST=$((WAN_RATE / POLICE_BURST_SCALE))
+
+ WAN_POLICE_FLOWID=1
+
+ $ECHO tc qdisc add dev $DEV handle ffff: ingress
+ $ECHO tc filter add dev $DEV parent ffff: protocol ip prio 999 u32 match ip src 0.0.0.0/0 police rate $WAN_RATE burst $WAN_POLICE_BURST drop flowid :$WAN_POLICE_FLOWID
+
+ $ECHO
+}
+
+###########################################################################################################
+#
+#
+set_cpolice()
+{
+
+ # Calculation of policing bursts
+ # burst = rate / 17 (taken basing on experemental results)
+
+ POLICE_BURST_SCALE=17
+ INTERACTIVE_POLICE_BURST=$((INTERACTIVE_RATE / POLICE_BURST_SCALE))
+ PRIVILEGED_POLICE_BURST=$((PRIVILEGED_RATE / POLICE_BURST_SCALE))
+ BESTEFFORT_POLICE_BURST=$((BESTEFFORT_RATE / POLICE_BURST_SCALE))
+
+ CLASS_TYPES="INTERACTIVE PRIVILEGED"
+ INTERACTIVE_POLICE_FLOWID=1
+ PRIVILEGED_POLICE_FLOWID=2
+
+ $ECHO tc qdisc add dev $DEV handle ffff: ingress
+
+ for CLASS_TYPE in $CLASS_TYPES; do
+ for FILTER_NUM in `seq 1 100`; do
+ eval FILTER="\$$CLASS_TYPE"_FILTER_$FILTER_NUM
+ [ -z "$FILTER" ] && break
+ eval FILTER_FLOWID="\$$CLASS_TYPE"_POLICE_FLOWID
+ eval FILTER_RATE="\$$CLASS_TYPE"_RATE
+ eval FILTER_BURST="\$$CLASS_TYPE"_POLICE_BURST
+ $ECHO tc filter add dev $DEV parent ffff: $FILTER police rate $FILTER_RATE burst $FILTER_BURST continue flowid :$FILTER_FLOWID
+ done
+ done
+
+ $ECHO tc filter add dev $DEV parent ffff: protocol ip prio 999 u32 match ip src 0.0.0.0/0 police rate $BESTEFFORT_RATE burst $BESTEFFORT_POLICE_BURST drop flowid :3
+
+ $ECHO
+}
+
+###########################################################################################################
+#
+#
+get_stats()
+{
+ echo $DEV Statistics
+ echo
+ echo " Classes:"
+ echo "--------------------------"
+ $ECHO tc -s class show dev $DEV
+
+ echo
+ echo " Leaf Queuing Disciplines:"
+ echo "--------------------------"
+ $ECHO tc -s qdisc show dev $DEV
+
+ echo
+ echo " EGRESS Filters:"
+ echo "--------------------------"
+ $ECHO tc -s filter show dev $DEV
+ $ECHO tc -s filter show dev $DEV parent 10: # if PRIO qdisc is applied
+
+ echo
+ echo " INGRESS Policing Filters:"
+ echo "--------------------------"
+ $ECHO tc -s filter show dev $DEV parent ffff:
+
+ echo
+}
+
+###########################################################################################################
+#
+#
+compile()
+{
+ DEBUG=1
+
+ start
+}
+
+###########################################################################################################
+#
+#
+start()
+{
+ checkconfig || return 1
+
+ if [ $DEBUG -gt 0 ]; then
+ ECHO="echo"
+ else
+ ebegin "Starting QoS at $DEV"
+ fi
+
+ reset
+
+ for LINK_DIRECTION in EGRESS INGRESS; do
+ configure $LINK_DIRECTION
+ eval ALG_CMD="\$$LINK_DIRECTION"_ALG
+ if [ ! "$ALG_CMD" = "none" ]; then
+ set_$ALG_CMD
+ fi
+ done
+
+ if [ $DEBUG -eq 0 ]; then
+ eend $?
+ fi
+}
+
+###########################################################################################################
+#
+#
+stop()
+{
+ checkconfig || return 1
+
+ if [ $DEBUG -gt 0 ]; then
+ ECHO="echo"
+ else
+ ebegin "Stopping QoS at $DEV"
+ fi
+
+ reset
+
+ if [ $DEBUG -eq 0 ]; then
+ eend $?
+ fi
+}
+
+###########################################################################################################
+#
+#
+restart()
+{
+ stop
+ start
+}
+
+###########################################################################################################
+#
+#
+describe()
+{
+ checkconfig || return 1
+
+ get_stats
+}
diff --git a/main/iproute2-qos/setup-qos b/main/iproute2-qos/setup-qos
new file mode 100644
index 0000000000..5d5c601268
--- /dev/null
+++ b/main/iproute2-qos/setup-qos
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+PREFIX=
+. "$PREFIX/lib/libalpine.sh"
+
+conf="$ROOT/etc/conf.d/qos"
+
+cfgval() {
+ awk -F= "/^$1/ {print \$2}" $conf 2>/dev/null
+}
+
+setcfg() {
+ local key=$1
+ local value=$2
+ sed -i "s/^\\(\\#\\)*$key=.*/$key=$value/" "$conf"
+ if ! grep "^$key=" "$conf" >/dev/null ; then
+ echo "$key=$value" >> "$conf"
+ fi
+}
+
+apk_add iproute2
+
+if [ -f "$conf" ] ; then
+ _UPLINK_RATE=$(cfgval UPLINK_RATE)
+ _DOWNLINK_RATE=$(cfgval DOWNLINK_RATE)
+ _RATE_SUB_PERCENT=$(cfgval RATE_SUB_PERCENT)
+else
+ echo "Configuration file '$conf' not found"
+ exit 1
+fi
+
+echo "**********************************************************************"
+echo "Since ISPs tend to overestimate the speeds they offer, it would probably be best"
+echo " if you measure this on a free line to set values very precisely."
+echo "**********************************************************************"
+echo
+echon "Specify the upload speed of your internet connection (mbps, mbit, kbit, kbps, bps): [$_UPLINK_RATE] "
+ default_read _UPLINK_RATE $_UPLINK_RATE
+echo
+echon "Specify the download speed of your internet connection (mbps, mbit, kbit, kbps, bps): [$_DOWNLINK_RATE] "
+ default_read _DOWNLINK_RATE $_DOWNLINK_RATE
+echo
+echo "**********************************************************************"
+echo "In order to prevent traffic queuing at the ISP side or in your modem,"
+echo " you should set a slightly lower rate than real one."
+echo "This way the bottleneck is the router,"
+echo " not the ISP or modem, which allows to control the queue."
+echo "**********************************************************************"
+echo
+echon "Specify amount of percents: [$_RATE_SUB_PERCENT] "
+ default_read _RATE_SUB_PERCENT $_RATE_SUB_PERCENT
+
+echon "Start QoS? (y/n) [y] "
+ default_read startqos "y"
+ case "$startqos" in
+ [Yy]*) /etc/init.d/qos start;;
+ esac
+
+echon "Make QoS to be started on boot? (y/n) [y] "
+ default_read bootstartqos "y"
+ case "$bootstartqos" in
+ [Yy]*) rc_add qos;;
+ esac
+
+setcfg UPLINK_RATE $_UPLINK_RATE
+setcfg DOWNLINK_RATE $_DOWNLINK_RATE
+setcfg RATE_SUB_PERCENT $_RATE_SUB_PERCENT
diff --git a/main/iproute2/APKBUILD b/main/iproute2/APKBUILD
new file mode 100644
index 0000000000..6a5d2f9805
--- /dev/null
+++ b/main/iproute2/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iproute2
+pkgver=2.6.38
+_realver=$pkgver
+pkgrel=0
+pkgdesc="IP Routing Utilities"
+url="http://www.linux-foundation.org/en/Net:Iproute2"
+arch="all"
+license="GPL2"
+depends=
+install="$pkgname.post-install $pkgname.post-deinstall"
+makedepends="bison flex bash"
+subpackages="$pkgname-doc"
+source="http://devresources.linux-foundation.org/dev/iproute2/download/$pkgname-$_realver.tar.bz2
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$_realver
+
+ for i in $source; do
+ case $i in
+ *.patch) msg "$i"; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ sed -i '/^TARGETS=/s: arpd : :' misc/Makefile
+ sed -i 's:/usr/local:/usr:' tc/m_ipt.c include/iptables.h || return 1
+ sed -i 's:=/share:=/usr/share:' Makefile || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$_realver
+ ./configure || return 1
+ make CCOPTS="-D_GNU_SOURCE $CFLAGS" LIBDIR=/lib || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$_realver
+ make -j1 DESTDIR="$pkgdir" install
+}
+
+md5sums="a243bfea837e71824b7ca26c3bb45fa8 iproute2-2.6.38.tar.bz2"
diff --git a/main/iproute2/iproute2.post-deinstall b/main/iproute2/iproute2.post-deinstall
new file mode 100644
index 0000000000..dd117e5d80
--- /dev/null
+++ b/main/iproute2/iproute2.post-deinstall
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+busybox --install -s
+
diff --git a/main/iproute2/iproute2.post-install b/main/iproute2/iproute2.post-install
new file mode 100644
index 0000000000..36d567ea21
--- /dev/null
+++ b/main/iproute2/iproute2.post-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if [ "$(readlink /bin/ip)" = "/bin/busybox" ]; then
+ rm -f /bin/ip
+fi
+exit 0
diff --git a/main/ipsec-tools/20-grekey-support.patch b/main/ipsec-tools/20-grekey-support.patch
new file mode 100644
index 0000000000..17fea3e991
--- /dev/null
+++ b/main/ipsec-tools/20-grekey-support.patch
@@ -0,0 +1,786 @@
+Index: ipsec-tools-cvs-HEAD/src/racoon/racoonctl.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/racoonctl.c 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/racoonctl.c 2011-03-29 22:08:43.000000000 +0300
+@@ -232,7 +232,7 @@
+ "\n"
+ " <saopts>: \"isakmp\" <family> <src> <dst>\n"
+ " : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n"
+-" <ul_proto>\n"
++" <ul_proto> [grekey <grekey>]\n"
+ " <family>: \"inet\" or \"inet6\"\n"
+ " <ul_proto>: \"icmp\", \"tcp\", \"udp\", \"gre\" or \"any\"\n"
+ "\n",
+@@ -819,7 +819,7 @@
+ {
+ int family;
+
+- if (ac != 3 && ac != 4) {
++ if (ac < 3) {
+ errno = EINVAL;
+ return NULL;
+ }
+@@ -861,10 +861,8 @@
+ struct sockaddr *src = NULL, *dst = NULL;
+ int ulproto;
+
+- if (ac != 2 && ac != 3) {
+- errno = EINVAL;
+- return NULL;
+- }
++ if (ac < 2)
++ goto bad_args;
+
+ if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1)
+ goto bad;
+@@ -901,13 +899,34 @@
+
+ av++;
+ ac--;
+- if(ac){
++ if (ac) {
+ ulproto = get_ulproto(*av);
+ if (ulproto == -1)
+ goto bad;
+- }else
++ av++;
++ ac--;
++ } else
+ ulproto=0;
+
++ if (ac == 2 && strcmp(av[0], "grekey") == 0) {
++ int a, b, c, d;
++ unsigned long u;
++
++ if (sscanf(av[1], "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
++ set_port(src, (a << 8) + b);
++ set_port(dst, (c << 8) + d);
++ } else if (sscanf(av[1], "%lu", &u) == 1) {
++ set_port(src, u >> 16);
++ set_port(dst, u & 0xffff);
++ } else
++ goto bad_args;
++ av += 2;
++ ac -= 2;
++ }
++
++ if (ac != 0)
++ goto bad_args;
++
+ ci = (struct admin_com_indexes *)buf->v;
+ if(p_prefs)
+ ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */
+@@ -926,7 +945,9 @@
+
+ return buf;
+
+- bad:
++bad_args:
++ errno = EINVAL;
++bad:
+ if (p_name)
+ racoon_free(p_name);
+ if (p_port)
+Index: ipsec-tools-cvs-HEAD/src/racoon/admin.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/admin.c 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/admin.c 2011-03-30 09:41:46.000000000 +0300
+@@ -444,7 +444,7 @@
+
+ /* search appropreate configuration */
+ if (name == NULL)
+- rmconf = getrmconf(dst, 0);
++ rmconf = getrmconf(dst, 0, 0);
+ else
+ rmconf = getrmconf_by_name(name);
+ if (rmconf == NULL) {
+@@ -536,6 +536,7 @@
+ spidx.prefs = ndx->prefd;
+ spidx.prefd = ndx->prefs;
+ spidx.ul_proto = ndx->ul_proto;
++ spidx_normalize_ulports(&spidx);
+
+ sp_in = getsp_r(&spidx);
+ if (sp_in) {
+Index: ipsec-tools-cvs-HEAD/src/racoon/cftoken.l
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/cftoken.l 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/cftoken.l 2011-03-29 22:08:43.000000000 +0300
+@@ -288,6 +288,7 @@
+ <S_SAINF>any { YYD; return(ANY); }
+ <S_SAINF>from { YYD; return(FROM); }
+ <S_SAINF>group { YYD; return(GROUP); }
++<S_SAINF>grekey { YYD; return(GREKEY); }
+ /* sainfo spec */
+ <S_SAINF>{bcl} { BEGIN S_SAINFS; return(BOC); }
+ <S_SAINF>{semi} { BEGIN S_INI; return(EOS); }
+Index: ipsec-tools-cvs-HEAD/src/racoon/cfparse.y
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/cfparse.y 2011-03-14 19:12:41.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/cfparse.y 2011-03-29 22:08:43.000000000 +0300
+@@ -214,7 +214,7 @@
+ /* algorithm */
+ %token ALGORITHM_CLASS ALGORITHMTYPE STRENGTHTYPE
+ /* sainfo */
+-%token SAINFO FROM
++%token SAINFO FROM GREKEY
+ /* remote */
+ %token REMOTE ANONYMOUS CLIENTADDR INHERIT REMOTE_ADDRESS
+ %token EXCHANGE_MODE EXCHANGETYPE DOI DOITYPE SITUATION SITUATIONTYPE
+@@ -1302,6 +1302,35 @@
+ cur_sainfo->idsrc = $1;
+ cur_sainfo->iddst = $2;
+ }
++ | sainfo_id sainfo_id GREKEY ADDRSTRING
++ {
++ int a, b, c, d;
++
++ if (sscanf($4->v, "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
++ a = ipsecdoi_fixup_id_uldata(
++ $1, $2, IPPROTO_GRE,
++ (a << 8) + b, (c << 8) + d);
++ } else {
++ yyerror("grekey format unrecognized.");
++ return -1;
++ }
++ if (a != 0) {
++ yyerror("ul_proto needs to be 'gre' to use grekey.");
++ return -1;
++ }
++ cur_sainfo->idsrc = $1;
++ cur_sainfo->iddst = $2;
++ }
++ | sainfo_id sainfo_id GREKEY NUMBER
++ {
++ if (ipsecdoi_fixup_id_uldata($1, $2, IPPROTO_GRE,
++ ($4) >> 16, ($4) & 0xffff) != 0) {
++ yyerror("ul_proto needs to be 'gre' to use grekey.");
++ return -1;
++ }
++ cur_sainfo->idsrc = $1;
++ cur_sainfo->iddst = $2;
++ }
+ ;
+ sainfo_id
+ : IDENTIFIERTYPE ADDRSTRING prefix port ul_proto
+@@ -1668,7 +1697,7 @@
+ {
+ struct remoteconf *from, *new;
+
+- from = getrmconf($4, GETRMCONF_F_NO_ANONYMOUS);
++ from = getrmconf($4, GETRMCONF_F_NO_ANONYMOUS, 0);
+ if (from == NULL) {
+ yyerror("failed to get remoteconf for %s.",
+ saddr2str($4));
+Index: ipsec-tools-cvs-HEAD/src/racoon/ipsec_doi.h
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/ipsec_doi.h 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/ipsec_doi.h 2011-03-30 09:22:13.000000000 +0300
+@@ -227,6 +227,10 @@
+ extern int set_identifier_qual __P((vchar_t **, int, vchar_t *, int));
+ extern int ipsecdoi_setid2 __P((struct ph2handle *));
+ extern vchar_t *ipsecdoi_sockaddr2id __P((struct sockaddr *, u_int, u_int));
++extern int ipsecdoi_fixup_id_uldata __P((vchar_t *, vchar_t *, u_int16_t, u_int16_t, u_int16_t));
++extern int ipsecdoi_normalize_id_uldata __P((vchar_t *, vchar_t *));
++extern int ipsecdoi_id_has_port __P((vchar_t *));
++
+ extern int ipsecdoi_id2sockaddr __P((vchar_t *, struct sockaddr *,
+ u_int8_t *, u_int16_t *));
+ extern char *ipsecdoi_id2str __P((const vchar_t *));
+Index: ipsec-tools-cvs-HEAD/src/racoon/ipsec_doi.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/ipsec_doi.c 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/ipsec_doi.c 2011-03-30 16:59:49.000000000 +0300
+@@ -3308,6 +3308,7 @@
+ const vchar_t *subnet;
+ const vchar_t *address;
+ {
++ struct in_addr *a, *b;
+ struct in_addr *mask;
+
+ if (address->l != sizeof(struct in_addr))
+@@ -3316,12 +3317,15 @@
+ if (subnet->l != (sizeof(struct in_addr)*2))
+ return 1;
+
++ a = (struct in_addr*)(subnet->v);
++ b = (struct in_addr*)(address->v);
+ mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
+
+- if (mask->s_addr!=0xffffffff)
+- return 1;
++ //if (mask->s_addr!=0xffffffff)
++ // return 1;
++ //return memcmp(subnet->v,address->v,address->l);
+
+- return memcmp(subnet->v,address->v,address->l);
++ return (a->s_addr & mask->s_addr) != (b->s_addr & mask->s_addr);
+ }
+
+ #ifdef INET6
+@@ -3371,6 +3375,7 @@
+ vchar_t ident_t;
+ vchar_t ident_s;
+ int result;
++ int check_ports = 0;
+
+ /* handle wildcard IDs */
+
+@@ -3410,12 +3415,14 @@
+
+ if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
+ (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
++ check_ports = 1;
+ result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
+ goto cmpid_result;
+ }
+
+ if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
+ (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
++ check_ports = 1;
+ result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
+ goto cmpid_result;
+ }
+@@ -3423,12 +3430,14 @@
+ #ifdef INET6
+ if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
+ (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
++ check_ports = 1;
+ result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
+ goto cmpid_result;
+ }
+
+ if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
+ (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
++ check_ports = 1;
+ result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
+ goto cmpid_result;
+ }
+@@ -3460,6 +3469,7 @@
+
+ case IPSECDOI_ID_IPV4_ADDR:
+ /* validate lengths */
++ check_ports = 1;
+ if ((ident_t.l != sizeof(struct in_addr))||
+ (ident_s.l != sizeof(struct in_addr)))
+ goto cmpid_invalid;
+@@ -3468,6 +3478,7 @@
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+ /* validate lengths */
++ check_ports = 1;
+ if ((ident_t.l != (sizeof(struct in_addr)*2))||
+ (ident_s.l != (sizeof(struct in_addr)*2)))
+ goto cmpid_invalid;
+@@ -3476,6 +3487,7 @@
+ #ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ /* validate lengths */
++ check_ports = 1;
+ if ((ident_t.l != sizeof(struct in6_addr))||
+ (ident_s.l != sizeof(struct in6_addr)))
+ goto cmpid_invalid;
+@@ -3484,6 +3496,7 @@
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+ /* validate lengths */
++ check_ports = 1;
+ if ((ident_t.l != (sizeof(struct in6_addr)*2))||
+ (ident_s.l != (sizeof(struct in6_addr)*2)))
+ goto cmpid_invalid;
+@@ -3502,12 +3515,18 @@
+ }
+
+ /* validate matching data and length */
+- if (ident_t.l == ident_s.l)
+- result = memcmp(ident_t.v,ident_s.v,ident_t.l);
+- else
++ if (ident_t.l != ident_s.l)
+ result = 1;
++ else
++ result = memcmp(ident_t.v,ident_s.v,ident_t.l);
+
+ cmpid_result:
++ if (check_ports &&
++ (id_bt->port != id_bs->port && id_bs->port != 0)) {
++ /* if target is wildcard, source should be too, otherwise
++ * specific rule matches wildcard request */
++ result = 1;
++ }
+
+ /* debug level output */
+ if(loglevel >= LLV_DEBUG) {
+@@ -4089,6 +4108,67 @@
+ return new;
+ }
+
++int ipsecdoi_fixup_id_uldata(srcid, dstid, ul_proto, ul_data1, ul_data2)
++ vchar_t *srcid, *dstid;
++ u_int16_t ul_proto;
++ u_int16_t ul_data1, ul_data2;
++{
++ struct ipsecdoi_id_b *src = (struct ipsecdoi_id_b *) srcid->v;
++ struct ipsecdoi_id_b *dst = (struct ipsecdoi_id_b *) dstid->v;
++
++ if (src->proto_id != ul_proto ||
++ dst->proto_id != ul_proto)
++ return -1;
++
++ src->port = htons(ul_data1);
++ dst->port = htons(ul_data2);
++
++ return 0;
++}
++
++int ipsecdoi_normalize_id_uldata(srcid, dstid)
++ vchar_t *srcid, *dstid;
++{
++ struct ipsecdoi_id_b *src = (struct ipsecdoi_id_b *) srcid->v;
++ struct ipsecdoi_id_b *dst = (struct ipsecdoi_id_b *) dstid->v;
++ u_int16_t tmp;
++
++ if (src->proto_id != dst->proto_id)
++ return -1;
++
++ switch (src->proto_id) {
++ case IPPROTO_ICMP:
++ case IPPROTO_ICMPV6:
++ case IPPROTO_GRE:
++ tmp = src->port;
++ src->port = dst->port;
++ dst->port = tmp;
++ break;
++ }
++
++ return 0;
++}
++
++int ipsecdoi_id_has_port(id)
++ vchar_t *id;
++{
++ struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *) id->v;
++
++ switch (id_b->type) {
++ case IPSECDOI_ID_IPV4_ADDR:
++ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
++ case IPSECDOI_ID_IPV4_ADDR_RANGE:
++ case IPSECDOI_ID_IPV6_ADDR:
++ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
++ case IPSECDOI_ID_IPV6_ADDR_RANGE:
++ if (ntohs(id_b->port) != 0)
++ return 1;
++ break;
++ }
++ return 0;
++}
++
++
+ vchar_t *
+ ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
+ struct sockaddr *laddr, *haddr;
+@@ -4318,7 +4398,7 @@
+ saddr.sa.sa_len = sizeof(struct sockaddr_in);
+ #endif
+ saddr.sa.sa_family = AF_INET;
+- saddr.sin.sin_port = IPSEC_PORT_ANY;
++ saddr.sin.sin_port = id_b->port;
+ memcpy(&saddr.sin.sin_addr,
+ id->v + sizeof(*id_b), sizeof(struct in_addr));
+ break;
+@@ -4331,7 +4411,7 @@
+ saddr.sa.sa_len = sizeof(struct sockaddr_in6);
+ #endif
+ saddr.sa.sa_family = AF_INET6;
+- saddr.sin6.sin6_port = IPSEC_PORT_ANY;
++ saddr.sin6.sin6_port = id_b->port;
+ memcpy(&saddr.sin6.sin6_addr,
+ id->v + sizeof(*id_b), sizeof(struct in6_addr));
+ saddr.sin6.sin6_scope_id =
+@@ -4347,7 +4427,7 @@
+ #ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ #endif
+- len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr.sa));
++ len = snprintf( buf, BUFLEN, "%s", saddr2str(&saddr.sa));
+ break;
+
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+@@ -4403,7 +4483,9 @@
+ plen += l;
+ }
+
+- len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr.sa), plen);
++ len = snprintf(buf, BUFLEN, "%s/%i[%d]",
++ saddrwop2str(&saddr.sa), plen,
++ ntohs(id_b->port));
+ }
+ break;
+
+@@ -4415,12 +4497,12 @@
+ saddr.sa.sa_len = sizeof(struct sockaddr_in);
+ #endif
+ saddr.sa.sa_family = AF_INET;
+- saddr.sin.sin_port = IPSEC_PORT_ANY;
++ saddr.sin.sin_port = id_b->port;
+ memcpy(&saddr.sin.sin_addr,
+ id->v + sizeof(*id_b) + sizeof(struct in_addr),
+ sizeof(struct in_addr));
+
+- len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
++ len += snprintf(buf + len, BUFLEN - len, "%s", saddr2str(&saddr.sa));
+ break;
+
+ #ifdef INET6
+@@ -4431,7 +4513,7 @@
+ saddr.sa.sa_len = sizeof(struct sockaddr_in6);
+ #endif
+ saddr.sa.sa_family = AF_INET6;
+- saddr.sin6.sin6_port = IPSEC_PORT_ANY;
++ saddr.sin6.sin6_port = id_b->port;
+ memcpy(&saddr.sin6.sin6_addr,
+ id->v + sizeof(*id_b) + sizeof(struct in6_addr),
+ sizeof(struct in6_addr));
+@@ -4440,7 +4522,7 @@
+ ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
+ : 0);
+
+- len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
++ len += snprintf(buf + len, BUFLEN - len, "%s", saddr2str(&saddr.sa));
+ break;
+ #endif
+
+Index: ipsec-tools-cvs-HEAD/src/racoon/sainfo.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/sainfo.c 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/sainfo.c 2011-03-29 22:08:44.000000000 +0300
+@@ -124,7 +124,7 @@
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "evaluating sainfo: %s\n", sainfostr);
+
+- if(s->remoteid != remoteid) {
++ if (remoteid != -1 && s->remoteid != remoteid) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "remoteid mismatch: %u != %u\n",
+ s->remoteid, remoteid);
+@@ -234,16 +234,22 @@
+ int pri = 0;
+
+ if(s->remoteid)
+- pri += 3;
++ pri += 7;
+
+ if(s->id_i)
+- pri += 3;
++ pri += 7;
+
+- if(s->idsrc)
++ if(s->idsrc) {
+ pri++;
++ if (ipsecdoi_id_has_port(s->idsrc))
++ pri += 2;
++ }
+
+- if(s->iddst)
++ if(s->iddst) {
+ pri++;
++ if (ipsecdoi_id_has_port(s->iddst))
++ pri += 2;
++ }
+
+ return pri;
+ }
+Index: ipsec-tools-cvs-HEAD/src/racoon/isakmp.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/isakmp.c 2011-03-14 19:18:12.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/isakmp.c 2011-03-30 09:41:46.000000000 +0300
+@@ -2173,7 +2173,15 @@
+ * so no need to bother yet. --arno */
+
+ if (iph1hint == NULL || iph1hint->rmconf == NULL) {
+- rmconf = getrmconf(iph2->dst, nopassive ? GETRMCONF_F_NO_PASSIVE : 0);
++ int flags = 0;
++ uint32_t remoteid;
++ if (nopassive)
++ flags |= GETRMCONF_F_NO_PASSIVE;
++ if (iph2->sainfo != NULL) {
++ flags |= GETRMCONF_F_HAS_REMOTEID;
++ remoteid = iph2->sainfo->remoteid;
++ }
++ rmconf = getrmconf(iph2->dst, flags, remoteid);
+ if (rmconf == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no configuration found for %s.\n",
+@@ -2249,7 +2257,7 @@
+ struct secpolicy *sp_out, *sp_in;
+ {
+ struct remoteconf *conf;
+- uint32_t remoteid = 0;
++ uint32_t remoteid = -1;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "new acquire %s\n", spidx2str(&sp_out->spidx));
+@@ -2276,7 +2284,7 @@
+ return -1;
+ }
+
+- conf = getrmconf(iph2->dst, 0);
++ conf = getrmconf(iph2->dst, 0, 0);
+ if (conf != NULL)
+ remoteid = conf->ph1id;
+ else
+@@ -3582,6 +3590,8 @@
+
+ #undef _XIDT
+
++ spidx_normalize_ulports(&spidx);
++
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "get a src address from ID payload "
+ "%s prefixlen=%u ul_proto=%u\n",
+@@ -3654,6 +3664,7 @@
+ pref = spidx.prefs;
+ spidx.prefs = spidx.prefd;
+ spidx.prefd = pref;
++ spidx_normalize_ulports(&spidx);
+
+ if (pk_sendspddelete(iph2) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+Index: ipsec-tools-cvs-HEAD/src/racoon/remoteconf.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/remoteconf.c 2011-03-14 19:12:41.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/remoteconf.c 2011-03-29 22:08:44.000000000 +0300
+@@ -217,6 +217,13 @@
+ return MATCH_NONE;
+ }
+
++ if ((rmsel->flags & GETRMCONF_F_HAS_REMOTEID) &&
++ rmsel->remoteid != rmconf->ph1id){
++ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
++ "Not matched: remote_id did not match.\n");
++ return MATCH_NONE;
++ }
++
+ ret |= MATCH_BASIC;
+
+ /* Check address */
+@@ -387,9 +394,10 @@
+ */
+
+ struct remoteconf *
+-getrmconf(remote, flags)
++getrmconf(remote, flags, remoteid)
+ struct sockaddr *remote;
+ int flags;
++ uint32_t remoteid;
+ {
+ struct rmconf_find_context ctx;
+ int n = 0;
+@@ -397,6 +405,7 @@
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.sel.flags = flags;
+ ctx.sel.remote = remote;
++ ctx.sel.remoteid = remoteid;
+
+ if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
+ plog(LLV_ERROR, LOCATION, remote,
+Index: ipsec-tools-cvs-HEAD/src/racoon/remoteconf.h
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/remoteconf.h 2011-03-14 19:12:41.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/remoteconf.h 2011-03-29 22:08:44.000000000 +0300
+@@ -178,6 +178,7 @@
+ int flags;
+ struct sockaddr *remote;
+ int etype;
++ uint32_t remoteid;
+ struct isakmpsa *approval;
+ vchar_t *identity;
+ vchar_t *certificate_request;
+@@ -191,12 +192,13 @@
+
+ #define GETRMCONF_F_NO_ANONYMOUS 0x0001
+ #define GETRMCONF_F_NO_PASSIVE 0x0002
++#define GETRMCONF_F_HAS_REMOTEID 0x0004
+
+ #define RMCONF_ERR_MULTIPLE ((struct remoteconf *) -1)
+
+ extern int rmconf_match_identity __P((struct remoteconf *rmconf,
+ vchar_t *id_p));
+-extern struct remoteconf *getrmconf __P((struct sockaddr *remote, int flags));
++extern struct remoteconf *getrmconf __P((struct sockaddr *remote, int flags, uint32_t remoteid));
+ extern struct remoteconf *getrmconf_by_ph1 __P((struct ph1handle *iph1));
+ extern struct remoteconf *getrmconf_by_name __P((const char *name));
+
+Index: ipsec-tools-cvs-HEAD/src/racoon/pfkey.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/pfkey.c 2011-03-14 19:18:13.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/pfkey.c 2011-03-30 08:21:09.000000000 +0300
+@@ -1886,6 +1886,7 @@
+ spidx.prefs = sp_out->spidx.prefd;
+ spidx.prefd = sp_out->spidx.prefs;
+ spidx.ul_proto = sp_out->spidx.ul_proto;
++ spidx_normalize_ulports(&spidx);
+
+ #ifdef HAVE_SECCTX
+ if (m_sec_ctx) {
+@@ -2898,7 +2899,7 @@
+
+ /* If we are not acting as initiator, let's just leave and
+ * let the remote peer handle the restart */
+- rmconf = getrmconf(ma->remote, 0);
++ rmconf = getrmconf(ma->remote, 0, 0);
+ if (rmconf == NULL || !rmconf->passive) {
+ iph1->status = PHASE1ST_EXPIRED;
+ sched_schedule(&iph1->sce, 1, isakmp_ph1delete_stub);
+@@ -3068,8 +3069,10 @@
+
+ if (iph2->ph1 && iph2->ph1->rmconf)
+ rmconf = iph2->ph1->rmconf;
++ else if (iph2->sainfo != NULL)
++ rmconf = getrmconf(iph2->dst, GETRMCONF_F_HAS_REMOTEID, iph2->sainfo->remoteid);
+ else
+- rmconf = getrmconf(iph2->dst, 0);
++ rmconf = getrmconf(iph2->dst, 0, 0);
+
+ if (rmconf && !rmconf->passive) {
+ struct ph1handle *iph1hint;
+Index: ipsec-tools-cvs-HEAD/src/setkey/setkey.8
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/setkey/setkey.8 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/setkey/setkey.8 2011-03-29 22:08:44.000000000 +0300
+@@ -453,7 +453,7 @@
+ .Pp
+ A second example of requiring transport mode encryption of specific
+ GRE tunnel:
+-.Dl spdadd 0.0.0.0 0.0.0.0 gre 1234 ipsec esp/transport//require ;
++.Dl spdadd 0.0.0.0 0.0.0.0 gre 1234 -P in ipsec esp/transport//require ;
+ .Pp
+ .Em Note :
+ .Ar upperspec
+Index: ipsec-tools-cvs-HEAD/src/racoon/racoon.conf.5
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/racoon.conf.5 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/racoon.conf.5 2011-03-29 22:08:44.000000000 +0300
+@@ -981,6 +981,7 @@
+ .Bl -tag -width Ds -compact
+ .It Ic sainfo Po Ar local_id | Ic anonymous Pc \
+ Po Ar remote_id | Ic clientaddr | Ic anonymous Pc \
++Bo Ic grekey Ar key Bc \
+ Bo Ic from Ar idtype Bo Ar string Bc Bc Bo Ic group Ar string Bc \
+ Ic { Ar statements Ic }
+ Defines the parameters of the IKE phase 2 (IPsec-SA establishment).
+@@ -1026,6 +1027,15 @@
+ to restrict policy generation when racoon is acting as a client gateway
+ for peers with dynamic ip addresses.
+ .Pp
++If both
++.Ar local_id
++and
++.Ar remote_id
++are specified with GRE as upper layer protocol, the upper layer GRE
++key match can be specified with
++.Ic grekey
++.Ar key .
++.Pp
+ The
+ .Ic from
+ keyword allows an sainfo to only match for peers that use a specific phase1
+Index: ipsec-tools-cvs-HEAD/src/setkey/parse.y
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/setkey/parse.y 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/setkey/parse.y 2011-03-29 22:08:44.000000000 +0300
+@@ -856,6 +856,17 @@
+ }
+ $$.len = strlen($$.buf);
+ }
++ | DECSTRING
++ {
++ char tmp[16];
++ sprintf(tmp, "%lu", $1);
++ $$.buf = strdup(tmp);
++ if (!$$.buf) {
++ yyerror("insufficient memory");
++ return -1;
++ }
++ $$.len = strlen(tmp);
++ }
+ ;
+
+ context_spec
+Index: ipsec-tools-cvs-HEAD/src/racoon/racoonctl.8
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/racoonctl.8 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/racoonctl.8 2011-03-29 22:08:44.000000000 +0300
+@@ -158,8 +158,8 @@
+ has the following format:
+ .Bl -tag -width Bl
+ .It isakmp {inet|inet6} Ar src Ar dst
+-.It {esp|ah} {inet|inet6} Ar src/prefixlen/port Ar dst/prefixlen/port
+-{icmp|tcp|udp|gre|any}
++.It {esp|ah} {inet|inet6} Ar src/prefixlen/port Ar dst/prefixlen/port \
++ {icmp|tcp|udp|gre|any} Oo grekey Ar key Oc
+ .El
+ .It vpn-connect Oo Fl u Ar username Oc Ar vpn_gateway
+ This is a particular case of the previous command.
+Index: ipsec-tools-cvs-HEAD/src/racoon/isakmp_quick.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/isakmp_quick.c 2011-03-29 22:18:12.000000000 +0300
++++ ipsec-tools-cvs-HEAD/src/racoon/isakmp_quick.c 2011-03-30 09:23:13.000000000 +0300
+@@ -2168,6 +2168,8 @@
+ goto end;
+ }
+
++ ipsecdoi_normalize_id_uldata(idsrc, iddst);
++
+ #ifdef ENABLE_HYBRID
+
+ /* clientaddr check : obtain modecfg address */
+@@ -2494,6 +2496,7 @@
+ pref = spidx.prefs;
+ spidx.prefs = spidx.prefd;
+ spidx.prefd = pref;
++ spidx_normalize_ulports(&spidx);
+
+ sp_out = getsp_r(&spidx);
+ if (!sp_out) {
+Index: ipsec-tools-cvs-HEAD/src/racoon/policy.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/policy.c 2011-03-30 08:03:15.000000000 +0300
++++ ipsec-tools-cvs-HEAD/src/racoon/policy.c 2011-03-30 08:05:23.000000000 +0300
+@@ -444,6 +444,25 @@
+ return new;
+ }
+
++void
++spidx_normalize_ulports(spidx)
++ struct policyindex *spidx;
++{
++ u_int16_t tmp;
++
++ switch (spidx->ul_proto) {
++ case IPPROTO_ICMP:
++ case IPPROTO_ICMPV6:
++ case IPPROTO_GRE:
++ /* Ports are UL specific data, and should not get swapped */
++ tmp = extract_port((struct sockaddr *) &spidx->src);
++ set_port((struct sockaddr *) &spidx->src,
++ extract_port((struct sockaddr *) &spidx->dst));
++ set_port((struct sockaddr *) &spidx->dst, tmp);
++ break;
++ }
++}
++
+ const char *
+ spidx2str(spidx)
+ const struct policyindex *spidx;
+Index: ipsec-tools-cvs-HEAD/src/racoon/policy.h
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/policy.h 2011-03-30 08:15:44.000000000 +0300
++++ ipsec-tools-cvs-HEAD/src/racoon/policy.h 2011-03-30 08:16:21.000000000 +0300
+@@ -156,6 +156,7 @@
+ extern void flushsp __P((void));
+ extern void initsp __P((void));
+ extern struct ipsecrequest *newipsecreq __P((void));
++extern void spidx_normalize_ulports __P((struct policyindex *));
+
+ extern const char *spidx2str __P((const struct policyindex *));
+ #ifdef HAVE_SECCTX
diff --git a/main/ipsec-tools/50-reverse-connect.patch b/main/ipsec-tools/50-reverse-connect.patch
new file mode 100644
index 0000000000..54e77a3976
--- /dev/null
+++ b/main/ipsec-tools/50-reverse-connect.patch
@@ -0,0 +1,197 @@
+When new ISAKMP is required, allow incoming reverse connection to take
+
+From: Timo Teras <timo.teras@iki.fi>
+
+over pending phase1:s. Useful when the other party is firewalled or NATted.
+---
+
+ src/racoon/admin.c | 12 ++++++++++++
+ src/racoon/evt.c | 13 +++++++++++++
+ src/racoon/evt.h | 3 +++
+ src/racoon/handler.c | 28 +++++++++++++++++++++-------
+ src/racoon/isakmp.c | 39 ++++++++++++++++++++++++++++++++++-----
+ 5 files changed, 83 insertions(+), 12 deletions(-)
+
+
+Index: ipsec-tools-cvs-HEAD/src/racoon/admin.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/admin.c 2011-03-03 21:16:47.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/admin.c 2011-03-04 13:50:30.000000000 +0200
+@@ -414,11 +414,23 @@
+ struct sockaddr *dst;
+ struct sockaddr *src;
+ char *name = NULL;
++ char *loc, *rem;
+
+ ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
+ src = (struct sockaddr *) &ndx->src;
+ dst = (struct sockaddr *) &ndx->dst;
+
++ loc = racoon_strdup(saddr2str(src));
++ rem = racoon_strdup(saddr2str(dst));
++ STRDUP_FATAL(loc);
++ STRDUP_FATAL(rem);
++
++ plog(LLV_INFO, LOCATION, NULL,
++ "admin establish-sa %x %s %s\n",
++ com->ac_proto, loc, rem);
++ racoon_free(loc);
++ racoon_free(rem);
++
+ if (com->ac_cmd == ADMIN_ESTABLISH_SA &&
+ com->ac_len > sizeof(*com) + sizeof(*ndx))
+ name = (char *) ((caddr_t) ndx + sizeof(*ndx));
+Index: ipsec-tools-cvs-HEAD/src/racoon/evt.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/evt.c 2011-03-03 19:25:50.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/evt.c 2011-03-04 13:50:30.000000000 +0200
+@@ -396,4 +396,17 @@
+ evt_unsubscribe(LIST_FIRST(list));
+ }
+
++void
++evt_list_move(from, to)
++ struct evt_listener_list *from, *to;
++{
++ struct evt_listener *l;
++
++ while (!LIST_EMPTY(from)) {
++ l = LIST_FIRST(from);
++ LIST_REMOVE(l, ll_chain);
++ LIST_INSERT_HEAD(to, l, ll_chain);
++ }
++}
++
+ #endif /* ENABLE_ADMINPORT */
+Index: ipsec-tools-cvs-HEAD/src/racoon/evt.h
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/evt.h 2011-03-03 19:25:50.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/evt.h 2011-03-04 13:50:30.000000000 +0200
+@@ -124,6 +124,8 @@
+ vchar_t *evt_dump __P((void));
+
+ int evt_subscribe __P((struct evt_listener_list *list, int fd));
++void evt_list_move __P((struct evt_listener_list *from,
++ struct evt_listener_list *to));
+ void evt_list_init __P((struct evt_listener_list *list));
+ void evt_list_cleanup __P((struct evt_listener_list *list));
+
+@@ -136,6 +138,7 @@
+ #define evt_phase2(ph2, type, optdata) ;
+
+ #define evt_subscribe(eventlist, fd) ;
++#deifne evt_list_move(from, to) ;
+ #define evt_list_init(eventlist) ;
+ #define evt_list_cleanup(eventlist) ;
+ #define evt_get_fdmask(nfds, fdset) nfds
+Index: ipsec-tools-cvs-HEAD/src/racoon/handler.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/handler.c 2011-03-03 19:29:31.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/handler.c 2011-03-04 13:53:01.000000000 +0200
+@@ -292,17 +292,32 @@
+ void migrate_dying_ph12(iph1)
+ struct ph1handle *iph1;
+ {
+- struct ph1handle *p;
++ struct ph1handle *p, *next;
+
+- LIST_FOREACH(p, &ph1tree, chain) {
++ for (p = LIST_FIRST(&ph1tree); p; p = next) {
++ next = LIST_NEXT(p, chain);
+ if (p == iph1)
+ continue;
+- if (p->status < PHASE1ST_DYING)
++
++ /* Same remote? */
++ if (cmpsaddr(iph1->local, p->local) > CMPSADDR_WOP_MATCH ||
++ cmpsaddr(iph1->remote, p->remote) > CMPSADDR_WOP_MATCH ||
++ iph1->rmconf != p->rmconf)
+ continue;
+
+- if (cmpsaddr(iph1->local, p->local) == CMPSADDR_MATCH
+- && cmpsaddr(iph1->remote, p->remote) == CMPSADDR_MATCH)
++ /* migrate phase2:s from expiring entries */
++ if (p->status >= PHASE1ST_DYING)
+ migrate_ph12(p, iph1);
++
++ /* and allow reverse connections to release
++ * pending connections that do not work due
++ * to firewall or nat */
++ if (iph1->side == RESPONDER && p->side == INITIATOR &&
++ p->status < PHASE1ST_MSG3RECEIVED) {
++ /* Do not delete ph1, since if the node is not NATted,
++ * and we delete it we might get phase2's lost */
++ evt_list_move(&p->evt_listeners, &iph1->evt_listeners);
++ }
+ }
+ }
+
+Index: ipsec-tools-cvs-HEAD/src/racoon/isakmp.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/isakmp.c 2011-03-03 21:14:13.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/isakmp.c 2011-03-04 13:50:30.000000000 +0200
+@@ -2138,13 +2138,33 @@
+
+ remph2(iph2);
+ delph2(iph2);
+-
+- return;
+ }
+
+ /* %%%
+ * Interface between PF_KEYv2 and ISAKMP
+ */
++
++static void
++isakmp_chkph2there(p)
++ struct sched *p;
++{
++ struct ph2handle *iph2 = container_of(p, struct ph2handle, sce);
++ struct ph2handle *tmp;
++
++ /* Check if a similar phase2 appared meanwhile */
++ remph2(iph2);
++ tmp = getph2byid(iph2->src, iph2->dst, iph2->spid);
++ if (tmp == NULL) {
++ /* Nope, lets start this then */
++ insph2(iph2);
++ isakmp_chkph1there(iph2);
++ } else {
++ /* Yes, delete this initiation attempt as redundant */
++ evt_phase2(iph2, EVT_PHASE2_UP, NULL);
++ delph2(iph2);
++ }
++}
++
+ /*
+ * receive ACQUIRE from kernel, and begin either phase1 or phase2.
+ * if phase1 has been finished, begin phase2.
+@@ -2235,8 +2255,14 @@
+ /*NOTREACHED*/
+ }
+
+- /* found established ISAKMP-SA */
+- /* i.e. iph1->status == PHASE1ST_ESTABLISHED */
++ /* found established ISAKMP-SA, if this is a RESPONDER ISAKMP-SA
++ * add a small delay; this will make sure the initiator gets
++ * an first attempt at rekeying, and usually avoids duplicate ph2:s */
++ if (iph1->side == RESPONDER) {
++ iph2->retry_checkph1 = 1;
++ sched_schedule(&iph2->sce, 1, isakmp_chkph2there);
++ return 0;
++ }
+
+ /* found ISAKMP-SA. */
+ plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
+@@ -2403,7 +2429,10 @@
+ plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(iph2->dst));
+
+ /* begin quick mode */
+- (void)isakmp_ph2begin_i(iph1, iph2);
++ if (isakmp_ph2begin_i(iph1, iph2)) {
++ remph2(iph2);
++ delph2(iph2);
++ }
+ return;
+ }
+
diff --git a/main/ipsec-tools/70-defer-isakmp-ident-handling.patch b/main/ipsec-tools/70-defer-isakmp-ident-handling.patch
new file mode 100644
index 0000000000..9be37aa154
--- /dev/null
+++ b/main/ipsec-tools/70-defer-isakmp-ident-handling.patch
@@ -0,0 +1,179 @@
+Index: src/racoon/isakmp.c
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/isakmp.c,v
+retrieving revision 1.63
+diff -u -r1.63 isakmp.c
+--- a/src/racoon/isakmp.c 21 Oct 2010 06:15:28 -0000 1.63
++++ b/src/racoon/isakmp.c 29 Oct 2010 10:51:28 -0000
+@@ -130,6 +130,10 @@
+ # define SOL_UDP IPPROTO_UDP
+ # endif /* __NetBSD__ / __FreeBSD__ */
+
++vchar_t *postponed_buf;
++struct sockaddr_storage postponed_remote;
++struct sockaddr_storage postponed_local;
++
+ static int nostate1 __P((struct ph1handle *, vchar_t *));
+ static int nostate2 __P((struct ph2handle *, vchar_t *));
+
+@@ -177,7 +181,7 @@
+
+ static u_char r_ck0[] = { 0,0,0,0,0,0,0,0 }; /* used to verify the r_ck. */
+
+-static int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *));
++/* static int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *)); */
+ static int ph1_main __P((struct ph1handle *, vchar_t *));
+ static int quick_main __P((struct ph2handle *, vchar_t *));
+ static int isakmp_ph1begin_r __P((vchar_t *,
+@@ -374,10 +378,17 @@
+ }
+
+ /* isakmp main routine */
+- if (isakmp_main(buf, (struct sockaddr *)&remote,
+- (struct sockaddr *)&local) != 0) goto end;
+-
+- error = 0;
++ res = isakmp_main(buf, (struct sockaddr *)&remote,
++ (struct sockaddr *)&local);
++ if (res == 0) {
++ error = 0;
++ } else if (res == -42424 && postponed_buf == NULL) {
++ postponed_buf = buf;
++ postponed_remote = remote;
++ postponed_local = local;
++ buf = NULL;
++ error = 0;
++ }
+
+ end:
+ if (tmpbuf != NULL)
+@@ -390,7 +401,7 @@
+ /*
+ * main processing to handle isakmp payload
+ */
+-static int
++int
+ isakmp_main(msg, remote, local)
+ vchar_t *msg;
+ struct sockaddr *remote, *local;
+@@ -399,6 +410,7 @@
+ isakmp_index *index = (isakmp_index *)isakmp;
+ u_int32_t msgid = isakmp->msgid;
+ struct ph1handle *iph1;
++ int rc;
+
+ #ifdef HAVE_PRINT_ISAKMP_C
+ isakmp_printpacket(msg, remote, local, 0);
+@@ -604,12 +616,14 @@
+ #endif
+
+ /* call main process of phase 1 */
+- if (ph1_main(iph1, msg) < 0) {
+- plog(LLV_ERROR, LOCATION, iph1->remote,
+- "phase1 negotiation failed.\n");
+- remph1(iph1);
+- delph1(iph1);
+- return -1;
++ if ((rc=ph1_main(iph1, msg)) < 0) {
++ if (rc != -42424) {
++ plog(LLV_ERROR, LOCATION, iph1->remote,
++ "phase1 negotiation failed.\n");
++ remph1(iph1);
++ delph1(iph1);
++ }
++ return rc;
+ }
+ break;
+
+@@ -813,10 +827,11 @@
+ "failed to pre-process ph1 packet (side: %d, status %d).\n",
+ iph1->side, iph1->status);
+ return -1;
+- } else {
+- /* ignore the error and keep phase 1 handler */
+- return 0;
+ }
++ if (error == -42424)
++ return error;
++ /* ignore the error and keep phase 1 handler */
++ return 0;
+ }
+
+ #ifndef ENABLE_FRAG
+Index: src/racoon/isakmp_ident.c
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/isakmp_ident.c,v
+retrieving revision 1.13
+diff -u -r1.13 isakmp_ident.c
+--- a/src/racoon/isakmp_ident.c 18 Sep 2009 10:31:11 -0000 1.13
++++ b/src/racoon/isakmp_ident.c 29 Oct 2010 10:51:29 -0000
+@@ -1128,6 +1128,11 @@
+ goto end;
+ }
+
++ if (postponed_buf != msg) {
++ error = -42424;
++ goto end;
++ }
++
+ /* validate the type of next payload */
+ pbuf = isakmp_parse(msg);
+ if (pbuf == NULL)
+Index: src/racoon/isakmp_var.h
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/isakmp_var.h,v
+retrieving revision 1.16
+diff -u -r1.16 isakmp_var.h
+--- a/src/racoon/isakmp_var.h 3 Sep 2009 09:29:07 -0000 1.16
++++ b/src/racoon/isakmp_var.h 29 Oct 2010 10:51:29 -0000
+@@ -141,4 +141,10 @@
+ u_int32_t setscopeid __P((struct sockaddr *, struct sockaddr *));
+ #endif
+
++int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *));
++
++extern vchar_t *postponed_buf;
++extern struct sockaddr_storage postponed_remote;
++extern struct sockaddr_storage postponed_local;
++
+ #endif /* _ISAKMP_VAR_H */
+Index: src/racoon/session.c
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/session.c,v
+retrieving revision 1.28
+diff -u -r1.28 session.c
+--- a/src/racoon/session.c 21 Oct 2010 06:15:28 -0000 1.28
++++ b/src/racoon/session.c 29 Oct 2010 10:51:29 -0000
+@@ -172,7 +172,7 @@
+ int
+ session(void)
+ {
+- struct timeval *timeout;
++ struct timeval *timeout, to_zero = { 0, 0 };
+ int error;
+ char pid_file[MAXPATHLEN];
+ FILE *fp;
+@@ -295,6 +295,8 @@
+
+ /* scheduling */
+ timeout = schedular();
++ if (postponed_buf != NULL)
++ timeout = &to_zero;
+
+ /* schedular can change select() mask, so we reset
+ * the working copy here */
+@@ -332,6 +334,14 @@
+ break;
+ }
+
++ if (count == 0 && postponed_buf != NULL) {
++ (void) isakmp_main(
++ postponed_buf,
++ (struct sockaddr *) &postponed_remote,
++ (struct sockaddr *) &postponed_local);
++ vfree(postponed_buf);
++ postponed_buf = NULL;
++ }
+ }
+ }
+
diff --git a/main/ipsec-tools/75-racoonctl-rcvbuf.patch b/main/ipsec-tools/75-racoonctl-rcvbuf.patch
new file mode 100644
index 0000000000..3a68bfc2ae
--- /dev/null
+++ b/main/ipsec-tools/75-racoonctl-rcvbuf.patch
@@ -0,0 +1,33 @@
+Index: src/racoon/kmpstat.c
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/kmpstat.c,v
+retrieving revision 1.6
+diff -u -r1.6 kmpstat.c
+--- a/src/racoon/kmpstat.c 2 Oct 2007 09:47:45 -0000 1.6
++++ b/src/racoon/kmpstat.c 14 Oct 2010 12:48:22 -0000
+@@ -99,6 +99,7 @@
+ com_init()
+ {
+ struct sockaddr_un name;
++ int rcvSize;
+
+ memset(&name, 0, sizeof(name));
+ name.sun_family = AF_UNIX;
+@@ -114,6 +115,17 @@
+ return -1;
+ }
+
++ /* set receive buffer size - should be relative large:
++ * racoon daemon will try to send all info in one go, if
++ * it does not fit we'll miss stuff */
++ rcvSize = 1024 * 1024;
++ if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
++ (void*) &rcvSize, sizeof(rcvSize)) < 0) {
++ rcvSize = 512 * 1024;
++ (void) setsockopt(so, SOL_SOCKET, SO_RCVBUF,
++ (void*) &rcvSize, sizeof(rcvSize));
++ }
++
+ return 0;
+ }
+
diff --git a/main/ipsec-tools/APKBUILD b/main/ipsec-tools/APKBUILD
new file mode 100644
index 0000000000..99804bce51
--- /dev/null
+++ b/main/ipsec-tools/APKBUILD
@@ -0,0 +1,65 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ipsec-tools
+pkgver=0.8.0
+pkgrel=3
+pkgdesc="User-space IPsec tools for various IPsec implementations"
+url="http://ipsec-tools.sourceforge.net/"
+arch="all"
+license="BSD"
+depends=""
+makedepends="openssl-dev bison flex"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ racoon.initd
+ racoon.confd
+ 20-grekey-support.patch
+ 50-reverse-connect.patch
+ 70-defer-isakmp-ident-handling.patch
+ 75-racoonctl-rcvbuf.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 -i $i || return 1
+ done
+
+ sed -i 's:-Werror::g' configure
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var/lib \
+ --with-kernel-headers=/usr/include \
+ --disable-security-context \
+ --enable-adminport \
+ --enable-dpd \
+ --enable-frag \
+ --enable-hybrid \
+ --enable-ipv6 \
+ --enable-natt
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -D -m755 ../racoon.initd "$pkgdir"/etc/init.d/racoon
+ install -D -m644 ../racoon.confd "$pkgdir"/etc/conf.d/racoon
+}
+
+md5sums="c9a318cdbc0946f4e51464866d529739 ipsec-tools-0.8.0.tar.gz
+74f12ed04ed273a738229c0bfbf829cc racoon.initd
+2d00250cf72da7f2f559c91b65a48747 racoon.confd
+79b919ab23080f54dc3e7686877ca6bd 20-grekey-support.patch
+f97205eea3dc68d2437a2ad8720f4520 50-reverse-connect.patch
+94773c94233e14cdce0fa02ff780a43e 70-defer-isakmp-ident-handling.patch
+2d5d24c4a3684a38584f88720f71c7d6 75-racoonctl-rcvbuf.patch"
diff --git a/main/ipsec-tools/racoon.confd b/main/ipsec-tools/racoon.confd
new file mode 100644
index 0000000000..bf9926c5b5
--- /dev/null
+++ b/main/ipsec-tools/racoon.confd
@@ -0,0 +1,20 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-firewall/ipsec-tools/files/racoon.conf.d,v 1.3 2004/07/14 23:29:57 agriffis Exp $
+
+# Config file for /etc/init.d/racoon
+
+# See the manual pages for racoon or run `racoon --help`
+# for valid command-line options
+
+RACOON_OPTS="-4"
+SETKEY_OPTS=""
+
+RACOON_CONF="/etc/racoon/racoon.conf"
+RACOON_PSK_FILE="/etc/racoon/psk.txt"
+SETKEY_CONF="/etc/ipsec.conf"
+
+# Comment or remove the following if you don't want the policy tables
+# to be flushed when racoon is stopped.
+
+RACOON_RESET_TABLES="true"
diff --git a/main/ipsec-tools/racoon.initd b/main/ipsec-tools/racoon.initd
new file mode 100644
index 0000000000..724eee0237
--- /dev/null
+++ b/main/ipsec-tools/racoon.initd
@@ -0,0 +1,60 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+depend() {
+ before netmount
+ use net
+ after firewall ntp-client
+ provide ipsec
+}
+
+checkconfig() {
+ if [ ! -e ${SETKEY_CONF} ] ; then
+ eerror "You need to configure setkey before starting racoon."
+ return 1
+ fi
+ if [ ! -e ${RACOON_CONF} ] ; then
+ eerror "You need a configuration file to start racoon."
+ return 1
+ fi
+ if [ ! -z ${RACOON_PSK_FILE} ] ; then
+ if [ ! -f ${RACOON_PSK_FILE} ] ; then
+ eerror "PSK file not found as specified."
+ eerror "Set RACOON_PSK_FILE in /etc/conf.d/racoon."
+ return 1
+ fi
+ case "`ls -Lldn ${RACOON_PSK_FILE}`" in
+ -r--------*)
+ ;;
+ *)
+ eerror "Your defined PSK file should be mode 400 for security!"
+ return 1
+ ;;
+ esac
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ einfo "Loading ipsec policies from ${SETKEY_CONF}."
+ /usr/sbin/setkey ${SETKEY_OPTS} -f ${SETKEY_CONF}
+ if [ $? -eq 1 ] ; then
+ eerror "Error while loading ipsec policies"
+ fi
+ ebegin "Starting racoon"
+ start-stop-daemon -S -x /usr/sbin/racoon -- -f ${RACOON_CONF} ${RACOON_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping racoon"
+ start-stop-daemon -K -p /var/run/racoon.pid
+ eend $?
+ if [ -n "${RACOON_RESET_TABLES}" ]; then
+ ebegin "Flushing policy entries"
+ /usr/sbin/setkey -F
+ /usr/sbin/setkey -FP
+ eend $?
+ fi
+}
diff --git a/main/iptables/APKBUILD b/main/iptables/APKBUILD
new file mode 100644
index 0000000000..b08f790d5e
--- /dev/null
+++ b/main/iptables/APKBUILD
@@ -0,0 +1,81 @@
+#!/bin/sh
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+pkgname=iptables
+pkgver=1.4.11.1
+pkgrel=1
+pkgdesc="Linux kernel firewall, NAT and packet mangling tools"
+url="http://www.iptables.org/"
+arch="all"
+license=GPL-2
+source="http://iptables.org/projects/iptables/files/$pkgname-$pkgver.tar.bz2
+ iptables-1.4.2-include-in.patch
+ iptables.initd
+ iptables.confd
+ ip6tables.confd
+ "
+
+makedepends="linux-headers autoconf automake"
+subpackages="ip6tables $pkgname-doc $pkgname-dev"
+
+prepare() {
+ cd "$srcdir/$pkgname-$pkgver"
+ local i
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --sbindir=/sbin \
+ --without-kernel \
+ --enable-devel \
+ --enable-libipq \
+ --enable-shared \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 install DESTDIR="$pkgdir" || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ mkdir -p "$pkgdir"/usr/include/libiptc \
+ "$pkgdir"/usr/lib \
+ "$pkgdir"/var/lib/iptables \
+ "$pkgdir"/etc/init.d \
+ "$pkgdir"/etc/conf.d
+ install -m644 include/iptables.h include/ip6tables.h \
+ "$pkgdir"/usr/include/
+ install include/libiptc/*.h "$pkgdir"/usr/include/libiptc/
+ install -m644 libiptc/libiptc.a "$pkgdir"/usr/lib
+ install -m755 "$startdir"/iptables.initd "$pkgdir"/etc/init.d/iptables
+ install -m644 "$startdir"/iptables.confd "$pkgdir"/etc/conf.d/iptables
+ install -m644 "$startdir"/ip6tables.confd "$pkgdir"/etc/conf.d/ip6tables
+}
+
+ip6tables() {
+ depends="iptables"
+ mkdir -p "$subpkgdir"/sbin \
+ "$subpkgdir"/etc/init.d/ \
+ "$subpkgdir"/var/lib/ip6tables \
+ "$subpkgdir"/usr/libexec/xtables
+
+ mv "$pkgdir"/sbin/ip6* "$subpkgdir"/sbin/
+ mv "$pkgdir"/usr/libexec/xtables/libip6* \
+ "$subpkgdir"/usr/libexec/xtables/
+ install -m755 "$startdir"/iptables.initd \
+ "$subpkgdir"/etc/init.d/ip6tables
+}
+
+md5sums="7de6e1ae7ed8a2025f184763a6a24b9a iptables-1.4.11.1.tar.bz2
+ec3e80a1b0ea3e13e4e60824b7ebd1b9 iptables-1.4.2-include-in.patch
+2202ac150a5dfe32a8363b0ad565ee1d iptables.initd
+956ebf5ab69e5a1e1d3983541eab643b iptables.confd
+91933090bd9d493c91dcffc0221def61 ip6tables.confd"
diff --git a/main/iptables/ip6tables.confd b/main/iptables/ip6tables.confd
new file mode 100644
index 0000000000..6a8d94c75c
--- /dev/null
+++ b/main/iptables/ip6tables.confd
@@ -0,0 +1,11 @@
+# /etc/conf.d/ip6tables
+
+# Location in which ip6tables initscript will save set rules on
+# service shutdown
+IP6TABLES_SAVE="/var/lib/ip6tables/rules-save"
+
+# Options to pass to ip6tables-save and ip6tables-restore
+SAVE_RESTORE_OPTIONS="-c"
+
+# Save state on stopping iptables
+SAVE_ON_STOP="yes"
diff --git a/main/iptables/iptables-1.4.2-include-in.patch b/main/iptables/iptables-1.4.2-include-in.patch
new file mode 100644
index 0000000000..138fa564ca
--- /dev/null
+++ b/main/iptables/iptables-1.4.2-include-in.patch
@@ -0,0 +1,12 @@
+pull in in.h as it sets up some proto defines that iptables relies on
+
+--- a/include/xtables.h.in
++++ b/include/xtables.h.in
+@@ -5,6 +5,7 @@
+ #include <sys/types.h>
+ #include <stdbool.h>
+ #include <net/if.h>
++#include <netinet/in.h>
+ #include <linux/types.h>
+ #include <linux/netfilter/x_tables.h>
+
diff --git a/main/iptables/iptables.confd b/main/iptables/iptables.confd
new file mode 100644
index 0000000000..91287debdb
--- /dev/null
+++ b/main/iptables/iptables.confd
@@ -0,0 +1,11 @@
+# /etc/conf.d/iptables
+
+# Location in which iptables initscript will save set rules on
+# service shutdown
+IPTABLES_SAVE="/var/lib/iptables/rules-save"
+
+# Options to pass to iptables-save and iptables-restore
+SAVE_RESTORE_OPTIONS="-c"
+
+# Save state on stopping iptables
+SAVE_ON_STOP="yes"
diff --git a/main/iptables/iptables.initd b/main/iptables/iptables.initd
new file mode 100755
index 0000000000..e63d8ea9e2
--- /dev/null
+++ b/main/iptables/iptables.initd
@@ -0,0 +1,114 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-firewall/iptables/files/iptables-1.3.2.init,v 1.6 2007/03/12 21:49:04 vapier Exp $
+
+opts="save reload panic"
+
+iptables_name=${SVCNAME}
+if [ "${iptables_name}" != "iptables" -a "${iptables_name}" != "ip6tables" ] ; then
+ iptables_name="iptables"
+fi
+
+iptables_bin="/sbin/${iptables_name}"
+case ${iptables_name} in
+ iptables) iptables_proc="/proc/net/ip_tables_names"
+ iptables_save=${IPTABLES_SAVE};;
+ ip6tables) iptables_proc="/proc/net/ip6_tables_names"
+ iptables_save=${IP6TABLES_SAVE};;
+esac
+
+depend() {
+ before net
+ use logger
+}
+
+set_table_policy() {
+ local chains table=$1 policy=$2
+ case ${table} in
+ nat) chains="PREROUTING POSTROUTING OUTPUT";;
+ mangle) chains="PREROUTING INPUT FORWARD OUTPUT POSTROUTING";;
+ filter) chains="INPUT FORWARD OUTPUT";;
+ *) chains="";;
+ esac
+ local chain
+ for chain in ${chains} ; do
+ ${iptables_bin} -t ${table} -P ${chain} ${policy}
+ done
+}
+
+checkkernel() {
+ if [ ! -e ${iptables_proc} ] ; then
+ eerror "Your kernel lacks ${iptables_name} support, please load"
+ eerror "appropriate modules and try again."
+ return 1
+ fi
+ return 0
+}
+checkconfig() {
+ if [ ! -f ${iptables_save} ] ; then
+ eerror "Not starting ${iptables_name}. First create some rules then run:"
+ eerror "/etc/init.d/${iptables_name} save"
+ return 1
+ fi
+ return 0
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Loading ${iptables_name} state and starting firewall"
+ ${iptables_bin}-restore ${SAVE_RESTORE_OPTIONS} < "${iptables_save}"
+ eend $?
+}
+
+stop() {
+ if [ "${SAVE_ON_STOP}" = "yes" ] ; then
+ save || return 1
+ fi
+ checkkernel || return 1
+ ebegin "Stopping firewall"
+ local a
+ for a in $(cat ${iptables_proc}) ; do
+ set_table_policy $a ACCEPT
+
+ ${iptables_bin} -F -t $a
+ ${iptables_bin} -X -t $a
+ done
+ eend $?
+}
+
+reload() {
+ checkkernel || return 1
+ ebegin "Flushing firewall"
+ local a
+ for a in $(cat ${iptables_proc}) ; do
+ ${iptables_bin} -F -t $a
+ ${iptables_bin} -X -t $a
+ done
+ eend $?
+
+ start
+}
+
+save() {
+ ebegin "Saving ${iptables_name} state"
+ touch "${iptables_save}"
+ chmod 0600 "${iptables_save}"
+ ${iptables_bin}-save ${SAVE_RESTORE_OPTIONS} > "${iptables_save}"
+ eend $?
+}
+
+panic() {
+ checkkernel || return 1
+ service_started ${iptables_name} && svc_stop
+
+ local a
+ ebegin "Dropping all packets"
+ for a in $(cat ${iptables_proc}) ; do
+ ${iptables_bin} -F -t $a
+ ${iptables_bin} -X -t $a
+
+ set_table_policy $a DROP
+ done
+ eend $?
+}
diff --git a/main/iptraf/APKBUILD b/main/iptraf/APKBUILD
new file mode 100644
index 0000000000..260d51a369
--- /dev/null
+++ b/main/iptraf/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=iptraf
+pkgver=3.0.0
+pkgrel=4
+pkgdesc="IP Network Monitoring Software"
+url="http://iptraf.seoul.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc"
+source="ftp://iptraf.seul.org/pub/$pkgname/$pkgname-$pkgver.tar.gz
+ iptraf-3.0.0-vlan.patch
+ iptraf-3.0.0-interface.patch
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver/src"
+ patch -p1 -i "$srcdir"/iptraf-3.0.0-vlan.patch || return 1
+
+ sed -i -e s:/var/local/iptraf:/var/lib/iptraf: \
+ -e s:/usr/local/bin:/usr/sbin: dirs.h
+ make CFLAGS="$CFLAGS" DEBUG="" TARGET="/usr/sbin" \
+ WORKDIR="/var/lib/iptraf" || return 1
+
+ for sbin in iptraf rvnamed; do
+ install -D -m755 $sbin "$pkgdir"/usr/sbin/$sbin
+ done
+
+ cd ../Documentation
+ for man in *.8; do
+ install -D -m644 $man "$pkgdir"/usr/share/man/man8/$man
+ done
+
+ for dir in lib log run; do
+ mkdir -p "$pkgdir"/var/$dir/iptraf
+ done
+}
+
+md5sums="377371c28ee3c21a76f7024920649ea8 iptraf-3.0.0.tar.gz
+4136483b9e41c8789c629c42f9a67d07 iptraf-3.0.0-vlan.patch
+667def7e433fe95823fec8faeb3cd8b9 iptraf-3.0.0-interface.patch"
diff --git a/main/iptraf/iptraf-3.0.0-interface.patch b/main/iptraf/iptraf-3.0.0-interface.patch
new file mode 100644
index 0000000000..d64c963813
--- /dev/null
+++ b/main/iptraf/iptraf-3.0.0-interface.patch
@@ -0,0 +1,68 @@
+--- iptraf-3.0.0/src/packet.c.interface 2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0/src/packet.c 2008-04-22 15:27:30.000000000 +0200
+@@ -102,11 +102,19 @@ unsigned short getlinktype(unsigned shor
+ else if (strncmp(ifname, "tun", 3) == 0)
+ result = LINK_ETHERNET;
+ else if (strncmp(ifname, "vlan", 3) == 0)
+- result = LINK_VLAN;
++ result = LINK_ETHERNET;
++ else if (strncmp(ifname, "bond", 4) == 0)
++ result = LINK_ETHERNET;
+ else if (strncmp(ifname, "brg", 3) == 0)
+ result = LINK_ETHERNET;
+ else if (strncmp(ifname, "tap", 3) == 0)
+ result = LINK_ETHERNET;
++ else if (strncmp(ifname, "ctc", 3) == 0)
++ result = LINK_ETHERNET;
++ else if (strncmp(ifname, "hsi", 3) == 0)
++ result = LINK_ETHERNET;
++ else if (strncmp(ifname, "ath", 3) == 0)
++ result = LINK_ETHERNET;
+ else if ((strncmp(ifname, "isdn", 4) == 0) && (isdn_fd != -1)) {
+ isdnent = isdn_table_lookup(isdnlist, ifname, isdn_fd);
+
+@@ -235,6 +243,7 @@ void adjustpacket(char *tpacket, unsigne
+ */
+ memmove(aligned_buf, *packet, min(SNAPSHOT_LEN, *readlen));
+ *packet = aligned_buf;
++ break;
+ default:
+ *packet = (char *) NULL; /* return a NULL packet to signal */
+ break; /* an unrecognized link protocol */
+@@ -344,9 +353,14 @@ int processpacket(char *tpacket, char **
+ * Get IPTraf link type based on returned information and move past
+ * data link header.
+ */
+- *linktype =
+- getlinktype(fromaddr->sll_hatype, ifname, isdnfd, &isdntable);
+ fromaddr->sll_protocol = ntohs(fromaddr->sll_protocol);
++ if (fromaddr->sll_protocol != ETH_P_8021Q)
++ *linktype =
++ getlinktype(fromaddr->sll_hatype, ifname, isdnfd, &isdntable);
++ else {
++ *linktype = LINK_VLAN;
++ fromaddr->sll_protocol = ntohs(*((unsigned short*)(tpacket+ETH_HLEN+2)));
++ }
+ adjustpacket(tpacket, *linktype, packet, aligned_buf, br);
+
+ if (*packet == NULL)
+--- iptraf-3.0.0/src/ifaces.c.interface 2005-09-13 08:42:54.000000000 +0200
++++ iptraf-3.0.0/src/ifaces.c 2008-04-22 15:35:40.000000000 +0200
+@@ -32,14 +32,15 @@ details.
+ #include "error.h"
+
+ extern int accept_unsupported_interfaces;
+-#define NUM_SUPPORTED_IFACES 26
++#define NUM_SUPPORTED_IFACES 30
+
+ extern int daemonized;
+
+ char ifaces[][6] =
+ { "lo", "eth", "sl", "ppp", "ippp", "plip", "fddi", "isdn", "dvb",
+ "pvc", "hdlc", "ipsec", "sbni", "tr", "wvlan", "wlan", "sm2", "sm3",
+- "pent", "lec", "brg", "tun", "tap", "cipcb", "tunl", "vlan"
++ "pent", "lec", "brg", "tun", "tap", "cipcb", "tunl", "vlan", "hsi",
++ "ctc", "ath", "bond"
+ };
+
+ char *ltrim(char *buf)
diff --git a/main/iptraf/iptraf-3.0.0-vlan.patch b/main/iptraf/iptraf-3.0.0-vlan.patch
new file mode 100644
index 0000000000..f0087bf394
--- /dev/null
+++ b/main/iptraf/iptraf-3.0.0-vlan.patch
@@ -0,0 +1,28 @@
+--- src/packet.c.orig 2008-03-07 17:56:48.000000000 +0200
++++ src/packet.c 2008-03-07 18:05:41.000000000 +0200
+@@ -101,8 +101,8 @@
+ result = LINK_ETHERNET;
+ else if (strncmp(ifname, "tun", 3) == 0)
+ result = LINK_ETHERNET;
+- else if (strncmp(ifname, "vlan", 3) == 0)
+- result = LINK_VLAN;
++ else if (strncmp(ifname, "vlan", 4) == 0)
++ result = LINK_ETHERNET;
+ else if (strncmp(ifname, "brg", 3) == 0)
+ result = LINK_ETHERNET;
+ else if (strncmp(ifname, "tap", 3) == 0)
+@@ -231,14 +231,6 @@
+ case LINK_IPIP:
+ *packet = tpacket;
+ break;
+- case LINK_VLAN:
+- *packet = tpacket + VLAN_ETH_HLEN;
+- readlen -= VLAN_ETH_HLEN;
+- /*
+- * Move IP datagram into an aligned buffer.
+- */
+- memmove(aligned_buf, *packet, min(SNAPSHOT_LEN, *readlen));
+- *packet = aligned_buf;
+ default:
+ *packet = (char *) NULL; /* return a NULL packet to signal */
+ break; /* an unrecognized link protocol */
diff --git a/main/iputils/APKBUILD b/main/iputils/APKBUILD
new file mode 100644
index 0000000000..31b0daf9fc
--- /dev/null
+++ b/main/iputils/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iputils
+pkgver=20100214
+pkgrel=3
+pkgdesc="IP Configuration Utilities (and Ping)"
+url="http://www.linuxfoundation.org/en/Net:Iputils"
+arch="all"
+license="GPL"
+install=$pkgname.post-install
+depends=
+replaces="bbsuid"
+source="http://www.skbuff.net/$pkgname/$pkgname-s$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-s$pkgver
+ make KERNEL_INCLUDE=/usr/include || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-s$pkgver
+ for i in arping clockdiff ipg rarpd rdisc tftpd tracepath tracepath6; do
+ install -D -m755 $i "$pkgdir"/usr/sbin/$i
+ done
+ for i in ping ping6 traceroute6; do
+ install -D -m4755 $i "$pkgdir"/bin/$i
+ done
+}
+md5sums="37596c8b3eed537294e77464b9804726 iputils-s20100214.tar.bz2"
diff --git a/main/iputils/iputils-20070202-no-open-max.patch b/main/iputils/iputils-20070202-no-open-max.patch
new file mode 100644
index 0000000000..5013ba4fdc
--- /dev/null
+++ b/main/iputils/iputils-20070202-no-open-max.patch
@@ -0,0 +1,16 @@
+the OPEN_MAX define has been removed in newer kernel headers so use the
+proper method of getting the value dynamically
+
+http://bugs.gentoo.org/195861
+
+--- a/rdisc.c
++++ b/rdisc.c
+@@ -247,7 +247,7 @@ void do_fork(void)
+ if ((pid=fork()) != 0)
+ exit(0);
+
+- for (t = 0; t < OPEN_MAX; t++)
++ for (t = 0; t < sysconf(_SC_OPEN_MAX); t++)
+ if (t != s)
+ close(t);
+
diff --git a/main/iputils/iputils.post-install b/main/iputils/iputils.post-install
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/iputils/iputils.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/ircii/APKBUILD b/main/ircii/APKBUILD
new file mode 100644
index 0000000000..e80d88b513
--- /dev/null
+++ b/main/ircii/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ircii
+pkgver=20080314
+pkgrel=3
+pkgdesc="Universal IRC for Unix systems"
+url="http://www.eterna.com.au/ircii/"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc $pkgname-dev"
+source="ftp://ircii.warped.com/pub/ircII/ircii-20080314.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-default-server=irc.freenode.net \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+}
+
+md5sums="da7fcf2a442bd25f303778eb6466eb19 ircii-20080314.tar.bz2"
diff --git a/main/ircservices/APKBUILD b/main/ircservices/APKBUILD
new file mode 100644
index 0000000000..ec564eb83c
--- /dev/null
+++ b/main/ircservices/APKBUILD
@@ -0,0 +1,87 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ircservices
+pkgver=5.1.23
+pkgrel=2
+pkgdesc="Services for IRC (NickServ, ChanServ, MemoServ)"
+url="http://www.ircservices.za.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends="perl"
+install=$pkgname.pre-install
+pkgusers="ircservices"
+pkggroups="ircservices"
+subpackages="$pkgname-doc"
+source="http://www.ircservices.za.net/download/$pkgname-$pkgver.tar.gz
+ $pkgname.initd"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ sed -i \
+ -e "s/-m 750/-m 755/" \
+ -e "s/-m 640/-m 644/" \
+ configure
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ RUNGROUP=ircservices ./configure \
+ -cc "$CC" \
+ -cflags "$CFLAGS" \
+ -bindest /usr/bin \
+ -datdest /var/lib/ircservices \
+ || return 1
+
+ # build targets one by one as paralell builds breaks
+ make config-check &&\
+ make ircservices &&\
+ make languages &&\
+ make tools
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+# export INSTALL_PREFIX="$pkgdir"
+ make -j1 \
+ BINDEST="$pkgdir"/usr/bin \
+ DATDEST="$pkgdir"/var/lib/ircservices \
+ install || return 1
+
+ install -d "$pkgdir"/usr/share/man/man8
+ install docs/ircservices.8 "$pkgdir"/usr/share/man/man8/ircservices.8
+ install docs/convert-db.8 \
+ "$pkgdir"/usr/share/man/man8/ircservices-convert-db.8
+
+ # try conform to FHS
+ cd "$pkgdir"
+ install -d etc/ircservices usr/share/ircservices var/log/ircservices
+
+ mv var/lib/ircservices/convert-db usr/bin/ircservices-convert-db
+
+ mv var/lib/ircservices/example-ircservices.conf \
+ etc/ircservices/ircservices.conf
+ ln -s /etc/ircservices/ircservices.conf \
+ var/lib/ircservices/ircservices.conf
+
+ mv var/lib/ircservices/example-modules.conf \
+ etc/ircservices/modules.conf
+ ln -s /etc/ircservices/modules.conf var/lib/ircservices/modules.conf
+
+ mv var/lib/ircservices/languages \
+ var/lib/ircservices/helpfiles \
+ usr/share/ircservices/
+ ln -s /usr/share/ircservices/languages var/lib/ircservices/
+ ln -s /usr/share/ircservices/helpfiles var/lib/ircservices/
+
+ install -Dm755 "$srcdir"/ircservices.initd \
+ etc/init.d/ircservices
+
+ chown ircservices:ircservices var/lib/ircservices \
+ var/log/ircservices
+
+ chown root:ircservices etc/ircservices/ircservices.conf \
+ etc/ircservices/modules.conf
+}
+
+md5sums="666351f44adf57effc310a7a5943c9a2 ircservices-5.1.23.tar.gz
+279ea42c5d97b47787b5959c9981fbaa ircservices.initd"
diff --git a/main/ircservices/ircservices.confd b/main/ircservices/ircservices.confd
new file mode 100644
index 0000000000..31cc902d21
--- /dev/null
+++ b/main/ircservices/ircservices.confd
@@ -0,0 +1,6 @@
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-irc/ircservices/files/ircservices.conf.d,v 1.2 2005/05/16 15:36:11 swegener Exp $
+
+# Se this to true to have ircservices depend on a local ircd to be up
+LOCALIRCD="false"
diff --git a/main/ircservices/ircservices.initd b/main/ircservices/ircservices.initd
new file mode 100644
index 0000000000..8c2a11e8ba
--- /dev/null
+++ b/main/ircservices/ircservices.initd
@@ -0,0 +1,29 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-irc/ircservices/files/ircservices.init.d,v 1.5 2006/11/05 22:23:08 swegener Exp $
+
+depend() {
+ need net
+ after firewall
+ use ircd
+}
+
+start() {
+ ebegin "Starting IRC Services"
+ start-stop-daemon --start --quiet --exec /usr/bin/ircservices \
+ --chuid ircservices \
+ -- \
+ -dir=/var/lib/ircservices \
+ -log=/var/log/ircservices/ircservices.log \
+ &>/dev/null
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping IRC Services"
+ start-stop-daemon --stop --quiet \
+ --pidfile /var/lib/ircservices/ircservices.pid
+ eend $?
+ rm -f /var/lib/ircservices/ircservices.pid
+}
diff --git a/main/ircservices/ircservices.pre-install b/main/ircservices/ircservices.pre-install
new file mode 100644
index 0000000000..093f888563
--- /dev/null
+++ b/main/ircservices/ircservices.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /var/lib/ircservices -s /bin/false -S -D ircservices 2>/dev/null
+exit 0
+
diff --git a/main/irssi/APKBUILD b/main/irssi/APKBUILD
new file mode 100644
index 0000000000..dffcf24958
--- /dev/null
+++ b/main/irssi/APKBUILD
@@ -0,0 +1,70 @@
+# Maintainer: Kiyoshi Aman <kiyoshi.aman at gmail.com>
+pkgname=irssi
+pkgver=0.8.15
+pkgrel=7
+pkgdesc="A modular textUI IRC client with IPv6 support"
+url="http://irssi.org/"
+arch="all"
+license='GPL'
+depends=
+makedepends="glib-dev openssl-dev ncurses-dev perl-dev pkgconfig"
+source="
+ http://irssi.org/files/irssi-${pkgver}.tar.bz2
+ $pkgname-italics.patch
+ "
+subpackages="$pkgname-doc $pkgname-dev $pkgname-perl:perl $pkgname-proxy:proxy"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --with-perl=module \
+ --with-proxy
+ make || return 1
+ make DESTDIR="$pkgdir" install
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+perl() {
+ depends="$pkgname perl"
+ pkgdesc="Irssi perl support and scripts"
+ mkdir -p "$subpkgdir"/usr/share/irssi
+ mv "$pkgdir"/usr/share/irssi/scripts "$subpkgdir"/usr/share/irssi/
+ mkdir -p "$subpkgdir"/usr/lib/irssi/modules
+ mv "$pkgdir"/usr/lib/irssi/modules/libfe_perl.* \
+ "$pkgdir"/usr/lib/irssi/modules/libperl_core.* "$subpkgdir"/usr/lib/irssi/modules/
+ mv "$pkgdir"/usr/lib/perl5 "$subpkgdir"/usr/lib/
+ #need write permission when stripping
+ chmod +w "$subpkgdir"/usr/lib/perl5/core_perl/auto/Irssi/TextUI/TextUI.so
+ chmod +w "$subpkgdir"/usr/lib/perl5/core_perl/auto/Irssi/Irssi.so
+ chmod +w "$subpkgdir"/usr/lib/perl5/core_perl/auto/Irssi/Irc/Irc.so
+ chmod +w "$subpkgdir"/usr/lib/perl5/core_perl/auto/Irssi/UI/UI.so
+}
+
+proxy() {
+ depends="$pkgname"
+ pkgdesc="Irssi module for enabling bouncer-like functionality"
+ mkdir -p "$subpkgdir"/usr/lib/irssi/modules
+ mv "$pkgdir"/usr/lib/irssi/modules/libirc_proxy.* "$subpkgdir"/usr/lib/irssi/modules/
+}
+
+md5sums="1dcb3f511b88df94b0c996f36668c7da irssi-0.8.15.tar.bz2
+bb8b9f8b960837ad061a8e5b9b19824b irssi-italics.patch"
diff --git a/main/irssi/irssi-italics.patch b/main/irssi/irssi-italics.patch
new file mode 100644
index 0000000000..27763bd9ef
--- /dev/null
+++ b/main/irssi/irssi-italics.patch
@@ -0,0 +1,112 @@
+--- irssi-0.8.15/src/fe-common/core/fe-messages.c
++++ irssi-b/src/fe-common/core/fe-messages.c
+@@ -64,8 +64,12 @@
+
+ if (*bgn == '*')
+ type = 2; /* bold */
+- else if (*bgn == '_')
++ else if (*bgn == '_')
+ type = 31; /* underlined */
++ /* XXX: irssi does not support 'true' italics at this time. */
++ else if (settings_get_bool("emphasis_underline_slashes") &&
++ (*bgn == '/'))
++ type = 31; /* italics */
+ else
+ continue;
+
+@@ -76,7 +80,8 @@
+ if ((end = strchr(bgn+1, *bgn)) == NULL)
+ continue;
+ if (!ishighalnum(end[-1]) || ishighalnum(end[1]) ||
+- end[1] == type || end[1] == '*' || end[1] == '_')
++ end[1] == type || end[1] == '*' || end[1] == '_' ||
++ end[1] == '/')
+ continue;
+
+ if (IS_CHANNEL(item)) {
+@@ -643,6 +648,7 @@
+ settings_add_bool("lookandfeel", "emphasis", TRUE);
+ settings_add_bool("lookandfeel", "emphasis_replace", FALSE);
+ settings_add_bool("lookandfeel", "emphasis_multiword", FALSE);
++ settings_add_bool("lookandfeel", "emphasis_underline_slashes", FALSE);
+ settings_add_bool("lookandfeel", "show_nickmode", TRUE);
+ settings_add_bool("lookandfeel", "show_nickmode_empty", TRUE);
+ settings_add_bool("lookandfeel", "print_active_channel", FALSE);
+--- irssi-0.8.15/src/fe-common/core/formats.c
++++ irssi-b/src/fe-common/core/formats.c
+@@ -118,6 +118,10 @@
+ g_string_append_c(out, 4);
+ g_string_append_c(out, FORMAT_STYLE_UNDERLINE);
+ break;
++ case 'I':
++ /* italics on/off */
++ g_string_append_c(out, 4);
++ g_string_append_c(out, FORMAT_STYLE_ITALIC);
+ case '9':
+ case '_':
+ /* bold on/off */
+@@ -832,7 +836,7 @@
+
+ #define IS_COLOR_CODE(c) \
+ ((c) == 2 || (c) == 3 || (c) == 4 || (c) == 6 || (c) == 7 || \
+- (c) == 15 || (c) == 22 || (c) == 27 || (c) == 31)
++ (c) == 15 || (c) == 22 || (c) == 27 || (c) == 29 || (c) == 31)
+
+ /* Return how many characters in `str' must be skipped before `len'
+ characters of text is skipped. */
+@@ -1001,6 +1005,9 @@
+ case FORMAT_STYLE_UNDERLINE:
+ flags ^= GUI_PRINT_FLAG_UNDERLINE;
+ break;
++ case FORMAT_STYLE_ITALIC:
++ flags ^= GUI_PRINT_FLAG_ITALIC;
++ break;
+ case FORMAT_STYLE_BOLD:
+ flags ^= GUI_PRINT_FLAG_BOLD;
+ break;
+@@ -1050,6 +1057,7 @@
+ if (!hide_text_style)
+ flags ^= GUI_PRINT_FLAG_REVERSE;
+ break;
++ case 29: /* italics */
+ case 31:
+ /* underline */
+ if (!hide_text_style)
+--- irssi-0.8.15/src/fe-common/core/formats.h
++++ irssi-b/src/fe-common/core/formats.h
+@@ -7,9 +7,10 @@
+ #define GUI_PRINT_FLAG_BOLD 0x0001
+ #define GUI_PRINT_FLAG_REVERSE 0x0002
+ #define GUI_PRINT_FLAG_UNDERLINE 0x0004
+-#define GUI_PRINT_FLAG_BLINK 0x0008
+-#define GUI_PRINT_FLAG_MIRC_COLOR 0x0010
+-#define GUI_PRINT_FLAG_INDENT 0x0020
++#define GUI_PRINT_FLAG_ITALIC 0x0008
++#define GUI_PRINT_FLAG_BLINK 0x0010
++#define GUI_PRINT_FLAG_MIRC_COLOR 0x0020
++#define GUI_PRINT_FLAG_INDENT 0x0040
+ #define GUI_PRINT_FLAG_NEWLINE 0x0080
+ #define GUI_PRINT_FLAG_CLRTOEOL 0x0100
+ #define GUI_PRINT_FLAG_MONOSPACE 0x0200
+@@ -126,8 +127,9 @@
+ #define FORMAT_STYLE_BLINK (0x01 + FORMAT_STYLE_SPECIAL)
+ #define FORMAT_STYLE_UNDERLINE (0x02 + FORMAT_STYLE_SPECIAL)
+ #define FORMAT_STYLE_BOLD (0x03 + FORMAT_STYLE_SPECIAL)
+-#define FORMAT_STYLE_REVERSE (0x04 + FORMAT_STYLE_SPECIAL)
+-#define FORMAT_STYLE_INDENT (0x05 + FORMAT_STYLE_SPECIAL)
++#define FORMAT_STYLE_ITALIC (0x04 + FORMAT_STYLE_SPECIAL)
++#define FORMAT_STYLE_REVERSE (0x05 + FORMAT_STYLE_SPECIAL)
++#define FORMAT_STYLE_INDENT (0x06 + FORMAT_STYLE_SPECIAL)
+ #define FORMAT_STYLE_DEFAULTS (0x07 + FORMAT_STYLE_SPECIAL)
+ #define FORMAT_STYLE_CLRTOEOL (0x08 + FORMAT_STYLE_SPECIAL)
+ #define FORMAT_STYLE_MONOSPACE (0x09 + FORMAT_STYLE_SPECIAL)
+--- irssi-0.8.15/src/fe-text/gui-printtext.c
++++ irssi-b/src/fe-text/gui-printtext.c
+@@ -157,6 +157,7 @@
+ if (flags & GUI_PRINT_FLAG_REVERSE) *attr |= ATTR_REVERSE;
+ if (flags & GUI_PRINT_FLAG_BOLD) *attr |= ATTR_BOLD;
+ if (flags & GUI_PRINT_FLAG_UNDERLINE) *attr |= ATTR_UNDERLINE;
++ if (flags & GUI_PRINT_FLAG_ITALIC) *attr |= ATTR_UNDERLINE;
+ if (flags & GUI_PRINT_FLAG_BLINK) *attr |= ATTR_BLINK;
+ }
+
diff --git a/main/iscsitarget-grsec/APKBUILD b/main/iscsitarget-grsec/APKBUILD
new file mode 100644
index 0000000000..1dc1be2be4
--- /dev/null
+++ b/main/iscsitarget-grsec/APKBUILD
@@ -0,0 +1,58 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+_flavor=${FLAVOR:-grsec}
+_realname=iscsitarget
+# source the kernel version
+if [ -f ../linux-$_flavor/APKBUILD ]; then
+ . ../linux-$_flavor/APKBUILD
+fi
+_kver=$pkgver
+_kernelver=$pkgver-r$pkgrel
+_abi_release=$pkgver-${_flavor}
+_kpkgrel=$pkgrel
+
+_iscsiver=1.4.20.2
+
+pkgname=${_realname}-${_flavor}
+pkgver=$_kver
+_mypkgrel=0
+pkgrel=$(($_kpkgrel + $_mypkgrel))
+pkgdesc="$_flavor kernel modules for iscsitarget $_iscsiver"
+url="http://iscsitarget.sourceforge.net/"
+arch="all"
+license="GPL-2"
+depends="linux-${_flavor}=${_kernelver}"
+install=
+makedepends="linux-${_flavor}-dev=${_kernelver}"
+subpackages=
+source="http://downloads.sourceforge.net/$_realname/$_realname-$_iscsiver.tar.gz
+ iscsitarget-2.6.36.patch
+ iscsitarget-2.6.37.patch
+ iscsitarget-2.6.38.patch
+ "
+_ksrc=/usr/src/linux-headers-${_abi_release}
+
+prepare() {
+ cd "$srcdir"/$_realname-$_iscsiver
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/$_realname-$_iscsiver
+ unset ARCH
+ make KSRC="$_ksrc" kernel || return 1
+}
+
+package() {
+ cd "$srcdir"/$_realname-$_iscsiver
+ make KSRC="$_ksrc" DESTDIR="$pkgdir" install-kernel || return 1
+}
+
+md5sums="2f23c0bfe124d79f5c20e34ef2aaff82 iscsitarget-1.4.20.2.tar.gz
+19f311cf41aff5f13b371ff38aa543df iscsitarget-2.6.36.patch
+f29a9701fd2ba3e6e3c0c411ff0e6327 iscsitarget-2.6.37.patch
+26c42eeb23f5afd5f62dcd5aa3a639bd iscsitarget-2.6.38.patch"
diff --git a/main/iscsitarget-grsec/iscsitarget-2.6.36.patch b/main/iscsitarget-grsec/iscsitarget-2.6.36.patch
new file mode 100644
index 0000000000..43feb89975
--- /dev/null
+++ b/main/iscsitarget-grsec/iscsitarget-2.6.36.patch
@@ -0,0 +1,11 @@
+--- iscsitarget-1.4.20.2/kernel/conn.c
++++ iscsitarget-1.4.20.2.mod/kernel/conn.c
+@@ -44,7 +44,7 @@
+ switch (sk->sk_family) {
+ case AF_INET:
+ snprintf(buf, sizeof(buf),
+- "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->inet_daddr));
++ "%pI4",inet_sk(sk)->inet_daddr);
+ break;
+ case AF_INET6:
+ snprintf(buf, sizeof(buf), "[%pI6]",
diff --git a/main/iscsitarget-grsec/iscsitarget-2.6.37.patch b/main/iscsitarget-grsec/iscsitarget-2.6.37.patch
new file mode 100644
index 0000000000..42c2e7ec43
--- /dev/null
+++ b/main/iscsitarget-grsec/iscsitarget-2.6.37.patch
@@ -0,0 +1,283 @@
+diff --git a/kernel/config.c b/kernel/config.c
+index 87fa44b..672a1e3 100644
+--- a/kernel/config.c
++++ b/kernel/config.c
+@@ -9,7 +9,7 @@
+ #include "iscsi.h"
+ #include "iscsi_dbg.h"
+
+-static DECLARE_MUTEX(ioctl_sem);
++static DEFINE_MUTEX(ioctl_mutex);
+
+ struct proc_entries {
+ const char *name;
+@@ -258,7 +258,7 @@ static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ long err;
+ u32 id;
+
+- err = down_interruptible(&ioctl_sem);
++ err = mutex_lock_interruptible(&ioctl_mutex);
+ if (err < 0)
+ return err;
+
+@@ -339,7 +339,7 @@ static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+
+ target_unlock(target);
+ done:
+- up(&ioctl_sem);
++ mutex_unlock(&ioctl_mutex);
+
+ return err;
+ }
+@@ -347,9 +347,9 @@ done:
+ static int release(struct inode *i __attribute__((unused)),
+ struct file *f __attribute__((unused)))
+ {
+- down(&ioctl_sem);
++ mutex_lock(&ioctl_mutex);
+ target_del_all();
+- up(&ioctl_sem);
++ mutex_unlock(&ioctl_mutex);
+
+ return 0;
+ }
+diff --git a/kernel/iscsi.h b/kernel/iscsi.h
+index 9ded23a..f9076f2 100644
+--- a/kernel/iscsi.h
++++ b/kernel/iscsi.h
+@@ -8,7 +8,6 @@
+ #ifndef __ISCSI_H__
+ #define __ISCSI_H__
+
+-#include <linux/blkdev.h>
+ #include <linux/completion.h>
+ #include <linux/pagemap.h>
+ #include <linux/seq_file.h>
+@@ -94,8 +93,6 @@ struct worker_thread_info {
+ struct list_head work_queue;
+
+ wait_queue_head_t wthread_sleep;
+-
+- struct io_context *wthread_ioc;
+ };
+
+ struct iscsi_cmnd;
+@@ -130,7 +127,7 @@ struct iscsi_target {
+ /* Points either to own list or global pool */
+ struct worker_thread_info * wthread_info;
+
+- struct semaphore target_sem;
++ struct mutex target_mutex;
+ };
+
+ struct iscsi_queue {
+diff --git a/kernel/target.c b/kernel/target.c
+index 43326dc..2df633b 100644
+--- a/kernel/target.c
++++ b/kernel/target.c
+@@ -4,6 +4,8 @@
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
++#include <linux/mutex.h>
++
+ #include "iscsi.h"
+ #include "digest.h"
+ #include "iscsi_dbg.h"
+@@ -11,7 +13,7 @@
+ #define MAX_NR_TARGETS (1UL << 30)
+
+ static LIST_HEAD(target_list);
+-static DECLARE_MUTEX(target_list_sem);
++static DEFINE_MUTEX(target_list_mutex);
+ static u32 next_target_id;
+ static u32 nr_targets;
+
+@@ -48,16 +50,16 @@ inline int target_lock(struct iscsi_target *target, int interruptible)
+ int err = 0;
+
+ if (interruptible)
+- err = down_interruptible(&target->target_sem);
++ err = mutex_lock_interruptible(&target->target_mutex);
+ else
+- down(&target->target_sem);
++ mutex_lock(&target->target_mutex);
+
+ return err;
+ }
+
+ inline void target_unlock(struct iscsi_target *target)
+ {
+- up(&target->target_sem);
++ mutex_unlock(&target->target_mutex);
+ }
+
+ static struct iscsi_target *__target_lookup_by_id(u32 id)
+@@ -86,9 +88,9 @@ struct iscsi_target *target_lookup_by_id(u32 id)
+ {
+ struct iscsi_target *target;
+
+- down(&target_list_sem);
++ mutex_lock(&target_list_mutex);
+ target = __target_lookup_by_id(id);
+- up(&target_list_sem);
++ mutex_unlock(&target_list_mutex);
+
+ return target;
+ }
+@@ -157,7 +159,7 @@ static int iscsi_target_create(struct target_info *info, u32 tid)
+
+ strncpy(target->name, name, sizeof(target->name) - 1);
+
+- init_MUTEX(&target->target_sem);
++ mutex_init(&target->target_mutex);
+ spin_lock_init(&target->session_list_lock);
+
+ INIT_LIST_HEAD(&target->session_list);
+@@ -195,7 +197,7 @@ int target_add(struct target_info *info)
+ u32 tid = info->tid;
+ int err;
+
+- err = down_interruptible(&target_list_sem);
++ err = mutex_lock_interruptible(&target_list_mutex);
+ if (err < 0)
+ return err;
+
+@@ -204,7 +206,7 @@ int target_add(struct target_info *info)
+ goto out;
+ }
+
+- if (__target_lookup_by_name(info->name) ||
++ if (__target_lookup_by_name(info->name) ||
+ (tid && __target_lookup_by_id(tid))) {
+ err = -EEXIST;
+ goto out;
+@@ -223,7 +225,7 @@ int target_add(struct target_info *info)
+ if (!err)
+ nr_targets++;
+ out:
+- up(&target_list_sem);
++ mutex_unlock(&target_list_mutex);
+
+ return err;
+ }
+@@ -248,7 +250,7 @@ static void target_destroy(struct iscsi_target *target)
+ module_put(THIS_MODULE);
+ }
+
+-/* @locking: target_list_sem must be locked */
++/* @locking: target_list_mutex must be locked */
+ static int __target_del(struct iscsi_target *target)
+ {
+ int err;
+@@ -283,7 +285,7 @@ int target_del(u32 id)
+ struct iscsi_target *target;
+ int err;
+
+- err = down_interruptible(&target_list_sem);
++ err = mutex_lock_interruptible(&target_list_mutex);
+ if (err < 0)
+ return err;
+
+@@ -295,7 +297,7 @@ int target_del(u32 id)
+
+ err = __target_del(target);
+ out:
+- up(&target_list_sem);
++ mutex_unlock(&target_list_mutex);
+
+ return err;
+ }
+@@ -305,7 +307,7 @@ void target_del_all(void)
+ struct iscsi_target *target, *tmp;
+ int err;
+
+- down(&target_list_sem);
++ mutex_lock(&target_list_mutex);
+
+ if (!list_empty(&target_list))
+ iprintk("Removing all connections, sessions and targets\n");
+@@ -319,7 +321,7 @@ void target_del_all(void)
+
+ next_target_id = 0;
+
+- up(&target_list_sem);
++ mutex_unlock(&target_list_mutex);
+ }
+
+ static void *iet_seq_start(struct seq_file *m, loff_t *pos)
+@@ -327,7 +329,7 @@ static void *iet_seq_start(struct seq_file *m, loff_t *pos)
+ int err;
+
+ /* are you sure this is to be interruptible? */
+- err = down_interruptible(&target_list_sem);
++ err = mutex_lock_interruptible(&target_list_mutex);
+ if (err < 0)
+ return ERR_PTR(err);
+
+@@ -341,7 +343,7 @@ static void *iet_seq_next(struct seq_file *m, void *v, loff_t *pos)
+
+ static void iet_seq_stop(struct seq_file *m, void *v)
+ {
+- up(&target_list_sem);
++ mutex_unlock(&target_list_mutex);
+ }
+
+ static int iet_seq_show(struct seq_file *m, void *p)
+diff --git a/kernel/volume.c b/kernel/volume.c
+index 2c9a698..ecffa21 100644
+--- a/kernel/volume.c
++++ b/kernel/volume.c
+@@ -6,6 +6,7 @@
+
+ #include <linux/types.h>
+ #include <linux/parser.h>
++#include <linux/blkdev.h>
+
+ #include "iscsi.h"
+ #include "iscsi_dbg.h"
+diff --git a/kernel/wthread.c b/kernel/wthread.c
+index 997a3d6..884c03a 100644
+--- a/kernel/wthread.c
++++ b/kernel/wthread.c
+@@ -67,15 +67,6 @@ static int worker_thread(void *arg)
+ struct iscsi_conn *conn;
+ DECLARE_WAITQUEUE(wait, current);
+
+- get_io_context(GFP_KERNEL, -1);
+-
+- if (!current->io_context)
+- eprintk("%s\n", "Failed to get IO context");
+- else if (info->wthread_ioc)
+- copy_io_context(&current->io_context, &info->wthread_ioc);
+- else
+- info->wthread_ioc = current->io_context;
+-
+ add_wait_queue(&info->wthread_sleep, &wait);
+
+ __set_current_state(TASK_RUNNING);
+@@ -100,16 +91,6 @@ static int worker_thread(void *arg)
+
+ remove_wait_queue(&info->wthread_sleep, &wait);
+
+- if (current->io_context) {
+- struct io_context *ioc = current->io_context;
+-
+- task_lock(current);
+- current->io_context = NULL;
+- task_unlock(current);
+-
+- put_io_context(ioc);
+- }
+-
+ return 0;
+ }
+
+@@ -160,7 +141,6 @@ int wthread_init(struct worker_thread_info *info)
+ spin_lock_init(&info->wthread_lock);
+
+ info->nr_running_wthreads = 0;
+- info->wthread_ioc = NULL;
+
+ INIT_LIST_HEAD(&info->work_queue);
+ INIT_LIST_HEAD(&info->wthread_list);
diff --git a/main/iscsitarget-grsec/iscsitarget-2.6.38.patch b/main/iscsitarget-grsec/iscsitarget-2.6.38.patch
new file mode 100644
index 0000000000..90a5e56449
--- /dev/null
+++ b/main/iscsitarget-grsec/iscsitarget-2.6.38.patch
@@ -0,0 +1,32 @@
+--- ./kernel/block-io.c.orig
++++ ./kernel/block-io.c
+@@ -155,14 +155,14 @@
+ {
+ struct blockio_data *bio_data = volume->private;
+ struct block_device *bdev;
+- int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE);
++ int flags = FMODE_EXCL | FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE);
+ int err = 0;
+
+ bio_data->path = kstrdup(path, GFP_KERNEL);
+ if (!bio_data->path)
+ return -ENOMEM;
+
+- bdev = open_bdev_exclusive(path, flags, THIS_MODULE);
++ bdev = blkdev_get_by_path(path, flags, THIS_MODULE);
+ if (IS_ERR(bdev)) {
+ err = PTR_ERR(bdev);
+ eprintk("Can't open device %s, error %d\n", path, err);
+@@ -250,10 +250,10 @@
+ blockio_detach(struct iet_volume *volume)
+ {
+ struct blockio_data *bio_data = volume->private;
+- int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE);
++ int flags = FMODE_EXCL | FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE);
+
+ if (bio_data->bdev)
+- close_bdev_exclusive(bio_data->bdev, flags);
++ blkdev_put(bio_data->bdev, flags);
+ kfree(bio_data->path);
+
+ kfree(volume->private);
diff --git a/main/iscsitarget/APKBUILD b/main/iscsitarget/APKBUILD
new file mode 100644
index 0000000000..3771e7bae0
--- /dev/null
+++ b/main/iscsitarget/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+pkgname=iscsitarget
+pkgver=1.4.20.2
+pkgrel=1
+pkgdesc="Open Source iSCSI target with professional features - userspace utils"
+url="http://iscsitarget.sourceforge.net/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="openssl-dev"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ ietd.initd
+ ietd.confd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ [ -r "$i" ] || continue
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make usr || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install-usr install-doc
+
+ for i in etc/ietd.conf etc/initiators.*; do
+ install -Dm640 $i "$pkgdir"/$i || return 1
+ done
+ install -Dm755 ../ietd.initd "$pkgdir"/etc/init.d/ietd
+ install -Dm755 ../ietd.confd "$pkgdir"/etc/conf.d/ietd
+}
+
+md5sums="2f23c0bfe124d79f5c20e34ef2aaff82 iscsitarget-1.4.20.2.tar.gz
+9b0ca79dc47b12024c2b67d828d6d361 ietd.initd
+06ba479d3533d557b8582abe6f182410 ietd.confd"
diff --git a/main/iscsitarget/ietd.confd b/main/iscsitarget/ietd.confd
new file mode 100644
index 0000000000..3621326b1a
--- /dev/null
+++ b/main/iscsitarget/ietd.confd
@@ -0,0 +1,30 @@
+# Copyright 1999-2006 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/sys-block/iscsitarget/files/ietd-conf.d,v 1.1 2006/02/20 08:33:40 robbat2 Exp $
+
+# Address and port to listen on for connections.
+#ADDRESS="" # set this to non-empty to listen somewhere specific
+PORT=3260
+
+# Address of your SNS server
+# if available
+#ISNS=""
+
+# User and group to run as
+# You must ensure that the UID/GID have access to the files/devices you
+# have provided in your configuration.
+USER="root"
+GROUP="root"
+
+# Debug level - see ietd(8) for the levels
+#DEBUGLEVEL=
+
+# This setting disables the memory configuration warnings.
+# Upstream takes the general policy of forcing all of the memory settings that
+# they want, but that doesn't mesh with users that have it set higher.
+# Gentoo by default ignores the settings that are higher, but issues warnings
+# on those that are lower.
+# Uncomment the next line to disable those warnings.
+#DISABLE_MEMORY_WARNINGS=1
+
+# vim: filetype=gentoo-conf-d tw=72:
diff --git a/main/iscsitarget/ietd.initd b/main/iscsitarget/ietd.initd
new file mode 100644
index 0000000000..565b8df3fa
--- /dev/null
+++ b/main/iscsitarget/ietd.initd
@@ -0,0 +1,107 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/sys-block/iscsitarget/files/ietd-init.d-2,v 1.1 2008/07/18 16:03:38 flameeyes Exp $
+
+MEM_SIZE=1048576
+DAEMON=/usr/sbin/ietd
+CONFIG_FILE=/etc/ietd.conf
+PID_FILE=/var/run/iscsi_trgt.pid
+NAME="iSCSI Enterprise Target"
+
+ARGS=""
+[ -n "$USER" ] && ARGS="${ARGS} --uid=${USER}"
+[ -n "$GROUP" ] && ARGS="${ARGS} --gid=${GROUP}"
+[ -n "$ISNS" ] && ARGS="${ARGS} --isns=${ISNS}"
+[ -n "$PORT" ] && ARGS="${ARGS} --port=${PORT}"
+[ -n "$ADDRESS" ] && ARGS="${ARGS} --address=${ADDRESS}"
+[ -n "$DEBUGLEVEL" ] && ARGS="${ARGS} --debug=${DEBUGLEVEL}"
+
+depend() {
+ use net
+ after firewall modules
+}
+
+checkconfig() {
+ if [ ! -f $CONFIG_FILE ]; then
+ eerror "Config file $CONFIG_FILE does not exist!"
+ return 1
+ fi
+ if [ -z "$DISABLE_MEMORY_WARNINGS" ]; then
+ check_memsize
+ fi
+}
+
+check_memsize() {
+ local wr md sysctl_key v k
+ for wr in r w; do
+ for md in max default; do
+ sysctl_key="net.core.${wr}mem_${md}"
+ v="$(sysctl -n ${sysctl_key})"
+ if [ "${v}" -lt "${MEM_SIZE}" ]; then
+ ewarn "$sysctl_key ($v) is lower than recommended ${MEM_SIZE}"
+ fi
+ done
+ done
+ for wr in "" r w; do
+ sysctl_key="net.ipv4.tcp_${wr}mem"
+ set -- $(sysctl -n ${sysctl_key})
+ for k in min default max ; do
+ if [ "${1}" -lt "${MEM_SIZE}" ]; then
+ ewarn "$sysctl_key:$k (${1}) is lower than recommended ${MEM_SIZE}"
+ fi
+ shift
+ done
+ done
+}
+
+do_modules() {
+ msg="$1"
+ shift
+ modules="$1"
+ shift
+ opts="$@"
+ for m in ${modules}; do
+ ebegin "${msg} - ${m}"
+ modprobe ${opts} $m
+ ret=$?
+ eend $ret
+ [ $ret -ne 0 ] && return $ret
+ done
+ return 0
+}
+
+start() {
+ checkconfig || return 1
+ do_modules 'Loading iSCSI-Target modules' 'iscsi_trgt'
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --exec $DAEMON --quiet -- ${ARGS}
+ eend $?
+}
+
+stop() {
+ ebegin "Removing ${NAME} devices"
+ # ugly, but ietadm does not allways provides correct exit values
+ RETURN="$(ietadm --op delete 2>&1)"
+ RETVAL=$?
+ if [ $RETVAL -eq 0 ] && [ "$RETURN" != "something wrong" ] ; then
+ eend 0
+ else
+ eend 1
+ eerror "ietadm failed - $RETURN"
+ return 1
+ fi
+
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet --exec $DAEMON --pidfile $PID_FILE
+ ret=$?
+ eend $ret
+ [ $ret -ne 0 ] && return 1
+
+ # ugly, but pid file is not removed by ietd
+ rm -f $PID_FILE
+ do_modules 'Removing iSCSI-Target modules' 'iscsi_trgt' '-r'
+ return $?
+}
+
+# vim: tw=72:
diff --git a/main/iso-codes/APKBUILD b/main/iso-codes/APKBUILD
new file mode 100644
index 0000000000..f6ba4ba90e
--- /dev/null
+++ b/main/iso-codes/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iso-codes
+pkgver=3.14
+pkgrel=0
+pkgdesc="Lists of the country, language, and currency names"
+url="http://pkg-isocodes.alioth.debian.org/"
+arch="noarch"
+license="LGPL"
+depends=""
+makedepends="python gettext"
+source="ftp://pkg-isocodes.alioth.debian.org/pub/pkg-isocodes/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" pkgconfigdir=/usr/lib/pkgconfig install || return 1
+}
+md5sums="b4bedcd57de703ac4f9f4c21a77dc7d5 iso-codes-3.14.tar.bz2"
diff --git a/main/iw/APKBUILD b/main/iw/APKBUILD
new file mode 100644
index 0000000000..85f4435e82
--- /dev/null
+++ b/main/iw/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iw
+pkgver=0.9.22
+pkgrel=0
+pkgdesc="nl80211 based CLI configuration utility for wireless devices"
+url="http://wireless.kernel.org/en/users/Documentation/iw"
+arch="all"
+license="GPL"
+depends=""
+makedepends="libnl-dev"
+source="http://wireless.kernel.org/download/iw/iw-$pkgver.tar.bz2
+ iw-git-version.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build () {
+ cd "$_builddir"
+ make V=1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="561c2602c5ce7c65a590118286c0892a iw-0.9.22.tar.bz2
+779d0e73df6e484c071149c9fb720551 iw-git-version.patch"
diff --git a/main/iw/iw-git-version.patch b/main/iw/iw-git-version.patch
new file mode 100644
index 0000000000..0286eb4889
--- /dev/null
+++ b/main/iw/iw-git-version.patch
@@ -0,0 +1,11 @@
+--- ./version.sh.orig
++++ ./version.sh
+@@ -5,7 +5,7 @@
+
+ echo '#include "iw.h"' > "$OUT"
+
+-if head=`git rev-parse --verify HEAD 2>/dev/null`; then
++if [ -d .git ] && head=`git rev-parse --verify HEAD 2>/dev/null`; then
+ git update-index --refresh --unmerged > /dev/null
+ descr=$(git describe)
+
diff --git a/main/iwlwifi-1000-ucode/APKBUILD b/main/iwlwifi-1000-ucode/APKBUILD
new file mode 100644
index 0000000000..cd70cd1030
--- /dev/null
+++ b/main/iwlwifi-1000-ucode/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iwlwifi-1000-ucode
+pkgver=128.50.3.1
+pkgrel=1
+pkgdesc="Intel WiFi Link 1000BGN Microcode"
+url="http://intellinuxwireless.org/?p=iwlwifi"
+arch="all"
+license="custom"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://intellinuxwireless.org/iwlwifi/downloads/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/lib/firmware \
+ "$pkgdir"/usr/share/doc/$pkgname \
+ "$pkgdir"/usr/share/licenses/$pkgname
+ install iwlwifi-*.ucode "$pkgdir"/lib/firmware/
+ install -m644 README.* "$pkgdir"/usr/share/doc/$pkgname/
+ install -m644 LICENSE.* "$pkgdir"/usr/share/licenses/$pkgname/
+}
+
+md5sums="cfad8d5a7651dde665c5c23e8209c35d iwlwifi-1000-ucode-128.50.3.1.tgz"
diff --git a/main/iwlwifi-3945-ucode/APKBUILD b/main/iwlwifi-3945-ucode/APKBUILD
new file mode 100644
index 0000000000..038162eced
--- /dev/null
+++ b/main/iwlwifi-3945-ucode/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iwlwifi-3945-ucode
+pkgver=15.32.2.9
+pkgrel=1
+pkgdesc="Intel (R) PRO/Wireless 3945ABG Network Connection Microcode"
+url="http://intellinuxwireless.org/?p=iwlwifi"
+arch="all"
+license="custom"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://intellinuxwireless.org/iwlwifi/downloads/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/lib/firmware \
+ "$pkgdir"/usr/share/doc/$pkgname \
+ "$pkgdir"/usr/share/licenses/$pkgname
+ install iwlwifi-*.ucode "$pkgdir"/lib/firmware/
+ install -m644 README.* "$pkgdir"/usr/share/doc/$pkgname/
+ install -m644 LICENSE.* "$pkgdir"/usr/share/licenses/$pkgname/
+}
+
+md5sums="d99a75ab1305d1532a09471b2f9a547a iwlwifi-3945-ucode-15.32.2.9.tgz"
diff --git a/main/iwlwifi-4965-ucode/APKBUILD b/main/iwlwifi-4965-ucode/APKBUILD
new file mode 100644
index 0000000000..635d54f4d2
--- /dev/null
+++ b/main/iwlwifi-4965-ucode/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iwlwifi-4965-ucode
+pkgver=228.61.2.24
+pkgrel=1
+pkgdesc="Intel (R) WiFi 4965AGN Microcode"
+url="http://intellinuxwireless.org/?p=iwlwifi"
+arch="all"
+license="custom"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://intellinuxwireless.org/iwlwifi/downloads/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/lib/firmware \
+ "$pkgdir"/usr/share/doc/$pkgname \
+ "$pkgdir"/usr/share/licenses/$pkgname
+ install iwlwifi-*.ucode "$pkgdir"/lib/firmware/
+ install -m644 README.* "$pkgdir"/usr/share/doc/$pkgname/
+ install -m644 LICENSE.* "$pkgdir"/usr/share/licenses/$pkgname/
+}
+
+md5sums="2531028773cfc22aca5539c734f2a241 iwlwifi-4965-ucode-228.61.2.24.tgz"
diff --git a/main/iwlwifi-5000-ucode/APKBUILD b/main/iwlwifi-5000-ucode/APKBUILD
new file mode 100644
index 0000000000..0c5119a35c
--- /dev/null
+++ b/main/iwlwifi-5000-ucode/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iwlwifi-5000-ucode
+pkgver=8.24.2.12
+pkgrel=1
+pkgdesc="Intel WiFi 5100AGN, 5300AGN, and 5350AGN Microcode"
+url="http://intellinuxwireless.org/?p=iwlwifi"
+arch="all"
+license="custom"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://intellinuxwireless.org/iwlwifi/downloads/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/lib/firmware \
+ "$pkgdir"/usr/share/doc/$pkgname \
+ "$pkgdir"/usr/share/licenses/$pkgname
+ install iwlwifi-*.ucode "$pkgdir"/lib/firmware/
+ install -m644 README.* "$pkgdir"/usr/share/doc/$pkgname/
+ install -m644 LICENSE.* "$pkgdir"/usr/share/licenses/$pkgname/
+}
+
+md5sums="45f74d052d52f6f473dc7a8d412f2274 iwlwifi-5000-ucode-8.24.2.12.tgz"
diff --git a/main/iwlwifi-5150-ucode/APKBUILD b/main/iwlwifi-5150-ucode/APKBUILD
new file mode 100644
index 0000000000..d22bcfe88f
--- /dev/null
+++ b/main/iwlwifi-5150-ucode/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iwlwifi-5150-ucode
+pkgver=8.24.2.2
+pkgrel=1
+pkgdesc="Intel WiFi 5150AGN Microcode"
+url="http://intellinuxwireless.org/?p=iwlwifi"
+arch="all"
+license="custom"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://intellinuxwireless.org/iwlwifi/downloads/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/lib/firmware \
+ "$pkgdir"/usr/share/doc/$pkgname \
+ "$pkgdir"/usr/share/licenses/$pkgname
+ install iwlwifi-*.ucode "$pkgdir"/lib/firmware/
+ install -m644 README.* "$pkgdir"/usr/share/doc/$pkgname/
+ install -m644 LICENSE.* "$pkgdir"/usr/share/licenses/$pkgname/
+}
+
+md5sums="f9cee16e455e8046b1bf62c93f882d5d iwlwifi-5150-ucode-8.24.2.2.tgz"
diff --git a/main/iwlwifi-6000-ucode/APKBUILD b/main/iwlwifi-6000-ucode/APKBUILD
new file mode 100644
index 0000000000..7b6113eeef
--- /dev/null
+++ b/main/iwlwifi-6000-ucode/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=iwlwifi-6000-ucode
+pkgver=9.193.4.1
+pkgrel=1
+pkgdesc="Intel 6000 Series Wi-Fi Adapters Microcode"
+url="http://intellinuxwireless.org/?p=iwlwifi"
+arch="all"
+license="custom"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://intellinuxwireless.org/iwlwifi/downloads/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/lib/firmware \
+ "$pkgdir"/usr/share/doc/$pkgname \
+ "$pkgdir"/usr/share/licenses/$pkgname
+ install iwlwifi-*.ucode "$pkgdir"/lib/firmware/
+ install -m644 README.* "$pkgdir"/usr/share/doc/$pkgname/
+ install -m644 LICENSE.* "$pkgdir"/usr/share/licenses/$pkgname/
+}
+
+md5sums="e6f369713f4e60c8035f8df8cf60c2f7 iwlwifi-6000-ucode-9.193.4.1.tgz"
diff --git a/main/jasper/APKBUILD b/main/jasper/APKBUILD
new file mode 100644
index 0000000000..ff083e7567
--- /dev/null
+++ b/main/jasper/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=jasper
+pkgver=1.900.1
+pkgrel=6
+pkgdesc="A software-based implementation of the codec specified in the emerging JPEG-2000 Part-1 standard"
+url="http://www.ece.uvic.ca/~mdadams/jasper/"
+arch="all"
+license="custom:JasPer2.0"
+depends= #"libjpeg>=8 freeglut libxi libxmu mesa"
+makedepends="jpeg-dev>=8"
+subpackages="$pkgname-dev $pkgname-doc libjasper"
+source="http://www.ece.uvic.ca/~mdadams/$pkgname/software/$pkgname-$pkgver.zip
+ jpc_dec.c.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -Np1 < "$srcdir"/jpc_dec.c.patch || return 1
+ chmod +x configure
+}
+
+build () {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --enable-shared || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 LICENSE \
+ "$pkgdir"/usr/share/licenses/$pkgname/LICENSE || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+libjasper() {
+ pkgdesc="JPEG-2000 library"
+ install -d "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/lib "$subpkgdir"/usr
+}
+
+md5sums="a342b2b4495b3e1394e161eb5d85d754 jasper-1.900.1.zip
+36de7128eea6f701c1e2e13ce5bd8d37 jpc_dec.c.patch"
diff --git a/main/jasper/jpc_dec.c.patch b/main/jasper/jpc_dec.c.patch
new file mode 100644
index 0000000000..ae1cd0617e
--- /dev/null
+++ b/main/jasper/jpc_dec.c.patch
@@ -0,0 +1,18 @@
+diff -urN jasper-1.900.1/src/libjasper/jpc/jpc_dec.c jasper-1.900.1-fix/src/libjasper/jpc/jpc_dec.c
+--- jasper-1.900.1/src/libjasper/jpc/jpc_dec.c 2007-01-19 14:43:07.000000000 -0700
++++ jasper-1.900.1-fix/src/libjasper/jpc/jpc_dec.c 2008-03-06 16:51:12.000000000 -0700
+@@ -1069,12 +1069,12 @@
+ /* Apply an inverse intercomponent transform if necessary. */
+ switch (tile->cp->mctid) {
+ case JPC_MCT_RCT:
+- assert(dec->numcomps == 3);
++ assert(dec->numcomps >= 3);
+ jpc_irct(tile->tcomps[0].data, tile->tcomps[1].data,
+ tile->tcomps[2].data);
+ break;
+ case JPC_MCT_ICT:
+- assert(dec->numcomps == 3);
++ assert(dec->numcomps >= 3);
+ jpc_iict(tile->tcomps[0].data, tile->tcomps[1].data,
+ tile->tcomps[2].data);
+ break;
diff --git a/main/java-common/APKBUILD b/main/java-common/APKBUILD
new file mode 100644
index 0000000000..d5e3e4d383
--- /dev/null
+++ b/main/java-common/APKBUILD
@@ -0,0 +1,24 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=java-common
+pkgver=0.1
+pkgrel=0
+pkgdesc="Java common (updates java links)"
+url="http://git.alpinelinux.org/aports.git"
+arch="noarch"
+license="GPL2"
+depends=
+makedepends=""
+install=""
+subpackages=""
+source=""
+triggers="java-common.trigger:/usr/lib/jvm"
+
+package() {
+ mkdir -p "$pkgdir"/usr/bin
+ ln -sf ../lib/jvm/default-jvm/jre/bin/java "$pkgdir"/usr/bin
+ ln -sf ../lib/jvm/default-jvm/jre/bin/rmiregistry "$pkgdir"/usr/bin
+ ln -sf ../lib/jvm/default-jvm/jre/bin/keytool "$pkgdir"/usr/bin
+ ln -sf ../lib/jvm/default-jvm/bin/appletviewer "$pkgdir"/usr/bin
+}
+
diff --git a/main/java-common/java-common.trigger b/main/java-common/java-common.trigger
new file mode 100644
index 0000000000..6d0613d48e
--- /dev/null
+++ b/main/java-common/java-common.trigger
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+if [ -x /usr/lib/jvm/forced-jvm ]; then
+ ln -sfn forced-jvm default-jvm
+ exit 0
+fi
+
+cd /usr/lib/jvm
+LATEST=`ls -d java-* | sort -r | head -1`
+if [ "$LATEST" ]; then
+ ln -sfn $LATEST default-jvm
+fi
+
diff --git a/main/java-gcj-compat/APKBUILD b/main/java-gcj-compat/APKBUILD
new file mode 100644
index 0000000000..e9a421c69d
--- /dev/null
+++ b/main/java-gcj-compat/APKBUILD
@@ -0,0 +1,65 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+
+gccver=`(. ../../main/gcc/APKBUILD ; echo "$pkgver")`
+gccpkgrel=`(. ../../main/gcc/APKBUILD ; echo "$pkgrel")`
+
+pkgname=java-gcj-compat
+pkgver=$gccver
+_mypkgrel=0
+pkgrel=$(( $_mypkgrel + $gccpkgrel ))
+pkgdesc="JDK like environment using GCJ"
+url="http://git.alpinelinux.org/aports.git"
+arch="all"
+license="GPL"
+depends="fastjar gcc-java=$gccver-r$gccpkgrel java-common"
+makedepends="gcc-java=$gccver-r$gccpkgrel zlib-dev"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ mkdir -p $_builddir
+ cd $_builddir
+ gcj -Wl,-Bsymbolic -findirect-dispatch -o ecj \
+ --main=org.eclipse.jdt.internal.compiler.batch.Main \
+ /usr/share/java/ecj.jar
+}
+
+package() {
+ JVM_DIR=$pkgdir/usr/lib/jvm
+ JDK_DIR=$JVM_DIR/java-1.5-gcj
+ JDK_BIN_DIR=$JDK_DIR/bin
+ JRE_DIR=$JDK_DIR/jre
+ JRE_BIN_DIR=$JRE_DIR/bin
+ JRE_LIB_DIR=$JRE_DIR/lib
+
+ CPU=$(uname -m | sed -e 's/i.86/i386/g' -e 's/x86_64/amd64/g')
+
+ mkdir -p $JDK_BIN_DIR
+ ln -sf ../../../../bin/gij $JDK_BIN_DIR/java
+ ln -sf ../../../../bin/fastjar $JDK_BIN_DIR/fastjar
+ ln -sf ../../../../bin/sinjdoc $JDK_BIN_DIR/javadoc
+ ln -sf ../../../../bin/grmic $JDK_BIN_DIR/rmic
+ ln -sf ../../../../bin/gjavah $JDK_BIN_DIR/javah
+ install -s $_builddir/ecj $JDK_BIN_DIR/javac
+ ln -sf ../../../../bin/gappletviewer $JDK_BIN_DIR/appletviewer
+ ln -sf ../../../../bin/gjarsigner $JDK_BIN_DIR/jarsigner
+ ln -sf ../../../../bin/grmiregistry $JDK_BIN_DIR/rmiregistry
+ ln -sf ../../../../bin/gkeytool $JDK_BIN_DIR/keytool
+
+ gcjrel=`ls -d /usr/lib/gcj-$gccver-* | cut -d '-' -f 3`
+
+ mkdir -p $JRE_BIN_DIR $JRE_LIB_DIR/$CPU
+ ln -sf ../../../../../bin/gij $JRE_BIN_DIR/java
+ ln -sf ../../../../../bin/grmiregistry $JRE_BIN_DIR/rmiregistry
+ ln -sf ../../../../../bin/gkeytool $JRE_BIN_DIR/keytool
+ ln -sf ../../../../../share/java/libgcj-$gccver.jar $JRE_LIB_DIR/rt.jar
+ ln -sf ../../../../../share/java/libgcj-tools-$gccver.jar $JRE_LIB_DIR/tools.jar
+ ln -sf ../../../../../../lib/gcj-$gccver-$gcjrel/libjvm.so $JRE_LIB_DIR/$CPU
+ ln -sf ../../../../../../lib/gcj-$gccver-$gcjrel/libjavamath.so $JRE_LIB_DIR/$CPU
+ ln -sf ../../../../../../lib/gcj-$gccver-$gcjrel/classmap.db $JRE_LIB_DIR/$CPU
+}
+
diff --git a/main/jfsutils/APKBUILD b/main/jfsutils/APKBUILD
new file mode 100644
index 0000000000..19c28838fc
--- /dev/null
+++ b/main/jfsutils/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Teran McKinney <sega01@go-beyond.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=jfsutils
+pkgver=1.1.15
+pkgrel=0
+pkgdesc="JFS filesystem utilities"
+url="http://jfs.sourceforge.net"
+arch="all"
+license="GPL"
+depends=
+install=
+makedepends="e2fsprogs-dev" # pkgconfig is pulled in externally.
+subpackages="$pkgname-doc"
+source="http://jfs.sourceforge.net/project/pub/jfsutils-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build () {
+ cd "$_builddir"
+ ./configure \
+ --mandir=/usr/share/man
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 LDCONFIG=: DESTDIR="${pkgdir}" install || return 1
+}
+
+md5sums="8809465cd48a202895bc2a12e1923b5d jfsutils-1.1.15.tar.gz"
diff --git a/main/jpeg/APKBUILD b/main/jpeg/APKBUILD
new file mode 100644
index 0000000000..19d620c0e3
--- /dev/null
+++ b/main/jpeg/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Carlo Landmeter <clandmeter at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=jpeg
+pkgver=8
+pkgrel=5
+pkgdesc="JPEG image tools"
+url="http://www.ijg.org/"
+arch="all"
+license="AS-IS"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc $pkgname-dev libjpeg"
+source="http://www.ijg.org/files/jpegsrc.v${pkgver}.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-shared
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 install DESTDIR="$pkgdir" || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 jpegint.h "$pkgdir"/usr/include/jpegint.h
+}
+
+libjpeg() {
+ pkgdesc="JPEG image library"
+ install -d "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libjpeg* "$subpkgdir"/usr/lib/
+}
+
+
+md5sums="9c6b3514e922ad42298706163bb5e2d7 jpegsrc.v8.tar.gz"
diff --git a/main/json-glib/APKBUILD b/main/json-glib/APKBUILD
new file mode 100644
index 0000000000..80955d50d6
--- /dev/null
+++ b/main/json-glib/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=json-glib
+pkgver=0.12.6
+pkgrel=1
+pkgdesc="JSON library built on GLib"
+arch="all"
+url="http://live.gnome.org/JsonGlib"
+license="GPL"
+depends=""
+makedepends="gobject-introspection-dev glib-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/json-glib/0.12/json-glib-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd $srcdir/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="88e83b27854748421f5dadf47ca42d1a json-glib-0.12.6.tar.bz2"
diff --git a/main/jwhois/APKBUILD b/main/jwhois/APKBUILD
new file mode 100644
index 0000000000..d2fbc460c0
--- /dev/null
+++ b/main/jwhois/APKBUILD
@@ -0,0 +1,41 @@
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=jwhois
+pkgver=4.0
+pkgrel=1
+pkgdesc="WHOIS/RWHOIS client"
+url="http://www.gnu.org/software/jwhois/"
+license="GPL"
+depends=
+makedepends="libiconv-dev autoconf automake libtool"
+install=
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz
+ jwhois-libiconv.patch"
+arch="all"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ patch -p1 < "$srcdir/jwhois-libiconv.patch"
+ autoreconf
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/ \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="977d0ba90ee058a7998c94d933fc9546 jwhois-4.0.tar.gz
+f861d1891a718f3b370e1ac032b0b337 jwhois-libiconv.patch"
diff --git a/main/jwhois/jwhois-libiconv.patch b/main/jwhois/jwhois-libiconv.patch
new file mode 100644
index 0000000000..31c54bdf45
--- /dev/null
+++ b/main/jwhois/jwhois-libiconv.patch
@@ -0,0 +1,10 @@
+--- jwhois-4.0/src/Makefile.am
++++ jwhois-4.0.mod/src/Makefile.am
+@@ -23,6 +23,7 @@
+ getopt.c getopt1.c jconfig.c string.c cache.c rwhois.c jwhois.c \
+ whois.c http.c
+
++LIBS += @LIBICONV@
+ jwhois_LIBS = @LIBINTL@ @LIBICONV@ @LIBS@
+
+ jwhois_CFLAGS = $(OLDCFLAGS) -DSYSCONFDIR="\"$(sysconfdir)\"" \
diff --git a/main/kamailio/0001-utils-Install-the-sqlite-scripts.patch b/main/kamailio/0001-utils-Install-the-sqlite-scripts.patch
new file mode 100644
index 0000000000..0c72f64511
--- /dev/null
+++ b/main/kamailio/0001-utils-Install-the-sqlite-scripts.patch
@@ -0,0 +1,66 @@
+From 3ced6fc0e5298ac6f2f6dade4d564078ec586ebf Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Thu, 26 May 2011 14:04:26 +0000
+Subject: [PATCH] utils: Install the sqlite scripts
+
+Fix the makefiles to actually install the sqlite scripts
+---
+ modules_k/db_sqlite/Makefile | 10 ++++++++++
+ utils/kamctl/Makefile | 23 +++++++++++++++++++++++
+ 2 files changed, 33 insertions(+), 0 deletions(-)
+
+diff --git a/modules_k/db_sqlite/Makefile b/modules_k/db_sqlite/Makefile
+index 9a75593..1f1dd2d 100644
+--- a/modules_k/db_sqlite/Makefile
++++ b/modules_k/db_sqlite/Makefile
+@@ -13,3 +13,13 @@ DEFS+=-DOPENSER_MOD_INTERFACE
+ SERLIBPATH=../../lib
+ SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
+ include ../../Makefile.modules
++
++ifeq ($(INSTALL_FLAVOUR),kamailio)
++# extra install for kamailio
++
++install-sqlite-scripts: $(bin_prefix)/$(bin_dir)
++ SQLITEON=yes make -C ../../utils/kamctl/ install-modules
++
++install-scripts: install-sqlite-scripts
++
++endif # INSTALL_FLAVOUR
+diff --git a/utils/kamctl/Makefile b/utils/kamctl/Makefile
+index 0f2643b..8b0f790 100644
+--- a/utils/kamctl/Makefile
++++ b/utils/kamctl/Makefile
+@@ -245,6 +245,29 @@ install-modules: $(bin_prefix)/$(bin_dir)
+ fi ;\
+ done ;\
+ fi
++ # install sqlite stuff
++ if [ "$(SQLITEON)" = "yes" ]; then \
++ mkdir -p $(modules_prefix)/$(lib_dir)/kamctl ; \
++ sed -e "s#/usr/local/sbin#$(bin_target)#g" \
++ < kamctl.sqlite > /tmp/kamctl.sqlite ; \
++ $(INSTALL_CFG) /tmp/kamctl.sqlite \
++ $(modules_prefix)/$(lib_dir)/kamctl/kamctl.sqlite ; \
++ rm -fr /tmp/kamctl.sqlite ; \
++ sed -e "s#/usr/local/share/kamailio#$(data_target)#g" \
++ < kamdbctl.sqlite > /tmp/kamdbctl.sqlite ; \
++ $(INSTALL_TOUCH) $(modules_prefix)/$(lib_dir)/kamctl/kamdbctl.sqlite ; \
++ $(INSTALL_CFG) /tmp/kamdbctl.sqlite $(modules_prefix)/$(lib_dir)/kamctl/ ; \
++ rm -fr /tmp/kamdbctl.sqlite ; \
++ mkdir -p $(data_prefix)/$(data_dir)/sqlite ; \
++ for FILE in $(wildcard sqlite/*) ; do \
++ if [ -f $$FILE ] ; then \
++ $(INSTALL_TOUCH) $$FILE \
++ $(data_prefix)/$(data_dir)/sqlite/`basename "$$FILE"` ; \
++ $(INSTALL_CFG) $$FILE \
++ $(data_prefix)/$(data_dir)/sqlite/`basename "$$FILE"` ; \
++ fi ;\
++ done ; \
++ fi
+
+
+ $(cfg_prefix)/$(cfg_dir):
+--
+1.7.4.5
+
diff --git a/main/kamailio/0001-utils-add-sqlite-support-to-kamctl-kamdbctl.patch b/main/kamailio/0001-utils-add-sqlite-support-to-kamctl-kamdbctl.patch
new file mode 100644
index 0000000000..30525faf85
--- /dev/null
+++ b/main/kamailio/0001-utils-add-sqlite-support-to-kamctl-kamdbctl.patch
@@ -0,0 +1,1223 @@
+From 215a55e097c07b497747caf2a04c65cb11d783c6 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Thu, 26 May 2011 07:07:19 +0000
+Subject: [PATCH] utils: add sqlite support to kamctl/kamdbctl
+
+I basically copied the postgrersql scripts and simplified them a bit
+---
+ utils/kamctl/kamctl | 6 +
+ utils/kamctl/kamctl.sqlite | 51 +++++++++
+ utils/kamctl/kamctlrc | 6 +-
+ utils/kamctl/kamdbctl | 13 ++
+ utils/kamctl/kamdbctl.sqlite | 152 ++++++++++++++++++++++++++
+ utils/kamctl/sqlite/acc-create.sql | 28 +++++
+ utils/kamctl/sqlite/alias_db-create.sql | 12 ++
+ utils/kamctl/sqlite/auth_db-create.sql | 15 +++
+ utils/kamctl/sqlite/avpops-create.sql | 15 +++
+ utils/kamctl/sqlite/carrierroute-create.sql | 42 +++++++
+ utils/kamctl/sqlite/cpl-create.sql | 10 ++
+ utils/kamctl/sqlite/dialog-create.sql | 29 +++++
+ utils/kamctl/sqlite/dialplan-create.sql | 13 ++
+ utils/kamctl/sqlite/dispatcher-create.sql | 11 ++
+ utils/kamctl/sqlite/domain-create.sql | 8 ++
+ utils/kamctl/sqlite/domainpolicy-create.sql | 13 ++
+ utils/kamctl/sqlite/drouting-create.sql | 39 +++++++
+ utils/kamctl/sqlite/group-create.sql | 19 +++
+ utils/kamctl/sqlite/htable-create.sql | 9 ++
+ utils/kamctl/sqlite/imc-create.sql | 19 +++
+ utils/kamctl/sqlite/lcr-create.sql | 43 +++++++
+ utils/kamctl/sqlite/matrix-create.sql | 9 ++
+ utils/kamctl/sqlite/msilo-create.sql | 16 +++
+ utils/kamctl/sqlite/mtree-create.sql | 8 ++
+ utils/kamctl/sqlite/pdt-create.sql | 9 ++
+ utils/kamctl/sqlite/permissions-create.sql | 21 ++++
+ utils/kamctl/sqlite/presence-create.sql | 92 ++++++++++++++++
+ utils/kamctl/sqlite/purple-create.sql | 9 ++
+ utils/kamctl/sqlite/registrar-create.sql | 22 ++++
+ utils/kamctl/sqlite/rls-create.sql | 42 +++++++
+ utils/kamctl/sqlite/siptrace-create.sql | 20 ++++
+ utils/kamctl/sqlite/speeddial-create.sql | 14 +++
+ utils/kamctl/sqlite/standard-create.sql | 5 +
+ utils/kamctl/sqlite/uac-create.sql | 16 +++
+ utils/kamctl/sqlite/uri_db-create.sql | 10 ++
+ utils/kamctl/sqlite/userblacklist-create.sql | 21 ++++
+ utils/kamctl/sqlite/usrloc-create.sql | 22 ++++
+ 37 files changed, 887 insertions(+), 2 deletions(-)
+ create mode 100644 utils/kamctl/kamctl.sqlite
+ create mode 100644 utils/kamctl/kamdbctl.sqlite
+ create mode 100644 utils/kamctl/sqlite/acc-create.sql
+ create mode 100644 utils/kamctl/sqlite/alias_db-create.sql
+ create mode 100644 utils/kamctl/sqlite/auth_db-create.sql
+ create mode 100644 utils/kamctl/sqlite/avpops-create.sql
+ create mode 100644 utils/kamctl/sqlite/carrierroute-create.sql
+ create mode 100644 utils/kamctl/sqlite/cpl-create.sql
+ create mode 100644 utils/kamctl/sqlite/dialog-create.sql
+ create mode 100644 utils/kamctl/sqlite/dialplan-create.sql
+ create mode 100644 utils/kamctl/sqlite/dispatcher-create.sql
+ create mode 100644 utils/kamctl/sqlite/domain-create.sql
+ create mode 100644 utils/kamctl/sqlite/domainpolicy-create.sql
+ create mode 100644 utils/kamctl/sqlite/drouting-create.sql
+ create mode 100644 utils/kamctl/sqlite/group-create.sql
+ create mode 100644 utils/kamctl/sqlite/htable-create.sql
+ create mode 100644 utils/kamctl/sqlite/imc-create.sql
+ create mode 100644 utils/kamctl/sqlite/lcr-create.sql
+ create mode 100644 utils/kamctl/sqlite/matrix-create.sql
+ create mode 100644 utils/kamctl/sqlite/msilo-create.sql
+ create mode 100644 utils/kamctl/sqlite/mtree-create.sql
+ create mode 100644 utils/kamctl/sqlite/pdt-create.sql
+ create mode 100644 utils/kamctl/sqlite/permissions-create.sql
+ create mode 100644 utils/kamctl/sqlite/presence-create.sql
+ create mode 100644 utils/kamctl/sqlite/purple-create.sql
+ create mode 100644 utils/kamctl/sqlite/registrar-create.sql
+ create mode 100644 utils/kamctl/sqlite/rls-create.sql
+ create mode 100644 utils/kamctl/sqlite/siptrace-create.sql
+ create mode 100644 utils/kamctl/sqlite/speeddial-create.sql
+ create mode 100644 utils/kamctl/sqlite/standard-create.sql
+ create mode 100644 utils/kamctl/sqlite/uac-create.sql
+ create mode 100644 utils/kamctl/sqlite/uri_db-create.sql
+ create mode 100644 utils/kamctl/sqlite/userblacklist-create.sql
+ create mode 100644 utils/kamctl/sqlite/usrloc-create.sql
+
+diff --git a/utils/kamctl/kamctl b/utils/kamctl/kamctl
+index 2ec550a..c548849 100755
+--- a/utils/kamctl/kamctl
++++ b/utils/kamctl/kamctl
+@@ -124,6 +124,12 @@ case $DBENGINE in
+ DBENGINELOADED=1
+ fi
+ ;;
++ SQLITE|sqlite)
++ if [ -f "$MYLIBDIR/kamctl.sqlite" ]; then
++ . "$MYLIBDIR/kamctl.sqlite"
++ DBENGINELOADED=1
++ fi
++ ;;
+
+ esac
+
+diff --git a/utils/kamctl/kamctl.sqlite b/utils/kamctl/kamctl.sqlite
+new file mode 100644
+index 0000000..8c3eb21
+--- /dev/null
++++ b/utils/kamctl/kamctl.sqlite
+@@ -0,0 +1,51 @@
++#
++# $Id$
++#
++# control tool for maintaining Kamailio
++#
++#===================================================================
++
++##### ----------------------------------------------- #####
++### SQLITE specific variables and functions
++#
++
++##### ----------------------------------------------- #####
++### load SQL base
++#
++if [ -f "$MYLIBDIR/kamctl.sqlbase" ]; then
++ . "$MYLIBDIR/kamctl.sqlbase"
++else
++ echo "Cannot load SQL core functions '$MYLIBDIR/kamctl.sqlbase' - exiting ..."
++ exit -1
++fi
++
++DBNAME=$DB_PATH
++
++##### ----------------------------------------------- #####
++### binaries
++if [ -z "$SQLITE" ] ; then
++ locate_tool sqlite3
++ if [ -z "$TOOLPATH" ] ; then
++ echo "error: 'sqlite3' tool not found: set SQLITE variable to correct tool path"
++ exit
++ fi
++ SQLITE="$TOOLPATH"
++fi
++
++
++# input: sql query, optional sqlite3 command-line params
++sqlite_query() {
++ # if password not yet queried, query it now
++ mecho "sqlite_query: $SQLITE $2 $DBNAME $1"
++ $SQLITE $2 $DBNAME "$1"
++}
++
++# input: sql query, optional sqlite3 command-line params
++sqlite_ro_query() {
++ sqlite_query "$@"
++}
++
++DBCMD=sqlite_query
++DBROCMD=sqlite_ro_query
++DBRAWPARAMS=
++
+diff --git a/utils/kamctl/kamctlrc b/utils/kamctl/kamctlrc
+index 5e888bd..ceb6f54 100644
+--- a/utils/kamctl/kamctlrc
++++ b/utils/kamctl/kamctlrc
+@@ -12,7 +12,9 @@
+ ## chrooted directory
+ # $CHROOT_DIR="/path/to/chrooted/directory"
+
+-## database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, or DBTEXT, by default none is loaded
++## database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT, or SQLITE
++# by default none is loaded
++#
+ # If you want to setup a database with kamdbctl, you must at least specify
+ # this parameter.
+ # DBENGINE=MYSQL
+@@ -23,7 +25,7 @@
+ ## database name (for ORACLE this is TNS name)
+ # DBNAME=openser
+
+-# database path used by dbtext or db_berkeley
++# database path used by dbtext, db_berkeley or sqlite
+ # DB_PATH="/usr/local/etc/kamailio/dbtext"
+
+ ## database read/write user
+diff --git a/utils/kamctl/kamdbctl b/utils/kamctl/kamdbctl
+index c04bebd..d60f10f 100755
+--- a/utils/kamctl/kamdbctl
++++ b/utils/kamctl/kamdbctl
+@@ -108,6 +108,15 @@ case $DBENGINE in
+ merr "could not load the script in $MYLIBDIR/kamdbctl.db_berkeley for database engine $DBENGINE"
+ fi
+ ;;
++ SQLITE|sqlite)
++ if [ -f "$MYLIBDIR/kamdbctl.sqlite" ]; then
++ . "$MYLIBDIR/kamdbctl.sqlite"
++ USED_DBENGINE="sqlite"
++ DBNAME=$DB_PATH
++ else
++ merr "could not load the script in $MYLIBDIR/kamdbctl.sqlite for database engine $DBENGINE"
++ fi
++ ;;
+ esac
+
+ if [ -z "$USED_DBENGINE" ] ; then
+@@ -194,6 +203,10 @@ case $1 in
+ usage
+ exit 1
+ fi
++ if [ "$USED_DBENGINE" = "sqlite" ]; then
++ cp $DB_PATH $1
++ exit $?
++ fi
+ tmp_file=`mktemp /tmp/kamdbctl.XXXXXXXXXX` || exit 1
+ openser_dump $DBNAME $tmp_file
+ ret=$?
+diff --git a/utils/kamctl/kamdbctl.sqlite b/utils/kamctl/kamdbctl.sqlite
+new file mode 100644
+index 0000000..ecb51aa
+--- /dev/null
++++ b/utils/kamctl/kamdbctl.sqlite
+@@ -0,0 +1,152 @@
++# $Id$
++#
++# Script for adding and dropping Kamailio sqlite tables
++#
++
++# path to the database schemas
++DATA_DIR="/usr/local/share/kamailio"
++if [ -d "$DATA_DIR/sqlite" ] ; then
++ DB_SCHEMA="$DATA_DIR/sqlite"
++else
++ DB_SCHEMA="./sqlite"
++fi
++
++#################################################################
++# config vars
++#################################################################
++
++CMD="sqlite3"
++DUMP_CMD="sql_dump"
++#################################################################
++
++sql_dump()
++{
++ $CMD ${1:-$DB_PATH} .dump
++}
++
++# execute sql command with optional db name
++sql_query()
++{
++ $CMD "$@"
++}
++
++
++openser_drop() # pars: <database name>
++{
++if [ $# -ne 1 ] ; then
++ merr "openser_drop function takes one param"
++ exit 1
++fi
++
++if ! rm $1; then
++ merr "Dropping database $1 failed!"
++ exit 1
++fi
++
++minfo "Database $1 dropped"
++} #openser_drop
++
++
++openser_create () # pars: <database name>
++{
++if [ $# -ne 1 ] ; then
++ merr "openser_create function takes one param"
++ exit 1
++fi
++
++minfo "creating database $1 ..."
++
++if [ $? -ne 0 ] ; then
++ merr "Creating database failed!"
++ exit 1
++fi
++
++#sql_query "$1" "CREATE FUNCTION "concat" (text,text) RETURNS text AS 'SELECT \$1 || \$2;' LANGUAGE 'sql';
++# CREATE FUNCTION "rand" () RETURNS double precision AS 'SELECT random();' LANGUAGE 'sql';"
++# emulate mysql proprietary functions used by the lcr module in postgresql
++
++#if [ $? -ne 0 ] ; then
++# merr "Creating mysql emulation functions failed!"
++# exit 1
++#fi
++
++for TABLE in $STANDARD_MODULES; do
++ mdbg "Creating core table: $TABLE"
++ sql_query "$1" < $DB_SCHEMA/$TABLE-create.sql
++ if [ $? -ne 0 ] ; then
++ merr "Creating core tables failed!"
++ exit 1
++ fi
++done
++
++if [ -e $DB_SCHEMA/extensions-create.sql ]
++then
++ minfo "Creating custom extensions tables"
++ sql_query $1 < $DB_SCHEMA/extensions-create.sql
++ if [ $? -ne 0 ] ; then
++ merr "Creating custom extensions tables failed!"
++ exit 1
++ fi
++fi
++
++minfo "Core Kamailio tables succesfully created."
++
++get_answer $INSTALL_PRESENCE_TABLES "Install presence related tables? (y/n): "
++if [ "$ANSWER" = "y" ]; then
++ presence_create $1
++fi
++
++get_answer $INSTALL_EXTRA_TABLES "Install tables for $EXTRA_MODULES? (y/n): "
++if [ "$ANSWER" = "y" ]; then
++ extra_create $1
++fi
++} # openser_create
++
++
++presence_create () # pars: <database name>
++{
++if [ $# -ne 1 ] ; then
++ merr "presence_create function takes one param"
++ exit 1
++fi
++
++minfo "creating presence tables into $1 ..."
++
++sql_query "$1" < $DB_SCHEMA/presence-create.sql
++
++if [ $? -ne 0 ] ; then
++ merr "Failed to create presence tables!"
++ exit 1
++fi
++
++sql_query "$1" < $DB_SCHEMA/rls-create.sql
++
++if [ $? -ne 0 ] ; then
++ merr "Failed to create rls-presence tables!"
++ exit 1
++fi
++
++minfo "Presence tables succesfully created."
++} # end presence_create
++
++
++extra_create () # pars: <database name>
++{
++if [ $# -ne 1 ] ; then
++ merr "extra_create function takes one param"
++ exit 1
++fi
++
++minfo "creating extra tables into $1 ..."
++
++for TABLE in $EXTRA_MODULES; do
++ mdbg "Creating extra table: $TABLE"
++ sql_query "$1" < $DB_SCHEMA/$TABLE-create.sql
++ if [ $? -ne 0 ] ; then
++ merr "Creating extra tables failed!"
++ exit 1
++ fi
++done
++
++minfo "Extra tables succesfully created."
++} # end extra_create
+diff --git a/utils/kamctl/sqlite/acc-create.sql b/utils/kamctl/sqlite/acc-create.sql
+new file mode 100644
+index 0000000..4d23363
+--- /dev/null
++++ b/utils/kamctl/sqlite/acc-create.sql
+@@ -0,0 +1,28 @@
++INSERT INTO version (table_name, table_version) values ('acc','4');
++CREATE TABLE acc (
++ id INTEGER PRIMARY KEY NOT NULL,
++ method VARCHAR(16) DEFAULT '' NOT NULL,
++ from_tag VARCHAR(64) DEFAULT '' NOT NULL,
++ to_tag VARCHAR(64) DEFAULT '' NOT NULL,
++ callid VARCHAR(64) DEFAULT '' NOT NULL,
++ sip_code VARCHAR(3) DEFAULT '' NOT NULL,
++ sip_reason VARCHAR(32) DEFAULT '' NOT NULL,
++ time TIMESTAMP WITHOUT TIME ZONE NOT NULL
++);
++
++CREATE INDEX acc_callid_idx ON acc (callid);
++
++INSERT INTO version (table_name, table_version) values ('missed_calls','3');
++CREATE TABLE missed_calls (
++ id INTEGER PRIMARY KEY NOT NULL,
++ method VARCHAR(16) DEFAULT '' NOT NULL,
++ from_tag VARCHAR(64) DEFAULT '' NOT NULL,
++ to_tag VARCHAR(64) DEFAULT '' NOT NULL,
++ callid VARCHAR(64) DEFAULT '' NOT NULL,
++ sip_code VARCHAR(3) DEFAULT '' NOT NULL,
++ sip_reason VARCHAR(32) DEFAULT '' NOT NULL,
++ time TIMESTAMP WITHOUT TIME ZONE NOT NULL
++);
++
++CREATE INDEX missed_calls_callid_idx ON missed_calls (callid);
++
+diff --git a/utils/kamctl/sqlite/alias_db-create.sql b/utils/kamctl/sqlite/alias_db-create.sql
+new file mode 100644
+index 0000000..90656e9
+--- /dev/null
++++ b/utils/kamctl/sqlite/alias_db-create.sql
+@@ -0,0 +1,12 @@
++INSERT INTO version (table_name, table_version) values ('dbaliases','1');
++CREATE TABLE dbaliases (
++ id INTEGER PRIMARY KEY NOT NULL,
++ alias_username VARCHAR(64) DEFAULT '' NOT NULL,
++ alias_domain VARCHAR(64) DEFAULT '' NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ CONSTRAINT dbaliases_alias_idx UNIQUE (alias_username, alias_domain)
++);
++
++CREATE INDEX dbaliases_target_idx ON dbaliases (username, domain);
++
+diff --git a/utils/kamctl/sqlite/auth_db-create.sql b/utils/kamctl/sqlite/auth_db-create.sql
+new file mode 100644
+index 0000000..7d6d1f8
+--- /dev/null
++++ b/utils/kamctl/sqlite/auth_db-create.sql
+@@ -0,0 +1,15 @@
++INSERT INTO version (table_name, table_version) values ('subscriber','6');
++CREATE TABLE subscriber (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ password VARCHAR(25) DEFAULT '' NOT NULL,
++ email_address VARCHAR(64) DEFAULT '' NOT NULL,
++ ha1 VARCHAR(64) DEFAULT '' NOT NULL,
++ ha1b VARCHAR(64) DEFAULT '' NOT NULL,
++ rpid VARCHAR(64) DEFAULT NULL,
++ CONSTRAINT subscriber_account_idx UNIQUE (username, domain)
++);
++
++CREATE INDEX subscriber_username_idx ON subscriber (username);
++
+diff --git a/utils/kamctl/sqlite/avpops-create.sql b/utils/kamctl/sqlite/avpops-create.sql
+new file mode 100644
+index 0000000..007ecb5
+--- /dev/null
++++ b/utils/kamctl/sqlite/avpops-create.sql
+@@ -0,0 +1,15 @@
++INSERT INTO version (table_name, table_version) values ('usr_preferences','2');
++CREATE TABLE usr_preferences (
++ id INTEGER PRIMARY KEY NOT NULL,
++ uuid VARCHAR(64) DEFAULT '' NOT NULL,
++ username VARCHAR(128) DEFAULT 0 NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ attribute VARCHAR(32) DEFAULT '' NOT NULL,
++ type INTEGER DEFAULT 0 NOT NULL,
++ value VARCHAR(128) DEFAULT '' NOT NULL,
++ last_modified TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL
++);
++
++CREATE INDEX usr_preferences_ua_idx ON usr_preferences (uuid, attribute);
++CREATE INDEX usr_preferences_uda_idx ON usr_preferences (username, domain, attribute);
++
+diff --git a/utils/kamctl/sqlite/carrierroute-create.sql b/utils/kamctl/sqlite/carrierroute-create.sql
+new file mode 100644
+index 0000000..baafbee
+--- /dev/null
++++ b/utils/kamctl/sqlite/carrierroute-create.sql
+@@ -0,0 +1,42 @@
++INSERT INTO version (table_name, table_version) values ('carrierroute','3');
++CREATE TABLE carrierroute (
++ id INTEGER PRIMARY KEY NOT NULL,
++ carrier INTEGER DEFAULT 0 NOT NULL,
++ domain INTEGER DEFAULT 0 NOT NULL,
++ scan_prefix VARCHAR(64) DEFAULT '' NOT NULL,
++ flags INTEGER DEFAULT 0 NOT NULL,
++ mask INTEGER DEFAULT 0 NOT NULL,
++ prob REAL DEFAULT 0 NOT NULL,
++ strip INTEGER DEFAULT 0 NOT NULL,
++ rewrite_host VARCHAR(128) DEFAULT '' NOT NULL,
++ rewrite_prefix VARCHAR(64) DEFAULT '' NOT NULL,
++ rewrite_suffix VARCHAR(64) DEFAULT '' NOT NULL,
++ description VARCHAR(255) DEFAULT NULL
++);
++
++INSERT INTO version (table_name, table_version) values ('carrierfailureroute','2');
++CREATE TABLE carrierfailureroute (
++ id INTEGER PRIMARY KEY NOT NULL,
++ carrier INTEGER DEFAULT 0 NOT NULL,
++ domain INTEGER DEFAULT 0 NOT NULL,
++ scan_prefix VARCHAR(64) DEFAULT '' NOT NULL,
++ host_name VARCHAR(128) DEFAULT '' NOT NULL,
++ reply_code VARCHAR(3) DEFAULT '' NOT NULL,
++ flags INTEGER DEFAULT 0 NOT NULL,
++ mask INTEGER DEFAULT 0 NOT NULL,
++ next_domain INTEGER DEFAULT 0 NOT NULL,
++ description VARCHAR(255) DEFAULT NULL
++);
++
++INSERT INTO version (table_name, table_version) values ('carrier_name','1');
++CREATE TABLE carrier_name (
++ id INTEGER PRIMARY KEY NOT NULL,
++ carrier VARCHAR(64) DEFAULT NULL
++);
++
++INSERT INTO version (table_name, table_version) values ('domain_name','1');
++CREATE TABLE domain_name (
++ id INTEGER PRIMARY KEY NOT NULL,
++ domain VARCHAR(64) DEFAULT NULL
++);
++
+diff --git a/utils/kamctl/sqlite/cpl-create.sql b/utils/kamctl/sqlite/cpl-create.sql
+new file mode 100644
+index 0000000..8beedf5
+--- /dev/null
++++ b/utils/kamctl/sqlite/cpl-create.sql
+@@ -0,0 +1,10 @@
++INSERT INTO version (table_name, table_version) values ('cpl','1');
++CREATE TABLE cpl (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ cpl_xml TEXT,
++ cpl_bin TEXT,
++ CONSTRAINT cpl_account_idx UNIQUE (username, domain)
++);
++
+diff --git a/utils/kamctl/sqlite/dialog-create.sql b/utils/kamctl/sqlite/dialog-create.sql
+new file mode 100644
+index 0000000..bb086a5
+--- /dev/null
++++ b/utils/kamctl/sqlite/dialog-create.sql
+@@ -0,0 +1,29 @@
++INSERT INTO version (table_name, table_version) values ('dialog','5');
++CREATE TABLE dialog (
++ id INTEGER PRIMARY KEY NOT NULL,
++ hash_entry INTEGER NOT NULL,
++ hash_id INTEGER NOT NULL,
++ callid VARCHAR(255) NOT NULL,
++ from_uri VARCHAR(128) NOT NULL,
++ from_tag VARCHAR(64) NOT NULL,
++ to_uri VARCHAR(128) NOT NULL,
++ to_tag VARCHAR(64) NOT NULL,
++ caller_cseq VARCHAR(7) NOT NULL,
++ callee_cseq VARCHAR(7) NOT NULL,
++ caller_route_set VARCHAR(512),
++ callee_route_set VARCHAR(512),
++ caller_contact VARCHAR(128) NOT NULL,
++ callee_contact VARCHAR(128) NOT NULL,
++ caller_sock VARCHAR(64) NOT NULL,
++ callee_sock VARCHAR(64) NOT NULL,
++ state INTEGER NOT NULL,
++ start_time INTEGER NOT NULL,
++ timeout INTEGER DEFAULT 0 NOT NULL,
++ sflags INTEGER DEFAULT 0 NOT NULL,
++ toroute INTEGER DEFAULT 0 NOT NULL,
++ toroute_name VARCHAR(32),
++ req_uri VARCHAR(128) NOT NULL
++);
++
++CREATE INDEX dialog_hash_idx ON dialog (hash_entry, hash_id);
++
+diff --git a/utils/kamctl/sqlite/dialplan-create.sql b/utils/kamctl/sqlite/dialplan-create.sql
+new file mode 100644
+index 0000000..1a85e50
+--- /dev/null
++++ b/utils/kamctl/sqlite/dialplan-create.sql
+@@ -0,0 +1,13 @@
++INSERT INTO version (table_name, table_version) values ('dialplan','1');
++CREATE TABLE dialplan (
++ id INTEGER PRIMARY KEY NOT NULL,
++ dpid INTEGER NOT NULL,
++ pr INTEGER NOT NULL,
++ match_op INTEGER NOT NULL,
++ match_exp VARCHAR(64) NOT NULL,
++ match_len INTEGER NOT NULL,
++ subst_exp VARCHAR(64) NOT NULL,
++ repl_exp VARCHAR(32) NOT NULL,
++ attrs VARCHAR(32) NOT NULL
++);
++
+diff --git a/utils/kamctl/sqlite/dispatcher-create.sql b/utils/kamctl/sqlite/dispatcher-create.sql
+new file mode 100644
+index 0000000..ec37fc4
+--- /dev/null
++++ b/utils/kamctl/sqlite/dispatcher-create.sql
+@@ -0,0 +1,11 @@
++INSERT INTO version (table_name, table_version) values ('dispatcher','4');
++CREATE TABLE dispatcher (
++ id INTEGER PRIMARY KEY NOT NULL,
++ setid INTEGER DEFAULT 0 NOT NULL,
++ destination VARCHAR(192) DEFAULT '' NOT NULL,
++ flags INTEGER DEFAULT 0 NOT NULL,
++ priority INTEGER DEFAULT 0 NOT NULL,
++ attrs VARCHAR(128) DEFAULT '' NOT NULL,
++ description VARCHAR(64) DEFAULT '' NOT NULL
++);
++
+diff --git a/utils/kamctl/sqlite/domain-create.sql b/utils/kamctl/sqlite/domain-create.sql
+new file mode 100644
+index 0000000..0b1fbe4
+--- /dev/null
++++ b/utils/kamctl/sqlite/domain-create.sql
+@@ -0,0 +1,8 @@
++INSERT INTO version (table_name, table_version) values ('domain','1');
++CREATE TABLE domain (
++ id INTEGER PRIMARY KEY NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ last_modified TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL,
++ CONSTRAINT domain_domain_idx UNIQUE (domain)
++);
++
+diff --git a/utils/kamctl/sqlite/domainpolicy-create.sql b/utils/kamctl/sqlite/domainpolicy-create.sql
+new file mode 100644
+index 0000000..c7cb279
+--- /dev/null
++++ b/utils/kamctl/sqlite/domainpolicy-create.sql
+@@ -0,0 +1,13 @@
++INSERT INTO version (table_name, table_version) values ('domainpolicy','2');
++CREATE TABLE domainpolicy (
++ id INTEGER PRIMARY KEY NOT NULL,
++ rule VARCHAR(255) NOT NULL,
++ type VARCHAR(255) NOT NULL,
++ att VARCHAR(255),
++ val VARCHAR(128),
++ description VARCHAR(255) NOT NULL,
++ CONSTRAINT domainpolicy_rav_idx UNIQUE (rule, att, val)
++);
++
++CREATE INDEX domainpolicy_rule_idx ON domainpolicy (rule);
++
+diff --git a/utils/kamctl/sqlite/drouting-create.sql b/utils/kamctl/sqlite/drouting-create.sql
+new file mode 100644
+index 0000000..9c962fa
+--- /dev/null
++++ b/utils/kamctl/sqlite/drouting-create.sql
+@@ -0,0 +1,39 @@
++INSERT INTO version (table_name, table_version) values ('dr_gateways','3');
++CREATE TABLE dr_gateways (
++ gwid INTEGER PRIMARY KEY NOT NULL,
++ type INTEGER DEFAULT 0 NOT NULL,
++ address VARCHAR(128) NOT NULL,
++ strip INTEGER DEFAULT 0 NOT NULL,
++ pri_prefix VARCHAR(64) DEFAULT NULL,
++ attrs VARCHAR(255) DEFAULT NULL,
++ description VARCHAR(128) DEFAULT '' NOT NULL
++);
++
++INSERT INTO version (table_name, table_version) values ('dr_rules','3');
++CREATE TABLE dr_rules (
++ ruleid INTEGER PRIMARY KEY NOT NULL,
++ groupid VARCHAR(255) NOT NULL,
++ prefix VARCHAR(64) NOT NULL,
++ timerec VARCHAR(255) NOT NULL,
++ priority INTEGER DEFAULT 0 NOT NULL,
++ routeid VARCHAR(64) NOT NULL,
++ gwlist VARCHAR(255) NOT NULL,
++ description VARCHAR(128) DEFAULT '' NOT NULL
++);
++
++INSERT INTO version (table_name, table_version) values ('dr_gw_lists','1');
++CREATE TABLE dr_gw_lists (
++ id INTEGER PRIMARY KEY NOT NULL,
++ gwlist VARCHAR(255) NOT NULL,
++ description VARCHAR(128) DEFAULT '' NOT NULL
++);
++
++INSERT INTO version (table_name, table_version) values ('dr_groups','2');
++CREATE TABLE dr_groups (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) NOT NULL,
++ domain VARCHAR(128) DEFAULT '' NOT NULL,
++ groupid INTEGER DEFAULT 0 NOT NULL,
++ description VARCHAR(128) DEFAULT '' NOT NULL
++);
++
+diff --git a/utils/kamctl/sqlite/group-create.sql b/utils/kamctl/sqlite/group-create.sql
+new file mode 100644
+index 0000000..fbd91c5
+--- /dev/null
++++ b/utils/kamctl/sqlite/group-create.sql
+@@ -0,0 +1,19 @@
++INSERT INTO version (table_name, table_version) values ('grp','2');
++CREATE TABLE grp (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ grp VARCHAR(64) DEFAULT '' NOT NULL,
++ last_modified TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL,
++ CONSTRAINT grp_account_group_idx UNIQUE (username, domain, grp)
++);
++
++INSERT INTO version (table_name, table_version) values ('re_grp','1');
++CREATE TABLE re_grp (
++ id INTEGER PRIMARY KEY NOT NULL,
++ reg_exp VARCHAR(128) DEFAULT '' NOT NULL,
++ group_id INTEGER DEFAULT 0 NOT NULL
++);
++
++CREATE INDEX re_grp_group_idx ON re_grp (group_id);
++
+diff --git a/utils/kamctl/sqlite/htable-create.sql b/utils/kamctl/sqlite/htable-create.sql
+new file mode 100644
+index 0000000..59fa681
+--- /dev/null
++++ b/utils/kamctl/sqlite/htable-create.sql
+@@ -0,0 +1,9 @@
++INSERT INTO version (table_name, table_version) values ('htable','1');
++CREATE TABLE htable (
++ id INTEGER PRIMARY KEY NOT NULL,
++ key_name VARCHAR(64) DEFAULT '' NOT NULL,
++ key_type INTEGER DEFAULT 0 NOT NULL,
++ value_type INTEGER DEFAULT 0 NOT NULL,
++ key_value VARCHAR(128) DEFAULT '' NOT NULL
++);
++
+diff --git a/utils/kamctl/sqlite/imc-create.sql b/utils/kamctl/sqlite/imc-create.sql
+new file mode 100644
+index 0000000..99d68c1
+--- /dev/null
++++ b/utils/kamctl/sqlite/imc-create.sql
+@@ -0,0 +1,19 @@
++INSERT INTO version (table_name, table_version) values ('imc_rooms','1');
++CREATE TABLE imc_rooms (
++ id INTEGER PRIMARY KEY NOT NULL,
++ name VARCHAR(64) NOT NULL,
++ domain VARCHAR(64) NOT NULL,
++ flag INTEGER NOT NULL,
++ CONSTRAINT imc_rooms_name_domain_idx UNIQUE (name, domain)
++);
++
++INSERT INTO version (table_name, table_version) values ('imc_members','1');
++CREATE TABLE imc_members (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) NOT NULL,
++ domain VARCHAR(64) NOT NULL,
++ room VARCHAR(64) NOT NULL,
++ flag INTEGER NOT NULL,
++ CONSTRAINT imc_members_account_room_idx UNIQUE (username, domain, room)
++);
++
+diff --git a/utils/kamctl/sqlite/lcr-create.sql b/utils/kamctl/sqlite/lcr-create.sql
+new file mode 100644
+index 0000000..bf93141
+--- /dev/null
++++ b/utils/kamctl/sqlite/lcr-create.sql
+@@ -0,0 +1,43 @@
++INSERT INTO version (table_name, table_version) values ('lcr_gw','2');
++CREATE TABLE lcr_gw (
++ id INTEGER PRIMARY KEY NOT NULL,
++ lcr_id SMALLINT NOT NULL,
++ gw_name VARCHAR(128),
++ ip_addr VARCHAR(15),
++ hostname VARCHAR(64),
++ port SMALLINT,
++ params VARCHAR(64),
++ uri_scheme SMALLINT,
++ transport SMALLINT,
++ strip SMALLINT,
++ prefix VARCHAR(16) DEFAULT NULL,
++ tag VARCHAR(64) DEFAULT NULL,
++ flags INTEGER DEFAULT 0 NOT NULL,
++ defunct INTEGER DEFAULT NULL,
++ CONSTRAINT lcr_gw_lcr_id_ip_addr_port_hostname_idx UNIQUE (lcr_id, ip_addr, port, hostname)
++);
++
++INSERT INTO version (table_name, table_version) values ('lcr_rule_target','1');
++CREATE TABLE lcr_rule_target (
++ id INTEGER PRIMARY KEY NOT NULL,
++ lcr_id SMALLINT NOT NULL,
++ rule_id INTEGER NOT NULL,
++ gw_id INTEGER NOT NULL,
++ priority SMALLINT NOT NULL,
++ weight INTEGER DEFAULT 1 NOT NULL,
++ CONSTRAINT lcr_rule_target_rule_id_gw_id_idx UNIQUE (rule_id, gw_id)
++);
++
++CREATE INDEX lcr_rule_target_lcr_id_idx ON lcr_rule_target (lcr_id);
++
++INSERT INTO version (table_name, table_version) values ('lcr_rule','1');
++CREATE TABLE lcr_rule (
++ id INTEGER PRIMARY KEY NOT NULL,
++ lcr_id SMALLINT NOT NULL,
++ prefix VARCHAR(16) DEFAULT NULL,
++ from_uri VARCHAR(64) DEFAULT NULL,
++ stopper INTEGER DEFAULT 0 NOT NULL,
++ enabled INTEGER DEFAULT 1 NOT NULL,
++ CONSTRAINT lcr_rule_lcr_id_prefix_from_uri_idx UNIQUE (lcr_id, prefix, from_uri)
++);
++
+diff --git a/utils/kamctl/sqlite/matrix-create.sql b/utils/kamctl/sqlite/matrix-create.sql
+new file mode 100644
+index 0000000..50f2ed8
+--- /dev/null
++++ b/utils/kamctl/sqlite/matrix-create.sql
+@@ -0,0 +1,9 @@
++INSERT INTO version (table_name, table_version) values ('matrix','1');
++CREATE TABLE matrix (
++ first INTEGER NOT NULL,
++ second SMALLINT NOT NULL,
++ res INTEGER NOT NULL
++);
++
++CREATE INDEX matrix_matrix_idx ON matrix (first, second);
++
+diff --git a/utils/kamctl/sqlite/msilo-create.sql b/utils/kamctl/sqlite/msilo-create.sql
+new file mode 100644
+index 0000000..7234112
+--- /dev/null
++++ b/utils/kamctl/sqlite/msilo-create.sql
+@@ -0,0 +1,16 @@
++INSERT INTO version (table_name, table_version) values ('silo','5');
++CREATE TABLE silo (
++ id INTEGER PRIMARY KEY NOT NULL,
++ src_addr VARCHAR(128) DEFAULT '' NOT NULL,
++ dst_addr VARCHAR(128) DEFAULT '' NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ inc_time INTEGER DEFAULT 0 NOT NULL,
++ exp_time INTEGER DEFAULT 0 NOT NULL,
++ snd_time INTEGER DEFAULT 0 NOT NULL,
++ ctype VARCHAR(32) DEFAULT 'text/plain' NOT NULL,
++ body BYTEA DEFAULT '' NOT NULL
++);
++
++CREATE INDEX silo_account_idx ON silo (username, domain);
++
+diff --git a/utils/kamctl/sqlite/mtree-create.sql b/utils/kamctl/sqlite/mtree-create.sql
+new file mode 100644
+index 0000000..9b6f56f
+--- /dev/null
++++ b/utils/kamctl/sqlite/mtree-create.sql
+@@ -0,0 +1,8 @@
++INSERT INTO version (table_name, table_version) values ('mtree','1');
++CREATE TABLE mtree (
++ id INTEGER PRIMARY KEY NOT NULL,
++ tprefix VARCHAR(32) DEFAULT '' NOT NULL,
++ tvalue VARCHAR(128) DEFAULT '' NOT NULL,
++ CONSTRAINT mtree_tprefix_idx UNIQUE (tprefix)
++);
++
+diff --git a/utils/kamctl/sqlite/pdt-create.sql b/utils/kamctl/sqlite/pdt-create.sql
+new file mode 100644
+index 0000000..46b517a
+--- /dev/null
++++ b/utils/kamctl/sqlite/pdt-create.sql
+@@ -0,0 +1,9 @@
++INSERT INTO version (table_name, table_version) values ('pdt','1');
++CREATE TABLE pdt (
++ id INTEGER PRIMARY KEY NOT NULL,
++ sdomain VARCHAR(128) NOT NULL,
++ prefix VARCHAR(32) NOT NULL,
++ domain VARCHAR(128) DEFAULT '' NOT NULL,
++ CONSTRAINT pdt_sdomain_prefix_idx UNIQUE (sdomain, prefix)
++);
++
+diff --git a/utils/kamctl/sqlite/permissions-create.sql b/utils/kamctl/sqlite/permissions-create.sql
+new file mode 100644
+index 0000000..ff3ac56
+--- /dev/null
++++ b/utils/kamctl/sqlite/permissions-create.sql
+@@ -0,0 +1,21 @@
++INSERT INTO version (table_name, table_version) values ('trusted','5');
++CREATE TABLE trusted (
++ id INTEGER PRIMARY KEY NOT NULL,
++ src_ip VARCHAR(50) NOT NULL,
++ proto VARCHAR(4) NOT NULL,
++ from_pattern VARCHAR(64) DEFAULT NULL,
++ tag VARCHAR(64)
++);
++
++CREATE INDEX trusted_peer_idx ON trusted (src_ip);
++
++INSERT INTO version (table_name, table_version) values ('address','4');
++CREATE TABLE address (
++ id INTEGER PRIMARY KEY NOT NULL,
++ grp SMALLINT DEFAULT 1 NOT NULL,
++ ip_addr VARCHAR(15) NOT NULL,
++ mask SMALLINT DEFAULT 32 NOT NULL,
++ port SMALLINT DEFAULT 0 NOT NULL,
++ tag VARCHAR(64)
++);
++
+diff --git a/utils/kamctl/sqlite/presence-create.sql b/utils/kamctl/sqlite/presence-create.sql
+new file mode 100644
+index 0000000..fe89b36
+--- /dev/null
++++ b/utils/kamctl/sqlite/presence-create.sql
+@@ -0,0 +1,92 @@
++INSERT INTO version (table_name, table_version) values ('presentity','3');
++CREATE TABLE presentity (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) NOT NULL,
++ domain VARCHAR(64) NOT NULL,
++ event VARCHAR(64) NOT NULL,
++ etag VARCHAR(64) NOT NULL,
++ expires INTEGER NOT NULL,
++ received_time INTEGER NOT NULL,
++ body BYTEA NOT NULL,
++ sender VARCHAR(128) NOT NULL,
++ CONSTRAINT presentity_presentity_idx UNIQUE (username, domain, event, etag)
++);
++
++INSERT INTO version (table_name, table_version) values ('active_watchers','9');
++CREATE TABLE active_watchers (
++ id INTEGER PRIMARY KEY NOT NULL,
++ presentity_uri VARCHAR(128) NOT NULL,
++ watcher_username VARCHAR(64) NOT NULL,
++ watcher_domain VARCHAR(64) NOT NULL,
++ to_user VARCHAR(64) NOT NULL,
++ to_domain VARCHAR(64) NOT NULL,
++ event VARCHAR(64) DEFAULT 'presence' NOT NULL,
++ event_id VARCHAR(64),
++ to_tag VARCHAR(64) NOT NULL,
++ from_tag VARCHAR(64) NOT NULL,
++ callid VARCHAR(128) NOT NULL,
++ local_cseq INTEGER NOT NULL,
++ remote_cseq INTEGER NOT NULL,
++ contact VARCHAR(128) NOT NULL,
++ record_route TEXT,
++ expires INTEGER NOT NULL,
++ status INTEGER DEFAULT 2 NOT NULL,
++ reason VARCHAR(64) NOT NULL,
++ version INTEGER DEFAULT 0 NOT NULL,
++ socket_info VARCHAR(64) NOT NULL,
++ local_contact VARCHAR(128) NOT NULL,
++ CONSTRAINT active_watchers_active_watchers_idx UNIQUE (presentity_uri, callid, to_tag, from_tag)
++);
++
++INSERT INTO version (table_name, table_version) values ('watchers','3');
++CREATE TABLE watchers (
++ id INTEGER PRIMARY KEY NOT NULL,
++ presentity_uri VARCHAR(128) NOT NULL,
++ watcher_username VARCHAR(64) NOT NULL,
++ watcher_domain VARCHAR(64) NOT NULL,
++ event VARCHAR(64) DEFAULT 'presence' NOT NULL,
++ status INTEGER NOT NULL,
++ reason VARCHAR(64),
++ inserted_time INTEGER NOT NULL,
++ CONSTRAINT watchers_watcher_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event)
++);
++
++INSERT INTO version (table_name, table_version) values ('xcap','3');
++CREATE TABLE xcap (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) NOT NULL,
++ domain VARCHAR(64) NOT NULL,
++ doc BYTEA NOT NULL,
++ doc_type INTEGER NOT NULL,
++ etag VARCHAR(64) NOT NULL,
++ source INTEGER NOT NULL,
++ doc_uri VARCHAR(128) NOT NULL,
++ port INTEGER NOT NULL,
++ CONSTRAINT xcap_account_doc_type_idx UNIQUE (username, domain, doc_type, doc_uri)
++);
++
++CREATE INDEX xcap_source_idx ON xcap (source);
++
++INSERT INTO version (table_name, table_version) values ('pua','6');
++CREATE TABLE pua (
++ id INTEGER PRIMARY KEY NOT NULL,
++ pres_uri VARCHAR(128) NOT NULL,
++ pres_id VARCHAR(64) NOT NULL,
++ event INTEGER NOT NULL,
++ expires INTEGER NOT NULL,
++ desired_expires INTEGER NOT NULL,
++ flag INTEGER NOT NULL,
++ etag VARCHAR(64) NOT NULL,
++ tuple_id VARCHAR(64),
++ watcher_uri VARCHAR(128) NOT NULL,
++ call_id VARCHAR(128) NOT NULL,
++ to_tag VARCHAR(64) NOT NULL,
++ from_tag VARCHAR(64) NOT NULL,
++ cseq INTEGER NOT NULL,
++ record_route TEXT,
++ contact VARCHAR(128) NOT NULL,
++ remote_contact VARCHAR(128) NOT NULL,
++ version INTEGER NOT NULL,
++ extra_headers TEXT NOT NULL
++);
++
+diff --git a/utils/kamctl/sqlite/purple-create.sql b/utils/kamctl/sqlite/purple-create.sql
+new file mode 100644
+index 0000000..b58c53e
+--- /dev/null
++++ b/utils/kamctl/sqlite/purple-create.sql
+@@ -0,0 +1,9 @@
++INSERT INTO version (table_name, table_version) values ('purplemap','1');
++CREATE TABLE purplemap (
++ id INTEGER PRIMARY KEY NOT NULL,
++ sip_user VARCHAR(128) NOT NULL,
++ ext_user VARCHAR(128) NOT NULL,
++ ext_prot VARCHAR(16) NOT NULL,
++ ext_pass VARCHAR(64)
++);
++
+diff --git a/utils/kamctl/sqlite/registrar-create.sql b/utils/kamctl/sqlite/registrar-create.sql
+new file mode 100644
+index 0000000..68f2adc
+--- /dev/null
++++ b/utils/kamctl/sqlite/registrar-create.sql
+@@ -0,0 +1,22 @@
++INSERT INTO version (table_name, table_version) values ('aliases','1004');
++CREATE TABLE aliases (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT NULL,
++ contact VARCHAR(255) DEFAULT '' NOT NULL,
++ received VARCHAR(128) DEFAULT NULL,
++ path VARCHAR(128) DEFAULT NULL,
++ expires TIMESTAMP WITHOUT TIME ZONE DEFAULT '2020-05-28 21:32:15' NOT NULL,
++ q REAL DEFAULT 1.0 NOT NULL,
++ callid VARCHAR(255) DEFAULT 'Default-Call-ID' NOT NULL,
++ cseq INTEGER DEFAULT 13 NOT NULL,
++ last_modified TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL,
++ flags INTEGER DEFAULT 0 NOT NULL,
++ cflags INTEGER DEFAULT 0 NOT NULL,
++ user_agent VARCHAR(255) DEFAULT '' NOT NULL,
++ socket VARCHAR(64) DEFAULT NULL,
++ methods INTEGER DEFAULT NULL
++);
++
++CREATE INDEX aliases_alias_idx ON aliases (username, domain, contact);
++
+diff --git a/utils/kamctl/sqlite/rls-create.sql b/utils/kamctl/sqlite/rls-create.sql
+new file mode 100644
+index 0000000..b15120d
+--- /dev/null
++++ b/utils/kamctl/sqlite/rls-create.sql
+@@ -0,0 +1,42 @@
++INSERT INTO version (table_name, table_version) values ('rls_presentity','0');
++CREATE TABLE rls_presentity (
++ id INTEGER PRIMARY KEY NOT NULL,
++ rlsubs_did VARCHAR(255) NOT NULL,
++ resource_uri VARCHAR(128) NOT NULL,
++ content_type VARCHAR(64) NOT NULL,
++ presence_state BYTEA NOT NULL,
++ expires INTEGER NOT NULL,
++ updated INTEGER NOT NULL,
++ auth_state INTEGER NOT NULL,
++ reason VARCHAR(64) NOT NULL,
++ CONSTRAINT rls_presentity_rls_presentity_idx UNIQUE (rlsubs_did, resource_uri)
++);
++
++CREATE INDEX rls_presentity_updated_idx ON rls_presentity (updated);
++
++INSERT INTO version (table_name, table_version) values ('rls_watchers','1');
++CREATE TABLE rls_watchers (
++ id INTEGER PRIMARY KEY NOT NULL,
++ presentity_uri VARCHAR(128) NOT NULL,
++ to_user VARCHAR(64) NOT NULL,
++ to_domain VARCHAR(64) NOT NULL,
++ watcher_username VARCHAR(64) NOT NULL,
++ watcher_domain VARCHAR(64) NOT NULL,
++ event VARCHAR(64) DEFAULT 'presence' NOT NULL,
++ event_id VARCHAR(64),
++ to_tag VARCHAR(64) NOT NULL,
++ from_tag VARCHAR(64) NOT NULL,
++ callid VARCHAR(64) NOT NULL,
++ local_cseq INTEGER NOT NULL,
++ remote_cseq INTEGER NOT NULL,
++ contact VARCHAR(64) NOT NULL,
++ record_route TEXT,
++ expires INTEGER NOT NULL,
++ status INTEGER DEFAULT 2 NOT NULL,
++ reason VARCHAR(64) NOT NULL,
++ version INTEGER DEFAULT 0 NOT NULL,
++ socket_info VARCHAR(64) NOT NULL,
++ local_contact VARCHAR(128) NOT NULL,
++ CONSTRAINT rls_watchers_rls_watcher_idx UNIQUE (presentity_uri, callid, to_tag, from_tag)
++);
++
+diff --git a/utils/kamctl/sqlite/siptrace-create.sql b/utils/kamctl/sqlite/siptrace-create.sql
+new file mode 100644
+index 0000000..a784d0b
+--- /dev/null
++++ b/utils/kamctl/sqlite/siptrace-create.sql
+@@ -0,0 +1,20 @@
++INSERT INTO version (table_name, table_version) values ('sip_trace','2');
++CREATE TABLE sip_trace (
++ id INTEGER PRIMARY KEY NOT NULL,
++ time_stamp TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL,
++ callid VARCHAR(255) DEFAULT '' NOT NULL,
++ traced_user VARCHAR(128) DEFAULT '' NOT NULL,
++ msg TEXT NOT NULL,
++ method VARCHAR(50) DEFAULT '' NOT NULL,
++ status VARCHAR(128) DEFAULT '' NOT NULL,
++ fromip VARCHAR(50) DEFAULT '' NOT NULL,
++ toip VARCHAR(50) DEFAULT '' NOT NULL,
++ fromtag VARCHAR(64) DEFAULT '' NOT NULL,
++ direction VARCHAR(4) DEFAULT '' NOT NULL
++);
++
++CREATE INDEX sip_trace_traced_user_idx ON sip_trace (traced_user);
++CREATE INDEX sip_trace_date_idx ON sip_trace (time_stamp);
++CREATE INDEX sip_trace_fromip_idx ON sip_trace (fromip);
++CREATE INDEX sip_trace_callid_idx ON sip_trace (callid);
++
+diff --git a/utils/kamctl/sqlite/speeddial-create.sql b/utils/kamctl/sqlite/speeddial-create.sql
+new file mode 100644
+index 0000000..64e1ae6
+--- /dev/null
++++ b/utils/kamctl/sqlite/speeddial-create.sql
+@@ -0,0 +1,14 @@
++INSERT INTO version (table_name, table_version) values ('speed_dial','2');
++CREATE TABLE speed_dial (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ sd_username VARCHAR(64) DEFAULT '' NOT NULL,
++ sd_domain VARCHAR(64) DEFAULT '' NOT NULL,
++ new_uri VARCHAR(128) DEFAULT '' NOT NULL,
++ fname VARCHAR(64) DEFAULT '' NOT NULL,
++ lname VARCHAR(64) DEFAULT '' NOT NULL,
++ description VARCHAR(64) DEFAULT '' NOT NULL,
++ CONSTRAINT speed_dial_speed_dial_idx UNIQUE (username, domain, sd_domain, sd_username)
++);
++
+diff --git a/utils/kamctl/sqlite/standard-create.sql b/utils/kamctl/sqlite/standard-create.sql
+new file mode 100644
+index 0000000..0add99d
+--- /dev/null
++++ b/utils/kamctl/sqlite/standard-create.sql
+@@ -0,0 +1,5 @@
++CREATE TABLE version (
++ table_name VARCHAR(32) NOT NULL,
++ table_version INTEGER DEFAULT 0 NOT NULL
++);
++
+diff --git a/utils/kamctl/sqlite/uac-create.sql b/utils/kamctl/sqlite/uac-create.sql
+new file mode 100644
+index 0000000..f0cf80d
+--- /dev/null
++++ b/utils/kamctl/sqlite/uac-create.sql
+@@ -0,0 +1,16 @@
++INSERT INTO version (table_name, table_version) values ('uacreg','1');
++CREATE TABLE uacreg (
++ id INTEGER PRIMARY KEY NOT NULL,
++ l_uuid VARCHAR(64) DEFAULT '' NOT NULL,
++ l_username VARCHAR(64) DEFAULT '' NOT NULL,
++ l_domain VARCHAR(128) DEFAULT '' NOT NULL,
++ r_username VARCHAR(64) DEFAULT '' NOT NULL,
++ r_domain VARCHAR(128) DEFAULT '' NOT NULL,
++ realm VARCHAR(64) DEFAULT '' NOT NULL,
++ auth_username VARCHAR(64) DEFAULT '' NOT NULL,
++ auth_password VARCHAR(64) DEFAULT '' NOT NULL,
++ auth_proxy VARCHAR(64) DEFAULT '' NOT NULL,
++ expires INTEGER DEFAULT 0 NOT NULL,
++ CONSTRAINT uacreg_l_uuid_idx UNIQUE (l_uuid)
++);
++
+diff --git a/utils/kamctl/sqlite/uri_db-create.sql b/utils/kamctl/sqlite/uri_db-create.sql
+new file mode 100644
+index 0000000..8e291fc
+--- /dev/null
++++ b/utils/kamctl/sqlite/uri_db-create.sql
+@@ -0,0 +1,10 @@
++INSERT INTO version (table_name, table_version) values ('uri','1');
++CREATE TABLE uri (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ uri_user VARCHAR(64) DEFAULT '' NOT NULL,
++ last_modified TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL,
++ CONSTRAINT uri_account_idx UNIQUE (username, domain, uri_user)
++);
++
+diff --git a/utils/kamctl/sqlite/userblacklist-create.sql b/utils/kamctl/sqlite/userblacklist-create.sql
+new file mode 100644
+index 0000000..34d9eb1
+--- /dev/null
++++ b/utils/kamctl/sqlite/userblacklist-create.sql
+@@ -0,0 +1,21 @@
++INSERT INTO version (table_name, table_version) values ('userblacklist','1');
++CREATE TABLE userblacklist (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT '' NOT NULL,
++ prefix VARCHAR(64) DEFAULT '' NOT NULL,
++ whitelist SMALLINT DEFAULT 0 NOT NULL
++);
++
++CREATE INDEX userblacklist_userblacklist_idx ON userblacklist (username, domain, prefix);
++
++INSERT INTO version (table_name, table_version) values ('globalblacklist','1');
++CREATE TABLE globalblacklist (
++ id INTEGER PRIMARY KEY NOT NULL,
++ prefix VARCHAR(64) DEFAULT '' NOT NULL,
++ whitelist SMALLINT DEFAULT 0 NOT NULL,
++ description VARCHAR(255) DEFAULT NULL
++);
++
++CREATE INDEX globalblacklist_globalblacklist_idx ON globalblacklist (prefix);
++
+diff --git a/utils/kamctl/sqlite/usrloc-create.sql b/utils/kamctl/sqlite/usrloc-create.sql
+new file mode 100644
+index 0000000..6eb7d07
+--- /dev/null
++++ b/utils/kamctl/sqlite/usrloc-create.sql
+@@ -0,0 +1,22 @@
++INSERT INTO version (table_name, table_version) values ('location','1004');
++CREATE TABLE location (
++ id INTEGER PRIMARY KEY NOT NULL,
++ username VARCHAR(64) DEFAULT '' NOT NULL,
++ domain VARCHAR(64) DEFAULT NULL,
++ contact VARCHAR(255) DEFAULT '' NOT NULL,
++ received VARCHAR(128) DEFAULT NULL,
++ path VARCHAR(128) DEFAULT NULL,
++ expires TIMESTAMP WITHOUT TIME ZONE DEFAULT '2020-05-28 21:32:15' NOT NULL,
++ q REAL DEFAULT 1.0 NOT NULL,
++ callid VARCHAR(255) DEFAULT 'Default-Call-ID' NOT NULL,
++ cseq INTEGER DEFAULT 13 NOT NULL,
++ last_modified TIMESTAMP WITHOUT TIME ZONE DEFAULT '1900-01-01 00:00:01' NOT NULL,
++ flags INTEGER DEFAULT 0 NOT NULL,
++ cflags INTEGER DEFAULT 0 NOT NULL,
++ user_agent VARCHAR(255) DEFAULT '' NOT NULL,
++ socket VARCHAR(64) DEFAULT NULL,
++ methods INTEGER DEFAULT NULL
++);
++
++CREATE INDEX location_account_contact_idx ON location (username, domain, contact);
++
+--
+1.7.4.5
+
diff --git a/main/kamailio/APKBUILD b/main/kamailio/APKBUILD
new file mode 100644
index 0000000000..9933495068
--- /dev/null
+++ b/main/kamailio/APKBUILD
@@ -0,0 +1,187 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=kamailio
+pkgver=3.1.4
+pkgrel=1
+pkgdesc="Open Source SIP Server"
+url="http://www.kamailio.org/"
+pkgusers="kamailio"
+pkggroups="kamailio"
+arch="all"
+license="GPL"
+depends=
+arch=all
+makedepends="bison flex expat-dev postgresql-dev pcre-dev mysql-dev
+ libxml2-dev curl-dev unixodbc-dev confuse-dev ncurses-dev sqlite-dev"
+install="$pkgname.pre-install $pkgname.pre-upgrade"
+subpackages="$pkgname-doc $pkgname-postgres $pkgname-presence $pkgname-pcre
+ $pkgname-mediaproxy $pkgname-unixodbc $pkgname-mysql $pkgname-sqlite"
+source="http://www.kamailio.org/pub/kamailio/$pkgver/src/kamailio-${pkgver}_src.tar.gz
+ kamailio.cfg
+ kamailio.initd
+ kamailio-3.1-backslash.patch
+ sqlite.patch
+ 0001-utils-add-sqlite-support-to-kamctl-kamdbctl.patch
+ 0001-utils-Install-the-sqlite-scripts.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+
+_default="carrierroute xmlrpc tm"
+_presence="presence presence_xml presence_mwi pua pua_bla pua_mi pua_usrloc pua_xmpp rls xcap_client presence_dialoginfo pua_dialoginfo"
+_pcre="dialplan lcr regex"
+_postgres="db_postgres"
+_mysql="db_mysql"
+_mediaproxy="mediaproxy"
+_odbc="db_unixodbc"
+# Makefile does not handle newline
+_modules="$_default $_postgres $_mediaproxy $_odbc $_presence $_mysql $_pcre"
+
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+
+ sed -i \
+ -e "s:-O9 -funroll-loops:$CFLAGS:g" \
+ Makefile.defs \
+ || return 1
+
+# -e 's:^cfg-target.*:cfg-target = $(cfg-dir):' \
+# -e 's:^cfg-prefix.*:cfg-prefix = $(basedir):' \
+
+ cd utils/kamctl/
+ sed -i -e 's:/var/run/kamailio.pid:/var/run/kamailio/kamailio.pid:g' \
+ kamctl.base kamctlrc || return 1
+ # we actually dont need bash
+ sed -i -e 's:/bin/bash:/bin/sh:' kamctl kamdbctl \
+ || return 1
+ # Set email_address field as not required field (could be null)
+ cd dbtext/kamailio
+ sed -i -e 's:email_address(string):email_address(string,null):' subscriber \
+ || return 1
+
+}
+
+build() {
+ cd "$_builddir"
+ make FLAVOUR=kamailio \
+ PREFIX=/usr \
+ cfg_target=/etc/kamailio/ \
+ include_modules="$_modules" \
+ LIBDIR=lib \
+ DESTDIR="$pkgdir" \
+ cfg_prefix="$pkgdir" \
+ cfg
+ make all || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 install || return 1
+
+ # move default config to -doc package and use our own default config
+
+ mv "$pkgdir"/etc/kamailio/kamailio.cfg \
+ "$pkgdir"/usr/share/doc/kamailio/
+ install -m644 -D "$srcdir"/kamailio.cfg \
+ "$pkgdir"/etc/kamailio/kamailio.cfg
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -d -o kamailio "$pkgdir"/var/run/kamailio
+}
+
+_mv_mod() {
+ local moddir=usr/lib/kamailio/modules i=
+ mkdir -p "$subpkgdir"/$moddir
+ for i in $@; do
+ mv "$pkgdir"/$moddir/$i.so "$subpkgdir"/$moddir/ || return 1
+ done
+}
+
+_mv_mod_k() {
+ local moddir=usr/lib/kamailio/modules_k i=
+ mkdir -p "$subpkgdir"/$moddir
+ for i in $@; do
+ mv "$pkgdir"/$moddir/$i.so "$subpkgdir"/$moddir/ || return 1
+ done
+}
+
+
+mysql() {
+ pkgdesc="MySQL support for kamailio"
+ depends="kamailio mysql-client"
+ replaces="kamailio"
+ _mv_mod db_mysql
+ mkdir -p "$subpkgdir"/usr/share/kamailio \
+ "$subpkgdir"/usr/lib/kamailio/kamctl
+ mv "$pkgdir"/usr/share/kamailio/mysql \
+ "$subpkgdir"/usr/share/kamailio/ || return 1
+ mv "$pkgdir"/usr/lib/kamailio/kamctl/*.mysql \
+ "$subpkgdir"/usr/lib/kamailio/kamctl/ || return 1
+}
+
+postgres() {
+ pkgdesc="PostgreSQL support for kamailio"
+ depends="kamailio postgresql-client"
+ replaces="kamailio"
+ _mv_mod db_postgres
+ mkdir -p "$subpkgdir"/usr/share/kamailio \
+ "$subpkgdir"/usr/lib/kamailio/kamctl
+ mv "$pkgdir"/usr/share/kamailio/postgres \
+ "$subpkgdir"/usr/share/kamailio/
+ mv "$pkgdir"/usr/lib/kamailio/kamctl/*.pgsql \
+ "$subpkgdir"/usr/lib/kamailio/kamctl/ || return 1
+}
+
+sqlite() {
+ pkgdesc="Sqlite support for kamailio"
+ depends="kamailio sqlite"
+ replaces="kamailio"
+ _mv_mod_k db_sqlite || return 1
+ mkdir -p "$subpkgdir"/usr/share/kamailio \
+ "$subpkgdir"/usr/lib/kamailio/kamctl
+ mv "$pkgdir"/usr/share/kamailio/sqlite \
+ "$subpkgdir"/usr/share/kamailio/ || return 1
+ mv "$pkgdir"/usr/lib/kamailio/kamctl/*.sqlite \
+ "$subpkgdir"/usr/lib/kamailio/kamctl/ || return 1
+}
+
+pcre() {
+ pkgdesc="Regular expressions support for kamailio"
+ _mv_mod dialplan lcr
+ _mv_mod_k regex
+}
+
+presence() {
+ pkgdesc="Presence support for kamailio"
+ _mv_mod_k $_presence
+}
+
+mediaproxy() {
+ pkgdesc="Mediaproxy support for kamailio"
+ depends="kamailio"
+ _mv_mod $_mediaproxy
+}
+
+unixodbc() {
+ pkgdesc="UnixODBC support for kamailio"
+ depends="kamailio"
+ _mv_mod_k $_odbc
+}
+
+md5sums="15124e1f09108b63c6929ca97cdbce9a kamailio-3.1.4_src.tar.gz
+a3c959ec568c43a905710e7d25cd8c25 kamailio.cfg
+c0dc4e13d9e57feb99f016d3ee443c0b kamailio.initd
+8454687f047f703c5cb443db3a0003a8 kamailio-3.1-backslash.patch
+199df21eaa4856dcacdcc438f72765f1 sqlite.patch
+9611a1246bc522cbfa5d8d99b3a55ac8 0001-utils-add-sqlite-support-to-kamctl-kamdbctl.patch
+8751c968e57d7c1bd7342d83d5a8d48d 0001-utils-Install-the-sqlite-scripts.patch"
diff --git a/main/kamailio/kamailio-3.1-backslash.patch b/main/kamailio/kamailio-3.1-backslash.patch
new file mode 100644
index 0000000000..85e0f3fbf0
--- /dev/null
+++ b/main/kamailio/kamailio-3.1-backslash.patch
@@ -0,0 +1,44 @@
+diff --git a/utils/kamctl/kamdbctl.base b/utils/kamctl/kamdbctl.base
+index acc7d4a..3a50270 100644
+--- a/utils/kamctl/kamdbctl.base
++++ b/utils/kamctl/kamdbctl.base
+@@ -32,14 +32,14 @@ INSTALL_PRESENCE_TABLES=${INSTALL_PRESENCE_TABLES:-ask}
+
+ # Used by dbtext and db_berkeley to define tables to be created, used by
+ # postgres to do the grants
+-STANDARD_TABLES=${STANDARD_TABLES:-version acc dbaliases domain grp
+- uri speed_dial lcr_gw lcr_rule lcr_rule_target pdt subscriber
+- location re_grp trusted address missed_calls usr_preferences
++STANDARD_TABLES=${STANDARD_TABLES:-version acc dbaliases domain grp \
++ uri speed_dial lcr_gw lcr_rule lcr_rule_target pdt subscriber \
++ location re_grp trusted address missed_calls usr_preferences \
+ aliases silo dialog dispatcher dialplan}
+-EXTRA_TABLES=${EXTRA_TABLES:-imc_members imc_rooms cpl sip_trace domainpolicy
+- carrierroute carrier_name domain_name carrierfailureroute userblacklist
++EXTRA_TABLES=${EXTRA_TABLES:-imc_members imc_rooms cpl sip_trace domainpolicy \
++ carrierroute carrier_name domain_name carrierfailureroute userblacklist \
+ globalblacklist htable purplemap uacreg}
+-PRESENCE_TABLES=${PRESENCE_TABLES:-presentity active_watchers watchers xcap
++PRESENCE_TABLES=${PRESENCE_TABLES:-presentity active_watchers watchers xcap \
+ pua rls_presentity rls_watchers}
+
+ # SQL definitions
+@@ -62,11 +62,11 @@ GREP=${GREP:-grep}
+ SED=${SED:-sed}
+
+ # define what modules should be installed
+-STANDARD_MODULES=${STANDARD_MODULES:-standard acc lcr domain group permissions
+- registrar usrloc msilo alias_db uri_db
+- speeddial avpops auth_db pdt dialog dispatcher
++STANDARD_MODULES=${STANDARD_MODULES:-standard acc lcr domain group permissions \
++ registrar usrloc msilo alias_db uri_db \
++ speeddial avpops auth_db pdt dialog dispatcher \
+ dialplan}
+-EXTRA_MODULES=${EXTRA_MODULES:-imc cpl siptrace domainpolicy carrierroute
++EXTRA_MODULES=${EXTRA_MODULES:-imc cpl siptrace domainpolicy carrierroute \
+ userblacklist htable purple uac}
+
+ ############################################################
+--
+1.7.1
+
diff --git a/main/kamailio/kamailio.cfg b/main/kamailio/kamailio.cfg
new file mode 100644
index 0000000000..1558cce9ca
--- /dev/null
+++ b/main/kamailio/kamailio.cfg
@@ -0,0 +1,107 @@
+# Sample Kamailio Configuration
+# 23 June 2010 - For Alpine Linux
+# Accepts all registrations; routes calls to any registered AOR
+
+#--------------------------------------------------------
+# Section 1: Global Definitions
+#--------------------------------------------------------
+debug = 2
+fork = yes
+log_stderror = no
+# listen = 0.0.0.0
+port = 5060
+children = 4
+
+dns = no
+rev_dns = no
+
+mpath = "/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/"
+
+#--------------------------------------------------------
+# Section 2: Modules
+#--------------------------------------------------------
+
+loadmodule "tm.so"
+loadmodule "sl.so"
+loadmodule "tmx.so"
+loadmodule "rr.so"
+loadmodule "maxfwd.so"
+loadmodule "usrloc.so"
+loadmodule "registrar.so"
+loadmodule "mi_fifo.so"
+loadmodule "pv.so"
+loadmodule "xlog.so"
+
+#--------------------------------------------------------
+# Section 3: Module Configuration
+#--------------------------------------------------------
+
+modparam ( "usrloc", "db_mode", 0 )
+modparam ( "rr", "enable_full_lr", 1 )
+modparam ( "mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+#--------------------------------------------------------
+# Section 4: Main Route Block
+#--------------------------------------------------------
+
+route
+ {
+ # Uncomment next line if you want to see
+ # each incoming message
+ xlog( "L_INFO", "$rm: $fu -> $ru" );
+
+ if (!mf_process_maxfwd_header("10"))
+ {
+ sl_send_reply("483", "Too Many Hops");
+ return;
+ }
+
+ if (msg:len > 4096)
+ {
+ sl_send_reply("513", "Message too big" );
+ return;
+ }
+
+ if (method == "REGISTER" )
+ {
+ route(REGISTER);
+ return;
+ }
+
+ loose_route();
+
+ if (!lookup("location")) {
+ sl_send_reply("404", "User Not Found");
+ return;
+ }
+
+ route(RELAY);
+
+}
+#--------------------------------------------------------
+# Section 5: Secondary Route Blocks
+#--------------------------------------------------------
+
+# - Default message handler
+route[RELAY] {
+ if (!t_relay()) {
+ sl_reply_error();
+ }
+}
+
+#- Registration Request
+route[REGISTER] {
+ if (!save("location")) {
+ sl_reply_error();
+ }
+}
+
+#--------------------------------------------------------
+# Section 6: Reply Route Block
+#--------------------------------------------------------
+
+
+#--------------------------------------------------------
+# Section 7: Failure Route Block
+#--------------------------------------------------------
+
diff --git a/main/kamailio/kamailio.initd b/main/kamailio/kamailio.initd
new file mode 100644
index 0000000000..98ba6c761d
--- /dev/null
+++ b/main/kamailio/kamailio.initd
@@ -0,0 +1,34 @@
+#!/sbin/runscript
+
+daemon=/usr/sbin/kamailio
+pidfile=/var/run/kamailio/kamailio.pid
+
+opts="reload"
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting Kamailio"
+ start-stop-daemon --start --quiet --pidfile $pidfile --exec $daemon \
+ -- \
+ -u ${KAMAILIO_USER:-kamailio} \
+ -g ${KAMAILIO_GROUP:-kamailio} \
+ -P $pidfile \
+ ${KAMAILIO_OPTS:-}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping Kamailio"
+ start-stop-daemon --stop --quiet --pidfile $pidfile
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading Kamailio"
+ echo mi_dg dp_reload | sercmd 2>/dev/null
+ eend $?
+}
diff --git a/main/kamailio/kamailio.pre-install b/main/kamailio/kamailio.pre-install
new file mode 100644
index 0000000000..84b28849aa
--- /dev/null
+++ b/main/kamailio/kamailio.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+addgroup kamailio 2>/dev/null
+adduser -H -h /var/empty -s /bin/false -D -G kamailio kamailio 2>/dev/null
+
+exit 0
diff --git a/main/kamailio/kamailio.pre-upgrade b/main/kamailio/kamailio.pre-upgrade
new file mode 120000
index 0000000000..d7cdaa807a
--- /dev/null
+++ b/main/kamailio/kamailio.pre-upgrade
@@ -0,0 +1 @@
+kamailio.pre-install \ No newline at end of file
diff --git a/main/kamailio/sqlite.patch b/main/kamailio/sqlite.patch
new file mode 100644
index 0000000000..38cae2ec90
--- /dev/null
+++ b/main/kamailio/sqlite.patch
@@ -0,0 +1,712 @@
+Index: kamailio-3.1.1/modules_k/db_sqlite/Makefile
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ kamailio-3.1.1/modules_k/db_sqlite/Makefile 2011-01-05 14:19:03.000000000 +0200
+@@ -0,0 +1,15 @@
++# $Id$
++#
++# WARNING: do not run this directly, it should be run by the master Makefile
++
++include ../../Makefile.defs
++auto_gen=
++NAME=db_sqlite.so
++
++LIBS +=-lsqlite3
++
++DEFS+=-DOPENSER_MOD_INTERFACE
++
++SERLIBPATH=../../lib
++SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
++include ../../Makefile.modules
+Index: kamailio-3.1.1/modules_k/db_sqlite/db_sqlite.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ kamailio-3.1.1/modules_k/db_sqlite/db_sqlite.c 2011-01-05 14:21:13.000000000 +0200
+@@ -0,0 +1,90 @@
++/*
++ * $Id$
++ *
++ * SQlite module interface
++ *
++ * Copyright (C) 2010 Timo Teräs
++ *
++ * This file is part of Kamailio, a free SIP server.
++ *
++ * Kamailio 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
++ *
++ * Kamailio 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 <sys/time.h>
++#include <sqlite3.h>
++
++#include "../../sr_module.h"
++#include "../../lib/srdb1/db.h"
++#include "dbase.h"
++
++MODULE_VERSION
++
++static int sqlite_bind_api(db_func_t *dbb)
++{
++ if(dbb==NULL)
++ return -1;
++
++ memset(dbb, 0, sizeof(db_func_t));
++
++ dbb->use_table = db_sqlite_use_table;
++ dbb->init = db_sqlite_init;
++ dbb->close = db_sqlite_close;
++ dbb->free_result = db_sqlite_free_result;
++ dbb->query = db_sqlite_query;
++ dbb->insert = db_sqlite_insert;
++ dbb->delete = db_sqlite_delete;
++ dbb->update = db_sqlite_update;
++ dbb->raw_query = db_sqlite_raw_query;
++
++ return 0;
++}
++
++static cmd_export_t cmds[] = {
++ {"db_bind_api", (cmd_function)sqlite_bind_api, 0, 0, 0, 0},
++ {0, 0, 0, 0, 0, 0}
++};
++
++static int sqlite_mod_init(void)
++{
++ sqlite3_initialize();
++
++ LM_INFO("SQlite library version %s (compiled using %s)\n",
++ sqlite3_libversion(),
++ SQLITE_VERSION);
++ return 0;
++}
++
++
++static void sqlite_mod_destroy(void)
++{
++ LM_INFO("SQlite terminate\n");
++
++ sqlite3_shutdown();
++}
++
++struct module_exports exports = {
++ "db_sqlite",
++ DEFAULT_DLFLAGS, /* dlopen flags */
++ cmds, /* module commands */
++ 0, /* module parameters */
++ 0, /* exported statistics */
++ 0, /* exported MI functions */
++ 0, /* exported pseudo-variables */
++ 0, /* extra processes */
++ sqlite_mod_init, /* module initialization function */
++ 0, /* response function*/
++ sqlite_mod_destroy, /* destroy function */
++ 0 /* per-child init function */
++};
+Index: kamailio-3.1.1/modules_k/db_sqlite/dbase.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ kamailio-3.1.1/modules_k/db_sqlite/dbase.c 2011-01-05 14:20:47.000000000 +0200
+@@ -0,0 +1,515 @@
++/*
++ * $Id$
++ *
++ * SQlite module core functions
++ *
++ * Copyright (C) 2010 Timo Teräs
++ *
++ * This file is part of Kamailio, a free SIP server.
++ *
++ * Kamailio 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
++ *
++ * Kamailio 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 "../../mem/mem.h"
++#include "../../dprint.h"
++#include "../../lib/srdb1/db_pool.h"
++#include "../../lib/srdb1/db_ut.h"
++#include "../../lib/srdb1/db_res.h"
++#include "../../lib/srdb1/db_query.h"
++#include "dbase.h"
++
++static time_t sqlite_to_timet(double rT)
++{
++ return 86400.0*(rT - 2440587.5) + 0.5;
++}
++
++static double timet_to_sqlite(time_t t)
++{
++ return ((((double) t) - 0.5) / 86400.0) + 2440587.5;
++}
++
++/*
++ * Initialize database module
++ * No function should be called before this
++ */
++
++static struct sqlite_connection * db_sqlite_new_connection(const struct db_id* id)
++{
++ struct sqlite_connection *con;
++ int rc;
++
++ con = pkg_malloc(sizeof(*con));
++ if (!con) {
++ LM_ERR("failed to allocate driver connection\n");
++ return NULL;
++ }
++
++ memset(con, 0, sizeof(*con));
++ con->hdr.ref = 1;
++ con->hdr.id = (struct db_id*) id; /* set here - freed on error */
++
++ rc = sqlite3_open_v2(id->database, &con->conn,
++ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
++ if (rc != SQLITE_OK) {
++ pkg_free(con);
++ LM_ERR("failed to open sqlite database '%s'\n", id->database);
++ return NULL;
++ }
++
++ return con;
++}
++
++db1_con_t* db_sqlite_init(const str* _url)
++{
++ return db_do_init(_url, (void *) db_sqlite_new_connection);
++}
++
++
++/*
++ * Shut down database module
++ * No function should be called after this
++ */
++
++static void db_sqlite_free_connection(struct sqlite_connection* con)
++{
++ if (!con) return;
++
++ sqlite3_close(con->conn);
++ free_db_id(con->hdr.id);
++ pkg_free(con);
++}
++
++void db_sqlite_close(db1_con_t* _h)
++{
++ db_do_close(_h, db_sqlite_free_connection);
++}
++
++/*
++ * Release a result set from memory
++ */
++int db_sqlite_free_result(db1_con_t* _h, db1_res_t* _r)
++{
++ if (!_h || !_r) {
++ LM_ERR("invalid parameter value\n");
++ return -1;
++ }
++
++ if (db_free_result(_r) < 0)
++ {
++ LM_ERR("failed to free result structure\n");
++ return -1;
++ }
++ return 0;
++}
++
++/*
++ * Store name of table that will be used by
++ * subsequent database functions
++ */
++int db_sqlite_use_table(db1_con_t* _h, const str* _t)
++{
++ return db_use_table(_h, _t);
++}
++
++/*
++ * Reset query context
++ */
++static void db_sqlite_cleanup_query(const db1_con_t* _c)
++{
++ struct sqlite_connection *conn = CON_SQLITE(_c);
++ int rc;
++
++ if (conn->stmt != NULL) {
++ rc = sqlite3_finalize(conn->stmt);
++ if (rc != SQLITE_OK)
++ LM_ERR("finalize failed: %s\n",
++ sqlite3_errmsg(conn->conn));
++ }
++
++ conn->stmt = NULL;
++ conn->bindpos = 0;
++}
++
++/*
++ * Convert value to sql-string as db bind index
++ */
++static int db_sqlite_val2str(const db1_con_t* _c, const db_val_t* _v, char* _s, int* _len)
++{
++ struct sqlite_connection *conn;
++ int ret;
++
++ if (!_c || !_v || !_s || !_len || *_len <= 0) {
++ LM_ERR("invalid parameter value\n");
++ return -1;
++ }
++
++ conn = CON_SQLITE(_c);
++ if (conn->bindpos >= DB_SQLITE_MAX_BINDS) {
++ LM_ERR("too many bindings, recompile with larger DB_SQLITE_MAX_BINDS\n");
++ return -2;
++ }
++
++ conn->bindarg[conn->bindpos] = _v;
++ ret = snprintf(_s, *_len, "?%u", ++conn->bindpos);
++ if ((unsigned)ret >= (unsigned) *_len)
++ return -11;
++
++ *_len = ret;
++ return 0;
++}
++
++/*
++ * Send an SQL query to the server
++ */
++static int db_sqlite_submit_query(const db1_con_t* _h, const str* _s)
++{
++ struct sqlite_connection *conn = CON_SQLITE(_h);
++ sqlite3_stmt *stmt;
++ const db_val_t *val;
++ int rc, i;
++
++ LM_DBG("submit_query: %.*s\n", _s->len, _s->s);
++
++ rc = sqlite3_prepare_v2(conn->conn, _s->s, _s->len, &stmt, NULL);
++ if (rc != SQLITE_OK) {
++ LM_ERR("failed to prepare statement: %s\n",
++ sqlite3_errmsg(conn->conn));
++ return -1;
++ }
++ conn->stmt = stmt;
++
++ for (i = 1; i <= conn->bindpos; i++) {
++ val = conn->bindarg[i-1];
++ if (VAL_NULL(val)) {
++ rc = sqlite3_bind_null(stmt, i);
++ } else switch (VAL_TYPE(val)) {
++ case DB1_INT:
++ rc = sqlite3_bind_int(stmt, i, VAL_INT(val));
++ break;
++ case DB1_BIGINT:
++ rc = sqlite3_bind_int64(stmt, i, VAL_BIGINT(val));
++ break;
++ case DB1_DOUBLE:
++ rc = sqlite3_bind_double(stmt, i, VAL_DOUBLE(val));
++ break;
++ case DB1_STRING:
++ rc = sqlite3_bind_text(stmt, i,
++ VAL_STRING(val), -1, NULL);
++ break;
++ case DB1_STR:
++ rc = sqlite3_bind_text(stmt, i,
++ VAL_STR(val).s, VAL_STR(val).len, NULL);
++ break;
++ case DB1_DATETIME:
++ rc = sqlite3_bind_double(stmt, i, timet_to_sqlite(VAL_TIME(val)));
++ break;
++ case DB1_BLOB:
++ rc = sqlite3_bind_blob(stmt, i,
++ VAL_BLOB(val).s, VAL_BLOB(val).len,
++ NULL);
++ break;
++ case DB1_BITMAP:
++ rc = sqlite3_bind_int(stmt, i, VAL_BITMAP(val));
++ break;
++ default:
++ LM_ERR("unknown bind value type %d\n", VAL_TYPE(val));
++ return -1;
++ }
++ if (rc != SQLITE_OK) {
++ LM_ERR("Parameter bind failed: %s\n",
++ sqlite3_errmsg(conn->conn));
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
++static int decltype_to_dbtype(const char *decltype)
++{
++ /* SQlite3 has dynamic typing. It does not store the actual
++ * exact type, instead it uses 'affinity' depending on the
++ * value. We have to go through the declaration types to see
++ * what to return. */
++ if (strstr(decltype, "INT") != NULL ||
++ strncasecmp(decltype, "SERIAL", 6) == 0)
++ return DB1_INT;
++ if (strstr(decltype, "CHAR") != NULL)
++ return DB1_STRING;
++ if (strstr(decltype, "TEXT") != NULL)
++ return DB1_STR;
++ if (strstr(decltype, "REAL") != NULL ||
++ strstr(decltype, "FLOA") != NULL ||
++ strstr(decltype, "DOUB") != NULL)
++ return DB1_DOUBLE;
++ if (strstr(decltype, "BLOB") != NULL)
++ return DB1_BLOB;
++ if (strncasecmp(decltype, "TIME", 4) == 0 ||
++ strncasecmp(decltype, "DATE", 4) == 0)
++ return DB1_DATETIME;
++
++ LM_ERR("sqlite decltype '%s' not recognized, defaulting to int",
++ decltype);
++ return DB1_INT;
++}
++
++static str* str_dup(const char *_s)
++{
++ str *s;
++ int len = strlen(_s);
++
++ s = (str*) pkg_malloc(sizeof(str)+len+1);
++ s->len = len;
++ s->s = ((char*)s) + sizeof(str);
++ memcpy(s->s, _s, len);
++ s->s[len] = '\0';
++
++ return s;
++}
++
++static void str_assign(str* s, const char *_s, int len)
++{
++ s->s = (char *) pkg_malloc(len + 1);
++ s->len = len;
++ memcpy(s->s, _s, len);
++ s->s[len] = 0;
++}
++
++/*
++ * Read database answer and fill the structure
++ */
++int db_sqlite_store_result(const db1_con_t* _h, db1_res_t** _r)
++{
++ struct sqlite_connection *conn = CON_SQLITE(_h);
++ db1_res_t *res;
++ int i, rc, num_rows = 0, num_alloc = 0;
++ db_row_t *rows = NULL, *row;
++ db_val_t *val;
++
++ res = db_new_result();
++ if (res == NULL)
++ goto no_mem;
++
++ while (1) {
++ rc = sqlite3_step(conn->stmt);
++ if (rc == SQLITE_DONE) {
++ *_r = res;
++ return 0;
++ }
++ if (rc != SQLITE_ROW) {
++ LM_INFO("sqlite3_step failed: %s\n", sqlite3_errmsg(conn->conn));
++ goto err;
++ }
++ if (num_rows == 0) {
++ /* get column types */
++ rc = sqlite3_column_count(conn->stmt);
++ if (db_allocate_columns(res, rc) != 0)
++ goto err;
++ RES_COL_N(res) = rc;
++
++ for (i = 0; i < RES_COL_N(res); i++) {
++ RES_NAMES(res)[i] = str_dup(sqlite3_column_name(conn->stmt, i));
++ RES_TYPES(res)[i] = decltype_to_dbtype(sqlite3_column_decltype(conn->stmt, i));
++ }
++ }
++ if (num_rows >= num_alloc) {
++ if (num_alloc)
++ num_alloc *= 2;
++ else
++ num_alloc = 8;
++ rows = pkg_realloc(rows, sizeof(db_row_t) * num_alloc);
++ if (rows == NULL)
++ goto no_mem;
++ RES_ROWS(res) = rows;
++ }
++
++ row = &RES_ROWS(res)[num_rows];
++ num_rows++;
++ RES_ROW_N(res) = num_rows; /* rows in this result set */
++ RES_NUM_ROWS(res) = num_rows; /* rows in total */
++
++ if (db_allocate_row(res, row) != 0)
++ goto no_mem;
++
++ for (i = 0, val = ROW_VALUES(row); i < RES_COL_N(res); i++, val++) {
++ VAL_TYPE(val) = RES_TYPES(res)[i];
++ VAL_NULL(val) = 0;
++ VAL_FREE(val) = 0;
++ if (sqlite3_column_type(conn->stmt, i) == SQLITE_NULL) {
++ VAL_NULL(val) = 1;
++ } else switch (VAL_TYPE(val)) {
++ case DB1_INT:
++ VAL_INT(val) = sqlite3_column_int(conn->stmt, i);
++ break;
++ case DB1_BIGINT:
++ VAL_BIGINT(val) = sqlite3_column_int64(conn->stmt, i);
++ break;
++ case DB1_STRING:
++ /* first field of struct str* is the char* so we can just
++ * do whatever DB1_STR case does */
++ case DB1_STR:
++ str_assign(&VAL_STR(val),
++ (const char*) sqlite3_column_text(conn->stmt, i),
++ sqlite3_column_bytes(conn->stmt, i));
++ VAL_FREE(val) = 1;
++ break;
++ case DB1_DOUBLE:
++ VAL_DOUBLE(val) = sqlite3_column_double(conn->stmt, i);
++ break;
++ case DB1_DATETIME:
++ VAL_TIME(val) = sqlite_to_timet(sqlite3_column_double(conn->stmt, i));
++ break;
++ case DB1_BLOB:
++ str_assign(&VAL_BLOB(val),
++ (const char*) sqlite3_column_blob(conn->stmt, i),
++ sqlite3_column_bytes(conn->stmt, i));
++ VAL_FREE(val) = 1;
++ break;
++ default:
++ LM_ERR("unhandled db-type\n");
++ goto err;
++ }
++ }
++ }
++
++no_mem:
++ LM_ERR("no private memory left\n");
++err:
++ if (res)
++ db_free_result(res);
++ return -1;
++}
++
++/*
++ * Query table for specified rows
++ * _h: structure representing database connection
++ * _k: key names
++ * _op: operators
++ * _v: values of the keys that must match
++ * _c: column names to return
++ * _n: number of key=values pairs to compare
++ * _nc: number of columns to return
++ * _o: order by the specified column
++ */
++int db_sqlite_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
++ const db_val_t* _v, const db_key_t* _c, int _n, int _nc,
++ const db_key_t _o, db1_res_t** _r)
++{
++ int rc;
++
++ rc = db_do_query(_h, _k, _op, _v, _c, _n, _nc, _o, _r,
++ db_sqlite_val2str,
++ db_sqlite_submit_query,
++ db_sqlite_store_result);
++ db_sqlite_cleanup_query(_h);
++
++ return rc;
++}
++
++static int db_sqlite_commit(const db1_con_t* _h)
++{
++ struct sqlite_connection *conn = CON_SQLITE(_h);
++ int rc;
++
++ rc = sqlite3_step(conn->stmt);
++ if (rc != SQLITE_DONE && rc != SQLITE_OK) {
++ LM_ERR("sqlite commit failed: %s\n",
++ sqlite3_errmsg(conn->conn));
++ return -1;
++ }
++
++ return 0;
++}
++
++/*
++ * Insert a row into specified table
++ * _h: structure representing database connection
++ * _k: key names
++ * _v: values of the keys
++ * _n: number of key=value pairs
++ */
++int db_sqlite_insert(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
++ int _n)
++{
++ int rc = -1;
++
++ rc = db_do_insert(_h, _k, _v, _n,
++ db_sqlite_val2str,
++ db_sqlite_submit_query);
++ if (rc == 0)
++ rc = db_sqlite_commit(_h);
++ db_sqlite_cleanup_query(_h);
++
++ return rc;
++}
++
++
++/*
++ * Delete a row from the specified table
++ * _h: structure representing database connection
++ * _k: key names
++ * _o: operators
++ * _v: values of the keys that must match
++ * _n: number of key=value pairs
++ */
++int db_sqlite_delete(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
++ const db_val_t* _v, int _n)
++{
++ int rc;
++
++ rc = db_do_delete(_h, _k, _o, _v, _n,
++ db_sqlite_val2str,
++ db_sqlite_submit_query);
++ if (rc == 0)
++ rc = db_sqlite_commit(_h);
++ db_sqlite_cleanup_query(_h);
++
++ return rc;
++}
++
++
++/*
++ * Update some rows in the specified table
++ * _h: structure representing database connection
++ * _k: key names
++ * _o: operators
++ * _v: values of the keys that must match
++ * _uk: updated columns
++ * _uv: updated values of the columns
++ * _n: number of key=value pairs
++ * _un: number of columns to update
++ */
++int db_sqlite_update(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
++ const db_val_t* _v, const db_key_t* _uk, const db_val_t* _uv,
++ int _n, int _un)
++{
++ int rc;
++
++ rc = db_do_update(_h, _k, _o, _v, _uk, _uv, _n, _un,
++ db_sqlite_val2str,
++ db_sqlite_submit_query);
++ if (rc == 0)
++ rc = db_sqlite_commit(_h);
++ db_sqlite_cleanup_query(_h);
++
++ return rc;
++}
++
++int db_sqlite_raw_query(const db1_con_t* _h, const str* _s, db1_res_t** _r)
++{
++ return db_do_raw_query(_h, _s, _r,
++ db_sqlite_submit_query,
++ db_sqlite_store_result);
++}
+Index: kamailio-3.1.1/modules_k/db_sqlite/dbase.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ kamailio-3.1.1/modules_k/db_sqlite/dbase.h 2011-01-05 14:20:47.000000000 +0200
+@@ -0,0 +1,72 @@
++/*
++ * $Id$
++ *
++ * SQlite module core functions
++ *
++ * Copyright (C) 2010 Timo Teräs
++ *
++ * This file is part of Kamailio, a free SIP server.
++ *
++ * Kamailio 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
++ *
++ * Kamailio 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
++ */
++
++
++#ifndef DBASE_H
++#define DBASE_H
++
++#include <sqlite3.h>
++
++#include "../../lib/srdb1/db_pool.h"
++#include "../../lib/srdb1/db_con.h"
++#include "../../lib/srdb1/db_res.h"
++#include "../../lib/srdb1/db_key.h"
++#include "../../lib/srdb1/db_op.h"
++#include "../../lib/srdb1/db_val.h"
++
++#define DB_SQLITE_MAX_BINDS 64
++
++struct sqlite_connection {
++ struct pool_con hdr;
++
++ sqlite3 *conn;
++ int bindpos;
++
++ sqlite3_stmt *stmt;
++ const db_val_t *bindarg[DB_SQLITE_MAX_BINDS];
++};
++
++#define CON_SQLITE(db_con) ((struct sqlite_connection *) db_con->tail)
++
++db1_con_t* db_sqlite_init(const str* _sqlurl);
++void db_sqlite_close(db1_con_t* _h);
++
++int db_sqlite_free_result(db1_con_t* _h, db1_res_t* _r);
++
++int db_sqlite_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
++ const db_val_t* _v, const db_key_t* _c, int _n, int _nc,
++ const db_key_t _o, db1_res_t** _r);
++int db_sqlite_insert(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
++ int _n);
++int db_sqlite_delete(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
++ const db_val_t* _v, int _n);
++int db_sqlite_update(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
++ const db_val_t* _v, const db_key_t* _uk, const db_val_t* _uv,
++ int _n, int _un);
++int db_sqlite_raw_query(const db1_con_t* _h, const str* _s, db1_res_t** _r);
++
++int db_sqlite_use_table(db1_con_t* _h, const str* _t);
++
++
++#endif /* DBASE_H */
diff --git a/main/kbproto/APKBUILD b/main/kbproto/APKBUILD
new file mode 100644
index 0000000000..3e91d8abae
--- /dev/null
+++ b/main/kbproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=kbproto
+pkgver=1.0.5
+pkgrel=0
+pkgdesc="X11 XKB extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="e7edb59a3f54af15f749e8f3e314ee62 kbproto-1.0.5.tar.bz2"
diff --git a/main/ksymoops/APKBUILD b/main/ksymoops/APKBUILD
new file mode 100644
index 0000000000..09411308d4
--- /dev/null
+++ b/main/ksymoops/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ksymoops
+pkgver=2.4.11
+pkgrel=3
+pkgdesc="A Linux kernel Oops file troubleshooting tool"
+url="ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4"
+arch="all"
+license="GPL-2"
+depends=""
+makedepends="!gettext !libiconv"
+source="http://ftp.kernel.org/pub/linux/utils/kernel/$pkgname/v2.4/$pkgname-$pkgver.tar.bz2
+ $pkgname-2.4.11-build.patch
+ "
+subpackages="$pkgname-doc"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ patch -p1 < "$srcdir"/$pkgname-2.4.11-build.patch || return 1
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install \
+ INSTALL=install \
+ INSTALL_PREFIX="$pkgdir"/usr \
+ INSTALL_MANDIR="$pkgdir"/usr/share/man
+}
+md5sums="4a8249e182a5dbc75e566d162e9f3314 ksymoops-2.4.11.tar.bz2
+bad82d31c7d15431fc022be237791d59 ksymoops-2.4.11-build.patch"
diff --git a/main/ksymoops/ksymoops-2.4.11-build.patch b/main/ksymoops/ksymoops-2.4.11-build.patch
new file mode 100644
index 0000000000..e563840c6c
--- /dev/null
+++ b/main/ksymoops/ksymoops-2.4.11-build.patch
@@ -0,0 +1,12 @@
+--- a/Makefile.orig 2006-11-16 17:39:45.000000000 -0500
++++ b/Makefile 2006-11-16 17:39:55.000000000 -0500
+@@ -96,9 +96,6 @@
+ INSTALL_MANDIR := $(INSTALL_PREFIX)/man
+ endif
+
+-STATIC := -Wl,-Bstatic
+-DYNAMIC := -Wl,-Bdynamic
+-
+ OBJECTS := io.o ksyms.o ksymoops.o map.o misc.o object.o oops.o re.o symbol.o
+
+ all: $(PROGS)
diff --git a/main/lame/APKBUILD b/main/lame/APKBUILD
new file mode 100644
index 0000000000..cffb7502ed
--- /dev/null
+++ b/main/lame/APKBUILD
@@ -0,0 +1,62 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lame
+pkgver=3.98.4
+_ver=398-2
+pkgrel=4
+pkgdesc="An MP3 encoder and graphical frame analyzer"
+url="http://lame.sourceforge.net/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="nasm ncurses-dev autoconf automake libtool"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-398-2.tar.gz
+ lame-3.98.2-ffmpeg-0.5.patch"
+
+_builddir="$srcdir"/$pkgname-$_ver
+
+prepare() {
+ cd "$_builddir"
+
+ # link fronted shared
+ sed -i -e 's/\(^LDFLAGS.*\)-static/\1/g' frontend/Makefile.am
+
+ # fix for parallel builds
+ mkdir -p libmp3lame/i386/.libs
+
+ # fix for pic build with new nasm
+ sed -i -e '/define sp/s/+/ + /g' libmp3lame/i386/nasm.h || return 1
+
+ # Fix for ffmpeg.
+ # https://bugs.gentoo.org/show_bug.cgi?id=265830
+ patch -p1 < ../lame-3.98.2-ffmpeg-0.5.patch || return 1
+
+ aclocal && automake || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --enable-nasm \
+ --disable-mp3x \
+ --enable-shared \
+ --with-pic
+
+ make || return 1
+}
+
+package() {
+ local _textrels=
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+ _textrels=$(scanelf -q -Rt "$pkgdir")
+ if [ -n "$_textrels" ]; then
+ error "Textrels found:"
+ echo "$_textrels"
+ return 1
+ fi
+}
+
+md5sums="719dae0ee675d0c16e0e89952930ed35 lame-398-2.tar.gz
+e84a65409b0512045edd147524ba3ad4 lame-3.98.2-ffmpeg-0.5.patch"
diff --git a/main/lame/lame-3.98.2-ffmpeg-0.5.patch b/main/lame/lame-3.98.2-ffmpeg-0.5.patch
new file mode 100644
index 0000000000..30528c7db9
--- /dev/null
+++ b/main/lame/lame-3.98.2-ffmpeg-0.5.patch
@@ -0,0 +1,86 @@
+diff -NrU5 lame-398-2.orig/libmp3lame/lame.c lame-398-2/libmp3lame/lame.c
+--- lame-398-2.orig/libmp3lame/lame.c 2009-05-03 15:16:40.000000000 +0200
++++ lame-398-2/libmp3lame/lame.c 2009-05-03 15:24:49.000000000 +0200
+@@ -1600,10 +1600,17 @@
+ in_buffer[1] += n_in;
+
+ /* update mfbuf[] counters */
+ gfc->mf_size += n_out;
+ assert(gfc->mf_size <= MFSIZE);
++
++ /* lame_encode_flush may have set gfc->mf_sample_to_encode to 0
++ * so we have to reinitialize it here when that happened.
++ */
++ if (gfc->mf_samples_to_encode < 1) {
++ gfc->mf_samples_to_encode = ENCDELAY + POSTDELAY;
++ }
+ gfc->mf_samples_to_encode += n_out;
+
+
+ if (gfc->mf_size >= mf_needed) {
+ /* encode the frame. */
+@@ -1929,10 +1936,14 @@
+ int end_padding = POSTDELAY;
+ int pad_out_samples;
+ int frames_left;
+ int samples_to_encode = gfc->mf_samples_to_encode;
+
++ /* Was flush already called? */
++ if (gfc->mf_samples_to_encode < 1) {
++ return 0;
++ }
+ memset(buffer, 0, sizeof(buffer));
+ mp3count = 0;
+
+ if (gfp->in_samplerate != gfp->out_samplerate) {
+ /* delay due to resampling; needs to be fixed, if resampling code gets changed */
+@@ -1940,35 +1951,38 @@
+ }
+ pad_out_samples = gfp->framesize - (samples_to_encode % gfp->framesize);
+ end_padding += pad_out_samples;
+
+ frames_left = (samples_to_encode + pad_out_samples) / gfp->framesize;
+- while (frames_left > 0) {
++
++ /* send in a frame of 0 padding until all internal sample buffers are flushed */
++ while (frames_left > 0 && imp3 >= 0) {
+ int frame_num = gfp->frameNum;
+
+ mp3buffer_size_remaining = mp3buffer_size - mp3count;
+
+ /* if user specifed buffer size = 0, dont check size */
+ if (mp3buffer_size == 0)
+ mp3buffer_size_remaining = 0;
+
+- /* send in a frame of 0 padding until all internal sample buffers
+- * are flushed
+- */
+ imp3 = lame_encode_buffer(gfp, buffer[0], buffer[1], 32,
+ mp3buffer, mp3buffer_size_remaining);
+
+- if (frame_num != gfp->frameNum) {
+- --frames_left;
+- }
+- if (imp3 < 0) {
+- /* some type of fatal error */
+- return imp3;
+- }
+ mp3buffer += imp3;
+ mp3count += imp3;
++ frames_left -= (frame_num != gfp->frameNum) ? 1 : 0;
+ }
++ /* Set gfc->mf_samples_to_encode to 0, so we may detect
++ * and break loops calling it more than once in a row.
++ */
++ gfc->mf_samples_to_encode = 0;
++
++ if (imp3 < 0) {
++ /* some type of fatal error */
++ return imp3;
++ }
++
+ mp3buffer_size_remaining = mp3buffer_size - mp3count;
+ /* if user specifed buffer size = 0, dont check size */
+ if (mp3buffer_size == 0)
+ mp3buffer_size_remaining = 0;
+
diff --git a/main/lcms/APKBUILD b/main/lcms/APKBUILD
new file mode 100644
index 0000000000..94e50ce470
--- /dev/null
+++ b/main/lcms/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lcms
+pkgver=1.19
+pkgrel=2
+pkgdesc="Lightweight color management development library/engine"
+url="http://www.littlecms.com"
+arch="all"
+license="custom"
+depends=
+makedepends="tiff-dev jpeg-dev zlib-dev"
+subpackages="$pkgname-dev $pkgname-doc liblcms"
+source="http://downloads.sourceforge.net/project/lcms/lcms/$pkgver/lcms-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm 644 COPYING $pkgdir/usr/share/licenses/$pkgname/LICENSE
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+liblcms() {
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/liblcms.so.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="8af94611baf20d9646c7c2c285859818 lcms-1.19.tar.gz"
diff --git a/main/less/APKBUILD b/main/less/APKBUILD
new file mode 100644
index 0000000000..fe3a63def1
--- /dev/null
+++ b/main/less/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Cameron Banta <cbanta@gmail.com>
+# Maintainer: Cameron Banta <cbanta@gmail.com>
+pkgname=less
+pkgver=444
+pkgrel=0
+pkgdesc="File pager"
+url="http://www.greenwoodsoftware.com/less/"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+install="$pkgname.post-deinstall"
+subpackages="$pkgname-doc"
+source="http://www.greenwoodsoftware.com/$pkgname/$pkgname-$pkgver.tar.gz
+ $install"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="56f9f76ffe13f70155f47f6b3c87d421 less-444.tar.gz
+b84506d253e04db3c5af9016fead45a3 less.post-deinstall"
diff --git a/main/less/less.post-deinstall b/main/less/less.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/less/less.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/lftp/APKBUILD b/main/lftp/APKBUILD
new file mode 100644
index 0000000000..a8bafdc6ab
--- /dev/null
+++ b/main/lftp/APKBUILD
@@ -0,0 +1,35 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=lftp
+pkgver=4.2.2
+pkgrel=0
+pkgdesc="LFTP is sophisticated ftp/http client"
+url="http://lftp.yar.ru/"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev readline-dev ncurses-dev gettext-dev"
+subpackages="$pkgname-doc"
+source="http://ftp.yars.free.net/pub/source/lftp/lftp-${pkgver}.tar.bz2"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/lftp \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-modules \
+ --disable-nls \
+ --with-openssl
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+}
+
+md5sums="801d90de9def7fc0f88817bcc71295b7 lftp-4.2.2.tar.bz2"
diff --git a/main/lha/APKBUILD b/main/lha/APKBUILD
new file mode 100644
index 0000000000..40d13213b6
--- /dev/null
+++ b/main/lha/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=lha
+pkgver=1.14i
+pkgrel=2
+pkgdesc="Compression and archive utility for LH-7 format archives"
+url="http://www.infor.kanazawa-it.ac.jp/~ishii/lhaunix/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=""
+makedepends=""
+install=
+source="http://osdn.dl.sourceforge.jp/lha/22231/$pkgname-$pkgver-ac20050924p1.tar.gz"
+
+build ()
+{
+ cd $srcdir/$pkgname-$pkgver-ac20050924p1
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make "DESTDIR=$pkgdir" install
+ #install -D -m755 $srcdir/lha $pkgdir/usr/bin/lha
+}
+
+md5sums="9f52430410928ba4390a73a41a36d56f lha-1.14i-ac20050924p1.tar.gz"
diff --git a/main/libaio/APKBUILD b/main/libaio/APKBUILD
new file mode 100644
index 0000000000..55f302a262
--- /dev/null
+++ b/main/libaio/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname="libaio"
+pkgver="0.3.109"
+pkgrel=1
+pkgdesc="Asynchronous input/output library"
+url="http://lse.sourceforge.net/io/aio.html"
+arch="all"
+license="LGPL-2"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev"
+source="http://distfiles.gentoo.org/distfiles/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ cd $_builddir
+
+ make prefix="$pkgdir/usr" \
+ sysconfdir="$pkgdir/etc" \
+ mandir="$pkgdir/usr/share/man" \
+ infodir="$pkgdir/usr/share/info" \
+ install || return 1
+}
+
+md5sums="14f3a22fc14118a48be80ab5ea974f49 libaio-0.3.109.tar.bz2"
diff --git a/main/libao/APKBUILD b/main/libao/APKBUILD
new file mode 100644
index 0000000000..5e47953411
--- /dev/null
+++ b/main/libao/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libao
+pkgver=1.1.0
+pkgrel=2
+pkgdesc="Cross-platform audio output library and plugins"
+url="http://www.xiph.org/ao"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="alsa-lib-dev"
+source="http://downloads.xiph.org/releases/ao/$pkgname-$pkgver.tar.gz"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-alsa09 \
+ --disable-esd \
+ --disable-arts
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/ao/plugins*/*.la
+}
+
+md5sums="2b2508c29bc97e4dc218fa162cf883c8 libao-1.1.0.tar.gz"
diff --git a/main/libarchive/APKBUILD b/main/libarchive/APKBUILD
new file mode 100644
index 0000000000..9a4b6a809b
--- /dev/null
+++ b/main/libarchive/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libarchive
+pkgver=2.8.4
+pkgrel=2
+pkgdesc="library that can create and read several streaming archive formats"
+url="http://libarchive.googlecode.com/"
+arch="all"
+license="BSD"
+depends=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-tools"
+makedepends="zlib-dev bzip2-dev xz-dev acl-dev openssl-dev expat-dev"
+depends_dev="$makedepends"
+source="http://libarchive.googlecode.com/files/libarchive-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build () {
+ cd "$_builddir"
+ ./configure --prefix=/usr --without-xml2
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+tools() {
+ pkgdesc="libarchive tools bsdtar and bsdcpio"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="83b237a542f27969a8d68ac217dc3796 libarchive-2.8.4.tar.gz"
diff --git a/main/libart-lgpl/APKBUILD b/main/libart-lgpl/APKBUILD
new file mode 100644
index 0000000000..0f76730111
--- /dev/null
+++ b/main/libart-lgpl/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libart-lgpl
+pkgver=2.3.21
+pkgrel=5
+pkgdesc="A library for high-performance 2D graphics"
+url="http://www.levien.com/libart/"
+arch="all"
+license="LGPL"
+depends=
+makedepends=
+subpackages="$pkgname-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/libart_lgpl/2.3/libart_lgpl-$pkgver.tar.bz2
+ "
+
+_builddir="$srcdir"/libart_lgpl-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="08559ff3c67fd95d57b0c5e91a6b4302 libart_lgpl-2.3.21.tar.bz2"
diff --git a/main/libass/APKBUILD b/main/libass/APKBUILD
new file mode 100644
index 0000000000..ae78855b53
--- /dev/null
+++ b/main/libass/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=libass
+pkgver=0.9.12
+pkgrel=1
+pkgdesc="A portable library for SSA/ASS subtitles rendering"
+url="http://code.google.com/p/libass/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="pkgconfig enca-dev fontconfig-dev libpng-dev"
+subpackages="$pkgname-dev"
+source="http://libass.googlecode.com/files/${pkgname}-${pkgver}.tar.xz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="fcef4b048ca2655a14073d692551cd1f libass-0.9.12.tar.xz"
diff --git a/main/libassuan/APKBUILD b/main/libassuan/APKBUILD
new file mode 100644
index 0000000000..c8ad6fe71d
--- /dev/null
+++ b/main/libassuan/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libassuan
+pkgver=2.0.1
+pkgrel=2
+pkgdesc="Libassuan is the IPC library used by some GnuPG related software"
+url="ftp://ftp.gnupg.org/gcrypt/libgcrypt"
+arch="all"
+license="GPL"
+depends=
+makedepends="pth-dev libgpg-error-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnupg.org/gcrypt/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="53a7d4c22af909d7236d17d454ef935b libassuan-2.0.1.tar.bz2"
diff --git a/main/libatasmart/APKBUILD b/main/libatasmart/APKBUILD
new file mode 100644
index 0000000000..cfd76d9087
--- /dev/null
+++ b/main/libatasmart/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libatasmart
+pkgver=0.17
+pkgrel=2
+pkgdesc="ATA S.M.A.R.T. Reading and Parsing Library"
+url="http://0pointer.de/blog/projects/being-smart.html"
+arch="all"
+license="GPL"
+depends=
+depends_dev="udev-dev"
+makedepends="udev-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://0pointer.de/public/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-static \
+ --localstatedir=/var
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="dc36cadbbb7fa38f8af175713eda1a21 libatasmart-0.17.tar.gz"
diff --git a/main/libavc1394/APKBUILD b/main/libavc1394/APKBUILD
new file mode 100644
index 0000000000..9310215de2
--- /dev/null
+++ b/main/libavc1394/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libavc1394
+pkgver=0.5.3
+pkgrel=1
+pkgdesc="Audio/Video Control library for IEEE-1394 devices"
+url="http://sourceforge.net/projects/libavc1394/"
+arch="all"
+license="GPLv2+ LGPLv2+"
+depends=
+depends_dev="libraw1394-dev"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/libavc1394/libavc1394-$pkgver.tar.gz"
+
+_builddir="$srcdir"/libavc1394-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="09e30b1fb5ae455b6d8407e457a711a3 libavc1394-0.5.3.tar.gz"
diff --git a/main/libbluray/APKBUILD b/main/libbluray/APKBUILD
new file mode 100644
index 0000000000..748ddb82ac
--- /dev/null
+++ b/main/libbluray/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=libbluray
+pkgver=20100902
+pkgrel=2
+pkgdesc="Blu-ray playback libraries"
+url="http://git.videolan.org/?p=libbluray.git;a=summary"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev"
+source="http://alpine.nethq.org/distfiles/libbluray-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="c9ba7a906f5071affc347a6024f174d9 libbluray-20100902.tar.bz2"
diff --git a/main/libbonobo/APKBUILD b/main/libbonobo/APKBUILD
new file mode 100644
index 0000000000..8c65f3bea3
--- /dev/null
+++ b/main/libbonobo/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libbonobo
+pkgver=2.32.1
+pkgrel=2
+pkgdesc="GNOME base library"
+url="http://www.gnome.org/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="gtk+-dev libidl-dev orbit2-dev popt-dev libxml2-dev"
+makedepends="$depends_dev flex bison"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.acc.umu.se/pub/gnome/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="27fa902d4fdf6762ee010e7053aaf77b libbonobo-2.32.1.tar.bz2"
diff --git a/main/libc0.9.32/0001-getaddrinfo-allow-numeric-service-without-any-hints.patch b/main/libc0.9.32/0001-getaddrinfo-allow-numeric-service-without-any-hints.patch
new file mode 100644
index 0000000000..bdd3ce4892
--- /dev/null
+++ b/main/libc0.9.32/0001-getaddrinfo-allow-numeric-service-without-any-hints.patch
@@ -0,0 +1,37 @@
+From 66cdddf50492b9b645200ef580ae957c388694ab Mon Sep 17 00:00:00 2001
+From: Natanael Copa <natanael.copa@gmail.com>
+Date: Wed, 8 Jun 2011 09:12:16 +0000
+Subject: [PATCH] getaddrinfo: allow numeric service without any hints
+
+This appears to correspond to what glibc does and this fixes an
+issue with iptables-1.4.11 with udp and raw port numbers.
+
+(see http://bugzilla.netfilter.org/show_bug.cgi?id=721)
+
+This fixes #3841
+https://bugs.busybox.net/show_bug.cgi?id=3841
+---
+ libc/inet/getaddrinfo.c | 7 -------
+ 1 files changed, 0 insertions(+), 7 deletions(-)
+
+diff --git a/libc/inet/getaddrinfo.c b/libc/inet/getaddrinfo.c
+index 1a77c51..e7511f6 100644
+--- a/libc/inet/getaddrinfo.c
++++ b/libc/inet/getaddrinfo.c
+@@ -820,13 +820,6 @@ getaddrinfo(const char *name, const char *service,
+ if (hints->ai_flags & AI_NUMERICSERV)
+ return EAI_NONAME;
+ gaih_service.num = -1;
+- } else {
+- /*
+- * Can't specify a numerical socket unless a protocol
+- * family was given.
+- */
+- if (hints->ai_socktype == 0 && hints->ai_protocol == 0)
+- return EAI_SERVICE;
+ }
+ pservice = &gaih_service;
+ } else
+--
+1.7.5.4
+
diff --git a/main/libc0.9.32/0001-ldso-limited-support-for-ORIGIN-in-rpath.patch b/main/libc0.9.32/0001-ldso-limited-support-for-ORIGIN-in-rpath.patch
new file mode 100644
index 0000000000..73e0fab2bf
--- /dev/null
+++ b/main/libc0.9.32/0001-ldso-limited-support-for-ORIGIN-in-rpath.patch
@@ -0,0 +1,198 @@
+From 0ba7ee452f26088f6b738c37e05c16c7c9eb1caf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Fri, 18 Mar 2011 10:53:56 +0200
+Subject: [PATCH 1/3] ldso: limited support for $ORIGIN in rpath
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Handle it if it's in the beginning of the rpath entry as it
+should be.
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+ ldso/ldso/dl-elf.c | 80 ++++++++++++++++++++++++++++-----------------------
+ ldso/ldso/ldso.c | 18 ++++++++++--
+ 2 files changed, 59 insertions(+), 39 deletions(-)
+
+diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
+index 505247e..2b2d429 100644
+--- a/ldso/ldso/dl-elf.c
++++ b/ldso/ldso/dl-elf.c
+@@ -133,53 +133,60 @@ _dl_protect_relro (struct elf_resolve *l)
+ * in uClibc/ldso/util/ldd.c */
+ static struct elf_resolve *
+ search_for_named_library(const char *name, int secure, const char *path_list,
+- struct dyn_elf **rpnt)
++ struct dyn_elf **rpnt, const char *origin)
+ {
+- char *path, *path_n, *mylibname;
++ char *mylibname;
++ const char *p, *pn;
+ struct elf_resolve *tpnt;
+- int done;
++ int plen;
+
+ if (path_list==NULL)
+ return NULL;
+
+- /* We need a writable copy of this string, but we don't
+- * need this allocated permanently since we don't want
+- * to leak memory, so use alloca to put path on the stack */
+- done = _dl_strlen(path_list);
+- path = alloca(done + 1);
+-
+ /* another bit of local storage */
+ mylibname = alloca(2050);
+
+- _dl_memcpy(path, path_list, done+1);
+-
+ /* Unlike ldd.c, don't bother to eliminate double //s */
+
+ /* Replace colons with zeros in path_list */
+ /* : at the beginning or end of path maps to CWD */
+ /* :: anywhere maps CWD */
+ /* "" maps to CWD */
+- done = 0;
+- path_n = path;
+- do {
+- if (*path == 0) {
+- *path = ':';
+- done = 1;
+- }
+- if (*path == ':') {
+- *path = 0;
+- if (*path_n)
+- _dl_strcpy(mylibname, path_n);
+- else
+- _dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
+- _dl_strcat(mylibname, "/");
+- _dl_strcat(mylibname, name);
+- if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL)
+- return tpnt;
+- path_n = path+1;
++ for (p = path_list; p != NULL; p = pn) {
++ pn = _dl_strchr(p + 1, ':');
++ if (pn != NULL) {
++ plen = pn - p;
++ pn++;
++ } else
++ plen = _dl_strlen(p);
++
++ if (plen >= 7 && _dl_memcmp(p, "$ORIGIN", 7) == 0) {
++ int olen;
++ if (secure && plen != 7)
++ continue;
++ if (origin == NULL)
++ continue;
++ for (olen = _dl_strlen(origin) - 1; olen >= 0 && origin[olen] != '/'; olen--)
++ ;
++ if (olen <= 0)
++ continue;
++ _dl_memcpy(&mylibname[0], origin, olen);
++ _dl_memcpy(&mylibname[olen], p + 7, plen - 7);
++ mylibname[olen + plen - 7] = 0;
++ } else if (plen != 0) {
++ _dl_memcpy(mylibname, p, plen);
++ mylibname[plen] = 0;
++ } else {
++ _dl_strcpy(mylibname, ".");
+ }
+- path++;
+- } while (!done);
++ _dl_strcat(mylibname, "/");
++ _dl_strcat(mylibname, name);
++
++ tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname);
++ if (tpnt != NULL)
++ return tpnt;
++ }
++
+ return NULL;
+ }
+
+@@ -231,7 +238,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ if (pnt) {
+ pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+ _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
+- if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
++ if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt,
++ tpnt->libname)) != NULL)
+ return tpnt1;
+ }
+ #endif
+@@ -239,7 +247,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
+ if (_dl_library_path) {
+ _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
+- if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL)
++ if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt, NULL)) != NULL)
+ {
+ return tpnt1;
+ }
+@@ -253,7 +261,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ if (pnt) {
+ pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+ _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
+- if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
++ if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt, NULL)) != NULL)
+ return tpnt1;
+ }
+ #endif
+@@ -287,7 +295,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ /* Look for libraries wherever the shared library loader
+ * was installed */
+ _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
+- tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt);
++ tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt, NULL);
+ if (tpnt1 != NULL)
+ return tpnt1;
+
+@@ -300,7 +308,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ #ifndef __LDSO_CACHE_SUPPORT__
+ ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
+ #endif
+- , rpnt);
++ , rpnt, NULL);
+ if (tpnt1 != NULL)
+ return tpnt1;
+
+diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
+index 7ee9257..9423670 100644
+--- a/ldso/ldso/ldso.c
++++ b/ldso/ldso/ldso.c
+@@ -272,6 +272,20 @@ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
+ }
+ }
+
++static void _dl_setup_progname(const char *argv0)
++{
++ char image[PATH_MAX];
++ ssize_t s;
++
++ s = _dl_readlink("/proc/self/exe", image, sizeof(image));
++ if (s > 0 && image[0] == '/') {
++ image[s] = 0;
++ _dl_progname = _dl_strdup(image);
++ } else if (argv0) {
++ _dl_progname = argv0;
++ }
++}
++
+ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
+ ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp,
+ char **argv
+@@ -321,9 +335,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
+ * been fixed up by now. Still no function calls outside of this
+ * library, since the dynamic resolver is not yet ready.
+ */
+- if (argv[0]) {
+- _dl_progname = argv[0];
+- }
++ _dl_setup_progname(argv[0]);
+
+ if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
+ _dl_dprintf(_dl_debug_file, "Standalone execution is not supported yet\n");
+--
+1.7.1
+
diff --git a/main/libc0.9.32/0001-libdl-rudimentary-locking-for-dlopen-dlsym-dlclose.patch b/main/libc0.9.32/0001-libdl-rudimentary-locking-for-dlopen-dlsym-dlclose.patch
new file mode 100644
index 0000000000..d406f030d6
--- /dev/null
+++ b/main/libc0.9.32/0001-libdl-rudimentary-locking-for-dlopen-dlsym-dlclose.patch
@@ -0,0 +1,152 @@
+From 521807eb4d18c5e693f91ad53cb277c76aab8686 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Thu, 24 Mar 2011 13:24:32 +0200
+Subject: [PATCH] libdl: rudimentary locking for dlopen/dlsym/dlclose
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This implements big-dlfcn lock to allow multithreaded usage of
+dlopen/dlsym/dlclose. We should really clean up the dl code so
+we can use more fine grained locking or even RCU where appropriate.
+But at least we won't crash now.
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+ TODO | 1 +
+ ldso/libdl/libdl.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 50 insertions(+), 5 deletions(-)
+
+diff --git a/TODO b/TODO
+index ae305a5..95cabd5 100644
+--- a/TODO
++++ b/TODO
+@@ -101,6 +101,7 @@ TODO list for AFTER the uClibc 1.0.0 release:
+ *) run 'nm -D --size-sort -t d libuClibc-0.9.26.so' and work on the
+ biggest things (i.e. stuff at the end of the list) to make
+ them smaller.
++ *) Fix dlopen/dlsym/dlclose locking to more fine grained or use RCU
+ <more wishlist items here>
+
+
+diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
+index 68cd579..e007f54 100644
+--- a/ldso/libdl/libdl.c
++++ b/ldso/libdl/libdl.c
+@@ -34,6 +34,7 @@
+ #include <stdio.h>
+ #include <string.h> /* Needed for 'strstr' prototype' */
+ #include <stdbool.h>
++#include <bits/uClibc_mutex.h>
+
+ #ifdef __UCLIBC_HAS_TLS__
+ #include <tls.h>
+@@ -44,6 +45,10 @@
+ extern void _dl_add_to_slotinfo(struct link_map *l);
+ #endif
+
++/* TODO: get rid of global lock and use more finegrained locking, or
++ * perhaps RCU for the global structures */
++__UCLIBC_MUTEX_STATIC(_dl_mutex, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
++
+ #ifdef SHARED
+ # if defined(USE_TLS) && USE_TLS
+ # include <dl-tls.h>
+@@ -271,7 +276,7 @@ void dl_cleanup(void)
+ }
+ }
+
+-void *dlopen(const char *libname, int flag)
++static void *do_dlopen(const char *libname, int flag)
+ {
+ struct elf_resolve *tpnt, *tfrom;
+ struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle;
+@@ -605,7 +610,18 @@ oops:
+ return NULL;
+ }
+
+-void *dlsym(void *vhandle, const char *name)
++void *dlopen(const char *libname, int flag)
++{
++ void *ret;
++
++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
++ ret = do_dlopen(libname, flag);
++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
++
++ return ret;
++}
++
++static void *do_dlsym(void *vhandle, const char *name, void *caller_address)
+ {
+ struct elf_resolve *tpnt, *tfrom;
+ struct dyn_elf *handle;
+@@ -653,7 +669,7 @@ void *dlsym(void *vhandle, const char *name)
+ * dynamic loader itself, as it doesn't know
+ * how to properly treat it.
+ */
+- from = (ElfW(Addr)) __builtin_return_address(0);
++ from = (ElfW(Addr)) caller_address;
+
+ tfrom = NULL;
+ for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
+@@ -690,6 +706,17 @@ out:
+ return ret;
+ }
+
++void *dlsym(void *vhandle, const char *name)
++{
++ void *ret;
++
++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
++ ret = do_dlsym(vhandle, name, __builtin_return_address(0));
++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
++
++ return ret;
++}
++
+ #if 0
+ void *dlvsym(void *vhandle, const char *name, const char *version)
+ {
+@@ -957,7 +984,13 @@ static int do_dlclose(void *vhandle, int need_fini)
+
+ int dlclose(void *vhandle)
+ {
+- return do_dlclose(vhandle, 1);
++ int ret;
++
++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
++ ret = do_dlclose(vhandle, 1);
++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
++
++ return ret;
+ }
+
+ char *dlerror(void)
+@@ -1004,7 +1037,7 @@ int dlinfo(void)
+ return 0;
+ }
+
+-int dladdr(const void *__address, Dl_info * __info)
++static int do_dladdr(const void *__address, Dl_info * __info)
+ {
+ struct elf_resolve *pelf;
+ struct elf_resolve *rpnt;
+@@ -1108,3 +1141,14 @@ int dladdr(const void *__address, Dl_info * __info)
+ }
+ }
+ #endif
++
++int dladdr(const void *__address, Dl_info * __info)
++{
++ int ret;
++
++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1);
++ ret = do_dladdr(__address, __info);
++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1);
++
++ return ret;
++}
+--
+1.7.1
+
diff --git a/main/libc0.9.32/0001-libm-x86_64-implement-fesetround.patch b/main/libc0.9.32/0001-libm-x86_64-implement-fesetround.patch
new file mode 100644
index 0000000000..84d6a2e08b
--- /dev/null
+++ b/main/libc0.9.32/0001-libm-x86_64-implement-fesetround.patch
@@ -0,0 +1,98 @@
+From b58032ae6a34afc1887d9a6f3d05891d0d4fdbab Mon Sep 17 00:00:00 2001
+From: Natanael Copa <natanael.copa@gmail.com>
+Date: Sun, 28 Nov 2010 12:43:33 +0000
+Subject: [PATCH] libm/x86_64: implement fesetround
+
+from glibc
+---
+ libm/x86_64/Makefile.arch | 24 +++++++++++++++++++++++
+ libm/x86_64/fesetround.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 70 insertions(+), 0 deletions(-)
+ create mode 100644 libm/x86_64/Makefile.arch
+ create mode 100644 libm/x86_64/fesetround.c
+
+diff --git a/libm/x86_64/Makefile.arch b/libm/x86_64/Makefile.arch
+new file mode 100644
+index 0000000..e1be961
+--- /dev/null
++++ b/libm/x86_64/Makefile.arch
+@@ -0,0 +1,24 @@
++# Makefile for uClibc
++#
++# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
++#
++# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
++#
++# The routines included in this math library are derived from
++# glibc's libm.
++#
++
++ifeq ($(UCLIBC_HAS_FENV),y)
++libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
++libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
++endif
++
++libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
++
++ifeq ($(DOPIC),y)
++libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
++else
++libm-a-y+=$(libm_ARCH_OBJS)
++endif
++libm-so-y+=$(libm_ARCH_OBJS:.o=.os)
++
+diff --git a/libm/x86_64/fesetround.c b/libm/x86_64/fesetround.c
+new file mode 100644
+index 0000000..3d2ef4c
+--- /dev/null
++++ b/libm/x86_64/fesetround.c
+@@ -0,0 +1,46 @@
++/* Set current rounding direction.
++ Copyright (C) 2001, 2005 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C 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.
++
++ The GNU C 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 the GNU C Library; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#include <fenv.h>
++
++int
++fesetround (int round)
++{
++ unsigned short int cw;
++ int mxcsr;
++
++ if ((round & ~0xc00) != 0)
++ /* ROUND is no valid rounding mode. */
++ return 1;
++
++ /* First set the x87 FPU. */
++ __asm__ ("fnstcw %0" : "=m" (*&cw));
++ cw &= ~0xc00;
++ cw |= round;
++ __asm__ ("fldcw %0" : : "m" (*&cw));
++
++ /* And now the MSCSR register for SSE, the precision is at different bit
++ positions in the different units, we need to shift it 3 bits. */
++ __asm__ ("stmxcsr %0" : "=m" (*&mxcsr));
++ mxcsr &= ~ 0x6000;
++ mxcsr |= round << 3;
++ __asm__ ("ldmxcsr %0" : : "m" (*&mxcsr));
++
++ return 0;
++}
+--
+1.7.3.2
+
diff --git a/main/libc0.9.32/0001-malloc-standard-synchronize-on-fork.patch b/main/libc0.9.32/0001-malloc-standard-synchronize-on-fork.patch
new file mode 100644
index 0000000000..eb3bfbe04f
--- /dev/null
+++ b/main/libc0.9.32/0001-malloc-standard-synchronize-on-fork.patch
@@ -0,0 +1,54 @@
+From 168215f9c3ec4ec9a2fad9387038ced8b386ebaa Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Sat, 26 Mar 2011 20:23:09 +0200
+Subject: [PATCH] malloc-standard: synchronize on fork
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Otherwise other threads can leave malloc state locked, and the child
+will hang indefinitely if it tries to malloc something.
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+ libc/stdlib/malloc-standard/free.c | 17 +++++++++++++++++
+ 1 files changed, 17 insertions(+), 0 deletions(-)
+
+diff --git a/libc/stdlib/malloc-standard/free.c b/libc/stdlib/malloc-standard/free.c
+index 39e54d6..df512cc 100644
+--- a/libc/stdlib/malloc-standard/free.c
++++ b/libc/stdlib/malloc-standard/free.c
+@@ -118,6 +118,21 @@ int malloc_trim(size_t pad)
+ to inline it at all call points, which turns out not to be an
+ optimization at all. (Inlining it in __malloc_consolidate is fine though.)
+ */
++static void _malloc_lock(void)
++{
++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(__malloc_lock);
++}
++
++static void _malloc_unlock(void)
++{
++ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(__malloc_lock);
++}
++
++static void _malloc_reset(void)
++{
++ __UCLIBC_MUTEX_INIT_VAR(__malloc_lock);
++}
++
+ static void malloc_init_state(mstate av)
+ {
+ int i;
+@@ -145,6 +160,8 @@ static void malloc_init_state(mstate av)
+
+ av->top = initial_top(av);
+ av->pagesize = malloc_getpagesize;
++
++ __libc_atfork(_malloc_lock, _malloc_unlock, _malloc_reset);
+ }
+
+
+--
+1.7.1
+
diff --git a/main/libc0.9.32/0001-time-fix-parsing-of-tzdata-files-where-off_t-is-64-b.patch b/main/libc0.9.32/0001-time-fix-parsing-of-tzdata-files-where-off_t-is-64-b.patch
new file mode 100644
index 0000000000..e47d89620c
--- /dev/null
+++ b/main/libc0.9.32/0001-time-fix-parsing-of-tzdata-files-where-off_t-is-64-b.patch
@@ -0,0 +1,32 @@
+From ef44545eb332eac26577ea2672e89b01b3aa5706 Mon Sep 17 00:00:00 2001
+From: William Pitcock <nenolod@dereferenced.org>
+To: uclibc@uclibc.org
+Date: Thu, 28 Apr 2011 03:09:20 -0500
+Subject: [PATCH] time: fix parsing of tzdata files where off_t is 64-bit
+
+lseek takes off_t as the offset type, but gcc will normally pass a
+32-bit value unless the number is wider than 16 bits. so we force
+gcc to pass the constant as off_t type always by casting the constant
+to off_t.
+
+Signed-off-by: William Pitcock <nenolod@dereferenced.org>
+---
+ libc/misc/time/time.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c
+index 19d68e1..1b21f9e 100644
+--- a/libc/misc/time/time.c
++++ b/libc/misc/time/time.c
+@@ -1856,7 +1856,7 @@ ERROR:
+ if (r != TZ_BUFLEN
+ || strncmp(buf, "TZif", 4) != 0
+ || (unsigned char)buf[4] < 2
+- || lseek(fd, -TZ_BUFLEN, SEEK_END) < 0
++ || lseek(fd, (off_t) -TZ_BUFLEN, SEEK_END) < 0
+ ) {
+ goto ERROR;
+ }
+--
+1.7.4.5
+
diff --git a/main/libc0.9.32/0002-stdlib-fix-arc4random-return-type-to-u_int32_t.patch b/main/libc0.9.32/0002-stdlib-fix-arc4random-return-type-to-u_int32_t.patch
new file mode 100644
index 0000000000..9d924655df
--- /dev/null
+++ b/main/libc0.9.32/0002-stdlib-fix-arc4random-return-type-to-u_int32_t.patch
@@ -0,0 +1,61 @@
+From 70debeff167858502d99e92a221fe14f5428a9b6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Fri, 18 Mar 2011 10:57:31 +0200
+Subject: [PATCH 2/3] stdlib: fix arc4random return type to u_int32_t
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It's documented to be u_int32_t and not uint32_t:
+ http://www.manpagez.com/man/3/arc4random/
+
+This also fixes a major bug that stdlib.h includes stdint.h. Things
+might go very wrong because stdint.h has conditional defines and
+if stdlib.h is included before #define's for stdint.h we end up
+missing things and breaking builds (e.g. openjdk).
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+ include/stdlib.h | 4 ++--
+ libc/stdlib/arc4random.c | 3 ++-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/include/stdlib.h b/include/stdlib.h
+index e9a8b84..7b35840 100644
+--- a/include/stdlib.h
++++ b/include/stdlib.h
+@@ -902,8 +902,8 @@ extern int getloadavg (double __loadavg[], int __nelem)
+ #endif
+
+ #ifdef __UCLIBC_HAS_ARC4RANDOM__
+-#include <stdint.h>
+-extern uint32_t arc4random(void);
++# include <sys/types.h>
++extern u_int32_t arc4random(void);
+ extern void arc4random_stir(void);
+ extern void arc4random_addrandom(unsigned char *, int);
+ #endif
+diff --git a/libc/stdlib/arc4random.c b/libc/stdlib/arc4random.c
+index c7aed66..7b9b12d 100644
+--- a/libc/stdlib/arc4random.c
++++ b/libc/stdlib/arc4random.c
+@@ -30,6 +30,7 @@
+ #include <fcntl.h>
+ #include <stdlib.h>
+ #include <unistd.h>
++#include <stdint.h>
+ #include <sys/types.h>
+ #include <sys/param.h>
+ #include <sys/time.h>
+@@ -175,7 +176,7 @@ arc4random_addrandom(u_char *dat, int datlen)
+ arc4_addrandom(&rs, dat, datlen);
+ }
+
+-uint32_t
++u_int32_t
+ arc4random(void)
+ {
+ if (!rs_initialized)
+--
+1.7.1
+
diff --git a/main/libc0.9.32/0003-ldso-support-RTLD_NOLOAD.patch b/main/libc0.9.32/0003-ldso-support-RTLD_NOLOAD.patch
new file mode 100644
index 0000000000..f10d6f002d
--- /dev/null
+++ b/main/libc0.9.32/0003-ldso-support-RTLD_NOLOAD.patch
@@ -0,0 +1,234 @@
+From 4bb377585b95cb67c90ff4ffc21a6870a4e78a37 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Fri, 18 Mar 2011 11:40:04 +0200
+Subject: [PATCH 3/3] ldso: support RTLD_NOLOAD
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+So application query if specified modile is loaded or not with
+dlopen.
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+ ldso/include/dl-elf.h | 6 ++++--
+ ldso/ldso/dl-elf.c | 30 +++++++++++++++++-------------
+ ldso/ldso/ldso.c | 4 +++-
+ ldso/libdl/libdl.c | 5 +++--
+ libc/sysdeps/linux/common/bits/dlfcn.h | 4 ++--
+ 5 files changed, 29 insertions(+), 20 deletions(-)
+
+diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h
+index 7fbb373..7102351 100644
+--- a/ldso/include/dl-elf.h
++++ b/ldso/include/dl-elf.h
+@@ -25,16 +25,18 @@ static __inline__ void _dl_map_cache(void) { }
+ static __inline__ void _dl_unmap_cache(void) { }
+ #endif
+
++#define DL_RESOLVE_SECURE 0x0001
++#define DL_RESOLVE_NOLOAD 0x0002
+
+ /* Function prototypes for non-static stuff in readelflib1.c */
+ extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size);
+ extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
+ unsigned long rel_addr, unsigned long rel_size);
+-extern struct elf_resolve * _dl_load_shared_library(int secure,
++extern struct elf_resolve * _dl_load_shared_library(int resolve_flags,
+ struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
+ int trace_loaded_objects);
+-extern struct elf_resolve * _dl_load_elf_shared_library(int secure,
++extern struct elf_resolve * _dl_load_elf_shared_library(int resolve_flags,
+ struct dyn_elf **rpnt, char *libname);
+ extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
+ int trace_loaded_objects);
+diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
+index 2b2d429..6d35bf2 100644
+--- a/ldso/ldso/dl-elf.c
++++ b/ldso/ldso/dl-elf.c
+@@ -132,7 +132,7 @@ _dl_protect_relro (struct elf_resolve *l)
+ /* This function's behavior must exactly match that
+ * in uClibc/ldso/util/ldd.c */
+ static struct elf_resolve *
+-search_for_named_library(const char *name, int secure, const char *path_list,
++search_for_named_library(const char *name, int resolve_flags, const char *path_list,
+ struct dyn_elf **rpnt, const char *origin)
+ {
+ char *mylibname;
+@@ -162,7 +162,7 @@ search_for_named_library(const char *name, int secure, const char *path_list,
+
+ if (plen >= 7 && _dl_memcmp(p, "$ORIGIN", 7) == 0) {
+ int olen;
+- if (secure && plen != 7)
++ if ((resolve_flags & DL_RESOLVE_SECURE) && plen != 7)
+ continue;
+ if (origin == NULL)
+ continue;
+@@ -182,7 +182,7 @@ search_for_named_library(const char *name, int secure, const char *path_list,
+ _dl_strcat(mylibname, "/");
+ _dl_strcat(mylibname, name);
+
+- tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname);
++ tpnt = _dl_load_elf_shared_library(resolve_flags, rpnt, mylibname);
+ if (tpnt != NULL)
+ return tpnt;
+ }
+@@ -194,7 +194,7 @@ search_for_named_library(const char *name, int secure, const char *path_list,
+ unsigned long _dl_error_number;
+ unsigned long _dl_internal_error_number;
+
+-struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
++struct elf_resolve *_dl_load_shared_library(int resolve_flags, struct dyn_elf **rpnt,
+ struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects)
+ {
+ char *pnt;
+@@ -223,7 +223,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+
+ if (libname != full_libname) {
+ _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname);
+- tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname);
++ tpnt1 = _dl_load_elf_shared_library(resolve_flags, rpnt, full_libname);
+ if (tpnt1) {
+ return tpnt1;
+ }
+@@ -238,7 +238,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ if (pnt) {
+ pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+ _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt);
+- if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt,
++ if ((tpnt1 = search_for_named_library(libname, resolve_flags, pnt, rpnt,
+ tpnt->libname)) != NULL)
+ return tpnt1;
+ }
+@@ -247,7 +247,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
+ if (_dl_library_path) {
+ _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path);
+- if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt, NULL)) != NULL)
++ if ((tpnt1 = search_for_named_library(libname, resolve_flags, _dl_library_path, rpnt, NULL)) != NULL)
+ {
+ return tpnt1;
+ }
+@@ -261,7 +261,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ if (pnt) {
+ pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+ _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
+- if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt, NULL)) != NULL)
++ if ((tpnt1 = search_for_named_library(libname, resolve_flags, pnt, rpnt, NULL)) != NULL)
+ return tpnt1;
+ }
+ #endif
+@@ -284,7 +284,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ || libent[i].flags == LIB_ELF_LIBC0
+ || libent[i].flags == LIB_ELF_LIBC5)
+ && _dl_strcmp(libname, strs + libent[i].sooffset) == 0
+- && (tpnt1 = _dl_load_elf_shared_library(secure, rpnt, strs + libent[i].liboffset))
++ && (tpnt1 = _dl_load_elf_shared_library(resolve_flags, rpnt, strs + libent[i].liboffset))
+ ) {
+ return tpnt1;
+ }
+@@ -295,14 +295,14 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
+ /* Look for libraries wherever the shared library loader
+ * was installed */
+ _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
+- tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt, NULL);
++ tpnt1 = search_for_named_library(libname, resolve_flags, _dl_ldsopath, rpnt, NULL);
+ if (tpnt1 != NULL)
+ return tpnt1;
+
+ /* Lastly, search the standard list of paths for the library.
+ This list must exactly match the list in uClibc/ldso/util/ldd.c */
+ _dl_if_debug_dprint("\tsearching full lib path list\n");
+- tpnt1 = search_for_named_library(libname, secure,
++ tpnt1 = search_for_named_library(libname, resolve_flags,
+ UCLIBC_RUNTIME_PREFIX "lib:"
+ UCLIBC_RUNTIME_PREFIX "usr/lib"
+ #ifndef __LDSO_CACHE_SUPPORT__
+@@ -329,7 +329,7 @@ goof:
+ * are required.
+ */
+
+-struct elf_resolve *_dl_load_elf_shared_library(int secure,
++struct elf_resolve *_dl_load_elf_shared_library(int resolve_flags,
+ struct dyn_elf **rpnt, char *libname)
+ {
+ ElfW(Ehdr) *epnt;
+@@ -368,7 +368,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
+ }
+ /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
+ we don't load the library if it isn't setuid. */
+- if (secure) {
++ if (resolve_flags & DL_RESOLVE_SECURE) {
+ if (!(st.st_mode & S_ISUID)) {
+ _dl_close(infile);
+ return NULL;
+@@ -384,6 +384,10 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
+ return tpnt;
+ }
+ }
++ if (resolve_flags & DL_RESOLVE_NOLOAD) {
++ _dl_close(infile);
++ return NULL;
++ }
+ header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
+ if (_dl_mmap_check_error(header)) {
+diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
+index 9423670..b71af34 100644
+--- a/ldso/ldso/ldso.c
++++ b/ldso/ldso/ldso.c
+@@ -646,7 +646,9 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
+ if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
+ _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname);
+
+- tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
++ tpnt1 = _dl_load_shared_library(
++ _dl_secure ? DL_RESOLVE_SECURE : 0,
++ &rpnt, NULL, str, trace_loaded_objects);
+ if (!tpnt1) {
+ #ifdef __LDSO_LDD_SUPPORT__
+ if (trace_loaded_objects)
+diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
+index 68cd579..edf38d2 100644
+--- a/ldso/libdl/libdl.c
++++ b/ldso/libdl/libdl.c
+@@ -288,7 +288,7 @@ void *dlopen(const char *libname, int flag)
+ #endif
+
+ /* A bit of sanity checking... */
+- if (!(flag & (RTLD_LAZY|RTLD_NOW))) {
++ if (!(flag & (RTLD_LAZY|RTLD_NOW|RTLD_NOLOAD))) {
+ _dl_error_number = LD_BAD_HANDLE;
+ return NULL;
+ }
+@@ -358,8 +358,9 @@ void *dlopen(const char *libname, int flag)
+ /* Try to load the specified library */
+ _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n",
+ (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0));
+- tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
+
++ tpnt = _dl_load_shared_library((flag & RTLD_NOLOAD) ? DL_RESOLVE_NOLOAD : 0,
++ &rpnt, tfrom, (char*)libname, 0);
+ if (tpnt == NULL) {
+ _dl_unmap_cache();
+ return NULL;
+diff --git a/libc/sysdeps/linux/common/bits/dlfcn.h b/libc/sysdeps/linux/common/bits/dlfcn.h
+index 4bfbbff..47b42ad 100644
+--- a/libc/sysdeps/linux/common/bits/dlfcn.h
++++ b/libc/sysdeps/linux/common/bits/dlfcn.h
+@@ -24,9 +24,9 @@
+ /* The MODE argument to `dlopen' contains one of the following: */
+ #define RTLD_LAZY 0x00001 /* Lazy function call binding. */
+ #define RTLD_NOW 0x00002 /* Immediate function call binding. */
+-#if 0 /* uClibc doesnt support these */
+-#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
++#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
+ #define RTLD_NOLOAD 0x00004 /* Do not load the object. */
++#if 0 /* uClibc doesnt support these */
+ #define RTLD_DEEPBIND 0x00008 /* Use deep binding. */
+ #endif
+
+--
+1.7.1
+
diff --git a/main/libc0.9.32/APKBUILD b/main/libc0.9.32/APKBUILD
new file mode 100644
index 0000000000..80cacf8978
--- /dev/null
+++ b/main/libc0.9.32/APKBUILD
@@ -0,0 +1,150 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+_abiver=0.9.32
+pkgname=libc$_abiver
+_gitver=
+pkgver=0.9.32
+_ver=${pkgver/_/-}
+pkgrel=0
+pkgdesc="C library for developing embedded Linux systems"
+url=http://uclibc.org
+license="LGPL-2"
+arch="all"
+options=
+makedepends="linux-headers"
+subpackages="uclibc-dev:dev uclibc-utils:utils libthread_db"
+depends_dev="linux-headers=>2.6.32"
+replaces=uclibc
+options="!strip"
+triggers=
+
+_snapurl="http://git.uclibc.org/uClibc/snapshot/master.tar.bz2"
+_snapfile="$pkgname-$pkgver.tar.bz2"
+source="http://uclibc.org/downloads/uClibc-${_ver}.tar.bz2
+ compat-stack-guard.patch
+ uclibc-resolv-cname-fix.diff
+ 0001-libm-x86_64-implement-fesetround.patch
+ 0001-ldso-limited-support-for-ORIGIN-in-rpath.patch
+ 0002-stdlib-fix-arc4random-return-type-to-u_int32_t.patch
+ 0003-ldso-support-RTLD_NOLOAD.patch
+ 0001-libdl-rudimentary-locking-for-dlopen-dlsym-dlclose.patch
+ 0001-malloc-standard-synchronize-on-fork.patch
+ 0001-time-fix-parsing-of-tzdata-files-where-off_t-is-64-b.patch
+ 0001-getaddrinfo-allow-numeric-service-without-any-hints.patch
+ uclibc-ubacktrace-asneeded-fix.patch
+ uclibc-librt-asneeded-fix.patch
+ uclibc-epoll_pwait-hack.patch
+ uclibcconfig.x86
+ uclibcconfig.x86_64
+ uclibcconfig.i486
+ uclibcconfig.arm
+ uclibcconfig.powerpc
+ sha512-crypt.patch
+ uclibc-utils.trigger
+ "
+
+_config="$srcdir"/uclibcconfig.${CARCH}
+_builddir="$srcdir"/uClibc-${_ver}
+
+snapshot() {
+ local _date=$(date +%y%m%d%H%M)
+ _gitver=$_date
+ pkgver=${_abiver}_alpha0_git$_gitver
+ _snapfile="$pkgname-$pkgver.tar.bz2"
+
+ rm -f "$SRCDEST"/$_snapfile
+ msg "snapfile=$_snapfile"
+ wget -O "$SRCDEST"/$_snapfile $_snapurl
+ pkgrel=0
+ sed -i -e "s/^_gitver=.*/_gitver=$_gitver/" \
+ -e "s/^pkgrel=.*/pkgrel=$pkgrel/" \
+ APKBUILD
+ checksum
+}
+
+prepare() {
+ local i
+ cd "$_builddir"
+ # patches goes here
+ for i in $source; do
+ case $i in
+ *.patch|*.diff)
+ msg "Applying $i..."
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+ # set abi version and remove unsupported warnings c flag
+ sed -i -e "s/^ABI_VERSION.*/ABI_VERSION := $_abiver/" \
+ -e "s/-Wold-style-declaration//g" \
+ Rules.mak
+}
+
+build() {
+ local _kh=
+ cd "$_builddir"
+ if [ -n "$SYSROOT" ]; then
+ _kh=KERNEL_HEADERS="$SYSROOT/include"
+ fi
+ cp "$_config" .config
+ if [ -n "$DEBUG" ]; then
+ sed -i -e 's/# DODEBUG is not set/DODEBUG=y/' \
+ -e 's/DOSTRIP=y/# DOSTRIP is not set/' \
+ .config
+ fi
+ make silentoldconfig
+ make -j1 pregen KERNEL_HEADERS="$SYSROOT"/usr/include \
+ CROSS="$CROSS" || return 1
+ make all KERNEL_HEADERS="$SYSROOT/usr/include" CROSS="$CROSS" || return 1
+ make utils CROSS="$CROSS" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" KERNEL_HEADERS="$SYSROOT/usr/include" \
+ CROSS="$CROSS" install install_utils
+ install -Dm755 extra/scripts/getent "$pkgdir"/usr/bin/getent
+}
+
+dev() {
+ default_dev
+ replaces="uclibc linux-headers"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/*.so "$subpkgdir"/usr/lib/
+}
+
+utils() {
+ pkgdesc="uClibc utility programs"
+ replaces="uclibc $pkgname"
+ triggers="uclibc-utils.trigger:/lib /usr/lib"
+ mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/sbin
+ mv "$pkgdir"/sbin/* "$subpkgdir"/sbin/
+ mv "$pkgdir"/usr/bin/* "$subpkgdir"/usr/bin/
+}
+
+libthread_db() {
+ pkgdesc="uClibc thread debugging library"
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libthread_db* "$subpkgdir"/lib/
+}
+
+md5sums="cfcb6c25d8ebe12817499d8749ee8ae1 uClibc-0.9.32.tar.bz2
+a9bfb77ea7dc5fb9abf4d4b19201c614 compat-stack-guard.patch
+5d6e3e382b66f59cfd7242a4fe453f98 uclibc-resolv-cname-fix.diff
+e0c901502602f7e9e002d910d0f32ab9 0001-libm-x86_64-implement-fesetround.patch
+bc164e262c5feab55c800780704fa71c 0001-ldso-limited-support-for-ORIGIN-in-rpath.patch
+b4fb68ad3d0e8331b1b40c30eb21dfdc 0002-stdlib-fix-arc4random-return-type-to-u_int32_t.patch
+6147efd2eee5af5e734896823c2d1a3d 0003-ldso-support-RTLD_NOLOAD.patch
+3e151ae3d3613dff9296d166aca3a800 0001-libdl-rudimentary-locking-for-dlopen-dlsym-dlclose.patch
+30f27fe51fdc4d121166ad2af18dfb8d 0001-malloc-standard-synchronize-on-fork.patch
+2548d9f470c9a5b2c117ec3d6f35c105 0001-time-fix-parsing-of-tzdata-files-where-off_t-is-64-b.patch
+9e1ffc8dae55f4489c770f284734804f 0001-getaddrinfo-allow-numeric-service-without-any-hints.patch
+7c47e9cb284b0da8df6ed2096b2c9c66 uclibc-ubacktrace-asneeded-fix.patch
+e5caf13c43ee8d48f22eded21b857d81 uclibc-librt-asneeded-fix.patch
+0ed588014227935fbb83b207282f3c15 uclibc-epoll_pwait-hack.patch
+7a0a26d002de3a2dcb541e4db9840485 uclibcconfig.x86
+d08010019b097a099ab23810c0da60ce uclibcconfig.x86_64
+7a0a26d002de3a2dcb541e4db9840485 uclibcconfig.i486
+af6526daf5adb86398cab1bf67514c51 uclibcconfig.arm
+a8eb360d4ae99dc6e7634d7e9b5c653a uclibcconfig.powerpc
+7bf1af84106de9e05160ed6d4853c54f sha512-crypt.patch
+f3be4f2bc54d7561d252937e10abf0d2 uclibc-utils.trigger"
diff --git a/main/libc0.9.32/compat-stack-guard.patch b/main/libc0.9.32/compat-stack-guard.patch
new file mode 100644
index 0000000000..c69a9c5350
--- /dev/null
+++ b/main/libc0.9.32/compat-stack-guard.patch
@@ -0,0 +1,55 @@
+diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
+index 2857f7e..dce6fd8 100644
+--- a/ldso/ldso/ldso.c
++++ b/ldso/ldso/ldso.c
+@@ -103,11 +103,7 @@ extern void _start(void);
+ #ifdef __UCLIBC_HAS_SSP__
+ # include <dl-osinfo.h>
+ static uintptr_t stack_chk_guard;
+-# ifndef THREAD_SET_STACK_GUARD
+-/* Only exported for architectures that don't store the stack guard canary
+- * in local thread area. */
+ uintptr_t __stack_chk_guard attribute_relro;
+-# endif
+ # ifdef __UCLIBC_HAS_SSP_COMPAT__
+ uintptr_t __guard attribute_relro;
+ # endif
+@@ -953,9 +949,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
+ stack_chk_guard = _dl_setup_stack_chk_guard ();
+ # ifdef THREAD_SET_STACK_GUARD
+ THREAD_SET_STACK_GUARD (stack_chk_guard);
+-# else
+- __stack_chk_guard = stack_chk_guard;
+ # endif
++ __stack_chk_guard = stack_chk_guard;
+ # ifdef __UCLIBC_HAS_SSP_COMPAT__
+ __guard = stack_chk_guard;
+ # endif
+diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c
+index 315365a..78cd058 100644
+--- a/libc/misc/internals/__uClibc_main.c
++++ b/libc/misc/internals/__uClibc_main.c
+@@ -46,12 +46,7 @@ void *__libc_stack_end = NULL;
+ # ifdef __UCLIBC_HAS_SSP__
+ # include <dl-osinfo.h>
+ static uintptr_t stack_chk_guard;
+-# ifndef THREAD_SET_STACK_GUARD
+-/* Only exported for architectures that don't store the stack guard canary
+- * in thread local area. */
+-/* for gcc-4.1 non-TLS */
+ uintptr_t __stack_chk_guard attribute_relro;
+-# endif
+ /* for gcc-3.x + Etoh ssp */
+ # ifdef __UCLIBC_HAS_SSP_COMPAT__
+ uintptr_t __guard attribute_relro;
+@@ -247,9 +242,8 @@ void __uClibc_init(void)
+ stack_chk_guard = _dl_setup_stack_chk_guard();
+ # ifdef THREAD_SET_STACK_GUARD
+ THREAD_SET_STACK_GUARD (stack_chk_guard);
+-# else
+- __stack_chk_guard = stack_chk_guard;
+ # endif
++ __stack_chk_guard = stack_chk_guard;
+ # ifdef __UCLIBC_HAS_SSP_COMPAT__
+ __guard = stack_chk_guard;
+ # endif
diff --git a/main/libc0.9.32/sha512-crypt.patch b/main/libc0.9.32/sha512-crypt.patch
new file mode 100644
index 0000000000..4f460cf5d9
--- /dev/null
+++ b/main/libc0.9.32/sha512-crypt.patch
@@ -0,0 +1,854 @@
+--- uClibc-0.9.32-rc2/libcrypt/Makefile.in
++++ uclibc.mod/libcrypt/Makefile.in
+@@ -19,7 +19,7 @@
+ libcrypt_OUT := $(top_builddir)libcrypt
+
+ libcrypt_SRC-y :=
+-libcrypt_SRC-$(UCLIBC_HAS_CRYPT_IMPL) += crypt.c des.c md5.c
++libcrypt_SRC-$(UCLIBC_HAS_CRYPT_IMPL) += crypt.c des.c md5.c sha512.c sha512-crypt.c
+ libcrypt_SRC-$(UCLIBC_HAS_CRYPT_STUB) += crypt_stub.c
+
+ libcrypt_SRC := $(addprefix $(libcrypt_DIR)/,$(libcrypt_SRC-y))
+--- uClibc-0.9.32-rc2/libcrypt/crypt.c
++++ uclibc.mod/libcrypt/crypt.c
+@@ -16,6 +16,8 @@
+ * instead of DES... */
+ if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$')
+ return __md5_crypt((unsigned char*)key, (unsigned char*)salt);
++ else if (salt[0]=='$' && salt[1]=='6' && salt[2]=='$')
++ return __sha512_crypt((unsigned char*)key, (unsigned char*)salt);
+ else
+ return __des_crypt((unsigned char*)key, (unsigned char*)salt);
+ }
+--- uClibc-0.9.32-rc2/libcrypt/libcrypt.h
++++ uclibc.mod/libcrypt/libcrypt.h
+@@ -9,6 +9,7 @@
+ #define __LIBCRYPT_H__
+
+ extern char *__md5_crypt(const unsigned char *pw, const unsigned char *salt) attribute_hidden;
++extern char *__sha512_crypt(const unsigned char *pw, const unsigned char *salt) attribute_hidden;
+ extern char *__des_crypt(const unsigned char *pw, const unsigned char *salt) attribute_hidden;
+
+ /* shut up gcc-4.x signed warnings */
+--- /dev/null
++++ uclibc.mod/libcrypt/sha512-crypt.c
+@@ -0,0 +1,419 @@
++/* One way encryption based on SHA512 sum.
++ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
++
++ The GNU C 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.
++
++ The GNU C 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 the GNU C Library; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/param.h>
++
++#include "sha512.h"
++
++
++#ifdef USE_NSS
++typedef int PRBool;
++# include <hasht.h>
++# include <nsslowhash.h>
++
++# define sha512_init_ctx(ctxp, nss_ctxp) \
++ do \
++ { \
++ if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgSHA512)) \
++ == NULL)) \
++ { \
++ if (nss_ctx != NULL) \
++ NSSLOWHASH_Destroy (nss_ctx); \
++ if (nss_alt_ctx != NULL) \
++ NSSLOWHASH_Destroy (nss_alt_ctx); \
++ return NULL; \
++ } \
++ NSSLOWHASH_Begin (nss_ctxp); \
++ } \
++ while (0)
++
++# define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \
++ NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len)
++
++# define sha512_finish_ctx(ctxp, nss_ctxp, result) \
++ do \
++ { \
++ unsigned int ret; \
++ NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result)); \
++ assert (ret == sizeof (result)); \
++ NSSLOWHASH_Destroy (nss_ctxp); \
++ nss_ctxp = NULL; \
++ } \
++ while (0)
++#else
++# define sha512_init_ctx(ctxp, nss_ctxp) \
++ __sha512_init_ctx (ctxp)
++
++# define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \
++ __sha512_process_bytes(buf, len, ctxp)
++
++# define sha512_finish_ctx(ctxp, nss_ctxp, result) \
++ __sha512_finish_ctx (ctxp, result)
++#endif
++
++
++/* Define our magic string to mark salt for SHA512 "encryption"
++ replacement. */
++static const char sha512_salt_prefix[] = "$6$";
++
++/* Prefix for optional rounds specification. */
++static const char sha512_rounds_prefix[] = "rounds=";
++
++/* Maximum salt string length. */
++#define SALT_LEN_MAX 16
++/* Default number of rounds if not explicitly specified. */
++#define ROUNDS_DEFAULT 5000
++/* Minimum number of rounds. */
++#define ROUNDS_MIN 1000
++/* Maximum number of rounds. */
++#define ROUNDS_MAX 999999999
++
++/* Table with characters for base64 transformation. */
++static const char b64t[64] =
++"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
++
++
++/* Prototypes for local functions. */
++extern char *__sha512_crypt_r (const char *key, const char *salt,
++ char *buffer, int buflen);
++extern char *__sha512_crypt (const char *key, const char *salt);
++
++
++char *
++__sha512_crypt_r (key, salt, buffer, buflen)
++ const char *key;
++ const char *salt;
++ char *buffer;
++ int buflen;
++{
++ unsigned char alt_result[64]
++ __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
++ unsigned char temp_result[64]
++ __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
++ size_t salt_len;
++ size_t key_len;
++ size_t cnt;
++ char *cp;
++ char *copied_key = NULL;
++ char *copied_salt = NULL;
++ char *p_bytes;
++ char *s_bytes;
++ /* Default number of rounds. */
++ size_t rounds = ROUNDS_DEFAULT;
++ bool rounds_custom = false;
++
++ /* Find beginning of salt string. The prefix should normally always
++ be present. Just in case it is not. */
++ if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
++ /* Skip salt prefix. */
++ salt += sizeof (sha512_salt_prefix) - 1;
++
++ if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
++ == 0)
++ {
++ const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
++ char *endp;
++ unsigned long int srounds = strtoul (num, &endp, 10);
++ if (*endp == '$')
++ {
++ salt = endp + 1;
++ rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX));
++ rounds_custom = true;
++ }
++ }
++
++ salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
++ key_len = strlen (key);
++
++ if ((key - (char *) 0) % __alignof__ (uint64_t) != 0)
++ {
++ char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
++ key = copied_key =
++ memcpy (tmp + __alignof__ (uint64_t)
++ - (tmp - (char *) 0) % __alignof__ (uint64_t),
++ key, key_len);
++ assert ((key - (char *) 0) % __alignof__ (uint64_t) == 0);
++ }
++
++ if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0)
++ {
++ char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t));
++ salt = copied_salt =
++ memcpy (tmp + __alignof__ (uint64_t)
++ - (tmp - (char *) 0) % __alignof__ (uint64_t),
++ salt, salt_len);
++ assert ((salt - (char *) 0) % __alignof__ (uint64_t) == 0);
++ }
++
++#ifdef USE_NSS
++ /* Initialize libfreebl3. */
++ NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
++ if (nss_ictx == NULL)
++ return NULL;
++ NSSLOWHASHContext *nss_ctx = NULL;
++ NSSLOWHASHContext *nss_alt_ctx = NULL;
++#else
++ struct sha512_ctx ctx;
++ struct sha512_ctx alt_ctx;
++#endif
++
++ /* Prepare for the real work. */
++ sha512_init_ctx (&ctx, nss_ctx);
++
++ /* Add the key string. */
++ sha512_process_bytes (key, key_len, &ctx, nss_ctx);
++
++ /* The last part is the salt string. This must be at most 16
++ characters and it ends at the first `$' character. */
++ sha512_process_bytes (salt, salt_len, &ctx, nss_ctx);
++
++
++ /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The
++ final result will be added to the first context. */
++ sha512_init_ctx (&alt_ctx, nss_alt_ctx);
++
++ /* Add key. */
++ sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
++
++ /* Add salt. */
++ sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
++
++ /* Add key again. */
++ sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
++
++ /* Now get result of this (64 bytes) and add it to the other
++ context. */
++ sha512_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);
++
++ /* Add for any character in the key one byte of the alternate sum. */
++ for (cnt = key_len; cnt > 64; cnt -= 64)
++ sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
++ sha512_process_bytes (alt_result, cnt, &ctx, nss_ctx);
++
++ /* Take the binary representation of the length of the key and for every
++ 1 add the alternate sum, for every 0 the key. */
++ for (cnt = key_len; cnt > 0; cnt >>= 1)
++ if ((cnt & 1) != 0)
++ sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
++ else
++ sha512_process_bytes (key, key_len, &ctx, nss_ctx);
++
++ /* Create intermediate result. */
++ sha512_finish_ctx (&ctx, nss_ctx, alt_result);
++
++ /* Start computation of P byte sequence. */
++ sha512_init_ctx (&alt_ctx, nss_alt_ctx);
++
++ /* For every character in the password add the entire password. */
++ for (cnt = 0; cnt < key_len; ++cnt)
++ sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
++
++ /* Finish the digest. */
++ sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);
++
++ /* Create byte sequence P. */
++ cp = p_bytes = alloca (key_len);
++ for (cnt = key_len; cnt >= 64; cnt -= 64)
++ cp = mempcpy (cp, temp_result, 64);
++ memcpy (cp, temp_result, cnt);
++
++ /* Start computation of S byte sequence. */
++ sha512_init_ctx (&alt_ctx, nss_alt_ctx);
++
++ /* For every character in the password add the entire password. */
++ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
++ sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
++
++ /* Finish the digest. */
++ sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);
++
++ /* Create byte sequence S. */
++ cp = s_bytes = alloca (salt_len);
++ for (cnt = salt_len; cnt >= 64; cnt -= 64)
++ cp = mempcpy (cp, temp_result, 64);
++ memcpy (cp, temp_result, cnt);
++
++ /* Repeatedly run the collected hash value through SHA512 to burn
++ CPU cycles. */
++ for (cnt = 0; cnt < rounds; ++cnt)
++ {
++ /* New context. */
++ sha512_init_ctx (&ctx, nss_ctx);
++
++ /* Add key or last result. */
++ if ((cnt & 1) != 0)
++ sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
++ else
++ sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
++
++ /* Add salt for numbers not divisible by 3. */
++ if (cnt % 3 != 0)
++ sha512_process_bytes (s_bytes, salt_len, &ctx, nss_ctx);
++
++ /* Add key for numbers not divisible by 7. */
++ if (cnt % 7 != 0)
++ sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
++
++ /* Add key or last result. */
++ if ((cnt & 1) != 0)
++ sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
++ else
++ sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
++
++ /* Create intermediate result. */
++ sha512_finish_ctx (&ctx, nss_ctx, alt_result);
++ }
++
++#ifdef USE_NSS
++ /* Free libfreebl3 resources. */
++ NSSLOW_Shutdown (nss_ictx);
++#endif
++
++ /* Now we can construct the result string. It consists of three
++ parts. */
++ cp = stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen));
++ buflen -= sizeof (sha512_salt_prefix) - 1;
++
++ if (rounds_custom)
++ {
++ int n = snprintf (cp, MAX (0, buflen), "%s%zu$",
++ sha512_rounds_prefix, rounds);
++ cp += n;
++ buflen -= n;
++ }
++
++ cp = stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
++ buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
++
++ if (buflen > 0)
++ {
++ *cp++ = '$';
++ --buflen;
++ }
++
++ void b64_from_24bit (unsigned int b2, unsigned int b1, unsigned int b0,
++ int n)
++ {
++ unsigned int w = (b2 << 16) | (b1 << 8) | b0;
++ while (n-- > 0 && buflen > 0)
++ {
++ *cp++ = b64t[w & 0x3f];
++ --buflen;
++ w >>= 6;
++ }
++ }
++
++ b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4);
++ b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4);
++ b64_from_24bit (alt_result[44], alt_result[2], alt_result[23], 4);
++ b64_from_24bit (alt_result[3], alt_result[24], alt_result[45], 4);
++ b64_from_24bit (alt_result[25], alt_result[46], alt_result[4], 4);
++ b64_from_24bit (alt_result[47], alt_result[5], alt_result[26], 4);
++ b64_from_24bit (alt_result[6], alt_result[27], alt_result[48], 4);
++ b64_from_24bit (alt_result[28], alt_result[49], alt_result[7], 4);
++ b64_from_24bit (alt_result[50], alt_result[8], alt_result[29], 4);
++ b64_from_24bit (alt_result[9], alt_result[30], alt_result[51], 4);
++ b64_from_24bit (alt_result[31], alt_result[52], alt_result[10], 4);
++ b64_from_24bit (alt_result[53], alt_result[11], alt_result[32], 4);
++ b64_from_24bit (alt_result[12], alt_result[33], alt_result[54], 4);
++ b64_from_24bit (alt_result[34], alt_result[55], alt_result[13], 4);
++ b64_from_24bit (alt_result[56], alt_result[14], alt_result[35], 4);
++ b64_from_24bit (alt_result[15], alt_result[36], alt_result[57], 4);
++ b64_from_24bit (alt_result[37], alt_result[58], alt_result[16], 4);
++ b64_from_24bit (alt_result[59], alt_result[17], alt_result[38], 4);
++ b64_from_24bit (alt_result[18], alt_result[39], alt_result[60], 4);
++ b64_from_24bit (alt_result[40], alt_result[61], alt_result[19], 4);
++ b64_from_24bit (alt_result[62], alt_result[20], alt_result[41], 4);
++ b64_from_24bit (0, 0, alt_result[63], 2);
++
++ if (buflen <= 0)
++ {
++ __set_errno (ERANGE);
++ buffer = NULL;
++ }
++ else
++ *cp = '\0'; /* Terminate the string. */
++
++ /* Clear the buffer for the intermediate result so that people
++ attaching to processes or reading core dumps cannot get any
++ information. We do it in this way to clear correct_words[]
++ inside the SHA512 implementation as well. */
++#ifndef USE_NSS
++ __sha512_init_ctx (&ctx);
++ __sha512_finish_ctx (&ctx, alt_result);
++ memset (&ctx, '\0', sizeof (ctx));
++ memset (&alt_ctx, '\0', sizeof (alt_ctx));
++#endif
++ memset (temp_result, '\0', sizeof (temp_result));
++ memset (p_bytes, '\0', key_len);
++ memset (s_bytes, '\0', salt_len);
++ if (copied_key != NULL)
++ memset (copied_key, '\0', key_len);
++ if (copied_salt != NULL)
++ memset (copied_salt, '\0', salt_len);
++
++ return buffer;
++}
++
++#ifndef _LIBC
++# define libc_freeres_ptr(decl) decl
++#endif
++libc_freeres_ptr (static char *buffer);
++
++/* This entry point is equivalent to the `crypt' function in Unix
++ libcs. */
++char *
++__sha512_crypt (const char *key, const char *salt)
++{
++ /* We don't want to have an arbitrary limit in the size of the
++ password. We can compute an upper bound for the size of the
++ result in advance and so we can prepare the buffer we pass to
++ `sha512_crypt_r'. */
++ static int buflen;
++ int needed = (sizeof (sha512_salt_prefix) - 1
++ + sizeof (sha512_rounds_prefix) + 9 + 1
++ + strlen (salt) + 1 + 86 + 1);
++
++ if (buflen < needed)
++ {
++ char *new_buffer = (char *) realloc (buffer, needed);
++ if (new_buffer == NULL)
++ return NULL;
++
++ buffer = new_buffer;
++ buflen = needed;
++ }
++
++ return __sha512_crypt_r (key, salt, buffer, buflen);
++}
++
++#ifndef _LIBC
++static void
++__attribute__ ((__destructor__))
++free_mem (void)
++{
++ free (buffer);
++}
++#endif
+--- /dev/null
++++ uclibc.mod/libcrypt/sha512.c
+@@ -0,0 +1,336 @@
++/* Functions to compute SHA512 message digest of files or memory blocks.
++ according to the definition of SHA512 in FIPS 180-2.
++ Copyright (C) 2007 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C 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.
++
++ The GNU C 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 the GNU C Library; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */
++
++#ifdef HAVE_CONFIG_H
++# include <config.h>
++#endif
++
++#include <endian.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include "sha512.h"
++
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++# ifdef _LIBC
++# include <byteswap.h>
++# define SWAP(n) bswap_64 (n)
++# else
++# define SWAP(n) \
++ (((n) << 56) \
++ | (((n) & 0xff00) << 40) \
++ | (((n) & 0xff0000) << 24) \
++ | (((n) & 0xff000000) << 8) \
++ | (((n) >> 8) & 0xff000000) \
++ | (((n) >> 24) & 0xff0000) \
++ | (((n) >> 40) & 0xff00) \
++ | ((n) >> 56))
++# endif
++#else
++# define SWAP(n) (n)
++#endif
++
++
++/* This array contains the bytes used to pad the buffer to the next
++ 64-byte boundary. (FIPS 180-2:5.1.2) */
++static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ };
++
++
++/* Constants for SHA512 from FIPS 180-2:4.2.3. */
++static const uint64_t K[80] =
++ {
++ UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
++ UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
++ UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
++ UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
++ UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
++ UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
++ UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
++ UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
++ UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
++ UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
++ UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
++ UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
++ UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
++ UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
++ UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
++ UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
++ UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
++ UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
++ UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
++ UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
++ UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
++ UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
++ UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
++ UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
++ UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
++ UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
++ UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
++ UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
++ UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
++ UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
++ UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
++ UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
++ UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
++ UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
++ UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
++ UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
++ UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
++ UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
++ UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
++ UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
++ };
++
++
++/* Process LEN bytes of BUFFER, accumulating context into CTX.
++ It is assumed that LEN % 128 == 0. */
++static void
++sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
++{
++ const uint64_t *words = buffer;
++ size_t nwords = len / sizeof (uint64_t);
++ uint64_t a = ctx->H[0];
++ uint64_t b = ctx->H[1];
++ uint64_t c = ctx->H[2];
++ uint64_t d = ctx->H[3];
++ uint64_t e = ctx->H[4];
++ uint64_t f = ctx->H[5];
++ uint64_t g = ctx->H[6];
++ uint64_t h = ctx->H[7];
++
++ /* First increment the byte count. FIPS 180-2 specifies the possible
++ length of the file up to 2^128 bits. Here we only compute the
++ number of bytes. Do a double word increment. */
++ ctx->total[0] += len;
++ if (ctx->total[0] < len)
++ ++ctx->total[1];
++
++ /* Process all bytes in the buffer with 128 bytes in each round of
++ the loop. */
++ while (nwords > 0)
++ {
++ uint64_t W[80];
++ uint64_t a_save = a;
++ uint64_t b_save = b;
++ uint64_t c_save = c;
++ uint64_t d_save = d;
++ uint64_t e_save = e;
++ uint64_t f_save = f;
++ uint64_t g_save = g;
++ uint64_t h_save = h;
++
++ /* Operators defined in FIPS 180-2:4.1.2. */
++#define Ch(x, y, z) ((x & y) ^ (~x & z))
++#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
++#define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
++#define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
++#define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
++#define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
++
++ /* It is unfortunate that C does not provide an operator for
++ cyclic rotation. Hope the C compiler is smart enough. */
++#define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
++
++ /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
++ for (unsigned int t = 0; t < 16; ++t)
++ {
++ W[t] = SWAP (*words);
++ ++words;
++ }
++ for (unsigned int t = 16; t < 80; ++t)
++ W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
++
++ /* The actual computation according to FIPS 180-2:6.3.2 step 3. */
++ for (unsigned int t = 0; t < 80; ++t)
++ {
++ uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
++ uint64_t T2 = S0 (a) + Maj (a, b, c);
++ h = g;
++ g = f;
++ f = e;
++ e = d + T1;
++ d = c;
++ c = b;
++ b = a;
++ a = T1 + T2;
++ }
++
++ /* Add the starting values of the context according to FIPS 180-2:6.3.2
++ step 4. */
++ a += a_save;
++ b += b_save;
++ c += c_save;
++ d += d_save;
++ e += e_save;
++ f += f_save;
++ g += g_save;
++ h += h_save;
++
++ /* Prepare for the next round. */
++ nwords -= 16;
++ }
++
++ /* Put checksum in context given as argument. */
++ ctx->H[0] = a;
++ ctx->H[1] = b;
++ ctx->H[2] = c;
++ ctx->H[3] = d;
++ ctx->H[4] = e;
++ ctx->H[5] = f;
++ ctx->H[6] = g;
++ ctx->H[7] = h;
++}
++
++
++/* Initialize structure containing state of computation.
++ (FIPS 180-2:5.3.3) */
++void
++__sha512_init_ctx (ctx)
++ struct sha512_ctx *ctx;
++{
++ ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
++ ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
++ ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
++ ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
++ ctx->H[4] = UINT64_C (0x510e527fade682d1);
++ ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
++ ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
++ ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
++
++ ctx->total[0] = ctx->total[1] = 0;
++ ctx->buflen = 0;
++}
++
++
++/* Process the remaining bytes in the internal buffer and the usual
++ prolog according to the standard and write the result to RESBUF.
++
++ IMPORTANT: On some systems it is required that RESBUF is correctly
++ aligned for a 32 bits value. */
++void *
++__sha512_finish_ctx (ctx, resbuf)
++ struct sha512_ctx *ctx;
++ void *resbuf;
++{
++ /* Take yet unprocessed bytes into account. */
++ uint64_t bytes = ctx->buflen;
++ size_t pad;
++
++ /* Now count remaining bytes. */
++ ctx->total[0] += bytes;
++ if (ctx->total[0] < bytes)
++ ++ctx->total[1];
++
++ pad = bytes >= 112 ? 128 + 112 - bytes : 112 - bytes;
++ memcpy (&ctx->buffer[bytes], fillbuf, pad);
++
++ /* Put the 128-bit file length in *bits* at the end of the buffer. */
++ *(uint64_t *) &ctx->buffer[bytes + pad + 8] = SWAP (ctx->total[0] << 3);
++ *(uint64_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
++ (ctx->total[0] >> 61));
++
++ /* Process last bytes. */
++ sha512_process_block (ctx->buffer, bytes + pad + 16, ctx);
++
++ /* Put result from CTX in first 64 bytes following RESBUF. */
++ for (unsigned int i = 0; i < 8; ++i)
++ ((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]);
++
++ return resbuf;
++}
++
++
++void
++__sha512_process_bytes (buffer, len, ctx)
++ const void *buffer;
++ size_t len;
++ struct sha512_ctx *ctx;
++{
++ /* When we already have some bits in our internal buffer concatenate
++ both inputs first. */
++ if (ctx->buflen != 0)
++ {
++ size_t left_over = ctx->buflen;
++ size_t add = 256 - left_over > len ? len : 256 - left_over;
++
++ memcpy (&ctx->buffer[left_over], buffer, add);
++ ctx->buflen += add;
++
++ if (ctx->buflen > 128)
++ {
++ sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);
++
++ ctx->buflen &= 127;
++ /* The regions in the following copy operation cannot overlap. */
++ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~127],
++ ctx->buflen);
++ }
++
++ buffer = (const char *) buffer + add;
++ len -= add;
++ }
++
++ /* Process available complete blocks. */
++ if (len >= 128)
++ {
++#if !_STRING_ARCH_unaligned
++/* To check alignment gcc has an appropriate operator. Other
++ compilers don't. */
++# if __GNUC__ >= 2
++# define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0)
++# else
++# define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint64_t) != 0)
++# endif
++ if (UNALIGNED_P (buffer))
++ while (len > 128)
++ {
++ sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128,
++ ctx);
++ buffer = (const char *) buffer + 128;
++ len -= 128;
++ }
++ else
++#endif
++ {
++ sha512_process_block (buffer, len & ~127, ctx);
++ buffer = (const char *) buffer + (len & ~127);
++ len &= 127;
++ }
++ }
++
++ /* Move remaining bytes into internal buffer. */
++ if (len > 0)
++ {
++ size_t left_over = ctx->buflen;
++
++ memcpy (&ctx->buffer[left_over], buffer, len);
++ left_over += len;
++ if (left_over >= 128)
++ {
++ sha512_process_block (ctx->buffer, 128, ctx);
++ left_over -= 128;
++ memcpy (ctx->buffer, &ctx->buffer[128], left_over);
++ }
++ ctx->buflen = left_over;
++ }
++}
+--- /dev/null
++++ uclibc.mod/libcrypt/sha512.h
+@@ -0,0 +1,58 @@
++/* Declaration of functions and data types used for SHA512 sum computing
++ library functions.
++ Copyright (C) 2007 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C 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.
++
++ The GNU C 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 the GNU C Library; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#ifndef _SHA512_H
++#define _SHA512_H 1
++
++#include <limits.h>
++#include <stdint.h>
++#include <stdio.h>
++
++
++/* Structure to save state of computation between the single steps. */
++struct sha512_ctx
++{
++ uint64_t H[8];
++
++ uint64_t total[2];
++ uint64_t buflen;
++ char buffer[256] __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
++};
++
++/* Initialize structure containing state of computation.
++ (FIPS 180-2: 5.3.3) */
++extern void __sha512_init_ctx (struct sha512_ctx *ctx) __THROW;
++
++/* Starting with the result of former calls of this function (or the
++ initialization function update the context for the next LEN bytes
++ starting at BUFFER.
++ It is NOT required that LEN is a multiple of 128. */
++extern void __sha512_process_bytes (const void *buffer, size_t len,
++ struct sha512_ctx *ctx) __THROW;
++
++/* Process the remaining bytes in the buffer and put result from CTX
++ in first 64 bytes following RESBUF.
++
++ IMPORTANT: On some systems it is required that RESBUF is correctly
++ aligned for a 64 bits value. */
++extern void *__sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
++ __THROW;
++
++#endif /* sha512.h */
diff --git a/main/libc0.9.32/uclibc-epoll_pwait-hack.patch b/main/libc0.9.32/uclibc-epoll_pwait-hack.patch
new file mode 100644
index 0000000000..7e28056848
--- /dev/null
+++ b/main/libc0.9.32/uclibc-epoll_pwait-hack.patch
@@ -0,0 +1,20 @@
+diff --git a/libc/sysdeps/linux/common/epoll.c b/libc/sysdeps/linux/common/epoll.c
+index 85b0cfd..8fff9e6 100644
+--- a/libc/sysdeps/linux/common/epoll.c
++++ b/libc/sysdeps/linux/common/epoll.c
+@@ -67,12 +67,13 @@ extern __typeof(epoll_pwait) __libc_epoll_pwait;
+ int __libc_epoll_pwait(int epfd, struct epoll_event *events, int maxevents,
+ int timeout, const sigset_t *set)
+ {
++ int n = _NSIG / 8;
+ if (SINGLE_THREAD_P)
+- return INLINE_SYSCALL(epoll_pwait, 6, epfd, events, maxevents, timeout, set, _NSIG / 8);
++ return INLINE_SYSCALL(epoll_pwait, 6, epfd, events, maxevents, timeout, set, n);
+ # ifdef __UCLIBC_HAS_THREADS_NATIVE__
+ else {
+ int oldtype = LIBC_CANCEL_ASYNC ();
+- int result = INLINE_SYSCALL(epoll_pwait, 6, epfd, events, maxevents, timeout, set, _NSIG / 8);
++ int result = INLINE_SYSCALL(epoll_pwait, 6, epfd, events, maxevents, timeout, set, n);
+ LIBC_CANCEL_RESET (oldtype);
+ return result;
+ }
diff --git a/main/libc0.9.32/uclibc-librt-asneeded-fix.patch b/main/libc0.9.32/uclibc-librt-asneeded-fix.patch
new file mode 100644
index 0000000000..d85af19f2a
--- /dev/null
+++ b/main/libc0.9.32/uclibc-librt-asneeded-fix.patch
@@ -0,0 +1,39 @@
+--- uClibc-0.9.32-rc3.orig/Makefile.in
++++ uClibc-0.9.32-rc3/Makefile.in
+@@ -340,6 +340,12 @@
+ echo "GROUP ( $(UBACKTRACE_ASNEEDED) )" >> $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so; \
+ fi
+ endif
++ifeq ($(UCLIBC_HAS_REALTIME),y)
++# Add the AS_NEEDED entry for librt.so
++ if [ -f $(top_builddir)lib/libc.so -a -f $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so ] ; then \
++ echo "GROUP ( $(LIBRT_ASNEEDED) )" >> $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so; \
++ fi
++endif
+ ifeq ($(UCLIBC_HAS_THREADS),y)
+ ifneq ($(LINUXTHREADS_OLD),y)
+ ifeq ($(HARDWIRED_ABSPATH),y)
+--- uClibc-0.9.32-rc3.orig/Rules.mak
++++ uClibc-0.9.32-rc3/Rules.mak
+@@ -119,6 +119,7 @@
+ LIBC := libc
+ SHARED_LIBNAME := $(LIBC).so.$(ABI_VERSION)
+ UBACKTRACE_DSO := libubacktrace.so.$(ABI_VERSION)
++LIBRT_DSO := librt.so.$(ABI_VERSION)
+ ifneq ($(findstring $(TARGET_ARCH) , hppa64 ia64 mips64 powerpc64 s390x sparc64 x86_64 ),)
+ UCLIBC_LDSO_NAME := ld64-uClibc
+ ARCH_NATIVE_BIT := 64
+@@ -542,6 +543,13 @@
+ export UBACKTRACE_ASNEEDED:=$(shell $(LD) --help 2>/dev/null | grep -q -- --as-needed && echo "AS_NEEDED ( $(UBACKTRACE_FULL_NAME) )" || echo "$(UBACKTRACE_FULL_NAME)")
+ else
+ export UBACKTRACE_ASNEEDED:=""
++endif
++ifeq ($(UCLIBC_HAS_REALTIME),y)
++# Only used in installed libc.so linker script
++LIBRT_FULL_NAME := $(RUNTIME_PREFIX)lib/$(LIBRT_DSO)
++export LIBRT_ASNEEDED:=$(shell $(LD) --help 2>/dev/null | grep -q -- --as-needed && echo "AS_NEEDED ( $(LIBRT_FULL_NAME) )" || echo "$(LIBRT_FULL_NAME)")
++else
++export LIBRT_ASNEEDED:=""
+ endif
+ endif
+
diff --git a/main/libc0.9.32/uclibc-resolv-cname-fix.diff b/main/libc0.9.32/uclibc-resolv-cname-fix.diff
new file mode 100644
index 0000000000..cf5e777f7e
--- /dev/null
+++ b/main/libc0.9.32/uclibc-resolv-cname-fix.diff
@@ -0,0 +1,19 @@
+diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
+index 1e394d4..03d68fe 100644
+--- a/libc/inet/resolv.c
++++ b/libc/inet/resolv.c
+@@ -3099,11 +3099,9 @@ int res_query(const char *dname, int class, int type,
+
+ free(a.dotted);
+
+- if (a.atype == type) { /* CNAME */
+- if (i > anslen)
+- i = anslen;
+- memcpy(answer, packet, i);
+- }
++ i = MIN(anslen, i);
++ memcpy(answer, packet, i);
++
+ free(packet);
+ return i;
+ }
diff --git a/main/libc0.9.32/uclibc-ubacktrace-asneeded-fix.patch b/main/libc0.9.32/uclibc-ubacktrace-asneeded-fix.patch
new file mode 100644
index 0000000000..8fc06508eb
--- /dev/null
+++ b/main/libc0.9.32/uclibc-ubacktrace-asneeded-fix.patch
@@ -0,0 +1,22 @@
+--- uClibc-0.9.32-rc3.orig/Makefile.in
++++ uClibc-0.9.32-rc3/Makefile.in
+@@ -336,7 +336,7 @@
+ endif
+ ifeq ($(UCLIBC_HAS_BACKTRACE),y)
+ # Add the AS_NEEDED entry for libubacktrace.so
+- if [ -f $(top_builddir)lib/libc.so -a -f $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR)/$(SHARED_LIBNAME) ] ; then \
++ if [ -f $(top_builddir)lib/libc.so -a -f $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so ] ; then \
+ echo "GROUP ( $(UBACKTRACE_ASNEEDED) )" >> $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so; \
+ fi
+ endif
+--- uClibc-0.9.32-rc3.orig/Rules.mak
++++ uClibc-0.9.32-rc3/Rules.mak
+@@ -118,7 +118,7 @@
+
+ LIBC := libc
+ SHARED_LIBNAME := $(LIBC).so.$(ABI_VERSION)
+-UBACKTRACE_DSO := libubacktrace.so.$(MAJOR_VERSION)
++UBACKTRACE_DSO := libubacktrace.so.$(ABI_VERSION)
+ ifneq ($(findstring $(TARGET_ARCH) , hppa64 ia64 mips64 powerpc64 s390x sparc64 x86_64 ),)
+ UCLIBC_LDSO_NAME := ld64-uClibc
+ ARCH_NATIVE_BIT := 64
diff --git a/main/libc0.9.32/uclibc-utils.trigger b/main/libc0.9.32/uclibc-utils.trigger
new file mode 100644
index 0000000000..072c3c7389
--- /dev/null
+++ b/main/libc0.9.32/uclibc-utils.trigger
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec /sbin/ldconfig -X
diff --git a/main/libc0.9.32/uclibcconfig.arm b/main/libc0.9.32/uclibcconfig.arm
new file mode 100644
index 0000000000..da17fec837
--- /dev/null
+++ b/main/libc0.9.32/uclibcconfig.arm
@@ -0,0 +1,267 @@
+#
+# Automatically generated make config: don't edit
+# Version: 0.9.32-rc3
+# Fri Mar 18 13:13:20 2011
+#
+# TARGET_alpha is not set
+TARGET_arm=y
+# TARGET_avr32 is not set
+# TARGET_bfin is not set
+# TARGET_cris is not set
+# TARGET_e1 is not set
+# TARGET_frv is not set
+# TARGET_h8300 is not set
+# TARGET_hppa is not set
+# TARGET_i386 is not set
+# TARGET_i960 is not set
+# TARGET_ia64 is not set
+# TARGET_m68k is not set
+# TARGET_microblaze is not set
+# TARGET_mips is not set
+# TARGET_nios is not set
+# TARGET_nios2 is not set
+# TARGET_powerpc is not set
+# TARGET_sh is not set
+# TARGET_sh64 is not set
+# TARGET_sparc is not set
+# TARGET_v850 is not set
+# TARGET_vax is not set
+# TARGET_x86_64 is not set
+# TARGET_xtensa is not set
+# TARGET_c6x is not set
+
+#
+# Target Architecture Features and Options
+#
+TARGET_ARCH="arm"
+FORCE_OPTIONS_FOR_ARCH=y
+# CONFIG_ARM_OABI is not set
+CONFIG_ARM_EABI=y
+CONFIG_GENERIC_ARM=y
+# CONFIG_ARM610 is not set
+# CONFIG_ARM710 is not set
+# CONFIG_ARM7TDMI is not set
+# CONFIG_ARM720T is not set
+# CONFIG_ARM920T is not set
+# CONFIG_ARM922T is not set
+# CONFIG_ARM926T is not set
+# CONFIG_ARM10T is not set
+# CONFIG_ARM1136JF_S is not set
+# CONFIG_ARM1176JZ_S is not set
+# CONFIG_ARM1176JZF_S is not set
+# CONFIG_ARM_CORTEX_M3 is not set
+# CONFIG_ARM_CORTEX_M1 is not set
+# CONFIG_ARM_SA110 is not set
+# CONFIG_ARM_SA1100 is not set
+# CONFIG_ARM_XSCALE is not set
+# CONFIG_ARM_IWMMXT is not set
+TARGET_SUBARCH=""
+
+#
+# Using ELF file format
+#
+ARCH_ANY_ENDIAN=y
+ARCH_LITTLE_ENDIAN=y
+# ARCH_WANTS_BIG_ENDIAN is not set
+ARCH_WANTS_LITTLE_ENDIAN=y
+ARCH_HAS_MMU=y
+ARCH_USE_MMU=y
+UCLIBC_HAS_FLOATS=y
+UCLIBC_HAS_FPU=y
+DO_C99_MATH=y
+DO_XSI_MATH=y
+UCLIBC_HAS_FENV=y
+KERNEL_HEADERS="/usr/include"
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+# HAVE_NO_PIC is not set
+DOPIC=y
+# ARCH_HAS_NO_SHARED is not set
+# ARCH_HAS_NO_LDSO is not set
+HAVE_SHARED=y
+FORCE_SHAREABLE_TEXT_SEGMENTS=y
+LDSO_LDD_SUPPORT=y
+LDSO_CACHE_SUPPORT=y
+LDSO_PRELOAD_ENV_SUPPORT=y
+# LDSO_PRELOAD_FILE_SUPPORT is not set
+LDSO_BASE_FILENAME="ld.so"
+UCLIBC_STATIC_LDCONFIG=y
+LDSO_RUNPATH=y
+LDSO_SEARCH_INTERP_PATH=y
+UCLIBC_CTOR_DTOR=y
+LDSO_GNU_HASH_SUPPORT=y
+# HAS_NO_THREADS is not set
+# LINUXTHREADS_OLD is not set
+# LINUXTHREADS_NEW is not set
+UCLIBC_HAS_THREADS_NATIVE=y
+UCLIBC_HAS_THREADS=y
+UCLIBC_HAS_TLS=y
+PTHREADS_DEBUG_SUPPORT=y
+UCLIBC_HAS_SYSLOG=y
+UCLIBC_HAS_LFS=y
+# MALLOC is not set
+# MALLOC_SIMPLE is not set
+MALLOC_STANDARD=y
+MALLOC_GLIBC_COMPAT=y
+UCLIBC_DYNAMIC_ATEXIT=y
+COMPAT_ATEXIT=y
+UCLIBC_SUSV3_LEGACY=y
+UCLIBC_SUSV3_LEGACY_MACROS=y
+UCLIBC_SUSV4_LEGACY=y
+# UCLIBC_STRICT_HEADERS is not set
+# UCLIBC_HAS_STUBS is not set
+UCLIBC_HAS_SHADOW=y
+UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y
+UCLIBC_HAS___PROGNAME=y
+UCLIBC_HAS_PTY=y
+ASSUME_DEVPTS=y
+UNIX98PTY_ONLY=y
+# UCLIBC_HAS_GETPT is not set
+UCLIBC_HAS_LIBUTIL=y
+UCLIBC_HAS_TM_EXTENSIONS=y
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+UCLIBC_FALLBACK_TO_ETC_LOCALTIME=y
+
+#
+# Advanced Library Settings
+#
+UCLIBC_PWD_BUFFER_SIZE=256
+UCLIBC_GRP_BUFFER_SIZE=256
+
+#
+# Support various families of functions
+#
+UCLIBC_LINUX_MODULE_24=y
+UCLIBC_LINUX_SPECIFIC=y
+UCLIBC_HAS_GNU_ERROR=y
+UCLIBC_BSD_SPECIFIC=y
+UCLIBC_HAS_BSD_ERR=y
+UCLIBC_HAS_OBSOLETE_BSD_SIGNAL=y
+UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL=y
+# UCLIBC_NTP_LEGACY is not set
+UCLIBC_SV4_DEPRECATED=y
+UCLIBC_HAS_REALTIME=y
+UCLIBC_HAS_ADVANCED_REALTIME=y
+UCLIBC_HAS_EPOLL=y
+UCLIBC_HAS_XATTR=y
+UCLIBC_HAS_PROFILING=y
+UCLIBC_HAS_CRYPT_IMPL=y
+UCLIBC_HAS_CRYPT=y
+UCLIBC_HAS_NETWORK_SUPPORT=y
+UCLIBC_HAS_SOCKET=y
+UCLIBC_HAS_IPV4=y
+UCLIBC_HAS_IPV6=y
+UCLIBC_HAS_RPC=y
+UCLIBC_HAS_FULL_RPC=y
+UCLIBC_HAS_REENTRANT_RPC=y
+UCLIBC_USE_NETLINK=y
+UCLIBC_SUPPORT_AI_ADDRCONFIG=y
+UCLIBC_HAS_BSD_RES_CLOSE=y
+UCLIBC_HAS_COMPAT_RES_STATE=y
+# UCLIBC_HAS_EXTRA_COMPAT_RES_STATE is not set
+UCLIBC_HAS_LIBRESOLV_STUB=y
+# UCLIBC_HAS_LIBNSL_STUB is not set
+
+#
+# String and Stdio Support
+#
+UCLIBC_HAS_STRING_GENERIC_OPT=y
+UCLIBC_HAS_STRING_ARCH_OPT=y
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+# UCLIBC_HAS_CTYPE_UNSAFE is not set
+UCLIBC_HAS_CTYPE_CHECKED=y
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+UCLIBC_HAS_HEXADECIMAL_FLOATS=y
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+# UCLIBC_HAS_SCANF_GLIBC_A_FLAG is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
+UCLIBC_HAS_STDIO_BUFSIZ_4096=y
+# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
+# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set
+UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
+UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
+UCLIBC_HAS_PRINTF_M_SPEC=y
+UCLIBC_HAS_ERRNO_MESSAGES=y
+# UCLIBC_HAS_SYS_ERRLIST is not set
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+# UCLIBC_HAS_SYS_SIGLIST is not set
+UCLIBC_HAS_GNU_GETOPT=y
+UCLIBC_HAS_STDIO_FUTEXES=y
+UCLIBC_HAS_GNU_GETSUBOPT=y
+
+#
+# Big and Tall
+#
+UCLIBC_HAS_REGEX=y
+UCLIBC_HAS_REGEX_OLD=y
+UCLIBC_HAS_FNMATCH=y
+# UCLIBC_HAS_FNMATCH_OLD is not set
+UCLIBC_HAS_WORDEXP=y
+UCLIBC_HAS_NFTW=y
+UCLIBC_HAS_FTW=y
+# UCLIBC_HAS_FTS is not set
+UCLIBC_HAS_GLOB=y
+UCLIBC_HAS_GNU_GLOB=y
+UCLIBC_HAS_UTMPX=y
+
+#
+# Library Installation Options
+#
+RUNTIME_PREFIX="/"
+DEVEL_PREFIX="/usr"
+MULTILIB_DIR="lib"
+# HARDWIRED_ABSPATH is not set=y
+
+#
+# Security options
+#
+# UCLIBC_BUILD_PIE is not set
+UCLIBC_HAS_ARC4RANDOM=y
+# HAVE_NO_SSP is not set
+UCLIBC_HAS_SSP=y
+UCLIBC_HAS_SSP_COMPAT=y
+# SSP_QUICK_CANARY is not set
+# PROPOLICE_BLOCK_ABRT is not set
+PROPOLICE_BLOCK_SEGV=y
+UCLIBC_BUILD_SSP=y
+UCLIBC_BUILD_RELRO=y
+UCLIBC_BUILD_NOW=y
+UCLIBC_BUILD_NOEXECSTACK=y
+
+#
+# uClibc development/debugging options
+#
+CROSS_COMPILER_PREFIX=""
+UCLIBC_EXTRA_CFLAGS=""
+# DODEBUG is not set
+DOSTRIP=y
+# DOASSERTS is not set
+# SUPPORT_LD_DEBUG is not set
+# SUPPORT_LD_DEBUG_EARLY is not set
+# UCLIBC_MALLOC_DEBUGGING is not set
+UCLIBC_HAS_BACKTRACE=y
+WARNINGS="-Wall"
+EXTRA_WARNINGS=y
+# DOMULTI is not set
+# UCLIBC_MJN3_ONLY is not set
diff --git a/main/libc0.9.32/uclibcconfig.i486 b/main/libc0.9.32/uclibcconfig.i486
new file mode 120000
index 0000000000..6ab0f7e5d3
--- /dev/null
+++ b/main/libc0.9.32/uclibcconfig.i486
@@ -0,0 +1 @@
+uclibcconfig.x86 \ No newline at end of file
diff --git a/main/libc0.9.32/uclibcconfig.powerpc b/main/libc0.9.32/uclibcconfig.powerpc
new file mode 100644
index 0000000000..e4d8779395
--- /dev/null
+++ b/main/libc0.9.32/uclibcconfig.powerpc
@@ -0,0 +1,251 @@
+#
+# Automatically generated make config: don't edit
+# Version: 0.9.32-rc3
+# Fri Mar 18 13:12:53 2011
+#
+# TARGET_alpha is not set
+# TARGET_arm is not set
+# TARGET_avr32 is not set
+# TARGET_bfin is not set
+# TARGET_cris is not set
+# TARGET_e1 is not set
+# TARGET_frv is not set
+# TARGET_h8300 is not set
+# TARGET_hppa is not set
+# TARGET_i386 is not set
+# TARGET_i960 is not set
+# TARGET_ia64 is not set
+# TARGET_m68k is not set
+# TARGET_microblaze is not set
+# TARGET_mips is not set
+# TARGET_nios is not set
+# TARGET_nios2 is not set
+TARGET_powerpc=y
+# TARGET_sh is not set
+# TARGET_sh64 is not set
+# TARGET_sparc is not set
+# TARGET_v850 is not set
+# TARGET_vax is not set
+# TARGET_x86_64 is not set
+# TARGET_xtensa is not set
+# TARGET_c6x is not set
+
+#
+# Target Architecture Features and Options
+#
+TARGET_ARCH="powerpc"
+FORCE_OPTIONS_FOR_ARCH=y
+CONFIG_CLASSIC=y
+# CONFIG_E500 is not set
+TARGET_SUBARCH="classic"
+
+#
+# Using ELF file format
+#
+ARCH_BIG_ENDIAN=y
+
+#
+# Using Big Endian
+#
+ARCH_HAS_MMU=y
+ARCH_USE_MMU=y
+UCLIBC_HAS_FLOATS=y
+UCLIBC_HAS_FPU=y
+DO_C99_MATH=y
+DO_XSI_MATH=y
+UCLIBC_HAS_FENV=y
+UCLIBC_HAS_LONG_DOUBLE_MATH=y
+KERNEL_HEADERS="/usr/include"
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+# HAVE_NO_PIC is not set
+DOPIC=y
+# ARCH_HAS_NO_SHARED is not set
+# ARCH_HAS_NO_LDSO is not set
+HAVE_SHARED=y
+FORCE_SHAREABLE_TEXT_SEGMENTS=y
+LDSO_LDD_SUPPORT=y
+LDSO_CACHE_SUPPORT=y
+LDSO_PRELOAD_ENV_SUPPORT=y
+# LDSO_PRELOAD_FILE_SUPPORT is not set
+LDSO_BASE_FILENAME="ld.so"
+UCLIBC_STATIC_LDCONFIG=y
+LDSO_RUNPATH=y
+LDSO_SEARCH_INTERP_PATH=y
+UCLIBC_CTOR_DTOR=y
+LDSO_GNU_HASH_SUPPORT=y
+# HAS_NO_THREADS is not set
+# LINUXTHREADS_OLD is not set
+# LINUXTHREADS_NEW is not set
+UCLIBC_HAS_THREADS_NATIVE=y
+UCLIBC_HAS_THREADS=y
+UCLIBC_HAS_TLS=y
+PTHREADS_DEBUG_SUPPORT=y
+UCLIBC_HAS_SYSLOG=y
+UCLIBC_HAS_LFS=y
+# MALLOC is not set
+# MALLOC_SIMPLE is not set
+MALLOC_STANDARD=y
+MALLOC_GLIBC_COMPAT=y
+UCLIBC_DYNAMIC_ATEXIT=y
+COMPAT_ATEXIT=y
+UCLIBC_SUSV3_LEGACY=y
+UCLIBC_SUSV3_LEGACY_MACROS=y
+UCLIBC_SUSV4_LEGACY=y
+# UCLIBC_STRICT_HEADERS is not set
+# UCLIBC_HAS_STUBS is not set
+UCLIBC_HAS_SHADOW=y
+UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y
+UCLIBC_HAS___PROGNAME=y
+UCLIBC_HAS_PTY=y
+ASSUME_DEVPTS=y
+UNIX98PTY_ONLY=y
+# UCLIBC_HAS_GETPT is not set
+UCLIBC_HAS_LIBUTIL=y
+UCLIBC_HAS_TM_EXTENSIONS=y
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+UCLIBC_FALLBACK_TO_ETC_LOCALTIME=y
+
+#
+# Advanced Library Settings
+#
+UCLIBC_PWD_BUFFER_SIZE=256
+UCLIBC_GRP_BUFFER_SIZE=256
+
+#
+# Support various families of functions
+#
+UCLIBC_LINUX_MODULE_24=y
+UCLIBC_LINUX_SPECIFIC=y
+UCLIBC_HAS_GNU_ERROR=y
+UCLIBC_BSD_SPECIFIC=y
+UCLIBC_HAS_BSD_ERR=y
+UCLIBC_HAS_OBSOLETE_BSD_SIGNAL=y
+UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL=y
+# UCLIBC_NTP_LEGACY is not set
+UCLIBC_SV4_DEPRECATED=y
+UCLIBC_HAS_REALTIME=y
+UCLIBC_HAS_ADVANCED_REALTIME=y
+UCLIBC_HAS_EPOLL=y
+UCLIBC_HAS_XATTR=y
+UCLIBC_HAS_PROFILING=y
+UCLIBC_HAS_CRYPT_IMPL=y
+UCLIBC_HAS_CRYPT=y
+UCLIBC_HAS_NETWORK_SUPPORT=y
+UCLIBC_HAS_SOCKET=y
+UCLIBC_HAS_IPV4=y
+UCLIBC_HAS_IPV6=y
+UCLIBC_HAS_RPC=y
+UCLIBC_HAS_FULL_RPC=y
+UCLIBC_HAS_REENTRANT_RPC=y
+UCLIBC_USE_NETLINK=y
+UCLIBC_SUPPORT_AI_ADDRCONFIG=y
+UCLIBC_HAS_BSD_RES_CLOSE=y
+UCLIBC_HAS_COMPAT_RES_STATE=y
+# UCLIBC_HAS_EXTRA_COMPAT_RES_STATE is not set
+UCLIBC_HAS_LIBRESOLV_STUB=y
+# UCLIBC_HAS_LIBNSL_STUB is not set
+
+#
+# String and Stdio Support
+#
+UCLIBC_HAS_STRING_GENERIC_OPT=y
+UCLIBC_HAS_STRING_ARCH_OPT=y
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+# UCLIBC_HAS_CTYPE_UNSAFE is not set
+UCLIBC_HAS_CTYPE_CHECKED=y
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+UCLIBC_HAS_HEXADECIMAL_FLOATS=y
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+# UCLIBC_HAS_SCANF_GLIBC_A_FLAG is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
+UCLIBC_HAS_STDIO_BUFSIZ_4096=y
+# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
+# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set
+UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
+UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
+UCLIBC_HAS_PRINTF_M_SPEC=y
+UCLIBC_HAS_ERRNO_MESSAGES=y
+# UCLIBC_HAS_SYS_ERRLIST is not set
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+# UCLIBC_HAS_SYS_SIGLIST is not set
+UCLIBC_HAS_GNU_GETOPT=y
+UCLIBC_HAS_STDIO_FUTEXES=y
+UCLIBC_HAS_GNU_GETSUBOPT=y
+
+#
+# Big and Tall
+#
+UCLIBC_HAS_REGEX=y
+UCLIBC_HAS_REGEX_OLD=y
+UCLIBC_HAS_FNMATCH=y
+# UCLIBC_HAS_FNMATCH_OLD is not set
+UCLIBC_HAS_WORDEXP=y
+UCLIBC_HAS_NFTW=y
+UCLIBC_HAS_FTW=y
+# UCLIBC_HAS_FTS is not set
+UCLIBC_HAS_GLOB=y
+UCLIBC_HAS_GNU_GLOB=y
+UCLIBC_HAS_UTMPX=y
+
+#
+# Library Installation Options
+#
+RUNTIME_PREFIX="/"
+DEVEL_PREFIX="/usr"
+MULTILIB_DIR="lib"
+# HARDWIRED_ABSPATH is not set=y
+
+#
+# Security options
+#
+# UCLIBC_BUILD_PIE is not set
+UCLIBC_HAS_ARC4RANDOM=y
+# HAVE_NO_SSP is not set
+UCLIBC_HAS_SSP=y
+UCLIBC_HAS_SSP_COMPAT=y
+# SSP_QUICK_CANARY is not set
+# PROPOLICE_BLOCK_ABRT is not set
+PROPOLICE_BLOCK_SEGV=y
+UCLIBC_BUILD_SSP=y
+UCLIBC_BUILD_RELRO=y
+UCLIBC_BUILD_NOW=y
+UCLIBC_BUILD_NOEXECSTACK=y
+
+#
+# uClibc development/debugging options
+#
+CROSS_COMPILER_PREFIX=""
+UCLIBC_EXTRA_CFLAGS=""
+# DODEBUG is not set
+DOSTRIP=y
+# DOASSERTS is not set
+# SUPPORT_LD_DEBUG is not set
+# SUPPORT_LD_DEBUG_EARLY is not set
+# UCLIBC_MALLOC_DEBUGGING is not set
+UCLIBC_HAS_BACKTRACE=y
+WARNINGS="-Wall"
+EXTRA_WARNINGS=y
+# DOMULTI is not set
+# UCLIBC_MJN3_ONLY is not set
diff --git a/main/libc0.9.32/uclibcconfig.x86 b/main/libc0.9.32/uclibcconfig.x86
new file mode 100644
index 0000000000..dcbe1d010b
--- /dev/null
+++ b/main/libc0.9.32/uclibcconfig.x86
@@ -0,0 +1,266 @@
+#
+# Automatically generated make config: don't edit
+# Version: 0.9.32
+# Tue Jun 14 09:35:04 2011
+#
+# TARGET_alpha is not set
+# TARGET_arm is not set
+# TARGET_avr32 is not set
+# TARGET_bfin is not set
+# TARGET_cris is not set
+# TARGET_e1 is not set
+# TARGET_frv is not set
+# TARGET_h8300 is not set
+# TARGET_hppa is not set
+TARGET_i386=y
+# TARGET_i960 is not set
+# TARGET_ia64 is not set
+# TARGET_m68k is not set
+# TARGET_microblaze is not set
+# TARGET_mips is not set
+# TARGET_nios is not set
+# TARGET_nios2 is not set
+# TARGET_powerpc is not set
+# TARGET_sh is not set
+# TARGET_sh64 is not set
+# TARGET_sparc is not set
+# TARGET_v850 is not set
+# TARGET_vax is not set
+# TARGET_x86_64 is not set
+# TARGET_xtensa is not set
+# TARGET_c6x is not set
+
+#
+# Target Architecture Features and Options
+#
+TARGET_ARCH="i386"
+FORCE_OPTIONS_FOR_ARCH=y
+# CONFIG_GENERIC_386 is not set
+# CONFIG_386 is not set
+CONFIG_486=y
+# CONFIG_586 is not set
+# CONFIG_586MMX is not set
+# CONFIG_686 is not set
+# CONFIG_PENTIUMII is not set
+# CONFIG_PENTIUMIII is not set
+# CONFIG_PENTIUM4 is not set
+# CONFIG_K6 is not set
+# CONFIG_K7 is not set
+# CONFIG_ELAN is not set
+# CONFIG_CRUSOE is not set
+# CONFIG_WINCHIPC6 is not set
+# CONFIG_WINCHIP2 is not set
+# CONFIG_CYRIXIII is not set
+# CONFIG_NEHEMIAH is not set
+TARGET_SUBARCH="i486"
+
+#
+# Using ELF file format
+#
+ARCH_LITTLE_ENDIAN=y
+
+#
+# Using Little Endian
+#
+ARCH_HAS_MMU=y
+ARCH_USE_MMU=y
+UCLIBC_HAS_FLOATS=y
+UCLIBC_HAS_FPU=y
+DO_C99_MATH=y
+DO_XSI_MATH=y
+UCLIBC_HAS_FENV=y
+UCLIBC_HAS_LONG_DOUBLE_MATH=y
+KERNEL_HEADERS="/usr/include"
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+# HAVE_NO_PIC is not set
+DOPIC=y
+# ARCH_HAS_NO_SHARED is not set
+# ARCH_HAS_NO_LDSO is not set
+HAVE_SHARED=y
+FORCE_SHAREABLE_TEXT_SEGMENTS=y
+LDSO_LDD_SUPPORT=y
+LDSO_CACHE_SUPPORT=y
+LDSO_PRELOAD_ENV_SUPPORT=y
+# LDSO_PRELOAD_FILE_SUPPORT is not set
+LDSO_BASE_FILENAME="ld.so"
+UCLIBC_STATIC_LDCONFIG=y
+LDSO_RUNPATH=y
+LDSO_SEARCH_INTERP_PATH=y
+UCLIBC_CTOR_DTOR=y
+LDSO_GNU_HASH_SUPPORT=y
+# HAS_NO_THREADS is not set
+# LINUXTHREADS_OLD is not set
+# LINUXTHREADS_NEW is not set
+UCLIBC_HAS_THREADS_NATIVE=y
+UCLIBC_HAS_THREADS=y
+UCLIBC_HAS_TLS=y
+PTHREADS_DEBUG_SUPPORT=y
+UCLIBC_HAS_SYSLOG=y
+UCLIBC_HAS_LFS=y
+# MALLOC is not set
+# MALLOC_SIMPLE is not set
+MALLOC_STANDARD=y
+MALLOC_GLIBC_COMPAT=y
+UCLIBC_DYNAMIC_ATEXIT=y
+COMPAT_ATEXIT=y
+UCLIBC_SUSV3_LEGACY=y
+UCLIBC_SUSV3_LEGACY_MACROS=y
+UCLIBC_SUSV4_LEGACY=y
+# UCLIBC_STRICT_HEADERS is not set
+# UCLIBC_HAS_STUBS is not set
+UCLIBC_HAS_SHADOW=y
+UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y
+UCLIBC_HAS___PROGNAME=y
+UCLIBC_HAS_PTY=y
+ASSUME_DEVPTS=y
+UNIX98PTY_ONLY=y
+# UCLIBC_HAS_GETPT is not set
+UCLIBC_HAS_LIBUTIL=y
+UCLIBC_HAS_TM_EXTENSIONS=y
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+UCLIBC_FALLBACK_TO_ETC_LOCALTIME=y
+
+#
+# Advanced Library Settings
+#
+UCLIBC_PWD_BUFFER_SIZE=256
+UCLIBC_GRP_BUFFER_SIZE=256
+
+#
+# Support various families of functions
+#
+UCLIBC_LINUX_MODULE_24=y
+UCLIBC_LINUX_SPECIFIC=y
+UCLIBC_HAS_GNU_ERROR=y
+UCLIBC_BSD_SPECIFIC=y
+UCLIBC_HAS_BSD_ERR=y
+UCLIBC_HAS_OBSOLETE_BSD_SIGNAL=y
+UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL=y
+# UCLIBC_NTP_LEGACY is not set
+UCLIBC_SV4_DEPRECATED=y
+UCLIBC_HAS_REALTIME=y
+UCLIBC_HAS_ADVANCED_REALTIME=y
+UCLIBC_HAS_EPOLL=y
+UCLIBC_HAS_XATTR=y
+UCLIBC_HAS_PROFILING=y
+UCLIBC_HAS_CRYPT_IMPL=y
+UCLIBC_HAS_CRYPT=y
+UCLIBC_HAS_NETWORK_SUPPORT=y
+UCLIBC_HAS_SOCKET=y
+UCLIBC_HAS_IPV4=y
+UCLIBC_HAS_IPV6=y
+UCLIBC_HAS_RPC=y
+UCLIBC_HAS_FULL_RPC=y
+UCLIBC_HAS_REENTRANT_RPC=y
+UCLIBC_USE_NETLINK=y
+UCLIBC_SUPPORT_AI_ADDRCONFIG=y
+UCLIBC_HAS_BSD_RES_CLOSE=y
+UCLIBC_HAS_COMPAT_RES_STATE=y
+# UCLIBC_HAS_EXTRA_COMPAT_RES_STATE is not set
+UCLIBC_HAS_LIBRESOLV_STUB=y
+# UCLIBC_HAS_LIBNSL_STUB is not set
+
+#
+# String and Stdio Support
+#
+UCLIBC_HAS_STRING_GENERIC_OPT=y
+UCLIBC_HAS_STRING_ARCH_OPT=y
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+# UCLIBC_HAS_CTYPE_UNSAFE is not set
+UCLIBC_HAS_CTYPE_CHECKED=y
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+UCLIBC_HAS_HEXADECIMAL_FLOATS=y
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+# UCLIBC_HAS_SCANF_GLIBC_A_FLAG is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
+UCLIBC_HAS_STDIO_BUFSIZ_4096=y
+# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
+# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set
+UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
+UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
+UCLIBC_HAS_PRINTF_M_SPEC=y
+UCLIBC_HAS_ERRNO_MESSAGES=y
+# UCLIBC_HAS_SYS_ERRLIST is not set
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+# UCLIBC_HAS_SYS_SIGLIST is not set
+UCLIBC_HAS_GNU_GETOPT=y
+UCLIBC_HAS_STDIO_FUTEXES=y
+UCLIBC_HAS_GNU_GETSUBOPT=y
+
+#
+# Big and Tall
+#
+UCLIBC_HAS_REGEX=y
+UCLIBC_HAS_REGEX_OLD=y
+UCLIBC_HAS_FNMATCH=y
+# UCLIBC_HAS_FNMATCH_OLD is not set
+UCLIBC_HAS_WORDEXP=y
+UCLIBC_HAS_NFTW=y
+UCLIBC_HAS_FTW=y
+# UCLIBC_HAS_FTS is not set
+UCLIBC_HAS_GLOB=y
+UCLIBC_HAS_GNU_GLOB=y
+UCLIBC_HAS_UTMPX=y
+
+#
+# Library Installation Options
+#
+RUNTIME_PREFIX="/"
+DEVEL_PREFIX="/usr"
+MULTILIB_DIR="lib"
+# HARDWIRED_ABSPATH is not set
+
+#
+# Security options
+#
+UCLIBC_BUILD_PIE=y
+UCLIBC_HAS_ARC4RANDOM=y
+# HAVE_NO_SSP is not set
+UCLIBC_HAS_SSP=y
+UCLIBC_HAS_SSP_COMPAT=y
+# SSP_QUICK_CANARY is not set
+# PROPOLICE_BLOCK_ABRT is not set
+PROPOLICE_BLOCK_SEGV=y
+UCLIBC_BUILD_SSP=y
+UCLIBC_BUILD_RELRO=y
+UCLIBC_BUILD_NOW=y
+UCLIBC_BUILD_NOEXECSTACK=y
+
+#
+# uClibc development/debugging options
+#
+CROSS_COMPILER_PREFIX=""
+UCLIBC_EXTRA_CFLAGS=""
+# DODEBUG is not set
+DOSTRIP=y
+# DOASSERTS is not set
+# SUPPORT_LD_DEBUG is not set
+# SUPPORT_LD_DEBUG_EARLY is not set
+# UCLIBC_MALLOC_DEBUGGING is not set
+UCLIBC_HAS_BACKTRACE=y
+WARNINGS="-Wall"
+EXTRA_WARNINGS=y
+# DOMULTI is not set
+# UCLIBC_MJN3_ONLY is not set
diff --git a/main/libc0.9.32/uclibcconfig.x86_64 b/main/libc0.9.32/uclibcconfig.x86_64
new file mode 100644
index 0000000000..29a81d3dd0
--- /dev/null
+++ b/main/libc0.9.32/uclibcconfig.x86_64
@@ -0,0 +1,248 @@
+#
+# Automatically generated make config: don't edit
+# Version: 0.9.32-rc3
+# Fri Mar 18 13:10:43 2011
+#
+# TARGET_alpha is not set
+# TARGET_arm is not set
+# TARGET_avr32 is not set
+# TARGET_bfin is not set
+# TARGET_cris is not set
+# TARGET_e1 is not set
+# TARGET_frv is not set
+# TARGET_h8300 is not set
+# TARGET_hppa is not set
+# TARGET_i386 is not set
+# TARGET_i960 is not set
+# TARGET_ia64 is not set
+# TARGET_m68k is not set
+# TARGET_microblaze is not set
+# TARGET_mips is not set
+# TARGET_nios is not set
+# TARGET_nios2 is not set
+# TARGET_powerpc is not set
+# TARGET_sh is not set
+# TARGET_sh64 is not set
+# TARGET_sparc is not set
+# TARGET_v850 is not set
+# TARGET_vax is not set
+TARGET_x86_64=y
+# TARGET_xtensa is not set
+# TARGET_c6x is not set
+
+#
+# Target Architecture Features and Options
+#
+TARGET_ARCH="x86_64"
+FORCE_OPTIONS_FOR_ARCH=y
+TARGET_SUBARCH=""
+
+#
+# Using ELF file format
+#
+ARCH_LITTLE_ENDIAN=y
+
+#
+# Using Little Endian
+#
+ARCH_HAS_MMU=y
+ARCH_USE_MMU=y
+UCLIBC_HAS_FLOATS=y
+UCLIBC_HAS_FPU=y
+DO_C99_MATH=y
+DO_XSI_MATH=y
+UCLIBC_HAS_FENV=y
+UCLIBC_HAS_LONG_DOUBLE_MATH=y
+KERNEL_HEADERS="/usr/include"
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+# HAVE_NO_PIC is not set
+DOPIC=y
+# ARCH_HAS_NO_SHARED is not set
+# ARCH_HAS_NO_LDSO is not set
+HAVE_SHARED=y
+FORCE_SHAREABLE_TEXT_SEGMENTS=y
+LDSO_LDD_SUPPORT=y
+LDSO_CACHE_SUPPORT=y
+LDSO_PRELOAD_ENV_SUPPORT=y
+# LDSO_PRELOAD_FILE_SUPPORT is not set
+LDSO_BASE_FILENAME="ld.so"
+UCLIBC_STATIC_LDCONFIG=y
+LDSO_RUNPATH=y
+LDSO_SEARCH_INTERP_PATH=y
+UCLIBC_CTOR_DTOR=y
+LDSO_GNU_HASH_SUPPORT=y
+# HAS_NO_THREADS is not set
+# LINUXTHREADS_OLD is not set
+# LINUXTHREADS_NEW is not set
+UCLIBC_HAS_THREADS_NATIVE=y
+UCLIBC_HAS_THREADS=y
+UCLIBC_HAS_TLS=y
+PTHREADS_DEBUG_SUPPORT=y
+UCLIBC_HAS_SYSLOG=y
+UCLIBC_HAS_LFS=y
+# MALLOC is not set
+# MALLOC_SIMPLE is not set
+MALLOC_STANDARD=y
+MALLOC_GLIBC_COMPAT=y
+UCLIBC_DYNAMIC_ATEXIT=y
+COMPAT_ATEXIT=y
+UCLIBC_SUSV3_LEGACY=y
+UCLIBC_SUSV3_LEGACY_MACROS=y
+UCLIBC_SUSV4_LEGACY=y
+# UCLIBC_STRICT_HEADERS is not set
+# UCLIBC_HAS_STUBS is not set
+UCLIBC_HAS_SHADOW=y
+UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y
+UCLIBC_HAS___PROGNAME=y
+UCLIBC_HAS_PTY=y
+ASSUME_DEVPTS=y
+UNIX98PTY_ONLY=y
+# UCLIBC_HAS_GETPT is not set
+UCLIBC_HAS_LIBUTIL=y
+UCLIBC_HAS_TM_EXTENSIONS=y
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+UCLIBC_FALLBACK_TO_ETC_LOCALTIME=y
+
+#
+# Advanced Library Settings
+#
+UCLIBC_PWD_BUFFER_SIZE=256
+UCLIBC_GRP_BUFFER_SIZE=256
+
+#
+# Support various families of functions
+#
+UCLIBC_LINUX_MODULE_24=y
+UCLIBC_LINUX_SPECIFIC=y
+UCLIBC_HAS_GNU_ERROR=y
+UCLIBC_BSD_SPECIFIC=y
+UCLIBC_HAS_BSD_ERR=y
+UCLIBC_HAS_OBSOLETE_BSD_SIGNAL=y
+UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL=y
+# UCLIBC_NTP_LEGACY is not set
+UCLIBC_SV4_DEPRECATED=y
+UCLIBC_HAS_REALTIME=y
+UCLIBC_HAS_ADVANCED_REALTIME=y
+UCLIBC_HAS_EPOLL=y
+UCLIBC_HAS_XATTR=y
+UCLIBC_HAS_PROFILING=y
+UCLIBC_HAS_CRYPT_IMPL=y
+UCLIBC_HAS_CRYPT=y
+UCLIBC_HAS_NETWORK_SUPPORT=y
+UCLIBC_HAS_SOCKET=y
+UCLIBC_HAS_IPV4=y
+UCLIBC_HAS_IPV6=y
+UCLIBC_HAS_RPC=y
+UCLIBC_HAS_FULL_RPC=y
+UCLIBC_HAS_REENTRANT_RPC=y
+UCLIBC_USE_NETLINK=y
+UCLIBC_SUPPORT_AI_ADDRCONFIG=y
+UCLIBC_HAS_BSD_RES_CLOSE=y
+UCLIBC_HAS_COMPAT_RES_STATE=y
+# UCLIBC_HAS_EXTRA_COMPAT_RES_STATE is not set
+UCLIBC_HAS_LIBRESOLV_STUB=y
+# UCLIBC_HAS_LIBNSL_STUB is not set
+
+#
+# String and Stdio Support
+#
+UCLIBC_HAS_STRING_GENERIC_OPT=y
+UCLIBC_HAS_STRING_ARCH_OPT=y
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+# UCLIBC_HAS_CTYPE_UNSAFE is not set
+UCLIBC_HAS_CTYPE_CHECKED=y
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+UCLIBC_HAS_HEXADECIMAL_FLOATS=y
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+# UCLIBC_HAS_SCANF_GLIBC_A_FLAG is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
+UCLIBC_HAS_STDIO_BUFSIZ_4096=y
+# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
+# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set
+UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
+UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
+UCLIBC_HAS_PRINTF_M_SPEC=y
+UCLIBC_HAS_ERRNO_MESSAGES=y
+# UCLIBC_HAS_SYS_ERRLIST is not set
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+# UCLIBC_HAS_SYS_SIGLIST is not set
+UCLIBC_HAS_GNU_GETOPT=y
+UCLIBC_HAS_STDIO_FUTEXES=y
+UCLIBC_HAS_GNU_GETSUBOPT=y
+
+#
+# Big and Tall
+#
+UCLIBC_HAS_REGEX=y
+UCLIBC_HAS_REGEX_OLD=y
+UCLIBC_HAS_FNMATCH=y
+# UCLIBC_HAS_FNMATCH_OLD is not set
+UCLIBC_HAS_WORDEXP=y
+UCLIBC_HAS_NFTW=y
+UCLIBC_HAS_FTW=y
+# UCLIBC_HAS_FTS is not set
+UCLIBC_HAS_GLOB=y
+UCLIBC_HAS_GNU_GLOB=y
+UCLIBC_HAS_UTMPX=y
+
+#
+# Library Installation Options
+#
+RUNTIME_PREFIX="/"
+DEVEL_PREFIX="/usr"
+MULTILIB_DIR="lib"
+# HARDWIRED_ABSPATH is not set=y
+
+#
+# Security options
+#
+UCLIBC_HAS_ARC4RANDOM=y
+# HAVE_NO_SSP is not set
+UCLIBC_HAS_SSP=y
+UCLIBC_HAS_SSP_COMPAT=y
+# SSP_QUICK_CANARY is not set
+# PROPOLICE_BLOCK_ABRT is not set
+PROPOLICE_BLOCK_SEGV=y
+UCLIBC_BUILD_SSP=y
+UCLIBC_BUILD_RELRO=y
+UCLIBC_BUILD_NOW=y
+UCLIBC_BUILD_NOEXECSTACK=y
+
+#
+# uClibc development/debugging options
+#
+CROSS_COMPILER_PREFIX=""
+UCLIBC_EXTRA_CFLAGS=""
+# DODEBUG is not set
+DOSTRIP=y
+# DOASSERTS is not set
+# SUPPORT_LD_DEBUG is not set
+# SUPPORT_LD_DEBUG_EARLY is not set
+# UCLIBC_MALLOC_DEBUGGING is not set
+UCLIBC_HAS_BACKTRACE=y
+WARNINGS="-Wall"
+EXTRA_WARNINGS=y
+# DOMULTI is not set
+# UCLIBC_MJN3_ONLY is not set
diff --git a/main/libcanberra/APKBUILD b/main/libcanberra/APKBUILD
new file mode 100644
index 0000000000..a08be00c90
--- /dev/null
+++ b/main/libcanberra/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=libcanberra
+pkgver=0.26
+pkgrel=3
+pkgdesc="simple audio library for GTK applications"
+url="http://0pointer.de/lennart/projects/libcanberra/"
+license="LGPL"
+depends=
+makedepends="gtk+-dev libogg-dev libvorbis-dev alsa-lib-dev libtool"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://0pointer.de/lennart/projects/$pkgname/$pkgname-$pkgver.tar.gz"
+arch="all"
+
+depends_dev="$makedepends"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="ee2c66ada7c851a4e7b6eb1682285a24 libcanberra-0.26.tar.gz"
diff --git a/main/libcap-ng/APKBUILD b/main/libcap-ng/APKBUILD
new file mode 100644
index 0000000000..853baa898a
--- /dev/null
+++ b/main/libcap-ng/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libcap-ng
+pkgver=0.6.4
+pkgrel=2
+pkgdesc="posix capabilities library"
+url="http://people.redhat.com/sgrubb/libcap-ng/index.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="python"
+install=
+subpackages="$pkgname-dev $pkgname-doc $pkgname-utils"
+source="http://people.redhat.com/sgrubb/libcap-ng/libcap-ng-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+utils() {
+ pkgdesc="posix capabilities utils"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/* "$subpkgdir"/usr/bin/
+}
+
+md5sums="ae817cd585ca11db257330b392003ed6 libcap-ng-0.6.4.tar.gz"
diff --git a/main/libcap/APKBUILD b/main/libcap/APKBUILD
new file mode 100644
index 0000000000..37af199ebc
--- /dev/null
+++ b/main/libcap/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libcap
+pkgver=2.21
+pkgrel=0
+pkgdesc="POSIX 1003.1e capabilities"
+arch="all"
+license="GPL"
+url="http://www.friedhoff.org/posixfilecaps.html"
+depends=
+makedepends="perl"
+source="http://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/$pkgname-$pkgver.tar.gz
+ "
+subpackages="$pkgname-doc $pkgname-dev"
+
+build ()
+{
+ cd "$srcdir/$pkgname-$pkgver"
+ make lib=/lib prefix=/usr LIBATTR=no DESTDIR="$pkgdir"
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make lib=/lib prefix=/usr LIBATTR=no DESTDIR="$pkgdir" install
+}
+md5sums="61966ef40f2dee8731b69db895e4548d libcap-2.21.tar.gz"
diff --git a/main/libcddb/APKBUILD b/main/libcddb/APKBUILD
new file mode 100644
index 0000000000..482702da7a
--- /dev/null
+++ b/main/libcddb/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=libcddb
+pkgver=1.3.2
+pkgrel=2
+pkgdesc="Library that implements the different protocols (CDDBP, HTTP, SMTP) to access data on a CDDB server (e.g. http://freedb.org)."
+url="http://sourceforge.net/projects/libcddb/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+if [ "$ALPINE_LIBC" != "eglibc" ]; then
+ makedepends="libiconv-dev"
+fi
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="8bb4a6f542197e8e9648ae597cd6bc8a libcddb-1.3.2.tar.bz2"
diff --git a/main/libcdio/APKBUILD b/main/libcdio/APKBUILD
new file mode 100644
index 0000000000..5931a87a19
--- /dev/null
+++ b/main/libcdio/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=libcdio
+pkgver=0.82
+pkgrel=2
+pkgdesc="GNU Compact Disc Input and Control Library"
+url="http://www.gnu.org/software/libcdio/"
+arch="all"
+license="GPL3"
+depends=
+makedepends="libcddb-dev ncurses-dev"
+if [ "$ALPINE_LIBC" != "eglibc" ]; then
+ makedepends="$makedepends libiconv-dev"
+fi
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnu.org/gnu/libcdio/${pkgname}-${pkgver}.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-vcd-info \
+ --enable-cpp-progs
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="1c29b18e01ab2b966162bc727bf3c360 libcdio-0.82.tar.gz"
diff --git a/main/libconfig/APKBUILD b/main/libconfig/APKBUILD
new file mode 100644
index 0000000000..8535c3c7f2
--- /dev/null
+++ b/main/libconfig/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libconfig
+pkgver=1.4.7
+pkgrel=1
+pkgdesc="a simple library for manipulating structured configuration files"
+url="http://www.hyperrealm.com/libconfig/"
+arch="all"
+license='LGPL'
+depends=
+makedepends=
+source="http://www.hyperrealm.com/$pkgname/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-doc $pkgname-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --disable-cxx
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir/" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="d57da7a91aadbfd53afedb5c1bade5f4 libconfig-1.4.7.tar.gz"
diff --git a/main/libcroco/APKBUILD b/main/libcroco/APKBUILD
new file mode 100644
index 0000000000..3fcb647a86
--- /dev/null
+++ b/main/libcroco/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libcroco
+pkgver=0.6.2
+pkgrel=5
+pkgdesc="GNOME CSS2 parsing and manipulation toolkit"
+url="http://www.gnome.org"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev"
+depends=
+makedepends="glib-dev libxml2-dev pkgconfig"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/0.6/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev libxml2-dev pkgconfig"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="1429c597aa4b75fc610ab3a542c99209 libcroco-0.6.2.tar.bz2"
diff --git a/main/libcue/APKBUILD b/main/libcue/APKBUILD
new file mode 100644
index 0000000000..0972f23880
--- /dev/null
+++ b/main/libcue/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=libcue
+pkgver=1.4.0
+pkgrel=1
+pkgdesc="library for parsing cue files"
+url="http://libcue.sourceforge.net/"
+license="GPL"
+arch="all"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="5f5045f00e6ac92d9a057fe5b0982c69 libcue-1.4.0.tar.bz2"
diff --git a/main/libdaemon/APKBUILD b/main/libdaemon/APKBUILD
new file mode 100644
index 0000000000..bac12d55ac
--- /dev/null
+++ b/main/libdaemon/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libdaemon
+pkgver=0.14
+pkgrel=1
+pkgdesc="A lightweight C library which eases the writing of UNIX daemons"
+url="http://0pointer.de/lennart/projects/libdaemon/"
+arch="all"
+license="LGPL"
+depends=""
+makedepends=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://0pointer.de/lennart/projects/libdaemon/libdaemon-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build () {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --localstatedir=/var \
+ --disable-lynx \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="509dc27107c21bcd9fbf2f95f5669563 libdaemon-0.14.tar.gz"
diff --git a/main/libdc1394/APKBUILD b/main/libdc1394/APKBUILD
new file mode 100644
index 0000000000..93b33d2c2e
--- /dev/null
+++ b/main/libdc1394/APKBUILD
@@ -0,0 +1,56 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libdc1394
+pkgver=2.1.3
+pkgrel=2
+pkgdesc="High level programming interface to control IEEE 1394 based cameras"
+url="http://damien.douxchamps.net/ieee1394/libdc1394/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="libusb-dev libraw1394-dev"
+makedepends="$depends_dev autoconf automake libtool"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/project/libdc1394/libdc1394-2/libdc1394-$pkgver.tar.gz
+ conditional-dc1394_vloopback.patch"
+
+_builddir="$srcdir"/libdc1394-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ libtoolize --force && aclocal && autoconf && automake
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+# there is on ly one tool and its only 4k...
+#tools() {
+# pkgdesc="Tools to use with $pkgname"
+# replaces="$pkgname"
+# mkdir -p "$subpkgdir"/usr/
+# mv "$pkgdir"/usr/bin "$subpkgdir"/usr
+#}
+
+md5sums="d8b2cbfae1b329fdeaa638da80427334 libdc1394-2.1.3.tar.gz
+33a30ef4e4a881707011ff4554c57c38 conditional-dc1394_vloopback.patch"
diff --git a/main/libdc1394/conditional-dc1394_vloopback.patch b/main/libdc1394/conditional-dc1394_vloopback.patch
new file mode 100644
index 0000000000..308d539636
--- /dev/null
+++ b/main/libdc1394/conditional-dc1394_vloopback.patch
@@ -0,0 +1,36 @@
+From: David Moore <david.moore@gmail.com>
+Date: Mon, 28 Mar 2011 05:48:15 +0000 (-0700)
+Subject: Conditionally compile dc1394_vloopback only when linux/videodev.h exists
+X-Git-Url: http://libdc1394.git.sourceforge.net/git/gitweb.cgi?p=libdc1394%2Flibdc1394;a=commitdiff_plain;h=2ee7e7f98dd6225b40d5cd570c240504be7bc86a
+
+Conditionally compile dc1394_vloopback only when linux/videodev.h exists
+---
+
+diff --git a/configure.in b/libdc1394/configure.in
+index 69babab..bdddc9b 100644
+--- a/configure.in
++++ b/configure.in
+@@ -75,6 +75,9 @@ AM_CONDITIONAL(HAVE_WINDOWS, test x$have_windows = xtrue)
+ AM_CONDITIONAL(HAVE_LIBRAW1394, test x$libraw1394 = xtrue)
+ AM_CONDITIONAL(HAVE_LIBUSB, test "x$LIBUSB_LIBS" != "x")
+
++AC_CHECK_HEADER([linux/videodev.h], [have_videodev=true])
++AM_CONDITIONAL(HAVE_VIDEODEV, test x$have_videodev = xtrue)
++
+ AC_ARG_ENABLE([examples], [AS_HELP_STRING([--disable-examples], [don't build example programs])], [build_examples=$enableval], [build_examples=true])
+
+ AM_CONDITIONAL(MAKE_EXAMPLES, test x$build_examples = xtrue)
+diff --git a/libdc1394/examples/Makefile.am b/libdc1394/examples/Makefile.am
+index fcebf18..035612e 100644
+--- a/examples/Makefile.am
++++ b/examples/Makefile.am
+@@ -8,7 +8,9 @@ A = grab_gray_image grab_partial_image grab_color_image \
+ B = dc1394_reset_bus
+
+ if HAVE_LINUX
++if HAVE_VIDEODEV
+ B += dc1394_vloopback
++endif
+ if HAVE_XV
+ A += dc1394_multiview
+ endif
diff --git a/main/libdnet/APKBUILD b/main/libdnet/APKBUILD
new file mode 100644
index 0000000000..aed8efb404
--- /dev/null
+++ b/main/libdnet/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libdnet
+pkgver=1.12
+pkgrel=5
+pkgdesc="A simplified, portable interface to several low-level networking routines"
+url="http://code.google.com/p/libdnet/"
+arch="all"
+license="BSD"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=""
+makedepends="autoconf automake libtool"
+install=
+source="http://$pkgname.googlecode.com/files/$pkgname-$pkgver.tgz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ # the libtool script does not add .so extention to we generate
+ # new libtool
+ aclocal -I config && autoconf && automake && libtoolize || return 1
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --without-python
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="9253ef6de1b5e28e9c9a62b882e44cc9 libdnet-1.12.tgz"
diff --git a/main/libdrm/APKBUILD b/main/libdrm/APKBUILD
new file mode 100644
index 0000000000..a39c52375a
--- /dev/null
+++ b/main/libdrm/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libdrm
+pkgver=2.4.25
+pkgrel=1
+pkgdesc="Userspace interface to kernel DRM services"
+url="http://dri.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig libpthread-stubs udev-dev"
+subpackages="$pkgname-dev"
+source="http://dri.freedesktop.org/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-udev \
+ --enable-nouveau-experimental-api || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="f53dc4c72109b17908e4113c3b8addfe libdrm-2.4.25.tar.bz2"
diff --git a/main/libdv/APKBUILD b/main/libdv/APKBUILD
new file mode 100644
index 0000000000..dcf10dd9f7
--- /dev/null
+++ b/main/libdv/APKBUILD
@@ -0,0 +1,61 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libdv
+pkgver=1.0.0
+pkgrel=1
+pkgdesc="Software decoder for DV format video"
+url="http://libdv.sourceforge.net/"
+arch="all"
+license="LGPLv2+"
+depends=
+makedepends="gtk+-dev libxv-dev sdl-dev autoconf automake libtool"
+install=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-tools"
+source="http://downloads.sourceforge.net/libdv/libdv-$pkgver.tar.gz
+ libdv-0.104-no-exec-stack.patch
+ libdv-1.0.0-dso-linking.patch
+ libdv-1.0.0-pic.patch
+ libdv-1.0.0-gtk2.patch
+ "
+
+_builddir="$srcdir"/libdv-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ libtoolize && autoreconf
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ --with-pic \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+tools() {
+ pkgdesc="Basic tools to manipulate Digital Video streams"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="f895162161cfa4bb4a94c070a7caa6c7 libdv-1.0.0.tar.gz
+e1cf9483fe9efdab5e2326fccbdb7ed5 libdv-0.104-no-exec-stack.patch
+9e3a12489495e01ad0ddf5a3ea2cef7f libdv-1.0.0-dso-linking.patch
+4fb792fd927a7abbc0e2ab9a8e96df53 libdv-1.0.0-pic.patch
+0498e719e3ed660a97b889b0502a4cb8 libdv-1.0.0-gtk2.patch"
diff --git a/main/libdv/libdv-0.104-no-exec-stack.patch b/main/libdv/libdv-0.104-no-exec-stack.patch
new file mode 100644
index 0000000000..edf917c370
--- /dev/null
+++ b/main/libdv/libdv-0.104-no-exec-stack.patch
@@ -0,0 +1,137 @@
+Make sure that the asm files don't incorrectly trigger an executable
+stack marking in the final shared library. That's bad, mmmkay.
+
+Upstream has already fixed this in their cvs.
+
+--- a/libdv/dct_block_mmx.S
++++ b/libdv/dct_block_mmx.S
+@@ -1207,3 +1207,7 @@ _dv_dct_block_mmx_postscale_248:
+ popl %esi
+ popl %ebp
+ ret
++
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/dct_block_mmx_x86_64.S
++++ b/libdv/dct_block_mmx_x86_64.S
+@@ -1197,3 +1197,7 @@ _dv_dct_block_mmx_x86_64_postscale_248:
+ pop %r12
+
+ ret
++
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/encode_x86.S
++++ b/libdv/encode_x86.S
+@@ -599,3 +599,6 @@ _dv_need_dct_248_mmx_rows:
+
+
+
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/encode_x86_64.S
++++ b/libdv/encode_x86_64.S
+@@ -600,3 +600,6 @@ _dv_need_dct_248_mmx_x86_64_rows:
+
+
+
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/idct_block_mmx.S
++++ b/libdv/idct_block_mmx.S
+@@ -648,3 +648,6 @@ x0:
+ .long 0,0
+ .align 8
+
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/idct_block_mmx_x86_64.S
++++ b/libdv/idct_block_mmx_x86_64.S
+@@ -653,3 +653,6 @@ x0:
+ .long 0,0
+ .align 8
+
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/quant_x86.S
++++ b/libdv/quant_x86.S
+@@ -454,3 +454,6 @@ _dv_quant_x86:
+
+
+
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/quant_x86_64.S
++++ b/libdv/quant_x86_64.S
+@@ -459,3 +459,6 @@ _dv_quant_x86_64:
+
+
+
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/rgbtoyuv.S
++++ b/libdv/rgbtoyuv.S
+@@ -1430,3 +1430,6 @@ video_copy_ntsc_c_block_mmx_loop:
+
+
+
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/rgbtoyuv_x86_64.S
++++ b/libdv/rgbtoyuv_x86_64.S
+@@ -1370,3 +1370,6 @@ video_copy_ntsc_c_block_mmx_loop:
+
+
+
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/transpose_x86.S
++++ b/libdv/transpose_x86.S
+@@ -188,3 +188,7 @@ popl %esi
+ popl %ebp
+
+ ret $0
++
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/transpose_x86_64.S
++++ b/libdv/transpose_x86_64.S
+@@ -188,3 +188,7 @@ all_done_ready_to_exit:
+ pop %r12
+
+ ret $0
++
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/vlc_x86.S
++++ b/libdv/vlc_x86.S
+@@ -585,3 +585,7 @@ mod_12:
+ .align 16
+ const_f_0_0_0:
+ .short 0xffff,0,0,0
++
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- a/libdv/vlc_x86_64.S
++++ b/libdv/vlc_x86_64.S
+@@ -671,3 +671,7 @@ mod_12:
+ .align 16
+ const_f_0_0_0:
+ .short 0xffff,0,0,0
++
++#ifdef __ELF__
++.section .note.GNU-stack,"",@progbits
++#endif
diff --git a/main/libdv/libdv-1.0.0-dso-linking.patch b/main/libdv/libdv-1.0.0-dso-linking.patch
new file mode 100644
index 0000000000..ced01f2b87
--- /dev/null
+++ b/main/libdv/libdv-1.0.0-dso-linking.patch
@@ -0,0 +1,12 @@
+We now need to explicitly link to libraries that we use because we can no
+longer depend on our dependencies to pull them in for us. See
+http://fedoraproject.org/wiki/UnderstandingDSOLinkChange
+
+--- libdv-1.0.0/playdv/#Makefile.am~ 2010-02-15 14:49:06.000000000 -0500
++++ libdv-1.0.0/playdv/Makefile.am 2010-02-15 14:49:06.000000000 -0500
+@@ -15,4 +15,4 @@ bin_PROGRAMS= playdv
+ noinst_HEADERS= display.h oss.h
+
+ playdv_SOURCES= playdv.c display.c display.h oss.c
+-playdv_LDADD= $(SDL_LIBS) $(GTK_LIBS) $(XV_LIB) ../libdv/libdv.la $(POPT_LIB)
++playdv_LDADD= $(SDL_LIBS) $(GTK_LIBS) $(XV_LIB) ../libdv/libdv.la $(POPT_LIB) -lX11 -lXext
diff --git a/main/libdv/libdv-1.0.0-gtk2.patch b/main/libdv/libdv-1.0.0-gtk2.patch
new file mode 100644
index 0000000000..ca93dc5544
--- /dev/null
+++ b/main/libdv/libdv-1.0.0-gtk2.patch
@@ -0,0 +1,11 @@
+--- libdv-1.0.0/configure.ac.orig 2007-01-19 15:48:43.000000000 -0500
++++ libdv-1.0.0/configure.ac 2007-01-19 15:50:08.000000000 -0500
+@@ -162,7 +162,7 @@
+ dnl Checks for libraries.
+ have_gtk="false"
+ if $use_gtk; then
+- REQUIRES='glib >= 1.2.4 gtk+ >= 1.2.4'
++ REQUIRES='glib-2.0 >= 2.1.0 gtk+-x11-2.0 >= 2.1.0'
+ PKG_CHECK_MODULES(GTK,$REQUIRES,have_gtk="true",have_gtk="false")
+ AC_DEFINE(HAVE_GTK)
+ fi
diff --git a/main/libdv/libdv-1.0.0-pic.patch b/main/libdv/libdv-1.0.0-pic.patch
new file mode 100644
index 0000000000..25cc11dca7
--- /dev/null
+++ b/main/libdv/libdv-1.0.0-pic.patch
@@ -0,0 +1,1634 @@
+Patch downloaded from
+http://bugs.gentoo.org/show_bug.cgi?id=121871
+http://bugs.gentoo.org/attachment.cgi?id=98094
+
+--- libdv-0.104-old/libdv/asm_common.S
++++ libdv-0.104/libdv/asm_common.S
+@@ -0,0 +1,29 @@
++/* public domain, do what you want */
++
++#ifdef __PIC__
++# define MUNG(sym) sym##@GOTOFF(%ebp)
++# define MUNG_ARR(sym, args...) sym##@GOTOFF(%ebp,##args)
++#else
++# define MUNG(sym) sym
++# define MUNG_ARR(sym, args...) sym(,##args)
++#endif
++
++#ifdef __PIC__
++# undef __i686 /* gcc define gets in our way */
++# define LOAD_PIC_REG(reg) \
++ .ifndef __i686.get_pc_thunk.reg; \
++ .section .gnu.linkonce.t.__i686.get_pc_thunk.reg,"ax",@progbits; \
++ .global __i686.get_pc_thunk.reg; \
++ .hidden __i686.get_pc_thunk.reg; \
++ .type __i686.get_pc_thunk.reg,@function; \
++ __i686.get_pc_thunk.reg: \
++ movl (%esp), %e##reg; \
++ ret; \
++ .size __i686.get_pc_thunk.reg,.-__i686.get_pc_thunk.reg; \
++ .previous; \
++ .endif; \
++ call __i686.get_pc_thunk.reg; \
++ addl $_GLOBAL_OFFSET_TABLE_, %e##reg
++#else
++# define LOAD_PIC_REG(reg)
++#endif
+--- libdv-0.104-old/libdv/dct_block_mmx.S
++++ libdv-0.104/libdv/dct_block_mmx.S
+@@ -53,19 +53,22 @@ scratch2: .quad 0
+
+ .section .note.GNU-stack, "", @progbits
+
++#include "asm_common.S"
++
+ .text
+
+ .align 8
+ .global _dv_dct_88_block_mmx
+ .hidden _dv_dct_88_block_mmx
+ .type _dv_dct_88_block_mmx,@function
+ _dv_dct_88_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+
+- movl 8(%ebp), %esi # source
++ LOAD_PIC_REG(bp)
++
++ movl 12(%esp), %esi # source
+
+ # column 0
+ movq 16*0(%esi), %mm0 # v0
+@@ -86,22 +91,22 @@ _dv_dct_88_block_mmx:
+
+ movq 16*3(%esi), %mm5 # v3
+ movq 16*4(%esi), %mm7 # v4
+- movq %mm7, scratch1 # scratch1: v4 ;
++ movq %mm7, MUNG(scratch1) # scratch1: v4 ;
+ movq %mm5, %mm7 # duplicate v3
+- paddw scratch1, %mm5 # v03: v3+v4
+- psubw scratch1, %mm7 # v04: v3-v4
+- movq %mm5, scratch2 # scratch2: v03
++ paddw MUNG(scratch1), %mm5 # v03: v3+v4
++ psubw MUNG(scratch1), %mm7 # v04: v3-v4
++ movq %mm5, MUNG(scratch2) # scratch2: v03
+ movq %mm0, %mm5 # mm5: v00
+
+- paddw scratch2, %mm0 # v10: v00+v03
+- psubw scratch2, %mm5 # v13: v00-v03
+- movq %mm3, scratch3 # scratch3: v02
++ paddw MUNG(scratch2), %mm0 # v10: v00+v03
++ psubw MUNG(scratch2), %mm5 # v13: v00-v03
++ movq %mm3, MUNG(scratch3) # scratch3: v02
+ movq %mm1, %mm3 # duplicate v01
+
+- paddw scratch3, %mm1 # v11: v01+v02
+- psubw scratch3, %mm3 # v12: v01-v02
++ paddw MUNG(scratch3), %mm1 # v11: v01+v02
++ psubw MUNG(scratch3), %mm3 # v12: v01-v02
+
+- movq %mm6, scratch4 # scratch4: v05
++ movq %mm6, MUNG(scratch4) # scratch4: v05
+ movq %mm0, %mm6 # duplicate v10
+
+ paddw %mm1, %mm0 # v10+v11
+@@ -111,10 +116,10 @@ _dv_dct_88_block_mmx:
+ movq %mm6, 16*4(%esi) # out4: v10-v11
+
+ movq %mm4, %mm0 # mm0: v06
+- paddw scratch4, %mm4 # v15: v05+v06
++ paddw MUNG(scratch4), %mm4 # v15: v05+v06
+ paddw %mm2, %mm0 # v16: v07+v06
+
+- pmulhw WA3, %mm4 # v35~: WA3*v15
++ pmulhw MUNG(WA3), %mm4 # v35~: WA3*v15
+ psllw $1, %mm4 # v35: compensate the coeefient scale
+
+ movq %mm4, %mm6 # duplicate v35
+@@ -123,7 +128,7 @@ _dv_dct_88_block_mmx:
+
+ paddw %mm5, %mm3 # v22: v12+v13
+
+- pmulhw WA1, %mm3 # v32~: WA1*v22
++ pmulhw MUNG(WA1), %mm3 # v32~: WA1*v22
+ psllw $16-NSHIFT, %mm3 # v32: compensate the coeefient scale
+ movq %mm5, %mm6 # duplicate v13
+
+@@ -134,13 +139,13 @@ _dv_dct_88_block_mmx:
+ movq %mm6, 16*6(%esi) # out6: v13-v32
+
+
+- paddw scratch4, %mm7 # v14n: v04+v05
++ paddw MUNG(scratch4), %mm7 # v14n: v04+v05
+ movq %mm0, %mm5 # duplicate v16
+
+ psubw %mm7, %mm0 # va1: v16-v14n
+- pmulhw WA5, %mm0 # va0~: va1*WA5
+- pmulhw WA4, %mm5 # v36~~: v16*WA4
+- pmulhw WA2, %mm7 # v34~~: v14n*WA2
++ pmulhw MUNG(WA5), %mm0 # va0~: va1*WA5
++ pmulhw MUNG(WA4), %mm5 # v36~~: v16*WA4
++ pmulhw MUNG(WA2), %mm7 # v34~~: v14n*WA2
+ psllw $16-WA4_SHIFT, %mm5 # v36: compensate the coeefient scale
+ psllw $16-NSHIFT, %mm7 # v34: compensate the coeefient scale
+
+@@ -188,22 +193,22 @@ _dv_dct_88_block_mmx:
+
+ movq 16*3(%esi), %mm5 # v3
+ movq 16*4(%esi), %mm7 # v4
+- movq %mm7, scratch1 # scratch1: v4 ;
++ movq %mm7, MUNG(scratch1) # scratch1: v4 ;
+ movq %mm5, %mm7 # duplicate v3
+- paddw scratch1, %mm5 # v03: v3+v4
+- psubw scratch1, %mm7 # v04: v3-v4
+- movq %mm5, scratch2 # scratch2: v03
++ paddw MUNG(scratch1), %mm5 # v03: v3+v4
++ psubw MUNG(scratch1), %mm7 # v04: v3-v4
++ movq %mm5, MUNG(scratch2) # scratch2: v03
+ movq %mm0, %mm5 # mm5: v00
+
+- paddw scratch2, %mm0 # v10: v00+v03
+- psubw scratch2, %mm5 # v13: v00-v03
+- movq %mm3, scratch3 # scratc3: v02
++ paddw MUNG(scratch2), %mm0 # v10: v00+v03
++ psubw MUNG(scratch2), %mm5 # v13: v00-v03
++ movq %mm3, MUNG(scratch3) # scratc3: v02
+ movq %mm1, %mm3 # duplicate v01
+
+- paddw scratch3, %mm1 # v11: v01+v02
+- psubw scratch3, %mm3 # v12: v01-v02
++ paddw MUNG(scratch3), %mm1 # v11: v01+v02
++ psubw MUNG(scratch3), %mm3 # v12: v01-v02
+
+- movq %mm6, scratch4 # scratc4: v05
++ movq %mm6, MUNG(scratch4) # scratc4: v05
+ movq %mm0, %mm6 # duplicate v10
+
+ paddw %mm1, %mm0 # v10+v11
+@@ -213,10 +218,10 @@ _dv_dct_88_block_mmx:
+ movq %mm6, 16*4(%esi) # out4: v10-v11
+
+ movq %mm4, %mm0 # mm0: v06
+- paddw scratch4, %mm4 # v15: v05+v06
++ paddw MUNG(scratch4), %mm4 # v15: v05+v06
+ paddw %mm2, %mm0 # v16: v07+v06
+
+- pmulhw WA3, %mm4 # v35~: WA3*v15
++ pmulhw MUNG(WA3), %mm4 # v35~: WA3*v15
+ psllw $16-NSHIFT, %mm4 # v35: compensate the coeefient scale
+
+ movq %mm4, %mm6 # duplicate v35
+@@ -225,7 +230,7 @@ _dv_dct_88_block_mmx:
+
+ paddw %mm5, %mm3 # v22: v12+v13
+
+- pmulhw WA1, %mm3 # v32~: WA3*v15
++ pmulhw MUNG(WA1), %mm3 # v32~: WA3*v15
+ psllw $16-NSHIFT, %mm3 # v32: compensate the coeefient scale
+ movq %mm5, %mm6 # duplicate v13
+
+@@ -235,13 +240,13 @@ _dv_dct_88_block_mmx:
+ movq %mm5, 16*2(%esi) # out2: v13+v32
+ movq %mm6, 16*6(%esi) # out6: v13-v32
+
+- paddw scratch4, %mm7 # v14n: v04+v05
++ paddw MUNG(scratch4), %mm7 # v14n: v04+v05
+ movq %mm0, %mm5 # duplicate v16
+
+ psubw %mm7, %mm0 # va1: v16-v14n
+- pmulhw WA2, %mm7 # v34~~: v14n*WA2
+- pmulhw WA5, %mm0 # va0~: va1*WA5
+- pmulhw WA4, %mm5 # v36~~: v16*WA4
++ pmulhw MUNG(WA2), %mm7 # v34~~: v14n*WA2
++ pmulhw MUNG(WA5), %mm0 # va0~: va1*WA5
++ pmulhw MUNG(WA4), %mm5 # v36~~: v16*WA4
+ psllw $16-NSHIFT, %mm7
+ psllw $16-WA4_SHIFT, %mm5 # v36: compensate the coeffient
+ # scale note that WA4 is shifted 1 bit less than the others
+@@ -748,11 +755,12 @@ _dv_dct_block_mmx_postscale_88:
+ _dv_dct_248_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+
+- movl 8(%ebp), %esi # source
++ LOAD_PIC_REG(bp)
++
++ movl 16(%esp), %esi # source
+
+ # column 0
+
+@@ -779,7 +789,7 @@ _dv_dct_248_block_mmx:
+ paddw %mm1, %mm0 # v20: v10+v11
+ psubw %mm1, %mm3 # v21: v10-v11
+
+- pmulhw WA1, %mm5 # v32~: WA1*v22
++ pmulhw MUNG(WA1), %mm5 # v32~: WA1*v22
+ movq %mm4, %mm2
+ psllw $16-NSHIFT, %mm5 # v32: compensate the coeffient scale
+
+@@ -818,7 +828,7 @@ _dv_dct_248_block_mmx:
+ paddw %mm1, %mm0 # v20: v10+v11
+ psubw %mm1, %mm3 # v21: v10-v11
+
+- pmulhw WA1, %mm5 # v32~: WA1*v22
++ pmulhw MUNG(WA1), %mm5 # v32~: WA1*v22
+ movq %mm4, %mm2
+ psllw $16-NSHIFT, %mm5 # v32: compensate the coeffient scale
+
+@@ -855,7 +865,7 @@ _dv_dct_248_block_mmx:
+ paddw %mm1, %mm0 # v20: v10+v11
+ psubw %mm1, %mm3 # v21: v10-v11
+
+- pmulhw WA1, %mm5 # v32~: WA1*v22
++ pmulhw MUNG(WA1), %mm5 # v32~: WA1*v22
+ movq %mm4, %mm2
+ psllw $16-NSHIFT, %mm5 # v32: compensate the coeffient scale
+
+@@ -892,7 +902,7 @@ _dv_dct_248_block_mmx:
+ paddw %mm1, %mm0 # v20: v10+v11
+ psubw %mm1, %mm3 # v21: v10-v11
+
+- pmulhw WA1, %mm5 # v32~: WA1*v22
++ pmulhw MUNG(WA1), %mm5 # v32~: WA1*v22
+ movq %mm4, %mm2
+ psllw $16-NSHIFT, %mm5 # v32: compensate the coeffient scale
+
+--- libdv-0.104-old/libdv/dv.c
++++ libdv-0.104/libdv/dv.c
+@@ -205,6 +205,9 @@ dv_reconfigure(int clamp_luma, int clamp
+ } /* dv_reconfigure */
+
+
++extern uint8_t dv_quant_offset[4];
++extern uint8_t dv_quant_shifts[22][4];
++
+ static inline void
+ dv_decode_macroblock(dv_decoder_t *dv, dv_macroblock_t *mb, unsigned int quality) {
+ int i;
+@@ -218,7 +221,7 @@ dv_decode_macroblock(dv_decoder_t *dv, d
+ dv_idct_248 (co248, mb->b[i].coeffs);
+ } else {
+ #if ARCH_X86
+- _dv_quant_88_inverse_x86(mb->b[i].coeffs,mb->qno,mb->b[i].class_no);
++ _dv_quant_88_inverse_x86(mb->b[i].coeffs,mb->qno,mb->b[i].class_no,dv_quant_offset,dv_quant_shifts);
+ _dv_idct_88(mb->b[i].coeffs);
+ #elif ARCH_X86_64
+ _dv_quant_88_inverse_x86_64(mb->b[i].coeffs,mb->qno,mb->b[i].class_no);
+@@ -250,7 +253,7 @@ dv_decode_video_segment(dv_decoder_t *dv
+ dv_idct_248 (co248, mb->b[b].coeffs);
+ } else {
+ #if ARCH_X86
+- _dv_quant_88_inverse_x86(bl->coeffs,mb->qno,bl->class_no);
++ _dv_quant_88_inverse_x86(bl->coeffs,mb->qno,bl->class_no,dv_quant_offset,dv_quant_shifts);
+ _dv_weight_88_inverse(bl->coeffs);
+ _dv_idct_88(bl->coeffs);
+ #elif ARCH_X86_64
+--- libdv-0.104-old/libdv/encode.c
++++ libdv-0.104/libdv/encode.c
+@@ -521,7 +521,8 @@ static void reorder_block(dv_block_t *bl
+ }
+
+ extern unsigned long _dv_vlc_encode_block_mmx(dv_coeff_t* coeffs,
+- dv_vlc_entry_t ** out);
++ dv_vlc_entry_t ** out,
++ dv_vlc_entry_t * lookup);
+
+ extern unsigned long _dv_vlc_encode_block_mmx_x86_64(dv_coeff_t* coeffs,
+ dv_vlc_entry_t ** out);
+@@ -558,7 +559,7 @@ static unsigned long vlc_encode_block(dv
+ #elif ARCH_X86
+ int num_bits;
+
+- num_bits = _dv_vlc_encode_block_mmx(coeffs, &o);
++ num_bits = _dv_vlc_encode_block_mmx(coeffs, &o, vlc_encode_lookup);
+ emms();
+ #else
+ int num_bits;
+@@ -574,7 +575,7 @@ static unsigned long vlc_encode_block(dv
+ return num_bits;
+ }
+
+-extern unsigned long _dv_vlc_num_bits_block_x86(dv_coeff_t* coeffs);
++extern unsigned long _dv_vlc_num_bits_block_x86(dv_coeff_t* coeffs, unsigned char* lookup);
+ extern unsigned long _dv_vlc_num_bits_block_x86_64(dv_coeff_t* coeffs);
+
+ extern unsigned long _dv_vlc_num_bits_block(dv_coeff_t* coeffs)
+@@ -600,7 +601,7 @@ extern unsigned long _dv_vlc_num_bits_bl
+ #elif ARCH_X86_64
+ return _dv_vlc_num_bits_block_x86_64(coeffs);
+ #else
+- return _dv_vlc_num_bits_block_x86(coeffs);
++ return _dv_vlc_num_bits_block_x86(coeffs, vlc_num_bits_lookup);
+ #endif
+ }
+
+--- libdv-0.104-old/libdv/encode_x86.S
++++ libdv-0.104/libdv/encode_x86.S
+@@ -23,9 +23,6 @@
+ * The libdv homepage is http://libdv.sourceforge.net/.
+ */
+
+-.data
+-ALLONE: .word 1,1,1,1
+-VLCADDMASK: .byte 255,0,0,0,255,0,0,0
+
+
+ .section .note.GNU-stack, "", @progbits
+@@ -45,11 +43,14 @@ _dv_vlc_encode_block_mmx:
+
+ movl $63, %ecx
+
+- movl vlc_encode_lookup, %esi
++ movl 4+4*4+8(%esp), %esi # vlc_encode_lookup
+
+ pxor %mm0, %mm0
+ pxor %mm2, %mm2
+- movq VLCADDMASK, %mm1
++ pushl $0x000000FF # these four lines
++ pushl $0x000000FF # load VLCADDMASK
++ movq (%esp), %mm1 # into %mm1 off the stack
++ addl $8, %esp # --> no TEXTRELs
+ xorl %ebp, %ebp
+ subl $8, %edx
+ vlc_encode_block_mmx_loop:
+@@ -121,7 +124,7 @@ _dv_vlc_num_bits_block_x86:
+ addl $2, %edi
+
+ movl $63, %ecx
+- movl vlc_num_bits_lookup, %esi
++ movl 4+4*4+4(%esp), %esi # vlc_num_bits_lookup
+
+ vlc_num_bits_block_x86_loop:
+ movw (%edi), %ax
+@@ -579,8 +590,11 @@ _dv_need_dct_248_mmx_rows:
+ paddw %mm5, %mm1
+
+ paddw %mm1, %mm0
+-
+- pmaddwd ALLONE, %mm0
++
++ pushl $0x00010001 # these four lines
++ pushl $0x00010001 # load ALLONE
++ pmaddwd (%esp), %mm0 # into %mm0 off the stack
++ addl $8, %esp # --> no TEXTRELs
+ movq %mm0, %mm1
+ psrlq $32, %mm1
+ paddd %mm1, %mm0
+--- libdv-0.104-old/libdv/idct_block_mmx.S
++++ libdv-0.104/libdv/idct_block_mmx.S
+@@ -8,17 +8,21 @@
+
+ .section .note.GNU-stack, "", @progbits
+
++#include "asm_common.S"
++
+ .text
+ .align 4
+ .global _dv_idct_block_mmx
+ .hidden _dv_idct_block_mmx
+ .type _dv_idct_block_mmx,@function
+ _dv_idct_block_mmx:
+ pushl %ebp
+- movl %esp,%ebp
+ pushl %esi
+- leal preSC, %ecx
+- movl 8(%ebp),%esi /* source matrix */
++
++ LOAD_PIC_REG(bp)
++
++ leal MUNG(preSC), %ecx
++ movl 12(%esp),%esi /* source matrix */
+
+ /*
+ * column 0: even part
+@@ -35,7 +41,7 @@ _dv_idct_block_mmx:
+ movq %mm1, %mm2 /* added 11/1/96 */
+ pmulhw 8*8(%esi),%mm5 /* V8 */
+ psubsw %mm0, %mm1 /* V16 */
+- pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V18 */
++ pmulhw MUNG(x5a825a825a825a82), %mm1 /* 23170 ->V18 */
+ paddsw %mm0, %mm2 /* V17 */
+ movq %mm2, %mm0 /* duplicate V17 */
+ psraw $1, %mm2 /* t75=t82 */
+@@ -76,7 +82,7 @@ _dv_idct_block_mmx:
+ paddsw %mm0, %mm3 /* V29 ; free mm0 */
+ movq %mm7, %mm1 /* duplicate V26 */
+ psraw $1, %mm3 /* t91=t94 */
+- pmulhw x539f539f539f539f,%mm7 /* V33 */
++ pmulhw MUNG(x539f539f539f539f),%mm7 /* V33 */
+ psraw $1, %mm1 /* t96 */
+ movq %mm5, %mm0 /* duplicate V2 */
+ psraw $2, %mm4 /* t85=t87 */
+@@ -84,15 +90,15 @@ _dv_idct_block_mmx:
+ psubsw %mm4, %mm0 /* V28 ; free mm4 */
+ movq %mm0, %mm2 /* duplicate V28 */
+ psraw $1, %mm5 /* t90=t93 */
+- pmulhw x4546454645464546,%mm0 /* V35 */
++ pmulhw MUNG(x4546454645464546),%mm0 /* V35 */
+ psraw $1, %mm2 /* t97 */
+ movq %mm5, %mm4 /* duplicate t90=t93 */
+ psubsw %mm2, %mm1 /* V32 ; free mm2 */
+- pmulhw x61f861f861f861f8,%mm1 /* V36 */
++ pmulhw MUNG(x61f861f861f861f8),%mm1 /* V36 */
+ psllw $1, %mm7 /* t107 */
+ paddsw %mm3, %mm5 /* V31 */
+ psubsw %mm3, %mm4 /* V30 ; free mm3 */
+- pmulhw x5a825a825a825a82,%mm4 /* V34 */
++ pmulhw MUNG(x5a825a825a825a82),%mm4 /* V34 */
+ nop
+ psubsw %mm1, %mm0 /* V38 */
+ psubsw %mm7, %mm1 /* V37 ; free mm7 */
+@@ -159,7 +165,7 @@ _dv_idct_block_mmx:
+ psubsw %mm7, %mm1 /* V50 */
+ pmulhw 8*9(%esi), %mm5 /* V9 */
+ paddsw %mm7, %mm2 /* V51 */
+- pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V52 */
++ pmulhw MUNG(x5a825a825a825a82), %mm1 /* 23170 ->V52 */
+ movq %mm2, %mm6 /* duplicate V51 */
+ psraw $1, %mm2 /* t138=t144 */
+ movq %mm3, %mm4 /* duplicate V1 */
+@@ -200,11 +206,11 @@ _dv_idct_block_mmx:
+ * even more by doing the correction step in a later stage when the number
+ * is actually multiplied by 16
+ */
+- paddw x0005000200010001, %mm4
++ paddw MUNG(x0005000200010001), %mm4
+ psubsw %mm6, %mm3 /* V60 ; free mm6 */
+ psraw $1, %mm0 /* t154=t156 */
+ movq %mm3, %mm1 /* duplicate V60 */
+- pmulhw x539f539f539f539f, %mm1 /* V67 */
++ pmulhw MUNG(x539f539f539f539f), %mm1 /* V67 */
+ movq %mm5, %mm6 /* duplicate V3 */
+ psraw $2, %mm4 /* t148=t150 */
+ paddsw %mm4, %mm5 /* V61 */
+@@ -213,13 +219,13 @@ _dv_idct_block_mmx:
+ psllw $1, %mm1 /* t169 */
+ paddsw %mm0, %mm5 /* V65 -> result */
+ psubsw %mm0, %mm4 /* V64 ; free mm0 */
+- pmulhw x5a825a825a825a82, %mm4 /* V68 */
++ pmulhw MUNG(x5a825a825a825a82), %mm4 /* V68 */
+ psraw $1, %mm3 /* t158 */
+ psubsw %mm6, %mm3 /* V66 */
+ movq %mm5, %mm2 /* duplicate V65 */
+- pmulhw x61f861f861f861f8, %mm3 /* V70 */
++ pmulhw MUNG(x61f861f861f861f8), %mm3 /* V70 */
+ psllw $1, %mm6 /* t165 */
+- pmulhw x4546454645464546, %mm6 /* V69 */
++ pmulhw MUNG(x4546454645464546), %mm6 /* V69 */
+ psraw $1, %mm2 /* t172 */
+ /* moved from next block */
+ movq 8*5(%esi), %mm0 /* V56 */
+@@ -344,7 +350,7 @@ _dv_idct_block_mmx:
+ * movq 8*13(%esi), %mm4 tmt13
+ */
+ psubsw %mm4, %mm3 /* V134 */
+- pmulhw x5a825a825a825a82, %mm3 /* 23170 ->V136 */
++ pmulhw MUNG(x5a825a825a825a82), %mm3 /* 23170 ->V136 */
+ movq 8*9(%esi), %mm6 /* tmt9 */
+ paddsw %mm4, %mm5 /* V135 ; mm4 free */
+ movq %mm0, %mm4 /* duplicate tmt1 */
+@@ -373,17 +379,17 @@ _dv_idct_block_mmx:
+ psubsw %mm7, %mm0 /* V144 */
+ movq %mm0, %mm3 /* duplicate V144 */
+ paddsw %mm7, %mm2 /* V147 ; free mm7 */
+- pmulhw x539f539f539f539f, %mm0 /* 21407-> V151 */
++ pmulhw MUNG(x539f539f539f539f), %mm0 /* 21407-> V151 */
+ movq %mm1, %mm7 /* duplicate tmt3 */
+ paddsw %mm5, %mm7 /* V145 */
+ psubsw %mm5, %mm1 /* V146 ; free mm5 */
+ psubsw %mm1, %mm3 /* V150 */
+ movq %mm7, %mm5 /* duplicate V145 */
+- pmulhw x4546454645464546, %mm1 /* 17734-> V153 */
++ pmulhw MUNG(x4546454645464546), %mm1 /* 17734-> V153 */
+ psubsw %mm2, %mm5 /* V148 */
+- pmulhw x61f861f861f861f8, %mm3 /* 25080-> V154 */
++ pmulhw MUNG(x61f861f861f861f8), %mm3 /* 25080-> V154 */
+ psllw $2, %mm0 /* t311 */
+- pmulhw x5a825a825a825a82, %mm5 /* 23170-> V152 */
++ pmulhw MUNG(x5a825a825a825a82), %mm5 /* 23170-> V152 */
+ paddsw %mm2, %mm7 /* V149 ; free mm2 */
+ psllw $1, %mm1 /* t313 */
+ nop /* without the nop - freeze here for one clock */
+@@ -409,7 +415,7 @@ _dv_idct_block_mmx:
+ paddsw %mm3, %mm6 /* V164 ; free mm3 */
+ movq %mm4, %mm3 /* duplicate V142 */
+ psubsw %mm5, %mm4 /* V165 ; free mm5 */
+- movq %mm2, scratch7 /* out7 */
++ movq %mm2, MUNG(scratch7) /* out7 */
+ psraw $4, %mm6
+ psraw $4, %mm4
+ paddsw %mm5, %mm3 /* V162 */
+@@ -420,11 +426,11 @@ _dv_idct_block_mmx:
+ */
+ movq %mm6, 8*9(%esi) /* out9 */
+ paddsw %mm1, %mm0 /* V161 */
+- movq %mm3, scratch5 /* out5 */
++ movq %mm3, MUNG(scratch5) /* out5 */
+ psubsw %mm1, %mm5 /* V166 ; free mm1 */
+ movq %mm4, 8*11(%esi) /* out11 */
+ psraw $4, %mm5
+- movq %mm0, scratch3 /* out3 */
++ movq %mm0, MUNG(scratch3) /* out3 */
+ movq %mm2, %mm4 /* duplicate V140 */
+ movq %mm5, 8*13(%esi) /* out13 */
+ paddsw %mm7, %mm2 /* V160 */
+@@ -434,7 +440,7 @@ _dv_idct_block_mmx:
+ /* moved from the next block */
+ movq 8*3(%esi), %mm7
+ psraw $4, %mm4
+- movq %mm2, scratch1 /* out1 */
++ movq %mm2, MUNG(scratch1) /* out1 */
+ /* moved from the next block */
+ movq %mm0, %mm1
+ movq %mm4, 8*15(%esi) /* out15 */
+@@ -491,15 +497,15 @@ _dv_idct_block_mmx:
+ paddsw %mm4, %mm3 /* V113 ; free mm4 */
+ movq %mm0, %mm4 /* duplicate V110 */
+ paddsw %mm1, %mm2 /* V111 */
+- pmulhw x539f539f539f539f, %mm0 /* 21407-> V117 */
++ pmulhw MUNG(x539f539f539f539f), %mm0 /* 21407-> V117 */
+ psubsw %mm1, %mm5 /* V112 ; free mm1 */
+ psubsw %mm5, %mm4 /* V116 */
+ movq %mm2, %mm1 /* duplicate V111 */
+- pmulhw x4546454645464546, %mm5 /* 17734-> V119 */
++ pmulhw MUNG(x4546454645464546), %mm5 /* 17734-> V119 */
+ psubsw %mm3, %mm2 /* V114 */
+- pmulhw x61f861f861f861f8, %mm4 /* 25080-> V120 */
++ pmulhw MUNG(x61f861f861f861f8), %mm4 /* 25080-> V120 */
+ paddsw %mm3, %mm1 /* V115 ; free mm3 */
+- pmulhw x5a825a825a825a82, %mm2 /* 23170-> V118 */
++ pmulhw MUNG(x5a825a825a825a82), %mm2 /* 23170-> V118 */
+ psllw $2, %mm0 /* t266 */
+ movq %mm1, (%esi) /* save V115 */
+ psllw $1, %mm5 /* t268 */
+@@ -517,7 +523,7 @@ _dv_idct_block_mmx:
+ movq %mm6, %mm3 /* duplicate tmt4 */
+ psubsw %mm0, %mm6 /* V100 */
+ paddsw %mm0, %mm3 /* V101 ; free mm0 */
+- pmulhw x5a825a825a825a82, %mm6 /* 23170 ->V102 */
++ pmulhw MUNG(x5a825a825a825a82), %mm6 /* 23170 ->V102 */
+ movq %mm7, %mm5 /* duplicate tmt0 */
+ movq 8*8(%esi), %mm1 /* tmt8 */
+ paddsw %mm1, %mm7 /* V103 */
+@@ -551,10 +557,10 @@ _dv_idct_block_mmx:
+ movq 8*2(%esi), %mm3 /* V123 */
+ paddsw %mm4, %mm7 /* out0 */
+ /* moved up from next block */
+- movq scratch3, %mm0
++ movq MUNG(scratch3), %mm0
+ psraw $4, %mm7
+ /* moved up from next block */
+- movq scratch5, %mm6
++ movq MUNG(scratch5), %mm6
+ psubsw %mm4, %mm1 /* out14 ; free mm4 */
+ paddsw %mm3, %mm5 /* out2 */
+ psraw $4, %mm1
+@@ -565,7 +571,7 @@ _dv_idct_block_mmx:
+ movq %mm5, 8*2(%esi) /* out2 ; free mm5 */
+ psraw $4, %mm2
+ /* moved up to the prev block */
+- movq scratch7, %mm4
++ movq MUNG(scratch7), %mm4
+ /* moved up to the prev block */
+ psraw $4, %mm0
+ movq %mm2, 8*12(%esi) /* out12 ; free mm2 */
+@@ -579,7 +585,7 @@ _dv_idct_block_mmx:
+ * psraw $4, %mm0
+ * psraw $4, %mm6
+ */
+- movq scratch1, %mm1
++ movq MUNG(scratch1), %mm1
+ psraw $4, %mm4
+ movq %mm0, 8*3(%esi) /* out3 */
+ psraw $4, %mm1
+--- libdv-0.104-old/libdv/parse.c
++++ libdv-0.104/libdv/parse.c
+@@ -477,6 +477,13 @@ dv_parse_ac_coeffs(dv_videosegment_t *se
+ exit(0);
+ #endif
+ } /* dv_parse_ac_coeffs */
++#if defined __GNUC__ && __ELF__
++# define dv_strong_hidden_alias(name, aliasname) \
++ extern __typeof (name) aliasname __attribute__ ((alias (#name), visibility ("hidden")))
++dv_strong_hidden_alias(dv_parse_ac_coeffs, asm_dv_parse_ac_coeffs);
++#else
++int asm_dv_parse_ac_coeffs(dv_videosegment_t *seg) { return dv_parse_ac_coeffs(seg); }
++#endif
+
+ /* ---------------------------------------------------------------------------
+ */
+--- libdv-0.104-old/libdv/quant.c
++++ libdv-0.104/libdv/quant.c
+@@ -144,7 +144,7 @@ uint8_t dv_quant_offset[4] = { 6,3,0,1
+ uint32_t dv_quant_248_mul_tab [2] [22] [64];
+ uint32_t dv_quant_88_mul_tab [2] [22] [64];
+
+-extern void _dv_quant_x86(dv_coeff_t *block,int qno,int klass);
++extern void _dv_quant_x86(dv_coeff_t *block,int qno,int klass,uint8_t *dv_quant_offset,uint8_t *dv_quant_shifts);
+ extern void _dv_quant_x86_64(dv_coeff_t *block,int qno,int klass);
+ static void quant_248_inverse_std(dv_coeff_t *block,int qno,int klass,dv_248_coeff_t *co);
+ static void quant_248_inverse_mmx(dv_coeff_t *block,int qno,int klass,dv_248_coeff_t *co);
+@@ -210,7 +210,7 @@ void _dv_quant(dv_coeff_t *block,int qno
+ _dv_quant_x86_64(block, qno, klass);
+ emms();
+ #else
+- _dv_quant_x86(block, qno, klass);
++ _dv_quant_x86(block, qno, klass, dv_quant_offset, dv_quant_shifts);
+ emms();
+ #endif
+ }
+--- libdv-0.104-old/libdv/quant.h
++++ libdv-0.104/libdv/quant.h
+@@ -27,7 +27,7 @@ extern void _dv_quant(dv_coeff_t *block,
+ extern void _dv_quant_88_inverse(dv_coeff_t *block,int qno,int klass);
+ extern void (*_dv_quant_248_inverse) (dv_coeff_t *block,int qno,int klass,
+ dv_248_coeff_t *co);
+-extern void _dv_quant_88_inverse_x86(dv_coeff_t *block,int qno,int klass);
++extern void _dv_quant_88_inverse_x86(dv_coeff_t *block,int qno,int klass, uint8_t *offset, uint8_t *shifts);
+ extern void _dv_quant_88_inverse_x86_64(dv_coeff_t *block,int qno,int klass);
+ extern void dv_quant_init (void);
+ #ifdef __cplusplus
+--- libdv-0.104-old/libdv/quant_x86.S
++++ libdv-0.104/libdv/quant_x86.S
+@@ -71,10 +73,13 @@ _dv_quant_88_inverse_x86:
+
+ /* pq = dv_quant_shifts[qno + dv_quant_offset[class]]; */
+ movl ARGn(1),%eax /* qno */
++ movl ARGn(3),%ebx /* dv_quant_offset */
++ addl ARGn(2),%ebx /* class */
++ movzbl (%ebx),%ecx
+ movl ARGn(2),%ebx /* class */
+- movzbl dv_quant_offset(%ebx),%ecx
+ addl %ecx,%eax
+- leal dv_quant_shifts(,%eax,4),%edx /* edx is pq */
++ movl ARGn(4),%edx /* dv_quant_shifts */
++ leal (%edx,%eax,4),%edx /* edx is pq */
+
+ /* extra = (class == 3); */
+ /* 0 1 2 3 */
+@@ -212,11 +219,13 @@ _dv_quant_x86:
+
+ /* pq = dv_quant_shifts[qno + dv_quant_offset[class]]; */
+ movl ARGn(1),%eax /* qno */
++ movl ARGn(3),%ebx /* offset */
++ addl ARGn(2),%ebx /* class */
++ movzbl (%ebx),%ecx
+ movl ARGn(2),%ebx /* class */
+-
+- movzbl dv_quant_offset(%ebx),%ecx
++ movl ARGn(4),%edx /* shifts */
+ addl %ecx,%eax
+- leal dv_quant_shifts(,%eax,4),%edx /* edx is pq */
++ leal (%edx,%eax,4),%edx /* edx is pq */
+
+ /* extra = (class == 3); */
+ /* 0 1 2 3 */
+--- libdv-0.104-old/libdv/rgbtoyuv.S
++++ libdv-0.104/libdv/rgbtoyuv.S
+@@ -41,9 +41,6 @@
+ #define DV_WIDTH_SHORT_HALF 720
+ #define DV_WIDTH_BYTE_HALF 360
+
+-.global _dv_rgbtoycb_mmx
+-# .global yuvtoycb_mmx
+-
+ .data
+
+ .align 8
+@@ -110,25 +107,26 @@ VR0GR: .long 0,0
+ VBG0B: .long 0,0
+
+ #endif
+-
++
++#include "asm_common.S"
++
+ .section .note.GNU-stack, "", @progbits
+
+ .text
+
+-#define _inPtr 8
+-#define _rows 12
+-#define _columns 16
+-#define _outyPtr 20
+-#define _outuPtr 24
+-#define _outvPtr 28
++#define _inPtr 24+8
++#define _rows 24+12
++#define _columns 24+16
++#define _outyPtr 24+20
++#define _outuPtr 24+24
++#define _outvPtr 24+28
+
+ .global _dv_rgbtoycb_mmx
+ .hidden _dv_rgbtoycb_mmx
+ .type _dv_rgbtoycb_mmx,@function
+ _dv_rgbtoycb_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+@@ -131,46 +132,47 @@ _dv_rgbtoycb_mmx:
+ pushl %esi
+ pushl %edi
+
+- leal ZEROSX, %eax #This section gets around a bug
++ LOAD_PIC_REG(bp)
++
++ leal MUNG(ZEROSX), %eax #This section gets around a bug
+ movq (%eax), %mm0 #unlikely to persist
+- movq %mm0, ZEROS
+- leal OFFSETDX, %eax
++ movq %mm0, MUNG(ZEROS)
++ leal MUNG(OFFSETDX), %eax
+ movq (%eax), %mm0
+- movq %mm0, OFFSETD
+- leal OFFSETWX, %eax
++ movq %mm0, MUNG(OFFSETD)
++ leal MUNG(OFFSETWX), %eax
+ movq (%eax), %mm0
+- movq %mm0, OFFSETW
+- leal OFFSETBX, %eax
++ movq %mm0, MUNG(OFFSETW)
++ leal MUNG(OFFSETBX), %eax
+ movq (%eax), %mm0
+- movq %mm0, OFFSETB
+- leal YR0GRX, %eax
++ movq %mm0, MUNG(OFFSETB)
++ leal MUNG(YR0GRX), %eax
+ movq (%eax), %mm0
+- movq %mm0, YR0GR
+- leal YBG0BX, %eax
++ movq %mm0, MUNG(YR0GR)
++ leal MUNG(YBG0BX), %eax
+ movq (%eax), %mm0
+- movq %mm0, YBG0B
+- leal UR0GRX, %eax
++ movq %mm0, MUNG(YBG0B)
++ leal MUNG(UR0GRX), %eax
+ movq (%eax), %mm0
+- movq %mm0, UR0GR
+- leal UBG0BX, %eax
++ movq %mm0, MUNG(UR0GR)
++ leal MUNG(UBG0BX), %eax
+ movq (%eax), %mm0
+- movq %mm0, UBG0B
+- leal VR0GRX, %eax
++ movq %mm0, MUNG(UBG0B)
++ leal MUNG(VR0GRX), %eax
+ movq (%eax), %mm0
+- movq %mm0, VR0GR
+- leal VBG0BX, %eax
++ movq %mm0, MUNG(VR0GR)
++ leal MUNG(VBG0BX), %eax
+ movq (%eax), %mm0
+- movq %mm0, VBG0B
+-
+- movl _rows(%ebp), %eax
+- movl _columns(%ebp), %ebx
++ movq %mm0, MUNG(VBG0B)
++ movl _rows(%esp), %eax
++ movl _columns(%esp), %ebx
+ mull %ebx #number pixels
+ shrl $3, %eax #number of loops
+ movl %eax, %edi #loop counter in edi
+- movl _inPtr(%ebp), %eax
+- movl _outyPtr(%ebp), %ebx
+- movl _outuPtr(%ebp), %ecx
+- movl _outvPtr(%ebp), %edx
++ movl _inPtr(%esp), %eax
++ movl _outyPtr(%esp), %ebx
++ movl _outuPtr(%esp), %ecx
++ movl _outvPtr(%esp), %edx
+ rgbtoycb_mmx_loop:
+ movq (%eax), %mm1 #load G2R2B1G1R1B0G0R0
+ pxor %mm6, %mm6 #0 -> mm6
+@@ -184,29 +186,29 @@ rgbtoycb_mmx_loop:
+ punpcklbw %mm6, %mm1 #B1G1R1B0 -> mm1
+ movq %mm0, %mm2 #R1B0G0R0 -> mm2
+
+- pmaddwd YR0GR, %mm0 #yrR1,ygG0+yrR0 -> mm0
++ pmaddwd MUNG(YR0GR), %mm0 #yrR1,ygG0+yrR0 -> mm0
+ movq %mm1, %mm3 #B1G1R1B0 -> mm3
+
+- pmaddwd YBG0B, %mm1 #ybB1+ygG1,ybB0 -> mm1
++ pmaddwd MUNG(YBG0B), %mm1 #ybB1+ygG1,ybB0 -> mm1
+ movq %mm2, %mm4 #R1B0G0R0 -> mm4
+
+- pmaddwd UR0GR, %mm2 #urR1,ugG0+urR0 -> mm2
++ pmaddwd MUNG(UR0GR), %mm2 #urR1,ugG0+urR0 -> mm2
+ movq %mm3, %mm5 #B1G1R1B0 -> mm5
+
+- pmaddwd UBG0B, %mm3 #ubB1+ugG1,ubB0 -> mm3
++ pmaddwd MUNG(UBG0B), %mm3 #ubB1+ugG1,ubB0 -> mm3
+ punpckhbw %mm6, %mm7 # 00G2R2 -> mm7
+
+- pmaddwd VR0GR, %mm4 #vrR1,vgG0+vrR0 -> mm4
++ pmaddwd MUNG(VR0GR), %mm4 #vrR1,vgG0+vrR0 -> mm4
+ paddd %mm1, %mm0 #Y1Y0 -> mm0
+
+- pmaddwd VBG0B, %mm5 #vbB1+vgG1,vbB0 -> mm5
++ pmaddwd MUNG(VBG0B), %mm5 #vbB1+vgG1,vbB0 -> mm5
+
+ movq 8(%eax), %mm1 #R5B4G4R4B3G3R3B2 -> mm1
+ paddd %mm3, %mm2 #U1U0 -> mm2
+
+ movq %mm1, %mm6 #R5B4G4R4B3G3R3B2 -> mm6
+
+- punpcklbw ZEROS, %mm1 #B3G3R3B2 -> mm1
++ punpcklbw MUNG(ZEROS), %mm1 #B3G3R3B2 -> mm1
+ paddd %mm5, %mm4 #V1V0 -> mm4
+
+ movq %mm1, %mm5 #B3G3R3B2 -> mm5
+@@ -214,29 +216,29 @@ rgbtoycb_mmx_loop:
+
+ paddd %mm7, %mm1 #R3B200+00G2R2=R3B2G2R2->mm1
+
+- punpckhbw ZEROS, %mm6 #R5B4G4R3 -> mm6
++ punpckhbw MUNG(ZEROS), %mm6 #R5B4G4R3 -> mm6
+ movq %mm1, %mm3 #R3B2G2R2 -> mm3
+
+- pmaddwd YR0GR, %mm1 #yrR3,ygG2+yrR2 -> mm1
++ pmaddwd MUNG(YR0GR), %mm1 #yrR3,ygG2+yrR2 -> mm1
+ movq %mm5, %mm7 #B3G3R3B2 -> mm7
+
+- pmaddwd YBG0B, %mm5 #ybB3+ygG3,ybB2 -> mm5
++ pmaddwd MUNG(YBG0B), %mm5 #ybB3+ygG3,ybB2 -> mm5
+ psrad $FIXPSHIFT, %mm0 #32-bit scaled Y1Y0 -> mm0
+
+- movq %mm6, TEMP0 #R5B4G4R4 -> TEMP0
++ movq %mm6, MUNG(TEMP0) #R5B4G4R4 -> TEMP0
+ movq %mm3, %mm6 #R3B2G2R2 -> mm6
+- pmaddwd UR0GR, %mm6 #urR3,ugG2+urR2 -> mm6
++ pmaddwd MUNG(UR0GR), %mm6 #urR3,ugG2+urR2 -> mm6
+ psrad $FIXPSHIFT, %mm2 #32-bit scaled U1U0 -> mm2
+
+ paddd %mm5, %mm1 #Y3Y2 -> mm1
+ movq %mm7, %mm5 #B3G3R3B2 -> mm5
+- pmaddwd UBG0B, %mm7 #ubB3+ugG3,ubB2
++ pmaddwd MUNG(UBG0B), %mm7 #ubB3+ugG3,ubB2
+ psrad $FIXPSHIFT, %mm1 #32-bit scaled Y3Y2 -> mm1
+
+- pmaddwd VR0GR, %mm3 #vrR3,vgG2+vgR2
++ pmaddwd MUNG(VR0GR), %mm3 #vrR3,vgG2+vgR2
+ packssdw %mm1, %mm0 #Y3Y2Y1Y0 -> mm0
+
+- pmaddwd VBG0B, %mm5 #vbB3+vgG3,vbB2 -> mm5
++ pmaddwd MUNG(VBG0B), %mm5 #vbB3+vgG3,vbB2 -> mm5
+ psrad $FIXPSHIFT, %mm4 #32-bit scaled V1V0 -> mm4
+
+ movq 16(%eax), %mm1 #B7G7R7B6G6R6B5G5 -> mm7
+@@ -251,58 +253,58 @@ rgbtoycb_mmx_loop:
+ movq %mm7, %mm5 #R7B6G6R6B5G500 -> mm5
+ psrad $FIXPSHIFT, %mm3 #32-bit scaled V3V2 -> mm3
+
+- paddw OFFSETY, %mm0
++ paddw MUNG(OFFSETY), %mm0
+ movq %mm0, (%ebx) #store Y3Y2Y1Y0
+ packssdw %mm6, %mm2 #32-bit scaled U3U2U1U0 -> mm2
+
+- movq TEMP0, %mm0 #R5B4G4R4 -> mm0
++ movq MUNG(TEMP0), %mm0 #R5B4G4R4 -> mm0
+ addl $8, %ebx
+-
+- punpcklbw ZEROS, %mm7 #B5G500 -> mm7
++
++ punpcklbw MUNG(ZEROS), %mm7 #B5G500 -> mm7
+ movq %mm0, %mm6 #R5B4G4R4 -> mm6
+
+- movq %mm2, TEMPU #32-bit scaled U3U2U1U0 -> TEMPU
++ movq %mm2, MUNG(TEMPU) #32-bit scaled U3U2U1U0 -> TEMPU
+ psrlq $32, %mm0 #00R5B4 -> mm0
+
+ paddw %mm0, %mm7 #B5G5R5B4 -> mm7
+ movq %mm6, %mm2 #B5B4G4R4 -> mm2
+
+- pmaddwd YR0GR, %mm2 #yrR5,ygG4+yrR4 -> mm2
++ pmaddwd MUNG(YR0GR), %mm2 #yrR5,ygG4+yrR4 -> mm2
+ movq %mm7, %mm0 #B5G5R5B4 -> mm0
+
+- pmaddwd YBG0B, %mm7 #ybB5+ygG5,ybB4 -> mm7
++ pmaddwd MUNG(YBG0B), %mm7 #ybB5+ygG5,ybB4 -> mm7
+ packssdw %mm3, %mm4 #32-bit scaled V3V2V1V0 -> mm4
+
+ addl $24, %eax #increment RGB count
+
+- movq %mm4, TEMPV #(V3V2V1V0)/256 -> mm4
++ movq %mm4, MUNG(TEMPV) #(V3V2V1V0)/256 -> mm4
+ movq %mm6, %mm4 #B5B4G4R4 -> mm4
+
+- pmaddwd UR0GR, %mm6 #urR5,ugG4+urR4
++ pmaddwd MUNG(UR0GR), %mm6 #urR5,ugG4+urR4
+ movq %mm0, %mm3 #B5G5R5B4 -> mm0
+
+- pmaddwd UBG0B, %mm0 #ubB5+ugG5,ubB4
++ pmaddwd MUNG(UBG0B), %mm0 #ubB5+ugG5,ubB4
+ paddd %mm7, %mm2 #Y5Y4 -> mm2
+
+- pmaddwd VR0GR, %mm4 #vrR5,vgG4+vrR4 -> mm4
++ pmaddwd MUNG(VR0GR), %mm4 #vrR5,vgG4+vrR4 -> mm4
+ pxor %mm7, %mm7 #0 -> mm7
+
+- pmaddwd VBG0B, %mm3 #vbB5+vgG5,vbB4 -> mm3
++ pmaddwd MUNG(VBG0B), %mm3 #vbB5+vgG5,vbB4 -> mm3
+ punpckhbw %mm7, %mm1 #B7G7R7B6 -> mm1
+
+ paddd %mm6, %mm0 #U5U4 -> mm0
+ movq %mm1, %mm6 #B7G7R7B6 -> mm6
+
+- pmaddwd YBG0B, %mm6 #ybB7+ygG7,ybB6 -> mm6
++ pmaddwd MUNG(YBG0B), %mm6 #ybB7+ygG7,ybB6 -> mm6
+ punpckhbw %mm7, %mm5 #R7B6G6R6 -> mm5
+
+ movq %mm5, %mm7 #R7B6G6R6 -> mm7
+ paddd %mm4, %mm3 #V5V4 -> mm3
+
+- pmaddwd YR0GR, %mm5 #yrR7,ygG6+yrR6 -> mm5
++ pmaddwd MUNG(YR0GR), %mm5 #yrR7,ygG6+yrR6 -> mm5
+ movq %mm1, %mm4 #B7G7R7B6 -> mm4
+
+- pmaddwd UBG0B, %mm4 #ubB7+ugG7,ubB6 -> mm4
++ pmaddwd MUNG(UBG0B), %mm4 #ubB7+ugG7,ubB6 -> mm4
+ psrad $FIXPSHIFT, %mm0 #32-bit scaled U5U4 -> mm0
+
+ psrad $FIXPSHIFT, %mm2 #32-bit scaled Y5Y4 -> mm2
+@@ -310,25 +312,25 @@ rgbtoycb_mmx_loop:
+ paddd %mm5, %mm6 #Y7Y6 -> mm6
+ movq %mm7, %mm5 #R7B6G6R6 -> mm5
+
+- pmaddwd UR0GR, %mm7 #urR7,ugG6+ugR6 -> mm7
++ pmaddwd MUNG(UR0GR), %mm7 #urR7,ugG6+ugR6 -> mm7
+ psrad $FIXPSHIFT, %mm3 #32-bit scaled V5V4 -> mm3
+
+- pmaddwd VBG0B, %mm1 #vbB7+vgG7,vbB6 -> mm1
++ pmaddwd MUNG(VBG0B), %mm1 #vbB7+vgG7,vbB6 -> mm1
+ psrad $FIXPSHIFT, %mm6 #32-bit scaled Y7Y6 -> mm6
+
+ packssdw %mm6, %mm2 #Y7Y6Y5Y4 -> mm2
+
+- pmaddwd VR0GR, %mm5 #vrR7,vgG6+vrR6 -> mm5
++ pmaddwd MUNG(VR0GR), %mm5 #vrR7,vgG6+vrR6 -> mm5
+ paddd %mm4, %mm7 #U7U6 -> mm7
+
+ psrad $FIXPSHIFT, %mm7 #32-bit scaled U7U6 -> mm7
+- paddw OFFSETY, %mm2
++ paddw MUNG(OFFSETY), %mm2
+ movq %mm2, (%ebx) #store Y7Y6Y5Y4
+
+- movq ALLONE, %mm6
++ movq MUNG(ALLONE), %mm6
+ packssdw %mm7, %mm0 #32-bit scaled U7U6U5U4 -> mm0
+
+- movq TEMPU, %mm4 #32-bit scaled U3U2U1U0 -> mm4
++ movq MUNG(TEMPU), %mm4 #32-bit scaled U3U2U1U0 -> mm4
+ pmaddwd %mm6, %mm0 #U7U6U5U4 averaged -> (U7U6)(U5U4)=UU3 UU2->mm0
+
+ pmaddwd %mm6, %mm4 #U3U2U1U0 averaged -> (U3U2)(U1U0)=UU1 UU0->mm4
+@@ -338,8 +340,8 @@ rgbtoycb_mmx_loop:
+
+ psrad $FIXPSHIFT, %mm1 #32-bit scaled V7V6 -> mm1
+ psraw $1, %mm4 #divide UU3 UU2 UU1 UU0 by 2 -> mm4
+-
+- movq TEMPV, %mm5 #32-bit scaled V3V2V1V0 -> mm5
++
++ movq MUNG(TEMPV), %mm5 #32-bit scaled V3V2V1V0 -> mm5
+
+ movq %mm4, (%ecx) # store U
+
+@@ -422,14 +426,15 @@ _dv_ppm_copy_y_block_mmx:
+ _dv_pgm_copy_y_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+-
+- movl 8(%ebp), %edi # dest
+- movl 12(%ebp), %esi # src
+
+- movq OFFSETY, %mm7
++ LOAD_PIC_REG(bp)
++
++ movl 16(%esp), %edi # dest
++ movl 20(%esp), %esi # src
++
++ movq MUNG(OFFSETY), %mm7
+ pxor %mm6, %mm6
+
+ movq (%esi), %mm0
+@@ -564,14 +571,15 @@ _dv_pgm_copy_y_block_mmx:
+ _dv_video_copy_y_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+-
+- movl 8(%ebp), %edi # dest
+- movl 12(%ebp), %esi # src
+
+- movq OFFSETBX, %mm7
++ LOAD_PIC_REG(bp)
++
++ movl 16(%esp), %edi # dest
++ movl 20(%esp), %esi # src
++
++ movq MUNG(OFFSETBX), %mm7
+ pxor %mm6, %mm6
+
+ movq (%esi), %mm0
+@@ -852,16 +864,16 @@ _dv_ppm_copy_pal_c_block_mmx:
+ _dv_pgm_copy_pal_c_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+-
+- movl 8(%ebp), %edi # dest
+- movl 12(%ebp), %esi # src
+
++ LOAD_PIC_REG(bp)
++
++ movl 20(%esp), %edi # dest
++ movl 24(%esp), %esi # src
+
+- movq OFFSETBX, %mm7
++ movq MUNG(OFFSETBX), %mm7
+ pxor %mm6, %mm6
+
+
+@@ -1000,15 +1014,16 @@ _dv_pgm_copy_pal_c_block_mmx:
+ _dv_video_copy_pal_c_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+-
+- movl 8(%ebp), %edi # dest
+- movl 12(%ebp), %esi # src
+
+- movq OFFSETBX, %mm7
++ LOAD_PIC_REG(bp)
++
++ movl 20(%esp), %edi # dest
++ movl 24(%esp), %esi # src
++
++ movq MUNG(OFFSETBX), %mm7
+ paddw %mm7, %mm7
+ pxor %mm6, %mm6
+
+@@ -1095,18 +1112,18 @@ video_copy_pal_c_block_mmx_loop:
+ _dv_ppm_copy_ntsc_c_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+-
+- movl 8(%ebp), %edi # dest
+- movl 12(%ebp), %esi # src
++
++ LOAD_PIC_REG(bp)
++
++ movl 20(%esp), %edi # dest
++ movl 24(%esp), %esi # src
+
+ movl $4, %ebx
+
+- movq ALLONE, %mm6
+-
++ movq MUNG(ALLONE), %mm6
+ ppm_copy_ntsc_c_block_mmx_loop:
+
+ movq (%esi), %mm0
+@@ -1168,14 +1187,15 @@ ppm_copy_ntsc_c_block_mmx_loop:
+ _dv_pgm_copy_ntsc_c_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+-
+- movl 8(%ebp), %edi # dest
+- movl 12(%ebp), %esi # src
+
+- movq OFFSETBX, %mm7
++ LOAD_PIC_REG(bp)
++
++ movl 16(%esp), %edi # dest
++ movl 20(%esp), %esi # src
++
++ movq MUNG(OFFSETBX), %mm7
+ paddw %mm7, %mm7
+ pxor %mm6, %mm6
+
+@@ -1325,15 +1347,16 @@ _dv_pgm_copy_ntsc_c_block_mmx:
+ _dv_video_copy_ntsc_c_block_mmx:
+
+ pushl %ebp
+- movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+-
+- movl 8(%ebp), %edi # dest
+- movl 12(%ebp), %esi # src
+
+- movq OFFSETBX, %mm7
++ LOAD_PIC_REG(bp)
++
++ movl 20(%esp), %edi # dest
++ movl 24(%esp), %esi # src
++
++ movq MUNG(OFFSETBX), %mm7
+ paddw %mm7, %mm7
+ pxor %mm6, %mm6
+
+--- libdv-0.104-old/libdv/rgbtoyuv_x86_64.S
++++ libdv-0.104/libdv/rgbtoyuv_x86_64.S
+@@ -41,9 +41,6 @@
+ #define DV_WIDTH_SHORT_HALF 720
+ #define DV_WIDTH_BYTE_HALF 360
+
+-.global _dv_rgbtoycb_mmx_x86_64
+-# .global yuvtoycb_mmx_x86_64
+-
+ .data
+
+ .align 8
+--- libdv-0.104-old/libdv/vlc_x86.S
++++ libdv-0.104/libdv/vlc_x86.S
+@@ -1,31 +1,39 @@
+ #include "asmoff.h"
+ .section .note.GNU-stack, "", @progbits
++ #include "asm_common.S"
+
+ .text
+ .align 4
+ .globl dv_decode_vlc
++.globl asm_dv_decode_vlc
++.hidden asm_dv_decode_vlc
++asm_dv_decode_vlc = dv_decode_vlc
++
+ .type dv_decode_vlc,@function
+ dv_decode_vlc:
+ pushl %ebx
++ pushl %ebp
++
++ LOAD_PIC_REG(bp)
+
+- /* Args are at 8(%esp). */
+- movl 8(%esp),%eax /* %eax is bits */
+- movl 12(%esp),%ebx /* %ebx is maxbits */
++ /* Args are at 12(%esp). */
++ movl 12(%esp),%eax /* %eax is bits */
++ movl 16(%esp),%ebx /* %ebx is maxbits */
+ andl $0x3f,%ebx /* limit index range STL*/
+
+- movl dv_vlc_class_index_mask(,%ebx,4),%edx
++ movl MUNG_ARR(dv_vlc_class_index_mask,%ebx,4),%edx
+ andl %eax,%edx
+- movl dv_vlc_class_index_rshift(,%ebx,4),%ecx
++ movl MUNG_ARR(dv_vlc_class_index_rshift,%ebx,4),%ecx
+ sarl %cl,%edx
+- movl dv_vlc_classes(,%ebx,4),%ecx
++ movl MUNG_ARR(dv_vlc_classes,%ebx,4),%ecx
+ movsbl (%ecx,%edx,1),%edx /* %edx is class */
+
+- movl dv_vlc_index_mask(,%edx,4),%ebx
+- movl dv_vlc_index_rshift(,%edx,4),%ecx
++ movl MUNG_ARR(dv_vlc_index_mask,%edx,4),%ebx
++ movl MUNG_ARR(dv_vlc_index_rshift,%edx,4),%ecx
+ andl %eax,%ebx
+ sarl %cl,%ebx
+
+- movl dv_vlc_lookups(,%edx,4),%edx
++ movl MUNG_ARR(dv_vlc_lookups,%edx,4),%edx
+ movl (%edx,%ebx,4),%edx
+
+ /* Now %edx holds result, like this:
+@@ -42,7 +51,7 @@ dv_decode_vlc:
+ movl %edx,%ecx
+ sarl $8,%ecx
+ andl $0xff,%ecx
+- movl sign_mask(,%ecx,4),%ebx
++ movl MUNG_ARR(sign_mask,%ecx,4),%ebx
+ andl %ebx,%eax
+ negl %eax
+ sarl $31,%eax
+@@ -63,14 +72,14 @@ dv_decode_vlc:
+ *result = broken;
+ Note that the 'broken' pattern is all ones (i.e. 0xffffffff)
+ */
+- movl 12(%esp),%ebx /* %ebx is maxbits */
++ movl 16(%esp),%ebx /* %ebx is maxbits */
+ subl %ecx,%ebx
+ sbbl %ebx,%ebx
+ orl %ebx,%edx
+
+- movl 16(%esp),%eax
++ movl 20(%esp),%eax
+ movl %edx,(%eax)
+-
++ popl %ebp
+ popl %ebx
+ ret
+
+@@ -80,21 +89,28 @@ dv_decode_vlc:
+ .type __dv_decode_vlc,@function
+ __dv_decode_vlc:
+ pushl %ebx
++ pushl %ebp
++
++ LOAD_PIC_REG(bp)
+
+- /* Args are at 8(%esp). */
+- movl 8(%esp),%eax /* %eax is bits */
++ /* Args are at 12(%esp). */
++ movl 12(%esp),%eax /* %eax is bits */
+
+ movl %eax,%edx /* %edx is class */
+ andl $0xfe00,%edx
+ sarl $9,%edx
++#ifdef __PIC__
++ movsbl dv_vlc_class_lookup5@GOTOFF(%ebp,%edx),%edx
++#else
+ movsbl dv_vlc_class_lookup5(%edx),%edx
+-
+- movl dv_vlc_index_mask(,%edx,4),%ebx
+- movl dv_vlc_index_rshift(,%edx,4),%ecx
++#endif
++
++ movl MUNG_ARR(dv_vlc_index_mask,%edx,4),%ebx
++ movl MUNG_ARR(dv_vlc_index_rshift,%edx,4),%ecx
+ andl %eax,%ebx
+ sarl %cl,%ebx
+
+- movl dv_vlc_lookups(,%edx,4),%edx
++ movl MUNG_ARR(dv_vlc_lookups,%edx,4),%edx
+ movl (%edx,%ebx,4),%edx
+
+ /* Now %edx holds result, like this:
+@@ -112,7 +128,7 @@ __dv_decode_vlc:
+ movl %edx,%ecx
+ sarl $8,%ecx
+ andl $0xff,%ecx
+- movl sign_mask(,%ecx,4),%ecx
++ movl MUNG_ARR(sign_mask,%ecx,4),%ecx
+ andl %ecx,%eax
+ negl %eax
+ sarl $31,%eax
+@@ -127,9 +143,9 @@ __dv_decode_vlc:
+ xorl %eax,%edx
+ subl %eax,%edx
+
+- movl 12(%esp),%eax
++ movl 16(%esp),%eax
+ movl %edx,(%eax)
+-
++ popl %ebp
+ popl %ebx
+ ret
+
+@@ -140,14 +156,20 @@ void dv_parse_ac_coeffs_pass0(bitstream_
+ */
+ .text
+ .align 4
++.globl asm_dv_parse_ac_coeffs_pass0
++.hidden asm_dv_parse_ac_coeffs_pass0
++ asm_dv_parse_ac_coeffs_pass0 = dv_parse_ac_coeffs_pass0
++
+ .globl dv_parse_ac_coeffs_pass0
+ .type dv_parse_ac_coeffs_pass0,@function
+ dv_parse_ac_coeffs_pass0:
+ pushl %ebx
+ pushl %edi
+ pushl %esi
+ pushl %ebp
+
++ LOAD_PIC_REG(si)
++
+ #define ARGn(N) (20+(4*(N)))(%esp)
+
+ /*
+@@ -159,8 +182,10 @@ dv_parse_ac_coeffs_pass0:
+ ebp bl
+ */
+ movl ARGn(2),%ebp
++#ifndef __PIC__
+ movl ARGn(0),%esi
+ movl bitstream_t_buf(%esi),%esi
++#endif
+ movl dv_block_t_offset(%ebp),%edi
+ movl dv_block_t_reorder(%ebp),%ebx
+
+@@ -170,7 +195,11 @@ dv_parse_ac_coeffs_pass0:
+
+ movq dv_block_t_coeffs(%ebp),%mm1
+ pxor %mm0,%mm0
++#ifdef __PIC__
++ pand const_f_0_0_0@GOTOFF(%esi),%mm1
++#else
+ pand const_f_0_0_0,%mm1
++#endif
+ movq %mm1,dv_block_t_coeffs(%ebp)
+ movq %mm0,(dv_block_t_coeffs + 8)(%ebp)
+ movq %mm0,(dv_block_t_coeffs + 16)(%ebp)
+@@ -191,9 +220,17 @@ dv_parse_ac_coeffs_pass0:
+ readloop:
+ movl %edi,%ecx
+ shrl $3,%ecx
++#ifdef __PIC__
++ movl ARGn(0),%eax
++ addl bitstream_t_buf(%eax),%ecx
++ movzbl (%ecx),%eax
++ movzbl 1(%ecx),%edx
++ movzbl 2(%ecx),%ecx
++#else
+ movzbl (%esi,%ecx,1),%eax
+ movzbl 1(%esi,%ecx,1),%edx
+ movzbl 2(%esi,%ecx,1),%ecx
++#endif
+ shll $16,%eax
+ shll $8,%edx
+ orl %ecx,%eax
+@@ -217,7 +254,11 @@ readloop:
+
+ /* Attempt to use the shortcut first. If it hits, then
+ this vlc term has been decoded. */
++#ifdef __PIC__
++ movl dv_vlc_class1_shortcut@GOTOFF(%esi,%ecx,4),%edx
++#else
+ movl dv_vlc_class1_shortcut(,%ecx,4),%edx
++#endif
+ test $0x80,%edx
+ je done_decode
+
+@@ -228,12 +269,19 @@ readloop:
+ movl %ebx,dv_block_t_reorder(%ebp)
+
+ /* %eax is bits */
+-
++#ifdef __PIC__
++ movsbl dv_vlc_class_lookup5@GOTOFF(%esi,%ecx),%ecx
++
++ movl dv_vlc_index_mask@GOTOFF(%esi,%ecx,4),%ebx
++ movl dv_vlc_lookups@GOTOFF(%esi,%ecx,4),%edx
++ movl dv_vlc_index_rshift@GOTOFF(%esi,%ecx,4),%ecx
++#else
+ movsbl dv_vlc_class_lookup5(%ecx),%ecx
+
+ movl dv_vlc_index_mask(,%ecx,4),%ebx
+ movl dv_vlc_lookups(,%ecx,4),%edx
+ movl dv_vlc_index_rshift(,%ecx,4),%ecx
++#endif
+ andl %eax,%ebx
+ sarl %cl,%ebx
+
+@@ -256,7 +304,11 @@ readloop:
+ movl %edx,%ecx
+ sarl $8,%ecx
+ andl $0xff,%ecx
++#ifdef __PIC__
++ movl sign_mask@GOTOFF(%esi,%ecx,4),%ecx
++#else
+ movl sign_mask(,%ecx,4),%ecx
++#endif
+ andl %ecx,%eax
+ negl %eax
+ sarl $31,%eax
+@@ -326,10 +378,16 @@ alldone:
+
+ slowpath:
+ /* slow path: use dv_decode_vlc */;
++#ifdef __PIC__
++ pushl %esi
++ leal vlc@GOTOFF(%esi),%esi
++ xchgl %esi,(%esp) /* last parameter is &vlc */
++#else
+ pushl $vlc /* last parameter is &vlc */
++#endif
+ pushl %edx /* bits_left */
+ pushl %eax /* bits */
+- call dv_decode_vlc
++ call asm_dv_decode_vlc
+ addl $12,%esp
+ test $0x80,%edx /* If (vlc.run < 0) break */
+ jne escape
+@@ -359,6 +417,8 @@ show16:
+ pushl %esi
+ pushl %ebp
+
++ LOAD_PIC_REG(si)
++
+ #define ARGn(N) (20+(4*(N)))(%esp)
+
+ movl ARGn(1),%eax /* quality */
+@@ -373,7 +434,11 @@ dv_parse_video_segment:
+ jz its_mono
+ movl $6,%ebx
+ its_mono:
++#ifdef __PIC__
++ movl %ebx,n_blocks@GOTOFF(%esi)
++#else
+ movl %ebx,n_blocks
++#endif
+
+ /*
+ * ebx seg/b
+@@ -384,15 +449,22 @@ its_mono:
+ * ebp bl
+ */
+ movl ARGn(0),%ebx
++#ifndef __PIC__
+ movl dv_videosegment_t_bs(%ebx),%esi
+ movl bitstream_t_buf(%esi),%esi
++#endif
+ leal dv_videosegment_t_mb(%ebx),%edi
+
+ movl $0,%eax
+ movl $0,%ecx
+ macloop:
++#ifdef __PIC__
++ movl %eax,m@GOTOFF(%esi)
++ movl %ecx,mb_start@GOTOFF(%esi)
++#else
+ movl %eax,m
+ movl %ecx,mb_start
++#endif
+
+ movl ARGn(0),%ebx
+
+@@ -400,7 +472,13 @@ macloop:
+ /* mb->qno = bitstream_get(bs,4); */
+ movl %ecx,%edx
+ shr $3,%edx
++#ifdef __PIC__
++ movl dv_videosegment_t_bs(%ebx),%ecx
++ movl bitstream_t_buf(%ecx),%ecx
++ movzbl 3(%ecx,%edx,1),%edx
++#else
+ movzbl 3(%esi,%edx,1),%edx
++#endif
+ andl $0xf,%edx
+ movl %edx,dv_macroblock_t_qno(%edi)
+
+@@ -411,7 +489,11 @@ macloop:
+ movl %edx,dv_macroblock_t_eob_count(%edi)
+
+ /* mb->i = (seg->i + dv_super_map_vertical[m]) % (seg->isPAL?12:10); */
++#ifdef __PIC__
++ movl dv_super_map_vertical@GOTOFF(%esi,%eax,4),%edx
++#else
+ movl dv_super_map_vertical(,%eax,4),%edx
++#endif
+ movl dv_videosegment_t_i(%ebx),%ecx
+ addl %ecx,%edx
+
+@@ -422,11 +504,20 @@ skarly:
+ andl $1,%ecx
+ shll $5,%ecx /* ecx = (isPAL ? 32 : 0) */
+
++#ifdef __PIC__
++ leal mod_10@GOTOFF(%esi),%edx
++ movzbl (%edx,%ecx,1),%edx /* uses mod_12 for PAL */
++#else
+ movzbl mod_10(%edx,%ecx,1),%edx /* uses mod_12 for PAL */
++#endif
+ movl %edx,dv_macroblock_t_i(%edi)
+
+ /* mb->j = dv_super_map_horizontal[m]; */
++#ifdef __PIC__
++ movl dv_super_map_horizontal@GOTOFF(%esi,%eax,4),%edx
++#else
+ movl dv_super_map_horizontal(,%eax,4),%edx
++#endif
+ movl %edx,dv_macroblock_t_j(%edi)
+
+ /* mb->k = seg->k; */
+@@ -445,12 +536,28 @@ blkloop:
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ */
+ /* dc = bitstream_get(bs,9); */
++#ifdef __PIC__
++ movl mb_start@GOTOFF(%esi),%ecx
++#else
+ movl mb_start,%ecx
++#endif
+ shr $3,%ecx
++#ifdef __PIC__
++ movzbl blk_start@GOTOFF(%esi,%ebx),%edx
++#else
+ movzbl blk_start(%ebx),%edx
++#endif
+ addl %ecx,%edx
++#ifdef __PIC__
++ movl ARGn(0),%ecx
++ movl dv_videosegment_t_bs(%ecx),%ecx
++ movl bitstream_t_buf(%ecx),%ecx
++ movzbl (%ecx,%edx,1),%eax /* hi byte */
++ movzbl 1(%ecx,%edx,1),%ecx /* lo byte */
++#else
+ movzbl (%esi,%edx,1),%eax /* hi byte */
+ movzbl 1(%esi,%edx,1),%ecx /* lo byte */
++#endif
+ shll $8,%eax
+ orl %ecx,%eax
+
+@@ -477,7 +584,11 @@ blkloop:
+
+ /* bl->reorder = &dv_reorder[bl->dct_mode][1]; */
+ shll $6,%eax
++#ifdef __PIC__
++ leal dv_reorder@GOTOFF+1(%esi,%eax),%eax
++#else
+ addl $(dv_reorder+1),%eax
++#endif
+ movl %eax,dv_block_t_reorder(%ebp)
+
+ /* bl->reorder_sentinel = bl->reorder + 63; */
+@@ -485,13 +596,22 @@ blkloop:
+ movl %eax,dv_block_t_reorder_sentinel(%ebp)
+
+ /* bl->offset= mb_start + dv_parse_bit_start[b]; */
++#ifdef __PIC__
++ movl mb_start@GOTOFF(%esi),%ecx
++ movl dv_parse_bit_start@GOTOFF(%esi,%ebx,4),%eax
++#else
+ movl mb_start,%ecx
+ movl dv_parse_bit_start(,%ebx,4),%eax
++#endif
+ addl %ecx,%eax
+ movl %eax,dv_block_t_offset(%ebp)
+
+ /* bl->end= mb_start + dv_parse_bit_end[b]; */
++#ifdef __PIC__
++ movl dv_parse_bit_end@GOTOFF(%esi,%ebx,4),%eax
++#else
+ movl dv_parse_bit_end(,%ebx,4),%eax
++#endif
+ addl %ecx,%eax
+ movl %eax,dv_block_t_end(%ebp)
+
+@@ -503,7 +623,11 @@ blkloop:
+ /* no AC pass. Just zero out the remaining coeffs */
+ movq dv_block_t_coeffs(%ebp),%mm1
+ pxor %mm0,%mm0
++#ifdef __PIC__
++ pand const_f_0_0_0@GOTOFF(%esi),%mm1
++#else
+ pand const_f_0_0_0,%mm1
++#endif
+ movq %mm1,dv_block_t_coeffs(%ebp)
+ movq %mm0,(dv_block_t_coeffs + 8)(%ebp)
+ movq %mm0,(dv_block_t_coeffs + 16)(%ebp)
+@@ -528,18 +652,27 @@ do_ac_pass:
+ pushl %ebp
+ pushl %edi
+ pushl %eax
+- call dv_parse_ac_coeffs_pass0
++ call asm_dv_parse_ac_coeffs_pass0
+ addl $12,%esp
+ done_ac:
+
++#ifdef __PIC__
++ movl n_blocks@GOTOFF(%esi),%eax
++#else
+ movl n_blocks,%eax
++#endif
+ addl $dv_block_t_size,%ebp
+ incl %ebx
+ cmpl %eax,%ebx
+ jnz blkloop
+
++#ifdef __PIC__
++ movl m@GOTOFF(%esi),%eax
++ movl mb_start@GOTOFF(%esi),%ecx
++#else
+ movl m,%eax
+ movl mb_start,%ecx
++#endif
+ addl $(8 * 80),%ecx
+ addl $dv_macroblock_t_size,%edi
+ incl %eax
+@@ -557,7 +690,7 @@ done_ac:
+
+ andl $DV_QUALITY_AC_MASK,%eax
+ cmpl $DV_QUALITY_AC_2,%eax
+- jz dv_parse_ac_coeffs
++ jz asm_dv_parse_ac_coeffs
+ movl $0,%eax
+ ret
+
diff --git a/main/libdvbpsi/APKBUILD b/main/libdvbpsi/APKBUILD
new file mode 100644
index 0000000000..c3c899a7b0
--- /dev/null
+++ b/main/libdvbpsi/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=libdvbpsi
+pkgver=0.1.7
+pkgrel=1
+pkgdesc="A library decoding and generating MPEG TS and DVB PSI tables"
+url="http://www.videolan.org/developers/libdvbpsi.html"
+arch="all"
+license="GPL"
+depends=
+makedepends=""
+subpackages="$pkgname-dev"
+source="http://download.videolan.org/pub/libdvbpsi/$pkgver/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --enable-release || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="af419575719e356b908b0c6946499052 libdvbpsi-0.1.7.tar.bz2"
diff --git a/main/libelf/APKBUILD b/main/libelf/APKBUILD
new file mode 100644
index 0000000000..82ad01352c
--- /dev/null
+++ b/main/libelf/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libelf
+pkgver=0.8.13
+pkgrel=1
+pkgdesc="libelf is a free ELF object file access library"
+url="http://www.mr511.de/software/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+subpackages="$pkgname-dev"
+source="http://www.mr511.de/software/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-shared \
+ --enable-gnu-names \
+ --enable-compat || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make install prefix="$pkgdir"/usr || return 1
+}
+md5sums="4136d7b4c04df68b686570afa26988ac libelf-0.8.13.tar.gz"
diff --git a/main/libetpan/APKBUILD b/main/libetpan/APKBUILD
new file mode 100644
index 0000000000..32c232da0f
--- /dev/null
+++ b/main/libetpan/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libetpan
+pkgver=1.0
+pkgrel=5
+pkgdesc="a portable middleware for email access"
+url="http://www.etpan.org/"
+arch="all"
+license="custom:etpan"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="db-dev cyrus-sasl-dev curl-dev expat-dev openssl-dev"
+depends=
+depends_dev="cyrus-sasl-dev db-dev"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-openssl \
+ --disable-static
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYRIGHT "$pkgdir"/usr/share/licenses/$pkgname/license.txt
+}
+md5sums="5addc766141a0b1d29ee1ca4ba1b6808 libetpan-1.0.tar.gz"
diff --git a/main/libev/APKBUILD b/main/libev/APKBUILD
new file mode 100644
index 0000000000..83afe50a0d
--- /dev/null
+++ b/main/libev/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libev
+pkgver=4.04
+pkgrel=1
+pkgdesc="event dispatch library"
+url="http://libev.schmorp.de/"
+arch="all"
+license="BSD GPL"
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://dist.schmorp.de/${pkgname}/${pkgname}-${pkgver}.tar.gz"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/include/event.h \
+ "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="c1130d0a4782681ba5277df1bc3fb335 libev-4.04.tar.gz"
diff --git a/main/libevent/APKBUILD b/main/libevent/APKBUILD
new file mode 100644
index 0000000000..20b8f712ee
--- /dev/null
+++ b/main/libevent/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libevent
+pkgver=2.0.12
+pkgrel=1
+pkgdesc="An event notification library"
+url="http://www.monkey.org/~provos/libevent/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends=
+subpackages="$pkgname-dev"
+source="http://www.monkey.org/~provos/$pkgname-$pkgver-stable.tar.gz"
+
+build() {
+ cd $srcdir/$pkgname-$pkgver-stable
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd $srcdir/$pkgname-$pkgver-stable
+ make -j1 DESTDIR=$pkgdir install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="42986228baf95e325778ed328a93e070 libevent-2.0.12-stable.tar.gz"
diff --git a/main/libexif/APKBUILD b/main/libexif/APKBUILD
new file mode 100644
index 0000000000..6a13217d61
--- /dev/null
+++ b/main/libexif/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libexif
+pkgver=0.6.20
+pkgrel=1
+pkgdesc="A library to parse an EXIF file and read the data from those tags"
+url="http://sourceforge.net/projects/libexif"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends=
+source="http://downloads.sf.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="19844ce6b5d075af16f0d45de1e8a6a3 libexif-0.6.20.tar.bz2"
diff --git a/main/libffi/APKBUILD b/main/libffi/APKBUILD
new file mode 100644
index 0000000000..2c534db8e2
--- /dev/null
+++ b/main/libffi/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libffi
+pkgver=3.0.9
+pkgrel=5
+pkgdesc="A portable, high level programming interface to various calling conventions."
+url="http://sourceware.org/libffi"
+arch="all"
+license="MIT"
+depends=
+makedepends="texinfo"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://sourceware.org/pub/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build () {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR=""$pkgdir"" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -m755 -d ""$pkgdir"/usr/share/licenses/$pkgname"
+ install -m644 LICENSE ""$pkgdir"/usr/share/licenses/$pkgname/" || return 1
+}
+md5sums="1f300a7a7f975d4046f51c3022fa5ff1 libffi-3.0.9.tar.gz"
diff --git a/main/libfontenc/APKBUILD b/main/libfontenc/APKBUILD
new file mode 100644
index 0000000000..c352715c90
--- /dev/null
+++ b/main/libfontenc/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libfontenc
+pkgver=1.1.0
+pkgrel=2
+pkgdesc="X11 font encoding library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig xproto zlib-dev"
+subpackages="$pkgname-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --with-encodingsdir=/usr/share/fonts/encodings
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="11d3c292f05a90f6f67840a9e9c3d9b8 libfontenc-1.1.0.tar.bz2"
diff --git a/main/libgcrypt/APKBUILD b/main/libgcrypt/APKBUILD
new file mode 100644
index 0000000000..76ab3c06a0
--- /dev/null
+++ b/main/libgcrypt/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgcrypt
+pkgver=1.4.6
+pkgrel=2
+pkgdesc="general purpose crypto library based on the code used in GnuPG"
+url="http://www.gnupg.org"
+arch="all"
+license="LGPL"
+depends=
+makedepends="libgpg-error-dev texinfo"
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.franken.de/pub/crypt/mirror/ftp.gnupg.org/gcrypt/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="libgpg-error-dev"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --build=${CHOST:-i486-alpine-linux-uclibc} \
+ --prefix=/usr \
+ --enable-padlock-support \
+ --disable-static
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ rm -f ${pkgdir}/usr/share/info/dir
+}
+md5sums="dbf99425a4fe9217c84ce3a35d938634 libgcrypt-1.4.6.tar.bz2"
diff --git a/main/libgcrypt/nocxx.patch b/main/libgcrypt/nocxx.patch
new file mode 100644
index 0000000000..beb1ab9006
--- /dev/null
+++ b/main/libgcrypt/nocxx.patch
@@ -0,0 +1,15 @@
+--- a/configure 2004-12-07 21:34:23.205172545 +0000
++++ b/configure 2004-12-07 21:37:17.726654782 +0000
+@@ -5148,10 +5148,8 @@
+ :
+ else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&5
+-echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&2;}
+- { (exit 1); exit 1; }; }
++See \`config.log' for more details." >&5;}
++ { echo "C++ sucks, ignoring ..." >&5; }; }
+ fi
+
+ ac_ext=cc
diff --git a/main/libgee/APKBUILD b/main/libgee/APKBUILD
new file mode 100644
index 0000000000..04298aa1c1
--- /dev/null
+++ b/main/libgee/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgee
+pkgver=0.6.1
+pkgrel=1
+pkgdesc="GObject collection library"
+url="http://live.gnome.org/Libgee"
+arch="all"
+license="LGPL2.1"
+depends=""
+makedepends=" glib-dev"
+subpackages="$pkgname-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/libgee/${pkgver%.*}/libgee-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="9cf60f41f3aa10ac7f1f7e1d094e05a1 libgee-0.6.1.tar.bz2"
diff --git a/main/libgexiv2/APKBUILD b/main/libgexiv2/APKBUILD
new file mode 100644
index 0000000000..2d589cd3e7
--- /dev/null
+++ b/main/libgexiv2/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgexiv2
+pkgver=0.3.0
+pkgrel=1
+pkgdesc="a GObject-based wrapper around the Exiv2 library"
+url="http://trac.yorba.org/wiki/gexiv2"
+arch="all"
+license="GPL"
+depends=
+depends_dev="glib-dev exiv2-dev"
+makedepends="exiv2-dev glib-dev libtool m4"
+install=
+subpackages="$pkgname-dev"
+source="http://yorba.org/download/gexiv2/${pkgver%.*}/libgexiv2-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="b6b2b2ae3c7d57a85d8c346b418ff98c libgexiv2-0.3.0.tar.bz2"
diff --git a/main/libglade/APKBUILD b/main/libglade/APKBUILD
new file mode 100644
index 0000000000..e46002e81a
--- /dev/null
+++ b/main/libglade/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libglade
+pkgver=2.6.4
+pkgrel=9
+pkgdesc="Allows you to load glade interface files in a program at runtime"
+url="http://www.gnome.org"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="libxml2-utils"
+makedepends="python pkgconfig gtk+-dev libxml2-dev"
+install="$pkgname.post-install $pkgname.pre-upgrade $pkgname.post-upgrade
+ $pkgname.post-deinstall"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/2.6/$pkgname-$pkgver.tar.bz2
+ $pkgname-2.0.1-nowarning.patch
+ "
+
+depends_dev="gtk+-dev libxml2-dev"
+_builddir="$srcdir"/$pkgname-$pkgver
+package() {
+ cd "$_builddir"
+ patch -Np1 -i "$srcdir"/libglade-2.0.1-nowarning.patch || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --sysconfdir=/etc \
+ --prefix=/usr \
+ --disable-static \
+ --localstatedir=/var || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -m755 libglade-convert "$pkgdir"/usr/bin/ || return 1
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="d1776b40f4e166b5e9c107f1c8fe4139 libglade-2.6.4.tar.bz2
+4f879c0ce550004905aa0fb24f25c353 libglade-2.0.1-nowarning.patch"
diff --git a/main/libglade/libglade-2.0.1-nowarning.patch b/main/libglade/libglade-2.0.1-nowarning.patch
new file mode 100644
index 0000000000..fd071215fa
--- /dev/null
+++ b/main/libglade/libglade-2.0.1-nowarning.patch
@@ -0,0 +1,39 @@
+--- libglade-2.0.1/glade/glade-gtk.c.nowarning 2003-08-29 14:50:10.000000000 -0400
++++ libglade-2.0.1/glade/glade-gtk.c 2003-08-29 14:58:41.000000000 -0400
+@@ -639,9 +639,8 @@
+ if (!strcmp (childinfo->properties[j].name, "label")) {
+ label = childinfo->properties[j].value;
+ break;
+- } else {
+- g_warning ("Unknown CList child property: %s", childinfo->properties[j].name);
+ }
++ /* Ignore all other properties */
+ }
+
+ if (label) {
+@@ -683,6 +682,7 @@
+ char *icon = NULL;
+ gboolean use_stock = FALSE, active = FALSE, new_group = FALSE;
+ gboolean use_underline = FALSE;
++ gboolean sensitive = TRUE;
+ GtkWidget *iconw = NULL;
+ int j;
+
+@@ -708,6 +708,8 @@
+ group_name = value;
+ } else if (!strcmp (name, "new_group")) {
+ new_group = BOOL (value);
++ } else if (!strcmp (name, "sensitive")) {
++ sensitive = BOOL (value);
+ } else if (!strcmp (name, "visible")) {
+ /* ignore for now */
+ } else if (!strcmp (name, "tooltip")) {
+@@ -785,6 +787,8 @@
+ gtk_label_set_use_underline (GTK_LABEL (toolbar_child->label),
+ TRUE);
+ }
++
++ gtk_widget_set_sensitive (child, sensitive);
+
+ glade_xml_set_common_params (xml, child, childinfo->child);
+ } else {
diff --git a/main/libglade/libglade.post-deinstall b/main/libglade/libglade.post-deinstall
new file mode 100644
index 0000000000..bb4b3039a0
--- /dev/null
+++ b/main/libglade/libglade.post-deinstall
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+xmlcatalog --noout --del \
+ /usr/share/xml/libglade/glade-2.0.dtd etc/xml/catalog
+
+exit 0
diff --git a/main/libglade/libglade.post-install b/main/libglade/libglade.post-install
new file mode 100644
index 0000000000..82e58a85fe
--- /dev/null
+++ b/main/libglade/libglade.post-install
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+mkdir -p etc/xml
+
+if [ ! -e etc/xml/catalog ]; then
+ xmlcatalog --noout --create etc/xml/catalog
+fi
+
+xmlcatalog --noout --add "system" \
+ "http://glade.gnome.org/glade-2.0.dtd" \
+ /usr/share/xml/libglade/glade-2.0.dtd etc/xml/catalog
+
+exit 0
diff --git a/main/libglade/libglade.post-upgrade b/main/libglade/libglade.post-upgrade
new file mode 120000
index 0000000000..25d67c626e
--- /dev/null
+++ b/main/libglade/libglade.post-upgrade
@@ -0,0 +1 @@
+libglade.post-install \ No newline at end of file
diff --git a/main/libglade/libglade.pre-upgrade b/main/libglade/libglade.pre-upgrade
new file mode 120000
index 0000000000..06b72fb37b
--- /dev/null
+++ b/main/libglade/libglade.pre-upgrade
@@ -0,0 +1 @@
+libglade.post-deinstall \ No newline at end of file
diff --git a/main/libgnome-keyring/APKBUILD b/main/libgnome-keyring/APKBUILD
new file mode 100644
index 0000000000..89e4a4bd8e
--- /dev/null
+++ b/main/libgnome-keyring/APKBUILD
@@ -0,0 +1,60 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=libgnome-keyring
+pkgver=2.32.0
+pkgrel=1
+pkgdesc="GNOME keyring"
+url="http://www.gnome.org"
+arch="all"
+license="GPL"
+depends="gnome-keyring"
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ libwnck-dev
+
+ libgcrypt-dev
+ libtasn1-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install=
+subpackages="$pkgname-dev"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="c42b2ca66204835d901d3dbfc1fa5ae6 libgnome-keyring-2.32.0.tar.bz2"
diff --git a/main/libgnome/APKBUILD b/main/libgnome/APKBUILD
new file mode 100644
index 0000000000..67ada29b48
--- /dev/null
+++ b/main/libgnome/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgnome
+pkgver=2.32.1
+pkgrel=2
+pkgdesc="GNOME base library"
+url="http://www.gnome.org/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="gtk+-dev gconf-dev libcanberra-dev gnome-vfs-dev libbonobo-dev"
+makedepends="$depends_dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.acc.umu.se/pub/gnome/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="a4345e6087ae6195d65a4674ffdca559 libgnome-2.32.1.tar.bz2"
diff --git a/main/libgnome/libgnome.post-install b/main/libgnome/libgnome.post-install
new file mode 100644
index 0000000000..89ba3aca5e
--- /dev/null
+++ b/main/libgnome/libgnome.post-install
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+for i in \
+ desktop_gnome_accessibility_keyboard.schemas \
+ desktop_gnome_accessibility_startup.schemas \
+ desktop_gnome_applications_at_mobility.schemas \
+ desktop_gnome_applications_at_visual.schemas \
+ desktop_gnome_applications_browser.schemas \
+ desktop_gnome_applications_office.schemas \
+ desktop_gnome_applications_terminal.schemas \
+ desktop_gnome_applications_window_manager.schemas \
+ desktop_gnome_background.schemas \
+ desktop_gnome_file_views.schemas \
+ desktop_gnome_interface.schemas \
+ desktop_gnome_lockdown.schemas \
+ desktop_gnome_peripherals_keyboard.schemas \
+ desktop_gnome_peripherals_mouse.schemas \
+ desktop_gnome_sound.schemas \
+ desktop_gnome_thumbnail_cache.schemas \
+ desktop_gnome_thumbnailers.schemas \
+ desktop_gnome_typing_break.schemas \
+; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i > /dev/null
+done
diff --git a/main/libgnome/libgnome.post-upgrade b/main/libgnome/libgnome.post-upgrade
new file mode 100644
index 0000000000..89ba3aca5e
--- /dev/null
+++ b/main/libgnome/libgnome.post-upgrade
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+for i in \
+ desktop_gnome_accessibility_keyboard.schemas \
+ desktop_gnome_accessibility_startup.schemas \
+ desktop_gnome_applications_at_mobility.schemas \
+ desktop_gnome_applications_at_visual.schemas \
+ desktop_gnome_applications_browser.schemas \
+ desktop_gnome_applications_office.schemas \
+ desktop_gnome_applications_terminal.schemas \
+ desktop_gnome_applications_window_manager.schemas \
+ desktop_gnome_background.schemas \
+ desktop_gnome_file_views.schemas \
+ desktop_gnome_interface.schemas \
+ desktop_gnome_lockdown.schemas \
+ desktop_gnome_peripherals_keyboard.schemas \
+ desktop_gnome_peripherals_mouse.schemas \
+ desktop_gnome_sound.schemas \
+ desktop_gnome_thumbnail_cache.schemas \
+ desktop_gnome_thumbnailers.schemas \
+ desktop_gnome_typing_break.schemas \
+; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i > /dev/null
+done
diff --git a/main/libgnome/libgnome.pre-deinstall b/main/libgnome/libgnome.pre-deinstall
new file mode 100644
index 0000000000..5a070981ee
--- /dev/null
+++ b/main/libgnome/libgnome.pre-deinstall
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+for i in \
+ desktop_gnome_accessibility_keyboard.schemas \
+ desktop_gnome_accessibility_startup.schemas \
+ desktop_gnome_applications_at_mobility.schemas \
+ desktop_gnome_applications_at_visual.schemas \
+ desktop_gnome_applications_browser.schemas \
+ desktop_gnome_applications_office.schemas \
+ desktop_gnome_applications_terminal.schemas \
+ desktop_gnome_applications_window_manager.schemas \
+ desktop_gnome_background.schemas \
+ desktop_gnome_file_views.schemas \
+ desktop_gnome_interface.schemas \
+ desktop_gnome_lockdown.schemas \
+ desktop_gnome_peripherals_keyboard.schemas \
+ desktop_gnome_peripherals_mouse.schemas \
+ desktop_gnome_sound.schemas \
+ desktop_gnome_thumbnail_cache.schemas \
+ desktop_gnome_thumbnailers.schemas \
+ desktop_gnome_typing_break.schemas \
+; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i > /dev/null
+done
diff --git a/main/libgnomekbd/APKBUILD b/main/libgnomekbd/APKBUILD
new file mode 100644
index 0000000000..2c44972669
--- /dev/null
+++ b/main/libgnomekbd/APKBUILD
@@ -0,0 +1,53 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer:
+pkgname=libgnomekbd
+pkgver=2.32.0
+pkgrel=1
+pkgdesc="GNOME keyboard library"
+url="http://www.gnome.org/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="gtk+-dev
+ gconf-dev
+ libxklavier-dev
+ libxml2-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev"
+makedepends="$depends_dev intltool"
+install=""
+subpackages="$pkgname-dev"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="de32a6e3e3464b566eecdc4332bf34bd libgnomekbd-2.32.0.tar.bz2"
diff --git a/main/libgnomekbd/libgnomekbd.post-install b/main/libgnomekbd/libgnomekbd.post-install
new file mode 100644
index 0000000000..34508a6a76
--- /dev/null
+++ b/main/libgnomekbd/libgnomekbd.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in desktop_gnome_peripherals_keyboard_xkb.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/libgnomekbd/libgnomekbd.post-upgrade b/main/libgnomekbd/libgnomekbd.post-upgrade
new file mode 100644
index 0000000000..34508a6a76
--- /dev/null
+++ b/main/libgnomekbd/libgnomekbd.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in desktop_gnome_peripherals_keyboard_xkb.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/libgnomekbd/libgnomekbd.pre-deinstall b/main/libgnomekbd/libgnomekbd.pre-deinstall
new file mode 100644
index 0000000000..4cfd37ac2e
--- /dev/null
+++ b/main/libgnomekbd/libgnomekbd.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in desktop_gnome_peripherals_keyboard_xkb.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/libgpg-error/APKBUILD b/main/libgpg-error/APKBUILD
new file mode 100644
index 0000000000..5703cde87e
--- /dev/null
+++ b/main/libgpg-error/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgpg-error
+pkgver=1.9
+pkgrel=2
+pkgdesc="Support library for libgcrypt"
+url="http://www.gnupg.org"
+arch="all"
+license="LGPL"
+depends=""
+subpackages="$pkgname-dev $pkgname-lisp"
+source="ftp://ftp.franken.de/pub/crypt/mirror/ftp.gnupg.org/gcrypt/$pkgname/$pkgname-$pkgver.tar.bz2
+ "
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-nls
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+lisp() {
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/share "$subpkgdir"/usr/share/
+}
+
+md5sums="521b98aa9395e7eaf0ef2236233a0796 libgpg-error-1.9.tar.bz2"
diff --git a/main/libgphoto2/APKBUILD b/main/libgphoto2/APKBUILD
new file mode 100644
index 0000000000..da8189ff1c
--- /dev/null
+++ b/main/libgphoto2/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgphoto2
+pkgver=2.4.10.1
+pkgrel=2
+pkgdesc="The core library of gphoto2, designed to allow access to digital camera by external programs."
+url="http://www.gphoto.org"
+arch="all"
+license="LGPL"
+depends=""
+depends_dev="libexif-dev libusb-compat-dev"
+makedepends="libexif-dev jpeg-dev libtool libusb-compat-dev libiconv-dev"
+install="$pkgname.pre-install $pkgname.pre-upgrade"
+subpackages="$pkgname-dev $pkgname-doc"
+replaces="libgphoto2-dev"
+source="http://downloads.sourceforge.net/gphoto/libgphoto2-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ udevscriptdir=/lib/udev ./configure --prefix=/usr \
+ --with-drivers=all \
+ --disable-static \
+ --disable-rpath \
+ || return 1
+ LD_PRELOAD="" make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/libgphoto2/*/*.a \
+ "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/*.a
+
+ install -m755 -d "$pkgdir/lib/udev/rules.d"
+ LD_LIBRARY_PATH="$pkgdir/usr/lib${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH" \
+ CAMLIBS="$pkgdir/usr/lib/libgphoto2/$pkgver" \
+ "$pkgdir/usr/lib/libgphoto2/print-camera-list" udev-rules version 136 group camera mode 0660 > "$pkgdir/lib/udev/rules.d/54-gphoto.rules" || return 1
+}
+
+dev() {
+ default_dev
+ # move back .la files for libltdl
+ mv "$subpkgdir"/usr/lib/libgphoto2/$pkgver/*.la \
+ "$pkgdir"/usr/lib/libgphoto2/$pkgver/
+}
+
+md5sums="362cd914c64b2363f4d0bd5ad07c7209 libgphoto2-2.4.10.1.tar.bz2"
diff --git a/main/libgphoto2/libgphoto2.pre-install b/main/libgphoto2/libgphoto2.pre-install
new file mode 100644
index 0000000000..a7d31448b8
--- /dev/null
+++ b/main/libgphoto2/libgphoto2.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if ! getent group camera >/dev/null; then
+ addgroup -S camera
+fi
+
diff --git a/main/libgphoto2/libgphoto2.pre-upgrade b/main/libgphoto2/libgphoto2.pre-upgrade
new file mode 120000
index 0000000000..bc38b3b082
--- /dev/null
+++ b/main/libgphoto2/libgphoto2.pre-upgrade
@@ -0,0 +1 @@
+libgphoto2.pre-install \ No newline at end of file
diff --git a/main/libgsf/APKBUILD b/main/libgsf/APKBUILD
new file mode 100644
index 0000000000..2310e91f9e
--- /dev/null
+++ b/main/libgsf/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgsf
+pkgver=1.14.21
+pkgrel=1
+pkgdesc="The GNOME Structured File Library is a utility library for reading and writing structured file formats."
+url="http://www.gnome.org/"
+arch="all"
+license="GPL LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="libxml2-dev glib-dev bzip2-dev intltool python zlib-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/$pkgname/1.14/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev bzip2-dev libxml2-dev pkgconfig"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ sed -i -e 's/gsf-gnome//' -e 's/thumbnailer//' Makefile.* || return 1
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --mandir=/usr/share/man \
+ --disable-static \
+ --without-gnome-vfs \
+ --without-bonobo || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ rm -f "$pkgdir"/usr/share/man/man1/gsf-office-thumbnailer.1
+}
+
+md5sums="2b702648b853402554c97d75405c60d3 libgsf-1.14.21.tar.bz2"
diff --git a/main/libgssglue/APKBUILD b/main/libgssglue/APKBUILD
new file mode 100644
index 0000000000..81bca94c41
--- /dev/null
+++ b/main/libgssglue/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgssglue
+pkgver=0.1
+pkgrel=3
+pkgdesc="exports a gssapi interface which calls other random gssapi libraries"
+url="http://www.citi.umich.edu/projects/nfsv4/linux/"
+arch="all"
+license="BSD"
+depends=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.citi.umich.edu/projects/nfsv4/linux/$pkgname/$pkgname-$pkgver.tar.gz
+ gssapi_mech.conf"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir/" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m 644 ../gssapi_mech.conf "$pkgdir/"etc/gssapi_mech.conf
+ install -D -m644 COPYING $pkgdir/usr/share/licenses/libgssglue/COPYING
+}
+md5sums="ce1b4c758e6de01b712d154c5c97e540 libgssglue-0.1.tar.gz
+234b9cca75a33af98eda3f1683756879 gssapi_mech.conf"
diff --git a/main/libgssglue/gssapi_mech.conf b/main/libgssglue/gssapi_mech.conf
new file mode 100644
index 0000000000..f71aca08ee
--- /dev/null
+++ b/main/libgssglue/gssapi_mech.conf
@@ -0,0 +1,22 @@
+# Example /etc/gssapi_mech.conf file
+#
+# GSSAPI Mechanism Definitions
+#
+# This configuration file determines which GSS-API mechanisms
+# the gssd code should use
+#
+# NOTE:
+# The initiaiization function "mechglue_internal_krb5_init"
+# is used for the MIT krb5 gssapi mechanism. This special
+# function name indicates that an internal function should
+# be used to determine the entry points for the MIT gssapi
+# mechanism funtions.
+#
+# library initialization function
+# ================================ ==========================
+# The MIT K5 gssapi library, use special function for initialization.
+#/usr/lib/libgssapi_krb5.so mechglue_internal_krb5_init
+/usr/lib/libgssapi.so mechglue_internal_krb5_init
+#
+# The SPKM3 gssapi library function. Use the function spkm3_gss_initialize.
+# /usr/local/gss_mechs/spkm/spkm3/libgssapi_spkm3.so spkm3_gss_initialize
diff --git a/main/libgtop/APKBUILD b/main/libgtop/APKBUILD
new file mode 100644
index 0000000000..206ea32df0
--- /dev/null
+++ b/main/libgtop/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libgtop
+pkgver=2.28.3
+pkgrel=1
+pkgdesc="GNOME top library"
+url="http://www.gnome.org/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="glib-dev libxau-dev libx11-dev"
+makedepends="$depends_dev intltool"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="2d6a3c7c1efffd0854b8d24d1d29d8ef libgtop-2.28.3.tar.bz2"
diff --git a/main/libguess/APKBUILD b/main/libguess/APKBUILD
new file mode 100644
index 0000000000..a967cdda76
--- /dev/null
+++ b/main/libguess/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=libguess
+pkgver=1.0
+pkgrel=0
+pkgdesc="extremely fast character set guessing library"
+url="http://atheme.org/project/libguess"
+arch="all"
+license="ISC"
+depends=
+makedepends="libmowgli-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://distfiles.atheme.org/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # workaround bug in busybox
+ sed -e "/touch/s/0001010000/200001010000/g" \
+ -i configure
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="89ef9296162a9b5baf32a321d9e367c0 libguess-1.0.tgz"
diff --git a/main/libgweather/APKBUILD b/main/libgweather/APKBUILD
new file mode 100644
index 0000000000..cb0fd1e7a9
--- /dev/null
+++ b/main/libgweather/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer:
+pkgname=libgweather
+pkgver=2.30.3
+pkgrel=1
+pkgdesc="GNOME weather library"
+url="http://www.gnome.org/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="gtk+-dev libsoup-dev libxml2-dev gconf-dev"
+makedepends="$depends_dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --with-zoneinfo-dir=. \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="bf6a0a05051341ecb250f332e3edfb88 libgweather-2.30.3.tar.bz2"
diff --git a/main/libgweather/libgweather.post-install b/main/libgweather/libgweather.post-install
new file mode 100644
index 0000000000..c9c323078a
--- /dev/null
+++ b/main/libgweather/libgweather.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gweather.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/libgweather/libgweather.post-upgrade b/main/libgweather/libgweather.post-upgrade
new file mode 100644
index 0000000000..c9c323078a
--- /dev/null
+++ b/main/libgweather/libgweather.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gweather.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/libgweather/libgweather.pre-deinstall b/main/libgweather/libgweather.pre-deinstall
new file mode 100644
index 0000000000..30dad25f8d
--- /dev/null
+++ b/main/libgweather/libgweather.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in gweather.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/libical/APKBUILD b/main/libical/APKBUILD
new file mode 100644
index 0000000000..f0cb1c2dfb
--- /dev/null
+++ b/main/libical/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libical
+pkgver=0.46
+pkgrel=2
+pkgdesc="An open source reference implementation of the icalendar data type and serialization format"
+url="http://sourceforge.net/projects/freeassociation/"
+arch="all"
+license="LGPL MPL"
+depends=
+makedepends="perl autoconf automake libtool"
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/freeassociation/$pkgname-$pkgver.tar.gz"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ aclocal && autoheader && autoconf && automake -a || return 1
+ libtoolize --force
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-shared \
+ --disable-static \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="9c08f88945bfd5d0791d102e4aa4125c libical-0.46.tar.gz"
diff --git a/main/libice/APKBUILD b/main/libice/APKBUILD
new file mode 100644
index 0000000000..3ad148eba4
--- /dev/null
+++ b/main/libice/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libice
+pkgver=1.0.7
+pkgrel=2
+pkgdesc="X11 Inter-Client Exchange library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig xproto xtrans"
+subpackages="$pkgname-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libICE-$pkgver.tar.bz2"
+
+depends_dev="xproto"
+build () {
+ cd "$srcdir"/libICE-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libICE-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="bb72a732b15e9dc25c3036559387eed5 libICE-1.0.7.tar.bz2"
diff --git a/main/libiconv/APKBUILD b/main/libiconv/APKBUILD
new file mode 100644
index 0000000000..1a1202fd55
--- /dev/null
+++ b/main/libiconv/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Carlo Landmeter <clandmeter at gmail.com>
+pkgname=libiconv
+pkgver=1.12
+pkgrel=6
+pkgdesc="GNU charset conversion library for libc which doesn't implement it"
+url="http://www.gnu.org/software/libiconv"
+arch="all"
+license='LGPL'
+depends=""
+source="http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.12.tar.gz"
+subpackages="$pkgname-doc $pkgname-dev"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ #only build if we need it
+ if [ "$ALPINE_LIBC" != "eglibc" ]; then
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+ fi
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ #if we use eglibc we install dummy libiconv
+ if [ "$ALPINE_LIBC" = "eglibc" ]; then
+ mkdir -p "$pkgdir"/usr/include "$pkgdir"/usr/share/doc
+ else
+ make DESTDIR="$pkgdir/" install
+ rm "$pkgdir"/usr/lib/*.la
+ fi
+}
+
+
+md5sums="c2be282595751535a618ae0edeb8f648 libiconv-1.12.tar.gz"
diff --git a/main/libid3tag/APKBUILD b/main/libid3tag/APKBUILD
new file mode 100644
index 0000000000..aaee71faec
--- /dev/null
+++ b/main/libid3tag/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=libid3tag
+pkgver=0.15.1b
+pkgrel=5
+pkgdesc="id3 tagger for mp3"
+url="http://www.underbit.com/products/mad/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="zlib-dev"
+install=
+subpackages="$pkgname-dev"
+source="ftp://ftp.mars.org/pub/mpeg/libid3tag-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+}
+
+md5sums="e5808ad997ba32c498803822078748c3 libid3tag-0.15.1b.tar.gz"
diff --git a/main/libidl/APKBUILD b/main/libidl/APKBUILD
new file mode 100644
index 0000000000..9d218e7e63
--- /dev/null
+++ b/main/libidl/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=libidl
+pkgver=0.8.14
+pkgrel=1
+pkgdesc="library for parsing Interface Definition Language files"
+url="http://www.gnome.org/"
+license="GPL"
+arch="all"
+depends=
+depends_dev="glib-dev"
+makedepends="${depends_dev} flex bison"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/gnome/sources/libIDL/${pkgver%.*}/libIDL-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/libIDL-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="bb8e10a218fac793a52d404d14adedcb libIDL-0.8.14.tar.bz2"
diff --git a/main/libidn/APKBUILD b/main/libidn/APKBUILD
new file mode 100644
index 0000000000..9190b3a5a4
--- /dev/null
+++ b/main/libidn/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libidn
+pkgver=1.22
+pkgrel=1
+pkgdesc="An encode and decode library for internationalized domain names"
+url="http://www.gnu.org/software/libidn/"
+arch="all"
+license="GPL"
+depends=
+makedepends=""
+install=
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://ftp.gnu.org/gnu/libidn/$pkgname-$pkgver.tar.gz"
+
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="893a1df0cf3b28b72d248382eaeaca71 libidn-1.22.tar.gz"
diff --git a/main/libiec61883/APKBUILD b/main/libiec61883/APKBUILD
new file mode 100644
index 0000000000..359da78dba
--- /dev/null
+++ b/main/libiec61883/APKBUILD
@@ -0,0 +1,51 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libiec61883
+pkgver=1.2.0
+pkgrel=1
+pkgdesc="Streaming library for IEEE1394"
+url="http://ieee1394.wiki.kernel.org/index.php/Libraries#libiec61883"
+arch="all"
+license="LGPLv2+"
+depends=
+depends_dev="libraw1394-dev"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-utils"
+source="http://www.kernel.org/pub/linux/libs/ieee1394/libiec61883-$pkgver.tar.gz"
+
+_builddir="$srcdir"/libiec61883-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" INSTALL="install -p" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+utils() {
+ pkgdesc="Utilities for use with libiec61883"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="8af39fff74988073c3ad53fbab147da9 libiec61883-1.2.0.tar.gz"
diff --git a/main/libksba/APKBUILD b/main/libksba/APKBUILD
new file mode 100644
index 0000000000..5bdbcfacc7
--- /dev/null
+++ b/main/libksba/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libksba
+pkgver=1.0.8
+pkgrel=2
+pkgdesc="Libksba is a CMS and X.509 access library"
+url="ftp://ftp.gnupg.org/gcrypt/alpha/libksba"
+arch="all"
+license="GPL"
+depends=
+makedepends="libgpg-error-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnupg.org/gcrypt/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="8acac0b3cbd0030dfc6d0f6a58c9b5b2 libksba-1.0.8.tar.bz2"
diff --git a/main/liblockfile/APKBUILD b/main/liblockfile/APKBUILD
new file mode 100644
index 0000000000..6f471cb11d
--- /dev/null
+++ b/main/liblockfile/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Duane Hughes <duanejevon@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=liblockfile
+pkgver=1.08
+pkgrel=0
+pkgdesc="Shared library with NFS-safe locking functions"
+url="http://packages.debian.org/sid/liblockfile1"
+arch="all"
+license="GPL"
+depends=""
+makedepends=
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.debian.org/debian/pool/main/libl/liblockfile/${pkgname}_$pkgver.orig.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man
+ make -j1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ install -d "$pkgdir"/usr/include
+ install -d "$pkgdir"/usr/bin
+ install -d "$pkgdir"/usr/lib
+ install -d "$pkgdir"/usr/share/man
+
+ make -j1 ROOT="$pkgdir" install
+}
+
+md5sums="c24e2dfb4a2aab0263fe5ac1564d305e liblockfile_1.08.orig.tar.gz"
diff --git a/main/libmad/APKBUILD b/main/libmad/APKBUILD
new file mode 100644
index 0000000000..9688b7d523
--- /dev/null
+++ b/main/libmad/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Sebastian Wicki <gandro@gmx.net>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmad
+pkgver=0.15.1b
+pkgrel=5
+pkgdesc="A high-quality MPEG audio decoder"
+url="http://www.underbit.com/products/mad/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev"
+depends=
+makedepends="autoconf automake libtool"
+source="http://downloads.sourceforge.net/sourceforge/mad/$pkgname-$pkgver.tar.gz
+ libmad-0.15.1b-cflags-O2.patch
+ libmad-0.15.1b-cflags.patch
+ mad.pc
+ "
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -Np1 -i $i || return 1
+ done
+
+ aclocal && autoconf && ./missing --run automake --foreign \
+ && libtoolize --force || return 1
+
+ ./configure --prefix=/usr \
+ --enable-fpm=intel \
+ --enable-accuracy
+
+ make -j1 || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 "$srcdir"/mad.pc "$pkgdir"/usr/lib/pkgconfig/mad.pc
+}
+md5sums="1be543bc30c56fb6bea1d7bf6a64e66c libmad-0.15.1b.tar.gz
+fbda7a1821e2038221deb3f476da034d libmad-0.15.1b-cflags-O2.patch
+bcd6eab331fc316baf4e9c9882fe13f4 libmad-0.15.1b-cflags.patch
+89806934195402446d21d1a83f523b11 mad.pc"
diff --git a/main/libmad/libmad-0.15.1b-cflags-O2.patch b/main/libmad/libmad-0.15.1b-cflags-O2.patch
new file mode 100644
index 0000000000..61b4b13bd7
--- /dev/null
+++ b/main/libmad/libmad-0.15.1b-cflags-O2.patch
@@ -0,0 +1,12 @@
+diff -Naur libmad-0.15.1b-orig/configure.ac libmad-0.15.1b/configure.ac
+--- libmad-0.15.1b-orig/configure.ac 2007-07-01 12:58:13.000000000 -0600
++++ libmad-0.15.1b/configure.ac 2007-07-01 12:59:13.000000000 -0600
+@@ -105,7 +105,7 @@
+ shift
+ ;;
+ -O2)
+- optimize="-O"
++ optimize="-O2"
+ shift
+ ;;
+ -fomit-frame-pointer)
diff --git a/main/libmad/libmad-0.15.1b-cflags.patch b/main/libmad/libmad-0.15.1b-cflags.patch
new file mode 100644
index 0000000000..2ec44e3445
--- /dev/null
+++ b/main/libmad/libmad-0.15.1b-cflags.patch
@@ -0,0 +1,146 @@
+diff -Naur libmad-0.15.1b-orig/configure.ac libmad-0.15.1b/configure.ac
+--- libmad-0.15.1b-orig/configure.ac 2007-06-30 20:22:31.000000000 -0600
++++ libmad-0.15.1b/configure.ac 2007-06-30 20:25:31.000000000 -0600
+@@ -122,74 +122,74 @@
+ esac
+ done
+
+-if test "$GCC" = yes
+-then
+- if test -z "$arch"
+- then
+- case "$host" in
+- i386-*) ;;
+- i?86-*) arch="-march=i486" ;;
+- arm*-empeg-*) arch="-march=armv4 -mtune=strongarm1100" ;;
+- armv4*-*) arch="-march=armv4 -mtune=strongarm" ;;
+- powerpc-*) ;;
+- mips*-agenda-*) arch="-mcpu=vr4100" ;;
+- mips*-luxsonor-*) arch="-mips1 -mcpu=r3000 -Wa,-m4010" ;;
+- esac
+- fi
+-
+- case "$optimize" in
+- -O|"-O "*)
+- optimize="-O"
+- optimize="$optimize -fforce-mem"
+- optimize="$optimize -fforce-addr"
+- : #x optimize="$optimize -finline-functions"
+- : #- optimize="$optimize -fstrength-reduce"
+- optimize="$optimize -fthread-jumps"
+- optimize="$optimize -fcse-follow-jumps"
+- optimize="$optimize -fcse-skip-blocks"
+- : #x optimize="$optimize -frerun-cse-after-loop"
+- : #x optimize="$optimize -frerun-loop-opt"
+- : #x optimize="$optimize -fgcse"
+- optimize="$optimize -fexpensive-optimizations"
+- optimize="$optimize -fregmove"
+- : #* optimize="$optimize -fdelayed-branch"
+- : #x optimize="$optimize -fschedule-insns"
+- optimize="$optimize -fschedule-insns2"
+- : #? optimize="$optimize -ffunction-sections"
+- : #? optimize="$optimize -fcaller-saves"
+- : #> optimize="$optimize -funroll-loops"
+- : #> optimize="$optimize -funroll-all-loops"
+- : #x optimize="$optimize -fmove-all-movables"
+- : #x optimize="$optimize -freduce-all-givs"
+- : #? optimize="$optimize -fstrict-aliasing"
+- : #* optimize="$optimize -fstructure-noalias"
+-
+- case "$host" in
+- arm*-*)
+- optimize="$optimize -fstrength-reduce"
+- ;;
+- mips*-*)
+- optimize="$optimize -fstrength-reduce"
+- optimize="$optimize -finline-functions"
+- ;;
+- i?86-*)
+- optimize="$optimize -fstrength-reduce"
+- ;;
+- powerpc-apple-*)
+- # this triggers an internal compiler error with gcc2
+- : #optimize="$optimize -fstrength-reduce"
+-
+- # this is really only beneficial with gcc3
+- : #optimize="$optimize -finline-functions"
+- ;;
+- *)
+- # this sometimes provokes bugs in gcc 2.95.2
+- : #optimize="$optimize -fstrength-reduce"
+- ;;
+- esac
+- ;;
+- esac
+-fi
++#if test "$GCC" = yes
++#then
++# if test -z "$arch"
++# then
++# case "$host" in
++# i386-*) ;;
++# i?86-*) arch="-march=i486" ;;
++# arm*-empeg-*) arch="-march=armv4 -mtune=strongarm1100" ;;
++# armv4*-*) arch="-march=armv4 -mtune=strongarm" ;;
++# powerpc-*) ;;
++# mips*-agenda-*) arch="-mcpu=vr4100" ;;
++# mips*-luxsonor-*) arch="-mips1 -mcpu=r3000 -Wa,-m4010" ;;
++# esac
++# fi
++#
++# case "$optimize" in
++# -O|"-O "*)
++# optimize="-O"
++# optimize="$optimize -fforce-mem"
++# optimize="$optimize -fforce-addr"
++# : #x optimize="$optimize -finline-functions"
++# : #- optimize="$optimize -fstrength-reduce"
++# optimize="$optimize -fthread-jumps"
++# optimize="$optimize -fcse-follow-jumps"
++# optimize="$optimize -fcse-skip-blocks"
++# : #x optimize="$optimize -frerun-cse-after-loop"
++# : #x optimize="$optimize -frerun-loop-opt"
++# : #x optimize="$optimize -fgcse"
++# optimize="$optimize -fexpensive-optimizations"
++# optimize="$optimize -fregmove"
++# : #* optimize="$optimize -fdelayed-branch"
++# : #x optimize="$optimize -fschedule-insns"
++# optimize="$optimize -fschedule-insns2"
++# : #? optimize="$optimize -ffunction-sections"
++# : #? optimize="$optimize -fcaller-saves"
++# : #> optimize="$optimize -funroll-loops"
++# : #> optimize="$optimize -funroll-all-loops"
++# : #x optimize="$optimize -fmove-all-movables"
++# : #x optimize="$optimize -freduce-all-givs"
++# : #? optimize="$optimize -fstrict-aliasing"
++# : #* optimize="$optimize -fstructure-noalias"
++#
++# case "$host" in
++# arm*-*)
++# optimize="$optimize -fstrength-reduce"
++# ;;
++# mips*-*)
++# optimize="$optimize -fstrength-reduce"
++# optimize="$optimize -finline-functions"
++# ;;
++# i?86-*)
++# optimize="$optimize -fstrength-reduce"
++# ;;
++# powerpc-apple-*)
++# # this triggers an internal compiler error with gcc2
++# : #optimize="$optimize -fstrength-reduce"
++#
++# # this is really only beneficial with gcc3
++# : #optimize="$optimize -finline-functions"
++# ;;
++# *)
++# # this sometimes provokes bugs in gcc 2.95.2
++# : #optimize="$optimize -fstrength-reduce"
++# ;;
++# esac
++# ;;
++# esac
++#fi
+
+ case "$host" in
+ mips*-agenda-*)
diff --git a/main/libmad/mad.pc b/main/libmad/mad.pc
new file mode 100644
index 0000000000..14a66f5525
--- /dev/null
+++ b/main/libmad/mad.pc
@@ -0,0 +1,11 @@
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: mad
+Description: MPEG Audio Decoder
+Requires:
+Version: 0.15.0b
+Libs: -L${libdir} -lmad -lm
+Cflags: -I${includedir}
diff --git a/main/libmcrypt/APKBUILD b/main/libmcrypt/APKBUILD
new file mode 100644
index 0000000000..2edbed5163
--- /dev/null
+++ b/main/libmcrypt/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=libmcrypt
+pkgver=2.5.8
+pkgrel=7
+pkgdesc="A library which provides a uniform interface to several symmetric encryption algorithms"
+url="http://mcrypt.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="libtool"
+install=
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://downloads.sourceforge.net/mcrypt/${pkgname}-${pkgver}.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --disable-posix-threads
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="c4f491dd411a09e9de3b8702ea6f73eb libmcrypt-2.5.8.tar.bz2"
diff --git a/main/libmcs/APKBUILD b/main/libmcs/APKBUILD
new file mode 100644
index 0000000000..b21a1cddcd
--- /dev/null
+++ b/main/libmcs/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=libmcs
+pkgver=0.7.2
+pkgrel=0
+pkgdesc="library for configuration system abstraction"
+url="http://atheme.org/project/mcs"
+arch="all"
+license="ISC"
+depends=
+makedepends="libmowgli-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://distfiles.atheme.org/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # workaround bug in busybox
+ sed -e "/touch/s/0001010000/200001010000/g" \
+ -i configure
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="c47fc81f3efacaa0a5a0b8fd14f9d48e libmcs-0.7.2.tgz"
diff --git a/main/libmicrohttpd/APKBUILD b/main/libmicrohttpd/APKBUILD
new file mode 100644
index 0000000000..406ca88c03
--- /dev/null
+++ b/main/libmicrohttpd/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmicrohttpd
+pkgver=0.9.11
+pkgrel=1
+pkgdesc="a small C library that is supposed to make it easy to run an HTTP server as part of another application."
+url="http://www.gnu.org/software/libmicrohttpd/"
+arch="all"
+license="GPL"
+depends=
+makedepends="curl-dev libgcrypt-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnu.org/gnu/libmicrohttpd/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-largefile \
+ --enable-curl \
+ --enable-messages
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 "$_builddir"/src/include/platform.h \
+ "$pkgdir"/usr/include/platform.h
+ install -Dm644 "$_builddir"/src/include/plibc/plibc.h \
+ "$pkgdir"/usr/include/plibc.h
+}
+
+md5sums="69b97b11437e53863e92d5f0221f339b libmicrohttpd-0.9.11.tar.gz"
diff --git a/main/libmikmod/APKBUILD b/main/libmikmod/APKBUILD
new file mode 100644
index 0000000000..b5db8df47f
--- /dev/null
+++ b/main/libmikmod/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmikmod
+pkgver=3.1.11
+pkgrel=1
+pkgdesc="module playing library"
+url="http://mikmod.raphnet.net/"
+arch="all"
+license="GPL"
+depends=
+depends_dev=
+makedepends="alsa-lib-dev $depends_dev"
+install=""
+subpackages="$pkgname-dev"
+source="http://mikmod.raphnet.net/files/libmikmod-3.1.11.tar.gz"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --enable-alsa || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="705106da305e8de191549f1e7393185c libmikmod-3.1.11.tar.gz"
diff --git a/main/libmms/APKBUILD b/main/libmms/APKBUILD
new file mode 100644
index 0000000000..010998c441
--- /dev/null
+++ b/main/libmms/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmms
+pkgver=0.6
+pkgrel=2
+pkgdesc="MMS stream protocol library"
+url="http://sourceforge.net/projects/libmms/"
+arch="all"
+license="LGPL"
+depends=
+makedepends="pkgconfig glib-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ libmms-0.5-this-keyword.patch
+"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ patch -p1 -i "$srcdir"/libmms-0.5-this-keyword.patch || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="650ad04a4c8bd79246390b81b29680b6 libmms-0.6.tar.gz
+5266259060f5723d8ee639b8a541f835 libmms-0.5-this-keyword.patch"
diff --git a/main/libmms/libmms-0.5-this-keyword.patch b/main/libmms/libmms-0.5-this-keyword.patch
new file mode 100644
index 0000000000..9d5ae762e3
--- /dev/null
+++ b/main/libmms/libmms-0.5-this-keyword.patch
@@ -0,0 +1,18 @@
+diff -Nurp libmms-0.5.orig//src/mmsx.h libmms-0.5//src/mmsx.h
+--- libmms-0.5.orig//src/mmsx.h 2010-03-03 11:42:14.000000000 +0100
++++ libmms-0.5//src/mmsx.h 2010-03-03 11:42:46.000000000 +0100
+@@ -55,11 +55,11 @@ int mmsx_peek_header (mmsx_t *inst
+
+ mms_off_t mmsx_get_current_pos (mmsx_t *instance);
+
+-uint32_t mmsx_get_asf_header_len (mmsx_t *this);
++uint32_t mmsx_get_asf_header_len (mmsx_t *instance);
+
+-uint64_t mmsx_get_asf_packet_len (mmsx_t *this);
++uint64_t mmsx_get_asf_packet_len (mmsx_t *instance);
+
+-int mmsx_get_seekable (mmsx_t *this);
++int mmsx_get_seekable (mmsx_t *instance);
+
+ #ifdef __cplusplus
+ }
diff --git a/main/libmng/APKBUILD b/main/libmng/APKBUILD
new file mode 100644
index 0000000000..cf35ab98f0
--- /dev/null
+++ b/main/libmng/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmng
+pkgver=1.0.10
+pkgrel=1
+pkgdesc="A collection of routines used to create and manipulate MNG format graphics files"
+url="http://www.libmng.com/"
+arch="all"
+license="custom"
+depends=""
+depends_dev="jpeg-dev"
+makedepends="zlib-dev jpeg-dev autoconf automake libtool"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/sourceforge/libmng/libmng-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ ln -s makefiles/configure.in .
+ ln -s makefiles/Makefile.am .
+ autoreconf --force --install
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="a464ae7d679781beebdf7440d144b7bd libmng-1.0.10.tar.gz"
diff --git a/main/libmodplug/APKBUILD b/main/libmodplug/APKBUILD
new file mode 100644
index 0000000000..5eefba853c
--- /dev/null
+++ b/main/libmodplug/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmodplug
+pkgver=0.8.8.1
+pkgrel=2
+pkgdesc="A MOD playing library"
+url="http://modplug-xmms.sourceforge.net/"
+arch="all"
+license="custom"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/modplug-xmms/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 COPYING ${pkgdir}/usr/share/licenses/${pkgname}/LICENSE
+}
+
+md5sums="f7fa53a60c650024ff51cca88341776b libmodplug-0.8.8.1.tar.gz"
diff --git a/main/libmowgli/APKBUILD b/main/libmowgli/APKBUILD
new file mode 100644
index 0000000000..a05a22a4cb
--- /dev/null
+++ b/main/libmowgli/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=libmowgli
+pkgver=0.9.50
+pkgrel=0
+pkgdesc="mowgli is a framework designed to reduce writing of boilerplate code"
+url="http://atheme.org/project/mowgli"
+arch="all"
+license="ISC"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev"
+source="http://nenolod.net/~nenolod/$pkgname-$pkgver.tar.bz2"
+#source="http://distfiles.atheme.org/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # workaround bug in busybox
+ sed -e "/touch/s/0001010000/200001010000/g" \
+ -i configure
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="104cafd29fe874377169cb7e81c7b50f libmowgli-0.9.50.tar.bz2"
diff --git a/main/libmpc/APKBUILD b/main/libmpc/APKBUILD
new file mode 100644
index 0000000000..2fb1129351
--- /dev/null
+++ b/main/libmpc/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmpc
+pkgver=0.9
+pkgrel=1
+pkgdesc="Multiprecision C library"
+url="http://www.multiprecision.org/"
+arch="all"
+license="LGPL-2.1"
+depends=
+makedepends="gmp-dev mpfr-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.multiprecision.org/mpc/download/mpc-$pkgver.tar.gz"
+
+_builddir="$srcdir"/mpc-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ # workaround for a bug in configure script
+ EGREP=egrep \
+ ./configure --prefix=/usr \
+ --build=${CBUILD} \
+ --host=${CHOST} \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-shared \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="0d6acab8d214bd7d1fbbc593e83dd00d mpc-0.9.tar.gz"
diff --git a/main/libmpdclient/APKBUILD b/main/libmpdclient/APKBUILD
new file mode 100644
index 0000000000..c1bdaca3b2
--- /dev/null
+++ b/main/libmpdclient/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmpdclient
+pkgver=2.4
+pkgrel=1
+pkgdesc="An asynchronous API library for interfacing MPD in the C, C++ & Objective C languages"
+url="http://mpd.wikia.com/wiki/Client:libmpdclient"
+arch="all"
+license="GPL2"
+depends=
+makedepends=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/musicpd/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="8c166c5212dd95d538d3a35bb9ad4634 libmpdclient-2.4.tar.bz2"
diff --git a/main/libmpeg2/APKBUILD b/main/libmpeg2/APKBUILD
new file mode 100644
index 0000000000..3b67503734
--- /dev/null
+++ b/main/libmpeg2/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libmpeg2
+pkgver=0.5.1
+pkgrel=6
+pkgdesc="libmpeg2 is a library for decoding MPEG-1 and MPEG-2 video streams."
+url="http://libmpeg2.sourceforge.net/"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-dev $pkgname-doc mpeg2dec"
+depends=
+makedepends="libx11-dev libice-dev libsm-dev libxext-dev libxv-dev"
+source="http://$pkgname.sourceforge.net/files/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-shared \
+ --disable-static || return 1
+ make OPT_CFLAGS="${CFLAGS}" \
+ MPEG2DEC_CFLAGS="${CFLAGS}" \
+ LIBMPEG2_CFLAGS="" || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+mpeg2dec() {
+ pkgdesc="a test program for libmpeg2"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/mpeg2dec "$subpkgdir"/usr/bin/
+}
+
+md5sums="0f92c7454e58379b4a5a378485bbd8ef libmpeg2-0.5.1.tar.gz"
diff --git a/main/libnet/APKBUILD b/main/libnet/APKBUILD
new file mode 100644
index 0000000000..caf48407e5
--- /dev/null
+++ b/main/libnet/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libnet
+pkgver=1.1.5
+pkgrel=2
+pkgdesc="A generic networking API that provides access to several protocols."
+url="http://sourceforge.net/projects/libnet-dev/"
+arch="all"
+license="BSD"
+depends=
+makedepends="autoconf automake libtool"
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/project/libnet-dev/libnet-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="a9bc1d75a610efcfee200d3e28d8eb8f libnet-1.1.5.tar.gz"
diff --git a/main/libnetcf/APKBUILD b/main/libnetcf/APKBUILD
new file mode 100644
index 0000000000..5e27adda44
--- /dev/null
+++ b/main/libnetcf/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor:
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=libnetcf
+_realname=netcf
+pkgver=0.1.7
+pkgrel=1
+pkgdesc="Cross-platform network configuration library"
+arch="all"
+url="https://fedorahosted.org/released/netcf"
+license="LGPLv2"
+depends=
+makedepends="augeas-dev libgcrypt-dev libnl-dev libxml2-dev libxslt-dev
+ pkgconfig readline-dev wget"
+install=
+subpackages="$pkgname-dev"
+source="https://fedorahosted.org/released/$_realname/$_realname-0.1.7.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+#prepare() {
+# cd "$_builddir"
+# patch -p1 < ../netcf-0.1.0-fix-initialization-of-libxslt.patch || return 1
+#}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="8e313b623c907eb035cf3948b71fecc2 netcf-0.1.7.tar.gz"
diff --git a/main/libnetfilter_conntrack/APKBUILD b/main/libnetfilter_conntrack/APKBUILD
new file mode 100644
index 0000000000..15f41fc034
--- /dev/null
+++ b/main/libnetfilter_conntrack/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libnetfilter_conntrack
+pkgver=0.9.1
+pkgrel=1
+pkgdesc="programming interface (API) to the in-kernel connection tracking state table"
+url="http://www.netfilter.org/projects/libnetfilter_conntrack/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="pkgconfig libnfnetlink-dev"
+subpackages="$pkgname-dev"
+source="http://www.netfilter.org/projects/$pkgname/files/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="b7506cbb7580433859809d8eac53a199 libnetfilter_conntrack-0.9.1.tar.bz2"
diff --git a/main/libnfnetlink/APKBUILD b/main/libnfnetlink/APKBUILD
new file mode 100644
index 0000000000..fe1162f63f
--- /dev/null
+++ b/main/libnfnetlink/APKBUILD
@@ -0,0 +1,30 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libnfnetlink
+pkgver=1.0.0
+pkgrel=5
+pkgdesc="low-level library for netfilter related kernel/userspace communication"
+url="http://www.netfilter.org/projects/libnfnetlink/"
+arch="all"
+license="GPL-2"
+depends=""
+makedepends=""
+subpackages="$pkgname-dev"
+source="http://www.netfilter.org/projects/libnfnetlink/files/libnfnetlink-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="016fdec8389242615024c529acc1adb8 libnfnetlink-1.0.0.tar.bz2"
diff --git a/main/libnih/APKBUILD b/main/libnih/APKBUILD
new file mode 100644
index 0000000000..18de63cf31
--- /dev/null
+++ b/main/libnih/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=libnih
+pkgver=1.0.3
+pkgrel=0
+pkgdesc="glib-like library for embedded use"
+url="http://launchpad.net/libnih"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="dbus-dev expat-dev gettext-dev"
+makedepends="$depends_dev pkgconfig"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://launchpad.net/libnih/${pkgver%.*}/${pkgver}/+download/${pkgname}-${pkgver}.tar.gz"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --libdir=/lib \
+ --sysconfdir=/etc \
+ --localstatedir=/var || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="db7990ce55e01daffe19006524a1ccb0 libnih-1.0.3.tar.gz"
diff --git a/main/libnl/APKBUILD b/main/libnl/APKBUILD
new file mode 100644
index 0000000000..49089fdcf3
--- /dev/null
+++ b/main/libnl/APKBUILD
@@ -0,0 +1,45 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libnl
+pkgver=1.1
+pkgrel=4
+pkgdesc="Library for applications dealing with netlink sockets"
+url="http://people.suug.ch/~tgr/libnl"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+subpackages="$pkgname-dev"
+source="http://distfiles.gentoo.org/distfiles/$pkgname-$pkgver.tar.gz
+ libnl-1.1-flags.patch
+ libnl-1.1-minor-leaks.patch
+ libnl-1.1-vlan-header.patch
+ libnl-1.1-glibc-2.8-ULONG_MAX.patch
+ "
+
+_builddir="$srcdir"/libnl-$pkgver
+
+prepare () {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ [ -r "$i" ] || continue
+ msg "Applying $i"
+ patch -s -p1 -i $i || return 1
+ done
+}
+
+build () {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="ae970ccd9144e132b68664f98e7ceeb1 libnl-1.1.tar.gz
+9c9072ac8b74135798e0ebcf2d90290d libnl-1.1-flags.patch
+3a42f98cfb353f2469ac3c44b7c0a027 libnl-1.1-minor-leaks.patch
+d757127e7af3bd3c82cdb51b1b09d2e0 libnl-1.1-vlan-header.patch
+9169c7eec8a2b4b2556dd26ac73c6020 libnl-1.1-glibc-2.8-ULONG_MAX.patch"
diff --git a/main/libnl/libnl-1.1-flags.patch b/main/libnl/libnl-1.1-flags.patch
new file mode 100644
index 0000000000..bb09b36266
--- /dev/null
+++ b/main/libnl/libnl-1.1-flags.patch
@@ -0,0 +1,11 @@
+--- libnl-1.1/lib/Makefile.orig 2008-01-14 16:48:45.000000000 +0100
++++ libnl-1.1/lib/Makefile 2009-05-26 09:47:42.000000000 +0200
+@@ -48,7 +48,7 @@
+
+ $(OUT_SLIB): ../Makefile.opts $(OBJ)
+ @echo " LD $(OUT_SLIB)"; \
+- $(CC) -shared -Wl,-soname,libnl.so.1 -o $(OUT_SLIB) $(OBJ) $(LIBNL_LIB) -lc
++ $(CC) $(CFLAGS) $(LDFLAGS) -shared -Wl,-soname,libnl.so.1 -o $(OUT_SLIB) $(OBJ) $(LIBNL_LIB) -lc
+ @echo " LN $(OUT_SLIB) $(LN1_SLIB)"; \
+ rm -f $(LN1_SLIB) ; $(LN) -s $(OUT_SLIB) $(LN1_SLIB)
+ @echo " LN $(LN1_SLIB) $(LN_SLIB)"; \
diff --git a/main/libnl/libnl-1.1-glibc-2.8-ULONG_MAX.patch b/main/libnl/libnl-1.1-glibc-2.8-ULONG_MAX.patch
new file mode 100644
index 0000000000..c4082cbab0
--- /dev/null
+++ b/main/libnl/libnl-1.1-glibc-2.8-ULONG_MAX.patch
@@ -0,0 +1,13 @@
+https://bugs.gentoo.org/show_bug.cgi?id=225393
+
+--- a/include/netlink-local.h 2008-06-09 07:54:20 +0000
++++ b/include/netlink-local.h 2008-06-09 07:54:47 +0000
+@@ -26,6 +26,7 @@
+ #include <sys/socket.h>
+ #include <inttypes.h>
+ #include <assert.h>
++#include <limits.h>
+
+ #include <arpa/inet.h>
+ #include <netdb.h>
+
diff --git a/main/libnl/libnl-1.1-minor-leaks.patch b/main/libnl/libnl-1.1-minor-leaks.patch
new file mode 100644
index 0000000000..855a6ab391
--- /dev/null
+++ b/main/libnl/libnl-1.1-minor-leaks.patch
@@ -0,0 +1,40 @@
+From: Patrick McHardy <kaber@trash.net>
+Date: Fri, 18 Jan 2008 16:55:49 +0000 (+0100)
+Subject: [LIBNL]: Fix minor memleaks on exit
+X-Git-Url: http://git.kernel.org/?p=libs%2Fnetlink%2Flibnl.git;a=commitdiff_plain;h=b64f15d6f947839236fa276d473d238f8c9b9d57;hp=e91bb2ffb090955d443e643a25b250bf3d33534a
+
+[LIBNL]: Fix minor memleaks on exit
+
+Make valgrind happy ...
+
+Signed-off-by: Patrick McHardy <kaber@trash.net>
+---
+
+diff --git a/lib/route/route_utils.c b/lib/route/route_utils.c
+index a12d169..1386cda 100644
+--- a/lib/route/route_utils.c
++++ b/lib/route/route_utils.c
+@@ -63,6 +63,11 @@ static void __init init_routing_table_names(void)
+ add_routing_table_name(RT_TABLE_LOCAL, "local");
+ };
+
++static void __exit release_routing_table_names(void)
++{
++ __trans_list_clear(&table_names);
++}
++
+ int rtnl_route_read_table_names(const char *path)
+ {
+ __trans_list_clear(&table_names);
+@@ -104,6 +109,11 @@ static void __init init_proto_names(void)
+ add_proto_name(RTPROT_STATIC, "static");
+ };
+
++static void __exit release_proto_names(void)
++{
++ __trans_list_clear(&proto_names);
++}
++
+ int rtnl_route_read_protocol_names(const char *path)
+ {
+ __trans_list_clear(&proto_names);
diff --git a/main/libnl/libnl-1.1-vlan-header.patch b/main/libnl/libnl-1.1-vlan-header.patch
new file mode 100644
index 0000000000..c4c2fc6382
--- /dev/null
+++ b/main/libnl/libnl-1.1-vlan-header.patch
@@ -0,0 +1,80 @@
+From: Patrick McHardy <kaber@trash.net>
+Date: Fri, 18 Jan 2008 16:55:48 +0000 (+0100)
+Subject: [LIBNL]: Add if_vlan.h
+X-Git-Url: http://git.kernel.org/?p=libs%2Fnetlink%2Flibnl.git;a=commitdiff_plain;h=e91bb2ffb090955d443e643a25b250bf3d33534a;hp=7f6b7a8eea0334b34d58dec72c66121a76f08958
+
+[LIBNL]: Add if_vlan.h
+
+vlan support needs VLAN_FLAG_REORDER_HDR, which is not available in
+older if_vlan.h versions. Add the current version from the kernel.
+
+Signed-off-by: Patrick McHardy <kaber@trash.net>
+---
+
+diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
+new file mode 100644
+index 0000000..068cd7b
+--- /dev/null
++++ include/linux/if_vlan.h
+@@ -0,0 +1,61 @@
++/*
++ * VLAN An implementation of 802.1Q VLAN tagging.
++ *
++ * Authors: Ben Greear <greearb@candelatech.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.
++ *
++ */
++
++#ifndef _LINUX_IF_VLAN_H_
++#define _LINUX_IF_VLAN_H_
++
++
++/* VLAN IOCTLs are found in sockios.h */
++
++/* Passed in vlan_ioctl_args structure to determine behaviour. */
++enum vlan_ioctl_cmds {
++ ADD_VLAN_CMD,
++ DEL_VLAN_CMD,
++ SET_VLAN_INGRESS_PRIORITY_CMD,
++ SET_VLAN_EGRESS_PRIORITY_CMD,
++ GET_VLAN_INGRESS_PRIORITY_CMD,
++ GET_VLAN_EGRESS_PRIORITY_CMD,
++ SET_VLAN_NAME_TYPE_CMD,
++ SET_VLAN_FLAG_CMD,
++ GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
++ GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
++};
++
++enum vlan_flags {
++ VLAN_FLAG_REORDER_HDR = 0x1,
++};
++
++enum vlan_name_types {
++ VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */
++ VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */
++ VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like: vlan5 */
++ VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like: eth0.5 */
++ VLAN_NAME_TYPE_HIGHEST
++};
++
++struct vlan_ioctl_args {
++ int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */
++ char device1[24];
++
++ union {
++ char device2[24];
++ int VID;
++ unsigned int skb_priority;
++ unsigned int name_type;
++ unsigned int bind_type;
++ unsigned int flag; /* Matches vlan_dev_info flags */
++ } u;
++
++ short vlan_qos;
++};
++
++#endif /* !(_LINUX_IF_VLAN_H_) */
diff --git a/main/libnotify/APKBUILD b/main/libnotify/APKBUILD
new file mode 100644
index 0000000000..23d14e6753
--- /dev/null
+++ b/main/libnotify/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libnotify
+pkgver=0.5.2
+pkgrel=2
+pkgdesc="Desktop notification library"
+url="http://www.galago-project.org/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="dbus-glib-dev gtk+-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+depends_dev="gtk+-dev glib-dev dbus-dev dbus-glib-dev"
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="4361058ae4e28a9ffce6764e7d03acd1 libnotify-0.5.2.tar.bz2"
diff --git a/main/libogg/APKBUILD b/main/libogg/APKBUILD
new file mode 100644
index 0000000000..5a9d651bbb
--- /dev/null
+++ b/main/libogg/APKBUILD
@@ -0,0 +1,30 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libogg
+pkgver=1.2.2
+pkgrel=1
+pkgdesc="Ogg bitstream and framing library"
+url="http://xiph.org/ogg/"
+arch="all"
+license="as-is"
+depends=
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://downloads.xiph.org/releases/ogg/$pkgname-$pkgver.tar.gz
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+md5sums="5a9fcabc9a1b7c6f1cd75ddc78f36c56 libogg-1.2.2.tar.gz"
diff --git a/main/libogg/nocxx.patch b/main/libogg/nocxx.patch
new file mode 100644
index 0000000000..beb1ab9006
--- /dev/null
+++ b/main/libogg/nocxx.patch
@@ -0,0 +1,15 @@
+--- a/configure 2004-12-07 21:34:23.205172545 +0000
++++ b/configure 2004-12-07 21:37:17.726654782 +0000
+@@ -5148,10 +5148,8 @@
+ :
+ else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&5
+-echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&2;}
+- { (exit 1); exit 1; }; }
++See \`config.log' for more details." >&5;}
++ { echo "C++ sucks, ignoring ..." >&5; }; }
+ fi
+
+ ac_ext=cc
diff --git a/main/liboil/APKBUILD b/main/liboil/APKBUILD
new file mode 100644
index 0000000000..a28283c120
--- /dev/null
+++ b/main/liboil/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=liboil
+pkgver=0.3.17
+pkgrel=5
+pkgdesc="Library of simple functions that are optimized for various CPUs."
+url="http://liboil.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+source="http://$pkgname.freedesktop.org/download/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ unset CFLAGS
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -m755 -d "$pkgdir"/usr/share/licenses/liboil
+ install -m644 COPYING "$pkgdir"/usr/share/licenses/liboil/ || return 1
+}
+md5sums="47dc734f82faeb2964d97771cfd2e701 liboil-0.3.17.tar.gz"
diff --git a/main/libotr/APKBUILD b/main/libotr/APKBUILD
new file mode 100644
index 0000000000..daaaa2cad9
--- /dev/null
+++ b/main/libotr/APKBUILD
@@ -0,0 +1,55 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+pkgname=libotr
+pkgver=3.2.0
+pkgrel=1
+pkgdesc="Off The Record Messaging, an encryption library for secure IM conversations"
+url="http://otr.cypherpunks.ca/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="libgcrypt-dev"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc:doc $pkgname-tools:tools"
+source="http://www.cypherpunks.ca/otr/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+tools() {
+ license="GPL"
+ depends="$pkgname"
+ cd "$_builddir"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+doc() {
+ depends="$pkgname"
+ cd "$_builddir"
+ install -Dm0644 Protocol-v2.html "$subpkgdir"/usr/share/doc/$pkgname/Protocol-v2.html
+ install -Dm0644 README "$subpkgdir"/usr/share/doc/$pkgname/README
+}
+
+md5sums="faba02e60f64e492838929be2272f839 libotr-3.2.0.tar.gz"
diff --git a/main/libowfat/APKBUILD b/main/libowfat/APKBUILD
new file mode 100644
index 0000000000..7ac2932f8b
--- /dev/null
+++ b/main/libowfat/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libowfat
+pkgver=0.28
+pkgrel=1
+pkgdesc="reimplementation of libdjb"
+url="http://www.fefe.de/libowfat/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://dl.fefe.de/libowfat-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make prefix="$pkgdir"/usr MAN3DIR="$pkgdir"/usr/share/man/man3 install
+ # buffer manpage conflicts with openssl
+ mv "$pkgdir"/usr/share/man/man3/buffer.3 \
+ "$pkgdir"/usr/share/man/man3/owfatbuffer.3
+}
+
+md5sums="6bbee9a86506419657d87123b7a6f2c1 libowfat-0.28.tar.bz2"
diff --git a/main/libpaper/APKBUILD b/main/libpaper/APKBUILD
new file mode 100644
index 0000000000..7bddda58e5
--- /dev/null
+++ b/main/libpaper/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libpaper
+pkgver=1.1.24
+pkgrel=2
+pkgdesc="Library for handling paper characteristics"
+url="http://packages.debian.org/unstable/source/libpaper"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="bash"
+makedepends=""
+source="http://ftp.debian.org/debian/pool/main/libp/libpaper/libpaper_${pkgver}.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build ()
+{
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir="$pkgdir"/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make prefix="$pkgdir"/usr install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="5bc87d494ba470aba54f6d2d51471834 libpaper_1.1.24.tar.gz"
diff --git a/main/libpcap/APKBUILD b/main/libpcap/APKBUILD
new file mode 100644
index 0000000000..f72cf0cef5
--- /dev/null
+++ b/main/libpcap/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libpcap
+pkgver=1.1.1
+_sover=1.0.0
+pkgrel=3
+pkgdesc="A system-independent interface for user-level packet capture"
+url="http://www.tcpdump.org/"
+arch="all"
+license="BSD"
+depends=
+makedepends="bison flex autoconf"
+source="http://www.tcpdump.org/release/$pkgname-$pkgver.tar.gz
+ "
+subpackages="$pkgname-doc $pkgname-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ [ -r "$i" ] || continue
+ msg "Applying $i..."
+ patch -p1 -i $i || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --enable-ipv6 || return 1
+ # seems to be problem with timestamps
+ sleep 1
+ ./config.status
+ make all shared || return 1
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir/usr/bin"
+ make -j1 DESTDIR="$pkgdir" install install-shared
+}
+md5sums="1bca27d206970badae248cfa471bbb47 libpcap-1.1.1.tar.gz"
diff --git a/main/libpciaccess/APKBUILD b/main/libpciaccess/APKBUILD
new file mode 100644
index 0000000000..2ea0be6668
--- /dev/null
+++ b/main/libpciaccess/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libpciaccess
+pkgver=0.12.1
+pkgrel=1
+pkgdesc="X11 PCI access library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig"
+source="http://xorg.freedesktop.org/releases/individual/lib/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="d6363ee9f4df79f6fc47cba7c67b0d35 libpciaccess-0.12.1.tar.bz2"
diff --git a/main/libpng/APKBUILD b/main/libpng/APKBUILD
new file mode 100644
index 0000000000..eff69d4912
--- /dev/null
+++ b/main/libpng/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libpng
+pkgver=1.5.2
+pkgrel=2
+pkgdesc="Portable Network Graphics library"
+url="http://www.libpng.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="zlib-dev gawk"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+depends_dev="zlib-dev"
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ install -Dm644 LICENSE "${pkgdir}"/usr/share/licenses/${pkgname}/LICENSE || return 1
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="31d448eb93a1646359a23f1b23434ab3 libpng-1.5.2.tar.gz"
diff --git a/main/libpri/APKBUILD b/main/libpri/APKBUILD
new file mode 100644
index 0000000000..aec4f46831
--- /dev/null
+++ b/main/libpri/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=libpri
+pkgver=1.4.12_beta3
+_pkgver=1.4.12-beta3
+pkgrel=0
+pkgdesc="Primary Rate ISDN (PRI) library"
+url="http://www.asterisk.orig"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.digium.com/pub/telephony/libpri/releases/$pkgname-$_pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$_pkgver"
+ for i in ../*.patch; do
+ [ -r "$i" ] || continue
+ msg "Applying $i"
+ patch -p1 < $i || return 1;
+ done
+
+ make LDCONFIG="echo" || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$_pkgver"
+ make LDCONFIG="echo" INSTALL_PREFIX="$pkgdir" install
+}
+
+md5sums="9cbbaa009264b76af930529e8aae8cfd libpri-1.4.12-beta3.tar.gz"
diff --git a/main/libpri/libpri-1.4-r1357.patch b/main/libpri/libpri-1.4-r1357.patch
new file mode 100644
index 0000000000..be827eebb7
--- /dev/null
+++ b/main/libpri/libpri-1.4-r1357.patch
@@ -0,0 +1,39961 @@
+===================================================================
+--- a/pri_timers.h (.../tags/1.4.10.2) (revision 1357)
++++ b/pri_timers.h (.../branches/1.4) (revision 1357)
+@@ -1,97 +0,0 @@
+-/*
+- * libpri: An implementation of Primary Rate ISDN
+- *
+- * Written by Mark Spencer <markster@digium.com>
+- *
+- * Copyright (C) 2001, Digium, Inc.
+- * All Rights Reserved.
+- */
+-
+-/*
+- * See http://www.asterisk.org for more information about
+- * the Asterisk project. Please do not directly contact
+- * any of the maintainers of this project for assistance;
+- * the project provides a web site, mailing lists and IRC
+- * channels for your use.
+- *
+- * This program is free software, distributed under the terms of
+- * the GNU General Public License Version 2 as published by the
+- * Free Software Foundation. See the LICENSE file included with
+- * this program for more details.
+- *
+- * In addition, when this program is distributed with Asterisk in
+- * any form that would qualify as a 'combined work' or as a
+- * 'derivative work' (but not mere aggregation), you can redistribute
+- * and/or modify the combination under the terms of the license
+- * provided with that copy of Asterisk, instead of the license
+- * terms granted here.
+- */
+-
+-#ifndef _PRI_TIMERS_H
+-#define _PRI_TIMERS_H
+-
+-/* -1 means we dont currently support the timer/counter */
+-#define PRI_TIMERS_DEFAULT { \
+- 3, /* N200 */ \
+- -1, /* N201 */ \
+- 3, /* N202 */ \
+- 7, /* K */ \
+- 1000, /* T200 */ \
+- -1, /* T201 */ \
+- 10000, /* T202 */ \
+- 10000, /* T203 */ \
+- -1, /* T300 */ \
+- -1, /* T301 */ \
+- -1, /* T302 */ \
+- -1, /* T303 */ \
+- -1, /* T304 */ \
+- 30000, /* T305 */ \
+- -1, /* T306 */ \
+- -1, /* T307 */ \
+- 4000, /* T308 */ \
+- -1, /* T309 */ \
+- -1, /* T310 */ \
+- 4000, /* T313 */ \
+- -1, /* T314 */ \
+- -1, /* T316 */ \
+- -1, /* T317 */ \
+- -1, /* T318 */ \
+- -1, /* T319 */ \
+- -1, /* T320 */ \
+- -1, /* T321 */ \
+- -1, /* T322 */ \
+- 2500, /* TM20 - Q.921 Appendix IV */ \
+- 3, /* NM20 - Q.921 Appendix IV */ \
+- }
+-
+-/* XXX Only our default timers are setup now XXX */
+-#define PRI_TIMERS_UNKNOWN PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_NI2 PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_DMS100 PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_LUCENT5E PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_ATT4ESS PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_EUROISDN_E1 PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_EUROISDN_T1 PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_NI1 PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_GR303_EOC PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_GR303_TMC PRI_TIMERS_DEFAULT
+-#define PRI_TIMERS_QSIG PRI_TIMERS_DEFAULT
+-#define __PRI_TIMERS_GR303_EOC_INT PRI_TIMERS_DEFAULT
+-#define __PRI_TIMERS_GR303_TMC_INT PRI_TIMERS_DEFAULT
+-
+-#define PRI_TIMERS_ALL { PRI_TIMERS_UNKNOWN, \
+- PRI_TIMERS_NI2, \
+- PRI_TIMERS_DMS100, \
+- PRI_TIMERS_LUCENT5E, \
+- PRI_TIMERS_ATT4ESS, \
+- PRI_TIMERS_EUROISDN_E1, \
+- PRI_TIMERS_EUROISDN_T1, \
+- PRI_TIMERS_NI1, \
+- PRI_TIMERS_QSIG, \
+- PRI_TIMERS_GR303_EOC, \
+- PRI_TIMERS_GR303_TMC, \
+- __PRI_TIMERS_GR303_EOC_INT, \
+- __PRI_TIMERS_GR303_TMC_INT, \
+- }
+-
+-#endif
+Index: .version
+===================================================================
+--- a/.version (.../tags/1.4.10.2) (revision 1357)
++++ b/.version (.../branches/1.4) (revision 1357)
+@@ -1 +1 @@
+-1.4.10.2
++1.4.10.2-r1357
+Index: prisched.c
+===================================================================
+--- a/prisched.c (.../tags/1.4.10.2) (revision 1357)
++++ b/prisched.c (.../branches/1.4) (revision 1357)
+@@ -33,25 +33,43 @@
+ #include "pri_internal.h"
+
+
++/*! \brief The maximum number of timers that were active at once. */
+ static int maxsched = 0;
+
+ /* Scheduler routines */
+-int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data)
++
++/*!
++ * \brief Start a timer to schedule an event.
++ *
++ * \param ctrl D channel controller.
++ * \param ms Number of milliseconds to scheduled event.
++ * \param function Callback function to call when timeout.
++ * \param data Value to give callback function when timeout.
++ *
++ * \retval 0 if scheduler table is full and could not schedule the event.
++ * \retval id Scheduled event id.
++ */
++int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data)
+ {
+ int x;
+ struct timeval tv;
++
+ /* Scheduling runs on master channels only */
+- while (pri->master)
+- pri = pri->master;
+- for (x=1;x<MAX_SCHED;x++)
+- if (!pri->pri_sched[x].callback)
++ while (ctrl->master) {
++ ctrl = ctrl->master;
++ }
++ for (x = 0; x < MAX_SCHED; ++x) {
++ if (!ctrl->pri_sched[x].callback) {
+ break;
++ }
++ }
+ if (x == MAX_SCHED) {
+- pri_error(pri, "No more room in scheduler\n");
+- return -1;
++ pri_error(ctrl, "No more room in scheduler\n");
++ return 0;
+ }
+- if (x > maxsched)
+- maxsched = x;
++ if (x >= maxsched) {
++ maxsched = x + 1;
++ }
+ gettimeofday(&tv, NULL);
+ tv.tv_sec += ms / 1000;
+ tv.tv_usec += (ms % 1000) * 1000;
+@@ -59,71 +77,110 @@
+ tv.tv_usec -= 1000000;
+ tv.tv_sec += 1;
+ }
+- pri->pri_sched[x].when = tv;
+- pri->pri_sched[x].callback = function;
+- pri->pri_sched[x].data = data;
+- return x;
++ ctrl->pri_sched[x].when = tv;
++ ctrl->pri_sched[x].callback = function;
++ ctrl->pri_sched[x].data = data;
++ return x + 1;
+ }
+
+-struct timeval *pri_schedule_next(struct pri *pri)
++/*!
++ * \brief Determine the time of the next scheduled event to expire.
++ *
++ * \param ctrl D channel controller.
++ *
++ * \return Time of the next scheduled event to expire or NULL if no timers active.
++ */
++struct timeval *pri_schedule_next(struct pri *ctrl)
+ {
+ struct timeval *closest = NULL;
+ int x;
+- /* Check subchannels */
+- if (pri->subchannel)
+- closest = pri_schedule_next(pri->subchannel);
+- for (x=1;x<MAX_SCHED;x++) {
+- if (pri->pri_sched[x].callback &&
+- (!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
+- ((closest->tv_sec == pri->pri_sched[x].when.tv_sec) &&
+- (closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
+- closest = &pri->pri_sched[x].when;
++
++ /* Scheduling runs on master channels only */
++ while (ctrl->master) {
++ ctrl = ctrl->master;
+ }
++ for (x = 0; x < MAX_SCHED; ++x) {
++ if (ctrl->pri_sched[x].callback && (!closest
++ || (closest->tv_sec > ctrl->pri_sched[x].when.tv_sec)
++ || ((closest->tv_sec == ctrl->pri_sched[x].when.tv_sec)
++ && (closest->tv_usec > ctrl->pri_sched[x].when.tv_usec)))) {
++ closest = &ctrl->pri_sched[x].when;
++ }
++ }
+ return closest;
+ }
+
+-static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
++/*!
++ * \internal
++ * \brief Run all expired timers or return an event generated by an expired timer.
++ *
++ * \param ctrl D channel controller.
++ * \param tv Current time.
++ *
++ * \return Event for upper layer to process or NULL if all expired timers run.
++ */
++static pri_event *__pri_schedule_run(struct pri *ctrl, struct timeval *tv)
+ {
+ int x;
+ void (*callback)(void *);
+ void *data;
+- pri_event *e;
+- if (pri->subchannel) {
+- if ((e = __pri_schedule_run(pri->subchannel, tv))) {
+- return e;
++
++ /* Scheduling runs on master channels only */
++ while (ctrl->master) {
++ ctrl = ctrl->master;
++ }
++ for (x = 0; x < MAX_SCHED; ++x) {
++ if (ctrl->pri_sched[x].callback && ((ctrl->pri_sched[x].when.tv_sec < tv->tv_sec)
++ || ((ctrl->pri_sched[x].when.tv_sec == tv->tv_sec)
++ && (ctrl->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
++ /* This timer has expired. */
++ ctrl->schedev = 0;
++ callback = ctrl->pri_sched[x].callback;
++ data = ctrl->pri_sched[x].data;
++ ctrl->pri_sched[x].callback = NULL;
++ callback(data);
++ if (ctrl->schedev) {
++ return &ctrl->ev;
++ }
+ }
+ }
+- for (x=1;x<MAX_SCHED;x++) {
+- if (pri->pri_sched[x].callback &&
+- ((pri->pri_sched[x].when.tv_sec < tv->tv_sec) ||
+- ((pri->pri_sched[x].when.tv_sec == tv->tv_sec) &&
+- (pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
+- pri->schedev = 0;
+- callback = pri->pri_sched[x].callback;
+- data = pri->pri_sched[x].data;
+- pri->pri_sched[x].callback = NULL;
+- pri->pri_sched[x].data = NULL;
+- callback(data);
+- if (pri->schedev)
+- return &pri->ev;
+- }
+- }
+ return NULL;
+ }
+
+-pri_event *pri_schedule_run(struct pri *pri)
++/*!
++ * \brief Run all expired timers or return an event generated by an expired timer.
++ *
++ * \param ctrl D channel controller.
++ *
++ * \return Event for upper layer to process or NULL if all expired timers run.
++ */
++pri_event *pri_schedule_run(struct pri *ctrl)
+ {
+ struct timeval tv;
++
+ gettimeofday(&tv, NULL);
+- return __pri_schedule_run(pri, &tv);
++ return __pri_schedule_run(ctrl, &tv);
+ }
+
+-
+-void pri_schedule_del(struct pri *pri,int id)
++/*!
++ * \brief Delete a scheduled event.
++ *
++ * \param ctrl D channel controller.
++ * \param id Scheduled event id to delete.
++ * 0 is a disabled/unscheduled event id that is ignored.
++ * 1 - MAX_SCHED is a valid event id.
++ *
++ * \return Nothing
++ */
++void pri_schedule_del(struct pri *ctrl, int id)
+ {
+- while (pri->master)
+- pri = pri->master;
+- if ((id >= MAX_SCHED) || (id < 0))
+- pri_error(pri, "Asked to delete sched id %d???\n", id);
+- pri->pri_sched[id].callback = NULL;
++ /* Scheduling runs on master channels only */
++ while (ctrl->master) {
++ ctrl = ctrl->master;
++ }
++ if (0 < id && id <= MAX_SCHED) {
++ ctrl->pri_sched[id - 1].callback = NULL;
++ } else if (id) {
++ pri_error(ctrl, "Asked to delete sched id %d???\n", id);
++ }
+ }
+Index: rose_qsig_mwi.c
+===================================================================
+--- a/rose_qsig_mwi.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_qsig_mwi.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,790 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief Q.SIG ROSE SS-MWI-Operations
++ *
++ * SS-MWI-Operations ECMA-242 Annex E Table E.1
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Encode the MsgCentreId type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param msg_centre_id
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_MsgCentreId(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct roseQsigMsgCentreId *msg_centre_id)
++{
++ unsigned char *seq_len;
++
++ switch (msg_centre_id->type) {
++ case 0: /* integer */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ msg_centre_id->u.integer));
++ break;
++ case 1: /* partyNumber */
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &msg_centre_id->u.number));
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++ break;
++ case 2: /* numericString */
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ msg_centre_id->u.str, sizeof(msg_centre_id->u.str) - 1));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown MsgCentreId type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the MWIActivate invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigMWIActivateArg *mwi_activate;
++ unsigned char *seq_len;
++ unsigned char *explicit_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ mwi_activate = &args->qsig.MWIActivate;
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &mwi_activate->served_user_number));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ mwi_activate->basic_service));
++ if (mwi_activate->msg_centre_id_present) {
++ ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
++ &mwi_activate->msg_centre_id));
++ }
++ if (mwi_activate->number_of_messages_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ mwi_activate->number_of_messages));
++ }
++ if (mwi_activate->originating_number.length) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &mwi_activate->originating_number));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++ if (mwi_activate->timestamp_present) {
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
++ mwi_activate->timestamp, sizeof(mwi_activate->timestamp) - 1));
++ }
++ if (mwi_activate->priority_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
++ mwi_activate->priority));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the MWIDeactivate invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigMWIDeactivateArg *mwi_deactivate;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ mwi_deactivate = &args->qsig.MWIDeactivate;
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &mwi_deactivate->served_user_number));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ mwi_deactivate->basic_service));
++ if (mwi_deactivate->msg_centre_id_present) {
++ ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
++ &mwi_deactivate->msg_centre_id));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the MWIInterrogate invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigMWIInterrogateArg *mwi_interrogate;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ mwi_interrogate = &args->qsig.MWIInterrogate;
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &mwi_interrogate->served_user_number));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ mwi_interrogate->basic_service));
++ if (mwi_interrogate->msg_centre_id_present) {
++ ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
++ &mwi_interrogate->msg_centre_id));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the MWIInterrogateResElt type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param record
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_MWIInterrogateResElt(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseQsigMWIInterrogateResElt *record)
++{
++ unsigned char *seq_len;
++ unsigned char *explicit_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, record->basic_service));
++ if (record->msg_centre_id_present) {
++ ASN1_CALL(pos, rose_enc_qsig_MsgCentreId(ctrl, pos, end,
++ &record->msg_centre_id));
++ }
++ if (record->number_of_messages_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ record->number_of_messages));
++ }
++ if (record->originating_number.length) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &record->originating_number));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++ if (record->timestamp_present) {
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
++ record->timestamp, sizeof(record->timestamp) - 1));
++ }
++ if (record->priority_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
++ record->priority));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the MWIInterrogate result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args)
++{
++ unsigned index;
++ unsigned char *seq_len;
++ const struct roseQsigMWIInterrogateRes *mwi_interrogate;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ mwi_interrogate = &args->qsig.MWIInterrogate;
++ for (index = 0; index < mwi_interrogate->num_records; ++index) {
++ ASN1_CALL(pos, rose_enc_qsig_MWIInterrogateResElt(ctrl, pos, end,
++ ASN1_TAG_SEQUENCE, &mwi_interrogate->list[index]));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the MsgCentreId argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param msg_centre_id Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_MsgCentreId(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigMsgCentreId *msg_centre_id)
++{
++ int32_t value;
++ size_t str_len;
++ int length;
++ int explicit_offset;
++ const unsigned char *explicit_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s MsgCentreId\n", name);
++ }
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ msg_centre_id->type = 0; /* integer */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "integer", tag, pos, end, &value));
++ msg_centre_id->u.integer = value;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ msg_centre_id->type = 1; /* partyNumber */
++
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, explicit_end,
++ &msg_centre_id->u.number));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ msg_centre_id->type = 2; /* numericString */
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "numericString", tag, pos, end,
++ sizeof(msg_centre_id->u.str), msg_centre_id->u.str, &str_len));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG MWIActivate invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ size_t str_len;
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *explicit_end;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigMWIActivateArg *mwi_activate;
++
++ mwi_activate = &args->qsig.MWIActivate;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " MWIActivateArg %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
++ &mwi_activate->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ mwi_activate->basic_service = value;
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ mwi_activate->msg_centre_id_present = 0;
++ mwi_activate->number_of_messages_present = 0;
++ mwi_activate->originating_number.length = 0;
++ mwi_activate->timestamp_present = 0;
++ mwi_activate->priority_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
++ seq_end, &mwi_activate->msg_centre_id));
++ mwi_activate->msg_centre_id_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ /* Must not be constructed but we will not check for it for simplicity. */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "nbOfMessages", tag, pos, seq_end,
++ &value));
++ mwi_activate->number_of_messages = value;
++ mwi_activate->number_of_messages_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ /* Must be constructed but we will not check for it for simplicity. */
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "originatingNr", tag, pos,
++ explicit_end, &mwi_activate->originating_number));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_TYPE_GENERALIZED_TIME:
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
++ sizeof(mwi_activate->timestamp), mwi_activate->timestamp, &str_len));
++ mwi_activate->timestamp_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
++ /* Must not be constructed but we will not check for it for simplicity. */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "priority", tag, pos, seq_end, &value));
++ mwi_activate->priority = value;
++ mwi_activate->priority_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG MWIDeactivate invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigMWIDeactivateArg *mwi_deactivate;
++
++ mwi_deactivate = &args->qsig.MWIDeactivate;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " MWIDeactivateArg %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
++ &mwi_deactivate->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ mwi_deactivate->basic_service = value;
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ mwi_deactivate->msg_centre_id_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
++ seq_end, &mwi_deactivate->msg_centre_id));
++ mwi_deactivate->msg_centre_id_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG MWIInterrogate invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigMWIInterrogateArg *mwi_interrogate;
++
++ mwi_interrogate = &args->qsig.MWIInterrogate;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " MWIInterrogateArg %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
++ &mwi_interrogate->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ mwi_interrogate->basic_service = value;
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ mwi_interrogate->msg_centre_id_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
++ seq_end, &mwi_interrogate->msg_centre_id));
++ mwi_interrogate->msg_centre_id_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the MWIInterrogateResElt argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param record Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_MWIInterrogateResElt(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigMWIInterrogateResElt *record)
++{
++ int32_t value;
++ size_t str_len;
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *explicit_end;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " MWIInterrogateResElt %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ record->basic_service = value;
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ record->msg_centre_id_present = 0;
++ record->number_of_messages_present = 0;
++ record->originating_number.length = 0;
++ record->timestamp_present = 0;
++ record->priority_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ ASN1_CALL(pos, rose_dec_qsig_MsgCentreId(ctrl, "msgCentreId", tag, pos,
++ seq_end, &record->msg_centre_id));
++ record->msg_centre_id_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ /* Must not be constructed but we will not check for it for simplicity. */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "nbOfMessages", tag, pos, seq_end,
++ &value));
++ record->number_of_messages = value;
++ record->number_of_messages_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ /* Must be constructed but we will not check for it for simplicity. */
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "originatingNr", tag, pos,
++ explicit_end, &record->originating_number));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_TYPE_GENERALIZED_TIME:
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
++ sizeof(record->timestamp), record->timestamp, &str_len));
++ record->timestamp_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
++ /* Must not be constructed but we will not check for it for simplicity. */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "priority", tag, pos, seq_end, &value));
++ record->priority = value;
++ record->priority_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " argumentExt %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG MWIInterrogate result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigMWIInterrogateRes *mwi_interrogate;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " MWIInterrogateRes %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ mwi_interrogate = &args->qsig.MWIInterrogate;
++
++ mwi_interrogate->num_records = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ if (mwi_interrogate->num_records < ARRAY_LEN(mwi_interrogate->list)) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_qsig_MWIInterrogateResElt(ctrl, "listEntry", tag,
++ pos, seq_end, &mwi_interrogate->list[mwi_interrogate->num_records]));
++ ++mwi_interrogate->num_records;
++ } else {
++ /* Too many records */
++ return NULL;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++
++/* ------------------------------------------------------------------- */
++/* end rose_qsig_mwi.c */
+
+Property changes on: rose_qsig_mwi.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rosetest.c
+===================================================================
+--- a/rosetest.c (.../tags/1.4.10.2) (revision 0)
++++ b/rosetest.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,2473 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ROSE encode/decode test program
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++
++#include <stdio.h>
++#include <stdlib.h>
++
++
++/* ------------------------------------------------------------------- */
++
++
++static const struct fac_extension_header fac_headers[] = {
++/* *INDENT-OFF* */
++ {
++ .nfe_present = 0,
++ },
++ {
++ .nfe_present = 1,
++ .nfe.source_entity = 1,
++ .nfe.destination_entity = 1,
++ },
++ {
++ .nfe_present = 1,
++ .nfe.source_entity = 1,
++ .nfe.source_number.plan = 4,
++ .nfe.source_number.length = 4,
++ .nfe.source_number.str = "9834",
++ .nfe.destination_entity = 1,
++ .nfe.destination_number.plan = 4,
++ .nfe.destination_number.length = 4,
++ .nfe.destination_number.str = "9834",
++ },
++ {
++ .nfe_present = 1,
++ .nfe.source_entity = 1,
++ .nfe.destination_entity = 1,
++ .npp_present = 1,
++ .npp = 19,
++ .interpretation_present = 1,
++ .interpretation = 2,
++ },
++/* *INDENT-ON* */
++};
++
++
++static const struct rose_message rose_etsi_msgs[] = {
++/* *INDENT-OFF* */
++ /* Error messages */
++ {
++ .type = ROSE_COMP_TYPE_ERROR,
++ .component.error.invoke_id = 82,
++ .component.error.code = ROSE_ERROR_Div_SpecialServiceNr,
++ },
++ {
++ .type = ROSE_COMP_TYPE_ERROR,
++ .component.error.invoke_id = 8,
++ .component.error.code = ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,
++ },
++
++ /* Reject messages */
++ {
++ .type = ROSE_COMP_TYPE_REJECT,
++ .component.reject.code = ROSE_REJECT_Gen_BadlyStructuredComponent,
++ },
++ {
++ .type = ROSE_COMP_TYPE_REJECT,
++ .component.reject.invoke_id_present = 1,
++ .component.reject.invoke_id = 10,
++ .component.reject.code = ROSE_REJECT_Inv_InitiatorReleasing,
++ },
++ {
++ .type = ROSE_COMP_TYPE_REJECT,
++ .component.reject.invoke_id_present = 1,
++ .component.reject.invoke_id = 11,
++ .component.reject.code = ROSE_REJECT_Res_MistypedResult,
++ },
++ {
++ .type = ROSE_COMP_TYPE_REJECT,
++ .component.reject.invoke_id_present = 1,
++ .component.reject.invoke_id = 12,
++ .component.reject.code = ROSE_REJECT_Err_ErrorResponseUnexpected,
++ },
++
++ /* Anonymous result or result without any arguments. */
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_None,
++ .component.result.invoke_id = 9,
++ },
++
++ /* Advice Of Charge (AOC) */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_ChargingRequest,
++ .component.invoke.invoke_id = 98,
++ .component.invoke.args.etsi.ChargingRequest.charging_case = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ChargingRequest,
++ .component.result.invoke_id = 99,
++ .component.result.args.etsi.ChargingRequest.type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.special_charging_code = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ChargingRequest,
++ .component.result.invoke_id = 100,
++ .component.result.args.etsi.ChargingRequest.type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.currency = "Dollars",
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.currency = 7,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.multiplier = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.charging_type = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.length = 8,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.scale = 4,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ChargingRequest,
++ .component.result.invoke_id = 101,
++ .component.result.args.etsi.ChargingRequest.type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.currency = "Dollars",
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.currency = 7,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.amount.multiplier = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.charging_type = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.length = 8,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.time.scale = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity_present = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity.length = 20,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.duration.granularity.scale = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ChargingRequest,
++ .component.result.invoke_id = 102,
++ .component.result.args.etsi.ChargingRequest.type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 2,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.currency = "Euros",
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.currency = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ChargingRequest,
++ .component.result.invoke_id = 103,
++ .component.result.args.etsi.ChargingRequest.type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 3,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.currency = "Yen",
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.amount.currency = 300,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.amount.multiplier = 5,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.volume_rate.unit = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ChargingRequest,
++ .component.result.invoke_id = 104,
++ .component.result.args.etsi.ChargingRequest.type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 2,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 2,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.currency = "Euros",
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.currency = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].currency_type = 3,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.currency = "Yen",
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.amount.currency = 300,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.amount.multiplier = 5,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[1].u.volume_rate.unit = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ChargingRequest,
++ .component.result.invoke_id = 105,
++ .component.result.args.etsi.ChargingRequest.type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 4,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ChargingRequest,
++ .component.result.invoke_id = 106,
++ .component.result.args.etsi.ChargingRequest.type = 0,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.num_records = 1,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].charged_item = 4,
++ .component.result.args.etsi.ChargingRequest.u.currency_info.list[0].currency_type = 5,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCSCurrency,
++ .component.invoke.invoke_id = 107,
++ .component.invoke.args.etsi.AOCSCurrency.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCSCurrency,
++ .component.invoke.invoke_id = 108,
++ .component.invoke.args.etsi.AOCSCurrency.type = 1,
++ .component.invoke.args.etsi.AOCSCurrency.currency_info.num_records = 1,
++ .component.invoke.args.etsi.AOCSCurrency.currency_info.list[0].charged_item = 3,
++ .component.invoke.args.etsi.AOCSCurrency.currency_info.list[0].currency_type = 4,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCSSpecialArr,
++ .component.invoke.invoke_id = 109,
++ .component.invoke.args.etsi.AOCSSpecialArr.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCSSpecialArr,
++ .component.invoke.invoke_id = 110,
++ .component.invoke.args.etsi.AOCSSpecialArr.type = 1,
++ .component.invoke.args.etsi.AOCSSpecialArr.special_arrangement = 9,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
++ .component.invoke.invoke_id = 111,
++ .component.invoke.args.etsi.AOCDCurrency.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
++ .component.invoke.invoke_id = 112,
++ .component.invoke.args.etsi.AOCDCurrency.type = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
++ .component.invoke.invoke_id = 113,
++ .component.invoke.args.etsi.AOCDCurrency.type = 2,
++ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.currency = "Francs",
++ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.currency = 674,
++ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.multiplier = 3,
++ .component.invoke.args.etsi.AOCDCurrency.specific.type_of_charging_info = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDCurrency,
++ .component.invoke.invoke_id = 114,
++ .component.invoke.args.etsi.AOCDCurrency.type = 2,
++ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.currency = "Francs",
++ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.currency = 674,
++ .component.invoke.args.etsi.AOCDCurrency.specific.recorded.amount.multiplier = 3,
++ .component.invoke.args.etsi.AOCDCurrency.specific.type_of_charging_info = 1,
++ .component.invoke.args.etsi.AOCDCurrency.specific.billing_id_present = 1,
++ .component.invoke.args.etsi.AOCDCurrency.specific.billing_id = 2,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
++ .component.invoke.invoke_id = 115,
++ .component.invoke.args.etsi.AOCDChargingUnit.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
++ .component.invoke.invoke_id = 116,
++ .component.invoke.args.etsi.AOCDChargingUnit.type = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
++ .component.invoke.invoke_id = 117,
++ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
++ .component.invoke.invoke_id = 118,
++ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 0,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].number_of_units = 8523,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.billing_id_present = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.billing_id = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
++ .component.invoke.invoke_id = 119,
++ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit_present = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit = 13,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
++ .component.invoke.invoke_id = 120,
++ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 0,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].number_of_units = 8523,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit_present = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].type_of_unit = 13,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCDChargingUnit,
++ .component.invoke.invoke_id = 121,
++ .component.invoke.args.etsi.AOCDChargingUnit.type = 2,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.num_records = 2,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[0].not_available = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].not_available = 0,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].number_of_units = 8523,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].type_of_unit_present = 1,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.recorded.list[1].type_of_unit = 13,
++ .component.invoke.args.etsi.AOCDChargingUnit.specific.type_of_charging_info = 1,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
++ .component.invoke.invoke_id = 122,
++ .component.invoke.args.etsi.AOCECurrency.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
++ .component.invoke.invoke_id = 123,
++ .component.invoke.args.etsi.AOCECurrency.type = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
++ .component.invoke.invoke_id = 124,
++ .component.invoke.args.etsi.AOCECurrency.type = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
++ .component.invoke.invoke_id = 125,
++ .component.invoke.args.etsi.AOCECurrency.type = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.plan = 0,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.length = 7,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.number.str = "5551212",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
++ .component.invoke.invoke_id = 126,
++ .component.invoke.args.etsi.AOCECurrency.type = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
++ .component.invoke.invoke_id = 127,
++ .component.invoke.args.etsi.AOCECurrency.type = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
++ .component.invoke.invoke_id = 128,
++ .component.invoke.args.etsi.AOCECurrency.type = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id_present = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCECurrency,
++ .component.invoke.invoke_id = 129,
++ .component.invoke.args.etsi.AOCECurrency.type = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.free_of_charge = 0,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.currency = "Francs",
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.currency = 674,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.recorded.amount.multiplier = 3,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id_present = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.specific.billing_id = 2,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association_present = 1,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.type = 0,
++ .component.invoke.args.etsi.AOCECurrency.currency_info.charging_association.id = -37,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
++ .component.invoke.invoke_id = 130,
++ .component.invoke.args.etsi.AOCEChargingUnit.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
++ .component.invoke.invoke_id = 131,
++ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
++ .component.invoke.invoke_id = 132,
++ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
++ .component.invoke.invoke_id = 133,
++ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
++ .component.invoke.invoke_id = 134,
++ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
++ .component.invoke.invoke_id = 135,
++ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id_present = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_AOCEChargingUnit,
++ .component.invoke.invoke_id = 136,
++ .component.invoke.args.etsi.AOCEChargingUnit.type = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 0,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].not_available = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id_present = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.specific.billing_id = 2,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association_present = 1,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.type = 0,
++ .component.invoke.args.etsi.AOCEChargingUnit.charging_unit.charging_association.id = -37,
++ },
++
++ /* Call diversion */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_ActivationDiversion,
++ .component.invoke.invoke_id = 67,
++ .component.invoke.linked_id_present = 1,
++ .component.invoke.linked_id = 27,
++ .component.invoke.args.etsi.ActivationDiversion.procedure = 2,
++ .component.invoke.args.etsi.ActivationDiversion.basic_service = 3,
++ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.plan = 4,
++ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.length = 4,
++ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.str = "1803",
++ .component.invoke.args.etsi.ActivationDiversion.served_user_number.plan = 4,
++ .component.invoke.args.etsi.ActivationDiversion.served_user_number.length = 4,
++ .component.invoke.args.etsi.ActivationDiversion.served_user_number.str = "5398",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_ActivationDiversion,
++ .component.invoke.invoke_id = 68,
++ .component.invoke.args.etsi.ActivationDiversion.procedure = 1,
++ .component.invoke.args.etsi.ActivationDiversion.basic_service = 5,
++ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.plan = 4,
++ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.length = 4,
++ .component.invoke.args.etsi.ActivationDiversion.forwarded_to.number.str = "1803",
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_ActivationDiversion,
++ .component.result.invoke_id = 69,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DeactivationDiversion,
++ .component.invoke.invoke_id = 70,
++ .component.invoke.args.etsi.DeactivationDiversion.procedure = 1,
++ .component.invoke.args.etsi.DeactivationDiversion.basic_service = 5,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_DeactivationDiversion,
++ .component.result.invoke_id = 71,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_ActivationStatusNotificationDiv,
++ .component.invoke.invoke_id = 72,
++ .component.invoke.args.etsi.ActivationStatusNotificationDiv.procedure = 1,
++ .component.invoke.args.etsi.ActivationStatusNotificationDiv.basic_service = 5,
++ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.plan = 4,
++ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.length = 4,
++ .component.invoke.args.etsi.ActivationStatusNotificationDiv.forwarded_to.number.str = "1803",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DeactivationStatusNotificationDiv,
++ .component.invoke.invoke_id = 73,
++ .component.invoke.args.etsi.DeactivationStatusNotificationDiv.procedure = 1,
++ .component.invoke.args.etsi.DeactivationStatusNotificationDiv.basic_service = 5,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_InterrogationDiversion,
++ .component.invoke.invoke_id = 74,
++ .component.invoke.args.etsi.InterrogationDiversion.procedure = 1,
++ .component.invoke.args.etsi.InterrogationDiversion.basic_service = 5,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_InterrogationDiversion,
++ .component.invoke.invoke_id = 75,
++ .component.invoke.args.etsi.InterrogationDiversion.procedure = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_InterrogationDiversion,
++ .component.result.invoke_id = 76,
++ .component.result.args.etsi.InterrogationDiversion.num_records = 2,
++ .component.result.args.etsi.InterrogationDiversion.list[0].procedure = 2,
++ .component.result.args.etsi.InterrogationDiversion.list[0].basic_service = 5,
++ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.plan = 4,
++ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.length = 4,
++ .component.result.args.etsi.InterrogationDiversion.list[0].forwarded_to.number.str = "1803",
++ .component.result.args.etsi.InterrogationDiversion.list[1].procedure = 1,
++ .component.result.args.etsi.InterrogationDiversion.list[1].basic_service = 3,
++ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.plan = 4,
++ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.length = 4,
++ .component.result.args.etsi.InterrogationDiversion.list[1].forwarded_to.number.str = "1903",
++ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.plan = 4,
++ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.length = 4,
++ .component.result.args.etsi.InterrogationDiversion.list[1].served_user_number.str = "5398",
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
++ .component.invoke.invoke_id = 77,
++ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
++ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
++ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.type = 1,
++ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.length = 4,
++ .component.invoke.args.etsi.DiversionInformation.served_user_subaddress.u.nsap = "6492",
++ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 0,
++ .component.invoke.args.etsi.DiversionInformation.calling.screened.screening_indicator = 3,
++ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.plan = 4,
++ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.length = 4,
++ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.str = "1803",
++ .component.invoke.args.etsi.DiversionInformation.original_called_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.original_called.presentation = 1,
++ .component.invoke.args.etsi.DiversionInformation.last_diverting_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.last_diverting.presentation = 2,
++ .component.invoke.args.etsi.DiversionInformation.last_diverting_reason_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.last_diverting_reason = 3,
++ .component.invoke.args.etsi.DiversionInformation.q931ie.length = 5,
++ .component.invoke.args.etsi.DiversionInformation.q931ie_contents = "79828",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
++ .component.invoke.invoke_id = 78,
++ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
++ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
++ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 1,
++ .component.invoke.args.etsi.DiversionInformation.original_called_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.original_called.presentation = 2,
++ .component.invoke.args.etsi.DiversionInformation.last_diverting_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.last_diverting.presentation = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
++ .component.invoke.invoke_id = 79,
++ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
++ .component.invoke.args.etsi.DiversionInformation.basic_service = 3,
++ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
++ .component.invoke.invoke_id = 80,
++ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 3,
++ .component.invoke.args.etsi.DiversionInformation.basic_service = 5,
++ .component.invoke.args.etsi.DiversionInformation.calling_present = 1,
++ .component.invoke.args.etsi.DiversionInformation.calling.presentation = 3,
++ .component.invoke.args.etsi.DiversionInformation.calling.screened.screening_indicator = 2,
++ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.plan = 4,
++ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.length = 4,
++ .component.invoke.args.etsi.DiversionInformation.calling.screened.number.str = "1803",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
++ .component.invoke.invoke_id = 81,
++ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
++ .component.invoke.args.etsi.DiversionInformation.basic_service = 4,
++ .component.invoke.args.etsi.DiversionInformation.q931ie.length = 5,
++ .component.invoke.args.etsi.DiversionInformation.q931ie_contents = "79828",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DiversionInformation,
++ .component.invoke.invoke_id = 82,
++ .component.invoke.args.etsi.DiversionInformation.diversion_reason = 2,
++ .component.invoke.args.etsi.DiversionInformation.basic_service = 4,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_CallDeflection,
++ .component.invoke.invoke_id = 83,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
++ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1,
++ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_CallDeflection,
++ .component.invoke.invoke_id = 84,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
++ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1,
++ .component.invoke.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_CallDeflection,
++ .component.invoke.invoke_id = 85,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.plan = 4,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.length = 4,
++ .component.invoke.args.etsi.CallDeflection.deflection.number.str = "1803",
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_CallDeflection,
++ .component.result.invoke_id = 86,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_CallRerouting,
++ .component.invoke.invoke_id = 87,
++ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
++ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
++ .component.invoke.args.etsi.CallRerouting.q931ie.length = 129,
++ .component.invoke.args.etsi.CallRerouting.q931ie_contents =
++ "YEHAW."
++ " The quick brown fox jumped over the lazy dog test."
++ " Now is the time for all good men to come to the aid of their country.",
++ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 1,
++ .component.invoke.args.etsi.CallRerouting.subscription_option = 2,
++ .component.invoke.args.etsi.CallRerouting.calling_subaddress.type = 1,
++ .component.invoke.args.etsi.CallRerouting.calling_subaddress.length = 4,
++ .component.invoke.args.etsi.CallRerouting.calling_subaddress.u.nsap = "6492",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_CallRerouting,
++ .component.invoke.invoke_id = 88,
++ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
++ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
++ .component.invoke.args.etsi.CallRerouting.q931ie.length = 2,
++ .component.invoke.args.etsi.CallRerouting.q931ie_contents = "RT",
++ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 1,
++ .component.invoke.args.etsi.CallRerouting.subscription_option = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_CallRerouting,
++ .component.invoke.invoke_id = 89,
++ .component.invoke.args.etsi.CallRerouting.rerouting_reason = 3,
++ .component.invoke.args.etsi.CallRerouting.rerouting_counter = 2,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.plan = 4,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.length = 4,
++ .component.invoke.args.etsi.CallRerouting.called_address.number.str = "1803",
++ .component.invoke.args.etsi.CallRerouting.q931ie.length = 2,
++ .component.invoke.args.etsi.CallRerouting.q931ie_contents = "RT",
++ .component.invoke.args.etsi.CallRerouting.last_rerouting.presentation = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_CallRerouting,
++ .component.result.invoke_id = 90,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_InterrogateServedUserNumbers,
++ .component.invoke.invoke_id = 91,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_InterrogateServedUserNumbers,
++ .component.result.invoke_id = 92,
++ .component.result.args.etsi.InterrogateServedUserNumbers.num_records = 2,
++ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].plan = 4,
++ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].length = 4,
++ .component.result.args.etsi.InterrogateServedUserNumbers.number[0].str = "1803",
++ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].plan = 4,
++ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].length = 4,
++ .component.result.args.etsi.InterrogateServedUserNumbers.number[1].str = "5786",
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation1,
++ .component.invoke.invoke_id = 93,
++ .component.invoke.args.etsi.DivertingLegInformation1.diversion_reason = 4,
++ .component.invoke.args.etsi.DivertingLegInformation1.subscription_option = 1,
++ .component.invoke.args.etsi.DivertingLegInformation1.diverted_to_present = 1,
++ .component.invoke.args.etsi.DivertingLegInformation1.diverted_to.presentation = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation1,
++ .component.invoke.invoke_id = 94,
++ .component.invoke.args.etsi.DivertingLegInformation1.diversion_reason = 4,
++ .component.invoke.args.etsi.DivertingLegInformation1.subscription_option = 1,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
++ .component.invoke.invoke_id = 95,
++ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 3,
++ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
++ .component.invoke.args.etsi.DivertingLegInformation2.diverting_present = 1,
++ .component.invoke.args.etsi.DivertingLegInformation2.diverting.presentation = 2,
++ .component.invoke.args.etsi.DivertingLegInformation2.original_called_present = 1,
++ .component.invoke.args.etsi.DivertingLegInformation2.original_called.presentation = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
++ .component.invoke.invoke_id = 96,
++ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 3,
++ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
++ .component.invoke.args.etsi.DivertingLegInformation2.original_called_present = 1,
++ .component.invoke.args.etsi.DivertingLegInformation2.original_called.presentation = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation2,
++ .component.invoke.invoke_id = 97,
++ .component.invoke.args.etsi.DivertingLegInformation2.diversion_counter = 1,
++ .component.invoke.args.etsi.DivertingLegInformation2.diversion_reason = 2,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_DivertingLegInformation3,
++ .component.invoke.invoke_id = 98,
++ .component.invoke.args.etsi.DivertingLegInformation3.presentation_allowed_indicator = 1,
++ },
++
++ /* Explicit Call Transfer (ECT) */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_EctExecute,
++ .component.invoke.invoke_id = 54,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_ExplicitEctExecute,
++ .component.invoke.invoke_id = 55,
++ .component.invoke.args.etsi.ExplicitEctExecute.link_id = 23,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_RequestSubaddress,
++ .component.invoke.invoke_id = 56,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_SubaddressTransfer,
++ .component.invoke.invoke_id = 57,
++ .component.invoke.args.etsi.SubaddressTransfer.subaddress.type = 1,
++ .component.invoke.args.etsi.SubaddressTransfer.subaddress.length = 4,
++ .component.invoke.args.etsi.SubaddressTransfer.subaddress.u.nsap = "6492",
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_EctLinkIdRequest,
++ .component.invoke.invoke_id = 58,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_EctLinkIdRequest,
++ .component.result.invoke_id = 59,
++ .component.result.args.etsi.EctLinkIdRequest.link_id = 76,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_EctInform,
++ .component.invoke.invoke_id = 60,
++ .component.invoke.args.etsi.EctInform.status = 1,
++ .component.invoke.args.etsi.EctInform.redirection_present = 1,
++ .component.invoke.args.etsi.EctInform.redirection.presentation = 0,
++ .component.invoke.args.etsi.EctInform.redirection.number.plan = 8,
++ .component.invoke.args.etsi.EctInform.redirection.number.length = 4,
++ .component.invoke.args.etsi.EctInform.redirection.number.str = "6229",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_EctInform,
++ .component.invoke.invoke_id = 61,
++ .component.invoke.args.etsi.EctInform.status = 1,
++ .component.invoke.args.etsi.EctInform.redirection_present = 1,
++ .component.invoke.args.etsi.EctInform.redirection.presentation = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_EctInform,
++ .component.invoke.invoke_id = 62,
++ .component.invoke.args.etsi.EctInform.status = 1,
++ .component.invoke.args.etsi.EctInform.redirection_present = 1,
++ .component.invoke.args.etsi.EctInform.redirection.presentation = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_EctInform,
++ .component.invoke.invoke_id = 63,
++ .component.invoke.args.etsi.EctInform.status = 1,
++ .component.invoke.args.etsi.EctInform.redirection_present = 1,
++ .component.invoke.args.etsi.EctInform.redirection.presentation = 3,
++ .component.invoke.args.etsi.EctInform.redirection.number.plan = 8,
++ .component.invoke.args.etsi.EctInform.redirection.number.length = 4,
++ .component.invoke.args.etsi.EctInform.redirection.number.str = "3340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_EctInform,
++ .component.invoke.invoke_id = 64,
++ .component.invoke.args.etsi.EctInform.status = 1,
++ .component.invoke.args.etsi.EctInform.redirection_present = 0,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_ETSI_EctLoopTest,
++ .component.invoke.invoke_id = 65,
++ .component.invoke.args.etsi.EctLoopTest.call_transfer_id = 7,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_ETSI_EctLoopTest,
++ .component.result.invoke_id = 66,
++ .component.result.args.etsi.EctLoopTest.loop_result = 2,
++ },
++/* *INDENT-ON* */
++};
++
++static unsigned char rose_etsi_indefinite_len[] = {
++/* *INDENT-OFF* */
++/*
++ * Context Specific/C [1 0x01] <A1> Len:24 <80>
++ * Integer(2 0x02) <02> Len:1 <01>
++ * <44>
++ * Integer(2 0x02) <02> Len:1 <01>
++ * <07>
++ * Sequence/C(48 0x30) <30> Len:16 <80>
++ * Enumerated(10 0x0A) <0A> Len:1 <01>
++ * <01>
++ * Enumerated(10 0x0A) <0A> Len:1 <01>
++ * <05>
++ * Sequence/C(48 0x30) <30> Len:6 <80>
++ * Context Specific [4 0x04] <84> Len:4 <80>
++ * <31 38 30 33>
++ * 0x00, 0x00,
++ * 0x00, 0x00,
++ * NULL(5 0x05) <05> Len:0 <00>
++ * 0x00, 0x00,
++ * 0x00, 0x00
++ */
++ 0x91,
++ 0xA1, 0x80,
++ 0x02, 0x01,
++ 0x44,
++ 0x02, 0x01,
++ 0x07,
++ 0x30, 0x80,
++ 0x0A, 0x01,
++ 0x01,
++ 0x0A, 0x01,
++ 0x05,
++ 0x30, 0x80,
++ 0x84, 0x80,
++ 0x31, 0x38, 0x30, 0x33,
++ 0x00, 0x00,
++ 0x00, 0x00,
++ 0x05, 0x00,
++ 0x00, 0x00,
++ 0x00, 0x00,
++ 0x00, 0x00
++/* *INDENT-ON* */
++};
++
++static unsigned char rose_etsi_unused_indefinite_len[] = {
++/* *INDENT-OFF* */
++/*
++ * Context Specific/C [1 0x01] <A1> Len:24 <80>
++ * Integer(2 0x02) <02> Len:1 <01>
++ * <44>
++ * Integer(2 0x02) <02> Len:1 <01>
++ * <06> -- EctExecute
++ * Sequence/C(48 0x30) <30> Len:16 <80>
++ * Enumerated(10 0x0A) <0A> Len:1 <01>
++ * <01>
++ * Enumerated(10 0x0A) <0A> Len:1 <01>
++ * <05>
++ * Sequence/C(48 0x30) <30> Len:6 <80>
++ * Context Specific [4 0x04] <84> Len:4 <80>
++ * <31 38 30 33>
++ * 0x00, 0x00,
++ * 0x00, 0x00,
++ * NULL(5 0x05) <05> Len:0 <00>
++ * 0x00, 0x00,
++ * 0x00, 0x00
++ */
++ 0x91,
++ 0xA1, 0x80,
++ 0x02, 0x01,
++ 0x44,
++ 0x02, 0x01,
++ 0x06,
++ 0x30, 0x80,
++ 0x0A, 0x01,
++ 0x01,
++ 0x0A, 0x01,
++ 0x05,
++ 0x30, 0x80,
++ 0x84, 0x80,
++ 0x31, 0x38, 0x30, 0x33,
++ 0x00, 0x00,
++ 0x00, 0x00,
++ 0x05, 0x00,
++ 0x00, 0x00,
++ 0x00, 0x00,
++ 0x00, 0x00
++/* *INDENT-ON* */
++};
++
++static unsigned char rose_etsi_unused[] = {
++/* *INDENT-OFF* */
++/*
++ * Context Specific/C [1 0x01] <A1> Len:24 <18>
++ * Integer(2 0x02) <02> Len:1 <01>
++ * <44>
++ * Integer(2 0x02) <02> Len:1 <01>
++ * <06> -- EctExecute
++ * Sequence/C(48 0x30) <30> Len:16 <10>
++ * Enumerated(10 0x0A) <0A> Len:1 <01>
++ * <01>
++ * Enumerated(10 0x0A) <0A> Len:1 <01>
++ * <05>
++ * Sequence/C(48 0x30) <30> Len:6 <06>
++ * Context Specific [4 0x04] <84> Len:4 <04>
++ * <31 38 30 33>
++ * NULL(5 0x05) <05> Len:0 <00>
++ */
++ 0x91,
++ 0xA1, 0x18,
++ 0x02, 0x01,
++ 0x44,
++ 0x02, 0x01,
++ 0x06,
++ 0x30, 0x10,
++ 0x0A, 0x01,
++ 0x01,
++ 0x0A, 0x01,
++ 0x05,
++ 0x30, 0x06,
++ 0x84, 0x04,
++ 0x31, 0x38, 0x30, 0x33,
++ 0x05, 0x00,
++ 0x00, 0x00
++/* *INDENT-ON* */
++};
++
++static unsigned char rose_etsi_extra[] = {
++/* *INDENT-OFF* */
++/*
++ * Context Specific/C [1 0x01] <A1> Len:24 <18>
++ * Integer(2 0x02) <02> Len:1 <01>
++ * <44>
++ * Integer(2 0x02) <02> Len:1 <01>
++ * <07>
++ * Sequence/C(48 0x30) <30> Len:16 <10>
++ * Enumerated(10 0x0A) <0A> Len:1 <01>
++ * <01>
++ * Enumerated(10 0x0A) <0A> Len:1 <01>
++ * <05>
++ * Sequence/C(48 0x30) <30> Len:6 <06>
++ * Context Specific [4 0x04] <84> Len:4 <04>
++ * <31 38 30 33>
++ * NULL(5 0x05) <05> Len:0 <00>
++ */
++ 0x91,
++ 0xA1, 0x18,
++ 0x02, 0x01,
++ 0x44,
++ 0x02, 0x01,
++ 0x07,
++ 0x30, 0x10,
++ 0x0A, 0x01,
++ 0x01,
++ 0x0A, 0x01,
++ 0x05,
++ 0x30, 0x06,
++ 0x84, 0x04,
++ 0x31, 0x38, 0x30, 0x33,
++ 0x05, 0x00,
++ 0x00, 0x00
++/* *INDENT-ON* */
++};
++
++
++static const struct rose_message rose_qsig_msgs[] = {
++/* *INDENT-OFF* */
++ /* Q.SIG Name-Operations */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallingName,
++ .component.invoke.invoke_id = 2,
++ .component.invoke.args.qsig.CallingName.name.presentation = 1,
++ .component.invoke.args.qsig.CallingName.name.char_set = 1,
++ .component.invoke.args.qsig.CallingName.name.length = 7,
++ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallingName,
++ .component.invoke.invoke_id = 3,
++ .component.invoke.args.qsig.CallingName.name.presentation = 1,
++ .component.invoke.args.qsig.CallingName.name.char_set = 3,
++ .component.invoke.args.qsig.CallingName.name.length = 7,
++ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallingName,
++ .component.invoke.invoke_id = 4,
++ .component.invoke.args.qsig.CallingName.name.presentation = 2,
++ .component.invoke.args.qsig.CallingName.name.char_set = 1,
++ .component.invoke.args.qsig.CallingName.name.length = 7,
++ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallingName,
++ .component.invoke.invoke_id = 5,
++ .component.invoke.args.qsig.CallingName.name.presentation = 2,
++ .component.invoke.args.qsig.CallingName.name.char_set = 3,
++ .component.invoke.args.qsig.CallingName.name.length = 7,
++ .component.invoke.args.qsig.CallingName.name.data = "Alphred",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallingName,
++ .component.invoke.invoke_id = 6,
++ .component.invoke.args.qsig.CallingName.name.presentation = 3,
++ .component.invoke.args.qsig.CallingName.name.char_set = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallingName,
++ .component.invoke.invoke_id = 7,
++ .component.invoke.args.qsig.CallingName.name.presentation = 4,
++ .component.invoke.args.qsig.CallingName.name.char_set = 1,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CalledName,
++ .component.invoke.invoke_id = 8,
++ .component.invoke.args.qsig.CallingName.name.presentation = 4,
++ .component.invoke.args.qsig.CallingName.name.char_set = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_ConnectedName,
++ .component.invoke.invoke_id = 9,
++ .component.invoke.args.qsig.CallingName.name.presentation = 4,
++ .component.invoke.args.qsig.CallingName.name.char_set = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_BusyName,
++ .component.invoke.invoke_id = 10,
++ .component.invoke.args.qsig.CallingName.name.presentation = 4,
++ .component.invoke.args.qsig.CallingName.name.char_set = 1,
++ },
++
++ /* Q.SIG SS-AOC-Operations */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
++ .component.invoke.invoke_id = 11,
++ .component.invoke.args.qsig.ChargeRequest.num_records = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
++ .component.invoke.invoke_id = 12,
++ .component.invoke.args.qsig.ChargeRequest.num_records = 1,
++ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[0] = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_ChargeRequest,
++ .component.invoke.invoke_id = 13,
++ .component.invoke.args.qsig.ChargeRequest.num_records = 2,
++ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[0] = 4,
++ .component.invoke.args.qsig.ChargeRequest.advice_mode_combinations[1] = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_ChargeRequest,
++ .component.result.invoke_id = 14,
++ .component.result.args.qsig.ChargeRequest.advice_mode_combination = 3,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_GetFinalCharge,
++ .component.invoke.invoke_id = 15,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocFinal,
++ .component.invoke.invoke_id = 16,
++ .component.invoke.args.qsig.AocFinal.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocFinal,
++ .component.invoke.invoke_id = 17,
++ .component.invoke.args.qsig.AocFinal.type = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocFinal,
++ .component.invoke.invoke_id = 18,
++ .component.invoke.args.qsig.AocFinal.type = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocFinal,
++ .component.invoke.invoke_id = 19,
++ .component.invoke.args.qsig.AocFinal.type = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
++ .component.invoke.args.qsig.AocFinal.specific.billing_id_present = 1,
++ .component.invoke.args.qsig.AocFinal.specific.billing_id = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocFinal,
++ .component.invoke.invoke_id = 20,
++ .component.invoke.args.qsig.AocFinal.type = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
++ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
++ .component.invoke.args.qsig.AocFinal.charging_association.type = 0,
++ .component.invoke.args.qsig.AocFinal.charging_association.id = 200,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocFinal,
++ .component.invoke.invoke_id = 21,
++ .component.invoke.args.qsig.AocFinal.type = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
++ .component.invoke.args.qsig.AocFinal.specific.billing_id_present = 1,
++ .component.invoke.args.qsig.AocFinal.specific.billing_id = 2,
++ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
++ .component.invoke.args.qsig.AocFinal.charging_association.type = 0,
++ .component.invoke.args.qsig.AocFinal.charging_association.id = 200,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocFinal,
++ .component.invoke.invoke_id = 22,
++ .component.invoke.args.qsig.AocFinal.type = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.currency = 800,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.amount.multiplier = 2,
++ .component.invoke.args.qsig.AocFinal.specific.recorded.currency = "Rupies",
++ .component.invoke.args.qsig.AocFinal.charging_association_present = 1,
++ .component.invoke.args.qsig.AocFinal.charging_association.type = 1,
++ .component.invoke.args.qsig.AocFinal.charging_association.number.plan = 4,
++ .component.invoke.args.qsig.AocFinal.charging_association.number.length = 4,
++ .component.invoke.args.qsig.AocFinal.charging_association.number.str = "1802",
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocInterim,
++ .component.invoke.invoke_id = 23,
++ .component.invoke.args.qsig.AocInterim.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocInterim,
++ .component.invoke.invoke_id = 24,
++ .component.invoke.args.qsig.AocInterim.type = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocInterim,
++ .component.invoke.invoke_id = 25,
++ .component.invoke.args.qsig.AocInterim.type = 2,
++ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.currency = 800,
++ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.multiplier = 2,
++ .component.invoke.args.qsig.AocInterim.specific.recorded.currency = "Rupies",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocInterim,
++ .component.invoke.invoke_id = 26,
++ .component.invoke.args.qsig.AocInterim.type = 2,
++ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.currency = 800,
++ .component.invoke.args.qsig.AocInterim.specific.recorded.amount.multiplier = 2,
++ .component.invoke.args.qsig.AocInterim.specific.recorded.currency = "Rupies",
++ .component.invoke.args.qsig.AocInterim.specific.billing_id_present = 1,
++ .component.invoke.args.qsig.AocInterim.specific.billing_id = 2,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 27,
++ .component.invoke.args.qsig.AocRate.type = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 28,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 0,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.special_charging_code = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 29,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.currency = "Dollars",
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.currency = 7,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.multiplier = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.charging_type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.length = 8,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.scale = 4,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 30,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.currency = "Dollars",
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.currency = 7,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.amount.multiplier = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.charging_type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.length = 8,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.time.scale = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity_present = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity.length = 20,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.duration.granularity.scale = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 31,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 2,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.currency = "Euros",
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.currency = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 32,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 3,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.currency = "Yen",
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.amount.currency = 300,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.amount.multiplier = 5,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.volume_rate.unit = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 33,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 2,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 2,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.currency = "Euros",
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.currency = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].u.flat_rate.amount.multiplier = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[1].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[1].currency_type = 3,
++ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.currency = "Yen",
++ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.amount.currency = 300,
++ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.amount.multiplier = 5,
++ .component.invoke.args.qsig.AocRate.currency_info.list[1].u.volume_rate.unit = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 34,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 4,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 35,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 5,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocRate,
++ .component.invoke.invoke_id = 36,
++ .component.invoke.args.qsig.AocRate.type = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.num_records = 1,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].charged_item = 4,
++ .component.invoke.args.qsig.AocRate.currency_info.list[0].currency_type = 6,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocComplete,
++ .component.invoke.invoke_id = 37,
++ .component.invoke.args.qsig.AocComplete.charged_user_number.plan = 4,
++ .component.invoke.args.qsig.AocComplete.charged_user_number.length = 4,
++ .component.invoke.args.qsig.AocComplete.charged_user_number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocComplete,
++ .component.invoke.invoke_id = 38,
++ .component.invoke.args.qsig.AocComplete.charged_user_number.plan = 4,
++ .component.invoke.args.qsig.AocComplete.charged_user_number.length = 4,
++ .component.invoke.args.qsig.AocComplete.charged_user_number.str = "8340",
++ .component.invoke.args.qsig.AocComplete.charging_association_present = 1,
++ .component.invoke.args.qsig.AocComplete.charging_association.type = 0,
++ .component.invoke.args.qsig.AocComplete.charging_association.id = 8298,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_AocComplete,
++ .component.result.invoke_id = 39,
++ .component.result.args.qsig.AocComplete.charging_option = 2,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocDivChargeReq,
++ .component.invoke.invoke_id = 40,
++ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.plan = 4,
++ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.length = 4,
++ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.str = "8340",
++ .component.invoke.args.qsig.AocDivChargeReq.diversion_type = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_AocDivChargeReq,
++ .component.invoke.invoke_id = 41,
++ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.plan = 4,
++ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.length = 4,
++ .component.invoke.args.qsig.AocDivChargeReq.diverting_user_number.str = "8340",
++ .component.invoke.args.qsig.AocDivChargeReq.charging_association_present = 1,
++ .component.invoke.args.qsig.AocDivChargeReq.charging_association.type = 0,
++ .component.invoke.args.qsig.AocDivChargeReq.charging_association.id = 8298,
++ .component.invoke.args.qsig.AocDivChargeReq.diversion_type = 3,
++ },
++
++ /* Q.SIG Call-Transfer-Operations (CT) */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferIdentify,
++ .component.invoke.invoke_id = 42,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_CallTransferIdentify,
++ .component.result.invoke_id = 43,
++ .component.result.args.qsig.CallTransferIdentify.call_id = "2345",
++ .component.result.args.qsig.CallTransferIdentify.rerouting_number.plan = 4,
++ .component.result.args.qsig.CallTransferIdentify.rerouting_number.length = 4,
++ .component.result.args.qsig.CallTransferIdentify.rerouting_number.str = "8340",
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferAbandon,
++ .component.invoke.invoke_id = 44,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferInitiate,
++ .component.invoke.invoke_id = 45,
++ .component.invoke.args.qsig.CallTransferInitiate.call_id = "2345",
++ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.plan = 4,
++ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.length = 4,
++ .component.invoke.args.qsig.CallTransferInitiate.rerouting_number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_CallTransferInitiate,
++ .component.result.invoke_id = 46,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferSetup,
++ .component.invoke.invoke_id = 47,
++ .component.invoke.args.qsig.CallTransferSetup.call_id = "23",
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_CallTransferSetup,
++ .component.result.invoke_id = 48,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
++ .component.invoke.invoke_id = 49,
++ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
++ .component.invoke.invoke_id = 50,
++ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
++ .component.invoke.args.qsig.CallTransferActive.q931ie.length = 2,
++ .component.invoke.args.qsig.CallTransferActive.q931ie_contents = "RT",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
++ .component.invoke.invoke_id = 51,
++ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
++ .component.invoke.args.qsig.CallTransferActive.connected_name_present = 1,
++ .component.invoke.args.qsig.CallTransferActive.connected_name.presentation = 1,
++ .component.invoke.args.qsig.CallTransferActive.connected_name.char_set = 1,
++ .component.invoke.args.qsig.CallTransferActive.connected_name.length = 7,
++ .component.invoke.args.qsig.CallTransferActive.connected_name.data = "Alphred",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferActive,
++ .component.invoke.invoke_id = 52,
++ .component.invoke.args.qsig.CallTransferActive.connected.presentation = 1,
++ .component.invoke.args.qsig.CallTransferActive.q931ie.length = 2,
++ .component.invoke.args.qsig.CallTransferActive.q931ie_contents = "RT",
++ .component.invoke.args.qsig.CallTransferActive.connected_name_present = 1,
++ .component.invoke.args.qsig.CallTransferActive.connected_name.presentation = 1,
++ .component.invoke.args.qsig.CallTransferActive.connected_name.char_set = 1,
++ .component.invoke.args.qsig.CallTransferActive.connected_name.length = 7,
++ .component.invoke.args.qsig.CallTransferActive.connected_name.data = "Alphred",
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
++ .component.invoke.invoke_id = 53,
++ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 0,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.screening_indicator = 3,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.plan = 4,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.length = 4,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
++ .component.invoke.invoke_id = 54,
++ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
++ .component.invoke.invoke_id = 55,
++ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
++ .component.invoke.invoke_id = 56,
++ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 3,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.screening_indicator = 3,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.plan = 4,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.length = 4,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.screened.number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
++ .component.invoke.invoke_id = 57,
++ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
++ .component.invoke.args.qsig.CallTransferComplete.q931ie.length = 2,
++ .component.invoke.args.qsig.CallTransferComplete.q931ie_contents = "RT",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
++ .component.invoke.invoke_id = 58,
++ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
++ .component.invoke.args.qsig.CallTransferComplete.redirection_name_present = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection_name.presentation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection_name.char_set = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection_name.length = 7,
++ .component.invoke.args.qsig.CallTransferComplete.redirection_name.data = "Alphred",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
++ .component.invoke.invoke_id = 59,
++ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
++ .component.invoke.args.qsig.CallTransferComplete.call_status = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferComplete,
++ .component.invoke.invoke_id = 60,
++ .component.invoke.args.qsig.CallTransferComplete.end_designation = 1,
++ .component.invoke.args.qsig.CallTransferComplete.redirection.presentation = 2,
++ .component.invoke.args.qsig.CallTransferComplete.q931ie.length = 2,
++ .component.invoke.args.qsig.CallTransferComplete.q931ie_contents = "RT",
++ .component.invoke.args.qsig.CallTransferComplete.call_status = 1,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
++ .component.invoke.invoke_id = 61,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
++ .component.invoke.invoke_id = 62,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name_present = 1,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.presentation = 1,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.char_set = 1,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.length = 7,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.data = "Alphred",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
++ .component.invoke.invoke_id = 63,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
++ .component.invoke.args.qsig.CallTransferUpdate.q931ie.length = 2,
++ .component.invoke.args.qsig.CallTransferUpdate.q931ie_contents = "RT",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallTransferUpdate,
++ .component.invoke.invoke_id = 64,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection.presentation = 2,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name_present = 1,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.presentation = 1,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.char_set = 1,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.length = 7,
++ .component.invoke.args.qsig.CallTransferUpdate.redirection_name.data = "Alphred",
++ .component.invoke.args.qsig.CallTransferUpdate.q931ie.length = 2,
++ .component.invoke.args.qsig.CallTransferUpdate.q931ie_contents = "RT",
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_SubaddressTransfer,
++ .component.invoke.invoke_id = 65,
++ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.type = 1,
++ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.length = 4,
++ .component.invoke.args.qsig.SubaddressTransfer.redirection_subaddress.u.nsap = "4356",
++ },
++
++ /* Q.SIG Call-Diversion-Operations */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_ActivateDiversionQ,
++ .component.invoke.invoke_id = 66,
++ .component.invoke.args.qsig.ActivateDiversionQ.procedure = 1,
++ .component.invoke.args.qsig.ActivateDiversionQ.basic_service = 3,
++ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.plan = 4,
++ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.length = 4,
++ .component.invoke.args.qsig.ActivateDiversionQ.diverted_to.number.str = "8340",
++ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.plan = 4,
++ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.length = 4,
++ .component.invoke.args.qsig.ActivateDiversionQ.served_user_number.str = "8340",
++ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.plan = 4,
++ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.length = 4,
++ .component.invoke.args.qsig.ActivateDiversionQ.activating_user_number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_ActivateDiversionQ,
++ .component.result.invoke_id = 67,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_DeactivateDiversionQ,
++ .component.invoke.invoke_id = 68,
++ .component.invoke.args.qsig.DeactivateDiversionQ.procedure = 1,
++ .component.invoke.args.qsig.DeactivateDiversionQ.basic_service = 3,
++ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.plan = 4,
++ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.length = 4,
++ .component.invoke.args.qsig.DeactivateDiversionQ.served_user_number.str = "8340",
++ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.plan = 4,
++ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.length = 4,
++ .component.invoke.args.qsig.DeactivateDiversionQ.deactivating_user_number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_DeactivateDiversionQ,
++ .component.result.invoke_id = 69,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_InterrogateDiversionQ,
++ .component.invoke.invoke_id = 70,
++ .component.invoke.args.qsig.InterrogateDiversionQ.procedure = 1,
++ .component.invoke.args.qsig.InterrogateDiversionQ.basic_service = 3,
++ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.plan = 4,
++ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.length = 4,
++ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.str = "8340",
++ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.plan = 4,
++ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.length = 4,
++ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_InterrogateDiversionQ,
++ .component.invoke.invoke_id = 71,
++ .component.invoke.args.qsig.InterrogateDiversionQ.procedure = 1,
++ .component.invoke.args.qsig.InterrogateDiversionQ.basic_service = 0,/* default */
++ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.plan = 4,
++ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.length = 4,
++ .component.invoke.args.qsig.InterrogateDiversionQ.served_user_number.str = "8340",
++ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.plan = 4,
++ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.length = 4,
++ .component.invoke.args.qsig.InterrogateDiversionQ.interrogating_user_number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
++ .component.result.invoke_id = 72,
++ .component.result.args.qsig.InterrogateDiversionQ.num_records = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
++ .component.result.invoke_id = 73,
++ .component.result.args.qsig.InterrogateDiversionQ.num_records = 1,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].remote_enabled = 0,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
++ .component.result.invoke_id = 74,
++ .component.result.args.qsig.InterrogateDiversionQ.num_records = 1,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].remote_enabled = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_InterrogateDiversionQ,
++ .component.result.invoke_id = 75,
++ .component.result.args.qsig.InterrogateDiversionQ.num_records = 2,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.plan = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.length = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].served_user_number.str = "8340",
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].basic_service = 3,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].procedure = 2,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.plan = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.length = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[0].diverted_to.number.str = "8340",
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.plan = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.length = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].served_user_number.str = "8340",
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].basic_service = 3,
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].procedure = 2,
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.plan = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.length = 4,
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].diverted_to.number.str = "8340",
++ .component.result.args.qsig.InterrogateDiversionQ.list[1].remote_enabled = 1,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CheckRestriction,
++ .component.invoke.invoke_id = 76,
++ .component.invoke.args.qsig.CheckRestriction.served_user_number.plan = 4,
++ .component.invoke.args.qsig.CheckRestriction.served_user_number.length = 4,
++ .component.invoke.args.qsig.CheckRestriction.served_user_number.str = "8340",
++ .component.invoke.args.qsig.CheckRestriction.basic_service = 3,
++ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.plan = 4,
++ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.length = 4,
++ .component.invoke.args.qsig.CheckRestriction.diverted_to_number.str = "8340",
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_CheckRestriction,
++ .component.result.invoke_id = 77,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallRerouting,
++ .component.invoke.invoke_id = 78,
++ .component.invoke.args.qsig.CallRerouting.rerouting_reason = 3,
++ .component.invoke.args.qsig.CallRerouting.called.number.plan = 4,
++ .component.invoke.args.qsig.CallRerouting.called.number.length = 4,
++ .component.invoke.args.qsig.CallRerouting.called.number.str = "8340",
++ .component.invoke.args.qsig.CallRerouting.diversion_counter = 5,
++ .component.invoke.args.qsig.CallRerouting.q931ie.length = 2,
++ .component.invoke.args.qsig.CallRerouting.q931ie_contents = "RT",
++ .component.invoke.args.qsig.CallRerouting.last_rerouting.presentation = 1,
++ .component.invoke.args.qsig.CallRerouting.subscription_option = 2,
++ .component.invoke.args.qsig.CallRerouting.calling.presentation = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CallRerouting,
++ .component.invoke.invoke_id = 79,
++ .component.invoke.args.qsig.CallRerouting.rerouting_reason = 3,
++ .component.invoke.args.qsig.CallRerouting.original_rerouting_reason_present = 1,
++ .component.invoke.args.qsig.CallRerouting.original_rerouting_reason = 2,
++ .component.invoke.args.qsig.CallRerouting.called.number.plan = 4,
++ .component.invoke.args.qsig.CallRerouting.called.number.length = 4,
++ .component.invoke.args.qsig.CallRerouting.called.number.str = "8340",
++ .component.invoke.args.qsig.CallRerouting.diversion_counter = 5,
++ .component.invoke.args.qsig.CallRerouting.q931ie.length = 2,
++ .component.invoke.args.qsig.CallRerouting.q931ie_contents = "RT",
++ .component.invoke.args.qsig.CallRerouting.last_rerouting.presentation = 1,
++ .component.invoke.args.qsig.CallRerouting.subscription_option = 2,
++ .component.invoke.args.qsig.CallRerouting.calling_subaddress.type = 1,
++ .component.invoke.args.qsig.CallRerouting.calling_subaddress.length = 4,
++ .component.invoke.args.qsig.CallRerouting.calling_subaddress.u.nsap = "3253",
++ .component.invoke.args.qsig.CallRerouting.calling.presentation = 1,
++ .component.invoke.args.qsig.CallRerouting.calling_name_present = 1,
++ .component.invoke.args.qsig.CallRerouting.calling_name.presentation = 4,
++ .component.invoke.args.qsig.CallRerouting.calling_name.char_set = 1,
++ .component.invoke.args.qsig.CallRerouting.original_called_present = 1,
++ .component.invoke.args.qsig.CallRerouting.original_called.presentation = 2,
++ .component.invoke.args.qsig.CallRerouting.redirecting_name_present = 1,
++ .component.invoke.args.qsig.CallRerouting.redirecting_name.presentation = 4,
++ .component.invoke.args.qsig.CallRerouting.redirecting_name.char_set = 1,
++ .component.invoke.args.qsig.CallRerouting.original_called_name_present = 1,
++ .component.invoke.args.qsig.CallRerouting.original_called_name.presentation = 4,
++ .component.invoke.args.qsig.CallRerouting.original_called_name.char_set = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_CallRerouting,
++ .component.result.invoke_id = 80,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation1,
++ .component.invoke.invoke_id = 81,
++ .component.invoke.args.qsig.DivertingLegInformation1.diversion_reason = 3,
++ .component.invoke.args.qsig.DivertingLegInformation1.subscription_option = 1,
++ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.plan = 4,
++ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.length = 4,
++ .component.invoke.args.qsig.DivertingLegInformation1.nominated_number.str = "8340",
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation2,
++ .component.invoke.invoke_id = 82,
++ .component.invoke.args.qsig.DivertingLegInformation2.diversion_counter = 6,
++ .component.invoke.args.qsig.DivertingLegInformation2.diversion_reason = 3,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation2,
++ .component.invoke.invoke_id = 83,
++ .component.invoke.args.qsig.DivertingLegInformation2.diversion_counter = 6,
++ .component.invoke.args.qsig.DivertingLegInformation2.diversion_reason = 3,
++ .component.invoke.args.qsig.DivertingLegInformation2.original_diversion_reason_present = 1,
++ .component.invoke.args.qsig.DivertingLegInformation2.original_diversion_reason = 2,
++ .component.invoke.args.qsig.DivertingLegInformation2.diverting_present = 1,
++ .component.invoke.args.qsig.DivertingLegInformation2.diverting.presentation = 2,
++ .component.invoke.args.qsig.DivertingLegInformation2.original_called_present = 1,
++ .component.invoke.args.qsig.DivertingLegInformation2.original_called.presentation = 2,
++ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name_present = 1,
++ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name.presentation = 4,
++ .component.invoke.args.qsig.DivertingLegInformation2.redirecting_name.char_set = 1,
++ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name_present = 1,
++ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name.presentation = 4,
++ .component.invoke.args.qsig.DivertingLegInformation2.original_called_name.char_set = 1,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation3,
++ .component.invoke.invoke_id = 84,
++ .component.invoke.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_DivertingLegInformation3,
++ .component.invoke.invoke_id = 85,
++ .component.invoke.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1,
++ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name_present = 1,
++ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name.presentation = 4,
++ .component.invoke.args.qsig.DivertingLegInformation3.redirection_name.char_set = 1,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_CfnrDivertedLegFailed,
++ .component.invoke.invoke_id = 86,
++ },
++
++ /* Q.SIG SS-MWI-Operations */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_MWIActivate,
++ .component.invoke.invoke_id = 102,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
++ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_MWIActivate,
++ .component.invoke.invoke_id = 103,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
++ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 0,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.integer = 532,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_MWIActivate,
++ .component.invoke.invoke_id = 104,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
++ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 1,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.plan = 4,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.length = 4,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.number.str = "9838",
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_MWIActivate,
++ .component.invoke.invoke_id = 105,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.plan = 4,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.length = 4,
++ .component.invoke.args.qsig.MWIActivate.served_user_number.str = "9838",
++ .component.invoke.args.qsig.MWIActivate.basic_service = 1,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id_present = 1,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id.type = 2,
++ .component.invoke.args.qsig.MWIActivate.msg_centre_id.u.str = "123456",
++ .component.invoke.args.qsig.MWIActivate.number_of_messages_present = 1,
++ .component.invoke.args.qsig.MWIActivate.number_of_messages = 6548,
++ .component.invoke.args.qsig.MWIActivate.originating_number.plan = 4,
++ .component.invoke.args.qsig.MWIActivate.originating_number.length = 4,
++ .component.invoke.args.qsig.MWIActivate.originating_number.str = "9838",
++ .component.invoke.args.qsig.MWIActivate.timestamp_present = 1,
++ .component.invoke.args.qsig.MWIActivate.timestamp = "19970621194530",
++ .component.invoke.args.qsig.MWIActivate.priority_present = 1,
++ .component.invoke.args.qsig.MWIActivate.priority = 7,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_MWIActivate,
++ .component.result.invoke_id = 106,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_MWIDeactivate,
++ .component.invoke.invoke_id = 107,
++ .component.invoke.args.qsig.MWIDeactivate.served_user_number.plan = 4,
++ .component.invoke.args.qsig.MWIDeactivate.served_user_number.length = 4,
++ .component.invoke.args.qsig.MWIDeactivate.served_user_number.str = "9838",
++ .component.invoke.args.qsig.MWIDeactivate.basic_service = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_MWIDeactivate,
++ .component.invoke.invoke_id = 108,
++ .component.invoke.args.qsig.MWIDeactivate.served_user_number.plan = 4,
++ .component.invoke.args.qsig.MWIDeactivate.served_user_number.length = 4,
++ .component.invoke.args.qsig.MWIDeactivate.served_user_number.str = "9838",
++ .component.invoke.args.qsig.MWIDeactivate.basic_service = 1,
++ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id_present = 1,
++ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id.type = 0,
++ .component.invoke.args.qsig.MWIDeactivate.msg_centre_id.u.integer = 532,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_MWIDeactivate,
++ .component.result.invoke_id = 109,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_MWIInterrogate,
++ .component.invoke.invoke_id = 110,
++ .component.invoke.args.qsig.MWIInterrogate.served_user_number.plan = 4,
++ .component.invoke.args.qsig.MWIInterrogate.served_user_number.length = 4,
++ .component.invoke.args.qsig.MWIInterrogate.served_user_number.str = "9838",
++ .component.invoke.args.qsig.MWIInterrogate.basic_service = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_QSIG_MWIInterrogate,
++ .component.invoke.invoke_id = 111,
++ .component.invoke.args.qsig.MWIInterrogate.served_user_number.plan = 4,
++ .component.invoke.args.qsig.MWIInterrogate.served_user_number.length = 4,
++ .component.invoke.args.qsig.MWIInterrogate.served_user_number.str = "9838",
++ .component.invoke.args.qsig.MWIInterrogate.basic_service = 1,
++ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id_present = 1,
++ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id.type = 0,
++ .component.invoke.args.qsig.MWIInterrogate.msg_centre_id.u.integer = 532,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_MWIInterrogate,
++ .component.result.invoke_id = 112,
++ .component.result.args.qsig.MWIInterrogate.num_records = 1,
++ .component.result.args.qsig.MWIInterrogate.list[0].basic_service = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_QSIG_MWIInterrogate,
++ .component.result.invoke_id = 113,
++ .component.result.args.qsig.MWIInterrogate.num_records = 2,
++ .component.result.args.qsig.MWIInterrogate.list[0].basic_service = 1,
++ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id_present = 1,
++ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id.type = 0,
++ .component.result.args.qsig.MWIInterrogate.list[0].msg_centre_id.u.integer = 987,
++ .component.result.args.qsig.MWIInterrogate.list[0].number_of_messages_present = 1,
++ .component.result.args.qsig.MWIInterrogate.list[0].number_of_messages = 6548,
++ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.plan = 4,
++ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.length = 4,
++ .component.result.args.qsig.MWIInterrogate.list[0].originating_number.str = "9838",
++ .component.result.args.qsig.MWIInterrogate.list[0].timestamp_present = 1,
++ .component.result.args.qsig.MWIInterrogate.list[0].timestamp = "19970621194530",
++ .component.result.args.qsig.MWIInterrogate.list[0].priority_present = 1,
++ .component.result.args.qsig.MWIInterrogate.list[0].priority = 7,
++ .component.result.args.qsig.MWIInterrogate.list[1].basic_service = 1,
++ },
++/* *INDENT-ON* */
++};
++
++
++static const struct rose_message rose_dms100_msgs[] = {
++/* *INDENT-OFF* */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_DMS100_RLT_OperationInd,
++ .component.invoke.invoke_id = ROSE_DMS100_RLT_OPERATION_IND,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_DMS100_RLT_OperationInd,
++ .component.result.invoke_id = ROSE_DMS100_RLT_OPERATION_IND,
++ .component.result.args.dms100.RLT_OperationInd.call_id = 130363,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_DMS100_RLT_ThirdParty,
++ .component.invoke.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY,
++ .component.invoke.args.dms100.RLT_ThirdParty.call_id = 120047,
++ .component.invoke.args.dms100.RLT_ThirdParty.reason = 1,
++ },
++ {
++ .type = ROSE_COMP_TYPE_RESULT,
++ .component.result.operation = ROSE_DMS100_RLT_ThirdParty,
++ .component.result.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY,
++ },
++/* *INDENT-ON* */
++};
++
++
++static const struct rose_message rose_ni2_msgs[] = {
++/* *INDENT-OFF* */
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_NI2_InformationFollowing,
++ .component.invoke.invoke_id = 1,
++ .component.invoke.args.ni2.InformationFollowing.value = 7,
++ },
++
++ {
++ .type = ROSE_COMP_TYPE_INVOKE,
++ .component.invoke.operation = ROSE_NI2_InitiateTransfer,
++ .component.invoke.invoke_id = 2,
++ .component.invoke.args.ni2.InitiateTransfer.call_reference = 5,
++ },
++/* *INDENT-ON* */
++};
++
++/* ------------------------------------------------------------------- */
++
++static void rose_pri_message(struct pri *ctrl, char *stuff)
++{
++ fprintf(stdout, "%s", stuff);
++}
++
++static void rose_pri_error(struct pri *ctrl, char *stuff)
++{
++ fprintf(stdout, "%s", stuff);
++ fprintf(stderr, "%s", stuff);
++}
++
++/*!
++ * \internal
++ * \brief Test ROSE encoding and decoding the given message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param index Message number to report.
++ * \param header Facility message header data to encode.
++ * \param encode_msg Message data to encode.
++ *
++ * \return Nothing
++ */
++static void rose_test_msg(struct pri *ctrl, unsigned index,
++ const struct fac_extension_header *header, const struct rose_message *encode_msg)
++{
++ struct fac_extension_header decoded_header;
++ struct rose_message decoded_msg;
++ unsigned char *enc_pos;
++ unsigned char *enc_end;
++ const unsigned char *dec_pos;
++ const unsigned char *dec_end;
++
++ static unsigned char buf[1024];
++
++ pri_message(ctrl, "\n\n");
++ enc_end = buf + sizeof(buf);
++ enc_pos = facility_encode_header(ctrl, buf, enc_end, header);
++ if (!enc_pos) {
++ pri_error(ctrl, "Error: Message:%u failed to encode header\n", index);
++ } else {
++ enc_pos = rose_encode(ctrl, enc_pos, enc_end, encode_msg);
++ if (!enc_pos) {
++ pri_error(ctrl, "Error: Message:%u failed to encode ROSE\n", index);
++ } else {
++ pri_message(ctrl, "Message %u encoded length is %u\n", index,
++ (unsigned) (enc_pos - buf));
++
++ /* Clear the decoded message contents for comparison. */
++ memset(&decoded_header, 0, sizeof(decoded_header));
++ memset(&decoded_msg, 0, sizeof(decoded_msg));
++
++ dec_end = enc_pos;
++ dec_pos = facility_decode_header(ctrl, buf, dec_end, &decoded_header);
++ if (!dec_pos) {
++ pri_error(ctrl, "Error: Message:%u failed to decode header\n", index);
++ } else {
++ dec_pos = rose_decode(ctrl, dec_pos, dec_end, &decoded_msg);
++ if (!dec_pos) {
++ pri_error(ctrl, "Error: Message:%u failed to decode ROSE\n", index);
++ } else {
++ if (header
++ && memcmp(header, &decoded_header, sizeof(decoded_header))) {
++ pri_error(ctrl, "Error: Message:%u Header did not match\n",
++ index);
++ }
++ if (memcmp(encode_msg, &decoded_msg, sizeof(decoded_msg))) {
++ pri_error(ctrl, "Error: Message:%u ROSE did not match\n", index);
++ }
++ }
++ }
++ }
++ }
++ pri_message(ctrl, "\n\n"
++ "************************************************************\n");
++}
++
++/*!
++ * \internal
++ * \brief Test ROSE decoding messages of unusual encodings.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Test name for the encoded message.
++ * \param msg_buf Encoded message to decode.
++ * \param msg_len Length of encoded message buffer.
++ *
++ * \return Nothing
++ */
++static void rose_test_exception(struct pri *ctrl, const char *name,
++ const unsigned char *msg, size_t msg_len)
++{
++ const unsigned char *pos;
++ const unsigned char *end;
++ struct fac_extension_header header;
++ struct rose_message decoded_msg;
++
++ pri_message(ctrl, "\n\n"
++ "%s test: Message encoded length is %u\n", name, (unsigned) msg_len);
++
++ pos = msg;
++ end = msg + msg_len;
++ pos = facility_decode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ pri_error(ctrl, "Error: %s test: Message failed to decode header\n", name);
++ } else {
++ pos = rose_decode(ctrl, pos, end, &decoded_msg);
++ if (!pos) {
++ pri_error(ctrl, "Error: %s test: Message failed to decode ROSE\n", name);
++ }
++ }
++
++ pri_message(ctrl, "\n\n"
++ "************************************************************\n");
++}
++
++/*!
++ * \brief ROSE encode/decode test program.
++ *
++ * \param argc Program argument count.
++ * \param argv Program argument string array.
++ *
++ * \retval 0 on success.
++ * \retval Nonzero on error.
++ */
++int main(int argc, char *argv[])
++{
++ unsigned index;
++ unsigned offset;
++ static struct pri dummy_ctrl;
++
++ pri_set_message(rose_pri_message);
++ pri_set_error(rose_pri_error);
++
++ memset(&dummy_ctrl, 0, sizeof(dummy_ctrl));
++ dummy_ctrl.debug = PRI_DEBUG_APDU;
++
++ offset = 0;
++ pri_message(&dummy_ctrl, "Encode/decode message(s)\n");
++ if (argc <= 1) {
++ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
++ for (index = 0; index < ARRAY_LEN(rose_etsi_msgs); ++index) {
++ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
++ &rose_etsi_msgs[index]);
++ }
++ offset += ARRAY_LEN(rose_etsi_msgs);
++
++ dummy_ctrl.switchtype = PRI_SWITCH_QSIG;
++ for (index = 0; index < ARRAY_LEN(rose_qsig_msgs); ++index) {
++ rose_test_msg(&dummy_ctrl, index + offset,
++ &fac_headers[index % ARRAY_LEN(fac_headers)], &rose_qsig_msgs[index]);
++ }
++ offset += ARRAY_LEN(rose_qsig_msgs);
++
++ dummy_ctrl.switchtype = PRI_SWITCH_DMS100;
++ for (index = 0; index < ARRAY_LEN(rose_dms100_msgs); ++index) {
++ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
++ &rose_dms100_msgs[index]);
++ }
++ offset += ARRAY_LEN(rose_dms100_msgs);
++
++ dummy_ctrl.switchtype = PRI_SWITCH_NI2;
++ for (index = 0; index < ARRAY_LEN(rose_ni2_msgs); ++index) {
++ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
++ &rose_ni2_msgs[index]);
++ }
++ //offset += ARRAY_LEN(rose_ni2_msgs);
++ } else {
++ index = atoi(argv[1]);
++
++ if (index < ARRAY_LEN(rose_etsi_msgs)) {
++ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
++ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
++ &rose_etsi_msgs[index]);
++ return 0;
++ }
++ offset += ARRAY_LEN(rose_etsi_msgs);
++ index -= ARRAY_LEN(rose_etsi_msgs);
++
++ if (index < ARRAY_LEN(rose_qsig_msgs)) {
++ dummy_ctrl.switchtype = PRI_SWITCH_QSIG;
++ rose_test_msg(&dummy_ctrl, index + offset,
++ &fac_headers[index % ARRAY_LEN(fac_headers)], &rose_qsig_msgs[index]);
++ return 0;
++ }
++ offset += ARRAY_LEN(rose_qsig_msgs);
++ index -= ARRAY_LEN(rose_qsig_msgs);
++
++ if (index < ARRAY_LEN(rose_dms100_msgs)) {
++ dummy_ctrl.switchtype = PRI_SWITCH_DMS100;
++ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
++ &rose_dms100_msgs[index]);
++ return 0;
++ }
++ offset += ARRAY_LEN(rose_dms100_msgs);
++ index -= ARRAY_LEN(rose_dms100_msgs);
++
++ if (index < ARRAY_LEN(rose_ni2_msgs)) {
++ dummy_ctrl.switchtype = PRI_SWITCH_NI2;
++ rose_test_msg(&dummy_ctrl, index + offset, &fac_headers[0],
++ &rose_ni2_msgs[index]);
++ return 0;
++ }
++ //offset += ARRAY_LEN(rose_ni2_msgs);
++ //index -= ARRAY_LEN(rose_ni2_msgs);
++
++ fprintf(stderr, "Invalid option\n");
++ return 0;
++ }
++
++/* ------------------------------------------------------------------- */
++
++ pri_message(&dummy_ctrl, "\n\n"
++ "Decode unusually encoded messages\n");
++
++ dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
++
++ rose_test_exception(&dummy_ctrl, "Extra bytes on end", rose_etsi_extra,
++ sizeof(rose_etsi_extra));
++
++ rose_test_exception(&dummy_ctrl, "Indefinite length", rose_etsi_indefinite_len,
++ sizeof(rose_etsi_indefinite_len) - 2);
++ rose_test_exception(&dummy_ctrl, "Indefinite length (extra)",
++ rose_etsi_indefinite_len, sizeof(rose_etsi_indefinite_len));
++
++ rose_test_exception(&dummy_ctrl, "Unused components (indefinite length)",
++ rose_etsi_unused_indefinite_len, sizeof(rose_etsi_unused_indefinite_len) - 2);
++ rose_test_exception(&dummy_ctrl, "Unused components (indefinite length, extra)",
++ rose_etsi_unused_indefinite_len, sizeof(rose_etsi_unused_indefinite_len));
++
++ rose_test_exception(&dummy_ctrl, "Unused components", rose_etsi_unused,
++ sizeof(rose_etsi_unused) - 2);
++ rose_test_exception(&dummy_ctrl, "Unused components (extra)", rose_etsi_unused,
++ sizeof(rose_etsi_unused));
++
++/* ------------------------------------------------------------------- */
++
++ pri_message(&dummy_ctrl, "\n\n"
++ "List of operation codes:\n");
++ for (index = 0; index < ROSE_Num_Operation_Codes; ++index) {
++ pri_message(&dummy_ctrl, "%d: %s\n", index, rose_operation2str(index));
++ }
++ pri_message(&dummy_ctrl, "\n\n"
++ "************************************************************\n");
++
++/* ------------------------------------------------------------------- */
++
++ pri_message(&dummy_ctrl, "\n\n"
++ "List of error codes:\n");
++ for (index = 0; index < ROSE_ERROR_Num_Codes; ++index) {
++ pri_message(&dummy_ctrl, "%d: %s\n", index, rose_error2str(index));
++ }
++ pri_message(&dummy_ctrl, "\n\n"
++ "************************************************************\n");
++
++/* ------------------------------------------------------------------- */
++
++ pri_message(&dummy_ctrl, "\n\n");
++ pri_message(&dummy_ctrl, "sizeof(struct rose_message) = %u\n",
++ (unsigned) sizeof(struct rose_message));
++ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_invoke) = %u\n",
++ (unsigned) sizeof(struct rose_msg_invoke));
++ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_result) = %u\n",
++ (unsigned) sizeof(struct rose_msg_result));
++ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_error) = %u\n",
++ (unsigned) sizeof(struct rose_msg_error));
++ pri_message(&dummy_ctrl, "sizeof(struct rose_msg_reject) = %u\n",
++ (unsigned) sizeof(struct rose_msg_reject));
++ pri_message(&dummy_ctrl, "sizeof(union rose_msg_invoke_args) = %u\n",
++ (unsigned) sizeof(union rose_msg_invoke_args));
++ pri_message(&dummy_ctrl, "sizeof(union rose_msg_result_args) = %u\n",
++ (unsigned) sizeof(union rose_msg_result_args));
++
++ pri_message(&dummy_ctrl, "\n");
++ pri_message(&dummy_ctrl, "sizeof(struct roseQsigForwardingList) = %u\n",
++ (unsigned) sizeof(struct roseQsigForwardingList));
++
++ pri_message(&dummy_ctrl, "\n");
++ pri_message(&dummy_ctrl, "sizeof(struct roseQsigCallRerouting_ARG) = %u\n",
++ (unsigned) sizeof(struct roseQsigCallRerouting_ARG));
++ pri_message(&dummy_ctrl, "sizeof(struct roseQsigAocRateArg_ARG) = %u\n",
++ (unsigned) sizeof(struct roseQsigAocRateArg_ARG));
++ pri_message(&dummy_ctrl, "sizeof(struct roseQsigMWIInterrogateRes) = %u\n",
++ (unsigned) sizeof(struct roseQsigMWIInterrogateRes));
++
++ pri_message(&dummy_ctrl, "\n");
++ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiForwardingList) = %u\n",
++ (unsigned) sizeof(struct roseEtsiForwardingList));
++ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiServedUserNumberList) = %u\n",
++ (unsigned) sizeof(struct roseEtsiServedUserNumberList));
++
++ pri_message(&dummy_ctrl, "\n");
++ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiCallRerouting_ARG) = %u\n",
++ (unsigned) sizeof(struct roseEtsiCallRerouting_ARG));
++ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiDiversionInformation_ARG) = %u\n",
++ (unsigned) sizeof(struct roseEtsiDiversionInformation_ARG));
++ pri_message(&dummy_ctrl, "sizeof(struct roseEtsiAOCSCurrencyInfoList) = %u\n",
++ (unsigned) sizeof(struct roseEtsiAOCSCurrencyInfoList));
++
++/* ------------------------------------------------------------------- */
++
++ return 0;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rosetest.c */
+
+Property changes on: rosetest.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_internal.h
+===================================================================
+--- a/rose_internal.h (.../tags/1.4.10.2) (revision 0)
++++ b/rose_internal.h (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,477 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief Internal definitions and prototypes for ROSE.
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++#ifndef _LIBPRI_ROSE_INTERNAL_H
++#define _LIBPRI_ROSE_INTERNAL_H
++
++#include "rose.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++
++/* ------------------------------------------------------------------- */
++
++
++/* Embedded-Q931-Types */
++unsigned char *rose_enc_Q931ie(struct pri *ctrl, unsigned char *pos, unsigned char *end,
++ unsigned tag, const struct roseQ931ie *q931ie);
++
++const unsigned char *rose_dec_Q931ie(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct roseQ931ie *q931ie,
++ size_t contents_size);
++
++/* Addressing-Data-Elements */
++unsigned char *rose_enc_PartyNumber(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePartyNumber *party_number);
++unsigned char *rose_enc_PartySubaddress(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePartySubaddress *party_subaddress);
++unsigned char *rose_enc_Address(struct pri *ctrl, unsigned char *pos, unsigned char *end,
++ unsigned tag, const struct roseAddress *address);
++unsigned char *rose_enc_PresentedNumberUnscreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePresentedNumberUnscreened *party);
++unsigned char *rose_enc_NumberScreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseNumberScreened *screened);
++unsigned char *rose_enc_PresentedNumberScreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePresentedNumberScreened *party);
++unsigned char *rose_enc_AddressScreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseAddressScreened *screened);
++unsigned char *rose_enc_PresentedAddressScreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePresentedAddressScreened *party);
++
++const unsigned char *rose_dec_PartyNumber(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartyNumber *party_number);
++const unsigned char *rose_dec_PartySubaddress(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartySubaddress *party_subaddress);
++const unsigned char *rose_dec_Address(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct roseAddress *address);
++const unsigned char *rose_dec_PresentedNumberUnscreened(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePresentedNumberUnscreened *party);
++const unsigned char *rose_dec_NumberScreened(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseNumberScreened *screened);
++const unsigned char *rose_dec_PresentedNumberScreened(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePresentedNumberScreened *party);
++const unsigned char *rose_dec_AddressScreened(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseAddressScreened *screened);
++const unsigned char *rose_dec_PresentedAddressScreened(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePresentedAddressScreened *party);
++
++/* ETSI Advice-of-Charge (AOC) */
++unsigned char *rose_enc_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++
++const unsigned char *rose_dec_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++
++/* ETSI Call Diversion */
++unsigned char *rose_enc_etsi_ActivationDiversion_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_DeactivationStatusNotificationDiv_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_InterrogationDiversion_RES(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_etsi_DiversionInformation_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++
++const unsigned char *rose_dec_etsi_ActivationDiversion_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_DeactivationStatusNotificationDiv_ARG(struct pri
++ *ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_InterrogationDiversion_RES(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_etsi_DiversionInformation_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++
++/* ETSI Explicit Call Transfer (ECT) */
++unsigned char *rose_enc_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_etsi_EctInform_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++
++const unsigned char *rose_dec_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_etsi_EctInform_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++
++/* Q.SIG Name-Operations */
++unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct roseQsigName *name);
++
++const unsigned char *rose_dec_qsig_Name(struct pri *ctrl, const char *fname,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigName *name);
++
++unsigned char *rose_enc_qsig_CallingName_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_CalledName_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_BusyName_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++
++const unsigned char *rose_dec_qsig_CallingName_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_CalledName_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_BusyName_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++
++/*
++ * Q.SIG Dummy invoke/result argument used by:
++ * SS-AOC-Operations,
++ * Call-Transfer-Operations,
++ * Call-Diversion-Operations,
++ * and SS-MWI-Operations.
++ */
++unsigned char *rose_enc_qsig_DummyArg_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_DummyRes_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++
++const unsigned char *rose_dec_qsig_DummyArg_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_DummyRes_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++
++/* Q.SIG SS-AOC-Operations */
++unsigned char *rose_enc_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_qsig_AocFinal_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_AocInterim_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_AocRate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_AocComplete_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_AocComplete_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++
++const unsigned char *rose_dec_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_qsig_AocFinal_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_AocInterim_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_AocRate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_AocComplete_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_AocComplete_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++
++/* Q.SIG Call-Diversion-Operations */
++unsigned char *rose_enc_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++
++const unsigned char *rose_dec_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++
++/* Q.SIG Call-Transfer-Operations (CT) */
++unsigned char *rose_enc_qsig_CallTransferIdentify_RES(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_CallTransferComplete_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++
++const unsigned char *rose_dec_qsig_CallTransferIdentify_RES(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_CallTransferComplete_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++
++/* Q.SIG SS-MWI-Operations */
++unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++
++const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_MWIInterrogate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_qsig_MWIInterrogate_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++
++/* Northern Telecom DMS-100 operations */
++unsigned char *rose_enc_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++unsigned char *rose_enc_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++
++const unsigned char *rose_dec_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++const unsigned char *rose_dec_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++
++/* National ISDN 2 (NI2) operations */
++unsigned char *rose_enc_ni2_InformationFollowing_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args);
++unsigned char *rose_enc_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++
++const unsigned char *rose_dec_ni2_InformationFollowing_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++const unsigned char *rose_dec_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++
++
++/* ------------------------------------------------------------------- */
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _LIBPRI_ROSE_INTERNAL_H */
++/* ------------------------------------------------------------------- */
++/* end rose_internal.h */
+
+Property changes on: rose_internal.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: pri_q921.h
+===================================================================
+--- a/pri_q921.h (.../tags/1.4.10.2) (revision 1357)
++++ b/pri_q921.h (.../branches/1.4) (revision 1357)
+@@ -192,4 +192,10 @@
+
+ extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
+
++extern int q921_transmit_uiframe(struct pri *pri, void *buf, int len);
++
++extern pri_event *q921_dchannel_up(struct pri *pri);
++
++extern pri_event *q921_dchannel_down(struct pri *pri);
++
+ #endif
+Index: pri_facility.c
+===================================================================
+--- a/pri_facility.c (.../tags/1.4.10.2) (revision 1357)
++++ b/pri_facility.c (.../branches/1.4) (revision 1357)
+@@ -33,872 +33,1340 @@
+ #include "pri_q921.h"
+ #include "pri_q931.h"
+ #include "pri_facility.h"
++#include "rose.h"
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <limits.h>
+
+-static char *asn1id2text(int id)
++static short get_invokeid(struct pri *ctrl)
+ {
+- static char data[32];
+- static char *strings[] = {
+- "none",
+- "Boolean",
+- "Integer",
+- "Bit String",
+- "Octet String",
+- "NULL",
+- "Object Identifier",
+- "Object Descriptor",
+- "External Reference",
+- "Real Number",
+- "Enumerated",
+- "Embedded PDV",
+- "UTF-8 String",
+- "Relative Object ID",
+- "Reserved (0e)",
+- "Reserved (0f)",
+- "Sequence",
+- "Set",
+- "Numeric String",
+- "Printable String",
+- "Tele-Text String",
+- "IA-5 String",
+- "UTC Time",
+- "Generalized Time",
+- };
+- if (id > 0 && id <= 0x18) {
+- return strings[id];
+- } else {
+- sprintf(data, "Unknown (%02x)", id);
+- return data;
+- }
++ ctrl = PRI_MASTER(ctrl);
++ return ++ctrl->last_invoke;
+ }
+
+-static int asn1_dumprecursive(struct pri *pri, void *comp_ptr, int len, int level)
++static int redirectingreason_from_q931(struct pri *ctrl, int redirectingreason)
+ {
+- unsigned char *vdata = (unsigned char *)comp_ptr;
+- struct rose_component *comp;
+- int i = 0;
+- int j, k, l;
+- int clen = 0;
++ int value;
+
+- while (len > 0) {
+- GET_COMPONENT(comp, i, vdata, len);
+- pri_message(pri, "%*s%02X %04X", 2 * level, "", comp->type, comp->len);
+- if ((comp->type == 0) && (comp->len == 0))
+- return clen + 2;
+- if ((comp->type & ASN1_PC_MASK) == ASN1_PRIMITIVE) {
+- for (j = 0; j < comp->len; ++j)
+- pri_message(pri, " %02X", comp->data[j]);
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_QSIG:
++ switch (redirectingreason) {
++ case PRI_REDIR_UNKNOWN:
++ value = QSIG_DIVERT_REASON_UNKNOWN;
++ break;
++ case PRI_REDIR_FORWARD_ON_BUSY:
++ value = QSIG_DIVERT_REASON_CFB;
++ break;
++ case PRI_REDIR_FORWARD_ON_NO_REPLY:
++ value = QSIG_DIVERT_REASON_CFNR;
++ break;
++ case PRI_REDIR_UNCONDITIONAL:
++ value = QSIG_DIVERT_REASON_CFU;
++ break;
++ case PRI_REDIR_DEFLECTION:
++ case PRI_REDIR_DTE_OUT_OF_ORDER:
++ case PRI_REDIR_FORWARDED_BY_DTE:
++ pri_message(ctrl,
++ "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n",
++ redirectingreason);
++ /* Fall through */
++ default:
++ value = QSIG_DIVERT_REASON_UNKNOWN;
++ break;
+ }
+- if ((comp->type & ASN1_CLAN_MASK) == ASN1_UNIVERSAL) {
+- switch (comp->type & ASN1_TYPE_MASK) {
+- case 0:
+- pri_message(pri, " (none)");
+- break;
+- case ASN1_BOOLEAN:
+- pri_message(pri, " (BOOLEAN: %d)", comp->data[0]);
+- break;
+- case ASN1_INTEGER:
+- for (k = l = 0; k < comp->len; ++k)
+- l = (l << 8) | comp->data[k];
+- pri_message(pri, " (INTEGER: %d)", l);
+- break;
+- case ASN1_BITSTRING:
+- pri_message(pri, " (BITSTRING:");
+- for (k = 0; k < comp->len; ++k)
+- pri_message(pri, " %02x", comp->data[k]);
+- pri_message(pri, ")");
+- break;
+- case ASN1_OCTETSTRING:
+- pri_message(pri, " (OCTETSTRING:");
+- for (k = 0; k < comp->len; ++k)
+- pri_message(pri, " %02x", comp->data[k]);
+- pri_message(pri, ")");
+- break;
+- case ASN1_NULL:
+- pri_message(pri, " (NULL)");
+- break;
+- case ASN1_OBJECTIDENTIFIER:
+- pri_message(pri, " (OBJECTIDENTIFIER:");
+- for (k = 0; k < comp->len; ++k)
+- pri_message(pri, " %02x", comp->data[k]);
+- pri_message(pri, ")");
+- break;
+- case ASN1_ENUMERATED:
+- for (k = l = 0; k < comp->len; ++k)
+- l = (l << 8) | comp->data[k];
+- pri_message(pri, " (ENUMERATED: %d)", l);
+- break;
+- case ASN1_SEQUENCE:
+- pri_message(pri, " (SEQUENCE)");
+- break;
+- default:
+- pri_message(pri, " (component %02x - %s)", comp->type, asn1id2text(comp->type & ASN1_TYPE_MASK));
+- break;
+- }
++ break;
++ default:
++ switch (redirectingreason) {
++ case PRI_REDIR_UNKNOWN:
++ value = Q952_DIVERT_REASON_UNKNOWN;
++ break;
++ case PRI_REDIR_FORWARD_ON_BUSY:
++ value = Q952_DIVERT_REASON_CFB;
++ break;
++ case PRI_REDIR_FORWARD_ON_NO_REPLY:
++ value = Q952_DIVERT_REASON_CFNR;
++ break;
++ case PRI_REDIR_DEFLECTION:
++ value = Q952_DIVERT_REASON_CD;
++ break;
++ case PRI_REDIR_UNCONDITIONAL:
++ value = Q952_DIVERT_REASON_CFU;
++ break;
++ case PRI_REDIR_DTE_OUT_OF_ORDER:
++ case PRI_REDIR_FORWARDED_BY_DTE:
++ pri_message(ctrl,
++ "!! Don't know how to convert Q.931 redirection reason %d to Q.952\n",
++ redirectingreason);
++ /* Fall through */
++ default:
++ value = Q952_DIVERT_REASON_UNKNOWN;
++ break;
+ }
+- else if ((comp->type & ASN1_CLAN_MASK) == ASN1_CONTEXT_SPECIFIC) {
+- pri_message(pri, " (CONTEXT SPECIFIC [%d])", comp->type & ASN1_TYPE_MASK);
++ break;
++ }
++
++ return value;
++}
++
++static int redirectingreason_for_q931(struct pri *ctrl, int redirectingreason)
++{
++ int value;
++
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_QSIG:
++ switch (redirectingreason) {
++ case QSIG_DIVERT_REASON_UNKNOWN:
++ value = PRI_REDIR_UNKNOWN;
++ break;
++ case QSIG_DIVERT_REASON_CFU:
++ value = PRI_REDIR_UNCONDITIONAL;
++ break;
++ case QSIG_DIVERT_REASON_CFB:
++ value = PRI_REDIR_FORWARD_ON_BUSY;
++ break;
++ case QSIG_DIVERT_REASON_CFNR:
++ value = PRI_REDIR_FORWARD_ON_NO_REPLY;
++ break;
++ default:
++ pri_message(ctrl, "!! Unknown Q.SIG diversion reason %d\n",
++ redirectingreason);
++ value = PRI_REDIR_UNKNOWN;
++ break;
+ }
+- else {
+- pri_message(pri, " (component %02x)", comp->type);
++ break;
++ default:
++ switch (redirectingreason) {
++ case Q952_DIVERT_REASON_UNKNOWN:
++ value = PRI_REDIR_UNKNOWN;
++ break;
++ case Q952_DIVERT_REASON_CFU:
++ value = PRI_REDIR_UNCONDITIONAL;
++ break;
++ case Q952_DIVERT_REASON_CFB:
++ value = PRI_REDIR_FORWARD_ON_BUSY;
++ break;
++ case Q952_DIVERT_REASON_CFNR:
++ value = PRI_REDIR_FORWARD_ON_NO_REPLY;
++ break;
++ case Q952_DIVERT_REASON_CD:
++ value = PRI_REDIR_DEFLECTION;
++ break;
++ case Q952_DIVERT_REASON_IMMEDIATE:
++ pri_message(ctrl,
++ "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
++ value = PRI_REDIR_UNKNOWN; /* ??? */
++ break;
++ default:
++ pri_message(ctrl, "!! Unknown Q.952 diversion reason %d\n",
++ redirectingreason);
++ value = PRI_REDIR_UNKNOWN;
++ break;
+ }
+- pri_message(pri, "\n");
+- if ((comp->type & ASN1_PC_MASK) == ASN1_CONSTRUCTOR)
+- j = asn1_dumprecursive(pri, comp->data, (comp->len ? comp->len : INT_MAX), level+1);
+- else
+- j = comp->len;
+- j += 2;
+- len -= j;
+- vdata += j;
+- clen += j;
++ break;
+ }
+- return clen;
++
++ return value;
+ }
+
+-int asn1_dump(struct pri *pri, void *comp, int len)
++/*!
++ * \brief Convert the Q.931 type-of-number field to facility.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param ton Q.931 ton/plan octet.
++ *
++ * \return PartyNumber enumeration value.
++ */
++static int typeofnumber_from_q931(struct pri *ctrl, int ton)
+ {
+- return asn1_dumprecursive(pri, comp, len, 0);
++ int value;
++
++ switch ((ton >> 4) & 0x03) {
++ default:
++ pri_message(ctrl, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
++ /* fall through */
++ case PRI_TON_UNKNOWN:
++ value = Q932_TON_UNKNOWN;
++ break;
++ case PRI_TON_INTERNATIONAL:
++ value = Q932_TON_INTERNATIONAL;
++ break;
++ case PRI_TON_NATIONAL:
++ value = Q932_TON_NATIONAL;
++ break;
++ case PRI_TON_NET_SPECIFIC:
++ value = Q932_TON_NET_SPECIFIC;
++ break;
++ case PRI_TON_SUBSCRIBER:
++ value = Q932_TON_SUBSCRIBER;
++ break;
++ case PRI_TON_ABBREVIATED:
++ value = Q932_TON_ABBREVIATED;
++ break;
++ }
++
++ return value;
+ }
+
+-static unsigned char get_invokeid(struct pri *pri)
++static int typeofnumber_for_q931(struct pri *ctrl, int ton)
+ {
+- return ++pri->last_invoke;
++ int value;
++
++ switch (ton) {
++ default:
++ pri_message(ctrl, "!! Invalid TypeOfNumber %d\n", ton);
++ /* fall through */
++ case Q932_TON_UNKNOWN:
++ value = PRI_TON_UNKNOWN;
++ break;
++ case Q932_TON_INTERNATIONAL:
++ value = PRI_TON_INTERNATIONAL;
++ break;
++ case Q932_TON_NATIONAL:
++ value = PRI_TON_NATIONAL;
++ break;
++ case Q932_TON_NET_SPECIFIC:
++ value = PRI_TON_NET_SPECIFIC;
++ break;
++ case Q932_TON_SUBSCRIBER:
++ value = PRI_TON_SUBSCRIBER;
++ break;
++ case Q932_TON_ABBREVIATED:
++ value = PRI_TON_ABBREVIATED;
++ break;
++ }
++
++ return value << 4;
+ }
+
+-struct addressingdataelements_presentednumberunscreened {
+- char partyaddress[21];
+- char partysubaddress[21];
+- int npi; /* Numbering Plan Indicator */
+- int ton; /* Type Of Number */
+- int pres; /* Presentation */
+-};
++/*!
++ * \internal
++ * \brief Convert the Q.931 numbering plan field to facility.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param plan Q.931 ton/plan octet.
++ *
++ * \return PartyNumber enumeration value.
++ */
++static int numbering_plan_from_q931(struct pri *ctrl, int plan)
++{
++ int value;
+
+-struct addressingdataelements_presentednumberscreened {
+- char partyaddress[21];
+- char partysubaddress[21];
+- int npi; /* Numbering Plan Indicator */
+- int ton; /* Type Of Number */
+- int pres; /* Presentation */
+- int scrind; /* Screening Indicator */
+-};
++ switch (plan & 0x0F) {
++ default:
++ pri_message(ctrl, "!! Unsupported Q.931 numbering plan value (%d)\n", plan);
++ /* fall through */
++ case PRI_NPI_UNKNOWN:
++ value = 0; /* unknown */
++ break;
++ case PRI_NPI_E163_E164:
++ value = 1; /* public */
++ break;
++ case PRI_NPI_X121:
++ value = 3; /* data */
++ break;
++ case PRI_NPI_F69:
++ value = 4; /* telex */
++ break;
++ case PRI_NPI_NATIONAL:
++ value = 8; /* nationalStandard */
++ break;
++ case PRI_NPI_PRIVATE:
++ value = 5; /* private */
++ break;
++ }
+
+-#define PRI_CHECKOVERFLOW(size) \
+- if (msgptr - message + (size) >= sizeof(message)) { \
+- *msgptr = '\0'; \
+- pri_message(pri, "%s", message); \
+- msgptr = message; \
+- }
++ return value;
++}
+
+-static void dump_apdu(struct pri *pri, unsigned char *c, int len)
++/*!
++ * \internal
++ * \brief Convert the PartyNumber numbering plan to Q.931 plan field value.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param plan PartyNumber enumeration value.
++ *
++ * \return Q.931 plan field value.
++ */
++static int numbering_plan_for_q931(struct pri *ctrl, int plan)
+ {
+- #define MAX_APDU_LENGTH 255
+- static char hexs[16] = "0123456789ABCDEF";
+- int i;
+- char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */
+- char *msgptr;
+-
+- msgptr = message;
+- *msgptr++ = ' ';
+- *msgptr++ = '[';
+- for (i=0; i<len; i++) {
+- PRI_CHECKOVERFLOW(3);
+- *msgptr++ = ' ';
+- *msgptr++ = hexs[(c[i] >> 4) & 0x0f];
+- *msgptr++ = hexs[(c[i]) & 0x0f];
++ int value;
++
++ switch (plan) {
++ default:
++ pri_message(ctrl,
++ "!! Unsupported PartyNumber to Q.931 numbering plan value (%d)\n", plan);
++ /* fall through */
++ case 0: /* unknown */
++ value = PRI_NPI_UNKNOWN;
++ break;
++ case 1: /* public */
++ value = PRI_NPI_E163_E164;
++ break;
++ case 3: /* data */
++ value = PRI_NPI_X121;
++ break;
++ case 4: /* telex */
++ value = PRI_NPI_F69;
++ break;
++ case 5: /* private */
++ value = PRI_NPI_PRIVATE;
++ break;
++ case 8: /* nationalStandard */
++ value = PRI_NPI_NATIONAL;
++ break;
+ }
+- PRI_CHECKOVERFLOW(6);
+- strcpy(msgptr, " ] - [");
+- msgptr += strlen(msgptr);
+- for (i=0; i<len; i++) {
+- PRI_CHECKOVERFLOW(1);
+- *msgptr++ = ((c[i] < ' ') || (c[i] > '~')) ? '.' : c[i];
++
++ return value;
++}
++
++/*!
++ * \internal
++ * \brief Convert the Q.931 number presentation field to facility.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param presentation Q.931 presentation/screening octet.
++ * \param number_present Non-zero if the number is available.
++ *
++ * \return Presented<Number/Address><Screened/Unscreened> enumeration value.
++ */
++static int presentation_from_q931(struct pri *ctrl, int presentation, int number_present)
++{
++ int value;
++
++ switch (presentation & PRI_PRES_RESTRICTION) {
++ case PRI_PRES_ALLOWED:
++ value = 0; /* presentationAllowed<Number/Address> */
++ break;
++ default:
++ pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
++ presentation);
++ /* fall through */
++ case PRI_PRES_RESTRICTED:
++ if (number_present) {
++ value = 3; /* presentationRestricted<Number/Address> */
++ } else {
++ value = 1; /* presentationRestricted */
++ }
++ break;
++ case PRI_PRES_UNAVAILABLE:
++ value = 2; /* numberNotAvailableDueToInterworking */
++ break;
+ }
+- PRI_CHECKOVERFLOW(2);
+- *msgptr++ = ']';
+- *msgptr++ = '\n';
+- *msgptr = '\0';
+- pri_message(pri, "%s", message);
++
++ return value;
+ }
+-#undef PRI_CHECKOVERFLOW
+
+-int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
++/*!
++ * \internal
++ * \brief Convert the Presented<Number/Address><Screened/Unscreened> presentation
++ * to Q.931 presentation field value.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param presentation Presented<Number/Address><Screened/Unscreened> value.
++ *
++ * \return Q.931 presentation field value.
++ */
++static int presentation_for_q931(struct pri *ctrl, int presentation)
+ {
+- switch(pri->switchtype) {
+- case PRI_SWITCH_QSIG:
+- switch(redirectingreason) {
+- case PRI_REDIR_UNKNOWN:
+- return QSIG_DIVERT_REASON_UNKNOWN;
+- case PRI_REDIR_FORWARD_ON_BUSY:
+- return QSIG_DIVERT_REASON_CFB;
+- case PRI_REDIR_FORWARD_ON_NO_REPLY:
+- return QSIG_DIVERT_REASON_CFNR;
+- case PRI_REDIR_UNCONDITIONAL:
+- return QSIG_DIVERT_REASON_CFU;
+- case PRI_REDIR_DEFLECTION:
+- case PRI_REDIR_DTE_OUT_OF_ORDER:
+- case PRI_REDIR_FORWARDED_BY_DTE:
+- pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason);
+- /* Fall through */
+- default:
+- return QSIG_DIVERT_REASON_UNKNOWN;
+- }
+- default:
+- switch(redirectingreason) {
+- case PRI_REDIR_UNKNOWN:
+- return Q952_DIVERT_REASON_UNKNOWN;
+- case PRI_REDIR_FORWARD_ON_BUSY:
+- return Q952_DIVERT_REASON_CFB;
+- case PRI_REDIR_FORWARD_ON_NO_REPLY:
+- return Q952_DIVERT_REASON_CFNR;
+- case PRI_REDIR_DEFLECTION:
+- return Q952_DIVERT_REASON_CD;
+- case PRI_REDIR_UNCONDITIONAL:
+- return Q952_DIVERT_REASON_CFU;
+- case PRI_REDIR_DTE_OUT_OF_ORDER:
+- case PRI_REDIR_FORWARDED_BY_DTE:
+- pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.952\n", redirectingreason);
+- /* Fall through */
+- default:
+- return Q952_DIVERT_REASON_UNKNOWN;
+- }
++ int value;
++
++ switch (presentation) {
++ case 0: /* presentationAllowed<Number/Address> */
++ value = PRI_PRES_ALLOWED;
++ break;
++ default:
++ pri_message(ctrl,
++ "!! Unsupported Presented<Number/Address><Screened/Unscreened> to Q.931 value (%d)\n",
++ presentation);
++ /* fall through */
++ case 1: /* presentationRestricted */
++ case 3: /* presentationRestricted<Number/Address> */
++ value = PRI_PRES_RESTRICTED;
++ break;
++ case 2: /* numberNotAvailableDueToInterworking */
++ value = PRI_PRES_UNAVAILABLE;
++ break;
+ }
++
++ return value;
+ }
+
+-static int redirectingreason_for_q931(struct pri *pri, int redirectingreason)
++/*!
++ * \internal
++ * \brief Convert the Q.931 number presentation field to Q.SIG name presentation.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param presentation Q.931 presentation/screening octet.
++ * \param name_present Non-zero if the name is available.
++ *
++ * \return Name presentation enumeration value.
++ */
++static int qsig_name_presentation_from_q931(struct pri *ctrl, int presentation, int name_present)
+ {
+- switch(pri->switchtype) {
+- case PRI_SWITCH_QSIG:
+- switch(redirectingreason) {
+- case QSIG_DIVERT_REASON_UNKNOWN:
+- return PRI_REDIR_UNKNOWN;
+- case QSIG_DIVERT_REASON_CFU:
+- return PRI_REDIR_UNCONDITIONAL;
+- case QSIG_DIVERT_REASON_CFB:
+- return PRI_REDIR_FORWARD_ON_BUSY;
+- case QSIG_DIVERT_REASON_CFNR:
+- return PRI_REDIR_FORWARD_ON_NO_REPLY;
+- default:
+- pri_message(pri, "!! Unknown Q.SIG diversion reason %d\n", redirectingreason);
+- return PRI_REDIR_UNKNOWN;
+- }
+- default:
+- switch(redirectingreason) {
+- case Q952_DIVERT_REASON_UNKNOWN:
+- return PRI_REDIR_UNKNOWN;
+- case Q952_DIVERT_REASON_CFU:
+- return PRI_REDIR_UNCONDITIONAL;
+- case Q952_DIVERT_REASON_CFB:
+- return PRI_REDIR_FORWARD_ON_BUSY;
+- case Q952_DIVERT_REASON_CFNR:
+- return PRI_REDIR_FORWARD_ON_NO_REPLY;
+- case Q952_DIVERT_REASON_CD:
+- return PRI_REDIR_DEFLECTION;
+- case Q952_DIVERT_REASON_IMMEDIATE:
+- pri_message(pri, "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
+- return PRI_REDIR_UNKNOWN; /* ??? */
+- default:
+- pri_message(pri, "!! Unknown Q.952 diversion reason %d\n", redirectingreason);
+- return PRI_REDIR_UNKNOWN;
+- }
++ int value;
++
++ switch (presentation & PRI_PRES_RESTRICTION) {
++ case PRI_PRES_ALLOWED:
++ if (name_present) {
++ value = 1; /* presentation_allowed */
++ } else {
++ value = 4; /* name_not_available */
++ }
++ break;
++ default:
++ pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
++ presentation);
++ /* fall through */
++ case PRI_PRES_RESTRICTED:
++ if (name_present) {
++ value = 2; /* presentation_restricted */
++ } else {
++ value = 3; /* presentation_restricted_null */
++ }
++ break;
++ case PRI_PRES_UNAVAILABLE:
++ value = 4; /* name_not_available */
++ break;
+ }
++
++ return value;
+ }
+
+-int typeofnumber_from_q931(struct pri *pri, int ton)
++/*!
++ * \internal
++ * \brief Convert the Q.SIG name presentation to Q.931 presentation field value.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param presentation Q.SIG name presentation value.
++ *
++ * \return Q.931 presentation field value.
++ */
++static int qsig_name_presentation_for_q931(struct pri *ctrl, int presentation)
+ {
+- switch(ton) {
+- case PRI_TON_INTERNATIONAL:
+- return Q932_TON_INTERNATIONAL;
+- case PRI_TON_NATIONAL:
+- return Q932_TON_NATIONAL;
+- case PRI_TON_NET_SPECIFIC:
+- return Q932_TON_NET_SPECIFIC;
+- case PRI_TON_SUBSCRIBER:
+- return Q932_TON_SUBSCRIBER;
+- case PRI_TON_ABBREVIATED:
+- return Q932_TON_ABBREVIATED;
+- case PRI_TON_RESERVED:
+- default:
+- pri_message(pri, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
+- /* fall through */
+- case PRI_TON_UNKNOWN:
+- return Q932_TON_UNKNOWN;
++ int value;
++
++ switch (presentation) {
++ case 1: /* presentation_allowed */
++ value = PRI_PRES_ALLOWED;
++ break;
++ default:
++ pri_message(ctrl,
++ "!! Unsupported Q.SIG name presentation to Q.931 value (%d)\n",
++ presentation);
++ /* fall through */
++ case 2: /* presentation_restricted */
++ case 3: /* presentation_restricted_null */
++ value = PRI_PRES_RESTRICTED;
++ break;
++ case 0: /* optional_name_not_present */
++ case 4: /* name_not_available */
++ value = PRI_PRES_UNAVAILABLE;
++ break;
+ }
++
++ return value;
+ }
+
+-static int typeofnumber_for_q931(struct pri *pri, int ton)
++/*!
++ * \internal
++ * \brief Convert number presentation to Q.SIG diversion subscription notification.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param presentation Number presentation value.
++ *
++ * \return Q.SIG diversion subscription notification value.
++ */
++static int presentation_to_subscription(struct pri *ctrl, int presentation)
+ {
+- switch (ton) {
+- case Q932_TON_UNKNOWN:
+- return PRI_TON_UNKNOWN;
+- case Q932_TON_INTERNATIONAL:
+- return PRI_TON_INTERNATIONAL;
+- case Q932_TON_NATIONAL:
+- return PRI_TON_NATIONAL;
+- case Q932_TON_NET_SPECIFIC:
+- return PRI_TON_NET_SPECIFIC;
+- case Q932_TON_SUBSCRIBER:
+- return PRI_TON_SUBSCRIBER;
+- case Q932_TON_ABBREVIATED:
+- return PRI_TON_ABBREVIATED;
+- default:
+- pri_message(pri, "!! Invalid Q.932 TypeOfNumber %d\n", ton);
+- return PRI_TON_UNKNOWN;
++ /* derive subscription value from presentation value */
++
++ switch (presentation & PRI_PRES_RESTRICTION) {
++ case PRI_PRES_ALLOWED:
++ return QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR;
++ case PRI_PRES_RESTRICTED:
++ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
++ case PRI_PRES_UNAVAILABLE: /* Number not available due to interworking */
++ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR; /* ?? QSIG_NO_NOTIFICATION */
++ default:
++ pri_message(ctrl, "!! Unknown Q.SIG presentationIndicator 0x%02x\n",
++ presentation);
++ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
+ }
+ }
+
+-int asn1_name_decode(void * data, int len, char *namebuf, int buflen)
++/*!
++ * \internal
++ * \brief Copy the given rose party number to the q931_party_number
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param q931_number Q.931 party number structure
++ * \param rose_number ROSE party number structure
++ *
++ * \note It is assumed that the q931_number has been initialized before calling.
++ *
++ * \return Nothing
++ */
++static void rose_copy_number_to_q931(struct pri *ctrl,
++ struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number)
+ {
+- struct rose_component *comp = (struct rose_component*)data;
+- int datalen = 0, res = 0;
++ //q931_party_number_init(q931_number);
++ libpri_copy_string(q931_number->str, (char *) rose_number->str,
++ sizeof(q931_number->str));
++ q931_number->plan = numbering_plan_for_q931(ctrl, rose_number->plan)
++ | typeofnumber_for_q931(ctrl, rose_number->ton);
++ q931_number->valid = 1;
++}
+
+- if (comp->len == ASN1_LEN_INDEF) {
+- datalen = strlen((char *)comp->data);
+- res = datalen + 2;
+- } else
+- datalen = res = comp->len;
++/*!
++ * \internal
++ * \brief Copy the given rose subaddress to the q931_party_subaddress.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param q931_subaddress Q.931 party subaddress structure
++ * \param rose_subaddress ROSE subaddress structure
++ *
++ * \note It is assumed that the q931_subaddress has been initialized before calling.
++ *
++ * \return Nothing
++ */
++static void rose_copy_subaddress_to_q931(struct pri *ctrl,
++ struct q931_party_subaddress *q931_subaddress,
++ const struct rosePartySubaddress *rose_subaddress)
++{
++ //q931_party_subaddress_init(q931_subaddress);
++ if (!rose_subaddress->length) {
++ /* Subaddress is not present. */
++ return;
++ }
+
+- if (datalen > buflen) {
+- /* Truncate */
+- datalen = buflen;
++ switch (rose_subaddress->type) {
++ case 0:/* UserSpecified */
++ q931_subaddress->type = 2;/* user_specified */
++ q931_subaddress->valid = 1;
++ q931_subaddress->length = rose_subaddress->length;
++ if (sizeof(q931_subaddress->data) <= q931_subaddress->length) {
++ q931_subaddress->length = sizeof(q931_subaddress->data) - 1;
++ }
++ memcpy(q931_subaddress->data, rose_subaddress->u.user_specified.information,
++ q931_subaddress->length);
++ q931_subaddress->data[q931_subaddress->length] = '\0';
++ if (rose_subaddress->u.user_specified.odd_count_present) {
++ q931_subaddress->odd_even_indicator =
++ rose_subaddress->u.user_specified.odd_count;
++ }
++ break;
++ case 1:/* NSAP */
++ q931_subaddress->type = 0;/* nsap */
++ q931_subaddress->valid = 1;
++ libpri_copy_string((char *) q931_subaddress->data,
++ (char *) rose_subaddress->u.nsap, sizeof(q931_subaddress->data));
++ q931_subaddress->length = strlen((char *) q931_subaddress->data);
++ break;
++ default:
++ /* Don't know how to encode so assume it is not present. */
++ break;
+ }
+- memcpy(namebuf, comp->data, datalen);
+- return res + 2;
+ }
+
+-int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len)
++/*!
++ * \internal
++ * \brief Copy the given rose address to the q931_party_id address.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param q931_address Q.931 party id structure to fill address
++ * \param rose_address ROSE address structure
++ *
++ * \note It is assumed that the q931_address has been initialized before calling.
++ *
++ * \return Nothing
++ */
++static void rose_copy_address_to_q931(struct pri *ctrl,
++ struct q931_party_id *q931_address, const struct roseAddress *rose_address)
+ {
+- struct rose_component *comp = NULL;
+-
+- if (len < 2 + src_len)
+- return -1;
++ rose_copy_number_to_q931(ctrl, &q931_address->number, &rose_address->number);
++ rose_copy_subaddress_to_q931(ctrl, &q931_address->subaddress,
++ &rose_address->subaddress);
++}
+
+- if (max_len && (src_len > max_len))
+- src_len = max_len;
++/*!
++ * \internal
++ * \brief Copy the given rose presented screened party number to the q931_party_number
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param q931_number Q.931 party number structure
++ * \param rose_presented ROSE presented screened party number structure
++ *
++ * \return Nothing
++ */
++static void rose_copy_presented_number_screened_to_q931(struct pri *ctrl,
++ struct q931_party_number *q931_number,
++ const struct rosePresentedNumberScreened *rose_presented)
++{
++ q931_party_number_init(q931_number);
++ q931_number->valid = 1;
++ q931_number->presentation = presentation_for_q931(ctrl, rose_presented->presentation);
++ switch (rose_presented->presentation) {
++ case 0: /* presentationAllowedNumber */
++ case 3: /* presentationRestrictedNumber */
++ q931_number->presentation |=
++ (rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
++ rose_copy_number_to_q931(ctrl, q931_number,
++ &rose_presented->screened.number);
++ break;
++ default:
++ q931_number->presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
++ break;
++ }
++}
+
+- comp = (struct rose_component *)data;
+- comp->type = asn1_type;
+- comp->len = src_len;
+- memcpy(comp->data, src, src_len);
+-
+- return 2 + src_len;
++/*!
++ * \internal
++ * \brief Copy the given rose presented unscreened party number to the q931_party_number
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param q931_number Q.931 party number structure
++ * \param rose_presented ROSE presented unscreened party number structure
++ *
++ * \return Nothing
++ */
++static void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl,
++ struct q931_party_number *q931_number,
++ const struct rosePresentedNumberUnscreened *rose_presented)
++{
++ q931_party_number_init(q931_number);
++ q931_number->valid = 1;
++ q931_number->presentation = presentation_for_q931(ctrl,
++ rose_presented->presentation) | PRI_PRES_USER_NUMBER_UNSCREENED;
++ switch (rose_presented->presentation) {
++ case 0: /* presentationAllowedNumber */
++ case 3: /* presentationRestrictedNumber */
++ rose_copy_number_to_q931(ctrl, q931_number, &rose_presented->number);
++ break;
++ default:
++ break;
++ }
+ }
+
+-int asn1_copy_string(char * buf, int buflen, struct rose_component *comp)
++/*!
++ * \internal
++ * \brief Copy the given rose presented screened party address to the q931_party_number
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param q931_address Q.931 party id structure to fill the address
++ * \param rose_presented ROSE presented screened party address structure
++ *
++ * \return Nothing
++ */
++static void rose_copy_presented_address_screened_to_q931(struct pri *ctrl,
++ struct q931_party_id *q931_address,
++ const struct rosePresentedAddressScreened *rose_presented)
+ {
+- int res;
+- int datalen;
++ q931_party_number_init(&q931_address->number);
++ q931_party_subaddress_init(&q931_address->subaddress);
++ q931_address->number.valid = 1;
++ q931_address->number.presentation = presentation_for_q931(ctrl,
++ rose_presented->presentation);
++ switch (rose_presented->presentation) {
++ case 0: /* presentationAllowedAddress */
++ case 3: /* presentationRestrictedAddress */
++ q931_address->number.presentation |=
++ (rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
++ rose_copy_number_to_q931(ctrl, &q931_address->number,
++ &rose_presented->screened.number);
++ rose_copy_subaddress_to_q931(ctrl, &q931_address->subaddress,
++ &rose_presented->screened.subaddress);
++ break;
++ default:
++ q931_address->number.presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
++ break;
++ }
++}
+
+- if ((comp->len > buflen) && (comp->len != ASN1_LEN_INDEF))
+- return -1;
++/*!
++ * \internal
++ * \brief Copy the given rose party name to the q931_party_name
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param qsig_name Q.SIG party name structure
++ * \param rose_name Q.SIG ROSE party name structure
++ *
++ * \return Nothing
++ */
++static void rose_copy_name_to_q931(struct pri *ctrl,
++ struct q931_party_name *qsig_name, const struct roseQsigName *rose_name)
++{
++ //q931_party_name_init(qsig_name);
++ qsig_name->valid = 1;
++ qsig_name->presentation = qsig_name_presentation_for_q931(ctrl,
++ rose_name->presentation);
++ qsig_name->char_set = rose_name->char_set;
++ libpri_copy_string(qsig_name->str, (char *) rose_name->data, sizeof(qsig_name->str));
++}
+
+- if (comp->len == ASN1_LEN_INDEF) {
+- datalen = strlen((char*)comp->data);
+- res = datalen + 2;
+- } else
+- res = datalen = comp->len;
++/*!
++ * \internal
++ * \brief Copy the given q931_party_number to the rose party number
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param rose_number ROSE party number structure
++ * \param q931_number Q.931 party number structure
++ *
++ * \return Nothing
++ */
++static void q931_copy_number_to_rose(struct pri *ctrl,
++ struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number)
++{
++ rose_number->plan = numbering_plan_from_q931(ctrl, q931_number->plan);
++ rose_number->ton = typeofnumber_from_q931(ctrl, q931_number->plan);
++ /* Truncate the q931_number->str if necessary. */
++ libpri_copy_string((char *) rose_number->str, q931_number->str,
++ sizeof(rose_number->str));
++ rose_number->length = strlen((char *) rose_number->str);
++}
+
+- memcpy(buf, comp->data, datalen);
+- buf[datalen] = 0;
++/*!
++ * \internal
++ * \brief Copy the given q931_party_subaddress to the rose subaddress.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param rose_subaddress ROSE subaddress structure
++ * \param q931_subaddress Q.931 party subaddress structure
++ *
++ * \return Nothing
++ */
++static void q931_copy_subaddress_to_rose(struct pri *ctrl,
++ struct rosePartySubaddress *rose_subaddress,
++ const struct q931_party_subaddress *q931_subaddress)
++{
++ if (!q931_subaddress->valid) {
++ /* Subaddress is not present. */
++ rose_subaddress->length = 0;
++ return;
++ }
+
+- return res;
++ switch (q931_subaddress->type) {
++ case 0: /* NSAP */
++ rose_subaddress->type = 1;/* NSAP */
++ libpri_copy_string((char *) rose_subaddress->u.nsap,
++ (char *) q931_subaddress->data, sizeof(rose_subaddress->u.nsap));
++ rose_subaddress->length = strlen((char *) rose_subaddress->u.nsap);
++ break;
++ case 2: /* user_specified */
++ rose_subaddress->type = 0;/* UserSpecified */
++ rose_subaddress->length = q931_subaddress->length;
++ if (sizeof(rose_subaddress->u.user_specified.information)
++ <= rose_subaddress->length) {
++ rose_subaddress->length =
++ sizeof(rose_subaddress->u.user_specified.information) - 1;
++ } else {
++ if (q931_subaddress->odd_even_indicator) {
++ rose_subaddress->u.user_specified.odd_count_present = 1;
++ rose_subaddress->u.user_specified.odd_count = 1;
++ }
++ }
++ memcpy(rose_subaddress->u.user_specified.information, q931_subaddress->data,
++ rose_subaddress->length);
++ rose_subaddress->u.user_specified.information[rose_subaddress->length] = '\0';
++ break;
++ default:
++ /* Don't know how to encode so assume it is not present. */
++ rose_subaddress->length = 0;
++ break;
++ }
+ }
+
+-static int rose_number_digits_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
++/*!
++ * \internal
++ * \brief Copy the given q931_party_id address to the rose address.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param rose_address ROSE address structure
++ * \param q931_address Q.931 party id structure to give address
++ *
++ * \return Nothing
++ */
++static void q931_copy_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address,
++ const struct q931_party_id *q931_address)
+ {
+- int i = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = data;
+- int datalen = 0;
+- int res = 0;
++ q931_copy_number_to_rose(ctrl, &rose_address->number, &q931_address->number);
++ q931_copy_subaddress_to_rose(ctrl, &rose_address->subaddress,
++ &q931_address->subaddress);
++}
+
+- do {
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
+- if(comp->len > 20 && comp->len != ASN1_LEN_INDEF) {
+- pri_message(pri, "!! Oversized NumberDigits component (%d)\n", comp->len);
+- return -1;
+- }
+- if (comp->len == ASN1_LEN_INDEF) {
+- datalen = strlen((char *)comp->data);
+- res = datalen + 2;
+- } else
+- res = datalen = comp->len;
+-
+- memcpy(value->partyaddress, comp->data, datalen);
+- value->partyaddress[datalen] = '\0';
++/*!
++ * \internal
++ * \brief Copy the given q931_party_number to the rose presented screened party number
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param rose_presented ROSE presented screened party number structure
++ * \param q931_number Q.931 party number structure
++ *
++ * \return Nothing
++ */
++static void q931_copy_presented_number_screened_to_rose(struct pri *ctrl,
++ struct rosePresentedNumberScreened *rose_presented,
++ const struct q931_party_number *q931_number)
++{
++ if (q931_number->valid) {
++ rose_presented->presentation =
++ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
++ rose_presented->screened.screening_indicator =
++ q931_number->presentation & PRI_PRES_NUMBER_TYPE;
++ q931_copy_number_to_rose(ctrl, &rose_presented->screened.number, q931_number);
++ } else {
++ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
++ }
++}
+
+- return res + 2;
++/*!
++ * \internal
++ * \brief Copy the given q931_party_number to the rose presented unscreened party number
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param rose_presented ROSE presented unscreened party number structure
++ * \param q931_number Q.931 party number structure
++ *
++ * \return Nothing
++ */
++static void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl,
++ struct rosePresentedNumberUnscreened *rose_presented,
++ const struct q931_party_number *q931_number)
++{
++ if (q931_number->valid) {
++ rose_presented->presentation =
++ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
++ q931_copy_number_to_rose(ctrl, &rose_presented->number, q931_number);
++ } else {
++ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
+ }
+- while(0);
+-
+- return -1;
+ }
+
+-static int rose_public_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
++#if 0 /* In case it is needed in the future */
++/*!
++ * \internal
++ * \brief Copy the given q931_party_number to the rose presented screened party address
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param rose_presented ROSE presented screened party address structure
++ * \param q931_address Q.931 party id structure to get the address
++ *
++ * \return Nothing
++ */
++static void q931_copy_presented_address_screened_to_rose(struct pri *ctrl,
++ struct rosePresentedAddressScreened *rose_presented,
++ const struct q931_party_id *q931_address)
+ {
+- int i = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = data;
+- int ton;
+- int res = 0;
++ if (q931_address->number.valid) {
++ rose_presented->presentation =
++ presentation_from_q931(ctrl, q931_address->number.presentation,
++ q931_address->number.str[0]);
++ rose_presented->screened.screening_indicator =
++ q931_address->number.presentation & PRI_PRES_NUMBER_TYPE;
++ q931_copy_number_to_rose(ctrl, &rose_presented->screened.number,
++ &q931_address->number);
++ q931_copy_subaddress_to_rose(ctrl, &rose_presented->screened.subaddress,
++ &q931_address->subaddress);
++ } else {
++ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
++ }
++}
++#endif /* In case it is needed in the future */
+
+- if (len < 2)
+- return -1;
++/*!
++ * \internal
++ * \brief Copy the given q931_party_name to the rose party name
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param rose_name Q.SIG ROSE party name structure
++ * \param qsig_name Q.SIG party name structure
++ *
++ * \return Nothing
++ */
++static void q931_copy_name_to_rose(struct pri *ctrl,
++ struct roseQsigName *rose_name, const struct q931_party_name *qsig_name)
++{
++ if (qsig_name->valid) {
++ rose_name->presentation = qsig_name_presentation_from_q931(ctrl,
++ qsig_name->presentation, qsig_name->str[0]);
++ rose_name->char_set = qsig_name->char_set;
++ /* Truncate the qsig_name->str if necessary. */
++ libpri_copy_string((char *) rose_name->data, qsig_name->str, sizeof(rose_name->data));
++ rose_name->length = strlen((char *) rose_name->data);
++ } else {
++ rose_name->presentation = 4;/* name_not_available */
++ }
++}
+
+- do {
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
+- ASN1_GET_INTEGER(comp, ton);
+- NEXT_COMPONENT(comp, i);
+- ton = typeofnumber_for_q931(pri, ton);
++/*!
++ * \internal
++ * \brief Encode the Q.SIG DivertingLegInformation1 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode diversion leg 1.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_diverting_leg_information1(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, q931_call *call)
++{
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
+
+- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
+- if (res < 0)
+- return -1;
+- value->ton = ton;
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
+- return res + 3;
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_DivertingLegInformation1;
++ msg.invoke_id = get_invokeid(ctrl);
++ msg.args.qsig.DivertingLegInformation1.diversion_reason =
++ redirectingreason_from_q931(ctrl, call->redirecting.reason);
+
+- } while(0);
+- return -1;
++ /* subscriptionOption is the redirecting.to.number.presentation */
++ msg.args.qsig.DivertingLegInformation1.subscription_option =
++ presentation_to_subscription(ctrl, call->redirecting.to.number.presentation);
++
++ /* nominatedNr is the redirecting.to.number */
++ q931_copy_number_to_rose(ctrl,
++ &msg.args.qsig.DivertingLegInformation1.nominated_number,
++ &call->redirecting.to.number);
++
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
+ }
+
+-static int rose_private_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
++/*!
++ * \internal
++ * \brief Encode the ETSI DivertingLegInformation1 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode diversion leg 1.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_diverting_leg_information1(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, q931_call *call)
+ {
+- int i = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = data;
+- int ton;
+- int res = 0;
++ struct rose_msg_invoke msg;
+
+- if (len < 2)
+- return -1;
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
+- do {
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PrivatePartyNumber ROSE component type 0x%x\n");
+- ASN1_GET_INTEGER(comp, ton);
+- NEXT_COMPONENT(comp, i);
+- ton = typeofnumber_for_q931(pri, ton);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_ETSI_DivertingLegInformation1;
++ msg.invoke_id = get_invokeid(ctrl);
++ msg.args.etsi.DivertingLegInformation1.diversion_reason =
++ redirectingreason_from_q931(ctrl, call->redirecting.reason);
+
+- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
+- if (res < 0)
+- return -1;
+- value->ton = ton;
++ if (call->redirecting.to.number.valid) {
++ msg.args.etsi.DivertingLegInformation1.subscription_option = 2;
+
+- return res + 3;
++ /* divertedToNumber is the redirecting.to.number */
++ msg.args.etsi.DivertingLegInformation1.diverted_to_present = 1;
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.etsi.DivertingLegInformation1.diverted_to,
++ &call->redirecting.to.number);
++ } else {
++ msg.args.etsi.DivertingLegInformation1.subscription_option = 1;
++ }
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- } while(0);
+- return -1;
++ return pos;
+ }
+
+-static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
++/*!
++ * \brief Encode and queue the DivertingLegInformation1 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode diversion leg 1.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int rose_diverting_leg_information1_encode(struct pri *ctrl, q931_call *call)
+ {
+- int i = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = data;
+- int res = 0;
++ unsigned char buffer[256];
++ unsigned char *end;
+
+- do {
+- GET_COMPONENT(comp, i, vdata, len);
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ end = enc_etsi_diverting_leg_information1(ctrl, buffer, buffer + sizeof(buffer),
++ call);
++ break;
++ case PRI_SWITCH_QSIG:
++ end = enc_qsig_diverting_leg_information1(ctrl, buffer, buffer + sizeof(buffer),
++ call);
++ break;
++ default:
++ return -1;
++ }
++ if (!end) {
++ return -1;
++ }
+
+- switch(comp->type) {
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] unknownPartyNumber */
+- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+- if (res < 0)
+- return -1;
+- value->npi = PRI_NPI_UNKNOWN;
+- value->ton = PRI_TON_UNKNOWN;
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber */
+- res = asn1_copy_string(value->partyaddress, sizeof(value->partyaddress), comp);
+- if (res < 0)
+- return -1;
+- value->npi = PRI_NPI_UNKNOWN;
+- value->ton = PRI_TON_UNKNOWN;
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber */
+- res = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
+- if (res < 0)
+- return -1;
+- value->npi = PRI_NPI_E163_E164;
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] nsapEncodedNumber */
+- pri_message(pri, "!! NsapEncodedNumber isn't handled\n");
+- return -1;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] dataPartyNumber */
+- if(rose_number_digits_decode(pri, call, comp->data, comp->len, value))
+- return -1;
+- value->npi = PRI_NPI_X121 /* ??? */;
+- value->ton = PRI_TON_UNKNOWN /* ??? */;
+- pri_message(pri, "!! dataPartyNumber isn't handled\n");
+- return -1;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] telexPartyNumber */
+- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+- if (res < 0)
+- return -1;
+- value->npi = PRI_NPI_F69 /* ??? */;
+- value->ton = PRI_TON_UNKNOWN /* ??? */;
+- pri_message(pri, "!! telexPartyNumber isn't handled\n");
+- return -1;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */
+- res = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
+- if (res < 0)
+- return -1;
+- value->npi = PRI_NPI_PRIVATE;
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */
+- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+- if (res < 0)
+- return -1;
+- value->npi = PRI_NPI_NATIONAL;
+- value->ton = PRI_TON_NATIONAL;
+- break;
+- default:
+- pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type);
+- return -1;
++ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
++}
++
++/*!
++ * \internal
++ * \brief Encode the Q.SIG DivertingLegInformation2 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode diversion leg 2.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_diverting_leg_information2(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, q931_call *call)
++{
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
++
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
++
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_DivertingLegInformation2;
++ msg.invoke_id = get_invokeid(ctrl);
++
++ /* diversionCounter is the redirecting.count */
++ msg.args.qsig.DivertingLegInformation2.diversion_counter = call->redirecting.count;
++
++ msg.args.qsig.DivertingLegInformation2.diversion_reason =
++ redirectingreason_from_q931(ctrl, call->redirecting.reason);
++
++ /* divertingNr is the redirecting.from.number */
++ msg.args.qsig.DivertingLegInformation2.diverting_present = 1;
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.qsig.DivertingLegInformation2.diverting,
++ &call->redirecting.from.number);
++
++ /* redirectingName is the redirecting.from.name */
++ if (call->redirecting.from.name.valid) {
++ msg.args.qsig.DivertingLegInformation2.redirecting_name_present = 1;
++ q931_copy_name_to_rose(ctrl,
++ &msg.args.qsig.DivertingLegInformation2.redirecting_name,
++ &call->redirecting.from.name);
++ }
++
++ if (1 < call->redirecting.count) {
++ /* originalCalledNr is the redirecting.orig_called.number */
++ msg.args.qsig.DivertingLegInformation2.original_called_present = 1;
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.qsig.DivertingLegInformation2.original_called,
++ &call->redirecting.orig_called.number);
++
++ msg.args.qsig.DivertingLegInformation2.original_diversion_reason_present = 1;
++ if (call->redirecting.orig_called.number.valid) {
++ msg.args.qsig.DivertingLegInformation2.original_diversion_reason =
++ redirectingreason_from_q931(ctrl, call->redirecting.orig_reason);
++ } else {
++ msg.args.qsig.DivertingLegInformation2.original_diversion_reason =
++ QSIG_DIVERT_REASON_UNKNOWN;
+ }
+- ASN1_FIXUP_LEN(comp, res);
+- NEXT_COMPONENT(comp, i);
+- if(i < len)
+- pri_message(pri, "!! not all information is handled from Address component\n");
+- return res + 2;
++
++ /* originalCalledName is the redirecting.orig_called.name */
++ if (call->redirecting.orig_called.name.valid) {
++ msg.args.qsig.DivertingLegInformation2.original_called_name_present = 1;
++ q931_copy_name_to_rose(ctrl,
++ &msg.args.qsig.DivertingLegInformation2.original_called_name,
++ &call->redirecting.orig_called.name);
++ }
+ }
+- while (0);
+
+- return -1;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
+ }
+
+-static int rose_presented_number_unscreened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
++/*!
++ * \internal
++ * \brief Encode the ETSI DivertingLegInformation2 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode diversion leg 2.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_diverting_leg_information2(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, q931_call *call)
+ {
+- int i = 0;
+- int size = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = data;
++ struct rose_msg_invoke msg;
+
+- /* Fill in default values */
+- value->ton = PRI_TON_UNKNOWN;
+- value->npi = PRI_NPI_E163_E164;
+- value->pres = -1; /* Data is not available */
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
+- do {
+- GET_COMPONENT(comp, i, vdata, len);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_ETSI_DivertingLegInformation2;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- switch(comp->type) {
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] presentationAllowedNumber */
+- value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+- size = rose_address_decode(pri, call, comp->data, comp->len, value);
+- ASN1_FIXUP_LEN(comp, size);
+- return size + 2;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
+- if (comp->len != 0) { /* must be NULL */
+- pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
+- return -1;
+- }
+- value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+- return 2;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
+- if (comp->len != 0) { /* must be NULL */
+- pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
+- return -1;
+- }
+- value->pres = PRES_NUMBER_NOT_AVAILABLE;
+- return 2;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */
+- value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+- size = rose_address_decode(pri, call, comp->data, comp->len, value) + 2;
+- ASN1_FIXUP_LEN(comp, size);
+- return size + 2;
+- default:
+- pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type);
+- }
+- return -1;
++ /* diversionCounter is the redirecting.count */
++ msg.args.etsi.DivertingLegInformation2.diversion_counter = call->redirecting.count;
++
++ msg.args.etsi.DivertingLegInformation2.diversion_reason =
++ redirectingreason_from_q931(ctrl, call->redirecting.reason);
++
++ /* divertingNr is the redirecting.from.number */
++ msg.args.etsi.DivertingLegInformation2.diverting_present = 1;
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.etsi.DivertingLegInformation2.diverting,
++ &call->redirecting.from.number);
++
++ if (1 < call->redirecting.count) {
++ /* originalCalledNr is the redirecting.orig_called.number */
++ msg.args.etsi.DivertingLegInformation2.original_called_present = 1;
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.etsi.DivertingLegInformation2.original_called,
++ &call->redirecting.orig_called.number);
+ }
+- while (0);
+
+- return -1;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
+ }
+
+-static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
++/*!
++ * \internal
++ * \brief Encode and queue the DivertingLegInformation2 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode diversion leg 2.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int rose_diverting_leg_information2_encode(struct pri *ctrl, q931_call *call)
+ {
+- int i = 0;
+- int diversion_counter;
+- int diversion_reason;
+- char origcalledname[50] = "", redirectingname[50] = "";
+- struct addressingdataelements_presentednumberunscreened divertingnr;
+- struct addressingdataelements_presentednumberunscreened originalcallednr;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = sequence->data;
+- int res = 0;
+- memset(&divertingnr, 0, sizeof(divertingnr));
+- memset(&originalcallednr, 0, sizeof(originalcallednr));
++ unsigned char buffer[256];
++ unsigned char *end;
+
+- /* Data checks */
+- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
+- pri_message(pri, "Invalid DivertingLegInformation2Type argument\n");
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ end = enc_etsi_diverting_leg_information2(ctrl, buffer, buffer + sizeof(buffer),
++ call);
++ break;
++ case PRI_SWITCH_QSIG:
++ end = enc_qsig_diverting_leg_information2(ctrl, buffer, buffer + sizeof(buffer),
++ call);
++ break;
++ default:
+ return -1;
+ }
++ if (!end) {
++ return -1;
++ }
+
+- if (sequence->len == ASN1_LEN_INDEF) {
+- len -= 4; /* For the 2 extra characters at the end
+- * and two characters of header */
+- } else
+- len -= 2;
++ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
++}
+
+- do {
+- /* diversionCounter stuff */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do it diversionCounter is of type 0x%x\n");
+- ASN1_GET_INTEGER(comp, diversion_counter);
+- NEXT_COMPONENT(comp, i);
++/*!
++ * \internal
++ * \brief Encode the Q.SIG DivertingLegInformation3 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode diversion leg 3.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_diverting_leg_information3(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, q931_call *call)
++{
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
+
+- /* diversionReason stuff */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid diversionReason type 0x%X of ROSE divertingLegInformation2 component received\n");
+- ASN1_GET_INTEGER(comp, diversion_reason);
+- NEXT_COMPONENT(comp, i);
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
+- diversion_reason = redirectingreason_for_q931(pri, diversion_reason);
+-
+- if(pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter);
+- pri_message(NULL, "Length of message is %d\n", len);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_DivertingLegInformation3;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- for(; i < len; NEXT_COMPONENT(comp, i)) {
+- GET_COMPONENT(comp, i, vdata, len);
+- switch(comp->type) {
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0):
+- call->origredirectingreason = redirectingreason_for_q931(pri, comp->data[0]);
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " Received reason for original redirection %d\n", call->origredirectingreason);
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1):
+- res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr);
+- /* TODO: Fix indefinite length form hacks */
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
+- if (res < 0)
+- return -1;
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, " Received divertingNr '%s'\n", divertingnr.partyaddress);
+- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi);
+- }
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2):
+- res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr);
+- if (res < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, " Received originalcallednr '%s'\n", originalcallednr.partyaddress);
+- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi);
+- }
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3):
+- res = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname));
+- if (res < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " Received RedirectingName '%s'\n", redirectingname);
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4):
+- res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname));
+- if (res < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname);
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5):
+- pri_message(pri, "!! Ignoring DivertingLegInformation2 component 0x%X\n", comp->type);
+- break;
+- default:
+- if (comp->type == 0 && comp->len == 0) {
+- break; /* Found termination characters */
+- }
+- pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type);
+- return -1;
+- }
+- }
++ /* redirecting.to.number.presentation also indicates if name presentation is allowed */
++ if ((call->redirecting.to.number.presentation & PRI_PRES_RESTRICTION) == PRI_PRES_ALLOWED) {
++ msg.args.qsig.DivertingLegInformation3.presentation_allowed_indicator = 1; /* TRUE */
+
+- if (divertingnr.pres >= 0) {
+- call->redirectingplan = divertingnr.npi;
+- call->redirectingpres = divertingnr.pres;
+- call->redirectingreason = diversion_reason;
+- libpri_copy_string(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum));
+- pri_message(pri, " Received redirectingnum '%s' (%d)\n", call->redirectingnum, (int)call->redirectingnum[0]);
++ /* redirectionName is the redirecting.to.name */
++ if (call->redirecting.to.name.valid) {
++ msg.args.qsig.DivertingLegInformation3.redirection_name_present = 1;
++ q931_copy_name_to_rose(ctrl,
++ &msg.args.qsig.DivertingLegInformation3.redirection_name,
++ &call->redirecting.to.name);
+ }
+- if (originalcallednr.pres >= 0) {
+- call->origcalledplan = originalcallednr.npi;
+- call->origcalledpres = originalcallednr.pres;
+- libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum));
+- pri_message(pri, " Received origcallednum '%s' (%d)\n", call->origcallednum, (int)call->origcallednum[0]);
+- }
+- libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname));
+- libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname));
+- return 0;
+ }
+- while (0);
+
+- return -1;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
+ }
+-
+-static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call)
++
++/*!
++ * \internal
++ * \brief Encode the ETSI DivertingLegInformation3 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode diversion leg 3.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_diverting_leg_information3(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, q931_call *call)
+ {
+- int i = 0, j, compsp = 0;
+- struct rose_component *comp, *compstk[10];
+- unsigned char buffer[256];
+- int len = 253;
+-
+-#if 0 /* This is not required by specifications */
+- if (!strlen(call->callername)) {
+- return -1;
++ struct rose_msg_invoke msg;
++
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
+ }
+-#endif
+
+- buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+- i++;
+- /* Interpretation component */
+- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* Discard unrecognized invokes */);
+-
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+-
+- ASN1_PUSH(compstk, compsp, comp);
+- /* Invoke component contents */
+- /* Invoke ID */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
+- /* Operation Tag */
+-
+- /* ROSE operationId component */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION2);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_ETSI_DivertingLegInformation3;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- /* ROSE ARGUMENT component */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* ROSE DivertingLegInformation2.diversionCounter component */
+- /* Always is 1 because other isn't available in the current design */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
+-
+- /* ROSE DivertingLegInformation2.diversionReason component */
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->redirectingreason));
+-
+- /* ROSE DivertingLegInformation2.divertingNr component */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+-
+- ASN1_PUSH(compstk, compsp, comp);
+- /* Redirecting information always not screened */
+-
+- switch(call->redirectingpres) {
+- case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+- case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+- if (call->redirectingnum && strlen(call->redirectingnum)) {
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* NPI of redirected number is not supported in the current design */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
+- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
+- if (j < 0)
+- return -1;
+-
+- i += j;
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- break;
+- }
+- /* fall through */
+- case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+- case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
+- break;
+- /* Don't know how to handle this */
+- case PRES_ALLOWED_NETWORK_NUMBER:
+- case PRES_PROHIB_NETWORK_NUMBER:
+- case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+- case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
+- break;
+- default:
+- pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
+- case PRES_NUMBER_NOT_AVAILABLE:
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
+- break;
++ if ((call->redirecting.to.number.presentation & PRI_PRES_RESTRICTION) == PRI_PRES_ALLOWED) {
++ msg.args.etsi.DivertingLegInformation3.presentation_allowed_indicator = 1; /* TRUE */
+ }
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+
+- /* ROSE DivertingLegInformation2.originalCalledNr component */
+- /* This information isn't supported by current design - duplicate divertingNr */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* Redirecting information always not screened */
+- switch(call->redirectingpres) {
+- case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+- case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+- if (call->redirectingnum && strlen(call->redirectingnum)) {
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
+-
+- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
+- if (j < 0)
+- return -1;
+-
+- i += j;
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- break;
+- }
+- /* fall through */
+- case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+- case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
+- break;
+- /* Don't know how to handle this */
+- case PRES_ALLOWED_NETWORK_NUMBER:
+- case PRES_PROHIB_NETWORK_NUMBER:
+- case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+- case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
+- break;
+- default:
+- pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
+- case PRES_NUMBER_NOT_AVAILABLE:
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
+- break;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode and queue the DivertingLegInformation3 invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode diversion leg 3.
++ * \param messagetype Q.931 message type to add facility ie to.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int rose_diverting_leg_information3_encode(struct pri *ctrl, q931_call *call,
++ int messagetype)
++{
++ unsigned char buffer[256];
++ unsigned char *end;
++
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ end = enc_etsi_diverting_leg_information3(ctrl, buffer, buffer + sizeof(buffer),
++ call);
++ break;
++ case PRI_SWITCH_QSIG:
++ end = enc_qsig_diverting_leg_information3(ctrl, buffer, buffer + sizeof(buffer),
++ call);
++ break;
++ default:
++ return -1;
+ }
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+-
+- /* Fix length of stacked components */
+- while(compsp > 0) {
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ if (!end) {
++ return -1;
+ }
+-
+- if (pri_call_apdu_queue(call, Q931_SETUP, buffer, i, NULL, NULL))
+- return -1;
+-
+- return 0;
++
++ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
+ }
+
+-/* Send the rltThirdParty: Invoke */
+-int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
++/*!
++ * \internal
++ * \brief Encode the rltThirdParty invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param callwithid Call-ID information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_dms100_rlt_initiate_transfer(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const q931_call *callwithid)
+ {
+- int i = 0;
++ struct rose_msg_invoke msg;
++
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
++
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_DMS100_RLT_ThirdParty;
++ msg.invoke_id = ROSE_DMS100_RLT_THIRD_PARTY;
++ msg.args.dms100.RLT_ThirdParty.call_id = callwithid->rlt_call_id & 0xFFFFFF;
++ msg.args.dms100.RLT_ThirdParty.reason = 0; /* unused, set to 129 */
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
++}
++
++/*!
++ * \brief Send the rltThirdParty: Invoke.
++ *
++ * \note For PRI_SWITCH_DMS100 only.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param c1 Q.931 call leg 1
++ * \param c2 Q.931 call leg 2
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int rlt_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
++{
+ unsigned char buffer[256];
+- struct rose_component *comp = NULL, *compstk[10];
+- const unsigned char rlt_3rd_pty = RLT_THIRD_PARTY;
+- q931_call *callwithid = NULL, *apdubearer = NULL;
+- int compsp = 0;
++ unsigned char *end;
++ q931_call *apdubearer;
++ q931_call *callwithid;
+
+ if (c2->transferable) {
+ apdubearer = c1;
+@@ -906,279 +1374,415 @@
+ } else if (c1->transferable) {
+ apdubearer = c2;
+ callwithid = c1;
+- } else
++ } else {
+ return -1;
++ }
+
+- buffer[i++] = (Q932_PROTOCOL_ROSE);
+- buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
++ end =
++ enc_dms100_rlt_initiate_transfer(ctrl, buffer, buffer + sizeof(buffer),
++ callwithid);
++ if (!end) {
++ return -1;
++ }
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+-
+- /* Invoke ID is set to the operation ID */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
+-
+- /* Operation Tag */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
+-
+- /* Additional RLT invoke info - Octet 12 */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+-
+- ASN1_ADD_WORDCOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, callwithid->rlt_call_id & 0xFFFFFF); /* Length is 3 octets */
+- /* Reason for redirect - unused, set to 129 */
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i, 0);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+-
+- if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, i, NULL, NULL))
++ if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, end - buffer, NULL)) {
+ return -1;
++ }
+
+ if (q931_facility(apdubearer->pri, apdubearer)) {
+- pri_message(pri, "Could not schedule facility message for call %d\n", apdubearer->cr);
++ pri_message(ctrl, "Could not schedule facility message for call %d\n",
++ apdubearer->cr);
+ return -1;
+ }
+ return 0;
+ }
+
+-static int add_dms100_transfer_ability_apdu(struct pri *pri, q931_call *c)
++/*!
++ * \internal
++ * \brief Encode the rltOperationInd invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_dms100_rlt_transfer_ability(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end)
+ {
+- int i = 0;
+- unsigned char buffer[256];
+- struct rose_component *comp = NULL, *compstk[10];
+- const unsigned char rlt_op_ind = RLT_OPERATION_IND;
+- int compsp = 0;
++ struct rose_msg_invoke msg;
+
+- buffer[i++] = (Q932_PROTOCOL_ROSE); /* Note to self: DON'T set the EXT bit */
+- buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_DMS100_RLT_OperationInd;
++ msg.invoke_id = ROSE_DMS100_RLT_OPERATION_IND;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- /* Invoke ID is set to the operation ID */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
+-
+- /* Operation Tag - basically the same as the invoke ID tag */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+-
+- if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
+- return -1;
+- else
+- return 0;
++ return pos;
+ }
+
+-/* Sending callername information functions */
+-static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
++/*!
++ * \internal
++ * \brief Send the rltOperationInd: Invoke.
++ *
++ * \note For PRI_SWITCH_DMS100 only.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Q.931 call leg
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int add_dms100_transfer_ability_apdu(struct pri *ctrl, q931_call *call)
+ {
+- int res = 0;
+- int i = 0;
+ unsigned char buffer[256];
+- unsigned char namelen = 0;
+- struct rose_component *comp = NULL, *compstk[10];
+- int compsp = 0;
+- int mymessage = 0;
+- static unsigned char op_tag[] = {
+- 0x2a, /* informationFollowing 42 */
+- 0x86,
+- 0x48,
+- 0xce,
+- 0x15,
+- 0x00,
+- 0x04
+- };
+-
+- if (!strlen(c->callername)) {
++ unsigned char *end;
++
++ end = enc_dms100_rlt_transfer_ability(ctrl, buffer, buffer + sizeof(buffer));
++ if (!end) {
+ return -1;
+ }
+
+- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+- /* Interpretation component */
++ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
++}
+
+- if (pri->switchtype == PRI_SWITCH_QSIG) {
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++/*!
++ * \internal
++ * \brief Encode the NI2 InformationFollowing invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_ni2_information_following(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end)
++{
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
++
++ memset(&header, 0, sizeof(header));
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
+ }
+
+- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_NI2_InformationFollowing;
++ msg.invoke_id = get_invokeid(ctrl);
++ msg.args.ni2.InformationFollowing.value = 0;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* Invoke ID */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
++ return pos;
++}
+
+- /* Operation Tag */
+- res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
+- if (res < 0)
+- return -1;
+- i += res;
++/*!
++ * \internal
++ * \brief Encode the Q.SIG CallingName invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param name Name data which to encode name.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_calling_name(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct q931_party_name *name)
++{
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
+
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+-
+- if (!cpe) {
+- if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
+- return -1;
++ memset(&header, 0, sizeof(header));
++ if (ctrl->switchtype == PRI_SWITCH_QSIG) {
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
+ }
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_CallingName;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- /* Now the APDU that contains the information that needs sent.
+- * We can reuse the buffer since the queue function doesn't
+- * need it. */
++ /* CallingName */
++ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CallingName.name, name);
+
+- i = 0;
+- namelen = strlen(c->callername);
+- if (namelen > 50) {
+- namelen = 50; /* truncate the name */
+- }
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+- /* Interpretation component */
++ return pos;
++}
+
+- if (pri->switchtype == PRI_SWITCH_QSIG) {
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++/*!
++ * \internal
++ * \brief Send caller name information.
++ *
++ * \note For PRI_SWITCH_NI2 and PRI_SWITCH_QSIG.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode name.
++ * \param cpe TRUE if we are the CPE side.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int add_callername_facility_ies(struct pri *ctrl, q931_call *call, int cpe)
++{
++ unsigned char buffer[256];
++ unsigned char *end;
++ int mymessage;
++
++ if (!call->local_id.name.valid) {
++ return 0;
+ }
+
+- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
++ if (ctrl->switchtype == PRI_SWITCH_NI2 && !cpe) {
++ end = enc_ni2_information_following(ctrl, buffer, buffer + sizeof(buffer));
++ if (!end) {
++ return -1;
++ }
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ if (pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL)) {
++ return -1;
++ }
+
+- /* Invoke ID */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
++ /*
++ * We can reuse the buffer since the queue function doesn't
++ * need it.
++ */
++ }
+
+- /* Operation ID: Calling name */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNID_CALLINGNAME);
+-
+- res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, 50, c->callername, namelen);
+- if (res < 0)
++ /* CallingName is the local_id.name */
++ end = enc_qsig_calling_name(ctrl, buffer, buffer + sizeof(buffer),
++ &call->local_id.name);
++ if (!end) {
+ return -1;
+- i += res;
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ }
+
+- if (cpe)
++ if (cpe) {
+ mymessage = Q931_SETUP;
+- else
++ } else {
+ mymessage = Q931_FACILITY;
++ }
+
+- if (pri_call_apdu_queue(c, mymessage, buffer, i, NULL, NULL))
+- return -1;
+-
+- return 0;
++ return pri_call_apdu_queue(call, mymessage, buffer, end - buffer, NULL);
+ }
+ /* End Callername */
+
+ /* MWI related encode and decode functions */
+-static void mwi_activate_encode_cb(void *data)
++
++/*!
++ * \internal
++ * \brief Encode the Q.SIG MWIActivate invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param req Served user setup request information.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_mwi_activate_message(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, struct pri_sr *req)
+ {
+- return;
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
++
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
++
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_MWIActivate;
++ msg.invoke_id = get_invokeid(ctrl);
++
++ /* The called.number is the served user */
++ q931_copy_number_to_rose(ctrl, &msg.args.qsig.MWIActivate.served_user_number,
++ &req->called.number);
++ /*
++ * For now, we will just force the numbering plan to unknown to preserve
++ * the original behaviour.
++ */
++ msg.args.qsig.MWIActivate.served_user_number.plan = 0; /* unknown */
++
++ msg.args.qsig.MWIActivate.basic_service = 1; /* speech */
++
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
+ }
+
+-int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate)
++/*!
++ * \internal
++ * \brief Encode the Q.SIG MWIDeactivate invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param req Served user setup request information.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_mwi_deactivate_message(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, struct pri_sr *req)
+ {
+- int i = 0;
+- unsigned char buffer[255] = "";
+- int destlen = strlen(req->called);
+- struct rose_component *comp = NULL, *compstk[10];
+- int compsp = 0;
+- int res;
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
+
+- if (destlen <= 0) {
+- return -1;
+- } else if (destlen > 20)
+- destlen = 20; /* Destination number cannot be greater then 20 digits */
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
+- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+- /* Interpretation component */
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_MWIDeactivate;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ /* The called.number is the served user */
++ q931_copy_number_to_rose(ctrl, &msg.args.qsig.MWIDeactivate.served_user_number,
++ &req->called.number);
++ /*
++ * For now, we will just force the numbering plan to unknown to preserve
++ * the original behaviour.
++ */
++ msg.args.qsig.MWIDeactivate.served_user_number.plan = 0; /* unknown */
+
+- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
++ msg.args.qsig.MWIDeactivate.basic_service = 1; /* speech */
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
++ return pos;
++}
+
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, (activate) ? SS_MWI_ACTIVATE : SS_MWI_DEACTIVATE);
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* PartyNumber */
+- res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, destlen, req->called, destlen);
+-
+- if (res < 0)
++/*!
++ * \brief Encode and queue the Q.SIG MWIActivate/MWIDeactivate invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg to queue message.
++ * \param req Served user setup request information.
++ * \param activate Nonzero to do the activate message.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int activate)
++{
++ unsigned char buffer[255];
++ unsigned char *end;
++
++ if (!req->called.number.valid || !req->called.number.str[0]) {
+ return -1;
+- i += res;
++ }
+
+- /* Enumeration: basicService */
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1 /* contents: Voice */);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ if (activate) {
++ end = enc_qsig_mwi_activate_message(ctrl, buffer, buffer + sizeof(buffer), req);
++ } else {
++ end =
++ enc_qsig_mwi_deactivate_message(ctrl, buffer, buffer + sizeof(buffer), req);
++ }
++ if (!end) {
++ return -1;
++ }
+
+- return pri_call_apdu_queue(call, Q931_SETUP, buffer, i, mwi_activate_encode_cb, NULL);
++ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
+ }
+ /* End MWI */
+
+ /* EECT functions */
+-int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
++/*!
++ * \internal
++ * \brief Encode the NI2 InitiateTransfer invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode transfer information.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_ni2_initiate_transfer(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call)
+ {
+- int i = 0;
+- int res = 0;
+- unsigned char buffer[255] = "";
+- short call_reference = c2->cr ^ 0x8000; /* Let's do the trickery to make sure the flag is correct */
+- struct rose_component *comp = NULL, *compstk[10];
+- int compsp = 0;
+- static unsigned char op_tag[] = {
+- 0x2A,
+- 0x86,
+- 0x48,
+- 0xCE,
+- 0x15,
+- 0x00,
+- 0x08,
+- };
++ struct rose_msg_invoke msg;
+
+- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_NI2_InitiateTransfer;
++ msg.invoke_id = get_invokeid(ctrl);
++ /* Let's do the trickery to make sure the flag is correct */
++ msg.args.ni2.InitiateTransfer.call_reference = call->cr ^ 0x8000;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
++ return pos;
++}
+
+- res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
+- if (res < 0)
++/*!
++ * \brief Start a 2BCT
++ *
++ * \note Called for PRI_SWITCH_NI2, PRI_SWITCH_LUCENT5E, and PRI_SWITCH_ATT4ESS
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param c1 Q.931 call leg 1
++ * \param c2 Q.931 call leg 2
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int eect_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
++{
++ unsigned char buffer[255];
++ unsigned char *end;
++
++ end = enc_ni2_initiate_transfer(ctrl, buffer, buffer + sizeof(buffer), c2);
++ if (!end) {
+ return -1;
+- i += res;
++ }
+
+- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+-
+- res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
+- if (res) {
+- pri_message(pri, "Could not queue APDU in facility message\n");
++ if (pri_call_apdu_queue(c1, Q931_FACILITY, buffer, end - buffer, NULL)) {
++ pri_message(ctrl, "Could not queue APDU in facility message\n");
+ return -1;
+ }
+
+ /* Remember that if we queue a facility IE for a facility message we
+ * have to explicitly send the facility message ourselves */
+
+- res = q931_facility(c1->pri, c1);
+- if (res) {
+- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
++ if (q931_facility(c1->pri, c1)) {
++ pri_message(ctrl, "Could not schedule facility message for call %d\n", c1->cr);
+ return -1;
+ }
+
+@@ -1187,1494 +1791,2316 @@
+ /* End EECT */
+
+ /* QSIG CF CallRerouting */
+-int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason)
++/*!
++ * \internal
++ * \brief Encode the Q.SIG CallRerouting invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Q.931 call leg.
++ * \param calling Call rerouting/deflecting updated caller data.
++ * \param deflection Call rerouting/deflecting redirection data.
++ * \param subscription_option Diverting user subscription option to specify if caller is notified.
++ *
++ * \note
++ * deflection->to is the new called number and must always be present.
++ * \note
++ * subscription option:
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_call_rerouting(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call, const struct q931_party_id *calling,
++ const struct q931_party_redirecting *deflection, int subscription_option)
+ {
+-/*CallRerouting ::= OPERATION
+- -- Sent from the Served User PINX to the Rerouting PINX
+- ARGUMENT SEQUENCE
+- { reroutingReason DiversionReason,
+- originalReroutingReason [0] IMPLICIT DiversionReason OPTIONAL,
+- calledAddress Address,
+- diversionCounter INTEGER (1..15),
+- pSS1InfoElement PSS1InformationElement,
+- -- The basic call information elements Bearer capability, High layer compatibility, Low
+- -- layer compatibity, Progress indicator and Party category can be embedded in the
+- -- pSS1InfoElement in accordance with 6.5.3.1.5
+- lastReroutingNr [1] PresentedNumberUnscreened,
+- subscriptionOption [2] IMPLICIT SubscriptionOption,
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
++ unsigned char *q931ie_pos;
+
+- callingPartySubaddress [3] PartySubaddress OPTIONAL,
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 2; /* rejectAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
+- callingNumber [4] PresentedNumberScreened,
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_CallRerouting;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- callingName [5] Name OPTIONAL,
+- originalCalledNr [6] PresentedNumberUnscreened OPTIONAL,
+- redirectingName [7] Name OPTIONAL,
+- originalCalledName [8] Name OPTIONAL,
+- extension CHOICE {
+- [9] IMPLICIT Extension ,
+- [10] IMPLICIT SEQUENCE OF Extension } OPTIONAL }
+-*/
++ msg.args.qsig.CallRerouting.rerouting_reason =
++ redirectingreason_from_q931(ctrl, deflection->reason);
+
+- int i = 0, j;
+- int res = 0;
+- unsigned char buffer[255] = "";
+- int len = 253;
+- struct rose_component *comp = NULL, *compstk[10];
+- int compsp = 0;
+- static unsigned char op_tag[] = {
+- 0x13,
+- };
++ /* calledAddress is the passed in deflection->to address */
++ q931_copy_address_to_rose(ctrl, &msg.args.qsig.CallRerouting.called, &deflection->to);
+
+- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+- /* Interpretation component */
++ msg.args.qsig.CallRerouting.diversion_counter = deflection->count;
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ /* pSS1InfoElement */
++ q931ie_pos = msg.args.qsig.CallRerouting.q931ie_contents;
++ *q931ie_pos++ = 0x04; /* Bearer Capability IE */
++ *q931ie_pos++ = 0x03; /* len */
++ *q931ie_pos++ = 0x80 | call->transcapability; /* Rxed transfer capability. */
++ *q931ie_pos++ = 0x90; /* circuit mode, 64kbit/s */
++ *q931ie_pos++ = 0xa3; /* level1 protocol, a-law */
++ *q931ie_pos++ = 0x95; /* locking shift to codeset 5 (national use) */
++ *q931ie_pos++ = 0x32; /* Unknown ie */
++ *q931ie_pos++ = 0x01; /* Unknown ie len */
++ *q931ie_pos++ = 0x81; /* Unknown ie body */
++ msg.args.qsig.CallRerouting.q931ie.length = q931ie_pos
++ - msg.args.qsig.CallRerouting.q931ie_contents;
+
+- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 2); /* reject - to get feedback from QSIG switch */
++ /* lastReroutingNr is the passed in deflection->from.number */
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.qsig.CallRerouting.last_rerouting, &deflection->from.number);
+
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ msg.args.qsig.CallRerouting.subscription_option = subscription_option;
+
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
++ /* callingNumber is the passed in calling->number */
++ q931_copy_presented_number_screened_to_rose(ctrl,
++ &msg.args.qsig.CallRerouting.calling, &calling->number);
+
+- res = asn1_string_encode(ASN1_INTEGER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
+- if (res < 0)
+- return -1;
+- i += res;
++ /* callingPartySubaddress is the passed in calling->subaddress if valid */
++ q931_copy_subaddress_to_rose(ctrl, &msg.args.qsig.CallRerouting.calling_subaddress,
++ &calling->subaddress);
+
+- /* call rerouting argument */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ /* callingName is the passed in calling->name if valid */
++ if (calling->name.valid) {
++ msg.args.qsig.CallRerouting.calling_name_present = 1;
++ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CallRerouting.calling_name,
++ &calling->name);
++ }
+
+- /* reroutingReason DiversionReason */
++ if (1 < deflection->count) {
++ /* originalCalledNr is the deflection->orig_called.number */
++ msg.args.qsig.CallRerouting.original_called_present = 1;
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.qsig.CallRerouting.original_called,
++ &deflection->orig_called.number);
+
+- if (reason) {
+- if (!strcasecmp(reason, "cfu"))
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1); /* cfu */
+- else if (!strcasecmp(reason, "cfb"))
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 2); /* cfb */
+- else if (!strcasecmp(reason, "cfnr"))
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 3); /* cfnr */
+- } else {
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0); /* unknown */
++ msg.args.qsig.CallRerouting.original_rerouting_reason_present = 1;
++ if (deflection->orig_called.number.valid) {
++ msg.args.qsig.CallRerouting.original_rerouting_reason =
++ redirectingreason_from_q931(ctrl, deflection->orig_reason);
++ } else {
++ msg.args.qsig.CallRerouting.original_rerouting_reason =
++ QSIG_DIVERT_REASON_UNKNOWN;
++ }
++
++ /* originalCalledName is the deflection->orig_called.name */
++ if (deflection->orig_called.name.valid) {
++ msg.args.qsig.CallRerouting.original_called_name_present = 1;
++ q931_copy_name_to_rose(ctrl,
++ &msg.args.qsig.CallRerouting.original_called_name,
++ &deflection->orig_called.name);
++ }
+ }
+
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- /* calledAddress Address */
+- /* explicit sequence tag for Address */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* implicit choice public party number tag */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* type of public party number = unknown */
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
+- /* NumberDigits of public party number */
+- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, (char*)dest, strlen(dest));
+- if (j < 0)
+- return -1;
++ return pos;
++}
+
+- i += j;
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++/*!
++ * \internal
++ * \brief Encode the ETSI CallRerouting invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Q.931 call leg.
++ * \param calling Call rerouting/deflecting updated caller data.
++ * \param deflection Call rerouting/deflecting redirection data.
++ * \param subscription_option Diverting user subscription option to specify if caller is notified.
++ *
++ * \note
++ * deflection->to is the new called number and must always be present.
++ * \note
++ * subscription option:
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_call_rerouting(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call, const struct q931_party_id *calling,
++ const struct q931_party_redirecting *deflection, int subscription_option)
++{
++ struct rose_msg_invoke msg;
++ unsigned char *q931ie_pos;
+
+- /* diversionCounter INTEGER (1..15) */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
+- /* pSS1InfoElement */
+- ASN1_ADD_SIMPLE(comp, (ASN1_APPLICATION | ASN1_TAG_0 ), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- buffer[i++] = (0x04); /* Bearer Capability IE */
+- buffer[i++] = (0x03); /* len */
+- buffer[i++] = (0x80); /* ETSI Standard, Speech */
+- buffer[i++] = (0x90); /* circuit mode, 64kbit/s */
+- buffer[i++] = (0xa3); /* level1 protocol, a-law */
+- buffer[i++] = (0x95); /* locking shift to codeset 5 (national use) */
+- buffer[i++] = (0x32); /* Unknown ie */
+- buffer[i++] = (0x01); /* Unknown ie len */
+- buffer[i++] = (0x81); /* Unknown ie body */
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_ETSI_CallRerouting;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- /* lastReroutingNr [1]*/
+- /* implicit optional lastReroutingNr tag */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ msg.args.etsi.CallRerouting.rerouting_reason =
++ redirectingreason_from_q931(ctrl, deflection->reason);
+
+- /* implicit choice presented number unscreened tag */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ /* calledAddress is the passed in deflection->to address */
++ q931_copy_address_to_rose(ctrl, &msg.args.etsi.CallRerouting.called_address,
++ &deflection->to);
+
+- /* implicit choice public party number tag */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* type of public party number = unknown */
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
+- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, original?(char*)original:c->callednum, original?strlen(original):strlen(c->callednum));
+- if (j < 0)
+- return -1;
++ msg.args.etsi.CallRerouting.rerouting_counter = deflection->count;
+
+- i += j;
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ /* q931InfoElement */
++ q931ie_pos = msg.args.etsi.CallRerouting.q931ie_contents;
++ *q931ie_pos++ = 0x04; /* Bearer Capability IE */
++ *q931ie_pos++ = 0x03; /* len */
++ *q931ie_pos++ = 0x80 | call->transcapability; /* Rxed transfer capability. */
++ *q931ie_pos++ = 0x90; /* circuit mode, 64kbit/s */
++ *q931ie_pos++ = 0xa3; /* level1 protocol, a-law */
++ msg.args.etsi.CallRerouting.q931ie.length = q931ie_pos
++ - msg.args.etsi.CallRerouting.q931ie_contents;
+
+- /* subscriptionOption [2]*/
+- /* implicit optional lastReroutingNr tag */
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* noNotification */
++ /* lastReroutingNr is the passed in deflection->from.number */
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.etsi.CallRerouting.last_rerouting, &deflection->from.number);
+
+- /* callingNumber [4]*/
+- /* implicit optional callingNumber tag */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ msg.args.etsi.CallRerouting.subscription_option = subscription_option;
+
+- /* implicit choice presented number screened tag */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ /* callingPartySubaddress is the passed in calling->subaddress if valid */
++ q931_copy_subaddress_to_rose(ctrl, &msg.args.etsi.CallRerouting.calling_subaddress,
++ &calling->subaddress);
+
+- /* implicit choice presentationAllowedAddress tag */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- /* type of public party number = subscriber number */
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 4);
+- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, c->callernum, strlen(c->callernum));
+- if (j < 0)
+- return -1;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- i += j;
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ return pos;
++}
+
+- /* Screeening Indicator network provided */
+- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 3);
++/*!
++ * \internal
++ * \brief Encode the ETSI CallDeflection invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Q.931 call leg.
++ * \param deflection Call deflection address.
++ *
++ * \note
++ * deflection is the new called number and must always be present.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_call_deflection(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call, const struct q931_party_id *deflection)
++{
++ struct rose_msg_invoke msg;
+
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
+- /**/
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_ETSI_CallDeflection;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
++ /* deflectionAddress is the passed in deflection->to address */
++ q931_copy_address_to_rose(ctrl, &msg.args.etsi.CallDeflection.deflection,
++ deflection);
+
+- res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
+- if (res) {
+- pri_message(pri, "Could not queue ADPU in facility message\n");
++ msg.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present = 1;
++ switch (deflection->number.presentation & PRI_PRES_RESTRICTION) {
++ case PRI_PRES_ALLOWED:
++ msg.args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user = 1;
++ break;
++ default:
++ case PRI_PRES_UNAVAILABLE:
++ case PRI_PRES_RESTRICTED:
++ break;
++ }
++
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode and queue the CallRerouting/CallDeflection message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg.
++ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
++ * \param deflection Call rerouting/deflecting redirection data.
++ * \param subscription_option Diverting user subscription option to specify if caller is notified.
++ *
++ * \note
++ * deflection->to is the new called number and must always be present.
++ * \note
++ * subscription option:
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int rose_reroute_request_encode(struct pri *ctrl, q931_call *call,
++ const struct q931_party_id *caller, const struct q931_party_redirecting *deflection,
++ int subscription_option)
++{
++ unsigned char buffer[256];
++ unsigned char *end;
++
++ if (!caller) {
++ /*
++ * We are deflecting an incoming call back to the network.
++ * Therefore, the Caller-ID is the remote party.
++ */
++ caller = &call->remote_id;
++ }
++
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ if (q931_is_ptmp(ctrl)) {
++ end =
++ enc_etsi_call_deflection(ctrl, buffer, buffer + sizeof(buffer), call,
++ &deflection->to);
++ } else {
++ end =
++ enc_etsi_call_rerouting(ctrl, buffer, buffer + sizeof(buffer), call,
++ caller, deflection, subscription_option);
++ }
++ break;
++ case PRI_SWITCH_QSIG:
++ end =
++ enc_qsig_call_rerouting(ctrl, buffer, buffer + sizeof(buffer), call, caller,
++ deflection, subscription_option);
++ break;
++ default:
+ return -1;
+ }
++ if (!end) {
++ return -1;
++ }
+
+- /* Remember that if we queue a facility IE for a facility message we
+- * have to explicitly send the facility message ourselves */
++ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
++}
+
+- res = q931_facility(c->pri, c);
+- if (res) {
+- pri_message(pri, "Could not schedule facility message for call %d\n", c->cr);
++/*!
++ * \brief Send the CallRerouting/CallDeflection message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg.
++ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
++ * \param deflection Call rerouting/deflecting redirection data.
++ * \param subscription_option Diverting user subscription option to specify if caller is notified.
++ *
++ * \note
++ * deflection->to is the new called number and must always be present.
++ * \note
++ * subscription option:
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int send_reroute_request(struct pri *ctrl, q931_call *call,
++ const struct q931_party_id *caller, const struct q931_party_redirecting *deflection,
++ int subscription_option)
++{
++ if (!deflection->to.number.str[0]) {
++ /* Must have a deflect to number. That is the point of deflection. */
+ return -1;
+ }
++ if (rose_reroute_request_encode(ctrl, call, caller, deflection, subscription_option)
++ || q931_facility(ctrl, call)) {
++ pri_message(ctrl,
++ "Could not schedule facility message for CallRerouting/CallDeflection message.\n");
++ return -1;
++ }
+
+ return 0;
+ }
++
++/*!
++ * \brief Send the Q.SIG CallRerouting invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Q.931 call leg.
++ * \param dest Destination number.
++ * \param original Original called number.
++ * \param reason Rerouting reason: cfu, cfb, cfnr
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int qsig_cf_callrerouting(struct pri *ctrl, q931_call *call, const char *dest,
++ const char *original, const char *reason)
++{
++ struct q931_party_redirecting reroute;
++
++ q931_party_redirecting_init(&reroute);
++
++ /* Rerouting to the dest number. */
++ reroute.to.number.valid = 1;
++ reroute.to.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
++ reroute.to.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ libpri_copy_string(reroute.to.number.str, dest, sizeof(reroute.to.number.str));
++
++ /* Rerouting from the original number. */
++ if (original) {
++ reroute.from.number.valid = 1;
++ reroute.from.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
++ libpri_copy_string(reroute.from.number.str, original, sizeof(reroute.from.number.str));
++ } else {
++ q931_party_address_to_id(&reroute.from, &call->called);
++ }
++ reroute.from.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++
++ /* Decode the rerouting reason. */
++ reroute.reason = PRI_REDIR_UNKNOWN;
++ if (!reason) {
++ /* No reason for rerouting given. */
++ } else if (!strcasecmp(reason, "cfu")) {
++ reroute.reason = PRI_REDIR_UNCONDITIONAL;
++ } else if (!strcasecmp(reason, "cfb")) {
++ reroute.reason = PRI_REDIR_FORWARD_ON_BUSY;
++ } else if (!strcasecmp(reason, "cfnr")) {
++ reroute.reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
++ }
++
++ reroute.count = (call->redirecting.count < PRI_MAX_REDIRECTS)
++ ? call->redirecting.count + 1 : PRI_MAX_REDIRECTS;
++
++ if (!call->redirecting.orig_called.number.valid) {
++ /*
++ * Since we do not already have an originally called party, we
++ * must either be the first redirected to party or this call
++ * has not been redirected before.
++ *
++ * Preserve who redirected to us as the originally called party.
++ */
++ reroute.orig_called = call->redirecting.from;
++ reroute.orig_reason = call->redirecting.reason;
++ } else {
++ reroute.orig_called = call->redirecting.orig_called;
++ reroute.orig_reason = call->redirecting.orig_reason;
++ }
++
++ return send_reroute_request(ctrl, call, NULL, &reroute, 0 /* noNotification */);
++}
+ /* End QSIG CC-CallRerouting */
+
+-static int anfpr_pathreplacement_respond(struct pri *pri, q931_call *call, q931_ie *ie)
++/*
++ * From Mantis issue 7778 description: (ETS 300 258, ISO 13863)
++ * After both legs of the call are setup and Asterisk has a successful "tromboned" or bridged call ...
++ * Asterisk sees both 'B' channels (from trombone) are on same PRI/technology and initiates "Path Replacement" events
++ * a. Asterisk sends "Transfer Complete" messages to both call legs
++ * b. QSIG Switch sends "PathReplacement" message on one of the legs (random 1-10sec timer expires - 1st leg to send is it!)
++ * c. Asterisk rebroadcasts "PathReplacement" message to other call leg
++ * d. QSIG Switch sends "Disconnect" message on one of the legs (same random timer sequence as above)
++ * e. Asterisk rebroadcasts "Disconnect" message to other call leg
++ * f. QSIG Switch disconnects Asterisk call legs - callers are now within QSIG switch
++ *
++ * Just need to resend the message to the other tromboned leg of the call.
++ */
++static int anfpr_pathreplacement_respond(struct pri *ctrl, q931_call *call, q931_ie *ie)
+ {
+ int res;
+-
+- res = pri_call_apdu_queue_cleanup(call->bridged_call);
+- if (res) {
+- pri_message(pri, "Could not Clear queue ADPU\n");
+- return -1;
+- }
+-
++
++ pri_call_apdu_queue_cleanup(call->bridged_call);
++
+ /* Send message */
+- res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, NULL, NULL);
++ res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, NULL);
+ if (res) {
+- pri_message(pri, "Could not queue ADPU in facility message\n");
+- return -1;
++ pri_message(ctrl, "Could not queue ADPU in facility message\n");
++ return -1;
+ }
+-
++
+ /* Remember that if we queue a facility IE for a facility message we
+ * have to explicitly send the facility message ourselves */
+-
++
+ res = q931_facility(call->bridged_call->pri, call->bridged_call);
+ if (res) {
+- pri_message(pri, "Could not schedule facility message for call %d\n", call->bridged_call->cr);
++ pri_message(ctrl, "Could not schedule facility message for call %d\n",
++ call->bridged_call->cr);
+ return -1;
+ }
+
+ return 0;
+ }
++
+ /* AFN-PR */
+-int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
++/*!
++ * \brief Start a Q.SIG path replacement.
++ *
++ * \note Called for PRI_SWITCH_QSIG
++ *
++ * \note Did all the tests to see if we're on the same PRI and
++ * are on a compatible switchtype.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param c1 Q.931 call leg 1
++ * \param c2 Q.931 call leg 2
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int anfpr_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
+ {
+- /* Did all the tests to see if we're on the same PRI and
+- * are on a compatible switchtype */
+- /* TODO */
+- int i = 0;
+- int res = 0;
+- unsigned char buffer[255] = "";
+- unsigned short call_reference = c2->cr;
+- struct rose_component *comp = NULL, *compstk[10];
+- unsigned char buffer2[255] = "";
+- int compsp = 0;
+- static unsigned char op_tag[] = {
+- 0x0C,
+- };
+-
+- /* Channel 1 */
+- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+-
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+-
+- /* Interpretation component */
+- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 2); /* reject - to get feedback from QSIG switch */
+-
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+-
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
+-
+- res = asn1_string_encode(ASN1_INTEGER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
+- if (res < 0)
++ unsigned char buffer[255];
++ unsigned char *pos;
++ unsigned char *end;
++ int res;
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
++
++ end = buffer + sizeof(buffer);
++
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 2; /* rejectAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, buffer, end, &header);
++ if (!pos) {
+ return -1;
+- i += res;
+-
+- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- buffer[i++] = (0x0a);/* Enumeration endDesignation */
+- buffer[i++] = (0x01);/* Len */
+- buffer[i++] = (0x00);/* primaryEnd */
+- buffer[i++] = (0x81);/* redirectionNumber = presentationRestricted */
+- buffer[i++] = (0x00);/* Len */
+- buffer[i++] = (0x0a);/* Enumeration callStatus */
+- buffer[i++] = (0x01);/* Len */
+- buffer[i++] = (0x01);/* alerting */
++ }
+
+- /*
+- * Where does this element come from? It is not in Q.SIG ECMA-178.
+- * We send this but we will not accept it.
+- * This seems to be a cut and paste error from eect_initiate_transfer().
+- */
+- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_CallTransferComplete;
++ msg.invoke_id = get_invokeid(ctrl);
++ msg.args.qsig.CallTransferComplete.end_designation = 0; /* primaryEnd */
++ msg.args.qsig.CallTransferComplete.redirection.presentation = 1; /* presentationRestricted */
++ msg.args.qsig.CallTransferComplete.call_status = 1; /* alerting */
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++ if (!pos) {
++ return -1;
++ }
+
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+-
+- res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
++ res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, pos - buffer, NULL);
+ if (res) {
+- pri_message(pri, "Could not queue ADPU in facility message\n");
++ pri_message(ctrl, "Could not queue ADPU in facility message\n");
+ return -1;
+ }
+-
++
+ /* Remember that if we queue a facility IE for a facility message we
+ * have to explicitly send the facility message ourselves */
+-
++
+ res = q931_facility(c1->pri, c1);
+ if (res) {
+- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
++ pri_message(ctrl, "Could not schedule facility message for call %d\n", c1->cr);
+ return -1;
+ }
+-
+- /* Channel 2 */
+- i = 0;
+- res = 0;
+- compsp = 0;
+-
+- buffer2[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
+-
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer2, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer2, i, 0);
+- ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer2, i, 0);
+- ASN1_FIXUP(compstk, compsp, buffer2, i);
+-
+- /* Interpretation component */
+- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer2, i, 2); /* reject */
+-
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer2, i);
+- ASN1_PUSH(compstk, compsp, comp);
+-
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer2, i, get_invokeid(pri));
+-
+- res = asn1_string_encode(ASN1_INTEGER, &buffer2[i], sizeof(buffer2)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
+- if (res < 0)
++
++ /* Reuse the previous message header */
++ pos = facility_encode_header(ctrl, buffer, end, &header);
++ if (!pos) {
+ return -1;
+- i += res;
+-
+- ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer2, i);
+- ASN1_PUSH(compstk, compsp, comp);
+- buffer2[i++] = (0x0a);/* Enumeration endDesignation */
+- buffer2[i++] = (0x01);/* Len */
+- buffer2[i++] = (0x01);/* secondaryEnd */
+- buffer2[i++] = (0x81);/* redirectionNumber = presentationRestricted */
+- buffer2[i++] = (0x00);/* Len */
+- buffer2[i++] = (0x0a);/* Enumeration callStatus */
+- buffer2[i++] = (0x01);/* Len */
+- buffer2[i++] = (0x01);/* alerting */
++ }
+
+- /*
+- * Where does this element come from? It is not in Q.SIG ECMA-178.
+- * We send this but we will not accept it.
+- * This seems to be a cut and paste error from eect_initiate_transfer().
+- */
+- ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer2, i, call_reference);
++ /* Update the previous message */
++ msg.invoke_id = get_invokeid(ctrl);
++ msg.args.qsig.CallTransferComplete.end_designation = 1; /* secondaryEnd */
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++ if (!pos) {
++ return -1;
++ }
+
+- ASN1_FIXUP(compstk, compsp, buffer2, i);
+- ASN1_FIXUP(compstk, compsp, buffer2, i);
+-
+-
+- res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer2, i, NULL, NULL);
++ res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer, pos - buffer, NULL);
+ if (res) {
+- pri_message(pri, "Could not queue ADPU in facility message\n");
++ pri_message(ctrl, "Could not queue ADPU in facility message\n");
+ return -1;
+ }
+-
++
+ /* Remember that if we queue a facility IE for a facility message we
+ * have to explicitly send the facility message ourselves */
+-
++
+ res = q931_facility(c2->pri, c2);
+ if (res) {
+- pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
++ pri_message(ctrl, "Could not schedule facility message for call %d\n", c2->cr);
+ return -1;
+ }
+-
++
+ return 0;
+ }
+ /* End AFN-PR */
+
+ /* AOC */
+-static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
++/*!
++ * \internal
++ * \brief Encode the ETSI AOCEChargingUnit invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param chargedunits Number of units charged to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_aoce_charging_unit(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, long chargedunits)
+ {
+- int chargingcase = -1;
+- unsigned char *vdata = data;
+- struct rose_component *comp = NULL;
+- int pos1 = 0;
++ struct rose_msg_invoke msg;
+
+- if (pri->debug & PRI_DEBUG_AOC)
+- dump_apdu (pri, data, len);
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
+- do {
+- GET_COMPONENT(comp, pos1, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "!! Invalid AOC Charging Request argument. Expected Enumerated (0x0A) but Received 0x%02X\n");
+- ASN1_GET_INTEGER(comp, chargingcase);
+- if (chargingcase >= 0 && chargingcase <= 2) {
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "Channel %d/%d, Call %d - received AOC charging request - charging case: %i\n",
+- call->ds1no, call->channelno, call->cr, chargingcase);
+- } else {
+- pri_message(pri, "!! unkown AOC ChargingCase: 0x%02X", chargingcase);
+- chargingcase = -1;
+- }
+- NEXT_COMPONENT(comp, pos1);
+- } while (pos1 < len);
+- if (pos1 < len) {
+- pri_message(pri, "!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len );
+- dump_apdu (pri, data, len);
+- return -1; /* Aborted before */
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_ETSI_AOCEChargingUnit;
++ msg.invoke_id = get_invokeid(ctrl);
++ msg.args.etsi.AOCEChargingUnit.type = 1; /* charging_unit */
++ if (chargedunits <= 0) {
++ msg.args.etsi.AOCEChargingUnit.charging_unit.free_of_charge = 1;
++ } else {
++ msg.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.num_records = 1;
++ msg.args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.list[0].
++ number_of_units = chargedunits;
+ }
+- return 0;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
+ }
+-
+
+-static int aoc_aoce_charging_unit_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
++/*!
++ * \internal
++ * \brief Send the ETSI AOCEChargingUnit invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode AOC.
++ * \param chargedunits Number of units charged to encode.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int aoc_aoce_charging_unit_encode(struct pri *ctrl, q931_call *call,
++ long chargedunits)
+ {
+- long chargingunits = 0, chargetype = -1, temp, chargeIdentifier = -1;
+- unsigned char *vdata = data;
+- struct rose_component *comp1 = NULL, *comp2 = NULL, *comp3 = NULL;
+- int pos1 = 0, pos2, pos3, sublen2, sublen3;
+- struct addressingdataelements_presentednumberunscreened chargednr;
++ unsigned char buffer[255];
++ unsigned char *end;
+
+- if (pri->debug & PRI_DEBUG_AOC)
+- dump_apdu (pri, data, len);
++ /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
+
+- do {
+- GET_COMPONENT(comp1, pos1, vdata, len); /* AOCEChargingUnitInfo */
+- CHECK_COMPONENT(comp1, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but Received 0x%02X\n");
+- SUB_COMPONENT(comp1, pos1);
+- GET_COMPONENT(comp1, pos1, vdata, len);
+- switch (comp1->type) {
+- case (ASN1_SEQUENCE | ASN1_CONSTRUCTOR): /* specificChargingUnits */
+- sublen2 = comp1->len;
+- pos2 = pos1;
+- comp2 = comp1;
+- SUB_COMPONENT(comp2, pos2);
+- do {
+- GET_COMPONENT(comp2, pos2, vdata, len);
+- switch (comp2->type) {
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* RecordedUnitsList (0xA1) */
+- SUB_COMPONENT(comp2, pos2);
+- GET_COMPONENT(comp2, pos2, vdata, len);
+- CHECK_COMPONENT(comp2, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but received 0x02%X\n"); /* RecordedUnits */
+- sublen3 = pos2 + comp2->len;
+- pos3 = pos2;
+- comp3 = comp2;
+- SUB_COMPONENT(comp3, pos3);
+- do {
+- GET_COMPONENT(comp3, pos3, vdata, len);
+- switch (comp3->type) {
+- case ASN1_INTEGER: /* numberOfUnits */
+- ASN1_GET_INTEGER(comp3, temp);
+- chargingunits += temp;
+- case ASN1_NULL: /* notAvailable */
+- break;
+- default:
+- pri_message(pri, "!! Don't know how to handle 0x%02X in AOC-E RecordedUnits\n", comp3->type);
+- }
+- NEXT_COMPONENT(comp3, pos3);
+- } while (pos3 < sublen3);
+- if (pri->debug & PRI_DEBUG_AOC)
+- pri_message(pri, "Channel %d/%d, Call %d - received AOC-E charging: %i unit%s\n",
+- call->ds1no, call->channelno, call->cr, chargingunits, (chargingunits == 1) ? "" : "s");
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* AOCEBillingID (0xA2) */
+- SUB_COMPONENT(comp2, pos2);
+- GET_COMPONENT(comp2, pos2, vdata, len);
+- ASN1_GET_INTEGER(comp2, chargetype);
+- pri_message(pri, "!! not handled: Channel %d/%d, Call %d - received AOC-E billing ID: %i\n",
+- call->ds1no, call->channelno, call->cr, chargetype);
+- break;
+- default:
+- pri_message(pri, "!! Don't know how to handle 0x%02X in AOC-E RecordedUnitsList\n", comp2->type);
+- }
+- NEXT_COMPONENT(comp2, pos2);
+- } while (pos2 < sublen2);
+- break;
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* freeOfCharge (0x81) */
+- if (pri->debug & PRI_DEBUG_AOC)
+- pri_message(pri, "Channel %d/%d, Call %d - received AOC-E free of charge\n", call->ds1no, call->channelno, call->cr);
+- chargingunits = 0;
+- break;
+- default:
+- pri_message(pri, "!! Invalid AOC-E specificChargingUnits. Expected Sequence (0x30) or Object Identifier (0x81/0x01) but received 0x%02X\n", comp1->type);
+- }
+- NEXT_COMPONENT(comp1, pos1);
+- GET_COMPONENT(comp1, pos1, vdata, len); /* get optional chargingAssociation. will 'break' when reached end of structure */
+- switch (comp1->type) {
+- /* TODO: charged number is untested - please report! */
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* chargedNumber (0xA0) */
+- if(rose_presented_number_unscreened_decode(pri, call, comp1->data, comp1->len, &chargednr) != 0)
+- return -1;
+- pri_message(pri, "!! not handled: Received ChargedNr '%s' \n", chargednr.partyaddress);
+- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", chargednr.ton, chargednr.pres, chargednr.npi);
+- break;
+- case ASN1_INTEGER:
+- ASN1_GET_INTEGER(comp1, chargeIdentifier);
+- break;
+- default:
+- pri_message(pri, "!! Invalid AOC-E chargingAssociation. Expected Object Identifier (0xA0) or Integer (0x02) but received 0x%02X\n", comp1->type);
+- }
+- NEXT_COMPONENT(comp1, pos1);
+- } while (pos1 < len);
++ end =
++ enc_etsi_aoce_charging_unit(ctrl, buffer, buffer + sizeof(buffer), chargedunits);
++ if (!end) {
++ return -1;
++ }
+
+- if (pos1 < len) {
+- pri_message(pri, "!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len );
+- dump_apdu (pri, data, len);
+- return -1; /* oops - aborted before */
++ /* Remember that if we queue a facility IE for a facility message we
++ * have to explicitly send the facility message ourselves */
++ if (pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL)
++ || q931_facility(call->pri, call)) {
++ pri_message(ctrl, "Could not schedule facility message for call %d\n", call->cr);
++ return -1;
+ }
+- call->aoc_units = chargingunits;
+-
++
+ return 0;
+ }
++/* End AOC */
+
+-static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits)
++/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
++
++/*!
++ * \internal
++ * \brief Encode the Q.SIG CallTransferComplete invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode call transfer.
++ * \param call_status TRUE if call is alerting.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_call_transfer_complete(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, q931_call *call, int call_status)
+ {
+- /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
+- int i = 0, res = 0, compsp = 0;
+- unsigned char buffer[255] = "";
+- struct rose_component *comp = NULL, *compstk[10];
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
+
+- /* ROSE protocol (0x91)*/
+- buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
+- /* ROSE Component (0xA1,len)*/
+- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_CallTransferComplete;
++ msg.invoke_id = get_invokeid(ctrl);
++ msg.args.qsig.CallTransferComplete.end_designation = 0; /* primaryEnd */
+
+- /* ROSE invokeId component (0x02,len,id)*/
+- ASN1_ADD_WORDCOMP(comp, INVOKE_IDENTIFIER, buffer, i, ++pri->last_invoke);
++ /* redirectionNumber is the local_id.number */
++ q931_copy_presented_number_screened_to_rose(ctrl,
++ &msg.args.qsig.CallTransferComplete.redirection, &call->local_id.number);
+
+- /* ROSE operationId component (0x02,0x01,0x24)*/
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_AOC_AOCE_CHARGING_UNIT);
++ /* redirectionName is the local_id.name */
++ if (call->local_id.name.valid) {
++ msg.args.qsig.CallTransferComplete.redirection_name_present = 1;
++ q931_copy_name_to_rose(ctrl,
++ &msg.args.qsig.CallTransferComplete.redirection_name,
++ &call->local_id.name);
++ }
+
+- /* AOCEChargingUnitInfo (0x30,len) */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ if (call_status) {
++ msg.args.qsig.CallTransferComplete.call_status = 1; /* alerting */
++ }
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- if (chargedunits > 0) {
+- /* SpecificChargingUnits (0x30,len) */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
++ return pos;
++}
+
+- /* RecordedUnitsList (0xA1,len) */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+-
+- /* RecordedUnits (0x30,len) */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+- ASN1_PUSH(compstk, compsp, comp);
+-
+- /* NumberOfUnits (0x02,len,charge) */
+- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, chargedunits);
++/*!
++ * \internal
++ * \brief Encode the ETSI EctInform invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode inform message.
++ * \param call_status TRUE if call is alerting.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_ect_inform(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call, int call_status)
++{
++ struct rose_msg_invoke msg;
+
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- } else {
+- /* freeOfCharge (0x81,0) */
+- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
+ }
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+- ASN1_FIXUP(compstk, compsp, buffer, i);
+-
+- if (pri->debug & PRI_DEBUG_AOC)
+- dump_apdu (pri, buffer, i);
+-
+- /* code below is untested */
+- res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
+- if (res) {
+- pri_message(pri, "Could not queue APDU in facility message\n");
+- return -1;
++
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_ETSI_EctInform;
++ msg.invoke_id = get_invokeid(ctrl);
++
++ if (!call_status) {
++ msg.args.etsi.EctInform.status = 1;/* active */
++
++ /*
++ * EctInform(active) contains the redirectionNumber
++ * redirectionNumber is the local_id.number
++ */
++ msg.args.etsi.EctInform.redirection_present = 1;
++ q931_copy_presented_number_unscreened_to_rose(ctrl,
++ &msg.args.etsi.EctInform.redirection, &call->local_id.number);
+ }
+
+- /* Remember that if we queue a facility IE for a facility message we
+- * have to explicitly send the facility message ourselves */
+- res = q931_facility(c->pri, c);
+- if (res) {
+- pri_message(pri, "Could not schedule facility message for call %d\n", c->cr);
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode and queue the CallTransferComplete/EctInform invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode call transfer.
++ * \param call_status TRUE if call is alerting.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int rose_call_transfer_complete_encode(struct pri *ctrl, q931_call *call,
++ int call_status)
++{
++ unsigned char buffer[256];
++ unsigned char *end;
++
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ end =
++ enc_etsi_ect_inform(ctrl, buffer, buffer + sizeof(buffer), call, call_status);
++ break;
++ case PRI_SWITCH_QSIG:
++ end =
++ enc_qsig_call_transfer_complete(ctrl, buffer, buffer + sizeof(buffer), call,
++ call_status);
++ break;
++ default:
+ return -1;
+ }
++ if (!end) {
++ return -1;
++ }
+
+- return 0;
++ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
+ }
+-/* End AOC */
+
+-static int rose_calling_name_decode(struct pri *pri, q931_call *call, struct rose_component *choice, int len)
++/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
++
++/*!
++ * \internal
++ * \brief Encode the Q.SIG CalledName invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param name Name data which to encode name.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_called_name(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct q931_party_name *name)
+ {
+- int i = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = choice->data;
+- int characterSet = 1;
+- switch (choice->type) {
+- case ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE:
+- memcpy(call->callername, choice->data, choice->len);
+- call->callername[choice->len] = 0;
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " Received simple calling name '%s'\n", call->callername);
+- return 0;
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
+
+- case ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED:
+- do {
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_OCTETSTRING, "Don't know what to do if nameData is of type 0x%x\n");
+- memcpy(call->callername, comp->data, comp->len);
+- call->callername[comp->len] = 0;
+- NEXT_COMPONENT(comp, i);
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if CharacterSet is of type 0x%x\n");
+- ASN1_GET_INTEGER(comp, characterSet);
+- }
+- while (0);
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_CalledName;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " Received extended calling name '%s', characterset %d\n", call->callername, characterSet);
+- return 0;
+- case ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE:
+- case ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED:
+- case ROSE_NAME_PRESENTATION_RESTRICTED_NULL:
+- case ROSE_NAME_NOT_AVAIL:
+- default:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "Do not handle argument of type 0x%X\n", choice->type);
+- return -1;
+- }
++ /* CalledName */
++ q931_copy_name_to_rose(ctrl, &msg.args.qsig.CalledName.name, name);
++
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
++
++ return pos;
+ }
+-/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
+
+-static int rose_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
++/*!
++ * \internal
++ * \brief Encode and queue the Q.SIG CalledName invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode name.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int rose_called_name_encode(struct pri *ctrl, q931_call *call, int messagetype)
+ {
+- int i = 0;
+- int size = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = data;
++ unsigned char buffer[256];
++ unsigned char *end;
+
++ /* CalledName is the local_id.name */
++ end = enc_qsig_called_name(ctrl, buffer, buffer + sizeof(buffer),
++ &call->local_id.name);
++ if (!end) {
++ return -1;
++ }
+
+- do {
+- GET_COMPONENT(comp, i, vdata, len);
++ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
++}
+
+- switch(comp->type) {
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT NumberDigits -- default: unknownPartyNumber */
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PartyNumber: UnknownPartyNumber len=%d\n", len);
+- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+- if (size < 0)
+- return -1;
+- value->npi = PRI_NPI_UNKNOWN;
+- value->ton = PRI_TON_UNKNOWN;
+- break;
++/*!
++ * \internal
++ * \brief Encode the Q.SIG ConnectedName invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param name Name data which to encode name.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_connected_name(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct q931_party_name *name)
++{
++ struct fac_extension_header header;
++ struct rose_msg_invoke msg;
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT PublicPartyNumber */
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PartyNumber: PublicPartyNumber len=%d\n", len);
+- size = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
+- if (size < 0)
+- return -1;
+- value->npi = PRI_NPI_E163_E164;
+- break;
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT NumberDigits -- not used: dataPartyNumber */
+- pri_message(pri, "!! PartyNumber: dataPartyNumber is reserved!\n");
+- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+- if (size < 0)
+- return -1;
+- value->npi = PRI_NPI_X121 /* ??? */;
+- value->ton = PRI_TON_UNKNOWN /* ??? */;
+- break;
++ memset(&msg, 0, sizeof(msg));
++ msg.operation = ROSE_QSIG_ConnectedName;
++ msg.invoke_id = get_invokeid(ctrl);
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] IMPLICIT NumberDigits -- not used: telexPartyNumber */
+- pri_message(pri, "!! PartyNumber: telexPartyNumber is reserved!\n");
+- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+- if (size < 0)
+- return -1;
+- value->npi = PRI_NPI_F69 /* ??? */;
+- value->ton = PRI_TON_UNKNOWN /* ??? */;
+- break;
++ /* ConnectedName */
++ q931_copy_name_to_rose(ctrl, &msg.args.qsig.ConnectedName.name, name);
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT PrivatePartyNumber */
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PartyNumber: PrivatePartyNumber len=%d\n", len);
+- size = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
+- if (size < 0)
+- return -1;
+- value->npi = PRI_NPI_PRIVATE;
+- break;
++ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] IMPLICIT NumberDigits -- not used: nationalStandatdPartyNumber */
+- pri_message(pri, "!! PartyNumber: nationalStandardPartyNumber is reserved!\n");
+- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+- if (size < 0)
+- return -1;
+- value->npi = PRI_NPI_NATIONAL;
+- value->ton = PRI_TON_NATIONAL;
+- break;
++ return pos;
++}
+
+- default:
+- pri_message(pri, "Invalid PartyNumber component 0x%X\n", comp->type);
+- return -1;
+- }
+- ASN1_FIXUP_LEN(comp, size);
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PartyNumber: '%s' size=%d len=%d\n", value->partyaddress, size, len);
+- return size;
++/*!
++ * \internal
++ * \brief Encode and queue the Q.SIG ConnectedName invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode name.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int rose_connected_name_encode(struct pri *ctrl, q931_call *call, int messagetype)
++{
++ unsigned char buffer[256];
++ unsigned char *end;
++
++ /* ConnectedName is the local_id.name */
++ end = enc_qsig_connected_name(ctrl, buffer, buffer + sizeof(buffer),
++ &call->local_id.name);
++ if (!end) {
++ return -1;
+ }
+- while (0);
+
+- return -1;
++ return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL);
+ }
+
+-
+-static int rose_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
++/*!
++ * \brief Put the APDU on the call queue.
++ *
++ * \param call Call to enqueue message.
++ * \param messagetype Q.931 message type.
++ * \param apdu Facility ie contents buffer.
++ * \param apdu_len Length of the contents buffer.
++ * \param response Sender supplied information to handle APDU response messages.
++ * NULL if don't care about responses.
++ *
++ * \note
++ * Only APDU messages with an invoke component can supply a response pointer.
++ * If any other APDU messages supply a response pointer then aliasing of the
++ * invoke_id can occur.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response)
+ {
+- int i = 0;
+- int size = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = data;
++ struct apdu_event *cur = NULL;
++ struct apdu_event *new_event = NULL;
+
+- int scrind = -1;
+-
+- do {
+- /* Party Number */
+- GET_COMPONENT(comp, i, vdata, len);
+- size = rose_party_number_decode(pri, call, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_presentednumberunscreened*) value);
+- if (size < 0)
++ if (!call || !messagetype || !apdu
++ || apdu_len < 1 || sizeof(new_event->apdu) < apdu_len) {
++ return -1;
++ }
++ switch (messagetype) {
++ case Q931_FACILITY:
++ break;
++ default:
++ if (q931_is_dummy_call(call)) {
++ pri_error(call->pri, "!! Cannot send %s message on dummy call reference.\n",
++ msg2str(messagetype));
+ return -1;
+- comp->len = size;
+- NEXT_COMPONENT(comp, i);
++ }
++ break;
++ }
+
+- /* Screening Indicator */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with NumberScreened ROSE component type 0x%x\n");
+- ASN1_GET_INTEGER(comp, scrind);
+- // Todo: scrind = screeningindicator_for_q931(pri, scrind);
+- NEXT_COMPONENT(comp, i);
++ new_event = calloc(1, sizeof(*new_event));
++ if (!new_event) {
++ pri_error(call->pri, "!! Malloc failed!\n");
++ return -1;
++ }
+
+- value->scrind = scrind;
++ /* Fill in the APDU event */
++ new_event->message = messagetype;
++ if (response) {
++ new_event->response = *response;
++ }
++ new_event->call = call;
++ new_event->apdu_len = apdu_len;
++ memcpy(new_event->apdu, apdu, apdu_len);
+
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " NumberScreened: '%s' ScreeningIndicator=%d i=%d len=%d\n", value->partyaddress, scrind, i, len);
+-
+- return i-2; // We do not have a sequence header here.
++ /* Append APDU event to the end of the list. */
++ if (call->apdus) {
++ for (cur = call->apdus; cur->next; cur = cur->next) {
++ }
++ cur->next = new_event;
++ } else {
++ call->apdus = new_event;
+ }
+- while (0);
+
+- return -1;
++ return 0;
+ }
+
+-
+-static int rose_presented_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
++/* Used by q931.c to cleanup the apdu queue upon destruction of a call */
++void pri_call_apdu_queue_cleanup(q931_call *call)
+ {
+- int i = 0;
+- int size = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = data;
++ struct apdu_event *cur_event;
++ struct apdu_event *free_event;
+
+- /* Fill in default values */
+- value->ton = PRI_TON_UNKNOWN;
+- value->npi = PRI_NPI_UNKNOWN;
+- value->pres = -1; /* Data is not available */
++ if (call) {
++ cur_event = call->apdus;
++ call->apdus = NULL;
++ while (cur_event) {
++ if (cur_event->response.callback) {
++ /* Indicate to callback that the APDU is being cleaned up. */
++ cur_event->response.callback(APDU_CALLBACK_REASON_CLEANUP, call->pri,
++ call, cur_event, NULL);
+
+- do {
+- GET_COMPONENT(comp, i, vdata, len);
++ /* Stop any response timeout. */
++ pri_schedule_del(call->pri, cur_event->timer);
++ }
++ free_event = cur_event;
++ cur_event = cur_event->next;
++ free(free_event);
++ }
++ }
++}
+
+- switch(comp->type) {
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT presentationAllowedNumber */
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PresentedNumberScreened: presentationAllowedNumber comp->len=%d\n", comp->len);
+- value->pres = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
+- size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
+- if (size < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, size);
+- return size + 2;
++/*!
++ * \internal
++ * \brief Find an outstanding APDU with the given invoke id.
++ *
++ * \param call Call to find APDU.
++ * \param invoke_id Invoke id to match outstanding APDUs in queue.
++ *
++ * \retval apdu_event if found.
++ * \retval NULL if not found.
++ */
++static struct apdu_event *pri_call_apdu_find(struct q931_call *call, int invoke_id)
++{
++ struct apdu_event *apdu;
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PresentedNumberScreened: presentationRestricted comp->len=%d\n", comp->len);
+- if (comp->len != 0) { /* must be NULL */
+- pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
+- return -1;
+- }
+- value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
+- return 2;
++ for (apdu = call->apdus; apdu; apdu = apdu->next) {
++ /*
++ * Note: The APDU cannot be sent and still in the queue without a
++ * callback and timeout timer active. Therefore, an invoke_id of
++ * zero is valid and not just the result of a memset().
++ */
++ if (apdu->response.invoke_id == invoke_id && apdu->sent) {
++ break;
++ }
++ }
++ return apdu;
++}
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PresentedNumberScreened: NumberNotAvailableDueToInterworking comp->len=%d\n", comp->len);
+- if (comp->len != 0) { /* must be NULL */
+- pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
+- return -1;
+- }
+- value->pres = PRES_NUMBER_NOT_AVAILABLE;
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PresentedNumberScreened: numberNotAvailableDueToInterworking Type=0x%X i=%d len=%d size=%d\n", comp->type, i, len);
+- return 2;
++/*!
++ * \brief Delete the given APDU event from the given call.
++ *
++ * \param call Call to remove the APDU.
++ * \param doomed APDU event to delete.
++ *
++ * \return Nothing
++ */
++void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed)
++{
++ struct apdu_event **prev;
++ struct apdu_event *cur;
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT presentationRestrictedNumber */
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " PresentedNumberScreened: presentationRestrictedNumber comp->len=%d\n", comp->len);
+- value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
+- size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
+- if (size < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, size);
+- return size + 2;
++ /* Find APDU in list. */
++ for (prev = &call->apdus, cur = call->apdus;
++ cur;
++ prev = &cur->next, cur = cur->next) {
++ if (cur == doomed) {
++ /* Stop any response timeout. */
++ pri_schedule_del(call->pri, cur->timer);
+
+- default:
+- pri_message(pri, "Invalid PresentedNumberScreened component 0x%X\n", comp->type);
++ /* Remove APDU from list. */
++ *prev = cur->next;
++ free(cur);
++ break;
+ }
+- return -1;
+ }
+- while (0);
+-
+- return -1;
+ }
+
+-
+-static int rose_call_transfer_complete_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
++/*! \note Only called when sending the SETUP message. */
++int pri_call_add_standard_apdus(struct pri *ctrl, q931_call *call)
+ {
+- int i = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = sequence->data;
+- int res = 0;
++ if (!ctrl->sendfacility) {
++ return 0;
++ }
+
+- int end_designation = 0;
+- struct addressingdataelements_presentednumberscreened redirection_number;
+- char redirection_name[50] = "";
+- int call_status = 0;
+- redirection_number.partyaddress[0] = 0;
+- redirection_number.partysubaddress[0] = 0;
+- call->callername[0] = 0;
+- call->callernum[0] = 0;
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ if (q931_is_ptmp(ctrl)) {
++ /* PTMP mode */
++ break;
++ }
++ /* PTP mode */
++ if (call->redirecting.count) {
++ rose_diverting_leg_information2_encode(ctrl, call);
+
++ /*
++ * Expect a DivertingLegInformation3 to update the COLR of the
++ * redirecting-to party we are attempting to call now.
++ */
++ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
++ }
++ break;
++ case PRI_SWITCH_QSIG:
++ /* For Q.SIG it does network and cpe operations */
++ if (call->redirecting.count) {
++ rose_diverting_leg_information2_encode(ctrl, call);
+
+- /* Data checks */
+- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
+- pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
+- return -1;
++ /*
++ * Expect a DivertingLegInformation3 to update the COLR of the
++ * redirecting-to party we are attempting to call now.
++ */
++ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
++ }
++ add_callername_facility_ies(ctrl, call, 1);
++ break;
++ case PRI_SWITCH_NI2:
++ add_callername_facility_ies(ctrl, call, (ctrl->localtype == PRI_CPE));
++ break;
++ case PRI_SWITCH_DMS100:
++ if (ctrl->localtype == PRI_CPE) {
++ add_dms100_transfer_ability_apdu(ctrl, call);
++ }
++ break;
++ default:
++ break;
+ }
+
+- if (sequence->len == ASN1_LEN_INDEF) {
+- len -= 4; /* For the 2 extra characters at the end
+- * and two characters of header */
+- } else
+- len -= 2;
++ return 0;
++}
+
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " CT-Complete: len=%d\n", len);
++/*!
++ * \brief Send the CallTransferComplete/EctInform invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode call transfer.
++ * \param call_status TRUE if call is alerting.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int send_call_transfer_complete(struct pri *ctrl, q931_call *call, int call_status)
++{
++ if (rose_call_transfer_complete_encode(ctrl, call, call_status)
++ || q931_facility(ctrl, call)) {
++ pri_message(ctrl,
++ "Could not schedule facility message for call transfer completed.\n");
++ return -1;
++ }
+
+- do {
+- /* End Designation */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid endDesignation type 0x%X of ROSE callTransferComplete component received\n");
+- ASN1_GET_INTEGER(comp, end_designation);
+- NEXT_COMPONENT(comp, i);
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " CT-Complete: Received endDesignation=%d\n", end_designation);
++ return 0;
++}
+
++/*!
++ * \internal
++ * \brief Encode a plain facility ETSI error code.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode error message response.
++ * \param invoke_id Invoke id to put in error message response.
++ * \param code Error code to put in error message response.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_error(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call, int invoke_id, enum rose_error_code code)
++{
++ struct rose_msg_error msg;
+
+- /* Redirection Number */
+- GET_COMPONENT(comp, i, vdata, len);
+- res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
+- if (res < 0)
+- return -1;
+- comp->len = res;
+- if (res > 2) {
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
+- strncpy(call->callernum, redirection_number.partyaddress, 20);
+- call->callernum[20] = 0;
+- }
+- NEXT_COMPONENT(comp, i);
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
++ memset(&msg, 0, sizeof(msg));
++ msg.invoke_id = invoke_id;
++ msg.code = code;
+
+-#if 0 /* This one is optional. How do we check if it is there? */
+- /* Basic Call Info Elements */
+- GET_COMPONENT(comp, i, vdata, len);
+- NEXT_COMPONENT(comp, i);
+-#endif
++ pos = rose_encode_error(ctrl, pos, end, &msg);
+
++ return pos;
++}
+
+- /* Redirection Name */
+- GET_COMPONENT(comp, i, vdata, len);
+- res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
+- if (res < 0)
+- return -1;
+- memcpy(call->callername, comp->data, comp->len);
+- call->callername[comp->len] = 0;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
+- NEXT_COMPONENT(comp, i);
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
++/*!
++ * \internal
++ * \brief Encode a plain facility Q.SIG error code.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode error message response.
++ * \param invoke_id Invoke id to put in error message response.
++ * \param code Error code to put in error message response.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_error(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call, int invoke_id, enum rose_error_code code)
++{
++ struct fac_extension_header header;
++ struct rose_msg_error msg;
+
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
++ }
+
+- /* Call Status */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid callStatus type 0x%X of ROSE callTransferComplete component received\n");
+- ASN1_GET_INTEGER(comp, call_status);
+- NEXT_COMPONENT(comp, i);
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " CT-Complete: Received callStatus=%d\n", call_status);
++ memset(&msg, 0, sizeof(msg));
++ msg.invoke_id = invoke_id;
++ msg.code = code;
+
++ pos = rose_encode_error(ctrl, pos, end, &msg);
+
+- /* Argument Extension */
+-#if 0 /* Not supported */
+- GET_COMPONENT(comp, i, vdata, len);
+- switch (comp->type) {
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
+- res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
+- if (res < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
++ return pos;
++}
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
+- res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
+- if (res < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
++/*!
++ * \internal
++ * \brief Encode and queue a plain facility error code.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode error message response.
++ * \param invoke_id Invoke id to put in error message response.
++ * \param code Error code to put in error message response.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int rose_facility_error_encode(struct pri *ctrl, q931_call *call, int invoke_id,
++ enum rose_error_code code)
++{
++ unsigned char buffer[256];
++ unsigned char *end;
+
+- default:
+- pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
+- return -1;
+- }
+-#else
+- GET_COMPONENT(comp, i, vdata, len);
+- ASN1_FIXUP_LEN(comp, res);
+- NEXT_COMPONENT(comp, i);
+-#endif
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ end =
++ enc_etsi_error(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id, code);
++ break;
++ case PRI_SWITCH_QSIG:
++ end =
++ enc_qsig_error(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id, code);
++ break;
++ default:
++ return -1;
++ }
++ if (!end) {
++ return -1;
++ }
+
+- if(i < len)
+- pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
++ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
++}
+
+- return 0;
++/*!
++ * \brief Encode and send a plain facility error code.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode error message response.
++ * \param invoke_id Invoke id to put in error message response.
++ * \param code Error code to put in error message response.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int send_facility_error(struct pri *ctrl, q931_call *call, int invoke_id,
++ enum rose_error_code code)
++{
++ if (rose_facility_error_encode(ctrl, call, invoke_id, code)
++ || q931_facility(ctrl, call)) {
++ pri_message(ctrl,
++ "Could not schedule facility message for error message.\n");
++ return -1;
+ }
+- while (0);
+
+- return -1;
++ return 0;
+ }
+
+-
+-static int rose_call_transfer_update_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
++/*!
++ * \internal
++ * \brief Encode a plain facility ETSI result ok.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode result ok message response.
++ * \param invoke_id Invoke id to put in result ok message response.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_etsi_result_ok(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call, int invoke_id)
+ {
+- int i = 0;
+- struct rose_component *comp = NULL;
+- unsigned char *vdata = sequence->data;
+- int res = 0;
++ struct rose_msg_result msg;
+
+- struct addressingdataelements_presentednumberscreened redirection_number;
+- redirection_number.partyaddress[0] = 0;
+- redirection_number.partysubaddress[0] = 0;
+- char redirection_name[50] = "";
+- call->callername[0] = 0;
+- call->callernum[0] = 0;
++ pos = facility_encode_header(ctrl, pos, end, NULL);
++ if (!pos) {
++ return NULL;
++ }
+
++ memset(&msg, 0, sizeof(msg));
++ msg.invoke_id = invoke_id;
++ msg.operation = ROSE_None;
+
+- /* Data checks */
+- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
+- pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
+- return -1;
++ pos = rose_encode_result(ctrl, pos, end, &msg);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode a plain facility Q.SIG result ok.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param call Call leg from which to encode result ok message response.
++ * \param invoke_id Invoke id to put in result ok message response.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *enc_qsig_result_ok(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, q931_call *call, int invoke_id)
++{
++ struct fac_extension_header header;
++ struct rose_msg_result msg;
++
++ memset(&header, 0, sizeof(header));
++ header.nfe_present = 1;
++ header.nfe.source_entity = 0; /* endPINX */
++ header.nfe.destination_entity = 0; /* endPINX */
++ header.interpretation_present = 1;
++ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
++ pos = facility_encode_header(ctrl, pos, end, &header);
++ if (!pos) {
++ return NULL;
+ }
+
+- if (sequence->len == ASN1_LEN_INDEF) {
+- len -= 4; /* For the 2 extra characters at the end
+- * and two characters of header */
+- } else
+- len -= 2;
++ memset(&msg, 0, sizeof(msg));
++ msg.invoke_id = invoke_id;
++ msg.operation = ROSE_None;
+
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " CT-Complete: len=%d\n", len);
++ pos = rose_encode_result(ctrl, pos, end, &msg);
+
+- do {
+- /* Redirection Number */
+- GET_COMPONENT(comp, i, vdata, len);
+- res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
+- if (res < 0)
+- return -1;
+- comp->len = res;
+- if (res > 2) {
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
+- strncpy(call->callernum, redirection_number.partyaddress, 20);
+- call->callernum[20] = 0;
+- }
+- NEXT_COMPONENT(comp, i);
++ return pos;
++}
+
+- /* Redirection Name */
+- GET_COMPONENT(comp, i, vdata, len);
+- res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
+- if (res < 0)
+- return -1;
+- memcpy(call->callername, comp->data, comp->len);
+- call->callername[comp->len] = 0;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
+- NEXT_COMPONENT(comp, i);
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
++/*!
++ * \internal
++ * \brief Encode and queue a plain ROSE result ok.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode result ok message response.
++ * \param msgtype Q.931 message type to put facility ie in.
++ * \param invoke_id Invoke id to put in result ok message response.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id)
++{
++ unsigned char buffer[256];
++ unsigned char *end;
+
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ end =
++ enc_etsi_result_ok(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id);
++ break;
++ case PRI_SWITCH_QSIG:
++ end =
++ enc_qsig_result_ok(ctrl, buffer, buffer + sizeof(buffer), call, invoke_id);
++ break;
++ default:
++ return -1;
++ }
++ if (!end) {
++ return -1;
++ }
+
+-#if 0 /* This one is optional. How do we check if it is there? */
+- /* Basic Call Info Elements */
+- GET_COMPONENT(comp, i, vdata, len);
+- NEXT_COMPONENT(comp, i);
+-#endif
++ return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL);
++}
+
++/*!
++ * \brief Encode and send a FACILITY message with a plain ROSE result ok.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which to encode result ok message response.
++ * \param invoke_id Invoke id to put in result ok message response.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int send_facility_result_ok(struct pri *ctrl, q931_call *call, int invoke_id)
++{
++ if (rose_result_ok_encode(ctrl, call, Q931_FACILITY, invoke_id)
++ || q931_facility(ctrl, call)) {
++ pri_message(ctrl,
++ "Could not schedule facility message for result OK message.\n");
++ return -1;
++ }
+
+- /* Argument Extension */
+-#if 0 /* Not supported */
+- GET_COMPONENT(comp, i, vdata, len);
+- switch (comp->type) {
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
+- res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
+- if (res < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
++ return 0;
++}
+
+- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
+- res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
+- if (res < 0)
+- return -1;
+- ASN1_FIXUP_LEN(comp, res);
+- comp->len = res;
++int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI_REROUTING_RSP_CODE code)
++{
++ enum rose_error_code rose_err;
+
+- default:
+- pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
+- return -1;
+- }
+-#else
+- GET_COMPONENT(comp, i, vdata, len);
+- ASN1_FIXUP_LEN(comp, res);
+- NEXT_COMPONENT(comp, i);
+-#endif
++ if (!ctrl || !call) {
++ return -1;
++ }
+
+- if(i < len)
+- pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
++ /* Convert the public rerouting response code to an error code or result ok. */
++ rose_err = ROSE_ERROR_Gen_ResourceUnavailable;
++ switch (code) {
++ case PRI_REROUTING_RSP_OK_CLEAR:
++ return rose_result_ok_encode(ctrl, call, Q931_DISCONNECT, invoke_id);
++ case PRI_REROUTING_RSP_OK_RETAIN:
++ return send_facility_result_ok(ctrl, call, invoke_id);
++ case PRI_REROUTING_RSP_NOT_SUBSCRIBED:
++ rose_err = ROSE_ERROR_Gen_NotSubscribed;
++ break;
++ case PRI_REROUTING_RSP_NOT_AVAILABLE:
++ rose_err = ROSE_ERROR_Gen_NotAvailable;
++ break;
++ case PRI_REROUTING_RSP_NOT_ALLOWED:
++ rose_err = ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed;
++ break;
++ case PRI_REROUTING_RSP_INVALID_NUMBER:
++ rose_err = ROSE_ERROR_Div_InvalidDivertedToNr;
++ break;
++ case PRI_REROUTING_RSP_SPECIAL_SERVICE_NUMBER:
++ rose_err = ROSE_ERROR_Div_SpecialServiceNr;
++ break;
++ case PRI_REROUTING_RSP_DIVERSION_TO_SELF:
++ rose_err = ROSE_ERROR_Div_DiversionToServedUserNr;
++ break;
++ case PRI_REROUTING_RSP_MAX_DIVERSIONS_EXCEEDED:
++ rose_err = ROSE_ERROR_Div_NumberOfDiversionsExceeded;
++ break;
++ case PRI_REROUTING_RSP_RESOURCE_UNAVAILABLE:
++ rose_err = ROSE_ERROR_Gen_ResourceUnavailable;
++ break;
++ }
++ return send_facility_error(ctrl, call, invoke_id, rose_err);
++}
+
+- return 0;
++/*!
++ * \brief Handle the ROSE reject message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which the message came.
++ * \param msgtype Q.931 message type ie is in.
++ * \param ie Raw ie contents.
++ * \param header Decoded facility header before ROSE.
++ * \param reject Decoded ROSE reject message contents.
++ *
++ * \return Nothing
++ */
++void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
++ const struct fac_extension_header *header, const struct rose_msg_reject *reject)
++{
++ struct apdu_event *apdu;
++ union apdu_msg_data msg;
++
++ /* Gripe to the user about getting rejected. */
++ pri_error(ctrl, "ROSE REJECT:\n");
++ if (reject->invoke_id_present) {
++ pri_error(ctrl, "\tINVOKE ID: %d\n", reject->invoke_id);
+ }
+- while (0);
++ pri_error(ctrl, "\tPROBLEM: %s\n", rose_reject2str(reject->code));
+
+- return -1;
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_DMS100:
++ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
++ return;
++ default:
++ break;
++ }
++
++ if (!reject->invoke_id_present) {
++ /*
++ * No invoke id to look up so we cannot match it to any outstanding APDUs.
++ * This REJECT is apparently meant for someone monitoring the link.
++ */
++ return;
++ }
++ apdu = pri_call_apdu_find(call, reject->invoke_id);
++ if (!apdu) {
++ return;
++ }
++ msg.reject = reject;
++ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_REJECT, ctrl, call, apdu, &msg)) {
++ pri_call_apdu_delete(call, apdu);
++ }
+ }
+
++/*!
++ * \brief Handle the ROSE error message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which the message came.
++ * \param msgtype Q.931 message type ie is in.
++ * \param ie Raw ie contents.
++ * \param header Decoded facility header before ROSE.
++ * \param error Decoded ROSE error message contents.
++ *
++ * \return Nothing
++ */
++void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
++ const struct fac_extension_header *header, const struct rose_msg_error *error)
++{
++ const char *dms100_operation;
++ struct apdu_event *apdu;
++ union apdu_msg_data msg;
+
+-/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
++ /* Gripe to the user about getting an error. */
++ pri_error(ctrl, "ROSE RETURN ERROR:\n");
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_DMS100:
++ switch (error->invoke_id) {
++ case ROSE_DMS100_RLT_OPERATION_IND:
++ dms100_operation = "RLT_OPERATION_IND";
++ break;
++ case ROSE_DMS100_RLT_THIRD_PARTY:
++ dms100_operation = "RLT_THIRD_PARTY";
++ break;
++ default:
++ dms100_operation = NULL;
++ break;
++ }
++ if (dms100_operation) {
++ pri_error(ctrl, "\tOPERATION: %s\n", dms100_operation);
++ break;
++ }
++ /* fall through */
++ default:
++ pri_error(ctrl, "\tINVOKE ID: %d\n", error->invoke_id);
++ break;
++ }
++ pri_error(ctrl, "\tERROR: %s\n", rose_error2str(error->code));
+
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_DMS100:
++ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
++ return;
++ default:
++ break;
++ }
+
++ apdu = pri_call_apdu_find(call, error->invoke_id);
++ if (!apdu) {
++ return;
++ }
++ msg.error = error;
++ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_ERROR, ctrl, call, apdu, &msg)) {
++ pri_call_apdu_delete(call, apdu);
++ }
++}
+
+-int rose_reject_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
++/*!
++ * \brief Handle the ROSE result message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which the message came.
++ * \param msgtype Q.931 message type ie is in.
++ * \param ie Raw ie contents.
++ * \param header Decoded facility header before ROSE.
++ * \param result Decoded ROSE result message contents.
++ *
++ * \return Nothing
++ */
++void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
++ const struct fac_extension_header *header, const struct rose_msg_result *result)
+ {
+- int i = 0;
+- int problemtag = -1;
+- int problem = -1;
+- int invokeidvalue = -1;
+- unsigned char *vdata = data;
+- struct rose_component *comp = NULL;
+- char *problemtagstr, *problemstr;
+-
+- do {
+- /* Invoke ID stuff */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
+- ASN1_GET_INTEGER(comp, invokeidvalue);
+- NEXT_COMPONENT(comp, i);
++ struct apdu_event *apdu;
++ union apdu_msg_data msg;
+
+- GET_COMPONENT(comp, i, vdata, len);
+- problemtag = comp->type;
+- problem = comp->data[0];
+-
+- if (pri->switchtype == PRI_SWITCH_DMS100) {
+- switch (problemtag) {
+- case 0x80:
+- problemtagstr = "General problem";
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_DMS100:
++ /* The DMS-100 switch apparently handles invoke_id as an invoke operation. */
++ switch (result->invoke_id) {
++ case ROSE_DMS100_RLT_OPERATION_IND:
++ if (result->operation != ROSE_DMS100_RLT_OperationInd) {
++ pri_message(ctrl, "Invalid Operation value in return result! %s\n",
++ rose_operation2str(result->operation));
+ break;
+- case 0x81:
+- problemtagstr = "Invoke problem";
+- break;
+- case 0x82:
+- problemtagstr = "Return result problem";
+- break;
+- case 0x83:
+- problemtagstr = "Return error problem";
+- break;
+- default:
+- problemtagstr = "Unknown";
+ }
+
+- switch (problem) {
+- case 0x00:
+- problemstr = "Unrecognized component";
+- break;
+- case 0x01:
+- problemstr = "Mistyped component";
+- break;
+- case 0x02:
+- problemstr = "Badly structured component";
+- break;
+- default:
+- problemstr = "Unknown";
++ /* We have enough data to transfer the call */
++ call->rlt_call_id = result->args.dms100.RLT_OperationInd.call_id;
++ call->transferable = 1;
++ break;
++ case ROSE_DMS100_RLT_THIRD_PARTY:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "Successfully completed RLT transfer!\n");
+ }
+-
+- pri_error(pri, "ROSE REJECT:\n");
+- pri_error(pri, "\tINVOKE ID: 0x%X\n", invokeidvalue);
+- pri_error(pri, "\tPROBLEM TYPE: %s (0x%x)\n", problemtagstr, problemtag);
+- pri_error(pri, "\tPROBLEM: %s (0x%x)\n", problemstr, problem);
+-
+- return 0;
+- } else {
+- pri_message(pri, "Unable to handle reject on switchtype %d!\n", pri->switchtype);
+- return -1;
++ break;
++ default:
++ pri_message(ctrl, "Could not parse invoke of type %d!\n", result->invoke_id);
++ break;
+ }
++ return;
++ default:
++ break;
++ }
+
+- } while(0);
+-
+- return -1;
++ apdu = pri_call_apdu_find(call, result->invoke_id);
++ if (!apdu) {
++ return;
++ }
++ msg.result = result;
++ if (apdu->response.callback(APDU_CALLBACK_REASON_MSG_RESULT, ctrl, call, apdu, &msg)) {
++ pri_call_apdu_delete(call, apdu);
++ }
+ }
+-int rose_return_error_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
++
++/*!
++ * \brief Handle the ROSE invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param call Call leg from which the message came.
++ * \param msgtype Q.931 message type ie is in.
++ * \param ie Raw ie contents.
++ * \param header Decoded facility header before ROSE.
++ * \param invoke Decoded ROSE invoke message contents.
++ *
++ * \return Nothing
++ */
++void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
++ const struct fac_extension_header *header, const struct rose_msg_invoke *invoke)
+ {
+- int i = 0;
+- int errorvalue = -1;
+- int invokeidvalue = -1;
+- unsigned char *vdata = data;
+- struct rose_component *comp = NULL;
+- char *invokeidstr, *errorstr;
+-
+- do {
+- /* Invoke ID stuff */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
+- ASN1_GET_INTEGER(comp, invokeidvalue);
+- NEXT_COMPONENT(comp, i);
++ struct pri_subcommand *subcmd;
++ struct q931_party_id party_id;
++ struct q931_party_redirecting deflection;
+
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second component in return error is 0x%x\n");
+- ASN1_GET_INTEGER(comp, errorvalue);
++ switch (invoke->operation) {
++#if 0 /* Not handled yet */
++ case ROSE_ETSI_ActivationDiversion:
++ break;
++ case ROSE_ETSI_DeactivationDiversion:
++ break;
++ case ROSE_ETSI_ActivationStatusNotificationDiv:
++ break;
++ case ROSE_ETSI_DeactivationStatusNotificationDiv:
++ break;
++ case ROSE_ETSI_InterrogationDiversion:
++ break;
++ case ROSE_ETSI_DiversionInformation:
++ break;
++#endif /* Not handled yet */
++ case ROSE_ETSI_CallDeflection:
++ if (!PRI_MASTER(ctrl)->deflection_support) {
++ send_facility_error(ctrl, call, invoke->invoke_id,
++ ROSE_ERROR_Gen_NotSubscribed);
++ break;
++ }
++ if (!q931_master_pass_event(ctrl, call, msgtype)) {
++ /* Some other user is further along to connecting than this call. */
++ send_facility_error(ctrl, call, invoke->invoke_id,
++ ROSE_ERROR_Div_IncomingCallAccepted);
++ break;
++ }
++ if (call->master_call->deflection_in_progress) {
++ /* Someone else is already doing a call deflection. */
++ send_facility_error(ctrl, call, invoke->invoke_id,
++ ROSE_ERROR_Div_RequestAlreadyAccepted);
++ break;
++ }
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (!subcmd) {
++ /*
++ * ROSE_ERROR_Gen_ResourceUnavailable was not in the list of allowed codes,
++ * but we will send it anyway.
++ */
++ send_facility_error(ctrl, call, invoke->invoke_id,
++ ROSE_ERROR_Gen_ResourceUnavailable);
++ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
++ break;
++ }
+
+- if (pri->switchtype == PRI_SWITCH_DMS100) {
+- switch (invokeidvalue) {
+- case RLT_OPERATION_IND:
+- invokeidstr = "RLT_OPERATION_IND";
+- break;
+- case RLT_THIRD_PARTY:
+- invokeidstr = "RLT_THIRD_PARTY";
+- break;
+- default:
+- invokeidstr = "Unknown";
+- }
++ call->master_call->deflection_in_progress = 1;
+
+- switch (errorvalue) {
+- case 0x10:
+- errorstr = "RLT Bridge Fail";
+- break;
+- case 0x11:
+- errorstr = "RLT Call ID Not Found";
+- break;
+- case 0x12:
+- errorstr = "RLT Not Allowed";
+- break;
+- case 0x13:
+- errorstr = "RLT Switch Equip Congs";
+- break;
+- default:
+- errorstr = "Unknown";
+- }
++ q931_party_redirecting_init(&deflection);
+
+- pri_error(pri, "ROSE RETURN ERROR:\n");
+- pri_error(pri, "\tOPERATION: %s\n", invokeidstr);
+- pri_error(pri, "\tERROR: %s\n", errorstr);
++ /* Deflecting from the called address. */
++ q931_party_address_to_id(&deflection.from, &call->called);
++ if (invoke->args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user_present) {
++ deflection.from.number.presentation =
++ invoke->args.etsi.CallDeflection.presentation_allowed_to_diverted_to_user
++ ? PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED
++ : PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ } else {
++ deflection.from.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ }
+
+- return 0;
++ /* Deflecting to the new address. */
++ rose_copy_address_to_q931(ctrl, &deflection.to,
++ &invoke->args.etsi.CallDeflection.deflection);
++ deflection.to.number.presentation = deflection.from.number.presentation;
++
++ deflection.count = (call->redirecting.count < PRI_MAX_REDIRECTS)
++ ? call->redirecting.count + 1 : PRI_MAX_REDIRECTS;
++ deflection.reason = PRI_REDIR_DEFLECTION;
++ if (deflection.count == 1) {
++ deflection.orig_called = deflection.from;
++ deflection.orig_reason = deflection.reason;
+ } else {
+- pri_message(pri, "Unable to handle return error on switchtype %d!\n", pri->switchtype);
++ deflection.orig_called = call->redirecting.orig_called;
++ deflection.orig_reason = call->redirecting.orig_reason;
+ }
+
+- } while(0);
+-
+- return -1;
+-}
++ subcmd->cmd = PRI_SUBCMD_REROUTING;
++ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
++ subcmd->u.rerouting.subscription_option = 3;/* notApplicable */
++ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &call->local_id);
++ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
++ &deflection);
++ break;
++ case ROSE_ETSI_CallRerouting:
++ if (!PRI_MASTER(ctrl)->deflection_support) {
++ send_facility_error(ctrl, call, invoke->invoke_id,
++ ROSE_ERROR_Gen_NotSubscribed);
++ break;
++ }
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (!subcmd) {
++ send_facility_error(ctrl, call, invoke->invoke_id,
++ ROSE_ERROR_Gen_ResourceUnavailable);
++ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
++ break;
++ }
+
+-int rose_return_result_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
+-{
+- int i = 0;
+- int operationidvalue = -1;
+- int invokeidvalue = -1;
+- unsigned char *vdata = data;
+- struct rose_component *comp = NULL;
+-
+- do {
+- /* Invoke ID stuff */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
+- ASN1_GET_INTEGER(comp, invokeidvalue);
+- NEXT_COMPONENT(comp, i);
++ q931_party_redirecting_init(&deflection);
+
+- if (pri->switchtype == PRI_SWITCH_DMS100) {
+- switch (invokeidvalue) {
+- case RLT_THIRD_PARTY:
+- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed RLT transfer!\n");
+- return 0;
+- case RLT_OPERATION_IND:
+- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Received RLT_OPERATION_IND\n");
+- /* Have to take out the rlt_call_id */
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Protocol error detected in parsing RLT_OPERATION_IND return result!\n");
++ /* Rerouting from the last address. */
++ rose_copy_presented_number_unscreened_to_q931(ctrl, &deflection.from.number,
++ &invoke->args.etsi.CallRerouting.last_rerouting);
+
+- /* Traverse the contents of this sequence */
+- /* First is the Operation Value */
+- SUB_COMPONENT(comp, i);
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_INTEGER, "RLT_OPERATION_IND should be of type ASN1_INTEGER!\n");
+- ASN1_GET_INTEGER(comp, operationidvalue);
++ /* Rerouting to the new address. */
++ rose_copy_address_to_q931(ctrl, &deflection.to,
++ &invoke->args.etsi.CallRerouting.called_address);
++ switch (invoke->args.etsi.CallRerouting.subscription_option) {
++ default:
++ case 0: /* noNotification */
++ case 1: /* notificationWithoutDivertedToNr */
++ deflection.to.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ break;
++ case 2: /* notificationWithDivertedToNr */
++ deflection.to.number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ break;
++ }
+
+- if (operationidvalue != RLT_OPERATION_IND) {
+- pri_message(pri, "Invalid Operation ID value (0x%x) in return result!\n", operationidvalue);
+- return -1;
+- }
++ /* Calling party subaddress update. */
++ party_id = call->local_id;
+
+- /* Next is the Call ID */
+- NEXT_COMPONENT(comp, i);
+- GET_COMPONENT(comp, i, vdata, len);
+- CHECK_COMPONENT(comp, ASN1_TAG_0, "Error check failed on Call ID!\n");
+- ASN1_GET_INTEGER(comp, call->rlt_call_id);
+- /* We have enough data to transfer the call */
+- call->transferable = 1;
++ deflection.count = invoke->args.etsi.CallRerouting.rerouting_counter;
++ deflection.reason = redirectingreason_for_q931(ctrl,
++ invoke->args.etsi.CallRerouting.rerouting_reason);
++ if (deflection.count == 1) {
++ deflection.orig_called = deflection.from;
++ deflection.orig_reason = deflection.reason;
++ } else {
++ deflection.orig_called = call->redirecting.orig_called;
++ deflection.orig_reason = call->redirecting.orig_reason;
++ }
+
+- return 0;
+-
+- default:
+- pri_message(pri, "Could not parse invoke of type 0x%x!\n", invokeidvalue);
+- return -1;
++ subcmd->cmd = PRI_SUBCMD_REROUTING;
++ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
++ subcmd->u.rerouting.subscription_option =
++ invoke->args.etsi.CallRerouting.subscription_option;
++ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &party_id);
++ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
++ &deflection);
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_ETSI_InterrogateServedUserNumbers:
++ break;
++#endif /* Not handled yet */
++ case ROSE_ETSI_DivertingLegInformation1:
++ if (invoke->args.etsi.DivertingLegInformation1.diverted_to_present) {
++ rose_copy_presented_number_unscreened_to_q931(ctrl, &party_id.number,
++ &invoke->args.etsi.DivertingLegInformation1.diverted_to);
++ /*
++ * We set the presentation value since the sender cannot know the
++ * presentation value preference of the destination party.
++ */
++ if (party_id.number.str[0]) {
++ party_id.number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ } else {
++ party_id.number.presentation =
++ PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
+ }
+- } else if (pri->switchtype == PRI_SWITCH_QSIG) {
+- switch (invokeidvalue) {
+- case 0x13:
+- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed QSIG CF callRerouting!\n");
+- return 0;
+- }
+ } else {
+- pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
+- return -1;
++ q931_party_number_init(&party_id.number);
++ party_id.number.valid = 1;
+ }
+
+- } while(0);
+-
+- return -1;
+-}
++ /*
++ * Unless otherwise indicated by CONNECT, the divertedToNumber will be
++ * the remote_id.number.
++ */
++ if (!call->connected_number_in_message) {
++ call->remote_id.number = party_id.number;
++ }
+
+-int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
+-{
+- int i = 0;
+- int res = 0;
+- int operation_tag;
+- unsigned char *vdata = data;
+- struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
+-
+- do {
+- /* Invoke ID stuff */
+- GET_COMPONENT(comp, i, vdata, len);
+-#if 0
+- CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
+-#endif
+- invokeid = comp;
+- NEXT_COMPONENT(comp, i);
++ /* divertedToNumber is put in redirecting.to.number */
++ switch (invoke->args.etsi.DivertingLegInformation1.subscription_option) {
++ default:
++ case 0: /* noNotification */
++ case 1: /* notificationWithoutDivertedToNr */
++ q931_party_number_init(&call->redirecting.to.number);
++ call->redirecting.to.number.valid = 1;
++ call->redirecting.to.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ break;
++ case 2: /* notificationWithDivertedToNr */
++ call->redirecting.to.number = party_id.number;
++ break;
++ }
+
+- /* Operation Tag */
+- GET_COMPONENT(comp, i, vdata, len);
+-#if 0
+- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second ROSE component is of type 0x%x\n");
+-#endif
+- operationid = comp;
+- ASN1_GET_INTEGER(comp, operation_tag);
+- NEXT_COMPONENT(comp, i);
++ call->redirecting.reason = redirectingreason_for_q931(ctrl,
++ invoke->args.etsi.DivertingLegInformation1.diversion_reason);
++ if (call->redirecting.count < PRI_MAX_REDIRECTS) {
++ ++call->redirecting.count;
++ }
++ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
++ break;
++ case ROSE_ETSI_DivertingLegInformation2:
++ call->redirecting.state = Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3;
++ call->redirecting.count =
++ invoke->args.etsi.DivertingLegInformation2.diversion_counter;
++ if (!call->redirecting.count) {
++ /* To be safe, make sure that the count is non-zero. */
++ call->redirecting.count = 1;
++ }
++ call->redirecting.reason = redirectingreason_for_q931(ctrl,
++ invoke->args.etsi.DivertingLegInformation2.diversion_reason);
+
+- /* No argument - return with error */
+- if (i >= len)
+- return -1;
++ /* divertingNr is put in redirecting.from.number */
++ if (invoke->args.etsi.DivertingLegInformation2.diverting_present) {
++ rose_copy_presented_number_unscreened_to_q931(ctrl,
++ &call->redirecting.from.number,
++ &invoke->args.etsi.DivertingLegInformation2.diverting);
++ } else if (!call->redirecting_number_in_message) {
++ q931_party_number_init(&call->redirecting.from.number);
++ call->redirecting.from.number.valid = 1;
++ }
+
+- /* Arguement Tag */
+- GET_COMPONENT(comp, i, vdata, len);
+- if (!comp->type)
+- return -1;
++ call->redirecting.orig_reason = PRI_REDIR_UNKNOWN;
+
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " [ Handling operation %d ]\n", operation_tag);
+- switch (operation_tag) {
+- case SS_CNID_CALLINGNAME:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, " Handle Name display operation\n");
+- return rose_calling_name_decode(pri, call, comp, len-i);
+- case ROSE_CALL_TRANSFER_IDENTIFY:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "ROSE %i: CallTransferIdentify - not handled!\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- return -1;
+- case ROSE_CALL_TRANSFER_ABANDON:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "ROSE %i: CallTransferAbandon - not handled!\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- return -1;
+- case ROSE_CALL_TRANSFER_INITIATE:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "ROSE %i: CallTransferInitiate - not handled!\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- return -1;
+- case ROSE_CALL_TRANSFER_SETUP:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "ROSE %i: CallTransferSetup - not handled!\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- return -1;
+- case ROSE_CALL_TRANSFER_ACTIVE:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "ROSE %i: CallTransferActive - not handled!\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- return -1;
+- case ROSE_CALL_TRANSFER_COMPLETE:
+- if (pri->debug & PRI_DEBUG_APDU)
+- {
+- pri_message(pri, "ROSE %i: Handle CallTransferComplete\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
++ /* originalCalledNr is put in redirecting.orig_called.number */
++ if (invoke->args.etsi.DivertingLegInformation2.original_called_present) {
++ rose_copy_presented_number_unscreened_to_q931(ctrl,
++ &call->redirecting.orig_called.number,
++ &invoke->args.etsi.DivertingLegInformation2.original_called);
++ } else {
++ q931_party_number_init(&call->redirecting.orig_called.number);
++ }
++ break;
++ case ROSE_ETSI_DivertingLegInformation3:
++ /*
++ * Unless otherwise indicated by CONNECT, this will be the
++ * remote_id.number.presentation.
++ */
++ if (!invoke->args.etsi.DivertingLegInformation3.presentation_allowed_indicator) {
++ call->redirecting.to.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ if (!call->connected_number_in_message) {
++ call->remote_id.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
+ }
+- return rose_call_transfer_complete_decode(pri, call, comp, len-i);
+- case ROSE_CALL_TRANSFER_UPDATE:
+- if (pri->debug & PRI_DEBUG_APDU)
+- {
+- pri_message(pri, "ROSE %i: Handle CallTransferUpdate\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
++ }
++
++ switch (call->redirecting.state) {
++ case Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3:
++ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (!subcmd) {
++ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
++ break;
+ }
+- return rose_call_transfer_update_decode(pri, call, comp, len-i);
+- case ROSE_SUBADDRESS_TRANSFER:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "ROSE %i: SubaddressTransfer - not handled!\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- return -1;
+- case ROSE_DIVERTING_LEG_INFORMATION2:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "ROSE %i: Handle CallingName\n", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- }
+- return rose_diverting_leg_information2_decode(pri, call, comp, len-i);
+- case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "ROSE %i: AOC No Charging Info Available - not handled!", operation_tag);
+- dump_apdu (pri, comp->data, comp->len);
+- }
+- return -1;
+- case ROSE_AOC_CHARGING_REQUEST:
+- return aoc_aoce_charging_request_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
+- case ROSE_AOC_AOCS_CURRENCY:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "ROSE %i: AOC-S Currency - not handled!", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- }
+- return -1;
+- case ROSE_AOC_AOCS_SPECIAL_ARR:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "ROSE %i: AOC-S Special Array - not handled!", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- }
+- return -1;
+- case ROSE_AOC_AOCD_CURRENCY:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "ROSE %i: AOC-D Currency - not handled!", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- }
+- return -1;
+- case ROSE_AOC_AOCD_CHARGING_UNIT:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "ROSE %i: AOC-D Charging Unit - not handled!", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- }
+- return -1;
+- case ROSE_AOC_AOCE_CURRENCY:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "ROSE %i: AOC-E Currency - not handled!", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- }
+- return -1;
+- case ROSE_AOC_AOCE_CHARGING_UNIT:
+- return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
+- if (0) { /* the following function is currently not used - just to make the compiler happy */
+- aoc_aoce_charging_unit_encode(pri, call, call->aoc_units); /* use this function to forward the aoc-e on a bridged channel */
+- return 0;
+- }
+- case ROSE_AOC_IDENTIFICATION_OF_CHARGE:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "ROSE %i: AOC Identification Of Charge - not handled!", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
+- }
+- return -1;
+- case SS_ANFPR_PATHREPLACEMENT:
+- /* Clear Queue */
+- res = pri_call_apdu_queue_cleanup(call->bridged_call);
+- if (res) {
+- pri_message(pri, "Could not Clear queue ADPU\n");
+- return -1;
+- }
+- anfpr_pathreplacement_respond(pri, call, ie);
+- break;
++ /* Setup redirecting subcommand */
++ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
++ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
++ &call->redirecting);
++ break;
+ default:
+- if (pri->debug & PRI_DEBUG_APDU) {
+- pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
+- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
++ break;
++ }
++ break;
++ case ROSE_ETSI_ChargingRequest:
++ /* Ignore messsage */
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_ETSI_AOCSCurrency:
++ break;
++ case ROSE_ETSI_AOCSSpecialArr:
++ break;
++ case ROSE_ETSI_AOCDCurrency:
++ break;
++ case ROSE_ETSI_AOCDChargingUnit:
++ break;
++ case ROSE_ETSI_AOCECurrency:
++ break;
++#endif /* Not handled yet */
++ case ROSE_ETSI_AOCEChargingUnit:
++ call->aoc_units = 0;
++ if (invoke->args.etsi.AOCEChargingUnit.type == 1
++ && !invoke->args.etsi.AOCEChargingUnit.charging_unit.free_of_charge) {
++ unsigned index;
++
++ for (index =
++ invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.
++ num_records; index--;) {
++ if (!invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.recorded.
++ list[index].not_available) {
++ call->aoc_units +=
++ invoke->args.etsi.AOCEChargingUnit.charging_unit.specific.
++ recorded.list[index].number_of_units;
++ }
+ }
+- return -1;
+ }
+- } while(0);
+-
+- return -1;
+-}
++ /* the following function is currently not used - just to make the compiler happy */
++ if (0) {
++ /* use this function to forward the aoc-e on a bridged channel */
++ aoc_aoce_charging_unit_encode(ctrl, call, call->aoc_units);
++ }
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_ITU_IdentificationOfCharge:
++ break;
++#endif /* Not handled yet */
++#if 0 /* Not handled yet */
++ case ROSE_ETSI_EctExecute:
++ break;
++ case ROSE_ETSI_ExplicitEctExecute:
++ break;
++#endif /* Not handled yet */
++ case ROSE_ETSI_RequestSubaddress:
++ /* Ignore since we are not handling subaddresses yet. */
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_ETSI_SubaddressTransfer:
++ break;
++ case ROSE_ETSI_EctLinkIdRequest:
++ break;
++#endif /* Not handled yet */
++ case ROSE_ETSI_EctInform:
++ /* redirectionNumber is put in remote_id.number */
++ if (invoke->args.etsi.EctInform.redirection_present) {
++ rose_copy_presented_number_unscreened_to_q931(ctrl,
++ &call->remote_id.number, &invoke->args.etsi.EctInform.redirection);
++ }
++ if (!invoke->args.etsi.EctInform.status) {
++ /* The remote party for the transfer has not answered yet. */
++ call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
++ } else {
++ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
++ }
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_ETSI_EctLoopTest:
++ break;
++#endif /* Not handled yet */
++ case ROSE_QSIG_CallingName:
++ /* CallingName is put in remote_id.name */
++ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
++ &invoke->args.qsig.CallingName.name);
++ break;
++ case ROSE_QSIG_CalledName:
++ /* CalledName is put in remote_id.name */
++ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
++ &invoke->args.qsig.CalledName.name);
+
+-int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data)
+-{
+- struct apdu_event *cur = NULL;
+- struct apdu_event *new_event = NULL;
++ /* Setup connected line subcommand */
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (!subcmd) {
++ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
++ break;
++ }
++ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
++ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &call->remote_id);
++ break;
++ case ROSE_QSIG_ConnectedName:
++ /* ConnectedName is put in remote_id.name */
++ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
++ &invoke->args.qsig.ConnectedName.name);
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_QSIG_BusyName:
++ break;
++#endif /* Not handled yet */
++#if 0 /* Not handled yet */
++ case ROSE_QSIG_ChargeRequest:
++ break;
++ case ROSE_QSIG_GetFinalCharge:
++ break;
++ case ROSE_QSIG_AocFinal:
++ break;
++ case ROSE_QSIG_AocInterim:
++ break;
++ case ROSE_QSIG_AocRate:
++ break;
++ case ROSE_QSIG_AocComplete:
++ break;
++ case ROSE_QSIG_AocDivChargeReq:
++ break;
++#endif /* Not handled yet */
++#if 0 /* Not handled yet */
++ case ROSE_QSIG_CallTransferIdentify:
++ break;
++ case ROSE_QSIG_CallTransferAbandon:
++ break;
++ case ROSE_QSIG_CallTransferInitiate:
++ break;
++ case ROSE_QSIG_CallTransferSetup:
++ break;
++#endif /* Not handled yet */
++ case ROSE_QSIG_CallTransferActive:
++ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
+
+- if (!call || !messagetype || !apdu || (apdu_len < 1) || (apdu_len > 255))
+- return -1;
++ /* connectedAddress is put in remote_id */
++ rose_copy_presented_address_screened_to_q931(ctrl, &call->remote_id,
++ &invoke->args.qsig.CallTransferActive.connected);
+
+- if (!(new_event = calloc(1, sizeof(*new_event)))) {
+- pri_error(call->pri, "!! Malloc failed!\n");
+- return -1;
+- }
++ /* connectedName is put in remote_id.name */
++ if (invoke->args.qsig.CallTransferActive.connected_name_present) {
++ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
++ &invoke->args.qsig.CallTransferActive.connected_name);
++ }
++ break;
++ case ROSE_QSIG_CallTransferComplete:
++ /* redirectionNumber is put in remote_id.number */
++ rose_copy_presented_number_screened_to_q931(ctrl, &call->remote_id.number,
++ &invoke->args.qsig.CallTransferComplete.redirection);
+
+- new_event->message = messagetype;
+- new_event->callback = function;
+- new_event->data = data;
+- memcpy(new_event->apdu, apdu, apdu_len);
+- new_event->apdu_len = apdu_len;
+-
+- if (call->apdus) {
+- cur = call->apdus;
+- while (cur->next) {
+- cur = cur->next;
++ /* redirectionName is put in remote_id.name */
++ if (invoke->args.qsig.CallTransferComplete.redirection_name_present) {
++ rose_copy_name_to_q931(ctrl, &call->remote_id.name,
++ &invoke->args.qsig.CallTransferComplete.redirection_name);
+ }
+- cur->next = new_event;
+- } else
+- call->apdus = new_event;
+
+- return 0;
+-}
++ if (invoke->args.qsig.CallTransferComplete.call_status == 1) {
++ /* The remote party for the transfer has not answered yet. */
++ call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
++ } else {
++ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
++ }
++ break;
++ case ROSE_QSIG_CallTransferUpdate:
++ party_id = call->remote_id;
+
+-int pri_call_apdu_queue_cleanup(q931_call *call)
+-{
+- struct apdu_event *cur_event = NULL, *free_event = NULL;
++ /* redirectionNumber is put in party_id.number */
++ rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
++ &invoke->args.qsig.CallTransferUpdate.redirection);
+
+- if (call && call->apdus) {
+- cur_event = call->apdus;
+- while (cur_event) {
+- /* TODO: callbacks, some way of giving return res on status of apdu */
+- free_event = cur_event;
+- cur_event = cur_event->next;
+- free(free_event);
++ /* redirectionName is put in party_id.name */
++ if (invoke->args.qsig.CallTransferUpdate.redirection_name_present) {
++ rose_copy_name_to_q931(ctrl, &party_id.name,
++ &invoke->args.qsig.CallTransferUpdate.redirection_name);
+ }
+- call->apdus = NULL;
+- }
+
+- return 0;
+-}
+-
+-int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
+-{
+- if (!pri->sendfacility)
+- return 0;
+-
+- if (pri->switchtype == PRI_SWITCH_QSIG) { /* For Q.SIG it does network and cpe operations */
+- if (call->redirectingnum[0])
+- rose_diverting_leg_information2_encode(pri, call);
+- add_callername_facility_ies(pri, call, 1);
+- return 0;
+- }
+-
+-#if 0
+- if (pri->localtype == PRI_NETWORK) {
+- switch (pri->switchtype) {
+- case PRI_SWITCH_NI2:
+- add_callername_facility_ies(pri, call, 0);
++ if (q931_party_id_cmp(&party_id, &call->remote_id)) {
++ /* The remote_id data has changed. */
++ call->remote_id = party_id;
++ switch (call->incoming_ct_state) {
++ case INCOMING_CT_STATE_IDLE:
++ call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
+ break;
+ default:
+ break;
++ }
+ }
+- return 0;
+- } else if (pri->localtype == PRI_CPE) {
+- switch (pri->switchtype) {
+- case PRI_SWITCH_NI2:
+- add_callername_facility_ies(pri, call, 1);
+- break;
+- default:
+- break;
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_QSIG_SubaddressTransfer:
++ break;
++#endif /* Not handled yet */
++ case ROSE_QSIG_PathReplacement:
++ anfpr_pathreplacement_respond(ctrl, call, ie);
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_QSIG_ActivateDiversionQ:
++ break;
++ case ROSE_QSIG_DeactivateDiversionQ:
++ break;
++ case ROSE_QSIG_InterrogateDiversionQ:
++ break;
++ case ROSE_QSIG_CheckRestriction:
++ break;
++#endif /* Not handled yet */
++ case ROSE_QSIG_CallRerouting:
++ if (!PRI_MASTER(ctrl)->deflection_support) {
++ send_facility_error(ctrl, call, invoke->invoke_id,
++ ROSE_ERROR_Gen_NotSubscribed);
++ break;
+ }
+- return 0;
+- }
+-#else
+- if (pri->switchtype == PRI_SWITCH_NI2)
+- add_callername_facility_ies(pri, call, (pri->localtype == PRI_CPE));
+-#endif
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (!subcmd) {
++ send_facility_error(ctrl, call, invoke->invoke_id,
++ ROSE_ERROR_Gen_ResourceUnavailable);
++ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
++ break;
++ }
+
+- if ((pri->switchtype == PRI_SWITCH_DMS100) && (pri->localtype == PRI_CPE)) {
+- add_dms100_transfer_ability_apdu(pri, call);
+- }
++ q931_party_redirecting_init(&deflection);
+
++ /* Rerouting from the last address. */
++ rose_copy_presented_number_unscreened_to_q931(ctrl, &deflection.from.number,
++ &invoke->args.qsig.CallRerouting.last_rerouting);
++ if (invoke->args.qsig.CallRerouting.redirecting_name_present) {
++ rose_copy_name_to_q931(ctrl, &deflection.from.name,
++ &invoke->args.qsig.CallRerouting.redirecting_name);
++ }
+
++ /* Rerouting to the new address. */
++ rose_copy_address_to_q931(ctrl, &deflection.to,
++ &invoke->args.qsig.CallRerouting.called);
++ switch (invoke->args.qsig.CallRerouting.subscription_option) {
++ default:
++ case 0: /* noNotification */
++ case 1: /* notificationWithoutDivertedToNr */
++ deflection.to.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ break;
++ case 2: /* notificationWithDivertedToNr */
++ deflection.to.number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ break;
++ }
+
+- return 0;
++ /* Calling party update. */
++ party_id = call->local_id;
++ rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
++ &invoke->args.qsig.CallRerouting.calling);
++ if (invoke->args.qsig.CallRerouting.calling_name_present) {
++ rose_copy_name_to_q931(ctrl, &party_id.name,
++ &invoke->args.qsig.CallRerouting.calling_name);
++ }
++
++ deflection.count = invoke->args.qsig.CallRerouting.diversion_counter;
++ deflection.reason = redirectingreason_for_q931(ctrl,
++ invoke->args.qsig.CallRerouting.rerouting_reason);
++
++ /* Original called party update. */
++ if (deflection.count == 1) {
++ deflection.orig_called = deflection.from;
++ deflection.orig_reason = deflection.reason;
++ } else {
++ deflection.orig_called = call->redirecting.orig_called;
++ deflection.orig_reason = call->redirecting.orig_reason;
++ }
++ if (invoke->args.qsig.CallRerouting.original_called_present) {
++ rose_copy_presented_number_unscreened_to_q931(ctrl,
++ &deflection.orig_called.number,
++ &invoke->args.qsig.CallRerouting.original_called);
++ }
++ if (invoke->args.qsig.CallRerouting.original_called_name_present) {
++ rose_copy_name_to_q931(ctrl, &deflection.orig_called.name,
++ &invoke->args.qsig.CallRerouting.original_called_name);
++ }
++ if (invoke->args.qsig.CallRerouting.original_rerouting_reason_present) {
++ deflection.orig_reason = redirectingreason_for_q931(ctrl,
++ invoke->args.qsig.CallRerouting.original_rerouting_reason);
++ }
++
++ subcmd->cmd = PRI_SUBCMD_REROUTING;
++ subcmd->u.rerouting.invoke_id = invoke->invoke_id;
++ subcmd->u.rerouting.subscription_option =
++ invoke->args.qsig.CallRerouting.subscription_option;
++ q931_party_id_copy_to_pri(&subcmd->u.rerouting.caller, &party_id);
++ q931_party_redirecting_copy_to_pri(&subcmd->u.rerouting.deflection,
++ &deflection);
++ break;
++ case ROSE_QSIG_DivertingLegInformation1:
++ q931_party_number_init(&party_id.number);
++ rose_copy_number_to_q931(ctrl, &party_id.number,
++ &invoke->args.qsig.DivertingLegInformation1.nominated_number);
++ if (party_id.number.str[0]) {
++ party_id.number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ }
++
++ /*
++ * Unless otherwise indicated by CONNECT, the nominatedNr will be
++ * the remote_id.number.
++ */
++ if (!call->connected_number_in_message) {
++ call->remote_id.number = party_id.number;
++ }
++
++ /* nominatedNr is put in redirecting.to.number */
++ switch (invoke->args.qsig.DivertingLegInformation1.subscription_option) {
++ default:
++ case QSIG_NO_NOTIFICATION:
++ case QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR:
++ q931_party_number_init(&call->redirecting.to.number);
++ call->redirecting.to.number.valid = 1;
++ call->redirecting.to.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ break;
++ case QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR:
++ call->redirecting.to.number = party_id.number;
++ break;
++ }
++
++ call->redirecting.reason = redirectingreason_for_q931(ctrl,
++ invoke->args.qsig.DivertingLegInformation1.diversion_reason);
++ if (call->redirecting.count < PRI_MAX_REDIRECTS) {
++ ++call->redirecting.count;
++ }
++ call->redirecting.state = Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3;
++ break;
++ case ROSE_QSIG_DivertingLegInformation2:
++ call->redirecting.state = Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3;
++ call->redirecting.count =
++ invoke->args.qsig.DivertingLegInformation2.diversion_counter;
++ if (!call->redirecting.count) {
++ /* To be safe, make sure that the count is non-zero. */
++ call->redirecting.count = 1;
++ }
++ call->redirecting.reason = redirectingreason_for_q931(ctrl,
++ invoke->args.qsig.DivertingLegInformation2.diversion_reason);
++
++ /* divertingNr is put in redirecting.from.number */
++ if (invoke->args.qsig.DivertingLegInformation2.diverting_present) {
++ rose_copy_presented_number_unscreened_to_q931(ctrl,
++ &call->redirecting.from.number,
++ &invoke->args.qsig.DivertingLegInformation2.diverting);
++ } else if (!call->redirecting_number_in_message) {
++ q931_party_number_init(&call->redirecting.from.number);
++ call->redirecting.from.number.valid = 1;
++ }
++
++ /* redirectingName is put in redirecting.from.name */
++ if (invoke->args.qsig.DivertingLegInformation2.redirecting_name_present) {
++ rose_copy_name_to_q931(ctrl, &call->redirecting.from.name,
++ &invoke->args.qsig.DivertingLegInformation2.redirecting_name);
++ } else {
++ q931_party_name_init(&call->redirecting.from.name);
++ }
++
++ call->redirecting.orig_reason = PRI_REDIR_UNKNOWN;
++ if (invoke->args.qsig.DivertingLegInformation2.original_diversion_reason_present) {
++ call->redirecting.orig_reason = redirectingreason_for_q931(ctrl,
++ invoke->args.qsig.DivertingLegInformation2.original_diversion_reason);
++ }
++
++ /* originalCalledNr is put in redirecting.orig_called.number */
++ if (invoke->args.qsig.DivertingLegInformation2.original_called_present) {
++ rose_copy_presented_number_unscreened_to_q931(ctrl,
++ &call->redirecting.orig_called.number,
++ &invoke->args.qsig.DivertingLegInformation2.original_called);
++ } else {
++ q931_party_number_init(&call->redirecting.orig_called.number);
++ }
++
++ /* originalCalledName is put in redirecting.orig_called.name */
++ if (invoke->args.qsig.DivertingLegInformation2.original_called_name_present) {
++ rose_copy_name_to_q931(ctrl, &call->redirecting.orig_called.name,
++ &invoke->args.qsig.DivertingLegInformation2.original_called_name);
++ } else {
++ q931_party_name_init(&call->redirecting.orig_called.name);
++ }
++ break;
++ case ROSE_QSIG_DivertingLegInformation3:
++ /*
++ * Unless otherwise indicated by CONNECT, this will be the
++ * remote_id.number.presentation.
++ */
++ if (!invoke->args.qsig.DivertingLegInformation3.presentation_allowed_indicator) {
++ call->redirecting.to.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ if (!call->connected_number_in_message) {
++ call->remote_id.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ }
++ }
++
++ /* redirectionName is put in redirecting.to.name */
++ if (invoke->args.qsig.DivertingLegInformation3.redirection_name_present) {
++ rose_copy_name_to_q931(ctrl, &call->redirecting.to.name,
++ &invoke->args.qsig.DivertingLegInformation3.redirection_name);
++ if (!invoke->args.qsig.DivertingLegInformation3.presentation_allowed_indicator) {
++ call->redirecting.to.name.presentation = PRI_PRES_RESTRICTED;
++ }
++ } else {
++ q931_party_name_init(&call->redirecting.to.name);
++ }
++
++ switch (call->redirecting.state) {
++ case Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3:
++ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (!subcmd) {
++ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
++ break;
++ }
++ /* Setup redirecting subcommand */
++ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
++ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
++ &call->redirecting);
++ break;
++ default:
++ break;
++ }
++ break;
++#if 0 /* Not handled yet */
++ case ROSE_QSIG_CfnrDivertedLegFailed:
++ break;
++#endif /* Not handled yet */
++#if 0 /* Not handled yet */
++ case ROSE_QSIG_MWIActivate:
++ break;
++ case ROSE_QSIG_MWIDeactivate:
++ break;
++ case ROSE_QSIG_MWIInterrogate:
++ break;
++#endif /* Not handled yet */
++ default:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "!! ROSE invoke operation not handled! %s\n",
++ rose_operation2str(invoke->operation));
++ }
++ break;
++ }
+ }
+-
+Index: pri_facility.h
+===================================================================
+--- a/pri_facility.h (.../tags/1.4.10.2) (revision 1357)
++++ b/pri_facility.h (.../branches/1.4) (revision 1357)
+@@ -31,123 +31,21 @@
+ #define _PRI_FACILITY_H
+ #include "pri_q931.h"
+
++/* Forward declare some structs */
++struct fac_extension_header;
++struct rose_msg_invoke;
++struct rose_msg_result;
++struct rose_msg_error;
++struct rose_msg_reject;
++
+ /* Protocol Profile field */
++#define Q932_PROTOCOL_MASK 0x1F
+ #define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
+ #define Q932_PROTOCOL_CMIP 0x12 /* Q.941 */
+ #define Q932_PROTOCOL_ACSE 0x13 /* X.217 & X.227 */
+ #define Q932_PROTOCOL_GAT 0x16
+ #define Q932_PROTOCOL_EXTENSIONS 0x1F
+
+-/* Argument values */
+-#define ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE 0x80
+-#define ROSE_NAME_PRESENTATION_RESTRICTED_NULL 0x87
+-#define ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED 0xA1
+-#define ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE 0xA2
+-#define ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED 0xA3
+-#define ROSE_NAME_NOT_AVAIL 0x84
+-
+-/* Component types */
+-#define COMP_TYPE_INTERPRETATION 0x8B
+-#define COMP_TYPE_NETWORK_PROTOCOL_PROFILE 0x92
+-#define COMP_TYPE_INVOKE 0xA1
+-#define COMP_TYPE_RETURN_RESULT 0xA2
+-#define COMP_TYPE_RETURN_ERROR 0xA3
+-#define COMP_TYPE_REJECT 0xA4
+-#define COMP_TYPE_NFE 0xAA
+-
+-/* Operation ID values */
+-/* Q.952.7 (ECMA-178) ROSE operations (Transfer) */
+-#define ROSE_CALL_TRANSFER_IDENTIFY 7
+-#define ROSE_CALL_TRANSFER_ABANDON 8
+-#define ROSE_CALL_TRANSFER_INITIATE 9
+-#define ROSE_CALL_TRANSFER_SETUP 10
+-#define ROSE_CALL_TRANSFER_ACTIVE 11
+-#define ROSE_CALL_TRANSFER_COMPLETE 12
+-#define ROSE_CALL_TRANSFER_UPDATE 13
+-#define ROSE_SUBADDRESS_TRANSFER 14
+-/* Q.952 ROSE operations (Diverting) */
+-#define ROSE_DIVERTING_LEG_INFORMATION1 18
+-#define ROSE_DIVERTING_LEG_INFORMATION2 0x15
+-#define ROSE_DIVERTING_LEG_INFORMATION3 19
+-/* Q.956 ROSE operations (Advice Of Charge) */
+-#define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE 26
+-#define ROSE_AOC_CHARGING_REQUEST 30
+-#define ROSE_AOC_AOCS_CURRENCY 31
+-#define ROSE_AOC_AOCS_SPECIAL_ARR 32
+-#define ROSE_AOC_AOCD_CURRENCY 33
+-#define ROSE_AOC_AOCD_CHARGING_UNIT 34
+-#define ROSE_AOC_AOCE_CURRENCY 35
+-#define ROSE_AOC_AOCE_CHARGING_UNIT 36
+-#define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
+-/* Q.SIG operations */
+-#define SS_CNID_CALLINGNAME 0
+-#define SS_ANFPR_PATHREPLACEMENT 4
+-#define SS_DIVERTING_LEG_INFORMATION2 21
+-#define SS_MWI_ACTIVATE 80
+-#define SS_MWI_DEACTIVATE 81
+-#define SS_MWI_INTERROGATE 82
+-
+-/* ROSE definitions and data structures */
+-#define INVOKE_IDENTIFIER 0x02
+-#define INVOKE_LINKED_IDENTIFIER 0x80
+-#define INVOKE_NULL_IDENTIFIER __USE_ASN1_NULL
+-
+-/* ASN.1 Identifier Octet - Data types */
+-#define ASN1_TYPE_MASK 0x1f
+-#define ASN1_BOOLEAN 0x01
+-#define ASN1_INTEGER 0x02
+-#define ASN1_BITSTRING 0x03
+-#define ASN1_OCTETSTRING 0x04
+-#define ASN1_NULL 0x05
+-#define ASN1_OBJECTIDENTIFIER 0x06
+-#define ASN1_OBJECTDESCRIPTOR 0x07
+-#define ASN1_EXTERN 0x08
+-#define ASN1_REAL 0x09
+-#define ASN1_ENUMERATED 0x0a
+-#define ASN1_EMBEDDEDPDV 0x0b
+-#define ASN1_UTF8STRING 0x0c
+-#define ASN1_RELATIVEOBJECTID 0x0d
+-/* 0x0e & 0x0f are reserved for future ASN.1 editions */
+-#define ASN1_SEQUENCE 0x10
+-#define ASN1_SET 0x11
+-#define ASN1_NUMERICSTRING 0x12
+-#define ASN1_PRINTABLESTRING 0x13
+-#define ASN1_TELETEXSTRING 0x14
+-#define ASN1_IA5STRING 0x16
+-#define ASN1_UTCTIME 0x17
+-#define ASN1_GENERALIZEDTIME 0x18
+-
+-/* ASN.1 Identifier Octet - Tags */
+-#define ASN1_TAG_0 0x00
+-#define ASN1_TAG_1 0x01
+-#define ASN1_TAG_2 0x02
+-#define ASN1_TAG_3 0x03
+-#define ASN1_TAG_4 0x04
+-#define ASN1_TAG_5 0x05
+-#define ASN1_TAG_6 0x06
+-#define ASN1_TAG_7 0x07
+-#define ASN1_TAG_8 0x08
+-#define ASN1_TAG_9 0x09
+-
+-/* ASN.1 Identifier Octet - Primitive/Constructor Bit */
+-#define ASN1_PC_MASK 0x20
+-#define ASN1_PRIMITIVE 0x00
+-#define ASN1_CONSTRUCTOR 0x20
+-
+-/* ASN.1 Identifier Octet - Clan Bits */
+-#define ASN1_CLAN_MASK 0xc0
+-#define ASN1_UNIVERSAL 0x00
+-#define ASN1_APPLICATION 0x40
+-#define ASN1_CONTEXT_SPECIFIC 0x80
+-#define ASN1_PRIVATE 0xc0
+-
+-/* ASN.1 Length masks */
+-#define ASN1_LEN_INDEF 0x80
+-
+-
+-#define INVOKE_OPERATION_INT __USE_ASN1_INTEGER
+-#define INVOKE_OBJECT_ID __USE_ASN1_OBJECTIDENTIFIER
+-
+ /* Q.952 Divert cause */
+ #define Q952_DIVERT_REASON_UNKNOWN 0x00
+ #define Q952_DIVERT_REASON_CFU 0x01
+@@ -169,138 +67,112 @@
+ #define Q932_TON_SUBSCRIBER 0x04
+ #define Q932_TON_ABBREVIATED 0x06
+
+-/* RLT related Operations */
+-#define RLT_SERVICE_ID 0x3e
+-#define RLT_OPERATION_IND 0x01
+-#define RLT_THIRD_PARTY 0x02
++/* Q.SIG Subscription Option. Listed in ECMA-174 */
++#define QSIG_NO_NOTIFICATION 0x00
++#define QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR 0x01
++#define QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR 0x02
+
+-struct rose_component {
+- u_int8_t type;
+- u_int8_t len;
+- u_int8_t data[0];
++/*! Reasons an APDU callback is called. */
++enum APDU_CALLBACK_REASON {
++ /*!
++ * \brief Send setup error. Abort and cleanup.
++ * \note The message may or may not actually get sent.
++ * \note The callback cannot generate an event subcmd.
++ * \note The callback should not send messages. Out of order messages will result.
++ */
++ APDU_CALLBACK_REASON_ERROR,
++ /*!
++ * \brief Abort and cleanup.
++ * \note The APDU queue is being destroyed.
++ * \note The callback cannot generate an event subcmd.
++ * \note The callback cannot send messages as the call is likely being destroyed.
++ */
++ APDU_CALLBACK_REASON_CLEANUP,
++ /*!
++ * \brief Timeout waiting for responses to the message.
++ * \note The callback can generate an event subcmd.
++ * \note The callback can send messages.
++ */
++ APDU_CALLBACK_REASON_TIMEOUT,
++ /*!
++ * \brief Received a facility response message.
++ * \note The callback can generate an event subcmd.
++ * \note The callback can send messages.
++ */
++ APDU_CALLBACK_REASON_MSG_RESULT,
++ /*!
++ * \brief Received a facility error message.
++ * \note The callback can generate an event subcmd.
++ * \note The callback can send messages.
++ */
++ APDU_CALLBACK_REASON_MSG_ERROR,
++ /*!
++ * \brief Received a facility reject message.
++ * \note The callback can generate an event subcmd.
++ * \note The callback can send messages.
++ */
++ APDU_CALLBACK_REASON_MSG_REJECT,
+ };
+
+-#if 1
+- #define GET_COMPONENT(component, idx, ptr, length) \
+- if ((idx)+2 > (length)) \
+- break; \
+- (component) = (struct rose_component*)&((ptr)[idx]); \
+- if ((idx)+(component)->len+2 > (length)) { \
+- if ((component)->len != ASN1_LEN_INDEF) \
+- pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
+- }
+-#else /* Debugging */
+- #define GET_COMPONENT(component, idx, ptr, length) \
+- if ((idx)+2 > (length)) \
+- break; \
+- (component) = (struct rose_component*)&((ptr)[idx]); \
+- if ((idx)+(component)->len+2 > (length)) { \
+- if ((component)->len != 128) \
+- pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
+- } \
+- pri_message(pri, "XX %s:%d Got component %d (0x%02X), length %d\n", __FUNCTION__, __LINE__, (component)->type, (component)->type, (component)->len); \
+- if ((component)->len > 0) { \
+- int zzz; \
+- pri_message(pri, "XX Data:"); \
+- for (zzz = 0; zzz < (component)->len; ++zzz) \
+- pri_message(pri, " %02X", (component)->data[zzz]); \
+- pri_message(pri, "\n"); \
+- }
+-#endif
++union apdu_msg_data {
++ const struct rose_msg_result *result;
++ const struct rose_msg_error *error;
++ const struct rose_msg_reject *reject;
++};
+
+-#define NEXT_COMPONENT(component, idx) \
+- (idx) += (component)->len + 2
++union apdu_callback_param {
++ void *ptr;
++ long value;
++ char pad[8];
++};
+
+-#define SUB_COMPONENT(component, idx) \
+- (idx) += 2
++struct apdu_callback_data {
++ /*! APDU invoke id to match with any response messages. (Result/Error/Reject) */
++ int invoke_id;
++ /*!
++ * \brief Time to wait for responses to APDU in ms.
++ * \note Set to 0 if send the message only.
++ * \note Set to less than 0 for PRI_TIMER_T_RESPONSE time.
++ */
++ int timeout_time;
++ /*!
++ * \brief APDU callback function.
++ *
++ * \param reason Reason callback is called.
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg.
++ * \param apdu APDU queued entry. Do not change!
++ * \param msg APDU response message data. (NULL if was not the reason called.)
++ *
++ * \note
++ * A callback must be supplied if the sender cares about any APDU_CALLBACK_REASON.
++ *
++ * \return TRUE if no more responses are expected.
++ */
++ int (*callback)(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const union apdu_msg_data *msg);
++ /*! \brief Sender data for the callback function to identify the particular APDU. */
++ union apdu_callback_param user;
++};
+
+-#define CHECK_COMPONENT(component, comptype, message) \
+- if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
+- pri_message(pri, (message), (component)->type); \
+- asn1_dump(pri, (component), (component)->len+2); \
+- break; \
+- }
+-
+-#define ASN1_GET_INTEGER(component, variable) \
+- do { \
+- int comp_idx; \
+- (variable) = 0; \
+- for (comp_idx = 0; comp_idx < (component)->len; ++comp_idx) \
+- (variable) = ((variable) << 8) | (component)->data[comp_idx]; \
+- } while (0)
++struct apdu_event {
++ /*! Linked list pointer */
++ struct apdu_event *next;
++ /*! TRUE if this APDU has been sent. */
++ int sent;
++ /*! What message to send the ADPU in */
++ int message;
++ /*! Sender supplied information to handle APDU response messages. */
++ struct apdu_callback_data response;
++ /*! Q.931 call leg. (Needed for the APDU timeout.) */
++ struct q931_call *call;
++ /*! Response timeout timer. */
++ int timer;
++ /*! Length of ADPU */
++ int apdu_len;
++ /*! ADPU to send */
++ unsigned char apdu[255];
++};
+
+-#define ASN1_FIXUP_LEN(component, size) \
+- do { \
+- if ((component)->len == ASN1_LEN_INDEF) \
+- size += 2; \
+- } while (0)
+-
+-#define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \
+- do { \
+- (component) = (struct rose_component *)&((ptr)[(idx)]); \
+- (component)->type = (comptype); \
+- (component)->len = 0; \
+- (idx) += 2; \
+- } while (0)
+-
+-#define ASN1_ADD_BYTECOMP(component, comptype, ptr, idx, value) \
+- do { \
+- (component) = (struct rose_component *)&((ptr)[(idx)]); \
+- (component)->type = (comptype); \
+- (component)->len = 1; \
+- (component)->data[0] = (value); \
+- (idx) += 3; \
+- } while (0)
+-
+-#define ASN1_ADD_WORDCOMP(component, comptype, ptr, idx, value) \
+- do { \
+- int __val = (value); \
+- int __i = 0; \
+- (component) = (struct rose_component *)&((ptr)[(idx)]); \
+- (component)->type = (comptype); \
+- if ((__val >> 24)) \
+- (component)->data[__i++] = (__val >> 24) & 0xff; \
+- if ((__val >> 16)) \
+- (component)->data[__i++] = (__val >> 16) & 0xff; \
+- if ((__val >> 8)) \
+- (component)->data[__i++] = (__val >> 8) & 0xff; \
+- (component)->data[__i++] = __val & 0xff; \
+- (component)->len = __i; \
+- (idx) += 2 + __i; \
+- } while (0)
+-
+-#define ASN1_PUSH(stack, stackpointer, component) \
+- (stack)[(stackpointer)++] = (component)
+-
+-#define ASN1_FIXUP(stack, stackpointer, data, idx) \
+- do { \
+- --(stackpointer); \
+- (stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
+- } while (0)
+-
+-/* Decoder for the invoke ROSE component */
+-int rose_invoke_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
+-
+-/* Decoder for the return result ROSE component */
+-int rose_return_result_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
+-
+-/* Decoder for the return error ROSE component */
+-int rose_return_error_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
+-
+-/* Decoder for the reject ROSE component */
+-int rose_reject_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
+-
+-int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
+-
+-int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
+-
+-/* Get Name types from ASN.1 */
+-int asn1_name_decode(void * data, int len, char *namebuf, int buflen);
+-
+-int typeofnumber_from_q931(struct pri *pri, int ton);
+-
+-int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
+-
+ /* Queues an MWI apdu on a the given call */
+ int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
+
+@@ -310,21 +182,31 @@
+ int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
+
+ int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason);
++int send_reroute_request(struct pri *ctrl, q931_call *call, const struct q931_party_id *caller, const struct q931_party_redirecting *deflection, int subscription_option);
+
+ /* starts a QSIG Path Replacement */
+ int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
+
+-/* Use this function to queue a facility-IE born APDU onto a call
+- * call is the call to use, messagetype is any one of the Q931 messages,
+- * apdu is the apdu data, apdu_len is the length of the apdu data */
+-int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data);
++int send_call_transfer_complete(struct pri *pri, q931_call *call, int call_status);
+
+-/* Used by q931.c to cleanup the apdu queue upon destruction of a call */
+-int pri_call_apdu_queue_cleanup(q931_call *call);
++int rose_diverting_leg_information1_encode(struct pri *pri, q931_call *call);
++int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int messagetype);
+
++int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype);
++int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
++
++int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response);
++void pri_call_apdu_queue_cleanup(q931_call *call);
++void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed);
++
+ /* Adds the "standard" APDUs to a call */
+ int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
+
+-int asn1_dump(struct pri *pri, void *comp, int len);
++void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1, const unsigned char *end);
+
++void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_invoke *invoke);
++void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_result *result);
++void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_error *error);
++void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
++
+ #endif /* _PRI_FACILITY_H */
+Index: libpri.h
+===================================================================
+--- a/libpri.h (.../tags/1.4.10.2) (revision 1357)
++++ b/libpri.h (.../branches/1.4) (revision 1357)
+@@ -26,7 +26,14 @@
+ * provided with that copy of Asterisk, instead of the license
+ * terms granted here.
+ */
+-
++
++/*
++ * NOTE:
++ * All new global identifiers that are added to this file MUST be
++ * prefixed with PRI_ or pri_ to indicate that they are part of this
++ * library and to reduce potential naming conflicts.
++ */
++
+ #ifndef _LIBPRI_H
+ #define _LIBPRI_H
+
+@@ -73,7 +80,8 @@
+ #define PRI_EVENT_ANSWER 8 /* Call has been answered (CONNECT) */
+ #define PRI_EVENT_HANGUP_ACK 9 /* Call hangup has been acknowledged */
+ #define PRI_EVENT_RESTART_ACK 10 /* Restart complete on a given channel (RESTART_ACKNOWLEDGE) */
+-#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility */
++#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility (DEPRECATED) */
++#define PRI_EVENT_FACILITY 11 /* Facility received (FACILITY) */
+ #define PRI_EVENT_INFO_RECEIVED 12 /* Additional info (digits) received (INFORMATION) */
+ #define PRI_EVENT_PROCEEDING 13 /* When we get CALL_PROCEEDING */
+ #define PRI_EVENT_SETUP_ACK 14 /* When we get SETUP_ACKNOWLEDGE */
+@@ -81,6 +89,14 @@
+ #define PRI_EVENT_NOTIFY 16 /* Notification received (NOTIFY) */
+ #define PRI_EVENT_PROGRESS 17 /* When we get PROGRESS */
+ #define PRI_EVENT_KEYPAD_DIGIT 18 /* When we receive during ACTIVE state (INFORMATION) */
++#define PRI_EVENT_SERVICE 19 /* SERVICE maintenance message */
++#define PRI_EVENT_SERVICE_ACK 20 /* SERVICE maintenance acknowledgement message */
++#define PRI_EVENT_HOLD 21 /* HOLD request received */
++#define PRI_EVENT_HOLD_ACK 22 /* HOLD_ACKNOWLEDGE received */
++#define PRI_EVENT_HOLD_REJ 23 /* HOLD_REJECT received */
++#define PRI_EVENT_RETRIEVE 24 /* RETRIEVE request received */
++#define PRI_EVENT_RETRIEVE_ACK 25 /* RETRIEVE_ACKNOWLEDGE received */
++#define PRI_EVENT_RETRIEVE_REJ 26 /* RETRIEVE_REJECT received */
+
+ /* Simple states */
+ #define PRI_STATE_DOWN 0
+@@ -101,13 +117,13 @@
+ #define PRI_PROG_CALLER_RETURNED_TO_ISDN (1 << 9)
+
+ /* Numbering plan identifier */
+-#define PRI_NPI_UNKNOWN 0x0
+-#define PRI_NPI_E163_E164 0x1
+-#define PRI_NPI_X121 0x3
+-#define PRI_NPI_F69 0x4
+-#define PRI_NPI_NATIONAL 0x8
+-#define PRI_NPI_PRIVATE 0x9
+-#define PRI_NPI_RESERVED 0xF
++#define PRI_NPI_UNKNOWN 0x0 /*!< Unknown numbering plan */
++#define PRI_NPI_E163_E164 0x1 /*!< ISDN/telephony numbering plan (public) */
++#define PRI_NPI_X121 0x3 /*!< Data numbering plan */
++#define PRI_NPI_F69 0x4 /*!< Telex numbering plan */
++#define PRI_NPI_NATIONAL 0x8 /*!< National standard numbering plan */
++#define PRI_NPI_PRIVATE 0x9 /*!< Private numbering plan */
++#define PRI_NPI_RESERVED 0xF /*!< Reserved for extension */
+
+ /* Type of number */
+ #define PRI_TON_UNKNOWN 0x0
+@@ -135,16 +151,49 @@
+ #define PRI_UNKNOWN 0x0
+
+ /* Presentation */
+-#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
+-#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
+-#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
+-#define PRES_ALLOWED_NETWORK_NUMBER 0x03
+-#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
+-#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
+-#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
+-#define PRES_PROHIB_NETWORK_NUMBER 0x23
+-#define PRES_NUMBER_NOT_AVAILABLE 0x43
++#define PRI_PRES_NUMBER_TYPE 0x03
++#define PRI_PRES_USER_NUMBER_UNSCREENED 0x00
++#define PRI_PRES_USER_NUMBER_PASSED_SCREEN 0x01
++#define PRI_PRES_USER_NUMBER_FAILED_SCREEN 0x02
++#define PRI_PRES_NETWORK_NUMBER 0x03
+
++#define PRI_PRES_RESTRICTION 0x60
++#define PRI_PRES_ALLOWED 0x00
++#define PRI_PRES_RESTRICTED 0x20
++#define PRI_PRES_UNAVAILABLE 0x40
++#define PRI_PRES_RESERVED 0x60
++
++#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED \
++ (PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED)
++
++#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN \
++ (PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_PASSED_SCREEN)
++
++#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN \
++ (PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_FAILED_SCREEN)
++
++#define PRES_ALLOWED_NETWORK_NUMBER \
++ (PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER)
++
++#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED \
++ (PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED)
++
++#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN \
++ (PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_PASSED_SCREEN)
++
++#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN \
++ (PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_FAILED_SCREEN)
++
++#define PRES_PROHIB_NETWORK_NUMBER \
++ (PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER)
++
++#define PRES_NUMBER_NOT_AVAILABLE \
++ (PRI_PRES_UNAVAILABLE | PRI_PRES_NETWORK_NUMBER)
++
++/* Reverse Charging Indication */
++#define PRI_REVERSECHARGE_NONE -1
++#define PRI_REVERSECHARGE_REQUESTED 1
++
+ /* Causes for disconnection */
+ #define PRI_CAUSE_UNALLOCATED 1
+ #define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2 /* !Q.SIG */
+@@ -157,6 +206,7 @@
+ #define PRI_CAUSE_NO_ANSWER 19
+ #define PRI_CAUSE_CALL_REJECTED 21
+ #define PRI_CAUSE_NUMBER_CHANGED 22
++#define PRI_CAUSE_NONSELECTED_USER_CLEARING 26
+ #define PRI_CAUSE_DESTINATION_OUT_OF_ORDER 27
+ #define PRI_CAUSE_INVALID_NUMBER_FORMAT 28
+ #define PRI_CAUSE_FACILITY_REJECTED 29 /* !Q.SIG */
+@@ -169,6 +219,7 @@
+ #define PRI_CAUSE_ACCESS_INFO_DISCARDED 43 /* !Q.SIG */
+ #define PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 44
+ #define PRI_CAUSE_PRE_EMPTED 45 /* !Q.SIG */
++#define PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED 47
+ #define PRI_CAUSE_FACILITY_NOT_SUBSCRIBED 50 /* !Q.SIG */
+ #define PRI_CAUSE_OUTGOING_CALL_BARRED 52 /* !Q.SIG */
+ #define PRI_CAUSE_INCOMING_CALL_BARRED 54 /* !Q.SIG */
+@@ -259,8 +310,8 @@
+ #define PRI_RATE_ADAPT_ASYNC 0x40
+
+ /* Notifications */
+-#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended */
+-#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed */
++#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended (Q.931) (Call is placed on hold) */
++#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed (Q.931) (Call is taken off hold) */
+ #define PRI_NOTIFY_BEARER_CHANGE 0x02 /* Bearer service change (DSS1) */
+ #define PRI_NOTIFY_ASN1_COMPONENT 0x03 /* ASN.1 encoded component (DSS1) */
+ #define PRI_NOTIFY_COMPLETION_DELAY 0x04 /* Call completion delay */
+@@ -275,12 +326,12 @@
+ #define PRI_NOTIFY_CONF_OTHER_DISCONNECTED 0x4a /* Other party disconnected */
+ #define PRI_NOTIFY_CONF_FLOATING 0x4b /* Conference floating */
+ #define PRI_NOTIFY_WAITING_CALL 0x60 /* Call is waiting call */
+-#define PRI_NOTIFY_DIVERSION_ACTIVATED 0x68 /* Diversion activated (DSS1) */
+-#define PRI_NOTIFY_TRANSFER_ALERTING 0x69 /* Call transfer, alerting */
+-#define PRI_NOTIFY_TRANSFER_ACTIVE 0x6a /* Call transfer, active */
++#define PRI_NOTIFY_DIVERSION_ACTIVATED 0x68 /* Diversion activated (DSS1) (cfu, cfb, cfnr) (EN 300 207-1 Section 7.2.1) */
++#define PRI_NOTIFY_TRANSFER_ALERTING 0x69 /* Call transfer, alerting (EN 300 369-1 Section 7.2) */
++#define PRI_NOTIFY_TRANSFER_ACTIVE 0x6a /* Call transfer, active(answered) (EN 300 369-1 Section 7.2) */
+ #define PRI_NOTIFY_REMOTE_HOLD 0x79 /* Remote hold */
+ #define PRI_NOTIFY_REMOTE_RETRIEVAL 0x7a /* Remote retrieval */
+-#define PRI_NOTIFY_CALL_DIVERTING 0x7b /* Call is diverting */
++#define PRI_NOTIFY_CALL_DIVERTING 0x7b /* Call is diverting (EN 300 207-1 Section 7.2.1) */
+
+ #define PRI_COPY_DIGITS_CALLED_NUMBER
+
+@@ -305,6 +356,200 @@
+
+ typedef struct q931_call q931_call;
+
++/* Name character set enumeration values */
++#define PRI_CHAR_SET_UNKNOWN 0
++#define PRI_CHAR_SET_ISO8859_1 1
++#define PRI_CHAR_SET_WITHDRAWN 2
++#define PRI_CHAR_SET_ISO8859_2 3
++#define PRI_CHAR_SET_ISO8859_3 4
++#define PRI_CHAR_SET_ISO8859_4 5
++#define PRI_CHAR_SET_ISO8859_5 6
++#define PRI_CHAR_SET_ISO8859_7 7
++#define PRI_CHAR_SET_ISO10646_BMPSTRING 8
++#define PRI_CHAR_SET_ISO10646_UTF_8STRING 9
++
++/*! \brief Q.SIG name information. */
++struct pri_party_name {
++ /*! \brief TRUE if the name information is valid/present */
++ int valid;
++ /*!
++ * \brief Q.931 presentation-indicator encoded field
++ * \note Must tollerate the Q.931 screening-indicator field values being present.
++ */
++ int presentation;
++ /*!
++ * \brief Character set the name is using.
++ * \details
++ * unknown(0),
++ * iso8859-1(1),
++ * enum-value-withdrawn-by-ITU-T(2)
++ * iso8859-2(3),
++ * iso8859-3(4),
++ * iso8859-4(5),
++ * iso8859-5(6),
++ * iso8859-7(7),
++ * iso10646-BmpString(8),
++ * iso10646-utf-8String(9)
++ * \details
++ * Set to iso8859-1(1) if unsure what to use.
++ */
++ int char_set;
++ /*! \brief Name data with null terminator. */
++ char str[64];
++};
++
++struct pri_party_number {
++ /*! \brief TRUE if the number information is valid/present */
++ int valid;
++ /*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
++ int presentation;
++ /*! \brief Q.931 Type-Of-Number and numbering-plan encoded fields */
++ int plan;
++ /*! \brief Number data with null terminator. */
++ char str[64];
++};
++
++/*!
++ * \note This structure is a place holder for possible future subaddress support
++ * to maintain ABI compatibility.
++ */
++struct pri_party_subaddress {
++ /*! \brief TRUE if the subaddress information is valid/present */
++ int valid;
++ /*!
++ * \brief Subaddress type.
++ * \details
++ * nsap(0),
++ * user_specified(2)
++ */
++ int type;
++ /*!
++ * \brief TRUE if odd number of address signals
++ * \note The odd/even indicator is used when the type of subaddress is
++ * user_specified and the coding is BCD.
++ */
++ int odd_even_indicator;
++ /*! \brief Length of the subaddress data */
++ int length;
++ /*!
++ * \brief Subaddress data with null terminator.
++ * \note The null terminator is a convenience only since the data could be
++ * BCD/binary and thus have a null byte as part of the contents.
++ */
++ unsigned char data[32];
++};
++
++/*! \brief Information needed to identify an endpoint in a call. */
++struct pri_party_id {
++ /*! \brief Subscriber name */
++ struct pri_party_name name;
++ /*! \brief Subscriber phone number */
++ struct pri_party_number number;
++ /*! \brief Subscriber subaddress */
++ struct pri_party_subaddress subaddress;
++};
++
++/*! \brief Connected Line/Party information */
++struct pri_party_connected_line {
++ /*! Connected party ID */
++ struct pri_party_id id;
++};
++
++/*!
++ * \brief Redirecting Line information.
++ * \details
++ * RDNIS (Redirecting Directory Number Information Service)
++ * Where a call diversion or transfer was invoked.
++ */
++struct pri_party_redirecting {
++ /*! Who is redirecting the call (Sent to the party the call is redirected toward) */
++ struct pri_party_id from;
++ /*! Call is redirecting to a new party (Sent to the caller) */
++ struct pri_party_id to;
++ /*! Originally called party (in cases of multiple redirects) */
++ struct pri_party_id orig_called;
++ /*! Number of times the call was redirected */
++ int count;
++ /*! Original reason for redirect (in cases of multiple redirects) */
++ int orig_reason;
++ /*! Redirection reason */
++ int reason;
++};
++
++/*!
++ * \brief Information for rerouting/deflecting the call.
++ */
++struct pri_rerouting_data {
++ /*!
++ * \brief Updated caller-id information.
++ * \note The information may have been altered by procedure in the private network.
++ */
++ struct pri_party_id caller;
++ /*!
++ * \note
++ * deflection.to is the new called number and must always be present.
++ */
++ struct pri_party_redirecting deflection;
++ /*!
++ * \brief Diverting user subscription option to specify if caller is notified.
++ * \details
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2),
++ * notApplicable(3) (Status only.)
++ */
++ int subscription_option;
++ /*! Invocation ID to use when sending a reply to the call rerouting/deflection request. */
++ int invoke_id;
++};
++
++/* Subcommands derived from supplementary services. */
++#define PRI_SUBCMD_REDIRECTING 1
++#define PRI_SUBCMD_CONNECTED_LINE 2
++#define PRI_SUBCMD_REROUTING 3
++
++
++struct pri_subcommand {
++ /*! PRI_SUBCMD_xxx defined values */
++ int cmd;
++ union {
++ /*! Reserve room for possible expansion to maintain ABI compatibility. */
++ char reserve_space[512];
++ struct pri_party_connected_line connected_line;
++ struct pri_party_redirecting redirecting;
++ struct pri_rerouting_data rerouting;
++ } u;
++};
++
++/* Max number of subcommands per event message */
++#define PRI_MAX_SUBCOMMANDS 8
++
++struct pri_subcommands {
++ int counter_subcmd;
++ struct pri_subcommand subcmd[PRI_MAX_SUBCOMMANDS];
++};
++
++
++/*
++ * Event channel parameter encoding:
++ * 3322 2222 2222 1111 1111 1100 0000 0000
++ * 1098 7654 3210 9876 5432 1098 7654 3210
++ * xxxx xxxx xxxx xEDC BBBBBBBBB AAAAAAAAA
++ *
++ * Bit field
++ * A - B channel
++ * B - Span (DS1) (0 - 127)
++ * C - DS1 Explicit bit
++ * D - D channel (cis_call) bit (status only)
++ * E - Call is held bit (status only)
++ *
++ * B channel values:
++ * 0 - No channel (ISDN uses for call waiting feature)
++ * 1-127 - B channel #
++ * 0xFF - Any channel (Also if whole channel value is -1 in event)
++ */
++
++
+ typedef struct pri_event_generic {
+ /* Events with no additional information fall in this category */
+ int e;
+@@ -328,6 +573,7 @@
+ int progressmask;
+ q931_call *call;
+ char useruserinfo[260]; /* User->User info */
++ struct pri_subcommands *subcmds;
+ } pri_event_ringing;
+
+ typedef struct pri_event_answer {
+@@ -338,8 +584,10 @@
+ int progressmask;
+ q931_call *call;
+ char useruserinfo[260]; /* User->User info */
++ struct pri_subcommands *subcmds;
+ } pri_event_answer;
+
++/*! Deprecated replaced by struct pri_event_facility. */
+ typedef struct pri_event_facname {
+ int e;
+ char callingname[256];
+@@ -351,6 +599,24 @@
+ int callingplan; /* Dialing plan of Calling entity */
+ } pri_event_facname;
+
++struct pri_event_facility {
++ int e;
++ char callingname[256]; /*!< Deprecated, preserved for struct pri_event_facname compatibility */
++ char callingnum[256]; /*!< Deprecated, preserved for struct pri_event_facname compatibility */
++ int channel;
++ int cref;
++ /*!
++ * \brief Master call or normal call.
++ * \note Call pointer known about by upper layer.
++ * \note NULL if dummy call reference.
++ */
++ q931_call *call;
++ int callingpres; /*!< Presentation of Calling CallerID (Deprecated, preserved for struct pri_event_facname compatibility) */
++ int callingplan; /*!< Dialing plan of Calling entity (Deprecated, preserved for struct pri_event_facname compatibility) */
++ struct pri_subcommands *subcmds;
++ q931_call *subcall; /*!< Subcall to send any reply toward. */
++};
++
+ #define PRI_CALLINGPLANANI
+ #define PRI_CALLINGPLANRDNIS
+ typedef struct pri_event_ring {
+@@ -376,13 +642,18 @@
+ int layer1; /* User layer 1 */
+ int complete; /* Have we seen "Complete" i.e. no more number? */
+ q931_call *call; /* Opaque call pointer */
+- char callingsubaddr[256]; /* Calling parties subaddress */
++ char callingsubaddr[256]; /* Calling parties subaddress, backwards compatibility */
+ int progress;
+ int progressmask;
+ char origcalledname[256];
+ char origcallednum[256];
+ int callingplanorigcalled; /* Dialing plan of Originally Called Number */
+ int origredirectingreason;
++ int reversecharge;
++ struct pri_subcommands *subcmds;
++ struct pri_party_id calling; /* Calling Party's info, initially subaddress' */
++ struct pri_party_subaddress called_subaddress; /* Called party's subaddress */
++ char keypad_digits[64]; /* Keypad digits in the SETUP message. */
+ } pri_event_ring;
+
+ typedef struct pri_event_hangup {
+@@ -390,10 +661,23 @@
+ int channel; /* Channel requested */
+ int cause;
+ int cref;
+- q931_call *call; /* Opaque call pointer */
++ q931_call *call; /* Opaque call pointer of call hanging up. */
+ long aoc_units; /* Advise of Charge number of charged units */
+ char useruserinfo[260]; /* User->User info */
+-} pri_event_hangup;
++ struct pri_subcommands *subcmds;
++ /*!
++ * \brief Opaque held call pointer for possible transfer to active call.
++ * \note The call_held and call_active pointers must not be NULL if
++ * transfer held call on disconnect is available.
++ */
++ q931_call *call_held;
++ /*!
++ * \brief Opaque active call pointer for possible transfer with held call.
++ * \note The call_held and call_active pointers must not be NULL if
++ * transfer held call on disconnect is available.
++ */
++ q931_call *call_active;
++} pri_event_hangup;
+
+ typedef struct pri_event_restart_ack {
+ int e;
+@@ -409,18 +693,22 @@
+ int progressmask;
+ int cause;
+ q931_call *call;
++ struct pri_subcommands *subcmds;
+ } pri_event_proceeding;
+-
++
+ typedef struct pri_event_setup_ack {
+ int e;
+ int channel;
+ q931_call *call;
++ struct pri_subcommands *subcmds;
+ } pri_event_setup_ack;
+
+ typedef struct pri_event_notify {
+ int e;
+ int channel;
+ int info;
++ struct pri_subcommands *subcmds;
++ q931_call *call;
+ } pri_event_notify;
+
+ typedef struct pri_event_keypad_digit {
+@@ -428,14 +716,72 @@
+ int channel;
+ q931_call *call;
+ char digits[64];
++ struct pri_subcommands *subcmds;
+ } pri_event_keypad_digit;
+
++typedef struct pri_event_service {
++ int e;
++ int channel;
++ int changestatus;
++} pri_event_service;
++
++typedef struct pri_event_service_ack {
++ int e;
++ int channel;
++ int changestatus;
++} pri_event_service_ack;
++
++struct pri_event_hold {
++ int e;
++ int channel;
++ q931_call *call;
++ struct pri_subcommands *subcmds;
++};
++
++struct pri_event_hold_ack {
++ int e;
++ int channel;
++ q931_call *call;
++ struct pri_subcommands *subcmds;
++};
++
++struct pri_event_hold_rej {
++ int e;
++ int channel;
++ q931_call *call;
++ int cause;
++ struct pri_subcommands *subcmds;
++};
++
++struct pri_event_retrieve {
++ int e;
++ int channel;
++ q931_call *call;
++ int flexible; /* Are we flexible with our channel selection? */
++ struct pri_subcommands *subcmds;
++};
++
++struct pri_event_retrieve_ack {
++ int e;
++ int channel;
++ q931_call *call;
++ struct pri_subcommands *subcmds;
++};
++
++struct pri_event_retrieve_rej {
++ int e;
++ int channel;
++ q931_call *call;
++ int cause;
++ struct pri_subcommands *subcmds;
++};
++
+ typedef union {
+ int e;
+ pri_event_generic gen; /* Generic view */
+ pri_event_restart restart; /* Restart view */
+ pri_event_error err; /* Error view */
+- pri_event_facname facname; /* Caller*ID Name on Facility */
++ pri_event_facname facname; /* Caller*ID Name on Facility (Deprecated, use pri_event.facility) */
+ pri_event_ring ring; /* Ring */
+ pri_event_hangup hangup; /* Hang up */
+ pri_event_ringing ringing; /* Ringing */
+@@ -445,6 +791,15 @@
+ pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
+ pri_event_notify notify; /* Notification */
+ pri_event_keypad_digit digit; /* Digits that come during a call */
++ pri_event_service service; /* service message */
++ pri_event_service_ack service_ack; /* service acknowledgement message */
++ struct pri_event_facility facility;
++ struct pri_event_hold hold;
++ struct pri_event_hold_ack hold_ack;
++ struct pri_event_hold_rej hold_rej;
++ struct pri_event_retrieve retrieve;
++ struct pri_event_retrieve_ack retrieve_ack;
++ struct pri_event_retrieve_rej retrieve_rej;
+ } pri_event;
+
+ struct pri;
+@@ -456,7 +811,7 @@
+
+ /* Create a D-channel on a given file descriptor. The file descriptor must be a
+ channel operating in HDLC mode with FCS computed by the fd's driver. Also it
+- must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
++ must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
+ must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
+ struct pri *pri_new(int fd, int nodetype, int switchtype);
+ struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
+@@ -521,7 +876,7 @@
+
+ #define PRI_KEYPAD_FACILITY_TX
+ /* Send a keypad facility string of digits */
+-int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits);
++int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
+
+ /* Answer the incomplete(call without called number) call on the given channel.
+ Set non-isdn to non-zero if you are not connecting to ISDN equipment */
+@@ -531,6 +886,18 @@
+ Set non-isdn to non-zero if you are not connecting to ISDN equipment */
+ int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
+
++/*!
++ * \brief Give connected line information to a call
++ * \note Could be used instead of pri_sr_set_caller_party() before calling pri_setup().
++ */
++int pri_connected_line_update(struct pri *pri, q931_call *call, const struct pri_party_connected_line *connected);
++
++/*!
++ * \brief Give redirection information to a call
++ * \note Could be used instead of pri_sr_set_redirecting_parties() before calling pri_setup().
++ */
++int pri_redirecting_update(struct pri *pri, q931_call *call, const struct pri_party_redirecting *redirecting);
++
+ /* Set CRV reference for GR-303 calls */
+
+
+@@ -556,9 +923,20 @@
+
+ int pri_reset(struct pri *pri, int channel);
+
++/* handle b-channel maintenance messages */
++extern int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus);
++
+ /* Create a new call */
+ q931_call *pri_new_call(struct pri *pri);
+
++/*!
++ * \brief Deterimine if the given call control pointer is a dummy call.
++ *
++ * \retval TRUE if given call is a dummy call.
++ * \retval FALSE otherwise.
++ */
++int pri_is_dummy_call(q931_call *call);
++
+ /* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
+ int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
+
+@@ -573,8 +951,8 @@
+ extern pri_event *pri_schedule_run_tv(struct pri *pri, const struct timeval *now);
+
+ int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
+- int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
+- char *called,int calledplan, int ulayer1);
++ int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
++ char *called, int calledplan, int ulayer1);
+
+ struct pri_sr *pri_sr_new(void);
+ void pri_sr_free(struct pri_sr *sr);
+@@ -582,25 +960,91 @@
+ int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
+ int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
+ int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
++
++/*!
++ * \brief Set the caller party ID information in the call SETUP record.
++ *
++ * \param sr New call SETUP record.
++ * \param caller Caller party ID information to set.
++ *
++ * \return Nothing
++ */
++void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller);
++/*! \note Use pri_sr_set_caller_party() instead to pass more precise caller information. */
+ int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
++
++/*!
++ * \brief Set the calling subaddress information in the call SETUP record.
++ *
++ * \param sr New call SETUP record.
++ * \param subaddress information to set.
++ *
++ * \return Nothing
++ */
++void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress);
++
++/*!
++ * \brief Set the called subaddress information in the call SETUP record.
++ *
++ * \param sr New call SETUP record.
++ * \param subaddress information to set.
++ *
++ * \return Nothing
++ */
++void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress);
++
++/*!
++ * \brief Set the redirecting information in the call SETUP record.
++ *
++ * \param sr New call SETUP record.
++ * \param caller Redirecting information to set.
++ *
++ * \return Nothing
++ */
++void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting);
++/*! \note Use pri_sr_set_redirecting_parties() instead to pass more precise redirecting information. */
+ int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
++
++/*!
++ * \brief Set the keypad digits in the call SETUP record.
++ *
++ * \param sr New call SETUP record.
++ * \param keypad_digits Keypad digits to send.
++ *
++ * \return Nothing
++ */
++void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits);
++
+ #define PRI_USER_USER_TX
+ /* Set the user user field. Warning! don't send binary data accross this field */
+ void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
++void pri_sr_set_reversecharge(struct pri_sr *sr, int requested);
+
+ void pri_call_set_useruser(q931_call *sr, const char *userchars);
+
+ int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
+
+-/* Set a call has a call indpendent signalling connection (i.e. no bchan) */
++/*!
++ * \brief Set a call as a call indpendent signalling connection (i.e. no bchan)
++ * \note Call will automaticlly disconnect after signalling sent.
++ */
+ int pri_sr_set_connection_call_independent(struct pri_sr *req);
+
++/*!
++ * \brief Set a call as a call indpendent signalling connection (i.e. no bchan)
++ * \note Call will stay connected until explicitly disconnected.
++ */
++int pri_sr_set_no_channel_call(struct pri_sr *req);
++
+ /* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, deactivates */
+ int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
+
+ /* Send an MWI deactivate request to a remote location */
+ int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
+
++/* Set service message support flag */
++int pri_set_service_message_support(struct pri *pri, int supportflag);
++
+ #define PRI_2BCT
+ /* Attempt to pass the channels back to the NET side if compatable and
+ * suscribed. Sometimes called 2 bchannel transfer (2BCT) */
+@@ -656,48 +1100,208 @@
+
+ int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason);
+
++/*!
++ * \brief Set the call deflection/rerouting feature enable flag.
++ *
++ * \param ctrl D channel controller.
++ * \param enable TRUE to enable call deflection/rerouting feature.
++ *
++ * \return Nothing
++ */
++void pri_reroute_enable(struct pri *ctrl, int enable);
++
++/*!
++ * \brief Send the CallRerouting/CallDeflection message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg.
++ * \param caller Call rerouting/deflecting updated caller data. (NULL if data not updated.)
++ * \param deflection Call rerouting/deflecting redirection data.
++ * \param subscription_option Diverting user subscription option to specify if caller is notified.
++ *
++ * \note
++ * deflection->to is the new called number and must always be present.
++ * \note
++ * subscription option:
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_id *caller, const struct pri_party_redirecting *deflection, int subscription_option);
++
++enum PRI_REROUTING_RSP_CODE {
++ /*!
++ * Rerouting invocation accepted and the network provider option
++ * "served user call retention on invocation of diversion"
++ * is "clear call on invocation".
++ */
++ PRI_REROUTING_RSP_OK_CLEAR,
++ /*!
++ * Rerouting invocation accepted and the network provider option
++ * "served user call retention on invocation of diversion"
++ * is "retain call until alerting begins at the deflected-to user".
++ */
++ PRI_REROUTING_RSP_OK_RETAIN,
++ PRI_REROUTING_RSP_NOT_SUBSCRIBED,
++ PRI_REROUTING_RSP_NOT_AVAILABLE,
++ /*! Supplementary service interaction not allowed. */
++ PRI_REROUTING_RSP_NOT_ALLOWED,
++ PRI_REROUTING_RSP_INVALID_NUMBER,
++ /*! Deflection to prohibited number (e.g., operator, police, emergency). */
++ PRI_REROUTING_RSP_SPECIAL_SERVICE_NUMBER,
++ /*! Deflection to served user number. */
++ PRI_REROUTING_RSP_DIVERSION_TO_SELF,
++ PRI_REROUTING_RSP_MAX_DIVERSIONS_EXCEEDED,
++ PRI_REROUTING_RSP_RESOURCE_UNAVAILABLE,
++};
++
++/*!
++ * \brief Send the CallRerouteing/CallDeflection response message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg.
++ * \param invoke_id Value given by the initiating request.
++ * \param code The result to send.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI_REROUTING_RSP_CODE code);
++
++/*!
++ * \brief Set the call hold feature enable flag.
++ *
++ * \param ctrl D channel controller.
++ * \param enable TRUE to enable call hold feature.
++ *
++ * \return Nothing
++ */
++void pri_hold_enable(struct pri *ctrl, int enable);
++
++/*!
++ * \brief Send the HOLD message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_hold(struct pri *ctrl, q931_call *call);
++
++/*!
++ * \brief Send the HOLD ACKNOWLEDGE message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_hold_ack(struct pri *ctrl, q931_call *call);
++
++/*!
++ * \brief Send the HOLD REJECT message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ * \param cause Q.931 cause code for rejecting the hold request.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause);
++
++/*!
++ * \brief Send the RETRIEVE message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ * \param channel Encoded channel id to use. If zero do not send channel id.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_retrieve(struct pri *ctrl, q931_call *call, int channel);
++
++/*!
++ * \brief Send the RETRIEVE ACKNOWLEDGE message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ * \param channel Encoded channel id to use.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel);
++
++/*!
++ * \brief Send the RETRIEVE REJECT message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ * \param cause Q.931 cause code for rejecting the retrieve request.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause);
++
+ /* Get/Set PRI Timers */
+ #define PRI_GETSET_TIMERS
+ int pri_set_timer(struct pri *pri, int timer, int value);
+ int pri_get_timer(struct pri *pri, int timer);
+-int pri_timer2idx(char *timer);
++int pri_timer2idx(const char *timer_name);
+
+-#define PRI_MAX_TIMERS 32
++/*! New configurable timers and counters must be added to the end of the list */
++enum PRI_TIMERS_AND_COUNTERS {
++ PRI_TIMER_N200, /*!< Maximum numer of Q.921 retransmissions */
++ PRI_TIMER_N201, /*!< Maximum numer of octets in an information field */
++ PRI_TIMER_N202, /*!< Maximum numer of transmissions of the TEI identity request message */
++ PRI_TIMER_K, /*!< Maximum number of outstanding I-frames */
+
+-#define PRI_TIMER_N200 0 /* Maximum numer of q921 retransmissions */
+-#define PRI_TIMER_N201 1 /* Maximum numer of octets in an information field */
+-#define PRI_TIMER_N202 2 /* Maximum numer of transmissions of the TEI identity request message */
+-#define PRI_TIMER_K 3 /* Maximum number of outstanding I-frames */
++ PRI_TIMER_T200, /*!< Time between SABME's */
++ PRI_TIMER_T201, /*!< Minimum time between retransmissions of the TEI Identity check messages */
++ PRI_TIMER_T202, /*!< Minimum time between transmission of TEI Identity request messages */
++ PRI_TIMER_T203, /*!< Maximum time without exchanging packets */
+
+-#define PRI_TIMER_T200 4 /* time between SABME's */
+-#define PRI_TIMER_T201 5 /* minimum time between retransmissions of the TEI Identity check messages */
+-#define PRI_TIMER_T202 6 /* minimum time between transmission of TEI Identity request messages */
+-#define PRI_TIMER_T203 7 /* maxiumum time without exchanging packets */
++ PRI_TIMER_T300,
++ PRI_TIMER_T301, /*!< Maximum time to respond to an ALERT */
++ PRI_TIMER_T302,
++ PRI_TIMER_T303, /*!< Maximum time to wait after sending a SETUP without a response */
++ PRI_TIMER_T304,
++ PRI_TIMER_T305, /*!< Wait for DISCONNECT acknowledge */
++ PRI_TIMER_T306,
++ PRI_TIMER_T307,
++ PRI_TIMER_T308, /*!< Wait for RELEASE acknowledge */
++ PRI_TIMER_T309, /*!< Time active calls can tollerate data link layer being down before clearing. */
++ PRI_TIMER_T310, /*!< Maximum time between receiving a CALL_PROCEEDING and receiving a ALERT/CONNECT/DISCONNECT/PROGRESS */
++ PRI_TIMER_T313, /*!< Wait for CONNECT acknowledge, CPE side only */
++ PRI_TIMER_T314,
++ PRI_TIMER_T316, /*!< Maximum time between transmitting a RESTART and receiving a RESTART ACK */
++ PRI_TIMER_T317,
++ PRI_TIMER_T318,
++ PRI_TIMER_T319,
++ PRI_TIMER_T320,
++ PRI_TIMER_T321,
++ PRI_TIMER_T322,
+
+-#define PRI_TIMER_T300 8
+-#define PRI_TIMER_T301 9 /* maximum time to respond to an ALERT */
+-#define PRI_TIMER_T302 10
+-#define PRI_TIMER_T303 11 /* maximum time to wait after sending a SETUP without a response */
+-#define PRI_TIMER_T304 12
+-#define PRI_TIMER_T305 13
+-#define PRI_TIMER_T306 14
+-#define PRI_TIMER_T307 15
+-#define PRI_TIMER_T308 16
+-#define PRI_TIMER_T309 17
+-#define PRI_TIMER_T310 18 /* maximum time between receiving a CALLPROCEEDING and receiving a ALERT/CONNECT/DISCONNECT/PROGRESS */
+-#define PRI_TIMER_T313 19
+-#define PRI_TIMER_T314 20
+-#define PRI_TIMER_T316 21 /* maximum time between transmitting a RESTART and receiving a RESTART ACK */
+-#define PRI_TIMER_T317 22
+-#define PRI_TIMER_T318 23
+-#define PRI_TIMER_T319 24
+-#define PRI_TIMER_T320 25
+-#define PRI_TIMER_T321 26
+-#define PRI_TIMER_T322 27
++ PRI_TIMER_TM20, /*!< Maximum time awaiting XID response */
++ PRI_TIMER_NM20, /*!< Number of XID retransmits */
+
+-#define PRI_TIMER_TM20 28 /* maximum time avaiting XID response */
+-#define PRI_TIMER_NM20 29 /* number of XID retransmits */
++ PRI_TIMER_T_HOLD, /*!< Maximum time to wait for HOLD request response. */
++ PRI_TIMER_T_RETRIEVE, /*!< Maximum time to wait for RETRIEVE request response. */
+
++ PRI_TIMER_T_RESPONSE, /*!< Maximum time to wait for a typical APDU response. */
++
++ /* Must be last in the enum list */
++ PRI_MAX_TIMERS
++};
++
+ /* Get PRI version */
+ const char *pri_get_version(void);
+
+Index: asn1_primitive.c
+===================================================================
+--- a/asn1_primitive.c (.../tags/1.4.10.2) (revision 0)
++++ b/asn1_primitive.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,1306 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ASN.1 BER encode/decode primitives
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include <stdio.h>
++#include <ctype.h>
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "asn1.h"
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Dump the memory contents indicated in printable characters. (Helper function.)
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param start Dump memory starting position.
++ * \param end Dump memory ending position. (Not included in dump.)
++ *
++ * \return Nothing
++ */
++static void asn1_dump_mem_helper(struct pri *ctrl, const unsigned char *start,
++ const unsigned char *end)
++{
++ pri_message(ctrl, " - \"");
++ for (; start < end; ++start) {
++ pri_message(ctrl, "%c", (isprint(*start)) ? *start : '~');
++ }
++ pri_message(ctrl, "\"\n");
++}
++
++/*!
++ * \internal
++ * \brief Dump the memory contents indicated.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param indent Number of spaces to indent for each new memory dump line.
++ * \param pos Dump memory starting position.
++ * \param length Number of bytes to dump.
++ *
++ * \return Nothing
++ */
++static void asn1_dump_mem(struct pri *ctrl, unsigned indent, const unsigned char *pos,
++ unsigned length)
++{
++ const unsigned char *seg_start;
++ const unsigned char *end;
++ unsigned delimiter;
++ unsigned count;
++
++ seg_start = pos;
++ end = pos + length;
++ if (pos < end) {
++ delimiter = '<';
++ for (;;) {
++ pri_message(ctrl, "%*s", indent, "");
++ for (count = 0; count++ < 16 && pos < end;) {
++ pri_message(ctrl, "%c%02X", delimiter, *pos++);
++ delimiter = (count == 8) ? '-' : ' ';
++ }
++ if (end <= pos) {
++ break;
++ }
++ asn1_dump_mem_helper(ctrl, seg_start, pos);
++ seg_start = pos;
++ }
++ } else {
++ pri_message(ctrl, "%*s<", indent, "");
++ }
++ pri_message(ctrl, ">");
++ asn1_dump_mem_helper(ctrl, seg_start, end);
++}
++
++/*!
++ * \brief Convert the given tag value to a descriptive string.
++ *
++ * \param tag Component tag value to convert to a string.
++ *
++ * \return Converted tag string.
++ */
++const char *asn1_tag2str(unsigned tag)
++{
++ static const char *primitives[32] = {
++ [ASN1_TYPE_INDEF_TERM] = "Indefinite length terminator",
++ [ASN1_TYPE_BOOLEAN] = "Boolean",
++ [ASN1_TYPE_INTEGER] = "Integer",
++ [ASN1_TYPE_BIT_STRING] = "Bit String",
++ [ASN1_TYPE_OCTET_STRING] = "Octet String",
++ [ASN1_TYPE_NULL] = "NULL",
++ [ASN1_TYPE_OBJECT_IDENTIFIER] = "OID",
++ [ASN1_TYPE_OBJECT_DESCRIPTOR] = "Object Descriptor",
++ [ASN1_TYPE_EXTERN] = "External",
++ [ASN1_TYPE_REAL] = "Real",
++ [ASN1_TYPE_ENUMERATED] = "Enumerated",
++ [ASN1_TYPE_EMBEDDED_PDV] = "Embedded PDV",
++ [ASN1_TYPE_UTF8_STRING] = "UTF8 String",
++ [ASN1_TYPE_RELATIVE_OID] = "Relative OID",
++ [ASN1_TYPE_SEQUENCE] = "Sequence",
++ [ASN1_TYPE_SET] = "Set",
++ [ASN1_TYPE_NUMERIC_STRING] = "Numeric String",
++ [ASN1_TYPE_PRINTABLE_STRING] = "Printable String",
++ [ASN1_TYPE_TELETEX_STRING] = "Teletex String",
++ [ASN1_TYPE_VIDEOTEX_STRING] = "Videotex String",
++ [ASN1_TYPE_IA5_STRING] = "IA5 String",
++ [ASN1_TYPE_UTC_TIME] = "UTC Time",
++ [ASN1_TYPE_GENERALIZED_TIME] = "Generalized Time",
++ [ASN1_TYPE_GRAPHIC_STRING] = "Graphic String",
++ [ASN1_TYPE_VISIBLE_STRING] = "Visible/ISO646 String",
++ [ASN1_TYPE_GENERAL_STRING] = "General String",
++ [ASN1_TYPE_UNIVERSAL_STRING] = "Universal String",
++ [ASN1_TYPE_CHAR_STRING] = "Character String",
++ [ASN1_TYPE_BMP_STRING] = "BMP String",
++ [ASN1_TYPE_EXTENSION] = "Type Extension",
++ };
++ static char buf[64];
++ const char *description;
++ unsigned asn1_constructed; /*! TRUE if the tag is constructed. */
++ unsigned asn1_type;
++
++ asn1_constructed = ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED);
++ asn1_type = tag & ASN1_TYPE_MASK;
++
++ switch (tag & ASN1_CLASS_MASK) {
++ case ASN1_CLASS_UNIVERSAL:
++ if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_INDEF_TERM)) {
++ description = NULL;
++ } else {
++ description = primitives[asn1_type];
++ }
++ if (!description) {
++ description = "Reserved";
++ }
++ snprintf(buf, sizeof(buf), "%s%s(%u 0x%02X)", description,
++ asn1_constructed ? "/C" : "", tag, tag);
++ return buf;
++ case ASN1_CLASS_APPLICATION:
++ description = "Application";
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC:
++ description = "Context Specific";
++ break;
++ case ASN1_CLASS_PRIVATE:
++ description = "Private";
++ break;
++ default:
++ snprintf(buf, sizeof(buf), "Unknown tag (%u 0x%02X)", tag, tag);
++ return buf;
++ }
++ snprintf(buf, sizeof(buf), "%s%s [%u 0x%02X]", description,
++ asn1_constructed ? "/C" : "", asn1_type, asn1_type);
++ return buf;
++}
++
++/*!
++ * \brief Decode the ASN.1 tag value.
++ *
++ * \param tag_pos ASN.1 tag starting position.
++ * \param end End of ASN.1 encoded data buffer.
++ * \param tag Decoded tag value returned on success.
++ *
++ * \retval Next octet after the tag on success.
++ * \retval NULL on error.
++ */
++const unsigned char *asn1_dec_tag(const unsigned char *tag_pos, const unsigned char *end,
++ unsigned *tag)
++{
++ unsigned extended_tag;
++
++ if (end <= tag_pos) {
++ return NULL;
++ }
++ *tag = *tag_pos++;
++ if ((*tag & ASN1_TYPE_MASK) == ASN1_TYPE_EXTENSION) {
++ /* Extract the extended tag value */
++ extended_tag = 0;
++ do {
++ if (end <= tag_pos) {
++ return NULL;
++ }
++ extended_tag <<= 7;
++ extended_tag |= *tag_pos & ~0x80;
++ } while (*tag_pos++ & 0x80);
++ if (extended_tag && extended_tag < ASN1_TYPE_EXTENSION) {
++ /*
++ * The sender did not need to use the extended format.
++ * This is an encoding error on their part, but we will
++ * accept it anyway.
++ *
++ * Note we cannot return a null tag value from this path.
++ * We would misinterpret the indefinite length
++ * terminator.
++ */
++ *tag &= ~ASN1_TYPE_MASK;
++ *tag |= extended_tag;
++ }
++ }
++
++ return tag_pos;
++}
++
++/*!
++ * \brief Decode the length of an ASN.1 component length.
++ *
++ * \param len_pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param length Decoded length value returned on success. (-1 if indefinite)
++ *
++ * \retval Next octet after the length on success.
++ * \retval NULL on error.
++ *
++ * \note The decoded length is checked to see if there is enough buffer
++ * left for the component body.
++ */
++const unsigned char *asn1_dec_length(const unsigned char *len_pos,
++ const unsigned char *end, int *length)
++{
++ unsigned length_size;
++
++ if (end <= len_pos) {
++ /* Not enough buffer to determine how the length is encoded */
++ return NULL;
++ }
++
++ if (*len_pos < 0x80) {
++ /* Short length encoding */
++ *length = *len_pos++;
++ } else if (*len_pos == 0x80) {
++ /* Indefinite length encoding */
++ *length = -1;
++ ++len_pos;
++ if (end < len_pos + ASN1_INDEF_TERM_LEN) {
++ /* Not enough buffer for the indefinite length terminator */
++ return NULL;
++ }
++ return len_pos;
++ } else {
++ /* Long length encoding */
++ length_size = *len_pos++ & 0x7f;
++ if (length_size == 0x7f) {
++ /* Reserved extension encoding that has not been defined. */
++ return NULL;
++ }
++ if (end < len_pos + length_size) {
++ /* Not enough buffer for the length value */
++ return NULL;
++ }
++ *length = 0;
++ while (length_size--) {
++ *length = (*length << 8) | *len_pos++;
++ }
++ }
++
++ if (end < len_pos + *length) {
++ /* Not enough buffer for the component body. */
++ return NULL;
++ }
++ return len_pos;
++}
++
++/*!
++ * \internal
++ * \brief Skip to the end of an indefinite length constructed component helper.
++ *
++ * \param pos ASN.1 tag starting position.
++ * \param end End of ASN.1 decoding data buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *asn1_dec_indef_end_fixup_helper(const unsigned char *pos,
++ const unsigned char *end)
++{
++ unsigned tag;
++ int length;
++
++ while (pos < end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ if (length < 0) {
++ /* Skip over indefinite length sub-component */
++ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED
++ || tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
++ || tag ==
++ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
++ /* This is an ITU encoded indefinite length component. */
++ ASN1_CALL(pos, asn1_dec_indef_end_fixup_helper(pos, end));
++ } else {
++ /* This is a non-ITU encoded indefinite length component. */
++ while (pos < end && *pos != ASN1_INDEF_TERM) {
++ ++pos;
++ }
++ pos += ASN1_INDEF_TERM_LEN;
++ }
++ } else {
++ /* Skip over defininte length sub-component */
++ pos += length;
++ }
++ }
++ if (end < pos + ASN1_INDEF_TERM_LEN) {
++ return NULL;
++ }
++
++ return pos + ASN1_INDEF_TERM_LEN;
++}
++
++/*!
++ * \brief Skip to the end of an indefinite length constructed component.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param pos ASN.1 tag starting position.
++ * \param end End of ASN.1 decoding data buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *asn1_dec_indef_end_fixup(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end)
++{
++ if (pos < end && *pos != ASN1_INDEF_TERM && (ctrl->debug & PRI_DEBUG_APDU)) {
++ pri_message(ctrl,
++ " Skipping unused indefinite length constructed component octets!\n");
++ }
++ return asn1_dec_indef_end_fixup_helper(pos, end);
++}
++
++/*!
++ * \brief Decode the boolean primitive.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this primitive.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param value Decoded boolean value.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *asn1_dec_boolean(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, int32_t *value)
++{
++ int length;
++
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ if (length != 1) {
++ /*
++ * The encoding rules say the length can only be one.
++ * It is rediculus to get anything else anyway.
++ */
++ return NULL;
++ }
++
++ *value = *pos++ ? 1 : 0;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s = %d\n", name, asn1_tag2str(tag), *value);
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the integer type primitive.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this primitive.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param value Decoded integer type value.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *asn1_dec_int(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, int32_t *value)
++{
++ int length;
++
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ if (length <= 0) {
++ /*
++ * The encoding rules say the length can not be indefinite.
++ * It cannot be empty for that matter either.
++ */
++ return NULL;
++ }
++
++#if 1
++ /* Read value as signed */
++ if (*pos & 0x80) {
++ /* The value is negative */
++ *value = -1;
++ } else {
++ *value = 0;
++ }
++#else
++ /* Read value as unsigned */
++ *value = 0;
++#endif
++ while (length--) {
++ *value = (*value << 8) | *pos;
++ pos++;
++ }
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s = %d 0x%04X\n", name, asn1_tag2str(tag), *value,
++ *value);
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the null primitive.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this primitive.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *asn1_dec_null(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end)
++{
++ int length;
++
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ if (length != 0) {
++ /*
++ * The encoding rules say the length can only be zero.
++ * It is rediculus to get anything else anyway.
++ */
++ return NULL;
++ }
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the object identifier primitive.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this primitive.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param oid Decoded OID type value.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *asn1_dec_oid(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct asn1_oid *oid)
++{
++ int length;
++ unsigned num_values;
++ unsigned value;
++ unsigned delimiter;
++
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ if (length < 0) {
++ /*
++ * The encoding rules say the length can not be indefinite.
++ */
++ return NULL;
++ }
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s =", name, asn1_tag2str(tag));
++ }
++ delimiter = ' ';
++ num_values = 0;
++ while (length) {
++ value = 0;
++ for (;;) {
++ --length;
++ value = (value << 7) | (*pos & 0x7F);
++ if (!(*pos++ & 0x80)) {
++ /* Last octet in the OID subidentifier value */
++ if (num_values < ARRAY_LEN(oid->value)) {
++ oid->value[num_values] = value;
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "%c%u", delimiter, value);
++ }
++ delimiter = '.';
++ } else {
++ /* Too many OID subidentifier values */
++ delimiter = '~';
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "%c%u", delimiter, value);
++ }
++ }
++ ++num_values;
++ break;
++ }
++ if (!length) {
++ oid->num_values = 0;
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "\n"
++ " Last OID subidentifier value not terminated!\n");
++ }
++ return NULL;
++ }
++ }
++ }
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "\n");
++ }
++
++ if (num_values <= ARRAY_LEN(oid->value)) {
++ oid->num_values = num_values;
++ return pos;
++ } else {
++ /* Need to increase the size of the OID subidentifier list. */
++ oid->num_values = 0;
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Too many OID values!\n");
++ }
++ return NULL;
++ }
++}
++
++/*!
++ * \brief Decode a binary string primitive.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this primitive.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param buf_size Size of the supplied string buffer. (Must be nonzero)
++ * \param str Where to put the decoded string.
++ * \param str_len Length of the decoded string.
++ *
++ * \note The string will be null terminated just in case.
++ * The buffer needs to have enough room for a null terminator.
++ * \note The parse will fail if the parsed string is too large for
++ * the supplied buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *asn1_dec_string_bin(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
++ unsigned char *str, size_t *str_len)
++{
++ int length;
++ size_t sub_buf_size;
++ size_t sub_str_len;
++ unsigned char *sub_str;
++
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ if (length < 0) {
++ /* This is an indefinite length string */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s = Indefinite length string\n", name,
++ asn1_tag2str(tag));
++ }
++ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
++ /*
++ * This is an ITU encoded indefinite length string
++ * and could contain null.
++ */
++
++ /* Ensure that an empty string is null terminated. */
++ *str = 0;
++
++ /* Collect all substrings into the original string buffer. */
++ *str_len = 0;
++ sub_str = str;
++ sub_buf_size = buf_size;
++ for (;;) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
++ if (tag == ASN1_INDEF_TERM) {
++ /* End-of-contents octets */
++ break;
++ }
++
++ /* Append the substring to the accumulated indefinite string. */
++ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
++ sub_buf_size, sub_str, &sub_str_len));
++
++ sub_buf_size -= sub_str_len;
++ sub_str += sub_str_len;
++ *str_len += sub_str_len;
++ }
++ } else {
++ /*
++ * This is a non-ITU encoded indefinite length string
++ * and must not contain null's.
++ */
++ for (length = 0;; ++length) {
++ if (end <= pos + length) {
++ /* Not enough buffer left */
++ return NULL;
++ }
++ if (pos[length] == 0) {
++ /* Found End-of-contents octets */
++ break;
++ }
++ }
++
++ if (buf_size - 1 < length) {
++ /* The destination buffer is not large enough for the data */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " String buffer not large enough!\n");
++ }
++ return NULL;
++ }
++
++ /* Extract the string and null terminate it. */
++ memcpy(str, pos, length);
++ str[length] = 0;
++ *str_len = length;
++
++ pos += length + 1;
++ }
++ if (end <= pos) {
++ /* Not enough buffer left for End-of-contents octets */
++ return NULL;
++ }
++ if (*pos++ != 0) {
++ /* We actually did not find the End-of-contents octets. */
++ return NULL;
++ }
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ /* Dump the collected string buffer contents. */
++ pri_message(ctrl, " Completed string =\n");
++ asn1_dump_mem(ctrl, 6, str, *str_len);
++ }
++ } else {
++ /* This is a definite length string */
++ if (buf_size - 1 < length) {
++ /* The destination buffer is not large enough for the data */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s = Buffer not large enough!\n", name,
++ asn1_tag2str(tag));
++ }
++ return NULL;
++ }
++
++ /* Extract the string and null terminate it. */
++ memcpy(str, pos, length);
++ str[length] = 0;
++ *str_len = length;
++
++ pos += length;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ /* Dump the collected string buffer contents. */
++ pri_message(ctrl, " %s %s =\n", name, asn1_tag2str(tag));
++ asn1_dump_mem(ctrl, 4, str, *str_len);
++ }
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode a string that can be truncated to a maximum length primitive.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this primitive.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param buf_size Size of the supplied string buffer. (Must be nonzero)
++ * \param str Where to put the decoded null terminated string.
++ * \param str_len Length of the decoded string.
++ * (computed for convenience since you could just do a strlen())
++ *
++ * \note The parsed string will be truncated if the string buffer
++ * cannot contain it.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *asn1_dec_string_max(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
++ unsigned char *str, size_t *str_len)
++{
++ int length;
++ size_t str_length;
++ size_t sub_buf_size;
++ size_t sub_str_len;
++ unsigned char *sub_str;
++
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ if (length < 0) {
++ /* This is an indefinite length string */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s = Indefinite length string\n", name,
++ asn1_tag2str(tag));
++ }
++ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
++ /* This is an ITU encoded indefinite length string. */
++
++ /* Ensure that an empty string is null terminated. */
++ *str = 0;
++
++ /* Collect all substrings into the original string buffer. */
++ *str_len = 0;
++ sub_str = str;
++ sub_buf_size = buf_size;
++ for (;;) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
++ if (tag == ASN1_INDEF_TERM) {
++ /* End-of-contents octets */
++ break;
++ }
++
++ /* Append the substring to the accumulated indefinite string. */
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, name, tag, pos, end,
++ sub_buf_size, sub_str, &sub_str_len));
++
++ sub_buf_size -= sub_str_len;
++ sub_str += sub_str_len;
++ *str_len += sub_str_len;
++ }
++ } else {
++ /* This is a non-ITU encoded indefinite length string. */
++ for (length = 0;; ++length) {
++ if (end <= pos + length) {
++ /* Not enough buffer left */
++ return NULL;
++ }
++ if (pos[length] == 0) {
++ /* Found End-of-contents octets */
++ break;
++ }
++ }
++
++ /* Extract the string, truncate if necessary, and terminate it. */
++ str_length = (buf_size - 1 < length) ? buf_size - 1 : length;
++ memcpy(str, pos, str_length);
++ str[str_length] = 0;
++ *str_len = str_length;
++
++ pos += length + 1;
++ }
++ if (end <= pos) {
++ /* Not enough buffer left for End-of-contents octets */
++ return NULL;
++ }
++ if (*pos++ != 0) {
++ /* We actually did not find the End-of-contents octets. */
++ return NULL;
++ }
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Completed string = \"%s\"\n", str);
++ }
++ } else {
++ /*
++ * This is a definite length string
++ *
++ * Extract the string, truncate if necessary, and terminate it.
++ */
++ str_length = (buf_size - 1 < length) ? buf_size - 1 : length;
++ memcpy(str, pos, str_length);
++ str[str_length] = 0;
++ *str_len = str_length;
++
++ pos += length;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s = \"%s\"\n", name, asn1_tag2str(tag), str);
++ }
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Recursive ASN.1 buffer decoding dump helper.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param pos ASN.1 tag starting position.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param level Indentation level to use.
++ * \param indefinite_term TRUE if to stop on an indefinite length terminator.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *asn1_dump_helper(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end, unsigned level, unsigned indefinite_term)
++{
++ unsigned delimiter;
++ unsigned tag;
++ int length;
++ const unsigned char *len_pos;
++
++ while (pos < end && (!indefinite_term || *pos != ASN1_INDEF_TERM)) {
++ /* Decode the tag */
++ pri_message(ctrl, "%*s", 2 * level, "");
++ len_pos = asn1_dec_tag(pos, end, &tag);
++ if (!len_pos) {
++ pri_message(ctrl, "Invalid tag encoding!\n");
++ return NULL;
++ }
++
++ /* Dump the tag contents. */
++ pri_message(ctrl, "%s ", asn1_tag2str(tag));
++ delimiter = '<';
++ while (pos < len_pos) {
++ pri_message(ctrl, "%c%02X", delimiter, *pos);
++ delimiter = ' ';
++ ++pos;
++ }
++ pri_message(ctrl, "> ");
++
++ /* Decode the length */
++ pos = asn1_dec_length(len_pos, end, &length);
++ if (!pos) {
++ pri_message(ctrl, "Invalid length encoding!\n");
++ return NULL;
++ }
++
++ /* Dump the length contents. */
++ if (length < 0) {
++ pri_message(ctrl, "Indefinite length ");
++ } else {
++ pri_message(ctrl, "Len:%d ", length);
++ }
++ delimiter = '<';
++ while (len_pos < pos) {
++ pri_message(ctrl, "%c%02X", delimiter, *len_pos);
++ delimiter = ' ';
++ ++len_pos;
++ }
++ pri_message(ctrl, ">\n");
++
++ /* Dump the body contents */
++ ++level;
++ if (length < 0) {
++ /* Indefinite length */
++ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
++ /* This is an ITU encoded indefinite length component. */
++ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, end, level, 1));
++ } else if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
++ || tag ==
++ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
++ pri_message(ctrl, "%*sThis tag must always be constructed!\n", 2 * level,
++ "");
++ /* Assume tag was constructed to keep going */
++ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, end, level, 1));
++ } else {
++ /* This is a non-ITU encoded indefinite length component. */
++ pri_message(ctrl, "%*sNon-ITU indefininte length component.\n",
++ 2 * level, "");
++ length = 0;
++ while (pos + length < end && pos[length] != ASN1_INDEF_TERM) {
++ ++length;
++ }
++ if (length) {
++ asn1_dump_mem(ctrl, 2 * level, pos, length);
++ pos += length;
++ }
++ }
++ --level;
++ if (end < pos + ASN1_INDEF_TERM_LEN) {
++ pri_message(ctrl, "%*sNot enough room for the End-of-contents octets!\n",
++ 2 * level, "");
++ pos = end;
++ } else {
++ pri_message(ctrl, "%*sEnd-of-contents <%02X %02X>%s\n", 2 * level, "",
++ pos[0], pos[1], (pos[1] != 0) ? " Invalid!" : "");
++ pos += ASN1_INDEF_TERM_LEN;
++ }
++ } else {
++ /* Defininte length */
++ if ((tag & ASN1_PC_MASK) == ASN1_PC_CONSTRUCTED) {
++ /* Dump constructed contents */
++ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, pos + length, level, 0));
++ } else if (tag == (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SET)
++ || tag ==
++ (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_SEQUENCE)) {
++ /* Assume tag was constructed to keep going */
++ pri_message(ctrl, "%*sThis tag must always be constructed!\n", 2 * level,
++ "");
++ ASN1_CALL(pos, asn1_dump_helper(ctrl, pos, pos + length, level, 0));
++ } else if (0 < length) {
++ /* Dump primitive contents. */
++ asn1_dump_mem(ctrl, 2 * level, pos, length);
++ pos += length;
++ }
++ --level;
++ }
++
++#if 0
++ pri_message(ctrl, "%*sEnd\n", 2 * level, "");
++#endif
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Dump the given ASN.1 buffer contents.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param start_asn1 First octet in the ASN.1 buffer. (ASN.1 tag starting position)
++ * \param end One beyond the last octet in the ASN.1 buffer.
++ *
++ * \return Nothing
++ */
++void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1,
++ const unsigned char *end)
++{
++ pri_message(ctrl, "ASN.1 dump\n");
++ if (start_asn1) {
++ asn1_dump_helper(ctrl, start_asn1, end, 1, 0);
++ }
++ pri_message(ctrl, "ASN.1 end\n");
++}
++
++/*!
++ * \brief Encode the length of an ASN.1 component body of predetermined size.
++ *
++ * \param len_pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param length Predetermined component body length.
++ *
++ * \note The encoding buffer does not need to be checked after calling.
++ * It is already checked to have the requested room.
++ *
++ * \retval Next octet after the length on success.
++ * \retval NULL on error.
++ */
++unsigned char *asn1_enc_length(unsigned char *len_pos, unsigned char *end, size_t length)
++{
++ u_int32_t body_length; /* Length of component contents */
++ u_int32_t value;
++ u_int32_t test_mask;
++ unsigned length_size; /* Length of the length encoding */
++
++ body_length = length;
++
++ /* Determine length encoding length */
++ if (body_length < 128) {
++ length_size = 1;
++ } else {
++ /* Find most significant octet of 32 bit integer that carries meaning. */
++ test_mask = 0xFF000000;
++ for (length_size = 4; --length_size;) {
++ if (body_length & test_mask) {
++ /*
++ * Found the first 8 bits of a multiple octet length that
++ * is not all zeroes.
++ */
++ break;
++ }
++ test_mask >>= 8;
++ }
++ length_size += 1 + 1;
++ }
++
++ if (end < len_pos + length_size + body_length) {
++ /* No room for the length and component body in the buffer */
++ return NULL;
++ }
++
++ /* Encode the component body length */
++ if (length_size == 1) {
++ *len_pos++ = body_length;
++ } else {
++ *len_pos++ = 0x80 | --length_size;
++ while (length_size--) {
++ value = body_length;
++ value >>= (8 * length_size);
++ *len_pos++ = value & 0xFF;
++ }
++ }
++
++ return len_pos;
++}
++
++/*!
++ * \brief Encode the length of an already encoded ASN.1 component.
++ *
++ * \param len_pos Starting position of the ASN.1 component length.
++ * \param component_end Next octet after the component body.
++ * \param end End of ASN.1 encoding data buffer.
++ *
++ * \note The total component size could increase or decrease.
++ * \note The component length field must have been initialized with
++ * ASN1_LEN_INIT() or ASN1_CONSTRUCTED_BEGIN().
++ *
++ * \retval Next octet after the component body on success.
++ * \retval NULL on error.
++ */
++unsigned char *asn1_enc_length_fixup(unsigned char *len_pos,
++ unsigned char *component_end, unsigned char *end)
++{
++ u_int32_t body_length; /* Length of component contents */
++ u_int32_t value;
++ u_int32_t test_mask;
++ unsigned length_size; /* Length of the length encoding */
++
++ if (component_end < len_pos + *len_pos) {
++ /* Sanity check */
++ return NULL;
++ }
++
++ body_length = component_end - len_pos - *len_pos;
++
++ /* Determine length encoding length */
++ if (body_length < 128) {
++ length_size = 1;
++ } else {
++ /* Find most significant octet of 32 bit integer that carries meaning. */
++ test_mask = 0xFF000000;
++ for (length_size = 4; --length_size;) {
++ if (body_length & test_mask) {
++ /*
++ * Found the first 8 bits of a multiple octet length that
++ * is not all zeroes.
++ */
++ break;
++ }
++ test_mask >>= 8;
++ }
++ length_size += 1 + 1;
++ }
++
++ component_end = len_pos + length_size + body_length;
++ if (end < component_end) {
++ /* No room for the component in the buffer */
++ return NULL;
++ }
++ if (length_size != *len_pos) {
++ /* Must shift the component body */
++ memmove(len_pos + length_size, len_pos + *len_pos, body_length);
++ }
++
++ /* Encode the component body length */
++ if (length_size == 1) {
++ *len_pos = body_length;
++ } else {
++ *len_pos++ = 0x80 | --length_size;
++ while (length_size--) {
++ value = body_length;
++ value >>= (8 * length_size);
++ *len_pos++ = value & 0xFF;
++ }
++ }
++
++ return component_end;
++}
++
++/*!
++ * \brief Encode the boolean primitive.
++ *
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * \param value Component value to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *asn1_enc_boolean(unsigned char *pos, unsigned char *end, unsigned tag,
++ int32_t value)
++{
++ if (end < pos + 3) {
++ /* No room for the component in the buffer */
++ return NULL;
++ }
++
++ /* Encode component */
++ *pos++ = tag;
++ *pos++ = 1;
++ *pos++ = value ? 1 : 0;
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the integer type primitive.
++ *
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * \param value Component value to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *asn1_enc_int(unsigned char *pos, unsigned char *end, unsigned tag,
++ int32_t value)
++{
++ unsigned count;
++ u_int32_t test_mask;
++ u_int32_t val;
++
++ /* Find most significant octet of 32 bit integer that carries meaning. */
++ test_mask = 0xFF800000;
++ val = (u_int32_t) value;
++ for (count = 4; --count;) {
++ if ((val & test_mask) != test_mask && (val & test_mask) != 0) {
++ /*
++ * The first 9 bits of a multiple octet integer is not
++ * all ones or zeroes.
++ */
++ break;
++ }
++ test_mask >>= 8;
++ }
++
++ if (end < pos + 3 + count) {
++ /* No room for the component in the buffer */
++ return NULL;
++ }
++
++ /* Encode component */
++ *pos++ = tag;
++ *pos++ = count + 1;
++ do {
++ val = (u_int32_t) value;
++ val >>= (8 * count);
++ *pos++ = val & 0xFF;
++ } while (count--);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the null type primitive.
++ *
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *asn1_enc_null(unsigned char *pos, unsigned char *end, unsigned tag)
++{
++ if (end < pos + 2) {
++ /* No room for the component in the buffer */
++ return NULL;
++ }
++
++ /* Encode component */
++ *pos++ = tag;
++ *pos++ = 0;
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the object identifier (OID) primitive.
++ *
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * \param oid Component value to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *asn1_enc_oid(unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct asn1_oid *oid)
++{
++ unsigned char *len_pos;
++ unsigned num_values;
++ unsigned count;
++ u_int32_t value;
++
++ if (end < pos + 2) {
++ /* No room for the component tag and length in the buffer */
++ return NULL;
++ }
++
++ *pos++ = tag;
++ len_pos = pos++;
++
++ /* For all OID subidentifer values */
++ for (num_values = 0; num_values < oid->num_values; ++num_values) {
++ /*
++ * Count the number of 7 bit chunks that are needed
++ * to encode the integer.
++ */
++ value = oid->value[num_values] >> 7;
++ for (count = 0; value; ++count) {
++ /* There are bits still set */
++ value >>= 7;
++ }
++
++ if (end < pos + count + 1) {
++ /* No room for the component body in the buffer */
++ return NULL;
++ }
++
++ /* Store OID subidentifier value */
++ do {
++ value = oid->value[num_values];
++ value >>= (7 * count);
++ *pos++ = (value & 0x7F) | (count ? 0x80 : 0);
++ } while (count--);
++ }
++
++ /* length */
++ *len_pos = pos - len_pos - 1;
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the binary string type primitive.
++ *
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * \param str Binary string to encode.
++ * \param str_len Length of binary string to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *asn1_enc_string_bin(unsigned char *pos, unsigned char *end, unsigned tag,
++ const unsigned char *str, size_t str_len)
++{
++ if (end < pos + 1) {
++ /* No room for the component tag in the buffer */
++ return NULL;
++ }
++
++ /* Encode component */
++ *pos++ = tag;
++ ASN1_CALL(pos, asn1_enc_length(pos, end, str_len));
++ memcpy(pos, str, str_len);
++
++ return pos + str_len;
++}
++
++/*!
++ * \brief Encode a string that can be truncated to a maximum length primitive.
++ *
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * \param str Null terminated string to encode.
++ * \param max_len Maximum length of string to encode.
++ *
++ * \note The string will be truncated if it is too long.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *asn1_enc_string_max(unsigned char *pos, unsigned char *end, unsigned tag,
++ const unsigned char *str, size_t max_len)
++{
++ size_t str_len;
++
++ str_len = strlen((char *) str);
++ if (max_len < str_len) {
++ str_len = max_len;
++ }
++ return asn1_enc_string_bin(pos, end, tag, str, str_len);
++}
++
++/* ------------------------------------------------------------------- */
++/* end asn1_primitive.c */
+
+Property changes on: asn1_primitive.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: pri.c
+===================================================================
+--- a/pri.c (.../tags/1.4.10.2) (revision 1357)
++++ b/pri.c (.../branches/1.4) (revision 1357)
+@@ -42,8 +42,56 @@
+ #include "pri_facility.h"
+ #include "pri_q921.h"
+ #include "pri_q931.h"
+-#include "pri_timers.h"
+
++#define PRI_BIT(a_bit) (1UL << (a_bit))
++#define PRI_ALL_SWITCHES 0xFFFFFFFF
++
++struct pri_timer_table {
++ const char *name;
++ enum PRI_TIMERS_AND_COUNTERS number;
++ unsigned long used_by;
++};
++
++/*!
++ * \note Sort the timer table entries in the order of the timer name so
++ * pri_dump_info_str() can display them in a consitent order.
++ */
++static const struct pri_timer_table pri_timer[] = {
++/* *INDENT-OFF* */
++ /* timer name timer number used by switches */
++ { "N200", PRI_TIMER_N200, PRI_ALL_SWITCHES },
++ { "N201", PRI_TIMER_N201, PRI_ALL_SWITCHES },
++ { "N202", PRI_TIMER_N202, PRI_ALL_SWITCHES },
++ { "K", PRI_TIMER_K, PRI_ALL_SWITCHES },
++ { "T200", PRI_TIMER_T200, PRI_ALL_SWITCHES },
++ { "T202", PRI_TIMER_T202, PRI_ALL_SWITCHES },
++ { "T203", PRI_TIMER_T203, PRI_ALL_SWITCHES },
++ { "T300", PRI_TIMER_T300, PRI_ALL_SWITCHES },
++ { "T301", PRI_TIMER_T301, PRI_ALL_SWITCHES },
++ { "T302", PRI_TIMER_T302, PRI_ALL_SWITCHES },
++ { "T303", PRI_TIMER_T303, PRI_ALL_SWITCHES },
++ { "T304", PRI_TIMER_T304, PRI_ALL_SWITCHES },
++ { "T305", PRI_TIMER_T305, PRI_ALL_SWITCHES },
++ { "T306", PRI_TIMER_T306, PRI_ALL_SWITCHES },
++ { "T307", PRI_TIMER_T307, PRI_ALL_SWITCHES },
++ { "T308", PRI_TIMER_T308, PRI_ALL_SWITCHES },
++ { "T309", PRI_TIMER_T309, PRI_ALL_SWITCHES },
++ { "T310", PRI_TIMER_T310, PRI_ALL_SWITCHES },
++ { "T313", PRI_TIMER_T313, PRI_ALL_SWITCHES },
++ { "T314", PRI_TIMER_T314, PRI_ALL_SWITCHES },
++ { "T316", PRI_TIMER_T316, PRI_ALL_SWITCHES },
++ { "T317", PRI_TIMER_T317, PRI_ALL_SWITCHES },
++ { "T318", PRI_TIMER_T318, PRI_ALL_SWITCHES },
++ { "T319", PRI_TIMER_T319, PRI_ALL_SWITCHES },
++ { "T320", PRI_TIMER_T320, PRI_ALL_SWITCHES },
++ { "T321", PRI_TIMER_T321, PRI_ALL_SWITCHES },
++ { "T322", PRI_TIMER_T322, PRI_ALL_SWITCHES },
++ { "T-HOLD", PRI_TIMER_T_HOLD, PRI_ALL_SWITCHES },
++ { "T-RETRIEVE", PRI_TIMER_T_RETRIEVE, PRI_ALL_SWITCHES },
++ { "T-RESPONSE", PRI_TIMER_T_RESPONSE, PRI_ALL_SWITCHES },
++/* *INDENT-ON* */
++};
++
+ char *pri_node2str(int node)
+ {
+ switch(node) {
+@@ -84,14 +132,39 @@
+ }
+ }
+
+-static void pri_default_timers(struct pri *pri, int switchtype)
++static void pri_default_timers(struct pri *ctrl, int switchtype)
+ {
+- static const int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;
+- int x;
++ unsigned idx;
+
+- for (x = 0; x<PRI_MAX_TIMERS; x++) {
+- pri->timers[x] = defaulttimers[switchtype][x];
++ /* Initialize all timers/counters to unsupported/disabled. */
++ for (idx = 0; idx < PRI_MAX_TIMERS; ++idx) {
++ ctrl->timers[idx] = -1;
+ }
++
++ /* Set timer values to standard defaults. Time is in ms. */
++ ctrl->timers[PRI_TIMER_N200] = 3; /* Max numer of Q.921 retransmissions */
++ ctrl->timers[PRI_TIMER_N202] = 3; /* Max numer of transmissions of the TEI identity request message */
++ ctrl->timers[PRI_TIMER_K] = 7; /* Max number of outstanding I-frames */
++ ctrl->timers[PRI_TIMER_T200] = 1000; /* Time between SABME's */
++ ctrl->timers[PRI_TIMER_T202] = 10 * 1000; /* Min time between transmission of TEI Identity request messages */
++ ctrl->timers[PRI_TIMER_T203] = 10 * 1000; /* Max time without exchanging packets */
++ ctrl->timers[PRI_TIMER_T305] = 30 * 1000; /* Wait for DISCONNECT acknowledge */
++ ctrl->timers[PRI_TIMER_T308] = 4 * 1000; /* Wait for RELEASE acknowledge */
++ ctrl->timers[PRI_TIMER_T313] = 4 * 1000; /* Wait for CONNECT acknowledge, CPE side only */
++ ctrl->timers[PRI_TIMER_TM20] = 2500; /* Max time awaiting XID response - Q.921 Appendix IV */
++ ctrl->timers[PRI_TIMER_NM20] = 3; /* Number of XID retransmits - Q.921 Appendix IV */
++ ctrl->timers[PRI_TIMER_T303] = 4 * 1000; /* Length between SETUP retransmissions and timeout */
++
++ ctrl->timers[PRI_TIMER_T_HOLD] = 4 * 1000; /* Wait for HOLD request response. */
++ ctrl->timers[PRI_TIMER_T_RETRIEVE] = 4 * 1000;/* Wait for RETRIEVE request response. */
++
++ ctrl->timers[PRI_TIMER_T_RESPONSE] = 4 * 1000; /* Maximum time to wait for a typical APDU response. */
++
++ /* Set any switch specific override default values */
++ switch (switchtype) {
++ default:
++ break;
++ }
+ }
+
+ int pri_set_timer(struct pri *pri, int timer, int value)
+@@ -110,66 +183,30 @@
+ return pri->timers[timer];
+ }
+
+-int pri_timer2idx(char *timer)
++int pri_set_service_message_support(struct pri *pri, int supportflag)
+ {
+- if (!strcasecmp(timer, "N200"))
+- return PRI_TIMER_N200;
+- else if (!strcasecmp(timer, "N201"))
+- return PRI_TIMER_N201;
+- else if (!strcasecmp(timer, "N202"))
+- return PRI_TIMER_N202;
+- else if (!strcasecmp(timer, "K"))
+- return PRI_TIMER_K;
+- else if (!strcasecmp(timer, "T200"))
+- return PRI_TIMER_T200;
+- else if (!strcasecmp(timer, "T202"))
+- return PRI_TIMER_T202;
+- else if (!strcasecmp(timer, "T203"))
+- return PRI_TIMER_T203;
+- else if (!strcasecmp(timer, "T300"))
+- return PRI_TIMER_T300;
+- else if (!strcasecmp(timer, "T301"))
+- return PRI_TIMER_T301;
+- else if (!strcasecmp(timer, "T302"))
+- return PRI_TIMER_T302;
+- else if (!strcasecmp(timer, "T303"))
+- return PRI_TIMER_T303;
+- else if (!strcasecmp(timer, "T304"))
+- return PRI_TIMER_T304;
+- else if (!strcasecmp(timer, "T305"))
+- return PRI_TIMER_T305;
+- else if (!strcasecmp(timer, "T306"))
+- return PRI_TIMER_T306;
+- else if (!strcasecmp(timer, "T307"))
+- return PRI_TIMER_T307;
+- else if (!strcasecmp(timer, "T308"))
+- return PRI_TIMER_T308;
+- else if (!strcasecmp(timer, "T309"))
+- return PRI_TIMER_T309;
+- else if (!strcasecmp(timer, "T310"))
+- return PRI_TIMER_T310;
+- else if (!strcasecmp(timer, "T313"))
+- return PRI_TIMER_T313;
+- else if (!strcasecmp(timer, "T314"))
+- return PRI_TIMER_T314;
+- else if (!strcasecmp(timer, "T316"))
+- return PRI_TIMER_T316;
+- else if (!strcasecmp(timer, "T317"))
+- return PRI_TIMER_T317;
+- else if (!strcasecmp(timer, "T318"))
+- return PRI_TIMER_T318;
+- else if (!strcasecmp(timer, "T319"))
+- return PRI_TIMER_T319;
+- else if (!strcasecmp(timer, "T320"))
+- return PRI_TIMER_T320;
+- else if (!strcasecmp(timer, "T321"))
+- return PRI_TIMER_T321;
+- else if (!strcasecmp(timer, "T322"))
+- return PRI_TIMER_T322;
+- else
++ if (!pri) {
+ return -1;
++ }
++ pri->service_message_support = supportflag;
++ return 0;
+ }
+
++int pri_timer2idx(const char *timer_name)
++{
++ unsigned idx;
++ enum PRI_TIMERS_AND_COUNTERS timer_number;
++
++ timer_number = -1;
++ for (idx = 0; idx < ARRAY_LEN(pri_timer); ++idx) {
++ if (!strcasecmp(timer_name, pri_timer[idx].name)) {
++ timer_number = pri_timer[idx].number;
++ break;
++ }
++ }
++ return timer_number;
++}
++
+ static int __pri_read(struct pri *pri, void *buf, int buflen)
+ {
+ int res = read(pri->fd, buf, buflen);
+@@ -192,18 +229,53 @@
+ return res;
+ }
+
+-/* Pass in the master for this function */
+ void __pri_free_tei(struct pri * p)
+ {
+- free (p);
++ if (p) {
++ struct q931_call *call;
++
++ call = p->dummy_call;
++ if (call) {
++ pri_schedule_del(call->pri, call->retranstimer);
++ pri_call_apdu_queue_cleanup(call);
++ }
++ free(p->msg_line);
++ free(p);
++ }
+ }
+
+ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
+ {
++ struct d_ctrl_dummy *dummy_ctrl;
+ struct pri *p;
+
+- if (!(p = calloc(1, sizeof(*p))))
+- return NULL;
++ switch (switchtype) {
++ case PRI_SWITCH_GR303_EOC:
++ case PRI_SWITCH_GR303_TMC:
++ case PRI_SWITCH_GR303_TMC_SWITCHING:
++ case PRI_SWITCH_GR303_EOC_PATH:
++ p = calloc(1, sizeof(*p));
++ if (!p) {
++ return NULL;
++ }
++ dummy_ctrl = NULL;
++ break;
++ default:
++ dummy_ctrl = calloc(1, sizeof(*dummy_ctrl));
++ if (!dummy_ctrl) {
++ return NULL;
++ }
++ p = &dummy_ctrl->ctrl;
++ break;
++ }
++ if (!master) {
++ /* This is the master record. */
++ p->msg_line = calloc(1, sizeof(*p->msg_line));
++ if (!p->msg_line) {
++ free(p);
++ return NULL;
++ }
++ }
+
+ p->bri = bri;
+ p->fd = fd;
+@@ -231,7 +303,14 @@
+ p->q931_rxcount = 0;
+ p->q931_txcount = 0;
+ #endif
+- if (switchtype == PRI_SWITCH_GR303_EOC) {
++ if (dummy_ctrl) {
++ /* Initialize the dummy call reference call record. */
++ dummy_ctrl->ctrl.dummy_call = &dummy_ctrl->dummy_call;
++ q931_init_call_record(&dummy_ctrl->ctrl, dummy_ctrl->ctrl.dummy_call,
++ Q931_DUMMY_CALL_REFERENCE);
++ }
++ switch (switchtype) {
++ case PRI_SWITCH_GR303_EOC:
+ p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
+ p->sapi = Q921_SAPI_GR303_EOC;
+ p->tei = Q921_TEI_GR303_EOC_OPS;
+@@ -240,7 +319,8 @@
+ free(p);
+ p = NULL;
+ }
+- } else if (switchtype == PRI_SWITCH_GR303_TMC) {
++ break;
++ case PRI_SWITCH_GR303_TMC:
+ p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
+ p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
+ p->tei = Q921_TEI_GR303_TMC_CALLPROC;
+@@ -249,14 +329,19 @@
+ free(p);
+ p = NULL;
+ }
+- } else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {
++ break;
++ case PRI_SWITCH_GR303_TMC_SWITCHING:
+ p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
+ p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;
+ p->tei = Q921_TEI_GR303_TMC_SWITCHING;
+- } else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {
++ break;
++ case PRI_SWITCH_GR303_EOC_PATH:
+ p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
+ p->sapi = Q921_SAPI_GR303_EOC;
+ p->tei = Q921_TEI_GR303_EOC_PATH;
++ break;
++ default:
++ break;
+ }
+ /* Start Q.921 layer, Wait if we're the network */
+ if (p)
+@@ -327,44 +412,47 @@
+
+ char *pri_event2str(int id)
+ {
+- switch(id) {
+- case PRI_EVENT_DCHAN_UP:
+- return "D-Channel Up";
+- case PRI_EVENT_DCHAN_DOWN:
+- return "D-channel Down";
+- case PRI_EVENT_RESTART:
+- return "Restart channel";
+- case PRI_EVENT_RING:
+- return "Ring";
+- case PRI_EVENT_HANGUP:
+- return "Hangup";
+- case PRI_EVENT_RINGING:
+- return "Ringing";
+- case PRI_EVENT_ANSWER:
+- return "Answer";
+- case PRI_EVENT_HANGUP_ACK:
+- return "Hangup ACK";
+- case PRI_EVENT_RESTART_ACK:
+- return "Restart ACK";
+- case PRI_EVENT_FACNAME:
+- return "FacName";
+- case PRI_EVENT_INFO_RECEIVED:
+- return "Info Received";
+- case PRI_EVENT_PROCEEDING:
+- return "Proceeding";
+- case PRI_EVENT_SETUP_ACK:
+- return "Setup ACK";
+- case PRI_EVENT_HANGUP_REQ:
+- return "Hangup Req";
+- case PRI_EVENT_NOTIFY:
+- return "Notify";
+- case PRI_EVENT_PROGRESS:
+- return "Progress";
+- case PRI_EVENT_CONFIG_ERR:
+- return "Configuration Error";
+- default:
+- return "Unknown Event";
++ unsigned idx;
++ struct {
++ int id;
++ char *name;
++ } events[] = {
++/* *INDENT-OFF* */
++ { PRI_EVENT_DCHAN_UP, "D-Channel Up" },
++ { PRI_EVENT_DCHAN_DOWN, "D-channel Down" },
++ { PRI_EVENT_RESTART, "Restart channel" },
++ { PRI_EVENT_CONFIG_ERR, "Configuration Error" },
++ { PRI_EVENT_RING, "Ring" },
++ { PRI_EVENT_HANGUP, "Hangup" },
++ { PRI_EVENT_RINGING, "Ringing" },
++ { PRI_EVENT_ANSWER, "Answer" },
++ { PRI_EVENT_HANGUP_ACK, "Hangup ACK" },
++ { PRI_EVENT_RESTART_ACK, "Restart ACK" },
++ { PRI_EVENT_FACILITY, "Facility" },
++ { PRI_EVENT_INFO_RECEIVED, "Info Received" },
++ { PRI_EVENT_PROCEEDING, "Proceeding" },
++ { PRI_EVENT_SETUP_ACK, "Setup ACK" },
++ { PRI_EVENT_HANGUP_REQ, "Hangup Req" },
++ { PRI_EVENT_NOTIFY, "Notify" },
++ { PRI_EVENT_PROGRESS, "Progress" },
++ { PRI_EVENT_KEYPAD_DIGIT, "Keypad Digit" },
++ { PRI_EVENT_SERVICE, "Service" },
++ { PRI_EVENT_SERVICE_ACK, "Service ACK" },
++ { PRI_EVENT_HOLD, "Hold" },
++ { PRI_EVENT_HOLD_ACK, "Hold Ack" },
++ { PRI_EVENT_HOLD_REJ, "Hold Rej" },
++ { PRI_EVENT_RETRIEVE, "Retrieve" },
++ { PRI_EVENT_RETRIEVE_ACK, "Retrieve ACK" },
++ { PRI_EVENT_RETRIEVE_REJ, "Retrieve Rej" },
++/* *INDENT-ON* */
++ };
++
++ for (idx = 0; idx < ARRAY_LEN(events); ++idx) {
++ if (events[idx].id == id) {
++ return events[idx].name;
++ }
+ }
++ return "Unknown Event";
+ }
+
+ pri_event *pri_check_event(struct pri *pri)
+@@ -506,7 +594,7 @@
+ return q931_information(pri, call, digit);
+ }
+
+-int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits)
++int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits)
+ {
+ if (!pri || !call || !digits || !digits[0])
+ return -1;
+@@ -514,15 +602,6 @@
+ return q931_keypad_facility(pri, call, digits);
+ }
+
+-
+-int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
+-{
+- if (!pri || !call)
+- return -1;
+-
+- return qsig_cf_callrerouting(pri, call, dest, original, reason);
+-}
+-
+ int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
+ {
+ if (!pri || !call)
+@@ -533,7 +612,7 @@
+ void pri_destroycall(struct pri *pri, q931_call *call)
+ {
+ if (pri && call)
+- __q931_destroycall(pri, call);
++ q931_destroycall(pri, call);
+ return;
+ }
+
+@@ -551,6 +630,268 @@
+ return q931_connect(pri, call, channel, nonisdn);
+ }
+
++/*!
++ * \internal
++ * \brief Copy the PRI party name to the Q.931 party name structure.
++ *
++ * \param q931_name Q.931 party name structure
++ * \param pri_name PRI party name structure
++ *
++ * \return Nothing
++ */
++static void pri_copy_party_name_to_q931(struct q931_party_name *q931_name, const struct pri_party_name *pri_name)
++{
++ q931_party_name_init(q931_name);
++ if (pri_name->valid) {
++ q931_name->valid = 1;
++ q931_name->presentation = pri_name->presentation;
++ q931_name->char_set = pri_name->char_set;
++ libpri_copy_string(q931_name->str, pri_name->str, sizeof(q931_name->str));
++ }
++}
++
++/*!
++ * \internal
++ * \brief Copy the PRI party number to the Q.931 party number structure.
++ *
++ * \param q931_number Q.931 party number structure
++ * \param pri_number PRI party number structure
++ *
++ * \return Nothing
++ */
++static void pri_copy_party_number_to_q931(struct q931_party_number *q931_number, const struct pri_party_number *pri_number)
++{
++ q931_party_number_init(q931_number);
++ if (pri_number->valid) {
++ q931_number->valid = 1;
++ q931_number->presentation = pri_number->presentation;
++ q931_number->plan = pri_number->plan;
++ libpri_copy_string(q931_number->str, pri_number->str, sizeof(q931_number->str));
++ }
++}
++
++/*!
++ * \internal
++ * \brief Copy the PRI party subaddress to the Q.931 party subaddress structure.
++ *
++ * \param q931_subaddress Q.931 party subaddress structure
++ * \param pri_subaddress PRI party subaddress structure
++ *
++ * \return Nothing
++ */
++static void pri_copy_party_subaddress_to_q931(struct q931_party_subaddress *q931_subaddress, const struct pri_party_subaddress *pri_subaddress)
++{
++ int length;
++ int maxlen = sizeof(q931_subaddress->data) - 1;
++
++ q931_party_subaddress_init(q931_subaddress);
++
++ if (!pri_subaddress->valid) {
++ return;
++ }
++
++ q931_subaddress->valid = 1;
++ q931_subaddress->type = pri_subaddress->type;
++
++ length = pri_subaddress->length;
++ if (length > maxlen){
++ length = maxlen;
++ } else {
++ q931_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
++ }
++ q931_subaddress->length = length;
++ memcpy(q931_subaddress->data, pri_subaddress->data, length);
++ q931_subaddress->data[length] = '\0';
++}
++
++/*!
++ * \internal
++ * \brief Copy the PRI party id to the Q.931 party id structure.
++ *
++ * \param q931_id Q.931 party id structure
++ * \param pri_id PRI party id structure
++ *
++ * \return Nothing
++ */
++static void pri_copy_party_id_to_q931(struct q931_party_id *q931_id, const struct pri_party_id *pri_id)
++{
++ pri_copy_party_name_to_q931(&q931_id->name, &pri_id->name);
++ pri_copy_party_number_to_q931(&q931_id->number, &pri_id->number);
++ pri_copy_party_subaddress_to_q931(&q931_id->subaddress, &pri_id->subaddress);
++}
++
++int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pri_party_connected_line *connected)
++{
++ struct q931_party_id party_id;
++ unsigned idx;
++ struct q931_call *subcall;
++
++ if (!ctrl || !call) {
++ return -1;
++ }
++
++ pri_copy_party_id_to_q931(&party_id, &connected->id);
++ q931_party_id_fixup(ctrl, &party_id);
++ if (!q931_party_id_cmp(&party_id, &call->local_id)) {
++ /* The local party information did not change so do nothing. */
++ return 0;
++ }
++ call->local_id = party_id;
++
++ /* Update all subcalls with new local_id. */
++ if (call->outboundbroadcast && call->master_call == call) {
++ for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
++ subcall = call->subcalls[idx];
++ if (subcall) {
++ subcall->local_id = party_id;
++ }
++ }
++ }
++
++ switch (call->ourcallstate) {
++ case Q931_CALL_STATE_CALL_INITIATED:
++ case Q931_CALL_STATE_OVERLAP_SENDING:
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ /*
++ * The local party transferred to someone else before
++ * the remote end answered.
++ */
++ case Q931_CALL_STATE_ACTIVE:
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ if (q931_is_ptmp(ctrl)) {
++ /* PTMP mode */
++ q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
++ &call->local_id.number);
++ } else {
++ /* PTP mode */
++ /* Immediately send EctInform APDU, callStatus=answered(0) */
++ send_call_transfer_complete(ctrl, call, 0);
++ }
++ break;
++ case PRI_SWITCH_QSIG:
++ /* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
++ send_call_transfer_complete(ctrl, call, 0);
++ break;
++ default:
++ break;
++ }
++ break;
++ default:
++ /* Just save the data for further developments. */
++ break;
++ }
++
++ return 0;
++}
++
++int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_party_redirecting *redirecting)
++{
++ unsigned idx;
++ struct q931_call *subcall;
++
++ if (!ctrl || !call) {
++ return -1;
++ }
++
++ /* Save redirecting.to information and reason. */
++ pri_copy_party_id_to_q931(&call->redirecting.to, &redirecting->to);
++ q931_party_id_fixup(ctrl, &call->redirecting.to);
++ call->redirecting.reason = redirecting->reason;
++
++ /*
++ * Update all subcalls with new redirecting.to information and reason.
++ * I do not think we will ever have any subcalls when this data is relevant,
++ * but update it just in case.
++ */
++ if (call->outboundbroadcast && call->master_call == call) {
++ for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
++ subcall = call->subcalls[idx];
++ if (subcall) {
++ subcall->redirecting.to = call->redirecting.to;
++ subcall->redirecting.reason = redirecting->reason;
++ }
++ }
++ }
++
++ switch (call->ourcallstate) {
++ case Q931_CALL_STATE_NULL:
++ /* Save the remaining redirecting information before we place a call. */
++ pri_copy_party_id_to_q931(&call->redirecting.from, &redirecting->from);
++ q931_party_id_fixup(ctrl, &call->redirecting.from);
++ pri_copy_party_id_to_q931(&call->redirecting.orig_called, &redirecting->orig_called);
++ q931_party_id_fixup(ctrl, &call->redirecting.orig_called);
++ call->redirecting.orig_reason = redirecting->orig_reason;
++ if (redirecting->count <= 0) {
++ if (call->redirecting.from.number.valid) {
++ /*
++ * We are redirecting with an unknown count
++ * so assume the count is one.
++ */
++ call->redirecting.count = 1;
++ } else {
++ call->redirecting.count = 0;
++ }
++ } else if (redirecting->count < PRI_MAX_REDIRECTS) {
++ call->redirecting.count = redirecting->count;
++ } else {
++ call->redirecting.count = PRI_MAX_REDIRECTS;
++ }
++ break;
++ case Q931_CALL_STATE_OVERLAP_RECEIVING:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ /* This is an incoming call that has not connected yet. */
++ if (!call->redirecting.to.number.valid) {
++ /* Not being redirected toward valid number data. Ignore. */
++ break;
++ }
++
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ if (q931_is_ptmp(ctrl)) {
++ /* PTMP mode */
++ q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING,
++ &call->redirecting.to.number);
++ break;
++ }
++ /* PTP mode - same behaviour as Q.SIG */
++ /* fall through */
++ case PRI_SWITCH_QSIG:
++ if (call->redirecting.state != Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3
++ || strcmp(call->redirecting.to.number.str, call->called.number.str) != 0) {
++ /* immediately send divertingLegInformation1 APDU */
++ if (rose_diverting_leg_information1_encode(ctrl, call)
++ || q931_facility(ctrl, call)) {
++ pri_message(ctrl,
++ "Could not schedule facility message for divertingLegInfo1\n");
++ }
++ }
++ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
++
++ /* immediately send divertingLegInformation3 APDU */
++ if (rose_diverting_leg_information3_encode(ctrl, call, Q931_FACILITY)
++ || q931_facility(ctrl, call)) {
++ pri_message(ctrl,
++ "Could not schedule facility message for divertingLegInfo3\n");
++ }
++ break;
++ default:
++ break;
++ }
++ break;
++ default:
++ pri_message(ctrl, "Ignored redirecting update because call in state %s(%d).\n",
++ q931_call_state_str(call->ourcallstate), call->ourcallstate);
++ break;
++ }
++
++ return 0;
++}
++
+ #if 0
+ /* deprecated routines, use pri_hangup */
+ int pri_release(struct pri *pri, q931_call *call, int cause)
+@@ -619,7 +960,7 @@
+ return -1;
+ if (cause == -1)
+ /* normal clear cause */
+- cause = 16;
++ cause = PRI_CAUSE_NORMAL_CLEARING;
+ return q931_hangup(pri, call, cause);
+ }
+
+@@ -630,6 +971,14 @@
+ return q931_restart(pri, channel);
+ }
+
++int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus)
++{
++ if (!pri) {
++ return -1;
++ }
++ return maintenance_service(pri, span, channel, changestatus);
++}
++
+ q931_call *pri_new_call(struct pri *pri)
+ {
+ if (!pri)
+@@ -637,6 +986,14 @@
+ return q931_new_call(pri);
+ }
+
++int pri_is_dummy_call(q931_call *call)
++{
++ if (!call) {
++ return 0;
++ }
++ return q931_is_dummy_call(call);
++}
++
+ void pri_dump_event(struct pri *pri, pri_event *e)
+ {
+ if (!pri || !e)
+@@ -667,7 +1024,10 @@
+ static void pri_sr_init(struct pri_sr *req)
+ {
+ memset(req, 0, sizeof(struct pri_sr));
+-
++ q931_party_redirecting_init(&req->redirecting);
++ q931_party_id_init(&req->caller);
++ q931_party_address_init(&req->called);
++ req->reversecharge = PRI_REVERSECHARGE_NONE;
+ }
+
+ int pri_sr_set_connection_call_independent(struct pri_sr *req)
+@@ -675,10 +1035,21 @@
+ if (!req)
+ return -1;
+
+- req->justsignalling = 1; /* have to set justsignalling for all those pesky IEs we need to setup */
++ req->cis_call = 1; /* have to set cis_call for all those pesky IEs we need to setup */
++ req->cis_auto_disconnect = 1;
+ return 0;
+ }
+
++int pri_sr_set_no_channel_call(struct pri_sr *req)
++{
++ if (!req) {
++ return -1;
++ }
++
++ req->cis_call = 1;
++ return 0;
++}
++
+ /* Don't call any other pri functions on this */
+ int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called,
+ int calledplan)
+@@ -689,14 +1060,9 @@
+
+ pri_sr_init(&req);
+ pri_sr_set_connection_call_independent(&req);
++ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
++ pri_sr_set_called(&req, called, calledplan, 0);
+
+- req.caller = caller;
+- req.callerplan = callerplan;
+- req.callername = callername;
+- req.callerpres = callerpres;
+- req.called = called;
+- req.calledplan = calledplan;
+-
+ if (mwi_message_send(pri, c, &req, 1) < 0) {
+ pri_message(pri, "Unable to send MWI activate message\n");
+ return -1;
+@@ -714,14 +1080,9 @@
+
+ pri_sr_init(&req);
+ pri_sr_set_connection_call_independent(&req);
++ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
++ pri_sr_set_called(&req, called, calledplan, 0);
+
+- req.caller = caller;
+- req.callerplan = callerplan;
+- req.callername = callername;
+- req.callerpres = callerpres;
+- req.called = called;
+- req.calledplan = calledplan;
+-
+ if(mwi_message_send(pri, c, &req, 0) < 0) {
+ pri_message(pri, "Unable to send MWI deactivate message\n");
+ return -1;
+@@ -740,22 +1101,18 @@
+
+ int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
+ int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
+- int calledplan,int ulayer1)
++ int calledplan, int ulayer1)
+ {
+ struct pri_sr req;
+ if (!pri || !c)
+ return -1;
+ pri_sr_init(&req);
++ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
++ pri_sr_set_called(&req, called, calledplan, 0);
+ req.transmode = transmode;
+ req.channel = channel;
+ req.exclusive = exclusive;
+ req.nonisdn = nonisdn;
+- req.caller = caller;
+- req.callerplan = callerplan;
+- req.callername = callername;
+- req.callerpres = callerpres;
+- req.called = called;
+- req.calledplan = calledplan;
+ req.userl1 = ulayer1;
+ return q931_setup(pri, c, &req);
+ }
+@@ -773,28 +1130,85 @@
+ __pri_error = func;
+ }
+
+-void pri_message(struct pri *pri, char *fmt, ...)
++static void pri_old_message(struct pri *ctrl, const char *fmt, va_list *ap)
+ {
+ char tmp[1024];
+- va_list ap;
+- va_start(ap, fmt);
+- vsnprintf(tmp, sizeof(tmp), fmt, ap);
+- va_end(ap);
++
++ vsnprintf(tmp, sizeof(tmp), fmt, *ap);
+ if (__pri_message)
+- __pri_message(pri, tmp);
++ __pri_message(ctrl, tmp);
+ else
+ fputs(tmp, stdout);
+ }
+
+-void pri_error(struct pri *pri, char *fmt, ...)
++void pri_message(struct pri *ctrl, const char *fmt, ...)
+ {
++ int added_length;
++ va_list ap;
++
++ ctrl = PRI_MASTER(ctrl);
++ if (!ctrl || !ctrl->msg_line) {
++ /* Just have to do it the old way. */
++ va_start(ap, fmt);
++ pri_old_message(ctrl, fmt, &ap);
++ va_end(ap);
++ return;
++ }
++
++ va_start(ap, fmt);
++ added_length = vsnprintf(ctrl->msg_line->str + ctrl->msg_line->length,
++ sizeof(ctrl->msg_line->str) - ctrl->msg_line->length, fmt, ap);
++ va_end(ap);
++ if (added_length < 0
++ || sizeof(ctrl->msg_line->str) <= ctrl->msg_line->length + added_length) {
++ static char truncated_output[] =
++ "v-- Error building output or output was truncated. (Next line) --v\n";
++
++ /*
++ * This clause should never need to run because the
++ * output line accumulation buffer is quite large.
++ */
++
++ /* vsnprintf() error or output string was truncated. */
++ if (__pri_message) {
++ __pri_message(ctrl, truncated_output);
++ } else {
++ fputs(truncated_output, stdout);
++ }
++
++ /* Add a terminating '\n' to force a flush of the line. */
++ ctrl->msg_line->length = strlen(ctrl->msg_line->str);
++ if (ctrl->msg_line->length) {
++ ctrl->msg_line->str[ctrl->msg_line->length - 1] = '\n';
++ } else {
++ ctrl->msg_line->str[0] = '\n';
++ ctrl->msg_line->str[1] = '\0';
++ }
++ } else {
++ ctrl->msg_line->length += added_length;
++ }
++
++ if (ctrl->msg_line->length
++ && ctrl->msg_line->str[ctrl->msg_line->length - 1] == '\n') {
++ /* The accumulated output line was terminated so send it out. */
++ ctrl->msg_line->length = 0;
++ if (__pri_message) {
++ __pri_message(ctrl, ctrl->msg_line->str);
++ } else {
++ fputs(ctrl->msg_line->str, stdout);
++ }
++ }
++}
++
++void pri_error(struct pri *pri, const char *fmt, ...)
++{
+ char tmp[1024];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(tmp, sizeof(tmp), fmt, ap);
+ va_end(ap);
+ if (__pri_error)
+- __pri_error(pri, tmp);
++ __pri_error(PRI_MASTER(pri), tmp);
+ else
+ fputs(tmp, stderr);
+ }
+@@ -821,49 +1235,102 @@
+ return pri->fd;
+ }
+
+-char *pri_dump_info_str(struct pri *pri)
++/*!
++ * \internal
++ * \brief Append snprintf output to the given buffer.
++ *
++ * \param buf Buffer currently filling.
++ * \param buf_used Offset into buffer where to put new stuff.
++ * \param buf_size Actual buffer size of buf.
++ * \param format printf format string.
++ *
++ * \return Total buffer space used.
++ */
++static size_t pri_snprintf(char *buf, size_t buf_used, size_t buf_size, const char *format, ...) __attribute__((format(printf, 4, 5)));
++static size_t pri_snprintf(char *buf, size_t buf_used, size_t buf_size, const char *format, ...)
+ {
+- char buf[4096];
+- int len = 0;
++ va_list args;
++
++ if (buf_used < buf_size) {
++ va_start(args, format);
++ buf_used += vsnprintf(buf + buf_used, buf_size - buf_used, format, args);
++ va_end(args);
++ }
++ if (buf_size < buf_used) {
++ buf_used = buf_size + 1;
++ }
++ return buf_used;
++}
++
++char *pri_dump_info_str(struct pri *ctrl)
++{
++ char *buf;
++ size_t buf_size;
++ size_t used;
+ #ifdef LIBPRI_COUNTERS
+ struct q921_frame *f;
+- int q921outstanding = 0;
++ unsigned q921outstanding;
+ #endif
+- if (!pri)
++ unsigned idx;
++ unsigned long switch_bit;
++
++ if (!ctrl) {
+ return NULL;
++ }
+
++ buf_size = 4096; /* This should be bigger than we will ever need. */
++ buf = malloc(buf_size);
++ if (!buf) {
++ return NULL;
++ }
++
+ /* Might be nice to format these a little better */
+- len += sprintf(buf + len, "Switchtype: %s\n", pri_switch2str(pri->switchtype));
+- len += sprintf(buf + len, "Type: %s\n", pri_node2str(pri->localtype));
++ used = 0;
++ used = pri_snprintf(buf, used, buf_size, "Switchtype: %s\n",
++ pri_switch2str(ctrl->switchtype));
++ used = pri_snprintf(buf, used, buf_size, "Type: %s\n", pri_node2str(ctrl->localtype));
+ #ifdef LIBPRI_COUNTERS
+ /* Remember that Q921 Counters include Q931 packets (and any retransmissions) */
+- len += sprintf(buf + len, "Q931 RX: %d\n", pri->q931_rxcount);
+- len += sprintf(buf + len, "Q931 TX: %d\n", pri->q931_txcount);
+- len += sprintf(buf + len, "Q921 RX: %d\n", pri->q921_rxcount);
+- len += sprintf(buf + len, "Q921 TX: %d\n", pri->q921_txcount);
+- f = pri->txqueue;
++ used = pri_snprintf(buf, used, buf_size, "Q931 RX: %d\n", ctrl->q931_rxcount);
++ used = pri_snprintf(buf, used, buf_size, "Q931 TX: %d\n", ctrl->q931_txcount);
++ used = pri_snprintf(buf, used, buf_size, "Q921 RX: %d\n", ctrl->q921_rxcount);
++ used = pri_snprintf(buf, used, buf_size, "Q921 TX: %d\n", ctrl->q921_txcount);
++ q921outstanding = 0;
++ f = ctrl->txqueue;
+ while (f) {
+ q921outstanding++;
+ f = f->next;
+ }
+- len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding);
++ used = pri_snprintf(buf, used, buf_size, "Q921 Outstanding: %u\n", q921outstanding);
+ #endif
+- len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen, pri->window);
+- len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej);
+- len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit);
+- len += sprintf(buf + len, "Retrans: %d\n", pri->retrans);
+- len += sprintf(buf + len, "Busy: %d\n", pri->busy);
+- len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial);
+- len += sprintf(buf + len, "Logical Channel Mapping: %d\n", pri->chan_mapping_logical);
+- len += sprintf(buf + len, "T200 Timer: %d\n", pri->timers[PRI_TIMER_T200]);
+- len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]);
+- len += sprintf(buf + len, "T305 Timer: %d\n", pri->timers[PRI_TIMER_T305]);
+- len += sprintf(buf + len, "T308 Timer: %d\n", pri->timers[PRI_TIMER_T308]);
+- len += sprintf(buf + len, "T309 Timer: %d\n", pri->timers[PRI_TIMER_T309]);
+- len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]);
+- len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]);
++ used = pri_snprintf(buf, used, buf_size, "Window Length: %d/%d\n", ctrl->windowlen,
++ ctrl->window);
++ used = pri_snprintf(buf, used, buf_size, "Sentrej: %d\n", ctrl->sentrej);
++ used = pri_snprintf(buf, used, buf_size, "SolicitFbit: %d\n", ctrl->solicitfbit);
++ used = pri_snprintf(buf, used, buf_size, "Retrans: %d\n", ctrl->retrans);
++ used = pri_snprintf(buf, used, buf_size, "Busy: %d\n", ctrl->busy);
++ used = pri_snprintf(buf, used, buf_size, "Overlap Dial: %d\n", ctrl->overlapdial);
++ used = pri_snprintf(buf, used, buf_size, "Logical Channel Mapping: %d\n",
++ ctrl->chan_mapping_logical);
++ used = pri_snprintf(buf, used, buf_size, "Timer and counter settings:\n");
++ switch_bit = PRI_BIT(ctrl->switchtype);
++ for (idx = 0; idx < ARRAY_LEN(pri_timer); ++idx) {
++ if (pri_timer[idx].used_by & switch_bit) {
++ enum PRI_TIMERS_AND_COUNTERS tmr;
+
+- return strdup(buf);
++ tmr = pri_timer[idx].number;
++ if (0 <= ctrl->timers[tmr] || tmr == PRI_TIMER_T309) {
++ used = pri_snprintf(buf, used, buf_size, " %s: %d\n",
++ pri_timer[idx].name, ctrl->timers[tmr]);
++ }
++ }
++ }
++
++ if (buf_size < used) {
++ pri_message(ctrl,
++ "pri_dump_info_str(): Produced output exceeded buffer capacity. (Truncated)\n");
++ }
++ return buf;
+ }
+
+ int pri_get_crv(struct pri *pri, q931_call *call, int *callmode)
+@@ -913,26 +1380,213 @@
+
+ int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int numcomplete)
+ {
+- sr->called = called;
+- sr->calledplan = calledplan;
++ q931_party_address_init(&sr->called);
++ if (called) {
++ sr->called.number.valid = 1;
++ sr->called.number.plan = calledplan;
++ libpri_copy_string(sr->called.number.str, called, sizeof(sr->called.number.str));
++ }
+ sr->numcomplete = numcomplete;
+ return 0;
+ }
+
++void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress)
++{
++ pri_copy_party_subaddress_to_q931(&sr->called.subaddress, subaddress);
++}
++
+ int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres)
+ {
+- sr->caller = caller;
+- sr->callername = callername;
+- sr->callerplan = callerplan;
+- sr->callerpres = callerpres;
++ q931_party_id_init(&sr->caller);
++ if (caller) {
++ sr->caller.number.valid = 1;
++ sr->caller.number.presentation = callerpres;
++ sr->caller.number.plan = callerplan;
++ libpri_copy_string(sr->caller.number.str, caller, sizeof(sr->caller.number.str));
++
++ if (callername) {
++ sr->caller.name.valid = 1;
++ sr->caller.name.presentation = callerpres;
++ sr->caller.name.char_set = PRI_CHAR_SET_ISO8859_1;
++ libpri_copy_string(sr->caller.name.str, callername,
++ sizeof(sr->caller.name.str));
++ }
++ }
+ return 0;
+ }
+
++void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress)
++{
++ pri_copy_party_subaddress_to_q931(&sr->caller.subaddress, subaddress);
++}
++
++void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller)
++{
++ pri_copy_party_id_to_q931(&sr->caller, caller);
++}
++
+ int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason)
+ {
+- sr->redirectingnum = num;
+- sr->redirectingplan = plan;
+- sr->redirectingpres = pres;
+- sr->redirectingreason = reason;
++ q931_party_redirecting_init(&sr->redirecting);
++ if (num && num[0]) {
++ sr->redirecting.from.number.valid = 1;
++ sr->redirecting.from.number.presentation = pres;
++ sr->redirecting.from.number.plan = plan;
++ libpri_copy_string(sr->redirecting.from.number.str, num,
++ sizeof(sr->redirecting.from.number.str));
++
++ sr->redirecting.count = 1;
++ sr->redirecting.reason = reason;
++ }
+ return 0;
+ }
++
++void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting)
++{
++ pri_copy_party_id_to_q931(&sr->redirecting.from, &redirecting->from);
++ pri_copy_party_id_to_q931(&sr->redirecting.to, &redirecting->to);
++ pri_copy_party_id_to_q931(&sr->redirecting.orig_called, &redirecting->orig_called);
++ sr->redirecting.orig_reason = redirecting->orig_reason;
++ sr->redirecting.reason = redirecting->reason;
++ if (redirecting->count <= 0) {
++ if (sr->redirecting.from.number.valid) {
++ /*
++ * We are redirecting with an unknown count
++ * so assume the count is one.
++ */
++ sr->redirecting.count = 1;
++ } else {
++ sr->redirecting.count = 0;
++ }
++ } else if (redirecting->count < PRI_MAX_REDIRECTS) {
++ sr->redirecting.count = redirecting->count;
++ } else {
++ sr->redirecting.count = PRI_MAX_REDIRECTS;
++ }
++}
++
++void pri_sr_set_reversecharge(struct pri_sr *sr, int requested)
++{
++ sr->reversecharge = requested;
++}
++
++void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits)
++{
++ sr->keypad_digits = keypad_digits;
++}
++
++void pri_hold_enable(struct pri *ctrl, int enable)
++{
++ ctrl = PRI_MASTER(ctrl);
++ if (ctrl) {
++ ctrl->hold_support = enable ? 1 : 0;
++ }
++}
++
++int pri_hold(struct pri *ctrl, q931_call *call)
++{
++ if (!ctrl || !call) {
++ return -1;
++ }
++ return q931_send_hold(ctrl, call);
++}
++
++int pri_hold_ack(struct pri *ctrl, q931_call *call)
++{
++ if (!ctrl || !call) {
++ return -1;
++ }
++ return q931_send_hold_ack(ctrl, call);
++}
++
++int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause)
++{
++ if (!ctrl || !call) {
++ return -1;
++ }
++ return q931_send_hold_rej(ctrl, call, cause);
++}
++
++int pri_retrieve(struct pri *ctrl, q931_call *call, int channel)
++{
++ if (!ctrl || !call) {
++ return -1;
++ }
++ return q931_send_retrieve(ctrl, call, channel);
++}
++
++int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel)
++{
++ if (!ctrl || !call) {
++ return -1;
++ }
++ return q931_send_retrieve_ack(ctrl, call, channel);
++}
++
++int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause)
++{
++ if (!ctrl || !call) {
++ return -1;
++ }
++ return q931_send_retrieve_rej(ctrl, call, cause);
++}
++
++int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
++{
++ if (!pri || !call || !dest)
++ return -1;
++
++ return qsig_cf_callrerouting(pri, call, dest, original, reason);
++}
++
++void pri_reroute_enable(struct pri *ctrl, int enable)
++{
++ ctrl = PRI_MASTER(ctrl);
++ if (ctrl) {
++ ctrl->deflection_support = enable ? 1 : 0;
++ }
++}
++
++int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_id *caller, const struct pri_party_redirecting *deflection, int subscription_option)
++{
++ const struct q931_party_id *caller_id;
++ struct q931_party_id local_caller;
++ struct q931_party_redirecting reroute;
++
++ if (!ctrl || !call || !deflection) {
++ return -1;
++ }
++
++ if (caller) {
++ /* Convert the caller update information. */
++ pri_copy_party_id_to_q931(&local_caller, caller);
++ q931_party_id_fixup(ctrl, &local_caller);
++ caller_id = &local_caller;
++ } else {
++ caller_id = NULL;
++ }
++
++ /* Convert the deflection information. */
++ q931_party_redirecting_init(&reroute);
++ pri_copy_party_id_to_q931(&reroute.from, &deflection->from);
++ q931_party_id_fixup(ctrl, &reroute.from);
++ pri_copy_party_id_to_q931(&reroute.to, &deflection->to);
++ q931_party_id_fixup(ctrl, &reroute.to);
++ pri_copy_party_id_to_q931(&reroute.orig_called, &deflection->orig_called);
++ q931_party_id_fixup(ctrl, &reroute.orig_called);
++ reroute.reason = deflection->reason;
++ reroute.orig_reason = deflection->orig_reason;
++ if (deflection->count <= 0) {
++ /*
++ * We are deflecting with an unknown count
++ * so assume the count is one.
++ */
++ reroute.count = 1;
++ } else if (deflection->count < PRI_MAX_REDIRECTS) {
++ reroute.count = deflection->count;
++ } else {
++ reroute.count = PRI_MAX_REDIRECTS;
++ }
++
++ return send_reroute_request(ctrl, call, caller_id, &reroute, subscription_option);
++}
+Index: Makefile
+===================================================================
+--- a/Makefile (.../tags/1.4.10.2) (revision 1357)
++++ b/Makefile (.../branches/1.4) (revision 1357)
+@@ -41,15 +41,55 @@
+
+ STATIC_LIBRARY=libpri.a
+ DYNAMIC_LIBRARY:=libpri.so.$(SONAME)
+-STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o version.o
+-DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo version.lo
+-CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
++STATIC_OBJS= \
++ copy_string.o \
++ pri.o \
++ q921.o \
++ prisched.o \
++ q931.o \
++ pri_facility.o \
++ asn1_primitive.o \
++ rose.o \
++ rose_address.o \
++ rose_etsi_aoc.o \
++ rose_etsi_diversion.o \
++ rose_etsi_ect.o \
++ rose_other.o \
++ rose_q931.o \
++ rose_qsig_aoc.o \
++ rose_qsig_ct.o \
++ rose_qsig_diversion.o \
++ rose_qsig_mwi.o \
++ rose_qsig_name.o \
++ version.o
++DYNAMIC_OBJS= \
++ copy_string.lo \
++ pri.lo \
++ q921.lo \
++ prisched.lo \
++ q931.lo \
++ pri_facility.lo \
++ asn1_primitive.lo \
++ rose.lo \
++ rose_address.lo \
++ rose_etsi_aoc.lo \
++ rose_etsi_diversion.lo \
++ rose_etsi_ect.lo \
++ rose_other.lo \
++ rose_q931.lo \
++ rose_qsig_aoc.lo \
++ rose_qsig_ct.lo \
++ rose_qsig_diversion.lo \
++ rose_qsig_mwi.lo \
++ rose_qsig_name.lo \
++ version.lo
++CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS) $(LIBPRI_OPT)
+ INSTALL_PREFIX=$(DESTDIR)
+ INSTALL_BASE=/usr
+ libdir?=$(INSTALL_BASE)/lib
+ SOFLAGS:=-Wl,-h$(DYNAMIC_LIBRARY)
+ LDCONFIG = /sbin/ldconfig
+-ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX))
++ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX XGNUX))
+ LDCONFIG_FLAGS=-n
+ else
+ ifeq (${OSARCH},FreeBSD)
+@@ -74,7 +114,9 @@
+ #A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesnt support it.
+ ifeq ($(PROC),sparc64)
+ PROC=ultrasparc
+-CFLAGS += -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
++LIBPRI_OPT = -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
++else
++LIBPRI_OPT = -O2
+ endif
+
+ all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
+@@ -132,6 +174,9 @@
+ pridump: pridump.o
+ $(CC) -o pridump pridump.o -L. -lpri $(CFLAGS)
+
++rosetest: rosetest.o
++ $(CC) -o rosetest rosetest.o -L. -lpri $(CFLAGS)
++
+ MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP
+
+ %.o: %.c
+Index: q931.c
+===================================================================
+--- a/q931.c (.../tags/1.4.10.2) (revision 1357)
++++ b/q931.c (.../branches/1.4) (revision 1357)
+@@ -33,6 +33,7 @@
+ #include "pri_q921.h"
+ #include "pri_q931.h"
+ #include "pri_facility.h"
++#include "rose.h"
+
+ #include <unistd.h>
+ #include <stdlib.h>
+@@ -67,7 +68,7 @@
+ { Q931_RESTART_ACKNOWLEDGE, "RESTART ACKNOWLEDGE", { Q931_RESTART_INDICATOR } },
+
+ /* Miscellaneous */
+- { Q931_STATUS, "STATUS", { Q931_CAUSE, Q931_CALL_STATE } },
++ { Q931_STATUS, "STATUS", { Q931_CAUSE, Q931_IE_CALL_STATE } },
+ { Q931_STATUS_ENQUIRY, "STATUS ENQUIRY" },
+ { Q931_USER_INFORMATION, "USER_INFORMATION" },
+ { Q931_SEGMENT, "SEGMENT" },
+@@ -79,22 +80,32 @@
+ /* Call Management */
+ { Q931_HOLD, "HOLD" },
+ { Q931_HOLD_ACKNOWLEDGE, "HOLD ACKNOWLEDGE" },
+- { Q931_HOLD_REJECT, "HOLD REJECT" },
++ { Q931_HOLD_REJECT, "HOLD REJECT", { Q931_CAUSE } },
+ { Q931_RETRIEVE, "RETRIEVE" },
+ { Q931_RETRIEVE_ACKNOWLEDGE, "RETRIEVE ACKNOWLEDGE" },
+- { Q931_RETRIEVE_REJECT, "RETRIEVE REJECT" },
++ { Q931_RETRIEVE_REJECT, "RETRIEVE REJECT", { Q931_CAUSE } },
+ { Q931_RESUME, "RESUME" },
+ { Q931_RESUME_ACKNOWLEDGE, "RESUME ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
+ { Q931_RESUME_REJECT, "RESUME REJECT", { Q931_CAUSE } },
+ { Q931_SUSPEND, "SUSPEND" },
+ { Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" },
+ { Q931_SUSPEND_REJECT, "SUSPEND REJECT" },
++};
+
+- /* Maintenance */
+- { NATIONAL_SERVICE, "SERVICE" },
+- { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" },
++static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand);
++static void nt_ptmp_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int *allow_event, int *allow_posthandle);
++
++struct msgtype att_maintenance_msgs[] = {
++ { ATT_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
++ { ATT_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
+ };
+
++struct msgtype national_maintenance_msgs[] = {
++ { NATIONAL_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
++ { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
++};
++static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, struct q931_mh *mh, struct q931_call *c);
++
+ static struct msgtype causes[] = {
+ { PRI_CAUSE_UNALLOCATED, "Unallocated (unassigned) number" },
+ { PRI_CAUSE_NO_ROUTE_TRANSIT_NET, "No route to specified transmit network" },
+@@ -107,6 +118,7 @@
+ { PRI_CAUSE_NO_ANSWER, "User alerting, no answer" },
+ { PRI_CAUSE_CALL_REJECTED, "Call Rejected" },
+ { PRI_CAUSE_NUMBER_CHANGED, "Number changed" },
++ { PRI_CAUSE_NONSELECTED_USER_CLEARING, "Non-selected user clearing" },
+ { PRI_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order" },
+ { PRI_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format" },
+ { PRI_CAUSE_FACILITY_REJECTED, "Facility rejected" },
+@@ -119,13 +131,14 @@
+ { PRI_CAUSE_ACCESS_INFO_DISCARDED, "Access information discarded" },
+ { PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel not available" },
+ { PRI_CAUSE_PRE_EMPTED, "Pre-empted" },
++ { PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED, "Resource unavailable, unspecified" },
+ { PRI_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed" },
+ { PRI_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred" },
+ { PRI_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred" },
+ { PRI_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized" },
+ { PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available" },
++ { PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
+ { PRI_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented" },
+- { PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
+ { PRI_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented" },
+ { PRI_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented" },
+ { PRI_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference value" },
+@@ -163,8 +176,9 @@
+ { PRI_NSF_CALL_REDIRECTION_SERVICE, "Call Redirection Service" }
+ };
+
+-#define FLAG_PREFERRED 2
+-#define FLAG_EXCLUSIVE 4
++#define FLAG_WHOLE_INTERFACE 0x01
++#define FLAG_PREFERRED 0x02
++#define FLAG_EXCLUSIVE 0x04
+
+ #define RESET_INDICATOR_CHANNEL 0
+ #define RESET_INDICATOR_DS1 6
+@@ -214,26 +228,49 @@
+ #define LOC_NETWORK_BEYOND_INTERWORKING 0xa
+
+ static char *ie2str(int ie);
+-static char *msg2str(int msg);
+
+
+-#define FUNC_DUMP(name) void ((name))(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix)
+-#define FUNC_RECV(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
+-#define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
++#define FUNC_DUMP(name) void (name)(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix)
++#define FUNC_RECV(name) int (name)(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
++#define FUNC_SEND(name) int (name)(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+
+ #if 1
+ /* Update call state with transition trace. */
+-#define UPDATE_OURCALLSTATE(pri,c,newstate) do {\
+- if (pri->debug & (PRI_DEBUG_Q931_STATE) && c->ourcallstate != newstate) \
+- pri_message(pri, DBGHEAD "call %d on channel %d enters state %d (%s)\n", DBGINFO, \
+- c->cr, c->channelno, newstate, callstate2str(newstate)); \
+- c->ourcallstate = newstate; \
++#define UPDATE_OURCALLSTATE(ctrl, call, newstate) \
++ do { \
++ if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) && (call)->ourcallstate != (newstate)) { \
++ pri_message((ctrl), \
++ DBGHEAD "%s %d enters state %d (%s). Hold state: %s\n", \
++ DBGINFO, ((call) == (call)->master_call) ? "Call" : "Subcall", \
++ (call)->cr, (newstate), q931_call_state_str(newstate), \
++ q931_hold_state_str((call)->master_call->hold_state)); \
++ } \
++ (call)->ourcallstate = (newstate); \
+ } while (0)
+ #else
+ /* Update call state with no trace. */
+-#define UPDATE_OURCALLSTATE(pri,c,newstate) c->ourcallstate = newstate
++#define UPDATE_OURCALLSTATE(ctrl, call, newstate) (call)->ourcallstate = (newstate)
+ #endif
+
++#if 1
++/* Update hold state with transition trace. */
++#define UPDATE_HOLD_STATE(ctrl, master_call, newstate) \
++ do { \
++ if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) \
++ && (master_call)->hold_state != (newstate)) { \
++ pri_message((ctrl), \
++ DBGHEAD "Call %d in state %d (%s) enters Hold state: %s\n", \
++ DBGINFO, (master_call)->cr, (master_call)->ourcallstate, \
++ q931_call_state_str((master_call)->ourcallstate), \
++ q931_hold_state_str(newstate)); \
++ } \
++ (master_call)->hold_state = (newstate); \
++ } while (0)
++#else
++/* Update hold state with no trace. */
++#define UPDATE_HOLD_STATE(ctrl, master_call, newstate) (master_call)->hold_state = (newstate)
++#endif
++
+ struct ie {
+ /* Maximal count of same IEs at the message (0 - any, 1..n - limited) */
+ int max_count;
+@@ -249,6 +286,506 @@
+ FUNC_SEND(*transmit);
+ };
+
++/*!
++ * \internal
++ * \brief Encode the channel id information to pass to upper level.
++ *
++ * \param call Q.931 call leg
++ *
++ * \return Encoded channel value.
++ */
++static int q931_encode_channel(const q931_call *call)
++{
++ int held_call;
++ int channelno;
++ int ds1no;
++
++ switch (call->master_call->hold_state) {
++ case Q931_HOLD_STATE_CALL_HELD:
++ case Q931_HOLD_STATE_RETRIEVE_REQ:
++ case Q931_HOLD_STATE_RETRIEVE_IND:
++ held_call = 1 << 18;
++
++ /* So a -1 does not wipe out the held_call flag. */
++ channelno = call->channelno & 0xFF;
++ ds1no = call->ds1no & 0xFF;
++ break;
++ default:
++ held_call = 0;
++ channelno = call->channelno;
++ ds1no = call->ds1no;
++ break;
++ }
++ return channelno | (ds1no << 8) | (call->ds1explicit << 16) | (call->cis_call << 17)
++ | held_call;
++}
++
++/*!
++ * \brief Determine if layer 2 is in PTMP mode.
++ *
++ * \param ctrl D channel controller.
++ *
++ * \retval TRUE if in PTMP mode.
++ * \retval FALSE otherwise.
++ */
++int q931_is_ptmp(const struct pri *ctrl)
++{
++ /* Check master control structure */
++ for (; ctrl->master; ctrl = ctrl->master) {
++ }
++ return ctrl->tei == Q921_TEI_GROUP;
++}
++
++/*!
++ * \brief Initialize the given struct q931_party_name
++ *
++ * \param name Structure to initialize
++ *
++ * \return Nothing
++ */
++void q931_party_name_init(struct q931_party_name *name)
++{
++ name->valid = 0;
++ name->presentation = PRI_PRES_UNAVAILABLE;
++ name->char_set = PRI_CHAR_SET_ISO8859_1;
++ name->str[0] = '\0';
++}
++
++/*!
++ * \brief Initialize the given struct q931_party_number
++ *
++ * \param number Structure to initialize
++ *
++ * \return Nothing
++ */
++void q931_party_number_init(struct q931_party_number *number)
++{
++ number->valid = 0;
++ number->presentation = PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
++ number->plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
++ number->str[0] = '\0';
++}
++
++/*!
++ * \brief Initialize the given struct q931_party_subaddress
++ *
++ * \param subaddress Structure to initialize
++ *
++ * \return Nothing
++ */
++void q931_party_subaddress_init(struct q931_party_subaddress *subaddress)
++{
++ subaddress->valid = 0;
++ subaddress->type = 0;
++ subaddress->odd_even_indicator = 0;
++ subaddress->length = 0;
++ subaddress->data[0] = '\0';
++}
++
++/*!
++ * \brief Initialize the given struct q931_party_address
++ *
++ * \param address Structure to initialize
++ *
++ * \return Nothing
++ */
++void q931_party_address_init(struct q931_party_address *address)
++{
++ q931_party_number_init(&address->number);
++ q931_party_subaddress_init(&address->subaddress);
++}
++
++/*!
++ * \brief Initialize the given struct q931_party_id
++ *
++ * \param id Structure to initialize
++ *
++ * \return Nothing
++ */
++void q931_party_id_init(struct q931_party_id *id)
++{
++ q931_party_name_init(&id->name);
++ q931_party_number_init(&id->number);
++ q931_party_subaddress_init(&id->subaddress);
++}
++
++/*!
++ * \brief Initialize the given struct q931_party_redirecting
++ *
++ * \param redirecting Structure to initialize
++ *
++ * \return Nothing
++ */
++void q931_party_redirecting_init(struct q931_party_redirecting *redirecting)
++{
++ q931_party_id_init(&redirecting->from);
++ q931_party_id_init(&redirecting->to);
++ q931_party_id_init(&redirecting->orig_called);
++ redirecting->state = Q931_REDIRECTING_STATE_IDLE;
++ redirecting->count = 0;
++ redirecting->orig_reason = PRI_REDIR_UNKNOWN;
++ redirecting->reason = PRI_REDIR_UNKNOWN;
++}
++
++/*!
++ * \brief Compare the left and right party name.
++ *
++ * \param left Left parameter party name.
++ * \param right Right parameter party name.
++ *
++ * \retval < 0 when left < right.
++ * \retval == 0 when left == right.
++ * \retval > 0 when left > right.
++ */
++int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right)
++{
++ int cmp;
++
++ if (!left->valid) {
++ if (!right->valid) {
++ return 0;
++ }
++ return -1;
++ } else if (!right->valid) {
++ return 1;
++ }
++ cmp = left->char_set - right->char_set;
++ if (cmp) {
++ return cmp;
++ }
++ cmp = strcmp(left->str, right->str);
++ if (cmp) {
++ return cmp;
++ }
++ cmp = left->presentation - right->presentation;
++ return cmp;
++}
++
++/*!
++ * \brief Compare the left and right party number.
++ *
++ * \param left Left parameter party number.
++ * \param right Right parameter party number.
++ *
++ * \retval < 0 when left < right.
++ * \retval == 0 when left == right.
++ * \retval > 0 when left > right.
++ */
++int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right)
++{
++ int cmp;
++
++ if (!left->valid) {
++ if (!right->valid) {
++ return 0;
++ }
++ return -1;
++ } else if (!right->valid) {
++ return 1;
++ }
++ cmp = left->plan - right->plan;
++ if (cmp) {
++ return cmp;
++ }
++ cmp = strcmp(left->str, right->str);
++ if (cmp) {
++ return cmp;
++ }
++ cmp = left->presentation - right->presentation;
++ return cmp;
++}
++
++/*!
++ * \brief Compare the left and right party subaddress.
++ *
++ * \param left Left parameter party subaddress.
++ * \param right Right parameter party subaddress.
++ *
++ * \retval < 0 when left < right.
++ * \retval == 0 when left == right.
++ * \retval > 0 when left > right.
++ */
++int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right)
++{
++ int cmp;
++
++ if (!left->valid) {
++ if (!right->valid) {
++ return 0;
++ }
++ return -1;
++ } else if (!right->valid) {
++ return 1;
++ }
++ cmp = left->type - right->type;
++ if (cmp) {
++ return cmp;
++ }
++ cmp = memcmp(left->data, right->data,
++ (left->length < right->length) ? left->length : right->length);
++ if (cmp) {
++ return cmp;
++ }
++ cmp = left->length - right->length;
++ if (cmp) {
++ return cmp;
++ }
++ cmp = left->odd_even_indicator - right->odd_even_indicator;
++ return cmp;
++}
++
++/*!
++ * \brief Compare the left and right party id.
++ *
++ * \param left Left parameter party id.
++ * \param right Right parameter party id.
++ *
++ * \retval < 0 when left < right.
++ * \retval == 0 when left == right.
++ * \retval > 0 when left > right.
++ */
++int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right)
++{
++ int cmp;
++
++ cmp = q931_party_number_cmp(&left->number, &right->number);
++ if (cmp) {
++ return cmp;
++ }
++ cmp = q931_party_subaddress_cmp(&left->subaddress, &right->subaddress);
++ if (cmp) {
++ return cmp;
++ }
++ cmp = q931_party_name_cmp(&left->name, &right->name);
++ return cmp;
++}
++
++/*!
++ * \brief Copy the Q.931 party name to the PRI party name structure.
++ *
++ * \param pri_name PRI party name structure
++ * \param q931_name Q.931 party name structure
++ *
++ * \return Nothing
++ */
++void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name)
++{
++ if (q931_name->valid) {
++ pri_name->valid = 1;
++ pri_name->presentation = q931_name->presentation;
++ pri_name->char_set = q931_name->char_set;
++ libpri_copy_string(pri_name->str, q931_name->str, sizeof(pri_name->str));
++ } else {
++ pri_name->valid = 0;
++ pri_name->presentation = PRI_PRES_UNAVAILABLE;
++ pri_name->char_set = PRI_CHAR_SET_ISO8859_1;
++ pri_name->str[0] = 0;
++ }
++}
++
++/*!
++ * \brief Copy the Q.931 party number to the PRI party number structure.
++ *
++ * \param pri_number PRI party number structure
++ * \param q931_number Q.931 party number structure
++ *
++ * \return Nothing
++ */
++void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number)
++{
++ if (q931_number->valid) {
++ pri_number->valid = 1;
++ pri_number->presentation = q931_number->presentation;
++ pri_number->plan = q931_number->plan;
++ libpri_copy_string(pri_number->str, q931_number->str, sizeof(pri_number->str));
++ } else {
++ pri_number->valid = 0;
++ pri_number->presentation = PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
++ pri_number->plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
++ pri_number->str[0] = 0;
++ }
++}
++
++/*!
++ * \brief Copy the Q.931 party subaddress to the PRI party subaddress structure.
++ *
++ * \param pri_subaddress PRI party subaddress structure
++ * \param q931_subaddress Q.931 party subaddress structure
++ *
++ * \return Nothing
++ */
++void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress)
++{
++ int length;
++
++ /*
++ * The size of pri_subaddress->data[] is not the same as the size of
++ * q931_subaddress->data[].
++ */
++
++ if (!q931_subaddress->valid) {
++ pri_subaddress->valid = 0;
++ pri_subaddress->type = 0;
++ pri_subaddress->odd_even_indicator = 0;
++ pri_subaddress->length = 0;
++ pri_subaddress->data[0] = '\0';
++ return;
++ }
++
++ pri_subaddress->valid = 1;
++ pri_subaddress->type = q931_subaddress->type;
++ pri_subaddress->odd_even_indicator = q931_subaddress->odd_even_indicator;
++
++ length = q931_subaddress->length;
++ pri_subaddress->length = length;
++ memcpy(pri_subaddress->data, q931_subaddress->data, length);
++ pri_subaddress->data[length] = '\0';
++}
++
++/*!
++ * \brief Copy the Q.931 party id to the PRI party id structure.
++ *
++ * \param pri_id PRI party id structure
++ * \param q931_id Q.931 party id structure
++ *
++ * \return Nothing
++ */
++void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id)
++{
++ q931_party_name_copy_to_pri(&pri_id->name, &q931_id->name);
++ q931_party_number_copy_to_pri(&pri_id->number, &q931_id->number);
++ q931_party_subaddress_copy_to_pri(&pri_id->subaddress, &q931_id->subaddress);
++}
++
++/*!
++ * \brief Copy the Q.931 redirecting data to the PRI redirecting structure.
++ *
++ * \param pri_redirecting PRI redirecting structure
++ * \param q931_redirecting Q.931 redirecting structure
++ *
++ * \return Nothing
++ */
++void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting)
++{
++ q931_party_id_copy_to_pri(&pri_redirecting->from, &q931_redirecting->from);
++ q931_party_id_copy_to_pri(&pri_redirecting->to, &q931_redirecting->to);
++ q931_party_id_copy_to_pri(&pri_redirecting->orig_called,
++ &q931_redirecting->orig_called);
++ pri_redirecting->count = q931_redirecting->count;
++ pri_redirecting->orig_reason = q931_redirecting->orig_reason;
++ pri_redirecting->reason = q931_redirecting->reason;
++}
++
++/*!
++ * \brief Fixup some values in the q931_party_id that may be objectionable by switches.
++ *
++ * \param ctrl D channel controller.
++ * \param id Party ID to tweak.
++ *
++ * \return Nothing
++ */
++void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id)
++{
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_DMS100:
++ case PRI_SWITCH_ATT4ESS:
++ /* Doesn't like certain presentation types */
++ if (id->number.valid && !(id->number.presentation & 0x7c)) {
++ /* i.e., If presentation is allowed it must be a network number */
++ id->number.presentation = PRES_ALLOWED_NETWORK_NUMBER;
++ }
++ break;
++ default:
++ break;
++ }
++}
++
++/*!
++ * \brief Determine the overall presentation value for the given party.
++ *
++ * \param id Party to determine the overall presentation value.
++ *
++ * \return Overall presentation value for the given party.
++ */
++int q931_party_id_presentation(const struct q931_party_id *id)
++{
++ int number_priority;
++ int number_value;
++ int number_screening;
++ int name_priority;
++ int name_value;
++
++ /* Determine name presentation priority. */
++ if (!id->name.valid) {
++ name_value = PRI_PRES_UNAVAILABLE;
++ name_priority = 3;
++ } else {
++ name_value = id->name.presentation & PRI_PRES_RESTRICTION;
++ switch (name_value) {
++ case PRI_PRES_RESTRICTED:
++ name_priority = 0;
++ break;
++ case PRI_PRES_ALLOWED:
++ name_priority = 1;
++ break;
++ case PRI_PRES_UNAVAILABLE:
++ name_priority = 2;
++ break;
++ default:
++ name_value = PRI_PRES_UNAVAILABLE;
++ name_priority = 3;
++ break;
++ }
++ }
++
++ /* Determine number presentation priority. */
++ if (!id->number.valid) {
++ number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
++ number_value = PRI_PRES_UNAVAILABLE;
++ number_priority = 3;
++ } else {
++ number_screening = id->number.presentation & PRI_PRES_NUMBER_TYPE;
++ number_value = id->number.presentation & PRI_PRES_RESTRICTION;
++ switch (number_value) {
++ case PRI_PRES_RESTRICTED:
++ number_priority = 0;
++ break;
++ case PRI_PRES_ALLOWED:
++ number_priority = 1;
++ break;
++ case PRI_PRES_UNAVAILABLE:
++ number_priority = 2;
++ break;
++ default:
++ number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
++ number_value = PRI_PRES_UNAVAILABLE;
++ number_priority = 3;
++ break;
++ }
++ }
++
++ /* Select the wining presentation value. */
++ if (name_priority < number_priority) {
++ number_value = name_value;
++ }
++
++ return number_value | number_screening;
++}
++
++static void q931_clr_subcommands(struct pri *ctrl)
++{
++ ctrl->subcmds.counter_subcmd = 0;
++}
++
++struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl)
++{
++ if (ctrl->subcmds.counter_subcmd < PRI_MAX_SUBCOMMANDS) {
++ return &ctrl->subcmds.subcmd[ctrl->subcmds.counter_subcmd++];
++ }
++
++ return NULL;
++}
++
+ static char *code2str(int code, struct msgtype *codes, int max)
+ {
+ int x;
+@@ -258,15 +795,18 @@
+ return "Unknown";
+ }
+
+-static void call_init(struct q931_call *c)
++static char *pritype(int type)
+ {
+- c->forceinvert = -1;
+- c->cr = -1;
+- c->slotmap = -1;
+- c->channelno = -1;
+- c->newcall = 1;
+- c->ourcallstate = Q931_CALL_STATE_NULL;
+- c->peercallstate = Q931_CALL_STATE_NULL;
++ switch (type) {
++ case PRI_CPE:
++ return "CPE";
++ break;
++ case PRI_NETWORK:
++ return "NET";
++ break;
++ default:
++ return "UNKNOWN";
++ }
+ }
+
+ static char *binary(int b, int len) {
+@@ -280,56 +820,85 @@
+ return res;
+ }
+
+-static FUNC_RECV(receive_channel_id)
++static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ int x;
+- int pos=0;
+-#ifdef NO_BRI_SUPPORT
+- if (!ie->data[0] & 0x20) {
+- pri_error(pri, "!! Not PRI type!?\n");
+- return -1;
+- }
+-#endif
+-#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
+- if (pri->bri) {
+- if (!(ie->data[0] & 3))
+- call->justsignalling = 1;
+- else
+- call->channelno = ie->data[0] & 3;
++ int pos = 0;
++ int need_extended_channel_octets;/*!< TRUE if octets 3.2 and 3.3 need to be present. */
++
++ if (ie->data[0] & 0x08) {
++ call->chanflags = FLAG_EXCLUSIVE;
+ } else {
+- switch (ie->data[0] & 3) {
+- case 0:
+- call->justsignalling = 1;
+- break;
+- case 1:
+- break;
+- default:
+- pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
+- return -1;
++ call->chanflags = FLAG_PREFERRED;
++ }
++
++ need_extended_channel_octets = 0;
++ if (ie->data[0] & 0x20) {
++ /* PRI encoded interface type */
++ switch (ie->data[0] & 0x03) {
++ case 0x00:
++ /* No channel */
++ call->channelno = 0;
++ call->chanflags = FLAG_PREFERRED;
++ break;
++ case 0x01:
++ /* As indicated in following octets */
++ need_extended_channel_octets = 1;
++ break;
++ case 0x03:
++ /* Any channel */
++ call->chanflags = FLAG_PREFERRED;
++ break;
++ default:
++ pri_error(ctrl, "!! Unexpected Channel selection %d\n", ie->data[0] & 0x03);
++ return -1;
+ }
++ } else {
++ /* BRI encoded interface type */
++ switch (ie->data[0] & 0x03) {
++ case 0x00:
++ /* No channel */
++ call->channelno = 0;
++ call->chanflags = FLAG_PREFERRED;
++ break;
++ case 0x03:
++ /* Any channel */
++ call->chanflags = FLAG_PREFERRED;
++ break;
++ default:
++ /* Specified B channel (B1 or B2) */
++ call->channelno = ie->data[0] & 0x03;
++ break;
++ }
+ }
+-#endif
+- if (ie->data[0] & 0x08)
+- call->chanflags = FLAG_EXCLUSIVE;
+- else
+- call->chanflags = FLAG_PREFERRED;
++
+ pos++;
+ if (ie->data[0] & 0x40) {
+ /* DS1 specified -- stop here */
+ call->ds1no = ie->data[1] & 0x7f;
+ call->ds1explicit = 1;
+ pos++;
+- } else
++ } else {
+ call->ds1explicit = 0;
++ }
+
+- if (pos+2 < len) {
++ if (ie->data[0] & 0x04) {
++ /* D channel call. Signaling only. */
++ call->cis_call = 1;
++ call->chanflags = FLAG_EXCLUSIVE;/* For safety mark this channel as exclusive. */
++ call->channelno = 0;
++ return 0;
++ }
++
++ if (need_extended_channel_octets && pos + 2 < len) {
+ /* More coming */
+ if ((ie->data[pos] & 0x0f) != 3) {
+- pri_error(pri, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
++ /* Channel type/mapping is not for B channel units. */
++ pri_error(ctrl, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
+ return -1;
+ }
+ if ((ie->data[pos] & 0x60) != 0) {
+- pri_error(pri, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
++ pri_error(ctrl, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
+ return -1;
+ }
+ if (ie->data[pos] & 0x10) {
+@@ -340,136 +909,167 @@
+ call->slotmap <<= 8;
+ call->slotmap |= ie->data[x + pos];
+ }
+- return 0;
+ } else {
+ pos++;
+ /* Only expect a particular channel */
+ call->channelno = ie->data[pos] & 0x7f;
+- if (pri->chan_mapping_logical && call->channelno > 15)
++ if (ctrl->chan_mapping_logical && call->channelno > 15)
+ call->channelno++;
+- return 0;
+ }
+- } else
+- return 0;
+- return -1;
++ }
++ return 0;
+ }
+
+-static FUNC_SEND(transmit_channel_id)
++static int transmit_channel_id(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+- int pos=0;
++ int pos = 0;
+
+-
+ /* We are ready to transmit single IE only */
+ if (order > 1)
+ return 0;
+-
+- if (call->justsignalling) {
+- ie->data[pos++] = 0xac; /* Read the standards docs to figure this out
+- ECMA-165 section 7.3 */
++
++ if (call->cis_call) {
++ /*
++ * Read the standards docs to figure this out.
++ * Q.SIG ECMA-165 section 7.3
++ * ITU Q.931 section 4.5.13
++ */
++ ie->data[pos++] = ctrl->bri ? 0x8c : 0xac;
+ return pos + 2;
+ }
+-
++
+ /* Start with standard stuff */
+- if (pri->switchtype == PRI_SWITCH_GR303_TMC)
++ if (ctrl->switchtype == PRI_SWITCH_GR303_TMC)
+ ie->data[pos] = 0x69;
+- else if (pri->bri) {
++ else if (ctrl->bri) {
+ ie->data[pos] = 0x80;
+- if (call->channelno > -1)
+- ie->data[pos] |= (call->channelno & 0x3);
+- } else
+- ie->data[pos] = 0xa1;
+- /* Add exclusive flag if necessary */
+- if (call->chanflags & FLAG_EXCLUSIVE)
++ ie->data[pos] |= (call->channelno & 0x3);
++ } else {
++ /* PRI */
++ if (call->slotmap != -1 || (call->chanflags & FLAG_WHOLE_INTERFACE)) {
++ /* Specified channel */
++ ie->data[pos] = 0xa1;
++ } else if (call->channelno < 0 || call->channelno == 0xff) {
++ /* Any channel */
++ ie->data[pos] = 0xa3;
++ } else if (!call->channelno) {
++ /* No channel */
++ ie->data[pos] = 0xa0;
++ } else {
++ /* Specified channel */
++ ie->data[pos] = 0xa1;
++ }
++ }
++ if (call->chanflags & FLAG_EXCLUSIVE) {
++ /* Channel is exclusive */
+ ie->data[pos] |= 0x08;
+- else if (!(call->chanflags & FLAG_PREFERRED)) {
++ } else if (!call->chanflags) {
+ /* Don't need this IE */
+ return 0;
+ }
+
+- if (((pri->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit) {
+- /* Note that we are specifying the identifier */
++ if (!ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
++ /* We are specifying the interface. Octet 3.1 */
+ ie->data[pos++] |= 0x40;
+- /* We need to use the Channel Identifier Present thingy. Just specify it and we're done */
+ ie->data[pos++] = 0x80 | call->ds1no;
+- } else
+- pos++;
++ } else {
++ ++pos;
++ }
+
+- if (pri->bri)
+- return pos + 2;
++ if (!ctrl->bri && (ie->data[0] & 0x03) == 0x01 /* Specified channel */
++ && !(call->chanflags & FLAG_WHOLE_INTERFACE)) {
++ /* The 3.2 and 3.3 octets need to be present */
++ ie->data[pos] = 0x83;
++ if (call->slotmap != -1) {
++ int octet;
+
+- if ((call->channelno > -1) || (call->slotmap != -1)) {
+- /* We'll have the octet 8.2 and 8.3's present */
+- ie->data[pos++] = 0x83;
+- if (call->channelno > -1) {
++ /* We have to send a channel map */
++ ie->data[pos++] |= 0x10;
++ for (octet = 3; octet--;) {
++ ie->data[pos++] = (call->slotmap >> (8 * octet)) & 0xff;
++ }
++ } else {
+ /* Channel number specified */
+- if (pri->chan_mapping_logical && call->channelno > 16)
++ ++pos;
++ if (ctrl->chan_mapping_logical && call->channelno > 16) {
+ ie->data[pos++] = 0x80 | (call->channelno - 1);
+- else
++ } else {
+ ie->data[pos++] = 0x80 | call->channelno;
+- return pos + 2;
++ }
+ }
+- /* We have to send a channel map */
+- if (call->slotmap != -1) {
+- ie->data[pos-1] |= 0x10;
+- ie->data[pos++] = (call->slotmap & 0xff0000) >> 16;
+- ie->data[pos++] = (call->slotmap & 0xff00) >> 8;
+- ie->data[pos++] = (call->slotmap & 0xff);
+- return pos + 2;
+- }
+ }
+- if (call->ds1no > 0) {
+- /* We're done */
+- return pos + 2;
+- }
+- pri_error(pri, "!! No channel map, no channel, and no ds1? What am I supposed to identify?\n");
+- return -1;
++
++ return pos + 2;
+ }
+
+-static FUNC_DUMP(dump_channel_id)
++static void dump_channel_id(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- int pos=0;
++ int pos;
+ int x;
+- int res = 0;
+- static const char* msg_chan_sel[] = {
+- "No channel selected", "B1 channel", "B2 channel","Any channel selected",
+- "No channel selected", "As indicated in following octets", "Reserved","Any channel selected"
++ int res;
++
++ static const char *msg_chan_sel[] = {
++ "No channel selected", "B1 channel", "B2 channel", "Any channel selected",
++ "No channel selected", "As indicated in following octets", "Reserved", "Any channel selected"
+ };
+
+- pri_message(pri, "%c Channel ID (len=%2d) [ Ext: %d IntID: %s %s Spare: %d %s Dchan: %d\n",
+- prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
+- (ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0,
+- (ie->data[0] & 0x08) ? "Exclusive" : "Preferred", (ie->data[0] & 0x04) ? 1 : 0);
+- pri_message(pri, "%c ChanSel: %s\n",
+- prefix, msg_chan_sel[(ie->data[0] & 0x3) + ((ie->data[0]>>3) & 0x4)]);
+- pos++;
+- len--;
+- if (ie->data[0] & 0x40) {
++ pri_message(ctrl,
++ "%c Channel ID (len=%2d) [ Ext: %d IntID: %s %s Spare: %d %s Dchan: %d\n",
++ prefix, len,
++ (ie->data[0] & 0x80) ? 1 : 0,
++ (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
++ (ie->data[0] & 0x20) ? "Other(PRI)" : "BRI",
++ (ie->data[0] & 0x10) ? 1 : 0,
++ (ie->data[0] & 0x08) ? "Exclusive" : "Preferred",
++ (ie->data[0] & 0x04) ? 1 : 0);
++ pri_message(ctrl, "%c ChanSel: %s\n",
++ prefix, msg_chan_sel[(ie->data[0] & 0x03) | ((ie->data[0] >> 3) & 0x04)]);
++ pos = 1;
++ len -= 2;
++ if (ie->data[0] & 0x40) {
+ /* Explicitly defined DS1 */
+- pri_message(pri, "%c Ext: %d DS1 Identifier: %d \n", prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
+- pos++;
++ do {
++ pri_message(ctrl, "%c Ext: %d DS1 Identifier: %d \n",
++ prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
++ ++pos;
++ } while (!(ie->data[pos - 1] & 0x80) && pos < len);
+ } else {
+ /* Implicitly defined DS1 */
+ }
+- if (pos+2 < len) {
++ if (pos < len) {
+ /* Still more information here */
+- pri_message(pri, "%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
+- prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
+- (ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
+- if (!(ie->data[pos] & 0x10)) {
++ pri_message(ctrl,
++ "%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
++ prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
++ (ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
++ ++pos;
++ }
++ if (pos < len) {
++ if (!(ie->data[pos - 1] & 0x10)) {
+ /* Number specified */
+- pos++;
+- pri_message(pri, "%c Ext: %d Channel: %d ]\n", prefix, (ie->data[pos] & 0x80) >> 7,
+- (ie->data[pos]) & 0x7f);
++ do {
++ pri_message(ctrl,
++ "%c Ext: %d Channel: %d Type: %s%c\n",
++ prefix, (ie->data[pos] & 0x80) >> 7,
++ (ie->data[pos]) & 0x7f, pritype(ctrl->localtype),
++ (pos + 1 < len) ? ' ' : ']');
++ ++pos;
++ } while (pos < len);
+ } else {
+- pos++;
+ /* Map specified */
+- for (x=0;x<3;x++) {
++ res = 0;
++ x = 0;
++ do {
+ res <<= 8;
+ res |= ie->data[pos++];
+- }
+- pri_message(pri, "%c Map: %s ]\n", prefix, binary(res, 24));
++ ++x;
++ } while (pos < len);
++ pri_message(ctrl, "%c Map len: %d Map: %s ]\n", prefix,
++ x, binary(res, x << 3));
+ }
+- } else pri_message(pri, " ]\n");
++ } else {
++ pri_message(ctrl, " ]\n");
++ }
+ }
+
+ static char *ri2str(int ri)
+@@ -482,20 +1082,20 @@
+ return code2str(ri, ris, sizeof(ris) / sizeof(ris[0]));
+ }
+
+-static FUNC_DUMP(dump_restart_indicator)
++static void dump_restart_indicator(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c Restart Indentifier (len=%2d) [ Ext: %d Spare: %d Resetting %s (%d) ]\n",
++ pri_message(ctrl, "%c Restart Indentifier (len=%2d) [ Ext: %d Spare: %d Resetting %s (%d) ]\n",
+ prefix, len, (ie->data[0] & 0x80) >> 7, (ie->data[0] & 0x78) >> 3, ri2str(ie->data[0] & 0x7), ie->data[0] & 0x7);
+ }
+
+-static FUNC_RECV(receive_restart_indicator)
++static int receive_restart_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ /* Pretty simple */
+ call->ri = ie->data[0] & 0x7;
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_restart_indicator)
++static int transmit_restart_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ /* Pretty simple */
+ switch(call->ri) {
+@@ -509,7 +1109,7 @@
+ ie->data[0] = 0xA0 | (call->ri & 0x7);
+ break;
+ default:
+- pri_error(pri, "!! Invalid restart indicator value %d\n", call->ri);
++ pri_error(ctrl, "!! Invalid restart indicator value %d\n", call->ri);
+ return-1;
+ }
+ return 3;
+@@ -607,16 +1207,16 @@
+ return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
+ }
+
+-static FUNC_DUMP(dump_bearer_capability)
++static void dump_bearer_capability(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ int pos=2;
+- pri_message(pri, "%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
++ pri_message(ctrl, "%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
+ prefix, len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
+- pri_message(pri, "%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
++ pri_message(ctrl, "%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
+
+ /* octet 4.1 exists iff mode/rate is multirate */
+ if ((ie->data[1] & 0x7f) == 0x18) {
+- pri_message(pri, "%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
++ pri_message(ctrl, "%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
+ pos++;
+ }
+
+@@ -632,7 +1232,7 @@
+ too, so we have to do the same for binary compatability */
+ u_int8_t layer1 = ie->data[pos] & 0x7f;
+
+- pri_message(pri, "%c User information layer 1: %s (%d)\n",
++ pri_message(ctrl, "%c User information layer 1: %s (%d)\n",
+ prefix, l12str(layer1), layer1);
+ pos++;
+
+@@ -640,7 +1240,7 @@
+ if (pos < len && !(ie->data[pos-1] & 0x80)) {
+ int ra = ie->data[pos] & 0x7f;
+
+- pri_message(pri, "%c Async: %d, Negotiation: %d, "
++ pri_message(ctrl, "%c Async: %d, Negotiation: %d, "
+ "User rate: %s (%#x)\n",
+ prefix,
+ ra & PRI_RATE_ADAPT_ASYNC ? 1 : 0,
+@@ -654,7 +1254,7 @@
+ if (pos < len && !(ie->data[pos-1] & 0x80)) {
+ u_int8_t data = ie->data[pos];
+ if (layer1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
+- pri_message(pri, "%c Intermediate rate: %s (%d), "
++ pri_message(ctrl, "%c Intermediate rate: %s (%d), "
+ "NIC on Tx: %d, NIC on Rx: %d, "
+ "Flow control on Tx: %d, "
+ "Flow control on Rx: %d\n",
+@@ -665,7 +1265,7 @@
+ (data & 0x04)?1:0,
+ (data & 0x02)?1:0);
+ } else if (layer1 == PRI_LAYER_1_V120_RATE_ADAPT) {
+- pri_message(pri, "%c Hdr: %d, Multiframe: %d, Mode: %d, "
++ pri_message(ctrl, "%c Hdr: %d, Multiframe: %d, Mode: %d, "
+ "LLI negot: %d, Assignor: %d, "
+ "In-band neg: %d\n", prefix,
+ (data & 0x40)?1:0,
+@@ -675,7 +1275,8 @@
+ (data & 0x04)?1:0,
+ (data & 0x02)?1:0);
+ } else {
+- pri_message(pri, "%c Unknown octet 5b: 0x%x\n", data );
++ pri_message(ctrl, "%c Unknown octet 5b: 0x%x\n",
++ prefix, data);
+ }
+ pos++;
+ }
+@@ -688,7 +1289,7 @@
+ const char *parity[] = {"Odd","?","Even","None",
+ "zero","one","?","?"};
+
+- pri_message(pri, "%c Stop bits: %s, data bits: %s, "
++ pri_message(ctrl, "%c Stop bits: %s, data bits: %s, "
+ "parity: %s\n", prefix,
+ stop_bits[(data & 0x60) >> 5],
+ data_bits[(data & 0x18) >> 3],
+@@ -700,7 +1301,7 @@
+ /* octet 5d? */
+ if (pos < len && !(ie->data[pos-1] & 0x80)) {
+ u_int8_t data = ie->data[pos];
+- pri_message(pri, "%c Duplex mode: %d, modem type: %d\n",
++ pri_message(ctrl, "%c Duplex mode: %d, modem type: %d\n",
+ prefix, (data & 0x40) ? 1 : 0,data & 0x3F);
+ pos++;
+ }
+@@ -710,7 +1311,7 @@
+ /* Look for octet 6; this is identified by bits 5,6 == 10 */
+ if (pos < len &&
+ (ie->data[pos] & 0x60) == 0x40) {
+- pri_message(pri, "%c User information layer 2: %s (%d)\n",
++ pri_message(ctrl, "%c User information layer 2: %s (%d)\n",
+ prefix, l22str(ie->data[pos] & 0x1f),
+ ie->data[pos] & 0x1f);
+ pos++;
+@@ -718,7 +1319,7 @@
+
+ /* Look for octet 7; this is identified by bits 5,6 == 11 */
+ if (pos < len && (ie->data[pos] & 0x60) == 0x60) {
+- pri_message(pri, "%c User information layer 3: %s (%d)\n",
++ pri_message(ctrl, "%c User information layer 3: %s (%d)\n",
+ prefix, l32str(ie->data[pos] & 0x1f),
+ ie->data[pos] & 0x1f);
+ pos++;
+@@ -730,18 +1331,18 @@
+ proto = ((ie->data[pos] & 0xF) << 4 ) |
+ (ie->data[pos+1] & 0xF);
+
+- pri_message(pri, "%c Network layer: 0x%x\n", prefix,
++ pri_message(ctrl, "%c Network layer: 0x%x\n", prefix,
+ proto );
+ pos += 2;
+ }
+ }
+ }
+
+-static FUNC_RECV(receive_bearer_capability)
++static int receive_bearer_capability(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ int pos=2;
+ if (ie->data[0] & 0x60) {
+- pri_error(pri, "!! non-standard Q.931 standard field\n");
++ pri_error(ctrl, "!! non-standard Q.931 standard field\n");
+ return -1;
+ }
+ call->transcapability = ie->data[0] & 0x1f;
+@@ -788,7 +1389,7 @@
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_bearer_capability)
++static int transmit_bearer_capability(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ int tc;
+ int pos;
+@@ -797,20 +1398,20 @@
+ if(order > 1)
+ return 0;
+
+- tc = call->transcapability;
+- if (pri->subchannel && !pri->bri) {
++ if (ctrl->subchannel && !ctrl->bri) {
+ /* Bearer capability is *hard coded* in GR-303 */
+ ie->data[0] = 0x88;
+ ie->data[1] = 0x90;
+ return 4;
+ }
+-
+- if (call->justsignalling) {
++
++ if (call->cis_call) {
+ ie->data[0] = 0xa8;
+ ie->data[1] = 0x80;
+ return 4;
+ }
+-
++
++ tc = call->transcapability;
+ ie->data[0] = 0x80 | tc;
+ ie->data[1] = call->transmoderate | 0x80;
+
+@@ -820,7 +1421,7 @@
+ ie->data[pos++] = call->transmultiple | 0x80;
+ }
+
+- if ((tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&
++ if ((tc & PRI_TRANS_CAP_DIGITAL) && (ctrl->switchtype == PRI_SWITCH_EUROISDN_E1) &&
+ (call->transmoderate == TRANS_MODE_PACKET)) {
+ /* Apparently EuroISDN switches don't seem to like user layer 2/3 */
+ return 4;
+@@ -833,7 +1434,7 @@
+
+ if (call->transmoderate != TRANS_MODE_PACKET) {
+ /* If you have an AT&T 4ESS, you don't send any more info */
+- if ((pri->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
++ if ((ctrl->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
+ ie->data[pos++] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
+ if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
+ ie->data[pos++] = call->rateadaption | 0x80;
+@@ -908,6 +1509,30 @@
+ return code2str(plan, plans, sizeof(plans) / sizeof(plans[0]));
+ }
+
++/* Calling Party Category (Definitions from Q.763) */
++static char *cpc2str(int plan)
++{
++ static struct msgtype plans[] = {
++ { 0, "Unknown Source" },
++ { 1, "Operator French" },
++ { 2, "Operator English" },
++ { 3, "Operator German" },
++ { 4, "Operator Russian" },
++ { 5, "Operator Spanish" },
++ { 6, "Mut Agree Chinese" },
++ { 7, "Mut Agreement" },
++ { 8, "Mut Agree Japanese" },
++ { 9, "National Operator" },
++ { 10, "Ordinary Toll Caller" },
++ { 11, "Priority Toll Caller" },
++ { 12, "Data Call" },
++ { 13, "Test Call" },
++ { 14, "Spare" },
++ { 15, "Pay Phone" },
++ };
++ return code2str(plan, plans, ARRAY_LEN(plans));
++}
++
+ char *pri_pres2str(int pres)
+ {
+ static struct msgtype press[] = {
+@@ -934,51 +1559,134 @@
+ num[len] = 0;
+ }
+
+-static FUNC_DUMP(dump_called_party_number)
++static void q931_get_subaddr_specific(unsigned char *num, int maxlen, unsigned char *src, int len, char oddflag)
+ {
+- unsigned char cnum[256];
++ /* User Specified */
++ int x;
++ char *ptr = (char *) num;
+
+- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
+- pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
+- prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
++ if (len <= 0) {
++ num[0] = '\0';
++ return;
++ }
++
++ if (((len * 2) + 1) > maxlen) {
++ len = (maxlen / 2) - 1;
++ }
++
++ for (x = 0; x < (len - 1); ++x) {
++ ptr += sprintf(ptr, "%02x", src[x]);
++ }
++
++ if (oddflag) {
++ /* ODD */
++ sprintf(ptr, "%01x", (src[len - 1]) >> 4);
++ } else {
++ /* EVEN */
++ sprintf(ptr, "%02x", src[len - 1]);
++ }
+ }
+
+-static FUNC_DUMP(dump_called_party_subaddr)
++static int transmit_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len, int order)
+ {
++ size_t datalen;
++
++ if (!q931_subaddress->valid) {
++ return 0;
++ }
++
++ datalen = q931_subaddress->length;
++ if (!q931_subaddress->type) {
++ /* 0 = NSAP */
++ /* 0 = Odd/Even indicator */
++ ie->data[0] = 0x80;
++ } else {
++ /* 2 = User Specified */
++ ie->data[0] = q931_subaddress->odd_even_indicator ? 0xA8 : 0xA0;
++ }
++ memcpy(ie->data + offset, q931_subaddress->data, datalen);
++
++ return datalen + (offset + 2);
++}
++
++static int receive_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len)
++{
++ if (len <= 0) {
++ return -1;
++ }
++
++ q931_subaddress->valid = 1;
++ q931_subaddress->length = len;
++ /* type: 0 = NSAP, 2 = User Specified */
++ q931_subaddress->type = ((ie->data[0] & 0x70) >> 4);
++ q931_subaddress->odd_even_indicator = (ie->data[0] & 0x08) ? 1 : 0;
++ q931_get_number(q931_subaddress->data, sizeof(q931_subaddress->data),
++ ie->data + offset, len);
++
++ return 0;
++}
++
++static void dump_subaddr_helper(int full_ie, struct pri *ctrl, q931_ie *ie, int offset, int len, int datalen, char prefix, const char *named)
++{
+ unsigned char cnum[256];
+- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
+- pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
+- prefix, len, ie->data[0] >> 7,
++
++ if (!(ie->data[0] & 0x70)) {
++ /* NSAP */
++ q931_get_number(cnum, sizeof(cnum), ie->data + offset, datalen);
++ } else {
++ /* User Specified */
++ q931_get_subaddr_specific(cnum, sizeof(cnum), ie->data + offset, datalen,
++ ie->data[0] & 0x08);
++ }
++
++ pri_message(ctrl,
++ "%c %s Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
++ prefix, named, len, ie->data[0] >> 7,
+ subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
+ (ie->data[0] & 0x08) >> 3, cnum);
+ }
+
+-static FUNC_DUMP(dump_calling_party_number)
++static void dump_called_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ unsigned char cnum[256];
++
++ q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
++ pri_message(ctrl, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
++ prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
++}
++
++static void dump_called_party_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
++ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Called");
++}
++
++static void dump_calling_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
++ unsigned char cnum[256];
+ if (ie->data[0] & 0x80)
+ q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
+ else
+ q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
+- pri_message(pri, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
++ pri_message(ctrl, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
+ if (ie->data[0] & 0x80)
+- pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
++ pri_message(ctrl, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
+ else
+- pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
++ pri_message(ctrl, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
+ }
+
+-static FUNC_DUMP(dump_calling_party_subaddr)
++static void dump_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- unsigned char cnum[256];
+- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
+- pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
+- prefix, len, ie->data[0] >> 7,
+- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
+- (ie->data[0] & 0x08) >> 3, cnum);
++ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Calling");
+ }
+
+-static FUNC_DUMP(dump_redirecting_number)
++static void dump_calling_party_category(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
++ pri_message(ctrl, "%c Calling Party Category (len=%2d) [ Ext: %d Cat: %s (%d) ]\n",
++ prefix, len, ie->data[0] >> 7, cpc2str(ie->data[0] & 0x0F), ie->data[0] & 0x0F);
++}
++
++static void dump_redirecting_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
+ unsigned char cnum[256];
+ int i = 0;
+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
+@@ -986,172 +1694,369 @@
+ do {
+ switch(i) {
+ case 0: /* Octet 3 */
+- pri_message(pri, "%c Redirecting Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
++ pri_message(ctrl, "%c Redirecting Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
+ prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
+ break;
+ case 1: /* Octet 3a */
+- pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
++ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
+ prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
+ break;
+ case 2: /* Octet 3b */
+- pri_message(pri, "\n%c Ext: %d Reason: %s (%d)",
++ pri_message(ctrl, "\n%c Ext: %d Reason: %s (%d)",
+ prefix, ie->data[2] >> 7, redirection_reason2str(ie->data[2] & 0x7f), ie->data[2] & 0x7f);
+ break;
+ }
+- }
+- while(!(ie->data[i++]& 0x80));
++ } while(!(ie->data[i++]& 0x80));
+ q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
+- pri_message(pri, " '%s' ]\n", cnum);
++ pri_message(ctrl, " '%s' ]\n", cnum);
+ }
+
+-static FUNC_DUMP(dump_connected_number)
++static void dump_redirection_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ unsigned char cnum[256];
+ int i = 0;
+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
+ walking through all bytes until one with ext bit (8) set to 1 */
+ do {
++ switch (i) {
++ case 0: /* Octet 3 */
++ pri_message(ctrl,
++ "%c Redirection Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
++ prefix, len, ie->data[0] >> 7,
++ ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07,
++ npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
++ break;
++ case 1: /* Octet 3a */
++ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
++ prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
++ break;
++ }
++ } while (!(ie->data[i++] & 0x80));
++ q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
++ pri_message(ctrl, " '%s' ]\n", cnum);
++}
++
++static int receive_connected_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
++{
++ int i = 0;
++
++ call->connected_number_in_message = 1;
++ call->remote_id.number.valid = 1;
++ call->remote_id.number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
++ walking through all bytes until one with ext bit (8) set to 1 */
++ do {
++ switch (i) {
++ case 0:
++ call->remote_id.number.plan = ie->data[i] & 0x7f;
++ break;
++ case 1:
++ /* Keep only the presentation and screening fields */
++ call->remote_id.number.presentation =
++ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
++ break;
++ }
++ } while (!(ie->data[i++] & 0x80));
++ q931_get_number((unsigned char *) call->remote_id.number.str, sizeof(call->remote_id.number.str), ie->data + i, ie->len - i);
++
++ return 0;
++}
++
++static int transmit_connected_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
++{
++ size_t datalen;
++
++ if (!call->local_id.number.valid) {
++ return 0;
++ }
++
++ datalen = strlen(call->local_id.number.str);
++ ie->data[0] = call->local_id.number.plan;
++ ie->data[1] = 0x80 | call->local_id.number.presentation;
++ memcpy(ie->data + 2, call->local_id.number.str, datalen);
++ return datalen + (2 + 2);
++}
++
++static void dump_connected_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
++ unsigned char cnum[256];
++ int i = 0;
++ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
++ walking through all bytes until one with ext bit (8) set to 1 */
++ do {
+ switch(i) {
+ case 0: /* Octet 3 */
+- pri_message(pri, "%c Connected Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
++ pri_message(ctrl, "%c Connected Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)",
+ prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
+ break;
+ case 1: /* Octet 3a */
+- pri_message(pri, "\n%c Ext: %d Presentation: %s (%d)",
++ pri_message(ctrl, "\n%c Ext: %d Presentation: %s (%d)",
+ prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
+ break;
+ }
+- }
+- while(!(ie->data[i++]& 0x80));
++ } while(!(ie->data[i++]& 0x80));
+ q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
+- pri_message(pri, " '%s' ]\n", cnum);
++ pri_message(ctrl, " '%s' ]\n", cnum);
+ }
+
++static int receive_connected_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
++{
++ if (len < 3) {
++ return -1;
++ }
+
+-static FUNC_RECV(receive_redirecting_number)
++ return receive_subaddr_helper(full_ie, ctrl, &call->remote_id.subaddress, msgtype, ie,
++ 1, len - 3);
++}
++
++static int transmit_connected_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
++ return transmit_subaddr_helper(full_ie, ctrl, &call->local_id.subaddress, msgtype, ie,
++ 1, len, order);
++}
++
++static void dump_connected_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
++ dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Connected");
++}
++
++static int receive_redirecting_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
++{
+ int i = 0;
+
++ call->redirecting_number_in_message = 1;
++ call->redirecting.from.number.valid = 1;
++ call->redirecting.from.number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ call->redirecting.reason = PRI_REDIR_UNKNOWN;
+ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
+ walking through all bytes until one with ext bit (8) set to 1 */
+ do {
+- switch(i) {
++ switch (i) {
+ case 0:
+- call->redirectingplan = ie->data[i] & 0x7f;
++ call->redirecting.from.number.plan = ie->data[i] & 0x7f;
+ break;
+ case 1:
+- call->redirectingpres = ie->data[i] & 0x7f;
++ /* Keep only the presentation and screening fields */
++ call->redirecting.from.number.presentation =
++ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
+ break;
+ case 2:
+- call->redirectingreason = ie->data[i] & 0x0f;
++ call->redirecting.reason = ie->data[i] & 0x0f;
+ break;
+ }
+- }
+- while(!(ie->data[i++] & 0x80));
+- q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
++ } while (!(ie->data[i++] & 0x80));
++ q931_get_number((unsigned char *) call->redirecting.from.number.str, sizeof(call->redirecting.from.number.str), ie->data + i, ie->len - i);
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_redirecting_number)
++static int transmit_redirecting_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
++ size_t datalen;
++
+ if (order > 1)
+ return 0;
+- if (call->redirectingnum && *call->redirectingnum) {
+- ie->data[0] = call->redirectingplan;
+- ie->data[1] = call->redirectingpres;
+- ie->data[2] = (call->redirectingreason & 0x0f) | 0x80;
+- memcpy(ie->data + 3, call->redirectingnum, strlen(call->redirectingnum));
+- return strlen(call->redirectingnum) + 3 + 2;
++ if (!call->redirecting.from.number.valid) {
++ return 0;
+ }
+- return 0;
++
++ datalen = strlen(call->redirecting.from.number.str);
++ ie->data[0] = call->redirecting.from.number.plan;
++#if 1
++ /* ETSI and Q.952 do not define the screening field */
++ ie->data[1] = call->redirecting.from.number.presentation & PRI_PRES_RESTRICTION;
++#else
++ /* Q.931 defines the screening field */
++ ie->data[1] = call->redirecting.from.number.presentation;
++#endif
++ ie->data[2] = (call->redirecting.reason & 0x0f) | 0x80;
++ memcpy(ie->data + 3, call->redirecting.from.number.str, datalen);
++ return datalen + (3 + 2);
+ }
+
+-static FUNC_DUMP(dump_redirecting_subaddr)
++static void dump_redirecting_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- unsigned char cnum[256];
+- q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
+- pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
+- prefix, len, ie->data[0] >> 7,
+- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
+- (ie->data[0] & 0x08) >> 3, cnum);
++ dump_subaddr_helper(full_ie, ctrl, ie, 2, len, len - 4, prefix, "Redirecting");
+ }
+
+-static FUNC_RECV(receive_calling_party_subaddr)
++static int receive_redirection_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+- /* copy digits to call->callingsubaddr */
+- q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3);
++ int i = 0;
++
++ call->redirection_number.valid = 1;
++ call->redirection_number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
++ walking through all bytes until one with ext bit (8) set to 1 */
++ do {
++ switch (i) {
++ case 0:
++ call->redirection_number.plan = ie->data[i] & 0x7f;
++ break;
++ case 1:
++ /* Keep only the presentation and screening fields */
++ call->redirection_number.presentation =
++ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
++ break;
++ }
++ } while (!(ie->data[i++] & 0x80));
++ q931_get_number((unsigned char *) call->redirection_number.str, sizeof(call->redirection_number.str), ie->data + i, ie->len - i);
+ return 0;
+ }
+
+-static FUNC_RECV(receive_called_party_number)
++static int transmit_redirection_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+- /* copy digits to call->callednum */
+- q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
+- call->calledplan = ie->data[0] & 0x7f;
+- return 0;
++ size_t datalen;
++
++ if (order > 1) {
++ return 0;
++ }
++ if (!call->redirection_number.valid) {
++ return 0;
++ }
++
++ datalen = strlen(call->redirection_number.str);
++ ie->data[0] = call->redirection_number.plan;
++ ie->data[1] = (call->redirection_number.presentation & PRI_PRES_RESTRICTION) | 0x80;
++ memcpy(ie->data + 2, call->redirection_number.str, datalen);
++ return datalen + (2 + 2);
+ }
+
+-static FUNC_SEND(transmit_called_party_number)
++static int receive_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+- ie->data[0] = 0x80 | call->calledplan;
+- if (*call->callednum)
+- memcpy(ie->data + 1, call->callednum, strlen(call->callednum));
+- return strlen(call->callednum) + 3;
++ if (len < 3) {
++ return -1;
++ }
++
++ return receive_subaddr_helper(full_ie, ctrl, &call->remote_id.subaddress, msgtype, ie,
++ 1, len - 3);
+ }
+
+-static FUNC_RECV(receive_calling_party_number)
++static int transmit_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+- u_int8_t *data;
+- size_t length;
+-
+- if (ie->data[0] & 0x80) {
+- data = ie->data + 1;
+- length = len - 3;
+- call->callerpres = 0; /* PI presentation allowed SI user-provided, not screened */
+- } else {
+- data = ie->data + 2;
+- length = len - 4;
+- call->callerpres = ie->data[1] & 0x7f;
++ return transmit_subaddr_helper(full_ie, ctrl, &call->local_id.subaddress, msgtype, ie,
++ 1, len, order);
++}
++
++static int receive_called_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
++{
++ if (len < 3) {
++ return -1;
+ }
++ return receive_subaddr_helper(full_ie, ctrl, &call->called.subaddress, msgtype, ie, 1,
++ len - 3);
++}
+
+- if (call->callerpres == PRES_ALLOWED_NETWORK_NUMBER ||
+- call->callerpres == PRES_PROHIB_NETWORK_NUMBER) {
+- q931_get_number((u_int8_t *)call->callerani, sizeof(call->callerani), data, length);
+- call->callerplanani = ie->data[0] & 0x7f;
++static int transmit_called_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
++{
++ return transmit_subaddr_helper(full_ie, ctrl, &call->called.subaddress, msgtype, ie,
++ 1, len, order);
++}
+
+- if (!*call->callernum) { /*Copy ANI to CallerID if CallerID is not already set */
+- libpri_copy_string(call->callernum, call->callerani, sizeof(call->callernum));
+- call->callerplan = call->callerplanani;
++static int receive_called_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
++{
++ size_t called_len;
++ size_t max_len;
++ char *called_end;
++
++ if (len < 3) {
++ return -1;
++ }
++
++ call->called.number.valid = 1;
++ call->called.number.plan = ie->data[0] & 0x7f;
++ if (msgtype == Q931_SETUP) {
++ q931_get_number((unsigned char *) call->called.number.str,
++ sizeof(call->called.number.str), ie->data + 1, len - 3);
++ } else if (call->ourcallstate == Q931_CALL_STATE_OVERLAP_RECEIVING) {
++ /*
++ * Since we are receiving overlap digits now, we need to append
++ * them to any previously received digits in call->called.number.str.
++ */
++ called_len = strlen(call->called.number.str);
++ called_end = call->called.number.str + called_len;
++ max_len = (sizeof(call->called.number.str) - 1) - called_len;
++ if (max_len < len - 3) {
++ called_len = max_len;
++ } else {
++ called_len = len - 3;
+ }
+-
+- } else {
+- q931_get_number((u_int8_t *)call->callernum, sizeof(call->callernum), data, length);
+- call->callerplan = ie->data[0] & 0x7f;
++ strncat(called_end, (char *) ie->data + 1, called_len);
+ }
+
++ q931_get_number((unsigned char *) call->overlap_digits, sizeof(call->overlap_digits),
++ ie->data + 1, len - 3);
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_calling_party_number)
++static int transmit_called_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+- ie->data[0] = call->callerplan;
+- ie->data[1] = 0x80 | call->callerpres;
+- if (*call->callernum)
+- memcpy(ie->data + 2, call->callernum, strlen(call->callernum));
+- return strlen(call->callernum) + 4;
++ size_t datalen;
++
++ if (!call->called.number.valid) {
++ return 0;
++ }
++
++ datalen = strlen(call->overlap_digits);
++ ie->data[0] = 0x80 | call->called.number.plan;
++ memcpy(ie->data + 1, call->overlap_digits, datalen);
++ return datalen + (1 + 2);
+ }
+
+-static FUNC_DUMP(dump_user_user)
++static int receive_calling_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
++ int i = 0;
++
++ call->remote_id.number.valid = 1;
++ call->remote_id.number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
++ walking through all bytes until one with ext bit (8) set to 1 */
++ do {
++ switch (i) {
++ case 0:
++ call->remote_id.number.plan = ie->data[i] & 0x7f;
++ break;
++ case 1:
++ /* Keep only the presentation and screening fields */
++ call->remote_id.number.presentation =
++ ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
++ break;
++ }
++ } while (!(ie->data[i++] & 0x80));
++ q931_get_number((unsigned char *) call->remote_id.number.str,
++ sizeof(call->remote_id.number.str), ie->data + i, ie->len - i);
++
++ return 0;
++}
++
++static int transmit_calling_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
++{
++ size_t datalen;
++
++ if (!call->local_id.number.valid) {
++ return 0;
++ }
++
++ datalen = strlen(call->local_id.number.str);
++ ie->data[0] = call->local_id.number.plan;
++ ie->data[1] = 0x80 | call->local_id.number.presentation;
++ memcpy(ie->data + 2, call->local_id.number.str, datalen);
++ return datalen + (2 + 2);
++}
++
++static void dump_user_user(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
+ int x;
+- pri_message(pri, "%c User-User Information (len=%2d) [", prefix, len);
++ pri_message(ctrl, "%c User-User Information (len=%2d) [", prefix, len);
+ for (x=0;x<ie->len;x++)
+- pri_message(pri, " %02x", ie->data[x] & 0x7f);
+- pri_message(pri, " ]\n");
++ pri_message(ctrl, " %02x", ie->data[x] & 0x7f);
++ pri_message(ctrl, " ]\n");
+ }
+
+
+-static FUNC_RECV(receive_user_user)
++static int receive_user_user(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ call->useruserprotocoldisc = ie->data[0] & 0xff;
+ if (call->useruserprotocoldisc == 4) /* IA5 */
+@@ -1159,7 +2064,7 @@
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_user_user)
++static int transmit_user_user(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ int datalen = strlen(call->useruserinfo);
+ if (datalen > 0) {
+@@ -1180,6 +2085,29 @@
+ return 0;
+ }
+
++static void dump_change_status(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
++ int x;
++
++ pri_message(ctrl, "%c Change Status Information (len=%2d) [", prefix, len);
++ for (x=0; x<ie->len; x++) {
++ pri_message(ctrl, " %02x", ie->data[x] & 0x7f);
++ }
++ pri_message(ctrl, " ]\n");
++}
++
++static int receive_change_status(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
++{
++ call->changestatus = ie->data[0] & 0x0f;
++ return 0;
++}
++
++static int transmit_change_status(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
++{
++ ie->data[0] = 0xc0 | call->changestatus;
++ return 3;
++}
++
+ static char *prog2str(int prog)
+ {
+ static struct msgtype progs[] = {
+@@ -1222,47 +2150,83 @@
+ return code2str(loc, locs, sizeof(locs) / sizeof(locs[0]));
+ }
+
+-static FUNC_DUMP(dump_progress_indicator)
++static void dump_progress_indicator(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
++ pri_message(ctrl, "%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
+ prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
+ (ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
+- pri_message(pri, "%c Ext: %d Progress Description: %s (%d) ]\n",
++ pri_message(ctrl, "%c Ext: %d Progress Description: %s (%d) ]\n",
+ prefix, ie->data[1] >> 7, prog2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
+ }
+
+-static FUNC_RECV(receive_display)
++static int receive_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ unsigned char *data;
++
++ switch (msgtype) {
++ case Q931_SETUP:
++ case Q931_CONNECT:
++ /*
++ * Only keep the display message on SETUP and CONNECT messages
++ * as the remote name.
++ */
++ break;
++ default:
++ return 0;
++ }
++
++ call->remote_id.name.valid = 1;
++
+ data = ie->data;
+ if (data[0] & 0x80) {
+ /* Skip over character set */
+ data++;
+ len--;
+ }
+- q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
++ call->remote_id.name.char_set = PRI_CHAR_SET_ISO8859_1;
++
++ q931_get_number((unsigned char *) call->remote_id.name.str, sizeof(call->remote_id.name.str), data, len - 2);
++ if (call->remote_id.name.str[0]) {
++ call->remote_id.name.presentation = PRI_PRES_ALLOWED;
++ } else {
++ call->remote_id.name.presentation = PRI_PRES_RESTRICTED;
++ }
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_display)
++static int transmit_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
++ size_t datalen;
+ int i;
+-
+- if ((pri->switchtype == PRI_SWITCH_QSIG) ||
+- ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) && (pri->localtype == PRI_CPE)) ||
+- !call->callername[0])
+- return 0;
+
+ i = 0;
+- if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
++
++ if (!call->local_id.name.valid || !call->local_id.name.str[0]) {
++ return 0;
++ }
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_QSIG:
++ /* Q.SIG supports names */
++ return 0;
++ case PRI_SWITCH_EUROISDN_E1:
++ case PRI_SWITCH_EUROISDN_T1:
++ if (ctrl->localtype == PRI_CPE) {
++ return 0;
++ }
++ break;
++ default:
++ /* Prefix name with character set indicator. */
+ ie->data[0] = 0xb1;
+ ++i;
++ break;
+ }
+- memcpy(ie->data + i, call->callername, strlen(call->callername));
+- return 2 + i + strlen(call->callername);
++
++ datalen = strlen(call->local_id.name.str);
++ memcpy(ie->data + i, call->local_id.name.str, datalen);
++ return 2 + i + datalen;
+ }
+
+-static FUNC_RECV(receive_progress_indicator)
++static int receive_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ call->progloc = ie->data[0] & 0xf;
+ call->progcode = (ie->data[0] & 0x60) >> 5;
+@@ -1298,153 +2262,204 @@
+ call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
+ break;
+ default:
+- pri_error(pri, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
++ pri_error(ctrl, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
+ break;
+ }
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_facility)
++static void q931_apdu_timeout(void *data);
++
++static int transmit_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+- struct apdu_event *tmp;
+- int i = 0;
++ struct apdu_event **prev;
++ struct apdu_event *cur;
++ int apdu_len;
+
+- for (tmp = call->apdus; tmp; tmp = tmp->next) {
+- if ((tmp->message == msgtype) && !tmp->sent)
++ for (prev = &call->apdus, cur = call->apdus;
++ cur;
++ prev = &cur->next, cur = cur->next) {
++ if (!cur->sent && cur->message == msgtype) {
+ break;
++ }
+ }
+-
+- if (!tmp) /* No APDU found */
++ if (!cur) {
++ /* No APDU found */
+ return 0;
++ }
+
+- if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */
+- pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "Adding facility ie contents to send in %s message:\n",
++ msg2str(msgtype));
++ facility_decode_dump(ctrl, cur->apdu, cur->apdu_len);
++ }
++
++ if (len < cur->apdu_len) {
++ pri_error(ctrl,
++ "Could not fit facility ie in message. Size needed:%d Available space:%d\n",
++ cur->apdu_len + 2, len);
++
++ /* Remove APDU from list. */
++ *prev = cur->next;
++
++ if (cur->response.callback) {
++ /* Indicate to callback that the APDU had a problem getting sent. */
++ cur->response.callback(APDU_CALLBACK_REASON_ERROR, ctrl, call, cur, NULL);
++ }
++
++ free(cur);
+ return 0;
+ }
+-
+- memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len);
+- i += tmp->apdu_len;
+- tmp->sent = 1;
+
+- return i + 2;
++ memcpy(ie->data, cur->apdu, cur->apdu_len);
++ apdu_len = cur->apdu_len;
++ cur->sent = 1;
++
++ if (cur->response.callback && cur->response.timeout_time) {
++ int duration;
++
++ if (0 < cur->response.timeout_time) {
++ /* Sender specified timeout duration. */
++ duration = cur->response.timeout_time;
++ } else {
++ /* Sender wants to use the typical timeout duration. */
++ duration = ctrl->timers[PRI_TIMER_T_RESPONSE];
++ }
++ cur->timer = pri_schedule_event(ctrl, duration, q931_apdu_timeout, cur);
++ if (!cur->timer) {
++ /* Remove APDU from list. */
++ *prev = cur->next;
++
++ /* Indicate to callback that the APDU had a problem getting sent. */
++ cur->response.callback(APDU_CALLBACK_REASON_ERROR, ctrl, call, cur, NULL);
++
++ free(cur);
++ }
++ } else if (!cur->timer) {
++ /* Remove APDU from list. */
++ *prev = cur->next;
++ free(cur);
++ }
++
++ return apdu_len + 2;
+ }
+
+-static FUNC_RECV(receive_facility)
++static int receive_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+- int i = 0;
+- int protocol, next_protocol;
+- struct rose_component *comp = NULL;
+- enum {
+- Q932_STATE_NFE, /* Network facility extension */
+- Q932_STATE_NPP, /* Network protocol profile */
+- Q932_STATE_INTERPRETATION, /* Interpretation component */
+- Q932_STATE_SERVICE /* Service component(s) */
+- } state = Q932_STATE_SERVICE;
+-#define Q932_HANDLE_PROC(component, my_state, name, handler) \
+- case component: \
+- if(state > my_state) { \
+- pri_error(pri, "!! %s component received in wrong place\n"); \
+- break; \
+- } \
+- state = my_state; \
+- if (pri->debug) \
+- pri_message(pri, "Handle Q.932 %s component\n", name); \
+- (handler)(pri, call, ie, comp->data, comp->len); \
+- break;
+-#define Q932_HANDLE_NULL(component, my_state, name, handle) \
+- case component: \
+- if(state > my_state) { \
+- pri_error(pri, "!! %s component received in wrong place\n"); \
+- break; \
+- } \
+- state = my_state; \
+- if (pri->debug & PRI_DEBUG_APDU) \
+- pri_message(pri, "Q.932 %s component is not handled\n", name); \
+- break;
+-
+- if (ie->len < 1)
++ /* Delay processing facility ie's till after all other ie's are processed. */
++ if (MAX_FACILITY_IES <= ctrl->facility.count) {
++ pri_message(ctrl, "!! Too many facility ie's to delay.\n");
+ return -1;
++ }
++ /* Make sure we have enough room for the protocol profile ie octet(s) */
++ if (ie->data + ie->len < ie->data + 2) {
++ return -1;
++ }
+
+- switch(next_protocol = protocol = (ie->data[i] & 0x1f)) {
+- case Q932_PROTOCOL_CMIP:
+- case Q932_PROTOCOL_ACSE:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "!! Don't know how to handle Q.932 Protocol Profile of type 0x%X\n", protocol);
++ /* Save the facility ie location for delayed decode. */
++ ctrl->facility.ie[ctrl->facility.count] = ie;
++ ctrl->facility.codeset[ctrl->facility.count] = Q931_IE_CODESET((unsigned) full_ie);
++ ++ctrl->facility.count;
++ return 0;
++}
++
++static int process_facility(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie)
++{
++ struct fac_extension_header header;
++ struct rose_message rose;
++ const unsigned char *pos;
++ const unsigned char *end;
++
++ pos = ie->data;
++ end = ie->data + ie->len;
++
++ /* Make sure we have enough room for the protocol profile ie octet(s) */
++ if (end < pos + 2) {
+ return -1;
++ }
++ switch (*pos & Q932_PROTOCOL_MASK) {
++ case Q932_PROTOCOL_ROSE:
+ case Q932_PROTOCOL_EXTENSIONS:
+- state = Q932_STATE_NFE;
+- next_protocol = Q932_PROTOCOL_ROSE;
+ break;
+- case Q932_PROTOCOL_ROSE:
+- break;
+ default:
+- pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol);
++ case Q932_PROTOCOL_CMIP:
++ case Q932_PROTOCOL_ACSE:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl,
++ "!! Don't know how to handle Q.932 Protocol Profile type 0x%X\n",
++ *pos & Q932_PROTOCOL_MASK);
++ }
+ return -1;
+ }
+- /* Service indicator octet - Just ignore for now */
+- if (!(ie->data[i] & 0x80))
+- i++;
+- i++;
++ if (!(*pos & 0x80)) {
++ /* DMS-100 Service indicator octet - Just ignore for now */
++ ++pos;
++ }
++ ++pos;
+
+- if (ie->len < 3)
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ asn1_dump(ctrl, pos, end);
++ }
++
++ pos = fac_dec_extension_header(ctrl, pos, end, &header);
++ if (!pos) {
+ return -1;
+-
+- while ((i+1 < ie->len) && (&ie->data[i])) {
+- comp = (struct rose_component*)&ie->data[i];
+- if (comp->type) {
+- if (protocol == Q932_PROTOCOL_EXTENSIONS) {
+- switch (comp->type) {
+- Q932_HANDLE_NULL(COMP_TYPE_INTERPRETATION, Q932_STATE_INTERPRETATION, "Interpretation", NULL);
+- Q932_HANDLE_NULL(COMP_TYPE_NFE, Q932_STATE_NFE, "Network facility extensions", NULL);
+- Q932_HANDLE_NULL(COMP_TYPE_NETWORK_PROTOCOL_PROFILE, Q932_STATE_NPP, "Network protocol profile", NULL);
+- default:
+- protocol = next_protocol;
+- break;
+- }
+- }
+- switch (protocol) {
+- case Q932_PROTOCOL_ROSE:
+- switch (comp->type) {
+- Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode);
+- Q932_HANDLE_PROC(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", rose_return_result_decode);
+- Q932_HANDLE_PROC(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", rose_return_error_decode);
+- Q932_HANDLE_PROC(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", rose_reject_decode);
+- default:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type);
+- break;
+- }
+- break;
+- case Q932_PROTOCOL_CMIP:
+- switch (comp->type) {
+- default:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "Don't know how to handle CMIP component of type 0x%X\n", comp->type);
+- break;
+- }
+- break;
+- case Q932_PROTOCOL_ACSE:
+- switch (comp->type) {
+- default:
+- if (pri->debug & PRI_DEBUG_APDU)
+- pri_message(pri, "Don't know how to handle ACSE component of type 0x%X\n", comp->type);
+- break;
+- }
+- break;
+- }
++ }
++ if (header.npp_present) {
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl,
++ "!! Don't know how to handle Network Protocol Profile type 0x%X\n",
++ header.npp);
+ }
+- i += (comp->len + 2);
++ return -1;
+ }
+-#undef Q932_HANDLE
+
++ pos = rose_decode(ctrl, pos, end, &rose);
++ if (!pos) {
++ return -1;
++ }
++ switch (rose.type) {
++ case ROSE_COMP_TYPE_INVOKE:
++ rose_handle_invoke(ctrl, call, msgtype, ie, &header, &rose.component.invoke);
++ break;
++ case ROSE_COMP_TYPE_RESULT:
++ rose_handle_result(ctrl, call, msgtype, ie, &header, &rose.component.result);
++ break;
++ case ROSE_COMP_TYPE_ERROR:
++ rose_handle_error(ctrl, call, msgtype, ie, &header, &rose.component.error);
++ break;
++ case ROSE_COMP_TYPE_REJECT:
++ rose_handle_reject(ctrl, call, msgtype, ie, &header, &rose.component.reject);
++ break;
++ default:
++ return -1;
++ }
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_progress_indicator)
++static void q931_handle_facilities(struct pri *ctrl, q931_call *call, int msgtype)
+ {
++ unsigned idx;
++ unsigned codeset;
++ unsigned full_ie;
++ q931_ie *ie;
++
++ for (idx = 0; idx < ctrl->facility.count; ++idx) {
++ ie = ctrl->facility.ie[idx];
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ codeset = ctrl->facility.codeset[idx];
++ full_ie = Q931_FULL_IE(codeset, ie->ie);
++ pri_message(ctrl, "-- Delayed processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
++ }
++ process_facility(ctrl, call, msgtype, ie);
++ }
++}
++
++static int transmit_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
++{
+ int code, mask;
+ /* Can't send progress indicator on GR-303 -- EVER! */
+- if (pri->subchannel && !pri->bri)
++ if (ctrl->subchannel && !ctrl->bri)
+ return 0;
+ if (call->progressmask > 0) {
+ if (call->progressmask & (mask = PRI_PROG_CALL_NOT_E2E_ISDN))
+@@ -1467,7 +2482,7 @@
+ code = Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
+ else {
+ code = 0;
+- pri_error(pri, "XXX Undefined progress bit: %x\n", call->progressmask);
++ pri_error(ctrl, "XXX Undefined progress bit: %x\n", call->progressmask);
+ }
+ if (code) {
+ ie->data[0] = 0x80 | (call->progcode << 5) | (call->progloc);
+@@ -1479,82 +2494,139 @@
+ /* Leave off */
+ return 0;
+ }
+-static FUNC_SEND(transmit_call_state)
++static int transmit_call_state(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+- if (call->ourcallstate > -1 ) {
++ ie->data[0] = Q931_CALL_STATE_NULL;
++ switch (call->ourcallstate) {
++ case Q931_CALL_STATE_NULL:
++ case Q931_CALL_STATE_CALL_INITIATED:
++ case Q931_CALL_STATE_OVERLAP_SENDING:
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_CALL_PRESENT:
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_ACTIVE:
++ case Q931_CALL_STATE_DISCONNECT_REQUEST:
++ case Q931_CALL_STATE_DISCONNECT_INDICATION:
++ case Q931_CALL_STATE_SUSPEND_REQUEST:
++ case Q931_CALL_STATE_RESUME_REQUEST:
++ case Q931_CALL_STATE_RELEASE_REQUEST:
++ case Q931_CALL_STATE_CALL_ABORT:
++ case Q931_CALL_STATE_OVERLAP_RECEIVING:
++ case Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE:
++ case Q931_CALL_STATE_RESTART_REQUEST:
++ case Q931_CALL_STATE_RESTART:
+ ie->data[0] = call->ourcallstate;
+- return 3;
++ break;
++ case Q931_CALL_STATE_NOT_SET:
++ break;
+ }
+- return 0;
++ return 3;
+ }
+
+-static FUNC_RECV(receive_call_state)
++static int receive_call_state(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ call->sugcallstate = ie->data[0] & 0x3f;
+ return 0;
+ }
+
+-static char *callstate2str(int callstate)
++/*!
++ * \brief Convert the internal Q.931 call state to a string.
++ *
++ * \param callstate Internal Q.931 call state.
++ *
++ * \return String equivalent of the given Q.931 call state.
++ */
++const char *q931_call_state_str(enum Q931_CALL_STATE callstate)
+ {
+ static struct msgtype callstates[] = {
+- { 0, "Null" },
+- { 1, "Call Initiated" },
+- { 2, "Overlap sending" },
+- { 3, "Outgoing call Proceeding" },
+- { 4, "Call Delivered" },
+- { 6, "Call Present" },
+- { 7, "Call Received" },
+- { 8, "Connect Request" },
+- { 9, "Incoming Call Proceeding" },
+- { 10, "Active" },
+- { 11, "Disconnect Request" },
+- { 12, "Disconnect Indication" },
+- { 15, "Suspend Request" },
+- { 17, "Resume Request" },
+- { 19, "Release Request" },
+- { 22, "Call Abort" },
+- { 25, "Overlap Receiving" },
+- { 61, "Restart Request" },
+- { 62, "Restart" },
++/* *INDENT-OFF* */
++ { Q931_CALL_STATE_NULL, "Null" },
++ { Q931_CALL_STATE_CALL_INITIATED, "Call Initiated" },
++ { Q931_CALL_STATE_OVERLAP_SENDING, "Overlap Sending" },
++ { Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING, "Outgoing Call Proceeding" },
++ { Q931_CALL_STATE_CALL_DELIVERED, "Call Delivered" },
++ { Q931_CALL_STATE_CALL_PRESENT, "Call Present" },
++ { Q931_CALL_STATE_CALL_RECEIVED, "Call Received" },
++ { Q931_CALL_STATE_CONNECT_REQUEST, "Connect Request" },
++ { Q931_CALL_STATE_INCOMING_CALL_PROCEEDING, "Incoming Call Proceeding" },
++ { Q931_CALL_STATE_ACTIVE, "Active" },
++ { Q931_CALL_STATE_DISCONNECT_REQUEST, "Disconnect Request" },
++ { Q931_CALL_STATE_DISCONNECT_INDICATION, "Disconnect Indication" },
++ { Q931_CALL_STATE_SUSPEND_REQUEST, "Suspend Request" },
++ { Q931_CALL_STATE_RESUME_REQUEST, "Resume Request" },
++ { Q931_CALL_STATE_RELEASE_REQUEST, "Release Request" },
++ { Q931_CALL_STATE_CALL_ABORT, "Call Abort" },
++ { Q931_CALL_STATE_OVERLAP_RECEIVING, "Overlap Receiving" },
++ { Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE, "Call Independent Service" },
++ { Q931_CALL_STATE_RESTART_REQUEST, "Restart Request" },
++ { Q931_CALL_STATE_RESTART, "Restart" },
++ { Q931_CALL_STATE_NOT_SET, "Not set. Internal use only." },
++/* *INDENT-ON* */
+ };
+- return code2str(callstate, callstates, sizeof(callstates) / sizeof(callstates[0]));
++ return code2str(callstate, callstates, ARRAY_LEN(callstates));
+ }
+
+-static FUNC_DUMP(dump_call_state)
++/*!
++ * \internal
++ * \brief Convert the Q.932 supplementary hold state to a string.
++ *
++ * \param state Q.932 supplementary hold state.
++ *
++ * \return String equivalent of the given hold state.
++ */
++static const char *q931_hold_state_str(enum Q931_HOLD_STATE state)
+ {
+- pri_message(pri, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
++ static struct msgtype hold_states[] = {
++/* *INDENT-OFF* */
++ { Q931_HOLD_STATE_IDLE, "Idle" },
++ { Q931_HOLD_STATE_HOLD_REQ, "Hold Request" },
++ { Q931_HOLD_STATE_HOLD_IND, "Hold Indication" },
++ { Q931_HOLD_STATE_CALL_HELD, "Call Held" },
++ { Q931_HOLD_STATE_RETRIEVE_REQ, "Retrieve Request" },
++ { Q931_HOLD_STATE_RETRIEVE_IND, "Retrieve Indication" },
++/* *INDENT-ON* */
++ };
++ return code2str(state, hold_states, ARRAY_LEN(hold_states));
++}
++
++static void dump_call_state(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
++ pri_message(ctrl, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
+ prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0xC0) >> 6), (ie->data[0] & 0xC0) >> 6,
+- callstate2str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);
++ q931_call_state_str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);
+ }
+
+-static FUNC_DUMP(dump_call_identity)
++static void dump_call_identity(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ int x;
+- pri_message(pri, "%c Call Identity (len=%2d) [ ", prefix, len);
++ pri_message(ctrl, "%c Call Identity (len=%2d) [ ", prefix, len);
+ for (x=0;x<ie->len;x++)
+- pri_message(pri, "0x%02X ", ie->data[x]);
+- pri_message(pri, " ]\n");
++ pri_message(ctrl, "0x%02X ", ie->data[x]);
++ pri_message(ctrl, " ]\n");
+ }
+
+-static FUNC_DUMP(dump_time_date)
++static void dump_time_date(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c Time Date (len=%2d) [ ", prefix, len);
++ pri_message(ctrl, "%c Time Date (len=%2d) [ ", prefix, len);
+ if (ie->len > 0)
+- pri_message(pri, "%02d", ie->data[0]);
++ pri_message(ctrl, "%02d", ie->data[0]);
+ if (ie->len > 1)
+- pri_message(pri, "-%02d", ie->data[1]);
++ pri_message(ctrl, "-%02d", ie->data[1]);
+ if (ie->len > 2)
+- pri_message(pri, "-%02d", ie->data[2]);
++ pri_message(ctrl, "-%02d", ie->data[2]);
+ if (ie->len > 3)
+- pri_message(pri, " %02d", ie->data[3]);
++ pri_message(ctrl, " %02d", ie->data[3]);
+ if (ie->len > 4)
+- pri_message(pri, ":%02d", ie->data[4]);
++ pri_message(ctrl, ":%02d", ie->data[4]);
+ if (ie->len > 5)
+- pri_message(pri, ":%02d", ie->data[5]);
+- pri_message(pri, " ]\n");
++ pri_message(ctrl, ":%02d", ie->data[5]);
++ pri_message(ctrl, " ]\n");
+ }
+
+-static FUNC_DUMP(dump_keypad_facility)
++static void dump_keypad_facility(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ char tmp[64];
+
+@@ -1563,10 +2635,10 @@
+
+ memcpy(tmp, ie->data, ie->len);
+ tmp[ie->len] = '\0';
+- pri_message(pri, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
++ pri_message(ctrl, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
+ }
+
+-static FUNC_RECV(receive_keypad_facility)
++static int receive_keypad_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ int mylen;
+
+@@ -1584,27 +2656,19 @@
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_keypad_facility)
++static int transmit_keypad_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ int sublen;
+
+ sublen = strlen(call->keypad_digits);
+-
+- if (sublen > 32) {
+- sublen = 32;
+- call->keypad_digits[32] = '\0';
+- }
+-
+ if (sublen) {
+- libpri_copy_string((char *)ie->data, (char *)call->keypad_digits, sizeof(call->keypad_digits));
+- /* Make sure we clear the field */
+- call->keypad_digits[0] = '\0';
++ libpri_copy_string((char *) ie->data, call->keypad_digits, sizeof(call->keypad_digits));
+ return sublen + 2;
+ } else
+ return 0;
+ }
+
+-static FUNC_DUMP(dump_display)
++static void dump_display(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ int x, y;
+ char *buf = malloc(len + 1);
+@@ -1618,7 +2682,7 @@
+ for (y=x; x<ie->len; x++)
+ buf[x] = ie->data[x] & 0x7f;
+ buf[x] = '\0';
+- pri_message(pri, "%c Display (len=%2d) %s[ %s ]\n", prefix, ie->len, tmp, &buf[y]);
++ pri_message(ctrl, "%c Display (len=%2d) %s[ %s ]\n", prefix, ie->len, tmp, &buf[y]);
+ free(buf);
+ }
+ }
+@@ -1626,10 +2690,10 @@
+ #define CHECK_OVERFLOW(limit) \
+ if (tmpptr - tmp + limit >= sizeof(tmp)) { \
+ *tmpptr = '\0'; \
+- pri_message(pri, "%s", tmpptr = tmp); \
++ pri_message(ctrl, "%s", tmpptr = tmp); \
+ }
+
+-static void dump_ie_data(struct pri *pri, unsigned char *c, int len)
++static void dump_ie_data(struct pri *ctrl, unsigned char *c, int len)
+ {
+ static char hexs[16] = "0123456789ABCDEF";
+ char tmp[1024], *tmpptr;
+@@ -1665,47 +2729,54 @@
+ if (lastascii)
+ *tmpptr++ = '\'';
+ *tmpptr = '\0';
+- pri_message(pri, "%s", tmp);
++ pri_message(ctrl, "%s", tmp);
+ }
+
+-static FUNC_DUMP(dump_facility)
++static void dump_facility(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- int dataat = (ie->data[0] & 0x80) ? 1 : 2;
+- pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
+- dump_ie_data(pri, ie->data, ie->len);
+- pri_message(NULL, " ]\n");
++ pri_message(ctrl, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
++ dump_ie_data(ctrl, ie->data, ie->len);
++ pri_message(ctrl, " ]\n");
++#if 0 /* Lets not dump parse of facility contents here anymore. */
++ /*
++ * The ASN.1 decode dump has already been done when the facility ie was added to the outgoing
++ * message or the ASN.1 decode dump will be done when the facility ie is processed on incoming
++ * messages. This dump is redundant and very noisy.
++ */
+ if (ie->len > 1) {
+- pri_message(pri, "PROTOCOL %02X\n", ie->data[0] & ASN1_TYPE_MASK);
+- asn1_dump(pri, &ie->data[dataat], ie->len - dataat);
++ int dataat = (ie->data[0] & 0x80) ? 1 : 2;
++
++ pri_message(ctrl, "PROTOCOL %02X\n", ie->data[0] & Q932_PROTOCOL_MASK);
++ asn1_dump(ctrl, ie->data + dataat, ie->data + ie->len);
+ }
+-
++#endif /* Lets not dump parse of facility contents here anymore. */
+ }
+
+-static FUNC_DUMP(dump_network_spec_fac)
++static void dump_network_spec_fac(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
++ pri_message(ctrl, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
+ if (ie->data[0] == 0x00) {
+- pri_message(pri, "%s", code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
++ pri_message(ctrl, "%s", code2str(ie->data[1], facilities, ARRAY_LEN(facilities)));
+ }
+ else
+- dump_ie_data(pri, ie->data, ie->len);
+- pri_message(pri, " ]\n");
++ dump_ie_data(ctrl, ie->data, ie->len);
++ pri_message(ctrl, " ]\n");
+ }
+
+-static FUNC_RECV(receive_network_spec_fac)
++static int receive_network_spec_fac(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_network_spec_fac)
++static int transmit_network_spec_fac(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ /* We are ready to transmit single IE only */
+ if (order > 1)
+ return 0;
+
+- if (pri->nsf != PRI_NSF_NONE) {
++ if (ctrl->nsf != PRI_NSF_NONE) {
+ ie->data[0] = 0x00;
+- ie->data[1] = pri->nsf;
++ ie->data[1] = ctrl->nsf;
+ return 4;
+ }
+ /* Leave off */
+@@ -1732,13 +2803,13 @@
+ return code2str(cause, causeclasses, sizeof(causeclasses) / sizeof(causeclasses[0]));
+ }
+
+-static FUNC_DUMP(dump_cause)
++static void dump_cause(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ int x;
+- pri_message(pri, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n",
++ pri_message(ctrl, "%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n",
+ prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
+ (ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
+- pri_message(pri, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
++ pri_message(ctrl, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
+ prefix, (ie->data[1] >> 7), pri_cause2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f,
+ pri_causeclass2str((ie->data[1] & 0x7f) >> 4), (ie->data[1] & 0x7f) >> 4);
+ if (ie->len < 3)
+@@ -1747,29 +2818,29 @@
+ switch(ie->data[1] & 0x7f) {
+ case PRI_CAUSE_IE_NONEXIST:
+ for (x=2;x<ie->len;x++)
+- pri_message(pri, "%c Cause data %d: %02x (%d, %s IE)\n", prefix, x-1, ie->data[x], ie->data[x], ie2str(ie->data[x]));
++ pri_message(ctrl, "%c Cause data %d: %02x (%d, %s IE)\n", prefix, x-1, ie->data[x], ie->data[x], ie2str(ie->data[x]));
+ break;
+ case PRI_CAUSE_WRONG_CALL_STATE:
+ for (x=2;x<ie->len;x++)
+- pri_message(pri, "%c Cause data %d: %02x (%d, %s message)\n", prefix, x-1, ie->data[x], ie->data[x], msg2str(ie->data[x]));
++ pri_message(ctrl, "%c Cause data %d: %02x (%d, %s message)\n", prefix, x-1, ie->data[x], ie->data[x], msg2str(ie->data[x]));
+ break;
+ case PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
+- pri_message(pri, "%c Cause data:", prefix);
++ pri_message(ctrl, "%c Cause data:", prefix);
+ for (x=2;x<ie->len;x++)
+- pri_message(pri, " %02x", ie->data[x]);
+- pri_message(pri, " (Timer T");
++ pri_message(ctrl, " %02x", ie->data[x]);
++ pri_message(ctrl, " (Timer T");
+ for (x=2;x<ie->len;x++)
+- pri_message(pri, "%c", ((ie->data[x] >= ' ') && (ie->data[x] < 0x7f)) ? ie->data[x] : '.');
+- pri_message(pri, ")\n");
++ pri_message(ctrl, "%c", ((ie->data[x] >= ' ') && (ie->data[x] < 0x7f)) ? ie->data[x] : '.');
++ pri_message(ctrl, ")\n");
+ break;
+ default:
+ for (x=2;x<ie->len;x++)
+- pri_message(pri, "%c Cause data %d: %02x (%d)\n", prefix, x-1, ie->data[x], ie->data[x]);
++ pri_message(ctrl, "%c Cause data %d: %02x (%d)\n", prefix, x-1, ie->data[x], ie->data[x]);
+ break;
+ }
+ }
+
+-static FUNC_RECV(receive_cause)
++static int receive_cause(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ call->causeloc = ie->data[0] & 0xf;
+ call->causecode = (ie->data[0] & 0x60) >> 5;
+@@ -1777,7 +2848,7 @@
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_cause)
++static int transmit_cause(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ /* We are ready to transmit single IE only */
+ if (order > 1)
+@@ -1793,23 +2864,23 @@
+ }
+ }
+
+-static FUNC_DUMP(dump_sending_complete)
++static void dump_sending_complete(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c Sending Complete (len=%2d)\n", prefix, len);
++ pri_message(ctrl, "%c Sending Complete (len=%2d)\n", prefix, len);
+ }
+
+-static FUNC_RECV(receive_sending_complete)
++static int receive_sending_complete(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ /* We've got a "Complete" message: Exect no further digits. */
+ call->complete = 1;
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_sending_complete)
++static int transmit_sending_complete(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+- if ((pri->overlapdial && call->complete) || /* Explicit */
+- (!pri->overlapdial && ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) ||
+- /* Implicit */ (pri->switchtype == PRI_SWITCH_EUROISDN_T1)))) {
++ if ((ctrl->overlapdial && call->complete) || /* Explicit */
++ (!ctrl->overlapdial && ((ctrl->switchtype == PRI_SWITCH_EUROISDN_E1) ||
++ /* Implicit */ (ctrl->switchtype == PRI_SWITCH_EUROISDN_T1)))) {
+ /* Include this single-byte IE */
+ return 1;
+ }
+@@ -1846,18 +2917,18 @@
+ return code2str(info, notifies, sizeof(notifies) / sizeof(notifies[0]));
+ }
+
+-static FUNC_DUMP(dump_notify)
++static void dump_notify(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c Notification indicator (len=%2d): Ext: %d %s (%d)\n", prefix, len, ie->data[0] >> 7, notify2str(ie->data[0] & 0x7f), ie->data[0] & 0x7f);
++ pri_message(ctrl, "%c Notification indicator (len=%2d): Ext: %d %s (%d)\n", prefix, len, ie->data[0] >> 7, notify2str(ie->data[0] & 0x7f), ie->data[0] & 0x7f);
+ }
+
+-static FUNC_RECV(receive_notify)
++static int receive_notify(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ call->notify = ie->data[0] & 0x7F;
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_notify)
++static int transmit_notify(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ if (call->notify >= 0) {
+ ie->data[0] = 0x80 | call->notify;
+@@ -1866,9 +2937,9 @@
+ return 0;
+ }
+
+-static FUNC_DUMP(dump_shift)
++static void dump_shift(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c %sLocking Shift (len=%02d): Requested codeset %d\n", prefix, (full_ie & 8) ? "Non-" : "", len, full_ie & 7);
++ pri_message(ctrl, "%c %sLocking Shift (len=%02d): Requested codeset %d\n", prefix, (full_ie & 8) ? "Non-" : "", len, full_ie & 7);
+ }
+
+ static char *lineinfo2str(int info)
+@@ -1903,21 +2974,21 @@
+ return code2str(info, lineinfo, sizeof(lineinfo) / sizeof(lineinfo[0]));
+ }
+
+-static FUNC_DUMP(dump_line_information)
++static void dump_line_information(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c Originating Line Information (len=%02d): %s (%d)\n", prefix, len, lineinfo2str(ie->data[0]), ie->data[0]);
++ pri_message(ctrl, "%c Originating Line Information (len=%02d): %s (%d)\n", prefix, len, lineinfo2str(ie->data[0]), ie->data[0]);
+ }
+
+-static FUNC_RECV(receive_line_information)
++static int receive_line_information(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ call->ani2 = ie->data[0];
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_line_information)
++static int transmit_line_information(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ #if 0 /* XXX Is this IE possible for 4ESS only? XXX */
+- if(pri->switchtype == PRI_SWITCH_ATT4ESS) {
++ if(ctrl->switchtype == PRI_SWITCH_ATT4ESS) {
+ ie->data[0] = 0;
+ return 3;
+ }
+@@ -1953,53 +3024,54 @@
+ return code2str(type, gdtype, sizeof(gdtype) / sizeof(gdtype[0]));
+ }
+
+-static FUNC_DUMP(dump_generic_digits)
++static void dump_generic_digits(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ int encoding;
+ int type;
+ int idx;
+ int value;
+ if (len < 3) {
+- pri_message(pri, "%c Generic Digits (len=%02d): Invalid length\n", prefix, len);
++ pri_message(ctrl, "%c Generic Digits (len=%02d): Invalid length\n", prefix, len);
+ return;
+ }
+ encoding = (ie->data[0] >> 5) & 7;
+ type = ie->data[0] & 0x1F;
+- pri_message(pri, "%c Generic Digits (len=%02d): Encoding %s Type %s\n", prefix, len, gdencoding2str(encoding), gdtype2str(type));
++ pri_message(ctrl, "%c Generic Digits (len=%02d): Encoding %s Type %s\n", prefix, len, gdencoding2str(encoding), gdtype2str(type));
+ if (encoding == 3) { /* Binary */
+- pri_message(pri, "%c Don't know how to handle binary encoding\n");
++ pri_message(ctrl, "%c Don't know how to handle binary encoding\n",
++ prefix);
+ return;
+ }
+ if (len == 3) /* No number information */
+ return;
+- pri_message(pri, "%c Digits: ");
++ pri_message(ctrl, "%c Digits: ", prefix);
+ value = 0;
+ for(idx = 3; idx < len; ++idx) {
+ switch(encoding) {
+ case 0: /* BCD even */
+ case 1: /* BCD odd */
+- pri_message(pri, "%d", ie->data[idx-2] & 0x0f);
++ pri_message(ctrl, "%d", ie->data[idx-2] & 0x0f);
+ value = value * 10 + (ie->data[idx-2] & 0x0f);
+ if(!encoding || (idx+1 < len)) { /* Special handling for BCD odd */
+- pri_message(pri, "%d", (ie->data[idx-2] >> 4) & 0x0f);
++ pri_message(ctrl, "%d", (ie->data[idx-2] >> 4) & 0x0f);
+ value = value * 10 + ((ie->data[idx-2] >> 4) & 0x0f);
+ }
+ break;
+ case 2: /* IA5 */
+- pri_message(pri, "%c", ie->data[idx-2]);
++ pri_message(ctrl, "%c", ie->data[idx-2]);
+ value = value * 10 + ie->data[idx-2] - '0';
+ break;
+ }
+ }
+ switch(type) {
+ case 4: /* Info Digits */
+- pri_message(pri, " - %s", lineinfo2str(value));
++ pri_message(ctrl, " - %s", lineinfo2str(value));
+ break;
+ }
+- pri_message(pri, "\n");
++ pri_message(ctrl, "\n");
+ }
+
+-static FUNC_RECV(receive_generic_digits)
++static int receive_generic_digits(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
+ {
+ int encoding;
+ int type;
+@@ -2009,13 +3081,13 @@
+ char number[260];
+
+ if (len < 3) {
+- pri_error(pri, "Invalid length of Generic Digits IE\n");
++ pri_error(ctrl, "Invalid length of Generic Digits IE\n");
+ return -1;
+ }
+ encoding = (ie->data[0] >> 5) & 7;
+ type = ie->data[0] & 0x1F;
+ if (encoding == 3) { /* Binary */
+- pri_message(pri, "!! Unable to handle binary encoded Generic Digits IE\n");
++ pri_message(ctrl, "!! Unable to handle binary encoded Generic Digits IE\n");
+ return 0;
+ }
+ if (len == 3) /* No number information */
+@@ -2063,10 +3135,13 @@
+ break;
+ #if 0
+ case 5: /* Callid */
+- if (!call->callernum[0]) {
+- memcpy(call->callernum, number, sizeof(call->callernum)-1);
+- call->callerpres = 0;
+- call->callerplan = 0;
++ if (!call->remote_id.number.valid) {
++ call->remote_id.number.valid = 1;
++ call->remote_id.number.presentation =
++ PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ call->remote_id.number.plan = PRI_UNKNOWN;
++ libpri_copy_string(call->remote_id.number.str, number,
++ sizeof(call->remote_id.number.str));
+ }
+ break;
+ #endif
+@@ -2074,13 +3149,13 @@
+ return 0;
+ }
+
+-static FUNC_SEND(transmit_generic_digits)
++static int transmit_generic_digits(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
+ {
+ #if 0 /* XXX Is this IE possible for other switches? XXX */
+ if (order > 1)
+ return 0;
+
+- if(pri->switchtype == PRI_SWITCH_NI1) {
++ if(ctrl->switchtype == PRI_SWITCH_NI1) {
+ ie->data[0] = 0x04; /* BCD even, Info Digits */
+ ie->data[1] = 0x00; /* POTS */
+ return 4;
+@@ -2119,35 +3194,54 @@
+ }
+
+
+-static FUNC_DUMP(dump_signal)
++static void dump_signal(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+- pri_message(pri, "%c Signal (len=%02d): ", prefix, len);
++ pri_message(ctrl, "%c Signal (len=%02d): ", prefix, len);
+ if (len < 3) {
+- pri_message(pri, "Invalid length\n");
++ pri_message(ctrl, "Invalid length\n");
+ return;
+ }
+- pri_message(pri, "Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]);
++ pri_message(ctrl, "Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]);
+ }
+
+-static FUNC_DUMP(dump_transit_count)
++static void dump_transit_count(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
+ {
+ /* Defined in ECMA-225 */
+- pri_message(pri, "%c Transit Count (len=%02d): ", prefix, len);
++ pri_message(ctrl, "%c Transit Count (len=%02d): ", prefix, len);
+ if (len < 3) {
+- pri_message(pri, "Invalid length\n");
++ pri_message(ctrl, "Invalid length\n");
+ return;
+ }
+- pri_message(pri, "Count=%d (0x%02x)\n", ie->data[0] & 0x1f, ie->data[0] & 0x1f);
++ pri_message(ctrl, "Count=%d (0x%02x)\n", ie->data[0] & 0x1f, ie->data[0] & 0x1f);
+ }
+
++static void dump_reverse_charging_indication(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
++{
++ pri_message(ctrl, "%c Reverse Charging Indication (len=%02d): %d\n", prefix, len, ie->data[0] & 0x7);
++}
+
++static int receive_reverse_charging_indication(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
++{
++ call->reversecharge = ie->data[0] & 0x7;
++ return 0;
++}
++
++static int transmit_reverse_charging_indication(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
++{
++ if (call->reversecharge != PRI_REVERSECHARGE_NONE) {
++ ie->data[0] = 0x80 | (call->reversecharge & 0x7);
++ return 3;
++ }
++ return 0;
++}
++
+ static struct ie ies[] = {
+ /* Codeset 0 - Common */
+- { 1, NATIONAL_CHANGE_STATUS, "Change Status" },
++ { 1, NATIONAL_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status },
+ { 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
+ { 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability },
+ { 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause },
+- { 1, Q931_CALL_STATE, "Call State", dump_call_state, receive_call_state, transmit_call_state },
++ { 1, Q931_IE_CALL_STATE, "Call State", dump_call_state, receive_call_state, transmit_call_state },
+ { 0, Q931_CHANNEL_IDENT, "Channel Identification", dump_channel_id, receive_channel_id, transmit_channel_id },
+ { 0, Q931_PROGRESS_INDICATOR, "Progress Indicator", dump_progress_indicator, receive_progress_indicator, transmit_progress_indicator },
+ { 0, Q931_NETWORK_SPEC_FAC, "Network-Specific Facilities", dump_network_spec_fac, receive_network_spec_fac, transmit_network_spec_fac },
+@@ -2157,11 +3251,11 @@
+ { 1, Q931_BINARY_PARAMETERS, "Packet-layer Binary Parameters" },
+ { 1, Q931_WINDOW_SIZE, "Packet-layer Window Size" },
+ { 1, Q931_CLOSED_USER_GROUP, "Closed User Group" },
+- { 1, Q931_REVERSE_CHARGE_INDIC, "Reverse Charging Indication" },
++ { 1, Q931_REVERSE_CHARGE_INDIC, "Reverse Charging Indication", dump_reverse_charging_indication, receive_reverse_charging_indication, transmit_reverse_charging_indication },
+ { 1, Q931_CALLING_PARTY_NUMBER, "Calling Party Number", dump_calling_party_number, receive_calling_party_number, transmit_calling_party_number },
+- { 1, Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr },
++ { 1, Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr, transmit_calling_party_subaddr },
+ { 1, Q931_CALLED_PARTY_NUMBER, "Called Party Number", dump_called_party_number, receive_called_party_number, transmit_called_party_number },
+- { 1, Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr },
++ { 1, Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr, receive_called_party_subaddr, transmit_called_party_subaddr },
+ { 0, Q931_REDIRECTING_NUMBER, "Redirecting Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
+ { 1, Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr },
+ { 0, Q931_TRANSIT_NET_SELECT, "Transit Network Selection" },
+@@ -2170,7 +3264,7 @@
+ { 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
+ { 1, Q931_PACKET_SIZE, "Packet Size" },
+ { 0, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
+- { 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
++ { 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number", dump_redirection_number, receive_redirection_number, transmit_redirection_number },
+ { 1, Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
+ { 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
+ { 1, Q931_IE_INFO_REQUEST, "Feature Request" },
+@@ -2187,15 +3281,18 @@
+ { 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user, transmit_user_user },
+ { 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
+ { 1, Q931_IE_CALL_STATUS, "Call Status" },
+- { 1, Q931_IE_CHANGE_STATUS, "Change Status" },
++ { 1, Q931_IE_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status },
+ { 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number },
+- { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number },
++ { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number, receive_connected_number, transmit_connected_number },
++ { 1, Q931_IE_CONNECTED_SUBADDR, "Connected Subaddress", dump_connected_subaddr, receive_connected_subaddr, transmit_connected_subaddr },
+ { 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
+ { 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" },
+ { 1, Q931_IE_UPDATE, "Update" },
+ { 1, Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
+ /* Codeset 4 - Q.SIG specific */
+ { 1, QSIG_IE_TRANSIT_COUNT | Q931_CODESET(4), "Transit Count", dump_transit_count },
++ /* Codeset 5 - National specific (ETSI PISN specific) */
++ { 1, Q931_CALLING_PARTY_CATEGORY, "Calling Party Category", dump_calling_party_category },
+ /* Codeset 6 - Network specific */
+ { 1, Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information },
+ { 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility },
+@@ -2264,7 +3361,7 @@
+ return 2 + ie->len;
+ }
+
+-static char *msg2str(int msg)
++const char *msg2str(int msg)
+ {
+ unsigned int x;
+ for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++)
+@@ -2273,35 +3370,64 @@
+ return "Unknown Message Type";
+ }
+
++static char *maintenance_msg2str(int msg, int pd)
++{
++ unsigned int x, max;
++ struct msgtype *m = NULL;
++
++ if (pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) {
++ m = att_maintenance_msgs;
++ max = ARRAY_LEN(att_maintenance_msgs);
++ } else {
++ m = national_maintenance_msgs;
++ max = ARRAY_LEN(national_maintenance_msgs);
++ }
++
++ for (x = 0; x < max; x++) {
++ if (m[x].msgnum == msg) {
++ return m[x].name;
++ }
++ }
++ return "Unknown Message Type";
++}
++
++/* Decode the call reference */
+ static inline int q931_cr(q931_h *h)
+ {
+- int cr = 0;
++ int cr;
+ int x;
++
+ if (h->crlen > 3) {
+ pri_error(NULL, "Call Reference Length Too long: %d\n", h->crlen);
+- return -1;
++ return Q931_DUMMY_CALL_REFERENCE;
+ }
+ switch (h->crlen) {
+- case 2:
+- for (x=0;x<h->crlen;x++) {
+- cr <<= 8;
+- cr |= h->crv[x];
+- }
+- break;
+- case 1:
+- cr = h->crv[0];
+- if (cr & 0x80) {
+- cr &= ~0x80;
+- cr |= 0x8000;
+- }
+- break;
+- default:
+- pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen);
++ case 2:
++ cr = 0;
++ for (x = 0; x < h->crlen; ++x) {
++ cr <<= 8;
++ cr |= h->crv[x];
++ }
++ break;
++ case 1:
++ cr = h->crv[0];
++ if (cr & 0x80) {
++ cr &= ~0x80;
++ cr |= 0x8000;
++ }
++ break;
++ case 0:
++ cr = Q931_DUMMY_CALL_REFERENCE;
++ break;
++ default:
++ pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen);
++ cr = Q931_DUMMY_CALL_REFERENCE;
++ break;
+ }
+ return cr;
+ }
+
+-static inline void q931_dumpie(struct pri *pri, int codeset, q931_ie *ie, char prefix)
++static inline void q931_dumpie(struct pri *ctrl, int codeset, q931_ie *ie, char prefix)
+ {
+ unsigned int x;
+ int full_ie = Q931_FULL_IE(codeset, ie->ie);
+@@ -2315,7 +3441,7 @@
+ for (x = 0; x + 2 < ielen(ie); ++x)
+ buflen += sprintf(buf + buflen, " %02x", ie->data[x]);
+ }
+- pri_message(pri, "%c [%02x%s]\n", prefix, ie->ie, buf);
++ pri_message(ctrl, "%c [%02x%s]\n", prefix, ie->ie, buf);
+ free(buf);
+
+ /* Special treatment for shifts */
+@@ -2324,130 +3450,306 @@
+
+ base_ie = (((full_ie & ~0x7f) == Q931_FULL_IE(0, 0x80)) && ((full_ie & 0x70) != 0x20)) ? full_ie & ~0x0f : full_ie;
+
+- for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++)
++ for (x = 0; x < ARRAY_LEN(ies); ++x)
+ if (ies[x].ie == base_ie) {
+ if (ies[x].dump)
+- ies[x].dump(full_ie, pri, ie, ielen(ie), prefix);
++ ies[x].dump(full_ie, ctrl, ie, ielen(ie), prefix);
+ else
+- pri_message(pri, "%c IE: %s (len = %d)\n", prefix, ies[x].name, ielen(ie));
++ pri_message(ctrl, "%c IE: %s (len = %d)\n", prefix, ies[x].name, ielen(ie));
+ return;
+ }
+
+- pri_error(pri, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
++ pri_error(ctrl, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
+ }
+
+-static q931_call *q931_getcall(struct pri *pri, int cr, int outboundnew)
++/*!
++ * \brief Initialize the call record.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg.
++ *
++ * \note The call record is assumed to already be memset() to zero.
++ *
++ * \return Nothing
++ */
++void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr)
+ {
+- q931_call *cur, *prev;
++ call->cr = cr;
++ call->slotmap = -1;
++ call->channelno = -1;
++ if (cr != Q931_DUMMY_CALL_REFERENCE) {
++ call->newcall = 1;
++ }
++ call->ourcallstate = Q931_CALL_STATE_NULL;
++ call->peercallstate = Q931_CALL_STATE_NULL;
++ call->sugcallstate = Q931_CALL_STATE_NOT_SET;
++ call->ri = -1;
++ call->transcapability = -1;
++ call->transmoderate = -1;
++ call->transmultiple = -1;
++ call->userl1 = -1;
++ call->userl2 = -1;
++ call->userl3 = -1;
++ call->rateadaption = -1;
++ call->progress = -1;
++ call->causecode = -1;
++ call->causeloc = -1;
++ call->cause = -1;
++ call->useruserprotocoldisc = -1;
++ call->aoc_units = -1;
++ call->changestatus = -1;
++ call->reversecharge = -1;
++ call->pri_winner = -1;
++ call->master_call = call;
++ q931_party_number_init(&call->redirection_number);
++ q931_party_address_init(&call->called);
++ q931_party_id_init(&call->local_id);
++ q931_party_id_init(&call->remote_id);
++ q931_party_redirecting_init(&call->redirecting);
++
++ /* PRI is set to whoever called us */
++ if (BRI_TE_PTMP(ctrl)) {
++ /*
++ * Point to the master to avoid stale pointer problems if
++ * the TEI is removed later.
++ */
++ call->pri = PRI_MASTER(ctrl);
++ } else {
++ call->pri = ctrl;
++ }
++}
++
++static q931_call *q931_getcall(struct pri *ctrl, int cr)
++{
++ q931_call *cur;
++ q931_call *prev;
+ struct pri *master;
+
++ if (cr == Q931_DUMMY_CALL_REFERENCE) {
++ return ctrl->dummy_call;
++ }
++
+ /* Find the master - He has the call pool */
+- if (pri->master)
+- master = pri->master;
+- else
+- master = pri;
+-
++ master = PRI_MASTER(ctrl);
++
+ cur = *master->callpool;
+ prev = NULL;
+- while(cur) {
+- if (cur->cr == cr)
++ while (cur) {
++ if (cur->cr == cr) {
++ /* Found existing call. */
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_GR303_EOC:
++ case PRI_SWITCH_GR303_EOC_PATH:
++ case PRI_SWITCH_GR303_TMC:
++ case PRI_SWITCH_GR303_TMC_SWITCHING:
++ break;
++ default:
++ if (!ctrl->bri) {
++ /* PRI is set to whoever called us */
++ cur->pri = ctrl;
++ }
++ break;
++ }
+ return cur;
++ }
+ prev = cur;
+ cur = cur->next;
+ }
++
+ /* No call exists, make a new one */
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "-- Making new call for cr %d\n", cr);
+-
+- if (!(cur = calloc(1, sizeof(*cur))))
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "-- Making new call for cr %d\n", cr);
++ }
++
++ cur = calloc(1, sizeof(*cur));
++ if (!cur) {
+ return NULL;
++ }
+
+- call_init(cur);
+- /* Call reference */
+- cur->cr = cr;
+- /* PRI is set to whoever called us */
+- if (pri->bri && (pri->localtype == PRI_CPE) && pri->subchannel && outboundnew)
+- cur->pri = pri->subchannel;
+- else
+- cur->pri = pri;
++ /* Initialize call structure. */
++ q931_init_call_record(ctrl, cur, cr);
+
+ /* Append to end of list */
+- if (prev)
++ if (prev) {
+ prev->next = cur;
+- else
++ } else {
+ *master->callpool = cur;
+-
++ }
++
+ return cur;
+ }
+
+-q931_call *q931_new_call(struct pri *pri)
++q931_call *q931_new_call(struct pri *ctrl)
+ {
+ q931_call *cur;
+
+ do {
+- cur = *pri->callpool;
+- pri->cref++;
+- if (!pri->bri) {
+- if (pri->cref > 32767)
+- pri->cref = 1;
++ cur = *ctrl->callpool;
++ ctrl->cref++;
++ if (!ctrl->bri) {
++ if (ctrl->cref > 32767)
++ ctrl->cref = 1;
+ } else {
+- if (pri->cref > 127)
+- pri->cref = 1;
++ if (ctrl->cref > 127)
++ ctrl->cref = 1;
+ }
+ while(cur) {
+- if (cur->cr == (0x8000 | pri->cref))
++ if (cur->cr == (0x8000 | ctrl->cref))
+ break;
+ cur = cur->next;
+ }
+ } while(cur);
+
+- return q931_getcall(pri, pri->cref | 0x8000, 1);
++ return q931_getcall(ctrl, ctrl->cref | 0x8000);
+ }
+
+-static void q931_destroy(struct pri *pri, int cr, q931_call *c)
++static void stop_t303(struct q931_call *call);
++
++static void cleanup_and_free_call(struct q931_call *cur)
+ {
+- q931_call *cur, *prev;
++ stop_t303(cur);
++ pri_schedule_del(cur->pri, cur->retranstimer);
++ pri_call_apdu_queue_cleanup(cur);
++ free(cur);
++}
+
++static void pri_create_fake_clearing(struct q931_call *c, struct pri *master);
++
++void q931_destroycall(struct pri *ctrl, q931_call *c)
++{
++ q931_call *cur;
++ q931_call *prev;
++ q931_call *slave;
++ int i;
++ int slavesleft;
++ int slaveidx;
++
++ if (q931_is_dummy_call(c)) {
++ /* Cannot destroy the dummy call. */
++ return;
++ }
++ if (c->master_call != c) {
++ slave = c;
++ c = slave->master_call;
++ } else {
++ slave = NULL;
++ }
++
+ /* For destroying, make sure we are using the master span, since it maintains the call pool */
+- for (;pri->master; pri = pri->master);
++ ctrl = PRI_MASTER(ctrl);
+
+ prev = NULL;
+- cur = *pri->callpool;
+- while(cur) {
+- if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
++ cur = *ctrl->callpool;
++ while (cur) {
++ if (cur == c) {
++ slaveidx = -1;
++ if (slave) {
++ for (i = 0; i < Q931_MAX_TEI; i++) {
++ if (cur->subcalls[i] == slave) {
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "Destroying subcall %p of call %p at %d\n",
++ slave, cur, i);
++ }
++ cleanup_and_free_call(slave);
++ cur->subcalls[i] = NULL;
++ slaveidx = i;
++ break;
++ }
++ }
++ }
++
++ slavesleft = 0;
++ for (i = 0; i < Q931_MAX_TEI; i++) {
++ if (cur->subcalls[i]) {
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "Subcall still present at %d\n", i);
++ }
++ slavesleft++;
++ }
++ }
++
++ /* We have 3 different phases to deal with:
++ * 1.) Sent outbound call, but no response, indicated by t203 present
++ * 2.) Sent outbound call, with responses, indicated by lack of t203 and subcalls present
++ * 3.) Outbound call connected, indicated by pri_winner > -1
++ *
++ * If chan_dahdi hangs up in phase:
++ * 1.) T303 will be present, and we will fake clear in this case
++ * 2.) pri_winner will be < 0 and subcalls will be present.
++ * 3.) pri_winner will be > -1 and we will free the master when the winner dies.
++ *
++ * If remote ends hang up in phase:
++ * 1.) Impossible, defined by phase.
++ * 2.) When last end hangs up, we should cause a fake clearing.
++ * 3.) Pass events to winner up and be freed when winner is freed
++ *
++ * Exceptional conditions in phase:
++ * 1.) None.
++ * 2.) None.
++ * 3.) We hang up a call so quickly that it hangs up before other competing lines finish hangup sequence
++ * Subcalls present still even though we have hung up the winner.
++ *
++ * So, we could say:
++ * If, when the library user hangs up the master call, and there are more than one subcall up, we fake clear
++ * regardless of whether or not we drop down to one subcall left in the clearing process.
++ *
++ * If there are only one call up, we mirror what it does.
++ *
++ * OR
++ *
++ * Phase 2. them clearing:
++ * For handling of Phase 2 (indicated by not running and pri_winner not present):
++ * We create a fake hangup sequence after all the subcalls have been destroyed and after
++ *
++ * "" us clearing:
++ * For we need to start the fake clearing, but it needs to be half of a fake clearing, not a full one (since we already had a hangup).
++ *
++ * For handling of Phase 3 plus exceptions:
++ *
++ * If pri_winner exists, we mirror him in terms of events (which provides our hangup sequence), and when we have the complete
++ * hangup sequence completed (destroy called on master call), if there still exist non winner subcalls at this time, we declare the master
++ * call as dead and free it when the last subcall clears.
++ */
++
++ if ((slave && !slavesleft) &&
++ ((cur->pri_winner < 0) || (slave && slaveidx != cur->pri_winner))) {
++ pri_create_fake_clearing(cur, ctrl);
++ return;
++ }
++
++ if (slavesleft) {
++ return;
++ }
++
++ /* Master call or normal call destruction. */
++ if ((cur->pri_winner > -1) && cur->outboundbroadcast) {
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl,
++ "Since we already had a winner, we should just be able to kill the call anyways\n");
++ }
++ }
+ if (prev)
+ prev->next = cur->next;
+ else
+- *pri->callpool = cur->next;
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));
+- if (cur->retranstimer)
+- pri_schedule_del(pri, cur->retranstimer);
+- pri_call_apdu_queue_cleanup(cur);
+- free(cur);
++ *ctrl->callpool = cur->next;
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl,
++ "NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s, hold-state %s\n",
++ q931_call_state_str(cur->ourcallstate),
++ q931_call_state_str(cur->peercallstate),
++ q931_hold_state_str(cur->hold_state));
++ pri_schedule_del(ctrl, cur->hold_timer);
++ cleanup_and_free_call(cur);
+ return;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+- pri_error(pri, "Can't destroy call %d!\n", cr);
++ pri_error(ctrl, "Can't destroy call %p cref:%d!\n", c, c->cr);
+ }
+
+-static void q931_destroycall(struct pri *pri, int cr)
++static int add_ie(struct pri *ctrl, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen, int *codeset)
+ {
+- return q931_destroy(pri, cr, NULL);
+-}
+-
+-
+-void __q931_destroycall(struct pri *pri, q931_call *c)
+-{
+- if (pri && c)
+- q931_destroy(pri,0, c);
+- return;
+-}
+-
+-static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen, int *codeset)
+-{
+ unsigned int x;
+ int res, total_res;
+ int have_shift;
+@@ -2473,7 +3775,7 @@
+ total_res = 0;
+ do {
+ iet->ie = ie;
+- res = ies[x].transmit(ie, pri, call, msgtype, iet, maxlen, ++order);
++ res = ies[x].transmit(ie, ctrl, call, msgtype, iet, maxlen, ++order);
+ /* Error if res < 0 or ignored if res == 0 */
+ if (res < 0)
+ return res;
+@@ -2484,8 +3786,7 @@
+ maxlen -= res;
+ iet = (q931_ie *)((char *)iet + res);
+ }
+- }
+- while (res > 0 && order < ies_count);
++ } while (res > 0 && order < ies_count);
+ if (have_shift && total_res) {
+ if (Q931_IE_CODESET(ies[x].ie))
+ *codeset = Q931_IE_CODESET(ies[x].ie);
+@@ -2493,12 +3794,12 @@
+ }
+ return total_res;
+ } else {
+- pri_error(pri, "!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
++ pri_error(ctrl, "!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
+ return -1;
+ }
+ }
+ }
+- pri_error(pri, "!! Unknown IE %d (%s)\n", ie, ie2str(ie));
++ pri_error(ctrl, "!! Unknown IE %d (%s)\n", ie, ie2str(ie));
+ return -1;
+ }
+
+@@ -2513,25 +3814,37 @@
+ return code2str(disc, discs, sizeof(discs) / sizeof(discs[0]));
+ }
+
+-void q931_dump(struct pri *pri, q931_h *h, int len, int txrx)
++void q931_dump(struct pri *ctrl, q931_h *h, int len, int txrx)
+ {
+ q931_mh *mh;
+ char c;
+ int x=0, r;
+ int cur_codeset;
+ int codeset;
++ int cref;
++
+ c = txrx ? '>' : '<';
+- pri_message(pri, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
+- pri_message(pri, "%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n", c, h->crlen, q931_cr(h) & 0x7FFF, q931_cr(h) & 0x7FFF, (h->crv[0] & 0x80) ? "Terminator" : "Originator");
++ pri_message(ctrl, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
++ cref = q931_cr(h);
++ pri_message(ctrl, "%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n",
++ c, h->crlen, cref & 0x7FFF, cref & 0x7FFF,
++ (cref == Q931_DUMMY_CALL_REFERENCE)
++ ? "Dummy"
++ : (cref & 0x8000) ? "Terminator" : "Originator");
++
+ /* Message header begins at the end of the call reference number */
+ mh = (q931_mh *)(h->contents + h->crlen);
+- pri_message(pri, "%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
++ if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
++ pri_message(ctrl, "%c Message Type: %s (%d)\n", c, maintenance_msg2str(mh->msg, h->pd), mh->msg);
++ } else {
++ pri_message(ctrl, "%c Message Type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
++ }
+ /* Drop length of header, including call reference */
+ len -= (h->crlen + 3);
+ codeset = cur_codeset = 0;
+ while(x < len) {
+ r = ielen((q931_ie *)(mh->data + x));
+- q931_dumpie(pri, cur_codeset, (q931_ie *)(mh->data + x), c);
++ q931_dumpie(ctrl, cur_codeset, (q931_ie *)(mh->data + x), c);
+ switch (mh->data[x] & 0xf8) {
+ case Q931_LOCKING_SHIFT:
+ if ((mh->data[x] & 7) > 0)
+@@ -2547,86 +3860,106 @@
+ x += r;
+ }
+ if (x > len)
+- pri_error(pri, "XXX Message longer than it should be?? XXX\n");
++ pri_error(ctrl, "XXX Message longer than it should be?? XXX\n");
+ }
+
+-static int q931_handle_ie(int codeset, struct pri *pri, q931_call *c, int msg, q931_ie *ie)
++static int q931_handle_ie(int codeset, struct pri *ctrl, q931_call *c, int msg, q931_ie *ie)
+ {
+ unsigned int x;
+ int full_ie = Q931_FULL_IE(codeset, ie->ie);
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, "-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
+ for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
+ if (full_ie == ies[x].ie) {
+ if (ies[x].receive)
+- return ies[x].receive(full_ie, pri, c, msg, ie, ielen(ie));
++ return ies[x].receive(full_ie, ctrl, c, msg, ie, ielen(ie));
+ else {
+- if (pri->debug & PRI_DEBUG_Q931_ANOMALY)
+- pri_error(pri, "!! No handler for IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
++ if (ctrl->debug & PRI_DEBUG_Q931_ANOMALY)
++ pri_error(ctrl, "!! No handler for IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
+ return -1;
+ }
+ }
+ }
+- pri_message(pri, "!! Unknown IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
++ pri_message(ctrl, "!! Unknown IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
+ return -1;
+ }
+
+-static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len)
++/* Returns header and message header and modifies length in place */
++static void init_header(struct pri *ctrl, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int protodisc)
+ {
+- /* Returns header and message header and modifies length in place */
+- q931_h *h = (q931_h *)buf;
+- q931_mh * mh;
+- h->pd = pri->protodisc;
++ q931_h *h = (q931_h *) buf;
++ q931_mh *mh;
++ unsigned crv;
++
++ if (protodisc) {
++ h->pd = protodisc;
++ } else {
++ h->pd = ctrl->protodisc;
++ }
+ h->x0 = 0; /* Reserved 0 */
+- if (!pri->bri) {
+- h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */
+- if (call->cr || call->forceinvert) {
+- h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
+- h->crv[1] = (call->cr & 0xff);
+- } else {
+- /* Unless of course this has no call reference */
+- h->crv[0] = 0;
+- h->crv[1] = 0;
+- }
+- if (pri->subchannel && !pri->bri) {
++ if (q931_is_dummy_call(call)) {
++ h->crlen = 0;
++ } else if (!ctrl->bri) {
++ /* Two bytes of Call Reference. */
++ h->crlen = 2;
++ /* Invert the top bit to make it from our sense */
++ crv = (unsigned) call->cr;
++ h->crv[0] = ((crv >> 8) ^ 0x80) & 0xff;
++ h->crv[1] = crv & 0xff;
++ if (ctrl->subchannel && !ctrl->bri) {
+ /* On GR-303, top bit is always 0 */
+ h->crv[0] &= 0x7f;
+ }
+ } else {
+ h->crlen = 1;
+- if (call->cr || call->forceinvert) {
+- h->crv[0] = (((call->cr ^ 0x8000) & 0x8000) >> 8) | (call->cr & 0x7f);
+- } else {
+- /* Unless of course this has no call reference */
+- h->crv[0] = 0;
+- }
++ /* Invert the top bit to make it from our sense */
++ crv = (unsigned) call->cr;
++ h->crv[0] = (((crv >> 8) ^ 0x80) & 0x80) | (crv & 0x7f);
+ }
+- mh = (q931_mh *)(h->contents + h->crlen);
++ *hb = h;
++
++ *len -= 3;/* Protocol discriminator, call reference length, message type id */
++ *len -= h->crlen;
++
++ mh = (q931_mh *) (h->contents + h->crlen);
+ mh->f = 0;
+- *hb = h;
+ *mhb = mh;
+- if (h->crlen == 2)
+- *len -= 5;
+- else
+- *len -= 4;
+-
+ }
+
+-static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr)
++static int q931_xmit(struct pri *ctrl, q931_h *h, int len, int cr, int uiframe)
+ {
+- q921_transmit_iframe(pri, h, len, cr);
++ if (uiframe) {
++ q921_transmit_uiframe(ctrl, h, len);
++ } else {
++ q921_transmit_iframe(ctrl, h, len, cr);
++ }
+ /* The transmit operation might dump the q921 header, so logging the q931
+ message body after the transmit puts the sections of the message in the
+ right order in the log */
+- if (pri->debug & PRI_DEBUG_Q931_DUMP)
+- q931_dump(pri, h, len, 1);
++ if (ctrl->debug & PRI_DEBUG_Q931_DUMP)
++ q931_dump(ctrl, h, len, 1);
+ #ifdef LIBPRI_COUNTERS
+- pri->q931_txcount++;
++ ctrl->q931_txcount++;
+ #endif
+ return 0;
+ }
+
+-static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
++/*!
++ * \internal
++ * \brief Build and send the requested message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ * \param msgtype Q.931 message type to build.
++ * \param ies List of ie's to put in the message.
++ *
++ * \note The ie's in the ie list must be in numerical order.
++ * See Q.931 section 4.5.1 coding rules.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[])
+ {
+ unsigned char buf[1024];
+ q931_h *h;
+@@ -2636,18 +3969,24 @@
+ int offset=0;
+ int x;
+ int codeset;
+-
++
++ if (call->outboundbroadcast && call->master_call == call && msgtype != Q931_SETUP) {
++ pri_error(ctrl,
++ "Attempting to use master call record to send %s on BRI PTMP NT %p\n",
++ msg2str(msgtype), ctrl);
++ return -1;
++ }
++
+ memset(buf, 0, sizeof(buf));
+ len = sizeof(buf);
+- init_header(pri, c, buf, &h, &mh, &len);
+- mh->msg = msgtype;
++ init_header(ctrl, call, buf, &h, &mh, &len, (msgtype >> 8));
++ mh->msg = msgtype & 0x00ff;
+ x=0;
+ codeset = 0;
+ while(ies[x] > -1) {
+- res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
+-
++ res = add_ie(ctrl, call, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
+ if (res < 0) {
+- pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
++ pri_error(ctrl, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
+ return -1;
+ }
+
+@@ -2657,20 +3996,121 @@
+ }
+ /* Invert the logic */
+ len = sizeof(buf) - len;
+- q931_xmit(c->pri, h, len, 1);
+- c->acked = 1;
++
++ ctrl = call->pri;
++ if (BRI_TE_PTMP(ctrl)) {
++ /*
++ * Must use the BRI subchannel structure to send with the correct TEI.
++ * Note: If the subchannel is NULL then there is no TEI assigned and
++ * we should not be sending anything out at this time.
++ */
++ ctrl = ctrl->subchannel;
++ }
++ if (ctrl) {
++ int uiframe;
++
++ switch (msgtype) {
++ case Q931_SETUP:
++ /*
++ * For NT-PTMP mode, we need to check the following:
++ * MODE = NT-PTMP
++ * MESSAGE = SETUP
++ *
++ * If those are true, we need to send the SETUP in a UI frame
++ * instead of an I-frame.
++ */
++ if (BRI_NT_PTMP(ctrl))
++ uiframe = 1;
++ else
++ uiframe = 0;
++ break;
++ case Q931_FACILITY:
++ if (ctrl->tei == Q921_TEI_GROUP) {
++ /* Broadcast TEI. */
++ if (q931_is_dummy_call(call)) {
++ /*
++ * This is a FACILITY message on the dummy call reference
++ * for the broadcast TEI.
++ */
++ uiframe = 1;
++ } else {
++ pri_error(ctrl,
++ "Attempting to broadcast %s on cref %d\n",
++ msg2str(msgtype), call->cr);
++ return -1;
++ }
++ } else {
++ uiframe = 0;
++ }
++ break;
++ default:
++ uiframe = 0;
++ break;
++ }
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl,
++ "Sending message for call %p on %p TEI/SAPI %d/%d, call->pri is %p, TEI/SAPI %d/%d\n",
++ call,
++ ctrl, ctrl->tei, ctrl->sapi,
++ call->pri, call->pri->tei, call->pri->sapi);
++ }
++ q931_xmit(ctrl, h, len, 1, uiframe);
++ }
++ call->acked = 1;
+ return 0;
+ }
+
+-static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
++static int maintenance_service_ies[] = { Q931_IE_CHANGE_STATUS, Q931_CHANNEL_IDENT, -1 };
+
+-static int q931_status(struct pri *pri, q931_call *c, int cause)
++int maintenance_service_ack(struct pri *ctrl, q931_call *c)
+ {
++ int pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_1;
++ int mt = ATT_SERVICE_ACKNOWLEDGE;
++
++ if (ctrl->switchtype == PRI_SWITCH_NI2) {
++ pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_2;
++ mt = NATIONAL_SERVICE_ACKNOWLEDGE;
++ }
++ return send_message(ctrl, c, (pd << 8) | mt, maintenance_service_ies);
++}
++
++int maintenance_service(struct pri *ctrl, int span, int channel, int changestatus)
++{
++ struct q931_call *c;
++ int pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_1;
++ int mt = ATT_SERVICE;
++
++ c = q931_getcall(ctrl, 0 | 0x8000);
++ if (!c) {
++ return -1;
++ }
++ if (channel > -1) {
++ c->channelno = channel & 0xff;
++ c->chanflags = FLAG_EXCLUSIVE;
++ } else {
++ c->channelno = channel;
++ c->chanflags = FLAG_EXCLUSIVE | FLAG_WHOLE_INTERFACE;
++ }
++ c->ds1no = span;
++ c->ds1explicit = 0;
++ c->changestatus = changestatus;
++
++ if (ctrl->switchtype == PRI_SWITCH_NI2) {
++ pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_2;
++ mt = NATIONAL_SERVICE;
++ }
++ return send_message(ctrl, c, (pd << 8) | mt, maintenance_service_ies);
++}
++
++static int status_ies[] = { Q931_CAUSE, Q931_IE_CALL_STATE, -1 };
++
++static int q931_status(struct pri *ctrl, q931_call *c, int cause)
++{
+ q931_call *cur = NULL;
+ if (!cause)
+ cause = PRI_CAUSE_RESPONSE_TO_STATUS_ENQUIRY;
+ if (c->cr > -1)
+- cur = *pri->callpool;
++ cur = *ctrl->callpool;
+ while(cur) {
+ if (cur->cr == c->cr) {
+ cur->cause=cause;
+@@ -2681,79 +4121,156 @@
+ cur = cur->next;
+ }
+ if (!cur) {
+- pri_message(pri, "YYY Here we get reset YYY\n");
++ pri_message(ctrl, "YYY Here we get reset YYY\n");
+ /* something went wrong, respond with "no such call" */
+ c->ourcallstate = Q931_CALL_STATE_NULL;
+ c->peercallstate = Q931_CALL_STATE_NULL;
+ cur=c;
+ }
+- return send_message(pri, cur, Q931_STATUS, status_ies);
++ return send_message(ctrl, cur, Q931_STATUS, status_ies);
+ }
+
+-static int information_ies[] = { Q931_IE_KEYPAD_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
++static int information_ies[] = { Q931_CALLED_PARTY_NUMBER, -1 };
+
+-int q931_information(struct pri *pri, q931_call *c, char digit)
++int q931_information(struct pri *ctrl, q931_call *c, char digit)
+ {
+- c->callednum[0] = digit;
+- c->callednum[1] = '\0';
+- return send_message(pri, c, Q931_INFORMATION, information_ies);
++ c->overlap_digits[0] = digit;
++ c->overlap_digits[1] = '\0';
++
++ /*
++ * Since we are doing overlap dialing now, we need to accumulate
++ * the digits into call->called.number.str.
++ */
++ c->called.number.valid = 1;
++ if (strlen(c->called.number.str) < sizeof(c->called.number.str) - 1) {
++ /* There is enough room for the new digit. */
++ strcat(c->called.number.str, c->overlap_digits);
++ }
++
++ return send_message(ctrl, c, Q931_INFORMATION, information_ies);
+ }
+
+ static int keypad_facility_ies[] = { Q931_IE_KEYPAD_FACILITY, -1 };
+
+-int q931_keypad_facility(struct pri *pri, q931_call *call, char *digits)
++int q931_keypad_facility(struct pri *ctrl, q931_call *call, const char *digits)
+ {
+ libpri_copy_string(call->keypad_digits, digits, sizeof(call->keypad_digits));
+- return send_message(pri, call, Q931_INFORMATION, keypad_facility_ies);
++ return send_message(ctrl, call, Q931_INFORMATION, keypad_facility_ies);
+ }
+
+ static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
+
+-static int restart_ack(struct pri *pri, q931_call *c)
++static int restart_ack(struct pri *ctrl, q931_call *c)
+ {
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
+ c->peercallstate = Q931_CALL_STATE_NULL;
+- return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
++ return send_message(ctrl, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
+ }
+
+ static int facility_ies[] = { Q931_IE_FACILITY, -1 };
+
+-int q931_facility(struct pri*pri, q931_call *c)
++int q931_facility(struct pri*ctrl, q931_call *c)
+ {
+- return send_message(pri, c, Q931_FACILITY, facility_ies);
++ return send_message(ctrl, c, Q931_FACILITY, facility_ies);
+ }
+
+-static int notify_ies[] = { Q931_IE_NOTIFY_IND, -1 };
++static int notify_ies[] = { Q931_IE_NOTIFY_IND, Q931_IE_REDIRECTION_NUMBER, -1 };
+
+-int q931_notify(struct pri *pri, q931_call *c, int channel, int info)
++/*!
++ * \internal
++ * \brief Actually send a NOTIFY message with optional redirection number.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ * \param notify Notification indicator
++ * \param number Redirection number to send if not NULL.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int q931_notify_redirection_helper(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number)
+ {
+- if ((pri->switchtype == PRI_SWITCH_EUROISDN_T1) || (pri->switchtype != PRI_SWITCH_EUROISDN_E1)) {
+- if ((info > 0x2) || (info < 0x00))
++ if (number) {
++ call->redirection_number = *number;
++ } else {
++ q931_party_number_init(&call->redirection_number);
++ }
++ call->notify = notify;
++ return send_message(ctrl, call, Q931_NOTIFY, notify_ies);
++}
++
++/*!
++ * \brief Send a NOTIFY message with optional redirection number.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg
++ * \param notify Notification indicator
++ * \param number Redirection number to send if not NULL.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number)
++{
++ int status;
++ unsigned idx;
++ struct q931_call *subcall;
++
++ if (call->outboundbroadcast && call->master_call == call) {
++ status = 0;
++ for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
++ subcall = call->subcalls[idx];
++ if (subcall) {
++ /* Send to all subcalls that have given a positive response. */
++ switch (subcall->ourcallstate) {
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_ACTIVE:
++ if (q931_notify_redirection_helper(ctrl, subcall, notify, number)) {
++ status = -1;
++ }
++ break;
++ default:
++ break;
++ }
++ }
++ }
++ } else {
++ status = q931_notify_redirection_helper(ctrl, call, notify, number);
++ }
++ return status;
++}
++
++int q931_notify(struct pri *ctrl, q931_call *c, int channel, int info)
++{
++ if ((ctrl->switchtype == PRI_SWITCH_EUROISDN_T1) || (ctrl->switchtype != PRI_SWITCH_EUROISDN_E1)) {
++ if ((info > 0x2) || (info < 0x00)) {
+ return 0;
++ }
+ }
+
+- if (info >= 0)
+- c->notify = info & 0x7F;
+- else
+- c->notify = -1;
+- return send_message(pri, c, Q931_NOTIFY, notify_ies);
++ if (info >= 0) {
++ info = info & 0x7F;
++ } else {
++ info = -1;
++ }
++ return q931_notify_redirection(ctrl, c, info, NULL);
+ }
+
+ #ifdef ALERTING_NO_PROGRESS
+ static int call_progress_ies[] = { -1 };
+ #else
+-static int call_progress_with_cause_ies[] = { Q931_PROGRESS_INDICATOR, Q931_CAUSE, -1 };
++static int call_progress_with_cause_ies[] = { Q931_CAUSE, Q931_PROGRESS_INDICATOR, -1 };
+
+ static int call_progress_ies[] = { Q931_PROGRESS_INDICATOR, -1 };
+ #endif
+
+-int q931_call_progress(struct pri *pri, q931_call *c, int channel, int info)
++int q931_call_progress(struct pri *ctrl, q931_call *c, int channel, int info)
+ {
+ if (channel) {
+ c->ds1no = (channel & 0xff00) >> 8;
+ c->ds1explicit = (channel & 0x10000) >> 16;
+- channel &= 0xff;
+- c->channelno = channel;
++ c->channelno = channel & 0xff;
+ }
+
+ if (info) {
+@@ -2762,21 +4279,20 @@
+ c->progressmask = PRI_PROG_INBAND_AVAILABLE;
+ } else {
+ /* PI is mandatory IE for PROGRESS message - Q.931 3.1.8 */
+- pri_error(pri, "XXX Progress message requested but no information is provided\n");
++ pri_error(ctrl, "XXX Progress message requested but no information is provided\n");
+ c->progressmask = 0;
+ }
+
+ c->alive = 1;
+- return send_message(pri, c, Q931_PROGRESS, call_progress_ies);
++ return send_message(ctrl, c, Q931_PROGRESS, call_progress_ies);
+ }
+
+-int q931_call_progress_with_cause(struct pri *pri, q931_call *c, int channel, int info, int cause)
++int q931_call_progress_with_cause(struct pri *ctrl, q931_call *c, int channel, int info, int cause)
+ {
+ if (channel) {
+ c->ds1no = (channel & 0xff00) >> 8;
+ c->ds1explicit = (channel & 0x10000) >> 16;
+- channel &= 0xff;
+- c->channelno = channel;
++ c->channelno = channel & 0xff;
+ }
+
+ if (info) {
+@@ -2785,7 +4301,7 @@
+ c->progressmask = PRI_PROG_INBAND_AVAILABLE;
+ } else {
+ /* PI is mandatory IE for PROGRESS message - Q.931 3.1.8 */
+- pri_error(pri, "XXX Progress message requested but no information is provided\n");
++ pri_error(ctrl, "XXX Progress message requested but no information is provided\n");
+ c->progressmask = 0;
+ }
+
+@@ -2794,7 +4310,7 @@
+ c->causeloc = LOC_PRIV_NET_LOCAL_USER;
+
+ c->alive = 1;
+- return send_message(pri, c, Q931_PROGRESS, call_progress_with_cause_ies);
++ return send_message(ctrl, c, Q931_PROGRESS, call_progress_with_cause_ies);
+ }
+
+ #ifdef ALERTING_NO_PROGRESS
+@@ -2803,17 +4319,16 @@
+ static int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
+ #endif
+
+-int q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info)
++int q931_call_proceeding(struct pri *ctrl, q931_call *c, int channel, int info)
+ {
+ if (channel) {
+ c->ds1no = (channel & 0xff00) >> 8;
+ c->ds1explicit = (channel & 0x10000) >> 16;
+- channel &= 0xff;
+- c->channelno = channel;
++ c->channelno = channel & 0xff;
+ }
+ c->chanflags &= ~FLAG_PREFERRED;
+ c->chanflags |= FLAG_EXCLUSIVE;
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_INCOMING_CALL_PROCEEDING);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_INCOMING_CALL_PROCEEDING);
+ c->peercallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
+ if (info) {
+ c->progloc = LOC_PRIV_NET_LOCAL_USER;
+@@ -2823,62 +4338,73 @@
+ c->progressmask = 0;
+ c->proc = 1;
+ c->alive = 1;
+- return send_message(pri, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
++ return send_message(ctrl, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
+ }
+ #ifndef ALERTING_NO_PROGRESS
+-static int alerting_ies[] = { Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, -1 };
++static int alerting_ies[] = { Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, -1 };
+ #else
+-static int alerting_ies[] = { -1 };
++static int alerting_ies[] = { Q931_IE_FACILITY, -1 };
+ #endif
+
+-int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
++int q931_alerting(struct pri *ctrl, q931_call *c, int channel, int info)
+ {
+ if (!c->proc)
+- q931_call_proceeding(pri, c, channel, 0);
++ q931_call_proceeding(ctrl, c, channel, 0);
+ if (info) {
+ c->progloc = LOC_PRIV_NET_LOCAL_USER;
+ c->progcode = CODE_CCITT;
+ c->progressmask = PRI_PROG_INBAND_AVAILABLE;
+ } else
+ c->progressmask = 0;
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_RECEIVED);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_RECEIVED);
+ c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
+ c->alive = 1;
+- return send_message(pri, c, Q931_ALERTING, alerting_ies);
++
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_QSIG:
++ if (c->local_id.name.valid) {
++ /* Send calledName with ALERTING */
++ rose_called_name_encode(ctrl, c, Q931_ALERTING);
++ }
++ break;
++ default:
++ break;
++ }
++
++ return send_message(ctrl, c, Q931_ALERTING, alerting_ies);
+ }
+
+-static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
++static int setup_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, -1 };
+
+-int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
++int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn)
+ {
+ if (channel) {
+ c->ds1no = (channel & 0xff00) >> 8;
+ c->ds1explicit = (channel & 0x10000) >> 16;
+- channel &= 0xff;
+- c->channelno = channel;
++ c->channelno = channel & 0xff;
+ }
+ c->chanflags &= ~FLAG_PREFERRED;
+ c->chanflags |= FLAG_EXCLUSIVE;
+- if (nonisdn && (pri->switchtype != PRI_SWITCH_DMS100)) {
++ if (nonisdn && (ctrl->switchtype != PRI_SWITCH_DMS100)) {
+ c->progloc = LOC_PRIV_NET_LOCAL_USER;
+ c->progcode = CODE_CCITT;
+ c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
+ } else
+ c->progressmask = 0;
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OVERLAP_RECEIVING);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OVERLAP_RECEIVING);
+ c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
+ c->alive = 1;
+- return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
++ return send_message(ctrl, c, Q931_SETUP_ACKNOWLEDGE, setup_ack_ies);
+ }
+
+ /* T313 expiry, first time */
+ static void pri_connect_timeout(void *data)
+ {
+ struct q931_call *c = data;
+- struct pri *pri = c->pri;
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "Timed out looking for connect acknowledge\n");
+- q931_disconnect(pri, c, PRI_CAUSE_NORMAL_CLEARING);
++ struct pri *ctrl = c->pri;
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, "Timed out looking for connect acknowledge\n");
++ q931_disconnect(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
+
+ }
+
+@@ -2886,85 +4412,120 @@
+ static void pri_release_timeout(void *data)
+ {
+ struct q931_call *c = data;
+- struct pri *pri = c->pri;
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "Timed out looking for release complete\n");
++ struct pri *ctrl = c->pri;
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, "Timed out looking for release complete\n");
+ c->t308_timedout++;
+ c->alive = 1;
+
+ /* The call to q931_release will re-schedule T308 */
+- q931_release(pri, c, c->cause);
++ q931_release(ctrl, c, c->cause);
+ }
+
+ /* T308 expiry, second time */
+ static void pri_release_finaltimeout(void *data)
+ {
+ struct q931_call *c = data;
+- struct pri *pri = c->pri;
++ struct pri *ctrl = c->pri;
+ c->alive = 1;
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "Final time-out looking for release complete\n");
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, "Final time-out looking for release complete\n");
+ c->t308_timedout++;
+ c->ourcallstate = Q931_CALL_STATE_NULL;
+ c->peercallstate = Q931_CALL_STATE_NULL;
+- pri->schedev = 1;
+- pri->ev.e = PRI_EVENT_HANGUP_ACK;
+- pri->ev.hangup.channel = c->channelno;
+- pri->ev.hangup.cause = c->cause;
+- pri->ev.hangup.cref = c->cr;
+- pri->ev.hangup.call = c;
+- pri->ev.hangup.aoc_units = c->aoc_units;
+- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
+- q931_hangup(pri, c, c->cause);
++ q931_clr_subcommands(ctrl);
++ ctrl->schedev = 1;
++ ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
++ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
++ ctrl->ev.hangup.channel = q931_encode_channel(c);
++ ctrl->ev.hangup.cause = c->cause;
++ ctrl->ev.hangup.cref = c->cr;
++ ctrl->ev.hangup.call = c->master_call;
++ ctrl->ev.hangup.aoc_units = c->aoc_units;
++ ctrl->ev.hangup.call_held = NULL;
++ ctrl->ev.hangup.call_active = NULL;
++ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
++ pri_hangup(ctrl, c, c->cause);
+ }
+
+ /* T305 expiry, first time */
+ static void pri_disconnect_timeout(void *data)
+ {
+ struct q931_call *c = data;
+- struct pri *pri = c->pri;
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "Timed out looking for release\n");
++ struct pri *ctrl = c->pri;
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, "Timed out looking for release\n");
+ c->alive = 1;
+- q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
++ q931_release(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
+ }
+
+-int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
++static int connect_ies[] = {
++ Q931_CHANNEL_IDENT,
++ Q931_IE_FACILITY,
++ Q931_PROGRESS_INDICATOR,
++ Q931_DISPLAY,
++ Q931_IE_CONNECTED_NUM,
++ Q931_IE_CONNECTED_SUBADDR,
++ -1
++};
++
++int q931_connect(struct pri *ctrl, q931_call *c, int channel, int nonisdn)
+ {
+ if (channel) {
+ c->ds1no = (channel & 0xff00) >> 8;
+ c->ds1explicit = (channel & 0x10000) >> 16;
+- channel &= 0xff;
+- c->channelno = channel;
++ c->channelno = channel & 0xff;
+ }
+ c->chanflags &= ~FLAG_PREFERRED;
+ c->chanflags |= FLAG_EXCLUSIVE;
+- if (nonisdn && (pri->switchtype != PRI_SWITCH_DMS100)) {
++ if (nonisdn && (ctrl->switchtype != PRI_SWITCH_DMS100)) {
+ c->progloc = LOC_PRIV_NET_LOCAL_USER;
+ c->progcode = CODE_CCITT;
+ c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
+ } else
+ c->progressmask = 0;
+- if(pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG)
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
++ if(ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG)
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
+ else
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CONNECT_REQUEST);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CONNECT_REQUEST);
+ c->peercallstate = Q931_CALL_STATE_ACTIVE;
+ c->alive = 1;
+ /* Connect request timer */
+- if (c->retranstimer)
+- pri_schedule_del(pri, c->retranstimer);
++ pri_schedule_del(ctrl, c->retranstimer);
+ c->retranstimer = 0;
+- if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (pri->bri || (!pri->subchannel)))
+- c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T313], pri_connect_timeout, c);
+- return send_message(pri, c, Q931_CONNECT, connect_ies);
++ if ((c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && (ctrl->bri || (!ctrl->subchannel)))
++ c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T313], pri_connect_timeout, c);
++
++ if (c->redirecting.state == Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3) {
++ c->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
++ /* Send DivertingLegInformation3 with CONNECT. */
++ c->redirecting.to = c->local_id;
++ if (!c->redirecting.to.number.valid) {
++ q931_party_number_init(&c->redirecting.to.number);
++ c->redirecting.to.number.valid = 1;
++ c->redirecting.to.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ }
++ rose_diverting_leg_information3_encode(ctrl, c, Q931_CONNECT);
++ }
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_QSIG:
++ if (c->local_id.name.valid) {
++ /* Send connectedName with CONNECT */
++ rose_connected_name_encode(ctrl, c, Q931_CONNECT);
++ }
++ break;
++ default:
++ break;
++ }
++ return send_message(ctrl, c, Q931_CONNECT, connect_ies);
+ }
+
+ static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
+
+-int q931_release(struct pri *pri, q931_call *c, int cause)
++int q931_release(struct pri *ctrl, q931_call *c, int cause)
+ {
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RELEASE_REQUEST);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_RELEASE_REQUEST);
+ /* c->peercallstate stays the same */
+ if (c->alive) {
+ c->alive = 0;
+@@ -2972,26 +4533,26 @@
+ c->causecode = CODE_CCITT;
+ c->causeloc = LOC_PRIV_NET_LOCAL_USER;
+ if (c->acked) {
+- if (c->retranstimer)
+- pri_schedule_del(pri, c->retranstimer);
++ pri_schedule_del(ctrl, c->retranstimer);
+ if (!c->t308_timedout) {
+- c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T308], pri_release_timeout, c);
++ c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T308], pri_release_timeout, c);
+ } else {
+- c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T308], pri_release_finaltimeout, c);
++ c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T308], pri_release_finaltimeout, c);
+ }
+- return send_message(pri, c, Q931_RELEASE, release_ies);
++ return send_message(ctrl, c, Q931_RELEASE, release_ies);
+ } else
+- return send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies); /* Yes, release_ies, not release_complete_ies */
++ return send_message(ctrl, c, Q931_RELEASE_COMPLETE, release_ies); /* Yes, release_ies, not release_complete_ies */
+ } else
+ return 0;
+ }
+
+ static int restart_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
+
+-int q931_restart(struct pri *pri, int channel)
++int q931_restart(struct pri *ctrl, int channel)
+ {
+ struct q931_call *c;
+- c = q931_getcall(pri, 0 | 0x8000, 1);
++
++ c = q931_getcall(ctrl, 0 | 0x8000);
+ if (!c)
+ return -1;
+ if (!channel)
+@@ -2999,20 +4560,19 @@
+ c->ri = 0;
+ c->ds1no = (channel & 0xff00) >> 8;
+ c->ds1explicit = (channel & 0x10000) >> 16;
+- channel &= 0xff;
+- c->channelno = channel;
++ c->channelno = channel & 0xff;
+ c->chanflags &= ~FLAG_PREFERRED;
+ c->chanflags |= FLAG_EXCLUSIVE;
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_RESTART);
+ c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
+- return send_message(pri, c, Q931_RESTART, restart_ies);
++ return send_message(ctrl, c, Q931_RESTART, restart_ies);
+ }
+
+-static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
++static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_FACILITY, Q931_IE_USER_USER, -1 };
+
+-int q931_disconnect(struct pri *pri, q931_call *c, int cause)
++int q931_disconnect(struct pri *ctrl, q931_call *c, int cause)
+ {
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_REQUEST);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_DISCONNECT_REQUEST);
+ c->peercallstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
+ if (c->alive) {
+ c->alive = 0;
+@@ -3020,27 +4580,125 @@
+ c->causecode = CODE_CCITT;
+ c->causeloc = LOC_PRIV_NET_LOCAL_USER;
+ c->sendhangupack = 1;
+- if (c->retranstimer)
+- pri_schedule_del(pri, c->retranstimer);
+- c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T305], pri_disconnect_timeout, c);
+- return send_message(pri, c, Q931_DISCONNECT, disconnect_ies);
++ pri_schedule_del(ctrl, c->retranstimer);
++ c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T305], pri_disconnect_timeout, c);
++ return send_message(ctrl, c, Q931_DISCONNECT, disconnect_ies);
+ } else
+ return 0;
+ }
+
+-static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY,
+- Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_IE_USER_USER, Q931_SENDING_COMPLETE,
+- Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 };
++static int setup_ies[] = {
++ Q931_BEARER_CAPABILITY,
++ Q931_CHANNEL_IDENT,
++ Q931_IE_FACILITY,
++ Q931_PROGRESS_INDICATOR,
++ Q931_NETWORK_SPEC_FAC,
++ Q931_DISPLAY,
++ Q931_IE_KEYPAD_FACILITY,
++ Q931_REVERSE_CHARGE_INDIC,
++ Q931_CALLING_PARTY_NUMBER,
++ Q931_CALLING_PARTY_SUBADDR,
++ Q931_CALLED_PARTY_NUMBER,
++ Q931_CALLED_PARTY_SUBADDR,
++ Q931_REDIRECTING_NUMBER,
++ Q931_IE_USER_USER,
++ Q931_SENDING_COMPLETE,
++ Q931_IE_ORIGINATING_LINE_INFO,
++ Q931_IE_GENERIC_DIGITS,
++ -1
++};
+
+-static int gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
++static int gr303_setup_ies[] = {
++ Q931_BEARER_CAPABILITY,
++ Q931_CHANNEL_IDENT,
++ -1
++};
+
+-static int cis_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
++/*! Call Independent Signalling SETUP ie's */
++static int cis_setup_ies[] = {
++ Q931_BEARER_CAPABILITY,
++ Q931_CHANNEL_IDENT,
++ Q931_IE_FACILITY,
++ Q931_IE_KEYPAD_FACILITY,
++ Q931_CALLING_PARTY_NUMBER,
++ Q931_CALLING_PARTY_SUBADDR,
++ Q931_CALLED_PARTY_NUMBER,
++ Q931_CALLED_PARTY_SUBADDR,
++ Q931_SENDING_COMPLETE,
++ -1
++};
+
+-int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
++static void stop_t303(struct q931_call *call)
+ {
++ /* T303 should only be running on the master call */
++ pri_schedule_del(call->master_call->pri, call->master_call->t303_timer);
++ call->master_call->t303_timer = 0;
++}
++
++static void t303_expiry(void *data);
++
++static void start_t303(struct q931_call *call)
++{
++ if (call->t303_timer) {
++ pri_error(call->pri, "Should not have T303 set when starting again. Stopping first\n");
++ stop_t303(call);
++ }
++
++ //pri_error(call->pri, "T303 should be %d\n", call->pri->timers[PRI_TIMER_T303]);
++ call->t303_timer = pri_schedule_event(call->pri, call->pri->timers[PRI_TIMER_T303], t303_expiry, call);
++}
++
++static void pri_fake_clearing(void *data);
++
++static void t303_expiry(void *data)
++{
++ struct q931_call *c = data;
++ struct pri *ctrl = c->pri;
+ int res;
+-
+-
++
++ c->t303_expirycnt++;
++ c->t303_timer = 0;
++
++ if (c->cause != -1) {
++ /* We got a DISCONNECT, RELEASE, or RELEASE_COMPLETE and no other responses. */
++ pri_fake_clearing(c);
++ } else if (c->t303_expirycnt < 2) {
++ if (ctrl->subchannel && !ctrl->bri)
++ res = send_message(ctrl, c, Q931_SETUP, gr303_setup_ies);
++ else if (c->cis_call)
++ res = send_message(ctrl, c, Q931_SETUP, cis_setup_ies);
++ else
++ res = send_message(ctrl, c, Q931_SETUP, setup_ies);
++
++ if (res) {
++ pri_error(c->pri, "Error resending setup message!\n");
++ }
++ start_t303(c);
++ } else {
++ c->cause = PRI_CAUSE_NO_USER_RESPONSE;
++ pri_fake_clearing(c);
++ }
++}
++
++int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
++{
++ int res;
++
++ if (!req->called.number.valid && (!req->keypad_digits || !req->keypad_digits[0])) {
++ /* No called number or keypad digits to send. */
++ return -1;
++ }
++
++ c->called = req->called;
++ libpri_copy_string(c->overlap_digits, req->called.number.str, sizeof(c->overlap_digits));
++
++ if (req->keypad_digits) {
++ libpri_copy_string(c->keypad_digits, req->keypad_digits,
++ sizeof(c->keypad_digits));
++ } else {
++ c->keypad_digits[0] = '\0';
++ }
++
+ c->transcapability = req->transmode;
+ c->transmoderate = TRANS_MODE_64_CIRCUIT;
+ if (!req->userl1)
+@@ -3050,89 +4708,68 @@
+ c->userl3 = -1;
+ c->ds1no = (req->channel & 0xff00) >> 8;
+ c->ds1explicit = (req->channel & 0x10000) >> 16;
+- req->channel &= 0xff;
+- if ((pri->localtype == PRI_CPE) && pri->subchannel && !pri->bri) {
+- req->channel = 0;
+- req->exclusive = 0;
++ if ((ctrl->localtype == PRI_CPE) && ctrl->subchannel && !ctrl->bri) {
++ c->channelno = 0;
++ c->chanflags = 0;
++ } else {
++ c->channelno = req->channel & 0xff;
++ if (req->exclusive) {
++ c->chanflags = FLAG_EXCLUSIVE;
++ } else {
++ c->chanflags = FLAG_PREFERRED;
++ }
+ }
+-
+- c->channelno = req->channel;
++
+ c->slotmap = -1;
+ c->nonisdn = req->nonisdn;
+ c->newcall = 0;
+- c->justsignalling = req->justsignalling;
++ c->cis_call = req->cis_call;
++ c->cis_auto_disconnect = req->cis_auto_disconnect;
+ c->complete = req->numcomplete;
+- if (req->exclusive)
+- c->chanflags = FLAG_EXCLUSIVE;
+- else if (c->channelno)
+- c->chanflags = FLAG_PREFERRED;
+- if (req->caller) {
+- libpri_copy_string(c->callernum, req->caller, sizeof(c->callernum));
+- c->callerplan = req->callerplan;
+- if (req->callername)
+- libpri_copy_string(c->callername, req->callername, sizeof(c->callername));
+- else
+- c->callername[0] = '\0';
+- if ((pri->switchtype == PRI_SWITCH_DMS100) ||
+- (pri->switchtype == PRI_SWITCH_ATT4ESS)) {
+- /* Doesn't like certain presentation types */
+- if (!(req->callerpres & 0x7c))
+- req->callerpres = PRES_ALLOWED_NETWORK_NUMBER;
+- }
+- c->callerpres = req->callerpres;
+- } else {
+- c->callernum[0] = '\0';
+- c->callername[0] = '\0';
+- c->callerplan = PRI_UNKNOWN;
+- c->callerpres = PRES_NUMBER_NOT_AVAILABLE;
++
++ if (req->caller.number.valid) {
++ c->local_id = req->caller;
++ q931_party_id_fixup(ctrl, &c->local_id);
+ }
+- if (req->redirectingnum) {
+- libpri_copy_string(c->redirectingnum, req->redirectingnum, sizeof(c->redirectingnum));
+- c->redirectingplan = req->redirectingplan;
+- if ((pri->switchtype == PRI_SWITCH_DMS100) ||
+- (pri->switchtype == PRI_SWITCH_ATT4ESS)) {
+- /* Doesn't like certain presentation types */
+- if (!(req->redirectingpres & 0x7c))
+- req->redirectingpres = PRES_ALLOWED_NETWORK_NUMBER;
+- }
+- c->redirectingpres = req->redirectingpres;
+- c->redirectingreason = req->redirectingreason;
+- } else {
+- c->redirectingnum[0] = '\0';
+- c->redirectingplan = PRI_UNKNOWN;
+- c->redirectingpres = PRES_NUMBER_NOT_AVAILABLE;
+- c->redirectingreason = PRI_REDIR_UNKNOWN;
++
++ if (req->redirecting.from.number.valid) {
++ c->redirecting = req->redirecting;
++ q931_party_id_fixup(ctrl, &c->redirecting.from);
++ q931_party_id_fixup(ctrl, &c->redirecting.to);
++ q931_party_id_fixup(ctrl, &c->redirecting.orig_called);
+ }
+- if (req->called) {
+- libpri_copy_string(c->callednum, req->called, sizeof(c->callednum));
+- c->calledplan = req->calledplan;
+- } else
+- return -1;
+
+ if (req->useruserinfo)
+ libpri_copy_string(c->useruserinfo, req->useruserinfo, sizeof(c->useruserinfo));
+ else
+ c->useruserinfo[0] = '\0';
+
+- if (req->nonisdn && (pri->switchtype == PRI_SWITCH_NI2))
++ if (req->nonisdn && (ctrl->switchtype == PRI_SWITCH_NI2))
+ c->progressmask = PRI_PROG_CALLER_NOT_ISDN;
+ else
+ c->progressmask = 0;
+
+- pri_call_add_standard_apdus(pri, c);
++ c->reversecharge = req->reversecharge;
+
+- if (pri->subchannel && !pri->bri)
+- res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
+- else if (c->justsignalling)
+- res = send_message(pri, c, Q931_SETUP, cis_setup_ies);
++ pri_call_add_standard_apdus(ctrl, c);
++
++ if (ctrl->subchannel && !ctrl->bri)
++ res = send_message(ctrl, c, Q931_SETUP, gr303_setup_ies);
++ else if (c->cis_call)
++ res = send_message(ctrl, c, Q931_SETUP, cis_setup_ies);
+ else
+- res = send_message(pri, c, Q931_SETUP, setup_ies);
++ res = send_message(ctrl, c, Q931_SETUP, setup_ies);
+ if (!res) {
+ c->alive = 1;
+ /* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
+ c->sendhangupack = 1;
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_INITIATED);
+- c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_INITIATED);
++ c->peercallstate = Q931_CALL_STATE_CALL_PRESENT;
++ c->t303_expirycnt = 0;
++ if (BRI_NT_PTMP(ctrl)) {
++ c->outboundbroadcast = 1;
++ }
++ start_t303(c);
+ }
+ return res;
+
+@@ -3140,22 +4777,22 @@
+
+ static int release_complete_ies[] = { Q931_IE_USER_USER, -1 };
+
+-static int q931_release_complete(struct pri *pri, q931_call *c, int cause)
++static int q931_release_complete(struct pri *ctrl, q931_call *c, int cause)
+ {
+ int res = 0;
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
+ c->peercallstate = Q931_CALL_STATE_NULL;
+ if (cause > -1) {
+ c->cause = cause;
+ c->causecode = CODE_CCITT;
+ c->causeloc = LOC_PRIV_NET_LOCAL_USER;
+ /* release_ies has CAUSE in it */
+- res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies);
++ res = send_message(ctrl, c, Q931_RELEASE_COMPLETE, release_ies);
+ } else
+- res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_complete_ies);
++ res = send_message(ctrl, c, Q931_RELEASE_COMPLETE, release_complete_ies);
+ c->alive = 0;
+ /* release the structure */
+- res += q931_hangup(pri,c,cause);
++ res += pri_hangup(ctrl, c, cause);
+ return res;
+ }
+
+@@ -3163,46 +4800,553 @@
+
+ static int gr303_connect_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
+
+-static int q931_connect_acknowledge(struct pri *pri, q931_call *c)
++static int q931_connect_acknowledge(struct pri *ctrl, q931_call *c)
+ {
+- if (pri->subchannel && !pri->bri) {
+- if (pri->localtype == PRI_CPE)
+- return send_message(pri, c, Q931_CONNECT_ACKNOWLEDGE, gr303_connect_acknowledge_ies);
++ if (ctrl->subchannel && !ctrl->bri) {
++ if (ctrl->localtype == PRI_CPE)
++ return send_message(ctrl, c, Q931_CONNECT_ACKNOWLEDGE, gr303_connect_acknowledge_ies);
+ } else
+- return send_message(pri, c, Q931_CONNECT_ACKNOWLEDGE, connect_acknowledge_ies);
++ return send_message(ctrl, c, Q931_CONNECT_ACKNOWLEDGE, connect_acknowledge_ies);
+ return 0;
+ }
+
+-int q931_hangup(struct pri *pri, q931_call *c, int cause)
++/*!
++ * \internal
++ * \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
++ *
++ * \param call Starting Q.931 call record of search.
++ *
++ * \retval winning-call or given call if not outboundbroadcast.
++ * \retval NULL if no winning call yet.
++ */
++static struct q931_call *q931_find_winning_call(struct q931_call *call)
+ {
++ struct q931_call *master;
++
++ master = call->master_call;
++ if (master->outboundbroadcast) {
++ /* We have potential subcalls. Now get the winning call if declared yet. */
++ if (master->pri_winner < 0) {
++ /* Winner not declared yet.*/
++ call = NULL;
++ } else {
++ call = master->subcalls[master->pri_winner];
++ }
++ }
++ return call;
++}
++
++/*!
++ * \internal
++ * \brief Send HOLD message response wait timeout.
++ *
++ * \param data Q.931 call leg. (Master Q.931 subcall structure)
++ *
++ * \return Nothing
++ */
++static void q931_hold_timeout(void *data)
++{
++ struct q931_call *call = data;
++ struct pri *ctrl = call->pri;
++
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "Time-out waiting for HOLD response\n");
++ }
++
++ /* Ensure that the timer is deleted. */
++ pri_schedule_del(ctrl, call->hold_timer);
++ call->hold_timer = 0;
++
++ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
++
++ q931_clr_subcommands(ctrl);
++ ctrl->schedev = 1;
++ ctrl->ev.e = PRI_EVENT_HOLD_REJ;
++ ctrl->ev.hold_rej.channel = q931_encode_channel(call);
++ ctrl->ev.hold_rej.call = call;
++ ctrl->ev.hold_rej.cause = PRI_CAUSE_MESSAGE_TYPE_NONEXIST;
++ ctrl->ev.hold_rej.subcmds = &ctrl->subcmds;
++}
++
++/*!
++ * \internal
++ * \brief Determine if a hold request is allowed now.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (Master Q.931 subcall structure)
++ *
++ * \retval TRUE if we can send a HOLD request.
++ * \retval FALSE if not allowed.
++ */
++static int q931_is_hold_allowed(const struct pri *ctrl, const struct q931_call *call)
++{
++ int allowed;
++
++ allowed = 0;
++ switch (call->ourcallstate) {
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ if (q931_is_ptmp(ctrl)) {
++ /* HOLD request only allowed in these states if point-to-point mode. */
++ break;
++ }
++ /* Fall through */
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_ACTIVE:
++ switch (call->hold_state) {
++ case Q931_HOLD_STATE_IDLE:
++ allowed = 1;
++ break;
++ default:
++ break;
++ }
++ break;
++ case Q931_CALL_STATE_DISCONNECT_INDICATION:
++ case Q931_CALL_STATE_RELEASE_REQUEST:
++ /* Ignore HOLD request in these states. */
++ break;
++ default:
++ break;
++ }
++
++ return allowed;
++}
++
++static int hold_ies[] = {
++ -1
++};
++
++/*!
++ * \brief Send the HOLD message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (Master Q.931 subcall structure)
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int q931_send_hold(struct pri *ctrl, struct q931_call *call)
++{
++ struct q931_call *winner;
++
++ winner = q931_find_winning_call(call);
++ if (!winner || !q931_is_hold_allowed(ctrl, call)) {
++ return -1;
++ }
++ pri_schedule_del(ctrl, call->hold_timer);
++ call->hold_timer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T_HOLD],
++ q931_hold_timeout, call);
++ if (send_message(ctrl, winner, Q931_HOLD, hold_ies)) {
++ pri_schedule_del(ctrl, call->hold_timer);
++ call->hold_timer = 0;
++ return -1;
++ }
++ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_HOLD_REQ);
++ return 0;
++}
++
++static int hold_ack_ies[] = {
++ -1
++};
++
++/*!
++ * \brief Send the HOLD ACKNOWLEDGE message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (Master Q.931 subcall structure)
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call)
++{
++ struct q931_call *winner;
++
++ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
++
++ winner = q931_find_winning_call(call);
++ if (!winner) {
++ return -1;
++ }
++
++ /* Call is now on hold so forget the channel. */
++ winner->channelno = 0;/* No channel */
++ winner->ds1no = 0;
++ winner->ds1explicit = 0;
++ winner->chanflags = 0;
++
++ return send_message(ctrl, winner, Q931_HOLD_ACKNOWLEDGE, hold_ack_ies);
++}
++
++static int hold_reject_ies[] = {
++ Q931_CAUSE,
++ -1
++};
++
++/*!
++ * \internal
++ * \brief Send the HOLD REJECT message only.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (subcall)
++ * \param cause Q.931 cause code for rejecting the hold request.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int q931_send_hold_rej_msg(struct pri *ctrl, struct q931_call *call, int cause)
++{
++ call->cause = cause;
++ call->causecode = CODE_CCITT;
++ call->causeloc = LOC_PRIV_NET_LOCAL_USER;
++ return send_message(ctrl, call, Q931_HOLD_REJECT, hold_reject_ies);
++}
++
++/*!
++ * \brief Send the HOLD REJECT message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (Master Q.931 subcall structure)
++ * \param cause Q.931 cause code for rejecting the hold request.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int q931_send_hold_rej(struct pri *ctrl, struct q931_call *call, int cause)
++{
++ struct q931_call *winner;
++
++ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
++
++ winner = q931_find_winning_call(call);
++ if (!winner) {
++ return -1;
++ }
++
++ return q931_send_hold_rej_msg(ctrl, winner, cause);
++}
++
++/*!
++ * \internal
++ * \brief Send RETRIEVE message response wait timeout.
++ *
++ * \param data Q.931 call leg. (Master Q.931 subcall structure)
++ *
++ * \return Nothing
++ */
++static void q931_retrieve_timeout(void *data)
++{
++ struct q931_call *call = data;
++ struct pri *ctrl = call->pri;
++ struct q931_call *winner;
++
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "Time-out waiting for RETRIEVE response\n");
++ }
++
++ /* Ensure that the timer is deleted. */
++ pri_schedule_del(ctrl, call->hold_timer);
++ call->hold_timer = 0;
++
++ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
++
++ winner = q931_find_winning_call(call);
++ if (winner) {
++ /* Call is still on hold so forget the channel. */
++ winner->channelno = 0;/* No channel */
++ winner->ds1no = 0;
++ winner->ds1explicit = 0;
++ winner->chanflags = 0;
++ }
++
++ q931_clr_subcommands(ctrl);
++ ctrl->schedev = 1;
++ ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
++ ctrl->ev.retrieve_rej.channel = q931_encode_channel(call);
++ ctrl->ev.retrieve_rej.call = call;
++ ctrl->ev.retrieve_rej.cause = PRI_CAUSE_MESSAGE_TYPE_NONEXIST;
++ ctrl->ev.retrieve_rej.subcmds = &ctrl->subcmds;
++}
++
++/*!
++ * \internal
++ * \brief Determine if a retrieve request is allowed now.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (Master Q.931 subcall structure)
++ *
++ * \retval TRUE if we can send a RETRIEVE request.
++ * \retval FALSE if not allowed.
++ */
++static int q931_is_retrieve_allowed(const struct pri *ctrl, const struct q931_call *call)
++{
++ int allowed;
++
++ allowed = 0;
++ switch (call->ourcallstate) {
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ if (q931_is_ptmp(ctrl)) {
++ /* RETRIEVE request only allowed in these states if point-to-point mode. */
++ break;
++ }
++ /* Fall through */
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_ACTIVE:
++ switch (call->hold_state) {
++ case Q931_HOLD_STATE_CALL_HELD:
++ allowed = 1;
++ break;
++ default:
++ break;
++ }
++ break;
++ case Q931_CALL_STATE_DISCONNECT_INDICATION:
++ case Q931_CALL_STATE_RELEASE_REQUEST:
++ /* Ignore RETRIEVE request in these states. */
++ break;
++ default:
++ break;
++ }
++
++ return allowed;
++}
++
++static int retrieve_ies[] = {
++ Q931_CHANNEL_IDENT,
++ -1
++};
++
++/*!
++ * \brief Send the RETRIEVE message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (Master Q.931 subcall structure)
++ * \param channel Encoded channel id to use. If zero do not send channel id.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel)
++{
++ struct q931_call *winner;
++
++ winner = q931_find_winning_call(call);
++ if (!winner || !q931_is_retrieve_allowed(ctrl, call)) {
++ return -1;
++ }
++
++ if (channel) {
++ winner->ds1no = (channel & 0xff00) >> 8;
++ winner->ds1explicit = (channel & 0x10000) >> 16;
++ winner->channelno = channel & 0xff;
++ if (ctrl->localtype == PRI_NETWORK) {
++ winner->chanflags = FLAG_EXCLUSIVE;
++ } else {
++ winner->chanflags = FLAG_PREFERRED;
++ }
++ } else {
++ /* Do not send Q931_CHANNEL_IDENT */
++ winner->chanflags = 0;
++ }
++
++ pri_schedule_del(ctrl, call->hold_timer);
++ call->hold_timer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T_RETRIEVE],
++ q931_retrieve_timeout, call);
++ if (send_message(ctrl, winner, Q931_RETRIEVE, retrieve_ies)) {
++ pri_schedule_del(ctrl, call->hold_timer);
++ call->hold_timer = 0;
++
++ /* Call is still on hold so forget the channel. */
++ winner->channelno = 0;/* No channel */
++ winner->ds1no = 0;
++ winner->ds1explicit = 0;
++ winner->chanflags = 0;
++ return -1;
++ }
++ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_RETRIEVE_REQ);
++ return 0;
++}
++
++static int retrieve_ack_ies[] = {
++ Q931_CHANNEL_IDENT,
++ -1
++};
++
++/*!
++ * \brief Send the RETRIEVE ACKNOWLEDGE message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (Master Q.931 subcall structure)
++ * \param channel Encoded channel id to use.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int q931_send_retrieve_ack(struct pri *ctrl, struct q931_call *call, int channel)
++{
++ struct q931_call *winner;
++
++ winner = q931_find_winning_call(call);
++ if (!winner) {
++ return -1;
++ }
++
++ winner->ds1no = (channel & 0xff00) >> 8;
++ winner->ds1explicit = (channel & 0x10000) >> 16;
++ winner->channelno = channel & 0xff;
++ winner->chanflags = FLAG_EXCLUSIVE;
++
++ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
++
++ return send_message(ctrl, winner, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_ack_ies);
++}
++
++static int retrieve_reject_ies[] = {
++ Q931_CAUSE,
++ -1
++};
++
++/*!
++ * \internal
++ * \brief Send the RETRIEVE REJECT message only.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (subcall)
++ * \param cause Q.931 cause code for rejecting the retrieve request.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int q931_send_retrieve_rej_msg(struct pri *ctrl, struct q931_call *call, int cause)
++{
++ call->cause = cause;
++ call->causecode = CODE_CCITT;
++ call->causeloc = LOC_PRIV_NET_LOCAL_USER;
++ return send_message(ctrl, call, Q931_RETRIEVE_REJECT, retrieve_reject_ies);
++}
++
++/*!
++ * \brief Send the RETRIEVE REJECT message.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg. (Master Q.931 subcall structure)
++ * \param cause Q.931 cause code for rejecting the retrieve request.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++int q931_send_retrieve_rej(struct pri *ctrl, struct q931_call *call, int cause)
++{
++ struct q931_call *winner;
++
++ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
++
++ winner = q931_find_winning_call(call);
++ if (!winner) {
++ return -1;
++ }
++
++ /* Call is still on hold so forget the channel. */
++ winner->channelno = 0;/* No channel */
++ winner->ds1no = 0;
++ winner->ds1explicit = 0;
++ winner->chanflags = 0;
++
++ return q931_send_retrieve_rej_msg(ctrl, winner, cause);
++}
++
++static int pri_internal_clear(void *data);
++
++/* Fake RELEASE for NT-PTMP initiated SETUPs w/o response */
++static void pri_fake_clearing(void *data)
++{
++ struct q931_call *c = data;
++ struct pri *ctrl = c->pri;
++
++ c->performing_fake_clearing = 1;
++ if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
++ ctrl->schedev = 1;
++}
++
++static void pri_create_fake_clearing(struct q931_call *c, struct pri *master)
++{
++ c->pri = master;
++
++ pri_schedule_del(master, c->retranstimer);
++ c->retranstimer = pri_schedule_event(master, 0, pri_fake_clearing, c);
++}
++
++//static int q931_get_subcall_count(struct q931_call *call);
++
++static int __q931_hangup(struct pri *ctrl, q931_call *c, int cause)
++{
+ int disconnect = 1;
+ int release_compl = 0;
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "NEW_HANGUP DEBUG: Calling q931_hangup, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
+- if (!pri || !c)
++ int t303_was_running = c->master_call->t303_timer;
++
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl,
++ "NEW_HANGUP DEBUG: Calling q931_hangup, ourstate %s, peerstate %s, hold-state %s\n",
++ q931_call_state_str(c->ourcallstate),
++ q931_call_state_str(c->peercallstate),
++ q931_hold_state_str(c->master_call->hold_state));
++ if (!ctrl || !c)
+ return -1;
+ /* If mandatory IE was missing, insist upon that cause code */
+ if (c->cause == PRI_CAUSE_MANDATORY_IE_MISSING)
+ cause = c->cause;
+- if (cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81) {
++ switch (cause) {
++ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
++ case PRI_CAUSE_REQUESTED_CHAN_UNAVAIL:
++ case PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST:
++ case PRI_CAUSE_UNALLOCATED:
++ case PRI_CAUSE_INVALID_CALL_REFERENCE:
+ /* We'll send RELEASE_COMPLETE with these causes */
+ disconnect = 0;
+ release_compl = 1;
+- }
+- if (cause == 6 || cause == 7 || cause == 26) {
++ break;
++ case PRI_CAUSE_CHANNEL_UNACCEPTABLE:
++ case PRI_CAUSE_CALL_AWARDED_DELIVERED:
++ case PRI_CAUSE_NONSELECTED_USER_CLEARING:
+ /* We'll send RELEASE with these causes */
+ disconnect = 0;
++ break;
++ default:
++ break;
+ }
++ if (c->cis_call) {
++ disconnect = 0;
++ }
++
++ c->hangupinitiated = 1;
++ stop_t303(c);
++
+ /* All other causes we send with DISCONNECT */
+ switch(c->ourcallstate) {
+ case Q931_CALL_STATE_NULL:
+ if (c->peercallstate == Q931_CALL_STATE_NULL)
+ /* free the resources if we receive or send REL_COMPL */
+- q931_destroycall(pri, c->cr);
++ pri_destroycall(ctrl, c);
+ else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST)
+- q931_release_complete(pri,c,cause);
++ q931_release_complete(ctrl,c,cause);
+ break;
+ case Q931_CALL_STATE_CALL_INITIATED:
++ if (c->outboundbroadcast && c->master_call == c && t303_was_running) {
++ //c->fakeclearing = 1;
++ //c->alive = 0;
++ /* We need to fake a received clearing sequence in this case... */
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "Faking clearing\n");
++ }
++ pri_create_fake_clearing(c, PRI_MASTER(ctrl));
++ /* This means that we never got a response from a TEI */
++ return 0;
++ }
+ /* we sent SETUP */
+ case Q931_CALL_STATE_OVERLAP_SENDING:
+ /* received SETUP_ACKNOWLEDGE */
+@@ -3221,29 +5365,45 @@
+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
+ /* received SETUP_ACKNOWLEDGE */
+ /* send DISCONNECT in general */
+- if (c->peercallstate != Q931_CALL_STATE_NULL && c->peercallstate != Q931_CALL_STATE_DISCONNECT_REQUEST && c->peercallstate != Q931_CALL_STATE_DISCONNECT_INDICATION && c->peercallstate != Q931_CALL_STATE_RELEASE_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART) {
++ switch (c->peercallstate) {
++ default:
+ if (disconnect)
+- q931_disconnect(pri,c,cause);
++ q931_disconnect(ctrl,c,cause);
+ else if (release_compl)
+- q931_release_complete(pri,c,cause);
++ q931_release_complete(ctrl,c,cause);
+ else
+- q931_release(pri,c,cause);
+- } else
+- pri_error(pri, "Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
++ q931_release(ctrl,c,cause);
++ break;
++ case Q931_CALL_STATE_NULL:
++ case Q931_CALL_STATE_DISCONNECT_REQUEST:
++ case Q931_CALL_STATE_DISCONNECT_INDICATION:
++ case Q931_CALL_STATE_RELEASE_REQUEST:
++ case Q931_CALL_STATE_RESTART_REQUEST:
++ case Q931_CALL_STATE_RESTART:
++ pri_error(ctrl,
++ "Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",
++ q931_call_state_str(c->ourcallstate),
++ q931_call_state_str(c->peercallstate));
++ break;
++ }
+ break;
+ case Q931_CALL_STATE_ACTIVE:
+ /* received CONNECT */
+- q931_disconnect(pri,c,cause);
++ if (c->cis_call) {
++ q931_release(ctrl, c, cause);
++ break;
++ }
++ q931_disconnect(ctrl,c,cause);
+ break;
+ case Q931_CALL_STATE_DISCONNECT_REQUEST:
+ /* sent DISCONNECT */
+- q931_release(pri,c,cause);
++ q931_release(ctrl,c,cause);
+ break;
+ case Q931_CALL_STATE_DISCONNECT_INDICATION:
+ /* received DISCONNECT */
+ if (c->peercallstate == Q931_CALL_STATE_DISCONNECT_REQUEST) {
+ c->alive = 1;
+- q931_release(pri,c,cause);
++ q931_release(ctrl,c,cause);
+ }
+ break;
+ case Q931_CALL_STATE_RELEASE_REQUEST:
+@@ -3253,75 +5413,129 @@
+ case Q931_CALL_STATE_RESTART:
+ case Q931_CALL_STATE_RESTART_REQUEST:
+ /* sent RESTART */
+- pri_error(pri, "q931_hangup shouldn't be called in this state, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
++ pri_error(ctrl,
++ "q931_hangup shouldn't be called in this state, ourstate %s, peerstate %s\n",
++ q931_call_state_str(c->ourcallstate),
++ q931_call_state_str(c->peercallstate));
+ break;
+ default:
+- pri_error(pri, "We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n",
+- c->ourcallstate,
+- callstate2str(c->ourcallstate),
+- callstate2str(c->peercallstate));
++ pri_error(ctrl,
++ "We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n",
++ c->ourcallstate,
++ q931_call_state_str(c->ourcallstate),
++ q931_call_state_str(c->peercallstate));
+ return -1;
+ }
+ /* we did handle hangup properly at this point */
+ return 0;
+ }
+
+-int q931_receive(struct pri *pri, q931_h *h, int len)
++static void initiate_hangup_if_needed(struct pri *pri, q931_call *call, int cause);
++
++int q931_hangup(struct pri *ctrl, q931_call *call, int cause)
+ {
+- q931_mh *mh;
+- q931_call *c;
+- q931_ie *ie;
+- unsigned int x;
+- int y;
+- int res;
+- int r;
+- int mandies[MAX_MAND_IES];
+- int missingmand;
+- int codeset, cur_codeset;
+- int last_ie[8];
+- struct apdu_event *cur = NULL;
++ int i;
+
+- memset(last_ie, 0, sizeof(last_ie));
+- if (pri->debug & PRI_DEBUG_Q931_DUMP)
+- q931_dump(pri, h, len, 0);
+-#ifdef LIBPRI_COUNTERS
+- pri->q931_rxcount++;
+-#endif
+- mh = (q931_mh *)(h->contents + h->crlen);
+- if ((h->pd == 0x3) || (h->pd == 0x43)) {
+- /* This is the weird maintenance stuff. We majorly
+- KLUDGE this by changing byte 4 from a 0xf (SERVICE)
+- to a 0x7 (SERVICE ACKNOWLEDGE) */
+- h->raw[h->crlen + 2] -= 0x8;
+- q931_xmit(pri, h, len, 1);
+- return 0;
+- } else if (h->pd != pri->protodisc) {
+- pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
+- return 0;
++ if (call->master_call->outboundbroadcast) {
++ if (call->master_call == call) {
++ int slaves = 0;
++
++ /* Master is called with hangup - initiate hangup with slaves */
++ for (i = 0; i < Q931_MAX_TEI; i++) {
++ if (call->subcalls[i]) {
++ slaves++;
++ if (i == call->master_call->pri_winner) {
++ __q931_hangup(call->subcalls[i]->pri, call->subcalls[i], cause);
++ } else {
++ initiate_hangup_if_needed(call->subcalls[i]->pri, call->subcalls[i], cause);
++ }
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "%s: Hanging up %d, winner %d\n", __FUNCTION__,
++ i, call->master_call->pri_winner);
++ }
++ }
++ }
++
++ call->hangupinitiated = 1;
++
++ if ((!slaves && (call->master_call->pri_winner < 0)) || (call->performing_fake_clearing)) {
++ __q931_hangup(ctrl, call, cause);
++ }
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "%s: Slaves %d\n", __FUNCTION__, slaves);
++ }
++ return 0;
++ } else {
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "%s: Slave hangup\n", __FUNCTION__);
++ }
++ return __q931_hangup(ctrl, call, cause);
++ }
++ } else {
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "%s: other hangup\n", __FUNCTION__);
++ }
++ return __q931_hangup(ctrl, call, cause);
+ }
+- c = q931_getcall(pri, q931_cr(h), 0);
+- if (!c) {
+- pri_error(pri, "Unable to locate call %d\n", q931_cr(h));
++ return 0;
++}
++
++static int prepare_to_handle_maintenance_message(struct pri *ctrl, q931_mh *mh, q931_call *c)
++{
++ if ((!ctrl) || (!mh) || (!c)) {
+ return -1;
+ }
+- /* Preliminary handling */
++ /* SERVICE messages are a superset of messages that can take b-channels
++ * or entire d-channels in and out of service */
+ switch(mh->msg) {
++ /* the ATT_SERVICE/ATT_SERVICE_ACKNOWLEDGE and NATIONAL_SERVICE/NATIONAL_SERVICE_ACKNOWLEDGE
++ * are mirrors of each other. We only have to check for one type because they are pre-handled
++ * the same way as each other */
++ case ATT_SERVICE:
++ case ATT_SERVICE_ACKNOWLEDGE:
++ c->channelno = -1;
++ c->slotmap = -1;
++ c->chanflags = 0;
++ c->ds1explicit = 0;
++ c->ds1no = 0;
++ c->cis_call = 0;
++ c->ri = -1;
++ c->changestatus = -1;
++ break;
++ default:
++ pri_error(ctrl, "!! Don't know how to pre-handle maintenance message type '%d'\n", mh->msg);
++ return -1;
++ }
++ return 0;
++}
++
++static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_call *c)
++{
++ if ((!ctrl) || (!mh) || (!c)) {
++ return -1;
++ }
++
++ switch(mh->msg) {
+ case Q931_RESTART:
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "-- Processing Q.931 Restart\n");
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, "-- Processing Q.931 Restart\n");
+ /* Reset information */
+ c->channelno = -1;
+ c->slotmap = -1;
+ c->chanflags = 0;
+ c->ds1no = 0;
++ c->ds1explicit = 0;
++ c->cis_call = 0;
+ c->ri = -1;
+ break;
+ case Q931_FACILITY:
+- c->callername[0] = '\0';
++ if (q931_is_dummy_call(c)) {
++ q931_party_address_init(&c->called);
++ }
+ break;
+ case Q931_SETUP:
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, "-- Processing Q.931 Call Setup\n");
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, "-- Processing Q.931 Call Setup\n");
+ c->channelno = -1;
+ c->slotmap = -1;
+ c->chanflags = 0;
+@@ -3334,29 +5548,25 @@
+ c->userl2 = -1;
+ c->userl3 = -1;
+ c->rateadaption = -1;
+- c->calledplan = -1;
+- c->callerplan = -1;
+- c->callerpres = -1;
+- c->callernum[0] = '\0';
+- c->callednum[0] = '\0';
+- c->callername[0] = '\0';
+- c->callerani[0] = '\0';
+- c->callerplanani = -1;
+- c->redirectingplan = -1;
+- c->redirectingpres = -1;
+- c->redirectingreason = -1;
+- c->origcalledplan = -1;
+- c->origcalledpres = -1;
+- c->origredirectingreason = -1;
+- c->redirectingnum[0] = '\0';
+- c->origcallednum[0] = '\0';
+- c->redirectingname[0] = '\0';
+- c->origcalledname[0] = '\0';
++
++ q931_party_address_init(&c->called);
++ q931_party_id_init(&c->local_id);
++ q931_party_id_init(&c->remote_id);
++ q931_party_redirecting_init(&c->redirecting);
++
++ /*
++ * Make sure that keypad and overlap digit buffers are empty in
++ * case they are not in the message.
++ */
++ c->keypad_digits[0] = '\0';
++ c->overlap_digits[0] = '\0';
++
+ c->useruserprotocoldisc = -1;
+ c->useruserinfo[0] = '\0';
+ c->complete = 0;
+ c->nonisdn = 0;
+ c->aoc_units = -1;
++ c->reversecharge = -1;
+ /* Fall through */
+ case Q931_CONNECT:
+ case Q931_ALERTING:
+@@ -3369,8 +5579,7 @@
+ c->progressmask = 0;
+ break;
+ case Q931_CONNECT_ACKNOWLEDGE:
+- if (c->retranstimer)
+- pri_schedule_del(pri, c->retranstimer);
++ pri_schedule_del(ctrl, c->retranstimer);
+ c->retranstimer = 0;
+ break;
+ case Q931_RELEASE:
+@@ -3379,14 +5588,12 @@
+ c->causecode = -1;
+ c->causeloc = -1;
+ c->aoc_units = -1;
+- if (c->retranstimer)
+- pri_schedule_del(pri, c->retranstimer);
++ pri_schedule_del(ctrl, c->retranstimer);
+ c->retranstimer = 0;
+ c->useruserinfo[0] = '\0';
+ break;
+ case Q931_RELEASE_COMPLETE:
+- if (c->retranstimer)
+- pri_schedule_del(pri, c->retranstimer);
++ pri_schedule_del(ctrl, c->retranstimer);
+ c->retranstimer = 0;
+ c->useruserinfo[0] = '\0';
+ /* Fall through */
+@@ -3394,45 +5601,252 @@
+ c->cause = -1;
+ c->causecode = -1;
+ c->causeloc = -1;
+- c->sugcallstate = -1;
++ c->sugcallstate = Q931_CALL_STATE_NOT_SET;
+ c->aoc_units = -1;
+ break;
+ case Q931_RESTART_ACKNOWLEDGE:
+ c->channelno = -1;
++ c->ds1no = 0;
++ c->ds1explicit = 0;
++ c->cis_call = 0;
+ break;
+ case Q931_INFORMATION:
+- c->callednum[0] = '\0';
++ /*
++ * Make sure that keypad and overlap digit buffers are empty in
++ * case they are not in the message.
++ */
++ c->keypad_digits[0] = '\0';
++ c->overlap_digits[0] = '\0';
+ break;
+ case Q931_STATUS_ENQUIRY:
+ break;
+ case Q931_SETUP_ACKNOWLEDGE:
+ break;
+ case Q931_NOTIFY:
++ q931_party_number_init(&c->redirection_number);
+ break;
+- case Q931_USER_INFORMATION:
+- case Q931_SEGMENT:
+- case Q931_CONGESTION_CONTROL:
+ case Q931_HOLD:
++ break;
+ case Q931_HOLD_ACKNOWLEDGE:
++ break;
+ case Q931_HOLD_REJECT:
++ c->cause = -1;
++ break;
+ case Q931_RETRIEVE:
++ c->channelno = 0xFF;
++ c->ds1no = 0;
++ c->ds1explicit = 0;
++ break;
+ case Q931_RETRIEVE_ACKNOWLEDGE:
++ break;
+ case Q931_RETRIEVE_REJECT:
++ c->cause = -1;
++ break;
++ case Q931_USER_INFORMATION:
++ case Q931_SEGMENT:
++ case Q931_CONGESTION_CONTROL:
+ case Q931_RESUME:
+ case Q931_RESUME_ACKNOWLEDGE:
+ case Q931_RESUME_REJECT:
+ case Q931_SUSPEND:
+ case Q931_SUSPEND_ACKNOWLEDGE:
+ case Q931_SUSPEND_REJECT:
+- pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
++ pri_error(ctrl, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
+ /* Fall through */
+ default:
+- pri_error(pri, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
+- q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
++ pri_error(ctrl, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
++ q931_status(ctrl,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
+ if (c->newcall)
+- q931_destroycall(pri,c->cr);
++ pri_destroycall(ctrl, c);
+ return -1;
+ }
++ return 0;
++}
++
++static struct q931_call *q931_get_subcall_winner(struct q931_call *master)
++{
++ if (master->pri_winner < 0) {
++ return NULL;
++ } else {
++ return master->subcalls[master->pri_winner];
++ }
++}
++
++static void initiate_hangup_if_needed(struct pri *pri, q931_call *call, int cause)
++{
++ if (!call->hangupinitiated) {
++ q931_hangup(pri, call, cause);
++ call->alive = 0;
++ }
++}
++
++#if 0
++static int q931_get_subcall_count(struct q931_call *call)
++{
++ int count = 0;
++ int i;
++
++ call = call->master_call;
++ for (i = 0; i < Q931_MAX_TEI; i++) {
++ if (call->subcalls[i])
++ count++;
++ }
++
++ return count;
++}
++#endif
++
++static void q931_set_subcall_winner(struct q931_call *subcall)
++{
++ struct q931_call *realcall = subcall->master_call;
++ int i;
++
++ /* Set the winner first */
++ for (i = 0; i < Q931_MAX_TEI; i++) {
++ if (realcall->subcalls[i] && realcall->subcalls[i] == subcall) {
++ realcall->pri_winner = i;
++ }
++ }
++ if (realcall->pri_winner < 0) {
++ pri_error(subcall->pri, "We should always find the winner in the list!\n");
++ return;
++ }
++
++ /* Start tear down of calls that were not chosen */
++ for (i = 0; i < Q931_MAX_TEI; i++) {
++ if (realcall->subcalls[i] && realcall->subcalls[i] != subcall) {
++ initiate_hangup_if_needed(realcall->subcalls[i]->pri, realcall->subcalls[i],
++ PRI_CAUSE_NONSELECTED_USER_CLEARING);
++ }
++ }
++}
++
++static struct q931_call *q931_get_subcall(struct pri *ctrl, struct q931_call *master_call)
++{
++ int i;
++ struct q931_call *cur;
++ int firstfree = -1;
++
++ /* First try to locate our subcall */
++ for (i = 0; i < Q931_MAX_TEI; i++) {
++ if (master_call->subcalls[i]) {
++ if (master_call->subcalls[i]->pri == ctrl) {
++ return master_call->subcalls[i];
++ }
++ } else if (firstfree == -1) {
++ firstfree = i;
++ }
++ }
++ if (firstfree < 0) {
++ pri_error(ctrl, "Tried to add more than %d TEIs to call and failed\n",
++ Q931_MAX_TEI);
++ return NULL;
++ }
++
++ /* Create new subcall. */
++ cur = malloc(sizeof(*cur));
++ if (!cur) {
++ pri_error(ctrl, "Unable to allocate call\n");
++ return NULL;
++ }
++ *cur = *master_call;
++ cur->pri = ctrl;
++ cur->next = NULL;
++ cur->apdus = NULL;
++ cur->bridged_call = NULL;
++ //cur->master_call = master_call; /* We get this assignment for free. */
++ for (i = 0; i < Q931_MAX_TEI; ++i) {
++ cur->subcalls[i] = NULL;
++ }
++ cur->t303_timer = 0;/* T303 should only be on on the master call */
++ cur->hold_timer = 0;
++ cur->retranstimer = 0;
++
++ /* Assume we sent a SETUP and this is the first response to it from this peer. */
++ cur->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
++ cur->peercallstate = Q931_CALL_STATE_CALL_PRESENT;
++
++ master_call->subcalls[firstfree] = cur;
++
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "Adding subcall %p for TEI %d to call %p at position %d\n",
++ cur, ctrl->tei, master_call, firstfree);
++ }
++ /* Should only get here if the TEI is not found */
++ return cur;
++}
++
++int q931_receive(struct pri *ctrl, q931_h *h, int len)
++{
++ q931_mh *mh;
++ q931_call *c;
++ q931_ie *ie;
++ unsigned int x;
++ int y;
++ int res;
++ int r;
++ int mandies[MAX_MAND_IES];
++ int missingmand;
++ int codeset, cur_codeset;
++ int last_ie[8];
++ int cref;
++
++ memset(last_ie, 0, sizeof(last_ie));
++ if (ctrl->debug & PRI_DEBUG_Q931_DUMP)
++ q931_dump(ctrl, h, len, 0);
++#ifdef LIBPRI_COUNTERS
++ ctrl->q931_rxcount++;
++#endif
++ mh = (q931_mh *)(h->contents + h->crlen);
++ if ((h->pd != ctrl->protodisc) && (h->pd != MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) && (h->pd != MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
++ pri_error(ctrl, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
++ return 0;
++ }
++ if (((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) && (!ctrl->service_message_support)) {
++ /* Real service message support has not been enabled (and is OFF in libpri by default),
++ * so we have to revert to the 'traditional' KLUDGE of changing byte 4 from a 0xf (SERVICE)
++ * to a 0x7 (SERVICE ACKNOWLEDGE) */
++ /* This is the weird maintenance stuff. We majorly
++ KLUDGE this by changing byte 4 from a 0xf (SERVICE)
++ to a 0x7 (SERVICE ACKNOWLEDGE) */
++ h->raw[h->crlen + 2] -= 0x8;
++ q931_xmit(ctrl, h, len, 1, 0);
++ return 0;
++ }
++
++ cref = q931_cr(h);
++ c = q931_getcall(ctrl, cref);
++ if (!c) {
++ pri_error(ctrl, "Unable to locate call %d\n", cref);
++ return -1;
++ }
++ if (c->master_call->outboundbroadcast && ctrl != PRI_MASTER(ctrl)) {
++ c = q931_get_subcall(ctrl, c->master_call);
++ if (!c) {
++ pri_error(ctrl, "Unable to locate subcall for %d\n", cref);
++ return -1;
++ }
++ }
++
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl,
++ "Received message for call %p on %p TEI/SAPI %d/%d, call->pri is %p TEI/SAPI %d/%d\n",
++ c,
++ ctrl, ctrl->tei, ctrl->sapi,
++ c->pri, c->pri->tei, c->pri->sapi);
++ }
++
++ /* Preliminary handling */
++ ctrl->facility.count = 0;
++ c->connected_number_in_message = 0;
++ c->redirecting_number_in_message = 0;
++ if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
++ prepare_to_handle_maintenance_message(ctrl, mh, c);
++ } else {
++ prepare_to_handle_q931_message(ctrl, mh, c);
++ }
++ q931_clr_subcommands(ctrl);
++
+ /* Handle IEs */
+ memset(mandies, 0, sizeof(mandies));
+ missingmand = 0;
+@@ -3453,7 +5867,7 @@
+ }
+ r = ielen(ie);
+ if (r > len) {
+- pri_error(pri, "XXX Message longer than it should be?? XXX\n");
++ pri_error(ctrl, "XXX Message longer than it should be?? XXX\n");
+ return -1;
+ }
+ /* Special processing for codeset shifts */
+@@ -3461,16 +5875,16 @@
+ case Q931_LOCKING_SHIFT:
+ y = ie->ie & 7; /* Requested codeset */
+ /* Locking shifts couldn't go to lower codeset, and couldn't follows non-locking shifts - verify this */
+- if ((cur_codeset != codeset) && (pri->debug & PRI_DEBUG_Q931_ANOMALY))
+- pri_message(pri, "XXX Locking shift immediately follows non-locking shift (from %d through %d to %d) XXX\n", codeset, cur_codeset, y);
++ if ((cur_codeset != codeset) && (ctrl->debug & PRI_DEBUG_Q931_ANOMALY))
++ pri_message(ctrl, "XXX Locking shift immediately follows non-locking shift (from %d through %d to %d) XXX\n", codeset, cur_codeset, y);
+ if (y > 0) {
+- if ((y < codeset) && (pri->debug & PRI_DEBUG_Q931_ANOMALY))
+- pri_error(pri, "!! Trying to locked downshift codeset from %d to %d !!\n", codeset, y);
++ if ((y < codeset) && (ctrl->debug & PRI_DEBUG_Q931_ANOMALY))
++ pri_error(ctrl, "!! Trying to locked downshift codeset from %d to %d !!\n", codeset, y);
+ codeset = cur_codeset = y;
+ }
+ else {
+ /* Locking shift to codeset 0 is forbidden by all specifications */
+- pri_error(pri, "!! Invalid locking shift to codeset 0 !!\n");
++ pri_error(ctrl, "!! Invalid locking shift to codeset 0 !!\n");
+ }
+ break;
+ case Q931_NON_LOCKING_SHIFT:
+@@ -3480,24 +5894,24 @@
+ /* Sanity check for IE code order */
+ if (!(ie->ie & 0x80)) {
+ if (last_ie[cur_codeset] > ie->ie) {
+- if ((pri->debug & PRI_DEBUG_Q931_ANOMALY))
+- pri_message(pri, "XXX Out-of-order IE %d at codeset %d (last was %d)\n", ie->ie, cur_codeset, last_ie[cur_codeset]);
++ if ((ctrl->debug & PRI_DEBUG_Q931_ANOMALY))
++ pri_message(ctrl, "XXX Out-of-order IE %d at codeset %d (last was %d)\n", ie->ie, cur_codeset, last_ie[cur_codeset]);
+ }
+ else
+ last_ie[cur_codeset] = ie->ie;
+ }
+ /* Ignore non-locking shifts for TR41459-based signalling */
+- switch (pri->switchtype) {
++ switch (ctrl->switchtype) {
+ case PRI_SWITCH_LUCENT5E:
+ case PRI_SWITCH_ATT4ESS:
+ if (cur_codeset != codeset) {
+- if ((pri->debug & PRI_DEBUG_Q931_DUMP))
+- pri_message(pri, "XXX Ignoring IE %d for temporary codeset %d XXX\n", ie->ie, cur_codeset);
++ if ((ctrl->debug & PRI_DEBUG_Q931_DUMP))
++ pri_message(ctrl, "XXX Ignoring IE %d for temporary codeset %d XXX\n", ie->ie, cur_codeset);
+ break;
+ }
+ /* Fall through */
+ default:
+- y = q931_handle_ie(cur_codeset, pri, c, mh->msg, ie);
++ y = q931_handle_ie(cur_codeset, ctrl, c, mh->msg, ie);
+ /* XXX Applicable to codeset 0 only? XXX */
+ if (!cur_codeset && !(ie->ie & 0xf0) && (y < 0))
+ mandies[MAX_MAND_IES - 1] = Q931_FULL_IE(cur_codeset, ie->ie);
+@@ -3512,33 +5926,562 @@
+ for (x=0;x<MAX_MAND_IES;x++) {
+ if (mandies[x]) {
+ /* check if there is no channel identification when we're configured as network -> that's not an error */
+- if (((pri->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) &&
++ if (((ctrl->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) &&
+ ((mh->msg != Q931_PROGRESS) || (mandies[x] != Q931_PROGRESS_INDICATOR))) {
+- pri_error(pri, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
++ pri_error(ctrl, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
+ missingmand++;
+ }
+ }
+ }
+-
++
++ /* Now handle the facility ie's after all the other ie's were processed. */
++ q931_handle_facilities(ctrl, c, mh->msg);
++
+ /* Post handling */
++ if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) {
++ res = post_handle_maintenance_message(ctrl, h->pd, mh, c);
++ } else {
++ int allow_event = 1, allow_posthandle = 1;
++
++ if (c->master_call->outboundbroadcast) {
++ nt_ptmp_handle_q931_message(ctrl, mh, c, &allow_event, &allow_posthandle);
++ }
++
++ if (allow_posthandle) {
++ res = post_handle_q931_message(ctrl, mh, c, missingmand);
++
++ if (res == Q931_RES_HAVEEVENT && !allow_event) {
++ res = 0;
++ }
++ } else {
++ res = 0;
++ }
++ }
++ return res;
++}
++
++static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, struct q931_mh *mh, struct q931_call *c)
++{
++ /* Do some maintenance stuff */
++ if (((protodisc == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) && (mh->msg == ATT_SERVICE))
++ || ((protodisc == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2) && (mh->msg == NATIONAL_SERVICE))) {
++ if (c->channelno > 0) {
++ ctrl->ev.e = PRI_EVENT_SERVICE;
++ ctrl->ev.service.channel = q931_encode_channel(c);
++ ctrl->ev.service.changestatus = 0x0f & c->changestatus;
++ } else {
++ switch (0x0f & c->changestatus) {
++ case SERVICE_CHANGE_STATUS_INSERVICE:
++ ctrl->ev.e = PRI_EVENT_DCHAN_UP;
++ q921_dchannel_up(ctrl);
++ break;
++ case SERVICE_CHANGE_STATUS_OUTOFSERVICE:
++ ctrl->ev.e = PRI_EVENT_DCHAN_DOWN;
++ q921_dchannel_down(ctrl);
++ break;
++ default:
++ pri_error(ctrl, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus));
++ return -1;
++ }
++ }
++ maintenance_service_ack(ctrl, c);
++ return Q931_RES_HAVEEVENT;
++ }
++ if (((protodisc == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) && (mh->msg == ATT_SERVICE_ACKNOWLEDGE))
++ || ((protodisc == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2) && (mh->msg == NATIONAL_SERVICE_ACKNOWLEDGE))) {
++ if (c->channelno > 0) {
++ ctrl->ev.e = PRI_EVENT_SERVICE_ACK;
++ ctrl->ev.service_ack.channel = q931_encode_channel(c);
++ ctrl->ev.service_ack.changestatus = 0x0f & c->changestatus;
++ } else {
++ switch (0x0f & c->changestatus) {
++ case SERVICE_CHANGE_STATUS_INSERVICE:
++ ctrl->ev.e = PRI_EVENT_DCHAN_UP;
++ q921_dchannel_up(ctrl);
++ break;
++ case SERVICE_CHANGE_STATUS_OUTOFSERVICE:
++ ctrl->ev.e = PRI_EVENT_DCHAN_DOWN;
++ q921_dchannel_down(ctrl);
++ break;
++ default:
++ pri_error(ctrl, "!! Don't know how to handle span service change status '%d'\n", (0x0f & c->changestatus));
++ return -1;
++ }
++ }
++ return Q931_RES_HAVEEVENT;
++ }
++
++ pri_error(ctrl, "!! Don't know how to post-handle maintenance message type %d\n", mh->msg);
++ return -1;
++}
++
++/*!
++ * \internal
++ * \brief Rank the given Q.931 call state for call etablishment.
++ *
++ * \param state Q.931 call state to rank for competing PTMP NT calls.
++ *
++ * \return Call establishment state ranking.
++ */
++static enum Q931_RANKED_CALL_STATE q931_rank_state(enum Q931_CALL_STATE state)
++{
++ enum Q931_RANKED_CALL_STATE rank;
++
++ switch (state) {
++ case Q931_CALL_STATE_CALL_INITIATED:
++ case Q931_CALL_STATE_CALL_PRESENT:
++ rank = Q931_RANKED_CALL_STATE_PRESENT;
++ break;
++ case Q931_CALL_STATE_OVERLAP_SENDING:
++ case Q931_CALL_STATE_OVERLAP_RECEIVING:
++ rank = Q931_RANKED_CALL_STATE_OVERLAP;
++ break;
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ rank = Q931_RANKED_CALL_STATE_PROCEEDING;
++ break;
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ rank = Q931_RANKED_CALL_STATE_ALERTING;
++ break;
++ case Q931_CALL_STATE_ACTIVE:
++ case Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE:
++ rank = Q931_RANKED_CALL_STATE_CONNECT;
++ break;
++ default:
++ rank = Q931_RANKED_CALL_STATE_OTHER;
++ break;
++ }
++
++ return rank;
++}
++
++/*!
++ * \brief Determine if the master will pass an event to the upper layer.
++ *
++ * \param ctrl D channel controller.
++ * \param subcall Q.931 call leg.
++ * \param msg_type Current message type being processed.
++ *
++ * \note This function must parallel nt_ptmp_handle_q931_message().
++ *
++ * \retval TRUE if the master will pass an event to the upper layer.
++ * \retval FALSE if the event will be blocked.
++ */
++int q931_master_pass_event(struct pri *ctrl, struct q931_call *subcall, int msg_type)
++{
++ struct q931_call *winner;
++ struct q931_call *master;
++ enum Q931_RANKED_CALL_STATE master_rank;
++ enum Q931_RANKED_CALL_STATE subcall_rank;
++ int will_pass; /*!< TRUE if the master will pass an event to the upper layer. */
++
++ master = subcall->master_call;
++ if (subcall == master) {
++ /* We are the master call so of course the master will pass an event. */
++ return 1;
++ }
++
++ winner = q931_get_subcall_winner(master);
++ if (winner && subcall == winner) {
++ /* We are the winner so of course the master will pass an event. */
++ return 1;
++ }
++
++ master_rank = q931_rank_state(master->ourcallstate);
++ will_pass = 0;
++ switch (msg_type) {
++ case Q931_SETUP_ACKNOWLEDGE:
++#if 0 /* Overlap dialing in PTMP NT mode not supported at the present time. */
++ if (master_rank < Q931_RANKED_CALL_STATE_OVERLAP) {
++ will_pass = 1;
++ }
++#endif /* Overlap dialing in PTMP NT mode not supported at the present time. */
++ break;
++ case Q931_CALL_PROCEEDING:
++ if (master_rank < Q931_RANKED_CALL_STATE_PROCEEDING) {
++ will_pass = 1;
++ }
++ break;
++ case Q931_PROGRESS:
++ /*
++ * We will just ignore this message since there could be multiple devices
++ * competing for this call. Who has access to the B channel at this time
++ * to give in-band signals anyway?
++ */
++ break;
++ case Q931_ALERTING:
++ if (master_rank < Q931_RANKED_CALL_STATE_ALERTING) {
++ will_pass = 1;
++ }
++ break;
++ case Q931_CONNECT:
++ if (master_rank < Q931_RANKED_CALL_STATE_CONNECT) {
++ /* We are expected to be the winner for the next message. */
++ will_pass = 1;
++ }
++ break;
++ case Q931_DISCONNECT:
++ case Q931_RELEASE:
++ case Q931_RELEASE_COMPLETE:
++ /* Only deal with the winner. */
++ break;
++ case Q931_FACILITY:
++ case Q931_NOTIFY:
++ if (!winner) {
++ /* The overlap rank does not count here. */
++ if (master_rank == Q931_RANKED_CALL_STATE_OVERLAP) {
++ master_rank = Q931_RANKED_CALL_STATE_PRESENT;
++ }
++ subcall_rank = q931_rank_state(subcall->ourcallstate);
++ if (subcall_rank == Q931_RANKED_CALL_STATE_OVERLAP) {
++ subcall_rank = Q931_RANKED_CALL_STATE_PRESENT;
++ }
++ if (master_rank == subcall_rank) {
++ /*
++ * No winner yet but the subcall is as advanced as the master.
++ * Allow the supplementary service event to pass.
++ */
++ will_pass = 1;
++ }
++ }
++ break;
++ default:
++ /* Only deal with the winner. */
++ break;
++ }
++
++ return will_pass;
++}
++
++/*!
++ * \internal
++ * \brief Handle outboundbroadcast incoming messages for the master_call's state.
++ *
++ * \param ctrl D channel controller.
++ * \param mh Q.931 message type header.
++ * \param subcall Q.931 call leg.
++ * \param allow_event Where to set the allow event to upper layer flag.
++ * \param allow_posthandle Where to set the allow post handle event flag.
++ *
++ * \details
++ * This is where we interact the subcalls state with the master_call's state.
++ *
++ * \note This function must parallel q931_master_pass_event().
++ *
++ * \return Nothing
++ */
++static void nt_ptmp_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *subcall, int *allow_event, int *allow_posthandle)
++{
++ struct q931_call *master = subcall->master_call;
++ struct q931_call *winner = q931_get_subcall_winner(master);
++ enum Q931_RANKED_CALL_STATE master_rank;
++ enum Q931_RANKED_CALL_STATE subcall_rank;
++ enum Q931_CALL_STATE newstate;
++
++ /* For broadcast calls, we default to not allowing events to keep events received to a minimum
++ * and to allow post processing, since that is where hangup and subcall state handling and other processing is done */
++ *allow_event = 0;
++ *allow_posthandle = 1;
++
++ master_rank = q931_rank_state(master->ourcallstate);
++
++ switch (mh->msg) {
++ case Q931_SETUP_ACKNOWLEDGE:
++#if 0 /* Overlap dialing in PTMP NT mode not supported at the present time. */
++ if (master_rank < Q931_RANKED_CALL_STATE_OVERLAP) {
++ *allow_event = 1;
++ UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_OVERLAP_SENDING);
++ }
++#endif /* Overlap dialing in PTMP NT mode not supported at the present time. */
++ break;
++ case Q931_CALL_PROCEEDING:
++ if (master_rank < Q931_RANKED_CALL_STATE_PROCEEDING) {
++ *allow_event = 1;
++ UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
++ }
++ break;
++ case Q931_PROGRESS:
++ /*
++ * We will just ignore this message since there could be multiple devices
++ * competing for this call. Who has access to the B channel at this time
++ * to give in-band signals anyway?
++ */
++ break;
++ case Q931_ALERTING:
++ if (master_rank < Q931_RANKED_CALL_STATE_ALERTING) {
++ *allow_event = 1;
++ UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_CALL_DELIVERED);
++ }
++ break;
++ case Q931_CONNECT:
++ if (master_rank < Q931_RANKED_CALL_STATE_CONNECT) {
++ UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_ACTIVE);
++ q931_set_subcall_winner(subcall);
++ *allow_event = 1;
++ } else {
++ /* Call clearing of non selected calls occurs in
++ * q931_set_subcall_winner() - All we need to do is make sure
++ * that this connect is not acknowledged */
++ *allow_posthandle = 0;
++ }
++ break;
++ case Q931_DISCONNECT:
++ newstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
++ goto process_hangup;
++ case Q931_RELEASE:
++ case Q931_RELEASE_COMPLETE:
++ newstate = Q931_CALL_STATE_NULL;
++process_hangup:
++ if (!winner) {
++ /* If there's not a winner, we just take the cause and pass it up to the
++ * master_call */
++ master->cause = subcall->cause;
++ } else {
++ /* There *is* a winner */
++ if (subcall == winner) {
++ /* .. and we're it: */
++ *allow_event = 1;
++ UPDATE_OURCALLSTATE(ctrl, master, newstate);
++ }
++ }
++ break;
++ case Q931_FACILITY:
++ case Q931_NOTIFY:
++ if (winner) {
++ if (subcall == winner) {
++ /* Only deal with the winner. */
++ *allow_event = 1;
++ }
++ } else {
++ /* The overlap rank does not count here. */
++ if (master_rank == Q931_RANKED_CALL_STATE_OVERLAP) {
++ master_rank = Q931_RANKED_CALL_STATE_PRESENT;
++ }
++ subcall_rank = q931_rank_state(subcall->ourcallstate);
++ if (subcall_rank == Q931_RANKED_CALL_STATE_OVERLAP) {
++ subcall_rank = Q931_RANKED_CALL_STATE_PRESENT;
++ }
++ if (master_rank == subcall_rank) {
++ /*
++ * No winner yet but the subcall is as advanced as the master.
++ * Allow the supplementary service event to pass.
++ */
++ *allow_event = 1;
++ }
++ }
++ break;
++ default:
++ if (winner && subcall == winner) {
++ /* Only deal with the winner. */
++ *allow_event = 1;
++ }
++ break;
++ }
++}
++
++/*!
++ * \internal
++ * \brief Fill in the FACILITY event fields.
++ *
++ * \param ctrl D channel controller.
++ * \param call Q.931 call leg.
++ *
++ * \return Nothing
++ */
++static void q931_fill_facility_event(struct pri *ctrl, struct q931_call *call)
++{
++ ctrl->ev.e = PRI_EVENT_FACILITY;
++ ctrl->ev.facility.subcmds = &ctrl->subcmds;
++ ctrl->ev.facility.channel = q931_encode_channel(call);
++ ctrl->ev.facility.cref = call->cr;
++ ctrl->ev.facility.call = call->master_call;
++ ctrl->ev.facility.subcall = call;
++
++ /* Need to do this for backward compatibility with struct pri_event_facname */
++ libpri_copy_string(ctrl->ev.facility.callingname, call->remote_id.name.str,
++ sizeof(ctrl->ev.facility.callingname));
++ libpri_copy_string(ctrl->ev.facility.callingnum, call->remote_id.number.str,
++ sizeof(ctrl->ev.facility.callingnum));
++ ctrl->ev.facility.callingpres = q931_party_id_presentation(&call->remote_id);
++ ctrl->ev.facility.callingplan = call->remote_id.number.plan;
++}
++
++/*!
++ * \internal
++ * \brief APDU wait for response message timeout.
++ *
++ * \param data Callback data pointer.
++ *
++ * \return Nothing
++ */
++static void q931_apdu_timeout(void *data)
++{
++ struct apdu_event *apdu;
++ struct pri *ctrl;
++ struct q931_call *call;
++
++ apdu = data;
++ call = apdu->call;
++ ctrl = call->pri;
++
++ q931_clr_subcommands(ctrl);
++ apdu->response.callback(APDU_CALLBACK_REASON_TIMEOUT, ctrl, call, apdu, NULL);
++ if (ctrl->subcmds.counter_subcmd) {
++ q931_fill_facility_event(ctrl, call);
++ ctrl->schedev = 1;
++ }
++
++ pri_call_apdu_delete(call, apdu);
++}
++
++/*!
++ * \internal
++ * \brief Find the active call given the held call.
++ *
++ * \param ctrl D channel controller.
++ * \param held_call Held call to help locate a compatible active call.
++ *
++ * \retval master-active-call on success.
++ * \retval NULL on error.
++ */
++static struct q931_call *q931_find_held_active_call(struct pri *ctrl, struct q931_call *held_call)
++{
++ struct pri *master;
++ struct q931_call *cur;
++ struct q931_call *winner;
++ struct q931_call *match;
++
++ match = NULL;
++ master = PRI_MASTER(ctrl);
++ for (cur = *master->callpool; cur; cur = cur->next) {
++ if (cur->hold_state == Q931_HOLD_STATE_IDLE) {
++ /* Found an active call. */
++ winner = q931_find_winning_call(cur);
++ if (!winner || (BRI_NT_PTMP(ctrl) && winner->pri != held_call->pri)) {
++ /* There is no winner or the active call does not go to the same TEI. */
++ continue;
++ }
++ switch (winner->ourcallstate) {
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_ACTIVE:
++ break;
++ default:
++ /* Active call not in a good state to transfer. */
++ continue;
++ }
++ if (q931_party_number_cmp(&winner->remote_id.number,
++ &held_call->remote_id.number)) {
++ /* The remote party number does not match. This is a weak match. */
++ match = cur;
++ continue;
++ }
++ /* Found an exact match. */
++ match = cur;
++ break;
++ }
++ }
++
++ return match;
++}
++
++/*!
++ * \internal
++ * \brief Find the held call given the active call.
++ *
++ * \param ctrl D channel controller.
++ * \param active_call Active call to help locate a compatible held call.
++ *
++ * \retval master-held-call on success.
++ * \retval NULL on error.
++ */
++static struct q931_call *q931_find_held_call(struct pri *ctrl, struct q931_call *active_call)
++{
++ struct pri *master;
++ struct q931_call *cur;
++ struct q931_call *winner;
++ struct q931_call *match;
++
++ match = NULL;
++ master = PRI_MASTER(ctrl);
++ for (cur = *master->callpool; cur; cur = cur->next) {
++ if (cur->hold_state == Q931_HOLD_STATE_CALL_HELD) {
++ /* Found a held call. */
++ winner = q931_find_winning_call(cur);
++ if (!winner || (BRI_NT_PTMP(ctrl) && winner->pri != active_call->pri)) {
++ /* There is no winner or the held call does not go to the same TEI. */
++ continue;
++ }
++ switch (winner->ourcallstate) {
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_ACTIVE:
++ break;
++ default:
++ /* Held call not in a good state to transfer. */
++ continue;
++ }
++ if (q931_party_number_cmp(&winner->remote_id.number,
++ &active_call->remote_id.number)) {
++ /* The remote party number does not match. This is a weak match. */
++ match = cur;
++ continue;
++ }
++ /* Found an exact match. */
++ match = cur;
++ break;
++ }
++ }
++
++ return match;
++}
++
++/*!
++ * \internal
++ * \brief Process the decoded information in the Q.931 message.
++ *
++ * \param ctrl D channel controller.
++ * \param mh Q.931 message header.
++ * \param c Q.931 call leg.
++ * \param missingmand Number of missing mandatory ie's.
++ *
++ * \retval 0 if no error or event.
++ * \retval Q931_RES_HAVEEVENT if have an event.
++ * \retval -1 on error.
++ */
++static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand)
++{
++ int res;
++ struct apdu_event *cur = NULL;
++ struct pri_subcommand *subcmd;
++ struct q931_call *master_call;
++
+ switch(mh->msg) {
+ case Q931_RESTART:
+ if (missingmand) {
+- q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+- q931_destroycall(pri, c->cr);
++ q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
++ pri_destroycall(ctrl, c);
+ break;
+ }
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_RESTART);
+ c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
+ /* Send back the Restart Acknowledge */
+- restart_ack(pri, c);
++ restart_ack(ctrl, c);
+ /* Notify user of restart event */
+- pri->ev.e = PRI_EVENT_RESTART;
+- pri->ev.restart.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
++ ctrl->ev.e = PRI_EVENT_RESTART;
++ ctrl->ev.restart.channel = q931_encode_channel(c);
+ return Q931_RES_HAVEEVENT;
+ case Q931_SETUP:
+ if (missingmand) {
+- q931_release_complete(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
++ q931_release_complete(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+ break;
+ }
+ /* Must be new call */
+@@ -3548,185 +6491,279 @@
+ if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
+ c->nonisdn = 1;
+ c->newcall = 0;
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_PRESENT);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_PRESENT);
+ c->peercallstate = Q931_CALL_STATE_CALL_INITIATED;
+ /* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */
+ c->alive = 0;
+ if (c->transmoderate != TRANS_MODE_64_CIRCUIT) {
+- q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
++ q931_release_complete(ctrl, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
+ break;
+ }
+- pri->ev.e = PRI_EVENT_RING;
+- pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.ring.callingpres = c->callerpres;
+- pri->ev.ring.callingplan = c->callerplan;
+- pri->ev.ring.callingplanani = c->callerplanani;
+- pri->ev.ring.callingplanrdnis = c->redirectingplan;
+- pri->ev.ring.callingplanorigcalled = c->origcalledplan;
+- pri->ev.ring.ani2 = c->ani2;
+- libpri_copy_string(pri->ev.ring.callingani, c->callerani, sizeof(pri->ev.ring.callingani));
+- libpri_copy_string(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum));
+- libpri_copy_string(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname));
+- pri->ev.ring.calledplan = c->calledplan;
+- libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
+- libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
+- libpri_copy_string(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname));
+- libpri_copy_string(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum));
+- libpri_copy_string(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum));
+- libpri_copy_string(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname));
+- libpri_copy_string(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
++
++ if (c->redirecting.from.number.valid && !c->redirecting.count) {
++ /*
++ * This is most likely because the redirecting number came in
++ * with the redirecting ie only and not a DivertingLegInformation2.
++ */
++ c->redirecting.count = 1;
++ }
++ if (c->redirecting.state == Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3) {
++ /*
++ * Valid for Q.SIG and ETSI PRI/BRI-PTP modes:
++ * Setup the redirecting.to informtion so we can identify
++ * if the user wants to manually supply the COLR for this
++ * redirected to number if further redirects could happen.
++ *
++ * All the user needs to do is set the REDIRECTING(to-pres)
++ * to the COLR and REDIRECTING(to-num) = complete-dialed-number
++ * (i.e. CALLERID(dnid)) to be safe after determining that the
++ * incoming call was redirected by checking if the
++ * REDIRECTING(count) is nonzero.
++ */
++ c->redirecting.to.number = c->called.number;
++ c->redirecting.to.number.presentation =
++ PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
++ }
++
++ ctrl->ev.e = PRI_EVENT_RING;
++ ctrl->ev.ring.subcmds = &ctrl->subcmds;
++ ctrl->ev.ring.channel = q931_encode_channel(c);
++
++ /* Calling party information */
++ ctrl->ev.ring.callingpres = q931_party_id_presentation(&c->remote_id);
++ ctrl->ev.ring.callingplan = c->remote_id.number.plan;
++ if (c->remote_id.number.valid
++ && (c->remote_id.number.presentation == PRES_ALLOWED_NETWORK_NUMBER
++ || c->remote_id.number.presentation == PRES_PROHIB_NETWORK_NUMBER)) {
++ ctrl->ev.ring.callingplanani = c->remote_id.number.plan;
++ libpri_copy_string(ctrl->ev.ring.callingani, c->remote_id.number.str, sizeof(ctrl->ev.ring.callingani));
++ } else {
++ ctrl->ev.ring.callingplanani = -1;
++ ctrl->ev.ring.callingani[0] = '\0';
++ }
++ libpri_copy_string(ctrl->ev.ring.callingnum, c->remote_id.number.str, sizeof(ctrl->ev.ring.callingnum));
++ libpri_copy_string(ctrl->ev.ring.callingname, c->remote_id.name.str, sizeof(ctrl->ev.ring.callingname));
++ q931_party_id_copy_to_pri(&ctrl->ev.ring.calling, &c->remote_id);
++ /* for backwards compatibility, still need ctrl->ev.ring.callingsubaddr */
++ if (!c->remote_id.subaddress.type) { /* NSAP: Type = 0 */
++ libpri_copy_string(ctrl->ev.ring.callingsubaddr, (char *) c->remote_id.subaddress.data, sizeof(ctrl->ev.ring.callingsubaddr));
++ } else {
++ ctrl->ev.ring.callingsubaddr[0] = '\0';
++ }
++
++ ctrl->ev.ring.ani2 = c->ani2;
++
++ /* Called party information */
++ ctrl->ev.ring.calledplan = c->called.number.plan;
++ libpri_copy_string(ctrl->ev.ring.callednum, c->called.number.str, sizeof(ctrl->ev.ring.callednum));
++ q931_party_subaddress_copy_to_pri(&ctrl->ev.ring.called_subaddress, &c->called.subaddress);
++
++ /* Original called party information (For backward compatibility) */
++ libpri_copy_string(ctrl->ev.ring.origcalledname, c->redirecting.orig_called.name.str, sizeof(ctrl->ev.ring.origcalledname));
++ libpri_copy_string(ctrl->ev.ring.origcallednum, c->redirecting.orig_called.number.str, sizeof(ctrl->ev.ring.origcallednum));
++ ctrl->ev.ring.callingplanorigcalled = c->redirecting.orig_called.number.plan;
++ if (c->redirecting.orig_called.number.valid
++ || c->redirecting.orig_called.name.valid) {
++ ctrl->ev.ring.origredirectingreason = c->redirecting.orig_reason;
++ } else {
++ ctrl->ev.ring.origredirectingreason = -1;
++ }
++
++ /* Redirecting from party information (For backward compatibility) */
++ ctrl->ev.ring.callingplanrdnis = c->redirecting.from.number.plan;
++ libpri_copy_string(ctrl->ev.ring.redirectingnum, c->redirecting.from.number.str, sizeof(ctrl->ev.ring.redirectingnum));
++ libpri_copy_string(ctrl->ev.ring.redirectingname, c->redirecting.from.name.str, sizeof(ctrl->ev.ring.redirectingname));
++
++ ctrl->ev.ring.redirectingreason = c->redirecting.reason;
++
++ libpri_copy_string(ctrl->ev.ring.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.ring.useruserinfo));
+ c->useruserinfo[0] = '\0';
+- pri->ev.ring.redirectingreason = c->redirectingreason;
+- pri->ev.ring.origredirectingreason = c->origredirectingreason;
+- pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
+- pri->ev.ring.cref = c->cr;
+- pri->ev.ring.call = c;
+- pri->ev.ring.layer1 = c->userl1;
+- pri->ev.ring.complete = c->complete;
+- pri->ev.ring.ctype = c->transcapability;
+- pri->ev.ring.redirectingreason = c->redirectingreason;
+- pri->ev.ring.progress = c->progress;
+- pri->ev.ring.progressmask = c->progressmask;
++
++ libpri_copy_string(ctrl->ev.ring.keypad_digits, c->keypad_digits,
++ sizeof(ctrl->ev.ring.keypad_digits));
++
++ ctrl->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
++ ctrl->ev.ring.cref = c->cr;
++ ctrl->ev.ring.call = c->master_call;
++ ctrl->ev.ring.layer1 = c->userl1;
++ ctrl->ev.ring.complete = c->complete;
++ ctrl->ev.ring.ctype = c->transcapability;
++ ctrl->ev.ring.progress = c->progress;
++ ctrl->ev.ring.progressmask = c->progressmask;
++ ctrl->ev.ring.reversecharge = c->reversecharge;
++
++ if (c->redirecting.count) {
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (subcmd) {
++ /* Setup redirecting subcommand */
++ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
++ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
++ &c->redirecting);
++ }
++ }
++
+ return Q931_RES_HAVEEVENT;
+ case Q931_ALERTING:
++ stop_t303(c);
+ if (c->newcall) {
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+ break;
+ }
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_DELIVERED);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_DELIVERED);
+ c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
+- pri->ev.e = PRI_EVENT_RINGING;
+- pri->ev.ringing.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.ringing.cref = c->cr;
+- pri->ev.ringing.call = c;
+- pri->ev.ringing.progress = c->progress;
+- pri->ev.ringing.progressmask = c->progressmask;
+- libpri_copy_string(pri->ev.ringing.useruserinfo, c->useruserinfo, sizeof(pri->ev.ringing.useruserinfo));
++ ctrl->ev.e = PRI_EVENT_RINGING;
++ ctrl->ev.ringing.subcmds = &ctrl->subcmds;
++ ctrl->ev.ringing.channel = q931_encode_channel(c);
++ ctrl->ev.ringing.cref = c->cr;
++ ctrl->ev.ringing.call = c->master_call;
++ ctrl->ev.ringing.progress = c->progress;
++ ctrl->ev.ringing.progressmask = c->progressmask;
++
++ libpri_copy_string(ctrl->ev.ringing.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.ringing.useruserinfo));
+ c->useruserinfo[0] = '\0';
+
+- cur = c->apdus;
+- while (cur) {
++ for (cur = c->apdus; cur; cur = cur->next) {
+ if (!cur->sent && cur->message == Q931_FACILITY) {
+- q931_facility(pri, c);
++ q931_facility(ctrl, c);
+ break;
+ }
+- cur = cur->next;
+ }
+
+ return Q931_RES_HAVEEVENT;
+ case Q931_CONNECT:
++ stop_t303(c);
+ if (c->newcall) {
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+ break;
+ }
+ if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) {
+- q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
++ q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
+ break;
+ }
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
+ c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
+- pri->ev.e = PRI_EVENT_ANSWER;
+- pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.answer.cref = c->cr;
+- pri->ev.answer.call = c;
+- pri->ev.answer.progress = c->progress;
+- pri->ev.answer.progressmask = c->progressmask;
+- libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.answer.useruserinfo));
++
++ ctrl->ev.e = PRI_EVENT_ANSWER;
++ ctrl->ev.answer.subcmds = &ctrl->subcmds;
++ ctrl->ev.answer.channel = q931_encode_channel(c);
++ ctrl->ev.answer.cref = c->cr;
++ ctrl->ev.answer.call = c->master_call;
++ ctrl->ev.answer.progress = c->progress;
++ ctrl->ev.answer.progressmask = c->progressmask;
++ libpri_copy_string(ctrl->ev.answer.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.answer.useruserinfo));
+ c->useruserinfo[0] = '\0';
+- q931_connect_acknowledge(pri, c);
+- if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */
+- q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
++
++ q931_connect_acknowledge(ctrl, c);
++
++ if (c->cis_auto_disconnect && c->cis_call) {
++ /* Make sure WE release when we initiate a signalling only connection */
++ q931_hangup(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
+ break;
+- } else
++ } else {
++ c->incoming_ct_state = INCOMING_CT_STATE_IDLE;
++
++ /* Setup connected line subcommand */
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (subcmd) {
++ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
++ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &c->remote_id);
++ }
++
+ return Q931_RES_HAVEEVENT;
++ }
+ case Q931_FACILITY:
+ if (c->newcall) {
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+ break;
+ }
+- pri->ev.e = PRI_EVENT_FACNAME;
+- libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
+- libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum));
+- pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.facname.callingpres = c->callerpres;
+- pri->ev.facname.callingplan = c->callerplan;
+- pri->ev.facname.cref = c->cr;
+- pri->ev.facname.call = c;
+-#if 0
+- pri_message(pri, "Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
+-#endif
+- return Q931_RES_HAVEEVENT;
++ switch (c->incoming_ct_state) {
++ case INCOMING_CT_STATE_POST_CONNECTED_LINE:
++ c->incoming_ct_state = INCOMING_CT_STATE_IDLE;
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (subcmd) {
++ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
++ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &c->remote_id);
++ }
++ break;
++ default:
++ break;
++ }
++ if (ctrl->subcmds.counter_subcmd) {
++ q931_fill_facility_event(ctrl, c);
++ return Q931_RES_HAVEEVENT;
++ }
++ break;
+ case Q931_PROGRESS:
+ if (missingmand) {
+- q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+- q931_destroycall(pri, c->cr);
++ q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
++ pri_destroycall(ctrl, c);
+ break;
+ }
+- pri->ev.e = PRI_EVENT_PROGRESS;
+- pri->ev.proceeding.cause = c->cause;
++ ctrl->ev.e = PRI_EVENT_PROGRESS;
++ ctrl->ev.proceeding.cause = c->cause;
+ /* Fall through */
+ case Q931_CALL_PROCEEDING:
++ stop_t303(c);
++ ctrl->ev.proceeding.subcmds = &ctrl->subcmds;
+ if (c->newcall) {
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+ break;
+ }
+ if ((c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) &&
+ (c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) &&
+ (c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) &&
+ (c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) {
+- q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
++ q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
+ break;
+ }
+- pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
++ ctrl->ev.proceeding.channel = q931_encode_channel(c);
+ if (mh->msg == Q931_CALL_PROCEEDING) {
+- pri->ev.e = PRI_EVENT_PROCEEDING;
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
++ ctrl->ev.e = PRI_EVENT_PROCEEDING;
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
+ c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
+ }
+- pri->ev.proceeding.progress = c->progress;
+- pri->ev.proceeding.progressmask = c->progressmask;
+- pri->ev.proceeding.cref = c->cr;
+- pri->ev.proceeding.call = c;
++ ctrl->ev.proceeding.progress = c->progress;
++ ctrl->ev.proceeding.progressmask = c->progressmask;
++ ctrl->ev.proceeding.cref = c->cr;
++ ctrl->ev.proceeding.call = c->master_call;
+
+- cur = c->apdus;
+- while (cur) {
++ for (cur = c->apdus; cur; cur = cur->next) {
+ if (!cur->sent && cur->message == Q931_FACILITY) {
+- q931_facility(pri, c);
++ q931_facility(ctrl, c);
+ break;
+ }
+- cur = cur->next;
+ }
+ return Q931_RES_HAVEEVENT;
+ case Q931_CONNECT_ACKNOWLEDGE:
+ if (c->newcall) {
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+ break;
+ }
+ if (!(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) &&
+ !(c->ourcallstate == Q931_CALL_STATE_ACTIVE &&
+- (pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG))) {
+- q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
++ (ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG))) {
++ q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
+ break;
+ }
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
+ c->peercallstate = Q931_CALL_STATE_ACTIVE;
+ break;
+ case Q931_STATUS:
+ if (missingmand) {
+- q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+- q931_destroycall(pri, c->cr);
++ q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
++ pri_destroycall(ctrl, c);
+ break;
+ }
+ if (c->newcall) {
+ if (c->cr & 0x7fff)
+- q931_release_complete(pri,c,PRI_CAUSE_WRONG_CALL_STATE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_WRONG_CALL_STATE);
+ break;
+ }
+ /* Do nothing */
+ /* Also when the STATUS asks for the call of an unexisting reference send RELEASE_COMPL */
+- if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) &&
++ if ((ctrl->debug & PRI_DEBUG_Q931_ANOMALY) &&
+ (c->cause != PRI_CAUSE_INTERWORKING))
+- pri_error(pri, "Received unsolicited status: %s\n", pri_cause2str(c->cause));
++ pri_error(ctrl, "Received unsolicited status: %s\n", pri_cause2str(c->cause));
+ /* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */
+ #if 0
+ if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) {
+@@ -3737,25 +6774,28 @@
+
+ if (!c->sugcallstate) {
+ #endif
+- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.hangup.cause = c->cause;
+- pri->ev.hangup.cref = c->cr;
+- pri->ev.hangup.call = c;
+- pri->ev.hangup.aoc_units = c->aoc_units;
+- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
++ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
++ ctrl->ev.hangup.channel = q931_encode_channel(c);
++ ctrl->ev.hangup.cause = c->cause;
++ ctrl->ev.hangup.cref = c->cr;
++ ctrl->ev.hangup.call = c->master_call;
++ ctrl->ev.hangup.aoc_units = c->aoc_units;
++ ctrl->ev.hangup.call_held = NULL;
++ ctrl->ev.hangup.call_active = NULL;
++ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
+ /* Free resources */
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
+ c->peercallstate = Q931_CALL_STATE_NULL;
+ if (c->alive) {
+- pri->ev.e = PRI_EVENT_HANGUP;
++ ctrl->ev.e = PRI_EVENT_HANGUP;
+ res = Q931_RES_HAVEEVENT;
+ c->alive = 0;
+ } else if (c->sendhangupack) {
+ res = Q931_RES_HAVEEVENT;
+- pri->ev.e = PRI_EVENT_HANGUP_ACK;
+- q931_hangup(pri, c, c->cause);
++ ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
++ pri_hangup(ctrl, c, c->cause);
+ } else {
+- q931_hangup(pri, c, c->cause);
++ pri_hangup(ctrl, c, c->cause);
+ res = 0;
+ }
+ if (res)
+@@ -3763,32 +6803,38 @@
+ }
+ break;
+ case Q931_RELEASE_COMPLETE:
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
++ c->hangupinitiated = 1;
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
+ c->peercallstate = Q931_CALL_STATE_NULL;
+- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.hangup.cause = c->cause;
+- pri->ev.hangup.cref = c->cr;
+- pri->ev.hangup.call = c;
+- pri->ev.hangup.aoc_units = c->aoc_units;
+- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
++ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
++ ctrl->ev.hangup.channel = q931_encode_channel(c);
++ ctrl->ev.hangup.cause = c->cause;
++ ctrl->ev.hangup.cref = c->cr;
++ ctrl->ev.hangup.call = c->master_call;
++ ctrl->ev.hangup.aoc_units = c->aoc_units;
++ ctrl->ev.hangup.call_held = NULL;
++ ctrl->ev.hangup.call_active = NULL;
++ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
+ c->useruserinfo[0] = '\0';
+ /* Free resources */
+ if (c->alive) {
+- pri->ev.e = PRI_EVENT_HANGUP;
++ ctrl->ev.e = PRI_EVENT_HANGUP;
+ res = Q931_RES_HAVEEVENT;
+ c->alive = 0;
+ } else if (c->sendhangupack) {
+ res = Q931_RES_HAVEEVENT;
+- pri->ev.e = PRI_EVENT_HANGUP_ACK;
+- pri_hangup(pri, c, c->cause);
++ ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
++ pri_hangup(ctrl, c, c->cause);
+ } else
+ res = 0;
++
+ if (res)
+ return res;
+ else
+- q931_hangup(pri,c,c->cause);
++ pri_hangup(ctrl,c,c->cause);
+ break;
+ case Q931_RELEASE:
++ c->hangupinitiated = 1;
+ if (missingmand) {
+ /* Force cause to be mandatory IE missing */
+ c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
+@@ -3798,59 +6844,113 @@
+ else {
+ c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST;
+ }
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
+- pri->ev.e = PRI_EVENT_HANGUP;
+- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.hangup.cause = c->cause;
+- pri->ev.hangup.cref = c->cr;
+- pri->ev.hangup.call = c;
+- pri->ev.hangup.aoc_units = c->aoc_units;
+- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
++ ctrl->ev.e = PRI_EVENT_HANGUP;
++ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
++ ctrl->ev.hangup.channel = q931_encode_channel(c);
++ ctrl->ev.hangup.cause = c->cause;
++ ctrl->ev.hangup.cref = c->cr;
++ ctrl->ev.hangup.call = c->master_call;
++ ctrl->ev.hangup.aoc_units = c->aoc_units;
++ ctrl->ev.hangup.call_held = NULL;
++ ctrl->ev.hangup.call_active = NULL;
++ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
+ c->useruserinfo[0] = '\0';
+ /* Don't send release complete if they send us release
+ while we sent it, assume a NULL state */
+ if (c->newcall)
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+- else
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ else if (c->outboundbroadcast && (c != q931_get_subcall_winner(c->master_call)))
++ return pri_hangup(ctrl, c, -1);
++ else
+ return Q931_RES_HAVEEVENT;
+ break;
+ case Q931_DISCONNECT:
++ c->hangupinitiated = 1;
+ if (missingmand) {
+ /* Still let user call release */
+ c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
+ }
+ if (c->newcall) {
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+ break;
+ }
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
++
++ /*
++ * Determine if there are any calls that can be proposed for
++ * a transfer of held call on disconnect.
++ */
++ ctrl->ev.hangup.call_held = NULL;
++ ctrl->ev.hangup.call_active = NULL;
++ switch (c->ourcallstate) {
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_ACTIVE:
++ if (c->master_call->hold_state == Q931_HOLD_STATE_CALL_HELD) {
++ /* Held call is being disconnected first. */
++ ctrl->ev.hangup.call_held = c->master_call;
++ ctrl->ev.hangup.call_active = q931_find_held_active_call(ctrl, c);
++ } else {
++ /* Active call is being disconnected first. */
++ if (q931_find_winning_call(c) == c) {
++ /*
++ * Only a normal call or the winning call of a broadcast SETUP
++ * can participate in a transfer of held call on disconnet.
++ */
++ ctrl->ev.hangup.call_active = c->master_call;
++ ctrl->ev.hangup.call_held = q931_find_held_call(ctrl, c);
++ }
++ }
++ break;
++ default:
++ break;
++ }
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ if (ctrl->ev.hangup.call_held) {
++ pri_message(ctrl, "-- Found held call: %p cref:%d\n",
++ ctrl->ev.hangup.call_held, ctrl->ev.hangup.call_held->cr);
++ }
++ if (ctrl->ev.hangup.call_active) {
++ pri_message(ctrl, "-- Found active call: %p cref:%d\n",
++ ctrl->ev.hangup.call_active, ctrl->ev.hangup.call_active->cr);
++ }
++ if (ctrl->ev.hangup.call_held && ctrl->ev.hangup.call_active) {
++ pri_message(ctrl, "-- Transfer held call on disconnect possible.\n");
++ }
++ }
++
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
+ c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
+ c->sendhangupack = 1;
+
+ /* wait for a RELEASE so that sufficient time has passed
+ for the inband audio to be heard */
+- if (pri->acceptinbanddisconnect && (c->progressmask & PRI_PROG_INBAND_AVAILABLE))
++ if (ctrl->acceptinbanddisconnect && (c->progressmask & PRI_PROG_INBAND_AVAILABLE))
+ break;
+
+ /* Return such an event */
+- pri->ev.e = PRI_EVENT_HANGUP_REQ;
+- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.hangup.cause = c->cause;
+- pri->ev.hangup.cref = c->cr;
+- pri->ev.hangup.call = c;
+- pri->ev.hangup.aoc_units = c->aoc_units;
+- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
++ ctrl->ev.e = PRI_EVENT_HANGUP_REQ;
++ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
++ ctrl->ev.hangup.channel = q931_encode_channel(c);
++ ctrl->ev.hangup.cause = c->cause;
++ ctrl->ev.hangup.cref = c->cr;
++ ctrl->ev.hangup.call = c->master_call;
++ ctrl->ev.hangup.aoc_units = c->aoc_units;
++ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
+ c->useruserinfo[0] = '\0';
+ if (c->alive)
+ return Q931_RES_HAVEEVENT;
+ else
+- q931_hangup(pri,c,c->cause);
++ pri_hangup(ctrl,c,c->cause);
+ break;
+ case Q931_RESTART_ACKNOWLEDGE:
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
+ c->peercallstate = Q931_CALL_STATE_NULL;
+- pri->ev.e = PRI_EVENT_RESTART_ACK;
+- pri->ev.restartack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
++ ctrl->ev.e = PRI_EVENT_RESTART_ACK;
++ ctrl->ev.restartack.channel = q931_encode_channel(c);
+ return Q931_RES_HAVEEVENT;
+ case Q931_INFORMATION:
+ /* XXX We're handling only INFORMATION messages that contain
+@@ -3858,80 +6958,376 @@
+ + the "Complete" msg which is basically an EOF on further digits
+ XXX */
+ if (c->newcall) {
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+ break;
+ }
+ if (c->ourcallstate != Q931_CALL_STATE_OVERLAP_RECEIVING) {
+- pri->ev.e = PRI_EVENT_KEYPAD_DIGIT;
+- pri->ev.digit.call = c;
+- pri->ev.digit.channel = c->channelno | (c->ds1no << 8);
+- libpri_copy_string(pri->ev.digit.digits, c->keypad_digits, sizeof(pri->ev.digit.digits));
+- /* Make sure we clear it out before we return */
+- c->keypad_digits[0] = '\0';
++ ctrl->ev.e = PRI_EVENT_KEYPAD_DIGIT;
++ ctrl->ev.digit.subcmds = &ctrl->subcmds;
++ ctrl->ev.digit.call = c->master_call;
++ ctrl->ev.digit.channel = q931_encode_channel(c);
++ libpri_copy_string(ctrl->ev.digit.digits, c->keypad_digits, sizeof(ctrl->ev.digit.digits));
+ return Q931_RES_HAVEEVENT;
+ }
+- pri->ev.e = PRI_EVENT_INFO_RECEIVED;
+- pri->ev.ring.call = c;
+- pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
+- libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
+- pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */
++ ctrl->ev.e = PRI_EVENT_INFO_RECEIVED;
++ ctrl->ev.ring.subcmds = &ctrl->subcmds;
++ ctrl->ev.ring.call = c->master_call;
++ ctrl->ev.ring.channel = q931_encode_channel(c);
++ libpri_copy_string(ctrl->ev.ring.callednum, c->overlap_digits, sizeof(ctrl->ev.ring.callednum));
++
++ q931_party_id_copy_to_pri(&ctrl->ev.ring.calling, &c->remote_id);
++ /* for backwards compatibility, still need ctrl->ev.ring.callingsubaddr */
++ if (!c->remote_id.subaddress.type) { /* NSAP: Type = 0 */
++ libpri_copy_string(ctrl->ev.ring.callingsubaddr, (char *) c->remote_id.subaddress.data, sizeof(ctrl->ev.ring.callingsubaddr));
++ } else {
++ ctrl->ev.ring.callingsubaddr[0] = '\0';
++ }
++
++ ctrl->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */
+ return Q931_RES_HAVEEVENT;
+ case Q931_STATUS_ENQUIRY:
+ if (c->newcall) {
+- q931_release_complete(pri, c, PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl, c, PRI_CAUSE_INVALID_CALL_REFERENCE);
+ } else
+- q931_status(pri,c, 0);
++ q931_status(ctrl,c, 0);
+ break;
+ case Q931_SETUP_ACKNOWLEDGE:
++ stop_t303(c);
+ if (c->newcall) {
+- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
++ q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+ break;
+ }
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OVERLAP_SENDING);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OVERLAP_SENDING);
+ c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
+- pri->ev.e = PRI_EVENT_SETUP_ACK;
+- pri->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.setup_ack.call = c;
++ ctrl->ev.e = PRI_EVENT_SETUP_ACK;
++ ctrl->ev.setup_ack.subcmds = &ctrl->subcmds;
++ ctrl->ev.setup_ack.channel = q931_encode_channel(c);
++ ctrl->ev.setup_ack.call = c->master_call;
+
+- cur = c->apdus;
+- while (cur) {
++ for (cur = c->apdus; cur; cur = cur->next) {
+ if (!cur->sent && cur->message == Q931_FACILITY) {
+- q931_facility(pri, c);
++ q931_facility(ctrl, c);
+ break;
+ }
+- cur = cur->next;
+ }
+
+ return Q931_RES_HAVEEVENT;
+ case Q931_NOTIFY:
+- pri->ev.e = PRI_EVENT_NOTIFY;
+- pri->ev.notify.channel = c->channelno;
+- pri->ev.notify.info = c->notify;
+- return Q931_RES_HAVEEVENT;
+- case Q931_USER_INFORMATION:
+- case Q931_SEGMENT:
+- case Q931_CONGESTION_CONTROL:
++ res = 0;
++ switch (c->notify) {
++ case PRI_NOTIFY_CALL_DIVERTING:
++ if (c->redirection_number.valid) {
++ c->redirecting.to.number = c->redirection_number;
++ if (c->redirecting.count < PRI_MAX_REDIRECTS) {
++ ++c->redirecting.count;
++ }
++ switch (c->ourcallstate) {
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ /* Call is deflecting after we have seen an ALERTING message */
++ c->redirecting.reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
++ break;
++ default:
++ /* Call is deflecting for call forwarding unconditional or busy reason. */
++ c->redirecting.reason = PRI_REDIR_UNKNOWN;
++ break;
++ }
++
++ /* Setup redirecting subcommand */
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (subcmd) {
++ subcmd->cmd = PRI_SUBCMD_REDIRECTING;
++ q931_party_redirecting_copy_to_pri(&subcmd->u.redirecting,
++ &c->redirecting);
++ }
++ }
++
++ if (ctrl->subcmds.counter_subcmd) {
++ q931_fill_facility_event(ctrl, c);
++ res = Q931_RES_HAVEEVENT;
++ }
++ break;
++ case PRI_NOTIFY_TRANSFER_ALERTING:
++ case PRI_NOTIFY_TRANSFER_ACTIVE:
++ if (c->redirection_number.valid
++ && q931_party_number_cmp(&c->remote_id.number, &c->redirection_number)) {
++ /* The remote party information changed. */
++ c->remote_id.number = c->redirection_number;
++
++ /* Setup connected line subcommand */
++ subcmd = q931_alloc_subcommand(ctrl);
++ if (subcmd) {
++ subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
++ q931_party_id_copy_to_pri(&subcmd->u.connected_line.id,
++ &c->remote_id);
++ }
++ }
++
++ if (ctrl->subcmds.counter_subcmd) {
++ q931_fill_facility_event(ctrl, c);
++ res = Q931_RES_HAVEEVENT;
++ }
++ break;
++ default:
++ ctrl->ev.e = PRI_EVENT_NOTIFY;
++ ctrl->ev.notify.subcmds = &ctrl->subcmds;
++ ctrl->ev.notify.channel = q931_encode_channel(c);
++ ctrl->ev.notify.info = c->notify;
++ ctrl->ev.notify.call = c->master_call;
++ res = Q931_RES_HAVEEVENT;
++ break;
++ }
++ return res;
+ case Q931_HOLD:
++ res = 0;
++ if (!PRI_MASTER(ctrl)->hold_support) {
++ /*
++ * Blocking any calls from getting on HOLD effectively
++ * disables HOLD/RETRIEVE.
++ */
++ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_FACILITY_NOT_IMPLEMENTED);
++ break;
++ }
++ switch (c->ourcallstate) {
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ if (q931_is_ptmp(ctrl)) {
++ /* HOLD request only allowed in these states if point-to-point mode. */
++ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
++ break;
++ }
++ /* Fall through */
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_ACTIVE:
++ if (!q931_find_winning_call(c)) {
++ /*
++ * Only the winning call of a broadcast SETUP can do hold since the
++ * call must be answered first.
++ */
++ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
++ break;
++ }
++ master_call = c->master_call;
++ switch (master_call->hold_state) {
++ case Q931_HOLD_STATE_HOLD_REQ:
++ if (ctrl->localtype == PRI_NETWORK) {
++ /* The network ignores HOLD request on a hold collision. */
++ break;
++ }
++ /* Fall through */
++ case Q931_HOLD_STATE_IDLE:
++ ctrl->ev.e = PRI_EVENT_HOLD;
++ ctrl->ev.hold.channel = q931_encode_channel(c);
++ ctrl->ev.hold.call = master_call;
++ ctrl->ev.hold.subcmds = &ctrl->subcmds;
++ res = Q931_RES_HAVEEVENT;
++
++ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_HOLD_IND);
++
++ /* Stop any T-HOLD timer from possible hold collision. */
++ pri_schedule_del(ctrl, master_call->hold_timer);
++ master_call->hold_timer = 0;
++ break;
++ default:
++ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
++ break;
++ }
++ break;
++ case Q931_CALL_STATE_DISCONNECT_INDICATION:
++ case Q931_CALL_STATE_RELEASE_REQUEST:
++ /* Ignore HOLD request in these states. */
++ break;
++ default:
++ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
++ break;
++ }
++ return res;
+ case Q931_HOLD_ACKNOWLEDGE:
++ res = 0;
++ master_call = c->master_call;
++ switch (master_call->hold_state) {
++ case Q931_HOLD_STATE_HOLD_REQ:
++ ctrl->ev.e = PRI_EVENT_HOLD_ACK;
++ ctrl->ev.hold_ack.channel = q931_encode_channel(c);
++ ctrl->ev.hold_ack.call = master_call;
++ ctrl->ev.hold_ack.subcmds = &ctrl->subcmds;
++ res = Q931_RES_HAVEEVENT;
++
++ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_CALL_HELD);
++
++ /* Call is now on hold so forget the channel. */
++ c->channelno = 0;/* No channel */
++ c->ds1no = 0;
++ c->ds1explicit = 0;
++ c->chanflags = 0;
++
++ /* Stop T-HOLD timer */
++ pri_schedule_del(ctrl, master_call->hold_timer);
++ master_call->hold_timer = 0;
++ break;
++ default:
++ /* Ignore response. Response is late or spurrious. */
++ break;
++ }
++ return res;
+ case Q931_HOLD_REJECT:
++ res = 0;
++ master_call = c->master_call;
++ switch (master_call->hold_state) {
++ case Q931_HOLD_STATE_HOLD_REQ:
++ if (missingmand) {
++ /* Still, let hold rejection continue. */
++ c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
++ }
++ ctrl->ev.e = PRI_EVENT_HOLD_REJ;
++ ctrl->ev.hold_rej.channel = q931_encode_channel(c);
++ ctrl->ev.hold_rej.call = master_call;
++ ctrl->ev.hold_rej.cause = c->cause;
++ ctrl->ev.hold_rej.subcmds = &ctrl->subcmds;
++ res = Q931_RES_HAVEEVENT;
++
++ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_IDLE);
++
++ /* Stop T-HOLD timer */
++ pri_schedule_del(ctrl, master_call->hold_timer);
++ master_call->hold_timer = 0;
++ break;
++ default:
++ /* Ignore response. Response is late or spurrious. */
++ break;
++ }
++ return res;
+ case Q931_RETRIEVE:
++ res = 0;
++ switch (c->ourcallstate) {
++ case Q931_CALL_STATE_CALL_RECEIVED:
++ case Q931_CALL_STATE_CONNECT_REQUEST:
++ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
++ if (q931_is_ptmp(ctrl)) {
++ /* RETRIEVE request only allowed in these states if point-to-point mode. */
++ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
++ break;
++ }
++ /* Fall through */
++ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
++ case Q931_CALL_STATE_CALL_DELIVERED:
++ case Q931_CALL_STATE_ACTIVE:
++ if (!q931_find_winning_call(c)) {
++ /*
++ * Only the winning call of a broadcast SETUP can do hold since the
++ * call must be answered first.
++ */
++ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
++ break;
++ }
++ master_call = c->master_call;
++ switch (master_call->hold_state) {
++ case Q931_HOLD_STATE_RETRIEVE_REQ:
++ if (ctrl->localtype == PRI_NETWORK) {
++ /* The network ignores RETRIEVE request on a retrieve collision. */
++ break;
++ }
++ /* Fall through */
++ case Q931_HOLD_STATE_CALL_HELD:
++ ctrl->ev.e = PRI_EVENT_RETRIEVE;
++ ctrl->ev.retrieve.channel = q931_encode_channel(c);
++ ctrl->ev.retrieve.call = master_call;
++ ctrl->ev.retrieve.flexible = !(c->chanflags & FLAG_EXCLUSIVE);
++ ctrl->ev.retrieve.subcmds = &ctrl->subcmds;
++ res = Q931_RES_HAVEEVENT;
++
++ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_RETRIEVE_IND);
++
++ /* Stop any T-RETRIEVE timer from possible retrieve collision. */
++ pri_schedule_del(ctrl, master_call->hold_timer);
++ master_call->hold_timer = 0;
++ break;
++ default:
++ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
++ break;
++ }
++ break;
++ case Q931_CALL_STATE_DISCONNECT_INDICATION:
++ case Q931_CALL_STATE_RELEASE_REQUEST:
++ /* Ignore RETRIEVE request in these states. */
++ break;
++ default:
++ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
++ break;
++ }
++ return res;
+ case Q931_RETRIEVE_ACKNOWLEDGE:
++ res = 0;
++ master_call = c->master_call;
++ switch (master_call->hold_state) {
++ case Q931_HOLD_STATE_RETRIEVE_REQ:
++ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_IDLE);
++
++ /* Stop T-RETRIEVE timer */
++ pri_schedule_del(ctrl, master_call->hold_timer);
++ master_call->hold_timer = 0;
++
++ ctrl->ev.e = PRI_EVENT_RETRIEVE_ACK;
++ ctrl->ev.retrieve_ack.channel = q931_encode_channel(c);
++ ctrl->ev.retrieve_ack.call = master_call;
++ ctrl->ev.retrieve_ack.subcmds = &ctrl->subcmds;
++ res = Q931_RES_HAVEEVENT;
++ break;
++ default:
++ /* Ignore response. Response is late or spurrious. */
++ break;
++ }
++ return res;
+ case Q931_RETRIEVE_REJECT:
++ res = 0;
++ master_call = c->master_call;
++ switch (master_call->hold_state) {
++ case Q931_HOLD_STATE_RETRIEVE_REQ:
++ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_CALL_HELD);
++
++ /* Call is still on hold so forget the channel. */
++ c->channelno = 0;/* No channel */
++ c->ds1no = 0;
++ c->ds1explicit = 0;
++ c->chanflags = 0;
++
++ /* Stop T-RETRIEVE timer */
++ pri_schedule_del(ctrl, master_call->hold_timer);
++ master_call->hold_timer = 0;
++
++ if (missingmand) {
++ /* Still, let retrive rejection continue. */
++ c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
++ }
++ ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
++ ctrl->ev.retrieve_rej.channel = q931_encode_channel(c);
++ ctrl->ev.retrieve_rej.call = master_call;
++ ctrl->ev.retrieve_rej.cause = c->cause;
++ ctrl->ev.retrieve_rej.subcmds = &ctrl->subcmds;
++ res = Q931_RES_HAVEEVENT;
++ break;
++ default:
++ /* Ignore response. Response is late or spurrious. */
++ break;
++ }
++ return res;
++ case Q931_USER_INFORMATION:
++ case Q931_SEGMENT:
++ case Q931_CONGESTION_CONTROL:
+ case Q931_RESUME:
+ case Q931_RESUME_ACKNOWLEDGE:
+ case Q931_RESUME_REJECT:
+ case Q931_SUSPEND:
+ case Q931_SUSPEND_ACKNOWLEDGE:
+ case Q931_SUSPEND_REJECT:
+- pri_error(pri, "!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
++ pri_error(ctrl, "!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
+ /* Fall through */
+ default:
+-
+- pri_error(pri, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
+- q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
++ pri_error(ctrl, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
++ q931_status(ctrl,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
+ if (c->newcall)
+- q931_destroycall(pri,c->cr);
++ pri_destroycall(ctrl, c);
+ return -1;
+ }
+ return 0;
+@@ -3941,40 +7337,46 @@
+ static int pri_internal_clear(void *data)
+ {
+ struct q931_call *c = data;
+- struct pri *pri = c->pri;
++ struct pri *ctrl = c->pri;
+ int res;
+
+- if (c->retranstimer)
+- pri_schedule_del(pri, c->retranstimer);
++ pri_schedule_del(ctrl, c->retranstimer);
+ c->retranstimer = 0;
+ c->useruserinfo[0] = '\0';
+- c->cause = -1;
++ //c->cause = -1;
+ c->causecode = -1;
+ c->causeloc = -1;
+- c->sugcallstate = -1;
++ c->sugcallstate = Q931_CALL_STATE_NOT_SET;
+ c->aoc_units = -1;
+
+- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
++ UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
+ c->peercallstate = Q931_CALL_STATE_NULL;
+- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+- pri->ev.hangup.cause = c->cause;
+- pri->ev.hangup.cref = c->cr;
+- pri->ev.hangup.call = c;
+- pri->ev.hangup.aoc_units = c->aoc_units;
+- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
++ q931_clr_subcommands(ctrl);
++ ctrl->ev.hangup.subcmds = &ctrl->subcmds;
++ ctrl->ev.hangup.channel = q931_encode_channel(c);
++ ctrl->ev.hangup.cause = c->cause;
++ ctrl->ev.hangup.cref = c->cr;
++ ctrl->ev.hangup.call = c->master_call;
++ ctrl->ev.hangup.aoc_units = c->aoc_units;
++ ctrl->ev.hangup.call_held = NULL;
++ ctrl->ev.hangup.call_active = NULL;
++ libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
+
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
++ pri_message(ctrl, "clearing, alive %d, hangupack %d\n", c->alive, c->sendhangupack);
++ }
+ /* Free resources */
+ if (c->alive) {
+- pri->ev.e = PRI_EVENT_HANGUP;
++ ctrl->ev.e = PRI_EVENT_HANGUP;
+ res = Q931_RES_HAVEEVENT;
+ c->alive = 0;
+ } else if (c->sendhangupack) {
+ res = Q931_RES_HAVEEVENT;
+- pri->ev.e = PRI_EVENT_HANGUP_ACK;
+- q931_hangup(pri, c, c->cause);
++ ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
++ pri_hangup(ctrl, c, c->cause);
+ } else {
+ res = 0;
+- q931_hangup(pri, c, c->cause);
++ pri_hangup(ctrl, c, c->cause);
+ }
+
+ return res;
+@@ -3984,94 +7386,97 @@
+ static void pri_dl_down_timeout(void *data)
+ {
+ struct q931_call *c = data;
+- struct pri *pri = c->pri;
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, DBGHEAD "Timed out waiting for data link re-establishment\n", DBGINFO);
++ struct pri *ctrl = c->pri;
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, DBGHEAD "Timed out waiting for data link re-establishment\n", DBGINFO);
+
+ c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
+ if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
+- pri->schedev = 1;
++ ctrl->schedev = 1;
+ }
+
+ /* Handle Layer 2 down event for a non active call. */
+ static void pri_dl_down_cancelcall(void *data)
+ {
+ struct q931_call *c = data;
+- struct pri *pri = c->pri;
+- if (pri->debug & PRI_DEBUG_Q931_STATE)
+- pri_message(pri, DBGHEAD "Cancel non active call after data link failure\n", DBGINFO);
++ struct pri *ctrl = c->pri;
++ if (ctrl->debug & PRI_DEBUG_Q931_STATE)
++ pri_message(ctrl, DBGHEAD "Cancel non active call after data link failure\n", DBGINFO);
+
+ c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
+ if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
+- pri->schedev = 1;
++ ctrl->schedev = 1;
+ }
+
+ /* Receive an indication from Layer 2 */
+-void q931_dl_indication(struct pri *pri, int event)
++void q931_dl_indication(struct pri *ctrl, int event)
+ {
+ q931_call *cur = NULL;
+
+ /* Just return if T309 is not enabled. */
+- if (!pri || pri->timers[PRI_TIMER_T309] < 0)
++ if (!ctrl || ctrl->timers[PRI_TIMER_T309] < 0)
+ return;
+
+ switch (event) {
+ case PRI_EVENT_DCHAN_DOWN:
+- pri_message(pri, DBGHEAD "link is DOWN\n", DBGINFO);
+- cur = *pri->callpool;
++ pri_message(ctrl, DBGHEAD "link is DOWN\n", DBGINFO);
++ cur = *ctrl->callpool;
+ while(cur) {
+ if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE) {
+ /* For a call in Active state, activate T309 only if there is no timer already running. */
+ if (!cur->retranstimer) {
+- pri_message(pri, DBGHEAD "activate T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
+- cur->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T309], pri_dl_down_timeout, cur);
++ pri_message(ctrl, DBGHEAD "activate T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
++ cur->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T309], pri_dl_down_timeout, cur);
+ }
+ } else if (cur->ourcallstate != Q931_CALL_STATE_NULL) {
+ /* For a call that is not in Active state, schedule internal clearing of the call 'ASAP' (delay 0). */
+- pri_message(pri, DBGHEAD "cancel call %d on channel %d in state %d (%s)\n", DBGINFO,
+- cur->cr, cur->channelno, cur->ourcallstate, callstate2str(cur->ourcallstate));
+- if (cur->retranstimer)
+- pri_schedule_del(pri, cur->retranstimer);
+- cur->retranstimer = pri_schedule_event(pri, 0, pri_dl_down_cancelcall, cur);
++ pri_message(ctrl, DBGHEAD "cancel call %d on channel %d in state %d (%s)\n", DBGINFO,
++ cur->cr, cur->channelno, cur->ourcallstate,
++ q931_call_state_str(cur->ourcallstate));
++ pri_schedule_del(ctrl, cur->retranstimer);
++ cur->retranstimer = pri_schedule_event(ctrl, 0, pri_dl_down_cancelcall, cur);
+ }
+ cur = cur->next;
+ }
+ break;
+ case PRI_EVENT_DCHAN_UP:
+- pri_message(pri, DBGHEAD "link is UP\n", DBGINFO);
+- cur = *pri->callpool;
++ pri_message(ctrl, DBGHEAD "link is UP\n", DBGINFO);
++ cur = *ctrl->callpool;
+ while(cur) {
+ if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE && cur->retranstimer) {
+- pri_message(pri, DBGHEAD "cancel T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
+- pri_schedule_del(pri, cur->retranstimer);
++ pri_message(ctrl, DBGHEAD "cancel T309 for call %d on channel %d\n", DBGINFO, cur->cr, cur->channelno);
++ pri_schedule_del(ctrl, cur->retranstimer);
+ cur->retranstimer = 0;
+- q931_status(pri, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
++ q931_status(ctrl, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
+ } else if (cur->ourcallstate != Q931_CALL_STATE_NULL &&
+ cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_REQUEST &&
+ cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_INDICATION &&
+ cur->ourcallstate != Q931_CALL_STATE_RELEASE_REQUEST) {
+
+ /* The STATUS message sent here is not required by Q.931, but it may help anyway. */
+- q931_status(pri, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
++ q931_status(ctrl, cur, PRI_CAUSE_NORMAL_UNSPECIFIED);
+ }
+ cur = cur->next;
+ }
+ break;
+ default:
+- pri_message(pri, DBGHEAD "unexpected event %d.\n", DBGINFO, event);
++ pri_message(ctrl, DBGHEAD "unexpected event %d.\n", DBGINFO, event);
+ }
+ }
+
+-int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode)
++int q931_call_getcrv(struct pri *ctrl, q931_call *call, int *callmode)
+ {
+ if (callmode)
+ *callmode = call->cr & 0x7;
+ return ((call->cr & 0x7fff) >> 3);
+ }
+
+-int q931_call_setcrv(struct pri *pri, q931_call *call, int crv, int callmode)
++int q931_call_setcrv(struct pri *ctrl, q931_call *call, int crv, int callmode)
+ {
+- call->cr = (crv << 3) & 0x7fff;
+- call->cr |= (callmode & 0x7);
++ /* Do not allow changing the dummy call reference */
++ if (!q931_is_dummy_call(call)) {
++ call->cr = (crv << 3) & 0x7fff;
++ call->cr |= (callmode & 0x7);
++ }
+ return 0;
+ }
+Index: asn1.h
+===================================================================
+--- a/asn1.h (.../tags/1.4.10.2) (revision 0)
++++ b/asn1.h (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,257 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ASN.1 definitions and prototypes
++ *
++ * \details
++ * This file contains all ASN.1 primitive data structures and
++ * definitions needed for ROSE component encoding and decoding.
++ *
++ * ROSE - Remote Operations Service Element
++ * ASN.1 - Abstract Syntax Notation 1
++ * APDU - Application Protocol Data Unit
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++#ifndef _LIBPRI_ASN1_H
++#define _LIBPRI_ASN1_H
++
++#include <string.h>
++#include <sys/types.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* ------------------------------------------------------------------- */
++
++/*! ASN.1 Identifier Octet - Tag class bits */
++#define ASN1_CLASS_MASK 0xc0
++#define ASN1_CLASS_UNIVERSAL 0x00 /*!< Universal primitive data types */
++#define ASN1_CLASS_APPLICATION 0x40 /*!< Application wide data tag */
++#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /*!< Context specifc data tag */
++#define ASN1_CLASS_PRIVATE 0xc0 /*!< Private organization data tag */
++
++/*! ASN.1 Identifier Octet - Primitive/Constructor bit */
++#define ASN1_PC_MASK 0x20
++#define ASN1_PC_PRIMITIVE 0x00
++#define ASN1_PC_CONSTRUCTED 0x20
++
++/*! ASN.1 Identifier Octet - Universal data types */
++#define ASN1_TYPE_MASK 0x1f
++#define ASN1_TYPE_INDEF_TERM 0x00 /* 0 */
++#define ASN1_TYPE_BOOLEAN 0x01 /* 1 */
++#define ASN1_TYPE_INTEGER 0x02 /* 2 */
++#define ASN1_TYPE_BIT_STRING 0x03 /* 3 */
++#define ASN1_TYPE_OCTET_STRING 0x04 /* 4 */
++#define ASN1_TYPE_NULL 0x05 /* 5 */
++#define ASN1_TYPE_OBJECT_IDENTIFIER 0x06 /* 6 */
++#define ASN1_TYPE_OBJECT_DESCRIPTOR 0x07 /* 7 */
++#define ASN1_TYPE_EXTERN 0x08 /* 8 */
++#define ASN1_TYPE_REAL 0x09 /* 9 */
++#define ASN1_TYPE_ENUMERATED 0x0a /* 10 */
++#define ASN1_TYPE_EMBEDDED_PDV 0x0b /* 11 */
++#define ASN1_TYPE_UTF8_STRING 0x0c /* 12 */
++#define ASN1_TYPE_RELATIVE_OID 0x0d /* 13 */
++/* 0x0e & 0x0f are reserved for future ASN.1 editions */
++#define ASN1_TYPE_SEQUENCE 0x10 /* 16 */
++#define ASN1_TYPE_SET 0x11 /* 17 */
++#define ASN1_TYPE_NUMERIC_STRING 0x12 /* 18 */
++#define ASN1_TYPE_PRINTABLE_STRING 0x13 /* 19 */
++#define ASN1_TYPE_TELETEX_STRING 0x14 /* 20 */
++#define ASN1_TYPE_VIDEOTEX_STRING 0x15 /* 21 */
++#define ASN1_TYPE_IA5_STRING 0x16 /* 22 */
++#define ASN1_TYPE_UTC_TIME 0x17 /* 23 */
++#define ASN1_TYPE_GENERALIZED_TIME 0x18 /* 24 */
++#define ASN1_TYPE_GRAPHIC_STRING 0x19 /* 25 */
++#define ASN1_TYPE_VISIBLE_STRING 0x1a /* 26 */
++#define ASN1_TYPE_ISO646_STRING 0x1a /* 26 */
++#define ASN1_TYPE_GENERAL_STRING 0x1b /* 27 */
++#define ASN1_TYPE_UNIVERSAL_STRING 0x1c /* 28 */
++#define ASN1_TYPE_CHAR_STRING 0x1d /* 29 */
++#define ASN1_TYPE_BMP_STRING 0x1e /* 30 */
++#define ASN1_TYPE_EXTENSION 0x1f /* 31 */
++
++#define ASN1_TAG_SEQUENCE (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_SEQUENCE)
++#define ASN1_TAG_SET (ASN1_CLASS_UNIVERSAL | ASN1_PC_CONSTRUCTED | ASN1_TYPE_SET)
++
++#define ASN1_INDEF_TERM (ASN1_CLASS_UNIVERSAL | ASN1_PC_PRIMITIVE | ASN1_TYPE_INDEF_TERM)
++#define ASN1_INDEF_TERM_LEN 2
++
++struct asn1_oid {
++ /*! \brief Number of subidentifier values in OID list */
++ u_int16_t num_values;
++
++ /*!
++ * \brief OID subidentifier value list
++ * \note The first value is really the first two OID subidentifiers.
++ * They are compressed using this formula:
++ * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
++ */
++ u_int16_t value[10];
++};
++
++#define ASN1_CALL(new_pos, do_it) \
++ do \
++ { \
++ (new_pos) = (do_it); \
++ if (!(new_pos)) { \
++ return NULL; \
++ } \
++ } while (0)
++
++/*! \brief Determine the ending position of the set or sequence to verify the length. */
++#define ASN1_END_SETUP(component_end, offset, length, pos, end) \
++ do { \
++ if ((length) < 0) { \
++ (offset) = ASN1_INDEF_TERM_LEN; \
++ (component_end) = (end); \
++ } else { \
++ (offset) = 0; \
++ (component_end) = (pos) + (length); \
++ } \
++ } while (0)
++
++/*! \brief Account for the indefinite length terminator of the set or sequence. */
++#define ASN1_END_FIXUP(ctrl, pos, offset, component_end, end) \
++ do { \
++ if (offset) { \
++ ASN1_CALL((pos), asn1_dec_indef_end_fixup((ctrl), (pos), (end))); \
++ } else if ((pos) != (component_end)) { \
++ if ((ctrl)->debug & PRI_DEBUG_APDU) { \
++ pri_message((ctrl), \
++ " Skipping unused constructed component octets!\n"); \
++ } \
++ (pos) = (component_end); \
++ } \
++ } while (0)
++
++#define ASN1_DID_NOT_EXPECT_TAG(ctrl, tag) \
++ do { \
++ if ((ctrl)->debug & PRI_DEBUG_APDU) { \
++ pri_message((ctrl), " Did not expect: %s\n", asn1_tag2str(tag)); \
++ } \
++ } while (0)
++
++#define ASN1_CHECK_TAG(ctrl, actual_tag, match_tag, expected_tag) \
++ do { \
++ if ((match_tag) != (expected_tag)) { \
++ ASN1_DID_NOT_EXPECT_TAG((ctrl), (actual_tag)); \
++ return NULL; \
++ } \
++ } while (0)
++
++
++const unsigned char *asn1_dec_tag(const unsigned char *tag_pos, const unsigned char *end,
++ unsigned *tag);
++const unsigned char *asn1_dec_length(const unsigned char *len_pos,
++ const unsigned char *end, int *length);
++const unsigned char *asn1_dec_indef_end_fixup(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end);
++
++const unsigned char *asn1_dec_boolean(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, int32_t *value);
++const unsigned char *asn1_dec_int(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, int32_t *value);
++const unsigned char *asn1_dec_null(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end);
++const unsigned char *asn1_dec_oid(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct asn1_oid *oid);
++const unsigned char *asn1_dec_string_bin(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
++ unsigned char *str, size_t *str_len);
++const unsigned char *asn1_dec_string_max(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end, size_t buf_size,
++ unsigned char *str, size_t *str_len);
++
++const char *asn1_tag2str(unsigned tag);
++void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1,
++ const unsigned char *end);
++
++
++#define ASN1_LEN_FORM_SHORT 1 /*!< Hint that the final length will be less than 128 octets */
++#define ASN1_LEN_FORM_LONG_U8 2 /*!< Hint that the final length will be less than 256 octets */
++#define ASN1_LEN_FORM_LONG_U16 3 /*!< Hint that the final length will be less than 65536 octets */
++#define ASN1_LEN_INIT(len_pos, end, form_hint) \
++ do { \
++ if ((end) < (len_pos) + (form_hint)) { \
++ return NULL; \
++ } \
++ *(len_pos) = (form_hint); \
++ (len_pos) += (form_hint); \
++ } while (0)
++
++#define ASN1_LEN_FIXUP(len_pos, component_end, end) \
++ ASN1_CALL((component_end), asn1_enc_length_fixup((len_pos), (component_end), (end)))
++
++/*! \brief Use to begin encoding explicit tags, SET, and SEQUENCE constructed groupings. */
++#define ASN1_CONSTRUCTED_BEGIN(len_pos_save, pos, end, tag) \
++ do { \
++ if ((end) < (pos) + (1 + ASN1_LEN_FORM_SHORT)) { \
++ return NULL; \
++ } \
++ *(pos)++ = (tag) | ASN1_PC_CONSTRUCTED; \
++ (len_pos_save) = (pos); \
++ *(pos) = ASN1_LEN_FORM_SHORT; \
++ (pos) += ASN1_LEN_FORM_SHORT; \
++ } while (0)
++
++/*! \brief Use to end encoding explicit tags, SET, and SEQUENCE constructed groupings. */
++#define ASN1_CONSTRUCTED_END(len_pos, component_end, end) \
++ ASN1_CALL((component_end), asn1_enc_length_fixup((len_pos), (component_end), (end)))
++
++#define ASN1_ENC_ERROR(ctrl, msg) \
++ pri_error((ctrl), "%s error: %s\n", __FUNCTION__, (msg))
++
++unsigned char *asn1_enc_length(unsigned char *len_pos, unsigned char *end,
++ size_t str_len);
++unsigned char *asn1_enc_length_fixup(unsigned char *len_pos,
++ unsigned char *component_end, unsigned char *end);
++
++unsigned char *asn1_enc_boolean(unsigned char *pos, unsigned char *end, unsigned tag,
++ int32_t value);
++unsigned char *asn1_enc_int(unsigned char *pos, unsigned char *end, unsigned tag,
++ int32_t value);
++unsigned char *asn1_enc_null(unsigned char *pos, unsigned char *end, unsigned tag);
++unsigned char *asn1_enc_oid(unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct asn1_oid *oid);
++unsigned char *asn1_enc_string_bin(unsigned char *pos, unsigned char *end, unsigned tag,
++ const unsigned char *str, size_t str_len);
++unsigned char *asn1_enc_string_max(unsigned char *pos, unsigned char *end, unsigned tag,
++ const unsigned char *str, size_t max_len);
++
++/* ------------------------------------------------------------------- */
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _LIBPRI_ASN1_H */
++/* ------------------------------------------------------------------- */
++/* end asn1.h */
+
+Property changes on: asn1.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose.c
+===================================================================
+--- a/rose.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,2464 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief Remote Operations Service Element (ROSE) main controlling functions
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include <stdio.h>
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++#include "pri_facility.h"
++
++
++#define ROSE_TAG_COMPONENT_INVOKE (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1)
++#define ROSE_TAG_COMPONENT_RESULT (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2)
++#define ROSE_TAG_COMPONENT_ERROR (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3)
++#define ROSE_TAG_COMPONENT_REJECT (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4)
++
++/*! \brief Structure to convert a code value to a string */
++struct rose_code_strings {
++ /*! \brief Code value to convert to a string */
++ int code;
++ /*! \brief String equivalent of the associated code value */
++ const char *name;
++};
++
++/*! \brief ROSE invoke/result message conversion table entry. */
++struct rose_convert_msg {
++ /*! \brief library encoded operation-value */
++ enum rose_operation operation;
++ /*!
++ * \brief OID prefix values to use when encoding/decoding the operation-value OID
++ * \note NULL if operation-value is a localValue.
++ */
++ const struct asn1_oid *oid_prefix;
++ /*! \brief Last OID value or localValue for the encoded operation-value */
++ u_int16_t value;
++
++ /*!
++ * \brief Encode the ROSE invoke operation-value arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ *
++ * \note The function pointer is NULL if there are no arguments to encode.
++ */
++ unsigned char *(*encode_invoke_args)(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args);
++ /*!
++ * \brief Encode the ROSE result operation-value arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ *
++ * \note The function pointer is NULL if there are no arguments to encode.
++ */
++ unsigned char *(*encode_result_args)(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args);
++
++ /*!
++ * \brief Decode the ROSE invoke operation-value arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ *
++ * \note The function pointer is NULL if there are no arguments to decode.
++ */
++ const unsigned char *(*decode_invoke_args)(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args);
++ /*!
++ * \brief Decode the ROSE result operation-value arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ *
++ * \note The function pointer is NULL if there are no arguments to decode.
++ */
++ const unsigned char *(*decode_result_args)(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args);
++};
++
++/*! \brief ROSE error code conversion table entry. */
++struct rose_convert_error {
++ /*! \brief library encoded error-value */
++ enum rose_error_code code;
++ /*!
++ * \brief OID prefix values to use when encoding/decoding the error-value OID
++ * \note NULL if error-value is a localValue.
++ */
++ const struct asn1_oid *oid_prefix;
++ /*! \brief Last OID value or localValue for the encoded error-value */
++ u_int16_t value;
++
++ /*!
++ * \brief Encode the ROSE error parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ *
++ * \note The function pointer is NULL if there are no arguments to encode.
++ */
++ unsigned char *(*encode_error_args)(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_error_args *args);
++
++ /*!
++ * \brief Decode the ROSE error parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ *
++ * \note The function pointer is NULL if there are no arguments to decode.
++ */
++ const unsigned char *(*decode_error_args)(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ union rose_msg_error_args *args);
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * Note the first value in oid.values[] is really the first two
++ * OID subidentifiers. They are compressed using this formula:
++ * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
++ */
++
++/*! \brief ETSI Explicit Call Transfer OID prefix. */
++static const struct asn1_oid rose_etsi_ect = {
++/* *INDENT-OFF* */
++ /* {ccitt(0) identified-organization(4) etsi(0) 369 operations-and-errors(1)} */
++ 4, { 4, 0, 369, 1 }
++/* *INDENT-ON* */
++};
++
++/*! \brief ETSI specific invoke/result encode/decode message table */
++static const struct rose_convert_msg rose_etsi_msgs[] = {
++/* *INDENT-OFF* */
++/*
++ * operation, oid_prefix, value,
++ * encode_invoke_args, encode_result_args,
++ * decode_invoke_args, decode_result_args
++ */
++ /*
++ * localValue's from Diversion-Operations
++ * {ccitt identified-organization etsi(0) 207 operations-and-errors(1)}
++ */
++ {
++ ROSE_ETSI_ActivationDiversion, NULL, 7,
++ rose_enc_etsi_ActivationDiversion_ARG, NULL,
++ rose_dec_etsi_ActivationDiversion_ARG, NULL
++ },
++ {
++ ROSE_ETSI_DeactivationDiversion, NULL, 8,
++ rose_enc_etsi_DeactivationDiversion_ARG,NULL,
++ rose_dec_etsi_DeactivationDiversion_ARG,NULL
++ },
++ {
++ ROSE_ETSI_ActivationStatusNotificationDiv, NULL, 9,
++ rose_enc_etsi_ActivationStatusNotificationDiv_ARG,NULL,
++ rose_dec_etsi_ActivationStatusNotificationDiv_ARG,NULL
++ },
++ {
++ ROSE_ETSI_DeactivationStatusNotificationDiv,NULL, 10,
++ rose_enc_etsi_DeactivationStatusNotificationDiv_ARG,NULL,
++ rose_dec_etsi_DeactivationStatusNotificationDiv_ARG,NULL
++ },
++ {
++ ROSE_ETSI_InterrogationDiversion, NULL, 11,
++ rose_enc_etsi_InterrogationDiversion_ARG,rose_enc_etsi_InterrogationDiversion_RES,
++ rose_dec_etsi_InterrogationDiversion_ARG,rose_dec_etsi_InterrogationDiversion_RES
++ },
++ {
++ ROSE_ETSI_DiversionInformation, NULL, 12,
++ rose_enc_etsi_DiversionInformation_ARG, NULL,
++ rose_dec_etsi_DiversionInformation_ARG, NULL
++ },
++ {
++ ROSE_ETSI_CallDeflection, NULL, 13,
++ rose_enc_etsi_CallDeflection_ARG, NULL,
++ rose_dec_etsi_CallDeflection_ARG, NULL
++ },
++ {
++ ROSE_ETSI_CallRerouting, NULL, 14,
++ rose_enc_etsi_CallRerouting_ARG, NULL,
++ rose_dec_etsi_CallRerouting_ARG, NULL
++ },
++ {
++ ROSE_ETSI_DivertingLegInformation2, NULL, 15,
++ rose_enc_etsi_DivertingLegInformation2_ARG,NULL,
++ rose_dec_etsi_DivertingLegInformation2_ARG,NULL
++ },
++ {
++ ROSE_ETSI_InterrogateServedUserNumbers, NULL, 17,
++ NULL, rose_enc_etsi_InterrogateServedUserNumbers_RES,
++ NULL, rose_dec_etsi_InterrogateServedUserNumbers_RES
++ },
++ {
++ ROSE_ETSI_DivertingLegInformation1, NULL, 18,
++ rose_enc_etsi_DivertingLegInformation1_ARG,NULL,
++ rose_dec_etsi_DivertingLegInformation1_ARG,NULL
++ },
++ {
++ ROSE_ETSI_DivertingLegInformation3, NULL, 19,
++ rose_enc_etsi_DivertingLegInformation3_ARG,NULL,
++ rose_dec_etsi_DivertingLegInformation3_ARG,NULL
++ },
++
++ /*
++ * localValue's from Advice-of-Charge-Operations
++ * {ccitt identified-organization etsi (0) 182 operations-and-errors (1)}
++ *
++ * Advice-Of-Charge-at-call-Setup(AOCS)
++ * Advice-Of-Charge-During-the-call(AOCD)
++ * Advice-Of-Charge-at-the-End-of-the-call(AOCE)
++ */
++ {
++ ROSE_ETSI_ChargingRequest, NULL, 30,
++ rose_enc_etsi_ChargingRequest_ARG, rose_enc_etsi_ChargingRequest_RES,
++ rose_dec_etsi_ChargingRequest_ARG, rose_dec_etsi_ChargingRequest_RES
++ },
++ {
++ ROSE_ETSI_AOCSCurrency, NULL, 31,
++ rose_enc_etsi_AOCSCurrency_ARG, NULL,
++ rose_dec_etsi_AOCSCurrency_ARG, NULL
++ },
++ {
++ ROSE_ETSI_AOCSSpecialArr, NULL, 32,
++ rose_enc_etsi_AOCSSpecialArr_ARG, NULL,
++ rose_dec_etsi_AOCSSpecialArr_ARG, NULL
++ },
++ {
++ ROSE_ETSI_AOCDCurrency, NULL, 33,
++ rose_enc_etsi_AOCDCurrency_ARG, NULL,
++ rose_dec_etsi_AOCDCurrency_ARG, NULL
++ },
++ {
++ ROSE_ETSI_AOCDChargingUnit, NULL, 34,
++ rose_enc_etsi_AOCDChargingUnit_ARG, NULL,
++ rose_dec_etsi_AOCDChargingUnit_ARG, NULL
++ },
++ {
++ ROSE_ETSI_AOCECurrency, NULL, 35,
++ rose_enc_etsi_AOCECurrency_ARG, NULL,
++ rose_dec_etsi_AOCECurrency_ARG, NULL
++ },
++ {
++ ROSE_ETSI_AOCEChargingUnit, NULL, 36,
++ rose_enc_etsi_AOCEChargingUnit_ARG, NULL,
++ rose_dec_etsi_AOCEChargingUnit_ARG, NULL
++ },
++
++ /*
++ * localValue's from Explicit-Call-Transfer-Operations-and-Errors
++ * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
++ */
++ {
++ ROSE_ETSI_EctExecute, NULL, 6,
++ NULL, NULL,
++ NULL, NULL
++ },
++
++ /*
++ * globalValue's (OIDs) from Explicit-Call-Transfer-Operations-and-Errors
++ * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
++ */
++ {
++ ROSE_ETSI_ExplicitEctExecute, &rose_etsi_ect, 1,
++ rose_enc_etsi_ExplicitEctExecute_ARG, NULL,
++ rose_dec_etsi_ExplicitEctExecute_ARG, NULL
++ },
++ {
++ ROSE_ETSI_RequestSubaddress, &rose_etsi_ect, 2,
++ NULL, NULL,
++ NULL, NULL
++ },
++ {
++ ROSE_ETSI_SubaddressTransfer, &rose_etsi_ect, 3,
++ rose_enc_etsi_SubaddressTransfer_ARG, NULL,
++ rose_dec_etsi_SubaddressTransfer_ARG, NULL
++ },
++ {
++ ROSE_ETSI_EctLinkIdRequest, &rose_etsi_ect, 4,
++ NULL, rose_enc_etsi_EctLinkIdRequest_RES,
++ NULL, rose_dec_etsi_EctLinkIdRequest_RES
++ },
++ {
++ ROSE_ETSI_EctInform, &rose_etsi_ect, 5,
++ rose_enc_etsi_EctInform_ARG, NULL,
++ rose_dec_etsi_EctInform_ARG, NULL
++ },
++ {
++ ROSE_ETSI_EctLoopTest, &rose_etsi_ect, 6,
++ rose_enc_etsi_EctLoopTest_ARG, rose_enc_etsi_EctLoopTest_RES,
++ rose_dec_etsi_EctLoopTest_ARG, rose_dec_etsi_EctLoopTest_RES
++ },
++/* *INDENT-ON* */
++};
++
++
++/*! \brief ETSI specific error-value converion table */
++static const struct rose_convert_error rose_etsi_errors[] = {
++/* *INDENT-OFF* */
++/*
++ * error-code, oid_prefix, value
++ * encode_error_args, decode_error_args
++ */
++ /*
++ * localValue Errors from General-Errors
++ * {ccitt identified-organization etsi(0) 196 general-errors(2)}
++ */
++ {
++ ROSE_ERROR_Gen_NotSubscribed, NULL, 0,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_NotAvailable, NULL, 3,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_NotImplemented, NULL, 4,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_InvalidServedUserNr, NULL, 6,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_InvalidCallState, NULL, 7,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_BasicServiceNotProvided, NULL, 8,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_NotIncomingCall, NULL, 9,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_ResourceUnavailable, NULL, 11,
++ NULL, NULL
++ },
++
++ /*
++ * localValue Errors from Diversion-Operations
++ * {ccitt identified-organization etsi(0) 207 operations-and-errors(1)}
++ */
++ {
++ ROSE_ERROR_Div_InvalidDivertedToNr, NULL, 12,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_SpecialServiceNr, NULL, 14,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_DiversionToServedUserNr, NULL, 15,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_IncomingCallAccepted, NULL, 23,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_NumberOfDiversionsExceeded, NULL, 24,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_NotActivated, NULL, 46,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_RequestAlreadyAccepted, NULL, 48,
++ NULL, NULL
++ },
++
++ /*
++ * localValue Errors from Advice-of-Charge-Operations
++ * {ccitt identified-organization etsi (0) 182 operations-and-errors (1)}
++ */
++ {
++ ROSE_ERROR_AOC_NoChargingInfoAvailable, NULL, 26,
++ NULL, NULL
++ },
++
++ /*
++ * globalValue Errors (OIDs) from Explicit-Call-Transfer-Operations-and-Errors
++ * {ccitt identified-organization etsi(0) 369 operations-and-errors(1)}
++ */
++ {
++ ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork, &rose_etsi_ect, 21,
++ NULL, NULL
++ },
++/* *INDENT-ON* */
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*! \brief Q.SIG specific invoke/result encode/decode message table */
++static const struct rose_convert_msg rose_qsig_msgs[] = {
++/* *INDENT-OFF* */
++/*
++ * operation, oid_prefix, value,
++ * encode_invoke_args, encode_result_args,
++ * decode_invoke_args, decode_result_args
++ */
++ /*
++ * localValue's from Q.SIG Name-Operations
++ * { iso(1) standard(0) pss1-name(13868) name-operations(0) }
++ */
++ {
++ ROSE_QSIG_CallingName, NULL, 0,
++ rose_enc_qsig_CallingName_ARG, NULL,
++ rose_dec_qsig_CallingName_ARG, NULL
++ },
++ {
++ ROSE_QSIG_CalledName, NULL, 1,
++ rose_enc_qsig_CalledName_ARG, NULL,
++ rose_dec_qsig_CalledName_ARG, NULL
++ },
++ {
++ ROSE_QSIG_ConnectedName, NULL, 2,
++ rose_enc_qsig_ConnectedName_ARG, NULL,
++ rose_dec_qsig_ConnectedName_ARG, NULL
++ },
++ {
++ ROSE_QSIG_BusyName, NULL, 3,
++ rose_enc_qsig_BusyName_ARG, NULL,
++ rose_dec_qsig_BusyName_ARG, NULL
++ },
++
++ /*
++ * localValue's from Q.SIG SS-AOC-Operations
++ * { iso(1) standard(0) pss1-advice-of-charge(15050) advice-of-charge-operations(0) }
++ */
++ {
++ ROSE_QSIG_ChargeRequest, NULL, 59,
++ rose_enc_qsig_ChargeRequest_ARG, rose_enc_qsig_ChargeRequest_RES,
++ rose_dec_qsig_ChargeRequest_ARG, rose_dec_qsig_ChargeRequest_RES
++ },
++ {
++ ROSE_QSIG_GetFinalCharge, NULL, 60,
++ rose_enc_qsig_DummyArg_ARG, NULL,
++ rose_dec_qsig_DummyArg_ARG, NULL
++ },
++ {
++ ROSE_QSIG_AocFinal, NULL, 61,
++ rose_enc_qsig_AocFinal_ARG, NULL,
++ rose_dec_qsig_AocFinal_ARG, NULL
++ },
++ {
++ ROSE_QSIG_AocInterim, NULL, 62,
++ rose_enc_qsig_AocInterim_ARG, NULL,
++ rose_dec_qsig_AocInterim_ARG, NULL
++ },
++ {
++ ROSE_QSIG_AocRate, NULL, 63,
++ rose_enc_qsig_AocRate_ARG, NULL,
++ rose_dec_qsig_AocRate_ARG, NULL
++ },
++ {
++ ROSE_QSIG_AocComplete, NULL, 64,
++ rose_enc_qsig_AocComplete_ARG, rose_enc_qsig_AocComplete_RES,
++ rose_dec_qsig_AocComplete_ARG, rose_dec_qsig_AocComplete_RES
++ },
++ {
++ ROSE_QSIG_AocDivChargeReq, NULL, 65,
++ rose_enc_qsig_AocDivChargeReq_ARG, NULL,
++ rose_dec_qsig_AocDivChargeReq_ARG, NULL
++ },
++
++ /*
++ * localValue's from Q.SIG Call-Transfer-Operations
++ * { iso(1) standard(0) pss1-call-transfer(13869) call-transfer-operations(0) }
++ */
++ {
++ ROSE_QSIG_CallTransferIdentify, NULL, 7,
++ rose_enc_qsig_DummyArg_ARG, rose_enc_qsig_CallTransferIdentify_RES,
++ rose_dec_qsig_DummyArg_ARG, rose_dec_qsig_CallTransferIdentify_RES
++ },
++ {
++ ROSE_QSIG_CallTransferAbandon, NULL, 8,
++ rose_enc_qsig_DummyArg_ARG, NULL,
++ rose_dec_qsig_DummyArg_ARG, NULL
++ },
++ {
++ ROSE_QSIG_CallTransferInitiate, NULL, 9,
++ rose_enc_qsig_CallTransferInitiate_ARG, rose_enc_qsig_DummyRes_RES,
++ rose_dec_qsig_CallTransferInitiate_ARG, rose_dec_qsig_DummyRes_RES
++ },
++ {
++ ROSE_QSIG_CallTransferSetup, NULL, 10,
++ rose_enc_qsig_CallTransferSetup_ARG, rose_enc_qsig_DummyRes_RES,
++ rose_dec_qsig_CallTransferSetup_ARG, rose_dec_qsig_DummyRes_RES
++ },
++ {
++ ROSE_QSIG_CallTransferActive, NULL, 11,
++ rose_enc_qsig_CallTransferActive_ARG, NULL,
++ rose_dec_qsig_CallTransferActive_ARG, NULL
++ },
++ {
++ ROSE_QSIG_CallTransferComplete, NULL, 12,
++ rose_enc_qsig_CallTransferComplete_ARG, NULL,
++ rose_dec_qsig_CallTransferComplete_ARG, NULL
++ },
++ {
++ ROSE_QSIG_CallTransferUpdate, NULL, 13,
++ rose_enc_qsig_CallTransferUpdate_ARG, NULL,
++ rose_dec_qsig_CallTransferUpdate_ARG, NULL
++ },
++ {
++ ROSE_QSIG_SubaddressTransfer, NULL, 14,
++ rose_enc_qsig_SubaddressTransfer_ARG, NULL,
++ rose_dec_qsig_SubaddressTransfer_ARG, NULL
++ },
++
++ /*
++ * NOTE: I do not have the specification needed to fully support this
++ * message. Fortunately, all I have to do for this message is to switch
++ * it to the bridged call leg for 2BCT support.
++ */
++ {
++ ROSE_QSIG_PathReplacement, NULL, 4,
++ NULL, NULL,
++ NULL, NULL
++ },
++
++ /*
++ * localValue's from Q.SIG Call-Diversion-Operations
++ * { iso(1) standard(0) pss1-call-diversion(13873) call-diversion-operations(0) }
++ */
++ {
++ ROSE_QSIG_ActivateDiversionQ, NULL, 15,
++ rose_enc_qsig_ActivateDiversionQ_ARG, rose_enc_qsig_DummyRes_RES,
++ rose_dec_qsig_ActivateDiversionQ_ARG, rose_dec_qsig_DummyRes_RES
++ },
++ {
++ ROSE_QSIG_DeactivateDiversionQ, NULL, 16,
++ rose_enc_qsig_DeactivateDiversionQ_ARG, rose_enc_qsig_DummyRes_RES,
++ rose_dec_qsig_DeactivateDiversionQ_ARG, rose_dec_qsig_DummyRes_RES
++ },
++ {
++ ROSE_QSIG_InterrogateDiversionQ, NULL, 17,
++ rose_enc_qsig_InterrogateDiversionQ_ARG,rose_enc_qsig_InterrogateDiversionQ_RES,
++ rose_dec_qsig_InterrogateDiversionQ_ARG,rose_dec_qsig_InterrogateDiversionQ_RES
++ },
++ {
++ ROSE_QSIG_CheckRestriction, NULL, 18,
++ rose_enc_qsig_CheckRestriction_ARG, rose_enc_qsig_DummyRes_RES,
++ rose_dec_qsig_CheckRestriction_ARG, rose_dec_qsig_DummyRes_RES
++ },
++ {
++ ROSE_QSIG_CallRerouting, NULL, 19,
++ rose_enc_qsig_CallRerouting_ARG, rose_enc_qsig_DummyRes_RES,
++ rose_dec_qsig_CallRerouting_ARG, rose_dec_qsig_DummyRes_RES
++ },
++ {
++ ROSE_QSIG_DivertingLegInformation1, NULL, 20,
++ rose_enc_qsig_DivertingLegInformation1_ARG,NULL,
++ rose_dec_qsig_DivertingLegInformation1_ARG,NULL
++ },
++ {
++ ROSE_QSIG_DivertingLegInformation2, NULL, 21,
++ rose_enc_qsig_DivertingLegInformation2_ARG,NULL,
++ rose_dec_qsig_DivertingLegInformation2_ARG,NULL
++ },
++ {
++ ROSE_QSIG_DivertingLegInformation3, NULL, 22,
++ rose_enc_qsig_DivertingLegInformation3_ARG,NULL,
++ rose_dec_qsig_DivertingLegInformation3_ARG,NULL
++ },
++ {
++ ROSE_QSIG_CfnrDivertedLegFailed, NULL, 23,
++ rose_enc_qsig_DummyArg_ARG, NULL,
++ rose_dec_qsig_DummyArg_ARG, NULL
++ },
++
++ /*
++ * localValue's from Q.SIG SS-MWI-Operations
++ * { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
++ */
++ {
++ ROSE_QSIG_MWIActivate, NULL, 80,
++ rose_enc_qsig_MWIActivate_ARG, rose_enc_qsig_DummyRes_RES,
++ rose_dec_qsig_MWIActivate_ARG, rose_dec_qsig_DummyRes_RES
++ },
++ {
++ ROSE_QSIG_MWIDeactivate, NULL, 81,
++ rose_enc_qsig_MWIDeactivate_ARG, rose_enc_qsig_DummyRes_RES,
++ rose_dec_qsig_MWIDeactivate_ARG, rose_dec_qsig_DummyRes_RES
++ },
++ {
++ ROSE_QSIG_MWIInterrogate, NULL, 82,
++ rose_enc_qsig_MWIInterrogate_ARG, rose_enc_qsig_MWIInterrogate_RES,
++ rose_dec_qsig_MWIInterrogate_ARG, rose_dec_qsig_MWIInterrogate_RES
++ },
++/* *INDENT-ON* */
++};
++
++
++/*! \brief Q.SIG specific error-value converion table */
++static const struct rose_convert_error rose_qsig_errors[] = {
++/* *INDENT-OFF* */
++/*
++ * error-code, oid_prefix, value
++ * encode_error_args, decode_error_args
++ */
++ /*
++ * localValue Errors from General-Error-List
++ * {ccitt identified-organization q 950 general-error-list(1)}
++ */
++ {
++ ROSE_ERROR_Gen_NotSubscribed, NULL, 0,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_RejectedByNetwork, NULL, 1,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_RejectedByUser, NULL, 2,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_NotAvailable, NULL, 3,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_InsufficientInformation, NULL, 5,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_InvalidServedUserNr, NULL, 6,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_InvalidCallState, NULL, 7,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_BasicServiceNotProvided, NULL, 8,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_NotIncomingCall, NULL, 9,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_ResourceUnavailable, NULL, 11,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_CallFailure, NULL, 25,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_ProceduralError, NULL, 43,
++ NULL, NULL
++ },
++
++ /*
++ * From various Q.SIG specifications.
++ * We will ignore the manufacturer specific extension information.
++ */
++ {
++ ROSE_ERROR_QSIG_Unspecified, NULL, 1008,
++ NULL, NULL
++ },
++
++ /*
++ * localValue Errors from Q.SIG SS-AOC-Operations
++ * { iso(1) standard(0) pss1-advice-of-charge(15050) advice-of-charge-operations(0) }
++ */
++ {
++ ROSE_ERROR_QSIG_AOC_FreeOfCharge, NULL, 1016,
++ NULL, NULL
++ },
++
++ /*
++ * localValue's from Q.SIG Call-Transfer-Operations
++ * { iso(1) standard(0) pss1-call-transfer(13869) call-transfer-operations(0) }
++ */
++ {
++ ROSE_ERROR_QSIG_CT_InvalidReroutingNumber, NULL, 1004,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_QSIG_CT_UnrecognizedCallIdentity,NULL, 1005,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_QSIG_CT_EstablishmentFailure, NULL, 1006,
++ NULL, NULL
++ },
++
++ /*
++ * localValue's from Q.SIG Call-Diversion-Operations
++ * { iso(1) standard(0) pss1-call-diversion(13873) call-diversion-operations(0) }
++ */
++ {
++ ROSE_ERROR_Div_InvalidDivertedToNr, NULL, 12,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_SpecialServiceNr, NULL, 14,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_DiversionToServedUserNr, NULL, 15,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Div_NumberOfDiversionsExceeded, NULL, 24,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_QSIG_Div_TemporarilyUnavailable, NULL, 1000,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_QSIG_Div_NotAuthorized, NULL, 1007,
++ NULL, NULL
++ },
++
++ /*
++ * localValue's from Q.SIG SS-MWI-Operations
++ * { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
++ */
++ {
++ ROSE_ERROR_QSIG_InvalidMsgCentreId, NULL, 1018,
++ NULL, NULL
++ },
++/* *INDENT-ON* */
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*! \brief DMS-100 specific invoke/result encode/decode message table */
++static const struct rose_convert_msg rose_dms100_msgs[] = {
++/* *INDENT-OFF* */
++/*
++ * operation, oid_prefix, value,
++ * encode_invoke_args, encode_result_args,
++ * decode_invoke_args, decode_result_args
++ */
++ {
++ ROSE_DMS100_RLT_OperationInd, NULL, ROSE_DMS100_RLT_OPERATION_IND,
++ NULL, rose_enc_dms100_RLT_OperationInd_RES,
++ NULL, rose_dec_dms100_RLT_OperationInd_RES
++ },
++ {
++ ROSE_DMS100_RLT_ThirdParty, NULL, ROSE_DMS100_RLT_THIRD_PARTY,
++ rose_enc_dms100_RLT_ThirdParty_ARG, NULL,
++ rose_dec_dms100_RLT_ThirdParty_ARG, NULL
++ },
++/* *INDENT-ON* */
++};
++
++
++/*! \brief DMS-100 specific error-value converion table */
++static const struct rose_convert_error rose_dms100_errors[] = {
++/* *INDENT-OFF* */
++/*
++ * error-code, oid_prefix, value
++ * encode_error_args, decode_error_args
++ */
++ {
++ ROSE_ERROR_DMS100_RLT_BridgeFail, NULL, 0x10,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_DMS100_RLT_CallIDNotFound, NULL, 0x11,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_DMS100_RLT_NotAllowed, NULL, 0x12,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_DMS100_RLT_SwitchEquipCongs, NULL, 0x13,
++ NULL, NULL
++ },
++/* *INDENT-ON* */
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * Note the first value in oid.values[] is really the first two
++ * OID subidentifiers. They are compressed using this formula:
++ * First_Value = (First_Subidentifier * 40) + Second_Subidentifier
++ */
++
++static const struct asn1_oid rose_ni2_oid = {
++/* *INDENT-OFF* */
++ /* { iso(1) member-body(2) usa(840) ansi-t1(10005) operations(0) } */
++ 4, { 42, 840, 10005, 0 }
++/* *INDENT-ON* */
++};
++
++/*! \brief NI2 specific invoke/result encode/decode message table */
++static const struct rose_convert_msg rose_ni2_msgs[] = {
++/* *INDENT-OFF* */
++/*
++ * operation, oid_prefix, value,
++ * encode_invoke_args, encode_result_args,
++ * decode_invoke_args, decode_result_args
++ */
++ /* NI2 seems to have pirated several Q.SIG messages */
++ /*
++ * localValue's from Q.SIG Name-Operations
++ * { iso(1) standard(0) pss1-name(13868) name-operations(0) }
++ */
++ {
++ ROSE_QSIG_CallingName, NULL, 0,
++ rose_enc_qsig_CallingName_ARG, NULL,
++ rose_dec_qsig_CallingName_ARG, NULL
++ },
++ {
++ ROSE_QSIG_CalledName, NULL, 1,
++ rose_enc_qsig_CalledName_ARG, NULL,
++ rose_dec_qsig_CalledName_ARG, NULL
++ },
++ {
++ ROSE_QSIG_ConnectedName, NULL, 2,
++ rose_enc_qsig_ConnectedName_ARG, NULL,
++ rose_dec_qsig_ConnectedName_ARG, NULL
++ },
++ {
++ ROSE_QSIG_BusyName, NULL, 3,
++ rose_enc_qsig_BusyName_ARG, NULL,
++ rose_dec_qsig_BusyName_ARG, NULL
++ },
++
++ {
++ ROSE_NI2_InformationFollowing, &rose_ni2_oid, 4,
++ rose_enc_ni2_InformationFollowing_ARG, NULL,
++ rose_dec_ni2_InformationFollowing_ARG, NULL
++ },
++
++ /* Also used by PRI_SWITCH_ATT4ESS and PRI_SWITCH_LUCENT5E */
++ {
++ ROSE_NI2_InitiateTransfer, &rose_ni2_oid, 8,
++ rose_enc_ni2_InitiateTransfer_ARG, NULL,
++ rose_dec_ni2_InitiateTransfer_ARG, NULL
++ },
++/* *INDENT-ON* */
++};
++
++
++/*! \brief NI2 specific error-value converion table */
++static const struct rose_convert_error rose_ni2_errors[] = {
++/* *INDENT-OFF* */
++/*
++ * error-code, oid_prefix, value
++ * encode_error_args, decode_error_args
++ */
++ /*
++ * localValue Errors from General-Error-List
++ * {ccitt identified-organization q 950 general-error-list(1)}
++ */
++ {
++ ROSE_ERROR_Gen_NotSubscribed, NULL, 0,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_RejectedByNetwork, NULL, 1,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_RejectedByUser, NULL, 2,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_NotAvailable, NULL, 3,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_InsufficientInformation, NULL, 5,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_InvalidServedUserNr, NULL, 6,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_InvalidCallState, NULL, 7,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_BasicServiceNotProvided, NULL, 8,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_NotIncomingCall, NULL, 9,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,NULL, 10,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_ResourceUnavailable, NULL, 11,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_CallFailure, NULL, 25,
++ NULL, NULL
++ },
++ {
++ ROSE_ERROR_Gen_ProceduralError, NULL, 43,
++ NULL, NULL
++ },
++/* *INDENT-ON* */
++};
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Convert the given code value to a string.
++ *
++ * \param code Code value to convert to a string.
++ * \param arr Array to convert the code to a string.
++ * \param num_elements Number of elements in the conversion array.
++ *
++ * \retval String version of the given code value.
++ */
++static const char *rose_code2str(int code, const struct rose_code_strings *arr,
++ unsigned num_elements)
++{
++ static char invalid_code[40];
++
++ unsigned index;
++
++ for (index = 0; index < num_elements; ++index) {
++ if (arr[index].code == code) {
++ return arr[index].name;
++ }
++ }
++
++ snprintf(invalid_code, sizeof(invalid_code), "Invalid code:%d 0x%X", code, code);
++ return invalid_code;
++}
++
++/*!
++ * \brief Convert the given operation-value to a string.
++ *
++ * \param operation Operation-value to convert to a string.
++ *
++ * \retval String version of the given operation-value.
++ */
++const char *rose_operation2str(enum rose_operation operation)
++{
++ static const struct rose_code_strings arr[] = {
++/* *INDENT-OFF* */
++ { ROSE_None, "ROSE_None" },
++ { ROSE_Unknown, "ROSE_Unknown" },
++
++ { ROSE_ETSI_ActivationDiversion, "ROSE_ETSI_ActivationDiversion" },
++ { ROSE_ETSI_DeactivationDiversion, "ROSE_ETSI_DeactivationDiversion" },
++ { ROSE_ETSI_ActivationStatusNotificationDiv,"ROSE_ETSI_ActivationStatusNotificationDiv" },
++ { ROSE_ETSI_DeactivationStatusNotificationDiv,"ROSE_ETSI_DeactivationStatusNotificationDiv" },
++ { ROSE_ETSI_InterrogationDiversion, "ROSE_ETSI_InterrogationDiversion" },
++ { ROSE_ETSI_DiversionInformation, "ROSE_ETSI_DiversionInformation" },
++ { ROSE_ETSI_CallDeflection, "ROSE_ETSI_CallDeflection" },
++ { ROSE_ETSI_CallRerouting, "ROSE_ETSI_CallRerouting" },
++ { ROSE_ETSI_DivertingLegInformation2, "ROSE_ETSI_DivertingLegInformation2" },
++ { ROSE_ETSI_InterrogateServedUserNumbers, "ROSE_ETSI_InterrogateServedUserNumbers" },
++ { ROSE_ETSI_DivertingLegInformation1, "ROSE_ETSI_DivertingLegInformation1" },
++ { ROSE_ETSI_DivertingLegInformation3, "ROSE_ETSI_DivertingLegInformation3" },
++
++ { ROSE_ETSI_EctExecute, "ROSE_ETSI_EctExecute" },
++ { ROSE_ETSI_ExplicitEctExecute, "ROSE_ETSI_ExplicitEctExecute" },
++ { ROSE_ETSI_RequestSubaddress, "ROSE_ETSI_RequestSubaddress" },
++ { ROSE_ETSI_SubaddressTransfer, "ROSE_ETSI_SubaddressTransfer" },
++ { ROSE_ETSI_EctLinkIdRequest, "ROSE_ETSI_EctLinkIdRequest" },
++ { ROSE_ETSI_EctInform, "ROSE_ETSI_EctInform" },
++ { ROSE_ETSI_EctLoopTest, "ROSE_ETSI_EctLoopTest" },
++
++ { ROSE_ETSI_ChargingRequest, "ROSE_ETSI_ChargingRequest" },
++ { ROSE_ETSI_AOCSCurrency, "ROSE_ETSI_AOCSCurrency" },
++ { ROSE_ETSI_AOCSSpecialArr, "ROSE_ETSI_AOCSSpecialArr" },
++ { ROSE_ETSI_AOCDCurrency, "ROSE_ETSI_AOCDCurrency" },
++ { ROSE_ETSI_AOCDChargingUnit, "ROSE_ETSI_AOCDChargingUnit" },
++ { ROSE_ETSI_AOCECurrency, "ROSE_ETSI_AOCECurrency" },
++ { ROSE_ETSI_AOCEChargingUnit, "ROSE_ETSI_AOCEChargingUnit" },
++
++ { ROSE_QSIG_CallingName, "ROSE_QSIG_CallingName" },
++ { ROSE_QSIG_CalledName, "ROSE_QSIG_CalledName" },
++ { ROSE_QSIG_ConnectedName, "ROSE_QSIG_ConnectedName" },
++ { ROSE_QSIG_BusyName, "ROSE_QSIG_BusyName" },
++
++ { ROSE_QSIG_ChargeRequest, "ROSE_QSIG_ChargeRequest" },
++ { ROSE_QSIG_GetFinalCharge, "ROSE_QSIG_GetFinalCharge" },
++ { ROSE_QSIG_AocFinal, "ROSE_QSIG_AocFinal" },
++ { ROSE_QSIG_AocInterim, "ROSE_QSIG_AocInterim" },
++ { ROSE_QSIG_AocRate, "ROSE_QSIG_AocRate" },
++ { ROSE_QSIG_AocComplete, "ROSE_QSIG_AocComplete" },
++ { ROSE_QSIG_AocDivChargeReq, "ROSE_QSIG_AocDivChargeReq" },
++
++ { ROSE_QSIG_CallTransferIdentify, "ROSE_QSIG_CallTransferIdentify" },
++ { ROSE_QSIG_CallTransferAbandon, "ROSE_QSIG_CallTransferAbandon" },
++ { ROSE_QSIG_CallTransferInitiate, "ROSE_QSIG_CallTransferInitiate" },
++ { ROSE_QSIG_CallTransferSetup, "ROSE_QSIG_CallTransferSetup" },
++ { ROSE_QSIG_CallTransferActive, "ROSE_QSIG_CallTransferActive" },
++ { ROSE_QSIG_CallTransferComplete, "ROSE_QSIG_CallTransferComplete" },
++ { ROSE_QSIG_CallTransferUpdate, "ROSE_QSIG_CallTransferUpdate" },
++ { ROSE_QSIG_SubaddressTransfer, "ROSE_QSIG_SubaddressTransfer" },
++
++ { ROSE_QSIG_PathReplacement, "ROSE_QSIG_PathReplacement" },
++
++ { ROSE_QSIG_ActivateDiversionQ, "ROSE_QSIG_ActivateDiversionQ" },
++ { ROSE_QSIG_DeactivateDiversionQ, "ROSE_QSIG_DeactivateDiversionQ" },
++ { ROSE_QSIG_InterrogateDiversionQ, "ROSE_QSIG_InterrogateDiversionQ" },
++ { ROSE_QSIG_CheckRestriction, "ROSE_QSIG_CheckRestriction" },
++ { ROSE_QSIG_CallRerouting, "ROSE_QSIG_CallRerouting" },
++ { ROSE_QSIG_DivertingLegInformation1, "ROSE_QSIG_DivertingLegInformation1" },
++ { ROSE_QSIG_DivertingLegInformation2, "ROSE_QSIG_DivertingLegInformation2" },
++ { ROSE_QSIG_DivertingLegInformation3, "ROSE_QSIG_DivertingLegInformation3" },
++ { ROSE_QSIG_CfnrDivertedLegFailed, "ROSE_QSIG_CfnrDivertedLegFailed" },
++
++ { ROSE_QSIG_MWIActivate, "ROSE_QSIG_MWIActivate" },
++ { ROSE_QSIG_MWIDeactivate, "ROSE_QSIG_MWIDeactivate" },
++ { ROSE_QSIG_MWIInterrogate, "ROSE_QSIG_MWIInterrogate" },
++
++ { ROSE_DMS100_RLT_OperationInd, "ROSE_DMS100_RLT_OperationInd" },
++ { ROSE_DMS100_RLT_ThirdParty, "ROSE_DMS100_RLT_ThirdParty" },
++
++ { ROSE_NI2_InformationFollowing, "ROSE_NI2_InformationFollowing" },
++ { ROSE_NI2_InitiateTransfer, "ROSE_NI2_InitiateTransfer" },
++/* *INDENT-ON* */
++ };
++
++ return rose_code2str(operation, arr, ARRAY_LEN(arr));
++}
++
++/*!
++ * \brief Convert the given error-value to a string.
++ *
++ * \param code Error-value to convert to a string.
++ *
++ * \retval String version of the given error-value.
++ */
++const char *rose_error2str(enum rose_error_code code)
++{
++ static const struct rose_code_strings arr[] = {
++/* *INDENT-OFF* */
++ { ROSE_ERROR_None, "No error occurred" },
++ { ROSE_ERROR_Unknown, "Unknown error-value code" },
++
++ { ROSE_ERROR_Gen_NotSubscribed, "General: Not Subscribed" },
++ { ROSE_ERROR_Gen_NotAvailable, "General: Not Available" },
++ { ROSE_ERROR_Gen_NotImplemented, "General: Not Implemented" },
++ { ROSE_ERROR_Gen_InvalidServedUserNr, "General: Invalid Served User Number" },
++ { ROSE_ERROR_Gen_InvalidCallState, "General: Invalid Call State" },
++ { ROSE_ERROR_Gen_BasicServiceNotProvided, "General: Basic Service Not Provided" },
++ { ROSE_ERROR_Gen_NotIncomingCall, "General: Not Incoming Call" },
++ { ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
++ { ROSE_ERROR_Gen_ResourceUnavailable, "General: Resource Unavailable" },
++
++ /* Additional Q.950 General-Errors for Q.SIG */
++ { ROSE_ERROR_Gen_RejectedByNetwork, "General: Rejected By Network" },
++ { ROSE_ERROR_Gen_RejectedByUser, "General: Rejected By User" },
++ { ROSE_ERROR_Gen_InsufficientInformation, "General: Insufficient Information" },
++ { ROSE_ERROR_Gen_CallFailure, "General: Call Failure" },
++ { ROSE_ERROR_Gen_ProceduralError, "General: Procedural Error" },
++
++ { ROSE_ERROR_Div_InvalidDivertedToNr, "Diversion: Invalid Diverted To Number" },
++ { ROSE_ERROR_Div_SpecialServiceNr, "Diversion: Special Service Number" },
++ { ROSE_ERROR_Div_DiversionToServedUserNr, "Diversion: Diversion To Served User Number" },
++ { ROSE_ERROR_Div_IncomingCallAccepted, "Diversion: Incoming Call Accepted" },
++ { ROSE_ERROR_Div_NumberOfDiversionsExceeded, "Diversion: Number Of Diversions Exceeded" },
++ { ROSE_ERROR_Div_NotActivated, "Diversion: Not Activated" },
++ { ROSE_ERROR_Div_RequestAlreadyAccepted, "Diversion: Request Already Accepted" },
++
++ { ROSE_ERROR_AOC_NoChargingInfoAvailable, "AOC: No Charging Info Available" },
++
++ { ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
++
++ /* Q.SIG specific errors */
++ { ROSE_ERROR_QSIG_Unspecified, "Unspecified" },
++
++ { ROSE_ERROR_QSIG_AOC_FreeOfCharge, "AOC: FreeOfCharge" },
++
++ { ROSE_ERROR_QSIG_CT_InvalidReroutingNumber, "CT: Invalid Rerouting Number" },
++ { ROSE_ERROR_QSIG_CT_UnrecognizedCallIdentity,"CT: Unrecognized Call Identity" },
++ { ROSE_ERROR_QSIG_CT_EstablishmentFailure, "CT: Establishment Failure" },
++
++ { ROSE_ERROR_QSIG_Div_TemporarilyUnavailable, "Diversion: Temporarily Unavailable" },
++ { ROSE_ERROR_QSIG_Div_NotAuthorized, "Diversion: Not Authorized" },
++
++ { ROSE_ERROR_QSIG_InvalidMsgCentreId, "MWI: Invalid Message Center ID" },
++
++ /* DMS-100 specific errors */
++ { ROSE_ERROR_DMS100_RLT_BridgeFail, "RLT: Bridge Fail" },
++ { ROSE_ERROR_DMS100_RLT_CallIDNotFound, "RLT: Call ID Not Found" },
++ { ROSE_ERROR_DMS100_RLT_NotAllowed, "RLT: Not Allowed" },
++ { ROSE_ERROR_DMS100_RLT_SwitchEquipCongs, "RLT: Switch Equip Congs" },
++/* *INDENT-ON* */
++ };
++
++ return rose_code2str(code, arr, ARRAY_LEN(arr));
++}
++
++/*!
++ * \brief Convert the given reject problem-value to a string.
++ *
++ * \param code Reject problem-value to convert to a string.
++ *
++ * \retval String version of the given reject problem-value.
++ */
++const char *rose_reject2str(enum rose_reject_code code)
++{
++ static const struct rose_code_strings arr[] = {
++/* *INDENT-OFF* */
++ { ROSE_REJECT_None, "No reject occurred" },
++ { ROSE_REJECT_Unknown, "Unknown reject code" },
++
++ { ROSE_REJECT_Gen_UnrecognizedComponent, "General: Unrecognized Component" },
++ { ROSE_REJECT_Gen_MistypedComponent, "General: Mistyped Component" },
++ { ROSE_REJECT_Gen_BadlyStructuredComponent, "General: Badly Structured Component" },
++
++ { ROSE_REJECT_Inv_DuplicateInvocation, "Invoke: Duplicate Invocation" },
++ { ROSE_REJECT_Inv_UnrecognizedOperation, "Invoke: Unrecognized Operation" },
++ { ROSE_REJECT_Inv_MistypedArgument, "Invoke: Mistyped Argument" },
++ { ROSE_REJECT_Inv_ResourceLimitation, "Invoke: Resource Limitation" },
++ { ROSE_REJECT_Inv_InitiatorReleasing, "Invoke: Initiator Releasing" },
++ { ROSE_REJECT_Inv_UnrecognizedLinkedID, "Invoke: Unrecognized Linked ID" },
++ { ROSE_REJECT_Inv_LinkedResponseUnexpected, "Invoke: Linked Response Unexpected" },
++ { ROSE_REJECT_Inv_UnexpectedChildOperation, "Invoke: Unexpected Child Operation" },
++
++ { ROSE_REJECT_Res_UnrecognizedInvocation, "Result: Unrecognized Invocation" },
++ { ROSE_REJECT_Res_ResultResponseUnexpected, "Result: Result Response Unexpected" },
++ { ROSE_REJECT_Res_MistypedResult, "Result: Mistyped Result" },
++
++ { ROSE_REJECT_Err_UnrecognizedInvocation, "Error: Unrecognized Invocation" },
++ { ROSE_REJECT_Err_ErrorResponseUnexpected, "Error: Error Response Unexpected" },
++ { ROSE_REJECT_Err_UnrecognizedError, "Error: Unrecognized Error" },
++ { ROSE_REJECT_Err_UnexpectedError, "Error: Unexpected Error" },
++ { ROSE_REJECT_Err_MistypedParameter, "Error: Mistyped Parameter" },
++/* *INDENT-ON* */
++ };
++
++ return rose_code2str(code, arr, ARRAY_LEN(arr));
++}
++
++/*!
++ * \internal
++ * \brief Find an operation message conversion entry using the operation code.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param operation Library operation-value code.
++ *
++ * \retval Message conversion entry on success.
++ * \retval NULL on error.
++ */
++static const struct rose_convert_msg *rose_find_msg_by_op_code(struct pri *ctrl,
++ enum rose_operation operation)
++{
++ const struct rose_convert_msg *found;
++ const struct rose_convert_msg *table;
++ size_t num_entries;
++ size_t index;
++
++ /* Determine which message conversion table to use */
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_T1:
++ case PRI_SWITCH_EUROISDN_E1:
++ table = rose_etsi_msgs;
++ num_entries = ARRAY_LEN(rose_etsi_msgs);
++ break;
++ case PRI_SWITCH_QSIG:
++ table = rose_qsig_msgs;
++ num_entries = ARRAY_LEN(rose_qsig_msgs);
++ break;
++ case PRI_SWITCH_DMS100:
++ table = rose_dms100_msgs;
++ num_entries = ARRAY_LEN(rose_dms100_msgs);
++ break;
++ case PRI_SWITCH_ATT4ESS:
++ case PRI_SWITCH_LUCENT5E:
++ case PRI_SWITCH_NI2:
++ table = rose_ni2_msgs;
++ num_entries = ARRAY_LEN(rose_ni2_msgs);
++ break;
++ default:
++ return NULL;
++ }
++
++ /* Search for the table entry */
++ found = NULL;
++ for (index = 0; index < num_entries; ++index) {
++ if (table[index].operation == operation) {
++ found = &table[index];
++ break;
++ }
++ }
++
++ return found;
++}
++
++/*!
++ * \internal
++ * \brief Find an operation message conversion entry using the
++ * operation-value OID value or localValue.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param oid Search for the full OID if not NULL.
++ * \param local Search for the localValue if OID is NULL.
++ *
++ * \retval Message conversion entry on success.
++ * \retval NULL on error.
++ */
++static const struct rose_convert_msg *rose_find_msg_by_op_val(struct pri *ctrl,
++ const struct asn1_oid *oid, unsigned local)
++{
++ const struct rose_convert_msg *found;
++ const struct rose_convert_msg *table;
++ size_t num_entries;
++ size_t index;
++ int sub_index;
++
++ /* Determine which message conversion table to use */
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_T1:
++ case PRI_SWITCH_EUROISDN_E1:
++ table = rose_etsi_msgs;
++ num_entries = ARRAY_LEN(rose_etsi_msgs);
++ break;
++ case PRI_SWITCH_QSIG:
++ table = rose_qsig_msgs;
++ num_entries = ARRAY_LEN(rose_qsig_msgs);
++ break;
++ case PRI_SWITCH_DMS100:
++ table = rose_dms100_msgs;
++ num_entries = ARRAY_LEN(rose_dms100_msgs);
++ break;
++ case PRI_SWITCH_ATT4ESS:
++ case PRI_SWITCH_LUCENT5E:
++ case PRI_SWITCH_NI2:
++ table = rose_ni2_msgs;
++ num_entries = ARRAY_LEN(rose_ni2_msgs);
++ break;
++ default:
++ return NULL;
++ }
++
++ /* Search for the table entry */
++ found = NULL;
++ if (oid) {
++ /* Search for an OID entry */
++ local = oid->value[oid->num_values - 1];
++ for (index = 0; index < num_entries; ++index) {
++ if (table[index].value == local && table[index].oid_prefix
++ && table[index].oid_prefix->num_values == oid->num_values - 1) {
++ /* Now lets match the OID prefix subidentifiers */
++ for (sub_index = oid->num_values - 2; 0 <= sub_index; --sub_index) {
++ if (oid->value[sub_index]
++ != table[index].oid_prefix->value[sub_index]) {
++ break;
++ }
++ }
++ if (sub_index == -1) {
++ /* All of the OID subidentifiers matched */
++ found = &table[index];
++ break;
++ }
++ }
++ }
++ } else {
++ /* Search for a localValue entry */
++ for (index = 0; index < num_entries; ++index) {
++ if (table[index].value == local && !table[index].oid_prefix) {
++ found = &table[index];
++ break;
++ }
++ }
++ }
++
++ return found;
++}
++
++/*!
++ * \internal
++ * \brief Find an error conversion entry using the error code.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param code Library error-value code.
++ *
++ * \retval Error conversion entry on success.
++ * \retval NULL on error.
++ */
++static const struct rose_convert_error *rose_find_error_by_op_code(struct pri *ctrl,
++ enum rose_error_code code)
++{
++ const struct rose_convert_error *found;
++ const struct rose_convert_error *table;
++ size_t num_entries;
++ size_t index;
++
++ /* Determine which error conversion table to use */
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_T1:
++ case PRI_SWITCH_EUROISDN_E1:
++ table = rose_etsi_errors;
++ num_entries = ARRAY_LEN(rose_etsi_errors);
++ break;
++ case PRI_SWITCH_QSIG:
++ table = rose_qsig_errors;
++ num_entries = ARRAY_LEN(rose_qsig_errors);
++ break;
++ case PRI_SWITCH_DMS100:
++ table = rose_dms100_errors;
++ num_entries = ARRAY_LEN(rose_dms100_errors);
++ break;
++ case PRI_SWITCH_ATT4ESS:
++ case PRI_SWITCH_LUCENT5E:
++ case PRI_SWITCH_NI2:
++ table = rose_ni2_errors;
++ num_entries = ARRAY_LEN(rose_ni2_errors);
++ break;
++ default:
++ return NULL;
++ }
++
++ /* Search for the table entry */
++ found = NULL;
++ for (index = 0; index < num_entries; ++index) {
++ if (table[index].code == code) {
++ found = &table[index];
++ break;
++ }
++ }
++
++ return found;
++}
++
++/*!
++ * \internal
++ * \brief Find an error conversion entry using the
++ * error-value OID value or localValue.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param oid Search for the full OID if not NULL.
++ * \param local Search for the localValue if OID is NULL.
++ *
++ * \retval Error conversion entry on success.
++ * \retval NULL on error.
++ */
++static const struct rose_convert_error *rose_find_error_by_op_val(struct pri *ctrl,
++ const struct asn1_oid *oid, unsigned local)
++{
++ const struct rose_convert_error *found;
++ const struct rose_convert_error *table;
++ size_t num_entries;
++ size_t index;
++ int sub_index;
++
++ /* Determine which error conversion table to use */
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_T1:
++ case PRI_SWITCH_EUROISDN_E1:
++ table = rose_etsi_errors;
++ num_entries = ARRAY_LEN(rose_etsi_errors);
++ break;
++ case PRI_SWITCH_QSIG:
++ table = rose_qsig_errors;
++ num_entries = ARRAY_LEN(rose_qsig_errors);
++ break;
++ case PRI_SWITCH_DMS100:
++ table = rose_dms100_errors;
++ num_entries = ARRAY_LEN(rose_dms100_errors);
++ break;
++ case PRI_SWITCH_ATT4ESS:
++ case PRI_SWITCH_LUCENT5E:
++ case PRI_SWITCH_NI2:
++ table = rose_ni2_errors;
++ num_entries = ARRAY_LEN(rose_ni2_errors);
++ break;
++ default:
++ return NULL;
++ }
++
++ /* Search for the table entry */
++ found = NULL;
++ if (oid) {
++ /* Search for an OID entry */
++ local = oid->value[oid->num_values - 1];
++ for (index = 0; index < num_entries; ++index) {
++ if (table[index].value == local && table[index].oid_prefix
++ && table[index].oid_prefix->num_values == oid->num_values - 1) {
++ /* Now lets match the OID prefix subidentifiers */
++ for (sub_index = oid->num_values - 2; 0 <= sub_index; --sub_index) {
++ if (oid->value[sub_index]
++ != table[index].oid_prefix->value[sub_index]) {
++ break;
++ }
++ }
++ if (sub_index == -1) {
++ /* All of the OID subidentifiers matched */
++ found = &table[index];
++ break;
++ }
++ }
++ }
++ } else {
++ /* Search for a localValue entry */
++ for (index = 0; index < num_entries; ++index) {
++ if (table[index].value == local && !table[index].oid_prefix) {
++ found = &table[index];
++ break;
++ }
++ }
++ }
++
++ return found;
++}
++
++/*!
++ * \internal
++ * \brief Encode the Facility ie component operation-value.
++ *
++ * \param pos Starting position to encode the operation-value.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param oid_prefix Encode as an OID if not NULL.
++ * \param local Encode as a localValue if oid_prefix is NULL
++ * else it is the last OID subidentifier.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_operation_value(unsigned char *pos, unsigned char *end,
++ const struct asn1_oid *oid_prefix, unsigned local)
++{
++ struct asn1_oid oid;
++
++ if (oid_prefix) {
++ if (ARRAY_LEN(oid_prefix->value) <= oid_prefix->num_values) {
++ return NULL;
++ }
++ oid = *oid_prefix;
++ oid.value[oid.num_values++] = local;
++ return asn1_enc_oid(pos, end, ASN1_TYPE_OBJECT_IDENTIFIER, &oid);
++ } else {
++ return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, local);
++ }
++}
++
++/*! \brief Mapped to rose_enc_operation_value() */
++#define rose_enc_error_value(pos, end, oid_prefix, local) \
++ rose_enc_operation_value(pos, end, oid_prefix, local)
++
++/*!
++ * \brief Encode the invoke component for a ROSE message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 message.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param msg ROSE invoke message to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_encode_invoke(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rose_msg_invoke *msg)
++{
++ const struct rose_convert_msg *convert;
++ unsigned char *seq_len;
++
++ convert = rose_find_msg_by_op_code(ctrl, msg->operation);
++ if (!convert) {
++ return NULL;
++ }
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_INVOKE);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
++ if (msg->linked_id_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ msg->linked_id));
++ }
++ ASN1_CALL(pos, rose_enc_operation_value(pos, end, convert->oid_prefix,
++ convert->value));
++
++ if (convert->encode_invoke_args) {
++ ASN1_CALL(pos, convert->encode_invoke_args(ctrl, pos, end, &msg->args));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the result component for a ROSE message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 message.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param msg ROSE result message to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_encode_result(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rose_msg_result *msg)
++{
++ const struct rose_convert_msg *convert;
++ unsigned char *seq_len;
++ unsigned char *op_seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_RESULT);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
++
++ if (msg->operation != ROSE_None) {
++ convert = rose_find_msg_by_op_code(ctrl, msg->operation);
++ if (!convert) {
++ return NULL;
++ }
++
++ ASN1_CONSTRUCTED_BEGIN(op_seq_len, pos, end, ASN1_TYPE_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_operation_value(pos, end, convert->oid_prefix,
++ convert->value));
++
++ if (convert->encode_result_args) {
++ ASN1_CALL(pos, convert->encode_result_args(ctrl, pos, end, &msg->args));
++ }
++
++ ASN1_CONSTRUCTED_END(op_seq_len, pos, end);
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the error component for a ROSE message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 message.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param msg ROSE error message to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_encode_error(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rose_msg_error *msg)
++{
++ const struct rose_convert_error *convert;
++ unsigned char *seq_len;
++
++ convert = rose_find_error_by_op_code(ctrl, msg->code);
++ if (!convert) {
++ return NULL;
++ }
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_ERROR);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
++ ASN1_CALL(pos, rose_enc_error_value(pos, end, convert->oid_prefix, convert->value));
++ if (convert->encode_error_args) {
++ ASN1_CALL(pos, convert->encode_error_args(ctrl, pos, end, &msg->args));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the reject component for a ROSE message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 message.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param msg ROSE reject message to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_encode_reject(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rose_msg_reject *msg)
++{
++ unsigned char *seq_len;
++ unsigned tag;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ROSE_TAG_COMPONENT_REJECT);
++
++ /* Encode Invoke ID */
++ if (msg->invoke_id_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg->invoke_id));
++ } else {
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ }
++
++ /* Encode the reject problem */
++ switch (msg->code & ~0xFF) {
++ case ROSE_REJECT_BASE(ROSE_REJECT_BASE_General):
++ tag = ASN1_CLASS_CONTEXT_SPECIFIC | 0;
++ break;
++ case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke):
++ tag = ASN1_CLASS_CONTEXT_SPECIFIC | 1;
++ break;
++ case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result):
++ tag = ASN1_CLASS_CONTEXT_SPECIFIC | 2;
++ break;
++ case ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error):
++ tag = ASN1_CLASS_CONTEXT_SPECIFIC | 3;
++ break;
++ default:
++ return NULL;
++ }
++ ASN1_CALL(pos, asn1_enc_int(pos, end, tag, msg->code & 0xFF));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the ROSE message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 message.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param msg ROSE message to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ *
++ * \note This function only encodes the ROSE contents. It does not include
++ * the protocol profile, NFE, NPP, and interpretation octets defined in
++ * a facility ie that may precede the ROSE contents. These header octets
++ * may already be stored in the encompassing buffer before the starting
++ * position given here.
++ */
++unsigned char *rose_encode(struct pri *ctrl, unsigned char *pos, unsigned char *end,
++ const struct rose_message *msg)
++{
++ switch (msg->type) {
++ case ROSE_COMP_TYPE_INVOKE:
++ pos = rose_encode_invoke(ctrl, pos, end, &msg->component.invoke);
++ break;
++ case ROSE_COMP_TYPE_RESULT:
++ pos = rose_encode_result(ctrl, pos, end, &msg->component.result);
++ break;
++ case ROSE_COMP_TYPE_ERROR:
++ pos = rose_encode_error(ctrl, pos, end, &msg->component.error);
++ break;
++ case ROSE_COMP_TYPE_REJECT:
++ pos = rose_encode_reject(ctrl, pos, end, &msg->component.reject);
++ break;
++ default:
++ pos = NULL;
++ break;
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the NetworkFacilityExtension type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param nfe Network Facility Extension information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *fac_enc_nfe(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct facNetworkFacilityExtension *nfe)
++{
++ unsigned char *seq_len;
++ unsigned char *explicit_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 10);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ nfe->source_entity));
++ if (nfe->source_number.length) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &nfe->source_number));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ nfe->destination_entity));
++ if (nfe->destination_number.length) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &nfe->destination_number));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the facility extension header.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param header Facility extension information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *fac_enc_extension_header(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct fac_extension_header *header)
++{
++ if (header->nfe_present) {
++ ASN1_CALL(pos, fac_enc_nfe(ctrl, pos, end, &header->nfe));
++ }
++ if (header->npp_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 18,
++ header->npp));
++ }
++ if (header->interpretation_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 11,
++ header->interpretation));
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the facility ie contents header.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode the facility ie contents.
++ * \param end End of facility ie contents encoding data buffer.
++ * \param header Facility extension header data to encode (NULL if none).
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *facility_encode_header(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct fac_extension_header *header)
++{
++ /* Make sure we have some room. */
++ if (end < pos + 2) {
++ return NULL;
++ }
++
++ switch (ctrl->switchtype) {
++ case PRI_SWITCH_EUROISDN_T1:
++ case PRI_SWITCH_EUROISDN_E1:
++ *pos++ = 0x80 | Q932_PROTOCOL_ROSE;
++ header = NULL;
++ break;
++ case PRI_SWITCH_QSIG:
++ *pos++ = 0x80 | Q932_PROTOCOL_EXTENSIONS;
++ break;
++ case PRI_SWITCH_DMS100:
++ *pos++ = Q932_PROTOCOL_ROSE; /* DON'T set the EXT bit yet. */
++ *pos++ = 0x80 | ROSE_DMS100_RLT_SERVICE_ID;
++ header = NULL;
++ break;
++ case PRI_SWITCH_ATT4ESS:
++ case PRI_SWITCH_LUCENT5E:
++ case PRI_SWITCH_NI2:
++ if (header) {
++ *pos++ = 0x80 | Q932_PROTOCOL_EXTENSIONS;
++ } else {
++ *pos++ = 0x80 | Q932_PROTOCOL_ROSE;
++ }
++ break;
++ default:
++ return NULL;
++ }
++
++ if (header) {
++ ASN1_CALL(pos, fac_enc_extension_header(ctrl, pos, end, header));
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the ROSE invoke message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param msg ROSE invoke message data to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_decode_invoke(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct rose_msg_invoke *msg)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const struct rose_convert_msg *convert;
++ struct asn1_oid oid;
++ unsigned local;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "INVOKE Component %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
++ msg->invoke_id = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | 0)) {
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "linkedId", tag, pos, seq_end, &value));
++ msg->linked_id = value;
++ msg->linked_id_present = 1;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ } else {
++ msg->linked_id_present = 0;
++ }
++
++ /* Decode operation-value */
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "operationValue", tag, pos, seq_end, &value));
++ local = value;
++ oid.num_values = 0;
++ break;
++ case ASN1_TYPE_OBJECT_IDENTIFIER:
++ ASN1_CALL(pos, asn1_dec_oid(ctrl, "operationValue", tag, pos, seq_end, &oid));
++ local = 0;
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++ convert = rose_find_msg_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
++ if (convert) {
++ msg->operation = convert->operation;
++ } else {
++ msg->operation = ROSE_Unknown;
++ }
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " operationValue = %s\n", rose_operation2str(msg->operation));
++ }
++
++ /* Decode any expected invoke arguments */
++ if (convert && convert->decode_invoke_args) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, convert->decode_invoke_args(ctrl, tag, pos, seq_end, &msg->args));
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the ROSE result message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param msg ROSE result message data to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_decode_result(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct rose_msg_result *msg)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int op_seq_offset;
++ const unsigned char *seq_end;
++ const unsigned char *op_seq_end;
++ const struct rose_convert_msg *convert;
++ struct asn1_oid oid;
++ unsigned local;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "RESULT Component %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
++ msg->invoke_id = value;
++
++ /* Decode optional operation sequence */
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " operation %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(op_seq_end, op_seq_offset, length, pos, seq_end);
++
++ /* Decode operation-value */
++ ASN1_CALL(pos, asn1_dec_tag(pos, op_seq_end, &tag));
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "operationValue", tag, pos, op_seq_end,
++ &value));
++ local = value;
++ oid.num_values = 0;
++ break;
++ case ASN1_TYPE_OBJECT_IDENTIFIER:
++ ASN1_CALL(pos, asn1_dec_oid(ctrl, "operationValue", tag, pos, op_seq_end,
++ &oid));
++ local = 0;
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++ convert =
++ rose_find_msg_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
++ if (convert) {
++ msg->operation = convert->operation;
++ } else {
++ msg->operation = ROSE_Unknown;
++ }
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " operationValue = %s\n",
++ rose_operation2str(msg->operation));
++ }
++
++ /* Decode any expected result arguments */
++ if (convert && convert->decode_result_args) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, op_seq_end, &tag));
++ ASN1_CALL(pos, convert->decode_result_args(ctrl, tag, pos, op_seq_end,
++ &msg->args));
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, op_seq_offset, op_seq_end, seq_end);
++ } else {
++ msg->operation = ROSE_None;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the ROSE error message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param msg ROSE error message data to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_decode_error(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct rose_msg_error *msg)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const struct rose_convert_error *convert;
++ struct asn1_oid oid;
++ unsigned local;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "ERROR Component %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
++ msg->invoke_id = value;
++
++ /* Decode error-value */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "errorValue", tag, pos, seq_end, &value));
++ local = value;
++ oid.num_values = 0;
++ break;
++ case ASN1_TYPE_OBJECT_IDENTIFIER:
++ ASN1_CALL(pos, asn1_dec_oid(ctrl, "errorValue", tag, pos, seq_end, &oid));
++ local = 0;
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++ convert =
++ rose_find_error_by_op_val(ctrl, (oid.num_values == 0) ? NULL : &oid, local);
++ if (convert) {
++ msg->code = convert->code;
++ } else {
++ msg->code = ROSE_ERROR_Unknown;
++ }
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " errorValue = %s\n", rose_error2str(msg->code));
++ }
++
++ /* Decode any expected error parameters */
++ if (convert && convert->decode_error_args) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, convert->decode_error_args(ctrl, tag, pos, seq_end, &msg->args));
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the ROSE reject message.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param msg ROSE reject message data to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_decode_reject(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct rose_msg_reject *msg)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, "REJECT Component %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ /* Invoke ID choice */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "invokeId", tag, pos, seq_end, &value));
++ msg->invoke_id = value;
++ msg->invoke_id_present = 1;
++ break;
++ case ASN1_TYPE_NULL:
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "invokeId", tag, pos, seq_end));
++ msg->invoke_id_present = 0;
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ /* Problem choice */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "problemGeneral", tag, pos, seq_end, &value));
++ msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) | (value & 0xFF);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "problemInvoke", tag, pos, seq_end, &value));
++ msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) | (value & 0xFF);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "problemResult", tag, pos, seq_end, &value));
++ msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) | (value & 0xFF);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "problemError", tag, pos, seq_end, &value));
++ msg->code = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) | (value & 0xFF);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " problem = %s\n", rose_reject2str(msg->code));
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the ROSE message into the given buffer.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position of the ASN.1 component.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param msg Decoded ROSE message contents.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ *
++ * \note This function only decodes the ROSE contents. It does not check
++ * for the protocol profile, NFE, NPP, and interpretation octets defined in
++ * a facility ie that may preceed the ROSE contents. These header octets
++ * may already have been consumed from the encompasing buffer before the
++ * buffer given here.
++ */
++const unsigned char *rose_decode(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end, struct rose_message *msg)
++{
++ unsigned tag;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
++ switch (tag) {
++ case ROSE_TAG_COMPONENT_INVOKE:
++ msg->type = ROSE_COMP_TYPE_INVOKE;
++ ASN1_CALL(pos, rose_decode_invoke(ctrl, tag, pos, end, &msg->component.invoke));
++ break;
++ case ROSE_TAG_COMPONENT_RESULT:
++ msg->type = ROSE_COMP_TYPE_RESULT;
++ ASN1_CALL(pos, rose_decode_result(ctrl, tag, pos, end, &msg->component.result));
++ break;
++ case ROSE_TAG_COMPONENT_ERROR:
++ msg->type = ROSE_COMP_TYPE_ERROR;
++ ASN1_CALL(pos, rose_decode_error(ctrl, tag, pos, end, &msg->component.error));
++ break;
++ case ROSE_TAG_COMPONENT_REJECT:
++ msg->type = ROSE_COMP_TYPE_REJECT;
++ ASN1_CALL(pos, rose_decode_reject(ctrl, tag, pos, end, &msg->component.reject));
++ break;
++ default:
++ msg->type = ROSE_COMP_TYPE_INVALID;
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ if (pos < end) {
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %u byte(s) of trailing data not consumed.\n",
++ (unsigned) (end - pos));
++ }
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the NetworkFacilityExtension argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param nfe Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *fac_dec_nfe(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end,
++ struct facNetworkFacilityExtension *nfe)
++{
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *seq_end;
++ const unsigned char *explicit_end;
++ const unsigned char *save_pos;
++ int32_t value;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s NetworkFacilityExtension %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "sourceEntity", tag, pos, seq_end, &value));
++ nfe->source_entity = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1)) {
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "sourceEntityAddress", tag, pos,
++ seq_end, &nfe->source_number));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ } else {
++ nfe->source_number.length = 0;
++ }
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "destinationEntity", tag, pos, seq_end, &value));
++ nfe->destination_entity = value;
++
++ nfe->destination_number.length = 0;
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3)) {
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "destinationEntityAddress", tag,
++ pos, seq_end, &nfe->destination_number));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ } else {
++ pos = save_pos;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the extension header argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param pos Starting position of the ASN.1 component.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param header Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *fac_dec_extension_header(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end, struct fac_extension_header *header)
++{
++ int32_t value;
++ unsigned tag;
++ const unsigned char *save_pos;
++
++ /*
++ * For simplicity we are not checking the order of
++ * the optional header components.
++ */
++ header->nfe_present = 0;
++ header->npp_present = 0;
++ header->interpretation_present = 0;
++ while (pos < end) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
++ ASN1_CALL(pos, fac_dec_nfe(ctrl, "nfe", tag, pos, end, &header->nfe));
++ header->nfe_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 18:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "networkProtocolProfile", tag, pos, end,
++ &value));
++ header->npp = value;
++ header->npp_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 11:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "interpretation", tag, pos, end, &value));
++ header->interpretation = value;
++ header->interpretation_present = 1;
++ break;
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the facility ie contents header.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param pos Starting position of the facility ie contents.
++ * \param end End of facility ie contents.
++ * \param header Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success (ROSE message).
++ * \retval NULL on error.
++ */
++const unsigned char *facility_decode_header(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end, struct fac_extension_header *header)
++{
++ /* Make sure we have enough room for the protocol profile ie octet(s) */
++ if (end < pos + 2) {
++ return NULL;
++ }
++ switch (*pos & Q932_PROTOCOL_MASK) {
++ case Q932_PROTOCOL_ROSE:
++ case Q932_PROTOCOL_EXTENSIONS:
++ break;
++ default:
++ return NULL;
++ }
++ if (!(*pos & 0x80)) {
++ /* DMS-100 Service indicator octet - Just ignore for now */
++ ++pos;
++ }
++ ++pos;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ asn1_dump(ctrl, pos, end);
++ }
++
++ pos = fac_dec_extension_header(ctrl, pos, end, header);
++ return pos;
++}
++
++/*!
++ * \brief Decode the facility ie contents for debug purposes.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param buf Buffer containing the facility ie contents.
++ * \param length Length of facility ie contents.
++ *
++ * \return Nothing
++ *
++ * \note Should only be called if PRI_DEBUG_APDU is enabled. Otherwise,
++ * it it does nothing useful.
++ */
++void facility_decode_dump(struct pri *ctrl, const unsigned char *buf, size_t length)
++{
++ const unsigned char *pos;
++ const unsigned char *end;
++ union {
++ struct fac_extension_header header;
++ struct rose_message rose;
++ } discard;
++
++ end = buf + length;
++ pos = facility_decode_header(ctrl, buf, end, &discard.header);
++ while (pos && pos < end) {
++ pos = rose_decode(ctrl, pos, end, &discard.rose);
++ }
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose.c */
+
+Property changes on: rose.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_other.c
+===================================================================
+--- a/rose_other.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_other.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,277 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief Switch type operations for: NI2, 4ESS, 5ESS, DMS-100
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \brief Encode the DMS-100 RLT_OperationInd result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args)
++{
++ return asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ args->dms100.RLT_OperationInd.call_id);
++}
++
++/*!
++ * \brief Encode the DMS-100 RLT_ThirdParty invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseDms100RLTThirdParty_ARG *rlt_thirdparty;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ rlt_thirdparty = &args->dms100.RLT_ThirdParty;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ rlt_thirdparty->call_id));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ rlt_thirdparty->reason));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the DMS-100 RLT_OperationInd result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_dms100_RLT_OperationInd_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
++{
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "callId", tag, pos, end, &value));
++ args->dms100.RLT_OperationInd.call_id = value;
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the DMS-100 RLT_ThirdParty invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_dms100_RLT_ThirdParty_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseDms100RLTThirdParty_ARG *rlt_third_party;
++
++ rlt_third_party = &args->dms100.RLT_ThirdParty;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " RLT_ThirdParty %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "callId", tag, pos, seq_end, &value));
++ rlt_third_party->call_id = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "reason", tag, pos, seq_end, &value));
++ rlt_third_party->reason = value;
++
++ /* Fixup will skip over any OPTIONAL information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the NI2 InformationFollowing invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_ni2_InformationFollowing_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ /* Encode the unknown enumeration value. */
++ return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ args->ni2.InformationFollowing.value);
++}
++
++/*!
++ * \brief Encode the NI2 InitiateTransfer invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseNi2InitiateTransfer_ARG *initiate_transfer;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ initiate_transfer = &args->ni2.InitiateTransfer;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ initiate_transfer->call_reference));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the NI2 InformationFollowing invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_ni2_InformationFollowing_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "unknown", tag, pos, end, &value));
++ args->ni2.InformationFollowing.value = value;
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the NI2 InitiateTransfer invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_ni2_InitiateTransfer_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseNi2InitiateTransfer_ARG *initiate_transfer;
++
++ initiate_transfer = &args->ni2.InitiateTransfer;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " InitiateTransfer %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "callReference", tag, pos, seq_end, &value));
++ initiate_transfer->call_reference = value;
++
++ /* Fixup will skip over any OPTIONAL information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_other.c */
+
+Property changes on: rose_other.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: pri_q931.h
+===================================================================
+--- a/pri_q931.h (.../tags/1.4.10.2) (revision 1357)
++++ b/pri_q931.h (.../branches/1.4) (revision 1357)
+@@ -30,44 +30,6 @@
+ #ifndef _PRI_Q931_H
+ #define _PRI_Q931_H
+
+-typedef enum q931_state {
+- /* User states */
+- U0_NULL_STATE,
+- U1_CALL_INITIATED,
+- U2_OVERLAP_SENDING,
+- U3_OUTGOING_CALL_PROCEEDING,
+- U4_CALL_DELIVERED,
+- U6_CALL_PRESENT,
+- U7_CALL_RECEIVED,
+- U8_CONNECT_REQUEST,
+- U9_INCOMING_CALL_PROCEEDING,
+- U10_ACTIVE,
+- U11_DISCONNECT_REQUEST,
+- U12_DISCONNECT_INDICATION,
+- U15_SUSPEND_REQUEST,
+- U17_RESUME_REQUEST,
+- U19_RELEASE_REQUEST,
+- U25_OVERLAP_RECEIVING,
+- /* Network states */
+- N0_NULL_STATE,
+- N1_CALL_INITIATED,
+- N2_OVERLAP_SENDING,
+- N3_OUTGOING_CALL_PROCEEDING,
+- N4_CALL_DELIVERED,
+- N6_CALL_PRESENT,
+- N7_CALL_RECEIVED,
+- N8_CONNECT_REQUEST,
+- N9_INCOMING_CALL_PROCEEDING,
+- N10_ACTIVE,
+- N11_DISCONNECT_REQUEST,
+- N12_DISCONNECT_INDICATION,
+- N15_SUSPEND_REQUEST,
+- N17_RESUME_REQUEST,
+- N19_RELEASE_REQUEST,
+- N22_CALL_ABORT,
+- N25_OVERLAP_RECEIVING
+-} q931_state;
+-
+ typedef enum q931_mode {
+ UNKNOWN_MODE,
+ CIRCUIT_MODE,
+@@ -79,13 +41,13 @@
+ u_int8_t pd; /* Protocol Discriminator */
+ #if __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t x0:4;
+- u_int8_t crlen:4;
++ u_int8_t crlen:4;/*!< Call reference length */
+ #else
+- u_int8_t crlen:4;
++ u_int8_t crlen:4;/*!< Call reference length */
+ u_int8_t x0:4;
+ #endif
+ u_int8_t contents[0];
+- u_int8_t crv[3];
++ u_int8_t crv[3];/*!< Call reference value */
+ } __attribute__ ((packed)) q931_h;
+
+
+@@ -113,6 +75,10 @@
+
+ #define Q931_PROTOCOL_DISCRIMINATOR 0x08
+ #define GR303_PROTOCOL_DISCRIMINATOR 0x4f
++/* AT&T Maintenance Protocol Discriminator */
++#define MAINTENANCE_PROTOCOL_DISCRIMINATOR_1 0x03
++/* National Maintenance Protocol Discriminator */
++#define MAINTENANCE_PROTOCOL_DISCRIMINATOR_2 0x43
+
+ /* Q.931 / National ISDN Message Types */
+
+@@ -157,9 +123,17 @@
+ #define Q931_SUSPEND_REJECT 0x21
+
+ /* Maintenance messages (codeset 0 only) */
+-#define NATIONAL_SERVICE 0x0f
+-#define NATIONAL_SERVICE_ACKNOWLEDGE 0x07
++#define ATT_SERVICE 0x0f
++#define ATT_SERVICE_ACKNOWLEDGE 0x07
++#define NATIONAL_SERVICE 0x07
++#define NATIONAL_SERVICE_ACKNOWLEDGE 0x0f
+
++#define SERVICE_CHANGE_STATUS_INSERVICE 0
++#define SERVICE_CHANGE_STATUS_LOOPBACK 1 /* not supported */
++#define SERVICE_CHANGE_STATUS_OUTOFSERVICE 2
++#define SERVICE_CHANGE_STATUS_REQCONTINUITYCHECK 3 /* not supported */
++#define SERVICE_CHANGE_STATUS_SHUTDOWN 4 /* not supported */
++
+ /* Special codeset 0 IE */
+ #define NATIONAL_CHANGE_STATUS 0x1
+
+@@ -168,10 +142,11 @@
+ #define Q931_NON_LOCKING_SHIFT 0x98
+ #define Q931_BEARER_CAPABILITY 0x04
+ #define Q931_CAUSE 0x08
+-#define Q931_CALL_STATE 0x14
++#define Q931_IE_CALL_STATE 0x14
+ #define Q931_CHANNEL_IDENT 0x18
+ #define Q931_PROGRESS_INDICATOR 0x1e
+ #define Q931_NETWORK_SPEC_FAC 0x20
++#define Q931_CALLING_PARTY_CATEGORY (0x32 | Q931_CODESET(5))
+ #define Q931_INFORMATION_RATE 0x40
+ #define Q931_TRANSIT_DELAY 0x42
+ #define Q931_TRANS_DELAY_SELECT 0x43
+@@ -200,8 +175,9 @@
+ #define Q931_IE_SEGMENTED_MSG 0x00
+ #define Q931_IE_CHANGE_STATUS 0x01
+ #define Q931_IE_ORIGINATING_LINE_INFO (0x01 | Q931_CODESET(6))
+-#define Q931_IE_CONNECTED_ADDR 0x0C
+-#define Q931_IE_CONNECTED_NUM 0x4C
++#define Q931_IE_CONNECTED_ADDR 0x0c
++#define Q931_IE_CONNECTED_NUM 0x4c
++#define Q931_IE_CONNECTED_SUBADDR 0x4d
+ #define Q931_IE_CALL_IDENTITY 0x10
+ #define Q931_IE_FACILITY 0x1c
+ #define Q931_IE_ENDPOINT_ID 0x26
+@@ -224,31 +200,255 @@
+ #define Q931_IE_ESCAPE_FOR_EXT 0x7F
+
+
+-/* Call state stuff */
+-#define Q931_CALL_STATE_NULL 0
+-#define Q931_CALL_STATE_CALL_INITIATED 1
+-#define Q931_CALL_STATE_OVERLAP_SENDING 2
+-#define Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING 3
+-#define Q931_CALL_STATE_CALL_DELIVERED 4
+-#define Q931_CALL_STATE_CALL_PRESENT 6
+-#define Q931_CALL_STATE_CALL_RECEIVED 7
+-#define Q931_CALL_STATE_CONNECT_REQUEST 8
+-#define Q931_CALL_STATE_INCOMING_CALL_PROCEEDING 9
+-#define Q931_CALL_STATE_ACTIVE 10
+-#define Q931_CALL_STATE_DISCONNECT_REQUEST 11
+-#define Q931_CALL_STATE_DISCONNECT_INDICATION 12
+-#define Q931_CALL_STATE_SUSPEND_REQUEST 15
+-#define Q931_CALL_STATE_RESUME_REQUEST 17
+-#define Q931_CALL_STATE_RELEASE_REQUEST 19
+-#define Q931_CALL_STATE_OVERLAP_RECEIVING 25
+-#define Q931_CALL_STATE_RESTART_REQUEST 61
+-#define Q931_CALL_STATE_RESTART 62
++/*! Q.931 call states */
++enum Q931_CALL_STATE {
++ /*!
++ * \details
++ * null state (U0):
++ * No call exists.
++ * \details
++ * null state (N0):
++ * No call exists.
++ */
++ Q931_CALL_STATE_NULL = 0,
++ /*!
++ * \details
++ * call initiated (U1):
++ * This state exists for an outgoing call, when the user requests
++ * call establishment from the network.
++ * \details
++ * call initiated (N1):
++ * This state exists for an outgoing call when the network has received
++ * a call establishment request but has not yet responded.
++ */
++ Q931_CALL_STATE_CALL_INITIATED = 1,
++ /*!
++ * \details
++ * overlap sending (U2):
++ * This state exists for an outgoing call when the user has
++ * received acknowledgement of the call establishment request which
++ * permits the user to send additional call information to the network
++ * in overlap mode.
++ * \details
++ * overlap sending (N2):
++ * This state exists for an outgoing call when the network has acknowledged
++ * the call establishment request and is prepared to receive additional
++ * call information (if any) in overlap mode.
++ */
++ Q931_CALL_STATE_OVERLAP_SENDING = 2,
++ /*!
++ * \details
++ * outgoing call proceeding (U3):
++ * This state exists for an outgoing call when the user has
++ * received acknowledgement that the network has received all
++ * call information necessary to effect call establishment.
++ * \details
++ * outgoing call proceeding (N3):
++ * This state exists for an outgoing call when the network has sent
++ * acknowledgement that the network has received all call information
++ * necessary to effect call establishment.
++ */
++ Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING = 3,
++ /*!
++ * \details
++ * call delivered (U4):
++ * This state exists for an outgoing call when the calling user has
++ * received an indication that remote user alerting has been initiated.
++ * \details
++ * call delivered (N4):
++ * This state exists for an outgoing call when the network has indicated
++ * that remote user alerting has been initiated.
++ */
++ Q931_CALL_STATE_CALL_DELIVERED = 4,
++ /*!
++ * \details
++ * call present (U6):
++ * This state exists for an incoming call when the user has received a
++ * call establishment request but has not yet responded.
++ * \details
++ * call present (N6):
++ * This state exists for an incoming call when the network has sent a
++ * call establishment request but has not yet received a satisfactory
++ * response.
++ */
++ Q931_CALL_STATE_CALL_PRESENT = 6,
++ /*!
++ * \details
++ * call received (U7):
++ * This state exists for an incoming call when the user has indicated
++ * alerting but has not yet answered.
++ * \details
++ * call received (N7):
++ * This state exists for an incoming call when the network has received
++ * an indication that the user is alerting but has not yet received an
++ * answer.
++ */
++ Q931_CALL_STATE_CALL_RECEIVED = 7,
++ /*!
++ * \details
++ * connect request (U8):
++ * This state exists for an incoming call when the user has answered
++ * the call and is waiting to be awarded the call.
++ * \details
++ * connect request (N8):
++ * This state exists for an incoming call when the network has received
++ * an answer but the network has not yet awarded the call.
++ */
++ Q931_CALL_STATE_CONNECT_REQUEST = 8,
++ /*!
++ * \details
++ * incoming call proceeding (U9):
++ * This state exists for an incoming call when the user has sent
++ * acknowledgement that the user has received all call information
++ * necessary to effect call establishment.
++ * \details
++ * incoming call proceeding (N9):
++ * This state exists for an incoming call when the network has received
++ * acknowledgement that the user has received all call information
++ * necessary to effect call establishment.
++ */
++ Q931_CALL_STATE_INCOMING_CALL_PROCEEDING = 9,
++ /*!
++ * \details
++ * active (U10):
++ * This state exists for an incoming call when the user has received
++ * an acknowledgement from the network that the user has been awarded
++ * the call. This state exists for an outgoing call when the user has
++ * received an indication that the remote user has answered the call.
++ * \details
++ * active (N10):
++ * This state exists for an incoming call when the network has awarded
++ * the call to the called user. This state exists for an outgoing call
++ * when the network has indicated that the remote user has answered
++ * the call.
++ */
++ Q931_CALL_STATE_ACTIVE = 10,
++ /*!
++ * \details
++ * disconnect request (U11):
++ * This state exists when the user has requested the network to clear
++ * the end-to-end connection (if any) and is waiting for a response.
++ * \details
++ * disconnect request (N11):
++ * This state exists when the network has received a request from the
++ * user to clear the end-to-end connection (if any).
++ */
++ Q931_CALL_STATE_DISCONNECT_REQUEST = 11,
++ /*!
++ * \details
++ * disconnect indication (U12):
++ * This state exists when the user has received an invitation to
++ * disconnect because the network has disconnected the end-to-end
++ * connection (if any).
++ * \details
++ * disconnect indication (N12):
++ * This state exists when the network has disconnected the end-to-end
++ * connection (if any) and has sent an invitation to disconnect the
++ * user-network connection.
++ */
++ Q931_CALL_STATE_DISCONNECT_INDICATION = 12,
++ /*!
++ * \details
++ * suspend request (U15):
++ * This state exists when the user has requested the network to suspend
++ * the call and is waiting for a response.
++ * \details
++ * suspend request (N15):
++ * This state exists when the network has received a request to suspend
++ * the call but has not yet responded.
++ */
++ Q931_CALL_STATE_SUSPEND_REQUEST = 15,
++ /*!
++ * \details
++ * resume request (U17):
++ * This state exists when the user has requested the network to resume
++ * a previously suspended call and is waiting for a response.
++ * \details
++ * resume request (N17):
++ * This state exists when the network has received a request to resume
++ * a previously suspended call but has not yet responded.
++ */
++ Q931_CALL_STATE_RESUME_REQUEST = 17,
++ /*!
++ * \details
++ * release request (U19):
++ * This state exists when the user has requested the network to release
++ * and is waiting for a response.
++ * \details
++ * release request (N19):
++ * This state exists when the network has requested the user to release
++ * and is waiting for a response.
++ */
++ Q931_CALL_STATE_RELEASE_REQUEST = 19,
++ /*!
++ * \details
++ * call abort (N22):
++ * This state exists for an incoming call for the point-to-multipoint
++ * configuration when the call is being cleared before any user has been
++ * awarded the call.
++ */
++ Q931_CALL_STATE_CALL_ABORT = 22,
++ /*!
++ * \details
++ * overlap receiving (U25):
++ * This state exists for an incoming call when the user has acknowledged
++ * the call establishment request from the network and is prepared to
++ * receive additional call information (if any) in overlap mode.
++ * \details
++ * overlap receiving (N25):
++ * This state exists for an incoming call when the network has received
++ * acknowledgement of the call establishment request which permits the
++ * network to send additional call information (if any) in the overlap
++ * mode.
++ */
++ Q931_CALL_STATE_OVERLAP_RECEIVING = 25,
++ /*!
++ * \details
++ * call independent service (U31): (From Q.932)
++ * This state exists when a call independent supplementary service
++ * signalling connection is established.
++ * \details
++ * call independent service (N31): (From Q.932)
++ * This state exists when a call independent supplementary service
++ * signalling connection is established.
++ */
++ Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE = 31,
++ Q931_CALL_STATE_RESTART_REQUEST = 61,
++ Q931_CALL_STATE_RESTART = 62,
++ /*!
++ * \details
++ * Call state has not been set.
++ * Call state does not exist.
++ * Call state not initialized.
++ * Call state internal use only.
++ */
++ Q931_CALL_STATE_NOT_SET = 0xFF,
++};
+
++/*! Q.931 call establishment state ranking for competing calls in PTMP NT mode. */
++enum Q931_RANKED_CALL_STATE {
++ /*! Call is present but has no response yet. */
++ Q931_RANKED_CALL_STATE_PRESENT,
++ /*! Call is collecting digits. */
++ Q931_RANKED_CALL_STATE_OVERLAP,
++ /*! Call routing is happening. */
++ Q931_RANKED_CALL_STATE_PROCEEDING,
++ /*! Called party is being alerted of the call. */
++ Q931_RANKED_CALL_STATE_ALERTING,
++ /*! Call is connected. A winner has been declared. */
++ Q931_RANKED_CALL_STATE_CONNECT,
++ /*! Call is in some non-call establishment state (likely disconnecting). */
++ Q931_RANKED_CALL_STATE_OTHER,
++};
+
+ /* EuroISDN */
+ #define Q931_SENDING_COMPLETE 0xa1
+
++extern int maintenance_service(struct pri *pri, int span, int channel, int changestatus);
+
++extern int maintenance_service_ack(struct pri *pri, q931_call *call);
++
++
+ /* Q.SIG specific */
+ #define QSIG_IE_TRANSIT_COUNT 0x31
+
+@@ -268,7 +468,7 @@
+
+ extern int q931_information(struct pri *pri, q931_call *call, char digit);
+
+-extern int q931_keypad_facility(struct pri *pri, q931_call *call, char *digits);
++extern int q931_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
+
+ extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
+
+@@ -291,8 +491,16 @@
+ extern int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req);
+ extern void q931_dump(struct pri *pri, q931_h *h, int len, int txrx);
+
+-extern void __q931_destroycall(struct pri *pri, q931_call *c);
++void q931_destroycall(struct pri *pri, q931_call *c);
+
+ extern void q931_dl_indication(struct pri *pri, int event);
+
++int q931_send_hold(struct pri *ctrl, struct q931_call *call);
++int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call);
++int q931_send_hold_rej(struct pri *ctrl, struct q931_call *call, int cause);
++
++int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel);
++int q931_send_retrieve_ack(struct pri *ctrl, struct q931_call *call, int channel);
++int q931_send_retrieve_rej(struct pri *ctrl, struct q931_call *call, int cause);
++
+ #endif
+Index: rose_qsig_diversion.c
+===================================================================
+--- a/rose_qsig_diversion.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_qsig_diversion.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,1390 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief Q.SIG ROSE Call-Diversion-Operations
++ *
++ * Call-Diversion-Operations ECMA-174 Annex F Table F.1
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Encode the IntResult type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param int_result Forwarding record information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_IntResult(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseQsigForwardingRecord *int_result)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &int_result->served_user_number));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ int_result->basic_service));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, int_result->procedure));
++ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &int_result->diverted_to));
++ if (int_result->remote_enabled) {
++ /* Not the DEFAULT value */
++ ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
++ int_result->remote_enabled));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the IntResultList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SET unless the caller implicitly
++ * tags it otherwise.
++ * \param int_result_list Forwarding record list information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_IntResultList(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag,
++ const struct roseQsigForwardingList *int_result_list)
++{
++ unsigned index;
++ unsigned char *set_len;
++
++ ASN1_CONSTRUCTED_BEGIN(set_len, pos, end, tag);
++
++ for (index = 0; index < int_result_list->num_records; ++index) {
++ ASN1_CALL(pos, rose_enc_qsig_IntResult(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &int_result_list->list[index]));
++ }
++
++ ASN1_CONSTRUCTED_END(set_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the ActivateDiversionQ invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigActivateDiversionQ_ARG *activate_diversion_q;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ activate_diversion_q = &args->qsig.ActivateDiversionQ;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ activate_diversion_q->procedure));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ activate_diversion_q->basic_service));
++ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &activate_diversion_q->diverted_to));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &activate_diversion_q->served_user_number));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &activate_diversion_q->activating_user_number));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the DeactivateDiversionQ invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigDeactivateDiversionQ_ARG *deactivate_diversion_q;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ deactivate_diversion_q = &args->qsig.DeactivateDiversionQ;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ deactivate_diversion_q->procedure));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ deactivate_diversion_q->basic_service));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &deactivate_diversion_q->served_user_number));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &deactivate_diversion_q->deactivating_user_number));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the InterrogateDiversionQ invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigInterrogateDiversionQ_ARG *interrogate_diversion_q;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ interrogate_diversion_q = &args->qsig.InterrogateDiversionQ;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ interrogate_diversion_q->procedure));
++ if (interrogate_diversion_q->basic_service) {
++ /* Not the DEFAULT value */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ interrogate_diversion_q->basic_service));
++ }
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &interrogate_diversion_q->served_user_number));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &interrogate_diversion_q->interrogating_user_number));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the InterrogateDiversionQ result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
++{
++ return rose_enc_qsig_IntResultList(ctrl, pos, end, ASN1_TAG_SET,
++ &args->qsig.InterrogateDiversionQ);
++}
++
++/*!
++ * \brief Encode the CheckRestriction invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigCheckRestriction_ARG *check_restriction;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ check_restriction = &args->qsig.CheckRestriction;
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &check_restriction->served_user_number));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ check_restriction->basic_service));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &check_restriction->diverted_to_number));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the CallRerouting invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigCallRerouting_ARG *call_rerouting;
++ unsigned char *seq_len;
++ unsigned char *exp_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ call_rerouting = &args->qsig.CallRerouting;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ call_rerouting->rerouting_reason));
++ if (call_rerouting->original_rerouting_reason_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ call_rerouting->original_rerouting_reason));
++ }
++ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &call_rerouting->called));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ call_rerouting->diversion_counter));
++ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
++ &call_rerouting->q931ie));
++
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &call_rerouting->last_rerouting));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ call_rerouting->subscription_option));
++
++ if (call_rerouting->calling_subaddress.length) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
++ &call_rerouting->calling_subaddress));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
++ ASN1_CALL(pos, rose_enc_PresentedNumberScreened(ctrl, pos, end,
++ &call_rerouting->calling));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++
++ if (call_rerouting->calling_name_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &call_rerouting->calling_name));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ if (call_rerouting->original_called_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &call_rerouting->original_called));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ if (call_rerouting->redirecting_name_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 7);
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &call_rerouting->redirecting_name));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ if (call_rerouting->original_called_name_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 8);
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &call_rerouting->original_called_name));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the DivertingLegInformation1 invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigDivertingLegInformation1_ARG *diverting_leg_information_1;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ diverting_leg_information_1 = &args->qsig.DivertingLegInformation1;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diverting_leg_information_1->diversion_reason));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diverting_leg_information_1->subscription_option));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &diverting_leg_information_1->nominated_number));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the DivertingLegInformation2 invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigDivertingLegInformation2_ARG *diverting_leg_information_2;
++ unsigned char *seq_len;
++ unsigned char *exp_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ diverting_leg_information_2 = &args->qsig.DivertingLegInformation2;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ diverting_leg_information_2->diversion_counter));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diverting_leg_information_2->diversion_reason));
++ if (diverting_leg_information_2->original_diversion_reason_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ diverting_leg_information_2->original_diversion_reason));
++ }
++
++ if (diverting_leg_information_2->diverting_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &diverting_leg_information_2->diverting));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ if (diverting_leg_information_2->original_called_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &diverting_leg_information_2->original_called));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ if (diverting_leg_information_2->redirecting_name_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &diverting_leg_information_2->redirecting_name));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ if (diverting_leg_information_2->original_called_name_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &diverting_leg_information_2->original_called_name));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the DivertingLegInformation3 invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseQsigDivertingLegInformation3_ARG *diverting_leg_information_3;
++ unsigned char *seq_len;
++ unsigned char *exp_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ diverting_leg_information_3 = &args->qsig.DivertingLegInformation3;
++ ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
++ diverting_leg_information_3->presentation_allowed_indicator));
++
++ if (diverting_leg_information_3->redirection_name_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &diverting_leg_information_3->redirection_name));
++ ASN1_CONSTRUCTED_END(exp_len, pos, end);
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the IntResult argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param int_result Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_IntResult(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigForwardingRecord *int_result)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s IntResult %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
++ &int_result->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ int_result->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ int_result->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_Address(ctrl, "divertedToAddress", tag, pos, seq_end,
++ &int_result->diverted_to));
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ int_result->remote_enabled = 0; /* DEFAULT FALSE */
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_TYPE_BOOLEAN:
++ /* Must not be constructed but we will not check for it for simplicity. */
++ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "remoteEnabled", tag, pos, seq_end,
++ &value));
++ int_result->remote_enabled = value;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " extension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the IntResultList argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param int_result_list Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_IntResultList(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigForwardingList *int_result_list)
++{
++ int length;
++ int set_offset;
++ const unsigned char *set_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s IntResultList %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(set_end, set_offset, length, pos, end);
++
++ int_result_list->num_records = 0;
++ while (pos < set_end && *pos != ASN1_INDEF_TERM) {
++ if (int_result_list->num_records < ARRAY_LEN(int_result_list->list)) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, set_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_qsig_IntResult(ctrl, "listEntry", tag, pos, set_end,
++ &int_result_list->list[int_result_list->num_records]));
++ ++int_result_list->num_records;
++ } else {
++ /* Too many records */
++ return NULL;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, set_offset, set_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG ActivateDiversionQ invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_ActivateDiversionQ_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigActivateDiversionQ_ARG *activate_diversion_q;
++
++ activate_diversion_q = &args->qsig.ActivateDiversionQ;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " ActivateDiversionQ %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ activate_diversion_q->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ activate_diversion_q->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_Address(ctrl, "divertedToAddress", tag, pos, seq_end,
++ &activate_diversion_q->diverted_to));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
++ &activate_diversion_q->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "activatingUserNr", tag, pos, seq_end,
++ &activate_diversion_q->activating_user_number));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG DeactivateDiversionQ invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_DeactivateDiversionQ_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigDeactivateDiversionQ_ARG *deactivate_diversion_q;
++
++ deactivate_diversion_q = &args->qsig.DeactivateDiversionQ;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DeactivateDiversionQ %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ deactivate_diversion_q->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ deactivate_diversion_q->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
++ &deactivate_diversion_q->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "deactivatingUserNr", tag, pos, seq_end,
++ &deactivate_diversion_q->deactivating_user_number));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG InterrogateDiversionQ invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_InterrogateDiversionQ_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigInterrogateDiversionQ_ARG *interrogate_diversion_q;
++
++ interrogate_diversion_q = &args->qsig.InterrogateDiversionQ;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " InterrogateDiversionQ %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ interrogate_diversion_q->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ if (tag == ASN1_TYPE_ENUMERATED) {
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ interrogate_diversion_q->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ } else {
++ interrogate_diversion_q->basic_service = 0; /* allServices */
++ }
++
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
++ &interrogate_diversion_q->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "interrogatingUserNr", tag, pos, seq_end,
++ &interrogate_diversion_q->interrogating_user_number));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG InterrogateDiversionQ result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_InterrogateDiversionQ_RES(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args)
++{
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SET);
++ return rose_dec_qsig_IntResultList(ctrl, "InterrogateDiversionQ", tag, pos, end,
++ &args->qsig.InterrogateDiversionQ);
++}
++
++/*!
++ * \brief Decode the Q.SIG CheckRestriction invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CheckRestriction_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigCheckRestriction_ARG *check_restriction;
++
++ check_restriction = &args->qsig.CheckRestriction;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CheckRestriction %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "servedUserNr", tag, pos, seq_end,
++ &check_restriction->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ check_restriction->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "divertedToNr", tag, pos, seq_end,
++ &check_restriction->diverted_to_number));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG CallRerouting invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *explicit_end;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigCallRerouting_ARG *call_rerouting;
++
++ call_rerouting = &args->qsig.CallRerouting;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallRerouting %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "reroutingReason", tag, pos, seq_end, &value));
++ call_rerouting->rerouting_reason = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | 0)) {
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "originalReroutingReason", tag, pos, seq_end,
++ &value));
++ call_rerouting->original_rerouting_reason = value;
++ call_rerouting->original_rerouting_reason_present = 1;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ } else {
++ call_rerouting->original_rerouting_reason_present = 0;
++ }
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_Address(ctrl, "calledAddress", tag, pos, seq_end,
++ &call_rerouting->called));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionCounter", tag, pos, seq_end, &value));
++ call_rerouting->diversion_counter = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_CLASS_APPLICATION | 0);
++ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "pSS1InfoElement", tag, pos, seq_end,
++ &call_rerouting->q931ie, sizeof(call_rerouting->q931ie_contents)));
++
++ /* Remove EXPLICIT tag */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "lastReroutingNr", tag, pos,
++ explicit_end, &call_rerouting->last_rerouting));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "subscriptionOption", tag, pos, seq_end, &value));
++ call_rerouting->subscription_option = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ if (tag == (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3)) {
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "callingPartySubaddress", tag, pos,
++ explicit_end, &call_rerouting->calling_subaddress));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ } else {
++ call_rerouting->calling_subaddress.length = 0;
++ }
++
++ /* Remove EXPLICIT tag */
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberScreened(ctrl, "callingNumber", tag, pos,
++ explicit_end, &call_rerouting->calling));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ call_rerouting->calling_name_present = 0;
++ call_rerouting->redirecting_name_present = 0;
++ call_rerouting->original_called_name_present = 0;
++ call_rerouting->original_called_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "callingName", tag, pos,
++ explicit_end, &call_rerouting->calling_name));
++ call_rerouting->calling_name_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "originalCalledNr",
++ tag, pos, explicit_end, &call_rerouting->original_called));
++ call_rerouting->original_called_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 7:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectingName", tag, pos,
++ explicit_end, &call_rerouting->redirecting_name));
++ call_rerouting->redirecting_name_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 8:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "originalCalledName", tag, pos,
++ explicit_end, &call_rerouting->original_called_name));
++ call_rerouting->original_called_name_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 9:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " extension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG DivertingLegInformation1 invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_DivertingLegInformation1_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigDivertingLegInformation1_ARG *diverting_leg_information_1;
++
++ diverting_leg_information_1 = &args->qsig.DivertingLegInformation1;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DivertingLegInformation1 %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
++ diverting_leg_information_1->diversion_reason = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "subscriptionOption", tag, pos, seq_end, &value));
++ diverting_leg_information_1->subscription_option = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "nominatedNr", tag, pos, seq_end,
++ &diverting_leg_information_1->nominated_number));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG DivertingLegInformation2 invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_DivertingLegInformation2_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *explicit_end;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigDivertingLegInformation2_ARG *diverting_leg_information_2;
++
++ diverting_leg_information_2 = &args->qsig.DivertingLegInformation2;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DivertingLegInformation2 %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionCounter", tag, pos, seq_end, &value));
++ diverting_leg_information_2->diversion_counter = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
++ diverting_leg_information_2->diversion_reason = value;
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ diverting_leg_information_2->original_diversion_reason_present = 0;
++ diverting_leg_information_2->diverting_present = 0;
++ diverting_leg_information_2->original_called_present = 0;
++ diverting_leg_information_2->redirecting_name_present = 0;
++ diverting_leg_information_2->original_called_name_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "originalDiversionReason", tag, pos,
++ seq_end, &value));
++ diverting_leg_information_2->original_diversion_reason = value;
++ diverting_leg_information_2->original_diversion_reason_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "divertingNr", tag,
++ pos, explicit_end, &diverting_leg_information_2->diverting));
++ diverting_leg_information_2->diverting_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "originalCalledNr",
++ tag, pos, explicit_end, &diverting_leg_information_2->original_called));
++ diverting_leg_information_2->original_called_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectingName", tag, pos,
++ explicit_end, &diverting_leg_information_2->redirecting_name));
++ diverting_leg_information_2->redirecting_name_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "originalCalledName", tag, pos,
++ explicit_end, &diverting_leg_information_2->original_called_name));
++ diverting_leg_information_2->original_called_name_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " extension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG DivertingLegInformation3 invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_DivertingLegInformation3_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *explicit_end;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigDivertingLegInformation3_ARG *diverting_leg_information_3;
++
++ diverting_leg_information_3 = &args->qsig.DivertingLegInformation3;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DivertingLegInformation3 %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
++ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "presentationAllowedIndicator", tag, pos,
++ seq_end, &value));
++ diverting_leg_information_3->presentation_allowed_indicator = value;
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ diverting_leg_information_3->redirection_name_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectionName", tag, pos,
++ explicit_end, &diverting_leg_information_3->redirection_name));
++ diverting_leg_information_3->redirection_name_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " extension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_qsig_diversion.c */
+
+Property changes on: rose_qsig_diversion.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose.h
+===================================================================
+--- a/rose.h (.../tags/1.4.10.2) (revision 0)
++++ b/rose.h (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,3580 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ROSE definitions and prototypes
++ *
++ * \details
++ * This file contains all of the data structures and definitions needed
++ * for ROSE component encoding and decoding.
++ *
++ * ROSE - Remote Operations Service Element
++ * ASN.1 - Abstract Syntax Notation 1
++ * APDU - Application Protocol Data Unit
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++#ifndef _LIBPRI_ROSE_H
++#define _LIBPRI_ROSE_H
++
++#include <string.h>
++#include <sys/types.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* ------------------------------------------------------------------- */
++
++
++/* Northern Telecom DMS-100 RLT related operations */
++#define ROSE_DMS100_RLT_SERVICE_ID 0x3e
++#define ROSE_DMS100_RLT_OPERATION_IND 0x01
++#define ROSE_DMS100_RLT_THIRD_PARTY 0x02
++
++/*! \brief ROSE operation-value function code */
++enum rose_operation {
++ /*! \brief No ROSE operation */
++ ROSE_None,
++ /*! \brief Unknown OID/localValue operation-value code */
++ ROSE_Unknown,
++
++/* *INDENT-OFF* */
++ /* ETSI Diversion-Operations */
++ ROSE_ETSI_ActivationDiversion, /*!< Invoke/Result */
++ ROSE_ETSI_DeactivationDiversion, /*!< Invoke/Result */
++ ROSE_ETSI_ActivationStatusNotificationDiv,/*!< Invoke only */
++ ROSE_ETSI_DeactivationStatusNotificationDiv,/*!< Invoke only */
++ ROSE_ETSI_InterrogationDiversion, /*!< Invoke/Result */
++ ROSE_ETSI_DiversionInformation, /*!< Invoke only */
++ ROSE_ETSI_CallDeflection, /*!< Invoke/Result */
++ ROSE_ETSI_CallRerouting, /*!< Invoke/Result */
++ ROSE_ETSI_InterrogateServedUserNumbers, /*!< Invoke/Result */
++ ROSE_ETSI_DivertingLegInformation1, /*!< Invoke only */
++ ROSE_ETSI_DivertingLegInformation2, /*!< Invoke only */
++ ROSE_ETSI_DivertingLegInformation3, /*!< Invoke only */
++
++ /*
++ * ETSI Advice-of-Charge-Operations
++ *
++ * Advice-Of-Charge-at-call-Setup(AOCS)
++ * Advice-Of-Charge-During-the-call(AOCD)
++ * Advice-Of-Charge-at-the-End-of-the-call(AOCE)
++ */
++ ROSE_ETSI_ChargingRequest, /*!< Invoke/Result */
++ ROSE_ETSI_AOCSCurrency, /*!< Invoke only */
++ ROSE_ETSI_AOCSSpecialArr, /*!< Invoke only */
++ ROSE_ETSI_AOCDCurrency, /*!< Invoke only */
++ ROSE_ETSI_AOCDChargingUnit, /*!< Invoke only */
++ ROSE_ETSI_AOCECurrency, /*!< Invoke only */
++ ROSE_ETSI_AOCEChargingUnit, /*!< Invoke only */
++
++ /* ETSI Explicit-Call-Transfer-Operations-and-Errors */
++ ROSE_ETSI_EctExecute, /*!< Invoke/Result */
++ ROSE_ETSI_ExplicitEctExecute, /*!< Invoke/Result */
++ ROSE_ETSI_RequestSubaddress, /*!< Invoke only */
++ ROSE_ETSI_SubaddressTransfer, /*!< Invoke only */
++ ROSE_ETSI_EctLinkIdRequest, /*!< Invoke/Result */
++ ROSE_ETSI_EctInform, /*!< Invoke only */
++ ROSE_ETSI_EctLoopTest, /*!< Invoke/Result */
++
++ /* Q.SIG Name-Operations */
++ ROSE_QSIG_CallingName, /*!< Invoke only */
++ ROSE_QSIG_CalledName, /*!< Invoke only */
++ ROSE_QSIG_ConnectedName, /*!< Invoke only */
++ ROSE_QSIG_BusyName, /*!< Invoke only */
++
++ /* Q.SIG SS-AOC-Operations */
++ ROSE_QSIG_ChargeRequest, /*!< Invoke/Result */
++ ROSE_QSIG_GetFinalCharge, /*!< Invoke only */
++ ROSE_QSIG_AocFinal, /*!< Invoke only */
++ ROSE_QSIG_AocInterim, /*!< Invoke only */
++ ROSE_QSIG_AocRate, /*!< Invoke only */
++ ROSE_QSIG_AocComplete, /*!< Invoke/Result */
++ ROSE_QSIG_AocDivChargeReq, /*!< Invoke only */
++
++ /* Q.SIG Call-Transfer-Operations (CT) */
++ ROSE_QSIG_CallTransferIdentify, /*!< Invoke/Result */
++ ROSE_QSIG_CallTransferAbandon, /*!< Invoke only */
++ ROSE_QSIG_CallTransferInitiate, /*!< Invoke/Result */
++ ROSE_QSIG_CallTransferSetup, /*!< Invoke/Result */
++ ROSE_QSIG_CallTransferActive, /*!< Invoke only */
++ ROSE_QSIG_CallTransferComplete, /*!< Invoke only */
++ ROSE_QSIG_CallTransferUpdate, /*!< Invoke only */
++ ROSE_QSIG_SubaddressTransfer, /*!< Invoke only */
++
++ ROSE_QSIG_PathReplacement, /*!< Invoke only */
++
++ /* Q.SIG Call-Diversion-Operations */
++ ROSE_QSIG_ActivateDiversionQ, /*!< Invoke/Result */
++ ROSE_QSIG_DeactivateDiversionQ, /*!< Invoke/Result */
++ ROSE_QSIG_InterrogateDiversionQ, /*!< Invoke/Result */
++ ROSE_QSIG_CheckRestriction, /*!< Invoke/Result */
++ ROSE_QSIG_CallRerouting, /*!< Invoke/Result */
++ ROSE_QSIG_DivertingLegInformation1, /*!< Invoke only */
++ ROSE_QSIG_DivertingLegInformation2, /*!< Invoke only */
++ ROSE_QSIG_DivertingLegInformation3, /*!< Invoke only */
++ ROSE_QSIG_CfnrDivertedLegFailed, /*!< Invoke only */
++
++ /* Q.SIG SS-MWI-Operations */
++ ROSE_QSIG_MWIActivate, /*!< Invoke/Result */
++ ROSE_QSIG_MWIDeactivate, /*!< Invoke/Result */
++ ROSE_QSIG_MWIInterrogate, /*!< Invoke/Result */
++
++ /* Northern Telecom DMS-100 RLT related operations */
++ /*! Invoke/Result: Must set invokeId to ROSE_DMS100_RLT_OPERATION_IND */
++ ROSE_DMS100_RLT_OperationInd,
++ /*! Invoke/Result: Must set invokeId to ROSE_DMS100_RLT_THIRD_PARTY */
++ ROSE_DMS100_RLT_ThirdParty,
++
++ ROSE_NI2_InformationFollowing, /*!< Invoke only? */
++ ROSE_NI2_InitiateTransfer, /*!< Invoke only? Is this correct operation name? */
++
++ ROSE_Num_Operation_Codes /*!< Must be last in the enumeration */
++/* *INDENT-ON* */
++};
++
++enum rose_error_code {
++ /*! \brief No error occurred */
++ ROSE_ERROR_None,
++ /*! \brief Unknown OID/localValue error-value code */
++ ROSE_ERROR_Unknown,
++
++ /* General-Errors (ETS 300 196) and General-Error-List(Q.950) */
++ ROSE_ERROR_Gen_NotSubscribed, /*!< also: UserNotSubscribed */
++ ROSE_ERROR_Gen_NotAvailable,
++ ROSE_ERROR_Gen_NotImplemented, /*!< Not in Q.950 */
++ ROSE_ERROR_Gen_InvalidServedUserNr,
++ ROSE_ERROR_Gen_InvalidCallState,
++ ROSE_ERROR_Gen_BasicServiceNotProvided,
++ ROSE_ERROR_Gen_NotIncomingCall,
++ ROSE_ERROR_Gen_SupplementaryServiceInteractionNotAllowed,
++ ROSE_ERROR_Gen_ResourceUnavailable,
++
++ /* Additional General-Error-List(Q.950) */
++ ROSE_ERROR_Gen_RejectedByNetwork,
++ ROSE_ERROR_Gen_RejectedByUser,
++ ROSE_ERROR_Gen_InsufficientInformation,
++ ROSE_ERROR_Gen_CallFailure,
++ ROSE_ERROR_Gen_ProceduralError,
++
++ /* ETSI Diversion-Operations */
++ ROSE_ERROR_Div_InvalidDivertedToNr,
++ ROSE_ERROR_Div_SpecialServiceNr,
++ ROSE_ERROR_Div_DiversionToServedUserNr,
++ ROSE_ERROR_Div_IncomingCallAccepted,
++ ROSE_ERROR_Div_NumberOfDiversionsExceeded,
++ ROSE_ERROR_Div_NotActivated,
++ ROSE_ERROR_Div_RequestAlreadyAccepted,
++
++ /* ETSI Advice-of-Charge-Operations */
++ ROSE_ERROR_AOC_NoChargingInfoAvailable,
++
++ /* ETSI Explicit-Call-Transfer-Operations-and-Errors */
++ ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,
++
++ /* Q.SIG from various specifications */
++ ROSE_ERROR_QSIG_Unspecified,
++
++ /* Q.SIG SS-AOC-Operations */
++ ROSE_ERROR_QSIG_AOC_FreeOfCharge,
++
++ /* Q.SIG Call-Transfer-Operations (CT) */
++ ROSE_ERROR_QSIG_CT_InvalidReroutingNumber,
++ ROSE_ERROR_QSIG_CT_UnrecognizedCallIdentity,
++ ROSE_ERROR_QSIG_CT_EstablishmentFailure,
++
++ /* Q.SIG Call-Diversion-Operations (Additional Q.SIG specific errors) */
++ ROSE_ERROR_QSIG_Div_TemporarilyUnavailable,
++ ROSE_ERROR_QSIG_Div_NotAuthorized,
++
++ /* Q.SIG SS-MWI-Operations */
++ ROSE_ERROR_QSIG_InvalidMsgCentreId,
++
++ /* Northern Telecom DMS-100 RLT related operations */
++ ROSE_ERROR_DMS100_RLT_BridgeFail,
++ ROSE_ERROR_DMS100_RLT_CallIDNotFound,
++ ROSE_ERROR_DMS100_RLT_NotAllowed,
++ ROSE_ERROR_DMS100_RLT_SwitchEquipCongs,
++
++ ROSE_ERROR_Num_Codes /*!< Must be last in the enumeration */
++};
++
++#define ROSE_REJECT_BASE(base) ((base) * 0x100)
++enum rose_reject_base {
++ ROSE_REJECT_BASE_General,
++ ROSE_REJECT_BASE_Invoke,
++ ROSE_REJECT_BASE_Result,
++ ROSE_REJECT_BASE_Error,
++
++ /*! \brief Must be last in the list */
++ ROSE_REJECT_BASE_Last
++};
++
++/*!
++ * \brief From Facility-Information-Element-Components
++ * {itu-t identified-organization etsi(0) 196 facility-information-element-component(3)}
++ */
++enum rose_reject_code {
++ /*! \brief Not rejected */
++ ROSE_REJECT_None = -1,
++ /*! \brief Unknown reject code */
++ ROSE_REJECT_Unknown = -2,
++
++/* *INDENT-OFF* */
++ ROSE_REJECT_Gen_UnrecognizedComponent = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) + 0,
++ ROSE_REJECT_Gen_MistypedComponent = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) + 1,
++ ROSE_REJECT_Gen_BadlyStructuredComponent = ROSE_REJECT_BASE(ROSE_REJECT_BASE_General) + 2,
++
++ ROSE_REJECT_Inv_DuplicateInvocation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 0,
++ ROSE_REJECT_Inv_UnrecognizedOperation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 1,
++ ROSE_REJECT_Inv_MistypedArgument = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 2,
++ ROSE_REJECT_Inv_ResourceLimitation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 3,
++ ROSE_REJECT_Inv_InitiatorReleasing = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 4,
++ ROSE_REJECT_Inv_UnrecognizedLinkedID = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 5,
++ ROSE_REJECT_Inv_LinkedResponseUnexpected = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 6,
++ ROSE_REJECT_Inv_UnexpectedChildOperation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Invoke) + 7,
++
++ ROSE_REJECT_Res_UnrecognizedInvocation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) + 0,
++ ROSE_REJECT_Res_ResultResponseUnexpected = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) + 1,
++ ROSE_REJECT_Res_MistypedResult = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Result) + 2,
++
++ ROSE_REJECT_Err_UnrecognizedInvocation = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 0,
++ ROSE_REJECT_Err_ErrorResponseUnexpected = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 1,
++ ROSE_REJECT_Err_UnrecognizedError = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 2,
++ ROSE_REJECT_Err_UnexpectedError = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 3,
++ ROSE_REJECT_Err_MistypedParameter = ROSE_REJECT_BASE(ROSE_REJECT_BASE_Error) + 4,
++/* *INDENT-ON* */
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * Q931InformationElement ::= [APPLICATION 0] IMPLICIT OCTET STRING
++ */
++struct roseQ931ie {
++ /*!
++ * \brief The Q.931 ie is present if length is nonzero.
++ * (If this field is optional in the message.)
++ */
++ u_int8_t length;
++
++ /*!
++ * \brief We mostly just need to store the contents so we will defer
++ * decoding/encoding.
++ *
++ * \note To reduce the size of the structure, the memory for the
++ * ie contents is "allocated" after the structure.
++ * \note Remember the "allocated" memory needs to have room for a
++ * null terminator.
++ */
++ unsigned char contents[0];
++};
++
++enum {
++ /*! Bearer Capability has a max length of 12. */
++ ROSE_Q931_MAX_BC = 12,
++ /*! High Layer Compatibility has a max length of 5. */
++ ROSE_Q931_MAX_HLC = 5,
++ /*! Low Layer Compatibility has a max length of 18. */
++ ROSE_Q931_MAX_LLC = 18,
++ /*!
++ * User-User Information has a network dependent maximum.
++ * The network dependent maximum is either 35 or 131 octets
++ * in non-USER-INFORMATION messages.
++ */
++ ROSE_Q931_MAX_USER = 131,
++ /*!
++ * Progress Indicator has a max length of 4.
++ * There can be multiple progress indicator ies.
++ * Q.SIG allows up to 3.
++ * ITU-T allows up to 2.
++ */
++ ROSE_Q931_MAX_PROGRESS = 3 * 4,
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * PartyNumber ::= CHOICE {
++ * -- the numbering plan is the default numbering plan of
++ * -- the network. It is recommended that this value is
++ * -- used.
++ * unknownPartyNumber [0] IMPLICIT NumberDigits,
++ *
++ * -- the numbering plan is according to
++ * -- ITU-T Recommendation E.164.
++ * publicPartyNumber [1] IMPLICIT PublicPartyNumber,
++ *
++ * -- ATM endsystem address encoded as an NSAP address.
++ * nsapEncodedNumber [2] IMPLICIT NsapEncodedNumber,
++ *
++ * -- not used, value reserved.
++ * dataPartyNumber [3] IMPLICIT NumberDigits,
++ *
++ * -- not used, value reserved.
++ * telexPartyNumber [4] IMPLICIT NumberDigits,
++ * privatePartyNumber [5] IMPLICIT PrivatePartyNumber,
++ *
++ * -- not used, value reserved.
++ * nationalStandardPartyNumber [8] IMPLICIT NumberDigits
++ * }
++ */
++struct rosePartyNumber {
++ /*!
++ * \brief Party numbering plan
++ * \details
++ * unknown(0),
++ * public(1) - The numbering plan is according to ITU-T E.164,
++ * nsapEncoded(2),
++ * data(3) - Reserved,
++ * telex(4) - Reserved,
++ * private(5),
++ * nationalStandard(8) - Reserved
++ */
++ u_int8_t plan;
++
++ /*!
++ * \brief Type-Of-Number valid for public and private party number plans
++ * \details
++ * public:
++ * unknown(0),
++ * internationalNumber(1),
++ * nationalNumber(2),
++ * networkSpecificNumber(3) - Reserved,
++ * subscriberNumber(4) - Reserved,
++ * abbreviatedNumber(6)
++ * \details
++ * private:
++ * unknown(0),
++ * level2RegionalNumber(1),
++ * level1RegionalNumber(2),
++ * pTNSpecificNumber/pISNSpecificNumber(3),
++ * localNumber(4),
++ * abbreviatedNumber(6)
++ */
++ u_int8_t ton;
++
++ /*! \brief Number present if length is nonzero. */
++ u_int8_t length;
++
++ /*! \brief Number string data. */
++ unsigned char str[20 + 1];
++};
++
++/*
++ * NumberScreened ::= SEQUENCE {
++ * partyNumber PartyNumber,
++ * screeningIndicator ScreeningIndicator
++ * }
++ */
++struct roseNumberScreened {
++ struct rosePartyNumber number;
++
++ /*!
++ * \details
++ * userProvidedNotScreened(0),
++ * userProvidedVerifiedAndPassed(1),
++ * userProvidedVerifiedAndFailed(2) (Not used, value reserved),
++ * networkProvided(3)
++ */
++ u_int8_t screening_indicator;
++};
++
++/*
++ * PartySubaddress ::= CHOICE {
++ * -- not recommended
++ * UserSpecifiedSubaddress,
++ *
++ * -- according to ITU-T Recommendation X.213
++ * NSAPSubaddress
++ * }
++ *
++ * UserSpecifiedSubaddress ::= SEQUENCE {
++ * SubaddressInformation,
++ *
++ * -- used when the coding of subaddress is BCD
++ * oddCountIndicator BOOLEAN OPTIONAL
++ * }
++ *
++ * -- specified according to ITU-T Recommendation X.213. Some
++ * -- networks may limit the subaddress value to some other
++ * -- length, e.g. 4 octets
++ * NSAPSubaddress ::= OCTET STRING (SIZE(1..20))
++ *
++ * -- coded according to user requirements. Some networks may
++ * -- limit the subaddress value to some other length,
++ * -- e.g. 4 octets
++ * SubaddressInformation ::= OCTET STRING (SIZE(1..20))
++ */
++struct rosePartySubaddress {
++ /*! \brief Subaddress type UserSpecified(0), NSAP(1) */
++ u_int8_t type;
++
++ /*! \brief Subaddress present if length is nonzero */
++ u_int8_t length;
++
++ union {
++ /*! \brief Specified according to ITU-T Recommendation X.213 */
++ unsigned char nsap[20 + 1];
++
++ /*! \brief Use of this formatting is not recommended */
++ struct {
++ /*! \brief TRUE if OddCount present */
++ u_int8_t odd_count_present;
++
++ /*!
++ * \brief TRUE if odd number of BCD digits (optional)
++ * \note Used when the coding of subaddress is BCD.
++ */
++ u_int8_t odd_count;
++ unsigned char information[20 + 1];
++ } user_specified;
++ } u;
++};
++
++/*
++ * Address ::= SEQUENCE {
++ * PartyNumber,
++ * PartySubaddress OPTIONAL
++ * }
++ */
++struct roseAddress {
++ struct rosePartyNumber number;
++
++ /*! \brief Subaddress (Optional) */
++ struct rosePartySubaddress subaddress;
++};
++
++/*
++ * AddressScreened ::= SEQUENCE {
++ * PartyNumber,
++ * ScreeningIndicator,
++ * PartySubaddress OPTIONAL
++ * }
++ */
++struct roseAddressScreened {
++ struct rosePartyNumber number;
++
++ /*! \brief Subaddress (Optional) */
++ struct rosePartySubaddress subaddress;
++
++ /*!
++ * \details
++ * userProvidedNotScreened(0),
++ * userProvidedVerifiedAndPassed(1),
++ * userProvidedVerifiedAndFailed(2) (Not used, value reserved),
++ * networkProvided(3)
++ */
++ u_int8_t screening_indicator;
++};
++
++/*
++ * PresentedNumberUnscreened ::= CHOICE {
++ * presentationAllowedNumber [0] EXPLICIT PartyNumber,
++ * presentationRestricted [1] IMPLICIT NULL,
++ * numberNotAvailableDueToInterworking [2] IMPLICIT NULL,
++ * presentationRestrictedNumber [3] EXPLICIT PartyNumber
++ * }
++ */
++struct rosePresentedNumberUnscreened {
++ struct rosePartyNumber number;
++ /*!
++ * \brief Number presentation type
++ * \details
++ * presentationAllowedNumber(0),
++ * presentationRestricted(1),
++ * numberNotAvailableDueToInterworking(2),
++ * presentationRestrictedNumber(3)
++ */
++ u_int8_t presentation;
++};
++
++/*
++ * PresentedNumberScreened ::= CHOICE {
++ * presentationAllowedNumber [0] IMPLICIT NumberScreened,
++ * presentationRestricted [1] IMPLICIT NULL,
++ * numberNotAvailableDueToInterworking [2] IMPLICIT NULL,
++ * presentationRestrictedNumber [3] IMPLICIT NumberScreened
++ * }
++ */
++struct rosePresentedNumberScreened {
++ /*! \brief Screened number */
++ struct roseNumberScreened screened;
++ /*!
++ * \brief Number presentation type
++ * \details
++ * presentationAllowedNumber(0),
++ * presentationRestricted(1),
++ * numberNotAvailableDueToInterworking(2),
++ * presentationRestrictedNumber(3)
++ */
++ u_int8_t presentation;
++};
++
++/*
++ * PresentedAddressScreened ::= CHOICE {
++ * presentationAllowedAddress [0] IMPLICIT AddressScreened,
++ * presentationRestricted [1] IMPLICIT NULL,
++ * numberNotAvailableDueToInterworking [2] IMPLICIT NULL,
++ * presentationRestrictedAddress [3] IMPLICIT AddressScreened
++ * }
++ */
++struct rosePresentedAddressScreened {
++ /*! \breif Screened address */
++ struct roseAddressScreened screened;
++ /*!
++ * \brief Address presentation type
++ * \details
++ * presentationAllowedAddress(0),
++ * presentationRestricted(1),
++ * numberNotAvailableDueToInterworking(2),
++ * presentationRestrictedAddress(3)
++ */
++ u_int8_t presentation;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * Time ::= SEQUENCE {
++ * lengthOfTimeUnit [1] IMPLICIT LengthOfTimeUnit,
++ * scale [2] IMPLICIT Scale
++ * }
++ */
++struct roseEtsiAOCTime {
++ /*! LengthOfTimeUnit ::= INTEGER (0..16777215) -- 24 bit number */
++ u_int32_t length;
++ /*!
++ * \details
++ * oneHundredthSecond(0),
++ * oneTenthSecond(1),
++ * oneSecond(2),
++ * tenSeconds(3),
++ * oneMinute(4),
++ * oneHour(5),
++ * twentyFourHours(6)
++ */
++ u_int8_t scale;
++};
++
++/*
++ * Amount ::= SEQUENCE {
++ * currencyAmount [1] IMPLICIT CurrencyAmount,
++ * multiplier [2] IMPLICIT Multiplier
++ * }
++ */
++struct roseEtsiAOCAmount {
++ /*! CurrencyAmount ::= INTEGER (0..16777215) -- 24 bit number */
++ u_int32_t currency;
++ /*!
++ * \details
++ * oneThousandth(0),
++ * oneHundredth(1),
++ * oneTenth(2),
++ * one(3),
++ * ten(4),
++ * hundred(5),
++ * thousand(6)
++ */
++ u_int8_t multiplier;
++};
++
++/*
++ * DurationCurrency ::= SEQUENCE {
++ * dCurrency [1] IMPLICIT Currency,
++ * dAmount [2] IMPLICIT Amount,
++ * dChargingType [3] IMPLICIT ChargingType,
++ * dTime [4] IMPLICIT Time,
++ * dGranularity [5] IMPLICIT Time OPTIONAL
++ * }
++ */
++struct roseEtsiAOCDurationCurrency {
++ struct roseEtsiAOCAmount amount;
++ struct roseEtsiAOCTime time;
++ /*! \breif dGranularity (optional) */
++ struct roseEtsiAOCTime granularity;
++ /*! Currency ::= IA5String (SIZE (1..10)) -- Name of currency. */
++ unsigned char currency[10 + 1];
++ /*!
++ * \details
++ * continuousCharging(0),
++ * stepFunction(1)
++ */
++ u_int8_t charging_type;
++ /*! TRUE if granularity time is present */
++ u_int8_t granularity_present;
++};
++
++/*
++ * FlatRateCurrency ::= SEQUENCE {
++ * fRCurrency [1] IMPLICIT Currency,
++ * fRAmount [2] IMPLICIT Amount
++ * }
++ */
++struct roseEtsiAOCFlatRateCurrency {
++ struct roseEtsiAOCAmount amount;
++ /*! Currency ::= IA5String (SIZE (1..10)) -- Name of currency. */
++ unsigned char currency[10 + 1];
++};
++
++/*
++ * VolumeRateCurrency ::= SEQUENCE {
++ * vRCurrency [1] IMPLICIT Currency,
++ * vRAmount [2] IMPLICIT Amount,
++ * vRVolumeUnit [3] IMPLICIT VolumeUnit
++ * }
++ */
++struct roseEtsiAOCVolumeRateCurrency {
++ struct roseEtsiAOCAmount amount;
++ /*! Currency ::= IA5String (SIZE (1..10)) -- Name of currency. */
++ unsigned char currency[10 + 1];
++ /*!
++ * \brief Volume rate volume unit
++ * \details
++ * octet(0),
++ * segment(1),
++ * message(2)
++ */
++ u_int8_t unit;
++};
++
++/*
++ * AOCSCurrencyInfo ::= SEQUENCE {
++ * chargedItem ChargedItem,
++ * CHOICE {
++ * specialChargingCode SpecialChargingCode,
++ * durationCurrency [1] IMPLICIT DurationCurrency,
++ * flatRateCurrency [2] IMPLICIT FlatRateCurrency,
++ * volumeRateCurrency [3] IMPLICIT VolumeRateCurrency
++ * freeOfCharge [4] IMPLICIT NULL,
++ * currencyInfoNotAvailable [5] IMPLICIT NULL
++ * }
++ * }
++ */
++struct roseEtsiAOCSCurrencyInfo {
++ union {
++ struct roseEtsiAOCDurationCurrency duration;
++ struct roseEtsiAOCFlatRateCurrency flat_rate;
++ struct roseEtsiAOCVolumeRateCurrency volume_rate;
++ /*! SpecialChargingCode ::= INTEGER (1..10) */
++ u_int8_t special_charging_code;
++ } u;
++ /*!
++ * \brief Determine what is stored in the union.
++ * \details
++ * specialChargingCode(0),
++ * durationCurrency(1),
++ * flatRateCurrency(2),
++ * volumeRateCurrency(3),
++ * freeOfCharge(4),
++ * currencyInfoNotAvailable(5),
++ */
++ u_int8_t currency_type;
++ /*!
++ * \brief What service is being billed.
++ * \details
++ * basicCommunication(0),
++ * callAttempt(1),
++ * callSetup(2),
++ * userToUserInfo(3),
++ * operationOfSupplementaryServ(4)
++ */
++ u_int8_t charged_item;
++};
++
++/*
++ * AOCSCurrencyInfoList ::= SEQUENCE SIZE (1..10) OF AOCSCurrencyInfo
++ */
++struct roseEtsiAOCSCurrencyInfoList {
++ /*! \brief SEQUENCE SIZE (1..10) OF AOCSCurrencyInfo */
++ struct roseEtsiAOCSCurrencyInfo list[10];
++
++ /*! \brief Number of AOCSCurrencyInfo records present */
++ u_int8_t num_records;
++};
++
++/*
++ * RecordedCurrency ::= SEQUENCE {
++ * rCurrency [1] IMPLICIT Currency,
++ * rAmount [2] IMPLICIT Amount
++ * }
++ */
++struct roseEtsiAOCRecordedCurrency {
++ /*! Amount of currency involved. */
++ struct roseEtsiAOCAmount amount;
++ /*! Currency ::= IA5String (SIZE (1..10)) -- Name of currency. */
++ unsigned char currency[10 + 1];
++};
++
++/*
++ * RecordedUnits ::= SEQUENCE {
++ * CHOICE {
++ * recordedNumberOfUnits NumberOfUnits,
++ * notAvailable NULL
++ * },
++ * recordedTypeOfUnits TypeOfUnit OPTIONAL
++ * }
++ */
++struct roseEtsiAOCRecordedUnits {
++ /*! \brief recordedNumberOfUnits INTEGER (0..16777215) -- 24 bit number */
++ u_int32_t number_of_units;
++ /*! \brief TRUE if number_of_units is not available (not present) */
++ u_int8_t not_available;
++ /*! \brief recordedTypeOfUnits INTEGER (1..16) (optional) */
++ u_int8_t type_of_unit;
++ /*! \brief TRUE if type_of_unit is present */
++ u_int8_t type_of_unit_present;
++};
++
++/*
++ * RecordedUnitsList ::= SEQUENCE SIZE (1..32) OF RecordedUnits
++ */
++struct roseEtsiAOCRecordedUnitsList {
++ /*! \brief SEQUENCE SIZE (1..32) OF RecordedUnits */
++ struct roseEtsiAOCRecordedUnits list[32];
++
++ /*! \brief Number of RecordedUnits records present */
++ u_int8_t num_records;
++};
++
++/*
++ * ChargingAssociation ::= CHOICE {
++ * chargedNumber [0] EXPLICIT PartyNumber,
++ * chargeIdentifier ChargeIdentifier
++ * }
++ */
++struct roseEtsiAOCChargingAssociation {
++ /*! chargeIdentifier: INTEGER (-32768..32767) -- 16 bit number */
++ int16_t id;
++ /*! chargedNumber */
++ struct rosePartyNumber number;
++ /*!
++ * \details
++ * charge_identifier(0),
++ * charged_number(1)
++ */
++ u_int8_t type;
++};
++
++/*
++ * AOCECurrencyInfo ::= SEQUENCE {
++ * CHOICE {
++ * freeOfCharge [1] IMPLICIT NULL,
++ * specificCurrency SEQUENCE {
++ * recordedCurrency [1] IMPLICIT RecordedCurrency,
++ * aOCEBillingId [2] IMPLICIT AOCEBillingId OPTIONAL
++ * }
++ * },
++ * chargingAssociation ChargingAssociation OPTIONAL
++ * }
++ */
++struct roseEtsiAOCECurrencyInfo {
++ struct {
++ /*! \brief recorded currency */
++ struct roseEtsiAOCRecordedCurrency recorded;
++ /*!
++ * \brief AOCEBillingId (optional)
++ * \details
++ * normalCharging(0),
++ * reverseCharging(1),
++ * creditCardCharging(2),
++ * callForwardingUnconditional(3),
++ * callForwardingBusy(4),
++ * callForwardingNoReply(5),
++ * callDeflection(6),
++ * callTransfer(7)
++ */
++ u_int8_t billing_id;
++ /*! \brief TRUE if billing id is present */
++ u_int8_t billing_id_present;
++ } specific;
++
++ /*! \brief chargingAssociation (optional) */
++ struct roseEtsiAOCChargingAssociation charging_association;
++
++ /*! \brief TRUE if charging_association is present */
++ u_int8_t charging_association_present;
++
++ /*!
++ * \brief TRUE if this is free of charge.
++ * \note When TRUE, the contents of specific are not valid.
++ */
++ u_int8_t free_of_charge;
++};
++
++/*
++ * AOCEChargingUnitInfo ::= SEQUENCE {
++ * CHOICE {
++ * freeOfCharge [1] IMPLICIT NULL,
++ * specificChargingUnits SEQUENCE
++ * {
++ * recordedUnitsList [1] IMPLICIT RecordedUnitsList,
++ * aOCEBillingId [2] IMPLICIT AOCEBillingId OPTIONAL
++ * }
++ * },
++ * chargingAssociation ChargingAssociation OPTIONAL
++ * }
++ */
++struct roseEtsiAOCEChargingUnitInfo {
++ /*! \brief Not valid if free_of_charge is TRUE */
++ struct {
++ /*! \brief RecordedUnitsList */
++ struct roseEtsiAOCRecordedUnitsList recorded;
++ /*!
++ * \brief AOCEBillingId (optional)
++ * \details
++ * normalCharging(0),
++ * reverseCharging(1),
++ * creditCardCharging(2),
++ * callForwardingUnconditional(3),
++ * callForwardingBusy(4),
++ * callForwardingNoReply(5),
++ * callDeflection(6),
++ * callTransfer(7)
++ */
++ u_int8_t billing_id;
++ /*! \brief TRUE if billing id is present */
++ u_int8_t billing_id_present;
++ } specific;
++
++ /*! \brief chargingAssociation (optional) */
++ struct roseEtsiAOCChargingAssociation charging_association;
++
++ /*! \brief TRUE if charging_association is present */
++ u_int8_t charging_association_present;
++
++ /*!
++ * \brief TRUE if this is free of charge.
++ * \note When TRUE, the contents of specific are not valid.
++ */
++ u_int8_t free_of_charge;
++};
++
++/*
++ * ARGUMENT ChargingCase
++ */
++struct roseEtsiChargingRequest_ARG {
++ /*!
++ * \details
++ * chargingInformationAtCallSetup(0),
++ * chargingDuringACall(1),
++ * chargingAtTheEndOfACall(2)
++ */
++ u_int8_t charging_case;
++};
++
++/*
++ * RESULT CHOICE {
++ * AOCSCurrencyInfoList,
++ * AOCSSpecialArrInfo,
++ * chargingInfoFollows NULL
++ * }
++ */
++struct roseEtsiChargingRequest_RES {
++ union {
++ struct roseEtsiAOCSCurrencyInfoList currency_info;
++
++ /*! AOCSSpecialArrInfo ::= INTEGER (1..10) */
++ u_int8_t special_arrangement;
++ } u;
++ /*!
++ * \details
++ * currency_info_list(0),
++ * special_arrangement_info(1),
++ * charging_info_follows(2)
++ */
++ u_int8_t type;
++};
++
++/*
++ * ARGUMENT CHOICE {
++ * chargeNotAvailable NULL,
++ * AOCSCurrencyInfoList
++ * }
++ */
++struct roseEtsiAOCSCurrency_ARG {
++ struct roseEtsiAOCSCurrencyInfoList currency_info;
++ /*!
++ * \details
++ * charge_not_available(0),
++ * currency_info_list(1)
++ */
++ u_int8_t type;
++};
++
++/*
++ * ARGUMENT CHOICE {
++ * chargeNotAvailable NULL,
++ * AOCSSpecialArrInfo
++ * }
++ */
++struct roseEtsiAOCSSpecialArr_ARG {
++ /*!
++ * \details
++ * charge_not_available(0),
++ * special_arrangement_info(1)
++ */
++ u_int8_t type;
++ /*! AOCSSpecialArrInfo ::= INTEGER (1..10) */
++ u_int8_t special_arrangement;
++};
++
++/*
++ * ARGUMENT CHOICE {
++ * chargeNotAvailable NULL,
++ * aOCDCurrencyInfo CHOICE {
++ * freeOfCharge [1] IMPLICIT NULL,
++ * specificCurrency SEQUENCE {
++ * recordedCurrency [1] IMPLICIT RecordedCurrency,
++ * typeOfChargingInfo [2] IMPLICIT TypeOfChargingInfo,
++ * aOCDBillingId [3] IMPLICIT AOCDBillingId OPTIONAL
++ * }
++ * }
++ * }
++ */
++struct roseEtsiAOCDCurrency_ARG {
++ struct {
++ /*! \brief recorded currency */
++ struct roseEtsiAOCRecordedCurrency recorded;
++ /*!
++ * \brief Type of recorded charging information.
++ * \details
++ * subTotal(0),
++ * total(1)
++ */
++ u_int8_t type_of_charging_info;
++ /*!
++ * \brief AOCDBillingId (optional)
++ * \details
++ * normalCharging(0),
++ * reverseCharging(1),
++ * creditCardCharging(2)
++ */
++ u_int8_t billing_id;
++ /*! \brief TRUE if billing id is present */
++ u_int8_t billing_id_present;
++ } specific;
++ /*!
++ * \details
++ * charge_not_available(0),
++ * free_of_charge(1),
++ * specific_currency(2)
++ */
++ u_int8_t type;
++};
++
++/*
++ * ARGUMENT CHOICE {
++ * chargeNotAvailable NULL,
++ * aOCDChargingUnitInfo CHOICE {
++ * freeOfCharge [1] IMPLICIT NULL,
++ * specificChargingUnits SEQUENCE {
++ * recordedUnitsList [1] IMPLICIT RecordedUnitsList,
++ * typeOfChargingInfo [2] IMPLICIT TypeOfChargingInfo,
++ * aOCDBillingId [3] IMPLICIT AOCDBillingId OPTIONAL
++ * }
++ * }
++ * }
++ */
++struct roseEtsiAOCDChargingUnit_ARG {
++ struct {
++ /*! \brief RecordedUnitsList */
++ struct roseEtsiAOCRecordedUnitsList recorded;
++ /*!
++ * \brief Type of recorded charging information.
++ * \details
++ * subTotal(0),
++ * total(1)
++ */
++ u_int8_t type_of_charging_info;
++ /*!
++ * \brief AOCDBillingId (optional)
++ * \details
++ * normalCharging(0),
++ * reverseCharging(1),
++ * creditCardCharging(2)
++ */
++ u_int8_t billing_id;
++ /*! \brief TRUE if billing id is present */
++ u_int8_t billing_id_present;
++ } specific;
++ /*!
++ * \details
++ * charge_not_available(0),
++ * free_of_charge(1),
++ * specific_charging_units(2)
++ */
++ u_int8_t type;
++};
++
++/*
++ * ARGUMENT CHOICE {
++ * chargeNotAvailable NULL,
++ * AOCECurrencyInfo
++ * }
++ */
++struct roseEtsiAOCECurrency_ARG {
++ struct roseEtsiAOCECurrencyInfo currency_info;
++ /*!
++ * \details
++ * charge_not_available(0),
++ * currency_info(1)
++ */
++ u_int8_t type;
++};
++
++/*
++ * ARGUMENT CHOICE {
++ * chargeNotAvailable NULL,
++ * AOCEChargingUnitInfo
++ * }
++ */
++struct roseEtsiAOCEChargingUnit_ARG {
++ struct roseEtsiAOCEChargingUnitInfo charging_unit;
++ /*!
++ * \details
++ * charge_not_available(0),
++ * charging_unit(1)
++ */
++ u_int8_t type;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * ARGUMENT SEQUENCE {
++ * procedure Procedure,
++ * basicService BasicService,
++ * forwardedToAddress Address,
++ * servedUserNr ServedUserNr
++ * }
++ */
++struct roseEtsiActivationDiversion_ARG {
++ /*! \brief Forwarded to address */
++ struct roseAddress forwarded_to;
++
++ /*! \brief Forward all numbers if not present (Number length is zero). */
++ struct rosePartyNumber served_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3k1Hz(3),
++ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
++ * multirate(5),
++ * telephony3k1Hz(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * telephony7kHz(38),
++ * euroFileTransfer(39),
++ * fileTransferAndAccessManagement(40),
++ * videoconference(41),
++ * audioGraphicConference(42)
++ */
++ u_int8_t basic_service;
++};
++
++
++/*
++ * ARGUMENT SEQUENCE {
++ * procedure Procedure,
++ * basicService BasicService,
++ * servedUserNr ServedUserNr
++ * }
++ */
++struct roseEtsiDeactivationDiversion_ARG {
++ /*! \brief Forward all numbers if not present (Number length is zero). */
++ struct rosePartyNumber served_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3k1Hz(3),
++ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
++ * multirate(5),
++ * telephony3k1Hz(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * telephony7kHz(38),
++ * euroFileTransfer(39),
++ * fileTransferAndAccessManagement(40),
++ * videoconference(41),
++ * audioGraphicConference(42)
++ */
++ u_int8_t basic_service;
++};
++
++
++/*
++ * ARGUMENT SEQUENCE {
++ * procedure Procedure,
++ * basicService BasicService,
++ * forwardedToAddresss Address,
++ * servedUserNr ServedUserNr
++ * }
++ */
++struct roseEtsiActivationStatusNotificationDiv_ARG {
++ /*! \brief Forwarded to address */
++ struct roseAddress forwarded_to;
++
++ /*! \brief Forward all numbers if not present (Number length is zero). */
++ struct rosePartyNumber served_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3k1Hz(3),
++ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
++ * multirate(5),
++ * telephony3k1Hz(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * telephony7kHz(38),
++ * euroFileTransfer(39),
++ * fileTransferAndAccessManagement(40),
++ * videoconference(41),
++ * audioGraphicConference(42)
++ */
++ u_int8_t basic_service;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * procedure Procedure,
++ * basicService BasicService,
++ * servedUserNr ServedUserNr
++ * }
++ */
++struct roseEtsiDeactivationStatusNotificationDiv_ARG {
++ /*! \brief Forward all numbers if not present (Number length is zero). */
++ struct rosePartyNumber served_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3k1Hz(3),
++ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
++ * multirate(5),
++ * telephony3k1Hz(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * telephony7kHz(38),
++ * euroFileTransfer(39),
++ * fileTransferAndAccessManagement(40),
++ * videoconference(41),
++ * audioGraphicConference(42)
++ */
++ u_int8_t basic_service;
++};
++
++
++/*
++ * ARGUMENT SEQUENCE {
++ * procedure Procedure,
++ * basicService BasicService DEFAULT allServices,
++ * servedUserNr ServedUserNr
++ * }
++ */
++struct roseEtsiInterrogationDiversion_ARG {
++ /*! \brief Forward all numbers if not present (Number length is zero). */
++ struct rosePartyNumber served_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * DEFAULT allServices
++ *
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3k1Hz(3),
++ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
++ * multirate(5),
++ * telephony3k1Hz(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * telephony7kHz(38),
++ * euroFileTransfer(39),
++ * fileTransferAndAccessManagement(40),
++ * videoconference(41),
++ * audioGraphicConference(42)
++ */
++ u_int8_t basic_service;
++};
++
++/*
++ * IntResult ::= SEQUENCE {
++ * servedUserNr ServedUserNr,
++ * basicService BasicService,
++ * procedure Procedure,
++ * forwardedToAddress Address
++ * }
++ */
++struct roseEtsiForwardingRecord {
++ /*! \brief Forwarded to address */
++ struct roseAddress forwarded_to;
++
++ /*! \brief Forward all numbers if not present (Number length is zero). */
++ struct rosePartyNumber served_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3k1Hz(3),
++ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
++ * multirate(5),
++ * telephony3k1Hz(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * telephony7kHz(38),
++ * euroFileTransfer(39),
++ * fileTransferAndAccessManagement(40),
++ * videoconference(41),
++ * audioGraphicConference(42)
++ */
++ u_int8_t basic_service;
++};
++
++/*
++ * roseInterrogationDiversion_RES
++ * IntResultList ::= SET SIZE (0..29) OF IntResult
++ */
++struct roseEtsiForwardingList {
++ /*!
++ * \brief SET SIZE (0..29) OF Forwarding Records
++ * \note Reduced the size of the array to conserve
++ * potential stack usage.
++ */
++ struct roseEtsiForwardingRecord list[10];
++
++ /*! \brief Number of Forwarding records present */
++ u_int8_t num_records;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * diversionReason DiversionReason,
++ * basicService BasicService,
++ * servedUserSubaddress PartySubaddress OPTIONAL,
++ * callingAddress [0] EXPLICIT PresentedAddressScreened OPTIONAL,
++ * originalCalledNr [1] EXPLICIT PresentedNumberUnscreened OPTIONAL,
++ * lastDivertingNr [2] EXPLICIT PresentedNumberUnscreened OPTIONAL,
++ * lastDivertingReason [3] EXPLICIT DiversionReason OPTIONAL,
++ *
++ * -- The User-user information element, as specified
++ * -- in ETS 300 102-1 [11], subclause 4.5.29, shall
++ * -- be embedded in the userInfo parameter.
++ * userInfo Q931InformationElement OPTIONAL
++ * }
++ */
++struct roseEtsiDiversionInformation_ARG {
++ /*! \brief Served user subaddress (Optional) */
++ struct rosePartySubaddress served_user_subaddress;
++
++ /*! \brief Calling address (Optional) */
++ struct rosePresentedAddressScreened calling;
++
++ /*! \brief Original called number (Optional) */
++ struct rosePresentedNumberUnscreened original_called;
++
++ /*! \brief Last diverting number (Optional) */
++ struct rosePresentedNumberUnscreened last_diverting;
++
++ /*! \brief User-User information embedded in Q.931 IE (Optional) */
++ struct roseQ931ie q931ie;
++ /*! \brief q931ie.contents "allocated" after the stucture. */
++ unsigned char q931ie_contents[ROSE_Q931_MAX_USER + 1];
++
++ /*!
++ * \brief Last diverting reason (Optional)
++ *
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3),
++ * cdAlerting(4),
++ * cdImmediate(5)
++ */
++ u_int8_t last_diverting_reason;
++
++ /*! \brief TRUE if CallingAddress is present */
++ u_int8_t calling_present;
++
++ /*! \brief TRUE if OriginalCalled is present */
++ u_int8_t original_called_present;
++
++ /*! \brief TRUE if LastDiverting is present */
++ u_int8_t last_diverting_present;
++
++ /*! \brief TRUE if LastDivertingReason is present */
++ u_int8_t last_diverting_reason_present;
++
++ /*!
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3),
++ * cdAlerting(4),
++ * cdImmediate(5)
++ */
++ u_int8_t diversion_reason;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3k1Hz(3),
++ * unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
++ * multirate(5),
++ * telephony3k1Hz(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * telephony7kHz(38),
++ * euroFileTransfer(39),
++ * fileTransferAndAccessManagement(40),
++ * videoconference(41),
++ * audioGraphicConference(42)
++ */
++ u_int8_t basic_service;
++};
++
++
++/*
++ * ARGUMENT SEQUENCE {
++ * deflectionAddress Address,
++ * presentationAllowedDivertedToUser PresentationAllowedIndicator OPTIONAL
++ * }
++ */
++struct roseEtsiCallDeflection_ARG {
++ /*! \brief Deflection address (Deflected-To address) */
++ struct roseAddress deflection;
++
++ /*! \brief TRUE if PresentationAllowedToDivertedToUser is present */
++ u_int8_t presentation_allowed_to_diverted_to_user_present;
++
++ /*! \brief TRUE if presentation is allowed (Optional) */
++ u_int8_t presentation_allowed_to_diverted_to_user;
++};
++
++
++/*
++ * ARGUMENT SEQUENCE {
++ * reroutingReason DiversionReason,
++ * calledAddress Address,
++ * reroutingCounter DiversionCounter,
++ *
++ * -- The User-user information element (optional),
++ * -- High layer compatibility information element (optional),
++ * -- Bearer capability information element
++ * -- and Low layer compatibility information element (optional)
++ * -- as specified in ETS 300 102-1 [11] subclause 4.5 shall be
++ * -- embedded in the q931InfoElement.
++ * q931InfoElement Q931InformationElement,
++ * lastReroutingNr [1] EXPLICIT PresentedNumberUnscreened,
++ * subscriptionOption [2] EXPLICIT SubscriptionOption DEFAULT noNotification,
++ * callingPartySubaddress [3] EXPLICIT PartySubaddress OPTIONAL
++ * }
++ */
++struct roseEtsiCallRerouting_ARG {
++ struct roseAddress called_address;
++
++ /*! \brief The BC, HLC (optional), LLC (optional), and User-user (optional) information */
++ struct roseQ931ie q931ie;
++ /*! \brief q931ie.contents "allocated" after the stucture. */
++ unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
++ ROSE_Q931_MAX_LLC + ROSE_Q931_MAX_USER + 1];
++
++ /*! \brief Last rerouting number */
++ struct rosePresentedNumberUnscreened last_rerouting;
++
++ /*! \brief Calling party subaddress (Optional) */
++ struct rosePartySubaddress calling_subaddress;
++
++ /*!
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3),
++ * cdAlerting(4),
++ * cdImmediate(5)
++ */
++ u_int8_t rerouting_reason;
++
++ /*! \brief Range 1-5 */
++ u_int8_t rerouting_counter;
++
++ /*!
++ * \details
++ * DEFAULT noNotification
++ *
++ * \details
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ */
++ u_int8_t subscription_option;
++};
++
++
++/*
++ * roseInterrogateServedUserNumbers_RES
++ * ServedUserNumberList ::= SET SIZE (0..99) OF PartyNumber
++ */
++struct roseEtsiServedUserNumberList {
++ /*!
++ * \brief SET SIZE (0..99) OF Served user numbers
++ * \note Reduced the size of the array to conserve
++ * potential stack usage.
++ */
++ struct rosePartyNumber number[20];
++
++ /*! \brief Number of Served user numbers present */
++ u_int8_t num_records;
++};
++
++
++/*
++ * ARGUMENT SEQUENCE {
++ * diversionReason DiversionReason,
++ * subscriptionOption SubscriptionOption,
++ * divertedToNumber PresentedNumberUnscreened OPTIONAL
++ * }
++ */
++struct roseEtsiDivertingLegInformation1_ARG {
++ /*! \brief Diverted to number (Optional) */
++ struct rosePresentedNumberUnscreened diverted_to;
++
++ /*! \brief TRUE if DivertedTo is present */
++ u_int8_t diverted_to_present;
++
++ /*!
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3),
++ * cdAlerting(4),
++ * cdImmediate(5)
++ */
++ u_int8_t diversion_reason;
++
++ /*!
++ * \details
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ */
++ u_int8_t subscription_option;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * diversionCounter DiversionCounter,
++ * diversionReason DiversionReason,
++ * divertingNr [1] EXPLICIT PresentedNumberUnscreened OPTIONAL,
++ * originalCalledNr [2] EXPLICIT PresentedNumberUnscreened OPTIONAL
++ * }
++ */
++struct roseEtsiDivertingLegInformation2_ARG {
++ /*! \brief Diverting number (Optional) */
++ struct rosePresentedNumberUnscreened diverting;
++
++ /*! \brief Original called number (Optional) */
++ struct rosePresentedNumberUnscreened original_called;
++
++ /*! \brief TRUE if Diverting number is present */
++ u_int8_t diverting_present;
++
++ /*! \brief TRUE if OriginalCalled is present */
++ u_int8_t original_called_present;
++
++ /*!
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3),
++ * cdAlerting(4),
++ * cdImmediate(5)
++ */
++ u_int8_t diversion_reason;
++
++ /*! \brief Range 1-5 */
++ u_int8_t diversion_counter;
++};
++
++/*
++ * ARGUMENT presentationAllowedIndicator PresentationAllowedIndicator
++ */
++struct roseEtsiDivertingLegInformation3_ARG {
++ /*! \brief TRUE if presentation is allowed */
++ u_int8_t presentation_allowed_indicator;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * ARGUMENT LinkId
++ */
++struct roseEtsiExplicitEctExecute_ARG {
++ int16_t link_id;
++};
++
++/*
++ * ARGUMENT transferredToSubaddress PartySubaddress
++ */
++struct roseEtsiSubaddressTransfer_ARG {
++ /*! \brief Transferred to subaddress */
++ struct rosePartySubaddress subaddress;
++};
++
++
++/*
++ * RESULT LinkId
++ */
++struct roseEtsiEctLinkIdRequest_RES {
++ int16_t link_id;
++};
++
++
++/*
++ * ARGUMENT SEQUENCE {
++ * ENUMERATED {
++ * alerting (0),
++ * active (1)
++ * },
++ * redirectionNumber PresentedNumberUnscreened OPTIONAL
++ * }
++ */
++struct roseEtsiEctInform_ARG {
++ /*! \brief Redirection Number (Optional) */
++ struct rosePresentedNumberUnscreened redirection;
++
++ /*! \brief TRUE if the Redirection Number is present */
++ u_int8_t redirection_present;
++
++ /*! \details alerting(0), active(1) */
++ u_int8_t status;
++};
++
++
++/*
++ * ARGUMENT CallTransferIdentity
++ */
++struct roseEtsiEctLoopTest_ARG {
++ int8_t call_transfer_id;
++};
++
++/*
++ * RESULT LoopResult
++ */
++struct roseEtsiEctLoopTest_RES {
++ /*!
++ * \details
++ * insufficientInformation(0),
++ * noLoopExists(1),
++ * simultaneousTransfer(2)
++ */
++ u_int8_t loop_result;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * Name ::= CHOICE {
++ * -- iso8859-1 is implied in namePresentationAllowedSimple.
++ * namePresentationAllowedSimple [0] IMPLICIT NameData,
++ * namePresentationAllowedExtended [1] IMPLICIT NameSet,
++ *
++ * -- iso8859-1 is implied in namePresentationRestrictedSimple.
++ * namePresentationRestrictedSimple [2] IMPLICIT NameData,
++ * namePresentationRestrictedExtended [3] IMPLICIT NameSet,
++ *
++ * -- namePresentationRestrictedNull shall only be used in the
++ * -- case of interworking where the other network provides an
++ * -- indication that the name is restricted without the name itself.
++ * namePresentationRestrictedNull [7] IMPLICIT NULL,
++ *
++ * nameNotAvailable [4] IMPLICIT NULL
++ * }
++ *
++ * NameSet ::= SEQUENCE {
++ * nameData NameData,
++ *
++ * -- If characterSet is not included, iso8859-1 is implied.
++ * characterSet CharacterSet OPTIONAL -- DEFAULT iso8859-1
++ * }
++ *
++ * -- The maximum allowed size of the name field is 50 octets.
++ * -- The minimum required size of the name field is 1 octet.
++ * NameData ::= OCTET STRING (SIZE (1..50))
++ */
++struct roseQsigName {
++ /*!
++ * \details
++ * optional_name_not_present(0),
++ * presentation_allowed(1),
++ * presentation_restricted(2),
++ * presentation_restricted_null(3),
++ * name_not_available(4)
++ */
++ u_int8_t presentation;
++
++ /*!
++ * \details
++ * Set to iso8859-1 if not present in the encoding.
++ *
++ * \details
++ * unknown(0),
++ * iso8859-1(1),
++ * enum-value-withdrawn-by-ITU-T(2)
++ * iso8859-2(3),
++ * iso8859-3(4),
++ * iso8859-4(5),
++ * iso8859-5(6),
++ * iso8859-7(7),
++ * iso10646-BmpString(8),
++ * iso10646-utf-8String(9)
++ */
++ u_int8_t char_set;
++
++ /*! \brief Length of name data */
++ u_int8_t length;
++
++ /*! \brief Name string data */
++ unsigned char data[50 + 1];
++};
++
++/*
++ * NOTE: We are not going to record the Extension information
++ * since it is manufacturer specific.
++ *
++ * ARGUMENT CHOICE {
++ * Name,
++ * SEQUENCE {
++ * Name,
++ * CHOICE {
++ * [5] IMPLICIT Extension,
++ * [6] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ * }
++ */
++struct roseQsigPartyName_ARG {
++ struct roseQsigName name;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * Time ::= SEQUENCE {
++ * lengthOfTimeUnit [1] IMPLICIT LengthOfTimeUnit,
++ * scale [2] IMPLICIT Scale
++ * }
++ */
++struct roseQsigAOCTime {
++ /*! LengthOfTimeUnit ::= INTEGER (0..16777215) -- 24 bit number */
++ u_int32_t length;
++ /*!
++ * \details
++ * oneHundredthSecond(0),
++ * oneTenthSecond(1),
++ * oneSecond(2),
++ * tenSeconds(3),
++ * oneMinute(4),
++ * oneHour(5),
++ * twentyFourHours(6)
++ */
++ u_int8_t scale;
++};
++
++/*
++ * Amount ::= SEQUENCE {
++ * currencyAmount [1] IMPLICIT CurrencyAmount,
++ * multiplier [2] IMPLICIT Multiplier
++ * }
++ */
++struct roseQsigAOCAmount {
++ /*! CurrencyAmount ::= INTEGER (0..16777215) -- 24 bit number */
++ u_int32_t currency;
++ /*!
++ * \details
++ * oneThousandth(0),
++ * oneHundredth(1),
++ * oneTenth(2),
++ * one(3),
++ * ten(4),
++ * hundred(5),
++ * thousand(6)
++ */
++ u_int8_t multiplier;
++};
++
++/*
++ * DurationCurrency ::= SEQUENCE {
++ * dCurrency [1] IMPLICIT Currency,
++ * dAmount [2] IMPLICIT Amount,
++ * dChargingType [3] IMPLICIT ChargingType,
++ * dTime [4] IMPLICIT Time,
++ * dGranularity [5] IMPLICIT Time OPTIONAL
++ * }
++ */
++struct roseQsigAOCDurationCurrency {
++ struct roseQsigAOCAmount amount;
++ struct roseQsigAOCTime time;
++ /*! \brief dGranularity (optional) */
++ struct roseQsigAOCTime granularity;
++ /*!
++ * \brief Name of currency
++ * \details
++ * Currency ::= IA5String (SIZE (0..10))
++ * \note The empty string is the default currency for the network.
++ */
++ unsigned char currency[10 + 1];
++ /*!
++ * \details
++ * continuousCharging(0),
++ * stepFunction(1)
++ */
++ u_int8_t charging_type;
++ /*! TRUE if granularity time is present */
++ u_int8_t granularity_present;
++};
++
++/*
++ * FlatRateCurrency ::= SEQUENCE {
++ * fRCurrency [1] IMPLICIT Currency,
++ * fRAmount [2] IMPLICIT Amount
++ * }
++ */
++struct roseQsigAOCFlatRateCurrency {
++ struct roseQsigAOCAmount amount;
++ /*!
++ * \brief Name of currency
++ * \details
++ * Currency ::= IA5String (SIZE (0..10))
++ * \note The empty string is the default currency for the network.
++ */
++ unsigned char currency[10 + 1];
++};
++
++/*
++ * VolumeRateCurrency ::= SEQUENCE {
++ * vRCurrency [1] IMPLICIT Currency,
++ * vRAmount [2] IMPLICIT Amount,
++ * vRVolumeUnit [3] IMPLICIT VolumeUnit
++ * }
++ */
++struct roseQsigAOCVolumeRateCurrency {
++ struct roseQsigAOCAmount amount;
++ /*!
++ * \brief Name of currency
++ * \details
++ * Currency ::= IA5String (SIZE (0..10))
++ * \note The empty string is the default currency for the network.
++ */
++ unsigned char currency[10 + 1];
++ /*!
++ * \brief Volume rate volume unit
++ * \details
++ * octet(0),
++ * segment(1),
++ * message(2)
++ */
++ u_int8_t unit;
++};
++
++/*
++ * AOCSCurrencyInfo ::= SEQUENCE {
++ * chargedItem ChargedItem,
++ * rateType CHOICE {
++ * durationCurrency [1] IMPLICIT DurationCurrency,
++ * flatRateCurrency [2] IMPLICIT FlatRateCurrency,
++ * volumeRateCurrency [3] IMPLICIT VolumeRateCurrency,
++ * specialChargingCode SpecialChargingCode,
++ * freeOfCharge [4] IMPLICIT NULL,
++ * currencyInfoNotAvailable [5] IMPLICIT NULL,
++ * freeOfChargefromBeginning [6] IMPLICIT NULL
++ * }
++ * }
++ */
++struct roseQsigAOCSCurrencyInfo {
++ union {
++ struct roseQsigAOCDurationCurrency duration;
++ struct roseQsigAOCFlatRateCurrency flat_rate;
++ struct roseQsigAOCVolumeRateCurrency volume_rate;
++ /*! SpecialChargingCode ::= INTEGER (1..10) */
++ u_int8_t special_charging_code;
++ } u;
++ /*!
++ * \brief Determine what is stored in the union.
++ * \details
++ * specialChargingCode(0),
++ * durationCurrency(1),
++ * flatRateCurrency(2),
++ * volumeRateCurrency(3),
++ * freeOfCharge(4),
++ * currencyInfoNotAvailable(5),
++ * freeOfChargeFromBeginning(6)
++ */
++ u_int8_t currency_type;
++ /*!
++ * \brief What service is being billed.
++ * \details
++ * basicCommunication(0),
++ * callAttempt(1),
++ * callSetup(2),
++ * userToUserInfo(3),
++ * operationOfSupplementaryServ(4)
++ */
++ u_int8_t charged_item;
++};
++
++/*
++ * AOCSCurrencyInfoList ::= SEQUENCE SIZE (1..10) OF AOCSCurrencyInfo
++ */
++struct roseQsigAOCSCurrencyInfoList {
++ /*! \brief SEQUENCE SIZE (1..10) OF AOCSCurrencyInfo */
++ struct roseQsigAOCSCurrencyInfo list[10];
++
++ /*! \brief Number of AOCSCurrencyInfo records present */
++ u_int8_t num_records;
++};
++
++/*
++ * RecordedCurrency ::= SEQUENCE {
++ * rCurrency [1] IMPLICIT Currency,
++ * rAmount [2] IMPLICIT Amount
++ * }
++ */
++struct roseQsigAOCRecordedCurrency {
++ /*! Amount of currency involved. */
++ struct roseQsigAOCAmount amount;
++ /*!
++ * \brief Name of currency
++ * \details
++ * Currency ::= IA5String (SIZE (0..10))
++ * \note The empty string is the default currency for the network.
++ */
++ unsigned char currency[10 + 1];
++};
++
++/*
++ * ChargingAssociation ::= CHOICE {
++ * chargedNumber [0] EXPLICIT PartyNumber,
++ * chargeIdentifier ChargeIdentifier
++ * }
++ */
++struct roseQsigAOCChargingAssociation {
++ /*! chargeIdentifier: INTEGER (-32768..32767) -- 16 bit number */
++ int16_t id;
++ /*! chargedNumber */
++ struct rosePartyNumber number;
++ /*!
++ * \details
++ * charge_identifier(0)
++ * charged_number(1),
++ */
++ u_int8_t type;
++};
++
++/*
++ * AocRateArg ::= SEQUENCE {
++ * aocRate CHOICE
++ * {
++ * chargeNotAvailable NULL,
++ * aocSCurrencyInfoList AOCSCurrencyInfoList
++ * },
++ * rateArgExtension CHOICE {
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigAocRateArg_ARG {
++ struct roseQsigAOCSCurrencyInfoList currency_info;
++ /*!
++ * \details
++ * charge_not_available(0),
++ * currency_info_list(1)
++ */
++ u_int8_t type;
++};
++
++/*
++ * AocInterimArg ::= SEQUENCE {
++ * interimCharge CHOICE {
++ * chargeNotAvailable [0] IMPLICIT NULL,
++ * freeOfCharge [1] IMPLICIT NULL,
++ * specificCurrency SEQUENCE {
++ * recordedCurrency [1] IMPLICIT RecordedCurrency,
++ * interimBillingId [2] IMPLICIT InterimBillingId OPTIONAL
++ * }
++ * },
++ * interimArgExtension CHOICE {
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigAocInterimArg_ARG {
++ struct {
++ /*! \brief recorded currency */
++ struct roseQsigAOCRecordedCurrency recorded;
++ /*!
++ * \brief InterimBillingId (optional)
++ * \details
++ * normalCharging(0),
++ * creditCardCharging(2)
++ */
++ u_int8_t billing_id;
++ /*! \brief TRUE if billing id is present */
++ u_int8_t billing_id_present;
++ } specific;
++ /*!
++ * \details
++ * charge_not_available(0),
++ * free_of_charge(1),
++ * specific_currency(2)
++ */
++ u_int8_t type;
++};
++
++/*
++ * AocFinalArg ::= SEQUENCE {
++ * finalCharge CHOICE {
++ * chargeNotAvailable [0] IMPLICIT NULL,
++ * freeOfCharge [1] IMPLICIT NULL,
++ * specificCurrency SEQUENCE {
++ * recordedCurrency [1] IMPLICIT RecordedCurrency,
++ * finalBillingId [2] IMPLICIT FinalBillingId OPTIONAL
++ * }
++ * },
++ * chargingAssociation ChargingAssociation OPTIONAL,
++ * finalArgExtension CHOICE {
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigAocFinalArg_ARG {
++ struct {
++ /*! \brief recorded currency */
++ struct roseQsigAOCRecordedCurrency recorded;
++ /*!
++ * \brief FinalBillingId (optional)
++ * \details
++ * normalCharging(0),
++ * creditCardCharging(2),
++ * callForwardingUnconditional(3),
++ * callForwardingBusy(4),
++ * callForwardingNoReply(5),
++ * callDeflection(6),
++ * callTransfer(7)
++ */
++ u_int8_t billing_id;
++ /*! \brief TRUE if billing id is present */
++ u_int8_t billing_id_present;
++ } specific;
++
++ /*! \brief chargingAssociation (optional) */
++ struct roseQsigAOCChargingAssociation charging_association;
++
++ /*! \brief TRUE if charging_association is present */
++ u_int8_t charging_association_present;
++
++ /*!
++ * \details
++ * charge_not_available(0),
++ * free_of_charge(1),
++ * specific_currency(2)
++ */
++ u_int8_t type;
++};
++
++/*
++ * ChargeRequestArg ::= SEQUENCE {
++ * adviceModeCombinations SEQUENCE SIZE(0..7) OF AdviceModeCombination,
++ * chargeReqArgExtension CHOICE {
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigChargeRequestArg_ARG {
++ /*!
++ * \brief SEQUENCE SIZE(0..7) OF AdviceModeCombination
++ * \details
++ * rate(0) <charge rate provision>,
++ * rateInterim(1) <charge rate and interim charge provision>,
++ * rateFinal(2) <charge rate and final charge provision>,
++ * interim(3) <interim charge provision>,
++ * final(4) <final charge provision>,
++ * interimFinal(5) <interim charge and final charge provision>,
++ * rateInterimFinal(6) <charge rate, interim charge and final charge provision>
++ */
++ u_int8_t advice_mode_combinations[7];
++
++ /*! \brief Number of AdviceModeCombination values present */
++ u_int8_t num_records;
++};
++
++/*
++ * ChargeRequestRes ::= SEQUENCE {
++ * adviceModeCombination AdviceModeCombination,
++ * chargeReqResExtension CHOICE {
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigChargeRequestRes_RES {
++ /*!
++ * \details
++ * rate(0) <charge rate provision>,
++ * rateInterim(1) <charge rate and interim charge provision>,
++ * rateFinal(2) <charge rate and final charge provision>,
++ * interim(3) <interim charge provision>,
++ * final(4) <final charge provision>,
++ * interimFinal(5) <interim charge and final charge provision>,
++ * rateInterimFinal(6) <charge rate, interim charge and final charge provision>
++ */
++ u_int8_t advice_mode_combination;
++};
++
++/*
++ * AocCompleteArg ::= SEQUENCE {
++ * chargedUser PartyNumber,
++ * chargingAssociation ChargingAssociation OPTIONAL,
++ * completeArgExtension CHOICE {
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigAocCompleteArg_ARG {
++ /*! \brief chargingAssociation (optional) */
++ struct roseQsigAOCChargingAssociation charging_association;
++
++ struct rosePartyNumber charged_user_number;
++
++ /*! \brief TRUE if charging_association is present */
++ u_int8_t charging_association_present;
++};
++
++/*
++ * AocCompleteRes ::= SEQUENCE {
++ * chargingOption ChargingOption,
++ * completeResExtension CHOICE {
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigAocCompleteRes_RES {
++ /*!
++ * \details
++ * aocFreeOfCharge(0),
++ * aocContinueCharging(1),
++ * aocStopCharging(2)
++ */
++ u_int8_t charging_option;
++};
++
++/*
++ * AocDivChargeReqArg ::= SEQUENCE {
++ * divertingUser PartyNumber,
++ * chargingAssociation ChargingAssociation OPTIONAL,
++ * diversionType DiversionType,
++ * aocDivChargeReqArgExt CHOICE {
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigAocDivChargeReqArg_ARG {
++ /*! \brief chargingAssociation (optional) */
++ struct roseQsigAOCChargingAssociation charging_association;
++
++ struct rosePartyNumber diverting_user_number;
++
++ /*! \brief TRUE if charging_association is present */
++ u_int8_t charging_association_present;
++
++ /*!
++ * \details
++ * callForwardingUnconditional(0),
++ * callForwardingBusy(1),
++ * callForwardingNoReply(2),
++ * callDeflection(3)
++ */
++ u_int8_t diversion_type;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * CTIdentifyRes ::= SEQUENCE {
++ * callIdentity CallIdentity,
++ * reroutingNumber PartyNumber,
++ * resultExtension CHOICE {
++ * [6] IMPLICIT Extension,
++ * [7] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigCTIdentifyRes_RES {
++ struct rosePartyNumber rerouting_number;
++
++ /*! \brief CallIdentity ::= NumericString (SIZE (1..4)) */
++ unsigned char call_id[4 + 1];
++};
++
++/*
++ * CTInitiateArg ::= SEQUENCE {
++ * callIdentity CallIdentity,
++ * reroutingNumber PartyNumber,
++ * argumentExtension CHOICE {
++ * [6] IMPLICIT Extension,
++ * [7] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigCTInitiateArg_ARG {
++ struct rosePartyNumber rerouting_number;
++
++ /*! \brief CallIdentity ::= NumericString (SIZE (1..4)) */
++ unsigned char call_id[4 + 1];
++};
++
++/*
++ * CTSetupArg ::= SEQUENCE {
++ * callIdentity CallIdentity,
++ * argumentExtension CHOICE {
++ * [0] IMPLICIT Extension,
++ * [1] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigCTSetupArg_ARG {
++ /*! \brief CallIdentity ::= NumericString (SIZE (1..4)) */
++ unsigned char call_id[4 + 1];
++};
++
++/*
++ * CTActiveArg ::= SEQUENCE {
++ * connectedAddress PresentedAddressScreened,
++ *
++ * -- ISO/IEC 11572 information elements Party
++ * -- category and Progress indicator are conveyed
++ * basicCallInfoElements PSS1InformationElement OPTIONAL,
++ * connectedName Name OPTIONAL,
++ * argumentExtension CHOICE {
++ * [9] IMPLICIT Extension,
++ * [10] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigCTActiveArg_ARG {
++ /*! \brief connectedAddress */
++ struct rosePresentedAddressScreened connected;
++
++ /*! \brief basicCallInfoElements (optional) */
++ struct roseQ931ie q931ie;
++ /*! \brief q931ie.contents "allocated" after the stucture. */
++ unsigned char q931ie_contents[ROSE_Q931_MAX_PROGRESS + 1];
++
++ /*! \brief connectedName (optional) */
++ struct roseQsigName connected_name;
++
++ /*! \brief TRUE if connected_name is present */
++ u_int8_t connected_name_present;
++};
++
++/*
++ * CTCompleteArg ::= SEQUENCE {
++ * endDesignation EndDesignation,
++ * redirectionNumber PresentedNumberScreened,
++ *
++ * -- ISO/IEC 11572 information elements Party
++ * -- category and Progress indicator are conveyed
++ * basicCallInfoElements PSS1InformationElement OPTIONAL,
++ * redirectionName Name OPTIONAL,
++ * callStatus CallStatus DEFAULT answered,
++ * argumentExtension CHOICE {
++ * [9] IMPLICIT Extension,
++ * [10] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigCTCompleteArg_ARG {
++ /*! \brief redirectionNumber */
++ struct rosePresentedNumberScreened redirection;
++
++ /*! \brief basicCallInfoElements (optional) */
++ struct roseQ931ie q931ie;
++ /*! \brief q931ie.contents "allocated" after the stucture. */
++ unsigned char q931ie_contents[ROSE_Q931_MAX_PROGRESS + 1];
++
++ /*! \brief redirectionName (optional) */
++ struct roseQsigName redirection_name;
++
++ /*! \brief TRUE if redirection_name is present */
++ u_int8_t redirection_name_present;
++
++ /*!
++ * \brief endDesignation
++ * \details
++ * primaryEnd(0),
++ * secondaryEnd(1)
++ */
++ u_int8_t end_designation;
++
++ /*!
++ * \brief callStatus
++ * \details
++ * DEFAULT answered
++ *
++ * \details
++ * answered(0),
++ * alerting(1)
++ */
++ u_int8_t call_status;
++};
++
++/*
++ * CTUpdateArg ::= SEQUENCE {
++ * redirectionNumber PresentedNumberScreened,
++ * redirectionName Name OPTIONAL,
++ *
++ * -- ISO/IEC 11572 information elements Party
++ * -- category and Progress indicator are conveyed
++ * basicCallInfoElements PSS1InformationElement OPTIONAL,
++ * argumentExtension CHOICE {
++ * [9] IMPLICIT Extension,
++ * [10] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigCTUpdateArg_ARG {
++ /*! \brief redirectionNumber */
++ struct rosePresentedNumberScreened redirection;
++
++ /*! \brief basicCallInfoElements (optional) */
++ struct roseQ931ie q931ie;
++ /*! \brief q931ie.contents "allocated" after the stucture. */
++ unsigned char q931ie_contents[ROSE_Q931_MAX_PROGRESS + 1];
++
++ /*! \brief redirectionName (optional) */
++ struct roseQsigName redirection_name;
++
++ /*! \brief TRUE if redirection_name is present */
++ u_int8_t redirection_name_present;
++};
++
++/*
++ * SubaddressTransferArg ::= SEQUENCE {
++ * redirectionSubaddress PartySubaddress,
++ * argumentExtension CHOICE {
++ * [0] IMPLICIT Extension,
++ * [1] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigSubaddressTransferArg_ARG {
++ struct rosePartySubaddress redirection_subaddress;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * IntResult ::= SEQUENCE {
++ * servedUserNr PartyNumber,
++ * basicService BasicService,
++ * procedure Procedure,
++ * divertedToAddress Address,
++ * remoteEnabled BOOLEAN DEFAULT FALSE,
++ * extension CHOICE {
++ * [1] IMPLICIT Extension,
++ * [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigForwardingRecord {
++ /*! \brief Diverted to address */
++ struct roseAddress diverted_to;
++
++ struct rosePartyNumber served_user_number;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36)
++ */
++ u_int8_t basic_service;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*! \brief remoteEnabled BOOLEAN DEFAULT FALSE */
++ u_int8_t remote_enabled;
++};
++
++/*
++ * roseQsigInterrogateDiversionQ_REQ
++ * IntResultList ::= SET SIZE (0..29) OF IntResult
++ */
++struct roseQsigForwardingList {
++ /*!
++ * \brief SET SIZE (0..29) OF Forwarding Records
++ * \note Reduced the size of the array to conserve
++ * potential stack usage.
++ */
++ struct roseQsigForwardingRecord list[10];
++
++ /*! \brief Number of Forwarding records present */
++ u_int8_t num_records;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * procedure Procedure,
++ * basicService BasicService,
++ * divertedToAddress Address,
++ * servedUserNr PartyNumber,
++ * activatingUserNr PartyNumber,
++ * extension CHOICE {
++ * [1] IMPLICIT Extension,
++ * [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigActivateDiversionQ_ARG {
++ /*! \brief divertedToAddress */
++ struct roseAddress diverted_to;
++
++ struct rosePartyNumber served_user_number;
++ struct rosePartyNumber activating_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36)
++ */
++ u_int8_t basic_service;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * procedure Procedure,
++ * basicService BasicService,
++ * servedUserNr PartyNumber,
++ * deactivatingUserNr PartyNumber,
++ * extension CHOICE {
++ * [1] IMPLICIT Extension,
++ * [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigDeactivateDiversionQ_ARG {
++ struct rosePartyNumber served_user_number;
++ struct rosePartyNumber deactivating_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36)
++ */
++ u_int8_t basic_service;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * procedure Procedure,
++ * basicService BasicService DEFAULT allServices,
++ * servedUserNr PartyNumber,
++ * interrogatingUserNr PartyNumber,
++ * extension CHOICE {
++ * [1] IMPLICIT Extension,
++ * [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigInterrogateDiversionQ_ARG {
++ struct rosePartyNumber served_user_number;
++ struct rosePartyNumber interrogating_user_number;
++
++ /*! \details cfu(0), cfb(1), cfnr(2) */
++ u_int8_t procedure;
++
++ /*!
++ * \details
++ * DEFAULT allServices
++ *
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36)
++ */
++ u_int8_t basic_service;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * servedUserNr PartyNumber,
++ * basicService BasicService,
++ * divertedToNr PartyNumber,
++ * extension CHOICE {
++ * [1] IMPLICIT Extension,
++ * [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigCheckRestriction_ARG {
++ struct rosePartyNumber served_user_number;
++ struct rosePartyNumber diverted_to_number;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotexSyntaxBased(35),
++ * videotelephony(36)
++ */
++ u_int8_t basic_service;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * reroutingReason DiversionReason,
++ * originalReroutingReason [0] IMPLICIT DiversionReason OPTIONAL,
++ * calledAddress Address,
++ * diversionCounter INTEGER (1..15),
++ *
++ * -- The basic call information elements Bearer capability,
++ * -- High layer compatibility, Low layer compatibity
++ * -- and Progress indicator can be embedded in the
++ * -- pSS1InfoElement in accordance with 6.5.3.1.5.
++ * pSS1InfoElement PSS1InformationElement,
++ * lastReroutingNr [1] EXPLICIT PresentedNumberUnscreened,
++ * subscriptionOption [2] IMPLICIT SubscriptionOption,
++ * callingPartySubaddress [3] EXPLICIT PartySubaddress OPTIONAL,
++ * callingNumber [4] EXPLICIT PresentedNumberScreened,
++ * callingName [5] EXPLICIT Name OPTIONAL,
++ * originalCalledNr [6] EXPLICIT PresentedNumberUnscreened OPTIONAL,
++ * redirectingName [7] EXPLICIT Name OPTIONAL,
++ * originalCalledName [8] EXPLICIT Name OPTIONAL,
++ * extension CHOICE {
++ * [9] IMPLICIT Extension,
++ * [10] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigCallRerouting_ARG {
++ /*! \brief calledAddress */
++ struct roseAddress called;
++
++ /*! \brief lastReroutingNr */
++ struct rosePresentedNumberUnscreened last_rerouting;
++
++ /*! \brief originalCalledNr (optional) */
++ struct rosePresentedNumberUnscreened original_called;
++
++ /*!
++ * \brief callingPartySubaddress (optional)
++ * The subaddress is present if the length is nonzero.
++ */
++ struct rosePartySubaddress calling_subaddress;
++
++ /*! \brief callingNumber */
++ struct rosePresentedNumberScreened calling;
++
++ /*! \brief callingName (optional) */
++ struct roseQsigName calling_name;
++
++ /*! \brief redirectingName (optional) */
++ struct roseQsigName redirecting_name;
++
++ /*! \brief originalCalledName (optional) */
++ struct roseQsigName original_called_name;
++
++ /*!
++ * \brief The BC, HLC (optional), LLC (optional),
++ * and progress indicator(s) information.
++ */
++ struct roseQ931ie q931ie;
++ /*! \brief q931ie.contents "allocated" after the stucture. */
++ unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
++ ROSE_Q931_MAX_LLC + ROSE_Q931_MAX_PROGRESS + 1];
++
++ /*! \brief TRUE if calling_name is present */
++ u_int8_t calling_name_present;
++
++ /*! \brief TRUE if redirecting_name is present */
++ u_int8_t redirecting_name_present;
++
++ /*! \brief TRUE if original_called_name is present */
++ u_int8_t original_called_name_present;
++
++ /*! \brief TRUE if original_called number is present */
++ u_int8_t original_called_present;
++
++ /*!
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3)
++ *
++ * \note The value unknown is only used if received from
++ * another network when interworking.
++ */
++ u_int8_t rerouting_reason;
++
++ /*!
++ * \brief originalReroutingReason (optional)
++ *
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3)
++ *
++ * \note The value unknown is only used if received from
++ * another network when interworking.
++ */
++ u_int8_t original_rerouting_reason;
++
++ /*! \brief TRUE if original_rerouting_reason is present */
++ u_int8_t original_rerouting_reason_present;
++
++ /*! \brief diversionCounter INTEGER (1..15) */
++ u_int8_t diversion_counter;
++
++ /*!
++ * \brief subscriptionOption
++ *
++ * \details
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ */
++ u_int8_t subscription_option;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * diversionReason DiversionReason,
++ * subscriptionOption SubscriptionOption,
++ * nominatedNr PartyNumber,
++ * extension CHOICE {
++ * [9] IMPLICIT Extension,
++ * [10] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigDivertingLegInformation1_ARG {
++ struct rosePartyNumber nominated_number;
++
++ /*!
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3)
++ *
++ * \note The value unknown is only used if received from
++ * another network when interworking.
++ */
++ u_int8_t diversion_reason;
++
++ /*!
++ * \brief subscriptionOption
++ *
++ * \details
++ * noNotification(0),
++ * notificationWithoutDivertedToNr(1),
++ * notificationWithDivertedToNr(2)
++ */
++ u_int8_t subscription_option;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * diversionCounter INTEGER (1..15),
++ * diversionReason DiversionReason,
++ * originalDiversionReason [0] IMPLICIT DiversionReason OPTIONAL,
++ *
++ * -- The divertingNr element is mandatory except in the case
++ * -- of interworking.
++ * divertingNr [1] EXPLICIT PresentedNumberUnscreened OPTIONAL,
++ * originalCalledNr [2] EXPLICIT PresentedNumberUnscreened OPTIONAL,
++ * redirectingName [3] EXPLICIT Name OPTIONAL,
++ * originalCalledName [4] EXPLICIT Name OPTIONAL,
++ * extension CHOICE {
++ * [5] IMPLICIT Extension,
++ * [6] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigDivertingLegInformation2_ARG {
++ /*! \brief divertingNr (optional) */
++ struct rosePresentedNumberUnscreened diverting;
++
++ /*! \brief originalCalledNr (optional) */
++ struct rosePresentedNumberUnscreened original_called;
++
++ /*! \brief redirectingName (optional) */
++ struct roseQsigName redirecting_name;
++
++ /*! \brief originalCalledName (optional) */
++ struct roseQsigName original_called_name;
++
++ /*! \brief diversionCounter INTEGER (1..15) */
++ u_int8_t diversion_counter;
++
++ /*!
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3)
++ *
++ * \note The value unknown is only used if received from
++ * another network when interworking.
++ */
++ u_int8_t diversion_reason;
++
++ /*!
++ * \brief originalDiversionReason (optional)
++ *
++ * \details
++ * unknown(0),
++ * cfu(1),
++ * cfb(2),
++ * cfnr(3)
++ *
++ * \note The value unknown is only used if received from
++ * another network when interworking.
++ */
++ u_int8_t original_diversion_reason;
++
++ /*! \brief TRUE if original_diversion_reason is present */
++ u_int8_t original_diversion_reason_present;
++
++ /*! \brief TRUE if diverting number is present */
++ u_int8_t diverting_present;
++
++ /*! \brief TRUE if original_called number is present */
++ u_int8_t original_called_present;
++
++ /*! \brief TRUE if redirecting_name is present */
++ u_int8_t redirecting_name_present;
++
++ /*! \brief TRUE if original_called_name is present */
++ u_int8_t original_called_name_present;
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * presentationAllowedIndicator PresentationAllowedIndicator, -- BOOLEAN
++ * redirectionName [0] EXPLICIT Name OPTIONAL,
++ * extension CHOICE {
++ * [1] IMPLICIT Extension,
++ * [2] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigDivertingLegInformation3_ARG {
++ /*! \brief redirectionName (optional) */
++ struct roseQsigName redirection_name;
++
++ /*! \brief TRUE if redirection_name is present */
++ u_int8_t redirection_name_present;
++
++ /*! \brief TRUE if presentation is allowed */
++ u_int8_t presentation_allowed_indicator;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * MsgCentreId ::= CHOICE {
++ * integer [0] IMPLICIT INTEGER (0..65535),
++ *
++ * -- The party number must be a complete number as required
++ * -- for routing purposes.
++ * partyNumber [1] EXPLICIT PartyNumber,
++ * numericString [2] IMPLICIT NumericString (SIZE (1..10))
++ * }
++ */
++struct roseQsigMsgCentreId {
++ union {
++ /*! \brief INTEGER (0..65535) */
++ u_int16_t integer;
++
++ /*!
++ * \note The party number must be a complete number as required
++ * for routing purposes.
++ */
++ struct rosePartyNumber number;
++
++ /*! \brief NumericString (SIZE (1..10)) */
++ unsigned char str[10 + 1];
++ } u;
++
++ /*!
++ * \details
++ * integer(0),
++ * partyNumber(1),
++ * numericString(2)
++ */
++ u_int8_t type;
++};
++
++/*
++ * MWIActivateArg ::= SEQUENCE {
++ * servedUserNr PartyNumber,
++ * basicService BasicService,
++ * msgCentreId MsgCentreId OPTIONAL,
++ * nbOfMessages [3] IMPLICIT NbOfMessages OPTIONAL,
++ * originatingNr [4] EXPLICIT PartyNumber OPTIONAL,
++ * timestamp TimeStamp OPTIONAL,
++ *
++ * -- The value 0 means the highest priority and 9 the lowest
++ * priority [5] IMPLICIT INTEGER (0..9) OPTIONAL,
++ * argumentExt CHOICE {
++ * extension [6] IMPLICIT Extension,
++ * multipleExtension [7] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigMWIActivateArg {
++ /*! \brief NbOfMessages ::= INTEGER (0..65535) (optional) */
++ u_int16_t number_of_messages;
++
++ /*! \brief msgCentreId (optional) */
++ struct roseQsigMsgCentreId msg_centre_id;
++
++ struct rosePartyNumber served_user_number;
++
++ /*! \brief originatingNr (optional) (Number present if length is nonzero) */
++ struct rosePartyNumber originating_number;
++
++ /*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
++ unsigned char timestamp[19 + 1];
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotextSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * reservedNotUsed1(38),
++ * reservedNotUsed2(39),
++ * reservedNotUsed3(40),
++ * reservedNotUsed4(41),
++ * reservedNotUsed5(42),
++ * email(51),
++ * video(52),
++ * fileTransfer(53),
++ * shortMessageService(54),
++ * speechAndVideo(55),
++ * speechAndFax(56),
++ * speechAndEmail(57),
++ * videoAndFax(58),
++ * videoAndEmail(59),
++ * faxAndEmail(60),
++ * speechVideoAndFax(61),
++ * speechVideoAndEmail(62),
++ * speechFaxAndEmail(63),
++ * videoFaxAndEmail(64),
++ * speechVideoFaxAndEmail(65),
++ * multimediaUnknown(66),
++ * serviceUnknown(67),
++ * futureReserve1(68),
++ * futureReserve2(69),
++ * futureReserve3(70),
++ * futureReserve4(71),
++ * futureReserve5(72),
++ * futureReserve6(73),
++ * futureReserve7(74),
++ * futureReserve8(75)
++ */
++ u_int8_t basic_service;
++
++ /*!
++ * \brief INTEGER (0..9) (optional)
++ * \note The value 0 means the highest priority and 9 the lowest.
++ */
++ u_int8_t priority;
++
++ /*! \brief TRUE if msg_centre_id is present */
++ u_int8_t msg_centre_id_present;
++
++ /*! \brief TRUE if number_of_messages is present */
++ u_int8_t number_of_messages_present;
++
++ /*! \brief TRUE if timestamp is present */
++ u_int8_t timestamp_present;
++
++ /*! \brief TRUE if priority is present */
++ u_int8_t priority_present;
++};
++
++/*
++ * MWIDeactivateArg ::= SEQUENCE {
++ * servedUserNr PartyNumber,
++ * basicService BasicService,
++ * msgCentreId MsgCentreId OPTIONAL,
++ * argumentExt CHOICE {
++ * extension [3] IMPLICIT Extension,
++ * multipleExtension [4] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigMWIDeactivateArg {
++ /*! \brief msgCentreId (optional) */
++ struct roseQsigMsgCentreId msg_centre_id;
++
++ struct rosePartyNumber served_user_number;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotextSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * reservedNotUsed1(38),
++ * reservedNotUsed2(39),
++ * reservedNotUsed3(40),
++ * reservedNotUsed4(41),
++ * reservedNotUsed5(42),
++ * email(51),
++ * video(52),
++ * fileTransfer(53),
++ * shortMessageService(54),
++ * speechAndVideo(55),
++ * speechAndFax(56),
++ * speechAndEmail(57),
++ * videoAndFax(58),
++ * videoAndEmail(59),
++ * faxAndEmail(60),
++ * speechVideoAndFax(61),
++ * speechVideoAndEmail(62),
++ * speechFaxAndEmail(63),
++ * videoFaxAndEmail(64),
++ * speechVideoFaxAndEmail(65),
++ * multimediaUnknown(66),
++ * serviceUnknown(67),
++ * futureReserve1(68),
++ * futureReserve2(69),
++ * futureReserve3(70),
++ * futureReserve4(71),
++ * futureReserve5(72),
++ * futureReserve6(73),
++ * futureReserve7(74),
++ * futureReserve8(75)
++ */
++ u_int8_t basic_service;
++
++ /*! \brief TRUE if msg_centre_id is present */
++ u_int8_t msg_centre_id_present;
++};
++
++/*
++ * MWIInterrogateArg ::= SEQUENCE {
++ * servedUserNr PartyNumber,
++ * basicService BasicService,
++ * msgCentreId MsgCentreId OPTIONAL,
++ * argumentExt CHOICE {
++ * extension [3] IMPLICIT Extension,
++ * multipleExtension [4] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigMWIInterrogateArg {
++ /*! \brief msgCentreId (optional) */
++ struct roseQsigMsgCentreId msg_centre_id;
++
++ struct rosePartyNumber served_user_number;
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotextSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * reservedNotUsed1(38),
++ * reservedNotUsed2(39),
++ * reservedNotUsed3(40),
++ * reservedNotUsed4(41),
++ * reservedNotUsed5(42),
++ * email(51),
++ * video(52),
++ * fileTransfer(53),
++ * shortMessageService(54),
++ * speechAndVideo(55),
++ * speechAndFax(56),
++ * speechAndEmail(57),
++ * videoAndFax(58),
++ * videoAndEmail(59),
++ * faxAndEmail(60),
++ * speechVideoAndFax(61),
++ * speechVideoAndEmail(62),
++ * speechFaxAndEmail(63),
++ * videoFaxAndEmail(64),
++ * speechVideoFaxAndEmail(65),
++ * multimediaUnknown(66),
++ * serviceUnknown(67),
++ * futureReserve1(68),
++ * futureReserve2(69),
++ * futureReserve3(70),
++ * futureReserve4(71),
++ * futureReserve5(72),
++ * futureReserve6(73),
++ * futureReserve7(74),
++ * futureReserve8(75)
++ */
++ u_int8_t basic_service;
++
++ /*! \brief TRUE if msg_centre_id is present */
++ u_int8_t msg_centre_id_present;
++};
++
++/*
++ * MWIInterrogateResElt ::= SEQUENCE {
++ * basicService BasicService,
++ * msgCentreId MsgCentreId OPTIONAL,
++ * nbOfMessages [3] IMPLICIT NbOfMessages OPTIONAL,
++ * originatingNr [4] EXPLICIT PartyNumber OPTIONAL,
++ * timestamp TimeStamp OPTIONAL,
++ *
++ * -- The value 0 means the highest priority and 9 the lowest
++ * priority [5] IMPLICIT INTEGER (0..9) OPTIONAL,
++ * argumentExt CHOICE {
++ * extension [6] IMPLICIT Extension,
++ * multipleExtension [7] IMPLICIT SEQUENCE OF Extension
++ * } OPTIONAL
++ * }
++ */
++struct roseQsigMWIInterrogateResElt {
++ /*! \brief NbOfMessages ::= INTEGER (0..65535) (optional) */
++ u_int16_t number_of_messages;
++
++ /*! \brief msgCentreId (optional) */
++ struct roseQsigMsgCentreId msg_centre_id;
++
++ /*! \brief originatingNr (optional) (Number present if length is nonzero) */
++ struct rosePartyNumber originating_number;
++
++ /*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
++ unsigned char timestamp[19 + 1];
++
++ /*!
++ * \details
++ * allServices(0),
++ * speech(1),
++ * unrestrictedDigitalInformation(2),
++ * audio3100Hz(3),
++ * telephony(32),
++ * teletex(33),
++ * telefaxGroup4Class1(34),
++ * videotextSyntaxBased(35),
++ * videotelephony(36),
++ * telefaxGroup2-3(37),
++ * reservedNotUsed1(38),
++ * reservedNotUsed2(39),
++ * reservedNotUsed3(40),
++ * reservedNotUsed4(41),
++ * reservedNotUsed5(42),
++ * email(51),
++ * video(52),
++ * fileTransfer(53),
++ * shortMessageService(54),
++ * speechAndVideo(55),
++ * speechAndFax(56),
++ * speechAndEmail(57),
++ * videoAndFax(58),
++ * videoAndEmail(59),
++ * faxAndEmail(60),
++ * speechVideoAndFax(61),
++ * speechVideoAndEmail(62),
++ * speechFaxAndEmail(63),
++ * videoFaxAndEmail(64),
++ * speechVideoFaxAndEmail(65),
++ * multimediaUnknown(66),
++ * serviceUnknown(67),
++ * futureReserve1(68),
++ * futureReserve2(69),
++ * futureReserve3(70),
++ * futureReserve4(71),
++ * futureReserve5(72),
++ * futureReserve6(73),
++ * futureReserve7(74),
++ * futureReserve8(75)
++ */
++ u_int8_t basic_service;
++
++ /*!
++ * \brief INTEGER (0..9) (optional)
++ * \note The value 0 means the highest priority and 9 the lowest.
++ */
++ u_int8_t priority;
++
++ /*! \brief TRUE if msg_centre_id is present */
++ u_int8_t msg_centre_id_present;
++
++ /*! \brief TRUE if number_of_messages is present */
++ u_int8_t number_of_messages_present;
++
++ /*! \brief TRUE if timestamp is present */
++ u_int8_t timestamp_present;
++
++ /*! \brief TRUE if priority is present */
++ u_int8_t priority_present;
++};
++
++/*
++ * MWIInterrogateRes ::= SEQUENCE SIZE(1..10) OF MWIInterrogateResElt
++ */
++struct roseQsigMWIInterrogateRes {
++ /*! \brief SEQUENCE SIZE(1..10) OF MWIInterrogateResElt */
++ struct roseQsigMWIInterrogateResElt list[10];
++
++ /*! \brief Number of MWIInterrogateResElt records present */
++ u_int8_t num_records;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*
++ * Northern Telecom DMS-100 transfer ability result
++ *
++ * callId [0] IMPLICIT INTEGER (0..16777215) -- 24 bit number
++ */
++struct roseDms100RLTOperationInd_RES {
++ /*! INTEGER (0..16777215) -- 24 bit number */
++ u_int32_t call_id;
++};
++
++/*
++ * Northern Telecom DMS-100 transfer invoke
++ *
++ * ARGUMENT SEQUENCE {
++ * callId [0] IMPLICIT INTEGER (0..16777215), -- 24 bit number
++ * reason [1] IMPLICIT INTEGER
++ * }
++ */
++struct roseDms100RLTThirdParty_ARG {
++ /*! INTEGER (0..16777215) -- 24 bit number */
++ u_int32_t call_id;
++
++ /*! Reason for redirect */
++ u_int8_t reason;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/* ARGUMENT ENUMERATED */
++struct roseNi2InformationFollowing_ARG {
++ u_int8_t value; /*!< Unknown enumerated value */
++};
++
++/*
++ * ARGUMENT SEQUENCE {
++ * callReference INTEGER -- 16 bit number
++ * }
++ */
++struct roseNi2InitiateTransfer_ARG {
++ u_int16_t call_reference;
++};
++
++
++/* ------------------------------------------------------------------- */
++
++
++/*! \brief Facility ie invoke etsi messages with arguments. */
++union rose_msg_invoke_etsi_args {
++ /* ETSI Advice Of Charge (AOC) */
++ struct roseEtsiChargingRequest_ARG ChargingRequest;
++ struct roseEtsiAOCSCurrency_ARG AOCSCurrency;
++ struct roseEtsiAOCSSpecialArr_ARG AOCSSpecialArr;
++ struct roseEtsiAOCDCurrency_ARG AOCDCurrency;
++ struct roseEtsiAOCDChargingUnit_ARG AOCDChargingUnit;
++ struct roseEtsiAOCECurrency_ARG AOCECurrency;
++ struct roseEtsiAOCEChargingUnit_ARG AOCEChargingUnit;
++
++ /* ETSI Call Diversion */
++ struct roseEtsiActivationDiversion_ARG ActivationDiversion;
++ struct roseEtsiDeactivationDiversion_ARG DeactivationDiversion;
++ struct roseEtsiActivationStatusNotificationDiv_ARG ActivationStatusNotificationDiv;
++ struct roseEtsiDeactivationStatusNotificationDiv_ARG
++ DeactivationStatusNotificationDiv;
++ struct roseEtsiInterrogationDiversion_ARG InterrogationDiversion;
++ struct roseEtsiDiversionInformation_ARG DiversionInformation;
++ struct roseEtsiCallDeflection_ARG CallDeflection;
++ struct roseEtsiCallRerouting_ARG CallRerouting;
++ struct roseEtsiDivertingLegInformation1_ARG DivertingLegInformation1;
++ struct roseEtsiDivertingLegInformation2_ARG DivertingLegInformation2;
++ struct roseEtsiDivertingLegInformation3_ARG DivertingLegInformation3;
++
++ /* ETSI Explicit Call Transfer (ECT) */
++ struct roseEtsiExplicitEctExecute_ARG ExplicitEctExecute;
++ struct roseEtsiSubaddressTransfer_ARG SubaddressTransfer;
++ struct roseEtsiEctInform_ARG EctInform;
++ struct roseEtsiEctLoopTest_ARG EctLoopTest;
++};
++
++/*! \brief Facility ie result etsi messages with arguments. */
++union rose_msg_result_etsi_args {
++ /* ETSI Advice Of Charge (AOC) */
++ struct roseEtsiChargingRequest_RES ChargingRequest;
++
++ /* ETSI Call Diversion */
++ struct roseEtsiForwardingList InterrogationDiversion;
++ struct roseEtsiServedUserNumberList InterrogateServedUserNumbers;
++
++ /* ETSI Explicit Call Transfer (ECT) */
++ struct roseEtsiEctLinkIdRequest_RES EctLinkIdRequest;
++ struct roseEtsiEctLoopTest_RES EctLoopTest;
++};
++
++/*! \brief Facility ie invoke qsig messages with arguments. */
++union rose_msg_invoke_qsig_args {
++ /* Q.SIG Name-Operations */
++ struct roseQsigPartyName_ARG CallingName;
++ struct roseQsigPartyName_ARG CalledName;
++ struct roseQsigPartyName_ARG ConnectedName;
++ struct roseQsigPartyName_ARG BusyName;
++
++ /* Q.SIG SS-AOC-Operations */
++ struct roseQsigChargeRequestArg_ARG ChargeRequest;
++ struct roseQsigAocFinalArg_ARG AocFinal;
++ struct roseQsigAocInterimArg_ARG AocInterim;
++ struct roseQsigAocRateArg_ARG AocRate;
++ struct roseQsigAocCompleteArg_ARG AocComplete;
++ struct roseQsigAocDivChargeReqArg_ARG AocDivChargeReq;
++
++ /* Q.SIG Call-Transfer-Operations */
++ struct roseQsigCTInitiateArg_ARG CallTransferInitiate;
++ struct roseQsigCTSetupArg_ARG CallTransferSetup;
++ struct roseQsigCTActiveArg_ARG CallTransferActive;
++ struct roseQsigCTCompleteArg_ARG CallTransferComplete;
++ struct roseQsigCTUpdateArg_ARG CallTransferUpdate;
++ struct roseQsigSubaddressTransferArg_ARG SubaddressTransfer;
++
++ /* Q.SIG Call-Diversion-Operations */
++ struct roseQsigActivateDiversionQ_ARG ActivateDiversionQ;
++ struct roseQsigDeactivateDiversionQ_ARG DeactivateDiversionQ;
++ struct roseQsigInterrogateDiversionQ_ARG InterrogateDiversionQ;
++ struct roseQsigCheckRestriction_ARG CheckRestriction;
++ struct roseQsigCallRerouting_ARG CallRerouting;
++ struct roseQsigDivertingLegInformation1_ARG DivertingLegInformation1;
++ struct roseQsigDivertingLegInformation2_ARG DivertingLegInformation2;
++ struct roseQsigDivertingLegInformation3_ARG DivertingLegInformation3;
++
++ /* Q.SIG SS-MWI-Operations */
++ struct roseQsigMWIActivateArg MWIActivate;
++ struct roseQsigMWIDeactivateArg MWIDeactivate;
++ struct roseQsigMWIInterrogateArg MWIInterrogate;
++};
++
++/*! \brief Facility ie result qsig messages with arguments. */
++union rose_msg_result_qsig_args {
++ /* Q.SIG SS-AOC-Operations */
++ struct roseQsigChargeRequestRes_RES ChargeRequest;
++ struct roseQsigAocCompleteRes_RES AocComplete;
++
++ /* Q.SIG Call-Transfer-Operations */
++ struct roseQsigCTIdentifyRes_RES CallTransferIdentify;
++
++ /* Q.SIG Call-Diversion-Operations */
++ struct roseQsigForwardingList InterrogateDiversionQ;
++
++ /* Q.SIG SS-MWI-Operations */
++ struct roseQsigMWIInterrogateRes MWIInterrogate;
++};
++
++/*! \brief Facility ie invoke DMS-100 messages with arguments. */
++union rose_msg_invoke_dms100_args {
++ struct roseDms100RLTThirdParty_ARG RLT_ThirdParty;
++};
++
++/*! \brief Facility ie result DMS-100 messages with arguments. */
++union rose_msg_result_dms100_args {
++ struct roseDms100RLTOperationInd_RES RLT_OperationInd;
++};
++
++/*! \brief Facility ie invoke NI2 messages with arguments. */
++union rose_msg_invoke_ni2_args {
++ struct roseNi2InformationFollowing_ARG InformationFollowing;
++ struct roseNi2InitiateTransfer_ARG InitiateTransfer;
++};
++
++/*! \brief Facility ie result NI2 messages with arguments. */
++union rose_msg_result_ni2_args {
++ int dummy; /*!< place holder until there are results with parameters */
++};
++
++/*! \brief Facility ie invoke messages with arguments. */
++union rose_msg_invoke_args {
++ union rose_msg_invoke_etsi_args etsi;
++ union rose_msg_invoke_qsig_args qsig;
++ union rose_msg_invoke_dms100_args dms100;
++ union rose_msg_invoke_ni2_args ni2;
++};
++
++/*! \brief Facility ie result messages with arguments. */
++union rose_msg_result_args {
++ union rose_msg_result_etsi_args etsi;
++ union rose_msg_result_qsig_args qsig;
++ union rose_msg_result_dms100_args dms100;
++ union rose_msg_result_ni2_args ni2;
++};
++
++/*! \brief Facility ie error messages with parameters. */
++union rose_msg_error_args {
++ int dummy; /*!< place holder until there are errors with parameters */
++};
++
++struct rose_msg_invoke {
++ /*! \brief Invoke ID (-32768..32767) */
++ int16_t invoke_id;
++ /*! \brief Linked ID (-32768..32767) (optional) */
++ int16_t linked_id;
++ /*! \brief library encoded operation-value */
++ enum rose_operation operation;
++ /*! \brief TRUE if the Linked ID is present */
++ u_int8_t linked_id_present;
++ union rose_msg_invoke_args args;
++};
++
++struct rose_msg_result {
++ /*! \brief Invoke ID (-32768..32767) */
++ int16_t invoke_id;
++ /*!
++ * \brief library encoded operation-value
++ * \note Set to ROSE_None if the operation sequence is not present.
++ * \note ETSI and Q.SIG imply that if a return result does not have
++ * any arguments then you must rely upon the invokeId value to
++ * distinguish between return results because the operation-value is
++ * not present.
++ */
++ enum rose_operation operation;
++ union rose_msg_result_args args;
++};
++
++struct rose_msg_error {
++ /*! \brief Invoke ID (-32768..32767) */
++ int16_t invoke_id;
++ /*! \brief library encoded error-value */
++ enum rose_error_code code;
++ union rose_msg_error_args args;
++};
++
++struct rose_msg_reject {
++ /*! \brief Invoke ID (-32768..32767) (optional) */
++ int16_t invoke_id;
++ /*! \brief TRUE if the Invoke ID is present */
++ u_int8_t invoke_id_present;
++ /*! \brief library encoded problem-value */
++ enum rose_reject_code code;
++};
++
++enum rose_component_type {
++ ROSE_COMP_TYPE_INVALID,
++ ROSE_COMP_TYPE_INVOKE,
++ ROSE_COMP_TYPE_RESULT,
++ ROSE_COMP_TYPE_ERROR,
++ ROSE_COMP_TYPE_REJECT
++};
++
++struct rose_message {
++ /*! \brief invoke, result, error, reject */
++ enum rose_component_type type;
++ union {
++ struct rose_msg_invoke invoke;
++ struct rose_msg_result result;
++ struct rose_msg_error error;
++ struct rose_msg_reject reject;
++ } component;
++};
++
++/*
++ * NetworkFacilityExtension ::= [10] IMPLICIT SEQUENCE {
++ * sourceEntity [0] IMPLICIT EntityType,
++ * sourceEntityAddress [1] EXPLICIT AddressInformation OPTIONAL,
++ * destinationEntity [2] IMPLICIT EntityType,
++ * destinationEntityAddress [3] EXPLICIT AddressInformation OPTIONAL
++ * }
++ *
++ * AddressInformation ::= PartyNumber
++ */
++struct facNetworkFacilityExtension {
++ /*! \brief sourceEntityAddress (optional) (Number present if length is nonzero) */
++ struct rosePartyNumber source_number;
++ /*! \brief destinationEntityAddress (optional) (Number present if length is nonzero) */
++ struct rosePartyNumber destination_number;
++
++ /*!
++ * \details
++ * endPINX(0),
++ * anyTypeOfPINX(1)
++ */
++ u_int8_t source_entity;
++
++ /*!
++ * \details
++ * endPINX(0),
++ * anyTypeOfPINX(1)
++ */
++ u_int8_t destination_entity;
++};
++
++/*
++ * The network extensions header is a sequence of the following components:
++ *
++ * nfe NetworkFacilityExtension OPTIONAL,
++ * npp NetworkProtocolProfile OPTIONAL,
++ * interpretation InterpretationApdu OPTIONAL
++ *
++ * NetworkProtocolProfile ::= [18] IMPLICIT INTEGER (0..254)
++ *
++ * InterpretationApdu ::= [11] IMPLICIT ENUMERATED {
++ * discardAnyUnrecognisedInvokePdu(0),
++ *
++ * -- this value also applies to Call independent signalling connections
++ * -- see clause 8.1.2 (ECMA-165)
++ * clearCallIfAnyInvokePduNotRecognised(1),
++ *
++ * -- this coding is implied by the absence of an
++ * -- interpretation APDU.
++ * rejectAnyUnrecognisedInvokePdu(2)
++ * }
++ */
++struct fac_extension_header {
++ /*! \brief Network Facility Extension component */
++ struct facNetworkFacilityExtension nfe;
++
++ /*! \brief Network Protocol Profile component */
++ u_int8_t npp;
++
++ /*!
++ * \brief interpretation component
++ *
++ * \details
++ * discardAnyUnrecognisedInvokePdu(0),
++ * clearCallIfAnyInvokePduNotRecognised(1),
++ * rejectAnyUnrecognisedInvokePdu(2)
++ */
++ u_int8_t interpretation;
++
++ /*! \brief TRUE if nfe is present */
++ u_int8_t nfe_present;
++
++ /*! \brief TRUE if npp is present */
++ u_int8_t npp_present;
++
++ /*! \brief TRUE if interpretation is present */
++ u_int8_t interpretation_present;
++};
++
++const char *rose_operation2str(enum rose_operation operation);
++const char *rose_error2str(enum rose_error_code code);
++const char *rose_reject2str(enum rose_reject_code code);
++
++unsigned char *rose_encode_invoke(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rose_msg_invoke *msg);
++unsigned char *rose_encode_result(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rose_msg_result *msg);
++unsigned char *rose_encode_error(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rose_msg_error *msg);
++unsigned char *rose_encode_reject(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rose_msg_reject *msg);
++
++unsigned char *rose_encode(struct pri *ctrl, unsigned char *pos, unsigned char *end,
++ const struct rose_message *msg);
++const unsigned char *rose_decode(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end, struct rose_message *msg);
++
++unsigned char *fac_enc_extension_header(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct fac_extension_header *header);
++unsigned char *facility_encode_header(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct fac_extension_header *header);
++
++const unsigned char *fac_dec_extension_header(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end, struct fac_extension_header *header);
++const unsigned char *facility_decode_header(struct pri *ctrl, const unsigned char *pos,
++ const unsigned char *end, struct fac_extension_header *header);
++
++void facility_decode_dump(struct pri *ctrl, const unsigned char *buf, size_t length);
++
++/* ------------------------------------------------------------------- */
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _LIBPRI_ROSE_H */
++/* ------------------------------------------------------------------- */
++/* end rose.h */
+
+Property changes on: rose.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_address.c
+===================================================================
+--- a/rose_address.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_address.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,983 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ROSE Addressing-Data-Elements
++ *
++ * Addressing-Data-Elements ETS 300 196-1 D.3
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Encode the public or private network PartyNumber type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param number
++ * \param length_of_number
++ * \param type_of_number
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_NetworkPartyNumber(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const unsigned char *number,
++ size_t length_of_number, u_int8_t type_of_number)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, type_of_number));
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_NUMERIC_STRING, number,
++ length_of_number));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the PartyNumber type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param party_number
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_PartyNumber(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePartyNumber *party_number)
++{
++ switch (party_number->plan) {
++ case 0: /* Unknown PartyNumber */
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ party_number->str, party_number->length));
++ break;
++ case 1: /* Public PartyNumber */
++ ASN1_CALL(pos, rose_enc_NetworkPartyNumber(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, party_number->str, party_number->length,
++ party_number->ton));
++ break;
++ case 2: /* NSAP encoded PartyNumber */
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ party_number->str, party_number->length));
++ break;
++ case 3: /* Data PartyNumber (Not used) */
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ party_number->str, party_number->length));
++ break;
++ case 4: /* Telex PartyNumber (Not used) */
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4,
++ party_number->str, party_number->length));
++ break;
++ case 5: /* Private PartyNumber */
++ ASN1_CALL(pos, rose_enc_NetworkPartyNumber(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 5, party_number->str, party_number->length,
++ party_number->ton));
++ break;
++ case 8: /* National Standard PartyNumber (Not used) */
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 8,
++ party_number->str, party_number->length));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown numbering plan");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the PartySubaddress type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param party_subaddress
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_PartySubaddress(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePartySubaddress *party_subaddress)
++{
++ unsigned char *seq_len;
++
++ switch (party_subaddress->type) {
++ case 0: /* UserSpecified */
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING,
++ party_subaddress->u.user_specified.information, party_subaddress->length));
++ if (party_subaddress->u.user_specified.odd_count_present) {
++ ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
++ party_subaddress->u.user_specified.odd_count));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++ break;
++ case 1: /* NSAP */
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING,
++ party_subaddress->u.nsap, party_subaddress->length));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown subaddress type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Address type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param address
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_Address(struct pri *ctrl, unsigned char *pos, unsigned char *end,
++ unsigned tag, const struct roseAddress *address)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &address->number));
++ if (address->subaddress.length) {
++ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end, &address->subaddress));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the PresentedNumberUnscreened type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param party
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_PresentedNumberUnscreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePresentedNumberUnscreened *party)
++{
++ unsigned char *seq_len;
++
++ switch (party->presentation) {
++ case 0: /* presentationAllowedNumber */
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &party->number));
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++ break;
++ case 1: /* presentationRestricted */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ break;
++ case 2: /* numberNotAvailableDueToInterworking */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
++ break;
++ case 3: /* presentationRestrictedNumber */
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &party->number));
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the NumberScreened type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param screened
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_NumberScreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseNumberScreened *screened)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &screened->number));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ screened->screening_indicator));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the PresentedNumberScreened type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param party
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_PresentedNumberScreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePresentedNumberScreened *party)
++{
++ switch (party->presentation) {
++ case 0: /* presentationAllowedNumber */
++ ASN1_CALL(pos, rose_enc_NumberScreened(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 0, &party->screened));
++ break;
++ case 1: /* presentationRestricted */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ break;
++ case 2: /* numberNotAvailableDueToInterworking */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
++ break;
++ case 3: /* presentationRestrictedNumber */
++ ASN1_CALL(pos, rose_enc_NumberScreened(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 3, &party->screened));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the AddressScreened type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param screened
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_AddressScreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseAddressScreened *screened)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &screened->number));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ screened->screening_indicator));
++ if (screened->subaddress.length) {
++ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end, &screened->subaddress));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the PresentedAddressScreened type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param party
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_PresentedAddressScreened(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct rosePresentedAddressScreened *party)
++{
++ switch (party->presentation) {
++ case 0: /* presentationAllowedAddress */
++ ASN1_CALL(pos, rose_enc_AddressScreened(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 0, &party->screened));
++ break;
++ case 1: /* presentationRestricted */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ break;
++ case 2: /* numberNotAvailableDueToInterworking */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2));
++ break;
++ case 3: /* presentationRestrictedAddress */
++ ASN1_CALL(pos, rose_enc_AddressScreened(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 3, &party->screened));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown presentation type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the NumberDigits PartyNumber argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party_number Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_NumberDigits(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartyNumber *party_number)
++{
++ size_t str_len;
++
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, name, tag, pos, end,
++ sizeof(party_number->str), party_number->str, &str_len));
++ party_number->length = str_len;
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the NSAP PartyNumber argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party_number Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_NSAPPartyNumber(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartyNumber *party_number)
++{
++ size_t str_len;
++
++ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
++ sizeof(party_number->str), party_number->str, &str_len));
++ party_number->length = str_len;
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the public or private network PartyNumber argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party_number Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_NetworkPartyNumber(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartyNumber *party_number)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfNumber", tag, pos, seq_end, &value));
++ party_number->ton = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_NUMERIC_STRING);
++ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "numberDigits", tag, pos, seq_end,
++ party_number));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the PartyNumber argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party_number Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_PartyNumber(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartyNumber *party_number)
++{
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s PartyNumber\n", name);
++ }
++ party_number->ton = 0; /* unknown */
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ party_number->plan = 0; /* Unknown PartyNumber */
++ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "unknownPartyNumber", tag, pos, end,
++ party_number));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ /* Must be constructed but we will not check for it for simplicity. */
++ party_number->plan = 1; /* Public PartyNumber */
++ ASN1_CALL(pos, rose_dec_NetworkPartyNumber(ctrl, "publicPartyNumber", tag, pos,
++ end, party_number));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ party_number->plan = 2; /* NSAP encoded PartyNumber */
++ ASN1_CALL(pos, rose_dec_NSAPPartyNumber(ctrl, "nsapEncodedPartyNumber", tag, pos,
++ end, party_number));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ party_number->plan = 3; /* Data PartyNumber (Not used) */
++ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "dataPartyNumber", tag, pos, end,
++ party_number));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ party_number->plan = 4; /* Telex PartyNumber (Not used) */
++ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "telexPartyNumber", tag, pos, end,
++ party_number));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
++ /* Must be constructed but we will not check for it for simplicity. */
++ party_number->plan = 5; /* Private PartyNumber */
++ ASN1_CALL(pos, rose_dec_NetworkPartyNumber(ctrl, "privatePartyNumber", tag, pos,
++ end, party_number));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 8:
++ party_number->plan = 8; /* National Standard PartyNumber (Not used) */
++ ASN1_CALL(pos, rose_dec_NumberDigits(ctrl, "nationalStandardPartyNumber", tag,
++ pos, end, party_number));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the User PartySubaddress argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party_subaddress Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_UserSubaddress(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartySubaddress *party_subaddress)
++{
++ size_t str_len;
++ int32_t odd_count;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ party_subaddress->type = 0; /* UserSpecified */
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s UserSpecified %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ /* SubaddressInformation */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_OCTET_STRING);
++ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, "subaddressInformation", tag, pos, seq_end,
++ sizeof(party_subaddress->u.user_specified.information),
++ party_subaddress->u.user_specified.information, &str_len));
++ party_subaddress->length = str_len;
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ /*
++ * The optional odd count indicator must be present since there
++ * is something left.
++ */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
++ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "oddCount", tag, pos, seq_end,
++ &odd_count));
++ party_subaddress->u.user_specified.odd_count = odd_count;
++ party_subaddress->u.user_specified.odd_count_present = 1;
++ } else {
++ party_subaddress->u.user_specified.odd_count = 0;
++ party_subaddress->u.user_specified.odd_count_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the NSAP PartySubaddress argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party_subaddress Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_NSAPSubaddress(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartySubaddress *party_subaddress)
++{
++ size_t str_len;
++
++ party_subaddress->type = 1; /* NSAP */
++
++ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end,
++ sizeof(party_subaddress->u.nsap), party_subaddress->u.nsap, &str_len));
++ party_subaddress->length = str_len;
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the PartySubaddress argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party_subaddress Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_PartySubaddress(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartySubaddress *party_subaddress)
++{
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s PartySubaddress\n", name);
++ }
++ switch (tag) {
++ case ASN1_TAG_SEQUENCE:
++ ASN1_CALL(pos, rose_dec_UserSubaddress(ctrl, "user", tag, pos, end,
++ party_subaddress));
++ break;
++ case ASN1_TYPE_OCTET_STRING:
++ case ASN1_TYPE_OCTET_STRING | ASN1_PC_CONSTRUCTED:
++ ASN1_CALL(pos, rose_dec_NSAPSubaddress(ctrl, "nsap", tag, pos, end,
++ party_subaddress));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Address argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param address Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_Address(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct roseAddress *address)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s Address %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
++ &address->number));
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ /* The optional subaddress must be present since there is something left. */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "partySubaddress", tag, pos,
++ seq_end, &address->subaddress));
++ } else {
++ address->subaddress.length = 0; /* Subaddress not present */
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the PresentedNumberUnscreened argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_PresentedNumberUnscreened(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePresentedNumberUnscreened *party)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s PresentedNumberUnscreened\n", name);
++ }
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ party->presentation = 0; /* presentationAllowedNumber */
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "presentationAllowedNumber", tag, pos,
++ seq_end, &party->number));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ party->presentation = 1; /* presentationRestricted */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ party->presentation = 2; /* numberNotAvailableDueToInterworking */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
++ pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ party->presentation = 3; /* presentationRestrictedNumber */
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "presentationRestrictedNumber", tag,
++ pos, seq_end, &party->number));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the NumberScreened argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param screened Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_NumberScreened(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseNumberScreened *screened)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s NumberScreened %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
++ &screened->number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "screeningIndicator", tag, pos, seq_end, &value));
++ screened->screening_indicator = value;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the PresentedNumberScreened argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_PresentedNumberScreened(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePresentedNumberScreened *party)
++{
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s PresentedNumberScreened\n", name);
++ }
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ party->presentation = 0; /* presentationAllowedNumber */
++ ASN1_CALL(pos, rose_dec_NumberScreened(ctrl, "presentationAllowedNumber", tag,
++ pos, end, &party->screened));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ party->presentation = 1; /* presentationRestricted */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ party->presentation = 2; /* numberNotAvailableDueToInterworking */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
++ pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
++ party->presentation = 3; /* presentationRestrictedNumber */
++ ASN1_CALL(pos, rose_dec_NumberScreened(ctrl, "presentationRestrictedNumber", tag,
++ pos, end, &party->screened));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the AddressScreened argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param screened Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_AddressScreened(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseAddressScreened *screened)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s AddressScreened %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "partyNumber", tag, pos, seq_end,
++ &screened->number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "screeningIndicator", tag, pos, seq_end, &value));
++ screened->screening_indicator = value;
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ /* The optional subaddress must be present since there is something left. */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "partySubaddress", tag, pos,
++ seq_end, &screened->subaddress));
++ } else {
++ screened->subaddress.length = 0; /* Subaddress not present */
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the PresentedAddressScreened argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_PresentedAddressScreened(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePresentedAddressScreened *party)
++{
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s PresentedAddressScreened\n", name);
++ }
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ party->presentation = 0; /* presentationAllowedAddress */
++ ASN1_CALL(pos, rose_dec_AddressScreened(ctrl, "presentationAllowedAddress", tag,
++ pos, end, &party->screened));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ party->presentation = 1; /* presentationRestricted */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "presentationRestricted", tag, pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ party->presentation = 2; /* numberNotAvailableDueToInterworking */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "numberNotAvailableDueToInterworking", tag,
++ pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
++ party->presentation = 3; /* presentationRestrictedAddress */
++ ASN1_CALL(pos, rose_dec_AddressScreened(ctrl, "presentationRestrictedAddress",
++ tag, pos, end, &party->screened));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_address.c */
+
+Property changes on: rose_address.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_qsig_aoc.c
+===================================================================
+--- a/rose_qsig_aoc.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_qsig_aoc.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,1714 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief Q.SIG ROSE Advice-Of-Charge (AOC) operations
++ *
++ * SS-AOC-Operations ECMA-212 Annex E Table E.1
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Encode the Time type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param time Time information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOC_Time(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseQsigAOCTime *time)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ time->length));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2, time->scale));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the Amount type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param amount Amount information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOC_Amount(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseQsigAOCAmount *amount)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ amount->currency));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ amount->multiplier));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the RecordedCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param recorded Recorded currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOC_RecordedCurrency(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseQsigAOCRecordedCurrency *recorded)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ recorded->currency, sizeof(recorded->currency) - 1));
++ ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &recorded->amount));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the DurationCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param duration Duration currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOC_DurationCurrency(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseQsigAOCDurationCurrency *duration)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ duration->currency, sizeof(duration->currency) - 1));
++ ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &duration->amount));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ duration->charging_type));
++ ASN1_CALL(pos, rose_enc_qsig_AOC_Time(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 4, &duration->time));
++ if (duration->granularity_present) {
++ ASN1_CALL(pos, rose_enc_qsig_AOC_Time(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 5, &duration->granularity));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the FlatRateCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param flat_rate Flat rate currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOC_FlatRateCurrency(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseQsigAOCFlatRateCurrency *flat_rate)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ flat_rate->currency, sizeof(flat_rate->currency) - 1));
++ ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &flat_rate->amount));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the VolumeRateCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param volume_rate Volume rate currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOC_VolumeRateCurrency(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseQsigAOCVolumeRateCurrency *volume_rate)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ volume_rate->currency, sizeof(volume_rate->currency) - 1));
++ ASN1_CALL(pos, rose_enc_qsig_AOC_Amount(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &volume_rate->amount));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ volume_rate->unit));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the AOCSCurrencyInfo type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param currency_info Currency information record to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOCSCurrencyInfo(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseQsigAOCSCurrencyInfo *currency_info)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ currency_info->charged_item));
++
++ switch (currency_info->currency_type) {
++ case 0: /* specialChargingCode */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ currency_info->u.special_charging_code));
++ break;
++ case 1: /* durationCurrency */
++ ASN1_CALL(pos, rose_enc_qsig_AOC_DurationCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &currency_info->u.duration));
++ break;
++ case 2: /* flatRateCurrency */
++ ASN1_CALL(pos, rose_enc_qsig_AOC_FlatRateCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &currency_info->u.flat_rate));
++ break;
++ case 3: /* volumeRateCurrency */
++ ASN1_CALL(pos, rose_enc_qsig_AOC_VolumeRateCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 3, &currency_info->u.volume_rate));
++ break;
++ case 4: /* freeOfCharge */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
++ break;
++ case 5: /* currencyInfoNotAvailable */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5));
++ break;
++ case 6: /* freeOfChargeFromBeginning */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown currency type");
++ return NULL;
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the AOCSCurrencyInfoList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param currency_info Currency information list to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOCSCurrencyInfoList(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseQsigAOCSCurrencyInfoList *currency_info)
++{
++ unsigned index;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ for (index = 0; index < currency_info->num_records; ++index) {
++ ASN1_CALL(pos, rose_enc_qsig_AOCSCurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &currency_info->list[index]));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the ChargingAssociation type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param charging Charging association information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_AOC_ChargingAssociation(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end,
++ const struct roseQsigAOCChargingAssociation *charging)
++{
++ unsigned char *explicit_len;
++
++ switch (charging->type) {
++ case 0: /* charge_identifier */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, charging->id));
++ break;
++ case 1: /* charged_number */
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &charging->number));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown ChargingAssociation type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG ChargeRequest invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned index;
++ unsigned char *seq_len;
++ unsigned char *advice_len;
++ const struct roseQsigChargeRequestArg_ARG *charge_request;
++
++ charge_request = &args->qsig.ChargeRequest;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ /* SEQUENCE SIZE(0..7) OF AdviceModeCombination */
++ ASN1_CONSTRUCTED_BEGIN(advice_len, pos, end, ASN1_TAG_SEQUENCE);
++ for (index = 0; index < charge_request->num_records; ++index) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ charge_request->advice_mode_combinations[index]));
++ }
++ ASN1_CONSTRUCTED_END(advice_len, pos, end);
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG ChargeRequest result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigChargeRequestRes_RES *charge_request;
++
++ charge_request = &args->qsig.ChargeRequest;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ charge_request->advice_mode_combination));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG AocFinal invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_AocFinal_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ unsigned char *specific_len;
++ const struct roseQsigAocFinalArg_ARG *aoc_final;
++
++ aoc_final = &args->qsig.AocFinal;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ switch (aoc_final->type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0));
++ break;
++ case 1: /* free_of_charge */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ break;
++ case 2: /* specific_currency */
++ ASN1_CONSTRUCTED_BEGIN(specific_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_qsig_AOC_RecordedCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_final->specific.recorded));
++
++ if (aoc_final->specific.billing_id_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ aoc_final->specific.billing_id));
++ }
++
++ ASN1_CONSTRUCTED_END(specific_len, pos, end);
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AocFinal type");
++ return NULL;
++ }
++
++ if (aoc_final->charging_association_present) {
++ ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
++ &aoc_final->charging_association));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG AocInterim invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_AocInterim_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ unsigned char *specific_len;
++ const struct roseQsigAocInterimArg_ARG *aoc_interim;
++
++ aoc_interim = &args->qsig.AocInterim;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ switch (aoc_interim->type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0));
++ break;
++ case 1: /* free_of_charge */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ break;
++ case 2: /* specific_currency */
++ ASN1_CONSTRUCTED_BEGIN(specific_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_qsig_AOC_RecordedCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_interim->specific.recorded));
++
++ if (aoc_interim->specific.billing_id_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ aoc_interim->specific.billing_id));
++ }
++
++ ASN1_CONSTRUCTED_END(specific_len, pos, end);
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AocInterim type");
++ return NULL;
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG AocRate invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_AocRate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigAocRateArg_ARG *aoc_rate;
++
++ aoc_rate = &args->qsig.AocRate;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ switch (aoc_rate->type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ break;
++ case 1: /* currency_info_list */
++ ASN1_CALL(pos, rose_enc_qsig_AOCSCurrencyInfoList(ctrl, pos, end,
++ ASN1_TAG_SEQUENCE, &aoc_rate->currency_info));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AocRate type");
++ return NULL;
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG AocComplete invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_AocComplete_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigAocCompleteArg_ARG *aoc_complete;
++
++ aoc_complete = &args->qsig.AocComplete;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &aoc_complete->charged_user_number));
++
++ if (aoc_complete->charging_association_present) {
++ ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
++ &aoc_complete->charging_association));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG AocComplete result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_AocComplete_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigAocCompleteRes_RES *aoc_complete;
++
++ aoc_complete = &args->qsig.AocComplete;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ aoc_complete->charging_option));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG AocDivChargeReq invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigAocDivChargeReqArg_ARG *aoc_div_charge_req;
++
++ aoc_div_charge_req = &args->qsig.AocDivChargeReq;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &aoc_div_charge_req->diverting_user_number));
++
++ if (aoc_div_charge_req->charging_association_present) {
++ ASN1_CALL(pos, rose_enc_qsig_AOC_ChargingAssociation(ctrl, pos, end,
++ &aoc_div_charge_req->charging_association));
++ }
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ aoc_div_charge_req->diversion_type));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the Time type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param time Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOC_Time(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCTime *time)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s Time %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "lengthOfTimeUnit", tag, pos, seq_end, &value));
++ time->length = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "scale", tag, pos, seq_end, &value));
++ time->scale = value;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the Amount type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param amount Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOC_Amount(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCAmount *amount)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s Amount %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "currencyAmount", tag, pos, seq_end, &value));
++ amount->currency = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "multiplier", tag, pos, seq_end, &value));
++ amount->multiplier = value;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the RecordedCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param recorded Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOC_RecordedCurrency(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCRecordedCurrency *recorded)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ size_t str_len;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s RecordedCurrency %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "rCurrency", tag, pos, seq_end,
++ sizeof(recorded->currency), recorded->currency, &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
++ ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "rAmount", tag, pos, seq_end,
++ &recorded->amount));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the DurationCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param duration Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOC_DurationCurrency(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCDurationCurrency *duration)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ size_t str_len;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s DurationCurrency %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "dCurrency", tag, pos, seq_end,
++ sizeof(duration->currency), duration->currency, &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
++ ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "dAmount", tag, pos, seq_end,
++ &duration->amount));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "dChargingType", tag, pos, seq_end, &value));
++ duration->charging_type = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4);
++ ASN1_CALL(pos, rose_dec_qsig_AOC_Time(ctrl, "dTime", tag, pos, seq_end,
++ &duration->time));
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5);
++ ASN1_CALL(pos, rose_dec_qsig_AOC_Time(ctrl, "dGranularity", tag, pos, seq_end,
++ &duration->granularity));
++ duration->granularity_present = 1;
++ } else {
++ duration->granularity_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the FlatRateCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param flat_rate Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOC_FlatRateCurrency(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCFlatRateCurrency *flat_rate)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ size_t str_len;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s FlatRateCurrency %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "fRCurrency", tag, pos, seq_end,
++ sizeof(flat_rate->currency), flat_rate->currency, &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
++ ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "fRAmount", tag, pos, seq_end,
++ &flat_rate->amount));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the VolumeRateCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param volume_rate Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOC_VolumeRateCurrency(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCVolumeRateCurrency *volume_rate)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ size_t str_len;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s VolumeRateCurrency %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "vRCurrency", tag, pos, seq_end,
++ sizeof(volume_rate->currency), volume_rate->currency, &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
++ ASN1_CALL(pos, rose_dec_qsig_AOC_Amount(ctrl, "vRAmount", tag, pos, seq_end,
++ &volume_rate->amount));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "vRVolumeUnit", tag, pos, seq_end, &value));
++ volume_rate->unit = value;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the AOCSCurrencyInfo type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param currency_info Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOCSCurrencyInfo(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCSCurrencyInfo *currency_info)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s AOCSCurrencyInfo %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargedItem", tag, pos, seq_end, &value));
++ currency_info->charged_item = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ currency_info->currency_type = 0; /* specialChargingCode */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "specialChargingCode", tag, pos, seq_end,
++ &value));
++ currency_info->u.special_charging_code = value;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ currency_info->currency_type = 1; /* durationCurrency */
++ ASN1_CALL(pos, rose_dec_qsig_AOC_DurationCurrency(ctrl, "durationCurrency", tag,
++ pos, seq_end, &currency_info->u.duration));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ currency_info->currency_type = 2; /* flatRateCurrency */
++ ASN1_CALL(pos, rose_dec_qsig_AOC_FlatRateCurrency(ctrl, "flatRateCurrency", tag,
++ pos, seq_end, &currency_info->u.flat_rate));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
++ currency_info->currency_type = 3; /* volumeRateCurrency */
++ ASN1_CALL(pos, rose_dec_qsig_AOC_VolumeRateCurrency(ctrl, "volumeRateCurrency",
++ tag, pos, seq_end, &currency_info->u.volume_rate));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ currency_info->currency_type = 4; /* freeOfCharge */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
++ currency_info->currency_type = 5; /* currencyInfoNotAvailable */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "currencyInfoNotAvailable", tag, pos,
++ seq_end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 6:
++ currency_info->currency_type = 6; /* freeOfChargeFromBeginning */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfChargeFromBeginning", tag, pos,
++ seq_end));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the AOCSCurrencyInfoList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param currency_info Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOCSCurrencyInfoList(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCSCurrencyInfoList *currency_info)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s AOCSCurrencyInfoList %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ currency_info->num_records = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ if (currency_info->num_records < ARRAY_LEN(currency_info->list)) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_qsig_AOCSCurrencyInfo(ctrl, "listEntry", tag, pos,
++ seq_end, &currency_info->list[currency_info->num_records]));
++ ++currency_info->num_records;
++ } else {
++ /* Too many records */
++ return NULL;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the ChargingAssociation type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param charging Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_AOC_ChargingAssociation(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigAOCChargingAssociation *charging)
++{
++ int32_t value;
++ int length;
++ int explicit_offset;
++ const unsigned char *explicit_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s ChargingAssociation\n", name);
++ }
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ charging->type = 0; /* charge_identifier */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargeIdentifier", tag, pos, end, &value));
++ charging->id = value;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ charging->type = 1; /* charged_number */
++
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedNumber", tag, pos,
++ explicit_end, &charging->number));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG ChargeRequest invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_ChargeRequest_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int advice_offset;
++ const unsigned char *seq_end;
++ const unsigned char *advice_end;
++ struct roseQsigChargeRequestArg_ARG *charge_request;
++
++ charge_request = &args->qsig.ChargeRequest;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " ChargeRequest %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ /* SEQUENCE SIZE(0..7) OF AdviceModeCombination */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " adviceModeCombinations %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(advice_end, advice_offset, length, pos, seq_end);
++
++ /* Decode SIZE(0..7) OF AdviceModeCombination */
++ charge_request->num_records = 0;
++ while (pos < advice_end && *pos != ASN1_INDEF_TERM) {
++ if (charge_request->num_records <
++ ARRAY_LEN(charge_request->advice_mode_combinations)) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, advice_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "adviceModeCombination", tag, pos,
++ advice_end, &value));
++ charge_request->advice_mode_combinations[charge_request->num_records] =
++ value;
++ ++charge_request->num_records;
++ } else {
++ /* Too many records */
++ return NULL;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, advice_offset, advice_end, seq_end);
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG ChargeRequest result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_ChargeRequest_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigChargeRequestRes_RES *charge_request;
++
++ charge_request = &args->qsig.ChargeRequest;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " ChargeRequest %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "adviceModeCombination", tag, pos, seq_end,
++ &value));
++ charge_request->advice_mode_combination = value;
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG AocFinal invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_AocFinal_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int specific_offset;
++ const unsigned char *seq_end;
++ const unsigned char *specific_end;
++ const unsigned char *save_pos;
++ struct roseQsigAocFinalArg_ARG *aoc_final;
++
++ aoc_final = &args->qsig.AocFinal;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " AocFinal %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ aoc_final->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ aoc_final->type = 1; /* free_of_charge */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ aoc_final->type = 2; /* specific_currency */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
++ ASN1_CALL(pos, rose_dec_qsig_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
++ pos, specific_end, &aoc_final->specific.recorded));
++
++ if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "finalBillingId", tag, pos, specific_end,
++ &value));
++ aoc_final->specific.billing_id = value;
++ aoc_final->specific.billing_id_present = 1;
++ } else {
++ aoc_final->specific.billing_id_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ aoc_final->charging_association_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ case ASN1_TYPE_INTEGER:
++ ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl,
++ "chargingAssociation", tag, pos, seq_end,
++ &aoc_final->charging_association));
++ aoc_final->charging_association_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " finalArgExtension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG AocInterim invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_AocInterim_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int specific_offset;
++ const unsigned char *seq_end;
++ const unsigned char *specific_end;
++ struct roseQsigAocInterimArg_ARG *aoc_interim;
++
++ aoc_interim = &args->qsig.AocInterim;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " AocInterim %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ aoc_interim->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ aoc_interim->type = 1; /* free_of_charge */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ aoc_interim->type = 2; /* specific_currency */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
++ ASN1_CALL(pos, rose_dec_qsig_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
++ pos, specific_end, &aoc_interim->specific.recorded));
++
++ if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "interimBillingId", tag, pos, specific_end,
++ &value));
++ aoc_interim->specific.billing_id = value;
++ aoc_interim->specific.billing_id_present = 1;
++ } else {
++ aoc_interim->specific.billing_id_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG AocRate invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_AocRate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigAocRateArg_ARG *aoc_rate;
++
++ aoc_rate = &args->qsig.AocRate;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " AocRate %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ aoc_rate->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, seq_end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ aoc_rate->type = 1; /* currency_info_list */
++ ASN1_CALL(pos, rose_dec_qsig_AOCSCurrencyInfoList(ctrl, "aocSCurrencyInfoList",
++ tag, pos, seq_end, &aoc_rate->currency_info));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG AocComplete invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_AocComplete_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigAocCompleteArg_ARG *aoc_complete;
++
++ aoc_complete = &args->qsig.AocComplete;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " AocComplete %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedUser", tag, pos, seq_end,
++ &aoc_complete->charged_user_number));
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ aoc_complete->charging_association_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ case ASN1_TYPE_INTEGER:
++ ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl,
++ "chargingAssociation", tag, pos, seq_end,
++ &aoc_complete->charging_association));
++ aoc_complete->charging_association_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " completeArgExtension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG AocComplete result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_AocComplete_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigAocCompleteRes_RES *aoc_complete;
++
++ aoc_complete = &args->qsig.AocComplete;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " AocComplete %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargingOption", tag, pos, seq_end, &value));
++ aoc_complete->charging_option = value;
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG AocDivChargeReq invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_AocDivChargeReq_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigAocDivChargeReqArg_ARG *aoc_div_charge_req;
++
++ aoc_div_charge_req = &args->qsig.AocDivChargeReq;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " AocDivChargeReq %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "divertingUser", tag, pos, seq_end,
++ &aoc_div_charge_req->diverting_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ case ASN1_TYPE_INTEGER:
++ ASN1_CALL(pos, rose_dec_qsig_AOC_ChargingAssociation(ctrl, "chargingAssociation",
++ tag, pos, seq_end, &aoc_div_charge_req->charging_association));
++ aoc_div_charge_req->charging_association_present = 1;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ break;
++ default:
++ aoc_div_charge_req->charging_association_present = 0;
++ break;
++ }
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionType", tag, pos, seq_end, &value));
++ aoc_div_charge_req->diversion_type = value;
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_qsig_aoc.c */
+
+Property changes on: rose_qsig_aoc.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_etsi_aoc.c
+===================================================================
+--- a/rose_etsi_aoc.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_etsi_aoc.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,1929 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ROSE Advice Of Charge (AOC) operations
++ *
++ * Advice of Charge (AOC) supplementary service EN 300 182-1
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Encode the Time type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param time Time information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_Time(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseEtsiAOCTime *time)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ time->length));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2, time->scale));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the Amount type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param amount Amount information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_Amount(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseEtsiAOCAmount *amount)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ amount->currency));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ amount->multiplier));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the RecordedCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param recorded Recorded currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_RecordedCurrency(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCRecordedCurrency *recorded)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ recorded->currency, sizeof(recorded->currency) - 1));
++ ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &recorded->amount));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the DurationCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param duration Duration currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_DurationCurrency(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCDurationCurrency *duration)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ duration->currency, sizeof(duration->currency) - 1));
++ ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &duration->amount));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ duration->charging_type));
++ ASN1_CALL(pos, rose_enc_etsi_AOC_Time(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 4, &duration->time));
++ if (duration->granularity_present) {
++ ASN1_CALL(pos, rose_enc_etsi_AOC_Time(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 5, &duration->granularity));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the FlatRateCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param flat_rate Flat rate currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_FlatRateCurrency(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCFlatRateCurrency *flat_rate)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ flat_rate->currency, sizeof(flat_rate->currency) - 1));
++ ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &flat_rate->amount));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the VolumeRateCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param volume_rate Volume rate currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_VolumeRateCurrency(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCVolumeRateCurrency *volume_rate)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
++ volume_rate->currency, sizeof(volume_rate->currency) - 1));
++ ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &volume_rate->amount));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ volume_rate->unit));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the AOCSCurrencyInfo type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param currency_info Currency information record to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOCSCurrencyInfo(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCSCurrencyInfo *currency_info)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ currency_info->charged_item));
++
++ switch (currency_info->currency_type) {
++ case 0: /* specialChargingCode */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ currency_info->u.special_charging_code));
++ break;
++ case 1: /* durationCurrency */
++ ASN1_CALL(pos, rose_enc_etsi_AOC_DurationCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &currency_info->u.duration));
++ break;
++ case 2: /* flatRateCurrency */
++ ASN1_CALL(pos, rose_enc_etsi_AOC_FlatRateCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 2, &currency_info->u.flat_rate));
++ break;
++ case 3: /* volumeRateCurrency */
++ ASN1_CALL(pos, rose_enc_etsi_AOC_VolumeRateCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 3, &currency_info->u.volume_rate));
++ break;
++ case 4: /* freeOfCharge */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
++ break;
++ case 5: /* currencyInfoNotAvailable */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown currency type");
++ return NULL;
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the AOCSCurrencyInfoList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param currency_info Currency information list to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOCSCurrencyInfoList(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCSCurrencyInfoList *currency_info)
++{
++ unsigned index;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ for (index = 0; index < currency_info->num_records; ++index) {
++ ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &currency_info->list[index]));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the RecordedUnits type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param recorded Recorded units information record to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_RecordedUnits(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCRecordedUnits *recorded)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ if (recorded->not_available) {
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ } else {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ recorded->number_of_units));
++ }
++
++ if (recorded->type_of_unit_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ recorded->type_of_unit));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the RecordedUnitsList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param recorded_info Recorded units information list to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_RecordedUnitsList(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCRecordedUnitsList *recorded_info)
++{
++ unsigned index;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ for (index = 0; index < recorded_info->num_records; ++index) {
++ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnits(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &recorded_info->list[index]));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the ChargingAssociation type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param charging Charging association information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOC_ChargingAssociation(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end,
++ const struct roseEtsiAOCChargingAssociation *charging)
++{
++ unsigned char *explicit_len;
++
++ switch (charging->type) {
++ case 0: /* charge_identifier */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, charging->id));
++ break;
++ case 1: /* charged_number */
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &charging->number));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown ChargingAssociation type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the AOCECurrencyInfo type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param currency_info Currency information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOCECurrencyInfo(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCECurrencyInfo *currency_info)
++{
++ unsigned char *seq_len;
++ unsigned char *specific_seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ if (currency_info->free_of_charge) {
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ } else {
++ ASN1_CONSTRUCTED_BEGIN(specific_seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &currency_info->specific.recorded));
++
++ if (currency_info->specific.billing_id_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ currency_info->specific.billing_id));
++ }
++
++ ASN1_CONSTRUCTED_END(specific_seq_len, pos, end);
++ }
++
++ if (currency_info->charging_association_present) {
++ ASN1_CALL(pos, rose_enc_etsi_AOC_ChargingAssociation(ctrl, pos, end,
++ &currency_info->charging_association));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the AOCEChargingUnitInfo type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param charging_unit Charging unit information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_AOCEChargingUnitInfo(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiAOCEChargingUnitInfo *charging_unit)
++{
++ unsigned char *seq_len;
++ unsigned char *specific_seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ if (charging_unit->free_of_charge) {
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ } else {
++ ASN1_CONSTRUCTED_BEGIN(specific_seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnitsList(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &charging_unit->specific.recorded));
++
++ if (charging_unit->specific.billing_id_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ charging_unit->specific.billing_id));
++ }
++
++ ASN1_CONSTRUCTED_END(specific_seq_len, pos, end);
++ }
++
++ if (charging_unit->charging_association_present) {
++ ASN1_CALL(pos, rose_enc_etsi_AOC_ChargingAssociation(ctrl, pos, end,
++ &charging_unit->charging_association));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the ChargingRequest invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ args->etsi.ChargingRequest.charging_case);
++}
++
++/*!
++ * \brief Encode the ChargingRequest result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args)
++{
++ switch (args->etsi.ChargingRequest.type) {
++ case 0: /* currency_info_list */
++ ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
++ ASN1_TAG_SEQUENCE, &args->etsi.ChargingRequest.u.currency_info));
++ break;
++ case 1: /* special_arrangement_info */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ args->etsi.ChargingRequest.u.special_arrangement));
++ break;
++ case 2: /* charging_info_follows */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown ChargingRequst type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the AOCSCurrency invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ switch (args->etsi.AOCSCurrency.type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ break;
++ case 1: /* currency_info_list */
++ ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
++ ASN1_TAG_SEQUENCE, &args->etsi.AOCSCurrency.currency_info));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AOCSCurrency type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the AOCSSpecialArr invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ switch (args->etsi.AOCSSpecialArr.type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ break;
++ case 1: /* special_arrangement_info */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ args->etsi.AOCSSpecialArr.special_arrangement));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AOCSSpecialArr type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the AOCDCurrency invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiAOCDCurrency_ARG *aoc_d;
++ unsigned char *seq_len;
++
++ aoc_d = &args->etsi.AOCDCurrency;
++ switch (aoc_d->type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ break;
++ case 1: /* free_of_charge */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ break;
++ case 2: /* specific_currency */
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedCurrency(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_d->specific.recorded));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ aoc_d->specific.type_of_charging_info));
++ if (aoc_d->specific.billing_id_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ aoc_d->specific.billing_id));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AOCDCurrency type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the AOCDChargingUnit invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiAOCDChargingUnit_ARG *aoc_d;
++ unsigned char *seq_len;
++
++ aoc_d = &args->etsi.AOCDChargingUnit;
++ switch (aoc_d->type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ break;
++ case 1: /* free_of_charge */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
++ break;
++ case 2: /* specific_charging_units */
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnitsList(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_d->specific.recorded));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ aoc_d->specific.type_of_charging_info));
++ if (aoc_d->specific.billing_id_present) {
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
++ aoc_d->specific.billing_id));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AOCDChargingUnit type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the AOCECurrency invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ switch (args->etsi.AOCECurrency.type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ break;
++ case 1: /* currency_info */
++ ASN1_CALL(pos, rose_enc_etsi_AOCECurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &args->etsi.AOCECurrency.currency_info));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AOCECurrency type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the AOCEChargingUnit invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ switch (args->etsi.AOCEChargingUnit.type) {
++ case 0: /* charge_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
++ break;
++ case 1: /* charging_unit */
++ ASN1_CALL(pos, rose_enc_etsi_AOCEChargingUnitInfo(ctrl, pos, end,
++ ASN1_TAG_SEQUENCE, &args->etsi.AOCEChargingUnit.charging_unit));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown AOCEChargingUnit type");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the Time type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param time Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_Time(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCTime *time)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s Time %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "lengthOfTimeUnit", tag, pos, seq_end, &value));
++ time->length = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "scale", tag, pos, seq_end, &value));
++ time->scale = value;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the Amount type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param amount Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_Amount(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCAmount *amount)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s Amount %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "currencyAmount", tag, pos, seq_end, &value));
++ amount->currency = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "multiplier", tag, pos, seq_end, &value));
++ amount->multiplier = value;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the RecordedCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param recorded Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_RecordedCurrency(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCRecordedCurrency *recorded)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ size_t str_len;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s RecordedCurrency %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "rCurrency", tag, pos, seq_end,
++ sizeof(recorded->currency), recorded->currency, &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "rAmount", tag, pos, seq_end,
++ &recorded->amount));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the DurationCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param duration Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_DurationCurrency(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCDurationCurrency *duration)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ size_t str_len;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s DurationCurrency %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "dCurrency", tag, pos, seq_end,
++ sizeof(duration->currency), duration->currency, &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "dAmount", tag, pos, seq_end,
++ &duration->amount));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "dChargingType", tag, pos, seq_end, &value));
++ duration->charging_type = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_Time(ctrl, "dTime", tag, pos, seq_end,
++ &duration->time));
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_Time(ctrl, "dGranularity", tag, pos, seq_end,
++ &duration->granularity));
++ duration->granularity_present = 1;
++ } else {
++ duration->granularity_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the FlatRateCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param flat_rate Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_FlatRateCurrency(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCFlatRateCurrency *flat_rate)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ size_t str_len;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s FlatRateCurrency %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "fRCurrency", tag, pos, seq_end,
++ sizeof(flat_rate->currency), flat_rate->currency, &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "fRAmount", tag, pos, seq_end,
++ &flat_rate->amount));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the VolumeRateCurrency type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param volume_rate Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_VolumeRateCurrency(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCVolumeRateCurrency *volume_rate)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ size_t str_len;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s VolumeRateCurrency %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "vRCurrency", tag, pos, seq_end,
++ sizeof(volume_rate->currency), volume_rate->currency, &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "vRAmount", tag, pos, seq_end,
++ &volume_rate->amount));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "vRVolumeUnit", tag, pos, seq_end, &value));
++ volume_rate->unit = value;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the AOCSCurrencyInfo type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param currency_info Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOCSCurrencyInfo(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCSCurrencyInfo *currency_info)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s AOCSCurrencyInfo %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargedItem", tag, pos, seq_end, &value));
++ currency_info->charged_item = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ currency_info->currency_type = 0; /* specialChargingCode */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "specialChargingCode", tag, pos, seq_end,
++ &value));
++ currency_info->u.special_charging_code = value;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ currency_info->currency_type = 1; /* durationCurrency */
++ ASN1_CALL(pos, rose_dec_etsi_AOC_DurationCurrency(ctrl, "durationCurrency", tag,
++ pos, seq_end, &currency_info->u.duration));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ currency_info->currency_type = 2; /* flatRateCurrency */
++ ASN1_CALL(pos, rose_dec_etsi_AOC_FlatRateCurrency(ctrl, "flatRateCurrency", tag,
++ pos, seq_end, &currency_info->u.flat_rate));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
++ currency_info->currency_type = 3; /* volumeRateCurrency */
++ ASN1_CALL(pos, rose_dec_etsi_AOC_VolumeRateCurrency(ctrl, "volumeRateCurrency",
++ tag, pos, seq_end, &currency_info->u.volume_rate));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ currency_info->currency_type = 4; /* freeOfCharge */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
++ currency_info->currency_type = 5; /* currencyInfoNotAvailable */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "currencyInfoNotAvailable", tag, pos,
++ seq_end));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the AOCSCurrencyInfoList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param currency_info Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOCSCurrencyInfoList(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCSCurrencyInfoList *currency_info)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s AOCSCurrencyInfoList %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ currency_info->num_records = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ if (currency_info->num_records < ARRAY_LEN(currency_info->list)) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfo(ctrl, "listEntry", tag, pos,
++ seq_end, &currency_info->list[currency_info->num_records]));
++ ++currency_info->num_records;
++ } else {
++ /* Too many records */
++ return NULL;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the RecordedUnits type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param recorded Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_RecordedUnits(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCRecordedUnits *recorded)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s RecordedUnits %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ recorded->not_available = 0;
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "recordedNumberOfUnits", tag, pos, seq_end,
++ &value));
++ recorded->number_of_units = value;
++ break;
++ case ASN1_TYPE_NULL:
++ recorded->not_available = 1;
++ recorded->number_of_units = 0;
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "notAvailable", tag, pos, seq_end));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "recordedTypeOfUnits", tag, pos, seq_end,
++ &value));
++ recorded->type_of_unit = value;
++ recorded->type_of_unit_present = 1;
++ } else {
++ recorded->type_of_unit_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the RecordedUnitsList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param recorded_info Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_RecordedUnitsList(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCRecordedUnitsList *recorded_info)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s RecordedUnitsList %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ recorded_info->num_records = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ if (recorded_info->num_records < ARRAY_LEN(recorded_info->list)) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnits(ctrl, "listEntry", tag, pos,
++ seq_end, &recorded_info->list[recorded_info->num_records]));
++ ++recorded_info->num_records;
++ } else {
++ /* Too many records */
++ return NULL;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the ChargingAssociation type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param charging Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOC_ChargingAssociation(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCChargingAssociation *charging)
++{
++ int32_t value;
++ int length;
++ int explicit_offset;
++ const unsigned char *explicit_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s ChargingAssociation\n", name);
++ }
++ switch (tag) {
++ case ASN1_TYPE_INTEGER:
++ charging->type = 0; /* charge_identifier */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargeIdentifier", tag, pos, end, &value));
++ charging->id = value;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ charging->type = 1; /* charged_number */
++
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedNumber", tag, pos,
++ explicit_end, &charging->number));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the AOCECurrencyInfo type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param currency_info Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOCECurrencyInfo(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCECurrencyInfo *currency_info)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int specific_offset;
++ const unsigned char *seq_end;
++ const unsigned char *specific_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s AOCECurrencyInfo %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ currency_info->free_of_charge = 1;
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ currency_info->free_of_charge = 0;
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
++ pos, specific_end, &currency_info->specific.recorded));
++
++ if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, specific_end,
++ &value));
++ currency_info->specific.billing_id = value;
++ currency_info->specific.billing_id_present = 1;
++ } else {
++ currency_info->specific.billing_id_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_etsi_AOC_ChargingAssociation(ctrl, "chargingAssociation",
++ tag, pos, seq_end, &currency_info->charging_association));
++ currency_info->charging_association_present = 1;
++ } else {
++ currency_info->charging_association_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the AOCEChargingUnitInfo type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param charging_unit Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_AOCEChargingUnitInfo(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiAOCEChargingUnitInfo *charging_unit)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ int specific_offset;
++ const unsigned char *seq_end;
++ const unsigned char *specific_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s AOCEChargingUnitInfo %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ charging_unit->free_of_charge = 1;
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ charging_unit->free_of_charge = 0;
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " specificChargingUnits %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnitsList(ctrl, "recordedUnitsList",
++ tag, pos, specific_end, &charging_unit->specific.recorded));
++
++ if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, specific_end,
++ &value));
++ charging_unit->specific.billing_id = value;
++ charging_unit->specific.billing_id_present = 1;
++ } else {
++ charging_unit->specific.billing_id_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_etsi_AOC_ChargingAssociation(ctrl, "chargingAssociation",
++ tag, pos, seq_end, &charging_unit->charging_association));
++ charging_unit->charging_association_present = 1;
++ } else {
++ charging_unit->charging_association_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the ChargingRequest invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "chargingCase", tag, pos, end, &value));
++ args->etsi.ChargingRequest.charging_case = value;
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the ChargingRequest result parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
++{
++ struct roseEtsiChargingRequest_RES *charging_request;
++ int32_t value;
++
++ charging_request = &args->etsi.ChargingRequest;
++ switch (tag) {
++ case ASN1_TAG_SEQUENCE:
++ charging_request->type = 0; /* currency_info_list */
++ ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfoList(ctrl, "currencyList", tag, pos,
++ end, &charging_request->u.currency_info));
++ break;
++ case ASN1_TYPE_INTEGER:
++ charging_request->type = 1; /* special_arrangement_info */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "specialArrangement", tag, pos, end, &value));
++ charging_request->u.special_arrangement = value;
++ break;
++ case ASN1_TYPE_NULL:
++ charging_request->type = 2; /* charging_info_follows */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargingInfoFollows", tag, pos, end));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the AOCSCurrency invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiAOCSCurrency_ARG *aoc_s;
++
++ aoc_s = &args->etsi.AOCSCurrency;
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ aoc_s->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ aoc_s->type = 1; /* currency_info_list */
++ ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfoList(ctrl, "currencyInfo", tag, pos,
++ end, &aoc_s->currency_info));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the AOCSSpecialArr invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiAOCSSpecialArr_ARG *aoc_s;
++ int32_t value;
++
++ aoc_s = &args->etsi.AOCSSpecialArr;
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ aoc_s->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
++ break;
++ case ASN1_TYPE_INTEGER:
++ aoc_s->type = 1; /* special_arrangement_info */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "specialArrangement", tag, pos, end, &value));
++ aoc_s->special_arrangement = value;
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the AOCDCurrency invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiAOCDCurrency_ARG *aoc_d;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ aoc_d = &args->etsi.AOCDCurrency;
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ aoc_d->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ aoc_d->type = 1; /* free_of_charge */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ aoc_d->type = 2; /* specific_currency */
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
++ pos, seq_end, &aoc_d->specific.recorded));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfChargingInfo", tag, pos, seq_end,
++ &value));
++ aoc_d->specific.type_of_charging_info = value;
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, seq_end, &value));
++ aoc_d->specific.billing_id = value;
++ aoc_d->specific.billing_id_present = 1;
++ } else {
++ aoc_d->specific.billing_id_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the AOCDChargingUnit invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiAOCDChargingUnit_ARG *aoc_d;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ aoc_d = &args->etsi.AOCDChargingUnit;
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ aoc_d->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ aoc_d->type = 1; /* free_of_charge */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ aoc_d->type = 2; /* specific_charging_units */
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " specificChargingUnits %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
++ ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnitsList(ctrl, "recordedUnitsList",
++ tag, pos, seq_end, &aoc_d->specific.recorded));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfChargingInfo", tag, pos, seq_end,
++ &value));
++ aoc_d->specific.type_of_charging_info = value;
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, seq_end, &value));
++ aoc_d->specific.billing_id = value;
++ aoc_d->specific.billing_id_present = 1;
++ } else {
++ aoc_d->specific.billing_id_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the AOCECurrency invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiAOCECurrency_ARG *aoc_e;
++
++ aoc_e = &args->etsi.AOCECurrency;
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ aoc_e->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ aoc_e->type = 1; /* currency_info */
++ ASN1_CALL(pos, rose_dec_etsi_AOCECurrencyInfo(ctrl, "currencyInfo", tag, pos,
++ end, &aoc_e->currency_info));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the AOCEChargingUnit invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiAOCEChargingUnit_ARG *aoc_e;
++
++ aoc_e = &args->etsi.AOCEChargingUnit;
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ aoc_e->type = 0; /* charge_not_available */
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
++ break;
++ case ASN1_TAG_SEQUENCE:
++ aoc_e->type = 1; /* charging_unit */
++ ASN1_CALL(pos, rose_dec_etsi_AOCEChargingUnitInfo(ctrl, "chargingUnitInfo", tag,
++ pos, end, &aoc_e->charging_unit));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_etsi_aoc.c */
+
+Property changes on: rose_etsi_aoc.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_etsi_diversion.c
+===================================================================
+--- a/rose_etsi_diversion.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_etsi_diversion.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,1623 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ROSE Call diversion operations
++ *
++ * Diversion Supplementary Services ETS 300 207-1 Table 3
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Encode the ServedUserNr type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param served_user_number Served user number information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_ServedUserNumber(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end,
++ const struct rosePartyNumber *served_user_number)
++{
++ if (served_user_number->length) {
++ /* Forward this number */
++ pos = rose_enc_PartyNumber(ctrl, pos, end, served_user_number);
++ } else {
++ /* Forward all numbers */
++ pos = asn1_enc_null(pos, end, ASN1_TYPE_NULL);
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the IntResult type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
++ * tags it otherwise.
++ * \param int_result Forwarding record information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_IntResult(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseEtsiForwardingRecord *int_result)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
++ &int_result->served_user_number));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ int_result->basic_service));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, int_result->procedure));
++ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &int_result->forwarded_to));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the IntResultList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SET unless the caller implicitly
++ * tags it otherwise.
++ * \param int_result_list Forwarding record list information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_IntResultList(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag,
++ const struct roseEtsiForwardingList *int_result_list)
++{
++ unsigned index;
++ unsigned char *set_len;
++
++ ASN1_CONSTRUCTED_BEGIN(set_len, pos, end, tag);
++
++ for (index = 0; index < int_result_list->num_records; ++index) {
++ ASN1_CALL(pos, rose_enc_etsi_IntResult(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &int_result_list->list[index]));
++ }
++
++ ASN1_CONSTRUCTED_END(set_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the ServedUserNumberList type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SET unless the caller implicitly
++ * tags it otherwise.
++ * \param served_user_number_list Served user record list information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_etsi_ServedUserNumberList(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, unsigned tag,
++ const struct roseEtsiServedUserNumberList *served_user_number_list)
++{
++ unsigned index;
++ unsigned char *set_len;
++
++ ASN1_CONSTRUCTED_BEGIN(set_len, pos, end, tag);
++
++ for (index = 0; index < served_user_number_list->num_records; ++index) {
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &served_user_number_list->number[index]));
++ }
++
++ ASN1_CONSTRUCTED_END(set_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the ActivationDiversion invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_ActivationDiversion_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiActivationDiversion_ARG *activation_diversion;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ activation_diversion = &args->etsi.ActivationDiversion;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ activation_diversion->procedure));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ activation_diversion->basic_service));
++ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &activation_diversion->forwarded_to));
++ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
++ &activation_diversion->served_user_number));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the DeactivationDiversion invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiDeactivationDiversion_ARG *deactivation_diversion;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ deactivation_diversion = &args->etsi.DeactivationDiversion;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ deactivation_diversion->procedure));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ deactivation_diversion->basic_service));
++ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
++ &deactivation_diversion->served_user_number));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the ActivationStatusNotificationDiv invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiActivationStatusNotificationDiv_ARG
++ *activation_status_notification_div;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ activation_status_notification_div = &args->etsi.ActivationStatusNotificationDiv;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ activation_status_notification_div->procedure));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ activation_status_notification_div->basic_service));
++ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &activation_status_notification_div->forwarded_to));
++ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
++ &activation_status_notification_div->served_user_number));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the DeactivationStatusNotificationDiv invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_DeactivationStatusNotificationDiv_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiDeactivationStatusNotificationDiv_ARG
++ *deactivation_status_notification_div;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ deactivation_status_notification_div = &args->etsi.DeactivationStatusNotificationDiv;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ deactivation_status_notification_div->procedure));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ deactivation_status_notification_div->basic_service));
++ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
++ &deactivation_status_notification_div->served_user_number));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the InterrogationDiversion invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiInterrogationDiversion_ARG *interrogation_diversion;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ interrogation_diversion = &args->etsi.InterrogationDiversion;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ interrogation_diversion->procedure));
++ if (interrogation_diversion->basic_service) {
++ /* Not the DEFAULT value */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ interrogation_diversion->basic_service));
++ }
++ ASN1_CALL(pos, rose_enc_etsi_ServedUserNumber(ctrl, pos, end,
++ &interrogation_diversion->served_user_number));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the InterrogationDiversion result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_InterrogationDiversion_RES(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
++{
++ return rose_enc_etsi_IntResultList(ctrl, pos, end, ASN1_TAG_SET,
++ &args->etsi.InterrogationDiversion);
++}
++
++/*!
++ * \brief Encode the DiversionInformation invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_DiversionInformation_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiDiversionInformation_ARG *diversion_information;
++ unsigned char *seq_len;
++ unsigned char *explicit_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ diversion_information = &args->etsi.DiversionInformation;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diversion_information->diversion_reason));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diversion_information->basic_service));
++ if (diversion_information->served_user_subaddress.length) {
++ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
++ &diversion_information->served_user_subaddress));
++ }
++ if (diversion_information->calling_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
++ ASN1_CALL(pos, rose_enc_PresentedAddressScreened(ctrl, pos, end,
++ &diversion_information->calling));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++ if (diversion_information->original_called_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &diversion_information->original_called));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++ if (diversion_information->last_diverting_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &diversion_information->last_diverting));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++ if (diversion_information->last_diverting_reason_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diversion_information->last_diverting_reason));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++ if (diversion_information->q931ie.length) {
++ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
++ &diversion_information->q931ie));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the CallDeflection invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiCallDeflection_ARG *call_deflection;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ call_deflection = &args->etsi.CallDeflection;
++ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &call_deflection->deflection));
++ if (call_deflection->presentation_allowed_to_diverted_to_user_present) {
++ ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
++ call_deflection->presentation_allowed_to_diverted_to_user));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the CallRerouting invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiCallRerouting_ARG *call_rerouting;
++ unsigned char *seq_len;
++ unsigned char *explicit_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ call_rerouting = &args->etsi.CallRerouting;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ call_rerouting->rerouting_reason));
++ ASN1_CALL(pos, rose_enc_Address(ctrl, pos, end, ASN1_TAG_SEQUENCE,
++ &call_rerouting->called_address));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ call_rerouting->rerouting_counter));
++ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
++ &call_rerouting->q931ie));
++
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &call_rerouting->last_rerouting));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++
++ if (call_rerouting->subscription_option) {
++ /* Not the DEFAULT value */
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ call_rerouting->subscription_option));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++
++ if (call_rerouting->calling_subaddress.length) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
++ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
++ &call_rerouting->calling_subaddress));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the InterrogateServedUserNumbers result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
++{
++ return rose_enc_etsi_ServedUserNumberList(ctrl, pos, end, ASN1_TAG_SET,
++ &args->etsi.InterrogateServedUserNumbers);
++}
++
++/*!
++ * \brief Encode the DivertingLegInformation1 invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiDivertingLegInformation1_ARG *diverting_leg_information_1;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ diverting_leg_information_1 = &args->etsi.DivertingLegInformation1;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diverting_leg_information_1->diversion_reason));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diverting_leg_information_1->subscription_option));
++ if (diverting_leg_information_1->diverted_to_present) {
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &diverting_leg_information_1->diverted_to));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the DivertingLegInformation2 invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiDivertingLegInformation2_ARG *diverting_leg_information_2;
++ unsigned char *seq_len;
++ unsigned char *explicit_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ diverting_leg_information_2 = &args->etsi.DivertingLegInformation2;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ diverting_leg_information_2->diversion_counter));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ diverting_leg_information_2->diversion_reason));
++
++ if (diverting_leg_information_2->diverting_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &diverting_leg_information_2->diverting));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++
++ if (diverting_leg_information_2->original_called_present) {
++ /* EXPLICIT tag */
++ ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &diverting_leg_information_2->original_called));
++ ASN1_CONSTRUCTED_END(explicit_len, pos, end);
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the DivertingLegInformation3 invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return asn1_enc_boolean(pos, end, ASN1_TYPE_BOOLEAN,
++ args->etsi.DivertingLegInformation3.presentation_allowed_indicator);
++}
++
++/*!
++ * \internal
++ * \brief Decode the ServedUserNr argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param served_user_number Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_ServedUserNumber(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct rosePartyNumber *served_user_number)
++{
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s ServedUserNumber\n", name);
++ }
++ if (tag == ASN1_TYPE_NULL) {
++ served_user_number->length = 0;
++ pos = asn1_dec_null(ctrl, "allNumbers", tag, pos, end);
++ } else {
++ /* Must be a PartyNumber (Which is itself a CHOICE) */
++ pos =
++ rose_dec_PartyNumber(ctrl, "individualNumber", tag, pos, end,
++ served_user_number);
++ }
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the IntResult argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param int_result Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_IntResult(struct pri *ctrl, const char *name,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiForwardingRecord *int_result)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s IntResult %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
++ seq_end, &int_result->served_user_number));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ int_result->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ int_result->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_Address(ctrl, "forwardedToAddress", tag, pos, seq_end,
++ &int_result->forwarded_to));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the IntResultList argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param int_result_list Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_IntResultList(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiForwardingList *int_result_list)
++{
++ int length;
++ int set_offset;
++ const unsigned char *set_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s IntResultList %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(set_end, set_offset, length, pos, end);
++
++ int_result_list->num_records = 0;
++ while (pos < set_end && *pos != ASN1_INDEF_TERM) {
++ if (int_result_list->num_records < ARRAY_LEN(int_result_list->list)) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, set_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_etsi_IntResult(ctrl, "listEntry", tag, pos, set_end,
++ &int_result_list->list[int_result_list->num_records]));
++ ++int_result_list->num_records;
++ } else {
++ /* Too many records */
++ return NULL;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, set_offset, set_end, end);
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the ServedUserNumberList argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param served_user_number_list Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_etsi_ServedUserNumberList(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseEtsiServedUserNumberList *served_user_number_list)
++{
++ int length;
++ int set_offset;
++ const unsigned char *set_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s ServedUserNumberList %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(set_end, set_offset, length, pos, end);
++
++ served_user_number_list->num_records = 0;
++ while (pos < set_end && *pos != ASN1_INDEF_TERM) {
++ if (served_user_number_list->num_records <
++ ARRAY_LEN(served_user_number_list->number)) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, set_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "listEntry", tag, pos, set_end,
++ &served_user_number_list->number[served_user_number_list->num_records]));
++ ++served_user_number_list->num_records;
++ } else {
++ /* Too many records */
++ return NULL;
++ }
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, set_offset, set_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the ActivationDiversion invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_ActivationDiversion_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ struct roseEtsiActivationDiversion_ARG *activation_diversion;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " ActivationDiversion %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ activation_diversion = &args->etsi.ActivationDiversion;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ activation_diversion->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ activation_diversion->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_Address(ctrl, "forwardedToAddress", tag, pos, seq_end,
++ &activation_diversion->forwarded_to));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
++ seq_end, &activation_diversion->served_user_number));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the DeactivationDiversion invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_DeactivationDiversion_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ struct roseEtsiDeactivationDiversion_ARG *deactivation_diversion;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DeactivationDiversion %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ deactivation_diversion = &args->etsi.DeactivationDiversion;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ deactivation_diversion->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ deactivation_diversion->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
++ seq_end, &deactivation_diversion->served_user_number));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the ActivationStatusNotificationDiv invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_ActivationStatusNotificationDiv_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ struct roseEtsiActivationStatusNotificationDiv_ARG
++ *activation_status_notification_div;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " ActivationStatusNotificationDiv %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ activation_status_notification_div = &args->etsi.ActivationStatusNotificationDiv;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ activation_status_notification_div->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ activation_status_notification_div->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_Address(ctrl, "forwardedToAddress", tag, pos, seq_end,
++ &activation_status_notification_div->forwarded_to));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
++ seq_end, &activation_status_notification_div->served_user_number));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the DeactivationStatusNotificationDiv invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_DeactivationStatusNotificationDiv_ARG(struct pri
++ *ctrl, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ struct roseEtsiDeactivationStatusNotificationDiv_ARG
++ *deactivation_status_notification_div;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DeactivationStatusNotificationDiv %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ deactivation_status_notification_div = &args->etsi.DeactivationStatusNotificationDiv;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ deactivation_status_notification_div->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ deactivation_status_notification_div->basic_service = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "forwardedToAddress", tag, pos,
++ seq_end, &deactivation_status_notification_div->served_user_number));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the InterrogationDiversion invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_InterrogationDiversion_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ struct roseEtsiInterrogationDiversion_ARG *interrogation_diversion;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " InterrogationDiversion %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ interrogation_diversion = &args->etsi.InterrogationDiversion;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "procedure", tag, pos, seq_end, &value));
++ interrogation_diversion->procedure = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ if (tag == ASN1_TYPE_ENUMERATED) {
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ } else {
++ value = 0; /* DEFAULT BasicService value (allServices) */
++ }
++ interrogation_diversion->basic_service = value;
++
++ ASN1_CALL(pos, rose_dec_etsi_ServedUserNumber(ctrl, "servedUserNr", tag, pos,
++ seq_end, &interrogation_diversion->served_user_number));
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the InterrogationDiversion result parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_InterrogationDiversion_RES(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args)
++{
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SET);
++ return rose_dec_etsi_IntResultList(ctrl, "diversionList", tag, pos, end,
++ &args->etsi.InterrogationDiversion);
++}
++
++/*!
++ * \brief Decode the DiversionInformation invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_DiversionInformation_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ struct roseEtsiDiversionInformation_ARG *diversion_information;
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *seq_end;
++ const unsigned char *explicit_end;
++ const unsigned char *save_pos;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DiversionInformation %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ diversion_information = &args->etsi.DiversionInformation;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
++ diversion_information->diversion_reason = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
++ diversion_information->basic_service = value;
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ diversion_information->served_user_subaddress.length = 0;
++ diversion_information->calling_present = 0;
++ diversion_information->original_called_present = 0;
++ diversion_information->last_diverting_present = 0;
++ diversion_information->last_diverting_reason_present = 0;
++ diversion_information->q931ie.length = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_TAG_SEQUENCE:
++ case ASN1_TYPE_OCTET_STRING:
++ case ASN1_TYPE_OCTET_STRING | ASN1_PC_CONSTRUCTED:
++ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "servedUserSubaddress", tag,
++ pos, seq_end, &diversion_information->served_user_subaddress));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedAddressScreened(ctrl, "callingAddress", tag,
++ pos, explicit_end, &diversion_information->calling));
++ diversion_information->calling_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "originalCalledNr",
++ tag, pos, explicit_end, &diversion_information->original_called));
++ diversion_information->original_called_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "lastDivertingNr",
++ tag, pos, explicit_end, &diversion_information->last_diverting));
++ diversion_information->last_diverting_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "lastDivertingReason", tag, pos,
++ explicit_end, &value));
++ diversion_information->last_diverting_reason = value;
++ diversion_information->last_diverting_reason_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_APPLICATION | 0:
++ case ASN1_CLASS_APPLICATION | ASN1_PC_CONSTRUCTED | 0:
++ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "userInfo", tag, pos, seq_end,
++ &diversion_information->q931ie,
++ sizeof(diversion_information->q931ie_contents)));
++ break;
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the CallDeflection invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_CallDeflection_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiCallDeflection_ARG *call_deflection;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallDeflection %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ call_deflection = &args->etsi.CallDeflection;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_Address(ctrl, "deflectionAddress", tag, pos, seq_end,
++ &call_deflection->deflection));
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
++ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "presentationAllowedDivertedToUser", tag,
++ pos, seq_end, &value));
++ call_deflection->presentation_allowed_to_diverted_to_user = value;
++ call_deflection->presentation_allowed_to_diverted_to_user_present = 1;
++ } else {
++ call_deflection->presentation_allowed_to_diverted_to_user_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the CallRerouting invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_CallRerouting_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiCallRerouting_ARG *call_rerouting;
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *seq_end;
++ const unsigned char *explicit_end;
++ const unsigned char *save_pos;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallRerouting %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ call_rerouting = &args->etsi.CallRerouting;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "reroutingReason", tag, pos, seq_end, &value));
++ call_rerouting->rerouting_reason = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ ASN1_CALL(pos, rose_dec_Address(ctrl, "calledAddress", tag, pos, seq_end,
++ &call_rerouting->called_address));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "reroutingCounter", tag, pos, seq_end, &value));
++ call_rerouting->rerouting_counter = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_CLASS_APPLICATION | 0);
++ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "q931ie", tag, pos, seq_end,
++ &call_rerouting->q931ie, sizeof(call_rerouting->q931ie_contents)));
++
++ /* Remove EXPLICIT tag */
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag,
++ ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "lastReroutingNr", tag, pos,
++ explicit_end, &call_rerouting->last_rerouting));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ call_rerouting->subscription_option = 0; /* DEFAULT value noNotification */
++ call_rerouting->calling_subaddress.length = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "subscriptionOption", tag, pos,
++ explicit_end, &value));
++ call_rerouting->subscription_option = value;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "callingPartySubaddress", tag,
++ pos, explicit_end, &call_rerouting->calling_subaddress));
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the InterrogateServedUserNumbers result parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_InterrogateServedUserNumbers_RES(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args)
++{
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SET);
++ return rose_dec_etsi_ServedUserNumberList(ctrl, "interrogateServedUserNumbers", tag,
++ pos, end, &args->etsi.InterrogateServedUserNumbers);
++}
++
++/*!
++ * \brief Decode the DivertingLegInformation1 invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_DivertingLegInformation1_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ struct roseEtsiDivertingLegInformation1_ARG *diverting_leg_informtion_1;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DivertingLegInformation1 %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ diverting_leg_informtion_1 = &args->etsi.DivertingLegInformation1;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
++ diverting_leg_informtion_1->diversion_reason = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "subscriptionOption", tag, pos, seq_end, &value));
++ diverting_leg_informtion_1->subscription_option = value;
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "divertedToNumber", tag,
++ pos, seq_end, &diverting_leg_informtion_1->diverted_to));
++ diverting_leg_informtion_1->diverted_to_present = 1;
++ } else {
++ diverting_leg_informtion_1->diverted_to_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the DivertingLegInformation2 invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_DivertingLegInformation2_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ struct roseEtsiDivertingLegInformation2_ARG *diverting_leg_information_2;
++ int length;
++ int seq_offset;
++ int explicit_offset;
++ const unsigned char *seq_end;
++ const unsigned char *explicit_end;
++ const unsigned char *save_pos;
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " DivertingLegInformation2 %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ diverting_leg_information_2 = &args->etsi.DivertingLegInformation2;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionCounter", tag, pos, seq_end, &value));
++ diverting_leg_information_2->diversion_counter = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "diversionReason", tag, pos, seq_end, &value));
++ diverting_leg_information_2->diversion_reason = value;
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ diverting_leg_information_2->diverting_present = 0;
++ diverting_leg_information_2->original_called_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "divertingNr", tag,
++ pos, explicit_end, &diverting_leg_information_2->diverting));
++ diverting_leg_information_2->diverting_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ /* Remove EXPLICIT tag */
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
++ ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "originalCalledNr",
++ tag, pos, explicit_end, &diverting_leg_information_2->original_called));
++ diverting_leg_information_2->original_called_present = 1;
++
++ ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
++ break;
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the DivertingLegInformation3 invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_DivertingLegInformation3_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_BOOLEAN);
++ ASN1_CALL(pos, asn1_dec_boolean(ctrl, "presentationAllowedIndicator", tag, pos, end,
++ &value));
++ args->etsi.DivertingLegInformation3.presentation_allowed_indicator = value;
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_etsi_diversion.c */
+
+Property changes on: rose_etsi_diversion.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_qsig_ct.c
+===================================================================
+--- a/rose_qsig_ct.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_qsig_ct.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,883 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief Q.SIG ROSE Call-Transfer-Operations (CT)
++ *
++ * Call-Transfer-Operations ECMA-178 Annex F Table F.1
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \brief Encode the Q.SIG CallTransferIdentify result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CallTransferIdentify_RES(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_result_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigCTIdentifyRes_RES *call_transfer_identify;
++
++ call_transfer_identify = &args->qsig.CallTransferIdentify;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
++ call_transfer_identify->call_id, sizeof(call_transfer_identify->call_id) - 1));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &call_transfer_identify->rerouting_number));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG CallTransferInitiate invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigCTInitiateArg_ARG *call_transfer_initiate;
++
++ call_transfer_initiate = &args->qsig.CallTransferInitiate;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
++ call_transfer_initiate->call_id, sizeof(call_transfer_initiate->call_id) - 1));
++ ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
++ &call_transfer_initiate->rerouting_number));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG CallTransferSetup invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigCTSetupArg_ARG *call_transfer_setup;
++
++ call_transfer_setup = &args->qsig.CallTransferSetup;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_NUMERIC_STRING,
++ call_transfer_setup->call_id, sizeof(call_transfer_setup->call_id) - 1));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG CallTransferActive invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigCTActiveArg_ARG *call_transfer_active;
++
++ call_transfer_active = &args->qsig.CallTransferActive;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_PresentedAddressScreened(ctrl, pos, end,
++ &call_transfer_active->connected));
++
++ if (call_transfer_active->q931ie.length) {
++ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
++ &call_transfer_active->q931ie));
++ }
++
++ if (call_transfer_active->connected_name_present) {
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &call_transfer_active->connected_name));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG CallTransferComplete invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CallTransferComplete_ARG(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigCTCompleteArg_ARG *call_transfer_complete;
++
++ call_transfer_complete = &args->qsig.CallTransferComplete;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ call_transfer_complete->end_designation));
++
++ ASN1_CALL(pos, rose_enc_PresentedNumberScreened(ctrl, pos, end,
++ &call_transfer_complete->redirection));
++
++ if (call_transfer_complete->q931ie.length) {
++ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
++ &call_transfer_complete->q931ie));
++ }
++
++ if (call_transfer_complete->redirection_name_present) {
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &call_transfer_complete->redirection_name));
++ }
++
++ if (call_transfer_complete->call_status) {
++ /* Not the DEFAULT value */
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ call_transfer_complete->call_status));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG CallTransferUpdate invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigCTUpdateArg_ARG *call_transfer_update;
++
++ call_transfer_update = &args->qsig.CallTransferUpdate;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_PresentedNumberScreened(ctrl, pos, end,
++ &call_transfer_update->redirection));
++
++ if (call_transfer_update->redirection_name_present) {
++ ASN1_CALL(pos, rose_enc_qsig_Name(ctrl, pos, end,
++ &call_transfer_update->redirection_name));
++ }
++
++ if (call_transfer_update->q931ie.length) {
++ ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
++ &call_transfer_update->q931ie));
++ }
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG SubaddressTransfer invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ unsigned char *seq_len;
++ const struct roseQsigSubaddressTransferArg_ARG *subaddress_transfer;
++
++ subaddress_transfer = &args->qsig.SubaddressTransfer;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
++ &subaddress_transfer->redirection_subaddress));
++
++ /* No extension to encode */
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG DummyArg invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ *
++ * \details
++ * DummyArg ::= CHOICE {
++ * none NULL,
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * }
++ */
++unsigned char *rose_enc_qsig_DummyArg_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return asn1_enc_null(pos, end, ASN1_TYPE_NULL);
++}
++
++/*!
++ * \brief Encode the Q.SIG DummyRes result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ *
++ * \details
++ * DummyRes ::= CHOICE {
++ * none NULL,
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * }
++ */
++unsigned char *rose_enc_qsig_DummyRes_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args)
++{
++ return asn1_enc_null(pos, end, ASN1_TYPE_NULL);
++}
++
++/*!
++ * \brief Decode the Q.SIG CallTransferIdentify result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CallTransferIdentify_RES(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_result_args *args)
++{
++ size_t str_len;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigCTIdentifyRes_RES *call_transfer_identify;
++
++ call_transfer_identify = &args->qsig.CallTransferIdentify;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallTransferIdentify %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
++ sizeof(call_transfer_identify->call_id), call_transfer_identify->call_id,
++ &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "reroutingNumber", tag, pos, seq_end,
++ &call_transfer_identify->rerouting_number));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG CallTransferInitiate invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CallTransferInitiate_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ size_t str_len;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigCTInitiateArg_ARG *call_transfer_initiate;
++
++ call_transfer_initiate = &args->qsig.CallTransferInitiate;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallTransferInitiate %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
++ sizeof(call_transfer_initiate->call_id), call_transfer_initiate->call_id,
++ &str_len));
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "reroutingNumber", tag, pos, seq_end,
++ &call_transfer_initiate->rerouting_number));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG CallTransferSetup invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CallTransferSetup_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ size_t str_len;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigCTSetupArg_ARG *call_transfer_setup;
++
++ call_transfer_setup = &args->qsig.CallTransferSetup;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallTransferSetup %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_NUMERIC_STRING);
++ ASN1_CALL(pos, asn1_dec_string_max(ctrl, "callIdentity", tag, pos, seq_end,
++ sizeof(call_transfer_setup->call_id), call_transfer_setup->call_id, &str_len));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG CallTransferActive invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CallTransferActive_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigCTActiveArg_ARG *call_transfer_active;
++
++ call_transfer_active = &args->qsig.CallTransferActive;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallTransferActive %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedAddressScreened(ctrl, "connectedAddress", tag, pos,
++ seq_end, &call_transfer_active->connected));
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ call_transfer_active->q931ie.length = 0;
++ call_transfer_active->connected_name_present = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_APPLICATION | 0:
++ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
++ seq_end, &call_transfer_active->q931ie,
++ sizeof(call_transfer_active->q931ie_contents)));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "connectedName", tag, pos, seq_end,
++ &call_transfer_active->connected_name));
++ call_transfer_active->connected_name_present = 1;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG CallTransferComplete invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CallTransferComplete_ARG(struct pri *ctrl,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ union rose_msg_invoke_args *args)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigCTCompleteArg_ARG *call_transfer_complete;
++
++ call_transfer_complete = &args->qsig.CallTransferComplete;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallTransferComplete %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "endDesignation", tag, pos, seq_end, &value));
++ call_transfer_complete->end_designation = value;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberScreened(ctrl, "redirectionNumber", tag, pos,
++ seq_end, &call_transfer_complete->redirection));
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ call_transfer_complete->q931ie.length = 0;
++ call_transfer_complete->redirection_name_present = 0;
++ call_transfer_complete->call_status = 0; /* DEFAULT answered */
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_APPLICATION | 0:
++ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
++ seq_end, &call_transfer_complete->q931ie,
++ sizeof(call_transfer_complete->q931ie_contents)));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectionName", tag, pos, seq_end,
++ &call_transfer_complete->redirection_name));
++ call_transfer_complete->redirection_name_present = 1;
++ break;
++ case ASN1_TYPE_ENUMERATED:
++ /* Must not be constructed but we will not check for it for simplicity. */
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "callStatus", tag, pos, seq_end, &value));
++ call_transfer_complete->call_status = value;
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG CallTransferUpdate invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CallTransferUpdate_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ const unsigned char *save_pos;
++ struct roseQsigCTUpdateArg_ARG *call_transfer_update;
++
++ call_transfer_update = &args->qsig.CallTransferUpdate;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " CallTransferUpdate %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberScreened(ctrl, "redirectionNumber", tag, pos,
++ seq_end, &call_transfer_update->redirection));
++
++ /*
++ * A sequence specifies an ordered list of component types.
++ * However, for simplicity we are not checking the order of
++ * the remaining optional components.
++ */
++ call_transfer_update->redirection_name_present = 0;
++ call_transfer_update->q931ie.length = 0;
++ while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ save_pos = pos;
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "redirectionName", tag, pos, seq_end,
++ &call_transfer_update->redirection_name));
++ call_transfer_update->redirection_name_present = 1;
++ break;
++ case ASN1_CLASS_APPLICATION | 0:
++ ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "basicCallInfoElements", tag, pos,
++ seq_end, &call_transfer_update->q931ie,
++ sizeof(call_transfer_update->q931ie_contents)));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 9:
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 10:
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " argumentExtension %s\n", asn1_tag2str(tag));
++ }
++ /* Fixup will skip over the manufacturer extension information */
++ default:
++ pos = save_pos;
++ goto cancel_options;
++ }
++ }
++cancel_options:;
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG SubaddressTransfer invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ struct roseQsigSubaddressTransferArg_ARG *subaddress_transfer;
++
++ subaddress_transfer = &args->qsig.SubaddressTransfer;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " SubaddressTransfer %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "redirectionSubaddress", tag, pos,
++ seq_end, &subaddress_transfer->redirection_subaddress));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG DummyArg invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ *
++ * \details
++ * DummyArg ::= CHOICE {
++ * none NULL,
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * }
++ */
++const unsigned char *rose_dec_qsig_DummyArg_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ const char *name;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ return asn1_dec_null(ctrl, "none", tag, pos, end);
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ name = "extension Extension";
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ name = "multipleExtension SEQUENCE OF Extension";
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ /* Fixup will skip over the manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG DummyRes result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ *
++ * \details
++ * DummyRes ::= CHOICE {
++ * none NULL,
++ * extension [1] IMPLICIT Extension,
++ * multipleExtension [2] IMPLICIT SEQUENCE OF Extension
++ * }
++ */
++const unsigned char *rose_dec_qsig_DummyRes_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
++{
++ const char *name;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ switch (tag) {
++ case ASN1_TYPE_NULL:
++ return asn1_dec_null(ctrl, "none", tag, pos, end);
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
++ name = "extension Extension";
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
++ name = "multipleExtension SEQUENCE OF Extension";
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ /* Fixup will skip over the manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_qsig_ct.c */
+
+Property changes on: rose_qsig_ct.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_q931.c
+===================================================================
+--- a/rose_q931.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_q931.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,100 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ROSE Q.931 ie encode/decode functions
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \brief Encode the Q.931 ie value.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_CLASS_APPLICATION | 0 unless the caller
++ * implicitly tags it otherwise.
++ * \param q931ie Q931 ie information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_Q931ie(struct pri *ctrl, unsigned char *pos, unsigned char *end,
++ unsigned tag, const struct roseQ931ie *q931ie)
++{
++ return asn1_enc_string_bin(pos, end, tag, q931ie->contents, q931ie->length);
++}
++
++/*!
++ * \brief Decode the Q.931 ie value.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param q931ie Parameter storage to fill.
++ * \param contents_size Amount of space "allocated" for the q931ie->contents
++ * element. Must have enough room for a null terminator.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_Q931ie(struct pri *ctrl, const char *name, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, struct roseQ931ie *q931ie,
++ size_t contents_size)
++{
++ size_t str_len;
++
++ /* NOTE: The q931ie->contents memory is "allocated" after the struct. */
++ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, name, tag, pos, end, contents_size,
++ q931ie->contents, &str_len));
++ q931ie->length = str_len;
++
++ /*
++ * NOTE: We may want to do some basic decoding of the Q.931 ie list
++ * for debug purposes.
++ */
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_q931.c */
+
+Property changes on: rose_q931.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: rose_etsi_ect.c
+===================================================================
+--- a/rose_etsi_ect.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_etsi_ect.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,332 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief ROSE Explicit Call Transfer operations.
++ *
++ * Explicit Call Transfer (ECT) Supplementary Services ETS 300 369-1
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \brief Encode the ExplicitEctExecute invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ args->etsi.ExplicitEctExecute.link_id);
++}
++
++/*!
++ * \brief Encode the SubaddressTransfer invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return rose_enc_PartySubaddress(ctrl, pos, end,
++ &args->etsi.SubaddressTransfer.subaddress);
++}
++
++/*!
++ * \brief Encode the EctLinkIdRequest result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args)
++{
++ return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ args->etsi.EctLinkIdRequest.link_id);
++}
++
++/*!
++ * \brief Encode the EctInform invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_EctInform_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ const struct roseEtsiEctInform_ARG *ect_inform;
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
++
++ ect_inform = &args->etsi.EctInform;
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, ect_inform->status));
++ if (ect_inform->redirection_present) {
++ ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
++ &ect_inform->redirection));
++ }
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the EctLoopTest invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
++ args->etsi.EctLoopTest.call_transfer_id);
++}
++
++/*!
++ * \brief Encode the EctLoopTest result facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_result_args *args)
++{
++ return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
++ args->etsi.EctLoopTest.loop_result);
++}
++
++/*!
++ * \brief Decode the ExplicitEctExecute invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_ExplicitEctExecute_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "linkId", tag, pos, end, &value));
++ args->etsi.ExplicitEctExecute.link_id = value;
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the SubaddressTransfer invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_SubaddressTransfer_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ return rose_dec_PartySubaddress(ctrl, "transferredToSubaddress", tag, pos, end,
++ &args->etsi.SubaddressTransfer.subaddress);
++}
++
++/*!
++ * \brief Decode the EctLinkIdRequest result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_EctLinkIdRequest_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
++{
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "linkId", tag, pos, end, &value));
++ args->etsi.EctLinkIdRequest.link_id = value;
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the EctInform invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_EctInform_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ struct roseEtsiEctInform_ARG *ect_inform;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++ int32_t value;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " EctInform %s\n", asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ect_inform = &args->etsi.EctInform;
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "callStatus", tag, pos, seq_end, &value));
++ ect_inform->status = value;
++
++ if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "redirectionNumber", tag,
++ pos, seq_end, &ect_inform->redirection));
++ ect_inform->redirection_present = 1;
++ } else {
++ ect_inform->redirection_present = 0;
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the EctLoopTest invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_EctLoopTest_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "callTransferId", tag, pos, end, &value));
++ args->etsi.EctLoopTest.call_transfer_id = value;
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the EctLoopTest result argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
++{
++ int32_t value;
++
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "loopResult", tag, pos, end, &value));
++ args->etsi.EctLoopTest.loop_result = value;
++
++ return pos;
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_etsi_ect.c */
+
+Property changes on: rose_etsi_ect.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: pri_internal.h
+===================================================================
+--- a/pri_internal.h (.../tags/1.4.10.2) (revision 1357)
++++ b/pri_internal.h (.../branches/1.4) (revision 1357)
+@@ -32,30 +32,45 @@
+
+ #include <stddef.h>
+ #include <sys/time.h>
++#include "pri_q921.h"
++#include "pri_q931.h"
+
++#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
++
+ #define DBGHEAD __FILE__ ":%d %s: "
+ #define DBGINFO __LINE__,__PRETTY_FUNCTION__
+
++/* Forward declare some structs */
++struct apdu_event;
++
+ struct pri_sched {
+ struct timeval when;
+ void (*callback)(void *data);
+ void *data;
+ };
+
+-struct q921_frame;
+-enum q931_state;
+-enum q931_mode;
+-
+-/* No more than 128 scheduled events */
++/*! Maximum number of scheduled events active at the same time. */
+ #define MAX_SCHED 128
+
+-#define MAX_TIMERS 32
++/*! Maximum number of facility ie's to handle per incoming message. */
++#define MAX_FACILITY_IES 8
+
++/*! Accumulated pri_message() line until a '\n' is seen on the end. */
++struct pri_msg_line {
++ /*! Accumulated buffer used. */
++ unsigned length;
++ /*! Accumulated pri_message() contents. */
++ char str[2048];
++};
++
++/*! \brief D channel controller structure */
+ struct pri {
+ int fd; /* File descriptor for D-Channel */
+ pri_io_cb read_func; /* Read data callback */
+ pri_io_cb write_func; /* Write data callback */
+ void *userdata;
++ /*! Accumulated pri_message() line. (Valid in master record only) */
++ struct pri_msg_line *msg_line;
+ struct pri *subchannel; /* Sub-channel if appropriate */
+ struct pri *master; /* Master channel if appropriate */
+ struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */
+@@ -71,7 +86,9 @@
+ int protodisc;
+ unsigned int bri:1;
+ unsigned int acceptinbanddisconnect:1; /* Should we allow inband progress after DISCONNECT? */
+-
++ unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */
++ unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */
++
+ /* Q.921 State */
+ int q921_state;
+ int window; /* Max window size */
+@@ -97,12 +114,14 @@
+ int ri;
+ int t200_timer; /* T-200 retransmission timer */
+ /* All ISDN Timer values */
+- int timers[MAX_TIMERS];
++ int timers[PRI_MAX_TIMERS];
+
+ /* Used by scheduler */
+ struct timeval tv;
+ int schedev;
+ pri_event ev; /* Static event thingy */
++ /*! Subcommands for static event thingy. */
++ struct pri_subcommands subcmds;
+
+ /* Q.921 Re-transmission queue */
+ struct q921_frame *txqueue;
+@@ -111,9 +130,19 @@
+ q931_call **callpool;
+ q931_call *localpool;
+
++ /*!
++ * \brief Q.931 Dummy call reference call associated with this TEI.
++ * \note If present then this call is allocated as part of the
++ * D channel control structure.
++ */
++ q931_call *dummy_call;
++
+ /* do we do overlap dialing */
+ int overlapdial;
+
++ /* do we support SERVICE messages */
++ int service_message_support;
++
+ /* do not skip channel 16 */
+ int chan_mapping_logical;
+
+@@ -125,52 +154,227 @@
+ unsigned int q931_rxcount;
+ #endif
+
+- unsigned char last_invoke; /* Last ROSE invoke ID */
++ short last_invoke; /* Last ROSE invoke ID (Valid in master record only) */
+ unsigned char sendfacility;
++
++ /*! For delayed processing of facility ie's. */
++ struct {
++ /*! Array of facility ie locations in the current received message. */
++ q931_ie *ie[MAX_FACILITY_IES];
++ /*! Codeset facility ie found within. */
++ unsigned char codeset[MAX_FACILITY_IES];
++ /*! Number of facility ie's in the array from the current received message. */
++ unsigned char count;
++ } facility;
+ };
+
++/*! \brief Maximum name length plus null terminator (From ECMA-164) */
++#define PRI_MAX_NAME_LEN (50 + 1)
++
++/*! \brief Q.SIG name information. */
++struct q931_party_name {
++ /*! \brief TRUE if name data is valid */
++ unsigned char valid;
++ /*!
++ * \brief Q.931 presentation-indicator encoded field
++ * \note Must tollerate the Q.931 screening-indicator field values being present.
++ */
++ unsigned char presentation;
++ /*!
++ * \brief Character set the name is using.
++ * \details
++ * unknown(0),
++ * iso8859-1(1),
++ * enum-value-withdrawn-by-ITU-T(2)
++ * iso8859-2(3),
++ * iso8859-3(4),
++ * iso8859-4(5),
++ * iso8859-5(6),
++ * iso8859-7(7),
++ * iso10646-BmpString(8),
++ * iso10646-utf-8String(9)
++ */
++ unsigned char char_set;
++ /*! \brief Name data with null terminator. */
++ char str[PRI_MAX_NAME_LEN];
++};
++
++/*! \brief Maximum phone number (address) length plus null terminator */
++#define PRI_MAX_NUMBER_LEN (31 + 1)
++
++struct q931_party_number {
++ /*! \brief TRUE if number data is valid */
++ unsigned char valid;
++ /*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
++ unsigned char presentation;
++ /*! \brief Q.931 Type-Of-Number and numbering-plan encoded fields */
++ unsigned char plan;
++ /*! \brief Number data with terminator. */
++ char str[PRI_MAX_NUMBER_LEN];
++};
++
++/*! \brief Maximum subaddress length plus null terminator */
++#define PRI_MAX_SUBADDRESS_LEN (20 + 1)
++
++struct q931_party_subaddress {
++ /*! \brief TRUE if the subaddress information is valid/present */
++ unsigned char valid;
++ /*!
++ * \brief Subaddress type.
++ * \details
++ * nsap(0),
++ * user_specified(2)
++ */
++ unsigned char type;
++ /*!
++ * \brief TRUE if odd number of address signals
++ * \note The odd/even indicator is used when the type of subaddress is
++ * user_specified and the coding is BCD.
++ */
++ unsigned char odd_even_indicator;
++ /*! \brief Length of the subaddress data */
++ unsigned char length;
++ /*!
++ * \brief Subaddress data with null terminator.
++ * \note The null terminator is a convenience only since the data could be
++ * BCD/binary and thus have a null byte as part of the contents.
++ */
++ unsigned char data[PRI_MAX_SUBADDRESS_LEN];
++};
++
++struct q931_party_address {
++ /*! \brief Subscriber phone number */
++ struct q931_party_number number;
++ /*! \brief Subscriber subaddress */
++ struct q931_party_subaddress subaddress;
++};
++
++/*! \brief Information needed to identify an endpoint in a call. */
++struct q931_party_id {
++ /*! \brief Subscriber name */
++ struct q931_party_name name;
++ /*! \brief Subscriber phone number */
++ struct q931_party_number number;
++ /*! \brief Subscriber subaddress */
++ struct q931_party_subaddress subaddress;
++};
++
++enum Q931_REDIRECTING_STATE {
++ /*!
++ * \details
++ * CDO-Idle/CDF-Inv-Idle
++ */
++ Q931_REDIRECTING_STATE_IDLE,
++ /*!
++ * \details
++ * CDF-Inv-Wait - A DivLeg2 has been received and
++ * we are waiting for valid presentation restriction information to send.
++ */
++ Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3,
++ /*!
++ * \details
++ * CDO-Divert - A DivLeg1 has been received and
++ * we are waiting for the presentation restriction information to come in.
++ */
++ Q931_REDIRECTING_STATE_EXPECTING_RX_DIV_LEG_3,
++};
++
++/*!
++ * \brief Do not increment above this count.
++ * \details
++ * It is not our responsibility to enforce the maximum number of redirects.
++ * However, we cannot allow an increment past this number without breaking things.
++ * Besides, more than 255 redirects is probably not a good thing.
++ */
++#define PRI_MAX_REDIRECTS 0xFF
++
++/*! \brief Redirecting information struct */
++struct q931_party_redirecting {
++ enum Q931_REDIRECTING_STATE state;
++ /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
++ struct q931_party_id from;
++ /*! \brief Call is redirecting to a new party (Sent to the caller) */
++ struct q931_party_id to;
++ /*! Originally called party (in cases of multiple redirects) */
++ struct q931_party_id orig_called;
++ /*!
++ * \brief Number of times the call was redirected
++ * \note The call is being redirected if the count is non-zero.
++ */
++ unsigned char count;
++ /*! Original reason for redirect (in cases of multiple redirects) */
++ unsigned char orig_reason;
++ /*! \brief Redirection reasons */
++ unsigned char reason;
++};
++
++/*! \brief New call setup parameter structure */
+ struct pri_sr {
+ int transmode;
+ int channel;
+ int exclusive;
+ int nonisdn;
+- char *caller;
+- int callerplan;
+- char *callername;
+- int callerpres;
+- char *called;
+- int calledplan;
++ struct q931_party_redirecting redirecting;
++ struct q931_party_id caller;
++ struct q931_party_address called;
+ int userl1;
+ int numcomplete;
+- char *redirectingnum;
+- int redirectingplan;
+- int redirectingpres;
+- int redirectingreason;
+- int justsignalling;
++ int cis_call;
++ int cis_auto_disconnect;
+ const char *useruserinfo;
++ const char *keypad_digits;
+ int transferable;
++ int reversecharge;
+ };
+
+ /* Internal switch types */
+ #define PRI_SWITCH_GR303_EOC_PATH 19
+ #define PRI_SWITCH_GR303_TMC_SWITCHING 20
+
+-struct apdu_event {
+- int message; /* What message to send the ADPU in */
+- void (*callback)(void *data); /* Callback function for when response is received */
+- void *data; /* Data to callback */
+- unsigned char apdu[255]; /* ADPU to send */
+- int apdu_len; /* Length of ADPU */
+- int sent; /* Have we been sent already? */
+- struct apdu_event *next; /* Linked list pointer */
++#define Q931_MAX_TEI 8
++
++/*! \brief Incoming call transfer states. */
++enum INCOMING_CT_STATE {
++ /*!
++ * \details
++ * Incoming call transfer is not active.
++ */
++ INCOMING_CT_STATE_IDLE,
++ /*!
++ * \details
++ * We have seen an incoming CallTransferComplete(alerting)
++ * so we are waiting for the expected CallTransferActive
++ * before updating the connected line about the remote party id.
++ */
++ INCOMING_CT_STATE_EXPECT_CT_ACTIVE,
++ /*!
++ * \details
++ * A call transfer message came in that updated the remote party id
++ * that we need to post a connected line update.
++ */
++ INCOMING_CT_STATE_POST_CONNECTED_LINE
+ };
+
++/*! Call hold supplementary states. */
++enum Q931_HOLD_STATE {
++ /*! \brief No call hold activity. */
++ Q931_HOLD_STATE_IDLE,
++ /*! \brief Request made to hold call. */
++ Q931_HOLD_STATE_HOLD_REQ,
++ /*! \brief Request received to hold call. */
++ Q931_HOLD_STATE_HOLD_IND,
++ /*! \brief Call is held. */
++ Q931_HOLD_STATE_CALL_HELD,
++ /*! \brief Request made to retrieve call. */
++ Q931_HOLD_STATE_RETRIEVE_REQ,
++ /*! \brief Request received to retrieve call. */
++ Q931_HOLD_STATE_RETRIEVE_IND,
++};
++
+ /* q931_call datastructure */
+-
+ struct q931_call {
+ struct pri *pri; /* PRI */
+ int cr; /* Call Reference */
+- int forceinvert; /* Force inversion of call number even if 0 */
+ q931_call *next;
+ /* Slotmap specified (bitmap of channels 31/24-1) (Channel Identifier IE) (-1 means not specified) */
+ int slotmap;
+@@ -199,73 +403,144 @@
+ int userl2;
+ int userl3;
+ int rateadaption;
+-
+- int sentchannel;
+- int justsignalling; /* for a signalling-only connection */
+
++ /*!
++ * \brief TRUE if the call is a Call Independent Signalling connection.
++ * \note The call has no B channel associated with it. (Just signalling)
++ */
++ int cis_call;
++ /*! \brief TRUE if we will auto disconnect the cis_call we originated. */
++ int cis_auto_disconnect;
++
+ int progcode; /* Progress coding */
+ int progloc; /* Progress Location */
+ int progress; /* Progress indicator */
+ int progressmask; /* Progress Indicator bitmask */
+
+- int notify; /* Notification */
++ int notify; /* Notification indicator. */
+
+ int causecode; /* Cause Coding */
+ int causeloc; /* Cause Location */
+ int cause; /* Cause of clearing */
+
+- int peercallstate; /* Call state of peer as reported */
+- int ourcallstate; /* Our call state */
+- int sugcallstate; /* Status call state */
+-
+- int callerplan;
+- int callerplanani;
+- int callerpres; /* Caller presentation */
+- char callerani[256]; /* Caller */
+- char callernum[256];
+- char callername[256];
++ enum Q931_CALL_STATE peercallstate; /* Call state of peer as reported */
++ enum Q931_CALL_STATE ourcallstate; /* Our call state */
++ enum Q931_CALL_STATE sugcallstate; /* Status call state */
+
+- char keypad_digits[64]; /* Buffer for digits that come in KEYPAD_FACILITY */
++ int ani2; /* ANI II */
+
+- int ani2; /* ANI II */
+-
+- int calledplan;
++ /*! Buffer for digits that come in KEYPAD_FACILITY */
++ char keypad_digits[32 + 1];
++
++ /*! Current dialed digits to be sent or just received. */
++ char overlap_digits[PRI_MAX_NUMBER_LEN];
++
++ /*!
++ * \brief Local party ID
++ * \details
++ * The Caller-ID and connected-line ID are just roles the local and remote party
++ * play while a call is being established. Which roll depends upon the direction
++ * of the call.
++ * Outgoing party info is to identify the local party to the other end.
++ * (Caller-ID for originated or connected-line for answered calls.)
++ * Incoming party info is to identify the remote party to us.
++ * (Caller-ID for answered or connected-line for originated calls.)
++ */
++ struct q931_party_id local_id;
++ /*!
++ * \brief Remote party ID
++ * \details
++ * The Caller-ID and connected-line ID are just roles the local and remote party
++ * play while a call is being established. Which roll depends upon the direction
++ * of the call.
++ * Outgoing party info is to identify the local party to the other end.
++ * (Caller-ID for originated or connected-line for answered calls.)
++ * Incoming party info is to identify the remote party to us.
++ * (Caller-ID for answered or connected-line for originated calls.)
++ */
++ struct q931_party_id remote_id;
++
++ /*!
++ * \brief Staging place for the Q.931 redirection number ie.
++ * \note
++ * The number could be the remote_id.number or redirecting.to.number
++ * depending upon the notification indicator.
++ */
++ struct q931_party_number redirection_number;
++
++ /*!
++ * \brief Called party address.
++ * \note The called.number.str is the accumulated overlap dial digits
++ * and enbloc digits.
++ * \note The called.number.presentation value is not used.
++ */
++ struct q931_party_address called;
+ int nonisdn;
+- char callednum[256]; /* Called Number */
+ int complete; /* no more digits coming */
+ int newcall; /* if the received message has a new call reference value */
+
+ int retranstimer; /* Timer for retransmitting DISC */
+ int t308_timedout; /* Whether t308 timed out once */
+
+- int redirectingplan;
+- int redirectingpres;
+- int redirectingreason;
+- char redirectingnum[256]; /* Number of redirecting party */
+- char redirectingname[256]; /* Name of redirecting party */
++ struct q931_party_redirecting redirecting;
+
+- /* Filled in cases of multiple diversions */
+- int origcalledplan;
+- int origcalledpres;
+- int origredirectingreason; /* Original reason for redirect (in cases of multiple redirects) */
+- char origcalledname[256]; /* Original name of person being called */
+- char origcallednum[256]; /* Orignal number of person being called */
++ /*! \brief Incoming call transfer state. */
++ enum INCOMING_CT_STATE incoming_ct_state;
++ /*! Call hold supplementary state. */
++ enum Q931_HOLD_STATE hold_state;
++ /*! Call hold event timer */
++ int hold_timer;
+
++ int deflection_in_progress; /*!< CallDeflection for NT PTMP in progress. */
++ /*! TRUE if the connected number ie was in the current received message. */
++ int connected_number_in_message;
++ /*! TRUE if the redirecting number ie was in the current received message. */
++ int redirecting_number_in_message;
++
+ int useruserprotocoldisc;
+ char useruserinfo[256];
+- char callingsubaddr[256]; /* Calling parties sub address */
+
+ long aoc_units; /* Advice of Charge Units */
+
+ struct apdu_event *apdus; /* APDU queue for call */
+
+- int transferable;
++ int transferable; /* RLT call is transferable */
+ unsigned int rlt_call_id; /* RLT call id */
+
+ /* Bridged call info */
+- q931_call *bridged_call; /* Pointer to other leg of bridged call */
++ q931_call *bridged_call; /* Pointer to other leg of bridged call (Used by Q.SIG when eliminating tromboned calls) */
++
++ int changestatus; /* SERVICE message changestatus */
++ int reversecharge; /* Reverse charging indication:
++ -1 - No reverse charging
++ 1 - Reverse charging
++ 0,2-7 - Reserved for future use */
++ int t303_timer;
++ int t303_expirycnt;
++
++ int hangupinitiated;
++ /*! \brief TRUE if we broadcast this call's SETUP message. */
++ int outboundbroadcast;
++ int performing_fake_clearing;
++ /*!
++ * \brief Master call controlling this call.
++ * \note Always valid. Master and normal calls point to self.
++ */
++ struct q931_call *master_call;
++
++ /* These valid in master call only */
++ struct q931_call *subcalls[Q931_MAX_TEI];
++ int pri_winner;
+ };
+
++/*! D channel control structure with associated dummy call reference record. */
++struct d_ctrl_dummy {
++ /*! D channel control structure. Must be first in the structure. */
++ struct pri ctrl;
++ /*! Dummy call reference call record. */
++ struct q931_call dummy_call;
++};
++
+ extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
+
+ extern pri_event *pri_schedule_run(struct pri *pri);
+@@ -274,14 +549,104 @@
+
+ extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
+
+-extern void pri_message(struct pri *pri, char *fmt, ...);
++void pri_message(struct pri *ctrl, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
++void pri_error(struct pri *ctrl, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+
+-extern void pri_error(struct pri *pri, char *fmt, ...);
+-
+ void libpri_copy_string(char *dst, const char *src, size_t size);
+
+ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri);
+
+ void __pri_free_tei(struct pri *p);
+
++void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr);
++
++void q931_party_name_init(struct q931_party_name *name);
++void q931_party_number_init(struct q931_party_number *number);
++void q931_party_subaddress_init(struct q931_party_subaddress *subaddr);
++void q931_party_address_init(struct q931_party_address *address);
++void q931_party_id_init(struct q931_party_id *id);
++void q931_party_redirecting_init(struct q931_party_redirecting *redirecting);
++
++static inline void q931_party_address_to_id(struct q931_party_id *id, struct q931_party_address *address)
++{
++ id->number = address->number;
++ id->subaddress = address->subaddress;
++}
++
++int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right);
++int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right);
++int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right);
++int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right);
++
++void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name);
++void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number);
++void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress);
++void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id);
++void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting);
++
++void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id);
++int q931_party_id_presentation(const struct q931_party_id *id);
++
++const char *q931_call_state_str(enum Q931_CALL_STATE callstate);
++const char *msg2str(int msg);
++
++int q931_is_ptmp(const struct pri *ctrl);
++int q931_master_pass_event(struct pri *ctrl, struct q931_call *subcall, int msg_type);
++struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl);
++
++int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
++
++static inline struct pri * PRI_MASTER(struct pri *mypri)
++{
++ struct pri *pri = mypri;
++
++ if (!pri)
++ return NULL;
++
++ while (pri->master)
++ pri = pri->master;
++
++ return pri;
++}
++
++static inline int BRI_NT_PTMP(struct pri *mypri)
++{
++ struct pri *pri;
++
++ pri = PRI_MASTER(mypri);
++
++ return pri->bri && (((pri)->localtype == PRI_NETWORK) && ((pri)->tei == Q921_TEI_GROUP));
++}
++
++static inline int BRI_TE_PTMP(struct pri *mypri)
++{
++ struct pri *pri;
++
++ pri = PRI_MASTER(mypri);
++
++ return pri->bri && (((pri)->localtype == PRI_CPE) && ((pri)->tei == Q921_TEI_GROUP));
++}
++
++static inline int PRI_PTP(struct pri *mypri)
++{
++ struct pri *pri;
++
++ pri = PRI_MASTER(mypri);
++
++ return !pri->bri;
++}
++
++#define Q931_DUMMY_CALL_REFERENCE -1
++
++/*!
++ * \brief Deterimine if the given call control pointer is a dummy call.
++ *
++ * \retval TRUE if given call is a dummy call.
++ * \retval FALSE otherwise.
++ */
++static inline int q931_is_dummy_call(const q931_call *call)
++{
++ return (call->cr == Q931_DUMMY_CALL_REFERENCE) ? 1 : 0;
++}
++
+ #endif
+Index: rose_qsig_name.c
+===================================================================
+--- a/rose_qsig_name.c (.../tags/1.4.10.2) (revision 0)
++++ b/rose_qsig_name.c (.../branches/1.4) (revision 1357)
+@@ -0,0 +1,474 @@
++/*
++ * libpri: An implementation of Primary Rate ISDN
++ *
++ * Copyright (C) 2009 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2 as published by the
++ * Free Software Foundation. See the LICENSE file included with
++ * this program for more details.
++ *
++ * In addition, when this program is distributed with Asterisk in
++ * any form that would qualify as a 'combined work' or as a
++ * 'derivative work' (but not mere aggregation), you can redistribute
++ * and/or modify the combination under the terms of the license
++ * provided with that copy of Asterisk, instead of the license
++ * terms granted here.
++ */
++
++/*!
++ * \file
++ * \brief Q.SIG ROSE Name operations and elements
++ *
++ * Name-Operations ECMA-164 Annex C
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ */
++
++
++#include "compat.h"
++#include "libpri.h"
++#include "pri_internal.h"
++#include "rose.h"
++#include "rose_internal.h"
++#include "asn1.h"
++
++
++/* ------------------------------------------------------------------- */
++
++/*!
++ * \internal
++ * \brief Encode the Q.SIG NameSet type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param tag Component tag to identify the encoded component.
++ * The tag should be ASN1_TAG_SEQUENCE unless the caller
++ * implicitly tags it otherwise.
++ * \param name
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_NameSet(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, unsigned tag, const struct roseQsigName *name)
++{
++ unsigned char *seq_len;
++
++ ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
++
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_TYPE_OCTET_STRING, name->data,
++ name->length));
++ ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, name->char_set));
++
++ ASN1_CONSTRUCTED_END(seq_len, pos, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Encode the Q.SIG Name type.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param name
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const struct roseQsigName *name)
++{
++ switch (name->presentation) {
++ case 0: /* optional_name_not_present */
++ /* Do not encode anything */
++ break;
++ case 1: /* presentation_allowed */
++ if (name->char_set == 1) {
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
++ name->data, name->length));
++ } else {
++ ASN1_CALL(pos, rose_enc_qsig_NameSet(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 1, name));
++ }
++ break;
++ case 2: /* presentation_restricted */
++ if (name->char_set == 1) {
++ ASN1_CALL(pos, asn1_enc_string_bin(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
++ name->data, name->length));
++ } else {
++ ASN1_CALL(pos, rose_enc_qsig_NameSet(ctrl, pos, end,
++ ASN1_CLASS_CONTEXT_SPECIFIC | 3, name));
++ }
++ break;
++ case 3: /* presentation_restricted_null */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 7));
++ break;
++ case 4: /* name_not_available */
++ ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
++ break;
++ default:
++ ASN1_ENC_ERROR(ctrl, "Unknown name presentation");
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Encode the Q.SIG party-Name invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param party Information to encode.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++static unsigned char *rose_enc_qsig_PartyName_ARG_Backend(struct pri *ctrl,
++ unsigned char *pos, unsigned char *end, const struct roseQsigPartyName_ARG *party)
++{
++ return rose_enc_qsig_Name(ctrl, pos, end, &party->name);
++}
++
++/*!
++ * \brief Encode the Q.SIG CallingName invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CallingName_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.CallingName);
++}
++
++/*!
++ * \brief Encode the Q.SIG CalledName invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_CalledName_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.CalledName);
++}
++
++/*!
++ * \brief Encode the Q.SIG ConnectedName invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end,
++ &args->qsig.ConnectedName);
++}
++
++/*!
++ * \brief Encode the Q.SIG BusyName invoke facility ie arguments.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param pos Starting position to encode ASN.1 component.
++ * \param end End of ASN.1 encoding data buffer.
++ * \param args Arguments to encode in the buffer.
++ *
++ * \retval Start of the next ASN.1 component to encode on success.
++ * \retval NULL on error.
++ */
++unsigned char *rose_enc_qsig_BusyName_ARG(struct pri *ctrl, unsigned char *pos,
++ unsigned char *end, const union rose_msg_invoke_args *args)
++{
++ return rose_enc_qsig_PartyName_ARG_Backend(ctrl, pos, end, &args->qsig.BusyName);
++}
++
++/*!
++ * \internal
++ * \brief Decode the Q.SIG NameData Name argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param fname Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param name Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_NameData(struct pri *ctrl, const char *fname,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigName *name)
++{
++ size_t str_len;
++
++ ASN1_CALL(pos, asn1_dec_string_bin(ctrl, fname, tag, pos, end, sizeof(name->data),
++ name->data, &str_len));
++ name->length = str_len;
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the Q.SIG NameSet Name argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param fname Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param name Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_NameSet(struct pri *ctrl, const char *fname,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigName *name)
++{
++ int32_t value;
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s NameSet %s\n", fname, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_TYPE_OCTET_STRING);
++ ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "nameData", tag, pos, seq_end, name));
++
++ if (pos < end && *pos != ASN1_INDEF_TERM) {
++ ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
++ ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
++ ASN1_CALL(pos, asn1_dec_int(ctrl, "characterSet", tag, pos, seq_end, &value));
++ name->char_set = value;
++ } else {
++ name->char_set = 1; /* default to iso8859-1 */
++ }
++
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG Name argument parameters.
++ *
++ * \param ctrl D channel controller for any diagnostic messages.
++ * \param fname Field name
++ * \param tag Component tag that identified this production.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param name Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_Name(struct pri *ctrl, const char *fname,
++ unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigName *name)
++{
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s Name\n", fname);
++ }
++ name->char_set = 1; /* default to iso8859-1 */
++ switch (tag & ~ASN1_PC_MASK) {
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
++ name->presentation = 1; /* presentation_allowed */
++ ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "namePresentationAllowedSimple", tag,
++ pos, end, name));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
++ /* Must be constructed but we will not check for it for simplicity. */
++ name->presentation = 1; /* presentation_allowed */
++ ASN1_CALL(pos, rose_dec_qsig_NameSet(ctrl, "namePresentationAllowedExtended",
++ tag, pos, end, name));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 2:
++ name->presentation = 2; /* presentation_restricted */
++ ASN1_CALL(pos, rose_dec_qsig_NameData(ctrl, "namePresentationRestrictedSimple",
++ tag, pos, end, name));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 3:
++ /* Must be constructed but we will not check for it for simplicity. */
++ name->presentation = 2; /* presentation_restricted */
++ ASN1_CALL(pos, rose_dec_qsig_NameSet(ctrl, "namePresentationRestrictedExtended",
++ tag, pos, end, name));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
++ /* Must not be constructed but we will not check for it for simplicity. */
++ name->presentation = 4; /* name_not_available */
++ name->length = 0;
++ name->data[0] = 0;
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "nameNotAvailable", tag, pos, end));
++ break;
++ case ASN1_CLASS_CONTEXT_SPECIFIC | 7:
++ /* Must not be constructed but we will not check for it for simplicity. */
++ name->presentation = 3; /* presentation_restricted_null */
++ name->length = 0;
++ name->data[0] = 0;
++ ASN1_CALL(pos, asn1_dec_null(ctrl, "namePresentationRestrictedNull", tag, pos,
++ end));
++ break;
++ default:
++ ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
++ return NULL;
++ }
++
++ return pos;
++}
++
++/*!
++ * \internal
++ * \brief Decode the Q.SIG party-Name invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param name Field name
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param party Parameter storage to fill.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++static const unsigned char *rose_dec_qsig_PartyName_ARG_Backend(struct pri *ctrl,
++ const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
++ struct roseQsigPartyName_ARG *party)
++{
++ int length;
++ int seq_offset;
++ const unsigned char *seq_end;
++
++ if (tag == ASN1_TAG_SEQUENCE) {
++ if (ctrl->debug & PRI_DEBUG_APDU) {
++ pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
++ }
++ ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
++ ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
++
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "name", tag, pos, seq_end,
++ &party->name));
++
++ /* Fixup will skip over any OPTIONAL manufacturer extension information */
++ ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
++ } else {
++ ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, name, tag, pos, end, &party->name));
++ }
++
++ return pos;
++}
++
++/*!
++ * \brief Decode the Q.SIG CallingName invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CallingName_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "callingName", tag, pos, end,
++ &args->qsig.CallingName);
++}
++
++/*!
++ * \brief Decode the Q.SIG CalledName invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_CalledName_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "calledName", tag, pos, end,
++ &args->qsig.CalledName);
++}
++
++/*!
++ * \brief Decode the Q.SIG ConnectedName invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_ConnectedName_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "connectedName", tag, pos, end,
++ &args->qsig.ConnectedName);
++}
++
++/*!
++ * \brief Decode the Q.SIG BusyName invoke argument parameters.
++ *
++ * \param ctrl D channel controller for diagnostic messages or global options.
++ * \param tag Component tag that identified this structure.
++ * \param pos Starting position of the ASN.1 component length.
++ * \param end End of ASN.1 decoding data buffer.
++ * \param args Arguments to fill in from the decoded buffer.
++ *
++ * \retval Start of the next ASN.1 component on success.
++ * \retval NULL on error.
++ */
++const unsigned char *rose_dec_qsig_BusyName_ARG(struct pri *ctrl, unsigned tag,
++ const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
++{
++ return rose_dec_qsig_PartyName_ARG_Backend(ctrl, "busyName", tag, pos, end,
++ &args->qsig.BusyName);
++}
++
++/* ------------------------------------------------------------------- */
++/* end rose_qsig_name.c */
+
+Property changes on: rose_qsig_name.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + 'Author Date Id Revision'
+
+Index: q921.c
+===================================================================
+--- a/q921.c (.../tags/1.4.10.2) (revision 1357)
++++ b/q921.c (.../branches/1.4) (revision 1357)
+@@ -27,6 +27,7 @@
+ * terms granted here.
+ */
+
++#include <stdint.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+@@ -139,8 +140,7 @@
+ #endif
+ pri->ri = random() % 65535;
+ q921_send_tei(pri, Q921_TEI_IDENTITY_REQUEST, pri->ri, Q921_TEI_GROUP, 1);
+- if (pri->t202_timer)
+- pri_schedule_del(pri, pri->t202_timer);
++ pri_schedule_del(pri, pri->t202_timer);
+ pri->t202_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_tei_request, pri);
+ }
+
+@@ -174,8 +174,8 @@
+ {
+ struct pri *pri = vpri;
+ q921_h h;
++
+ pri_schedule_del(pri, pri->sabme_timer);
+- pri->sabme_timer = 0;
+ pri->sabme_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri);
+ if (!now)
+ return;
+@@ -248,14 +248,12 @@
+
+ static void t203_expire(void *);
+ static void t200_expire(void *);
+-static pri_event *q921_dchannel_down(struct pri *pri);
+
+ static void reschedule_t200(struct pri *pri)
+ {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Restarting T200 timer\n");
+- if (pri->t200_timer)
+- pri_schedule_del(pri, pri->t200_timer);
++ pri_schedule_del(pri, pri->t200_timer);
+ pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
+ }
+
+@@ -263,8 +261,7 @@
+ {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Restarting T203 timer\n");
+- if (pri->t203_timer)
+- pri_schedule_del(pri, pri->t203_timer);
++ pri_schedule_del(pri, pri->t203_timer);
+ pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
+ }
+
+@@ -312,10 +309,8 @@
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n");
+ /* Something was ACK'd. Stop T200 counter */
+- if (pri->t200_timer) {
+- pri_schedule_del(pri, pri->t200_timer);
+- pri->t200_timer = 0;
+- }
++ pri_schedule_del(pri, pri->t200_timer);
++ pri->t200_timer = 0;
+ }
+ if (pri->t203_timer) {
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+@@ -483,6 +478,45 @@
+ }
+ }
+
++int q921_transmit_uiframe(struct pri *pri, void *buf, int len)
++{
++ uint8_t ubuf[512];
++ q921_h *h = (void *)&ubuf[0];
++
++ if (len >= 512) {
++ pri_error(pri, "Requested to send UI frame larger than 512 bytes!\n");
++ return -1;
++ }
++
++ memset(ubuf, 0, sizeof(ubuf));
++ h->h.sapi = 0;
++ h->h.ea1 = 0;
++ h->h.ea2 = 1;
++ h->h.tei = pri->tei;
++ h->u.m3 = 0;
++ h->u.m2 = 0;
++ h->u.p_f = 0; /* Poll bit set */
++ h->u.ft = Q921_FRAMETYPE_U;
++
++ switch(pri->localtype) {
++ case PRI_NETWORK:
++ h->h.c_r = 1;
++ break;
++ case PRI_CPE:
++ h->h.c_r = 0;
++ break;
++ default:
++ pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
++ return -1;
++ }
++
++ memcpy(h->u.data, buf, len);
++
++ q921_transmit(pri, h, len + 3);
++
++ return 0;
++}
++
+ int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
+ {
+ q921_frame *f, *prev=NULL;
+@@ -521,6 +555,10 @@
+ pri->txqueue = f;
+ /* Immediately transmit unless we're in a recovery state, or the window
+ size is too big */
++ if (pri->debug & PRI_DEBUG_Q921_DUMP) {
++ pri_message(pri, "TEI/SAPI: %d/%d state %d retran %d busy %d\n",
++ pri->tei, pri->sapi, pri->q921_state, pri->retrans, pri->busy);
++ }
+ if ((pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) && (!pri->retrans && !pri->busy)) {
+ if (pri->windowlen < pri->window) {
+ q921_send_queued_iframes(pri);
+@@ -564,11 +602,15 @@
+ /* Start timer T200 to resend our RR if we don't get it */
+ pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
+ } else {
+- if (pri->debug & PRI_DEBUG_Q921_DUMP)
+- pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state);
++ if (pri->debug & PRI_DEBUG_Q921_DUMP) {
++ pri_message(pri,
++ "T203 counter expired in weird state %d on pri with SAPI/TEI of %d/%d\n",
++ pri->q921_state, pri->sapi, pri->tei);
++ }
+ pri->t203_timer = 0;
+ }
+ }
++
+ static pri_event *q921_handle_iframe(struct pri *pri, q921_i *i, int len)
+ {
+ int res;
+@@ -622,33 +664,34 @@
+ char *buf = malloc(len * 3 + 1);
+ int buflen = 0;
+ if (buf) {
++ pri_message(pri, "\n");
+ for (x=0;x<len;x++)
+ buflen += sprintf(buf + buflen, "%02x ", h->raw[x]);
+- pri_message(pri, "\n%c [ %s]\n", direction_tag, buf);
++ pri_message(pri, "%c [ %s]\n", direction_tag, buf);
+ free(buf);
+ }
+ }
+
++ pri_message(pri, "\n");
+ switch (h->h.data[0] & Q921_FRAMETYPE_MASK) {
+ case 0:
+ case 2:
+- pri_message(pri, "\n%c Informational frame:\n", direction_tag);
++ pri_message(pri, "%c Informational frame:\n", direction_tag);
+ break;
+ case 1:
+- pri_message(pri, "\n%c Supervisory frame:\n", direction_tag);
++ pri_message(pri, "%c Supervisory frame:\n", direction_tag);
+ break;
+ case 3:
+- pri_message(pri, "\n%c Unnumbered frame:\n", direction_tag);
++ pri_message(pri, "%c Unnumbered frame:\n", direction_tag);
+ break;
+ }
+
+- pri_message(pri,
+-"%c SAPI: %02d C/R: %d EA: %d\n"
+-"%c TEI: %03d EA: %d\n",
++ pri_message(pri, "%c SAPI: %02d C/R: %d EA: %d\n",
+ direction_tag,
+ h->h.sapi,
+ h->h.c_r,
+- h->h.ea1,
++ h->h.ea1);
++ pri_message(pri, "%c TEI: %03d EA: %d\n",
+ direction_tag,
+ h->h.tei,
+ h->h.ea2);
+@@ -658,15 +701,17 @@
+ case 2:
+ /* Informational frame */
+ pri_message(pri,
+-"%c N(S): %03d 0: %d\n"
+-"%c N(R): %03d P: %d\n"
+-"%c %d bytes of data\n",
++"%c N(S): %03d 0: %d\n",
+ direction_tag,
+ h->i.n_s,
+- h->i.ft,
++ h->i.ft);
++ pri_message(pri,
++"%c N(R): %03d P: %d\n",
+ direction_tag,
+ h->i.n_r,
+- h->i.p_f,
++ h->i.p_f);
++ pri_message(pri,
++"%c %d bytes of data\n",
+ direction_tag,
+ len - 4);
+ break;
+@@ -685,17 +730,19 @@
+ break;
+ }
+ pri_message(pri,
+-"%c Zero: %d S: %d 01: %d [ %s ]\n"
+-"%c N(R): %03d P/F: %d\n"
+-"%c %d bytes of data\n",
++"%c Zero: %d S: %d 01: %d [ %s ]\n",
+ direction_tag,
+ h->s.x0,
+ h->s.ss,
+ h->s.ft,
+- type,
++ type);
++ pri_message(pri,
++"%c N(R): %03d P/F: %d\n",
+ direction_tag,
+ h->s.n_r,
+- h->s.p_f,
++ h->s.p_f);
++ pri_message(pri,
++"%c %d bytes of data\n",
+ direction_tag,
+ len - 4);
+ break;
+@@ -731,14 +778,15 @@
+ }
+ }
+ pri_message(pri,
+-"%c M3: %d P/F: %d M2: %d 11: %d [ %s ]\n"
+-"%c %d bytes of data\n",
++"%c M3: %d P/F: %d M2: %d 11: %d [ %s ]\n",
+ direction_tag,
+ h->u.m3,
+ h->u.p_f,
+ h->u.m2,
+ h->u.ft,
+- type,
++ type);
++ pri_message(pri,
++"%c %d bytes of data\n",
+ direction_tag,
+ len - 3);
+ break;
+@@ -783,7 +831,7 @@
+ }
+ }
+
+-static pri_event *q921_dchannel_up(struct pri *pri)
++pri_event *q921_dchannel_up(struct pri *pri)
+ {
+ if (pri->tei == Q921_TEI_PRI) {
+ q921_reset(pri, 1);
+@@ -792,10 +840,8 @@
+ }
+
+ /* Stop any SABME retransmissions */
+- if (pri->sabme_timer) {
+- pri_schedule_del(pri, pri->sabme_timer);
+- pri->sabme_timer = 0;
+- }
++ pri_schedule_del(pri, pri->sabme_timer);
++ pri->sabme_timer = 0;
+
+ /* Reset any rejects */
+ pri->sentrej = 0;
+@@ -805,7 +851,12 @@
+ pri_message(pri, DBGHEAD "q921_state now is Q921_LINK_CONNECTION_ESTABLISHED\n", DBGINFO);
+ pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
+
++ /* Ensure that we do not have T200 or T203 running when the link comes up */
++ pri_schedule_del(pri, pri->t200_timer);
++ pri->t200_timer = 0;
++
+ /* Start the T203 timer */
++ pri_schedule_del(pri, pri->t203_timer);
+ pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
+
+ /* Notify Layer 3 */
+@@ -818,7 +869,7 @@
+ return &pri->ev;
+ }
+
+-static pri_event *q921_dchannel_down(struct pri *pri)
++pri_event *q921_dchannel_down(struct pri *pri)
+ {
+ /* Reset counters, reset sabme timer etc */
+ q921_reset(pri, 1);
+@@ -826,7 +877,7 @@
+ /* Notify Layer 3 */
+ q931_dl_indication(pri, PRI_EVENT_DCHAN_DOWN);
+
+- /* Report event that D-Channel is now up */
++ /* Report event that D-Channel is now down */
+ pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
+ return &pri->ev;
+ }
+@@ -842,12 +893,9 @@
+ pri->v_na = 0;
+ pri->window = pri->timers[PRI_TIMER_K];
+ pri->windowlen = 0;
+- if (pri->sabme_timer)
+- pri_schedule_del(pri, pri->sabme_timer);
+- if (pri->t203_timer)
+- pri_schedule_del(pri, pri->t203_timer);
+- if (pri->t200_timer)
+- pri_schedule_del(pri, pri->t200_timer);
++ pri_schedule_del(pri, pri->sabme_timer);
++ pri_schedule_del(pri, pri->t203_timer);
++ pri_schedule_del(pri, pri->t200_timer);
+ pri->sabme_timer = 0;
+ pri->sabme_count = 0;
+ pri->t203_timer = 0;
+@@ -879,8 +927,14 @@
+ static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
+ {
+ int ri;
+- struct pri *sub;
++ struct pri *sub = pri;
+ int tei;
++
++ if (!BRI_NT_PTMP(pri) && !BRI_TE_PTMP(pri)) {
++ pri_error(pri, "Received MDL/TEI managemement message, but configured for mode other than PTMP!\n");
++ return NULL;
++ }
++
+ if (pri->debug & PRI_DEBUG_Q921_STATE)
+ pri_message(pri, "Received MDL message\n");
+ if (h->data[0] != 0x0f) {
+@@ -895,16 +949,19 @@
+ tei = (h->data[4] >> 1);
+ switch(h->data[3]) {
+ case Q921_TEI_IDENTITY_REQUEST:
++ if (!BRI_NT_PTMP(pri)) {
++ return NULL;
++ }
++
+ if (tei != 127) {
+ pri_error(pri, "Received TEI identity request with invalid TEI %d\n", tei);
+ q921_send_tei(pri, Q921_TEI_IDENTITY_DENIED, ri, tei, 1);
+ }
+- /* Go to master */
+- for (sub = pri; sub->master; sub = sub->master);
+ tei = 64;
+- while(sub->subchannel) {
+- if(sub->subchannel->tei == tei)
++ while (sub->subchannel) {
++ if (sub->subchannel->tei == tei)
+ ++tei;
++ sub = sub->subchannel;
+ }
+ sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
+ if (!sub->subchannel) {
+@@ -914,14 +971,15 @@
+ q921_send_tei(pri, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 1);
+ break;
+ case Q921_TEI_IDENTITY_ASSIGNED:
++ if (!BRI_TE_PTMP(pri))
++ return NULL;
++
+ if (ri != pri->ri) {
+ pri_message(pri, "TEI assignment received for invalid Ri %02x (our is %02x)\n", ri, pri->ri);
+ return NULL;
+ }
+- if (pri->t202_timer) {
+- pri_schedule_del(pri, pri->t202_timer);
+- pri->t202_timer = 0;
+- }
++ pri_schedule_del(pri, pri->t202_timer);
++ pri->t202_timer = 0;
+ if (pri->subchannel && (pri->subchannel->tei == tei)) {
+ pri_error(pri, "TEI already assigned (new is %d, current is %d)\n", tei, pri->subchannel->tei);
+ q921_tei_release_and_reacquire(pri);
+@@ -937,6 +995,8 @@
+ pri->q921_state = Q921_TEI_ASSIGNED;
+ break;
+ case Q921_TEI_IDENTITY_CHECK_REQUEST:
++ if (!BRI_TE_PTMP(pri))
++ return NULL;
+ /* We're assuming one TEI per PRI in TE PTMP mode */
+
+ /* If no subchannel (TEI) ignore */
+@@ -949,6 +1009,8 @@
+
+ break;
+ case Q921_TEI_IDENTITY_REMOVE:
++ if (!BRI_TE_PTMP(pri))
++ return NULL;
+ /* XXX: Assuming multiframe mode has been disconnected already */
+ if (!pri->subchannel)
+ return NULL;
+@@ -990,6 +1052,10 @@
+ pri_error(pri, "!! Received short I-frame (expected 4, got %d)\n", len);
+ break;
+ }
++
++ /* T203 is rescheduled only on reception of I frames or S frames */
++ reschedule_t203(pri);
++
+ return q921_handle_iframe(pri, &h->i, len);
+ break;
+ case 1:
+@@ -1001,6 +1067,10 @@
+ pri_error(pri, "!! Received short S-frame (expected 4, got %d)\n", len);
+ break;
+ }
++
++ /* T203 is rescheduled only on reception of I frames or S frames */
++ reschedule_t203(pri);
++
+ switch(h->s.ss) {
+ case 0:
+ /* Receiver Ready */
+@@ -1091,10 +1161,8 @@
+ }
+ }
+ /* Reset t200 timer if it was somehow going */
+- if (pri->t200_timer) {
+- pri_schedule_del(pri, pri->t200_timer);
+- pri->t200_timer = 0;
+- }
++ pri_schedule_del(pri, pri->t200_timer);
++ pri->t200_timer = 0;
+ /* Reset and restart t203 timer */
+ reschedule_t203(pri);
+ }
+@@ -1152,7 +1220,9 @@
+ /* Acknowledge */
+ q921_send_ua(pri, h->u.p_f);
+ ev = q921_dchannel_down(pri);
+- q921_restart(pri, 0);
++ if (BRI_TE_PTMP(pri) || PRI_PTP(pri)) {
++ q921_restart(pri, PRI_PTP(pri) ? 1 : 0);
++ }
+ return ev;
+ case 3:
+ if (h->u.m2 == 3) {
+@@ -1212,6 +1282,34 @@
+ return NULL;
+ }
+
++static pri_event *q921_handle_unmatched_frame(struct pri *pri, q921_h *h, int len)
++{
++ pri = PRI_MASTER(pri);
++
++ if (h->h.tei < 64) {
++ pri_error(pri, "Do not support manual TEI range. Discarding\n");
++ return NULL;
++ }
++
++ if (h->h.sapi != Q921_SAPI_CALL_CTRL) {
++ pri_error(pri, "Message with SAPI other than CALL CTRL is discarded\n");
++ return NULL;
++ }
++
++ if (pri->debug & PRI_DEBUG_Q921_DUMP) {
++ pri_message(pri,
++ "Could not find candidate subchannel for received frame with SAPI/TEI of %d/%d.\n",
++ h->h.sapi, h->h.tei);
++ pri_message(pri, "Sending TEI release, in order to re-establish TEI state\n");
++ }
++
++ /* Q.921 says we should send the remove message twice, in case of link corruption */
++ q921_send_tei(pri, Q921_TEI_IDENTITY_REMOVE, 0, h->h.tei, 1);
++ q921_send_tei(pri, Q921_TEI_IDENTITY_REMOVE, 0, h->h.tei, 1);
++
++ return NULL;
++}
++
+ static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len)
+ {
+ pri_event *ev;
+@@ -1225,26 +1323,22 @@
+ if (h->h.ea1 || !(h->h.ea2))
+ return NULL;
+
+-#if 0 /* Will be rejected by subchannel analyzis */
+- /* Check for broadcasts - not yet handled */
+- if (h->h.tei == Q921_TEI_GROUP)
+- return NULL;
+-#endif
+-
+ if (!((h->h.sapi == pri->sapi) && ((h->h.tei == pri->tei) || (h->h.tei == Q921_TEI_GROUP)))) {
+ /* Check for SAPIs we don't yet handle */
+ /* If it's not us, try any subchannels we have */
+ if (pri->subchannel)
+ return q921_receive(pri->subchannel, h, len + 2);
+ else {
+- return NULL;
++ /* This means we couldn't find a candidate subchannel for it...
++ * Time for some corrective action */
++
++ return q921_handle_unmatched_frame(pri, h, len);
+ }
+
+ }
+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
+ pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei);
+ ev = __q921_receive_qualified(pri, h, len);
+- reschedule_t203(pri);
+ return ev;
+ }
+
+
+Property changes on: .
+___________________________________________________________________
+Added: reviewboard:url
+ + https://reviewboard.asterisk.org
+
diff --git a/main/libpri/libpri-cflags.patch b/main/libpri/libpri-cflags.patch
new file mode 100644
index 0000000000..7bf31c7ac1
--- /dev/null
+++ b/main/libpri/libpri-cflags.patch
@@ -0,0 +1,21 @@
+Index: Makefile
+===================================================================
+--- a/Makefile (revision 650)
++++ b/Makefile (working copy)
+@@ -43,7 +43,7 @@
+ DYNAMIC_LIBRARY:=libpri.so.$(SONAME)
+ STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o version.o
+ DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo version.lo
+-CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
++CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
+ INSTALL_PREFIX=$(DESTDIR)
+ INSTALL_BASE=/usr
+ libdir?=$(INSTALL_BASE)/lib
+@@ -102,7 +102,6 @@
+ ifneq (${OSARCH},SunOS)
+ install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include
+ install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
+- if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi
+ ( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so)
+ install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
+ if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(libdir); fi
diff --git a/main/libproxy/APKBUILD b/main/libproxy/APKBUILD
new file mode 100644
index 0000000000..d2895b090c
--- /dev/null
+++ b/main/libproxy/APKBUILD
@@ -0,0 +1,62 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libproxy
+pkgver=0.4.6
+pkgrel=1
+pkgdesc="A library handling all the details of proxy configuration"
+url="http://code.google.com/p/libproxy/"
+arch="all"
+license="LGPLv2+"
+depends=
+depends_dev="zlib-dev"
+makedepends="cmake python-dev $depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-bin py-$pkgname:py"
+source="http://libproxy.googlecode.com/files/libproxy-$pkgver.tar.gz"
+
+_builddir="$srcdir"/libproxy-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ cmake \
+ -DCMAKE_INSTALL_PREFIX=/usr \
+ -DLIBEXEC_INSTALL_DIR=lib \
+ -DMODULE_INSTALL_DIR=/usr/lib/libproxy/$pkgver/modules \
+ -DWITH_PERL=OFF \
+ ./ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+dev() {
+ default_dev
+ mkdir -p "$subpkgdir"/usr/share
+ mv "$pkgdir"/usr/share/cmake "$subpkgdir"/usr/share/
+}
+
+bin() {
+ pkgdesc="Binary to test libproxy"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+py() {
+ pkgdesc="Binding for libproxy and python"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/python* "$subpkgdir"/usr/lib/
+}
+
+md5sums="199c6b120baf1f7258a55f38d5ec74f5 libproxy-0.4.6.tar.gz"
diff --git a/main/libpthread-stubs/APKBUILD b/main/libpthread-stubs/APKBUILD
new file mode 100644
index 0000000000..9f9347e000
--- /dev/null
+++ b/main/libpthread-stubs/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libpthread-stubs
+pkgver=0.3
+pkgrel=2
+pkgdesc="Pthread functions stubs for platforms missing them"
+url="http://cgit.freedesktop.org/xcb/pthread-stubs"
+arch="all"
+license="X11"
+depends=
+source="http://xcb.freedesktop.org/dist/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ # we actually have pthread_exit, the configure script just
+ # fails to detect it
+ make CFLAGS="$CFLAGS -DHAVE_PTHREAD_EXIT=1"
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install
+}
+md5sums="e8fa31b42e13f87e8f5a7a2b731db7ee libpthread-stubs-0.3.tar.bz2"
diff --git a/main/libraw/APKBUILD b/main/libraw/APKBUILD
new file mode 100644
index 0000000000..fb7b8001f6
--- /dev/null
+++ b/main/libraw/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libraw
+pkgver=0.13.5
+pkgrel=1
+pkgdesc="Library for reading RAW files obtained from digital photo cameras"
+url="http://www.libraw.org/"
+arch="all"
+license="CDDL LGPL custom"
+depends=""
+makedepends=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.libraw.org/data/LibRaw-$pkgver.tar.gz"
+
+_builddir="$srcdir"/LibRaw-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make lib/libraw.a lib/libraw_r.a
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+}
+
+md5sums="bf6894f6a60b411da012f58a0954e910 LibRaw-0.13.5.tar.gz"
diff --git a/main/libraw1394/APKBUILD b/main/libraw1394/APKBUILD
new file mode 100644
index 0000000000..af42d9f20f
--- /dev/null
+++ b/main/libraw1394/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=libraw1394
+pkgver=2.0.5
+pkgrel=1
+pkgdesc="Library to provide access to Linux 1394 subsystem"
+url="http://sourceforge.net/projects/libraw1394"
+arch="all"
+license="LGPL"
+depends=
+depends_dev=
+makedepends=""
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/project/$pkgname/$pkgname/$pkgname-$pkgver.tar.gz"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="1db64231c78540c32859b591cb8b40cf libraw1394-2.0.5.tar.gz"
diff --git a/main/libresample/APKBUILD b/main/libresample/APKBUILD
new file mode 100644
index 0000000000..be81aacf80
--- /dev/null
+++ b/main/libresample/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor:
+# Maintainer:
+pkgname=libresample
+pkgver=0.1.3
+pkgrel=1
+pkgdesc="real-time library for sampling rate conversion"
+url="https://ccrma.stanford.edu/~jos/resample/Free_Resampling_Software.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="wget"
+install=
+subpackages=
+source="https://ccrma.stanford.edu/~jos/gz/libresample-$pkgver.tgz"
+
+# append extra dependencies to -dev subpackage
+# remove if not used.
+# depends_dev="somepackage-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/usr/include "$pkgdir"/usr/lib
+ install -m644 include/libresample.h "$pkgdir"/usr/include/
+ install -m644 libresample.a "$pkgdir"/usr/lib/
+
+}
+
+md5sums="99bc5ea15ef76b83e5655a10968f674b libresample-0.1.3.tgz"
diff --git a/main/librsvg/APKBUILD b/main/librsvg/APKBUILD
new file mode 100644
index 0000000000..025f979b5c
--- /dev/null
+++ b/main/librsvg/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=librsvg
+pkgver=2.34.0
+pkgrel=1
+pkgdesc="SAX-based renderer for SVG files into a GdkPixbuf"
+url="http://librsvg.sourceforge.net/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="gtk+-dev libcroco-dev libgsf-dev bzip2-dev"
+install=
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev gtk+-dev cairo-dev libcroco-dev libgsf-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --libexecdir=/usr/lib/$pkgname \
+ --with-croco \
+ --disable-static \
+ --disable-mozilla-plugin \
+ --with-svgz || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR=""$pkgdir"" install || return 1
+ rm -rf "$pkgdir"/usr/lib/mozilla "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="5eb2fcd0765aa5e47a4999985e3c27ab librsvg-2.34.0.tar.bz2"
diff --git a/main/librsync/APKBUILD b/main/librsync/APKBUILD
new file mode 100644
index 0000000000..25c1b0ee87
--- /dev/null
+++ b/main/librsync/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Jeremy Thomerson <jeremy@thomersonfamily.com>
+# Maintainer: Jeremy Thomerson <jeremy@thomersonfamily.com>
+pkgname=librsync
+pkgver=0.9.7
+pkgrel=1
+pkgdesc="librsync implements the rolling-checksum algorithm of rsync"
+url="http://sourceforge.net/projects/librsync/"
+arch="all"
+license="LGPL 2.1"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr --mandir=/usr/share/man --enable-shared
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="24cdb6b78f45e0e83766903fd4f6bc84 librsync-0.9.7.tar.gz"
diff --git a/main/libsamplerate/APKBUILD b/main/libsamplerate/APKBUILD
new file mode 100644
index 0000000000..17c50b96fd
--- /dev/null
+++ b/main/libsamplerate/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libsamplerate
+pkgver=0.1.7
+pkgrel=5
+pkgdesc="Secret Rabbit Code - aka Sample Rate Converter for audio"
+url="http://www.mega-nerd.com/SRC/index.html"
+subpackages="$pkgname-dev"
+arch="all"
+license="GPL"
+depends=""
+source="http://www.mega-nerd.com/SRC/$pkgname-$pkgver.tar.gz"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="6731a81cb0c622c483b28c0d7f90867d libsamplerate-0.1.7.tar.gz"
diff --git a/main/libsexy/APKBUILD b/main/libsexy/APKBUILD
new file mode 100644
index 0000000000..f6d7bfde1f
--- /dev/null
+++ b/main/libsexy/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libsexy
+pkgver=0.1.11
+pkgrel=5
+pkgdesc="Doing naughty things to good widgets."
+url="http://chipx86.com/wiki/Libsexy"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="gtk+-dev libxml2-dev iso-codes"
+source="http://releases.chipx86.com/$pkgname/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ rm -f "$pkgdir"/usr/lib/libsexy.a
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="33c079a253270ec8bfb9508e4bb30754 libsexy-0.1.11.tar.gz"
diff --git a/main/libshout/APKBUILD b/main/libshout/APKBUILD
new file mode 100644
index 0000000000..9c7ecaa5df
--- /dev/null
+++ b/main/libshout/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=libshout
+pkgver=2.2.2
+pkgrel=1
+pkgdesc="Library for accessing a shoutcast/icecast server"
+url="http://www.icecast.org/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="speex-dev libtheora-dev libvorbis-dev"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.xiph.org/releases/$pkgname/$pkgname-$pkgver.tar.gz"
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ --sysconfdir=/etc
+ --localstatedir=/var
+ make LDFLAGS+=-lspeex || return 1
+
+}
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="4f75fc9901c724b712c371c9a1e782d3 libshout-2.2.2.tar.gz"
diff --git a/main/libsigc++/APKBUILD b/main/libsigc++/APKBUILD
new file mode 100644
index 0000000000..9aba44a10c
--- /dev/null
+++ b/main/libsigc++/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libsigc++
+pkgver=2.2.9
+pkgrel=1
+pkgdesc="type-safe Signal Framework for C++"
+url="http://libsigc.sourceforge.net/"
+arch="all"
+license="LGPL"
+depends=
+makedepends="m4 perl tar"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/$pkgname/2.2/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="16dc0c868aeef9ee5ef055f3e3e865d3 libsigc++-2.2.9.tar.bz2"
diff --git a/main/libsm/APKBUILD b/main/libsm/APKBUILD
new file mode 100644
index 0000000000..bd67296bf5
--- /dev/null
+++ b/main/libsm/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libsm
+pkgver=1.2.0
+pkgrel=2
+pkgdesc="X11 Session Management library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="pkgconfig libice-dev e2fsprogs-dev xproto xtrans"
+source="http://xorg.freedesktop.org/releases/individual/lib/libSM-$pkgver.tar.bz2"
+
+depends_dev="libice-dev xproto"
+
+build () {
+ cd "$srcdir"/libSM-$pkgver
+ ./configure --prefix=/usr --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libSM-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="e78c447bf1790552b644eca81b542742 libSM-1.2.0.tar.bz2"
diff --git a/main/libsndfile/APKBUILD b/main/libsndfile/APKBUILD
new file mode 100644
index 0000000000..06274e824a
--- /dev/null
+++ b/main/libsndfile/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libsndfile
+pkgver=1.0.24
+pkgrel=1
+pkgdesc="A C library for reading and writing files containing sampled sound"
+url="http://www.mega-nerd.com/libsndfile"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+depends_dev="flac-dev libvorbis-dev libogg-dev"
+makedepends="alsa-lib-dev $depends_dev"
+source="http://www.mega-nerd.com/$pkgname/files/$pkgname-$pkgver.tar.gz"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-sqlite \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="8f823c30c1d8d44830db6ab845d6679e libsndfile-1.0.24.tar.gz"
diff --git a/main/libsoup/APKBUILD b/main/libsoup/APKBUILD
new file mode 100644
index 0000000000..9ee8bf44a0
--- /dev/null
+++ b/main/libsoup/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libsoup
+pkgver=2.34.2
+pkgrel=1
+pkgdesc="Gnome HTTP Library"
+url="http://www.gnome.org"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="glib-networking"
+makedepends="pkgconfig glib-dev gnutls-dev libxml2-dev libiconv-dev
+ gettext-dev libgcrypt-dev libgpg-error-dev zlib-dev
+ gobject-introspection-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev libxml2-dev gnutls-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --without-gnome \
+ --disable-tls-check \
+ --enable-introspection=yes \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="2454b38681a6e082b613a781a501e721 libsoup-2.34.2.tar.bz2"
diff --git a/main/libspf2/0001-provide-dn_skipname.patch b/main/libspf2/0001-provide-dn_skipname.patch
new file mode 100644
index 0000000000..feb46efa68
--- /dev/null
+++ b/main/libspf2/0001-provide-dn_skipname.patch
@@ -0,0 +1,120 @@
+From abfd38dbff2be2e63ee222a87b4f24de5573e7eb Mon Sep 17 00:00:00 2001
+From: Natanael Copa <natanael.copa@gmail.com>
+Date: Mon, 19 Apr 2010 14:53:35 +0000
+Subject: [PATCH] provide dn_skipname
+
+---
+ configure.ac | 3 +-
+ src/libreplace/__dn_skipname.c | 87 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 89 insertions(+), 1 deletions(-)
+ create mode 100644 src/libreplace/__dn_skipname.c
+
+diff --git a/configure.ac b/configure.ac
+index 310d73c..8a0dd2b 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -272,7 +273,7 @@ AC_CHECK_FUNCS([strcasecmp strncasecmp strspn strtoul])
+ AC_CHECK_FUNCS([gethostbyname inet_ntoa select strrchr strstr strtol])
+
+ AC_REPLACE_FUNCS([getopt_long_only strncasecmp])
+-AC_REPLACE_FUNCS([__ns_initparse __ns_name_uncompress __ns_get16 __ns_msg_getflag])
++AC_REPLACE_FUNCS([__ns_initparse __ns_name_uncompress __ns_get16 __ns_msg_getflag __dn_skipname])
+
+ AC_CONFIG_FILES([Makefile
+ Doxyfile
+diff --git a/src/libreplace/__dn_skipname.c b/src/libreplace/__dn_skipname.c
+new file mode 100644
+index 0000000..88d48b5
+--- /dev/null
++++ b/src/libreplace/__dn_skipname.c
+@@ -0,0 +1,87 @@
++/* taken from OpenBSD source */
++/*
++ * ++Copyright++ 1985, 1993
++ * -
++ * Copyright (c) 1985, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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.
++ * -
++ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies, and that
++ * the name of Digital Equipment Corporation not be used in advertising or
++ * publicity pertaining to distribution of the document or software without
++ * specific, written prior permission.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
++ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
++ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
++ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
++ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
++ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
++ * SOFTWARE.
++ * -
++ * --Copyright--
++ */
++
++/*
++ * Skip over a compressed domain name. Return the size or -1.
++ */
++#include <sys/types.h>
++#include <resolv.h>
++
++int
++__dn_skipname(const u_char *comp_dn, const u_char *eom)
++{
++ const u_char *cp;
++ int n;
++
++ cp = comp_dn;
++ while (cp < eom && (n = *cp++)) {
++ /*
++ * check for indirection
++ */
++ switch (n & INDIR_MASK) {
++ case 0: /* normal case, n == len */
++ cp += n;
++ continue;
++ case INDIR_MASK: /* indirection */
++ cp++;
++ break;
++ default: /* illegal type */
++ return (-1);
++ }
++ break;
++ }
++ if (cp > eom)
++ return (-1);
++ return (cp - comp_dn);
++}
++
++
+--
+1.7.0.4
+
diff --git a/main/libspf2/APKBUILD b/main/libspf2/APKBUILD
new file mode 100644
index 0000000000..4c45a5b09b
--- /dev/null
+++ b/main/libspf2/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libspf2
+pkgver=1.2.9
+pkgrel=6
+pkgdesc="Sender Policy Framework library, a part of the SPF/SRS protocol pair."
+url="http://www.libspf2.org"
+arch="all"
+license="LGPL-2.1 BSD-2"
+subpackages="$pkgname-dev"
+makedepends="autoconf automake libtool bind-dev"
+depends=
+source="http://www.libspf2.org/spf/libspf2-$pkgver.tar.gz
+ libspf2-localpolicy-fix.patch
+ 0001-provide-dn_skipname.patch
+ libspf2-res_ninit-uclibc.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ msg "Apply $i"
+ patch -p1 < $i || return 1
+ done
+ libtoolize --force && aclocal && automake && autoconf && autoheader
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="3305df4d1b13ca964d80b23bb5e4e2b6 libspf2-1.2.9.tar.gz
+48d82a6af8c513d75a7402f2933b8b0a libspf2-localpolicy-fix.patch
+201889cbd209aa7cae9ce11ed5ebaaa6 0001-provide-dn_skipname.patch
+06c981fcca0434d447f8a2749b51696f libspf2-res_ninit-uclibc.patch"
diff --git a/main/libspf2/libspf2-localpolicy-fix.patch b/main/libspf2/libspf2-localpolicy-fix.patch
new file mode 100644
index 0000000000..346bfbfd7d
--- /dev/null
+++ b/main/libspf2/libspf2-localpolicy-fix.patch
@@ -0,0 +1,20 @@
+--- libspf2-1.2.9/src/libspf2/spf_interpret.c Wed Oct 22 15:47:43 2008
++++ libspf2-1.2.9.patched/src/libspf2/spf_interpret.c Mon Sep 21 12:22:51 2009
+@@ -1261,6 +1261,7 @@
+ */
+
+ if ( mech == local_policy ) {
++ spf_request->use_local_policy = 0;
+ err = SPF_record_interpret(spf_server->local_policy,
+ spf_request, spf_response, depth + 1);
+
+--- libspf2-1.2.9/src/spfquery/spfquery.c Mon Sep 15 00:17:49 2008
++++ libspf2-1.2.9.patched/src/spfquery/spfquery.c Mon Sep 21 12:14:38 2009
+@@ -602,6 +602,7 @@
+ FREE_RESPONSE(spf_response);
+
+ spf_request = SPF_request_new(spf_server);
++ spf_request->use_local_policy = 1;
+
+ if (SPF_request_set_ipv4_str(spf_request, req->ip)
+ && SPF_request_set_ipv6_str(spf_request, req->ip)) {
diff --git a/main/libspf2/libspf2-res_ninit-uclibc.patch b/main/libspf2/libspf2-res_ninit-uclibc.patch
new file mode 100644
index 0000000000..ae9ba9add6
--- /dev/null
+++ b/main/libspf2/libspf2-res_ninit-uclibc.patch
@@ -0,0 +1,64 @@
+diff --git a/src/libspf2/spf_dns_resolv.c b/src/libspf2/spf_dns_resolv.c
+index 10ccee6..7acdd1f 100644
+--- a/src/libspf2/spf_dns_resolv.c
++++ b/src/libspf2/spf_dns_resolv.c
+@@ -79,13 +79,13 @@ static const struct res_sym ns_sects[] = {
+ static const int num_ns_sect = sizeof(ns_sects) / sizeof(*ns_sects);
+
+
+-#if HAVE_DECL_RES_NINIT
++#if HAVE_DECL_RES_NINIT && !defined(__UCLIBC__)
+ # define SPF_h_errno res_state->res_h_errno
+ #else
+ # define SPF_h_errno h_errno
+ #endif
+
+-#if HAVE_DECL_RES_NINIT
++#if HAVE_DECL_RES_NINIT && !defined(__UCLIBC__)
+ static pthread_once_t res_state_control = PTHREAD_ONCE_INIT;
+ static pthread_key_t res_state_key;
+
+@@ -239,14 +239,14 @@ SPF_dns_resolv_lookup(SPF_dns_server_t *spf_dns_server,
+ size_t rdlen;
+ const u_char *rdata;
+
+-#if HAVE_DECL_RES_NINIT
++#if HAVE_DECL_RES_NINIT && !defined(__UCLIBC__)
+ void *res_spec;
+ struct __res_state *res_state;
+ #endif
+
+ SPF_ASSERT_NOTNULL(spf_dns_server);
+
+-#if HAVE_DECL_RES_NINIT
++#if HAVE_DECL_RES_NINIT && !defined(__UCLIBC__)
+ /** Get the thread-local resolver state. */
+ res_spec = pthread_getspecific(res_state_key);
+ if (res_spec == NULL) {
+@@ -292,7 +292,7 @@ SPF_dns_resolv_lookup(SPF_dns_server_t *spf_dns_server,
+ for (;;) {
+ int dns_len;
+
+-#if HAVE_DECL_RES_NINIT
++#if HAVE_DECL_RES_NINIT && !defined(__UCLIBC__)
+ /* Resolve the name. */
+ dns_len = res_nquery(res_state, domain, ns_c_in, rr_type,
+ responsebuf, responselen);
+@@ -606,7 +606,7 @@ SPF_dns_resolv_free(SPF_dns_server_t *spf_dns_server)
+ {
+ SPF_ASSERT_NOTNULL(spf_dns_server);
+
+-#if ! HAVE_DECL_RES_NINIT
++#if ! HAVE_DECL_RES_NINIT || defined(__UCLIBC__)
+ res_close();
+ #endif
+
+@@ -619,7 +619,7 @@ SPF_dns_resolv_new(SPF_dns_server_t *layer_below,
+ {
+ SPF_dns_server_t *spf_dns_server;
+
+-#if HAVE_DECL_RES_NINIT
++#if HAVE_DECL_RES_NINIT && !defined(__UCLIBC__)
+ pthread_once(&res_state_control, SPF_dns_resolv_init_key);
+ #else
+ if (res_init() != 0) {
diff --git a/main/libssh/APKBUILD b/main/libssh/APKBUILD
new file mode 100644
index 0000000000..51260bf43e
--- /dev/null
+++ b/main/libssh/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=libssh
+pkgver=0.5.0
+pkgrel=0
+pkgdesc="Library for accessing ssh client services through C libraries"
+url="http://www.libssh.org/"
+arch="all"
+license="LGPL"
+depends=
+makedepends="openssl-dev cmake doxygen"
+subpackages="$pkgname-dev"
+source="http://www.libssh.org/files/${pkgver%.*}/${pkgname}-${pkgver}.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"
+
+ mkdir build && cd build
+ cmake "$srcdir"/${pkgname}-${pkgver} \
+ -DCMAKE_INSTALL_PREFIX=/usr \
+ -DCMAKE_BUILD_TYPE=Release
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/build
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="9b37f45751c0ae7ba66099c1fb136946 libssh-0.5.0.tar.gz"
diff --git a/main/libtasn1/APKBUILD b/main/libtasn1/APKBUILD
new file mode 100644
index 0000000000..8fb900a6b3
--- /dev/null
+++ b/main/libtasn1/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libtasn1
+pkgver=2.9
+pkgrel=1
+pkgdesc="The ASN.1 library used in GNUTLS"
+url="http://www.gnu.org/software/gnutls/"
+arch="all"
+license="GPL3 LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="texinfo"
+install=
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="f4f4035b84550100ffeb8ad4b261dea9 libtasn1-2.9.tar.gz"
diff --git a/main/libtheora/APKBUILD b/main/libtheora/APKBUILD
new file mode 100644
index 0000000000..1618ae7d91
--- /dev/null
+++ b/main/libtheora/APKBUILD
@@ -0,0 +1,61 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libtheora
+pkgver=1.1.1
+pkgrel=7
+pkgdesc="An open video codec developed by the Xiph.org"
+url="http://www.xiph.org"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-examples"
+depends=
+makedepends="libvorbis-dev libogg-dev sdl-dev autoconf automake libtool"
+source="http://downloads.xiph.org/releases/theora/$pkgname-$pkgver.tar.bz2
+ libtheora-flags.patch
+ enc.patch
+ "
+
+depends_dev="libogg-dev"
+_builddir="$srcdir"/libtheora-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+ aclocal -I m4 && autoconf && automake && libtoolize || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --enable-shared \
+ --disable-static || return 1
+
+ cd lib && make || return 1
+ cd ..
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -m755 -d ""$pkgdir"/usr/share/licenses/$pkgname"
+ install -m644 LICENSE COPYING "$pkgdir"/usr/share/licenses/$pkgname/
+}
+
+examples() {
+ pkgdesc="Example applications for libtheora"
+ cd "$_builddir"/examples
+ install -d "$subpkgdir"/usr/bin
+ install -m755 dump_psnr player_example dump_video encoder_example \
+ "$subpkgdir"/usr/bin/
+}
+
+md5sums="292ab65cedd5021d6b7ddd117e07cd8e libtheora-1.1.1.tar.bz2
+7cbab1ce1f52adb98e1c241515a27aca libtheora-flags.patch
+5024b6c41351433bf0e8a354969f8efd enc.patch"
diff --git a/main/libtheora/enc.patch b/main/libtheora/enc.patch
new file mode 100644
index 0000000000..ea604d28ed
--- /dev/null
+++ b/main/libtheora/enc.patch
@@ -0,0 +1,11 @@
+--- ./lib/Makefile.am.orig
++++ ./lib/Makefile.am
+@@ -152,7 +154,7 @@
+ Version_script-enc theoraenc.exp
+ libtheoraenc_la_LDFLAGS = \
+ -version-info @THENC_LIB_CURRENT@:@THENC_LIB_REVISION@:@THENC_LIB_AGE@ \
+- @THEORAENC_LDFLAGS@ $(OGG_LIBS)
++ -ltheoradec @THEORAENC_LDFLAGS@ $(OGG_LIBS)
+
+ libtheora_la_SOURCES = \
+ $(decoder_sources) \
diff --git a/main/libtheora/libtheora-flags.patch b/main/libtheora/libtheora-flags.patch
new file mode 100644
index 0000000000..a47cc57716
--- /dev/null
+++ b/main/libtheora/libtheora-flags.patch
@@ -0,0 +1,14 @@
+diff -ur libtheora-1.0beta2.orig/configure.ac libtheora-1.0beta2/configure.ac
+--- libtheora-1.0beta2.orig/configure.ac 2007-10-13 00:01:38.000000000 +0300
++++ libtheora-1.0beta2/configure.ac 2007-11-25 22:44:49.000000000 +0200
+@@ -102,8 +102,8 @@
+ case $host in
+ *)
+ DEBUG="-g -Wall -Wno-parentheses -DDEBUG -D__NO_MATH_INLINES"
+- CFLAGS="-Wall -Wno-parentheses -O3 -fforce-addr -fomit-frame-pointer -finline-functions -funroll-loops"
+- PROFILE="-Wall -Wno-parentheses -pg -g -O3 -fno-inline-functions -DDEBUG";;
++ CFLAGS="-Wall -Wno-parentheses"
++ PROFILE="-Wall -Wno-parentheses -pg -g -fno-inline-functions -DDEBUG";;
+ esac
+ fi
+ CFLAGS="$CFLAGS $cflags_save"
diff --git a/main/libtirpc/APKBUILD b/main/libtirpc/APKBUILD
new file mode 100644
index 0000000000..92865f6670
--- /dev/null
+++ b/main/libtirpc/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libtirpc
+pkgver=0.2.1
+pkgrel=4
+pkgdesc="Transport Independent RPC library (SunRPC replacement)"
+url="http://libtirpc.sourceforge.net/"
+arch="all"
+license="GPL2"
+depends=
+makedepends="libgssglue-dev heimdal-dev autoconf automake libtool"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2
+ nis.h
+ libtirpc-no-des.patch"
+
+depends_dev="libgssglue-dev heimdal-dev"
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+ # uclibc does not provide nis.h so provide our own
+ mkdir src/rpcsvc
+ cp "$srcdir"/nis.h src/rpcsvc/
+
+ sh bootstrap && libtoolize
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-gss
+ make || return 1
+}
+
+package() {
+ cd $srcdir/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 doc/etc_netconfig "$pkgdir"/etc/netconfig
+}
+md5sums="d77eb15f464bf9d6e66259eaf78b2a4e libtirpc-0.2.1.tar.bz2
+082dff1bc78bdcbac6d305c1534fe3c0 nis.h
+e386d2893527ed313686eca6314d6675 libtirpc-no-des.patch"
diff --git a/main/libtirpc/libtirpc-no-des.patch b/main/libtirpc/libtirpc-no-des.patch
new file mode 100644
index 0000000000..8c59de21f8
--- /dev/null
+++ b/main/libtirpc/libtirpc-no-des.patch
@@ -0,0 +1,38 @@
+--- ./src/Makefile.am.orig
++++ ./src/Makefile.am
+@@ -40,7 +40,7 @@
+ # release number of your package. This is an abuse that only fosters
+ # misunderstanding of the purpose of library versions."
+ #
+-libtirpc_la_LDFLAGS = -lnsl -lpthread -version-info 1:10:0
++libtirpc_la_LDFLAGS = -lpthread -version-info 1:10:0
+
+ libtirpc_la_SOURCES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c clnt_bcast.c \
+ clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c \
+@@ -50,7 +50,7 @@
+ rpc_callmsg.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c \
+ rpcb_st_xdr.c svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c \
+ svc_raw.c svc_run.c svc_simple.c svc_vc.c getpeereid.c \
+- auth_time.c auth_des.c authdes_prot.c
++ auth_time.c
+
+ ## XDR
+ libtirpc_la_SOURCES += xdr.c xdr_rec.c xdr_array.c xdr_float.c xdr_mem.c xdr_reference.c xdr_stdio.c
+--- ./src/rpc_soc.c.orig
++++ ./src/rpc_soc.c
+@@ -479,6 +479,7 @@
+ (resultproc_t) rpc_wrap_bcast, "udp");
+ }
+
++#if 0
+ /*
+ * Create the client des authentication object. Obsoleted by
+ * authdes_seccreate().
+@@ -511,6 +512,7 @@
+ return (dummy);
+ }
+
++#endif
+ /*
+ * Create a client handle for a unix connection. Obsoleted by clnt_vc_create()
+ */
diff --git a/main/libtirpc/nis.h b/main/libtirpc/nis.h
new file mode 100644
index 0000000000..a03a25f37b
--- /dev/null
+++ b/main/libtirpc/nis.h
@@ -0,0 +1,542 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#ifndef _RPCSVC_NIS_H
+#define _RPCSVC_NIS_H 1
+
+#include <features.h>
+//#include <rpc/rpc.h>
+//#include <rpcsvc/nis_tags.h>
+
+__BEGIN_DECLS
+
+/*
+ * nis.h
+ *
+ * This file is the main include file for NIS clients. It contains
+ * both the client library function defines and the various data
+ * structures used by the NIS service. It includes the file nis_tags.h
+ * which defines the tag values. This allows the tags to change without
+ * having to change the nis.x file.
+ *
+ * NOTE : THIS FILE IS NOT GENERATED WITH RPCGEN ! SO YOU HAVE TO
+ * ADD ALL THE CHANGES ON nis_*.x FILES HERE AGAIN !
+ *
+ * I have removed all the Solaris internal structs and variables,
+ * because they are not supported, Sun changed them between various
+ * releases and they shouldn't be used in user programs.
+ * <kukuk@suse.de>
+ */
+
+
+#ifndef __nis_object_h
+#define __nis_object_h
+
+#define NIS_MAXSTRINGLEN 255
+#define NIS_MAXNAMELEN 1024
+#define NIS_MAXATTRNAME 32
+#define NIS_MAXATTRVAL 2048
+#define NIS_MAXCOLUMNS 64
+#define NIS_MAXATTR 16
+#define NIS_MAXPATH 1024
+#define NIS_MAXREPLICAS 128
+#define NIS_MAXLINKS 16
+#define NIS_PK_NONE 0
+#define NIS_PK_DH 1
+#define NIS_PK_RSA 2
+#define NIS_PK_KERB 3
+#define NIS_PK_DHEXT 4
+
+struct nis_attr {
+ char *zattr_ndx;
+ struct {
+ u_int zattr_val_len;
+ char *zattr_val_val;
+ } zattr_val;
+};
+typedef struct nis_attr nis_attr;
+
+typedef char *nis_name;
+
+enum zotypes {
+ BOGUS_OBJ = 0,
+ NO_OBJ = 1,
+ DIRECTORY_OBJ = 2,
+ GROUP_OBJ = 3,
+ TABLE_OBJ = 4,
+ ENTRY_OBJ = 5,
+ LINK_OBJ = 6,
+ PRIVATE_OBJ = 7,
+ NIS_BOGUS_OBJ = 0,
+ NIS_NO_OBJ = 1,
+ NIS_DIRECTORY_OBJ = 2,
+ NIS_GROUP_OBJ = 3,
+ NIS_TABLE_OBJ = 4,
+ NIS_ENTRY_OBJ = 5,
+ NIS_LINK_OBJ = 6,
+ NIS_PRIVATE_OBJ = 7
+};
+typedef enum zotypes zotypes;
+
+enum nstype {
+ UNKNOWN = 0,
+ NIS = 1,
+ SUNYP = 2,
+ IVY = 3,
+ DNS = 4,
+ X500 = 5,
+ DNANS = 6,
+ XCHS = 7,
+ CDS = 8,
+};
+typedef enum nstype nstype;
+
+struct oar_mask {
+ uint32_t oa_rights;
+ zotypes oa_otype;
+};
+typedef struct oar_mask oar_mask;
+
+struct endpoint {
+ char *uaddr;
+ char *family;
+ char *proto;
+};
+typedef struct endpoint endpoint;
+
+struct nis_server {
+ nis_name name;
+ struct {
+ u_int ep_len;
+ endpoint *ep_val;
+ } ep;
+ uint32_t key_type;
+ netobj pkey;
+};
+typedef struct nis_server nis_server;
+
+struct directory_obj {
+ nis_name do_name;
+ nstype do_type;
+ struct {
+ u_int do_servers_len;
+ nis_server *do_servers_val;
+ } do_servers;
+ uint32_t do_ttl;
+ struct {
+ u_int do_armask_len;
+ oar_mask *do_armask_val;
+ } do_armask;
+};
+typedef struct directory_obj directory_obj;
+
+#define EN_BINARY 1
+#define EN_CRYPT 2
+#define EN_XDR 4
+#define EN_MODIFIED 8
+#define EN_ASN1 64
+
+struct entry_col {
+ uint32_t ec_flags;
+ struct {
+ u_int ec_value_len;
+ char *ec_value_val;
+ } ec_value;
+};
+typedef struct entry_col entry_col;
+
+struct entry_obj {
+ char *en_type;
+ struct {
+ u_int en_cols_len;
+ entry_col *en_cols_val;
+ } en_cols;
+};
+typedef struct entry_obj entry_obj;
+
+struct group_obj {
+ uint32_t gr_flags;
+ struct {
+ u_int gr_members_len;
+ nis_name *gr_members_val;
+ } gr_members;
+};
+typedef struct group_obj group_obj;
+
+struct link_obj {
+ zotypes li_rtype;
+ struct {
+ u_int li_attrs_len;
+ nis_attr *li_attrs_val;
+ } li_attrs;
+ nis_name li_name;
+};
+typedef struct link_obj link_obj;
+
+#define TA_BINARY 1
+#define TA_CRYPT 2
+#define TA_XDR 4
+#define TA_SEARCHABLE 8
+#define TA_CASE 16
+#define TA_MODIFIED 32
+#define TA_ASN1 64
+
+struct table_col {
+ char *tc_name;
+ uint32_t tc_flags;
+ uint32_t tc_rights;
+};
+typedef struct table_col table_col;
+
+struct table_obj {
+ char *ta_type;
+ int ta_maxcol;
+ u_char ta_sep;
+ struct {
+ u_int ta_cols_len;
+ table_col *ta_cols_val;
+ } ta_cols;
+ char *ta_path;
+};
+typedef struct table_obj table_obj;
+
+struct objdata {
+ zotypes zo_type;
+ union {
+ struct directory_obj di_data;
+ struct group_obj gr_data;
+ struct table_obj ta_data;
+ struct entry_obj en_data;
+ struct link_obj li_data;
+ struct {
+ u_int po_data_len;
+ char *po_data_val;
+ } po_data;
+ } objdata_u;
+};
+typedef struct objdata objdata;
+
+struct nis_oid {
+ uint32_t ctime;
+ uint32_t mtime;
+};
+typedef struct nis_oid nis_oid;
+
+struct nis_object {
+ nis_oid zo_oid;
+ nis_name zo_name;
+ nis_name zo_owner;
+ nis_name zo_group;
+ nis_name zo_domain;
+ uint32_t zo_access;
+ uint32_t zo_ttl;
+ objdata zo_data;
+};
+typedef struct nis_object nis_object;
+
+#endif /* if __nis_object_h */
+
+enum nis_error {
+ NIS_SUCCESS = 0,
+ NIS_S_SUCCESS = 1,
+ NIS_NOTFOUND = 2,
+ NIS_S_NOTFOUND = 3,
+ NIS_CACHEEXPIRED = 4,
+ NIS_NAMEUNREACHABLE = 5,
+ NIS_UNKNOWNOBJ = 6,
+ NIS_TRYAGAIN = 7,
+ NIS_SYSTEMERROR = 8,
+ NIS_CHAINBROKEN = 9,
+ NIS_PERMISSION = 10,
+ NIS_NOTOWNER = 11,
+ NIS_NOT_ME = 12,
+ NIS_NOMEMORY = 13,
+ NIS_NAMEEXISTS = 14,
+ NIS_NOTMASTER = 15,
+ NIS_INVALIDOBJ = 16,
+ NIS_BADNAME = 17,
+ NIS_NOCALLBACK = 18,
+ NIS_CBRESULTS = 19,
+ NIS_NOSUCHNAME = 20,
+ NIS_NOTUNIQUE = 21,
+ NIS_IBMODERROR = 22,
+ NIS_NOSUCHTABLE = 23,
+ NIS_TYPEMISMATCH = 24,
+ NIS_LINKNAMEERROR = 25,
+ NIS_PARTIAL = 26,
+ NIS_TOOMANYATTRS = 27,
+ NIS_RPCERROR = 28,
+ NIS_BADATTRIBUTE = 29,
+ NIS_NOTSEARCHABLE = 30,
+ NIS_CBERROR = 31,
+ NIS_FOREIGNNS = 32,
+ NIS_BADOBJECT = 33,
+ NIS_NOTSAMEOBJ = 34,
+ NIS_MODFAIL = 35,
+ NIS_BADREQUEST = 36,
+ NIS_NOTEMPTY = 37,
+ NIS_COLDSTART_ERR = 38,
+ NIS_RESYNC = 39,
+ NIS_FAIL = 40,
+ NIS_UNAVAIL = 41,
+ NIS_RES2BIG = 42,
+ NIS_SRVAUTH = 43,
+ NIS_CLNTAUTH = 44,
+ NIS_NOFILESPACE = 45,
+ NIS_NOPROC = 46,
+ NIS_DUMPLATER = 47,
+};
+typedef enum nis_error nis_error;
+
+struct nis_result {
+ nis_error status;
+ struct {
+ u_int objects_len;
+ nis_object *objects_val;
+ } objects;
+ netobj cookie;
+ uint32_t zticks;
+ uint32_t dticks;
+ uint32_t aticks;
+ uint32_t cticks;
+};
+typedef struct nis_result nis_result;
+
+struct ns_request {
+ nis_name ns_name;
+ struct {
+ u_int ns_object_len;
+ nis_object *ns_object_val;
+ } ns_object;
+};
+typedef struct ns_request ns_request;
+
+struct ib_request {
+ nis_name ibr_name;
+ struct {
+ u_int ibr_srch_len;
+ nis_attr *ibr_srch_val;
+ } ibr_srch;
+ uint32_t ibr_flags;
+ struct {
+ u_int ibr_obj_len;
+ nis_object *ibr_obj_val;
+ } ibr_obj;
+ struct {
+ u_int ibr_cbhost_len;
+ nis_server *ibr_cbhost_val;
+ } ibr_cbhost;
+ u_int ibr_bufsize;
+ netobj ibr_cookie;
+};
+typedef struct ib_request ib_request;
+
+struct ping_args {
+ nis_name dir;
+ uint32_t stamp;
+};
+typedef struct ping_args ping_args;
+
+enum log_entry_t {
+ LOG_NOP = 0,
+ ADD_NAME = 1,
+ REM_NAME = 2,
+ MOD_NAME_OLD = 3,
+ MOD_NAME_NEW = 4,
+ ADD_IBASE = 5,
+ REM_IBASE = 6,
+ MOD_IBASE = 7,
+ UPD_STAMP = 8,
+};
+typedef enum log_entry_t log_entry_t;
+
+struct log_entry {
+ uint32_t le_time;
+ log_entry_t le_type;
+ nis_name le_princp;
+ nis_name le_name;
+ struct {
+ u_int le_attrs_len;
+ nis_attr *le_attrs_val;
+ } le_attrs;
+ nis_object le_object;
+};
+typedef struct log_entry log_entry;
+
+struct log_result {
+ nis_error lr_status;
+ netobj lr_cookie;
+ struct {
+ u_int lr_entries_len;
+ log_entry *lr_entries_val;
+ } lr_entries;
+};
+typedef struct log_result log_result;
+
+struct cp_result {
+ nis_error cp_status;
+ uint32_t cp_zticks;
+ uint32_t cp_dticks;
+};
+typedef struct cp_result cp_result;
+
+struct nis_tag {
+ uint32_t tag_type;
+ char *tag_val;
+};
+typedef struct nis_tag nis_tag;
+
+struct nis_taglist {
+ struct {
+ u_int tags_len;
+ nis_tag *tags_val;
+ } tags;
+};
+typedef struct nis_taglist nis_taglist;
+
+struct dump_args {
+ nis_name da_dir;
+ uint32_t da_time;
+ struct {
+ u_int da_cbhost_len;
+ nis_server *da_cbhost_val;
+ } da_cbhost;
+};
+typedef struct dump_args dump_args;
+
+struct fd_args {
+ nis_name dir_name;
+ nis_name requester;
+};
+typedef struct fd_args fd_args;
+
+struct fd_result {
+ nis_error status;
+ nis_name source;
+ struct {
+ u_int dir_data_len;
+ char *dir_data_val;
+ } dir_data;
+ struct {
+ u_int signature_len;
+ char *signature_val;
+ } signature;
+};
+typedef struct fd_result fd_result;
+
+/* Generic client creating flags */
+#define ZMH_VC 1
+#define ZMH_DG 2
+#define ZMH_AUTH 4
+
+/* Testing Access rights for objects */
+
+#define NIS_READ_ACC 1
+#define NIS_MODIFY_ACC 2
+#define NIS_CREATE_ACC 4
+#define NIS_DESTROY_ACC 8
+/* Test macros. a == access rights, m == desired rights. */
+#define NIS_WORLD(a, m) (((a) & (m)) != 0)
+#define NIS_GROUP(a, m) (((a) & ((m) << 8)) != 0)
+#define NIS_OWNER(a, m) (((a) & ((m) << 16)) != 0)
+#define NIS_NOBODY(a, m) (((a) & ((m) << 24)) != 0)
+/*
+ * EOL Alert - The following non-prefixed test macros are
+ * here for backward compatability, and will be not be present
+ * in future releases - use the NIS_*() macros above.
+ */
+#define WORLD(a, m) (((a) & (m)) != 0)
+#define GROUP(a, m) (((a) & ((m) << 8)) != 0)
+#define OWNER(a, m) (((a) & ((m) << 16)) != 0)
+#define NOBODY(a, m) (((a) & ((m) << 24)) != 0)
+
+#define OATYPE(d, n) (((d)->do_armask.do_armask_val+n)->oa_otype)
+#define OARIGHTS(d, n) (((d)->do_armask.do_armask_val+n)->oa_rights)
+#define WORLD_DEFAULT (NIS_READ_ACC)
+#define GROUP_DEFAULT (NIS_READ_ACC << 8)
+#define OWNER_DEFAULT ((NIS_READ_ACC + NIS_MODIFY_ACC + NIS_CREATE_ACC +\
+ NIS_DESTROY_ACC) << 16)
+#define DEFAULT_RIGHTS (WORLD_DEFAULT | GROUP_DEFAULT | OWNER_DEFAULT)
+
+/* Result manipulation defines ... */
+#define NIS_RES_NUMOBJ(x) ((x)->objects.objects_len)
+#define NIS_RES_OBJECT(x) ((x)->objects.objects_val)
+#define NIS_RES_COOKIE(x) ((x)->cookie)
+#define NIS_RES_STATUS(x) ((x)->status)
+
+/* These defines make getting at the variant part of the object easier. */
+#define TA_data zo_data.objdata_u.ta_data
+#define EN_data zo_data.objdata_u.en_data
+#define DI_data zo_data.objdata_u.di_data
+#define LI_data zo_data.objdata_u.li_data
+#define GR_data zo_data.objdata_u.gr_data
+
+#define __type_of(o) ((o)->zo_data.zo_type)
+
+/* Declarations for the internal subroutines in nislib.c */
+enum name_pos {SAME_NAME, HIGHER_NAME, LOWER_NAME, NOT_SEQUENTIAL, BAD_NAME};
+typedef enum name_pos name_pos;
+
+/*
+ * Defines for getting at column data in entry objects. Because RPCGEN
+ * generates some rather wordy structures, we create some defines that
+ * collapse the needed keystrokes to access a particular value using
+ * these definitions they take an nis_object *, and an int and return
+ * a u_char * for Value, and an int for length.
+ */
+#define ENTRY_VAL(obj, col) (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val
+#define ENTRY_LEN(obj, col) (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len
+
+
+/* Prototypes, and extern declarations for the NIS library functions. */
+//#include <rpcsvc/nislib.h>
+#endif
+
+/*
+ * nis_3.h
+ *
+ * This file contains definitions that are only of interest to the actual
+ * service daemon and client stubs. Normal users of NIS will not include
+ * this file.
+ *
+ * NOTE : This include file is automatically created by a combination
+ * of rpcgen and sed. DO NOT EDIT IT, change the nis.x file instead
+ * and then remake this file.
+ */
+#ifndef __nis_3_h
+#define __nis_3_h
+
+#define NIS_PROG 100300
+#define NIS_VERSION 3
+
+
+__END_DECLS
+
+#endif /* ! _RPCSVC_NIS_H */
diff --git a/main/libtool/APKBUILD b/main/libtool/APKBUILD
new file mode 100644
index 0000000000..9bbdb3813b
--- /dev/null
+++ b/main/libtool/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libtool
+pkgver=2.4
+pkgrel=2
+pkgdesc="A generic library support script"
+arch="all"
+license='GPL'
+url="http://www.gnu.org/software/libtool"
+source="ftp://ftp.gnu.org/pub/gnu/libtool/${pkgname}-${pkgver}.tar.gz"
+depends="bash libltdl"
+subpackages="libltdl $pkgname-doc"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+libltdl() {
+ pkgdesc="Runtime libraries for GNU Libtool Dynamic Module Loade"
+ depends=
+ mkdir -p "$subpkgdir/usr/lib"
+ mv "$pkgdir/usr/lib/libltdl.so"* "$subpkgdir/usr/lib/"
+}
+
+md5sums="b32b04148ecdd7344abc6fe8bd1bb021 libtool-2.4.tar.gz"
diff --git a/main/libunique/APKBUILD b/main/libunique/APKBUILD
new file mode 100644
index 0000000000..83294fa83c
--- /dev/null
+++ b/main/libunique/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libunique
+pkgver=1.1.6
+pkgrel=3
+pkgdesc="Library for writing single instance applications"
+url="http://live.gnome.org/LibUnique"
+arch="all"
+license="LGPL"
+depends=
+makedepends="pkgconfig gtk+-dev dbus-glib-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/1.1/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="7955769ef31f1bc4f83446dbb3625e6d libunique-1.1.6.tar.bz2"
diff --git a/main/libusb-compat/APKBUILD b/main/libusb-compat/APKBUILD
new file mode 100644
index 0000000000..cf4ed97af7
--- /dev/null
+++ b/main/libusb-compat/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libusb-compat
+pkgver=0.1.3
+pkgrel=2
+pkgdesc="Compatility for older libusb"
+url="http://libusb.sourceforge.net/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev"
+depends=
+makedepends="libusb-dev"
+depends_dev="libusb-dev"
+source="http://downloads.sourceforge.net/libusb/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --disable-build-docs
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="570ac2ea085b80d1f74ddc7c6a93c0eb libusb-compat-0.1.3.tar.bz2"
diff --git a/main/libusb/APKBUILD b/main/libusb/APKBUILD
new file mode 100644
index 0000000000..d9c58aa60b
--- /dev/null
+++ b/main/libusb/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libusb
+pkgver=1.0.8
+pkgrel=3
+pkgdesc="Library to enable user space application programs to communicate with USB devices"
+url="http://libusb.sourceforge.net/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev"
+depends=""
+makedepends=""
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --disable-build-docs
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="37d34e6eaa69a4b645a19ff4ca63ceef libusb-1.0.8.tar.bz2"
diff --git a/main/libvdpau/APKBUILD b/main/libvdpau/APKBUILD
new file mode 100644
index 0000000000..b87fba81fe
--- /dev/null
+++ b/main/libvdpau/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=libvdpau
+pkgver=0.4.1
+pkgrel=1
+pkgdesc="Nvidia VDPAU library"
+url="http://cgit.freedesktop.org/~aplattner/libvdpau"
+arch="all"
+license="custom"
+depends=
+makedepends="libx11-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://people.freedesktop.org/~aplattner/vdpau/${pkgname}-${pkgver}.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/vdpau/*.la \
+ "$pkgdir"/usr/lib/*.la || return 1
+ install -d -m755 "${pkgdir}/usr/share/licenses/${pkgname}"
+ install -m644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}/" || return 1
+}
+
+md5sums="8e1f0639bea4e4a842aee93ab64406cc libvdpau-0.4.1.tar.gz"
diff --git a/main/libvirt/APKBUILD b/main/libvirt/APKBUILD
new file mode 100644
index 0000000000..ace035aa51
--- /dev/null
+++ b/main/libvirt/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=libvirt
+pkgver=0.9.2
+pkgrel=3
+pkgdesc="A virtualization API for several hypervisor and container systems"
+url="http://libvirt.org/"
+arch="all"
+license="LGPL"
+depends="netcat-openbsd python"
+makedepends="augeas-dev bridge-utils-dev device-mapper e2fsprogs-dev gnutls-dev
+ libcap-ng-dev libgpg-error-dev libnetcf-dev libnl-dev libxml2-dev
+ libxslt-dev libtasn1-dev lvm2-dev gnutls-dev open-iscsi parted-dev perl
+ pkgconfig udev-dev zlib-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://libvirt.org/sources/$pkgname-$pkgver.tar.gz
+ libvirt.confd
+ libvirt.initd"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+# patch -p1 < ../fix_undefined_symbol_error_when_macvtap_support_is_disabled.patch || return 1
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --libexec=/usr/lib/"$pkgname"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+ install -D -m755 $srcdir/$pkgname.initd $pkgdir/etc/init.d/libvirtd
+ install -D -m755 $srcdir/$pkgname.confd $pkgdir/etc/conf.d/libvirtd
+}
+
+md5sums="a9f974e173471a9c9b381ad1e93642b0 libvirt-0.9.2.tar.gz
+1c84a7baeafe0a7f4e9d7ae5180311b7 libvirt.confd
+3d32c12642cb9a84baf019c7b0971755 libvirt.initd"
diff --git a/main/libvirt/fix_undefined_symbol_error_when_macvtap_support_is_disabled.patch b/main/libvirt/fix_undefined_symbol_error_when_macvtap_support_is_disabled.patch
new file mode 100644
index 0000000000..c00d38bd1f
--- /dev/null
+++ b/main/libvirt/fix_undefined_symbol_error_when_macvtap_support_is_disabled.patch
@@ -0,0 +1,117 @@
+diff --git a/src/libvirt_macvtap.syms b/src/libvirt_macvtap.syms
+index 107b7da..b48565b 100644
+--- a/src/libvirt_macvtap.syms
++++ b/src/libvirt_macvtap.syms
+@@ -1,9 +1,10 @@
+ #
++# These symbols are dependent on WITH_MACVTAP.
++#
++
+
+ # macvtap.h
+ delMacvtap;
+ openMacvtapTap;
+-virVMOperationTypeFromString;
+-virVMOperationTypeToString;
+ vpAssociatePortProfileId;
+ vpDisassociatePortProfileId;
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 310d8f4..3c1c823 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -504,6 +504,11 @@ virLogStartup;
+ virLogUnlock;
+
+
++# macvtap.h
++virVMOperationTypeFromString;
++virVMOperationTypeToString;
++
++
+ # memory.h
+ virAlloc;
+ virAllocN;
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index fcb90a3..aa3478f 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -11879,6 +11879,7 @@ cleanup:
+ return ret;
+ }
+
++#if WITH_MACVTAP
+ static void
+ qemudVPAssociatePortProfiles(virDomainDefPtr def) {
+ int i;
+@@ -11913,6 +11914,7 @@ err_exit:
+ }
+ }
+ }
++#endif /* WITH_MACVTAP */
+
+ /* Finish is the third and final step, and it runs on the destination host. */
+ static virDomainPtr
+@@ -11974,7 +11976,9 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
+ goto cleanup;
+ }
+
++#if WITH_MACVTAP
+ qemudVPAssociatePortProfiles(vm->def);
++#endif /* WITH_MACVTAP */
+
+ if (flags & VIR_MIGRATE_PERSIST_DEST) {
+ if (vm->persistent)
+diff --git a/src/util/macvtap.h b/src/util/macvtap.h
+index 389d1fd..3ae2c24 100644
+--- a/src/util/macvtap.h
++++ b/src/util/macvtap.h
+@@ -57,11 +57,6 @@ struct _virVirtualPortProfileParams {
+ } u;
+ };
+
+-
+-# if defined(WITH_MACVTAP)
+-
+-# include "internal.h"
+-
+ enum virVMOperationType {
+ VIR_VM_OP_CREATE,
+ VIR_VM_OP_SAVE,
+@@ -75,6 +70,10 @@ enum virVMOperationType {
+ VIR_VM_OP_LAST
+ };
+
++# if WITH_MACVTAP
++
++# include "internal.h"
++
+ int openMacvtapTap(const char *ifname,
+ const unsigned char *macaddress,
+ const char *linkdev,
+@@ -90,11 +89,9 @@ void delMacvtap(const char *ifname,
+ const char *linkdev,
+ virVirtualPortProfileParamsPtr virtPortProfile);
+
+-# endif /* WITH_MACVTAP */
+-
+-# define MACVTAP_MODE_PRIVATE_STR "private"
+-# define MACVTAP_MODE_VEPA_STR "vepa"
+-# define MACVTAP_MODE_BRIDGE_STR "bridge"
++# define MACVTAP_MODE_PRIVATE_STR "private"
++# define MACVTAP_MODE_VEPA_STR "vepa"
++# define MACVTAP_MODE_BRIDGE_STR "bridge"
+
+ int vpAssociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+@@ -109,6 +106,8 @@ int vpDisassociatePortProfileId(const char *macvtap_ifname,
+ const virVirtualPortProfileParamsPtr virtPort,
+ enum virVMOperationType vmOp);
+
++# endif /* WITH_MACVTAP */
++
+ VIR_ENUM_DECL(virVirtualPort)
+ VIR_ENUM_DECL(virVMOperation)
+
+--
+1.7.0.4
+
diff --git a/main/libvirt/libvirt.confd b/main/libvirt/libvirt.confd
new file mode 100644
index 0000000000..d51bdb99d1
--- /dev/null
+++ b/main/libvirt/libvirt.confd
@@ -0,0 +1,27 @@
+# /etc/conf.d/libvirtd
+
+# You may want to add '--listen' to have libvirtd listen for tcp/ip connections
+# if you want to use libvirt for remote control
+
+# Please consult 'libvirtd --help' for more options
+
+#LIBVIRTD_OPTS="--listen"
+
+# Valid options:
+# * shutdown - Sends an ACPI shutdown (think when you tap the power button
+# on your machine and it begins a graceful shutdown). If your
+# VM ignores this, it will have the power yanked out from under
+# it in LIBVIRTD_KVM_SHUTDOWN_MAXWAIT seconds.
+# * managedsave - Performs a state save external to the VM. qemu-kvm will stop
+# stop the CPU and save off all state to a separate file. When
+# the machine is started again, it will resume like nothing ever
+# happened. This is guarenteed to always successfully stop your
+# machine and restart it. However it may take some time to finish.
+# * none - No attempts will be made to stop any VMs. If you are restarting your
+# machine the qemu-kvm process will be simply killed, which may result
+# in your VMs having disk corruption.
+LIBVIRTD_KVM_SHUTDOWN="managedsave"
+
+# Timeout in seconds until stopping libvirtd and "pulling the plug" on the
+# remaining VM's still in a running state
+#LIBVIRTD_KVM_SHUTDOWN_MAXWAIT="500"
diff --git a/main/libvirt/libvirt.initd b/main/libvirt/libvirt.initd
new file mode 100644
index 0000000000..d0b9d34a01
--- /dev/null
+++ b/main/libvirt/libvirt.initd
@@ -0,0 +1,87 @@
+#!/sbin/runscript
+
+opts="start stop status reload restart"
+
+depend() {
+ need net
+ after firewall
+}
+
+libvirtd_virsh() {
+ # Silence errors because virsh always throws an error about
+ # not finding the hypervisor version when connecting to libvirtd
+ LC_ALL=C virsh -c qemu:///system "$@" 2>/dev/null
+}
+
+libvirtd_dom_list() {
+ # Make sure that it wouldn't be confused if the domain name
+ # contains the word running.
+ libvirtd_virsh list | awk '$3 == "running" { print $1 }'
+}
+
+libvirtd_dom_count() {
+ # Make sure that it wouldn't be confused if the domain name
+ # contains the word running.
+ libvirtd_virsh list | awk 'BEGIN { count = 0 } \
+ $3 == "running" { count++ } \
+ END { print count }'
+}
+
+start() {
+ ebegin "Starting libvirtd"
+ start-stop-daemon --start \
+ --env KRB5_KTNAME=/etc/libvirt/krb5.tab \
+ --exec /usr/sbin/libvirtd -- -d ${LIBVIRTD_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping libvirtd"
+ # try to shutdown all (KVM/Qemu) domains
+ DOM_COUNT="$(libvirtd_dom_count)"
+ if [ "${LIBVIRTD_KVM_SHUTDOWN}" != "none" ] \
+ && [ "${DOM_COUNT}" != "0" ] ; then
+
+ einfo " Shutting down domain(s):"
+ for DOM_ID in $(libvirtd_dom_list) ; do
+ NAME="$(libvirtd_virsh domname ${DOM_ID} | head -n 1)"
+ einfo " ${NAME}"
+ libvirtd_virsh ${LIBVIRTD_KVM_SHUTDOWN} ${DOM_ID} > /dev/null
+ done
+
+ if [ -n "${LIBVIRTD_KVM_SHUTDOWN_MAXWAIT}" ] ; then
+ COUNTER="${LIBVIRTD_KVM_SHUTDOWN_MAXWAIT}"
+ else
+ COUNTER=500
+ fi
+
+ if [ "${LIBVIRTD_KVM_SHUTDOWN}" = "shutdown" ]; then
+ einfo " Waiting ${COUNTER} seconds while domains shutdown ..."
+ DOM_COUNT="$(libvirtd_dom_count)"
+ while [ ${DOM_COUNT} -gt 0 ] && [ ${COUNTER} -gt 0 ] ; do
+ DOM_COUNT="$(libvirtd_dom_count)"
+ sleep 1
+ COUNTER=$((${COUNTER} - 1))
+ echo -n "."
+ done
+ fi
+
+ DOM_COUNT="$(libvirtd_dom_count)"
+ if [ "${DOM_COUNT}" != "0" ] ; then
+ eerror " !!! Some guests are still running, stopping anyways"
+ fi
+
+ fi
+ start-stop-daemon --stop --quiet --exec /usr/sbin/libvirtd --pidfile=/var/run/libvirtd.pid
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading libvirtd without shutting down your VMs"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/libvirtd --pidfile=/var/run/libvirtd.pid
+ if [ $? -ne 0 ]; then
+ eend $?
+ fi
+ start-stop-daemon --start --quiet --exec /usr/sbin/libvirtd -- -d ${LIBVIRTD_OPTS}
+ eend $?
+}
diff --git a/main/libvorbis/APKBUILD b/main/libvorbis/APKBUILD
new file mode 100644
index 0000000000..bfe65a02e7
--- /dev/null
+++ b/main/libvorbis/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libvorbis
+pkgver=1.3.2
+pkgrel=2
+pkgdesc="Vorbis codec library"
+url="http://www.xiph.org/ogg/vorbis/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="libogg-dev"
+#source="http://people.xiph.org/~giles/2008/$pkgname-$pkgver.tar.gz"
+source="http://downloads.xiph.org/releases/vorbis/libvorbis-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="c870b9bd5858a0ecb5275c14486d9554 libvorbis-1.3.2.tar.gz"
diff --git a/main/libvpx/APKBUILD b/main/libvpx/APKBUILD
new file mode 100644
index 0000000000..4391f06f50
--- /dev/null
+++ b/main/libvpx/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libvpx
+pkgver=0.9.6
+pkgrel=1
+pkgdesc="Library for the vp8 codec"
+url="http://www.webmproject.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="coreutils yasm bash perl"
+install=
+subpackages="$pkgname-dev"
+source="http://webm.googlecode.com/files/libvpx-v$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-v$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure \
+ --enable-pic \
+ --enable-libs \
+ --enable-runtime-cpu-detect \
+ --enable-vp8 \
+ --disable-install-srcs \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DIST_DIR="$pkgdir"/usr install
+ chmod 644 "$pkgdir"/usr/include/vpx/*.h
+}
+
+md5sums="383f3f07a76099682abb43f79b692b72 libvpx-v0.9.6.tar.bz2"
diff --git a/main/libvpx/git100617.patch b/main/libvpx/git100617.patch
new file mode 100644
index 0000000000..3c5eece135
--- /dev/null
+++ b/main/libvpx/git100617.patch
@@ -0,0 +1,27956 @@
+diff --git a/AUTHORS b/AUTHORS
+index 9686ac1..4ab6881 100644
+--- a/AUTHORS
++++ b/AUTHORS
+@@ -2,3 +2,6 @@
+ # Name or Organization <email address>
+
+ Google Inc.
++The Mozilla Foundation
++Timothy B. Terriberry <tterriberry@mozilla.com>
++The Xiph.Org Foundation
+diff --git a/LICENSE b/LICENSE
+index 6b0e867..7a6f995 100644
+--- a/LICENSE
++++ b/LICENSE
+@@ -1,22 +1,20 @@
+-Copyright (c) 2010, Google, Inc.
+-
+-All rights reserved.
++Copyright (c) 2010, Google Inc. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+-modification, are permitted provided that the following conditions
+-are met:
++modification, are permitted provided that the following conditions are
++met:
+
+-- Redistributions of source code must retain the above copyright
+- notice, this list of conditions and the following disclaimer.
++ * Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
+
+-- Redistributions in binary form must reproduce the above
+- copyright notice, this list of conditions and the following
+- disclaimer in the documentation and/or other materials provided
+- with the distribution.
++ * Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in
++ the documentation and/or other materials provided with the
++ distribution.
+
+-- Neither the name of Google nor the names of its contributors may
+- be used to endorse or promote products derived from this software
+- without specific prior written permission.
++ * Neither the name of Google nor the names of its contributors may
++ be used to endorse or promote products derived from this software
++ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+@@ -30,19 +28,3 @@ 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.
+
+-Subject to the terms and conditions of the above License, Google
+-hereby grants to You a perpetual, worldwide, non-exclusive,
+-no-charge, royalty-free, irrevocable (except as stated in this
+-section) patent license to make, have made, use, offer to sell, sell,
+-import, and otherwise transfer this implementation of VP8, where such
+-license applies only to those patent claims, both currently owned by
+-Google and acquired in the future, licensable by Google that are
+-necessarily infringed by this implementation of VP8. If You or your
+-agent or exclusive licensee institute or order or agree to the
+-institution of patent litigation against any entity (including a
+-cross-claim or counterclaim in a lawsuit) alleging that this
+-implementation of VP8 or any code incorporated within this
+-implementation of VP8 constitutes direct or contributory patent
+-infringement, or inducement of patent infringement, then any rights
+-granted to You under this License for this implementation of VP8
+-shall terminate as of the date such litigation is filed.
+diff --git a/PATENTS b/PATENTS
+new file mode 100644
+index 0000000..4414d83
+--- /dev/null
++++ b/PATENTS
+@@ -0,0 +1,22 @@
++Additional IP Rights Grant (Patents)
++
++"This implementation" means the copyrightable works distributed by
++Google as part of the WebM Project.
++
++Google hereby grants to you a perpetual, worldwide, non-exclusive,
++no-charge, royalty-free, irrevocable (except as stated in this section)
++patent license to make, have made, use, offer to sell, sell, import,
++transfer, and otherwise run, modify and propagate the contents of this
++implementation of VP8, where such license applies only to those patent
++claims, both currently owned by Google and acquired in the future,
++licensable by Google that are necessarily infringed by this
++implementation of VP8. This grant does not include claims that would be
++infringed only as a consequence of further modification of this
++implementation. If you or your agent or exclusive licensee institute or
++order or agree to the institution of patent litigation against any
++entity (including a cross-claim or counterclaim in a lawsuit) alleging
++that this implementation of VP8 or any code incorporated within this
++implementation of VP8 constitutes direct or contributory patent
++infringement, or inducement of patent infringement, then any patent
++rights granted to you under this License for this implementation of VP8
++shall terminate as of the date such litigation is filed.
+diff --git a/args.c b/args.c
+index f2ad697..5fd0466 100644
+--- a/args.c
++++ b/args.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/args.h b/args.h
+index c063f53..f1ec6c0 100644
+--- a/args.h
++++ b/args.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/build/.gitattributes b/build/.gitattributes
+new file mode 100644
+index 0000000..03db79b
+--- /dev/null
++++ b/build/.gitattributes
+@@ -0,0 +1,2 @@
++*-vs8/*.rules -crlf
++*-msvs/*.rules -crlf
+diff --git a/build/arm-wince-vs8/.gitattributes b/build/arm-wince-vs8/.gitattributes
+deleted file mode 100644
+index be1eeb9..0000000
+--- a/build/arm-wince-vs8/.gitattributes
++++ /dev/null
+@@ -1 +0,0 @@
+-*.rules -crlf
+diff --git a/build/arm-wince-vs8/obj_int_extract.bat b/build/arm-wince-vs8/obj_int_extract.bat
+index e58bdd6..3069160 100644
+--- a/build/arm-wince-vs8/obj_int_extract.bat
++++ b/build/arm-wince-vs8/obj_int_extract.bat
+@@ -1,12 +1,13 @@
+ @echo off
+ REM Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ REM
+-REM Use of this source code is governed by a BSD-style license and patent
+-REM grant that can be found in the LICENSE file in the root of the source
+-REM tree. All contributing project authors may be found in the AUTHORS
+-REM file in the root of the source tree.
++REM Use of this source code is governed by a BSD-style license
++REM that can be found in the LICENSE file in the root of the source
++REM tree. An additional intellectual property rights grant can be found
++REM in the file PATENTS. All contributing project authors may
++REM be found in the AUTHORS file in the root of the source tree.
+ echo on
+
+
+-cl /I ".\\" /I "..\vp6_decoder_sdk" /I "..\vp6_decoder_sdk\vpx_ports" /D "NDEBUG" /D "_WIN32_WCE=0x420" /D "UNDER_CE" /D "WIN32_PLATFORM_PSPC" /D "WINCE" /D "_LIB" /D "ARM" /D "_ARM_" /D "_UNICODE" /D "UNICODE" /D "HAVE_CONFIG_H" /FD /EHsc /MT /GS- /fp:fast /GR- /Fo"Pocket_PC_2003__ARMV4_\%1/" /Fd"Pocket_PC_2003__ARMV4_\%1/vc80.pdb" /W3 /nologo /c /TC ..\vp6_decoder_sdk\vp6_decoder\algo\common\arm\dec_asm_offsets_arm.c
++cl /I ".\\" /I "..\vp6_decoder_sdk" /I "..\vp6_decoder_sdk\vpx_ports" /D "NDEBUG" /D "_WIN32_WCE=0x420" /D "UNDER_CE" /D "WIN32_PLATFORM_PSPC" /D "WINCE" /D "_LIB" /D "ARM" /D "_ARM_" /D "_UNICODE" /D "UNICODE" /FD /EHsc /MT /GS- /fp:fast /GR- /Fo"Pocket_PC_2003__ARMV4_\%1/" /Fd"Pocket_PC_2003__ARMV4_\%1/vc80.pdb" /W3 /nologo /c /TC ..\vp6_decoder_sdk\vp6_decoder\algo\common\arm\dec_asm_offsets_arm.c
+ obj_int_extract.exe rvds "Pocket_PC_2003__ARMV4_\%1/dec_asm_offsets_arm.obj"
+diff --git a/build/make/Makefile b/build/make/Makefile
+index 412629e..4f7df43 100755
+--- a/build/make/Makefile
++++ b/build/make/Makefile
+@@ -1,10 +1,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+-##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++##
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+@@ -18,6 +19,7 @@ ifeq ($(target),)
+ done
+ all: .DEFAULT
+ clean:: .DEFAULT
++install:: .DEFAULT
+
+
+ # Note: md5sum is not installed on OS X, but openssl is. Openssl may not be
+@@ -29,7 +31,7 @@ md5sum := $(firstword $(wildcard \
+ md5sum := $(if $(filter %openssl,$(md5sum)),$(md5sum) dgst -md5,$(md5sum))
+
+ TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
+-install:
++dist:
+ @for t in $(ALL_TARGETS); do \
+ $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\
+ done
+@@ -37,7 +39,7 @@ install:
+ @if [ -d "$(DIST_DIR)/src" ]; then \
+ mkdir -p "$(DIST_DIR)/build"; \
+ cd "$(DIST_DIR)/build"; \
+- if [ $(TGT_CC) = "rvct" ] ; then \
++ if [ "$(TGT_CC)" = "rvct" ] ; then \
+ echo "../src/configure --target=$(TOOLCHAIN) --libc=$(ALT_LIBC)"; \
+ ../src/configure --target=$(TOOLCHAIN) --libc=$(ALT_LIBC); \
+ else \
+@@ -94,10 +96,10 @@ clean::
+ rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.s.o=.asm.s)
+ rm -f $(CLEAN-OBJS)
+
++.PHONY: dist
++dist:
+ .PHONY: install
+-install:
+-.PHONY: install-helper
+-install-helper:
++install::
+
+ $(BUILD_PFX)%.c.d: %.c
+ $(if $(quiet),@echo " [DEP] $@")
+@@ -218,6 +220,20 @@ $(1):
+ $(qexec)$$(AR) $$(ARFLAGS) $$@ $$?
+ endef
+
++define so_template
++# Not using a pattern rule here because we don't want to generate empty
++# archives when they are listed as a dependency in files not responsible
++# for creating them.
++#
++# This needs further abstraction for dealing with non-GNU linkers.
++$(1):
++ $(if $(quiet),@echo " [LD] $$@")
++ $(qexec)$$(LD) -shared $$(LDFLAGS) \
++ -Wl,--no-undefined -Wl,-soname,$$(SONAME) \
++ -Wl,--version-script,$$(SO_VERSION_SCRIPT) -o $$@ \
++ $$(filter %.o,$$?) $$(extralibs)
++endef
++
+ define lipo_lib_template
+ $(1): $(addsuffix /$(1),$(FAT_ARCHS))
+ $(if $(quiet),@echo " [LIPO] $$@")
+@@ -254,6 +270,9 @@ DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,DOCS)
+ @touch $@
+
+ INSTALL-DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,INSTALL-DOCS)
++ifeq ($(MAKECMDGOALS),dist)
++INSTALL-DOCS+=$(call cond_enabled,CONFIG_INSTALL_DOCS,DIST-DOCS)
++endif
+ .install-docs: .docs $(addprefix $(DIST_DIR)/,$(INSTALL-DOCS))
+ @touch $@
+
+@@ -265,6 +284,9 @@ BINS=$(call enabled,BINS)
+ @touch $@
+
+ INSTALL-BINS=$(call cond_enabled,CONFIG_INSTALL_BINS,INSTALL-BINS)
++ifeq ($(MAKECMDGOALS),dist)
++INSTALL-BINS+=$(call cond_enabled,CONFIG_INSTALL_BINS,DIST-BINS)
++endif
+ .install-bins: .bins $(addprefix $(DIST_DIR)/,$(INSTALL-BINS))
+ @touch $@
+
+@@ -275,8 +297,12 @@ LIBS=$(call enabled,LIBS)
+ .libs: $(LIBS)
+ @touch $@
+ $(foreach lib,$(filter %_g.a,$(LIBS)),$(eval $(call archive_template,$(lib))))
++$(foreach lib,$(filter %so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH),$(LIBS)),$(eval $(call so_template,$(lib))))
+
+ INSTALL-LIBS=$(call cond_enabled,CONFIG_INSTALL_LIBS,INSTALL-LIBS)
++ifeq ($(MAKECMDGOALS),dist)
++INSTALL-LIBS+=$(call cond_enabled,CONFIG_INSTALL_LIBS,DIST-LIBS)
++endif
+ .install-libs: .libs $(addprefix $(DIST_DIR)/,$(INSTALL-LIBS))
+ @touch $@
+
+@@ -289,6 +315,9 @@ PROJECTS=$(call enabled,PROJECTS)
+ @touch $@
+
+ INSTALL-PROJECTS=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,INSTALL-PROJECTS)
++ifeq ($(MAKECMDGOALS),dist)
++INSTALL-PROJECTS+=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,DIST-PROJECTS)
++endif
+ .install-projects: .projects $(addprefix $(DIST_DIR)/,$(INSTALL-PROJECTS))
+ @touch $@
+
+@@ -296,26 +325,29 @@ clean::
+ rm -f .projects .install-projects $(PROJECTS)
+ endif
+
+-# If there are any source files to be installed, then include the build
++# If there are any source files to be distributed, then include the build
+ # system too.
+-ifneq ($(call enabled,INSTALL-SRCS),)
+- INSTALL-SRCS-yes += configure
+- INSTALL-SRCS-yes += build/make/configure.sh
+- INSTALL-SRCS-yes += build/make/gen_asm_deps.sh
+- INSTALL-SRCS-yes += build/make/Makefile
+- INSTALL-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_def.sh
+- INSTALL-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_proj.sh
+- INSTALL-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_sln.sh
+- INSTALL-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
++ifneq ($(call enabled,DIST-SRCS),)
++ DIST-SRCS-yes += configure
++ DIST-SRCS-yes += build/make/configure.sh
++ DIST-SRCS-yes += build/make/gen_asm_deps.sh
++ DIST-SRCS-yes += build/make/Makefile
++ DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_def.sh
++ DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_proj.sh
++ DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_sln.sh
++ DIST-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
+ #
+ # This isn't really ARCH_ARM dependent, it's dependant on whether we're
+ # using assembly code or not (CONFIG_OPTIMIZATIONS maybe). Just use
+ # this for now.
+- INSTALL-SRCS-$(ARCH_ARM) += build/make/obj_int_extract.c
+- INSTALL-SRCS-$(ARCH_ARM) += build/make/ads2gas.pl
+- INSTALL-SRCS-yes += $(target:-$(TOOLCHAIN)=).mk
++ DIST-SRCS-$(ARCH_ARM) += build/make/obj_int_extract.c
++ DIST-SRCS-$(ARCH_ARM) += build/make/ads2gas.pl
++ DIST-SRCS-yes += $(target:-$(TOOLCHAIN)=).mk
+ endif
+ INSTALL-SRCS := $(call cond_enabled,CONFIG_INSTALL_SRCS,INSTALL-SRCS)
++ifeq ($(MAKECMDGOALS),dist)
++INSTALL-SRCS += $(call cond_enabled,CONFIG_INSTALL_SRCS,DIST-SRCS)
++endif
+ .install-srcs: $(addprefix $(DIST_DIR)/src/,$(INSTALL-SRCS))
+ @touch $@
+
+@@ -329,7 +361,8 @@ endif
+ BUILD_TARGETS += .docs .libs .bins
+ INSTALL_TARGETS += .install-docs .install-srcs .install-libs .install-bins
+ all-$(target): $(BUILD_TARGETS)
+-install: $(INSTALL_TARGETS)
++install:: $(INSTALL_TARGETS)
++dist: $(INSTALL_TARGETS)
+
+ #
+ # Development helper targets
+diff --git a/build/make/ads2gas.pl b/build/make/ads2gas.pl
+index 6fcba84..bd5e772 100755
+--- a/build/make/ads2gas.pl
++++ b/build/make/ads2gas.pl
+@@ -1,11 +1,12 @@
+ #!/usr/bin/perl
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+-##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++##
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/build/make/ads2gas_apple.pl b/build/make/ads2gas_apple.pl
+index 569c3e7..7a32445 100755
+--- a/build/make/ads2gas_apple.pl
++++ b/build/make/ads2gas_apple.pl
+@@ -1,11 +1,12 @@
+ #!/usr/bin/env perl
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+-##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++##
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/build/make/armlink_adapter.sh b/build/make/armlink_adapter.sh
+index dcaa82c..25fb627 100755
+--- a/build/make/armlink_adapter.sh
++++ b/build/make/armlink_adapter.sh
+@@ -2,10 +2,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/build/make/configure.sh b/build/make/configure.sh
+index ed3a34f..05e550f 100755
+--- a/build/make/configure.sh
++++ b/build/make/configure.sh
+@@ -1,13 +1,13 @@
+ #!/bin/bash
+ ##
+-## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++## configure.sh
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## This script is sourced by the main configure script and contains
++## utility functions and other common bits that aren't strictly libvpx
++## related.
++##
++## This build system is based in part on the FFmpeg configure script.
+ ##
+-
+
+
+ #
+@@ -120,8 +120,8 @@ EOF
+
+ show_targets() {
+ while [ -n "$*" ]; do
+- if [ "${1%%-*}" == "${2%%-*}" ]; then
+- if [ "${2%%-*}" == "${3%%-*}" ]; then
++ if [ "${1%%-*}" = "${2%%-*}" ]; then
++ if [ "${2%%-*}" = "${3%%-*}" ]; then
+ printf " %-24s %-24s %-24s\n" "$1" "$2" "$3"
+ shift; shift; shift
+ else
+@@ -348,7 +348,6 @@ true
+ }
+
+ write_common_target_config_mk() {
+- [ -n "$2" ] && local have_config_h="-DHAVE_CONFIG_H=\"${2##*/}\""
+ local CC=${CC}
+ enabled ccache && CC="ccache ${CC}"
+
+@@ -367,7 +366,7 @@ AS=${AS}
+ STRIP=${STRIP}
+ NM=${NM}
+
+-CFLAGS = ${CFLAGS} ${have_config_h}
++CFLAGS = ${CFLAGS}
+ ARFLAGS = -rus\$(if \$(quiet),c,v)
+ LDFLAGS = ${LDFLAGS}
+ ASFLAGS = ${ASFLAGS}
+@@ -443,7 +442,13 @@ process_common_cmdline() {
+ disable builtin_libc
+ alt_libc="${optval}"
+ ;;
+- --libc)
++ --prefix=*)
++ prefix="${optval}"
++ ;;
++ --libdir=*)
++ libdir="${optval}"
++ ;;
++ --libc|--prefix|--libdir)
+ die "Option ${opt} requires argument"
+ ;;
+ --help|-h) show_help
+@@ -464,6 +469,18 @@ process_cmdline() {
+ done
+ }
+
++
++post_process_common_cmdline() {
++ prefix="${prefix:-/usr/local}"
++ prefix="${prefix%/}"
++ libdir="${libdir:-${prefix}/lib}"
++ libdir="${libdir%/}"
++ if [ "${libdir#${prefix}}" = "${libdir}" ]; then
++ die "Libdir ${libdir} must be a subdirectory of ${prefix}"
++ fi
++}
++
++
+ post_process_cmdline() {
+ true;
+ }
+@@ -479,6 +496,42 @@ setup_gnu_toolchain() {
+ }
+
+ process_common_toolchain() {
++ if [ -z "$toolchain" ]; then
++ gcctarget="$(gcc -dumpmachine 2> /dev/null)"
++
++ # detect tgt_isa
++ case "$gcctarget" in
++ *x86_64*|*amd64*)
++ tgt_isa=x86_64
++ ;;
++ *i[3456]86*)
++ tgt_isa=x86
++ ;;
++ esac
++
++ # detect tgt_os
++ case "$gcctarget" in
++ *darwin8*)
++ tgt_isa=universal
++ tgt_os=darwin8
++ ;;
++ *darwin9*)
++ tgt_isa=universal
++ tgt_os=darwin9
++ ;;
++ *mingw32*|*cygwin*)
++ tgt_os=win32
++ ;;
++ *linux*|*bsd*)
++ tgt_os=linux
++ ;;
++ esac
++
++ if [ -n "$tgt_isa" ] && [ -n "$tgt_os" ]; then
++ toolchain=${tgt_isa}-${tgt_os}-gcc
++ fi
++ fi
++
+ toolchain=${toolchain:-generic-gnu}
+
+ is_in ${toolchain} ${all_platforms} || enabled force_toolchain \
+@@ -781,6 +834,7 @@ process_common_toolchain() {
+ ;;
+ universal*|*-gcc|generic-gnu)
+ link_with_cc=gcc
++ enable gcc
+ setup_gnu_toolchain
+ ;;
+ esac
+@@ -844,8 +898,8 @@ process_toolchain() {
+ }
+
+ print_config_mk() {
+- prefix=$1
+- makefile=$2
++ local prefix=$1
++ local makefile=$2
+ shift 2
+ for cfg; do
+ upname="`toupper $cfg`"
+@@ -856,8 +910,8 @@ print_config_mk() {
+ }
+
+ print_config_h() {
+- prefix=$1
+- header=$2
++ local prefix=$1
++ local header=$2
+ shift 2
+ for cfg; do
+ upname="`toupper $cfg`"
+@@ -888,6 +942,7 @@ process() {
+ else
+ echo "# ${self} $@" > ${logfile}
+ fi
++ post_process_common_cmdline
+ post_process_cmdline
+ process_toolchain
+ process_detect
+diff --git a/build/make/gen_asm_deps.sh b/build/make/gen_asm_deps.sh
+index c1118e1..2c972e5 100755
+--- a/build/make/gen_asm_deps.sh
++++ b/build/make/gen_asm_deps.sh
+@@ -2,10 +2,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/build/make/gen_msvs_def.sh b/build/make/gen_msvs_def.sh
+index 68b2406..b5c54fd 100755
+--- a/build/make/gen_msvs_def.sh
++++ b/build/make/gen_msvs_def.sh
+@@ -2,10 +2,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/build/make/gen_msvs_proj.sh b/build/make/gen_msvs_proj.sh
+index eb482a4..d94ae4d 100755
+--- a/build/make/gen_msvs_proj.sh
++++ b/build/make/gen_msvs_proj.sh
+@@ -2,15 +2,17 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+ self=$0
+ self_basename=${self##*/}
++self_dirname=$(dirname "$0")
+ EOL=$'\n'
+
+ show_help() {
+@@ -291,8 +293,8 @@ case "$target" in
+ x86*)
+ platforms[0]="Win32"
+ # these are only used by vs7
+- asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} \$(InputPath)"
+- asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} \$(InputPath)"
++ asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
++ asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
+ ;;
+ arm*|iwmmx*)
+ case "${name}" in
+@@ -342,19 +344,19 @@ generate_vcproj() {
+
+ open_tag ToolFiles
+ case "$target" in
+- x86*) $uses_asm && tag DefaultToolFile FileName="yasm.rules"
++ x86*) $uses_asm && tag ToolFile RelativePath="$self_dirname/../x86-msvs/yasm.rules"
+ ;;
+ arm*|iwmmx*)
+ if [ "$name" == "vpx_decoder" ];then
+ case "$target" in
+ armv5*)
+- tag DefaultToolFile FileName="armasmv5.rules"
++ tag ToolFile RelativePath="$self_dirname/../arm-wince-vs8/armasmv5.rules"
+ ;;
+ armv6*)
+- tag DefaultToolFile FileName="armasmv6.rules"
++ tag ToolFile RelativePath="$self_dirname/../arm-wince-vs8/armasmv6.rules"
+ ;;
+ iwmmxt*)
+- tag DefaultToolFile FileName="armasmxscale.rules"
++ tag ToolFile RelativePath="$self_dirname/../arm-wince-vs8/armasmxscale.rules"
+ ;;
+ esac
+ fi
+@@ -385,7 +387,7 @@ generate_vcproj() {
+ ExecutionBucket="7" \
+ Optimization="0" \
+ AdditionalIncludeDirectories="$incs" \
+- PreprocessorDefinitions="_DEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_CONFIG_H" \
++ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;" \
+ MinimalRebuild="true" \
+ RuntimeLibrary="1" \
+ BufferSecurityCheck="false" \
+@@ -404,7 +406,7 @@ generate_vcproj() {
+ ExecutionBucket="7" \
+ Optimization="0" \
+ AdditionalIncludeDirectories="$incs" \
+- PreprocessorDefinitions="_DEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;DEBUG;_CONSOLE;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_CONFIG_H" \
++ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;DEBUG;_CONSOLE;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;" \
+ MinimalRebuild="true" \
+ RuntimeLibrary="1" \
+ BufferSecurityCheck="false" \
+@@ -544,7 +546,7 @@ generate_vcproj() {
+ Optimization="2" \
+ FavorSizeOrSpeed="1" \
+ AdditionalIncludeDirectories="$incs" \
+- PreprocessorDefinitions="NDEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;_LIB;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_CONFIG_H" \
++ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;_LIB;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;" \
+ RuntimeLibrary="0" \
+ BufferSecurityCheck="false" \
+ UsePrecompiledHeader="0" \
+@@ -563,7 +565,7 @@ generate_vcproj() {
+ Optimization="2" \
+ FavorSizeOrSpeed="1" \
+ AdditionalIncludeDirectories="$incs" \
+- PreprocessorDefinitions="NDEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;_CONSOLE;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_CONFIG_H" \
++ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;_CONSOLE;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;" \
+ RuntimeLibrary="0" \
+ BufferSecurityCheck="false" \
+ UsePrecompiledHeader="0" \
+diff --git a/build/make/gen_msvs_sln.sh b/build/make/gen_msvs_sln.sh
+index b670ec5..ef425f5 100755
+--- a/build/make/gen_msvs_sln.sh
++++ b/build/make/gen_msvs_sln.sh
+@@ -2,10 +2,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/build/make/obj_int_extract.c b/build/make/obj_int_extract.c
+index cef14e7..0f64e89 100644
+--- a/build/make/obj_int_extract.c
++++ b/build/make/obj_int_extract.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -16,7 +17,7 @@
+ #if defined(_MSC_VER)
+ #include <io.h>
+ #include <share.h>
+-#include "vpx_ports/vpx_integer.h"
++#include "vpx/vpx_integer.h"
+ #else
+ #include <stdint.h>
+ #include <unistd.h>
+diff --git a/build/make/version.sh b/build/make/version.sh
+index 2bda701..81682d6 100755
+--- a/build/make/version.sh
++++ b/build/make/version.sh
+@@ -2,10 +2,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/build/x86-msvs/yasm.rules b/build/x86-msvs/yasm.rules
+new file mode 100644
+index 0000000..ee1fefb
+--- /dev/null
++++ b/build/x86-msvs/yasm.rules
+@@ -0,0 +1,115 @@
++<?xml version="1.0" encoding="utf-8"?>
++<VisualStudioToolFile
++ Name="Yasm"
++ Version="8.00"
++ >
++ <Rules>
++ <CustomBuildRule
++ Name="YASM"
++ DisplayName="Yasm Assembler"
++ CommandLine="yasm -Xvc -f $(PlatformName) [AllOptions] [AdditionalOptions] [Inputs]"
++ Outputs="[$ObjectFileName]"
++ FileExtensions="*.asm"
++ ExecutionDescription="Assembling $(InputFileName)"
++ ShowOnlyRuleProperties="false"
++ >
++ <Properties>
++ <StringProperty
++ Name="Defines"
++ DisplayName="Definitions"
++ Category="Pre-Defined Symbols"
++ Description="Specify pre-defined symbols (&apos;symbol&apos; or &apos;symbol = value&apos;) "
++ Switch="-D [value]"
++ Delimited="true"
++ Inheritable="true"
++ />
++ <StringProperty
++ Name="IncludePaths"
++ DisplayName="Include Paths"
++ Category="Configuration"
++ Description="Set the paths for any additional include files"
++ Switch="-I [value]"
++ Delimited="true"
++ Inheritable="true"
++ />
++ <StringProperty
++ Name="UnDefines"
++ DisplayName="Remove Definitions"
++ Category="Pre-Defined Symbols"
++ Description="Remove pre-defined symbols "
++ Switch="-U [value]"
++ Delimited="true"
++ Inheritable="true"
++ />
++ <StringProperty
++ Name="ObjectFileName"
++ DisplayName="Object File Name"
++ Category="Output"
++ Description="Select the output file name"
++ Switch="-o [value]"
++ DefaultValue="$(IntDir)\$(InputName).obj"
++ />
++ <StringProperty
++ Name="ListFileName"
++ DisplayName="List File Name"
++ Category="Output"
++ Description="Select an output listing by setting its file name"
++ Switch="-l [value]"
++ />
++ <StringProperty
++ Name="PreIncludeFile"
++ DisplayName="Pre Include File"
++ Category="Configuration"
++ Description="Select a pre-included file by setting its name"
++ Switch="-P [value]"
++ />
++ <BooleanProperty
++ Name="Debug"
++ DisplayName="Debug Information"
++ Category="Output"
++ Description="Generate debugging information"
++ Switch="-g cv8"
++ />
++ <EnumProperty
++ Name="PreProc"
++ DisplayName="Pre-Processor"
++ Category="Configuration"
++ Description="Select the pre-processor (&apos;nasm&apos; or &apos;raw&apos;)"
++ >
++ <Values>
++ <EnumValue
++ Value="0"
++ Switch="-rnasm"
++ DisplayName="Nasm "
++ />
++ <EnumValue
++ Value="1"
++ Switch="-rraw"
++ DisplayName="Raw"
++ />
++ </Values>
++ </EnumProperty>
++ <EnumProperty
++ Name="Parser"
++ DisplayName="Parser"
++ Category="Configuration"
++ Description="Select the parser for Intel (&apos;nasm&apos;) or AT&amp;T ( &apos;gas&apos;) syntax"
++ >
++ <Values>
++ <EnumValue
++ Value="0"
++ Switch="-pnasm"
++ DisplayName="Nasm"
++ />
++ <EnumValue
++ Value="1"
++ Switch="-pgas"
++ DisplayName="Gas"
++ />
++ </Values>
++ </EnumProperty>
++ </Properties>
++ </CustomBuildRule>
++ </Rules>
++</VisualStudioToolFile>
++
+diff --git a/configure b/configure
+index 3083343..9a3269a 100755
+--- a/configure
++++ b/configure
+@@ -1,13 +1,16 @@
+ #!/bin/bash
+ ##
+-## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++## configure
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## This script is the front-end to the build system. It provides a similar
++## interface to standard configure scripts with some extra bits for dealing
++## with toolchains that differ from the standard POSIX interface and
++## for extracting subsets of the source tree. In theory, reusable parts
++## of this script were intended to live in build/make/configure.sh,
++## but in practice, the line is pretty blurry.
++##
++## This build system is based in part on the FFmpeg configure script.
+ ##
+-
+
+ #source_path="`dirname \"$0\"`"
+ source_path=${0%/*}
+@@ -24,18 +27,17 @@ Advanced options:
+ supported by hardware [auto]
+ ${toggle_codec_srcs} in/exclude codec library source code
+ ${toggle_debug_libs} in/exclude debug version of libraries
+- ${toggle_eval_limit} enable limited evaluation build
+ ${toggle_md5} support for output of checksum data
+ ${toggle_static_msvcrt} use static MSVCRT (VS builds only)
+ ${toggle_vp8} VP8 codec support
+ ${toggle_psnr} output of PSNR data, if supported (encoders)
+ ${toggle_mem_tracker} track memory usage
+- ${toggle_eval_limit} decoder limitted to 500 frames
+ ${toggle_postproc} postprocessing
+ ${toggle_multithread} multithreaded encoding and decoding.
+ ${toggle_spatial_resampling} spatial sampling (scaling) support
+ ${toggle_realtime_only} enable this option while building for real-time encoding
+ ${toggle_runtime_cpu_detect} runtime cpu detection
++ ${toggle_shared} shared library support
+
+ Codecs:
+ Codecs can be selectively enabled or disabled individually, or by family:
+@@ -135,11 +137,12 @@ if [ ${doxy_major:-0} -ge 1 ]; then
+ [ $doxy_minor -eq 5 ] && [ $doxy_patch -ge 3 ] && enable doxygen
+ fi
+
+-# install everything, by default
++# install everything except the sources, by default. sources will have
++# to be enabled when doing dist builds, since that's no longer a common
++# case.
+ enabled doxygen && php -v >/dev/null 2>&1 && enable install_docs
+ enable install_bins
+ enable install_libs
+-enable install_srcs
+
+ enable optimizations
+ enable fast_unaligned #allow unaligned accesses, if supported by hw
+@@ -157,8 +160,8 @@ if ! enabled alt_tree_layout; then
+ [ -d ${source_path}/vp8 ] && CODECS="${CODECS} vp8_encoder vp8_decoder"
+ else
+ # customer environment
+-[ -f ${source_path}/../include/vp8cx.h ] && CODECS="${CODECS} vp8_encoder"
+-[ -f ${source_path}/../include/vp8dx.h ] && CODECS="${CODECS} vp8_decoder"
++[ -f ${source_path}/../include/vpx/vp8cx.h ] && CODECS="${CODECS} vp8_encoder"
++[ -f ${source_path}/../include/vpx/vp8dx.h ] && CODECS="${CODECS} vp8_decoder"
+
+ [ -f ${source_path}/../lib/*/*mt.lib ] && soft_enable static_msvcrt
+ fi
+@@ -225,7 +228,6 @@ CONFIG_LIST="
+ dequant_tokens
+ dc_recon
+ new_tokens
+- eval_limit
+ runtime_cpu_detect
+ postproc
+ postproc_generic
+@@ -238,6 +240,7 @@ CONFIG_LIST="
+ static_msvcrt
+ spatial_resampling
+ realtime_only
++ shared
+ "
+ CMDLINE_SELECT="
+ extra_warnings
+@@ -265,7 +268,6 @@ CMDLINE_SELECT="
+ dequant_tokens
+ dc_recon
+ new_tokens
+- eval_limit
+ postproc
+ postproc_generic
+ multithread
+@@ -276,6 +278,7 @@ CMDLINE_SELECT="
+ mem_tracker
+ spatial_resampling
+ realtime_only
++ shared
+ "
+
+ process_cmdline() {
+@@ -354,7 +357,6 @@ process_targets() {
+ enabled codec_srcs && DIST_DIR="${DIST_DIR}-src"
+ ! enabled postproc && DIST_DIR="${DIST_DIR}-nopost"
+ ! enabled multithread && DIST_DIR="${DIST_DIR}-nomt"
+- enabled eval_limit && DIST_DIR="${DIST_DIR}-eval"
+ ! enabled install_docs && DIST_DIR="${DIST_DIR}-nodocs"
+ DIST_DIR="${DIST_DIR}-${tgt_isa}-${tgt_os}"
+ case "${tgt_os}" in
+@@ -365,8 +367,26 @@ process_targets() {
+ if [ -f "${source_path}/build/make/version.sh" ]; then
+ local ver=`"$source_path/build/make/version.sh" --bare $source_path`
+ DIST_DIR="${DIST_DIR}-${ver}"
++ ver=${ver%%-*}
++ VERSION_PATCH=${ver##*.}
++ ver=${ver%.*}
++ VERSION_MINOR=${ver##*.}
++ ver=${ver#v}
++ VERSION_MAJOR=${ver%.*}
+ fi
+- enabled child || echo "DIST_DIR?=${DIST_DIR}" >> config.mk
++ enabled child || cat <<EOF >> config.mk
++ifeq (\$(MAKECMDGOALS),dist)
++DIST_DIR?=${DIST_DIR}
++else
++DIST_DIR?=\$(DESTDIR)${prefix}
++endif
++LIBSUBDIR=${libdir##${prefix}/}
++
++VERSION_MAJOR=${VERSION_MAJOR}
++VERSION_MINOR=${VERSION_MINOR}
++VERSION_PATCH=${VERSION_PATCH}
++
++EOF
+ enabled child || echo "CONFIGURE_ARGS?=${CONFIGURE_ARGS}" >> config.mk
+
+ #
+@@ -385,6 +405,12 @@ process_targets() {
+ }
+
+ process_detect() {
++ if enabled shared; then
++ # Can only build shared libs on a subset of platforms. Doing this check
++ # here rather than at option parse time because the target auto-detect
++ # magic happens after the command line has been parsed.
++ enabled linux || die "--enable-shared only supported on ELF for now"
++ fi
+ if [ -z "$CC" ]; then
+ echo "Bypassing toolchain for environment detection."
+ enable external_build
+@@ -419,7 +445,7 @@ EOF
+ check_header pthread.h
+ check_header sys/mman.h
+
+- check_header vpx_ports/vpx_integer.h -I${source_path} && enable vpx_ports
++ check_header vpx/vpx_integer.h -I${source_path} && enable vpx_ports
+ }
+
+ process_toolchain() {
+diff --git a/docs.mk b/docs.mk
+index 3e7b5cd..f60a482 100644
+--- a/docs.mk
++++ b/docs.mk
+@@ -1,10 +1,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+@@ -47,8 +48,8 @@ docs/html/index.html: doxyfile $(CODEC_DOX) $(TXT_DOX)
+ @doxygen $<
+ DOCS-yes += docs/html/index.html
+
+-INSTALL-DOCS-yes = $(wildcard docs/html/*)
+-INSTALL-DOCS-$(CONFIG_CODEC_SRCS) += $(addprefix src/,$(CODEC_DOX))
+-INSTALL-DOCS-$(CONFIG_CODEC_SRCS) += src/libs.doxy_template
+-INSTALL-DOCS-yes += CHANGELOG
+-INSTALL-DOCS-yes += README
++DIST-DOCS-yes = $(wildcard docs/html/*)
++DIST-DOCS-$(CONFIG_CODEC_SRCS) += $(addprefix src/,$(CODEC_DOX))
++DIST-DOCS-$(CONFIG_CODEC_SRCS) += src/libs.doxy_template
++DIST-DOCS-yes += CHANGELOG
++DIST-DOCS-yes += README
+diff --git a/example_xma.c b/example_xma.c
+index cc4e591..e5eca7a 100644
+--- a/example_xma.c
++++ b/example_xma.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -15,10 +16,10 @@
+ #include <string.h>
+ #define VPX_CODEC_DISABLE_COMPAT 1
+ #include "vpx_config.h"
+-#include "vpx_decoder.h"
+-#include "vpx_integer.h"
++#include "vpx/vpx_decoder.h"
++#include "vpx/vpx_integer.h"
+ #if CONFIG_VP8_DECODER
+-#include "vp8dx.h"
++#include "vpx/vp8dx.h"
+ #endif
+
+ static char *exec_name;
+diff --git a/examples.mk b/examples.mk
+index 036a423..bca0d9c 100644
+--- a/examples.mk
++++ b/examples.mk
+@@ -1,10 +1,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+@@ -14,18 +15,21 @@
+ UTILS-$(CONFIG_DECODERS) += ivfdec.c
+ ivfdec.SRCS += md5_utils.c md5_utils.h
+ ivfdec.SRCS += vpx_ports/vpx_timer.h
+-ivfdec.SRCS += vpx_ports/vpx_integer.h
++ivfdec.SRCS += vpx/vpx_integer.h
+ ivfdec.SRCS += args.c args.h vpx_ports/config.h
+ ivfdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
+ ivfdec.DESCRIPTION = Full featured decoder
+ UTILS-$(CONFIG_ENCODERS) += ivfenc.c
+-ivfenc.SRCS += args.c args.h vpx_ports/config.h
+-ivfenc.SRCS += vpx_ports/mem_ops.h vpx_ports/mem_ops_aligned.h
++ivfenc.SRCS += args.c args.h y4minput.c y4minput.h
++ivfenc.SRCS += vpx_ports/config.h vpx_ports/mem_ops.h
++ivfenc.SRCS += vpx_ports/mem_ops_aligned.h
+ ivfenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
+ ivfenc.DESCRIPTION = Full featured encoder
+-UTILS-$(CONFIG_DECODERS) += example_xma.c
+-example_xma.GUID = A955FC4A-73F1-44F7-135E-30D84D32F022
+-example_xma.DESCRIPTION = External Memory Allocation mode usage
++
++# XMA example disabled for now, not used in VP8
++#UTILS-$(CONFIG_DECODERS) += example_xma.c
++#example_xma.GUID = A955FC4A-73F1-44F7-135E-30D84D32F022
++#example_xma.DESCRIPTION = External Memory Allocation mode usage
+
+ GEN_EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c
+ simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
+@@ -84,8 +88,6 @@ ifeq ($(HAVE_ALT_TREE_LAYOUT),yes)
+ INC_PATH := $(SRC_PATH_BARE)/../include
+ else
+ LIB_PATH-yes += $(if $(BUILD_PFX),$(BUILD_PFX),.)
+- INC_PATH-yes += $(SRC_PATH_BARE)/vpx_codec
+- INC_PATH-yes += $(SRC_PATH_BARE)/vpx_ports
+ INC_PATH-$(CONFIG_VP8_DECODER) += $(SRC_PATH_BARE)/vp8
+ INC_PATH-$(CONFIG_VP8_ENCODER) += $(SRC_PATH_BARE)/vp8
+ LIB_PATH := $(call enabled,LIB_PATH)
+@@ -99,6 +101,7 @@ LDFLAGS += $(addprefix -L,$(LIB_PATH))
+ UTILS = $(call enabled,UTILS)
+ GEN_EXAMPLES = $(call enabled,GEN_EXAMPLES)
+ ALL_EXAMPLES = $(UTILS) $(GEN_EXAMPLES)
++UTIL_SRCS = $(foreach ex,$(UTILS),$($(ex:.c=).SRCS))
+ ALL_SRCS = $(foreach ex,$(ALL_EXAMPLES),$($(ex:.c=).SRCS))
+ CODEC_EXTRA_LIBS=$(sort $(call enabled,CODEC_EXTRA_LIBS))
+
+@@ -120,8 +123,10 @@ $(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_OBJS,BUILD_OBJS):=yes)
+ # Create build/install dependencies for all examples. The common case
+ # is handled here. The MSVS case is handled below.
+ NOT_MSVS = $(if $(CONFIG_MSVS),,yes)
+-INSTALL-BINS-$(NOT_MSVS) += $(addprefix bin/,$(ALL_EXAMPLES:.c=))
+-INSTALL-SRCS-yes += $(ALL_SRCS)
++DIST-BINS-$(NOT_MSVS) += $(addprefix bin/,$(ALL_EXAMPLES:.c=))
++INSTALL-BINS-$(NOT_MSVS) += $(addprefix bin/,$(UTILS:.c=))
++DIST-SRCS-yes += $(ALL_SRCS)
++INSTALL-SRCS-yes += $(UTIL_SRCS)
+ OBJS-$(NOT_MSVS) += $(if $(BUILD_OBJS),$(call objs,$(ALL_SRCS)))
+ BINS-$(NOT_MSVS) += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=))
+
+diff --git a/examples/decode_to_md5.txt b/examples/decode_to_md5.txt
+index 0599b13..b3dd568 100644
+--- a/examples/decode_to_md5.txt
++++ b/examples/decode_to_md5.txt
+@@ -26,21 +26,21 @@ is processed, then U, then V. It is important to honor the image's `stride`
+ values.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
+ unsigned char md5_sum[16];
+-md5_ctx_t md5;
++MD5Context md5;
+ int i;
+
+-md5_init(&md5);
++MD5Init(&md5);
+
+ for(plane=0; plane < 3; plane++) {
+ unsigned char *buf =img->planes[plane];
+
+ for(y=0; y<img->d_h >> (plane?1:0); y++) {
+- md5_update(&md5, buf, img->d_w >> (plane?1:0));
++ MD5Update(&md5, buf, img->d_w >> (plane?1:0));
+ buf += img->stride[plane];
+ }
+ }
+
+-md5_finalize(&md5, md5_sum);
++MD5Final(md5_sum, &md5);
+ for(i=0; i<16; i++)
+ fprintf(outfile, "%02x",md5_sum[i]);
+ fprintf(outfile, " img-%dx%d-%04d.i420\n", img->d_w, img->d_h,
+diff --git a/examples/decoder_tmpl.c b/examples/decoder_tmpl.c
+index deea449..826ad20 100644
+--- a/examples/decoder_tmpl.c
++++ b/examples/decoder_tmpl.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -16,11 +17,9 @@
+ #include <stdarg.h>
+ #include <string.h>
+ #define VPX_CODEC_DISABLE_COMPAT 1
+-#include "vpx_decoder.h"
+-#if CONFIG_VP8_DECODER && !defined(interface)
+-#include "vp8dx.h"
++#include "vpx/vpx_decoder.h"
++#include "vpx/vp8dx.h"
+ #define interface (&vpx_codec_vp8_dx_algo)
+-#endif
+ @EXTRA_INCLUDES
+
+
+diff --git a/examples/decoder_tmpl.txt b/examples/decoder_tmpl.txt
+index 3287d50..6da38c2 100644
+--- a/examples/decoder_tmpl.txt
++++ b/examples/decoder_tmpl.txt
+@@ -1,7 +1,7 @@
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
+ #define VPX_CODEC_DISABLE_COMPAT 1
+-#include "vpx_decoder.h"
+-#include "vp8dx.h"
++#include "vpx/vpx_decoder.h"
++#include "vpx/vp8dx.h"
+ #define interface (&vpx_codec_vp8_dx_algo)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
+
+diff --git a/examples/encoder_tmpl.c b/examples/encoder_tmpl.c
+index 2df893a..9e262e9 100644
+--- a/examples/encoder_tmpl.c
++++ b/examples/encoder_tmpl.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -16,12 +17,10 @@
+ #include <stdarg.h>
+ #include <string.h>
+ #define VPX_CODEC_DISABLE_COMPAT 1
+-#include "vpx_encoder.h"
+-#if CONFIG_VP8_ENCODER && !defined(interface)
+-#include "vp8cx.h"
++#include "vpx/vpx_encoder.h"
++#include "vpx/vp8cx.h"
+ #define interface (&vpx_codec_vp8_cx_algo)
+ #define fourcc 0x30385056
+-#endif
+ @EXTRA_INCLUDES
+
+ #define IVF_FILE_HDR_SZ (32)
+@@ -129,7 +128,7 @@ int main(int argc, char **argv) {
+ height = strtol(argv[2], NULL, 0);
+ if(width < 16 || width%2 || height <16 || height%2)
+ die("Invalid resolution: %ldx%ld", width, height);
+- if(!vpx_img_alloc(&raw, IMG_FMT_YV12, width, height, 1))
++ if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
+ die("Faile to allocate image", width, height);
+ if(!(outfile = fopen(argv[4], "wb")))
+ die("Failed to open %s for writing", argv[4]);
+diff --git a/examples/encoder_tmpl.txt b/examples/encoder_tmpl.txt
+index db1ea77..87055ca 100644
+--- a/examples/encoder_tmpl.txt
++++ b/examples/encoder_tmpl.txt
+@@ -1,7 +1,7 @@
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
+ #define VPX_CODEC_DISABLE_COMPAT 1
+-#include "vpx_encoder.h"
+-#include "vp8cx.h"
++#include "vpx/vpx_encoder.h"
++#include "vpx/vp8cx.h"
+ #define interface (&vpx_codec_vp8_cx_algo)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
+
+diff --git a/examples/gen_example_code.sh b/examples/gen_example_code.sh
+index f2e45c5..dc7ad72 100755
+--- a/examples/gen_example_code.sh
++++ b/examples/gen_example_code.sh
+@@ -2,10 +2,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/examples/gen_example_doxy.php b/examples/gen_example_doxy.php
+index 08beade..ba2617f 100755
+--- a/examples/gen_example_doxy.php
++++ b/examples/gen_example_doxy.php
+@@ -2,10 +2,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/examples/gen_example_text.sh b/examples/gen_example_text.sh
+index 0e1f796..fcc73d8 100755
+--- a/examples/gen_example_text.sh
++++ b/examples/gen_example_text.sh
+@@ -2,10 +2,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php.orig b/examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php.orig
+deleted file mode 100644
+index b0ed7c9..0000000
+--- a/examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php.orig
++++ /dev/null
+@@ -1,2909 +0,0 @@
+-<?php
+-#
+-# Markdown Extra - A text-to-HTML conversion tool for web writers
+-#
+-# PHP Markdown & Extra
+-# Copyright (c) 2004-2008 Michel Fortin
+-# <http://www.michelf.com/projects/php-markdown/>
+-#
+-# Original Markdown
+-# Copyright (c) 2004-2006 John Gruber
+-# <http://daringfireball.net/projects/markdown/>
+-#
+-
+-
+-define( 'MARKDOWN_VERSION', "1.0.1m" ); # Sat 21 Jun 2008
+-define( 'MARKDOWNEXTRA_VERSION', "1.2.3" ); # Wed 31 Dec 2008
+-
+-
+-#
+-# Global default settings:
+-#
+-
+-# Change to ">" for HTML output
+-@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX', " />");
+-
+-# Define the width of a tab for code blocks.
+-@define( 'MARKDOWN_TAB_WIDTH', 4 );
+-
+-# Optional title attribute for footnote links and backlinks.
+-@define( 'MARKDOWN_FN_LINK_TITLE', "" );
+-@define( 'MARKDOWN_FN_BACKLINK_TITLE', "" );
+-
+-# Optional class attribute for footnote links and backlinks.
+-@define( 'MARKDOWN_FN_LINK_CLASS', "" );
+-@define( 'MARKDOWN_FN_BACKLINK_CLASS', "" );
+-
+-
+-#
+-# WordPress settings:
+-#
+-
+-# Change to false to remove Markdown from posts and/or comments.
+-@define( 'MARKDOWN_WP_POSTS', true );
+-@define( 'MARKDOWN_WP_COMMENTS', true );
+-
+-
+-
+-### Standard Function Interface ###
+-
+-@define( 'MARKDOWN_PARSER_CLASS', 'MarkdownExtra_Parser' );
+-
+-function Markdown($text) {
+-#
+-# Initialize the parser and return the result of its transform method.
+-#
+- # Setup static parser variable.
+- static $parser;
+- if (!isset($parser)) {
+- $parser_class = MARKDOWN_PARSER_CLASS;
+- $parser = new $parser_class;
+- }
+-
+- # Transform text using parser.
+- return $parser->transform($text);
+-}
+-
+-
+-### WordPress Plugin Interface ###
+-
+-/*
+-Plugin Name: Markdown Extra
+-Plugin URI: http://www.michelf.com/projects/php-markdown/
+-Description: <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://www.michelf.com/projects/php-markdown/">More...</a>
+-Version: 1.2.2
+-Author: Michel Fortin
+-Author URI: http://www.michelf.com/
+-*/
+-
+-if (isset($wp_version)) {
+- # More details about how it works here:
+- # <http://www.michelf.com/weblog/2005/wordpress-text-flow-vs-markdown/>
+-
+- # Post content and excerpts
+- # - Remove WordPress paragraph generator.
+- # - Run Markdown on excerpt, then remove all tags.
+- # - Add paragraph tag around the excerpt, but remove it for the excerpt rss.
+- if (MARKDOWN_WP_POSTS) {
+- remove_filter('the_content', 'wpautop');
+- remove_filter('the_content_rss', 'wpautop');
+- remove_filter('the_excerpt', 'wpautop');
+- add_filter('the_content', 'mdwp_MarkdownPost', 6);
+- add_filter('the_content_rss', 'mdwp_MarkdownPost', 6);
+- add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6);
+- add_filter('get_the_excerpt', 'trim', 7);
+- add_filter('the_excerpt', 'mdwp_add_p');
+- add_filter('the_excerpt_rss', 'mdwp_strip_p');
+-
+- remove_filter('content_save_pre', 'balanceTags', 50);
+- remove_filter('excerpt_save_pre', 'balanceTags', 50);
+- add_filter('the_content', 'balanceTags', 50);
+- add_filter('get_the_excerpt', 'balanceTags', 9);
+- }
+-
+- # Add a footnote id prefix to posts when inside a loop.
+- function mdwp_MarkdownPost($text) {
+- static $parser;
+- if (!$parser) {
+- $parser_class = MARKDOWN_PARSER_CLASS;
+- $parser = new $parser_class;
+- }
+- if (is_single() || is_page() || is_feed()) {
+- $parser->fn_id_prefix = "";
+- } else {
+- $parser->fn_id_prefix = get_the_ID() . ".";
+- }
+- return $parser->transform($text);
+- }
+-
+- # Comments
+- # - Remove WordPress paragraph generator.
+- # - Remove WordPress auto-link generator.
+- # - Scramble important tags before passing them to the kses filter.
+- # - Run Markdown on excerpt then remove paragraph tags.
+- if (MARKDOWN_WP_COMMENTS) {
+- remove_filter('comment_text', 'wpautop', 30);
+- remove_filter('comment_text', 'make_clickable');
+- add_filter('pre_comment_content', 'Markdown', 6);
+- add_filter('pre_comment_content', 'mdwp_hide_tags', 8);
+- add_filter('pre_comment_content', 'mdwp_show_tags', 12);
+- add_filter('get_comment_text', 'Markdown', 6);
+- add_filter('get_comment_excerpt', 'Markdown', 6);
+- add_filter('get_comment_excerpt', 'mdwp_strip_p', 7);
+-
+- global $mdwp_hidden_tags, $mdwp_placeholders;
+- $mdwp_hidden_tags = explode(' ',
+- '<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>');
+- $mdwp_placeholders = explode(' ', str_rot13(
+- 'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '.
+- 'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli'));
+- }
+-
+- function mdwp_add_p($text) {
+- if (!preg_match('{^$|^<(p|ul|ol|dl|pre|blockquote)>}i', $text)) {
+- $text = '<p>'.$text.'</p>';
+- $text = preg_replace('{\n{2,}}', "</p>\n\n<p>", $text);
+- }
+- return $text;
+- }
+-
+- function mdwp_strip_p($t) { return preg_replace('{</?p>}i', '', $t); }
+-
+- function mdwp_hide_tags($text) {
+- global $mdwp_hidden_tags, $mdwp_placeholders;
+- return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text);
+- }
+- function mdwp_show_tags($text) {
+- global $mdwp_hidden_tags, $mdwp_placeholders;
+- return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text);
+- }
+-}
+-
+-
+-### bBlog Plugin Info ###
+-
+-function identify_modifier_markdown() {
+- return array(
+- 'name' => 'markdown',
+- 'type' => 'modifier',
+- 'nicename' => 'PHP Markdown Extra',
+- 'description' => 'A text-to-HTML conversion tool for web writers',
+- 'authors' => 'Michel Fortin and John Gruber',
+- 'licence' => 'GPL',
+- 'version' => MARKDOWNEXTRA_VERSION,
+- 'help' => '<a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://www.michelf.com/projects/php-markdown/">More...</a>',
+- );
+-}
+-
+-
+-### Smarty Modifier Interface ###
+-
+-function smarty_modifier_markdown($text) {
+- return Markdown($text);
+-}
+-
+-
+-### Textile Compatibility Mode ###
+-
+-# Rename this file to "classTextile.php" and it can replace Textile everywhere.
+-
+-if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) {
+- # Try to include PHP SmartyPants. Should be in the same directory.
+- @include_once 'smartypants.php';
+- # Fake Textile class. It calls Markdown instead.
+- class Textile {
+- function TextileThis($text, $lite='', $encode='') {
+- if ($lite == '' && $encode == '') $text = Markdown($text);
+- if (function_exists('SmartyPants')) $text = SmartyPants($text);
+- return $text;
+- }
+- # Fake restricted version: restrictions are not supported for now.
+- function TextileRestricted($text, $lite='', $noimage='') {
+- return $this->TextileThis($text, $lite);
+- }
+- # Workaround to ensure compatibility with TextPattern 4.0.3.
+- function blockLite($text) { return $text; }
+- }
+-}
+-
+-
+-
+-#
+-# Markdown Parser Class
+-#
+-
+-class Markdown_Parser {
+-
+- # Regex to match balanced [brackets].
+- # Needed to insert a maximum bracked depth while converting to PHP.
+- var $nested_brackets_depth = 6;
+- var $nested_brackets_re;
+-
+- var $nested_url_parenthesis_depth = 4;
+- var $nested_url_parenthesis_re;
+-
+- # Table of hash values for escaped characters:
+- var $escape_chars = '\`*_{}[]()>#+-.!';
+- var $escape_chars_re;
+-
+- # Change to ">" for HTML output.
+- var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX;
+- var $tab_width = MARKDOWN_TAB_WIDTH;
+-
+- # Change to `true` to disallow markup or entities.
+- var $no_markup = false;
+- var $no_entities = true;
+-
+- # Predefined urls and titles for reference links and images.
+- var $predef_urls = array();
+- var $predef_titles = array();
+-
+-
+- function Markdown_Parser() {
+- #
+- # Constructor function. Initialize appropriate member variables.
+- #
+- $this->_initDetab();
+- $this->prepareItalicsAndBold();
+-
+- $this->nested_brackets_re =
+- str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
+- str_repeat('\])*', $this->nested_brackets_depth);
+-
+- $this->nested_url_parenthesis_re =
+- str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
+- str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
+-
+- $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
+-
+- # Sort document, block, and span gamut in ascendent priority order.
+- asort($this->document_gamut);
+- asort($this->block_gamut);
+- asort($this->span_gamut);
+- }
+-
+-
+- # Internal hashes used during transformation.
+- var $urls = array();
+- var $titles = array();
+- var $html_hashes = array();
+-
+- # Status flag to avoid invalid nesting.
+- var $in_anchor = false;
+-
+-
+- function setup() {
+- #
+- # Called before the transformation process starts to setup parser
+- # states.
+- #
+- # Clear global hashes.
+- $this->urls = $this->predef_urls;
+- $this->titles = $this->predef_titles;
+- $this->html_hashes = array();
+-
+- $in_anchor = false;
+- }
+-
+- function teardown() {
+- #
+- # Called after the transformation process to clear any variable
+- # which may be taking up memory unnecessarly.
+- #
+- $this->urls = array();
+- $this->titles = array();
+- $this->html_hashes = array();
+- }
+-
+-
+- function transform($text) {
+- #
+- # Main function. Performs some preprocessing on the input text
+- # and pass it through the document gamut.
+- #
+- $this->setup();
+-
+- # Remove UTF-8 BOM and marker character in input, if present.
+- $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
+-
+- # Standardize line endings:
+- # DOS to Unix and Mac to Unix
+- $text = preg_replace('{\r\n?}', "\n", $text);
+-
+- # Make sure $text ends with a couple of newlines:
+- $text .= "\n\n";
+-
+- # Convert all tabs to spaces.
+- $text = $this->detab($text);
+-
+- # Turn block-level HTML blocks into hash entries
+- $text = $this->hashHTMLBlocks($text);
+-
+- # Strip any lines consisting only of spaces and tabs.
+- # This makes subsequent regexen easier to write, because we can
+- # match consecutive blank lines with /\n+/ instead of something
+- # contorted like /[ ]*\n+/ .
+- $text = preg_replace('/^[ ]+$/m', '', $text);
+-
+- # Run document gamut methods.
+- foreach ($this->document_gamut as $method => $priority) {
+- $text = $this->$method($text);
+- }
+-
+- $this->teardown();
+-
+- return $text . "\n";
+- }
+-
+- var $document_gamut = array(
+- # Strip link definitions, store in hashes.
+- "stripLinkDefinitions" => 20,
+-
+- "runBasicBlockGamut" => 30,
+- );
+-
+-
+- function stripLinkDefinitions($text) {
+- #
+- # Strips link definitions from text, stores the URLs and titles in
+- # hash references.
+- #
+- $less_than_tab = $this->tab_width - 1;
+-
+- # Link defs are in the form: ^[id]: url "optional title"
+- $text = preg_replace_callback('{
+- ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
+- [ ]*
+- \n? # maybe *one* newline
+- [ ]*
+- <?(\S+?)>? # url = $2
+- [ ]*
+- \n? # maybe one newline
+- [ ]*
+- (?:
+- (?<=\s) # lookbehind for whitespace
+- ["(]
+- (.*?) # title = $3
+- [")]
+- [ ]*
+- )? # title is optional
+- (?:\n+|\Z)
+- }xm',
+- array(&$this, '_stripLinkDefinitions_callback'),
+- $text);
+- return $text;
+- }
+- function _stripLinkDefinitions_callback($matches) {
+- $link_id = strtolower($matches[1]);
+- $this->urls[$link_id] = $matches[2];
+- $this->titles[$link_id] =& $matches[3];
+- return ''; # String that will replace the block
+- }
+-
+-
+- function hashHTMLBlocks($text) {
+- if ($this->no_markup) return $text;
+-
+- $less_than_tab = $this->tab_width - 1;
+-
+- # Hashify HTML blocks:
+- # We only want to do this for block-level HTML tags, such as headers,
+- # lists, and tables. That's because we still want to wrap <p>s around
+- # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+- # phrase emphasis, and spans. The list of tags we're looking for is
+- # hard-coded:
+- #
+- # * List "a" is made of tags which can be both inline or block-level.
+- # These will be treated block-level when the start tag is alone on
+- # its line, otherwise they're not matched here and will be taken as
+- # inline later.
+- # * List "b" is made of tags which are always block-level;
+- #
+- $block_tags_a_re = 'ins|del';
+- $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
+- 'script|noscript|form|fieldset|iframe|math';
+-
+- # Regular expression for the content of a block tag.
+- $nested_tags_level = 4;
+- $attr = '
+- (?> # optional tag attributes
+- \s # starts with whitespace
+- (?>
+- [^>"/]+ # text outside quotes
+- |
+- /+(?!>) # slash not followed by ">"
+- |
+- "[^"]*" # text inside double quotes (tolerate ">")
+- |
+- \'[^\']*\' # text inside single quotes (tolerate ">")
+- )*
+- )?
+- ';
+- $content =
+- str_repeat('
+- (?>
+- [^<]+ # content without tag
+- |
+- <\2 # nested opening tag
+- '.$attr.' # attributes
+- (?>
+- />
+- |
+- >', $nested_tags_level). # end of opening tag
+- '.*?'. # last level nested tag content
+- str_repeat('
+- </\2\s*> # closing nested tag
+- )
+- |
+- <(?!/\2\s*> # other tags with a different name
+- )
+- )*',
+- $nested_tags_level);
+- $content2 = str_replace('\2', '\3', $content);
+-
+- # First, look for nested blocks, e.g.:
+- # <div>
+- # <div>
+- # tags for inner block must be indented.
+- # </div>
+- # </div>
+- #
+- # The outermost tags must start at the left margin for this to match, and
+- # the inner nested divs must be indented.
+- # We need to do this before the next, more liberal match, because the next
+- # match will start at the first `<div>` and stop at the first `</div>`.
+- $text = preg_replace_callback('{(?>
+- (?>
+- (?<=\n\n) # Starting after a blank line
+- | # or
+- \A\n? # the beginning of the doc
+- )
+- ( # save in $1
+-
+- # Match from `\n<tag>` to `</tag>\n`, handling nested tags
+- # in between.
+-
+- [ ]{0,'.$less_than_tab.'}
+- <('.$block_tags_b_re.')# start tag = $2
+- '.$attr.'> # attributes followed by > and \n
+- '.$content.' # content, support nesting
+- </\2> # the matching end tag
+- [ ]* # trailing spaces/tabs
+- (?=\n+|\Z) # followed by a newline or end of document
+-
+- | # Special version for tags of group a.
+-
+- [ ]{0,'.$less_than_tab.'}
+- <('.$block_tags_a_re.')# start tag = $3
+- '.$attr.'>[ ]*\n # attributes followed by >
+- '.$content2.' # content, support nesting
+- </\3> # the matching end tag
+- [ ]* # trailing spaces/tabs
+- (?=\n+|\Z) # followed by a newline or end of document
+-
+- | # Special case just for <hr />. It was easier to make a special
+- # case than to make the other regex more complicated.
+-
+- [ ]{0,'.$less_than_tab.'}
+- <(hr) # start tag = $2
+- '.$attr.' # attributes
+- /?> # the matching end tag
+- [ ]*
+- (?=\n{2,}|\Z) # followed by a blank line or end of document
+-
+- | # Special case for standalone HTML comments:
+-
+- [ ]{0,'.$less_than_tab.'}
+- (?s:
+- <!-- .*? -->
+- )
+- [ ]*
+- (?=\n{2,}|\Z) # followed by a blank line or end of document
+-
+- | # PHP and ASP-style processor instructions (<? and <%)
+-
+- [ ]{0,'.$less_than_tab.'}
+- (?s:
+- <([?%]) # $2
+- .*?
+- \2>
+- )
+- [ ]*
+- (?=\n{2,}|\Z) # followed by a blank line or end of document
+-
+- )
+- )}Sxmi',
+- array(&$this, '_hashHTMLBlocks_callback'),
+- $text);
+-
+- return $text;
+- }
+- function _hashHTMLBlocks_callback($matches) {
+- $text = $matches[1];
+- $key = $this->hashBlock($text);
+- return "\n\n$key\n\n";
+- }
+-
+-
+- function hashPart($text, $boundary = 'X') {
+- #
+- # Called whenever a tag must be hashed when a function insert an atomic
+- # element in the text stream. Passing $text to through this function gives
+- # a unique text-token which will be reverted back when calling unhash.
+- #
+- # The $boundary argument specify what character should be used to surround
+- # the token. By convension, "B" is used for block elements that needs not
+- # to be wrapped into paragraph tags at the end, ":" is used for elements
+- # that are word separators and "X" is used in the general case.
+- #
+- # Swap back any tag hash found in $text so we do not have to `unhash`
+- # multiple times at the end.
+- $text = $this->unhash($text);
+-
+- # Then hash the block.
+- static $i = 0;
+- $key = "$boundary\x1A" . ++$i . $boundary;
+- $this->html_hashes[$key] = $text;
+- return $key; # String that will replace the tag.
+- }
+-
+-
+- function hashBlock($text) {
+- #
+- # Shortcut function for hashPart with block-level boundaries.
+- #
+- return $this->hashPart($text, 'B');
+- }
+-
+-
+- var $block_gamut = array(
+- #
+- # These are all the transformations that form block-level
+- # tags like paragraphs, headers, and list items.
+- #
+- "doHeaders" => 10,
+- "doHorizontalRules" => 20,
+-
+- "doLists" => 40,
+- "doCodeBlocks" => 50,
+- "doBlockQuotes" => 60,
+- );
+-
+- function runBlockGamut($text) {
+- #
+- # Run block gamut tranformations.
+- #
+- # We need to escape raw HTML in Markdown source before doing anything
+- # else. This need to be done for each block, and not only at the
+- # begining in the Markdown function since hashed blocks can be part of
+- # list items and could have been indented. Indented blocks would have
+- # been seen as a code block in a previous pass of hashHTMLBlocks.
+- $text = $this->hashHTMLBlocks($text);
+-
+- return $this->runBasicBlockGamut($text);
+- }
+-
+- function runBasicBlockGamut($text) {
+- #
+- # Run block gamut tranformations, without hashing HTML blocks. This is
+- # useful when HTML blocks are known to be already hashed, like in the first
+- # whole-document pass.
+- #
+- foreach ($this->block_gamut as $method => $priority) {
+- $text = $this->$method($text);
+- }
+-
+- # Finally form paragraph and restore hashed blocks.
+- $text = $this->formParagraphs($text);
+-
+- return $text;
+- }
+-
+-
+- function doHorizontalRules($text) {
+- # Do Horizontal Rules:
+- return preg_replace(
+- '{
+- ^[ ]{0,3} # Leading space
+- ([-*_]) # $1: First marker
+- (?> # Repeated marker group
+- [ ]{0,2} # Zero, one, or two spaces.
+- \1 # Marker character
+- ){2,} # Group repeated at least twice
+- [ ]* # Tailing spaces
+- $ # End of line.
+- }mx',
+- "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
+- $text);
+- }
+-
+-
+- var $span_gamut = array(
+- #
+- # These are all the transformations that occur *within* block-level
+- # tags like paragraphs, headers, and list items.
+- #
+- # Process character escapes, code spans, and inline HTML
+- # in one shot.
+- "parseSpan" => -30,
+-
+- # Process anchor and image tags. Images must come first,
+- # because ![foo][f] looks like an anchor.
+- "doImages" => 10,
+- "doAnchors" => 20,
+-
+- # Make links out of things like `<http://example.com/>`
+- # Must come after doAnchors, because you can use < and >
+- # delimiters in inline links like [this](<url>).
+- "doAutoLinks" => 30,
+- "encodeAmpsAndAngles" => 40,
+-
+- "doItalicsAndBold" => 50,
+- "doHardBreaks" => 60,
+- );
+-
+- function runSpanGamut($text) {
+- #
+- # Run span gamut tranformations.
+- #
+- foreach ($this->span_gamut as $method => $priority) {
+- $text = $this->$method($text);
+- }
+-
+- return $text;
+- }
+-
+-
+- function doHardBreaks($text) {
+- # Do hard breaks:
+- return preg_replace_callback('/ {2,}\n/',
+- array(&$this, '_doHardBreaks_callback'), $text);
+- }
+- function _doHardBreaks_callback($matches) {
+- return $this->hashPart("<br$this->empty_element_suffix\n");
+- }
+-
+-
+- function doAnchors($text) {
+- #
+- # Turn Markdown link shortcuts into XHTML <a> tags.
+- #
+- if ($this->in_anchor) return $text;
+- $this->in_anchor = true;
+-
+- #
+- # First, handle reference-style links: [link text] [id]
+- #
+- $text = preg_replace_callback('{
+- ( # wrap whole match in $1
+- \[
+- ('.$this->nested_brackets_re.') # link text = $2
+- \]
+-
+- [ ]? # one optional space
+- (?:\n[ ]*)? # one optional newline followed by spaces
+-
+- \[
+- (.*?) # id = $3
+- \]
+- )
+- }xs',
+- array(&$this, '_doAnchors_reference_callback'), $text);
+-
+- #
+- # Next, inline-style links: [link text](url "optional title")
+- #
+- $text = preg_replace_callback('{
+- ( # wrap whole match in $1
+- \[
+- ('.$this->nested_brackets_re.') # link text = $2
+- \]
+- \( # literal paren
+- [ ]*
+- (?:
+- <(\S*)> # href = $3
+- |
+- ('.$this->nested_url_parenthesis_re.') # href = $4
+- )
+- [ ]*
+- ( # $5
+- ([\'"]) # quote char = $6
+- (.*?) # Title = $7
+- \6 # matching quote
+- [ ]* # ignore any spaces/tabs between closing quote and )
+- )? # title is optional
+- \)
+- )
+- }xs',
+- array(&$this, '_DoAnchors_inline_callback'), $text);
+-
+- #
+- # Last, handle reference-style shortcuts: [link text]
+- # These must come last in case you've also got [link test][1]
+- # or [link test](/foo)
+- #
+-// $text = preg_replace_callback('{
+-// ( # wrap whole match in $1
+-// \[
+-// ([^\[\]]+) # link text = $2; can\'t contain [ or ]
+-// \]
+-// )
+-// }xs',
+-// array(&$this, '_doAnchors_reference_callback'), $text);
+-
+- $this->in_anchor = false;
+- return $text;
+- }
+- function _doAnchors_reference_callback($matches) {
+- $whole_match = $matches[1];
+- $link_text = $matches[2];
+- $link_id =& $matches[3];
+-
+- if ($link_id == "") {
+- # for shortcut links like [this][] or [this].
+- $link_id = $link_text;
+- }
+-
+- # lower-case and turn embedded newlines into spaces
+- $link_id = strtolower($link_id);
+- $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
+-
+- if (isset($this->urls[$link_id])) {
+- $url = $this->urls[$link_id];
+- $url = $this->encodeAttribute($url);
+-
+- $result = "<a href=\"$url\"";
+- if ( isset( $this->titles[$link_id] ) ) {
+- $title = $this->titles[$link_id];
+- $title = $this->encodeAttribute($title);
+- $result .= " title=\"$title\"";
+- }
+-
+- $link_text = $this->runSpanGamut($link_text);
+- $result .= ">$link_text</a>";
+- $result = $this->hashPart($result);
+- }
+- else {
+- $result = $whole_match;
+- }
+- return $result;
+- }
+- function _doAnchors_inline_callback($matches) {
+- $whole_match = $matches[1];
+- $link_text = $this->runSpanGamut($matches[2]);
+- $url = $matches[3] == '' ? $matches[4] : $matches[3];
+- $title =& $matches[7];
+-
+- $url = $this->encodeAttribute($url);
+-
+- $result = "<a href=\"$url\"";
+- if (isset($title)) {
+- $title = $this->encodeAttribute($title);
+- $result .= " title=\"$title\"";
+- }
+-
+- $link_text = $this->runSpanGamut($link_text);
+- $result .= ">$link_text</a>";
+-
+- return $this->hashPart($result);
+- }
+-
+-
+- function doImages($text) {
+- #
+- # Turn Markdown image shortcuts into <img> tags.
+- #
+- #
+- # First, handle reference-style labeled images: ![alt text][id]
+- #
+- $text = preg_replace_callback('{
+- ( # wrap whole match in $1
+- !\[
+- ('.$this->nested_brackets_re.') # alt text = $2
+- \]
+-
+- [ ]? # one optional space
+- (?:\n[ ]*)? # one optional newline followed by spaces
+-
+- \[
+- (.*?) # id = $3
+- \]
+-
+- )
+- }xs',
+- array(&$this, '_doImages_reference_callback'), $text);
+-
+- #
+- # Next, handle inline images: ![alt text](url "optional title")
+- # Don't forget: encode * and _
+- #
+- $text = preg_replace_callback('{
+- ( # wrap whole match in $1
+- !\[
+- ('.$this->nested_brackets_re.') # alt text = $2
+- \]
+- \s? # One optional whitespace character
+- \( # literal paren
+- [ ]*
+- (?:
+- <(\S*)> # src url = $3
+- |
+- ('.$this->nested_url_parenthesis_re.') # src url = $4
+- )
+- [ ]*
+- ( # $5
+- ([\'"]) # quote char = $6
+- (.*?) # title = $7
+- \6 # matching quote
+- [ ]*
+- )? # title is optional
+- \)
+- )
+- }xs',
+- array(&$this, '_doImages_inline_callback'), $text);
+-
+- return $text;
+- }
+- function _doImages_reference_callback($matches) {
+- $whole_match = $matches[1];
+- $alt_text = $matches[2];
+- $link_id = strtolower($matches[3]);
+-
+- if ($link_id == "") {
+- $link_id = strtolower($alt_text); # for shortcut links like ![this][].
+- }
+-
+- $alt_text = $this->encodeAttribute($alt_text);
+- if (isset($this->urls[$link_id])) {
+- $url = $this->encodeAttribute($this->urls[$link_id]);
+- $result = "<img src=\"$url\" alt=\"$alt_text\"";
+- if (isset($this->titles[$link_id])) {
+- $title = $this->titles[$link_id];
+- $title = $this->encodeAttribute($title);
+- $result .= " title=\"$title\"";
+- }
+- $result .= $this->empty_element_suffix;
+- $result = $this->hashPart($result);
+- }
+- else {
+- # If there's no such link ID, leave intact:
+- $result = $whole_match;
+- }
+-
+- return $result;
+- }
+- function _doImages_inline_callback($matches) {
+- $whole_match = $matches[1];
+- $alt_text = $matches[2];
+- $url = $matches[3] == '' ? $matches[4] : $matches[3];
+- $title =& $matches[7];
+-
+- $alt_text = $this->encodeAttribute($alt_text);
+- $url = $this->encodeAttribute($url);
+- $result = "<img src=\"$url\" alt=\"$alt_text\"";
+- if (isset($title)) {
+- $title = $this->encodeAttribute($title);
+- $result .= " title=\"$title\""; # $title already quoted
+- }
+- $result .= $this->empty_element_suffix;
+-
+- return $this->hashPart($result);
+- }
+-
+-
+- function doHeaders($text) {
+- # Setext-style headers:
+- # Header 1
+- # ========
+- #
+- # Header 2
+- # --------
+- #
+- $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
+- array(&$this, '_doHeaders_callback_setext'), $text);
+-
+- # atx-style headers:
+- # # Header 1
+- # ## Header 2
+- # ## Header 2 with closing hashes ##
+- # ...
+- # ###### Header 6
+- #
+- $text = preg_replace_callback('{
+- ^(\#{1,6}) # $1 = string of #\'s
+- [ ]*
+- (.+?) # $2 = Header text
+- [ ]*
+- \#* # optional closing #\'s (not counted)
+- \n+
+- }xm',
+- array(&$this, '_doHeaders_callback_atx'), $text);
+-
+- return $text;
+- }
+- function _doHeaders_callback_setext($matches) {
+- # Terrible hack to check we haven't found an empty list item.
+- if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
+- return $matches[0];
+-
+- $level = $matches[2]{0} == '=' ? 1 : 2;
+- $block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
+- return "\n" . $this->hashBlock($block) . "\n\n";
+- }
+- function _doHeaders_callback_atx($matches) {
+- $level = strlen($matches[1]);
+- $block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
+- return "\n" . $this->hashBlock($block) . "\n\n";
+- }
+-
+-
+- function doLists($text) {
+- #
+- # Form HTML ordered (numbered) and unordered (bulleted) lists.
+- #
+- $less_than_tab = $this->tab_width - 1;
+-
+- # Re-usable patterns to match list item bullets and number markers:
+- $marker_ul_re = '[*+-]';
+- $marker_ol_re = '\d+[.]';
+- $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+-
+- $markers_relist = array($marker_ul_re, $marker_ol_re);
+-
+- foreach ($markers_relist as $marker_re) {
+- # Re-usable pattern to match any entirel ul or ol list:
+- $whole_list_re = '
+- ( # $1 = whole list
+- ( # $2
+- [ ]{0,'.$less_than_tab.'}
+- ('.$marker_re.') # $3 = first list item marker
+- [ ]+
+- )
+- (?s:.+?)
+- ( # $4
+- \z
+- |
+- \n{2,}
+- (?=\S)
+- (?! # Negative lookahead for another list item marker
+- [ ]*
+- '.$marker_re.'[ ]+
+- )
+- )
+- )
+- '; // mx
+-
+- # We use a different prefix before nested lists than top-level lists.
+- # See extended comment in _ProcessListItems().
+-
+- if ($this->list_level) {
+- $text = preg_replace_callback('{
+- ^
+- '.$whole_list_re.'
+- }mx',
+- array(&$this, '_doLists_callback'), $text);
+- }
+- else {
+- $text = preg_replace_callback('{
+- (?:(?<=\n)\n|\A\n?) # Must eat the newline
+- '.$whole_list_re.'
+- }mx',
+- array(&$this, '_doLists_callback'), $text);
+- }
+- }
+-
+- return $text;
+- }
+- function _doLists_callback($matches) {
+- # Re-usable patterns to match list item bullets and number markers:
+- $marker_ul_re = '[*+-]';
+- $marker_ol_re = '\d+[.]';
+- $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+-
+- $list = $matches[1];
+- $list_type = preg_match("/$marker_ul_re/", $matches[3]) ? "ul" : "ol";
+-
+- $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
+-
+- $list .= "\n";
+- $result = $this->processListItems($list, $marker_any_re);
+-
+- $result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
+- return "\n". $result ."\n\n";
+- }
+-
+- var $list_level = 0;
+-
+- function processListItems($list_str, $marker_any_re) {
+- #
+- # Process the contents of a single ordered or unordered list, splitting it
+- # into individual list items.
+- #
+- # The $this->list_level global keeps track of when we're inside a list.
+- # Each time we enter a list, we increment it; when we leave a list,
+- # we decrement. If it's zero, we're not in a list anymore.
+- #
+- # We do this because when we're not inside a list, we want to treat
+- # something like this:
+- #
+- # I recommend upgrading to version
+- # 8. Oops, now this line is treated
+- # as a sub-list.
+- #
+- # As a single paragraph, despite the fact that the second line starts
+- # with a digit-period-space sequence.
+- #
+- # Whereas when we're inside a list (or sub-list), that line will be
+- # treated as the start of a sub-list. What a kludge, huh? This is
+- # an aspect of Markdown's syntax that's hard to parse perfectly
+- # without resorting to mind-reading. Perhaps the solution is to
+- # change the syntax rules such that sub-lists must start with a
+- # starting cardinal number; e.g. "1." or "a.".
+-
+- $this->list_level++;
+-
+- # trim trailing blank lines:
+- $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+-
+- $list_str = preg_replace_callback('{
+- (\n)? # leading line = $1
+- (^[ ]*) # leading whitespace = $2
+- ('.$marker_any_re.' # list marker and space = $3
+- (?:[ ]+|(?=\n)) # space only required if item is not empty
+- )
+- ((?s:.*?)) # list item text = $4
+- (?:(\n+(?=\n))|\n) # tailing blank line = $5
+- (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
+- }xm',
+- array(&$this, '_processListItems_callback'), $list_str);
+-
+- $this->list_level--;
+- return $list_str;
+- }
+- function _processListItems_callback($matches) {
+- $item = $matches[4];
+- $leading_line =& $matches[1];
+- $leading_space =& $matches[2];
+- $marker_space = $matches[3];
+- $tailing_blank_line =& $matches[5];
+-
+- if ($leading_line || $tailing_blank_line ||
+- preg_match('/\n{2,}/', $item))
+- {
+- # Replace marker with the appropriate whitespace indentation
+- $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
+- $item = $this->runBlockGamut($this->outdent($item)."\n");
+- }
+- else {
+- # Recursion for sub-lists:
+- $item = $this->doLists($this->outdent($item));
+- $item = preg_replace('/\n+$/', '', $item);
+- $item = $this->runSpanGamut($item);
+- }
+-
+- return "<li>" . $item . "</li>\n";
+- }
+-
+-
+- function doCodeBlocks($text) {
+- #
+- # Process Markdown `<pre><code>` blocks.
+- #
+- $text = preg_replace_callback('{
+- (?:\n\n|\A\n?)
+- ( # $1 = the code block -- one or more lines, starting with a space/tab
+- (?>
+- [ ]{'.$this->tab_width.'} # Lines must start with a tab or a tab-width of spaces
+- .*\n+
+- )+
+- )
+- ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
+- }xm',
+- array(&$this, '_doCodeBlocks_callback'), $text);
+-
+- return $text;
+- }
+- function _doCodeBlocks_callback($matches) {
+- $codeblock = $matches[1];
+-
+- $codeblock = $this->outdent($codeblock);
+- $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+-
+- # trim leading newlines and trailing newlines
+- $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
+-
+- $codeblock = "<pre><code>$codeblock\n</code></pre>";
+- return "\n\n".$this->hashBlock($codeblock)."\n\n";
+- }
+-
+-
+- function makeCodeSpan($code) {
+- #
+- # Create a code span markup for $code. Called from handleSpanToken.
+- #
+- $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
+- return $this->hashPart("<code>$code</code>");
+- }
+-
+-
+- var $em_relist = array(
+- '' => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S)(?![.,:;]\s)',
+- '*' => '(?<=\S)(?<!\*)\*(?!\*)',
+- '_' => '(?<=\S)(?<!_)_(?!_)',
+- );
+- var $strong_relist = array(
+- '' => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S)(?![.,:;]\s)',
+- '**' => '(?<=\S)(?<!\*)\*\*(?!\*)',
+- '__' => '(?<=\S)(?<!_)__(?!_)',
+- );
+- var $em_strong_relist = array(
+- '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S)(?![.,:;]\s)',
+- '***' => '(?<=\S)(?<!\*)\*\*\*(?!\*)',
+- '___' => '(?<=\S)(?<!_)___(?!_)',
+- );
+- var $em_strong_prepared_relist;
+-
+- function prepareItalicsAndBold() {
+- #
+- # Prepare regular expressions for seraching emphasis tokens in any
+- # context.
+- #
+- foreach ($this->em_relist as $em => $em_re) {
+- foreach ($this->strong_relist as $strong => $strong_re) {
+- # Construct list of allowed token expressions.
+- $token_relist = array();
+- if (isset($this->em_strong_relist["$em$strong"])) {
+- $token_relist[] = $this->em_strong_relist["$em$strong"];
+- }
+- $token_relist[] = $em_re;
+- $token_relist[] = $strong_re;
+-
+- # Construct master expression from list.
+- $token_re = '{('. implode('|', $token_relist) .')}';
+- $this->em_strong_prepared_relist["$em$strong"] = $token_re;
+- }
+- }
+- }
+-
+- function doItalicsAndBold($text) {
+- $token_stack = array('');
+- $text_stack = array('');
+- $em = '';
+- $strong = '';
+- $tree_char_em = false;
+-
+- while (1) {
+- #
+- # Get prepared regular expression for seraching emphasis tokens
+- # in current context.
+- #
+- $token_re = $this->em_strong_prepared_relist["$em$strong"];
+-
+- #
+- # Each loop iteration seach for the next emphasis token.
+- # Each token is then passed to handleSpanToken.
+- #
+- $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+- $text_stack[0] .= $parts[0];
+- $token =& $parts[1];
+- $text =& $parts[2];
+-
+- if (empty($token)) {
+- # Reached end of text span: empty stack without emitting.
+- # any more emphasis.
+- while ($token_stack[0]) {
+- $text_stack[1] .= array_shift($token_stack);
+- $text_stack[0] .= array_shift($text_stack);
+- }
+- break;
+- }
+-
+- $token_len = strlen($token);
+- if ($tree_char_em) {
+- # Reached closing marker while inside a three-char emphasis.
+- if ($token_len == 3) {
+- # Three-char closing marker, close em and strong.
+- array_shift($token_stack);
+- $span = array_shift($text_stack);
+- $span = $this->runSpanGamut($span);
+- $span = "<strong><em>$span</em></strong>";
+- $text_stack[0] .= $this->hashPart($span);
+- $em = '';
+- $strong = '';
+- } else {
+- # Other closing marker: close one em or strong and
+- # change current token state to match the other
+- $token_stack[0] = str_repeat($token{0}, 3-$token_len);
+- $tag = $token_len == 2 ? "strong" : "em";
+- $span = $text_stack[0];
+- $span = $this->runSpanGamut($span);
+- $span = "<$tag>$span</$tag>";
+- $text_stack[0] = $this->hashPart($span);
+- $$tag = ''; # $$tag stands for $em or $strong
+- }
+- $tree_char_em = false;
+- } else if ($token_len == 3) {
+- if ($em) {
+- # Reached closing marker for both em and strong.
+- # Closing strong marker:
+- for ($i = 0; $i < 2; ++$i) {
+- $shifted_token = array_shift($token_stack);
+- $tag = strlen($shifted_token) == 2 ? "strong" : "em";
+- $span = array_shift($text_stack);
+- $span = $this->runSpanGamut($span);
+- $span = "<$tag>$span</$tag>";
+- $text_stack[0] .= $this->hashPart($span);
+- $$tag = ''; # $$tag stands for $em or $strong
+- }
+- } else {
+- # Reached opening three-char emphasis marker. Push on token
+- # stack; will be handled by the special condition above.
+- $em = $token{0};
+- $strong = "$em$em";
+- array_unshift($token_stack, $token);
+- array_unshift($text_stack, '');
+- $tree_char_em = true;
+- }
+- } else if ($token_len == 2) {
+- if ($strong) {
+- # Unwind any dangling emphasis marker:
+- if (strlen($token_stack[0]) == 1) {
+- $text_stack[1] .= array_shift($token_stack);
+- $text_stack[0] .= array_shift($text_stack);
+- }
+- # Closing strong marker:
+- array_shift($token_stack);
+- $span = array_shift($text_stack);
+- $span = $this->runSpanGamut($span);
+- $span = "<strong>$span</strong>";
+- $text_stack[0] .= $this->hashPart($span);
+- $strong = '';
+- } else {
+- array_unshift($token_stack, $token);
+- array_unshift($text_stack, '');
+- $strong = $token;
+- }
+- } else {
+- # Here $token_len == 1
+- if ($em) {
+- if (strlen($token_stack[0]) == 1) {
+- # Closing emphasis marker:
+- array_shift($token_stack);
+- $span = array_shift($text_stack);
+- $span = $this->runSpanGamut($span);
+- $span = "<em>$span</em>";
+- $text_stack[0] .= $this->hashPart($span);
+- $em = '';
+- } else {
+- $text_stack[0] .= $token;
+- }
+- } else {
+- array_unshift($token_stack, $token);
+- array_unshift($text_stack, '');
+- $em = $token;
+- }
+- }
+- }
+- return $text_stack[0];
+- }
+-
+-
+- function doBlockQuotes($text) {
+- $text = preg_replace_callback('/
+- ( # Wrap whole match in $1
+- (?>
+- ^[ ]*>[ ]? # ">" at the start of a line
+- .+\n # rest of the first line
+- (.+\n)* # subsequent consecutive lines
+- \n* # blanks
+- )+
+- )
+- /xm',
+- array(&$this, '_doBlockQuotes_callback'), $text);
+-
+- return $text;
+- }
+- function _doBlockQuotes_callback($matches) {
+- $bq = $matches[1];
+- # trim one level of quoting - trim whitespace-only lines
+- $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
+- $bq = $this->runBlockGamut($bq); # recurse
+-
+- $bq = preg_replace('/^/m', " ", $bq);
+- # These leading spaces cause problem with <pre> content,
+- # so we need to fix that:
+- $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
+- array(&$this, '_DoBlockQuotes_callback2'), $bq);
+-
+- return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
+- }
+- function _doBlockQuotes_callback2($matches) {
+- $pre = $matches[1];
+- $pre = preg_replace('/^ /m', '', $pre);
+- return $pre;
+- }
+-
+-
+- function formParagraphs($text) {
+- #
+- # Params:
+- # $text - string to process with html <p> tags
+- #
+- # Strip leading and trailing lines:
+- $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+-
+- $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+-
+- #
+- # Wrap <p> tags and unhashify HTML blocks
+- #
+- foreach ($grafs as $key => $value) {
+- if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
+- # Is a paragraph.
+- $value = $this->runSpanGamut($value);
+- $value = preg_replace('/^([ ]*)/', "<p>", $value);
+- $value .= "</p>";
+- $grafs[$key] = $this->unhash($value);
+- }
+- else {
+- # Is a block.
+- # Modify elements of @grafs in-place...
+- $graf = $value;
+- $block = $this->html_hashes[$graf];
+- $graf = $block;
+-// if (preg_match('{
+-// \A
+-// ( # $1 = <div> tag
+-// <div \s+
+-// [^>]*
+-// \b
+-// markdown\s*=\s* ([\'"]) # $2 = attr quote char
+-// 1
+-// \2
+-// [^>]*
+-// >
+-// )
+-// ( # $3 = contents
+-// .*
+-// )
+-// (</div>) # $4 = closing tag
+-// \z
+-// }xs', $block, $matches))
+-// {
+-// list(, $div_open, , $div_content, $div_close) = $matches;
+-//
+-// # We can't call Markdown(), because that resets the hash;
+-// # that initialization code should be pulled into its own sub, though.
+-// $div_content = $this->hashHTMLBlocks($div_content);
+-//
+-// # Run document gamut methods on the content.
+-// foreach ($this->document_gamut as $method => $priority) {
+-// $div_content = $this->$method($div_content);
+-// }
+-//
+-// $div_open = preg_replace(
+-// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
+-//
+-// $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
+-// }
+- $grafs[$key] = $graf;
+- }
+- }
+-
+- return implode("\n\n", $grafs);
+- }
+-
+-
+- function encodeAttribute($text) {
+- #
+- # Encode text for a double-quoted HTML attribute. This function
+- # is *not* suitable for attributes enclosed in single quotes.
+- #
+- $text = $this->encodeAmpsAndAngles($text);
+- $text = str_replace('"', '&quot;', $text);
+- return $text;
+- }
+-
+-
+- function encodeAmpsAndAngles($text) {
+- #
+- # Smart processing for ampersands and angle brackets that need to
+- # be encoded. Valid character entities are left alone unless the
+- # no-entities mode is set.
+- #
+- if ($this->no_entities) {
+- $text = str_replace('&', '&amp;', $text);
+- } else {
+- # Ampersand-encoding based entirely on Nat Irons's Amputator
+- # MT plugin: <http://bumppo.net/projects/amputator/>
+- $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
+- '&amp;', $text);;
+- }
+- # Encode remaining <'s
+- $text = str_replace('<', '&lt;', $text);
+-
+- return $text;
+- }
+-
+-
+- function doAutoLinks($text) {
+- $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i',
+- array(&$this, '_doAutoLinks_url_callback'), $text);
+-
+- # Email addresses: <address@domain.foo>
+- $text = preg_replace_callback('{
+- <
+- (?:mailto:)?
+- (
+- [-.\w\x80-\xFF]+
+- \@
+- [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
+- )
+- >
+- }xi',
+- array(&$this, '_doAutoLinks_email_callback'), $text);
+-
+- return $text;
+- }
+- function _doAutoLinks_url_callback($matches) {
+- $url = $this->encodeAttribute($matches[1]);
+- $link = "<a href=\"$url\">$url</a>";
+- return $this->hashPart($link);
+- }
+- function _doAutoLinks_email_callback($matches) {
+- $address = $matches[1];
+- $link = $this->encodeEmailAddress($address);
+- return $this->hashPart($link);
+- }
+-
+-
+- function encodeEmailAddress($addr) {
+- #
+- # Input: an email address, e.g. "foo@example.com"
+- #
+- # Output: the email address as a mailto link, with each character
+- # of the address encoded as either a decimal or hex entity, in
+- # the hopes of foiling most address harvesting spam bots. E.g.:
+- #
+- # <p><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
+- # &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
+- # &#x6d;">&#x66;o&#111;&#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;
+- # &#101;&#46;&#x63;&#111;&#x6d;</a></p>
+- #
+- # Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
+- # With some optimizations by Milian Wolff.
+- #
+- $addr = "mailto:" . $addr;
+- $chars = preg_split('/(?<!^)(?!$)/', $addr);
+- $seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
+-
+- foreach ($chars as $key => $char) {
+- $ord = ord($char);
+- # Ignore non-ascii chars.
+- if ($ord < 128) {
+- $r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
+- # roughly 10% raw, 45% hex, 45% dec
+- # '@' *must* be encoded. I insist.
+- if ($r > 90 && $char != '@') /* do nothing */;
+- else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
+- else $chars[$key] = '&#'.$ord.';';
+- }
+- }
+-
+- $addr = implode('', $chars);
+- $text = implode('', array_slice($chars, 7)); # text without `mailto:`
+- $addr = "<a href=\"$addr\">$text</a>";
+-
+- return $addr;
+- }
+-
+-
+- function parseSpan($str) {
+- #
+- # Take the string $str and parse it into tokens, hashing embeded HTML,
+- # escaped characters and handling code spans.
+- #
+- $output = '';
+-
+- $span_re = '{
+- (
+- \\\\'.$this->escape_chars_re.'
+- |
+- (?<![`\\\\])
+- `+ # code span marker
+- '.( $this->no_markup ? '' : '
+- |
+- <!-- .*? --> # comment
+- |
+- <\?.*?\?> | <%.*?%> # processing instruction
+- |
+- <[/!$]?[-a-zA-Z0-9:]+ # regular tags
+- (?>
+- \s
+- (?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
+- )?
+- >
+- ').'
+- )
+- }xs';
+-
+- while (1) {
+- #
+- # Each loop iteration seach for either the next tag, the next
+- # openning code span marker, or the next escaped character.
+- # Each token is then passed to handleSpanToken.
+- #
+- $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
+-
+- # Create token from text preceding tag.
+- if ($parts[0] != "") {
+- $output .= $parts[0];
+- }
+-
+- # Check if we reach the end.
+- if (isset($parts[1])) {
+- $output .= $this->handleSpanToken($parts[1], $parts[2]);
+- $str = $parts[2];
+- }
+- else {
+- break;
+- }
+- }
+-
+- return $output;
+- }
+-
+-
+- function handleSpanToken($token, &$str) {
+- #
+- # Handle $token provided by parseSpan by determining its nature and
+- # returning the corresponding value that should replace it.
+- #
+- switch ($token{0}) {
+- case "\\":
+- return $this->hashPart("&#". ord($token{1}). ";");
+- case "`":
+- # Search for end marker in remaining text.
+- if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
+- $str, $matches))
+- {
+- $str = $matches[2];
+- $codespan = $this->makeCodeSpan($matches[1]);
+- return $this->hashPart($codespan);
+- }
+- return $token; // return as text since no ending marker found.
+- default:
+- return $this->hashPart($token);
+- }
+- }
+-
+-
+- function outdent($text) {
+- #
+- # Remove one level of line-leading tabs or spaces
+- #
+- return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
+- }
+-
+-
+- # String length function for detab. `_initDetab` will create a function to
+- # hanlde UTF-8 if the default function does not exist.
+- var $utf8_strlen = 'mb_strlen';
+-
+- function detab($text) {
+- #
+- # Replace tabs with the appropriate amount of space.
+- #
+- # For each line we separate the line in blocks delemited by
+- # tab characters. Then we reconstruct every line by adding the
+- # appropriate number of space between each blocks.
+-
+- $text = preg_replace_callback('/^.*\t.*$/m',
+- array(&$this, '_detab_callback'), $text);
+-
+- return $text;
+- }
+- function _detab_callback($matches) {
+- $line = $matches[0];
+- $strlen = $this->utf8_strlen; # strlen function for UTF-8.
+-
+- # Split in blocks.
+- $blocks = explode("\t", $line);
+- # Add each blocks to the line.
+- $line = $blocks[0];
+- unset($blocks[0]); # Do not add first block twice.
+- foreach ($blocks as $block) {
+- # Calculate amount of space, insert spaces, insert block.
+- $amount = $this->tab_width -
+- $strlen($line, 'UTF-8') % $this->tab_width;
+- $line .= str_repeat(" ", $amount) . $block;
+- }
+- return $line;
+- }
+- function _initDetab() {
+- #
+- # Check for the availability of the function in the `utf8_strlen` property
+- # (initially `mb_strlen`). If the function is not available, create a
+- # function that will loosely count the number of UTF-8 characters with a
+- # regular expression.
+- #
+- if (function_exists($this->utf8_strlen)) return;
+- $this->utf8_strlen = create_function('$text', 'return preg_match_all(
+- "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/",
+- $text, $m);');
+- }
+-
+-
+- function unhash($text) {
+- #
+- # Swap back in all the tags hashed by _HashHTMLBlocks.
+- #
+- return preg_replace_callback('/(.)\x1A[0-9]+\1/',
+- array(&$this, '_unhash_callback'), $text);
+- }
+- function _unhash_callback($matches) {
+- return $this->html_hashes[$matches[0]];
+- }
+-
+-}
+-
+-
+-#
+-# Markdown Extra Parser Class
+-#
+-
+-class MarkdownExtra_Parser extends Markdown_Parser {
+-
+- # Prefix for footnote ids.
+- var $fn_id_prefix = "";
+-
+- # Optional title attribute for footnote links and backlinks.
+- var $fn_link_title = MARKDOWN_FN_LINK_TITLE;
+- var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE;
+-
+- # Optional class attribute for footnote links and backlinks.
+- var $fn_link_class = MARKDOWN_FN_LINK_CLASS;
+- var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS;
+-
+- # Predefined abbreviations.
+- var $predef_abbr = array();
+-
+-
+- function MarkdownExtra_Parser() {
+- #
+- # Constructor function. Initialize the parser object.
+- #
+- # Add extra escapable characters before parent constructor
+- # initialize the table.
+- $this->escape_chars .= ':|';
+-
+- # Insert extra document, block, and span transformations.
+- # Parent constructor will do the sorting.
+- $this->document_gamut += array(
+- "doFencedCodeBlocks" => 5,
+- "stripFootnotes" => 15,
+- "stripAbbreviations" => 25,
+- "appendFootnotes" => 50,
+- );
+- $this->block_gamut += array(
+- "doFencedCodeBlocks" => 5,
+- "doTables" => 15,
+- "doDefLists" => 45,
+- );
+- $this->span_gamut += array(
+- "doFootnotes" => 5,
+- "doAbbreviations" => 70,
+- );
+-
+- parent::Markdown_Parser();
+- }
+-
+-
+- # Extra variables used during extra transformations.
+- var $footnotes = array();
+- var $footnotes_ordered = array();
+- var $abbr_desciptions = array();
+- var $abbr_word_re = '';
+-
+- # Give the current footnote number.
+- var $footnote_counter = 1;
+-
+-
+- function setup() {
+- #
+- # Setting up Extra-specific variables.
+- #
+- parent::setup();
+-
+- $this->footnotes = array();
+- $this->footnotes_ordered = array();
+- $this->abbr_desciptions = array();
+- $this->abbr_word_re = '';
+- $this->footnote_counter = 1;
+-
+- foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
+- if ($this->abbr_word_re)
+- $this->abbr_word_re .= '|';
+- $this->abbr_word_re .= preg_quote($abbr_word);
+- $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+- }
+- }
+-
+- function teardown() {
+- #
+- # Clearing Extra-specific variables.
+- #
+- $this->footnotes = array();
+- $this->footnotes_ordered = array();
+- $this->abbr_desciptions = array();
+- $this->abbr_word_re = '';
+-
+- parent::teardown();
+- }
+-
+-
+- ### HTML Block Parser ###
+-
+- # Tags that are always treated as block tags:
+- var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend';
+-
+- # Tags treated as block tags only if the opening tag is alone on it's line:
+- var $context_block_tags_re = 'script|noscript|math|ins|del';
+-
+- # Tags where markdown="1" default to span mode:
+- var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
+-
+- # Tags which must not have their contents modified, no matter where
+- # they appear:
+- var $clean_tags_re = 'script|math';
+-
+- # Tags that do not need to be closed.
+- var $auto_close_tags_re = 'hr|img';
+-
+-
+- function hashHTMLBlocks($text) {
+- #
+- # Hashify HTML Blocks and "clean tags".
+- #
+- # We only want to do this for block-level HTML tags, such as headers,
+- # lists, and tables. That's because we still want to wrap <p>s around
+- # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+- # phrase emphasis, and spans. The list of tags we're looking for is
+- # hard-coded.
+- #
+- # This works by calling _HashHTMLBlocks_InMarkdown, which then calls
+- # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
+- # attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back
+- # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
+- # These two functions are calling each other. It's recursive!
+- #
+- #
+- # Call the HTML-in-Markdown hasher.
+- #
+- list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
+-
+- return $text;
+- }
+- function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
+- $enclosing_tag_re = '', $span = false)
+- {
+- #
+- # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
+- #
+- # * $indent is the number of space to be ignored when checking for code
+- # blocks. This is important because if we don't take the indent into
+- # account, something like this (which looks right) won't work as expected:
+- #
+- # <div>
+- # <div markdown="1">
+- # Hello World. <-- Is this a Markdown code block or text?
+- # </div> <-- Is this a Markdown code block or a real tag?
+- # <div>
+- #
+- # If you don't like this, just don't indent the tag on which
+- # you apply the markdown="1" attribute.
+- #
+- # * If $enclosing_tag_re is not empty, stops at the first unmatched closing
+- # tag with that name. Nested tags supported.
+- #
+- # * If $span is true, text inside must treated as span. So any double
+- # newline will be replaced by a single newline so that it does not create
+- # paragraphs.
+- #
+- # Returns an array of that form: ( processed text , remaining text )
+- #
+- if ($text === '') return array('', '');
+-
+- # Regex to check for the presense of newlines around a block tag.
+- $newline_before_re = '/(?:^\n?|\n\n)*$/';
+- $newline_after_re =
+- '{
+- ^ # Start of text following the tag.
+- (?>[ ]*<!--.*?-->)? # Optional comment.
+- [ ]*\n # Must be followed by newline.
+- }xs';
+-
+- # Regex to match any tag.
+- $block_tag_re =
+- '{
+- ( # $2: Capture hole tag.
+- </? # Any opening or closing tag.
+- (?> # Tag name.
+- '.$this->block_tags_re.' |
+- '.$this->context_block_tags_re.' |
+- '.$this->clean_tags_re.' |
+- (?!\s)'.$enclosing_tag_re.'
+- )
+- (?:
+- (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
+- (?>
+- ".*?" | # Double quotes (can contain `>`)
+- \'.*?\' | # Single quotes (can contain `>`)
+- .+? # Anything but quotes and `>`.
+- )*?
+- )?
+- > # End of tag.
+- |
+- <!-- .*? --> # HTML Comment
+- |
+- <\?.*?\?> | <%.*?%> # Processing instruction
+- |
+- <!\[CDATA\[.*?\]\]> # CData Block
+- |
+- # Code span marker
+- `+
+- '. ( !$span ? ' # If not in span.
+- |
+- # Indented code block
+- (?> ^[ ]*\n? | \n[ ]*\n )
+- [ ]{'.($indent+4).'}[^\n]* \n
+- (?>
+- (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
+- )*
+- |
+- # Fenced code block marker
+- (?> ^ | \n )
+- [ ]{'.($indent).'}~~~+[ ]*\n
+- ' : '' ). ' # End (if not is span).
+- )
+- }xs';
+-
+-
+- $depth = 0; # Current depth inside the tag tree.
+- $parsed = ""; # Parsed text that will be returned.
+-
+- #
+- # Loop through every tag until we find the closing tag of the parent
+- # or loop until reaching the end of text if no parent tag specified.
+- #
+- do {
+- #
+- # Split the text using the first $tag_match pattern found.
+- # Text before pattern will be first in the array, text after
+- # pattern will be at the end, and between will be any catches made
+- # by the pattern.
+- #
+- $parts = preg_split($block_tag_re, $text, 2,
+- PREG_SPLIT_DELIM_CAPTURE);
+-
+- # If in Markdown span mode, add a empty-string span-level hash
+- # after each newline to prevent triggering any block element.
+- if ($span) {
+- $void = $this->hashPart("", ':');
+- $newline = "$void\n";
+- $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
+- }
+-
+- $parsed .= $parts[0]; # Text before current tag.
+-
+- # If end of $text has been reached. Stop loop.
+- if (count($parts) < 3) {
+- $text = "";
+- break;
+- }
+-
+- $tag = $parts[1]; # Tag to handle.
+- $text = $parts[2]; # Remaining text after current tag.
+- $tag_re = preg_quote($tag); # For use in a regular expression.
+-
+- #
+- # Check for: Code span marker
+- #
+- if ($tag{0} == "`") {
+- # Find corresponding end marker.
+- $tag_re = preg_quote($tag);
+- if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
+- $text, $matches))
+- {
+- # End marker found: pass text unchanged until marker.
+- $parsed .= $tag . $matches[0];
+- $text = substr($text, strlen($matches[0]));
+- }
+- else {
+- # Unmatched marker: just skip it.
+- $parsed .= $tag;
+- }
+- }
+- #
+- # Check for: Indented code block or fenced code block marker.
+- #
+- else if ($tag{0} == "\n" || $tag{0} == "~") {
+- if ($tag{1} == "\n" || $tag{1} == " ") {
+- # Indented code block: pass it unchanged, will be handled
+- # later.
+- $parsed .= $tag;
+- }
+- else {
+- # Fenced code block marker: find matching end marker.
+- $tag_re = preg_quote(trim($tag));
+- if (preg_match('{^(?>.*\n)+?'.$tag_re.' *\n}', $text,
+- $matches))
+- {
+- # End marker found: pass text unchanged until marker.
+- $parsed .= $tag . $matches[0];
+- $text = substr($text, strlen($matches[0]));
+- }
+- else {
+- # No end marker: just skip it.
+- $parsed .= $tag;
+- }
+- }
+- }
+- #
+- # Check for: Opening Block level tag or
+- # Opening Context Block tag (like ins and del)
+- # used as a block tag (tag is alone on it's line).
+- #
+- else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
+- ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
+- preg_match($newline_before_re, $parsed) &&
+- preg_match($newline_after_re, $text) )
+- )
+- {
+- # Need to parse tag and following text using the HTML parser.
+- list($block_text, $text) =
+- $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
+-
+- # Make sure it stays outside of any paragraph by adding newlines.
+- $parsed .= "\n\n$block_text\n\n";
+- }
+- #
+- # Check for: Clean tag (like script, math)
+- # HTML Comments, processing instructions.
+- #
+- else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
+- $tag{1} == '!' || $tag{1} == '?')
+- {
+- # Need to parse tag and following text using the HTML parser.
+- # (don't check for markdown attribute)
+- list($block_text, $text) =
+- $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
+-
+- $parsed .= $block_text;
+- }
+- #
+- # Check for: Tag with same name as enclosing tag.
+- #
+- else if ($enclosing_tag_re !== '' &&
+- # Same name as enclosing tag.
+- preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
+- {
+- #
+- # Increase/decrease nested tag count.
+- #
+- if ($tag{1} == '/') $depth--;
+- else if ($tag{strlen($tag)-2} != '/') $depth++;
+-
+- if ($depth < 0) {
+- #
+- # Going out of parent element. Clean up and break so we
+- # return to the calling function.
+- #
+- $text = $tag . $text;
+- break;
+- }
+-
+- $parsed .= $tag;
+- }
+- else {
+- $parsed .= $tag;
+- }
+- } while ($depth >= 0);
+-
+- return array($parsed, $text);
+- }
+- function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
+- #
+- # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
+- #
+- # * Calls $hash_method to convert any blocks.
+- # * Stops when the first opening tag closes.
+- # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
+- # (it is not inside clean tags)
+- #
+- # Returns an array of that form: ( processed text , remaining text )
+- #
+- if ($text === '') return array('', '');
+-
+- # Regex to match `markdown` attribute inside of a tag.
+- $markdown_attr_re = '
+- {
+- \s* # Eat whitespace before the `markdown` attribute
+- markdown
+- \s*=\s*
+- (?>
+- (["\']) # $1: quote delimiter
+- (.*?) # $2: attribute value
+- \1 # matching delimiter
+- |
+- ([^\s>]*) # $3: unquoted attribute value
+- )
+- () # $4: make $3 always defined (avoid warnings)
+- }xs';
+-
+- # Regex to match any tag.
+- $tag_re = '{
+- ( # $2: Capture hole tag.
+- </? # Any opening or closing tag.
+- [\w:$]+ # Tag name.
+- (?:
+- (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
+- (?>
+- ".*?" | # Double quotes (can contain `>`)
+- \'.*?\' | # Single quotes (can contain `>`)
+- .+? # Anything but quotes and `>`.
+- )*?
+- )?
+- > # End of tag.
+- |
+- <!-- .*? --> # HTML Comment
+- |
+- <\?.*?\?> | <%.*?%> # Processing instruction
+- |
+- <!\[CDATA\[.*?\]\]> # CData Block
+- )
+- }xs';
+-
+- $original_text = $text; # Save original text in case of faliure.
+-
+- $depth = 0; # Current depth inside the tag tree.
+- $block_text = ""; # Temporary text holder for current text.
+- $parsed = ""; # Parsed text that will be returned.
+-
+- #
+- # Get the name of the starting tag.
+- # (This pattern makes $base_tag_name_re safe without quoting.)
+- #
+- if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
+- $base_tag_name_re = $matches[1];
+-
+- #
+- # Loop through every tag until we find the corresponding closing tag.
+- #
+- do {
+- #
+- # Split the text using the first $tag_match pattern found.
+- # Text before pattern will be first in the array, text after
+- # pattern will be at the end, and between will be any catches made
+- # by the pattern.
+- #
+- $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+-
+- if (count($parts) < 3) {
+- #
+- # End of $text reached with unbalenced tag(s).
+- # In that case, we return original text unchanged and pass the
+- # first character as filtered to prevent an infinite loop in the
+- # parent function.
+- #
+- return array($original_text{0}, substr($original_text, 1));
+- }
+-
+- $block_text .= $parts[0]; # Text before current tag.
+- $tag = $parts[1]; # Tag to handle.
+- $text = $parts[2]; # Remaining text after current tag.
+-
+- #
+- # Check for: Auto-close tag (like <hr/>)
+- # Comments and Processing Instructions.
+- #
+- if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
+- $tag{1} == '!' || $tag{1} == '?')
+- {
+- # Just add the tag to the block as if it was text.
+- $block_text .= $tag;
+- }
+- else {
+- #
+- # Increase/decrease nested tag count. Only do so if
+- # the tag's name match base tag's.
+- #
+- if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
+- if ($tag{1} == '/') $depth--;
+- else if ($tag{strlen($tag)-2} != '/') $depth++;
+- }
+-
+- #
+- # Check for `markdown="1"` attribute and handle it.
+- #
+- if ($md_attr &&
+- preg_match($markdown_attr_re, $tag, $attr_m) &&
+- preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
+- {
+- # Remove `markdown` attribute from opening tag.
+- $tag = preg_replace($markdown_attr_re, '', $tag);
+-
+- # Check if text inside this tag must be parsed in span mode.
+- $this->mode = $attr_m[2] . $attr_m[3];
+- $span_mode = $this->mode == 'span' || $this->mode != 'block' &&
+- preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
+-
+- # Calculate indent before tag.
+- if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
+- $strlen = $this->utf8_strlen;
+- $indent = $strlen($matches[1], 'UTF-8');
+- } else {
+- $indent = 0;
+- }
+-
+- # End preceding block with this tag.
+- $block_text .= $tag;
+- $parsed .= $this->$hash_method($block_text);
+-
+- # Get enclosing tag name for the ParseMarkdown function.
+- # (This pattern makes $tag_name_re safe without quoting.)
+- preg_match('/^<([\w:$]*)\b/', $tag, $matches);
+- $tag_name_re = $matches[1];
+-
+- # Parse the content using the HTML-in-Markdown parser.
+- list ($block_text, $text)
+- = $this->_hashHTMLBlocks_inMarkdown($text, $indent,
+- $tag_name_re, $span_mode);
+-
+- # Outdent markdown text.
+- if ($indent > 0) {
+- $block_text = preg_replace("/^[ ]{1,$indent}/m", "",
+- $block_text);
+- }
+-
+- # Append tag content to parsed text.
+- if (!$span_mode) $parsed .= "\n\n$block_text\n\n";
+- else $parsed .= "$block_text";
+-
+- # Start over a new block.
+- $block_text = "";
+- }
+- else $block_text .= $tag;
+- }
+-
+- } while ($depth > 0);
+-
+- #
+- # Hash last block text that wasn't processed inside the loop.
+- #
+- $parsed .= $this->$hash_method($block_text);
+-
+- return array($parsed, $text);
+- }
+-
+-
+- function hashClean($text) {
+- #
+- # Called whenever a tag must be hashed when a function insert a "clean" tag
+- # in $text, it pass through this function and is automaticaly escaped,
+- # blocking invalid nested overlap.
+- #
+- return $this->hashPart($text, 'C');
+- }
+-
+-
+- function doHeaders($text) {
+- #
+- # Redefined to add id attribute support.
+- #
+- # Setext-style headers:
+- # Header 1 {#header1}
+- # ========
+- #
+- # Header 2 {#header2}
+- # --------
+- #
+- $text = preg_replace_callback(
+- '{
+- (^.+?) # $1: Header text
+- (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # $2: Id attribute
+- [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
+- }mx',
+- array(&$this, '_doHeaders_callback_setext'), $text);
+-
+- # atx-style headers:
+- # # Header 1 {#header1}
+- # ## Header 2 {#header2}
+- # ## Header 2 with closing hashes ## {#header3}
+- # ...
+- # ###### Header 6 {#header2}
+- #
+- $text = preg_replace_callback('{
+- ^(\#{1,6}) # $1 = string of #\'s
+- [ ]*
+- (.+?) # $2 = Header text
+- [ ]*
+- \#* # optional closing #\'s (not counted)
+- (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute
+- [ ]*
+- \n+
+- }xm',
+- array(&$this, '_doHeaders_callback_atx'), $text);
+-
+- return $text;
+- }
+- function _doHeaders_attr($attr) {
+- if (empty($attr)) return "";
+- return " id=\"$attr\"";
+- }
+- function _doHeaders_callback_setext($matches) {
+- if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
+- return $matches[0];
+- $level = $matches[3]{0} == '=' ? 1 : 2;
+- $attr = $this->_doHeaders_attr($id =& $matches[2]);
+- $block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
+- return "\n" . $this->hashBlock($block) . "\n\n";
+- }
+- function _doHeaders_callback_atx($matches) {
+- $level = strlen($matches[1]);
+- $attr = $this->_doHeaders_attr($id =& $matches[3]);
+- $block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
+- return "\n" . $this->hashBlock($block) . "\n\n";
+- }
+-
+-
+- function doTables($text) {
+- #
+- # Form HTML tables.
+- #
+- $less_than_tab = $this->tab_width - 1;
+- #
+- # Find tables with leading pipe.
+- #
+- # | Header 1 | Header 2
+- # | -------- | --------
+- # | Cell 1 | Cell 2
+- # | Cell 3 | Cell 4
+- #
+- $text = preg_replace_callback('
+- {
+- ^ # Start of a line
+- [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+- [|] # Optional leading pipe (present)
+- (.+) \n # $1: Header row (at least one pipe)
+-
+- [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+- [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline
+-
+- ( # $3: Cells
+- (?>
+- [ ]* # Allowed whitespace.
+- [|] .* \n # Row content.
+- )*
+- )
+- (?=\n|\Z) # Stop at final double newline.
+- }xm',
+- array(&$this, '_doTable_leadingPipe_callback'), $text);
+-
+- #
+- # Find tables without leading pipe.
+- #
+- # Header 1 | Header 2
+- # -------- | --------
+- # Cell 1 | Cell 2
+- # Cell 3 | Cell 4
+- #
+- $text = preg_replace_callback('
+- {
+- ^ # Start of a line
+- [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+- (\S.*[|].*) \n # $1: Header row (at least one pipe)
+-
+- [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+- ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline
+-
+- ( # $3: Cells
+- (?>
+- .* [|] .* \n # Row content
+- )*
+- )
+- (?=\n|\Z) # Stop at final double newline.
+- }xm',
+- array(&$this, '_DoTable_callback'), $text);
+-
+- return $text;
+- }
+- function _doTable_leadingPipe_callback($matches) {
+- $head = $matches[1];
+- $underline = $matches[2];
+- $content = $matches[3];
+-
+- # Remove leading pipe for each row.
+- $content = preg_replace('/^ *[|]/m', '', $content);
+-
+- return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
+- }
+- function _doTable_callback($matches) {
+- $head = $matches[1];
+- $underline = $matches[2];
+- $content = $matches[3];
+-
+- # Remove any tailing pipes for each line.
+- $head = preg_replace('/[|] *$/m', '', $head);
+- $underline = preg_replace('/[|] *$/m', '', $underline);
+- $content = preg_replace('/[|] *$/m', '', $content);
+-
+- # Reading alignement from header underline.
+- $separators = preg_split('/ *[|] */', $underline);
+- foreach ($separators as $n => $s) {
+- if (preg_match('/^ *-+: *$/', $s)) $attr[$n] = ' align="right"';
+- else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"';
+- else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"';
+- else $attr[$n] = '';
+- }
+-
+- # Parsing span elements, including code spans, character escapes,
+- # and inline HTML tags, so that pipes inside those gets ignored.
+- $head = $this->parseSpan($head);
+- $headers = preg_split('/ *[|] */', $head);
+- $col_count = count($headers);
+-
+- # Write column headers.
+- $text = "<table>\n";
+- $text .= "<thead>\n";
+- $text .= "<tr>\n";
+- foreach ($headers as $n => $header)
+- $text .= " <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
+- $text .= "</tr>\n";
+- $text .= "</thead>\n";
+-
+- # Split content by row.
+- $rows = explode("\n", trim($content, "\n"));
+-
+- $text .= "<tbody>\n";
+- foreach ($rows as $row) {
+- # Parsing span elements, including code spans, character escapes,
+- # and inline HTML tags, so that pipes inside those gets ignored.
+- $row = $this->parseSpan($row);
+-
+- # Split row by cell.
+- $row_cells = preg_split('/ *[|] */', $row, $col_count);
+- $row_cells = array_pad($row_cells, $col_count, '');
+-
+- $text .= "<tr>\n";
+- foreach ($row_cells as $n => $cell)
+- $text .= " <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
+- $text .= "</tr>\n";
+- }
+- $text .= "</tbody>\n";
+- $text .= "</table>";
+-
+- return $this->hashBlock($text) . "\n";
+- }
+-
+-
+- function doDefLists($text) {
+- #
+- # Form HTML definition lists.
+- #
+- $less_than_tab = $this->tab_width - 1;
+-
+- # Re-usable pattern to match any entire dl list:
+- $whole_list_re = '(?>
+- ( # $1 = whole list
+- ( # $2
+- [ ]{0,'.$less_than_tab.'}
+- ((?>.*\S.*\n)+) # $3 = defined term
+- \n?
+- [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+- )
+- (?s:.+?)
+- ( # $4
+- \z
+- |
+- \n{2,}
+- (?=\S)
+- (?! # Negative lookahead for another term
+- [ ]{0,'.$less_than_tab.'}
+- (?: \S.*\n )+? # defined term
+- \n?
+- [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+- )
+- (?! # Negative lookahead for another definition
+- [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+- )
+- )
+- )
+- )'; // mx
+-
+- $text = preg_replace_callback('{
+- (?>\A\n?|(?<=\n\n))
+- '.$whole_list_re.'
+- }mx',
+- array(&$this, '_doDefLists_callback'), $text);
+-
+- return $text;
+- }
+- function _doDefLists_callback($matches) {
+- # Re-usable patterns to match list item bullets and number markers:
+- $list = $matches[1];
+-
+- # Turn double returns into triple returns, so that we can make a
+- # paragraph for the last item in a list, if necessary:
+- $result = trim($this->processDefListItems($list));
+- $result = "<dl>\n" . $result . "\n</dl>";
+- return $this->hashBlock($result) . "\n\n";
+- }
+-
+-
+- function processDefListItems($list_str) {
+- #
+- # Process the contents of a single definition list, splitting it
+- # into individual term and definition list items.
+- #
+- $less_than_tab = $this->tab_width - 1;
+-
+- # trim trailing blank lines:
+- $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+-
+- # Process definition terms.
+- $list_str = preg_replace_callback('{
+- (?>\A\n?|\n\n+) # leading line
+- ( # definition terms = $1
+- [ ]{0,'.$less_than_tab.'} # leading whitespace
+- (?![:][ ]|[ ]) # negative lookahead for a definition
+- # mark (colon) or more whitespace.
+- (?> \S.* \n)+? # actual term (not whitespace).
+- )
+- (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
+- # with a definition mark.
+- }xm',
+- array(&$this, '_processDefListItems_callback_dt'), $list_str);
+-
+- # Process actual definitions.
+- $list_str = preg_replace_callback('{
+- \n(\n+)? # leading line = $1
+- ( # marker space = $2
+- [ ]{0,'.$less_than_tab.'} # whitespace before colon
+- [:][ ]+ # definition mark (colon)
+- )
+- ((?s:.+?)) # definition text = $3
+- (?= \n+ # stop at next definition mark,
+- (?: # next term or end of text
+- [ ]{0,'.$less_than_tab.'} [:][ ] |
+- <dt> | \z
+- )
+- )
+- }xm',
+- array(&$this, '_processDefListItems_callback_dd'), $list_str);
+-
+- return $list_str;
+- }
+- function _processDefListItems_callback_dt($matches) {
+- $terms = explode("\n", trim($matches[1]));
+- $text = '';
+- foreach ($terms as $term) {
+- $term = $this->runSpanGamut(trim($term));
+- $text .= "\n<dt>" . $term . "</dt>";
+- }
+- return $text . "\n";
+- }
+- function _processDefListItems_callback_dd($matches) {
+- $leading_line = $matches[1];
+- $marker_space = $matches[2];
+- $def = $matches[3];
+-
+- if ($leading_line || preg_match('/\n{2,}/', $def)) {
+- # Replace marker with the appropriate whitespace indentation
+- $def = str_repeat(' ', strlen($marker_space)) . $def;
+- $def = $this->runBlockGamut($this->outdent($def . "\n\n"));
+- $def = "\n". $def ."\n";
+- }
+- else {
+- $def = rtrim($def);
+- $def = $this->runSpanGamut($this->outdent($def));
+- }
+-
+- return "\n<dd>" . $def . "</dd>\n";
+- }
+-
+-
+- function doFencedCodeBlocks($text) {
+- #
+- # Adding the fenced code block syntax to regular Markdown:
+- #
+- # ~~~
+- # Code block
+- # ~~~
+- #
+- $less_than_tab = $this->tab_width;
+-
+- $text = preg_replace_callback('{
+- (?:\n|\A)
+- # 1: Opening marker
+- (
+- ~{3,} # Marker: three tilde or more.
+- )
+- [ ]* \n # Whitespace and newline following marker.
+-
+- # 2: Content
+- (
+- (?>
+- (?!\1 [ ]* \n) # Not a closing marker.
+- .*\n+
+- )+
+- )
+-
+- # Closing marker.
+- \1 [ ]* \n
+- }xm',
+- array(&$this, '_doFencedCodeBlocks_callback'), $text);
+-
+- return $text;
+- }
+- function _doFencedCodeBlocks_callback($matches) {
+- $codeblock = $matches[2];
+- $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+- $codeblock = preg_replace_callback('/^\n+/',
+- array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock);
+- $codeblock = "<pre><code>$codeblock</code></pre>";
+- return "\n\n".$this->hashBlock($codeblock)."\n\n";
+- }
+- function _doFencedCodeBlocks_newlines($matches) {
+- return str_repeat("<br$this->empty_element_suffix",
+- strlen($matches[0]));
+- }
+-
+-
+- #
+- # Redefining emphasis markers so that emphasis by underscore does not
+- # work in the middle of a word.
+- #
+- var $em_relist = array(
+- '' => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?=\S)(?![.,:;]\s)',
+- '*' => '(?<=\S)(?<!\*)\*(?!\*)',
+- '_' => '(?<=\S)(?<!_)_(?![a-zA-Z0-9_])',
+- );
+- var $strong_relist = array(
+- '' => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?=\S)(?![.,:;]\s)',
+- '**' => '(?<=\S)(?<!\*)\*\*(?!\*)',
+- '__' => '(?<=\S)(?<!_)__(?![a-zA-Z0-9_])',
+- );
+- var $em_strong_relist = array(
+- '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?=\S)(?![.,:;]\s)',
+- '***' => '(?<=\S)(?<!\*)\*\*\*(?!\*)',
+- '___' => '(?<=\S)(?<!_)___(?![a-zA-Z0-9_])',
+- );
+-
+-
+- function formParagraphs($text) {
+- #
+- # Params:
+- # $text - string to process with html <p> tags
+- #
+- # Strip leading and trailing lines:
+- $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+-
+- $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+-
+- #
+- # Wrap <p> tags and unhashify HTML blocks
+- #
+- foreach ($grafs as $key => $value) {
+- $value = trim($this->runSpanGamut($value));
+-
+- # Check if this should be enclosed in a paragraph.
+- # Clean tag hashes & block tag hashes are left alone.
+- $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
+-
+- if ($is_p) {
+- $value = "<p>$value</p>";
+- }
+- $grafs[$key] = $value;
+- }
+-
+- # Join grafs in one text, then unhash HTML tags.
+- $text = implode("\n\n", $grafs);
+-
+- # Finish by removing any tag hashes still present in $text.
+- $text = $this->unhash($text);
+-
+- return $text;
+- }
+-
+-
+- ### Footnotes
+-
+- function stripFootnotes($text) {
+- #
+- # Strips link definitions from text, stores the URLs and titles in
+- # hash references.
+- #
+- $less_than_tab = $this->tab_width - 1;
+-
+- # Link defs are in the form: [^id]: url "optional title"
+- $text = preg_replace_callback('{
+- ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1
+- [ ]*
+- \n? # maybe *one* newline
+- ( # text = $2 (no blank lines allowed)
+- (?:
+- .+ # actual text
+- |
+- \n # newlines but
+- (?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
+- (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
+- # by non-indented content
+- )*
+- )
+- }xm',
+- array(&$this, '_stripFootnotes_callback'),
+- $text);
+- return $text;
+- }
+- function _stripFootnotes_callback($matches) {
+- $note_id = $this->fn_id_prefix . $matches[1];
+- $this->footnotes[$note_id] = $this->outdent($matches[2]);
+- return ''; # String that will replace the block
+- }
+-
+-
+- function doFootnotes($text) {
+- #
+- # Replace footnote references in $text [^id] with a special text-token
+- # which will be replaced by the actual footnote marker in appendFootnotes.
+- #
+- if (!$this->in_anchor) {
+- $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
+- }
+- return $text;
+- }
+-
+-
+- function appendFootnotes($text) {
+- #
+- # Append footnote list to text.
+- #
+- $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+- array(&$this, '_appendFootnotes_callback'), $text);
+-
+- if (!empty($this->footnotes_ordered)) {
+- $text .= "\n\n";
+- $text .= "<div class=\"footnotes\">\n";
+- $text .= "<hr". MARKDOWN_EMPTY_ELEMENT_SUFFIX ."\n";
+- $text .= "<ol>\n\n";
+-
+- $attr = " rev=\"footnote\"";
+- if ($this->fn_backlink_class != "") {
+- $class = $this->fn_backlink_class;
+- $class = $this->encodeAttribute($class);
+- $attr .= " class=\"$class\"";
+- }
+- if ($this->fn_backlink_title != "") {
+- $title = $this->fn_backlink_title;
+- $title = $this->encodeAttribute($title);
+- $attr .= " title=\"$title\"";
+- }
+- $num = 0;
+-
+- while (!empty($this->footnotes_ordered)) {
+- $footnote = reset($this->footnotes_ordered);
+- $note_id = key($this->footnotes_ordered);
+- unset($this->footnotes_ordered[$note_id]);
+-
+- $footnote .= "\n"; # Need to append newline before parsing.
+- $footnote = $this->runBlockGamut("$footnote\n");
+- $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+- array(&$this, '_appendFootnotes_callback'), $footnote);
+-
+- $attr = str_replace("%%", ++$num, $attr);
+- $note_id = $this->encodeAttribute($note_id);
+-
+- # Add backlink to last paragraph; create new paragraph if needed.
+- $backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
+- if (preg_match('{</p>$}', $footnote)) {
+- $footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
+- } else {
+- $footnote .= "\n\n<p>$backlink</p>";
+- }
+-
+- $text .= "<li id=\"fn:$note_id\">\n";
+- $text .= $footnote . "\n";
+- $text .= "</li>\n\n";
+- }
+-
+- $text .= "</ol>\n";
+- $text .= "</div>";
+- }
+- return $text;
+- }
+- function _appendFootnotes_callback($matches) {
+- $node_id = $this->fn_id_prefix . $matches[1];
+-
+- # Create footnote marker only if it has a corresponding footnote *and*
+- # the footnote hasn't been used by another marker.
+- if (isset($this->footnotes[$node_id])) {
+- # Transfert footnote content to the ordered list.
+- $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
+- unset($this->footnotes[$node_id]);
+-
+- $num = $this->footnote_counter++;
+- $attr = " rel=\"footnote\"";
+- if ($this->fn_link_class != "") {
+- $class = $this->fn_link_class;
+- $class = $this->encodeAttribute($class);
+- $attr .= " class=\"$class\"";
+- }
+- if ($this->fn_link_title != "") {
+- $title = $this->fn_link_title;
+- $title = $this->encodeAttribute($title);
+- $attr .= " title=\"$title\"";
+- }
+-
+- $attr = str_replace("%%", $num, $attr);
+- $node_id = $this->encodeAttribute($node_id);
+-
+- return
+- "<sup id=\"fnref:$node_id\">".
+- "<a href=\"#fn:$node_id\"$attr>$num</a>".
+- "</sup>";
+- }
+-
+- return "[^".$matches[1]."]";
+- }
+-
+-
+- ### Abbreviations ###
+-
+- function stripAbbreviations($text) {
+- #
+- # Strips abbreviations from text, stores titles in hash references.
+- #
+- $less_than_tab = $this->tab_width - 1;
+-
+- # Link defs are in the form: [id]*: url "optional title"
+- $text = preg_replace_callback('{
+- ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1
+- (.*) # text = $2 (no blank lines allowed)
+- }xm',
+- array(&$this, '_stripAbbreviations_callback'),
+- $text);
+- return $text;
+- }
+- function _stripAbbreviations_callback($matches) {
+- $abbr_word = $matches[1];
+- $abbr_desc = $matches[2];
+- if ($this->abbr_word_re)
+- $this->abbr_word_re .= '|';
+- $this->abbr_word_re .= preg_quote($abbr_word);
+- $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+- return ''; # String that will replace the block
+- }
+-
+-
+- function doAbbreviations($text) {
+- #
+- # Find defined abbreviations in text and wrap them in <abbr> elements.
+- #
+- if ($this->abbr_word_re) {
+- // cannot use the /x modifier because abbr_word_re may
+- // contain significant spaces:
+- $text = preg_replace_callback('{'.
+- '(?<![\w\x1A])'.
+- '(?:'.$this->abbr_word_re.')'.
+- '(?![\w\x1A])'.
+- '}',
+- array(&$this, '_doAbbreviations_callback'), $text);
+- }
+- return $text;
+- }
+- function _doAbbreviations_callback($matches) {
+- $abbr = $matches[0];
+- if (isset($this->abbr_desciptions[$abbr])) {
+- $desc = $this->abbr_desciptions[$abbr];
+- if (empty($desc)) {
+- return $this->hashPart("<abbr>$abbr</abbr>");
+- } else {
+- $desc = $this->encodeAttribute($desc);
+- return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
+- }
+- } else {
+- return $matches[0];
+- }
+- }
+-
+-}
+-
+-
+-/*
+-
+-PHP Markdown Extra
+-==================
+-
+-Description
+------------
+-
+-This is a PHP port of the original Markdown formatter written in Perl
+-by John Gruber. This special "Extra" version of PHP Markdown features
+-further enhancements to the syntax for making additional constructs
+-such as tables and definition list.
+-
+-Markdown is a text-to-HTML filter; it translates an easy-to-read /
+-easy-to-write structured text format into HTML. Markdown's text format
+-is most similar to that of plain text email, and supports features such
+-as headers, *emphasis*, code blocks, blockquotes, and links.
+-
+-Markdown's syntax is designed not as a generic markup language, but
+-specifically to serve as a front-end to (X)HTML. You can use span-level
+-HTML tags anywhere in a Markdown document, and you can use block level
+-HTML tags (like <div> and <table> as well).
+-
+-For more information about Markdown's syntax, see:
+-
+-<http://daringfireball.net/projects/markdown/>
+-
+-
+-Bugs
+-----
+-
+-To file bug reports please send email to:
+-
+-<michel.fortin@michelf.com>
+-
+-Please include with your report: (1) the example input; (2) the output you
+-expected; (3) the output Markdown actually produced.
+-
+-
+-Version History
+----------------
+-
+-See the readme file for detailed release notes for this version.
+-
+-
+-Copyright and License
+----------------------
+-
+-PHP Markdown & Extra
+-Copyright (c) 2004-2008 Michel Fortin
+-<http://www.michelf.com/>
+-All rights reserved.
+-
+-Based on Markdown
+-Copyright (c) 2003-2006 John Gruber
+-<http://daringfireball.net/>
+-All rights reserved.
+-
+-Redistribution and use in source and binary forms, with or without
+-modification, are permitted provided that the following conditions are
+-met:
+-
+-* Redistributions of source code must retain the above copyright notice,
+- this list of conditions and the following disclaimer.
+-
+-* Redistributions in binary form must reproduce the above copyright
+- notice, this list of conditions and the following disclaimer in the
+- documentation and/or other materials provided with the distribution.
+-
+-* Neither the name "Markdown" nor the names of its contributors may
+- be used to endorse or promote products derived from this software
+- without specific prior written permission.
+-
+-This software is provided by the copyright holders and contributors "as
+-is" and any express or implied warranties, including, but not limited
+-to, the implied warranties of merchantability and fitness for a
+-particular purpose are disclaimed. In no event shall the copyright owner
+-or contributors 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.
+-
+-*/
+-?>
+\ No newline at end of file
+diff --git a/ivfdec.c b/ivfdec.c
+index e4c9981..2b26d55 100644
+--- a/ivfdec.c
++++ b/ivfdec.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -17,10 +18,10 @@
+ #include <string.h>
+ #define VPX_CODEC_DISABLE_COMPAT 1
+ #include "vpx_config.h"
+-#include "vpx_decoder.h"
++#include "vpx/vpx_decoder.h"
+ #include "vpx_ports/vpx_timer.h"
+ #if CONFIG_VP8_DECODER
+-#include "vp8dx.h"
++#include "vpx/vp8dx.h"
+ #endif
+ #if CONFIG_MD5
+ #include "md5_utils.h"
+@@ -62,8 +63,10 @@ static const arg_def_t postprocarg = ARG_DEF(NULL, "postproc", 0,
+ "Postprocess decoded frames");
+ static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0,
+ "Show timing summary");
+-static const arg_def_t outputfile = ARG_DEF("o", "output-raw-file", 1,
++static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
+ "Output raw yv12 file instead of images");
++static const arg_def_t usey4marg = ARG_DEF("y", "y4m", 0,
++ "Output file is YUV4MPEG2");
+ static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1,
+ "Max threads to use");
+ static const arg_def_t quietarg = ARG_DEF("q", "quiet", 0,
+@@ -77,7 +80,7 @@ static const arg_def_t *all_args[] =
+ {
+ &codecarg, &prefixarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
+ &progressarg, &limitarg, &postprocarg, &summaryarg, &outputfile,
+- &threadsarg, &quietarg,
++ &usey4marg, &threadsarg, &quietarg,
+ #if CONFIG_MD5
+ &md5arg,
+ #endif
+@@ -232,9 +235,9 @@ void *out_open(const char *out_fn, int do_md5)
+ if (do_md5)
+ {
+ #if CONFIG_MD5
+- md5_ctx_t *md5_ctx = out = malloc(sizeof(md5_ctx_t));
++ MD5Context *md5_ctx = out = malloc(sizeof(MD5Context));
+ (void)out_fn;
+- md5_init(md5_ctx);
++ MD5Init(md5_ctx);
+ #endif
+ }
+ else
+@@ -256,7 +259,7 @@ void out_put(void *out, const uint8_t *buf, unsigned int len, int do_md5)
+ if (do_md5)
+ {
+ #if CONFIG_MD5
+- md5_update(out, buf, len);
++ MD5Update(out, buf, len);
+ #endif
+ }
+ else
+@@ -273,7 +276,7 @@ void out_close(void *out, const char *out_fn, int do_md5)
+ uint8_t md5[16];
+ int i;
+
+- md5_finalize(out, md5);
++ MD5Final(md5, out);
+ free(out);
+
+ for (i = 0; i < 16; i++)
+@@ -288,7 +291,12 @@ void out_close(void *out, const char *out_fn, int do_md5)
+ }
+ }
+
+-unsigned int file_is_ivf(FILE *infile, unsigned int *fourcc)
++unsigned int file_is_ivf(FILE *infile,
++ unsigned int *fourcc,
++ unsigned int *width,
++ unsigned int *height,
++ unsigned int *timebase_num,
++ unsigned int *timebase_den)
+ {
+ char raw_hdr[32];
+ int is_ivf = 0;
+@@ -305,6 +313,10 @@ unsigned int file_is_ivf(FILE *infile, unsigned int *fourcc)
+ " decode properly.");
+
+ *fourcc = mem_get_le32(raw_hdr + 8);
++ *width = mem_get_le16(raw_hdr + 12);
++ *height = mem_get_le16(raw_hdr + 14);
++ *timebase_den = mem_get_le32(raw_hdr + 16);
++ *timebase_num = mem_get_le32(raw_hdr + 20);
+ }
+ }
+
+@@ -330,6 +342,11 @@ int main(int argc, const char **argv_)
+ struct arg arg;
+ char **argv, **argi, **argj;
+ const char *fn2 = 0;
++ int use_y4m = 0;
++ unsigned int width;
++ unsigned int height;
++ unsigned int timebase_num;
++ unsigned int timebase_den;
+ void *out = NULL;
+ vpx_codec_dec_cfg_t cfg = {0};
+ #if CONFIG_VP8_DECODER
+@@ -361,6 +378,8 @@ int main(int argc, const char **argv_)
+ }
+ else if (arg_match(&arg, &outputfile, argi))
+ fn2 = arg.val;
++ else if (arg_match(&arg, &usey4marg, argi))
++ use_y4m = 1;
+ else if (arg_match(&arg, &prefixarg, argi))
+ prefix = strdup(arg.val);
+ else if (arg_match(&arg, &use_yv12, argi))
+@@ -446,10 +465,31 @@ int main(int argc, const char **argv_)
+ if (fn2)
+ out = out_open(fn2, do_md5);
+
+- is_ivf = file_is_ivf(infile, &fourcc);
++ is_ivf = file_is_ivf(infile, &fourcc, &width, &height,
++ &timebase_num, &timebase_den);
+
+ if (is_ivf)
+ {
++ if (use_y4m)
++ {
++ char buffer[128];
++ if (!fn2)
++ {
++ fprintf(stderr, "YUV4MPEG2 output only supported with -o.\n");
++ return EXIT_FAILURE;
++ }
++ /*Correct for the factor of 2 applied to the timebase in the
++ encoder.*/
++ if(timebase_den&1)timebase_num<<=1;
++ else timebase_den>>=1;
++ /*Note: We can't output an aspect ratio here because IVF doesn't
++ store one, and neither does VP8.
++ That will have to wait until these tools support WebM natively.*/
++ sprintf(buffer, "YUV4MPEG2 C%s W%u H%u F%u:%u I%c\n",
++ "420jpeg", width, height, timebase_den, timebase_num, 'p');
++ out_put(out, (unsigned char *)buffer, strlen(buffer), do_md5);
++ }
++
+ /* Try to determine the codec from the fourcc. */
+ for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+ if ((fourcc & ifaces[i].fourcc_mask) == ifaces[i].fourcc)
+@@ -465,6 +505,11 @@ int main(int argc, const char **argv_)
+ break;
+ }
+ }
++ else if(use_y4m)
++ {
++ fprintf(stderr, "YUV4MPEG2 output only supported from IVF input.\n");
++ return EXIT_FAILURE;
++ }
+
+ if (vpx_codec_dec_init(&decoder, iface ? iface : ifaces[0].iface, &cfg,
+ postproc ? VPX_CODEC_USE_POSTPROC : 0))
+@@ -533,29 +578,31 @@ int main(int argc, const char **argv_)
+ prefix, img->d_w, img->d_h, frame_in, sfx);
+ out = out_open(out_fn, do_md5);
+ }
++ else if(use_y4m)
++ out_put(out, (unsigned char *)"FRAME\n", 6, do_md5);
+
+- buf = img->planes[PLANE_Y];
++ buf = img->planes[VPX_PLANE_Y];
+
+ for (y = 0; y < img->d_h; y++)
+ {
+ out_put(out, buf, img->d_w, do_md5);
+- buf += img->stride[PLANE_Y];
++ buf += img->stride[VPX_PLANE_Y];
+ }
+
+- buf = img->planes[flipuv?PLANE_V:PLANE_U];
++ buf = img->planes[flipuv?VPX_PLANE_V:VPX_PLANE_U];
+
+ for (y = 0; y < (1 + img->d_h) / 2; y++)
+ {
+ out_put(out, buf, (1 + img->d_w) / 2, do_md5);
+- buf += img->stride[PLANE_U];
++ buf += img->stride[VPX_PLANE_U];
+ }
+
+- buf = img->planes[flipuv?PLANE_U:PLANE_V];
++ buf = img->planes[flipuv?VPX_PLANE_U:VPX_PLANE_V];
+
+ for (y = 0; y < (1 + img->d_h) / 2; y++)
+ {
+ out_put(out, buf, (1 + img->d_w) / 2, do_md5);
+- buf += img->stride[PLANE_V];
++ buf += img->stride[VPX_PLANE_V];
+ }
+
+ if (!fn2)
+diff --git a/ivfenc.c b/ivfenc.c
+index bef3d58..11f2a8f 100644
+--- a/ivfenc.c
++++ b/ivfenc.c
+@@ -1,23 +1,28 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+ /* This is a simple program that encodes YV12 files and generates ivf
+ * files using the new interface.
+ */
+-#define USE_POSIX_MMAP HAVE_SYS_MMAN_H
++#if defined(_WIN32)
++#define USE_POSIX_MMAP 0
++#else
++#define USE_POSIX_MMAP 1
++#endif
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdarg.h>
+ #include <string.h>
+-#include "vpx_encoder.h"
++#include "vpx/vpx_encoder.h"
+ #if USE_POSIX_MMAP
+ #include <sys/types.h>
+ #include <sys/stat.h>
+@@ -25,11 +30,10 @@
+ #include <fcntl.h>
+ #include <unistd.h>
+ #endif
+-#if CONFIG_VP8_ENCODER
+-#include "vp8cx.h"
+-#endif
++#include "vpx/vp8cx.h"
+ #include "vpx_ports/mem_ops.h"
+ #include "vpx_ports/vpx_timer.h"
++#include "y4minput.h"
+
+ static const char *exec_name;
+
+@@ -51,8 +55,8 @@ void die(const char *fmt, ...)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+- vprintf(fmt, ap);
+- printf("\n");
++ vfprintf(stderr, fmt, ap);
++ fprintf(stderr, "\n");
+ usage_exit();
+ }
+
+@@ -62,10 +66,10 @@ static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s)
+ {
+ const char *detail = vpx_codec_error_detail(ctx);
+
+- printf("%s: %s\n", s, vpx_codec_error(ctx));
++ fprintf(stderr, "%s: %s\n", s, vpx_codec_error(ctx));
+
+ if (detail)
+- printf(" %s\n", detail);
++ fprintf(stderr, " %s\n", detail);
+
+ exit(EXIT_FAILURE);
+ }
+@@ -215,49 +219,79 @@ vpx_fixed_buf_t stats_get(stats_io_t *stats)
+ return stats->buf;
+ }
+
++enum video_file_type
++{
++ FILE_TYPE_RAW,
++ FILE_TYPE_IVF,
++ FILE_TYPE_Y4M
++};
++
++struct detect_buffer {
++ char buf[4];
++ int valid;
++};
++
++
+ #define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
+-static int read_frame(FILE *f, vpx_image_t *img, unsigned int is_ivf)
++static int read_frame(FILE *f, vpx_image_t *img, unsigned int file_type,
++ y4m_input *y4m, struct detect_buffer *detect)
+ {
+ int plane = 0;
+
+- if (is_ivf)
++ if (file_type == FILE_TYPE_Y4M)
+ {
+- char junk[IVF_FRAME_HDR_SZ];
+-
+- /* Skip the frame header. We know how big the frame should be. See
+- * write_ivf_frame_header() for documentation on the frame header
+- * layout.
+- */
+- fread(junk, 1, IVF_FRAME_HDR_SZ, f);
++ if (y4m_input_fetch_frame(y4m, f, img) < 0)
++ return 0;
+ }
+-
+- for (plane = 0; plane < 3; plane++)
++ else
+ {
+- unsigned char *ptr;
+- int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
+- int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
+- int r;
+-
+- /* Determine the correct plane based on the image format. The for-loop
+- * always counts in Y,U,V order, but this may not match the order of
+- * the data on disk.
+- */
+- switch (plane)
++ if (file_type == FILE_TYPE_IVF)
+ {
+- case 1:
+- ptr = img->planes[img->fmt==IMG_FMT_YV12? PLANE_V : PLANE_U];
+- break;
+- case 2:
+- ptr = img->planes[img->fmt==IMG_FMT_YV12?PLANE_U : PLANE_V];
+- break;
+- default:
+- ptr = img->planes[plane];
++ char junk[IVF_FRAME_HDR_SZ];
++
++ /* Skip the frame header. We know how big the frame should be. See
++ * write_ivf_frame_header() for documentation on the frame header
++ * layout.
++ */
++ fread(junk, 1, IVF_FRAME_HDR_SZ, f);
+ }
+
+- for (r = 0; r < h; r++)
++ for (plane = 0; plane < 3; plane++)
+ {
+- fread(ptr, 1, w, f);
+- ptr += img->stride[plane];
++ unsigned char *ptr;
++ int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
++ int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
++ int r;
++
++ /* Determine the correct plane based on the image format. The for-loop
++ * always counts in Y,U,V order, but this may not match the order of
++ * the data on disk.
++ */
++ switch (plane)
++ {
++ case 1:
++ ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12? VPX_PLANE_V : VPX_PLANE_U];
++ break;
++ case 2:
++ ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12?VPX_PLANE_U : VPX_PLANE_V];
++ break;
++ default:
++ ptr = img->planes[plane];
++ }
++
++ for (r = 0; r < h; r++)
++ {
++ if (detect->valid)
++ {
++ memcpy(ptr, detect->buf, 4);
++ fread(ptr+4, 1, w-4, f);
++ detect->valid = 0;
++ }
++ else
++ fread(ptr, 1, w, f);
++
++ ptr += img->stride[plane];
++ }
+ }
+ }
+
+@@ -265,22 +299,36 @@ static int read_frame(FILE *f, vpx_image_t *img, unsigned int is_ivf)
+ }
+
+
++unsigned int file_is_y4m(FILE *infile,
++ y4m_input *y4m,
++ char detect[4])
++{
++ if(memcmp(detect, "YUV4", 4) == 0)
++ {
++ return 1;
++ }
++ return 0;
++}
++
+ #define IVF_FILE_HDR_SZ (32)
+ unsigned int file_is_ivf(FILE *infile,
+ unsigned int *fourcc,
+ unsigned int *width,
+- unsigned int *height)
++ unsigned int *height,
++ char detect[4])
+ {
+ char raw_hdr[IVF_FILE_HDR_SZ];
+ int is_ivf = 0;
+
++ if(memcmp(detect, "DKIF", 4) != 0)
++ return 0;
++
+ /* See write_ivf_file_header() for more documentation on the file header
+ * layout.
+ */
+- if (fread(raw_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ)
++ if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
++ == IVF_FILE_HDR_SZ - 4)
+ {
+- if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K'
+- && raw_hdr[2] == 'I' && raw_hdr[3] == 'F')
+ {
+ is_ivf = 1;
+
+@@ -297,8 +345,6 @@ unsigned int file_is_ivf(FILE *infile,
+ *width = mem_get_le16(raw_hdr + 12);
+ *height = mem_get_le16(raw_hdr + 14);
+ }
+- else
+- rewind(infile);
+
+ return is_ivf;
+ }
+@@ -512,28 +558,28 @@ static void usage_exit()
+ {
+ int i;
+
+- printf("Usage: %s <options> src_filename dst_filename\n", exec_name);
++ fprintf(stderr, "Usage: %s <options> src_filename dst_filename\n", exec_name);
+
+- printf("\n_options:\n");
++ fprintf(stderr, "\n_options:\n");
+ arg_show_usage(stdout, main_args);
+- printf("\n_encoder Global Options:\n");
++ fprintf(stderr, "\n_encoder Global Options:\n");
+ arg_show_usage(stdout, global_args);
+- printf("\n_rate Control Options:\n");
++ fprintf(stderr, "\n_rate Control Options:\n");
+ arg_show_usage(stdout, rc_args);
+- printf("\n_twopass Rate Control Options:\n");
++ fprintf(stderr, "\n_twopass Rate Control Options:\n");
+ arg_show_usage(stdout, rc_twopass_args);
+- printf("\n_keyframe Placement Options:\n");
++ fprintf(stderr, "\n_keyframe Placement Options:\n");
+ arg_show_usage(stdout, kf_args);
+ #if CONFIG_VP8_ENCODER
+- printf("\n_vp8 Specific Options:\n");
++ fprintf(stderr, "\n_vp8 Specific Options:\n");
+ arg_show_usage(stdout, vp8_args);
+ #endif
+- printf("\n"
++ fprintf(stderr, "\n"
+ "Included encoders:\n"
+ "\n");
+
+ for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
+- printf(" %-6s - %s\n",
++ fprintf(stderr, " %-6s - %s\n",
+ codecs[i].name,
+ vpx_codec_iface_name(codecs[i].iface));
+
+@@ -566,8 +612,10 @@ int main(int argc, const char **argv_)
+ static const int *ctrl_args_map = NULL;
+ int verbose = 0, show_psnr = 0;
+ int arg_use_i420 = 1;
++ int arg_have_timebase = 0;
+ unsigned long cx_time = 0;
+- unsigned int is_ivf, fourcc;
++ unsigned int file_type, fourcc;
++ y4m_input y4m;
+
+ exec_name = argv_[0];
+
+@@ -651,7 +699,7 @@ int main(int argc, const char **argv_)
+ /* DWIM: Assume the user meant passes=2 if pass=2 is specified */
+ if (one_pass_only > arg_passes)
+ {
+- printf("Warning: Assuming --pass=%d implies --passes=%d\n",
++ fprintf(stderr, "Warning: Assuming --pass=%d implies --passes=%d\n",
+ one_pass_only, one_pass_only);
+ arg_passes = one_pass_only;
+ }
+@@ -665,7 +713,8 @@ int main(int argc, const char **argv_)
+
+ if (res)
+ {
+- printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
++ fprintf(stderr, "Failed to get config: %s\n",
++ vpx_codec_err_to_string(res));
+ return EXIT_FAILURE;
+ }
+
+@@ -684,7 +733,10 @@ int main(int argc, const char **argv_)
+ else if (arg_match(&arg, &height, argi))
+ cfg.g_h = arg_parse_uint(&arg);
+ else if (arg_match(&arg, &timebase, argi))
++ {
+ cfg.g_timebase = arg_parse_rational(&arg);
++ arg_have_timebase = 1;
++ }
+ else if (arg_match(&arg, &error_resilient, argi))
+ cfg.g_error_resilient = arg_parse_uint(&arg);
+ else if (arg_match(&arg, &lag_in_frames, argi))
+@@ -722,24 +774,27 @@ int main(int argc, const char **argv_)
+ cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
+
+ if (arg_passes < 2)
+- printf("Warning: option %s ignored in one-pass mode.\n",
+- arg.name);
++ fprintf(stderr,
++ "Warning: option %s ignored in one-pass mode.\n",
++ arg.name);
+ }
+ else if (arg_match(&arg, &minsection_pct, argi))
+ {
+ cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
+
+ if (arg_passes < 2)
+- printf("Warning: option %s ignored in one-pass mode.\n",
+- arg.name);
++ fprintf(stderr,
++ "Warning: option %s ignored in one-pass mode.\n",
++ arg.name);
+ }
+ else if (arg_match(&arg, &maxsection_pct, argi))
+ {
+ cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
+
+ if (arg_passes < 2)
+- printf("Warning: option %s ignored in one-pass mode.\n",
+- arg.name);
++ fprintf(stderr,
++ "Warning: option %s ignored in one-pass mode.\n",
++ arg.name);
+ }
+ else if (arg_match(&arg, &kf_min_dist, argi))
+ cfg.kf_min_dist = arg_parse_uint(&arg);
+@@ -787,7 +842,7 @@ int main(int argc, const char **argv_)
+
+ /* Check for unrecognized options */
+ for (argi = argv; *argi; argi++)
+- if (argi[0][0] == '-')
++ if (argi[0][0] == '-' && argi[0][1])
+ die("Error: Unrecognized option %s\n", *argi);
+
+ /* Handle non-option arguments */
+@@ -797,106 +852,134 @@ int main(int argc, const char **argv_)
+ if (!in_fn || !out_fn)
+ usage_exit();
+
+- /* Parse certain options from the input file, if possible */
+- infile = fopen(in_fn, "rb");
+-
+- if (!infile)
+- {
+- printf("Failed to open input file");
+- return EXIT_FAILURE;
+- }
+-
+- is_ivf = file_is_ivf(infile, &fourcc, &cfg.g_w, &cfg.g_h);
+-
+- if (is_ivf)
+- {
+- switch (fourcc)
+- {
+- case 0x32315659:
+- arg_use_i420 = 0;
+- break;
+- case 0x30323449:
+- arg_use_i420 = 1;
+- break;
+- default:
+- printf("Unsupported fourcc (%08x) in IVF\n", fourcc);
+- return EXIT_FAILURE;
+- }
+- }
+-
+- fclose(infile);
+-
+-
+-#define SHOW(field) printf(" %-28s = %d\n", #field, cfg.field)
+-
+- if (verbose)
+- {
+- printf("Codec: %s\n", vpx_codec_iface_name(codec->iface));
+- printf("Source file: %s Format: %s\n", in_fn, arg_use_i420 ? "I420" : "YV12");
+- printf("Destination file: %s\n", out_fn);
+- printf("Encoder parameters:\n");
+-
+- SHOW(g_usage);
+- SHOW(g_threads);
+- SHOW(g_profile);
+- SHOW(g_w);
+- SHOW(g_h);
+- SHOW(g_timebase.num);
+- SHOW(g_timebase.den);
+- SHOW(g_error_resilient);
+- SHOW(g_pass);
+- SHOW(g_lag_in_frames);
+- SHOW(rc_dropframe_thresh);
+- SHOW(rc_resize_allowed);
+- SHOW(rc_resize_up_thresh);
+- SHOW(rc_resize_down_thresh);
+- SHOW(rc_end_usage);
+- SHOW(rc_target_bitrate);
+- SHOW(rc_min_quantizer);
+- SHOW(rc_max_quantizer);
+- SHOW(rc_undershoot_pct);
+- SHOW(rc_overshoot_pct);
+- SHOW(rc_buf_sz);
+- SHOW(rc_buf_initial_sz);
+- SHOW(rc_buf_optimal_sz);
+- SHOW(rc_2pass_vbr_bias_pct);
+- SHOW(rc_2pass_vbr_minsection_pct);
+- SHOW(rc_2pass_vbr_maxsection_pct);
+- SHOW(kf_mode);
+- SHOW(kf_min_dist);
+- SHOW(kf_max_dist);
+- }
+-
+- vpx_img_alloc(&raw, arg_use_i420 ? IMG_FMT_I420 : IMG_FMT_YV12,
+- cfg.g_w, cfg.g_h, 1);
+-
+- // This was added so that ivfenc will create monotically increasing
+- // timestamps. Since we create new timestamps for alt-reference frames
+- // we need to make room in the series of timestamps. Since there can
+- // only be 1 alt-ref frame ( current bitstream) multiplying by 2
+- // gives us enough room.
+- cfg.g_timebase.den *= 2;
+-
+ memset(&stats, 0, sizeof(stats));
+
+ for (pass = one_pass_only ? one_pass_only - 1 : 0; pass < arg_passes; pass++)
+ {
+ int frames_in = 0, frames_out = 0;
+ unsigned long nbytes = 0;
++ struct detect_buffer detect;
+
+- infile = fopen(in_fn, "rb");
++ /* Parse certain options from the input file, if possible */
++ infile = strcmp(in_fn, "-") ? fopen(in_fn, "rb") : stdin;
+
+ if (!infile)
+ {
+- printf("Failed to open input file");
++ fprintf(stderr, "Failed to open input file\n");
+ return EXIT_FAILURE;
+ }
+
+- outfile = fopen(out_fn, "wb");
++ fread(detect.buf, 1, 4, infile);
++ detect.valid = 0;
++
++ if (file_is_y4m(infile, &y4m, detect.buf))
++ {
++ if (y4m_input_open(&y4m, infile, detect.buf, 4) >= 0)
++ {
++ file_type = FILE_TYPE_Y4M;
++ cfg.g_w = y4m.pic_w;
++ cfg.g_h = y4m.pic_h;
++ /* Use the frame rate from the file only if none was specified
++ * on the command-line.
++ */
++ if (!arg_have_timebase)
++ {
++ cfg.g_timebase.num = y4m.fps_d;
++ cfg.g_timebase.den = y4m.fps_n;
++ }
++ arg_use_i420 = 0;
++ }
++ else
++ {
++ fprintf(stderr, "Unsupported Y4M stream.\n");
++ return EXIT_FAILURE;
++ }
++ }
++ else if (file_is_ivf(infile, &fourcc, &cfg.g_w, &cfg.g_h, detect.buf))
++ {
++ file_type = FILE_TYPE_IVF;
++ switch (fourcc)
++ {
++ case 0x32315659:
++ arg_use_i420 = 0;
++ break;
++ case 0x30323449:
++ arg_use_i420 = 1;
++ break;
++ default:
++ fprintf(stderr, "Unsupported fourcc (%08x) in IVF\n", fourcc);
++ return EXIT_FAILURE;
++ }
++ }
++ else
++ {
++ file_type = FILE_TYPE_RAW;
++ detect.valid = 1;
++ }
++#define SHOW(field) fprintf(stderr, " %-28s = %d\n", #field, cfg.field)
++
++ if (verbose && pass == 0)
++ {
++ fprintf(stderr, "Codec: %s\n", vpx_codec_iface_name(codec->iface));
++ fprintf(stderr, "Source file: %s Format: %s\n", in_fn,
++ arg_use_i420 ? "I420" : "YV12");
++ fprintf(stderr, "Destination file: %s\n", out_fn);
++ fprintf(stderr, "Encoder parameters:\n");
++
++ SHOW(g_usage);
++ SHOW(g_threads);
++ SHOW(g_profile);
++ SHOW(g_w);
++ SHOW(g_h);
++ SHOW(g_timebase.num);
++ SHOW(g_timebase.den);
++ SHOW(g_error_resilient);
++ SHOW(g_pass);
++ SHOW(g_lag_in_frames);
++ SHOW(rc_dropframe_thresh);
++ SHOW(rc_resize_allowed);
++ SHOW(rc_resize_up_thresh);
++ SHOW(rc_resize_down_thresh);
++ SHOW(rc_end_usage);
++ SHOW(rc_target_bitrate);
++ SHOW(rc_min_quantizer);
++ SHOW(rc_max_quantizer);
++ SHOW(rc_undershoot_pct);
++ SHOW(rc_overshoot_pct);
++ SHOW(rc_buf_sz);
++ SHOW(rc_buf_initial_sz);
++ SHOW(rc_buf_optimal_sz);
++ SHOW(rc_2pass_vbr_bias_pct);
++ SHOW(rc_2pass_vbr_minsection_pct);
++ SHOW(rc_2pass_vbr_maxsection_pct);
++ SHOW(kf_mode);
++ SHOW(kf_min_dist);
++ SHOW(kf_max_dist);
++ }
++
++ if(pass == (one_pass_only ? one_pass_only - 1 : 0)) {
++ if (file_type == FILE_TYPE_Y4M)
++ /*The Y4M reader does its own allocation.
++ Just initialize this here to avoid problems if we never read any
++ frames.*/
++ memset(&raw, 0, sizeof(raw));
++ else
++ vpx_img_alloc(&raw, arg_use_i420 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_YV12,
++ cfg.g_w, cfg.g_h, 1);
++
++ // This was added so that ivfenc will create monotically increasing
++ // timestamps. Since we create new timestamps for alt-reference frames
++ // we need to make room in the series of timestamps. Since there can
++ // only be 1 alt-ref frame ( current bitstream) multiplying by 2
++ // gives us enough room.
++ cfg.g_timebase.den *= 2;
++ }
++
++ outfile = strcmp(out_fn, "-") ? fopen(out_fn, "wb") : stdout;
+
+ if (!outfile)
+ {
+- printf("Failed to open output file");
++ fprintf(stderr, "Failed to open output file\n");
+ return EXIT_FAILURE;
+ }
+
+@@ -904,7 +987,7 @@ int main(int argc, const char **argv_)
+ {
+ if (!stats_open_file(&stats, stats_fn, pass))
+ {
+- printf("Failed to open statistics store\n");
++ fprintf(stderr, "Failed to open statistics store\n");
+ return EXIT_FAILURE;
+ }
+ }
+@@ -912,7 +995,7 @@ int main(int argc, const char **argv_)
+ {
+ if (!stats_open_mem(&stats, pass))
+ {
+- printf("Failed to open statistics store\n");
++ fprintf(stderr, "Failed to open statistics store\n");
+ return EXIT_FAILURE;
+ }
+ }
+@@ -947,8 +1030,8 @@ int main(int argc, const char **argv_)
+ for (i = 0; i < arg_ctrl_cnt; i++)
+ {
+ if (vpx_codec_control_(&encoder, arg_ctrls[i][0], arg_ctrls[i][1]))
+- printf("Error: Tried to set control %d = %d\n",
+- arg_ctrls[i][0], arg_ctrls[i][1]);
++ fprintf(stderr, "Error: Tried to set control %d = %d\n",
++ arg_ctrls[i][0], arg_ctrls[i][1]);
+
+ ctx_exit_on_error(&encoder, "Failed to control codec");
+ }
+@@ -964,13 +1047,15 @@ int main(int argc, const char **argv_)
+
+ if (!arg_limit || frames_in < arg_limit)
+ {
+- frame_avail = read_frame(infile, &raw, is_ivf);
++ frame_avail = read_frame(infile, &raw, file_type, &y4m,
++ &detect);
+
+ if (frame_avail)
+ frames_in++;
+
+- printf("\rPass %d/%d frame %4d/%-4d %7ldB \033[K", pass + 1,
+- arg_passes, frames_in, frames_out, nbytes);
++ fprintf(stderr,
++ "\rPass %d/%d frame %4d/%-4d %7ldB \033[K", pass + 1,
++ arg_passes, frames_in, frames_out, nbytes);
+ }
+ else
+ frame_avail = 0;
+@@ -989,24 +1074,25 @@ int main(int argc, const char **argv_)
+ while ((pkt = vpx_codec_get_cx_data(&encoder, &iter)))
+ {
+ got_data = 1;
+- nbytes += pkt->data.raw.sz;
+
+ switch (pkt->kind)
+ {
+ case VPX_CODEC_CX_FRAME_PKT:
+ frames_out++;
+- printf(" %6luF",
+- (unsigned long)pkt->data.frame.sz);
++ fprintf(stderr, " %6luF",
++ (unsigned long)pkt->data.frame.sz);
+ write_ivf_frame_header(outfile, pkt);
+ fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile);
++ nbytes += pkt->data.raw.sz;
+ break;
+ case VPX_CODEC_STATS_PKT:
+ frames_out++;
+- printf(" %6luS",
++ fprintf(stderr, " %6luS",
+ (unsigned long)pkt->data.twopass_stats.sz);
+ stats_write(&stats,
+ pkt->data.twopass_stats.buf,
+ pkt->data.twopass_stats.sz);
++ nbytes += pkt->data.raw.sz;
+ break;
+ case VPX_CODEC_PSNR_PKT:
+
+@@ -1015,7 +1101,7 @@ int main(int argc, const char **argv_)
+ int i;
+
+ for (i = 0; i < 4; i++)
+- printf("%.3lf ", pkt->data.psnr.psnr[i]);
++ fprintf(stderr, "%.3lf ", pkt->data.psnr.psnr[i]);
+ }
+
+ break;
+@@ -1030,10 +1116,11 @@ int main(int argc, const char **argv_)
+ /* this bitrate calc is simplified and relies on the fact that this
+ * application uses 1/timebase for framerate.
+ */
+- printf("\rPass %d/%d frame %4d/%-4d %7ldB %7ldb/f %7"PRId64"b/s"
++ fprintf(stderr,
++ "\rPass %d/%d frame %4d/%-4d %7ldB %7ldb/f %7"PRId64"b/s"
+ " %7lu %s (%.2f fps)\033[K", pass + 1,
+ arg_passes, frames_in, frames_out, nbytes, nbytes * 8 / frames_in,
+- nbytes * 8 *(int64_t)cfg.g_timebase.den / cfg.g_timebase.num / frames_in,
++ nbytes * 8 *(int64_t)cfg.g_timebase.den/2/ cfg.g_timebase.num / frames_in,
+ cx_time > 9999999 ? cx_time / 1000 : cx_time,
+ cx_time > 9999999 ? "ms" : "us",
+ (float)frames_in * 1000000.0 / (float)cx_time);
+@@ -1047,7 +1134,7 @@ int main(int argc, const char **argv_)
+
+ fclose(outfile);
+ stats_close(&stats);
+- printf("\n");
++ fprintf(stderr, "\n");
+
+ if (one_pass_only)
+ break;
+diff --git a/libs.doxy_template b/libs.doxy_template
+index eb37dfc..ce8fde6 100644
+--- a/libs.doxy_template
++++ b/libs.doxy_template
+@@ -1,10 +1,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+-##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++##
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/libs.mk b/libs.mk
+index f741dba..115ceb5 100644
+--- a/libs.mk
++++ b/libs.mk
+@@ -1,17 +1,18 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+ ASM:=$(if $(filter yes,$(CONFIG_GCC)),.asm.s,.asm)
+
+-include $(SRC_PATH_BARE)/vpx_codec/vpx_codec.mk
+-CODEC_SRCS-yes += $(addprefix vpx_codec/,$(call enabled,API_SRCS))
++include $(SRC_PATH_BARE)/vpx/vpx_codec.mk
++CODEC_SRCS-yes += $(addprefix vpx/,$(call enabled,API_SRCS))
+
+ include $(SRC_PATH_BARE)/vpx_mem/vpx_mem.mk
+ CODEC_SRCS-yes += $(addprefix vpx_mem/,$(call enabled,MEM_SRCS))
+@@ -19,18 +20,16 @@ CODEC_SRCS-yes += $(addprefix vpx_mem/,$(call enabled,MEM_SRCS))
+ include $(SRC_PATH_BARE)/vpx_scale/vpx_scale.mk
+ CODEC_SRCS-yes += $(addprefix vpx_scale/,$(call enabled,SCALE_SRCS))
+
+-# Add vpx_codec/ to the include path to allow vp_n[cd]x.h to reference
+-# vpx_codec_impl_*.h without extra ifdeffery
+-CFLAGS += -I$(SRC_PATH_BARE)/vpx_codec
+
+ ifeq ($(CONFIG_VP8_ENCODER),yes)
+ VP8_PREFIX=vp8/
+ include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8cx.mk
+ CODEC_SRCS-yes += $(addprefix $(VP8_PREFIX),$(call enabled,VP8_CX_SRCS))
+ CODEC_EXPORTS-yes += $(addprefix $(VP8_PREFIX),$(VP8_CX_EXPORTS))
+- CODEC_SRCS-yes += $(VP8_PREFIX)vp8cx.mk
+- INSTALL_MAPS += include/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/%
+- CODEC_DOC_SRCS += vp8/vp8.h vp8/vp8cx.h
++ CODEC_SRCS-yes += $(VP8_PREFIX)vp8cx.mk vpx/vp8.h vpx/vp8cx.h vpx/vp8e.h
++ INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8e.h include/vpx/vp8cx.h
++ INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/%
++ CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
+ CODEC_DOC_SECTIONS += vp8 vp8_encoder
+ endif
+
+@@ -39,9 +38,10 @@ ifeq ($(CONFIG_VP8_DECODER),yes)
+ include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8dx.mk
+ CODEC_SRCS-yes += $(addprefix $(VP8_PREFIX),$(call enabled,VP8_DX_SRCS))
+ CODEC_EXPORTS-yes += $(addprefix $(VP8_PREFIX),$(VP8_DX_EXPORTS))
+- CODEC_SRCS-yes += $(VP8_PREFIX)vp8dx.mk
+- INSTALL_MAPS += include/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/%
+- CODEC_DOC_SRCS += vp8/vp8.h vp8/vp8dx.h
++ CODEC_SRCS-yes += $(VP8_PREFIX)vp8dx.mk vpx/vp8.h vpx/vp8dx.h
++ INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h
++ INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/%
++ CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8dx.h
+ CODEC_DOC_SECTIONS += vp8 vp8_decoder
+ endif
+
+@@ -64,13 +64,13 @@ endif
+
+ # The following pairs define a mapping of locations in the distribution
+ # tree to locations in the source/build trees.
+-INSTALL_MAPS += include/% $(SRC_PATH_BARE)/vpx_codec/%
+-INSTALL_MAPS += include/% $(SRC_PATH_BARE)/vpx_ports/%
+-INSTALL_MAPS += lib/% %
++INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/vpx/%
++INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/vpx_ports/%
++INSTALL_MAPS += $(LIBSUBDIR)/% %
+ INSTALL_MAPS += src/% $(SRC_PATH_BARE)/%
+ ifeq ($(CONFIG_MSVS),yes)
+-INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),lib/$(p)/% $(p)/Release/%)
+-INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),lib/$(p)/% $(p)/Debug/%)
++INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/% $(p)/Release/%)
++INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/% $(p)/Debug/%)
+ endif
+
+ # If this is a universal (fat) binary, then all the subarchitectures have
+@@ -81,7 +81,7 @@ endif
+ $(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_LIBVPX,BUILD_LIBVPX):=yes)
+
+ CODEC_SRCS-$(BUILD_LIBVPX) += build/make/version.sh
+-CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/vpx_integer.h
++CODEC_SRCS-$(BUILD_LIBVPX) += vpx/vpx_integer.h
+ CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/vpx_timer.h
+ CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/mem.h
+ CODEC_SRCS-$(BUILD_LIBVPX) += $(BUILD_PFX)vpx_config.c
+@@ -92,26 +92,28 @@ CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/x86.h
+ CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/x86_abi_support.asm
+ endif
+ CODEC_SRCS-$(ARCH_ARM) += $(BUILD_PFX)vpx_config.asm
+-CODEC_EXPORTS-$(BUILD_LIBVPX) += vpx_codec/exports
+-
+-INSTALL-LIBS-yes += include/vpx_codec.h
+-INSTALL-LIBS-yes += include/vpx_image.h
+-INSTALL-LIBS-yes += include/vpx_integer.h
+-INSTALL-LIBS-yes += include/vpx_codec_impl_top.h
+-INSTALL-LIBS-yes += include/vpx_codec_impl_bottom.h
+-INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx_decoder.h
+-INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx_decoder_compat.h
+-INSTALL-LIBS-$(CONFIG_ENCODERS) += include/vpx_encoder.h
++CODEC_EXPORTS-$(BUILD_LIBVPX) += vpx/exports_com
++CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc
++CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec
++
++INSTALL-LIBS-yes += include/vpx/vpx_codec.h
++INSTALL-LIBS-yes += include/vpx/vpx_image.h
++INSTALL-LIBS-yes += include/vpx/vpx_integer.h
++INSTALL-LIBS-yes += include/vpx/vpx_codec_impl_top.h
++INSTALL-LIBS-yes += include/vpx/vpx_codec_impl_bottom.h
++INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h
++INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder_compat.h
++INSTALL-LIBS-$(CONFIG_ENCODERS) += include/vpx/vpx_encoder.h
+ ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+ ifeq ($(CONFIG_MSVS),yes)
+-INSTALL-LIBS-yes += $(foreach p,$(VS_PLATFORMS),lib/$(p)/$(CODEC_LIB).lib)
+-INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(foreach p,$(VS_PLATFORMS),lib/$(p)/$(CODEC_LIB)d.lib)
+-INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),lib/$(p)/vpx.dll)
+-INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),lib/$(p)/vpx.exp)
++INSTALL-LIBS-yes += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/$(CODEC_LIB).lib)
++INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/$(CODEC_LIB)d.lib)
++INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/vpx.dll)
++INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/vpx.exp)
+ endif
+ else
+-INSTALL-LIBS-yes += lib/libvpx.a
+-INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += lib/libvpx_g.a
++INSTALL-LIBS-yes += $(LIBSUBDIR)/libvpx.a
++INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(LIBSUBDIR)/libvpx_g.a
+ endif
+
+ CODEC_SRCS=$(call enabled,CODEC_SRCS)
+@@ -130,7 +132,6 @@ ARM_ARCH=v6
+ endif
+ obj_int_extract.vcproj: $(SRC_PATH_BARE)/build/make/obj_int_extract.c
+ @cp $(SRC_PATH_BARE)/build/arm-wince-vs8/obj_int_extract.bat .
+- @cp $(SRC_PATH_BARE)/build/arm-wince-vs8/armasm$(ARM_ARCH).rules .
+ @echo " [CREATE] $@"
+ $(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh\
+ --exe\
+@@ -175,6 +176,31 @@ LIBVPX_OBJS=$(call objs,$(CODEC_SRCS))
+ OBJS-$(BUILD_LIBVPX) += $(LIBVPX_OBJS)
+ LIBS-$(BUILD_LIBVPX) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a
+ $(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS)
++
++BUILD_LIBVPX_SO := $(if $(BUILD_LIBVPX),$(CONFIG_SHARED))
++LIBVPX_SO := libvpx.so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
++LIBS-$(BUILD_LIBVPX_SO) += $(BUILD_PFX)$(LIBVPX_SO)
++$(BUILD_PFX)$(LIBVPX_SO): $(LIBVPX_OBJS) libvpx.ver
++$(BUILD_PFX)$(LIBVPX_SO): extralibs += -lm -pthread
++$(BUILD_PFX)$(LIBVPX_SO): SONAME = libvpx.so.$(VERSION_MAJOR)
++$(BUILD_PFX)$(LIBVPX_SO): SO_VERSION_SCRIPT = libvpx.ver
++LIBVPX_SO_SYMLINKS := $(addprefix $(LIBSUBDIR)/, \
++ libvpx.so libvpx.so.$(VERSION_MAJOR) \
++ libvpx.so.$(VERSION_MAJOR).$(VERSION_MINOR))
++
++libvpx.ver: $(call enabled,CODEC_EXPORTS)
++ @echo " [CREATE] $@"
++ $(qexec)echo "{ global:" > $@
++ $(qexec)for f in $?; do awk '{print $$2";"}' < $$f >>$@; done
++ $(qexec)echo "local: *; };" >> $@
++CLEAN-OBJS += libvpx.ver
++
++$(addprefix $(DIST_DIR)/,$(LIBVPX_SO_SYMLINKS)):
++ @echo " [LN] $@"
++ $(qexec)ln -sf $(LIBVPX_SO) $@
++
++INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBVPX_SO_SYMLINKS)
++INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBSUBDIR)/$(LIBVPX_SO)
+ endif
+
+ LIBS-$(LIPO_LIBVPX) += libvpx.a
+@@ -209,10 +235,10 @@ $(filter %.asm.o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
+ $(shell $(SRC_PATH_BARE)/build/make/version.sh "$(SRC_PATH_BARE)" $(BUILD_PFX)vpx_version.h)
+ CLEAN-OBJS += $(BUILD_PFX)vpx_version.h
+
+-CODEC_DOC_SRCS += vpx_codec/vpx_codec.h \
+- vpx_codec/vpx_decoder.h \
+- vpx_codec/vpx_encoder.h \
+- vpx_codec/vpx_image.h
++CODEC_DOC_SRCS += vpx/vpx_codec.h \
++ vpx/vpx_decoder.h \
++ vpx/vpx_encoder.h \
++ vpx/vpx_image.h
+
+ CLEAN-OBJS += libs.doxy
+ DOCS-yes += libs.doxy
+diff --git a/md5_utils.c b/md5_utils.c
+index 16c6f7e..455d9cd 100644
+--- a/md5_utils.c
++++ b/md5_utils.c
+@@ -1,298 +1,253 @@
+ /*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ * 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.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * 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.
++ *
++ * Changed so as no longer to depend on Colin Plumb's `usual.h' header
++ * definitions
++ * - Ian Jackson <ian@chiark.greenend.org.uk>.
++ * Still in the public domain.
+ */
+
++#include <sys/types.h> /* for stupid systems */
+
+-/*
+-Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+-rights reserved.
+-
+-License to copy and use this software is granted provided that it
+-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+-Algorithm" in all material mentioning or referencing this software
+-or this function.
+-
+-License is also granted to make and use derivative works provided
+-that such works are identified as "derived from the RSA Data
+-Security, Inc. MD5 Message-Digest Algorithm" in all material
+-mentioning or referencing the derived work.
+-
+-RSA Data Security, Inc. makes no representations concerning either
+-the merchantability of this software or the suitability of this
+-software for any particular purpose. It is provided "as is"
+-without express or implied warranty of any kind.
+-
+-These notices must be retained in any copies of any part of this
+-documentation and/or software.
+-*/
++#include <string.h> /* for memcpy() */
+
+ #include "md5_utils.h"
+-#include <string.h>
+
+-/* Constants for md5_transform routine.
+- */
+-#define S11 7
+-#define S12 12
+-#define S13 17
+-#define S14 22
+-#define S21 5
+-#define S22 9
+-#define S23 14
+-#define S24 20
+-#define S31 4
+-#define S32 11
+-#define S33 16
+-#define S34 23
+-#define S41 6
+-#define S42 10
+-#define S43 15
+-#define S44 21
+-
+-static void md5_transform(uint32_t state[4], const uint8_t block[64]);
+-static void Encode(uint8_t *output, const uint32_t *input, unsigned int len);
+-static void Decode(uint32_t *output, const uint8_t *input, unsigned int len);
+-#define md5_memset memset
+-#define md5_memcpy memcpy
+-
+-static unsigned char PADDING[64] =
++void
++byteSwap(UWORD32 *buf, unsigned words)
+ {
+- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+-};
++ md5byte *p;
+
+-/* F, G, H and I are basic MD5 functions.
+- */
+-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+-#define H(x, y, z) ((x) ^ (y) ^ (z))
+-#define I(x, y, z) ((y) ^ ((x) | (~z)))
++ /* Only swap bytes for big endian machines */
++ int i = 1;
+
+-/* ROTATE_LEFT rotates x left n bits.
+- */
+-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
++ if (*(char *)&i == 1)
++ return;
+
+-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+-Rotation is separate from addition to prevent recomputation.
+- */
+-#define FF(a, b, c, d, x, s, ac) { \
+- (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+- (a) = ROTATE_LEFT ((a), (s)); \
+- (a) += (b); \
+- }
+-#define GG(a, b, c, d, x, s, ac) { \
+- (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+- (a) = ROTATE_LEFT ((a), (s)); \
+- (a) += (b); \
+- }
+-#define HH(a, b, c, d, x, s, ac) { \
+- (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+- (a) = ROTATE_LEFT ((a), (s)); \
+- (a) += (b); \
+- }
+-#define II(a, b, c, d, x, s, ac) { \
+- (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+- (a) = ROTATE_LEFT ((a), (s)); \
+- (a) += (b); \
++ p = (md5byte *)buf;
++
++ do
++ {
++ *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 |
++ ((unsigned)p[1] << 8 | p[0]);
++ p += 4;
+ }
++ while (--words);
++}
+
+-/* MD5 initialization. Begins an MD5 operation, writing a new context.
++/*
++ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
++ * initialization constants.
+ */
+-void md5_init(md5_ctx_t *context)
++void
++MD5Init(struct MD5Context *ctx)
+ {
+- context->count[0] = context->count[1] = 0;
+- /* Load magic initialization constants.
+- */
+- context->state[0] = 0x67452301;
+- context->state[1] = 0xefcdab89;
+- context->state[2] = 0x98badcfe;
+- context->state[3] = 0x10325476;
++ ctx->buf[0] = 0x67452301;
++ ctx->buf[1] = 0xefcdab89;
++ ctx->buf[2] = 0x98badcfe;
++ ctx->buf[3] = 0x10325476;
++
++ ctx->bytes[0] = 0;
++ ctx->bytes[1] = 0;
+ }
+
+-/* MD5 block update operation. Continues an MD5 message-digest
+- operation, processing another message block, and updating the
+- context.
++/*
++ * Update context to reflect the concatenation of another buffer full
++ * of bytes.
+ */
+-void md5_update(md5_ctx_t *context, const uint8_t *input, unsigned int input_len)
++void
++MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)
+ {
+- unsigned int i, index, part_len;
++ UWORD32 t;
+
+- /* Compute number of bytes mod 64 */
+- index = (unsigned int)((context->count[0] >> 3) & 0x3F);
++ /* Update byte count */
+
+- /* Update number of bits */
+- if ((context->count[0] += ((uint32_t)input_len << 3))
+- < ((uint32_t)input_len << 3))
+- context->count[1]++;
++ t = ctx->bytes[0];
+
+- context->count[1] += ((uint32_t)input_len >> 29);
++ if ((ctx->bytes[0] = t + len) < t)
++ ctx->bytes[1]++; /* Carry from low to high */
+
+- part_len = 64 - index;
++ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
+
+- /* Transform as many times as possible. */
+- if (input_len >= part_len)
++ if (t > len)
+ {
+- memcpy(&context->buffer[index], input, part_len);
+- md5_transform(context->state, context->buffer);
++ memcpy((md5byte *)ctx->in + 64 - t, buf, len);
++ return;
++ }
+
+- for (i = part_len; i + 63 < input_len; i += 64)
+- md5_transform(context->state, &input[i]);
++ /* First chunk is an odd size */
++ memcpy((md5byte *)ctx->in + 64 - t, buf, t);
++ byteSwap(ctx->in, 16);
++ MD5Transform(ctx->buf, ctx->in);
++ buf += t;
++ len -= t;
+
+- index = 0;
++ /* Process data in 64-byte chunks */
++ while (len >= 64)
++ {
++ memcpy(ctx->in, buf, 64);
++ byteSwap(ctx->in, 16);
++ MD5Transform(ctx->buf, ctx->in);
++ buf += 64;
++ len -= 64;
+ }
+- else
+- i = 0;
+
+- /* Buffer remaining input */
+- memcpy(&context->buffer[index], &input[i], input_len - i);
++ /* Handle any remaining bytes of data. */
++ memcpy(ctx->in, buf, len);
+ }
+
+-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+- the message digest and zeroizing the context.
++/*
++ * Final wrapup - pad to 64-byte boundary with the bit pattern
++ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+-void md5_finalize(md5_ctx_t *context, uint8_t digest[16])
++void
++MD5Final(md5byte digest[16], struct MD5Context *ctx)
+ {
+- unsigned char bits[8];
+- unsigned int index, pad_len;
+-
+- /* Save number of bits */
+- Encode(bits, context->count, 8);
+-
+- /* Pad out to 56 mod 64.
+- */
+- index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+- pad_len = (index < 56) ? (56 - index) : (120 - index);
+- md5_update(context, PADDING, pad_len);
+-
+- /* Append length (before padding) */
+- md5_update(context, bits, 8);
+- /* Store state in digest */
+- Encode(digest, context->state, 16);
+-
+- /* Zeroize sensitive information.
+- */
+- memset(context, 0, sizeof(*context));
+-}
++ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
++ md5byte *p = (md5byte *)ctx->in + count;
+
+-/* MD5 basic transformation. Transforms state based on block.
+- */
+-static void md5_transform(uint32_t state[4], const uint8_t block[64])
+-{
+- uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+-
+- Decode(x, block, 64);
+-
+- /* Round 1 */
+- FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+- FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+- FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+- FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+- FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+- FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+- FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+- FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+- FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+- FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+- FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+- FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+- FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+- FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+- FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+- FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+-
+- /* Round 2 */
+- GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+- GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+- GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+- GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+- GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+- GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+- GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+- GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+- GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+- GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+- GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+- GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+- GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+- GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+- GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+- GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+-
+- /* Round 3 */
+- HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+- HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+- HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+- HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+- HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+- HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+- HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+- HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+- HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+- HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+- HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+- HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+- HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+- HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+- HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+- HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+-
+- /* Round 4 */
+- II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+- II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+- II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+- II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+- II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+- II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+- II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+- II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+- II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+- II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+- II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+- II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+- II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+- II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+- II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+- II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+-
+- state[0] += a;
+- state[1] += b;
+- state[2] += c;
+- state[3] += d;
+-
+- /* Zeroize sensitive information.
+- */
+- memset(x, 0, sizeof(x));
+-}
++ /* Set the first char of padding to 0x80. There is always room. */
++ *p++ = 0x80;
+
+-/* Encodes input (uint32_t) into output (unsigned char). Assumes len is
+- a multiple of 4.
+- */
+-static void Encode(uint8_t *output, const uint32_t *input, unsigned int len)
+-{
+- unsigned int i, j;
++ /* Bytes of padding needed to make 56 bytes (-8..55) */
++ count = 56 - 1 - count;
+
+- for (i = 0, j = 0; j < len; i++, j += 4)
++ if (count < 0) /* Padding forces an extra block */
+ {
+- output[j] = (unsigned char)(input[i] & 0xff);
+- output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+- output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+- output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
++ memset(p, 0, count + 8);
++ byteSwap(ctx->in, 16);
++ MD5Transform(ctx->buf, ctx->in);
++ p = (md5byte *)ctx->in;
++ count = 56;
+ }
++
++ memset(p, 0, count);
++ byteSwap(ctx->in, 14);
++
++ /* Append length in bits and transform */
++ ctx->in[14] = ctx->bytes[0] << 3;
++ ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
++ MD5Transform(ctx->buf, ctx->in);
++
++ byteSwap(ctx->buf, 4);
++ memcpy(digest, ctx->buf, 16);
++ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+ }
+
+-/* Decodes input (unsigned char) into output (uint32_t). Assumes len is
+- a multiple of 4.
++#ifndef ASM_MD5
++
++/* 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,in,s) \
++ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + 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 Decode(uint32_t *output, const uint8_t *input, unsigned int len)
++void
++MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
+ {
+- unsigned int i, j;
+-
+- for (i = 0, j = 0; j < len; i++, j += 4)
+- output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
+- (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
++ register UWORD32 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;
+ }
++
++#endif
+diff --git a/md5_utils.h b/md5_utils.h
+index 8dda8d1..5ca1b5f 100644
+--- a/md5_utils.h
++++ b/md5_utils.h
+@@ -1,51 +1,42 @@
+ /*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ * This is the header file for 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.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * 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.
++ *
++ * Changed so as no longer to depend on Colin Plumb's `usual.h'
++ * header definitions
++ * - Ian Jackson <ian@chiark.greenend.org.uk>.
++ * Still in the public domain.
+ */
+
+-/*
+-Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+-rights reserved.
+-
+-License to copy and use this software is granted provided that it
+-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+-Algorithm" in all material mentioning or referencing this software
+-or this function.
++#ifndef MD5_H
++#define MD5_H
+
+-License is also granted to make and use derivative works provided
+-that such works are identified as "derived from the RSA Data
+-Security, Inc. MD5 Message-Digest Algorithm" in all material
+-mentioning or referencing the derived work.
++#define md5byte unsigned char
++#define UWORD32 unsigned int
+
+-RSA Data Security, Inc. makes no representations concerning either
+-the merchantability of this software or the suitability of this
+-software for any particular purpose. It is provided "as is"
+-without express or implied warranty of any kind.
+-
+-These notices must be retained in any copies of any part of this
+-documentation and/or software.
+-*/
+-#ifndef HAVE_VPX_PORTS
+-#define HAVE_VPX_PORTS 0
+-#endif
+-#if HAVE_VPX_PORTS
+-#include "vpx_ports/vpx_integer.h"
+-#else
+-#include "vpx_integer.h"
+-#endif
+-
+-/* MD5 context. */
+-typedef struct
++typedef struct MD5Context MD5Context;
++struct MD5Context
+ {
+- uint32_t state[4]; /* state (ABCD) */
+- uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
+- uint8_t buffer[64]; /* input buffer */
+-} md5_ctx_t;
++ UWORD32 buf[4];
++ UWORD32 bytes[2];
++ UWORD32 in[16];
++};
++
++void MD5Init(struct MD5Context *context);
++void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
++void MD5Final(unsigned char digest[16], struct MD5Context *context);
++void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
+
+-void md5_init(md5_ctx_t *ctx);
+-void md5_update(md5_ctx_t *ctx, const uint8_t *buf, unsigned int len);
+-void md5_finalize(md5_ctx_t *ctx, uint8_t md5[16]);
++#endif /* !MD5_H */
+diff --git a/release.sh b/release.sh
+index 3b77dad..880ad0f 100755
+--- a/release.sh
++++ b/release.sh
+@@ -1,11 +1,12 @@
+-#!/bin/bash
++#!/bin/sh
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+@@ -20,7 +21,7 @@ for opt; do
+ esac
+ done
+
+-TAB=$'\t'
++TAB="$(printf '\t')"
+ cat > release.mk << EOF
+ %\$(BUILD_SFX).tar.bz2: %/.done
+ ${TAB}@echo "\$(subst .tar.bz2,,\$@): tarball"
+@@ -185,7 +186,7 @@ for cfg in $CONFIGS; do
+ esac
+ opts="$opts --enable-postproc"
+
+- [ "x${clean}" == "xyes" ] \
++ [ "x${clean}" = "xyes" ] \
+ && rm -rf ${full_cfg}${BUILD_SFX}${TAR_SFX} \
+ && rm -rf logs/${full_cfg}${BUILD_SFX}.log.bz2
+
+diff --git a/solution.mk b/solution.mk
+index 783c6f8..21bf065 100644
+--- a/solution.mk
++++ b/solution.mk
+@@ -1,10 +1,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/tools/gen_authors.sh b/tools/gen_authors.sh
+new file mode 100755
+index 0000000..e1246f0
+--- /dev/null
++++ b/tools/gen_authors.sh
+@@ -0,0 +1,13 @@
++#!/bin/bash
++
++# Add organization names manually.
++
++cat <<EOF
++# This file is automatically generated from the git commit history
++# by tools/gen_authors.sh.
++
++$(git log --pretty=format:"%aN <%aE>" | sort | uniq)
++Google Inc.
++The Mozilla Foundation
++The Xiph.Org Foundation
++EOF
+diff --git a/vp8/common/alloccommon.c b/vp8/common/alloccommon.c
+index ac110f7..9f6397e 100644
+--- a/vp8/common/alloccommon.c
++++ b/vp8/common/alloccommon.c
+@@ -1,13 +1,15 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
++#include "vpx_ports/config.h"
+ #include "blockd.h"
+ #include "vpx_mem/vpx_mem.h"
+ #include "onyxc_int.h"
+@@ -16,9 +18,6 @@
+ #include "systemdependent.h"
+ #include "vpxerrors.h"
+
+-#ifdef HAVE_CONFIG_H
+-#include "vpx_config.h"
+-#endif
+
+ extern void vp8_init_scan_order_mask();
+
+diff --git a/vp8/common/alloccommon.h b/vp8/common/alloccommon.h
+index 73c7383..b877412 100644
+--- a/vp8/common/alloccommon.h
++++ b/vp8/common/alloccommon.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/armv6/bilinearfilter_v6.asm b/vp8/common/arm/armv6/bilinearfilter_v6.asm
+index 4428cf8..ac0d333 100644
+--- a/vp8/common/arm/armv6/bilinearfilter_v6.asm
++++ b/vp8/common/arm/armv6/bilinearfilter_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/copymem16x16_v6.asm b/vp8/common/arm/armv6/copymem16x16_v6.asm
+index 00e9739..344c453 100644
+--- a/vp8/common/arm/armv6/copymem16x16_v6.asm
++++ b/vp8/common/arm/armv6/copymem16x16_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/copymem8x4_v6.asm b/vp8/common/arm/armv6/copymem8x4_v6.asm
+index 94473ca..3556b3a 100644
+--- a/vp8/common/arm/armv6/copymem8x4_v6.asm
++++ b/vp8/common/arm/armv6/copymem8x4_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/copymem8x8_v6.asm b/vp8/common/arm/armv6/copymem8x8_v6.asm
+index 7cfa533..1da0ff5 100644
+--- a/vp8/common/arm/armv6/copymem8x8_v6.asm
++++ b/vp8/common/arm/armv6/copymem8x8_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/filter_v6.asm b/vp8/common/arm/armv6/filter_v6.asm
+index a7863fc..cdc74ba 100644
+--- a/vp8/common/arm/armv6/filter_v6.asm
++++ b/vp8/common/arm/armv6/filter_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/idct_v6.asm b/vp8/common/arm/armv6/idct_v6.asm
+index 25c5165..9e932fa 100644
+--- a/vp8/common/arm/armv6/idct_v6.asm
++++ b/vp8/common/arm/armv6/idct_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/iwalsh_v6.asm b/vp8/common/arm/armv6/iwalsh_v6.asm
+index 8747568..4606783 100644
+--- a/vp8/common/arm/armv6/iwalsh_v6.asm
++++ b/vp8/common/arm/armv6/iwalsh_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+ EXPORT |vp8_short_inv_walsh4x4_armv6|
+diff --git a/vp8/common/arm/armv6/loopfilter_v6.asm b/vp8/common/arm/armv6/loopfilter_v6.asm
+index c2b02dc..eeeacd3 100644
+--- a/vp8/common/arm/armv6/loopfilter_v6.asm
++++ b/vp8/common/arm/armv6/loopfilter_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/recon_v6.asm b/vp8/common/arm/armv6/recon_v6.asm
+index 085ff80..6f3ccbe 100644
+--- a/vp8/common/arm/armv6/recon_v6.asm
++++ b/vp8/common/arm/armv6/recon_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/simpleloopfilter_v6.asm b/vp8/common/arm/armv6/simpleloopfilter_v6.asm
+index 15c6c7d..b820ced 100644
+--- a/vp8/common/arm/armv6/simpleloopfilter_v6.asm
++++ b/vp8/common/arm/armv6/simpleloopfilter_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/armv6/sixtappredict8x4_v6.asm b/vp8/common/arm/armv6/sixtappredict8x4_v6.asm
+index 551d863..6415463 100644
+--- a/vp8/common/arm/armv6/sixtappredict8x4_v6.asm
++++ b/vp8/common/arm/armv6/sixtappredict8x4_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/bilinearfilter_arm.c b/vp8/common/arm/bilinearfilter_arm.c
+index bf972a3..b93539c 100644
+--- a/vp8/common/arm/bilinearfilter_arm.c
++++ b/vp8/common/arm/bilinearfilter_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/filter_arm.c b/vp8/common/arm/filter_arm.c
+index 2a4640c..233be24 100644
+--- a/vp8/common/arm/filter_arm.c
++++ b/vp8/common/arm/filter_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/idct_arm.h b/vp8/common/arm/idct_arm.h
+index f9ed21e..cfd9d76 100644
+--- a/vp8/common/arm/idct_arm.h
++++ b/vp8/common/arm/idct_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/loopfilter_arm.c b/vp8/common/arm/loopfilter_arm.c
+index fa7c626..d98c908 100644
+--- a/vp8/common/arm/loopfilter_arm.c
++++ b/vp8/common/arm/loopfilter_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/loopfilter_arm.h b/vp8/common/arm/loopfilter_arm.h
+index 4bb4945..b59e2b5 100644
+--- a/vp8/common/arm/loopfilter_arm.h
++++ b/vp8/common/arm/loopfilter_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/neon/bilinearpredict16x16_neon.asm b/vp8/common/arm/neon/bilinearpredict16x16_neon.asm
+index a2fea2b..076a3d3 100644
+--- a/vp8/common/arm/neon/bilinearpredict16x16_neon.asm
++++ b/vp8/common/arm/neon/bilinearpredict16x16_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/bilinearpredict4x4_neon.asm b/vp8/common/arm/neon/bilinearpredict4x4_neon.asm
+index 74d2db5..f199ba3 100644
+--- a/vp8/common/arm/neon/bilinearpredict4x4_neon.asm
++++ b/vp8/common/arm/neon/bilinearpredict4x4_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/bilinearpredict8x4_neon.asm b/vp8/common/arm/neon/bilinearpredict8x4_neon.asm
+index 46ebb0e..9a3a039 100644
+--- a/vp8/common/arm/neon/bilinearpredict8x4_neon.asm
++++ b/vp8/common/arm/neon/bilinearpredict8x4_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/bilinearpredict8x8_neon.asm b/vp8/common/arm/neon/bilinearpredict8x8_neon.asm
+index 80728d4..10a6366 100644
+--- a/vp8/common/arm/neon/bilinearpredict8x8_neon.asm
++++ b/vp8/common/arm/neon/bilinearpredict8x8_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm b/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm
+index f42ac63..7cd9d75 100644
+--- a/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm
++++ b/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/copymem16x16_neon.asm b/vp8/common/arm/neon/copymem16x16_neon.asm
+index 89d5e10..b25bfdc 100644
+--- a/vp8/common/arm/neon/copymem16x16_neon.asm
++++ b/vp8/common/arm/neon/copymem16x16_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/copymem8x4_neon.asm b/vp8/common/arm/neon/copymem8x4_neon.asm
+index 302f734..0c62ee2 100644
+--- a/vp8/common/arm/neon/copymem8x4_neon.asm
++++ b/vp8/common/arm/neon/copymem8x4_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/copymem8x8_neon.asm b/vp8/common/arm/neon/copymem8x8_neon.asm
+index 50d39ef..84e0afd 100644
+--- a/vp8/common/arm/neon/copymem8x8_neon.asm
++++ b/vp8/common/arm/neon/copymem8x8_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/iwalsh_neon.asm b/vp8/common/arm/neon/iwalsh_neon.asm
+index 4fc744c..b8199ce 100644
+--- a/vp8/common/arm/neon/iwalsh_neon.asm
++++ b/vp8/common/arm/neon/iwalsh_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+ EXPORT |vp8_short_inv_walsh4x4_neon|
+ EXPORT |vp8_short_inv_walsh4x4_1_neon|
+diff --git a/vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm b/vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm
+index e3e8e8a..5d25e3d 100644
+--- a/vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm
++++ b/vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm b/vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm
+index f11055d..ebe52fc 100644
+--- a/vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm
++++ b/vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm b/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm
+index 6d74fab..dbbdd74 100644
+--- a/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm
++++ b/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm b/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm
+index 2bb6222..480e318 100644
+--- a/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm
++++ b/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm b/vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm
+index d79cc68..a402282 100644
+--- a/vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm
++++ b/vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm b/vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm
+index 3a230a9..18eba9f 100644
+--- a/vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm
++++ b/vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm b/vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm
+index 86eddaa..21b85da 100644
+--- a/vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm
++++ b/vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm b/vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm
+index 2ab0fc2..64d98c6 100644
+--- a/vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm
++++ b/vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm b/vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm
+index ad5afba..0e72e80 100644
+--- a/vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm
++++ b/vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm b/vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm
+index 60e5175..91396a1 100644
+--- a/vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm
++++ b/vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/recon16x16mb_neon.asm b/vp8/common/arm/neon/recon16x16mb_neon.asm
+index b9ba1cb..7c06c03 100644
+--- a/vp8/common/arm/neon/recon16x16mb_neon.asm
++++ b/vp8/common/arm/neon/recon16x16mb_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/recon2b_neon.asm b/vp8/common/arm/neon/recon2b_neon.asm
+index 25aaf8c..3d87e2d 100644
+--- a/vp8/common/arm/neon/recon2b_neon.asm
++++ b/vp8/common/arm/neon/recon2b_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/recon4b_neon.asm b/vp8/common/arm/neon/recon4b_neon.asm
+index a4f5b80..63cd987 100644
+--- a/vp8/common/arm/neon/recon4b_neon.asm
++++ b/vp8/common/arm/neon/recon4b_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/reconb_neon.asm b/vp8/common/arm/neon/reconb_neon.asm
+index 16d85a0..0ecdc14 100644
+--- a/vp8/common/arm/neon/reconb_neon.asm
++++ b/vp8/common/arm/neon/reconb_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/save_neon_reg.asm b/vp8/common/arm/neon/save_neon_reg.asm
+index 4873e44..f5db2a8 100644
+--- a/vp8/common/arm/neon/save_neon_reg.asm
++++ b/vp8/common/arm/neon/save_neon_reg.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/shortidct4x4llm_1_neon.asm b/vp8/common/arm/neon/shortidct4x4llm_1_neon.asm
+index 7d06ff9..24e5fed 100644
+--- a/vp8/common/arm/neon/shortidct4x4llm_1_neon.asm
++++ b/vp8/common/arm/neon/shortidct4x4llm_1_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/shortidct4x4llm_neon.asm b/vp8/common/arm/neon/shortidct4x4llm_neon.asm
+index ffecfbf..c566c67 100644
+--- a/vp8/common/arm/neon/shortidct4x4llm_neon.asm
++++ b/vp8/common/arm/neon/shortidct4x4llm_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/sixtappredict16x16_neon.asm b/vp8/common/arm/neon/sixtappredict16x16_neon.asm
+index 9f5f0d2..6f3716d 100644
+--- a/vp8/common/arm/neon/sixtappredict16x16_neon.asm
++++ b/vp8/common/arm/neon/sixtappredict16x16_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/sixtappredict4x4_neon.asm b/vp8/common/arm/neon/sixtappredict4x4_neon.asm
+index c23a9db..6fe9ead 100644
+--- a/vp8/common/arm/neon/sixtappredict4x4_neon.asm
++++ b/vp8/common/arm/neon/sixtappredict4x4_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/sixtappredict8x4_neon.asm b/vp8/common/arm/neon/sixtappredict8x4_neon.asm
+index 18e19f9..a6ff4f7 100644
+--- a/vp8/common/arm/neon/sixtappredict8x4_neon.asm
++++ b/vp8/common/arm/neon/sixtappredict8x4_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/neon/sixtappredict8x8_neon.asm b/vp8/common/arm/neon/sixtappredict8x8_neon.asm
+index d27485e..bb35ae4 100644
+--- a/vp8/common/arm/neon/sixtappredict8x8_neon.asm
++++ b/vp8/common/arm/neon/sixtappredict8x8_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/arm/recon_arm.c b/vp8/common/arm/recon_arm.c
+index 130059e..2cc9ee7 100644
+--- a/vp8/common/arm/recon_arm.c
++++ b/vp8/common/arm/recon_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/recon_arm.h b/vp8/common/arm/recon_arm.h
+index fd9f85e..392297b 100644
+--- a/vp8/common/arm/recon_arm.h
++++ b/vp8/common/arm/recon_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/reconintra4x4_arm.c b/vp8/common/arm/reconintra4x4_arm.c
+index 334d352..65fb1f0 100644
+--- a/vp8/common/arm/reconintra4x4_arm.c
++++ b/vp8/common/arm/reconintra4x4_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/reconintra_arm.c b/vp8/common/arm/reconintra_arm.c
+index d7ee1dd..29f4a2c 100644
+--- a/vp8/common/arm/reconintra_arm.c
++++ b/vp8/common/arm/reconintra_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/subpixel_arm.h b/vp8/common/arm/subpixel_arm.h
+index 56aec55..0eb2c58 100644
+--- a/vp8/common/arm/subpixel_arm.h
++++ b/vp8/common/arm/subpixel_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/systemdependent.c b/vp8/common/arm/systemdependent.c
+index ecc6929..27d3dee 100644
+--- a/vp8/common/arm/systemdependent.c
++++ b/vp8/common/arm/systemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/arm/vpx_asm_offsets.c b/vp8/common/arm/vpx_asm_offsets.c
+index 68634bf..ff4d752 100644
+--- a/vp8/common/arm/vpx_asm_offsets.c
++++ b/vp8/common/arm/vpx_asm_offsets.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/bigend.h b/vp8/common/bigend.h
+index 6a91ba1..cd6b988 100644
+--- a/vp8/common/bigend.h
++++ b/vp8/common/bigend.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/blockd.c b/vp8/common/blockd.c
+index 53f5e72..e0ed561 100644
+--- a/vp8/common/blockd.c
++++ b/vp8/common/blockd.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h
+index 84ed53a..2b25f62 100644
+--- a/vp8/common/blockd.h
++++ b/vp8/common/blockd.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -173,9 +174,8 @@ typedef struct
+ int dc_diff;
+ unsigned char segment_id; // Which set of segmentation parameters should be used for this MB
+ int force_no_skip;
+-
++ int need_to_clamp_mvs;
+ B_MODE_INFO partition_bmi[16];
+-
+ } MB_MODE_INFO;
+
+
+diff --git a/vp8/common/boolcoder.h b/vp8/common/boolcoder.h
+index 0659d48..66f67c2 100644
+--- a/vp8/common/boolcoder.h
++++ b/vp8/common/boolcoder.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/codec_common_interface.h b/vp8/common/codec_common_interface.h
+index 7881b0a..d836564 100644
+--- a/vp8/common/codec_common_interface.h
++++ b/vp8/common/codec_common_interface.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+ #ifndef CODEC_COMMON_INTERFACE_H
+diff --git a/vp8/common/coefupdateprobs.h b/vp8/common/coefupdateprobs.h
+index 99affd6..6131d12 100644
+--- a/vp8/common/coefupdateprobs.h
++++ b/vp8/common/coefupdateprobs.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/common.h b/vp8/common/common.h
+index 29f6d37..bfa8a9c 100644
+--- a/vp8/common/common.h
++++ b/vp8/common/common.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/common_types.h b/vp8/common/common_types.h
+index deb5ed8..a307ed6 100644
+--- a/vp8/common/common_types.h
++++ b/vp8/common/common_types.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/context.c b/vp8/common/context.c
+index 17ee8c3..f0cb838 100644
+--- a/vp8/common/context.c
++++ b/vp8/common/context.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/debugmodes.c b/vp8/common/debugmodes.c
+index e2d2d2c..e669814 100644
+--- a/vp8/common/debugmodes.c
++++ b/vp8/common/debugmodes.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/defaultcoefcounts.h b/vp8/common/defaultcoefcounts.h
+index ccdf326..f9247d2 100644
+--- a/vp8/common/defaultcoefcounts.h
++++ b/vp8/common/defaultcoefcounts.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/dma_desc.h b/vp8/common/dma_desc.h
+index 5e6fa0c..765405d 100644
+--- a/vp8/common/dma_desc.h
++++ b/vp8/common/dma_desc.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/duck_io.h b/vp8/common/duck_io.h
+index f63a5cd..02f6895 100644
+--- a/vp8/common/duck_io.h
++++ b/vp8/common/duck_io.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/entropy.c b/vp8/common/entropy.c
+index e524c2a..8d01bf8 100644
+--- a/vp8/common/entropy.c
++++ b/vp8/common/entropy.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/entropy.h b/vp8/common/entropy.h
+index 1415832..29be82c 100644
+--- a/vp8/common/entropy.h
++++ b/vp8/common/entropy.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/entropymode.c b/vp8/common/entropymode.c
+index 7dc1acd..72cbd64 100644
+--- a/vp8/common/entropymode.c
++++ b/vp8/common/entropymode.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/entropymode.h b/vp8/common/entropymode.h
+index ff630a4..bd44b83 100644
+--- a/vp8/common/entropymode.h
++++ b/vp8/common/entropymode.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/entropymv.c b/vp8/common/entropymv.c
+index 2b00c17..176fecd 100644
+--- a/vp8/common/entropymv.c
++++ b/vp8/common/entropymv.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/entropymv.h b/vp8/common/entropymv.h
+index d940c59..395984c 100644
+--- a/vp8/common/entropymv.h
++++ b/vp8/common/entropymv.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/extend.c b/vp8/common/extend.c
+index 7407952..43d7aed 100644
+--- a/vp8/common/extend.c
++++ b/vp8/common/extend.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/extend.h b/vp8/common/extend.h
+index 6809ae7..bb8a016 100644
+--- a/vp8/common/extend.h
++++ b/vp8/common/extend.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/filter_c.c b/vp8/common/filter_c.c
+index 38991cb..f24f8a2 100644
+--- a/vp8/common/filter_c.c
++++ b/vp8/common/filter_c.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/findnearmv.c b/vp8/common/findnearmv.c
+index fcb1f20..550681e 100644
+--- a/vp8/common/findnearmv.c
++++ b/vp8/common/findnearmv.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/findnearmv.h b/vp8/common/findnearmv.h
+index 2c02033..3e0718a 100644
+--- a/vp8/common/findnearmv.h
++++ b/vp8/common/findnearmv.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/fourcc.hpp b/vp8/common/fourcc.hpp
+index 5f1faed..9823b56 100644
+--- a/vp8/common/fourcc.hpp
++++ b/vp8/common/fourcc.hpp
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/g_common.h b/vp8/common/g_common.h
+index e68c53e..3f43401 100644
+--- a/vp8/common/g_common.h
++++ b/vp8/common/g_common.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/generic/systemdependent.c b/vp8/common/generic/systemdependent.c
+index 0011ae0..6e64885 100644
+--- a/vp8/common/generic/systemdependent.c
++++ b/vp8/common/generic/systemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/header.h b/vp8/common/header.h
+index 8b2b009..b8b9059 100644
+--- a/vp8/common/header.h
++++ b/vp8/common/header.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/idct.h b/vp8/common/idct.h
+index 47b5f05..2185bd3 100644
+--- a/vp8/common/idct.h
++++ b/vp8/common/idct.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/idctllm.c b/vp8/common/idctllm.c
+index 57cf858..4261d24 100644
+--- a/vp8/common/idctllm.c
++++ b/vp8/common/idctllm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/invtrans.c b/vp8/common/invtrans.c
+index 1ff596e..00502c6 100644
+--- a/vp8/common/invtrans.c
++++ b/vp8/common/invtrans.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/invtrans.h b/vp8/common/invtrans.h
+index 93a40f9..be30ca0 100644
+--- a/vp8/common/invtrans.h
++++ b/vp8/common/invtrans.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/littlend.h b/vp8/common/littlend.h
+index 08c525c..0961163 100644
+--- a/vp8/common/littlend.h
++++ b/vp8/common/littlend.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/loopfilter.c b/vp8/common/loopfilter.c
+index 79e6177..4937195 100644
+--- a/vp8/common/loopfilter.c
++++ b/vp8/common/loopfilter.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/loopfilter.h b/vp8/common/loopfilter.h
+index c6ce508..a9a976e 100644
+--- a/vp8/common/loopfilter.h
++++ b/vp8/common/loopfilter.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/loopfilter_filters.c b/vp8/common/loopfilter_filters.c
+index 7d16e48..eaf7327 100644
+--- a/vp8/common/loopfilter_filters.c
++++ b/vp8/common/loopfilter_filters.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/mac_specs.h b/vp8/common/mac_specs.h
+index 97bffc7..a12b8d5 100644
+--- a/vp8/common/mac_specs.h
++++ b/vp8/common/mac_specs.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/mbpitch.c b/vp8/common/mbpitch.c
+index a7e0ce9..b183b8e 100644
+--- a/vp8/common/mbpitch.c
++++ b/vp8/common/mbpitch.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/modecont.c b/vp8/common/modecont.c
+index 9301a25..c008eef 100644
+--- a/vp8/common/modecont.c
++++ b/vp8/common/modecont.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/modecont.h b/vp8/common/modecont.h
+index 0c57651..4b79722 100644
+--- a/vp8/common/modecont.h
++++ b/vp8/common/modecont.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/modecontext.c b/vp8/common/modecontext.c
+index ceee74c..a4b2f76 100644
+--- a/vp8/common/modecontext.c
++++ b/vp8/common/modecontext.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/mv.h b/vp8/common/mv.h
+index 3d84181..c3db5f0 100644
+--- a/vp8/common/mv.h
++++ b/vp8/common/mv.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/onyx.h b/vp8/common/onyx.h
+index b66c400..3ed6f2d 100644
+--- a/vp8/common/onyx.h
++++ b/vp8/common/onyx.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -16,7 +17,7 @@ extern "C"
+ {
+ #endif
+
+-#include "vpx_codec/internal/vpx_codec_internal.h"
++#include "vpx/internal/vpx_codec_internal.h"
+ #include "vpx_scale/yv12config.h"
+ #include "type_aliases.h"
+ #include "ppflags.h"
+diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h
+index a40ffb9..d1cb766 100644
+--- a/vp8/common/onyxc_int.h
++++ b/vp8/common/onyxc_int.h
+@@ -1,18 +1,19 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+ #ifndef __INC_VP8C_INT_H
+ #define __INC_VP8C_INT_H
+
+-#include "vpx_ports/config.h"
+-#include "vpx_codec/internal/vpx_codec_internal.h"
++#include "vpx_config.h"
++#include "vpx/internal/vpx_codec_internal.h"
+ #include "loopfilter.h"
+ #include "entropymv.h"
+ #include "entropy.h"
+diff --git a/vp8/common/onyxd.h b/vp8/common/onyxd.h
+index 644c0ec..ea04c14 100644
+--- a/vp8/common/onyxd.h
++++ b/vp8/common/onyxd.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/partialgfupdate.h b/vp8/common/partialgfupdate.h
+index 32a55ee..355aa79 100644
+--- a/vp8/common/partialgfupdate.h
++++ b/vp8/common/partialgfupdate.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/postproc.c b/vp8/common/postproc.c
+index f019925..1f36d4e 100644
+--- a/vp8/common/postproc.c
++++ b/vp8/common/postproc.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -274,7 +275,7 @@ static void vp8_deblock_and_de_macro_block(YV12_BUFFER_CONFIG *source,
+
+ }
+
+-extern void vp8_deblock(YV12_BUFFER_CONFIG *source,
++void vp8_deblock(YV12_BUFFER_CONFIG *source,
+ YV12_BUFFER_CONFIG *post,
+ int q,
+ int low_var_thresh,
+diff --git a/vp8/common/postproc.h b/vp8/common/postproc.h
+index c45fe92..e148f2a 100644
+--- a/vp8/common/postproc.h
++++ b/vp8/common/postproc.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -87,4 +88,11 @@ void vp8_de_noise(YV12_BUFFER_CONFIG *source,
+ int low_var_thresh,
+ int flag,
+ vp8_postproc_rtcd_vtable_t *rtcd);
++
++void vp8_deblock(YV12_BUFFER_CONFIG *source,
++ YV12_BUFFER_CONFIG *post,
++ int q,
++ int low_var_thresh,
++ int flag,
++ vp8_postproc_rtcd_vtable_t *rtcd);
+ #endif
+diff --git a/vp8/common/ppc/copy_altivec.asm b/vp8/common/ppc/copy_altivec.asm
+index e87eb21..5ca2d17 100644
+--- a/vp8/common/ppc/copy_altivec.asm
++++ b/vp8/common/ppc/copy_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/ppc/filter_altivec.asm b/vp8/common/ppc/filter_altivec.asm
+index 2a35507..1a7ebf7 100644
+--- a/vp8/common/ppc/filter_altivec.asm
++++ b/vp8/common/ppc/filter_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/ppc/filter_bilinear_altivec.asm b/vp8/common/ppc/filter_bilinear_altivec.asm
+index 27e02a8..73e758e 100644
+--- a/vp8/common/ppc/filter_bilinear_altivec.asm
++++ b/vp8/common/ppc/filter_bilinear_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/ppc/idctllm_altivec.asm b/vp8/common/ppc/idctllm_altivec.asm
+index e88af8d..9ebe6af 100644
+--- a/vp8/common/ppc/idctllm_altivec.asm
++++ b/vp8/common/ppc/idctllm_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/ppc/loopfilter_altivec.c b/vp8/common/ppc/loopfilter_altivec.c
+index 586eed4..8bf5e57 100644
+--- a/vp8/common/ppc/loopfilter_altivec.c
++++ b/vp8/common/ppc/loopfilter_altivec.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/ppc/loopfilter_filters_altivec.asm b/vp8/common/ppc/loopfilter_filters_altivec.asm
+index 78a5cf9..26c51a6 100644
+--- a/vp8/common/ppc/loopfilter_filters_altivec.asm
++++ b/vp8/common/ppc/loopfilter_filters_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/ppc/platform_altivec.asm b/vp8/common/ppc/platform_altivec.asm
+index 227ef2a..23680c9 100644
+--- a/vp8/common/ppc/platform_altivec.asm
++++ b/vp8/common/ppc/platform_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/ppc/recon_altivec.asm b/vp8/common/ppc/recon_altivec.asm
+index f478b95..212664d 100644
+--- a/vp8/common/ppc/recon_altivec.asm
++++ b/vp8/common/ppc/recon_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/ppc/systemdependent.c b/vp8/common/ppc/systemdependent.c
+index 2847310..4ccf690 100644
+--- a/vp8/common/ppc/systemdependent.c
++++ b/vp8/common/ppc/systemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/ppflags.h b/vp8/common/ppflags.h
+index c663976..57aeb1d 100644
+--- a/vp8/common/ppflags.h
++++ b/vp8/common/ppflags.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/pragmas.h b/vp8/common/pragmas.h
+index 25a4b77..523c8b7 100644
+--- a/vp8/common/pragmas.h
++++ b/vp8/common/pragmas.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/predictdc.c b/vp8/common/predictdc.c
+index df4c96e..18d7da8 100644
+--- a/vp8/common/predictdc.c
++++ b/vp8/common/predictdc.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/predictdc.h b/vp8/common/predictdc.h
+index b8871e4..69036ee 100644
+--- a/vp8/common/predictdc.h
++++ b/vp8/common/predictdc.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/preproc.h b/vp8/common/preproc.h
+index 00ec9a8..a02745c 100644
+--- a/vp8/common/preproc.h
++++ b/vp8/common/preproc.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/preprocif.h b/vp8/common/preprocif.h
+index 986c45b..f700f76 100644
+--- a/vp8/common/preprocif.h
++++ b/vp8/common/preprocif.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/proposed.h b/vp8/common/proposed.h
+index 1171ede..65b7834 100644
+--- a/vp8/common/proposed.h
++++ b/vp8/common/proposed.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/quant_common.c b/vp8/common/quant_common.c
+index 09fe31f..6fd3bc0 100644
+--- a/vp8/common/quant_common.c
++++ b/vp8/common/quant_common.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/quant_common.h b/vp8/common/quant_common.h
+index 0c92ce8..49d11bc 100644
+--- a/vp8/common/quant_common.h
++++ b/vp8/common/quant_common.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/recon.c b/vp8/common/recon.c
+index d1268ea..b09ef37 100644
+--- a/vp8/common/recon.c
++++ b/vp8/common/recon.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/recon.h b/vp8/common/recon.h
+index f65a90f..607895c 100644
+--- a/vp8/common/recon.h
++++ b/vp8/common/recon.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/reconinter.c b/vp8/common/reconinter.c
+index c48886d..91ec76b 100644
+--- a/vp8/common/reconinter.c
++++ b/vp8/common/reconinter.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/reconinter.h b/vp8/common/reconinter.h
+index b2d1ae9..9df4806 100644
+--- a/vp8/common/reconinter.h
++++ b/vp8/common/reconinter.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/reconintra.c b/vp8/common/reconintra.c
+index e33bce3..23d87ee 100644
+--- a/vp8/common/reconintra.c
++++ b/vp8/common/reconintra.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/reconintra.h b/vp8/common/reconintra.h
+index d63aa15..b7c4d1d 100644
+--- a/vp8/common/reconintra.h
++++ b/vp8/common/reconintra.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/reconintra4x4.c b/vp8/common/reconintra4x4.c
+index d92d5c9..3b22423 100644
+--- a/vp8/common/reconintra4x4.c
++++ b/vp8/common/reconintra4x4.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/reconintra4x4.h b/vp8/common/reconintra4x4.h
+index 788c8c4..881d091 100644
+--- a/vp8/common/reconintra4x4.h
++++ b/vp8/common/reconintra4x4.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/segmentation_common.c b/vp8/common/segmentation_common.c
+index 72b8c87..2568c7c 100644
+--- a/vp8/common/segmentation_common.c
++++ b/vp8/common/segmentation_common.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/segmentation_common.h b/vp8/common/segmentation_common.h
+index bb93533..7b36b49 100644
+--- a/vp8/common/segmentation_common.h
++++ b/vp8/common/segmentation_common.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/setupintrarecon.c b/vp8/common/setupintrarecon.c
+index dcaafe6..e796d42 100644
+--- a/vp8/common/setupintrarecon.c
++++ b/vp8/common/setupintrarecon.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -16,21 +17,15 @@ void vp8_setup_intra_recon(YV12_BUFFER_CONFIG *ybf)
+ int i;
+
+ // set up frame new frame for intra coded blocks
+- vpx_memset(ybf->y_buffer - 1 - 2 * ybf->y_stride, 127, ybf->y_width + 5);
+ vpx_memset(ybf->y_buffer - 1 - ybf->y_stride, 127, ybf->y_width + 5);
+-
+ for (i = 0; i < ybf->y_height; i++)
+ ybf->y_buffer[ybf->y_stride *i - 1] = (unsigned char) 129;
+
+- vpx_memset(ybf->u_buffer - 1 - 2 * ybf->uv_stride, 127, ybf->uv_width + 5);
+ vpx_memset(ybf->u_buffer - 1 - ybf->uv_stride, 127, ybf->uv_width + 5);
+-
+ for (i = 0; i < ybf->uv_height; i++)
+ ybf->u_buffer[ybf->uv_stride *i - 1] = (unsigned char) 129;
+
+- vpx_memset(ybf->v_buffer - 1 - 2 * ybf->uv_stride, 127, ybf->uv_width + 5);
+ vpx_memset(ybf->v_buffer - 1 - ybf->uv_stride, 127, ybf->uv_width + 5);
+-
+ for (i = 0; i < ybf->uv_height; i++)
+ ybf->v_buffer[ybf->uv_stride *i - 1] = (unsigned char) 129;
+
+diff --git a/vp8/common/setupintrarecon.h b/vp8/common/setupintrarecon.h
+index 6ec79b2..ea4e342 100644
+--- a/vp8/common/setupintrarecon.h
++++ b/vp8/common/setupintrarecon.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/subpixel.h b/vp8/common/subpixel.h
+index fbd5f4d..446697c 100644
+--- a/vp8/common/subpixel.h
++++ b/vp8/common/subpixel.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/swapyv12buffer.c b/vp8/common/swapyv12buffer.c
+index afe6a88..5bdf431 100644
+--- a/vp8/common/swapyv12buffer.c
++++ b/vp8/common/swapyv12buffer.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/swapyv12buffer.h b/vp8/common/swapyv12buffer.h
+index caf9499..f2c3b74 100644
+--- a/vp8/common/swapyv12buffer.h
++++ b/vp8/common/swapyv12buffer.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/systemdependent.h b/vp8/common/systemdependent.h
+index 1829b64..56218e6 100644
+--- a/vp8/common/systemdependent.h
++++ b/vp8/common/systemdependent.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/textblit.c b/vp8/common/textblit.c
+index a45937b..5d117f1 100644
+--- a/vp8/common/textblit.c
++++ b/vp8/common/textblit.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/threading.h b/vp8/common/threading.h
+index a02cb24..7c94645 100644
+--- a/vp8/common/threading.h
++++ b/vp8/common/threading.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/treecoder.c b/vp8/common/treecoder.c
+index 4ad018d..0ccd64d 100644
+--- a/vp8/common/treecoder.c
++++ b/vp8/common/treecoder.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/treecoder.h b/vp8/common/treecoder.h
+index 0356d2b..908dbcb 100644
+--- a/vp8/common/treecoder.h
++++ b/vp8/common/treecoder.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/type_aliases.h b/vp8/common/type_aliases.h
+index addd264..a0d8717 100644
+--- a/vp8/common/type_aliases.h
++++ b/vp8/common/type_aliases.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/vfwsetting.hpp b/vp8/common/vfwsetting.hpp
+index e352e7a..c01a0dd 100644
+--- a/vp8/common/vfwsetting.hpp
++++ b/vp8/common/vfwsetting.hpp
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/vpx_ref_build_prefix.h b/vp8/common/vpx_ref_build_prefix.h
+index 40608c6..cded66c 100644
+--- a/vp8/common/vpx_ref_build_prefix.h
++++ b/vp8/common/vpx_ref_build_prefix.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/vpxblit.h b/vp8/common/vpxblit.h
+index d03e0bd..2c7f673 100644
+--- a/vp8/common/vpxblit.h
++++ b/vp8/common/vpxblit.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/vpxblit_c64.h b/vp8/common/vpxblit_c64.h
+index a8e28f5..7659b5c 100644
+--- a/vp8/common/vpxblit_c64.h
++++ b/vp8/common/vpxblit_c64.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/vpxerrors.h b/vp8/common/vpxerrors.h
+index e4c9f3e..f0ec707 100644
+--- a/vp8/common/vpxerrors.h
++++ b/vp8/common/vpxerrors.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/boolcoder.cxx b/vp8/common/x86/boolcoder.cxx
+index 06faca6..cd9c495 100644
+--- a/vp8/common/x86/boolcoder.cxx
++++ b/vp8/common/x86/boolcoder.cxx
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/idct_x86.h b/vp8/common/x86/idct_x86.h
+index 5dfb212..1f2cb63 100644
+--- a/vp8/common/x86/idct_x86.h
++++ b/vp8/common/x86/idct_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/idctllm_mmx.asm b/vp8/common/x86/idctllm_mmx.asm
+index 2751c69..5ec01e9 100644
+--- a/vp8/common/x86/idctllm_mmx.asm
++++ b/vp8/common/x86/idctllm_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/x86/iwalsh_mmx.asm b/vp8/common/x86/iwalsh_mmx.asm
+index 562e590..6cb8979 100644
+--- a/vp8/common/x86/iwalsh_mmx.asm
++++ b/vp8/common/x86/iwalsh_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/x86/iwalsh_sse2.asm b/vp8/common/x86/iwalsh_sse2.asm
+index 96943df..bb0d1d7 100644
+--- a/vp8/common/x86/iwalsh_sse2.asm
++++ b/vp8/common/x86/iwalsh_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+@@ -16,6 +17,7 @@ sym(vp8_short_inv_walsh4x4_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 2
++ SAVE_XMM
+ push rsi
+ push rdi
+ ; end prolog
+@@ -100,6 +102,7 @@ sym(vp8_short_inv_walsh4x4_sse2):
+ ; begin epilog
+ pop rdi
+ pop rsi
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+diff --git a/vp8/common/x86/loopfilter_mmx.asm b/vp8/common/x86/loopfilter_mmx.asm
+index 6e4d2b6..6e6efab 100644
+--- a/vp8/common/x86/loopfilter_mmx.asm
++++ b/vp8/common/x86/loopfilter_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/x86/loopfilter_sse2.asm b/vp8/common/x86/loopfilter_sse2.asm
+index 5275dfa..d160dd6 100644
+--- a/vp8/common/x86/loopfilter_sse2.asm
++++ b/vp8/common/x86/loopfilter_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+@@ -25,6 +26,7 @@ sym(vp8_loop_filter_horizontal_edge_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -211,6 +213,7 @@ sym(vp8_loop_filter_horizontal_edge_sse2):
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -230,6 +233,7 @@ sym(vp8_loop_filter_vertical_edge_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -651,6 +655,7 @@ sym(vp8_loop_filter_vertical_edge_sse2):
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -670,6 +675,7 @@ sym(vp8_mbloop_filter_horizontal_edge_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -1001,6 +1007,7 @@ sym(vp8_mbloop_filter_horizontal_edge_sse2):
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -1020,6 +1027,7 @@ sym(vp8_mbloop_filter_vertical_edge_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -1563,6 +1571,7 @@ sym(vp8_mbloop_filter_vertical_edge_sse2):
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -1582,6 +1591,7 @@ sym(vp8_loop_filter_simple_horizontal_edge_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -1678,6 +1688,7 @@ sym(vp8_loop_filter_simple_horizontal_edge_sse2):
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -1697,6 +1708,7 @@ sym(vp8_loop_filter_simple_vertical_edge_sse2):
+ push rbp ; save old base pointer value.
+ mov rbp, rsp ; set new base pointer value.
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx ; save callee-saved reg
+ push rsi
+ push rdi
+@@ -1941,6 +1953,7 @@ sym(vp8_loop_filter_simple_vertical_edge_sse2):
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+diff --git a/vp8/common/x86/loopfilter_x86.c b/vp8/common/x86/loopfilter_x86.c
+index 143ee74..f5af7cf 100644
+--- a/vp8/common/x86/loopfilter_x86.c
++++ b/vp8/common/x86/loopfilter_x86.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/loopfilter_x86.h b/vp8/common/x86/loopfilter_x86.h
+index c87f38a..503bf5b 100644
+--- a/vp8/common/x86/loopfilter_x86.h
++++ b/vp8/common/x86/loopfilter_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/postproc_mmx.asm b/vp8/common/x86/postproc_mmx.asm
+index 721c8d6..0707651 100644
+--- a/vp8/common/x86/postproc_mmx.asm
++++ b/vp8/common/x86/postproc_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/x86/postproc_mmx.c b/vp8/common/x86/postproc_mmx.c
+index 095797b..f3b2923 100644
+--- a/vp8/common/x86/postproc_mmx.c
++++ b/vp8/common/x86/postproc_mmx.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/postproc_sse2.asm b/vp8/common/x86/postproc_sse2.asm
+index bfa36fa..9e56429 100644
+--- a/vp8/common/x86/postproc_sse2.asm
++++ b/vp8/common/x86/postproc_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+@@ -25,6 +26,7 @@ sym(vp8_post_proc_down_and_across_xmm):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 7
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -239,6 +241,7 @@ acrossnextcol:
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -253,6 +256,7 @@ sym(vp8_mbpost_proc_down_xmm):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 5
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -438,6 +442,7 @@ loop_row:
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -451,6 +456,7 @@ sym(vp8_mbpost_proc_across_ip_xmm):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 5
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -611,6 +617,7 @@ nextcol4:
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+diff --git a/vp8/common/x86/postproc_x86.h b/vp8/common/x86/postproc_x86.h
+index 49a1907..f939427 100644
+--- a/vp8/common/x86/postproc_x86.h
++++ b/vp8/common/x86/postproc_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/recon_mmx.asm b/vp8/common/x86/recon_mmx.asm
+index ba60c5d..95c308d 100644
+--- a/vp8/common/x86/recon_mmx.asm
++++ b/vp8/common/x86/recon_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/x86/recon_sse2.asm b/vp8/common/x86/recon_sse2.asm
+index f2685a7..cfdbfad 100644
+--- a/vp8/common/x86/recon_sse2.asm
++++ b/vp8/common/x86/recon_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+@@ -66,6 +67,7 @@ sym(vp8_recon4b_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 4
++ SAVE_XMM
+ push rsi
+ push rdi
+ ; end prolog
+@@ -118,6 +120,7 @@ sym(vp8_recon4b_sse2):
+ ; begin epilog
+ pop rdi
+ pop rsi
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+diff --git a/vp8/common/x86/recon_x86.h b/vp8/common/x86/recon_x86.h
+index c469778..fcd429c 100644
+--- a/vp8/common/x86/recon_x86.h
++++ b/vp8/common/x86/recon_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/subpixel_mmx.asm b/vp8/common/x86/subpixel_mmx.asm
+index c502118..b3e4ad5 100644
+--- a/vp8/common/x86/subpixel_mmx.asm
++++ b/vp8/common/x86/subpixel_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/common/x86/subpixel_sse2.asm b/vp8/common/x86/subpixel_sse2.asm
+index dee04f2..ee383ad 100644
+--- a/vp8/common/x86/subpixel_sse2.asm
++++ b/vp8/common/x86/subpixel_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+@@ -36,6 +37,7 @@ sym(vp8_filter_block1d8_h6_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 7
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -128,6 +130,7 @@ filter_block1d8_h6_rowloop:
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -154,6 +157,7 @@ sym(vp8_filter_block1d16_h6_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 7
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -303,6 +307,7 @@ filter_block1d16_h6_sse2_rowloop:
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -328,6 +333,7 @@ sym(vp8_filter_block1d8_v6_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 8
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -396,221 +402,553 @@ vp8_filter_block1d8_v6_sse2_loop:
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+
+-;void vp8_unpack_block1d16_h6_sse2
++;void vp8_filter_block1d16_v6_sse2
++;(
++; unsigned short *src_ptr,
++; unsigned char *output_ptr,
++; int dst_ptich,
++; unsigned int pixels_per_line,
++; unsigned int pixel_step,
++; unsigned int output_height,
++; unsigned int output_width,
++; const short *vp8_filter
++;)
++;/************************************************************************************
++; Notes: filter_block1d16_v6 applies a 6 tap filter vertically to the input pixels. The
++; input pixel array has output_height rows.
++;*************************************************************************************/
++global sym(vp8_filter_block1d16_v6_sse2)
++sym(vp8_filter_block1d16_v6_sse2):
++ push rbp
++ mov rbp, rsp
++ SHADOW_ARGS_TO_STACK 8
++ SAVE_XMM
++ GET_GOT rbx
++ push rsi
++ push rdi
++ ; end prolog
++
++ mov rax, arg(7) ;vp8_filter
++ movsxd rdx, dword ptr arg(3) ;pixels_per_line
++
++ mov rdi, arg(1) ;output_ptr
++ mov rsi, arg(0) ;src_ptr
++
++ sub rsi, rdx
++ sub rsi, rdx
++
++ movsxd rcx, DWORD PTR arg(5) ;[output_height]
++%if ABI_IS_32BIT=0
++ movsxd r8, dword ptr arg(2) ; dst_ptich
++%endif
++
++vp8_filter_block1d16_v6_sse2_loop:
++; The order for adding 6-tap is 2 5 3 1 4 6. Read in data in that order.
++ movdqa xmm1, XMMWORD PTR [rsi + rdx] ; line 2
++ movdqa xmm2, XMMWORD PTR [rsi + rdx + 16]
++ pmullw xmm1, [rax + 16]
++ pmullw xmm2, [rax + 16]
++
++ movdqa xmm3, XMMWORD PTR [rsi + rdx * 4] ; line 5
++ movdqa xmm4, XMMWORD PTR [rsi + rdx * 4 + 16]
++ pmullw xmm3, [rax + 64]
++ pmullw xmm4, [rax + 64]
++
++ movdqa xmm5, XMMWORD PTR [rsi + rdx * 2] ; line 3
++ movdqa xmm6, XMMWORD PTR [rsi + rdx * 2 + 16]
++ pmullw xmm5, [rax + 32]
++ pmullw xmm6, [rax + 32]
++
++ movdqa xmm7, XMMWORD PTR [rsi] ; line 1
++ movdqa xmm0, XMMWORD PTR [rsi + 16]
++ pmullw xmm7, [rax]
++ pmullw xmm0, [rax]
++
++ paddsw xmm1, xmm3
++ paddsw xmm2, xmm4
++ paddsw xmm1, xmm5
++ paddsw xmm2, xmm6
++ paddsw xmm1, xmm7
++ paddsw xmm2, xmm0
++
++ add rsi, rdx
++
++ movdqa xmm3, XMMWORD PTR [rsi + rdx * 2] ; line 4
++ movdqa xmm4, XMMWORD PTR [rsi + rdx * 2 + 16]
++ pmullw xmm3, [rax + 48]
++ pmullw xmm4, [rax + 48]
++
++ movdqa xmm5, XMMWORD PTR [rsi + rdx * 4] ; line 6
++ movdqa xmm6, XMMWORD PTR [rsi + rdx * 4 + 16]
++ pmullw xmm5, [rax + 80]
++ pmullw xmm6, [rax + 80]
++
++ movdqa xmm7, XMMWORD PTR [rd GLOBAL]
++ pxor xmm0, xmm0 ; clear xmm0
++
++ paddsw xmm1, xmm3
++ paddsw xmm2, xmm4
++ paddsw xmm1, xmm5
++ paddsw xmm2, xmm6
++
++ paddsw xmm1, xmm7
++ paddsw xmm2, xmm7
++
++ psraw xmm1, 7
++ psraw xmm2, 7
++
++ packuswb xmm1, xmm2 ; pack and saturate
++ movdqa XMMWORD PTR [rdi], xmm1 ; store the results in the destination
++%if ABI_IS_32BIT
++ add rdi, DWORD PTR arg(2) ;[dst_ptich]
++%else
++ add rdi, r8
++%endif
++ dec rcx ; decrement count
++ jnz vp8_filter_block1d16_v6_sse2_loop ; next row
++
++ ; begin epilog
++ pop rdi
++ pop rsi
++ RESTORE_GOT
++ RESTORE_XMM
++ UNSHADOW_ARGS
++ pop rbp
++ ret
++
++
++;void vp8_filter_block1d8_h6_only_sse2
+ ;(
+ ; unsigned char *src_ptr,
+-; unsigned short *output_ptr,
+ ; unsigned int src_pixels_per_line,
++; unsigned char *output_ptr,
++; int dst_ptich,
+ ; unsigned int output_height,
+-; unsigned int output_width
++; const short *vp8_filter
+ ;)
+-global sym(vp8_unpack_block1d16_h6_sse2)
+-sym(vp8_unpack_block1d16_h6_sse2):
++; First-pass filter only when yoffset==0
++global sym(vp8_filter_block1d8_h6_only_sse2)
++sym(vp8_filter_block1d8_h6_only_sse2):
+ push rbp
+ mov rbp, rsp
+- SHADOW_ARGS_TO_STACK 5
++ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+ ; end prolog
+
++ mov rdx, arg(5) ;vp8_filter
+ mov rsi, arg(0) ;src_ptr
+- mov rdi, arg(1) ;output_ptr
+
+- movsxd rcx, dword ptr arg(3) ;output_height
+- movsxd rax, dword ptr arg(2) ;src_pixels_per_line ; Pitch for Source
++ mov rdi, arg(2) ;output_ptr
+
+- pxor xmm0, xmm0 ; clear xmm0 for unpack
++ movsxd rcx, dword ptr arg(4) ;output_height
++ movsxd rax, dword ptr arg(1) ;src_pixels_per_line ; Pitch for Source
+ %if ABI_IS_32BIT=0
+- movsxd r8, dword ptr arg(4) ;output_width ; Pitch for Source
++ movsxd r8, dword ptr arg(3) ;dst_ptich
+ %endif
++ pxor xmm0, xmm0 ; clear xmm0 for unpack
+
+-unpack_block1d16_h6_sse2_rowloop:
+- movq xmm1, MMWORD PTR [rsi] ; 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1 -2
+- movq xmm3, MMWORD PTR [rsi+8] ; make copy of xmm1
++filter_block1d8_h6_only_rowloop:
++ movq xmm3, MMWORD PTR [rsi - 2]
++ movq xmm1, MMWORD PTR [rsi + 6]
++
++ prefetcht2 [rsi+rax-2]
++
++ pslldq xmm1, 8
++ por xmm1, xmm3
++
++ movdqa xmm4, xmm1
++ movdqa xmm5, xmm1
++
++ movdqa xmm6, xmm1
++ movdqa xmm7, xmm1
+
+ punpcklbw xmm3, xmm0 ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+- punpcklbw xmm1, xmm0
++ psrldq xmm4, 1 ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
++
++ pmullw xmm3, XMMWORD PTR [rdx] ; x[-2] * H[-2]; Tap 1
++ punpcklbw xmm4, xmm0 ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
++
++ psrldq xmm5, 2 ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
++ pmullw xmm4, XMMWORD PTR [rdx+16] ; x[-1] * H[-1]; Tap 2
++
++
++ punpcklbw xmm5, xmm0 ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
++ psrldq xmm6, 3 ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
++
++ pmullw xmm5, [rdx+32] ; x[ 0] * H[ 0]; Tap 3
++
++ punpcklbw xmm6, xmm0 ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
++ psrldq xmm7, 4 ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
++
++ pmullw xmm6, [rdx+48] ; x[ 1] * h[ 1] ; Tap 4
++
++ punpcklbw xmm7, xmm0 ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
++ psrldq xmm1, 5 ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
++
++
++ pmullw xmm7, [rdx+64] ; x[ 2] * h[ 2] ; Tap 5
++
++ punpcklbw xmm1, xmm0 ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
++ pmullw xmm1, [rdx+80] ; x[ 3] * h[ 3] ; Tap 6
+
+- movdqa XMMWORD Ptr [rdi], xmm1
+- movdqa XMMWORD Ptr [rdi + 16], xmm3
+
++ paddsw xmm4, xmm7
++ paddsw xmm4, xmm5
++
++ paddsw xmm4, xmm3
++ paddsw xmm4, xmm6
++
++ paddsw xmm4, xmm1
++ paddsw xmm4, [rd GLOBAL]
++
++ psraw xmm4, 7
++
++ packuswb xmm4, xmm0
++
++ movq QWORD PTR [rdi], xmm4 ; store the results in the destination
+ lea rsi, [rsi + rax]
++
+ %if ABI_IS_32BIT
+- add rdi, DWORD Ptr arg(4) ;[output_width]
++ add rdi, DWORD Ptr arg(3) ;dst_ptich
+ %else
+ add rdi, r8
+ %endif
+ dec rcx
+- jnz unpack_block1d16_h6_sse2_rowloop ; next row
++
++ jnz filter_block1d8_h6_only_rowloop ; next row
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+
+-;void vp8_unpack_block1d8_h6_sse2
++;void vp8_filter_block1d16_h6_only_sse2
+ ;(
+ ; unsigned char *src_ptr,
+-; unsigned short *output_ptr,
+ ; unsigned int src_pixels_per_line,
++; unsigned char *output_ptr,
++; int dst_ptich,
+ ; unsigned int output_height,
+-; unsigned int output_width
++; const short *vp8_filter
+ ;)
+-global sym(vp8_unpack_block1d8_h6_sse2)
+-sym(vp8_unpack_block1d8_h6_sse2):
++; First-pass filter only when yoffset==0
++global sym(vp8_filter_block1d16_h6_only_sse2)
++sym(vp8_filter_block1d16_h6_only_sse2):
+ push rbp
+ mov rbp, rsp
+- SHADOW_ARGS_TO_STACK 5
++ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+ ; end prolog
+
++ mov rdx, arg(5) ;vp8_filter
+ mov rsi, arg(0) ;src_ptr
+- mov rdi, arg(1) ;output_ptr
+
+- movsxd rcx, dword ptr arg(3) ;output_height
+- movsxd rax, dword ptr arg(2) ;src_pixels_per_line ; Pitch for Source
++ mov rdi, arg(2) ;output_ptr
+
+- pxor xmm0, xmm0 ; clear xmm0 for unpack
++ movsxd rcx, dword ptr arg(4) ;output_height
++ movsxd rax, dword ptr arg(1) ;src_pixels_per_line ; Pitch for Source
+ %if ABI_IS_32BIT=0
+- movsxd r8, dword ptr arg(4) ;output_width ; Pitch for Source
++ movsxd r8, dword ptr arg(3) ;dst_ptich
+ %endif
+
+-unpack_block1d8_h6_sse2_rowloop:
+- movq xmm1, MMWORD PTR [rsi] ; 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1 -2
+- lea rsi, [rsi + rax]
++ pxor xmm0, xmm0 ; clear xmm0 for unpack
+
+- punpcklbw xmm1, xmm0
+- movdqa XMMWORD Ptr [rdi], xmm1
++filter_block1d16_h6_only_sse2_rowloop:
++ movq xmm3, MMWORD PTR [rsi - 2]
++ movq xmm1, MMWORD PTR [rsi + 6]
++
++ movq xmm2, MMWORD PTR [rsi +14]
++ pslldq xmm2, 8
++
++ por xmm2, xmm1
++ prefetcht2 [rsi+rax-2]
++
++ pslldq xmm1, 8
++ por xmm1, xmm3
+
++ movdqa xmm4, xmm1
++ movdqa xmm5, xmm1
++
++ movdqa xmm6, xmm1
++ movdqa xmm7, xmm1
++
++ punpcklbw xmm3, xmm0 ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
++ psrldq xmm4, 1 ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
++
++ pmullw xmm3, XMMWORD PTR [rdx] ; x[-2] * H[-2]; Tap 1
++ punpcklbw xmm4, xmm0 ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
++
++ psrldq xmm5, 2 ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
++ pmullw xmm4, XMMWORD PTR [rdx+16] ; x[-1] * H[-1]; Tap 2
++
++ punpcklbw xmm5, xmm0 ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
++ psrldq xmm6, 3 ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
++
++ pmullw xmm5, [rdx+32] ; x[ 0] * H[ 0]; Tap 3
++
++ punpcklbw xmm6, xmm0 ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
++ psrldq xmm7, 4 ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
++
++ pmullw xmm6, [rdx+48] ; x[ 1] * h[ 1] ; Tap 4
++
++ punpcklbw xmm7, xmm0 ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
++ psrldq xmm1, 5 ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
++
++ pmullw xmm7, [rdx+64] ; x[ 2] * h[ 2] ; Tap 5
++
++ punpcklbw xmm1, xmm0 ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
++ pmullw xmm1, [rdx+80] ; x[ 3] * h[ 3] ; Tap 6
++
++ paddsw xmm4, xmm7
++ paddsw xmm4, xmm5
++
++ paddsw xmm4, xmm3
++ paddsw xmm4, xmm6
++
++ paddsw xmm4, xmm1
++ paddsw xmm4, [rd GLOBAL]
++
++ psraw xmm4, 7
++
++ packuswb xmm4, xmm0 ; lower 8 bytes
++
++ movq QWORD Ptr [rdi], xmm4 ; store the results in the destination
++
++ movdqa xmm3, xmm2
++ movdqa xmm4, xmm2
++
++ movdqa xmm5, xmm2
++ movdqa xmm6, xmm2
++
++ movdqa xmm7, xmm2
++
++ punpcklbw xmm3, xmm0 ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
++ psrldq xmm4, 1 ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
++
++ pmullw xmm3, XMMWORD PTR [rdx] ; x[-2] * H[-2]; Tap 1
++ punpcklbw xmm4, xmm0 ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
++
++ psrldq xmm5, 2 ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
++ pmullw xmm4, XMMWORD PTR [rdx+16] ; x[-1] * H[-1]; Tap 2
++
++ punpcklbw xmm5, xmm0 ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
++ psrldq xmm6, 3 ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
++
++ pmullw xmm5, [rdx+32] ; x[ 0] * H[ 0]; Tap 3
++
++ punpcklbw xmm6, xmm0 ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
++ psrldq xmm7, 4 ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
++
++ pmullw xmm6, [rdx+48] ; x[ 1] * h[ 1] ; Tap 4
++
++ punpcklbw xmm7, xmm0 ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
++ psrldq xmm2, 5 ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
++
++ pmullw xmm7, [rdx+64] ; x[ 2] * h[ 2] ; Tap 5
++
++ punpcklbw xmm2, xmm0 ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
++ pmullw xmm2, [rdx+80] ; x[ 3] * h[ 3] ; Tap 6
++
++ paddsw xmm4, xmm7
++ paddsw xmm4, xmm5
++
++ paddsw xmm4, xmm3
++ paddsw xmm4, xmm6
++
++ paddsw xmm4, xmm2
++ paddsw xmm4, [rd GLOBAL]
++
++ psraw xmm4, 7
++
++ packuswb xmm4, xmm0 ; higher 8 bytes
++
++ movq QWORD Ptr [rdi+8], xmm4 ; store the results in the destination
++
++ lea rsi, [rsi + rax]
+ %if ABI_IS_32BIT
+- add rdi, DWORD Ptr arg(4) ;[output_width]
++ add rdi, DWORD Ptr arg(3) ;dst_ptich
+ %else
+ add rdi, r8
+ %endif
++
+ dec rcx
+- jnz unpack_block1d8_h6_sse2_rowloop ; next row
++ jnz filter_block1d16_h6_only_sse2_rowloop ; next row
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+
+-;void vp8_pack_block1d8_v6_sse2
++;void vp8_filter_block1d8_v6_only_sse2
+ ;(
+-; short *src_ptr,
++; unsigned char *src_ptr,
++; unsigned int src_pixels_per_line,
+ ; unsigned char *output_ptr,
+ ; int dst_ptich,
+-; unsigned int pixels_per_line,
+ ; unsigned int output_height,
+-; unsigned int output_width
++; const short *vp8_filter
+ ;)
+-global sym(vp8_pack_block1d8_v6_sse2)
+-sym(vp8_pack_block1d8_v6_sse2):
++; Second-pass filter only when xoffset==0
++global sym(vp8_filter_block1d8_v6_only_sse2)
++sym(vp8_filter_block1d8_v6_only_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+ ; end prolog
+
+- movsxd rdx, dword ptr arg(3) ;pixels_per_line
+- mov rdi, arg(1) ;output_ptr
+-
+ mov rsi, arg(0) ;src_ptr
+- movsxd rcx, DWORD PTR arg(4) ;[output_height]
++ mov rdi, arg(2) ;output_ptr
++
++ movsxd rcx, dword ptr arg(4) ;output_height
++ movsxd rdx, dword ptr arg(1) ;src_pixels_per_line
++
++ mov rax, arg(5) ;vp8_filter
++
++ pxor xmm0, xmm0 ; clear xmm0
++
++ movdqa xmm7, XMMWORD PTR [rd GLOBAL]
+ %if ABI_IS_32BIT=0
+- movsxd r8, dword ptr arg(5) ;output_width ; Pitch for Source
++ movsxd r8, dword ptr arg(3) ; dst_ptich
+ %endif
+
+-pack_block1d8_v6_sse2_loop:
+- movdqa xmm0, XMMWORD PTR [rsi]
+- packuswb xmm0, xmm0
++vp8_filter_block1d8_v6_only_sse2_loop:
++ movq xmm1, MMWORD PTR [rsi]
++ movq xmm2, MMWORD PTR [rsi + rdx]
++ movq xmm3, MMWORD PTR [rsi + rdx * 2]
++ movq xmm5, MMWORD PTR [rsi + rdx * 4]
++ add rsi, rdx
++ movq xmm4, MMWORD PTR [rsi + rdx * 2]
++ movq xmm6, MMWORD PTR [rsi + rdx * 4]
++
++ punpcklbw xmm1, xmm0
++ pmullw xmm1, [rax]
++
++ punpcklbw xmm2, xmm0
++ pmullw xmm2, [rax + 16]
++
++ punpcklbw xmm3, xmm0
++ pmullw xmm3, [rax + 32]
++
++ punpcklbw xmm5, xmm0
++ pmullw xmm5, [rax + 64]
++
++ punpcklbw xmm4, xmm0
++ pmullw xmm4, [rax + 48]
++
++ punpcklbw xmm6, xmm0
++ pmullw xmm6, [rax + 80]
++
++ paddsw xmm2, xmm5
++ paddsw xmm2, xmm3
++
++ paddsw xmm2, xmm1
++ paddsw xmm2, xmm4
++
++ paddsw xmm2, xmm6
++ paddsw xmm2, xmm7
+
+- movq QWORD PTR [rdi], xmm0 ; store the results in the destination
+- lea rsi, [rsi+rdx]
++ psraw xmm2, 7
++ packuswb xmm2, xmm0 ; pack and saturate
+
++ movq QWORD PTR [rdi], xmm2 ; store the results in the destination
+ %if ABI_IS_32BIT
+- add rdi, DWORD Ptr arg(5) ;[output_width]
++ add rdi, DWORD PTR arg(3) ;[dst_ptich]
+ %else
+ add rdi, r8
+ %endif
+ dec rcx ; decrement count
+- jnz pack_block1d8_v6_sse2_loop ; next row
++ jnz vp8_filter_block1d8_v6_only_sse2_loop ; next row
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+
+
+-;void vp8_pack_block1d16_v6_sse2
++;void vp8_unpack_block1d16_h6_sse2
+ ;(
+-; short *src_ptr,
+-; unsigned char *output_ptr,
+-; int dst_ptich,
+-; unsigned int pixels_per_line,
+-; unsigned int output_height,
+-; unsigned int output_width
++; unsigned char *src_ptr,
++; unsigned short *output_ptr,
++; unsigned int src_pixels_per_line,
++; unsigned int output_height,
++; unsigned int output_width
+ ;)
+-global sym(vp8_pack_block1d16_v6_sse2)
+-sym(vp8_pack_block1d16_v6_sse2):
++global sym(vp8_unpack_block1d16_h6_sse2)
++sym(vp8_unpack_block1d16_h6_sse2):
+ push rbp
+ mov rbp, rsp
+- SHADOW_ARGS_TO_STACK 6
++ SHADOW_ARGS_TO_STACK 5
++ ;SAVE_XMM ;xmm6, xmm7 are not used here.
+ GET_GOT rbx
+ push rsi
+ push rdi
+ ; end prolog
+
+- movsxd rdx, dword ptr arg(3) ;pixels_per_line
++ mov rsi, arg(0) ;src_ptr
+ mov rdi, arg(1) ;output_ptr
+
+- mov rsi, arg(0) ;src_ptr
+- movsxd rcx, DWORD PTR arg(4) ;[output_height]
++ movsxd rcx, dword ptr arg(3) ;output_height
++ movsxd rax, dword ptr arg(2) ;src_pixels_per_line ; Pitch for Source
++
++ pxor xmm0, xmm0 ; clear xmm0 for unpack
+ %if ABI_IS_32BIT=0
+- movsxd r8, dword ptr arg(2) ;dst_pitch
++ movsxd r8, dword ptr arg(4) ;output_width ; Pitch for Source
+ %endif
+
+-pack_block1d16_v6_sse2_loop:
+- movdqa xmm0, XMMWORD PTR [rsi]
+- movdqa xmm1, XMMWORD PTR [rsi+16]
++unpack_block1d16_h6_sse2_rowloop:
++ movq xmm1, MMWORD PTR [rsi] ; 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1 -2
++ movq xmm3, MMWORD PTR [rsi+8] ; make copy of xmm1
++
++ punpcklbw xmm3, xmm0 ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
++ punpcklbw xmm1, xmm0
+
+- packuswb xmm0, xmm1
+- movdqa XMMWORD PTR [rdi], xmm0 ; store the results in the destination
++ movdqa XMMWORD Ptr [rdi], xmm1
++ movdqa XMMWORD Ptr [rdi + 16], xmm3
+
+- add rsi, rdx
++ lea rsi, [rsi + rax]
+ %if ABI_IS_32BIT
+- add rdi, DWORD Ptr arg(2) ;dst_pitch
++ add rdi, DWORD Ptr arg(4) ;[output_width]
+ %else
+ add rdi, r8
+ %endif
+- dec rcx ; decrement count
+- jnz pack_block1d16_v6_sse2_loop ; next row
++ dec rcx
++ jnz unpack_block1d16_h6_sse2_rowloop ; next row
+
+ ; begin epilog
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ ;RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -631,6 +969,7 @@ sym(vp8_bilinear_predict16x16_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -878,6 +1217,7 @@ done:
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+@@ -898,6 +1238,7 @@ sym(vp8_bilinear_predict8x8_sse2):
+ push rbp
+ mov rbp, rsp
+ SHADOW_ARGS_TO_STACK 6
++ SAVE_XMM
+ GET_GOT rbx
+ push rsi
+ push rdi
+@@ -1021,6 +1362,7 @@ next_row8x8:
+ pop rdi
+ pop rsi
+ RESTORE_GOT
++ RESTORE_XMM
+ UNSHADOW_ARGS
+ pop rbp
+ ret
+diff --git a/vp8/common/x86/subpixel_x86.h b/vp8/common/x86/subpixel_x86.h
+index efa7b2e..bd6859c 100644
+--- a/vp8/common/x86/subpixel_x86.h
++++ b/vp8/common/x86/subpixel_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/common/x86/vp8_asm_stubs.c b/vp8/common/x86/vp8_asm_stubs.c
+index 68454f7..163ec5b 100644
+--- a/vp8/common/x86/vp8_asm_stubs.c
++++ b/vp8/common/x86/vp8_asm_stubs.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -67,6 +68,17 @@ extern void vp8_filter_block1d8_v6_sse2
+ unsigned int output_width,
+ const short *vp8_filter
+ );
++extern void vp8_filter_block1d16_v6_sse2
++(
++ unsigned short *src_ptr,
++ unsigned char *output_ptr,
++ int dst_ptich,
++ unsigned int pixels_per_line,
++ unsigned int pixel_step,
++ unsigned int output_height,
++ unsigned int output_width,
++ const short *vp8_filter
++);
+ extern void vp8_unpack_block1d16_h6_sse2
+ (
+ unsigned char *src_ptr,
+@@ -75,31 +87,32 @@ extern void vp8_unpack_block1d16_h6_sse2
+ unsigned int output_height,
+ unsigned int output_width
+ );
+-extern void vp8_unpack_block1d8_h6_sse2
++extern void vp8_filter_block1d8_h6_only_sse2
+ (
+ unsigned char *src_ptr,
+- unsigned short *output_ptr,
+ unsigned int src_pixels_per_line,
++ unsigned char *output_ptr,
++ int dst_ptich,
+ unsigned int output_height,
+- unsigned int output_width
++ const short *vp8_filter
+ );
+-extern void vp8_pack_block1d8_v6_sse2
++extern void vp8_filter_block1d16_h6_only_sse2
+ (
+- unsigned short *src_ptr,
+- unsigned char *output_ptr,
++ unsigned char *src_ptr,
++ unsigned int src_pixels_per_line,
++ unsigned char *output_ptr,
+ int dst_ptich,
+- unsigned int pixels_per_line,
+- unsigned int output_height,
+- unsigned int output_width
++ unsigned int output_height,
++ const short *vp8_filter
+ );
+-extern void vp8_pack_block1d16_v6_sse2
++extern void vp8_filter_block1d8_v6_only_sse2
+ (
+- unsigned short *src_ptr,
++ unsigned char *src_ptr,
++ unsigned int src_pixels_per_line,
+ unsigned char *output_ptr,
+ int dst_ptich,
+- unsigned int pixels_per_line,
+- unsigned int output_height,
+- unsigned int output_width
++ unsigned int output_height,
++ const short *vp8_filter
+ );
+ extern prototype_subpixel_predict(vp8_bilinear_predict8x8_mmx);
+
+@@ -246,23 +259,26 @@ void vp8_sixtap_predict16x16_sse2
+
+ if (xoffset)
+ {
+- HFilter = vp8_six_tap_mmx[xoffset];
+- vp8_filter_block1d16_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 1, 21, 32, HFilter);
++ if (yoffset)
++ {
++ HFilter = vp8_six_tap_mmx[xoffset];
++ vp8_filter_block1d16_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 1, 21, 32, HFilter);
++ VFilter = vp8_six_tap_mmx[yoffset];
++ vp8_filter_block1d16_v6_sse2(FData2 + 32, dst_ptr, dst_pitch, 32, 16 , 16, dst_pitch, VFilter);
++ }
++ else
++ {
++ // First-pass only
++ HFilter = vp8_six_tap_mmx[xoffset];
++ vp8_filter_block1d16_h6_only_sse2(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 16, HFilter);
++ }
+ }
+ else
+ {
+- vp8_unpack_block1d16_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 21, 32);
+- }
+-
+- if (yoffset)
+- {
++ // Second-pass only
+ VFilter = vp8_six_tap_mmx[yoffset];
+- vp8_filter_block1d8_v6_sse2(FData2 + 32, dst_ptr, dst_pitch, 32, 16 , 16, 16, VFilter);
+- vp8_filter_block1d8_v6_sse2(FData2 + 40, dst_ptr + 8, dst_pitch, 32, 16 , 16, 16, VFilter);
+- }
+- else
+- {
+- vp8_pack_block1d16_v6_sse2(FData2 + 32, dst_ptr, dst_pitch, 32, 16, 16);
++ vp8_unpack_block1d16_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 21, 32);
++ vp8_filter_block1d16_v6_sse2(FData2 + 32, dst_ptr, dst_pitch, 32, 16 , 16, dst_pitch, VFilter);
+ }
+ }
+
+@@ -282,25 +298,26 @@ void vp8_sixtap_predict8x8_sse2
+
+ if (xoffset)
+ {
+- HFilter = vp8_six_tap_mmx[xoffset];
+- vp8_filter_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 1, 13, 16, HFilter);
++ if (yoffset)
++ {
++ HFilter = vp8_six_tap_mmx[xoffset];
++ vp8_filter_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 1, 13, 16, HFilter);
++ VFilter = vp8_six_tap_mmx[yoffset];
++ vp8_filter_block1d8_v6_sse2(FData2 + 16, dst_ptr, dst_pitch, 16, 8 , 8, dst_pitch, VFilter);
++ }
++ else
++ {
++ // First-pass only
++ HFilter = vp8_six_tap_mmx[xoffset];
++ vp8_filter_block1d8_h6_only_sse2(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 8, HFilter);
++ }
+ }
+ else
+ {
+- vp8_unpack_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 13, 16);
+- }
+-
+- if (yoffset)
+- {
++ // Second-pass only
+ VFilter = vp8_six_tap_mmx[yoffset];
+- vp8_filter_block1d8_v6_sse2(FData2 + 16, dst_ptr, dst_pitch, 16, 8 , 8, dst_pitch, VFilter);
+- }
+- else
+- {
+- vp8_pack_block1d8_v6_sse2(FData2 + 16, dst_ptr, dst_pitch, 16, 8, dst_pitch);
++ vp8_filter_block1d8_v6_only_sse2(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, dst_ptr, dst_pitch, 8, VFilter);
+ }
+-
+-
+ }
+
+
+@@ -319,24 +336,26 @@ void vp8_sixtap_predict8x4_sse2
+
+ if (xoffset)
+ {
+- HFilter = vp8_six_tap_mmx[xoffset];
+- vp8_filter_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 1, 9, 16, HFilter);
++ if (yoffset)
++ {
++ HFilter = vp8_six_tap_mmx[xoffset];
++ vp8_filter_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 1, 9, 16, HFilter);
++ VFilter = vp8_six_tap_mmx[yoffset];
++ vp8_filter_block1d8_v6_sse2(FData2 + 16, dst_ptr, dst_pitch, 16, 8 , 4, dst_pitch, VFilter);
++ }
++ else
++ {
++ // First-pass only
++ HFilter = vp8_six_tap_mmx[xoffset];
++ vp8_filter_block1d8_h6_only_sse2(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 4, HFilter);
++ }
+ }
+ else
+ {
+- vp8_unpack_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 9, 16);
+- }
+-
+- if (yoffset)
+- {
++ // Second-pass only
+ VFilter = vp8_six_tap_mmx[yoffset];
+- vp8_filter_block1d8_v6_sse2(FData2 + 16, dst_ptr, dst_pitch, 16, 8 , 4, dst_pitch, VFilter);
++ vp8_filter_block1d8_v6_only_sse2(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, dst_ptr, dst_pitch, 4, VFilter);
+ }
+- else
+- {
+- vp8_pack_block1d8_v6_sse2(FData2 + 16, dst_ptr, dst_pitch, 16, 4, dst_pitch);
+- }
+-
+-
+ }
++
+ #endif
+diff --git a/vp8/common/x86/x86_systemdependent.c b/vp8/common/x86/x86_systemdependent.c
+index 5312e06..09ff3c5 100644
+--- a/vp8/common/x86/x86_systemdependent.c
++++ b/vp8/common/x86/x86_systemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/arm/armv5/dequantize_v5.asm b/vp8/decoder/arm/armv5/dequantize_v5.asm
+index eb3f030..80b2e0c 100644
+--- a/vp8/decoder/arm/armv5/dequantize_v5.asm
++++ b/vp8/decoder/arm/armv5/dequantize_v5.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/armv6/dboolhuff_v6.asm b/vp8/decoder/arm/armv6/dboolhuff_v6.asm
+index 143e33e..eca8eeb 100644
+--- a/vp8/decoder/arm/armv6/dboolhuff_v6.asm
++++ b/vp8/decoder/arm/armv6/dboolhuff_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/armv6/dequantdcidct_v6.asm b/vp8/decoder/arm/armv6/dequantdcidct_v6.asm
+index 3daa9b3..c5b0b7b 100644
+--- a/vp8/decoder/arm/armv6/dequantdcidct_v6.asm
++++ b/vp8/decoder/arm/armv6/dequantdcidct_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/armv6/dequantidct_v6.asm b/vp8/decoder/arm/armv6/dequantidct_v6.asm
+index 61bb48d..0d1c6b4 100644
+--- a/vp8/decoder/arm/armv6/dequantidct_v6.asm
++++ b/vp8/decoder/arm/armv6/dequantidct_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/armv6/dequantize_v6.asm b/vp8/decoder/arm/armv6/dequantize_v6.asm
+index 95e3859..c35e7c6 100644
+--- a/vp8/decoder/arm/armv6/dequantize_v6.asm
++++ b/vp8/decoder/arm/armv6/dequantize_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/dequantize_arm.c b/vp8/decoder/arm/dequantize_arm.c
+index 54006a9..913267d 100644
+--- a/vp8/decoder/arm/dequantize_arm.c
++++ b/vp8/decoder/arm/dequantize_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/arm/dequantize_arm.h b/vp8/decoder/arm/dequantize_arm.h
+index c8a61a4..ae7cf8e 100644
+--- a/vp8/decoder/arm/dequantize_arm.h
++++ b/vp8/decoder/arm/dequantize_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/arm/detokenizearm_sjl.c b/vp8/decoder/arm/detokenizearm_sjl.c
+index c714452..a126a05 100644
+--- a/vp8/decoder/arm/detokenizearm_sjl.c
++++ b/vp8/decoder/arm/detokenizearm_sjl.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/arm/detokenizearm_v6.asm b/vp8/decoder/arm/detokenizearm_v6.asm
+index 4d87ee5..439c9ab 100644
+--- a/vp8/decoder/arm/detokenizearm_v6.asm
++++ b/vp8/decoder/arm/detokenizearm_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/dsystemdependent.c b/vp8/decoder/arm/dsystemdependent.c
+index 455c83a..f146d60 100644
+--- a/vp8/decoder/arm/dsystemdependent.c
++++ b/vp8/decoder/arm/dsystemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/arm/neon/dboolhuff_neon.asm b/vp8/decoder/arm/neon/dboolhuff_neon.asm
+index 7ec62a3..01315a4 100644
+--- a/vp8/decoder/arm/neon/dboolhuff_neon.asm
++++ b/vp8/decoder/arm/neon/dboolhuff_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/neon/dequantdcidct_neon.asm b/vp8/decoder/arm/neon/dequantdcidct_neon.asm
+index 3392f2c..482f02d 100644
+--- a/vp8/decoder/arm/neon/dequantdcidct_neon.asm
++++ b/vp8/decoder/arm/neon/dequantdcidct_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/neon/dequantidct_neon.asm b/vp8/decoder/arm/neon/dequantidct_neon.asm
+index bba4d5d..3d00dbf 100644
+--- a/vp8/decoder/arm/neon/dequantidct_neon.asm
++++ b/vp8/decoder/arm/neon/dequantidct_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/arm/neon/dequantizeb_neon.asm b/vp8/decoder/arm/neon/dequantizeb_neon.asm
+index 1bde946..14698f8 100644
+--- a/vp8/decoder/arm/neon/dequantizeb_neon.asm
++++ b/vp8/decoder/arm/neon/dequantizeb_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/dboolhuff.c b/vp8/decoder/dboolhuff.c
+index 442054e..7027c0f 100644
+--- a/vp8/decoder/dboolhuff.c
++++ b/vp8/decoder/dboolhuff.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/dboolhuff.h b/vp8/decoder/dboolhuff.h
+index f5c9822..c6d69e7 100644
+--- a/vp8/decoder/dboolhuff.h
++++ b/vp8/decoder/dboolhuff.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -12,7 +13,7 @@
+ #define DBOOLHUFF_H
+ #include "vpx_ports/config.h"
+ #include "vpx_ports/mem.h"
+-#include "vpx_ports/vpx_integer.h"
++#include "vpx/vpx_integer.h"
+
+ /* Size of the bool decoder backing storage
+ *
+diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c
+index 6035f3e..7e00423 100644
+--- a/vp8/decoder/decodemv.c
++++ b/vp8/decoder/decodemv.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -170,6 +171,7 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
+ VP8_COMMON *const pc = &pbi->common;
+ MACROBLOCKD *xd = &pbi->mb;
+
++ mbmi->need_to_clamp_mvs = 0;
+ vp8dx_bool_decoder_fill(bc);
+
+ // Distance of Mb to the various image edges.
+@@ -268,6 +270,17 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
+ break;
+ }
+
++ if (mv->col < xd->mb_to_left_edge
++ - LEFT_TOP_MARGIN
++ || mv->col > xd->mb_to_right_edge
++ + RIGHT_BOTTOM_MARGIN
++ || mv->row < xd->mb_to_top_edge
++ - LEFT_TOP_MARGIN
++ || mv->row > xd->mb_to_bottom_edge
++ + RIGHT_BOTTOM_MARGIN
++ )
++ mbmi->need_to_clamp_mvs = 1;
++
+ /* Fill (uniform) modes, mvs of jth subset.
+ Must do it here because ensuing subsets can
+ refer back to us via "left" or "above". */
+@@ -324,27 +337,18 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
+ read_mv(bc, mv, (const MV_CONTEXT *) mvc);
+ mv->row += best_mv.row;
+ mv->col += best_mv.col;
+- /* Encoder should not produce invalid motion vectors, but since
+- * arbitrary length MVs can be parsed from the bitstream, we
+- * need to clamp them here in case we're reading bad data to
+- * avoid a crash.
+- */
+-#if CONFIG_DEBUG
+- assert(mv->col >= (xd->mb_to_left_edge - LEFT_TOP_MARGIN));
+- assert(mv->col <= (xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN));
+- assert(mv->row >= (xd->mb_to_top_edge - LEFT_TOP_MARGIN));
+- assert(mv->row <= (xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN));
+-#endif
+
+- if (mv->col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
+- mv->col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
+- else if (mv->col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
+- mv->col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
+-
+- if (mv->row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
+- mv->row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
+- else if (mv->row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
+- mv->row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
++ /* Don't need to check this on NEARMV and NEARESTMV modes
++ * since those modes clamp the MV. The NEWMV mode does not,
++ * so signal to the prediction stage whether special
++ * handling may be required.
++ */
++ if (mv->col < xd->mb_to_left_edge - LEFT_TOP_MARGIN
++ || mv->col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN
++ || mv->row < xd->mb_to_top_edge - LEFT_TOP_MARGIN
++ || mv->row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN
++ )
++ mbmi->need_to_clamp_mvs = 1;
+
+ propagate_mv: /* same MV throughout */
+ {
+@@ -380,7 +384,6 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
+ assert(0);
+ #endif
+ }
+-
+ }
+ else
+ {
+diff --git a/vp8/decoder/decodemv.h b/vp8/decoder/decodemv.h
+index 4030071..8b7fb68 100644
+--- a/vp8/decoder/decodemv.h
++++ b/vp8/decoder/decodemv.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/decoderthreading.h b/vp8/decoder/decoderthreading.h
+index ebc5c27..6c0363b 100644
+--- a/vp8/decoder/decoderthreading.h
++++ b/vp8/decoder/decoderthreading.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c
+index 4edf4f6..0f1b879 100644
+--- a/vp8/decoder/decodframe.c
++++ b/vp8/decoder/decodframe.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -125,6 +126,62 @@ static void skip_recon_mb(VP8D_COMP *pbi, MACROBLOCKD *xd)
+ }
+ }
+
++
++static void clamp_mv_to_umv_border(MV *mv, const MACROBLOCKD *xd)
++{
++ /* If the MV points so far into the UMV border that no visible pixels
++ * are used for reconstruction, the subpel part of the MV can be
++ * discarded and the MV limited to 16 pixels with equivalent results.
++ *
++ * This limit kicks in at 19 pixels for the top and left edges, for
++ * the 16 pixels plus 3 taps right of the central pixel when subpel
++ * filtering. The bottom and right edges use 16 pixels plus 2 pixels
++ * left of the central pixel when filtering.
++ */
++ if (mv->col < (xd->mb_to_left_edge - (19 << 3)))
++ mv->col = xd->mb_to_left_edge - (16 << 3);
++ else if (mv->col > xd->mb_to_right_edge + (18 << 3))
++ mv->col = xd->mb_to_right_edge + (16 << 3);
++
++ if (mv->row < (xd->mb_to_top_edge - (19 << 3)))
++ mv->row = xd->mb_to_top_edge - (16 << 3);
++ else if (mv->row > xd->mb_to_bottom_edge + (18 << 3))
++ mv->row = xd->mb_to_bottom_edge + (16 << 3);
++}
++
++/* A version of the above function for chroma block MVs.*/
++static void clamp_uvmv_to_umv_border(MV *mv, const MACROBLOCKD *xd)
++{
++ if (2*mv->col < (xd->mb_to_left_edge - (19 << 3)))
++ mv->col = (xd->mb_to_left_edge - (16 << 3)) >> 1;
++ else if (2*mv->col > xd->mb_to_right_edge + (18 << 3))
++ mv->col = (xd->mb_to_right_edge + (16 << 3)) >> 1;
++
++ if (2*mv->row < (xd->mb_to_top_edge - (19 << 3)))
++ mv->row = (xd->mb_to_top_edge - (16 << 3)) >> 1;
++ else if (2*mv->row > xd->mb_to_bottom_edge + (18 << 3))
++ mv->row = (xd->mb_to_bottom_edge + (16 << 3)) >> 1;
++}
++
++static void clamp_mvs(MACROBLOCKD *xd)
++{
++ if (xd->mbmi.mode == SPLITMV)
++ {
++ int i;
++
++ for (i=0; i<16; i++)
++ clamp_mv_to_umv_border(&xd->block[i].bmi.mv.as_mv, xd);
++ for (i=16; i<24; i++)
++ clamp_uvmv_to_umv_border(&xd->block[i].bmi.mv.as_mv, xd);
++ }
++ else
++ {
++ clamp_mv_to_umv_border(&xd->mbmi.mv.as_mv, xd);
++ clamp_uvmv_to_umv_border(&xd->block[16].bmi.mv.as_mv, xd);
++ }
++
++}
++
+ static void reconstruct_mb(VP8D_COMP *pbi, MACROBLOCKD *xd)
+ {
+ if (xd->frame_type == KEY_FRAME || xd->mbmi.ref_frame == INTRA_FRAME)
+@@ -232,6 +289,8 @@ static void de_quantand_idct(VP8D_COMP *pbi, MACROBLOCKD *xd)
+ void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd)
+ {
+ int eobtotal = 0;
++ MV orig_mvs[24];
++ int i, do_clamp = xd->mbmi.need_to_clamp_mvs;
+
+ if (xd->mbmi.mb_skip_coeff)
+ {
+@@ -242,20 +301,49 @@ void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd)
+ eobtotal = vp8_decode_mb_tokens(pbi, xd);
+ }
+
++ /* Perform temporary clamping of the MV to be used for prediction */
++ if (do_clamp)
++ {
++ if (xd->mbmi.mode == SPLITMV)
++ for (i=0; i<24; i++)
++ orig_mvs[i] = xd->block[i].bmi.mv.as_mv;
++ else
++ {
++ orig_mvs[0] = xd->mbmi.mv.as_mv;
++ orig_mvs[1] = xd->block[16].bmi.mv.as_mv;
++ }
++ clamp_mvs(xd);
++ }
++
+ xd->mode_info_context->mbmi.dc_diff = 1;
+
+ if (xd->mbmi.mode != B_PRED && xd->mbmi.mode != SPLITMV && eobtotal == 0)
+ {
+ xd->mode_info_context->mbmi.dc_diff = 0;
+ skip_recon_mb(pbi, xd);
+- return;
+ }
++ else
++ {
++ if (xd->segmentation_enabled)
++ mb_init_dequantizer(pbi, xd);
+
+- if (xd->segmentation_enabled)
+- mb_init_dequantizer(pbi, xd);
++ de_quantand_idct(pbi, xd);
++ reconstruct_mb(pbi, xd);
++ }
+
+- de_quantand_idct(pbi, xd);
+- reconstruct_mb(pbi, xd);
++
++ /* Restore the original MV so as not to affect the entropy context. */
++ if (do_clamp)
++ {
++ if (xd->mbmi.mode == SPLITMV)
++ for (i=0; i<24; i++)
++ xd->block[i].bmi.mv.as_mv = orig_mvs[i];
++ else
++ {
++ xd->mbmi.mv.as_mv = orig_mvs[0];
++ xd->block[16].bmi.mv.as_mv = orig_mvs[1];
++ }
++ }
+ }
+
+ static int get_delta_q(vp8_reader *bc, int prev, int *q_update)
+@@ -313,7 +401,9 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
+ for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
+ {
+ // Take a copy of the mode and Mv information for this macroblock into the xd->mbmi
+- vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi, 32); //sizeof(MB_MODE_INFO) );
++ // the partition_bmi array is unused in the decoder, so don't copy it.
++ vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi,
++ sizeof(MB_MODE_INFO) - sizeof(xd->mbmi.partition_bmi));
+
+ if (xd->mbmi.mode == SPLITMV || xd->mbmi.mode == B_PRED)
+ {
+@@ -360,7 +450,7 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
+ vp8_build_uvmvs(xd, pc->full_pixel);
+
+ /*
+- if(pbi->common.current_video_frame==0 &&mb_col==1 && mb_row==0)
++ if(pc->current_video_frame==0 &&mb_col==1 && mb_row==0)
+ pbi->debugoutput =1;
+ else
+ pbi->debugoutput =0;
+@@ -609,7 +699,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
+ "Invalid frame height");
+ }
+
+- if (vp8_alloc_frame_buffers(&pbi->common, pc->Width, pc->Height))
++ if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height))
+ vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate frame buffers");
+ }
+@@ -846,17 +936,17 @@ int vp8_decode_frame(VP8D_COMP *pbi)
+ vpx_memcpy(&xd->block[0].bmi, &xd->mode_info_context->bmi[0], sizeof(B_MODE_INFO));
+
+
+- if (pbi->b_multithreaded_lf && pbi->common.filter_level != 0)
++ if (pbi->b_multithreaded_lf && pc->filter_level != 0)
+ vp8_start_lfthread(pbi);
+
+- if (pbi->b_multithreaded_rd && pbi->common.multi_token_partition != ONE_PARTITION)
++ if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
+ {
+ vp8_mtdecode_mb_rows(pbi, xd);
+ }
+ else
+ {
+ int ibc = 0;
+- int num_part = 1 << pbi->common.multi_token_partition;
++ int num_part = 1 << pc->multi_token_partition;
+
+ // Decode the individual macro block
+ for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
+@@ -885,8 +975,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
+ // vpx_log("Decoder: Frame Decoded, Size Roughly:%d bytes \n",bc->pos+pbi->bc2.pos);
+
+ // If this was a kf or Gf note the Q used
+- if ((pc->frame_type == KEY_FRAME) || (pc->refresh_golden_frame) || pbi->common.refresh_alt_ref_frame)
++ if ((pc->frame_type == KEY_FRAME) ||
++ pc->refresh_golden_frame || pc->refresh_alt_ref_frame)
++ {
+ pc->last_kf_gf_q = pc->base_qindex;
++ }
+
+ if (pc->refresh_entropy_probs == 0)
+ {
+diff --git a/vp8/decoder/demode.c b/vp8/decoder/demode.c
+index fd05e6d..881b49e 100644
+--- a/vp8/decoder/demode.c
++++ b/vp8/decoder/demode.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/demode.h b/vp8/decoder/demode.h
+index 51bbc5e..8d2fbee 100644
+--- a/vp8/decoder/demode.h
++++ b/vp8/decoder/demode.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/dequantize.c b/vp8/decoder/dequantize.c
+index 14798d9..2c286ec 100644
+--- a/vp8/decoder/dequantize.c
++++ b/vp8/decoder/dequantize.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/dequantize.h b/vp8/decoder/dequantize.h
+index d16b02e..7fd7cbb 100644
+--- a/vp8/decoder/dequantize.h
++++ b/vp8/decoder/dequantize.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/detokenize.c b/vp8/decoder/detokenize.c
+index a42f18d..d6f5ca2 100644
+--- a/vp8/decoder/detokenize.c
++++ b/vp8/decoder/detokenize.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -65,25 +66,43 @@ void vp8_reset_mb_tokens_context(MACROBLOCKD *x)
+
+ ENTROPY_CONTEXT *a;
+ ENTROPY_CONTEXT *l;
+- int i;
+-
+- for (i = 0; i < 24; i++)
+- {
+-
+- a = A[ vp8_block2context[i] ] + vp8_block2above[i];
+- l = L[ vp8_block2context[i] ] + vp8_block2left[i];
+-
+- *a = *l = 0;
+- }
+
++ /* Clear entropy contexts for Y blocks */
++ a = A[Y1CONTEXT];
++ l = L[Y1CONTEXT];
++ *a = 0;
++ *(a+1) = 0;
++ *(a+2) = 0;
++ *(a+3) = 0;
++ *l = 0;
++ *(l+1) = 0;
++ *(l+2) = 0;
++ *(l+3) = 0;
++
++ /* Clear entropy contexts for U blocks */
++ a = A[UCONTEXT];
++ l = L[UCONTEXT];
++ *a = 0;
++ *(a+1) = 0;
++ *l = 0;
++ *(l+1) = 0;
++
++ /* Clear entropy contexts for V blocks */
++ a = A[VCONTEXT];
++ l = L[VCONTEXT];
++ *a = 0;
++ *(a+1) = 0;
++ *l = 0;
++ *(l+1) = 0;
++
++ /* Clear entropy contexts for Y2 blocks */
+ if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+ {
+- a = A[Y2CONTEXT] + vp8_block2above[24];
+- l = L[Y2CONTEXT] + vp8_block2left[24];
+- *a = *l = 0;
++ a = A[Y2CONTEXT];
++ l = L[Y2CONTEXT];
++ *a = 0;
++ *l = 0;
+ }
+-
+-
+ }
+ DECLARE_ALIGNED(16, extern const unsigned int, vp8dx_bitreader_norm[256]);
+ #define NORMALIZE \
+diff --git a/vp8/decoder/detokenize.h b/vp8/decoder/detokenize.h
+index 6a9a476..6cfb66b 100644
+--- a/vp8/decoder/detokenize.h
++++ b/vp8/decoder/detokenize.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/generic/dsystemdependent.c b/vp8/decoder/generic/dsystemdependent.c
+index 302b64b..ad64a38 100644
+--- a/vp8/decoder/generic/dsystemdependent.c
++++ b/vp8/decoder/generic/dsystemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c
+index 6875585..76387f5 100644
+--- a/vp8/decoder/onyxd_if.c
++++ b/vp8/decoder/onyxd_if.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/onyxd_if_sjl.c b/vp8/decoder/onyxd_if_sjl.c
+index 363ad5d..12d28a5 100644
+--- a/vp8/decoder/onyxd_if_sjl.c
++++ b/vp8/decoder/onyxd_if_sjl.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h
+index fa4fa48..2eea614 100644
+--- a/vp8/decoder/onyxd_int.h
++++ b/vp8/decoder/onyxd_int.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/threading.c b/vp8/decoder/threading.c
+index e35d175..87bba20 100644
+--- a/vp8/decoder/threading.c
++++ b/vp8/decoder/threading.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -153,7 +154,9 @@ THREAD_FUNCTION vp8_thread_decoding_proc(void *p_data)
+ }
+
+ // Take a copy of the mode and Mv information for this macroblock into the xd->mbmi
+- vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi, 32); //sizeof(MB_MODE_INFO) );
++ // the partition_bmi array is unused in the decoder, so don't copy it.
++ vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi,
++ sizeof(MB_MODE_INFO) - sizeof(xd->mbmi.partition_bmi));
+
+ if (xd->mbmi.mode == SPLITMV || xd->mbmi.mode == B_PRED)
+ {
+diff --git a/vp8/decoder/treereader.h b/vp8/decoder/treereader.h
+index eb10e24..f1893df 100644
+--- a/vp8/decoder/treereader.h
++++ b/vp8/decoder/treereader.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/x86/dequantize_mmx.asm b/vp8/decoder/x86/dequantize_mmx.asm
+index 02be487..1611e03 100644
+--- a/vp8/decoder/x86/dequantize_mmx.asm
++++ b/vp8/decoder/x86/dequantize_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/decoder/x86/dequantize_x86.h b/vp8/decoder/x86/dequantize_x86.h
+index 5def406..4c91633 100644
+--- a/vp8/decoder/x86/dequantize_x86.h
++++ b/vp8/decoder/x86/dequantize_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/x86/onyxdxv.c b/vp8/decoder/x86/onyxdxv.c
+index 75a676a..22d0548 100644
+--- a/vp8/decoder/x86/onyxdxv.c
++++ b/vp8/decoder/x86/onyxdxv.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/x86/x86_dsystemdependent.c b/vp8/decoder/x86/x86_dsystemdependent.c
+index 6d7cc36..2dfb469 100644
+--- a/vp8/decoder/x86/x86_dsystemdependent.c
++++ b/vp8/decoder/x86/x86_dsystemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/xprintf.c b/vp8/decoder/xprintf.c
+index cb2221c..7465010 100644
+--- a/vp8/decoder/xprintf.c
++++ b/vp8/decoder/xprintf.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/decoder/xprintf.h b/vp8/decoder/xprintf.h
+index 2f175e9..7656075 100644
+--- a/vp8/decoder/xprintf.h
++++ b/vp8/decoder/xprintf.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/armv6/walsh_v6.asm b/vp8/encoder/arm/armv6/walsh_v6.asm
+index 608c9ae..461e492 100644
+--- a/vp8/encoder/arm/armv6/walsh_v6.asm
++++ b/vp8/encoder/arm/armv6/walsh_v6.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+ EXPORT |vp8_short_walsh4x4_armv6|
+diff --git a/vp8/encoder/arm/boolhuff_arm.c b/vp8/encoder/arm/boolhuff_arm.c
+index e70b3ad..8c0faff 100644
+--- a/vp8/encoder/arm/boolhuff_arm.c
++++ b/vp8/encoder/arm/boolhuff_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/csystemdependent.c b/vp8/encoder/arm/csystemdependent.c
+index 0039796..7fba995 100644
+--- a/vp8/encoder/arm/csystemdependent.c
++++ b/vp8/encoder/arm/csystemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/dct_arm.h b/vp8/encoder/arm/dct_arm.h
+index a671862..bb60c9d 100644
+--- a/vp8/encoder/arm/dct_arm.h
++++ b/vp8/encoder/arm/dct_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/encodemb_arm.c b/vp8/encoder/arm/encodemb_arm.c
+index 3f1d053..7d58f94 100644
+--- a/vp8/encoder/arm/encodemb_arm.c
++++ b/vp8/encoder/arm/encodemb_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/encodemb_arm.h b/vp8/encoder/arm/encodemb_arm.h
+index 28f9e5c..525135a 100644
+--- a/vp8/encoder/arm/encodemb_arm.h
++++ b/vp8/encoder/arm/encodemb_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/mcomp_arm.c b/vp8/encoder/arm/mcomp_arm.c
+index 07f2186..9418a60 100644
+--- a/vp8/encoder/arm/mcomp_arm.c
++++ b/vp8/encoder/arm/mcomp_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/neon/boolhuff_armv7.asm b/vp8/encoder/arm/neon/boolhuff_armv7.asm
+index 9a5f366..674eea9 100644
+--- a/vp8/encoder/arm/neon/boolhuff_armv7.asm
++++ b/vp8/encoder/arm/neon/boolhuff_armv7.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/fastfdct4x4_neon.asm b/vp8/encoder/arm/neon/fastfdct4x4_neon.asm
+index d5dec44..44e6dfc 100644
+--- a/vp8/encoder/arm/neon/fastfdct4x4_neon.asm
++++ b/vp8/encoder/arm/neon/fastfdct4x4_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/fastfdct8x4_neon.asm b/vp8/encoder/arm/neon/fastfdct8x4_neon.asm
+index de1c254..6a286f6 100644
+--- a/vp8/encoder/arm/neon/fastfdct8x4_neon.asm
++++ b/vp8/encoder/arm/neon/fastfdct8x4_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/fastquantizeb_neon.asm b/vp8/encoder/arm/neon/fastquantizeb_neon.asm
+index 1107037..e3a94a6 100644
+--- a/vp8/encoder/arm/neon/fastquantizeb_neon.asm
++++ b/vp8/encoder/arm/neon/fastquantizeb_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/sad16_neon.asm b/vp8/encoder/arm/neon/sad16_neon.asm
+index 6169f10..7e2ab13 100644
+--- a/vp8/encoder/arm/neon/sad16_neon.asm
++++ b/vp8/encoder/arm/neon/sad16_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/sad8_neon.asm b/vp8/encoder/arm/neon/sad8_neon.asm
+index 28604dd..fc8c4e1 100644
+--- a/vp8/encoder/arm/neon/sad8_neon.asm
++++ b/vp8/encoder/arm/neon/sad8_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/shortfdct_neon.asm b/vp8/encoder/arm/neon/shortfdct_neon.asm
+index 26bc0d0..4399c97 100644
+--- a/vp8/encoder/arm/neon/shortfdct_neon.asm
++++ b/vp8/encoder/arm/neon/shortfdct_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/subtract_neon.asm b/vp8/encoder/arm/neon/subtract_neon.asm
+index 8781ca0..d4803ff 100644
+--- a/vp8/encoder/arm/neon/subtract_neon.asm
++++ b/vp8/encoder/arm/neon/subtract_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/variance_neon.asm b/vp8/encoder/arm/neon/variance_neon.asm
+index 64b83ca..b901693 100644
+--- a/vp8/encoder/arm/neon/variance_neon.asm
++++ b/vp8/encoder/arm/neon/variance_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_memcpy_neon.asm b/vp8/encoder/arm/neon/vp8_memcpy_neon.asm
+index f26b4d7..0a372c3 100644
+--- a/vp8/encoder/arm/neon/vp8_memcpy_neon.asm
++++ b/vp8/encoder/arm/neon/vp8_memcpy_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm b/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm
+index f535967..087ea17 100644
+--- a/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm
++++ b/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_packtokens_armv7.asm b/vp8/encoder/arm/neon/vp8_packtokens_armv7.asm
+index 9c52c52..bfa97d7 100644
+--- a/vp8/encoder/arm/neon/vp8_packtokens_armv7.asm
++++ b/vp8/encoder/arm/neon/vp8_packtokens_armv7.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm b/vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm
+index 92b0989..334c88f 100644
+--- a/vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm
++++ b/vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm b/vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm
+index 6d5f882..267e216 100644
+--- a/vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm
++++ b/vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm b/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm
+index 5269c0a..ebd5dc1 100644
+--- a/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm
++++ b/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm b/vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm
+index aec716e..185277f 100644
+--- a/vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm
++++ b/vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm b/vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm
+index 3d02d7c..611b1e4 100644
+--- a/vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm
++++ b/vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm b/vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm
+index bd56761..614d48f 100644
+--- a/vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm
++++ b/vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/arm/picklpf_arm.c b/vp8/encoder/arm/picklpf_arm.c
+index 0586e55..fb0b3bd 100644
+--- a/vp8/encoder/arm/picklpf_arm.c
++++ b/vp8/encoder/arm/picklpf_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/quantize_arm.c b/vp8/encoder/arm/quantize_arm.c
+index 46906d3..e8bd44b 100644
+--- a/vp8/encoder/arm/quantize_arm.c
++++ b/vp8/encoder/arm/quantize_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/quantize_arm.h b/vp8/encoder/arm/quantize_arm.h
+index e93f0fe..14bc923 100644
+--- a/vp8/encoder/arm/quantize_arm.h
++++ b/vp8/encoder/arm/quantize_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/variance_arm.h b/vp8/encoder/arm/variance_arm.h
+index d9fc9b3..1c16020 100644
+--- a/vp8/encoder/arm/variance_arm.h
++++ b/vp8/encoder/arm/variance_arm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c b/vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c
+index 8cdf079..28aac70 100644
+--- a/vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c
++++ b/vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c
+index 31ad56a..ce9d2fd 100644
+--- a/vp8/encoder/bitstream.c
++++ b/vp8/encoder/bitstream.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -1385,8 +1386,6 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
+ // every keyframe send startcode, width, height, scale factor, clamp and color type
+ if (oh.type == KEY_FRAME)
+ {
+- int w, h, hs, vs;
+-
+ // Start / synch code
+ cx_data[0] = 0x9D;
+ cx_data[1] = 0x01;
+diff --git a/vp8/encoder/bitstream.h b/vp8/encoder/bitstream.h
+index ee69f66..de4b94d 100644
+--- a/vp8/encoder/bitstream.h
++++ b/vp8/encoder/bitstream.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/block.h b/vp8/encoder/block.h
+index cc4cbe0..2e866dd 100644
+--- a/vp8/encoder/block.h
++++ b/vp8/encoder/block.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -101,11 +102,9 @@ typedef struct
+ void (*vp8_short_fdct8x4)(short *input, short *output, int pitch);
+ void (*short_fdct4x4rd)(short *input, short *output, int pitch);
+ void (*short_fdct8x4rd)(short *input, short *output, int pitch);
+- void (*vp8_short_fdct4x4_ptr)(short *input, short *output, int pitch);
+ void (*short_walsh4x4)(short *input, short *output, int pitch);
+
+ void (*quantize_b)(BLOCK *b, BLOCKD *d);
+- void (*quantize_brd)(BLOCK *b, BLOCKD *d);
+
+
+
+diff --git a/vp8/encoder/boolhuff.c b/vp8/encoder/boolhuff.c
+index c101384..2e95c75 100644
+--- a/vp8/encoder/boolhuff.c
++++ b/vp8/encoder/boolhuff.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/boolhuff.h b/vp8/encoder/boolhuff.h
+index 0d929f0..95635e3 100644
+--- a/vp8/encoder/boolhuff.h
++++ b/vp8/encoder/boolhuff.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/dct.c b/vp8/encoder/dct.c
+index 5207e39..4f5f9f0 100644
+--- a/vp8/encoder/dct.c
++++ b/vp8/encoder/dct.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/dct.h b/vp8/encoder/dct.h
+index fb307cf..2aaf731 100644
+--- a/vp8/encoder/dct.h
++++ b/vp8/encoder/dct.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
+index a4e3772..46b697e 100644
+--- a/vp8/encoder/encodeframe.c
++++ b/vp8/encoder/encodeframe.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/encodeintra.c b/vp8/encoder/encodeintra.c
+index 403d020..d632bd8 100644
+--- a/vp8/encoder/encodeintra.c
++++ b/vp8/encoder/encodeintra.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -67,7 +68,7 @@ void vp8_encode_intra4x4block_rd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x, BL
+
+ x->short_fdct4x4rd(be->src_diff, be->coeff, 32);
+
+- x->quantize_brd(be, b);
++ x->quantize_b(be, b);
+
+ x->e_mbd.mbmi.mb_skip_coeff &= (!b->eob);
+
+@@ -159,8 +160,7 @@ void vp8_encode_intra16x16mbyrd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+
+ x->e_mbd.mbmi.mb_skip_coeff = 1;
+
+- vp8_quantize_mbyrd(x);
+-
++ vp8_quantize_mby(x);
+
+ vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+@@ -226,9 +226,7 @@ void vp8_encode_intra16x16mbuvrd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+
+ vp8_transform_mbuvrd(x);
+
+- vp8_quantize_mbuvrd(x);
+-
+-
++ vp8_quantize_mbuv(x);
+
+ vp8_inverse_transform_mbuv(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+diff --git a/vp8/encoder/encodeintra.h b/vp8/encoder/encodeintra.h
+index 4a43ab2..49b3257 100644
+--- a/vp8/encoder/encodeintra.h
++++ b/vp8/encoder/encodeintra.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/encodemb.c b/vp8/encoder/encodemb.c
+index d825133..a66b90c 100644
+--- a/vp8/encoder/encodemb.c
++++ b/vp8/encoder/encodemb.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -493,140 +494,6 @@ void vp8_optimize_b(MACROBLOCK *x, int i, int type, ENTROPY_CONTEXT *a, ENTROPY_
+ return;
+ }
+
+-void vp8_optimize_bplus(MACROBLOCK *x, int i, int type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, const VP8_ENCODER_RTCD *rtcd)
+-{
+- BLOCK *b = &x->block[i];
+- BLOCKD *bd = &x->e_mbd.block[i];
+- short *dequant_ptr = &bd->dequant[0][0];
+- int nzpos[16] = {0};
+- short saved_qcoefs[16];
+- short saved_dqcoefs[16];
+- int baserate, baseerror, baserd;
+- int rate, error, thisrd;
+- int k;
+- int nzcoefcount = 0;
+- int nc, bestnc = 0;
+- int besteob;
+-
+- // count potential coefficient to be optimized
+- for (k = !type; k < 16; k++)
+- {
+- int qcoef = abs(bd->qcoeff[k]);
+- int coef = abs(b->coeff[k]);
+- int dq = dequant_ptr[k];
+-
+- if (qcoef && (qcoef * dq < coef) && (coef < (qcoef * dq + dq)))
+- {
+- nzpos[nzcoefcount] = k;
+- nzcoefcount++;
+- }
+- }
+-
+- // if nothing here, do nothing for this block.
+- if (!nzcoefcount)
+- {
+- //do not update context, we need do the other half.
+- //*a = *l = (bd->eob != !type);
+- return;
+- }
+-
+- // save a copy of quantized coefficients
+- vpx_memcpy(saved_qcoefs, bd->qcoeff, 32);
+- vpx_memcpy(saved_dqcoefs, bd->dqcoeff, 32);
+-
+- besteob = bd->eob;
+- baserate = cost_coeffs(x, bd, type, a, l);
+- baseerror = ENCODEMB_INVOKE(&rtcd->encodemb, berr)(b->coeff, bd->dqcoeff) >> 2;
+- baserd = RDFUNC(x->rdmult, x->rddiv, baserate, baseerror, 100);
+-
+- for (nc = 1; nc < (1 << nzcoefcount); nc++)
+- {
+- //reset coefficients
+- vpx_memcpy(bd->qcoeff, saved_qcoefs, 32);
+- vpx_memcpy(bd->dqcoeff, saved_dqcoefs, 32);
+-
+- for (k = 0; k < nzcoefcount; k++)
+- {
+- int pos = nzpos[k];
+-
+- if ((nc & (1 << k)))
+- {
+- int cur_qcoef = bd->qcoeff[pos];
+-
+- if (cur_qcoef < 0)
+- {
+- bd->qcoeff[pos]--;
+- bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+- }
+- else
+- {
+- bd->qcoeff[pos]++;
+- bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+- }
+- }
+- }
+-
+- {
+- int eob = -1;
+- int rc;
+- int m;
+-
+- for (m = 0; m < 16; m++)
+- {
+- rc = vp8_default_zig_zag1d[m];
+-
+- if (bd->qcoeff[rc])
+- eob = m;
+- }
+-
+- bd->eob = eob + 1;
+- }
+-
+- rate = cost_coeffs(x, bd, type, a, l);
+- error = ENCODEMB_INVOKE(&rtcd->encodemb, berr)(b->coeff, bd->dqcoeff) >> 2;
+- thisrd = RDFUNC(x->rdmult, x->rddiv, rate, error, 100);
+-
+- if (thisrd < baserd)
+- {
+- baserd = thisrd;
+- bestnc = nc;
+- besteob = bd->eob;
+- }
+- }
+-
+- //reset coefficients
+- vpx_memcpy(bd->qcoeff, saved_qcoefs, 32);
+- vpx_memcpy(bd->dqcoeff, saved_dqcoefs, 32);
+-
+- if (bestnc)
+- {
+- for (k = 0; k < nzcoefcount; k++)
+- {
+- int pos = nzpos[k];
+-
+- if (bestnc & (1 << k))
+- {
+- int cur_qcoef = bd->qcoeff[pos];
+-
+- if (cur_qcoef < 0)
+- {
+- bd->qcoeff[pos]++;
+- bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+- }
+- else
+- {
+- bd->qcoeff[pos]--;
+- bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+- }
+- }
+- }
+- }
+-
+- bd->eob = besteob;
+- //do not update context, we need do the other half.
+- //*a = *l = (bd->eob != !type);
+- return;
+-}
+
+ void vp8_optimize_y2b(MACROBLOCK *x, int i, int type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, const VP8_ENCODER_RTCD *rtcd)
+ {
+@@ -718,7 +585,6 @@ void vp8_optimize_y2b(MACROBLOCK *x, int i, int type, ENTROPY_CONTEXT *a, ENTROP
+
+ void vp8_optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+ {
+- int cost = 0;
+ int b;
+ TEMP_CONTEXT t, t2;
+ int type = 0;
+@@ -752,181 +618,6 @@ void vp8_optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+
+
+
+-void vp8_super_slow_yquant_optimization(MACROBLOCK *x, int type, const VP8_ENCODER_RTCD *rtcd)
+-{
+- BLOCK *b = &x->block[0];
+- BLOCKD *bd = &x->e_mbd.block[0];
+- short *dequant_ptr = &bd->dequant[0][0];
+- struct
+- {
+- int block;
+- int pos;
+- } nzpos[256];
+- short saved_qcoefs[256];
+- short saved_dqcoefs[256];
+- short *coef_ptr = x->coeff;
+- short *qcoef_ptr = x->e_mbd.qcoeff;
+- short *dqcoef_ptr = x->e_mbd.dqcoeff;
+-
+- int baserate, baseerror, baserd;
+- int rate, error, thisrd;
+- int i, k;
+- int nzcoefcount = 0;
+- int nc, bestnc = 0;
+- int besteob;
+-
+- //this code has assumption in macroblock coeff buffer layout
+- for (i = 0; i < 16; i++)
+- {
+- // count potential coefficient to be optimized
+- for (k = !type; k < 16; k++)
+- {
+- int qcoef = abs(qcoef_ptr[i*16 + k]);
+- int coef = abs(coef_ptr[i*16 + k]);
+- int dq = dequant_ptr[k];
+-
+- if (qcoef && (qcoef * dq > coef) && (qcoef * dq < coef + dq))
+- {
+- nzpos[nzcoefcount].block = i;
+- nzpos[nzcoefcount].pos = k;
+- nzcoefcount++;
+- }
+- }
+- }
+-
+- // if nothing here, do nothing for this macro_block.
+- if (!nzcoefcount || nzcoefcount > 15)
+- {
+- return;
+- }
+-
+- /******************************************************************************
+- looking from each coeffient's perspective, each identifed coefficent above could
+- have 2 values:roundeddown(x) and roundedup(x). Therefore the total number of
+- different states is less than 2**nzcoefcount.
+- ******************************************************************************/
+- // save the qunatized coefficents and dequantized coefficicents
+- vpx_memcpy(saved_qcoefs, x->e_mbd.qcoeff, 256);
+- vpx_memcpy(saved_dqcoefs, x->e_mbd.dqcoeff, 256);
+-
+- baserate = mbycost_coeffs(x);
+- baseerror = ENCODEMB_INVOKE(&rtcd->encodemb, mberr)(x, !type);
+- baserd = RDFUNC(x->rdmult, x->rddiv, baserate, baseerror, 100);
+-
+- for (nc = 1; nc < (1 << nzcoefcount); nc++)
+- {
+- //reset coefficients
+- vpx_memcpy(x->e_mbd.qcoeff, saved_qcoefs, 256);
+- vpx_memcpy(x->e_mbd.dqcoeff, saved_dqcoefs, 256);
+-
+- for (k = 0; k < nzcoefcount; k++)
+- {
+- int bk = nzpos[k].block;
+- int pos = nzpos[k].pos;
+- int mbkpos = bk * 16 + pos;
+-
+- if ((nc & (1 << k)))
+- {
+- int cur_qcoef = x->e_mbd.qcoeff[mbkpos];
+-
+- if (cur_qcoef < 0)
+- {
+- x->e_mbd.qcoeff[mbkpos]++;
+- x->e_mbd.dqcoeff[mbkpos] = x->e_mbd.qcoeff[mbkpos] * dequant_ptr[pos];
+- }
+- else
+- {
+- x->e_mbd.qcoeff[mbkpos]--;
+- x->e_mbd.dqcoeff[mbkpos] = x->e_mbd.qcoeff[mbkpos] * dequant_ptr[pos];
+- }
+- }
+- }
+-
+- for (i = 0; i < 16; i++)
+- {
+- BLOCKD *bd = &x->e_mbd.block[i];
+- {
+- int eob = -1;
+- int rc;
+- int l;
+-
+- for (l = 0; l < 16; l++)
+- {
+- rc = vp8_default_zig_zag1d[l];
+-
+- if (bd->qcoeff[rc])
+- eob = l;
+- }
+-
+- bd->eob = eob + 1;
+- }
+- }
+-
+- rate = mbycost_coeffs(x);
+- error = ENCODEMB_INVOKE(&rtcd->encodemb, mberr)(x, !type);;
+- thisrd = RDFUNC(x->rdmult, x->rddiv, rate, error, 100);
+-
+- if (thisrd < baserd)
+- {
+- baserd = thisrd;
+- bestnc = nc;
+- besteob = bd->eob;
+- }
+- }
+-
+- //reset coefficients
+- vpx_memcpy(x->e_mbd.qcoeff, saved_qcoefs, 256);
+- vpx_memcpy(x->e_mbd.dqcoeff, saved_dqcoefs, 256);
+-
+- if (bestnc)
+- {
+- for (k = 0; k < nzcoefcount; k++)
+- {
+- int bk = nzpos[k].block;
+- int pos = nzpos[k].pos;
+- int mbkpos = bk * 16 + pos;
+-
+- if ((nc & (1 << k)))
+- {
+- int cur_qcoef = x->e_mbd.qcoeff[mbkpos];
+-
+- if (cur_qcoef < 0)
+- {
+- x->e_mbd.qcoeff[mbkpos]++;
+- x->e_mbd.dqcoeff[mbkpos] = x->e_mbd.qcoeff[mbkpos] * dequant_ptr[pos];
+- }
+- else
+- {
+- x->e_mbd.qcoeff[mbkpos]--;
+- x->e_mbd.dqcoeff[mbkpos] = x->e_mbd.qcoeff[mbkpos] * dequant_ptr[pos];
+- }
+- }
+- }
+- }
+-
+- for (i = 0; i < 16; i++)
+- {
+- BLOCKD *bd = &x->e_mbd.block[i];
+- {
+- int eob = -1;
+- int rc;
+- int l;
+-
+- for (l = 0; l < 16; l++)
+- {
+- rc = vp8_default_zig_zag1d[l];
+-
+- if (bd->qcoeff[rc])
+- eob = l;
+- }
+-
+- bd->eob = eob + 1;
+- }
+- }
+-
+- return;
+-}
+-
+ static void vp8_find_mb_skip_coef(MACROBLOCK *x)
+ {
+ int i;
+@@ -955,46 +646,8 @@ static void vp8_find_mb_skip_coef(MACROBLOCK *x)
+ }
+
+
+-void vp8_optimize_mb_slow(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+-{
+- int cost = 0;
+- int b;
+- TEMP_CONTEXT t, t2;
+- int type = 0;
+-
+-
+- vp8_setup_temp_context(&t, x->e_mbd.above_context[Y1CONTEXT], x->e_mbd.left_context[Y1CONTEXT], 4);
+-
+- if (x->e_mbd.mbmi.mode == SPLITMV || x->e_mbd.mbmi.mode == B_PRED)
+- type = 3;
+-
+- vp8_super_slow_yquant_optimization(x, type, rtcd);
+- /*
+- for(b=0;b<16;b++)
+- {
+- vp8_optimize_b(x, b, type, t.a + vp8_block2above[b], t.l + vp8_block2left[b]);
+- }
+- */
+-
+- vp8_setup_temp_context(&t, x->e_mbd.above_context[UCONTEXT], x->e_mbd.left_context[UCONTEXT], 2);
+-
+- for (b = 16; b < 20; b++)
+- {
+- vp8_optimize_b(x, b, vp8_block2type[b], t.a + vp8_block2above[b], t.l + vp8_block2left[b], rtcd);
+- }
+-
+- vp8_setup_temp_context(&t2, x->e_mbd.above_context[VCONTEXT], x->e_mbd.left_context[VCONTEXT], 2);
+-
+- for (b = 20; b < 24; b++)
+- {
+- vp8_optimize_b(x, b, vp8_block2type[b], t2.a + vp8_block2above[b], t2.l + vp8_block2left[b], rtcd);
+- }
+-}
+-
+-
+ void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+ {
+- int cost = 0;
+ int b;
+ TEMP_CONTEXT t;
+ int type = 0;
+@@ -1019,10 +672,8 @@ void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+
+ void vp8_optimize_mbuv(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+ {
+- int cost = 0;
+ int b;
+ TEMP_CONTEXT t, t2;
+- int type = 0;
+
+ if (!x->e_mbd.above_context[UCONTEXT])
+ return;
+@@ -1124,6 +775,6 @@ void vp8_encode_inter16x16uvrd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+
+ vp8_transform_mbuvrd(x);
+
+- vp8_quantize_mbuvrd(x);
++ vp8_quantize_mbuv(x);
+
+ }
+diff --git a/vp8/encoder/encodemb.h b/vp8/encoder/encodemb.h
+index 91ca8f5..5285a38 100644
+--- a/vp8/encoder/encodemb.h
++++ b/vp8/encoder/encodemb.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/encodemv.c b/vp8/encoder/encodemv.c
+index f287edc..3b58a80 100644
+--- a/vp8/encoder/encodemv.c
++++ b/vp8/encoder/encodemv.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -282,8 +283,6 @@ static void write_component_probs(
+
+ //j=0
+ {
+- int j = 0;
+-
+ const int c = events [mv_max];
+
+ is_short_ct [0] += c; // Short vector
+diff --git a/vp8/encoder/encodemv.h b/vp8/encoder/encodemv.h
+index 1c1f450..bf6d7af 100644
+--- a/vp8/encoder/encodemv.h
++++ b/vp8/encoder/encodemv.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/ethreading.c b/vp8/encoder/ethreading.c
+index a0b50d2..11b1936 100644
+--- a/vp8/encoder/ethreading.c
++++ b/vp8/encoder/ethreading.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -259,10 +260,8 @@ static void setup_mbby_copy(MACROBLOCK *mbdst, MACROBLOCK *mbsrc)
+ z->short_fdct4x4rd = x->short_fdct4x4rd;
+ z->short_fdct8x4rd = x->short_fdct8x4rd;
+ z->short_fdct8x4rd = x->short_fdct8x4rd;
+- z->vp8_short_fdct4x4_ptr = x->vp8_short_fdct4x4_ptr;
+ z->short_walsh4x4 = x->short_walsh4x4;
+ z->quantize_b = x->quantize_b;
+- z->quantize_brd = x->quantize_brd;
+
+ /*
+ z->mvc = x->mvc;
+diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
+index c519080..ced2d7c 100644
+--- a/vp8/encoder/firstpass.c
++++ b/vp8/encoder/firstpass.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -175,7 +176,6 @@ static double calculate_modified_err(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+ double vp8_simple_weight(YV12_BUFFER_CONFIG *source)
+ {
+ int i, j;
+- int Total = 0;
+
+ unsigned char *src = source->y_buffer;
+ unsigned char value;
+@@ -779,7 +779,6 @@ void vp8_first_pass(VP8_COMP *cpi)
+ vp8_clear_system_state(); //__asm emms;
+ {
+ double weight = 0.0;
+- double weigth2 = 0.0;
+
+ FIRSTPASS_STATS fps;
+
+@@ -1193,7 +1192,6 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+ FIRSTPASS_STATS next_frame;
+ FIRSTPASS_STATS *start_pos;
+ int i;
+- int count = 0;
+ int image_size = cpi->common.last_frame.y_width * cpi->common.last_frame.y_height;
+ double boost_score = 0.0;
+ double old_boost_score = 0.0;
+@@ -1234,6 +1232,8 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+
+ start_pos = cpi->stats_in;
+
++ vpx_memset(&next_frame, 0, sizeof(next_frame)); // assure clean
++
+ // Preload the stats for the next frame.
+ mod_frame_err = calculate_modified_err(cpi, this_frame);
+
+@@ -1871,6 +1871,18 @@ void vp8_second_pass(VP8_COMP *cpi)
+ }
+ }
+
++ // Keep a globally available copy of this and the next frame's iiratio.
++ cpi->this_iiratio = this_frame_intra_error /
++ DOUBLE_DIVIDE_CHECK(this_frame_coded_error);
++ {
++ FIRSTPASS_STATS next_frame;
++ if ( lookup_next_frame_stats(cpi, &next_frame) != EOF )
++ {
++ cpi->next_iiratio = next_frame.intra_error /
++ DOUBLE_DIVIDE_CHECK(next_frame.coded_error);
++ }
++ }
++
+ // Set nominal per second bandwidth for this frame
+ cpi->target_bandwidth = cpi->per_frame_bandwidth * cpi->output_frame_rate;
+ if (cpi->target_bandwidth < 0)
+@@ -2028,6 +2040,8 @@ void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+ double kf_group_coded_err = 0.0;
+ double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+
++ vpx_memset(&next_frame, 0, sizeof(next_frame)); // assure clean
++
+ vp8_clear_system_state(); //__asm emms;
+ start_position = cpi->stats_in;
+
+diff --git a/vp8/encoder/firstpass.h b/vp8/encoder/firstpass.h
+index d7b52f3..48257ce 100644
+--- a/vp8/encoder/firstpass.h
++++ b/vp8/encoder/firstpass.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/generic/csystemdependent.c b/vp8/encoder/generic/csystemdependent.c
+index 52aab66..96028b3 100644
+--- a/vp8/encoder/generic/csystemdependent.c
++++ b/vp8/encoder/generic/csystemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/mcomp.c b/vp8/encoder/mcomp.c
+index d80059d..3c1507f 100644
+--- a/vp8/encoder/mcomp.c
++++ b/vp8/encoder/mcomp.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -1137,7 +1138,6 @@ int vp8_diamond_search_sadx4
+ }
+
+
+-#if !(CONFIG_REALTIME_ONLY)
+ int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *ref_mv, int error_per_bit, int distance, vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2], int *mvsadcost[2])
+ {
+ unsigned char *what = (*(b->base_src) + b->src);
+@@ -1350,7 +1350,6 @@ int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *ref_mv, int er
+ else
+ return INT_MAX;
+ }
+-#endif
+
+ #ifdef ENTROPY_STATS
+ void print_mode_context(void)
+diff --git a/vp8/encoder/mcomp.h b/vp8/encoder/mcomp.h
+index 921206f..40cbb07 100644
+--- a/vp8/encoder/mcomp.h
++++ b/vp8/encoder/mcomp.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/modecosts.c b/vp8/encoder/modecosts.c
+index 73170cf..6632a36 100644
+--- a/vp8/encoder/modecosts.c
++++ b/vp8/encoder/modecosts.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/modecosts.h b/vp8/encoder/modecosts.h
+index 5ade265..0c46acd 100644
+--- a/vp8/encoder/modecosts.h
++++ b/vp8/encoder/modecosts.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
+index 7662720..98827f9 100644
+--- a/vp8/encoder/onyx_if.c
++++ b/vp8/encoder/onyx_if.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -281,7 +282,6 @@ static void segmentation_test_function(VP8_PTR ptr)
+
+ unsigned char *seg_map;
+ signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+- int i, j;
+
+ // Create a temporary map for segmentation data.
+ CHECK_MEM_ERROR(seg_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+@@ -811,7 +811,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
+ sf->full_freq[1] = 31;
+ sf->search_method = NSTEP;
+
+- if (!cpi->ref_frame_flags & VP8_LAST_FLAG)
++ if (!(cpi->ref_frame_flags & VP8_LAST_FLAG))
+ {
+ sf->thresh_mult[THR_NEWMV ] = INT_MAX;
+ sf->thresh_mult[THR_NEARESTMV] = INT_MAX;
+@@ -820,7 +820,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
+ sf->thresh_mult[THR_SPLITMV ] = INT_MAX;
+ }
+
+- if (!cpi->ref_frame_flags & VP8_GOLD_FLAG)
++ if (!(cpi->ref_frame_flags & VP8_GOLD_FLAG))
+ {
+ sf->thresh_mult[THR_NEARESTG ] = INT_MAX;
+ sf->thresh_mult[THR_ZEROG ] = INT_MAX;
+@@ -829,7 +829,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
+ sf->thresh_mult[THR_SPLITG ] = INT_MAX;
+ }
+
+- if (!cpi->ref_frame_flags & VP8_ALT_FLAG)
++ if (!(cpi->ref_frame_flags & VP8_ALT_FLAG))
+ {
+ sf->thresh_mult[THR_NEARESTA ] = INT_MAX;
+ sf->thresh_mult[THR_ZEROA ] = INT_MAX;
+@@ -1144,18 +1144,15 @@ void vp8_set_speed_features(VP8_COMP *cpi)
+ cpi->mb.short_fdct4x4rd = FDCT_INVOKE(&cpi->rtcd.fdct, fast4x4);
+ }
+
+- cpi->mb.vp8_short_fdct4x4_ptr = FDCT_INVOKE(&cpi->rtcd.fdct, short4x4);
+ cpi->mb.short_walsh4x4 = FDCT_INVOKE(&cpi->rtcd.fdct, walsh_short4x4);
+
+ if (cpi->sf.improved_quant)
+ {
+ cpi->mb.quantize_b = QUANTIZE_INVOKE(&cpi->rtcd.quantize, quantb);
+- cpi->mb.quantize_brd = QUANTIZE_INVOKE(&cpi->rtcd.quantize, quantb);
+ }
+ else
+ {
+ cpi->mb.quantize_b = QUANTIZE_INVOKE(&cpi->rtcd.quantize, fastquantb);
+- cpi->mb.quantize_brd = QUANTIZE_INVOKE(&cpi->rtcd.quantize, fastquantb);
+ }
+
+ #if CONFIG_RUNTIME_CPU_DETECT
+@@ -2252,7 +2249,7 @@ void vp8_remove_compressor(VP8_PTR *ptr)
+ double total_psnr2 = vp8_mse2psnr(samples, 255.0, cpi->total_sq_error2);
+ double total_ssim = 100 * pow(cpi->summed_quality / cpi->summed_weights, 8.0);
+
+- fprintf(f, "Bitrate\AVGPsnr\tGLBPsnr\tAVPsnrP\tGLPsnrP\tVPXSSIM\t Time(us)\n");
++ fprintf(f, "Bitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\tGLPsnrP\tVPXSSIM\t Time(us)\n");
+ fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f %8.0f\n",
+ dr, cpi->total / cpi->count, total_psnr, cpi->totalp / cpi->count, total_psnr2, total_ssim,
+ total_encode_time);
+@@ -4739,7 +4736,6 @@ void vp8_check_gf_quality(VP8_COMP *cpi)
+ #if !(CONFIG_REALTIME_ONLY)
+ static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
+ {
+- double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+
+ if (!cpi->common.refresh_alt_ref_frame)
+ vp8_second_pass(cpi);
+@@ -4748,7 +4744,11 @@ static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest,
+ cpi->bits_left -= 8 * *size;
+
+ if (!cpi->common.refresh_alt_ref_frame)
++ {
++ double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth
++ *cpi->oxcf.two_pass_vbrmin_section / 100);
+ cpi->bits_left += (long long)(two_pass_min_rate / cpi->oxcf.frame_rate);
++ }
+ }
+ #endif
+
+@@ -5402,7 +5402,7 @@ int vp8_calc_low_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, co
+ {
+ for (j = 0; j < source->y_width; j += 16)
+ {
+- unsigned int sse, sse2, sum2;
++ unsigned int sse;
+ VARIANCE_INVOKE(rtcd, mse16x16)(src + j, source->y_stride, dst + j, dest->y_stride, &sse);
+
+ if (sse < 8096)
+diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
+index 29b120e..889bf73 100644
+--- a/vp8/encoder/onyx_int.h
++++ b/vp8/encoder/onyx_int.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -25,7 +26,7 @@
+ #include "entropy.h"
+ #include "threading.h"
+ #include "vpx_ports/mem.h"
+-#include "vpx_codec/internal/vpx_codec_internal.h"
++#include "vpx/internal/vpx_codec_internal.h"
+ #include "mcomp.h"
+
+ #define INTRARDOPT
+@@ -522,8 +523,8 @@ typedef struct
+ int motion_lvl;
+ int motion_speed;
+ int motion_var;
+- int next_iiratio;
+- int this_iiratio;
++ unsigned int next_iiratio;
++ unsigned int this_iiratio;
+ int this_frame_modified_error;
+
+ double norm_intra_err_per_mb;
+diff --git a/vp8/encoder/parms.cpp b/vp8/encoder/parms.cpp
+index 66fdafb..d7d30a8 100644
+--- a/vp8/encoder/parms.cpp
++++ b/vp8/encoder/parms.cpp
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c
+index d61e2ce..a50f99b 100644
+--- a/vp8/encoder/pickinter.c
++++ b/vp8/encoder/pickinter.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -453,6 +454,7 @@ int vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int rec
+ vpx_memset(mode_mv, 0, sizeof(mode_mv));
+ vpx_memset(nearest_mv, 0, sizeof(nearest_mv));
+ vpx_memset(near_mv, 0, sizeof(near_mv));
++ vpx_memset(&best_mbmode, 0, sizeof(best_mbmode));
+
+
+ // set up all the refframe dependent pointers.
+diff --git a/vp8/encoder/pickinter.h b/vp8/encoder/pickinter.h
+index fb28837..76fdb99 100644
+--- a/vp8/encoder/pickinter.h
++++ b/vp8/encoder/pickinter.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/picklpf.c b/vp8/encoder/picklpf.c
+index bbd7840..0527b80 100644
+--- a/vp8/encoder/picklpf.c
++++ b/vp8/encoder/picklpf.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/ppc/csystemdependent.c b/vp8/encoder/ppc/csystemdependent.c
+index f99277f..66fca8f 100644
+--- a/vp8/encoder/ppc/csystemdependent.c
++++ b/vp8/encoder/ppc/csystemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/ppc/encodemb_altivec.asm b/vp8/encoder/ppc/encodemb_altivec.asm
+index e0e976d..14a36a1 100644
+--- a/vp8/encoder/ppc/encodemb_altivec.asm
++++ b/vp8/encoder/ppc/encodemb_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/ppc/fdct_altivec.asm b/vp8/encoder/ppc/fdct_altivec.asm
+index eaab14c..01f3364 100644
+--- a/vp8/encoder/ppc/fdct_altivec.asm
++++ b/vp8/encoder/ppc/fdct_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/ppc/rdopt_altivec.asm b/vp8/encoder/ppc/rdopt_altivec.asm
+index 917bfe0..4f9b050 100644
+--- a/vp8/encoder/ppc/rdopt_altivec.asm
++++ b/vp8/encoder/ppc/rdopt_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/ppc/sad_altivec.asm b/vp8/encoder/ppc/sad_altivec.asm
+index 1102ccf..6d92728 100644
+--- a/vp8/encoder/ppc/sad_altivec.asm
++++ b/vp8/encoder/ppc/sad_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/ppc/variance_altivec.asm b/vp8/encoder/ppc/variance_altivec.asm
+index 952bf72..4e3fd59 100644
+--- a/vp8/encoder/ppc/variance_altivec.asm
++++ b/vp8/encoder/ppc/variance_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/ppc/variance_subpixel_altivec.asm b/vp8/encoder/ppc/variance_subpixel_altivec.asm
+index 148a8d2..4dcf7e4 100644
+--- a/vp8/encoder/ppc/variance_subpixel_altivec.asm
++++ b/vp8/encoder/ppc/variance_subpixel_altivec.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/preproc.c b/vp8/encoder/preproc.c
+index d2a13dc..e9cc075 100644
+--- a/vp8/encoder/preproc.c
++++ b/vp8/encoder/preproc.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/psnr.c b/vp8/encoder/psnr.c
+index 0e34cec..c5e9dad 100644
+--- a/vp8/encoder/psnr.c
++++ b/vp8/encoder/psnr.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/psnr.h b/vp8/encoder/psnr.h
+index 9f6ca0b..dd0b4e5 100644
+--- a/vp8/encoder/psnr.h
++++ b/vp8/encoder/psnr.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/quantize.c b/vp8/encoder/quantize.c
+index 6028ebf..73e80e3 100644
+--- a/vp8/encoder/quantize.c
++++ b/vp8/encoder/quantize.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -55,9 +56,7 @@ void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
+ }
+ }
+ }
+-
+ d->eob = eob + 1;
+-
+ }
+
+ void vp8_regular_quantize_b(BLOCK *b, BLOCKD *d)
+@@ -111,61 +110,40 @@ void vp8_regular_quantize_b(BLOCK *b, BLOCKD *d)
+
+ d->eob = eob + 1;
+ }
++
+ void vp8_quantize_mby(MACROBLOCK *x)
+ {
+ int i;
++ int has_2nd_order = (x->e_mbd.mbmi.mode != B_PRED
++ && x->e_mbd.mbmi.mode != SPLITMV);
+
+- if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
++ for (i = 0; i < 16; i++)
+ {
+- for (i = 0; i < 16; i++)
+- {
+- x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+- }
++ x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
++ x->e_mbd.mbmi.mb_skip_coeff &=
++ (x->e_mbd.block[i].eob <= has_2nd_order);
++ }
+
++ if(has_2nd_order)
++ {
+ x->quantize_b(&x->block[24], &x->e_mbd.block[24]);
+ x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[24].eob);
+-
+- }
+- else
+- {
+- for (i = 0; i < 16; i++)
+- {
+- x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+- }
+ }
+ }
+
+ void vp8_quantize_mb(MACROBLOCK *x)
+ {
+ int i;
++ int has_2nd_order=(x->e_mbd.mbmi.mode != B_PRED
++ && x->e_mbd.mbmi.mode != SPLITMV);
+
+ x->e_mbd.mbmi.mb_skip_coeff = 1;
+-
+- if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
++ for (i = 0; i < 24+has_2nd_order; i++)
+ {
+- for (i = 0; i < 16; i++)
+- {
+- x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+- }
+-
+- for (i = 16; i < 25; i++)
+- {
+- x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+- }
+- }
+- else
+- {
+- for (i = 0; i < 24; i++)
+- {
+- x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+- }
++ x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
++ x->e_mbd.mbmi.mb_skip_coeff &=
++ (x->e_mbd.block[i].eob <= (has_2nd_order && i<16));
+ }
+-
+ }
+
+
+@@ -179,71 +157,3 @@ void vp8_quantize_mbuv(MACROBLOCK *x)
+ x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+ }
+ }
+-
+-// This function is not currently called
+-void vp8_quantize_mbrd(MACROBLOCK *x)
+-{
+- int i;
+-
+- x->e_mbd.mbmi.mb_skip_coeff = 1;
+-
+- if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
+- {
+- for (i = 0; i < 16; i++)
+- {
+- x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+- }
+-
+- for (i = 16; i < 25; i++)
+- {
+- x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+- }
+- }
+- else
+- {
+- for (i = 0; i < 24; i++)
+- {
+- x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+- }
+- }
+-}
+-
+-void vp8_quantize_mbuvrd(MACROBLOCK *x)
+-{
+- int i;
+-
+- for (i = 16; i < 24; i++)
+- {
+- x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+- }
+-}
+-
+-void vp8_quantize_mbyrd(MACROBLOCK *x)
+-{
+- int i;
+-
+- if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
+- {
+- for (i = 0; i < 16; i++)
+- {
+- x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+- }
+-
+- x->quantize_brd(&x->block[24], &x->e_mbd.block[24]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[24].eob);
+-
+- }
+- else
+- {
+- for (i = 0; i < 16; i++)
+- {
+- x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+- x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+- }
+- }
+-}
+diff --git a/vp8/encoder/quantize.h b/vp8/encoder/quantize.h
+index 868e8e3..ca073ef 100644
+--- a/vp8/encoder/quantize.h
++++ b/vp8/encoder/quantize.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -16,6 +17,10 @@
+ #define prototype_quantize_block(sym) \
+ void (sym)(BLOCK *b,BLOCKD *d)
+
++#if ARCH_X86 || ARCH_X86_64
++#include "x86/quantize_x86.h"
++#endif
++
+ #if ARCH_ARM
+ #include "arm/quantize_arm.h"
+ #endif
+@@ -45,8 +50,5 @@ typedef struct
+ extern void vp8_quantize_mb(MACROBLOCK *x);
+ extern void vp8_quantize_mbuv(MACROBLOCK *x);
+ extern void vp8_quantize_mby(MACROBLOCK *x);
+-extern void vp8_quantize_mbyrd(MACROBLOCK *x);
+-extern void vp8_quantize_mbuvrd(MACROBLOCK *x);
+-extern void vp8_quantize_mbrd(MACROBLOCK *x);
+
+ #endif
+diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c
+index 05040d3..944a2e8 100644
+--- a/vp8/encoder/ratectrl.c
++++ b/vp8/encoder/ratectrl.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -1063,7 +1064,6 @@ void vp8_calc_pframe_target_size(VP8_COMP *cpi)
+
+ if (cpi->common.refresh_golden_frame == TRUE)
+ {
+- int isize_adjustment = 0;
+ #if 0
+
+ if (0) // p_gw
+@@ -1119,8 +1119,9 @@ void vp8_calc_pframe_target_size(VP8_COMP *cpi)
+ cpi->this_frame_target = (baseline_bits_at_q(1, Q, cpi->common.MBs) * cpi->last_boost) / 100;
+
+ }
+- // If there is an active ARF at this location use the minimum bits on this frame
+- else
++ // If there is an active ARF at this location use the minimum
++ // bits on this frame unless it was a contructed arf.
++ else if (cpi->oxcf.arnr_max_frames == 0)
+ {
+ cpi->this_frame_target = 0; // Minimial spend on gf that is replacing an arf
+ }
+@@ -1171,7 +1172,8 @@ void vp8_update_rate_correction_factors(VP8_COMP *cpi, int damp_var)
+ while (Z > 0)
+ {
+ Z --;
+- projected_size_based_on_q *= (int)Factor;
++ projected_size_based_on_q =
++ (int)(Factor * projected_size_based_on_q);
+ Factor += factor_adjustment;
+
+ if (Factor >= 0.999)
+@@ -1362,7 +1364,8 @@ int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame)
+ if (cpi->zbin_over_quant > zbin_oqmax)
+ cpi->zbin_over_quant = zbin_oqmax;
+
+- bits_per_mb_at_this_q *= (int)Factor; // Each over-ruin step is assumed to equate to approximately 3% reduction in bitrate
++ // Adjust bits_per_mb_at_this_q estimate
++ bits_per_mb_at_this_q = (int)(Factor * bits_per_mb_at_this_q);
+ Factor += factor_adjustment;
+
+ if (Factor >= 0.999)
+diff --git a/vp8/encoder/ratectrl.h b/vp8/encoder/ratectrl.h
+index 588c7a8..ff5778f 100644
+--- a/vp8/encoder/ratectrl.h
++++ b/vp8/encoder/ratectrl.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c
+index 0846996..9a772a7 100644
+--- a/vp8/encoder/rdopt.c
++++ b/vp8/encoder/rdopt.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -170,15 +171,13 @@ static void fill_token_costs(
+
+ }
+
+-static int rd_iifactor [ 32 ] = { 16, 16, 16, 12, 8, 4, 2, 0,
++static int rd_iifactor [ 32 ] = { 4, 4, 3, 2, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+
+-
+-
+ // The values in this table should be reviewed
+ static int sad_per_bit16lut[128] =
+ {
+@@ -237,36 +236,32 @@ void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue)
+
+ vp8_clear_system_state(); //__asm emms;
+
+- cpi->RDMULT = (int)((0.00007 * (capped_q * capped_q * capped_q * capped_q)) - (0.0125 * (capped_q * capped_q * capped_q)) +
+- (2.25 * (capped_q * capped_q)) - (12.5 * capped_q) + 25.0);
++ cpi->RDMULT = (int)( (0.0001 * (capped_q * capped_q * capped_q * capped_q))
++ -(0.015 * (capped_q * capped_q * capped_q))
++ +(3.25 * (capped_q * capped_q))
++ -(17.5 * capped_q) + 125.0);
+
+- if (cpi->RDMULT < 25)
+- cpi->RDMULT = 25;
++ if (cpi->RDMULT < 125)
++ cpi->RDMULT = 125;
+
+- if (cpi->pass == 2)
++ if (cpi->pass == 2 && (cpi->common.frame_type != KEY_FRAME))
+ {
+- if (cpi->common.frame_type == KEY_FRAME)
+- cpi->RDMULT += (cpi->RDMULT * rd_iifactor[0]) / 16;
+- else if (cpi->next_iiratio > 31)
+- cpi->RDMULT += (cpi->RDMULT * rd_iifactor[31]) / 16;
++ if (cpi->next_iiratio > 31)
++ cpi->RDMULT += (cpi->RDMULT * rd_iifactor[31]) >> 4;
+ else
+- cpi->RDMULT += (cpi->RDMULT * rd_iifactor[cpi->next_iiratio]) / 16;
++ cpi->RDMULT += (cpi->RDMULT * rd_iifactor[cpi->next_iiratio]) >> 4;
+ }
+
+
+ // Extend rate multiplier along side quantizer zbin increases
+ if (cpi->zbin_over_quant > 0)
+ {
+- // Extend rate multiplier along side quantizer zbin increases
+- if (cpi->zbin_over_quant > 0)
+- {
+- double oq_factor = pow(1.006, cpi->zbin_over_quant);
++ double oq_factor = pow(1.006, cpi->zbin_over_quant);
+
+- if (oq_factor > (1.0 + ((double)cpi->zbin_over_quant / 64.0)))
+- oq_factor = (1.0 + (double)cpi->zbin_over_quant / 64.0);
++ if (oq_factor > (1.0 + ((double)cpi->zbin_over_quant / 64.0)))
++ oq_factor = (1.0 + (double)cpi->zbin_over_quant / 64.0);
+
+- cpi->RDMULT *= (int)oq_factor;
+- }
++ cpi->RDMULT = (int)(oq_factor * cpi->RDMULT);
+ }
+
+ cpi->mb.errorperbit = (cpi->RDMULT / 100);
+@@ -1037,7 +1032,7 @@ static unsigned int vp8_encode_inter_mb_segment(MACROBLOCK *x, int const *labels
+
+ // set to 0 no way to account for 2nd order DC so discount
+ //be->coeff[0] = 0;
+- x->quantize_brd(be, bd);
++ x->quantize_b(be, bd);
+
+ distortion += ENCODEMB_INVOKE(rtcd, berr)(be->coeff, bd->dqcoeff);
+ }
+@@ -1075,7 +1070,7 @@ static void macro_block_yrd(MACROBLOCK *mb, int *Rate, int *Distortion, const vp
+ // Quantization
+ for (b = 0; b < 16; b++)
+ {
+- mb->quantize_brd(&mb->block[b], &mb->e_mbd.block[b]);
++ mb->quantize_b(&mb->block[b], &mb->e_mbd.block[b]);
+ }
+
+ // DC predication and Quantization of 2nd Order block
+@@ -1083,7 +1078,7 @@ static void macro_block_yrd(MACROBLOCK *mb, int *Rate, int *Distortion, const vp
+ {
+
+ {
+- mb->quantize_brd(mb_y2, x_y2);
++ mb->quantize_b(mb_y2, x_y2);
+ }
+ }
+
+@@ -1130,6 +1125,9 @@ static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x, MV *bes
+ MV bmvs[16];
+ int beobs[16];
+
++ vpx_memset(beobs, 0, sizeof(beobs));
++
++
+ for (segmentation = 0; segmentation < VP8_NUMMBSPLITS; segmentation++)
+ {
+ int label_count;
+@@ -1464,6 +1462,8 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
+
+ *returnintra = INT_MAX;
+
++ vpx_memset(&best_mbmode, 0, sizeof(best_mbmode)); // clean
++
+ cpi->mbs_tested_so_far++; // Count of the number of MBs tested so far this frame
+
+ x->skip = 0;
+diff --git a/vp8/encoder/rdopt.h b/vp8/encoder/rdopt.h
+index c6eae4b..617241d 100644
+--- a/vp8/encoder/rdopt.h
++++ b/vp8/encoder/rdopt.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/sad_c.c b/vp8/encoder/sad_c.c
+index 74c6bd7..1914c60 100644
+--- a/vp8/encoder/sad_c.c
++++ b/vp8/encoder/sad_c.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/ssim.c b/vp8/encoder/ssim.c
+index df214a8..35dd10c 100644
+--- a/vp8/encoder/ssim.c
++++ b/vp8/encoder/ssim.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/tokenize.c b/vp8/encoder/tokenize.c
+index 33ddd64..819f6a5 100644
+--- a/vp8/encoder/tokenize.c
++++ b/vp8/encoder/tokenize.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/tokenize.h b/vp8/encoder/tokenize.h
+index 02aacc2..51f912b 100644
+--- a/vp8/encoder/tokenize.h
++++ b/vp8/encoder/tokenize.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/treewriter.c b/vp8/encoder/treewriter.c
+index e398044..942442b 100644
+--- a/vp8/encoder/treewriter.c
++++ b/vp8/encoder/treewriter.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/treewriter.h b/vp8/encoder/treewriter.h
+index 05ac74c..075df50 100644
+--- a/vp8/encoder/treewriter.h
++++ b/vp8/encoder/treewriter.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/variance.h b/vp8/encoder/variance.h
+index b3b55c3..6610e7d 100644
+--- a/vp8/encoder/variance.h
++++ b/vp8/encoder/variance.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/variance_c.c b/vp8/encoder/variance_c.c
+index 85269b9..efcf2b7 100644
+--- a/vp8/encoder/variance_c.c
++++ b/vp8/encoder/variance_c.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/x86/csystemdependent.c b/vp8/encoder/x86/csystemdependent.c
+index 186ee68..8bc6877 100644
+--- a/vp8/encoder/x86/csystemdependent.c
++++ b/vp8/encoder/x86/csystemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/x86/dct_mmx.asm b/vp8/encoder/x86/dct_mmx.asm
+index e134237..3dfc47b 100644
+--- a/vp8/encoder/x86/dct_mmx.asm
++++ b/vp8/encoder/x86/dct_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/dct_sse2.asm b/vp8/encoder/x86/dct_sse2.asm
+index 3e5e9a7..8ddc5d7 100644
+--- a/vp8/encoder/x86/dct_sse2.asm
++++ b/vp8/encoder/x86/dct_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/dct_x86.h b/vp8/encoder/x86/dct_x86.h
+index bc80e64..fec1a2e 100644
+--- a/vp8/encoder/x86/dct_x86.h
++++ b/vp8/encoder/x86/dct_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/x86/encodemb_x86.h b/vp8/encoder/x86/encodemb_x86.h
+index 9397a6c..d1ba7d9 100644
+--- a/vp8/encoder/x86/encodemb_x86.h
++++ b/vp8/encoder/x86/encodemb_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/x86/encodeopt.asm b/vp8/encoder/x86/encodeopt.asm
+index 1940471..cdc17a5 100644
+--- a/vp8/encoder/x86/encodeopt.asm
++++ b/vp8/encoder/x86/encodeopt.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/fwalsh_sse2.asm b/vp8/encoder/x86/fwalsh_sse2.asm
+index 7d86201..1966697 100644
+--- a/vp8/encoder/x86/fwalsh_sse2.asm
++++ b/vp8/encoder/x86/fwalsh_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/mcomp_x86.h b/vp8/encoder/x86/mcomp_x86.h
+index 5661491..c2b4b36 100644
+--- a/vp8/encoder/x86/mcomp_x86.h
++++ b/vp8/encoder/x86/mcomp_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/x86/preproc_mmx.c b/vp8/encoder/x86/preproc_mmx.c
+index 69617ca..8b23bb5 100644
+--- a/vp8/encoder/x86/preproc_mmx.c
++++ b/vp8/encoder/x86/preproc_mmx.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/x86/quantize_mmx.asm b/vp8/encoder/x86/quantize_mmx.asm
+index 847fc6e..25adca0 100644
+--- a/vp8/encoder/x86/quantize_mmx.asm
++++ b/vp8/encoder/x86/quantize_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/quantize_sse2.asm b/vp8/encoder/x86/quantize_sse2.asm
+new file mode 100644
+index 0000000..c64a8ba
+--- /dev/null
++++ b/vp8/encoder/x86/quantize_sse2.asm
+@@ -0,0 +1,254 @@
++;
++; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++;
++; Use of this source code is governed by a BSD-style license and patent
++; grant that can be found in the LICENSE file in the root of the source
++; tree. All contributing project authors may be found in the AUTHORS
++; file in the root of the source tree.
++;
++
++
++%include "vpx_ports/x86_abi_support.asm"
++
++
++;int vp8_regular_quantize_b_impl_sse2(short *coeff_ptr, short *zbin_ptr,
++; short *qcoeff_ptr,short *dequant_ptr,
++; const int *default_zig_zag, short *round_ptr,
++; short *quant_ptr, short *dqcoeff_ptr,
++; unsigned short zbin_oq_value,
++; short *zbin_boost_ptr);
++;
++global sym(vp8_regular_quantize_b_impl_sse2)
++sym(vp8_regular_quantize_b_impl_sse2):
++ push rbp
++ mov rbp, rsp
++ SHADOW_ARGS_TO_STACK 10
++ push rsi
++ push rdi
++ push rbx
++ ; end prolog
++
++ ALIGN_STACK 16, rax
++
++ %define abs_minus_zbin_lo 0
++ %define abs_minus_zbin_hi 16
++ %define temp_qcoeff_lo 32
++ %define temp_qcoeff_hi 48
++ %define save_xmm6 64
++ %define save_xmm7 80
++ %define eob 96
++
++ %define vp8_regularquantizeb_stack_size eob + 16
++
++ sub rsp, vp8_regularquantizeb_stack_size
++
++ movdqa DQWORD PTR[rsp + save_xmm6], xmm6
++ movdqa DQWORD PTR[rsp + save_xmm7], xmm7
++
++ mov rdx, arg(0) ;coeff_ptr
++ mov eax, arg(8) ;zbin_oq_value
++
++ mov rcx, arg(1) ;zbin_ptr
++ movd xmm7, eax
++
++ movdqa xmm0, DQWORD PTR[rdx]
++ movdqa xmm4, DQWORD PTR[rdx + 16]
++
++ movdqa xmm1, xmm0
++ movdqa xmm5, xmm4
++
++ psraw xmm0, 15 ;sign of z (aka sz)
++ psraw xmm4, 15 ;sign of z (aka sz)
++
++ pxor xmm1, xmm0
++ pxor xmm5, xmm4
++
++ movdqa xmm2, DQWORD PTR[rcx] ;load zbin_ptr
++ movdqa xmm3, DQWORD PTR[rcx + 16] ;load zbin_ptr
++
++ pshuflw xmm7, xmm7, 0
++ psubw xmm1, xmm0 ;x = abs(z)
++
++ punpcklwd xmm7, xmm7 ;duplicated zbin_oq_value
++ psubw xmm5, xmm4 ;x = abs(z)
++
++ paddw xmm2, xmm7
++ paddw xmm3, xmm7
++
++ psubw xmm1, xmm2 ;sub (zbin_ptr + zbin_oq_value)
++ psubw xmm5, xmm3 ;sub (zbin_ptr + zbin_oq_value)
++
++ mov rdi, arg(5) ;round_ptr
++ mov rsi, arg(6) ;quant_ptr
++
++ movdqa DQWORD PTR[rsp + abs_minus_zbin_lo], xmm1
++ movdqa DQWORD PTR[rsp + abs_minus_zbin_hi], xmm5
++
++ paddw xmm1, xmm2 ;add (zbin_ptr + zbin_oq_value) back
++ paddw xmm5, xmm3 ;add (zbin_ptr + zbin_oq_value) back
++
++ movdqa xmm2, DQWORD PTR[rdi]
++ movdqa xmm3, DQWORD PTR[rsi]
++
++ movdqa xmm6, DQWORD PTR[rdi + 16]
++ movdqa xmm7, DQWORD PTR[rsi + 16]
++
++ paddw xmm1, xmm2
++ paddw xmm5, xmm6
++
++ pmulhw xmm1, xmm3
++ pmulhw xmm5, xmm7
++
++ mov rsi, arg(2) ;qcoeff_ptr
++ pxor xmm6, xmm6
++
++ pxor xmm1, xmm0
++ pxor xmm5, xmm4
++
++ psubw xmm1, xmm0
++ psubw xmm5, xmm4
++
++ movdqa DQWORD PTR[rsp + temp_qcoeff_lo], xmm1
++ movdqa DQWORD PTR[rsp + temp_qcoeff_hi], xmm5
++
++ movdqa DQWORD PTR[rsi], xmm6 ;zero qcoeff
++ movdqa DQWORD PTR[rsi + 16], xmm6 ;zero qcoeff
++
++ xor rax, rax
++ mov rcx, -1
++
++ mov [rsp + eob], rcx
++ mov rsi, arg(9) ;zbin_boost_ptr
++
++ mov rbx, arg(4) ;default_zig_zag
++
++rq_zigzag_loop:
++ movsxd rcx, DWORD PTR[rbx + rax*4] ;now we have rc
++ movsx edi, WORD PTR [rsi] ;*zbin_boost_ptr aka zbin
++ lea rsi, [rsi + 2] ;zbin_boost_ptr++
++
++ movsx edx, WORD PTR[rsp + abs_minus_zbin_lo + rcx *2]
++
++ sub edx, edi ;x - zbin
++ jl rq_zigzag_1
++
++ mov rdi, arg(2) ;qcoeff_ptr
++
++ movsx edx, WORD PTR[rsp + temp_qcoeff_lo + rcx *2]
++
++ cmp edx, 0
++ je rq_zigzag_1
++
++ mov WORD PTR[rdi + rcx * 2], dx ;qcoeff_ptr[rc] = temp_qcoeff[rc]
++
++ mov rsi, arg(9) ;zbin_boost_ptr
++ mov [rsp + eob], rax ;eob = i
++
++rq_zigzag_1:
++ movsxd rcx, DWORD PTR[rbx + rax*4 + 4]
++ movsx edi, WORD PTR [rsi] ;*zbin_boost_ptr aka zbin
++ lea rsi, [rsi + 2] ;zbin_boost_ptr++
++
++ movsx edx, WORD PTR[rsp + abs_minus_zbin_lo + rcx *2]
++ lea rax, [rax + 1]
++
++ sub edx, edi ;x - zbin
++ jl rq_zigzag_1a
++
++ mov rdi, arg(2) ;qcoeff_ptr
++
++ movsx edx, WORD PTR[rsp + temp_qcoeff_lo + rcx *2]
++
++ cmp edx, 0
++ je rq_zigzag_1a
++
++ mov WORD PTR[rdi + rcx * 2], dx ;qcoeff_ptr[rc] = temp_qcoeff[rc]
++
++ mov rsi, arg(9) ;zbin_boost_ptr
++ mov [rsp + eob], rax ;eob = i
++
++rq_zigzag_1a:
++ movsxd rcx, DWORD PTR[rbx + rax*4 + 4]
++ movsx edi, WORD PTR [rsi] ;*zbin_boost_ptr aka zbin
++ lea rsi, [rsi + 2] ;zbin_boost_ptr++
++
++ movsx edx, WORD PTR[rsp + abs_minus_zbin_lo + rcx *2]
++ lea rax, [rax + 1]
++
++ sub edx, edi ;x - zbin
++ jl rq_zigzag_1b
++
++ mov rdi, arg(2) ;qcoeff_ptr
++
++ movsx edx, WORD PTR[rsp + temp_qcoeff_lo + rcx *2]
++
++ cmp edx, 0
++ je rq_zigzag_1b
++
++ mov WORD PTR[rdi + rcx * 2], dx ;qcoeff_ptr[rc] = temp_qcoeff[rc]
++
++ mov rsi, arg(9) ;zbin_boost_ptr
++ mov [rsp + eob], rax ;eob = i
++
++rq_zigzag_1b:
++ movsxd rcx, DWORD PTR[rbx + rax*4 + 4]
++ movsx edi, WORD PTR [rsi] ;*zbin_boost_ptr aka zbin
++ lea rsi, [rsi + 2] ;zbin_boost_ptr++
++
++ movsx edx, WORD PTR[rsp + abs_minus_zbin_lo + rcx *2]
++ lea rax, [rax + 1]
++
++ sub edx, edi ;x - zbin
++ jl rq_zigzag_1c
++
++ mov rdi, arg(2) ;qcoeff_ptr
++
++ movsx edx, WORD PTR[rsp + temp_qcoeff_lo + rcx *2]
++
++ cmp edx, 0
++ je rq_zigzag_1c
++
++ mov WORD PTR[rdi + rcx * 2], dx ;qcoeff_ptr[rc] = temp_qcoeff[rc]
++
++ mov rsi, arg(9) ;zbin_boost_ptr
++ mov [rsp + eob], rax ;eob = i
++
++rq_zigzag_1c:
++ lea rax, [rax + 1]
++
++ cmp rax, 16
++ jl rq_zigzag_loop
++
++ mov rdi, arg(2) ;qcoeff_ptr
++ mov rcx, arg(3) ;dequant_ptr
++ mov rsi, arg(7) ;dqcoeff_ptr
++
++ movdqa xmm2, DQWORD PTR[rdi]
++ movdqa xmm3, DQWORD PTR[rdi + 16]
++
++ movdqa xmm0, DQWORD PTR[rcx]
++ movdqa xmm1, DQWORD PTR[rcx + 16]
++
++ pmullw xmm0, xmm2
++ pmullw xmm1, xmm3
++
++ movdqa DQWORD PTR[rsi], xmm0 ;store dqcoeff
++ movdqa DQWORD PTR[rsi + 16], xmm1 ;store dqcoeff
++
++ mov rax, [rsp + eob]
++
++ movdqa xmm6, DQWORD PTR[rsp + save_xmm6]
++ movdqa xmm7, DQWORD PTR[rsp + save_xmm7]
++
++ add rax, 1
++
++ add rsp, vp8_regularquantizeb_stack_size
++ pop rsp
++
++ ; begin epilog
++ pop rbx
++ pop rdi
++ pop rsi
++ UNSHADOW_ARGS
++ pop rbp
++ ret
+diff --git a/vp8/encoder/x86/quantize_x86.h b/vp8/encoder/x86/quantize_x86.h
+new file mode 100644
+index 0000000..37d69a8
+--- /dev/null
++++ b/vp8/encoder/x86/quantize_x86.h
+@@ -0,0 +1,38 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license and patent
++ * grant that can be found in the LICENSE file in the root of the source
++ * tree. All contributing project authors may be found in the AUTHORS
++ * file in the root of the source tree.
++ */
++
++#ifndef QUANTIZE_X86_H
++#define QUANTIZE_X86_H
++
++
++/* Note:
++ *
++ * This platform is commonly built for runtime CPU detection. If you modify
++ * any of the function mappings present in this file, be sure to also update
++ * them in the function pointer initialization code
++ */
++#if HAVE_MMX
++
++#endif
++
++
++#if HAVE_SSE2
++extern prototype_quantize_block(vp8_regular_quantize_b_sse2);
++
++#if !CONFIG_RUNTIME_CPU_DETECT
++
++#undef vp8_quantize_quantb
++#define vp8_quantize_quantb vp8_regular_quantize_b_sse2
++
++#endif
++
++#endif
++
++
++#endif
+diff --git a/vp8/encoder/x86/sad_mmx.asm b/vp8/encoder/x86/sad_mmx.asm
+index a825698..4b35749 100644
+--- a/vp8/encoder/x86/sad_mmx.asm
++++ b/vp8/encoder/x86/sad_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/sad_sse2.asm b/vp8/encoder/x86/sad_sse2.asm
+index 53240bb..f4ef551 100644
+--- a/vp8/encoder/x86/sad_sse2.asm
++++ b/vp8/encoder/x86/sad_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/sad_sse3.asm b/vp8/encoder/x86/sad_sse3.asm
+index 38cc029..edfe82f 100644
+--- a/vp8/encoder/x86/sad_sse3.asm
++++ b/vp8/encoder/x86/sad_sse3.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/sad_ssse3.asm b/vp8/encoder/x86/sad_ssse3.asm
+index 1bb9561..79c4b44 100644
+--- a/vp8/encoder/x86/sad_ssse3.asm
++++ b/vp8/encoder/x86/sad_ssse3.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/subtract_mmx.asm b/vp8/encoder/x86/subtract_mmx.asm
+index ce3e610..d9babd3 100644
+--- a/vp8/encoder/x86/subtract_mmx.asm
++++ b/vp8/encoder/x86/subtract_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/variance_impl_mmx.asm b/vp8/encoder/x86/variance_impl_mmx.asm
+index d0da82a..31f66ec 100644
+--- a/vp8/encoder/x86/variance_impl_mmx.asm
++++ b/vp8/encoder/x86/variance_impl_mmx.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/variance_impl_sse2.asm b/vp8/encoder/x86/variance_impl_sse2.asm
+index 7e5ee28..1ccc6c5 100644
+--- a/vp8/encoder/x86/variance_impl_sse2.asm
++++ b/vp8/encoder/x86/variance_impl_sse2.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vp8/encoder/x86/variance_mmx.c b/vp8/encoder/x86/variance_mmx.c
+index 4a5b25b..788b833 100644
+--- a/vp8/encoder/x86/variance_mmx.c
++++ b/vp8/encoder/x86/variance_mmx.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/x86/variance_sse2.c b/vp8/encoder/x86/variance_sse2.c
+index ea80753..78ecd7b 100644
+--- a/vp8/encoder/x86/variance_sse2.c
++++ b/vp8/encoder/x86/variance_sse2.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vp8/encoder/x86/variance_x86.h b/vp8/encoder/x86/variance_x86.h
+index 35fc90c..9cdd662 100644
+--- a/vp8/encoder/x86/variance_x86.h
++++ b/vp8/encoder/x86/variance_x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -240,7 +241,7 @@ extern prototype_sad_multi_dif_address(vp8_sad4x4x4d_sse3);
+ #define vp8_variance_sad4x4x3 vp8_sad4x4x3_sse3
+
+ #undef vp8_variance_sad16x16x4d
+-#define vp8_variance_sad16x16x4 vp8_sad16x16x4d_sse3
++#define vp8_variance_sad16x16x4d vp8_sad16x16x4d_sse3
+
+ #undef vp8_variance_sad16x8x4d
+ #define vp8_variance_sad16x8x4d vp8_sad16x8x4d_sse3
+diff --git a/vp8/encoder/x86/x86_csystemdependent.c b/vp8/encoder/x86/x86_csystemdependent.c
+index f1391ba..f6123a8 100644
+--- a/vp8/encoder/x86/x86_csystemdependent.c
++++ b/vp8/encoder/x86/x86_csystemdependent.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -120,6 +121,40 @@ void vp8_fast_quantize_b_sse(BLOCK *b, BLOCKD *d)
+ );
+ }
+
++int vp8_regular_quantize_b_impl_sse2(short *coeff_ptr, short *zbin_ptr,
++ short *qcoeff_ptr,short *dequant_ptr,
++ const int *default_zig_zag, short *round_ptr,
++ short *quant_ptr, short *dqcoeff_ptr,
++ unsigned short zbin_oq_value,
++ short *zbin_boost_ptr);
++
++void vp8_regular_quantize_b_sse2(BLOCK *b,BLOCKD *d)
++{
++ short *zbin_boost_ptr = &b->zrun_zbin_boost[0];
++ short *coeff_ptr = &b->coeff[0];
++ short *zbin_ptr = &b->zbin[0][0];
++ short *round_ptr = &b->round[0][0];
++ short *quant_ptr = &b->quant[0][0];
++ short *qcoeff_ptr = d->qcoeff;
++ short *dqcoeff_ptr = d->dqcoeff;
++ short *dequant_ptr = &d->dequant[0][0];
++ short zbin_oq_value = b->zbin_extra;
++
++ d->eob = vp8_regular_quantize_b_impl_sse2(
++ coeff_ptr,
++ zbin_ptr,
++ qcoeff_ptr,
++ dequant_ptr,
++ vp8_default_zig_zag1d,
++
++ round_ptr,
++ quant_ptr,
++ dqcoeff_ptr,
++ zbin_oq_value,
++ zbin_boost_ptr
++ );
++}
++
+ int vp8_mbblock_error_xmm_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+ int vp8_mbblock_error_xmm(MACROBLOCK *mb, int dc)
+ {
+@@ -250,6 +285,7 @@ void vp8_arch_x86_encoder_init(VP8_COMP *cpi)
+ /* cpi->rtcd.encodemb.sub* not implemented for wmt */
+
+ cpi->rtcd.quantize.fastquantb = vp8_fast_quantize_b_sse;
++ cpi->rtcd.quantize.quantb = vp8_regular_quantize_b_sse2;
+ }
+
+ #endif
+diff --git a/vp8/exports_dec b/vp8/exports_dec
+new file mode 100644
+index 0000000..f9b985c
+--- /dev/null
++++ b/vp8/exports_dec
+@@ -0,0 +1 @@
++data vpx_codec_vp8_dx_algo
+diff --git a/vp8/exports_enc b/vp8/exports_enc
+new file mode 100644
+index 0000000..9967011
+--- /dev/null
++++ b/vp8/exports_enc
+@@ -0,0 +1 @@
++data vpx_codec_vp8_cx_algo
+diff --git a/vp8/vp8.h b/vp8/vp8.h
+deleted file mode 100644
+index 87ca217..0000000
+--- a/vp8/vp8.h
++++ /dev/null
+@@ -1,116 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\defgroup vp8 VP8
+- * \ingroup codecs
+- * VP8 is vpx's newest video compression algorithm that uses motion
+- * compensated prediction, Discrete Cosine Transform (DCT) coding of the
+- * prediction error signal and context dependent entropy coding techniques
+- * based on arithmatic principles. It features:
+- * - YUV 4:2:0 image format
+- * - Macro-block based coding (16x16 luma plus two 8x8 chroma)
+- * - 1/4 (1/8) pixel accuracy motion compensated prediction
+- * - 4x4 DCT transform
+- * - 128 level linear quantizer
+- * - In loop deblocking filter
+- * - Context-based entropy coding
+- *
+- * @{
+- */
+-/*!\file vp8.h
+- * \brief Provides controls common to both the VP8 encoder and decoder.
+- */
+-#ifndef VP8_H
+-#define VP8_H
+-#include "vpx_codec_impl_top.h"
+-
+-/*!\brief Control functions
+- *
+- * The set of macros define the control functions of VP8 interface
+- */
+-enum vp8_dec_control_id
+-{
+- VP8_SET_REFERENCE = 1, /**< pass in an external frame into decoder to be used as reference frame */
+- VP8_COPY_REFERENCE = 2, /**< get a copy of reference frame from the decoder */
+- VP8_SET_POSTPROC = 3, /**< set decoder's the post processing settings */
+- VP8_COMMON_CTRL_ID_MAX
+-};
+-
+-/*!\brief post process flags
+- *
+- * The set of macros define VP8 decoder post processing flags
+- */
+-enum vp8_postproc_level
+-{
+- VP8_NOFILTERING = 0,
+- VP8_DEBLOCK = 1,
+- VP8_DEMACROBLOCK = 2,
+- VP8_ADDNOISE = 4,
+-};
+-
+-/*!\brief post process flags
+- *
+- * This define a structure that describe the post processing settings. For
+- * the best objective measure (using thet PSNR metric) set post_proc_flag
+- * to VP8_DEBLOCK and deblocking_level to 1.
+- */
+-
+-typedef struct vp8_postproc_cfg
+-{
+- int post_proc_flag; /**< the types of post processing to be done, should be combination of "vp8_postproc_level" */
+- int deblocking_level; /**< the strength of deblocking, valid range [0, 16] */
+- int noise_level; /**< the strength of additive noise, valid range [0, 16] */
+-} vp8_postproc_cfg_t;
+-
+-/*!\brief reference frame type
+- *
+- * The set of macros define the type of VP8 reference frames
+- */
+-typedef enum vpx_ref_frame_type
+-{
+- VP8_LAST_FRAME = 1,
+- VP8_GOLD_FRAME = 2,
+- VP8_ALTR_FRAME = 4
+-} vpx_ref_frame_type_t;
+-
+-/*!\brief reference frame data struct
+- *
+- * define the data struct to access vp8 reference frames
+- */
+-
+-typedef struct vpx_ref_frame
+-{
+- vpx_ref_frame_type_t frame_type; /**< which reference frame */
+- vpx_image_t img; /**< reference frame data in image format */
+-} vpx_ref_frame_t;
+-
+-
+-/*!\brief vp8 decoder control funciton parameter type
+- *
+- * defines the data type for each of VP8 decoder control funciton requires
+- */
+-
+-VPX_CTRL_USE_TYPE(VP8_SET_REFERENCE, vpx_ref_frame_t *)
+-VPX_CTRL_USE_TYPE(VP8_COPY_REFERENCE, vpx_ref_frame_t *)
+-VPX_CTRL_USE_TYPE(VP8_SET_POSTPROC, vp8_postproc_cfg_t *)
+-
+-
+-/*! @} - end defgroup vp8 */
+-
+-#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
+-/* The following definitions are provided for backward compatibility with
+- * the VP8 1.0.x SDK. USE IN PRODUCTION CODE IS NOT RECOMMENDED.
+- */
+-
+-DECLSPEC_DEPRECATED extern vpx_codec_iface_t vpx_codec_vp8_algo DEPRECATED;
+-#endif
+-
+-#include "vpx_codec_impl_bottom.h"
+-#endif
+diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk
+index ec467c5..5ed53ba 100644
+--- a/vp8/vp8_common.mk
++++ b/vp8/vp8_common.mk
+@@ -1,19 +1,17 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+ #add this file to the installed sources list
+ VP8_COMMON_SRCS-yes += vp8_common.mk
+
+-#common interface
+-VP8_COMMON_SRCS-yes += vp8.h
+-
+ CFLAGS+=-I$(SRC_PATH_BARE)/$(VP8_PREFIX)common
+ VP8_COMMON_SRCS-yes += common/type_aliases.h
+ VP8_COMMON_SRCS-yes += common/pragmas.h
+diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
+index e129ec9..d63c039 100644
+--- a/vp8/vp8_cx_iface.c
++++ b/vp8/vp8_cx_iface.c
+@@ -1,18 +1,19 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+-#include "vpx_codec/vpx_codec.h"
+-#include "vpx_codec/internal/vpx_codec_internal.h"
++#include "vpx/vpx_codec.h"
++#include "vpx/internal/vpx_codec_internal.h"
+ #include "vpx_version.h"
+ #include "onyx_int.h"
+-#include "vp8e.h"
++#include "vpx/vp8e.h"
+ #include "onyx.h"
+ #include <stdlib.h>
+ #include <string.h>
+@@ -52,15 +53,15 @@ static const struct extraconfig_map extracfg_map[] =
+ NULL,
+ #if !(CONFIG_REALTIME_ONLY)
+ VP8_BEST_QUALITY_ENCODING, /* Encoding Mode */
+- -4, /* cpu_used */
++ 0, /* cpu_used */
+ #else
+ VP8_REAL_TIME_ENCODING, /* Encoding Mode */
+- -8, /* cpu_used */
++ 4, /* cpu_used */
+ #endif
+ 0, /* enable_auto_alt_ref */
+ 0, /* noise_sensitivity */
+ 0, /* Sharpness */
+- 800, /* static_thresh */
++ 0, /* static_thresh */
+ VP8_ONE_TOKENPARTITION, /* token_partitions */
+ 0, /* arnr_max_frames */
+ 0, /* arnr_strength */
+@@ -81,7 +82,7 @@ struct vpx_codec_alg_priv
+ vpx_image_t preview_img;
+ unsigned int next_frame_flag;
+ vp8_postproc_cfg_t preview_ppcfg;
+- vpx_codec_pkt_list_decl(26) pkt_list; // changed to accomendate the maximum number of lagged frames allowed
++ vpx_codec_pkt_list_decl(64) pkt_list; // changed to accomendate the maximum number of lagged frames allowed
+ int deprecated_mode;
+ unsigned int fixed_kf_cntr;
+ };
+@@ -108,7 +109,7 @@ update_error_state(vpx_codec_alg_priv_t *ctx,
+ } while(0)
+
+ #define RANGE_CHECK(p,memb,lo,hi) do {\
+- if(!((p)->memb >= (lo) && (p)->memb <= hi)) \
++ if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
+ ERROR(#memb " out of range ["#lo".."#hi"]");\
+ } while(0)
+
+@@ -211,10 +212,10 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
+ {
+ switch (img->fmt)
+ {
+- case IMG_FMT_YV12:
+- case IMG_FMT_I420:
+- case IMG_FMT_VPXI420:
+- case IMG_FMT_VPXYV12:
++ case VPX_IMG_FMT_YV12:
++ case VPX_IMG_FMT_I420:
++ case VPX_IMG_FMT_VPXI420:
++ case VPX_IMG_FMT_VPXYV12:
+ break;
+ default:
+ ERROR("Invalid image format. Only YV12 and I420 images are supported");
+@@ -536,20 +537,20 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
+ YV12_BUFFER_CONFIG *yv12)
+ {
+ vpx_codec_err_t res = VPX_CODEC_OK;
+- yv12->y_buffer = img->planes[PLANE_Y];
+- yv12->u_buffer = img->planes[PLANE_U];
+- yv12->v_buffer = img->planes[PLANE_V];
++ yv12->y_buffer = img->planes[VPX_PLANE_Y];
++ yv12->u_buffer = img->planes[VPX_PLANE_U];
++ yv12->v_buffer = img->planes[VPX_PLANE_V];
+
+ yv12->y_width = img->d_w;
+ yv12->y_height = img->d_h;
+ yv12->uv_width = (1 + yv12->y_width) / 2;
+ yv12->uv_height = (1 + yv12->y_height) / 2;
+
+- yv12->y_stride = img->stride[PLANE_Y];
+- yv12->uv_stride = img->stride[PLANE_U];
++ yv12->y_stride = img->stride[VPX_PLANE_Y];
++ yv12->uv_stride = img->stride[VPX_PLANE_U];
+
+- yv12->border = (img->stride[PLANE_Y] - img->w) / 2;
+- yv12->clrtype = (img->fmt == IMG_FMT_VPXI420 || img->fmt == IMG_FMT_VPXYV12); //REG_YUV = 0
++ yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2;
++ yv12->clrtype = (img->fmt == VPX_IMG_FMT_VPXI420 || img->fmt == VPX_IMG_FMT_VPXYV12); //REG_YUV = 0
+ return res;
+ }
+
+@@ -846,7 +847,7 @@ static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx)
+ {
+
+ /*
+- vpx_img_wrap(&ctx->preview_img, IMG_FMT_YV12,
++ vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12,
+ sd.y_width + 2*VP8BORDERINPIXELS,
+ sd.y_height + 2*VP8BORDERINPIXELS,
+ 1,
+@@ -857,23 +858,23 @@ static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx)
+ */
+
+ ctx->preview_img.bps = 12;
+- ctx->preview_img.planes[PLANE_Y] = sd.y_buffer;
+- ctx->preview_img.planes[PLANE_U] = sd.u_buffer;
+- ctx->preview_img.planes[PLANE_V] = sd.v_buffer;
++ ctx->preview_img.planes[VPX_PLANE_Y] = sd.y_buffer;
++ ctx->preview_img.planes[VPX_PLANE_U] = sd.u_buffer;
++ ctx->preview_img.planes[VPX_PLANE_V] = sd.v_buffer;
+
+ if (sd.clrtype == REG_YUV)
+- ctx->preview_img.fmt = IMG_FMT_I420;
++ ctx->preview_img.fmt = VPX_IMG_FMT_I420;
+ else
+- ctx->preview_img.fmt = IMG_FMT_VPXI420;
++ ctx->preview_img.fmt = VPX_IMG_FMT_VPXI420;
+
+ ctx->preview_img.x_chroma_shift = 1;
+ ctx->preview_img.y_chroma_shift = 1;
+
+ ctx->preview_img.d_w = ctx->cfg.g_w;
+ ctx->preview_img.d_h = ctx->cfg.g_h;
+- ctx->preview_img.stride[PLANE_Y] = sd.y_stride;
+- ctx->preview_img.stride[PLANE_U] = sd.uv_stride;
+- ctx->preview_img.stride[PLANE_V] = sd.uv_stride;
++ ctx->preview_img.stride[VPX_PLANE_Y] = sd.y_stride;
++ ctx->preview_img.stride[VPX_PLANE_U] = sd.uv_stride;
++ ctx->preview_img.stride[VPX_PLANE_V] = sd.uv_stride;
+ ctx->preview_img.w = sd.y_width;
+ ctx->preview_img.h = sd.y_height;
+
+@@ -1067,7 +1068,7 @@ static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] =
+ #endif
+ vpx_codec_iface_t vpx_codec_vp8_cx_algo =
+ {
+- "vpx Technologies VP8 Encoder" VERSION_STRING,
++ "WebM Project VP8 Encoder" VERSION_STRING,
+ VPX_CODEC_INTERNAL_ABI_VERSION,
+ VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,
+ /* vpx_codec_caps_t caps; */
+@@ -1156,7 +1157,7 @@ static vpx_codec_err_t api1_encode(vpx_codec_alg_priv_t *ctx,
+
+ vpx_codec_iface_t vpx_enc_vp8_algo =
+ {
+- "vpx Technologies VP8 Encoder (Deprecated API)" VERSION_STRING,
++ "WebM Project VP8 Encoder (Deprecated API)" VERSION_STRING,
+ VPX_CODEC_INTERNAL_ABI_VERSION,
+ VPX_CODEC_CAP_ENCODER,
+ /* vpx_codec_caps_t caps; */
+diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
+index 3e6cdf4..a99364d 100644
+--- a/vp8/vp8_dx_iface.c
++++ b/vp8/vp8_dx_iface.c
+@@ -1,18 +1,19 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+ #include <stdlib.h>
+ #include <string.h>
+-#include "vpx_codec/vpx_decoder.h"
+-#include "vp8dx.h"
+-#include "vpx_codec/internal/vpx_codec_internal.h"
++#include "vpx/vpx_decoder.h"
++#include "vpx/vp8dx.h"
++#include "vpx/internal/vpx_codec_internal.h"
+ #include "vpx_version.h"
+ #include "onyxd.h"
+ #include "onyxd_int.h"
+@@ -257,12 +258,12 @@ static vpx_codec_err_t vp8_peek_si(const uint8_t *data,
+
+ vpx_codec_err_t res = VPX_CODEC_OK;
+ {
+- /*Parse from VP8 compressed data, the implies knowledge of the
+- *VP8 bitsteam.
+- * First 3 byte header including version, frame type and an offset
+- * Next 3 bytes are image sizewith 12 bit each for width and height
++ /* Parse uncompresssed part of key frame header.
++ * 3 bytes:- including version, frame type and an offset
++ * 3 bytes:- sync code (0x9d, 0x01, 0x2a)
++ * 4 bytes:- including image width and height in the lowest 14 bits
++ * of each 2-byte value.
+ */
+-
+ si->is_kf = 0;
+
+ if (data_sz >= 10 && !(data[0] & 0x01)) /* I-Frame */
+@@ -434,7 +435,7 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
+ unsigned int a_w = (sd.y_width + 15) & ~15;
+ unsigned int a_h = (sd.y_height + 15) & ~15;
+
+- vpx_img_wrap(&ctx->img, IMG_FMT_I420,
++ vpx_img_wrap(&ctx->img, VPX_IMG_FMT_I420,
+ a_w + 2 * VP8BORDERINPIXELS,
+ a_h + 2 * VP8BORDERINPIXELS,
+ 1,
+@@ -557,20 +558,20 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
+ YV12_BUFFER_CONFIG *yv12)
+ {
+ vpx_codec_err_t res = VPX_CODEC_OK;
+- yv12->y_buffer = img->planes[PLANE_Y];
+- yv12->u_buffer = img->planes[PLANE_U];
+- yv12->v_buffer = img->planes[PLANE_V];
++ yv12->y_buffer = img->planes[VPX_PLANE_Y];
++ yv12->u_buffer = img->planes[VPX_PLANE_U];
++ yv12->v_buffer = img->planes[VPX_PLANE_V];
+
+ yv12->y_width = img->d_w;
+ yv12->y_height = img->d_h;
+ yv12->uv_width = yv12->y_width / 2;
+ yv12->uv_height = yv12->y_height / 2;
+
+- yv12->y_stride = img->stride[PLANE_Y];
+- yv12->uv_stride = img->stride[PLANE_U];
++ yv12->y_stride = img->stride[VPX_PLANE_Y];
++ yv12->uv_stride = img->stride[VPX_PLANE_U];
+
+- yv12->border = (img->stride[PLANE_Y] - img->d_w) / 2;
+- yv12->clrtype = (img->fmt == IMG_FMT_VPXI420 || img->fmt == IMG_FMT_VPXYV12);
++ yv12->border = (img->stride[VPX_PLANE_Y] - img->d_w) / 2;
++ yv12->clrtype = (img->fmt == VPX_IMG_FMT_VPXI420 || img->fmt == VPX_IMG_FMT_VPXYV12);
+
+ return res;
+ }
+@@ -656,7 +657,7 @@ vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
+ #endif
+ vpx_codec_iface_t vpx_codec_vp8_dx_algo =
+ {
+- "vpx Technologies VP8 Decoder" VERSION_STRING,
++ "WebM Project VP8 Decoder" VERSION_STRING,
+ VPX_CODEC_INTERNAL_ABI_VERSION,
+ VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC,
+ /* vpx_codec_caps_t caps; */
+@@ -679,7 +680,7 @@ vpx_codec_iface_t vpx_codec_vp8_dx_algo =
+ */
+ vpx_codec_iface_t vpx_codec_vp8_algo =
+ {
+- "vpx Technologies VP8 Decoder (Deprecated API)" VERSION_STRING,
++ "WebM Project VP8 Decoder (Deprecated API)" VERSION_STRING,
+ VPX_CODEC_INTERNAL_ABI_VERSION,
+ VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC,
+ /* vpx_codec_caps_t caps; */
+diff --git a/vp8/vp8cx.h b/vp8/vp8cx.h
+deleted file mode 100644
+index dd48c07..0000000
+--- a/vp8/vp8cx.h
++++ /dev/null
+@@ -1,261 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\defgroup vp8_encoder WebM VP8 Encoder
+- * \ingroup vp8
+- *
+- * @{
+- */
+-#include "vp8.h"
+-
+-/*!\file vp8cx.h
+- * \brief Provides definitions for using the VP8 encoder algorithm within the
+- * vpx Codec Interface.
+- */
+-#ifndef VP8CX_H
+-#define VP8CX_H
+-#include "vpx_codec_impl_top.h"
+-
+-/*!\brief Algorithm interface for VP8
+- *
+- * This interface provides the capability to encode raw VP8 streams, as would
+- * be found in AVI files.
+- */
+-extern vpx_codec_iface_t vpx_codec_vp8_cx_algo;
+-
+-
+-/*
+- * Algorithm Flags
+- */
+-
+-/*!\brief Don't reference the last frame
+- *
+- * When this flag is set, the encoder will not use the last frame as a
+- * predictor. When not set, the encoder will choose whether to use the
+- * last frame or not automatically.
+- */
+-#define VP8_EFLAG_NO_REF_LAST (1<<16)
+-
+-
+-/*!\brief Don't reference the golden frame
+- *
+- * When this flag is set, the encoder will not use the golden frame as a
+- * predictor. When not set, the encoder will choose whether to use the
+- * golden frame or not automatically.
+- */
+-#define VP8_EFLAG_NO_REF_GF (1<<17)
+-
+-
+-/*!\brief Don't reference the alternate reference frame
+- *
+- * When this flag is set, the encoder will not use the alt ref frame as a
+- * predictor. When not set, the encoder will choose whether to use the
+- * alt ref frame or not automatically.
+- */
+-#define VP8_EFLAG_NO_REF_ARF (1<<21)
+-
+-
+-/*!\brief Don't update the last frame
+- *
+- * When this flag is set, the encoder will not update the last frame with
+- * the contents of the current frame.
+- */
+-#define VP8_EFLAG_NO_UPD_LAST (1<<18)
+-
+-
+-/*!\brief Don't update the golden frame
+- *
+- * When this flag is set, the encoder will not update the golden frame with
+- * the contents of the current frame.
+- */
+-#define VP8_EFLAG_NO_UPD_GF (1<<22)
+-
+-
+-/*!\brief Don't update the alternate reference frame
+- *
+- * When this flag is set, the encoder will not update the alt ref frame with
+- * the contents of the current frame.
+- */
+-#define VP8_EFLAG_NO_UPD_ARF (1<<23)
+-
+-
+-/*!\brief Force golden frame update
+- *
+- * When this flag is set, the encoder copy the contents of the current frame
+- * to the golden frame buffer.
+- */
+-#define VP8_EFLAG_FORCE_GF (1<<19)
+-
+-
+-/*!\brief Force alternate reference frame update
+- *
+- * When this flag is set, the encoder copy the contents of the current frame
+- * to the alternate reference frame buffer.
+- */
+-#define VP8_EFLAG_FORCE_ARF (1<<24)
+-
+-
+-/*!\brief Disable entropy update
+- *
+- * When this flag is set, the encoder will not update its internal entropy
+- * model based on the entropy of this frame.
+- */
+-#define VP8_EFLAG_NO_UPD_ENTROPY (1<<20)
+-
+-
+-/*!\brief VP8 encoder control functions
+- *
+- * The set of macros define the control functions of VP8 encoder interface
+- */
+-enum vp8e_enc_control_id
+-{
+- VP8E_UPD_ENTROPY = 5, /**< control function to set mode of entropy update in encoder */
+- VP8E_UPD_REFERENCE, /**< control function to set reference update mode in encoder */
+- VP8E_USE_REFERENCE, /**< control function to set which reference frame encoder can use */
+- VP8E_SET_ROI_MAP, /**< control function to pass an ROI map to encoder */
+- VP8E_SET_ACTIVEMAP, /**< control function to pass an Active map to encoder */
+- VP8E_SET_SCALEMODE = 11, /**< control function to set encoder scaling mode */
+- VP8E_SET_CPUUSED = 13, /**< control function to set vp8 encoder cpuused */
+- VP8E_SET_ENABLEAUTOALTREF, /**< control function to enable vp8 to automatic set and use altref frame */
+- VP8E_SET_NOISE_SENSITIVITY, /**< control function to set noise sensitivity */
+- VP8E_SET_SHARPNESS, /**< control function to set sharpness */
+- VP8E_SET_STATIC_THRESHOLD, /**< control function to set the threshold for macroblocks treated static */
+- VP8E_SET_TOKEN_PARTITIONS, /**< control function to set the number of token partitions */
+- VP8E_GET_LAST_QUANTIZER, /**< return the quantizer chosen by the
+- encoder for the last frame using the internal
+- scale */
+- VP8E_GET_LAST_QUANTIZER_64, /**< return the quantizer chosen by the
+- encoder for the last frame, using the 0..63
+- scale as used by the rc_*_quantizer config
+- parameters */
+- VP8E_SET_ARNR_MAXFRAMES, /**< control function to set the max number of frames blurred creating arf*/
+- VP8E_SET_ARNR_STRENGTH , /**< control function to set the filter strength for the arf */
+- VP8E_SET_ARNR_TYPE , /**< control function to set the type of filter to use for the arf*/
+-} ;
+-
+-/*!\brief vpx 1-D scaling mode
+- *
+- * This set of constants define 1-D vpx scaling modes
+- */
+-typedef enum vpx_scaling_mode_1d
+-{
+- VP8E_NORMAL = 0,
+- VP8E_FOURFIVE = 1,
+- VP8E_THREEFIVE = 2,
+- VP8E_ONETWO = 3
+-} VPX_SCALING_MODE;
+-
+-
+-/*!\brief vpx region of interest map
+- *
+- * These defines the data structures for the region of interest map
+- *
+- */
+-
+-typedef struct vpx_roi_map
+-{
+- unsigned char *roi_map; /**< specify an id between 0 and 3 for each 16x16 region within a frame */
+- unsigned int rows; /**< number of rows */
+- unsigned int cols; /**< number of cols */
+- int delta_q[4]; /**< quantizer delta [-64, 64] off baseline for regions with id between 0 and 3*/
+- int delta_lf[4]; /**< loop filter strength delta [-32, 32] for regions with id between 0 and 3 */
+- unsigned int static_threshold[4];/**< threshold for region to be treated as static */
+-} vpx_roi_map_t;
+-
+-/*!\brief vpx active region map
+- *
+- * These defines the data structures for active region map
+- *
+- */
+-
+-
+-typedef struct vpx_active_map
+-{
+- unsigned char *active_map; /**< specify an on (1) or off (0) each 16x16 region within a frame */
+- unsigned int rows; /**< number of rows */
+- unsigned int cols; /**< number of cols */
+-} vpx_active_map_t;
+-
+-/*!\brief vpx image scaling mode
+- *
+- * This defines the data structure for image scaling mode
+- *
+- */
+-typedef struct vpx_scaling_mode
+-{
+- VPX_SCALING_MODE h_scaling_mode; /**< horizontal scaling mode */
+- VPX_SCALING_MODE v_scaling_mode; /**< vertical scaling mode */
+-} vpx_scaling_mode_t;
+-
+-/*!\brief VP8 encoding mode
+- *
+- * This defines VP8 encoding mode
+- *
+- */
+-typedef enum
+-{
+- VP8_BEST_QUALITY_ENCODING,
+- VP8_GOOD_QUALITY_ENCODING,
+- VP8_REAL_TIME_ENCODING
+-} vp8e_encoding_mode;
+-
+-/*!\brief VP8 token partition mode
+- *
+- * This defines VP8 partitioning mode for compressed data, i.e., the number of
+- * sub-streams in the bitstream. Used for parallelized decoding.
+- *
+- */
+-
+-typedef enum
+-{
+- VP8_ONE_TOKENPARTITION = 0,
+- VP8_TWO_TOKENPARTITION = 1,
+- VP8_FOUR_TOKENPARTITION = 2,
+- VP8_EIGHT_TOKENPARTITION = 3,
+-} vp8e_token_partitions;
+-
+-
+-/*!\brief VP8 encoder control function parameter type
+- *
+- * Defines the data types that VP8E control functions take. Note that
+- * additional common controls are defined in vp8.h
+- *
+- */
+-
+-
+-/* These controls have been deprecated in favor of the flags parameter to
+- * vpx_codec_encode(). See the definition of VP8_EFLAG_* above.
+- */
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_ENTROPY, int)
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_REFERENCE, int)
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_USE_REFERENCE, int)
+-
+-VPX_CTRL_USE_TYPE(VP8E_SET_ROI_MAP, vpx_roi_map_t *)
+-VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP, vpx_active_map_t *)
+-VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE, vpx_scaling_mode_t *)
+-
+-VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED, int)
+-VPX_CTRL_USE_TYPE(VP8E_SET_ENABLEAUTOALTREF, unsigned int)
+-VPX_CTRL_USE_TYPE(VP8E_SET_NOISE_SENSITIVITY, unsigned int)
+-VPX_CTRL_USE_TYPE(VP8E_SET_SHARPNESS, unsigned int)
+-VPX_CTRL_USE_TYPE(VP8E_SET_STATIC_THRESHOLD, unsigned int)
+-VPX_CTRL_USE_TYPE(VP8E_SET_TOKEN_PARTITIONS, vp8e_token_partitions)
+-
+-VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_MAXFRAMES, unsigned int)
+-VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_STRENGTH , unsigned int)
+-VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_TYPE , unsigned int)
+-
+-
+-VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER, int *)
+-VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64, int *)
+-
+-/*! @} - end defgroup vp8_encoder */
+-#include "vpx_codec_impl_bottom.h"
+-#endif
+diff --git a/vp8/vp8cx.mk b/vp8/vp8cx.mk
+index e7e7663..971a175 100644
+--- a/vp8/vp8cx.mk
++++ b/vp8/vp8cx.mk
+@@ -1,14 +1,18 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+ include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk
++
++VP8_CX_EXPORTS += exports_enc
++
+ VP8_CX_SRCS-yes += $(VP8_COMMON_SRCS-yes)
+ VP8_CX_SRCS-no += $(VP8_COMMON_SRCS-no)
+ VP8_CX_SRCS_REMOVE-yes += $(VP8_COMMON_SRCS_REMOVE-yes)
+@@ -18,7 +22,7 @@ ifeq ($(ARCH_ARM),yes)
+ include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8cx_arm.mk
+ endif
+
+-VP8_CX_SRCS-yes += vp8cx.h vp8e.h vp8_cx_iface.c
++VP8_CX_SRCS-yes += vp8_cx_iface.c
+
+ # encoder
+ #INCLUDES += algo/vpx_common/vpx_mem/include
+@@ -70,7 +74,7 @@ VP8_CX_SRCS-yes += encoder/quantize.c
+ VP8_CX_SRCS-yes += encoder/ratectrl.c
+ VP8_CX_SRCS-yes += encoder/rdopt.c
+ VP8_CX_SRCS-yes += encoder/sad_c.c
+-VP8_CX_SRCS-yes += encoder/ssim.c
++VP8_CX_SRCS-$(CONFIG_PSNR) += encoder/ssim.c
+ VP8_CX_SRCS-yes += encoder/tokenize.c
+ VP8_CX_SRCS-yes += encoder/treewriter.c
+ VP8_CX_SRCS-yes += encoder/variance_c.c
+@@ -94,11 +98,10 @@ VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/variance_impl_sse2.asm
+ VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/sad_sse2.asm
+ VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/dct_sse2.asm
+ VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/fwalsh_sse2.asm
++VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/quantize_sse2.asm
+ VP8_CX_SRCS-$(HAVE_SSE3) += encoder/x86/sad_sse3.asm
+ VP8_CX_SRCS-$(HAVE_SSSE3) += encoder/x86/sad_ssse3.asm
+ VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/quantize_mmx.asm
+ VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/encodeopt.asm
+
+ VP8_CX_SRCS-yes := $(filter-out $(VP8_CX_SRCS_REMOVE-yes),$(VP8_CX_SRCS-yes))
+-
+-INSTALL-LIBS-yes += include/vp8.h include/vp8e.h include/vp8cx.h
+diff --git a/vp8/vp8cx_arm.mk b/vp8/vp8cx_arm.mk
+index f0753d9..16009f9 100644
+--- a/vp8/vp8cx_arm.mk
++++ b/vp8/vp8cx_arm.mk
+@@ -1,10 +1,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/vp8/vp8dx.h b/vp8/vp8dx.h
+deleted file mode 100644
+index 7310b3b..0000000
+--- a/vp8/vp8dx.h
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-#include "vp8.h"
+-
+-/*!\defgroup vp8_decoder WebM VP8 Decoder
+- * \ingroup vp8
+- *
+- * @{
+- */
+-/*!\file vp8dx.h
+- * \brief Provides definitions for using the VP8 algorithm within the vpx Decoder
+- * interface.
+- */
+-#ifndef VP8DX_H
+-#define VP8DX_H
+-#include "vpx_codec_impl_top.h"
+-
+-/*!\brief Algorithm interface for VP8
+- *
+- * This interface provides the capability to decode raw VP8 streams, as would
+- * be found in AVI files and other non-Flash uses.
+- */
+-extern vpx_codec_iface_t vpx_codec_vp8_dx_algo;
+-
+-/* Include controls common to both the encoder and decoder */
+-#include "vp8.h"
+-
+-
+-/*! @} - end defgroup vp8_decoder */
+-
+-
+-#include "vpx_codec_impl_bottom.h"
+-#endif
+diff --git a/vp8/vp8dx.mk b/vp8/vp8dx.mk
+index e6af543..24f18b7 100644
+--- a/vp8/vp8dx.mk
++++ b/vp8/vp8dx.mk
+@@ -1,14 +1,18 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+ include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk
++
++VP8_DX_EXPORTS += exports_dec
++
+ VP8_DX_SRCS-yes += $(VP8_COMMON_SRCS-yes)
+ VP8_DX_SRCS-no += $(VP8_COMMON_SRCS-no)
+ VP8_DX_SRCS_REMOVE-yes += $(VP8_COMMON_SRCS_REMOVE-yes)
+@@ -18,7 +22,7 @@ ifeq ($(ARCH_ARM),yes)
+ include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8dx_arm.mk
+ endif
+
+-VP8_DX_SRCS-yes += vp8dx.h vp8_dx_iface.c
++VP8_DX_SRCS-yes += vp8_dx_iface.c
+
+ CFLAGS+=-I$(SRC_PATH_BARE)/$(VP8_PREFIX)decoder
+
+@@ -69,8 +73,6 @@ VP8_DX_SRCS-yes += decoder/threading.c
+
+ VP8_DX_SRCS-yes := $(filter-out $(VP8_DX_SRCS_REMOVE-yes),$(VP8_DX_SRCS-yes))
+
+-INSTALL-LIBS-yes += include/vp8.h include/vp8dx.h
+-
+ VP8_DX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += decoder/x86/dequantize_x86.h
+ VP8_DX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += decoder/x86/x86_dsystemdependent.c
+ VP8_DX_SRCS-$(HAVE_MMX) += decoder/x86/dequantize_mmx.asm
+diff --git a/vp8/vp8dx_arm.mk b/vp8/vp8dx_arm.mk
+index 1b4a7ec..58ccac5 100644
+--- a/vp8/vp8dx_arm.mk
++++ b/vp8/vp8dx_arm.mk
+@@ -1,10 +1,11 @@
+ ##
+ ## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
+ ##
+
+
+diff --git a/vp8/vp8e.h b/vp8/vp8e.h
+deleted file mode 100644
+index a90aa2a..0000000
+--- a/vp8/vp8e.h
++++ /dev/null
+@@ -1,62 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/* This file contains backwards compatibility stubs for applications using
+- * the VP8 version 1.0 API.
+- */
+-#ifndef VP8E_H
+-#define VP8E_H
+-#include "vpx_codec_impl_top.h"
+-
+-#if defined(VPX_CODEC_DISABLE_COMPAT) && VPX_CODEC_DISABLE_COMPAT
+-#error "Backwards compatibility disabled: don't include vp8e.h"
+-#endif
+-
+-#include "vp8cx.h"
+-DECLSPEC_DEPRECATED extern vpx_codec_iface_t vpx_enc_vp8_algo DEPRECATED;
+-
+-
+-enum
+-{
+- VP8E_SET_REFERENCE = VP8_SET_REFERENCE,
+- VP8E_COPY_REFERENCE = VP8_COPY_REFERENCE,
+- VP8E_SET_PREVIEWPP = VP8_SET_POSTPROC,
+- VP8E_SET_FLUSHFLAG = 4,
+- VP8E_SET_FRAMETYPE = 10,
+- VP8E_SET_ENCODING_MODE = 12
+-};
+-
+-#define NORMAL_FRAME (0)
+-#define KEY_FRAME (1)
+-
+-/* Change VP8E to VP8 to get the undeprecated version of these (defined in
+- * vp8.h)
+- */
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_REFERENCE, vpx_ref_frame_t *)
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_COPY_REFERENCE, vpx_ref_frame_t *)
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_PREVIEWPP, vp8_postproc_cfg_t *)
+-
+-
+-/* Flush is done by calling vpx_codec_encode with a NULL input image. */
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_FLUSHFLAG, int)
+-
+-
+-/* Frame type is set with a flag to vpx_codec_control. See VPX_EFLAG_FORCE_KF
+- */
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_FRAMETYPE, int)
+-
+-
+-/* This control has been deprecated in favor of the duration parameter to
+- * vpx_codec_encode(). Use the #VPX_DL_REALTIME, #VPX_DL_GOOD_QUALITY,
+- * #VPX_DL_BEST_QUALITY constants to that parameter instead.
+- */
+-VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_ENCODING_MODE, vp8e_encoding_mode)
+-#include "vpx_codec_impl_bottom.h"
+-#endif
+diff --git a/vpx/exports_com b/vpx/exports_com
+new file mode 100644
+index 0000000..2ab0509
+--- /dev/null
++++ b/vpx/exports_com
+@@ -0,0 +1,16 @@
++text vpx_codec_build_config
++text vpx_codec_control_
++text vpx_codec_destroy
++text vpx_codec_err_to_string
++text vpx_codec_error
++text vpx_codec_error_detail
++text vpx_codec_get_caps
++text vpx_codec_iface_name
++text vpx_codec_version
++text vpx_codec_version_extra_str
++text vpx_codec_version_str
++text vpx_img_alloc
++text vpx_img_flip
++text vpx_img_free
++text vpx_img_set_rect
++text vpx_img_wrap
+diff --git a/vpx/exports_dec b/vpx/exports_dec
+new file mode 100644
+index 0000000..ed121f7
+--- /dev/null
++++ b/vpx/exports_dec
+@@ -0,0 +1,9 @@
++text vpx_codec_dec_init_ver
++text vpx_codec_decode
++text vpx_codec_get_frame
++text vpx_codec_get_mem_map
++text vpx_codec_get_stream_info
++text vpx_codec_peek_stream_info
++text vpx_codec_register_put_frame_cb
++text vpx_codec_register_put_slice_cb
++text vpx_codec_set_mem_map
+diff --git a/vpx/exports_enc b/vpx/exports_enc
+new file mode 100644
+index 0000000..3d56749
+--- /dev/null
++++ b/vpx/exports_enc
+@@ -0,0 +1,8 @@
++text vpx_codec_enc_config_default
++text vpx_codec_enc_config_set
++text vpx_codec_enc_init_ver
++text vpx_codec_encode
++text vpx_codec_get_cx_data
++text vpx_codec_get_global_headers
++text vpx_codec_get_preview_frame
++text vpx_codec_set_cx_data_buf
+diff --git a/vpx/internal/vpx_codec_internal.h b/vpx/internal/vpx_codec_internal.h
+new file mode 100644
+index 0000000..c653cc5
+--- /dev/null
++++ b/vpx/internal/vpx_codec_internal.h
+@@ -0,0 +1,457 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\file decoder_impl.h
++ * \brief Describes the decoder algorithm interface for algorithm
++ * implementations.
++ *
++ * This file defines the private structures and data types that are only
++ * relevant to implementing an algorithm, as opposed to using it.
++ *
++ * To create a decoder algorithm class, an interface structure is put
++ * into the global namespace:
++ * <pre>
++ * my_codec.c:
++ * vpx_codec_iface_t my_codec = {
++ * "My Codec v1.0",
++ * VPX_CODEC_ALG_ABI_VERSION,
++ * ...
++ * };
++ * </pre>
++ *
++ * An application instantiates a specific decoder instance by using
++ * vpx_codec_init() and a pointer to the algorithm's interface structure:
++ * <pre>
++ * my_app.c:
++ * extern vpx_codec_iface_t my_codec;
++ * {
++ * vpx_codec_ctx_t algo;
++ * res = vpx_codec_init(&algo, &my_codec);
++ * }
++ * </pre>
++ *
++ * Once initialized, the instance is manged using other functions from
++ * the vpx_codec_* family.
++ */
++#ifndef VPX_CODEC_INTERNAL_H
++#define VPX_CODEC_INTERNAL_H
++#include "../vpx_decoder.h"
++#include "../vpx_encoder.h"
++#include <stdarg.h>
++
++
++/*!\brief Current ABI version number
++ *
++ * \internal
++ * If this file is altered in any way that changes the ABI, this value
++ * must be bumped. Examples include, but are not limited to, changing
++ * types, removing or reassigning enums, adding/removing/rearranging
++ * fields to structures
++ */
++#define VPX_CODEC_INTERNAL_ABI_VERSION (3) /**<\hideinitializer*/
++
++typedef struct vpx_codec_alg_priv vpx_codec_alg_priv_t;
++
++/*!\brief init function pointer prototype
++ *
++ * Performs algorithm-specific initialization of the decoder context. This
++ * function is called by the generic vpx_codec_init() wrapper function, so
++ * plugins implementing this interface may trust the input parameters to be
++ * properly initialized.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \retval #VPX_CODEC_OK
++ * The input stream was recognized and decoder initialized.
++ * \retval #VPX_CODEC_MEM_ERROR
++ * Memory operation failed.
++ */
++typedef vpx_codec_err_t (*vpx_codec_init_fn_t)(vpx_codec_ctx_t *ctx);
++
++/*!\brief destroy function pointer prototype
++ *
++ * Performs algorithm-specific destruction of the decoder context. This
++ * function is called by the generic vpx_codec_destroy() wrapper function,
++ * so plugins implementing this interface may trust the input parameters
++ * to be properly initialized.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \retval #VPX_CODEC_OK
++ * The input stream was recognized and decoder initialized.
++ * \retval #VPX_CODEC_MEM_ERROR
++ * Memory operation failed.
++ */
++typedef vpx_codec_err_t (*vpx_codec_destroy_fn_t)(vpx_codec_alg_priv_t *ctx);
++
++/*!\brief parse stream info function pointer prototype
++ *
++ * Performs high level parsing of the bitstream. This function is called by
++ * the generic vpx_codec_parse_stream() wrapper function, so plugins implementing
++ * this interface may trust the input parameters to be properly initialized.
++ *
++ * \param[in] data Pointer to a block of data to parse
++ * \param[in] data_sz Size of the data buffer
++ * \param[in,out] si Pointer to stream info to update. The size member
++ * \ref MUST be properly initialized, but \ref MAY be
++ * clobbered by the algorithm. This parameter \ref MAY
++ * be NULL.
++ *
++ * \retval #VPX_CODEC_OK
++ * Bitstream is parsable and stream information updated
++ */
++typedef vpx_codec_err_t (*vpx_codec_peek_si_fn_t)(const uint8_t *data,
++ unsigned int data_sz,
++ vpx_codec_stream_info_t *si);
++
++/*!\brief Return information about the current stream.
++ *
++ * Returns information about the stream that has been parsed during decoding.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in,out] si Pointer to stream info to update. The size member
++ * \ref MUST be properly initialized, but \ref MAY be
++ * clobbered by the algorithm. This parameter \ref MAY
++ * be NULL.
++ *
++ * \retval #VPX_CODEC_OK
++ * Bitstream is parsable and stream information updated
++ */
++typedef vpx_codec_err_t (*vpx_codec_get_si_fn_t)(vpx_codec_alg_priv_t *ctx,
++ vpx_codec_stream_info_t *si);
++
++/*!\brief control function pointer prototype
++ *
++ * This function is used to exchange algorithm specific data with the decoder
++ * instance. This can be used to implement features specific to a particular
++ * algorithm.
++ *
++ * This function is called by the generic vpx_codec_control() wrapper
++ * function, so plugins implementing this interface may trust the input
++ * parameters to be properly initialized. However, this interface does not
++ * provide type safety for the exchanged data or assign meanings to the
++ * control codes. Those details should be specified in the algorithm's
++ * header file. In particular, the ctrl_id parameter is guaranteed to exist
++ * in the algorithm's control mapping table, and the data paramter may be NULL.
++ *
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] ctrl_id Algorithm specific control identifier
++ * \param[in,out] data Data to exchange with algorithm instance.
++ *
++ * \retval #VPX_CODEC_OK
++ * The internal state data was deserialized.
++ */
++typedef vpx_codec_err_t (*vpx_codec_control_fn_t)(vpx_codec_alg_priv_t *ctx,
++ int ctrl_id,
++ va_list ap);
++
++/*!\brief control function pointer mapping
++ *
++ * This structure stores the mapping between control identifiers and
++ * implementing functions. Each algorithm provides a list of these
++ * mappings. This list is searched by the vpx_codec_control() wrapper
++ * function to determine which function to invoke. The special
++ * value {0, NULL} is used to indicate end-of-list, and must be
++ * present. The special value {0, <non-null>} can be used as a catch-all
++ * mapping. This implies that ctrl_id values chosen by the algorithm
++ * \ref MUST be non-zero.
++ */
++typedef const struct
++{
++ int ctrl_id;
++ vpx_codec_control_fn_t fn;
++} vpx_codec_ctrl_fn_map_t;
++
++/*!\brief decode data function pointer prototype
++ *
++ * Processes a buffer of coded data. If the processing results in a new
++ * decoded frame becoming available, #VPX_CODEC_CB_PUT_SLICE and
++ * #VPX_CODEC_CB_PUT_FRAME events are generated as appropriate. This
++ * function is called by the generic vpx_codec_decode() wrapper function,
++ * so plugins implementing this interface may trust the input parameters
++ * to be properly initialized.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] data Pointer to this block of new coded data. If
++ * NULL, a #VPX_CODEC_CB_PUT_FRAME event is posted
++ * for the previously decoded frame.
++ * \param[in] data_sz Size of the coded data, in bytes.
++ *
++ * \return Returns #VPX_CODEC_OK if the coded data was processed completely
++ * and future pictures can be decoded without error. Otherwise,
++ * see the descriptions of the other error codes in ::vpx_codec_err_t
++ * for recoverability capabilities.
++ */
++typedef vpx_codec_err_t (*vpx_codec_decode_fn_t)(vpx_codec_alg_priv_t *ctx,
++ const uint8_t *data,
++ unsigned int data_sz,
++ void *user_priv,
++ long deadline);
++
++/*!\brief Decoded frames iterator
++ *
++ * Iterates over a list of the frames available for display. The iterator
++ * storage should be initialized to NULL to start the iteration. Iteration is
++ * complete when this function returns NULL.
++ *
++ * The list of available frames becomes valid upon completion of the
++ * vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in out] iter Iterator storage, initialized to NULL
++ *
++ * \return Returns a pointer to an image, if one is ready for display. Frames
++ * produced will always be in PTS (presentation time stamp) order.
++ */
++typedef vpx_image_t*(*vpx_codec_get_frame_fn_t)(vpx_codec_alg_priv_t *ctx,
++ vpx_codec_iter_t *iter);
++
++
++/*\brief e_xternal Memory Allocation memory map get iterator
++ *
++ * Iterates over a list of the memory maps requested by the decoder. The
++ * iterator storage should be initialized to NULL to start the iteration.
++ * Iteration is complete when this function returns NULL.
++ *
++ * \param[in out] iter Iterator storage, initialized to NULL
++ *
++ * \return Returns a pointer to an memory segment descriptor, or NULL to
++ * indicate end-of-list.
++ */
++typedef vpx_codec_err_t (*vpx_codec_get_mmap_fn_t)(const vpx_codec_ctx_t *ctx,
++ vpx_codec_mmap_t *mmap,
++ vpx_codec_iter_t *iter);
++
++
++/*\brief e_xternal Memory Allocation memory map set iterator
++ *
++ * Sets a memory descriptor inside the decoder instance.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] mmap Memory map to store.
++ *
++ * \retval #VPX_CODEC_OK
++ * The memory map was accepted and stored.
++ * \retval #VPX_CODEC_MEM_ERROR
++ * The memory map was rejected.
++ */
++typedef vpx_codec_err_t (*vpx_codec_set_mmap_fn_t)(vpx_codec_ctx_t *ctx,
++ const vpx_codec_mmap_t *mmap);
++
++
++typedef vpx_codec_err_t (*vpx_codec_encode_fn_t)(vpx_codec_alg_priv_t *ctx,
++ const vpx_image_t *img,
++ vpx_codec_pts_t pts,
++ unsigned long duration,
++ vpx_enc_frame_flags_t flags,
++ unsigned long deadline);
++typedef const vpx_codec_cx_pkt_t*(*vpx_codec_get_cx_data_fn_t)(vpx_codec_alg_priv_t *ctx,
++ vpx_codec_iter_t *iter);
++
++typedef vpx_codec_err_t
++(*vpx_codec_enc_config_set_fn_t)(vpx_codec_alg_priv_t *ctx,
++ const vpx_codec_enc_cfg_t *cfg);
++typedef vpx_fixed_buf_t *
++(*vpx_codec_get_global_headers_fn_t)(vpx_codec_alg_priv_t *ctx);
++
++typedef vpx_image_t *
++(*vpx_codec_get_preview_frame_fn_t)(vpx_codec_alg_priv_t *ctx);
++
++/*!\brief usage configuration mapping
++ *
++ * This structure stores the mapping between usage identifiers and
++ * configuration structures. Each algorithm provides a list of these
++ * mappings. This list is searched by the vpx_codec_enc_config_default()
++ * wrapper function to determine which config to return. The special value
++ * {-1, {0}} is used to indicate end-of-list, and must be present. At least
++ * one mapping must be present, in addition to the end-of-list.
++ *
++ */
++typedef const struct
++{
++ int usage;
++ vpx_codec_enc_cfg_t cfg;
++} vpx_codec_enc_cfg_map_t;
++
++#define NOT_IMPLEMENTED 0
++
++/*!\brief Decoder algorithm interface interface
++ *
++ * All decoders \ref MUST expose a variable of this type.
++ */
++struct vpx_codec_iface
++{
++ const char *name; /**< Identification String */
++ int abi_version; /**< Implemented ABI version */
++ vpx_codec_caps_t caps; /**< Decoder capabilities */
++ vpx_codec_init_fn_t init; /**< \copydoc ::vpx_codec_init_fn_t */
++ vpx_codec_destroy_fn_t destroy; /**< \copydoc ::vpx_codec_destroy_fn_t */
++ vpx_codec_ctrl_fn_map_t *ctrl_maps; /**< \copydoc ::vpx_codec_ctrl_fn_map_t */
++ vpx_codec_get_mmap_fn_t get_mmap; /**< \copydoc ::vpx_codec_get_mmap_fn_t */
++ vpx_codec_set_mmap_fn_t set_mmap; /**< \copydoc ::vpx_codec_set_mmap_fn_t */
++ struct
++ {
++ vpx_codec_peek_si_fn_t peek_si; /**< \copydoc ::vpx_codec_peek_si_fn_t */
++ vpx_codec_get_si_fn_t get_si; /**< \copydoc ::vpx_codec_peek_si_fn_t */
++ vpx_codec_decode_fn_t decode; /**< \copydoc ::vpx_codec_decode_fn_t */
++ vpx_codec_get_frame_fn_t get_frame; /**< \copydoc ::vpx_codec_get_frame_fn_t */
++ } dec;
++ struct
++ {
++ vpx_codec_enc_cfg_map_t *cfg_maps; /**< \copydoc ::vpx_codec_enc_cfg_map_t */
++ vpx_codec_encode_fn_t encode; /**< \copydoc ::vpx_codec_encode_fn_t */
++ vpx_codec_get_cx_data_fn_t get_cx_data; /**< \copydoc ::vpx_codec_get_cx_data_fn_t */
++ vpx_codec_enc_config_set_fn_t cfg_set; /**< \copydoc ::vpx_codec_enc_config_set_fn_t */
++ vpx_codec_get_global_headers_fn_t get_glob_hdrs; /**< \copydoc ::vpx_codec_enc_config_set_fn_t */
++ vpx_codec_get_preview_frame_fn_t get_preview; /**< \copydoc ::vpx_codec_get_preview_frame_fn_t */
++ } enc;
++};
++
++/*!\brief Callback function pointer / user data pair storage */
++typedef struct vpx_codec_priv_cb_pair
++{
++ union
++ {
++ vpx_codec_put_frame_cb_fn_t put_frame;
++ vpx_codec_put_slice_cb_fn_t put_slice;
++ };
++ void *user_priv;
++} vpx_codec_priv_cb_pair_t;
++
++
++/*!\brief Instance private storage
++ *
++ * This structure is allocated by the algorithm's init function. It can be
++ * extended in one of two ways. First, a second, algorithm specific structure
++ * can be allocated and the priv member pointed to it. Alternatively, this
++ * structure can be made the first member of the algorithm specific structure,
++ * and the pointer casted to the proper type.
++ */
++struct vpx_codec_priv
++{
++ unsigned int sz;
++ vpx_codec_iface_t *iface;
++ struct vpx_codec_alg_priv *alg_priv;
++ const char *err_detail;
++ vpx_codec_flags_t init_flags;
++ struct
++ {
++ vpx_codec_priv_cb_pair_t put_frame_cb;
++ vpx_codec_priv_cb_pair_t put_slice_cb;
++ } dec;
++ struct
++ {
++ int tbd;
++ struct vpx_fixed_buf cx_data_dst_buf;
++ unsigned int cx_data_pad_before;
++ unsigned int cx_data_pad_after;
++ vpx_codec_cx_pkt_t cx_data_pkt;
++ } enc;
++};
++
++#undef VPX_CTRL_USE_TYPE
++#define VPX_CTRL_USE_TYPE(id, typ) \
++ static typ id##__value(va_list args) {return va_arg(args, typ);} \
++ static typ id##__convert(void *x)\
++ {\
++ union\
++ {\
++ void *x;\
++ typ d;\
++ } u;\
++ u.x = x;\
++ return u.d;\
++ }
++
++
++#undef VPX_CTRL_USE_TYPE_DEPRECATED
++#define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
++ static typ id##__value(va_list args) {return va_arg(args, typ);} \
++ static typ id##__convert(void *x)\
++ {\
++ union\
++ {\
++ void *x;\
++ typ d;\
++ } u;\
++ u.x = x;\
++ return u.d;\
++ }
++
++#define CAST(id, arg) id##__value(arg)
++#define RECAST(id, x) id##__convert(x)
++
++
++/* Internal Utility Functions
++ *
++ * The following functions are indended to be used inside algorithms as
++ * utilities for manipulating vpx_codec_* data structures.
++ */
++struct vpx_codec_pkt_list
++{
++ unsigned int cnt;
++ unsigned int max;
++ struct vpx_codec_cx_pkt pkts[1];
++};
++
++#define vpx_codec_pkt_list_decl(n)\
++ union {struct vpx_codec_pkt_list head;\
++ struct {struct vpx_codec_pkt_list head;\
++ struct vpx_codec_cx_pkt pkts[n];} alloc;}
++
++#define vpx_codec_pkt_list_init(m)\
++ (m)->alloc.head.cnt = 0,\
++ (m)->alloc.head.max = sizeof((m)->alloc.pkts) / sizeof((m)->alloc.pkts[0])
++
++int
++vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *,
++ const struct vpx_codec_cx_pkt *);
++
++const vpx_codec_cx_pkt_t*
++vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
++ vpx_codec_iter_t *iter);
++
++
++#include <stdio.h>
++#include <setjmp.h>
++struct vpx_internal_error_info
++{
++ vpx_codec_err_t error_code;
++ int has_detail;
++ char detail[80];
++ int setjmp;
++ jmp_buf jmp;
++};
++
++static void vpx_internal_error(struct vpx_internal_error_info *info,
++ vpx_codec_err_t error,
++ const char *fmt,
++ ...)
++{
++ va_list ap;
++
++ info->error_code = error;
++ info->has_detail = 0;
++
++ if (fmt)
++ {
++ size_t sz = sizeof(info->detail);
++
++ info->has_detail = 1;
++ va_start(ap, fmt);
++ vsnprintf(info->detail, sz - 1, fmt, ap);
++ va_end(ap);
++ info->detail[sz-1] = '\0';
++ }
++
++ if (info->setjmp)
++ longjmp(info->jmp, info->error_code);
++}
++#endif
+diff --git a/vpx/src/vpx_codec.c b/vpx/src/vpx_codec.c
+new file mode 100644
+index 0000000..0ef3a7b
+--- /dev/null
++++ b/vpx/src/vpx_codec.c
+@@ -0,0 +1,150 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\file vpx_decoder.c
++ * \brief Provides the high level interface to wrap decoder algorithms.
++ *
++ */
++#include <stdarg.h>
++#include "vpx/vpx_integer.h"
++#include "vpx/internal/vpx_codec_internal.h"
++#include "vpx_version.h"
++
++#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
++
++int vpx_codec_version(void)
++{
++ return VERSION_PACKED;
++}
++
++
++const char *vpx_codec_version_str(void)
++{
++ return VERSION_STRING_NOSP;
++}
++
++
++const char *vpx_codec_version_extra_str(void)
++{
++ return VERSION_EXTRA;
++}
++
++
++const char *vpx_codec_iface_name(vpx_codec_iface_t *iface)
++{
++ return iface ? iface->name : "<invalid interface>";
++}
++
++const char *vpx_codec_err_to_string(vpx_codec_err_t err)
++{
++ switch (err)
++ {
++ case VPX_CODEC_OK:
++ return "Success";
++ case VPX_CODEC_ERROR:
++ return "Unspecified internal error";
++ case VPX_CODEC_MEM_ERROR:
++ return "Memory allocation error";
++ case VPX_CODEC_ABI_MISMATCH:
++ return "ABI version mismatch";
++ case VPX_CODEC_INCAPABLE:
++ return "Codec does not implement requested capability";
++ case VPX_CODEC_UNSUP_BITSTREAM:
++ return "Bitstream not supported by this decoder";
++ case VPX_CODEC_UNSUP_FEATURE:
++ return "Bitstream required feature not supported by this decoder";
++ case VPX_CODEC_CORRUPT_FRAME:
++ return "Corrupt frame detected";
++ case VPX_CODEC_INVALID_PARAM:
++ return "Invalid parameter";
++ case VPX_CODEC_LIST_END:
++ return "End of iterated list";
++ }
++
++ return "Unrecognized error code";
++}
++
++const char *vpx_codec_error(vpx_codec_ctx_t *ctx)
++{
++ return (ctx) ? vpx_codec_err_to_string(ctx->err)
++ : vpx_codec_err_to_string(VPX_CODEC_INVALID_PARAM);
++}
++
++const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx)
++{
++ if (ctx && ctx->err)
++ return ctx->priv ? ctx->priv->err_detail : ctx->err_detail;
++
++ return NULL;
++}
++
++
++vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx)
++{
++ vpx_codec_err_t res;
++
++ if (!ctx)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!ctx->iface || !ctx->priv)
++ res = VPX_CODEC_ERROR;
++ else
++ {
++ if (ctx->priv->alg_priv)
++ ctx->iface->destroy(ctx->priv->alg_priv);
++
++ ctx->iface = NULL;
++ ctx->name = NULL;
++ ctx->priv = NULL;
++ res = VPX_CODEC_OK;
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface)
++{
++ return (iface) ? iface->caps : 0;
++}
++
++
++vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx,
++ int ctrl_id,
++ ...)
++{
++ vpx_codec_err_t res;
++
++ if (!ctx || !ctrl_id)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!ctx->iface || !ctx->priv || !ctx->iface->ctrl_maps)
++ res = VPX_CODEC_ERROR;
++ else
++ {
++ vpx_codec_ctrl_fn_map_t *entry;
++
++ res = VPX_CODEC_ERROR;
++
++ for (entry = ctx->iface->ctrl_maps; entry && entry->fn; entry++)
++ {
++ if (!entry->ctrl_id || entry->ctrl_id == ctrl_id)
++ {
++ va_list ap;
++
++ va_start(ap, ctrl_id);
++ res = entry->fn(ctx->priv->alg_priv, ctrl_id, ap);
++ va_end(ap);
++ break;
++ }
++ }
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
+diff --git a/vpx/src/vpx_decoder.c b/vpx/src/vpx_decoder.c
+new file mode 100644
+index 0000000..cbf5259
+--- /dev/null
++++ b/vpx/src/vpx_decoder.c
+@@ -0,0 +1,237 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\file vpx_decoder.c
++ * \brief Provides the high level interface to wrap decoder algorithms.
++ *
++ */
++#include <string.h>
++#include "vpx/internal/vpx_codec_internal.h"
++
++#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
++
++vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx,
++ vpx_codec_iface_t *iface,
++ vpx_codec_dec_cfg_t *cfg,
++ vpx_codec_flags_t flags,
++ int ver)
++{
++ vpx_codec_err_t res;
++
++ if (ver != VPX_DECODER_ABI_VERSION)
++ res = VPX_CODEC_ABI_MISMATCH;
++ else if (!ctx || !iface)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
++ res = VPX_CODEC_ABI_MISMATCH;
++ else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
++ res = VPX_CODEC_INCAPABLE;
++ else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC))
++ res = VPX_CODEC_INCAPABLE;
++ else
++ {
++ memset(ctx, 0, sizeof(*ctx));
++ ctx->iface = iface;
++ ctx->name = iface->name;
++ ctx->priv = NULL;
++ ctx->init_flags = flags;
++ ctx->config.dec = cfg;
++ res = VPX_CODEC_OK;
++
++ if (!(flags & VPX_CODEC_USE_XMA))
++ {
++ res = ctx->iface->init(ctx);
++
++ if (res)
++ {
++ ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
++ vpx_codec_destroy(ctx);
++ }
++
++ if (ctx->priv)
++ ctx->priv->iface = ctx->iface;
++ }
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface,
++ const uint8_t *data,
++ unsigned int data_sz,
++ vpx_codec_stream_info_t *si)
++{
++ vpx_codec_err_t res;
++
++ if (!iface || !data || !data_sz || !si
++ || si->sz < sizeof(vpx_codec_stream_info_t))
++ res = VPX_CODEC_INVALID_PARAM;
++ else
++ {
++ /* Set default/unknown values */
++ si->w = 0;
++ si->h = 0;
++
++ res = iface->dec.peek_si(data, data_sz, si);
++ }
++
++ return res;
++}
++
++
++vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx,
++ vpx_codec_stream_info_t *si)
++{
++ vpx_codec_err_t res;
++
++ if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t))
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!ctx->iface || !ctx->priv)
++ res = VPX_CODEC_ERROR;
++ else
++ {
++ /* Set default/unknown values */
++ si->w = 0;
++ si->h = 0;
++
++ res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si);
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx,
++ const uint8_t *data,
++ unsigned int data_sz,
++ void *user_priv,
++ long deadline)
++{
++ vpx_codec_err_t res;
++
++ if (!ctx || !data || !data_sz)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!ctx->iface || !ctx->priv)
++ res = VPX_CODEC_ERROR;
++ else
++ {
++ res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz,
++ user_priv, deadline);
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx,
++ vpx_codec_iter_t *iter)
++{
++ vpx_image_t *img;
++
++ if (!ctx || !iter || !ctx->iface || !ctx->priv)
++ img = NULL;
++ else
++ img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter);
++
++ return img;
++}
++
++
++vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx,
++ vpx_codec_put_frame_cb_fn_t cb,
++ void *user_priv)
++{
++ vpx_codec_err_t res;
++
++ if (!ctx || !cb)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!ctx->iface || !ctx->priv
++ || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
++ res = VPX_CODEC_ERROR;
++ else
++ {
++ ctx->priv->dec.put_frame_cb.put_frame = cb;
++ ctx->priv->dec.put_frame_cb.user_priv = user_priv;
++ res = VPX_CODEC_OK;
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx,
++ vpx_codec_put_slice_cb_fn_t cb,
++ void *user_priv)
++{
++ vpx_codec_err_t res;
++
++ if (!ctx || !cb)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!ctx->iface || !ctx->priv
++ || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
++ res = VPX_CODEC_ERROR;
++ else
++ {
++ ctx->priv->dec.put_slice_cb.put_slice = cb;
++ ctx->priv->dec.put_slice_cb.user_priv = user_priv;
++ res = VPX_CODEC_OK;
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx,
++ vpx_codec_mmap_t *mmap,
++ vpx_codec_iter_t *iter)
++{
++ vpx_codec_err_t res = VPX_CODEC_OK;
++
++ if (!ctx || !mmap || !iter || !ctx->iface)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA))
++ res = VPX_CODEC_ERROR;
++ else
++ res = ctx->iface->get_mmap(ctx, mmap, iter);
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx,
++ vpx_codec_mmap_t *mmap,
++ unsigned int num_maps)
++{
++ vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
++
++ if (!ctx || !mmap || !ctx->iface)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA))
++ res = VPX_CODEC_ERROR;
++ else
++ {
++ unsigned int i;
++
++ for (i = 0; i < num_maps; i++, mmap++)
++ {
++ if (!mmap->base)
++ break;
++
++ /* Everything look ok, set the mmap in the decoder */
++ res = ctx->iface->set_mmap(ctx, mmap);
++
++ if (res)
++ break;
++ }
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
+diff --git a/vpx/src/vpx_decoder_compat.c b/vpx/src/vpx_decoder_compat.c
+new file mode 100644
+index 0000000..d5cc16e
+--- /dev/null
++++ b/vpx/src/vpx_decoder_compat.c
+@@ -0,0 +1,201 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\file vpx_decoder.c
++ * \brief Provides the high level interface to wrap decoder algorithms.
++ *
++ */
++#include <stdlib.h>
++#include <string.h>
++#include "vpx/vpx_decoder.h"
++#include "vpx/internal/vpx_codec_internal.h"
++
++#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
++
++const char *vpx_dec_iface_name(vpx_dec_iface_t *iface)
++{
++ return vpx_codec_iface_name((vpx_codec_iface_t *)iface);
++}
++
++const char *vpx_dec_err_to_string(vpx_dec_err_t err)
++{
++ return vpx_codec_err_to_string(err);
++}
++
++const char *vpx_dec_error(vpx_dec_ctx_t *ctx)
++{
++ return vpx_codec_error((vpx_codec_ctx_t *)ctx);
++}
++
++const char *vpx_dec_error_detail(vpx_dec_ctx_t *ctx)
++{
++ return vpx_codec_error_detail((vpx_codec_ctx_t *)ctx);
++}
++
++
++vpx_dec_err_t vpx_dec_init_ver(vpx_dec_ctx_t *ctx,
++ vpx_dec_iface_t *iface,
++ int ver)
++{
++ return vpx_codec_dec_init_ver((vpx_codec_ctx_t *)ctx,
++ (vpx_codec_iface_t *)iface,
++ NULL,
++ 0,
++ ver);
++}
++
++
++vpx_dec_err_t vpx_dec_destroy(vpx_dec_ctx_t *ctx)
++{
++ return vpx_codec_destroy((vpx_codec_ctx_t *)ctx);
++}
++
++
++vpx_dec_caps_t vpx_dec_get_caps(vpx_dec_iface_t *iface)
++{
++ return vpx_codec_get_caps((vpx_codec_iface_t *)iface);
++}
++
++
++vpx_dec_err_t vpx_dec_peek_stream_info(vpx_dec_iface_t *iface,
++ const uint8_t *data,
++ unsigned int data_sz,
++ vpx_dec_stream_info_t *si)
++{
++ return vpx_codec_peek_stream_info((vpx_codec_iface_t *)iface, data, data_sz,
++ (vpx_codec_stream_info_t *)si);
++}
++
++
++vpx_dec_err_t vpx_dec_get_stream_info(vpx_dec_ctx_t *ctx,
++ vpx_dec_stream_info_t *si)
++{
++ return vpx_codec_get_stream_info((vpx_codec_ctx_t *)ctx,
++ (vpx_codec_stream_info_t *)si);
++}
++
++
++vpx_dec_err_t vpx_dec_control(vpx_dec_ctx_t *ctx,
++ int ctrl_id,
++ void *data)
++{
++ return vpx_codec_control_((vpx_codec_ctx_t *)ctx, ctrl_id, data);
++}
++
++
++vpx_dec_err_t vpx_dec_decode(vpx_dec_ctx_t *ctx,
++ uint8_t *data,
++ unsigned int data_sz,
++ void *user_priv,
++ int rel_pts)
++{
++ (void)rel_pts;
++ return vpx_codec_decode((vpx_codec_ctx_t *)ctx, data, data_sz, user_priv,
++ 0);
++}
++
++vpx_image_t *vpx_dec_get_frame(vpx_dec_ctx_t *ctx,
++ vpx_dec_iter_t *iter)
++{
++ return vpx_codec_get_frame((vpx_codec_ctx_t *)ctx, iter);
++}
++
++
++vpx_dec_err_t vpx_dec_register_put_frame_cb(vpx_dec_ctx_t *ctx,
++ vpx_dec_put_frame_cb_fn_t cb,
++ void *user_priv)
++{
++ return vpx_codec_register_put_frame_cb((vpx_codec_ctx_t *)ctx, cb,
++ user_priv);
++}
++
++
++vpx_dec_err_t vpx_dec_register_put_slice_cb(vpx_dec_ctx_t *ctx,
++ vpx_dec_put_slice_cb_fn_t cb,
++ void *user_priv)
++{
++ return vpx_codec_register_put_slice_cb((vpx_codec_ctx_t *)ctx, cb,
++ user_priv);
++}
++
++
++vpx_dec_err_t vpx_dec_xma_init_ver(vpx_dec_ctx_t *ctx,
++ vpx_dec_iface_t *iface,
++ int ver)
++{
++ return vpx_codec_dec_init_ver((vpx_codec_ctx_t *)ctx,
++ (vpx_codec_iface_t *)iface,
++ NULL,
++ VPX_CODEC_USE_XMA,
++ ver);
++}
++
++vpx_dec_err_t vpx_dec_get_mem_map(vpx_dec_ctx_t *ctx_,
++ vpx_dec_mmap_t *mmap,
++ const vpx_dec_stream_info_t *si,
++ vpx_dec_iter_t *iter)
++{
++ vpx_codec_ctx_t *ctx = (vpx_codec_ctx_t *)ctx_;
++ vpx_dec_err_t res = VPX_DEC_OK;
++
++ if (!ctx || !mmap || !si || !iter || !ctx->iface)
++ res = VPX_DEC_INVALID_PARAM;
++ else if (!(ctx->iface->caps & VPX_DEC_CAP_XMA))
++ res = VPX_DEC_ERROR;
++ else
++ {
++ if (!ctx->config.dec)
++ {
++ ctx->config.dec = malloc(sizeof(vpx_codec_dec_cfg_t));
++ ctx->config.dec->w = si->w;
++ ctx->config.dec->h = si->h;
++ }
++
++ res = ctx->iface->get_mmap(ctx, mmap, iter);
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++vpx_dec_err_t vpx_dec_set_mem_map(vpx_dec_ctx_t *ctx_,
++ vpx_dec_mmap_t *mmap,
++ unsigned int num_maps)
++{
++ vpx_codec_ctx_t *ctx = (vpx_codec_ctx_t *)ctx_;
++ vpx_dec_err_t res = VPX_DEC_MEM_ERROR;
++
++ if (!ctx || !mmap || !ctx->iface)
++ res = VPX_DEC_INVALID_PARAM;
++ else if (!(ctx->iface->caps & VPX_DEC_CAP_XMA))
++ res = VPX_DEC_ERROR;
++ else
++ {
++ void *save = (ctx->priv) ? NULL : ctx->config.dec;
++ unsigned int i;
++
++ for (i = 0; i < num_maps; i++, mmap++)
++ {
++ if (!mmap->base)
++ break;
++
++ /* Everything look ok, set the mmap in the decoder */
++ res = ctx->iface->set_mmap(ctx, mmap);
++
++ if (res)
++ break;
++ }
++
++ if (save) free(save);
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
+diff --git a/vpx/src/vpx_encoder.c b/vpx/src/vpx_encoder.c
+new file mode 100644
+index 0000000..f43328f
+--- /dev/null
++++ b/vpx/src/vpx_encoder.c
+@@ -0,0 +1,312 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\file vpx_encoder.c
++ * \brief Provides the high level interface to wrap encoder algorithms.
++ *
++ */
++#include <limits.h>
++#include <string.h>
++#include "vpx/internal/vpx_codec_internal.h"
++
++#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
++
++vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
++ vpx_codec_iface_t *iface,
++ vpx_codec_enc_cfg_t *cfg,
++ vpx_codec_flags_t flags,
++ int ver)
++{
++ vpx_codec_err_t res;
++
++ if (ver != VPX_ENCODER_ABI_VERSION)
++ res = VPX_CODEC_ABI_MISMATCH;
++ else if (!ctx || !iface || !cfg)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
++ res = VPX_CODEC_ABI_MISMATCH;
++ else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
++ res = VPX_CODEC_INCAPABLE;
++ else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
++ res = VPX_CODEC_INCAPABLE;
++ else if ((flags & VPX_CODEC_USE_PSNR)
++ && !(iface->caps & VPX_CODEC_CAP_PSNR))
++ res = VPX_CODEC_INCAPABLE;
++ else
++ {
++ ctx->iface = iface;
++ ctx->name = iface->name;
++ ctx->priv = NULL;
++ ctx->init_flags = flags;
++ ctx->config.enc = cfg;
++ res = ctx->iface->init(ctx);
++
++ if (res)
++ {
++ ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
++ vpx_codec_destroy(ctx);
++ }
++
++ if (ctx->priv)
++ ctx->priv->iface = ctx->iface;
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++
++vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface,
++ vpx_codec_enc_cfg_t *cfg,
++ unsigned int usage)
++{
++ vpx_codec_err_t res;
++ vpx_codec_enc_cfg_map_t *map;
++
++ if (!iface || !cfg || usage > INT_MAX)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
++ res = VPX_CODEC_INCAPABLE;
++ else
++ {
++ res = VPX_CODEC_INVALID_PARAM;
++
++ for (map = iface->enc.cfg_maps; map->usage >= 0; map++)
++ {
++ if (map->usage == (int)usage)
++ {
++ *cfg = map->cfg;
++ cfg->g_usage = usage;
++ res = VPX_CODEC_OK;
++ break;
++ }
++ }
++ }
++
++ return res;
++}
++
++
++#if ARCH_X86 || ARCH_X86_64
++/* On X86, disable the x87 unit's internal 80 bit precision for better
++ * consistency with the SSE unit's 64 bit precision.
++ */
++#include "vpx_ports/x86.h"
++#define FLOATING_POINT_INIT() do {\
++ unsigned short x87_orig_mode = x87_set_double_precision();
++#define FLOATING_POINT_RESTORE() \
++ x87_set_control_word(x87_orig_mode); }while(0)
++
++
++#else
++static void FLOATING_POINT_INIT() {}
++static void FLOATING_POINT_RESTORE() {}
++#endif
++
++
++vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx,
++ const vpx_image_t *img,
++ vpx_codec_pts_t pts,
++ unsigned long duration,
++ vpx_enc_frame_flags_t flags,
++ unsigned long deadline)
++{
++ vpx_codec_err_t res;
++
++ if (!ctx || (img && !duration))
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!ctx->iface || !ctx->priv)
++ res = VPX_CODEC_ERROR;
++ else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
++ res = VPX_CODEC_INCAPABLE;
++ else
++ {
++ /* Execute in a normalized floating point environment, if the platform
++ * requires it.
++ */
++ FLOATING_POINT_INIT();
++ res = ctx->iface->enc.encode(ctx->priv->alg_priv, img, pts,
++ duration, flags, deadline);
++ FLOATING_POINT_RESTORE();
++ }
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx,
++ vpx_codec_iter_t *iter)
++{
++ const vpx_codec_cx_pkt_t *pkt = NULL;
++
++ if (ctx)
++ {
++ if (!iter)
++ ctx->err = VPX_CODEC_INVALID_PARAM;
++ else if (!ctx->iface || !ctx->priv)
++ ctx->err = VPX_CODEC_ERROR;
++ else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
++ ctx->err = VPX_CODEC_INCAPABLE;
++ else
++ pkt = ctx->iface->enc.get_cx_data(ctx->priv->alg_priv, iter);
++ }
++
++ if (pkt && pkt->kind == VPX_CODEC_CX_FRAME_PKT)
++ {
++ /* If the application has specified a destination area for the
++ * compressed data, and the codec has not placed the data there,
++ * and it fits, copy it.
++ */
++ char *dst_buf = ctx->priv->enc.cx_data_dst_buf.buf;
++
++ if (dst_buf
++ && pkt->data.raw.buf != dst_buf
++ && pkt->data.raw.sz
++ + ctx->priv->enc.cx_data_pad_before
++ + ctx->priv->enc.cx_data_pad_after
++ <= ctx->priv->enc.cx_data_dst_buf.sz)
++ {
++ vpx_codec_cx_pkt_t *modified_pkt = &ctx->priv->enc.cx_data_pkt;
++
++ memcpy(dst_buf + ctx->priv->enc.cx_data_pad_before,
++ pkt->data.raw.buf, pkt->data.raw.sz);
++ *modified_pkt = *pkt;
++ modified_pkt->data.raw.buf = dst_buf;
++ modified_pkt->data.raw.sz += ctx->priv->enc.cx_data_pad_before
++ + ctx->priv->enc.cx_data_pad_after;
++ pkt = modified_pkt;
++ }
++
++ if (dst_buf == pkt->data.raw.buf)
++ {
++ ctx->priv->enc.cx_data_dst_buf.buf = dst_buf + pkt->data.raw.sz;
++ ctx->priv->enc.cx_data_dst_buf.sz -= pkt->data.raw.sz;
++ }
++ }
++
++ return pkt;
++}
++
++
++vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx,
++ const vpx_fixed_buf_t *buf,
++ unsigned int pad_before,
++ unsigned int pad_after)
++{
++ if (!ctx || !ctx->priv)
++ return VPX_CODEC_INVALID_PARAM;
++
++ if (buf)
++ {
++ ctx->priv->enc.cx_data_dst_buf = *buf;
++ ctx->priv->enc.cx_data_pad_before = pad_before;
++ ctx->priv->enc.cx_data_pad_after = pad_after;
++ }
++ else
++ {
++ ctx->priv->enc.cx_data_dst_buf.buf = NULL;
++ ctx->priv->enc.cx_data_dst_buf.sz = 0;
++ ctx->priv->enc.cx_data_pad_before = 0;
++ ctx->priv->enc.cx_data_pad_after = 0;
++ }
++
++ return VPX_CODEC_OK;
++}
++
++
++const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx)
++{
++ vpx_image_t *img = NULL;
++
++ if (ctx)
++ {
++ if (!ctx->iface || !ctx->priv)
++ ctx->err = VPX_CODEC_ERROR;
++ else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
++ ctx->err = VPX_CODEC_INCAPABLE;
++ else if (!ctx->iface->enc.get_preview)
++ ctx->err = VPX_CODEC_INCAPABLE;
++ else
++ img = ctx->iface->enc.get_preview(ctx->priv->alg_priv);
++ }
++
++ return img;
++}
++
++
++vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx)
++{
++ vpx_fixed_buf_t *buf = NULL;
++
++ if (ctx)
++ {
++ if (!ctx->iface || !ctx->priv)
++ ctx->err = VPX_CODEC_ERROR;
++ else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
++ ctx->err = VPX_CODEC_INCAPABLE;
++ else if (!ctx->iface->enc.get_glob_hdrs)
++ ctx->err = VPX_CODEC_INCAPABLE;
++ else
++ buf = ctx->iface->enc.get_glob_hdrs(ctx->priv->alg_priv);
++ }
++
++ return buf;
++}
++
++
++vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx,
++ const vpx_codec_enc_cfg_t *cfg)
++{
++ vpx_codec_err_t res;
++
++ if (!ctx || !ctx->iface || !ctx->priv || !cfg)
++ res = VPX_CODEC_INVALID_PARAM;
++ else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
++ res = VPX_CODEC_INCAPABLE;
++ else
++ res = ctx->iface->enc.cfg_set(ctx->priv->alg_priv, cfg);
++
++ return SAVE_STATUS(ctx, res);
++}
++
++
++int vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *list,
++ const struct vpx_codec_cx_pkt *pkt)
++{
++ if (list->cnt < list->max)
++ {
++ list->pkts[list->cnt++] = *pkt;
++ return 0;
++ }
++
++ return 1;
++}
++
++
++const vpx_codec_cx_pkt_t *vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
++ vpx_codec_iter_t *iter)
++{
++ const vpx_codec_cx_pkt_t *pkt;
++
++ if (!(*iter))
++ {
++ *iter = list->pkts;
++ }
++
++ pkt = (const void *) * iter;
++
++ if (pkt - list->pkts < list->cnt)
++ *iter = pkt + 1;
++ else
++ pkt = NULL;
++
++ return pkt;
++}
+diff --git a/vpx/src/vpx_image.c b/vpx/src/vpx_image.c
+new file mode 100644
+index 0000000..e8a2959
+--- /dev/null
++++ b/vpx/src/vpx_image.c
+@@ -0,0 +1,262 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++#include <stdlib.h>
++#include <string.h>
++#include "vpx/vpx_image.h"
++
++static vpx_image_t *img_alloc_helper(vpx_image_t *img,
++ vpx_img_fmt_t fmt,
++ unsigned int d_w,
++ unsigned int d_h,
++ unsigned int stride_align,
++ unsigned char *img_data)
++{
++
++ unsigned int h, w, s, xcs, ycs, bps;
++ int align;
++
++ /* Treat align==0 like align==1 */
++ if (!stride_align)
++ stride_align = 1;
++
++ /* Validate alignment (must be power of 2) */
++ if (stride_align & (stride_align - 1))
++ goto fail;
++
++ /* Get sample size for this format */
++ switch (fmt)
++ {
++ case VPX_IMG_FMT_RGB32:
++ case VPX_IMG_FMT_RGB32_LE:
++ case VPX_IMG_FMT_ARGB:
++ case VPX_IMG_FMT_ARGB_LE:
++ bps = 32;
++ break;
++ case VPX_IMG_FMT_RGB24:
++ case VPX_IMG_FMT_BGR24:
++ bps = 24;
++ break;
++ case VPX_IMG_FMT_RGB565:
++ case VPX_IMG_FMT_RGB565_LE:
++ case VPX_IMG_FMT_RGB555:
++ case VPX_IMG_FMT_RGB555_LE:
++ case VPX_IMG_FMT_UYVY:
++ case VPX_IMG_FMT_YUY2:
++ case VPX_IMG_FMT_YVYU:
++ bps = 16;
++ break;
++ case VPX_IMG_FMT_I420:
++ case VPX_IMG_FMT_YV12:
++ case VPX_IMG_FMT_VPXI420:
++ case VPX_IMG_FMT_VPXYV12:
++ bps = 12;
++ break;
++ default:
++ bps = 16;
++ break;
++ }
++
++ /* Get chroma shift values for this format */
++ switch (fmt)
++ {
++ case VPX_IMG_FMT_I420:
++ case VPX_IMG_FMT_YV12:
++ case VPX_IMG_FMT_VPXI420:
++ case VPX_IMG_FMT_VPXYV12:
++ xcs = 1;
++ break;
++ default:
++ xcs = 0;
++ break;
++ }
++
++ switch (fmt)
++ {
++ case VPX_IMG_FMT_I420:
++ case VPX_IMG_FMT_YV12:
++ case VPX_IMG_FMT_VPXI420:
++ case VPX_IMG_FMT_VPXYV12:
++ ycs = 1;
++ break;
++ default:
++ ycs = 0;
++ break;
++ }
++
++ /* Calculate storage sizes given the chroma subsampling */
++ align = (1 << xcs) - 1;
++ w = (d_w + align) & ~align;
++ align = (1 << ycs) - 1;
++ h = (d_h + align) & ~align;
++ s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8;
++ s = (s + stride_align - 1) & ~(stride_align - 1);
++
++ /* Allocate the new image */
++ if (!img)
++ {
++ img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t));
++
++ if (!img)
++ goto fail;
++
++ img->self_allocd = 1;
++ }
++ else
++ {
++ memset(img, 0, sizeof(vpx_image_t));
++ }
++
++ img->img_data = img_data;
++
++ if (!img_data)
++ {
++ img->img_data = malloc((fmt & VPX_IMG_FMT_PLANAR) ? h * w * bps / 8 : h * s);
++ img->img_data_owner = 1;
++ }
++
++ if (!img->img_data)
++ goto fail;
++
++ img->fmt = fmt;
++ img->w = w;
++ img->h = h;
++ img->x_chroma_shift = xcs;
++ img->y_chroma_shift = ycs;
++ img->bps = bps;
++
++ /* Calculate strides */
++ img->stride[VPX_PLANE_Y] = img->stride[VPX_PLANE_ALPHA] = s;
++ img->stride[VPX_PLANE_U] = img->stride[VPX_PLANE_V] = s >> xcs;
++
++ /* Default viewport to entire image */
++ if (!vpx_img_set_rect(img, 0, 0, d_w, d_h))
++ return img;
++
++fail:
++ vpx_img_free(img);
++ return NULL;
++}
++
++vpx_image_t *vpx_img_alloc(vpx_image_t *img,
++ vpx_img_fmt_t fmt,
++ unsigned int d_w,
++ unsigned int d_h,
++ unsigned int stride_align)
++{
++ return img_alloc_helper(img, fmt, d_w, d_h, stride_align, NULL);
++}
++
++vpx_image_t *vpx_img_wrap(vpx_image_t *img,
++ vpx_img_fmt_t fmt,
++ unsigned int d_w,
++ unsigned int d_h,
++ unsigned int stride_align,
++ unsigned char *img_data)
++{
++ return img_alloc_helper(img, fmt, d_w, d_h, stride_align, img_data);
++}
++
++int vpx_img_set_rect(vpx_image_t *img,
++ unsigned int x,
++ unsigned int y,
++ unsigned int w,
++ unsigned int h)
++{
++ unsigned char *data;
++
++ if (x + w <= img->w && y + h <= img->h)
++ {
++ img->d_w = w;
++ img->d_h = h;
++
++ /* Calculate plane pointers */
++ if (!(img->fmt & VPX_IMG_FMT_PLANAR))
++ {
++ img->planes[VPX_PLANE_PACKED] =
++ img->img_data + x * img->bps / 8 + y * img->stride[VPX_PLANE_PACKED];
++ }
++ else
++ {
++ data = img->img_data;
++
++ if (img->fmt & VPX_IMG_FMT_HAS_ALPHA)
++ {
++ img->planes[VPX_PLANE_ALPHA] =
++ data + x + y * img->stride[VPX_PLANE_ALPHA];
++ data += img->h * img->stride[VPX_PLANE_ALPHA];
++ }
++
++ img->planes[VPX_PLANE_Y] = data + x + y * img->stride[VPX_PLANE_Y];
++ data += img->h * img->stride[VPX_PLANE_Y];
++
++ if (!(img->fmt & VPX_IMG_FMT_UV_FLIP))
++ {
++ img->planes[VPX_PLANE_U] = data
++ + (x >> img->x_chroma_shift)
++ + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
++ data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
++ img->planes[VPX_PLANE_V] = data
++ + (x >> img->x_chroma_shift)
++ + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
++ }
++ else
++ {
++ img->planes[VPX_PLANE_V] = data
++ + (x >> img->x_chroma_shift)
++ + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
++ data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
++ img->planes[VPX_PLANE_U] = data
++ + (x >> img->x_chroma_shift)
++ + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
++ }
++ }
++
++ return 0;
++ }
++
++ return -1;
++}
++
++void vpx_img_flip(vpx_image_t *img)
++{
++ /* Note: In the calculation pointer adjustment calculation, we want the
++ * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99
++ * standard indicates that if the adjustment parameter is unsigned, the
++ * stride parameter will be promoted to unsigned, causing errors when
++ * the lhs is a larger type than the rhs.
++ */
++ img->planes[VPX_PLANE_Y] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_Y];
++ img->stride[VPX_PLANE_Y] = -img->stride[VPX_PLANE_Y];
++
++ img->planes[VPX_PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
++ * img->stride[VPX_PLANE_U];
++ img->stride[VPX_PLANE_U] = -img->stride[VPX_PLANE_U];
++
++ img->planes[VPX_PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
++ * img->stride[VPX_PLANE_V];
++ img->stride[VPX_PLANE_V] = -img->stride[VPX_PLANE_V];
++
++ img->planes[VPX_PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_ALPHA];
++ img->stride[VPX_PLANE_ALPHA] = -img->stride[VPX_PLANE_ALPHA];
++}
++
++void vpx_img_free(vpx_image_t *img)
++{
++ if (img)
++ {
++ if (img->img_data && img->img_data_owner)
++ free(img->img_data);
++
++ if (img->self_allocd)
++ free(img);
++ }
++}
+diff --git a/vpx/vp8.h b/vpx/vp8.h
+new file mode 100644
+index 0000000..a493ef6
+--- /dev/null
++++ b/vpx/vp8.h
+@@ -0,0 +1,117 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\defgroup vp8 VP8
++ * \ingroup codecs
++ * VP8 is vpx's newest video compression algorithm that uses motion
++ * compensated prediction, Discrete Cosine Transform (DCT) coding of the
++ * prediction error signal and context dependent entropy coding techniques
++ * based on arithmatic principles. It features:
++ * - YUV 4:2:0 image format
++ * - Macro-block based coding (16x16 luma plus two 8x8 chroma)
++ * - 1/4 (1/8) pixel accuracy motion compensated prediction
++ * - 4x4 DCT transform
++ * - 128 level linear quantizer
++ * - In loop deblocking filter
++ * - Context-based entropy coding
++ *
++ * @{
++ */
++/*!\file vp8.h
++ * \brief Provides controls common to both the VP8 encoder and decoder.
++ */
++#ifndef VP8_H
++#define VP8_H
++#include "vpx/vpx_codec_impl_top.h"
++
++/*!\brief Control functions
++ *
++ * The set of macros define the control functions of VP8 interface
++ */
++enum vp8_dec_control_id
++{
++ VP8_SET_REFERENCE = 1, /**< pass in an external frame into decoder to be used as reference frame */
++ VP8_COPY_REFERENCE = 2, /**< get a copy of reference frame from the decoder */
++ VP8_SET_POSTPROC = 3, /**< set decoder's the post processing settings */
++ VP8_COMMON_CTRL_ID_MAX
++};
++
++/*!\brief post process flags
++ *
++ * The set of macros define VP8 decoder post processing flags
++ */
++enum vp8_postproc_level
++{
++ VP8_NOFILTERING = 0,
++ VP8_DEBLOCK = 1,
++ VP8_DEMACROBLOCK = 2,
++ VP8_ADDNOISE = 4,
++};
++
++/*!\brief post process flags
++ *
++ * This define a structure that describe the post processing settings. For
++ * the best objective measure (using thet PSNR metric) set post_proc_flag
++ * to VP8_DEBLOCK and deblocking_level to 1.
++ */
++
++typedef struct vp8_postproc_cfg
++{
++ int post_proc_flag; /**< the types of post processing to be done, should be combination of "vp8_postproc_level" */
++ int deblocking_level; /**< the strength of deblocking, valid range [0, 16] */
++ int noise_level; /**< the strength of additive noise, valid range [0, 16] */
++} vp8_postproc_cfg_t;
++
++/*!\brief reference frame type
++ *
++ * The set of macros define the type of VP8 reference frames
++ */
++typedef enum vpx_ref_frame_type
++{
++ VP8_LAST_FRAME = 1,
++ VP8_GOLD_FRAME = 2,
++ VP8_ALTR_FRAME = 4
++} vpx_ref_frame_type_t;
++
++/*!\brief reference frame data struct
++ *
++ * define the data struct to access vp8 reference frames
++ */
++
++typedef struct vpx_ref_frame
++{
++ vpx_ref_frame_type_t frame_type; /**< which reference frame */
++ vpx_image_t img; /**< reference frame data in image format */
++} vpx_ref_frame_t;
++
++
++/*!\brief vp8 decoder control funciton parameter type
++ *
++ * defines the data type for each of VP8 decoder control funciton requires
++ */
++
++VPX_CTRL_USE_TYPE(VP8_SET_REFERENCE, vpx_ref_frame_t *)
++VPX_CTRL_USE_TYPE(VP8_COPY_REFERENCE, vpx_ref_frame_t *)
++VPX_CTRL_USE_TYPE(VP8_SET_POSTPROC, vp8_postproc_cfg_t *)
++
++
++/*! @} - end defgroup vp8 */
++
++#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
++/* The following definitions are provided for backward compatibility with
++ * the VP8 1.0.x SDK. USE IN PRODUCTION CODE IS NOT RECOMMENDED.
++ */
++
++DECLSPEC_DEPRECATED extern vpx_codec_iface_t vpx_codec_vp8_algo DEPRECATED;
++#endif
++
++#include "vpx/vpx_codec_impl_bottom.h"
++#endif
+diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h
+new file mode 100644
+index 0000000..1104064
+--- /dev/null
++++ b/vpx/vp8cx.h
+@@ -0,0 +1,262 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\defgroup vp8_encoder WebM VP8 Encoder
++ * \ingroup vp8
++ *
++ * @{
++ */
++#include "vp8.h"
++
++/*!\file vp8cx.h
++ * \brief Provides definitions for using the VP8 encoder algorithm within the
++ * vpx Codec Interface.
++ */
++#ifndef VP8CX_H
++#define VP8CX_H
++#include "vpx/vpx_codec_impl_top.h"
++
++/*!\brief Algorithm interface for VP8
++ *
++ * This interface provides the capability to encode raw VP8 streams, as would
++ * be found in AVI files.
++ */
++extern vpx_codec_iface_t vpx_codec_vp8_cx_algo;
++
++
++/*
++ * Algorithm Flags
++ */
++
++/*!\brief Don't reference the last frame
++ *
++ * When this flag is set, the encoder will not use the last frame as a
++ * predictor. When not set, the encoder will choose whether to use the
++ * last frame or not automatically.
++ */
++#define VP8_EFLAG_NO_REF_LAST (1<<16)
++
++
++/*!\brief Don't reference the golden frame
++ *
++ * When this flag is set, the encoder will not use the golden frame as a
++ * predictor. When not set, the encoder will choose whether to use the
++ * golden frame or not automatically.
++ */
++#define VP8_EFLAG_NO_REF_GF (1<<17)
++
++
++/*!\brief Don't reference the alternate reference frame
++ *
++ * When this flag is set, the encoder will not use the alt ref frame as a
++ * predictor. When not set, the encoder will choose whether to use the
++ * alt ref frame or not automatically.
++ */
++#define VP8_EFLAG_NO_REF_ARF (1<<21)
++
++
++/*!\brief Don't update the last frame
++ *
++ * When this flag is set, the encoder will not update the last frame with
++ * the contents of the current frame.
++ */
++#define VP8_EFLAG_NO_UPD_LAST (1<<18)
++
++
++/*!\brief Don't update the golden frame
++ *
++ * When this flag is set, the encoder will not update the golden frame with
++ * the contents of the current frame.
++ */
++#define VP8_EFLAG_NO_UPD_GF (1<<22)
++
++
++/*!\brief Don't update the alternate reference frame
++ *
++ * When this flag is set, the encoder will not update the alt ref frame with
++ * the contents of the current frame.
++ */
++#define VP8_EFLAG_NO_UPD_ARF (1<<23)
++
++
++/*!\brief Force golden frame update
++ *
++ * When this flag is set, the encoder copy the contents of the current frame
++ * to the golden frame buffer.
++ */
++#define VP8_EFLAG_FORCE_GF (1<<19)
++
++
++/*!\brief Force alternate reference frame update
++ *
++ * When this flag is set, the encoder copy the contents of the current frame
++ * to the alternate reference frame buffer.
++ */
++#define VP8_EFLAG_FORCE_ARF (1<<24)
++
++
++/*!\brief Disable entropy update
++ *
++ * When this flag is set, the encoder will not update its internal entropy
++ * model based on the entropy of this frame.
++ */
++#define VP8_EFLAG_NO_UPD_ENTROPY (1<<20)
++
++
++/*!\brief VP8 encoder control functions
++ *
++ * The set of macros define the control functions of VP8 encoder interface
++ */
++enum vp8e_enc_control_id
++{
++ VP8E_UPD_ENTROPY = 5, /**< control function to set mode of entropy update in encoder */
++ VP8E_UPD_REFERENCE, /**< control function to set reference update mode in encoder */
++ VP8E_USE_REFERENCE, /**< control function to set which reference frame encoder can use */
++ VP8E_SET_ROI_MAP, /**< control function to pass an ROI map to encoder */
++ VP8E_SET_ACTIVEMAP, /**< control function to pass an Active map to encoder */
++ VP8E_SET_SCALEMODE = 11, /**< control function to set encoder scaling mode */
++ VP8E_SET_CPUUSED = 13, /**< control function to set vp8 encoder cpuused */
++ VP8E_SET_ENABLEAUTOALTREF, /**< control function to enable vp8 to automatic set and use altref frame */
++ VP8E_SET_NOISE_SENSITIVITY, /**< control function to set noise sensitivity */
++ VP8E_SET_SHARPNESS, /**< control function to set sharpness */
++ VP8E_SET_STATIC_THRESHOLD, /**< control function to set the threshold for macroblocks treated static */
++ VP8E_SET_TOKEN_PARTITIONS, /**< control function to set the number of token partitions */
++ VP8E_GET_LAST_QUANTIZER, /**< return the quantizer chosen by the
++ encoder for the last frame using the internal
++ scale */
++ VP8E_GET_LAST_QUANTIZER_64, /**< return the quantizer chosen by the
++ encoder for the last frame, using the 0..63
++ scale as used by the rc_*_quantizer config
++ parameters */
++ VP8E_SET_ARNR_MAXFRAMES, /**< control function to set the max number of frames blurred creating arf*/
++ VP8E_SET_ARNR_STRENGTH , /**< control function to set the filter strength for the arf */
++ VP8E_SET_ARNR_TYPE , /**< control function to set the type of filter to use for the arf*/
++} ;
++
++/*!\brief vpx 1-D scaling mode
++ *
++ * This set of constants define 1-D vpx scaling modes
++ */
++typedef enum vpx_scaling_mode_1d
++{
++ VP8E_NORMAL = 0,
++ VP8E_FOURFIVE = 1,
++ VP8E_THREEFIVE = 2,
++ VP8E_ONETWO = 3
++} VPX_SCALING_MODE;
++
++
++/*!\brief vpx region of interest map
++ *
++ * These defines the data structures for the region of interest map
++ *
++ */
++
++typedef struct vpx_roi_map
++{
++ unsigned char *roi_map; /**< specify an id between 0 and 3 for each 16x16 region within a frame */
++ unsigned int rows; /**< number of rows */
++ unsigned int cols; /**< number of cols */
++ int delta_q[4]; /**< quantizer delta [-64, 64] off baseline for regions with id between 0 and 3*/
++ int delta_lf[4]; /**< loop filter strength delta [-32, 32] for regions with id between 0 and 3 */
++ unsigned int static_threshold[4];/**< threshold for region to be treated as static */
++} vpx_roi_map_t;
++
++/*!\brief vpx active region map
++ *
++ * These defines the data structures for active region map
++ *
++ */
++
++
++typedef struct vpx_active_map
++{
++ unsigned char *active_map; /**< specify an on (1) or off (0) each 16x16 region within a frame */
++ unsigned int rows; /**< number of rows */
++ unsigned int cols; /**< number of cols */
++} vpx_active_map_t;
++
++/*!\brief vpx image scaling mode
++ *
++ * This defines the data structure for image scaling mode
++ *
++ */
++typedef struct vpx_scaling_mode
++{
++ VPX_SCALING_MODE h_scaling_mode; /**< horizontal scaling mode */
++ VPX_SCALING_MODE v_scaling_mode; /**< vertical scaling mode */
++} vpx_scaling_mode_t;
++
++/*!\brief VP8 encoding mode
++ *
++ * This defines VP8 encoding mode
++ *
++ */
++typedef enum
++{
++ VP8_BEST_QUALITY_ENCODING,
++ VP8_GOOD_QUALITY_ENCODING,
++ VP8_REAL_TIME_ENCODING
++} vp8e_encoding_mode;
++
++/*!\brief VP8 token partition mode
++ *
++ * This defines VP8 partitioning mode for compressed data, i.e., the number of
++ * sub-streams in the bitstream. Used for parallelized decoding.
++ *
++ */
++
++typedef enum
++{
++ VP8_ONE_TOKENPARTITION = 0,
++ VP8_TWO_TOKENPARTITION = 1,
++ VP8_FOUR_TOKENPARTITION = 2,
++ VP8_EIGHT_TOKENPARTITION = 3,
++} vp8e_token_partitions;
++
++
++/*!\brief VP8 encoder control function parameter type
++ *
++ * Defines the data types that VP8E control functions take. Note that
++ * additional common controls are defined in vp8.h
++ *
++ */
++
++
++/* These controls have been deprecated in favor of the flags parameter to
++ * vpx_codec_encode(). See the definition of VP8_EFLAG_* above.
++ */
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_ENTROPY, int)
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_REFERENCE, int)
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_USE_REFERENCE, int)
++
++VPX_CTRL_USE_TYPE(VP8E_SET_ROI_MAP, vpx_roi_map_t *)
++VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP, vpx_active_map_t *)
++VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE, vpx_scaling_mode_t *)
++
++VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED, int)
++VPX_CTRL_USE_TYPE(VP8E_SET_ENABLEAUTOALTREF, unsigned int)
++VPX_CTRL_USE_TYPE(VP8E_SET_NOISE_SENSITIVITY, unsigned int)
++VPX_CTRL_USE_TYPE(VP8E_SET_SHARPNESS, unsigned int)
++VPX_CTRL_USE_TYPE(VP8E_SET_STATIC_THRESHOLD, unsigned int)
++VPX_CTRL_USE_TYPE(VP8E_SET_TOKEN_PARTITIONS, vp8e_token_partitions)
++
++VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_MAXFRAMES, unsigned int)
++VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_STRENGTH , unsigned int)
++VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_TYPE , unsigned int)
++
++
++VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER, int *)
++VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64, int *)
++
++/*! @} - end defgroup vp8_encoder */
++#include "vpx/vpx_codec_impl_bottom.h"
++#endif
+diff --git a/vpx/vp8dx.h b/vpx/vp8dx.h
+new file mode 100644
+index 0000000..d602e80
+--- /dev/null
++++ b/vpx/vp8dx.h
+@@ -0,0 +1,42 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++#include "vp8.h"
++
++/*!\defgroup vp8_decoder WebM VP8 Decoder
++ * \ingroup vp8
++ *
++ * @{
++ */
++/*!\file vp8dx.h
++ * \brief Provides definitions for using the VP8 algorithm within the vpx Decoder
++ * interface.
++ */
++#ifndef VP8DX_H
++#define VP8DX_H
++#include "vpx/vpx_codec_impl_top.h"
++
++/*!\brief Algorithm interface for VP8
++ *
++ * This interface provides the capability to decode raw VP8 streams, as would
++ * be found in AVI files and other non-Flash uses.
++ */
++extern vpx_codec_iface_t vpx_codec_vp8_dx_algo;
++
++/* Include controls common to both the encoder and decoder */
++#include "vp8.h"
++
++
++/*! @} - end defgroup vp8_decoder */
++
++
++#include "vpx/vpx_codec_impl_bottom.h"
++#endif
+diff --git a/vpx/vp8e.h b/vpx/vp8e.h
+new file mode 100644
+index 0000000..f72fd24
+--- /dev/null
++++ b/vpx/vp8e.h
+@@ -0,0 +1,63 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/* This file contains backwards compatibility stubs for applications using
++ * the VP8 version 1.0 API.
++ */
++#ifndef VP8E_H
++#define VP8E_H
++#include "vpx/vpx_codec_impl_top.h"
++
++#if defined(VPX_CODEC_DISABLE_COMPAT) && VPX_CODEC_DISABLE_COMPAT
++#error "Backwards compatibility disabled: don't include vp8e.h"
++#endif
++
++#include "vp8cx.h"
++DECLSPEC_DEPRECATED extern vpx_codec_iface_t vpx_enc_vp8_algo DEPRECATED;
++
++
++enum
++{
++ VP8E_SET_REFERENCE = VP8_SET_REFERENCE,
++ VP8E_COPY_REFERENCE = VP8_COPY_REFERENCE,
++ VP8E_SET_PREVIEWPP = VP8_SET_POSTPROC,
++ VP8E_SET_FLUSHFLAG = 4,
++ VP8E_SET_FRAMETYPE = 10,
++ VP8E_SET_ENCODING_MODE = 12
++};
++
++#define NORMAL_FRAME (0)
++#define KEY_FRAME (1)
++
++/* Change VP8E to VP8 to get the undeprecated version of these (defined in
++ * vp8.h)
++ */
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_REFERENCE, vpx_ref_frame_t *)
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_COPY_REFERENCE, vpx_ref_frame_t *)
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_PREVIEWPP, vp8_postproc_cfg_t *)
++
++
++/* Flush is done by calling vpx_codec_encode with a NULL input image. */
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_FLUSHFLAG, int)
++
++
++/* Frame type is set with a flag to vpx_codec_control. See VPX_EFLAG_FORCE_KF
++ */
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_FRAMETYPE, int)
++
++
++/* This control has been deprecated in favor of the duration parameter to
++ * vpx_codec_encode(). Use the #VPX_DL_REALTIME, #VPX_DL_GOOD_QUALITY,
++ * #VPX_DL_BEST_QUALITY constants to that parameter instead.
++ */
++VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_ENCODING_MODE, vp8e_encoding_mode)
++#include "vpx/vpx_codec_impl_bottom.h"
++#endif
+diff --git a/vpx/vpx_codec.h b/vpx/vpx_codec.h
+new file mode 100644
+index 0000000..f821559
+--- /dev/null
++++ b/vpx/vpx_codec.h
+@@ -0,0 +1,554 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\defgroup codec Common Algorithm Interface
++ * This abstraction allows applications to easily support multiple video
++ * formats with minimal code duplication. This section describes the interface
++ * common to all codecs (both encoders and decoders).
++ * @{
++ */
++
++/*!\file vpx_codec.h
++ * \brief Describes the codec algorithm interface to applications.
++ *
++ * This file describes the interface between an application and a
++ * video codec algorithm.
++ *
++ * An application instantiates a specific codec instance by using
++ * vpx_codec_init() and a pointer to the algorithm's interface structure:
++ * <pre>
++ * my_app.c:
++ * extern vpx_codec_iface_t my_codec;
++ * {
++ * vpx_codec_ctx_t algo;
++ * res = vpx_codec_init(&algo, &my_codec);
++ * }
++ * </pre>
++ *
++ * Once initialized, the instance is manged using other functions from
++ * the vpx_codec_* family.
++ */
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef VPX_CODEC_H
++#define VPX_CODEC_H
++#include "vpx_integer.h"
++#include "vpx_image.h"
++
++ /*!\brief Decorator indicating a function is deprecated */
++#ifndef DEPRECATED
++#if defined(__GNUC__) && __GNUC__
++#define DEPRECATED __attribute__ ((deprecated))
++#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
++#elif defined(_MSC_VER)
++#define DEPRECATED
++#define DECLSPEC_DEPRECATED __declspec(deprecated) /**< \copydoc #DEPRECATED */
++#else
++#define DEPRECATED
++#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
++#endif
++#endif
++
++ /*!\brief Decorator indicating a function is potentially unused */
++#ifdef UNUSED
++#elif __GNUC__
++#define UNUSED __attribute__ ((unused));
++#else
++#define UNUSED
++#endif
++
++ /*!\brief Current ABI version number
++ *
++ * \internal
++ * If this file is altered in any way that changes the ABI, this value
++ * must be bumped. Examples include, but are not limited to, changing
++ * types, removing or reassigning enums, adding/removing/rearranging
++ * fields to structures
++ */
++#define VPX_CODEC_ABI_VERSION (2 + VPX_IMAGE_ABI_VERSION) /**<\hideinitializer*/
++
++ /*!\brief Algorithm return codes */
++ typedef enum {
++ /*!\brief Operation completed without error */
++ VPX_CODEC_OK,
++
++ /*!\brief Unspecified error */
++ VPX_CODEC_ERROR,
++
++ /*!\brief Memory operation failed */
++ VPX_CODEC_MEM_ERROR,
++
++ /*!\brief ABI version mismatch */
++ VPX_CODEC_ABI_MISMATCH,
++
++ /*!\brief Algorithm does not have required capability */
++ VPX_CODEC_INCAPABLE,
++
++ /*!\brief The given bitstream is not supported.
++ *
++ * The bitstream was unable to be parsed at the highest level. The decoder
++ * is unable to proceed. This error \ref SHOULD be treated as fatal to the
++ * stream. */
++ VPX_CODEC_UNSUP_BITSTREAM,
++
++ /*!\brief Encoded bitstream uses an unsupported feature
++ *
++ * The decoder does not implement a feature required by the encoder. This
++ * return code should only be used for features that prevent future
++ * pictures from being properly decoded. This error \ref MAY be treated as
++ * fatal to the stream or \ref MAY be treated as fatal to the current GOP.
++ */
++ VPX_CODEC_UNSUP_FEATURE,
++
++ /*!\brief The coded data for this stream is corrupt or incomplete
++ *
++ * There was a problem decoding the current frame. This return code
++ * should only be used for failures that prevent future pictures from
++ * being properly decoded. This error \ref MAY be treated as fatal to the
++ * stream or \ref MAY be treated as fatal to the current GOP. If decoding
++ * is continued for the current GOP, artifacts may be present.
++ */
++ VPX_CODEC_CORRUPT_FRAME,
++
++ /*!\brief An application-supplied parameter is not valid.
++ *
++ */
++ VPX_CODEC_INVALID_PARAM,
++
++ /*!\brief An iterator reached the end of list.
++ *
++ */
++ VPX_CODEC_LIST_END,
++
++ }
++ vpx_codec_err_t;
++
++
++ /*! \brief Codec capabilities bitfield
++ *
++ * Each codec advertises the capabilities it supports as part of its
++ * ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
++ * or functionality, and are not required to be supported.
++ *
++ * The available flags are specified by VPX_CODEC_CAP_* defines.
++ */
++ typedef long vpx_codec_caps_t;
++#define VPX_CODEC_CAP_DECODER 0x1 /**< Is a decoder */
++#define VPX_CODEC_CAP_ENCODER 0x2 /**< Is an encoder */
++#define VPX_CODEC_CAP_XMA 0x4 /**< Supports e_xternal Memory Allocation */
++
++
++ /*! \brief Initialization-time Feature Enabling
++ *
++ * Certain codec features must be known at initialization time, to allow for
++ * proper memory allocation.
++ *
++ * The available flags are specified by VPX_CODEC_USE_* defines.
++ */
++ typedef long vpx_codec_flags_t;
++#define VPX_CODEC_USE_XMA 0x00000001 /**< Use e_xternal Memory Allocation mode */
++
++
++ /*!\brief Codec interface structure.
++ *
++ * Contains function pointers and other data private to the codec
++ * implementation. This structure is opaque to the application.
++ */
++ typedef const struct vpx_codec_iface vpx_codec_iface_t;
++
++
++ /*!\brief Codec private data structure.
++ *
++ * Contains data private to the codec implementation. This structure is opaque
++ * to the application.
++ */
++ typedef struct vpx_codec_priv vpx_codec_priv_t;
++
++
++ /*!\brief Iterator
++ *
++ * Opaque storage used for iterating over lists.
++ */
++ typedef const void *vpx_codec_iter_t;
++
++
++ /*!\brief Codec context structure
++ *
++ * All codecs \ref MUST support this context structure fully. In general,
++ * this data should be considered private to the codec algorithm, and
++ * not be manipulated or examined by the calling application. Applications
++ * may reference the 'name' member to get a printable description of the
++ * algorithm.
++ */
++ typedef struct vpx_codec_ctx
++ {
++ const char *name; /**< Printable interface name */
++ vpx_codec_iface_t *iface; /**< Interface pointers */
++ vpx_codec_err_t err; /**< Last returned error */
++ const char *err_detail; /**< Detailed info, if available */
++ vpx_codec_flags_t init_flags; /**< Flags passed at init time */
++ union
++ {
++ struct vpx_codec_dec_cfg *dec; /**< Decoder Configuration Pointer */
++ struct vpx_codec_enc_cfg *enc; /**< Encoder Configuration Pointer */
++ void *raw;
++ } config; /**< Configuration pointer aliasing union */
++ vpx_codec_priv_t *priv; /**< Algorithm private storage */
++ } vpx_codec_ctx_t;
++
++
++ /*
++ * Library Version Number Interface
++ *
++ * For example, see the following sample return values:
++ * vpx_codec_version() (1<<16 | 2<<8 | 3)
++ * vpx_codec_version_str() "v1.2.3-rc1-16-gec6a1ba"
++ * vpx_codec_version_extra_str() "rc1-16-gec6a1ba"
++ */
++
++ /*!\brief Return the version information (as an integer)
++ *
++ * Returns a packed encoding of the library version number. This will only include
++ * the major.minor.patch component of the version number. Note that this encoded
++ * value should be accessed through the macros provided, as the encoding may change
++ * in the future.
++ *
++ */
++ int vpx_codec_version(void);
++#define VPX_VERSION_MAJOR(v) ((v>>16)&0xff) /**< extract major from packed version */
++#define VPX_VERSION_MINOR(v) ((v>>8)&0xff) /**< extract minor from packed version */
++#define VPX_VERSION_PATCH(v) ((v>>0)&0xff) /**< extract patch from packed version */
++
++ /*!\brief Return the version major number */
++#define vpx_codec_version_major() ((vpx_codec_version()>>16)&0xff)
++
++ /*!\brief Return the version minr number */
++#define vpx_codec_version_minor() ((vpx_codec_version()>>8)&0xff)
++
++ /*!\brief Return the version patch number */
++#define vpx_codec_version_patch() ((vpx_codec_version()>>0)&0xff)
++
++
++ /*!\brief Return the version information (as a string)
++ *
++ * Returns a printable string containing the full library version number. This may
++ * contain additional text following the three digit version number, as to indicate
++ * release candidates, prerelease versions, etc.
++ *
++ */
++ const char *vpx_codec_version_str(void);
++
++
++ /*!\brief Return the version information (as a string)
++ *
++ * Returns a printable "extra string". This is the component of the string returned
++ * by vpx_codec_version_str() following the three digit version number.
++ *
++ */
++ const char *vpx_codec_version_extra_str(void);
++
++
++ /*!\brief Return the build configuration
++ *
++ * Returns a printable string containing an encoded version of the build
++ * configuration. This may be useful to vpx support.
++ *
++ */
++ const char *vpx_codec_build_config(void);
++
++
++ /*!\brief Return the name for a given interface
++ *
++ * Returns a human readable string for name of the given codec interface.
++ *
++ * \param[in] iface Interface pointer
++ *
++ */
++ const char *vpx_codec_iface_name(vpx_codec_iface_t *iface);
++
++
++ /*!\brief Convert error number to printable string
++ *
++ * Returns a human readable string for the last error returned by the
++ * algorithm. The returned error will be one line and will not contain
++ * any newline characters.
++ *
++ *
++ * \param[in] err Error number.
++ *
++ */
++ const char *vpx_codec_err_to_string(vpx_codec_err_t err);
++
++
++ /*!\brief Retrieve error synopsis for codec context
++ *
++ * Returns a human readable string for the last error returned by the
++ * algorithm. The returned error will be one line and will not contain
++ * any newline characters.
++ *
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ *
++ */
++ const char *vpx_codec_error(vpx_codec_ctx_t *ctx);
++
++
++ /*!\brief Retrieve detailed error information for codec context
++ *
++ * Returns a human readable string providing detailed information about
++ * the last error.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ *
++ * \retval NULL
++ * No detailed information is available.
++ */
++ const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx);
++
++
++ /* REQUIRED FUNCTIONS
++ *
++ * The following functions are required to be implemented for all codecs.
++ * They represent the base case functionality expected of all codecs.
++ */
++
++ /*!\brief Destroy a codec instance
++ *
++ * Destroys a codec context, freeing any associated memory buffers.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ *
++ * \retval #VPX_CODEC_OK
++ * The codec algorithm initialized.
++ * \retval #VPX_CODEC_MEM_ERROR
++ * Memory allocation failed.
++ */
++ vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx);
++
++
++ /*!\brief Get the capabilities of an algorithm.
++ *
++ * Retrieves the capabliities bitfield from the algorithm's interface.
++ *
++ * \param[in] iface Pointer to the alogrithm interface
++ *
++ */
++ vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface);
++
++
++ /*!\brief Control algorithm
++ *
++ * This function is used to exchange algorithm specific data with the codec
++ * instance. This can be used to implement features specific to a particular
++ * algorithm.
++ *
++ * This wrapper function dispatches the request to the helper function
++ * associated with the given ctrl_id. It tries to call this function
++ * transparantly, but will return #VPX_CODEC_ERROR if the request could not
++ * be dispatched.
++ *
++ * Note that this function should not be used directly. Call the
++ * #vpx_codec_control wrapper macro instead.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] ctrl_id Algorithm specific control identifier
++ *
++ * \retval #VPX_CODEC_OK
++ * The control request was processed.
++ * \retval #VPX_CODEC_ERROR
++ * The control request was not processed.
++ * \retval #VPX_CODEC_INVALID_PARAM
++ * The data was not valid.
++ */
++ vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx,
++ int ctrl_id,
++ ...);
++#if defined(VPX_DISABLE_CTRL_TYPECHECKS) && VPX_DISABLE_CTRL_TYPECHECKS
++# define vpx_codec_control(ctx,id,data) vpx_codec_control_(ctx,id,data)
++# define VPX_CTRL_USE_TYPE(id, typ)
++# define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ)
++# define VPX_CTRL_VOID(id, typ)
++
++#else
++ /*!\brief vpx_codec_control wrapper macro
++ *
++ * This macro allows for type safe conversions across the variadic parameter
++ * to vpx_codec_control_().
++ *
++ * \internal
++ * It works by dispatching the call to the control function through a wrapper
++ * function named with the id parameter.
++ */
++# define vpx_codec_control(ctx,id,data) vpx_codec_control_##id(ctx,id,data)\
++ /**<\hideinitializer*/
++
++
++ /*!\brief vpx_codec_control type definition macro
++ *
++ * This macro allows for type safe conversions across the variadic parameter
++ * to vpx_codec_control_(). It defines the type of the argument for a given
++ * control identifier.
++ *
++ * \internal
++ * It defines a static function with
++ * the correctly typed arguments as a wrapper to the type-unsafe internal
++ * function.
++ */
++# define VPX_CTRL_USE_TYPE(id, typ) \
++ static vpx_codec_err_t \
++ vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) UNUSED;\
++ \
++ static vpx_codec_err_t \
++ vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {\
++ return vpx_codec_control_(ctx, ctrl_id, data);\
++ } /**<\hideinitializer*/
++
++
++ /*!\brief vpx_codec_control deprecated type definition macro
++ *
++ * Like #VPX_CTRL_USE_TYPE, but indicates that the specified control is
++ * deprecated and should not be used. Consult the documentation for your
++ * codec for more information.
++ *
++ * \internal
++ * It defines a static function with the correctly typed arguments as a
++ * wrapper to the type-unsafe internal function.
++ */
++# define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
++ DECLSPEC_DEPRECATED static vpx_codec_err_t \
++ vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) DEPRECATED UNUSED;\
++ \
++ DECLSPEC_DEPRECATED static vpx_codec_err_t \
++ vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {\
++ return vpx_codec_control_(ctx, ctrl_id, data);\
++ } /**<\hideinitializer*/
++
++
++ /*!\brief vpx_codec_control void type definition macro
++ *
++ * This macro allows for type safe conversions across the variadic parameter
++ * to vpx_codec_control_(). It indicates that a given control identifier takes
++ * no argument.
++ *
++ * \internal
++ * It defines a static function without a data argument as a wrapper to the
++ * type-unsafe internal function.
++ */
++# define VPX_CTRL_VOID(id) \
++ static vpx_codec_err_t \
++ vpx_codec_control_##id(vpx_codec_ctx_t*, int) UNUSED;\
++ \
++ static vpx_codec_err_t \
++ vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id) {\
++ return vpx_codec_control_(ctx, ctrl_id);\
++ } /**<\hideinitializer*/
++
++
++#endif
++
++
++ /*!\defgroup cap_xma External Memory Allocation Functions
++ *
++ * The following functions are required to be implemented for all codecs
++ * that advertise the VPX_CODEC_CAP_XMA capability. Calling these functions
++ * for codecs that don't advertise this capability will result in an error
++ * code being returned, usually VPX_CODEC_INCAPABLE
++ * @{
++ */
++
++
++ /*!\brief Memory Map Entry
++ *
++ * This structure is used to contain the properties of a memory segment. It
++ * is populated by the codec in the request phase, and by the calling
++ * application once the requested allocation has been performed.
++ */
++ typedef struct vpx_codec_mmap
++ {
++ /*
++ * The following members are set by the codec when requesting a segment
++ */
++ unsigned int id; /**< identifier for the segment's contents */
++ unsigned long sz; /**< size of the segment, in bytes */
++ unsigned int align; /**< required alignment of the segment, in bytes */
++ unsigned int flags; /**< bitfield containing segment properties */
++#define VPX_CODEC_MEM_ZERO 0x1 /**< Segment must be zeroed by allocation */
++#define VPX_CODEC_MEM_WRONLY 0x2 /**< Segment need not be readable */
++#define VPX_CODEC_MEM_FAST 0x4 /**< Place in fast memory, if available */
++
++ /* The following members are to be filled in by the allocation function */
++ void *base; /**< pointer to the allocated segment */
++ void (*dtor)(struct vpx_codec_mmap *map); /**< destructor to call */
++ void *priv; /**< allocator private storage */
++ } vpx_codec_mmap_t; /**< alias for struct vpx_codec_mmap */
++
++
++ /*!\brief Iterate over the list of segments to allocate.
++ *
++ * Iterates over a list of the segments to allocate. The iterator storage
++ * should be initialized to NULL to start the iteration. Iteration is complete
++ * when this function returns VPX_CODEC_LIST_END. The amount of memory needed to
++ * allocate is dependant upon the size of the encoded stream. In cases where the
++ * stream is not available at allocation time, a fixed size must be requested.
++ * The codec will not be able to operate on streams larger than the size used at
++ * allocation time.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ * \param[out] mmap Pointer to the memory map entry to populate.
++ * \param[in,out] iter Iterator storage, initialized to NULL
++ *
++ * \retval #VPX_CODEC_OK
++ * The memory map entry was populated.
++ * \retval #VPX_CODEC_ERROR
++ * Codec does not support XMA mode.
++ * \retval #VPX_CODEC_MEM_ERROR
++ * Unable to determine segment size from stream info.
++ */
++ vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx,
++ vpx_codec_mmap_t *mmap,
++ vpx_codec_iter_t *iter);
++
++
++ /*!\brief Identify allocated segments to codec instance
++ *
++ * Stores a list of allocated segments in the codec. Segments \ref MUST be
++ * passed in the order they are read from vpx_codec_get_mem_map(), but may be
++ * passed in groups of any size. Segments \ref MUST be set only once. The
++ * allocation function \ref MUST ensure that the vpx_codec_mmap_t::base member
++ * is non-NULL. If the segment requires cleanup handling (eg, calling free()
++ * or close()) then the vpx_codec_mmap_t::dtor member \ref MUST be populated.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ * \param[in] mmaps Pointer to the first memory map entry in the list.
++ * \param[in] num_maps Number of entries being set at this time
++ *
++ * \retval #VPX_CODEC_OK
++ * The segment was stored in the codec context.
++ * \retval #VPX_CODEC_INCAPABLE
++ * Codec does not support XMA mode.
++ * \retval #VPX_CODEC_MEM_ERROR
++ * Segment base address was not set, or segment was already stored.
++
++ */
++ vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx,
++ vpx_codec_mmap_t *mmaps,
++ unsigned int num_maps);
++
++ /*!@} - end defgroup cap_xma*/
++ /*!@} - end defgroup codec*/
++
++
++#endif
++#ifdef __cplusplus
++}
++#endif
+diff --git a/vpx/vpx_codec.mk b/vpx/vpx_codec.mk
+new file mode 100644
+index 0000000..4e09b5f
+--- /dev/null
++++ b/vpx/vpx_codec.mk
+@@ -0,0 +1,27 @@
++##
++## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++##
++## Use of this source code is governed by a BSD-style license
++## that can be found in the LICENSE file in the root of the source
++## tree. An additional intellectual property rights grant can be found
++## in the file PATENTS. All contributing project authors may
++## be found in the AUTHORS file in the root of the source tree.
++##
++
++
++API_EXPORTS += exports
++
++API_SRCS-$(CONFIG_DECODERS) += src/vpx_decoder.c
++API_SRCS-$(CONFIG_DECODERS) += src/vpx_decoder_compat.c
++API_SRCS-$(CONFIG_DECODERS) += vpx_decoder.h
++API_SRCS-$(CONFIG_DECODERS) += vpx_decoder_compat.h
++API_SRCS-$(CONFIG_ENCODERS) += src/vpx_encoder.c
++API_SRCS-$(CONFIG_ENCODERS) += vpx_encoder.h
++API_SRCS-yes += internal/vpx_codec_internal.h
++API_SRCS-yes += src/vpx_codec.c
++API_SRCS-yes += src/vpx_image.c
++API_SRCS-yes += vpx_codec.h
++API_SRCS-yes += vpx_codec.mk
++API_SRCS-yes += vpx_codec_impl_bottom.h
++API_SRCS-yes += vpx_codec_impl_top.h
++API_SRCS-yes += vpx_image.h
+diff --git a/vpx/vpx_codec_impl_bottom.h b/vpx/vpx_codec_impl_bottom.h
+new file mode 100644
+index 0000000..02bf8b3
+--- /dev/null
++++ b/vpx/vpx_codec_impl_bottom.h
+@@ -0,0 +1,19 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*
++ * This file is to be included at the bottom of the header files defining the
++ * interface to individual codecs and contains matching blocks to those defined
++ * in vpx_codec_impl_top.h
++ */
++#ifdef __cplusplus
++}
++#endif
+diff --git a/vpx/vpx_codec_impl_top.h b/vpx/vpx_codec_impl_top.h
+new file mode 100644
+index 0000000..fce14c1
+--- /dev/null
++++ b/vpx/vpx_codec_impl_top.h
+@@ -0,0 +1,19 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*
++ * This file is to be included at the top of the header files defining the
++ * interface to individual codecs and contains various workarounds common
++ * to all codec implementations.
++ */
++#ifdef __cplusplus
++extern "C" {
++#endif
+diff --git a/vpx/vpx_decoder.h b/vpx/vpx_decoder.h
+new file mode 100644
+index 0000000..865f5df
+--- /dev/null
++++ b/vpx/vpx_decoder.h
+@@ -0,0 +1,317 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\defgroup decoder Decoder Algorithm Interface
++ * \ingroup codec
++ * This abstraction allows applications using this decoder to easily support
++ * multiple video formats with minimal code duplication. This section describes
++ * the interface common to all decoders.
++ * @{
++ */
++
++/*!\file vpx_decoder.h
++ * \brief Describes the decoder algorithm interface to applications.
++ *
++ * This file describes the interface between an application and a
++ * video decoder algorithm.
++ *
++ */
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef VPX_DECODER_H
++#define VPX_DECODER_H
++#include "vpx_codec.h"
++
++ /*!\brief Current ABI version number
++ *
++ * \internal
++ * If this file is altered in any way that changes the ABI, this value
++ * must be bumped. Examples include, but are not limited to, changing
++ * types, removing or reassigning enums, adding/removing/rearranging
++ * fields to structures
++ */
++#define VPX_DECODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
++
++ /*! \brief Decoder capabilities bitfield
++ *
++ * Each decoder advertises the capabilities it supports as part of its
++ * ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
++ * or functionality, and are not required to be supported by a decoder.
++ *
++ * The available flags are specifiedby VPX_CODEC_CAP_* defines.
++ */
++#define VPX_CODEC_CAP_PUT_SLICE 0x10000 /**< Will issue put_slice callbacks */
++#define VPX_CODEC_CAP_PUT_FRAME 0x20000 /**< Will issue put_frame callbacks */
++#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */
++
++ /*! \brief Initialization-time Feature Enabling
++ *
++ * Certain codec features must be known at initialization time, to allow for
++ * proper memory allocation.
++ *
++ * The available flags are specified by VPX_CODEC_USE_* defines.
++ */
++#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */
++
++ /*!\brief Stream properties
++ *
++ * This structure is used to query or set properties of the decoded
++ * stream. Algorithms may extend this structure with data specific
++ * to their bitstream by setting the sz member appropriately.
++ */
++ typedef struct vpx_codec_stream_info
++ {
++ unsigned int sz; /**< Size of this structure */
++ unsigned int w; /**< Width (or 0 for unknown/default) */
++ unsigned int h; /**< Height (or 0 for unknown/default) */
++ unsigned int is_kf; /**< Current frame is a keyframe */
++ } vpx_codec_stream_info_t;
++
++ /* REQUIRED FUNCTIONS
++ *
++ * The following functions are required to be implemented for all decoders.
++ * They represent the base case functionality expected of all decoders.
++ */
++
++
++ /*!\brief Initialization Configurations
++ *
++ * This structure is used to pass init time configuration options to the
++ * decoder.
++ */
++ typedef struct vpx_codec_dec_cfg
++ {
++ unsigned int threads; /**< Maximum number of threads to use, default 1 */
++ unsigned int w; /**< Width */
++ unsigned int h; /**< Height */
++ } vpx_codec_dec_cfg_t; /**< alias for struct vpx_codec_dec_cfg */
++
++
++ /*!\brief Initialize a decoder instance
++ *
++ * Initializes a decoder context using the given interface. Applications
++ * should call the vpx_codec_dec_init convenience macro instead of this
++ * function directly, to ensure that the ABI version number parameter
++ * is properly initialized.
++ *
++ * In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
++ * parameter), the storage pointed to by the cfg parameter must be
++ * kept readable and stable until all memory maps have been set.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ * \param[in] iface Pointer to the alogrithm interface to use.
++ * \param[in] cfg Configuration to use, if known. May be NULL.
++ * \param[in] flags Bitfield of VPX_CODEC_USE_* flags
++ * \param[in] ver ABI version number. Must be set to
++ * VPX_DECODER_ABI_VERSION
++ * \retval #VPX_CODEC_OK
++ * The decoder algorithm initialized.
++ * \retval #VPX_CODEC_MEM_ERROR
++ * Memory allocation failed.
++ */
++ vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx,
++ vpx_codec_iface_t *iface,
++ vpx_codec_dec_cfg_t *cfg,
++ vpx_codec_flags_t flags,
++ int ver);
++
++ /*!\brief Convenience macro for vpx_codec_dec_init_ver()
++ *
++ * Ensures the ABI version parameter is properly set.
++ */
++#define vpx_codec_dec_init(ctx, iface, cfg, flags) \
++ vpx_codec_dec_init_ver(ctx, iface, cfg, flags, VPX_DECODER_ABI_VERSION)
++
++
++ /*!\brief Parse stream info from a buffer
++ *
++ * Performs high level parsing of the bitstream. Construction of a decoder
++ * context is not necessary. Can be used to determine if the bitstream is
++ * of the proper format, and to extract information from the stream.
++ *
++ * \param[in] iface Pointer to the alogrithm interface
++ * \param[in] data Pointer to a block of data to parse
++ * \param[in] data_sz Size of the data buffer
++ * \param[in,out] si Pointer to stream info to update. The size member
++ * \ref MUST be properly initialized, but \ref MAY be
++ * clobbered by the algorithm. This parameter \ref MAY
++ * be NULL.
++ *
++ * \retval #VPX_CODEC_OK
++ * Bitstream is parsable and stream information updated
++ */
++ vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface,
++ const uint8_t *data,
++ unsigned int data_sz,
++ vpx_codec_stream_info_t *si);
++
++
++ /*!\brief Return information about the current stream.
++ *
++ * Returns information about the stream that has been parsed during decoding.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in,out] si Pointer to stream info to update. The size member
++ * \ref MUST be properly initialized, but \ref MAY be
++ * clobbered by the algorithm. This parameter \ref MAY
++ * be NULL.
++ *
++ * \retval #VPX_CODEC_OK
++ * Bitstream is parsable and stream information updated
++ */
++ vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx,
++ vpx_codec_stream_info_t *si);
++
++
++ /*!\brief Decode data
++ *
++ * Processes a buffer of coded data. If the processing results in a new
++ * decoded frame becoming available, PUT_SLICE and PUT_FRAME events may be
++ * generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode
++ * time stamp) order. Frames produced will always be in PTS (presentation
++ * time stamp) order.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] data Pointer to this block of new coded data. If
++ * NULL, a VPX_CODEC_CB_PUT_FRAME event is posted
++ * for the previously decoded frame.
++ * \param[in] data_sz Size of the coded data, in bytes.
++ * \param[in] user_priv Application specific data to associate with
++ * this frame.
++ * \param[in] deadline Soft deadline the decoder should attempt to meet,
++ * in us. Set to zero for unlimited.
++ *
++ * \return Returns #VPX_CODEC_OK if the coded data was processed completely
++ * and future pictures can be decoded without error. Otherwise,
++ * see the descriptions of the other error codes in ::vpx_codec_err_t
++ * for recoverability capabilities.
++ */
++ vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx,
++ const uint8_t *data,
++ unsigned int data_sz,
++ void *user_priv,
++ long deadline);
++
++
++ /*!\brief Decoded frames iterator
++ *
++ * Iterates over a list of the frames available for display. The iterator
++ * storage should be initialized to NULL to start the iteration. Iteration is
++ * complete when this function returns NULL.
++ *
++ * The list of available frames becomes valid upon completion of the
++ * vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in,out] iter Iterator storage, initialized to NULL
++ *
++ * \return Returns a pointer to an image, if one is ready for display. Frames
++ * produced will always be in PTS (presentation time stamp) order.
++ */
++ vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx,
++ vpx_codec_iter_t *iter);
++
++
++ /*!\defgroup cap_put_frame Frame-Based Decoding Functions
++ *
++ * The following functions are required to be implemented for all decoders
++ * that advertise the VPX_CODEC_CAP_PUT_FRAME capability. Calling these functions
++ * for codecs that don't advertise this capability will result in an error
++ * code being returned, usually VPX_CODEC_ERROR
++ * @{
++ */
++
++ /*!\brief put frame callback prototype
++ *
++ * This callback is invoked by the decoder to notify the application of
++ * the availability of decoded image data.
++ */
++ typedef void (*vpx_codec_put_frame_cb_fn_t)(void *user_priv,
++ const vpx_image_t *img);
++
++
++ /*!\brief Register for notification of frame completion.
++ *
++ * Registers a given function to be called when a decoded frame is
++ * available.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] cb Pointer to the callback function
++ * \param[in] user_priv User's private data
++ *
++ * \retval #VPX_CODEC_OK
++ * Callback successfully registered.
++ * \retval #VPX_CODEC_ERROR
++ * Decoder context not initialized, or algorithm not capable of
++ * posting slice completion.
++ */
++ vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx,
++ vpx_codec_put_frame_cb_fn_t cb,
++ void *user_priv);
++
++
++ /*!@} - end defgroup cap_put_frame */
++
++ /*!\defgroup cap_put_slice Slice-Based Decoding Functions
++ *
++ * The following functions are required to be implemented for all decoders
++ * that advertise the VPX_CODEC_CAP_PUT_SLICE capability. Calling these functions
++ * for codecs that don't advertise this capability will result in an error
++ * code being returned, usually VPX_CODEC_ERROR
++ * @{
++ */
++
++ /*!\brief put slice callback prototype
++ *
++ * This callback is invoked by the decoder to notify the application of
++ * the availability of partially decoded image data. The
++ */
++ typedef void (*vpx_codec_put_slice_cb_fn_t)(void *user_priv,
++ const vpx_image_t *img,
++ const vpx_image_rect_t *valid,
++ const vpx_image_rect_t *update);
++
++
++ /*!\brief Register for notification of slice completion.
++ *
++ * Registers a given function to be called when a decoded slice is
++ * available.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] cb Pointer to the callback function
++ * \param[in] user_priv User's private data
++ *
++ * \retval #VPX_CODEC_OK
++ * Callback successfully registered.
++ * \retval #VPX_CODEC_ERROR
++ * Decoder context not initialized, or algorithm not capable of
++ * posting slice completion.
++ */
++ vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx,
++ vpx_codec_put_slice_cb_fn_t cb,
++ void *user_priv);
++
++
++ /*!@} - end defgroup cap_put_slice*/
++
++ /*!@} - end defgroup decoder*/
++
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
++#include "vpx_decoder_compat.h"
++#endif
+diff --git a/vpx/vpx_decoder_compat.h b/vpx/vpx_decoder_compat.h
+new file mode 100644
+index 0000000..e66a096
+--- /dev/null
++++ b/vpx/vpx_decoder_compat.h
+@@ -0,0 +1,587 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\defgroup decoder Common Decoder Algorithm Interface
++ * This abstraction allows applications using this decoder to easily support
++ * multiple video formats with minimal code duplication. This section describes
++ * the interface common to all codecs.
++ * @{
++ */
++
++/*!\file vpx_decoder_compat.h
++ * \brief Provides a compatibility layer between version 1 and 2 of this API.
++ *
++ * This interface has been deprecated. Only existing code should make use
++ * of this interface, and therefore, it is only thinly documented. Existing
++ * code should be ported to the vpx_codec_* API.
++ */
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef VPX_DECODER_COMPAT_H
++#define VPX_DECODER_COMPAT_H
++
++ /*!\brief Decoder algorithm return codes */
++ typedef enum {
++ /*!\brief Operation completed without error */
++ VPX_DEC_OK = VPX_CODEC_OK,
++
++ /*!\brief Unspecified error */
++ VPX_DEC_ERROR = VPX_CODEC_ERROR,
++
++ /*!\brief Memory operation failed */
++ VPX_DEC_MEM_ERROR = VPX_CODEC_MEM_ERROR,
++
++ /*!\brief ABI version mismatch */
++ VPX_DEC_ABI_MISMATCH = VPX_CODEC_ABI_MISMATCH,
++
++ /*!\brief The given bitstream is not supported.
++ *
++ * The bitstream was unable to be parsed at the highest level. The decoder
++ * is unable to proceed. This error \ref SHOULD be treated as fatal to the
++ * stream. */
++ VPX_DEC_UNSUP_BITSTREAM = VPX_CODEC_UNSUP_BITSTREAM,
++
++ /*!\brief Encoded bitstream uses an unsupported feature
++ *
++ * The decoder does not implement a feature required by the encoder. This
++ * return code should only be used for features that prevent future
++ * pictures from being properly decoded. This error \ref MAY be treated as
++ * fatal to the stream or \ref MAY be treated as fatal to the current GOP.
++ */
++ VPX_DEC_UNSUP_FEATURE = VPX_CODEC_UNSUP_FEATURE,
++
++ /*!\brief The coded data for this stream is corrupt or incomplete
++ *
++ * There was a problem decoding the current frame. This return code
++ * should only be used for failures that prevent future pictures from
++ * being properly decoded. This error \ref MAY be treated as fatal to the
++ * stream or \ref MAY be treated as fatal to the current GOP. If decoding
++ * is continued for the current GOP, artifacts may be present.
++ */
++ VPX_DEC_CORRUPT_FRAME = VPX_CODEC_CORRUPT_FRAME,
++
++ /*!\brief An application-supplied parameter is not valid.
++ *
++ */
++ VPX_DEC_INVALID_PARAM = VPX_CODEC_INVALID_PARAM,
++
++ /*!\brief An iterator reached the end of list.
++ *
++ */
++ VPX_DEC_LIST_END = VPX_CODEC_LIST_END,
++
++ }
++ vpx_dec_err_t;
++
++ /*! \brief Decoder capabilities bitfield
++ *
++ * Each decoder advertises the capabilities it supports as part of its
++ * ::vpx_dec_iface_t interface structure. Capabilities are extra interfaces
++ * or functionality, and are not required to be supported by a decoder.
++ *
++ * The available flags are specifiedby VPX_DEC_CAP_* defines.
++ */
++ typedef int vpx_dec_caps_t;
++#define VPX_DEC_CAP_PUT_SLICE 0x0001 /**< Will issue put_slice callbacks */
++#define VPX_DEC_CAP_PUT_FRAME 0x0002 /**< Will issue put_frame callbacks */
++#define VPX_DEC_CAP_XMA 0x0004 /**< Supports e_xternal Memory Allocation */
++
++ /*!\brief Stream properties
++ *
++ * This structure is used to query or set properties of the decoded
++ * stream. Algorithms may extend this structure with data specific
++ * to their bitstream by setting the sz member appropriately.
++ */
++#if 1
++ typedef vpx_codec_stream_info_t vpx_dec_stream_info_t;
++#else
++ typedef struct
++ {
++ unsigned int sz; /**< Size of this structure */
++ unsigned int w; /**< Width (or 0 for unknown/default) */
++ unsigned int h; /**< Height (or 0 for unknown/default) */
++ unsigned int is_kf; /**< Current frame is a keyframe */
++ } vpx_dec_stream_info_t;
++#endif
++
++
++ /*!\brief Decoder interface structure.
++ *
++ * Contains function pointers and other data private to the decoder
++ * implementation. This structure is opaque to the application.
++ */
++ typedef const struct vpx_codec_iface vpx_dec_iface_t;
++ typedef struct vpx_codec_priv vpx_dec_priv_t;
++
++ /*!\brief Iterator
++ *
++ * Opaque storage used for iterating over lists.
++ */
++ typedef vpx_codec_iter_t vpx_dec_iter_t;
++
++ /*!\brief Decoder context structure
++ *
++ * All decoders \ref MUST support this context structure fully. In general,
++ * this data should be considered private to the decoder algorithm, and
++ * not be manipulated or examined by the calling application. Applications
++ * may reference the 'name' member to get a printable description of the
++ * algorithm.
++ */
++#if 1
++ typedef vpx_codec_ctx_t vpx_dec_ctx_t;
++#else
++ typedef struct
++ {
++ const char *name; /**< Printable interface name */
++ vpx_dec_iface_t *iface; /**< Interface pointers */
++ vpx_dec_err_t err; /**< Last returned error */
++ vpx_dec_priv_t *priv; /**< Algorithm private storage */
++ } vpx_dec_ctx_t;
++#endif
++
++
++ /*!\brief Return the build configuration
++ *
++ * Returns a printable string containing an encoded version of the build
++ * configuration. This may be useful to vpx support.
++ *
++ */
++ const char *vpx_dec_build_config(void) DEPRECATED;
++
++ /*!\brief Return the name for a given interface
++ *
++ * Returns a human readable string for name of the given decoder interface.
++ *
++ * \param[in] iface Interface pointer
++ *
++ */
++ const char *vpx_dec_iface_name(vpx_dec_iface_t *iface) DEPRECATED;
++
++
++ /*!\brief Convert error number to printable string
++ *
++ * Returns a human readable string for the last error returned by the
++ * algorithm. The returned error will be one line and will not contain
++ * any newline characters.
++ *
++ *
++ * \param[in] err Error number.
++ *
++ */
++ const char *vpx_dec_err_to_string(vpx_dec_err_t err) DEPRECATED;
++
++
++ /*!\brief Retrieve error synopsis for decoder context
++ *
++ * Returns a human readable string for the last error returned by the
++ * algorithm. The returned error will be one line and will not contain
++ * any newline characters.
++ *
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ *
++ */
++ const char *vpx_dec_error(vpx_dec_ctx_t *ctx) DEPRECATED;
++
++
++ /*!\brief Retrieve detailed error information for decoder context
++ *
++ * Returns a human readable string providing detailed information about
++ * the last error.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ *
++ * \retval NULL
++ * No detailed information is available.
++ */
++ const char *vpx_dec_error_detail(vpx_dec_ctx_t *ctx) DEPRECATED;
++
++
++ /* REQUIRED FUNCTIONS
++ *
++ * The following functions are required to be implemented for all decoders.
++ * They represent the base case functionality expected of all decoders.
++ */
++
++
++ /*!\brief Initialize a decoder instance
++ *
++ * Initializes a decoder context using the given interface. Applications
++ * should call the vpx_dec_init convenience macro instead of this
++ * function directly, to ensure that the ABI version number parameter
++ * is properly initialized.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ * \param[in] iface Pointer to the alogrithm interface to use.
++ * \param[in] ver ABI version number. Must be set to
++ * VPX_DECODER_ABI_VERSION
++ * \retval #VPX_DEC_OK
++ * The decoder algorithm initialized.
++ * \retval #VPX_DEC_MEM_ERROR
++ * Memory allocation failed.
++ */
++ vpx_dec_err_t vpx_dec_init_ver(vpx_dec_ctx_t *ctx,
++ vpx_dec_iface_t *iface,
++ int ver) DEPRECATED;
++#define vpx_dec_init(ctx, iface) \
++ vpx_dec_init_ver(ctx, iface, VPX_DECODER_ABI_VERSION)
++
++
++ /*!\brief Destroy a decoder instance
++ *
++ * Destroys a decoder context, freeing any associated memory buffers.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ *
++ * \retval #VPX_DEC_OK
++ * The decoder algorithm initialized.
++ * \retval #VPX_DEC_MEM_ERROR
++ * Memory allocation failed.
++ */
++ vpx_dec_err_t vpx_dec_destroy(vpx_dec_ctx_t *ctx) DEPRECATED;
++
++
++ /*!\brief Get the capabilities of an algorithm.
++ *
++ * Retrieves the capabliities bitfield from the algorithm's interface.
++ *
++ * \param[in] iface Pointer to the alogrithm interface
++ *
++ */
++ vpx_dec_caps_t vpx_dec_get_caps(vpx_dec_iface_t *iface) DEPRECATED;
++
++
++ /*!\brief Parse stream info from a buffer
++ *
++ * Performs high level parsing of the bitstream. Construction of a decoder
++ * context is not necessary. Can be used to determine if the bitstream is
++ * of the proper format, and to extract information from the stream.
++ *
++ * \param[in] iface Pointer to the alogrithm interface
++ * \param[in] data Pointer to a block of data to parse
++ * \param[in] data_sz Size of the data buffer
++ * \param[in,out] si Pointer to stream info to update. The size member
++ * \ref MUST be properly initialized, but \ref MAY be
++ * clobbered by the algorithm. This parameter \ref MAY
++ * be NULL.
++ *
++ * \retval #VPX_DEC_OK
++ * Bitstream is parsable and stream information updated
++ */
++ vpx_dec_err_t vpx_dec_peek_stream_info(vpx_dec_iface_t *iface,
++ const uint8_t *data,
++ unsigned int data_sz,
++ vpx_dec_stream_info_t *si) DEPRECATED;
++
++
++ /*!\brief Return information about the current stream.
++ *
++ * Returns information about the stream that has been parsed during decoding.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in,out] si Pointer to stream info to update. The size member
++ * \ref MUST be properly initialized, but \ref MAY be
++ * clobbered by the algorithm. This parameter \ref MAY
++ * be NULL.
++ *
++ * \retval #VPX_DEC_OK
++ * Bitstream is parsable and stream information updated
++ */
++ vpx_dec_err_t vpx_dec_get_stream_info(vpx_dec_ctx_t *ctx,
++ vpx_dec_stream_info_t *si) DEPRECATED;
++
++
++ /*!\brief Control algorithm
++ *
++ * This function is used to exchange algorithm specific data with the decoder
++ * instance. This can be used to implement features specific to a particular
++ * algorithm.
++ *
++ * This wrapper function dispatches the request to the helper function
++ * associated with the given ctrl_id. It tries to call this function
++ * transparantly, but will return #VPX_DEC_ERROR if the request could not
++ * be dispatched.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] ctrl_id Algorithm specific control identifier
++ * \param[in,out] data Data to exchange with algorithm instance.
++ *
++ * \retval #VPX_DEC_OK
++ * The control request was processed.
++ * \retval #VPX_DEC_ERROR
++ * The control request was not processed.
++ * \retval #VPX_DEC_INVALID_PARAM
++ * The data was not valid.
++ */
++ vpx_dec_err_t vpx_dec_control(vpx_dec_ctx_t *ctx,
++ int ctrl_id,
++ void *data) DEPRECATED;
++
++ /*!\brief Decode data
++ *
++ * Processes a buffer of coded data. If the processing results in a new
++ * decoded frame becoming available, #VPX_DEC_CB_PUT_SLICE and
++ * #VPX_DEC_CB_PUT_FRAME events may be generated, as appropriate. Encoded data
++ * \ref MUST be passed in DTS (decode time stamp) order. Frames produced will
++ * always be in PTS (presentation time stamp) order.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] data Pointer to this block of new coded data. If
++ * NULL, a VPX_DEC_CB_PUT_FRAME event is posted
++ * for the previously decoded frame.
++ * \param[in] data_sz Size of the coded data, in bytes.
++ * \param[in] user_priv Application specific data to associate with
++ * this frame.
++ * \param[in] rel_pts PTS relative to the previous frame, in us. If
++ * unknown or unavailable, set to zero.
++ *
++ * \return Returns #VPX_DEC_OK if the coded data was processed completely
++ * and future pictures can be decoded without error. Otherwise,
++ * see the descriptions of the other error codes in ::vpx_dec_err_t
++ * for recoverability capabilities.
++ */
++ vpx_dec_err_t vpx_dec_decode(vpx_dec_ctx_t *ctx,
++ uint8_t *data,
++ unsigned int data_sz,
++ void *user_priv,
++ int rel_pts) DEPRECATED;
++
++
++ /*!\brief Decoded frames iterator
++ *
++ * Iterates over a list of the frames available for display. The iterator
++ * storage should be initialized to NULL to start the iteration. Iteration is
++ * complete when this function returns NULL.
++ *
++ * The list of available frames becomes valid upon completion of the
++ * vpx_dec_decode call, and remains valid until the next call to vpx_dec_decode.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in out] iter Iterator storage, initialized to NULL
++ *
++ * \return Returns a pointer to an image, if one is ready for display. Frames
++ * produced will always be in PTS (presentation time stamp) order.
++ */
++ vpx_image_t *vpx_dec_get_frame(vpx_dec_ctx_t *ctx,
++ vpx_dec_iter_t *iter) DEPRECATED;
++
++
++ /*!\defgroup cap_put_frame Frame-Based Decoding Functions
++ *
++ * The following functions are required to be implemented for all decoders
++ * that advertise the VPX_DEC_CAP_PUT_FRAME capability. Calling these functions
++ * for codecs that don't advertise this capability will result in an error
++ * code being returned, usually VPX_DEC_ERROR
++ * @{
++ */
++
++ /*!\brief put frame callback prototype
++ *
++ * This callback is invoked by the decoder to notify the application of
++ * the availability of decoded image data.
++ */
++ typedef void (*vpx_dec_put_frame_cb_fn_t)(void *user_priv,
++ const vpx_image_t *img);
++
++
++ /*!\brief Register for notification of frame completion.
++ *
++ * Registers a given function to be called when a decoded frame is
++ * available.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] cb Pointer to the callback function
++ * \param[in] user_priv User's private data
++ *
++ * \retval #VPX_DEC_OK
++ * Callback successfully registered.
++ * \retval #VPX_DEC_ERROR
++ * Decoder context not initialized, or algorithm not capable of
++ * posting slice completion.
++ */
++ vpx_dec_err_t vpx_dec_register_put_frame_cb(vpx_dec_ctx_t *ctx,
++ vpx_dec_put_frame_cb_fn_t cb,
++ void *user_priv) DEPRECATED;
++
++
++ /*!@} - end defgroup cap_put_frame */
++
++ /*!\defgroup cap_put_slice Slice-Based Decoding Functions
++ *
++ * The following functions are required to be implemented for all decoders
++ * that advertise the VPX_DEC_CAP_PUT_SLICE capability. Calling these functions
++ * for codecs that don't advertise this capability will result in an error
++ * code being returned, usually VPX_DEC_ERROR
++ * @{
++ */
++
++ /*!\brief put slice callback prototype
++ *
++ * This callback is invoked by the decoder to notify the application of
++ * the availability of partially decoded image data. The
++ */
++ typedef void (*vpx_dec_put_slice_cb_fn_t)(void *user_priv,
++ const vpx_image_t *img,
++ const vpx_image_rect_t *valid,
++ const vpx_image_rect_t *update);
++
++
++ /*!\brief Register for notification of slice completion.
++ *
++ * Registers a given function to be called when a decoded slice is
++ * available.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] cb Pointer to the callback function
++ * \param[in] user_priv User's private data
++ *
++ * \retval #VPX_DEC_OK
++ * Callback successfully registered.
++ * \retval #VPX_DEC_ERROR
++ * Decoder context not initialized, or algorithm not capable of
++ * posting slice completion.
++ */
++ vpx_dec_err_t vpx_dec_register_put_slice_cb(vpx_dec_ctx_t *ctx,
++ vpx_dec_put_slice_cb_fn_t cb,
++ void *user_priv) DEPRECATED;
++
++
++ /*!@} - end defgroup cap_put_slice*/
++
++ /*!\defgroup cap_xma External Memory Allocation Functions
++ *
++ * The following functions are required to be implemented for all decoders
++ * that advertise the VPX_DEC_CAP_XMA capability. Calling these functions
++ * for codecs that don't advertise this capability will result in an error
++ * code being returned, usually VPX_DEC_ERROR
++ * @{
++ */
++
++ /*!\brief Memory Map Entry
++ *
++ * This structure is used to contain the properties of a memory segment. It
++ * is populated by the decoder in the request phase, and by the calling
++ * application once the requested allocation has been performed.
++ */
++#if 1
++#define VPX_DEC_MEM_ZERO 0x1 /**< Segment must be zeroed by allocation */
++#define VPX_DEC_MEM_WRONLY 0x2 /**< Segment need not be readable */
++#define VPX_DEC_MEM_FAST 0x4 /**< Place in fast memory, if available */
++ typedef struct vpx_codec_mmap vpx_dec_mmap_t;
++#else
++ typedef struct vpx_dec_mmap
++ {
++ /*
++ * The following members are set by the codec when requesting a segment
++ */
++ unsigned int id; /**< identifier for the segment's contents */
++ unsigned long sz; /**< size of the segment, in bytes */
++ unsigned int align; /**< required alignment of the segment, in bytes */
++ unsigned int flags; /**< bitfield containing segment properties */
++#define VPX_DEC_MEM_ZERO 0x1 /**< Segment must be zeroed by allocation */
++#define VPX_DEC_MEM_WRONLY 0x2 /**< Segment need not be readable */
++#define VPX_DEC_MEM_FAST 0x4 /**< Place in fast memory, if available */
++
++ /* The following members are to be filled in by the allocation function */
++ void *base; /**< pointer to the allocated segment */
++ void (*dtor)(struct vpx_dec_mmap *map); /**< destructor to call */
++ void *priv; /**< allocator private storage */
++ } vpx_dec_mmap_t;
++#endif
++
++ /*!\brief Initialize a decoder instance in external allocation mode
++ *
++ * Initializes a decoder context using the given interface. Applications
++ * should call the vpx_dec_xma_init convenience macro instead of this
++ * function directly, to ensure that the ABI version number parameter
++ * is properly initialized.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ * \param[in] iface Pointer to the alogrithm interface to use.
++ * \param[in] ver ABI version number. Must be set to
++ * VPX_DECODER_ABI_VERSION
++ * \retval #VPX_DEC_OK
++ * The decoder algorithm initialized.
++ * \retval #VPX_DEC_ERROR
++ * Decoder does not support XMA mode.
++ */
++ vpx_dec_err_t vpx_dec_xma_init_ver(vpx_dec_ctx_t *ctx,
++ vpx_dec_iface_t *iface,
++ int ver) DEPRECATED;
++#define vpx_dec_xma_init(ctx, iface) \
++ vpx_dec_xma_init_ver(ctx, iface, VPX_DECODER_ABI_VERSION)
++
++
++ /*!\brief Iterate over the list of segments to allocate.
++ *
++ * Iterates over a list of the segments to allocate. The iterator storage
++ * should be initialized to NULL to start the iteration. Iteration is complete
++ * when this function returns VPX_DEC_LIST_END. The amount of memory needed to
++ * allocate is dependant upon the size of the encoded stream. This means that
++ * the stream info structure must be known at allocation time. It can be
++ * populated with the vpx_dec_peek_stream_info() function. In cases where the
++ * stream to be decoded is not available at allocation time, a fixed size must
++ * be requested. The decoder will not be able to decode streams larger than
++ * the size used at allocation time.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ * \param[out] mmap Pointer to the memory map entry to populate.
++ * \param[in] si Pointer to the stream info.
++ * \param[in out] iter Iterator storage, initialized to NULL
++ *
++ * \retval #VPX_DEC_OK
++ * The memory map entry was populated.
++ * \retval #VPX_DEC_ERROR
++ * Decoder does not support XMA mode.
++ * \retval #VPX_DEC_MEM_ERROR
++ * Unable to determine segment size from stream info.
++ */
++ vpx_dec_err_t vpx_dec_get_mem_map(vpx_dec_ctx_t *ctx,
++ vpx_dec_mmap_t *mmap,
++ const vpx_dec_stream_info_t *si,
++ vpx_dec_iter_t *iter) DEPRECATED;
++
++
++ /*!\brief Identify allocated segments to decoder instance
++ *
++ * Stores a list of allocated segments in the decoder. Segments \ref MUST be
++ * passed in the order they are read from vpx_dec_get_mem_map(), but may be
++ * passed in groups of any size. Segments \ref MUST be set only once. The
++ * allocation function \ref MUST ensure that the vpx_dec_mmap_t::base member
++ * is non-NULL. If the segment requires cleanup handling (eg, calling free()
++ * or close()) then the vpx_dec_mmap_t::dtor member \ref MUST be populated.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ * \param[in] mmaps Pointer to the first memory map entry in the list.
++ * \param[in] num_maps Number of entries being set at this time
++ *
++ * \retval #VPX_DEC_OK
++ * The segment was stored in the decoder context.
++ * \retval #VPX_DEC_ERROR
++ * Decoder does not support XMA mode.
++ * \retval #VPX_DEC_MEM_ERROR
++ * Segment base address was not set, or segment was already stored.
++
++ */
++ vpx_dec_err_t vpx_dec_set_mem_map(vpx_dec_ctx_t *ctx,
++ vpx_dec_mmap_t *mmaps,
++ unsigned int num_maps) DEPRECATED;
++
++ /*!@} - end defgroup cap_xma*/
++ /*!@} - end defgroup decoder*/
++
++
++#endif
++#ifdef __cplusplus
++}
++#endif
+diff --git a/vpx/vpx_encoder.h b/vpx/vpx_encoder.h
+new file mode 100644
+index 0000000..8ad7055
+--- /dev/null
++++ b/vpx/vpx_encoder.h
+@@ -0,0 +1,793 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\defgroup encoder Encoder Algorithm Interface
++ * \ingroup codec
++ * This abstraction allows applications using this encoder to easily support
++ * multiple video formats with minimal code duplication. This section describes
++ * the interface common to all encoders.
++ * @{
++ */
++
++/*!\file vpx_encoder.h
++ * \brief Describes the encoder algorithm interface to applications.
++ *
++ * This file describes the interface between an application and a
++ * video encoder algorithm.
++ *
++ */
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef VPX_ENCODER_H
++#define VPX_ENCODER_H
++#include "vpx_codec.h"
++
++
++ /*!\brief Current ABI version number
++ *
++ * \internal
++ * If this file is altered in any way that changes the ABI, this value
++ * must be bumped. Examples include, but are not limited to, changing
++ * types, removing or reassigning enums, adding/removing/rearranging
++ * fields to structures
++ */
++#define VPX_ENCODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
++
++
++ /*! \brief Encoder capabilities bitfield
++ *
++ * Each encoder advertises the capabilities it supports as part of its
++ * ::vpx_codec_iface_t interface structure. Capabilities are extra
++ * interfaces or functionality, and are not required to be supported
++ * by an encoder.
++ *
++ * The available flags are specifiedby VPX_CODEC_CAP_* defines.
++ */
++#define VPX_CODEC_CAP_PSNR 0x10000 /**< Can issue PSNR packets */
++
++
++ /*! \brief Initialization-time Feature Enabling
++ *
++ * Certain codec features must be known at initialization time, to allow
++ * for proper memory allocation.
++ *
++ * The available flags are specified by VPX_CODEC_USE_* defines.
++ */
++#define VPX_CODEC_USE_PSNR 0x10000 /**< Calculate PSNR on each frame */
++
++
++ /*!\brief Generic fixed size buffer structure
++ *
++ * This structure is able to hold a reference to any fixed size buffer.
++ */
++ typedef struct vpx_fixed_buf
++ {
++ void *buf; /**< Pointer to the data */
++ size_t sz; /**< Length of the buffer, in chars */
++ } vpx_fixed_buf_t; /**< alias for struct vpx_fixed_buf */
++
++
++ /*!\brief Time Stamp Type
++ *
++ * An integer, which when multiplied by the stream's time base, provides
++ * the absolute time of a sample.
++ */
++ typedef int64_t vpx_codec_pts_t;
++
++
++ /*!\brief Compressed Frame Flags
++ *
++ * This type represents a bitfield containing information about a compressed
++ * frame that may be useful to an application. The most significant 16 bits
++ * can be used by an algorithm to provide additional detail, for example to
++ * support frame types that are codec specific (MPEG-1 D-frames for example)
++ */
++ typedef uint32_t vpx_codec_frame_flags_t;
++#define VPX_FRAME_IS_KEY 0x1 /**< frame is the start of a GOP */
++#define VPX_FRAME_IS_DROPPABLE 0x2 /**< frame can be dropped without affecting
++ the stream (no future frame depends on
++ this one) */
++#define VPX_FRAME_IS_INVISIBLE 0x4 /**< frame should be decoded but will not
++ be shown */
++
++
++ /*!\brief Encoder output packet variants
++ *
++ * This enumeration lists the different kinds of data packets that can be
++ * returned by calls to vpx_codec_get_cx_data(). Algorithms \ref MAY
++ * extend this list to provide additional functionality.
++ */
++ enum vpx_codec_cx_pkt_kind
++ {
++ VPX_CODEC_CX_FRAME_PKT, /**< Compressed video frame */
++ VPX_CODEC_STATS_PKT, /**< Two-pass statistics for this frame */
++ VPX_CODEC_PSNR_PKT, /**< PSNR statistics for this frame */
++ VPX_CODEC_CUSTOM_PKT = 256 /**< Algorithm extensions */
++ };
++
++
++ /*!\brief Encoder output packet
++ *
++ * This structure contains the different kinds of output data the encoder
++ * may produce while compressing a frame.
++ */
++ typedef struct vpx_codec_cx_pkt
++ {
++ enum vpx_codec_cx_pkt_kind kind; /**< packet variant */
++ union
++ {
++ struct
++ {
++ void *buf; /**< compressed data buffer */
++ size_t sz; /**< length of compressed data */
++ vpx_codec_pts_t pts; /**< time stamp to show frame
++ (in timebase units) */
++ unsigned long duration; /**< duration to show frame
++ (in timebase units) */
++ vpx_codec_frame_flags_t flags; /**< flags for this frame */
++ } frame; /**< data for compressed frame packet */
++ struct vpx_fixed_buf twopass_stats; /**< data for two-pass packet */
++ struct vpx_psnr_pkt
++ {
++ unsigned int samples[4]; /**< Number of samples, total/y/u/v */
++ uint64_t sse[4]; /**< sum squared error, total/y/u/v */
++ double psnr[4]; /**< PSNR, total/y/u/v */
++ } psnr; /**< data for PSNR packet */
++ struct vpx_fixed_buf raw; /**< data for arbitrary packets */
++
++ /* This packet size is fixed to allow codecs to extend this
++ * interface without having to manage storage for raw packets,
++ * ie if it's smaller than 128 bytes, you can store in the
++ * packet list directly.
++ */
++ char pad[128 - sizeof(enum vpx_codec_cx_pkt_kind)]; /**< fixed sz */
++ } data; /**< packet data */
++ } vpx_codec_cx_pkt_t; /**< alias for struct vpx_codec_cx_pkt */
++
++
++ /*!\brief Rational Number
++ *
++ * This structure holds a fractional value.
++ */
++ typedef struct vpx_rational
++ {
++ int num; /**< fraction numerator */
++ int den; /**< fraction denominator */
++ } vpx_rational_t; /**< alias for struct vpx_rational */
++
++
++ /*!\brief Multi-pass Encoding Pass */
++ enum vpx_enc_pass
++ {
++ VPX_RC_ONE_PASS, /**< Single pass mode */
++ VPX_RC_FIRST_PASS, /**< First pass of multi-pass mode */
++ VPX_RC_LAST_PASS, /**< Final pass of multi-pass mode */
++ };
++
++
++ /*!\brief Rate control mode */
++ enum vpx_rc_mode
++ {
++ VPX_VBR, /**< Variable Bit Rate (VBR) mode */
++ VPX_CBR /**< Constant Bit Rate (CBR) mode */
++ };
++
++
++ /*!\brief Keyframe placement mode.
++ *
++ * This enumeration determines whether keyframes are placed automatically by
++ * the encoder or whether this behavior is disabled. Older releases of this
++ * SDK were implemented such that VPX_KF_FIXED meant keyframes were disabled.
++ * This name is confusing for this behavior, so the new symbols to be used
++ * are VPX_KF_AUTO and VPX_KF_DISABLED.
++ */
++ enum vpx_kf_mode
++ {
++ VPX_KF_FIXED, /**< deprecated, implies VPX_KF_DISABLED */
++ VPX_KF_AUTO, /**< Encoder determines optimal placement automatically */
++ VPX_KF_DISABLED = 0 /**< Encoder does not place keyframes. */
++ };
++
++
++ /*!\brief Encoded Frame Flags
++ *
++ * This type indicates a bitfield to be passed to vpx_codec_encode(), defining
++ * per-frame boolean values. By convention, bits common to all codecs will be
++ * named VPX_EFLAG_*, and bits specific to an algorithm will be named
++ * /algo/_eflag_*. The lower order 16 bits are reserved for common use.
++ */
++ typedef long vpx_enc_frame_flags_t;
++#define VPX_EFLAG_FORCE_KF (1<<0) /**< Force this frame to be a keyframe */
++
++
++ /*!\brief Encoder configuration structure
++ *
++ * This structure contains the encoder settings that have common representations
++ * across all codecs. This doesn't imply that all codecs support all features,
++ * however.
++ */
++ typedef struct vpx_codec_enc_cfg
++ {
++ /*
++ * generic settings (g)
++ */
++
++ /*!\brief Algorithm specific "usage" value
++ *
++ * Algorithms may define multiple values for usage, which may convey the
++ * intent of how the application intends to use the stream. If this value
++ * is non-zero, consult the documentation for the codec to determine its
++ * meaning.
++ */
++ unsigned int g_usage;
++
++
++ /*!\brief Maximum number of threads to use
++ *
++ * For multi-threaded implementations, use no more than this number of
++ * threads. The codec may use fewer threads than allowed. The value
++ * 0 is equivalent to the value 1.
++ */
++ unsigned int g_threads;
++
++
++ /*!\brief Bitstream profile to use
++ *
++ * Some codecs support a notion of multiple bitstream profiles. Typically
++ * this maps to a set of features that are turned on or off. Often the
++ * profile to use is determined by the features of the intended decoder.
++ * Consult the documentation for the codec to determine the valid values
++ * for this parameter, or set to zero for a sane default.
++ */
++ unsigned int g_profile; /**< profile of bitstream to use */
++
++
++
++ /*!\brief Width of the frame
++ *
++ * This value identifies the presentation resolution of the frame,
++ * in pixels. Note that the frames passed as input to the encoder must
++ * have this resolution. Frames will be presented by the decoder in this
++ * resolution, independent of any spatial resampling the encoder may do.
++ */
++ unsigned int g_w;
++
++
++ /*!\brief Height of the frame
++ *
++ * This value identifies the presentation resolution of the frame,
++ * in pixels. Note that the frames passed as input to the encoder must
++ * have this resolution. Frames will be presented by the decoder in this
++ * resolution, independent of any spatial resampling the encoder may do.
++ */
++ unsigned int g_h;
++
++
++ /*!\brief Stream timebase units
++ *
++ * Indicates the smallest interval of time, in seconds, used by the stream.
++ * For fixed frame rate material, or variable frame rate material where
++ * frames are timed at a multiple of a given clock (ex: video capture),
++ * the \ref RECOMMENDED method is to set the timebase to the reciprocal
++ * of the frame rate (ex: 1001/30000 for 29.970 Hz NTSC). This allows the
++ * pts to correspond to the frame number, which can be handy. For
++ * re-encoding video from containers with absolute time timestamps, the
++ * \ref RECOMMENDED method is to set the timebase to that of the parent
++ * container or multimedia framework (ex: 1/1000 for ms, as in FLV).
++ */
++ struct vpx_rational g_timebase;
++
++
++ /*!\brief Enable error resilient mode.
++ *
++ * Error resilient mode indicates to the encoder that it should take
++ * measures appropriate for streaming over lossy or noisy links, if
++ * possible. Set to 1 to enable this feature, 0 to disable it.
++ */
++ unsigned int g_error_resilient;
++
++
++ /*!\brief Multi-pass Encoding Mode
++ *
++ * This value should be set to the current phase for multi-pass encoding.
++ * For single pass, set to #VPX_RC_ONE_PASS.
++ */
++ enum vpx_enc_pass g_pass;
++
++
++ /*!\brief Allow lagged encoding
++ *
++ * If set, this value allows the encoder to consume a number of input
++ * frames before producing output frames. This allows the encoder to
++ * base decisions for the current frame on future frames. This does
++ * increase the latency of the encoding pipeline, so it is not appropriate
++ * in all situations (ex: realtime encoding).
++ *
++ * Note that this is a maximum value -- the encoder may produce frames
++ * sooner than the given limit. Set this value to 0 to disable this
++ * feature.
++ */
++ unsigned int g_lag_in_frames;
++
++
++ /*
++ * rate control settings (rc)
++ */
++
++ /*!\brief Temporal resampling configuration, if supported by the codec.
++ *
++ * Temporal resampling allows the codec to "drop" frames as a strategy to
++ * meet its target data rate. This can cause temporal discontinuities in
++ * the encoded video, which may appear as stuttering during playback. This
++ * trade-off is often acceptable, but for many applications is not. It can
++ * be disabled in these cases.
++ *
++ * Note that not all codecs support this feature. All vpx VPx codecs do.
++ * For other codecs, consult the documentation for that algorithm.
++ *
++ * This threshold is described as a percentage of the target data buffer.
++ * When the data buffer falls below this percentage of fullness, a
++ * dropped frame is indicated. Set the threshold to zero (0) to disable
++ * this feature.
++ */
++ unsigned int rc_dropframe_thresh;
++
++
++ /*!\brief Enable/disable spatial resampling, if supported by the codec.
++ *
++ * Spatial resampling allows the codec to compress a lower resolution
++ * version of the frame, which is then upscaled by the encoder to the
++ * correct presentation resolution. This increases visual quality at
++ * low data rates, at the expense of CPU time on the encoder/decoder.
++ */
++ unsigned int rc_resize_allowed;
++
++
++ /*!\brief Spatial resampling up watermark.
++ *
++ * This threshold is described as a percentage of the target data buffer.
++ * When the data buffer rises above this percentage of fullness, the
++ * encoder will step up to a higher resolution version of the frame.
++ */
++ unsigned int rc_resize_up_thresh;
++
++
++ /*!\brief Spatial resampling down watermark.
++ *
++ * This threshold is described as a percentage of the target data buffer.
++ * When the data buffer falls below this percentage of fullness, the
++ * encoder will step down to a lower resolution version of the frame.
++ */
++ unsigned int rc_resize_down_thresh;
++
++
++ /*!\brief Rate control algorithm to use.
++ *
++ * Indicates whether the end usage of this stream is to be streamed over
++ * a bandwidth constrained link, indicating that Constant Bit Rate (CBR)
++ * mode should be used, or whether it will be played back on a high
++ * bandwidth link, as from a local disk, where higher variations in
++ * bitrate are acceptable.
++ */
++ enum vpx_rc_mode rc_end_usage;
++
++
++ /*!\brief Two-pass stats buffer.
++ *
++ * A buffer containing all of the stats packets produced in the first
++ * pass, concatenated.
++ */
++ struct vpx_fixed_buf rc_twopass_stats_in;
++
++
++ /*!\brief Target data rate
++ *
++ * Target bandwidth to use for this stream, in kilobits per second.
++ */
++ unsigned int rc_target_bitrate;
++
++
++ /*
++ * quantizer settings
++ */
++
++
++ /*!\brief Minimum (Best Quality) Quantizer
++ *
++ * The quantizer is the most direct control over the quality of the
++ * encoded image. The range of valid values for the quantizer is codec
++ * specific. Consult the documentation for the codec to determine the
++ * values to use. To determine the range programmatically, call
++ * vpx_codec_enc_config_default() with a usage value of 0.
++ */
++ unsigned int rc_min_quantizer;
++
++
++ /*!\brief Maximum (Worst Quality) Quantizer
++ *
++ * The quantizer is the most direct control over the quality of the
++ * encoded image. The range of valid values for the quantizer is codec
++ * specific. Consult the documentation for the codec to determine the
++ * values to use. To determine the range programmatically, call
++ * vpx_codec_enc_config_default() with a usage value of 0.
++ */
++ unsigned int rc_max_quantizer;
++
++
++ /*
++ * bitrate tolerance
++ */
++
++
++ /*!\brief Rate control undershoot tolerance
++ *
++ * This value, expressed as a percentage of the target bitrate, describes
++ * the target bitrate for easier frames, allowing bits to be saved for
++ * harder frames. Set to zero to use the codec default.
++ */
++ unsigned int rc_undershoot_pct;
++
++
++ /*!\brief Rate control overshoot tolerance
++ *
++ * This value, expressed as a percentage of the target bitrate, describes
++ * the maximum allowed bitrate for a given frame. Set to zero to use the
++ * codec default.
++ */
++ unsigned int rc_overshoot_pct;
++
++
++ /*
++ * decoder buffer model parameters
++ */
++
++
++ /*!\brief Decoder Buffer Size
++ *
++ * This value indicates the amount of data that may be buffered by the
++ * decoding application. Note that this value is expressed in units of
++ * time (milliseconds). For example, a value of 5000 indicates that the
++ * client will buffer (at least) 5000ms worth of encoded data. Use the
++ * target bitrate (#rc_target_bitrate) to convert to bits/bytes, if
++ * necessary.
++ */
++ unsigned int rc_buf_sz;
++
++
++ /*!\brief Decoder Buffer Initial Size
++ *
++ * This value indicates the amount of data that will be buffered by the
++ * decoding application prior to beginning playback. This value is
++ * expressed in units of time (milliseconds). Use the target bitrate
++ * (#rc_target_bitrate) to convert to bits/bytes, if necessary.
++ */
++ unsigned int rc_buf_initial_sz;
++
++
++ /*!\brief Decoder Buffer Optimal Size
++ *
++ * This value indicates the amount of data that the encoder should try
++ * to maintain in the decoder's buffer. This value is expressed in units
++ * of time (milliseconds). Use the target bitrate (#rc_target_bitrate)
++ * to convert to bits/bytes, if necessary.
++ */
++ unsigned int rc_buf_optimal_sz;
++
++
++ /*
++ * 2 pass rate control parameters
++ */
++
++
++ /*!\brief Two-pass mode CBR/VBR bias
++ *
++ * Bias, expressed on a scale of 0 to 100, for determining target size
++ * for the current frame. The value 0 indicates the optimal CBR mode
++ * value should be used. The value 100 indicates the optimal VBR mode
++ * value should be used. Values in between indicate which way the
++ * encoder should "lean."
++ */
++ unsigned int rc_2pass_vbr_bias_pct; /**< RC mode bias between CBR and VBR(0-100: 0->CBR, 100->VBR) */
++
++
++ /*!\brief Two-pass mode per-GOP minimum bitrate
++ *
++ * This value, expressed as a percentage of the target bitrate, indicates
++ * the minimum bitrate to be used for a single GOP (aka "section")
++ */
++ unsigned int rc_2pass_vbr_minsection_pct;
++
++
++ /*!\brief Two-pass mode per-GOP maximum bitrate
++ *
++ * This value, expressed as a percentage of the target bitrate, indicates
++ * the maximum bitrate to be used for a single GOP (aka "section")
++ */
++ unsigned int rc_2pass_vbr_maxsection_pct;
++
++
++ /*
++ * keyframing settings (kf)
++ */
++
++ /*!\brief Keyframe placement mode
++ *
++ * This value indicates whether the encoder should place keyframes at a
++ * fixed interval, or determine the optimal placement automatically
++ * (as governed by the #kf_min_dist and #kf_max_dist parameters)
++ */
++ enum vpx_kf_mode kf_mode;
++
++
++ /*!\brief Keyframe minimum interval
++ *
++ * This value, expressed as a number of frames, prevents the encoder from
++ * placing a keyframe nearer than kf_min_dist to the previous keyframe. At
++ * least kf_min_dist frames non-keyframes will be coded before the next
++ * keyframe. Set kf_min_dist equal to kf_max_dist for a fixed interval.
++ */
++ unsigned int kf_min_dist;
++
++
++ /*!\brief Keyframe maximum interval
++ *
++ * This value, expressed as a number of frames, forces the encoder to code
++ * a keyframe if one has not been coded in the last kf_max_dist frames.
++ * A value of 0 implies all frames will be keyframes. Set kf_min_dist
++ * equal to kf_max_dist for a fixed interval.
++ */
++ unsigned int kf_max_dist;
++
++ } vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
++
++
++ /*!\brief Initialize an encoder instance
++ *
++ * Initializes a encoder context using the given interface. Applications
++ * should call the vpx_codec_enc_init convenience macro instead of this
++ * function directly, to ensure that the ABI version number parameter
++ * is properly initialized.
++ *
++ * In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
++ * parameter), the storage pointed to by the cfg parameter must be
++ * kept readable and stable until all memory maps have been set.
++ *
++ * \param[in] ctx Pointer to this instance's context.
++ * \param[in] iface Pointer to the algorithm interface to use.
++ * \param[in] cfg Configuration to use, if known. May be NULL.
++ * \param[in] flags Bitfield of VPX_CODEC_USE_* flags
++ * \param[in] ver ABI version number. Must be set to
++ * VPX_ENCODER_ABI_VERSION
++ * \retval #VPX_CODEC_OK
++ * The decoder algorithm initialized.
++ * \retval #VPX_CODEC_MEM_ERROR
++ * Memory allocation failed.
++ */
++ vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
++ vpx_codec_iface_t *iface,
++ vpx_codec_enc_cfg_t *cfg,
++ vpx_codec_flags_t flags,
++ int ver);
++
++
++ /*!\brief Convenience macro for vpx_codec_enc_init_ver()
++ *
++ * Ensures the ABI version parameter is properly set.
++ */
++#define vpx_codec_enc_init(ctx, iface, cfg, flags) \
++ vpx_codec_enc_init_ver(ctx, iface, cfg, flags, VPX_ENCODER_ABI_VERSION)
++
++
++ /*!\brief Get a default configuration
++ *
++ * Initializes a encoder configuration structure with default values. Supports
++ * the notion of "usages" so that an algorithm may offer different default
++ * settings depending on the user's intended goal. This function \ref SHOULD
++ * be called by all applications to initialize the configuration structure
++ * before specializing the configuration with application specific values.
++ *
++ * \param[in] iface Pointer to the algorithm interface to use.
++ * \param[out] cfg Configuration buffer to populate
++ * \param[in] usage End usage. Set to 0 or use codec specific values.
++ *
++ * \retval #VPX_CODEC_OK
++ * The configuration was populated.
++ * \retval #VPX_CODEC_INCAPABLE
++ * Interface is not an encoder interface.
++ * \retval #VPX_CODEC_INVALID_PARAM
++ * A parameter was NULL, or the usage value was not recognized.
++ */
++ vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface,
++ vpx_codec_enc_cfg_t *cfg,
++ unsigned int usage);
++
++
++ /*!\brief Set or change configuration
++ *
++ * Reconfigures an encoder instance according to the given configuration.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] cfg Configuration buffer to use
++ *
++ * \retval #VPX_CODEC_OK
++ * The configuration was populated.
++ * \retval #VPX_CODEC_INCAPABLE
++ * Interface is not an encoder interface.
++ * \retval #VPX_CODEC_INVALID_PARAM
++ * A parameter was NULL, or the usage value was not recognized.
++ */
++ vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx,
++ const vpx_codec_enc_cfg_t *cfg);
++
++
++ /*!\brief Get global stream headers
++ *
++ * Retrieves a stream level global header packet, if supported by the codec.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ *
++ * \retval NULL
++ * Encoder does not support global header
++ * \retval Non-NULL
++ * Pointer to buffer containing global header packet
++ */
++ vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx);
++
++
++#define VPX_DL_REALTIME (1) /**< deadline parameter analogous to
++ * VPx REALTIME mode. */
++#define VPX_DL_GOOD_QUALITY (1000000) /**< deadline parameter analogous to
++ * VPx GOOD QUALITY mode. */
++#define VPX_DL_BEST_QUALITY (0) /**< deadline parameter analogous to
++ * VPx BEST QUALITY mode. */
++ /*!\brief Encode a frame
++ *
++ * Encodes a video frame at the given "presentation time." The presentation
++ * time stamp (PTS) \ref MUST be strictly increasing.
++ *
++ * The encoder supports the notion of a soft real-time deadline. Given a
++ * non-zero value to the deadline parameter, the encoder will make a "best
++ * effort" guarantee to return before the given time slice expires. It is
++ * implicit that limiting the available time to encode will degrade the
++ * output quality. The encoder can be given an unlimited time to produce the
++ * best possible frame by specifying a deadline of '0'. This deadline
++ * supercedes the VPx notion of "best quality, good quality, realtime".
++ * Applications that wish to map these former settings to the new deadline
++ * based system can use the symbols #VPX_DL_REALTIME, #VPX_DL_GOOD_QUALITY,
++ * and #VPX_DL_BEST_QUALITY.
++ *
++ * When the last frame has been passed to the encoder, this function should
++ * continue to be called, with the img parameter set to NULL. This will
++ * signal the end-of-stream condition to the encoder and allow it to encode
++ * any held buffers. Encoding is complete when vpx_codec_encode() is called
++ * and vpx_codec_get_cx_data() returns no data.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] img Image data to encode, NULL to flush.
++ * \param[in] pts Presentation time stamp, in timebase units.
++ * \param[in] duration Duration to show frame, in timebase units.
++ * \param[in] flags Flags to use for encoding this frame.
++ * \param[in] deadline Time to spend encoding, in microseconds. (0=infinite)
++ *
++ * \retval #VPX_CODEC_OK
++ * The configuration was populated.
++ * \retval #VPX_CODEC_INCAPABLE
++ * Interface is not an encoder interface.
++ * \retval #VPX_CODEC_INVALID_PARAM
++ * A parameter was NULL, the image format is unsupported, etc.
++ */
++ vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx,
++ const vpx_image_t *img,
++ vpx_codec_pts_t pts,
++ unsigned long duration,
++ vpx_enc_frame_flags_t flags,
++ unsigned long deadline);
++
++
++ /*!\brief Set compressed data output buffer
++ *
++ * Sets the buffer that the codec should output the compressed data
++ * into. This call effectively sets the buffer pointer returned in the
++ * next VPX_CODEC_CX_FRAME_PKT packet. Subsequent packets will be
++ * appended into this buffer. The buffer is preserved across frames,
++ * so applications must periodically call this function after flushing
++ * the accumulated compressed data to disk or to the network to reset
++ * the pointer to the buffer's head.
++ *
++ * `pad_before` bytes will be skipped before writing the compressed
++ * data, and `pad_after` bytes will be appended to the packet. The size
++ * of the packet will be the sum of the size of the actual compressed
++ * data, pad_before, and pad_after. The padding bytes will be preserved
++ * (not overwritten).
++ *
++ * Note that calling this function does not guarantee that the returned
++ * compressed data will be placed into the specified buffer. In the
++ * event that the encoded data will not fit into the buffer provided,
++ * the returned packet \ref MAY point to an internal buffer, as it would
++ * if this call were never used. In this event, the output packet will
++ * NOT have any padding, and the application must free space and copy it
++ * to the proper place. This is of particular note in configurations
++ * that may output multiple packets for a single encoded frame (e.g., lagged
++ * encoding) or if the application does not reset the buffer periodically.
++ *
++ * Applications may restore the default behavior of the codec providing
++ * the compressed data buffer by calling this function with a NULL
++ * buffer.
++ *
++ * Applications \ref MUSTNOT call this function during iteration of
++ * vpx_codec_get_cx_data().
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in] buf Buffer to store compressed data into
++ * \param[in] pad_before Bytes to skip before writing compressed data
++ * \param[in] pad_after Bytes to skip after writing compressed data
++ *
++ * \retval #VPX_CODEC_OK
++ * The buffer was set successfully.
++ * \retval #VPX_CODEC_INVALID_PARAM
++ * A parameter was NULL, the image format is unsupported, etc.
++ */
++ vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx,
++ const vpx_fixed_buf_t *buf,
++ unsigned int pad_before,
++ unsigned int pad_after);
++
++
++ /*!\brief Encoded data iterator
++ *
++ * Iterates over a list of data packets to be passed from the encoder to the
++ * application. The different kinds of packets available are enumerated in
++ * #vpx_codec_cx_pkt_kind.
++ *
++ * #VPX_CODEC_CX_FRAME_PKT packets should be passed to the application's
++ * muxer. Multiple compressed frames may be in the list.
++ * #VPX_CODEC_STATS_PKT packets should be appended to a global buffer.
++ *
++ * The application \ref MUST silently ignore any packet kinds that it does
++ * not recognize or support.
++ *
++ * The data buffers returned from this function are only guaranteed to be
++ * valid until the application makes another call to any vpx_codec_* function.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ * \param[in,out] iter Iterator storage, initialized to NULL
++ *
++ * \return Returns a pointer to an output data packet (compressed frame data,
++ * two-pass statistics, etc.) or NULL to signal end-of-list.
++ *
++ */
++ const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx,
++ vpx_codec_iter_t *iter);
++
++
++ /*!\brief Get Preview Frame
++ *
++ * Returns an image that can be used as a preview. Shows the image as it would
++ * exist at the decompressor. The application \ref MUST NOT write into this
++ * image buffer.
++ *
++ * \param[in] ctx Pointer to this instance's context
++ *
++ * \return Returns a pointer to a preview image, or NULL if no image is
++ * available.
++ *
++ */
++ const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx);
++
++
++ /*!@} - end defgroup encoder*/
++
++#endif
++#ifdef __cplusplus
++}
++#endif
+diff --git a/vpx/vpx_image.h b/vpx/vpx_image.h
+new file mode 100644
+index 0000000..7e4a03a
+--- /dev/null
++++ b/vpx/vpx_image.h
+@@ -0,0 +1,242 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++/*!\file vpx_image.h
++ * \brief Describes the vpx image descriptor and associated operations
++ *
++ */
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef VPX_IMAGE_H
++#define VPX_IMAGE_H
++
++ /*!\brief Current ABI version number
++ *
++ * \internal
++ * If this file is altered in any way that changes the ABI, this value
++ * must be bumped. Examples include, but are not limited to, changing
++ * types, removing or reassigning enums, adding/removing/rearranging
++ * fields to structures
++ */
++#define VPX_IMAGE_ABI_VERSION (1) /**<\hideinitializer*/
++
++
++#define VPX_IMG_FMT_PLANAR 0x100 /**< Image is a planar format */
++#define VPX_IMG_FMT_UV_FLIP 0x200 /**< V plane precedes U plane in memory */
++#define VPX_IMG_FMT_HAS_ALPHA 0x400 /**< Image has an alpha channel componnent */
++
++
++ /*!\brief List of supported image formats */
++ typedef enum vpx_img_fmt {
++ VPX_IMG_FMT_NONE,
++ VPX_IMG_FMT_RGB24, /**< 24 bit per pixel packed RGB */
++ VPX_IMG_FMT_RGB32, /**< 32 bit per pixel packed 0RGB */
++ VPX_IMG_FMT_RGB565, /**< 16 bit per pixel, 565 */
++ VPX_IMG_FMT_RGB555, /**< 16 bit per pixel, 555 */
++ VPX_IMG_FMT_UYVY, /**< UYVY packed YUV */
++ VPX_IMG_FMT_YUY2, /**< YUYV packed YUV */
++ VPX_IMG_FMT_YVYU, /**< YVYU packed YUV */
++ VPX_IMG_FMT_BGR24, /**< 24 bit per pixel packed BGR */
++ VPX_IMG_FMT_RGB32_LE, /**< 32 bit packed BGR0 */
++ VPX_IMG_FMT_ARGB, /**< 32 bit packed ARGB, alpha=255 */
++ VPX_IMG_FMT_ARGB_LE, /**< 32 bit packed BGRA, alpha=255 */
++ VPX_IMG_FMT_RGB565_LE, /**< 16 bit per pixel, gggbbbbb rrrrrggg */
++ VPX_IMG_FMT_RGB555_LE, /**< 16 bit per pixel, gggbbbbb 0rrrrrgg */
++ VPX_IMG_FMT_YV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 1, /**< planar YVU */
++ VPX_IMG_FMT_I420 = VPX_IMG_FMT_PLANAR | 2,
++ VPX_IMG_FMT_VPXYV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 3, /** < planar 4:2:0 format with vpx color space */
++ VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4, /** < planar 4:2:0 format with vpx color space */
++ }
++ vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */
++
++#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
++#define IMG_FMT_PLANAR VPX_IMG_FMT_PLANAR /**< \deprecated Use #VPX_IMG_FMT_PLANAR */
++#define IMG_FMT_UV_FLIP VPX_IMG_FMT_UV_FLIP /**< \deprecated Use #VPX_IMG_FMT_UV_FLIP */
++#define IMG_FMT_HAS_ALPHA VPX_IMG_FMT_HAS_ALPHA /**< \deprecated Use #VPX_IMG_FMT_HAS_ALPHA */
++
++ /*!\brief Deprecated list of supported image formats
++ * \deprecated New code should use #vpx_img_fmt
++ */
++#define img_fmt vpx_img_fmt
++ /*!\brief alias for enum img_fmt.
++ * \deprecated New code should use #vpx_img_fmt_t
++ */
++#define img_fmt_t vpx_img_fmt_t
++
++#define IMG_FMT_NONE VPX_IMG_FMT_NONE /**< \deprecated Use #VPX_IMG_FMT_NONE */
++#define IMG_FMT_RGB24 VPX_IMG_FMT_RGB24 /**< \deprecated Use #VPX_IMG_FMT_RGB24 */
++#define IMG_FMT_RGB32 VPX_IMG_FMT_RGB32 /**< \deprecated Use #VPX_IMG_FMT_RGB32 */
++#define IMG_FMT_RGB565 VPX_IMG_FMT_RGB565 /**< \deprecated Use #VPX_IMG_FMT_RGB565 */
++#define IMG_FMT_RGB555 VPX_IMG_FMT_RGB555 /**< \deprecated Use #VPX_IMG_FMT_RGB555 */
++#define IMG_FMT_UYVY VPX_IMG_FMT_UYVY /**< \deprecated Use #VPX_IMG_FMT_UYVY */
++#define IMG_FMT_YUY2 VPX_IMG_FMT_YUY2 /**< \deprecated Use #VPX_IMG_FMT_YUY2 */
++#define IMG_FMT_YVYU VPX_IMG_FMT_YVYU /**< \deprecated Use #VPX_IMG_FMT_YVYU */
++#define IMG_FMT_BGR24 VPX_IMG_FMT_BGR24 /**< \deprecated Use #VPX_IMG_FMT_BGR24 */
++#define IMG_FMT_RGB32_LE VPX_IMG_FMT_RGB32_LE /**< \deprecated Use #VPX_IMG_FMT_RGB32_LE */
++#define IMG_FMT_ARGB VPX_IMG_FMT_ARGB /**< \deprecated Use #VPX_IMG_FMT_ARGB */
++#define IMG_FMT_ARGB_LE VPX_IMG_FMT_ARGB_LE /**< \deprecated Use #VPX_IMG_FMT_ARGB_LE */
++#define IMG_FMT_RGB565_LE VPX_IMG_FMT_RGB565_LE /**< \deprecated Use #VPX_IMG_FMT_RGB565_LE */
++#define IMG_FMT_RGB555_LE VPX_IMG_FMT_RGB555_LE /**< \deprecated Use #VPX_IMG_FMT_RGB555_LE */
++#define IMG_FMT_YV12 VPX_IMG_FMT_YV12 /**< \deprecated Use #VPX_IMG_FMT_YV12 */
++#define IMG_FMT_I420 VPX_IMG_FMT_I420 /**< \deprecated Use #VPX_IMG_FMT_I420 */
++#define IMG_FMT_VPXYV12 VPX_IMG_FMT_VPXYV12 /**< \deprecated Use #VPX_IMG_FMT_VPXYV12 */
++#define IMG_FMT_VPXI420 VPX_IMG_FMT_VPXI420 /**< \deprecated Use #VPX_IMG_FMT_VPXI420 */
++#endif /* VPX_CODEC_DISABLE_COMPAT */
++
++ /**\brief Image Descriptor */
++ typedef struct vpx_image
++ {
++ vpx_img_fmt_t fmt; /**< Image Format */
++
++ /* Image storage dimensions */
++ unsigned int w; /**< Stored image width */
++ unsigned int h; /**< Stored image height */
++
++ /* Image display dimensions */
++ unsigned int d_w; /**< Displayed image width */
++ unsigned int d_h; /**< Displayed image height */
++
++ /* Chroma subsampling info */
++ unsigned int x_chroma_shift; /**< subsampling order, X */
++ unsigned int y_chroma_shift; /**< subsampling order, Y */
++
++ /* Image data pointers. */
++#define VPX_PLANE_PACKED 0 /**< To be used for all packed formats */
++#define VPX_PLANE_Y 0 /**< Y (Luminance) plane */
++#define VPX_PLANE_U 1 /**< U (Chroma) plane */
++#define VPX_PLANE_V 2 /**< V (Chroma) plane */
++#define VPX_PLANE_ALPHA 3 /**< A (Transparancy) plane */
++#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
++#define PLANE_PACKED VPX_PLANE_PACKED
++#define PLANE_Y VPX_PLANE_Y
++#define PLANE_U VPX_PLANE_U
++#define PLANE_V VPX_PLANE_V
++#define PLANE_ALPHA VPX_PLANE_ALPHA
++#endif
++ unsigned char *planes[4]; /**< pointer to the top left pixel for each plane */
++ int stride[4]; /**< stride between rows for each plane */
++
++ int bps; /**< bits per sample (for packed formats) */
++
++ /* The following member may be set by the application to associate data
++ * with this image.
++ */
++ void *user_priv; /**< may be set by the application to associate data
++ * with this image. */
++
++ /* The following members should be treated as private. */
++ unsigned char *img_data; /**< private */
++ int img_data_owner; /**< private */
++ int self_allocd; /**< private */
++ } vpx_image_t; /**< alias for struct vpx_image */
++
++ /**\brief Representation of a rectangle on a surface */
++ typedef struct vpx_image_rect
++ {
++ unsigned int x; /**< leftmost column */
++ unsigned int y; /**< topmost row */
++ unsigned int w; /**< width */
++ unsigned int h; /**< height */
++ } vpx_image_rect_t; /**< alias for struct vpx_image_rect */
++
++ /*!\brief Open a descriptor, allocating storage for the underlying image
++ *
++ * Returns a descriptor for storing an image of the given format. The
++ * storage for the descriptor is allocated on the heap.
++ *
++ * \param[in] img Pointer to storage for descriptor. If this parameter
++ * is NULL, the storage for the descriptor will be
++ * allocated on the heap.
++ * \param[in] fmt Format for the image
++ * \param[in] d_w Width of the image
++ * \param[in] d_h Height of the image
++ * \param[in] align Alignment, in bytes, of each row in the image.
++ *
++ * \return Returns a pointer to the initialized image descriptor. If the img
++ * parameter is non-null, the value of the img parameter will be
++ * returned.
++ */
++ vpx_image_t *vpx_img_alloc(vpx_image_t *img,
++ vpx_img_fmt_t fmt,
++ unsigned int d_w,
++ unsigned int d_h,
++ unsigned int align);
++
++ /*!\brief Open a descriptor, using existing storage for the underlying image
++ *
++ * Returns a descriptor for storing an image of the given format. The
++ * storage for descriptor has been allocated elsewhere, and a descriptor is
++ * desired to "wrap" that storage.
++ *
++ * \param[in] img Pointer to storage for descriptor. If this parameter
++ * is NULL, the storage for the descriptor will be
++ * allocated on the heap.
++ * \param[in] fmt Format for the image
++ * \param[in] d_w Width of the image
++ * \param[in] d_h Height of the image
++ * \param[in] align Alignment, in bytes, of each row in the image.
++ * \param[in] img_data Storage to use for the image
++ *
++ * \return Returns a pointer to the initialized image descriptor. If the img
++ * parameter is non-null, the value of the img parameter will be
++ * returned.
++ */
++ vpx_image_t *vpx_img_wrap(vpx_image_t *img,
++ vpx_img_fmt_t fmt,
++ unsigned int d_w,
++ unsigned int d_h,
++ unsigned int align,
++ unsigned char *img_data);
++
++
++ /*!\brief Set the rectangle identifying the displayed portion of the image
++ *
++ * Updates the displayed rectangle (aka viewport) on the image surface to
++ * match the specified coordinates and size.
++ *
++ * \param[in] img Image descriptor
++ * \param[in] x leftmost column
++ * \param[in] y topmost row
++ * \param[in] w width
++ * \param[in] h height
++ *
++ * \return 0 if the requested rectangle is valid, nonzero otherwise.
++ */
++ int vpx_img_set_rect(vpx_image_t *img,
++ unsigned int x,
++ unsigned int y,
++ unsigned int w,
++ unsigned int h);
++
++
++ /*!\brief Flip the image vertically (top for bottom)
++ *
++ * Adjusts the image descriptor's pointers and strides to make the image
++ * be referenced upside-down.
++ *
++ * \param[in] img Image descriptor
++ */
++ void vpx_img_flip(vpx_image_t *img);
++
++ /*!\brief Close an image descriptor
++ *
++ * Frees all allocated storage associated with an image descriptor.
++ *
++ * \param[in] img Image descriptor
++ */
++ void vpx_img_free(vpx_image_t *img);
++
++#endif
++#ifdef __cplusplus
++}
++#endif
+diff --git a/vpx/vpx_integer.h b/vpx/vpx_integer.h
+new file mode 100644
+index 0000000..f06c641
+--- /dev/null
++++ b/vpx/vpx_integer.h
+@@ -0,0 +1,57 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++
++#ifndef VPX_INTEGER_H
++#define VPX_INTEGER_H
++
++/* get ptrdiff_t, size_t, wchar_t, NULL */
++#include <stddef.h>
++
++#if defined(_MSC_VER) || defined(VPX_EMULATE_INTTYPES)
++typedef signed char int8_t;
++typedef signed short int16_t;
++typedef signed int int32_t;
++
++typedef unsigned char uint8_t;
++typedef unsigned short uint16_t;
++typedef unsigned int uint32_t;
++
++#if defined(_MSC_VER)
++typedef signed __int64 int64_t;
++typedef unsigned __int64 uint64_t;
++#define PRId64 "I64d"
++#endif
++
++#ifdef HAVE_ARMV6
++typedef unsigned int int_fast16_t;
++#else
++typedef signed short int_fast16_t;
++#endif
++typedef signed char int_fast8_t;
++typedef unsigned char uint_fast8_t;
++
++#ifndef _UINTPTR_T_DEFINED
++typedef unsigned int uintptr_t;
++#endif
++
++#else
++
++/* Most platforms have the C99 standard integer types. */
++
++#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
++#define __STDC_FORMAT_MACROS
++#endif
++#include <stdint.h>
++#include <inttypes.h>
++
++#endif
++
++#endif
+diff --git a/vpx_codec/exports b/vpx_codec/exports
+deleted file mode 100644
+index f5e7473..0000000
+--- a/vpx_codec/exports
++++ /dev/null
+@@ -1,17 +0,0 @@
+-text vpx_dec_control
+-text vpx_dec_decode
+-text vpx_dec_destroy
+-text vpx_dec_err_to_string
+-text vpx_dec_error
+-text vpx_dec_error_detail
+-text vpx_dec_get_caps
+-text vpx_dec_get_frame
+-text vpx_dec_get_mem_map
+-text vpx_dec_get_stream_info
+-text vpx_dec_iface_name
+-text vpx_dec_init_ver
+-text vpx_dec_peek_stream_info
+-text vpx_dec_register_put_frame_cb
+-text vpx_dec_register_put_slice_cb
+-text vpx_dec_set_mem_map
+-text vpx_dec_xma_init_ver
+diff --git a/vpx_codec/internal/vpx_codec_internal.h b/vpx_codec/internal/vpx_codec_internal.h
+deleted file mode 100644
+index 0867552..0000000
+--- a/vpx_codec/internal/vpx_codec_internal.h
++++ /dev/null
+@@ -1,457 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\file decoder_impl.h
+- * \brief Describes the decoder algorithm interface for algorithm
+- * implementations.
+- *
+- * This file defines the private structures and data types that are only
+- * relevant to implementing an algorithm, as opposed to using it.
+- *
+- * To create a decoder algorithm class, an interface structure is put
+- * into the global namespace:
+- * <pre>
+- * my_codec.c:
+- * vpx_codec_iface_t my_codec = {
+- * "My Codec v1.0",
+- * VPX_CODEC_ALG_ABI_VERSION,
+- * ...
+- * };
+- * </pre>
+- *
+- * An application instantiates a specific decoder instance by using
+- * vpx_codec_init() and a pointer to the algorithm's interface structure:
+- * <pre>
+- * my_app.c:
+- * extern vpx_codec_iface_t my_codec;
+- * {
+- * vpx_codec_ctx_t algo;
+- * res = vpx_codec_init(&algo, &my_codec);
+- * }
+- * </pre>
+- *
+- * Once initialized, the instance is manged using other functions from
+- * the vpx_codec_* family.
+- */
+-#ifndef VPX_CODEC_INTERNAL_H
+-#define VPX_CODEC_INTERNAL_H
+-#include "../vpx_decoder.h"
+-#include "../vpx_encoder.h"
+-#include <stdarg.h>
+-
+-
+-/*!\brief Current ABI version number
+- *
+- * \internal
+- * If this file is altered in any way that changes the ABI, this value
+- * must be bumped. Examples include, but are not limited to, changing
+- * types, removing or reassigning enums, adding/removing/rearranging
+- * fields to structures
+- */
+-#define VPX_CODEC_INTERNAL_ABI_VERSION (2) /**<\hideinitializer*/
+-
+-typedef struct vpx_codec_alg_priv vpx_codec_alg_priv_t;
+-
+-/*!\brief init function pointer prototype
+- *
+- * Performs algorithm-specific initialization of the decoder context. This
+- * function is called by the generic vpx_codec_init() wrapper function, so
+- * plugins implementing this interface may trust the input parameters to be
+- * properly initialized.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \retval #VPX_CODEC_OK
+- * The input stream was recognized and decoder initialized.
+- * \retval #VPX_CODEC_MEM_ERROR
+- * Memory operation failed.
+- */
+-typedef vpx_codec_err_t (*vpx_codec_init_fn_t)(vpx_codec_ctx_t *ctx);
+-
+-/*!\brief destroy function pointer prototype
+- *
+- * Performs algorithm-specific destruction of the decoder context. This
+- * function is called by the generic vpx_codec_destroy() wrapper function,
+- * so plugins implementing this interface may trust the input parameters
+- * to be properly initialized.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \retval #VPX_CODEC_OK
+- * The input stream was recognized and decoder initialized.
+- * \retval #VPX_CODEC_MEM_ERROR
+- * Memory operation failed.
+- */
+-typedef vpx_codec_err_t (*vpx_codec_destroy_fn_t)(vpx_codec_alg_priv_t *ctx);
+-
+-/*!\brief parse stream info function pointer prototype
+- *
+- * Performs high level parsing of the bitstream. This function is called by
+- * the generic vpx_codec_parse_stream() wrapper function, so plugins implementing
+- * this interface may trust the input parameters to be properly initialized.
+- *
+- * \param[in] data Pointer to a block of data to parse
+- * \param[in] data_sz Size of the data buffer
+- * \param[in,out] si Pointer to stream info to update. The size member
+- * \ref MUST be properly initialized, but \ref MAY be
+- * clobbered by the algorithm. This parameter \ref MAY
+- * be NULL.
+- *
+- * \retval #VPX_CODEC_OK
+- * Bitstream is parsable and stream information updated
+- */
+-typedef vpx_codec_err_t (*vpx_codec_peek_si_fn_t)(const uint8_t *data,
+- unsigned int data_sz,
+- vpx_codec_stream_info_t *si);
+-
+-/*!\brief Return information about the current stream.
+- *
+- * Returns information about the stream that has been parsed during decoding.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in,out] si Pointer to stream info to update. The size member
+- * \ref MUST be properly initialized, but \ref MAY be
+- * clobbered by the algorithm. This parameter \ref MAY
+- * be NULL.
+- *
+- * \retval #VPX_CODEC_OK
+- * Bitstream is parsable and stream information updated
+- */
+-typedef vpx_codec_err_t (*vpx_codec_get_si_fn_t)(vpx_codec_alg_priv_t *ctx,
+- vpx_codec_stream_info_t *si);
+-
+-/*!\brief control function pointer prototype
+- *
+- * This function is used to exchange algorithm specific data with the decoder
+- * instance. This can be used to implement features specific to a particular
+- * algorithm.
+- *
+- * This function is called by the generic vpx_codec_control() wrapper
+- * function, so plugins implementing this interface may trust the input
+- * parameters to be properly initialized. However, this interface does not
+- * provide type safety for the exchanged data or assign meanings to the
+- * control codes. Those details should be specified in the algorithm's
+- * header file. In particular, the ctrl_id parameter is guaranteed to exist
+- * in the algorithm's control mapping table, and the data paramter may be NULL.
+- *
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] ctrl_id Algorithm specific control identifier
+- * \param[in,out] data Data to exchange with algorithm instance.
+- *
+- * \retval #VPX_CODEC_OK
+- * The internal state data was deserialized.
+- */
+-typedef vpx_codec_err_t (*vpx_codec_control_fn_t)(vpx_codec_alg_priv_t *ctx,
+- int ctrl_id,
+- va_list ap);
+-
+-/*!\brief control function pointer mapping
+- *
+- * This structure stores the mapping between control identifiers and
+- * implementing functions. Each algorithm provides a list of these
+- * mappings. This list is searched by the vpx_codec_control() wrapper
+- * function to determine which function to invoke. The special
+- * value {0, NULL} is used to indicate end-of-list, and must be
+- * present. The special value {0, <non-null>} can be used as a catch-all
+- * mapping. This implies that ctrl_id values chosen by the algorithm
+- * \ref MUST be non-zero.
+- */
+-typedef const struct
+-{
+- int ctrl_id;
+- vpx_codec_control_fn_t fn;
+-} vpx_codec_ctrl_fn_map_t;
+-
+-/*!\brief decode data function pointer prototype
+- *
+- * Processes a buffer of coded data. If the processing results in a new
+- * decoded frame becoming available, #VPX_CODEC_CB_PUT_SLICE and
+- * #VPX_CODEC_CB_PUT_FRAME events are generated as appropriate. This
+- * function is called by the generic vpx_codec_decode() wrapper function,
+- * so plugins implementing this interface may trust the input parameters
+- * to be properly initialized.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] data Pointer to this block of new coded data. If
+- * NULL, a #VPX_CODEC_CB_PUT_FRAME event is posted
+- * for the previously decoded frame.
+- * \param[in] data_sz Size of the coded data, in bytes.
+- *
+- * \return Returns #VPX_CODEC_OK if the coded data was processed completely
+- * and future pictures can be decoded without error. Otherwise,
+- * see the descriptions of the other error codes in ::vpx_codec_err_t
+- * for recoverability capabilities.
+- */
+-typedef vpx_codec_err_t (*vpx_codec_decode_fn_t)(vpx_codec_alg_priv_t *ctx,
+- const uint8_t *data,
+- unsigned int data_sz,
+- void *user_priv,
+- long deadline);
+-
+-/*!\brief Decoded frames iterator
+- *
+- * Iterates over a list of the frames available for display. The iterator
+- * storage should be initialized to NULL to start the iteration. Iteration is
+- * complete when this function returns NULL.
+- *
+- * The list of available frames becomes valid upon completion of the
+- * vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in out] iter Iterator storage, initialized to NULL
+- *
+- * \return Returns a pointer to an image, if one is ready for display. Frames
+- * produced will always be in PTS (presentation time stamp) order.
+- */
+-typedef vpx_image_t*(*vpx_codec_get_frame_fn_t)(vpx_codec_alg_priv_t *ctx,
+- vpx_codec_iter_t *iter);
+-
+-
+-/*\brief e_xternal Memory Allocation memory map get iterator
+- *
+- * Iterates over a list of the memory maps requested by the decoder. The
+- * iterator storage should be initialized to NULL to start the iteration.
+- * Iteration is complete when this function returns NULL.
+- *
+- * \param[in out] iter Iterator storage, initialized to NULL
+- *
+- * \return Returns a pointer to an memory segment descriptor, or NULL to
+- * indicate end-of-list.
+- */
+-typedef vpx_codec_err_t (*vpx_codec_get_mmap_fn_t)(const vpx_codec_ctx_t *ctx,
+- vpx_codec_mmap_t *mmap,
+- vpx_codec_iter_t *iter);
+-
+-
+-/*\brief e_xternal Memory Allocation memory map set iterator
+- *
+- * Sets a memory descriptor inside the decoder instance.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] mmap Memory map to store.
+- *
+- * \retval #VPX_CODEC_OK
+- * The memory map was accepted and stored.
+- * \retval #VPX_CODEC_MEM_ERROR
+- * The memory map was rejected.
+- */
+-typedef vpx_codec_err_t (*vpx_codec_set_mmap_fn_t)(vpx_codec_ctx_t *ctx,
+- const vpx_codec_mmap_t *mmap);
+-
+-
+-typedef vpx_codec_err_t (*vpx_codec_encode_fn_t)(vpx_codec_alg_priv_t *ctx,
+- const vpx_image_t *img,
+- vpx_codec_pts_t pts,
+- unsigned long duration,
+- vpx_enc_frame_flags_t flags,
+- unsigned long deadline);
+-typedef const vpx_codec_cx_pkt_t*(*vpx_codec_get_cx_data_fn_t)(vpx_codec_alg_priv_t *ctx,
+- vpx_codec_iter_t *iter);
+-
+-typedef vpx_codec_err_t
+-(*vpx_codec_enc_config_set_fn_t)(vpx_codec_alg_priv_t *ctx,
+- const vpx_codec_enc_cfg_t *cfg);
+-typedef vpx_fixed_buf_t *
+-(*vpx_codec_get_global_headers_fn_t)(vpx_codec_alg_priv_t *ctx);
+-
+-typedef vpx_image_t *
+-(*vpx_codec_get_preview_frame_fn_t)(vpx_codec_alg_priv_t *ctx);
+-
+-/*!\brief usage configuration mapping
+- *
+- * This structure stores the mapping between usage identifiers and
+- * configuration structures. Each algorithm provides a list of these
+- * mappings. This list is searched by the vpx_codec_enc_config_default()
+- * wrapper function to determine which config to return. The special value
+- * {-1, {0}} is used to indicate end-of-list, and must be present. At least
+- * one mapping must be present, in addition to the end-of-list.
+- *
+- */
+-typedef const struct
+-{
+- int usage;
+- vpx_codec_enc_cfg_t cfg;
+-} vpx_codec_enc_cfg_map_t;
+-
+-#define NOT_IMPLEMENTED 0
+-
+-/*!\brief Decoder algorithm interface interface
+- *
+- * All decoders \ref MUST expose a variable of this type.
+- */
+-struct vpx_codec_iface
+-{
+- const char *name; /**< Identification String */
+- int abi_version; /**< Implemented ABI version */
+- vpx_codec_caps_t caps; /**< Decoder capabilities */
+- vpx_codec_init_fn_t init; /**< \copydoc ::vpx_codec_init_fn_t */
+- vpx_codec_destroy_fn_t destroy; /**< \copydoc ::vpx_codec_destroy_fn_t */
+- vpx_codec_ctrl_fn_map_t *ctrl_maps; /**< \copydoc ::vpx_codec_ctrl_fn_map_t */
+- vpx_codec_get_mmap_fn_t get_mmap; /**< \copydoc ::vpx_codec_get_mmap_fn_t */
+- vpx_codec_set_mmap_fn_t set_mmap; /**< \copydoc ::vpx_codec_set_mmap_fn_t */
+- struct
+- {
+- vpx_codec_peek_si_fn_t peek_si; /**< \copydoc ::vpx_codec_peek_si_fn_t */
+- vpx_codec_get_si_fn_t get_si; /**< \copydoc ::vpx_codec_peek_si_fn_t */
+- vpx_codec_decode_fn_t decode; /**< \copydoc ::vpx_codec_decode_fn_t */
+- vpx_codec_get_frame_fn_t get_frame; /**< \copydoc ::vpx_codec_get_frame_fn_t */
+- } dec;
+- struct
+- {
+- vpx_codec_enc_cfg_map_t *cfg_maps; /**< \copydoc ::vpx_codec_enc_cfg_map_t */
+- vpx_codec_encode_fn_t encode; /**< \copydoc ::vpx_codec_encode_fn_t */
+- vpx_codec_get_cx_data_fn_t get_cx_data; /**< \copydoc ::vpx_codec_get_cx_data_fn_t */
+- vpx_codec_enc_config_set_fn_t cfg_set; /**< \copydoc ::vpx_codec_enc_config_set_fn_t */
+- vpx_codec_get_global_headers_fn_t get_glob_hdrs; /**< \copydoc ::vpx_codec_enc_config_set_fn_t */
+- vpx_codec_get_preview_frame_fn_t get_preview; /**< \copydoc ::vpx_codec_get_preview_frame_fn_t */
+- } enc;
+-};
+-
+-/*!\brief Callback function pointer / user data pair storage */
+-typedef struct
+-{
+- union
+- {
+- vpx_codec_put_frame_cb_fn_t put_frame;
+- vpx_codec_put_slice_cb_fn_t put_slice;
+- };
+- void *user_priv;
+-} vpx_codec_priv_cb_pair_t;
+-
+-
+-/*!\brief Instance private storage
+- *
+- * This structure is allocated by the algorithm's init function. It can be
+- * extended in one of two ways. First, a second, algorithm specific structure
+- * can be allocated and the priv member pointed to it. Alternatively, this
+- * structure can be made the first member of the algorithm specific structure,
+- * and the pointer casted to the proper type.
+- */
+-struct vpx_codec_priv
+-{
+- unsigned int sz;
+- vpx_codec_iface_t *iface;
+- struct vpx_codec_alg_priv *alg_priv;
+- const char *err_detail;
+- unsigned int eval_counter;
+- vpx_codec_flags_t init_flags;
+- struct
+- {
+- vpx_codec_priv_cb_pair_t put_frame_cb;
+- vpx_codec_priv_cb_pair_t put_slice_cb;
+- } dec;
+- struct
+- {
+- int tbd;
+- struct vpx_fixed_buf cx_data_dst_buf;
+- unsigned int cx_data_pad_before;
+- unsigned int cx_data_pad_after;
+- vpx_codec_cx_pkt_t cx_data_pkt;
+- } enc;
+-};
+-
+-#undef VPX_CTRL_USE_TYPE
+-#define VPX_CTRL_USE_TYPE(id, typ) \
+- static typ id##__value(va_list args) {return va_arg(args, typ);} \
+- static typ id##__convert(void *x)\
+- {\
+- union\
+- {\
+- void *x;\
+- typ d;\
+- } u;\
+- u.x = x;\
+- return u.d;\
+- }
+-
+-
+-#undef VPX_CTRL_USE_TYPE_DEPRECATED
+-#define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
+- static typ id##__value(va_list args) {return va_arg(args, typ);} \
+- static typ id##__convert(void *x)\
+- {\
+- union\
+- {\
+- void *x;\
+- typ d;\
+- } u;\
+- u.x = x;\
+- return u.d;\
+- }
+-
+-#define CAST(id, arg) id##__value(arg)
+-#define RECAST(id, x) id##__convert(x)
+-
+-
+-/* Internal Utility Functions
+- *
+- * The following functions are indended to be used inside algorithms as
+- * utilities for manipulating vpx_codec_* data structures.
+- */
+-struct vpx_codec_pkt_list
+-{
+- unsigned int cnt;
+- unsigned int max;
+- struct vpx_codec_cx_pkt pkts[1];
+-};
+-
+-#define vpx_codec_pkt_list_decl(n)\
+- union {struct vpx_codec_pkt_list head;\
+- struct {struct vpx_codec_pkt_list head;\
+- struct vpx_codec_cx_pkt pkts[n];} alloc;}
+-
+-#define vpx_codec_pkt_list_init(m)\
+- (m)->alloc.head.cnt = 0,\
+- (m)->alloc.head.max = sizeof((m)->alloc.pkts) / sizeof((m)->alloc.pkts[0])
+-
+-int
+-vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *,
+- const struct vpx_codec_cx_pkt *);
+-
+-const vpx_codec_cx_pkt_t*
+-vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
+- vpx_codec_iter_t *iter);
+-
+-
+-#include <stdio.h>
+-#include <setjmp.h>
+-struct vpx_internal_error_info
+-{
+- vpx_codec_err_t error_code;
+- int has_detail;
+- char detail[80];
+- int setjmp;
+- jmp_buf jmp;
+-};
+-
+-static void vpx_internal_error(struct vpx_internal_error_info *info,
+- vpx_codec_err_t error,
+- const char *fmt,
+- ...)
+-{
+- va_list ap;
+-
+- info->error_code = error;
+- info->has_detail = 0;
+-
+- if (fmt)
+- {
+- size_t sz = sizeof(info->detail);
+-
+- info->has_detail = 1;
+- va_start(ap, fmt);
+- vsnprintf(info->detail, sz - 1, fmt, ap);
+- va_end(ap);
+- info->detail[sz-1] = '\0';
+- }
+-
+- if (info->setjmp)
+- longjmp(info->jmp, info->error_code);
+-}
+-#endif
+diff --git a/vpx_codec/src/vpx_codec.c b/vpx_codec/src/vpx_codec.c
+deleted file mode 100644
+index 6366416..0000000
+--- a/vpx_codec/src/vpx_codec.c
++++ /dev/null
+@@ -1,196 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\file vpx_decoder.c
+- * \brief Provides the high level interface to wrap decoder algorithms.
+- *
+- */
+-#include <stdlib.h>
+-#include <string.h>
+-#include "vpx_codec/internal/vpx_codec_internal.h"
+-#include "vpx_version.h"
+-
+-#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
+-
+-int vpx_codec_version(void)
+-{
+- return VERSION_PACKED;
+-}
+-
+-
+-const char *vpx_codec_version_str(void)
+-{
+- return VERSION_STRING_NOSP;
+-}
+-
+-
+-const char *vpx_codec_version_extra_str(void)
+-{
+- return VERSION_EXTRA;
+-}
+-
+-
+-const char *vpx_codec_iface_name(vpx_codec_iface_t *iface)
+-{
+- return iface ? iface->name : "<invalid interface>";
+-}
+-
+-const char *vpx_codec_err_to_string(vpx_codec_err_t err)
+-{
+- switch (err)
+- {
+- case VPX_CODEC_OK:
+- return "Success";
+- case VPX_CODEC_ERROR:
+- return "Unspecified internal error";
+- case VPX_CODEC_MEM_ERROR:
+- return "Memory allocation error";
+- case VPX_CODEC_ABI_MISMATCH:
+- return "ABI version mismatch";
+- case VPX_CODEC_INCAPABLE:
+- return "Codec does not implement requested capability";
+- case VPX_CODEC_UNSUP_BITSTREAM:
+- return "Bitstream not supported by this decoder";
+- case VPX_CODEC_UNSUP_FEATURE:
+- return "Bitstream required feature not supported by this decoder";
+- case VPX_CODEC_CORRUPT_FRAME:
+- return "Corrupt frame detected";
+- case VPX_CODEC_INVALID_PARAM:
+- return "Invalid parameter";
+- case VPX_CODEC_LIST_END:
+- return "End of iterated list";
+- }
+-
+- return "Unrecognized error code";
+-}
+-
+-const char *vpx_codec_error(vpx_codec_ctx_t *ctx)
+-{
+- return (ctx) ? vpx_codec_err_to_string(ctx->err)
+- : vpx_codec_err_to_string(VPX_CODEC_INVALID_PARAM);
+-}
+-
+-const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx)
+-{
+- if (ctx && ctx->err)
+- return ctx->priv ? ctx->priv->err_detail : ctx->err_detail;
+-
+- return NULL;
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx,
+- vpx_codec_iface_t *iface,
+- vpx_codec_dec_cfg_t *cfg,
+- vpx_codec_flags_t flags,
+- int ver)
+-{
+- vpx_codec_err_t res;
+-
+- if (ver != VPX_DECODER_ABI_VERSION)
+- res = VPX_CODEC_ABI_MISMATCH;
+- else if (!ctx || !iface)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
+- res = VPX_CODEC_ABI_MISMATCH;
+- else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
+- res = VPX_CODEC_INCAPABLE;
+- else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC))
+- res = VPX_CODEC_INCAPABLE;
+- else
+- {
+- memset(ctx, 0, sizeof(*ctx));
+- ctx->iface = iface;
+- ctx->name = iface->name;
+- ctx->priv = NULL;
+- ctx->init_flags = flags;
+- ctx->config.dec = cfg;
+- res = VPX_CODEC_OK;
+-
+- if (!(flags & VPX_CODEC_USE_XMA))
+- {
+- res = ctx->iface->init(ctx);
+-
+- if (res)
+- {
+- ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
+- vpx_codec_destroy(ctx);
+- }
+-
+- if (ctx->priv)
+- ctx->priv->iface = ctx->iface;
+- }
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx)
+-{
+- vpx_codec_err_t res;
+-
+- if (!ctx)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!ctx->iface || !ctx->priv)
+- res = VPX_CODEC_ERROR;
+- else
+- {
+- if (ctx->priv->alg_priv)
+- ctx->iface->destroy(ctx->priv->alg_priv);
+-
+- ctx->iface = NULL;
+- ctx->name = NULL;
+- ctx->priv = NULL;
+- res = VPX_CODEC_OK;
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface)
+-{
+- return (iface) ? iface->caps : 0;
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx,
+- int ctrl_id,
+- ...)
+-{
+- vpx_codec_err_t res;
+-
+- if (!ctx || !ctrl_id)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!ctx->iface || !ctx->priv || !ctx->iface->ctrl_maps)
+- res = VPX_CODEC_ERROR;
+- else
+- {
+- vpx_codec_ctrl_fn_map_t *entry;
+-
+- res = VPX_CODEC_ERROR;
+-
+- for (entry = ctx->iface->ctrl_maps; entry && entry->fn; entry++)
+- {
+- if (!entry->ctrl_id || entry->ctrl_id == ctrl_id)
+- {
+- va_list ap;
+-
+- va_start(ap, ctrl_id);
+- res = entry->fn(ctx->priv->alg_priv, ctrl_id, ap);
+- va_end(ap);
+- break;
+- }
+- }
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+diff --git a/vpx_codec/src/vpx_decoder.c b/vpx_codec/src/vpx_decoder.c
+deleted file mode 100644
+index 7e8575f..0000000
+--- a/vpx_codec/src/vpx_decoder.c
++++ /dev/null
+@@ -1,201 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\file vpx_decoder.c
+- * \brief Provides the high level interface to wrap decoder algorithms.
+- *
+- */
+-#include <stdlib.h>
+-#include "vpx_codec/internal/vpx_codec_internal.h"
+-
+-#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
+-
+-vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface,
+- const uint8_t *data,
+- unsigned int data_sz,
+- vpx_codec_stream_info_t *si)
+-{
+- vpx_codec_err_t res;
+-
+- if (!iface || !data || !data_sz || !si
+- || si->sz < sizeof(vpx_codec_stream_info_t))
+- res = VPX_CODEC_INVALID_PARAM;
+- else
+- {
+- /* Set default/unknown values */
+- si->w = 0;
+- si->h = 0;
+-
+- res = iface->dec.peek_si(data, data_sz, si);
+- }
+-
+- return res;
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx,
+- vpx_codec_stream_info_t *si)
+-{
+- vpx_codec_err_t res;
+-
+- if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t))
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!ctx->iface || !ctx->priv)
+- res = VPX_CODEC_ERROR;
+- else
+- {
+- /* Set default/unknown values */
+- si->w = 0;
+- si->h = 0;
+-
+- res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si);
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx,
+- const uint8_t *data,
+- unsigned int data_sz,
+- void *user_priv,
+- long deadline)
+-{
+- vpx_codec_err_t res;
+-
+- if (!ctx || !data || !data_sz)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!ctx->iface || !ctx->priv)
+- res = VPX_CODEC_ERROR;
+-
+-#if CONFIG_EVAL_LIMIT
+- else if (ctx->priv->eval_counter >= 500)
+- {
+- ctx->priv->err_detail = "Evaluation limit exceeded.";
+- res = VPX_CODEC_ERROR;
+- }
+-
+-#endif
+- else
+- {
+- res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz,
+- user_priv, deadline);
+-#if CONFIG_EVAL_LIMIT
+- ctx->priv->eval_counter++;
+-#endif
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx,
+- vpx_codec_iter_t *iter)
+-{
+- vpx_image_t *img;
+-
+- if (!ctx || !iter || !ctx->iface || !ctx->priv)
+- img = NULL;
+- else
+- img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter);
+-
+- return img;
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx,
+- vpx_codec_put_frame_cb_fn_t cb,
+- void *user_priv)
+-{
+- vpx_codec_err_t res;
+-
+- if (!ctx || !cb)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!ctx->iface || !ctx->priv
+- || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
+- res = VPX_CODEC_ERROR;
+- else
+- {
+- ctx->priv->dec.put_frame_cb.put_frame = cb;
+- ctx->priv->dec.put_frame_cb.user_priv = user_priv;
+- res = VPX_CODEC_OK;
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx,
+- vpx_codec_put_slice_cb_fn_t cb,
+- void *user_priv)
+-{
+- vpx_codec_err_t res;
+-
+- if (!ctx || !cb)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!ctx->iface || !ctx->priv
+- || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
+- res = VPX_CODEC_ERROR;
+- else
+- {
+- ctx->priv->dec.put_slice_cb.put_slice = cb;
+- ctx->priv->dec.put_slice_cb.user_priv = user_priv;
+- res = VPX_CODEC_OK;
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx,
+- vpx_codec_mmap_t *mmap,
+- vpx_codec_iter_t *iter)
+-{
+- vpx_codec_err_t res = VPX_CODEC_OK;
+-
+- if (!ctx || !mmap || !iter || !ctx->iface)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA))
+- res = VPX_CODEC_ERROR;
+- else
+- res = ctx->iface->get_mmap(ctx, mmap, iter);
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx,
+- vpx_codec_mmap_t *mmap,
+- unsigned int num_maps)
+-{
+- vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
+-
+- if (!ctx || !mmap || !ctx->iface)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA))
+- res = VPX_CODEC_ERROR;
+- else
+- {
+- unsigned int i;
+-
+- for (i = 0; i < num_maps; i++, mmap++)
+- {
+- if (!mmap->base)
+- break;
+-
+- /* Everything look ok, set the mmap in the decoder */
+- res = ctx->iface->set_mmap(ctx, mmap);
+-
+- if (res)
+- break;
+- }
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+diff --git a/vpx_codec/src/vpx_decoder_compat.c b/vpx_codec/src/vpx_decoder_compat.c
+deleted file mode 100644
+index d5b04ae..0000000
+--- a/vpx_codec/src/vpx_decoder_compat.c
++++ /dev/null
+@@ -1,200 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\file vpx_decoder.c
+- * \brief Provides the high level interface to wrap decoder algorithms.
+- *
+- */
+-#include <stdlib.h>
+-#include <string.h>
+-#include "vpx_codec/vpx_decoder.h"
+-#include "vpx_codec/internal/vpx_codec_internal.h"
+-
+-#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
+-
+-const char *vpx_dec_iface_name(vpx_dec_iface_t *iface)
+-{
+- return vpx_codec_iface_name((vpx_codec_iface_t *)iface);
+-}
+-
+-const char *vpx_dec_err_to_string(vpx_dec_err_t err)
+-{
+- return vpx_codec_err_to_string(err);
+-}
+-
+-const char *vpx_dec_error(vpx_dec_ctx_t *ctx)
+-{
+- return vpx_codec_error((vpx_codec_ctx_t *)ctx);
+-}
+-
+-const char *vpx_dec_error_detail(vpx_dec_ctx_t *ctx)
+-{
+- return vpx_codec_error_detail((vpx_codec_ctx_t *)ctx);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_init_ver(vpx_dec_ctx_t *ctx,
+- vpx_dec_iface_t *iface,
+- int ver)
+-{
+- return vpx_codec_dec_init_ver((vpx_codec_ctx_t *)ctx,
+- (vpx_codec_iface_t *)iface,
+- NULL,
+- 0,
+- ver);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_destroy(vpx_dec_ctx_t *ctx)
+-{
+- return vpx_codec_destroy((vpx_codec_ctx_t *)ctx);
+-}
+-
+-
+-vpx_dec_caps_t vpx_dec_get_caps(vpx_dec_iface_t *iface)
+-{
+- return vpx_codec_get_caps((vpx_codec_iface_t *)iface);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_peek_stream_info(vpx_dec_iface_t *iface,
+- const uint8_t *data,
+- unsigned int data_sz,
+- vpx_dec_stream_info_t *si)
+-{
+- return vpx_codec_peek_stream_info((vpx_codec_iface_t *)iface, data, data_sz,
+- (vpx_codec_stream_info_t *)si);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_get_stream_info(vpx_dec_ctx_t *ctx,
+- vpx_dec_stream_info_t *si)
+-{
+- return vpx_codec_get_stream_info((vpx_codec_ctx_t *)ctx,
+- (vpx_codec_stream_info_t *)si);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_control(vpx_dec_ctx_t *ctx,
+- int ctrl_id,
+- void *data)
+-{
+- return vpx_codec_control_((vpx_codec_ctx_t *)ctx, ctrl_id, data);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_decode(vpx_dec_ctx_t *ctx,
+- uint8_t *data,
+- unsigned int data_sz,
+- void *user_priv,
+- int rel_pts)
+-{
+- (void)rel_pts;
+- return vpx_codec_decode((vpx_codec_ctx_t *)ctx, data, data_sz, user_priv,
+- 0);
+-}
+-
+-vpx_image_t *vpx_dec_get_frame(vpx_dec_ctx_t *ctx,
+- vpx_dec_iter_t *iter)
+-{
+- return vpx_codec_get_frame((vpx_codec_ctx_t *)ctx, iter);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_register_put_frame_cb(vpx_dec_ctx_t *ctx,
+- vpx_dec_put_frame_cb_fn_t cb,
+- void *user_priv)
+-{
+- return vpx_codec_register_put_frame_cb((vpx_codec_ctx_t *)ctx, cb,
+- user_priv);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_register_put_slice_cb(vpx_dec_ctx_t *ctx,
+- vpx_dec_put_slice_cb_fn_t cb,
+- void *user_priv)
+-{
+- return vpx_codec_register_put_slice_cb((vpx_codec_ctx_t *)ctx, cb,
+- user_priv);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_xma_init_ver(vpx_dec_ctx_t *ctx,
+- vpx_dec_iface_t *iface,
+- int ver)
+-{
+- return vpx_codec_dec_init_ver((vpx_codec_ctx_t *)ctx,
+- (vpx_codec_iface_t *)iface,
+- NULL,
+- VPX_CODEC_USE_XMA,
+- ver);
+-}
+-
+-vpx_dec_err_t vpx_dec_get_mem_map(vpx_dec_ctx_t *ctx_,
+- vpx_dec_mmap_t *mmap,
+- const vpx_dec_stream_info_t *si,
+- vpx_dec_iter_t *iter)
+-{
+- vpx_codec_ctx_t *ctx = (vpx_codec_ctx_t *)ctx_;
+- vpx_dec_err_t res = VPX_DEC_OK;
+-
+- if (!ctx || !mmap || !si || !iter || !ctx->iface)
+- res = VPX_DEC_INVALID_PARAM;
+- else if (!(ctx->iface->caps & VPX_DEC_CAP_XMA))
+- res = VPX_DEC_ERROR;
+- else
+- {
+- if (!ctx->config.dec)
+- {
+- ctx->config.dec = malloc(sizeof(vpx_codec_dec_cfg_t));
+- ctx->config.dec->w = si->w;
+- ctx->config.dec->h = si->h;
+- }
+-
+- res = ctx->iface->get_mmap(ctx, mmap, iter);
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-vpx_dec_err_t vpx_dec_set_mem_map(vpx_dec_ctx_t *ctx_,
+- vpx_dec_mmap_t *mmap,
+- unsigned int num_maps)
+-{
+- vpx_codec_ctx_t *ctx = (vpx_codec_ctx_t *)ctx_;
+- vpx_dec_err_t res = VPX_DEC_MEM_ERROR;
+-
+- if (!ctx || !mmap || !ctx->iface)
+- res = VPX_DEC_INVALID_PARAM;
+- else if (!(ctx->iface->caps & VPX_DEC_CAP_XMA))
+- res = VPX_DEC_ERROR;
+- else
+- {
+- void *save = (ctx->priv) ? NULL : ctx->config.dec;
+- unsigned int i;
+-
+- for (i = 0; i < num_maps; i++, mmap++)
+- {
+- if (!mmap->base)
+- break;
+-
+- /* Everything look ok, set the mmap in the decoder */
+- res = ctx->iface->set_mmap(ctx, mmap);
+-
+- if (res)
+- break;
+- }
+-
+- if (save) free(save);
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+diff --git a/vpx_codec/src/vpx_encoder.c b/vpx_codec/src/vpx_encoder.c
+deleted file mode 100644
+index 98ad8ba..0000000
+--- a/vpx_codec/src/vpx_encoder.c
++++ /dev/null
+@@ -1,324 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\file vpx_encoder.c
+- * \brief Provides the high level interface to wrap encoder algorithms.
+- *
+- */
+-#include <limits.h>
+-#include <string.h>
+-#include "vpx_codec/internal/vpx_codec_internal.h"
+-
+-#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
+-
+-vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
+- vpx_codec_iface_t *iface,
+- vpx_codec_enc_cfg_t *cfg,
+- vpx_codec_flags_t flags,
+- int ver)
+-{
+- vpx_codec_err_t res;
+-
+- if (ver != VPX_ENCODER_ABI_VERSION)
+- res = VPX_CODEC_ABI_MISMATCH;
+- else if (!ctx || !iface || !cfg)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
+- res = VPX_CODEC_ABI_MISMATCH;
+- else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
+- res = VPX_CODEC_INCAPABLE;
+- else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
+- res = VPX_CODEC_INCAPABLE;
+- else if ((flags & VPX_CODEC_USE_PSNR)
+- && !(iface->caps & VPX_CODEC_CAP_PSNR))
+- res = VPX_CODEC_INCAPABLE;
+- else
+- {
+- ctx->iface = iface;
+- ctx->name = iface->name;
+- ctx->priv = NULL;
+- ctx->init_flags = flags;
+- ctx->config.enc = cfg;
+- res = ctx->iface->init(ctx);
+-
+- if (res)
+- {
+- ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
+- vpx_codec_destroy(ctx);
+- }
+-
+- if (ctx->priv)
+- ctx->priv->iface = ctx->iface;
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-
+-vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface,
+- vpx_codec_enc_cfg_t *cfg,
+- unsigned int usage)
+-{
+- vpx_codec_err_t res;
+- vpx_codec_enc_cfg_map_t *map;
+-
+- if (!iface || !cfg || usage > INT_MAX)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
+- res = VPX_CODEC_INCAPABLE;
+- else
+- {
+- res = VPX_CODEC_INVALID_PARAM;
+-
+- for (map = iface->enc.cfg_maps; map->usage >= 0; map++)
+- {
+- if (map->usage == (int)usage)
+- {
+- *cfg = map->cfg;
+- cfg->g_usage = usage;
+- res = VPX_CODEC_OK;
+- break;
+- }
+- }
+- }
+-
+- return res;
+-}
+-
+-
+-#if ARCH_X86 || ARCH_X86_64
+-/* On X86, disable the x87 unit's internal 80 bit precision for better
+- * consistency with the SSE unit's 64 bit precision.
+- */
+-#include "vpx_ports/x86.h"
+-#define FLOATING_POINT_INIT() do {\
+- unsigned short x87_orig_mode = x87_set_double_precision();
+-#define FLOATING_POINT_RESTORE() \
+- x87_set_control_word(x87_orig_mode); }while(0)
+-
+-
+-#else
+-static void FLOATING_POINT_INIT() {}
+-static void FLOATING_POINT_RESTORE() {}
+-#endif
+-
+-
+-vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx,
+- const vpx_image_t *img,
+- vpx_codec_pts_t pts,
+- unsigned long duration,
+- vpx_enc_frame_flags_t flags,
+- unsigned long deadline)
+-{
+- vpx_codec_err_t res;
+-
+- if (!ctx || (img && !duration))
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!ctx->iface || !ctx->priv)
+- res = VPX_CODEC_ERROR;
+- else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+- res = VPX_CODEC_INCAPABLE;
+-
+-#if CONFIG_EVAL_LIMIT
+- else if (ctx->priv->eval_counter >= 500)
+- {
+- ctx->priv->err_detail = "Evaluation limit exceeded.";
+- res = VPX_CODEC_ERROR;
+- }
+-
+-#endif
+- else
+- {
+- /* Execute in a normalized floating point environment, if the platform
+- * requires it.
+- */
+- FLOATING_POINT_INIT();
+- res = ctx->iface->enc.encode(ctx->priv->alg_priv, img, pts,
+- duration, flags, deadline);
+- FLOATING_POINT_RESTORE();
+-
+-#if CONFIG_EVAL_LIMIT
+- ctx->priv->eval_counter++;
+-#endif
+- }
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx,
+- vpx_codec_iter_t *iter)
+-{
+- const vpx_codec_cx_pkt_t *pkt = NULL;
+-
+- if (ctx)
+- {
+- if (!iter)
+- ctx->err = VPX_CODEC_INVALID_PARAM;
+- else if (!ctx->iface || !ctx->priv)
+- ctx->err = VPX_CODEC_ERROR;
+- else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+- ctx->err = VPX_CODEC_INCAPABLE;
+- else
+- pkt = ctx->iface->enc.get_cx_data(ctx->priv->alg_priv, iter);
+- }
+-
+- if (pkt && pkt->kind == VPX_CODEC_CX_FRAME_PKT)
+- {
+- /* If the application has specified a destination area for the
+- * compressed data, and the codec has not placed the data there,
+- * and it fits, copy it.
+- */
+- char *dst_buf = ctx->priv->enc.cx_data_dst_buf.buf;
+-
+- if (dst_buf
+- && pkt->data.raw.buf != dst_buf
+- && pkt->data.raw.sz
+- + ctx->priv->enc.cx_data_pad_before
+- + ctx->priv->enc.cx_data_pad_after
+- <= ctx->priv->enc.cx_data_dst_buf.sz)
+- {
+- vpx_codec_cx_pkt_t *modified_pkt = &ctx->priv->enc.cx_data_pkt;
+-
+- memcpy(dst_buf + ctx->priv->enc.cx_data_pad_before,
+- pkt->data.raw.buf, pkt->data.raw.sz);
+- *modified_pkt = *pkt;
+- modified_pkt->data.raw.buf = dst_buf;
+- modified_pkt->data.raw.sz += ctx->priv->enc.cx_data_pad_before
+- + ctx->priv->enc.cx_data_pad_after;
+- pkt = modified_pkt;
+- }
+-
+- if (dst_buf == pkt->data.raw.buf)
+- {
+- ctx->priv->enc.cx_data_dst_buf.buf = dst_buf + pkt->data.raw.sz;
+- ctx->priv->enc.cx_data_dst_buf.sz -= pkt->data.raw.sz;
+- }
+- }
+-
+- return pkt;
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx,
+- const vpx_fixed_buf_t *buf,
+- unsigned int pad_before,
+- unsigned int pad_after)
+-{
+- if (!ctx || !ctx->priv)
+- return VPX_CODEC_INVALID_PARAM;
+-
+- if (buf)
+- {
+- ctx->priv->enc.cx_data_dst_buf = *buf;
+- ctx->priv->enc.cx_data_pad_before = pad_before;
+- ctx->priv->enc.cx_data_pad_after = pad_after;
+- }
+- else
+- {
+- ctx->priv->enc.cx_data_dst_buf.buf = NULL;
+- ctx->priv->enc.cx_data_dst_buf.sz = 0;
+- ctx->priv->enc.cx_data_pad_before = 0;
+- ctx->priv->enc.cx_data_pad_after = 0;
+- }
+-
+- return VPX_CODEC_OK;
+-}
+-
+-
+-const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx)
+-{
+- vpx_image_t *img = NULL;
+-
+- if (ctx)
+- {
+- if (!ctx->iface || !ctx->priv)
+- ctx->err = VPX_CODEC_ERROR;
+- else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+- ctx->err = VPX_CODEC_INCAPABLE;
+- else if (!ctx->iface->enc.get_preview)
+- ctx->err = VPX_CODEC_INCAPABLE;
+- else
+- img = ctx->iface->enc.get_preview(ctx->priv->alg_priv);
+- }
+-
+- return img;
+-}
+-
+-
+-vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx)
+-{
+- vpx_fixed_buf_t *buf = NULL;
+-
+- if (ctx)
+- {
+- if (!ctx->iface || !ctx->priv)
+- ctx->err = VPX_CODEC_ERROR;
+- else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+- ctx->err = VPX_CODEC_INCAPABLE;
+- else if (!ctx->iface->enc.get_glob_hdrs)
+- ctx->err = VPX_CODEC_INCAPABLE;
+- else
+- buf = ctx->iface->enc.get_glob_hdrs(ctx->priv->alg_priv);
+- }
+-
+- return buf;
+-}
+-
+-
+-vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx,
+- const vpx_codec_enc_cfg_t *cfg)
+-{
+- vpx_codec_err_t res;
+-
+- if (!ctx || !ctx->iface || !ctx->priv || !cfg)
+- res = VPX_CODEC_INVALID_PARAM;
+- else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+- res = VPX_CODEC_INCAPABLE;
+- else
+- res = ctx->iface->enc.cfg_set(ctx->priv->alg_priv, cfg);
+-
+- return SAVE_STATUS(ctx, res);
+-}
+-
+-
+-int vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *list,
+- const struct vpx_codec_cx_pkt *pkt)
+-{
+- if (list->cnt < list->max)
+- {
+- list->pkts[list->cnt++] = *pkt;
+- return 0;
+- }
+-
+- return 1;
+-}
+-
+-
+-const vpx_codec_cx_pkt_t *vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
+- vpx_codec_iter_t *iter)
+-{
+- const vpx_codec_cx_pkt_t *pkt;
+-
+- if (!(*iter))
+- {
+- *iter = list->pkts;
+- }
+-
+- pkt = (const void *) * iter;
+-
+- if (pkt - list->pkts < list->cnt)
+- *iter = pkt + 1;
+- else
+- pkt = NULL;
+-
+- return pkt;
+-}
+diff --git a/vpx_codec/src/vpx_image.c b/vpx_codec/src/vpx_image.c
+deleted file mode 100644
+index 8a16e58..0000000
+--- a/vpx_codec/src/vpx_image.c
++++ /dev/null
+@@ -1,261 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-#include <stdlib.h>
+-#include <string.h>
+-#include "vpx_codec/vpx_image.h"
+-
+-static vpx_image_t *img_alloc_helper(vpx_image_t *img,
+- img_fmt_t fmt,
+- unsigned int d_w,
+- unsigned int d_h,
+- unsigned int stride_align,
+- unsigned char *img_data)
+-{
+-
+- unsigned int h, w, s, xcs, ycs, bps;
+- int align;
+-
+- /* Treat align==0 like align==1 */
+- if (!stride_align)
+- stride_align = 1;
+-
+- /* Validate alignment (must be power of 2) */
+- if (stride_align & (stride_align - 1))
+- goto fail;
+-
+- /* Get sample size for this format */
+- switch (fmt)
+- {
+- case IMG_FMT_RGB32:
+- case IMG_FMT_RGB32_LE:
+- case IMG_FMT_ARGB:
+- case IMG_FMT_ARGB_LE:
+- bps = 32;
+- break;
+- case IMG_FMT_RGB24:
+- case IMG_FMT_BGR24:
+- bps = 24;
+- break;
+- case IMG_FMT_RGB565:
+- case IMG_FMT_RGB565_LE:
+- case IMG_FMT_RGB555:
+- case IMG_FMT_RGB555_LE:
+- case IMG_FMT_UYVY:
+- case IMG_FMT_YUY2:
+- case IMG_FMT_YVYU:
+- bps = 16;
+- break;
+- case IMG_FMT_I420:
+- case IMG_FMT_YV12:
+- case IMG_FMT_VPXI420:
+- case IMG_FMT_VPXYV12:
+- bps = 12;
+- break;
+- default:
+- bps = 16;
+- break;
+- }
+-
+- /* Get chroma shift values for this format */
+- switch (fmt)
+- {
+- case IMG_FMT_I420:
+- case IMG_FMT_YV12:
+- case IMG_FMT_VPXI420:
+- case IMG_FMT_VPXYV12:
+- xcs = 1;
+- break;
+- default:
+- xcs = 0;
+- break;
+- }
+-
+- switch (fmt)
+- {
+- case IMG_FMT_I420:
+- case IMG_FMT_YV12:
+- case IMG_FMT_VPXI420:
+- case IMG_FMT_VPXYV12:
+- ycs = 1;
+- break;
+- default:
+- ycs = 0;
+- break;
+- }
+-
+- /* Calculate storage sizes given the chroma subsampling */
+- align = (1 << xcs) - 1;
+- w = (d_w + align) & ~align;
+- align = (1 << ycs) - 1;
+- h = (d_h + align) & ~align;
+- s = (fmt & IMG_FMT_PLANAR) ? w : bps * w / 8;
+- s = (s + stride_align - 1) & ~(stride_align - 1);
+-
+- /* Allocate the new image */
+- if (!img)
+- {
+- img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t));
+-
+- if (!img)
+- goto fail;
+-
+- img->self_allocd = 1;
+- }
+- else
+- {
+- memset(img, 0, sizeof(vpx_image_t));
+- }
+-
+- img->img_data = img_data;
+-
+- if (!img_data)
+- {
+- img->img_data = malloc((fmt & IMG_FMT_PLANAR) ? h * w * bps / 8 : h * s);
+- img->img_data_owner = 1;
+- }
+-
+- if (!img->img_data)
+- goto fail;
+-
+- img->fmt = fmt;
+- img->w = w;
+- img->h = h;
+- img->x_chroma_shift = xcs;
+- img->y_chroma_shift = ycs;
+- img->bps = bps;
+-
+- /* Calculate strides */
+- img->stride[PLANE_Y] = img->stride[PLANE_ALPHA] = s;
+- img->stride[PLANE_U] = img->stride[PLANE_V] = s >> xcs;
+-
+- /* Default viewport to entire image */
+- if (!vpx_img_set_rect(img, 0, 0, d_w, d_h))
+- return img;
+-
+-fail:
+- vpx_img_free(img);
+- return NULL;
+-}
+-
+-vpx_image_t *vpx_img_alloc(vpx_image_t *img,
+- img_fmt_t fmt,
+- unsigned int d_w,
+- unsigned int d_h,
+- unsigned int stride_align)
+-{
+- return img_alloc_helper(img, fmt, d_w, d_h, stride_align, NULL);
+-}
+-
+-vpx_image_t *vpx_img_wrap(vpx_image_t *img,
+- img_fmt_t fmt,
+- unsigned int d_w,
+- unsigned int d_h,
+- unsigned int stride_align,
+- unsigned char *img_data)
+-{
+- return img_alloc_helper(img, fmt, d_w, d_h, stride_align, img_data);
+-}
+-
+-int vpx_img_set_rect(vpx_image_t *img,
+- unsigned int x,
+- unsigned int y,
+- unsigned int w,
+- unsigned int h)
+-{
+- unsigned char *data;
+-
+- if (x + w <= img->w && y + h <= img->h)
+- {
+- img->d_w = w;
+- img->d_h = h;
+-
+- /* Calculate plane pointers */
+- if (!(img->fmt & IMG_FMT_PLANAR))
+- {
+- img->planes[PLANE_PACKED] =
+- img->img_data + x * img->bps / 8 + y * img->stride[PLANE_PACKED];
+- }
+- else
+- {
+- data = img->img_data;
+-
+- if (img->fmt & IMG_FMT_HAS_ALPHA)
+- {
+- img->planes[PLANE_ALPHA] =
+- data + x + y * img->stride[PLANE_ALPHA];
+- data += img->h * img->stride[PLANE_ALPHA];
+- }
+-
+- img->planes[PLANE_Y] = data + x + y * img->stride[PLANE_Y];
+- data += img->h * img->stride[PLANE_Y];
+-
+- if (!(img->fmt & IMG_FMT_UV_FLIP))
+- {
+- img->planes[PLANE_U] = data
+- + (x >> img->x_chroma_shift)
+- + (y >> img->y_chroma_shift) * img->stride[PLANE_U];
+- data += (img->h >> img->y_chroma_shift) * img->stride[PLANE_U];
+- img->planes[PLANE_V] = data
+- + (x >> img->x_chroma_shift)
+- + (y >> img->y_chroma_shift) * img->stride[PLANE_V];
+- }
+- else
+- {
+- img->planes[PLANE_V] = data
+- + (x >> img->x_chroma_shift)
+- + (y >> img->y_chroma_shift) * img->stride[PLANE_V];
+- data += (img->h >> img->y_chroma_shift) * img->stride[PLANE_V];
+- img->planes[PLANE_U] = data
+- + (x >> img->x_chroma_shift)
+- + (y >> img->y_chroma_shift) * img->stride[PLANE_U];
+- }
+- }
+-
+- return 0;
+- }
+-
+- return -1;
+-}
+-
+-void vpx_img_flip(vpx_image_t *img)
+-{
+- /* Note: In the calculation pointer adjustment calculation, we want the
+- * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99
+- * standard indicates that if the adjustment parameter is unsigned, the
+- * stride parameter will be promoted to unsigned, causing errors when
+- * the lhs is a larger type than the rhs.
+- */
+- img->planes[PLANE_Y] += (signed)(img->d_h - 1) * img->stride[PLANE_Y];
+- img->stride[PLANE_Y] = -img->stride[PLANE_Y];
+-
+- img->planes[PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
+- * img->stride[PLANE_U];
+- img->stride[PLANE_U] = -img->stride[PLANE_U];
+-
+- img->planes[PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
+- * img->stride[PLANE_V];
+- img->stride[PLANE_V] = -img->stride[PLANE_V];
+-
+- img->planes[PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[PLANE_ALPHA];
+- img->stride[PLANE_ALPHA] = -img->stride[PLANE_ALPHA];
+-}
+-
+-void vpx_img_free(vpx_image_t *img)
+-{
+- if (img)
+- {
+- if (img->img_data && img->img_data_owner)
+- free(img->img_data);
+-
+- if (img->self_allocd)
+- free(img);
+- }
+-}
+diff --git a/vpx_codec/vpx_codec.h b/vpx_codec/vpx_codec.h
+deleted file mode 100644
+index e2a79f9..0000000
+--- a/vpx_codec/vpx_codec.h
++++ /dev/null
+@@ -1,560 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\defgroup codec Common Algorithm Interface
+- * This abstraction allows applications to easily support multiple video
+- * formats with minimal code duplication. This section describes the interface
+- * common to all codecs (both encoders and decoders).
+- * @{
+- */
+-
+-/*!\file vpx_codec.h
+- * \brief Describes the codec algorithm interface to applications.
+- *
+- * This file describes the interface between an application and a
+- * video codec algorithm.
+- *
+- * An application instantiates a specific codec instance by using
+- * vpx_codec_init() and a pointer to the algorithm's interface structure:
+- * <pre>
+- * my_app.c:
+- * extern vpx_codec_iface_t my_codec;
+- * {
+- * vpx_codec_ctx_t algo;
+- * res = vpx_codec_init(&algo, &my_codec);
+- * }
+- * </pre>
+- *
+- * Once initialized, the instance is manged using other functions from
+- * the vpx_codec_* family.
+- */
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#ifndef VPX_CODEC_H
+-#define VPX_CODEC_H
+-#ifdef HAVE_CONFIG_H
+-# include "vpx_config.h"
+-#endif
+-#if defined(HAVE_VPX_PORTS) && HAVE_VPX_PORTS
+-# include "vpx_ports/vpx_integer.h"
+-#else
+-# include "vpx_integer.h"
+-#endif
+-#include "vpx_image.h"
+-
+- /*!\brief Decorator indicating a function is deprecated */
+-#ifndef DEPRECATED
+-#if defined(__GNUC__) && __GNUC__
+-#define DEPRECATED __attribute__ ((deprecated))
+-#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
+-#elif defined(_MSC_VER)
+-#define DEPRECATED
+-#define DECLSPEC_DEPRECATED __declspec(deprecated) /**< \copydoc #DEPRECATED */
+-#else
+-#define DEPRECATED
+-#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
+-#endif
+-#endif
+-
+- /*!\brief Decorator indicating a function is potentially unused */
+-#ifdef UNUSED
+-#elif __GNUC__
+-#define UNUSED __attribute__ ((unused));
+-#else
+-#define UNUSED
+-#endif
+-
+- /*!\brief Current ABI version number
+- *
+- * \internal
+- * If this file is altered in any way that changes the ABI, this value
+- * must be bumped. Examples include, but are not limited to, changing
+- * types, removing or reassigning enums, adding/removing/rearranging
+- * fields to structures
+- */
+-#define VPX_CODEC_ABI_VERSION (2 + VPX_IMAGE_ABI_VERSION) /**<\hideinitializer*/
+-
+- /*!\brief Algorithm return codes */
+- typedef enum {
+- /*!\brief Operation completed without error */
+- VPX_CODEC_OK,
+-
+- /*!\brief Unspecified error */
+- VPX_CODEC_ERROR,
+-
+- /*!\brief Memory operation failed */
+- VPX_CODEC_MEM_ERROR,
+-
+- /*!\brief ABI version mismatch */
+- VPX_CODEC_ABI_MISMATCH,
+-
+- /*!\brief Algorithm does not have required capability */
+- VPX_CODEC_INCAPABLE,
+-
+- /*!\brief The given bitstream is not supported.
+- *
+- * The bitstream was unable to be parsed at the highest level. The decoder
+- * is unable to proceed. This error \ref SHOULD be treated as fatal to the
+- * stream. */
+- VPX_CODEC_UNSUP_BITSTREAM,
+-
+- /*!\brief Encoded bitstream uses an unsupported feature
+- *
+- * The decoder does not implement a feature required by the encoder. This
+- * return code should only be used for features that prevent future
+- * pictures from being properly decoded. This error \ref MAY be treated as
+- * fatal to the stream or \ref MAY be treated as fatal to the current GOP.
+- */
+- VPX_CODEC_UNSUP_FEATURE,
+-
+- /*!\brief The coded data for this stream is corrupt or incomplete
+- *
+- * There was a problem decoding the current frame. This return code
+- * should only be used for failures that prevent future pictures from
+- * being properly decoded. This error \ref MAY be treated as fatal to the
+- * stream or \ref MAY be treated as fatal to the current GOP. If decoding
+- * is continued for the current GOP, artifacts may be present.
+- */
+- VPX_CODEC_CORRUPT_FRAME,
+-
+- /*!\brief An application-supplied parameter is not valid.
+- *
+- */
+- VPX_CODEC_INVALID_PARAM,
+-
+- /*!\brief An iterator reached the end of list.
+- *
+- */
+- VPX_CODEC_LIST_END,
+-
+- }
+- vpx_codec_err_t;
+-
+-
+- /*! \brief Codec capabilities bitfield
+- *
+- * Each codec advertises the capabilities it supports as part of its
+- * ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
+- * or functionality, and are not required to be supported.
+- *
+- * The available flags are specified by VPX_CODEC_CAP_* defines.
+- */
+- typedef long vpx_codec_caps_t;
+-#define VPX_CODEC_CAP_DECODER 0x1 /**< Is a decoder */
+-#define VPX_CODEC_CAP_ENCODER 0x2 /**< Is an encoder */
+-#define VPX_CODEC_CAP_XMA 0x4 /**< Supports e_xternal Memory Allocation */
+-
+-
+- /*! \brief Initialization-time Feature Enabling
+- *
+- * Certain codec features must be known at initialization time, to allow for
+- * proper memory allocation.
+- *
+- * The available flags are specified by VPX_CODEC_USE_* defines.
+- */
+- typedef long vpx_codec_flags_t;
+-#define VPX_CODEC_USE_XMA 0x00000001 /**< Use e_xternal Memory Allocation mode */
+-
+-
+- /*!\brief Codec interface structure.
+- *
+- * Contains function pointers and other data private to the codec
+- * implementation. This structure is opaque to the application.
+- */
+- typedef const struct vpx_codec_iface vpx_codec_iface_t;
+-
+-
+- /*!\brief Codec private data structure.
+- *
+- * Contains data private to the codec implementation. This structure is opaque
+- * to the application.
+- */
+- typedef struct vpx_codec_priv vpx_codec_priv_t;
+-
+-
+- /*!\brief Iterator
+- *
+- * Opaque storage used for iterating over lists.
+- */
+- typedef const void *vpx_codec_iter_t;
+-
+-
+- /*!\brief Codec context structure
+- *
+- * All codecs \ref MUST support this context structure fully. In general,
+- * this data should be considered private to the codec algorithm, and
+- * not be manipulated or examined by the calling application. Applications
+- * may reference the 'name' member to get a printable description of the
+- * algorithm.
+- */
+- typedef struct
+- {
+- const char *name; /**< Printable interface name */
+- vpx_codec_iface_t *iface; /**< Interface pointers */
+- vpx_codec_err_t err; /**< Last returned error */
+- const char *err_detail; /**< Detailed info, if available */
+- vpx_codec_flags_t init_flags; /**< Flags passed at init time */
+- union
+- {
+- struct vpx_codec_dec_cfg *dec; /**< Decoder Configuration Pointer */
+- struct vpx_codec_enc_cfg *enc; /**< Encoder Configuration Pointer */
+- void *raw;
+- } config; /**< Configuration pointer aliasing union */
+- vpx_codec_priv_t *priv; /**< Algorithm private storage */
+- } vpx_codec_ctx_t;
+-
+-
+- /*
+- * Library Version Number Interface
+- *
+- * For example, see the following sample return values:
+- * vpx_codec_version() (1<<16 | 2<<8 | 3)
+- * vpx_codec_version_str() "v1.2.3-rc1-16-gec6a1ba"
+- * vpx_codec_version_extra_str() "rc1-16-gec6a1ba"
+- */
+-
+- /*!\brief Return the version information (as an integer)
+- *
+- * Returns a packed encoding of the library version number. This will only include
+- * the major.minor.patch component of the version number. Note that this encoded
+- * value should be accessed through the macros provided, as the encoding may change
+- * in the future.
+- *
+- */
+- int vpx_codec_version(void);
+-#define VPX_VERSION_MAJOR(v) ((v>>16)&0xff) /**< extract major from packed version */
+-#define VPX_VERSION_MINOR(v) ((v>>8)&0xff) /**< extract minor from packed version */
+-#define VPX_VERSION_PATCH(v) ((v>>0)&0xff) /**< extract patch from packed version */
+-
+- /*!\brief Return the version major number */
+-#define vpx_codec_version_major() ((vpx_codec_version()>>16)&0xff)
+-
+- /*!\brief Return the version minr number */
+-#define vpx_codec_version_minor() ((vpx_codec_version()>>8)&0xff)
+-
+- /*!\brief Return the version patch number */
+-#define vpx_codec_version_patch() ((vpx_codec_version()>>0)&0xff)
+-
+-
+- /*!\brief Return the version information (as a string)
+- *
+- * Returns a printable string containing the full library version number. This may
+- * contain additional text following the three digit version number, as to indicate
+- * release candidates, prerelease versions, etc.
+- *
+- */
+- const char *vpx_codec_version_str(void);
+-
+-
+- /*!\brief Return the version information (as a string)
+- *
+- * Returns a printable "extra string". This is the component of the string returned
+- * by vpx_codec_version_str() following the three digit version number.
+- *
+- */
+- const char *vpx_codec_version_extra_str(void);
+-
+-
+- /*!\brief Return the build configuration
+- *
+- * Returns a printable string containing an encoded version of the build
+- * configuration. This may be useful to vpx support.
+- *
+- */
+- const char *vpx_codec_build_config(void);
+-
+-
+- /*!\brief Return the name for a given interface
+- *
+- * Returns a human readable string for name of the given codec interface.
+- *
+- * \param[in] iface Interface pointer
+- *
+- */
+- const char *vpx_codec_iface_name(vpx_codec_iface_t *iface);
+-
+-
+- /*!\brief Convert error number to printable string
+- *
+- * Returns a human readable string for the last error returned by the
+- * algorithm. The returned error will be one line and will not contain
+- * any newline characters.
+- *
+- *
+- * \param[in] err Error number.
+- *
+- */
+- const char *vpx_codec_err_to_string(vpx_codec_err_t err);
+-
+-
+- /*!\brief Retrieve error synopsis for codec context
+- *
+- * Returns a human readable string for the last error returned by the
+- * algorithm. The returned error will be one line and will not contain
+- * any newline characters.
+- *
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- *
+- */
+- const char *vpx_codec_error(vpx_codec_ctx_t *ctx);
+-
+-
+- /*!\brief Retrieve detailed error information for codec context
+- *
+- * Returns a human readable string providing detailed information about
+- * the last error.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- *
+- * \retval NULL
+- * No detailed information is available.
+- */
+- const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx);
+-
+-
+- /* REQUIRED FUNCTIONS
+- *
+- * The following functions are required to be implemented for all codecs.
+- * They represent the base case functionality expected of all codecs.
+- */
+-
+- /*!\brief Destroy a codec instance
+- *
+- * Destroys a codec context, freeing any associated memory buffers.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- *
+- * \retval #VPX_CODEC_OK
+- * The codec algorithm initialized.
+- * \retval #VPX_CODEC_MEM_ERROR
+- * Memory allocation failed.
+- */
+- vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx);
+-
+-
+- /*!\brief Get the capabilities of an algorithm.
+- *
+- * Retrieves the capabliities bitfield from the algorithm's interface.
+- *
+- * \param[in] iface Pointer to the alogrithm interface
+- *
+- */
+- vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface);
+-
+-
+- /*!\brief Control algorithm
+- *
+- * This function is used to exchange algorithm specific data with the codec
+- * instance. This can be used to implement features specific to a particular
+- * algorithm.
+- *
+- * This wrapper function dispatches the request to the helper function
+- * associated with the given ctrl_id. It tries to call this function
+- * transparantly, but will return #VPX_CODEC_ERROR if the request could not
+- * be dispatched.
+- *
+- * Note that this function should not be used directly. Call the
+- * #vpx_codec_control wrapper macro instead.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] ctrl_id Algorithm specific control identifier
+- *
+- * \retval #VPX_CODEC_OK
+- * The control request was processed.
+- * \retval #VPX_CODEC_ERROR
+- * The control request was not processed.
+- * \retval #VPX_CODEC_INVALID_PARAM
+- * The data was not valid.
+- */
+- vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx,
+- int ctrl_id,
+- ...);
+-#if defined(VPX_DISABLE_CTRL_TYPECHECKS) && VPX_DISABLE_CTRL_TYPECHECKS
+-# define vpx_codec_control(ctx,id,data) vpx_codec_control_(ctx,id,data)
+-# define VPX_CTRL_USE_TYPE(id, typ)
+-# define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ)
+-# define VPX_CTRL_VOID(id, typ)
+-
+-#else
+- /*!\brief vpx_codec_control wrapper macro
+- *
+- * This macro allows for type safe conversions across the variadic parameter
+- * to vpx_codec_control_().
+- *
+- * \internal
+- * It works by dispatching the call to the control function through a wrapper
+- * function named with the id parameter.
+- */
+-# define vpx_codec_control(ctx,id,data) vpx_codec_control_##id(ctx,id,data)\
+- /**<\hideinitializer*/
+-
+-
+- /*!\brief vpx_codec_control type definition macro
+- *
+- * This macro allows for type safe conversions across the variadic parameter
+- * to vpx_codec_control_(). It defines the type of the argument for a given
+- * control identifier.
+- *
+- * \internal
+- * It defines a static function with
+- * the correctly typed arguments as a wrapper to the type-unsafe internal
+- * function.
+- */
+-# define VPX_CTRL_USE_TYPE(id, typ) \
+- static vpx_codec_err_t \
+- vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) UNUSED;\
+- \
+- static vpx_codec_err_t \
+- vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {\
+- return vpx_codec_control_(ctx, ctrl_id, data);\
+- } /**<\hideinitializer*/
+-
+-
+- /*!\brief vpx_codec_control deprecated type definition macro
+- *
+- * Like #VPX_CTRL_USE_TYPE, but indicates that the specified control is
+- * deprecated and should not be used. Consult the documentation for your
+- * codec for more information.
+- *
+- * \internal
+- * It defines a static function with the correctly typed arguments as a
+- * wrapper to the type-unsafe internal function.
+- */
+-# define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
+- DECLSPEC_DEPRECATED static vpx_codec_err_t \
+- vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) DEPRECATED UNUSED;\
+- \
+- DECLSPEC_DEPRECATED static vpx_codec_err_t \
+- vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {\
+- return vpx_codec_control_(ctx, ctrl_id, data);\
+- } /**<\hideinitializer*/
+-
+-
+- /*!\brief vpx_codec_control void type definition macro
+- *
+- * This macro allows for type safe conversions across the variadic parameter
+- * to vpx_codec_control_(). It indicates that a given control identifier takes
+- * no argument.
+- *
+- * \internal
+- * It defines a static function without a data argument as a wrapper to the
+- * type-unsafe internal function.
+- */
+-# define VPX_CTRL_VOID(id) \
+- static vpx_codec_err_t \
+- vpx_codec_control_##id(vpx_codec_ctx_t*, int) UNUSED;\
+- \
+- static vpx_codec_err_t \
+- vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id) {\
+- return vpx_codec_control_(ctx, ctrl_id);\
+- } /**<\hideinitializer*/
+-
+-
+-#endif
+-
+-
+- /*!\defgroup cap_xma External Memory Allocation Functions
+- *
+- * The following functions are required to be implemented for all codecs
+- * that advertise the VPX_CODEC_CAP_XMA capability. Calling these functions
+- * for codecs that don't advertise this capability will result in an error
+- * code being returned, usually VPX_CODEC_INCAPABLE
+- * @{
+- */
+-
+-
+- /*!\brief Memory Map Entry
+- *
+- * This structure is used to contain the properties of a memory segment. It
+- * is populated by the codec in the request phase, and by the calling
+- * application once the requested allocation has been performed.
+- */
+- typedef struct vpx_codec_mmap
+- {
+- /*
+- * The following members are set by the codec when requesting a segment
+- */
+- unsigned int id; /**< identifier for the segment's contents */
+- unsigned long sz; /**< size of the segment, in bytes */
+- unsigned int align; /**< required alignment of the segment, in bytes */
+- unsigned int flags; /**< bitfield containing segment properties */
+-#define VPX_CODEC_MEM_ZERO 0x1 /**< Segment must be zeroed by allocation */
+-#define VPX_CODEC_MEM_WRONLY 0x2 /**< Segment need not be readable */
+-#define VPX_CODEC_MEM_FAST 0x4 /**< Place in fast memory, if available */
+-
+- /* The following members are to be filled in by the allocation function */
+- void *base; /**< pointer to the allocated segment */
+- void (*dtor)(struct vpx_codec_mmap *map); /**< destructor to call */
+- void *priv; /**< allocator private storage */
+- } vpx_codec_mmap_t; /**< alias for struct vpx_codec_mmap */
+-
+-
+- /*!\brief Iterate over the list of segments to allocate.
+- *
+- * Iterates over a list of the segments to allocate. The iterator storage
+- * should be initialized to NULL to start the iteration. Iteration is complete
+- * when this function returns VPX_CODEC_LIST_END. The amount of memory needed to
+- * allocate is dependant upon the size of the encoded stream. In cases where the
+- * stream is not available at allocation time, a fixed size must be requested.
+- * The codec will not be able to operate on streams larger than the size used at
+- * allocation time.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- * \param[out] mmap Pointer to the memory map entry to populate.
+- * \param[in,out] iter Iterator storage, initialized to NULL
+- *
+- * \retval #VPX_CODEC_OK
+- * The memory map entry was populated.
+- * \retval #VPX_CODEC_ERROR
+- * Codec does not support XMA mode.
+- * \retval #VPX_CODEC_MEM_ERROR
+- * Unable to determine segment size from stream info.
+- */
+- vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx,
+- vpx_codec_mmap_t *mmap,
+- vpx_codec_iter_t *iter);
+-
+-
+- /*!\brief Identify allocated segments to codec instance
+- *
+- * Stores a list of allocated segments in the codec. Segments \ref MUST be
+- * passed in the order they are read from vpx_codec_get_mem_map(), but may be
+- * passed in groups of any size. Segments \ref MUST be set only once. The
+- * allocation function \ref MUST ensure that the vpx_codec_mmap_t::base member
+- * is non-NULL. If the segment requires cleanup handling (eg, calling free()
+- * or close()) then the vpx_codec_mmap_t::dtor member \ref MUST be populated.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- * \param[in] mmaps Pointer to the first memory map entry in the list.
+- * \param[in] num_maps Number of entries being set at this time
+- *
+- * \retval #VPX_CODEC_OK
+- * The segment was stored in the codec context.
+- * \retval #VPX_CODEC_INCAPABLE
+- * Codec does not support XMA mode.
+- * \retval #VPX_CODEC_MEM_ERROR
+- * Segment base address was not set, or segment was already stored.
+-
+- */
+- vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx,
+- vpx_codec_mmap_t *mmaps,
+- unsigned int num_maps);
+-
+- /*!@} - end defgroup cap_xma*/
+- /*!@} - end defgroup codec*/
+-
+-
+-#endif
+-#ifdef __cplusplus
+-}
+-#endif
+diff --git a/vpx_codec/vpx_codec.mk b/vpx_codec/vpx_codec.mk
+deleted file mode 100644
+index 75fbeea..0000000
+--- a/vpx_codec/vpx_codec.mk
++++ /dev/null
+@@ -1,26 +0,0 @@
+-##
+-## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+-##
+-## Use of this source code is governed by a BSD-style license and patent
+-## grant that can be found in the LICENSE file in the root of the source
+-## tree. All contributing project authors may be found in the AUTHORS
+-## file in the root of the source tree.
+-##
+-
+-
+-API_EXPORTS += exports
+-
+-API_SRCS-yes += internal/vpx_codec_internal.h
+-API_SRCS-yes += vpx_codec.h
+-API_SRCS-yes += vpx_codec.mk
+-API_SRCS-yes += vpx_codec_impl_top.h
+-API_SRCS-yes += vpx_codec_impl_bottom.h
+-API_SRCS-yes += vpx_decoder.h
+-API_SRCS-yes += vpx_decoder_compat.h
+-API_SRCS-yes += vpx_encoder.h
+-API_SRCS-yes += vpx_image.h
+-API_SRCS-yes += src/vpx_codec.c
+-API_SRCS-yes += src/vpx_decoder.c
+-API_SRCS-yes += src/vpx_decoder_compat.c
+-API_SRCS-yes += src/vpx_image.c
+-API_SRCS-yes += src/vpx_encoder.c
+diff --git a/vpx_codec/vpx_codec_impl_bottom.h b/vpx_codec/vpx_codec_impl_bottom.h
+deleted file mode 100644
+index c52654c..0000000
+--- a/vpx_codec/vpx_codec_impl_bottom.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*
+- * This file is to be included at the bottom of the header files defining the
+- * interface to individual codecs and contains matching blocks to those defined
+- * in vpx_codec_impl_top.h
+- */
+-#ifdef __cplusplus
+-}
+-#endif
+diff --git a/vpx_codec/vpx_codec_impl_top.h b/vpx_codec/vpx_codec_impl_top.h
+deleted file mode 100644
+index f73809a..0000000
+--- a/vpx_codec/vpx_codec_impl_top.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*
+- * This file is to be included at the top of the header files defining the
+- * interface to individual codecs and contains various workarounds common
+- * to all codec implementations.
+- */
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+diff --git a/vpx_codec/vpx_decoder.h b/vpx_codec/vpx_decoder.h
+deleted file mode 100644
+index 5e4968d..0000000
+--- a/vpx_codec/vpx_decoder.h
++++ /dev/null
+@@ -1,316 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\defgroup decoder Decoder Algorithm Interface
+- * \ingroup codec
+- * This abstraction allows applications using this decoder to easily support
+- * multiple video formats with minimal code duplication. This section describes
+- * the interface common to all decoders.
+- * @{
+- */
+-
+-/*!\file vpx_decoder.h
+- * \brief Describes the decoder algorithm interface to applications.
+- *
+- * This file describes the interface between an application and a
+- * video decoder algorithm.
+- *
+- */
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#ifndef VPX_DECODER_H
+-#define VPX_DECODER_H
+-#include "vpx_codec.h"
+-
+- /*!\brief Current ABI version number
+- *
+- * \internal
+- * If this file is altered in any way that changes the ABI, this value
+- * must be bumped. Examples include, but are not limited to, changing
+- * types, removing or reassigning enums, adding/removing/rearranging
+- * fields to structures
+- */
+-#define VPX_DECODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
+-
+- /*! \brief Decoder capabilities bitfield
+- *
+- * Each decoder advertises the capabilities it supports as part of its
+- * ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
+- * or functionality, and are not required to be supported by a decoder.
+- *
+- * The available flags are specifiedby VPX_CODEC_CAP_* defines.
+- */
+-#define VPX_CODEC_CAP_PUT_SLICE 0x10000 /**< Will issue put_slice callbacks */
+-#define VPX_CODEC_CAP_PUT_FRAME 0x20000 /**< Will issue put_frame callbacks */
+-#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */
+-
+- /*! \brief Initialization-time Feature Enabling
+- *
+- * Certain codec features must be known at initialization time, to allow for
+- * proper memory allocation.
+- *
+- * The available flags are specified by VPX_CODEC_USE_* defines.
+- */
+-#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */
+-
+- /*!\brief Stream properties
+- *
+- * This structure is used to query or set properties of the decoded
+- * stream. Algorithms may extend this structure with data specific
+- * to their bitstream by setting the sz member appropriately.
+- */
+- typedef struct
+- {
+- unsigned int sz; /**< Size of this structure */
+- unsigned int w; /**< Width (or 0 for unknown/default) */
+- unsigned int h; /**< Height (or 0 for unknown/default) */
+- unsigned int is_kf; /**< Current frame is a keyframe */
+- } vpx_codec_stream_info_t;
+-
+- /* REQUIRED FUNCTIONS
+- *
+- * The following functions are required to be implemented for all decoders.
+- * They represent the base case functionality expected of all decoders.
+- */
+-
+-
+- /*!\brief Initialization Configurations
+- *
+- * This structure is used to pass init time configuration options to the
+- * decoder.
+- */
+- typedef struct vpx_codec_dec_cfg
+- {
+- unsigned int threads; /**< Maximum number of threads to use, default 1 */
+- unsigned int w; /**< Width */
+- unsigned int h; /**< Height */
+- } vpx_codec_dec_cfg_t; /**< alias for struct vpx_codec_dec_cfg */
+-
+-
+- /*!\brief Initialize a decoder instance
+- *
+- * Initializes a decoder context using the given interface. Applications
+- * should call the vpx_codec_dec_init convenience macro instead of this
+- * function directly, to ensure that the ABI version number parameter
+- * is properly initialized.
+- *
+- * In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
+- * parameter), the storage pointed to by the cfg parameter must be
+- * kept readable and stable until all memory maps have been set.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- * \param[in] iface Pointer to the alogrithm interface to use.
+- * \param[in] cfg Configuration to use, if known. May be NULL.
+- * \param[in] flags Bitfield of VPX_CODEC_USE_* flags
+- * \param[in] ver ABI version number. Must be set to
+- * VPX_DECODER_ABI_VERSION
+- * \retval #VPX_CODEC_OK
+- * The decoder algorithm initialized.
+- * \retval #VPX_CODEC_MEM_ERROR
+- * Memory allocation failed.
+- */
+- vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx,
+- vpx_codec_iface_t *iface,
+- vpx_codec_dec_cfg_t *cfg,
+- vpx_codec_flags_t flags,
+- int ver);
+-
+- /*!\brief Convenience macro for vpx_codec_dec_init_ver()
+- *
+- * Ensures the ABI version parameter is properly set.
+- */
+-#define vpx_codec_dec_init(ctx, iface, cfg, flags) \
+- vpx_codec_dec_init_ver(ctx, iface, cfg, flags, VPX_DECODER_ABI_VERSION)
+-
+-
+- /*!\brief Parse stream info from a buffer
+- *
+- * Performs high level parsing of the bitstream. Construction of a decoder
+- * context is not necessary. Can be used to determine if the bitstream is
+- * of the proper format, and to extract information from the stream.
+- *
+- * \param[in] iface Pointer to the alogrithm interface
+- * \param[in] data Pointer to a block of data to parse
+- * \param[in] data_sz Size of the data buffer
+- * \param[in,out] si Pointer to stream info to update. The size member
+- * \ref MUST be properly initialized, but \ref MAY be
+- * clobbered by the algorithm. This parameter \ref MAY
+- * be NULL.
+- *
+- * \retval #VPX_CODEC_OK
+- * Bitstream is parsable and stream information updated
+- */
+- vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface,
+- const uint8_t *data,
+- unsigned int data_sz,
+- vpx_codec_stream_info_t *si);
+-
+-
+- /*!\brief Return information about the current stream.
+- *
+- * Returns information about the stream that has been parsed during decoding.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in,out] si Pointer to stream info to update. The size member
+- * \ref MUST be properly initialized, but \ref MAY be
+- * clobbered by the algorithm. This parameter \ref MAY
+- * be NULL.
+- *
+- * \retval #VPX_CODEC_OK
+- * Bitstream is parsable and stream information updated
+- */
+- vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx,
+- vpx_codec_stream_info_t *si);
+-
+-
+- /*!\brief Decode data
+- *
+- * Processes a buffer of coded data. If the processing results in a new
+- * decoded frame becoming available, PUT_SLICE and PUT_FRAME events may be
+- * generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode
+- * time stamp) order. Frames produced will always be in PTS (presentation
+- * time stamp) order.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] data Pointer to this block of new coded data. If
+- * NULL, a VPX_CODEC_CB_PUT_FRAME event is posted
+- * for the previously decoded frame.
+- * \param[in] data_sz Size of the coded data, in bytes.
+- * \param[in] user_priv Application specific data to associate with
+- * this frame.
+- * \param[in] deadline Soft deadline the decoder should attempt to meet,
+- * in us. Set to zero for unlimited.
+- *
+- * \return Returns #VPX_CODEC_OK if the coded data was processed completely
+- * and future pictures can be decoded without error. Otherwise,
+- * see the descriptions of the other error codes in ::vpx_codec_err_t
+- * for recoverability capabilities.
+- */
+- vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx,
+- const uint8_t *data,
+- unsigned int data_sz,
+- void *user_priv,
+- long deadline);
+-
+-
+- /*!\brief Decoded frames iterator
+- *
+- * Iterates over a list of the frames available for display. The iterator
+- * storage should be initialized to NULL to start the iteration. Iteration is
+- * complete when this function returns NULL.
+- *
+- * The list of available frames becomes valid upon completion of the
+- * vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in,out] iter Iterator storage, initialized to NULL
+- *
+- * \return Returns a pointer to an image, if one is ready for display. Frames
+- * produced will always be in PTS (presentation time stamp) order.
+- */
+- vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx,
+- vpx_codec_iter_t *iter);
+-
+-
+- /*!\defgroup cap_put_frame Frame-Based Decoding Functions
+- *
+- * The following functions are required to be implemented for all decoders
+- * that advertise the VPX_CODEC_CAP_PUT_FRAME capability. Calling these functions
+- * for codecs that don't advertise this capability will result in an error
+- * code being returned, usually VPX_CODEC_ERROR
+- * @{
+- */
+-
+- /*!\brief put frame callback prototype
+- *
+- * This callback is invoked by the decoder to notify the application of
+- * the availability of decoded image data.
+- */
+- typedef void (*vpx_codec_put_frame_cb_fn_t)(void *user_priv,
+- const vpx_image_t *img);
+-
+-
+- /*!\brief Register for notification of frame completion.
+- *
+- * Registers a given function to be called when a decoded frame is
+- * available.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] cb Pointer to the callback function
+- * \param[in] user_priv User's private data
+- *
+- * \retval #VPX_CODEC_OK
+- * Callback successfully registered.
+- * \retval #VPX_CODEC_ERROR
+- * Decoder context not initialized, or algorithm not capable of
+- * posting slice completion.
+- */
+- vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx,
+- vpx_codec_put_frame_cb_fn_t cb,
+- void *user_priv);
+-
+-
+- /*!@} - end defgroup cap_put_frame */
+-
+- /*!\defgroup cap_put_slice Slice-Based Decoding Functions
+- *
+- * The following functions are required to be implemented for all decoders
+- * that advertise the VPX_CODEC_CAP_PUT_SLICE capability. Calling these functions
+- * for codecs that don't advertise this capability will result in an error
+- * code being returned, usually VPX_CODEC_ERROR
+- * @{
+- */
+-
+- /*!\brief put slice callback prototype
+- *
+- * This callback is invoked by the decoder to notify the application of
+- * the availability of partially decoded image data. The
+- */
+- typedef void (*vpx_codec_put_slice_cb_fn_t)(void *user_priv,
+- const vpx_image_t *img,
+- const vpx_image_rect_t *valid,
+- const vpx_image_rect_t *update);
+-
+-
+- /*!\brief Register for notification of slice completion.
+- *
+- * Registers a given function to be called when a decoded slice is
+- * available.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] cb Pointer to the callback function
+- * \param[in] user_priv User's private data
+- *
+- * \retval #VPX_CODEC_OK
+- * Callback successfully registered.
+- * \retval #VPX_CODEC_ERROR
+- * Decoder context not initialized, or algorithm not capable of
+- * posting slice completion.
+- */
+- vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx,
+- vpx_codec_put_slice_cb_fn_t cb,
+- void *user_priv);
+-
+-
+- /*!@} - end defgroup cap_put_slice*/
+-
+- /*!@} - end defgroup decoder*/
+-
+-#endif
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
+-#include "vpx_decoder_compat.h"
+-#endif
+diff --git a/vpx_codec/vpx_decoder_compat.h b/vpx_codec/vpx_decoder_compat.h
+deleted file mode 100644
+index 25bb5eb..0000000
+--- a/vpx_codec/vpx_decoder_compat.h
++++ /dev/null
+@@ -1,586 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\defgroup decoder Common Decoder Algorithm Interface
+- * This abstraction allows applications using this decoder to easily support
+- * multiple video formats with minimal code duplication. This section describes
+- * the interface common to all codecs.
+- * @{
+- */
+-
+-/*!\file vpx_decoder_compat.h
+- * \brief Provides a compatibility layer between version 1 and 2 of this API.
+- *
+- * This interface has been deprecated. Only existing code should make use
+- * of this interface, and therefore, it is only thinly documented. Existing
+- * code should be ported to the vpx_codec_* API.
+- */
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#ifndef VPX_DECODER_COMPAT_H
+-#define VPX_DECODER_COMPAT_H
+-
+- /*!\brief Decoder algorithm return codes */
+- typedef enum {
+- /*!\brief Operation completed without error */
+- VPX_DEC_OK = VPX_CODEC_OK,
+-
+- /*!\brief Unspecified error */
+- VPX_DEC_ERROR = VPX_CODEC_ERROR,
+-
+- /*!\brief Memory operation failed */
+- VPX_DEC_MEM_ERROR = VPX_CODEC_MEM_ERROR,
+-
+- /*!\brief ABI version mismatch */
+- VPX_DEC_ABI_MISMATCH = VPX_CODEC_ABI_MISMATCH,
+-
+- /*!\brief The given bitstream is not supported.
+- *
+- * The bitstream was unable to be parsed at the highest level. The decoder
+- * is unable to proceed. This error \ref SHOULD be treated as fatal to the
+- * stream. */
+- VPX_DEC_UNSUP_BITSTREAM = VPX_CODEC_UNSUP_BITSTREAM,
+-
+- /*!\brief Encoded bitstream uses an unsupported feature
+- *
+- * The decoder does not implement a feature required by the encoder. This
+- * return code should only be used for features that prevent future
+- * pictures from being properly decoded. This error \ref MAY be treated as
+- * fatal to the stream or \ref MAY be treated as fatal to the current GOP.
+- */
+- VPX_DEC_UNSUP_FEATURE = VPX_CODEC_UNSUP_FEATURE,
+-
+- /*!\brief The coded data for this stream is corrupt or incomplete
+- *
+- * There was a problem decoding the current frame. This return code
+- * should only be used for failures that prevent future pictures from
+- * being properly decoded. This error \ref MAY be treated as fatal to the
+- * stream or \ref MAY be treated as fatal to the current GOP. If decoding
+- * is continued for the current GOP, artifacts may be present.
+- */
+- VPX_DEC_CORRUPT_FRAME = VPX_CODEC_CORRUPT_FRAME,
+-
+- /*!\brief An application-supplied parameter is not valid.
+- *
+- */
+- VPX_DEC_INVALID_PARAM = VPX_CODEC_INVALID_PARAM,
+-
+- /*!\brief An iterator reached the end of list.
+- *
+- */
+- VPX_DEC_LIST_END = VPX_CODEC_LIST_END,
+-
+- }
+- vpx_dec_err_t;
+-
+- /*! \brief Decoder capabilities bitfield
+- *
+- * Each decoder advertises the capabilities it supports as part of its
+- * ::vpx_dec_iface_t interface structure. Capabilities are extra interfaces
+- * or functionality, and are not required to be supported by a decoder.
+- *
+- * The available flags are specifiedby VPX_DEC_CAP_* defines.
+- */
+- typedef int vpx_dec_caps_t;
+-#define VPX_DEC_CAP_PUT_SLICE 0x0001 /**< Will issue put_slice callbacks */
+-#define VPX_DEC_CAP_PUT_FRAME 0x0002 /**< Will issue put_frame callbacks */
+-#define VPX_DEC_CAP_XMA 0x0004 /**< Supports e_xternal Memory Allocation */
+-
+- /*!\brief Stream properties
+- *
+- * This structure is used to query or set properties of the decoded
+- * stream. Algorithms may extend this structure with data specific
+- * to their bitstream by setting the sz member appropriately.
+- */
+-#if 1
+- typedef vpx_codec_stream_info_t vpx_dec_stream_info_t;
+-#else
+- typedef struct
+- {
+- unsigned int sz; /**< Size of this structure */
+- unsigned int w; /**< Width (or 0 for unknown/default) */
+- unsigned int h; /**< Height (or 0 for unknown/default) */
+- unsigned int is_kf; /**< Current frame is a keyframe */
+- } vpx_dec_stream_info_t;
+-#endif
+-
+-
+- /*!\brief Decoder interface structure.
+- *
+- * Contains function pointers and other data private to the decoder
+- * implementation. This structure is opaque to the application.
+- */
+- typedef const struct vpx_codec_iface vpx_dec_iface_t;
+- typedef struct vpx_codec_priv vpx_dec_priv_t;
+-
+- /*!\brief Iterator
+- *
+- * Opaque storage used for iterating over lists.
+- */
+- typedef vpx_codec_iter_t vpx_dec_iter_t;
+-
+- /*!\brief Decoder context structure
+- *
+- * All decoders \ref MUST support this context structure fully. In general,
+- * this data should be considered private to the decoder algorithm, and
+- * not be manipulated or examined by the calling application. Applications
+- * may reference the 'name' member to get a printable description of the
+- * algorithm.
+- */
+-#if 1
+- typedef vpx_codec_ctx_t vpx_dec_ctx_t;
+-#else
+- typedef struct
+- {
+- const char *name; /**< Printable interface name */
+- vpx_dec_iface_t *iface; /**< Interface pointers */
+- vpx_dec_err_t err; /**< Last returned error */
+- vpx_dec_priv_t *priv; /**< Algorithm private storage */
+- } vpx_dec_ctx_t;
+-#endif
+-
+-
+- /*!\brief Return the build configuration
+- *
+- * Returns a printable string containing an encoded version of the build
+- * configuration. This may be useful to vpx support.
+- *
+- */
+- const char *vpx_dec_build_config(void) DEPRECATED;
+-
+- /*!\brief Return the name for a given interface
+- *
+- * Returns a human readable string for name of the given decoder interface.
+- *
+- * \param[in] iface Interface pointer
+- *
+- */
+- const char *vpx_dec_iface_name(vpx_dec_iface_t *iface) DEPRECATED;
+-
+-
+- /*!\brief Convert error number to printable string
+- *
+- * Returns a human readable string for the last error returned by the
+- * algorithm. The returned error will be one line and will not contain
+- * any newline characters.
+- *
+- *
+- * \param[in] err Error number.
+- *
+- */
+- const char *vpx_dec_err_to_string(vpx_dec_err_t err) DEPRECATED;
+-
+-
+- /*!\brief Retrieve error synopsis for decoder context
+- *
+- * Returns a human readable string for the last error returned by the
+- * algorithm. The returned error will be one line and will not contain
+- * any newline characters.
+- *
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- *
+- */
+- const char *vpx_dec_error(vpx_dec_ctx_t *ctx) DEPRECATED;
+-
+-
+- /*!\brief Retrieve detailed error information for decoder context
+- *
+- * Returns a human readable string providing detailed information about
+- * the last error.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- *
+- * \retval NULL
+- * No detailed information is available.
+- */
+- const char *vpx_dec_error_detail(vpx_dec_ctx_t *ctx) DEPRECATED;
+-
+-
+- /* REQUIRED FUNCTIONS
+- *
+- * The following functions are required to be implemented for all decoders.
+- * They represent the base case functionality expected of all decoders.
+- */
+-
+-
+- /*!\brief Initialize a decoder instance
+- *
+- * Initializes a decoder context using the given interface. Applications
+- * should call the vpx_dec_init convenience macro instead of this
+- * function directly, to ensure that the ABI version number parameter
+- * is properly initialized.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- * \param[in] iface Pointer to the alogrithm interface to use.
+- * \param[in] ver ABI version number. Must be set to
+- * VPX_DECODER_ABI_VERSION
+- * \retval #VPX_DEC_OK
+- * The decoder algorithm initialized.
+- * \retval #VPX_DEC_MEM_ERROR
+- * Memory allocation failed.
+- */
+- vpx_dec_err_t vpx_dec_init_ver(vpx_dec_ctx_t *ctx,
+- vpx_dec_iface_t *iface,
+- int ver) DEPRECATED;
+-#define vpx_dec_init(ctx, iface) \
+- vpx_dec_init_ver(ctx, iface, VPX_DECODER_ABI_VERSION)
+-
+-
+- /*!\brief Destroy a decoder instance
+- *
+- * Destroys a decoder context, freeing any associated memory buffers.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- *
+- * \retval #VPX_DEC_OK
+- * The decoder algorithm initialized.
+- * \retval #VPX_DEC_MEM_ERROR
+- * Memory allocation failed.
+- */
+- vpx_dec_err_t vpx_dec_destroy(vpx_dec_ctx_t *ctx) DEPRECATED;
+-
+-
+- /*!\brief Get the capabilities of an algorithm.
+- *
+- * Retrieves the capabliities bitfield from the algorithm's interface.
+- *
+- * \param[in] iface Pointer to the alogrithm interface
+- *
+- */
+- vpx_dec_caps_t vpx_dec_get_caps(vpx_dec_iface_t *iface) DEPRECATED;
+-
+-
+- /*!\brief Parse stream info from a buffer
+- *
+- * Performs high level parsing of the bitstream. Construction of a decoder
+- * context is not necessary. Can be used to determine if the bitstream is
+- * of the proper format, and to extract information from the stream.
+- *
+- * \param[in] iface Pointer to the alogrithm interface
+- * \param[in] data Pointer to a block of data to parse
+- * \param[in] data_sz Size of the data buffer
+- * \param[in,out] si Pointer to stream info to update. The size member
+- * \ref MUST be properly initialized, but \ref MAY be
+- * clobbered by the algorithm. This parameter \ref MAY
+- * be NULL.
+- *
+- * \retval #VPX_DEC_OK
+- * Bitstream is parsable and stream information updated
+- */
+- vpx_dec_err_t vpx_dec_peek_stream_info(vpx_dec_iface_t *iface,
+- const uint8_t *data,
+- unsigned int data_sz,
+- vpx_dec_stream_info_t *si) DEPRECATED;
+-
+-
+- /*!\brief Return information about the current stream.
+- *
+- * Returns information about the stream that has been parsed during decoding.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in,out] si Pointer to stream info to update. The size member
+- * \ref MUST be properly initialized, but \ref MAY be
+- * clobbered by the algorithm. This parameter \ref MAY
+- * be NULL.
+- *
+- * \retval #VPX_DEC_OK
+- * Bitstream is parsable and stream information updated
+- */
+- vpx_dec_err_t vpx_dec_get_stream_info(vpx_dec_ctx_t *ctx,
+- vpx_dec_stream_info_t *si) DEPRECATED;
+-
+-
+- /*!\brief Control algorithm
+- *
+- * This function is used to exchange algorithm specific data with the decoder
+- * instance. This can be used to implement features specific to a particular
+- * algorithm.
+- *
+- * This wrapper function dispatches the request to the helper function
+- * associated with the given ctrl_id. It tries to call this function
+- * transparantly, but will return #VPX_DEC_ERROR if the request could not
+- * be dispatched.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] ctrl_id Algorithm specific control identifier
+- * \param[in,out] data Data to exchange with algorithm instance.
+- *
+- * \retval #VPX_DEC_OK
+- * The control request was processed.
+- * \retval #VPX_DEC_ERROR
+- * The control request was not processed.
+- * \retval #VPX_DEC_INVALID_PARAM
+- * The data was not valid.
+- */
+- vpx_dec_err_t vpx_dec_control(vpx_dec_ctx_t *ctx,
+- int ctrl_id,
+- void *data) DEPRECATED;
+-
+- /*!\brief Decode data
+- *
+- * Processes a buffer of coded data. If the processing results in a new
+- * decoded frame becoming available, #VPX_DEC_CB_PUT_SLICE and
+- * #VPX_DEC_CB_PUT_FRAME events may be generated, as appropriate. Encoded data
+- * \ref MUST be passed in DTS (decode time stamp) order. Frames produced will
+- * always be in PTS (presentation time stamp) order.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] data Pointer to this block of new coded data. If
+- * NULL, a VPX_DEC_CB_PUT_FRAME event is posted
+- * for the previously decoded frame.
+- * \param[in] data_sz Size of the coded data, in bytes.
+- * \param[in] user_priv Application specific data to associate with
+- * this frame.
+- * \param[in] rel_pts PTS relative to the previous frame, in us. If
+- * unknown or unavailable, set to zero.
+- *
+- * \return Returns #VPX_DEC_OK if the coded data was processed completely
+- * and future pictures can be decoded without error. Otherwise,
+- * see the descriptions of the other error codes in ::vpx_dec_err_t
+- * for recoverability capabilities.
+- */
+- vpx_dec_err_t vpx_dec_decode(vpx_dec_ctx_t *ctx,
+- uint8_t *data,
+- unsigned int data_sz,
+- void *user_priv,
+- int rel_pts) DEPRECATED;
+-
+-
+- /*!\brief Decoded frames iterator
+- *
+- * Iterates over a list of the frames available for display. The iterator
+- * storage should be initialized to NULL to start the iteration. Iteration is
+- * complete when this function returns NULL.
+- *
+- * The list of available frames becomes valid upon completion of the
+- * vpx_dec_decode call, and remains valid until the next call to vpx_dec_decode.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in out] iter Iterator storage, initialized to NULL
+- *
+- * \return Returns a pointer to an image, if one is ready for display. Frames
+- * produced will always be in PTS (presentation time stamp) order.
+- */
+- vpx_image_t *vpx_dec_get_frame(vpx_dec_ctx_t *ctx,
+- vpx_dec_iter_t *iter) DEPRECATED;
+-
+-
+- /*!\defgroup cap_put_frame Frame-Based Decoding Functions
+- *
+- * The following functions are required to be implemented for all decoders
+- * that advertise the VPX_DEC_CAP_PUT_FRAME capability. Calling these functions
+- * for codecs that don't advertise this capability will result in an error
+- * code being returned, usually VPX_DEC_ERROR
+- * @{
+- */
+-
+- /*!\brief put frame callback prototype
+- *
+- * This callback is invoked by the decoder to notify the application of
+- * the availability of decoded image data.
+- */
+- typedef void (*vpx_dec_put_frame_cb_fn_t)(void *user_priv,
+- const vpx_image_t *img);
+-
+-
+- /*!\brief Register for notification of frame completion.
+- *
+- * Registers a given function to be called when a decoded frame is
+- * available.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] cb Pointer to the callback function
+- * \param[in] user_priv User's private data
+- *
+- * \retval #VPX_DEC_OK
+- * Callback successfully registered.
+- * \retval #VPX_DEC_ERROR
+- * Decoder context not initialized, or algorithm not capable of
+- * posting slice completion.
+- */
+- vpx_dec_err_t vpx_dec_register_put_frame_cb(vpx_dec_ctx_t *ctx,
+- vpx_dec_put_frame_cb_fn_t cb,
+- void *user_priv) DEPRECATED;
+-
+-
+- /*!@} - end defgroup cap_put_frame */
+-
+- /*!\defgroup cap_put_slice Slice-Based Decoding Functions
+- *
+- * The following functions are required to be implemented for all decoders
+- * that advertise the VPX_DEC_CAP_PUT_SLICE capability. Calling these functions
+- * for codecs that don't advertise this capability will result in an error
+- * code being returned, usually VPX_DEC_ERROR
+- * @{
+- */
+-
+- /*!\brief put slice callback prototype
+- *
+- * This callback is invoked by the decoder to notify the application of
+- * the availability of partially decoded image data. The
+- */
+- typedef void (*vpx_dec_put_slice_cb_fn_t)(void *user_priv,
+- const vpx_image_t *img,
+- const vpx_image_rect_t *valid,
+- const vpx_image_rect_t *update);
+-
+-
+- /*!\brief Register for notification of slice completion.
+- *
+- * Registers a given function to be called when a decoded slice is
+- * available.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] cb Pointer to the callback function
+- * \param[in] user_priv User's private data
+- *
+- * \retval #VPX_DEC_OK
+- * Callback successfully registered.
+- * \retval #VPX_DEC_ERROR
+- * Decoder context not initialized, or algorithm not capable of
+- * posting slice completion.
+- */
+- vpx_dec_err_t vpx_dec_register_put_slice_cb(vpx_dec_ctx_t *ctx,
+- vpx_dec_put_slice_cb_fn_t cb,
+- void *user_priv) DEPRECATED;
+-
+-
+- /*!@} - end defgroup cap_put_slice*/
+-
+- /*!\defgroup cap_xma External Memory Allocation Functions
+- *
+- * The following functions are required to be implemented for all decoders
+- * that advertise the VPX_DEC_CAP_XMA capability. Calling these functions
+- * for codecs that don't advertise this capability will result in an error
+- * code being returned, usually VPX_DEC_ERROR
+- * @{
+- */
+-
+- /*!\brief Memory Map Entry
+- *
+- * This structure is used to contain the properties of a memory segment. It
+- * is populated by the decoder in the request phase, and by the calling
+- * application once the requested allocation has been performed.
+- */
+-#if 1
+-#define VPX_DEC_MEM_ZERO 0x1 /**< Segment must be zeroed by allocation */
+-#define VPX_DEC_MEM_WRONLY 0x2 /**< Segment need not be readable */
+-#define VPX_DEC_MEM_FAST 0x4 /**< Place in fast memory, if available */
+- typedef struct vpx_codec_mmap vpx_dec_mmap_t;
+-#else
+- typedef struct vpx_dec_mmap
+- {
+- /*
+- * The following members are set by the codec when requesting a segment
+- */
+- unsigned int id; /**< identifier for the segment's contents */
+- unsigned long sz; /**< size of the segment, in bytes */
+- unsigned int align; /**< required alignment of the segment, in bytes */
+- unsigned int flags; /**< bitfield containing segment properties */
+-#define VPX_DEC_MEM_ZERO 0x1 /**< Segment must be zeroed by allocation */
+-#define VPX_DEC_MEM_WRONLY 0x2 /**< Segment need not be readable */
+-#define VPX_DEC_MEM_FAST 0x4 /**< Place in fast memory, if available */
+-
+- /* The following members are to be filled in by the allocation function */
+- void *base; /**< pointer to the allocated segment */
+- void (*dtor)(struct vpx_dec_mmap *map); /**< destructor to call */
+- void *priv; /**< allocator private storage */
+- } vpx_dec_mmap_t;
+-#endif
+-
+- /*!\brief Initialize a decoder instance in external allocation mode
+- *
+- * Initializes a decoder context using the given interface. Applications
+- * should call the vpx_dec_xma_init convenience macro instead of this
+- * function directly, to ensure that the ABI version number parameter
+- * is properly initialized.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- * \param[in] iface Pointer to the alogrithm interface to use.
+- * \param[in] ver ABI version number. Must be set to
+- * VPX_DECODER_ABI_VERSION
+- * \retval #VPX_DEC_OK
+- * The decoder algorithm initialized.
+- * \retval #VPX_DEC_ERROR
+- * Decoder does not support XMA mode.
+- */
+- vpx_dec_err_t vpx_dec_xma_init_ver(vpx_dec_ctx_t *ctx,
+- vpx_dec_iface_t *iface,
+- int ver) DEPRECATED;
+-#define vpx_dec_xma_init(ctx, iface) \
+- vpx_dec_xma_init_ver(ctx, iface, VPX_DECODER_ABI_VERSION)
+-
+-
+- /*!\brief Iterate over the list of segments to allocate.
+- *
+- * Iterates over a list of the segments to allocate. The iterator storage
+- * should be initialized to NULL to start the iteration. Iteration is complete
+- * when this function returns VPX_DEC_LIST_END. The amount of memory needed to
+- * allocate is dependant upon the size of the encoded stream. This means that
+- * the stream info structure must be known at allocation time. It can be
+- * populated with the vpx_dec_peek_stream_info() function. In cases where the
+- * stream to be decoded is not available at allocation time, a fixed size must
+- * be requested. The decoder will not be able to decode streams larger than
+- * the size used at allocation time.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- * \param[out] mmap Pointer to the memory map entry to populate.
+- * \param[in] si Pointer to the stream info.
+- * \param[in out] iter Iterator storage, initialized to NULL
+- *
+- * \retval #VPX_DEC_OK
+- * The memory map entry was populated.
+- * \retval #VPX_DEC_ERROR
+- * Decoder does not support XMA mode.
+- * \retval #VPX_DEC_MEM_ERROR
+- * Unable to determine segment size from stream info.
+- */
+- vpx_dec_err_t vpx_dec_get_mem_map(vpx_dec_ctx_t *ctx,
+- vpx_dec_mmap_t *mmap,
+- const vpx_dec_stream_info_t *si,
+- vpx_dec_iter_t *iter) DEPRECATED;
+-
+-
+- /*!\brief Identify allocated segments to decoder instance
+- *
+- * Stores a list of allocated segments in the decoder. Segments \ref MUST be
+- * passed in the order they are read from vpx_dec_get_mem_map(), but may be
+- * passed in groups of any size. Segments \ref MUST be set only once. The
+- * allocation function \ref MUST ensure that the vpx_dec_mmap_t::base member
+- * is non-NULL. If the segment requires cleanup handling (eg, calling free()
+- * or close()) then the vpx_dec_mmap_t::dtor member \ref MUST be populated.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- * \param[in] mmaps Pointer to the first memory map entry in the list.
+- * \param[in] num_maps Number of entries being set at this time
+- *
+- * \retval #VPX_DEC_OK
+- * The segment was stored in the decoder context.
+- * \retval #VPX_DEC_ERROR
+- * Decoder does not support XMA mode.
+- * \retval #VPX_DEC_MEM_ERROR
+- * Segment base address was not set, or segment was already stored.
+-
+- */
+- vpx_dec_err_t vpx_dec_set_mem_map(vpx_dec_ctx_t *ctx,
+- vpx_dec_mmap_t *mmaps,
+- unsigned int num_maps) DEPRECATED;
+-
+- /*!@} - end defgroup cap_xma*/
+- /*!@} - end defgroup decoder*/
+-
+-
+-#endif
+-#ifdef __cplusplus
+-}
+-#endif
+diff --git a/vpx_codec/vpx_encoder.h b/vpx_codec/vpx_encoder.h
+deleted file mode 100644
+index 67393be..0000000
+--- a/vpx_codec/vpx_encoder.h
++++ /dev/null
+@@ -1,792 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\defgroup encoder Encoder Algorithm Interface
+- * \ingroup codec
+- * This abstraction allows applications using this encoder to easily support
+- * multiple video formats with minimal code duplication. This section describes
+- * the interface common to all encoders.
+- * @{
+- */
+-
+-/*!\file vpx_encoder.h
+- * \brief Describes the encoder algorithm interface to applications.
+- *
+- * This file describes the interface between an application and a
+- * video encoder algorithm.
+- *
+- */
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#ifndef VPX_ENCODER_H
+-#define VPX_ENCODER_H
+-#include "vpx_codec.h"
+-
+-
+- /*!\brief Current ABI version number
+- *
+- * \internal
+- * If this file is altered in any way that changes the ABI, this value
+- * must be bumped. Examples include, but are not limited to, changing
+- * types, removing or reassigning enums, adding/removing/rearranging
+- * fields to structures
+- */
+-#define VPX_ENCODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
+-
+-
+- /*! \brief Encoder capabilities bitfield
+- *
+- * Each encoder advertises the capabilities it supports as part of its
+- * ::vpx_codec_iface_t interface structure. Capabilities are extra
+- * interfaces or functionality, and are not required to be supported
+- * by an encoder.
+- *
+- * The available flags are specifiedby VPX_CODEC_CAP_* defines.
+- */
+-#define VPX_CODEC_CAP_PSNR 0x10000 /**< Can issue PSNR packets */
+-
+-
+- /*! \brief Initialization-time Feature Enabling
+- *
+- * Certain codec features must be known at initialization time, to allow
+- * for proper memory allocation.
+- *
+- * The available flags are specified by VPX_CODEC_USE_* defines.
+- */
+-#define VPX_CODEC_USE_PSNR 0x10000 /**< Calculate PSNR on each frame */
+-
+-
+- /*!\brief Generic fixed size buffer structure
+- *
+- * This structure is able to hold a reference to any fixed size buffer.
+- */
+- typedef struct vpx_fixed_buf
+- {
+- void *buf; /**< Pointer to the data */
+- size_t sz; /**< Length of the buffer, in chars */
+- } vpx_fixed_buf_t; /**< alias for struct vpx_fixed_buf */
+-
+-
+- /*!\brief Time Stamp Type
+- *
+- * An integer, which when multiplied by the stream's time base, provides
+- * the absolute time of a sample.
+- */
+- typedef int64_t vpx_codec_pts_t;
+-
+-
+- /*!\brief Compressed Frame Flags
+- *
+- * This type represents a bitfield containing information about a compressed
+- * frame that may be useful to an application. The most significant 16 bits
+- * can be used by an algorithm to provide additional detail, for example to
+- * support frame types that are codec specific (MPEG-1 D-frames for example)
+- */
+- typedef uint32_t vpx_codec_frame_flags_t;
+-#define VPX_FRAME_IS_KEY 0x1 /**< frame is the start of a GOP */
+-#define VPX_FRAME_IS_DROPPABLE 0x2 /**< frame can be dropped without affecting
+- the stream (no future frame depends on
+- this one) */
+-#define VPX_FRAME_IS_INVISIBLE 0x4 /**< frame should be decoded but will not
+- be shown */
+-
+-
+- /*!\brief Encoder output packet variants
+- *
+- * This enumeration lists the different kinds of data packets that can be
+- * returned by calls to vpx_codec_get_cx_data(). Algorithms \ref MAY
+- * extend this list to provide additional functionality.
+- */
+- enum vpx_codec_cx_pkt_kind
+- {
+- VPX_CODEC_CX_FRAME_PKT, /**< Compressed video frame */
+- VPX_CODEC_STATS_PKT, /**< Two-pass statistics for this frame */
+- VPX_CODEC_PSNR_PKT, /**< PSNR statistics for this frame */
+- VPX_CODEC_CUSTOM_PKT = 256 /**< Algorithm extensions */
+- };
+-
+-
+- /*!\brief Encoder output packet
+- *
+- * This structure contains the different kinds of output data the encoder
+- * may produce while compressing a frame.
+- */
+- typedef struct vpx_codec_cx_pkt
+- {
+- enum vpx_codec_cx_pkt_kind kind; /**< packet variant */
+- union
+- {
+- struct
+- {
+- void *buf; /**< compressed data buffer */
+- size_t sz; /**< length of compressed data */
+- vpx_codec_pts_t pts; /**< time stamp to show frame
+- (in timebase units) */
+- unsigned long duration; /**< duration to show frame
+- (in timebase units) */
+- vpx_codec_frame_flags_t flags; /**< flags for this frame */
+- } frame; /**< data for compressed frame packet */
+- struct vpx_fixed_buf twopass_stats; /**< data for two-pass packet */
+- struct vpx_psnr_pkt
+- {
+- unsigned int samples[4]; /**< Number of samples, total/y/u/v */
+- uint64_t sse[4]; /**< sum squared error, total/y/u/v */
+- double psnr[4]; /**< PSNR, total/y/u/v */
+- } psnr; /**< data for PSNR packet */
+- struct vpx_fixed_buf raw; /**< data for arbitrary packets */
+-
+- /* This packet size is fixed to allow codecs to extend this
+- * interface without having to manage storage for raw packets,
+- * ie if it's smaller than 128 bytes, you can store in the
+- * packet list directly.
+- */
+- char pad[128 - sizeof(enum vpx_codec_cx_pkt_kind)]; /**< fixed sz */
+- } data; /**< packet data */
+- } vpx_codec_cx_pkt_t; /**< alias for struct vpx_codec_cx_pkt */
+-
+-
+- /*!\brief Rational Number
+- *
+- * This structure holds a fractional value.
+- */
+- typedef struct vpx_rational
+- {
+- int num; /**< fraction numerator */
+- int den; /**< fraction denominator */
+- } vpx_rational_t; /**< alias for struct vpx_rational */
+-
+-
+- /*!\brief Multi-pass Encoding Pass */
+- enum vpx_enc_pass
+- {
+- VPX_RC_ONE_PASS, /**< Single pass mode */
+- VPX_RC_FIRST_PASS, /**< First pass of multi-pass mode */
+- VPX_RC_LAST_PASS, /**< Final pass of multi-pass mode */
+- };
+-
+-
+- /*!\brief Rate control mode */
+- enum vpx_rc_mode
+- {
+- VPX_VBR, /**< Variable Bit Rate (VBR) mode */
+- VPX_CBR /**< Constant Bit Rate (CBR) mode */
+- };
+-
+-
+- /*!\brief Keyframe placement mode.
+- *
+- * This enumeration determines whether keyframes are placed automatically by
+- * the encoder or whether this behavior is disabled. Older releases of this
+- * SDK were implemented such that VPX_KF_FIXED meant keyframes were disabled.
+- * This name is confusing for this behavior, so the new symbols to be used
+- * are VPX_KF_AUTO and VPX_KF_DISABLED.
+- */
+- enum vpx_kf_mode
+- {
+- VPX_KF_FIXED, /**< deprecated, implies VPX_KF_DISABLED */
+- VPX_KF_AUTO, /**< Encoder determines optimal placement automatically */
+- VPX_KF_DISABLED = 0 /**< Encoder does not place keyframes. */
+- };
+-
+-
+- /*!\brief Encoded Frame Flags
+- *
+- * This type indicates a bitfield to be passed to vpx_codec_encode(), defining
+- * per-frame boolean values. By convention, bits common to all codecs will be
+- * named VPX_EFLAG_*, and bits specific to an algorithm will be named
+- * /algo/_eflag_*. The lower order 16 bits are reserved for common use.
+- */
+- typedef long vpx_enc_frame_flags_t;
+-#define VPX_EFLAG_FORCE_KF (1<<0) /**< Force this frame to be a keyframe */
+-
+-
+- /*!\brief Encoder configuration structure
+- *
+- * This structure contains the encoder settings that have common representations
+- * across all codecs. This doesn't imply that all codecs support all features,
+- * however.
+- */
+- typedef struct vpx_codec_enc_cfg
+- {
+- /*
+- * generic settings (g)
+- */
+-
+- /*!\brief Algorithm specific "usage" value
+- *
+- * Algorithms may define multiple values for usage, which may convey the
+- * intent of how the application intends to use the stream. If this value
+- * is non-zero, consult the documentation for the codec to determine its
+- * meaning.
+- */
+- unsigned int g_usage;
+-
+-
+- /*!\brief Maximum number of threads to use
+- *
+- * For multi-threaded implementations, use no more than this number of
+- * threads. The codec may use fewer threads than allowed. The value
+- * 0 is equivalent to the value 1.
+- */
+- unsigned int g_threads;
+-
+-
+- /*!\brief Bitstream profile to use
+- *
+- * Some codecs support a notion of multiple bitstream profiles. Typically
+- * this maps to a set of features that are turned on or off. Often the
+- * profile to use is determined by the features of the intended decoder.
+- * Consult the documentation for the codec to determine the valid values
+- * for this parameter, or set to zero for a sane default.
+- */
+- unsigned int g_profile; /**< profile of bitstream to use */
+-
+-
+-
+- /*!\brief Width of the frame
+- *
+- * This value identifies the presentation resolution of the frame,
+- * in pixels. Note that the frames passed as input to the encoder must
+- * have this resolution. Frames will be presented by the decoder in this
+- * resolution, independent of any spatial resampling the encoder may do.
+- */
+- unsigned int g_w;
+-
+-
+- /*!\brief Height of the frame
+- *
+- * This value identifies the presentation resolution of the frame,
+- * in pixels. Note that the frames passed as input to the encoder must
+- * have this resolution. Frames will be presented by the decoder in this
+- * resolution, independent of any spatial resampling the encoder may do.
+- */
+- unsigned int g_h;
+-
+-
+- /*!\brief Stream timebase units
+- *
+- * Indicates the smallest interval of time, in seconds, used by the stream.
+- * For fixed frame rate material, or variable frame rate material where
+- * frames are timed at a multiple of a given clock (ex: video capture),
+- * the \ref RECOMMENDED method is to set the timebase to the reciprocal
+- * of the frame rate (ex: 1001/30000 for 29.970 Hz NTSC). This allows the
+- * pts to correspond to the frame number, which can be handy. For
+- * re-encoding video from containers with absolute time timestamps, the
+- * \ref RECOMMENDED method is to set the timebase to that of the parent
+- * container or multimedia framework (ex: 1/1000 for ms, as in FLV).
+- */
+- struct vpx_rational g_timebase;
+-
+-
+- /*!\brief Enable error resilient mode.
+- *
+- * Error resilient mode indicates to the encoder that it should take
+- * measures appropriate for streaming over lossy or noisy links, if
+- * possible. Set to 1 to enable this feature, 0 to disable it.
+- */
+- unsigned int g_error_resilient;
+-
+-
+- /*!\brief Multi-pass Encoding Mode
+- *
+- * This value should be set to the current phase for multi-pass encoding.
+- * For single pass, set to #VPX_RC_ONE_PASS.
+- */
+- enum vpx_enc_pass g_pass;
+-
+-
+- /*!\brief Allow lagged encoding
+- *
+- * If set, this value allows the encoder to consume a number of input
+- * frames before producing output frames. This allows the encoder to
+- * base decisions for the current frame on future frames. This does
+- * increase the latency of the encoding pipeline, so it is not appropriate
+- * in all situations (ex: realtime encoding).
+- *
+- * Note that this is a maximum value -- the encoder may produce frames
+- * sooner than the given limit. Set this value to 0 to disable this
+- * feature.
+- */
+- unsigned int g_lag_in_frames;
+-
+-
+- /*
+- * rate control settings (rc)
+- */
+-
+- /*!\brief Temporal resampling configuration, if supported by the codec.
+- *
+- * Temporal resampling allows the codec to "drop" frames as a strategy to
+- * meet its target data rate. This can cause temporal discontinuities in
+- * the encoded video, which may appear as stuttering during playback. This
+- * trade-off is often acceptable, but for many applications is not. It can
+- * be disabled in these cases.
+- *
+- * Note that not all codecs support this feature. All vpx VPx codecs do.
+- * For other codecs, consult the documentation for that algorithm.
+- *
+- * This threshold is described as a percentage of the target data buffer.
+- * When the data buffer falls below this percentage of fullness, a
+- * dropped frame is indicated. Set the threshold to zero (0) to disable
+- * this feature.
+- */
+- unsigned int rc_dropframe_thresh;
+-
+-
+- /*!\brief Enable/disable spatial resampling, if supported by the codec.
+- *
+- * Spatial resampling allows the codec to compress a lower resolution
+- * version of the frame, which is then upscaled by the encoder to the
+- * correct presentation resolution. This increases visual quality at
+- * low data rates, at the expense of CPU time on the encoder/decoder.
+- */
+- unsigned int rc_resize_allowed;
+-
+-
+- /*!\brief Spatial resampling up watermark.
+- *
+- * This threshold is described as a percentage of the target data buffer.
+- * When the data buffer rises above this percentage of fullness, the
+- * encoder will step up to a higher resolution version of the frame.
+- */
+- unsigned int rc_resize_up_thresh;
+-
+-
+- /*!\brief Spatial resampling down watermark.
+- *
+- * This threshold is described as a percentage of the target data buffer.
+- * When the data buffer falls below this percentage of fullness, the
+- * encoder will step down to a lower resolution version of the frame.
+- */
+- unsigned int rc_resize_down_thresh;
+-
+-
+- /*!\brief Rate control algorithm to use.
+- *
+- * Indicates whether the end usage of this stream is to be streamed over
+- * a bandwidth constrained link, indicating that Constant Bit Rate (CBR)
+- * mode should be used, or whether it will be played back on a high
+- * bandwidth link, as from a local disk, where higher variations in
+- * bitrate are acceptable.
+- */
+- enum vpx_rc_mode rc_end_usage;
+-
+-
+- /*!\brief Two-pass stats buffer.
+- *
+- * A buffer containing all of the stats packets produced in the first
+- * pass, concatenated.
+- */
+- struct vpx_fixed_buf rc_twopass_stats_in;
+-
+-
+- /*!\brief Target data rate
+- *
+- * Target bandwidth to use for this stream, in kilobits per second.
+- */
+- unsigned int rc_target_bitrate;
+-
+-
+- /*
+- * quantizer settings
+- */
+-
+-
+- /*!\brief Minimum (Best Quality) Quantizer
+- *
+- * The quantizer is the most direct control over the quality of the
+- * encoded image. The range of valid values for the quantizer is codec
+- * specific. Consult the documentation for the codec to determine the
+- * values to use. To determine the range programmatically, call
+- * vpx_codec_enc_config_default() with a usage value of 0.
+- */
+- unsigned int rc_min_quantizer;
+-
+-
+- /*!\brief Maximum (Worst Quality) Quantizer
+- *
+- * The quantizer is the most direct control over the quality of the
+- * encoded image. The range of valid values for the quantizer is codec
+- * specific. Consult the documentation for the codec to determine the
+- * values to use. To determine the range programmatically, call
+- * vpx_codec_enc_config_default() with a usage value of 0.
+- */
+- unsigned int rc_max_quantizer;
+-
+-
+- /*
+- * bitrate tolerance
+- */
+-
+-
+- /*!\brief Rate control undershoot tolerance
+- *
+- * This value, expressed as a percentage of the target bitrate, describes
+- * the target bitrate for easier frames, allowing bits to be saved for
+- * harder frames. Set to zero to use the codec default.
+- */
+- unsigned int rc_undershoot_pct;
+-
+-
+- /*!\brief Rate control overshoot tolerance
+- *
+- * This value, expressed as a percentage of the target bitrate, describes
+- * the maximum allowed bitrate for a given frame. Set to zero to use the
+- * codec default.
+- */
+- unsigned int rc_overshoot_pct;
+-
+-
+- /*
+- * decoder buffer model parameters
+- */
+-
+-
+- /*!\brief Decoder Buffer Size
+- *
+- * This value indicates the amount of data that may be buffered by the
+- * decoding application. Note that this value is expressed in units of
+- * time (milliseconds). For example, a value of 5000 indicates that the
+- * client will buffer (at least) 5000ms worth of encoded data. Use the
+- * target bitrate (#rc_target_bitrate) to convert to bits/bytes, if
+- * necessary.
+- */
+- unsigned int rc_buf_sz;
+-
+-
+- /*!\brief Decoder Buffer Initial Size
+- *
+- * This value indicates the amount of data that will be buffered by the
+- * decoding application prior to beginning playback. This value is
+- * expressed in units of time (milliseconds). Use the target bitrate
+- * (#rc_target_bitrate) to convert to bits/bytes, if necessary.
+- */
+- unsigned int rc_buf_initial_sz;
+-
+-
+- /*!\brief Decoder Buffer Optimal Size
+- *
+- * This value indicates the amount of data that the encoder should try
+- * to maintain in the decoder's buffer. This value is expressed in units
+- * of time (milliseconds). Use the target bitrate (#rc_target_bitrate)
+- * to convert to bits/bytes, if necessary.
+- */
+- unsigned int rc_buf_optimal_sz;
+-
+-
+- /*
+- * 2 pass rate control parameters
+- */
+-
+-
+- /*!\brief Two-pass mode CBR/VBR bias
+- *
+- * Bias, expressed on a scale of 0 to 100, for determining target size
+- * for the current frame. The value 0 indicates the optimal CBR mode
+- * value should be used. The value 100 indicates the optimal VBR mode
+- * value should be used. Values in between indicate which way the
+- * encoder should "lean."
+- */
+- unsigned int rc_2pass_vbr_bias_pct; /**< RC mode bias between CBR and VBR(0-100: 0->CBR, 100->VBR) */
+-
+-
+- /*!\brief Two-pass mode per-GOP minimum bitrate
+- *
+- * This value, expressed as a percentage of the target bitrate, indicates
+- * the minimum bitrate to be used for a single GOP (aka "section")
+- */
+- unsigned int rc_2pass_vbr_minsection_pct;
+-
+-
+- /*!\brief Two-pass mode per-GOP maximum bitrate
+- *
+- * This value, expressed as a percentage of the target bitrate, indicates
+- * the maximum bitrate to be used for a single GOP (aka "section")
+- */
+- unsigned int rc_2pass_vbr_maxsection_pct;
+-
+-
+- /*
+- * keyframing settings (kf)
+- */
+-
+- /*!\brief Keyframe placement mode
+- *
+- * This value indicates whether the encoder should place keyframes at a
+- * fixed interval, or determine the optimal placement automatically
+- * (as governed by the #kf_min_dist and #kf_max_dist parameters)
+- */
+- enum vpx_kf_mode kf_mode;
+-
+-
+- /*!\brief Keyframe minimum interval
+- *
+- * This value, expressed as a number of frames, prevents the encoder from
+- * placing a keyframe nearer than kf_min_dist to the previous keyframe. At
+- * least kf_min_dist frames non-keyframes will be coded before the next
+- * keyframe. Set kf_min_dist equal to kf_max_dist for a fixed interval.
+- */
+- unsigned int kf_min_dist;
+-
+-
+- /*!\brief Keyframe maximum interval
+- *
+- * This value, expressed as a number of frames, forces the encoder to code
+- * a keyframe if one has not been coded in the last kf_max_dist frames.
+- * A value of 0 implies all frames will be keyframes. Set kf_min_dist
+- * equal to kf_max_dist for a fixed interval.
+- */
+- unsigned int kf_max_dist;
+-
+- } vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
+-
+-
+- /*!\brief Initialize an encoder instance
+- *
+- * Initializes a encoder context using the given interface. Applications
+- * should call the vpx_codec_enc_init convenience macro instead of this
+- * function directly, to ensure that the ABI version number parameter
+- * is properly initialized.
+- *
+- * In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
+- * parameter), the storage pointed to by the cfg parameter must be
+- * kept readable and stable until all memory maps have been set.
+- *
+- * \param[in] ctx Pointer to this instance's context.
+- * \param[in] iface Pointer to the algorithm interface to use.
+- * \param[in] cfg Configuration to use, if known. May be NULL.
+- * \param[in] flags Bitfield of VPX_CODEC_USE_* flags
+- * \param[in] ver ABI version number. Must be set to
+- * VPX_ENCODER_ABI_VERSION
+- * \retval #VPX_CODEC_OK
+- * The decoder algorithm initialized.
+- * \retval #VPX_CODEC_MEM_ERROR
+- * Memory allocation failed.
+- */
+- vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
+- vpx_codec_iface_t *iface,
+- vpx_codec_enc_cfg_t *cfg,
+- vpx_codec_flags_t flags,
+- int ver);
+-
+-
+- /*!\brief Convenience macro for vpx_codec_enc_init_ver()
+- *
+- * Ensures the ABI version parameter is properly set.
+- */
+-#define vpx_codec_enc_init(ctx, iface, cfg, flags) \
+- vpx_codec_enc_init_ver(ctx, iface, cfg, flags, VPX_ENCODER_ABI_VERSION)
+-
+-
+- /*!\brief Get a default configuration
+- *
+- * Initializes a encoder configuration structure with default values. Supports
+- * the notion of "usages" so that an algorithm may offer different default
+- * settings depending on the user's intended goal. This function \ref SHOULD
+- * be called by all applications to initialize the configuration structure
+- * before specializing the configuration with application specific values.
+- *
+- * \param[in] iface Pointer to the algorithm interface to use.
+- * \param[out] cfg Configuration buffer to populate
+- * \param[in] usage End usage. Set to 0 or use codec specific values.
+- *
+- * \retval #VPX_CODEC_OK
+- * The configuration was populated.
+- * \retval #VPX_CODEC_INCAPABLE
+- * Interface is not an encoder interface.
+- * \retval #VPX_CODEC_INVALID_PARAM
+- * A parameter was NULL, or the usage value was not recognized.
+- */
+- vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface,
+- vpx_codec_enc_cfg_t *cfg,
+- unsigned int usage);
+-
+-
+- /*!\brief Set or change configuration
+- *
+- * Reconfigures an encoder instance according to the given configuration.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] cfg Configuration buffer to use
+- *
+- * \retval #VPX_CODEC_OK
+- * The configuration was populated.
+- * \retval #VPX_CODEC_INCAPABLE
+- * Interface is not an encoder interface.
+- * \retval #VPX_CODEC_INVALID_PARAM
+- * A parameter was NULL, or the usage value was not recognized.
+- */
+- vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx,
+- const vpx_codec_enc_cfg_t *cfg);
+-
+-
+- /*!\brief Get global stream headers
+- *
+- * Retrieves a stream level global header packet, if supported by the codec.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- *
+- * \retval NULL
+- * Encoder does not support global header
+- * \retval Non-NULL
+- * Pointer to buffer containing global header packet
+- */
+- vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx);
+-
+-
+-#define VPX_DL_REALTIME (1) /**< deadline parameter analogous to
+- * VPx REALTIME mode. */
+-#define VPX_DL_GOOD_QUALITY (1000000) /**< deadline parameter analogous to
+- * VPx GOOD QUALITY mode. */
+-#define VPX_DL_BEST_QUALITY (0) /**< deadline parameter analogous to
+- * VPx BEST QUALITY mode. */
+- /*!\brief Encode a frame
+- *
+- * Encodes a video frame at the given "presentation time." The presentation
+- * time stamp (PTS) \ref MUST be strictly increasing.
+- *
+- * The encoder supports the notion of a soft real-time deadline. Given a
+- * non-zero value to the deadline parameter, the encoder will make a "best
+- * effort" guarantee to return before the given time slice expires. It is
+- * implicit that limiting the available time to encode will degrade the
+- * output quality. The encoder can be given an unlimited time to produce the
+- * best possible frame by specifying a deadline of '0'. This deadline
+- * supercedes the VPx notion of "best quality, good quality, realtime".
+- * Applications that wish to map these former settings to the new deadline
+- * based system can use the symbols #VPX_DL_REALTIME, #VPX_DL_GOOD_QUALITY,
+- * and #VPX_DL_BEST_QUALITY.
+- *
+- * When the last frame has been passed to the encoder, this function should
+- * continue to be called, with the img parameter set to NULL. This will
+- * signal the end-of-stream condition to the encoder and allow it to encode
+- * any held buffers. Encoding is complete when vpx_codec_encode() is called
+- * and vpx_codec_get_cx_data() returns no data.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] img Image data to encode, NULL to flush.
+- * \param[in] pts Presentation time stamp, in timebase units.
+- * \param[in] duration Duration to show frame, in timebase units.
+- * \param[in] flags Flags to use for encoding this frame.
+- * \param[in] deadline Time to spend encoding, in microseconds. (0=infinite)
+- *
+- * \retval #VPX_CODEC_OK
+- * The configuration was populated.
+- * \retval #VPX_CODEC_INCAPABLE
+- * Interface is not an encoder interface.
+- * \retval #VPX_CODEC_INVALID_PARAM
+- * A parameter was NULL, the image format is unsupported, etc.
+- */
+- vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx,
+- const vpx_image_t *img,
+- vpx_codec_pts_t pts,
+- unsigned long duration,
+- vpx_enc_frame_flags_t flags,
+- unsigned long deadline);
+-
+-
+- /*!\brief Set compressed data output buffer
+- *
+- * Sets the buffer that the codec should output the compressed data
+- * into. This call effectively sets the buffer pointer returned in the
+- * next VPX_CODEC_CX_FRAME_PKT packet. Subsequent packets will be
+- * appended into this buffer. The buffer is preserved across frames,
+- * so applications must periodically call this function after flushing
+- * the accumulated compressed data to disk or to the network to reset
+- * the pointer to the buffer's head.
+- *
+- * `pad_before` bytes will be skipped before writing the compressed
+- * data, and `pad_after` bytes will be appended to the packet. The size
+- * of the packet will be the sum of the size of the actual compressed
+- * data, pad_before, and pad_after. The padding bytes will be preserved
+- * (not overwritten).
+- *
+- * Note that calling this function does not guarantee that the returned
+- * compressed data will be placed into the specified buffer. In the
+- * event that the encoded data will not fit into the buffer provided,
+- * the returned packet \ref MAY point to an internal buffer, as it would
+- * if this call were never used. In this event, the output packet will
+- * NOT have any padding, and the application must free space and copy it
+- * to the proper place. This is of particular note in configurations
+- * that may output multiple packets for a single encoded frame (e.g., lagged
+- * encoding) or if the application does not reset the buffer periodically.
+- *
+- * Applications may restore the default behavior of the codec providing
+- * the compressed data buffer by calling this function with a NULL
+- * buffer.
+- *
+- * Applications \ref MUSTNOT call this function during iteration of
+- * vpx_codec_get_cx_data().
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in] buf Buffer to store compressed data into
+- * \param[in] pad_before Bytes to skip before writing compressed data
+- * \param[in] pad_after Bytes to skip after writing compressed data
+- *
+- * \retval #VPX_CODEC_OK
+- * The buffer was set successfully.
+- * \retval #VPX_CODEC_INVALID_PARAM
+- * A parameter was NULL, the image format is unsupported, etc.
+- */
+- vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx,
+- const vpx_fixed_buf_t *buf,
+- unsigned int pad_before,
+- unsigned int pad_after);
+-
+-
+- /*!\brief Encoded data iterator
+- *
+- * Iterates over a list of data packets to be passed from the encoder to the
+- * application. The different kinds of packets available are enumerated in
+- * #vpx_codec_cx_pkt_kind.
+- *
+- * #VPX_CODEC_CX_FRAME_PKT packets should be passed to the application's
+- * muxer. Multiple compressed frames may be in the list.
+- * #VPX_CODEC_STATS_PKT packets should be appended to a global buffer.
+- *
+- * The application \ref MUST silently ignore any packet kinds that it does
+- * not recognize or support.
+- *
+- * The data buffers returned from this function are only guaranteed to be
+- * valid until the application makes another call to any vpx_codec_* function.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- * \param[in,out] iter Iterator storage, initialized to NULL
+- *
+- * \return Returns a pointer to an output data packet (compressed frame data,
+- * two-pass statistics, etc.) or NULL to signal end-of-list.
+- *
+- */
+- const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx,
+- vpx_codec_iter_t *iter);
+-
+-
+- /*!\brief Get Preview Frame
+- *
+- * Returns an image that can be used as a preview. Shows the image as it would
+- * exist at the decompressor. The application \ref MUST NOT write into this
+- * image buffer.
+- *
+- * \param[in] ctx Pointer to this instance's context
+- *
+- * \return Returns a pointer to a preview image, or NULL if no image is
+- * available.
+- *
+- */
+- const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx);
+-
+-
+- /*!@} - end defgroup encoder*/
+-
+-#endif
+-#ifdef __cplusplus
+-}
+-#endif
+diff --git a/vpx_codec/vpx_image.h b/vpx_codec/vpx_image.h
+deleted file mode 100644
+index a8a9416..0000000
+--- a/vpx_codec/vpx_image.h
++++ /dev/null
+@@ -1,201 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-/*!\file vpx_image.h
+- * \brief Describes the vpx image descriptor and associated operations
+- *
+- */
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#ifndef VPX_IMAGE_H
+-#define VPX_IMAGE_H
+-
+- /*!\brief Current ABI version number
+- *
+- * \internal
+- * If this file is altered in any way that changes the ABI, this value
+- * must be bumped. Examples include, but are not limited to, changing
+- * types, removing or reassigning enums, adding/removing/rearranging
+- * fields to structures
+- */
+-#define VPX_IMAGE_ABI_VERSION (1) /**<\hideinitializer*/
+-
+-
+-#define IMG_FMT_PLANAR 0x100 /**< Image is a planar format */
+-#define IMG_FMT_UV_FLIP 0x200 /**< V plane precedes U plane in memory */
+-#define IMG_FMT_HAS_ALPHA 0x400 /**< Image has an alpha channel componnent */
+-
+-
+- /*!\brief List of supported image formats */
+- typedef enum img_fmt {
+- IMG_FMT_NONE,
+- IMG_FMT_RGB24, /**< 24 bit per pixel packed RGB */
+- IMG_FMT_RGB32, /**< 32 bit per pixel packed 0RGB */
+- IMG_FMT_RGB565, /**< 16 bit per pixel, 565 */
+- IMG_FMT_RGB555, /**< 16 bit per pixel, 555 */
+- IMG_FMT_UYVY, /**< UYVY packed YUV */
+- IMG_FMT_YUY2, /**< YUYV packed YUV */
+- IMG_FMT_YVYU, /**< YVYU packed YUV */
+- IMG_FMT_BGR24, /**< 24 bit per pixel packed BGR */
+- IMG_FMT_RGB32_LE, /**< 32 bit packed BGR0 */
+- IMG_FMT_ARGB, /**< 32 bit packed ARGB, alpha=255 */
+- IMG_FMT_ARGB_LE, /**< 32 bit packed BGRA, alpha=255 */
+- IMG_FMT_RGB565_LE, /**< 16 bit per pixel, gggbbbbb rrrrrggg */
+- IMG_FMT_RGB555_LE, /**< 16 bit per pixel, gggbbbbb 0rrrrrgg */
+- IMG_FMT_YV12 = IMG_FMT_PLANAR | IMG_FMT_UV_FLIP | 1, /**< planar YVU */
+- IMG_FMT_I420 = IMG_FMT_PLANAR | 2,
+- IMG_FMT_VPXYV12 = IMG_FMT_PLANAR | IMG_FMT_UV_FLIP | 3, /** < planar 4:2:0 format with vpx color space */
+- IMG_FMT_VPXI420 = IMG_FMT_PLANAR | 4, /** < planar 4:2:0 format with vpx color space */
+- }
+- img_fmt_t; /**< alias for enum img_fmt */
+-
+-
+- /**\brief Image Descriptor */
+- typedef struct
+- {
+- img_fmt_t fmt; /**< Image Format */
+-
+- /* Image storage dimensions */
+- unsigned int w; /**< Stored image width */
+- unsigned int h; /**< Stored image height */
+-
+- /* Image display dimensions */
+- unsigned int d_w; /**< Displayed image width */
+- unsigned int d_h; /**< Displayed image height */
+-
+- /* Chroma subsampling info */
+- unsigned int x_chroma_shift; /**< subsampling order, X */
+- unsigned int y_chroma_shift; /**< subsampling order, Y */
+-
+- /* Image data pointers. */
+-#define PLANE_PACKED 0 /**< To be used for all packed formats */
+-#define PLANE_Y 0 /**< Y (Luminance) plane */
+-#define PLANE_U 1 /**< U (Chroma) plane */
+-#define PLANE_V 2 /**< V (Chroma) plane */
+-#define PLANE_ALPHA 3 /**< A (Transparancy) plane */
+- unsigned char *planes[4]; /**< pointer to the top left pixel for each plane */
+- int stride[4]; /**< stride between rows for each plane */
+-
+- int bps; /**< bits per sample (for packed formats) */
+-
+- /* The following member may be set by the application to associate data
+- * with this image.
+- */
+- void *user_priv; /**< may be set by the application to associate data
+- * with this image. */
+-
+- /* The following members should be treated as private. */
+- unsigned char *img_data; /**< private */
+- int img_data_owner; /**< private */
+- int self_allocd; /**< private */
+- } vpx_image_t; /**< alias for struct vpx_image */
+-
+- /**\brief Representation of a rectangle on a surface */
+- typedef struct vpx_image_rect
+- {
+- unsigned int x; /**< leftmost column */
+- unsigned int y; /**< topmost row */
+- unsigned int w; /**< width */
+- unsigned int h; /**< height */
+- } vpx_image_rect_t; /**< alias for struct vpx_image_rect */
+-
+- /*!\brief Open a descriptor, allocating storage for the underlying image
+- *
+- * Returns a descriptor for storing an image of the given format. The
+- * storage for the descriptor is allocated on the heap.
+- *
+- * \param[in] img Pointer to storage for descriptor. If this parameter
+- * is NULL, the storage for the descriptor will be
+- * allocated on the heap.
+- * \param[in] fmt Format for the image
+- * \param[in] d_w Width of the image
+- * \param[in] d_h Height of the image
+- * \param[in] align Alignment, in bytes, of each row in the image.
+- *
+- * \return Returns a pointer to the initialized image descriptor. If the img
+- * parameter is non-null, the value of the img parameter will be
+- * returned.
+- */
+- vpx_image_t *vpx_img_alloc(vpx_image_t *img,
+- img_fmt_t fmt,
+- unsigned int d_w,
+- unsigned int d_h,
+- unsigned int align);
+-
+- /*!\brief Open a descriptor, using existing storage for the underlying image
+- *
+- * Returns a descriptor for storing an image of the given format. The
+- * storage for descriptor has been allocated elsewhere, and a descriptor is
+- * desired to "wrap" that storage.
+- *
+- * \param[in] img Pointer to storage for descriptor. If this parameter
+- * is NULL, the storage for the descriptor will be
+- * allocated on the heap.
+- * \param[in] fmt Format for the image
+- * \param[in] d_w Width of the image
+- * \param[in] d_h Height of the image
+- * \param[in] align Alignment, in bytes, of each row in the image.
+- * \param[in] img_data Storage to use for the image
+- *
+- * \return Returns a pointer to the initialized image descriptor. If the img
+- * parameter is non-null, the value of the img parameter will be
+- * returned.
+- */
+- vpx_image_t *vpx_img_wrap(vpx_image_t *img,
+- img_fmt_t fmt,
+- unsigned int d_w,
+- unsigned int d_h,
+- unsigned int align,
+- unsigned char *img_data);
+-
+-
+- /*!\brief Set the rectangle identifying the displayed portion of the image
+- *
+- * Updates the displayed rectangle (aka viewport) on the image surface to
+- * match the specified coordinates and size.
+- *
+- * \param[in] img Image descriptor
+- * \param[in] x leftmost column
+- * \param[in] y topmost row
+- * \param[in] w width
+- * \param[in] h height
+- *
+- * \return 0 if the requested rectangle is valid, nonzero otherwise.
+- */
+- int vpx_img_set_rect(vpx_image_t *img,
+- unsigned int x,
+- unsigned int y,
+- unsigned int w,
+- unsigned int h);
+-
+-
+- /*!\brief Flip the image vertically (top for bottom)
+- *
+- * Adjusts the image descriptor's pointers and strides to make the image
+- * be referenced upside-down.
+- *
+- * \param[in] img Image descriptor
+- */
+- void vpx_img_flip(vpx_image_t *img);
+-
+- /*!\brief Close an image descriptor
+- *
+- * Frees all allocated storage associated with an image descriptor.
+- *
+- * \param[in] img Image descriptor
+- */
+- void vpx_img_free(vpx_image_t *img);
+-
+-#endif
+-#ifdef __cplusplus
+-}
+-#endif
+diff --git a/vpx_mem/include/nds/vpx_mem_nds.h b/vpx_mem/include/nds/vpx_mem_nds.h
+index c332403..361c29b 100644
+--- a/vpx_mem/include/nds/vpx_mem_nds.h
++++ b/vpx_mem/include/nds/vpx_mem_nds.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/include/vpx_mem_intrnl.h b/vpx_mem/include/vpx_mem_intrnl.h
+index 3b68d86..4605b34 100644
+--- a/vpx_mem/include/vpx_mem_intrnl.h
++++ b/vpx_mem/include/vpx_mem_intrnl.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/include/vpx_mem_tracker.h b/vpx_mem/include/vpx_mem_tracker.h
+index ab85d19..49f783e 100644
+--- a/vpx_mem/include/vpx_mem_tracker.h
++++ b/vpx_mem/include/vpx_mem_tracker.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/intel_linux/vpx_mem.c b/vpx_mem/intel_linux/vpx_mem.c
+index 002e407..7bce794 100644
+--- a/vpx_mem/intel_linux/vpx_mem.c
++++ b/vpx_mem/intel_linux/vpx_mem.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/intel_linux/vpx_mem_tracker.c b/vpx_mem/intel_linux/vpx_mem_tracker.c
+index fa023e3..fcbebc9 100644
+--- a/vpx_mem/intel_linux/vpx_mem_tracker.c
++++ b/vpx_mem/intel_linux/vpx_mem_tracker.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/hmm_alloc.c b/vpx_mem/memory_manager/hmm_alloc.c
+index 9abd81e..3f10097 100644
+--- a/vpx_mem/memory_manager/hmm_alloc.c
++++ b/vpx_mem/memory_manager/hmm_alloc.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/hmm_base.c b/vpx_mem/memory_manager/hmm_base.c
+index 0cacc3f..fbc36de 100644
+--- a/vpx_mem/memory_manager/hmm_base.c
++++ b/vpx_mem/memory_manager/hmm_base.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/hmm_dflt_abort.c b/vpx_mem/memory_manager/hmm_dflt_abort.c
+index dc59f55..71b41d9 100644
+--- a/vpx_mem/memory_manager/hmm_dflt_abort.c
++++ b/vpx_mem/memory_manager/hmm_dflt_abort.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/hmm_grow.c b/vpx_mem/memory_manager/hmm_grow.c
+index 79d75a7..a979c7a 100644
+--- a/vpx_mem/memory_manager/hmm_grow.c
++++ b/vpx_mem/memory_manager/hmm_grow.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/hmm_largest.c b/vpx_mem/memory_manager/hmm_largest.c
+index 5ebe398..82a6a36 100644
+--- a/vpx_mem/memory_manager/hmm_largest.c
++++ b/vpx_mem/memory_manager/hmm_largest.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/hmm_resize.c b/vpx_mem/memory_manager/hmm_resize.c
+index 6e3f2f0..cb93bb1 100644
+--- a/vpx_mem/memory_manager/hmm_resize.c
++++ b/vpx_mem/memory_manager/hmm_resize.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/hmm_shrink.c b/vpx_mem/memory_manager/hmm_shrink.c
+index 5ef9b23..d845136 100644
+--- a/vpx_mem/memory_manager/hmm_shrink.c
++++ b/vpx_mem/memory_manager/hmm_shrink.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/hmm_true.c b/vpx_mem/memory_manager/hmm_true.c
+index 41103c8..586fc22 100644
+--- a/vpx_mem/memory_manager/hmm_true.c
++++ b/vpx_mem/memory_manager/hmm_true.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/include/cavl_if.h b/vpx_mem/memory_manager/include/cavl_if.h
+index e2733ef..da1b148 100644
+--- a/vpx_mem/memory_manager/include/cavl_if.h
++++ b/vpx_mem/memory_manager/include/cavl_if.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/include/cavl_impl.h b/vpx_mem/memory_manager/include/cavl_impl.h
+index 267bc73..e67cc8a 100644
+--- a/vpx_mem/memory_manager/include/cavl_impl.h
++++ b/vpx_mem/memory_manager/include/cavl_impl.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/include/heapmm.h b/vpx_mem/memory_manager/include/heapmm.h
+index 933e30d..4e46c41 100644
+--- a/vpx_mem/memory_manager/include/heapmm.h
++++ b/vpx_mem/memory_manager/include/heapmm.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/include/hmm_cnfg.h b/vpx_mem/memory_manager/include/hmm_cnfg.h
+index 86e4e9f..715163c 100644
+--- a/vpx_mem/memory_manager/include/hmm_cnfg.h
++++ b/vpx_mem/memory_manager/include/hmm_cnfg.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/memory_manager/include/hmm_intrnl.h b/vpx_mem/memory_manager/include/hmm_intrnl.h
+index 6e2be08..1dddb8a 100644
+--- a/vpx_mem/memory_manager/include/hmm_intrnl.h
++++ b/vpx_mem/memory_manager/include/hmm_intrnl.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/nds/vpx_mem_nds.c b/vpx_mem/nds/vpx_mem_nds.c
+index f2a3043..88d474a 100644
+--- a/vpx_mem/nds/vpx_mem_nds.c
++++ b/vpx_mem/nds/vpx_mem_nds.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/ti_c6x/vpx_mem_ti_6cx.c b/vpx_mem/ti_c6x/vpx_mem_ti_6cx.c
+index 6501855..c2a1c28 100644
+--- a/vpx_mem/ti_c6x/vpx_mem_ti_6cx.c
++++ b/vpx_mem/ti_c6x/vpx_mem_ti_6cx.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/vpx_mem.c b/vpx_mem/vpx_mem.c
+index f6b1a35..ba92024 100644
+--- a/vpx_mem/vpx_mem.c
++++ b/vpx_mem/vpx_mem.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/vpx_mem.h b/vpx_mem/vpx_mem.h
+index 6ccb9be..a1239c1 100644
+--- a/vpx_mem/vpx_mem.h
++++ b/vpx_mem/vpx_mem.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_mem/vpx_mem_tracker.c b/vpx_mem/vpx_mem_tracker.c
+index 4427e27..92152a6 100644
+--- a/vpx_mem/vpx_mem_tracker.c
++++ b/vpx_mem/vpx_mem_tracker.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_ports/config.h b/vpx_ports/config.h
+index da38137..9d32393 100644
+--- a/vpx_ports/config.h
++++ b/vpx_ports/config.h
+@@ -1,19 +1,10 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+-
+-
+-/* This file uses some preprocessor magic to expand the value of HAVE_CONFIG_H,
+- * as defined by the build system, so that different projects can use the file
+- * name for config.h that suits them.
+- */
+-#define QUOTE_(x) #x
+-#define QUOTE(x) QUOTE_(x)
+-#include QUOTE(HAVE_CONFIG_H)
+-#undef QUOTE
+-#undef QUOTE_
++#include "vpx_config.h"
+diff --git a/vpx_ports/emms.asm b/vpx_ports/emms.asm
+index 03e3499..096176d 100644
+--- a/vpx_ports/emms.asm
++++ b/vpx_ports/emms.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vpx_ports/mem.h b/vpx_ports/mem.h
+index 10942f1..ade2e30 100644
+--- a/vpx_ports/mem.h
++++ b/vpx_ports/mem.h
+@@ -1,17 +1,18 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+ #ifndef VPX_PORTS_MEM_H
+ #define VPX_PORTS_MEM_H
+ #include "vpx_config.h"
+-#include "vpx_integer.h"
++#include "vpx/vpx_integer.h"
+
+ #if defined(__GNUC__) && __GNUC__
+ #define DECLARE_ALIGNED(n,typ,val) typ val __attribute__ ((aligned (n)))
+diff --git a/vpx_ports/mem_ops.h b/vpx_ports/mem_ops.h
+index 869d583..109c270 100644
+--- a/vpx_ports/mem_ops.h
++++ b/vpx_ports/mem_ops.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_ports/mem_ops_aligned.h b/vpx_ports/mem_ops_aligned.h
+index 1d0db2c..7c4d95e 100644
+--- a/vpx_ports/mem_ops_aligned.h
++++ b/vpx_ports/mem_ops_aligned.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_ports/vpx_integer.h b/vpx_ports/vpx_integer.h
+deleted file mode 100644
+index d3f7ddd..0000000
+--- a/vpx_ports/vpx_integer.h
++++ /dev/null
+@@ -1,52 +0,0 @@
+-/*
+- * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+- *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
+- */
+-
+-
+-#ifndef VPX_INTEGER_H
+-#define VPX_INTEGER_H
+-
+-/* get ptrdiff_t, size_t, wchar_t, NULL */
+-#include <stddef.h>
+-
+-#if defined(HAVE_STDINT_H) && HAVE_STDINT_H
+-#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
+-#define __STDC_FORMAT_MACROS
+-#endif
+-#include <stdint.h>
+-#include <inttypes.h>
+-#else
+-typedef signed char int8_t;
+-typedef signed short int16_t;
+-typedef signed int int32_t;
+-
+-typedef unsigned char uint8_t;
+-typedef unsigned short uint16_t;
+-typedef unsigned int uint32_t;
+-
+-#if defined(_MSC_VER)
+-typedef signed __int64 int64_t;
+-typedef unsigned __int64 uint64_t;
+-#define PRId64 "I64d"
+-#endif
+-
+-#ifdef HAVE_ARMV6
+-typedef unsigned int int_fast16_t;
+-#else
+-typedef signed short int_fast16_t;
+-#endif
+-typedef signed char int_fast8_t;
+-typedef unsigned char uint_fast8_t;
+-
+-#ifndef _UINTPTR_T_DEFINED
+-typedef unsigned int uintptr_t;
+-#endif
+-
+-#endif
+-
+-#endif
+diff --git a/vpx_ports/vpx_timer.h b/vpx_ports/vpx_timer.h
+index 5c04538..11fee84 100644
+--- a/vpx_ports/vpx_timer.h
++++ b/vpx_ports/vpx_timer.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_ports/vpxtypes.h b/vpx_ports/vpxtypes.h
+index 86525b7..b9c8b8c 100644
+--- a/vpx_ports/vpxtypes.h
++++ b/vpx_ports/vpxtypes.h
+@@ -1,19 +1,18 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+ #ifndef __VPXTYPES_H__
+ #define __VPXTYPES_H__
+
+-#ifdef HAVE_CONFIG_H
+-#include HAVE_CONFIG_H
+-#endif
++#include "vpx_ports/config.h"
+
+ //#include <sys/types.h>
+ #ifdef _MSC_VER
+diff --git a/vpx_ports/x86.h b/vpx_ports/x86.h
+index 935d037..8c23abd 100644
+--- a/vpx_ports/x86.h
++++ b/vpx_ports/x86.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_ports/x86_abi_support.asm b/vpx_ports/x86_abi_support.asm
+index db8208f..a1622e6 100644
+--- a/vpx_ports/x86_abi_support.asm
++++ b/vpx_ports/x86_abi_support.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+@@ -198,22 +199,38 @@
+ push r9
+ %endif
+ %if %1 > 6
+- mov rax,[rbp+16]
+- push rax
+- %endif
+- %if %1 > 7
+- mov rax,[rbp+24]
+- push rax
+- %endif
+- %if %1 > 8
+- mov rax,[rbp+32]
++ %assign i %1-6
++ %assign off 16
++ %rep i
++ mov rax,[rbp+off]
+ push rax
++ %assign off off+8
++ %endrep
+ %endif
+ %endm
+ %endif
+ %define UNSHADOW_ARGS mov rsp, rbp
+ %endif
+
++; must keep XMM6:XMM15 (libvpx uses XMM6 and XMM7) on Win64 ABI
++; rsp register has to be aligned
++%ifidn __OUTPUT_FORMAT__,x64
++%macro SAVE_XMM 0
++ sub rsp, 32
++ movdqa XMMWORD PTR [rsp], xmm6
++ movdqa XMMWORD PTR [rsp+16], xmm7
++%endmacro
++%macro RESTORE_XMM 0
++ movdqa xmm6, XMMWORD PTR [rsp]
++ movdqa xmm7, XMMWORD PTR [rsp+16]
++ add rsp, 32
++%endmacro
++%else
++%macro SAVE_XMM 0
++%endmacro
++%macro RESTORE_XMM 0
++%endmacro
++%endif
+
+ ; Name of the rodata section
+ ;
+@@ -229,3 +246,14 @@ fake_got:
+ %else
+ %define SECTION_RODATA section .rodata
+ %endif
++
++
++; Tell GNU ld that we don't require an executable stack.
++%ifidn __OUTPUT_FORMAT__,elf32
++section .note.GNU-stack noalloc noexec nowrite progbits
++section .text
++%elifidn __OUTPUT_FORMAT__,elf64
++section .note.GNU-stack noalloc noexec nowrite progbits
++section .text
++%endif
++
+diff --git a/vpx_scale/arm/armv4/gen_scalers_armv4.asm b/vpx_scale/arm/armv4/gen_scalers_armv4.asm
+index 1c904ed..e317fe9 100644
+--- a/vpx_scale/arm/armv4/gen_scalers_armv4.asm
++++ b/vpx_scale/arm/armv4/gen_scalers_armv4.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vpx_scale/arm/nds/yv12extend.c b/vpx_scale/arm/nds/yv12extend.c
+index 56959cb..9ec3466 100644
+--- a/vpx_scale/arm/nds/yv12extend.c
++++ b/vpx_scale/arm/nds/yv12extend.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm b/vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm
+index 26384c4..64e7bfe 100644
+--- a/vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm
++++ b/vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vpx_scale/arm/neon/vp8_vpxyv12_copyframeyonly_neon.asm b/vpx_scale/arm/neon/vp8_vpxyv12_copyframeyonly_neon.asm
+index a50ae60..f79de3c 100644
+--- a/vpx_scale/arm/neon/vp8_vpxyv12_copyframeyonly_neon.asm
++++ b/vpx_scale/arm/neon/vp8_vpxyv12_copyframeyonly_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm b/vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm
+index c8923d5..2e24e24 100644
+--- a/vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm
++++ b/vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm b/vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm
+index 8c9ce19..418578f 100644
+--- a/vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm
++++ b/vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vpx_scale/arm/scalesystemdependant.c b/vpx_scale/arm/scalesystemdependant.c
+index 3c355be..67954b2 100644
+--- a/vpx_scale/arm/scalesystemdependant.c
++++ b/vpx_scale/arm/scalesystemdependant.c
+@@ -1,18 +1,17 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
++#include "vpx_ports/config.h"
+ #include "vpx_scale/vpxscale.h"
+
+-#ifdef HAVE_CONFIG_H
+-#include "vpx_config.h"
+-#endif
+
+ void (*vp8_yv12_extend_frame_borders_ptr)(YV12_BUFFER_CONFIG *ybf);
+ extern void vp8_yv12_extend_frame_borders(YV12_BUFFER_CONFIG *ybf);
+diff --git a/vpx_scale/arm/yv12extend_arm.c b/vpx_scale/arm/yv12extend_arm.c
+index 7c3f7cd..5069030 100644
+--- a/vpx_scale/arm/yv12extend_arm.c
++++ b/vpx_scale/arm/yv12extend_arm.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/blackfin/yv12config.c b/vpx_scale/blackfin/yv12config.c
+index 7cb083f..950a5d2 100644
+--- a/vpx_scale/blackfin/yv12config.c
++++ b/vpx_scale/blackfin/yv12config.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/blackfin/yv12extend.c b/vpx_scale/blackfin/yv12extend.c
+index d5be495..80504ef 100644
+--- a/vpx_scale/blackfin/yv12extend.c
++++ b/vpx_scale/blackfin/yv12extend.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/dm642/bicubic_scaler_c64.c b/vpx_scale/dm642/bicubic_scaler_c64.c
+index 9bd3797..e026be5 100644
+--- a/vpx_scale/dm642/bicubic_scaler_c64.c
++++ b/vpx_scale/dm642/bicubic_scaler_c64.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/dm642/gen_scalers_c64.c b/vpx_scale/dm642/gen_scalers_c64.c
+index 2126a75..34f95f7 100644
+--- a/vpx_scale/dm642/gen_scalers_c64.c
++++ b/vpx_scale/dm642/gen_scalers_c64.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/dm642/yv12extend.c b/vpx_scale/dm642/yv12extend.c
+index ca25a5f..2557a3a 100644
+--- a/vpx_scale/dm642/yv12extend.c
++++ b/vpx_scale/dm642/yv12extend.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/generic/bicubic_scaler.c b/vpx_scale/generic/bicubic_scaler.c
+index e3c2b4a..48f9096 100644
+--- a/vpx_scale/generic/bicubic_scaler.c
++++ b/vpx_scale/generic/bicubic_scaler.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/generic/gen_scalers.c b/vpx_scale/generic/gen_scalers.c
+index a5e545f..ff841f3 100644
+--- a/vpx_scale/generic/gen_scalers.c
++++ b/vpx_scale/generic/gen_scalers.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+@@ -936,12 +937,13 @@ void vp8cx_vertical_band_2_1_scale_c(unsigned char *source, unsigned int src_pit
+
+ void vp8cx_vertical_band_2_1_scale_i_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+ {
+- unsigned int i;
++ int i;
+ int temp;
++ int width = dest_width;
+
+ (void) dest_pitch;
+
+- for (i = 0; i < dest_width; i++)
++ for (i = 0; i < width; i++)
+ {
+ temp = 8;
+ temp += source[i-(int)src_pitch] * 3;
+diff --git a/vpx_scale/generic/scalesystemdependant.c b/vpx_scale/generic/scalesystemdependant.c
+index 28f5c72..7a24a26 100644
+--- a/vpx_scale/generic/scalesystemdependant.c
++++ b/vpx_scale/generic/scalesystemdependant.c
+@@ -1,18 +1,17 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
++#include "vpx_ports/config.h"
+ #include "vpx_scale/vpxscale.h"
+
+-#ifdef HAVE_CONFIG_H
+-#include "vpx_config.h"
+-#endif
+
+ void (*vp8_yv12_extend_frame_borders_ptr)(YV12_BUFFER_CONFIG *ybf);
+ extern void vp8_yv12_extend_frame_borders(YV12_BUFFER_CONFIG *ybf);
+diff --git a/vpx_scale/generic/vpxscale.c b/vpx_scale/generic/vpxscale.c
+index 206cd55..8f8cfb5 100644
+--- a/vpx_scale/generic/vpxscale.c
++++ b/vpx_scale/generic/vpxscale.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c
+index 04617be..008130b 100644
+--- a/vpx_scale/generic/yv12config.c
++++ b/vpx_scale/generic/yv12config.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/generic/yv12extend.c b/vpx_scale/generic/yv12extend.c
+index 4906625..907fa68 100644
+--- a/vpx_scale/generic/yv12extend.c
++++ b/vpx_scale/generic/yv12extend.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/include/arm/vpxscale_nofp.h b/vpx_scale/include/arm/vpxscale_nofp.h
+index d6181d2..39e3742 100644
+--- a/vpx_scale/include/arm/vpxscale_nofp.h
++++ b/vpx_scale/include/arm/vpxscale_nofp.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/include/generic/vpxscale_arbitrary.h b/vpx_scale/include/generic/vpxscale_arbitrary.h
+index 2b50f24..68b8fc0 100644
+--- a/vpx_scale/include/generic/vpxscale_arbitrary.h
++++ b/vpx_scale/include/generic/vpxscale_arbitrary.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/include/generic/vpxscale_depricated.h b/vpx_scale/include/generic/vpxscale_depricated.h
+index 015eed0..dbe7786 100644
+--- a/vpx_scale/include/generic/vpxscale_depricated.h
++++ b/vpx_scale/include/generic/vpxscale_depricated.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/include/generic/vpxscale_nofp.h b/vpx_scale/include/generic/vpxscale_nofp.h
+index c4d5f4c..97ea60e 100644
+--- a/vpx_scale/include/generic/vpxscale_nofp.h
++++ b/vpx_scale/include/generic/vpxscale_nofp.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/include/leapster/vpxscale.h b/vpx_scale/include/leapster/vpxscale.h
+index f70029c..a40f2eb 100644
+--- a/vpx_scale/include/leapster/vpxscale.h
++++ b/vpx_scale/include/leapster/vpxscale.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/include/symbian/vpxscale_nofp.h b/vpx_scale/include/symbian/vpxscale_nofp.h
+index d6181d2..39e3742 100644
+--- a/vpx_scale/include/symbian/vpxscale_nofp.h
++++ b/vpx_scale/include/symbian/vpxscale_nofp.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/include/vpxscale_nofp.h b/vpx_scale/include/vpxscale_nofp.h
+index f6482f9..f39a1c6 100644
+--- a/vpx_scale/include/vpxscale_nofp.h
++++ b/vpx_scale/include/vpxscale_nofp.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/intel_linux/scaleopt.c b/vpx_scale/intel_linux/scaleopt.c
+index 6555600..1bdb488 100644
+--- a/vpx_scale/intel_linux/scaleopt.c
++++ b/vpx_scale/intel_linux/scaleopt.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/intel_linux/scalesystemdependant.c b/vpx_scale/intel_linux/scalesystemdependant.c
+index 9ed48bf..82b90c9 100644
+--- a/vpx_scale/intel_linux/scalesystemdependant.c
++++ b/vpx_scale/intel_linux/scalesystemdependant.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/leapster/doptsystemdependant_lf.c b/vpx_scale/leapster/doptsystemdependant_lf.c
+index ca13167..f4ccb16 100644
+--- a/vpx_scale/leapster/doptsystemdependant_lf.c
++++ b/vpx_scale/leapster/doptsystemdependant_lf.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/leapster/gen_scalers_lf.c b/vpx_scale/leapster/gen_scalers_lf.c
+index 1b9c7c7..f9a11fe 100644
+--- a/vpx_scale/leapster/gen_scalers_lf.c
++++ b/vpx_scale/leapster/gen_scalers_lf.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/leapster/vpxscale_lf.c b/vpx_scale/leapster/vpxscale_lf.c
+index 5f05e5d..deabd98 100644
+--- a/vpx_scale/leapster/vpxscale_lf.c
++++ b/vpx_scale/leapster/vpxscale_lf.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/leapster/yv12extend.c b/vpx_scale/leapster/yv12extend.c
+index 480d971..5a89c31 100644
+--- a/vpx_scale/leapster/yv12extend.c
++++ b/vpx_scale/leapster/yv12extend.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/scale_mode.h b/vpx_scale/scale_mode.h
+index 2a9ab76..41aefa2 100644
+--- a/vpx_scale/scale_mode.h
++++ b/vpx_scale/scale_mode.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/symbian/gen_scalers_armv4.asm b/vpx_scale/symbian/gen_scalers_armv4.asm
+index 1c904ed..e317fe9 100644
+--- a/vpx_scale/symbian/gen_scalers_armv4.asm
++++ b/vpx_scale/symbian/gen_scalers_armv4.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vpx_scale/symbian/scalesystemdependant.c b/vpx_scale/symbian/scalesystemdependant.c
+index a2acc3e..75ef26d 100644
+--- a/vpx_scale/symbian/scalesystemdependant.c
++++ b/vpx_scale/symbian/scalesystemdependant.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/vpxscale.h b/vpx_scale/vpxscale.h
+index 9a86b75..f3057fe 100644
+--- a/vpx_scale/vpxscale.h
++++ b/vpx_scale/vpxscale.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/wce/gen_scalers_armv4.asm b/vpx_scale/wce/gen_scalers_armv4.asm
+index 1c904ed..e317fe9 100644
+--- a/vpx_scale/wce/gen_scalers_armv4.asm
++++ b/vpx_scale/wce/gen_scalers_armv4.asm
+@@ -1,10 +1,11 @@
+ ;
+ ; Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ ;
+-; Use of this source code is governed by a BSD-style license and patent
+-; grant that can be found in the LICENSE file in the root of the source
+-; tree. All contributing project authors may be found in the AUTHORS
+-; file in the root of the source tree.
++; Use of this source code is governed by a BSD-style license
++; that can be found in the LICENSE file in the root of the source
++; tree. An additional intellectual property rights grant can be found
++; in the file PATENTS. All contributing project authors may
++; be found in the AUTHORS file in the root of the source tree.
+ ;
+
+
+diff --git a/vpx_scale/wce/scalesystemdependant.c b/vpx_scale/wce/scalesystemdependant.c
+index a5a6a52..1d62eb5 100644
+--- a/vpx_scale/wce/scalesystemdependant.c
++++ b/vpx_scale/wce/scalesystemdependant.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/win32/scaleopt.c b/vpx_scale/win32/scaleopt.c
+index da0533e..59d49e6 100644
+--- a/vpx_scale/win32/scaleopt.c
++++ b/vpx_scale/win32/scaleopt.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/win32/scalesystemdependant.c b/vpx_scale/win32/scalesystemdependant.c
+index 9ed48bf..82b90c9 100644
+--- a/vpx_scale/win32/scalesystemdependant.c
++++ b/vpx_scale/win32/scalesystemdependant.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/x86_64/scaleopt.c b/vpx_scale/x86_64/scaleopt.c
+index 3d2d5f2..de4c478 100644
+--- a/vpx_scale/x86_64/scaleopt.c
++++ b/vpx_scale/x86_64/scaleopt.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/x86_64/scalesystemdependant.c b/vpx_scale/x86_64/scalesystemdependant.c
+index 43f05a6..0324449 100644
+--- a/vpx_scale/x86_64/scalesystemdependant.c
++++ b/vpx_scale/x86_64/scalesystemdependant.c
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h
+index a8d0ce4..f01bd78 100644
+--- a/vpx_scale/yv12config.h
++++ b/vpx_scale/yv12config.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/vpx_scale/yv12extend.h b/vpx_scale/yv12extend.h
+index 9968fea..b310ef5 100644
+--- a/vpx_scale/yv12extend.h
++++ b/vpx_scale/yv12extend.h
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/wince_wmain_adapter.cpp b/wince_wmain_adapter.cpp
+index db2119c..48d3ab3 100644
+--- a/wince_wmain_adapter.cpp
++++ b/wince_wmain_adapter.cpp
+@@ -1,10 +1,11 @@
+ /*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+- * Use of this source code is governed by a BSD-style license and patent
+- * grant that can be found in the LICENSE file in the root of the source
+- * tree. All contributing project authors may be found in the AUTHORS
+- * file in the root of the source tree.
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+diff --git a/y4minput.c b/y4minput.c
+new file mode 100644
+index 0000000..895226d
+--- /dev/null
++++ b/y4minput.c
+@@ -0,0 +1,881 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ *
++ * Based on code from the OggTheora software codec source code,
++ * Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
++ */
++#include <stdlib.h>
++#include <string.h>
++#include "y4minput.h"
++
++static int y4m_parse_tags(y4m_input *_y4m,char *_tags){
++ int got_w;
++ int got_h;
++ int got_fps;
++ int got_interlace;
++ int got_par;
++ int got_chroma;
++ char *p;
++ char *q;
++ got_w=got_h=got_fps=got_interlace=got_par=got_chroma=0;
++ for(p=_tags;;p=q){
++ /*Skip any leading spaces.*/
++ while(*p==' ')p++;
++ /*If that's all we have, stop.*/
++ if(p[0]=='\0')break;
++ /*Find the end of this tag.*/
++ for(q=p+1;*q!='\0'&&*q!=' ';q++);
++ /*Process the tag.*/
++ switch(p[0]){
++ case 'W':{
++ if(sscanf(p+1,"%d",&_y4m->pic_w)!=1)return -1;
++ got_w=1;
++ }break;
++ case 'H':{
++ if(sscanf(p+1,"%d",&_y4m->pic_h)!=1)return -1;
++ got_h=1;
++ }break;
++ case 'F':{
++ if(sscanf(p+1,"%d:%d",&_y4m->fps_n,&_y4m->fps_d)!=2){
++ return -1;
++ }
++ got_fps=1;
++ }break;
++ case 'I':{
++ _y4m->interlace=p[1];
++ got_interlace=1;
++ }break;
++ case 'A':{
++ if(sscanf(p+1,"%d:%d",&_y4m->par_n,&_y4m->par_d)!=2){
++ return -1;
++ }
++ got_par=1;
++ }break;
++ case 'C':{
++ if(q-p>16)return -1;
++ memcpy(_y4m->chroma_type,p+1,q-p-1);
++ _y4m->chroma_type[q-p-1]='\0';
++ got_chroma=1;
++ }break;
++ /*Ignore unknown tags.*/
++ }
++ }
++ if(!got_w||!got_h||!got_fps)return -1;
++ if(!got_interlace)_y4m->interlace='?';
++ if(!got_par)_y4m->par_n=_y4m->par_d=0;
++ /*Chroma-type is not specified in older files, e.g., those generated by
++ mplayer.*/
++ if(!got_chroma)strcpy(_y4m->chroma_type,"420");
++ return 0;
++}
++
++
++
++/*All anti-aliasing filters in the following conversion functions are based on
++ one of two window functions:
++ The 6-tap Lanczos window (for down-sampling and shifts):
++ sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
++ 0, |t|>=3
++ The 4-tap Mitchell window (for up-sampling):
++ 7|t|^3-12|t|^2+16/3, |t|<1
++ -(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
++ 0, |t|>=2
++ The number of taps is intentionally kept small to reduce computational
++ overhead and limit ringing.
++
++ The taps from these filters are scaled so that their sum is 1, and the result
++ is scaled by 128 and rounded to integers to create a filter whose
++ intermediate values fit inside 16 bits.
++ Coefficients are rounded in such a way as to ensure their sum is still 128,
++ which is usually equivalent to normal rounding.
++
++ Conversions which require both horizontal and vertical filtering could
++ have these steps pipelined, for less memory consumption and better cache
++ performance, but we do them separately for simplicity.*/
++
++#define OC_MINI(_a,_b) ((_a)>(_b)?(_b):(_a))
++#define OC_MAXI(_a,_b) ((_a)<(_b)?(_b):(_a))
++#define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c)))
++
++/*420jpeg chroma samples are sited like:
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ 420mpeg2 chroma samples are sited like:
++ Y-------Y-------Y-------Y-------
++ | | | |
++ BR | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ BR | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ We use a resampling filter to shift the site locations one quarter pixel (at
++ the chroma plane's resolution) to the right.
++ The 4:2:2 modes look exactly the same, except there are twice as many chroma
++ lines, and they are vertically co-sited with the luma samples in both the
++ mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
++static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
++ const unsigned char *_src,int _c_w,int _c_h){
++ int pli;
++ int y;
++ int x;
++ for(y=0;y<_c_h;y++){
++ /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
++ window.*/
++ for(x=0;x<OC_MINI(_c_w,2);x++){
++ _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[0]-17*_src[OC_MAXI(x-1,0)]+
++ 114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+
++ _src[OC_MINI(x+3,_c_w-1)]+64)>>7,255);
++ }
++ for(;x<_c_w-3;x++){
++ _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+
++ 114*_src[x]+35*_src[x+1]-9*_src[x+2]+_src[x+3]+64)>>7,255);
++ }
++ for(;x<_c_w;x++){
++ _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+
++ 114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+
++ _src[_c_w-1]+64)>>7,255);
++ }
++ _dst+=_c_w;
++ _src+=_c_w;
++ }
++}
++
++/*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
++static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m,unsigned char *_dst,
++ unsigned char *_aux){
++ int c_w;
++ int c_h;
++ int c_sz;
++ int pli;
++ int y;
++ int x;
++ /*Skip past the luma data.*/
++ _dst+=_y4m->pic_w*_y4m->pic_h;
++ /*Compute the size of each chroma plane.*/
++ c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
++ c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
++ c_sz=c_w*c_h;
++ for(pli=1;pli<3;pli++){
++ y4m_42xmpeg2_42xjpeg_helper(_dst,_aux,c_w,c_h);
++ _dst+=c_sz;
++ _aux+=c_sz;
++ }
++}
++
++/*This format is only used for interlaced content, but is included for
++ completeness.
++
++ 420jpeg chroma samples are sited like:
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ 420paldv chroma samples are sited like:
++ YR------Y-------YR------Y-------
++ | | | |
++ | | | |
++ | | | |
++ YB------Y-------YB------Y-------
++ | | | |
++ | | | |
++ | | | |
++ YR------Y-------YR------Y-------
++ | | | |
++ | | | |
++ | | | |
++ YB------Y-------YB------Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ We use a resampling filter to shift the site locations one quarter pixel (at
++ the chroma plane's resolution) to the right.
++ Then we use another filter to move the C_r location down one quarter pixel,
++ and the C_b location up one quarter pixel.*/
++static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m,unsigned char *_dst,
++ unsigned char *_aux){
++ unsigned char *tmp;
++ int c_w;
++ int c_h;
++ int c_sz;
++ int pli;
++ int y;
++ int x;
++ /*Skip past the luma data.*/
++ _dst+=_y4m->pic_w*_y4m->pic_h;
++ /*Compute the size of each chroma plane.*/
++ c_w=(_y4m->pic_w+1)/2;
++ c_h=(_y4m->pic_h+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
++ c_sz=c_w*c_h;
++ tmp=_aux+2*c_sz;
++ for(pli=1;pli<3;pli++){
++ /*First do the horizontal re-sampling.
++ This is the same as the mpeg2 case, except that after the horizontal
++ case, we need to apply a second vertical filter.*/
++ y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h);
++ _aux+=c_sz;
++ switch(pli){
++ case 1:{
++ /*Slide C_b up a quarter-pel.
++ This is the same filter used above, but in the other order.*/
++ for(x=0;x<c_w;x++){
++ for(y=0;y<OC_MINI(c_h,3);y++){
++ _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[0]
++ -9*tmp[OC_MAXI(y-2,0)*c_w]+35*tmp[OC_MAXI(y-1,0)*c_w]
++ +114*tmp[y*c_w]-17*tmp[OC_MINI(y+1,c_h-1)*c_w]
++ +4*tmp[OC_MINI(y+2,c_h-1)*c_w]+64)>>7,255);
++ }
++ for(;y<c_h-2;y++){
++ _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w]
++ -9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]
++ -17*tmp[(y+1)*c_w]+4*tmp[(y+2)*c_w]+64)>>7,255);
++ }
++ for(;y<c_h;y++){
++ _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w]
++ -9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]
++ -17*tmp[OC_MINI(y+1,c_h-1)*c_w]+4*tmp[(c_h-1)*c_w]+64)>>7,255);
++ }
++ _dst++;
++ tmp++;
++ }
++ _dst+=c_sz-c_w;
++ tmp-=c_w;
++ }break;
++ case 2:{
++ /*Slide C_r down a quarter-pel.
++ This is the same as the horizontal filter.*/
++ for(x=0;x<c_w;x++){
++ for(y=0;y<OC_MINI(c_h,2);y++){
++ _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[0]
++ -17*tmp[OC_MAXI(y-1,0)*c_w]+114*tmp[y*c_w]
++ +35*tmp[OC_MINI(y+1,c_h-1)*c_w]-9*tmp[OC_MINI(y+2,c_h-1)*c_w]
++ +tmp[OC_MINI(y+3,c_h-1)*c_w]+64)>>7,255);
++ }
++ for(;y<c_h-3;y++){
++ _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w]
++ -17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[(y+1)*c_w]
++ -9*tmp[(y+2)*c_w]+tmp[(y+3)*c_w]+64)>>7,255);
++ }
++ for(;y<c_h;y++){
++ _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w]
++ -17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[OC_MINI(y+1,c_h-1)*c_w]
++ -9*tmp[OC_MINI(y+2,c_h-1)*c_w]+tmp[(c_h-1)*c_w]+64)>>7,255);
++ }
++ _dst++;
++ tmp++;
++ }
++ }break;
++ }
++ /*For actual interlaced material, this would have to be done separately on
++ each field, and the shift amounts would be different.
++ C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
++ C_b up 1/8 in the bottom field.
++ The corresponding filters would be:
++ Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
++ Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
++ }
++}
++
++/*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
++ This is used as a helper by several converation routines.*/
++static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
++ const unsigned char *_src,int _c_w,int _c_h){
++ int y;
++ int x;
++ /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
++ for(x=0;x<_c_w;x++){
++ for(y=0;y<OC_MINI(_c_h,2);y+=2){
++ _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(64*_src[0]
++ +78*_src[OC_MINI(1,_c_h-1)*_c_w]
++ -17*_src[OC_MINI(2,_c_h-1)*_c_w]
++ +3*_src[OC_MINI(3,_c_h-1)*_c_w]+64)>>7,255);
++ }
++ for(;y<_c_h-3;y+=2){
++ _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]+_src[(y+3)*_c_w])
++ -17*(_src[(y-1)*_c_w]+_src[(y+2)*_c_w])
++ +78*(_src[y*_c_w]+_src[(y+1)*_c_w])+64)>>7,255);
++ }
++ for(;y<_c_h;y+=2){
++ _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]
++ +_src[(_c_h-1)*_c_w])-17*(_src[(y-1)*_c_w]
++ +_src[OC_MINI(y+2,_c_h-1)*_c_w])
++ +78*(_src[y*_c_w]+_src[OC_MINI(y+1,_c_h-1)*_c_w])+64)>>7,255);
++ }
++ _src++;
++ _dst++;
++ }
++}
++
++/*420jpeg chroma samples are sited like:
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ 422jpeg chroma samples are sited like:
++ Y---BR--Y-------Y---BR--Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y---BR--Y-------Y---BR--Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y---BR--Y-------Y---BR--Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y---BR--Y-------Y---BR--Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ We use a resampling filter to decimate the chroma planes by two in the
++ vertical direction.*/
++static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m,unsigned char *_dst,
++ unsigned char *_aux){
++ int c_w;
++ int c_h;
++ int c_sz;
++ int dst_c_w;
++ int dst_c_h;
++ int dst_c_sz;
++ int tmp_sz;
++ int pic_sz;
++ int pli;
++ /*Skip past the luma data.*/
++ _dst+=_y4m->pic_w*_y4m->pic_h;
++ /*Compute the size of each chroma plane.*/
++ c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
++ c_h=_y4m->pic_h;
++ dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
++ dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
++ c_sz=c_w*c_h;
++ dst_c_sz=dst_c_w*dst_c_h;
++ for(pli=1;pli<3;pli++){
++ y4m_422jpeg_420jpeg_helper(_dst,_aux,c_w,c_h);
++ _aux+=c_sz;
++ _dst+=dst_c_sz;
++ }
++}
++
++/*420jpeg chroma samples are sited like:
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ 422 chroma samples are sited like:
++ YBR-----Y-------YBR-----Y-------
++ | | | |
++ | | | |
++ | | | |
++ YBR-----Y-------YBR-----Y-------
++ | | | |
++ | | | |
++ | | | |
++ YBR-----Y-------YBR-----Y-------
++ | | | |
++ | | | |
++ | | | |
++ YBR-----Y-------YBR-----Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ We use a resampling filter to shift the original site locations one quarter
++ pixel (at the original chroma resolution) to the right.
++ Then we use a second resampling filter to decimate the chroma planes by two
++ in the vertical direction.*/
++static void y4m_convert_422_420jpeg(y4m_input *_y4m,unsigned char *_dst,
++ unsigned char *_aux){
++ unsigned char *tmp;
++ int c_w;
++ int c_h;
++ int c_sz;
++ int dst_c_w;
++ int dst_c_h;
++ int dst_c_sz;
++ int pli;
++ int y;
++ int x;
++ /*Skip past the luma data.*/
++ _dst+=_y4m->pic_w*_y4m->pic_h;
++ /*Compute the size of each chroma plane.*/
++ c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
++ c_h=_y4m->pic_h;
++ dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
++ c_sz=c_w*c_h;
++ dst_c_sz=c_w*dst_c_h;
++ tmp=_aux+2*c_sz;
++ for(pli=1;pli<3;pli++){
++ /*In reality, the horizontal and vertical steps could be pipelined, for
++ less memory consumption and better cache performance, but we do them
++ separately for simplicity.*/
++ /*First do horizontal filtering (convert to 422jpeg)*/
++ y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h);
++ /*Now do the vertical filtering.*/
++ y4m_422jpeg_420jpeg_helper(_dst,tmp,c_w,c_h);
++ _aux+=c_sz;
++ _dst+=dst_c_sz;
++ }
++}
++
++/*420jpeg chroma samples are sited like:
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | BR | | BR |
++ | | | |
++ Y-------Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ 411 chroma samples are sited like:
++ YBR-----Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ YBR-----Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ YBR-----Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++ YBR-----Y-------Y-------Y-------
++ | | | |
++ | | | |
++ | | | |
++
++ We use a filter to resample at site locations one eighth pixel (at the source
++ chroma plane's horizontal resolution) and five eighths of a pixel to the
++ right.
++ Then we use another filter to decimate the planes by 2 in the vertical
++ direction.*/
++static void y4m_convert_411_420jpeg(y4m_input *_y4m,unsigned char *_dst,
++ unsigned char *_aux){
++ unsigned char *tmp;
++ int c_w;
++ int c_h;
++ int c_sz;
++ int dst_c_w;
++ int dst_c_h;
++ int dst_c_sz;
++ int tmp_sz;
++ int pli;
++ int y;
++ int x;
++ /*Skip past the luma data.*/
++ _dst+=_y4m->pic_w*_y4m->pic_h;
++ /*Compute the size of each chroma plane.*/
++ c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
++ c_h=_y4m->pic_h;
++ dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
++ dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
++ c_sz=c_w*c_h;
++ dst_c_sz=dst_c_w*dst_c_h;
++ tmp_sz=dst_c_w*c_h;
++ tmp=_aux+2*c_sz;
++ for(pli=1;pli<3;pli++){
++ /*In reality, the horizontal and vertical steps could be pipelined, for
++ less memory consumption and better cache performance, but we do them
++ separately for simplicity.*/
++ /*First do horizontal filtering (convert to 422jpeg)*/
++ for(y=0;y<c_h;y++){
++ /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
++ 4-tap Mitchell window.*/
++ for(x=0;x<OC_MINI(c_w,1);x++){
++ tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(111*_aux[0]
++ +18*_aux[OC_MINI(1,c_w-1)]-_aux[OC_MINI(2,c_w-1)]+64)>>7,255);
++ tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(47*_aux[0]
++ +86*_aux[OC_MINI(1,c_w-1)]-5*_aux[OC_MINI(2,c_w-1)]+64)>>7,255);
++ }
++ for(;x<c_w-2;x++){
++ tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x]
++ +18*_aux[x+1]-_aux[x+2]+64)>>7,255);
++ tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x]
++ +86*_aux[x+1]-5*_aux[x+2]+64)>>7,255);
++ }
++ for(;x<c_w;x++){
++ tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x]
++ +18*_aux[OC_MINI(x+1,c_w-1)]-_aux[c_w-1]+64)>>7,255);
++ if((x<<1|1)<dst_c_w){
++ tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x]
++ +86*_aux[OC_MINI(x+1,c_w-1)]-5*_aux[c_w-1]+64)>>7,255);
++ }
++ }
++ tmp+=dst_c_w;
++ _aux+=c_w;
++ }
++ tmp-=tmp_sz;
++ /*Now do the vertical filtering.*/
++ y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h);
++ _dst+=dst_c_sz;
++ }
++}
++
++/*Convert 444 to 420jpeg.*/
++static void y4m_convert_444_420jpeg(y4m_input *_y4m,unsigned char *_dst,
++ unsigned char *_aux){
++ unsigned char *tmp;
++ int c_w;
++ int c_h;
++ int c_sz;
++ int dst_c_w;
++ int dst_c_h;
++ int dst_c_sz;
++ int tmp_sz;
++ int pli;
++ int y;
++ int x;
++ /*Skip past the luma data.*/
++ _dst+=_y4m->pic_w*_y4m->pic_h;
++ /*Compute the size of each chroma plane.*/
++ c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
++ c_h=_y4m->pic_h;
++ dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
++ dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
++ c_sz=c_w*c_h;
++ dst_c_sz=dst_c_w*dst_c_h;
++ tmp_sz=dst_c_w*c_h;
++ tmp=_aux+2*c_sz;
++ for(pli=1;pli<3;pli++){
++ /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
++ for(y=0;y<c_h;y++){
++ for(x=0;x<OC_MINI(c_w,2);x+=2){
++ tmp[x>>1]=OC_CLAMPI(0,(64*_aux[0]+78*_aux[OC_MINI(1,c_w-1)]
++ -17*_aux[OC_MINI(2,c_w-1)]
++ +3*_aux[OC_MINI(3,c_w-1)]+64)>>7,255);
++ }
++ for(;x<c_w-3;x+=2){
++ tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[x+3])
++ -17*(_aux[x-1]+_aux[x+2])+78*(_aux[x]+_aux[x+1])+64)>>7,255);
++ }
++ for(;x<c_w;x+=2){
++ tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[c_w-1])-
++ 17*(_aux[x-1]+_aux[OC_MINI(x+2,c_w-1)])+
++ 78*(_aux[x]+_aux[OC_MINI(x+1,c_w-1)])+64)>>7,255);
++ }
++ tmp+=dst_c_w;
++ _aux+=c_w;
++ }
++ tmp-=tmp_sz;
++ /*Now do the vertical filtering.*/
++ y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h);
++ _dst+=dst_c_sz;
++ }
++}
++
++/*The image is padded with empty chroma components at 4:2:0.*/
++static void y4m_convert_mono_420jpeg(y4m_input *_y4m,unsigned char *_dst,
++ unsigned char *_aux){
++ int c_sz;
++ _dst+=_y4m->pic_w*_y4m->pic_h;
++ c_sz=((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)*
++ ((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v);
++ memset(_dst,128,c_sz*2);
++}
++
++/*No conversion function needed.*/
++static void y4m_convert_null(y4m_input *_y4m,unsigned char *_dst,
++ unsigned char *_aux){
++}
++
++int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip){
++ char buffer[80];
++ int ret;
++ int i;
++ /*Read until newline, or 80 cols, whichever happens first.*/
++ for(i=0;i<79;i++){
++ if(_nskip>0){
++ buffer[i]=*_skip++;
++ _nskip--;
++ }
++ else{
++ ret=fread(buffer+i,1,1,_fin);
++ if(ret<1)return -1;
++ }
++ if(buffer[i]=='\n')break;
++ }
++ /*We skipped too much header data.*/
++ if(_nskip>0)return -1;
++ if(i==79){
++ fprintf(stderr,"Error parsing header; not a YUV2MPEG2 file?\n");
++ return -1;
++ }
++ buffer[i]='\0';
++ if(memcmp(buffer,"YUV4MPEG",8)){
++ fprintf(stderr,"Incomplete magic for YUV4MPEG file.\n");
++ return -1;
++ }
++ if(buffer[8]!='2'){
++ fprintf(stderr,"Incorrect YUV input file version; YUV4MPEG2 required.\n");
++ }
++ ret=y4m_parse_tags(_y4m,buffer+5);
++ if(ret<0){
++ fprintf(stderr,"Error parsing YUV4MPEG2 header.\n");
++ return ret;
++ }
++ if(_y4m->interlace=='?'){
++ fprintf(stderr,"Warning: Input video interlacing format unknown; "
++ "assuming progressive scan.\n");
++ }
++ else if(_y4m->interlace!='p'){
++ fprintf(stderr,"Input video is interlaced; "
++ "Only progressive scan handled.\n");
++ return -1;
++ }
++ if(strcmp(_y4m->chroma_type,"420")==0||
++ strcmp(_y4m->chroma_type,"420jpeg")==0){
++ _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h
++ +2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
++ /*Natively supported: no conversion required.*/
++ _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0;
++ _y4m->convert=y4m_convert_null;
++ }
++ else if(strcmp(_y4m->chroma_type,"420mpeg2")==0){
++ _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
++ /*Chroma filter required: read into the aux buf first.*/
++ _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=
++ 2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
++ _y4m->convert=y4m_convert_42xmpeg2_42xjpeg;
++ }
++ else if(strcmp(_y4m->chroma_type,"420paldv")==0){
++ _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
++ /*Chroma filter required: read into the aux buf first.
++ We need to make two filter passes, so we need some extra space in the
++ aux buffer.*/
++ _y4m->aux_buf_sz=3*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
++ _y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
++ _y4m->convert=y4m_convert_42xpaldv_42xjpeg;
++ }
++ else if(strcmp(_y4m->chroma_type,"422jpeg")==0){
++ _y4m->src_c_dec_h=_y4m->dst_c_dec_h=2;
++ _y4m->src_c_dec_v=1;
++ _y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
++ /*Chroma filter required: read into the aux buf first.*/
++ _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h;
++ _y4m->convert=y4m_convert_422jpeg_420jpeg;
++ }
++ else if(strcmp(_y4m->chroma_type,"422")==0){
++ _y4m->src_c_dec_h=_y4m->dst_c_dec_h=2;
++ _y4m->src_c_dec_v=1;
++ _y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
++ /*Chroma filter required: read into the aux buf first.
++ We need to make two filter passes, so we need some extra space in the
++ aux buffer.*/
++ _y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h;
++ _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
++ _y4m->convert=y4m_convert_422_420jpeg;
++ }
++ else if(strcmp(_y4m->chroma_type,"411")==0){
++ _y4m->src_c_dec_h=4;
++ _y4m->dst_c_dec_h=2;
++ _y4m->src_c_dec_v=1;
++ _y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
++ /*Chroma filter required: read into the aux buf first.
++ We need to make two filter passes, so we need some extra space in the
++ aux buffer.*/
++ _y4m->aux_buf_read_sz=2*((_y4m->pic_w+3)/4)*_y4m->pic_h;
++ _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
++ _y4m->convert=y4m_convert_411_420jpeg;
++ }
++ else if(strcmp(_y4m->chroma_type,"444")==0){
++ _y4m->src_c_dec_h=1;
++ _y4m->dst_c_dec_h=2;
++ _y4m->src_c_dec_v=1;
++ _y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
++ /*Chroma filter required: read into the aux buf first.
++ We need to make two filter passes, so we need some extra space in the
++ aux buffer.*/
++ _y4m->aux_buf_read_sz=2*_y4m->pic_w*_y4m->pic_h;
++ _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
++ _y4m->convert=y4m_convert_444_420jpeg;
++ }
++ else if(strcmp(_y4m->chroma_type,"444alpha")==0){
++ _y4m->src_c_dec_h=1;
++ _y4m->dst_c_dec_h=2;
++ _y4m->src_c_dec_v=1;
++ _y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
++ /*Chroma filter required: read into the aux buf first.
++ We need to make two filter passes, so we need some extra space in the
++ aux buffer.
++ The extra plane also gets read into the aux buf.
++ It will be discarded.*/
++ _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=3*_y4m->pic_w*_y4m->pic_h;
++ _y4m->convert=y4m_convert_444_420jpeg;
++ }
++ else if(strcmp(_y4m->chroma_type,"mono")==0){
++ _y4m->src_c_dec_h=_y4m->src_c_dec_v=0;
++ _y4m->dst_c_dec_h=_y4m->dst_c_dec_v=2;
++ _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
++ /*No extra space required, but we need to clear the chroma planes.*/
++ _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0;
++ _y4m->convert=y4m_convert_mono_420jpeg;
++ }
++ else{
++ fprintf(stderr,"Unknown chroma sampling type: %s\n",_y4m->chroma_type);
++ return -1;
++ }
++ /*The size of the final frame buffers is always computed from the
++ destination chroma decimation type.*/
++ _y4m->dst_buf_sz=_y4m->pic_w*_y4m->pic_h
++ +2*((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)*
++ ((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v);
++ _y4m->dst_buf=(unsigned char *)malloc(_y4m->dst_buf_sz);
++ _y4m->aux_buf=(unsigned char *)malloc(_y4m->aux_buf_sz);
++ return 0;
++}
++
++void y4m_input_close(y4m_input *_y4m){
++ free(_y4m->dst_buf);
++ free(_y4m->aux_buf);
++}
++
++int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *_img){
++ char frame[6];
++ int pic_sz;
++ int frame_c_w;
++ int frame_c_h;
++ int c_w;
++ int c_h;
++ int c_sz;
++ int ret;
++ /*Read and skip the frame header.*/
++ ret=fread(frame,1,6,_fin);
++ if(ret<6)return 0;
++ if(memcmp(frame,"FRAME",5)){
++ fprintf(stderr,"Loss of framing in Y4M input data\n");
++ return -1;
++ }
++ if(frame[5]!='\n'){
++ char c;
++ int j;
++ for(j=0;j<79&&fread(&c,1,1,_fin)&&c!='\n';j++);
++ if(j==79){
++ fprintf(stderr,"Error parsing Y4M frame header\n");
++ return -1;
++ }
++ }
++ /*Read the frame data that needs no conversion.*/
++ if(fread(_y4m->dst_buf,1,_y4m->dst_buf_read_sz,_fin)!=_y4m->dst_buf_read_sz){
++ fprintf(stderr,"Error reading Y4M frame data.\n");
++ return -1;
++ }
++ /*Read the frame data that does need conversion.*/
++ if(fread(_y4m->aux_buf,1,_y4m->aux_buf_read_sz,_fin)!=_y4m->aux_buf_read_sz){
++ fprintf(stderr,"Error reading Y4M frame data.\n");
++ return -1;
++ }
++ /*Now convert the just read frame.*/
++ (*_y4m->convert)(_y4m,_y4m->dst_buf,_y4m->aux_buf);
++ /*Fill in the frame buffer pointers.
++ We don't use vpx_img_wrap() because it forces padding for odd picture
++ sizes, which would require a separate fread call for every row.*/
++ memset(_img,0,sizeof(*_img));
++ /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
++ _img->fmt=IMG_FMT_I420;
++ _img->w=_img->d_w=_y4m->pic_w;
++ _img->h=_img->d_h=_y4m->pic_h;
++ /*This is hard-coded to 4:2:0 for now, as that's all VP8 supports.*/
++ _img->x_chroma_shift=1;
++ _img->y_chroma_shift=1;
++ _img->bps=12;
++ /*Set up the buffer pointers.*/
++ pic_sz=_y4m->pic_w*_y4m->pic_h;
++ c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
++ c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
++ c_sz=c_w*c_h;
++ _img->stride[PLANE_Y]=_y4m->pic_w;
++ _img->stride[PLANE_U]=_img->stride[PLANE_V]=c_w;
++ _img->planes[PLANE_Y]=_y4m->dst_buf;
++ _img->planes[PLANE_U]=_y4m->dst_buf+pic_sz;
++ _img->planes[PLANE_V]=_y4m->dst_buf+pic_sz+c_sz;
++ return 0;
++}
+diff --git a/y4minput.h b/y4minput.h
+new file mode 100644
+index 0000000..e3f9304
+--- /dev/null
++++ b/y4minput.h
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ *
++ * Based on code from the OggTheora software codec source code,
++ * Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
++ */
++#if !defined(_y4minput_H)
++# define _y4minput_H (1)
++# include <stdio.h>
++# include "vpx/vpx_image.h"
++
++
++
++typedef struct y4m_input y4m_input;
++
++
++
++/*The function used to perform chroma conversion.*/
++typedef void (*y4m_convert_func)(y4m_input *_y4m,
++ unsigned char *_dst,unsigned char *_src);
++
++
++
++struct y4m_input{
++ int pic_w;
++ int pic_h;
++ int fps_n;
++ int fps_d;
++ int par_n;
++ int par_d;
++ char interlace;
++ int src_c_dec_h;
++ int src_c_dec_v;
++ int dst_c_dec_h;
++ int dst_c_dec_v;
++ char chroma_type[16];
++ /*The size of each converted frame buffer.*/
++ size_t dst_buf_sz;
++ /*The amount to read directly into the converted frame buffer.*/
++ size_t dst_buf_read_sz;
++ /*The size of the auxilliary buffer.*/
++ size_t aux_buf_sz;
++ /*The amount to read into the auxilliary buffer.*/
++ size_t aux_buf_read_sz;
++ y4m_convert_func convert;
++ unsigned char *dst_buf;
++ unsigned char *aux_buf;
++};
++
++int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip);
++void y4m_input_close(y4m_input *_y4m);
++int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *img);
++
++#endif
diff --git a/main/libwebp/APKBUILD b/main/libwebp/APKBUILD
new file mode 100644
index 0000000000..7ff7933211
--- /dev/null
+++ b/main/libwebp/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer:
+pkgname=libwebp
+pkgver=0.1.2
+pkgrel=1
+pkgdesc="Libraries for working with WebP images"
+url="http://code.google.com/speed/webp/index.html"
+arch="all"
+license="BSD"
+depends=
+depends_dev=
+makedepends="libpng-dev jpeg-dev automake autoconf libtool"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://webp.googlecode.com/files/libwebp-$pkgver.tar.gz"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ cd "$_builddir"
+ sh autogen.sh
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ mkdir -p "$pkgdir"/usr/share/doc/$pkgname
+ install -Dm644 PATENTS README "$pkgdir"/usr/share/doc/$pkgname
+}
+
+md5sums="5534f6e3c8b9f5851a9a5b56bf78f2b0 libwebp-0.1.2.tar.gz"
diff --git a/main/libwnck/APKBUILD b/main/libwnck/APKBUILD
new file mode 100644
index 0000000000..27273722ce
--- /dev/null
+++ b/main/libwnck/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libwnck
+pkgver=2.30.6
+pkgrel=3
+pkgdesc="Window Navigator Construction Kit"
+url="http://www.gnome.org/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig gtk+-dev startup-notification-dev libxres-dev intltool
+ gettext-dev libiconv-dev expat-dev libsm-dev e2fsprogs-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev gtk+-dev libx11-dev pango-dev cairo-dev
+ startup-notification-dev libxres-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="323127c546d4b6796ae569f3da0892ab libwnck-2.30.6.tar.bz2"
diff --git a/main/libx11/APKBUILD b/main/libx11/APKBUILD
new file mode 100644
index 0000000000..1f028a708c
--- /dev/null
+++ b/main/libx11/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libx11
+pkgver=1.4.3
+pkgrel=3
+pkgdesc="X11 client-side library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom:XFREE86"
+depends=
+subpackages="$pkgname-dev $pkgname-doc"
+depends_dev="libxcb-dev xproto xextproto xf86bigfontproto xtrans kbproto
+ inputproto"
+makedepends="$depends_dev util-macros pkgconfig"
+source="http://xorg.freedesktop.org/releases/individual/lib/libX11-$pkgver.tar.bz2
+ "
+
+build() {
+ cd "$srcdir"/libX11-$pkgver
+ ./configure --prefix=/usr \
+ --with-xcb || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/libX11-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+md5sums="85e942627aaa020813e0eb8433353563 libX11-1.4.3.tar.bz2"
diff --git a/main/libxau/APKBUILD b/main/libxau/APKBUILD
new file mode 100644
index 0000000000..999b7dcc89
--- /dev/null
+++ b/main/libxau/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxau
+pkgver=1.0.6
+pkgrel=2
+pkgdesc="X11 authorisation library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig xproto"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXau-$pkgver.tar.bz2"
+
+depends_dev="xproto"
+
+build() {
+ cd "$srcdir"/libXau-$pkgver
+ ./configure --prefix=/usr --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXau-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -m755 -d "$pkgdir"/usr/share/licenses/$pkgname
+ install -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING || return 1
+}
+md5sums="4a2cbd83727682f9ee1c1e719bac6adb libXau-1.0.6.tar.bz2"
diff --git a/main/libxcb/APKBUILD b/main/libxcb/APKBUILD
new file mode 100644
index 0000000000..5b6ef91190
--- /dev/null
+++ b/main/libxcb/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxcb
+pkgver=1.7
+pkgrel=2
+pkgdesc="X11 client-side library"
+url="http://xcb.freedesktop.org/"
+arch="all"
+license="custom"
+depends="xcb-proto"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="libxdmcp-dev libxau-dev libxslt libpthread-stubs pkgconfig python"
+source="http://xcb.freedesktop.org/dist/$pkgname-$pkgver.tar.bz2
+ "
+depends_dev="libpthread-stubs libxau-dev libxdmcp-dev"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-xinput || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="925699df361b99491165ebc12068056b libxcb-1.7.tar.bz2"
diff --git a/main/libxcomposite/APKBUILD b/main/libxcomposite/APKBUILD
new file mode 100644
index 0000000000..461450ee6b
--- /dev/null
+++ b/main/libxcomposite/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxcomposite
+pkgver=0.4.3
+pkgrel=2
+pkgdesc="X11 Composite extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxfixes-dev libxext-dev compositeproto"
+source="http://xorg.freedesktop.org//releases/individual/lib/libXcomposite-$pkgver.tar.bz2"
+
+depends_dev="xproto compositeproto libxfixes-dev libx11-dev libxext-dev"
+_builddir="$srcdir"/libXcomposite-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="a60e0b5c276d0aa9e2d3b982c98f61c8 libXcomposite-0.4.3.tar.bz2"
diff --git a/main/libxcursor/APKBUILD b/main/libxcursor/APKBUILD
new file mode 100644
index 0000000000..2740c1bd88
--- /dev/null
+++ b/main/libxcursor/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxcursor
+pkgver=1.1.11
+pkgrel=2
+pkgdesc="X cursor management library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxfixes-dev libx11-dev libxrender-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXcursor-$pkgver.tar.bz2"
+
+depends_dev="xproto libx11-dev libxrender-dev libxfixes-dev"
+build() {
+ cd "$srcdir"/libXcursor-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXcursor-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="866ed46f7e0d85b8c0003cebbb78a4af libXcursor-1.1.11.tar.bz2"
diff --git a/main/libxdamage/APKBUILD b/main/libxdamage/APKBUILD
new file mode 100644
index 0000000000..80e40989f5
--- /dev/null
+++ b/main/libxdamage/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxdamage
+pkgver=1.1.3
+pkgrel=2
+pkgdesc="X11 damaged region extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig libxfixes-dev damageproto xextproto"
+subpackages="$pkgname-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXdamage-$pkgver.tar.bz2"
+
+depends_dev="xproto damageproto libxfixes-dev libx11-dev fixesproto"
+build() {
+ cd "$srcdir"/libXdamage-$pkgver
+ ./configure --prefix=/usr --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXdamage-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="44774e1a065158b52f1a0da5100cebec libXdamage-1.1.3.tar.bz2"
diff --git a/main/libxdmcp/APKBUILD b/main/libxdmcp/APKBUILD
new file mode 100644
index 0000000000..35f2a90c19
--- /dev/null
+++ b/main/libxdmcp/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxdmcp
+pkgver=1.1.0
+pkgrel=2
+pkgdesc="X11 Display Manager Control Protocol library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="xproto pkgconfig"
+subpackages="$pkgname-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXdmcp-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/libXdmcp-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXdmcp-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="762b6bbaff7b7d0831ddb4f072f939a5 libXdmcp-1.1.0.tar.bz2"
diff --git a/main/libxext/APKBUILD b/main/libxext/APKBUILD
new file mode 100644
index 0000000000..41cb44f560
--- /dev/null
+++ b/main/libxext/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxext
+pkgver=1.3.0
+pkgrel=1
+pkgdesc="X11 miscellaneous extensions library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig xproto xextproto libx11-dev libxau-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXext-$pkgver.tar.bz2"
+
+depends_dev="xextproto libx11-dev libxau-dev"
+build() {
+ cd "$srcdir"/libXext-$pkgver
+ ./configure --prefix=/usr --sysconfdir=/etc
+ make
+}
+
+package() {
+ cd "$srcdir"/libXext-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="161d200b690ace818db1cc7537e70ba9 libXext-1.3.0.tar.bz2"
diff --git a/main/libxfce4ui/APKBUILD b/main/libxfce4ui/APKBUILD
new file mode 100644
index 0000000000..6626d681f9
--- /dev/null
+++ b/main/libxfce4ui/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxfce4ui
+pkgver=4.8.0
+pkgrel=2
+pkgdesc="Widgets library for the Xfce desktop environment"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+replaces="libxfcegui4"
+makedepends="gtk+-dev xfconf-dev libxfce4util-dev startup-notification-dev"
+source="http://archive.xfce.org/src/xfce/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+depends_dev="gtk+-dev libxfce4util-dev xfconf-dev startup-notification-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="df9acb3328dff905bd0777b84532b69f libxfce4ui-4.8.0.tar.bz2"
diff --git a/main/libxfce4util/APKBUILD b/main/libxfce4util/APKBUILD
new file mode 100644
index 0000000000..ec75d245e3
--- /dev/null
+++ b/main/libxfce4util/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxfce4util
+pkgver=4.8.1
+pkgrel=1
+pkgdesc="Basic utility non-GUI functions for Xfce"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig glib-dev gettext-dev libiconv-dev intltool"
+source="http://archive.xfce.org/src/xfce/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="2be3af4c7db5ad293a7525e1021e6f0f libxfce4util-4.8.1.tar.bz2"
diff --git a/main/libxfcegui4/APKBUILD b/main/libxfcegui4/APKBUILD
new file mode 100644
index 0000000000..e501b10fe0
--- /dev/null
+++ b/main/libxfcegui4/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxfcegui4
+pkgver=4.8.1
+pkgrel=2
+pkgdesc="Basic GUI functions for Xfce"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="gtk+-dev xfconf-dev libxfce4util-dev startup-notification-dev
+ libglade-dev"
+source="http://archive.xfce.org/src/xfce/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+depends_dev="gtk+-dev libxfce4util-dev xfconf-dev startup-notification-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="ca0cdeff99f1732307d0fc0672d382ef libxfcegui4-4.8.1.tar.bz2"
diff --git a/main/libxfixes/APKBUILD b/main/libxfixes/APKBUILD
new file mode 100644
index 0000000000..df130f988e
--- /dev/null
+++ b/main/libxfixes/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxfixes
+pkgver=5.0
+pkgrel=1
+pkgdesc="X11 miscellaneous 'fixes' extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig xproto libx11-dev fixesproto xextproto"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXfixes-$pkgver.tar.bz2"
+
+depends_dev="xproto fixesproto libx11-dev"
+_builddir="$srcdir"/libXfixes-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --sysconfdir=/etc --build=${CHOST} --host=${CHOST}
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="678071bd7f9f7467e2fc712d81022318 libXfixes-5.0.tar.bz2"
diff --git a/main/libxfont/APKBUILD b/main/libxfont/APKBUILD
new file mode 100644
index 0000000000..01e094baa6
--- /dev/null
+++ b/main/libxfont/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxfont
+pkgver=1.4.3
+pkgrel=2
+pkgdesc="X11 font rasterisation library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libfontenc-dev freetype-dev fontsproto xproto xtrans
+ zlib-dev"
+source="http://xorg.freedesktop.org/archive/individual/lib/libXfont-$pkgver.tar.bz2"
+
+depends_dev="xproto fontsproto libfontenc-dev freetype-dev"
+
+build() {
+ cd "$srcdir"/libXfont-$pkgver
+ ./configure --prefix=/usr --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXfont-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="6fb689cfe13d8d9460f4abb5bd88588d libXfont-1.4.3.tar.bz2"
diff --git a/main/libxft/APKBUILD b/main/libxft/APKBUILD
new file mode 100644
index 0000000000..b6adfa5120
--- /dev/null
+++ b/main/libxft/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxft
+pkgver=2.2.0
+pkgrel=2
+pkgdesc="FreeType-based font drawing library for X"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+depends_dev="xproto libxrender-dev fontconfig-dev freetype-dev zlib-dev"
+makedepends="$depends_dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXft-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/libXft-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXft-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="cce3c327258116493b753f157e0360c7 libXft-2.2.0.tar.bz2"
diff --git a/main/libxi/APKBUILD b/main/libxi/APKBUILD
new file mode 100644
index 0000000000..ec0ccb7055
--- /dev/null
+++ b/main/libxi/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxi
+pkgver=1.4.2
+pkgrel=1
+pkgdesc="X11 Input extension library"
+url="http://xorg.freedesktop.org"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="
+ inputproto
+ libx11-dev
+ libxext-dev
+ pkgconfig
+ xextproto
+ xproto
+ "
+source="http://xorg.freedesktop.org/releases/individual/lib/libXi-$pkgver.tar.bz2"
+
+depends_dev="inputproto libx11-dev libxext-dev"
+
+build ()
+{
+ cd "$srcdir"/libXi-$pkgver
+ ./configure --prefix=/usr --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXi-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="3d14f7bfc4a4335cf0144de9b67a5444 libXi-1.4.2.tar.bz2"
diff --git a/main/libxinerama/APKBUILD b/main/libxinerama/APKBUILD
new file mode 100644
index 0000000000..98f7e1b131
--- /dev/null
+++ b/main/libxinerama/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxinerama
+pkgver=1.1.1
+pkgrel=2
+pkgdesc="X11 Xinerama extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxext-dev libx11-dev xineramaproto"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXinerama-$pkgver.tar.bz2"
+depends_dev="xineramaproto libx11-dev libxext-dev"
+
+build() {
+ cd "$srcdir"/libXinerama-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXinerama-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="ecd4839ad01f6f637c6fb5327207f89b libXinerama-1.1.1.tar.bz2"
diff --git a/main/libxkbfile/APKBUILD b/main/libxkbfile/APKBUILD
new file mode 100644
index 0000000000..9bca99aa65
--- /dev/null
+++ b/main/libxkbfile/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxkbfile
+pkgver=1.0.7
+pkgrel=2
+pkgdesc="X11 keyboard file manipulation library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig libx11-dev"
+subpackages="$pkgname-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="libx11-dev kbproto"
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 "$srcdir"/$pkgname-$pkgver/COPYING \
+ "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="59b4fe0bdf8d9b05e45b59e8fe9e7516 libxkbfile-1.0.7.tar.bz2"
diff --git a/main/libxkbui/APKBUILD b/main/libxkbui/APKBUILD
new file mode 100644
index 0000000000..b9cffba90c
--- /dev/null
+++ b/main/libxkbui/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxkbui
+pkgver=1.0.2
+pkgrel=6
+pkgdesc="X11 keyboard UI presentation library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev"
+depends=
+makedepends="pkgconfig libxt-dev libx11-dev libsm-dev libice-dev libxkbfile-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="libx11-dev xproto libxt-dev"
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="1143e456f7429e18e88f2eadb2f2b6b1 libxkbui-1.0.2.tar.bz2"
diff --git a/main/libxklavier/APKBUILD b/main/libxklavier/APKBUILD
new file mode 100644
index 0000000000..4c211785c0
--- /dev/null
+++ b/main/libxklavier/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxklavier
+pkgver=5.1
+pkgrel=1
+pkgdesc="High-level API for X Keyboard Extension"
+url="http://gswitchit.sourceforge.net"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="xkeyboard-config iso-codes"
+makedepends="pkgconfig libxkbfile-dev libxml2-dev glib-dev libxi-dev iso-codes
+ gettext-dev libiconv-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/$pkgver/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="libxml2-dev glib-dev gettext-dev libxkbfile-dev"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-xkb-base=/usr/share/X11/xkb \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="cbc2a760827c20aef61eb7b18a6ce598 libxklavier-5.1.tar.bz2"
diff --git a/main/libxml2/APKBUILD b/main/libxml2/APKBUILD
new file mode 100644
index 0000000000..f7e4128856
--- /dev/null
+++ b/main/libxml2/APKBUILD
@@ -0,0 +1,58 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=libxml2
+pkgver=2.7.8
+pkgrel=5
+pkgdesc="XML parsing library, version 2"
+url="http://www.xmlsoft.org/"
+arch="all"
+license="MIT"
+depends=
+depends_dev="zlib-dev python-dev"
+makedepends="zlib-dev python-dev"
+subpackages="$pkgname-doc $pkgname-dev py-$pkgname:py $pkgname-utils"
+source="ftp://ftp.xmlsoft.org/${pkgname}/${pkgname}-${pkgver}.tar.gz
+ largefile64.patch"
+
+options="!strip"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ for _i in "$srcdir"/*.patch; do
+ patch -p1 -i "$_i"
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+py() {
+ cd "$_builddir"
+ pkgdesc="$pkgname python bindings"
+ install -d "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/python* "$subpkgdir"/usr/lib/
+}
+
+utils() {
+ pkgdesc="XML utilities"
+ replaces="libxml2"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="8127a65e8c3b08856093099b52599c86 libxml2-2.7.8.tar.gz
+5ad4915665608ebfa5b89f7908467a72 largefile64.patch"
diff --git a/main/libxml2/largefile64.patch b/main/libxml2/largefile64.patch
new file mode 100644
index 0000000000..29be82760f
--- /dev/null
+++ b/main/libxml2/largefile64.patch
@@ -0,0 +1,12 @@
+--- libxml2-2.6.32.dfsg.orig/libxml.h
++++ libxml2-2.6.32.dfsg/libxml.h
+@@ -13,6 +13,9 @@
+ #ifndef _LARGEFILE_SOURCE
+ #define _LARGEFILE_SOURCE
+ #endif
++#ifndef _LARGEFILE64_SOURCE
++#define _LARGEFILE64_SOURCE
++#endif
+ #ifndef _FILE_OFFSET_BITS
+ #define _FILE_OFFSET_BITS 64
+ #endif
diff --git a/main/libxmu/APKBUILD b/main/libxmu/APKBUILD
new file mode 100644
index 0000000000..4f3543f177
--- /dev/null
+++ b/main/libxmu/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxmu
+pkgver=1.1.0
+pkgrel=2
+pkgdesc="X11 miscellaneous micro-utility library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxext-dev libxt-dev libx11-dev libsm-dev
+ util-linux-ng-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXmu-$pkgver.tar.bz2"
+depends_dev="xproto libx11-dev libxt-dev libxext-dev util-linux-ng-dev"
+
+build ()
+{
+ cd "$srcdir"/libXmu-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXmu-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 $srcdir/libXmu-$pkgver/COPYING \
+ $pkgdir/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="6836883a0120e8346cf7f58dc42e465a libXmu-1.1.0.tar.bz2"
diff --git a/main/libxp/APKBUILD b/main/libxp/APKBUILD
new file mode 100644
index 0000000000..616e034f9e
--- /dev/null
+++ b/main/libxp/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxp
+pkgver=1.0.1
+pkgrel=1
+pkgdesc="X.Org X11 libXp runtime library"
+url="http://www.x.org"
+arch="all"
+license="MIT"
+depends=
+depends_dev="util-macros libx11-dev libxext-dev libxau-dev printproto"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXp-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/libXp-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="7ae1d63748e79086bd51a633da1ff1a9 libXp-1.0.1.tar.bz2"
diff --git a/main/libxpm/APKBUILD b/main/libxpm/APKBUILD
new file mode 100644
index 0000000000..0f9e0b25c7
--- /dev/null
+++ b/main/libxpm/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxpm
+pkgver=3.5.9
+pkgrel=2
+pkgdesc="X11 pixmap library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom:BELL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxt-dev libxext-dev libx11-dev util-linux-ng-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXpm-$pkgver.tar.bz2"
+
+depends_dev="libx11-dev"
+build() {
+ cd "$srcdir"/libXpm-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXpm-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="2de3a1b9541f4b3a6f9d84b69d25530e libXpm-3.5.9.tar.bz2"
diff --git a/main/libxrandr/APKBUILD b/main/libxrandr/APKBUILD
new file mode 100644
index 0000000000..3013fb959f
--- /dev/null
+++ b/main/libxrandr/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxrandr
+pkgver=1.3.1
+pkgrel=2
+pkgdesc="X11 RandR extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxext-dev libxrender-dev randrproto libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXrandr-$pkgver.tar.bz2"
+
+depends_dev="xproto randrproto libx11-dev libxext-dev libxrender-dev"
+
+build() {
+ cd "$srcdir"/libXrandr-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXrandr-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="7785c3f7cff2735c94657e8f87ed8ad3 libXrandr-1.3.1.tar.bz2"
diff --git a/main/libxrender/APKBUILD b/main/libxrender/APKBUILD
new file mode 100644
index 0000000000..63181eabaa
--- /dev/null
+++ b/main/libxrender/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxrender
+pkgver=0.9.6
+pkgrel=2
+pkgdesc="X Rendering Extension client library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev"
+depends=
+makedepends="pkgconfig libx11-dev renderproto"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXrender-$pkgver.tar.bz2"
+
+depends_dev="xproto renderproto libx11-dev"
+build() {
+ cd "$srcdir"/libXrender-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXrender-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="3b3b7d076c2384b6c600c0b5f4ba971f libXrender-0.9.6.tar.bz2"
diff --git a/main/libxres/APKBUILD b/main/libxres/APKBUILD
new file mode 100644
index 0000000000..977205e6b6
--- /dev/null
+++ b/main/libxres/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxres
+pkgver=1.0.5
+pkgrel=2
+pkgdesc="X11 Resource extension library"
+url="http://xorg.freedesktop.org"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="pkgconfig libxext-dev resourceproto"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/lib/libXres-$pkgver.tar.bz2"
+
+depends_dev="xproto libx11-dev libxext-dev"
+build ()
+{
+ cd "$srcdir"/libXres-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXres-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="d08f0b6df3f96c051637d37009f4e55a libXres-1.0.5.tar.bz2"
diff --git a/main/libxslt/APKBUILD b/main/libxslt/APKBUILD
new file mode 100644
index 0000000000..8e1b72f7f0
--- /dev/null
+++ b/main/libxslt/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxslt
+pkgver=1.1.26
+pkgrel=8
+pkgdesc="XML stylesheet transformation library"
+url="http://xmlsoft.org/XSLT/"
+arch="all"
+license="custom"
+depends=
+makedepends="libxml2-dev libgcrypt-dev libgpg-error-dev python-dev"
+subpackages="$pkgname-dev $pkgname-doc py-$pkgname:py"
+source="ftp://xmlsoft.org/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+py() {
+ pkgdesc="$pkgname python bindings"
+ install -d "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/python* "$subpkgdir"/usr/lib/
+}
+md5sums="e61d0364a30146aaa3001296f853b2b9 libxslt-1.1.26.tar.gz"
diff --git a/main/libxt/APKBUILD b/main/libxt/APKBUILD
new file mode 100644
index 0000000000..5ae67fbd3e
--- /dev/null
+++ b/main/libxt/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxt
+pkgver=1.1.1
+pkgrel=1
+pkgdesc="X11 toolkit intrinsics library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libsm-dev libice-dev libx11-dev e2fsprogs-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXt-$pkgver.tar.bz2"
+
+depends_dev="xproto libx11-dev libsm-dev"
+
+build () {
+ cd "$srcdir"/libXt-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-install-makestrs
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXt-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="eb22c0a1f172b06b97a3f5ae89768412 libXt-1.1.1.tar.bz2"
diff --git a/main/libxtst/APKBUILD b/main/libxtst/APKBUILD
new file mode 100644
index 0000000000..6a7ab8ea70
--- /dev/null
+++ b/main/libxtst/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxtst
+pkgver=1.2.0
+pkgrel=2
+pkgdesc="X11 Testing -- Resource extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxext-dev libxi-dev recordproto inputproto"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXtst-$pkgver.tar.bz2"
+depends_dev="recordproto libx11-dev libxext-dev inputproto libxi-dev"
+
+build ()
+{
+ cd "$srcdir"/libXtst-$pkgver
+ ./configure --prefix=/usr \
+ --build=${CHOST} --host=${CHOST}
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXtst-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="7c592c72da6676f8b0aeec9133b81686 libXtst-1.2.0.tar.bz2"
diff --git a/main/libxv/APKBUILD b/main/libxv/APKBUILD
new file mode 100644
index 0000000000..a75f8d7cb1
--- /dev/null
+++ b/main/libxv/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxv
+pkgver=1.0.6
+pkgrel=1
+pkgdesc="X11 Video extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxext-dev libx11-dev videoproto"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXv-$pkgver.tar.bz2"
+
+depends_dev="xproto videoproto libx11-dev libxext-dev"
+
+build() {
+ cd "$srcdir"/libXv-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXv-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="e292445a64b63e918bbc8b6aae6391dd libXv-1.0.6.tar.bz2"
diff --git a/main/libxvmc/APKBUILD b/main/libxvmc/APKBUILD
new file mode 100644
index 0000000000..48a13e4bda
--- /dev/null
+++ b/main/libxvmc/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxvmc
+pkgver=1.0.6
+pkgrel=2
+pkgdesc="X11 Video Motion Compensation extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev"
+depends=
+makedepends="pkgconfig libxv-dev libxext-dev libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXvMC-$pkgver.tar.bz2"
+
+depends_dev="xproto videoproto libxv-dev libx11-dev libxext-dev"
+
+build() {
+ cd "$srcdir"/libXvMC-$pkgver
+ ./configure --prefix=/usr --sysconfdir=/etc
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXvMC-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="bfc7524646f890dfc30dea1d676004a3 libXvMC-1.0.6.tar.bz2"
diff --git a/main/libxxf86dga/APKBUILD b/main/libxxf86dga/APKBUILD
new file mode 100644
index 0000000000..3789f5b125
--- /dev/null
+++ b/main/libxxf86dga/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxxf86dga
+pkgver=1.1.2
+pkgrel=2
+pkgdesc="X11 Direct Graphics Access extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xf86dgaproto libxext-dev libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXxf86dga-$pkgver.tar.bz2"
+
+depends_dev="xf86dgaproto libxext-dev libx11-dev"
+build() {
+ cd "$srcdir"/libXxf86dga-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXxf86dga-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="bbd5fdf63d4c107c8cb710d4df2012b4 libXxf86dga-1.1.2.tar.bz2"
diff --git a/main/libxxf86misc/APKBUILD b/main/libxxf86misc/APKBUILD
new file mode 100644
index 0000000000..3750178051
--- /dev/null
+++ b/main/libxxf86misc/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxxf86misc
+pkgver=1.0.2
+pkgrel=6
+pkgdesc="X11 XFree86 miscellaneous extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxext-dev libx11-dev xf86miscproto"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXxf86misc-$pkgver.tar.bz2"
+depends_dev="xf86miscproto libx11-dev libxext-dev"
+
+build() {
+ cd "$srcdir"/libXxf86misc-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXxf86misc-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="51fed53e8de067d4b8666f75a0212400 libXxf86misc-1.0.2.tar.bz2"
diff --git a/main/libxxf86vm/APKBUILD b/main/libxxf86vm/APKBUILD
new file mode 100644
index 0000000000..e1fffccbdc
--- /dev/null
+++ b/main/libxxf86vm/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxxf86vm
+pkgver=1.1.1
+pkgrel=2
+pkgdesc="X11 XFree86 video mode extension library"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xproto libx11-dev xf86vidmodeproto xextproto
+ libxext-dev"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXxf86vm-$pkgver.tar.bz2"
+
+depends_dev="xf86vidmodeproto libx11-dev libxext-dev"
+
+build() {
+ cd "$srcdir"/libXxf86vm-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/libXxf86vm-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="34dc3df888c164378da89a7deeb245a0 libXxf86vm-1.1.1.tar.bz2"
diff --git a/main/lighttpd/APKBUILD b/main/lighttpd/APKBUILD
new file mode 100644
index 0000000000..7154931f3c
--- /dev/null
+++ b/main/lighttpd/APKBUILD
@@ -0,0 +1,118 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lighttpd
+pkgver=1.4.29
+_streamver=2.2.0
+pkgrel=0
+pkgdesc="a secure, fast, compliant and very flexible web-server"
+url="http://www.lighttpd.net/"
+arch="all"
+license="custom"
+install="$pkgname.pre-install $pkgname.post-install"
+depends=
+makedepends="flex pcre-dev openssl-dev zlib-dev bzip2-dev lua-dev pkgconfig
+ automake autoconf openldap-dev"
+source="http://download.lighttpd.net/lighttpd/releases-1.4.x/$pkgname-$pkgver.tar.bz2
+ http://h264.code-shop.com/download/lighttpd-1.4.18_mod_h264_streaming-$_streamver.tar.gz
+ $pkgname.initd
+ $pkgname.confd
+ $pkgname.logrotate
+ spawn-fcgi.confd
+ spawn-fcgi.initd
+ lighttpd.conf
+ mime-types.conf
+ mod_cgi.conf
+ mod_fastcgi.conf
+ mod_fastcgi_fpm.conf
+ "
+subpackages="$pkgname-doc $pkgname-h264_streaming"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ # copy over the mod-h264-streaming mod
+ # http://h264.code-shop.com/trac/wiki/Mod-H264-Streaming-Lighttpd-Version2#DownloadLighttpd1.4.191.4.20andother1.4.x
+ cp "$srcdir"/lighttpd-1.4.18/src/moov.* src/
+ cp "$srcdir"/lighttpd-1.4.18/src/mod_h264_streaming.c src/
+
+ cat >> src/Makefile.am <<__EOF__
+
+lib_LTLIBRARIES += mod_h264_streaming.la
+mod_h264_streaming_la_SOURCES = mod_h264_streaming.c moov.c
+mod_h264_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+mod_h264_streaming_la_LIBADD = \$(common_libadd)
+__EOF__
+ aclocal -I m4 && autoconf && automake
+}
+
+build() {
+ local i
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-lfs \
+ --libdir=/usr/lib/lighttpd \
+ --without-mysql \
+ --without-attr \
+ --without-kerberos5 \
+ --without-fam \
+ --without-webdav-props \
+ --without-webdav-locks \
+ --without-gdbm \
+ --without-memcache \
+ --with-bzip2 \
+ --with-ldap \
+ --with-openssl \
+ --with-lua || return 1
+
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/lighttpd/*.la || return 1
+
+ # create dirs
+ install -d -m755 "$pkgdir"/var/run/lighttpd/ \
+ "$pkgdir"/var/log/lighttpd/ \
+ "$pkgdir"/etc/lighttpd/ \
+ "$pkgdir"/var/www/localhost/htdocs
+
+ # lighttpd
+ install -D -m755 "$srcdir"/lighttpd.initd "$pkgdir"/etc/init.d/lighttpd
+ install -D -m644 "$srcdir"/lighttpd.confd "$pkgdir"/etc/conf.d/lighttpd
+ install -D -m644 "$srcdir"/lighttpd.logrotate \
+ "$pkgdir"/etc/logrotate.d/lighttpd
+
+ # spawn-fcgi
+ install -D -m755 "$srcdir"/spawn-fcgi.initd \
+ "$pkgdir"/etc/init.d/spawn-fcgi
+ install -D -m644 "$srcdir"/spawn-fcgi.confd \
+ "$pkgdir"/etc/conf.d/spawn-fcgi
+
+ # config files
+ for i in lighttpd.conf mime-types.conf mod_cgi.conf mod_fastcgi.conf mod_fastcgi_fpm.conf; do
+ install -m644 "$srcdir"/$i "$pkgdir"/etc/lighttpd/$i
+ done
+}
+
+h264_streaming() {
+ pkgdesc="H264 Streaming Module for lighttpd"
+ url="http://h264.code-shop.com/trac"
+ license="CCPL-nc-sa-3.0"
+ mkdir -p "$subpkgdir"/usr/lib/lighttpd
+ mv "$pkgdir"/usr/lib/lighttpd/mod_h264_streaming.so \
+ "$subpkgdir"/usr/lib/lighttpd/
+}
+
+md5sums="e6e67b09986cb504db630b5a86b2dd76 lighttpd-1.4.29.tar.bz2
+ac37885c881a058194405232e7737a7a lighttpd-1.4.18_mod_h264_streaming-2.2.0.tar.gz
+e37770e4eed20390806a2420a3970fcd lighttpd.initd
+0dede109282bfe685bdec6b35f0e4b6b lighttpd.confd
+ad091c9157134890499f26d170352c9f lighttpd.logrotate
+1d925aed297ec4541fb230dd19e11bc1 spawn-fcgi.confd
+2f177ba0a35fd1c683edef3453c20bc8 spawn-fcgi.initd
+268bf5dd2c370ee5e119246775ac5640 lighttpd.conf
+fef397e7bcf1b741dea211a555e1803c mime-types.conf
+9c1407e95f62ed22da66c4ef5f69c3b5 mod_cgi.conf
+f3363e39832f1b6678468b482d121afb mod_fastcgi.conf
+aee5947a1abf380b0685a534ca384b42 mod_fastcgi_fpm.conf"
diff --git a/main/lighttpd/lighttpd.conf b/main/lighttpd/lighttpd.conf
new file mode 100644
index 0000000000..2cad7755aa
--- /dev/null
+++ b/main/lighttpd/lighttpd.conf
@@ -0,0 +1,323 @@
+###############################################################################
+# Default lighttpd.conf for Gentoo.
+# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/lighttpd.conf,v 1.3 2005/09/01 14:22:35 ka0ttic Exp $
+###############################################################################
+
+# {{{ variables
+var.basedir = "/var/www/localhost"
+var.logdir = "/var/log/lighttpd"
+var.statedir = "/var/lib/lighttpd"
+# }}}
+
+# {{{ modules
+# At the very least, mod_access and mod_accesslog should be enabled.
+# All other modules should only be loaded if necessary.
+# NOTE: the order of modules is important.
+server.modules = (
+# "mod_rewrite",
+# "mod_redirect",
+# "mod_alias",
+ "mod_access",
+# "mod_cml",
+# "mod_trigger_b4_dl",
+# "mod_auth",
+# "mod_status",
+# "mod_setenv",
+# "mod_proxy",
+# "mod_simple_vhost",
+# "mod_evhost",
+# "mod_userdir",
+# "mod_compress",
+# "mod_ssi",
+# "mod_usertrack",
+# "mod_expire",
+# "mod_secdownload",
+# "mod_rrdtool",
+# "mod_webdav",
+ "mod_accesslog"
+)
+# }}}
+
+# {{{ includes
+include "mime-types.conf"
+# uncomment for cgi support
+# include "mod_cgi.conf"
+# uncomment for php/fastcgi support
+# include "mod_fastcgi.conf"
+# uncomment for php/fastcgi fpm support
+# include "mod_fastcgi_fpm.conf"
+# }}}
+
+# {{{ server settings
+server.username = "lighttpd"
+server.groupname = "lighttpd"
+
+server.document-root = var.basedir + "/htdocs"
+server.pid-file = "/var/run/lighttpd.pid"
+
+server.errorlog = var.logdir + "/error.log"
+# log errors to syslog instead
+# server.errorlog-use-syslog = "enable"
+
+server.indexfiles = ("index.php", "index.html",
+ "index.htm", "default.htm")
+
+# server.tag = "lighttpd"
+
+server.follow-symlink = "enable"
+
+# event handler (defaults to "poll")
+# see performance.txt
+#
+# for >= linux-2.4
+# server.event-handler = "linux-rtsig"
+# for >= linux-2.6
+# server.event-handler = "linux-sysepoll"
+# for FreeBSD
+# server.event-handler = "freebsd-kqueue"
+
+# chroot to directory (defaults to no chroot)
+# server.chroot = "/"
+
+# bind to port (defaults to 80)
+# server.port = 81
+
+# bind to name (defaults to all interfaces)
+# server.bind = "grisu.home.kneschke.de"
+
+# error-handler for status 404
+# server.error-handler-404 = "/error-handler.html"
+# server.error-handler-404 = "/error-handler.php"
+
+# Format: <errorfile-prefix><status-code>.html
+# -> ..../status-404.html for 'File not found'
+# server.errorfile-prefix = var.basedir + "/error/status-"
+
+# FAM support for caching stat() calls
+# requires that lighttpd be built with USE=fam
+# server.stat-cache-engine = "fam"
+# }}}
+
+# {{{ mod_staticfile
+
+# which extensions should not be handled via static-file transfer
+# (extensions that are usually handled by mod_cgi, mod_fastcgi, etc).
+static-file.exclude-extensions = (".php", ".pl", ".cgi", ".fcgi")
+# }}}
+
+# {{{ mod_accesslog
+accesslog.filename = var.logdir + "/access.log"
+# }}}
+
+# {{{ mod_dirlisting
+# enable directory listings
+# dir-listing.activate = "enable"
+#
+# don't list hidden files/directories
+# dir-listing.hide-dotfiles = "enable"
+#
+# use a different css for directory listings
+# dir-listing.external-css = "/path/to/dir-listing.css"
+#
+# list of regular expressions. files that match any of the
+# specified regular expressions will be excluded from directory
+# listings.
+# dir-listing.exclude = ("^\.", "~$")
+# }}}
+
+# {{{ mod_access
+# see access.txt
+
+url.access-deny = ("~", ".inc")
+# }}}
+
+# {{{ mod_userdir
+# see userdir.txt
+#
+# userdir.path = "public_html"
+# userdir.exclude-user = ("root")
+# }}}
+
+# {{{ mod_ssi
+# see ssi.txt
+#
+# ssi.extension = (".shtml")
+# }}}
+
+# {{{ mod_ssl
+# see ssl.txt
+#
+# ssl.engine = "enable"
+# ssl.pemfile = "server.pem"
+# }}}
+
+# {{{ mod_status
+# see status.txt
+#
+# status.status-url = "/server-status"
+# status.config-url = "/server-config"
+# }}}
+
+# {{{ mod_simple_vhost
+# see simple-vhost.txt
+#
+# If you want name-based virtual hosting add the next three settings and load
+# mod_simple_vhost
+#
+# document-root =
+# virtual-server-root + virtual-server-default-host + virtual-server-docroot
+# or
+# virtual-server-root + http-host + virtual-server-docroot
+#
+# simple-vhost.server-root = "/home/weigon/wwwroot/servers/"
+# simple-vhost.default-host = "grisu.home.kneschke.de"
+# simple-vhost.document-root = "/pages/"
+# }}}
+
+# {{{ mod_compress
+# see compress.txt
+#
+# compress.cache-dir = var.statedir + "/cache/compress"
+# compress.filetype = ("text/plain", "text/html")
+# }}}
+
+# {{{ mod_proxy
+# see proxy.txt
+#
+# proxy.server = ( ".php" =>
+# ( "localhost" =>
+# (
+# "host" => "192.168.0.101",
+# "port" => 80
+# )
+# )
+# )
+# }}}
+
+# {{{ mod_auth
+# see authentication.txt
+#
+# auth.backend = "plain"
+# auth.backend.plain.userfile = "lighttpd.user"
+# auth.backend.plain.groupfile = "lighttpd.group"
+
+# auth.backend.ldap.hostname = "localhost"
+# auth.backend.ldap.base-dn = "dc=my-domain,dc=com"
+# auth.backend.ldap.filter = "(uid=$)"
+
+# auth.require = ( "/server-status" =>
+# (
+# "method" => "digest",
+# "realm" => "download archiv",
+# "require" => "user=jan"
+# ),
+# "/server-info" =>
+# (
+# "method" => "digest",
+# "realm" => "download archiv",
+# "require" => "valid-user"
+# )
+# )
+# }}}
+
+# {{{ mod_rewrite
+# see rewrite.txt
+#
+# url.rewrite = (
+# "^/$" => "/server-status"
+# )
+# }}}
+
+# {{{ mod_redirect
+# see redirect.txt
+#
+# url.redirect = (
+# "^/wishlist/(.+)" => "http://www.123.org/$1"
+# )
+# }}}
+
+# {{{ mod_evhost
+# define a pattern for the host url finding
+# %% => % sign
+# %0 => domain name + tld
+# %1 => tld
+# %2 => domain name without tld
+# %3 => subdomain 1 name
+# %4 => subdomain 2 name
+#
+# evhost.path-pattern = "/home/storage/dev/www/%3/htdocs/"
+# }}}
+
+# {{{ mod_expire
+# expire.url = (
+# "/buggy/" => "access 2 hours",
+# "/asdhas/" => "access plus 1 seconds 2 minutes"
+# )
+# }}}
+
+# {{{ mod_rrdtool
+# see rrdtool.txt
+#
+# rrdtool.binary = "/usr/bin/rrdtool"
+# rrdtool.db-name = var.statedir + "/lighttpd.rrd"
+# }}}
+
+# {{{ mod_setenv
+# see setenv.txt
+#
+# setenv.add-request-header = ( "TRAV_ENV" => "mysql://user@host/db" )
+# setenv.add-response-header = ( "X-Secret-Message" => "42" )
+# }}}
+
+# {{{ mod_trigger_b4_dl
+# see trigger_b4_dl.txt
+#
+# trigger-before-download.gdbm-filename = "/home/weigon/testbase/trigger.db"
+# trigger-before-download.memcache-hosts = ( "127.0.0.1:11211" )
+# trigger-before-download.trigger-url = "^/trigger/"
+# trigger-before-download.download-url = "^/download/"
+# trigger-before-download.deny-url = "http://127.0.0.1/index.html"
+# trigger-before-download.trigger-timeout = 10
+# }}}
+
+# {{{ mod_cml
+# see cml.txt
+#
+# don't forget to add index.cml to server.indexfiles
+# cml.extension = ".cml"
+# cml.memcache-hosts = ( "127.0.0.1:11211" )
+# }}}
+
+# {{{ mod_webdav
+# see webdav.txt
+#
+# $HTTP["url"] =~ "^/dav($|/)" {
+# webdav.activate = "enable"
+# webdav.is-readonly = "enable"
+# }
+# }}}
+
+# {{{ extra rules
+#
+# set Content-Encoding and reset Content-Type for browsers that
+# support decompressing on-thy-fly (requires mod_setenv)
+# $HTTP["url"] =~ "\.gz$" {
+# setenv.add-response-header = ("Content-Encoding" => "x-gzip")
+# mimetype.assign = (".gz" => "text/plain")
+# }
+
+# $HTTP["url"] =~ "\.bz2$" {
+# setenv.add-response-header = ("Content-Encoding" => "x-bzip2")
+# mimetype.assign = (".bz2" => "text/plain")
+# }
+#
+# }}}
+
+# {{{ debug
+# debug.log-request-header = "enable"
+# debug.log-response-header = "enable"
+# debug.log-request-handling = "enable"
+# debug.log-file-not-found = "enable"
+# }}}
+
+# vim: set ft=conf foldmethod=marker et :
diff --git a/main/lighttpd/lighttpd.confd b/main/lighttpd/lighttpd.confd
new file mode 100644
index 0000000000..70d4170555
--- /dev/null
+++ b/main/lighttpd/lighttpd.confd
@@ -0,0 +1,12 @@
+# /etc/conf.d/lighttpd
+
+# Location of a shell used by the 'include_shell' directive
+# in the lighttpd's configuration file
+#export SHELL="/bin/bash"
+
+# Location of the lighttpd configuration file
+LIGHTTPD_CONF="/etc/lighttpd/lighttpd.conf"
+
+# Location of the lighttpd pid file
+LIGHTTPD_PID="/var/run/lighttpd.pid"
+
diff --git a/main/lighttpd/lighttpd.initd b/main/lighttpd/lighttpd.initd
new file mode 100644
index 0000000000..a0bcc0110e
--- /dev/null
+++ b/main/lighttpd/lighttpd.initd
@@ -0,0 +1,74 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/lighttpd.initd-1.4.13-r3,v 1.2 2007/10/12 20:54:46 swegener Exp $
+
+opts="reload graceful"
+
+depend() {
+ need net
+ use mysql logger spawn-fcgi ldap slapd
+ after famd firewall sshd
+}
+
+_confopt() {
+ /usr/sbin/lighttpd -p -f ${LIGHTTPD_CONF} | awk -F = \
+ "/$1/"' {sub(/^ *"/, "", $2); sub(/" */, "", $2); print $2}'
+}
+
+checkconfig() {
+ if [ ! -f "${LIGHTTPD_CONF}" ] ; then
+ ewarn "${LIGHTTPD_CONF} does not exist."
+ return 1
+ fi
+
+ /usr/sbin/lighttpd -t -f ${LIGHTTPD_CONF} >/dev/null
+}
+
+start() {
+ checkconfig || return 1
+ local _user=$(_confopt server.user)
+ local _group=$(_confopt server.group)
+ chown $_user:$_group /var/*/lighttpd
+
+ ebegin "Starting lighttpd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/lighttpd \
+ --pidfile "${LIGHTTPD_PID}" -- -f "${LIGHTTPD_CONF}"
+ eend $?
+}
+
+stop() {
+ local rv=0
+ ebegin "Stopping lighttpd"
+ start-stop-daemon --stop --quiet --pidfile "${LIGHTTPD_PID}"
+ eend $?
+}
+
+reload() {
+ if ! service_started "${SVCNAME}" ; then
+ eerror "${SVCNAME} isn't running"
+ return 1
+ fi
+ checkconfig || return 1
+
+ ebegin "Re-opening lighttpd log files"
+ start-stop-daemon --stop --oknodo --quiet --pidfile "${LIGHTTPD_PID}" \
+ --signal HUP
+ eend $?
+}
+
+graceful() {
+ if ! service_started "${SVCNAME}" ; then
+ eerror "${SVCNAME} isn't running"
+ return 1
+ fi
+ checkconfig || return 1
+
+ ebegin "Gracefully stopping lighttpd"
+ start-stop-daemon --stop --oknodo --quiet --pidfile "${LIGHTTPD_PID}" \
+ --signal INT
+ if eend $? ; then
+ rm -f "${LIGHTTPD_PID}"
+ start
+ fi
+}
diff --git a/main/lighttpd/lighttpd.logrotate b/main/lighttpd/lighttpd.logrotate
new file mode 100644
index 0000000000..76f0ef3ff5
--- /dev/null
+++ b/main/lighttpd/lighttpd.logrotate
@@ -0,0 +1,17 @@
+# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/lighttpd.logrotate,v 1.2 2006/05/30 19:49:29 bangert Exp $
+# lighttpd logrotate script for Gentoo
+
+/var/log/lighttpd/*.log {
+ daily
+ missingok
+ copytruncate
+ rotate 7
+ compress
+ notifempty
+ sharedscripts
+ postrotate
+ if [ -f /var/run/lighttpd.pid ]; then \
+ /etc/init.d/lighttpd reload > /dev/null 2>&1 || true ; \
+ fi;
+ endscript
+}
diff --git a/main/lighttpd/lighttpd.post-install b/main/lighttpd/lighttpd.post-install
new file mode 100644
index 0000000000..5b116a6375
--- /dev/null
+++ b/main/lighttpd/lighttpd.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+chown lighttpd:lighttpd /var/*/lighttpd
+exit 0
diff --git a/main/lighttpd/lighttpd.pre-install b/main/lighttpd/lighttpd.pre-install
new file mode 100644
index 0000000000..4682680d6b
--- /dev/null
+++ b/main/lighttpd/lighttpd.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -H -h /var/www/localhost/htdocs -s /bin/false -D lighttpd 2>/dev/null
+exit 0
diff --git a/main/lighttpd/mime-types.conf b/main/lighttpd/mime-types.conf
new file mode 100644
index 0000000000..3c36577739
--- /dev/null
+++ b/main/lighttpd/mime-types.conf
@@ -0,0 +1,76 @@
+###############################################################################
+# Default mime-types.conf for Gentoo.
+# include'd from lighttpd.conf.
+# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/mime-types.conf,v 1.2 2005/08/27 12:36:13 ka0ttic Exp $
+###############################################################################
+
+# {{{ mime types
+mimetype.assign = (
+ ".pdf" => "application/pdf",
+ ".sig" => "application/pgp-signature",
+ ".spl" => "application/futuresplash",
+ ".class" => "application/octet-stream",
+ ".ps" => "application/postscript",
+ ".torrent" => "application/x-bittorrent",
+ ".dvi" => "application/x-dvi",
+ ".gz" => "application/x-gzip",
+ ".pac" => "application/x-ns-proxy-autoconfig",
+ ".swf" => "application/x-shockwave-flash",
+ ".tar.gz" => "application/x-tgz",
+ ".tgz" => "application/x-tgz",
+ ".tar" => "application/x-tar",
+ ".zip" => "application/zip",
+ ".mp3" => "audio/mpeg",
+ ".m3u" => "audio/x-mpegurl",
+ ".wma" => "audio/x-ms-wma",
+ ".wax" => "audio/x-ms-wax",
+ ".ogg" => "application/ogg",
+ ".wav" => "audio/x-wav",
+ ".gif" => "image/gif",
+ ".jpg" => "image/jpeg",
+ ".jpeg" => "image/jpeg",
+ ".png" => "image/png",
+ ".xbm" => "image/x-xbitmap",
+ ".xpm" => "image/x-xpixmap",
+ ".xwd" => "image/x-xwindowdump",
+ ".css" => "text/css",
+ ".html" => "text/html",
+ ".htm" => "text/html",
+ ".js" => "text/javascript",
+ ".asc" => "text/plain",
+ ".c" => "text/plain",
+ ".h" => "text/plain",
+ ".cc" => "text/plain",
+ ".cpp" => "text/plain",
+ ".hh" => "text/plain",
+ ".hpp" => "text/plain",
+ ".conf" => "text/plain",
+ ".log" => "text/plain",
+ ".text" => "text/plain",
+ ".txt" => "text/plain",
+ ".diff" => "text/plain",
+ ".patch" => "text/plain",
+ ".ebuild" => "text/plain",
+ ".eclass" => "text/plain",
+ ".rtf" => "application/rtf",
+ ".bmp" => "image/bmp",
+ ".tif" => "image/tiff",
+ ".tiff" => "image/tiff",
+ ".ico" => "image/x-icon",
+ ".dtd" => "text/xml",
+ ".xml" => "text/xml",
+ ".mpeg" => "video/mpeg",
+ ".mpg" => "video/mpeg",
+ ".mov" => "video/quicktime",
+ ".qt" => "video/quicktime",
+ ".avi" => "video/x-msvideo",
+ ".asf" => "video/x-ms-asf",
+ ".asx" => "video/x-ms-asf",
+ ".wmv" => "video/x-ms-wmv",
+ ".bz2" => "application/x-bzip",
+ ".tbz" => "application/x-bzip-compressed-tar",
+ ".tar.bz2" => "application/x-bzip-compressed-tar"
+ )
+# }}}
+
+# vim: set ft=conf foldmethod=marker et :
diff --git a/main/lighttpd/mod_cgi.conf b/main/lighttpd/mod_cgi.conf
new file mode 100644
index 0000000000..1cb3770f9b
--- /dev/null
+++ b/main/lighttpd/mod_cgi.conf
@@ -0,0 +1,33 @@
+###############################################################################
+# mod_cgi.conf
+# include'd by lighttpd.conf.
+# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/mod_cgi.conf,v 1.1 2005/08/27 12:36:13 ka0ttic Exp $
+###############################################################################
+
+#
+# see cgi.txt for more information on using mod_cgi
+#
+
+server.modules += ("mod_cgi")
+
+# NOTE: this requires mod_alias
+alias.url = (
+ "/cgi-bin/" => var.basedir + "/cgi-bin/"
+)
+
+#
+# Note that you'll also want to enable the
+# cgi-bin alias via mod_alias (above).
+#
+
+$HTTP["url"] =~ "^/cgi-bin/" {
+ # disable directory listings
+ dir-listing.activate = "disable"
+ # only allow cgi's in this directory
+ cgi.assign = (
+ ".pl" => "/usr/bin/perl",
+ ".cgi" => "/usr/bin/perl"
+ )
+}
+
+# vim: set ft=conf foldmethod=marker et :
diff --git a/main/lighttpd/mod_fastcgi.conf b/main/lighttpd/mod_fastcgi.conf
new file mode 100644
index 0000000000..ca1369af79
--- /dev/null
+++ b/main/lighttpd/mod_fastcgi.conf
@@ -0,0 +1,17 @@
+###############################################################################
+# mod_fastcgi.conf
+# include'd by lighttpd.conf.
+# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/mod_fastcgi.conf-1.4.13-r2,v 1.1 2007/04/01 23:22:00 robbat2 Exp $
+###############################################################################
+
+server.modules += ("mod_fastcgi")
+fastcgi.server = ( ".php" =>
+ ( "localhost" =>
+ (
+ "socket" => "/var/run/lighttpd/lighttpd-fastcgi-php-" + PID + ".socket",
+ "bin-path" => "/usr/bin/php-cgi"
+ )
+ )
+ )
+
+# vim: set ft=conf foldmethod=marker et :
diff --git a/main/lighttpd/mod_fastcgi_fpm.conf b/main/lighttpd/mod_fastcgi_fpm.conf
new file mode 100644
index 0000000000..926137a434
--- /dev/null
+++ b/main/lighttpd/mod_fastcgi_fpm.conf
@@ -0,0 +1,16 @@
+###############################################################################
+# mod_fastcgi_fpm.conf
+# include'd by lighttpd.conf.
+###############################################################################
+
+server.modules += ("mod_fastcgi")
+fastcgi.server = ( ".php" =>
+ ( "localhost" =>
+ (
+ "host" => "127.0.0.1",
+ "port" => "9000"
+ )
+ )
+ )
+
+# vim: set ft=conf foldmethod=marker et :
diff --git a/main/lighttpd/spawn-fcgi.confd b/main/lighttpd/spawn-fcgi.confd
new file mode 100644
index 0000000000..2a88806ae0
--- /dev/null
+++ b/main/lighttpd/spawn-fcgi.confd
@@ -0,0 +1,35 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/spawn-fcgi.confd,v 1.1 2005/02/14 11:39:01 ka0ttic Exp $
+
+# Configuration file for the FCGI-Part of /etc/init.d/lighttpd
+
+## Set this to "yes" to enable SPAWNFCGI
+ENABLE_SPAWNFCGI="yes"
+
+## ABSOLUTE path to the spawn-fcgi binary
+SPAWNFCGI="/usr/bin/spawn-fcgi"
+
+## ABSOLUTE path to the PHP binary
+FCGIPROGRAM="/usr/bin/php-cgi"
+
+## bind to tcp-port on localhost
+FCGIPORT="1026"
+
+## number of PHP childs to spawn
+PHP_FCGI_CHILDREN=5
+
+## number of request server by a single php-process until is will be restarted
+PHP_FCGI_MAX_REQUESTS=1000
+
+## IP adresses where PHP should access server connections from
+FCGI_WEB_SERVER_ADDRS="127.0.0.1"
+
+# allowed environment variables sperated by spaces
+ALLOWED_ENV="PATH USER"
+# do NOT change line below
+ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS"
+
+## if this script is run as root switch to the following user
+USERID=lighttpd
+GROUPID=lighttpd
diff --git a/main/lighttpd/spawn-fcgi.initd b/main/lighttpd/spawn-fcgi.initd
new file mode 100644
index 0000000000..a4023a2c25
--- /dev/null
+++ b/main/lighttpd/spawn-fcgi.initd
@@ -0,0 +1,53 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/spawn-fcgi.initd,v 1.2 2007/04/02 12:46:08 uberlord Exp $
+
+SPAWNFCGI_PID="/var/run/spawn-fcgi.pid"
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ local my_end
+
+ ebegin "Starting spawn-fcgi"
+ export PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS
+
+ EX="${SPAWNFCGI} -p ${FCGIPORT} -f ${FCGIPROGRAM} -u ${USERID} \
+ -g ${GROUPID} -C ${PHP_FCGI_CHILDREN}"
+
+ # copy the allowed environment variables
+ unset E
+ for i in ${ALLOWED_ENV}; do
+ eval "E=\"${E} ${i}=\$${i}\""
+ done
+
+ # clean environment and set up a new one
+ env - ${E} ${EX} 2>${SPAWNFCGI_PID}
+ my_end=$?
+ if [ "$my_end" != "0" ]; then
+ [ -f ${SPAWNFCGI_PID} ] && rm -f ${SPAWNFCGI_PID}
+ eend $my_end
+ fi
+
+ #extract parent-process-id and write it back to the file
+ FCGI_PPID=`cat ${SPAWNFCGI_PID} | cut -d':' -f4`
+ echo ${FCGI_PPID} > ${SPAWNFCGI_PID}
+ eend 0
+}
+
+stop() {
+ ebegin "Stopping spawn-fcgi"
+ if ! kill `cat ${SPAWNFCGI_PID}` ; then
+ eend $?
+ return 1
+ fi
+ if [ -w ${SPAWNFCGI_PID} ]; then
+ rm ${SPAWNFCGI_PID}
+ fi
+ eend 0
+}
+
diff --git a/main/links/APKBUILD b/main/links/APKBUILD
new file mode 100644
index 0000000000..4c5b19c095
--- /dev/null
+++ b/main/links/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=links
+pkgver=2.2
+pkgrel=4
+pkgdesc="A text WWW browser, similar to Lynx"
+url="http://atrey.karlin.mff.cuni.cz/~clock/twibright/links/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=
+makedepends="zlib-dev openssl-dev bzip2-dev"
+source="http://$pkgname.twibright.com/download/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --enable-javascript \
+ --disable-graphics \
+ --without-x \
+ --disable-nls || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="bf5b20529a2a811701c5af52b28ebdd4 links-2.2.tar.bz2"
diff --git a/main/linux-firmware/APKBUILD b/main/linux-firmware/APKBUILD
new file mode 100644
index 0000000000..46cf9c2022
--- /dev/null
+++ b/main/linux-firmware/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer:
+pkgname=linux-firmware
+pkgver=20110311
+pkgrel=0
+pkgdesc="firmware files for linux"
+url="http://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git;a=summary"
+arch="noarch"
+license="GPL"
+depends=
+makedepends=
+install=""
+subpackages=
+source="http://nenolod.net/~nenolod/linux-firmware-${pkgver}.tar.bz2"
+replaces="linux-grsec linux-vserver"
+
+_builddir="${srcdir}/${pkgname}"
+prepare() {
+ return 0
+}
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p ${pkgdir}/lib
+ mv "${_builddir}" ${pkgdir}/lib/firmware
+}
+
+md5sums="1af2f89b00cc24b567551fcd8f4a327d linux-firmware-20110311.tar.bz2"
diff --git a/main/linux-grsec/0004-arp-flush-arp-cache-on-device-change.patch b/main/linux-grsec/0004-arp-flush-arp-cache-on-device-change.patch
new file mode 100644
index 0000000000..85161ea3a3
--- /dev/null
+++ b/main/linux-grsec/0004-arp-flush-arp-cache-on-device-change.patch
@@ -0,0 +1,29 @@
+From 8a0e3ea4924059a7268446177d6869e3399adbb2 Mon Sep 17 00:00:00 2001
+From: Timo Teras <timo.teras@iki.fi>
+Date: Mon, 12 Apr 2010 13:46:45 +0000
+Subject: [PATCH 04/18] arp: flush arp cache on device change
+
+If IFF_NOARP is changed, we must flush the arp cache.
+
+Signed-off-by: Timo Teras <timo.teras@iki.fi>
+---
+ net/ipv4/arp.c | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
+index 4e80f33..580bfc3 100644
+--- a/net/ipv4/arp.c
++++ b/net/ipv4/arp.c
+@@ -1200,6 +1200,9 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
+ neigh_changeaddr(&arp_tbl, dev);
+ rt_cache_flush(dev_net(dev), 0);
+ break;
++ case NETDEV_CHANGE:
++ neigh_changeaddr(&arp_tbl, dev);
++ break;
+ default:
+ break;
+ }
+--
+1.7.0.2
+
diff --git a/main/linux-grsec/APKBUILD b/main/linux-grsec/APKBUILD
new file mode 100644
index 0000000000..758226d210
--- /dev/null
+++ b/main/linux-grsec/APKBUILD
@@ -0,0 +1,145 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+_flavor=grsec
+pkgname=linux-${_flavor}
+pkgver=2.6.38.7
+_kernver=2.6.38
+pkgrel=0
+pkgdesc="Linux kernel with grsecurity"
+url=http://grsecurity.net
+depends="mkinitfs linux-firmware"
+makedepends="perl installkernel bash"
+options="!strip"
+_config=${config:-kernelconfig.${CARCH}}
+install=
+source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
+ grsecurity-2.2.2-2.6.38.7-201105222331.patch
+
+ 0004-arp-flush-arp-cache-on-device-change.patch
+ net-gre-provide-multicast-mappings-for-ipv4-and-ipv6.patch
+
+ kernelconfig.x86
+ kernelconfig.x86_64
+ "
+subpackages="$pkgname-dev"
+arch="x86 x86_64 arm"
+license="GPL-2"
+
+_abi_release=${pkgver}-${_flavor}
+
+prepare() {
+ local _patch_failed=
+ cd "$srcdir"/linux-$_kernver
+ if [ "$_kernver" != "$pkgver" ]; then
+ bunzip2 -c < "$srcdir"/patch-$pkgver.bz2 | patch -p1 -N || return 1
+ fi
+
+ # first apply patches in specified order
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i..."
+ if ! patch -s -p1 -N -i "$srcdir"/$i; then
+ echo $i >>failed
+ _patch_failed=1
+ fi
+ ;;
+ esac
+ done
+
+ if ! [ -z "$_patch_failed" ]; then
+ error "The following patches failed:"
+ cat failed
+ return 1
+ fi
+
+ mkdir -p "$srcdir"/build
+ cp "$srcdir"/$_config "$srcdir"/build/.config || return 1
+ make -C "$srcdir"/linux-$_kernver O="$srcdir"/build HOSTCC="${CC:-gcc}" \
+ silentoldconfig
+}
+
+# this is so we can do: 'abuild menuconfig' to reconfigure kernel
+menuconfig() {
+ cd "$srcdir"/build || return 1
+ make menuconfig
+ cp .config "$startdir"/$_config
+}
+
+build() {
+ cd "$srcdir"/build
+ make CC="${CC:-gcc}" \
+ KBUILD_BUILD_VERSION="$((pkgrel + 1 ))-Alpine" \
+ || return 1
+}
+
+package() {
+ cd "$srcdir"/build
+ mkdir -p "$pkgdir"/boot "$pkgdir"/lib/modules
+ make -j1 modules_install firmware_install install \
+ INSTALL_MOD_PATH="$pkgdir" \
+ INSTALL_PATH="$pkgdir"/boot \
+ || return 1
+
+ rm -f "$pkgdir"/lib/modules/${_abi_release}/build \
+ "$pkgdir"/lib/modules/${_abi_release}/source
+ rm -rf "$pkgdir"/lib/firmware
+
+ install -D include/config/kernel.release \
+ "$pkgdir"/usr/share/kernel/$_flavor/kernel.release
+}
+
+dev() {
+ # copy the only the parts that we really need for build 3rd party
+ # kernel modules and install those as /usr/src/linux-headers,
+ # simlar to what ubuntu does
+ #
+ # this way you dont need to install the 300-400 kernel sources to
+ # build a tiny kernel module
+ #
+ pkgdesc="Headers and script for third party modules for grsec kernel"
+ local dir="$subpkgdir"/usr/src/linux-headers-${_abi_release}
+
+ # first we import config, run prepare to set up for building
+ # external modules, and create the scripts
+ mkdir -p "$dir"
+ cp "$srcdir"/$_config "$dir"/.config
+ make -j1 -C "$srcdir"/linux-$_kernver O="$dir" HOSTCC="${CC:-gcc}" \
+ silentoldconfig prepare scripts
+
+ # remove the stuff that poits to real sources. we want 3rd party
+ # modules to believe this is the soruces
+ rm "$dir"/Makefile "$dir"/source
+
+ # copy the needed stuff from real sources
+ #
+ # this is taken from ubuntu kernel build script
+ # http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-jaunty.git;a=blob;f=debian/rules.d/3-binary-indep.mk;hb=HEAD
+ cd "$srcdir"/linux-$_kernver
+ find . -path './include/*' -prune -o -path './scripts/*' -prune \
+ -o -type f \( -name 'Makefile*' -o -name 'Kconfig*' \
+ -o -name 'Kbuild*' -o -name '*.sh' -o -name '*.pl' \
+ -o -name '*.lds' \) | cpio -pdm "$dir"
+ cp -a drivers/media/dvb/dvb-core/*.h "$dir"/drivers/media/dvb/dvb-core
+ cp -a drivers/media/video/*.h "$dir"/drivers/media/video
+ cp -a drivers/media/dvb/frontends/*.h "$dir"/drivers/media/dvb/frontends
+ cp -a scripts include "$dir"
+ find $(find arch -name include -type d -print) -type f \
+ | cpio -pdm "$dir"
+
+ install -Dm644 "$srcdir"/build/Module.symvers \
+ "$dir"/Module.symvers
+
+ mkdir -p "$subpkgdir"/lib/modules/${_abi_release}
+ ln -sf /usr/src/linux-headers-${_abi_release} \
+ "$subpkgdir"/lib/modules/${_abi_release}/build
+}
+
+md5sums="7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2
+2639b4b98a2dcfc8b7f091543f289205 patch-2.6.38.7.bz2
+405571538f81e3ebbe8cbfc029c52fdd grsecurity-2.2.2-2.6.38.7-201105222331.patch
+776adeeb5272093574f8836c5037dd7d 0004-arp-flush-arp-cache-on-device-change.patch
+aa1b82da0cabfb41c5e6da5bddf60bab net-gre-provide-multicast-mappings-for-ipv4-and-ipv6.patch
+f4cf5b0ddfeef7aa87fb27792aff88a4 kernelconfig.x86
+0a73d8d896101de90f47dae32119e7ca kernelconfig.x86_64"
diff --git a/main/linux-grsec/grsecurity-2.2.2-2.6.38.7-201105222331.patch b/main/linux-grsec/grsecurity-2.2.2-2.6.38.7-201105222331.patch
new file mode 100644
index 0000000000..8ac4f8cdfc
--- /dev/null
+++ b/main/linux-grsec/grsecurity-2.2.2-2.6.38.7-201105222331.patch
@@ -0,0 +1,71257 @@
+diff -urNp linux-2.6.38.7/arch/alpha/include/asm/dma-mapping.h linux-2.6.38.7/arch/alpha/include/asm/dma-mapping.h
+--- linux-2.6.38.7/arch/alpha/include/asm/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/alpha/include/asm/dma-mapping.h 2011-04-28 19:34:14.000000000 -0400
+@@ -3,9 +3,9 @@
+
+ #include <linux/dma-attrs.h>
+
+-extern struct dma_map_ops *dma_ops;
++extern const struct dma_map_ops *dma_ops;
+
+-static inline struct dma_map_ops *get_dma_ops(struct device *dev)
++static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
+ {
+ return dma_ops;
+ }
+diff -urNp linux-2.6.38.7/arch/alpha/include/asm/elf.h linux-2.6.38.7/arch/alpha/include/asm/elf.h
+--- linux-2.6.38.7/arch/alpha/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/alpha/include/asm/elf.h 2011-04-28 19:34:14.000000000 -0400
+@@ -90,6 +90,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
+
+ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE (current->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL)
++
++#define PAX_DELTA_MMAP_LEN (current->personality & ADDR_LIMIT_32BIT ? 14 : 28)
++#define PAX_DELTA_STACK_LEN (current->personality & ADDR_LIMIT_32BIT ? 14 : 19)
++#endif
++
+ /* $0 is set by ld.so to a pointer to a function which might be
+ registered using atexit. This provides a mean for the dynamic
+ linker to call DT_FINI functions for shared libraries that have
+diff -urNp linux-2.6.38.7/arch/alpha/include/asm/pgtable.h linux-2.6.38.7/arch/alpha/include/asm/pgtable.h
+--- linux-2.6.38.7/arch/alpha/include/asm/pgtable.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/alpha/include/asm/pgtable.h 2011-04-28 19:34:14.000000000 -0400
+@@ -101,6 +101,17 @@ struct vm_area_struct;
+ #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS)
+ #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
+ #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
++
++#ifdef CONFIG_PAX_PAGEEXEC
++# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE)
++# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
++# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
++#else
++# define PAGE_SHARED_NOEXEC PAGE_SHARED
++# define PAGE_COPY_NOEXEC PAGE_COPY
++# define PAGE_READONLY_NOEXEC PAGE_READONLY
++#endif
++
+ #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
+
+ #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
+diff -urNp linux-2.6.38.7/arch/alpha/kernel/module.c linux-2.6.38.7/arch/alpha/kernel/module.c
+--- linux-2.6.38.7/arch/alpha/kernel/module.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/alpha/kernel/module.c 2011-04-28 19:34:14.000000000 -0400
+@@ -182,7 +182,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs,
+
+ /* The small sections were sorted to the end of the segment.
+ The following should definitely cover them. */
+- gp = (u64)me->module_core + me->core_size - 0x8000;
++ gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000;
+ got = sechdrs[me->arch.gotsecindex].sh_addr;
+
+ for (i = 0; i < n; i++) {
+diff -urNp linux-2.6.38.7/arch/alpha/kernel/osf_sys.c linux-2.6.38.7/arch/alpha/kernel/osf_sys.c
+--- linux-2.6.38.7/arch/alpha/kernel/osf_sys.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/alpha/kernel/osf_sys.c 2011-04-28 19:34:14.000000000 -0400
+@@ -1162,7 +1162,7 @@ arch_get_unmapped_area_1(unsigned long a
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (limit - len < addr)
+ return -ENOMEM;
+- if (!vma || addr + len <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr, len))
+ return addr;
+ addr = vma->vm_end;
+ vma = vma->vm_next;
+@@ -1198,6 +1198,10 @@ arch_get_unmapped_area(struct file *filp
+ merely specific addresses, but regions of memory -- perhaps
+ this feature should be incorporated into all ports? */
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ if (addr) {
+ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
+ if (addr != (unsigned long) -ENOMEM)
+@@ -1205,8 +1209,8 @@ arch_get_unmapped_area(struct file *filp
+ }
+
+ /* Next, try allocating at TASK_UNMAPPED_BASE. */
+- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
+- len, limit);
++ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit);
++
+ if (addr != (unsigned long) -ENOMEM)
+ return addr;
+
+diff -urNp linux-2.6.38.7/arch/alpha/kernel/pci_iommu.c linux-2.6.38.7/arch/alpha/kernel/pci_iommu.c
+--- linux-2.6.38.7/arch/alpha/kernel/pci_iommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/alpha/kernel/pci_iommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -950,7 +950,7 @@ static int alpha_pci_set_mask(struct dev
+ return 0;
+ }
+
+-struct dma_map_ops alpha_pci_ops = {
++const struct dma_map_ops alpha_pci_ops = {
+ .alloc_coherent = alpha_pci_alloc_coherent,
+ .free_coherent = alpha_pci_free_coherent,
+ .map_page = alpha_pci_map_page,
+@@ -962,5 +962,5 @@ struct dma_map_ops alpha_pci_ops = {
+ .set_dma_mask = alpha_pci_set_mask,
+ };
+
+-struct dma_map_ops *dma_ops = &alpha_pci_ops;
++const struct dma_map_ops *dma_ops = &alpha_pci_ops;
+ EXPORT_SYMBOL(dma_ops);
+diff -urNp linux-2.6.38.7/arch/alpha/kernel/pci-noop.c linux-2.6.38.7/arch/alpha/kernel/pci-noop.c
+--- linux-2.6.38.7/arch/alpha/kernel/pci-noop.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/alpha/kernel/pci-noop.c 2011-04-28 19:34:14.000000000 -0400
+@@ -173,7 +173,7 @@ static int alpha_noop_set_mask(struct de
+ return 0;
+ }
+
+-struct dma_map_ops alpha_noop_ops = {
++const struct dma_map_ops alpha_noop_ops = {
+ .alloc_coherent = alpha_noop_alloc_coherent,
+ .free_coherent = alpha_noop_free_coherent,
+ .map_page = alpha_noop_map_page,
+@@ -183,7 +183,7 @@ struct dma_map_ops alpha_noop_ops = {
+ .set_dma_mask = alpha_noop_set_mask,
+ };
+
+-struct dma_map_ops *dma_ops = &alpha_noop_ops;
++const struct dma_map_ops *dma_ops = &alpha_noop_ops;
+ EXPORT_SYMBOL(dma_ops);
+
+ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+diff -urNp linux-2.6.38.7/arch/alpha/mm/fault.c linux-2.6.38.7/arch/alpha/mm/fault.c
+--- linux-2.6.38.7/arch/alpha/mm/fault.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/alpha/mm/fault.c 2011-04-28 19:34:14.000000000 -0400
+@@ -54,6 +54,124 @@ __load_new_mm_context(struct mm_struct *
+ __reload_thread(pcb);
+ }
+
++#ifdef CONFIG_PAX_PAGEEXEC
++/*
++ * PaX: decide what to do with offenders (regs->pc = fault address)
++ *
++ * returns 1 when task should be killed
++ * 2 when patched PLT trampoline was detected
++ * 3 when unpatched PLT trampoline was detected
++ */
++static int pax_handle_fetch_fault(struct pt_regs *regs)
++{
++
++#ifdef CONFIG_PAX_EMUPLT
++ int err;
++
++ do { /* PaX: patched PLT emulation #1 */
++ unsigned int ldah, ldq, jmp;
++
++ err = get_user(ldah, (unsigned int *)regs->pc);
++ err |= get_user(ldq, (unsigned int *)(regs->pc+4));
++ err |= get_user(jmp, (unsigned int *)(regs->pc+8));
++
++ if (err)
++ break;
++
++ if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
++ (ldq & 0xFFFF0000U) == 0xA77B0000U &&
++ jmp == 0x6BFB0000U)
++ {
++ unsigned long r27, addr;
++ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
++ unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL;
++
++ addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
++ err = get_user(r27, (unsigned long *)addr);
++ if (err)
++ break;
++
++ regs->r27 = r27;
++ regs->pc = r27;
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: patched PLT emulation #2 */
++ unsigned int ldah, lda, br;
++
++ err = get_user(ldah, (unsigned int *)regs->pc);
++ err |= get_user(lda, (unsigned int *)(regs->pc+4));
++ err |= get_user(br, (unsigned int *)(regs->pc+8));
++
++ if (err)
++ break;
++
++ if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
++ (lda & 0xFFFF0000U) == 0xA77B0000U &&
++ (br & 0xFFE00000U) == 0xC3E00000U)
++ {
++ unsigned long addr = br | 0xFFFFFFFFFFE00000UL;
++ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
++ unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL;
++
++ regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
++ regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: unpatched PLT emulation */
++ unsigned int br;
++
++ err = get_user(br, (unsigned int *)regs->pc);
++
++ if (!err && (br & 0xFFE00000U) == 0xC3800000U) {
++ unsigned int br2, ldq, nop, jmp;
++ unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver;
++
++ addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
++ err = get_user(br2, (unsigned int *)addr);
++ err |= get_user(ldq, (unsigned int *)(addr+4));
++ err |= get_user(nop, (unsigned int *)(addr+8));
++ err |= get_user(jmp, (unsigned int *)(addr+12));
++ err |= get_user(resolver, (unsigned long *)(addr+16));
++
++ if (err)
++ break;
++
++ if (br2 == 0xC3600000U &&
++ ldq == 0xA77B000CU &&
++ nop == 0x47FF041FU &&
++ jmp == 0x6B7B0000U)
++ {
++ regs->r28 = regs->pc+4;
++ regs->r27 = addr+16;
++ regs->pc = resolver;
++ return 3;
++ }
++ }
++ } while (0);
++#endif
++
++ return 1;
++}
++
++void pax_report_insns(void *pc, void *sp)
++{
++ unsigned long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 5; i++) {
++ unsigned int c;
++ if (get_user(c, (unsigned int *)pc+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%08x ", c);
++ }
++ printk("\n");
++}
++#endif
+
+ /*
+ * This routine handles page faults. It determines the address,
+@@ -131,8 +249,29 @@ do_page_fault(unsigned long address, uns
+ good_area:
+ si_code = SEGV_ACCERR;
+ if (cause < 0) {
+- if (!(vma->vm_flags & VM_EXEC))
++ if (!(vma->vm_flags & VM_EXEC)) {
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc)
++ goto bad_area;
++
++ up_read(&mm->mmap_sem);
++ switch (pax_handle_fetch_fault(regs)) {
++
++#ifdef CONFIG_PAX_EMUPLT
++ case 2:
++ case 3:
++ return;
++#endif
++
++ }
++ pax_report_fault(regs, (void *)regs->pc, (void *)rdusp());
++ do_group_exit(SIGKILL);
++#else
+ goto bad_area;
++#endif
++
++ }
+ } else if (!cause) {
+ /* Allow reads even for write-only mappings */
+ if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
+diff -urNp linux-2.6.38.7/arch/arm/include/asm/elf.h linux-2.6.38.7/arch/arm/include/asm/elf.h
+--- linux-2.6.38.7/arch/arm/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/include/asm/elf.h 2011-04-28 19:34:14.000000000 -0400
+@@ -115,7 +115,14 @@ int dump_task_regs(struct task_struct *t
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
++#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
++
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE 0x00008000UL
++
++#define PAX_DELTA_MMAP_LEN ((current->personality == PER_LINUX_32BIT) ? 16 : 10)
++#define PAX_DELTA_STACK_LEN ((current->personality == PER_LINUX_32BIT) ? 16 : 10)
++#endif
+
+ /* When the program starts, a1 contains a pointer to a function to be
+ registered with atexit, as per the SVR4 ABI. A value of 0 means we
+@@ -125,10 +132,6 @@ int dump_task_regs(struct task_struct *t
+ extern void elf_set_personality(const struct elf32_hdr *);
+ #define SET_PERSONALITY(ex) elf_set_personality(&(ex))
+
+-struct mm_struct;
+-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+-#define arch_randomize_brk arch_randomize_brk
+-
+ extern int vectors_user_mapping(void);
+ #define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
+ #define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+diff -urNp linux-2.6.38.7/arch/arm/include/asm/kmap_types.h linux-2.6.38.7/arch/arm/include/asm/kmap_types.h
+--- linux-2.6.38.7/arch/arm/include/asm/kmap_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/include/asm/kmap_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -21,6 +21,7 @@ enum km_type {
+ KM_L1_CACHE,
+ KM_L2_CACHE,
+ KM_KDB,
++ KM_CLEARPAGE,
+ KM_TYPE_NR
+ };
+
+diff -urNp linux-2.6.38.7/arch/arm/include/asm/uaccess.h linux-2.6.38.7/arch/arm/include/asm/uaccess.h
+--- linux-2.6.38.7/arch/arm/include/asm/uaccess.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/include/asm/uaccess.h 2011-04-28 19:34:14.000000000 -0400
+@@ -403,6 +403,9 @@ extern unsigned long __must_check __strn
+
+ static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
++ if ((long)n < 0)
++ return n;
++
+ if (access_ok(VERIFY_READ, from, n))
+ n = __copy_from_user(to, from, n);
+ else /* security hole - plug it */
+@@ -412,6 +415,9 @@ static inline unsigned long __must_check
+
+ static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
++ if ((long)n < 0)
++ return n;
++
+ if (access_ok(VERIFY_WRITE, to, n))
+ n = __copy_to_user(to, from, n);
+ return n;
+diff -urNp linux-2.6.38.7/arch/arm/kernel/kgdb.c linux-2.6.38.7/arch/arm/kernel/kgdb.c
+--- linux-2.6.38.7/arch/arm/kernel/kgdb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/kernel/kgdb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -246,7 +246,7 @@ void kgdb_arch_exit(void)
+ * and we handle the normal undef case within the do_undefinstr
+ * handler.
+ */
+-struct kgdb_arch arch_kgdb_ops = {
++const struct kgdb_arch arch_kgdb_ops = {
+ #ifndef __ARMEB__
+ .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
+ #else /* ! __ARMEB__ */
+diff -urNp linux-2.6.38.7/arch/arm/kernel/process.c linux-2.6.38.7/arch/arm/kernel/process.c
+--- linux-2.6.38.7/arch/arm/kernel/process.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/kernel/process.c 2011-04-28 19:34:14.000000000 -0400
+@@ -28,7 +28,6 @@
+ #include <linux/tick.h>
+ #include <linux/utsname.h>
+ #include <linux/uaccess.h>
+-#include <linux/random.h>
+ #include <linux/hw_breakpoint.h>
+
+ #include <asm/cacheflush.h>
+@@ -477,12 +476,6 @@ unsigned long get_wchan(struct task_stru
+ return 0;
+ }
+
+-unsigned long arch_randomize_brk(struct mm_struct *mm)
+-{
+- unsigned long range_end = mm->brk + 0x02000000;
+- return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+-}
+-
+ #ifdef CONFIG_MMU
+ /*
+ * The vectors page is always readable from user space for the
+diff -urNp linux-2.6.38.7/arch/arm/mach-msm/last_radio_log.c linux-2.6.38.7/arch/arm/mach-msm/last_radio_log.c
+--- linux-2.6.38.7/arch/arm/mach-msm/last_radio_log.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/mach-msm/last_radio_log.c 2011-04-28 19:34:14.000000000 -0400
+@@ -47,7 +47,7 @@ static ssize_t last_radio_log_read(struc
+ return count;
+ }
+
+-static struct file_operations last_radio_log_fops = {
++static struct file_operations last_radio_log_fops = { /* cannot be const, see msm_init_last_radio_log */
+ .read = last_radio_log_read,
+ .llseek = default_llseek,
+ };
+diff -urNp linux-2.6.38.7/arch/arm/mach-ux500/mbox-db5500.c linux-2.6.38.7/arch/arm/mach-ux500/mbox-db5500.c
+--- linux-2.6.38.7/arch/arm/mach-ux500/mbox-db5500.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/mach-ux500/mbox-db5500.c 2011-04-28 19:34:14.000000000 -0400
+@@ -168,7 +168,7 @@ static ssize_t mbox_read_fifo(struct dev
+ return sprintf(buf, "0x%X\n", mbox_value);
+ }
+
+-static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
++static DEVICE_ATTR(fifo, S_IWUSR | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
+
+ static int mbox_show(struct seq_file *s, void *data)
+ {
+diff -urNp linux-2.6.38.7/arch/arm/mm/fault.c linux-2.6.38.7/arch/arm/mm/fault.c
+--- linux-2.6.38.7/arch/arm/mm/fault.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/mm/fault.c 2011-04-28 19:34:14.000000000 -0400
+@@ -167,6 +167,13 @@ __do_user_fault(struct task_struct *tsk,
+ }
+ #endif
+
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (fsr & FSR_LNX_PF) {
++ pax_report_fault(regs, (void *)regs->ARM_pc, (void *)regs->ARM_sp);
++ do_group_exit(SIGKILL);
++ }
++#endif
++
+ tsk->thread.address = addr;
+ tsk->thread.error_code = fsr;
+ tsk->thread.trap_no = 14;
+@@ -364,6 +371,33 @@ do_page_fault(unsigned long addr, unsign
+ }
+ #endif /* CONFIG_MMU */
+
++#ifdef CONFIG_PAX_PAGEEXEC
++void pax_report_insns(void *pc, void *sp)
++{
++ long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 20; i++) {
++ unsigned char c;
++ if (get_user(c, (__force unsigned char __user *)pc+i))
++ printk(KERN_CONT "?? ");
++ else
++ printk(KERN_CONT "%02x ", c);
++ }
++ printk("\n");
++
++ printk(KERN_ERR "PAX: bytes at SP-4: ");
++ for (i = -1; i < 20; i++) {
++ unsigned long c;
++ if (get_user(c, (__force unsigned long __user *)sp+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%08lx ", c);
++ }
++ printk("\n");
++}
++#endif
++
+ /*
+ * First Level Translation Fault Handler
+ *
+diff -urNp linux-2.6.38.7/arch/arm/mm/mmap.c linux-2.6.38.7/arch/arm/mm/mmap.c
+--- linux-2.6.38.7/arch/arm/mm/mmap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/arm/mm/mmap.c 2011-04-28 19:34:14.000000000 -0400
+@@ -64,6 +64,10 @@ arch_get_unmapped_area(struct file *filp
+ if (len > TASK_SIZE)
+ return -ENOMEM;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ if (addr) {
+ if (do_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+@@ -71,15 +75,14 @@ arch_get_unmapped_area(struct file *filp
+ addr = PAGE_ALIGN(addr);
+
+ vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (TASK_SIZE - len >= addr && check_heap_stack_gap(vma, addr, len))
+ return addr;
+ }
+ if (len > mm->cached_hole_size) {
+- start_addr = addr = mm->free_area_cache;
++ start_addr = addr = mm->free_area_cache;
+ } else {
+- start_addr = addr = TASK_UNMAPPED_BASE;
+- mm->cached_hole_size = 0;
++ start_addr = addr = mm->mmap_base;
++ mm->cached_hole_size = 0;
+ }
+ /* 8 bits of randomness in 20 address space bits */
+ if (current->flags & PF_RANDOMIZE)
+@@ -98,14 +101,14 @@ full_search:
+ * Start a new search - just in case we missed
+ * some holes.
+ */
+- if (start_addr != TASK_UNMAPPED_BASE) {
+- start_addr = addr = TASK_UNMAPPED_BASE;
++ if (start_addr != mm->mmap_base) {
++ start_addr = addr = mm->mmap_base;
+ mm->cached_hole_size = 0;
+ goto full_search;
+ }
+ return -ENOMEM;
+ }
+- if (!vma || addr + len <= vma->vm_start) {
++ if (check_heap_stack_gap(vma, addr, len)) {
+ /*
+ * Remember the place where we stopped the search:
+ */
+diff -urNp linux-2.6.38.7/arch/avr32/include/asm/elf.h linux-2.6.38.7/arch/avr32/include/asm/elf.h
+--- linux-2.6.38.7/arch/avr32/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/avr32/include/asm/elf.h 2011-04-28 19:34:14.000000000 -0400
+@@ -84,8 +84,14 @@ typedef struct user_fpu_struct elf_fpreg
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
++#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE 0x00001000UL
++
++#define PAX_DELTA_MMAP_LEN 15
++#define PAX_DELTA_STACK_LEN 15
++#endif
+
+ /* This yields a mask that user programs can use to figure out what
+ instruction set this CPU supports. This could be done in user space,
+diff -urNp linux-2.6.38.7/arch/avr32/include/asm/kmap_types.h linux-2.6.38.7/arch/avr32/include/asm/kmap_types.h
+--- linux-2.6.38.7/arch/avr32/include/asm/kmap_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/avr32/include/asm/kmap_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -22,7 +22,8 @@ D(10) KM_IRQ0,
+ D(11) KM_IRQ1,
+ D(12) KM_SOFTIRQ0,
+ D(13) KM_SOFTIRQ1,
+-D(14) KM_TYPE_NR
++D(14) KM_CLEARPAGE,
++D(15) KM_TYPE_NR
+ };
+
+ #undef D
+diff -urNp linux-2.6.38.7/arch/avr32/mm/fault.c linux-2.6.38.7/arch/avr32/mm/fault.c
+--- linux-2.6.38.7/arch/avr32/mm/fault.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/avr32/mm/fault.c 2011-04-28 19:34:14.000000000 -0400
+@@ -41,6 +41,23 @@ static inline int notify_page_fault(stru
+
+ int exception_trace = 1;
+
++#ifdef CONFIG_PAX_PAGEEXEC
++void pax_report_insns(void *pc, void *sp)
++{
++ unsigned long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 20; i++) {
++ unsigned char c;
++ if (get_user(c, (unsigned char *)pc+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%02x ", c);
++ }
++ printk("\n");
++}
++#endif
++
+ /*
+ * This routine handles page faults. It determines the address and the
+ * problem, and then passes it off to one of the appropriate routines.
+@@ -156,6 +173,16 @@ bad_area:
+ up_read(&mm->mmap_sem);
+
+ if (user_mode(regs)) {
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (mm->pax_flags & MF_PAX_PAGEEXEC) {
++ if (ecr == ECR_PROTECTION_X || ecr == ECR_TLB_MISS_X) {
++ pax_report_fault(regs, (void *)regs->pc, (void *)regs->sp);
++ do_group_exit(SIGKILL);
++ }
++ }
++#endif
++
+ if (exception_trace && printk_ratelimit())
+ printk("%s%s[%d]: segfault at %08lx pc %08lx "
+ "sp %08lx ecr %lu\n",
+diff -urNp linux-2.6.38.7/arch/blackfin/kernel/kgdb.c linux-2.6.38.7/arch/blackfin/kernel/kgdb.c
+--- linux-2.6.38.7/arch/blackfin/kernel/kgdb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/blackfin/kernel/kgdb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -420,7 +420,7 @@ int kgdb_arch_handle_exception(int vecto
+ return -1; /* this means that we do not want to exit from the handler */
+ }
+
+-struct kgdb_arch arch_kgdb_ops = {
++const struct kgdb_arch arch_kgdb_ops = {
+ .gdb_bpt_instr = {0xa1},
+ #ifdef CONFIG_SMP
+ .flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP,
+diff -urNp linux-2.6.38.7/arch/blackfin/mm/maccess.c linux-2.6.38.7/arch/blackfin/mm/maccess.c
+--- linux-2.6.38.7/arch/blackfin/mm/maccess.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/blackfin/mm/maccess.c 2011-04-28 19:34:14.000000000 -0400
+@@ -16,7 +16,7 @@ static int validate_memory_access_addres
+ return bfin_mem_access_type(addr, size);
+ }
+
+-long probe_kernel_read(void *dst, void *src, size_t size)
++long probe_kernel_read(void *dst, const void *src, size_t size)
+ {
+ unsigned long lsrc = (unsigned long)src;
+ int mem_type;
+@@ -55,7 +55,7 @@ long probe_kernel_read(void *dst, void *
+ return -EFAULT;
+ }
+
+-long probe_kernel_write(void *dst, void *src, size_t size)
++long probe_kernel_write(void *dst, const void *src, size_t size)
+ {
+ unsigned long ldst = (unsigned long)dst;
+ int mem_type;
+diff -urNp linux-2.6.38.7/arch/frv/include/asm/kmap_types.h linux-2.6.38.7/arch/frv/include/asm/kmap_types.h
+--- linux-2.6.38.7/arch/frv/include/asm/kmap_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/frv/include/asm/kmap_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -23,6 +23,7 @@ enum km_type {
+ KM_IRQ1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
++ KM_CLEARPAGE,
+ KM_TYPE_NR
+ };
+
+diff -urNp linux-2.6.38.7/arch/frv/mm/elf-fdpic.c linux-2.6.38.7/arch/frv/mm/elf-fdpic.c
+--- linux-2.6.38.7/arch/frv/mm/elf-fdpic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/frv/mm/elf-fdpic.c 2011-04-28 19:34:14.000000000 -0400
+@@ -73,8 +73,7 @@ unsigned long arch_get_unmapped_area(str
+ if (addr) {
+ addr = PAGE_ALIGN(addr);
+ vma = find_vma(current->mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (TASK_SIZE - len >= addr && check_heap_stack_gap(vma, addr, len))
+ goto success;
+ }
+
+@@ -89,7 +88,7 @@ unsigned long arch_get_unmapped_area(str
+ for (; vma; vma = vma->vm_next) {
+ if (addr > limit)
+ break;
+- if (addr + len <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr, len))
+ goto success;
+ addr = vma->vm_end;
+ }
+@@ -104,7 +103,7 @@ unsigned long arch_get_unmapped_area(str
+ for (; vma; vma = vma->vm_next) {
+ if (addr > limit)
+ break;
+- if (addr + len <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr, len))
+ goto success;
+ addr = vma->vm_end;
+ }
+diff -urNp linux-2.6.38.7/arch/ia64/hp/common/hwsw_iommu.c linux-2.6.38.7/arch/ia64/hp/common/hwsw_iommu.c
+--- linux-2.6.38.7/arch/ia64/hp/common/hwsw_iommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/hp/common/hwsw_iommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -17,7 +17,7 @@
+ #include <linux/swiotlb.h>
+ #include <asm/machvec.h>
+
+-extern struct dma_map_ops sba_dma_ops, swiotlb_dma_ops;
++extern const struct dma_map_ops sba_dma_ops, swiotlb_dma_ops;
+
+ /* swiotlb declarations & definitions: */
+ extern int swiotlb_late_init_with_default_size (size_t size);
+@@ -33,7 +33,7 @@ static inline int use_swiotlb(struct dev
+ !sba_dma_ops.dma_supported(dev, *dev->dma_mask);
+ }
+
+-struct dma_map_ops *hwsw_dma_get_ops(struct device *dev)
++const struct dma_map_ops *hwsw_dma_get_ops(struct device *dev)
+ {
+ if (use_swiotlb(dev))
+ return &swiotlb_dma_ops;
+diff -urNp linux-2.6.38.7/arch/ia64/hp/common/sba_iommu.c linux-2.6.38.7/arch/ia64/hp/common/sba_iommu.c
+--- linux-2.6.38.7/arch/ia64/hp/common/sba_iommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/hp/common/sba_iommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -2097,7 +2097,7 @@ static struct acpi_driver acpi_sba_ioc_d
+ },
+ };
+
+-extern struct dma_map_ops swiotlb_dma_ops;
++extern const struct dma_map_ops swiotlb_dma_ops;
+
+ static int __init
+ sba_init(void)
+@@ -2211,7 +2211,7 @@ sba_page_override(char *str)
+
+ __setup("sbapagesize=",sba_page_override);
+
+-struct dma_map_ops sba_dma_ops = {
++const struct dma_map_ops sba_dma_ops = {
+ .alloc_coherent = sba_alloc_coherent,
+ .free_coherent = sba_free_coherent,
+ .map_page = sba_map_page,
+diff -urNp linux-2.6.38.7/arch/ia64/include/asm/dma-mapping.h linux-2.6.38.7/arch/ia64/include/asm/dma-mapping.h
+--- linux-2.6.38.7/arch/ia64/include/asm/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/include/asm/dma-mapping.h 2011-04-28 19:34:14.000000000 -0400
+@@ -12,7 +12,7 @@
+
+ #define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
+-extern struct dma_map_ops *dma_ops;
++extern const struct dma_map_ops *dma_ops;
+ extern struct ia64_machine_vector ia64_mv;
+ extern void set_iommu_machvec(void);
+
+@@ -24,7 +24,7 @@ extern void machvec_dma_sync_sg(struct d
+ static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *daddr, gfp_t gfp)
+ {
+- struct dma_map_ops *ops = platform_dma_get_ops(dev);
++ const struct dma_map_ops *ops = platform_dma_get_ops(dev);
+ void *caddr;
+
+ caddr = ops->alloc_coherent(dev, size, daddr, gfp);
+@@ -35,7 +35,7 @@ static inline void *dma_alloc_coherent(s
+ static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *caddr, dma_addr_t daddr)
+ {
+- struct dma_map_ops *ops = platform_dma_get_ops(dev);
++ const struct dma_map_ops *ops = platform_dma_get_ops(dev);
+ debug_dma_free_coherent(dev, size, caddr, daddr);
+ ops->free_coherent(dev, size, caddr, daddr);
+ }
+@@ -49,13 +49,13 @@ static inline void dma_free_coherent(str
+
+ static inline int dma_mapping_error(struct device *dev, dma_addr_t daddr)
+ {
+- struct dma_map_ops *ops = platform_dma_get_ops(dev);
++ const struct dma_map_ops *ops = platform_dma_get_ops(dev);
+ return ops->mapping_error(dev, daddr);
+ }
+
+ static inline int dma_supported(struct device *dev, u64 mask)
+ {
+- struct dma_map_ops *ops = platform_dma_get_ops(dev);
++ const struct dma_map_ops *ops = platform_dma_get_ops(dev);
+ return ops->dma_supported(dev, mask);
+ }
+
+diff -urNp linux-2.6.38.7/arch/ia64/include/asm/elf.h linux-2.6.38.7/arch/ia64/include/asm/elf.h
+--- linux-2.6.38.7/arch/ia64/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/include/asm/elf.h 2011-04-28 19:34:14.000000000 -0400
+@@ -42,6 +42,13 @@
+ */
+ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x800000000UL)
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE (current->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
++
++#define PAX_DELTA_MMAP_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
++#define PAX_DELTA_STACK_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
++#endif
++
+ #define PT_IA_64_UNWIND 0x70000001
+
+ /* IA-64 relocations: */
+diff -urNp linux-2.6.38.7/arch/ia64/include/asm/machvec.h linux-2.6.38.7/arch/ia64/include/asm/machvec.h
+--- linux-2.6.38.7/arch/ia64/include/asm/machvec.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/include/asm/machvec.h 2011-04-28 19:34:14.000000000 -0400
+@@ -45,7 +45,7 @@ typedef void ia64_mv_kernel_launch_event
+ /* DMA-mapping interface: */
+ typedef void ia64_mv_dma_init (void);
+ typedef u64 ia64_mv_dma_get_required_mask (struct device *);
+-typedef struct dma_map_ops *ia64_mv_dma_get_ops(struct device *);
++typedef const struct dma_map_ops *ia64_mv_dma_get_ops(struct device *);
+
+ /*
+ * WARNING: The legacy I/O space is _architected_. Platforms are
+@@ -251,7 +251,7 @@ extern void machvec_init_from_cmdline(co
+ # endif /* CONFIG_IA64_GENERIC */
+
+ extern void swiotlb_dma_init(void);
+-extern struct dma_map_ops *dma_get_ops(struct device *);
++extern const struct dma_map_ops *dma_get_ops(struct device *);
+
+ /*
+ * Define default versions so we can extend machvec for new platforms without having
+diff -urNp linux-2.6.38.7/arch/ia64/include/asm/pgtable.h linux-2.6.38.7/arch/ia64/include/asm/pgtable.h
+--- linux-2.6.38.7/arch/ia64/include/asm/pgtable.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/include/asm/pgtable.h 2011-04-28 19:34:14.000000000 -0400
+@@ -12,7 +12,7 @@
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+-
++#include <linux/const.h>
+ #include <asm/mman.h>
+ #include <asm/page.h>
+ #include <asm/processor.h>
+@@ -143,6 +143,17 @@
+ #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
+ #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
+ #define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX)
++
++#ifdef CONFIG_PAX_PAGEEXEC
++# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW)
++# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
++# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
++#else
++# define PAGE_SHARED_NOEXEC PAGE_SHARED
++# define PAGE_READONLY_NOEXEC PAGE_READONLY
++# define PAGE_COPY_NOEXEC PAGE_COPY
++#endif
++
+ #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
+ #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX)
+ #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
+diff -urNp linux-2.6.38.7/arch/ia64/include/asm/spinlock.h linux-2.6.38.7/arch/ia64/include/asm/spinlock.h
+--- linux-2.6.38.7/arch/ia64/include/asm/spinlock.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/include/asm/spinlock.h 2011-04-28 19:34:14.000000000 -0400
+@@ -72,7 +72,7 @@ static __always_inline void __ticket_spi
+ unsigned short *p = (unsigned short *)&lock->lock + 1, tmp;
+
+ asm volatile ("ld2.bias %0=[%1]" : "=r"(tmp) : "r"(p));
+- ACCESS_ONCE(*p) = (tmp + 2) & ~1;
++ ACCESS_ONCE_RW(*p) = (tmp + 2) & ~1;
+ }
+
+ static __always_inline void __ticket_spin_unlock_wait(arch_spinlock_t *lock)
+diff -urNp linux-2.6.38.7/arch/ia64/include/asm/uaccess.h linux-2.6.38.7/arch/ia64/include/asm/uaccess.h
+--- linux-2.6.38.7/arch/ia64/include/asm/uaccess.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/include/asm/uaccess.h 2011-04-28 19:34:14.000000000 -0400
+@@ -257,7 +257,7 @@ __copy_from_user (void *to, const void _
+ const void *__cu_from = (from); \
+ long __cu_len = (n); \
+ \
+- if (__access_ok(__cu_to, __cu_len, get_fs())) \
++ if (__cu_len > 0 && __cu_len <= INT_MAX && __access_ok(__cu_to, __cu_len, get_fs())) \
+ __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \
+ __cu_len; \
+ })
+@@ -269,7 +269,7 @@ __copy_from_user (void *to, const void _
+ long __cu_len = (n); \
+ \
+ __chk_user_ptr(__cu_from); \
+- if (__access_ok(__cu_from, __cu_len, get_fs())) \
++ if (__cu_len > 0 && __cu_len <= INT_MAX && __access_ok(__cu_from, __cu_len, get_fs())) \
+ __cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len); \
+ __cu_len; \
+ })
+diff -urNp linux-2.6.38.7/arch/ia64/kernel/dma-mapping.c linux-2.6.38.7/arch/ia64/kernel/dma-mapping.c
+--- linux-2.6.38.7/arch/ia64/kernel/dma-mapping.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/kernel/dma-mapping.c 2011-04-28 19:34:14.000000000 -0400
+@@ -3,7 +3,7 @@
+ /* Set this to 1 if there is a HW IOMMU in the system */
+ int iommu_detected __read_mostly;
+
+-struct dma_map_ops *dma_ops;
++const struct dma_map_ops *dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+
+ #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+@@ -16,7 +16,7 @@ static int __init dma_init(void)
+ }
+ fs_initcall(dma_init);
+
+-struct dma_map_ops *dma_get_ops(struct device *dev)
++const struct dma_map_ops *dma_get_ops(struct device *dev)
+ {
+ return dma_ops;
+ }
+diff -urNp linux-2.6.38.7/arch/ia64/kernel/module.c linux-2.6.38.7/arch/ia64/kernel/module.c
+--- linux-2.6.38.7/arch/ia64/kernel/module.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/kernel/module.c 2011-04-28 19:34:14.000000000 -0400
+@@ -315,8 +315,7 @@ module_alloc (unsigned long size)
+ void
+ module_free (struct module *mod, void *module_region)
+ {
+- if (mod && mod->arch.init_unw_table &&
+- module_region == mod->module_init) {
++ if (mod && mod->arch.init_unw_table && module_region == mod->module_init_rx) {
+ unw_remove_unwind_table(mod->arch.init_unw_table);
+ mod->arch.init_unw_table = NULL;
+ }
+@@ -502,15 +501,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd
+ }
+
+ static inline int
++in_init_rx (const struct module *mod, uint64_t addr)
++{
++ return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx;
++}
++
++static inline int
++in_init_rw (const struct module *mod, uint64_t addr)
++{
++ return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw;
++}
++
++static inline int
+ in_init (const struct module *mod, uint64_t addr)
+ {
+- return addr - (uint64_t) mod->module_init < mod->init_size;
++ return in_init_rx(mod, addr) || in_init_rw(mod, addr);
++}
++
++static inline int
++in_core_rx (const struct module *mod, uint64_t addr)
++{
++ return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx;
++}
++
++static inline int
++in_core_rw (const struct module *mod, uint64_t addr)
++{
++ return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw;
+ }
+
+ static inline int
+ in_core (const struct module *mod, uint64_t addr)
+ {
+- return addr - (uint64_t) mod->module_core < mod->core_size;
++ return in_core_rx(mod, addr) || in_core_rw(mod, addr);
+ }
+
+ static inline int
+@@ -693,7 +716,14 @@ do_reloc (struct module *mod, uint8_t r_
+ break;
+
+ case RV_BDREL:
+- val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core);
++ if (in_init_rx(mod, val))
++ val -= (uint64_t) mod->module_init_rx;
++ else if (in_init_rw(mod, val))
++ val -= (uint64_t) mod->module_init_rw;
++ else if (in_core_rx(mod, val))
++ val -= (uint64_t) mod->module_core_rx;
++ else if (in_core_rw(mod, val))
++ val -= (uint64_t) mod->module_core_rw;
+ break;
+
+ case RV_LTV:
+@@ -828,15 +858,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs,
+ * addresses have been selected...
+ */
+ uint64_t gp;
+- if (mod->core_size > MAX_LTOFF)
++ if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF)
+ /*
+ * This takes advantage of fact that SHF_ARCH_SMALL gets allocated
+ * at the end of the module.
+ */
+- gp = mod->core_size - MAX_LTOFF / 2;
++ gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2;
+ else
+- gp = mod->core_size / 2;
+- gp = (uint64_t) mod->module_core + ((gp + 7) & -8);
++ gp = (mod->core_size_rx + mod->core_size_rw) / 2;
++ gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8);
+ mod->arch.gp = gp;
+ DEBUGP("%s: placing gp at 0x%lx\n", __func__, gp);
+ }
+diff -urNp linux-2.6.38.7/arch/ia64/kernel/pci-dma.c linux-2.6.38.7/arch/ia64/kernel/pci-dma.c
+--- linux-2.6.38.7/arch/ia64/kernel/pci-dma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/kernel/pci-dma.c 2011-04-28 19:34:14.000000000 -0400
+@@ -43,7 +43,7 @@ struct device fallback_dev = {
+ .dma_mask = &fallback_dev.coherent_dma_mask,
+ };
+
+-extern struct dma_map_ops intel_dma_ops;
++extern const struct dma_map_ops intel_dma_ops;
+
+ static int __init pci_iommu_init(void)
+ {
+diff -urNp linux-2.6.38.7/arch/ia64/kernel/pci-swiotlb.c linux-2.6.38.7/arch/ia64/kernel/pci-swiotlb.c
+--- linux-2.6.38.7/arch/ia64/kernel/pci-swiotlb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/kernel/pci-swiotlb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -22,7 +22,7 @@ static void *ia64_swiotlb_alloc_coherent
+ return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
+ }
+
+-struct dma_map_ops swiotlb_dma_ops = {
++const struct dma_map_ops swiotlb_dma_ops = {
+ .alloc_coherent = ia64_swiotlb_alloc_coherent,
+ .free_coherent = swiotlb_free_coherent,
+ .map_page = swiotlb_map_page,
+diff -urNp linux-2.6.38.7/arch/ia64/kernel/sys_ia64.c linux-2.6.38.7/arch/ia64/kernel/sys_ia64.c
+--- linux-2.6.38.7/arch/ia64/kernel/sys_ia64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/kernel/sys_ia64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -43,6 +43,13 @@ arch_get_unmapped_area (struct file *fil
+ if (REGION_NUMBER(addr) == RGN_HPAGE)
+ addr = 0;
+ #endif
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ addr = mm->free_area_cache;
++ else
++#endif
++
+ if (!addr)
+ addr = mm->free_area_cache;
+
+@@ -61,14 +68,14 @@ arch_get_unmapped_area (struct file *fil
+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) {
+- if (start_addr != TASK_UNMAPPED_BASE) {
++ if (start_addr != mm->mmap_base) {
+ /* Start a new search --- just in case we missed some holes. */
+- addr = TASK_UNMAPPED_BASE;
++ addr = mm->mmap_base;
+ goto full_search;
+ }
+ return -ENOMEM;
+ }
+- if (!vma || addr + len <= vma->vm_start) {
++ if (check_heap_stack_gap(vma, addr, len)) {
+ /* Remember the address where we stopped this search: */
+ mm->free_area_cache = addr + len;
+ return addr;
+diff -urNp linux-2.6.38.7/arch/ia64/kernel/vmlinux.lds.S linux-2.6.38.7/arch/ia64/kernel/vmlinux.lds.S
+--- linux-2.6.38.7/arch/ia64/kernel/vmlinux.lds.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/kernel/vmlinux.lds.S 2011-04-28 19:34:14.000000000 -0400
+@@ -199,7 +199,7 @@ SECTIONS {
+ /* Per-cpu data: */
+ . = ALIGN(PERCPU_PAGE_SIZE);
+ PERCPU_VADDR(PERCPU_ADDR, :percpu)
+- __phys_per_cpu_start = __per_cpu_load;
++ __phys_per_cpu_start = per_cpu_load;
+ /*
+ * ensure percpu data fits
+ * into percpu page size
+diff -urNp linux-2.6.38.7/arch/ia64/mm/fault.c linux-2.6.38.7/arch/ia64/mm/fault.c
+--- linux-2.6.38.7/arch/ia64/mm/fault.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/mm/fault.c 2011-04-28 19:34:14.000000000 -0400
+@@ -72,6 +72,23 @@ mapped_kernel_page_is_present (unsigned
+ return pte_present(pte);
+ }
+
++#ifdef CONFIG_PAX_PAGEEXEC
++void pax_report_insns(void *pc, void *sp)
++{
++ unsigned long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 8; i++) {
++ unsigned int c;
++ if (get_user(c, (unsigned int *)pc+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%08x ", c);
++ }
++ printk("\n");
++}
++#endif
++
+ void __kprobes
+ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
+ {
+@@ -145,9 +162,23 @@ ia64_do_page_fault (unsigned long addres
+ mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
+ | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
+
+- if ((vma->vm_flags & mask) != mask)
++ if ((vma->vm_flags & mask) != mask) {
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) {
++ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip)
++ goto bad_area;
++
++ up_read(&mm->mmap_sem);
++ pax_report_fault(regs, (void *)regs->cr_iip, (void *)regs->r12);
++ do_group_exit(SIGKILL);
++ }
++#endif
++
+ goto bad_area;
+
++ }
++
+ /*
+ * If for any reason at all we couldn't handle the fault, make
+ * sure we exit gracefully rather than endlessly redo the
+diff -urNp linux-2.6.38.7/arch/ia64/mm/hugetlbpage.c linux-2.6.38.7/arch/ia64/mm/hugetlbpage.c
+--- linux-2.6.38.7/arch/ia64/mm/hugetlbpage.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/mm/hugetlbpage.c 2011-04-28 19:34:14.000000000 -0400
+@@ -171,7 +171,7 @@ unsigned long hugetlb_get_unmapped_area(
+ /* At this point: (!vmm || addr < vmm->vm_end). */
+ if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT)
+ return -ENOMEM;
+- if (!vmm || (addr + len) <= vmm->vm_start)
++ if (check_heap_stack_gap(vmm, addr, len))
+ return addr;
+ addr = ALIGN(vmm->vm_end, HPAGE_SIZE);
+ }
+diff -urNp linux-2.6.38.7/arch/ia64/mm/init.c linux-2.6.38.7/arch/ia64/mm/init.c
+--- linux-2.6.38.7/arch/ia64/mm/init.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/mm/init.c 2011-04-28 19:34:14.000000000 -0400
+@@ -122,6 +122,19 @@ ia64_init_addr_space (void)
+ vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
+ vma->vm_end = vma->vm_start + PAGE_SIZE;
+ vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT;
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (current->mm->pax_flags & MF_PAX_PAGEEXEC) {
++ vma->vm_flags &= ~VM_EXEC;
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (current->mm->pax_flags & MF_PAX_MPROTECT)
++ vma->vm_flags &= ~VM_MAYEXEC;
++#endif
++
++ }
++#endif
++
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ down_write(&current->mm->mmap_sem);
+ if (insert_vm_struct(current->mm, vma)) {
+diff -urNp linux-2.6.38.7/arch/ia64/sn/pci/pci_dma.c linux-2.6.38.7/arch/ia64/sn/pci/pci_dma.c
+--- linux-2.6.38.7/arch/ia64/sn/pci/pci_dma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/ia64/sn/pci/pci_dma.c 2011-04-28 19:34:14.000000000 -0400
+@@ -465,7 +465,7 @@ int sn_pci_legacy_write(struct pci_bus *
+ return ret;
+ }
+
+-static struct dma_map_ops sn_dma_ops = {
++static const struct dma_map_ops sn_dma_ops = {
+ .alloc_coherent = sn_dma_alloc_coherent,
+ .free_coherent = sn_dma_free_coherent,
+ .map_page = sn_dma_map_page,
+diff -urNp linux-2.6.38.7/arch/m32r/lib/usercopy.c linux-2.6.38.7/arch/m32r/lib/usercopy.c
+--- linux-2.6.38.7/arch/m32r/lib/usercopy.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/m32r/lib/usercopy.c 2011-04-28 19:34:14.000000000 -0400
+@@ -14,6 +14,9 @@
+ unsigned long
+ __generic_copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
++ if ((long)n < 0)
++ return n;
++
+ prefetch(from);
+ if (access_ok(VERIFY_WRITE, to, n))
+ __copy_user(to,from,n);
+@@ -23,6 +26,9 @@ __generic_copy_to_user(void __user *to,
+ unsigned long
+ __generic_copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
++ if ((long)n < 0)
++ return n;
++
+ prefetchw(to);
+ if (access_ok(VERIFY_READ, from, n))
+ __copy_user_zeroing(to,from,n);
+diff -urNp linux-2.6.38.7/arch/microblaze/include/asm/device.h linux-2.6.38.7/arch/microblaze/include/asm/device.h
+--- linux-2.6.38.7/arch/microblaze/include/asm/device.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/microblaze/include/asm/device.h 2011-04-28 19:34:14.000000000 -0400
+@@ -13,7 +13,7 @@ struct device_node;
+
+ struct dev_archdata {
+ /* DMA operations on that device */
+- struct dma_map_ops *dma_ops;
++ const struct dma_map_ops *dma_ops;
+ void *dma_data;
+ };
+
+diff -urNp linux-2.6.38.7/arch/microblaze/include/asm/dma-mapping.h linux-2.6.38.7/arch/microblaze/include/asm/dma-mapping.h
+--- linux-2.6.38.7/arch/microblaze/include/asm/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/microblaze/include/asm/dma-mapping.h 2011-04-28 19:34:14.000000000 -0400
+@@ -43,14 +43,14 @@ static inline unsigned long device_to_ma
+ return 0xfffffffful;
+ }
+
+-extern struct dma_map_ops *dma_ops;
++extern const struct dma_map_ops *dma_ops;
+
+ /*
+ * Available generic sets of operations
+ */
+-extern struct dma_map_ops dma_direct_ops;
++extern const struct dma_map_ops dma_direct_ops;
+
+-static inline struct dma_map_ops *get_dma_ops(struct device *dev)
++static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
+ {
+ /* We don't handle the NULL dev case for ISA for now. We could
+ * do it via an out of line call but it is not needed for now. The
+@@ -63,14 +63,14 @@ static inline struct dma_map_ops *get_dm
+ return dev->archdata.dma_ops;
+ }
+
+-static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
++static inline void set_dma_ops(struct device *dev, const struct dma_map_ops *ops)
+ {
+ dev->archdata.dma_ops = ops;
+ }
+
+ static inline int dma_supported(struct device *dev, u64 mask)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ if (unlikely(!ops))
+ return 0;
+@@ -81,7 +81,7 @@ static inline int dma_supported(struct d
+
+ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ if (unlikely(ops == NULL))
+ return -EIO;
+@@ -97,7 +97,7 @@ static inline int dma_set_mask(struct de
+
+ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ if (ops->mapping_error)
+ return ops->mapping_error(dev, dma_addr);
+
+@@ -110,7 +110,7 @@ static inline int dma_mapping_error(stru
+ static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ void *memory;
+
+ BUG_ON(!ops);
+@@ -124,7 +124,7 @@ static inline void *dma_alloc_coherent(s
+ static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!ops);
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+diff -urNp linux-2.6.38.7/arch/microblaze/include/asm/pci.h linux-2.6.38.7/arch/microblaze/include/asm/pci.h
+--- linux-2.6.38.7/arch/microblaze/include/asm/pci.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/microblaze/include/asm/pci.h 2011-04-28 19:34:14.000000000 -0400
+@@ -54,8 +54,8 @@ static inline void pcibios_penalize_isa_
+ }
+
+ #ifdef CONFIG_PCI
+-extern void set_pci_dma_ops(struct dma_map_ops *dma_ops);
+-extern struct dma_map_ops *get_pci_dma_ops(void);
++extern void set_pci_dma_ops(const struct dma_map_ops *dma_ops);
++extern const struct dma_map_ops *get_pci_dma_ops(void);
+ #else /* CONFIG_PCI */
+ #define set_pci_dma_ops(d)
+ #define get_pci_dma_ops() NULL
+diff -urNp linux-2.6.38.7/arch/microblaze/kernel/dma.c linux-2.6.38.7/arch/microblaze/kernel/dma.c
+--- linux-2.6.38.7/arch/microblaze/kernel/dma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/microblaze/kernel/dma.c 2011-04-28 19:34:14.000000000 -0400
+@@ -133,7 +133,7 @@ static inline void dma_direct_unmap_page
+ __dma_sync_page(dma_address, 0 , size, direction);
+ }
+
+-struct dma_map_ops dma_direct_ops = {
++const struct dma_map_ops dma_direct_ops = {
+ .alloc_coherent = dma_direct_alloc_coherent,
+ .free_coherent = dma_direct_free_coherent,
+ .map_sg = dma_direct_map_sg,
+diff -urNp linux-2.6.38.7/arch/microblaze/kernel/kgdb.c linux-2.6.38.7/arch/microblaze/kernel/kgdb.c
+--- linux-2.6.38.7/arch/microblaze/kernel/kgdb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/microblaze/kernel/kgdb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -141,10 +141,11 @@ void kgdb_arch_exit(void)
+ /*
+ * Global data
+ */
+-struct kgdb_arch arch_kgdb_ops = {
++const struct kgdb_arch arch_kgdb_ops = {
+ #ifdef __MICROBLAZEEL__
+ .gdb_bpt_instr = {0x18, 0x00, 0x0c, 0xba}, /* brki r16, 0x18 */
+ #else
++>>>>>>> master
+ .gdb_bpt_instr = {0xba, 0x0c, 0x00, 0x18}, /* brki r16, 0x18 */
+ #endif
+ };
+diff -urNp linux-2.6.38.7/arch/microblaze/pci/pci-common.c linux-2.6.38.7/arch/microblaze/pci/pci-common.c
+--- linux-2.6.38.7/arch/microblaze/pci/pci-common.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/microblaze/pci/pci-common.c 2011-04-28 19:34:14.000000000 -0400
+@@ -47,14 +47,14 @@ resource_size_t isa_mem_base;
+ /* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
+ unsigned int pci_flags;
+
+-static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
++static const struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
+
+-void set_pci_dma_ops(struct dma_map_ops *dma_ops)
++void set_pci_dma_ops(const struct dma_map_ops *dma_ops)
+ {
+ pci_dma_ops = dma_ops;
+ }
+
+-struct dma_map_ops *get_pci_dma_ops(void)
++const struct dma_map_ops *get_pci_dma_ops(void)
+ {
+ return pci_dma_ops;
+ }
+diff -urNp linux-2.6.38.7/arch/mips/cavium-octeon/dma-octeon.c linux-2.6.38.7/arch/mips/cavium-octeon/dma-octeon.c
+--- linux-2.6.38.7/arch/mips/cavium-octeon/dma-octeon.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/cavium-octeon/dma-octeon.c 2011-04-28 19:34:14.000000000 -0400
+@@ -202,7 +202,7 @@ static phys_addr_t octeon_unity_dma_to_p
+ }
+
+ struct octeon_dma_map_ops {
+- struct dma_map_ops dma_map_ops;
++ const struct dma_map_ops dma_map_ops;
+ dma_addr_t (*phys_to_dma)(struct device *dev, phys_addr_t paddr);
+ phys_addr_t (*dma_to_phys)(struct device *dev, dma_addr_t daddr);
+ };
+@@ -324,7 +324,7 @@ static struct octeon_dma_map_ops _octeon
+ },
+ };
+
+-struct dma_map_ops *octeon_pci_dma_map_ops;
++const struct dma_map_ops *octeon_pci_dma_map_ops;
+
+ void __init octeon_pci_dma_init(void)
+ {
+diff -urNp linux-2.6.38.7/arch/mips/include/asm/device.h linux-2.6.38.7/arch/mips/include/asm/device.h
+--- linux-2.6.38.7/arch/mips/include/asm/device.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/include/asm/device.h 2011-04-28 19:34:14.000000000 -0400
+@@ -10,7 +10,7 @@ struct dma_map_ops;
+
+ struct dev_archdata {
+ /* DMA operations on that device */
+- struct dma_map_ops *dma_ops;
++ const struct dma_map_ops *dma_ops;
+ };
+
+ struct pdev_archdata {
+diff -urNp linux-2.6.38.7/arch/mips/include/asm/dma-mapping.h linux-2.6.38.7/arch/mips/include/asm/dma-mapping.h
+--- linux-2.6.38.7/arch/mips/include/asm/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/include/asm/dma-mapping.h 2011-04-28 19:34:14.000000000 -0400
+@@ -7,9 +7,9 @@
+
+ #include <dma-coherence.h>
+
+-extern struct dma_map_ops *mips_dma_map_ops;
++extern const struct dma_map_ops *mips_dma_map_ops;
+
+-static inline struct dma_map_ops *get_dma_ops(struct device *dev)
++static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
+ {
+ if (dev && dev->archdata.dma_ops)
+ return dev->archdata.dma_ops;
+@@ -31,13 +31,13 @@ static inline void dma_mark_clean(void *
+
+ static inline int dma_supported(struct device *dev, u64 mask)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ return ops->dma_supported(dev, mask);
+ }
+
+ static inline int dma_mapping_error(struct device *dev, u64 mask)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ return ops->mapping_error(dev, mask);
+ }
+
+@@ -59,7 +59,7 @@ static inline void *dma_alloc_coherent(s
+ dma_addr_t *dma_handle, gfp_t gfp)
+ {
+ void *ret;
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ ret = ops->alloc_coherent(dev, size, dma_handle, gfp);
+
+@@ -71,7 +71,7 @@ static inline void *dma_alloc_coherent(s
+ static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ ops->free_coherent(dev, size, vaddr, dma_handle);
+
+diff -urNp linux-2.6.38.7/arch/mips/include/asm/elf.h linux-2.6.38.7/arch/mips/include/asm/elf.h
+--- linux-2.6.38.7/arch/mips/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/include/asm/elf.h 2011-04-30 19:58:48.000000000 -0400
+@@ -372,13 +372,16 @@ extern const char *__elf_platform;
+ #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
+ #endif
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE (TASK_IS_32BIT_ADDR ? 0x00400000UL : 0x00400000UL)
++
++#define PAX_DELTA_MMAP_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
++#define PAX_DELTA_STACK_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
++#endif
++
+ #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+ struct linux_binprm;
+ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp);
+
+-struct mm_struct;
+-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+-#define arch_randomize_brk arch_randomize_brk
+-
+ #endif /* _ASM_ELF_H */
+diff -urNp linux-2.6.38.7/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h linux-2.6.38.7/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+--- linux-2.6.38.7/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h 2011-04-28 19:34:14.000000000 -0400
+@@ -66,7 +66,7 @@ dma_addr_t phys_to_dma(struct device *de
+ phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
+
+ struct dma_map_ops;
+-extern struct dma_map_ops *octeon_pci_dma_map_ops;
++extern const struct dma_map_ops *octeon_pci_dma_map_ops;
+ extern char *octeon_swiotlb;
+
+ #endif /* __ASM_MACH_CAVIUM_OCTEON_DMA_COHERENCE_H */
+diff -urNp linux-2.6.38.7/arch/mips/include/asm/page.h linux-2.6.38.7/arch/mips/include/asm/page.h
+--- linux-2.6.38.7/arch/mips/include/asm/page.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/include/asm/page.h 2011-04-28 19:34:14.000000000 -0400
+@@ -93,7 +93,7 @@ extern void copy_user_highpage(struct pa
+ #ifdef CONFIG_CPU_MIPS32
+ typedef struct { unsigned long pte_low, pte_high; } pte_t;
+ #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+- #define __pte(x) ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; })
++ #define __pte(x) ({ pte_t __pte = {(x), (x) >> 32}; __pte; })
+ #else
+ typedef struct { unsigned long long pte; } pte_t;
+ #define pte_val(x) ((x).pte)
+diff -urNp linux-2.6.38.7/arch/mips/include/asm/system.h linux-2.6.38.7/arch/mips/include/asm/system.h
+--- linux-2.6.38.7/arch/mips/include/asm/system.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/include/asm/system.h 2011-04-28 19:34:14.000000000 -0400
+@@ -230,6 +230,6 @@ extern void per_cpu_trap_init(void);
+ */
+ #define __ARCH_WANT_UNLOCKED_CTXSW
+
+-extern unsigned long arch_align_stack(unsigned long sp);
++#define arch_align_stack(x) ((x) & ~0xfUL)
+
+ #endif /* _ASM_SYSTEM_H */
+diff -urNp linux-2.6.38.7/arch/mips/kernel/binfmt_elfn32.c linux-2.6.38.7/arch/mips/kernel/binfmt_elfn32.c
+--- linux-2.6.38.7/arch/mips/kernel/binfmt_elfn32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/kernel/binfmt_elfn32.c 2011-04-30 19:58:48.000000000 -0400
+@@ -50,6 +50,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
+ #undef ELF_ET_DYN_BASE
+ #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE (TASK_IS_32BIT_ADDR ? 0x00400000UL : 0x00400000UL)
++
++#define PAX_DELTA_MMAP_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
++#define PAX_DELTA_STACK_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
++#endif
++
+ #include <asm/processor.h>
+ #include <linux/module.h>
+ #include <linux/elfcore.h>
+diff -urNp linux-2.6.38.7/arch/mips/kernel/binfmt_elfo32.c linux-2.6.38.7/arch/mips/kernel/binfmt_elfo32.c
+--- linux-2.6.38.7/arch/mips/kernel/binfmt_elfo32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/kernel/binfmt_elfo32.c 2011-04-30 19:58:48.000000000 -0400
+@@ -52,6 +52,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
+ #undef ELF_ET_DYN_BASE
+ #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE (TASK_IS_32BIT_ADDR ? 0x00400000UL : 0x00400000UL)
++
++#define PAX_DELTA_MMAP_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
++#define PAX_DELTA_STACK_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
++#endif
++
+ #include <asm/processor.h>
+
+ /*
+diff -urNp linux-2.6.38.7/arch/mips/kernel/kgdb.c linux-2.6.38.7/arch/mips/kernel/kgdb.c
+--- linux-2.6.38.7/arch/mips/kernel/kgdb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/kernel/kgdb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -351,7 +351,7 @@ int kgdb_arch_handle_exception(int vecto
+ return -1;
+ }
+
+-struct kgdb_arch arch_kgdb_ops;
++struct kgdb_arch arch_kgdb_ops; /* cannot be const, see kgdb_arch_init */
+
+ /*
+ * We use kgdb_early_setup so that functions we need to call now don't
+diff -urNp linux-2.6.38.7/arch/mips/kernel/process.c linux-2.6.38.7/arch/mips/kernel/process.c
+--- linux-2.6.38.7/arch/mips/kernel/process.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/kernel/process.c 2011-04-28 19:34:14.000000000 -0400
+@@ -473,15 +473,3 @@ unsigned long get_wchan(struct task_stru
+ out:
+ return pc;
+ }
+-
+-/*
+- * Don't forget that the stack pointer must be aligned on a 8 bytes
+- * boundary for 32-bits ABI and 16 bytes for 64-bits ABI.
+- */
+-unsigned long arch_align_stack(unsigned long sp)
+-{
+- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+- sp -= get_random_int() & ~PAGE_MASK;
+-
+- return sp & ALMASK;
+-}
+diff -urNp linux-2.6.38.7/arch/mips/kernel/syscall.c linux-2.6.38.7/arch/mips/kernel/syscall.c
+--- linux-2.6.38.7/arch/mips/kernel/syscall.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/kernel/syscall.c 2011-04-30 19:58:48.000000000 -0400
+@@ -108,14 +108,18 @@ unsigned long arch_get_unmapped_area(str
+ do_color_align = 0;
+ if (filp || (flags & MAP_SHARED))
+ do_color_align = 1;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ if (addr) {
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ else
+ addr = PAGE_ALIGN(addr);
+ vmm = find_vma(current->mm, addr);
+- if (task_size - len >= addr &&
+- (!vmm || addr + len <= vmm->vm_start))
++ if (task_size - len >= addr && check_heap_stack_gap(vmm, addr, len))
+ return addr;
+ }
+ addr = current->mm->mmap_base;
+@@ -128,7 +132,7 @@ unsigned long arch_get_unmapped_area(str
+ /* At this point: (!vmm || addr < vmm->vm_end). */
+ if (task_size - len < addr)
+ return -ENOMEM;
+- if (!vmm || addr + len <= vmm->vm_start)
++ if (check_heap_stack_gap(vmm, addr, len))
+ return addr;
+ addr = vmm->vm_end;
+ if (do_color_align)
+@@ -154,33 +158,6 @@ void arch_pick_mmap_layout(struct mm_str
+ mm->unmap_area = arch_unmap_area;
+ }
+
+-static inline unsigned long brk_rnd(void)
+-{
+- unsigned long rnd = get_random_int();
+-
+- rnd = rnd << PAGE_SHIFT;
+- /* 8MB for 32bit, 256MB for 64bit */
+- if (TASK_IS_32BIT_ADDR)
+- rnd = rnd & 0x7ffffful;
+- else
+- rnd = rnd & 0xffffffful;
+-
+- return rnd;
+-}
+-
+-unsigned long arch_randomize_brk(struct mm_struct *mm)
+-{
+- unsigned long base = mm->brk;
+- unsigned long ret;
+-
+- ret = PAGE_ALIGN(base + brk_rnd());
+-
+- if (ret < mm->brk)
+- return mm->brk;
+-
+- return ret;
+-}
+-
+ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
+ unsigned long, prot, unsigned long, flags, unsigned long,
+ fd, off_t, offset)
+diff -urNp linux-2.6.38.7/arch/mips/mm/dma-default.c linux-2.6.38.7/arch/mips/mm/dma-default.c
+--- linux-2.6.38.7/arch/mips/mm/dma-default.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/mm/dma-default.c 2011-04-28 19:34:14.000000000 -0400
+@@ -300,7 +300,7 @@ void dma_cache_sync(struct device *dev,
+
+ EXPORT_SYMBOL(dma_cache_sync);
+
+-static struct dma_map_ops mips_default_dma_map_ops = {
++static const struct dma_map_ops mips_default_dma_map_ops = {
+ .alloc_coherent = mips_dma_alloc_coherent,
+ .free_coherent = mips_dma_free_coherent,
+ .map_page = mips_dma_map_page,
+@@ -315,7 +315,7 @@ static struct dma_map_ops mips_default_d
+ .dma_supported = mips_dma_supported
+ };
+
+-struct dma_map_ops *mips_dma_map_ops = &mips_default_dma_map_ops;
++const struct dma_map_ops *mips_dma_map_ops = &mips_default_dma_map_ops;
+ EXPORT_SYMBOL(mips_dma_map_ops);
+
+ #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+diff -urNp linux-2.6.38.7/arch/mips/mm/fault.c linux-2.6.38.7/arch/mips/mm/fault.c
+--- linux-2.6.38.7/arch/mips/mm/fault.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/mips/mm/fault.c 2011-04-28 19:34:14.000000000 -0400
+@@ -28,6 +28,23 @@
+ #include <asm/highmem.h> /* For VMALLOC_END */
+ #include <linux/kdebug.h>
+
++#ifdef CONFIG_PAX_PAGEEXEC
++void pax_report_insns(void *pc, void *sp)
++{
++ unsigned long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 5; i++) {
++ unsigned int c;
++ if (get_user(c, (unsigned int *)pc+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%08x ", c);
++ }
++ printk("\n");
++}
++#endif
++
+ /*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+diff -urNp linux-2.6.38.7/arch/parisc/include/asm/elf.h linux-2.6.38.7/arch/parisc/include/asm/elf.h
+--- linux-2.6.38.7/arch/parisc/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/parisc/include/asm/elf.h 2011-04-28 19:34:14.000000000 -0400
+@@ -342,6 +342,13 @@ struct pt_regs; /* forward declaration..
+
+ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000)
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE 0x10000UL
++
++#define PAX_DELTA_MMAP_LEN 16
++#define PAX_DELTA_STACK_LEN 16
++#endif
++
+ /* This yields a mask that user programs can use to figure out what
+ instruction set this CPU supports. This could be done in user space,
+ but it's not easy, and we've already done it here. */
+diff -urNp linux-2.6.38.7/arch/parisc/include/asm/pgtable.h linux-2.6.38.7/arch/parisc/include/asm/pgtable.h
+--- linux-2.6.38.7/arch/parisc/include/asm/pgtable.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/parisc/include/asm/pgtable.h 2011-04-28 19:34:14.000000000 -0400
+@@ -209,6 +209,17 @@ struct vm_area_struct;
+ #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED)
+ #define PAGE_COPY PAGE_EXECREAD
+ #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED)
++
++#ifdef CONFIG_PAX_PAGEEXEC
++# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED)
++# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
++# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
++#else
++# define PAGE_SHARED_NOEXEC PAGE_SHARED
++# define PAGE_COPY_NOEXEC PAGE_COPY
++# define PAGE_READONLY_NOEXEC PAGE_READONLY
++#endif
++
+ #define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
+ #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
+ #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
+diff -urNp linux-2.6.38.7/arch/parisc/kernel/module.c linux-2.6.38.7/arch/parisc/kernel/module.c
+--- linux-2.6.38.7/arch/parisc/kernel/module.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/parisc/kernel/module.c 2011-04-28 19:34:14.000000000 -0400
+@@ -96,16 +96,38 @@
+
+ /* three functions to determine where in the module core
+ * or init pieces the location is */
++static inline int in_init_rx(struct module *me, void *loc)
++{
++ return (loc >= me->module_init_rx &&
++ loc < (me->module_init_rx + me->init_size_rx));
++}
++
++static inline int in_init_rw(struct module *me, void *loc)
++{
++ return (loc >= me->module_init_rw &&
++ loc < (me->module_init_rw + me->init_size_rw));
++}
++
+ static inline int in_init(struct module *me, void *loc)
+ {
+- return (loc >= me->module_init &&
+- loc <= (me->module_init + me->init_size));
++ return in_init_rx(me, loc) || in_init_rw(me, loc);
++}
++
++static inline int in_core_rx(struct module *me, void *loc)
++{
++ return (loc >= me->module_core_rx &&
++ loc < (me->module_core_rx + me->core_size_rx));
++}
++
++static inline int in_core_rw(struct module *me, void *loc)
++{
++ return (loc >= me->module_core_rw &&
++ loc < (me->module_core_rw + me->core_size_rw));
+ }
+
+ static inline int in_core(struct module *me, void *loc)
+ {
+- return (loc >= me->module_core &&
+- loc <= (me->module_core + me->core_size));
++ return in_core_rx(me, loc) || in_core_rw(me, loc);
+ }
+
+ static inline int in_local(struct module *me, void *loc)
+@@ -365,13 +387,13 @@ int module_frob_arch_sections(CONST Elf_
+ }
+
+ /* align things a bit */
+- me->core_size = ALIGN(me->core_size, 16);
+- me->arch.got_offset = me->core_size;
+- me->core_size += gots * sizeof(struct got_entry);
+-
+- me->core_size = ALIGN(me->core_size, 16);
+- me->arch.fdesc_offset = me->core_size;
+- me->core_size += fdescs * sizeof(Elf_Fdesc);
++ me->core_size_rw = ALIGN(me->core_size_rw, 16);
++ me->arch.got_offset = me->core_size_rw;
++ me->core_size_rw += gots * sizeof(struct got_entry);
++
++ me->core_size_rw = ALIGN(me->core_size_rw, 16);
++ me->arch.fdesc_offset = me->core_size_rw;
++ me->core_size_rw += fdescs * sizeof(Elf_Fdesc);
+
+ me->arch.got_max = gots;
+ me->arch.fdesc_max = fdescs;
+@@ -389,7 +411,7 @@ static Elf64_Word get_got(struct module
+
+ BUG_ON(value == 0);
+
+- got = me->module_core + me->arch.got_offset;
++ got = me->module_core_rw + me->arch.got_offset;
+ for (i = 0; got[i].addr; i++)
+ if (got[i].addr == value)
+ goto out;
+@@ -407,7 +429,7 @@ static Elf64_Word get_got(struct module
+ #ifdef CONFIG_64BIT
+ static Elf_Addr get_fdesc(struct module *me, unsigned long value)
+ {
+- Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
++ Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset;
+
+ if (!value) {
+ printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
+@@ -425,7 +447,7 @@ static Elf_Addr get_fdesc(struct module
+
+ /* Create new one */
+ fdesc->addr = value;
+- fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
++ fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
+ return (Elf_Addr)fdesc;
+ }
+ #endif /* CONFIG_64BIT */
+@@ -849,7 +871,7 @@ register_unwind_table(struct module *me,
+
+ table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
+ end = table + sechdrs[me->arch.unwind_section].sh_size;
+- gp = (Elf_Addr)me->module_core + me->arch.got_offset;
++ gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
+
+ DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
+ me->arch.unwind_section, table, end, gp);
+diff -urNp linux-2.6.38.7/arch/parisc/kernel/sys_parisc.c linux-2.6.38.7/arch/parisc/kernel/sys_parisc.c
+--- linux-2.6.38.7/arch/parisc/kernel/sys_parisc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/parisc/kernel/sys_parisc.c 2011-04-28 19:34:14.000000000 -0400
+@@ -43,7 +43,7 @@ static unsigned long get_unshared_area(u
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (TASK_SIZE - len < addr)
+ return -ENOMEM;
+- if (!vma || addr + len <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr, len))
+ return addr;
+ addr = vma->vm_end;
+ }
+@@ -79,7 +79,7 @@ static unsigned long get_shared_area(str
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (TASK_SIZE - len < addr)
+ return -ENOMEM;
+- if (!vma || addr + len <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr, len))
+ return addr;
+ addr = DCACHE_ALIGN(vma->vm_end - offset) + offset;
+ if (addr < vma->vm_end) /* handle wraparound */
+@@ -98,7 +98,7 @@ unsigned long arch_get_unmapped_area(str
+ if (flags & MAP_FIXED)
+ return addr;
+ if (!addr)
+- addr = TASK_UNMAPPED_BASE;
++ addr = current->mm->mmap_base;
+
+ if (filp) {
+ addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
+diff -urNp linux-2.6.38.7/arch/parisc/kernel/traps.c linux-2.6.38.7/arch/parisc/kernel/traps.c
+--- linux-2.6.38.7/arch/parisc/kernel/traps.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/parisc/kernel/traps.c 2011-04-28 19:34:14.000000000 -0400
+@@ -733,9 +733,7 @@ void notrace handle_interruption(int cod
+
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(current->mm,regs->iaoq[0]);
+- if (vma && (regs->iaoq[0] >= vma->vm_start)
+- && (vma->vm_flags & VM_EXEC)) {
+-
++ if (vma && (regs->iaoq[0] >= vma->vm_start)) {
+ fault_address = regs->iaoq[0];
+ fault_space = regs->iasq[0];
+
+diff -urNp linux-2.6.38.7/arch/parisc/mm/fault.c linux-2.6.38.7/arch/parisc/mm/fault.c
+--- linux-2.6.38.7/arch/parisc/mm/fault.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/parisc/mm/fault.c 2011-04-28 19:34:14.000000000 -0400
+@@ -15,6 +15,7 @@
+ #include <linux/sched.h>
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
++#include <linux/unistd.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/traps.h>
+@@ -52,7 +53,7 @@ DEFINE_PER_CPU(struct exception_data, ex
+ static unsigned long
+ parisc_acctyp(unsigned long code, unsigned int inst)
+ {
+- if (code == 6 || code == 16)
++ if (code == 6 || code == 7 || code == 16)
+ return VM_EXEC;
+
+ switch (inst & 0xf0000000) {
+@@ -138,6 +139,116 @@ parisc_acctyp(unsigned long code, unsign
+ }
+ #endif
+
++#ifdef CONFIG_PAX_PAGEEXEC
++/*
++ * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address)
++ *
++ * returns 1 when task should be killed
++ * 2 when rt_sigreturn trampoline was detected
++ * 3 when unpatched PLT trampoline was detected
++ */
++static int pax_handle_fetch_fault(struct pt_regs *regs)
++{
++
++#ifdef CONFIG_PAX_EMUPLT
++ int err;
++
++ do { /* PaX: unpatched PLT emulation */
++ unsigned int bl, depwi;
++
++ err = get_user(bl, (unsigned int *)instruction_pointer(regs));
++ err |= get_user(depwi, (unsigned int *)(instruction_pointer(regs)+4));
++
++ if (err)
++ break;
++
++ if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) {
++ unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12;
++
++ err = get_user(ldw, (unsigned int *)addr);
++ err |= get_user(bv, (unsigned int *)(addr+4));
++ err |= get_user(ldw2, (unsigned int *)(addr+8));
++
++ if (err)
++ break;
++
++ if (ldw == 0x0E801096U &&
++ bv == 0xEAC0C000U &&
++ ldw2 == 0x0E881095U)
++ {
++ unsigned int resolver, map;
++
++ err = get_user(resolver, (unsigned int *)(instruction_pointer(regs)+8));
++ err |= get_user(map, (unsigned int *)(instruction_pointer(regs)+12));
++ if (err)
++ break;
++
++ regs->gr[20] = instruction_pointer(regs)+8;
++ regs->gr[21] = map;
++ regs->gr[22] = resolver;
++ regs->iaoq[0] = resolver | 3UL;
++ regs->iaoq[1] = regs->iaoq[0] + 4;
++ return 3;
++ }
++ }
++ } while (0);
++#endif
++
++#ifdef CONFIG_PAX_EMUTRAMP
++
++#ifndef CONFIG_PAX_EMUSIGRT
++ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
++ return 1;
++#endif
++
++ do { /* PaX: rt_sigreturn emulation */
++ unsigned int ldi1, ldi2, bel, nop;
++
++ err = get_user(ldi1, (unsigned int *)instruction_pointer(regs));
++ err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4));
++ err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8));
++ err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12));
++
++ if (err)
++ break;
++
++ if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) &&
++ ldi2 == 0x3414015AU &&
++ bel == 0xE4008200U &&
++ nop == 0x08000240U)
++ {
++ regs->gr[25] = (ldi1 & 2) >> 1;
++ regs->gr[20] = __NR_rt_sigreturn;
++ regs->gr[31] = regs->iaoq[1] + 16;
++ regs->sr[0] = regs->iasq[1];
++ regs->iaoq[0] = 0x100UL;
++ regs->iaoq[1] = regs->iaoq[0] + 4;
++ regs->iasq[0] = regs->sr[2];
++ regs->iasq[1] = regs->sr[2];
++ return 2;
++ }
++ } while (0);
++#endif
++
++ return 1;
++}
++
++void pax_report_insns(void *pc, void *sp)
++{
++ unsigned long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 5; i++) {
++ unsigned int c;
++ if (get_user(c, (unsigned int *)pc+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%08x ", c);
++ }
++ printk("\n");
++}
++#endif
++
+ int fixup_exception(struct pt_regs *regs)
+ {
+ const struct exception_table_entry *fix;
+@@ -192,8 +303,33 @@ good_area:
+
+ acc_type = parisc_acctyp(code,regs->iir);
+
+- if ((vma->vm_flags & acc_type) != acc_type)
++ if ((vma->vm_flags & acc_type) != acc_type) {
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) &&
++ (address & ~3UL) == instruction_pointer(regs))
++ {
++ up_read(&mm->mmap_sem);
++ switch (pax_handle_fetch_fault(regs)) {
++
++#ifdef CONFIG_PAX_EMUPLT
++ case 3:
++ return;
++#endif
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ case 2:
++ return;
++#endif
++
++ }
++ pax_report_fault(regs, (void *)instruction_pointer(regs), (void *)regs->gr[30]);
++ do_group_exit(SIGKILL);
++ }
++#endif
++
+ goto bad_area;
++ }
+
+ /*
+ * If for any reason at all we couldn't handle the fault, make
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/device.h linux-2.6.38.7/arch/powerpc/include/asm/device.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/device.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/device.h 2011-04-28 19:34:14.000000000 -0400
+@@ -17,7 +17,7 @@ struct device_node;
+ */
+ struct dev_archdata {
+ /* DMA operations on that device */
+- struct dma_map_ops *dma_ops;
++ const struct dma_map_ops *dma_ops;
+
+ /*
+ * When an iommu is in use, dma_data is used as a ptr to the base of the
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/dma-mapping.h linux-2.6.38.7/arch/powerpc/include/asm/dma-mapping.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/dma-mapping.h 2011-04-28 19:34:14.000000000 -0400
+@@ -66,12 +66,13 @@ static inline unsigned long device_to_ma
+ /*
+ * Available generic sets of operations
+ */
++/* cannot be const */
+ #ifdef CONFIG_PPC64
+-extern struct dma_map_ops dma_iommu_ops;
++extern const struct dma_map_ops dma_iommu_ops;
+ #endif
+-extern struct dma_map_ops dma_direct_ops;
++extern const struct dma_map_ops dma_direct_ops;
+
+-static inline struct dma_map_ops *get_dma_ops(struct device *dev)
++static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
+ {
+ /* We don't handle the NULL dev case for ISA for now. We could
+ * do it via an out of line call but it is not needed for now. The
+@@ -84,7 +85,7 @@ static inline struct dma_map_ops *get_dm
+ return dev->archdata.dma_ops;
+ }
+
+-static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
++static inline void set_dma_ops(struct device *dev, const struct dma_map_ops *ops)
+ {
+ dev->archdata.dma_ops = ops;
+ }
+@@ -118,7 +119,7 @@ static inline void set_dma_offset(struct
+
+ static inline int dma_supported(struct device *dev, u64 mask)
+ {
+- struct dma_map_ops *dma_ops = get_dma_ops(dev);
++ const struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ if (unlikely(dma_ops == NULL))
+ return 0;
+@@ -132,7 +133,7 @@ extern int dma_set_mask(struct device *d
+ static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+ {
+- struct dma_map_ops *dma_ops = get_dma_ops(dev);
++ const struct dma_map_ops *dma_ops = get_dma_ops(dev);
+ void *cpu_addr;
+
+ BUG_ON(!dma_ops);
+@@ -147,7 +148,7 @@ static inline void *dma_alloc_coherent(s
+ static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+ {
+- struct dma_map_ops *dma_ops = get_dma_ops(dev);
++ const struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+
+@@ -158,7 +159,7 @@ static inline void dma_free_coherent(str
+
+ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+ {
+- struct dma_map_ops *dma_ops = get_dma_ops(dev);
++ const struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops->mapping_error)
+ return dma_ops->mapping_error(dev, dma_addr);
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/elf.h linux-2.6.38.7/arch/powerpc/include/asm/elf.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/elf.h 2011-04-28 19:34:14.000000000 -0400
+@@ -178,8 +178,19 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[E
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+-extern unsigned long randomize_et_dyn(unsigned long base);
+-#define ELF_ET_DYN_BASE (randomize_et_dyn(0x20000000))
++#define ELF_ET_DYN_BASE (0x20000000)
++
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE (0x10000000UL)
++
++#ifdef __powerpc64__
++#define PAX_DELTA_MMAP_LEN (is_32bit_task() ? 16 : 28)
++#define PAX_DELTA_STACK_LEN (is_32bit_task() ? 16 : 28)
++#else
++#define PAX_DELTA_MMAP_LEN 15
++#define PAX_DELTA_STACK_LEN 15
++#endif
++#endif
+
+ /*
+ * Our registers are always unsigned longs, whether we're a 32 bit
+@@ -274,9 +285,6 @@ extern int arch_setup_additional_pages(s
+ (0x7ff >> (PAGE_SHIFT - 12)) : \
+ (0x3ffff >> (PAGE_SHIFT - 12)))
+
+-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+-#define arch_randomize_brk arch_randomize_brk
+-
+ #endif /* __KERNEL__ */
+
+ /*
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/iommu.h linux-2.6.38.7/arch/powerpc/include/asm/iommu.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/iommu.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/iommu.h 2011-04-28 19:34:14.000000000 -0400
+@@ -116,6 +116,9 @@ extern void iommu_init_early_iSeries(voi
+ extern void iommu_init_early_dart(void);
+ extern void iommu_init_early_pasemi(void);
+
++/* dma-iommu.c */
++extern int dma_iommu_dma_supported(struct device *dev, u64 mask);
++
+ #ifdef CONFIG_PCI
+ extern void pci_iommu_init(void);
+ extern void pci_direct_iommu_init(void);
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/kmap_types.h linux-2.6.38.7/arch/powerpc/include/asm/kmap_types.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/kmap_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/kmap_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -27,6 +27,7 @@ enum km_type {
+ KM_PPC_SYNC_PAGE,
+ KM_PPC_SYNC_ICACHE,
+ KM_KDB,
++ KM_CLEARPAGE,
+ KM_TYPE_NR
+ };
+
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/page_64.h linux-2.6.38.7/arch/powerpc/include/asm/page_64.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/page_64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/page_64.h 2011-04-28 19:34:14.000000000 -0400
+@@ -172,15 +172,18 @@ do { \
+ * stack by default, so in the absense of a PT_GNU_STACK program header
+ * we turn execute permission off.
+ */
+-#define VM_STACK_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \
+- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
++#define VM_STACK_DEFAULT_FLAGS32 \
++ (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
++ VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+ #define VM_STACK_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
++#ifndef CONFIG_PAX_PAGEEXEC
+ #define VM_STACK_DEFAULT_FLAGS \
+ (is_32bit_task() ? \
+ VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
++#endif
+
+ #include <asm-generic/getorder.h>
+
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/page.h linux-2.6.38.7/arch/powerpc/include/asm/page.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/page.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/page.h 2011-04-28 19:34:14.000000000 -0400
+@@ -129,8 +129,9 @@ extern phys_addr_t kernstart_addr;
+ * and needs to be executable. This means the whole heap ends
+ * up being executable.
+ */
+-#define VM_DATA_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \
+- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
++#define VM_DATA_DEFAULT_FLAGS32 \
++ (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
++ VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+ #define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+@@ -158,6 +159,9 @@ extern phys_addr_t kernstart_addr;
+ #define is_kernel_addr(x) ((x) >= PAGE_OFFSET)
+ #endif
+
++#define ktla_ktva(addr) (addr)
++#define ktva_ktla(addr) (addr)
++
+ #ifndef __ASSEMBLY__
+
+ #undef STRICT_MM_TYPECHECKS
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/pci.h linux-2.6.38.7/arch/powerpc/include/asm/pci.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/pci.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/pci.h 2011-04-28 19:34:14.000000000 -0400
+@@ -65,8 +65,8 @@ static inline int pci_get_legacy_ide_irq
+ }
+
+ #ifdef CONFIG_PCI
+-extern void set_pci_dma_ops(struct dma_map_ops *dma_ops);
+-extern struct dma_map_ops *get_pci_dma_ops(void);
++extern void set_pci_dma_ops(const struct dma_map_ops *dma_ops);
++extern const struct dma_map_ops *get_pci_dma_ops(void);
+ #else /* CONFIG_PCI */
+ #define set_pci_dma_ops(d)
+ #define get_pci_dma_ops() NULL
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/pgtable.h linux-2.6.38.7/arch/powerpc/include/asm/pgtable.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/pgtable.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/pgtable.h 2011-04-28 19:34:14.000000000 -0400
+@@ -2,6 +2,7 @@
+ #define _ASM_POWERPC_PGTABLE_H
+ #ifdef __KERNEL__
+
++#include <linux/const.h>
+ #ifndef __ASSEMBLY__
+ #include <asm/processor.h> /* For TASK_SIZE */
+ #include <asm/mmu.h>
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/pte-hash32.h linux-2.6.38.7/arch/powerpc/include/asm/pte-hash32.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/pte-hash32.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/pte-hash32.h 2011-04-28 19:34:14.000000000 -0400
+@@ -21,6 +21,7 @@
+ #define _PAGE_FILE 0x004 /* when !present: nonlinear file mapping */
+ #define _PAGE_USER 0x004 /* usermode access allowed */
+ #define _PAGE_GUARDED 0x008 /* G: prohibit speculative access */
++#define _PAGE_EXEC _PAGE_GUARDED
+ #define _PAGE_COHERENT 0x010 /* M: enforce memory coherence (SMP systems) */
+ #define _PAGE_NO_CACHE 0x020 /* I: cache inhibit */
+ #define _PAGE_WRITETHRU 0x040 /* W: cache write-through */
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/reg.h linux-2.6.38.7/arch/powerpc/include/asm/reg.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/reg.h 2011-04-18 17:27:13.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/reg.h 2011-04-28 19:34:14.000000000 -0400
+@@ -191,6 +191,7 @@
+ #define SPRN_DBCR 0x136 /* e300 Data Breakpoint Control Reg */
+ #define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
+ #define DSISR_NOHPTE 0x40000000 /* no translation found */
++#define DSISR_GUARDED 0x10000000 /* fetch from guarded storage */
+ #define DSISR_PROTFAULT 0x08000000 /* protection fault */
+ #define DSISR_ISSTORE 0x02000000 /* access was a store */
+ #define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/swiotlb.h linux-2.6.38.7/arch/powerpc/include/asm/swiotlb.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/swiotlb.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/swiotlb.h 2011-04-28 19:34:14.000000000 -0400
+@@ -13,7 +13,7 @@
+
+ #include <linux/swiotlb.h>
+
+-extern struct dma_map_ops swiotlb_dma_ops;
++extern const struct dma_map_ops swiotlb_dma_ops;
+
+ static inline void dma_mark_clean(void *addr, size_t size) {}
+
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/system.h linux-2.6.38.7/arch/powerpc/include/asm/system.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/system.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/system.h 2011-04-28 19:34:14.000000000 -0400
+@@ -533,7 +533,7 @@ __cmpxchg_local(volatile void *ptr, unsi
+ #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+ #endif
+
+-extern unsigned long arch_align_stack(unsigned long sp);
++#define arch_align_stack(x) ((x) & ~0xfUL)
+
+ /* Used in very early kernel initialization. */
+ extern unsigned long reloc_offset(void);
+diff -urNp linux-2.6.38.7/arch/powerpc/include/asm/uaccess.h linux-2.6.38.7/arch/powerpc/include/asm/uaccess.h
+--- linux-2.6.38.7/arch/powerpc/include/asm/uaccess.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/include/asm/uaccess.h 2011-04-28 19:34:14.000000000 -0400
+@@ -13,6 +13,8 @@
+ #define VERIFY_READ 0
+ #define VERIFY_WRITE 1
+
++extern void check_object_size(const void *ptr, unsigned long n, bool to);
++
+ /*
+ * The fs value determines whether argument validity checking should be
+ * performed or not. If get_fs() == USER_DS, checking is performed, with
+@@ -327,52 +329,6 @@ do { \
+ extern unsigned long __copy_tofrom_user(void __user *to,
+ const void __user *from, unsigned long size);
+
+-#ifndef __powerpc64__
+-
+-static inline unsigned long copy_from_user(void *to,
+- const void __user *from, unsigned long n)
+-{
+- unsigned long over;
+-
+- if (access_ok(VERIFY_READ, from, n))
+- return __copy_tofrom_user((__force void __user *)to, from, n);
+- if ((unsigned long)from < TASK_SIZE) {
+- over = (unsigned long)from + n - TASK_SIZE;
+- return __copy_tofrom_user((__force void __user *)to, from,
+- n - over) + over;
+- }
+- return n;
+-}
+-
+-static inline unsigned long copy_to_user(void __user *to,
+- const void *from, unsigned long n)
+-{
+- unsigned long over;
+-
+- if (access_ok(VERIFY_WRITE, to, n))
+- return __copy_tofrom_user(to, (__force void __user *)from, n);
+- if ((unsigned long)to < TASK_SIZE) {
+- over = (unsigned long)to + n - TASK_SIZE;
+- return __copy_tofrom_user(to, (__force void __user *)from,
+- n - over) + over;
+- }
+- return n;
+-}
+-
+-#else /* __powerpc64__ */
+-
+-#define __copy_in_user(to, from, size) \
+- __copy_tofrom_user((to), (from), (size))
+-
+-extern unsigned long copy_from_user(void *to, const void __user *from,
+- unsigned long n);
+-extern unsigned long copy_to_user(void __user *to, const void *from,
+- unsigned long n);
+-extern unsigned long copy_in_user(void __user *to, const void __user *from,
+- unsigned long n);
+-
+-#endif /* __powerpc64__ */
+-
+ static inline unsigned long __copy_from_user_inatomic(void *to,
+ const void __user *from, unsigned long n)
+ {
+@@ -396,6 +352,10 @@ static inline unsigned long __copy_from_
+ if (ret == 0)
+ return 0;
+ }
++
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
++
+ return __copy_tofrom_user((__force void __user *)to, from, n);
+ }
+
+@@ -422,6 +382,10 @@ static inline unsigned long __copy_to_us
+ if (ret == 0)
+ return 0;
+ }
++
++ if (!__builtin_constant_p(n))
++ check_object_size(from, n, true);
++
+ return __copy_tofrom_user(to, (__force const void __user *)from, n);
+ }
+
+@@ -439,6 +403,92 @@ static inline unsigned long __copy_to_us
+ return __copy_to_user_inatomic(to, from, size);
+ }
+
++#ifndef __powerpc64__
++
++static inline unsigned long __must_check copy_from_user(void *to,
++ const void __user *from, unsigned long n)
++{
++ unsigned long over;
++
++ if ((long)n < 0)
++ return n;
++
++ if (access_ok(VERIFY_READ, from, n)) {
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
++ return __copy_tofrom_user((__force void __user *)to, from, n);
++ }
++ if ((unsigned long)from < TASK_SIZE) {
++ over = (unsigned long)from + n - TASK_SIZE;
++ if (!__builtin_constant_p(n - over))
++ check_object_size(to, n - over, false);
++ return __copy_tofrom_user((__force void __user *)to, from,
++ n - over) + over;
++ }
++ return n;
++}
++
++static inline unsigned long __must_check copy_to_user(void __user *to,
++ const void *from, unsigned long n)
++{
++ unsigned long over;
++
++ if ((long)n < 0)
++ return n;
++
++ if (access_ok(VERIFY_WRITE, to, n)) {
++ if (!__builtin_constant_p(n))
++ check_object_size(from, n, true);
++ return __copy_tofrom_user(to, (__force void __user *)from, n);
++ }
++ if ((unsigned long)to < TASK_SIZE) {
++ over = (unsigned long)to + n - TASK_SIZE;
++ if (!__builtin_constant_p(n))
++ check_object_size(from, n - over, true);
++ return __copy_tofrom_user(to, (__force void __user *)from,
++ n - over) + over;
++ }
++ return n;
++}
++
++#else /* __powerpc64__ */
++
++#define __copy_in_user(to, from, size) \
++ __copy_tofrom_user((to), (from), (size))
++
++static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
++{
++ if ((long)n < 0 || n > INT_MAX)
++ return n;
++
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
++
++ if (likely(access_ok(VERIFY_READ, from, n)))
++ n = __copy_from_user(to, from, n);
++ else
++ memset(to, 0, n);
++ return n;
++}
++
++static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
++{
++ if ((long)n < 0 || n > INT_MAX)
++ return n;
++
++ if (likely(access_ok(VERIFY_WRITE, to, n))) {
++ if (!__builtin_constant_p(n))
++ check_object_size(from, n, true);
++ n = __copy_to_user(to, from, n);
++ }
++ return n;
++}
++
++extern unsigned long copy_in_user(void __user *to, const void __user *from,
++ unsigned long n);
++
++#endif /* __powerpc64__ */
++
+ extern unsigned long __clear_user(void __user *addr, unsigned long size);
+
+ static inline unsigned long clear_user(void __user *addr, unsigned long size)
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/dma.c linux-2.6.38.7/arch/powerpc/kernel/dma.c
+--- linux-2.6.38.7/arch/powerpc/kernel/dma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/dma.c 2011-04-28 19:34:14.000000000 -0400
+@@ -136,7 +136,7 @@ static inline void dma_direct_sync_singl
+ }
+ #endif
+
+-struct dma_map_ops dma_direct_ops = {
++const struct dma_map_ops dma_direct_ops = {
+ .alloc_coherent = dma_direct_alloc_coherent,
+ .free_coherent = dma_direct_free_coherent,
+ .map_sg = dma_direct_map_sg,
+@@ -157,7 +157,7 @@ EXPORT_SYMBOL(dma_direct_ops);
+
+ int dma_set_mask(struct device *dev, u64 dma_mask)
+ {
+- struct dma_map_ops *dma_ops = get_dma_ops(dev);
++ const struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ if (ppc_md.dma_set_mask)
+ return ppc_md.dma_set_mask(dev, dma_mask);
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/dma-iommu.c linux-2.6.38.7/arch/powerpc/kernel/dma-iommu.c
+--- linux-2.6.38.7/arch/powerpc/kernel/dma-iommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/dma-iommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -70,7 +70,7 @@ static void dma_iommu_unmap_sg(struct de
+ }
+
+ /* We support DMA to/from any memory page via the iommu */
+-static int dma_iommu_dma_supported(struct device *dev, u64 mask)
++int dma_iommu_dma_supported(struct device *dev, u64 mask)
+ {
+ struct iommu_table *tbl = get_iommu_table_base(dev);
+
+@@ -90,7 +90,7 @@ static int dma_iommu_dma_supported(struc
+ return 1;
+ }
+
+-struct dma_map_ops dma_iommu_ops = {
++struct dma_map_ops dma_iommu_ops = { /* cannot be const, see arch/powerpc/platforms/cell/iommu.c */
+ .alloc_coherent = dma_iommu_alloc_coherent,
+ .free_coherent = dma_iommu_free_coherent,
+ .map_sg = dma_iommu_map_sg,
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/dma-swiotlb.c linux-2.6.38.7/arch/powerpc/kernel/dma-swiotlb.c
+--- linux-2.6.38.7/arch/powerpc/kernel/dma-swiotlb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/dma-swiotlb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -31,7 +31,7 @@ unsigned int ppc_swiotlb_enable;
+ * map_page, and unmap_page on highmem, use normal dma_ops
+ * for everything else.
+ */
+-struct dma_map_ops swiotlb_dma_ops = {
++const struct dma_map_ops swiotlb_dma_ops = {
+ .alloc_coherent = dma_direct_alloc_coherent,
+ .free_coherent = dma_direct_free_coherent,
+ .map_sg = swiotlb_map_sg_attrs,
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/exceptions-64e.S linux-2.6.38.7/arch/powerpc/kernel/exceptions-64e.S
+--- linux-2.6.38.7/arch/powerpc/kernel/exceptions-64e.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/exceptions-64e.S 2011-04-28 19:34:14.000000000 -0400
+@@ -495,6 +495,7 @@ storage_fault_common:
+ std r14,_DAR(r1)
+ std r15,_DSISR(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .save_nvgprs
+ mr r4,r14
+ mr r5,r15
+ ld r14,PACA_EXGEN+EX_R14(r13)
+@@ -504,8 +505,7 @@ storage_fault_common:
+ cmpdi r3,0
+ bne- 1f
+ b .ret_from_except_lite
+-1: bl .save_nvgprs
+- mr r5,r3
++1: mr r5,r3
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ ld r4,_DAR(r1)
+ bl .bad_page_fault
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/exceptions-64s.S linux-2.6.38.7/arch/powerpc/kernel/exceptions-64s.S
+--- linux-2.6.38.7/arch/powerpc/kernel/exceptions-64s.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/exceptions-64s.S 2011-04-28 19:34:14.000000000 -0400
+@@ -848,10 +848,10 @@ handle_page_fault:
+ 11: ld r4,_DAR(r1)
+ ld r5,_DSISR(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
++ bl .save_nvgprs
+ bl .do_page_fault
+ cmpdi r3,0
+ beq+ 13f
+- bl .save_nvgprs
+ mr r5,r3
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ lwz r4,_DAR(r1)
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/ibmebus.c linux-2.6.38.7/arch/powerpc/kernel/ibmebus.c
+--- linux-2.6.38.7/arch/powerpc/kernel/ibmebus.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/ibmebus.c 2011-04-28 19:34:14.000000000 -0400
+@@ -128,7 +128,7 @@ static int ibmebus_dma_supported(struct
+ return 1;
+ }
+
+-static struct dma_map_ops ibmebus_dma_ops = {
++static const struct dma_map_ops ibmebus_dma_ops = {
+ .alloc_coherent = ibmebus_alloc_coherent,
+ .free_coherent = ibmebus_free_coherent,
+ .map_sg = ibmebus_map_sg,
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/kgdb.c linux-2.6.38.7/arch/powerpc/kernel/kgdb.c
+--- linux-2.6.38.7/arch/powerpc/kernel/kgdb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/kgdb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -422,7 +422,7 @@ int kgdb_arch_handle_exception(int vecto
+ /*
+ * Global data
+ */
+-struct kgdb_arch arch_kgdb_ops = {
++const struct kgdb_arch arch_kgdb_ops = {
+ .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
+ };
+
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/module_32.c linux-2.6.38.7/arch/powerpc/kernel/module_32.c
+--- linux-2.6.38.7/arch/powerpc/kernel/module_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/module_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -162,7 +162,7 @@ int module_frob_arch_sections(Elf32_Ehdr
+ me->arch.core_plt_section = i;
+ }
+ if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
+- printk("Module doesn't contain .plt or .init.plt sections.\n");
++ printk("Module %s doesn't contain .plt or .init.plt sections.\n", me->name);
+ return -ENOEXEC;
+ }
+
+@@ -203,11 +203,16 @@ static uint32_t do_plt_call(void *locati
+
+ DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
+ /* Init, or core PLT? */
+- if (location >= mod->module_core
+- && location < mod->module_core + mod->core_size)
++ if ((location >= mod->module_core_rx && location < mod->module_core_rx + mod->core_size_rx) ||
++ (location >= mod->module_core_rw && location < mod->module_core_rw + mod->core_size_rw))
+ entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
+- else
++ else if ((location >= mod->module_init_rx && location < mod->module_init_rx + mod->init_size_rx) ||
++ (location >= mod->module_init_rw && location < mod->module_init_rw + mod->init_size_rw))
+ entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
++ else {
++ printk(KERN_ERR "%s: invalid R_PPC_REL24 entry found\n", mod->name);
++ return ~0UL;
++ }
+
+ /* Find this entry, or if that fails, the next avail. entry */
+ while (entry->jump[0]) {
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/module.c linux-2.6.38.7/arch/powerpc/kernel/module.c
+--- linux-2.6.38.7/arch/powerpc/kernel/module.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/module.c 2011-04-28 19:34:14.000000000 -0400
+@@ -31,11 +31,24 @@
+
+ LIST_HEAD(module_bug_list);
+
++#ifdef CONFIG_PAX_KERNEXEC
+ void *module_alloc(unsigned long size)
+ {
+ if (size == 0)
+ return NULL;
+
++ return vmalloc(size);
++}
++
++void *module_alloc_exec(unsigned long size)
++#else
++void *module_alloc(unsigned long size)
++#endif
++
++{
++ if (size == 0)
++ return NULL;
++
+ return vmalloc_exec(size);
+ }
+
+@@ -45,6 +58,13 @@ void module_free(struct module *mod, voi
+ vfree(module_region);
+ }
+
++#ifdef CONFIG_PAX_KERNEXEC
++void module_free_exec(struct module *mod, void *module_region)
++{
++ module_free(mod, module_region);
++}
++#endif
++
+ static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ const char *name)
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/pci-common.c linux-2.6.38.7/arch/powerpc/kernel/pci-common.c
+--- linux-2.6.38.7/arch/powerpc/kernel/pci-common.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/pci-common.c 2011-04-28 19:34:14.000000000 -0400
+@@ -52,14 +52,14 @@ resource_size_t isa_mem_base;
+ unsigned int ppc_pci_flags = 0;
+
+
+-static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
++static const struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
+
+-void set_pci_dma_ops(struct dma_map_ops *dma_ops)
++void set_pci_dma_ops(const struct dma_map_ops *dma_ops)
+ {
+ pci_dma_ops = dma_ops;
+ }
+
+-struct dma_map_ops *get_pci_dma_ops(void)
++const struct dma_map_ops *get_pci_dma_ops(void)
+ {
+ return pci_dma_ops;
+ }
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/process.c linux-2.6.38.7/arch/powerpc/kernel/process.c
+--- linux-2.6.38.7/arch/powerpc/kernel/process.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/process.c 2011-04-28 19:34:14.000000000 -0400
+@@ -655,8 +655,8 @@ void show_regs(struct pt_regs * regs)
+ * Lookup NIP late so we have the best change of getting the
+ * above info out without failing
+ */
+- printk("NIP ["REG"] %pS\n", regs->nip, (void *)regs->nip);
+- printk("LR ["REG"] %pS\n", regs->link, (void *)regs->link);
++ printk("NIP ["REG"] %pA\n", regs->nip, (void *)regs->nip);
++ printk("LR ["REG"] %pA\n", regs->link, (void *)regs->link);
+ #endif
+ show_stack(current, (unsigned long *) regs->gpr[1]);
+ if (!user_mode(regs))
+@@ -1146,10 +1146,10 @@ void show_stack(struct task_struct *tsk,
+ newsp = stack[0];
+ ip = stack[STACK_FRAME_LR_SAVE];
+ if (!firstframe || ip != lr) {
+- printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
++ printk("["REG"] ["REG"] %pA", sp, ip, (void *)ip);
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ if ((ip == rth || ip == mrth) && curr_frame >= 0) {
+- printk(" (%pS)",
++ printk(" (%pA)",
+ (void *)current->ret_stack[curr_frame].ret);
+ curr_frame--;
+ }
+@@ -1169,7 +1169,7 @@ void show_stack(struct task_struct *tsk,
+ struct pt_regs *regs = (struct pt_regs *)
+ (sp + STACK_FRAME_OVERHEAD);
+ lr = regs->link;
+- printk("--- Exception: %lx at %pS\n LR = %pS\n",
++ printk("--- Exception: %lx at %pA\n LR = %pA\n",
+ regs->trap, (void *)regs->nip, (void *)lr);
+ firstframe = 1;
+ }
+@@ -1244,58 +1244,3 @@ void thread_info_cache_init(void)
+ }
+
+ #endif /* THREAD_SHIFT < PAGE_SHIFT */
+-
+-unsigned long arch_align_stack(unsigned long sp)
+-{
+- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+- sp -= get_random_int() & ~PAGE_MASK;
+- return sp & ~0xf;
+-}
+-
+-static inline unsigned long brk_rnd(void)
+-{
+- unsigned long rnd = 0;
+-
+- /* 8MB for 32bit, 1GB for 64bit */
+- if (is_32bit_task())
+- rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
+- else
+- rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
+-
+- return rnd << PAGE_SHIFT;
+-}
+-
+-unsigned long arch_randomize_brk(struct mm_struct *mm)
+-{
+- unsigned long base = mm->brk;
+- unsigned long ret;
+-
+-#ifdef CONFIG_PPC_STD_MMU_64
+- /*
+- * If we are using 1TB segments and we are allowed to randomise
+- * the heap, we can put it above 1TB so it is backed by a 1TB
+- * segment. Otherwise the heap will be in the bottom 1TB
+- * which always uses 256MB segments and this may result in a
+- * performance penalty.
+- */
+- if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
+- base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T);
+-#endif
+-
+- ret = PAGE_ALIGN(base + brk_rnd());
+-
+- if (ret < mm->brk)
+- return mm->brk;
+-
+- return ret;
+-}
+-
+-unsigned long randomize_et_dyn(unsigned long base)
+-{
+- unsigned long ret = PAGE_ALIGN(base + brk_rnd());
+-
+- if (ret < base)
+- return base;
+-
+- return ret;
+-}
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/signal_32.c linux-2.6.38.7/arch/powerpc/kernel/signal_32.c
+--- linux-2.6.38.7/arch/powerpc/kernel/signal_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/signal_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -858,7 +858,7 @@ int handle_rt_signal32(unsigned long sig
+ /* Save user registers on the stack */
+ frame = &rt_sf->uc.uc_mcontext;
+ addr = frame;
+- if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
++ if (vdso32_rt_sigtramp && current->mm->context.vdso_base != ~0UL) {
+ if (save_user_regs(regs, frame, 0, 1))
+ goto badframe;
+ regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/signal_64.c linux-2.6.38.7/arch/powerpc/kernel/signal_64.c
+--- linux-2.6.38.7/arch/powerpc/kernel/signal_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/signal_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -429,7 +429,7 @@ int handle_rt_signal64(int signr, struct
+ current->thread.fpscr.val = 0;
+
+ /* Set up to return from userspace. */
+- if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
++ if (vdso64_rt_sigtramp && current->mm->context.vdso_base != ~0UL) {
+ regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
+ } else {
+ err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/vdso.c linux-2.6.38.7/arch/powerpc/kernel/vdso.c
+--- linux-2.6.38.7/arch/powerpc/kernel/vdso.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/vdso.c 2011-04-28 19:34:14.000000000 -0400
+@@ -36,6 +36,7 @@
+ #include <asm/firmware.h>
+ #include <asm/vdso.h>
+ #include <asm/vdso_datapage.h>
++#include <asm/mman.h>
+
+ #include "setup.h"
+
+@@ -220,7 +221,7 @@ int arch_setup_additional_pages(struct l
+ vdso_base = VDSO32_MBASE;
+ #endif
+
+- current->mm->context.vdso_base = 0;
++ current->mm->context.vdso_base = ~0UL;
+
+ /* vDSO has a problem and was disabled, just don't "enable" it for the
+ * process
+@@ -240,7 +241,7 @@ int arch_setup_additional_pages(struct l
+ vdso_base = get_unmapped_area(NULL, vdso_base,
+ (vdso_pages << PAGE_SHIFT) +
+ ((VDSO_ALIGNMENT - 1) & PAGE_MASK),
+- 0, 0);
++ 0, MAP_PRIVATE | MAP_EXECUTABLE);
+ if (IS_ERR_VALUE(vdso_base)) {
+ rc = vdso_base;
+ goto fail_mmapsem;
+diff -urNp linux-2.6.38.7/arch/powerpc/kernel/vio.c linux-2.6.38.7/arch/powerpc/kernel/vio.c
+--- linux-2.6.38.7/arch/powerpc/kernel/vio.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/kernel/vio.c 2011-04-28 19:34:14.000000000 -0400
+@@ -605,11 +605,12 @@ static int vio_dma_iommu_dma_supported(s
+ return dma_iommu_ops.dma_supported(dev, mask);
+ }
+
+-struct dma_map_ops vio_dma_mapping_ops = {
++const struct dma_map_ops vio_dma_mapping_ops = {
+ .alloc_coherent = vio_dma_iommu_alloc_coherent,
+ .free_coherent = vio_dma_iommu_free_coherent,
+ .map_sg = vio_dma_iommu_map_sg,
+ .unmap_sg = vio_dma_iommu_unmap_sg,
++ .dma_supported = dma_iommu_dma_supported,
+ .map_page = vio_dma_iommu_map_page,
+ .unmap_page = vio_dma_iommu_unmap_page,
+ .dma_supported = vio_dma_iommu_dma_supported,
+diff -urNp linux-2.6.38.7/arch/powerpc/lib/usercopy_64.c linux-2.6.38.7/arch/powerpc/lib/usercopy_64.c
+--- linux-2.6.38.7/arch/powerpc/lib/usercopy_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/lib/usercopy_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -9,22 +9,6 @@
+ #include <linux/module.h>
+ #include <asm/uaccess.h>
+
+-unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
+-{
+- if (likely(access_ok(VERIFY_READ, from, n)))
+- n = __copy_from_user(to, from, n);
+- else
+- memset(to, 0, n);
+- return n;
+-}
+-
+-unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
+-{
+- if (likely(access_ok(VERIFY_WRITE, to, n)))
+- n = __copy_to_user(to, from, n);
+- return n;
+-}
+-
+ unsigned long copy_in_user(void __user *to, const void __user *from,
+ unsigned long n)
+ {
+@@ -35,7 +19,5 @@ unsigned long copy_in_user(void __user *
+ return n;
+ }
+
+-EXPORT_SYMBOL(copy_from_user);
+-EXPORT_SYMBOL(copy_to_user);
+ EXPORT_SYMBOL(copy_in_user);
+
+diff -urNp linux-2.6.38.7/arch/powerpc/mm/fault.c linux-2.6.38.7/arch/powerpc/mm/fault.c
+--- linux-2.6.38.7/arch/powerpc/mm/fault.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/mm/fault.c 2011-04-28 19:34:14.000000000 -0400
+@@ -31,6 +31,10 @@
+ #include <linux/kdebug.h>
+ #include <linux/perf_event.h>
+ #include <linux/magic.h>
++#include <linux/slab.h>
++#include <linux/pagemap.h>
++#include <linux/compiler.h>
++#include <linux/unistd.h>
+
+ #include <asm/firmware.h>
+ #include <asm/page.h>
+@@ -42,6 +46,7 @@
+ #include <asm/tlbflush.h>
+ #include <asm/siginfo.h>
+ #include <mm/mmu_decl.h>
++#include <asm/ptrace.h>
+
+ #ifdef CONFIG_KPROBES
+ static inline int notify_page_fault(struct pt_regs *regs)
+@@ -65,6 +70,33 @@ static inline int notify_page_fault(stru
+ }
+ #endif
+
++#ifdef CONFIG_PAX_PAGEEXEC
++/*
++ * PaX: decide what to do with offenders (regs->nip = fault address)
++ *
++ * returns 1 when task should be killed
++ */
++static int pax_handle_fetch_fault(struct pt_regs *regs)
++{
++ return 1;
++}
++
++void pax_report_insns(void *pc, void *sp)
++{
++ unsigned long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 5; i++) {
++ unsigned int c;
++ if (get_user(c, (unsigned int __user *)pc+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%08x ", c);
++ }
++ printk("\n");
++}
++#endif
++
+ /*
+ * Check whether the instruction at regs->nip is a store using
+ * an update addressing form which will update r1.
+@@ -135,7 +167,7 @@ int __kprobes do_page_fault(struct pt_re
+ * indicate errors in DSISR but can validly be set in SRR1.
+ */
+ if (trap == 0x400)
+- error_code &= 0x48200000;
++ error_code &= 0x58200000;
+ else
+ is_write = error_code & DSISR_ISSTORE;
+ #else
+@@ -258,7 +290,7 @@ good_area:
+ * "undefined". Of those that can be set, this is the only
+ * one which seems bad.
+ */
+- if (error_code & 0x10000000)
++ if (error_code & DSISR_GUARDED)
+ /* Guarded storage error. */
+ goto bad_area;
+ #endif /* CONFIG_8xx */
+@@ -273,7 +305,7 @@ good_area:
+ * processors use the same I/D cache coherency mechanism
+ * as embedded.
+ */
+- if (error_code & DSISR_PROTFAULT)
++ if (error_code & (DSISR_PROTFAULT | DSISR_GUARDED))
+ goto bad_area;
+ #endif /* CONFIG_PPC_STD_MMU */
+
+@@ -342,6 +374,23 @@ bad_area:
+ bad_area_nosemaphore:
+ /* User mode accesses cause a SIGSEGV */
+ if (user_mode(regs)) {
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (mm->pax_flags & MF_PAX_PAGEEXEC) {
++#ifdef CONFIG_PPC_STD_MMU
++ if (is_exec && (error_code & (DSISR_PROTFAULT | DSISR_GUARDED))) {
++#else
++ if (is_exec && regs->nip == address) {
++#endif
++ switch (pax_handle_fetch_fault(regs)) {
++ }
++
++ pax_report_fault(regs, (void *)regs->nip, (void *)regs->gpr[PT_R1]);
++ do_group_exit(SIGKILL);
++ }
++ }
++#endif
++
+ _exception(SIGSEGV, regs, code, address);
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/arch/powerpc/mm/mmap_64.c linux-2.6.38.7/arch/powerpc/mm/mmap_64.c
+--- linux-2.6.38.7/arch/powerpc/mm/mmap_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/mm/mmap_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -99,10 +99,22 @@ void arch_pick_mmap_layout(struct mm_str
+ */
+ if (mmap_is_legacy()) {
+ mm->mmap_base = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+ mm->mmap_base = mmap_base();
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
+diff -urNp linux-2.6.38.7/arch/powerpc/mm/slice.c linux-2.6.38.7/arch/powerpc/mm/slice.c
+--- linux-2.6.38.7/arch/powerpc/mm/slice.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/mm/slice.c 2011-04-28 19:34:14.000000000 -0400
+@@ -98,7 +98,7 @@ static int slice_area_is_free(struct mm_
+ if ((mm->task_size - len) < addr)
+ return 0;
+ vma = find_vma(mm, addr);
+- return (!vma || (addr + len) <= vma->vm_start);
++ return check_heap_stack_gap(vma, addr, len);
+ }
+
+ static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice)
+@@ -256,7 +256,7 @@ full_search:
+ addr = _ALIGN_UP(addr + 1, 1ul << SLICE_HIGH_SHIFT);
+ continue;
+ }
+- if (!vma || addr + len <= vma->vm_start) {
++ if (check_heap_stack_gap(vma, addr, len)) {
+ /*
+ * Remember the place where we stopped the search:
+ */
+@@ -313,10 +313,14 @@ static unsigned long slice_find_area_top
+ }
+ }
+
+- addr = mm->mmap_base;
+- while (addr > len) {
++ if (mm->mmap_base < len)
++ addr = -ENOMEM;
++ else
++ addr = mm->mmap_base - len;
++
++ while (!IS_ERR_VALUE(addr)) {
+ /* Go down by chunk size */
+- addr = _ALIGN_DOWN(addr - len, 1ul << pshift);
++ addr = _ALIGN_DOWN(addr, 1ul << pshift);
+
+ /* Check for hit with different page size */
+ mask = slice_range_to_mask(addr, len);
+@@ -336,7 +340,7 @@ static unsigned long slice_find_area_top
+ * return with success:
+ */
+ vma = find_vma(mm, addr);
+- if (!vma || (addr + len) <= vma->vm_start) {
++ if (check_heap_stack_gap(vma, addr, len)) {
+ /* remember the address as a hint for next time */
+ if (use_cache)
+ mm->free_area_cache = addr;
+@@ -348,7 +352,7 @@ static unsigned long slice_find_area_top
+ mm->cached_hole_size = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+- addr = vma->vm_start;
++ addr = skip_heap_stack_gap(vma, len);
+ }
+
+ /*
+@@ -426,6 +430,11 @@ unsigned long slice_get_unmapped_area(un
+ if (fixed && addr > (mm->task_size - len))
+ return -EINVAL;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!fixed && (mm->pax_flags & MF_PAX_RANDMMAP))
++ addr = 0;
++#endif
++
+ /* If hint, make sure it matches our alignment restrictions */
+ if (!fixed && addr) {
+ addr = _ALIGN_UP(addr, 1ul << pshift);
+diff -urNp linux-2.6.38.7/arch/powerpc/platforms/cell/iommu.c linux-2.6.38.7/arch/powerpc/platforms/cell/iommu.c
+--- linux-2.6.38.7/arch/powerpc/platforms/cell/iommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/platforms/cell/iommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -642,7 +642,7 @@ static int dma_fixed_dma_supported(struc
+
+ static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
+
+-struct dma_map_ops dma_iommu_fixed_ops = {
++const struct dma_map_ops dma_iommu_fixed_ops = {
+ .alloc_coherent = dma_fixed_alloc_coherent,
+ .free_coherent = dma_fixed_free_coherent,
+ .map_sg = dma_fixed_map_sg,
+diff -urNp linux-2.6.38.7/arch/powerpc/platforms/ps3/system-bus.c linux-2.6.38.7/arch/powerpc/platforms/ps3/system-bus.c
+--- linux-2.6.38.7/arch/powerpc/platforms/ps3/system-bus.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/platforms/ps3/system-bus.c 2011-04-28 19:34:14.000000000 -0400
+@@ -695,7 +695,7 @@ static int ps3_dma_supported(struct devi
+ return mask >= DMA_BIT_MASK(32);
+ }
+
+-static struct dma_map_ops ps3_sb_dma_ops = {
++static const struct dma_map_ops ps3_sb_dma_ops = {
+ .alloc_coherent = ps3_alloc_coherent,
+ .free_coherent = ps3_free_coherent,
+ .map_sg = ps3_sb_map_sg,
+@@ -705,7 +705,7 @@ static struct dma_map_ops ps3_sb_dma_ops
+ .unmap_page = ps3_unmap_page,
+ };
+
+-static struct dma_map_ops ps3_ioc0_dma_ops = {
++static const struct dma_map_ops ps3_ioc0_dma_ops = {
+ .alloc_coherent = ps3_alloc_coherent,
+ .free_coherent = ps3_free_coherent,
+ .map_sg = ps3_ioc0_map_sg,
+diff -urNp linux-2.6.38.7/arch/powerpc/sysdev/ppc4xx_cpm.c linux-2.6.38.7/arch/powerpc/sysdev/ppc4xx_cpm.c
+--- linux-2.6.38.7/arch/powerpc/sysdev/ppc4xx_cpm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/powerpc/sysdev/ppc4xx_cpm.c 2011-04-28 19:34:14.000000000 -0400
+@@ -240,7 +240,7 @@ static int cpm_suspend_enter(suspend_sta
+ return 0;
+ }
+
+-static struct platform_suspend_ops cpm_suspend_ops = {
++static const struct platform_suspend_ops cpm_suspend_ops = {
+ .valid = cpm_suspend_valid,
+ .enter = cpm_suspend_enter,
+ };
+diff -urNp linux-2.6.38.7/arch/s390/include/asm/elf.h linux-2.6.38.7/arch/s390/include/asm/elf.h
+--- linux-2.6.38.7/arch/s390/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/include/asm/elf.h 2011-04-28 19:34:14.000000000 -0400
+@@ -162,8 +162,14 @@ extern unsigned int vdso_enabled;
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+-extern unsigned long randomize_et_dyn(unsigned long base);
+-#define ELF_ET_DYN_BASE (randomize_et_dyn(STACK_TOP / 3 * 2))
++#define ELF_ET_DYN_BASE (STACK_TOP / 3 * 2)
++
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_31BIT) ? 0x10000UL : 0x80000000UL)
++
++#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_31BIT) ? 15 : 26 )
++#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_31BIT) ? 15 : 26 )
++#endif
+
+ /* This yields a mask that user programs can use to figure out what
+ instruction set this CPU supports. */
+@@ -222,7 +228,4 @@ struct linux_binprm;
+ #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+ int arch_setup_additional_pages(struct linux_binprm *, int);
+
+-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+-#define arch_randomize_brk arch_randomize_brk
+-
+ #endif
+diff -urNp linux-2.6.38.7/arch/s390/include/asm/system.h linux-2.6.38.7/arch/s390/include/asm/system.h
+--- linux-2.6.38.7/arch/s390/include/asm/system.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/include/asm/system.h 2011-04-28 19:34:14.000000000 -0400
+@@ -449,7 +449,7 @@ extern void (*_machine_restart)(char *co
+ extern void (*_machine_halt)(void);
+ extern void (*_machine_power_off)(void);
+
+-extern unsigned long arch_align_stack(unsigned long sp);
++#define arch_align_stack(x) ((x) & ~0xfUL)
+
+ static inline int tprot(unsigned long addr)
+ {
+diff -urNp linux-2.6.38.7/arch/s390/include/asm/uaccess.h linux-2.6.38.7/arch/s390/include/asm/uaccess.h
+--- linux-2.6.38.7/arch/s390/include/asm/uaccess.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/include/asm/uaccess.h 2011-04-28 19:34:14.000000000 -0400
+@@ -234,6 +234,10 @@ static inline unsigned long __must_check
+ copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
+ might_fault();
++
++ if ((long)n < 0)
++ return n;
++
+ if (access_ok(VERIFY_WRITE, to, n))
+ n = __copy_to_user(to, from, n);
+ return n;
+@@ -259,6 +263,9 @@ copy_to_user(void __user *to, const void
+ static inline unsigned long __must_check
+ __copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
++ if ((long)n < 0)
++ return n;
++
+ if (__builtin_constant_p(n) && (n <= 256))
+ return uaccess.copy_from_user_small(n, from, to);
+ else
+@@ -293,6 +300,10 @@ copy_from_user(void *to, const void __us
+ unsigned int sz = __compiletime_object_size(to);
+
+ might_fault();
++
++ if ((long)n < 0)
++ return n;
++
+ if (unlikely(sz != -1 && sz < n)) {
+ copy_from_user_overflow();
+ return n;
+diff -urNp linux-2.6.38.7/arch/s390/Kconfig linux-2.6.38.7/arch/s390/Kconfig
+--- linux-2.6.38.7/arch/s390/Kconfig 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/Kconfig 2011-04-28 19:34:14.000000000 -0400
+@@ -233,11 +233,9 @@ config S390_EXEC_PROTECT
+ prompt "Data execute protection"
+ help
+ This option allows to enable a buffer overflow protection for user
+- space programs and it also selects the addressing mode option above.
+- The kernel parameter noexec=on will enable this feature and also
+- switch the addressing modes, default is disabled. Enabling this (via
+- kernel parameter) on machines earlier than IBM System z9 this will
+- reduce system performance.
++ space programs.
++ Enabling this (via kernel parameter) on machines earlier than IBM
++ System z9 this will reduce system performance.
+
+ comment "Code generation options"
+
+diff -urNp linux-2.6.38.7/arch/s390/kernel/module.c linux-2.6.38.7/arch/s390/kernel/module.c
+--- linux-2.6.38.7/arch/s390/kernel/module.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/kernel/module.c 2011-04-28 19:34:14.000000000 -0400
+@@ -168,11 +168,11 @@ module_frob_arch_sections(Elf_Ehdr *hdr,
+
+ /* Increase core size by size of got & plt and set start
+ offsets for got and plt. */
+- me->core_size = ALIGN(me->core_size, 4);
+- me->arch.got_offset = me->core_size;
+- me->core_size += me->arch.got_size;
+- me->arch.plt_offset = me->core_size;
+- me->core_size += me->arch.plt_size;
++ me->core_size_rw = ALIGN(me->core_size_rw, 4);
++ me->arch.got_offset = me->core_size_rw;
++ me->core_size_rw += me->arch.got_size;
++ me->arch.plt_offset = me->core_size_rx;
++ me->core_size_rx += me->arch.plt_size;
+ return 0;
+ }
+
+@@ -258,7 +258,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
+ if (info->got_initialized == 0) {
+ Elf_Addr *gotent;
+
+- gotent = me->module_core + me->arch.got_offset +
++ gotent = me->module_core_rw + me->arch.got_offset +
+ info->got_offset;
+ *gotent = val;
+ info->got_initialized = 1;
+@@ -282,7 +282,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
+ else if (r_type == R_390_GOTENT ||
+ r_type == R_390_GOTPLTENT)
+ *(unsigned int *) loc =
+- (val + (Elf_Addr) me->module_core - loc) >> 1;
++ (val + (Elf_Addr) me->module_core_rw - loc) >> 1;
+ else if (r_type == R_390_GOT64 ||
+ r_type == R_390_GOTPLT64)
+ *(unsigned long *) loc = val;
+@@ -296,7 +296,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
+ case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
+ if (info->plt_initialized == 0) {
+ unsigned int *ip;
+- ip = me->module_core + me->arch.plt_offset +
++ ip = me->module_core_rx + me->arch.plt_offset +
+ info->plt_offset;
+ #ifndef CONFIG_64BIT
+ ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */
+@@ -321,7 +321,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
+ val - loc + 0xffffUL < 0x1ffffeUL) ||
+ (r_type == R_390_PLT32DBL &&
+ val - loc + 0xffffffffULL < 0x1fffffffeULL)))
+- val = (Elf_Addr) me->module_core +
++ val = (Elf_Addr) me->module_core_rx +
+ me->arch.plt_offset +
+ info->plt_offset;
+ val += rela->r_addend - loc;
+@@ -343,7 +343,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
+ case R_390_GOTOFF32: /* 32 bit offset to GOT. */
+ case R_390_GOTOFF64: /* 64 bit offset to GOT. */
+ val = val + rela->r_addend -
+- ((Elf_Addr) me->module_core + me->arch.got_offset);
++ ((Elf_Addr) me->module_core_rw + me->arch.got_offset);
+ if (r_type == R_390_GOTOFF16)
+ *(unsigned short *) loc = val;
+ else if (r_type == R_390_GOTOFF32)
+@@ -353,7 +353,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
+ break;
+ case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */
+ case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */
+- val = (Elf_Addr) me->module_core + me->arch.got_offset +
++ val = (Elf_Addr) me->module_core_rw + me->arch.got_offset +
+ rela->r_addend - loc;
+ if (r_type == R_390_GOTPC)
+ *(unsigned int *) loc = val;
+diff -urNp linux-2.6.38.7/arch/s390/kernel/process.c linux-2.6.38.7/arch/s390/kernel/process.c
+--- linux-2.6.38.7/arch/s390/kernel/process.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/kernel/process.c 2011-04-28 19:34:14.000000000 -0400
+@@ -334,39 +334,3 @@ unsigned long get_wchan(struct task_stru
+ }
+ return 0;
+ }
+-
+-unsigned long arch_align_stack(unsigned long sp)
+-{
+- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+- sp -= get_random_int() & ~PAGE_MASK;
+- return sp & ~0xf;
+-}
+-
+-static inline unsigned long brk_rnd(void)
+-{
+- /* 8MB for 32bit, 1GB for 64bit */
+- if (is_32bit_task())
+- return (get_random_int() & 0x7ffUL) << PAGE_SHIFT;
+- else
+- return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT;
+-}
+-
+-unsigned long arch_randomize_brk(struct mm_struct *mm)
+-{
+- unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd());
+-
+- if (ret < mm->brk)
+- return mm->brk;
+- return ret;
+-}
+-
+-unsigned long randomize_et_dyn(unsigned long base)
+-{
+- unsigned long ret = PAGE_ALIGN(base + brk_rnd());
+-
+- if (!(current->flags & PF_RANDOMIZE))
+- return base;
+- if (ret < base)
+- return base;
+- return ret;
+-}
+diff -urNp linux-2.6.38.7/arch/s390/kernel/setup.c linux-2.6.38.7/arch/s390/kernel/setup.c
+--- linux-2.6.38.7/arch/s390/kernel/setup.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/kernel/setup.c 2011-04-28 19:34:14.000000000 -0400
+@@ -281,7 +281,7 @@ static int __init early_parse_mem(char *
+ }
+ early_param("mem", early_parse_mem);
+
+-unsigned int user_mode = HOME_SPACE_MODE;
++unsigned int user_mode = SECONDARY_SPACE_MODE;
+ EXPORT_SYMBOL_GPL(user_mode);
+
+ static int set_amode_and_uaccess(unsigned long user_amode,
+@@ -310,17 +310,6 @@ static int set_amode_and_uaccess(unsigne
+ }
+ }
+
+-/*
+- * Switch kernel/user addressing modes?
+- */
+-static int __init early_parse_switch_amode(char *p)
+-{
+- if (user_mode != SECONDARY_SPACE_MODE)
+- user_mode = PRIMARY_SPACE_MODE;
+- return 0;
+-}
+-early_param("switch_amode", early_parse_switch_amode);
+-
+ static int __init early_parse_user_mode(char *p)
+ {
+ if (p && strcmp(p, "primary") == 0)
+@@ -337,20 +326,6 @@ static int __init early_parse_user_mode(
+ }
+ early_param("user_mode", early_parse_user_mode);
+
+-#ifdef CONFIG_S390_EXEC_PROTECT
+-/*
+- * Enable execute protection?
+- */
+-static int __init early_parse_noexec(char *p)
+-{
+- if (!strncmp(p, "off", 3))
+- return 0;
+- user_mode = SECONDARY_SPACE_MODE;
+- return 0;
+-}
+-early_param("noexec", early_parse_noexec);
+-#endif /* CONFIG_S390_EXEC_PROTECT */
+-
+ static void setup_addressing_mode(void)
+ {
+ if (user_mode == SECONDARY_SPACE_MODE) {
+diff -urNp linux-2.6.38.7/arch/s390/mm/maccess.c linux-2.6.38.7/arch/s390/mm/maccess.c
+--- linux-2.6.38.7/arch/s390/mm/maccess.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/mm/maccess.c 2011-04-28 19:34:14.000000000 -0400
+@@ -45,7 +45,7 @@ static long probe_kernel_write_odd(void
+ return rc ? rc : count;
+ }
+
+-long probe_kernel_write(void *dst, void *src, size_t size)
++long probe_kernel_write(void *dst, const void *src, size_t size)
+ {
+ long copied = 0;
+
+diff -urNp linux-2.6.38.7/arch/s390/mm/mmap.c linux-2.6.38.7/arch/s390/mm/mmap.c
+--- linux-2.6.38.7/arch/s390/mm/mmap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/s390/mm/mmap.c 2011-04-28 19:34:14.000000000 -0400
+@@ -91,10 +91,22 @@ void arch_pick_mmap_layout(struct mm_str
+ */
+ if (mmap_is_legacy()) {
+ mm->mmap_base = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+ mm->mmap_base = mmap_base();
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
+@@ -166,10 +178,22 @@ void arch_pick_mmap_layout(struct mm_str
+ */
+ if (mmap_is_legacy()) {
+ mm->mmap_base = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
+ mm->get_unmapped_area = s390_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+ mm->mmap_base = mmap_base();
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
++#endif
++
+ mm->get_unmapped_area = s390_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
+diff -urNp linux-2.6.38.7/arch/score/include/asm/system.h linux-2.6.38.7/arch/score/include/asm/system.h
+--- linux-2.6.38.7/arch/score/include/asm/system.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/score/include/asm/system.h 2011-04-28 19:34:14.000000000 -0400
+@@ -17,7 +17,7 @@ do { \
+ #define finish_arch_switch(prev) do {} while (0)
+
+ typedef void (*vi_handler_t)(void);
+-extern unsigned long arch_align_stack(unsigned long sp);
++#define arch_align_stack(x) (x)
+
+ #define mb() barrier()
+ #define rmb() barrier()
+diff -urNp linux-2.6.38.7/arch/score/kernel/process.c linux-2.6.38.7/arch/score/kernel/process.c
+--- linux-2.6.38.7/arch/score/kernel/process.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/score/kernel/process.c 2011-04-28 19:34:14.000000000 -0400
+@@ -161,8 +161,3 @@ unsigned long get_wchan(struct task_stru
+
+ return task_pt_regs(task)->cp0_epc;
+ }
+-
+-unsigned long arch_align_stack(unsigned long sp)
+-{
+- return sp;
+-}
+diff -urNp linux-2.6.38.7/arch/sh/include/asm/dma-mapping.h linux-2.6.38.7/arch/sh/include/asm/dma-mapping.h
+--- linux-2.6.38.7/arch/sh/include/asm/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sh/include/asm/dma-mapping.h 2011-04-28 19:34:14.000000000 -0400
+@@ -1,10 +1,10 @@
+ #ifndef __ASM_SH_DMA_MAPPING_H
+ #define __ASM_SH_DMA_MAPPING_H
+
+-extern struct dma_map_ops *dma_ops;
++extern const struct dma_map_ops *dma_ops;
+ extern void no_iommu_init(void);
+
+-static inline struct dma_map_ops *get_dma_ops(struct device *dev)
++static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
+ {
+ return dma_ops;
+ }
+@@ -14,7 +14,7 @@ static inline struct dma_map_ops *get_dm
+
+ static inline int dma_supported(struct device *dev, u64 mask)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ if (ops->dma_supported)
+ return ops->dma_supported(dev, mask);
+@@ -24,7 +24,7 @@ static inline int dma_supported(struct d
+
+ static inline int dma_set_mask(struct device *dev, u64 mask)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ if (!dev->dma_mask || !dma_supported(dev, mask))
+ return -EIO;
+@@ -44,7 +44,7 @@ void dma_cache_sync(struct device *dev,
+
+ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ if (ops->mapping_error)
+ return ops->mapping_error(dev, dma_addr);
+@@ -55,7 +55,7 @@ static inline int dma_mapping_error(stru
+ static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ void *memory;
+
+ if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
+@@ -72,7 +72,7 @@ static inline void *dma_alloc_coherent(s
+ static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ if (dma_release_from_coherent(dev, get_order(size), vaddr))
+ return;
+diff -urNp linux-2.6.38.7/arch/sh/kernel/dma-nommu.c linux-2.6.38.7/arch/sh/kernel/dma-nommu.c
+--- linux-2.6.38.7/arch/sh/kernel/dma-nommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sh/kernel/dma-nommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -62,7 +62,7 @@ static void nommu_sync_sg(struct device
+ }
+ #endif
+
+-struct dma_map_ops nommu_dma_ops = {
++const struct dma_map_ops nommu_dma_ops = {
+ .alloc_coherent = dma_generic_alloc_coherent,
+ .free_coherent = dma_generic_free_coherent,
+ .map_page = nommu_map_page,
+diff -urNp linux-2.6.38.7/arch/sh/kernel/kgdb.c linux-2.6.38.7/arch/sh/kernel/kgdb.c
+--- linux-2.6.38.7/arch/sh/kernel/kgdb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sh/kernel/kgdb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -319,7 +319,7 @@ void kgdb_arch_exit(void)
+ unregister_die_notifier(&kgdb_notifier);
+ }
+
+-struct kgdb_arch arch_kgdb_ops = {
++const struct kgdb_arch arch_kgdb_ops = {
+ /* Breakpoint instruction: trapa #0x3c */
+ #ifdef CONFIG_CPU_LITTLE_ENDIAN
+ .gdb_bpt_instr = { 0x3c, 0xc3 },
+diff -urNp linux-2.6.38.7/arch/sh/mm/consistent.c linux-2.6.38.7/arch/sh/mm/consistent.c
+--- linux-2.6.38.7/arch/sh/mm/consistent.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sh/mm/consistent.c 2011-04-28 19:34:14.000000000 -0400
+@@ -22,7 +22,7 @@
+
+ #define PREALLOC_DMA_DEBUG_ENTRIES 4096
+
+-struct dma_map_ops *dma_ops;
++const struct dma_map_ops *dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+
+ static int __init dma_init(void)
+diff -urNp linux-2.6.38.7/arch/sh/mm/mmap.c linux-2.6.38.7/arch/sh/mm/mmap.c
+--- linux-2.6.38.7/arch/sh/mm/mmap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sh/mm/mmap.c 2011-04-28 19:34:14.000000000 -0400
+@@ -74,8 +74,7 @@ unsigned long arch_get_unmapped_area(str
+ addr = PAGE_ALIGN(addr);
+
+ vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (TASK_SIZE - len >= addr && check_heap_stack_gap(vma, addr, len))
+ return addr;
+ }
+
+@@ -106,7 +105,7 @@ full_search:
+ }
+ return -ENOMEM;
+ }
+- if (likely(!vma || addr + len <= vma->vm_start)) {
++ if (likely(check_heap_stack_gap(vma, addr, len))) {
+ /*
+ * Remember the place where we stopped the search:
+ */
+@@ -157,8 +156,7 @@ arch_get_unmapped_area_topdown(struct fi
+ addr = PAGE_ALIGN(addr);
+
+ vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (TASK_SIZE - len >= addr && check_heap_stack_gap(vma, addr, len))
+ return addr;
+ }
+
+@@ -179,7 +177,7 @@ arch_get_unmapped_area_topdown(struct fi
+ /* make sure it can fit in the remaining address space */
+ if (likely(addr > len)) {
+ vma = find_vma(mm, addr-len);
+- if (!vma || addr <= vma->vm_start) {
++ if (check_heap_stack_gap(vma, addr - len, len)) {
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr-len);
+ }
+@@ -188,18 +186,18 @@ arch_get_unmapped_area_topdown(struct fi
+ if (unlikely(mm->mmap_base < len))
+ goto bottomup;
+
+- addr = mm->mmap_base-len;
+- if (do_colour_align)
+- addr = COLOUR_ALIGN_DOWN(addr, pgoff);
++ addr = mm->mmap_base - len;
+
+ do {
++ if (do_colour_align)
++ addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+ /*
+ * Lookup failure means no vma is above this address,
+ * else if new region fits below vma->vm_start,
+ * return with success:
+ */
+ vma = find_vma(mm, addr);
+- if (likely(!vma || addr+len <= vma->vm_start)) {
++ if (likely(check_heap_stack_gap(vma, addr, len))) {
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr);
+ }
+@@ -209,10 +207,8 @@ arch_get_unmapped_area_topdown(struct fi
+ mm->cached_hole_size = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+- addr = vma->vm_start-len;
+- if (do_colour_align)
+- addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+- } while (likely(len < vma->vm_start));
++ addr = skip_heap_stack_gap(vma, len);
++ } while (!IS_ERR_VALUE(addr));
+
+ bottomup:
+ /*
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/atomic_64.h linux-2.6.38.7/arch/sparc/include/asm/atomic_64.h
+--- linux-2.6.38.7/arch/sparc/include/asm/atomic_64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/atomic_64.h 2011-04-28 19:57:25.000000000 -0400
+@@ -14,18 +14,40 @@
+ #define ATOMIC64_INIT(i) { (i) }
+
+ #define atomic_read(v) (*(volatile int *)&(v)->counter)
++static inline int atomic_read_unchecked(const atomic_unchecked_t *v)
++{
++ return v->counter;
++}
+ #define atomic64_read(v) (*(volatile long *)&(v)->counter)
++static inline long atomic64_read_unchecked(const atomic64_unchecked_t *v)
++{
++ return v->counter;
++}
+
+ #define atomic_set(v, i) (((v)->counter) = i)
++static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i)
++{
++ v->counter = i;
++}
+ #define atomic64_set(v, i) (((v)->counter) = i)
++static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i)
++{
++ v->counter = i;
++}
+
+ extern void atomic_add(int, atomic_t *);
++extern void atomic_add_unchecked(int, atomic_unchecked_t *);
+ extern void atomic64_add(long, atomic64_t *);
++extern void atomic64_add_unchecked(long, atomic64_unchecked_t *);
+ extern void atomic_sub(int, atomic_t *);
++extern void atomic_sub_unchecked(int, atomic_unchecked_t *);
+ extern void atomic64_sub(long, atomic64_t *);
++extern void atomic64_sub_unchecked(long, atomic64_unchecked_t *);
+
+ extern int atomic_add_ret(int, atomic_t *);
++extern int atomic_add_ret_unchecked(int, atomic_unchecked_t *);
+ extern long atomic64_add_ret(long, atomic64_t *);
++extern long atomic64_add_ret_unchecked(long, atomic64_unchecked_t *);
+ extern int atomic_sub_ret(int, atomic_t *);
+ extern long atomic64_sub_ret(long, atomic64_t *);
+
+@@ -33,12 +55,24 @@ extern long atomic64_sub_ret(long, atomi
+ #define atomic64_dec_return(v) atomic64_sub_ret(1, v)
+
+ #define atomic_inc_return(v) atomic_add_ret(1, v)
++static inline int atomic_inc_return_unchecked(atomic_unchecked_t *v)
++{
++ return atomic_add_ret_unchecked(1, v);
++}
+ #define atomic64_inc_return(v) atomic64_add_ret(1, v)
++static inline long atomic64_inc_return_unchecked(atomic64_unchecked_t *v)
++{
++ return atomic64_add_ret_unchecked(1, v);
++}
+
+ #define atomic_sub_return(i, v) atomic_sub_ret(i, v)
+ #define atomic64_sub_return(i, v) atomic64_sub_ret(i, v)
+
+ #define atomic_add_return(i, v) atomic_add_ret(i, v)
++static inline int atomic_add_return_unchecked(int i, atomic_unchecked_t *v)
++{
++ return atomic_add_ret_unchecked(i, v);
++}
+ #define atomic64_add_return(i, v) atomic64_add_ret(i, v)
+
+ /*
+@@ -50,6 +84,7 @@ extern long atomic64_sub_ret(long, atomi
+ * other cases.
+ */
+ #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
++#define atomic_inc_and_test_unchecked(v) (atomic_inc_return_unchecked(v) == 0)
+ #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
+
+ #define atomic_sub_and_test(i, v) (atomic_sub_ret(i, v) == 0)
+@@ -59,30 +94,59 @@ extern long atomic64_sub_ret(long, atomi
+ #define atomic64_dec_and_test(v) (atomic64_sub_ret(1, v) == 0)
+
+ #define atomic_inc(v) atomic_add(1, v)
++static inline void atomic_inc_unchecked(atomic_unchecked_t *v)
++{
++ atomic_add_unchecked(1, v);
++}
+ #define atomic64_inc(v) atomic64_add(1, v)
++static inline void atomic64_inc_unchecked(atomic64_unchecked_t *v)
++{
++ atomic64_add_unchecked(1, v);
++}
+
+ #define atomic_dec(v) atomic_sub(1, v)
++static inline void atomic_dec_unchecked(atomic_unchecked_t *v)
++{
++ atomic_sub_unchecked(1, v);
++}
+ #define atomic64_dec(v) atomic64_sub(1, v)
++static inline void atomic64_dec_unchecked(atomic64_unchecked_t *v)
++{
++ atomic64_sub_unchecked(1, v);
++}
+
+ #define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0)
+ #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0)
+
+ #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
++#define atomic_cmpxchg_unchecked(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+ #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
++#define atomic_xchg_unchecked(v, new) (xchg(&((v)->counter), new))
+
+ static inline int atomic_add_unless(atomic_t *v, int a, int u)
+ {
+- int c, old;
++ int c, old, new;
+ c = atomic_read(v);
+ for (;;) {
+- if (unlikely(c == (u)))
++ if (unlikely(c == u))
+ break;
+- old = atomic_cmpxchg((v), c, c + (a));
++
++ asm volatile("addcc %2, %0, %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "tvs %%icc, 6\n"
++#endif
++
++ : "=r" (new)
++ : "0" (c), "ir" (a)
++ : "cc");
++
++ old = atomic_cmpxchg(v, c, new);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+- return c != (u);
++ return c != u;
+ }
+
+ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+@@ -93,17 +157,28 @@ static inline int atomic_add_unless(atom
+
+ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
+ {
+- long c, old;
++ long c, old, new;
+ c = atomic64_read(v);
+ for (;;) {
+- if (unlikely(c == (u)))
++ if (unlikely(c == u))
+ break;
+- old = atomic64_cmpxchg((v), c, c + (a));
++
++ asm volatile("addcc %2, %0, %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "tvs %%xcc, 6\n"
++#endif
++
++ : "=r" (new)
++ : "0" (c), "ir" (a)
++ : "cc");
++
++ old = atomic64_cmpxchg(v, c, new);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+- return c != (u);
++ return c != u;
+ }
+
+ #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/cache.h linux-2.6.38.7/arch/sparc/include/asm/cache.h
+--- linux-2.6.38.7/arch/sparc/include/asm/cache.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/cache.h 2011-05-17 19:31:43.000000000 -0400
+@@ -10,7 +10,7 @@
+ #define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
+
+ #define L1_CACHE_SHIFT 5
+-#define L1_CACHE_BYTES 32
++#define L1_CACHE_BYTES 32U
+
+ #ifdef CONFIG_SPARC32
+ #define SMP_CACHE_BYTES_SHIFT 5
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/dma-mapping.h linux-2.6.38.7/arch/sparc/include/asm/dma-mapping.h
+--- linux-2.6.38.7/arch/sparc/include/asm/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/dma-mapping.h 2011-04-28 19:34:14.000000000 -0400
+@@ -12,10 +12,10 @@ extern int dma_supported(struct device *
+ #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+ #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+-extern struct dma_map_ops *dma_ops, pci32_dma_ops;
++extern const struct dma_map_ops *dma_ops, pci32_dma_ops;
+ extern struct bus_type pci_bus_type;
+
+-static inline struct dma_map_ops *get_dma_ops(struct device *dev)
++static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
+ {
+ #if defined(CONFIG_SPARC32) && defined(CONFIG_PCI)
+ if (dev->bus == &pci_bus_type)
+@@ -29,7 +29,7 @@ static inline struct dma_map_ops *get_dm
+ static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ void *cpu_addr;
+
+ cpu_addr = ops->alloc_coherent(dev, size, dma_handle, flag);
+@@ -40,7 +40,7 @@ static inline void *dma_alloc_coherent(s
+ static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+ ops->free_coherent(dev, size, cpu_addr, dma_handle);
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/elf_32.h linux-2.6.38.7/arch/sparc/include/asm/elf_32.h
+--- linux-2.6.38.7/arch/sparc/include/asm/elf_32.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/elf_32.h 2011-04-28 19:34:14.000000000 -0400
+@@ -114,6 +114,13 @@ typedef struct {
+
+ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE)
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE 0x10000UL
++
++#define PAX_DELTA_MMAP_LEN 16
++#define PAX_DELTA_STACK_LEN 16
++#endif
++
+ /* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. This can NOT be done in userspace
+ on Sparc. */
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/elf_64.h linux-2.6.38.7/arch/sparc/include/asm/elf_64.h
+--- linux-2.6.38.7/arch/sparc/include/asm/elf_64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/elf_64.h 2011-04-28 19:34:14.000000000 -0400
+@@ -162,6 +162,12 @@ typedef struct {
+ #define ELF_ET_DYN_BASE 0x0000010000000000UL
+ #define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL
+
++#ifdef CONFIG_PAX_ASLR
++#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL)
++
++#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT) ? 14 : 28)
++#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT) ? 15 : 29)
++#endif
+
+ /* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. */
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/pgtable_32.h linux-2.6.38.7/arch/sparc/include/asm/pgtable_32.h
+--- linux-2.6.38.7/arch/sparc/include/asm/pgtable_32.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/pgtable_32.h 2011-04-28 19:34:14.000000000 -0400
+@@ -43,6 +43,13 @@ BTFIXUPDEF_SIMM13(user_ptrs_per_pgd)
+ BTFIXUPDEF_INT(page_none)
+ BTFIXUPDEF_INT(page_copy)
+ BTFIXUPDEF_INT(page_readonly)
++
++#ifdef CONFIG_PAX_PAGEEXEC
++BTFIXUPDEF_INT(page_shared_noexec)
++BTFIXUPDEF_INT(page_copy_noexec)
++BTFIXUPDEF_INT(page_readonly_noexec)
++#endif
++
+ BTFIXUPDEF_INT(page_kernel)
+
+ #define PMD_SHIFT SUN4C_PMD_SHIFT
+@@ -64,6 +71,16 @@ extern pgprot_t PAGE_SHARED;
+ #define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy))
+ #define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly))
+
++#ifdef CONFIG_PAX_PAGEEXEC
++extern pgprot_t PAGE_SHARED_NOEXEC;
++# define PAGE_COPY_NOEXEC __pgprot(BTFIXUP_INT(page_copy_noexec))
++# define PAGE_READONLY_NOEXEC __pgprot(BTFIXUP_INT(page_readonly_noexec))
++#else
++# define PAGE_SHARED_NOEXEC PAGE_SHARED
++# define PAGE_COPY_NOEXEC PAGE_COPY
++# define PAGE_READONLY_NOEXEC PAGE_READONLY
++#endif
++
+ extern unsigned long page_kernel;
+
+ #ifdef MODULE
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/pgtsrmmu.h linux-2.6.38.7/arch/sparc/include/asm/pgtsrmmu.h
+--- linux-2.6.38.7/arch/sparc/include/asm/pgtsrmmu.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/pgtsrmmu.h 2011-04-28 19:34:14.000000000 -0400
+@@ -115,6 +115,13 @@
+ SRMMU_EXEC | SRMMU_REF)
+ #define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
+ SRMMU_EXEC | SRMMU_REF)
++
++#ifdef CONFIG_PAX_PAGEEXEC
++#define SRMMU_PAGE_SHARED_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_WRITE | SRMMU_REF)
++#define SRMMU_PAGE_COPY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_REF)
++#define SRMMU_PAGE_RDONLY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_REF)
++#endif
++
+ #define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
+ SRMMU_DIRTY | SRMMU_REF)
+
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/spinlock_64.h linux-2.6.38.7/arch/sparc/include/asm/spinlock_64.h
+--- linux-2.6.38.7/arch/sparc/include/asm/spinlock_64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/spinlock_64.h 2011-04-28 19:57:25.000000000 -0400
+@@ -92,14 +92,19 @@ static inline void arch_spin_lock_flags(
+
+ /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
+
+-static void inline arch_read_lock(arch_rwlock_t *lock)
++static inline void arch_read_lock(arch_rwlock_t *lock)
+ {
+ unsigned long tmp1, tmp2;
+
+ __asm__ __volatile__ (
+ "1: ldsw [%2], %0\n"
+ " brlz,pn %0, 2f\n"
+-"4: add %0, 1, %1\n"
++"4: addcc %0, 1, %1\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++" tvs %%icc, 6\n"
++#endif
++
+ " cas [%2], %0, %1\n"
+ " cmp %0, %1\n"
+ " bne,pn %%icc, 1b\n"
+@@ -112,10 +117,10 @@ static void inline arch_read_lock(arch_r
+ " .previous"
+ : "=&r" (tmp1), "=&r" (tmp2)
+ : "r" (lock)
+- : "memory");
++ : "memory", "cc");
+ }
+
+-static int inline arch_read_trylock(arch_rwlock_t *lock)
++static inline int arch_read_trylock(arch_rwlock_t *lock)
+ {
+ int tmp1, tmp2;
+
+@@ -123,7 +128,12 @@ static int inline arch_read_trylock(arch
+ "1: ldsw [%2], %0\n"
+ " brlz,a,pn %0, 2f\n"
+ " mov 0, %0\n"
+-" add %0, 1, %1\n"
++" addcc %0, 1, %1\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++" tvs %%icc, 6\n"
++#endif
++
+ " cas [%2], %0, %1\n"
+ " cmp %0, %1\n"
+ " bne,pn %%icc, 1b\n"
+@@ -136,13 +146,18 @@ static int inline arch_read_trylock(arch
+ return tmp1;
+ }
+
+-static void inline arch_read_unlock(arch_rwlock_t *lock)
++static inline void arch_read_unlock(arch_rwlock_t *lock)
+ {
+ unsigned long tmp1, tmp2;
+
+ __asm__ __volatile__(
+ "1: lduw [%2], %0\n"
+-" sub %0, 1, %1\n"
++" subcc %0, 1, %1\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++" tvs %%icc, 6\n"
++#endif
++
+ " cas [%2], %0, %1\n"
+ " cmp %0, %1\n"
+ " bne,pn %%xcc, 1b\n"
+@@ -152,7 +167,7 @@ static void inline arch_read_unlock(arch
+ : "memory");
+ }
+
+-static void inline arch_write_lock(arch_rwlock_t *lock)
++static inline void arch_write_lock(arch_rwlock_t *lock)
+ {
+ unsigned long mask, tmp1, tmp2;
+
+@@ -177,7 +192,7 @@ static void inline arch_write_lock(arch_
+ : "memory");
+ }
+
+-static void inline arch_write_unlock(arch_rwlock_t *lock)
++static inline void arch_write_unlock(arch_rwlock_t *lock)
+ {
+ __asm__ __volatile__(
+ " stw %%g0, [%0]"
+@@ -186,7 +201,7 @@ static void inline arch_write_unlock(arc
+ : "memory");
+ }
+
+-static int inline arch_write_trylock(arch_rwlock_t *lock)
++static inline int arch_write_trylock(arch_rwlock_t *lock)
+ {
+ unsigned long mask, tmp1, tmp2, result;
+
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/uaccess_32.h linux-2.6.38.7/arch/sparc/include/asm/uaccess_32.h
+--- linux-2.6.38.7/arch/sparc/include/asm/uaccess_32.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/uaccess_32.h 2011-04-28 19:34:14.000000000 -0400
+@@ -249,27 +249,46 @@ extern unsigned long __copy_user(void __
+
+ static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
+- if (n && __access_ok((unsigned long) to, n))
++ if ((long)n < 0)
++ return n;
++
++ if (n && __access_ok((unsigned long) to, n)) {
++ if (!__builtin_constant_p(n))
++ check_object_size(from, n, true);
+ return __copy_user(to, (__force void __user *) from, n);
+- else
++ } else
+ return n;
+ }
+
+ static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
++ if ((long)n < 0)
++ return n;
++
++ if (!__builtin_constant_p(n))
++ check_object_size(from, n, true);
++
+ return __copy_user(to, (__force void __user *) from, n);
+ }
+
+ static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
+- if (n && __access_ok((unsigned long) from, n))
++ if ((long)n < 0)
++ return n;
++
++ if (n && __access_ok((unsigned long) from, n)) {
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
+ return __copy_user((__force void __user *) to, from, n);
+- else
++ } else
+ return n;
+ }
+
+ static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
++ if ((long)n < 0)
++ return n;
++
+ return __copy_user((__force void __user *) to, from, n);
+ }
+
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/uaccess_64.h linux-2.6.38.7/arch/sparc/include/asm/uaccess_64.h
+--- linux-2.6.38.7/arch/sparc/include/asm/uaccess_64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/uaccess_64.h 2011-04-28 19:34:14.000000000 -0400
+@@ -10,6 +10,7 @@
+ #include <linux/compiler.h>
+ #include <linux/string.h>
+ #include <linux/thread_info.h>
++#include <linux/kernel.h>
+ #include <asm/asi.h>
+ #include <asm/system.h>
+ #include <asm/spitfire.h>
+@@ -213,8 +214,15 @@ extern unsigned long copy_from_user_fixu
+ static inline unsigned long __must_check
+ copy_from_user(void *to, const void __user *from, unsigned long size)
+ {
+- unsigned long ret = ___copy_from_user(to, from, size);
++ unsigned long ret;
+
++ if ((long)size < 0 || size > INT_MAX)
++ return size;
++
++ if (!__builtin_constant_p(size))
++ check_object_size(to, size, false);
++
++ ret = ___copy_from_user(to, from, size);
+ if (unlikely(ret))
+ ret = copy_from_user_fixup(to, from, size);
+
+@@ -230,8 +238,15 @@ extern unsigned long copy_to_user_fixup(
+ static inline unsigned long __must_check
+ copy_to_user(void __user *to, const void *from, unsigned long size)
+ {
+- unsigned long ret = ___copy_to_user(to, from, size);
++ unsigned long ret;
++
++ if ((long)size < 0 || size > INT_MAX)
++ return size;
++
++ if (!__builtin_constant_p(size))
++ check_object_size(from, size, true);
+
++ ret = ___copy_to_user(to, from, size);
+ if (unlikely(ret))
+ ret = copy_to_user_fixup(to, from, size);
+ return ret;
+diff -urNp linux-2.6.38.7/arch/sparc/include/asm/uaccess.h linux-2.6.38.7/arch/sparc/include/asm/uaccess.h
+--- linux-2.6.38.7/arch/sparc/include/asm/uaccess.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/include/asm/uaccess.h 2011-04-28 19:34:14.000000000 -0400
+@@ -1,5 +1,13 @@
+ #ifndef ___ASM_SPARC_UACCESS_H
+ #define ___ASM_SPARC_UACCESS_H
++
++#ifdef __KERNEL__
++#ifndef __ASSEMBLY__
++#include <linux/types.h>
++extern void check_object_size(const void *ptr, unsigned long n, bool to);
++#endif
++#endif
++
+ #if defined(__sparc__) && defined(__arch64__)
+ #include <asm/uaccess_64.h>
+ #else
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/iommu.c linux-2.6.38.7/arch/sparc/kernel/iommu.c
+--- linux-2.6.38.7/arch/sparc/kernel/iommu.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/iommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -824,7 +824,7 @@ static void dma_4u_sync_sg_for_cpu(struc
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ }
+
+-static struct dma_map_ops sun4u_dma_ops = {
++static const struct dma_map_ops sun4u_dma_ops = {
+ .alloc_coherent = dma_4u_alloc_coherent,
+ .free_coherent = dma_4u_free_coherent,
+ .map_page = dma_4u_map_page,
+@@ -835,7 +835,7 @@ static struct dma_map_ops sun4u_dma_ops
+ .sync_sg_for_cpu = dma_4u_sync_sg_for_cpu,
+ };
+
+-struct dma_map_ops *dma_ops = &sun4u_dma_ops;
++const struct dma_map_ops *dma_ops = &sun4u_dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+
+ extern int pci64_dma_supported(struct pci_dev *pdev, u64 device_mask);
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/ioport.c linux-2.6.38.7/arch/sparc/kernel/ioport.c
+--- linux-2.6.38.7/arch/sparc/kernel/ioport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/ioport.c 2011-04-28 19:34:14.000000000 -0400
+@@ -397,7 +397,7 @@ static void sbus_sync_sg_for_device(stru
+ BUG();
+ }
+
+-struct dma_map_ops sbus_dma_ops = {
++const struct dma_map_ops sbus_dma_ops = {
+ .alloc_coherent = sbus_alloc_coherent,
+ .free_coherent = sbus_free_coherent,
+ .map_page = sbus_map_page,
+@@ -408,7 +408,7 @@ struct dma_map_ops sbus_dma_ops = {
+ .sync_sg_for_device = sbus_sync_sg_for_device,
+ };
+
+-struct dma_map_ops *dma_ops = &sbus_dma_ops;
++const struct dma_map_ops *dma_ops = &sbus_dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+
+ static int __init sparc_register_ioport(void)
+@@ -645,7 +645,7 @@ static void pci32_sync_sg_for_device(str
+ }
+ }
+
+-struct dma_map_ops pci32_dma_ops = {
++const struct dma_map_ops pci32_dma_ops = {
+ .alloc_coherent = pci32_alloc_coherent,
+ .free_coherent = pci32_free_coherent,
+ .map_page = pci32_map_page,
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/kgdb_32.c linux-2.6.38.7/arch/sparc/kernel/kgdb_32.c
+--- linux-2.6.38.7/arch/sparc/kernel/kgdb_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/kgdb_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -164,7 +164,7 @@ void kgdb_arch_set_pc(struct pt_regs *re
+ regs->npc = regs->pc + 4;
+ }
+
+-struct kgdb_arch arch_kgdb_ops = {
++const struct kgdb_arch arch_kgdb_ops = {
+ /* Breakpoint instruction: ta 0x7d */
+ .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d },
+ };
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/kgdb_64.c linux-2.6.38.7/arch/sparc/kernel/kgdb_64.c
+--- linux-2.6.38.7/arch/sparc/kernel/kgdb_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/kgdb_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -187,7 +187,7 @@ void kgdb_arch_set_pc(struct pt_regs *re
+ regs->tnpc = regs->tpc + 4;
+ }
+
+-struct kgdb_arch arch_kgdb_ops = {
++const struct kgdb_arch arch_kgdb_ops = {
+ /* Breakpoint instruction: ta 0x72 */
+ .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 },
+ };
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/Makefile linux-2.6.38.7/arch/sparc/kernel/Makefile
+--- linux-2.6.38.7/arch/sparc/kernel/Makefile 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/Makefile 2011-04-28 19:34:14.000000000 -0400
+@@ -3,7 +3,7 @@
+ #
+
+ asflags-y := -ansi
+-ccflags-y := -Werror
++#ccflags-y := -Werror
+
+ extra-y := head_$(BITS).o
+ extra-y += init_task.o
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/pci_sun4v.c linux-2.6.38.7/arch/sparc/kernel/pci_sun4v.c
+--- linux-2.6.38.7/arch/sparc/kernel/pci_sun4v.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/pci_sun4v.c 2011-04-28 19:34:14.000000000 -0400
+@@ -525,7 +525,7 @@ static void dma_4v_unmap_sg(struct devic
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ }
+
+-static struct dma_map_ops sun4v_dma_ops = {
++static const struct dma_map_ops sun4v_dma_ops = {
+ .alloc_coherent = dma_4v_alloc_coherent,
+ .free_coherent = dma_4v_free_coherent,
+ .map_page = dma_4v_map_page,
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/process_32.c linux-2.6.38.7/arch/sparc/kernel/process_32.c
+--- linux-2.6.38.7/arch/sparc/kernel/process_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/process_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -196,7 +196,7 @@ void __show_backtrace(unsigned long fp)
+ rw->ins[4], rw->ins[5],
+ rw->ins[6],
+ rw->ins[7]);
+- printk("%pS\n", (void *) rw->ins[7]);
++ printk("%pA\n", (void *) rw->ins[7]);
+ rw = (struct reg_window32 *) rw->ins[6];
+ }
+ spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
+@@ -263,14 +263,14 @@ void show_regs(struct pt_regs *r)
+
+ printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n",
+ r->psr, r->pc, r->npc, r->y, print_tainted());
+- printk("PC: <%pS>\n", (void *) r->pc);
++ printk("PC: <%pA>\n", (void *) r->pc);
+ printk("%%G: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ r->u_regs[0], r->u_regs[1], r->u_regs[2], r->u_regs[3],
+ r->u_regs[4], r->u_regs[5], r->u_regs[6], r->u_regs[7]);
+ printk("%%O: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ r->u_regs[8], r->u_regs[9], r->u_regs[10], r->u_regs[11],
+ r->u_regs[12], r->u_regs[13], r->u_regs[14], r->u_regs[15]);
+- printk("RPC: <%pS>\n", (void *) r->u_regs[15]);
++ printk("RPC: <%pA>\n", (void *) r->u_regs[15]);
+
+ printk("%%L: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
+@@ -305,7 +305,7 @@ void show_stack(struct task_struct *tsk,
+ rw = (struct reg_window32 *) fp;
+ pc = rw->ins[7];
+ printk("[%08lx : ", pc);
+- printk("%pS ] ", (void *) pc);
++ printk("%pA ] ", (void *) pc);
+ fp = rw->ins[6];
+ } while (++count < 16);
+ printk("\n");
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/process_64.c linux-2.6.38.7/arch/sparc/kernel/process_64.c
+--- linux-2.6.38.7/arch/sparc/kernel/process_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/process_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -180,14 +180,14 @@ static void show_regwindow(struct pt_reg
+ printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lx\n",
+ rwk->ins[4], rwk->ins[5], rwk->ins[6], rwk->ins[7]);
+ if (regs->tstate & TSTATE_PRIV)
+- printk("I7: <%pS>\n", (void *) rwk->ins[7]);
++ printk("I7: <%pA>\n", (void *) rwk->ins[7]);
+ }
+
+ void show_regs(struct pt_regs *regs)
+ {
+ printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate,
+ regs->tpc, regs->tnpc, regs->y, print_tainted());
+- printk("TPC: <%pS>\n", (void *) regs->tpc);
++ printk("TPC: <%pA>\n", (void *) regs->tpc);
+ printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
+ regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
+ regs->u_regs[3]);
+@@ -200,7 +200,7 @@ void show_regs(struct pt_regs *regs)
+ printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n",
+ regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
+ regs->u_regs[15]);
+- printk("RPC: <%pS>\n", (void *) regs->u_regs[15]);
++ printk("RPC: <%pA>\n", (void *) regs->u_regs[15]);
+ show_regwindow(regs);
+ show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]);
+ }
+@@ -285,7 +285,7 @@ void arch_trigger_all_cpu_backtrace(void
+ ((tp && tp->task) ? tp->task->pid : -1));
+
+ if (gp->tstate & TSTATE_PRIV) {
+- printk(" TPC[%pS] O7[%pS] I7[%pS] RPC[%pS]\n",
++ printk(" TPC[%pA] O7[%pA] I7[%pA] RPC[%pA]\n",
+ (void *) gp->tpc,
+ (void *) gp->o7,
+ (void *) gp->i7,
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/sys_sparc_32.c linux-2.6.38.7/arch/sparc/kernel/sys_sparc_32.c
+--- linux-2.6.38.7/arch/sparc/kernel/sys_sparc_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/sys_sparc_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -56,7 +56,7 @@ unsigned long arch_get_unmapped_area(str
+ if (ARCH_SUN4C && len > 0x20000000)
+ return -ENOMEM;
+ if (!addr)
+- addr = TASK_UNMAPPED_BASE;
++ addr = current->mm->mmap_base;
+
+ if (flags & MAP_SHARED)
+ addr = COLOUR_ALIGN(addr);
+@@ -71,7 +71,7 @@ unsigned long arch_get_unmapped_area(str
+ }
+ if (TASK_SIZE - PAGE_SIZE - len < addr)
+ return -ENOMEM;
+- if (!vmm || addr + len <= vmm->vm_start)
++ if (check_heap_stack_gap(vmm, addr, len))
+ return addr;
+ addr = vmm->vm_end;
+ if (flags & MAP_SHARED)
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/sys_sparc_64.c linux-2.6.38.7/arch/sparc/kernel/sys_sparc_64.c
+--- linux-2.6.38.7/arch/sparc/kernel/sys_sparc_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/sys_sparc_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -124,7 +124,7 @@ unsigned long arch_get_unmapped_area(str
+ /* We do not accept a shared mapping if it would violate
+ * cache aliasing constraints.
+ */
+- if ((flags & MAP_SHARED) &&
++ if ((filp || (flags & MAP_SHARED)) &&
+ ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
+ return -EINVAL;
+ return addr;
+@@ -139,6 +139,10 @@ unsigned long arch_get_unmapped_area(str
+ if (filp || (flags & MAP_SHARED))
+ do_color_align = 1;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ if (addr) {
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+@@ -146,15 +150,14 @@ unsigned long arch_get_unmapped_area(str
+ addr = PAGE_ALIGN(addr);
+
+ vma = find_vma(mm, addr);
+- if (task_size - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (task_size - len >= addr && check_heap_stack_gap(vma, addr, len))
+ return addr;
+ }
+
+ if (len > mm->cached_hole_size) {
+- start_addr = addr = mm->free_area_cache;
++ start_addr = addr = mm->free_area_cache;
+ } else {
+- start_addr = addr = TASK_UNMAPPED_BASE;
++ start_addr = addr = mm->mmap_base;
+ mm->cached_hole_size = 0;
+ }
+
+@@ -174,14 +177,14 @@ full_search:
+ vma = find_vma(mm, VA_EXCLUDE_END);
+ }
+ if (unlikely(task_size < addr)) {
+- if (start_addr != TASK_UNMAPPED_BASE) {
+- start_addr = addr = TASK_UNMAPPED_BASE;
++ if (start_addr != mm->mmap_base) {
++ start_addr = addr = mm->mmap_base;
+ mm->cached_hole_size = 0;
+ goto full_search;
+ }
+ return -ENOMEM;
+ }
+- if (likely(!vma || addr + len <= vma->vm_start)) {
++ if (likely(check_heap_stack_gap(vma, addr, len))) {
+ /*
+ * Remember the place where we stopped the search:
+ */
+@@ -215,7 +218,7 @@ arch_get_unmapped_area_topdown(struct fi
+ /* We do not accept a shared mapping if it would violate
+ * cache aliasing constraints.
+ */
+- if ((flags & MAP_SHARED) &&
++ if ((filp || (flags & MAP_SHARED)) &&
+ ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
+ return -EINVAL;
+ return addr;
+@@ -236,8 +239,7 @@ arch_get_unmapped_area_topdown(struct fi
+ addr = PAGE_ALIGN(addr);
+
+ vma = find_vma(mm, addr);
+- if (task_size - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (task_size - len >= addr && check_heap_stack_gap(vma, addr, len))
+ return addr;
+ }
+
+@@ -258,7 +260,7 @@ arch_get_unmapped_area_topdown(struct fi
+ /* make sure it can fit in the remaining address space */
+ if (likely(addr > len)) {
+ vma = find_vma(mm, addr-len);
+- if (!vma || addr <= vma->vm_start) {
++ if (check_heap_stack_gap(vma, addr - len, len)) {
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr-len);
+ }
+@@ -267,18 +269,18 @@ arch_get_unmapped_area_topdown(struct fi
+ if (unlikely(mm->mmap_base < len))
+ goto bottomup;
+
+- addr = mm->mmap_base-len;
+- if (do_color_align)
+- addr = COLOUR_ALIGN_DOWN(addr, pgoff);
++ addr = mm->mmap_base - len;
+
+ do {
++ if (do_color_align)
++ addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+ /*
+ * Lookup failure means no vma is above this address,
+ * else if new region fits below vma->vm_start,
+ * return with success:
+ */
+ vma = find_vma(mm, addr);
+- if (likely(!vma || addr+len <= vma->vm_start)) {
++ if (likely(check_heap_stack_gap(vma, addr, len))) {
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr);
+ }
+@@ -288,10 +290,8 @@ arch_get_unmapped_area_topdown(struct fi
+ mm->cached_hole_size = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+- addr = vma->vm_start-len;
+- if (do_color_align)
+- addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+- } while (likely(len < vma->vm_start));
++ addr = skip_heap_stack_gap(vma, len);
++ } while (!IS_ERR_VALUE(addr));
+
+ bottomup:
+ /*
+@@ -385,6 +385,12 @@ void arch_pick_mmap_layout(struct mm_str
+ gap == RLIM_INFINITY ||
+ sysctl_legacy_va_layout) {
+ mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+@@ -397,6 +403,12 @@ void arch_pick_mmap_layout(struct mm_str
+ gap = (task_size / 6 * 5);
+
+ mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor);
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/traps_32.c linux-2.6.38.7/arch/sparc/kernel/traps_32.c
+--- linux-2.6.38.7/arch/sparc/kernel/traps_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/traps_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -76,7 +76,7 @@ void die_if_kernel(char *str, struct pt_
+ count++ < 30 &&
+ (((unsigned long) rw) >= PAGE_OFFSET) &&
+ !(((unsigned long) rw) & 0x7)) {
+- printk("Caller[%08lx]: %pS\n", rw->ins[7],
++ printk("Caller[%08lx]: %pA\n", rw->ins[7],
+ (void *) rw->ins[7]);
+ rw = (struct reg_window32 *)rw->ins[6];
+ }
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/traps_64.c linux-2.6.38.7/arch/sparc/kernel/traps_64.c
+--- linux-2.6.38.7/arch/sparc/kernel/traps_64.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/traps_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -75,7 +75,7 @@ static void dump_tl1_traplog(struct tl1_
+ i + 1,
+ p->trapstack[i].tstate, p->trapstack[i].tpc,
+ p->trapstack[i].tnpc, p->trapstack[i].tt);
+- printk("TRAPLOG: TPC<%pS>\n", (void *) p->trapstack[i].tpc);
++ printk("TRAPLOG: TPC<%pA>\n", (void *) p->trapstack[i].tpc);
+ }
+ }
+
+@@ -95,6 +95,12 @@ void bad_trap(struct pt_regs *regs, long
+
+ lvl -= 0x100;
+ if (regs->tstate & TSTATE_PRIV) {
++
++#ifdef CONFIG_PAX_REFCOUNT
++ if (lvl == 6)
++ pax_report_refcount_overflow(regs);
++#endif
++
+ sprintf(buffer, "Kernel bad sw trap %lx", lvl);
+ die_if_kernel(buffer, regs);
+ }
+@@ -113,11 +119,16 @@ void bad_trap(struct pt_regs *regs, long
+ void bad_trap_tl1(struct pt_regs *regs, long lvl)
+ {
+ char buffer[32];
+-
++
+ if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
+ 0, lvl, SIGTRAP) == NOTIFY_STOP)
+ return;
+
++#ifdef CONFIG_PAX_REFCOUNT
++ if (lvl == 6)
++ pax_report_refcount_overflow(regs);
++#endif
++
+ dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
+
+ sprintf (buffer, "Bad trap %lx at tl>0", lvl);
+@@ -1141,7 +1152,7 @@ static void cheetah_log_errors(struct pt
+ regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate);
+ printk("%s" "ERROR(%d): ",
+ (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id());
+- printk("TPC<%pS>\n", (void *) regs->tpc);
++ printk("TPC<%pA>\n", (void *) regs->tpc);
+ printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n",
+ (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
+ (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT,
+@@ -1748,7 +1759,7 @@ void cheetah_plus_parity_error(int type,
+ smp_processor_id(),
+ (type & 0x1) ? 'I' : 'D',
+ regs->tpc);
+- printk(KERN_EMERG "TPC<%pS>\n", (void *) regs->tpc);
++ printk(KERN_EMERG "TPC<%pA>\n", (void *) regs->tpc);
+ panic("Irrecoverable Cheetah+ parity error.");
+ }
+
+@@ -1756,7 +1767,7 @@ void cheetah_plus_parity_error(int type,
+ smp_processor_id(),
+ (type & 0x1) ? 'I' : 'D',
+ regs->tpc);
+- printk(KERN_WARNING "TPC<%pS>\n", (void *) regs->tpc);
++ printk(KERN_WARNING "TPC<%pA>\n", (void *) regs->tpc);
+ }
+
+ struct sun4v_error_entry {
+@@ -1963,9 +1974,9 @@ void sun4v_itlb_error_report(struct pt_r
+
+ printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n",
+ regs->tpc, tl);
+- printk(KERN_EMERG "SUN4V-ITLB: TPC<%pS>\n", (void *) regs->tpc);
++ printk(KERN_EMERG "SUN4V-ITLB: TPC<%pA>\n", (void *) regs->tpc);
+ printk(KERN_EMERG "SUN4V-ITLB: O7[%lx]\n", regs->u_regs[UREG_I7]);
+- printk(KERN_EMERG "SUN4V-ITLB: O7<%pS>\n",
++ printk(KERN_EMERG "SUN4V-ITLB: O7<%pA>\n",
+ (void *) regs->u_regs[UREG_I7]);
+ printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] "
+ "pte[%lx] error[%lx]\n",
+@@ -1987,9 +1998,9 @@ void sun4v_dtlb_error_report(struct pt_r
+
+ printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n",
+ regs->tpc, tl);
+- printk(KERN_EMERG "SUN4V-DTLB: TPC<%pS>\n", (void *) regs->tpc);
++ printk(KERN_EMERG "SUN4V-DTLB: TPC<%pA>\n", (void *) regs->tpc);
+ printk(KERN_EMERG "SUN4V-DTLB: O7[%lx]\n", regs->u_regs[UREG_I7]);
+- printk(KERN_EMERG "SUN4V-DTLB: O7<%pS>\n",
++ printk(KERN_EMERG "SUN4V-DTLB: O7<%pA>\n",
+ (void *) regs->u_regs[UREG_I7]);
+ printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] "
+ "pte[%lx] error[%lx]\n",
+@@ -2195,13 +2206,13 @@ void show_stack(struct task_struct *tsk,
+ fp = (unsigned long)sf->fp + STACK_BIAS;
+ }
+
+- printk(" [%016lx] %pS\n", pc, (void *) pc);
++ printk(" [%016lx] %pA\n", pc, (void *) pc);
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ if ((pc + 8UL) == (unsigned long) &return_to_handler) {
+ int index = tsk->curr_ret_stack;
+ if (tsk->ret_stack && index >= graph) {
+ pc = tsk->ret_stack[index - graph].ret;
+- printk(" [%016lx] %pS\n", pc, (void *) pc);
++ printk(" [%016lx] %pA\n", pc, (void *) pc);
+ graph++;
+ }
+ }
+@@ -2254,7 +2265,7 @@ void die_if_kernel(char *str, struct pt_
+ while (rw &&
+ count++ < 30 &&
+ kstack_valid(tp, (unsigned long) rw)) {
+- printk("Caller[%016lx]: %pS\n", rw->ins[7],
++ printk("Caller[%016lx]: %pA\n", rw->ins[7],
+ (void *) rw->ins[7]);
+
+ rw = kernel_stack_up(rw);
+diff -urNp linux-2.6.38.7/arch/sparc/kernel/unaligned_64.c linux-2.6.38.7/arch/sparc/kernel/unaligned_64.c
+--- linux-2.6.38.7/arch/sparc/kernel/unaligned_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/kernel/unaligned_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -278,7 +278,7 @@ static void log_unaligned(struct pt_regs
+ static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
+
+ if (__ratelimit(&ratelimit)) {
+- printk("Kernel unaligned access at TPC[%lx] %pS\n",
++ printk("Kernel unaligned access at TPC[%lx] %pA\n",
+ regs->tpc, (void *) regs->tpc);
+ }
+ }
+diff -urNp linux-2.6.38.7/arch/sparc/lib/atomic_64.S linux-2.6.38.7/arch/sparc/lib/atomic_64.S
+--- linux-2.6.38.7/arch/sparc/lib/atomic_64.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/lib/atomic_64.S 2011-04-28 19:34:14.000000000 -0400
+@@ -18,7 +18,12 @@
+ atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
+ 1: lduw [%o1], %g1
+- add %g1, %o0, %g7
++ addcc %g1, %o0, %g7
++
++#ifdef CONFIG_PAX_REFCOUNT
++ tvs %icc, 6
++#endif
++
+ cas [%o1], %g1, %g7
+ cmp %g1, %g7
+ bne,pn %icc, BACKOFF_LABEL(2f, 1b)
+@@ -28,12 +33,32 @@ atomic_add: /* %o0 = increment, %o1 = at
+ 2: BACKOFF_SPIN(%o2, %o3, 1b)
+ .size atomic_add, .-atomic_add
+
++ .globl atomic_add_unchecked
++ .type atomic_add_unchecked,#function
++atomic_add_unchecked: /* %o0 = increment, %o1 = atomic_ptr */
++ BACKOFF_SETUP(%o2)
++1: lduw [%o1], %g1
++ add %g1, %o0, %g7
++ cas [%o1], %g1, %g7
++ cmp %g1, %g7
++ bne,pn %icc, 2f
++ nop
++ retl
++ nop
++2: BACKOFF_SPIN(%o2, %o3, 1b)
++ .size atomic_add_unchecked, .-atomic_add_unchecked
++
+ .globl atomic_sub
+ .type atomic_sub,#function
+ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
+ 1: lduw [%o1], %g1
+- sub %g1, %o0, %g7
++ subcc %g1, %o0, %g7
++
++#ifdef CONFIG_PAX_REFCOUNT
++ tvs %icc, 6
++#endif
++
+ cas [%o1], %g1, %g7
+ cmp %g1, %g7
+ bne,pn %icc, BACKOFF_LABEL(2f, 1b)
+@@ -43,12 +68,32 @@ atomic_sub: /* %o0 = decrement, %o1 = at
+ 2: BACKOFF_SPIN(%o2, %o3, 1b)
+ .size atomic_sub, .-atomic_sub
+
++ .globl atomic_sub_unchecked
++ .type atomic_sub_unchecked,#function
++atomic_sub_unchecked: /* %o0 = decrement, %o1 = atomic_ptr */
++ BACKOFF_SETUP(%o2)
++1: lduw [%o1], %g1
++ sub %g1, %o0, %g7
++ cas [%o1], %g1, %g7
++ cmp %g1, %g7
++ bne,pn %icc, 2f
++ nop
++ retl
++ nop
++2: BACKOFF_SPIN(%o2, %o3, 1b)
++ .size atomic_sub_unchecked, .-atomic_sub_unchecked
++
+ .globl atomic_add_ret
+ .type atomic_add_ret,#function
+ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
+ 1: lduw [%o1], %g1
+- add %g1, %o0, %g7
++ addcc %g1, %o0, %g7
++
++#ifdef CONFIG_PAX_REFCOUNT
++ tvs %icc, 6
++#endif
++
+ cas [%o1], %g1, %g7
+ cmp %g1, %g7
+ bne,pn %icc, BACKOFF_LABEL(2f, 1b)
+@@ -58,12 +103,33 @@ atomic_add_ret: /* %o0 = increment, %o1
+ 2: BACKOFF_SPIN(%o2, %o3, 1b)
+ .size atomic_add_ret, .-atomic_add_ret
+
++ .globl atomic_add_ret_unchecked
++ .type atomic_add_ret_unchecked,#function
++atomic_add_ret_unchecked: /* %o0 = increment, %o1 = atomic_ptr */
++ BACKOFF_SETUP(%o2)
++1: lduw [%o1], %g1
++ addcc %g1, %o0, %g7
++ cas [%o1], %g1, %g7
++ cmp %g1, %g7
++ bne,pn %icc, 2f
++ add %g7, %o0, %g7
++ sra %g7, 0, %o0
++ retl
++ nop
++2: BACKOFF_SPIN(%o2, %o3, 1b)
++ .size atomic_add_ret_unchecked, .-atomic_add_ret_unchecked
++
+ .globl atomic_sub_ret
+ .type atomic_sub_ret,#function
+ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
+ 1: lduw [%o1], %g1
+- sub %g1, %o0, %g7
++ subcc %g1, %o0, %g7
++
++#ifdef CONFIG_PAX_REFCOUNT
++ tvs %icc, 6
++#endif
++
+ cas [%o1], %g1, %g7
+ cmp %g1, %g7
+ bne,pn %icc, BACKOFF_LABEL(2f, 1b)
+@@ -78,7 +144,12 @@ atomic_sub_ret: /* %o0 = decrement, %o1
+ atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
+ 1: ldx [%o1], %g1
+- add %g1, %o0, %g7
++ addcc %g1, %o0, %g7
++
++#ifdef CONFIG_PAX_REFCOUNT
++ tvs %xcc, 6
++#endif
++
+ casx [%o1], %g1, %g7
+ cmp %g1, %g7
+ bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
+@@ -88,12 +159,32 @@ atomic64_add: /* %o0 = increment, %o1 =
+ 2: BACKOFF_SPIN(%o2, %o3, 1b)
+ .size atomic64_add, .-atomic64_add
+
++ .globl atomic64_add_unchecked
++ .type atomic64_add_unchecked,#function
++atomic64_add_unchecked: /* %o0 = increment, %o1 = atomic_ptr */
++ BACKOFF_SETUP(%o2)
++1: ldx [%o1], %g1
++ addcc %g1, %o0, %g7
++ casx [%o1], %g1, %g7
++ cmp %g1, %g7
++ bne,pn %xcc, 2f
++ nop
++ retl
++ nop
++2: BACKOFF_SPIN(%o2, %o3, 1b)
++ .size atomic64_add_unchecked, .-atomic64_add_unchecked
++
+ .globl atomic64_sub
+ .type atomic64_sub,#function
+ atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
+ 1: ldx [%o1], %g1
+- sub %g1, %o0, %g7
++ subcc %g1, %o0, %g7
++
++#ifdef CONFIG_PAX_REFCOUNT
++ tvs %xcc, 6
++#endif
++
+ casx [%o1], %g1, %g7
+ cmp %g1, %g7
+ bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
+@@ -103,12 +194,32 @@ atomic64_sub: /* %o0 = decrement, %o1 =
+ 2: BACKOFF_SPIN(%o2, %o3, 1b)
+ .size atomic64_sub, .-atomic64_sub
+
++ .globl atomic64_sub_unchecked
++ .type atomic64_sub_unchecked,#function
++atomic64_sub_unchecked: /* %o0 = decrement, %o1 = atomic_ptr */
++ BACKOFF_SETUP(%o2)
++1: ldx [%o1], %g1
++ subcc %g1, %o0, %g7
++ casx [%o1], %g1, %g7
++ cmp %g1, %g7
++ bne,pn %xcc, 2f
++ nop
++ retl
++ nop
++2: BACKOFF_SPIN(%o2, %o3, 1b)
++ .size atomic64_sub_unchecked, .-atomic64_sub_unchecked
++
+ .globl atomic64_add_ret
+ .type atomic64_add_ret,#function
+ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
+ 1: ldx [%o1], %g1
+- add %g1, %o0, %g7
++ addcc %g1, %o0, %g7
++
++#ifdef CONFIG_PAX_REFCOUNT
++ tvs %xcc, 6
++#endif
++
+ casx [%o1], %g1, %g7
+ cmp %g1, %g7
+ bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
+@@ -118,12 +229,33 @@ atomic64_add_ret: /* %o0 = increment, %o
+ 2: BACKOFF_SPIN(%o2, %o3, 1b)
+ .size atomic64_add_ret, .-atomic64_add_ret
+
++ .globl atomic64_add_ret_unchecked
++ .type atomic64_add_ret_unchecked,#function
++atomic64_add_ret_unchecked: /* %o0 = increment, %o1 = atomic_ptr */
++ BACKOFF_SETUP(%o2)
++1: ldx [%o1], %g1
++ addcc %g1, %o0, %g7
++ casx [%o1], %g1, %g7
++ cmp %g1, %g7
++ bne,pn %xcc, 2f
++ add %g7, %o0, %g7
++ mov %g7, %o0
++ retl
++ nop
++2: BACKOFF_SPIN(%o2, %o3, 1b)
++ .size atomic64_add_ret_unchecked, .-atomic64_add_ret_unchecked
++
+ .globl atomic64_sub_ret
+ .type atomic64_sub_ret,#function
+ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
+ BACKOFF_SETUP(%o2)
+ 1: ldx [%o1], %g1
+- sub %g1, %o0, %g7
++ subcc %g1, %o0, %g7
++
++#ifdef CONFIG_PAX_REFCOUNT
++ tvs %xcc, 6
++#endif
++
+ casx [%o1], %g1, %g7
+ cmp %g1, %g7
+ bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
+diff -urNp linux-2.6.38.7/arch/sparc/lib/ksyms.c linux-2.6.38.7/arch/sparc/lib/ksyms.c
+--- linux-2.6.38.7/arch/sparc/lib/ksyms.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/lib/ksyms.c 2011-04-28 19:34:14.000000000 -0400
+@@ -142,12 +142,17 @@ EXPORT_SYMBOL(__downgrade_write);
+
+ /* Atomic counter implementation. */
+ EXPORT_SYMBOL(atomic_add);
++EXPORT_SYMBOL(atomic_add_unchecked);
+ EXPORT_SYMBOL(atomic_add_ret);
+ EXPORT_SYMBOL(atomic_sub);
++EXPORT_SYMBOL(atomic_sub_unchecked);
+ EXPORT_SYMBOL(atomic_sub_ret);
+ EXPORT_SYMBOL(atomic64_add);
++EXPORT_SYMBOL(atomic64_add_unchecked);
+ EXPORT_SYMBOL(atomic64_add_ret);
++EXPORT_SYMBOL(atomic64_add_ret_unchecked);
+ EXPORT_SYMBOL(atomic64_sub);
++EXPORT_SYMBOL(atomic64_sub_unchecked);
+ EXPORT_SYMBOL(atomic64_sub_ret);
+
+ /* Atomic bit operations. */
+diff -urNp linux-2.6.38.7/arch/sparc/lib/Makefile linux-2.6.38.7/arch/sparc/lib/Makefile
+--- linux-2.6.38.7/arch/sparc/lib/Makefile 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/lib/Makefile 2011-05-17 19:31:43.000000000 -0400
+@@ -2,7 +2,7 @@
+ #
+
+ asflags-y := -ansi -DST_DIV0=0x02
+-ccflags-y := -Werror
++#ccflags-y := -Werror
+
+ lib-$(CONFIG_SPARC32) += mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o
+ lib-$(CONFIG_SPARC32) += memcpy.o memset.o
+diff -urNp linux-2.6.38.7/arch/sparc/Makefile linux-2.6.38.7/arch/sparc/Makefile
+--- linux-2.6.38.7/arch/sparc/Makefile 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/Makefile 2011-04-28 19:34:14.000000000 -0400
+@@ -75,7 +75,7 @@ drivers-$(CONFIG_OPROFILE) += arch/sparc
+ # Export what is needed by arch/sparc/boot/Makefile
+ export VMLINUX_INIT VMLINUX_MAIN
+ VMLINUX_INIT := $(head-y) $(init-y)
+-VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/
++VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
+ VMLINUX_MAIN += $(patsubst %/, %/lib.a, $(libs-y)) $(libs-y)
+ VMLINUX_MAIN += $(drivers-y) $(net-y)
+
+diff -urNp linux-2.6.38.7/arch/sparc/mm/fault_32.c linux-2.6.38.7/arch/sparc/mm/fault_32.c
+--- linux-2.6.38.7/arch/sparc/mm/fault_32.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/mm/fault_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -22,6 +22,9 @@
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
+ #include <linux/kdebug.h>
++#include <linux/slab.h>
++#include <linux/pagemap.h>
++#include <linux/compiler.h>
+
+ #include <asm/system.h>
+ #include <asm/page.h>
+@@ -209,6 +212,268 @@ static unsigned long compute_si_addr(str
+ return safe_compute_effective_address(regs, insn);
+ }
+
++#ifdef CONFIG_PAX_PAGEEXEC
++#ifdef CONFIG_PAX_DLRESOLVE
++static void pax_emuplt_close(struct vm_area_struct *vma)
++{
++ vma->vm_mm->call_dl_resolve = 0UL;
++}
++
++static int pax_emuplt_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ unsigned int *kaddr;
++
++ vmf->page = alloc_page(GFP_HIGHUSER);
++ if (!vmf->page)
++ return VM_FAULT_OOM;
++
++ kaddr = kmap(vmf->page);
++ memset(kaddr, 0, PAGE_SIZE);
++ kaddr[0] = 0x9DE3BFA8U; /* save */
++ flush_dcache_page(vmf->page);
++ kunmap(vmf->page);
++ return VM_FAULT_MAJOR;
++}
++
++static const struct vm_operations_struct pax_vm_ops = {
++ .close = pax_emuplt_close,
++ .fault = pax_emuplt_fault
++};
++
++static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
++{
++ int ret;
++
++ INIT_LIST_HEAD(&vma->anon_vma_chain);
++ vma->vm_mm = current->mm;
++ vma->vm_start = addr;
++ vma->vm_end = addr + PAGE_SIZE;
++ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
++ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
++ vma->vm_ops = &pax_vm_ops;
++
++ ret = insert_vm_struct(current->mm, vma);
++ if (ret)
++ return ret;
++
++ ++current->mm->total_vm;
++ return 0;
++}
++#endif
++
++/*
++ * PaX: decide what to do with offenders (regs->pc = fault address)
++ *
++ * returns 1 when task should be killed
++ * 2 when patched PLT trampoline was detected
++ * 3 when unpatched PLT trampoline was detected
++ */
++static int pax_handle_fetch_fault(struct pt_regs *regs)
++{
++
++#ifdef CONFIG_PAX_EMUPLT
++ int err;
++
++ do { /* PaX: patched PLT emulation #1 */
++ unsigned int sethi1, sethi2, jmpl;
++
++ err = get_user(sethi1, (unsigned int *)regs->pc);
++ err |= get_user(sethi2, (unsigned int *)(regs->pc+4));
++ err |= get_user(jmpl, (unsigned int *)(regs->pc+8));
++
++ if (err)
++ break;
++
++ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
++ (sethi2 & 0xFFC00000U) == 0x03000000U &&
++ (jmpl & 0xFFFFE000U) == 0x81C06000U)
++ {
++ unsigned int addr;
++
++ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
++ addr = regs->u_regs[UREG_G1];
++ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
++ regs->pc = addr;
++ regs->npc = addr+4;
++ return 2;
++ }
++ } while (0);
++
++ { /* PaX: patched PLT emulation #2 */
++ unsigned int ba;
++
++ err = get_user(ba, (unsigned int *)regs->pc);
++
++ if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
++ unsigned int addr;
++
++ addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
++ regs->pc = addr;
++ regs->npc = addr+4;
++ return 2;
++ }
++ }
++
++ do { /* PaX: patched PLT emulation #3 */
++ unsigned int sethi, jmpl, nop;
++
++ err = get_user(sethi, (unsigned int *)regs->pc);
++ err |= get_user(jmpl, (unsigned int *)(regs->pc+4));
++ err |= get_user(nop, (unsigned int *)(regs->pc+8));
++
++ if (err)
++ break;
++
++ if ((sethi & 0xFFC00000U) == 0x03000000U &&
++ (jmpl & 0xFFFFE000U) == 0x81C06000U &&
++ nop == 0x01000000U)
++ {
++ unsigned int addr;
++
++ addr = (sethi & 0x003FFFFFU) << 10;
++ regs->u_regs[UREG_G1] = addr;
++ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
++ regs->pc = addr;
++ regs->npc = addr+4;
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: unpatched PLT emulation step 1 */
++ unsigned int sethi, ba, nop;
++
++ err = get_user(sethi, (unsigned int *)regs->pc);
++ err |= get_user(ba, (unsigned int *)(regs->pc+4));
++ err |= get_user(nop, (unsigned int *)(regs->pc+8));
++
++ if (err)
++ break;
++
++ if ((sethi & 0xFFC00000U) == 0x03000000U &&
++ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
++ nop == 0x01000000U)
++ {
++ unsigned int addr, save, call;
++
++ if ((ba & 0xFFC00000U) == 0x30800000U)
++ addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
++ else
++ addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2);
++
++ err = get_user(save, (unsigned int *)addr);
++ err |= get_user(call, (unsigned int *)(addr+4));
++ err |= get_user(nop, (unsigned int *)(addr+8));
++ if (err)
++ break;
++
++#ifdef CONFIG_PAX_DLRESOLVE
++ if (save == 0x9DE3BFA8U &&
++ (call & 0xC0000000U) == 0x40000000U &&
++ nop == 0x01000000U)
++ {
++ struct vm_area_struct *vma;
++ unsigned long call_dl_resolve;
++
++ down_read(&current->mm->mmap_sem);
++ call_dl_resolve = current->mm->call_dl_resolve;
++ up_read(&current->mm->mmap_sem);
++ if (likely(call_dl_resolve))
++ goto emulate;
++
++ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
++
++ down_write(&current->mm->mmap_sem);
++ if (current->mm->call_dl_resolve) {
++ call_dl_resolve = current->mm->call_dl_resolve;
++ up_write(&current->mm->mmap_sem);
++ if (vma)
++ kmem_cache_free(vm_area_cachep, vma);
++ goto emulate;
++ }
++
++ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
++ if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
++ up_write(&current->mm->mmap_sem);
++ if (vma)
++ kmem_cache_free(vm_area_cachep, vma);
++ return 1;
++ }
++
++ if (pax_insert_vma(vma, call_dl_resolve)) {
++ up_write(&current->mm->mmap_sem);
++ kmem_cache_free(vm_area_cachep, vma);
++ return 1;
++ }
++
++ current->mm->call_dl_resolve = call_dl_resolve;
++ up_write(&current->mm->mmap_sem);
++
++emulate:
++ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
++ regs->pc = call_dl_resolve;
++ regs->npc = addr+4;
++ return 3;
++ }
++#endif
++
++ /* PaX: glibc 2.4+ generates sethi/jmpl instead of save/call */
++ if ((save & 0xFFC00000U) == 0x05000000U &&
++ (call & 0xFFFFE000U) == 0x85C0A000U &&
++ nop == 0x01000000U)
++ {
++ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
++ regs->u_regs[UREG_G2] = addr + 4;
++ addr = (save & 0x003FFFFFU) << 10;
++ addr += (((call | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
++ regs->pc = addr;
++ regs->npc = addr+4;
++ return 3;
++ }
++ }
++ } while (0);
++
++ do { /* PaX: unpatched PLT emulation step 2 */
++ unsigned int save, call, nop;
++
++ err = get_user(save, (unsigned int *)(regs->pc-4));
++ err |= get_user(call, (unsigned int *)regs->pc);
++ err |= get_user(nop, (unsigned int *)(regs->pc+4));
++ if (err)
++ break;
++
++ if (save == 0x9DE3BFA8U &&
++ (call & 0xC0000000U) == 0x40000000U &&
++ nop == 0x01000000U)
++ {
++ unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2);
++
++ regs->u_regs[UREG_RETPC] = regs->pc;
++ regs->pc = dl_resolve;
++ regs->npc = dl_resolve+4;
++ return 3;
++ }
++ } while (0);
++#endif
++
++ return 1;
++}
++
++void pax_report_insns(void *pc, void *sp)
++{
++ unsigned long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 8; i++) {
++ unsigned int c;
++ if (get_user(c, (unsigned int *)pc+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%08x ", c);
++ }
++ printk("\n");
++}
++#endif
++
+ static noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
+ int text_fault)
+ {
+@@ -281,6 +546,24 @@ good_area:
+ if(!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else {
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & VM_EXEC)) {
++ up_read(&mm->mmap_sem);
++ switch (pax_handle_fetch_fault(regs)) {
++
++#ifdef CONFIG_PAX_EMUPLT
++ case 2:
++ case 3:
++ return;
++#endif
++
++ }
++ pax_report_fault(regs, (void *)regs->pc, (void *)regs->u_regs[UREG_FP]);
++ do_group_exit(SIGKILL);
++ }
++#endif
++
+ /* Allow reads even for write-only mappings */
+ if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+diff -urNp linux-2.6.38.7/arch/sparc/mm/fault_64.c linux-2.6.38.7/arch/sparc/mm/fault_64.c
+--- linux-2.6.38.7/arch/sparc/mm/fault_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/mm/fault_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -21,6 +21,9 @@
+ #include <linux/kprobes.h>
+ #include <linux/kdebug.h>
+ #include <linux/percpu.h>
++#include <linux/slab.h>
++#include <linux/pagemap.h>
++#include <linux/compiler.h>
+
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+@@ -74,7 +77,7 @@ static void __kprobes bad_kernel_pc(stru
+ printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n",
+ regs->tpc);
+ printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]);
+- printk("OOPS: RPC <%pS>\n", (void *) regs->u_regs[15]);
++ printk("OOPS: RPC <%pA>\n", (void *) regs->u_regs[15]);
+ printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr);
+ dump_stack();
+ unhandled_fault(regs->tpc, current, regs);
+@@ -272,6 +275,457 @@ static void noinline __kprobes bogus_32b
+ show_regs(regs);
+ }
+
++#ifdef CONFIG_PAX_PAGEEXEC
++#ifdef CONFIG_PAX_DLRESOLVE
++static void pax_emuplt_close(struct vm_area_struct *vma)
++{
++ vma->vm_mm->call_dl_resolve = 0UL;
++}
++
++static int pax_emuplt_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ unsigned int *kaddr;
++
++ vmf->page = alloc_page(GFP_HIGHUSER);
++ if (!vmf->page)
++ return VM_FAULT_OOM;
++
++ kaddr = kmap(vmf->page);
++ memset(kaddr, 0, PAGE_SIZE);
++ kaddr[0] = 0x9DE3BFA8U; /* save */
++ flush_dcache_page(vmf->page);
++ kunmap(vmf->page);
++ return VM_FAULT_MAJOR;
++}
++
++static const struct vm_operations_struct pax_vm_ops = {
++ .close = pax_emuplt_close,
++ .fault = pax_emuplt_fault
++};
++
++static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
++{
++ int ret;
++
++ INIT_LIST_HEAD(&vma->anon_vma_chain);
++ vma->vm_mm = current->mm;
++ vma->vm_start = addr;
++ vma->vm_end = addr + PAGE_SIZE;
++ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
++ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
++ vma->vm_ops = &pax_vm_ops;
++
++ ret = insert_vm_struct(current->mm, vma);
++ if (ret)
++ return ret;
++
++ ++current->mm->total_vm;
++ return 0;
++}
++#endif
++
++/*
++ * PaX: decide what to do with offenders (regs->tpc = fault address)
++ *
++ * returns 1 when task should be killed
++ * 2 when patched PLT trampoline was detected
++ * 3 when unpatched PLT trampoline was detected
++ */
++static int pax_handle_fetch_fault(struct pt_regs *regs)
++{
++
++#ifdef CONFIG_PAX_EMUPLT
++ int err;
++
++ do { /* PaX: patched PLT emulation #1 */
++ unsigned int sethi1, sethi2, jmpl;
++
++ err = get_user(sethi1, (unsigned int *)regs->tpc);
++ err |= get_user(sethi2, (unsigned int *)(regs->tpc+4));
++ err |= get_user(jmpl, (unsigned int *)(regs->tpc+8));
++
++ if (err)
++ break;
++
++ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
++ (sethi2 & 0xFFC00000U) == 0x03000000U &&
++ (jmpl & 0xFFFFE000U) == 0x81C06000U)
++ {
++ unsigned long addr;
++
++ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
++ addr = regs->u_regs[UREG_G1];
++ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
++
++ if (test_thread_flag(TIF_32BIT))
++ addr &= 0xFFFFFFFFUL;
++
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 2;
++ }
++ } while (0);
++
++ { /* PaX: patched PLT emulation #2 */
++ unsigned int ba;
++
++ err = get_user(ba, (unsigned int *)regs->tpc);
++
++ if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
++ unsigned long addr;
++
++ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
++
++ if (test_thread_flag(TIF_32BIT))
++ addr &= 0xFFFFFFFFUL;
++
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 2;
++ }
++ }
++
++ do { /* PaX: patched PLT emulation #3 */
++ unsigned int sethi, jmpl, nop;
++
++ err = get_user(sethi, (unsigned int *)regs->tpc);
++ err |= get_user(jmpl, (unsigned int *)(regs->tpc+4));
++ err |= get_user(nop, (unsigned int *)(regs->tpc+8));
++
++ if (err)
++ break;
++
++ if ((sethi & 0xFFC00000U) == 0x03000000U &&
++ (jmpl & 0xFFFFE000U) == 0x81C06000U &&
++ nop == 0x01000000U)
++ {
++ unsigned long addr;
++
++ addr = (sethi & 0x003FFFFFU) << 10;
++ regs->u_regs[UREG_G1] = addr;
++ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
++
++ if (test_thread_flag(TIF_32BIT))
++ addr &= 0xFFFFFFFFUL;
++
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: patched PLT emulation #4 */
++ unsigned int sethi, mov1, call, mov2;
++
++ err = get_user(sethi, (unsigned int *)regs->tpc);
++ err |= get_user(mov1, (unsigned int *)(regs->tpc+4));
++ err |= get_user(call, (unsigned int *)(regs->tpc+8));
++ err |= get_user(mov2, (unsigned int *)(regs->tpc+12));
++
++ if (err)
++ break;
++
++ if ((sethi & 0xFFC00000U) == 0x03000000U &&
++ mov1 == 0x8210000FU &&
++ (call & 0xC0000000U) == 0x40000000U &&
++ mov2 == 0x9E100001U)
++ {
++ unsigned long addr;
++
++ regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC];
++ addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
++
++ if (test_thread_flag(TIF_32BIT))
++ addr &= 0xFFFFFFFFUL;
++
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: patched PLT emulation #5 */
++ unsigned int sethi, sethi1, sethi2, or1, or2, sllx, jmpl, nop;
++
++ err = get_user(sethi, (unsigned int *)regs->tpc);
++ err |= get_user(sethi1, (unsigned int *)(regs->tpc+4));
++ err |= get_user(sethi2, (unsigned int *)(regs->tpc+8));
++ err |= get_user(or1, (unsigned int *)(regs->tpc+12));
++ err |= get_user(or2, (unsigned int *)(regs->tpc+16));
++ err |= get_user(sllx, (unsigned int *)(regs->tpc+20));
++ err |= get_user(jmpl, (unsigned int *)(regs->tpc+24));
++ err |= get_user(nop, (unsigned int *)(regs->tpc+28));
++
++ if (err)
++ break;
++
++ if ((sethi & 0xFFC00000U) == 0x03000000U &&
++ (sethi1 & 0xFFC00000U) == 0x03000000U &&
++ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
++ (or1 & 0xFFFFE000U) == 0x82106000U &&
++ (or2 & 0xFFFFE000U) == 0x8A116000U &&
++ sllx == 0x83287020U &&
++ jmpl == 0x81C04005U &&
++ nop == 0x01000000U)
++ {
++ unsigned long addr;
++
++ regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU);
++ regs->u_regs[UREG_G1] <<= 32;
++ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU);
++ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: patched PLT emulation #6 */
++ unsigned int sethi, sethi1, sethi2, sllx, or, jmpl, nop;
++
++ err = get_user(sethi, (unsigned int *)regs->tpc);
++ err |= get_user(sethi1, (unsigned int *)(regs->tpc+4));
++ err |= get_user(sethi2, (unsigned int *)(regs->tpc+8));
++ err |= get_user(sllx, (unsigned int *)(regs->tpc+12));
++ err |= get_user(or, (unsigned int *)(regs->tpc+16));
++ err |= get_user(jmpl, (unsigned int *)(regs->tpc+20));
++ err |= get_user(nop, (unsigned int *)(regs->tpc+24));
++
++ if (err)
++ break;
++
++ if ((sethi & 0xFFC00000U) == 0x03000000U &&
++ (sethi1 & 0xFFC00000U) == 0x03000000U &&
++ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
++ sllx == 0x83287020U &&
++ (or & 0xFFFFE000U) == 0x8A116000U &&
++ jmpl == 0x81C04005U &&
++ nop == 0x01000000U)
++ {
++ unsigned long addr;
++
++ regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10;
++ regs->u_regs[UREG_G1] <<= 32;
++ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU);
++ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: unpatched PLT emulation step 1 */
++ unsigned int sethi, ba, nop;
++
++ err = get_user(sethi, (unsigned int *)regs->tpc);
++ err |= get_user(ba, (unsigned int *)(regs->tpc+4));
++ err |= get_user(nop, (unsigned int *)(regs->tpc+8));
++
++ if (err)
++ break;
++
++ if ((sethi & 0xFFC00000U) == 0x03000000U &&
++ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
++ nop == 0x01000000U)
++ {
++ unsigned long addr;
++ unsigned int save, call;
++ unsigned int sethi1, sethi2, or1, or2, sllx, add, jmpl;
++
++ if ((ba & 0xFFC00000U) == 0x30800000U)
++ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
++ else
++ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
++
++ if (test_thread_flag(TIF_32BIT))
++ addr &= 0xFFFFFFFFUL;
++
++ err = get_user(save, (unsigned int *)addr);
++ err |= get_user(call, (unsigned int *)(addr+4));
++ err |= get_user(nop, (unsigned int *)(addr+8));
++ if (err)
++ break;
++
++#ifdef CONFIG_PAX_DLRESOLVE
++ if (save == 0x9DE3BFA8U &&
++ (call & 0xC0000000U) == 0x40000000U &&
++ nop == 0x01000000U)
++ {
++ struct vm_area_struct *vma;
++ unsigned long call_dl_resolve;
++
++ down_read(&current->mm->mmap_sem);
++ call_dl_resolve = current->mm->call_dl_resolve;
++ up_read(&current->mm->mmap_sem);
++ if (likely(call_dl_resolve))
++ goto emulate;
++
++ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
++
++ down_write(&current->mm->mmap_sem);
++ if (current->mm->call_dl_resolve) {
++ call_dl_resolve = current->mm->call_dl_resolve;
++ up_write(&current->mm->mmap_sem);
++ if (vma)
++ kmem_cache_free(vm_area_cachep, vma);
++ goto emulate;
++ }
++
++ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
++ if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
++ up_write(&current->mm->mmap_sem);
++ if (vma)
++ kmem_cache_free(vm_area_cachep, vma);
++ return 1;
++ }
++
++ if (pax_insert_vma(vma, call_dl_resolve)) {
++ up_write(&current->mm->mmap_sem);
++ kmem_cache_free(vm_area_cachep, vma);
++ return 1;
++ }
++
++ current->mm->call_dl_resolve = call_dl_resolve;
++ up_write(&current->mm->mmap_sem);
++
++emulate:
++ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
++ regs->tpc = call_dl_resolve;
++ regs->tnpc = addr+4;
++ return 3;
++ }
++#endif
++
++ /* PaX: glibc 2.4+ generates sethi/jmpl instead of save/call */
++ if ((save & 0xFFC00000U) == 0x05000000U &&
++ (call & 0xFFFFE000U) == 0x85C0A000U &&
++ nop == 0x01000000U)
++ {
++ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
++ regs->u_regs[UREG_G2] = addr + 4;
++ addr = (save & 0x003FFFFFU) << 10;
++ addr += (((call | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
++
++ if (test_thread_flag(TIF_32BIT))
++ addr &= 0xFFFFFFFFUL;
++
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 3;
++ }
++
++ /* PaX: 64-bit PLT stub */
++ err = get_user(sethi1, (unsigned int *)addr);
++ err |= get_user(sethi2, (unsigned int *)(addr+4));
++ err |= get_user(or1, (unsigned int *)(addr+8));
++ err |= get_user(or2, (unsigned int *)(addr+12));
++ err |= get_user(sllx, (unsigned int *)(addr+16));
++ err |= get_user(add, (unsigned int *)(addr+20));
++ err |= get_user(jmpl, (unsigned int *)(addr+24));
++ err |= get_user(nop, (unsigned int *)(addr+28));
++ if (err)
++ break;
++
++ if ((sethi1 & 0xFFC00000U) == 0x09000000U &&
++ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
++ (or1 & 0xFFFFE000U) == 0x88112000U &&
++ (or2 & 0xFFFFE000U) == 0x8A116000U &&
++ sllx == 0x89293020U &&
++ add == 0x8A010005U &&
++ jmpl == 0x89C14000U &&
++ nop == 0x01000000U)
++ {
++ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
++ regs->u_regs[UREG_G4] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU);
++ regs->u_regs[UREG_G4] <<= 32;
++ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU);
++ regs->u_regs[UREG_G5] += regs->u_regs[UREG_G4];
++ regs->u_regs[UREG_G4] = addr + 24;
++ addr = regs->u_regs[UREG_G5];
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 3;
++ }
++ }
++ } while (0);
++
++#ifdef CONFIG_PAX_DLRESOLVE
++ do { /* PaX: unpatched PLT emulation step 2 */
++ unsigned int save, call, nop;
++
++ err = get_user(save, (unsigned int *)(regs->tpc-4));
++ err |= get_user(call, (unsigned int *)regs->tpc);
++ err |= get_user(nop, (unsigned int *)(regs->tpc+4));
++ if (err)
++ break;
++
++ if (save == 0x9DE3BFA8U &&
++ (call & 0xC0000000U) == 0x40000000U &&
++ nop == 0x01000000U)
++ {
++ unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
++
++ if (test_thread_flag(TIF_32BIT))
++ dl_resolve &= 0xFFFFFFFFUL;
++
++ regs->u_regs[UREG_RETPC] = regs->tpc;
++ regs->tpc = dl_resolve;
++ regs->tnpc = dl_resolve+4;
++ return 3;
++ }
++ } while (0);
++#endif
++
++ do { /* PaX: patched PLT emulation #7, must be AFTER the unpatched PLT emulation */
++ unsigned int sethi, ba, nop;
++
++ err = get_user(sethi, (unsigned int *)regs->tpc);
++ err |= get_user(ba, (unsigned int *)(regs->tpc+4));
++ err |= get_user(nop, (unsigned int *)(regs->tpc+8));
++
++ if (err)
++ break;
++
++ if ((sethi & 0xFFC00000U) == 0x03000000U &&
++ (ba & 0xFFF00000U) == 0x30600000U &&
++ nop == 0x01000000U)
++ {
++ unsigned long addr;
++
++ addr = (sethi & 0x003FFFFFU) << 10;
++ regs->u_regs[UREG_G1] = addr;
++ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
++
++ if (test_thread_flag(TIF_32BIT))
++ addr &= 0xFFFFFFFFUL;
++
++ regs->tpc = addr;
++ regs->tnpc = addr+4;
++ return 2;
++ }
++ } while (0);
++
++#endif
++
++ return 1;
++}
++
++void pax_report_insns(void *pc, void *sp)
++{
++ unsigned long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 8; i++) {
++ unsigned int c;
++ if (get_user(c, (unsigned int *)pc+i))
++ printk(KERN_CONT "???????? ");
++ else
++ printk(KERN_CONT "%08x ", c);
++ }
++ printk("\n");
++}
++#endif
++
+ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
+ {
+ struct mm_struct *mm = current->mm;
+@@ -340,6 +794,29 @@ asmlinkage void __kprobes do_sparc64_fau
+ if (!vma)
+ goto bad_area;
+
++#ifdef CONFIG_PAX_PAGEEXEC
++ /* PaX: detect ITLB misses on non-exec pages */
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && vma->vm_start <= address &&
++ !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB))
++ {
++ if (address != regs->tpc)
++ goto good_area;
++
++ up_read(&mm->mmap_sem);
++ switch (pax_handle_fetch_fault(regs)) {
++
++#ifdef CONFIG_PAX_EMUPLT
++ case 2:
++ case 3:
++ return;
++#endif
++
++ }
++ pax_report_fault(regs, (void *)regs->tpc, (void *)(regs->u_regs[UREG_FP] + STACK_BIAS));
++ do_group_exit(SIGKILL);
++ }
++#endif
++
+ /* Pure DTLB misses do not tell us whether the fault causing
+ * load/store/atomic was a write or not, it only says that there
+ * was no match. So in such a case we (carefully) read the
+diff -urNp linux-2.6.38.7/arch/sparc/mm/hugetlbpage.c linux-2.6.38.7/arch/sparc/mm/hugetlbpage.c
+--- linux-2.6.38.7/arch/sparc/mm/hugetlbpage.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/mm/hugetlbpage.c 2011-04-28 19:34:14.000000000 -0400
+@@ -68,7 +68,7 @@ full_search:
+ }
+ return -ENOMEM;
+ }
+- if (likely(!vma || addr + len <= vma->vm_start)) {
++ if (likely(check_heap_stack_gap(vma, addr, len))) {
+ /*
+ * Remember the place where we stopped the search:
+ */
+@@ -107,7 +107,7 @@ hugetlb_get_unmapped_area_topdown(struct
+ /* make sure it can fit in the remaining address space */
+ if (likely(addr > len)) {
+ vma = find_vma(mm, addr-len);
+- if (!vma || addr <= vma->vm_start) {
++ if (check_heap_stack_gap(vma, addr - len, len)) {
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr-len);
+ }
+@@ -116,16 +116,17 @@ hugetlb_get_unmapped_area_topdown(struct
+ if (unlikely(mm->mmap_base < len))
+ goto bottomup;
+
+- addr = (mm->mmap_base-len) & HPAGE_MASK;
++ addr = mm->mmap_base - len;
+
+ do {
++ addr &= HPAGE_MASK;
+ /*
+ * Lookup failure means no vma is above this address,
+ * else if new region fits below vma->vm_start,
+ * return with success:
+ */
+ vma = find_vma(mm, addr);
+- if (likely(!vma || addr+len <= vma->vm_start)) {
++ if (likely(check_heap_stack_gap(vma, addr, len))) {
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr);
+ }
+@@ -135,8 +136,8 @@ hugetlb_get_unmapped_area_topdown(struct
+ mm->cached_hole_size = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+- addr = (vma->vm_start-len) & HPAGE_MASK;
+- } while (likely(len < vma->vm_start));
++ addr = skip_heap_stack_gap(vma, len);
++ } while (!IS_ERR_VALUE(addr));
+
+ bottomup:
+ /*
+@@ -182,8 +183,7 @@ hugetlb_get_unmapped_area(struct file *f
+ if (addr) {
+ addr = ALIGN(addr, HPAGE_SIZE);
+ vma = find_vma(mm, addr);
+- if (task_size - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (task_size - len >= addr && check_heap_stack_gap(vma, addr, len))
+ return addr;
+ }
+ if (mm->get_unmapped_area == arch_get_unmapped_area)
+diff -urNp linux-2.6.38.7/arch/sparc/mm/init_32.c linux-2.6.38.7/arch/sparc/mm/init_32.c
+--- linux-2.6.38.7/arch/sparc/mm/init_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/mm/init_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -318,6 +318,9 @@ extern void device_scan(void);
+ pgprot_t PAGE_SHARED __read_mostly;
+ EXPORT_SYMBOL(PAGE_SHARED);
+
++pgprot_t PAGE_SHARED_NOEXEC __read_mostly;
++EXPORT_SYMBOL(PAGE_SHARED_NOEXEC);
++
+ void __init paging_init(void)
+ {
+ switch(sparc_cpu_model) {
+@@ -346,17 +349,17 @@ void __init paging_init(void)
+
+ /* Initialize the protection map with non-constant, MMU dependent values. */
+ protection_map[0] = PAGE_NONE;
+- protection_map[1] = PAGE_READONLY;
+- protection_map[2] = PAGE_COPY;
+- protection_map[3] = PAGE_COPY;
++ protection_map[1] = PAGE_READONLY_NOEXEC;
++ protection_map[2] = PAGE_COPY_NOEXEC;
++ protection_map[3] = PAGE_COPY_NOEXEC;
+ protection_map[4] = PAGE_READONLY;
+ protection_map[5] = PAGE_READONLY;
+ protection_map[6] = PAGE_COPY;
+ protection_map[7] = PAGE_COPY;
+ protection_map[8] = PAGE_NONE;
+- protection_map[9] = PAGE_READONLY;
+- protection_map[10] = PAGE_SHARED;
+- protection_map[11] = PAGE_SHARED;
++ protection_map[9] = PAGE_READONLY_NOEXEC;
++ protection_map[10] = PAGE_SHARED_NOEXEC;
++ protection_map[11] = PAGE_SHARED_NOEXEC;
+ protection_map[12] = PAGE_READONLY;
+ protection_map[13] = PAGE_READONLY;
+ protection_map[14] = PAGE_SHARED;
+diff -urNp linux-2.6.38.7/arch/sparc/mm/Makefile linux-2.6.38.7/arch/sparc/mm/Makefile
+--- linux-2.6.38.7/arch/sparc/mm/Makefile 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/mm/Makefile 2011-04-28 19:34:14.000000000 -0400
+@@ -2,7 +2,7 @@
+ #
+
+ asflags-y := -ansi
+-ccflags-y := -Werror
++#ccflags-y := -Werror
+
+ obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o
+ obj-y += fault_$(BITS).o
+diff -urNp linux-2.6.38.7/arch/sparc/mm/srmmu.c linux-2.6.38.7/arch/sparc/mm/srmmu.c
+--- linux-2.6.38.7/arch/sparc/mm/srmmu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/sparc/mm/srmmu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -2200,6 +2200,13 @@ void __init ld_mmu_srmmu(void)
+ PAGE_SHARED = pgprot_val(SRMMU_PAGE_SHARED);
+ BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
+ BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ PAGE_SHARED_NOEXEC = pgprot_val(SRMMU_PAGE_SHARED_NOEXEC);
++ BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC));
++ BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC));
++#endif
++
+ BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
+ page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
+
+diff -urNp linux-2.6.38.7/arch/um/include/asm/kmap_types.h linux-2.6.38.7/arch/um/include/asm/kmap_types.h
+--- linux-2.6.38.7/arch/um/include/asm/kmap_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/um/include/asm/kmap_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -23,6 +23,7 @@ enum km_type {
+ KM_IRQ1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
++ KM_CLEARPAGE,
+ KM_TYPE_NR
+ };
+
+diff -urNp linux-2.6.38.7/arch/um/include/asm/page.h linux-2.6.38.7/arch/um/include/asm/page.h
+--- linux-2.6.38.7/arch/um/include/asm/page.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/um/include/asm/page.h 2011-04-28 19:34:14.000000000 -0400
+@@ -14,6 +14,9 @@
+ #define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
+ #define PAGE_MASK (~(PAGE_SIZE-1))
+
++#define ktla_ktva(addr) (addr)
++#define ktva_ktla(addr) (addr)
++
+ #ifndef __ASSEMBLY__
+
+ struct page;
+diff -urNp linux-2.6.38.7/arch/um/kernel/process.c linux-2.6.38.7/arch/um/kernel/process.c
+--- linux-2.6.38.7/arch/um/kernel/process.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/um/kernel/process.c 2011-04-28 19:34:14.000000000 -0400
+@@ -404,22 +404,6 @@ int singlestepping(void * t)
+ return 2;
+ }
+
+-/*
+- * Only x86 and x86_64 have an arch_align_stack().
+- * All other arches have "#define arch_align_stack(x) (x)"
+- * in their asm/system.h
+- * As this is included in UML from asm-um/system-generic.h,
+- * we can use it to behave as the subarch does.
+- */
+-#ifndef arch_align_stack
+-unsigned long arch_align_stack(unsigned long sp)
+-{
+- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+- sp -= get_random_int() % 8192;
+- return sp & ~0xf;
+-}
+-#endif
+-
+ unsigned long get_wchan(struct task_struct *p)
+ {
+ unsigned long stack_page, sp, ip;
+diff -urNp linux-2.6.38.7/arch/um/sys-i386/syscalls.c linux-2.6.38.7/arch/um/sys-i386/syscalls.c
+--- linux-2.6.38.7/arch/um/sys-i386/syscalls.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/um/sys-i386/syscalls.c 2011-04-28 19:34:14.000000000 -0400
+@@ -11,6 +11,21 @@
+ #include "asm/uaccess.h"
+ #include "asm/unistd.h"
+
++int i386_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
++{
++ unsigned long pax_task_size = TASK_SIZE;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
++ if (len > pax_task_size || addr > pax_task_size - len)
++ return -EINVAL;
++
++ return 0;
++}
++
+ /*
+ * The prototype on i386 is:
+ *
+diff -urNp linux-2.6.38.7/arch/x86/boot/bitops.h linux-2.6.38.7/arch/x86/boot/bitops.h
+--- linux-2.6.38.7/arch/x86/boot/bitops.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/bitops.h 2011-04-28 19:34:14.000000000 -0400
+@@ -26,7 +26,7 @@ static inline int variable_test_bit(int
+ u8 v;
+ const u32 *p = (const u32 *)addr;
+
+- asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr));
++ asm volatile("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr));
+ return v;
+ }
+
+@@ -37,7 +37,7 @@ static inline int variable_test_bit(int
+
+ static inline void set_bit(int nr, void *addr)
+ {
+- asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr));
++ asm volatile("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr));
+ }
+
+ #endif /* BOOT_BITOPS_H */
+diff -urNp linux-2.6.38.7/arch/x86/boot/boot.h linux-2.6.38.7/arch/x86/boot/boot.h
+--- linux-2.6.38.7/arch/x86/boot/boot.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/boot.h 2011-04-28 19:34:14.000000000 -0400
+@@ -85,7 +85,7 @@ static inline void io_delay(void)
+ static inline u16 ds(void)
+ {
+ u16 seg;
+- asm("movw %%ds,%0" : "=rm" (seg));
++ asm volatile("movw %%ds,%0" : "=rm" (seg));
+ return seg;
+ }
+
+@@ -181,7 +181,7 @@ static inline void wrgs32(u32 v, addr_t
+ static inline int memcmp(const void *s1, const void *s2, size_t len)
+ {
+ u8 diff;
+- asm("repe; cmpsb; setnz %0"
++ asm volatile("repe; cmpsb; setnz %0"
+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+ return diff;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/boot/compressed/head_32.S linux-2.6.38.7/arch/x86/boot/compressed/head_32.S
+--- linux-2.6.38.7/arch/x86/boot/compressed/head_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/compressed/head_32.S 2011-04-28 19:34:14.000000000 -0400
+@@ -76,7 +76,7 @@ ENTRY(startup_32)
+ notl %eax
+ andl %eax, %ebx
+ #else
+- movl $LOAD_PHYSICAL_ADDR, %ebx
++ movl $____LOAD_PHYSICAL_ADDR, %ebx
+ #endif
+
+ /* Target address to relocate to for decompression */
+@@ -162,7 +162,7 @@ relocated:
+ * and where it was actually loaded.
+ */
+ movl %ebp, %ebx
+- subl $LOAD_PHYSICAL_ADDR, %ebx
++ subl $____LOAD_PHYSICAL_ADDR, %ebx
+ jz 2f /* Nothing to be done if loaded at compiled addr. */
+ /*
+ * Process relocations.
+@@ -170,8 +170,7 @@ relocated:
+
+ 1: subl $4, %edi
+ movl (%edi), %ecx
+- testl %ecx, %ecx
+- jz 2f
++ jecxz 2f
+ addl %ebx, -__PAGE_OFFSET(%ebx, %ecx)
+ jmp 1b
+ 2:
+diff -urNp linux-2.6.38.7/arch/x86/boot/compressed/head_64.S linux-2.6.38.7/arch/x86/boot/compressed/head_64.S
+--- linux-2.6.38.7/arch/x86/boot/compressed/head_64.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/compressed/head_64.S 2011-04-28 19:34:14.000000000 -0400
+@@ -91,7 +91,7 @@ ENTRY(startup_32)
+ notl %eax
+ andl %eax, %ebx
+ #else
+- movl $LOAD_PHYSICAL_ADDR, %ebx
++ movl $____LOAD_PHYSICAL_ADDR, %ebx
+ #endif
+
+ /* Target address to relocate to for decompression */
+@@ -233,7 +233,7 @@ ENTRY(startup_64)
+ notq %rax
+ andq %rax, %rbp
+ #else
+- movq $LOAD_PHYSICAL_ADDR, %rbp
++ movq $____LOAD_PHYSICAL_ADDR, %rbp
+ #endif
+
+ /* Target address to relocate to for decompression */
+diff -urNp linux-2.6.38.7/arch/x86/boot/compressed/misc.c linux-2.6.38.7/arch/x86/boot/compressed/misc.c
+--- linux-2.6.38.7/arch/x86/boot/compressed/misc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/compressed/misc.c 2011-04-28 19:34:14.000000000 -0400
+@@ -310,7 +310,7 @@ static void parse_elf(void *output)
+ case PT_LOAD:
+ #ifdef CONFIG_RELOCATABLE
+ dest = output;
+- dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
++ dest += (phdr->p_paddr - ____LOAD_PHYSICAL_ADDR);
+ #else
+ dest = (void *)(phdr->p_paddr);
+ #endif
+@@ -363,7 +363,7 @@ asmlinkage void decompress_kernel(void *
+ error("Destination address too large");
+ #endif
+ #ifndef CONFIG_RELOCATABLE
+- if ((unsigned long)output != LOAD_PHYSICAL_ADDR)
++ if ((unsigned long)output != ____LOAD_PHYSICAL_ADDR)
+ error("Wrong destination address");
+ #endif
+
+diff -urNp linux-2.6.38.7/arch/x86/boot/compressed/relocs.c linux-2.6.38.7/arch/x86/boot/compressed/relocs.c
+--- linux-2.6.38.7/arch/x86/boot/compressed/relocs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/compressed/relocs.c 2011-04-28 19:34:14.000000000 -0400
+@@ -13,8 +13,11 @@
+
+ static void die(char *fmt, ...);
+
++#include "../../../../include/generated/autoconf.h"
++
+ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+ static Elf32_Ehdr ehdr;
++static Elf32_Phdr *phdr;
+ static unsigned long reloc_count, reloc_idx;
+ static unsigned long *relocs;
+
+@@ -270,9 +273,39 @@ static void read_ehdr(FILE *fp)
+ }
+ }
+
++static void read_phdrs(FILE *fp)
++{
++ unsigned int i;
++
++ phdr = calloc(ehdr.e_phnum, sizeof(Elf32_Phdr));
++ if (!phdr) {
++ die("Unable to allocate %d program headers\n",
++ ehdr.e_phnum);
++ }
++ if (fseek(fp, ehdr.e_phoff, SEEK_SET) < 0) {
++ die("Seek to %d failed: %s\n",
++ ehdr.e_phoff, strerror(errno));
++ }
++ if (fread(phdr, sizeof(*phdr), ehdr.e_phnum, fp) != ehdr.e_phnum) {
++ die("Cannot read ELF program headers: %s\n",
++ strerror(errno));
++ }
++ for(i = 0; i < ehdr.e_phnum; i++) {
++ phdr[i].p_type = elf32_to_cpu(phdr[i].p_type);
++ phdr[i].p_offset = elf32_to_cpu(phdr[i].p_offset);
++ phdr[i].p_vaddr = elf32_to_cpu(phdr[i].p_vaddr);
++ phdr[i].p_paddr = elf32_to_cpu(phdr[i].p_paddr);
++ phdr[i].p_filesz = elf32_to_cpu(phdr[i].p_filesz);
++ phdr[i].p_memsz = elf32_to_cpu(phdr[i].p_memsz);
++ phdr[i].p_flags = elf32_to_cpu(phdr[i].p_flags);
++ phdr[i].p_align = elf32_to_cpu(phdr[i].p_align);
++ }
++
++}
++
+ static void read_shdrs(FILE *fp)
+ {
+- int i;
++ unsigned int i;
+ Elf32_Shdr shdr;
+
+ secs = calloc(ehdr.e_shnum, sizeof(struct section));
+@@ -307,7 +340,7 @@ static void read_shdrs(FILE *fp)
+
+ static void read_strtabs(FILE *fp)
+ {
+- int i;
++ unsigned int i;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_STRTAB) {
+@@ -332,7 +365,7 @@ static void read_strtabs(FILE *fp)
+
+ static void read_symtabs(FILE *fp)
+ {
+- int i,j;
++ unsigned int i,j;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_SYMTAB) {
+@@ -365,7 +398,9 @@ static void read_symtabs(FILE *fp)
+
+ static void read_relocs(FILE *fp)
+ {
+- int i,j;
++ unsigned int i,j;
++ uint32_t base;
++
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ if (sec->shdr.sh_type != SHT_REL) {
+@@ -385,9 +420,18 @@ static void read_relocs(FILE *fp)
+ die("Cannot read symbol table: %s\n",
+ strerror(errno));
+ }
++ base = 0;
++ for (j = 0; j < ehdr.e_phnum; j++) {
++ if (phdr[j].p_type != PT_LOAD )
++ continue;
++ if (secs[sec->shdr.sh_info].shdr.sh_offset < phdr[j].p_offset || secs[sec->shdr.sh_info].shdr.sh_offset >= phdr[j].p_offset + phdr[j].p_filesz)
++ continue;
++ base = CONFIG_PAGE_OFFSET + phdr[j].p_paddr - phdr[j].p_vaddr;
++ break;
++ }
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
+ Elf32_Rel *rel = &sec->reltab[j];
+- rel->r_offset = elf32_to_cpu(rel->r_offset);
++ rel->r_offset = elf32_to_cpu(rel->r_offset) + base;
+ rel->r_info = elf32_to_cpu(rel->r_info);
+ }
+ }
+@@ -396,14 +440,14 @@ static void read_relocs(FILE *fp)
+
+ static void print_absolute_symbols(void)
+ {
+- int i;
++ unsigned int i;
+ printf("Absolute symbols\n");
+ printf(" Num: Value Size Type Bind Visibility Name\n");
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+- int j;
++ unsigned int j;
+
+ if (sec->shdr.sh_type != SHT_SYMTAB) {
+ continue;
+@@ -431,14 +475,14 @@ static void print_absolute_symbols(void)
+
+ static void print_absolute_relocs(void)
+ {
+- int i, printed = 0;
++ unsigned int i, printed = 0;
+
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ struct section *sec = &secs[i];
+ struct section *sec_applies, *sec_symtab;
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+- int j;
++ unsigned int j;
+ if (sec->shdr.sh_type != SHT_REL) {
+ continue;
+ }
+@@ -499,13 +543,13 @@ static void print_absolute_relocs(void)
+
+ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
+ {
+- int i;
++ unsigned int i;
+ /* Walk through the relocations */
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ char *sym_strtab;
+ Elf32_Sym *sh_symtab;
+ struct section *sec_applies, *sec_symtab;
+- int j;
++ unsigned int j;
+ struct section *sec = &secs[i];
+
+ if (sec->shdr.sh_type != SHT_REL) {
+@@ -530,6 +574,22 @@ static void walk_relocs(void (*visit)(El
+ !is_rel_reloc(sym_name(sym_strtab, sym))) {
+ continue;
+ }
++ /* Don't relocate actual per-cpu variables, they are absolute indices, not addresses */
++ if (!strcmp(sec_name(sym->st_shndx), ".data..percpu") && strcmp(sym_name(sym_strtab, sym), "__per_cpu_load"))
++ continue;
++
++#if defined(CONFIG_PAX_KERNEXEC) && defined(CONFIG_X86_32)
++ /* Don't relocate actual code, they are relocated implicitly by the base address of KERNEL_CS */
++ if (!strcmp(sec_name(sym->st_shndx), ".module.text") && !strcmp(sym_name(sym_strtab, sym), "_etext"))
++ continue;
++ if (!strcmp(sec_name(sym->st_shndx), ".init.text"))
++ continue;
++ if (!strcmp(sec_name(sym->st_shndx), ".exit.text"))
++ continue;
++ if (!strcmp(sec_name(sym->st_shndx), ".text") && strcmp(sym_name(sym_strtab, sym), "__LOAD_PHYSICAL_ADDR"))
++ continue;
++#endif
++
+ switch (r_type) {
+ case R_386_NONE:
+ case R_386_PC32:
+@@ -571,7 +631,7 @@ static int cmp_relocs(const void *va, co
+
+ static void emit_relocs(int as_text)
+ {
+- int i;
++ unsigned int i;
+ /* Count how many relocations I have and allocate space for them. */
+ reloc_count = 0;
+ walk_relocs(count_reloc);
+@@ -665,6 +725,7 @@ int main(int argc, char **argv)
+ fname, strerror(errno));
+ }
+ read_ehdr(fp);
++ read_phdrs(fp);
+ read_shdrs(fp);
+ read_strtabs(fp);
+ read_symtabs(fp);
+diff -urNp linux-2.6.38.7/arch/x86/boot/cpucheck.c linux-2.6.38.7/arch/x86/boot/cpucheck.c
+--- linux-2.6.38.7/arch/x86/boot/cpucheck.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/cpucheck.c 2011-04-28 19:34:14.000000000 -0400
+@@ -74,7 +74,7 @@ static int has_fpu(void)
+ u16 fcw = -1, fsw = -1;
+ u32 cr0;
+
+- asm("movl %%cr0,%0" : "=r" (cr0));
++ asm volatile("movl %%cr0,%0" : "=r" (cr0));
+ if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
+ cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
+ asm volatile("movl %0,%%cr0" : : "r" (cr0));
+@@ -90,7 +90,7 @@ static int has_eflag(u32 mask)
+ {
+ u32 f0, f1;
+
+- asm("pushfl ; "
++ asm volatile("pushfl ; "
+ "pushfl ; "
+ "popl %0 ; "
+ "movl %0,%1 ; "
+@@ -115,7 +115,7 @@ static void get_flags(void)
+ set_bit(X86_FEATURE_FPU, cpu.flags);
+
+ if (has_eflag(X86_EFLAGS_ID)) {
+- asm("cpuid"
++ asm volatile("cpuid"
+ : "=a" (max_intel_level),
+ "=b" (cpu_vendor[0]),
+ "=d" (cpu_vendor[1]),
+@@ -124,7 +124,7 @@ static void get_flags(void)
+
+ if (max_intel_level >= 0x00000001 &&
+ max_intel_level <= 0x0000ffff) {
+- asm("cpuid"
++ asm volatile("cpuid"
+ : "=a" (tfms),
+ "=c" (cpu.flags[4]),
+ "=d" (cpu.flags[0])
+@@ -136,7 +136,7 @@ static void get_flags(void)
+ cpu.model += ((tfms >> 16) & 0xf) << 4;
+ }
+
+- asm("cpuid"
++ asm volatile("cpuid"
+ : "=a" (max_amd_level)
+ : "a" (0x80000000)
+ : "ebx", "ecx", "edx");
+@@ -144,7 +144,7 @@ static void get_flags(void)
+ if (max_amd_level >= 0x80000001 &&
+ max_amd_level <= 0x8000ffff) {
+ u32 eax = 0x80000001;
+- asm("cpuid"
++ asm volatile("cpuid"
+ : "+a" (eax),
+ "=c" (cpu.flags[6]),
+ "=d" (cpu.flags[1])
+@@ -203,9 +203,9 @@ int check_cpu(int *cpu_level_ptr, int *r
+ u32 ecx = MSR_K7_HWCR;
+ u32 eax, edx;
+
+- asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
++ asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+ eax &= ~(1 << 15);
+- asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
++ asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+ get_flags(); /* Make sure it really did something */
+ err = check_flags();
+@@ -218,9 +218,9 @@ int check_cpu(int *cpu_level_ptr, int *r
+ u32 ecx = MSR_VIA_FCR;
+ u32 eax, edx;
+
+- asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
++ asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+ eax |= (1<<1)|(1<<7);
+- asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
++ asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+ set_bit(X86_FEATURE_CX8, cpu.flags);
+ err = check_flags();
+@@ -231,12 +231,12 @@ int check_cpu(int *cpu_level_ptr, int *r
+ u32 eax, edx;
+ u32 level = 1;
+
+- asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+- asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
+- asm("cpuid"
++ asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
++ asm volatile("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
++ asm volatile("cpuid"
+ : "+a" (level), "=d" (cpu.flags[0])
+ : : "ecx", "ebx");
+- asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
++ asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+ err = check_flags();
+ }
+diff -urNp linux-2.6.38.7/arch/x86/boot/header.S linux-2.6.38.7/arch/x86/boot/header.S
+--- linux-2.6.38.7/arch/x86/boot/header.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/header.S 2011-04-28 19:34:14.000000000 -0400
+@@ -224,7 +224,7 @@ setup_data: .quad 0 # 64-bit physical
+ # single linked list of
+ # struct setup_data
+
+-pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
++pref_address: .quad ____LOAD_PHYSICAL_ADDR # preferred load addr
+
+ #define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset)
+ #define VO_INIT_SIZE (VO__end - VO__text)
+diff -urNp linux-2.6.38.7/arch/x86/boot/memory.c linux-2.6.38.7/arch/x86/boot/memory.c
+--- linux-2.6.38.7/arch/x86/boot/memory.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/memory.c 2011-04-28 19:34:14.000000000 -0400
+@@ -19,7 +19,7 @@
+
+ static int detect_memory_e820(void)
+ {
+- int count = 0;
++ unsigned int count = 0;
+ struct biosregs ireg, oreg;
+ struct e820entry *desc = boot_params.e820_map;
+ static struct e820entry buf; /* static so it is zeroed */
+diff -urNp linux-2.6.38.7/arch/x86/boot/video.c linux-2.6.38.7/arch/x86/boot/video.c
+--- linux-2.6.38.7/arch/x86/boot/video.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/video.c 2011-04-28 19:34:14.000000000 -0400
+@@ -96,7 +96,7 @@ static void store_mode_params(void)
+ static unsigned int get_entry(void)
+ {
+ char entry_buf[4];
+- int i, len = 0;
++ unsigned int i, len = 0;
+ int key;
+ unsigned int v;
+
+diff -urNp linux-2.6.38.7/arch/x86/boot/video-vesa.c linux-2.6.38.7/arch/x86/boot/video-vesa.c
+--- linux-2.6.38.7/arch/x86/boot/video-vesa.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/boot/video-vesa.c 2011-04-28 19:34:14.000000000 -0400
+@@ -200,6 +200,7 @@ static void vesa_store_pm_info(void)
+
+ boot_params.screen_info.vesapm_seg = oreg.es;
+ boot_params.screen_info.vesapm_off = oreg.di;
++ boot_params.screen_info.vesapm_size = oreg.cx;
+ }
+
+ /*
+diff -urNp linux-2.6.38.7/arch/x86/ia32/ia32_aout.c linux-2.6.38.7/arch/x86/ia32/ia32_aout.c
+--- linux-2.6.38.7/arch/x86/ia32/ia32_aout.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/ia32/ia32_aout.c 2011-04-28 19:34:14.000000000 -0400
+@@ -162,6 +162,8 @@ static int aout_core_dump(long signr, st
+ unsigned long dump_start, dump_size;
+ struct user32 dump;
+
++ memset(&dump, 0, sizeof(dump));
++
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ has_dumped = 1;
+diff -urNp linux-2.6.38.7/arch/x86/ia32/ia32entry.S linux-2.6.38.7/arch/x86/ia32/ia32entry.S
+--- linux-2.6.38.7/arch/x86/ia32/ia32entry.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/ia32/ia32entry.S 2011-05-22 23:15:39.000000000 -0400
+@@ -13,6 +13,7 @@
+ #include <asm/thread_info.h>
+ #include <asm/segment.h>
+ #include <asm/irqflags.h>
++#include <asm/pgtable.h>
+ #include <linux/linkage.h>
+
+ /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
+@@ -93,6 +94,32 @@ ENTRY(native_irq_enable_sysexit)
+ ENDPROC(native_irq_enable_sysexit)
+ #endif
+
++ .macro pax_enter_kernel_user
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ call pax_enter_kernel_user
++#endif
++ .endm
++
++ .macro pax_exit_kernel_user
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ call pax_exit_kernel_user
++#endif
++#ifdef CONFIG_PAX_RANDKSTACK
++ pushq %rax
++ call pax_randomize_kstack
++ popq %rax
++#endif
++#ifdef CONFIG_PAX_MEMORY_STACKLEAK
++ call pax_erase_kstack
++#endif
++ .endm
++
++ .macro pax_erase_kstack
++#ifdef CONFIG_PAX_MEMORY_STACKLEAK
++ call pax_erase_kstack
++#endif
++ .endm
++
+ /*
+ * 32bit SYSENTER instruction entry.
+ *
+@@ -119,7 +146,7 @@ ENTRY(ia32_sysenter_target)
+ CFI_REGISTER rsp,rbp
+ SWAPGS_UNSAFE_STACK
+ movq PER_CPU_VAR(kernel_stack), %rsp
+- addq $(KERNEL_STACK_OFFSET),%rsp
++ pax_enter_kernel_user
+ /*
+ * No need to follow this irqs on/off section: the syscall
+ * disabled irqs, here we enable it straight after entry:
+@@ -135,7 +162,8 @@ ENTRY(ia32_sysenter_target)
+ pushfq
+ CFI_ADJUST_CFA_OFFSET 8
+ /*CFI_REL_OFFSET rflags,0*/
+- movl 8*3-THREAD_SIZE+TI_sysenter_return(%rsp), %r10d
++ GET_THREAD_INFO(%r10)
++ movl TI_sysenter_return(%r10), %r10d
+ CFI_REGISTER rip,r10
+ pushq $__USER32_CS
+ CFI_ADJUST_CFA_OFFSET 8
+@@ -150,6 +178,12 @@ ENTRY(ia32_sysenter_target)
+ SAVE_ARGS 0,0,1
+ /* no need to do an access_ok check here because rbp has been
+ 32bit zero extended */
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ mov $PAX_USER_SHADOW_BASE,%r10
++ add %r10,%rbp
++#endif
++
+ 1: movl (%rbp),%ebp
+ .section __ex_table,"a"
+ .quad 1b,ia32_badarg
+@@ -172,6 +206,7 @@ sysenter_dispatch:
+ testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
+ jnz sysexit_audit
+ sysexit_from_sys_call:
++ pax_exit_kernel_user
+ andl $~TS_COMPAT,TI_status(%r10)
+ /* clear IF, that popfq doesn't enable interrupts early */
+ andl $~0x200,EFLAGS-R11(%rsp)
+@@ -200,6 +235,9 @@ sysexit_from_sys_call:
+ movl %eax,%esi /* 2nd arg: syscall number */
+ movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
+ call audit_syscall_entry
++
++ pax_erase_kstack
++
+ movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
+ cmpq $(IA32_NR_syscalls-1),%rax
+ ja ia32_badsys
+@@ -252,6 +290,9 @@ sysenter_tracesys:
+ movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
+ movq %rsp,%rdi /* &pt_regs -> arg1 */
+ call syscall_trace_enter
++
++ pax_erase_kstack
++
+ LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
+ RESTORE_REST
+ cmpq $(IA32_NR_syscalls-1),%rax
+@@ -283,19 +324,24 @@ ENDPROC(ia32_sysenter_target)
+ ENTRY(ia32_cstar_target)
+ CFI_STARTPROC32 simple
+ CFI_SIGNAL_FRAME
+- CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET
++ CFI_DEF_CFA rsp,0
+ CFI_REGISTER rip,rcx
+ /*CFI_REGISTER rflags,r11*/
+ SWAPGS_UNSAFE_STACK
+ movl %esp,%r8d
+ CFI_REGISTER rsp,r8
+ movq PER_CPU_VAR(kernel_stack),%rsp
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pax_enter_kernel_user
++#endif
++
+ /*
+ * No need to follow this irqs on/off section: the syscall
+ * disabled irqs and here we enable it straight after entry:
+ */
+ ENABLE_INTERRUPTS(CLBR_NONE)
+- SAVE_ARGS 8,1,1
++ SAVE_ARGS 8*6,1,1
+ movl %eax,%eax /* zero extension */
+ movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
+ movq %rcx,RIP-ARGOFFSET(%rsp)
+@@ -311,6 +357,12 @@ ENTRY(ia32_cstar_target)
+ /* no need to do an access_ok check here because r8 has been
+ 32bit zero extended */
+ /* hardware stack frame is complete now */
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ mov $PAX_USER_SHADOW_BASE,%r10
++ add %r10,%r8
++#endif
++
+ 1: movl (%r8),%r9d
+ .section __ex_table,"a"
+ .quad 1b,ia32_badarg
+@@ -333,6 +385,7 @@ cstar_dispatch:
+ testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
+ jnz sysretl_audit
+ sysretl_from_sys_call:
++ pax_exit_kernel_user
+ andl $~TS_COMPAT,TI_status(%r10)
+ RESTORE_ARGS 1,-ARG_SKIP,1,1,1
+ movl RIP-ARGOFFSET(%rsp),%ecx
+@@ -370,6 +423,9 @@ cstar_tracesys:
+ movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+ movq %rsp,%rdi /* &pt_regs -> arg1 */
+ call syscall_trace_enter
++
++ pax_erase_kstack
++
+ LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
+ RESTORE_REST
+ xchgl %ebp,%r9d
+@@ -415,6 +471,7 @@ ENTRY(ia32_syscall)
+ CFI_REL_OFFSET rip,RIP-RIP
+ PARAVIRT_ADJUST_EXCEPTION_FRAME
+ SWAPGS
++ pax_enter_kernel_user
+ /*
+ * No need to follow this irqs on/off section: the syscall
+ * disabled irqs and here we enable it straight after entry:
+@@ -448,6 +505,9 @@ ia32_tracesys:
+ movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+ movq %rsp,%rdi /* &pt_regs -> arg1 */
+ call syscall_trace_enter
++
++ pax_erase_kstack
++
+ LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
+ RESTORE_REST
+ cmpq $(IA32_NR_syscalls-1),%rax
+diff -urNp linux-2.6.38.7/arch/x86/ia32/ia32_signal.c linux-2.6.38.7/arch/x86/ia32/ia32_signal.c
+--- linux-2.6.38.7/arch/x86/ia32/ia32_signal.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/ia32/ia32_signal.c 2011-04-28 19:34:14.000000000 -0400
+@@ -403,7 +403,7 @@ static void __user *get_sigframe(struct
+ sp -= frame_size;
+ /* Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0. */
+- sp = ((sp + 4) & -16ul) - 4;
++ sp = ((sp - 12) & -16ul) - 4;
+ return (void __user *) sp;
+ }
+
+@@ -461,7 +461,7 @@ int ia32_setup_frame(int sig, struct k_s
+ * These are actually not used anymore, but left because some
+ * gdb versions depend on them as a marker.
+ */
+- put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
++ put_user_ex(*((const u64 *)&code), (u64 *)frame->retcode);
+ } put_user_catch(err);
+
+ if (err)
+@@ -503,7 +503,7 @@ int ia32_setup_rt_frame(int sig, struct
+ 0xb8,
+ __NR_ia32_rt_sigreturn,
+ 0x80cd,
+- 0,
++ 0
+ };
+
+ frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
+@@ -533,16 +533,18 @@ int ia32_setup_rt_frame(int sig, struct
+
+ if (ka->sa.sa_flags & SA_RESTORER)
+ restorer = ka->sa.sa_restorer;
++ else if (current->mm->context.vdso)
++ /* Return stub is in 32bit vsyscall page */
++ restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
+ else
+- restorer = VDSO32_SYMBOL(current->mm->context.vdso,
+- rt_sigreturn);
++ restorer = &frame->retcode;
+ put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
+
+ /*
+ * Not actually used anymore, but left because some gdb
+ * versions need it.
+ */
+- put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
++ put_user_ex(*((const u64 *)&code), (u64 *)frame->retcode);
+ } put_user_catch(err);
+
+ if (err)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/alternative.h linux-2.6.38.7/arch/x86/include/asm/alternative.h
+--- linux-2.6.38.7/arch/x86/include/asm/alternative.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/alternative.h 2011-04-28 19:34:14.000000000 -0400
+@@ -94,7 +94,7 @@ static inline int alternatives_text_rese
+ ".section .discard,\"aw\",@progbits\n" \
+ " .byte 0xff + (664f-663f) - (662b-661b)\n" /* rlen <= slen */ \
+ ".previous\n" \
+- ".section .altinstr_replacement, \"ax\"\n" \
++ ".section .altinstr_replacement, \"a\"\n" \
+ "663:\n\t" newinstr "\n664:\n" /* replacement */ \
+ ".previous"
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/apm.h linux-2.6.38.7/arch/x86/include/asm/apm.h
+--- linux-2.6.38.7/arch/x86/include/asm/apm.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/apm.h 2011-04-28 19:34:14.000000000 -0400
+@@ -34,7 +34,7 @@ static inline void apm_bios_call_asm(u32
+ __asm__ __volatile__(APM_DO_ZERO_SEGS
+ "pushl %%edi\n\t"
+ "pushl %%ebp\n\t"
+- "lcall *%%cs:apm_bios_entry\n\t"
++ "lcall *%%ss:apm_bios_entry\n\t"
+ "setc %%al\n\t"
+ "popl %%ebp\n\t"
+ "popl %%edi\n\t"
+@@ -58,7 +58,7 @@ static inline u8 apm_bios_call_simple_as
+ __asm__ __volatile__(APM_DO_ZERO_SEGS
+ "pushl %%edi\n\t"
+ "pushl %%ebp\n\t"
+- "lcall *%%cs:apm_bios_entry\n\t"
++ "lcall *%%ss:apm_bios_entry\n\t"
+ "setc %%bl\n\t"
+ "popl %%ebp\n\t"
+ "popl %%edi\n\t"
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/atomic64_32.h linux-2.6.38.7/arch/x86/include/asm/atomic64_32.h
+--- linux-2.6.38.7/arch/x86/include/asm/atomic64_32.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/atomic64_32.h 2011-05-11 18:35:16.000000000 -0400
+@@ -12,6 +12,14 @@ typedef struct {
+ u64 __aligned(8) counter;
+ } atomic64_t;
+
++#ifdef CONFIG_PAX_REFCOUNT
++typedef struct {
++ u64 __aligned(8) counter;
++} atomic64_unchecked_t;
++#else
++typedef atomic64_t atomic64_unchecked_t;
++#endif
++
+ #define ATOMIC64_INIT(val) { (val) }
+
+ #ifdef CONFIG_X86_CMPXCHG64
+@@ -38,6 +46,21 @@ static inline long long atomic64_cmpxchg
+ }
+
+ /**
++ * atomic64_cmpxchg_unchecked - cmpxchg atomic64 variable
++ * @p: pointer to type atomic64_unchecked_t
++ * @o: expected value
++ * @n: new value
++ *
++ * Atomically sets @v to @n if it was equal to @o and returns
++ * the old value.
++ */
++
++static inline long long atomic64_cmpxchg_unchecked(atomic64_unchecked_t *v, long long o, long long n)
++{
++ return cmpxchg64(&v->counter, o, n);
++}
++
++/**
+ * atomic64_xchg - xchg atomic64 variable
+ * @v: pointer to type atomic64_t
+ * @n: value to assign
+@@ -77,6 +100,24 @@ static inline void atomic64_set(atomic64
+ }
+
+ /**
++ * atomic64_set_unchecked - set atomic64 variable
++ * @v: pointer to type atomic64_unchecked_t
++ * @n: value to assign
++ *
++ * Atomically sets the value of @v to @n.
++ */
++static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long long i)
++{
++ unsigned high = (unsigned)(i >> 32);
++ unsigned low = (unsigned)i;
++ asm volatile(ATOMIC64_ALTERNATIVE(set)
++ : "+b" (low), "+c" (high)
++ : "S" (v)
++ : "eax", "edx", "memory"
++ );
++}
++
++/**
+ * atomic64_read - read atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+@@ -93,6 +134,22 @@ static inline long long atomic64_read(at
+ }
+
+ /**
++ * atomic64_read_unchecked - read atomic64 variable
++ * @v: pointer to type atomic64_unchecked_t
++ *
++ * Atomically reads the value of @v and returns it.
++ */
++static inline long long atomic64_read_unchecked(atomic64_unchecked_t *v)
++{
++ long long r;
++ asm volatile(ATOMIC64_ALTERNATIVE(read_unchecked)
++ : "=A" (r), "+c" (v)
++ : : "memory"
++ );
++ return r;
++ }
++
++/**
+ * atomic64_add_return - add and return
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
+@@ -108,6 +165,22 @@ static inline long long atomic64_add_ret
+ return i;
+ }
+
++/**
++ * atomic64_add_return_unchecked - add and return
++ * @i: integer value to add
++ * @v: pointer to type atomic64_unchecked_t
++ *
++ * Atomically adds @i to @v and returns @i + *@v
++ */
++static inline long long atomic64_add_return_unchecked(long long i, atomic64_unchecked_t *v)
++{
++ asm volatile(ATOMIC64_ALTERNATIVE(add_return_unchecked)
++ : "+A" (i), "+c" (v)
++ : : "memory"
++ );
++ return i;
++}
++
+ /*
+ * Other variants with different arithmetic operators:
+ */
+@@ -131,6 +204,17 @@ static inline long long atomic64_inc_ret
+ return a;
+ }
+
++static inline long long atomic64_inc_return_unchecked(atomic64_unchecked_t *v)
++{
++ long long a;
++ asm volatile(ATOMIC64_ALTERNATIVE(inc_return_unchecked)
++ : "=A" (a)
++ : "S" (v)
++ : "memory", "ecx"
++ );
++ return a;
++}
++
+ static inline long long atomic64_dec_return(atomic64_t *v)
+ {
+ long long a;
+@@ -159,6 +243,22 @@ static inline long long atomic64_add(lon
+ }
+
+ /**
++ * atomic64_add_unchecked - add integer to atomic64 variable
++ * @i: integer value to add
++ * @v: pointer to type atomic64_unchecked_t
++ *
++ * Atomically adds @i to @v.
++ */
++static inline long long atomic64_add_unchecked(long long i, atomic64_unchecked_t *v)
++{
++ asm volatile(ATOMIC64_ALTERNATIVE_(add_unchecked, add_return_unchecked)
++ : "+A" (i), "+c" (v)
++ : : "memory"
++ );
++ return i;
++}
++
++/**
+ * atomic64_sub - subtract the atomic64 variable
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/atomic64_64.h linux-2.6.38.7/arch/x86/include/asm/atomic64_64.h
+--- linux-2.6.38.7/arch/x86/include/asm/atomic64_64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/atomic64_64.h 2011-05-16 21:47:08.000000000 -0400
+@@ -18,7 +18,19 @@
+ */
+ static inline long atomic64_read(const atomic64_t *v)
+ {
+- return (*(volatile long *)&(v)->counter);
++ return (*(volatile const long *)&(v)->counter);
++}
++
++/**
++ * atomic64_read_unchecked - read atomic64 variable
++ * @v: pointer of type atomic64_unchecked_t
++ *
++ * Atomically reads the value of @v.
++ * Doesn't imply a read memory barrier.
++ */
++static inline long atomic64_read_unchecked(const atomic64_unchecked_t *v)
++{
++ return (*(volatile const long *)&(v)->counter);
+ }
+
+ /**
+@@ -34,6 +46,18 @@ static inline void atomic64_set(atomic64
+ }
+
+ /**
++ * atomic64_set_unchecked - set atomic64 variable
++ * @v: pointer to type atomic64_unchecked_t
++ * @i: required value
++ *
++ * Atomically sets the value of @v to @i.
++ */
++static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i)
++{
++ v->counter = i;
++}
++
++/**
+ * atomic64_add - add integer to atomic64 variable
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
+@@ -42,6 +66,28 @@ static inline void atomic64_set(atomic64
+ */
+ static inline void atomic64_add(long i, atomic64_t *v)
+ {
++ asm volatile(LOCK_PREFIX "addq %1,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "subq %1,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=m" (v->counter)
++ : "er" (i), "m" (v->counter));
++}
++
++/**
++ * atomic64_add_unchecked - add integer to atomic64 variable
++ * @i: integer value to add
++ * @v: pointer to type atomic64_unchecked_t
++ *
++ * Atomically adds @i to @v.
++ */
++static inline void atomic64_add_unchecked(long i, atomic64_unchecked_t *v)
++{
+ asm volatile(LOCK_PREFIX "addq %1,%0"
+ : "=m" (v->counter)
+ : "er" (i), "m" (v->counter));
+@@ -56,7 +102,29 @@ static inline void atomic64_add(long i,
+ */
+ static inline void atomic64_sub(long i, atomic64_t *v)
+ {
+- asm volatile(LOCK_PREFIX "subq %1,%0"
++ asm volatile(LOCK_PREFIX "subq %1,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "addq %1,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=m" (v->counter)
++ : "er" (i), "m" (v->counter));
++}
++
++/**
++ * atomic64_sub_unchecked - subtract the atomic64 variable
++ * @i: integer value to subtract
++ * @v: pointer to type atomic64_unchecked_t
++ *
++ * Atomically subtracts @i from @v.
++ */
++static inline void atomic64_sub_unchecked(long i, atomic64_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "subq %1,%0\n"
+ : "=m" (v->counter)
+ : "er" (i), "m" (v->counter));
+ }
+@@ -74,7 +142,16 @@ static inline int atomic64_sub_and_test(
+ {
+ unsigned char c;
+
+- asm volatile(LOCK_PREFIX "subq %2,%0; sete %1"
++ asm volatile(LOCK_PREFIX "subq %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "addq %2,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
+ : "=m" (v->counter), "=qm" (c)
+ : "er" (i), "m" (v->counter) : "memory");
+ return c;
+@@ -88,6 +165,27 @@ static inline int atomic64_sub_and_test(
+ */
+ static inline void atomic64_inc(atomic64_t *v)
+ {
++ asm volatile(LOCK_PREFIX "incq %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "decq %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=m" (v->counter)
++ : "m" (v->counter));
++}
++
++/**
++ * atomic64_inc_unchecked - increment atomic64 variable
++ * @v: pointer to type atomic64_unchecked_t
++ *
++ * Atomically increments @v by 1.
++ */
++static inline void atomic64_inc_unchecked(atomic64_unchecked_t *v)
++{
+ asm volatile(LOCK_PREFIX "incq %0"
+ : "=m" (v->counter)
+ : "m" (v->counter));
+@@ -101,7 +199,28 @@ static inline void atomic64_inc(atomic64
+ */
+ static inline void atomic64_dec(atomic64_t *v)
+ {
+- asm volatile(LOCK_PREFIX "decq %0"
++ asm volatile(LOCK_PREFIX "decq %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "incq %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=m" (v->counter)
++ : "m" (v->counter));
++}
++
++/**
++ * atomic64_dec_unchecked - decrement atomic64 variable
++ * @v: pointer to type atomic64_t
++ *
++ * Atomically decrements @v by 1.
++ */
++static inline void atomic64_dec_unchecked(atomic64_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "decq %0\n"
+ : "=m" (v->counter)
+ : "m" (v->counter));
+ }
+@@ -118,7 +237,16 @@ static inline int atomic64_dec_and_test(
+ {
+ unsigned char c;
+
+- asm volatile(LOCK_PREFIX "decq %0; sete %1"
++ asm volatile(LOCK_PREFIX "decq %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "incq %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
+ : "=m" (v->counter), "=qm" (c)
+ : "m" (v->counter) : "memory");
+ return c != 0;
+@@ -136,7 +264,16 @@ static inline int atomic64_inc_and_test(
+ {
+ unsigned char c;
+
+- asm volatile(LOCK_PREFIX "incq %0; sete %1"
++ asm volatile(LOCK_PREFIX "incq %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "decq %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
+ : "=m" (v->counter), "=qm" (c)
+ : "m" (v->counter) : "memory");
+ return c != 0;
+@@ -155,7 +292,16 @@ static inline int atomic64_add_negative(
+ {
+ unsigned char c;
+
+- asm volatile(LOCK_PREFIX "addq %2,%0; sets %1"
++ asm volatile(LOCK_PREFIX "addq %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "subq %2,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sets %1\n"
+ : "=m" (v->counter), "=qm" (c)
+ : "er" (i), "m" (v->counter) : "memory");
+ return c;
+@@ -171,7 +317,31 @@ static inline int atomic64_add_negative(
+ static inline long atomic64_add_return(long i, atomic64_t *v)
+ {
+ long __i = i;
+- asm volatile(LOCK_PREFIX "xaddq %0, %1;"
++ asm volatile(LOCK_PREFIX "xaddq %0, %1\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "movq %0, %1\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "+r" (i), "+m" (v->counter)
++ : : "memory");
++ return i + __i;
++}
++
++/**
++ * atomic64_add_return_unchecked - add and return
++ * @i: integer value to add
++ * @v: pointer to type atomic64_unchecked_t
++ *
++ * Atomically adds @i to @v and returns @i + @v
++ */
++static inline long atomic64_add_return_unchecked(long i, atomic64_unchecked_t *v)
++{
++ long __i = i;
++ asm volatile(LOCK_PREFIX "xaddq %0, %1"
+ : "+r" (i), "+m" (v->counter)
+ : : "memory");
+ return i + __i;
+@@ -183,6 +353,10 @@ static inline long atomic64_sub_return(l
+ }
+
+ #define atomic64_inc_return(v) (atomic64_add_return(1, (v)))
++static inline long atomic64_inc_return_unchecked(atomic64_unchecked_t *v)
++{
++ return atomic64_add_return_unchecked(1, v);
++}
+ #define atomic64_dec_return(v) (atomic64_sub_return(1, (v)))
+
+ static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
+@@ -190,6 +364,11 @@ static inline long atomic64_cmpxchg(atom
+ return cmpxchg(&v->counter, old, new);
+ }
+
++static inline long atomic64_cmpxchg_unchecked(atomic64_unchecked_t *v, long old, long new)
++{
++ return cmpxchg(&v->counter, old, new);
++}
++
+ static inline long atomic64_xchg(atomic64_t *v, long new)
+ {
+ return xchg(&v->counter, new);
+@@ -206,17 +385,30 @@ static inline long atomic64_xchg(atomic6
+ */
+ static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
+ {
+- long c, old;
++ long c, old, new;
+ c = atomic64_read(v);
+ for (;;) {
+- if (unlikely(c == (u)))
++ if (unlikely(c == u))
+ break;
+- old = atomic64_cmpxchg((v), c, c + (a));
++
++ asm volatile("add %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "sub %2,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=r" (new)
++ : "0" (c), "ir" (a));
++
++ old = atomic64_cmpxchg(v, c, new);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+- return c != (u);
++ return c != u;
+ }
+
+ #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/atomic.h linux-2.6.38.7/arch/x86/include/asm/atomic.h
+--- linux-2.6.38.7/arch/x86/include/asm/atomic.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/atomic.h 2011-04-28 19:57:25.000000000 -0400
+@@ -22,7 +22,18 @@
+ */
+ static inline int atomic_read(const atomic_t *v)
+ {
+- return (*(volatile int *)&(v)->counter);
++ return (*(volatile const int *)&(v)->counter);
++}
++
++/**
++ * atomic_read_unchecked - read atomic variable
++ * @v: pointer of type atomic_unchecked_t
++ *
++ * Atomically reads the value of @v.
++ */
++static inline int atomic_read_unchecked(const atomic_unchecked_t *v)
++{
++ return (*(volatile const int *)&(v)->counter);
+ }
+
+ /**
+@@ -38,6 +49,18 @@ static inline void atomic_set(atomic_t *
+ }
+
+ /**
++ * atomic_set_unchecked - set atomic variable
++ * @v: pointer of type atomic_unchecked_t
++ * @i: required value
++ *
++ * Atomically sets the value of @v to @i.
++ */
++static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i)
++{
++ v->counter = i;
++}
++
++/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+@@ -46,7 +69,29 @@ static inline void atomic_set(atomic_t *
+ */
+ static inline void atomic_add(int i, atomic_t *v)
+ {
+- asm volatile(LOCK_PREFIX "addl %1,%0"
++ asm volatile(LOCK_PREFIX "addl %1,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "subl %1,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "+m" (v->counter)
++ : "ir" (i));
++}
++
++/**
++ * atomic_add_unchecked - add integer to atomic variable
++ * @i: integer value to add
++ * @v: pointer of type atomic_unchecked_t
++ *
++ * Atomically adds @i to @v.
++ */
++static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "addl %1,%0\n"
+ : "+m" (v->counter)
+ : "ir" (i));
+ }
+@@ -60,7 +105,29 @@ static inline void atomic_add(int i, ato
+ */
+ static inline void atomic_sub(int i, atomic_t *v)
+ {
+- asm volatile(LOCK_PREFIX "subl %1,%0"
++ asm volatile(LOCK_PREFIX "subl %1,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "addl %1,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "+m" (v->counter)
++ : "ir" (i));
++}
++
++/**
++ * atomic_sub_unchecked - subtract integer from atomic variable
++ * @i: integer value to subtract
++ * @v: pointer of type atomic_unchecked_t
++ *
++ * Atomically subtracts @i from @v.
++ */
++static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "subl %1,%0\n"
+ : "+m" (v->counter)
+ : "ir" (i));
+ }
+@@ -78,7 +145,16 @@ static inline int atomic_sub_and_test(in
+ {
+ unsigned char c;
+
+- asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
++ asm volatile(LOCK_PREFIX "subl %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "addl %2,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
+ : "+m" (v->counter), "=qm" (c)
+ : "ir" (i) : "memory");
+ return c;
+@@ -92,7 +168,27 @@ static inline int atomic_sub_and_test(in
+ */
+ static inline void atomic_inc(atomic_t *v)
+ {
+- asm volatile(LOCK_PREFIX "incl %0"
++ asm volatile(LOCK_PREFIX "incl %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "decl %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "+m" (v->counter));
++}
++
++/**
++ * atomic_inc_unchecked - increment atomic variable
++ * @v: pointer of type atomic_unchecked_t
++ *
++ * Atomically increments @v by 1.
++ */
++static inline void atomic_inc_unchecked(atomic_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "incl %0\n"
+ : "+m" (v->counter));
+ }
+
+@@ -104,7 +200,27 @@ static inline void atomic_inc(atomic_t *
+ */
+ static inline void atomic_dec(atomic_t *v)
+ {
+- asm volatile(LOCK_PREFIX "decl %0"
++ asm volatile(LOCK_PREFIX "decl %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "incl %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "+m" (v->counter));
++}
++
++/**
++ * atomic_dec_unchecked - decrement atomic variable
++ * @v: pointer of type atomic_unchecked_t
++ *
++ * Atomically decrements @v by 1.
++ */
++static inline void atomic_dec_unchecked(atomic_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "decl %0\n"
+ : "+m" (v->counter));
+ }
+
+@@ -120,7 +236,16 @@ static inline int atomic_dec_and_test(at
+ {
+ unsigned char c;
+
+- asm volatile(LOCK_PREFIX "decl %0; sete %1"
++ asm volatile(LOCK_PREFIX "decl %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "incl %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
+ : "+m" (v->counter), "=qm" (c)
+ : : "memory");
+ return c != 0;
+@@ -138,7 +263,35 @@ static inline int atomic_inc_and_test(at
+ {
+ unsigned char c;
+
+- asm volatile(LOCK_PREFIX "incl %0; sete %1"
++ asm volatile(LOCK_PREFIX "incl %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "decl %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
++ : "+m" (v->counter), "=qm" (c)
++ : : "memory");
++ return c != 0;
++}
++
++/**
++ * atomic_inc_and_test_unchecked - increment and test
++ * @v: pointer of type atomic_unchecked_t
++ *
++ * Atomically increments @v by 1
++ * and returns true if the result is zero, or false for all
++ * other cases.
++ */
++static inline int atomic_inc_and_test_unchecked(atomic_unchecked_t *v)
++{
++ unsigned char c;
++
++ asm volatile(LOCK_PREFIX "incl %0\n"
++ "sete %1\n"
+ : "+m" (v->counter), "=qm" (c)
+ : : "memory");
+ return c != 0;
+@@ -157,7 +310,16 @@ static inline int atomic_add_negative(in
+ {
+ unsigned char c;
+
+- asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
++ asm volatile(LOCK_PREFIX "addl %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "subl %2,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sets %1\n"
+ : "+m" (v->counter), "=qm" (c)
+ : "ir" (i) : "memory");
+ return c;
+@@ -180,6 +342,46 @@ static inline int atomic_add_return(int
+ #endif
+ /* Modern 486+ processor */
+ __i = i;
++ asm volatile(LOCK_PREFIX "xaddl %0, %1\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "movl %0, %1\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "+r" (i), "+m" (v->counter)
++ : : "memory");
++ return i + __i;
++
++#ifdef CONFIG_M386
++no_xadd: /* Legacy 386 processor */
++ local_irq_save(flags);
++ __i = atomic_read(v);
++ atomic_set(v, i + __i);
++ local_irq_restore(flags);
++ return i + __i;
++#endif
++}
++
++/**
++ * atomic_add_return_unchecked - add integer and return
++ * @v: pointer of type atomic_unchecked_t
++ * @i: integer value to add
++ *
++ * Atomically adds @i to @v and returns @i + @v
++ */
++static inline int atomic_add_return_unchecked(int i, atomic_unchecked_t *v)
++{
++ int __i;
++#ifdef CONFIG_M386
++ unsigned long flags;
++ if (unlikely(boot_cpu_data.x86 <= 3))
++ goto no_xadd;
++#endif
++ /* Modern 486+ processor */
++ __i = i;
+ asm volatile(LOCK_PREFIX "xaddl %0, %1"
+ : "+r" (i), "+m" (v->counter)
+ : : "memory");
+@@ -208,6 +410,10 @@ static inline int atomic_sub_return(int
+ }
+
+ #define atomic_inc_return(v) (atomic_add_return(1, v))
++static inline int atomic_inc_return_unchecked(atomic_unchecked_t *v)
++{
++ return atomic_add_return_unchecked(1, v);
++}
+ #define atomic_dec_return(v) (atomic_sub_return(1, v))
+
+ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+@@ -215,11 +421,21 @@ static inline int atomic_cmpxchg(atomic_
+ return cmpxchg(&v->counter, old, new);
+ }
+
++static inline int atomic_cmpxchg_unchecked(atomic_unchecked_t *v, int old, int new)
++{
++ return cmpxchg(&v->counter, old, new);
++}
++
+ static inline int atomic_xchg(atomic_t *v, int new)
+ {
+ return xchg(&v->counter, new);
+ }
+
++static inline int atomic_xchg_unchecked(atomic_unchecked_t *v, int new)
++{
++ return xchg(&v->counter, new);
++}
++
+ /**
+ * atomic_add_unless - add unless the number is already a given value
+ * @v: pointer of type atomic_t
+@@ -231,21 +447,77 @@ static inline int atomic_xchg(atomic_t *
+ */
+ static inline int atomic_add_unless(atomic_t *v, int a, int u)
+ {
+- int c, old;
++ int c, old, new;
+ c = atomic_read(v);
+ for (;;) {
+- if (unlikely(c == (u)))
++ if (unlikely(c == u))
+ break;
+- old = atomic_cmpxchg((v), c, c + (a));
++
++ asm volatile("addl %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "subl %2,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=r" (new)
++ : "0" (c), "ir" (a));
++
++ old = atomic_cmpxchg(v, c, new);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+- return c != (u);
++ return c != u;
+ }
+
+ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
++/**
++ * atomic_inc_not_zero_hint - increment if not null
++ * @v: pointer of type atomic_t
++ * @hint: probable value of the atomic before the increment
++ *
++ * This version of atomic_inc_not_zero() gives a hint of probable
++ * value of the atomic. This helps processor to not read the memory
++ * before doing the atomic read/modify/write cycle, lowering
++ * number of bus transactions on some arches.
++ *
++ * Returns: 0 if increment was not done, 1 otherwise.
++ */
++#define atomic_inc_not_zero_hint atomic_inc_not_zero_hint
++static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
++{
++ int val, c = hint, new;
++
++ /* sanity test, should be removed by compiler if hint is a constant */
++ if (!hint)
++ return atomic_inc_not_zero(v);
++
++ do {
++ asm volatile("incl %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "decl %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=r" (new)
++ : "0" (c));
++
++ val = atomic_cmpxchg(v, c, new);
++ if (val == c)
++ return 1;
++ c = val;
++ } while (c);
++
++ return 0;
++}
++
+ /*
+ * atomic_dec_if_positive - decrement by 1 if old value positive
+ * @v: pointer of type atomic_t
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/bitops.h linux-2.6.38.7/arch/x86/include/asm/bitops.h
+--- linux-2.6.38.7/arch/x86/include/asm/bitops.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/bitops.h 2011-04-28 19:34:14.000000000 -0400
+@@ -38,7 +38,7 @@
+ * a mask operation on a byte.
+ */
+ #define IS_IMMEDIATE(nr) (__builtin_constant_p(nr))
+-#define CONST_MASK_ADDR(nr, addr) BITOP_ADDR((void *)(addr) + ((nr)>>3))
++#define CONST_MASK_ADDR(nr, addr) BITOP_ADDR((volatile void *)(addr) + ((nr)>>3))
+ #define CONST_MASK(nr) (1 << ((nr) & 7))
+
+ /**
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/boot.h linux-2.6.38.7/arch/x86/include/asm/boot.h
+--- linux-2.6.38.7/arch/x86/include/asm/boot.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/boot.h 2011-04-28 19:34:14.000000000 -0400
+@@ -11,10 +11,15 @@
+ #include <asm/pgtable_types.h>
+
+ /* Physical address where kernel should be loaded. */
+-#define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
++#define ____LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
+ + (CONFIG_PHYSICAL_ALIGN - 1)) \
+ & ~(CONFIG_PHYSICAL_ALIGN - 1))
+
++#ifndef __ASSEMBLY__
++extern unsigned char __LOAD_PHYSICAL_ADDR[];
++#define LOAD_PHYSICAL_ADDR ((unsigned long)__LOAD_PHYSICAL_ADDR)
++#endif
++
+ /* Minimum kernel alignment, as a power of two */
+ #ifdef CONFIG_X86_64
+ #define MIN_KERNEL_ALIGN_LG2 PMD_SHIFT
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/cacheflush.h linux-2.6.38.7/arch/x86/include/asm/cacheflush.h
+--- linux-2.6.38.7/arch/x86/include/asm/cacheflush.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/cacheflush.h 2011-04-28 19:34:14.000000000 -0400
+@@ -26,7 +26,7 @@ static inline unsigned long get_page_mem
+ unsigned long pg_flags = pg->flags & _PGMT_MASK;
+
+ if (pg_flags == _PGMT_DEFAULT)
+- return -1;
++ return ~0UL;
+ else if (pg_flags == _PGMT_WC)
+ return _PAGE_CACHE_WC;
+ else if (pg_flags == _PGMT_UC_MINUS)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/cache.h linux-2.6.38.7/arch/x86/include/asm/cache.h
+--- linux-2.6.38.7/arch/x86/include/asm/cache.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/cache.h 2011-04-28 19:57:25.000000000 -0400
+@@ -5,12 +5,13 @@
+
+ /* L1 cache line size */
+ #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
+-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
++#define L1_CACHE_BYTES (_AC(1,U) << L1_CACHE_SHIFT)
+
+ #define __read_mostly __attribute__((__section__(".data..read_mostly")))
++#define __read_only __attribute__((__section__(".data..read_only")))
+
+ #define INTERNODE_CACHE_SHIFT CONFIG_X86_INTERNODE_CACHE_SHIFT
+-#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)
++#define INTERNODE_CACHE_BYTES (_AC(1,U) << INTERNODE_CACHE_SHIFT)
+
+ #ifdef CONFIG_X86_VSMP
+ #ifdef CONFIG_SMP
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/checksum_32.h linux-2.6.38.7/arch/x86/include/asm/checksum_32.h
+--- linux-2.6.38.7/arch/x86/include/asm/checksum_32.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/checksum_32.h 2011-04-28 19:34:14.000000000 -0400
+@@ -31,6 +31,14 @@ asmlinkage __wsum csum_partial_copy_gene
+ int len, __wsum sum,
+ int *src_err_ptr, int *dst_err_ptr);
+
++asmlinkage __wsum csum_partial_copy_generic_to_user(const void *src, void *dst,
++ int len, __wsum sum,
++ int *src_err_ptr, int *dst_err_ptr);
++
++asmlinkage __wsum csum_partial_copy_generic_from_user(const void *src, void *dst,
++ int len, __wsum sum,
++ int *src_err_ptr, int *dst_err_ptr);
++
+ /*
+ * Note: when you get a NULL pointer exception here this means someone
+ * passed in an incorrect kernel address to one of these functions.
+@@ -50,7 +58,7 @@ static inline __wsum csum_partial_copy_f
+ int *err_ptr)
+ {
+ might_sleep();
+- return csum_partial_copy_generic((__force void *)src, dst,
++ return csum_partial_copy_generic_from_user((__force void *)src, dst,
+ len, sum, err_ptr, NULL);
+ }
+
+@@ -178,7 +186,7 @@ static inline __wsum csum_and_copy_to_us
+ {
+ might_sleep();
+ if (access_ok(VERIFY_WRITE, dst, len))
+- return csum_partial_copy_generic(src, (__force void *)dst,
++ return csum_partial_copy_generic_to_user(src, (__force void *)dst,
+ len, sum, NULL, err_ptr);
+
+ if (len)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/cpufeature.h linux-2.6.38.7/arch/x86/include/asm/cpufeature.h
+--- linux-2.6.38.7/arch/x86/include/asm/cpufeature.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/cpufeature.h 2011-04-28 19:34:14.000000000 -0400
+@@ -349,7 +349,7 @@ static __always_inline __pure bool __sta
+ ".section .discard,\"aw\",@progbits\n"
+ " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */
+ ".previous\n"
+- ".section .altinstr_replacement,\"ax\"\n"
++ ".section .altinstr_replacement,\"a\"\n"
+ "3: movb $1,%0\n"
+ "4:\n"
+ ".previous\n"
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/desc_defs.h linux-2.6.38.7/arch/x86/include/asm/desc_defs.h
+--- linux-2.6.38.7/arch/x86/include/asm/desc_defs.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/desc_defs.h 2011-04-28 19:34:14.000000000 -0400
+@@ -31,6 +31,12 @@ struct desc_struct {
+ unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
+ unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
+ };
++ struct {
++ u16 offset_low;
++ u16 seg;
++ unsigned reserved: 8, type: 4, s: 1, dpl: 2, p: 1;
++ unsigned offset_high: 16;
++ } gate;
+ };
+ } __attribute__((packed));
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/desc.h linux-2.6.38.7/arch/x86/include/asm/desc.h
+--- linux-2.6.38.7/arch/x86/include/asm/desc.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/desc.h 2011-04-28 19:34:14.000000000 -0400
+@@ -4,6 +4,7 @@
+ #include <asm/desc_defs.h>
+ #include <asm/ldt.h>
+ #include <asm/mmu.h>
++#include <asm/pgtable.h>
+ #include <linux/smp.h>
+
+ static inline void fill_ldt(struct desc_struct *desc,
+@@ -15,6 +16,7 @@ static inline void fill_ldt(struct desc_
+ desc->base1 = (info->base_addr & 0x00ff0000) >> 16;
+ desc->type = (info->read_exec_only ^ 1) << 1;
+ desc->type |= info->contents << 2;
++ desc->type |= info->seg_not_present ^ 1;
+ desc->s = 1;
+ desc->dpl = 0x3;
+ desc->p = info->seg_not_present ^ 1;
+@@ -31,16 +33,12 @@ static inline void fill_ldt(struct desc_
+ }
+
+ extern struct desc_ptr idt_descr;
+-extern gate_desc idt_table[];
+-
+-struct gdt_page {
+- struct desc_struct gdt[GDT_ENTRIES];
+-} __attribute__((aligned(PAGE_SIZE)));
+-DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
++extern gate_desc idt_table[256];
+
++extern struct desc_struct cpu_gdt_table[NR_CPUS][PAGE_SIZE / sizeof(struct desc_struct)];
+ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+ {
+- return per_cpu(gdt_page, cpu).gdt;
++ return cpu_gdt_table[cpu];
+ }
+
+ #ifdef CONFIG_X86_64
+@@ -65,9 +63,14 @@ static inline void pack_gate(gate_desc *
+ unsigned long base, unsigned dpl, unsigned flags,
+ unsigned short seg)
+ {
+- gate->a = (seg << 16) | (base & 0xffff);
+- gate->b = (base & 0xffff0000) |
+- (((0x80 | type | (dpl << 5)) & 0xff) << 8);
++ gate->gate.offset_low = base;
++ gate->gate.seg = seg;
++ gate->gate.reserved = 0;
++ gate->gate.type = type;
++ gate->gate.s = 0;
++ gate->gate.dpl = dpl;
++ gate->gate.p = 1;
++ gate->gate.offset_high = base >> 16;
+ }
+
+ #endif
+@@ -115,13 +118,17 @@ static inline void paravirt_free_ldt(str
+ static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ const gate_desc *gate)
+ {
++ pax_open_kernel();
+ memcpy(&idt[entry], gate, sizeof(*gate));
++ pax_close_kernel();
+ }
+
+ static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ const void *desc)
+ {
++ pax_open_kernel();
+ memcpy(&ldt[entry], desc, 8);
++ pax_close_kernel();
+ }
+
+ static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+@@ -139,7 +146,10 @@ static inline void native_write_gdt_entr
+ size = sizeof(struct desc_struct);
+ break;
+ }
++
++ pax_open_kernel();
+ memcpy(&gdt[entry], desc, size);
++ pax_close_kernel();
+ }
+
+ static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
+@@ -211,7 +221,9 @@ static inline void native_set_ldt(const
+
+ static inline void native_load_tr_desc(void)
+ {
++ pax_open_kernel();
+ asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
++ pax_close_kernel();
+ }
+
+ static inline void native_load_gdt(const struct desc_ptr *dtr)
+@@ -246,8 +258,10 @@ static inline void native_load_tls(struc
+ unsigned int i;
+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
++ pax_open_kernel();
+ for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+ gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
++ pax_close_kernel();
+ }
+
+ #define _LDT_empty(info) \
+@@ -309,7 +323,7 @@ static inline void set_desc_limit(struct
+ desc->limit = (limit >> 16) & 0xf;
+ }
+
+-static inline void _set_gate(int gate, unsigned type, void *addr,
++static inline void _set_gate(int gate, unsigned type, const void *addr,
+ unsigned dpl, unsigned ist, unsigned seg)
+ {
+ gate_desc s;
+@@ -327,7 +341,7 @@ static inline void _set_gate(int gate, u
+ * Pentium F0 0F bugfix can have resulted in the mapped
+ * IDT being write-protected.
+ */
+-static inline void set_intr_gate(unsigned int n, void *addr)
++static inline void set_intr_gate(unsigned int n, const void *addr)
+ {
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+@@ -356,19 +370,19 @@ static inline void alloc_intr_gate(unsig
+ /*
+ * This routine sets up an interrupt gate at directory privilege level 3.
+ */
+-static inline void set_system_intr_gate(unsigned int n, void *addr)
++static inline void set_system_intr_gate(unsigned int n, const void *addr)
+ {
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
+ }
+
+-static inline void set_system_trap_gate(unsigned int n, void *addr)
++static inline void set_system_trap_gate(unsigned int n, const void *addr)
+ {
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
+ }
+
+-static inline void set_trap_gate(unsigned int n, void *addr)
++static inline void set_trap_gate(unsigned int n, const void *addr)
+ {
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
+@@ -377,19 +391,31 @@ static inline void set_trap_gate(unsigne
+ static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
+ {
+ BUG_ON((unsigned)n > 0xFF);
+- _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3));
++ _set_gate(n, GATE_TASK, (const void *)0, 0, 0, (gdt_entry<<3));
+ }
+
+-static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
++static inline void set_intr_gate_ist(int n, const void *addr, unsigned ist)
+ {
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
+ }
+
+-static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist)
++static inline void set_system_intr_gate_ist(int n, const void *addr, unsigned ist)
+ {
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
+ }
+
++#ifdef CONFIG_X86_32
++static inline void set_user_cs(unsigned long base, unsigned long limit, int cpu)
++{
++ struct desc_struct d;
++
++ if (likely(limit))
++ limit = (limit - 1UL) >> PAGE_SHIFT;
++ pack_descriptor(&d, base, limit, 0xFB, 0xC);
++ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_DEFAULT_USER_CS, &d, DESCTYPE_S);
++}
++#endif
++
+ #endif /* _ASM_X86_DESC_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/device.h linux-2.6.38.7/arch/x86/include/asm/device.h
+--- linux-2.6.38.7/arch/x86/include/asm/device.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/device.h 2011-04-28 19:34:14.000000000 -0400
+@@ -6,7 +6,7 @@ struct dev_archdata {
+ void *acpi_handle;
+ #endif
+ #ifdef CONFIG_X86_64
+-struct dma_map_ops *dma_ops;
++ const struct dma_map_ops *dma_ops;
+ #endif
+ #if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU)
+ void *iommu; /* hook for IOMMU specific extension */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/dma-mapping.h linux-2.6.38.7/arch/x86/include/asm/dma-mapping.h
+--- linux-2.6.38.7/arch/x86/include/asm/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/dma-mapping.h 2011-04-28 19:34:14.000000000 -0400
+@@ -26,9 +26,9 @@ extern int iommu_merge;
+ extern struct device x86_dma_fallback_dev;
+ extern int panic_on_overflow;
+
+-extern struct dma_map_ops *dma_ops;
++extern const struct dma_map_ops *dma_ops;
+
+-static inline struct dma_map_ops *get_dma_ops(struct device *dev)
++static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
+ {
+ #ifdef CONFIG_X86_32
+ return dma_ops;
+@@ -45,7 +45,7 @@ static inline struct dma_map_ops *get_dm
+ /* Make sure we keep the same behaviour */
+ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ if (ops->mapping_error)
+ return ops->mapping_error(dev, dma_addr);
+
+@@ -115,7 +115,7 @@ static inline void *
+ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t gfp)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ void *memory;
+
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+@@ -142,7 +142,7 @@ dma_alloc_coherent(struct device *dev, s
+ static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t bus)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ WARN_ON(irqs_disabled()); /* for portability */
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/e820.h linux-2.6.38.7/arch/x86/include/asm/e820.h
+--- linux-2.6.38.7/arch/x86/include/asm/e820.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/e820.h 2011-04-28 19:34:14.000000000 -0400
+@@ -69,7 +69,7 @@ struct e820map {
+ #define ISA_START_ADDRESS 0xa0000
+ #define ISA_END_ADDRESS 0x100000
+
+-#define BIOS_BEGIN 0x000a0000
++#define BIOS_BEGIN 0x000c0000
+ #define BIOS_END 0x00100000
+
+ #define BIOS_ROM_BASE 0xffe00000
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/elf.h linux-2.6.38.7/arch/x86/include/asm/elf.h
+--- linux-2.6.38.7/arch/x86/include/asm/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/elf.h 2011-04-28 19:34:14.000000000 -0400
+@@ -237,7 +237,25 @@ extern int force_personality32;
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
++#ifdef CONFIG_PAX_SEGMEXEC
++#define ELF_ET_DYN_BASE ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3*2 : TASK_SIZE/3*2)
++#else
+ #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
++#endif
++
++#ifdef CONFIG_PAX_ASLR
++#ifdef CONFIG_X86_32
++#define PAX_ELF_ET_DYN_BASE 0x10000000UL
++
++#define PAX_DELTA_MMAP_LEN (current->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
++#define PAX_DELTA_STACK_LEN (current->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
++#else
++#define PAX_ELF_ET_DYN_BASE 0x400000UL
++
++#define PAX_DELTA_MMAP_LEN ((test_thread_flag(TIF_IA32)) ? 16 : TASK_SIZE_MAX_SHIFT - PAGE_SHIFT - 3)
++#define PAX_DELTA_STACK_LEN ((test_thread_flag(TIF_IA32)) ? 16 : TASK_SIZE_MAX_SHIFT - PAGE_SHIFT - 3)
++#endif
++#endif
+
+ /* This yields a mask that user programs can use to figure out what
+ instruction set this CPU supports. This could be done in user space,
+@@ -291,8 +309,7 @@ do { \
+ #define ARCH_DLINFO \
+ do { \
+ if (vdso_enabled) \
+- NEW_AUX_ENT(AT_SYSINFO_EHDR, \
+- (unsigned long)current->mm->context.vdso); \
++ NEW_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso);\
+ } while (0)
+
+ #define AT_SYSINFO 32
+@@ -303,7 +320,7 @@ do { \
+
+ #endif /* !CONFIG_X86_32 */
+
+-#define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso)
++#define VDSO_CURRENT_BASE (current->mm->context.vdso)
+
+ #define VDSO_ENTRY \
+ ((unsigned long)VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall))
+@@ -317,7 +334,4 @@ extern int arch_setup_additional_pages(s
+ extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
+ #define compat_arch_setup_additional_pages syscall32_setup_pages
+
+-extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+-#define arch_randomize_brk arch_randomize_brk
+-
+ #endif /* _ASM_X86_ELF_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/emergency-restart.h linux-2.6.38.7/arch/x86/include/asm/emergency-restart.h
+--- linux-2.6.38.7/arch/x86/include/asm/emergency-restart.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/emergency-restart.h 2011-05-22 23:03:34.000000000 -0400
+@@ -15,6 +15,6 @@ enum reboot_type {
+
+ extern enum reboot_type reboot_type;
+
+-extern void machine_emergency_restart(void);
++extern void machine_emergency_restart(void) __noreturn;
+
+ #endif /* _ASM_X86_EMERGENCY_RESTART_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/futex.h linux-2.6.38.7/arch/x86/include/asm/futex.h
+--- linux-2.6.38.7/arch/x86/include/asm/futex.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/futex.h 2011-04-28 19:34:14.000000000 -0400
+@@ -12,16 +12,18 @@
+ #include <asm/system.h>
+
+ #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
++ typecheck(u32 *, uaddr); \
+ asm volatile("1:\t" insn "\n" \
+ "2:\t.section .fixup,\"ax\"\n" \
+ "3:\tmov\t%3, %1\n" \
+ "\tjmp\t2b\n" \
+ "\t.previous\n" \
+ _ASM_EXTABLE(1b, 3b) \
+- : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \
++ : "=r" (oldval), "=r" (ret), "+m" (*(u32 *)____m(uaddr))\
+ : "i" (-EFAULT), "0" (oparg), "1" (0))
+
+ #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
++ typecheck(u32 *, uaddr); \
+ asm volatile("1:\tmovl %2, %0\n" \
+ "\tmovl\t%0, %3\n" \
+ "\t" insn "\n" \
+@@ -34,10 +36,10 @@
+ _ASM_EXTABLE(1b, 4b) \
+ _ASM_EXTABLE(2b, 4b) \
+ : "=&a" (oldval), "=&r" (ret), \
+- "+m" (*uaddr), "=&r" (tem) \
++ "+m" (*(u32 *)____m(uaddr)), "=&r" (tem) \
+ : "r" (oparg), "i" (-EFAULT), "1" (0))
+
+-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
++static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+ {
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+@@ -61,10 +63,10 @@ static inline int futex_atomic_op_inuser
+
+ switch (op) {
+ case FUTEX_OP_SET:
+- __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
++ __futex_atomic_op1(__copyuser_seg"xchgl %0, %2", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+- __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval,
++ __futex_atomic_op1(LOCK_PREFIX __copyuser_seg"xaddl %0, %2", ret, oldval,
+ uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+@@ -109,7 +111,7 @@ static inline int futex_atomic_op_inuser
+ return ret;
+ }
+
+-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
++static inline int futex_atomic_cmpxchg_inatomic(u32 __user *uaddr, int oldval,
+ int newval)
+ {
+
+@@ -119,16 +121,16 @@ static inline int futex_atomic_cmpxchg_i
+ return -ENOSYS;
+ #endif
+
+- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
++ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+ return -EFAULT;
+
+- asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
++ asm volatile("1:\t" LOCK_PREFIX __copyuser_seg"cmpxchgl %3, %1\n"
+ "2:\t.section .fixup, \"ax\"\n"
+ "3:\tmov %2, %0\n"
+ "\tjmp 2b\n"
+ "\t.previous\n"
+ _ASM_EXTABLE(1b, 3b)
+- : "=a" (oldval), "+m" (*uaddr)
++ : "=a" (oldval), "+m" (*(u32 *)____m(uaddr))
+ : "i" (-EFAULT), "r" (newval), "0" (oldval)
+ : "memory"
+ );
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/hw_irq.h linux-2.6.38.7/arch/x86/include/asm/hw_irq.h
+--- linux-2.6.38.7/arch/x86/include/asm/hw_irq.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/hw_irq.h 2011-04-28 19:57:25.000000000 -0400
+@@ -113,8 +113,8 @@ extern void setup_ioapic_dest(void);
+ extern void enable_IO_APIC(void);
+
+ /* Statistics */
+-extern atomic_t irq_err_count;
+-extern atomic_t irq_mis_count;
++extern atomic_unchecked_t irq_err_count;
++extern atomic_unchecked_t irq_mis_count;
+
+ /* EISA */
+ extern void eisa_set_level_irq(unsigned int irq);
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/i387.h linux-2.6.38.7/arch/x86/include/asm/i387.h
+--- linux-2.6.38.7/arch/x86/include/asm/i387.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/i387.h 2011-04-28 19:34:14.000000000 -0400
+@@ -92,6 +92,11 @@ static inline int fxrstor_checking(struc
+ {
+ int err;
+
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ if ((unsigned long)fx < PAX_USER_SHADOW_BASE)
++ fx = (struct i387_fxsave_struct *)((void *)fx + PAX_USER_SHADOW_BASE);
++#endif
++
+ /* See comment in fxsave() below. */
+ #ifdef CONFIG_AS_FXSAVEQ
+ asm volatile("1: fxrstorq %[fx]\n\t"
+@@ -121,6 +126,11 @@ static inline int fxsave_user(struct i38
+ {
+ int err;
+
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ if ((unsigned long)fx < PAX_USER_SHADOW_BASE)
++ fx = (struct i387_fxsave_struct __user *)((void __user *)fx + PAX_USER_SHADOW_BASE);
++#endif
++
+ /*
+ * Clear the bytes not touched by the fxsave and reserved
+ * for the SW usage.
+@@ -213,13 +223,8 @@ static inline void fpu_fxsave(struct fpu
+ #endif /* CONFIG_X86_64 */
+
+ /* We need a safe address that is cheap to find and that is already
+- in L1 during context switch. The best choices are unfortunately
+- different for UP and SMP */
+-#ifdef CONFIG_SMP
+-#define safe_address (__per_cpu_offset[0])
+-#else
+-#define safe_address (kstat_cpu(0).cpustat.user)
+-#endif
++ in L1 during context switch. */
++#define safe_address (init_tss[smp_processor_id()].x86_tss.sp0)
+
+ /*
+ * These must be called with preempt disabled
+@@ -237,7 +242,7 @@ static inline void fpu_save_init(struct
+ } else if (use_fxsr()) {
+ fpu_fxsave(fpu);
+ } else {
+- asm volatile("fsave %[fx]; fwait"
++ asm volatile("fnsave %[fx]; fwait"
+ : [fx] "=m" (fpu->state->fsave));
+ return;
+ }
+@@ -312,7 +317,7 @@ static inline void kernel_fpu_begin(void
+ struct thread_info *me = current_thread_info();
+ preempt_disable();
+ if (me->status & TS_USEDFPU)
+- __save_init_fpu(me->task);
++ __save_init_fpu(current);
+ else
+ clts();
+ }
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/io.h linux-2.6.38.7/arch/x86/include/asm/io.h
+--- linux-2.6.38.7/arch/x86/include/asm/io.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/io.h 2011-04-28 19:34:14.000000000 -0400
+@@ -216,6 +216,17 @@ extern void set_iounmap_nonlazy(void);
+
+ #include <linux/vmalloc.h>
+
++#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
++static inline int valid_phys_addr_range(unsigned long addr, size_t count)
++{
++ return ((addr + count + PAGE_SIZE - 1) >> PAGE_SHIFT) < (1ULL << (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) ? 1 : 0;
++}
++
++static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
++{
++ return (pfn + (count >> PAGE_SHIFT)) < (1ULL << (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) ? 1 : 0;
++}
++
+ /*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/iommu.h linux-2.6.38.7/arch/x86/include/asm/iommu.h
+--- linux-2.6.38.7/arch/x86/include/asm/iommu.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/iommu.h 2011-04-28 19:34:14.000000000 -0400
+@@ -1,7 +1,7 @@
+ #ifndef _ASM_X86_IOMMU_H
+ #define _ASM_X86_IOMMU_H
+
+-extern struct dma_map_ops nommu_dma_ops;
++extern const struct dma_map_ops nommu_dma_ops;
+ extern int force_iommu, no_iommu;
+ extern int iommu_detected;
+ extern int iommu_pass_through;
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/irqflags.h linux-2.6.38.7/arch/x86/include/asm/irqflags.h
+--- linux-2.6.38.7/arch/x86/include/asm/irqflags.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/irqflags.h 2011-04-28 19:34:14.000000000 -0400
+@@ -140,6 +140,11 @@ static inline unsigned long arch_local_i
+ sti; \
+ sysexit
+
++#define GET_CR0_INTO_RDI mov %cr0, %rdi
++#define SET_RDI_INTO_CR0 mov %rdi, %cr0
++#define GET_CR3_INTO_RDI mov %cr3, %rdi
++#define SET_RDI_INTO_CR3 mov %rdi, %cr3
++
+ #else
+ #define INTERRUPT_RETURN iret
+ #define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/kprobes.h linux-2.6.38.7/arch/x86/include/asm/kprobes.h
+--- linux-2.6.38.7/arch/x86/include/asm/kprobes.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/kprobes.h 2011-04-28 19:34:14.000000000 -0400
+@@ -37,13 +37,8 @@ typedef u8 kprobe_opcode_t;
+ #define RELATIVEJUMP_SIZE 5
+ #define RELATIVECALL_OPCODE 0xe8
+ #define RELATIVE_ADDR_SIZE 4
+-#define MAX_STACK_SIZE 64
+-#define MIN_STACK_SIZE(ADDR) \
+- (((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \
+- THREAD_SIZE - (unsigned long)(ADDR))) \
+- ? (MAX_STACK_SIZE) \
+- : (((unsigned long)current_thread_info()) + \
+- THREAD_SIZE - (unsigned long)(ADDR)))
++#define MAX_STACK_SIZE 64UL
++#define MIN_STACK_SIZE(ADDR) min(MAX_STACK_SIZE, current->thread.sp0 - (unsigned long)(ADDR))
+
+ #define flush_insn_slot(p) do { } while (0)
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/kvm_host.h linux-2.6.38.7/arch/x86/include/asm/kvm_host.h
+--- linux-2.6.38.7/arch/x86/include/asm/kvm_host.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/kvm_host.h 2011-04-28 19:57:25.000000000 -0400
+@@ -423,7 +423,7 @@ struct kvm_arch {
+ unsigned int n_used_mmu_pages;
+ unsigned int n_requested_mmu_pages;
+ unsigned int n_max_mmu_pages;
+- atomic_t invlpg_counter;
++ atomic_unchecked_t invlpg_counter;
+ struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
+ /*
+ * Hash table of struct kvm_mmu_page.
+@@ -603,7 +603,7 @@ struct kvm_arch_async_pf {
+ bool direct_map;
+ };
+
+-extern struct kvm_x86_ops *kvm_x86_ops;
++extern const struct kvm_x86_ops *kvm_x86_ops;
+
+ int kvm_mmu_module_init(void);
+ void kvm_mmu_module_exit(void);
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/local.h linux-2.6.38.7/arch/x86/include/asm/local.h
+--- linux-2.6.38.7/arch/x86/include/asm/local.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/local.h 2011-04-28 19:34:14.000000000 -0400
+@@ -18,26 +18,58 @@ typedef struct {
+
+ static inline void local_inc(local_t *l)
+ {
+- asm volatile(_ASM_INC "%0"
++ asm volatile(_ASM_INC "%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_DEC "%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ : "+m" (l->a.counter));
+ }
+
+ static inline void local_dec(local_t *l)
+ {
+- asm volatile(_ASM_DEC "%0"
++ asm volatile(_ASM_DEC "%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_INC "%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ : "+m" (l->a.counter));
+ }
+
+ static inline void local_add(long i, local_t *l)
+ {
+- asm volatile(_ASM_ADD "%1,%0"
++ asm volatile(_ASM_ADD "%1,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_SUB "%1,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ : "+m" (l->a.counter)
+ : "ir" (i));
+ }
+
+ static inline void local_sub(long i, local_t *l)
+ {
+- asm volatile(_ASM_SUB "%1,%0"
++ asm volatile(_ASM_SUB "%1,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_ADD "%1,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ : "+m" (l->a.counter)
+ : "ir" (i));
+ }
+@@ -55,7 +87,16 @@ static inline int local_sub_and_test(lon
+ {
+ unsigned char c;
+
+- asm volatile(_ASM_SUB "%2,%0; sete %1"
++ asm volatile(_ASM_SUB "%2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_ADD "%2,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
+ : "+m" (l->a.counter), "=qm" (c)
+ : "ir" (i) : "memory");
+ return c;
+@@ -73,7 +114,16 @@ static inline int local_dec_and_test(loc
+ {
+ unsigned char c;
+
+- asm volatile(_ASM_DEC "%0; sete %1"
++ asm volatile(_ASM_DEC "%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_INC "%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
+ : "+m" (l->a.counter), "=qm" (c)
+ : : "memory");
+ return c != 0;
+@@ -91,7 +141,16 @@ static inline int local_inc_and_test(loc
+ {
+ unsigned char c;
+
+- asm volatile(_ASM_INC "%0; sete %1"
++ asm volatile(_ASM_INC "%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_DEC "%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sete %1\n"
+ : "+m" (l->a.counter), "=qm" (c)
+ : : "memory");
+ return c != 0;
+@@ -110,7 +169,16 @@ static inline int local_add_negative(lon
+ {
+ unsigned char c;
+
+- asm volatile(_ASM_ADD "%2,%0; sets %1"
++ asm volatile(_ASM_ADD "%2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_SUB "%2,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ "sets %1\n"
+ : "+m" (l->a.counter), "=qm" (c)
+ : "ir" (i) : "memory");
+ return c;
+@@ -133,7 +201,15 @@ static inline long local_add_return(long
+ #endif
+ /* Modern 486+ processor */
+ __i = i;
+- asm volatile(_ASM_XADD "%0, %1;"
++ asm volatile(_ASM_XADD "%0, %1\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ _ASM_MOV "%0,%1\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ : "+r" (i), "+m" (l->a.counter)
+ : : "memory");
+ return i + __i;
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/mce.h linux-2.6.38.7/arch/x86/include/asm/mce.h
+--- linux-2.6.38.7/arch/x86/include/asm/mce.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/mce.h 2011-04-28 19:34:14.000000000 -0400
+@@ -198,7 +198,7 @@ int mce_notify_irq(void);
+ void mce_notify_process(void);
+
+ DECLARE_PER_CPU(struct mce, injectm);
+-extern struct file_operations mce_chrdev_ops;
++extern struct file_operations mce_chrdev_ops; /* cannot be const, see arch/x86/kernel/cpu/mcheck/mce. */
+
+ /*
+ * Exception handler
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/microcode.h linux-2.6.38.7/arch/x86/include/asm/microcode.h
+--- linux-2.6.38.7/arch/x86/include/asm/microcode.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/microcode.h 2011-04-28 19:34:14.000000000 -0400
+@@ -12,13 +12,13 @@ struct device;
+ enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };
+
+ struct microcode_ops {
+- enum ucode_state (*request_microcode_user) (int cpu,
++ enum ucode_state (* const request_microcode_user) (int cpu,
+ const void __user *buf, size_t size);
+
+- enum ucode_state (*request_microcode_fw) (int cpu,
++ enum ucode_state (* const request_microcode_fw) (int cpu,
+ struct device *device);
+
+- void (*microcode_fini_cpu) (int cpu);
++ void (* const microcode_fini_cpu) (int cpu);
+
+ /*
+ * The generic 'microcode_core' part guarantees that
+@@ -38,16 +38,16 @@ struct ucode_cpu_info {
+ extern struct ucode_cpu_info ucode_cpu_info[];
+
+ #ifdef CONFIG_MICROCODE_INTEL
+-extern struct microcode_ops * __init init_intel_microcode(void);
++extern const struct microcode_ops * __init init_intel_microcode(void);
+ #else
+-static inline struct microcode_ops * __init init_intel_microcode(void)
++static inline const struct microcode_ops * __init init_intel_microcode(void)
+ {
+ return NULL;
+ }
+ #endif /* CONFIG_MICROCODE_INTEL */
+
+ #ifdef CONFIG_MICROCODE_AMD
+-extern struct microcode_ops * __init init_amd_microcode(void);
++extern const struct microcode_ops * __init init_amd_microcode(void);
+
+ static inline void get_ucode_data(void *to, const u8 *from, size_t n)
+ {
+@@ -55,7 +55,7 @@ static inline void get_ucode_data(void *
+ }
+
+ #else
+-static inline struct microcode_ops * __init init_amd_microcode(void)
++static inline const struct microcode_ops * __init init_amd_microcode(void)
+ {
+ return NULL;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/mman.h linux-2.6.38.7/arch/x86/include/asm/mman.h
+--- linux-2.6.38.7/arch/x86/include/asm/mman.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/mman.h 2011-04-28 19:34:14.000000000 -0400
+@@ -5,4 +5,14 @@
+
+ #include <asm-generic/mman.h>
+
++#ifdef __KERNEL__
++#ifndef __ASSEMBLY__
++#ifdef CONFIG_X86_32
++#define arch_mmap_check i386_mmap_check
++int i386_mmap_check(unsigned long addr, unsigned long len,
++ unsigned long flags);
++#endif
++#endif
++#endif
++
+ #endif /* _ASM_X86_MMAN_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/mmu_context.h linux-2.6.38.7/arch/x86/include/asm/mmu_context.h
+--- linux-2.6.38.7/arch/x86/include/asm/mmu_context.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/mmu_context.h 2011-04-28 19:34:14.000000000 -0400
+@@ -24,6 +24,21 @@ void destroy_context(struct mm_struct *m
+
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ unsigned int i;
++ pgd_t *pgd;
++
++ pax_open_kernel();
++ pgd = get_cpu_pgd(smp_processor_id());
++ for (i = USER_PGD_PTRS; i < 2 * USER_PGD_PTRS; ++i)
++ if (paravirt_enabled())
++ set_pgd(pgd+i, native_make_pgd(0));
++ else
++ pgd[i] = native_make_pgd(0);
++ pax_close_kernel();
++#endif
++
+ #ifdef CONFIG_SMP
+ if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
+ percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
+@@ -34,16 +49,30 @@ static inline void switch_mm(struct mm_s
+ struct task_struct *tsk)
+ {
+ unsigned cpu = smp_processor_id();
++#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
++ int tlbstate = TLBSTATE_OK;
++#endif
+
+ if (likely(prev != next)) {
+ #ifdef CONFIG_SMP
++#ifdef CONFIG_X86_32
++ tlbstate = percpu_read(cpu_tlbstate.state);
++#endif
+ percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+ percpu_write(cpu_tlbstate.active_mm, next);
+ #endif
+ cpumask_set_cpu(cpu, mm_cpumask(next));
+
+ /* Re-load page tables */
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ pax_open_kernel();
++ __clone_user_pgds(get_cpu_pgd(cpu), next->pgd, USER_PGD_PTRS);
++ __shadow_user_pgds(get_cpu_pgd(cpu) + USER_PGD_PTRS, next->pgd, USER_PGD_PTRS);
++ pax_close_kernel();
++ load_cr3(get_cpu_pgd(cpu));
++#else
+ load_cr3(next->pgd);
++#endif
+
+ /* stop flush ipis for the previous mm */
+ cpumask_clear_cpu(cpu, mm_cpumask(prev));
+@@ -53,9 +82,38 @@ static inline void switch_mm(struct mm_s
+ */
+ if (unlikely(prev->context.ldt != next->context.ldt))
+ load_LDT_nolock(&next->context);
+- }
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
++ if (!(__supported_pte_mask & _PAGE_NX)) {
++ smp_mb__before_clear_bit();
++ cpu_clear(cpu, prev->context.cpu_user_cs_mask);
++ smp_mb__after_clear_bit();
++ cpu_set(cpu, next->context.cpu_user_cs_mask);
++ }
++#endif
++
++#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC))
++ if (unlikely(prev->context.user_cs_base != next->context.user_cs_base ||
++ prev->context.user_cs_limit != next->context.user_cs_limit))
++ set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu);
+ #ifdef CONFIG_SMP
++ else if (unlikely(tlbstate != TLBSTATE_OK))
++ set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu);
++#endif
++#endif
++
++ }
+ else {
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ pax_open_kernel();
++ __clone_user_pgds(get_cpu_pgd(cpu), next->pgd, USER_PGD_PTRS);
++ __shadow_user_pgds(get_cpu_pgd(cpu) + USER_PGD_PTRS, next->pgd, USER_PGD_PTRS);
++ pax_close_kernel();
++ load_cr3(get_cpu_pgd(cpu));
++#endif
++
++#ifdef CONFIG_SMP
+ percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+ BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next);
+
+@@ -64,11 +122,28 @@ static inline void switch_mm(struct mm_s
+ * tlb flush IPI delivery. We must reload CR3
+ * to make sure to use no freed page tables.
+ */
++
++#ifndef CONFIG_PAX_PER_CPU_PGD
+ load_cr3(next->pgd);
++#endif
++
+ load_LDT_nolock(&next->context);
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC)
++ if (!(__supported_pte_mask & _PAGE_NX))
++ cpu_set(cpu, next->context.cpu_user_cs_mask);
++#endif
++
++#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC))
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (!((next->pax_flags & MF_PAX_PAGEEXEC) && (__supported_pte_mask & _PAGE_NX)))
++#endif
++ set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu);
++#endif
++
+ }
+- }
+ #endif
++ }
+ }
+
+ #define activate_mm(prev, next) \
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/mmu.h linux-2.6.38.7/arch/x86/include/asm/mmu.h
+--- linux-2.6.38.7/arch/x86/include/asm/mmu.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/mmu.h 2011-04-28 19:34:14.000000000 -0400
+@@ -9,10 +9,23 @@
+ * we put the segment information here.
+ */
+ typedef struct {
+- void *ldt;
++ struct desc_struct *ldt;
+ int size;
+ struct mutex lock;
+- void *vdso;
++ unsigned long vdso;
++
++#ifdef CONFIG_X86_32
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++ unsigned long user_cs_base;
++ unsigned long user_cs_limit;
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
++ cpumask_t cpu_user_cs_mask;
++#endif
++
++#endif
++#endif
++
+ } mm_context_t;
+
+ #ifdef CONFIG_SMP
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/module.h linux-2.6.38.7/arch/x86/include/asm/module.h
+--- linux-2.6.38.7/arch/x86/include/asm/module.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/module.h 2011-04-28 19:34:14.000000000 -0400
+@@ -5,6 +5,7 @@
+
+ #ifdef CONFIG_X86_64
+ /* X86_64 does not define MODULE_PROC_FAMILY */
++#define MODULE_PROC_FAMILY ""
+ #elif defined CONFIG_M386
+ #define MODULE_PROC_FAMILY "386 "
+ #elif defined CONFIG_M486
+@@ -59,8 +60,30 @@
+ #error unknown processor family
+ #endif
+
+-#ifdef CONFIG_X86_32
+-# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++#define MODULE_PAX_UDEREF "UDEREF "
++#else
++#define MODULE_PAX_UDEREF ""
++#endif
++
++#ifdef CONFIG_PAX_KERNEXEC
++#define MODULE_PAX_KERNEXEC "KERNEXEC "
++#else
++#define MODULE_PAX_KERNEXEC ""
+ #endif
+
++#ifdef CONFIG_PAX_REFCOUNT
++#define MODULE_PAX_REFCOUNT "REFCOUNT "
++#else
++#define MODULE_PAX_REFCOUNT ""
++#endif
++
++#ifdef CONFIG_GRKERNSEC
++#define MODULE_GRSEC "GRSECURITY "
++#else
++#define MODULE_GRSEC ""
++#endif
++
++#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_GRSEC MODULE_PAX_KERNEXEC MODULE_PAX_UDEREF MODULE_PAX_REFCOUNT
++
+ #endif /* _ASM_X86_MODULE_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/page_64_types.h linux-2.6.38.7/arch/x86/include/asm/page_64_types.h
+--- linux-2.6.38.7/arch/x86/include/asm/page_64_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/page_64_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -56,7 +56,7 @@ void copy_page(void *to, void *from);
+
+ /* duplicated to the one in bootmem.h */
+ extern unsigned long max_pfn;
+-extern unsigned long phys_base;
++extern const unsigned long phys_base;
+
+ extern unsigned long __phys_addr(unsigned long);
+ #define __phys_reloc_hide(x) (x)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/paravirt.h linux-2.6.38.7/arch/x86/include/asm/paravirt.h
+--- linux-2.6.38.7/arch/x86/include/asm/paravirt.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/paravirt.h 2011-04-28 19:34:14.000000000 -0400
+@@ -739,6 +739,21 @@ static inline void __set_fixmap(unsigned
+ pv_mmu_ops.set_fixmap(idx, phys, flags);
+ }
+
++#ifdef CONFIG_PAX_KERNEXEC
++static inline unsigned long pax_open_kernel(void)
++{
++ return PVOP_CALL0(unsigned long, pv_mmu_ops.pax_open_kernel);
++}
++
++static inline unsigned long pax_close_kernel(void)
++{
++ return PVOP_CALL0(unsigned long, pv_mmu_ops.pax_close_kernel);
++}
++#else
++static inline unsigned long pax_open_kernel(void) { return 0; }
++static inline unsigned long pax_close_kernel(void) { return 0; }
++#endif
++
+ #if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_SPINLOCKS)
+
+ static inline int arch_spin_is_locked(struct arch_spinlock *lock)
+@@ -955,7 +970,7 @@ extern void default_banner(void);
+
+ #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4)
+ #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4)
+-#define PARA_INDIRECT(addr) *%cs:addr
++#define PARA_INDIRECT(addr) *%ss:addr
+ #endif
+
+ #define INTERRUPT_RETURN \
+@@ -1032,6 +1047,21 @@ extern void default_banner(void);
+ PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \
+ CLBR_NONE, \
+ jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
++
++#define GET_CR0_INTO_RDI \
++ call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \
++ mov %rax,%rdi
++
++#define SET_RDI_INTO_CR0 \
++ call PARA_INDIRECT(pv_cpu_ops+PV_CPU_write_cr0)
++
++#define GET_CR3_INTO_RDI \
++ call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr3); \
++ mov %rax,%rdi
++
++#define SET_RDI_INTO_CR3 \
++ call PARA_INDIRECT(pv_mmu_ops+PV_MMU_write_cr3)
++
+ #endif /* CONFIG_X86_32 */
+
+ #endif /* __ASSEMBLY__ */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/paravirt_types.h linux-2.6.38.7/arch/x86/include/asm/paravirt_types.h
+--- linux-2.6.38.7/arch/x86/include/asm/paravirt_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/paravirt_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -317,6 +317,12 @@ struct pv_mmu_ops {
+ an mfn. We can tell which is which from the index. */
+ void (*set_fixmap)(unsigned /* enum fixed_addresses */ idx,
+ phys_addr_t phys, pgprot_t flags);
++
++#ifdef CONFIG_PAX_KERNEXEC
++ unsigned long (*pax_open_kernel)(void);
++ unsigned long (*pax_close_kernel)(void);
++#endif
++
+ };
+
+ struct arch_spinlock;
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pci_x86.h linux-2.6.38.7/arch/x86/include/asm/pci_x86.h
+--- linux-2.6.38.7/arch/x86/include/asm/pci_x86.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pci_x86.h 2011-04-28 19:34:14.000000000 -0400
+@@ -93,16 +93,16 @@ extern int (*pcibios_enable_irq)(struct
+ extern void (*pcibios_disable_irq)(struct pci_dev *dev);
+
+ struct pci_raw_ops {
+- int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
++ int (* const read)(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 *val);
+- int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
++ int (* const write)(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 val);
+ };
+
+-extern struct pci_raw_ops *raw_pci_ops;
+-extern struct pci_raw_ops *raw_pci_ext_ops;
++extern const struct pci_raw_ops *raw_pci_ops;
++extern const struct pci_raw_ops *raw_pci_ext_ops;
+
+-extern struct pci_raw_ops pci_direct_conf1;
++extern const struct pci_raw_ops pci_direct_conf1;
+ extern bool port_cf9_safe;
+
+ /* arch_initcall level */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgalloc.h linux-2.6.38.7/arch/x86/include/asm/pgalloc.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgalloc.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgalloc.h 2011-04-28 19:34:14.000000000 -0400
+@@ -63,6 +63,13 @@ static inline void pmd_populate_kernel(s
+ pmd_t *pmd, pte_t *pte)
+ {
+ paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
++ set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE));
++}
++
++static inline void pmd_populate_user(struct mm_struct *mm,
++ pmd_t *pmd, pte_t *pte)
++{
++ paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
+ set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
+ }
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgtable-2level.h linux-2.6.38.7/arch/x86/include/asm/pgtable-2level.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgtable-2level.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgtable-2level.h 2011-04-28 19:34:14.000000000 -0400
+@@ -18,7 +18,9 @@ static inline void native_set_pte(pte_t
+
+ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+ {
++ pax_open_kernel();
+ *pmdp = pmd;
++ pax_close_kernel();
+ }
+
+ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgtable_32.h linux-2.6.38.7/arch/x86/include/asm/pgtable_32.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgtable_32.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgtable_32.h 2011-04-28 19:34:14.000000000 -0400
+@@ -25,9 +25,6 @@
+ struct mm_struct;
+ struct vm_area_struct;
+
+-extern pgd_t swapper_pg_dir[1024];
+-extern pgd_t initial_page_table[1024];
+-
+ static inline void pgtable_cache_init(void) { }
+ static inline void check_pgt_cache(void) { }
+ void paging_init(void);
+@@ -48,6 +45,12 @@ extern void set_pmd_pfn(unsigned long, u
+ # include <asm/pgtable-2level.h>
+ #endif
+
++extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
++extern pgd_t initial_page_table[PTRS_PER_PGD];
++#ifdef CONFIG_X86_PAE
++extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD];
++#endif
++
+ #if defined(CONFIG_HIGHPTE)
+ #define pte_offset_map(dir, address) \
+ ((pte_t *)kmap_atomic(pmd_page(*(dir))) + \
+@@ -62,7 +65,9 @@ extern void set_pmd_pfn(unsigned long, u
+ /* Clear a kernel PTE and flush it from the TLB */
+ #define kpte_clear_flush(ptep, vaddr) \
+ do { \
++ pax_open_kernel(); \
+ pte_clear(&init_mm, (vaddr), (ptep)); \
++ pax_close_kernel(); \
+ __flush_tlb_one((vaddr)); \
+ } while (0)
+
+@@ -74,6 +79,9 @@ do { \
+
+ #endif /* !__ASSEMBLY__ */
+
++#define HAVE_ARCH_UNMAPPED_AREA
++#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
++
+ /*
+ * kern_addr_valid() is (1) for FLATMEM and (0) for
+ * SPARSEMEM and DISCONTIGMEM
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgtable_32_types.h linux-2.6.38.7/arch/x86/include/asm/pgtable_32_types.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgtable_32_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgtable_32_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -8,7 +8,7 @@
+ */
+ #ifdef CONFIG_X86_PAE
+ # include <asm/pgtable-3level_types.h>
+-# define PMD_SIZE (1UL << PMD_SHIFT)
++# define PMD_SIZE (_AC(1, UL) << PMD_SHIFT)
+ # define PMD_MASK (~(PMD_SIZE - 1))
+ #else
+ # include <asm/pgtable-2level_types.h>
+@@ -46,6 +46,19 @@ extern bool __vmalloc_start_set; /* set
+ # define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE)
+ #endif
+
++#ifdef CONFIG_PAX_KERNEXEC
++#ifndef __ASSEMBLY__
++extern unsigned char MODULES_EXEC_VADDR[];
++extern unsigned char MODULES_EXEC_END[];
++#endif
++#include <asm/boot.h>
++#define ktla_ktva(addr) (addr + LOAD_PHYSICAL_ADDR + PAGE_OFFSET)
++#define ktva_ktla(addr) (addr - LOAD_PHYSICAL_ADDR - PAGE_OFFSET)
++#else
++#define ktla_ktva(addr) (addr)
++#define ktva_ktla(addr) (addr)
++#endif
++
+ #define MODULES_VADDR VMALLOC_START
+ #define MODULES_END VMALLOC_END
+ #define MODULES_LEN (MODULES_VADDR - MODULES_END)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgtable-3level.h linux-2.6.38.7/arch/x86/include/asm/pgtable-3level.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgtable-3level.h 2011-04-18 17:27:13.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgtable-3level.h 2011-04-28 19:34:14.000000000 -0400
+@@ -38,12 +38,16 @@ static inline void native_set_pte_atomic
+
+ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+ {
++ pax_open_kernel();
+ set_64bit((unsigned long long *)(pmdp), native_pmd_val(pmd));
++ pax_close_kernel();
+ }
+
+ static inline void native_set_pud(pud_t *pudp, pud_t pud)
+ {
++ pax_open_kernel();
+ set_64bit((unsigned long long *)(pudp), native_pud_val(pud));
++ pax_close_kernel();
+ }
+
+ /*
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgtable_64.h linux-2.6.38.7/arch/x86/include/asm/pgtable_64.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgtable_64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgtable_64.h 2011-04-28 19:34:14.000000000 -0400
+@@ -16,10 +16,13 @@
+
+ extern pud_t level3_kernel_pgt[512];
+ extern pud_t level3_ident_pgt[512];
++extern pud_t level3_vmalloc_pgt[512];
++extern pud_t level3_vmemmap_pgt[512];
++extern pud_t level2_vmemmap_pgt[512];
+ extern pmd_t level2_kernel_pgt[512];
+ extern pmd_t level2_fixmap_pgt[512];
+-extern pmd_t level2_ident_pgt[512];
+-extern pgd_t init_level4_pgt[];
++extern pmd_t level2_ident_pgt[512*2];
++extern pgd_t init_level4_pgt[512];
+
+ #define swapper_pg_dir init_level4_pgt
+
+@@ -61,7 +64,9 @@ static inline void native_set_pte_atomic
+
+ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+ {
++ pax_open_kernel();
+ *pmdp = pmd;
++ pax_close_kernel();
+ }
+
+ static inline void native_pmd_clear(pmd_t *pmd)
+@@ -107,7 +112,9 @@ static inline void native_pud_clear(pud_
+
+ static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd)
+ {
++ pax_open_kernel();
+ *pgdp = pgd;
++ pax_close_kernel();
+ }
+
+ static inline void native_pgd_clear(pgd_t *pgd)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgtable_64_types.h linux-2.6.38.7/arch/x86/include/asm/pgtable_64_types.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgtable_64_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgtable_64_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -59,5 +59,10 @@ typedef struct { pteval_t pte; } pte_t;
+ #define MODULES_VADDR _AC(0xffffffffa0000000, UL)
+ #define MODULES_END _AC(0xffffffffff000000, UL)
+ #define MODULES_LEN (MODULES_END - MODULES_VADDR)
++#define MODULES_EXEC_VADDR MODULES_VADDR
++#define MODULES_EXEC_END MODULES_END
++
++#define ktla_ktva(addr) (addr)
++#define ktva_ktla(addr) (addr)
+
+ #endif /* _ASM_X86_PGTABLE_64_DEFS_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgtable.h linux-2.6.38.7/arch/x86/include/asm/pgtable.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgtable.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgtable.h 2011-04-28 19:34:14.000000000 -0400
+@@ -81,12 +81,51 @@ extern struct mm_struct *pgd_page_get_mm
+
+ #define arch_end_context_switch(prev) do {} while(0)
+
++#define pax_open_kernel() native_pax_open_kernel()
++#define pax_close_kernel() native_pax_close_kernel()
+ #endif /* CONFIG_PARAVIRT */
+
++#define __HAVE_ARCH_PAX_OPEN_KERNEL
++#define __HAVE_ARCH_PAX_CLOSE_KERNEL
++
++#ifdef CONFIG_PAX_KERNEXEC
++static inline unsigned long native_pax_open_kernel(void)
++{
++ unsigned long cr0;
++
++ preempt_disable();
++ barrier();
++ cr0 = read_cr0() ^ X86_CR0_WP;
++ BUG_ON(unlikely(cr0 & X86_CR0_WP));
++ write_cr0(cr0);
++ return cr0 ^ X86_CR0_WP;
++}
++
++static inline unsigned long native_pax_close_kernel(void)
++{
++ unsigned long cr0;
++
++ cr0 = read_cr0() ^ X86_CR0_WP;
++ BUG_ON(unlikely(!(cr0 & X86_CR0_WP)));
++ write_cr0(cr0);
++ barrier();
++ preempt_enable_no_resched();
++ return cr0 ^ X86_CR0_WP;
++}
++#else
++static inline unsigned long native_pax_open_kernel(void) { return 0; }
++static inline unsigned long native_pax_close_kernel(void) { return 0; }
++#endif
++
+ /*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
++static inline int pte_user(pte_t pte)
++{
++ return pte_val(pte) & _PAGE_USER;
++}
++
+ static inline int pte_dirty(pte_t pte)
+ {
+ return pte_flags(pte) & _PAGE_DIRTY;
+@@ -196,9 +235,29 @@ static inline pte_t pte_wrprotect(pte_t
+ return pte_clear_flags(pte, _PAGE_RW);
+ }
+
++static inline pte_t pte_mkread(pte_t pte)
++{
++ return __pte(pte_val(pte) | _PAGE_USER);
++}
++
+ static inline pte_t pte_mkexec(pte_t pte)
+ {
+- return pte_clear_flags(pte, _PAGE_NX);
++#ifdef CONFIG_X86_PAE
++ if (__supported_pte_mask & _PAGE_NX)
++ return pte_clear_flags(pte, _PAGE_NX);
++ else
++#endif
++ return pte_set_flags(pte, _PAGE_USER);
++}
++
++static inline pte_t pte_exprotect(pte_t pte)
++{
++#ifdef CONFIG_X86_PAE
++ if (__supported_pte_mask & _PAGE_NX)
++ return pte_set_flags(pte, _PAGE_NX);
++ else
++#endif
++ return pte_clear_flags(pte, _PAGE_USER);
+ }
+
+ static inline pte_t pte_mkdirty(pte_t pte)
+@@ -390,6 +449,15 @@ pte_t *populate_extra_pte(unsigned long
+ #endif
+
+ #ifndef __ASSEMBLY__
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++extern pgd_t cpu_pgd[NR_CPUS][PTRS_PER_PGD];
++static inline pgd_t *get_cpu_pgd(unsigned int cpu)
++{
++ return cpu_pgd[cpu];
++}
++#endif
++
+ #include <linux/mm_types.h>
+
+ static inline int pte_none(pte_t pte)
+@@ -560,7 +628,7 @@ static inline pud_t *pud_offset(pgd_t *p
+
+ static inline int pgd_bad(pgd_t pgd)
+ {
+- return (pgd_flags(pgd) & ~_PAGE_USER) != _KERNPG_TABLE;
++ return (pgd_flags(pgd) & ~(_PAGE_USER | _PAGE_NX)) != _KERNPG_TABLE;
+ }
+
+ static inline int pgd_none(pgd_t pgd)
+@@ -583,7 +651,12 @@ static inline int pgd_none(pgd_t pgd)
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
+-#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
++#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++#define pgd_offset_cpu(cpu, address) (get_cpu_pgd(cpu) + pgd_index(address))
++#endif
++
+ /*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+@@ -594,6 +667,20 @@ static inline int pgd_none(pgd_t pgd)
+ #define KERNEL_PGD_BOUNDARY pgd_index(PAGE_OFFSET)
+ #define KERNEL_PGD_PTRS (PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
+
++#ifdef CONFIG_X86_32
++#define USER_PGD_PTRS KERNEL_PGD_BOUNDARY
++#else
++#define TASK_SIZE_MAX_SHIFT CONFIG_TASK_SIZE_MAX_SHIFT
++#define USER_PGD_PTRS (_AC(1,UL) << (TASK_SIZE_MAX_SHIFT - PGDIR_SHIFT))
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++#define PAX_USER_SHADOW_BASE (_AC(1,UL) << TASK_SIZE_MAX_SHIFT)
++#else
++#define PAX_USER_SHADOW_BASE (_AC(0,UL))
++#endif
++
++#endif
++
+ #ifndef __ASSEMBLY__
+
+ extern int direct_gbpages;
+@@ -758,11 +845,23 @@ static inline void pmdp_set_wrprotect(st
+ * dst and src can be on the same page, but the range must not overlap,
+ * and must not cross a page boundary.
+ */
+-static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
++static inline void clone_pgd_range(pgd_t *dst, const pgd_t *src, int count)
+ {
+- memcpy(dst, src, count * sizeof(pgd_t));
++ pax_open_kernel();
++ while (count--)
++ *dst++ = *src++;
++ pax_close_kernel();
+ }
+
++#ifdef CONFIG_PAX_PER_CPU_PGD
++extern void __clone_user_pgds(pgd_t *dst, const pgd_t *src, int count);
++#endif
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++extern void __shadow_user_pgds(pgd_t *dst, const pgd_t *src, int count);
++#else
++static inline void __shadow_user_pgds(pgd_t *dst, const pgd_t *src, int count) {}
++#endif
+
+ #include <asm-generic/pgtable.h>
+ #endif /* __ASSEMBLY__ */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/pgtable_types.h linux-2.6.38.7/arch/x86/include/asm/pgtable_types.h
+--- linux-2.6.38.7/arch/x86/include/asm/pgtable_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/pgtable_types.h 2011-04-28 19:34:14.000000000 -0400
+@@ -16,13 +16,12 @@
+ #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */
+ #define _PAGE_BIT_PAT 7 /* on 4KB pages */
+ #define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */
+-#define _PAGE_BIT_UNUSED1 9 /* available for programmer */
++#define _PAGE_BIT_SPECIAL 9 /* special mappings, no associated struct page */
+ #define _PAGE_BIT_IOMAP 10 /* flag used to indicate IO mapping */
+ #define _PAGE_BIT_HIDDEN 11 /* hidden by kmemcheck */
+ #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */
+-#define _PAGE_BIT_SPECIAL _PAGE_BIT_UNUSED1
+-#define _PAGE_BIT_CPA_TEST _PAGE_BIT_UNUSED1
+-#define _PAGE_BIT_SPLITTING _PAGE_BIT_UNUSED1 /* only valid on a PSE pmd */
++#define _PAGE_BIT_CPA_TEST _PAGE_BIT_SPECIAL
++#define _PAGE_BIT_SPLITTING _PAGE_BIT_SPECIAL /* only valid on a PSE pmd */
+ #define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */
+
+ /* If _PAGE_BIT_PRESENT is clear, we use these: */
+@@ -40,7 +39,6 @@
+ #define _PAGE_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_DIRTY)
+ #define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE)
+ #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
+-#define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
+ #define _PAGE_IOMAP (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
+ #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT)
+ #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
+@@ -57,8 +55,10 @@
+
+ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+ #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX)
+-#else
++#elif defined(CONFIG_KMEMCHECK)
+ #define _PAGE_NX (_AT(pteval_t, 0))
++#else
++#define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN)
+ #endif
+
+ #define _PAGE_FILE (_AT(pteval_t, 1) << _PAGE_BIT_FILE)
+@@ -96,6 +96,9 @@
+ #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+ _PAGE_ACCESSED)
+
++#define PAGE_READONLY_NOEXEC PAGE_READONLY
++#define PAGE_SHARED_NOEXEC PAGE_SHARED
++
+ #define __PAGE_KERNEL_EXEC \
+ (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_GLOBAL)
+ #define __PAGE_KERNEL (__PAGE_KERNEL_EXEC | _PAGE_NX)
+@@ -106,8 +109,8 @@
+ #define __PAGE_KERNEL_WC (__PAGE_KERNEL | _PAGE_CACHE_WC)
+ #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
+ #define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD)
+-#define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER)
+-#define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RO | _PAGE_USER)
++#define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_RO | _PAGE_PCD | _PAGE_PWT | _PAGE_USER)
+ #define __PAGE_KERNEL_LARGE (__PAGE_KERNEL | _PAGE_PSE)
+ #define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
+ #define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE)
+@@ -166,8 +169,8 @@
+ * bits are combined, this will alow user to access the high address mapped
+ * VDSO in the presence of CONFIG_COMPAT_VDSO
+ */
+-#define PTE_IDENT_ATTR 0x003 /* PRESENT+RW */
+-#define PDE_IDENT_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */
++#define PTE_IDENT_ATTR 0x063 /* PRESENT+RW+DIRTY+ACCESSED */
++#define PDE_IDENT_ATTR 0x063 /* PRESENT+RW+DIRTY+ACCESSED */
+ #define PGD_IDENT_ATTR 0x001 /* PRESENT (no other attributes) */
+ #endif
+
+@@ -205,7 +208,17 @@ static inline pgdval_t pgd_flags(pgd_t p
+ {
+ return native_pgd_val(pgd) & PTE_FLAGS_MASK;
+ }
++#endif
+
++#if PAGETABLE_LEVELS == 3
++#include <asm-generic/pgtable-nopud.h>
++#endif
++
++#if PAGETABLE_LEVELS == 2
++#include <asm-generic/pgtable-nopmd.h>
++#endif
++
++#ifndef __ASSEMBLY__
+ #if PAGETABLE_LEVELS > 3
+ typedef struct { pudval_t pud; } pud_t;
+
+@@ -219,8 +232,6 @@ static inline pudval_t native_pud_val(pu
+ return pud.pud;
+ }
+ #else
+-#include <asm-generic/pgtable-nopud.h>
+-
+ static inline pudval_t native_pud_val(pud_t pud)
+ {
+ return native_pgd_val(pud.pgd);
+@@ -240,8 +251,6 @@ static inline pmdval_t native_pmd_val(pm
+ return pmd.pmd;
+ }
+ #else
+-#include <asm-generic/pgtable-nopmd.h>
+-
+ static inline pmdval_t native_pmd_val(pmd_t pmd)
+ {
+ return native_pgd_val(pmd.pud.pgd);
+@@ -281,7 +290,6 @@ typedef struct page *pgtable_t;
+
+ extern pteval_t __supported_pte_mask;
+ extern void set_nx(void);
+-extern int nx_enabled;
+
+ #define pgprot_writecombine pgprot_writecombine
+ extern pgprot_t pgprot_writecombine(pgprot_t prot);
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/processor.h linux-2.6.38.7/arch/x86/include/asm/processor.h
+--- linux-2.6.38.7/arch/x86/include/asm/processor.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/processor.h 2011-05-11 18:34:57.000000000 -0400
+@@ -270,7 +270,7 @@ struct tss_struct {
+
+ } ____cacheline_aligned;
+
+-DECLARE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss);
++extern struct tss_struct init_tss[NR_CPUS];
+
+ /*
+ * Save the original ist values for checking stack pointers during debugging
+@@ -864,11 +864,18 @@ static inline void spin_lock_prefetch(co
+ */
+ #define TASK_SIZE PAGE_OFFSET
+ #define TASK_SIZE_MAX TASK_SIZE
++
++#ifdef CONFIG_PAX_SEGMEXEC
++#define SEGMEXEC_TASK_SIZE (TASK_SIZE / 2)
++#define STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?SEGMEXEC_TASK_SIZE:TASK_SIZE)
++#else
+ #define STACK_TOP TASK_SIZE
+-#define STACK_TOP_MAX STACK_TOP
++#endif
++
++#define STACK_TOP_MAX TASK_SIZE
+
+ #define INIT_THREAD { \
+- .sp0 = sizeof(init_stack) + (long)&init_stack, \
++ .sp0 = sizeof(init_stack) + (long)&init_stack - 8, \
+ .vm86_info = NULL, \
+ .sysenter_cs = __KERNEL_CS, \
+ .io_bitmap_ptr = NULL, \
+@@ -882,7 +889,7 @@ static inline void spin_lock_prefetch(co
+ */
+ #define INIT_TSS { \
+ .x86_tss = { \
+- .sp0 = sizeof(init_stack) + (long)&init_stack, \
++ .sp0 = sizeof(init_stack) + (long)&init_stack - 8, \
+ .ss0 = __KERNEL_DS, \
+ .ss1 = __KERNEL_CS, \
+ .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
+@@ -893,11 +900,7 @@ static inline void spin_lock_prefetch(co
+ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+ #define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
+-#define KSTK_TOP(info) \
+-({ \
+- unsigned long *__ptr = (unsigned long *)(info); \
+- (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
+-})
++#define KSTK_TOP(info) ((container_of(info, struct task_struct, tinfo))->thread.sp0)
+
+ /*
+ * The below -8 is to reserve 8 bytes on top of the ring0 stack.
+@@ -912,7 +915,7 @@ extern unsigned long thread_saved_pc(str
+ #define task_pt_regs(task) \
+ ({ \
+ struct pt_regs *__regs__; \
+- __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
++ __regs__ = (struct pt_regs *)((task)->thread.sp0); \
+ __regs__ - 1; \
+ })
+
+@@ -922,13 +925,13 @@ extern unsigned long thread_saved_pc(str
+ /*
+ * User space process size. 47bits minus one guard page.
+ */
+-#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE)
++#define TASK_SIZE_MAX ((1UL << TASK_SIZE_MAX_SHIFT) - PAGE_SIZE)
+
+ /* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+ #define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \
+- 0xc0000000 : 0xFFFFe000)
++ 0xc0000000 : 0xFFFFf000)
+
+ #define TASK_SIZE (test_thread_flag(TIF_IA32) ? \
+ IA32_PAGE_OFFSET : TASK_SIZE_MAX)
+@@ -939,11 +942,11 @@ extern unsigned long thread_saved_pc(str
+ #define STACK_TOP_MAX TASK_SIZE_MAX
+
+ #define INIT_THREAD { \
+- .sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
++ .sp0 = (unsigned long)&init_stack + sizeof(init_stack) - 16 \
+ }
+
+ #define INIT_TSS { \
+- .x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
++ .x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) - 16 \
+ }
+
+ /*
+@@ -965,6 +968,10 @@ extern void start_thread(struct pt_regs
+ */
+ #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
+
++#ifdef CONFIG_PAX_SEGMEXEC
++#define SEGMEXEC_TASK_UNMAPPED_BASE (PAGE_ALIGN(SEGMEXEC_TASK_SIZE / 3))
++#endif
++
+ #define KSTK_EIP(task) (task_pt_regs(task)->ip)
+
+ /* Get/set a process' ability to use the timestamp counter instruction */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/ptrace.h linux-2.6.38.7/arch/x86/include/asm/ptrace.h
+--- linux-2.6.38.7/arch/x86/include/asm/ptrace.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/ptrace.h 2011-04-28 19:34:14.000000000 -0400
+@@ -152,28 +152,29 @@ static inline unsigned long regs_return_
+ }
+
+ /*
+- * user_mode_vm(regs) determines whether a register set came from user mode.
++ * user_mode(regs) determines whether a register set came from user mode.
+ * This is true if V8086 mode was enabled OR if the register set was from
+ * protected mode with RPL-3 CS value. This tricky test checks that with
+ * one comparison. Many places in the kernel can bypass this full check
+- * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
++ * if they have already ruled out V8086 mode, so user_mode_novm(regs) can
++ * be used.
+ */
+-static inline int user_mode(struct pt_regs *regs)
++static inline int user_mode_novm(struct pt_regs *regs)
+ {
+ #ifdef CONFIG_X86_32
+ return (regs->cs & SEGMENT_RPL_MASK) == USER_RPL;
+ #else
+- return !!(regs->cs & 3);
++ return !!(regs->cs & SEGMENT_RPL_MASK);
+ #endif
+ }
+
+-static inline int user_mode_vm(struct pt_regs *regs)
++static inline int user_mode(struct pt_regs *regs)
+ {
+ #ifdef CONFIG_X86_32
+ return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >=
+ USER_RPL;
+ #else
+- return user_mode(regs);
++ return user_mode_novm(regs);
+ #endif
+ }
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/reboot.h linux-2.6.38.7/arch/x86/include/asm/reboot.h
+--- linux-2.6.38.7/arch/x86/include/asm/reboot.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/reboot.h 2011-05-22 23:03:34.000000000 -0400
+@@ -6,19 +6,19 @@
+ struct pt_regs;
+
+ struct machine_ops {
+- void (*restart)(char *cmd);
+- void (*halt)(void);
+- void (*power_off)(void);
++ void (* __noreturn restart)(char *cmd);
++ void (* __noreturn halt)(void);
++ void (* __noreturn power_off)(void);
+ void (*shutdown)(void);
+ void (*crash_shutdown)(struct pt_regs *);
+- void (*emergency_restart)(void);
++ void (* __noreturn emergency_restart)(void);
+ };
+
+ extern struct machine_ops machine_ops;
+
+ void native_machine_crash_shutdown(struct pt_regs *regs);
+ void native_machine_shutdown(void);
+-void machine_real_restart(const unsigned char *code, int length);
++void machine_real_restart(const unsigned char *code, unsigned int length) __noreturn;
+
+ typedef void (*nmi_shootdown_cb)(int, struct die_args*);
+ void nmi_shootdown_cpus(nmi_shootdown_cb callback);
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/rwsem.h linux-2.6.38.7/arch/x86/include/asm/rwsem.h
+--- linux-2.6.38.7/arch/x86/include/asm/rwsem.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/rwsem.h 2011-04-28 19:34:14.000000000 -0400
+@@ -118,6 +118,14 @@ static inline void __down_read(struct rw
+ {
+ asm volatile("# beginning down_read\n\t"
+ LOCK_PREFIX _ASM_INC "(%1)\n\t"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX _ASM_DEC "(%1)\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ /* adds 0x00000001 */
+ " jns 1f\n"
+ " call call_rwsem_down_read_failed\n"
+@@ -139,6 +147,14 @@ static inline int __down_read_trylock(st
+ "1:\n\t"
+ " mov %1,%2\n\t"
+ " add %3,%2\n\t"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "sub %3,%2\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ " jle 2f\n\t"
+ LOCK_PREFIX " cmpxchg %2,%0\n\t"
+ " jnz 1b\n\t"
+@@ -158,6 +174,14 @@ static inline void __down_write_nested(s
+ rwsem_count_t tmp;
+ asm volatile("# beginning down_write\n\t"
+ LOCK_PREFIX " xadd %1,(%2)\n\t"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "mov %1,(%2)\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ /* adds 0xffff0001, returns the old value */
+ " test %1,%1\n\t"
+ /* was the count 0 before? */
+@@ -196,6 +220,14 @@ static inline void __up_read(struct rw_s
+ rwsem_count_t tmp;
+ asm volatile("# beginning __up_read\n\t"
+ LOCK_PREFIX " xadd %1,(%2)\n\t"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "mov %1,(%2)\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ /* subtracts 1, returns the old value */
+ " jns 1f\n\t"
+ " call call_rwsem_wake\n" /* expects old value in %edx */
+@@ -214,6 +246,14 @@ static inline void __up_write(struct rw_
+ rwsem_count_t tmp;
+ asm volatile("# beginning __up_write\n\t"
+ LOCK_PREFIX " xadd %1,(%2)\n\t"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "mov %1,(%2)\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ /* subtracts 0xffff0001, returns the old value */
+ " jns 1f\n\t"
+ " call call_rwsem_wake\n" /* expects old value in %edx */
+@@ -231,6 +271,14 @@ static inline void __downgrade_write(str
+ {
+ asm volatile("# beginning __downgrade_write\n\t"
+ LOCK_PREFIX _ASM_ADD "%2,(%1)\n\t"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX _ASM_SUB "%2,(%1)\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ /*
+ * transitions 0xZZZZ0001 -> 0xYYYY0001 (i386)
+ * 0xZZZZZZZZ00000001 -> 0xYYYYYYYY00000001 (x86_64)
+@@ -250,7 +298,15 @@ static inline void __downgrade_write(str
+ static inline void rwsem_atomic_add(rwsem_count_t delta,
+ struct rw_semaphore *sem)
+ {
+- asm volatile(LOCK_PREFIX _ASM_ADD "%1,%0"
++ asm volatile(LOCK_PREFIX _ASM_ADD "%1,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX _ASM_SUB "%1,%0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ : "+m" (sem->count)
+ : "er" (delta));
+ }
+@@ -263,7 +319,15 @@ static inline rwsem_count_t rwsem_atomic
+ {
+ rwsem_count_t tmp = delta;
+
+- asm volatile(LOCK_PREFIX "xadd %0,%1"
++ asm volatile(LOCK_PREFIX "xadd %0,%1\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "mov %0,%1\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ : "+r" (tmp), "+m" (sem->count)
+ : : "memory");
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/segment.h linux-2.6.38.7/arch/x86/include/asm/segment.h
+--- linux-2.6.38.7/arch/x86/include/asm/segment.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/segment.h 2011-04-28 19:34:14.000000000 -0400
+@@ -62,8 +62,8 @@
+ * 26 - ESPFIX small SS
+ * 27 - per-cpu [ offset to per-cpu data area ]
+ * 28 - stack_canary-20 [ for stack protector ]
+- * 29 - unused
+- * 30 - unused
++ * 29 - PCI BIOS CS
++ * 30 - PCI BIOS DS
+ * 31 - TSS for double fault handler
+ */
+ #define GDT_ENTRY_TLS_MIN 6
+@@ -77,6 +77,8 @@
+
+ #define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE+0)
+
++#define GDT_ENTRY_KERNEXEC_KERNEL_CS (4)
++
+ #define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE+1)
+
+ #define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE+4)
+@@ -102,6 +104,12 @@
+ #define __KERNEL_STACK_CANARY 0
+ #endif
+
++#define GDT_ENTRY_PCIBIOS_CS (GDT_ENTRY_KERNEL_BASE+17)
++#define __PCIBIOS_CS (GDT_ENTRY_PCIBIOS_CS * 8)
++
++#define GDT_ENTRY_PCIBIOS_DS (GDT_ENTRY_KERNEL_BASE+18)
++#define __PCIBIOS_DS (GDT_ENTRY_PCIBIOS_DS * 8)
++
+ #define GDT_ENTRY_DOUBLEFAULT_TSS 31
+
+ /*
+@@ -139,7 +147,7 @@
+ */
+
+ /* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
+-#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
++#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xFFFCU) == PNP_CS32 || ((x) & 0xFFFCU) == PNP_CS16)
+
+
+ #else
+@@ -163,6 +171,8 @@
+ #define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS * 8 + 3)
+ #define __USER32_DS __USER_DS
+
++#define GDT_ENTRY_KERNEXEC_KERNEL_CS 7
++
+ #define GDT_ENTRY_TSS 8 /* needs two entries */
+ #define GDT_ENTRY_LDT 10 /* needs two entries */
+ #define GDT_ENTRY_TLS_MIN 12
+@@ -183,6 +193,7 @@
+ #endif
+
+ #define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8)
++#define __KERNEXEC_KERNEL_CS (GDT_ENTRY_KERNEXEC_KERNEL_CS*8)
+ #define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
+ #define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8+3)
+ #define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8+3)
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/smp.h linux-2.6.38.7/arch/x86/include/asm/smp.h
+--- linux-2.6.38.7/arch/x86/include/asm/smp.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/smp.h 2011-04-28 19:34:14.000000000 -0400
+@@ -24,7 +24,7 @@ extern unsigned int num_processors;
+ DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map);
+ DECLARE_PER_CPU(cpumask_var_t, cpu_core_map);
+ DECLARE_PER_CPU(u16, cpu_llc_id);
+-DECLARE_PER_CPU(int, cpu_number);
++DECLARE_PER_CPU(unsigned int, cpu_number);
+
+ static inline struct cpumask *cpu_sibling_mask(int cpu)
+ {
+@@ -172,14 +172,8 @@ extern unsigned disabled_cpus __cpuinitd
+ extern int safe_smp_processor_id(void);
+
+ #elif defined(CONFIG_X86_64_SMP)
+-#define raw_smp_processor_id() (percpu_read(cpu_number))
+-
+-#define stack_smp_processor_id() \
+-({ \
+- struct thread_info *ti; \
+- __asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK)); \
+- ti->cpu; \
+-})
++#define raw_smp_processor_id() (percpu_read(cpu_number))
++#define stack_smp_processor_id() raw_smp_processor_id()
+ #define safe_smp_processor_id() smp_processor_id()
+
+ #endif
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/spinlock.h linux-2.6.38.7/arch/x86/include/asm/spinlock.h
+--- linux-2.6.38.7/arch/x86/include/asm/spinlock.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/spinlock.h 2011-04-28 19:34:14.000000000 -0400
+@@ -249,6 +249,14 @@ static inline int arch_write_can_lock(ar
+ static inline void arch_read_lock(arch_rwlock_t *rw)
+ {
+ asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX " addl $1,(%0)\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ "jns 1f\n"
+ "call __read_lock_failed\n\t"
+ "1:\n"
+@@ -258,6 +266,14 @@ static inline void arch_read_lock(arch_r
+ static inline void arch_write_lock(arch_rwlock_t *rw)
+ {
+ asm volatile(LOCK_PREFIX " subl %1,(%0)\n\t"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX " addl %1,(%0)\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ "jz 1f\n"
+ "call __write_lock_failed\n\t"
+ "1:\n"
+@@ -286,12 +302,29 @@ static inline int arch_write_trylock(arc
+
+ static inline void arch_read_unlock(arch_rwlock_t *rw)
+ {
+- asm volatile(LOCK_PREFIX "incl %0" :"+m" (rw->lock) : : "memory");
++ asm volatile(LOCK_PREFIX "incl %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "decl %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ :"+m" (rw->lock) : : "memory");
+ }
+
+ static inline void arch_write_unlock(arch_rwlock_t *rw)
+ {
+- asm volatile(LOCK_PREFIX "addl %1, %0"
++ asm volatile(LOCK_PREFIX "addl %1, %0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ LOCK_PREFIX "subl %1, %0\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
+ : "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory");
+ }
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/stackprotector.h linux-2.6.38.7/arch/x86/include/asm/stackprotector.h
+--- linux-2.6.38.7/arch/x86/include/asm/stackprotector.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/stackprotector.h 2011-04-28 19:34:14.000000000 -0400
+@@ -113,7 +113,7 @@ static inline void setup_stack_canary_se
+
+ static inline void load_stack_canary_segment(void)
+ {
+-#ifdef CONFIG_X86_32
++#if defined(CONFIG_X86_32) && !defined(CONFIG_PAX_MEMORY_UDEREF)
+ asm volatile ("mov %0, %%gs" : : "r" (0));
+ #endif
+ }
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/stacktrace.h linux-2.6.38.7/arch/x86/include/asm/stacktrace.h
+--- linux-2.6.38.7/arch/x86/include/asm/stacktrace.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/stacktrace.h 2011-04-28 19:34:14.000000000 -0400
+@@ -11,28 +11,20 @@
+
+ extern int kstack_depth_to_print;
+
+-struct thread_info;
++struct task_struct;
+ struct stacktrace_ops;
+
+-typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
+- unsigned long *stack,
+- unsigned long bp,
+- const struct stacktrace_ops *ops,
+- void *data,
+- unsigned long *end,
+- int *graph);
+-
+-extern unsigned long
+-print_context_stack(struct thread_info *tinfo,
+- unsigned long *stack, unsigned long bp,
+- const struct stacktrace_ops *ops, void *data,
+- unsigned long *end, int *graph);
+-
+-extern unsigned long
+-print_context_stack_bp(struct thread_info *tinfo,
+- unsigned long *stack, unsigned long bp,
+- const struct stacktrace_ops *ops, void *data,
+- unsigned long *end, int *graph);
++typedef unsigned long walk_stack_t(struct task_struct *task,
++ void *stack_start,
++ unsigned long *stack,
++ unsigned long bp,
++ const struct stacktrace_ops *ops,
++ void *data,
++ unsigned long *end,
++ int *graph);
++
++extern walk_stack_t print_context_stack;
++extern walk_stack_t print_context_stack_bp;
+
+ /* Generic stack tracer with callbacks */
+
+@@ -43,7 +35,7 @@ struct stacktrace_ops {
+ void (*address)(void *data, unsigned long address, int reliable);
+ /* On negative return stop dumping */
+ int (*stack)(void *data, char *name);
+- walk_stack_t walk_stack;
++ walk_stack_t *walk_stack;
+ };
+
+ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/system.h linux-2.6.38.7/arch/x86/include/asm/system.h
+--- linux-2.6.38.7/arch/x86/include/asm/system.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/system.h 2011-05-22 23:03:34.000000000 -0400
+@@ -131,7 +131,7 @@ do { \
+ "call __switch_to\n\t" \
+ "movq "__percpu_arg([current_task])",%%rsi\n\t" \
+ __switch_canary \
+- "movq %P[thread_info](%%rsi),%%r8\n\t" \
++ "movq "__percpu_arg([thread_info])",%%r8\n\t" \
+ "movq %%rax,%%rdi\n\t" \
+ "testl %[_tif_fork],%P[ti_flags](%%r8)\n\t" \
+ "jnz ret_from_fork\n\t" \
+@@ -142,7 +142,7 @@ do { \
+ [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
+ [ti_flags] "i" (offsetof(struct thread_info, flags)), \
+ [_tif_fork] "i" (_TIF_FORK), \
+- [thread_info] "i" (offsetof(struct task_struct, stack)), \
++ [thread_info] "m" (current_tinfo), \
+ [current_task] "m" (current_task) \
+ __switch_canary_iparam \
+ : "memory", "cc" __EXTRA_CLOBBER)
+@@ -202,7 +202,7 @@ static inline unsigned long get_limit(un
+ {
+ unsigned long __limit;
+ asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
+- return __limit + 1;
++ return __limit;
+ }
+
+ static inline void native_clts(void)
+@@ -342,12 +342,12 @@ void enable_hlt(void);
+
+ void cpu_idle_wait(void);
+
+-extern unsigned long arch_align_stack(unsigned long sp);
++#define arch_align_stack(x) ((x) & ~0xfUL)
+ extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+
+ void default_idle(void);
+
+-void stop_this_cpu(void *dummy);
++void stop_this_cpu(void *dummy) __noreturn;
+
+ /*
+ * Force strict CPU ordering.
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/thread_info.h linux-2.6.38.7/arch/x86/include/asm/thread_info.h
+--- linux-2.6.38.7/arch/x86/include/asm/thread_info.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/thread_info.h 2011-05-17 19:31:43.000000000 -0400
+@@ -10,6 +10,7 @@
+ #include <linux/compiler.h>
+ #include <asm/page.h>
+ #include <asm/types.h>
++#include <asm/percpu.h>
+
+ /*
+ * low level task data that entry.S needs immediate access to
+@@ -24,7 +25,6 @@ struct exec_domain;
+ #include <asm/atomic.h>
+
+ struct thread_info {
+- struct task_struct *task; /* main task structure */
+ struct exec_domain *exec_domain; /* execution domain */
+ __u32 flags; /* low level flags */
+ __u32 status; /* thread synchronous flags */
+@@ -34,18 +34,12 @@ struct thread_info {
+ mm_segment_t addr_limit;
+ struct restart_block restart_block;
+ void __user *sysenter_return;
+-#ifdef CONFIG_X86_32
+- unsigned long previous_esp; /* ESP of the previous stack in
+- case of nested (IRQ) stacks
+- */
+- __u8 supervisor_stack[0];
+-#endif
++ unsigned long lowest_stack;
+ int uaccess_err;
+ };
+
+-#define INIT_THREAD_INFO(tsk) \
++#define INIT_THREAD_INFO \
+ { \
+- .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+ .flags = 0, \
+ .cpu = 0, \
+@@ -56,7 +50,7 @@ struct thread_info {
+ }, \
+ }
+
+-#define init_thread_info (init_thread_union.thread_info)
++#define init_thread_info (init_thread_union.stack)
+ #define init_stack (init_thread_union.stack)
+
+ #else /* !__ASSEMBLY__ */
+@@ -164,6 +158,23 @@ struct thread_info {
+ #define alloc_thread_info(tsk) \
+ ((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER))
+
++#ifdef __ASSEMBLY__
++/* how to get the thread information struct from ASM */
++#define GET_THREAD_INFO(reg) \
++ mov PER_CPU_VAR(current_tinfo), reg
++
++/* use this one if reg already contains %esp */
++#define GET_THREAD_INFO_WITH_ESP(reg) GET_THREAD_INFO(reg)
++#else
++/* how to get the thread information struct from C */
++DECLARE_PER_CPU(struct thread_info *, current_tinfo);
++
++static __always_inline struct thread_info *current_thread_info(void)
++{
++ return percpu_read_stable(current_tinfo);
++}
++#endif
++
+ #ifdef CONFIG_X86_32
+
+ #define STACK_WARN (THREAD_SIZE/8)
+@@ -174,35 +185,13 @@ struct thread_info {
+ */
+ #ifndef __ASSEMBLY__
+
+-
+ /* how to get the current stack pointer from C */
+ register unsigned long current_stack_pointer asm("esp") __used;
+
+-/* how to get the thread information struct from C */
+-static inline struct thread_info *current_thread_info(void)
+-{
+- return (struct thread_info *)
+- (current_stack_pointer & ~(THREAD_SIZE - 1));
+-}
+-
+-#else /* !__ASSEMBLY__ */
+-
+-/* how to get the thread information struct from ASM */
+-#define GET_THREAD_INFO(reg) \
+- movl $-THREAD_SIZE, reg; \
+- andl %esp, reg
+-
+-/* use this one if reg already contains %esp */
+-#define GET_THREAD_INFO_WITH_ESP(reg) \
+- andl $-THREAD_SIZE, reg
+-
+ #endif
+
+ #else /* X86_32 */
+
+-#include <asm/percpu.h>
+-#define KERNEL_STACK_OFFSET (5*8)
+-
+ /*
+ * macros/functions for gaining access to the thread information structure
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+@@ -210,21 +199,8 @@ static inline struct thread_info *curren
+ #ifndef __ASSEMBLY__
+ DECLARE_PER_CPU(unsigned long, kernel_stack);
+
+-static inline struct thread_info *current_thread_info(void)
+-{
+- struct thread_info *ti;
+- ti = (void *)(percpu_read_stable(kernel_stack) +
+- KERNEL_STACK_OFFSET - THREAD_SIZE);
+- return ti;
+-}
+-
+-#else /* !__ASSEMBLY__ */
+-
+-/* how to get the thread information struct from ASM */
+-#define GET_THREAD_INFO(reg) \
+- movq PER_CPU_VAR(kernel_stack),reg ; \
+- subq $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg
+-
++/* how to get the current stack pointer from C */
++register unsigned long current_stack_pointer asm("rsp") __used;
+ #endif
+
+ #endif /* !X86_32 */
+@@ -260,5 +236,16 @@ extern void arch_task_cache_init(void);
+ extern void free_thread_info(struct thread_info *ti);
+ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
+ #define arch_task_cache_init arch_task_cache_init
++
++#define __HAVE_THREAD_FUNCTIONS
++#define task_thread_info(task) (&(task)->tinfo)
++#define task_stack_page(task) ((task)->stack)
++#define setup_thread_stack(p, org) do {} while (0)
++#define end_of_stack(p) ((unsigned long *)task_stack_page(p) + 1)
++
++#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
++extern struct task_struct *alloc_task_struct(void);
++extern void free_task_struct(struct task_struct *);
++
+ #endif
+ #endif /* _ASM_X86_THREAD_INFO_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/uaccess_32.h linux-2.6.38.7/arch/x86/include/asm/uaccess_32.h
+--- linux-2.6.38.7/arch/x86/include/asm/uaccess_32.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/uaccess_32.h 2011-05-16 21:47:08.000000000 -0400
+@@ -44,6 +44,11 @@ unsigned long __must_check __copy_from_u
+ static __always_inline unsigned long __must_check
+ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
+ {
++ pax_track_stack();
++
++ if ((long)n < 0)
++ return n;
++
+ if (__builtin_constant_p(n)) {
+ unsigned long ret;
+
+@@ -62,6 +67,8 @@ __copy_to_user_inatomic(void __user *to,
+ return ret;
+ }
+ }
++ if (!__builtin_constant_p(n))
++ check_object_size(from, n, true);
+ return __copy_to_user_ll(to, from, n);
+ }
+
+@@ -83,12 +90,16 @@ static __always_inline unsigned long __m
+ __copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
+ might_fault();
++
+ return __copy_to_user_inatomic(to, from, n);
+ }
+
+ static __always_inline unsigned long
+ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
+ {
++ if ((long)n < 0)
++ return n;
++
+ /* Avoid zeroing the tail if the copy fails..
+ * If 'n' is constant and 1, 2, or 4, we do still zero on a failure,
+ * but as the zeroing behaviour is only significant when n is not
+@@ -138,6 +149,12 @@ static __always_inline unsigned long
+ __copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
+ might_fault();
++
++ pax_track_stack();
++
++ if ((long)n < 0)
++ return n;
++
+ if (__builtin_constant_p(n)) {
+ unsigned long ret;
+
+@@ -153,6 +170,8 @@ __copy_from_user(void *to, const void __
+ return ret;
+ }
+ }
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
+ return __copy_from_user_ll(to, from, n);
+ }
+
+@@ -160,6 +179,10 @@ static __always_inline unsigned long __c
+ const void __user *from, unsigned long n)
+ {
+ might_fault();
++
++ if ((long)n < 0)
++ return n;
++
+ if (__builtin_constant_p(n)) {
+ unsigned long ret;
+
+@@ -182,15 +205,19 @@ static __always_inline unsigned long
+ __copy_from_user_inatomic_nocache(void *to, const void __user *from,
+ unsigned long n)
+ {
+- return __copy_from_user_ll_nocache_nozero(to, from, n);
+-}
++ if ((long)n < 0)
++ return n;
+
+-unsigned long __must_check copy_to_user(void __user *to,
+- const void *from, unsigned long n);
+-unsigned long __must_check _copy_from_user(void *to,
+- const void __user *from,
+- unsigned long n);
++ return __copy_from_user_ll_nocache_nozero(to, from, n);
++}
+
++extern void copy_to_user_overflow(void)
++#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
++ __compiletime_error("copy_to_user() buffer size is not provably correct")
++#else
++ __compiletime_warning("copy_to_user() buffer size is not provably correct")
++#endif
++;
+
+ extern void copy_from_user_overflow(void)
+ #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
+@@ -200,17 +227,61 @@ extern void copy_from_user_overflow(void
+ #endif
+ ;
+
+-static inline unsigned long __must_check copy_from_user(void *to,
+- const void __user *from,
+- unsigned long n)
++/**
++ * copy_to_user: - Copy a block of data into user space.
++ * @to: Destination address, in user space.
++ * @from: Source address, in kernel space.
++ * @n: Number of bytes to copy.
++ *
++ * Context: User context only. This function may sleep.
++ *
++ * Copy data from kernel space to user space.
++ *
++ * Returns number of bytes that could not be copied.
++ * On success, this will be zero.
++ */
++static inline unsigned long __must_check
++copy_to_user(void __user *to, const void *from, unsigned long n)
++{
++ int sz = __compiletime_object_size(from);
++
++ if (unlikely(sz != -1 && sz < n))
++ copy_to_user_overflow();
++ else if (access_ok(VERIFY_WRITE, to, n))
++ n = __copy_to_user(to, from, n);
++ return n;
++}
++
++/**
++ * copy_from_user: - Copy a block of data from user space.
++ * @to: Destination address, in kernel space.
++ * @from: Source address, in user space.
++ * @n: Number of bytes to copy.
++ *
++ * Context: User context only. This function may sleep.
++ *
++ * Copy data from user space to kernel space.
++ *
++ * Returns number of bytes that could not be copied.
++ * On success, this will be zero.
++ *
++ * If some data could not be copied, this function will pad the copied
++ * data to the requested size using zero bytes.
++ */
++static inline unsigned long __must_check
++copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
+ int sz = __compiletime_object_size(to);
+
+- if (likely(sz == -1 || sz >= n))
+- n = _copy_from_user(to, from, n);
+- else
++ if (unlikely(sz != -1 && sz < n))
+ copy_from_user_overflow();
+-
++ else if (access_ok(VERIFY_READ, from, n))
++ n = __copy_from_user(to, from, n);
++ else if ((long)n > 0) {
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
++ memset(to, 0, n);
++ }
+ return n;
+ }
+
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/uaccess_64.h linux-2.6.38.7/arch/x86/include/asm/uaccess_64.h
+--- linux-2.6.38.7/arch/x86/include/asm/uaccess_64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/uaccess_64.h 2011-05-16 21:47:08.000000000 -0400
+@@ -11,6 +11,9 @@
+ #include <asm/alternative.h>
+ #include <asm/cpufeature.h>
+ #include <asm/page.h>
++#include <asm/pgtable.h>
++
++#define set_fs(x) (current_thread_info()->addr_limit = (x))
+
+ /*
+ * Copy To/From Userspace
+@@ -37,26 +40,26 @@ copy_user_generic(void *to, const void *
+ return ret;
+ }
+
+-__must_check unsigned long
+-_copy_to_user(void __user *to, const void *from, unsigned len);
+-__must_check unsigned long
+-_copy_from_user(void *to, const void __user *from, unsigned len);
++static __always_inline __must_check unsigned long
++__copy_to_user(void __user *to, const void *from, unsigned len);
++static __always_inline __must_check unsigned long
++__copy_from_user(void *to, const void __user *from, unsigned len);
+ __must_check unsigned long
+ copy_in_user(void __user *to, const void __user *from, unsigned len);
+
+ static inline unsigned long __must_check copy_from_user(void *to,
+ const void __user *from,
+- unsigned long n)
++ unsigned n)
+ {
+- int sz = __compiletime_object_size(to);
+-
+ might_fault();
+- if (likely(sz == -1 || sz >= n))
+- n = _copy_from_user(to, from, n);
+-#ifdef CONFIG_DEBUG_VM
+- else
+- WARN(1, "Buffer overflow detected!\n");
+-#endif
++
++ if (access_ok(VERIFY_READ, from, n))
++ n = __copy_from_user(to, from, n);
++ else if ((int)n > 0) {
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
++ memset(to, 0, n);
++ }
+ return n;
+ }
+
+@@ -65,110 +68,198 @@ int copy_to_user(void __user *dst, const
+ {
+ might_fault();
+
+- return _copy_to_user(dst, src, size);
++ if (access_ok(VERIFY_WRITE, dst, size))
++ size = __copy_to_user(dst, src, size);
++ return size;
+ }
+
+ static __always_inline __must_check
+-int __copy_from_user(void *dst, const void __user *src, unsigned size)
++unsigned long __copy_from_user(void *dst, const void __user *src, unsigned size)
+ {
+- int ret = 0;
++ int sz = __compiletime_object_size(dst);
++ unsigned ret = 0;
+
+ might_fault();
+- if (!__builtin_constant_p(size))
+- return copy_user_generic(dst, (__force void *)src, size);
++
++ pax_track_stack();
++
++ if ((int)size < 0)
++ return size;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if (!__access_ok(VERIFY_READ, src, size))
++ return size;
++#endif
++
++ if (unlikely(sz != -1 && sz < size)) {
++#ifdef CONFIG_DEBUG_VM
++ WARN(1, "Buffer overflow detected!\n");
++#endif
++ return size;
++ }
++
++ if (!__builtin_constant_p(size)) {
++ check_object_size(dst, size, false);
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)src < PAX_USER_SHADOW_BASE)
++ src += PAX_USER_SHADOW_BASE;
++#endif
++
++ return copy_user_generic(dst, (__force const void *)src, size);
++ }
+ switch (size) {
+- case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src,
++ case 1:__get_user_asm(*(u8 *)dst, (const u8 __user *)src,
+ ret, "b", "b", "=q", 1);
+ return ret;
+- case 2:__get_user_asm(*(u16 *)dst, (u16 __user *)src,
++ case 2:__get_user_asm(*(u16 *)dst, (const u16 __user *)src,
+ ret, "w", "w", "=r", 2);
+ return ret;
+- case 4:__get_user_asm(*(u32 *)dst, (u32 __user *)src,
++ case 4:__get_user_asm(*(u32 *)dst, (const u32 __user *)src,
+ ret, "l", "k", "=r", 4);
+ return ret;
+- case 8:__get_user_asm(*(u64 *)dst, (u64 __user *)src,
++ case 8:__get_user_asm(*(u64 *)dst, (const u64 __user *)src,
+ ret, "q", "", "=r", 8);
+ return ret;
+ case 10:
+- __get_user_asm(*(u64 *)dst, (u64 __user *)src,
++ __get_user_asm(*(u64 *)dst, (const u64 __user *)src,
+ ret, "q", "", "=r", 10);
+ if (unlikely(ret))
+ return ret;
+ __get_user_asm(*(u16 *)(8 + (char *)dst),
+- (u16 __user *)(8 + (char __user *)src),
++ (const u16 __user *)(8 + (const char __user *)src),
+ ret, "w", "w", "=r", 2);
+ return ret;
+ case 16:
+- __get_user_asm(*(u64 *)dst, (u64 __user *)src,
++ __get_user_asm(*(u64 *)dst, (const u64 __user *)src,
+ ret, "q", "", "=r", 16);
+ if (unlikely(ret))
+ return ret;
+ __get_user_asm(*(u64 *)(8 + (char *)dst),
+- (u64 __user *)(8 + (char __user *)src),
++ (const u64 __user *)(8 + (const char __user *)src),
+ ret, "q", "", "=r", 8);
+ return ret;
+ default:
+- return copy_user_generic(dst, (__force void *)src, size);
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)src < PAX_USER_SHADOW_BASE)
++ src += PAX_USER_SHADOW_BASE;
++#endif
++
++ return copy_user_generic(dst, (__force const void *)src, size);
+ }
+ }
+
+ static __always_inline __must_check
+-int __copy_to_user(void __user *dst, const void *src, unsigned size)
++unsigned long __copy_to_user(void __user *dst, const void *src, unsigned size)
+ {
+- int ret = 0;
++ int sz = __compiletime_object_size(src);
++ unsigned ret = 0;
+
+ might_fault();
+- if (!__builtin_constant_p(size))
++
++ pax_track_stack();
++
++ if ((int)size < 0)
++ return size;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if (!__access_ok(VERIFY_WRITE, dst, size))
++ return size;
++#endif
++
++ if (unlikely(sz != -1 && sz < size)) {
++#ifdef CONFIG_DEBUG_VM
++ WARN(1, "Buffer overflow detected!\n");
++#endif
++ return size;
++ }
++
++ if (!__builtin_constant_p(size)) {
++ check_object_size(src, size, true);
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)dst < PAX_USER_SHADOW_BASE)
++ dst += PAX_USER_SHADOW_BASE;
++#endif
++
+ return copy_user_generic((__force void *)dst, src, size);
++ }
+ switch (size) {
+- case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst,
++ case 1:__put_user_asm(*(const u8 *)src, (u8 __user *)dst,
+ ret, "b", "b", "iq", 1);
+ return ret;
+- case 2:__put_user_asm(*(u16 *)src, (u16 __user *)dst,
++ case 2:__put_user_asm(*(const u16 *)src, (u16 __user *)dst,
+ ret, "w", "w", "ir", 2);
+ return ret;
+- case 4:__put_user_asm(*(u32 *)src, (u32 __user *)dst,
++ case 4:__put_user_asm(*(const u32 *)src, (u32 __user *)dst,
+ ret, "l", "k", "ir", 4);
+ return ret;
+- case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst,
++ case 8:__put_user_asm(*(const u64 *)src, (u64 __user *)dst,
+ ret, "q", "", "er", 8);
+ return ret;
+ case 10:
+- __put_user_asm(*(u64 *)src, (u64 __user *)dst,
++ __put_user_asm(*(const u64 *)src, (u64 __user *)dst,
+ ret, "q", "", "er", 10);
+ if (unlikely(ret))
+ return ret;
+ asm("":::"memory");
+- __put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
++ __put_user_asm(4[(const u16 *)src], 4 + (u16 __user *)dst,
+ ret, "w", "w", "ir", 2);
+ return ret;
+ case 16:
+- __put_user_asm(*(u64 *)src, (u64 __user *)dst,
++ __put_user_asm(*(const u64 *)src, (u64 __user *)dst,
+ ret, "q", "", "er", 16);
+ if (unlikely(ret))
+ return ret;
+ asm("":::"memory");
+- __put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
++ __put_user_asm(1[(const u64 *)src], 1 + (u64 __user *)dst,
+ ret, "q", "", "er", 8);
+ return ret;
+ default:
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)dst < PAX_USER_SHADOW_BASE)
++ dst += PAX_USER_SHADOW_BASE;
++#endif
++
+ return copy_user_generic((__force void *)dst, src, size);
+ }
+ }
+
+ static __always_inline __must_check
+-int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
++unsigned long __copy_in_user(void __user *dst, const void __user *src, unsigned size)
+ {
+- int ret = 0;
++ unsigned ret = 0;
+
+ might_fault();
+- if (!__builtin_constant_p(size))
++
++ if ((int)size < 0)
++ return size;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if (!__access_ok(VERIFY_READ, src, size))
++ return size;
++ if (!__access_ok(VERIFY_WRITE, dst, size))
++ return size;
++#endif
++
++ if (!__builtin_constant_p(size)) {
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)src < PAX_USER_SHADOW_BASE)
++ src += PAX_USER_SHADOW_BASE;
++ if ((unsigned long)dst < PAX_USER_SHADOW_BASE)
++ dst += PAX_USER_SHADOW_BASE;
++#endif
++
+ return copy_user_generic((__force void *)dst,
+- (__force void *)src, size);
++ (__force const void *)src, size);
++ }
+ switch (size) {
+ case 1: {
+ u8 tmp;
+- __get_user_asm(tmp, (u8 __user *)src,
++ __get_user_asm(tmp, (const u8 __user *)src,
+ ret, "b", "b", "=q", 1);
+ if (likely(!ret))
+ __put_user_asm(tmp, (u8 __user *)dst,
+@@ -177,7 +268,7 @@ int __copy_in_user(void __user *dst, con
+ }
+ case 2: {
+ u16 tmp;
+- __get_user_asm(tmp, (u16 __user *)src,
++ __get_user_asm(tmp, (const u16 __user *)src,
+ ret, "w", "w", "=r", 2);
+ if (likely(!ret))
+ __put_user_asm(tmp, (u16 __user *)dst,
+@@ -187,7 +278,7 @@ int __copy_in_user(void __user *dst, con
+
+ case 4: {
+ u32 tmp;
+- __get_user_asm(tmp, (u32 __user *)src,
++ __get_user_asm(tmp, (const u32 __user *)src,
+ ret, "l", "k", "=r", 4);
+ if (likely(!ret))
+ __put_user_asm(tmp, (u32 __user *)dst,
+@@ -196,7 +287,7 @@ int __copy_in_user(void __user *dst, con
+ }
+ case 8: {
+ u64 tmp;
+- __get_user_asm(tmp, (u64 __user *)src,
++ __get_user_asm(tmp, (const u64 __user *)src,
+ ret, "q", "", "=r", 8);
+ if (likely(!ret))
+ __put_user_asm(tmp, (u64 __user *)dst,
+@@ -204,8 +295,16 @@ int __copy_in_user(void __user *dst, con
+ return ret;
+ }
+ default:
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)src < PAX_USER_SHADOW_BASE)
++ src += PAX_USER_SHADOW_BASE;
++ if ((unsigned long)dst < PAX_USER_SHADOW_BASE)
++ dst += PAX_USER_SHADOW_BASE;
++#endif
++
+ return copy_user_generic((__force void *)dst,
+- (__force void *)src, size);
++ (__force const void *)src, size);
+ }
+ }
+
+@@ -222,33 +321,72 @@ __must_check unsigned long __clear_user(
+ static __must_check __always_inline int
+ __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size)
+ {
++ pax_track_stack();
++
++ if ((int)size < 0)
++ return size;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if (!__access_ok(VERIFY_READ, src, size))
++ return size;
++
++ if ((unsigned long)src < PAX_USER_SHADOW_BASE)
++ src += PAX_USER_SHADOW_BASE;
++#endif
++
+ return copy_user_generic(dst, (__force const void *)src, size);
+ }
+
+-static __must_check __always_inline int
++static __must_check __always_inline unsigned long
+ __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
+ {
++ if ((int)size < 0)
++ return size;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if (!__access_ok(VERIFY_WRITE, dst, size))
++ return size;
++
++ if ((unsigned long)dst < PAX_USER_SHADOW_BASE)
++ dst += PAX_USER_SHADOW_BASE;
++#endif
++
+ return copy_user_generic((__force void *)dst, src, size);
+ }
+
+-extern long __copy_user_nocache(void *dst, const void __user *src,
++extern unsigned long __copy_user_nocache(void *dst, const void __user *src,
+ unsigned size, int zerorest);
+
+-static inline int
+-__copy_from_user_nocache(void *dst, const void __user *src, unsigned size)
++static inline unsigned long __copy_from_user_nocache(void *dst, const void __user *src, unsigned size)
+ {
+ might_sleep();
++
++ if ((int)size < 0)
++ return size;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if (!__access_ok(VERIFY_READ, src, size))
++ return size;
++#endif
++
+ return __copy_user_nocache(dst, src, size, 1);
+ }
+
+-static inline int
+-__copy_from_user_inatomic_nocache(void *dst, const void __user *src,
++static inline unsigned long __copy_from_user_inatomic_nocache(void *dst, const void __user *src,
+ unsigned size)
+ {
++ if ((int)size < 0)
++ return size;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if (!__access_ok(VERIFY_READ, src, size))
++ return size;
++#endif
++
+ return __copy_user_nocache(dst, src, size, 0);
+ }
+
+-unsigned long
++extern unsigned long
+ copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest);
+
+ #endif /* _ASM_X86_UACCESS_64_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/uaccess.h linux-2.6.38.7/arch/x86/include/asm/uaccess.h
+--- linux-2.6.38.7/arch/x86/include/asm/uaccess.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/uaccess.h 2011-04-28 19:34:14.000000000 -0400
+@@ -8,12 +8,15 @@
+ #include <linux/thread_info.h>
+ #include <linux/prefetch.h>
+ #include <linux/string.h>
++#include <linux/sched.h>
+ #include <asm/asm.h>
+ #include <asm/page.h>
+
+ #define VERIFY_READ 0
+ #define VERIFY_WRITE 1
+
++extern void check_object_size(const void *ptr, unsigned long n, bool to);
++
+ /*
+ * The fs value determines whether argument validity checking should be
+ * performed or not. If get_fs() == USER_DS, checking is performed, with
+@@ -29,7 +32,12 @@
+
+ #define get_ds() (KERNEL_DS)
+ #define get_fs() (current_thread_info()->addr_limit)
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF)
++void __set_fs(mm_segment_t x);
++void set_fs(mm_segment_t x);
++#else
+ #define set_fs(x) (current_thread_info()->addr_limit = (x))
++#endif
+
+ #define segment_eq(a, b) ((a).seg == (b).seg)
+
+@@ -77,7 +85,33 @@
+ * checks that the pointer is in the user space range - after calling
+ * this function, memory access functions may still return -EFAULT.
+ */
+-#define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0))
++#define __access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0))
++#define access_ok(type, addr, size) \
++({ \
++ long __size = size; \
++ unsigned long __addr = (unsigned long)addr; \
++ unsigned long __addr_ao = __addr & PAGE_MASK; \
++ unsigned long __end_ao = __addr + __size - 1; \
++ bool __ret_ao = __range_not_ok(__addr, __size) == 0; \
++ if (__ret_ao && unlikely((__end_ao ^ __addr_ao) & PAGE_MASK)) { \
++ while(__addr_ao <= __end_ao) { \
++ char __c_ao; \
++ __addr_ao += PAGE_SIZE; \
++ if (__size > PAGE_SIZE) \
++ cond_resched(); \
++ if (__get_user(__c_ao, (char __user *)__addr)) \
++ break; \
++ if (type != VERIFY_WRITE) { \
++ __addr = __addr_ao; \
++ continue; \
++ } \
++ if (__put_user(__c_ao, (char __user *)__addr)) \
++ break; \
++ __addr = __addr_ao; \
++ } \
++ } \
++ __ret_ao; \
++})
+
+ /*
+ * The exception table consists of pairs of addresses: the first is the
+@@ -183,12 +217,20 @@ extern int __get_user_bad(void);
+ asm volatile("call __put_user_" #size : "=a" (__ret_pu) \
+ : "0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
+
+-
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF)
++#define __copyuser_seg "gs;"
++#define __COPYUSER_SET_ES "pushl %%gs; popl %%es\n"
++#define __COPYUSER_RESTORE_ES "pushl %%ss; popl %%es\n"
++#else
++#define __copyuser_seg
++#define __COPYUSER_SET_ES
++#define __COPYUSER_RESTORE_ES
++#endif
+
+ #ifdef CONFIG_X86_32
+ #define __put_user_asm_u64(x, addr, err, errret) \
+- asm volatile("1: movl %%eax,0(%2)\n" \
+- "2: movl %%edx,4(%2)\n" \
++ asm volatile("1: "__copyuser_seg"movl %%eax,0(%2)\n" \
++ "2: "__copyuser_seg"movl %%edx,4(%2)\n" \
+ "3:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "4: movl %3,%0\n" \
+@@ -200,8 +242,8 @@ extern int __get_user_bad(void);
+ : "A" (x), "r" (addr), "i" (errret), "0" (err))
+
+ #define __put_user_asm_ex_u64(x, addr) \
+- asm volatile("1: movl %%eax,0(%1)\n" \
+- "2: movl %%edx,4(%1)\n" \
++ asm volatile("1: "__copyuser_seg"movl %%eax,0(%1)\n" \
++ "2: "__copyuser_seg"movl %%edx,4(%1)\n" \
+ "3:\n" \
+ _ASM_EXTABLE(1b, 2b - 1b) \
+ _ASM_EXTABLE(2b, 3b - 2b) \
+@@ -374,7 +416,7 @@ do { \
+ } while (0)
+
+ #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
+- asm volatile("1: mov"itype" %2,%"rtype"1\n" \
++ asm volatile("1: "__copyuser_seg"mov"itype" %2,%"rtype"1\n"\
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: mov %3,%0\n" \
+@@ -382,7 +424,7 @@ do { \
+ " jmp 2b\n" \
+ ".previous\n" \
+ _ASM_EXTABLE(1b, 3b) \
+- : "=r" (err), ltype(x) \
++ : "=r" (err), ltype (x) \
+ : "m" (__m(addr)), "i" (errret), "0" (err))
+
+ #define __get_user_size_ex(x, ptr, size) \
+@@ -407,7 +449,7 @@ do { \
+ } while (0)
+
+ #define __get_user_asm_ex(x, addr, itype, rtype, ltype) \
+- asm volatile("1: mov"itype" %1,%"rtype"0\n" \
++ asm volatile("1: "__copyuser_seg"mov"itype" %1,%"rtype"0\n"\
+ "2:\n" \
+ _ASM_EXTABLE(1b, 2b - 1b) \
+ : ltype(x) : "m" (__m(addr)))
+@@ -424,13 +466,24 @@ do { \
+ int __gu_err; \
+ unsigned long __gu_val; \
+ __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
+- (x) = (__force __typeof__(*(ptr)))__gu_val; \
++ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+ })
+
+ /* FIXME: this hack is definitely wrong -AK */
+ struct __large_struct { unsigned long buf[100]; };
+-#define __m(x) (*(struct __large_struct __user *)(x))
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++#define ____m(x) \
++({ \
++ unsigned long ____x = (unsigned long)(x); \
++ if (____x < PAX_USER_SHADOW_BASE) \
++ ____x += PAX_USER_SHADOW_BASE; \
++ (void __user *)____x; \
++})
++#else
++#define ____m(x) (x)
++#endif
++#define __m(x) (*(struct __large_struct __user *)____m(x))
+
+ /*
+ * Tell gcc we read from memory instead of writing: this is because
+@@ -438,7 +491,7 @@ struct __large_struct { unsigned long bu
+ * aliasing issues.
+ */
+ #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
+- asm volatile("1: mov"itype" %"rtype"1,%2\n" \
++ asm volatile("1: "__copyuser_seg"mov"itype" %"rtype"1,%2\n"\
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: mov %3,%0\n" \
+@@ -446,10 +499,10 @@ struct __large_struct { unsigned long bu
+ ".previous\n" \
+ _ASM_EXTABLE(1b, 3b) \
+ : "=r"(err) \
+- : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
++ : ltype (x), "m" (__m(addr)), "i" (errret), "0" (err))
+
+ #define __put_user_asm_ex(x, addr, itype, rtype, ltype) \
+- asm volatile("1: mov"itype" %"rtype"0,%1\n" \
++ asm volatile("1: "__copyuser_seg"mov"itype" %"rtype"0,%1\n"\
+ "2:\n" \
+ _ASM_EXTABLE(1b, 2b - 1b) \
+ : : ltype(x), "m" (__m(addr)))
+@@ -488,8 +541,12 @@ struct __large_struct { unsigned long bu
+ * On error, the variable @x is set to zero.
+ */
+
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++#define __get_user(x, ptr) get_user((x), (ptr))
++#else
+ #define __get_user(x, ptr) \
+ __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
++#endif
+
+ /**
+ * __put_user: - Write a simple value into user space, with less checking.
+@@ -511,8 +568,12 @@ struct __large_struct { unsigned long bu
+ * Returns zero on success, or -EFAULT on error.
+ */
+
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++#define __put_user(x, ptr) put_user((x), (ptr))
++#else
+ #define __put_user(x, ptr) \
+ __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
++#endif
+
+ #define __get_user_unaligned __get_user
+ #define __put_user_unaligned __put_user
+@@ -530,7 +591,7 @@ struct __large_struct { unsigned long bu
+ #define get_user_ex(x, ptr) do { \
+ unsigned long __gue_val; \
+ __get_user_size_ex((__gue_val), (ptr), (sizeof(*(ptr)))); \
+- (x) = (__force __typeof__(*(ptr)))__gue_val; \
++ (x) = (__typeof__(*(ptr)))__gue_val; \
+ } while (0)
+
+ #ifdef CONFIG_X86_WP_WORKS_OK
+@@ -567,6 +628,7 @@ extern struct movsl_mask {
+
+ #define ARCH_HAS_NOCACHE_UACCESS 1
+
++#define ARCH_HAS_SORT_EXTABLE
+ #ifdef CONFIG_X86_32
+ # include "uaccess_32.h"
+ #else
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/vgtod.h linux-2.6.38.7/arch/x86/include/asm/vgtod.h
+--- linux-2.6.38.7/arch/x86/include/asm/vgtod.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/vgtod.h 2011-04-28 19:34:14.000000000 -0400
+@@ -14,6 +14,7 @@ struct vsyscall_gtod_data {
+ int sysctl_enabled;
+ struct timezone sys_tz;
+ struct { /* extract of a clocksource struct */
++ char name[8];
+ cycle_t (*vread)(void);
+ cycle_t cycle_last;
+ cycle_t mask;
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/vsyscall.h linux-2.6.38.7/arch/x86/include/asm/vsyscall.h
+--- linux-2.6.38.7/arch/x86/include/asm/vsyscall.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/vsyscall.h 2011-04-28 19:34:14.000000000 -0400
+@@ -15,9 +15,10 @@ enum vsyscall_num {
+
+ #ifdef __KERNEL__
+ #include <linux/seqlock.h>
++#include <linux/getcpu.h>
++#include <linux/time.h>
+
+ #define __section_vgetcpu_mode __attribute__ ((unused, __section__ (".vgetcpu_mode"), aligned(16)))
+-#define __section_jiffies __attribute__ ((unused, __section__ (".jiffies"), aligned(16)))
+
+ /* Definitions for CONFIG_GENERIC_TIME definitions */
+ #define __section_vsyscall_gtod_data __attribute__ \
+@@ -31,7 +32,6 @@ enum vsyscall_num {
+ #define VGETCPU_LSL 2
+
+ extern int __vgetcpu_mode;
+-extern volatile unsigned long __jiffies;
+
+ /* kernel space (writeable) */
+ extern int vgetcpu_mode;
+@@ -39,6 +39,9 @@ extern struct timezone sys_tz;
+
+ extern void map_vsyscall(void);
+
++extern int vgettimeofday(struct timeval * tv, struct timezone * tz);
++extern time_t vtime(time_t *t);
++extern long vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache);
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_X86_VSYSCALL_H */
+diff -urNp linux-2.6.38.7/arch/x86/include/asm/xsave.h linux-2.6.38.7/arch/x86/include/asm/xsave.h
+--- linux-2.6.38.7/arch/x86/include/asm/xsave.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/include/asm/xsave.h 2011-04-28 19:34:14.000000000 -0400
+@@ -65,6 +65,11 @@ static inline int xsave_user(struct xsav
+ {
+ int err;
+
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ if ((unsigned long)buf < PAX_USER_SHADOW_BASE)
++ buf = (struct xsave_struct __user *)((void __user*)buf + PAX_USER_SHADOW_BASE);
++#endif
++
+ /*
+ * Clear the xsave header first, so that reserved fields are
+ * initialized to zero.
+@@ -100,6 +105,11 @@ static inline int xrestore_user(struct x
+ u32 lmask = mask;
+ u32 hmask = mask >> 32;
+
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ if ((unsigned long)xstate < PAX_USER_SHADOW_BASE)
++ xstate = (struct xsave_struct *)((void *)xstate + PAX_USER_SHADOW_BASE);
++#endif
++
+ __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n"
+ "2:\n"
+ ".section .fixup,\"ax\"\n"
+diff -urNp linux-2.6.38.7/arch/x86/Kconfig linux-2.6.38.7/arch/x86/Kconfig
+--- linux-2.6.38.7/arch/x86/Kconfig 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/Kconfig 2011-04-28 19:34:14.000000000 -0400
+@@ -223,7 +223,7 @@ config X86_TRAMPOLINE
+
+ config X86_32_LAZY_GS
+ def_bool y
+- depends on X86_32 && !CC_STACKPROTECTOR
++ depends on X86_32 && !CC_STACKPROTECTOR && !PAX_MEMORY_UDEREF
+
+ config ARCH_HWEIGHT_CFLAGS
+ string
+@@ -1019,7 +1019,7 @@ choice
+
+ config NOHIGHMEM
+ bool "off"
+- depends on !X86_NUMAQ
++ depends on !X86_NUMAQ && !(PAX_PAGEEXEC && PAX_ENABLE_PAE)
+ ---help---
+ Linux can use up to 64 Gigabytes of physical memory on x86 systems.
+ However, the address space of 32-bit x86 processors is only 4
+@@ -1056,7 +1056,7 @@ config NOHIGHMEM
+
+ config HIGHMEM4G
+ bool "4GB"
+- depends on !X86_NUMAQ
++ depends on !X86_NUMAQ && !(PAX_PAGEEXEC && PAX_ENABLE_PAE)
+ ---help---
+ Select this if you have a 32-bit processor and between 1 and 4
+ gigabytes of physical RAM.
+@@ -1110,7 +1110,7 @@ config PAGE_OFFSET
+ hex
+ default 0xB0000000 if VMSPLIT_3G_OPT
+ default 0x80000000 if VMSPLIT_2G
+- default 0x78000000 if VMSPLIT_2G_OPT
++ default 0x70000000 if VMSPLIT_2G_OPT
+ default 0x40000000 if VMSPLIT_1G
+ default 0xC0000000
+ depends on X86_32
+@@ -1454,7 +1454,7 @@ config ARCH_USES_PG_UNCACHED
+
+ config EFI
+ bool "EFI runtime service support"
+- depends on ACPI
++ depends on ACPI && !PAX_KERNEXEC
+ ---help---
+ This enables the kernel to use EFI runtime services that are
+ available (such as the EFI variable services).
+@@ -1484,6 +1484,7 @@ config SECCOMP
+
+ config CC_STACKPROTECTOR
+ bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
++ depends on X86_64 || !PAX_MEMORY_UDEREF
+ ---help---
+ This option turns on the -fstack-protector GCC feature. This
+ feature puts, at the beginning of functions, a canary value on
+@@ -1541,6 +1542,7 @@ config KEXEC_JUMP
+ config PHYSICAL_START
+ hex "Physical address where the kernel is loaded" if (EXPERT || CRASH_DUMP)
+ default "0x1000000"
++ range 0x400000 0x40000000
+ ---help---
+ This gives the physical address where the kernel is loaded.
+
+@@ -1604,6 +1606,7 @@ config X86_NEED_RELOCS
+ config PHYSICAL_ALIGN
+ hex "Alignment value to which kernel should be aligned" if X86_32
+ default "0x1000000"
++ range 0x400000 0x1000000 if PAX_KERNEXEC
+ range 0x2000 0x1000000
+ ---help---
+ This value puts the alignment restrictions on physical address
+@@ -1635,9 +1638,10 @@ config HOTPLUG_CPU
+ Say N if you want to disable CPU hotplug.
+
+ config COMPAT_VDSO
+- def_bool y
++ def_bool n
+ prompt "Compat VDSO support"
+ depends on X86_32 || IA32_EMULATION
++ depends on !PAX_NOEXEC && !PAX_MEMORY_UDEREF
+ ---help---
+ Map the 32-bit VDSO to the predictable old-style address too.
+
+diff -urNp linux-2.6.38.7/arch/x86/Kconfig.cpu linux-2.6.38.7/arch/x86/Kconfig.cpu
+--- linux-2.6.38.7/arch/x86/Kconfig.cpu 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/Kconfig.cpu 2011-04-28 19:34:14.000000000 -0400
+@@ -339,7 +339,7 @@ config X86_PPRO_FENCE
+
+ config X86_F00F_BUG
+ def_bool y
+- depends on M586MMX || M586TSC || M586 || M486 || M386
++ depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC
+
+ config X86_INVD_BUG
+ def_bool y
+@@ -363,7 +363,7 @@ config X86_POPAD_OK
+
+ config X86_ALIGNMENT_16
+ def_bool y
+- depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
++ depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MCORE2 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
+
+ config X86_INTEL_USERCOPY
+ def_bool y
+@@ -409,7 +409,7 @@ config X86_CMPXCHG64
+ # generates cmov.
+ config X86_CMOV
+ def_bool y
+- depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX)
++ depends on (MK8 || MK7 || MCORE2 || MPSC || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX)
+
+ config X86_MINIMUM_CPU_FAMILY
+ int
+diff -urNp linux-2.6.38.7/arch/x86/Kconfig.debug linux-2.6.38.7/arch/x86/Kconfig.debug
+--- linux-2.6.38.7/arch/x86/Kconfig.debug 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/Kconfig.debug 2011-04-28 19:34:14.000000000 -0400
+@@ -101,7 +101,7 @@ config X86_PTDUMP
+ config DEBUG_RODATA
+ bool "Write protect kernel read-only data structures"
+ default y
+- depends on DEBUG_KERNEL
++ depends on DEBUG_KERNEL && BROKEN
+ ---help---
+ Mark the kernel read-only data as write-protected in the pagetables,
+ in order to catch accidental (and incorrect) writes to such const
+@@ -119,7 +119,7 @@ config DEBUG_RODATA_TEST
+
+ config DEBUG_SET_MODULE_RONX
+ bool "Set loadable kernel module data as NX and text as RO"
+- depends on MODULES
++ depends on MODULES && BROKEN
+ ---help---
+ This option helps catch unintended modifications to loadable
+ kernel module's text and read-only data. It also prevents execution
+diff -urNp linux-2.6.38.7/arch/x86/kernel/acpi/sleep.c linux-2.6.38.7/arch/x86/kernel/acpi/sleep.c
+--- linux-2.6.38.7/arch/x86/kernel/acpi/sleep.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/acpi/sleep.c 2011-04-28 19:34:14.000000000 -0400
+@@ -18,7 +18,7 @@
+ #include "realmode/wakeup.h"
+ #include "sleep.h"
+
+-unsigned long acpi_wakeup_address;
++unsigned long acpi_wakeup_address = 0x2000;
+ unsigned long acpi_realmode_flags;
+
+ /* address in low memory of the wakeup routine. */
+@@ -99,8 +99,12 @@ int acpi_save_state_mem(void)
+ header->trampoline_segment = setup_trampoline() >> 4;
+ #ifdef CONFIG_SMP
+ stack_start = (unsigned long)temp_stack + sizeof(temp_stack);
++
++ pax_open_kernel();
+ early_gdt_descr.address =
+ (unsigned long)get_cpu_gdt_table(smp_processor_id());
++ pax_close_kernel();
++
+ initial_gs = per_cpu_offset(smp_processor_id());
+ #endif
+ initial_code = (unsigned long)wakeup_long64;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/acpi/wakeup_32.S linux-2.6.38.7/arch/x86/kernel/acpi/wakeup_32.S
+--- linux-2.6.38.7/arch/x86/kernel/acpi/wakeup_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/acpi/wakeup_32.S 2011-04-28 19:34:14.000000000 -0400
+@@ -30,13 +30,11 @@ wakeup_pmode_return:
+ # and restore the stack ... but you need gdt for this to work
+ movl saved_context_esp, %esp
+
+- movl %cs:saved_magic, %eax
+- cmpl $0x12345678, %eax
++ cmpl $0x12345678, saved_magic
+ jne bogus_magic
+
+ # jump to place where we left off
+- movl saved_eip, %eax
+- jmp *%eax
++ jmp *(saved_eip)
+
+ bogus_magic:
+ jmp bogus_magic
+diff -urNp linux-2.6.38.7/arch/x86/kernel/alternative.c linux-2.6.38.7/arch/x86/kernel/alternative.c
+--- linux-2.6.38.7/arch/x86/kernel/alternative.c 2011-04-18 17:27:13.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/alternative.c 2011-04-28 19:34:14.000000000 -0400
+@@ -248,7 +248,7 @@ static void alternatives_smp_lock(const
+ if (!*poff || ptr < text || ptr >= text_end)
+ continue;
+ /* turn DS segment override prefix into lock prefix */
+- if (*ptr == 0x3e)
++ if (*ktla_ktva(ptr) == 0x3e)
+ text_poke(ptr, ((unsigned char []){0xf0}), 1);
+ };
+ mutex_unlock(&text_mutex);
+@@ -269,7 +269,7 @@ static void alternatives_smp_unlock(cons
+ if (!*poff || ptr < text || ptr >= text_end)
+ continue;
+ /* turn lock prefix into DS segment override prefix */
+- if (*ptr == 0xf0)
++ if (*ktla_ktva(ptr) == 0xf0)
+ text_poke(ptr, ((unsigned char []){0x3E}), 1);
+ };
+ mutex_unlock(&text_mutex);
+@@ -438,7 +438,7 @@ void __init_or_module apply_paravirt(str
+
+ BUG_ON(p->len > MAX_PATCH_LEN);
+ /* prep the buffer with the original instructions */
+- memcpy(insnbuf, p->instr, p->len);
++ memcpy(insnbuf, ktla_ktva(p->instr), p->len);
+ used = pv_init_ops.patch(p->instrtype, p->clobbers, insnbuf,
+ (unsigned long)p->instr, p->len);
+
+@@ -506,7 +506,7 @@ void __init alternative_instructions(voi
+ if (smp_alt_once)
+ free_init_pages("SMP alternatives",
+ (unsigned long)__smp_locks,
+- (unsigned long)__smp_locks_end);
++ PAGE_ALIGN((unsigned long)__smp_locks_end));
+
+ restart_nmi();
+ }
+@@ -523,13 +523,17 @@ void __init alternative_instructions(voi
+ * instructions. And on the local CPU you need to be protected again NMI or MCE
+ * handlers seeing an inconsistent instruction while you patch.
+ */
+-void *__init_or_module text_poke_early(void *addr, const void *opcode,
++void *__kprobes text_poke_early(void *addr, const void *opcode,
+ size_t len)
+ {
+ unsigned long flags;
+ local_irq_save(flags);
+- memcpy(addr, opcode, len);
++
++ pax_open_kernel();
++ memcpy(ktla_ktva(addr), opcode, len);
+ sync_core();
++ pax_close_kernel();
++
+ local_irq_restore(flags);
+ /* Could also do a CLFLUSH here to speed up CPU recovery; but
+ that causes hangs on some VIA CPUs. */
+@@ -551,36 +555,22 @@ void *__init_or_module text_poke_early(v
+ */
+ void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
+ {
+- unsigned long flags;
+- char *vaddr;
++ unsigned char *vaddr = ktla_ktva(addr);
+ struct page *pages[2];
+- int i;
++ size_t i;
+
+ if (!core_kernel_text((unsigned long)addr)) {
+- pages[0] = vmalloc_to_page(addr);
+- pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
++ pages[0] = vmalloc_to_page(vaddr);
++ pages[1] = vmalloc_to_page(vaddr + PAGE_SIZE);
+ } else {
+- pages[0] = virt_to_page(addr);
++ pages[0] = virt_to_page(vaddr);
+ WARN_ON(!PageReserved(pages[0]));
+- pages[1] = virt_to_page(addr + PAGE_SIZE);
++ pages[1] = virt_to_page(vaddr + PAGE_SIZE);
+ }
+ BUG_ON(!pages[0]);
+- local_irq_save(flags);
+- set_fixmap(FIX_TEXT_POKE0, page_to_phys(pages[0]));
+- if (pages[1])
+- set_fixmap(FIX_TEXT_POKE1, page_to_phys(pages[1]));
+- vaddr = (char *)fix_to_virt(FIX_TEXT_POKE0);
+- memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
+- clear_fixmap(FIX_TEXT_POKE0);
+- if (pages[1])
+- clear_fixmap(FIX_TEXT_POKE1);
+- local_flush_tlb();
+- sync_core();
+- /* Could also do a CLFLUSH here to speed up CPU recovery; but
+- that causes hangs on some VIA CPUs. */
++ text_poke_early(addr, opcode, len);
+ for (i = 0; i < len; i++)
+- BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
+- local_irq_restore(flags);
++ BUG_ON((vaddr)[i] != ((const unsigned char *)opcode)[i]);
+ return addr;
+ }
+
+@@ -682,9 +672,9 @@ void __kprobes text_poke_smp_batch(struc
+ #if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
+
+ #ifdef CONFIG_X86_64
+-unsigned char ideal_nop5[5] = { 0x66, 0x66, 0x66, 0x66, 0x90 };
++unsigned char ideal_nop5[5] __read_only = { 0x66, 0x66, 0x66, 0x66, 0x90 };
+ #else
+-unsigned char ideal_nop5[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
++unsigned char ideal_nop5[5] __read_only = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
+ #endif
+
+ void __init arch_init_ideal_nop5(void)
+diff -urNp linux-2.6.38.7/arch/x86/kernel/amd_iommu.c linux-2.6.38.7/arch/x86/kernel/amd_iommu.c
+--- linux-2.6.38.7/arch/x86/kernel/amd_iommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/amd_iommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -2286,7 +2286,7 @@ static void prealloc_protection_domains(
+ }
+ }
+
+-static struct dma_map_ops amd_iommu_dma_ops = {
++static const struct dma_map_ops amd_iommu_dma_ops = {
+ .alloc_coherent = alloc_coherent,
+ .free_coherent = free_coherent,
+ .map_page = map_page,
+diff -urNp linux-2.6.38.7/arch/x86/kernel/apic/apic.c linux-2.6.38.7/arch/x86/kernel/apic/apic.c
+--- linux-2.6.38.7/arch/x86/kernel/apic/apic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/apic/apic.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1819,7 +1819,7 @@ void smp_error_interrupt(struct pt_regs
+ apic_write(APIC_ESR, 0);
+ v1 = apic_read(APIC_ESR);
+ ack_APIC_irq();
+- atomic_inc(&irq_err_count);
++ atomic_inc_unchecked(&irq_err_count);
+
+ /*
+ * Here is what the APIC error bits mean:
+@@ -2209,6 +2209,8 @@ static int __cpuinit apic_cluster_num(vo
+ u16 *bios_cpu_apicid;
+ DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
+
++ pax_track_stack();
++
+ bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
+ bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
+
+diff -urNp linux-2.6.38.7/arch/x86/kernel/apic/io_apic.c linux-2.6.38.7/arch/x86/kernel/apic/io_apic.c
+--- linux-2.6.38.7/arch/x86/kernel/apic/io_apic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/apic/io_apic.c 2011-04-28 19:57:25.000000000 -0400
+@@ -617,7 +617,7 @@ struct IO_APIC_route_entry **alloc_ioapi
+ ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
+ GFP_KERNEL);
+ if (!ioapic_entries)
+- return 0;
++ return NULL;
+
+ for (apic = 0; apic < nr_ioapics; apic++) {
+ ioapic_entries[apic] =
+@@ -634,7 +634,7 @@ nomem:
+ kfree(ioapic_entries[apic]);
+ kfree(ioapic_entries);
+
+- return 0;
++ return NULL;
+ }
+
+ /*
+@@ -1044,7 +1044,7 @@ int IO_APIC_get_PCI_irq_vector(int bus,
+ }
+ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+
+-void lock_vector_lock(void)
++void lock_vector_lock(void) __acquires(vector_lock)
+ {
+ /* Used to the online set of cpus does not change
+ * during assign_irq_vector.
+@@ -1052,7 +1052,7 @@ void lock_vector_lock(void)
+ raw_spin_lock(&vector_lock);
+ }
+
+-void unlock_vector_lock(void)
++void unlock_vector_lock(void) __releases(vector_lock)
+ {
+ raw_spin_unlock(&vector_lock);
+ }
+@@ -2409,7 +2409,7 @@ static void ack_apic_edge(struct irq_dat
+ ack_APIC_irq();
+ }
+
+-atomic_t irq_mis_count;
++atomic_unchecked_t irq_mis_count;
+
+ /*
+ * IO-APIC versions below 0x20 don't support EOI register.
+@@ -2517,7 +2517,7 @@ static void ack_apic_level(struct irq_da
+ * at the cpu.
+ */
+ if (!(v & (1 << (i & 0x1f)))) {
+- atomic_inc(&irq_mis_count);
++ atomic_inc_unchecked(&irq_mis_count);
+
+ eoi_ioapic_irq(irq, cfg);
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/apm_32.c linux-2.6.38.7/arch/x86/kernel/apm_32.c
+--- linux-2.6.38.7/arch/x86/kernel/apm_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/apm_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -410,7 +410,7 @@ static DEFINE_MUTEX(apm_mutex);
+ * This is for buggy BIOS's that refer to (real mode) segment 0x40
+ * even though they are called in protected mode.
+ */
+-static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
++static const struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4093,
+ (unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1);
+
+ static const char driver_version[] = "1.16ac"; /* no spaces */
+@@ -588,7 +588,10 @@ static long __apm_bios_call(void *_call)
+ BUG_ON(cpu != 0);
+ gdt = get_cpu_gdt_table(cpu);
+ save_desc_40 = gdt[0x40 / 8];
++
++ pax_open_kernel();
+ gdt[0x40 / 8] = bad_bios_desc;
++ pax_close_kernel();
+
+ apm_irq_save(flags);
+ APM_DO_SAVE_SEGS;
+@@ -597,7 +600,11 @@ static long __apm_bios_call(void *_call)
+ &call->esi);
+ APM_DO_RESTORE_SEGS;
+ apm_irq_restore(flags);
++
++ pax_open_kernel();
+ gdt[0x40 / 8] = save_desc_40;
++ pax_close_kernel();
++
+ put_cpu();
+
+ return call->eax & 0xff;
+@@ -664,7 +671,10 @@ static long __apm_bios_call_simple(void
+ BUG_ON(cpu != 0);
+ gdt = get_cpu_gdt_table(cpu);
+ save_desc_40 = gdt[0x40 / 8];
++
++ pax_open_kernel();
+ gdt[0x40 / 8] = bad_bios_desc;
++ pax_close_kernel();
+
+ apm_irq_save(flags);
+ APM_DO_SAVE_SEGS;
+@@ -672,7 +682,11 @@ static long __apm_bios_call_simple(void
+ &call->eax);
+ APM_DO_RESTORE_SEGS;
+ apm_irq_restore(flags);
++
++ pax_open_kernel();
+ gdt[0x40 / 8] = save_desc_40;
++ pax_close_kernel();
++
+ put_cpu();
+ return error;
+ }
+@@ -975,7 +989,7 @@ recalc:
+
+ static void apm_power_off(void)
+ {
+- unsigned char po_bios_call[] = {
++ const unsigned char po_bios_call[] = {
+ 0xb8, 0x00, 0x10, /* movw $0x1000,ax */
+ 0x8e, 0xd0, /* movw ax,ss */
+ 0xbc, 0x00, 0xf0, /* movw $0xf000,sp */
+@@ -2356,12 +2370,15 @@ static int __init apm_init(void)
+ * code to that CPU.
+ */
+ gdt = get_cpu_gdt_table(0);
++
++ pax_open_kernel();
+ set_desc_base(&gdt[APM_CS >> 3],
+ (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4));
+ set_desc_base(&gdt[APM_CS_16 >> 3],
+ (unsigned long)__va((unsigned long)apm_info.bios.cseg_16 << 4));
+ set_desc_base(&gdt[APM_DS >> 3],
+ (unsigned long)__va((unsigned long)apm_info.bios.dseg << 4));
++ pax_close_kernel();
+
+ proc_create("apm", 0, NULL, &apm_file_ops);
+
+diff -urNp linux-2.6.38.7/arch/x86/kernel/asm-offsets_32.c linux-2.6.38.7/arch/x86/kernel/asm-offsets_32.c
+--- linux-2.6.38.7/arch/x86/kernel/asm-offsets_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/asm-offsets_32.c 2011-05-16 21:47:08.000000000 -0400
+@@ -51,7 +51,6 @@ void foo(void)
+ OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
+ BLANK();
+
+- OFFSET(TI_task, thread_info, task);
+ OFFSET(TI_exec_domain, thread_info, exec_domain);
+ OFFSET(TI_flags, thread_info, flags);
+ OFFSET(TI_status, thread_info, status);
+@@ -60,6 +59,8 @@ void foo(void)
+ OFFSET(TI_restart_block, thread_info, restart_block);
+ OFFSET(TI_sysenter_return, thread_info, sysenter_return);
+ OFFSET(TI_cpu, thread_info, cpu);
++ OFFSET(TI_lowest_stack, thread_info, lowest_stack);
++ DEFINE(TI_task_thread_sp0, offsetof(struct task_struct, thread.sp0) - offsetof(struct task_struct, tinfo));
+ BLANK();
+
+ OFFSET(GDS_size, desc_ptr, size);
+@@ -113,6 +114,11 @@ void foo(void)
+ OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
+ OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
+ OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
++
++#ifdef CONFIG_PAX_KERNEXEC
++ OFFSET(PV_CPU_write_cr0, pv_cpu_ops, write_cr0);
++#endif
++
+ #endif
+
+ #ifdef CONFIG_XEN
+diff -urNp linux-2.6.38.7/arch/x86/kernel/asm-offsets_64.c linux-2.6.38.7/arch/x86/kernel/asm-offsets_64.c
+--- linux-2.6.38.7/arch/x86/kernel/asm-offsets_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/asm-offsets_64.c 2011-05-16 21:47:08.000000000 -0400
+@@ -44,6 +44,8 @@ int main(void)
+ ENTRY(addr_limit);
+ ENTRY(preempt_count);
+ ENTRY(status);
++ ENTRY(lowest_stack);
++ DEFINE(TI_task_thread_sp0, offsetof(struct task_struct, thread.sp0) - offsetof(struct task_struct, tinfo));
+ #ifdef CONFIG_IA32_EMULATION
+ ENTRY(sysenter_return);
+ #endif
+@@ -63,6 +65,18 @@ int main(void)
+ OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
+ OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs);
+ OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2);
++
++#ifdef CONFIG_PAX_KERNEXEC
++ OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
++ OFFSET(PV_CPU_write_cr0, pv_cpu_ops, write_cr0);
++#endif
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ OFFSET(PV_MMU_read_cr3, pv_mmu_ops, read_cr3);
++ OFFSET(PV_MMU_write_cr3, pv_mmu_ops, write_cr3);
++ OFFSET(PV_MMU_set_pgd, pv_mmu_ops, set_pgd);
++#endif
++
+ #endif
+
+
+@@ -115,6 +129,7 @@ int main(void)
+ ENTRY(cr8);
+ BLANK();
+ #undef ENTRY
++ DEFINE(TSS_size, sizeof(struct tss_struct));
+ DEFINE(TSS_ist, offsetof(struct tss_struct, x86_tss.ist));
+ BLANK();
+ DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
+@@ -130,6 +145,7 @@ int main(void)
+
+ BLANK();
+ DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
++ DEFINE(THREAD_SIZE_asm, THREAD_SIZE);
+ #ifdef CONFIG_XEN
+ BLANK();
+ OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/cpu/amd.c linux-2.6.38.7/arch/x86/kernel/cpu/amd.c
+--- linux-2.6.38.7/arch/x86/kernel/cpu/amd.c 2011-05-22 23:05:18.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/cpu/amd.c 2011-05-22 23:05:54.000000000 -0400
+@@ -624,7 +624,7 @@ static unsigned int __cpuinit amd_size_c
+ unsigned int size)
+ {
+ /* AMD errata T13 (order #21922) */
+- if ((c->x86 == 6)) {
++ if (c->x86 == 6) {
+ /* Duron Rev A0 */
+ if (c->x86_model == 3 && c->x86_mask == 0)
+ size = 64;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/cpu/common.c linux-2.6.38.7/arch/x86/kernel/cpu/common.c
+--- linux-2.6.38.7/arch/x86/kernel/cpu/common.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/cpu/common.c 2011-05-11 18:34:57.000000000 -0400
+@@ -83,60 +83,6 @@ static const struct cpu_dev __cpuinitcon
+
+ static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+
+-DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
+-#ifdef CONFIG_X86_64
+- /*
+- * We need valid kernel segments for data and code in long mode too
+- * IRET will check the segment types kkeil 2000/10/28
+- * Also sysret mandates a special GDT layout
+- *
+- * TLS descriptors are currently at a different place compared to i386.
+- * Hopefully nobody expects them at a fixed place (Wine?)
+- */
+- [GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),
+- [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
+- [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
+- [GDT_ENTRY_DEFAULT_USER32_CS] = GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff),
+- [GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff),
+- [GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff),
+-#else
+- [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xc09a, 0, 0xfffff),
+- [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
+- [GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xc0fa, 0, 0xfffff),
+- [GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f2, 0, 0xfffff),
+- /*
+- * Segments used for calling PnP BIOS have byte granularity.
+- * They code segments and data segments have fixed 64k limits,
+- * the transfer segment sizes are set at run time.
+- */
+- /* 32-bit code */
+- [GDT_ENTRY_PNPBIOS_CS32] = GDT_ENTRY_INIT(0x409a, 0, 0xffff),
+- /* 16-bit code */
+- [GDT_ENTRY_PNPBIOS_CS16] = GDT_ENTRY_INIT(0x009a, 0, 0xffff),
+- /* 16-bit data */
+- [GDT_ENTRY_PNPBIOS_DS] = GDT_ENTRY_INIT(0x0092, 0, 0xffff),
+- /* 16-bit data */
+- [GDT_ENTRY_PNPBIOS_TS1] = GDT_ENTRY_INIT(0x0092, 0, 0),
+- /* 16-bit data */
+- [GDT_ENTRY_PNPBIOS_TS2] = GDT_ENTRY_INIT(0x0092, 0, 0),
+- /*
+- * The APM segments have byte granularity and their bases
+- * are set at run time. All have 64k limits.
+- */
+- /* 32-bit code */
+- [GDT_ENTRY_APMBIOS_BASE] = GDT_ENTRY_INIT(0x409a, 0, 0xffff),
+- /* 16-bit code */
+- [GDT_ENTRY_APMBIOS_BASE+1] = GDT_ENTRY_INIT(0x009a, 0, 0xffff),
+- /* data */
+- [GDT_ENTRY_APMBIOS_BASE+2] = GDT_ENTRY_INIT(0x4092, 0, 0xffff),
+-
+- [GDT_ENTRY_ESPFIX_SS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
+- [GDT_ENTRY_PERCPU] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
+- GDT_STACK_CANARY_INIT
+-#endif
+-} };
+-EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
+-
+ static int __init x86_xsave_setup(char *s)
+ {
+ setup_clear_cpu_cap(X86_FEATURE_XSAVE);
+@@ -352,7 +298,7 @@ void switch_to_new_gdt(int cpu)
+ {
+ struct desc_ptr gdt_descr;
+
+- gdt_descr.address = (long)get_cpu_gdt_table(cpu);
++ gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
+ gdt_descr.size = GDT_SIZE - 1;
+ load_gdt(&gdt_descr);
+ /* Reload the per-cpu base */
+@@ -825,6 +771,10 @@ static void __cpuinit identify_cpu(struc
+ /* Filter out anything that depends on CPUID levels we don't have */
+ filter_cpuid_features(c, true);
+
++#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || (defined(CONFIG_PAX_MEMORY_UDEREF) && defined(CONFIG_X86_32))
++ setup_clear_cpu_cap(X86_FEATURE_SEP);
++#endif
++
+ /* If the model name is still unset, do table lookup. */
+ if (!c->x86_model_id[0]) {
+ const char *p;
+@@ -1004,6 +954,9 @@ static __init int setup_disablecpuid(cha
+ }
+ __setup("clearcpuid=", setup_disablecpuid);
+
++DEFINE_PER_CPU(struct thread_info *, current_tinfo) = &init_task.tinfo;
++EXPORT_PER_CPU_SYMBOL(current_tinfo);
++
+ #ifdef CONFIG_X86_64
+ struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table };
+
+@@ -1019,7 +972,7 @@ DEFINE_PER_CPU(struct task_struct *, cur
+ EXPORT_PER_CPU_SYMBOL(current_task);
+
+ DEFINE_PER_CPU(unsigned long, kernel_stack) =
+- (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
++ (unsigned long)&init_thread_union - 16 + THREAD_SIZE;
+ EXPORT_PER_CPU_SYMBOL(kernel_stack);
+
+ DEFINE_PER_CPU(char *, irq_stack_ptr) =
+@@ -1084,7 +1037,7 @@ struct pt_regs * __cpuinit idle_regs(str
+ {
+ memset(regs, 0, sizeof(struct pt_regs));
+ regs->fs = __KERNEL_PERCPU;
+- regs->gs = __KERNEL_STACK_CANARY;
++ savesegment(gs, regs->gs);
+
+ return regs;
+ }
+@@ -1139,7 +1092,7 @@ void __cpuinit cpu_init(void)
+ int i;
+
+ cpu = stack_smp_processor_id();
+- t = &per_cpu(init_tss, cpu);
++ t = init_tss + cpu;
+ oist = &per_cpu(orig_ist, cpu);
+
+ #ifdef CONFIG_NUMA
+@@ -1165,7 +1118,7 @@ void __cpuinit cpu_init(void)
+ switch_to_new_gdt(cpu);
+ loadsegment(fs, 0);
+
+- load_idt((const struct desc_ptr *)&idt_descr);
++ load_idt(&idt_descr);
+
+ memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8);
+ syscall_init();
+@@ -1174,7 +1127,6 @@ void __cpuinit cpu_init(void)
+ wrmsrl(MSR_KERNEL_GS_BASE, 0);
+ barrier();
+
+- x86_configure_nx();
+ if (cpu != 0)
+ enable_x2apic();
+
+@@ -1228,7 +1180,7 @@ void __cpuinit cpu_init(void)
+ {
+ int cpu = smp_processor_id();
+ struct task_struct *curr = current;
+- struct tss_struct *t = &per_cpu(init_tss, cpu);
++ struct tss_struct *t = init_tss + cpu;
+ struct thread_struct *thread = &curr->thread;
+
+ if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
+diff -urNp linux-2.6.38.7/arch/x86/kernel/cpu/intel.c linux-2.6.38.7/arch/x86/kernel/cpu/intel.c
+--- linux-2.6.38.7/arch/x86/kernel/cpu/intel.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/cpu/intel.c 2011-04-28 19:34:14.000000000 -0400
+@@ -161,7 +161,7 @@ static void __cpuinit trap_init_f00f_bug
+ * Update the IDT descriptor and reload the IDT so that
+ * it uses the read-only mapped virtual address.
+ */
+- idt_descr.address = fix_to_virt(FIX_F00F_IDT);
++ idt_descr.address = (struct desc_struct *)fix_to_virt(FIX_F00F_IDT);
+ load_idt(&idt_descr);
+ }
+ #endif
+diff -urNp linux-2.6.38.7/arch/x86/kernel/cpu/Makefile linux-2.6.38.7/arch/x86/kernel/cpu/Makefile
+--- linux-2.6.38.7/arch/x86/kernel/cpu/Makefile 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/cpu/Makefile 2011-04-28 19:34:14.000000000 -0400
+@@ -8,10 +8,6 @@ CFLAGS_REMOVE_common.o = -pg
+ CFLAGS_REMOVE_perf_event.o = -pg
+ endif
+
+-# Make sure load_percpu_segment has no stackprotector
+-nostackp := $(call cc-option, -fno-stack-protector)
+-CFLAGS_common.o := $(nostackp)
+-
+ obj-y := intel_cacheinfo.o scattered.o topology.o
+ obj-y += proc.o capflags.o powerflags.o common.o
+ obj-y += vmware.o hypervisor.o sched.o mshyperv.o
+diff -urNp linux-2.6.38.7/arch/x86/kernel/cpu/mcheck/mce.c linux-2.6.38.7/arch/x86/kernel/cpu/mcheck/mce.c
+--- linux-2.6.38.7/arch/x86/kernel/cpu/mcheck/mce.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/cpu/mcheck/mce.c 2011-04-28 19:57:25.000000000 -0400
+@@ -45,6 +45,7 @@
+ #include <asm/ipi.h>
+ #include <asm/mce.h>
+ #include <asm/msr.h>
++#include <asm/local.h>
+
+ #include "mce-internal.h"
+
+@@ -219,7 +220,7 @@ static void print_mce(struct mce *m)
+ !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
+ m->cs, m->ip);
+
+- if (m->cs == __KERNEL_CS)
++ if (m->cs == __KERNEL_CS || m->cs == __KERNEXEC_KERNEL_CS)
+ print_symbol("{%s}", m->ip);
+ pr_cont("\n");
+ }
+@@ -243,10 +244,10 @@ static void print_mce(struct mce *m)
+
+ #define PANIC_TIMEOUT 5 /* 5 seconds */
+
+-static atomic_t mce_paniced;
++static atomic_unchecked_t mce_paniced;
+
+ static int fake_panic;
+-static atomic_t mce_fake_paniced;
++static atomic_unchecked_t mce_fake_paniced;
+
+ /* Panic in progress. Enable interrupts and wait for final IPI */
+ static void wait_for_panic(void)
+@@ -270,7 +271,7 @@ static void mce_panic(char *msg, struct
+ /*
+ * Make sure only one CPU runs in machine check panic
+ */
+- if (atomic_inc_return(&mce_paniced) > 1)
++ if (atomic_inc_return_unchecked(&mce_paniced) > 1)
+ wait_for_panic();
+ barrier();
+
+@@ -278,7 +279,7 @@ static void mce_panic(char *msg, struct
+ console_verbose();
+ } else {
+ /* Don't log too much for fake panic */
+- if (atomic_inc_return(&mce_fake_paniced) > 1)
++ if (atomic_inc_return_unchecked(&mce_fake_paniced) > 1)
+ return;
+ }
+ /* First print corrected ones that are still unlogged */
+@@ -646,7 +647,7 @@ static int mce_timed_out(u64 *t)
+ * might have been modified by someone else.
+ */
+ rmb();
+- if (atomic_read(&mce_paniced))
++ if (atomic_read_unchecked(&mce_paniced))
+ wait_for_panic();
+ if (!monarch_timeout)
+ goto out;
+@@ -1460,14 +1461,14 @@ void __cpuinit mcheck_cpu_init(struct cp
+ */
+
+ static DEFINE_SPINLOCK(mce_state_lock);
+-static int open_count; /* #times opened */
++static local_t open_count; /* #times opened */
+ static int open_exclu; /* already open exclusive? */
+
+ static int mce_open(struct inode *inode, struct file *file)
+ {
+ spin_lock(&mce_state_lock);
+
+- if (open_exclu || (open_count && (file->f_flags & O_EXCL))) {
++ if (open_exclu || (local_read(&open_count) && (file->f_flags & O_EXCL))) {
+ spin_unlock(&mce_state_lock);
+
+ return -EBUSY;
+@@ -1475,7 +1476,7 @@ static int mce_open(struct inode *inode,
+
+ if (file->f_flags & O_EXCL)
+ open_exclu = 1;
+- open_count++;
++ local_inc(&open_count);
+
+ spin_unlock(&mce_state_lock);
+
+@@ -1486,7 +1487,7 @@ static int mce_release(struct inode *ino
+ {
+ spin_lock(&mce_state_lock);
+
+- open_count--;
++ local_dec(&open_count);
+ open_exclu = 0;
+
+ spin_unlock(&mce_state_lock);
+@@ -1658,8 +1659,7 @@ static long mce_ioctl(struct file *f, un
+ }
+ }
+
+-/* Modified in mce-inject.c, so not static or const */
+-struct file_operations mce_chrdev_ops = {
++struct file_operations mce_chrdev_ops = { /* Modified in mce-inject.c, so not static or const */
+ .open = mce_open,
+ .release = mce_release,
+ .read = mce_read,
+@@ -2171,7 +2171,7 @@ struct dentry *mce_get_debugfs_dir(void)
+ static void mce_reset(void)
+ {
+ cpu_missing = 0;
+- atomic_set(&mce_fake_paniced, 0);
++ atomic_set_unchecked(&mce_fake_paniced, 0);
+ atomic_set(&mce_executing, 0);
+ atomic_set(&mce_callin, 0);
+ atomic_set(&global_nwo, 0);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/cpu/mtrr/main.c linux-2.6.38.7/arch/x86/kernel/cpu/mtrr/main.c
+--- linux-2.6.38.7/arch/x86/kernel/cpu/mtrr/main.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/cpu/mtrr/main.c 2011-04-28 19:34:14.000000000 -0400
+@@ -61,7 +61,7 @@ static DEFINE_MUTEX(mtrr_mutex);
+ u64 size_or_mask, size_and_mask;
+ static bool mtrr_aps_delayed_init;
+
+-static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM];
++static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM] __read_only;
+
+ const struct mtrr_ops *mtrr_if;
+
+diff -urNp linux-2.6.38.7/arch/x86/kernel/cpu/mtrr/mtrr.h linux-2.6.38.7/arch/x86/kernel/cpu/mtrr/mtrr.h
+--- linux-2.6.38.7/arch/x86/kernel/cpu/mtrr/mtrr.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/cpu/mtrr/mtrr.h 2011-04-28 19:34:14.000000000 -0400
+@@ -12,19 +12,19 @@
+ extern unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
+
+ struct mtrr_ops {
+- u32 vendor;
+- u32 use_intel_if;
+- void (*set)(unsigned int reg, unsigned long base,
++ const u32 vendor;
++ const u32 use_intel_if;
++ void (* const set)(unsigned int reg, unsigned long base,
+ unsigned long size, mtrr_type type);
+- void (*set_all)(void);
++ void (* const set_all)(void);
+
+- void (*get)(unsigned int reg, unsigned long *base,
++ void (* const get)(unsigned int reg, unsigned long *base,
+ unsigned long *size, mtrr_type *type);
+- int (*get_free_region)(unsigned long base, unsigned long size,
++ int (* const get_free_region)(unsigned long base, unsigned long size,
+ int replace_reg);
+- int (*validate_add_page)(unsigned long base, unsigned long size,
++ int (* const validate_add_page)(unsigned long base, unsigned long size,
+ unsigned int type);
+- int (*have_wrcomb)(void);
++ int (* const have_wrcomb)(void);
+ };
+
+ extern int generic_get_free_region(unsigned long base, unsigned long size,
+diff -urNp linux-2.6.38.7/arch/x86/kernel/cpu/perf_event.c linux-2.6.38.7/arch/x86/kernel/cpu/perf_event.c
+--- linux-2.6.38.7/arch/x86/kernel/cpu/perf_event.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/cpu/perf_event.c 2011-05-16 21:47:08.000000000 -0400
+@@ -674,6 +674,8 @@ static int x86_schedule_events(struct cp
+ int i, j, w, wmax, num = 0;
+ struct hw_perf_event *hwc;
+
++ pax_track_stack();
++
+ bitmap_zero(used_mask, X86_PMC_IDX_MAX);
+
+ for (i = 0; i < n; i++) {
+@@ -1781,7 +1783,7 @@ perf_callchain_user(struct perf_callchai
+ break;
+
+ perf_callchain_store(entry, frame.return_address);
+- fp = frame.next_frame;
++ fp = (__force const void __user *)frame.next_frame;
+ }
+ }
+
+diff -urNp linux-2.6.38.7/arch/x86/kernel/crash.c linux-2.6.38.7/arch/x86/kernel/crash.c
+--- linux-2.6.38.7/arch/x86/kernel/crash.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/crash.c 2011-04-28 19:34:14.000000000 -0400
+@@ -42,7 +42,7 @@ static void kdump_nmi_callback(int cpu,
+ regs = args->regs;
+
+ #ifdef CONFIG_X86_32
+- if (!user_mode_vm(regs)) {
++ if (!user_mode(regs)) {
+ crash_fixup_ss_esp(&fixed_regs, regs);
+ regs = &fixed_regs;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/doublefault_32.c linux-2.6.38.7/arch/x86/kernel/doublefault_32.c
+--- linux-2.6.38.7/arch/x86/kernel/doublefault_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/doublefault_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -11,7 +11,7 @@
+
+ #define DOUBLEFAULT_STACKSIZE (1024)
+ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
+-#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
++#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE-2)
+
+ #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM)
+
+@@ -21,7 +21,7 @@ static void doublefault_fn(void)
+ unsigned long gdt, tss;
+
+ store_gdt(&gdt_desc);
+- gdt = gdt_desc.address;
++ gdt = (unsigned long)gdt_desc.address;
+
+ printk(KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size);
+
+@@ -58,10 +58,10 @@ struct tss_struct doublefault_tss __cach
+ /* 0x2 bit is always set */
+ .flags = X86_EFLAGS_SF | 0x2,
+ .sp = STACK_START,
+- .es = __USER_DS,
++ .es = __KERNEL_DS,
+ .cs = __KERNEL_CS,
+ .ss = __KERNEL_DS,
+- .ds = __USER_DS,
++ .ds = __KERNEL_DS,
+ .fs = __KERNEL_PERCPU,
+
+ .__cr3 = __pa_nodebug(swapper_pg_dir),
+diff -urNp linux-2.6.38.7/arch/x86/kernel/dumpstack_32.c linux-2.6.38.7/arch/x86/kernel/dumpstack_32.c
+--- linux-2.6.38.7/arch/x86/kernel/dumpstack_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/dumpstack_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -37,15 +37,12 @@ void dump_trace(struct task_struct *task
+
+ bp = stack_frame(task, regs);
+ for (;;) {
+- struct thread_info *context;
++ void *stack_start = (void *)((unsigned long)stack & ~(THREAD_SIZE-1));
++ bp = ops->walk_stack(task, stack_start, stack, bp, ops, data, NULL, &graph);
+
+- context = (struct thread_info *)
+- ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+- bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph);
+-
+- stack = (unsigned long *)context->previous_esp;
+- if (!stack)
++ if (stack_start == task_stack_page(task))
+ break;
++ stack = *(unsigned long **)stack_start;
+ if (ops->stack(data, "IRQ") < 0)
+ break;
+ touch_nmi_watchdog();
+@@ -95,21 +92,22 @@ void show_registers(struct pt_regs *regs
+ * When in-kernel, we also print out the stack and code at the
+ * time of the fault..
+ */
+- if (!user_mode_vm(regs)) {
++ if (!user_mode(regs)) {
+ unsigned int code_prologue = code_bytes * 43 / 64;
+ unsigned int code_len = code_bytes;
+ unsigned char c;
+ u8 *ip;
++ unsigned long cs_base = get_desc_base(&get_cpu_gdt_table(smp_processor_id())[(0xffff & regs->cs) >> 3]);
+
+ printk(KERN_EMERG "Stack:\n");
+ show_stack_log_lvl(NULL, regs, &regs->sp, KERN_EMERG);
+
+ printk(KERN_EMERG "Code: ");
+
+- ip = (u8 *)regs->ip - code_prologue;
++ ip = (u8 *)regs->ip - code_prologue + cs_base;
+ if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
+ /* try starting at IP */
+- ip = (u8 *)regs->ip;
++ ip = (u8 *)regs->ip + cs_base;
+ code_len = code_len - code_prologue + 1;
+ }
+ for (i = 0; i < code_len; i++, ip++) {
+@@ -118,7 +116,7 @@ void show_registers(struct pt_regs *regs
+ printk(" Bad EIP value.");
+ break;
+ }
+- if (ip == (u8 *)regs->ip)
++ if (ip == (u8 *)regs->ip + cs_base)
+ printk("<%02x> ", c);
+ else
+ printk("%02x ", c);
+@@ -131,6 +129,7 @@ int is_valid_bugaddr(unsigned long ip)
+ {
+ unsigned short ud2;
+
++ ip = ktla_ktva(ip);
+ if (ip < PAGE_OFFSET)
+ return 0;
+ if (probe_kernel_address((unsigned short *)ip, ud2))
+diff -urNp linux-2.6.38.7/arch/x86/kernel/dumpstack_64.c linux-2.6.38.7/arch/x86/kernel/dumpstack_64.c
+--- linux-2.6.38.7/arch/x86/kernel/dumpstack_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/dumpstack_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -147,10 +147,10 @@ void dump_trace(struct task_struct *task
+ unsigned long *irq_stack_end =
+ (unsigned long *)per_cpu(irq_stack_ptr, cpu);
+ unsigned used = 0;
+- struct thread_info *tinfo;
+ int graph = 0;
+ unsigned long dummy;
+ unsigned long bp;
++ void *stack_start;
+
+ if (!task)
+ task = current;
+@@ -167,10 +167,10 @@ void dump_trace(struct task_struct *task
+ * current stack address. If the stacks consist of nested
+ * exceptions
+ */
+- tinfo = task_thread_info(task);
+ for (;;) {
+ char *id;
+ unsigned long *estack_end;
++
+ estack_end = in_exception_stack(cpu, (unsigned long)stack,
+ &used, &id);
+
+@@ -178,7 +178,7 @@ void dump_trace(struct task_struct *task
+ if (ops->stack(data, id) < 0)
+ break;
+
+- bp = ops->walk_stack(tinfo, stack, bp, ops,
++ bp = ops->walk_stack(task, estack_end - EXCEPTION_STKSZ, stack, bp, ops,
+ data, estack_end, &graph);
+ ops->stack(data, "<EOE>");
+ /*
+@@ -197,7 +197,7 @@ void dump_trace(struct task_struct *task
+ if (in_irq_stack(stack, irq_stack, irq_stack_end)) {
+ if (ops->stack(data, "IRQ") < 0)
+ break;
+- bp = ops->walk_stack(tinfo, stack, bp,
++ bp = ops->walk_stack(task, irq_stack, stack, bp,
+ ops, data, irq_stack_end, &graph);
+ /*
+ * We link to the next stack (which would be
+@@ -218,7 +218,8 @@ void dump_trace(struct task_struct *task
+ /*
+ * This handles the process stack:
+ */
+- bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph);
++ stack_start = (void *)((unsigned long)stack & ~(THREAD_SIZE-1));
++ bp = ops->walk_stack(task, stack_start, stack, bp, ops, data, NULL, &graph);
+ put_cpu();
+ }
+ EXPORT_SYMBOL(dump_trace);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/dumpstack.c linux-2.6.38.7/arch/x86/kernel/dumpstack.c
+--- linux-2.6.38.7/arch/x86/kernel/dumpstack.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/dumpstack.c 2011-04-28 19:34:14.000000000 -0400
+@@ -2,6 +2,9 @@
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ */
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++#define __INCLUDED_BY_HIDESYM 1
++#endif
+ #include <linux/kallsyms.h>
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
+@@ -27,7 +30,7 @@ static int die_counter;
+
+ void printk_address(unsigned long address, int reliable)
+ {
+- printk(" [<%p>] %s%pS\n", (void *) address,
++ printk(" [<%p>] %s%pA\n", (void *) address,
+ reliable ? "" : "? ", (void *) address);
+ }
+
+@@ -35,9 +38,8 @@ void printk_address(unsigned long addres
+ static void
+ print_ftrace_graph_addr(unsigned long addr, void *data,
+ const struct stacktrace_ops *ops,
+- struct thread_info *tinfo, int *graph)
++ struct task_struct *task, int *graph)
+ {
+- struct task_struct *task = tinfo->task;
+ unsigned long ret_addr;
+ int index = task->curr_ret_stack;
+
+@@ -58,7 +60,7 @@ print_ftrace_graph_addr(unsigned long ad
+ static inline void
+ print_ftrace_graph_addr(unsigned long addr, void *data,
+ const struct stacktrace_ops *ops,
+- struct thread_info *tinfo, int *graph)
++ struct task_struct *task, int *graph)
+ { }
+ #endif
+
+@@ -69,10 +71,8 @@ print_ftrace_graph_addr(unsigned long ad
+ * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
+ */
+
+-static inline int valid_stack_ptr(struct thread_info *tinfo,
+- void *p, unsigned int size, void *end)
++static inline int valid_stack_ptr(void *t, void *p, unsigned int size, void *end)
+ {
+- void *t = tinfo;
+ if (end) {
+ if (p < end && p >= (end-THREAD_SIZE))
+ return 1;
+@@ -83,14 +83,14 @@ static inline int valid_stack_ptr(struct
+ }
+
+ unsigned long
+-print_context_stack(struct thread_info *tinfo,
++print_context_stack(struct task_struct *task, void *stack_start,
+ unsigned long *stack, unsigned long bp,
+ const struct stacktrace_ops *ops, void *data,
+ unsigned long *end, int *graph)
+ {
+ struct stack_frame *frame = (struct stack_frame *)bp;
+
+- while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
++ while (valid_stack_ptr(stack_start, stack, sizeof(*stack), end)) {
+ unsigned long addr;
+
+ addr = *stack;
+@@ -102,7 +102,7 @@ print_context_stack(struct thread_info *
+ } else {
+ ops->address(data, addr, 0);
+ }
+- print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
++ print_ftrace_graph_addr(addr, data, ops, task, graph);
+ }
+ stack++;
+ }
+@@ -111,7 +111,7 @@ print_context_stack(struct thread_info *
+ EXPORT_SYMBOL_GPL(print_context_stack);
+
+ unsigned long
+-print_context_stack_bp(struct thread_info *tinfo,
++print_context_stack_bp(struct task_struct *task, void *stack_start,
+ unsigned long *stack, unsigned long bp,
+ const struct stacktrace_ops *ops, void *data,
+ unsigned long *end, int *graph)
+@@ -119,7 +119,7 @@ print_context_stack_bp(struct thread_inf
+ struct stack_frame *frame = (struct stack_frame *)bp;
+ unsigned long *ret_addr = &frame->return_address;
+
+- while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) {
++ while (valid_stack_ptr(stack_start, ret_addr, sizeof(*ret_addr), end)) {
+ unsigned long addr = *ret_addr;
+
+ if (!__kernel_text_address(addr))
+@@ -128,7 +128,7 @@ print_context_stack_bp(struct thread_inf
+ ops->address(data, addr, 1);
+ frame = frame->next_frame;
+ ret_addr = &frame->return_address;
+- print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
++ print_ftrace_graph_addr(addr, data, ops, task, graph);
+ }
+
+ return (unsigned long)frame;
+@@ -200,7 +200,7 @@ void dump_stack(void)
+ unsigned long stack;
+
+ printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+- current->pid, current->comm, print_tainted(),
++ task_pid_nr(current), current->comm, print_tainted(),
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+@@ -236,6 +236,8 @@ unsigned __kprobes long oops_begin(void)
+ }
+ EXPORT_SYMBOL_GPL(oops_begin);
+
++extern void gr_handle_kernel_exploit(void);
++
+ void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
+ {
+ if (regs && kexec_should_crash(current))
+@@ -257,7 +259,10 @@ void __kprobes oops_end(unsigned long fl
+ panic("Fatal exception in interrupt");
+ if (panic_on_oops)
+ panic("Fatal exception");
+- do_exit(signr);
++
++ gr_handle_kernel_exploit();
++
++ do_group_exit(signr);
+ }
+
+ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+@@ -284,7 +289,7 @@ int __kprobes __die(const char *str, str
+
+ show_registers(regs);
+ #ifdef CONFIG_X86_32
+- if (user_mode_vm(regs)) {
++ if (user_mode(regs)) {
+ sp = regs->sp;
+ ss = regs->ss & 0xffff;
+ } else {
+@@ -312,7 +317,7 @@ void die(const char *str, struct pt_regs
+ unsigned long flags = oops_begin();
+ int sig = SIGSEGV;
+
+- if (!user_mode_vm(regs))
++ if (!user_mode(regs))
+ report_bug(regs->ip, regs);
+
+ if (__die(str, regs, err))
+diff -urNp linux-2.6.38.7/arch/x86/kernel/early_printk.c linux-2.6.38.7/arch/x86/kernel/early_printk.c
+--- linux-2.6.38.7/arch/x86/kernel/early_printk.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/early_printk.c 2011-05-16 21:47:08.000000000 -0400
+@@ -7,6 +7,7 @@
+ #include <linux/pci_regs.h>
+ #include <linux/pci_ids.h>
+ #include <linux/errno.h>
++#include <linux/sched.h>
+ #include <asm/io.h>
+ #include <asm/processor.h>
+ #include <asm/fcntl.h>
+@@ -179,6 +180,8 @@ asmlinkage void early_printk(const char
+ int n;
+ va_list ap;
+
++ pax_track_stack();
++
+ va_start(ap, fmt);
+ n = vscnprintf(buf, sizeof(buf), fmt, ap);
+ early_console->write(early_console, buf, n);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/entry_32.S linux-2.6.38.7/arch/x86/kernel/entry_32.S
+--- linux-2.6.38.7/arch/x86/kernel/entry_32.S 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/entry_32.S 2011-05-22 23:03:34.000000000 -0400
+@@ -183,13 +183,146 @@
+ /*CFI_REL_OFFSET gs, PT_GS*/
+ .endm
+ .macro SET_KERNEL_GS reg
++
++#ifdef CONFIG_CC_STACKPROTECTOR
+ movl $(__KERNEL_STACK_CANARY), \reg
++#elif defined(CONFIG_PAX_MEMORY_UDEREF)
++ movl $(__USER_DS), \reg
++#else
++ xorl \reg, \reg
++#endif
++
+ movl \reg, %gs
+ .endm
+
+ #endif /* CONFIG_X86_32_LAZY_GS */
+
+-.macro SAVE_ALL
++.macro pax_enter_kernel
++#ifdef CONFIG_PAX_KERNEXEC
++ call pax_enter_kernel
++#endif
++.endm
++
++.macro pax_exit_kernel
++#ifdef CONFIG_PAX_KERNEXEC
++ call pax_exit_kernel
++#endif
++.endm
++
++#ifdef CONFIG_PAX_KERNEXEC
++ENTRY(pax_enter_kernel)
++#ifdef CONFIG_PARAVIRT
++ pushl %eax
++ pushl %ecx
++ call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0)
++ mov %eax, %esi
++#else
++ mov %cr0, %esi
++#endif
++ bts $16, %esi
++ jnc 1f
++ mov %cs, %esi
++ cmp $__KERNEL_CS, %esi
++ jz 3f
++ ljmp $__KERNEL_CS, $3f
++1: ljmp $__KERNEXEC_KERNEL_CS, $2f
++2:
++#ifdef CONFIG_PARAVIRT
++ mov %esi, %eax
++ call PARA_INDIRECT(pv_cpu_ops+PV_CPU_write_cr0)
++#else
++ mov %esi, %cr0
++#endif
++3:
++#ifdef CONFIG_PARAVIRT
++ popl %ecx
++ popl %eax
++#endif
++ ret
++ENDPROC(pax_enter_kernel)
++
++ENTRY(pax_exit_kernel)
++#ifdef CONFIG_PARAVIRT
++ pushl %eax
++ pushl %ecx
++#endif
++ mov %cs, %esi
++ cmp $__KERNEXEC_KERNEL_CS, %esi
++ jnz 2f
++#ifdef CONFIG_PARAVIRT
++ call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0);
++ mov %eax, %esi
++#else
++ mov %cr0, %esi
++#endif
++ btr $16, %esi
++ ljmp $__KERNEL_CS, $1f
++1:
++#ifdef CONFIG_PARAVIRT
++ mov %esi, %eax
++ call PARA_INDIRECT(pv_cpu_ops+PV_CPU_write_cr0);
++#else
++ mov %esi, %cr0
++#endif
++2:
++#ifdef CONFIG_PARAVIRT
++ popl %ecx
++ popl %eax
++#endif
++ ret
++ENDPROC(pax_exit_kernel)
++#endif
++
++.macro pax_erase_kstack
++#ifdef CONFIG_PAX_MEMORY_STACKLEAK
++ call pax_erase_kstack
++#endif
++.endm
++
++#ifdef CONFIG_PAX_MEMORY_STACKLEAK
++/*
++ * ebp: thread_info
++ * ecx, edx: can be clobbered
++ */
++ENTRY(pax_erase_kstack)
++ pushl %edi
++ pushl %eax
++
++ mov TI_lowest_stack(%ebp), %edi
++ mov $-0xBEEF, %eax
++ std
++
++1: mov %edi, %ecx
++ and $THREAD_SIZE_asm - 1, %ecx
++ shr $2, %ecx
++ repne scasl
++ jecxz 2f
++
++ cmp $2*16, %ecx
++ jc 2f
++
++ mov $2*16, %ecx
++ repe scasl
++ jecxz 2f
++ jne 1b
++
++2: cld
++ mov %esp, %ecx
++ sub %edi, %ecx
++ shr $2, %ecx
++ rep stosl
++
++ mov TI_task_thread_sp0(%ebp), %edi
++ sub $128, %edi
++ mov %edi, TI_lowest_stack(%ebp)
++
++ popl %eax
++ popl %edi
++ ret
++ENDPROC(pax_erase_kstack)
++#endif
++
++.macro __SAVE_ALL _DS
+ cld
+ PUSH_GS
+ pushl_cfi %fs
+@@ -212,7 +345,7 @@
+ CFI_REL_OFFSET ecx, 0
+ pushl_cfi %ebx
+ CFI_REL_OFFSET ebx, 0
+- movl $(__USER_DS), %edx
++ movl $\_DS, %edx
+ movl %edx, %ds
+ movl %edx, %es
+ movl $(__KERNEL_PERCPU), %edx
+@@ -220,6 +353,15 @@
+ SET_KERNEL_GS %edx
+ .endm
+
++.macro SAVE_ALL
++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF)
++ __SAVE_ALL __KERNEL_DS
++ pax_enter_kernel
++#else
++ __SAVE_ALL __USER_DS
++#endif
++.endm
++
+ .macro RESTORE_INT_REGS
+ popl_cfi %ebx
+ CFI_RESTORE ebx
+@@ -330,7 +472,15 @@ check_userspace:
+ movb PT_CS(%esp), %al
+ andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+ cmpl $USER_RPL, %eax
++
++#ifdef CONFIG_PAX_KERNEXEC
++ jae resume_userspace
++
++ PAX_EXIT_KERNEL
++ jmp resume_kernel
++#else
+ jb resume_kernel # not returning to v8086 or userspace
++#endif
+
+ ENTRY(resume_userspace)
+ LOCKDEP_SYS_EXIT
+@@ -342,7 +492,7 @@ ENTRY(resume_userspace)
+ andl $_TIF_WORK_MASK, %ecx # is there any work to be done on
+ # int/exception return?
+ jne work_pending
+- jmp restore_all
++ jmp restore_all_pax
+ END(ret_from_exception)
+
+ #ifdef CONFIG_PREEMPT
+@@ -392,23 +542,34 @@ sysenter_past_esp:
+ /*CFI_REL_OFFSET cs, 0*/
+ /*
+ * Push current_thread_info()->sysenter_return to the stack.
+- * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
+- * pushed above; +8 corresponds to copy_thread's esp0 setting.
+ */
+- pushl_cfi ((TI_sysenter_return)-THREAD_SIZE_asm+8+4*4)(%esp)
++ pushl_cfi $0
+ CFI_REL_OFFSET eip, 0
+
+ pushl_cfi %eax
+ SAVE_ALL
++ GET_THREAD_INFO(%ebp)
++ movl TI_sysenter_return(%ebp),%ebp
++ movl %ebp,PT_EIP(%esp)
+ ENABLE_INTERRUPTS(CLBR_NONE)
+
+ /*
+ * Load the potential sixth argument from user stack.
+ * Careful about security.
+ */
++ movl PT_OLDESP(%esp),%ebp
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ mov PT_OLDSS(%esp),%ds
++1: movl %ds:(%ebp),%ebp
++ push %ss
++ pop %ds
++#else
+ cmpl $__PAGE_OFFSET-3,%ebp
+ jae syscall_fault
+ 1: movl (%ebp),%ebp
++#endif
++
+ movl %ebp,PT_EBP(%esp)
+ .section __ex_table,"a"
+ .align 4
+@@ -431,12 +592,23 @@ sysenter_do_call:
+ testl $_TIF_ALLWORK_MASK, %ecx
+ jne sysexit_audit
+ sysenter_exit:
++
++#ifdef CONFIG_PAX_RANDKSTACK
++ pushl_cfi %eax
++ call pax_randomize_kstack
++ popl_cfi %eax
++#endif
++
++ pax_erase_kstack
++
+ /* if something modifies registers it must also disable sysexit */
+ movl PT_EIP(%esp), %edx
+ movl PT_OLDESP(%esp), %ecx
+ xorl %ebp,%ebp
+ TRACE_IRQS_ON
+ 1: mov PT_FS(%esp), %fs
++2: mov PT_DS(%esp), %ds
++3: mov PT_ES(%esp), %es
+ PTGS_TO_GS
+ ENABLE_INTERRUPTS_SYSEXIT
+
+@@ -453,6 +625,9 @@ sysenter_audit:
+ movl %eax,%edx /* 2nd arg: syscall number */
+ movl $AUDIT_ARCH_I386,%eax /* 1st arg: audit arch */
+ call audit_syscall_entry
++
++ pax_erase_kstack
++
+ pushl_cfi %ebx
+ movl PT_EAX(%esp),%eax /* reload syscall number */
+ jmp sysenter_do_call
+@@ -479,11 +654,17 @@ sysexit_audit:
+
+ CFI_ENDPROC
+ .pushsection .fixup,"ax"
+-2: movl $0,PT_FS(%esp)
++4: movl $0,PT_FS(%esp)
++ jmp 1b
++5: movl $0,PT_DS(%esp)
++ jmp 1b
++6: movl $0,PT_ES(%esp)
+ jmp 1b
+ .section __ex_table,"a"
+ .align 4
+- .long 1b,2b
++ .long 1b,4b
++ .long 2b,5b
++ .long 3b,6b
+ .popsection
+ PTGS_TO_GS_EX
+ ENDPROC(ia32_sysenter_target)
+@@ -516,6 +697,14 @@ syscall_exit:
+ testl $_TIF_ALLWORK_MASK, %ecx # current->work
+ jne syscall_exit_work
+
++restore_all_pax:
++
++#ifdef CONFIG_PAX_RANDKSTACK
++ call pax_randomize_kstack
++#endif
++
++ pax_erase_kstack
++
+ restore_all:
+ TRACE_IRQS_IRET
+ restore_all_notrace:
+@@ -575,14 +764,21 @@ ldt_ss:
+ * compensating for the offset by changing to the ESPFIX segment with
+ * a base address that matches for the difference.
+ */
+-#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8)
++#define GDT_ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)(%ebx)
+ mov %esp, %edx /* load kernel esp */
+ mov PT_OLDESP(%esp), %eax /* load userspace esp */
+ mov %dx, %ax /* eax: new kernel esp */
+ sub %eax, %edx /* offset (low word is 0) */
++#ifdef CONFIG_SMP
++ movl PER_CPU_VAR(cpu_number), %ebx
++ shll $PAGE_SHIFT_asm, %ebx
++ addl $cpu_gdt_table, %ebx
++#else
++ movl $cpu_gdt_table, %ebx
++#endif
+ shr $16, %edx
+- mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */
+- mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */
++ mov %dl, 4 + GDT_ESPFIX_SS /* bits 16..23 */
++ mov %dh, 7 + GDT_ESPFIX_SS /* bits 24..31 */
+ pushl_cfi $__ESPFIX_SS
+ pushl_cfi %eax /* new kernel esp */
+ /* Disable interrupts, but do not irqtrace this section: we
+@@ -611,29 +807,23 @@ work_resched:
+ movl TI_flags(%ebp), %ecx
+ andl $_TIF_WORK_MASK, %ecx # is there any work to be done other
+ # than syscall tracing?
+- jz restore_all
++ jz restore_all_pax
+ testb $_TIF_NEED_RESCHED, %cl
+ jnz work_resched
+
+ work_notifysig: # deal with pending signals and
+ # notify-resume requests
++ movl %esp, %eax
+ #ifdef CONFIG_VM86
+ testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
+- movl %esp, %eax
+- jne work_notifysig_v86 # returning to kernel-space or
++ jz 1f # returning to kernel-space or
+ # vm86-space
+- xorl %edx, %edx
+- call do_notify_resume
+- jmp resume_userspace_sig
+
+- ALIGN
+-work_notifysig_v86:
+ pushl_cfi %ecx # save ti_flags for do_notify_resume
+ call save_v86_state # %eax contains pt_regs pointer
+ popl_cfi %ecx
+ movl %eax, %esp
+-#else
+- movl %esp, %eax
++1:
+ #endif
+ xorl %edx, %edx
+ call do_notify_resume
+@@ -646,6 +836,9 @@ syscall_trace_entry:
+ movl $-ENOSYS,PT_EAX(%esp)
+ movl %esp, %eax
+ call syscall_trace_enter
++
++ pax_erase_kstack
++
+ /* What it returned is what we'll actually use. */
+ cmpl $(nr_syscalls), %eax
+ jnae syscall_call
+@@ -668,6 +861,10 @@ END(syscall_exit_work)
+
+ RING0_INT_FRAME # can't unwind into user space anyway
+ syscall_fault:
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ push %ss
++ pop %ds
++#endif
+ GET_THREAD_INFO(%ebp)
+ movl $-EFAULT,PT_EAX(%esp)
+ jmp resume_userspace
+@@ -750,6 +947,36 @@ ptregs_clone:
+ CFI_ENDPROC
+ ENDPROC(ptregs_clone)
+
++ ALIGN;
++ENTRY(kernel_execve)
++ CFI_STARTPROC
++ pushl_cfi %ebp
++ sub $PT_OLDSS+4,%esp
++ pushl_cfi %edi
++ pushl_cfi %ecx
++ pushl_cfi %eax
++ lea 3*4(%esp),%edi
++ mov $PT_OLDSS/4+1,%ecx
++ xorl %eax,%eax
++ rep stosl
++ popl_cfi %eax
++ popl_cfi %ecx
++ popl_cfi %edi
++ movl $X86_EFLAGS_IF,PT_EFLAGS(%esp)
++ pushl_cfi %esp
++ call sys_execve
++ add $4,%esp
++ CFI_ADJUST_CFA_OFFSET -4
++ GET_THREAD_INFO(%ebp)
++ test %eax,%eax
++ jz syscall_exit
++ add $PT_OLDSS+4,%esp
++ CFI_ADJUST_CFA_OFFSET -PT_OLDSS-4
++ popl_cfi %ebp
++ ret
++ CFI_ENDPROC
++ENDPROC(kernel_execve)
++
+ .macro FIXUP_ESPFIX_STACK
+ /*
+ * Switch back for ESPFIX stack to the normal zerobased stack
+@@ -759,8 +986,15 @@ ENDPROC(ptregs_clone)
+ * normal stack and adjusts ESP with the matching offset.
+ */
+ /* fixup the stack */
+- mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */
+- mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */
++#ifdef CONFIG_SMP
++ movl PER_CPU_VAR(cpu_number), %ebx
++ shll $PAGE_SHIFT_asm, %ebx
++ addl $cpu_gdt_table, %ebx
++#else
++ movl $cpu_gdt_table, %ebx
++#endif
++ mov 4 + GDT_ESPFIX_SS, %al /* bits 16..23 */
++ mov 7 + GDT_ESPFIX_SS, %ah /* bits 24..31 */
+ shl $16, %eax
+ addl %esp, %eax /* the adjusted stack pointer */
+ pushl_cfi $__KERNEL_DS
+@@ -1211,7 +1445,6 @@ return_to_handler:
+ jmp *%ecx
+ #endif
+
+-.section .rodata,"a"
+ #include "syscall_table_32.S"
+
+ syscall_table_size=(.-sys_call_table)
+@@ -1257,9 +1490,12 @@ error_code:
+ movl $-1, PT_ORIG_EAX(%esp) # no syscall to restart
+ REG_TO_PTGS %ecx
+ SET_KERNEL_GS %ecx
+- movl $(__USER_DS), %ecx
++ movl $(__KERNEL_DS), %ecx
+ movl %ecx, %ds
+ movl %ecx, %es
++
++ pax_enter_kernel
++
+ TRACE_IRQS_OFF
+ movl %esp,%eax # pt_regs pointer
+ call *%edi
+@@ -1344,6 +1580,9 @@ nmi_stack_correct:
+ xorl %edx,%edx # zero error code
+ movl %esp,%eax # pt_regs pointer
+ call do_nmi
++
++ pax_exit_kernel
++
+ jmp restore_all_notrace
+ CFI_ENDPROC
+
+@@ -1380,6 +1619,9 @@ nmi_espfix_stack:
+ FIXUP_ESPFIX_STACK # %eax == %esp
+ xorl %edx,%edx # zero error code
+ call do_nmi
++
++ pax_exit_kernel
++
+ RESTORE_REGS
+ lss 12+4(%esp), %esp # back to espfix stack
+ CFI_ADJUST_CFA_OFFSET -24
+diff -urNp linux-2.6.38.7/arch/x86/kernel/entry_64.S linux-2.6.38.7/arch/x86/kernel/entry_64.S
+--- linux-2.6.38.7/arch/x86/kernel/entry_64.S 2011-04-18 17:27:13.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/entry_64.S 2011-05-22 23:19:17.000000000 -0400
+@@ -53,6 +53,7 @@
+ #include <asm/paravirt.h>
+ #include <asm/ftrace.h>
+ #include <asm/percpu.h>
++#include <asm/pgtable.h>
+
+ /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
+ #include <linux/elf-em.h>
+@@ -174,6 +175,259 @@ ENTRY(native_usergs_sysret64)
+ ENDPROC(native_usergs_sysret64)
+ #endif /* CONFIG_PARAVIRT */
+
++ .macro ljmpq sel, off
++#if defined(CONFIG_MPSC) || defined(CONFIG_MCORE2) || defined (CONFIG_MATOM)
++ .byte 0x48; ljmp *1234f(%rip)
++ .pushsection .rodata
++ .align 16
++ 1234: .quad \off; .word \sel
++ .popsection
++#else
++ pushq $\sel
++ pushq $\off
++ lretq
++#endif
++ .endm
++
++ .macro pax_enter_kernel
++#ifdef CONFIG_PAX_KERNEXEC
++ call pax_enter_kernel
++#endif
++ .endm
++
++ .macro pax_exit_kernel
++#ifdef CONFIG_PAX_KERNEXEC
++ call pax_exit_kernel
++#endif
++ .endm
++
++#ifdef CONFIG_PAX_KERNEXEC
++ENTRY(pax_enter_kernel)
++ pushq %rdi
++
++#ifdef CONFIG_PARAVIRT
++ PV_SAVE_REGS(CLBR_RDI)
++#endif
++
++ GET_CR0_INTO_RDI
++ bts $16,%rdi
++ jnc 1f
++ mov %cs,%edi
++ cmp $__KERNEL_CS,%edi
++ jz 3f
++ ljmpq __KERNEL_CS,3f
++1: ljmpq __KERNEXEC_KERNEL_CS,2f
++2: SET_RDI_INTO_CR0
++3:
++
++#ifdef CONFIG_PARAVIRT
++ PV_RESTORE_REGS(CLBR_RDI)
++#endif
++
++ popq %rdi
++ retq
++ENDPROC(pax_enter_kernel)
++
++ENTRY(pax_exit_kernel)
++ pushq %rdi
++
++#ifdef CONFIG_PARAVIRT
++ PV_SAVE_REGS(CLBR_RDI)
++#endif
++
++ mov %cs,%rdi
++ cmp $__KERNEXEC_KERNEL_CS,%edi
++ jnz 2f
++ GET_CR0_INTO_RDI
++ btr $16,%rdi
++ ljmpq __KERNEL_CS,1f
++1: SET_RDI_INTO_CR0
++2:
++
++#ifdef CONFIG_PARAVIRT
++ PV_RESTORE_REGS(CLBR_RDI);
++#endif
++
++ popq %rdi
++ retq
++ENDPROC(pax_exit_kernel)
++#endif
++
++ .macro pax_enter_kernel_user
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ call pax_enter_kernel_user
++#endif
++ .endm
++
++ .macro pax_exit_kernel_user
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ call pax_exit_kernel_user
++#endif
++#ifdef CONFIG_PAX_RANDKSTACK
++ push %rax
++ call pax_randomize_kstack
++ pop %rax
++#endif
++#ifdef CONFIG_PAX_MEMORY_STACKLEAK
++ call pax_erase_kstack
++#endif
++ .endm
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ENTRY(pax_enter_kernel_user)
++ pushq %rdi
++ pushq %rbx
++
++#ifdef CONFIG_PARAVIRT
++ PV_SAVE_REGS(CLBR_RDI)
++#endif
++
++ GET_CR3_INTO_RDI
++ mov %rdi,%rbx
++ add $__START_KERNEL_map,%rbx
++ sub phys_base(%rip),%rbx
++
++#ifdef CONFIG_PARAVIRT
++ pushq %rdi
++ cmpl $0, pv_info+PARAVIRT_enabled
++ jz 1f
++ i = 0
++ .rept USER_PGD_PTRS
++ mov i*8(%rbx),%rsi
++ mov $0,%sil
++ lea i*8(%rbx),%rdi
++ call PARA_INDIRECT(pv_mmu_ops+PV_MMU_set_pgd)
++ i = i + 1
++ .endr
++ jmp 2f
++1:
++#endif
++
++ i = 0
++ .rept USER_PGD_PTRS
++ movb $0,i*8(%rbx)
++ i = i + 1
++ .endr
++
++#ifdef CONFIG_PARAVIRT
++2: popq %rdi
++#endif
++ SET_RDI_INTO_CR3
++
++#ifdef CONFIG_PAX_KERNEXEC
++ GET_CR0_INTO_RDI
++ bts $16,%rdi
++ SET_RDI_INTO_CR0
++#endif
++
++#ifdef CONFIG_PARAVIRT
++ PV_RESTORE_REGS(CLBR_RDI)
++#endif
++
++ popq %rbx
++ popq %rdi
++ retq
++ENDPROC(pax_enter_kernel_user)
++
++ENTRY(pax_exit_kernel_user)
++ push %rdi
++
++#ifdef CONFIG_PARAVIRT
++ pushq %rbx
++ PV_SAVE_REGS(CLBR_RDI)
++#endif
++
++#ifdef CONFIG_PAX_KERNEXEC
++ GET_CR0_INTO_RDI
++ btr $16,%rdi
++ SET_RDI_INTO_CR0
++#endif
++
++ GET_CR3_INTO_RDI
++ add $__START_KERNEL_map,%rdi
++ sub phys_base(%rip),%rdi
++
++#ifdef CONFIG_PARAVIRT
++ cmpl $0, pv_info+PARAVIRT_enabled
++ jz 1f
++ mov %rdi,%rbx
++ i = 0
++ .rept USER_PGD_PTRS
++ mov i*8(%rbx),%rsi
++ mov $0x67,%sil
++ lea i*8(%rbx),%rdi
++ call PARA_INDIRECT(pv_mmu_ops+PV_MMU_set_pgd)
++ i = i + 1
++ .endr
++ jmp 2f
++1:
++#endif
++
++ i = 0
++ .rept USER_PGD_PTRS
++ movb $0x67,i*8(%rdi)
++ i = i + 1
++ .endr
++
++#ifdef CONFIG_PARAVIRT
++2: PV_RESTORE_REGS(CLBR_RDI)
++ popq %rbx
++#endif
++
++ popq %rdi
++ retq
++ENDPROC(pax_exit_kernel_user)
++#endif
++
++ .macro pax_erase_kstack
++#ifdef CONFIG_PAX_MEMORY_STACKLEAK
++ call pax_erase_kstack
++#endif
++ .endm
++
++#ifdef CONFIG_PAX_MEMORY_STACKLEAK
++/*
++ * r10: thread_info
++ * rcx, rdx: can be clobbered
++ */
++ENTRY(pax_erase_kstack)
++ pushq %rdi
++ pushq %rax
++
++ GET_THREAD_INFO(%r10)
++ mov TI_lowest_stack(%r10), %rdi
++ mov $-0xBEEF, %rax
++ std
++
++1: mov %edi, %ecx
++ and $THREAD_SIZE_asm - 1, %ecx
++ shr $3, %ecx
++ repne scasq
++ jecxz 2f
++
++ cmp $2*8, %ecx
++ jc 2f
++
++ mov $2*8, %ecx
++ repe scasq
++ jecxz 2f
++ jne 1b
++
++2: cld
++ mov %esp, %ecx
++ sub %edi, %ecx
++ shr $3, %ecx
++ rep stosq
++
++ mov TI_task_thread_sp0(%r10), %rdi
++ sub $256, %rdi
++ mov %rdi, TI_lowest_stack(%r10)
++
++ popq %rax
++ popq %rdi
++ ret
++ENDPROC(pax_erase_kstack)
++#endif
+
+ .macro TRACE_IRQS_IRETQ offset=ARGOFFSET
+ #ifdef CONFIG_TRACE_IRQFLAGS
+@@ -316,7 +570,7 @@ ENTRY(save_args)
+ leaq -RBP+8(%rsp),%rdi /* arg1 for handler */
+ movq_cfi rbp, 8 /* push %rbp */
+ leaq 8(%rsp), %rbp /* mov %rsp, %ebp */
+- testl $3, CS(%rdi)
++ testb $3, CS(%rdi)
+ je 1f
+ SWAPGS
+ /*
+@@ -407,7 +661,7 @@ ENTRY(ret_from_fork)
+
+ RESTORE_REST
+
+- testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread?
++ testb $3, CS-ARGOFFSET(%rsp) # from kernel_thread?
+ je int_ret_from_sys_call
+
+ testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET
+@@ -453,7 +707,7 @@ END(ret_from_fork)
+ ENTRY(system_call)
+ CFI_STARTPROC simple
+ CFI_SIGNAL_FRAME
+- CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET
++ CFI_DEF_CFA rsp,0
+ CFI_REGISTER rip,rcx
+ /*CFI_REGISTER rflags,r11*/
+ SWAPGS_UNSAFE_STACK
+@@ -466,12 +720,13 @@ ENTRY(system_call_after_swapgs)
+
+ movq %rsp,PER_CPU_VAR(old_rsp)
+ movq PER_CPU_VAR(kernel_stack),%rsp
++ pax_enter_kernel_user
+ /*
+ * No need to follow this irqs off/on section - it's straight
+ * and short:
+ */
+ ENABLE_INTERRUPTS(CLBR_NONE)
+- SAVE_ARGS 8,1
++ SAVE_ARGS 8*6,1
+ movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
+ movq %rcx,RIP-ARGOFFSET(%rsp)
+ CFI_REL_OFFSET rip,RIP-ARGOFFSET
+@@ -500,6 +755,7 @@ sysret_check:
+ andl %edi,%edx
+ jnz sysret_careful
+ CFI_REMEMBER_STATE
++ pax_exit_kernel_user
+ /*
+ * sysretq will re-enable interrupts:
+ */
+@@ -558,6 +814,9 @@ auditsys:
+ movq %rax,%rsi /* 2nd arg: syscall number */
+ movl $AUDIT_ARCH_X86_64,%edi /* 1st arg: audit arch */
+ call audit_syscall_entry
++
++ pax_erase_kstack
++
+ LOAD_ARGS 0 /* reload call-clobbered registers */
+ jmp system_call_fastpath
+
+@@ -588,6 +847,9 @@ tracesys:
+ FIXUP_TOP_OF_STACK %rdi
+ movq %rsp,%rdi
+ call syscall_trace_enter
++
++ pax_erase_kstack
++
+ /*
+ * Reload arg registers from stack in case ptrace changed them.
+ * We don't reload %rax because syscall_trace_enter() returned
+@@ -609,7 +871,7 @@ tracesys:
+ GLOBAL(int_ret_from_sys_call)
+ DISABLE_INTERRUPTS(CLBR_NONE)
+ TRACE_IRQS_OFF
+- testl $3,CS-ARGOFFSET(%rsp)
++ testb $3,CS-ARGOFFSET(%rsp)
+ je retint_restore_args
+ movl $_TIF_ALLWORK_MASK,%edi
+ /* edi: mask to check */
+@@ -791,6 +1053,16 @@ END(interrupt)
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
+ call save_args
+ PARTIAL_FRAME 0
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ testb $3, CS(%rdi)
++ jnz 1f
++ pax_enter_kernel
++ jmp 2f
++1: pax_enter_kernel_user
++2:
++#else
++ pax_enter_kernel
++#endif
+ call \func
+ .endm
+
+@@ -823,7 +1095,7 @@ ret_from_intr:
+ CFI_ADJUST_CFA_OFFSET -8
+ exit_intr:
+ GET_THREAD_INFO(%rcx)
+- testl $3,CS-ARGOFFSET(%rsp)
++ testb $3,CS-ARGOFFSET(%rsp)
+ je retint_kernel
+
+ /* Interrupt came from user space */
+@@ -845,12 +1117,14 @@ retint_swapgs: /* return to user-space
+ * The iretq could re-enable interrupts:
+ */
+ DISABLE_INTERRUPTS(CLBR_ANY)
++ pax_exit_kernel_user
+ TRACE_IRQS_IRETQ
+ SWAPGS
+ jmp restore_args
+
+ retint_restore_args: /* return to kernel space */
+ DISABLE_INTERRUPTS(CLBR_ANY)
++ pax_exit_kernel
+ /*
+ * The iretq could re-enable interrupts:
+ */
+@@ -1022,6 +1296,16 @@ ENTRY(\sym)
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
+ call error_entry
+ DEFAULT_FRAME 0
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ testb $3, CS(%rsp)
++ jnz 1f
++ pax_enter_kernel
++ jmp 2f
++1: pax_enter_kernel_user
++2:
++#else
++ pax_enter_kernel
++#endif
+ movq %rsp,%rdi /* pt_regs pointer */
+ xorl %esi,%esi /* no error code */
+ call \do_sym
+@@ -1039,6 +1323,16 @@ ENTRY(\sym)
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
+ call save_paranoid
+ TRACE_IRQS_OFF
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ testb $3, CS(%rsp)
++ jnz 1f
++ pax_enter_kernel
++ jmp 2f
++1: pax_enter_kernel_user
++2:
++#else
++ pax_enter_kernel
++#endif
+ movq %rsp,%rdi /* pt_regs pointer */
+ xorl %esi,%esi /* no error code */
+ call \do_sym
+@@ -1047,7 +1341,7 @@ ENTRY(\sym)
+ END(\sym)
+ .endm
+
+-#define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
++#define INIT_TSS_IST(x) (TSS_ist + ((x) - 1) * 8)(%r12)
+ .macro paranoidzeroentry_ist sym do_sym ist
+ ENTRY(\sym)
+ INTR_FRAME
+@@ -1057,8 +1351,24 @@ ENTRY(\sym)
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
+ call save_paranoid
+ TRACE_IRQS_OFF
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ testb $3, CS(%rsp)
++ jnz 1f
++ pax_enter_kernel
++ jmp 2f
++1: pax_enter_kernel_user
++2:
++#else
++ pax_enter_kernel
++#endif
+ movq %rsp,%rdi /* pt_regs pointer */
+ xorl %esi,%esi /* no error code */
++#ifdef CONFIG_SMP
++ imul $TSS_size, PER_CPU_VAR(cpu_number), %r12d
++ lea init_tss(%r12), %r12
++#else
++ lea init_tss(%rip), %r12
++#endif
+ subq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist)
+ call \do_sym
+ addq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist)
+@@ -1075,6 +1385,16 @@ ENTRY(\sym)
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
+ call error_entry
+ DEFAULT_FRAME 0
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ testb $3, CS(%rsp)
++ jnz 1f
++ pax_enter_kernel
++ jmp 2f
++1: pax_enter_kernel_user
++2:
++#else
++ pax_enter_kernel
++#endif
+ movq %rsp,%rdi /* pt_regs pointer */
+ movq ORIG_RAX(%rsp),%rsi /* get error code */
+ movq $-1,ORIG_RAX(%rsp) /* no syscall to restart */
+@@ -1094,6 +1414,16 @@ ENTRY(\sym)
+ call save_paranoid
+ DEFAULT_FRAME 0
+ TRACE_IRQS_OFF
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ testb $3, CS(%rsp)
++ jnz 1f
++ pax_enter_kernel
++ jmp 2f
++1: pax_enter_kernel_user
++2:
++#else
++ pax_enter_kernel
++#endif
+ movq %rsp,%rdi /* pt_regs pointer */
+ movq ORIG_RAX(%rsp),%rsi /* get error code */
+ movq $-1,ORIG_RAX(%rsp) /* no syscall to restart */
+@@ -1356,14 +1686,27 @@ ENTRY(paranoid_exit)
+ TRACE_IRQS_OFF
+ testl %ebx,%ebx /* swapgs needed? */
+ jnz paranoid_restore
+- testl $3,CS(%rsp)
++ testb $3,CS(%rsp)
+ jnz paranoid_userspace
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pax_exit_kernel
++ TRACE_IRQS_IRETQ 0
++ SWAPGS_UNSAFE_STACK
++ RESTORE_ALL 8
++ jmp irq_return
++#endif
+ paranoid_swapgs:
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pax_exit_kernel_user
++#else
++ pax_exit_kernel
++#endif
+ TRACE_IRQS_IRETQ 0
+ SWAPGS_UNSAFE_STACK
+ RESTORE_ALL 8
+ jmp irq_return
+ paranoid_restore:
++ pax_exit_kernel
+ TRACE_IRQS_IRETQ 0
+ RESTORE_ALL 8
+ jmp irq_return
+@@ -1421,7 +1764,7 @@ ENTRY(error_entry)
+ movq_cfi r14, R14+8
+ movq_cfi r15, R15+8
+ xorl %ebx,%ebx
+- testl $3,CS+8(%rsp)
++ testb $3,CS+8(%rsp)
+ je error_kernelspace
+ error_swapgs:
+ SWAPGS
+@@ -1485,6 +1828,16 @@ ENTRY(nmi)
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
+ call save_paranoid
+ DEFAULT_FRAME 0
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ testb $3, CS(%rsp)
++ jnz 1f
++ pax_enter_kernel
++ jmp 2f
++1: pax_enter_kernel_user
++2:
++#else
++ pax_enter_kernel
++#endif
+ /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
+ movq %rsp,%rdi
+ movq $-1,%rsi
+@@ -1495,11 +1848,25 @@ ENTRY(nmi)
+ DISABLE_INTERRUPTS(CLBR_NONE)
+ testl %ebx,%ebx /* swapgs needed? */
+ jnz nmi_restore
+- testl $3,CS(%rsp)
++ testb $3,CS(%rsp)
+ jnz nmi_userspace
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pax_exit_kernel
++ SWAPGS_UNSAFE_STACK
++ RESTORE_ALL 8
++ jmp irq_return
++#endif
+ nmi_swapgs:
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pax_exit_kernel_user
++#else
++ pax_exit_kernel
++#endif
+ SWAPGS_UNSAFE_STACK
++ RESTORE_ALL 8
++ jmp irq_return
+ nmi_restore:
++ pax_exit_kernel
+ RESTORE_ALL 8
+ jmp irq_return
+ nmi_userspace:
+diff -urNp linux-2.6.38.7/arch/x86/kernel/ftrace.c linux-2.6.38.7/arch/x86/kernel/ftrace.c
+--- linux-2.6.38.7/arch/x86/kernel/ftrace.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/ftrace.c 2011-04-28 19:57:25.000000000 -0400
+@@ -126,7 +126,7 @@ static void *mod_code_ip; /* holds the
+ static void *mod_code_newcode; /* holds the text to write to the IP */
+
+ static unsigned nmi_wait_count;
+-static atomic_t nmi_update_count = ATOMIC_INIT(0);
++static atomic_unchecked_t nmi_update_count = ATOMIC_INIT(0);
+
+ int ftrace_arch_read_dyn_info(char *buf, int size)
+ {
+@@ -134,7 +134,7 @@ int ftrace_arch_read_dyn_info(char *buf,
+
+ r = snprintf(buf, size, "%u %u",
+ nmi_wait_count,
+- atomic_read(&nmi_update_count));
++ atomic_read_unchecked(&nmi_update_count));
+ return r;
+ }
+
+@@ -177,8 +177,10 @@ void ftrace_nmi_enter(void)
+
+ if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) {
+ smp_rmb();
++ pax_open_kernel();
+ ftrace_mod_code();
+- atomic_inc(&nmi_update_count);
++ pax_close_kernel();
++ atomic_inc_unchecked(&nmi_update_count);
+ }
+ /* Must have previous changes seen before executions */
+ smp_mb();
+@@ -271,6 +273,8 @@ ftrace_modify_code(unsigned long ip, uns
+ {
+ unsigned char replaced[MCOUNT_INSN_SIZE];
+
++ ip = ktla_ktva(ip);
++
+ /*
+ * Note: Due to modules and __init, code can
+ * disappear and change, we need to protect against faulting
+@@ -327,7 +331,7 @@ int ftrace_update_ftrace_func(ftrace_fun
+ unsigned char old[MCOUNT_INSN_SIZE], *new;
+ int ret;
+
+- memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
++ memcpy(old, (void *)ktla_ktva((unsigned long)ftrace_call), MCOUNT_INSN_SIZE);
+ new = ftrace_call_replace(ip, (unsigned long)func);
+ ret = ftrace_modify_code(ip, old, new);
+
+@@ -353,6 +357,8 @@ static int ftrace_mod_jmp(unsigned long
+ {
+ unsigned char code[MCOUNT_INSN_SIZE];
+
++ ip = ktla_ktva(ip);
++
+ if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
+ return -EFAULT;
+
+diff -urNp linux-2.6.38.7/arch/x86/kernel/head32.c linux-2.6.38.7/arch/x86/kernel/head32.c
+--- linux-2.6.38.7/arch/x86/kernel/head32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/head32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -19,6 +19,7 @@
+ #include <asm/io_apic.h>
+ #include <asm/bios_ebda.h>
+ #include <asm/tlbflush.h>
++#include <asm/boot.h>
+
+ static void __init i386_default_early_setup(void)
+ {
+@@ -43,7 +44,7 @@ void __init i386_start_kernel(void)
+ memblock_x86_reserve_range(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE");
+ #endif
+
+- memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
++ memblock_x86_reserve_range(LOAD_PHYSICAL_ADDR, __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+ /* Reserve INITRD */
+diff -urNp linux-2.6.38.7/arch/x86/kernel/head_32.S linux-2.6.38.7/arch/x86/kernel/head_32.S
+--- linux-2.6.38.7/arch/x86/kernel/head_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/head_32.S 2011-05-11 18:34:57.000000000 -0400
+@@ -25,6 +25,12 @@
+ /* Physical address */
+ #define pa(X) ((X) - __PAGE_OFFSET)
+
++#ifdef CONFIG_PAX_KERNEXEC
++#define ta(X) (X)
++#else
++#define ta(X) ((X) - __PAGE_OFFSET)
++#endif
++
+ /*
+ * References to members of the new_cpu_data structure.
+ */
+@@ -54,11 +60,7 @@
+ * and small than max_low_pfn, otherwise will waste some page table entries
+ */
+
+-#if PTRS_PER_PMD > 1
+-#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
+-#else
+-#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
+-#endif
++#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PTE)
+
+ /* Number of possible pages in the lowmem region */
+ LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT)
+@@ -77,6 +79,12 @@ INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_P
+ RESERVE_BRK(pagetables, INIT_MAP_SIZE)
+
+ /*
++ * Real beginning of normal "text" segment
++ */
++ENTRY(stext)
++ENTRY(_stext)
++
++/*
+ * 32-bit kernel entrypoint; only used by the boot CPU. On entry,
+ * %esi points to the real-mode code as a 32-bit pointer.
+ * CS and DS must be 4 GB flat segments, but we don't depend on
+@@ -84,6 +92,13 @@ RESERVE_BRK(pagetables, INIT_MAP_SIZE)
+ * can.
+ */
+ __HEAD
++
++#ifdef CONFIG_PAX_KERNEXEC
++ jmp startup_32
++/* PaX: fill first page in .text with int3 to catch NULL derefs in kernel mode */
++.fill PAGE_SIZE-5,1,0xcc
++#endif
++
+ ENTRY(startup_32)
+ movl pa(stack_start),%ecx
+
+@@ -105,6 +120,57 @@ ENTRY(startup_32)
+ 2:
+ leal -__PAGE_OFFSET(%ecx),%esp
+
++#ifdef CONFIG_SMP
++ movl $pa(cpu_gdt_table),%edi
++ movl $__per_cpu_load,%eax
++ movw %ax,__KERNEL_PERCPU + 2(%edi)
++ rorl $16,%eax
++ movb %al,__KERNEL_PERCPU + 4(%edi)
++ movb %ah,__KERNEL_PERCPU + 7(%edi)
++ movl $__per_cpu_end - 1,%eax
++ subl $__per_cpu_start,%eax
++ movw %ax,__KERNEL_PERCPU + 0(%edi)
++#endif
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ movl $NR_CPUS,%ecx
++ movl $pa(cpu_gdt_table),%edi
++1:
++ movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c09700),GDT_ENTRY_KERNEL_DS * 8 + 4(%edi)
++ movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c0fb00),GDT_ENTRY_DEFAULT_USER_CS * 8 + 4(%edi)
++ movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c0f300),GDT_ENTRY_DEFAULT_USER_DS * 8 + 4(%edi)
++ addl $PAGE_SIZE_asm,%edi
++ loop 1b
++#endif
++
++#ifdef CONFIG_PAX_KERNEXEC
++ movl $pa(boot_gdt),%edi
++ movl $__LOAD_PHYSICAL_ADDR,%eax
++ movw %ax,__BOOT_CS + 2(%edi)
++ rorl $16,%eax
++ movb %al,__BOOT_CS + 4(%edi)
++ movb %ah,__BOOT_CS + 7(%edi)
++ rorl $16,%eax
++
++ ljmp $(__BOOT_CS),$1f
++1:
++
++ movl $NR_CPUS,%ecx
++ movl $pa(cpu_gdt_table),%edi
++ addl $__PAGE_OFFSET,%eax
++1:
++ movw %ax,__KERNEL_CS + 2(%edi)
++ movw %ax,__KERNEXEC_KERNEL_CS + 2(%edi)
++ rorl $16,%eax
++ movb %al,__KERNEL_CS + 4(%edi)
++ movb %al,__KERNEXEC_KERNEL_CS + 4(%edi)
++ movb %ah,__KERNEL_CS + 7(%edi)
++ movb %ah,__KERNEXEC_KERNEL_CS + 7(%edi)
++ rorl $16,%eax
++ addl $PAGE_SIZE_asm,%edi
++ loop 1b
++#endif
++
+ /*
+ * Clear BSS first so that there are no surprises...
+ */
+@@ -195,8 +261,11 @@ ENTRY(startup_32)
+ movl %eax, pa(max_pfn_mapped)
+
+ /* Do early initialization of the fixmap area */
+- movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+- movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
++#ifdef CONFIG_COMPAT_VDSO
++ movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR+_PAGE_USER,pa(initial_pg_pmd+0x1000*KPMDS-8)
++#else
++ movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,pa(initial_pg_pmd+0x1000*KPMDS-8)
++#endif
+ #else /* Not PAE */
+
+ page_pde_offset = (__PAGE_OFFSET >> 20);
+@@ -226,8 +295,11 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
+ movl %eax, pa(max_pfn_mapped)
+
+ /* Do early initialization of the fixmap area */
+- movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+- movl %eax,pa(initial_page_table+0xffc)
++#ifdef CONFIG_COMPAT_VDSO
++ movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR+_PAGE_USER,pa(initial_page_table+0xffc)
++#else
++ movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,pa(initial_page_table+0xffc)
++#endif
+ #endif
+
+ #ifdef CONFIG_PARAVIRT
+@@ -241,9 +313,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
+ cmpl $num_subarch_entries, %eax
+ jae bad_subarch
+
+- movl pa(subarch_entries)(,%eax,4), %eax
+- subl $__PAGE_OFFSET, %eax
+- jmp *%eax
++ jmp *pa(subarch_entries)(,%eax,4)
+
+ bad_subarch:
+ WEAK(lguest_entry)
+@@ -255,10 +325,10 @@ WEAK(xen_entry)
+ __INITDATA
+
+ subarch_entries:
+- .long default_entry /* normal x86/PC */
+- .long lguest_entry /* lguest hypervisor */
+- .long xen_entry /* Xen hypervisor */
+- .long default_entry /* Moorestown MID */
++ .long ta(default_entry) /* normal x86/PC */
++ .long ta(lguest_entry) /* lguest hypervisor */
++ .long ta(xen_entry) /* Xen hypervisor */
++ .long ta(default_entry) /* Moorestown MID */
+ num_subarch_entries = (. - subarch_entries) / 4
+ .previous
+ #else
+@@ -312,6 +382,7 @@ default_entry:
+ orl %edx,%eax
+ movl %eax,%cr4
+
++#ifdef CONFIG_X86_PAE
+ testb $X86_CR4_PAE, %al # check if PAE is enabled
+ jz 6f
+
+@@ -340,6 +411,9 @@ default_entry:
+ /* Make changes effective */
+ wrmsr
+
++ btsl $_PAGE_BIT_NX-32,pa(__supported_pte_mask+4)
++#endif
++
+ 6:
+
+ /*
+@@ -443,7 +517,7 @@ is386: movl $2,%ecx # set MP
+ 1: movl $(__KERNEL_DS),%eax # reload all the segment registers
+ movl %eax,%ss # after changing gdt.
+
+- movl $(__USER_DS),%eax # DS/ES contains default USER segment
++# movl $(__KERNEL_DS),%eax # DS/ES contains default KERNEL segment
+ movl %eax,%ds
+ movl %eax,%es
+
+@@ -457,15 +531,22 @@ is386: movl $2,%ecx # set MP
+ */
+ cmpb $0,ready
+ jne 1f
+- movl $gdt_page,%eax
++ movl $cpu_gdt_table,%eax
+ movl $stack_canary,%ecx
++#ifdef CONFIG_SMP
++ addl $__per_cpu_load,%ecx
++#endif
+ movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
+ shrl $16, %ecx
+ movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
+ movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax)
+ 1:
+-#endif
+ movl $(__KERNEL_STACK_CANARY),%eax
++#elif defined(CONFIG_PAX_MEMORY_UDEREF)
++ movl $(__USER_DS),%eax
++#else
++ xorl %eax,%eax
++#endif
+ movl %eax,%gs
+
+ xorl %eax,%eax # Clear LDT
+@@ -558,22 +639,22 @@ early_page_fault:
+ jmp early_fault
+
+ early_fault:
+- cld
+ #ifdef CONFIG_PRINTK
++ cmpl $1,%ss:early_recursion_flag
++ je hlt_loop
++ incl %ss:early_recursion_flag
++ cld
+ pusha
+ movl $(__KERNEL_DS),%eax
+ movl %eax,%ds
+ movl %eax,%es
+- cmpl $2,early_recursion_flag
+- je hlt_loop
+- incl early_recursion_flag
+ movl %cr2,%eax
+ pushl %eax
+ pushl %edx /* trapno */
+ pushl $fault_msg
+ call printk
++; call dump_stack
+ #endif
+- call dump_stack
+ hlt_loop:
+ hlt
+ jmp hlt_loop
+@@ -581,8 +662,11 @@ hlt_loop:
+ /* This is the default interrupt "handler" :-) */
+ ALIGN
+ ignore_int:
+- cld
+ #ifdef CONFIG_PRINTK
++ cmpl $2,%ss:early_recursion_flag
++ je hlt_loop
++ incl %ss:early_recursion_flag
++ cld
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+@@ -591,9 +675,6 @@ ignore_int:
+ movl $(__KERNEL_DS),%eax
+ movl %eax,%ds
+ movl %eax,%es
+- cmpl $2,early_recursion_flag
+- je hlt_loop
+- incl early_recursion_flag
+ pushl 16(%esp)
+ pushl 24(%esp)
+ pushl 32(%esp)
+@@ -622,29 +703,43 @@ ENTRY(initial_code)
+ /*
+ * BSS section
+ */
+-__PAGE_ALIGNED_BSS
+- .align PAGE_SIZE_asm
+ #ifdef CONFIG_X86_PAE
++.section .initial_pg_pmd,"a",@progbits
+ initial_pg_pmd:
+ .fill 1024*KPMDS,4,0
+ #else
++.section .initial_page_table,"a",@progbits
+ ENTRY(initial_page_table)
+ .fill 1024,4,0
+ #endif
++.section .initial_pg_fixmap,"a",@progbits
+ initial_pg_fixmap:
+ .fill 1024,4,0
++.section .empty_zero_page,"a",@progbits
+ ENTRY(empty_zero_page)
+ .fill 4096,1,0
++.section .swapper_pg_dir,"a",@progbits
+ ENTRY(swapper_pg_dir)
++#ifdef CONFIG_X86_PAE
++ .fill 4,8,0
++#else
+ .fill 1024,4,0
++#endif
++
++/*
++ * The IDT has to be page-aligned to simplify the Pentium
++ * F0 0F bug workaround.. We have a special link segment
++ * for this.
++ */
++.section .idt,"a",@progbits
++ENTRY(idt_table)
++ .fill 256,8,0
+
+ /*
+ * This starts the data section.
+ */
+ #ifdef CONFIG_X86_PAE
+-__PAGE_ALIGNED_DATA
+- /* Page-aligned for the benefit of paravirt? */
+- .align PAGE_SIZE_asm
++.section .initial_page_table,"a",@progbits
+ ENTRY(initial_page_table)
+ .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */
+ # if KPMDS == 3
+@@ -663,18 +758,27 @@ ENTRY(initial_page_table)
+ # error "Kernel PMDs should be 1, 2 or 3"
+ # endif
+ .align PAGE_SIZE_asm /* needs to be page-sized too */
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ENTRY(cpu_pgd)
++ .rept NR_CPUS
++ .fill 4,8,0
++ .endr
++#endif
++
+ #endif
+
+ .data
+ .balign 4
+ ENTRY(stack_start)
+- .long init_thread_union+THREAD_SIZE
++ .long init_thread_union+THREAD_SIZE-8
++
++ready: .byte 0
+
++.section .rodata,"a",@progbits
+ early_recursion_flag:
+ .long 0
+
+-ready: .byte 0
+-
+ int_msg:
+ .asciz "Unknown interrupt or fault at: %p %p %p\n"
+
+@@ -707,7 +811,7 @@ fault_msg:
+ .word 0 # 32 bit align gdt_desc.address
+ boot_gdt_descr:
+ .word __BOOT_DS+7
+- .long boot_gdt - __PAGE_OFFSET
++ .long pa(boot_gdt)
+
+ .word 0 # 32-bit align idt_desc.address
+ idt_descr:
+@@ -718,7 +822,7 @@ idt_descr:
+ .word 0 # 32 bit align gdt_desc.address
+ ENTRY(early_gdt_descr)
+ .word GDT_ENTRIES*8-1
+- .long gdt_page /* Overwritten for secondary CPUs */
++ .long cpu_gdt_table /* Overwritten for secondary CPUs */
+
+ /*
+ * The boot_gdt must mirror the equivalent in setup.S and is
+@@ -727,5 +831,65 @@ ENTRY(early_gdt_descr)
+ .align L1_CACHE_BYTES
+ ENTRY(boot_gdt)
+ .fill GDT_ENTRY_BOOT_CS,8,0
+- .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */
+- .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */
++ .quad 0x00cf9b000000ffff /* kernel 4GB code at 0x00000000 */
++ .quad 0x00cf93000000ffff /* kernel 4GB data at 0x00000000 */
++
++ .align PAGE_SIZE_asm
++ENTRY(cpu_gdt_table)
++ .rept NR_CPUS
++ .quad 0x0000000000000000 /* NULL descriptor */
++ .quad 0x0000000000000000 /* 0x0b reserved */
++ .quad 0x0000000000000000 /* 0x13 reserved */
++ .quad 0x0000000000000000 /* 0x1b reserved */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ .quad 0x00cf9b000000ffff /* 0x20 alternate kernel 4GB code at 0x00000000 */
++#else
++ .quad 0x0000000000000000 /* 0x20 unused */
++#endif
++
++ .quad 0x0000000000000000 /* 0x28 unused */
++ .quad 0x0000000000000000 /* 0x33 TLS entry 1 */
++ .quad 0x0000000000000000 /* 0x3b TLS entry 2 */
++ .quad 0x0000000000000000 /* 0x43 TLS entry 3 */
++ .quad 0x0000000000000000 /* 0x4b reserved */
++ .quad 0x0000000000000000 /* 0x53 reserved */
++ .quad 0x0000000000000000 /* 0x5b reserved */
++
++ .quad 0x00cf9b000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
++ .quad 0x00cf93000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
++ .quad 0x00cffb000000ffff /* 0x73 user 4GB code at 0x00000000 */
++ .quad 0x00cff3000000ffff /* 0x7b user 4GB data at 0x00000000 */
++
++ .quad 0x0000000000000000 /* 0x80 TSS descriptor */
++ .quad 0x0000000000000000 /* 0x88 LDT descriptor */
++
++ /*
++ * Segments used for calling PnP BIOS have byte granularity.
++ * The code segments and data segments have fixed 64k limits,
++ * the transfer segment sizes are set at run time.
++ */
++ .quad 0x00409b000000ffff /* 0x90 32-bit code */
++ .quad 0x00009b000000ffff /* 0x98 16-bit code */
++ .quad 0x000093000000ffff /* 0xa0 16-bit data */
++ .quad 0x0000930000000000 /* 0xa8 16-bit data */
++ .quad 0x0000930000000000 /* 0xb0 16-bit data */
++
++ /*
++ * The APM segments have byte granularity and their bases
++ * are set at run time. All have 64k limits.
++ */
++ .quad 0x00409b000000ffff /* 0xb8 APM CS code */
++ .quad 0x00009b000000ffff /* 0xc0 APM CS 16 code (16 bit) */
++ .quad 0x004093000000ffff /* 0xc8 APM DS data */
++
++ .quad 0x00c0930000000000 /* 0xd0 - ESPFIX SS */
++ .quad 0x0040930000000000 /* 0xd8 - PERCPU */
++ .quad 0x0040910000000018 /* 0xe0 - STACK_CANARY */
++ .quad 0x0000000000000000 /* 0xe8 - PCIBIOS_CS */
++ .quad 0x0000000000000000 /* 0xf0 - PCIBIOS_DS */
++ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
++
++ /* Be sure this is zeroed to avoid false validations in Xen */
++ .fill PAGE_SIZE_asm - GDT_SIZE,1,0
++ .endr
+diff -urNp linux-2.6.38.7/arch/x86/kernel/head_64.S linux-2.6.38.7/arch/x86/kernel/head_64.S
+--- linux-2.6.38.7/arch/x86/kernel/head_64.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/head_64.S 2011-04-28 19:34:14.000000000 -0400
+@@ -19,6 +19,7 @@
+ #include <asm/cache.h>
+ #include <asm/processor-flags.h>
+ #include <asm/percpu.h>
++#include <asm/cpufeature.h>
+
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/asm-offsets.h>
+@@ -38,6 +39,10 @@ L4_PAGE_OFFSET = pgd_index(__PAGE_OFFSET
+ L3_PAGE_OFFSET = pud_index(__PAGE_OFFSET)
+ L4_START_KERNEL = pgd_index(__START_KERNEL_map)
+ L3_START_KERNEL = pud_index(__START_KERNEL_map)
++L4_VMALLOC_START = pgd_index(VMALLOC_START)
++L3_VMALLOC_START = pud_index(VMALLOC_START)
++L4_VMEMMAP_START = pgd_index(VMEMMAP_START)
++L3_VMEMMAP_START = pud_index(VMEMMAP_START)
+
+ .text
+ __HEAD
+@@ -85,35 +90,22 @@ startup_64:
+ */
+ addq %rbp, init_level4_pgt + 0(%rip)
+ addq %rbp, init_level4_pgt + (L4_PAGE_OFFSET*8)(%rip)
++ addq %rbp, init_level4_pgt + (L4_VMALLOC_START*8)(%rip)
++ addq %rbp, init_level4_pgt + (L4_VMEMMAP_START*8)(%rip)
+ addq %rbp, init_level4_pgt + (L4_START_KERNEL*8)(%rip)
+
+ addq %rbp, level3_ident_pgt + 0(%rip)
++#ifndef CONFIG_XEN
++ addq %rbp, level3_ident_pgt + 8(%rip)
++#endif
+
+- addq %rbp, level3_kernel_pgt + (510*8)(%rip)
+- addq %rbp, level3_kernel_pgt + (511*8)(%rip)
++ addq %rbp, level3_vmemmap_pgt + (L3_VMEMMAP_START*8)(%rip)
+
+- addq %rbp, level2_fixmap_pgt + (506*8)(%rip)
++ addq %rbp, level3_kernel_pgt + (L3_START_KERNEL*8)(%rip)
++ addq %rbp, level3_kernel_pgt + (L3_START_KERNEL*8+8)(%rip)
+
+- /* Add an Identity mapping if I am above 1G */
+- leaq _text(%rip), %rdi
+- andq $PMD_PAGE_MASK, %rdi
+-
+- movq %rdi, %rax
+- shrq $PUD_SHIFT, %rax
+- andq $(PTRS_PER_PUD - 1), %rax
+- jz ident_complete
+-
+- leaq (level2_spare_pgt - __START_KERNEL_map + _KERNPG_TABLE)(%rbp), %rdx
+- leaq level3_ident_pgt(%rip), %rbx
+- movq %rdx, 0(%rbx, %rax, 8)
+-
+- movq %rdi, %rax
+- shrq $PMD_SHIFT, %rax
+- andq $(PTRS_PER_PMD - 1), %rax
+- leaq __PAGE_KERNEL_IDENT_LARGE_EXEC(%rdi), %rdx
+- leaq level2_spare_pgt(%rip), %rbx
+- movq %rdx, 0(%rbx, %rax, 8)
+-ident_complete:
++ addq %rbp, level2_fixmap_pgt + (506*8)(%rip)
++ addq %rbp, level2_fixmap_pgt + (507*8)(%rip)
+
+ /*
+ * Fixup the kernel text+data virtual addresses. Note that
+@@ -161,8 +153,8 @@ ENTRY(secondary_startup_64)
+ * after the boot processor executes this code.
+ */
+
+- /* Enable PAE mode and PGE */
+- movl $(X86_CR4_PAE | X86_CR4_PGE), %eax
++ /* Enable PAE mode and PSE/PGE */
++ movl $(X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE), %eax
+ movq %rax, %cr4
+
+ /* Setup early boot stage 4 level pagetables. */
+@@ -184,9 +176,14 @@ ENTRY(secondary_startup_64)
+ movl $MSR_EFER, %ecx
+ rdmsr
+ btsl $_EFER_SCE, %eax /* Enable System Call */
+- btl $20,%edi /* No Execute supported? */
++ btl $(X86_FEATURE_NX & 31),%edi /* No Execute supported? */
+ jnc 1f
+ btsl $_EFER_NX, %eax
++ leaq init_level4_pgt(%rip), %rdi
++ btsq $_PAGE_BIT_NX, 8*L4_PAGE_OFFSET(%rdi)
++ btsq $_PAGE_BIT_NX, 8*L4_VMALLOC_START(%rdi)
++ btsq $_PAGE_BIT_NX, 8*L4_VMEMMAP_START(%rdi)
++ btsq $_PAGE_BIT_NX, __supported_pte_mask(%rip)
+ 1: wrmsr /* Make changes effective */
+
+ /* Setup cr0 */
+@@ -270,7 +267,7 @@ ENTRY(secondary_startup_64)
+ bad_address:
+ jmp bad_address
+
+- .section ".init.text","ax"
++ __INIT
+ #ifdef CONFIG_EARLY_PRINTK
+ .globl early_idt_handlers
+ early_idt_handlers:
+@@ -315,18 +312,23 @@ ENTRY(early_idt_handler)
+ #endif /* EARLY_PRINTK */
+ 1: hlt
+ jmp 1b
++ .previous
+
+ #ifdef CONFIG_EARLY_PRINTK
++ __INITDATA
+ early_recursion_flag:
+ .long 0
++ .previous
+
++ .section .rodata,"a",@progbits
+ early_idt_msg:
+ .asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n"
+ early_idt_ripmsg:
+ .asciz "RIP %s\n"
+-#endif /* CONFIG_EARLY_PRINTK */
+ .previous
++#endif /* CONFIG_EARLY_PRINTK */
+
++ .section .rodata,"a",@progbits
+ #define NEXT_PAGE(name) \
+ .balign PAGE_SIZE; \
+ ENTRY(name)
+@@ -339,7 +341,6 @@ ENTRY(name)
+ i = i + 1 ; \
+ .endr
+
+- .data
+ /*
+ * This default setting generates an ident mapping at address 0x100000
+ * and a mapping for the kernel that precisely maps virtual address
+@@ -350,13 +351,36 @@ NEXT_PAGE(init_level4_pgt)
+ .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+ .org init_level4_pgt + L4_PAGE_OFFSET*8, 0
+ .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
++ .org init_level4_pgt + L4_VMALLOC_START*8, 0
++ .quad level3_vmalloc_pgt - __START_KERNEL_map + _KERNPG_TABLE
++ .org init_level4_pgt + L4_VMEMMAP_START*8, 0
++ .quad level3_vmemmap_pgt - __START_KERNEL_map + _KERNPG_TABLE
+ .org init_level4_pgt + L4_START_KERNEL*8, 0
+ /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
+ .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+
++#ifdef CONFIG_PAX_PER_CPU_PGD
++NEXT_PAGE(cpu_pgd)
++ .rept NR_CPUS
++ .fill 512,8,0
++ .endr
++#endif
++
+ NEXT_PAGE(level3_ident_pgt)
+ .quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
++#ifdef CONFIG_XEN
+ .fill 511,8,0
++#else
++ .quad level2_ident_pgt + PAGE_SIZE - __START_KERNEL_map + _KERNPG_TABLE
++ .fill 510,8,0
++#endif
++
++NEXT_PAGE(level3_vmalloc_pgt)
++ .fill 512,8,0
++
++NEXT_PAGE(level3_vmemmap_pgt)
++ .fill L3_VMEMMAP_START,8,0
++ .quad level2_vmemmap_pgt - __START_KERNEL_map + _KERNPG_TABLE
+
+ NEXT_PAGE(level3_kernel_pgt)
+ .fill L3_START_KERNEL,8,0
+@@ -364,20 +388,23 @@ NEXT_PAGE(level3_kernel_pgt)
+ .quad level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
+ .quad level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+
++NEXT_PAGE(level2_vmemmap_pgt)
++ .fill 512,8,0
++
+ NEXT_PAGE(level2_fixmap_pgt)
+- .fill 506,8,0
+- .quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+- /* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
+- .fill 5,8,0
++ .fill 507,8,0
++ .quad level1_vsyscall_pgt - __START_KERNEL_map + _PAGE_TABLE
++ /* 6MB reserved for vsyscalls + a 2MB hole = 3 + 1 entries */
++ .fill 4,8,0
+
+-NEXT_PAGE(level1_fixmap_pgt)
++NEXT_PAGE(level1_vsyscall_pgt)
+ .fill 512,8,0
+
+-NEXT_PAGE(level2_ident_pgt)
+- /* Since I easily can, map the first 1G.
++ /* Since I easily can, map the first 2G.
+ * Don't set NX because code runs from these pages.
+ */
+- PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD)
++NEXT_PAGE(level2_ident_pgt)
++ PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, 2*PTRS_PER_PMD)
+
+ NEXT_PAGE(level2_kernel_pgt)
+ /*
+@@ -390,33 +417,55 @@ NEXT_PAGE(level2_kernel_pgt)
+ * If you want to increase this then increase MODULES_VADDR
+ * too.)
+ */
+- PMDS(0, __PAGE_KERNEL_LARGE_EXEC,
+- KERNEL_IMAGE_SIZE/PMD_SIZE)
+-
+-NEXT_PAGE(level2_spare_pgt)
+- .fill 512, 8, 0
++ PMDS(0, __PAGE_KERNEL_LARGE_EXEC, KERNEL_IMAGE_SIZE/PMD_SIZE)
+
+ #undef PMDS
+ #undef NEXT_PAGE
+
+- .data
++ .align PAGE_SIZE
++ENTRY(cpu_gdt_table)
++ .rept NR_CPUS
++ .quad 0x0000000000000000 /* NULL descriptor */
++ .quad 0x00cf9b000000ffff /* __KERNEL32_CS */
++ .quad 0x00af9b000000ffff /* __KERNEL_CS */
++ .quad 0x00cf93000000ffff /* __KERNEL_DS */
++ .quad 0x00cffb000000ffff /* __USER32_CS */
++ .quad 0x00cff3000000ffff /* __USER_DS, __USER32_DS */
++ .quad 0x00affb000000ffff /* __USER_CS */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ .quad 0x00af9b000000ffff /* __KERNEXEC_KERNEL_CS */
++#else
++ .quad 0x0 /* unused */
++#endif
++
++ .quad 0,0 /* TSS */
++ .quad 0,0 /* LDT */
++ .quad 0,0,0 /* three TLS descriptors */
++ .quad 0x0000f40000000000 /* node/CPU stored in limit */
++ /* asm/segment.h:GDT_ENTRIES must match this */
++
++ /* zero the remaining page */
++ .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
++ .endr
++
+ .align 16
+ .globl early_gdt_descr
+ early_gdt_descr:
+ .word GDT_ENTRIES*8-1
+ early_gdt_descr_base:
+- .quad INIT_PER_CPU_VAR(gdt_page)
++ .quad cpu_gdt_table
+
+ ENTRY(phys_base)
+ /* This must match the first entry in level2_kernel_pgt */
+ .quad 0x0000000000000000
+
+ #include "../../x86/xen/xen-head.S"
+-
+- .section .bss, "aw", @nobits
++
++ .section .rodata,"a",@progbits
+ .align L1_CACHE_BYTES
+ ENTRY(idt_table)
+- .skip IDT_ENTRIES * 16
++ .fill 512,8,0
+
+ __PAGE_ALIGNED_BSS
+ .align PAGE_SIZE
+diff -urNp linux-2.6.38.7/arch/x86/kernel/i386_ksyms_32.c linux-2.6.38.7/arch/x86/kernel/i386_ksyms_32.c
+--- linux-2.6.38.7/arch/x86/kernel/i386_ksyms_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/i386_ksyms_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -20,8 +20,12 @@ extern void cmpxchg8b_emu(void);
+ EXPORT_SYMBOL(cmpxchg8b_emu);
+ #endif
+
++EXPORT_SYMBOL_GPL(cpu_gdt_table);
++
+ /* Networking helper routines. */
+ EXPORT_SYMBOL(csum_partial_copy_generic);
++EXPORT_SYMBOL(csum_partial_copy_generic_to_user);
++EXPORT_SYMBOL(csum_partial_copy_generic_from_user);
+
+ EXPORT_SYMBOL(__get_user_1);
+ EXPORT_SYMBOL(__get_user_2);
+@@ -36,3 +40,7 @@ EXPORT_SYMBOL(strstr);
+
+ EXPORT_SYMBOL(csum_partial);
+ EXPORT_SYMBOL(empty_zero_page);
++
++#ifdef CONFIG_PAX_KERNEXEC
++EXPORT_SYMBOL(__LOAD_PHYSICAL_ADDR);
++#endif
+diff -urNp linux-2.6.38.7/arch/x86/kernel/i8259.c linux-2.6.38.7/arch/x86/kernel/i8259.c
+--- linux-2.6.38.7/arch/x86/kernel/i8259.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/i8259.c 2011-04-28 19:57:25.000000000 -0400
+@@ -210,7 +210,7 @@ spurious_8259A_irq:
+ "spurious 8259A interrupt: IRQ%d.\n", irq);
+ spurious_irq_mask |= irqmask;
+ }
+- atomic_inc(&irq_err_count);
++ atomic_inc_unchecked(&irq_err_count);
+ /*
+ * Theoretically we do not have to handle this IRQ,
+ * but in Linux this does not cause problems and is
+diff -urNp linux-2.6.38.7/arch/x86/kernel/init_task.c linux-2.6.38.7/arch/x86/kernel/init_task.c
+--- linux-2.6.38.7/arch/x86/kernel/init_task.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/init_task.c 2011-04-28 19:34:14.000000000 -0400
+@@ -20,8 +20,7 @@ static struct sighand_struct init_sighan
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+-union thread_union init_thread_union __init_task_data =
+- { INIT_THREAD_INFO(init_task) };
++union thread_union init_thread_union __init_task_data;
+
+ /*
+ * Initial task structure.
+@@ -38,5 +37,5 @@ EXPORT_SYMBOL(init_task);
+ * section. Since TSS's are completely CPU-local, we want them
+ * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+ */
+-DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
+-
++struct tss_struct init_tss[NR_CPUS] ____cacheline_internodealigned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS };
++EXPORT_SYMBOL(init_tss);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/ioport.c linux-2.6.38.7/arch/x86/kernel/ioport.c
+--- linux-2.6.38.7/arch/x86/kernel/ioport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/ioport.c 2011-04-28 19:34:14.000000000 -0400
+@@ -6,6 +6,7 @@
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/capability.h>
++#include <linux/security.h>
+ #include <linux/errno.h>
+ #include <linux/types.h>
+ #include <linux/ioport.h>
+@@ -41,6 +42,12 @@ asmlinkage long sys_ioperm(unsigned long
+
+ if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
+ return -EINVAL;
++#ifdef CONFIG_GRKERNSEC_IO
++ if (turn_on && grsec_disable_privio) {
++ gr_handle_ioperm();
++ return -EPERM;
++ }
++#endif
+ if (turn_on && !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+@@ -67,7 +74,7 @@ asmlinkage long sys_ioperm(unsigned long
+ * because the ->io_bitmap_max value must match the bitmap
+ * contents:
+ */
+- tss = &per_cpu(init_tss, get_cpu());
++ tss = init_tss + get_cpu();
+
+ set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
+
+@@ -112,6 +119,12 @@ long sys_iopl(unsigned int level, struct
+ return -EINVAL;
+ /* Trying to gain more privileges? */
+ if (level > old) {
++#ifdef CONFIG_GRKERNSEC_IO
++ if (grsec_disable_privio) {
++ gr_handle_iopl();
++ return -EPERM;
++ }
++#endif
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/irq_32.c linux-2.6.38.7/arch/x86/kernel/irq_32.c
+--- linux-2.6.38.7/arch/x86/kernel/irq_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/irq_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -36,7 +36,7 @@ static int check_stack_overflow(void)
+ __asm__ __volatile__("andl %%esp,%0" :
+ "=r" (sp) : "0" (THREAD_SIZE - 1));
+
+- return sp < (sizeof(struct thread_info) + STACK_WARN);
++ return sp < STACK_WARN;
+ }
+
+ static void print_stack_overflow(void)
+@@ -54,8 +54,8 @@ static inline void print_stack_overflow(
+ * per-CPU IRQ handling contexts (thread information and stack)
+ */
+ union irq_ctx {
+- struct thread_info tinfo;
+- u32 stack[THREAD_SIZE/sizeof(u32)];
++ unsigned long previous_esp;
++ u32 stack[THREAD_SIZE/sizeof(u32)];
+ } __attribute__((aligned(THREAD_SIZE)));
+
+ static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
+@@ -75,10 +75,9 @@ static void call_on_stack(void *func, vo
+ static inline int
+ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
+ {
+- union irq_ctx *curctx, *irqctx;
++ union irq_ctx *irqctx;
+ u32 *isp, arg1, arg2;
+
+- curctx = (union irq_ctx *) current_thread_info();
+ irqctx = __this_cpu_read(hardirq_ctx);
+
+ /*
+@@ -87,21 +86,17 @@ execute_on_irq_stack(int overflow, struc
+ * handler) we can't do that and just have to keep using the
+ * current stack (which is the irq stack already after all)
+ */
+- if (unlikely(curctx == irqctx))
++ if (unlikely((void *)current_stack_pointer - (void *)irqctx < THREAD_SIZE))
+ return 0;
+
+ /* build the stack frame on the IRQ stack */
+- isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
+- irqctx->tinfo.task = curctx->tinfo.task;
+- irqctx->tinfo.previous_esp = current_stack_pointer;
++ isp = (u32 *) ((char *)irqctx + sizeof(*irqctx) - 8);
++ irqctx->previous_esp = current_stack_pointer;
++ add_preempt_count(HARDIRQ_OFFSET);
+
+- /*
+- * Copy the softirq bits in preempt_count so that the
+- * softirq checks work in the hardirq context.
+- */
+- irqctx->tinfo.preempt_count =
+- (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
+- (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ __set_fs(MAKE_MM_SEG(0));
++#endif
+
+ if (unlikely(overflow))
+ call_on_stack(print_stack_overflow, isp);
+@@ -113,6 +108,12 @@ execute_on_irq_stack(int overflow, struc
+ : "0" (irq), "1" (desc), "2" (isp),
+ "D" (desc->handle_irq)
+ : "memory", "cc", "ecx");
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ __set_fs(current_thread_info()->addr_limit);
++#endif
++
++ sub_preempt_count(HARDIRQ_OFFSET);
+ return 1;
+ }
+
+@@ -121,29 +122,11 @@ execute_on_irq_stack(int overflow, struc
+ */
+ void __cpuinit irq_ctx_init(int cpu)
+ {
+- union irq_ctx *irqctx;
+-
+ if (per_cpu(hardirq_ctx, cpu))
+ return;
+
+- irqctx = page_address(alloc_pages_node(cpu_to_node(cpu),
+- THREAD_FLAGS,
+- THREAD_ORDER));
+- memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
+- irqctx->tinfo.cpu = cpu;
+- irqctx->tinfo.preempt_count = HARDIRQ_OFFSET;
+- irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
+-
+- per_cpu(hardirq_ctx, cpu) = irqctx;
+-
+- irqctx = page_address(alloc_pages_node(cpu_to_node(cpu),
+- THREAD_FLAGS,
+- THREAD_ORDER));
+- memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
+- irqctx->tinfo.cpu = cpu;
+- irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
+-
+- per_cpu(softirq_ctx, cpu) = irqctx;
++ per_cpu(hardirq_ctx, cpu) = page_address(alloc_pages_node(cpu_to_node(cpu), THREAD_FLAGS, THREAD_ORDER));
++ per_cpu(softirq_ctx, cpu) = page_address(alloc_pages_node(cpu_to_node(cpu), THREAD_FLAGS, THREAD_ORDER));
+
+ printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n",
+ cpu, per_cpu(hardirq_ctx, cpu), per_cpu(softirq_ctx, cpu));
+@@ -152,7 +135,6 @@ void __cpuinit irq_ctx_init(int cpu)
+ asmlinkage void do_softirq(void)
+ {
+ unsigned long flags;
+- struct thread_info *curctx;
+ union irq_ctx *irqctx;
+ u32 *isp;
+
+@@ -162,15 +144,22 @@ asmlinkage void do_softirq(void)
+ local_irq_save(flags);
+
+ if (local_softirq_pending()) {
+- curctx = current_thread_info();
+ irqctx = __this_cpu_read(softirq_ctx);
+- irqctx->tinfo.task = curctx->task;
+- irqctx->tinfo.previous_esp = current_stack_pointer;
++ irqctx->previous_esp = current_stack_pointer;
+
+ /* build the stack frame on the softirq stack */
+- isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
++ isp = (u32 *) ((char *)irqctx + sizeof(*irqctx) - 8);
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ __set_fs(MAKE_MM_SEG(0));
++#endif
+
+ call_on_stack(__do_softirq, isp);
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ __set_fs(current_thread_info()->addr_limit);
++#endif
++
+ /*
+ * Shouldnt happen, we returned above if in_interrupt():
+ */
+diff -urNp linux-2.6.38.7/arch/x86/kernel/irq.c linux-2.6.38.7/arch/x86/kernel/irq.c
+--- linux-2.6.38.7/arch/x86/kernel/irq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/irq.c 2011-04-28 19:57:25.000000000 -0400
+@@ -16,7 +16,7 @@
+ #include <asm/mce.h>
+ #include <asm/hw_irq.h>
+
+-atomic_t irq_err_count;
++atomic_unchecked_t irq_err_count;
+
+ /* Function pointer for generic interrupt vector handling */
+ void (*x86_platform_ipi_callback)(void) = NULL;
+@@ -115,9 +115,9 @@ static int show_other_interrupts(struct
+ seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
+ seq_printf(p, " Machine check polls\n");
+ #endif
+- seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
++ seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read_unchecked(&irq_err_count));
+ #if defined(CONFIG_X86_IO_APIC)
+- seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
++ seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read_unchecked(&irq_mis_count));
+ #endif
+ return 0;
+ }
+@@ -210,10 +210,10 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
+
+ u64 arch_irq_stat(void)
+ {
+- u64 sum = atomic_read(&irq_err_count);
++ u64 sum = atomic_read_unchecked(&irq_err_count);
+
+ #ifdef CONFIG_X86_IO_APIC
+- sum += atomic_read(&irq_mis_count);
++ sum += atomic_read_unchecked(&irq_mis_count);
+ #endif
+ return sum;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/kgdb.c linux-2.6.38.7/arch/x86/kernel/kgdb.c
+--- linux-2.6.38.7/arch/x86/kernel/kgdb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/kgdb.c 2011-04-28 19:57:25.000000000 -0400
+@@ -124,11 +124,11 @@ char *dbg_get_reg(int regno, void *mem,
+ switch (regno) {
+ #ifdef CONFIG_X86_32
+ case GDB_SS:
+- if (!user_mode_vm(regs))
++ if (!user_mode(regs))
+ *(unsigned long *)mem = __KERNEL_DS;
+ break;
+ case GDB_SP:
+- if (!user_mode_vm(regs))
++ if (!user_mode(regs))
+ *(unsigned long *)mem = kernel_stack_pointer(regs);
+ break;
+ case GDB_GS:
+@@ -473,12 +473,12 @@ int kgdb_arch_handle_exception(int e_vec
+ case 'k':
+ /* clear the trace bit */
+ linux_regs->flags &= ~X86_EFLAGS_TF;
+- atomic_set(&kgdb_cpu_doing_single_step, -1);
++ atomic_set_unchecked(&kgdb_cpu_doing_single_step, -1);
+
+ /* set the trace bit if we're stepping */
+ if (remcomInBuffer[0] == 's') {
+ linux_regs->flags |= X86_EFLAGS_TF;
+- atomic_set(&kgdb_cpu_doing_single_step,
++ atomic_set_unchecked(&kgdb_cpu_doing_single_step,
+ raw_smp_processor_id());
+ }
+
+@@ -543,7 +543,7 @@ static int __kgdb_notify(struct die_args
+ break;
+
+ case DIE_DEBUG:
+- if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
++ if (atomic_read_unchecked(&kgdb_cpu_doing_single_step) != -1) {
+ if (user_mode(regs))
+ return single_step_cont(regs, args);
+ break;
+@@ -719,7 +719,7 @@ void kgdb_arch_set_pc(struct pt_regs *re
+ regs->ip = ip;
+ }
+
+-struct kgdb_arch arch_kgdb_ops = {
++const struct kgdb_arch arch_kgdb_ops = {
+ /* Breakpoint instruction: */
+ .gdb_bpt_instr = { 0xcc },
+ .flags = KGDB_HW_BREAKPOINT,
+diff -urNp linux-2.6.38.7/arch/x86/kernel/kprobes.c linux-2.6.38.7/arch/x86/kernel/kprobes.c
+--- linux-2.6.38.7/arch/x86/kernel/kprobes.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/kprobes.c 2011-04-28 19:34:14.000000000 -0400
+@@ -115,8 +115,11 @@ static void __kprobes __synthesize_relat
+ } __attribute__((packed)) *insn;
+
+ insn = (struct __arch_relative_insn *)from;
++
++ pax_open_kernel();
+ insn->raddr = (s32)((long)(to) - ((long)(from) + 5));
+ insn->op = op;
++ pax_close_kernel();
+ }
+
+ /* Insert a jump instruction at address 'from', which jumps to address 'to'.*/
+@@ -153,7 +156,7 @@ static int __kprobes can_boost(kprobe_op
+ kprobe_opcode_t opcode;
+ kprobe_opcode_t *orig_opcodes = opcodes;
+
+- if (search_exception_tables((unsigned long)opcodes))
++ if (search_exception_tables(ktva_ktla((unsigned long)opcodes)))
+ return 0; /* Page fault may occur on this address. */
+
+ retry:
+@@ -314,7 +317,9 @@ static int __kprobes __copy_instruction(
+ }
+ }
+ insn_get_length(&insn);
++ pax_open_kernel();
+ memcpy(dest, insn.kaddr, insn.length);
++ pax_close_kernel();
+
+ #ifdef CONFIG_X86_64
+ if (insn_rip_relative(&insn)) {
+@@ -338,7 +343,9 @@ static int __kprobes __copy_instruction(
+ (u8 *) dest;
+ BUG_ON((s64) (s32) newdisp != newdisp); /* Sanity check. */
+ disp = (u8 *) dest + insn_offset_displacement(&insn);
++ pax_open_kernel();
+ *(s32 *) disp = (s32) newdisp;
++ pax_close_kernel();
+ }
+ #endif
+ return insn.length;
+@@ -352,12 +359,12 @@ static void __kprobes arch_copy_kprobe(s
+ */
+ __copy_instruction(p->ainsn.insn, p->addr, 0);
+
+- if (can_boost(p->addr))
++ if (can_boost(ktla_ktva(p->addr)))
+ p->ainsn.boostable = 0;
+ else
+ p->ainsn.boostable = -1;
+
+- p->opcode = *p->addr;
++ p->opcode = *(ktla_ktva(p->addr));
+ }
+
+ int __kprobes arch_prepare_kprobe(struct kprobe *p)
+@@ -474,7 +481,7 @@ static void __kprobes setup_singlestep(s
+ * nor set current_kprobe, because it doesn't use single
+ * stepping.
+ */
+- regs->ip = (unsigned long)p->ainsn.insn;
++ regs->ip = ktva_ktla((unsigned long)p->ainsn.insn);
+ preempt_enable_no_resched();
+ return;
+ }
+@@ -493,7 +500,7 @@ static void __kprobes setup_singlestep(s
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->ip = (unsigned long)p->addr;
+ else
+- regs->ip = (unsigned long)p->ainsn.insn;
++ regs->ip = ktva_ktla((unsigned long)p->ainsn.insn);
+ }
+
+ /*
+@@ -572,7 +579,7 @@ static int __kprobes kprobe_handler(stru
+ setup_singlestep(p, regs, kcb, 0);
+ return 1;
+ }
+- } else if (*addr != BREAKPOINT_INSTRUCTION) {
++ } else if (*(kprobe_opcode_t *)ktla_ktva((unsigned long)addr) != BREAKPOINT_INSTRUCTION) {
+ /*
+ * The breakpoint instruction was removed right
+ * after we hit it. Another cpu has removed
+@@ -817,7 +824,7 @@ static void __kprobes resume_execution(s
+ struct pt_regs *regs, struct kprobe_ctlblk *kcb)
+ {
+ unsigned long *tos = stack_addr(regs);
+- unsigned long copy_ip = (unsigned long)p->ainsn.insn;
++ unsigned long copy_ip = ktva_ktla((unsigned long)p->ainsn.insn);
+ unsigned long orig_ip = (unsigned long)p->addr;
+ kprobe_opcode_t *insn = p->ainsn.insn;
+
+@@ -999,7 +1006,7 @@ int __kprobes kprobe_exceptions_notify(s
+ struct die_args *args = data;
+ int ret = NOTIFY_DONE;
+
+- if (args->regs && user_mode_vm(args->regs))
++ if (args->regs && user_mode(args->regs))
+ return ret;
+
+ switch (val) {
+@@ -1372,7 +1379,7 @@ int __kprobes arch_prepare_optimized_kpr
+ * Verify if the address gap is in 2GB range, because this uses
+ * a relative jump.
+ */
+- rel = (long)op->optinsn.insn - (long)op->kp.addr + RELATIVEJUMP_SIZE;
++ rel = (long)op->optinsn.insn - ktla_ktva((long)op->kp.addr) + RELATIVEJUMP_SIZE;
+ if (abs(rel) > 0x7fffffff)
+ return -ERANGE;
+
+@@ -1393,11 +1400,11 @@ int __kprobes arch_prepare_optimized_kpr
+ synthesize_set_arg1(buf + TMPL_MOVE_IDX, (unsigned long)op);
+
+ /* Set probe function call */
+- synthesize_relcall(buf + TMPL_CALL_IDX, optimized_callback);
++ synthesize_relcall(buf + TMPL_CALL_IDX, ktla_ktva(optimized_callback));
+
+ /* Set returning jmp instruction at the tail of out-of-line buffer */
+ synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size,
+- (u8 *)op->kp.addr + op->optinsn.size);
++ (u8 *)ktla_ktva(op->kp.addr) + op->optinsn.size);
+
+ flush_icache_range((unsigned long) buf,
+ (unsigned long) buf + TMPL_END_IDX +
+@@ -1419,7 +1426,7 @@ static void __kprobes setup_optimize_kpr
+ ((long)op->kp.addr + RELATIVEJUMP_SIZE));
+
+ /* Backup instructions which will be replaced by jump address */
+- memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
++ memcpy(op->optinsn.copied_insn, ktla_ktva(op->kp.addr) + INT3_SIZE,
+ RELATIVE_ADDR_SIZE);
+
+ insn_buf[0] = RELATIVEJUMP_OPCODE;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/ldt.c linux-2.6.38.7/arch/x86/kernel/ldt.c
+--- linux-2.6.38.7/arch/x86/kernel/ldt.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/ldt.c 2011-04-28 19:34:14.000000000 -0400
+@@ -67,13 +67,13 @@ static int alloc_ldt(mm_context_t *pc, i
+ if (reload) {
+ #ifdef CONFIG_SMP
+ preempt_disable();
+- load_LDT(pc);
++ load_LDT_nolock(pc);
+ if (!cpumask_equal(mm_cpumask(current->mm),
+ cpumask_of(smp_processor_id())))
+ smp_call_function(flush_ldt, current->mm, 1);
+ preempt_enable();
+ #else
+- load_LDT(pc);
++ load_LDT_nolock(pc);
+ #endif
+ }
+ if (oldsize) {
+@@ -95,7 +95,7 @@ static inline int copy_ldt(mm_context_t
+ return err;
+
+ for (i = 0; i < old->size; i++)
+- write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
++ write_ldt_entry(new->ldt, i, old->ldt + i);
+ return 0;
+ }
+
+@@ -116,6 +116,24 @@ int init_new_context(struct task_struct
+ retval = copy_ldt(&mm->context, &old_mm->context);
+ mutex_unlock(&old_mm->context.lock);
+ }
++
++ if (tsk == current) {
++ mm->context.vdso = 0;
++
++#ifdef CONFIG_X86_32
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++ mm->context.user_cs_base = 0UL;
++ mm->context.user_cs_limit = ~0UL;
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
++ cpus_clear(mm->context.cpu_user_cs_mask);
++#endif
++
++#endif
++#endif
++
++ }
++
+ return retval;
+ }
+
+@@ -230,6 +248,13 @@ static int write_ldt(void __user *ptr, u
+ }
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (ldt_info.contents & MODIFY_LDT_CONTENTS_CODE)) {
++ error = -EINVAL;
++ goto out_unlock;
++ }
++#endif
++
+ fill_ldt(&ldt, &ldt_info);
+ if (oldmode)
+ ldt.avl = 0;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/machine_kexec_32.c linux-2.6.38.7/arch/x86/kernel/machine_kexec_32.c
+--- linux-2.6.38.7/arch/x86/kernel/machine_kexec_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/machine_kexec_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -27,7 +27,7 @@
+ #include <asm/cacheflush.h>
+ #include <asm/debugreg.h>
+
+-static void set_idt(void *newidt, __u16 limit)
++static void set_idt(struct desc_struct *newidt, __u16 limit)
+ {
+ struct desc_ptr curidt;
+
+@@ -39,7 +39,7 @@ static void set_idt(void *newidt, __u16
+ }
+
+
+-static void set_gdt(void *newgdt, __u16 limit)
++static void set_gdt(struct desc_struct *newgdt, __u16 limit)
+ {
+ struct desc_ptr curgdt;
+
+@@ -217,7 +217,7 @@ void machine_kexec(struct kimage *image)
+ }
+
+ control_page = page_address(image->control_code_page);
+- memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE);
++ memcpy(control_page, (void *)ktla_ktva((unsigned long)relocate_kernel), KEXEC_CONTROL_CODE_MAX_SIZE);
+
+ relocate_kernel_ptr = control_page;
+ page_list[PA_CONTROL_PAGE] = __pa(control_page);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/microcode_amd.c linux-2.6.38.7/arch/x86/kernel/microcode_amd.c
+--- linux-2.6.38.7/arch/x86/kernel/microcode_amd.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/microcode_amd.c 2011-04-28 19:34:14.000000000 -0400
+@@ -317,7 +317,7 @@ static void microcode_fini_cpu_amd(int c
+ uci->mc = NULL;
+ }
+
+-static struct microcode_ops microcode_amd_ops = {
++static const struct microcode_ops microcode_amd_ops = {
+ .request_microcode_user = request_microcode_user,
+ .request_microcode_fw = request_microcode_fw,
+ .collect_cpu_info = collect_cpu_info_amd,
+@@ -325,7 +325,7 @@ static struct microcode_ops microcode_am
+ .microcode_fini_cpu = microcode_fini_cpu_amd,
+ };
+
+-struct microcode_ops * __init init_amd_microcode(void)
++const struct microcode_ops * __init init_amd_microcode(void)
+ {
+ return &microcode_amd_ops;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/microcode_core.c linux-2.6.38.7/arch/x86/kernel/microcode_core.c
+--- linux-2.6.38.7/arch/x86/kernel/microcode_core.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/microcode_core.c 2011-04-28 19:34:14.000000000 -0400
+@@ -92,7 +92,7 @@ MODULE_LICENSE("GPL");
+
+ #define MICROCODE_VERSION "2.00"
+
+-static struct microcode_ops *microcode_ops;
++static const struct microcode_ops *microcode_ops;
+
+ /*
+ * Synchronization.
+diff -urNp linux-2.6.38.7/arch/x86/kernel/microcode_intel.c linux-2.6.38.7/arch/x86/kernel/microcode_intel.c
+--- linux-2.6.38.7/arch/x86/kernel/microcode_intel.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/microcode_intel.c 2011-04-28 19:34:14.000000000 -0400
+@@ -440,13 +440,13 @@ static enum ucode_state request_microcod
+
+ static int get_ucode_user(void *to, const void *from, size_t n)
+ {
+- return copy_from_user(to, from, n);
++ return copy_from_user(to, (__force const void __user *)from, n);
+ }
+
+ static enum ucode_state
+ request_microcode_user(int cpu, const void __user *buf, size_t size)
+ {
+- return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
++ return generic_load_microcode(cpu, (__force void *)buf, size, &get_ucode_user);
+ }
+
+ static void microcode_fini_cpu(int cpu)
+@@ -457,7 +457,7 @@ static void microcode_fini_cpu(int cpu)
+ uci->mc = NULL;
+ }
+
+-static struct microcode_ops microcode_intel_ops = {
++static const struct microcode_ops microcode_intel_ops = {
+ .request_microcode_user = request_microcode_user,
+ .request_microcode_fw = request_microcode_fw,
+ .collect_cpu_info = collect_cpu_info,
+@@ -465,7 +465,7 @@ static struct microcode_ops microcode_in
+ .microcode_fini_cpu = microcode_fini_cpu,
+ };
+
+-struct microcode_ops * __init init_intel_microcode(void)
++const struct microcode_ops * __init init_intel_microcode(void)
+ {
+ return &microcode_intel_ops;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/module.c linux-2.6.38.7/arch/x86/kernel/module.c
+--- linux-2.6.38.7/arch/x86/kernel/module.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/module.c 2011-04-28 19:34:14.000000000 -0400
+@@ -35,21 +35,66 @@
+ #define DEBUGP(fmt...)
+ #endif
+
+-void *module_alloc(unsigned long size)
++static inline void *__module_alloc(unsigned long size, pgprot_t prot)
+ {
+ if (PAGE_ALIGN(size) > MODULES_LEN)
+ return NULL;
+ return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+- GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
++ GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, prot,
+ -1, __builtin_return_address(0));
+ }
+
++void *module_alloc(unsigned long size)
++{
++
++#ifdef CONFIG_PAX_KERNEXEC
++ return __module_alloc(size, PAGE_KERNEL);
++#else
++ return __module_alloc(size, PAGE_KERNEL_EXEC);
++#endif
++
++}
++
+ /* Free memory returned from module_alloc */
+ void module_free(struct module *mod, void *module_region)
+ {
+ vfree(module_region);
+ }
+
++#ifdef CONFIG_PAX_KERNEXEC
++#ifdef CONFIG_X86_32
++void *module_alloc_exec(unsigned long size)
++{
++ struct vm_struct *area;
++
++ if (size == 0)
++ return NULL;
++
++ area = __get_vm_area(size, VM_ALLOC, (unsigned long)&MODULES_EXEC_VADDR, (unsigned long)&MODULES_EXEC_END);
++ return area ? area->addr : NULL;
++}
++EXPORT_SYMBOL(module_alloc_exec);
++
++void module_free_exec(struct module *mod, void *module_region)
++{
++ vunmap(module_region);
++}
++EXPORT_SYMBOL(module_free_exec);
++#else
++void module_free_exec(struct module *mod, void *module_region)
++{
++ module_free(mod, module_region);
++}
++EXPORT_SYMBOL(module_free_exec);
++
++void *module_alloc_exec(unsigned long size)
++{
++ return __module_alloc(size, PAGE_KERNEL_RX);
++}
++EXPORT_SYMBOL(module_alloc_exec);
++#endif
++#endif
++
+ /* We don't need anything special. */
+ int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+@@ -69,14 +114,16 @@ int apply_relocate(Elf32_Shdr *sechdrs,
+ unsigned int i;
+ Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+- uint32_t *location;
++ uint32_t *plocation, location;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+- + rel[i].r_offset;
++ plocation = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset;
++ location = (uint32_t)plocation;
++ if (sechdrs[sechdrs[relsec].sh_info].sh_flags & SHF_EXECINSTR)
++ plocation = ktla_ktva((void *)plocation);
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+@@ -85,11 +132,15 @@ int apply_relocate(Elf32_Shdr *sechdrs,
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_386_32:
+ /* We add the value into the location given */
+- *location += sym->st_value;
++ pax_open_kernel();
++ *plocation += sym->st_value;
++ pax_close_kernel();
+ break;
+ case R_386_PC32:
+ /* Add the value, subtract its postition */
+- *location += sym->st_value - (uint32_t)location;
++ pax_open_kernel();
++ *plocation += sym->st_value - location;
++ pax_close_kernel();
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+@@ -145,21 +196,30 @@ int apply_relocate_add(Elf64_Shdr *sechd
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_64:
++ pax_open_kernel();
+ *(u64 *)loc = val;
++ pax_close_kernel();
+ break;
+ case R_X86_64_32:
++ pax_open_kernel();
+ *(u32 *)loc = val;
++ pax_close_kernel();
+ if (val != *(u32 *)loc)
+ goto overflow;
+ break;
+ case R_X86_64_32S:
++ pax_open_kernel();
+ *(s32 *)loc = val;
++ pax_close_kernel();
+ if ((s64)val != *(s32 *)loc)
+ goto overflow;
+ break;
+ case R_X86_64_PC32:
+ val -= (u64)loc;
++ pax_open_kernel();
+ *(u32 *)loc = val;
++ pax_close_kernel();
++
+ #if 0
+ if ((s64)val != *(s32 *)loc)
+ goto overflow;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/paravirt.c linux-2.6.38.7/arch/x86/kernel/paravirt.c
+--- linux-2.6.38.7/arch/x86/kernel/paravirt.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/paravirt.c 2011-05-16 21:47:08.000000000 -0400
+@@ -122,7 +122,7 @@ unsigned paravirt_patch_jmp(void *insnbu
+ * corresponding structure. */
+ static void *get_call_destination(u8 type)
+ {
+- struct paravirt_patch_template tmpl = {
++ const struct paravirt_patch_template tmpl = {
+ .pv_init_ops = pv_init_ops,
+ .pv_time_ops = pv_time_ops,
+ .pv_cpu_ops = pv_cpu_ops,
+@@ -133,6 +133,9 @@ static void *get_call_destination(u8 typ
+ .pv_lock_ops = pv_lock_ops,
+ #endif
+ };
++
++ pax_track_stack();
++
+ return *((void **)&tmpl + type);
+ }
+
+@@ -145,14 +148,14 @@ unsigned paravirt_patch_default(u8 type,
+ if (opfunc == NULL)
+ /* If there's no function, patch it with a ud2a (BUG) */
+ ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a));
+- else if (opfunc == _paravirt_nop)
++ else if (opfunc == (void *)_paravirt_nop)
+ /* If the operation is a nop, then nop the callsite */
+ ret = paravirt_patch_nop();
+
+ /* identity functions just return their single argument */
+- else if (opfunc == _paravirt_ident_32)
++ else if (opfunc == (void *)_paravirt_ident_32)
+ ret = paravirt_patch_ident_32(insnbuf, len);
+- else if (opfunc == _paravirt_ident_64)
++ else if (opfunc == (void *)_paravirt_ident_64)
+ ret = paravirt_patch_ident_64(insnbuf, len);
+
+ else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
+@@ -178,7 +181,7 @@ unsigned paravirt_patch_insns(void *insn
+ if (insn_len > len || start == NULL)
+ insn_len = len;
+ else
+- memcpy(insnbuf, start, insn_len);
++ memcpy(insnbuf, ktla_ktva(start), insn_len);
+
+ return insn_len;
+ }
+@@ -294,22 +297,22 @@ void arch_flush_lazy_mmu_mode(void)
+ preempt_enable();
+ }
+
+-struct pv_info pv_info = {
++struct pv_info pv_info __read_only = {
+ .name = "bare hardware",
+ .paravirt_enabled = 0,
+ .kernel_rpl = 0,
+ .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */
+ };
+
+-struct pv_init_ops pv_init_ops = {
++struct pv_init_ops pv_init_ops __read_only = {
+ .patch = native_patch,
+ };
+
+-struct pv_time_ops pv_time_ops = {
++struct pv_time_ops pv_time_ops __read_only = {
+ .sched_clock = native_sched_clock,
+ };
+
+-struct pv_irq_ops pv_irq_ops = {
++struct pv_irq_ops pv_irq_ops __read_only = {
+ .save_fl = __PV_IS_CALLEE_SAVE(native_save_fl),
+ .restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl),
+ .irq_disable = __PV_IS_CALLEE_SAVE(native_irq_disable),
+@@ -321,7 +324,7 @@ struct pv_irq_ops pv_irq_ops = {
+ #endif
+ };
+
+-struct pv_cpu_ops pv_cpu_ops = {
++struct pv_cpu_ops pv_cpu_ops __read_only = {
+ .cpuid = native_cpuid,
+ .get_debugreg = native_get_debugreg,
+ .set_debugreg = native_set_debugreg,
+@@ -382,7 +385,7 @@ struct pv_cpu_ops pv_cpu_ops = {
+ .end_context_switch = paravirt_nop,
+ };
+
+-struct pv_apic_ops pv_apic_ops = {
++struct pv_apic_ops pv_apic_ops __read_only = {
+ #ifdef CONFIG_X86_LOCAL_APIC
+ .startup_ipi_hook = paravirt_nop,
+ #endif
+@@ -396,7 +399,7 @@ struct pv_apic_ops pv_apic_ops = {
+ #define PTE_IDENT __PV_IS_CALLEE_SAVE(_paravirt_ident_64)
+ #endif
+
+-struct pv_mmu_ops pv_mmu_ops = {
++struct pv_mmu_ops pv_mmu_ops __read_only = {
+
+ .read_cr2 = native_read_cr2,
+ .write_cr2 = native_write_cr2,
+@@ -465,6 +468,12 @@ struct pv_mmu_ops pv_mmu_ops = {
+ },
+
+ .set_fixmap = native_set_fixmap,
++
++#ifdef CONFIG_PAX_KERNEXEC
++ .pax_open_kernel = native_pax_open_kernel,
++ .pax_close_kernel = native_pax_close_kernel,
++#endif
++
+ };
+
+ EXPORT_SYMBOL_GPL(pv_time_ops);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/paravirt-spinlocks.c linux-2.6.38.7/arch/x86/kernel/paravirt-spinlocks.c
+--- linux-2.6.38.7/arch/x86/kernel/paravirt-spinlocks.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/paravirt-spinlocks.c 2011-04-28 19:34:14.000000000 -0400
+@@ -13,7 +13,7 @@ default_spin_lock_flags(arch_spinlock_t
+ arch_spin_lock(lock);
+ }
+
+-struct pv_lock_ops pv_lock_ops = {
++struct pv_lock_ops pv_lock_ops __read_only = {
+ #ifdef CONFIG_SMP
+ .spin_is_locked = __ticket_spin_is_locked,
+ .spin_is_contended = __ticket_spin_is_contended,
+diff -urNp linux-2.6.38.7/arch/x86/kernel/pci-calgary_64.c linux-2.6.38.7/arch/x86/kernel/pci-calgary_64.c
+--- linux-2.6.38.7/arch/x86/kernel/pci-calgary_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/pci-calgary_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -476,7 +476,7 @@ static void calgary_free_coherent(struct
+ free_pages((unsigned long)vaddr, get_order(size));
+ }
+
+-static struct dma_map_ops calgary_dma_ops = {
++static const struct dma_map_ops calgary_dma_ops = {
+ .alloc_coherent = calgary_alloc_coherent,
+ .free_coherent = calgary_free_coherent,
+ .map_sg = calgary_map_sg,
+diff -urNp linux-2.6.38.7/arch/x86/kernel/pci-dma.c linux-2.6.38.7/arch/x86/kernel/pci-dma.c
+--- linux-2.6.38.7/arch/x86/kernel/pci-dma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/pci-dma.c 2011-04-28 19:34:14.000000000 -0400
+@@ -16,7 +16,7 @@
+
+ static int forbid_dac __read_mostly;
+
+-struct dma_map_ops *dma_ops = &nommu_dma_ops;
++const struct dma_map_ops *dma_ops = &nommu_dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+
+ static int iommu_sac_force __read_mostly;
+@@ -250,7 +250,7 @@ early_param("iommu", iommu_setup);
+
+ int dma_supported(struct device *dev, u64 mask)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ #ifdef CONFIG_PCI
+ if (mask > 0xffffffff && forbid_dac > 0) {
+diff -urNp linux-2.6.38.7/arch/x86/kernel/pci-gart_64.c linux-2.6.38.7/arch/x86/kernel/pci-gart_64.c
+--- linux-2.6.38.7/arch/x86/kernel/pci-gart_64.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/pci-gart_64.c 2011-05-10 22:06:52.000000000 -0400
+@@ -713,7 +713,7 @@ static __init int init_amd_gatt(struct a
+ return -1;
+ }
+
+-static struct dma_map_ops gart_dma_ops = {
++static const struct dma_map_ops gart_dma_ops = {
+ .map_sg = gart_map_sg,
+ .unmap_sg = gart_unmap_sg,
+ .map_page = gart_map_page,
+diff -urNp linux-2.6.38.7/arch/x86/kernel/pci-iommu_table.c linux-2.6.38.7/arch/x86/kernel/pci-iommu_table.c
+--- linux-2.6.38.7/arch/x86/kernel/pci-iommu_table.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/pci-iommu_table.c 2011-05-16 21:47:08.000000000 -0400
+@@ -2,7 +2,7 @@
+ #include <asm/iommu_table.h>
+ #include <linux/string.h>
+ #include <linux/kallsyms.h>
+-
++#include <linux/sched.h>
+
+ #define DEBUG 1
+
+@@ -53,6 +53,8 @@ void __init check_iommu_entries(struct i
+ char sym_p[KSYM_SYMBOL_LEN];
+ char sym_q[KSYM_SYMBOL_LEN];
+
++ pax_track_stack();
++
+ /* Simple cyclic dependency checker. */
+ for (p = start; p < finish; p++) {
+ q = find_dependents_of(start, finish, p);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/pci-nommu.c linux-2.6.38.7/arch/x86/kernel/pci-nommu.c
+--- linux-2.6.38.7/arch/x86/kernel/pci-nommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/pci-nommu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -95,7 +95,7 @@ static void nommu_sync_sg_for_device(str
+ flush_write_buffers();
+ }
+
+-struct dma_map_ops nommu_dma_ops = {
++const struct dma_map_ops nommu_dma_ops = {
+ .alloc_coherent = dma_generic_alloc_coherent,
+ .free_coherent = nommu_free_coherent,
+ .map_sg = nommu_map_sg,
+diff -urNp linux-2.6.38.7/arch/x86/kernel/pci-swiotlb.c linux-2.6.38.7/arch/x86/kernel/pci-swiotlb.c
+--- linux-2.6.38.7/arch/x86/kernel/pci-swiotlb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/pci-swiotlb.c 2011-04-28 19:34:14.000000000 -0400
+@@ -26,7 +26,7 @@ static void *x86_swiotlb_alloc_coherent(
+ return swiotlb_alloc_coherent(hwdev, size, dma_handle, flags);
+ }
+
+-static struct dma_map_ops swiotlb_dma_ops = {
++static const struct dma_map_ops swiotlb_dma_ops = {
+ .mapping_error = swiotlb_dma_mapping_error,
+ .alloc_coherent = x86_swiotlb_alloc_coherent,
+ .free_coherent = swiotlb_free_coherent,
+diff -urNp linux-2.6.38.7/arch/x86/kernel/process_32.c linux-2.6.38.7/arch/x86/kernel/process_32.c
+--- linux-2.6.38.7/arch/x86/kernel/process_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/process_32.c 2011-05-16 21:47:08.000000000 -0400
+@@ -65,6 +65,7 @@ asmlinkage void ret_from_fork(void) __as
+ unsigned long thread_saved_pc(struct task_struct *tsk)
+ {
+ return ((unsigned long *)tsk->thread.sp)[3];
++//XXX return tsk->thread.eip;
+ }
+
+ #ifndef CONFIG_SMP
+@@ -126,15 +127,14 @@ void __show_regs(struct pt_regs *regs, i
+ unsigned long sp;
+ unsigned short ss, gs;
+
+- if (user_mode_vm(regs)) {
++ if (user_mode(regs)) {
+ sp = regs->sp;
+ ss = regs->ss & 0xffff;
+- gs = get_user_gs(regs);
+ } else {
+ sp = kernel_stack_pointer(regs);
+ savesegment(ss, ss);
+- savesegment(gs, gs);
+ }
++ gs = get_user_gs(regs);
+
+ show_regs_common();
+
+@@ -196,13 +196,14 @@ int copy_thread(unsigned long clone_flag
+ struct task_struct *tsk;
+ int err;
+
+- childregs = task_pt_regs(p);
++ childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 8;
+ *childregs = *regs;
+ childregs->ax = 0;
+ childregs->sp = sp;
+
+ p->thread.sp = (unsigned long) childregs;
+ p->thread.sp0 = (unsigned long) (childregs+1);
++ p->tinfo.lowest_stack = (unsigned long)task_stack_page(p);
+
+ p->thread.ip = (unsigned long) ret_from_fork;
+
+@@ -293,7 +294,7 @@ __switch_to(struct task_struct *prev_p,
+ struct thread_struct *prev = &prev_p->thread,
+ *next = &next_p->thread;
+ int cpu = smp_processor_id();
+- struct tss_struct *tss = &per_cpu(init_tss, cpu);
++ struct tss_struct *tss = init_tss + cpu;
+ bool preload_fpu;
+
+ /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
+@@ -328,6 +329,10 @@ __switch_to(struct task_struct *prev_p,
+ */
+ lazy_save_gs(prev->gs);
+
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ __set_fs(task_thread_info(next_p)->addr_limit);
++#endif
++
+ /*
+ * Load the per-thread Thread-Local Storage descriptor.
+ */
+@@ -363,6 +368,9 @@ __switch_to(struct task_struct *prev_p,
+ */
+ arch_end_context_switch(next_p);
+
++ percpu_write(current_task, next_p);
++ percpu_write(current_tinfo, &next_p->tinfo);
++
+ if (preload_fpu)
+ __math_state_restore();
+
+@@ -372,8 +380,6 @@ __switch_to(struct task_struct *prev_p,
+ if (prev->gs | next->gs)
+ lazy_load_gs(next->gs);
+
+- percpu_write(current_task, next_p);
+-
+ return prev_p;
+ }
+
+@@ -403,4 +409,3 @@ unsigned long get_wchan(struct task_stru
+ } while (count++ < 16);
+ return 0;
+ }
+-
+diff -urNp linux-2.6.38.7/arch/x86/kernel/process_64.c linux-2.6.38.7/arch/x86/kernel/process_64.c
+--- linux-2.6.38.7/arch/x86/kernel/process_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/process_64.c 2011-05-16 21:47:08.000000000 -0400
+@@ -87,7 +87,7 @@ static void __exit_idle(void)
+ void exit_idle(void)
+ {
+ /* idle loop has pid 0 */
+- if (current->pid)
++ if (task_pid_nr(current))
+ return;
+ __exit_idle();
+ }
+@@ -260,8 +260,7 @@ int copy_thread(unsigned long clone_flag
+ struct pt_regs *childregs;
+ struct task_struct *me = current;
+
+- childregs = ((struct pt_regs *)
+- (THREAD_SIZE + task_stack_page(p))) - 1;
++ childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 16;
+ *childregs = *regs;
+
+ childregs->ax = 0;
+@@ -273,6 +272,7 @@ int copy_thread(unsigned long clone_flag
+ p->thread.sp = (unsigned long) childregs;
+ p->thread.sp0 = (unsigned long) (childregs+1);
+ p->thread.usersp = me->thread.usersp;
++ p->tinfo.lowest_stack = (unsigned long)task_stack_page(p);
+
+ set_tsk_thread_flag(p, TIF_FORK);
+
+@@ -376,7 +376,7 @@ __switch_to(struct task_struct *prev_p,
+ struct thread_struct *prev = &prev_p->thread;
+ struct thread_struct *next = &next_p->thread;
+ int cpu = smp_processor_id();
+- struct tss_struct *tss = &per_cpu(init_tss, cpu);
++ struct tss_struct *tss = init_tss + cpu;
+ unsigned fsindex, gsindex;
+ bool preload_fpu;
+
+@@ -472,10 +472,9 @@ __switch_to(struct task_struct *prev_p,
+ prev->usersp = percpu_read(old_rsp);
+ percpu_write(old_rsp, next->usersp);
+ percpu_write(current_task, next_p);
++ percpu_write(current_tinfo, &next_p->tinfo);
+
+- percpu_write(kernel_stack,
+- (unsigned long)task_stack_page(next_p) +
+- THREAD_SIZE - KERNEL_STACK_OFFSET);
++ percpu_write(kernel_stack, next->sp0);
+
+ /*
+ * Now maybe reload the debug registers and handle I/O bitmaps
+@@ -529,12 +528,11 @@ unsigned long get_wchan(struct task_stru
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+ stack = (unsigned long)task_stack_page(p);
+- if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE)
++ if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE-16-sizeof(u64))
+ return 0;
+ fp = *(u64 *)(p->thread.sp);
+ do {
+- if (fp < (unsigned long)stack ||
+- fp >= (unsigned long)stack+THREAD_SIZE)
++ if (fp < stack || fp > stack+THREAD_SIZE-16-sizeof(u64))
+ return 0;
+ ip = *(u64 *)(fp+8);
+ if (!in_sched_functions(ip))
+diff -urNp linux-2.6.38.7/arch/x86/kernel/process.c linux-2.6.38.7/arch/x86/kernel/process.c
+--- linux-2.6.38.7/arch/x86/kernel/process.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/process.c 2011-05-22 23:03:34.000000000 -0400
+@@ -48,16 +48,33 @@ void free_thread_xstate(struct task_stru
+
+ void free_thread_info(struct thread_info *ti)
+ {
+- free_thread_xstate(ti->task);
+ free_pages((unsigned long)ti, get_order(THREAD_SIZE));
+ }
+
++static struct kmem_cache *task_struct_cachep;
++
+ void arch_task_cache_init(void)
+ {
+- task_xstate_cachep =
+- kmem_cache_create("task_xstate", xstate_size,
++ /* create a slab on which task_structs can be allocated */
++ task_struct_cachep =
++ kmem_cache_create("task_struct", sizeof(struct task_struct),
++ ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL);
++
++ task_xstate_cachep =
++ kmem_cache_create("task_xstate", xstate_size,
+ __alignof__(union thread_xstate),
+- SLAB_PANIC | SLAB_NOTRACK, NULL);
++ SLAB_PANIC | SLAB_NOTRACK | SLAB_USERCOPY, NULL);
++}
++
++struct task_struct *alloc_task_struct(void)
++{
++ return kmem_cache_alloc(task_struct_cachep, GFP_KERNEL);
++}
++
++void free_task_struct(struct task_struct *task)
++{
++ free_thread_xstate(task);
++ kmem_cache_free(task_struct_cachep, task);
+ }
+
+ /*
+@@ -70,7 +87,7 @@ void exit_thread(void)
+ unsigned long *bp = t->io_bitmap_ptr;
+
+ if (bp) {
+- struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
++ struct tss_struct *tss = init_tss + get_cpu();
+
+ t->io_bitmap_ptr = NULL;
+ clear_thread_flag(TIF_IO_BITMAP);
+@@ -106,7 +123,7 @@ void show_regs_common(void)
+
+ printk(KERN_CONT "\n");
+ printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s",
+- current->pid, current->comm, print_tainted(),
++ task_pid_nr(current), current->comm, print_tainted(),
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+@@ -123,6 +140,9 @@ void flush_thread(void)
+ {
+ struct task_struct *tsk = current;
+
++#if defined(CONFIG_X86_32) && !defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_PAX_MEMORY_UDEREF)
++ loadsegment(gs, 0);
++#endif
+ flush_ptrace_hw_breakpoint(tsk);
+ memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
+ /*
+@@ -285,10 +305,10 @@ int kernel_thread(int (*fn)(void *), voi
+ regs.di = (unsigned long) arg;
+
+ #ifdef CONFIG_X86_32
+- regs.ds = __USER_DS;
+- regs.es = __USER_DS;
++ regs.ds = __KERNEL_DS;
++ regs.es = __KERNEL_DS;
+ regs.fs = __KERNEL_PERCPU;
+- regs.gs = __KERNEL_STACK_CANARY;
++ savesegment(gs, regs.gs);
+ #else
+ regs.ss = __KERNEL_DS;
+ #endif
+@@ -404,7 +424,7 @@ void default_idle(void)
+ EXPORT_SYMBOL(default_idle);
+ #endif
+
+-void stop_this_cpu(void *dummy)
++__noreturn void stop_this_cpu(void *dummy)
+ {
+ local_irq_disable();
+ /*
+@@ -668,16 +688,34 @@ static int __init idle_setup(char *str)
+ }
+ early_param("idle", idle_setup);
+
+-unsigned long arch_align_stack(unsigned long sp)
++#ifdef CONFIG_PAX_RANDKSTACK
++asmlinkage void pax_randomize_kstack(void)
+ {
+- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+- sp -= get_random_int() % 8192;
+- return sp & ~0xf;
+-}
++ struct thread_struct *thread = &current->thread;
++ unsigned long time;
+
+-unsigned long arch_randomize_brk(struct mm_struct *mm)
+-{
+- unsigned long range_end = mm->brk + 0x02000000;
+- return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+-}
++ if (!randomize_va_space)
++ return;
++
++ rdtscl(time);
++
++ /* P4 seems to return a 0 LSB, ignore it */
++#ifdef CONFIG_MPENTIUM4
++ time &= 0x3EUL;
++ time <<= 2;
++#elif defined(CONFIG_X86_64)
++ time &= 0xFUL;
++ time <<= 4;
++#else
++ time &= 0x1FUL;
++ time <<= 3;
++#endif
++
++ thread->sp0 ^= time;
++ load_sp0(init_tss + smp_processor_id(), thread);
+
++#ifdef CONFIG_X86_64
++ percpu_write(kernel_stack, thread->sp0);
++#endif
++}
++#endif
+diff -urNp linux-2.6.38.7/arch/x86/kernel/ptrace.c linux-2.6.38.7/arch/x86/kernel/ptrace.c
+--- linux-2.6.38.7/arch/x86/kernel/ptrace.c 2011-05-22 23:05:18.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/ptrace.c 2011-05-22 23:05:54.000000000 -0400
+@@ -821,7 +821,7 @@ long arch_ptrace(struct task_struct *chi
+ unsigned long addr, unsigned long data)
+ {
+ int ret;
+- unsigned long __user *datap = (unsigned long __user *)data;
++ unsigned long __user *datap = (__force unsigned long __user *)data;
+
+ switch (request) {
+ /* read the word at location addr in the USER area. */
+@@ -906,14 +906,14 @@ long arch_ptrace(struct task_struct *chi
+ if ((int) addr < 0)
+ return -EIO;
+ ret = do_get_thread_area(child, addr,
+- (struct user_desc __user *)data);
++ (__force struct user_desc __user *) data);
+ break;
+
+ case PTRACE_SET_THREAD_AREA:
+ if ((int) addr < 0)
+ return -EIO;
+ ret = do_set_thread_area(child, addr,
+- (struct user_desc __user *)data, 0);
++ (__force struct user_desc __user *) data, 0);
+ break;
+ #endif
+
+@@ -1330,7 +1330,7 @@ static void fill_sigtrap_info(struct tas
+ memset(info, 0, sizeof(*info));
+ info->si_signo = SIGTRAP;
+ info->si_code = si_code;
+- info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL;
++ info->si_addr = user_mode(regs) ? (__force void __user *)regs->ip : NULL;
+ }
+
+ void user_single_step_siginfo(struct task_struct *tsk,
+@@ -1363,7 +1363,7 @@ void send_sigtrap(struct task_struct *ts
+ * We must return the syscall number to actually look up in the table.
+ * This can be -1L to skip running any syscall at all.
+ */
+-asmregparm long syscall_trace_enter(struct pt_regs *regs)
++long syscall_trace_enter(struct pt_regs *regs)
+ {
+ long ret = 0;
+
+@@ -1408,7 +1408,7 @@ asmregparm long syscall_trace_enter(stru
+ return ret ?: regs->orig_ax;
+ }
+
+-asmregparm void syscall_trace_leave(struct pt_regs *regs)
++void syscall_trace_leave(struct pt_regs *regs)
+ {
+ bool step;
+
+diff -urNp linux-2.6.38.7/arch/x86/kernel/pvclock.c linux-2.6.38.7/arch/x86/kernel/pvclock.c
+--- linux-2.6.38.7/arch/x86/kernel/pvclock.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/pvclock.c 2011-05-11 18:35:16.000000000 -0400
+@@ -81,11 +81,11 @@ unsigned long pvclock_tsc_khz(struct pvc
+ return pv_tsc_khz;
+ }
+
+-static atomic64_t last_value = ATOMIC64_INIT(0);
++static atomic64_unchecked_t last_value = ATOMIC64_INIT(0);
+
+ void pvclock_resume(void)
+ {
+- atomic64_set(&last_value, 0);
++ atomic64_set_unchecked(&last_value, 0);
+ }
+
+ cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
+@@ -121,11 +121,11 @@ cycle_t pvclock_clocksource_read(struct
+ * updating at the same time, and one of them could be slightly behind,
+ * making the assumption that last_value always go forward fail to hold.
+ */
+- last = atomic64_read(&last_value);
++ last = atomic64_read_unchecked(&last_value);
+ do {
+ if (ret < last)
+ return last;
+- last = atomic64_cmpxchg(&last_value, last, ret);
++ last = atomic64_cmpxchg_unchecked(&last_value, last, ret);
+ } while (unlikely(last != ret));
+
+ return ret;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/reboot.c linux-2.6.38.7/arch/x86/kernel/reboot.c
+--- linux-2.6.38.7/arch/x86/kernel/reboot.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/reboot.c 2011-05-22 23:03:34.000000000 -0400
+@@ -34,7 +34,7 @@ void (*pm_power_off)(void);
+ EXPORT_SYMBOL(pm_power_off);
+
+ static const struct desc_ptr no_idt = {};
+-static int reboot_mode;
++static unsigned short reboot_mode;
+ enum reboot_type reboot_type = BOOT_KBD;
+ int reboot_force;
+
+@@ -309,12 +309,12 @@ core_initcall(reboot_init);
+ controller to pulse the CPU reset line, which is more thorough, but
+ doesn't work with at least one type of 486 motherboard. It is easy
+ to stop this code working; hence the copious comments. */
+-static const unsigned long long
+-real_mode_gdt_entries [3] =
++static struct desc_struct
++real_mode_gdt_entries [3] __read_only =
+ {
+- 0x0000000000000000ULL, /* Null descriptor */
+- 0x00009b000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */
+- 0x000093000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
++ GDT_ENTRY_INIT(0, 0, 0), /* Null descriptor */
++ GDT_ENTRY_INIT(0x9b, 0, 0xffff), /* 16-bit real-mode 64k code at 0x00000000 */
++ GDT_ENTRY_INIT(0x93, 0x100, 0xffff) /* 16-bit real-mode 64k data at 0x00000100 */
+ };
+
+ static const struct desc_ptr
+@@ -363,7 +363,7 @@ static const unsigned char jump_to_bios
+ * specified by the code and length parameters.
+ * We assume that length will aways be less that 100!
+ */
+-void machine_real_restart(const unsigned char *code, int length)
++__noreturn void machine_real_restart(const unsigned char *code, unsigned int length)
+ {
+ local_irq_disable();
+
+@@ -390,16 +390,15 @@ void machine_real_restart(const unsigned
+ boot)". This seems like a fairly standard thing that gets set by
+ REBOOT.COM programs, and the previous reset routine did this
+ too. */
+- *((unsigned short *)0x472) = reboot_mode;
++ *(unsigned short *)(__va(0x472)) = reboot_mode;
+
+ /* For the switch to real mode, copy some code to low memory. It has
+ to be in the first 64k because it is running in 16-bit mode, and it
+ has to have the same physical and virtual address, because it turns
+ off paging. Copy it near the end of the first page, out of the way
+ of BIOS variables. */
+- memcpy((void *)(0x1000 - sizeof(real_mode_switch) - 100),
+- real_mode_switch, sizeof (real_mode_switch));
+- memcpy((void *)(0x1000 - 100), code, length);
++ memcpy(__va(0x1000 - sizeof (real_mode_switch) - 100), real_mode_switch, sizeof (real_mode_switch));
++ memcpy(__va(0x1000 - 100), code, length);
+
+ /* Set up the IDT for real mode. */
+ load_idt(&real_mode_idt);
+@@ -427,6 +426,7 @@ void machine_real_restart(const unsigned
+ __asm__ __volatile__ ("ljmp $0x0008,%0"
+ :
+ : "i" ((void *)(0x1000 - sizeof (real_mode_switch) - 100)));
++ unreachable();
+ }
+ #ifdef CONFIG_APM_MODULE
+ EXPORT_SYMBOL(machine_real_restart);
+@@ -547,7 +547,7 @@ void __attribute__((weak)) mach_reboot_f
+ {
+ }
+
+-static void native_machine_emergency_restart(void)
++__noreturn static void native_machine_emergency_restart(void)
+ {
+ int i;
+
+@@ -662,13 +662,13 @@ void native_machine_shutdown(void)
+ #endif
+ }
+
+-static void __machine_emergency_restart(int emergency)
++static __noreturn void __machine_emergency_restart(int emergency)
+ {
+ reboot_emergency = emergency;
+ machine_ops.emergency_restart();
+ }
+
+-static void native_machine_restart(char *__unused)
++static __noreturn void native_machine_restart(char *__unused)
+ {
+ printk("machine restart\n");
+
+@@ -677,7 +677,7 @@ static void native_machine_restart(char
+ __machine_emergency_restart(0);
+ }
+
+-static void native_machine_halt(void)
++static __noreturn void native_machine_halt(void)
+ {
+ /* stop other cpus and apics */
+ machine_shutdown();
+@@ -688,7 +688,7 @@ static void native_machine_halt(void)
+ stop_this_cpu(NULL);
+ }
+
+-static void native_machine_power_off(void)
++__noreturn static void native_machine_power_off(void)
+ {
+ if (pm_power_off) {
+ if (!reboot_force)
+@@ -697,6 +697,7 @@ static void native_machine_power_off(voi
+ }
+ /* a fallback in case there is no PM info available */
+ tboot_shutdown(TB_SHUTDOWN_HALT);
++ unreachable();
+ }
+
+ struct machine_ops machine_ops = {
+diff -urNp linux-2.6.38.7/arch/x86/kernel/setup.c linux-2.6.38.7/arch/x86/kernel/setup.c
+--- linux-2.6.38.7/arch/x86/kernel/setup.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/setup.c 2011-04-28 19:34:14.000000000 -0400
+@@ -654,7 +654,7 @@ static void __init trim_bios_range(void)
+ * area (640->1Mb) as ram even though it is not.
+ * take them out.
+ */
+- e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1);
++ e820_remove_range(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS, E820_RAM, 1);
+ sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
+ }
+
+@@ -790,14 +790,14 @@ void __init setup_arch(char **cmdline_p)
+
+ if (!boot_params.hdr.root_flags)
+ root_mountflags &= ~MS_RDONLY;
+- init_mm.start_code = (unsigned long) _text;
+- init_mm.end_code = (unsigned long) _etext;
++ init_mm.start_code = ktla_ktva((unsigned long) _text);
++ init_mm.end_code = ktla_ktva((unsigned long) _etext);
+ init_mm.end_data = (unsigned long) _edata;
+ init_mm.brk = _brk_end;
+
+- code_resource.start = virt_to_phys(_text);
+- code_resource.end = virt_to_phys(_etext)-1;
+- data_resource.start = virt_to_phys(_etext);
++ code_resource.start = virt_to_phys(ktla_ktva(_text));
++ code_resource.end = virt_to_phys(ktla_ktva(_etext))-1;
++ data_resource.start = virt_to_phys(_sdata);
+ data_resource.end = virt_to_phys(_edata)-1;
+ bss_resource.start = virt_to_phys(&__bss_start);
+ bss_resource.end = virt_to_phys(&__bss_stop)-1;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/setup_percpu.c linux-2.6.38.7/arch/x86/kernel/setup_percpu.c
+--- linux-2.6.38.7/arch/x86/kernel/setup_percpu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/setup_percpu.c 2011-04-28 19:34:14.000000000 -0400
+@@ -21,19 +21,17 @@
+ #include <asm/cpu.h>
+ #include <asm/stackprotector.h>
+
+-DEFINE_PER_CPU(int, cpu_number);
++#ifdef CONFIG_SMP
++DEFINE_PER_CPU(unsigned int, cpu_number);
+ EXPORT_PER_CPU_SYMBOL(cpu_number);
++#endif
+
+-#ifdef CONFIG_X86_64
+ #define BOOT_PERCPU_OFFSET ((unsigned long)__per_cpu_load)
+-#else
+-#define BOOT_PERCPU_OFFSET 0
+-#endif
+
+ DEFINE_PER_CPU(unsigned long, this_cpu_off) = BOOT_PERCPU_OFFSET;
+ EXPORT_PER_CPU_SYMBOL(this_cpu_off);
+
+-unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = {
++unsigned long __per_cpu_offset[NR_CPUS] __read_only = {
+ [0 ... NR_CPUS-1] = BOOT_PERCPU_OFFSET,
+ };
+ EXPORT_SYMBOL(__per_cpu_offset);
+@@ -155,10 +153,10 @@ static inline void setup_percpu_segment(
+ {
+ #ifdef CONFIG_X86_32
+ struct desc_struct gdt;
++ unsigned long base = per_cpu_offset(cpu);
+
+- pack_descriptor(&gdt, per_cpu_offset(cpu), 0xFFFFF,
+- 0x2 | DESCTYPE_S, 0x8);
+- gdt.s = 1;
++ pack_descriptor(&gdt, base, (VMALLOC_END - base - 1) >> PAGE_SHIFT,
++ 0x83 | DESCTYPE_S, 0xC);
+ write_gdt_entry(get_cpu_gdt_table(cpu),
+ GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S);
+ #endif
+@@ -207,6 +205,11 @@ void __init setup_per_cpu_areas(void)
+ /* alrighty, percpu areas up and running */
+ delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
+ for_each_possible_cpu(cpu) {
++#ifdef CONFIG_CC_STACKPROTECTOR
++#ifdef CONFIG_x86_32
++ unsigned long canary = per_cpu(stack_canary, cpu);
++#endif
++#endif
+ per_cpu_offset(cpu) = delta + pcpu_unit_offsets[cpu];
+ per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu);
+ per_cpu(cpu_number, cpu) = cpu;
+@@ -243,6 +246,12 @@ void __init setup_per_cpu_areas(void)
+ set_cpu_numa_node(cpu, early_cpu_to_node(cpu));
+ #endif
+ #endif
++#ifdef CONFIG_CC_STACKPROTECTOR
++#ifdef CONFIG_x86_32
++ if (cpu == boot_cpu_id)
++ per_cpu(stack_canary, cpu) = canary;
++#endif
++#endif
+ /*
+ * Up to this point, the boot CPU has been using .init.data
+ * area. Reload any changed state for the boot CPU.
+diff -urNp linux-2.6.38.7/arch/x86/kernel/signal.c linux-2.6.38.7/arch/x86/kernel/signal.c
+--- linux-2.6.38.7/arch/x86/kernel/signal.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/signal.c 2011-05-22 23:03:34.000000000 -0400
+@@ -198,7 +198,7 @@ static unsigned long align_sigframe(unsi
+ * Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0.
+ */
+- sp = ((sp + 4) & -16ul) - 4;
++ sp = ((sp - 12) & -16ul) - 4;
+ #else /* !CONFIG_X86_32 */
+ sp = round_down(sp, 16) - 8;
+ #endif
+@@ -249,11 +249,11 @@ get_sigframe(struct k_sigaction *ka, str
+ * Return an always-bogus address instead so we will die with SIGSEGV.
+ */
+ if (onsigstack && !likely(on_sig_stack(sp)))
+- return (void __user *)-1L;
++ return (__force void __user *)-1L;
+
+ /* save i387 state */
+ if (used_math() && save_i387_xstate(*fpstate) < 0)
+- return (void __user *)-1L;
++ return (__force void __user *)-1L;
+
+ return (void __user *)sp;
+ }
+@@ -308,9 +308,9 @@ __setup_frame(int sig, struct k_sigactio
+ }
+
+ if (current->mm->context.vdso)
+- restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn);
++ restorer = (__force void __user *)VDSO32_SYMBOL(current->mm->context.vdso, sigreturn);
+ else
+- restorer = &frame->retcode;
++ restorer = (void __user *)&frame->retcode;
+ if (ka->sa.sa_flags & SA_RESTORER)
+ restorer = ka->sa.sa_restorer;
+
+@@ -324,7 +324,7 @@ __setup_frame(int sig, struct k_sigactio
+ * reasons and because gdb uses it as a signature to notice
+ * signal handler stack frames.
+ */
+- err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode);
++ err |= __put_user(*((u64 *)&retcode), (u64 __user *)frame->retcode);
+
+ if (err)
+ return -EFAULT;
+@@ -378,7 +378,10 @@ static int __setup_rt_frame(int sig, str
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ /* Set up to return from userspace. */
+- restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
++ if (current->mm->context.vdso)
++ restorer = (__force void __user *)VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
++ else
++ restorer = (void __user *)&frame->retcode;
+ if (ka->sa.sa_flags & SA_RESTORER)
+ restorer = ka->sa.sa_restorer;
+ put_user_ex(restorer, &frame->pretcode);
+@@ -390,7 +393,7 @@ static int __setup_rt_frame(int sig, str
+ * reasons and because gdb uses it as a signature to notice
+ * signal handler stack frames.
+ */
+- put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
++ put_user_ex(*((u64 *)&rt_retcode), (u64 __user *)frame->retcode);
+ } put_user_catch(err);
+
+ if (err)
+@@ -773,6 +776,8 @@ static void do_signal(struct pt_regs *re
+ int signr;
+ sigset_t *oldset;
+
++ pax_track_stack();
++
+ /*
+ * We want the common case to go fast, which is why we may in certain
+ * cases get here from kernel mode. Just return without doing anything
+@@ -780,7 +785,7 @@ static void do_signal(struct pt_regs *re
+ * X86_32: vm86 regs switched out by assembly code before reaching
+ * here, so testing against kernel CS suffices.
+ */
+- if (!user_mode(regs))
++ if (!user_mode_novm(regs))
+ return;
+
+ if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+diff -urNp linux-2.6.38.7/arch/x86/kernel/smpboot.c linux-2.6.38.7/arch/x86/kernel/smpboot.c
+--- linux-2.6.38.7/arch/x86/kernel/smpboot.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/smpboot.c 2011-05-11 18:34:57.000000000 -0400
+@@ -773,17 +773,20 @@ static int __cpuinit do_boot_cpu(int api
+ set_idle_for_cpu(cpu, c_idle.idle);
+ do_rest:
+ per_cpu(current_task, cpu) = c_idle.idle;
++ per_cpu(current_tinfo, cpu) = &c_idle.idle->tinfo;
+ #ifdef CONFIG_X86_32
+ /* Stack for startup_32 can be just as for start_secondary onwards */
+ irq_ctx_init(cpu);
+ #else
+ clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
+ initial_gs = per_cpu_offset(cpu);
+- per_cpu(kernel_stack, cpu) =
+- (unsigned long)task_stack_page(c_idle.idle) -
+- KERNEL_STACK_OFFSET + THREAD_SIZE;
++ per_cpu(kernel_stack, cpu) = (unsigned long)task_stack_page(c_idle.idle) - 16 + THREAD_SIZE;
+ #endif
++
++ pax_open_kernel();
+ early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
++ pax_close_kernel();
++
+ initial_code = (unsigned long)start_secondary;
+ stack_start = c_idle.idle->thread.sp;
+
+@@ -923,6 +926,12 @@ int __cpuinit native_cpu_up(unsigned int
+
+ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ clone_pgd_range(get_cpu_pgd(cpu) + KERNEL_PGD_BOUNDARY,
++ swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++ KERNEL_PGD_PTRS);
++#endif
++
+ err = do_boot_cpu(apicid, cpu);
+ if (err) {
+ pr_debug("do_boot_cpu failed %d\n", err);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/step.c linux-2.6.38.7/arch/x86/kernel/step.c
+--- linux-2.6.38.7/arch/x86/kernel/step.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/step.c 2011-04-28 19:34:14.000000000 -0400
+@@ -27,10 +27,10 @@ unsigned long convert_ip_to_linear(struc
+ struct desc_struct *desc;
+ unsigned long base;
+
+- seg &= ~7UL;
++ seg >>= 3;
+
+ mutex_lock(&child->mm->context.lock);
+- if (unlikely((seg >> 3) >= child->mm->context.size))
++ if (unlikely(seg >= child->mm->context.size))
+ addr = -1L; /* bogus selector, access would fault */
+ else {
+ desc = child->mm->context.ldt + seg;
+@@ -42,7 +42,8 @@ unsigned long convert_ip_to_linear(struc
+ addr += base;
+ }
+ mutex_unlock(&child->mm->context.lock);
+- }
++ } else if (seg == __KERNEL_CS || seg == __KERNEXEC_KERNEL_CS)
++ addr = ktla_ktva(addr);
+
+ return addr;
+ }
+@@ -53,6 +54,9 @@ static int is_setting_trap_flag(struct t
+ unsigned char opcode[15];
+ unsigned long addr = convert_ip_to_linear(child, regs);
+
++ if (addr == -EINVAL)
++ return 0;
++
+ copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
+ for (i = 0; i < copied; i++) {
+ switch (opcode[i]) {
+@@ -74,7 +78,7 @@ static int is_setting_trap_flag(struct t
+
+ #ifdef CONFIG_X86_64
+ case 0x40 ... 0x4f:
+- if (regs->cs != __USER_CS)
++ if ((regs->cs & 0xffff) != __USER_CS)
+ /* 32-bit mode: register increment */
+ return 0;
+ /* 64-bit mode: REX prefix */
+diff -urNp linux-2.6.38.7/arch/x86/kernel/syscall_table_32.S linux-2.6.38.7/arch/x86/kernel/syscall_table_32.S
+--- linux-2.6.38.7/arch/x86/kernel/syscall_table_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/syscall_table_32.S 2011-04-28 19:34:14.000000000 -0400
+@@ -1,3 +1,4 @@
++.section .rodata,"a",@progbits
+ ENTRY(sys_call_table)
+ .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
+ .long sys_exit
+diff -urNp linux-2.6.38.7/arch/x86/kernel/sys_i386_32.c linux-2.6.38.7/arch/x86/kernel/sys_i386_32.c
+--- linux-2.6.38.7/arch/x86/kernel/sys_i386_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/sys_i386_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -24,17 +24,224 @@
+
+ #include <asm/syscalls.h>
+
+-/*
+- * Do a system call from kernel instead of calling sys_execve so we
+- * end up with proper pt_regs.
+- */
+-int kernel_execve(const char *filename,
+- const char *const argv[],
+- const char *const envp[])
++int i386_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
+ {
+- long __res;
+- asm volatile ("int $0x80"
+- : "=a" (__res)
+- : "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory");
+- return __res;
++ unsigned long pax_task_size = TASK_SIZE;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
++ if (len > pax_task_size || addr > pax_task_size - len)
++ return -EINVAL;
++
++ return 0;
++}
++
++unsigned long
++arch_get_unmapped_area(struct file *filp, unsigned long addr,
++ unsigned long len, unsigned long pgoff, unsigned long flags)
++{
++ struct mm_struct *mm = current->mm;
++ struct vm_area_struct *vma;
++ unsigned long start_addr, pax_task_size = TASK_SIZE;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
++ pax_task_size -= PAGE_SIZE;
++
++ if (len > pax_task_size)
++ return -ENOMEM;
++
++ if (flags & MAP_FIXED)
++ return addr;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
++ if (addr) {
++ addr = PAGE_ALIGN(addr);
++ if (pax_task_size - len >= addr) {
++ vma = find_vma(mm, addr);
++ if (check_heap_stack_gap(vma, addr, len))
++ return addr;
++ }
++ }
++ if (len > mm->cached_hole_size) {
++ start_addr = addr = mm->free_area_cache;
++ } else {
++ start_addr = addr = mm->mmap_base;
++ mm->cached_hole_size = 0;
++ }
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (!(__supported_pte_mask & _PAGE_NX) && (mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE) && start_addr >= mm->mmap_base) {
++ start_addr = 0x00110000UL;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ start_addr += mm->delta_mmap & 0x03FFF000UL;
++#endif
++
++ if (mm->start_brk <= start_addr && start_addr < mm->mmap_base)
++ start_addr = addr = mm->mmap_base;
++ else
++ addr = start_addr;
++ }
++#endif
++
++full_search:
++ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
++ /* At this point: (!vma || addr < vma->vm_end). */
++ if (pax_task_size - len < addr) {
++ /*
++ * Start a new search - just in case we missed
++ * some holes.
++ */
++ if (start_addr != mm->mmap_base) {
++ start_addr = addr = mm->mmap_base;
++ mm->cached_hole_size = 0;
++ goto full_search;
++ }
++ return -ENOMEM;
++ }
++ if (check_heap_stack_gap(vma, addr, len))
++ break;
++ if (addr + mm->cached_hole_size < vma->vm_start)
++ mm->cached_hole_size = vma->vm_start - addr;
++ addr = vma->vm_end;
++ if (mm->start_brk <= addr && addr < mm->mmap_base) {
++ start_addr = addr = mm->mmap_base;
++ mm->cached_hole_size = 0;
++ goto full_search;
++ }
++ }
++
++ /*
++ * Remember the place where we stopped the search:
++ */
++ mm->free_area_cache = addr + len;
++ return addr;
++}
++
++unsigned long
++arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
++ const unsigned long len, const unsigned long pgoff,
++ const unsigned long flags)
++{
++ struct vm_area_struct *vma;
++ struct mm_struct *mm = current->mm;
++ unsigned long base = mm->mmap_base, addr = addr0, pax_task_size = TASK_SIZE;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
++ pax_task_size -= PAGE_SIZE;
++
++ /* requested length too big for entire address space */
++ if (len > pax_task_size)
++ return -ENOMEM;
++
++ if (flags & MAP_FIXED)
++ return addr;
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (!(__supported_pte_mask & _PAGE_NX) && (mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE))
++ goto bottomup;
++#endif
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
++ /* requesting a specific address */
++ if (addr) {
++ addr = PAGE_ALIGN(addr);
++ if (pax_task_size - len >= addr) {
++ vma = find_vma(mm, addr);
++ if (check_heap_stack_gap(vma, addr, len))
++ return addr;
++ }
++ }
++
++ /* check if free_area_cache is useful for us */
++ if (len <= mm->cached_hole_size) {
++ mm->cached_hole_size = 0;
++ mm->free_area_cache = mm->mmap_base;
++ }
++
++ /* either no address requested or can't fit in requested address hole */
++ addr = mm->free_area_cache;
++
++ /* make sure it can fit in the remaining address space */
++ if (addr > len) {
++ vma = find_vma(mm, addr-len);
++ if (check_heap_stack_gap(vma, addr - len, len))
++ /* remember the address as a hint for next time */
++ return (mm->free_area_cache = addr-len);
++ }
++
++ if (mm->mmap_base < len)
++ goto bottomup;
++
++ addr = mm->mmap_base-len;
++
++ do {
++ /*
++ * Lookup failure means no vma is above this address,
++ * else if new region fits below vma->vm_start,
++ * return with success:
++ */
++ vma = find_vma(mm, addr);
++ if (check_heap_stack_gap(vma, addr, len))
++ /* remember the address as a hint for next time */
++ return (mm->free_area_cache = addr);
++
++ /* remember the largest hole we saw so far */
++ if (addr + mm->cached_hole_size < vma->vm_start)
++ mm->cached_hole_size = vma->vm_start - addr;
++
++ /* try just below the current vma->vm_start */
++ addr = skip_heap_stack_gap(vma, len);
++ } while (!IS_ERR_VALUE(addr));
++
++bottomup:
++ /*
++ * A failed mmap() very likely causes application failure,
++ * so fall back to the bottom-up function here. This scenario
++ * can happen with large stack limits and large mmap()
++ * allocations.
++ */
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ mm->mmap_base = SEGMEXEC_TASK_UNMAPPED_BASE;
++ else
++#endif
++
++ mm->mmap_base = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
++ mm->free_area_cache = mm->mmap_base;
++ mm->cached_hole_size = ~0UL;
++ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
++ /*
++ * Restore the topdown base:
++ */
++ mm->mmap_base = base;
++ mm->free_area_cache = base;
++ mm->cached_hole_size = ~0UL;
++
++ return addr;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/sys_x86_64.c linux-2.6.38.7/arch/x86/kernel/sys_x86_64.c
+--- linux-2.6.38.7/arch/x86/kernel/sys_x86_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/sys_x86_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -32,8 +32,8 @@ out:
+ return error;
+ }
+
+-static void find_start_end(unsigned long flags, unsigned long *begin,
+- unsigned long *end)
++static void find_start_end(struct mm_struct *mm, unsigned long flags,
++ unsigned long *begin, unsigned long *end)
+ {
+ if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
+ unsigned long new_begin;
+@@ -52,7 +52,7 @@ static void find_start_end(unsigned long
+ *begin = new_begin;
+ }
+ } else {
+- *begin = TASK_UNMAPPED_BASE;
++ *begin = mm->mmap_base;
+ *end = TASK_SIZE;
+ }
+ }
+@@ -69,16 +69,19 @@ arch_get_unmapped_area(struct file *filp
+ if (flags & MAP_FIXED)
+ return addr;
+
+- find_start_end(flags, &begin, &end);
++ find_start_end(mm, flags, &begin, &end);
+
+ if (len > end)
+ return -ENOMEM;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ if (addr) {
+ addr = PAGE_ALIGN(addr);
+ vma = find_vma(mm, addr);
+- if (end - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (end - len >= addr && check_heap_stack_gap(vma, addr, len))
+ return addr;
+ }
+ if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32))
+@@ -106,7 +109,7 @@ full_search:
+ }
+ return -ENOMEM;
+ }
+- if (!vma || addr + len <= vma->vm_start) {
++ if (check_heap_stack_gap(vma, addr, len)) {
+ /*
+ * Remember the place where we stopped the search:
+ */
+@@ -128,7 +131,7 @@ arch_get_unmapped_area_topdown(struct fi
+ {
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+- unsigned long addr = addr0;
++ unsigned long base = mm->mmap_base, addr = addr0;
+
+ /* requested length too big for entire address space */
+ if (len > TASK_SIZE)
+@@ -141,13 +144,18 @@ arch_get_unmapped_area_topdown(struct fi
+ if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT))
+ goto bottomup;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ /* requesting a specific address */
+ if (addr) {
+ addr = PAGE_ALIGN(addr);
+- vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
+- return addr;
++ if (TASK_SIZE - len >= addr) {
++ vma = find_vma(mm, addr);
++ if (check_heap_stack_gap(vma, addr, len))
++ return addr;
++ }
+ }
+
+ /* check if free_area_cache is useful for us */
+@@ -162,7 +170,7 @@ arch_get_unmapped_area_topdown(struct fi
+ /* make sure it can fit in the remaining address space */
+ if (addr > len) {
+ vma = find_vma(mm, addr-len);
+- if (!vma || addr <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr - len, len))
+ /* remember the address as a hint for next time */
+ return mm->free_area_cache = addr-len;
+ }
+@@ -179,7 +187,7 @@ arch_get_unmapped_area_topdown(struct fi
+ * return with success:
+ */
+ vma = find_vma(mm, addr);
+- if (!vma || addr+len <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr, len))
+ /* remember the address as a hint for next time */
+ return mm->free_area_cache = addr;
+
+@@ -188,8 +196,8 @@ arch_get_unmapped_area_topdown(struct fi
+ mm->cached_hole_size = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+- addr = vma->vm_start-len;
+- } while (len < vma->vm_start);
++ addr = skip_heap_stack_gap(vma, len);
++ } while (!IS_ERR_VALUE(addr));
+
+ bottomup:
+ /*
+@@ -198,13 +206,21 @@ bottomup:
+ * can happen with large stack limits and large mmap()
+ * allocations.
+ */
++ mm->mmap_base = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
++ mm->free_area_cache = mm->mmap_base;
+ mm->cached_hole_size = ~0UL;
+- mm->free_area_cache = TASK_UNMAPPED_BASE;
+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+ /*
+ * Restore the topdown base:
+ */
+- mm->free_area_cache = mm->mmap_base;
++ mm->mmap_base = base;
++ mm->free_area_cache = base;
+ mm->cached_hole_size = ~0UL;
+
+ return addr;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/tboot.c linux-2.6.38.7/arch/x86/kernel/tboot.c
+--- linux-2.6.38.7/arch/x86/kernel/tboot.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/tboot.c 2011-05-22 23:03:34.000000000 -0400
+@@ -218,7 +218,7 @@ static int tboot_setup_sleep(void)
+
+ void tboot_shutdown(u32 shutdown_type)
+ {
+- void (*shutdown)(void);
++ void (* __noreturn shutdown)(void);
+
+ if (!tboot_enabled())
+ return;
+@@ -240,7 +240,7 @@ void tboot_shutdown(u32 shutdown_type)
+
+ switch_to_tboot_pt();
+
+- shutdown = (void(*)(void))(unsigned long)tboot->shutdown_entry;
++ shutdown = (void *)tboot->shutdown_entry;
+ shutdown();
+
+ /* should not reach here */
+@@ -297,7 +297,7 @@ void tboot_sleep(u8 sleep_state, u32 pm1
+ tboot_shutdown(acpi_shutdown_map[sleep_state]);
+ }
+
+-static atomic_t ap_wfs_count;
++static atomic_unchecked_t ap_wfs_count;
+
+ static int tboot_wait_for_aps(int num_aps)
+ {
+@@ -321,9 +321,9 @@ static int __cpuinit tboot_cpu_callback(
+ {
+ switch (action) {
+ case CPU_DYING:
+- atomic_inc(&ap_wfs_count);
++ atomic_inc_unchecked(&ap_wfs_count);
+ if (num_online_cpus() == 1)
+- if (tboot_wait_for_aps(atomic_read(&ap_wfs_count)))
++ if (tboot_wait_for_aps(atomic_read_unchecked(&ap_wfs_count)))
+ return NOTIFY_BAD;
+ break;
+ }
+@@ -342,7 +342,7 @@ static __init int tboot_late_init(void)
+
+ tboot_create_trampoline();
+
+- atomic_set(&ap_wfs_count, 0);
++ atomic_set_unchecked(&ap_wfs_count, 0);
+ register_hotcpu_notifier(&tboot_cpu_notifier);
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/time.c linux-2.6.38.7/arch/x86/kernel/time.c
+--- linux-2.6.38.7/arch/x86/kernel/time.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/time.c 2011-04-28 19:34:14.000000000 -0400
+@@ -22,17 +22,13 @@
+ #include <asm/hpet.h>
+ #include <asm/time.h>
+
+-#ifdef CONFIG_X86_64
+-volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+-#endif
+-
+ unsigned long profile_pc(struct pt_regs *regs)
+ {
+ unsigned long pc = instruction_pointer(regs);
+
+- if (!user_mode_vm(regs) && in_lock_functions(pc)) {
++ if (!user_mode(regs) && in_lock_functions(pc)) {
+ #ifdef CONFIG_FRAME_POINTER
+- return *(unsigned long *)(regs->bp + sizeof(long));
++ return ktla_ktva(*(unsigned long *)(regs->bp + sizeof(long)));
+ #else
+ unsigned long *sp =
+ (unsigned long *)kernel_stack_pointer(regs);
+@@ -41,11 +37,17 @@ unsigned long profile_pc(struct pt_regs
+ * or above a saved flags. Eflags has bits 22-31 zero,
+ * kernel addresses don't.
+ */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ return ktla_ktva(sp[0]);
++#else
+ if (sp[0] >> 22)
+ return sp[0];
+ if (sp[1] >> 22)
+ return sp[1];
+ #endif
++
++#endif
+ }
+ return pc;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/kernel/tls.c linux-2.6.38.7/arch/x86/kernel/tls.c
+--- linux-2.6.38.7/arch/x86/kernel/tls.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/tls.c 2011-04-28 19:34:14.000000000 -0400
+@@ -85,6 +85,11 @@ int do_set_thread_area(struct task_struc
+ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+ return -EINVAL;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((p->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
++ return -EINVAL;
++#endif
++
+ set_tls_desc(p, idx, &info, 1);
+
+ return 0;
+diff -urNp linux-2.6.38.7/arch/x86/kernel/trampoline_32.S linux-2.6.38.7/arch/x86/kernel/trampoline_32.S
+--- linux-2.6.38.7/arch/x86/kernel/trampoline_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/trampoline_32.S 2011-04-28 19:34:14.000000000 -0400
+@@ -32,6 +32,12 @@
+ #include <asm/segment.h>
+ #include <asm/page_types.h>
+
++#ifdef CONFIG_PAX_KERNEXEC
++#define ta(X) (X)
++#else
++#define ta(X) ((X) - __PAGE_OFFSET)
++#endif
++
+ /* We can free up trampoline after bootup if cpu hotplug is not supported. */
+ __CPUINITRODATA
+ .code16
+@@ -60,7 +66,7 @@ r_base = .
+ inc %ax # protected mode (PE) bit
+ lmsw %ax # into protected mode
+ # flush prefetch and jump to startup_32_smp in arch/i386/kernel/head.S
+- ljmpl $__BOOT_CS, $(startup_32_smp-__PAGE_OFFSET)
++ ljmpl $__BOOT_CS, $ta(startup_32_smp)
+
+ # These need to be in the same 64K segment as the above;
+ # hence we don't use the boot_gdt_descr defined in head.S
+diff -urNp linux-2.6.38.7/arch/x86/kernel/trampoline_64.S linux-2.6.38.7/arch/x86/kernel/trampoline_64.S
+--- linux-2.6.38.7/arch/x86/kernel/trampoline_64.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/trampoline_64.S 2011-04-28 19:34:14.000000000 -0400
+@@ -91,7 +91,7 @@ startup_32:
+ movl $__KERNEL_DS, %eax # Initialize the %ds segment register
+ movl %eax, %ds
+
+- movl $X86_CR4_PAE, %eax
++ movl $(X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE), %eax
+ movl %eax, %cr4 # Enable PAE mode
+
+ # Setup trampoline 4 level pagetables
+@@ -138,7 +138,7 @@ tidt:
+ # so the kernel can live anywhere
+ .balign 4
+ tgdt:
+- .short tgdt_end - tgdt # gdt limit
++ .short tgdt_end - tgdt - 1 # gdt limit
+ .long tgdt - r_base
+ .short 0
+ .quad 0x00cf9b000000ffff # __KERNEL32_CS
+diff -urNp linux-2.6.38.7/arch/x86/kernel/traps.c linux-2.6.38.7/arch/x86/kernel/traps.c
+--- linux-2.6.38.7/arch/x86/kernel/traps.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/traps.c 2011-04-28 19:34:14.000000000 -0400
+@@ -70,12 +70,6 @@ asmlinkage int system_call(void);
+
+ /* Do we ignore FPU interrupts ? */
+ char ignore_fpu_irq;
+-
+-/*
+- * The IDT has to be page-aligned to simplify the Pentium
+- * F0 0F bug workaround.
+- */
+-gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, };
+ #endif
+
+ DECLARE_BITMAP(used_vectors, NR_VECTORS);
+@@ -117,13 +111,13 @@ static inline void preempt_conditional_c
+ }
+
+ static void __kprobes
+-do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
++do_trap(int trapnr, int signr, const char *str, struct pt_regs *regs,
+ long error_code, siginfo_t *info)
+ {
+ struct task_struct *tsk = current;
+
+ #ifdef CONFIG_X86_32
+- if (regs->flags & X86_VM_MASK) {
++ if (v8086_mode(regs)) {
+ /*
+ * traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
+ * On nmi (interrupt 2), do_trap should not be called.
+@@ -134,7 +128,7 @@ do_trap(int trapnr, int signr, char *str
+ }
+ #endif
+
+- if (!user_mode(regs))
++ if (!user_mode_novm(regs))
+ goto kernel_trap;
+
+ #ifdef CONFIG_X86_32
+@@ -157,7 +151,7 @@ trap_signal:
+ printk_ratelimit()) {
+ printk(KERN_INFO
+ "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+- tsk->comm, tsk->pid, str,
++ tsk->comm, task_pid_nr(tsk), str,
+ regs->ip, regs->sp, error_code);
+ print_vma_addr(" in ", regs->ip);
+ printk("\n");
+@@ -174,8 +168,20 @@ kernel_trap:
+ if (!fixup_exception(regs)) {
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = trapnr;
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ if (trapnr == 12 && ((regs->cs & 0xFFFF) == __KERNEL_CS || (regs->cs & 0xFFFF) == __KERNEXEC_KERNEL_CS))
++ str = "PAX: suspicious stack segment fault";
++#endif
++
+ die(str, regs, error_code);
+ }
++
++#ifdef CONFIG_PAX_REFCOUNT
++ if (trapnr == 4)
++ pax_report_refcount_overflow(regs);
++#endif
++
+ return;
+
+ #ifdef CONFIG_X86_32
+@@ -264,14 +270,30 @@ do_general_protection(struct pt_regs *re
+ conditional_sti(regs);
+
+ #ifdef CONFIG_X86_32
+- if (regs->flags & X86_VM_MASK)
++ if (v8086_mode(regs))
+ goto gp_in_vm86;
+ #endif
+
+ tsk = current;
+- if (!user_mode(regs))
++ if (!user_mode_novm(regs))
+ goto gp_in_kernel;
+
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC)
++ if (!(__supported_pte_mask & _PAGE_NX) && tsk->mm && (tsk->mm->pax_flags & MF_PAX_PAGEEXEC)) {
++ struct mm_struct *mm = tsk->mm;
++ unsigned long limit;
++
++ down_write(&mm->mmap_sem);
++ limit = mm->context.user_cs_limit;
++ if (limit < TASK_SIZE) {
++ track_exec_limit(mm, limit, TASK_SIZE, VM_EXEC);
++ up_write(&mm->mmap_sem);
++ return;
++ }
++ up_write(&mm->mmap_sem);
++ }
++#endif
++
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 13;
+
+@@ -304,6 +326,13 @@ gp_in_kernel:
+ if (notify_die(DIE_GPF, "general protection fault", regs,
+ error_code, 13, SIGSEGV) == NOTIFY_STOP)
+ return;
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ if ((regs->cs & 0xFFFF) == __KERNEL_CS || (regs->cs & 0xFFFF) == __KERNEXEC_KERNEL_CS)
++ die("PAX: suspicious general protection fault", regs, error_code);
++ else
++#endif
++
+ die("general protection fault", regs, error_code);
+ }
+
+@@ -569,7 +598,7 @@ dotraplinkage void __kprobes do_debug(st
+ /* It's safe to allow irq's after DR6 has been saved */
+ preempt_conditional_sti(regs);
+
+- if (regs->flags & X86_VM_MASK) {
++ if (v8086_mode(regs)) {
+ handle_vm86_trap((struct kernel_vm86_regs *) regs,
+ error_code, 1);
+ preempt_conditional_cli(regs);
+@@ -583,7 +612,7 @@ dotraplinkage void __kprobes do_debug(st
+ * We already checked v86 mode above, so we can check for kernel mode
+ * by just checking the CPL of CS.
+ */
+- if ((dr6 & DR_STEP) && !user_mode(regs)) {
++ if ((dr6 & DR_STEP) && !user_mode_novm(regs)) {
+ tsk->thread.debugreg6 &= ~DR_STEP;
+ set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+ regs->flags &= ~X86_EFLAGS_TF;
+@@ -612,7 +641,7 @@ void math_error(struct pt_regs *regs, in
+ return;
+ conditional_sti(regs);
+
+- if (!user_mode_vm(regs))
++ if (!user_mode(regs))
+ {
+ if (!fixup_exception(regs)) {
+ task->thread.error_code = error_code;
+@@ -723,7 +752,7 @@ asmlinkage void __attribute__((weak)) sm
+ void __math_state_restore(void)
+ {
+ struct thread_info *thread = current_thread_info();
+- struct task_struct *tsk = thread->task;
++ struct task_struct *tsk = current;
+
+ /*
+ * Paranoid restore. send a SIGSEGV if we fail to restore the state.
+@@ -750,8 +779,7 @@ void __math_state_restore(void)
+ */
+ asmlinkage void math_state_restore(void)
+ {
+- struct thread_info *thread = current_thread_info();
+- struct task_struct *tsk = thread->task;
++ struct task_struct *tsk = current;
+
+ if (!tsk_used_math(tsk)) {
+ local_irq_enable();
+diff -urNp linux-2.6.38.7/arch/x86/kernel/vm86_32.c linux-2.6.38.7/arch/x86/kernel/vm86_32.c
+--- linux-2.6.38.7/arch/x86/kernel/vm86_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/vm86_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -41,6 +41,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/audit.h>
+ #include <linux/stddef.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -148,7 +149,7 @@ struct pt_regs *save_v86_state(struct ke
+ do_exit(SIGSEGV);
+ }
+
+- tss = &per_cpu(init_tss, get_cpu());
++ tss = init_tss + get_cpu();
+ current->thread.sp0 = current->thread.saved_sp0;
+ current->thread.sysenter_cs = __KERNEL_CS;
+ load_sp0(tss, &current->thread);
+@@ -208,6 +209,13 @@ int sys_vm86old(struct vm86_struct __use
+ struct task_struct *tsk;
+ int tmp, ret = -EPERM;
+
++#ifdef CONFIG_GRKERNSEC_VM86
++ if (!capable(CAP_SYS_RAWIO)) {
++ gr_handle_vm86();
++ goto out;
++ }
++#endif
++
+ tsk = current;
+ if (tsk->thread.saved_sp0)
+ goto out;
+@@ -238,6 +246,14 @@ int sys_vm86(unsigned long cmd, unsigned
+ int tmp, ret;
+ struct vm86plus_struct __user *v86;
+
++#ifdef CONFIG_GRKERNSEC_VM86
++ if (!capable(CAP_SYS_RAWIO)) {
++ gr_handle_vm86();
++ ret = -EPERM;
++ goto out;
++ }
++#endif
++
+ tsk = current;
+ switch (cmd) {
+ case VM86_REQUEST_IRQ:
+@@ -324,7 +340,7 @@ static void do_sys_vm86(struct kernel_vm
+ tsk->thread.saved_fs = info->regs32->fs;
+ tsk->thread.saved_gs = get_user_gs(info->regs32);
+
+- tss = &per_cpu(init_tss, get_cpu());
++ tss = init_tss + get_cpu();
+ tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0;
+ if (cpu_has_sep)
+ tsk->thread.sysenter_cs = 0;
+@@ -529,7 +545,7 @@ static void do_int(struct kernel_vm86_re
+ goto cannot_handle;
+ if (i == 0x21 && is_revectored(AH(regs), &KVM86->int21_revectored))
+ goto cannot_handle;
+- intr_ptr = (unsigned long __user *) (i << 2);
++ intr_ptr = (__force unsigned long __user *) (i << 2);
+ if (get_user(segoffs, intr_ptr))
+ goto cannot_handle;
+ if ((segoffs >> 16) == BIOSSEG)
+diff -urNp linux-2.6.38.7/arch/x86/kernel/vmlinux.lds.S linux-2.6.38.7/arch/x86/kernel/vmlinux.lds.S
+--- linux-2.6.38.7/arch/x86/kernel/vmlinux.lds.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/vmlinux.lds.S 2011-04-28 19:34:14.000000000 -0400
+@@ -26,6 +26,13 @@
+ #include <asm/page_types.h>
+ #include <asm/cache.h>
+ #include <asm/boot.h>
++#include <asm/segment.h>
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++#define __KERNEL_TEXT_OFFSET (LOAD_OFFSET + ____LOAD_PHYSICAL_ADDR)
++#else
++#define __KERNEL_TEXT_OFFSET 0
++#endif
+
+ #undef i386 /* in case the preprocessor is a 32bit one */
+
+@@ -34,11 +41,9 @@ OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT, CONF
+ #ifdef CONFIG_X86_32
+ OUTPUT_ARCH(i386)
+ ENTRY(phys_startup_32)
+-jiffies = jiffies_64;
+ #else
+ OUTPUT_ARCH(i386:x86-64)
+ ENTRY(phys_startup_64)
+-jiffies_64 = jiffies;
+ #endif
+
+ #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
+@@ -69,31 +74,46 @@ jiffies_64 = jiffies;
+
+ PHDRS {
+ text PT_LOAD FLAGS(5); /* R_E */
++#ifdef CONFIG_X86_32
++ module PT_LOAD FLAGS(5); /* R_E */
++#endif
++#ifdef CONFIG_XEN
++ rodata PT_LOAD FLAGS(5); /* R_E */
++#else
++ rodata PT_LOAD FLAGS(4); /* R__ */
++#endif
+ data PT_LOAD FLAGS(6); /* RW_ */
+ #ifdef CONFIG_X86_64
+ user PT_LOAD FLAGS(5); /* R_E */
++#endif
++ init.begin PT_LOAD FLAGS(6); /* RW_ */
+ #ifdef CONFIG_SMP
+ percpu PT_LOAD FLAGS(6); /* RW_ */
+ #endif
++ text.init PT_LOAD FLAGS(5); /* R_E */
++ text.exit PT_LOAD FLAGS(5); /* R_E */
+ init PT_LOAD FLAGS(7); /* RWE */
+-#endif
+ note PT_NOTE FLAGS(0); /* ___ */
+ }
+
+ SECTIONS
+ {
+ #ifdef CONFIG_X86_32
+- . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
+- phys_startup_32 = startup_32 - LOAD_OFFSET;
++ . = LOAD_OFFSET + ____LOAD_PHYSICAL_ADDR;
+ #else
+- . = __START_KERNEL;
+- phys_startup_64 = startup_64 - LOAD_OFFSET;
++ . = __START_KERNEL;
+ #endif
+
+ /* Text and read-only data */
+- .text : AT(ADDR(.text) - LOAD_OFFSET) {
+- _text = .;
++ .text (. - __KERNEL_TEXT_OFFSET): AT(ADDR(.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
+ /* bootstrapping code */
++#ifdef CONFIG_X86_32
++ phys_startup_32 = startup_32 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET;
++#else
++ phys_startup_64 = startup_64 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET;
++#endif
++ __LOAD_PHYSICAL_ADDR = . - LOAD_OFFSET + __KERNEL_TEXT_OFFSET;
++ _text = .;
+ HEAD_TEXT
+ #ifdef CONFIG_X86_32
+ . = ALIGN(PAGE_SIZE);
+@@ -108,13 +128,47 @@ SECTIONS
+ IRQENTRY_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+- /* End of text section */
+- _etext = .;
+ } :text = 0x9090
+
+- NOTES :text :note
++ . += __KERNEL_TEXT_OFFSET;
++
++#ifdef CONFIG_X86_32
++ . = ALIGN(PAGE_SIZE);
++ .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) {
++
++#if defined(CONFIG_PAX_KERNEXEC) && defined(CONFIG_MODULES)
++ MODULES_EXEC_VADDR = .;
++ BYTE(0)
++ . += (CONFIG_PAX_KERNEXEC_MODULE_TEXT * 1024 * 1024);
++ . = ALIGN(HPAGE_SIZE);
++ MODULES_EXEC_END = . - 1;
++#endif
++
++ } :module
++#endif
++
++ .text.end : AT(ADDR(.text.end) - LOAD_OFFSET) {
++ /* End of text section */
++ _etext = . - __KERNEL_TEXT_OFFSET;
++ }
+
+- EXCEPTION_TABLE(16) :text = 0x9090
++#ifdef CONFIG_X86_32
++ . = ALIGN(PAGE_SIZE);
++ .rodata.page_aligned : AT(ADDR(.rodata.page_aligned) - LOAD_OFFSET) {
++ *(.idt)
++ . = ALIGN(PAGE_SIZE);
++ *(.empty_zero_page)
++ *(.initial_pg_fixmap)
++ *(.initial_pg_pmd)
++ *(.initial_page_table)
++ *(.swapper_pg_dir)
++ } :rodata
++#endif
++
++ . = ALIGN(PAGE_SIZE);
++ NOTES :rodata :note
++
++ EXCEPTION_TABLE(16) :rodata
+
+ #if defined(CONFIG_DEBUG_RODATA)
+ /* .text should occupy whole number of pages */
+@@ -126,16 +180,20 @@ SECTIONS
+
+ /* Data */
+ .data : AT(ADDR(.data) - LOAD_OFFSET) {
++
++#ifdef CONFIG_PAX_KERNEXEC
++ . = ALIGN(HPAGE_SIZE);
++#else
++ . = ALIGN(PAGE_SIZE);
++#endif
++
+ /* Start of data section */
+ _sdata = .;
+
+ /* init_task */
+ INIT_TASK_DATA(THREAD_SIZE)
+
+-#ifdef CONFIG_X86_32
+- /* 32 bit has nosave before _edata */
+ NOSAVE_DATA
+-#endif
+
+ PAGE_ALIGNED_DATA(PAGE_SIZE)
+
+@@ -144,6 +202,8 @@ SECTIONS
+ DATA_DATA
+ CONSTRUCTORS
+
++ jiffies = jiffies_64;
++
+ /* rarely changed data like cpu maps */
+ READ_MOSTLY_DATA(INTERNODE_CACHE_BYTES)
+
+@@ -198,12 +258,6 @@ SECTIONS
+ }
+ vgetcpu_mode = VVIRT(.vgetcpu_mode);
+
+- . = ALIGN(L1_CACHE_BYTES);
+- .jiffies : AT(VLOAD(.jiffies)) {
+- *(.jiffies)
+- }
+- jiffies = VVIRT(.jiffies);
+-
+ .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) {
+ *(.vsyscall_3)
+ }
+@@ -219,12 +273,19 @@ SECTIONS
+ #endif /* CONFIG_X86_64 */
+
+ /* Init code and data - will be freed after init */
+- . = ALIGN(PAGE_SIZE);
+ .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {
++ BYTE(0)
++
++#ifdef CONFIG_PAX_KERNEXEC
++ . = ALIGN(HPAGE_SIZE);
++#else
++ . = ALIGN(PAGE_SIZE);
++#endif
++
+ __init_begin = .; /* paired with __init_end */
+- }
++ } :init.begin
+
+-#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
++#ifdef CONFIG_SMP
+ /*
+ * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the
+ * output PHDR, so the next output section - .init.text - should
+@@ -233,12 +294,27 @@ SECTIONS
+ PERCPU_VADDR(0, :percpu)
+ #endif
+
+- INIT_TEXT_SECTION(PAGE_SIZE)
+-#ifdef CONFIG_X86_64
+- :init
+-#endif
++ . = ALIGN(PAGE_SIZE);
++ init_begin = .;
++ .init.text (. - __KERNEL_TEXT_OFFSET): AT(init_begin - LOAD_OFFSET) {
++ VMLINUX_SYMBOL(_sinittext) = .;
++ INIT_TEXT
++ VMLINUX_SYMBOL(_einittext) = .;
++ . = ALIGN(PAGE_SIZE);
++ } :text.init
+
+- INIT_DATA_SECTION(16)
++ /*
++ * .exit.text is discard at runtime, not link time, to deal with
++ * references from .altinstructions and .eh_frame
++ */
++ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
++ EXIT_TEXT
++ . = ALIGN(16);
++ } :text.exit
++ . = init_begin + SIZEOF(.init.text) + SIZEOF(.exit.text);
++
++ . = ALIGN(PAGE_SIZE);
++ INIT_DATA_SECTION(16) :init
+
+ .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
+ __x86_cpu_dev_start = .;
+@@ -292,19 +368,12 @@ SECTIONS
+ __iommu_table_end = .;
+ }
+ . = ALIGN(8);
+- /*
+- * .exit.text is discard at runtime, not link time, to deal with
+- * references from .altinstructions and .eh_frame
+- */
+- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+- EXIT_TEXT
+- }
+
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
+ EXIT_DATA
+ }
+
+-#if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
++#ifndef CONFIG_SMP
+ PERCPU(THREAD_SIZE)
+ #endif
+
+@@ -323,16 +392,10 @@ SECTIONS
+ .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+ __smp_locks = .;
+ *(.smp_locks)
+- . = ALIGN(PAGE_SIZE);
+ __smp_locks_end = .;
++ . = ALIGN(PAGE_SIZE);
+ }
+
+-#ifdef CONFIG_X86_64
+- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
+- NOSAVE_DATA
+- }
+-#endif
+-
+ /* BSS */
+ . = ALIGN(PAGE_SIZE);
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+@@ -348,6 +411,7 @@ SECTIONS
+ __brk_base = .;
+ . += 64 * 1024; /* 64k alignment slop space */
+ *(.brk_reservation) /* areas brk users have reserved */
++ . = ALIGN(HPAGE_SIZE);
+ __brk_limit = .;
+ }
+
+@@ -374,13 +438,12 @@ SECTIONS
+ * for the boot processor.
+ */
+ #define INIT_PER_CPU(x) init_per_cpu__##x = x + __per_cpu_load
+-INIT_PER_CPU(gdt_page);
+ INIT_PER_CPU(irq_stack_union);
+
+ /*
+ * Build-time check on the image size:
+ */
+-. = ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
++. = ASSERT((_end - _text - __KERNEL_TEXT_OFFSET <= KERNEL_IMAGE_SIZE),
+ "kernel image bigger than KERNEL_IMAGE_SIZE");
+
+ #ifdef CONFIG_SMP
+diff -urNp linux-2.6.38.7/arch/x86/kernel/vsyscall_64.c linux-2.6.38.7/arch/x86/kernel/vsyscall_64.c
+--- linux-2.6.38.7/arch/x86/kernel/vsyscall_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/vsyscall_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -80,6 +80,7 @@ void update_vsyscall(struct timespec *wa
+
+ write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+ /* copy vsyscall data */
++ strlcpy(vsyscall_gtod_data.clock.name, clock->name, sizeof vsyscall_gtod_data.clock.name);
+ vsyscall_gtod_data.clock.vread = clock->vread;
+ vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
+ vsyscall_gtod_data.clock.mask = clock->mask;
+@@ -208,7 +209,7 @@ vgetcpu(unsigned *cpu, unsigned *node, s
+ We do this here because otherwise user space would do it on
+ its own in a likely inferior way (no access to jiffies).
+ If you don't like it pass NULL. */
+- if (tcache && tcache->blob[0] == (j = __jiffies)) {
++ if (tcache && tcache->blob[0] == (j = jiffies)) {
+ p = tcache->blob[1];
+ } else if (__vgetcpu_mode == VGETCPU_RDTSCP) {
+ /* Load per CPU data from RDTSCP */
+diff -urNp linux-2.6.38.7/arch/x86/kernel/x8664_ksyms_64.c linux-2.6.38.7/arch/x86/kernel/x8664_ksyms_64.c
+--- linux-2.6.38.7/arch/x86/kernel/x8664_ksyms_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/x8664_ksyms_64.c 2011-04-28 19:34:14.000000000 -0400
+@@ -29,8 +29,6 @@ EXPORT_SYMBOL(__put_user_8);
+ EXPORT_SYMBOL(copy_user_generic_string);
+ EXPORT_SYMBOL(copy_user_generic_unrolled);
+ EXPORT_SYMBOL(__copy_user_nocache);
+-EXPORT_SYMBOL(_copy_from_user);
+-EXPORT_SYMBOL(_copy_to_user);
+
+ EXPORT_SYMBOL(copy_page);
+ EXPORT_SYMBOL(clear_page);
+diff -urNp linux-2.6.38.7/arch/x86/kernel/xsave.c linux-2.6.38.7/arch/x86/kernel/xsave.c
+--- linux-2.6.38.7/arch/x86/kernel/xsave.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kernel/xsave.c 2011-04-28 19:34:14.000000000 -0400
+@@ -130,7 +130,7 @@ int check_for_xstate(struct i387_fxsave_
+ fx_sw_user->xstate_size > fx_sw_user->extended_size)
+ return -EINVAL;
+
+- err = __get_user(magic2, (__u32 *) (((void *)fpstate) +
++ err = __get_user(magic2, (__u32 __user *) (((void __user *)fpstate) +
+ fx_sw_user->extended_size -
+ FP_XSTATE_MAGIC2_SIZE));
+ if (err)
+@@ -267,7 +267,7 @@ fx_only:
+ * the other extended state.
+ */
+ xrstor_state(init_xstate_buf, pcntxt_mask & ~XSTATE_FPSSE);
+- return fxrstor_checking((__force struct i387_fxsave_struct *)buf);
++ return fxrstor_checking((struct i387_fxsave_struct __user *)buf);
+ }
+
+ /*
+@@ -299,7 +299,7 @@ int restore_i387_xstate(void __user *buf
+ if (use_xsave())
+ err = restore_user_xstate(buf);
+ else
+- err = fxrstor_checking((__force struct i387_fxsave_struct *)
++ err = fxrstor_checking((struct i387_fxsave_struct __user *)
+ buf);
+ if (unlikely(err)) {
+ /*
+diff -urNp linux-2.6.38.7/arch/x86/kvm/emulate.c linux-2.6.38.7/arch/x86/kvm/emulate.c
+--- linux-2.6.38.7/arch/x86/kvm/emulate.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kvm/emulate.c 2011-04-28 19:34:14.000000000 -0400
+@@ -88,7 +88,7 @@
+ #define Src2ImmByte (2<<29)
+ #define Src2One (3<<29)
+ #define Src2Imm (4<<29)
+-#define Src2Mask (7<<29)
++#define Src2Mask (7U<<29)
+
+ #define X2(x...) x, x
+ #define X3(x...) X2(x), x
+@@ -189,6 +189,7 @@ struct group_dual {
+
+ #define ____emulate_2op(_op, _src, _dst, _eflags, _x, _y, _suffix, _dsttype) \
+ do { \
++ unsigned long _tmp; \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0", "4", "2") \
+ _op _suffix " %"_x"3,%1; " \
+@@ -202,8 +203,6 @@ struct group_dual {
+ /* Raw emulation: instruction has two explicit operands. */
+ #define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \
+ do { \
+- unsigned long _tmp; \
+- \
+ switch ((_dst).bytes) { \
+ case 2: \
+ ____emulate_2op(_op,_src,_dst,_eflags,_wx,_wy,"w",u16);\
+@@ -219,7 +218,6 @@ struct group_dual {
+
+ #define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
+ do { \
+- unsigned long _tmp; \
+ switch ((_dst).bytes) { \
+ case 1: \
+ ____emulate_2op(_op,_src,_dst,_eflags,_bx,_by,"b",u8); \
+diff -urNp linux-2.6.38.7/arch/x86/kvm/lapic.c linux-2.6.38.7/arch/x86/kvm/lapic.c
+--- linux-2.6.38.7/arch/x86/kvm/lapic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kvm/lapic.c 2011-04-28 19:34:14.000000000 -0400
+@@ -53,7 +53,7 @@
+ #define APIC_BUS_CYCLE_NS 1
+
+ /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */
+-#define apic_debug(fmt, arg...)
++#define apic_debug(fmt, arg...) do {} while (0)
+
+ #define APIC_LVT_NUM 6
+ /* 14 is the version for Xeon and Pentium 8.4.8*/
+diff -urNp linux-2.6.38.7/arch/x86/kvm/mmu.c linux-2.6.38.7/arch/x86/kvm/mmu.c
+--- linux-2.6.38.7/arch/x86/kvm/mmu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kvm/mmu.c 2011-04-28 19:57:25.000000000 -0400
+@@ -3271,7 +3271,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *
+
+ pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
+
+- invlpg_counter = atomic_read(&vcpu->kvm->arch.invlpg_counter);
++ invlpg_counter = atomic_read_unchecked(&vcpu->kvm->arch.invlpg_counter);
+
+ /*
+ * Assume that the pte write on a page table of the same type
+@@ -3305,7 +3305,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *
+
+ mmu_guess_page_from_pte_write(vcpu, gpa, gentry);
+ spin_lock(&vcpu->kvm->mmu_lock);
+- if (atomic_read(&vcpu->kvm->arch.invlpg_counter) != invlpg_counter)
++ if (atomic_read_unchecked(&vcpu->kvm->arch.invlpg_counter) != invlpg_counter)
+ gentry = 0;
+ kvm_mmu_access_page(vcpu, gfn);
+ kvm_mmu_free_some_pages(vcpu);
+diff -urNp linux-2.6.38.7/arch/x86/kvm/paging_tmpl.h linux-2.6.38.7/arch/x86/kvm/paging_tmpl.h
+--- linux-2.6.38.7/arch/x86/kvm/paging_tmpl.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kvm/paging_tmpl.h 2011-05-16 21:47:08.000000000 -0400
+@@ -554,6 +554,8 @@ static int FNAME(page_fault)(struct kvm_
+ unsigned long mmu_seq;
+ bool map_writable;
+
++ pax_track_stack();
++
+ pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
+
+ r = mmu_topup_memory_caches(vcpu);
+@@ -674,7 +676,7 @@ static void FNAME(invlpg)(struct kvm_vcp
+ if (need_flush)
+ kvm_flush_remote_tlbs(vcpu->kvm);
+
+- atomic_inc(&vcpu->kvm->arch.invlpg_counter);
++ atomic_inc_unchecked(&vcpu->kvm->arch.invlpg_counter);
+
+ spin_unlock(&vcpu->kvm->mmu_lock);
+
+diff -urNp linux-2.6.38.7/arch/x86/kvm/svm.c linux-2.6.38.7/arch/x86/kvm/svm.c
+--- linux-2.6.38.7/arch/x86/kvm/svm.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kvm/svm.c 2011-05-10 22:08:57.000000000 -0400
+@@ -3276,7 +3276,11 @@ static void reload_tss(struct kvm_vcpu *
+ int cpu = raw_smp_processor_id();
+
+ struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
++
++ pax_open_kernel();
+ sd->tss_desc->type = 9; /* available 32/64-bit TSS */
++ pax_close_kernel();
++
+ load_TR_desc();
+ }
+
+@@ -3651,6 +3655,10 @@ static void svm_vcpu_run(struct kvm_vcpu
+ loadsegment(fs, svm->host.fs);
+ #endif
+
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ __set_fs(current_thread_info()->addr_limit);
++#endif
++
+ reload_tss(vcpu);
+
+ local_irq_disable();
+@@ -3858,7 +3866,7 @@ static void svm_fpu_deactivate(struct kv
+ update_cr0_intercept(svm);
+ }
+
+-static struct kvm_x86_ops svm_x86_ops = {
++static const struct kvm_x86_ops svm_x86_ops = {
+ .cpu_has_kvm_support = has_svm,
+ .disabled_by_bios = is_disabled,
+ .hardware_setup = svm_hardware_setup,
+diff -urNp linux-2.6.38.7/arch/x86/kvm/vmx.c linux-2.6.38.7/arch/x86/kvm/vmx.c
+--- linux-2.6.38.7/arch/x86/kvm/vmx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kvm/vmx.c 2011-04-28 19:57:25.000000000 -0400
+@@ -725,7 +725,11 @@ static void reload_tss(void)
+ struct desc_struct *descs;
+
+ descs = (void *)gdt->address;
++
++ pax_open_kernel();
+ descs[GDT_ENTRY_TSS].type = 9; /* available TSS */
++ pax_close_kernel();
++
+ load_TR_desc();
+ }
+
+@@ -1642,8 +1646,11 @@ static __init int hardware_setup(void)
+ if (!cpu_has_vmx_flexpriority())
+ flexpriority_enabled = 0;
+
+- if (!cpu_has_vmx_tpr_shadow())
+- kvm_x86_ops->update_cr8_intercept = NULL;
++ if (!cpu_has_vmx_tpr_shadow()) {
++ pax_open_kernel();
++ *(void **)&kvm_x86_ops->update_cr8_intercept = NULL;
++ pax_close_kernel();
++ }
+
+ if (enable_ept && !cpu_has_vmx_ept_2m_page())
+ kvm_disable_largepages();
+@@ -2640,7 +2647,7 @@ static int vmx_vcpu_setup(struct vcpu_vm
+ vmcs_writel(HOST_IDTR_BASE, dt.address); /* 22.2.4 */
+
+ asm("mov $.Lkvm_vmx_return, %0" : "=r"(kvm_vmx_return));
+- vmcs_writel(HOST_RIP, kvm_vmx_return); /* 22.2.5 */
++ vmcs_writel(HOST_RIP, ktla_ktva(kvm_vmx_return)); /* 22.2.5 */
+ vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
+ vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host));
+@@ -4031,6 +4038,12 @@ static void vmx_vcpu_run(struct kvm_vcpu
+ "jmp .Lkvm_vmx_return \n\t"
+ ".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"
+ ".Lkvm_vmx_return: "
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ "ljmp %[cs],$.Lkvm_vmx_return2\n\t"
++ ".Lkvm_vmx_return2: "
++#endif
++
+ /* Save guest registers, load host registers, keep flags */
+ "xchg %0, (%%"R"sp) \n\t"
+ "mov %%"R"ax, %c[rax](%0) \n\t"
+@@ -4077,6 +4090,11 @@ static void vmx_vcpu_run(struct kvm_vcpu
+ [r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])),
+ #endif
+ [cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2))
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ ,[cs]"i"(__KERNEL_CS)
++#endif
++
+ : "cc", "memory"
+ , R"ax", R"bx", R"di", R"si"
+ #ifdef CONFIG_X86_64
+@@ -4091,7 +4109,16 @@ static void vmx_vcpu_run(struct kvm_vcpu
+
+ vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+
+- asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
++ asm("mov %0, %%ds; mov %0, %%es; mov %0, %%ss" : : "r"(__KERNEL_DS));
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ loadsegment(fs, __KERNEL_PERCPU);
++#endif
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ __set_fs(current_thread_info()->addr_limit);
++#endif
++
+ vmx->launched = 1;
+
+ vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
+@@ -4326,7 +4353,7 @@ static void vmx_set_supported_cpuid(u32
+ {
+ }
+
+-static struct kvm_x86_ops vmx_x86_ops = {
++static const struct kvm_x86_ops vmx_x86_ops = {
+ .cpu_has_kvm_support = cpu_has_kvm_support,
+ .disabled_by_bios = vmx_disabled_by_bios,
+ .hardware_setup = hardware_setup,
+diff -urNp linux-2.6.38.7/arch/x86/kvm/x86.c linux-2.6.38.7/arch/x86/kvm/x86.c
+--- linux-2.6.38.7/arch/x86/kvm/x86.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/kvm/x86.c 2011-04-28 19:34:14.000000000 -0400
+@@ -93,7 +93,7 @@ static void update_cr8_intercept(struct
+ static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
+ struct kvm_cpuid_entry2 __user *entries);
+
+-struct kvm_x86_ops *kvm_x86_ops;
++const struct kvm_x86_ops *kvm_x86_ops;
+ EXPORT_SYMBOL_GPL(kvm_x86_ops);
+
+ int ignore_msrs = 0;
+@@ -2023,6 +2023,8 @@ long kvm_arch_dev_ioctl(struct file *fil
+ if (n < msr_list.nmsrs)
+ goto out;
+ r = -EFAULT;
++ if (num_msrs_to_save > ARRAY_SIZE(msrs_to_save))
++ goto out;
+ if (copy_to_user(user_msr_list->indices, &msrs_to_save,
+ num_msrs_to_save * sizeof(u32)))
+ goto out;
+@@ -2190,15 +2192,20 @@ static int kvm_vcpu_ioctl_set_cpuid2(str
+ struct kvm_cpuid2 *cpuid,
+ struct kvm_cpuid_entry2 __user *entries)
+ {
+- int r;
++ int r, i;
+
+ r = -E2BIG;
+ if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
+ goto out;
+ r = -EFAULT;
+- if (copy_from_user(&vcpu->arch.cpuid_entries, entries,
+- cpuid->nent * sizeof(struct kvm_cpuid_entry2)))
++ if (!access_ok(VERIFY_READ, entries, cpuid->nent * sizeof(struct kvm_cpuid_entry2)))
+ goto out;
++ for (i = 0; i < cpuid->nent; ++i) {
++ struct kvm_cpuid_entry2 cpuid_entry;
++ if (__copy_from_user(&cpuid_entry, entries + i, sizeof(cpuid_entry)))
++ goto out;
++ vcpu->arch.cpuid_entries[i] = cpuid_entry;
++ }
+ vcpu->arch.cpuid_nent = cpuid->nent;
+ kvm_apic_set_version(vcpu);
+ kvm_x86_ops->cpuid_update(vcpu);
+@@ -2213,15 +2220,19 @@ static int kvm_vcpu_ioctl_get_cpuid2(str
+ struct kvm_cpuid2 *cpuid,
+ struct kvm_cpuid_entry2 __user *entries)
+ {
+- int r;
++ int r, i;
+
+ r = -E2BIG;
+ if (cpuid->nent < vcpu->arch.cpuid_nent)
+ goto out;
+ r = -EFAULT;
+- if (copy_to_user(entries, &vcpu->arch.cpuid_entries,
+- vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2)))
++ if (!access_ok(VERIFY_WRITE, entries, vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2)))
+ goto out;
++ for (i = 0; i < vcpu->arch.cpuid_nent; ++i) {
++ struct kvm_cpuid_entry2 cpuid_entry = vcpu->arch.cpuid_entries[i];
++ if (__copy_to_user(entries + i, &cpuid_entry, sizeof(cpuid_entry)))
++ goto out;
++ }
+ return 0;
+
+ out:
+@@ -2499,7 +2510,7 @@ static int kvm_vcpu_ioctl_set_lapic(stru
+ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
+ struct kvm_interrupt *irq)
+ {
+- if (irq->irq < 0 || irq->irq >= 256)
++ if (irq->irq >= 256)
+ return -EINVAL;
+ if (irqchip_in_kernel(vcpu->kvm))
+ return -ENXIO;
+@@ -4687,10 +4698,10 @@ void kvm_after_handle_nmi(struct kvm_vcp
+ }
+ EXPORT_SYMBOL_GPL(kvm_after_handle_nmi);
+
+-int kvm_arch_init(void *opaque)
++int kvm_arch_init(const void *opaque)
+ {
+ int r;
+- struct kvm_x86_ops *ops = (struct kvm_x86_ops *)opaque;
++ const struct kvm_x86_ops *ops = (const struct kvm_x86_ops *)opaque;
+
+ if (kvm_x86_ops) {
+ printk(KERN_ERR "kvm: already loaded the other module\n");
+diff -urNp linux-2.6.38.7/arch/x86/lib/atomic64_32.c linux-2.6.38.7/arch/x86/lib/atomic64_32.c
+--- linux-2.6.38.7/arch/x86/lib/atomic64_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/atomic64_32.c 2011-05-02 19:07:09.000000000 -0400
+@@ -8,18 +8,30 @@
+
+ long long atomic64_read_cx8(long long, const atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_read_cx8);
++long long atomic64_read_unchecked_cx8(long long, const atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_read_unchecked_cx8);
+ long long atomic64_set_cx8(long long, const atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_set_cx8);
++long long atomic64_set_unchecked_cx8(long long, const atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_set_unchecked_cx8);
+ long long atomic64_xchg_cx8(long long, unsigned high);
+ EXPORT_SYMBOL(atomic64_xchg_cx8);
+ long long atomic64_add_return_cx8(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_add_return_cx8);
++long long atomic64_add_return_unchecked_cx8(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_add_return_unchecked_cx8);
+ long long atomic64_sub_return_cx8(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_sub_return_cx8);
++long long atomic64_sub_return_unchecked_cx8(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_sub_return_unchecked_cx8);
+ long long atomic64_inc_return_cx8(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_inc_return_cx8);
++long long atomic64_inc_return_unchecked_cx8(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_inc_return_unchecked_cx8);
+ long long atomic64_dec_return_cx8(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_dec_return_cx8);
++long long atomic64_dec_return_unchecked_cx8(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_dec_return_unchecked_cx8);
+ long long atomic64_dec_if_positive_cx8(atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_dec_if_positive_cx8);
+ int atomic64_inc_not_zero_cx8(atomic64_t *v);
+@@ -30,26 +42,46 @@ EXPORT_SYMBOL(atomic64_add_unless_cx8);
+ #ifndef CONFIG_X86_CMPXCHG64
+ long long atomic64_read_386(long long, const atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_read_386);
++long long atomic64_read_unchecked_386(long long, const atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_read_unchecked_386);
+ long long atomic64_set_386(long long, const atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_set_386);
++long long atomic64_set_unchecked_386(long long, const atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_set_unchecked_386);
+ long long atomic64_xchg_386(long long, unsigned high);
+ EXPORT_SYMBOL(atomic64_xchg_386);
+ long long atomic64_add_return_386(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_add_return_386);
++long long atomic64_add_return_unchecked_386(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_add_return_unchecked_386);
+ long long atomic64_sub_return_386(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_sub_return_386);
++long long atomic64_sub_return_unchecked_386(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_sub_return_unchecked_386);
+ long long atomic64_inc_return_386(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_inc_return_386);
++long long atomic64_inc_return_unchecked_386(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_inc_return_unchecked_386);
+ long long atomic64_dec_return_386(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_dec_return_386);
++long long atomic64_dec_return_unchecked_386(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_dec_return_unchecked_386);
+ long long atomic64_add_386(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_add_386);
++long long atomic64_add_unchecked_386(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_add_unchecked_386);
+ long long atomic64_sub_386(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_sub_386);
++long long atomic64_sub_unchecked_386(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_sub_unchecked_386);
+ long long atomic64_inc_386(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_inc_386);
++long long atomic64_inc_unchecked_386(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_inc_unchecked_386);
+ long long atomic64_dec_386(long long a, atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_dec_386);
++long long atomic64_dec_unchecked_386(long long a, atomic64_unchecked_t *v);
++EXPORT_SYMBOL(atomic64_dec_unchecked_386);
+ long long atomic64_dec_if_positive_386(atomic64_t *v);
+ EXPORT_SYMBOL(atomic64_dec_if_positive_386);
+ int atomic64_inc_not_zero_386(atomic64_t *v);
+diff -urNp linux-2.6.38.7/arch/x86/lib/atomic64_386_32.S linux-2.6.38.7/arch/x86/lib/atomic64_386_32.S
+--- linux-2.6.38.7/arch/x86/lib/atomic64_386_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/atomic64_386_32.S 2011-05-02 19:07:09.000000000 -0400
+@@ -50,6 +50,10 @@ BEGIN(read)
+ movl (v), %eax
+ movl 4(v), %edx
+ RET_ENDP
++BEGIN(read_unchecked)
++ movl (v), %eax
++ movl 4(v), %edx
++RET_ENDP
+ #undef v
+
+ #define v %esi
+@@ -57,6 +61,10 @@ BEGIN(set)
+ movl %ebx, (v)
+ movl %ecx, 4(v)
+ RET_ENDP
++BEGIN(set_unchecked)
++ movl %ebx, (v)
++ movl %ecx, 4(v)
++RET_ENDP
+ #undef v
+
+ #define v %esi
+@@ -72,6 +80,20 @@ RET_ENDP
+ BEGIN(add)
+ addl %eax, (v)
+ adcl %edx, 4(v)
++
++#ifdef CONFIG_PAX_REFCOUNT
++ jno 0f
++ subl %eax, (v)
++ sbbl %edx, 4(v)
++ int $4
++0:
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++RET_ENDP
++BEGIN(add_unchecked)
++ addl %eax, (v)
++ adcl %edx, 4(v)
+ RET_ENDP
+ #undef v
+
+@@ -79,6 +101,24 @@ RET_ENDP
+ BEGIN(add_return)
+ addl (v), %eax
+ adcl 4(v), %edx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 2f)
++#endif
++
++ movl %eax, (v)
++ movl %edx, 4(v)
++
++#ifdef CONFIG_PAX_REFCOUNT
++2:
++#endif
++
++RET_ENDP
++BEGIN(add_return_unchecked)
++ addl (v), %eax
++ adcl 4(v), %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+ RET_ENDP
+@@ -88,6 +128,20 @@ RET_ENDP
+ BEGIN(sub)
+ subl %eax, (v)
+ sbbl %edx, 4(v)
++
++#ifdef CONFIG_PAX_REFCOUNT
++ jno 0f
++ addl %eax, (v)
++ adcl %edx, 4(v)
++ int $4
++0:
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++RET_ENDP
++BEGIN(sub_unchecked)
++ subl %eax, (v)
++ sbbl %edx, 4(v)
+ RET_ENDP
+ #undef v
+
+@@ -98,6 +152,27 @@ BEGIN(sub_return)
+ sbbl $0, %edx
+ addl (v), %eax
+ adcl 4(v), %edx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 2f)
++#endif
++
++ movl %eax, (v)
++ movl %edx, 4(v)
++
++#ifdef CONFIG_PAX_REFCOUNT
++2:
++#endif
++
++RET_ENDP
++BEGIN(sub_return_unchecked)
++ negl %edx
++ negl %eax
++ sbbl $0, %edx
++ addl (v), %eax
++ adcl 4(v), %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+ RET_ENDP
+@@ -107,6 +182,20 @@ RET_ENDP
+ BEGIN(inc)
+ addl $1, (v)
+ adcl $0, 4(v)
++
++#ifdef CONFIG_PAX_REFCOUNT
++ jno 0f
++ subl $1, (v)
++ sbbl $0, 4(v)
++ int $4
++0:
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++RET_ENDP
++BEGIN(inc_unchecked)
++ addl $1, (v)
++ adcl $0, 4(v)
+ RET_ENDP
+ #undef v
+
+@@ -116,6 +205,26 @@ BEGIN(inc_return)
+ movl 4(v), %edx
+ addl $1, %eax
+ adcl $0, %edx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 2f)
++#endif
++
++ movl %eax, (v)
++ movl %edx, 4(v)
++
++#ifdef CONFIG_PAX_REFCOUNT
++2:
++#endif
++
++RET_ENDP
++BEGIN(inc_return_unchecked)
++ movl (v), %eax
++ movl 4(v), %edx
++ addl $1, %eax
++ adcl $0, %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+ RET_ENDP
+@@ -125,6 +234,20 @@ RET_ENDP
+ BEGIN(dec)
+ subl $1, (v)
+ sbbl $0, 4(v)
++
++#ifdef CONFIG_PAX_REFCOUNT
++ jno 0f
++ addl $1, (v)
++ adcl $0, 4(v)
++ int $4
++0:
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++RET_ENDP
++BEGIN(dec_unchecked)
++ subl $1, (v)
++ sbbl $0, 4(v)
+ RET_ENDP
+ #undef v
+
+@@ -134,6 +257,26 @@ BEGIN(dec_return)
+ movl 4(v), %edx
+ subl $1, %eax
+ sbbl $0, %edx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 2f)
++#endif
++
++ movl %eax, (v)
++ movl %edx, 4(v)
++
++#ifdef CONFIG_PAX_REFCOUNT
++2:
++#endif
++
++RET_ENDP
++BEGIN(dec_return_unchecked)
++ movl (v), %eax
++ movl 4(v), %edx
++ subl $1, %eax
++ sbbl $0, %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+ RET_ENDP
+@@ -145,6 +288,13 @@ BEGIN(add_unless)
+ adcl %edx, %edi
+ addl (v), %eax
+ adcl 4(v), %edx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 2f)
++#endif
++
+ cmpl %eax, %esi
+ je 3f
+ 1:
+@@ -170,6 +320,13 @@ BEGIN(inc_not_zero)
+ 1:
+ addl $1, %eax
+ adcl $0, %edx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 2f)
++#endif
++
+ movl %eax, (v)
+ movl %edx, 4(v)
+ movl $1, %eax
+@@ -188,6 +345,13 @@ BEGIN(dec_if_positive)
+ movl 4(v), %edx
+ subl $1, %eax
+ sbbl $0, %edx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 1f)
++#endif
++
+ js 1f
+ movl %eax, (v)
+ movl %edx, 4(v)
+diff -urNp linux-2.6.38.7/arch/x86/lib/atomic64_cx8_32.S linux-2.6.38.7/arch/x86/lib/atomic64_cx8_32.S
+--- linux-2.6.38.7/arch/x86/lib/atomic64_cx8_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/atomic64_cx8_32.S 2011-05-02 19:07:09.000000000 -0400
+@@ -41,6 +41,14 @@ ENTRY(atomic64_read_cx8)
+ CFI_ENDPROC
+ ENDPROC(atomic64_read_cx8)
+
++ENTRY(atomic64_read_unchecked_cx8)
++ CFI_STARTPROC
++
++ read64 %ecx
++ ret
++ CFI_ENDPROC
++ENDPROC(atomic64_read_unchecked_cx8)
++
+ ENTRY(atomic64_set_cx8)
+ CFI_STARTPROC
+
+@@ -54,6 +62,19 @@ ENTRY(atomic64_set_cx8)
+ CFI_ENDPROC
+ ENDPROC(atomic64_set_cx8)
+
++ENTRY(atomic64_set_unchecked_cx8)
++ CFI_STARTPROC
++
++1:
++/* we don't need LOCK_PREFIX since aligned 64-bit writes
++ * are atomic on 586 and newer */
++ cmpxchg8b (%esi)
++ jne 1b
++
++ ret
++ CFI_ENDPROC
++ENDPROC(atomic64_set_unchecked_cx8)
++
+ ENTRY(atomic64_xchg_cx8)
+ CFI_STARTPROC
+
+@@ -68,8 +89,8 @@ ENTRY(atomic64_xchg_cx8)
+ CFI_ENDPROC
+ ENDPROC(atomic64_xchg_cx8)
+
+-.macro addsub_return func ins insc
+-ENTRY(atomic64_\func\()_return_cx8)
++.macro addsub_return func ins insc unchecked=""
++ENTRY(atomic64_\func\()_return\unchecked\()_cx8)
+ CFI_STARTPROC
+ SAVE ebp
+ SAVE ebx
+@@ -86,27 +107,43 @@ ENTRY(atomic64_\func\()_return_cx8)
+ movl %edx, %ecx
+ \ins\()l %esi, %ebx
+ \insc\()l %edi, %ecx
++
++.ifb \unchecked
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++2:
++ _ASM_EXTABLE(2b, 3f)
++#endif
++.endif
++
+ LOCK_PREFIX
+ cmpxchg8b (%ebp)
+ jne 1b
+-
+-10:
+ movl %ebx, %eax
+ movl %ecx, %edx
++
++.ifb \unchecked
++#ifdef CONFIG_PAX_REFCOUNT
++3:
++#endif
++.endif
++
+ RESTORE edi
+ RESTORE esi
+ RESTORE ebx
+ RESTORE ebp
+ ret
+ CFI_ENDPROC
+-ENDPROC(atomic64_\func\()_return_cx8)
++ENDPROC(atomic64_\func\()_return\unchecked\()_cx8)
+ .endm
+
+ addsub_return add add adc
+ addsub_return sub sub sbb
++addsub_return add add adc _unchecked
++addsub_return sub sub sbb _unchecked
+
+-.macro incdec_return func ins insc
+-ENTRY(atomic64_\func\()_return_cx8)
++.macro incdec_return func ins insc unchecked
++ENTRY(atomic64_\func\()_return\unchecked\()_cx8)
+ CFI_STARTPROC
+ SAVE ebx
+
+@@ -116,21 +153,38 @@ ENTRY(atomic64_\func\()_return_cx8)
+ movl %edx, %ecx
+ \ins\()l $1, %ebx
+ \insc\()l $0, %ecx
++
++.ifb \unchecked
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++2:
++ _ASM_EXTABLE(2b, 3f)
++#endif
++.endif
++
+ LOCK_PREFIX
+ cmpxchg8b (%esi)
+ jne 1b
+
+-10:
+ movl %ebx, %eax
+ movl %ecx, %edx
++
++.ifb \unchecked
++#ifdef CONFIG_PAX_REFCOUNT
++3:
++#endif
++.endif
++
+ RESTORE ebx
+ ret
+ CFI_ENDPROC
+-ENDPROC(atomic64_\func\()_return_cx8)
++ENDPROC(atomic64_\func\()_return\unchecked\()_cx8)
+ .endm
+
+ incdec_return inc add adc
+ incdec_return dec sub sbb
++incdec_return inc add adc _unchecked
++incdec_return dec sub sbb _unchecked
+
+ ENTRY(atomic64_dec_if_positive_cx8)
+ CFI_STARTPROC
+@@ -142,6 +196,13 @@ ENTRY(atomic64_dec_if_positive_cx8)
+ movl %edx, %ecx
+ subl $1, %ebx
+ sbb $0, %ecx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 2f)
++#endif
++
+ js 2f
+ LOCK_PREFIX
+ cmpxchg8b (%esi)
+@@ -176,6 +237,13 @@ ENTRY(atomic64_add_unless_cx8)
+ movl %edx, %ecx
+ addl %esi, %ebx
+ adcl %edi, %ecx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 3f)
++#endif
++
+ LOCK_PREFIX
+ cmpxchg8b (%ebp)
+ jne 1b
+@@ -208,6 +276,13 @@ ENTRY(atomic64_inc_not_zero_cx8)
+ movl %edx, %ecx
+ addl $1, %ebx
+ adcl $0, %ecx
++
++#ifdef CONFIG_PAX_REFCOUNT
++ into
++1234:
++ _ASM_EXTABLE(1234b, 3f)
++#endif
++
+ LOCK_PREFIX
+ cmpxchg8b (%esi)
+ jne 1b
+diff -urNp linux-2.6.38.7/arch/x86/lib/checksum_32.S linux-2.6.38.7/arch/x86/lib/checksum_32.S
+--- linux-2.6.38.7/arch/x86/lib/checksum_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/checksum_32.S 2011-04-28 19:34:14.000000000 -0400
+@@ -28,7 +28,8 @@
+ #include <linux/linkage.h>
+ #include <asm/dwarf2.h>
+ #include <asm/errno.h>
+-
++#include <asm/segment.h>
++
+ /*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+@@ -304,9 +305,28 @@ unsigned int csum_partial_copy_generic (
+
+ #define ARGBASE 16
+ #define FP 12
+-
+-ENTRY(csum_partial_copy_generic)
++
++ENTRY(csum_partial_copy_generic_to_user)
+ CFI_STARTPROC
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pushl %gs
++ CFI_ADJUST_CFA_OFFSET 4
++ popl %es
++ CFI_ADJUST_CFA_OFFSET -4
++ jmp csum_partial_copy_generic
++#endif
++
++ENTRY(csum_partial_copy_generic_from_user)
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pushl %gs
++ CFI_ADJUST_CFA_OFFSET 4
++ popl %ds
++ CFI_ADJUST_CFA_OFFSET -4
++#endif
++
++ENTRY(csum_partial_copy_generic)
+ subl $4,%esp
+ CFI_ADJUST_CFA_OFFSET 4
+ pushl %edi
+@@ -331,7 +351,7 @@ ENTRY(csum_partial_copy_generic)
+ jmp 4f
+ SRC(1: movw (%esi), %bx )
+ addl $2, %esi
+-DST( movw %bx, (%edi) )
++DST( movw %bx, %es:(%edi) )
+ addl $2, %edi
+ addw %bx, %ax
+ adcl $0, %eax
+@@ -343,30 +363,30 @@ DST( movw %bx, (%edi) )
+ SRC(1: movl (%esi), %ebx )
+ SRC( movl 4(%esi), %edx )
+ adcl %ebx, %eax
+-DST( movl %ebx, (%edi) )
++DST( movl %ebx, %es:(%edi) )
+ adcl %edx, %eax
+-DST( movl %edx, 4(%edi) )
++DST( movl %edx, %es:4(%edi) )
+
+ SRC( movl 8(%esi), %ebx )
+ SRC( movl 12(%esi), %edx )
+ adcl %ebx, %eax
+-DST( movl %ebx, 8(%edi) )
++DST( movl %ebx, %es:8(%edi) )
+ adcl %edx, %eax
+-DST( movl %edx, 12(%edi) )
++DST( movl %edx, %es:12(%edi) )
+
+ SRC( movl 16(%esi), %ebx )
+ SRC( movl 20(%esi), %edx )
+ adcl %ebx, %eax
+-DST( movl %ebx, 16(%edi) )
++DST( movl %ebx, %es:16(%edi) )
+ adcl %edx, %eax
+-DST( movl %edx, 20(%edi) )
++DST( movl %edx, %es:20(%edi) )
+
+ SRC( movl 24(%esi), %ebx )
+ SRC( movl 28(%esi), %edx )
+ adcl %ebx, %eax
+-DST( movl %ebx, 24(%edi) )
++DST( movl %ebx, %es:24(%edi) )
+ adcl %edx, %eax
+-DST( movl %edx, 28(%edi) )
++DST( movl %edx, %es:28(%edi) )
+
+ lea 32(%esi), %esi
+ lea 32(%edi), %edi
+@@ -380,7 +400,7 @@ DST( movl %edx, 28(%edi) )
+ shrl $2, %edx # This clears CF
+ SRC(3: movl (%esi), %ebx )
+ adcl %ebx, %eax
+-DST( movl %ebx, (%edi) )
++DST( movl %ebx, %es:(%edi) )
+ lea 4(%esi), %esi
+ lea 4(%edi), %edi
+ dec %edx
+@@ -392,12 +412,12 @@ DST( movl %ebx, (%edi) )
+ jb 5f
+ SRC( movw (%esi), %cx )
+ leal 2(%esi), %esi
+-DST( movw %cx, (%edi) )
++DST( movw %cx, %es:(%edi) )
+ leal 2(%edi), %edi
+ je 6f
+ shll $16,%ecx
+ SRC(5: movb (%esi), %cl )
+-DST( movb %cl, (%edi) )
++DST( movb %cl, %es:(%edi) )
+ 6: addl %ecx, %eax
+ adcl $0, %eax
+ 7:
+@@ -408,7 +428,7 @@ DST( movb %cl, (%edi) )
+
+ 6001:
+ movl ARGBASE+20(%esp), %ebx # src_err_ptr
+- movl $-EFAULT, (%ebx)
++ movl $-EFAULT, %ss:(%ebx)
+
+ # zero the complete destination - computing the rest
+ # is too much work
+@@ -421,11 +441,19 @@ DST( movb %cl, (%edi) )
+
+ 6002:
+ movl ARGBASE+24(%esp), %ebx # dst_err_ptr
+- movl $-EFAULT,(%ebx)
++ movl $-EFAULT,%ss:(%ebx)
+ jmp 5000b
+
+ .previous
+
++ pushl %ss
++ CFI_ADJUST_CFA_OFFSET 4
++ popl %ds
++ CFI_ADJUST_CFA_OFFSET -4
++ pushl %ss
++ CFI_ADJUST_CFA_OFFSET 4
++ popl %es
++ CFI_ADJUST_CFA_OFFSET -4
+ popl %ebx
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE ebx
+@@ -439,26 +467,47 @@ DST( movb %cl, (%edi) )
+ CFI_ADJUST_CFA_OFFSET -4
+ ret
+ CFI_ENDPROC
+-ENDPROC(csum_partial_copy_generic)
++ENDPROC(csum_partial_copy_generic_to_user)
+
+ #else
+
+ /* Version for PentiumII/PPro */
+
+ #define ROUND1(x) \
++ nop; nop; nop; \
+ SRC(movl x(%esi), %ebx ) ; \
+ addl %ebx, %eax ; \
+- DST(movl %ebx, x(%edi) ) ;
++ DST(movl %ebx, %es:x(%edi)) ;
+
+ #define ROUND(x) \
++ nop; nop; nop; \
+ SRC(movl x(%esi), %ebx ) ; \
+ adcl %ebx, %eax ; \
+- DST(movl %ebx, x(%edi) ) ;
++ DST(movl %ebx, %es:x(%edi)) ;
+
+ #define ARGBASE 12
+-
+-ENTRY(csum_partial_copy_generic)
++
++ENTRY(csum_partial_copy_generic_to_user)
+ CFI_STARTPROC
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pushl %gs
++ CFI_ADJUST_CFA_OFFSET 4
++ popl %es
++ CFI_ADJUST_CFA_OFFSET -4
++ jmp csum_partial_copy_generic
++#endif
++
++ENTRY(csum_partial_copy_generic_from_user)
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pushl %gs
++ CFI_ADJUST_CFA_OFFSET 4
++ popl %ds
++ CFI_ADJUST_CFA_OFFSET -4
++#endif
++
++ENTRY(csum_partial_copy_generic)
+ pushl %ebx
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET ebx, 0
+@@ -482,7 +531,7 @@ ENTRY(csum_partial_copy_generic)
+ subl %ebx, %edi
+ lea -1(%esi),%edx
+ andl $-32,%edx
+- lea 3f(%ebx,%ebx), %ebx
++ lea 3f(%ebx,%ebx,2), %ebx
+ testl %esi, %esi
+ jmp *%ebx
+ 1: addl $64,%esi
+@@ -503,19 +552,19 @@ ENTRY(csum_partial_copy_generic)
+ jb 5f
+ SRC( movw (%esi), %dx )
+ leal 2(%esi), %esi
+-DST( movw %dx, (%edi) )
++DST( movw %dx, %es:(%edi) )
+ leal 2(%edi), %edi
+ je 6f
+ shll $16,%edx
+ 5:
+ SRC( movb (%esi), %dl )
+-DST( movb %dl, (%edi) )
++DST( movb %dl, %es:(%edi) )
+ 6: addl %edx, %eax
+ adcl $0, %eax
+ 7:
+ .section .fixup, "ax"
+ 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
+- movl $-EFAULT, (%ebx)
++ movl $-EFAULT, %ss:(%ebx)
+ # zero the complete destination (computing the rest is too much work)
+ movl ARGBASE+8(%esp),%edi # dst
+ movl ARGBASE+12(%esp),%ecx # len
+@@ -523,10 +572,21 @@ DST( movb %dl, (%edi) )
+ rep; stosb
+ jmp 7b
+ 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr
+- movl $-EFAULT, (%ebx)
++ movl $-EFAULT, %ss:(%ebx)
+ jmp 7b
+ .previous
+
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ pushl %ss
++ CFI_ADJUST_CFA_OFFSET 4
++ popl %ds
++ CFI_ADJUST_CFA_OFFSET -4
++ pushl %ss
++ CFI_ADJUST_CFA_OFFSET 4
++ popl %es
++ CFI_ADJUST_CFA_OFFSET -4
++#endif
++
+ popl %esi
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE esi
+@@ -538,7 +598,7 @@ DST( movb %dl, (%edi) )
+ CFI_RESTORE ebx
+ ret
+ CFI_ENDPROC
+-ENDPROC(csum_partial_copy_generic)
++ENDPROC(csum_partial_copy_generic_to_user)
+
+ #undef ROUND
+ #undef ROUND1
+diff -urNp linux-2.6.38.7/arch/x86/lib/clear_page_64.S linux-2.6.38.7/arch/x86/lib/clear_page_64.S
+--- linux-2.6.38.7/arch/x86/lib/clear_page_64.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/clear_page_64.S 2011-04-28 19:34:14.000000000 -0400
+@@ -43,7 +43,7 @@ ENDPROC(clear_page)
+
+ #include <asm/cpufeature.h>
+
+- .section .altinstr_replacement,"ax"
++ .section .altinstr_replacement,"a"
+ 1: .byte 0xeb /* jmp <disp8> */
+ .byte (clear_page_c - clear_page) - (2f - 1b) /* offset */
+ 2:
+diff -urNp linux-2.6.38.7/arch/x86/lib/copy_page_64.S linux-2.6.38.7/arch/x86/lib/copy_page_64.S
+--- linux-2.6.38.7/arch/x86/lib/copy_page_64.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/copy_page_64.S 2011-04-28 19:34:14.000000000 -0400
+@@ -104,7 +104,7 @@ ENDPROC(copy_page)
+
+ #include <asm/cpufeature.h>
+
+- .section .altinstr_replacement,"ax"
++ .section .altinstr_replacement,"a"
+ 1: .byte 0xeb /* jmp <disp8> */
+ .byte (copy_page_c - copy_page) - (2f - 1b) /* offset */
+ 2:
+diff -urNp linux-2.6.38.7/arch/x86/lib/copy_user_64.S linux-2.6.38.7/arch/x86/lib/copy_user_64.S
+--- linux-2.6.38.7/arch/x86/lib/copy_user_64.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/copy_user_64.S 2011-04-28 19:34:14.000000000 -0400
+@@ -15,13 +15,14 @@
+ #include <asm/asm-offsets.h>
+ #include <asm/thread_info.h>
+ #include <asm/cpufeature.h>
++#include <asm/pgtable.h>
+
+ .macro ALTERNATIVE_JUMP feature,orig,alt
+ 0:
+ .byte 0xe9 /* 32bit jump */
+ .long \orig-1f /* by default jump to orig */
+ 1:
+- .section .altinstr_replacement,"ax"
++ .section .altinstr_replacement,"a"
+ 2: .byte 0xe9 /* near jump with 32bit immediate */
+ .long \alt-1b /* offset */ /* or alternatively to alt */
+ .previous
+@@ -64,37 +65,13 @@
+ #endif
+ .endm
+
+-/* Standard copy_to_user with segment limit checking */
+-ENTRY(_copy_to_user)
+- CFI_STARTPROC
+- GET_THREAD_INFO(%rax)
+- movq %rdi,%rcx
+- addq %rdx,%rcx
+- jc bad_to_user
+- cmpq TI_addr_limit(%rax),%rcx
+- jae bad_to_user
+- ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+- CFI_ENDPROC
+-ENDPROC(_copy_to_user)
+-
+-/* Standard copy_from_user with segment limit checking */
+-ENTRY(_copy_from_user)
+- CFI_STARTPROC
+- GET_THREAD_INFO(%rax)
+- movq %rsi,%rcx
+- addq %rdx,%rcx
+- jc bad_from_user
+- cmpq TI_addr_limit(%rax),%rcx
+- jae bad_from_user
+- ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+- CFI_ENDPROC
+-ENDPROC(_copy_from_user)
+-
+ .section .fixup,"ax"
+ /* must zero dest */
+ ENTRY(bad_from_user)
+ bad_from_user:
+ CFI_STARTPROC
++ testl %edx,%edx
++ js bad_to_user
+ movl %edx,%ecx
+ xorl %eax,%eax
+ rep
+diff -urNp linux-2.6.38.7/arch/x86/lib/copy_user_nocache_64.S linux-2.6.38.7/arch/x86/lib/copy_user_nocache_64.S
+--- linux-2.6.38.7/arch/x86/lib/copy_user_nocache_64.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/copy_user_nocache_64.S 2011-04-28 19:34:14.000000000 -0400
+@@ -14,6 +14,7 @@
+ #include <asm/current.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/thread_info.h>
++#include <asm/pgtable.h>
+
+ .macro ALIGN_DESTINATION
+ #ifdef FIX_ALIGNMENT
+@@ -50,6 +51,15 @@
+ */
+ ENTRY(__copy_user_nocache)
+ CFI_STARTPROC
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ mov $PAX_USER_SHADOW_BASE,%rcx
++ cmp %rcx,%rsi
++ jae 1f
++ add %rcx,%rsi
++1:
++#endif
++
+ cmpl $8,%edx
+ jb 20f /* less then 8 bytes, go to byte copy loop */
+ ALIGN_DESTINATION
+diff -urNp linux-2.6.38.7/arch/x86/lib/csum-wrappers_64.c linux-2.6.38.7/arch/x86/lib/csum-wrappers_64.c
+--- linux-2.6.38.7/arch/x86/lib/csum-wrappers_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/csum-wrappers_64.c 2011-04-28 19:57:25.000000000 -0400
+@@ -52,6 +52,12 @@ csum_partial_copy_from_user(const void _
+ len -= 2;
+ }
+ }
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)src < PAX_USER_SHADOW_BASE)
++ src += PAX_USER_SHADOW_BASE;
++#endif
++
+ isum = csum_partial_copy_generic((__force const void *)src,
+ dst, len, isum, errp, NULL);
+ if (unlikely(*errp))
+@@ -105,6 +111,12 @@ csum_partial_copy_to_user(const void *sr
+ }
+
+ *errp = 0;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)dst < PAX_USER_SHADOW_BASE)
++ dst += PAX_USER_SHADOW_BASE;
++#endif
++
+ return csum_partial_copy_generic(src, (void __force *)dst,
+ len, isum, NULL, errp);
+ }
+diff -urNp linux-2.6.38.7/arch/x86/lib/getuser.S linux-2.6.38.7/arch/x86/lib/getuser.S
+--- linux-2.6.38.7/arch/x86/lib/getuser.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/getuser.S 2011-04-28 19:34:14.000000000 -0400
+@@ -33,14 +33,35 @@
+ #include <asm/asm-offsets.h>
+ #include <asm/thread_info.h>
+ #include <asm/asm.h>
++#include <asm/segment.h>
++#include <asm/pgtable.h>
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF)
++#define __copyuser_seg gs;
++#else
++#define __copyuser_seg
++#endif
+
+ .text
+ ENTRY(__get_user_1)
+ CFI_STARTPROC
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF)
+ GET_THREAD_INFO(%_ASM_DX)
+ cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
+ jae bad_get_user
+-1: movzb (%_ASM_AX),%edx
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ mov $PAX_USER_SHADOW_BASE,%_ASM_DX
++ cmp %_ASM_DX,%_ASM_AX
++ jae 1234f
++ add %_ASM_DX,%_ASM_AX
++1234:
++#endif
++
++#endif
++
++1: __copyuser_seg movzb (%_ASM_AX),%edx
+ xor %eax,%eax
+ ret
+ CFI_ENDPROC
+@@ -49,11 +70,24 @@ ENDPROC(__get_user_1)
+ ENTRY(__get_user_2)
+ CFI_STARTPROC
+ add $1,%_ASM_AX
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF)
+ jc bad_get_user
+ GET_THREAD_INFO(%_ASM_DX)
+ cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
+ jae bad_get_user
+-2: movzwl -1(%_ASM_AX),%edx
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ mov $PAX_USER_SHADOW_BASE,%_ASM_DX
++ cmp %_ASM_DX,%_ASM_AX
++ jae 1234f
++ add %_ASM_DX,%_ASM_AX
++1234:
++#endif
++
++#endif
++
++2: __copyuser_seg movzwl -1(%_ASM_AX),%edx
+ xor %eax,%eax
+ ret
+ CFI_ENDPROC
+@@ -62,11 +96,24 @@ ENDPROC(__get_user_2)
+ ENTRY(__get_user_4)
+ CFI_STARTPROC
+ add $3,%_ASM_AX
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF)
+ jc bad_get_user
+ GET_THREAD_INFO(%_ASM_DX)
+ cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
+ jae bad_get_user
+-3: mov -3(%_ASM_AX),%edx
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ mov $PAX_USER_SHADOW_BASE,%_ASM_DX
++ cmp %_ASM_DX,%_ASM_AX
++ jae 1234f
++ add %_ASM_DX,%_ASM_AX
++1234:
++#endif
++
++#endif
++
++3: __copyuser_seg mov -3(%_ASM_AX),%edx
+ xor %eax,%eax
+ ret
+ CFI_ENDPROC
+@@ -80,6 +127,15 @@ ENTRY(__get_user_8)
+ GET_THREAD_INFO(%_ASM_DX)
+ cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
+ jae bad_get_user
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ mov $PAX_USER_SHADOW_BASE,%_ASM_DX
++ cmp %_ASM_DX,%_ASM_AX
++ jae 1234f
++ add %_ASM_DX,%_ASM_AX
++1234:
++#endif
++
+ 4: movq -7(%_ASM_AX),%_ASM_DX
+ xor %eax,%eax
+ ret
+diff -urNp linux-2.6.38.7/arch/x86/lib/insn.c linux-2.6.38.7/arch/x86/lib/insn.c
+--- linux-2.6.38.7/arch/x86/lib/insn.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/insn.c 2011-04-28 19:34:14.000000000 -0400
+@@ -21,6 +21,11 @@
+ #include <linux/string.h>
+ #include <asm/inat.h>
+ #include <asm/insn.h>
++#ifdef __KERNEL__
++#include <asm/pgtable_types.h>
++#else
++#define ktla_ktva(addr) addr
++#endif
+
+ #define get_next(t, insn) \
+ ({t r; r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
+@@ -40,8 +45,8 @@
+ void insn_init(struct insn *insn, const void *kaddr, int x86_64)
+ {
+ memset(insn, 0, sizeof(*insn));
+- insn->kaddr = kaddr;
+- insn->next_byte = kaddr;
++ insn->kaddr = ktla_ktva(kaddr);
++ insn->next_byte = ktla_ktva(kaddr);
+ insn->x86_64 = x86_64 ? 1 : 0;
+ insn->opnd_bytes = 4;
+ if (x86_64)
+diff -urNp linux-2.6.38.7/arch/x86/lib/mmx_32.c linux-2.6.38.7/arch/x86/lib/mmx_32.c
+--- linux-2.6.38.7/arch/x86/lib/mmx_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/mmx_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -29,6 +29,7 @@ void *_mmx_memcpy(void *to, const void *
+ {
+ void *p;
+ int i;
++ unsigned long cr0;
+
+ if (unlikely(in_interrupt()))
+ return __memcpy(to, from, len);
+@@ -39,44 +40,72 @@ void *_mmx_memcpy(void *to, const void *
+ kernel_fpu_begin();
+
+ __asm__ __volatile__ (
+- "1: prefetch (%0)\n" /* This set is 28 bytes */
+- " prefetch 64(%0)\n"
+- " prefetch 128(%0)\n"
+- " prefetch 192(%0)\n"
+- " prefetch 256(%0)\n"
++ "1: prefetch (%1)\n" /* This set is 28 bytes */
++ " prefetch 64(%1)\n"
++ " prefetch 128(%1)\n"
++ " prefetch 192(%1)\n"
++ " prefetch 256(%1)\n"
+ "2: \n"
+ ".section .fixup, \"ax\"\n"
+- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
++ "3: \n"
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %%cr0, %0\n"
++ " movl %0, %%eax\n"
++ " andl $0xFFFEFFFF, %%eax\n"
++ " movl %%eax, %%cr0\n"
++#endif
++
++ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %0, %%cr0\n"
++#endif
++
+ " jmp 2b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 3b)
+- : : "r" (from));
++ : "=&r" (cr0) : "r" (from) : "ax");
+
+ for ( ; i > 5; i--) {
+ __asm__ __volatile__ (
+- "1: prefetch 320(%0)\n"
+- "2: movq (%0), %%mm0\n"
+- " movq 8(%0), %%mm1\n"
+- " movq 16(%0), %%mm2\n"
+- " movq 24(%0), %%mm3\n"
+- " movq %%mm0, (%1)\n"
+- " movq %%mm1, 8(%1)\n"
+- " movq %%mm2, 16(%1)\n"
+- " movq %%mm3, 24(%1)\n"
+- " movq 32(%0), %%mm0\n"
+- " movq 40(%0), %%mm1\n"
+- " movq 48(%0), %%mm2\n"
+- " movq 56(%0), %%mm3\n"
+- " movq %%mm0, 32(%1)\n"
+- " movq %%mm1, 40(%1)\n"
+- " movq %%mm2, 48(%1)\n"
+- " movq %%mm3, 56(%1)\n"
++ "1: prefetch 320(%1)\n"
++ "2: movq (%1), %%mm0\n"
++ " movq 8(%1), %%mm1\n"
++ " movq 16(%1), %%mm2\n"
++ " movq 24(%1), %%mm3\n"
++ " movq %%mm0, (%2)\n"
++ " movq %%mm1, 8(%2)\n"
++ " movq %%mm2, 16(%2)\n"
++ " movq %%mm3, 24(%2)\n"
++ " movq 32(%1), %%mm0\n"
++ " movq 40(%1), %%mm1\n"
++ " movq 48(%1), %%mm2\n"
++ " movq 56(%1), %%mm3\n"
++ " movq %%mm0, 32(%2)\n"
++ " movq %%mm1, 40(%2)\n"
++ " movq %%mm2, 48(%2)\n"
++ " movq %%mm3, 56(%2)\n"
+ ".section .fixup, \"ax\"\n"
+- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
++ "3:\n"
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %%cr0, %0\n"
++ " movl %0, %%eax\n"
++ " andl $0xFFFEFFFF, %%eax\n"
++ " movl %%eax, %%cr0\n"
++#endif
++
++ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %0, %%cr0\n"
++#endif
++
+ " jmp 2b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 3b)
+- : : "r" (from), "r" (to) : "memory");
++ : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax");
+
+ from += 64;
+ to += 64;
+@@ -158,6 +187,7 @@ static void fast_clear_page(void *page)
+ static void fast_copy_page(void *to, void *from)
+ {
+ int i;
++ unsigned long cr0;
+
+ kernel_fpu_begin();
+
+@@ -166,42 +196,70 @@ static void fast_copy_page(void *to, voi
+ * but that is for later. -AV
+ */
+ __asm__ __volatile__(
+- "1: prefetch (%0)\n"
+- " prefetch 64(%0)\n"
+- " prefetch 128(%0)\n"
+- " prefetch 192(%0)\n"
+- " prefetch 256(%0)\n"
++ "1: prefetch (%1)\n"
++ " prefetch 64(%1)\n"
++ " prefetch 128(%1)\n"
++ " prefetch 192(%1)\n"
++ " prefetch 256(%1)\n"
+ "2: \n"
+ ".section .fixup, \"ax\"\n"
+- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
++ "3: \n"
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %%cr0, %0\n"
++ " movl %0, %%eax\n"
++ " andl $0xFFFEFFFF, %%eax\n"
++ " movl %%eax, %%cr0\n"
++#endif
++
++ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %0, %%cr0\n"
++#endif
++
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b, 3b) : : "r" (from));
++ _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from) : "ax");
+
+ for (i = 0; i < (4096-320)/64; i++) {
+ __asm__ __volatile__ (
+- "1: prefetch 320(%0)\n"
+- "2: movq (%0), %%mm0\n"
+- " movntq %%mm0, (%1)\n"
+- " movq 8(%0), %%mm1\n"
+- " movntq %%mm1, 8(%1)\n"
+- " movq 16(%0), %%mm2\n"
+- " movntq %%mm2, 16(%1)\n"
+- " movq 24(%0), %%mm3\n"
+- " movntq %%mm3, 24(%1)\n"
+- " movq 32(%0), %%mm4\n"
+- " movntq %%mm4, 32(%1)\n"
+- " movq 40(%0), %%mm5\n"
+- " movntq %%mm5, 40(%1)\n"
+- " movq 48(%0), %%mm6\n"
+- " movntq %%mm6, 48(%1)\n"
+- " movq 56(%0), %%mm7\n"
+- " movntq %%mm7, 56(%1)\n"
++ "1: prefetch 320(%1)\n"
++ "2: movq (%1), %%mm0\n"
++ " movntq %%mm0, (%2)\n"
++ " movq 8(%1), %%mm1\n"
++ " movntq %%mm1, 8(%2)\n"
++ " movq 16(%1), %%mm2\n"
++ " movntq %%mm2, 16(%2)\n"
++ " movq 24(%1), %%mm3\n"
++ " movntq %%mm3, 24(%2)\n"
++ " movq 32(%1), %%mm4\n"
++ " movntq %%mm4, 32(%2)\n"
++ " movq 40(%1), %%mm5\n"
++ " movntq %%mm5, 40(%2)\n"
++ " movq 48(%1), %%mm6\n"
++ " movntq %%mm6, 48(%2)\n"
++ " movq 56(%1), %%mm7\n"
++ " movntq %%mm7, 56(%2)\n"
+ ".section .fixup, \"ax\"\n"
+- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
++ "3:\n"
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %%cr0, %0\n"
++ " movl %0, %%eax\n"
++ " andl $0xFFFEFFFF, %%eax\n"
++ " movl %%eax, %%cr0\n"
++#endif
++
++ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %0, %%cr0\n"
++#endif
++
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b, 3b) : : "r" (from), "r" (to) : "memory");
++ _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax");
+
+ from += 64;
+ to += 64;
+@@ -280,47 +338,76 @@ static void fast_clear_page(void *page)
+ static void fast_copy_page(void *to, void *from)
+ {
+ int i;
++ unsigned long cr0;
+
+ kernel_fpu_begin();
+
+ __asm__ __volatile__ (
+- "1: prefetch (%0)\n"
+- " prefetch 64(%0)\n"
+- " prefetch 128(%0)\n"
+- " prefetch 192(%0)\n"
+- " prefetch 256(%0)\n"
++ "1: prefetch (%1)\n"
++ " prefetch 64(%1)\n"
++ " prefetch 128(%1)\n"
++ " prefetch 192(%1)\n"
++ " prefetch 256(%1)\n"
+ "2: \n"
+ ".section .fixup, \"ax\"\n"
+- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
++ "3: \n"
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %%cr0, %0\n"
++ " movl %0, %%eax\n"
++ " andl $0xFFFEFFFF, %%eax\n"
++ " movl %%eax, %%cr0\n"
++#endif
++
++ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %0, %%cr0\n"
++#endif
++
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b, 3b) : : "r" (from));
++ _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from) : "ax");
+
+ for (i = 0; i < 4096/64; i++) {
+ __asm__ __volatile__ (
+- "1: prefetch 320(%0)\n"
+- "2: movq (%0), %%mm0\n"
+- " movq 8(%0), %%mm1\n"
+- " movq 16(%0), %%mm2\n"
+- " movq 24(%0), %%mm3\n"
+- " movq %%mm0, (%1)\n"
+- " movq %%mm1, 8(%1)\n"
+- " movq %%mm2, 16(%1)\n"
+- " movq %%mm3, 24(%1)\n"
+- " movq 32(%0), %%mm0\n"
+- " movq 40(%0), %%mm1\n"
+- " movq 48(%0), %%mm2\n"
+- " movq 56(%0), %%mm3\n"
+- " movq %%mm0, 32(%1)\n"
+- " movq %%mm1, 40(%1)\n"
+- " movq %%mm2, 48(%1)\n"
+- " movq %%mm3, 56(%1)\n"
++ "1: prefetch 320(%1)\n"
++ "2: movq (%1), %%mm0\n"
++ " movq 8(%1), %%mm1\n"
++ " movq 16(%1), %%mm2\n"
++ " movq 24(%1), %%mm3\n"
++ " movq %%mm0, (%2)\n"
++ " movq %%mm1, 8(%2)\n"
++ " movq %%mm2, 16(%2)\n"
++ " movq %%mm3, 24(%2)\n"
++ " movq 32(%1), %%mm0\n"
++ " movq 40(%1), %%mm1\n"
++ " movq 48(%1), %%mm2\n"
++ " movq 56(%1), %%mm3\n"
++ " movq %%mm0, 32(%2)\n"
++ " movq %%mm1, 40(%2)\n"
++ " movq %%mm2, 48(%2)\n"
++ " movq %%mm3, 56(%2)\n"
+ ".section .fixup, \"ax\"\n"
+- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
++ "3:\n"
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %%cr0, %0\n"
++ " movl %0, %%eax\n"
++ " andl $0xFFFEFFFF, %%eax\n"
++ " movl %%eax, %%cr0\n"
++#endif
++
++ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
++
++#ifdef CONFIG_PAX_KERNEXEC
++ " movl %0, %%cr0\n"
++#endif
++
+ " jmp 2b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 3b)
+- : : "r" (from), "r" (to) : "memory");
++ : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax");
+
+ from += 64;
+ to += 64;
+diff -urNp linux-2.6.38.7/arch/x86/lib/putuser.S linux-2.6.38.7/arch/x86/lib/putuser.S
+--- linux-2.6.38.7/arch/x86/lib/putuser.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/putuser.S 2011-04-28 19:34:14.000000000 -0400
+@@ -15,7 +15,8 @@
+ #include <asm/thread_info.h>
+ #include <asm/errno.h>
+ #include <asm/asm.h>
+-
++#include <asm/segment.h>
++#include <asm/pgtable.h>
+
+ /*
+ * __put_user_X
+@@ -29,52 +30,119 @@
+ * as they get called from within inline assembly.
+ */
+
+-#define ENTER CFI_STARTPROC ; \
+- GET_THREAD_INFO(%_ASM_BX)
++#define ENTER CFI_STARTPROC
+ #define EXIT ret ; \
+ CFI_ENDPROC
+
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++#define _DEST %_ASM_CX,%_ASM_BX
++#else
++#define _DEST %_ASM_CX
++#endif
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF)
++#define __copyuser_seg gs;
++#else
++#define __copyuser_seg
++#endif
++
+ .text
+ ENTRY(__put_user_1)
+ ENTER
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF)
++ GET_THREAD_INFO(%_ASM_BX)
+ cmp TI_addr_limit(%_ASM_BX),%_ASM_CX
+ jae bad_put_user
+-1: movb %al,(%_ASM_CX)
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ mov $PAX_USER_SHADOW_BASE,%_ASM_BX
++ cmp %_ASM_BX,%_ASM_CX
++ jb 1234f
++ xor %ebx,%ebx
++1234:
++#endif
++
++#endif
++
++1: __copyuser_seg movb %al,(_DEST)
+ xor %eax,%eax
+ EXIT
+ ENDPROC(__put_user_1)
+
+ ENTRY(__put_user_2)
+ ENTER
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF)
++ GET_THREAD_INFO(%_ASM_BX)
+ mov TI_addr_limit(%_ASM_BX),%_ASM_BX
+ sub $1,%_ASM_BX
+ cmp %_ASM_BX,%_ASM_CX
+ jae bad_put_user
+-2: movw %ax,(%_ASM_CX)
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ mov $PAX_USER_SHADOW_BASE,%_ASM_BX
++ cmp %_ASM_BX,%_ASM_CX
++ jb 1234f
++ xor %ebx,%ebx
++1234:
++#endif
++
++#endif
++
++2: __copyuser_seg movw %ax,(_DEST)
+ xor %eax,%eax
+ EXIT
+ ENDPROC(__put_user_2)
+
+ ENTRY(__put_user_4)
+ ENTER
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF)
++ GET_THREAD_INFO(%_ASM_BX)
+ mov TI_addr_limit(%_ASM_BX),%_ASM_BX
+ sub $3,%_ASM_BX
+ cmp %_ASM_BX,%_ASM_CX
+ jae bad_put_user
+-3: movl %eax,(%_ASM_CX)
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ mov $PAX_USER_SHADOW_BASE,%_ASM_BX
++ cmp %_ASM_BX,%_ASM_CX
++ jb 1234f
++ xor %ebx,%ebx
++1234:
++#endif
++
++#endif
++
++3: __copyuser_seg movl %eax,(_DEST)
+ xor %eax,%eax
+ EXIT
+ ENDPROC(__put_user_4)
+
+ ENTRY(__put_user_8)
+ ENTER
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF)
++ GET_THREAD_INFO(%_ASM_BX)
+ mov TI_addr_limit(%_ASM_BX),%_ASM_BX
+ sub $7,%_ASM_BX
+ cmp %_ASM_BX,%_ASM_CX
+ jae bad_put_user
+-4: mov %_ASM_AX,(%_ASM_CX)
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ mov $PAX_USER_SHADOW_BASE,%_ASM_BX
++ cmp %_ASM_BX,%_ASM_CX
++ jb 1234f
++ xor %ebx,%ebx
++1234:
++#endif
++
++#endif
++
++4: __copyuser_seg mov %_ASM_AX,(_DEST)
+ #ifdef CONFIG_X86_32
+-5: movl %edx,4(%_ASM_CX)
++5: __copyuser_seg movl %edx,4(_DEST)
+ #endif
+ xor %eax,%eax
+ EXIT
+diff -urNp linux-2.6.38.7/arch/x86/lib/usercopy_32.c linux-2.6.38.7/arch/x86/lib/usercopy_32.c
+--- linux-2.6.38.7/arch/x86/lib/usercopy_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/usercopy_32.c 2011-04-28 19:34:14.000000000 -0400
+@@ -43,7 +43,7 @@ do { \
+ __asm__ __volatile__( \
+ " testl %1,%1\n" \
+ " jz 2f\n" \
+- "0: lodsb\n" \
++ "0: "__copyuser_seg"lodsb\n" \
+ " stosb\n" \
+ " testb %%al,%%al\n" \
+ " jz 1f\n" \
+@@ -128,10 +128,12 @@ do { \
+ int __d0; \
+ might_fault(); \
+ __asm__ __volatile__( \
++ __COPYUSER_SET_ES \
+ "0: rep; stosl\n" \
+ " movl %2,%0\n" \
+ "1: rep; stosb\n" \
+ "2:\n" \
++ __COPYUSER_RESTORE_ES \
+ ".section .fixup,\"ax\"\n" \
+ "3: lea 0(%2,%0,4),%0\n" \
+ " jmp 2b\n" \
+@@ -200,6 +202,7 @@ long strnlen_user(const char __user *s,
+ might_fault();
+
+ __asm__ __volatile__(
++ __COPYUSER_SET_ES
+ " testl %0, %0\n"
+ " jz 3f\n"
+ " andl %0,%%ecx\n"
+@@ -208,6 +211,7 @@ long strnlen_user(const char __user *s,
+ " subl %%ecx,%0\n"
+ " addl %0,%%eax\n"
+ "1:\n"
++ __COPYUSER_RESTORE_ES
+ ".section .fixup,\"ax\"\n"
+ "2: xorl %%eax,%%eax\n"
+ " jmp 1b\n"
+@@ -227,7 +231,7 @@ EXPORT_SYMBOL(strnlen_user);
+
+ #ifdef CONFIG_X86_INTEL_USERCOPY
+ static unsigned long
+-__copy_user_intel(void __user *to, const void *from, unsigned long size)
++__generic_copy_to_user_intel(void __user *to, const void *from, unsigned long size)
+ {
+ int d0, d1;
+ __asm__ __volatile__(
+@@ -239,36 +243,36 @@ __copy_user_intel(void __user *to, const
+ " .align 2,0x90\n"
+ "3: movl 0(%4), %%eax\n"
+ "4: movl 4(%4), %%edx\n"
+- "5: movl %%eax, 0(%3)\n"
+- "6: movl %%edx, 4(%3)\n"
++ "5: "__copyuser_seg" movl %%eax, 0(%3)\n"
++ "6: "__copyuser_seg" movl %%edx, 4(%3)\n"
+ "7: movl 8(%4), %%eax\n"
+ "8: movl 12(%4),%%edx\n"
+- "9: movl %%eax, 8(%3)\n"
+- "10: movl %%edx, 12(%3)\n"
++ "9: "__copyuser_seg" movl %%eax, 8(%3)\n"
++ "10: "__copyuser_seg" movl %%edx, 12(%3)\n"
+ "11: movl 16(%4), %%eax\n"
+ "12: movl 20(%4), %%edx\n"
+- "13: movl %%eax, 16(%3)\n"
+- "14: movl %%edx, 20(%3)\n"
++ "13: "__copyuser_seg" movl %%eax, 16(%3)\n"
++ "14: "__copyuser_seg" movl %%edx, 20(%3)\n"
+ "15: movl 24(%4), %%eax\n"
+ "16: movl 28(%4), %%edx\n"
+- "17: movl %%eax, 24(%3)\n"
+- "18: movl %%edx, 28(%3)\n"
++ "17: "__copyuser_seg" movl %%eax, 24(%3)\n"
++ "18: "__copyuser_seg" movl %%edx, 28(%3)\n"
+ "19: movl 32(%4), %%eax\n"
+ "20: movl 36(%4), %%edx\n"
+- "21: movl %%eax, 32(%3)\n"
+- "22: movl %%edx, 36(%3)\n"
++ "21: "__copyuser_seg" movl %%eax, 32(%3)\n"
++ "22: "__copyuser_seg" movl %%edx, 36(%3)\n"
+ "23: movl 40(%4), %%eax\n"
+ "24: movl 44(%4), %%edx\n"
+- "25: movl %%eax, 40(%3)\n"
+- "26: movl %%edx, 44(%3)\n"
++ "25: "__copyuser_seg" movl %%eax, 40(%3)\n"
++ "26: "__copyuser_seg" movl %%edx, 44(%3)\n"
+ "27: movl 48(%4), %%eax\n"
+ "28: movl 52(%4), %%edx\n"
+- "29: movl %%eax, 48(%3)\n"
+- "30: movl %%edx, 52(%3)\n"
++ "29: "__copyuser_seg" movl %%eax, 48(%3)\n"
++ "30: "__copyuser_seg" movl %%edx, 52(%3)\n"
+ "31: movl 56(%4), %%eax\n"
+ "32: movl 60(%4), %%edx\n"
+- "33: movl %%eax, 56(%3)\n"
+- "34: movl %%edx, 60(%3)\n"
++ "33: "__copyuser_seg" movl %%eax, 56(%3)\n"
++ "34: "__copyuser_seg" movl %%edx, 60(%3)\n"
+ " addl $-64, %0\n"
+ " addl $64, %4\n"
+ " addl $64, %3\n"
+@@ -278,10 +282,119 @@ __copy_user_intel(void __user *to, const
+ " shrl $2, %0\n"
+ " andl $3, %%eax\n"
+ " cld\n"
++ __COPYUSER_SET_ES
+ "99: rep; movsl\n"
+ "36: movl %%eax, %0\n"
+ "37: rep; movsb\n"
+ "100:\n"
++ __COPYUSER_RESTORE_ES
++ ".section .fixup,\"ax\"\n"
++ "101: lea 0(%%eax,%0,4),%0\n"
++ " jmp 100b\n"
++ ".previous\n"
++ ".section __ex_table,\"a\"\n"
++ " .align 4\n"
++ " .long 1b,100b\n"
++ " .long 2b,100b\n"
++ " .long 3b,100b\n"
++ " .long 4b,100b\n"
++ " .long 5b,100b\n"
++ " .long 6b,100b\n"
++ " .long 7b,100b\n"
++ " .long 8b,100b\n"
++ " .long 9b,100b\n"
++ " .long 10b,100b\n"
++ " .long 11b,100b\n"
++ " .long 12b,100b\n"
++ " .long 13b,100b\n"
++ " .long 14b,100b\n"
++ " .long 15b,100b\n"
++ " .long 16b,100b\n"
++ " .long 17b,100b\n"
++ " .long 18b,100b\n"
++ " .long 19b,100b\n"
++ " .long 20b,100b\n"
++ " .long 21b,100b\n"
++ " .long 22b,100b\n"
++ " .long 23b,100b\n"
++ " .long 24b,100b\n"
++ " .long 25b,100b\n"
++ " .long 26b,100b\n"
++ " .long 27b,100b\n"
++ " .long 28b,100b\n"
++ " .long 29b,100b\n"
++ " .long 30b,100b\n"
++ " .long 31b,100b\n"
++ " .long 32b,100b\n"
++ " .long 33b,100b\n"
++ " .long 34b,100b\n"
++ " .long 35b,100b\n"
++ " .long 36b,100b\n"
++ " .long 37b,100b\n"
++ " .long 99b,101b\n"
++ ".previous"
++ : "=&c"(size), "=&D" (d0), "=&S" (d1)
++ : "1"(to), "2"(from), "0"(size)
++ : "eax", "edx", "memory");
++ return size;
++}
++
++static unsigned long
++__generic_copy_from_user_intel(void *to, const void __user *from, unsigned long size)
++{
++ int d0, d1;
++ __asm__ __volatile__(
++ " .align 2,0x90\n"
++ "1: "__copyuser_seg" movl 32(%4), %%eax\n"
++ " cmpl $67, %0\n"
++ " jbe 3f\n"
++ "2: "__copyuser_seg" movl 64(%4), %%eax\n"
++ " .align 2,0x90\n"
++ "3: "__copyuser_seg" movl 0(%4), %%eax\n"
++ "4: "__copyuser_seg" movl 4(%4), %%edx\n"
++ "5: movl %%eax, 0(%3)\n"
++ "6: movl %%edx, 4(%3)\n"
++ "7: "__copyuser_seg" movl 8(%4), %%eax\n"
++ "8: "__copyuser_seg" movl 12(%4),%%edx\n"
++ "9: movl %%eax, 8(%3)\n"
++ "10: movl %%edx, 12(%3)\n"
++ "11: "__copyuser_seg" movl 16(%4), %%eax\n"
++ "12: "__copyuser_seg" movl 20(%4), %%edx\n"
++ "13: movl %%eax, 16(%3)\n"
++ "14: movl %%edx, 20(%3)\n"
++ "15: "__copyuser_seg" movl 24(%4), %%eax\n"
++ "16: "__copyuser_seg" movl 28(%4), %%edx\n"
++ "17: movl %%eax, 24(%3)\n"
++ "18: movl %%edx, 28(%3)\n"
++ "19: "__copyuser_seg" movl 32(%4), %%eax\n"
++ "20: "__copyuser_seg" movl 36(%4), %%edx\n"
++ "21: movl %%eax, 32(%3)\n"
++ "22: movl %%edx, 36(%3)\n"
++ "23: "__copyuser_seg" movl 40(%4), %%eax\n"
++ "24: "__copyuser_seg" movl 44(%4), %%edx\n"
++ "25: movl %%eax, 40(%3)\n"
++ "26: movl %%edx, 44(%3)\n"
++ "27: "__copyuser_seg" movl 48(%4), %%eax\n"
++ "28: "__copyuser_seg" movl 52(%4), %%edx\n"
++ "29: movl %%eax, 48(%3)\n"
++ "30: movl %%edx, 52(%3)\n"
++ "31: "__copyuser_seg" movl 56(%4), %%eax\n"
++ "32: "__copyuser_seg" movl 60(%4), %%edx\n"
++ "33: movl %%eax, 56(%3)\n"
++ "34: movl %%edx, 60(%3)\n"
++ " addl $-64, %0\n"
++ " addl $64, %4\n"
++ " addl $64, %3\n"
++ " cmpl $63, %0\n"
++ " ja 1b\n"
++ "35: movl %0, %%eax\n"
++ " shrl $2, %0\n"
++ " andl $3, %%eax\n"
++ " cld\n"
++ "99: rep; "__copyuser_seg" movsl\n"
++ "36: movl %%eax, %0\n"
++ "37: rep; "__copyuser_seg" movsb\n"
++ "100:\n"
+ ".section .fixup,\"ax\"\n"
+ "101: lea 0(%%eax,%0,4),%0\n"
+ " jmp 100b\n"
+@@ -339,41 +452,41 @@ __copy_user_zeroing_intel(void *to, cons
+ int d0, d1;
+ __asm__ __volatile__(
+ " .align 2,0x90\n"
+- "0: movl 32(%4), %%eax\n"
++ "0: "__copyuser_seg" movl 32(%4), %%eax\n"
+ " cmpl $67, %0\n"
+ " jbe 2f\n"
+- "1: movl 64(%4), %%eax\n"
++ "1: "__copyuser_seg" movl 64(%4), %%eax\n"
+ " .align 2,0x90\n"
+- "2: movl 0(%4), %%eax\n"
+- "21: movl 4(%4), %%edx\n"
++ "2: "__copyuser_seg" movl 0(%4), %%eax\n"
++ "21: "__copyuser_seg" movl 4(%4), %%edx\n"
+ " movl %%eax, 0(%3)\n"
+ " movl %%edx, 4(%3)\n"
+- "3: movl 8(%4), %%eax\n"
+- "31: movl 12(%4),%%edx\n"
++ "3: "__copyuser_seg" movl 8(%4), %%eax\n"
++ "31: "__copyuser_seg" movl 12(%4),%%edx\n"
+ " movl %%eax, 8(%3)\n"
+ " movl %%edx, 12(%3)\n"
+- "4: movl 16(%4), %%eax\n"
+- "41: movl 20(%4), %%edx\n"
++ "4: "__copyuser_seg" movl 16(%4), %%eax\n"
++ "41: "__copyuser_seg" movl 20(%4), %%edx\n"
+ " movl %%eax, 16(%3)\n"
+ " movl %%edx, 20(%3)\n"
+- "10: movl 24(%4), %%eax\n"
+- "51: movl 28(%4), %%edx\n"
++ "10: "__copyuser_seg" movl 24(%4), %%eax\n"
++ "51: "__copyuser_seg" movl 28(%4), %%edx\n"
+ " movl %%eax, 24(%3)\n"
+ " movl %%edx, 28(%3)\n"
+- "11: movl 32(%4), %%eax\n"
+- "61: movl 36(%4), %%edx\n"
++ "11: "__copyuser_seg" movl 32(%4), %%eax\n"
++ "61: "__copyuser_seg" movl 36(%4), %%edx\n"
+ " movl %%eax, 32(%3)\n"
+ " movl %%edx, 36(%3)\n"
+- "12: movl 40(%4), %%eax\n"
+- "71: movl 44(%4), %%edx\n"
++ "12: "__copyuser_seg" movl 40(%4), %%eax\n"
++ "71: "__copyuser_seg" movl 44(%4), %%edx\n"
+ " movl %%eax, 40(%3)\n"
+ " movl %%edx, 44(%3)\n"
+- "13: movl 48(%4), %%eax\n"
+- "81: movl 52(%4), %%edx\n"
++ "13: "__copyuser_seg" movl 48(%4), %%eax\n"
++ "81: "__copyuser_seg" movl 52(%4), %%edx\n"
+ " movl %%eax, 48(%3)\n"
+ " movl %%edx, 52(%3)\n"
+- "14: movl 56(%4), %%eax\n"
+- "91: movl 60(%4), %%edx\n"
++ "14: "__copyuser_seg" movl 56(%4), %%eax\n"
++ "91: "__copyuser_seg" movl 60(%4), %%edx\n"
+ " movl %%eax, 56(%3)\n"
+ " movl %%edx, 60(%3)\n"
+ " addl $-64, %0\n"
+@@ -385,9 +498,9 @@ __copy_user_zeroing_intel(void *to, cons
+ " shrl $2, %0\n"
+ " andl $3, %%eax\n"
+ " cld\n"
+- "6: rep; movsl\n"
++ "6: rep; "__copyuser_seg" movsl\n"
+ " movl %%eax,%0\n"
+- "7: rep; movsb\n"
++ "7: rep; "__copyuser_seg" movsb\n"
+ "8:\n"
+ ".section .fixup,\"ax\"\n"
+ "9: lea 0(%%eax,%0,4),%0\n"
+@@ -440,41 +553,41 @@ static unsigned long __copy_user_zeroing
+
+ __asm__ __volatile__(
+ " .align 2,0x90\n"
+- "0: movl 32(%4), %%eax\n"
++ "0: "__copyuser_seg" movl 32(%4), %%eax\n"
+ " cmpl $67, %0\n"
+ " jbe 2f\n"
+- "1: movl 64(%4), %%eax\n"
++ "1: "__copyuser_seg" movl 64(%4), %%eax\n"
+ " .align 2,0x90\n"
+- "2: movl 0(%4), %%eax\n"
+- "21: movl 4(%4), %%edx\n"
++ "2: "__copyuser_seg" movl 0(%4), %%eax\n"
++ "21: "__copyuser_seg" movl 4(%4), %%edx\n"
+ " movnti %%eax, 0(%3)\n"
+ " movnti %%edx, 4(%3)\n"
+- "3: movl 8(%4), %%eax\n"
+- "31: movl 12(%4),%%edx\n"
++ "3: "__copyuser_seg" movl 8(%4), %%eax\n"
++ "31: "__copyuser_seg" movl 12(%4),%%edx\n"
+ " movnti %%eax, 8(%3)\n"
+ " movnti %%edx, 12(%3)\n"
+- "4: movl 16(%4), %%eax\n"
+- "41: movl 20(%4), %%edx\n"
++ "4: "__copyuser_seg" movl 16(%4), %%eax\n"
++ "41: "__copyuser_seg" movl 20(%4), %%edx\n"
+ " movnti %%eax, 16(%3)\n"
+ " movnti %%edx, 20(%3)\n"
+- "10: movl 24(%4), %%eax\n"
+- "51: movl 28(%4), %%edx\n"
++ "10: "__copyuser_seg" movl 24(%4), %%eax\n"
++ "51: "__copyuser_seg" movl 28(%4), %%edx\n"
+ " movnti %%eax, 24(%3)\n"
+ " movnti %%edx, 28(%3)\n"
+- "11: movl 32(%4), %%eax\n"
+- "61: movl 36(%4), %%edx\n"
++ "11: "__copyuser_seg" movl 32(%4), %%eax\n"
++ "61: "__copyuser_seg" movl 36(%4), %%edx\n"
+ " movnti %%eax, 32(%3)\n"
+ " movnti %%edx, 36(%3)\n"
+- "12: movl 40(%4), %%eax\n"
+- "71: movl 44(%4), %%edx\n"
++ "12: "__copyuser_seg" movl 40(%4), %%eax\n"
++ "71: "__copyuser_seg" movl 44(%4), %%edx\n"
+ " movnti %%eax, 40(%3)\n"
+ " movnti %%edx, 44(%3)\n"
+- "13: movl 48(%4), %%eax\n"
+- "81: movl 52(%4), %%edx\n"
++ "13: "__copyuser_seg" movl 48(%4), %%eax\n"
++ "81: "__copyuser_seg" movl 52(%4), %%edx\n"
+ " movnti %%eax, 48(%3)\n"
+ " movnti %%edx, 52(%3)\n"
+- "14: movl 56(%4), %%eax\n"
+- "91: movl 60(%4), %%edx\n"
++ "14: "__copyuser_seg" movl 56(%4), %%eax\n"
++ "91: "__copyuser_seg" movl 60(%4), %%edx\n"
+ " movnti %%eax, 56(%3)\n"
+ " movnti %%edx, 60(%3)\n"
+ " addl $-64, %0\n"
+@@ -487,9 +600,9 @@ static unsigned long __copy_user_zeroing
+ " shrl $2, %0\n"
+ " andl $3, %%eax\n"
+ " cld\n"
+- "6: rep; movsl\n"
++ "6: rep; "__copyuser_seg" movsl\n"
+ " movl %%eax,%0\n"
+- "7: rep; movsb\n"
++ "7: rep; "__copyuser_seg" movsb\n"
+ "8:\n"
+ ".section .fixup,\"ax\"\n"
+ "9: lea 0(%%eax,%0,4),%0\n"
+@@ -537,41 +650,41 @@ static unsigned long __copy_user_intel_n
+
+ __asm__ __volatile__(
+ " .align 2,0x90\n"
+- "0: movl 32(%4), %%eax\n"
++ "0: "__copyuser_seg" movl 32(%4), %%eax\n"
+ " cmpl $67, %0\n"
+ " jbe 2f\n"
+- "1: movl 64(%4), %%eax\n"
++ "1: "__copyuser_seg" movl 64(%4), %%eax\n"
+ " .align 2,0x90\n"
+- "2: movl 0(%4), %%eax\n"
+- "21: movl 4(%4), %%edx\n"
++ "2: "__copyuser_seg" movl 0(%4), %%eax\n"
++ "21: "__copyuser_seg" movl 4(%4), %%edx\n"
+ " movnti %%eax, 0(%3)\n"
+ " movnti %%edx, 4(%3)\n"
+- "3: movl 8(%4), %%eax\n"
+- "31: movl 12(%4),%%edx\n"
++ "3: "__copyuser_seg" movl 8(%4), %%eax\n"
++ "31: "__copyuser_seg" movl 12(%4),%%edx\n"
+ " movnti %%eax, 8(%3)\n"
+ " movnti %%edx, 12(%3)\n"
+- "4: movl 16(%4), %%eax\n"
+- "41: movl 20(%4), %%edx\n"
++ "4: "__copyuser_seg" movl 16(%4), %%eax\n"
++ "41: "__copyuser_seg" movl 20(%4), %%edx\n"
+ " movnti %%eax, 16(%3)\n"
+ " movnti %%edx, 20(%3)\n"
+- "10: movl 24(%4), %%eax\n"
+- "51: movl 28(%4), %%edx\n"
++ "10: "__copyuser_seg" movl 24(%4), %%eax\n"
++ "51: "__copyuser_seg" movl 28(%4), %%edx\n"
+ " movnti %%eax, 24(%3)\n"
+ " movnti %%edx, 28(%3)\n"
+- "11: movl 32(%4), %%eax\n"
+- "61: movl 36(%4), %%edx\n"
++ "11: "__copyuser_seg" movl 32(%4), %%eax\n"
++ "61: "__copyuser_seg" movl 36(%4), %%edx\n"
+ " movnti %%eax, 32(%3)\n"
+ " movnti %%edx, 36(%3)\n"
+- "12: movl 40(%4), %%eax\n"
+- "71: movl 44(%4), %%edx\n"
++ "12: "__copyuser_seg" movl 40(%4), %%eax\n"
++ "71: "__copyuser_seg" movl 44(%4), %%edx\n"
+ " movnti %%eax, 40(%3)\n"
+ " movnti %%edx, 44(%3)\n"
+- "13: movl 48(%4), %%eax\n"
+- "81: movl 52(%4), %%edx\n"
++ "13: "__copyuser_seg" movl 48(%4), %%eax\n"
++ "81: "__copyuser_seg" movl 52(%4), %%edx\n"
+ " movnti %%eax, 48(%3)\n"
+ " movnti %%edx, 52(%3)\n"
+- "14: movl 56(%4), %%eax\n"
+- "91: movl 60(%4), %%edx\n"
++ "14: "__copyuser_seg" movl 56(%4), %%eax\n"
++ "91: "__copyuser_seg" movl 60(%4), %%edx\n"
+ " movnti %%eax, 56(%3)\n"
+ " movnti %%edx, 60(%3)\n"
+ " addl $-64, %0\n"
+@@ -584,9 +697,9 @@ static unsigned long __copy_user_intel_n
+ " shrl $2, %0\n"
+ " andl $3, %%eax\n"
+ " cld\n"
+- "6: rep; movsl\n"
++ "6: rep; "__copyuser_seg" movsl\n"
+ " movl %%eax,%0\n"
+- "7: rep; movsb\n"
++ "7: rep; "__copyuser_seg" movsb\n"
+ "8:\n"
+ ".section .fixup,\"ax\"\n"
+ "9: lea 0(%%eax,%0,4),%0\n"
+@@ -629,32 +742,36 @@ static unsigned long __copy_user_intel_n
+ */
+ unsigned long __copy_user_zeroing_intel(void *to, const void __user *from,
+ unsigned long size);
+-unsigned long __copy_user_intel(void __user *to, const void *from,
++unsigned long __generic_copy_to_user_intel(void __user *to, const void *from,
++ unsigned long size);
++unsigned long __generic_copy_from_user_intel(void *to, const void __user *from,
+ unsigned long size);
+ unsigned long __copy_user_zeroing_intel_nocache(void *to,
+ const void __user *from, unsigned long size);
+ #endif /* CONFIG_X86_INTEL_USERCOPY */
+
+ /* Generic arbitrary sized copy. */
+-#define __copy_user(to, from, size) \
++#define __copy_user(to, from, size, prefix, set, restore) \
+ do { \
+ int __d0, __d1, __d2; \
+ __asm__ __volatile__( \
++ set \
+ " cmp $7,%0\n" \
+ " jbe 1f\n" \
+ " movl %1,%0\n" \
+ " negl %0\n" \
+ " andl $7,%0\n" \
+ " subl %0,%3\n" \
+- "4: rep; movsb\n" \
++ "4: rep; "prefix"movsb\n" \
+ " movl %3,%0\n" \
+ " shrl $2,%0\n" \
+ " andl $3,%3\n" \
+ " .align 2,0x90\n" \
+- "0: rep; movsl\n" \
++ "0: rep; "prefix"movsl\n" \
+ " movl %3,%0\n" \
+- "1: rep; movsb\n" \
++ "1: rep; "prefix"movsb\n" \
+ "2:\n" \
++ restore \
+ ".section .fixup,\"ax\"\n" \
+ "5: addl %3,%0\n" \
+ " jmp 2b\n" \
+@@ -682,14 +799,14 @@ do { \
+ " negl %0\n" \
+ " andl $7,%0\n" \
+ " subl %0,%3\n" \
+- "4: rep; movsb\n" \
++ "4: rep; "__copyuser_seg"movsb\n" \
+ " movl %3,%0\n" \
+ " shrl $2,%0\n" \
+ " andl $3,%3\n" \
+ " .align 2,0x90\n" \
+- "0: rep; movsl\n" \
++ "0: rep; "__copyuser_seg"movsl\n" \
+ " movl %3,%0\n" \
+- "1: rep; movsb\n" \
++ "1: rep; "__copyuser_seg"movsb\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "5: addl %3,%0\n" \
+@@ -775,9 +892,9 @@ survive:
+ }
+ #endif
+ if (movsl_is_ok(to, from, n))
+- __copy_user(to, from, n);
++ __copy_user(to, from, n, "", __COPYUSER_SET_ES, __COPYUSER_RESTORE_ES);
+ else
+- n = __copy_user_intel(to, from, n);
++ n = __generic_copy_to_user_intel(to, from, n);
+ return n;
+ }
+ EXPORT_SYMBOL(__copy_to_user_ll);
+@@ -797,10 +914,9 @@ unsigned long __copy_from_user_ll_nozero
+ unsigned long n)
+ {
+ if (movsl_is_ok(to, from, n))
+- __copy_user(to, from, n);
++ __copy_user(to, from, n, __copyuser_seg, "", "");
+ else
+- n = __copy_user_intel((void __user *)to,
+- (const void *)from, n);
++ n = __generic_copy_from_user_intel(to, from, n);
+ return n;
+ }
+ EXPORT_SYMBOL(__copy_from_user_ll_nozero);
+@@ -827,65 +943,50 @@ unsigned long __copy_from_user_ll_nocach
+ if (n > 64 && cpu_has_xmm2)
+ n = __copy_user_intel_nocache(to, from, n);
+ else
+- __copy_user(to, from, n);
++ __copy_user(to, from, n, __copyuser_seg, "", "");
+ #else
+- __copy_user(to, from, n);
++ __copy_user(to, from, n, __copyuser_seg, "", "");
+ #endif
+ return n;
+ }
+ EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
+
+-/**
+- * copy_to_user: - Copy a block of data into user space.
+- * @to: Destination address, in user space.
+- * @from: Source address, in kernel space.
+- * @n: Number of bytes to copy.
+- *
+- * Context: User context only. This function may sleep.
+- *
+- * Copy data from kernel space to user space.
+- *
+- * Returns number of bytes that could not be copied.
+- * On success, this will be zero.
+- */
+-unsigned long
+-copy_to_user(void __user *to, const void *from, unsigned long n)
++void copy_from_user_overflow(void)
+ {
+- if (access_ok(VERIFY_WRITE, to, n))
+- n = __copy_to_user(to, from, n);
+- return n;
++ WARN(1, "Buffer overflow detected!\n");
+ }
+-EXPORT_SYMBOL(copy_to_user);
++EXPORT_SYMBOL(copy_from_user_overflow);
+
+-/**
+- * copy_from_user: - Copy a block of data from user space.
+- * @to: Destination address, in kernel space.
+- * @from: Source address, in user space.
+- * @n: Number of bytes to copy.
+- *
+- * Context: User context only. This function may sleep.
+- *
+- * Copy data from user space to kernel space.
+- *
+- * Returns number of bytes that could not be copied.
+- * On success, this will be zero.
+- *
+- * If some data could not be copied, this function will pad the copied
+- * data to the requested size using zero bytes.
+- */
+-unsigned long
+-_copy_from_user(void *to, const void __user *from, unsigned long n)
++void copy_to_user_overflow(void)
+ {
+- if (access_ok(VERIFY_READ, from, n))
+- n = __copy_from_user(to, from, n);
+- else
+- memset(to, 0, n);
+- return n;
++ WARN(1, "Buffer overflow detected!\n");
+ }
+-EXPORT_SYMBOL(_copy_from_user);
++EXPORT_SYMBOL(copy_to_user_overflow);
+
+-void copy_from_user_overflow(void)
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++void __set_fs(mm_segment_t x)
+ {
+- WARN(1, "Buffer overflow detected!\n");
++ switch (x.seg) {
++ case 0:
++ loadsegment(gs, 0);
++ break;
++ case TASK_SIZE_MAX:
++ loadsegment(gs, __USER_DS);
++ break;
++ case -1UL:
++ loadsegment(gs, __KERNEL_DS);
++ break;
++ default:
++ BUG();
++ }
++ return;
+ }
+-EXPORT_SYMBOL(copy_from_user_overflow);
++EXPORT_SYMBOL(__set_fs);
++
++void set_fs(mm_segment_t x)
++{
++ current_thread_info()->addr_limit = x;
++ __set_fs(x);
++}
++EXPORT_SYMBOL(set_fs);
++#endif
+diff -urNp linux-2.6.38.7/arch/x86/lib/usercopy_64.c linux-2.6.38.7/arch/x86/lib/usercopy_64.c
+--- linux-2.6.38.7/arch/x86/lib/usercopy_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/lib/usercopy_64.c 2011-04-28 19:57:25.000000000 -0400
+@@ -42,6 +42,12 @@ long
+ __strncpy_from_user(char *dst, const char __user *src, long count)
+ {
+ long res;
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)src < PAX_USER_SHADOW_BASE)
++ src += PAX_USER_SHADOW_BASE;
++#endif
++
+ __do_strncpy_from_user(dst, src, count, res);
+ return res;
+ }
+@@ -65,6 +71,12 @@ unsigned long __clear_user(void __user *
+ {
+ long __d0;
+ might_fault();
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)addr < PAX_USER_SHADOW_BASE)
++ addr += PAX_USER_SHADOW_BASE;
++#endif
++
+ /* no memory constraint because it doesn't change any memory gcc knows
+ about */
+ asm volatile(
+@@ -151,10 +163,18 @@ EXPORT_SYMBOL(strlen_user);
+
+ unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len)
+ {
+- if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) {
++ if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) {
++
++#ifdef CONFIG_PAX_MEMORY_UDEREF
++ if ((unsigned long)to < PAX_USER_SHADOW_BASE)
++ to += PAX_USER_SHADOW_BASE;
++ if ((unsigned long)from < PAX_USER_SHADOW_BASE)
++ from += PAX_USER_SHADOW_BASE;
++#endif
++
+ return copy_user_generic((__force void *)to, (__force void *)from, len);
+- }
+- return len;
++ }
++ return len;
+ }
+ EXPORT_SYMBOL(copy_in_user);
+
+diff -urNp linux-2.6.38.7/arch/x86/Makefile linux-2.6.38.7/arch/x86/Makefile
+--- linux-2.6.38.7/arch/x86/Makefile 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/Makefile 2011-04-28 19:34:14.000000000 -0400
+@@ -195,3 +195,12 @@ define archhelp
+ echo ' FDARGS="..." arguments for the booted kernel'
+ echo ' FDINITRD=file initrd for the booted kernel'
+ endef
++
++define OLD_LD
++
++*** ${VERSION}.${PATCHLEVEL} PaX kernels no longer build correctly with old versions of binutils.
++*** Please upgrade your binutils to 2.18 or newer
++endef
++
++archprepare:
++ $(if $(LDFLAGS_BUILD_ID),,$(error $(OLD_LD)))
+diff -urNp linux-2.6.38.7/arch/x86/mm/extable.c linux-2.6.38.7/arch/x86/mm/extable.c
+--- linux-2.6.38.7/arch/x86/mm/extable.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/extable.c 2011-04-28 19:34:14.000000000 -0400
+@@ -1,14 +1,71 @@
+ #include <linux/module.h>
+ #include <linux/spinlock.h>
++#include <linux/sort.h>
+ #include <asm/uaccess.h>
++#include <asm/pgtable.h>
+
++/*
++ * The exception table needs to be sorted so that the binary
++ * search that we use to find entries in it works properly.
++ * This is used both for the kernel exception table and for
++ * the exception tables of modules that get loaded.
++ */
++static int cmp_ex(const void *a, const void *b)
++{
++ const struct exception_table_entry *x = a, *y = b;
++
++ /* avoid overflow */
++ if (x->insn > y->insn)
++ return 1;
++ if (x->insn < y->insn)
++ return -1;
++ return 0;
++}
++
++static void swap_ex(void *a, void *b, int size)
++{
++ struct exception_table_entry t, *x = a, *y = b;
++
++ t = *x;
++
++ pax_open_kernel();
++ *x = *y;
++ *y = t;
++ pax_close_kernel();
++}
++
++void sort_extable(struct exception_table_entry *start,
++ struct exception_table_entry *finish)
++{
++ sort(start, finish - start, sizeof(struct exception_table_entry),
++ cmp_ex, swap_ex);
++}
++
++#ifdef CONFIG_MODULES
++/*
++ * If the exception table is sorted, any referring to the module init
++ * will be at the beginning or the end.
++ */
++void trim_init_extable(struct module *m)
++{
++ /*trim the beginning*/
++ while (m->num_exentries && within_module_init(m->extable[0].insn, m)) {
++ m->extable++;
++ m->num_exentries--;
++ }
++ /*trim the end*/
++ while (m->num_exentries &&
++ within_module_init(m->extable[m->num_exentries-1].insn, m))
++ m->num_exentries--;
++}
++#endif /* CONFIG_MODULES */
+
+ int fixup_exception(struct pt_regs *regs)
+ {
+ const struct exception_table_entry *fixup;
+
+ #ifdef CONFIG_PNPBIOS
+- if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
++ if (unlikely(!v8086_mode(regs) && SEGMENT_IS_PNP_CODE(regs->cs))) {
+ extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
+ extern u32 pnp_bios_is_utter_crap;
+ pnp_bios_is_utter_crap = 1;
+diff -urNp linux-2.6.38.7/arch/x86/mm/fault.c linux-2.6.38.7/arch/x86/mm/fault.c
+--- linux-2.6.38.7/arch/x86/mm/fault.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/fault.c 2011-05-22 23:31:40.000000000 -0400
+@@ -12,10 +12,18 @@
+ #include <linux/mmiotrace.h> /* kmmio_handler, ... */
+ #include <linux/perf_event.h> /* perf_sw_event */
+ #include <linux/hugetlb.h> /* hstate_index_to_shift */
++#include <linux/unistd.h>
++#include <linux/compiler.h>
+
+ #include <asm/traps.h> /* dotraplinkage, ... */
+ #include <asm/pgalloc.h> /* pgd_*(), ... */
+ #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */
++#include <asm/vsyscall.h>
++#include <asm/tlbflush.h>
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++#include <asm/stacktrace.h>
++#endif
+
+ /*
+ * Page fault error code bits:
+@@ -53,7 +61,7 @@ static inline int __kprobes notify_page_
+ int ret = 0;
+
+ /* kprobe_running() needs smp_processor_id() */
+- if (kprobes_built_in() && !user_mode_vm(regs)) {
++ if (kprobes_built_in() && !user_mode(regs)) {
+ preempt_disable();
+ if (kprobe_running() && kprobe_fault_handler(regs, 14))
+ ret = 1;
+@@ -114,7 +122,10 @@ check_prefetch_opcode(struct pt_regs *re
+ return !instr_lo || (instr_lo>>1) == 1;
+ case 0x00:
+ /* Prefetch instruction is 0x0F0D or 0x0F18 */
+- if (probe_kernel_address(instr, opcode))
++ if (user_mode(regs)) {
++ if (__copy_from_user_inatomic(&opcode, (__force unsigned char __user *)(instr), 1))
++ return 0;
++ } else if (probe_kernel_address(instr, opcode))
+ return 0;
+
+ *prefetch = (instr_lo == 0xF) &&
+@@ -148,7 +159,10 @@ is_prefetch(struct pt_regs *regs, unsign
+ while (instr < max_instr) {
+ unsigned char opcode;
+
+- if (probe_kernel_address(instr, opcode))
++ if (user_mode(regs)) {
++ if (__copy_from_user_inatomic(&opcode, (__force unsigned char __user *)(instr), 1))
++ break;
++ } else if (probe_kernel_address(instr, opcode))
+ break;
+
+ instr++;
+@@ -179,6 +193,30 @@ force_sig_info_fault(int si_signo, int s
+ force_sig_info(si_signo, &info, tsk);
+ }
+
++#ifdef CONFIG_PAX_EMUTRAMP
++static int pax_handle_fetch_fault(struct pt_regs *regs);
++#endif
++
++#ifdef CONFIG_PAX_PAGEEXEC
++static inline pmd_t * pax_get_pmd(struct mm_struct *mm, unsigned long address)
++{
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++
++ pgd = pgd_offset(mm, address);
++ if (!pgd_present(*pgd))
++ return NULL;
++ pud = pud_offset(pgd, address);
++ if (!pud_present(*pud))
++ return NULL;
++ pmd = pmd_offset(pud, address);
++ if (!pmd_present(*pmd))
++ return NULL;
++ return pmd;
++}
++#endif
++
+ DEFINE_SPINLOCK(pgd_lock);
+ LIST_HEAD(pgd_list);
+
+@@ -229,10 +267,22 @@ void vmalloc_sync_all(void)
+ for (address = VMALLOC_START & PMD_MASK;
+ address >= TASK_SIZE && address < FIXADDR_TOP;
+ address += PMD_SIZE) {
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ unsigned long cpu;
++#else
+ struct page *page;
++#endif
+
+ spin_lock(&pgd_lock);
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
++ pgd_t *pgd = get_cpu_pgd(cpu);
++ pmd_t *ret;
++#else
+ list_for_each_entry(page, &pgd_list, lru) {
++ pgd_t *pgd = page_address(page);
+ spinlock_t *pgt_lock;
+ pmd_t *ret;
+
+@@ -240,8 +290,13 @@ void vmalloc_sync_all(void)
+ pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+
+ spin_lock(pgt_lock);
+- ret = vmalloc_sync_one(page_address(page), address);
++#endif
++
++ ret = vmalloc_sync_one(pgd, address);
++
++#ifndef CONFIG_PAX_PER_CPU_PGD
+ spin_unlock(pgt_lock);
++#endif
+
+ if (!ret)
+ break;
+@@ -275,6 +330,11 @@ static noinline __kprobes int vmalloc_fa
+ * an interrupt in the middle of a task switch..
+ */
+ pgd_paddr = read_cr3();
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ BUG_ON(__pa(get_cpu_pgd(smp_processor_id())) != (pgd_paddr & PHYSICAL_PAGE_MASK));
++#endif
++
+ pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
+ if (!pmd_k)
+ return -1;
+@@ -370,7 +430,14 @@ static noinline __kprobes int vmalloc_fa
+ * happen within a race in page table update. In the later
+ * case just flush:
+ */
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ BUG_ON(__pa(get_cpu_pgd(smp_processor_id())) != (read_cr3() & PHYSICAL_PAGE_MASK));
++ pgd = pgd_offset_cpu(smp_processor_id(), address);
++#else
+ pgd = pgd_offset(current->active_mm, address);
++#endif
++
+ pgd_ref = pgd_offset_k(address);
+ if (pgd_none(*pgd_ref))
+ return -1;
+@@ -532,7 +599,7 @@ static int is_errata93(struct pt_regs *r
+ static int is_errata100(struct pt_regs *regs, unsigned long address)
+ {
+ #ifdef CONFIG_X86_64
+- if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && (address >> 32))
++ if ((regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT)) && (address >> 32))
+ return 1;
+ #endif
+ return 0;
+@@ -559,7 +626,7 @@ static int is_f00f_bug(struct pt_regs *r
+ }
+
+ static const char nx_warning[] = KERN_CRIT
+-"kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n";
++"kernel tried to execute NX-protected page - exploit attempt? (uid: %d, task: %s, pid: %d)\n";
+
+ static void
+ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
+@@ -568,15 +635,26 @@ show_fault_oops(struct pt_regs *regs, un
+ if (!oops_may_print())
+ return;
+
+- if (error_code & PF_INSTR) {
++ if ((__supported_pte_mask & _PAGE_NX) && (error_code & PF_INSTR)) {
+ unsigned int level;
+
+ pte_t *pte = lookup_address(address, &level);
+
+ if (pte && pte_present(*pte) && !pte_exec(*pte))
+- printk(nx_warning, current_uid());
++ printk(nx_warning, current_uid(), current->comm, task_pid_nr(current));
+ }
+
++#ifdef CONFIG_PAX_KERNEXEC
++ if (init_mm.start_code <= address && address < init_mm.end_code) {
++ if (current->signal->curr_ip)
++ printk(KERN_ERR "PAX: From %pI4: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n",
++ &current->signal->curr_ip, current->comm, task_pid_nr(current), current_uid(), current_euid());
++ else
++ printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n",
++ current->comm, task_pid_nr(current), current_uid(), current_euid());
++ }
++#endif
++
+ printk(KERN_ALERT "BUG: unable to handle kernel ");
+ if (address < PAGE_SIZE)
+ printk(KERN_CONT "NULL pointer dereference");
+@@ -701,6 +779,68 @@ __bad_area_nosemaphore(struct pt_regs *r
+ unsigned long address, int si_code)
+ {
+ struct task_struct *tsk = current;
++ struct mm_struct *mm = tsk->mm;
++
++#ifdef CONFIG_X86_64
++ if (mm && (error_code & PF_INSTR) && mm->context.vdso) {
++ if (regs->ip == (unsigned long)vgettimeofday) {
++ regs->ip = (unsigned long)VDSO64_SYMBOL(mm->context.vdso, fallback_gettimeofday);
++ return;
++ } else if (regs->ip == (unsigned long)vtime) {
++ regs->ip = (unsigned long)VDSO64_SYMBOL(mm->context.vdso, fallback_time);
++ return;
++ } else if (regs->ip == (unsigned long)vgetcpu) {
++ regs->ip = (unsigned long)VDSO64_SYMBOL(mm->context.vdso, getcpu);
++ return;
++ }
++ }
++#endif
++
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++ if (mm && (error_code & PF_USER)) {
++ unsigned long ip = regs->ip;
++
++ if (v8086_mode(regs))
++ ip = ((regs->cs & 0xffff) << 4) + (ip & 0xffff);
++
++ /*
++ * It's possible to have interrupts off here:
++ */
++ local_irq_enable();
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) &&
++ (((__supported_pte_mask & _PAGE_NX) && (error_code & PF_INSTR)) || (!(error_code & (PF_PROT | PF_WRITE)) && ip == address))) {
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ switch (pax_handle_fetch_fault(regs)) {
++ case 2:
++ return;
++ }
++#endif
++
++ pax_report_fault(regs, (void *)ip, (void *)regs->sp);
++ do_group_exit(SIGKILL);
++ }
++#endif
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && !(error_code & (PF_PROT | PF_WRITE)) && (ip + SEGMEXEC_TASK_SIZE == address)) {
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ switch (pax_handle_fetch_fault(regs)) {
++ case 2:
++ return;
++ }
++#endif
++
++ pax_report_fault(regs, (void *)ip, (void *)regs->sp);
++ do_group_exit(SIGKILL);
++ }
++#endif
++
++ }
++#endif
+
+ /* User mode accesses just cause a SIGSEGV */
+ if (error_code & PF_USER) {
+@@ -855,6 +995,99 @@ static int spurious_fault_check(unsigned
+ return 1;
+ }
+
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC)
++static int pax_handle_pageexec_fault(struct pt_regs *regs, struct mm_struct *mm, unsigned long address, unsigned long error_code)
++{
++ pte_t *pte;
++ pmd_t *pmd;
++ spinlock_t *ptl;
++ unsigned char pte_mask;
++
++ if ((__supported_pte_mask & _PAGE_NX) || (error_code & (PF_PROT|PF_USER)) != (PF_PROT|PF_USER) || v8086_mode(regs) ||
++ !(mm->pax_flags & MF_PAX_PAGEEXEC))
++ return 0;
++
++ /* PaX: it's our fault, let's handle it if we can */
++
++ /* PaX: take a look at read faults before acquiring any locks */
++ if (unlikely(!(error_code & PF_WRITE) && (regs->ip == address))) {
++ /* instruction fetch attempt from a protected page in user mode */
++ up_read(&mm->mmap_sem);
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ switch (pax_handle_fetch_fault(regs)) {
++ case 2:
++ return 1;
++ }
++#endif
++
++ pax_report_fault(regs, (void *)regs->ip, (void *)regs->sp);
++ do_group_exit(SIGKILL);
++ }
++
++ pmd = pax_get_pmd(mm, address);
++ if (unlikely(!pmd))
++ return 0;
++
++ pte = pte_offset_map_lock(mm, pmd, address, &ptl);
++ if (unlikely(!(pte_val(*pte) & _PAGE_PRESENT) || pte_user(*pte))) {
++ pte_unmap_unlock(pte, ptl);
++ return 0;
++ }
++
++ if (unlikely((error_code & PF_WRITE) && !pte_write(*pte))) {
++ /* write attempt to a protected page in user mode */
++ pte_unmap_unlock(pte, ptl);
++ return 0;
++ }
++
++#ifdef CONFIG_SMP
++ if (likely(address > get_limit(regs->cs) && cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask)))
++#else
++ if (likely(address > get_limit(regs->cs)))
++#endif
++ {
++ set_pte(pte, pte_mkread(*pte));
++ __flush_tlb_one(address);
++ pte_unmap_unlock(pte, ptl);
++ up_read(&mm->mmap_sem);
++ return 1;
++ }
++
++ pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & PF_WRITE) << (_PAGE_BIT_DIRTY-1));
++
++ /*
++ * PaX: fill DTLB with user rights and retry
++ */
++ __asm__ __volatile__ (
++ "orb %2,(%1)\n"
++#if defined(CONFIG_M586) || defined(CONFIG_M586TSC)
++/*
++ * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's
++ * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any*
++ * page fault when examined during a TLB load attempt. this is true not only
++ * for PTEs holding a non-present entry but also present entries that will
++ * raise a page fault (such as those set up by PaX, or the copy-on-write
++ * mechanism). in effect it means that we do *not* need to flush the TLBs
++ * for our target pages since their PTEs are simply not in the TLBs at all.
++
++ * the best thing in omitting it is that we gain around 15-20% speed in the
++ * fast path of the page fault handler and can get rid of tracing since we
++ * can no longer flush unintended entries.
++ */
++ "invlpg (%0)\n"
++#endif
++ __copyuser_seg"testb $0,(%0)\n"
++ "xorb %3,(%1)\n"
++ :
++ : "r" (address), "r" (pte), "q" (pte_mask), "i" (_PAGE_USER)
++ : "memory", "cc");
++ pte_unmap_unlock(pte, ptl);
++ up_read(&mm->mmap_sem);
++ return 1;
++}
++#endif
++
+ /*
+ * Handle a spurious fault caused by a stale TLB entry.
+ *
+@@ -927,6 +1160,9 @@ int show_unhandled_signals = 1;
+ static inline int
+ access_error(unsigned long error_code, struct vm_area_struct *vma)
+ {
++ if ((__supported_pte_mask & _PAGE_NX) && (error_code & PF_INSTR) && !(vma->vm_flags & VM_EXEC))
++ return 1;
++
+ if (error_code & PF_WRITE) {
+ /* write, present and write, not present: */
+ if (unlikely(!(vma->vm_flags & VM_WRITE)))
+@@ -960,19 +1196,33 @@ do_page_fault(struct pt_regs *regs, unsi
+ {
+ struct vm_area_struct *vma;
+ struct task_struct *tsk;
+- unsigned long address;
+ struct mm_struct *mm;
+ int fault;
+ int write = error_code & PF_WRITE;
+ unsigned int flags = FAULT_FLAG_ALLOW_RETRY |
+ (write ? FAULT_FLAG_WRITE : 0);
+
++ /* Get the faulting address: */
++ unsigned long address = read_cr2();
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ if (!user_mode(regs) && address < 2 * PAX_USER_SHADOW_BASE) {
++ if (!search_exception_tables(regs->ip)) {
++ bad_area_nosemaphore(regs, error_code, address);
++ return;
++ }
++ if (address < PAX_USER_SHADOW_BASE) {
++ printk(KERN_ERR "PAX: please report this to pageexec@freemail.hu\n");
++ printk(KERN_ERR "PAX: faulting IP: %pA\n", (void *)regs->ip);
++ show_trace_log_lvl(NULL, NULL, (void *)regs->sp, KERN_ERR);
++ } else
++ address -= PAX_USER_SHADOW_BASE;
++ }
++#endif
++
+ tsk = current;
+ mm = tsk->mm;
+
+- /* Get the faulting address: */
+- address = read_cr2();
+-
+ /*
+ * Detect and handle instructions that would cause a page fault for
+ * both a tracked kernel page and a userspace page.
+@@ -1032,7 +1282,7 @@ do_page_fault(struct pt_regs *regs, unsi
+ * User-mode registers count as a user access even for any
+ * potential system fault or CPU buglet:
+ */
+- if (user_mode_vm(regs)) {
++ if (user_mode(regs)) {
+ local_irq_enable();
+ error_code |= PF_USER;
+ } else {
+@@ -1087,6 +1337,11 @@ retry:
+ might_sleep();
+ }
+
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC)
++ if (pax_handle_pageexec_fault(regs, mm, address, error_code))
++ return;
++#endif
++
+ vma = find_vma(mm, address);
+ if (unlikely(!vma)) {
+ bad_area(regs, error_code, address);
+@@ -1098,18 +1353,24 @@ retry:
+ bad_area(regs, error_code, address);
+ return;
+ }
+- if (error_code & PF_USER) {
+- /*
+- * Accessing the stack below %sp is always a bug.
+- * The large cushion allows instructions like enter
+- * and pusha to work. ("enter $65535, $31" pushes
+- * 32 pointers and then decrements %sp by 65535.)
+- */
+- if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
+- bad_area(regs, error_code, address);
+- return;
+- }
++ /*
++ * Accessing the stack below %sp is always a bug.
++ * The large cushion allows instructions like enter
++ * and pusha to work. ("enter $65535, $31" pushes
++ * 32 pointers and then decrements %sp by 65535.)
++ */
++ if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < task_pt_regs(tsk)->sp)) {
++ bad_area(regs, error_code, address);
++ return;
+ }
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (unlikely((mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_end - SEGMEXEC_TASK_SIZE - 1 < address - SEGMEXEC_TASK_SIZE - 1)) {
++ bad_area(regs, error_code, address);
++ return;
++ }
++#endif
++
+ if (unlikely(expand_stack(vma, address))) {
+ bad_area(regs, error_code, address);
+ return;
+@@ -1164,3 +1425,199 @@ good_area:
+
+ up_read(&mm->mmap_sem);
+ }
++
++#ifdef CONFIG_PAX_EMUTRAMP
++static int pax_handle_fetch_fault_32(struct pt_regs *regs)
++{
++ int err;
++
++ do { /* PaX: gcc trampoline emulation #1 */
++ unsigned char mov1, mov2;
++ unsigned short jmp;
++ unsigned int addr1, addr2;
++
++#ifdef CONFIG_X86_64
++ if ((regs->ip + 11) >> 32)
++ break;
++#endif
++
++ err = get_user(mov1, (unsigned char __user *)regs->ip);
++ err |= get_user(addr1, (unsigned int __user *)(regs->ip + 1));
++ err |= get_user(mov2, (unsigned char __user *)(regs->ip + 5));
++ err |= get_user(addr2, (unsigned int __user *)(regs->ip + 6));
++ err |= get_user(jmp, (unsigned short __user *)(regs->ip + 10));
++
++ if (err)
++ break;
++
++ if (mov1 == 0xB9 && mov2 == 0xB8 && jmp == 0xE0FF) {
++ regs->cx = addr1;
++ regs->ax = addr2;
++ regs->ip = addr2;
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: gcc trampoline emulation #2 */
++ unsigned char mov, jmp;
++ unsigned int addr1, addr2;
++
++#ifdef CONFIG_X86_64
++ if ((regs->ip + 9) >> 32)
++ break;
++#endif
++
++ err = get_user(mov, (unsigned char __user *)regs->ip);
++ err |= get_user(addr1, (unsigned int __user *)(regs->ip + 1));
++ err |= get_user(jmp, (unsigned char __user *)(regs->ip + 5));
++ err |= get_user(addr2, (unsigned int __user *)(regs->ip + 6));
++
++ if (err)
++ break;
++
++ if (mov == 0xB9 && jmp == 0xE9) {
++ regs->cx = addr1;
++ regs->ip = (unsigned int)(regs->ip + addr2 + 10);
++ return 2;
++ }
++ } while (0);
++
++ return 1; /* PaX in action */
++}
++
++#ifdef CONFIG_X86_64
++static int pax_handle_fetch_fault_64(struct pt_regs *regs)
++{
++ int err;
++
++ do { /* PaX: gcc trampoline emulation #1 */
++ unsigned short mov1, mov2, jmp1;
++ unsigned char jmp2;
++ unsigned int addr1;
++ unsigned long addr2;
++
++ err = get_user(mov1, (unsigned short __user *)regs->ip);
++ err |= get_user(addr1, (unsigned int __user *)(regs->ip + 2));
++ err |= get_user(mov2, (unsigned short __user *)(regs->ip + 6));
++ err |= get_user(addr2, (unsigned long __user *)(regs->ip + 8));
++ err |= get_user(jmp1, (unsigned short __user *)(regs->ip + 16));
++ err |= get_user(jmp2, (unsigned char __user *)(regs->ip + 18));
++
++ if (err)
++ break;
++
++ if (mov1 == 0xBB41 && mov2 == 0xBA49 && jmp1 == 0xFF49 && jmp2 == 0xE3) {
++ regs->r11 = addr1;
++ regs->r10 = addr2;
++ regs->ip = addr1;
++ return 2;
++ }
++ } while (0);
++
++ do { /* PaX: gcc trampoline emulation #2 */
++ unsigned short mov1, mov2, jmp1;
++ unsigned char jmp2;
++ unsigned long addr1, addr2;
++
++ err = get_user(mov1, (unsigned short __user *)regs->ip);
++ err |= get_user(addr1, (unsigned long __user *)(regs->ip + 2));
++ err |= get_user(mov2, (unsigned short __user *)(regs->ip + 10));
++ err |= get_user(addr2, (unsigned long __user *)(regs->ip + 12));
++ err |= get_user(jmp1, (unsigned short __user *)(regs->ip + 20));
++ err |= get_user(jmp2, (unsigned char __user *)(regs->ip + 22));
++
++ if (err)
++ break;
++
++ if (mov1 == 0xBB49 && mov2 == 0xBA49 && jmp1 == 0xFF49 && jmp2 == 0xE3) {
++ regs->r11 = addr1;
++ regs->r10 = addr2;
++ regs->ip = addr1;
++ return 2;
++ }
++ } while (0);
++
++ return 1; /* PaX in action */
++}
++#endif
++
++/*
++ * PaX: decide what to do with offenders (regs->ip = fault address)
++ *
++ * returns 1 when task should be killed
++ * 2 when gcc trampoline was detected
++ */
++static int pax_handle_fetch_fault(struct pt_regs *regs)
++{
++ if (v8086_mode(regs))
++ return 1;
++
++ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
++ return 1;
++
++#ifdef CONFIG_X86_32
++ return pax_handle_fetch_fault_32(regs);
++#else
++ if (regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT))
++ return pax_handle_fetch_fault_32(regs);
++ else
++ return pax_handle_fetch_fault_64(regs);
++#endif
++}
++#endif
++
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++void pax_report_insns(void *pc, void *sp)
++{
++ long i;
++
++ printk(KERN_ERR "PAX: bytes at PC: ");
++ for (i = 0; i < 20; i++) {
++ unsigned char c;
++ if (get_user(c, (__force unsigned char __user *)pc+i))
++ printk(KERN_CONT "?? ");
++ else
++ printk(KERN_CONT "%02x ", c);
++ }
++ printk("\n");
++
++ printk(KERN_ERR "PAX: bytes at SP-%lu: ", (unsigned long)sizeof(long));
++ for (i = -1; i < 80 / (long)sizeof(long); i++) {
++ unsigned long c;
++ if (get_user(c, (__force unsigned long __user *)sp+i))
++#ifdef CONFIG_X86_32
++ printk(KERN_CONT "???????? ");
++#else
++ printk(KERN_CONT "???????????????? ");
++#endif
++ else
++ printk(KERN_CONT "%0*lx ", 2 * (int)sizeof(long), c);
++ }
++ printk("\n");
++}
++#endif
++
++/**
++ * probe_kernel_write(): safely attempt to write to a location
++ * @dst: address to write to
++ * @src: pointer to the data that shall be written
++ * @size: size of the data chunk
++ *
++ * Safely write to address @dst from the buffer at @src. If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++long notrace probe_kernel_write(void *dst, const void *src, size_t size)
++{
++ long ret;
++ mm_segment_t old_fs = get_fs();
++
++ set_fs(KERNEL_DS);
++ pagefault_disable();
++ pax_open_kernel();
++ ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
++ pax_close_kernel();
++ pagefault_enable();
++ set_fs(old_fs);
++
++ return ret ? -EFAULT : 0;
++}
+diff -urNp linux-2.6.38.7/arch/x86/mm/gup.c linux-2.6.38.7/arch/x86/mm/gup.c
+--- linux-2.6.38.7/arch/x86/mm/gup.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/gup.c 2011-04-28 19:34:14.000000000 -0400
+@@ -263,7 +263,7 @@ int __get_user_pages_fast(unsigned long
+ addr = start;
+ len = (unsigned long) nr_pages << PAGE_SHIFT;
+ end = start + len;
+- if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
++ if (unlikely(!__access_ok(write ? VERIFY_WRITE : VERIFY_READ,
+ (void __user *)start, len)))
+ return 0;
+
+diff -urNp linux-2.6.38.7/arch/x86/mm/highmem_32.c linux-2.6.38.7/arch/x86/mm/highmem_32.c
+--- linux-2.6.38.7/arch/x86/mm/highmem_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/highmem_32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -44,7 +44,10 @@ void *kmap_atomic_prot(struct page *page
+ idx = type + KM_TYPE_NR*smp_processor_id();
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ BUG_ON(!pte_none(*(kmap_pte-idx)));
++
++ pax_open_kernel();
+ set_pte(kmap_pte-idx, mk_pte(page, prot));
++ pax_close_kernel();
+
+ return (void *)vaddr;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/mm/hugetlbpage.c linux-2.6.38.7/arch/x86/mm/hugetlbpage.c
+--- linux-2.6.38.7/arch/x86/mm/hugetlbpage.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/hugetlbpage.c 2011-04-28 19:34:15.000000000 -0400
+@@ -266,13 +266,20 @@ static unsigned long hugetlb_get_unmappe
+ struct hstate *h = hstate_file(file);
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+- unsigned long start_addr;
++ unsigned long start_addr, pax_task_size = TASK_SIZE;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
++ pax_task_size -= PAGE_SIZE;
+
+ if (len > mm->cached_hole_size) {
+- start_addr = mm->free_area_cache;
++ start_addr = mm->free_area_cache;
+ } else {
+- start_addr = TASK_UNMAPPED_BASE;
+- mm->cached_hole_size = 0;
++ start_addr = mm->mmap_base;
++ mm->cached_hole_size = 0;
+ }
+
+ full_search:
+@@ -280,26 +287,27 @@ full_search:
+
+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
+- if (TASK_SIZE - len < addr) {
++ if (pax_task_size - len < addr) {
+ /*
+ * Start a new search - just in case we missed
+ * some holes.
+ */
+- if (start_addr != TASK_UNMAPPED_BASE) {
+- start_addr = TASK_UNMAPPED_BASE;
++ if (start_addr != mm->mmap_base) {
++ start_addr = mm->mmap_base;
+ mm->cached_hole_size = 0;
+ goto full_search;
+ }
+ return -ENOMEM;
+ }
+- if (!vma || addr + len <= vma->vm_start) {
+- mm->free_area_cache = addr + len;
+- return addr;
+- }
++ if (check_heap_stack_gap(vma, addr, len))
++ break;
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
+ addr = ALIGN(vma->vm_end, huge_page_size(h));
+ }
++
++ mm->free_area_cache = addr + len;
++ return addr;
+ }
+
+ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
+@@ -308,10 +316,9 @@ static unsigned long hugetlb_get_unmappe
+ {
+ struct hstate *h = hstate_file(file);
+ struct mm_struct *mm = current->mm;
+- struct vm_area_struct *vma, *prev_vma;
+- unsigned long base = mm->mmap_base, addr = addr0;
++ struct vm_area_struct *vma;
++ unsigned long base = mm->mmap_base, addr;
+ unsigned long largest_hole = mm->cached_hole_size;
+- int first_time = 1;
+
+ /* don't allow allocations above current base */
+ if (mm->free_area_cache > base)
+@@ -321,64 +328,63 @@ static unsigned long hugetlb_get_unmappe
+ largest_hole = 0;
+ mm->free_area_cache = base;
+ }
+-try_again:
++
+ /* make sure it can fit in the remaining address space */
+ if (mm->free_area_cache < len)
+ goto fail;
+
+ /* either no address requested or cant fit in requested address hole */
+- addr = (mm->free_area_cache - len) & huge_page_mask(h);
++ addr = (mm->free_area_cache - len);
+ do {
++ addr &= huge_page_mask(h);
++ vma = find_vma(mm, addr);
+ /*
+ * Lookup failure means no vma is above this address,
+ * i.e. return with success:
+- */
+- if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
+- return addr;
+-
+- /*
+ * new region fits between prev_vma->vm_end and
+ * vma->vm_start, use it:
+ */
+- if (addr + len <= vma->vm_start &&
+- (!prev_vma || (addr >= prev_vma->vm_end))) {
++ if (check_heap_stack_gap(vma, addr, len)) {
+ /* remember the address as a hint for next time */
+- mm->cached_hole_size = largest_hole;
+- return (mm->free_area_cache = addr);
+- } else {
+- /* pull free_area_cache down to the first hole */
+- if (mm->free_area_cache == vma->vm_end) {
+- mm->free_area_cache = vma->vm_start;
+- mm->cached_hole_size = largest_hole;
+- }
++ mm->cached_hole_size = largest_hole;
++ return (mm->free_area_cache = addr);
++ }
++ /* pull free_area_cache down to the first hole */
++ if (mm->free_area_cache == vma->vm_end) {
++ mm->free_area_cache = vma->vm_start;
++ mm->cached_hole_size = largest_hole;
+ }
+
+ /* remember the largest hole we saw so far */
+ if (addr + largest_hole < vma->vm_start)
+- largest_hole = vma->vm_start - addr;
++ largest_hole = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+- addr = (vma->vm_start - len) & huge_page_mask(h);
+- } while (len <= vma->vm_start);
++ addr = skip_heap_stack_gap(vma, len);
++ } while (!IS_ERR_VALUE(addr));
+
+ fail:
+ /*
+- * if hint left us with no space for the requested
+- * mapping then try again:
+- */
+- if (first_time) {
+- mm->free_area_cache = base;
+- largest_hole = 0;
+- first_time = 0;
+- goto try_again;
+- }
+- /*
+ * A failed mmap() very likely causes application failure,
+ * so fall back to the bottom-up function here. This scenario
+ * can happen with large stack limits and large mmap()
+ * allocations.
+ */
+- mm->free_area_cache = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ mm->mmap_base = SEGMEXEC_TASK_UNMAPPED_BASE;
++ else
++#endif
++
++ mm->mmap_base = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
++ mm->free_area_cache = mm->mmap_base;
+ mm->cached_hole_size = ~0UL;
+ addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
+ len, pgoff, flags);
+@@ -386,6 +392,7 @@ fail:
+ /*
+ * Restore the topdown base:
+ */
++ mm->mmap_base = base;
+ mm->free_area_cache = base;
+ mm->cached_hole_size = ~0UL;
+
+@@ -399,10 +406,19 @@ hugetlb_get_unmapped_area(struct file *f
+ struct hstate *h = hstate_file(file);
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
++ unsigned long pax_task_size = TASK_SIZE;
+
+ if (len & ~huge_page_mask(h))
+ return -EINVAL;
+- if (len > TASK_SIZE)
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
++ pax_task_size -= PAGE_SIZE;
++
++ if (len > pax_task_size)
+ return -ENOMEM;
+
+ if (flags & MAP_FIXED) {
+@@ -414,8 +430,7 @@ hugetlb_get_unmapped_area(struct file *f
+ if (addr) {
+ addr = ALIGN(addr, huge_page_size(h));
+ vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
++ if (pax_task_size - len >= addr && check_heap_stack_gap(vma, addr, len))
+ return addr;
+ }
+ if (mm->get_unmapped_area == arch_get_unmapped_area)
+diff -urNp linux-2.6.38.7/arch/x86/mm/init_32.c linux-2.6.38.7/arch/x86/mm/init_32.c
+--- linux-2.6.38.7/arch/x86/mm/init_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/init_32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -74,36 +74,6 @@ static __init void *alloc_low_page(void)
+ }
+
+ /*
+- * Creates a middle page table and puts a pointer to it in the
+- * given global directory entry. This only returns the gd entry
+- * in non-PAE compilation mode, since the middle layer is folded.
+- */
+-static pmd_t * __init one_md_table_init(pgd_t *pgd)
+-{
+- pud_t *pud;
+- pmd_t *pmd_table;
+-
+-#ifdef CONFIG_X86_PAE
+- if (!(pgd_val(*pgd) & _PAGE_PRESENT)) {
+- if (after_bootmem)
+- pmd_table = (pmd_t *)alloc_bootmem_pages(PAGE_SIZE);
+- else
+- pmd_table = (pmd_t *)alloc_low_page();
+- paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+- set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+- pud = pud_offset(pgd, 0);
+- BUG_ON(pmd_table != pmd_offset(pud, 0));
+-
+- return pmd_table;
+- }
+-#endif
+- pud = pud_offset(pgd, 0);
+- pmd_table = pmd_offset(pud, 0);
+-
+- return pmd_table;
+-}
+-
+-/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry:
+ */
+@@ -123,13 +93,28 @@ static pte_t * __init one_page_table_ini
+ page_table = (pte_t *)alloc_low_page();
+
+ paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++ set_pmd(pmd, __pmd(__pa(page_table) | _KERNPG_TABLE));
++#else
+ set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
++#endif
+ BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+ }
+
+ return pte_offset_kernel(pmd, 0);
+ }
+
++static pmd_t * __init one_md_table_init(pgd_t *pgd)
++{
++ pud_t *pud;
++ pmd_t *pmd_table;
++
++ pud = pud_offset(pgd, 0);
++ pmd_table = pmd_offset(pud, 0);
++
++ return pmd_table;
++}
++
+ pmd_t * __init populate_extra_pmd(unsigned long vaddr)
+ {
+ int pgd_idx = pgd_index(vaddr);
+@@ -203,6 +188,7 @@ page_table_range_init(unsigned long star
+ int pgd_idx, pmd_idx;
+ unsigned long vaddr;
+ pgd_t *pgd;
++ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte = NULL;
+
+@@ -212,8 +198,13 @@ page_table_range_init(unsigned long star
+ pgd = pgd_base + pgd_idx;
+
+ for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
+- pmd = one_md_table_init(pgd);
+- pmd = pmd + pmd_index(vaddr);
++ pud = pud_offset(pgd, vaddr);
++ pmd = pmd_offset(pud, vaddr);
++
++#ifdef CONFIG_X86_PAE
++ paravirt_alloc_pmd(&init_mm, __pa(pmd) >> PAGE_SHIFT);
++#endif
++
+ for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end);
+ pmd++, pmd_idx++) {
+ pte = page_table_kmap_check(one_page_table_init(pmd),
+@@ -225,11 +216,20 @@ page_table_range_init(unsigned long star
+ }
+ }
+
+-static inline int is_kernel_text(unsigned long addr)
++static inline int is_kernel_text(unsigned long start, unsigned long end)
+ {
+- if (addr >= (unsigned long)_text && addr <= (unsigned long)__init_end)
+- return 1;
+- return 0;
++ if ((start > ktla_ktva((unsigned long)_etext) ||
++ end <= ktla_ktva((unsigned long)_stext)) &&
++ (start > ktla_ktva((unsigned long)_einittext) ||
++ end <= ktla_ktva((unsigned long)_sinittext)) &&
++
++#ifdef CONFIG_ACPI_SLEEP
++ (start > (unsigned long)__va(acpi_wakeup_address) + 0x4000 || end <= (unsigned long)__va(acpi_wakeup_address)) &&
++#endif
++
++ (start > (unsigned long)__va(0xfffff) || end <= (unsigned long)__va(0xc0000)))
++ return 0;
++ return 1;
+ }
+
+ /*
+@@ -246,9 +246,10 @@ kernel_physical_mapping_init(unsigned lo
+ unsigned long last_map_addr = end;
+ unsigned long start_pfn, end_pfn;
+ pgd_t *pgd_base = swapper_pg_dir;
+- int pgd_idx, pmd_idx, pte_ofs;
++ unsigned int pgd_idx, pmd_idx, pte_ofs;
+ unsigned long pfn;
+ pgd_t *pgd;
++ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned pages_2m, pages_4k;
+@@ -281,8 +282,13 @@ repeat:
+ pfn = start_pfn;
+ pgd_idx = pgd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
+ pgd = pgd_base + pgd_idx;
+- for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
+- pmd = one_md_table_init(pgd);
++ for (; pgd_idx < PTRS_PER_PGD && pfn < max_low_pfn; pgd++, pgd_idx++) {
++ pud = pud_offset(pgd, 0);
++ pmd = pmd_offset(pud, 0);
++
++#ifdef CONFIG_X86_PAE
++ paravirt_alloc_pmd(&init_mm, __pa(pmd) >> PAGE_SHIFT);
++#endif
+
+ if (pfn >= end_pfn)
+ continue;
+@@ -294,14 +300,13 @@ repeat:
+ #endif
+ for (; pmd_idx < PTRS_PER_PMD && pfn < end_pfn;
+ pmd++, pmd_idx++) {
+- unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET;
++ unsigned long address = pfn * PAGE_SIZE + PAGE_OFFSET;
+
+ /*
+ * Map with big pages if possible, otherwise
+ * create normal page tables:
+ */
+ if (use_pse) {
+- unsigned int addr2;
+ pgprot_t prot = PAGE_KERNEL_LARGE;
+ /*
+ * first pass will use the same initial
+@@ -311,11 +316,7 @@ repeat:
+ __pgprot(PTE_IDENT_ATTR |
+ _PAGE_PSE);
+
+- addr2 = (pfn + PTRS_PER_PTE-1) * PAGE_SIZE +
+- PAGE_OFFSET + PAGE_SIZE-1;
+-
+- if (is_kernel_text(addr) ||
+- is_kernel_text(addr2))
++ if (is_kernel_text(address, address + PMD_SIZE))
+ prot = PAGE_KERNEL_LARGE_EXEC;
+
+ pages_2m++;
+@@ -332,7 +333,7 @@ repeat:
+ pte_ofs = pte_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
+ pte += pte_ofs;
+ for (; pte_ofs < PTRS_PER_PTE && pfn < end_pfn;
+- pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) {
++ pte++, pfn++, pte_ofs++, address += PAGE_SIZE) {
+ pgprot_t prot = PAGE_KERNEL;
+ /*
+ * first pass will use the same initial
+@@ -340,7 +341,7 @@ repeat:
+ */
+ pgprot_t init_prot = __pgprot(PTE_IDENT_ATTR);
+
+- if (is_kernel_text(addr))
++ if (is_kernel_text(address, address + PAGE_SIZE))
+ prot = PAGE_KERNEL_EXEC;
+
+ pages_4k++;
+@@ -472,7 +473,7 @@ void __init native_pagetable_setup_start
+
+ pud = pud_offset(pgd, va);
+ pmd = pmd_offset(pud, va);
+- if (!pmd_present(*pmd))
++ if (!pmd_present(*pmd) || pmd_huge(*pmd))
+ break;
+
+ pte = pte_offset_kernel(pmd, va);
+@@ -524,12 +525,10 @@ void __init early_ioremap_page_table_ran
+
+ static void __init pagetable_init(void)
+ {
+- pgd_t *pgd_base = swapper_pg_dir;
+-
+- permanent_kmaps_init(pgd_base);
++ permanent_kmaps_init(swapper_pg_dir);
+ }
+
+-pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
++pteval_t __supported_pte_mask __read_only = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
+ EXPORT_SYMBOL_GPL(__supported_pte_mask);
+
+ /* user-defined highmem size */
+@@ -755,6 +754,12 @@ void __init mem_init(void)
+
+ pci_iommu_alloc();
+
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ clone_pgd_range(get_cpu_pgd(0) + KERNEL_PGD_BOUNDARY,
++ swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++ KERNEL_PGD_PTRS);
++#endif
++
+ #ifdef CONFIG_FLATMEM
+ BUG_ON(!mem_map);
+ #endif
+@@ -772,7 +777,7 @@ void __init mem_init(void)
+ set_highmem_pages_init();
+
+ codesize = (unsigned long) &_etext - (unsigned long) &_text;
+- datasize = (unsigned long) &_edata - (unsigned long) &_etext;
++ datasize = (unsigned long) &_edata - (unsigned long) &_sdata;
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+ printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
+@@ -813,10 +818,10 @@ void __init mem_init(void)
+ ((unsigned long)&__init_end -
+ (unsigned long)&__init_begin) >> 10,
+
+- (unsigned long)&_etext, (unsigned long)&_edata,
+- ((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
++ (unsigned long)&_sdata, (unsigned long)&_edata,
++ ((unsigned long)&_edata - (unsigned long)&_sdata) >> 10,
+
+- (unsigned long)&_text, (unsigned long)&_etext,
++ ktla_ktva((unsigned long)&_text), ktla_ktva((unsigned long)&_etext),
+ ((unsigned long)&_etext - (unsigned long)&_text) >> 10);
+
+ /*
+@@ -894,6 +899,7 @@ void set_kernel_text_rw(void)
+ if (!kernel_set_to_readonly)
+ return;
+
++ start = ktla_ktva(start);
+ pr_debug("Set kernel text: %lx - %lx for read write\n",
+ start, start+size);
+
+@@ -908,6 +914,7 @@ void set_kernel_text_ro(void)
+ if (!kernel_set_to_readonly)
+ return;
+
++ start = ktla_ktva(start);
+ pr_debug("Set kernel text: %lx - %lx for read only\n",
+ start, start+size);
+
+@@ -936,6 +943,7 @@ void mark_rodata_ro(void)
+ unsigned long start = PFN_ALIGN(_text);
+ unsigned long size = PFN_ALIGN(_etext) - start;
+
++ start = ktla_ktva(start);
+ set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+ printk(KERN_INFO "Write protecting the kernel text: %luk\n",
+ size >> 10);
+diff -urNp linux-2.6.38.7/arch/x86/mm/init_64.c linux-2.6.38.7/arch/x86/mm/init_64.c
+--- linux-2.6.38.7/arch/x86/mm/init_64.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/init_64.c 2011-04-28 19:34:15.000000000 -0400
+@@ -72,7 +72,7 @@ early_param("gbpages", parse_direct_gbpa
+ * around without checking the pgd every time.
+ */
+
+-pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP;
++pteval_t __supported_pte_mask __read_only = ~(_PAGE_NX | _PAGE_IOMAP);
+ EXPORT_SYMBOL_GPL(__supported_pte_mask);
+
+ int force_personality32;
+@@ -105,12 +105,22 @@ void sync_global_pgds(unsigned long star
+
+ for (address = start; address <= end; address += PGDIR_SIZE) {
+ const pgd_t *pgd_ref = pgd_offset_k(address);
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ unsigned long cpu;
++#else
+ struct page *page;
++#endif
+
+ if (pgd_none(*pgd_ref))
+ continue;
+
+ spin_lock(&pgd_lock);
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
++ pgd_t *pgd = pgd_offset_cpu(cpu, address);
++#else
+ list_for_each_entry(page, &pgd_list, lru) {
+ pgd_t *pgd;
+ spinlock_t *pgt_lock;
+@@ -119,6 +129,7 @@ void sync_global_pgds(unsigned long star
+ /* the pgt_lock only for Xen */
+ pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+ spin_lock(pgt_lock);
++#endif
+
+ if (pgd_none(*pgd))
+ set_pgd(pgd, *pgd_ref);
+@@ -126,7 +137,10 @@ void sync_global_pgds(unsigned long star
+ BUG_ON(pgd_page_vaddr(*pgd)
+ != pgd_page_vaddr(*pgd_ref));
+
++#ifndef CONFIG_PAX_PER_CPU_PGD
+ spin_unlock(pgt_lock);
++#endif
++
+ }
+ spin_unlock(&pgd_lock);
+ }
+@@ -200,7 +214,9 @@ void set_pte_vaddr_pud(pud_t *pud_page,
+ pmd = fill_pmd(pud, vaddr);
+ pte = fill_pte(pmd, vaddr);
+
++ pax_open_kernel();
+ set_pte(pte, new_pte);
++ pax_close_kernel();
+
+ /*
+ * It's enough to flush this one mapping.
+@@ -259,14 +275,12 @@ static void __init __init_extra_mapping(
+ pgd = pgd_offset_k((unsigned long)__va(phys));
+ if (pgd_none(*pgd)) {
+ pud = (pud_t *) spp_getpage();
+- set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE |
+- _PAGE_USER));
++ set_pgd(pgd, __pgd(__pa(pud) | _PAGE_TABLE));
+ }
+ pud = pud_offset(pgd, (unsigned long)__va(phys));
+ if (pud_none(*pud)) {
+ pmd = (pmd_t *) spp_getpage();
+- set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE |
+- _PAGE_USER));
++ set_pud(pud, __pud(__pa(pmd) | _PAGE_TABLE));
+ }
+ pmd = pmd_offset(pud, phys);
+ BUG_ON(!pmd_none(*pmd));
+@@ -706,6 +720,12 @@ void __init mem_init(void)
+
+ pci_iommu_alloc();
+
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ clone_pgd_range(get_cpu_pgd(0) + KERNEL_PGD_BOUNDARY,
++ swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++ KERNEL_PGD_PTRS);
++#endif
++
+ /* clear_bss() already clear the empty_zero_page */
+
+ reservedpages = 0;
+@@ -866,8 +886,8 @@ int kern_addr_valid(unsigned long addr)
+ static struct vm_area_struct gate_vma = {
+ .vm_start = VSYSCALL_START,
+ .vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE),
+- .vm_page_prot = PAGE_READONLY_EXEC,
+- .vm_flags = VM_READ | VM_EXEC
++ .vm_page_prot = PAGE_READONLY,
++ .vm_flags = VM_READ
+ };
+
+ struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+@@ -901,7 +921,7 @@ int in_gate_area_no_task(unsigned long a
+
+ const char *arch_vma_name(struct vm_area_struct *vma)
+ {
+- if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
++ if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso)
+ return "[vdso]";
+ if (vma == &gate_vma)
+ return "[vsyscall]";
+diff -urNp linux-2.6.38.7/arch/x86/mm/init.c linux-2.6.38.7/arch/x86/mm/init.c
+--- linux-2.6.38.7/arch/x86/mm/init.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/init.c 2011-04-28 19:34:15.000000000 -0400
+@@ -72,11 +72,7 @@ static void __init find_early_table_spac
+ * cause a hotspot and fill up ZONE_DMA. The page tables
+ * need roughly 0.5KB per GB.
+ */
+-#ifdef CONFIG_X86_32
+- start = 0x7000;
+-#else
+- start = 0x8000;
+-#endif
++ start = 0x100000;
+ base = memblock_find_in_range(start, max_pfn_mapped<<PAGE_SHIFT,
+ tables, PAGE_SIZE);
+ if (base == MEMBLOCK_ERROR)
+@@ -323,7 +319,16 @@ unsigned long __init_refok init_memory_m
+ */
+ int devmem_is_allowed(unsigned long pagenr)
+ {
+- if (pagenr <= 256)
++#ifndef CONFIG_GRKERNSEC_KMEM
++ if (!pagenr)
++ return 1;
++#ifdef CONFIG_VM86
++ if (pagenr < (ISA_START_ADDRESS >> PAGE_SHIFT))
++ return 1;
++#endif
++#endif
++
++ if ((ISA_START_ADDRESS >> PAGE_SHIFT) <= pagenr && pagenr < (ISA_END_ADDRESS >> PAGE_SHIFT))
+ return 1;
+ if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+ return 0;
+@@ -383,6 +388,86 @@ void free_init_pages(char *what, unsigne
+
+ void free_initmem(void)
+ {
++
++#ifdef CONFIG_PAX_KERNEXEC
++#ifdef CONFIG_X86_32
++ /* PaX: limit KERNEL_CS to actual size */
++ unsigned long addr, limit;
++ struct desc_struct d;
++ int cpu;
++
++ limit = paravirt_enabled() ? ktva_ktla(0xffffffff) : (unsigned long)&_etext;
++ limit = (limit - 1UL) >> PAGE_SHIFT;
++
++ memset(__LOAD_PHYSICAL_ADDR + PAGE_OFFSET, POISON_FREE_INITMEM, PAGE_SIZE);
++ for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ pack_descriptor(&d, get_desc_base(&get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS]), limit, 0x9B, 0xC);
++ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_KERNEL_CS, &d, DESCTYPE_S);
++ }
++
++ /* PaX: make KERNEL_CS read-only */
++ addr = PFN_ALIGN(ktla_ktva((unsigned long)&_text));
++ if (!paravirt_enabled())
++ set_memory_ro(addr, (PFN_ALIGN(_sdata) - addr) >> PAGE_SHIFT);
++/*
++ for (addr = ktla_ktva((unsigned long)&_text); addr < (unsigned long)&_sdata; addr += PMD_SIZE) {
++ pgd = pgd_offset_k(addr);
++ pud = pud_offset(pgd, addr);
++ pmd = pmd_offset(pud, addr);
++ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW));
++ }
++*/
++#ifdef CONFIG_X86_PAE
++ set_memory_nx(PFN_ALIGN(__init_begin), (PFN_ALIGN(__init_end) - PFN_ALIGN(__init_begin)) >> PAGE_SHIFT);
++/*
++ for (addr = (unsigned long)&__init_begin; addr < (unsigned long)&__init_end; addr += PMD_SIZE) {
++ pgd = pgd_offset_k(addr);
++ pud = pud_offset(pgd, addr);
++ pmd = pmd_offset(pud, addr);
++ set_pmd(pmd, __pmd(pmd_val(*pmd) | (_PAGE_NX & __supported_pte_mask)));
++ }
++*/
++#endif
++
++#ifdef CONFIG_MODULES
++ set_memory_4k((unsigned long)MODULES_EXEC_VADDR, (MODULES_EXEC_END - MODULES_EXEC_VADDR) >> PAGE_SHIFT);
++#endif
++
++#else
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++ unsigned long addr, end;
++
++ /* PaX: make kernel code/rodata read-only, rest non-executable */
++ for (addr = __START_KERNEL_map; addr < __START_KERNEL_map + KERNEL_IMAGE_SIZE; addr += PMD_SIZE) {
++ pgd = pgd_offset_k(addr);
++ pud = pud_offset(pgd, addr);
++ pmd = pmd_offset(pud, addr);
++ if (!pmd_present(*pmd))
++ continue;
++ if ((unsigned long)_text <= addr && addr < (unsigned long)_sdata)
++ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW));
++ else
++ set_pmd(pmd, __pmd(pmd_val(*pmd) | (_PAGE_NX & __supported_pte_mask)));
++ }
++
++ addr = (unsigned long)__va(__pa(__START_KERNEL_map));
++ end = addr + KERNEL_IMAGE_SIZE;
++ for (; addr < end; addr += PMD_SIZE) {
++ pgd = pgd_offset_k(addr);
++ pud = pud_offset(pgd, addr);
++ pmd = pmd_offset(pud, addr);
++ if (!pmd_present(*pmd))
++ continue;
++ if ((unsigned long)__va(__pa(_text)) <= addr && addr < (unsigned long)__va(__pa(_sdata)))
++ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW));
++ }
++#endif
++
++ flush_tlb_all();
++#endif
++
+ free_init_pages("unused kernel memory",
+ (unsigned long)(&__init_begin),
+ (unsigned long)(&__init_end));
+diff -urNp linux-2.6.38.7/arch/x86/mm/iomap_32.c linux-2.6.38.7/arch/x86/mm/iomap_32.c
+--- linux-2.6.38.7/arch/x86/mm/iomap_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/iomap_32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -64,7 +64,11 @@ void *kmap_atomic_prot_pfn(unsigned long
+ type = kmap_atomic_idx_push();
+ idx = type + KM_TYPE_NR * smp_processor_id();
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++
++ pax_open_kernel();
+ set_pte(kmap_pte - idx, pfn_pte(pfn, prot));
++ pax_close_kernel();
++
+ arch_flush_lazy_mmu_mode();
+
+ return (void *)vaddr;
+diff -urNp linux-2.6.38.7/arch/x86/mm/ioremap.c linux-2.6.38.7/arch/x86/mm/ioremap.c
+--- linux-2.6.38.7/arch/x86/mm/ioremap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/ioremap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -104,7 +104,7 @@ static void __iomem *__ioremap_caller(re
+ for (pfn = phys_addr >> PAGE_SHIFT; pfn <= last_pfn; pfn++) {
+ int is_ram = page_is_ram(pfn);
+
+- if (is_ram && pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))
++ if (is_ram && pfn_valid(pfn) && (pfn >= 0x100 || !PageReserved(pfn_to_page(pfn))))
+ return NULL;
+ WARN_ON_ONCE(is_ram);
+ }
+@@ -344,7 +344,7 @@ static int __init early_ioremap_debug_se
+ early_param("early_ioremap_debug", early_ioremap_debug_setup);
+
+ static __initdata int after_paging_init;
+-static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
++static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __read_only __aligned(PAGE_SIZE);
+
+ static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+ {
+@@ -381,8 +381,7 @@ void __init early_ioremap_init(void)
+ slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
+
+ pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+- memset(bm_pte, 0, sizeof(bm_pte));
+- pmd_populate_kernel(&init_mm, pmd, bm_pte);
++ pmd_populate_user(&init_mm, pmd, bm_pte);
+
+ /*
+ * The boot-ioremap range spans multiple pmds, for which
+diff -urNp linux-2.6.38.7/arch/x86/mm/kmemcheck/kmemcheck.c linux-2.6.38.7/arch/x86/mm/kmemcheck/kmemcheck.c
+--- linux-2.6.38.7/arch/x86/mm/kmemcheck/kmemcheck.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/kmemcheck/kmemcheck.c 2011-04-28 19:34:15.000000000 -0400
+@@ -622,9 +622,9 @@ bool kmemcheck_fault(struct pt_regs *reg
+ * memory (e.g. tracked pages)? For now, we need this to avoid
+ * invoking kmemcheck for PnP BIOS calls.
+ */
+- if (regs->flags & X86_VM_MASK)
++ if (v8086_mode(regs))
+ return false;
+- if (regs->cs != __KERNEL_CS)
++ if (regs->cs != __KERNEL_CS && regs->cs != __KERNEXEC_KERNEL_CS)
+ return false;
+
+ pte = kmemcheck_pte_lookup(address);
+diff -urNp linux-2.6.38.7/arch/x86/mm/mmap.c linux-2.6.38.7/arch/x86/mm/mmap.c
+--- linux-2.6.38.7/arch/x86/mm/mmap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/mmap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -49,7 +49,7 @@ static unsigned int stack_maxrandom_size
+ * Leave an at least ~128 MB hole with possible stack randomization.
+ */
+ #define MIN_GAP (128*1024*1024UL + stack_maxrandom_size())
+-#define MAX_GAP (TASK_SIZE/6*5)
++#define MAX_GAP (pax_task_size/6*5)
+
+ /*
+ * True on X86_32 or when emulating IA32 on X86_64
+@@ -94,27 +94,40 @@ static unsigned long mmap_rnd(void)
+ return rnd << PAGE_SHIFT;
+ }
+
+-static unsigned long mmap_base(void)
++static unsigned long mmap_base(struct mm_struct *mm)
+ {
+ unsigned long gap = rlimit(RLIMIT_STACK);
++ unsigned long pax_task_size = TASK_SIZE;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
+
+ if (gap < MIN_GAP)
+ gap = MIN_GAP;
+ else if (gap > MAX_GAP)
+ gap = MAX_GAP;
+
+- return PAGE_ALIGN(TASK_SIZE - gap - mmap_rnd());
++ return PAGE_ALIGN(pax_task_size - gap - mmap_rnd());
+ }
+
+ /*
+ * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
+ * does, but not when emulating X86_32
+ */
+-static unsigned long mmap_legacy_base(void)
++static unsigned long mmap_legacy_base(struct mm_struct *mm)
+ {
+- if (mmap_is_ia32())
++ if (mmap_is_ia32()) {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ return SEGMEXEC_TASK_UNMAPPED_BASE;
++ else
++#endif
++
+ return TASK_UNMAPPED_BASE;
+- else
++ } else
+ return TASK_UNMAPPED_BASE + mmap_rnd();
+ }
+
+@@ -125,11 +138,23 @@ static unsigned long mmap_legacy_base(vo
+ void arch_pick_mmap_layout(struct mm_struct *mm)
+ {
+ if (mmap_is_legacy()) {
+- mm->mmap_base = mmap_legacy_base();
++ mm->mmap_base = mmap_legacy_base(mm);
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+- mm->mmap_base = mmap_base();
++ mm->mmap_base = mmap_base(mm);
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/mm/mmio-mod.c linux-2.6.38.7/arch/x86/mm/mmio-mod.c
+--- linux-2.6.38.7/arch/x86/mm/mmio-mod.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/mmio-mod.c 2011-04-28 19:57:25.000000000 -0400
+@@ -235,7 +235,7 @@ static void post(struct kmmio_probe *p,
+ static void ioremap_trace_core(resource_size_t offset, unsigned long size,
+ void __iomem *addr)
+ {
+- static atomic_t next_id;
++ static atomic_unchecked_t next_id;
+ struct remap_trace *trace = kmalloc(sizeof(*trace), GFP_KERNEL);
+ /* These are page-unaligned. */
+ struct mmiotrace_map map = {
+@@ -259,7 +259,7 @@ static void ioremap_trace_core(resource_
+ .private = trace
+ },
+ .phys = offset,
+- .id = atomic_inc_return(&next_id)
++ .id = atomic_inc_return_unchecked(&next_id)
+ };
+ map.map_id = trace->id;
+
+diff -urNp linux-2.6.38.7/arch/x86/mm/numa_32.c linux-2.6.38.7/arch/x86/mm/numa_32.c
+--- linux-2.6.38.7/arch/x86/mm/numa_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/numa_32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -99,7 +99,6 @@ unsigned long node_memmap_size_bytes(int
+ }
+ #endif
+
+-extern unsigned long find_max_low_pfn(void);
+ extern unsigned long highend_pfn, highstart_pfn;
+
+ #define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE)
+diff -urNp linux-2.6.38.7/arch/x86/mm/pageattr.c linux-2.6.38.7/arch/x86/mm/pageattr.c
+--- linux-2.6.38.7/arch/x86/mm/pageattr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/pageattr.c 2011-04-28 19:34:15.000000000 -0400
+@@ -261,7 +261,7 @@ static inline pgprot_t static_protection
+ */
+ #ifdef CONFIG_PCI_BIOS
+ if (pcibios_enabled && within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT))
+- pgprot_val(forbidden) |= _PAGE_NX;
++ pgprot_val(forbidden) |= _PAGE_NX & __supported_pte_mask;
+ #endif
+
+ /*
+@@ -269,9 +269,10 @@ static inline pgprot_t static_protection
+ * Does not cover __inittext since that is gone later on. On
+ * 64bit we do not enforce !NX on the low mapping
+ */
+- if (within(address, (unsigned long)_text, (unsigned long)_etext))
+- pgprot_val(forbidden) |= _PAGE_NX;
++ if (within(address, ktla_ktva((unsigned long)_text), ktla_ktva((unsigned long)_etext)))
++ pgprot_val(forbidden) |= _PAGE_NX & __supported_pte_mask;
+
++#ifdef CONFIG_DEBUG_RODATA
+ /*
+ * The .rodata section needs to be read-only. Using the pfn
+ * catches all aliases.
+@@ -279,6 +280,7 @@ static inline pgprot_t static_protection
+ if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT,
+ __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
+ pgprot_val(forbidden) |= _PAGE_RW;
++#endif
+
+ #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
+ /*
+@@ -317,6 +319,13 @@ static inline pgprot_t static_protection
+ }
+ #endif
+
++#ifdef CONFIG_PAX_KERNEXEC
++ if (within(pfn, __pa((unsigned long)&_text), __pa((unsigned long)&_sdata))) {
++ pgprot_val(forbidden) |= _PAGE_RW;
++ pgprot_val(forbidden) |= _PAGE_NX & __supported_pte_mask;
++ }
++#endif
++
+ prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
+
+ return prot;
+@@ -369,23 +378,37 @@ EXPORT_SYMBOL_GPL(lookup_address);
+ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
+ {
+ /* change init_mm */
++ pax_open_kernel();
+ set_pte_atomic(kpte, pte);
++
+ #ifdef CONFIG_X86_32
+ if (!SHARED_KERNEL_PMD) {
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ unsigned long cpu;
++#else
+ struct page *page;
++#endif
+
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ for (cpu = 0; cpu < NR_CPUS; ++cpu) {
++ pgd_t *pgd = get_cpu_pgd(cpu);
++#else
+ list_for_each_entry(page, &pgd_list, lru) {
+- pgd_t *pgd;
++ pgd_t *pgd = (pgd_t *)page_address(page);
++#endif
++
+ pud_t *pud;
+ pmd_t *pmd;
+
+- pgd = (pgd_t *)page_address(page) + pgd_index(address);
++ pgd += pgd_index(address);
+ pud = pud_offset(pgd, address);
+ pmd = pmd_offset(pud, address);
+ set_pte_atomic((pte_t *)pmd, pte);
+ }
+ }
+ #endif
++ pax_close_kernel();
+ }
+
+ static int
+diff -urNp linux-2.6.38.7/arch/x86/mm/pageattr-test.c linux-2.6.38.7/arch/x86/mm/pageattr-test.c
+--- linux-2.6.38.7/arch/x86/mm/pageattr-test.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/pageattr-test.c 2011-04-28 19:34:15.000000000 -0400
+@@ -36,7 +36,7 @@ enum {
+
+ static int pte_testbit(pte_t pte)
+ {
+- return pte_flags(pte) & _PAGE_UNUSED1;
++ return pte_flags(pte) & _PAGE_CPA_TEST;
+ }
+
+ struct split_state {
+diff -urNp linux-2.6.38.7/arch/x86/mm/pat.c linux-2.6.38.7/arch/x86/mm/pat.c
+--- linux-2.6.38.7/arch/x86/mm/pat.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/pat.c 2011-04-28 19:34:15.000000000 -0400
+@@ -361,7 +361,7 @@ int free_memtype(u64 start, u64 end)
+
+ if (!entry) {
+ printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
+- current->comm, current->pid, start, end);
++ current->comm, task_pid_nr(current), start, end);
+ return -EINVAL;
+ }
+
+@@ -492,8 +492,8 @@ static inline int range_is_allowed(unsig
+ while (cursor < to) {
+ if (!devmem_is_allowed(pfn)) {
+ printk(KERN_INFO
+- "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
+- current->comm, from, to);
++ "Program %s tried to access /dev/mem between %Lx->%Lx (%Lx).\n",
++ current->comm, from, to, cursor);
+ return 0;
+ }
+ cursor += PAGE_SIZE;
+@@ -557,7 +557,7 @@ int kernel_map_sync_memtype(u64 base, un
+ printk(KERN_INFO
+ "%s:%d ioremap_change_attr failed %s "
+ "for %Lx-%Lx\n",
+- current->comm, current->pid,
++ current->comm, task_pid_nr(current),
+ cattr_name(flags),
+ base, (unsigned long long)(base + size));
+ return -EINVAL;
+@@ -593,7 +593,7 @@ static int reserve_pfn_range(u64 paddr,
+ if (want_flags != flags) {
+ printk(KERN_WARNING
+ "%s:%d map pfn RAM range req %s for %Lx-%Lx, got %s\n",
+- current->comm, current->pid,
++ current->comm, task_pid_nr(current),
+ cattr_name(want_flags),
+ (unsigned long long)paddr,
+ (unsigned long long)(paddr + size),
+@@ -615,7 +615,7 @@ static int reserve_pfn_range(u64 paddr,
+ free_memtype(paddr, paddr + size);
+ printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
+ " for %Lx-%Lx, got %s\n",
+- current->comm, current->pid,
++ current->comm, task_pid_nr(current),
+ cattr_name(want_flags),
+ (unsigned long long)paddr,
+ (unsigned long long)(paddr + size),
+diff -urNp linux-2.6.38.7/arch/x86/mm/pgtable_32.c linux-2.6.38.7/arch/x86/mm/pgtable_32.c
+--- linux-2.6.38.7/arch/x86/mm/pgtable_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/pgtable_32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -48,10 +48,13 @@ void set_pte_vaddr(unsigned long vaddr,
+ return;
+ }
+ pte = pte_offset_kernel(pmd, vaddr);
++
++ pax_open_kernel();
+ if (pte_val(pteval))
+ set_pte_at(&init_mm, vaddr, pte, pteval);
+ else
+ pte_clear(&init_mm, vaddr, pte);
++ pax_close_kernel();
+
+ /*
+ * It's enough to flush this one mapping.
+diff -urNp linux-2.6.38.7/arch/x86/mm/pgtable.c linux-2.6.38.7/arch/x86/mm/pgtable.c
+--- linux-2.6.38.7/arch/x86/mm/pgtable.c 2011-04-18 17:27:13.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/pgtable.c 2011-05-11 18:34:57.000000000 -0400
+@@ -84,10 +84,52 @@ static inline void pgd_list_del(pgd_t *p
+ list_del(&page->lru);
+ }
+
+-#define UNSHARED_PTRS_PER_PGD \
+- (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++pgdval_t clone_pgd_mask __read_only = ~_PAGE_PRESENT;
+
++void __shadow_user_pgds(pgd_t *dst, const pgd_t *src, int count)
++{
++ while (count--)
++ *dst++ = __pgd((pgd_val(*src++) | (_PAGE_NX & __supported_pte_mask)) & ~_PAGE_USER);
++}
++#endif
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++void __clone_user_pgds(pgd_t *dst, const pgd_t *src, int count)
++{
++ while (count--)
++
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++ *dst++ = __pgd(pgd_val(*src++) & clone_pgd_mask);
++#else
++ *dst++ = *src++;
++#endif
+
++}
++#endif
++
++#ifdef CONFIG_X86_64
++#define pxd_t pud_t
++#define pyd_t pgd_t
++#define paravirt_release_pxd(pfn) paravirt_release_pud(pfn)
++#define pxd_free(mm, pud) pud_free((mm), (pud))
++#define pyd_populate(mm, pgd, pud) pgd_populate((mm), (pgd), (pud))
++#define pyd_offset(mm ,address) pgd_offset((mm), (address))
++#define PYD_SIZE PGDIR_SIZE
++#else
++#define pxd_t pmd_t
++#define pyd_t pud_t
++#define paravirt_release_pxd(pfn) paravirt_release_pmd(pfn)
++#define pxd_free(mm, pud) pmd_free((mm), (pud))
++#define pyd_populate(mm, pgd, pud) pud_populate((mm), (pgd), (pud))
++#define pyd_offset(mm ,address) pud_offset((mm), (address))
++#define PYD_SIZE PUD_SIZE
++#endif
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++static inline void pgd_ctor(struct mm_struct *mm, pgd_t *pgd) {}
++static inline void pgd_dtor(pgd_t *pgd) {}
++#else
+ static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)
+ {
+ BUILD_BUG_ON(sizeof(virt_to_page(pgd)->index) < sizeof(mm));
+@@ -128,6 +170,7 @@ static void pgd_dtor(pgd_t *pgd)
+ pgd_list_del(pgd);
+ spin_unlock(&pgd_lock);
+ }
++#endif
+
+ /*
+ * List of all pgd's needed for non-PAE so it can invalidate entries
+@@ -140,7 +183,7 @@ static void pgd_dtor(pgd_t *pgd)
+ * -- wli
+ */
+
+-#ifdef CONFIG_X86_PAE
++#if defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE)
+ /*
+ * In PAE mode, we need to do a cr3 reload (=tlb flush) when
+ * updating the top-level pagetable entries to guarantee the
+@@ -152,7 +195,7 @@ static void pgd_dtor(pgd_t *pgd)
+ * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
+ * and initialize the kernel pmds here.
+ */
+-#define PREALLOCATED_PMDS UNSHARED_PTRS_PER_PGD
++#define PREALLOCATED_PXDS (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
+
+ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
+ {
+@@ -170,36 +213,38 @@ void pud_populate(struct mm_struct *mm,
+ */
+ flush_tlb_mm(mm);
+ }
++#elif defined(CONFIG_X86_64) && defined(CONFIG_PAX_PER_CPU_PGD)
++#define PREALLOCATED_PXDS USER_PGD_PTRS
+ #else /* !CONFIG_X86_PAE */
+
+ /* No need to prepopulate any pagetable entries in non-PAE modes. */
+-#define PREALLOCATED_PMDS 0
++#define PREALLOCATED_PXDS 0
+
+ #endif /* CONFIG_X86_PAE */
+
+-static void free_pmds(pmd_t *pmds[])
++static void free_pxds(pxd_t *pxds[])
+ {
+ int i;
+
+- for(i = 0; i < PREALLOCATED_PMDS; i++)
+- if (pmds[i])
+- free_page((unsigned long)pmds[i]);
++ for(i = 0; i < PREALLOCATED_PXDS; i++)
++ if (pxds[i])
++ free_page((unsigned long)pxds[i]);
+ }
+
+-static int preallocate_pmds(pmd_t *pmds[])
++static int preallocate_pxds(pxd_t *pxds[])
+ {
+ int i;
+ bool failed = false;
+
+- for(i = 0; i < PREALLOCATED_PMDS; i++) {
+- pmd_t *pmd = (pmd_t *)__get_free_page(PGALLOC_GFP);
+- if (pmd == NULL)
++ for(i = 0; i < PREALLOCATED_PXDS; i++) {
++ pxd_t *pxd = (pxd_t *)__get_free_page(PGALLOC_GFP);
++ if (pxd == NULL)
+ failed = true;
+- pmds[i] = pmd;
++ pxds[i] = pxd;
+ }
+
+ if (failed) {
+- free_pmds(pmds);
++ free_pxds(pxds);
+ return -ENOMEM;
+ }
+
+@@ -212,51 +257,55 @@ static int preallocate_pmds(pmd_t *pmds[
+ * preallocate which never got a corresponding vma will need to be
+ * freed manually.
+ */
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
++static void pgd_mop_up_pxds(struct mm_struct *mm, pgd_t *pgdp)
+ {
+ int i;
+
+- for(i = 0; i < PREALLOCATED_PMDS; i++) {
++ for(i = 0; i < PREALLOCATED_PXDS; i++) {
+ pgd_t pgd = pgdp[i];
+
+ if (pgd_val(pgd) != 0) {
+- pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
++ pxd_t *pxd = (pxd_t *)pgd_page_vaddr(pgd);
+
+- pgdp[i] = native_make_pgd(0);
++ set_pgd(pgdp + i, native_make_pgd(0));
+
+- paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
+- pmd_free(mm, pmd);
++ paravirt_release_pxd(pgd_val(pgd) >> PAGE_SHIFT);
++ pxd_free(mm, pxd);
+ }
+ }
+ }
+
+-static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[])
++static void pgd_prepopulate_pxd(struct mm_struct *mm, pgd_t *pgd, pxd_t *pxds[])
+ {
+- pud_t *pud;
++ pyd_t *pyd;
+ unsigned long addr;
+ int i;
+
+- if (PREALLOCATED_PMDS == 0) /* Work around gcc-3.4.x bug */
++ if (PREALLOCATED_PXDS == 0) /* Work around gcc-3.4.x bug */
+ return;
+
+- pud = pud_offset(pgd, 0);
++#ifdef CONFIG_X86_64
++ pyd = pyd_offset(mm, 0L);
++#else
++ pyd = pyd_offset(pgd, 0L);
++#endif
+
+- for (addr = i = 0; i < PREALLOCATED_PMDS;
+- i++, pud++, addr += PUD_SIZE) {
+- pmd_t *pmd = pmds[i];
++ for (addr = i = 0; i < PREALLOCATED_PXDS;
++ i++, pyd++, addr += PYD_SIZE) {
++ pxd_t *pxd = pxds[i];
+
+ if (i >= KERNEL_PGD_BOUNDARY)
+- memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
+- sizeof(pmd_t) * PTRS_PER_PMD);
++ memcpy(pxd, (pxd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
++ sizeof(pxd_t) * PTRS_PER_PMD);
+
+- pud_populate(mm, pud, pmd);
++ pyd_populate(mm, pyd, pxd);
+ }
+ }
+
+ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+ pgd_t *pgd;
+- pmd_t *pmds[PREALLOCATED_PMDS];
++ pxd_t *pxds[PREALLOCATED_PXDS];
+
+ pgd = (pgd_t *)__get_free_page(PGALLOC_GFP);
+
+@@ -265,11 +314,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+
+ mm->pgd = pgd;
+
+- if (preallocate_pmds(pmds) != 0)
++ if (preallocate_pxds(pxds) != 0)
+ goto out_free_pgd;
+
+ if (paravirt_pgd_alloc(mm) != 0)
+- goto out_free_pmds;
++ goto out_free_pxds;
+
+ /*
+ * Make sure that pre-populating the pmds is atomic with
+@@ -279,14 +328,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ spin_lock(&pgd_lock);
+
+ pgd_ctor(mm, pgd);
+- pgd_prepopulate_pmd(mm, pgd, pmds);
++ pgd_prepopulate_pxd(mm, pgd, pxds);
+
+ spin_unlock(&pgd_lock);
+
+ return pgd;
+
+-out_free_pmds:
+- free_pmds(pmds);
++out_free_pxds:
++ free_pxds(pxds);
+ out_free_pgd:
+ free_page((unsigned long)pgd);
+ out:
+@@ -295,7 +344,7 @@ out:
+
+ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+- pgd_mop_up_pmds(mm, pgd);
++ pgd_mop_up_pxds(mm, pgd);
+ pgd_dtor(pgd);
+ paravirt_pgd_free(mm, pgd);
+ free_page((unsigned long)pgd);
+diff -urNp linux-2.6.38.7/arch/x86/mm/setup_nx.c linux-2.6.38.7/arch/x86/mm/setup_nx.c
+--- linux-2.6.38.7/arch/x86/mm/setup_nx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/setup_nx.c 2011-04-28 19:34:15.000000000 -0400
+@@ -5,8 +5,10 @@
+ #include <asm/pgtable.h>
+ #include <asm/proto.h>
+
++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+ static int disable_nx __cpuinitdata;
+
++#ifndef CONFIG_PAX_PAGEEXEC
+ /*
+ * noexec = on|off
+ *
+@@ -28,12 +30,17 @@ static int __init noexec_setup(char *str
+ return 0;
+ }
+ early_param("noexec", noexec_setup);
++#endif
++
++#endif
+
+ void __cpuinit x86_configure_nx(void)
+ {
++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+ if (cpu_has_nx && !disable_nx)
+ __supported_pte_mask |= _PAGE_NX;
+ else
++#endif
+ __supported_pte_mask &= ~_PAGE_NX;
+ }
+
+diff -urNp linux-2.6.38.7/arch/x86/mm/tlb.c linux-2.6.38.7/arch/x86/mm/tlb.c
+--- linux-2.6.38.7/arch/x86/mm/tlb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/mm/tlb.c 2011-04-28 19:34:15.000000000 -0400
+@@ -65,7 +65,11 @@ void leave_mm(int cpu)
+ BUG();
+ cpumask_clear_cpu(cpu,
+ mm_cpumask(percpu_read(cpu_tlbstate.active_mm)));
++
++#ifndef CONFIG_PAX_PER_CPU_PGD
+ load_cr3(swapper_pg_dir);
++#endif
++
+ }
+ EXPORT_SYMBOL_GPL(leave_mm);
+
+diff -urNp linux-2.6.38.7/arch/x86/oprofile/backtrace.c linux-2.6.38.7/arch/x86/oprofile/backtrace.c
+--- linux-2.6.38.7/arch/x86/oprofile/backtrace.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/oprofile/backtrace.c 2011-04-28 19:34:15.000000000 -0400
+@@ -57,7 +57,7 @@ dump_user_backtrace_32(struct stack_fram
+ struct stack_frame_ia32 *fp;
+
+ /* Also check accessibility of one struct frame_head beyond */
+- if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
++ if (!__access_ok(VERIFY_READ, head, sizeof(bufhead)))
+ return NULL;
+ if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+ return NULL;
+@@ -123,7 +123,7 @@ x86_backtrace(struct pt_regs * const reg
+ {
+ struct stack_frame *head = (struct stack_frame *)frame_pointer(regs);
+
+- if (!user_mode_vm(regs)) {
++ if (!user_mode(regs)) {
+ unsigned long stack = kernel_stack_pointer(regs);
+ if (depth)
+ dump_trace(NULL, regs, (unsigned long *)stack,
+diff -urNp linux-2.6.38.7/arch/x86/oprofile/op_model_p4.c linux-2.6.38.7/arch/x86/oprofile/op_model_p4.c
+--- linux-2.6.38.7/arch/x86/oprofile/op_model_p4.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/oprofile/op_model_p4.c 2011-04-28 19:34:15.000000000 -0400
+@@ -50,7 +50,7 @@ static inline void setup_num_counters(vo
+ #endif
+ }
+
+-static int inline addr_increment(void)
++static inline int addr_increment(void)
+ {
+ #ifdef CONFIG_SMP
+ return smp_num_siblings == 2 ? 2 : 1;
+diff -urNp linux-2.6.38.7/arch/x86/pci/ce4100.c linux-2.6.38.7/arch/x86/pci/ce4100.c
+--- linux-2.6.38.7/arch/x86/pci/ce4100.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/ce4100.c 2011-04-28 19:34:15.000000000 -0400
+@@ -302,7 +302,7 @@ static int ce4100_conf_write(unsigned in
+ return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
+ }
+
+-struct pci_raw_ops ce4100_pci_conf = {
++const struct pci_raw_ops ce4100_pci_conf = {
+ .read = ce4100_conf_read,
+ .write = ce4100_conf_write,
+ };
+diff -urNp linux-2.6.38.7/arch/x86/pci/common.c linux-2.6.38.7/arch/x86/pci/common.c
+--- linux-2.6.38.7/arch/x86/pci/common.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/common.c 2011-04-28 19:34:15.000000000 -0400
+@@ -33,8 +33,8 @@ int noioapicreroute = 1;
+ int pcibios_last_bus = -1;
+ unsigned long pirq_table_addr;
+ struct pci_bus *pci_root_bus;
+-struct pci_raw_ops *raw_pci_ops;
+-struct pci_raw_ops *raw_pci_ext_ops;
++const struct pci_raw_ops *raw_pci_ops;
++const struct pci_raw_ops *raw_pci_ext_ops;
+
+ int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 *val)
+diff -urNp linux-2.6.38.7/arch/x86/pci/direct.c linux-2.6.38.7/arch/x86/pci/direct.c
+--- linux-2.6.38.7/arch/x86/pci/direct.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/direct.c 2011-04-28 19:34:15.000000000 -0400
+@@ -79,7 +79,7 @@ static int pci_conf1_write(unsigned int
+
+ #undef PCI_CONF1_ADDRESS
+
+-struct pci_raw_ops pci_direct_conf1 = {
++const struct pci_raw_ops pci_direct_conf1 = {
+ .read = pci_conf1_read,
+ .write = pci_conf1_write,
+ };
+@@ -173,7 +173,7 @@ static int pci_conf2_write(unsigned int
+
+ #undef PCI_CONF2_ADDRESS
+
+-struct pci_raw_ops pci_direct_conf2 = {
++const struct pci_raw_ops pci_direct_conf2 = {
+ .read = pci_conf2_read,
+ .write = pci_conf2_write,
+ };
+@@ -189,7 +189,7 @@ struct pci_raw_ops pci_direct_conf2 = {
+ * This should be close to trivial, but it isn't, because there are buggy
+ * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
+ */
+-static int __init pci_sanity_check(struct pci_raw_ops *o)
++static int __init pci_sanity_check(const struct pci_raw_ops *o)
+ {
+ u32 x = 0;
+ int year, devfn;
+diff -urNp linux-2.6.38.7/arch/x86/pci/fixup.c linux-2.6.38.7/arch/x86/pci/fixup.c
+--- linux-2.6.38.7/arch/x86/pci/fixup.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/fixup.c 2011-04-28 19:34:15.000000000 -0400
+@@ -435,7 +435,7 @@ static const struct dmi_system_id __devi
+ DMI_MATCH(DMI_PRODUCT_VERSION, "PSA40U"),
+ },
+ },
+- { }
++ {}
+ };
+
+ static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
+diff -urNp linux-2.6.38.7/arch/x86/pci/mmconfig_32.c linux-2.6.38.7/arch/x86/pci/mmconfig_32.c
+--- linux-2.6.38.7/arch/x86/pci/mmconfig_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/mmconfig_32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -117,7 +117,7 @@ static int pci_mmcfg_write(unsigned int
+ return 0;
+ }
+
+-static struct pci_raw_ops pci_mmcfg = {
++static const struct pci_raw_ops pci_mmcfg = {
+ .read = pci_mmcfg_read,
+ .write = pci_mmcfg_write,
+ };
+diff -urNp linux-2.6.38.7/arch/x86/pci/mmconfig_64.c linux-2.6.38.7/arch/x86/pci/mmconfig_64.c
+--- linux-2.6.38.7/arch/x86/pci/mmconfig_64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/mmconfig_64.c 2011-04-28 19:34:15.000000000 -0400
+@@ -81,7 +81,7 @@ static int pci_mmcfg_write(unsigned int
+ return 0;
+ }
+
+-static struct pci_raw_ops pci_mmcfg = {
++static const struct pci_raw_ops pci_mmcfg = {
+ .read = pci_mmcfg_read,
+ .write = pci_mmcfg_write,
+ };
+diff -urNp linux-2.6.38.7/arch/x86/pci/numaq_32.c linux-2.6.38.7/arch/x86/pci/numaq_32.c
+--- linux-2.6.38.7/arch/x86/pci/numaq_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/numaq_32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -108,7 +108,7 @@ static int pci_conf1_mq_write(unsigned i
+
+ #undef PCI_CONF1_MQ_ADDRESS
+
+-static struct pci_raw_ops pci_direct_conf1_mq = {
++static const struct pci_raw_ops pci_direct_conf1_mq = {
+ .read = pci_conf1_mq_read,
+ .write = pci_conf1_mq_write
+ };
+diff -urNp linux-2.6.38.7/arch/x86/pci/olpc.c linux-2.6.38.7/arch/x86/pci/olpc.c
+--- linux-2.6.38.7/arch/x86/pci/olpc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/olpc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -297,7 +297,7 @@ static int pci_olpc_write(unsigned int s
+ return 0;
+ }
+
+-static struct pci_raw_ops pci_olpc_conf = {
++static const struct pci_raw_ops pci_olpc_conf = {
+ .read = pci_olpc_read,
+ .write = pci_olpc_write,
+ };
+diff -urNp linux-2.6.38.7/arch/x86/pci/pcbios.c linux-2.6.38.7/arch/x86/pci/pcbios.c
+--- linux-2.6.38.7/arch/x86/pci/pcbios.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/pci/pcbios.c 2011-04-28 19:34:15.000000000 -0400
+@@ -79,50 +79,93 @@ union bios32 {
+ static struct {
+ unsigned long address;
+ unsigned short segment;
+-} bios32_indirect = { 0, __KERNEL_CS };
++} bios32_indirect __read_only = { 0, __PCIBIOS_CS };
+
+ /*
+ * Returns the entry point for the given service, NULL on error
+ */
+
+-static unsigned long bios32_service(unsigned long service)
++static unsigned long __devinit bios32_service(unsigned long service)
+ {
+ unsigned char return_code; /* %al */
+ unsigned long address; /* %ebx */
+ unsigned long length; /* %ecx */
+ unsigned long entry; /* %edx */
+ unsigned long flags;
++ struct desc_struct d, *gdt;
+
+ local_irq_save(flags);
+- __asm__("lcall *(%%edi); cld"
++
++ gdt = get_cpu_gdt_table(smp_processor_id());
++
++ pack_descriptor(&d, 0UL, 0xFFFFFUL, 0x9B, 0xC);
++ write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_CS, &d, DESCTYPE_S);
++ pack_descriptor(&d, 0UL, 0xFFFFFUL, 0x93, 0xC);
++ write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_DS, &d, DESCTYPE_S);
++
++ __asm__("movw %w7, %%ds; lcall *(%%edi); push %%ss; pop %%ds; cld"
+ : "=a" (return_code),
+ "=b" (address),
+ "=c" (length),
+ "=d" (entry)
+ : "0" (service),
+ "1" (0),
+- "D" (&bios32_indirect));
++ "D" (&bios32_indirect),
++ "r"(__PCIBIOS_DS)
++ : "memory");
++
++ pax_open_kernel();
++ gdt[GDT_ENTRY_PCIBIOS_CS].a = 0;
++ gdt[GDT_ENTRY_PCIBIOS_CS].b = 0;
++ gdt[GDT_ENTRY_PCIBIOS_DS].a = 0;
++ gdt[GDT_ENTRY_PCIBIOS_DS].b = 0;
++ pax_close_kernel();
++
+ local_irq_restore(flags);
+
+ switch (return_code) {
+- case 0:
+- return address + entry;
+- case 0x80: /* Not present */
+- printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service);
+- return 0;
+- default: /* Shouldn't happen */
+- printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n",
+- service, return_code);
++ case 0: {
++ int cpu;
++ unsigned char flags;
++
++ printk(KERN_INFO "bios32_service: base:%08lx length:%08lx entry:%08lx\n", address, length, entry);
++ if (address >= 0xFFFF0 || length > 0x100000 - address || length <= entry) {
++ printk(KERN_WARNING "bios32_service: not valid\n");
+ return 0;
++ }
++ address = address + PAGE_OFFSET;
++ length += 16UL; /* some BIOSs underreport this... */
++ flags = 4;
++ if (length >= 64*1024*1024) {
++ length >>= PAGE_SHIFT;
++ flags |= 8;
++ }
++
++ for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ gdt = get_cpu_gdt_table(cpu);
++ pack_descriptor(&d, address, length, 0x9b, flags);
++ write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_CS, &d, DESCTYPE_S);
++ pack_descriptor(&d, address, length, 0x93, flags);
++ write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_DS, &d, DESCTYPE_S);
++ }
++ return entry;
++ }
++ case 0x80: /* Not present */
++ printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service);
++ return 0;
++ default: /* Shouldn't happen */
++ printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n",
++ service, return_code);
++ return 0;
+ }
+ }
+
+ static struct {
+ unsigned long address;
+ unsigned short segment;
+-} pci_indirect = { 0, __KERNEL_CS };
++} pci_indirect __read_only = { 0, __PCIBIOS_CS };
+
+-static int pci_bios_present;
++static int pci_bios_present __read_only;
+
+ static int __devinit check_pcibios(void)
+ {
+@@ -131,11 +174,13 @@ static int __devinit check_pcibios(void)
+ unsigned long flags, pcibios_entry;
+
+ if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
+- pci_indirect.address = pcibios_entry + PAGE_OFFSET;
++ pci_indirect.address = pcibios_entry;
+
+ local_irq_save(flags);
+- __asm__(
+- "lcall *(%%edi); cld\n\t"
++ __asm__("movw %w6, %%ds\n\t"
++ "lcall *%%ss:(%%edi); cld\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -144,7 +189,8 @@ static int __devinit check_pcibios(void)
+ "=b" (ebx),
+ "=c" (ecx)
+ : "1" (PCIBIOS_PCI_BIOS_PRESENT),
+- "D" (&pci_indirect)
++ "D" (&pci_indirect),
++ "r" (__PCIBIOS_DS)
+ : "memory");
+ local_irq_restore(flags);
+
+@@ -188,7 +234,10 @@ static int pci_bios_read(unsigned int se
+
+ switch (len) {
+ case 1:
+- __asm__("lcall *(%%esi); cld\n\t"
++ __asm__("movw %w6, %%ds\n\t"
++ "lcall *%%ss:(%%esi); cld\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -197,7 +246,8 @@ static int pci_bios_read(unsigned int se
+ : "1" (PCIBIOS_READ_CONFIG_BYTE),
+ "b" (bx),
+ "D" ((long)reg),
+- "S" (&pci_indirect));
++ "S" (&pci_indirect),
++ "r" (__PCIBIOS_DS));
+ /*
+ * Zero-extend the result beyond 8 bits, do not trust the
+ * BIOS having done it:
+@@ -205,7 +255,10 @@ static int pci_bios_read(unsigned int se
+ *value &= 0xff;
+ break;
+ case 2:
+- __asm__("lcall *(%%esi); cld\n\t"
++ __asm__("movw %w6, %%ds\n\t"
++ "lcall *%%ss:(%%esi); cld\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -214,7 +267,8 @@ static int pci_bios_read(unsigned int se
+ : "1" (PCIBIOS_READ_CONFIG_WORD),
+ "b" (bx),
+ "D" ((long)reg),
+- "S" (&pci_indirect));
++ "S" (&pci_indirect),
++ "r" (__PCIBIOS_DS));
+ /*
+ * Zero-extend the result beyond 16 bits, do not trust the
+ * BIOS having done it:
+@@ -222,7 +276,10 @@ static int pci_bios_read(unsigned int se
+ *value &= 0xffff;
+ break;
+ case 4:
+- __asm__("lcall *(%%esi); cld\n\t"
++ __asm__("movw %w6, %%ds\n\t"
++ "lcall *%%ss:(%%esi); cld\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -231,7 +288,8 @@ static int pci_bios_read(unsigned int se
+ : "1" (PCIBIOS_READ_CONFIG_DWORD),
+ "b" (bx),
+ "D" ((long)reg),
+- "S" (&pci_indirect));
++ "S" (&pci_indirect),
++ "r" (__PCIBIOS_DS));
+ break;
+ }
+
+@@ -254,7 +312,10 @@ static int pci_bios_write(unsigned int s
+
+ switch (len) {
+ case 1:
+- __asm__("lcall *(%%esi); cld\n\t"
++ __asm__("movw %w6, %%ds\n\t"
++ "lcall *%%ss:(%%esi); cld\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -263,10 +324,14 @@ static int pci_bios_write(unsigned int s
+ "c" (value),
+ "b" (bx),
+ "D" ((long)reg),
+- "S" (&pci_indirect));
++ "S" (&pci_indirect),
++ "r" (__PCIBIOS_DS));
+ break;
+ case 2:
+- __asm__("lcall *(%%esi); cld\n\t"
++ __asm__("movw %w6, %%ds\n\t"
++ "lcall *%%ss:(%%esi); cld\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -275,10 +340,14 @@ static int pci_bios_write(unsigned int s
+ "c" (value),
+ "b" (bx),
+ "D" ((long)reg),
+- "S" (&pci_indirect));
++ "S" (&pci_indirect),
++ "r" (__PCIBIOS_DS));
+ break;
+ case 4:
+- __asm__("lcall *(%%esi); cld\n\t"
++ __asm__("movw %w6, %%ds\n\t"
++ "lcall *%%ss:(%%esi); cld\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n\t"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -287,7 +356,8 @@ static int pci_bios_write(unsigned int s
+ "c" (value),
+ "b" (bx),
+ "D" ((long)reg),
+- "S" (&pci_indirect));
++ "S" (&pci_indirect),
++ "r" (__PCIBIOS_DS));
+ break;
+ }
+
+@@ -301,7 +371,7 @@ static int pci_bios_write(unsigned int s
+ * Function table for BIOS32 access
+ */
+
+-static struct pci_raw_ops pci_bios_access = {
++static const struct pci_raw_ops pci_bios_access = {
+ .read = pci_bios_read,
+ .write = pci_bios_write
+ };
+@@ -310,7 +380,7 @@ static struct pci_raw_ops pci_bios_acces
+ * Try to find PCI BIOS.
+ */
+
+-static struct pci_raw_ops * __devinit pci_find_bios(void)
++static const struct pci_raw_ops * __devinit pci_find_bios(void)
+ {
+ union bios32 *check;
+ unsigned char sum;
+@@ -392,10 +462,13 @@ struct irq_routing_table * pcibios_get_i
+
+ DBG("PCI: Fetching IRQ routing table... ");
+ __asm__("push %%es\n\t"
++ "movw %w8, %%ds\n\t"
+ "push %%ds\n\t"
+ "pop %%es\n\t"
+- "lcall *(%%esi); cld\n\t"
++ "lcall *%%ss:(%%esi); cld\n\t"
+ "pop %%es\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -406,7 +479,8 @@ struct irq_routing_table * pcibios_get_i
+ "1" (0),
+ "D" ((long) &opt),
+ "S" (&pci_indirect),
+- "m" (opt)
++ "m" (opt),
++ "r" (__PCIBIOS_DS)
+ : "memory");
+ DBG("OK ret=%d, size=%d, map=%x\n", ret, opt.size, map);
+ if (ret & 0xff00)
+@@ -430,7 +504,10 @@ int pcibios_set_irq_routing(struct pci_d
+ {
+ int ret;
+
+- __asm__("lcall *(%%esi); cld\n\t"
++ __asm__("movw %w5, %%ds\n\t"
++ "lcall *%%ss:(%%esi); cld\n\t"
++ "push %%ss\n\t"
++ "pop %%ds\n"
+ "jc 1f\n\t"
+ "xor %%ah, %%ah\n"
+ "1:"
+@@ -438,7 +515,8 @@ int pcibios_set_irq_routing(struct pci_d
+ : "0" (PCIBIOS_SET_PCI_HW_INT),
+ "b" ((dev->bus->number << 8) | dev->devfn),
+ "c" ((irq << 8) | (pin + 10)),
+- "S" (&pci_indirect));
++ "S" (&pci_indirect),
++ "r" (__PCIBIOS_DS));
+ return !(ret & 0xff00);
+ }
+ EXPORT_SYMBOL(pcibios_set_irq_routing);
+diff -urNp linux-2.6.38.7/arch/x86/platform/efi/efi_32.c linux-2.6.38.7/arch/x86/platform/efi/efi_32.c
+--- linux-2.6.38.7/arch/x86/platform/efi/efi_32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/platform/efi/efi_32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -38,70 +38,37 @@
+ */
+
+ static unsigned long efi_rt_eflags;
+-static pgd_t efi_bak_pg_dir_pointer[2];
++static pgd_t __initdata efi_bak_pg_dir_pointer[KERNEL_PGD_PTRS];
+
+-void efi_call_phys_prelog(void)
++void __init efi_call_phys_prelog(void)
+ {
+- unsigned long cr4;
+- unsigned long temp;
+ struct desc_ptr gdt_descr;
+
+ local_irq_save(efi_rt_eflags);
+
+- /*
+- * If I don't have PAE, I should just duplicate two entries in page
+- * directory. If I have PAE, I just need to duplicate one entry in
+- * page directory.
+- */
+- cr4 = read_cr4_safe();
+-
+- if (cr4 & X86_CR4_PAE) {
+- efi_bak_pg_dir_pointer[0].pgd =
+- swapper_pg_dir[pgd_index(0)].pgd;
+- swapper_pg_dir[0].pgd =
+- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
+- } else {
+- efi_bak_pg_dir_pointer[0].pgd =
+- swapper_pg_dir[pgd_index(0)].pgd;
+- efi_bak_pg_dir_pointer[1].pgd =
+- swapper_pg_dir[pgd_index(0x400000)].pgd;
+- swapper_pg_dir[pgd_index(0)].pgd =
+- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
+- temp = PAGE_OFFSET + 0x400000;
+- swapper_pg_dir[pgd_index(0x400000)].pgd =
+- swapper_pg_dir[pgd_index(temp)].pgd;
+- }
++ clone_pgd_range(efi_bak_pg_dir_pointer, swapper_pg_dir, KERNEL_PGD_PTRS);
++ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++ min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
+
+ /*
+ * After the lock is released, the original page table is restored.
+ */
+ __flush_tlb_all();
+
+- gdt_descr.address = __pa(get_cpu_gdt_table(0));
++ gdt_descr.address = (struct desc_struct *)__pa(get_cpu_gdt_table(0));
+ gdt_descr.size = GDT_SIZE - 1;
+ load_gdt(&gdt_descr);
+ }
+
+-void efi_call_phys_epilog(void)
++void __init efi_call_phys_epilog(void)
+ {
+- unsigned long cr4;
+ struct desc_ptr gdt_descr;
+
+- gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
++ gdt_descr.address = get_cpu_gdt_table(0);
+ gdt_descr.size = GDT_SIZE - 1;
+ load_gdt(&gdt_descr);
+
+- cr4 = read_cr4_safe();
+-
+- if (cr4 & X86_CR4_PAE) {
+- swapper_pg_dir[pgd_index(0)].pgd =
+- efi_bak_pg_dir_pointer[0].pgd;
+- } else {
+- swapper_pg_dir[pgd_index(0)].pgd =
+- efi_bak_pg_dir_pointer[0].pgd;
+- swapper_pg_dir[pgd_index(0x400000)].pgd =
+- efi_bak_pg_dir_pointer[1].pgd;
+- }
++ clone_pgd_range(swapper_pg_dir, efi_bak_pg_dir_pointer, KERNEL_PGD_PTRS);
+
+ /*
+ * After the lock is released, the original page table is restored.
+diff -urNp linux-2.6.38.7/arch/x86/platform/efi/efi_stub_32.S linux-2.6.38.7/arch/x86/platform/efi/efi_stub_32.S
+--- linux-2.6.38.7/arch/x86/platform/efi/efi_stub_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/platform/efi/efi_stub_32.S 2011-04-28 19:34:15.000000000 -0400
+@@ -6,6 +6,7 @@
+ */
+
+ #include <linux/linkage.h>
++#include <linux/init.h>
+ #include <asm/page_types.h>
+
+ /*
+@@ -20,7 +21,7 @@
+ * service functions will comply with gcc calling convention, too.
+ */
+
+-.text
++__INIT
+ ENTRY(efi_call_phys)
+ /*
+ * 0. The function can only be called in Linux kernel. So CS has been
+@@ -36,9 +37,7 @@ ENTRY(efi_call_phys)
+ * The mapping of lower virtual memory has been created in prelog and
+ * epilog.
+ */
+- movl $1f, %edx
+- subl $__PAGE_OFFSET, %edx
+- jmp *%edx
++ jmp 1f-__PAGE_OFFSET
+ 1:
+
+ /*
+@@ -47,14 +46,8 @@ ENTRY(efi_call_phys)
+ * parameter 2, ..., param n. To make things easy, we save the return
+ * address of efi_call_phys in a global variable.
+ */
+- popl %edx
+- movl %edx, saved_return_addr
+- /* get the function pointer into ECX*/
+- popl %ecx
+- movl %ecx, efi_rt_function_ptr
+- movl $2f, %edx
+- subl $__PAGE_OFFSET, %edx
+- pushl %edx
++ popl (saved_return_addr)
++ popl (efi_rt_function_ptr)
+
+ /*
+ * 3. Clear PG bit in %CR0.
+@@ -73,9 +66,8 @@ ENTRY(efi_call_phys)
+ /*
+ * 5. Call the physical function.
+ */
+- jmp *%ecx
++ call *(efi_rt_function_ptr-__PAGE_OFFSET)
+
+-2:
+ /*
+ * 6. After EFI runtime service returns, control will return to
+ * following instruction. We'd better readjust stack pointer first.
+@@ -88,35 +80,28 @@ ENTRY(efi_call_phys)
+ movl %cr0, %edx
+ orl $0x80000000, %edx
+ movl %edx, %cr0
+- jmp 1f
+-1:
++
+ /*
+ * 8. Now restore the virtual mode from flat mode by
+ * adding EIP with PAGE_OFFSET.
+ */
+- movl $1f, %edx
+- jmp *%edx
++ jmp 1f+__PAGE_OFFSET
+ 1:
+
+ /*
+ * 9. Balance the stack. And because EAX contain the return value,
+ * we'd better not clobber it.
+ */
+- leal efi_rt_function_ptr, %edx
+- movl (%edx), %ecx
+- pushl %ecx
++ pushl (efi_rt_function_ptr)
+
+ /*
+- * 10. Push the saved return address onto the stack and return.
++ * 10. Return to the saved return address.
+ */
+- leal saved_return_addr, %edx
+- movl (%edx), %ecx
+- pushl %ecx
+- ret
++ jmpl *(saved_return_addr)
+ ENDPROC(efi_call_phys)
+ .previous
+
+-.data
++__INITDATA
+ saved_return_addr:
+ .long 0
+ efi_rt_function_ptr:
+diff -urNp linux-2.6.38.7/arch/x86/platform/uv/tlb_uv.c linux-2.6.38.7/arch/x86/platform/uv/tlb_uv.c
+--- linux-2.6.38.7/arch/x86/platform/uv/tlb_uv.c 2011-05-22 23:05:18.000000000 -0400
++++ linux-2.6.38.7/arch/x86/platform/uv/tlb_uv.c 2011-05-22 23:05:54.000000000 -0400
+@@ -341,6 +341,8 @@ static void uv_reset_with_ipi(struct bau
+ cpumask_t mask;
+ struct reset_args reset_args;
+
++ pax_track_stack();
++
+ reset_args.sender = sender;
+
+ cpus_clear(mask);
+diff -urNp linux-2.6.38.7/arch/x86/power/cpu.c linux-2.6.38.7/arch/x86/power/cpu.c
+--- linux-2.6.38.7/arch/x86/power/cpu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/power/cpu.c 2011-04-28 19:34:15.000000000 -0400
+@@ -130,7 +130,7 @@ static void do_fpu_end(void)
+ static void fix_processor_context(void)
+ {
+ int cpu = smp_processor_id();
+- struct tss_struct *t = &per_cpu(init_tss, cpu);
++ struct tss_struct *t = init_tss + cpu;
+
+ set_tss_desc(cpu, t); /*
+ * This just modifies memory; should not be
+@@ -140,7 +140,9 @@ static void fix_processor_context(void)
+ */
+
+ #ifdef CONFIG_X86_64
++ pax_open_kernel();
+ get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
++ pax_close_kernel();
+
+ syscall_init(); /* This sets MSR_*STAR and related */
+ #endif
+diff -urNp linux-2.6.38.7/arch/x86/vdso/Makefile linux-2.6.38.7/arch/x86/vdso/Makefile
+--- linux-2.6.38.7/arch/x86/vdso/Makefile 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/vdso/Makefile 2011-04-28 19:34:15.000000000 -0400
+@@ -123,7 +123,7 @@ quiet_cmd_vdso = VDSO $@
+ -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
+ sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
+
+-VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
++VDSO_LDFLAGS = -fPIC -shared -Wl,--no-undefined $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+ GCOV_PROFILE := n
+
+ #
+diff -urNp linux-2.6.38.7/arch/x86/vdso/vclock_gettime.c linux-2.6.38.7/arch/x86/vdso/vclock_gettime.c
+--- linux-2.6.38.7/arch/x86/vdso/vclock_gettime.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/vdso/vclock_gettime.c 2011-04-28 19:34:15.000000000 -0400
+@@ -22,24 +22,48 @@
+ #include <asm/hpet.h>
+ #include <asm/unistd.h>
+ #include <asm/io.h>
++#include <asm/fixmap.h>
+ #include "vextern.h"
+
+ #define gtod vdso_vsyscall_gtod_data
+
++notrace noinline long __vdso_fallback_time(long *t)
++{
++ long secs;
++ asm volatile("syscall"
++ : "=a" (secs)
++ : "0" (__NR_time),"D" (t) : "r11", "cx", "memory");
++ return secs;
++}
++
+ notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
+ {
+ long ret;
+ asm("syscall" : "=a" (ret) :
+- "0" (__NR_clock_gettime),"D" (clock), "S" (ts) : "memory");
++ "0" (__NR_clock_gettime),"D" (clock), "S" (ts) : "r11", "cx", "memory");
+ return ret;
+ }
+
++notrace static inline cycle_t __vdso_vread_hpet(void)
++{
++ return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
++}
++
++notrace static inline cycle_t __vdso_vread_tsc(void)
++{
++ cycle_t ret = (cycle_t)vget_cycles();
++
++ return ret >= gtod->clock.cycle_last ? ret : gtod->clock.cycle_last;
++}
++
+ notrace static inline long vgetns(void)
+ {
+ long v;
+- cycles_t (*vread)(void);
+- vread = gtod->clock.vread;
+- v = (vread() - gtod->clock.cycle_last) & gtod->clock.mask;
++ if (gtod->clock.name[0] == 't' && gtod->clock.name[1] == 's' && gtod->clock.name[2] == 'c' && !gtod->clock.name[3])
++ v = __vdso_vread_tsc();
++ else
++ v = __vdso_vread_hpet();
++ v = (v - gtod->clock.cycle_last) & gtod->clock.mask;
+ return (v * gtod->clock.mult) >> gtod->clock.shift;
+ }
+
+@@ -113,7 +137,9 @@ notrace static noinline int do_monotonic
+
+ notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+ {
+- if (likely(gtod->sysctl_enabled))
++ if (likely(gtod->sysctl_enabled &&
++ ((gtod->clock.name[0] == 'h' && gtod->clock.name[1] == 'p' && gtod->clock.name[2] == 'e' && gtod->clock.name[3] == 't' && !gtod->clock.name[4]) ||
++ (gtod->clock.name[0] == 't' && gtod->clock.name[1] == 's' && gtod->clock.name[2] == 'c' && !gtod->clock.name[3]))))
+ switch (clock) {
+ case CLOCK_REALTIME:
+ if (likely(gtod->clock.vread))
+@@ -133,10 +159,20 @@ notrace int __vdso_clock_gettime(clockid
+ int clock_gettime(clockid_t, struct timespec *)
+ __attribute__((weak, alias("__vdso_clock_gettime")));
+
+-notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
++notrace noinline int __vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz)
+ {
+ long ret;
+- if (likely(gtod->sysctl_enabled && gtod->clock.vread)) {
++ asm("syscall" : "=a" (ret) :
++ "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "r11", "cx", "memory");
++ return ret;
++}
++
++notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
++{
++ if (likely(gtod->sysctl_enabled &&
++ ((gtod->clock.name[0] == 'h' && gtod->clock.name[1] == 'p' && gtod->clock.name[2] == 'e' && gtod->clock.name[3] == 't' && !gtod->clock.name[4]) ||
++ (gtod->clock.name[0] == 't' && gtod->clock.name[1] == 's' && gtod->clock.name[2] == 'c' && !gtod->clock.name[3]))))
++ {
+ if (likely(tv != NULL)) {
+ BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
+ offsetof(struct timespec, tv_nsec) ||
+@@ -151,9 +187,7 @@ notrace int __vdso_gettimeofday(struct t
+ }
+ return 0;
+ }
+- asm("syscall" : "=a" (ret) :
+- "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+- return ret;
++ return __vdso_fallback_gettimeofday(tv, tz);
+ }
+ int gettimeofday(struct timeval *, struct timezone *)
+ __attribute__((weak, alias("__vdso_gettimeofday")));
+diff -urNp linux-2.6.38.7/arch/x86/vdso/vdso32-setup.c linux-2.6.38.7/arch/x86/vdso/vdso32-setup.c
+--- linux-2.6.38.7/arch/x86/vdso/vdso32-setup.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/vdso/vdso32-setup.c 2011-04-28 19:34:15.000000000 -0400
+@@ -25,6 +25,7 @@
+ #include <asm/tlbflush.h>
+ #include <asm/vdso.h>
+ #include <asm/proto.h>
++#include <asm/mman.h>
+
+ enum {
+ VDSO_DISABLED = 0,
+@@ -226,7 +227,7 @@ static inline void map_compat_vdso(int m
+ void enable_sep_cpu(void)
+ {
+ int cpu = get_cpu();
+- struct tss_struct *tss = &per_cpu(init_tss, cpu);
++ struct tss_struct *tss = init_tss + cpu;
+
+ if (!boot_cpu_has(X86_FEATURE_SEP)) {
+ put_cpu();
+@@ -249,7 +250,7 @@ static int __init gate_vma_init(void)
+ gate_vma.vm_start = FIXADDR_USER_START;
+ gate_vma.vm_end = FIXADDR_USER_END;
+ gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+- gate_vma.vm_page_prot = __P101;
++ gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags);
+ /*
+ * Make sure the vDSO gets into every core dump.
+ * Dumping its contents makes post-mortem fully interpretable later
+@@ -331,14 +332,14 @@ int arch_setup_additional_pages(struct l
+ if (compat)
+ addr = VDSO_HIGH_BASE;
+ else {
+- addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
++ addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, MAP_EXECUTABLE);
+ if (IS_ERR_VALUE(addr)) {
+ ret = addr;
+ goto up_fail;
+ }
+ }
+
+- current->mm->context.vdso = (void *)addr;
++ current->mm->context.vdso = addr;
+
+ if (compat_uses_vma || !compat) {
+ /*
+@@ -361,11 +362,11 @@ int arch_setup_additional_pages(struct l
+ }
+
+ current_thread_info()->sysenter_return =
+- VDSO32_SYMBOL(addr, SYSENTER_RETURN);
++ (__force void __user *)VDSO32_SYMBOL(addr, SYSENTER_RETURN);
+
+ up_fail:
+ if (ret)
+- current->mm->context.vdso = NULL;
++ current->mm->context.vdso = 0;
+
+ up_write(&mm->mmap_sem);
+
+@@ -412,8 +413,14 @@ __initcall(ia32_binfmt_init);
+
+ const char *arch_vma_name(struct vm_area_struct *vma)
+ {
+- if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
++ if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso)
+ return "[vdso]";
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma->vm_mm && vma->vm_mirror && vma->vm_mirror->vm_start == vma->vm_mm->context.vdso)
++ return "[vdso]";
++#endif
++
+ return NULL;
+ }
+
+@@ -422,7 +429,7 @@ struct vm_area_struct *get_gate_vma(stru
+ struct mm_struct *mm = tsk->mm;
+
+ /* Check to see if this task was created in compat vdso mode */
+- if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE)
++ if (mm && mm->context.vdso == VDSO_HIGH_BASE)
+ return &gate_vma;
+ return NULL;
+ }
+diff -urNp linux-2.6.38.7/arch/x86/vdso/vdso.lds.S linux-2.6.38.7/arch/x86/vdso/vdso.lds.S
+--- linux-2.6.38.7/arch/x86/vdso/vdso.lds.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/vdso/vdso.lds.S 2011-04-28 19:34:15.000000000 -0400
+@@ -35,3 +35,9 @@ VDSO64_PRELINK = VDSO_PRELINK;
+ #define VEXTERN(x) VDSO64_ ## x = vdso_ ## x;
+ #include "vextern.h"
+ #undef VEXTERN
++
++#define VEXTERN(x) VDSO64_ ## x = __vdso_ ## x;
++VEXTERN(fallback_gettimeofday)
++VEXTERN(fallback_time)
++VEXTERN(getcpu)
++#undef VEXTERN
+diff -urNp linux-2.6.38.7/arch/x86/vdso/vextern.h linux-2.6.38.7/arch/x86/vdso/vextern.h
+--- linux-2.6.38.7/arch/x86/vdso/vextern.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/vdso/vextern.h 2011-04-28 19:34:15.000000000 -0400
+@@ -11,6 +11,5 @@
+ put into vextern.h and be referenced as a pointer with vdso prefix.
+ The main kernel later fills in the values. */
+
+-VEXTERN(jiffies)
+ VEXTERN(vgetcpu_mode)
+ VEXTERN(vsyscall_gtod_data)
+diff -urNp linux-2.6.38.7/arch/x86/vdso/vma.c linux-2.6.38.7/arch/x86/vdso/vma.c
+--- linux-2.6.38.7/arch/x86/vdso/vma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/vdso/vma.c 2011-04-28 19:34:15.000000000 -0400
+@@ -58,7 +58,7 @@ static int __init init_vdso_vars(void)
+ if (!vbase)
+ goto oom;
+
+- if (memcmp(vbase, "\177ELF", 4)) {
++ if (memcmp(vbase, ELFMAG, SELFMAG)) {
+ printk("VDSO: I'm broken; not ELF\n");
+ vdso_enabled = 0;
+ }
+@@ -118,7 +118,7 @@ int arch_setup_additional_pages(struct l
+ goto up_fail;
+ }
+
+- current->mm->context.vdso = (void *)addr;
++ current->mm->context.vdso = addr;
+
+ ret = install_special_mapping(mm, addr, vdso_size,
+ VM_READ|VM_EXEC|
+@@ -126,7 +126,7 @@ int arch_setup_additional_pages(struct l
+ VM_ALWAYSDUMP,
+ vdso_pages);
+ if (ret) {
+- current->mm->context.vdso = NULL;
++ current->mm->context.vdso = 0;
+ goto up_fail;
+ }
+
+@@ -134,10 +134,3 @@ up_fail:
+ up_write(&mm->mmap_sem);
+ return ret;
+ }
+-
+-static __init int vdso_setup(char *s)
+-{
+- vdso_enabled = simple_strtoul(s, NULL, 0);
+- return 0;
+-}
+-__setup("vdso=", vdso_setup);
+diff -urNp linux-2.6.38.7/arch/x86/xen/enlighten.c linux-2.6.38.7/arch/x86/xen/enlighten.c
+--- linux-2.6.38.7/arch/x86/xen/enlighten.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/xen/enlighten.c 2011-05-22 23:03:34.000000000 -0400
+@@ -85,8 +85,6 @@ EXPORT_SYMBOL_GPL(xen_start_info);
+
+ struct shared_info xen_dummy_shared_info;
+
+-void *xen_initial_gdt;
+-
+ RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
+ __read_mostly int xen_have_vector_callback;
+ EXPORT_SYMBOL_GPL(xen_have_vector_callback);
+@@ -1017,7 +1015,7 @@ static const struct pv_apic_ops xen_apic
+ #endif
+ };
+
+-static void xen_reboot(int reason)
++static __noreturn void xen_reboot(int reason)
+ {
+ struct sched_shutdown r = { .reason = reason };
+
+@@ -1025,17 +1023,17 @@ static void xen_reboot(int reason)
+ BUG();
+ }
+
+-static void xen_restart(char *msg)
++static __noreturn void xen_restart(char *msg)
+ {
+ xen_reboot(SHUTDOWN_reboot);
+ }
+
+-static void xen_emergency_restart(void)
++static __noreturn void xen_emergency_restart(void)
+ {
+ xen_reboot(SHUTDOWN_reboot);
+ }
+
+-static void xen_machine_halt(void)
++static __noreturn void xen_machine_halt(void)
+ {
+ xen_reboot(SHUTDOWN_poweroff);
+ }
+@@ -1134,7 +1132,17 @@ asmlinkage void __init xen_start_kernel(
+ __userpte_alloc_gfp &= ~__GFP_HIGHMEM;
+
+ /* Work out if we support NX */
+- x86_configure_nx();
++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
++ if ((cpuid_eax(0x80000000) & 0xffff0000) == 0x80000000 &&
++ (cpuid_edx(0x80000001) & (1U << (X86_FEATURE_NX & 31)))) {
++ unsigned l, h;
++
++ __supported_pte_mask |= _PAGE_NX;
++ rdmsr(MSR_EFER, l, h);
++ l |= EFER_NX;
++ wrmsr(MSR_EFER, l, h);
++ }
++#endif
+
+ xen_setup_features();
+
+@@ -1165,13 +1173,6 @@ asmlinkage void __init xen_start_kernel(
+
+ machine_ops = xen_machine_ops;
+
+- /*
+- * The only reliable way to retain the initial address of the
+- * percpu gdt_page is to remember it here, so we can go and
+- * mark it RW later, when the initial percpu area is freed.
+- */
+- xen_initial_gdt = &per_cpu(gdt_page, 0);
+-
+ xen_smp_init();
+
+ #ifdef CONFIG_ACPI_NUMA
+diff -urNp linux-2.6.38.7/arch/x86/xen/mmu.c linux-2.6.38.7/arch/x86/xen/mmu.c
+--- linux-2.6.38.7/arch/x86/xen/mmu.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/arch/x86/xen/mmu.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1721,6 +1721,8 @@ __init pgd_t *xen_setup_kernel_pagetable
+ convert_pfn_mfn(init_level4_pgt);
+ convert_pfn_mfn(level3_ident_pgt);
+ convert_pfn_mfn(level3_kernel_pgt);
++ convert_pfn_mfn(level3_vmalloc_pgt);
++ convert_pfn_mfn(level3_vmemmap_pgt);
+
+ l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
+ l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud);
+@@ -1739,7 +1741,10 @@ __init pgd_t *xen_setup_kernel_pagetable
+ set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
+ set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
+ set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
++ set_page_prot(level3_vmalloc_pgt, PAGE_KERNEL_RO);
++ set_page_prot(level3_vmemmap_pgt, PAGE_KERNEL_RO);
+ set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO);
++ set_page_prot(level2_vmemmap_pgt, PAGE_KERNEL_RO);
+ set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
+ set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
+
+diff -urNp linux-2.6.38.7/arch/x86/xen/pci-swiotlb-xen.c linux-2.6.38.7/arch/x86/xen/pci-swiotlb-xen.c
+--- linux-2.6.38.7/arch/x86/xen/pci-swiotlb-xen.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/xen/pci-swiotlb-xen.c 2011-04-28 19:34:15.000000000 -0400
+@@ -10,7 +10,7 @@
+
+ int xen_swiotlb __read_mostly;
+
+-static struct dma_map_ops xen_swiotlb_dma_ops = {
++static const struct dma_map_ops xen_swiotlb_dma_ops = {
+ .mapping_error = xen_swiotlb_dma_mapping_error,
+ .alloc_coherent = xen_swiotlb_alloc_coherent,
+ .free_coherent = xen_swiotlb_free_coherent,
+diff -urNp linux-2.6.38.7/arch/x86/xen/smp.c linux-2.6.38.7/arch/x86/xen/smp.c
+--- linux-2.6.38.7/arch/x86/xen/smp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/xen/smp.c 2011-05-11 18:34:57.000000000 -0400
+@@ -194,11 +194,6 @@ static void __init xen_smp_prepare_boot_
+ {
+ BUG_ON(smp_processor_id() != 0);
+ native_smp_prepare_boot_cpu();
+-
+- /* We've switched to the "real" per-cpu gdt, so make sure the
+- old memory can be recycled */
+- make_lowmem_page_readwrite(xen_initial_gdt);
+-
+ xen_filter_cpu_maps();
+ xen_setup_vcpu_info_placement();
+ }
+@@ -259,12 +254,12 @@ cpu_initialize_context(unsigned int cpu,
+ gdt = get_cpu_gdt_table(cpu);
+
+ ctxt->flags = VGCF_IN_KERNEL;
+- ctxt->user_regs.ds = __USER_DS;
+- ctxt->user_regs.es = __USER_DS;
++ ctxt->user_regs.ds = __KERNEL_DS;
++ ctxt->user_regs.es = __KERNEL_DS;
+ ctxt->user_regs.ss = __KERNEL_DS;
+ #ifdef CONFIG_X86_32
+ ctxt->user_regs.fs = __KERNEL_PERCPU;
+- ctxt->user_regs.gs = __KERNEL_STACK_CANARY;
++ savesegment(gs, ctxt->user_regs.gs);
+ #else
+ ctxt->gs_base_kernel = per_cpu_offset(cpu);
+ #endif
+@@ -315,13 +310,12 @@ static int __cpuinit xen_cpu_up(unsigned
+ int rc;
+
+ per_cpu(current_task, cpu) = idle;
++ per_cpu(current_tinfo, cpu) = &idle->tinfo;
+ #ifdef CONFIG_X86_32
+ irq_ctx_init(cpu);
+ #else
+ clear_tsk_thread_flag(idle, TIF_FORK);
+- per_cpu(kernel_stack, cpu) =
+- (unsigned long)task_stack_page(idle) -
+- KERNEL_STACK_OFFSET + THREAD_SIZE;
++ per_cpu(kernel_stack, cpu) = (unsigned long)task_stack_page(idle) - 16 + THREAD_SIZE;
+ #endif
+ xen_setup_runstate_info(cpu);
+ xen_setup_timer(cpu);
+diff -urNp linux-2.6.38.7/arch/x86/xen/xen-asm_32.S linux-2.6.38.7/arch/x86/xen/xen-asm_32.S
+--- linux-2.6.38.7/arch/x86/xen/xen-asm_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/xen/xen-asm_32.S 2011-04-28 19:34:15.000000000 -0400
+@@ -83,14 +83,14 @@ ENTRY(xen_iret)
+ ESP_OFFSET=4 # bytes pushed onto stack
+
+ /*
+- * Store vcpu_info pointer for easy access. Do it this way to
+- * avoid having to reload %fs
++ * Store vcpu_info pointer for easy access.
+ */
+ #ifdef CONFIG_SMP
+- GET_THREAD_INFO(%eax)
+- movl TI_cpu(%eax), %eax
+- movl __per_cpu_offset(,%eax,4), %eax
+- mov xen_vcpu(%eax), %eax
++ push %fs
++ mov $(__KERNEL_PERCPU), %eax
++ mov %eax, %fs
++ mov PER_CPU_VAR(xen_vcpu), %eax
++ pop %fs
+ #else
+ movl xen_vcpu, %eax
+ #endif
+diff -urNp linux-2.6.38.7/arch/x86/xen/xen-head.S linux-2.6.38.7/arch/x86/xen/xen-head.S
+--- linux-2.6.38.7/arch/x86/xen/xen-head.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/xen/xen-head.S 2011-04-28 19:34:15.000000000 -0400
+@@ -19,6 +19,17 @@ ENTRY(startup_xen)
+ #ifdef CONFIG_X86_32
+ mov %esi,xen_start_info
+ mov $init_thread_union+THREAD_SIZE,%esp
++#ifdef CONFIG_SMP
++ movl $cpu_gdt_table,%edi
++ movl $__per_cpu_load,%eax
++ movw %ax,__KERNEL_PERCPU + 2(%edi)
++ rorl $16,%eax
++ movb %al,__KERNEL_PERCPU + 4(%edi)
++ movb %ah,__KERNEL_PERCPU + 7(%edi)
++ movl $__per_cpu_end - 1,%eax
++ subl $__per_cpu_start,%eax
++ movw %ax,__KERNEL_PERCPU + 0(%edi)
++#endif
+ #else
+ mov %rsi,xen_start_info
+ mov $init_thread_union+THREAD_SIZE,%rsp
+diff -urNp linux-2.6.38.7/arch/x86/xen/xen-ops.h linux-2.6.38.7/arch/x86/xen/xen-ops.h
+--- linux-2.6.38.7/arch/x86/xen/xen-ops.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/arch/x86/xen/xen-ops.h 2011-04-28 19:34:15.000000000 -0400
+@@ -10,8 +10,6 @@
+ extern const char xen_hypervisor_callback[];
+ extern const char xen_failsafe_callback[];
+
+-extern void *xen_initial_gdt;
+-
+ struct trap_info;
+ void xen_copy_trap_info(struct trap_info *traps);
+
+diff -urNp linux-2.6.38.7/block/blk-iopoll.c linux-2.6.38.7/block/blk-iopoll.c
+--- linux-2.6.38.7/block/blk-iopoll.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/block/blk-iopoll.c 2011-04-28 19:34:15.000000000 -0400
+@@ -77,7 +77,7 @@ void blk_iopoll_complete(struct blk_iopo
+ }
+ EXPORT_SYMBOL(blk_iopoll_complete);
+
+-static void blk_iopoll_softirq(struct softirq_action *h)
++static void blk_iopoll_softirq(void)
+ {
+ struct list_head *list = &__get_cpu_var(blk_cpu_iopoll);
+ int rearm = 0, budget = blk_iopoll_budget;
+diff -urNp linux-2.6.38.7/block/blk-map.c linux-2.6.38.7/block/blk-map.c
+--- linux-2.6.38.7/block/blk-map.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/block/blk-map.c 2011-04-28 19:34:15.000000000 -0400
+@@ -301,7 +301,7 @@ int blk_rq_map_kern(struct request_queue
+ if (!len || !kbuf)
+ return -EINVAL;
+
+- do_copy = !blk_rq_aligned(q, addr, len) || object_is_on_stack(kbuf);
++ do_copy = !blk_rq_aligned(q, addr, len) || object_starts_on_stack(kbuf);
+ if (do_copy)
+ bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
+ else
+diff -urNp linux-2.6.38.7/block/blk-softirq.c linux-2.6.38.7/block/blk-softirq.c
+--- linux-2.6.38.7/block/blk-softirq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/block/blk-softirq.c 2011-04-28 19:34:15.000000000 -0400
+@@ -17,7 +17,7 @@ static DEFINE_PER_CPU(struct list_head,
+ * Softirq action handler - move entries to local list and loop over them
+ * while passing them to the queue registered handler.
+ */
+-static void blk_done_softirq(struct softirq_action *h)
++static void blk_done_softirq(void)
+ {
+ struct list_head *cpu_list, local_list;
+
+diff -urNp linux-2.6.38.7/block/bsg.c linux-2.6.38.7/block/bsg.c
+--- linux-2.6.38.7/block/bsg.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/block/bsg.c 2011-04-28 19:34:15.000000000 -0400
+@@ -176,16 +176,24 @@ static int blk_fill_sgv4_hdr_rq(struct r
+ struct sg_io_v4 *hdr, struct bsg_device *bd,
+ fmode_t has_write_perm)
+ {
++ unsigned char tmpcmd[sizeof(rq->__cmd)];
++ unsigned char *cmdptr;
++
+ if (hdr->request_len > BLK_MAX_CDB) {
+ rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL);
+ if (!rq->cmd)
+ return -ENOMEM;
+- }
++ cmdptr = rq->cmd;
++ } else
++ cmdptr = tmpcmd;
+
+- if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request,
++ if (copy_from_user(cmdptr, (void *)(unsigned long)hdr->request,
+ hdr->request_len))
+ return -EFAULT;
+
++ if (cmdptr != rq->cmd)
++ memcpy(rq->cmd, cmdptr, hdr->request_len);
++
+ if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
+ if (blk_verify_command(rq->cmd, has_write_perm))
+ return -EPERM;
+diff -urNp linux-2.6.38.7/block/scsi_ioctl.c linux-2.6.38.7/block/scsi_ioctl.c
+--- linux-2.6.38.7/block/scsi_ioctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/block/scsi_ioctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -222,8 +222,20 @@ EXPORT_SYMBOL(blk_verify_command);
+ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
+ struct sg_io_hdr *hdr, fmode_t mode)
+ {
+- if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
++ unsigned char tmpcmd[sizeof(rq->__cmd)];
++ unsigned char *cmdptr;
++
++ if (rq->cmd != rq->__cmd)
++ cmdptr = rq->cmd;
++ else
++ cmdptr = tmpcmd;
++
++ if (copy_from_user(cmdptr, hdr->cmdp, hdr->cmd_len))
+ return -EFAULT;
++
++ if (cmdptr != rq->cmd)
++ memcpy(rq->cmd, cmdptr, hdr->cmd_len);
++
+ if (blk_verify_command(rq->cmd, mode & FMODE_WRITE))
+ return -EPERM;
+
+@@ -432,6 +444,8 @@ int sg_scsi_ioctl(struct request_queue *
+ int err;
+ unsigned int in_len, out_len, bytes, opcode, cmdlen;
+ char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
++ unsigned char tmpcmd[sizeof(rq->__cmd)];
++ unsigned char *cmdptr;
+
+ if (!sic)
+ return -EINVAL;
+@@ -465,9 +479,18 @@ int sg_scsi_ioctl(struct request_queue *
+ */
+ err = -EFAULT;
+ rq->cmd_len = cmdlen;
+- if (copy_from_user(rq->cmd, sic->data, cmdlen))
++
++ if (rq->cmd != rq->__cmd)
++ cmdptr = rq->cmd;
++ else
++ cmdptr = tmpcmd;
++
++ if (copy_from_user(cmdptr, sic->data, cmdlen))
+ goto error;
+
++ if (rq->cmd != cmdptr)
++ memcpy(rq->cmd, cmdptr, cmdlen);
++
+ if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
+ goto error;
+
+diff -urNp linux-2.6.38.7/crypto/serpent.c linux-2.6.38.7/crypto/serpent.c
+--- linux-2.6.38.7/crypto/serpent.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/crypto/serpent.c 2011-05-16 21:47:08.000000000 -0400
+@@ -224,6 +224,8 @@ static int serpent_setkey(struct crypto_
+ u32 r0,r1,r2,r3,r4;
+ int i;
+
++ pax_track_stack();
++
+ /* Copy key, add padding */
+
+ for (i = 0; i < keylen; ++i)
+diff -urNp linux-2.6.38.7/Documentation/dontdiff linux-2.6.38.7/Documentation/dontdiff
+--- linux-2.6.38.7/Documentation/dontdiff 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/Documentation/dontdiff 2011-05-18 20:23:44.000000000 -0400
+@@ -1,13 +1,16 @@
+ *.a
+ *.aux
+ *.bin
++*.cis
+ *.cpio
+ *.csp
++*.dbg
+ *.dsp
+ *.dvi
+ *.elf
+ *.eps
+ *.fw
++*.gcno
+ *.gen.S
+ *.gif
+ *.grep
+@@ -38,8 +41,10 @@
+ *.tab.h
+ *.tex
+ *.ver
++*.vim
+ *.xml
+ *_MODULES
++*_reg_safe.h
+ *_vga16.c
+ *~
+ *.9
+@@ -49,11 +54,16 @@
+ 53c700_d.h
+ CVS
+ ChangeSet
++GPATH
++GRTAGS
++GSYMS
++GTAGS
+ Image
+ Kerntypes
+ Module.markers
+ Module.symvers
+ PENDING
++PERF*
+ SCCS
+ System.map*
+ TAGS
+@@ -80,8 +90,11 @@ btfixupprep
+ build
+ bvmlinux
+ bzImage*
++capability_names.h
+ capflags.c
+ classlist.h*
++clut_vga16.c
++common-cmds.h
+ comp*.log
+ compile.h*
+ conf
+@@ -106,16 +119,19 @@ fore200e_mkfirm
+ fore200e_pca_fw.c*
+ gconf
+ gen-devlist
++gen-kdb_cmds.c
+ gen_crc32table
+ gen_init_cpio
+ generated
+ genheaders
+ genksyms
+ *_gray256.c
++hash
+ ihex2fw
+ ikconfig.h*
+ inat-tables.c
+ initramfs_data.cpio
++initramfs_data.cpio.bz2
+ initramfs_data.cpio.gz
+ initramfs_list
+ int16.c
+@@ -125,7 +141,6 @@ int32.c
+ int4.c
+ int8.c
+ kallsyms
+-kconfig
+ keywords.c
+ ksym.c*
+ ksym.h*
+@@ -149,7 +164,9 @@ mkboot
+ mkbugboot
+ mkcpustr
+ mkdep
++mkpiggy
+ mkprep
++mkregtable
+ mktables
+ mktree
+ modpost
+@@ -165,6 +182,7 @@ parse.h
+ patches*
+ pca200e.bin
+ pca200e_ecd.bin2
++perf-archive
+ piggy.gz
+ piggyback
+ piggy.S
+@@ -180,7 +198,9 @@ r600_reg_safe.h
+ raid6altivec*.c
+ raid6int*.c
+ raid6tables.c
++regdb.c
+ relocs
++rlim_names.h
+ rn50_reg_safe.h
+ rs600_reg_safe.h
+ rv515_reg_safe.h
+@@ -189,6 +209,7 @@ setup
+ setup.bin
+ setup.elf
+ sImage
++slabinfo
+ sm_tbl*
+ split-include
+ syscalltab.h
+@@ -213,13 +234,17 @@ version.h*
+ vmlinux
+ vmlinux-*
+ vmlinux.aout
++vmlinux.bin.all
++vmlinux.bin.bz2
+ vmlinux.lds
++vmlinux.relocs
+ voffset.h
+ vsyscall.lds
+ vsyscall_32.lds
+ wanxlfw.inc
+ uImage
+ unifdef
++utsrelease.h
+ wakeup.bin
+ wakeup.elf
+ wakeup.lds
+diff -urNp linux-2.6.38.7/Documentation/filesystems/sysfs.txt linux-2.6.38.7/Documentation/filesystems/sysfs.txt
+--- linux-2.6.38.7/Documentation/filesystems/sysfs.txt 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/Documentation/filesystems/sysfs.txt 2011-04-28 19:34:15.000000000 -0400
+@@ -123,8 +123,8 @@ set of sysfs operations for forwarding r
+ show and store methods of the attribute owners.
+
+ struct sysfs_ops {
+- ssize_t (*show)(struct kobject *, struct attribute *, char *);
+- ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
++ ssize_t (* const show)(struct kobject *, struct attribute *, char *);
++ ssize_t (* const store)(struct kobject *, struct attribute *, const char *, size_t);
+ };
+
+ [ Subsystems should have already defined a struct kobj_type as a
+diff -urNp linux-2.6.38.7/Documentation/kernel-parameters.txt linux-2.6.38.7/Documentation/kernel-parameters.txt
+--- linux-2.6.38.7/Documentation/kernel-parameters.txt 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/Documentation/kernel-parameters.txt 2011-04-28 19:34:15.000000000 -0400
+@@ -1853,6 +1853,13 @@ bytes respectively. Such letter suffixes
+ the specified number of seconds. This is to be used if
+ your oopses keep scrolling off the screen.
+
++ pax_nouderef [X86] disables UDEREF. Most likely needed under certain
++ virtualization environments that don't cope well with the
++ expand down segment used by UDEREF on X86-32 or the frequent
++ page table updates on X86-64.
++
++ pax_softmode= 0/1 to disable/enable PaX softmode on boot already.
++
+ pcbit= [HW,ISDN]
+
+ pcd. [PARIDE]
+diff -urNp linux-2.6.38.7/drivers/acpi/apei/cper.c linux-2.6.38.7/drivers/acpi/apei/cper.c
+--- linux-2.6.38.7/drivers/acpi/apei/cper.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/acpi/apei/cper.c 2011-04-28 19:57:25.000000000 -0400
+@@ -37,12 +37,12 @@
+ */
+ u64 cper_next_record_id(void)
+ {
+- static atomic64_t seq;
++ static atomic64_unchecked_t seq;
+
+- if (!atomic64_read(&seq))
+- atomic64_set(&seq, ((u64)get_seconds()) << 32);
++ if (!atomic64_read_unchecked(&seq))
++ atomic64_set_unchecked(&seq, ((u64)get_seconds()) << 32);
+
+- return atomic64_inc_return(&seq);
++ return atomic64_inc_return_unchecked(&seq);
+ }
+ EXPORT_SYMBOL_GPL(cper_next_record_id);
+
+diff -urNp linux-2.6.38.7/drivers/acpi/battery.c linux-2.6.38.7/drivers/acpi/battery.c
+--- linux-2.6.38.7/drivers/acpi/battery.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/drivers/acpi/battery.c 2011-05-10 22:06:52.000000000 -0400
+@@ -864,7 +864,7 @@ DECLARE_FILE_FUNCTIONS(alarm);
+ }
+
+ static struct battery_file {
+- struct file_operations ops;
++ const struct file_operations ops;
+ mode_t mode;
+ const char *name;
+ } acpi_battery_file[] = {
+diff -urNp linux-2.6.38.7/drivers/acpi/dock.c linux-2.6.38.7/drivers/acpi/dock.c
+--- linux-2.6.38.7/drivers/acpi/dock.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/acpi/dock.c 2011-04-28 19:34:15.000000000 -0400
+@@ -77,7 +77,7 @@ struct dock_dependent_device {
+ struct list_head list;
+ struct list_head hotplug_list;
+ acpi_handle handle;
+- struct acpi_dock_ops *ops;
++ const struct acpi_dock_ops *ops;
+ void *context;
+ };
+
+@@ -589,7 +589,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifi
+ * the dock driver after _DCK is executed.
+ */
+ int
+-register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
++register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops,
+ void *context)
+ {
+ struct dock_dependent_device *dd;
+diff -urNp linux-2.6.38.7/drivers/acpi/ec_sys.c linux-2.6.38.7/drivers/acpi/ec_sys.c
+--- linux-2.6.38.7/drivers/acpi/ec_sys.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/acpi/ec_sys.c 2011-04-28 19:34:15.000000000 -0400
+@@ -96,7 +96,7 @@ static ssize_t acpi_ec_write_io(struct f
+ return count;
+ }
+
+-static struct file_operations acpi_ec_io_ops = {
++static const struct file_operations acpi_ec_io_ops = {
+ .owner = THIS_MODULE,
+ .open = acpi_ec_open_io,
+ .read = acpi_ec_read_io,
+diff -urNp linux-2.6.38.7/drivers/acpi/power_meter.c linux-2.6.38.7/drivers/acpi/power_meter.c
+--- linux-2.6.38.7/drivers/acpi/power_meter.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/acpi/power_meter.c 2011-04-28 19:34:15.000000000 -0400
+@@ -316,8 +316,6 @@ static ssize_t set_trip(struct device *d
+ return res;
+
+ temp /= 1000;
+- if (temp < 0)
+- return -EINVAL;
+
+ mutex_lock(&resource->lock);
+ resource->trip[attr->index - 7] = temp;
+diff -urNp linux-2.6.38.7/drivers/acpi/proc.c linux-2.6.38.7/drivers/acpi/proc.c
+--- linux-2.6.38.7/drivers/acpi/proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/acpi/proc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -342,19 +342,13 @@ acpi_system_write_wakeup_device(struct f
+ size_t count, loff_t * ppos)
+ {
+ struct list_head *node, *next;
+- char strbuf[5];
+- char str[5] = "";
+- unsigned int len = count;
+-
+- if (len > 4)
+- len = 4;
+- if (len < 0)
+- return -EFAULT;
++ char strbuf[5] = {0};
+
+- if (copy_from_user(strbuf, buffer, len))
++ if (count > 4)
++ count = 4;
++ if (copy_from_user(strbuf, buffer, count))
+ return -EFAULT;
+- strbuf[len] = '\0';
+- sscanf(strbuf, "%s", str);
++ strbuf[count] = '\0';
+
+ mutex_lock(&acpi_device_lock);
+ list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+@@ -363,7 +357,7 @@ acpi_system_write_wakeup_device(struct f
+ if (!dev->wakeup.flags.valid)
+ continue;
+
+- if (!strncmp(dev->pnp.bus_id, str, 4)) {
++ if (!strncmp(dev->pnp.bus_id, strbuf, 4)) {
+ if (device_can_wakeup(&dev->dev)) {
+ bool enable = !device_may_wakeup(&dev->dev);
+ device_set_wakeup_enable(&dev->dev, enable);
+diff -urNp linux-2.6.38.7/drivers/acpi/processor_driver.c linux-2.6.38.7/drivers/acpi/processor_driver.c
+--- linux-2.6.38.7/drivers/acpi/processor_driver.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/acpi/processor_driver.c 2011-04-28 19:34:15.000000000 -0400
+@@ -473,7 +473,7 @@ static int __cpuinit acpi_processor_add(
+ return 0;
+ #endif
+
+- BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
++ BUG_ON(pr->id >= nr_cpu_ids);
+
+ /*
+ * Buggy BIOS check
+diff -urNp linux-2.6.38.7/drivers/acpi/processor_idle.c linux-2.6.38.7/drivers/acpi/processor_idle.c
+--- linux-2.6.38.7/drivers/acpi/processor_idle.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/acpi/processor_idle.c 2011-04-28 19:34:15.000000000 -0400
+@@ -121,7 +121,7 @@ static struct dmi_system_id __cpuinitdat
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")},
+ (void *)1},
+- {},
++ {}
+ };
+
+
+diff -urNp linux-2.6.38.7/drivers/ata/acard-ahci.c linux-2.6.38.7/drivers/ata/acard-ahci.c
+--- linux-2.6.38.7/drivers/ata/acard-ahci.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/acard-ahci.c 2011-04-28 19:34:15.000000000 -0400
+@@ -87,7 +87,7 @@ static struct scsi_host_template acard_a
+ AHCI_SHT("acard-ahci"),
+ };
+
+-static struct ata_port_operations acard_ops = {
++static const struct ata_port_operations acard_ops = {
+ .inherits = &ahci_ops,
+ .qc_prep = acard_ahci_qc_prep,
+ .qc_fill_rtf = acard_ahci_qc_fill_rtf,
+diff -urNp linux-2.6.38.7/drivers/ata/ahci.c linux-2.6.38.7/drivers/ata/ahci.c
+--- linux-2.6.38.7/drivers/ata/ahci.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/ahci.c 2011-05-10 22:06:52.000000000 -0400
+@@ -94,17 +94,17 @@ static struct scsi_host_template ahci_sh
+ AHCI_SHT("ahci"),
+ };
+
+-static struct ata_port_operations ahci_vt8251_ops = {
++static const struct ata_port_operations ahci_vt8251_ops = {
+ .inherits = &ahci_ops,
+ .hardreset = ahci_vt8251_hardreset,
+ };
+
+-static struct ata_port_operations ahci_p5wdh_ops = {
++static const struct ata_port_operations ahci_p5wdh_ops = {
+ .inherits = &ahci_ops,
+ .hardreset = ahci_p5wdh_hardreset,
+ };
+
+-static struct ata_port_operations ahci_sb600_ops = {
++static const struct ata_port_operations ahci_sb600_ops = {
+ .inherits = &ahci_ops,
+ .softreset = ahci_sb600_softreset,
+ .pmp_softreset = ahci_sb600_softreset,
+diff -urNp linux-2.6.38.7/drivers/ata/ahci.h linux-2.6.38.7/drivers/ata/ahci.h
+--- linux-2.6.38.7/drivers/ata/ahci.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/ahci.h 2011-04-28 19:34:15.000000000 -0400
+@@ -309,7 +309,7 @@ extern struct device_attribute *ahci_sde
+ .shost_attrs = ahci_shost_attrs, \
+ .sdev_attrs = ahci_sdev_attrs
+
+-extern struct ata_port_operations ahci_ops;
++extern const struct ata_port_operations ahci_ops;
+
+ void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+ u32 opts);
+diff -urNp linux-2.6.38.7/drivers/ata/ata_generic.c linux-2.6.38.7/drivers/ata/ata_generic.c
+--- linux-2.6.38.7/drivers/ata/ata_generic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/ata_generic.c 2011-04-28 19:34:15.000000000 -0400
+@@ -101,7 +101,7 @@ static struct scsi_host_template generic
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations generic_port_ops = {
++static const struct ata_port_operations generic_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_unknown,
+ .set_mode = generic_set_mode,
+diff -urNp linux-2.6.38.7/drivers/ata/ata_piix.c linux-2.6.38.7/drivers/ata/ata_piix.c
+--- linux-2.6.38.7/drivers/ata/ata_piix.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/ata_piix.c 2011-04-28 19:34:15.000000000 -0400
+@@ -327,12 +327,12 @@ static struct scsi_host_template piix_sh
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations piix_sata_ops = {
++static const struct ata_port_operations piix_sata_ops = {
+ .inherits = &ata_bmdma32_port_ops,
+ .sff_irq_check = piix_irq_check,
+ };
+
+-static struct ata_port_operations piix_pata_ops = {
++static const struct ata_port_operations piix_pata_ops = {
+ .inherits = &piix_sata_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = piix_set_piomode,
+@@ -340,12 +340,12 @@ static struct ata_port_operations piix_p
+ .prereset = piix_pata_prereset,
+ };
+
+-static struct ata_port_operations piix_vmw_ops = {
++static const struct ata_port_operations piix_vmw_ops = {
+ .inherits = &piix_pata_ops,
+ .bmdma_status = piix_vmw_bmdma_status,
+ };
+
+-static struct ata_port_operations ich_pata_ops = {
++static const struct ata_port_operations ich_pata_ops = {
+ .inherits = &piix_pata_ops,
+ .cable_detect = ich_pata_cable_detect,
+ .set_dmamode = ich_set_dmamode,
+@@ -361,7 +361,7 @@ static struct scsi_host_template piix_si
+ .shost_attrs = piix_sidpr_shost_attrs,
+ };
+
+-static struct ata_port_operations piix_sidpr_sata_ops = {
++static const struct ata_port_operations piix_sidpr_sata_ops = {
+ .inherits = &piix_sata_ops,
+ .hardreset = sata_std_hardreset,
+ .scr_read = piix_sidpr_scr_read,
+diff -urNp linux-2.6.38.7/drivers/ata/libahci.c linux-2.6.38.7/drivers/ata/libahci.c
+--- linux-2.6.38.7/drivers/ata/libahci.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/libahci.c 2011-05-10 22:06:52.000000000 -0400
+@@ -137,7 +137,7 @@ struct device_attribute *ahci_sdev_attrs
+ };
+ EXPORT_SYMBOL_GPL(ahci_sdev_attrs);
+
+-struct ata_port_operations ahci_ops = {
++const struct ata_port_operations ahci_ops = {
+ .inherits = &sata_pmp_port_ops,
+
+ .qc_defer = ahci_pmp_qc_defer,
+diff -urNp linux-2.6.38.7/drivers/ata/libata-acpi.c linux-2.6.38.7/drivers/ata/libata-acpi.c
+--- linux-2.6.38.7/drivers/ata/libata-acpi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/libata-acpi.c 2011-04-28 19:34:15.000000000 -0400
+@@ -218,12 +218,12 @@ static void ata_acpi_dev_uevent(acpi_han
+ ata_acpi_uevent(dev->link->ap, dev, event);
+ }
+
+-static struct acpi_dock_ops ata_acpi_dev_dock_ops = {
++static const struct acpi_dock_ops ata_acpi_dev_dock_ops = {
+ .handler = ata_acpi_dev_notify_dock,
+ .uevent = ata_acpi_dev_uevent,
+ };
+
+-static struct acpi_dock_ops ata_acpi_ap_dock_ops = {
++static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
+ .handler = ata_acpi_ap_notify_dock,
+ .uevent = ata_acpi_ap_uevent,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/libata-core.c linux-2.6.38.7/drivers/ata/libata-core.c
+--- linux-2.6.38.7/drivers/ata/libata-core.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/libata-core.c 2011-05-10 22:06:52.000000000 -0400
+@@ -4746,7 +4746,7 @@ void ata_qc_free(struct ata_queued_cmd *
+ struct ata_port *ap;
+ unsigned int tag;
+
+- WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
++ BUG_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
+ ap = qc->ap;
+
+ qc->flags = 0;
+@@ -4762,7 +4762,7 @@ void __ata_qc_complete(struct ata_queued
+ struct ata_port *ap;
+ struct ata_link *link;
+
+- WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
++ BUG_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
+ WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE));
+ ap = qc->ap;
+ link = qc->dev->link;
+@@ -5755,7 +5755,7 @@ static void ata_host_stop(struct device
+ * LOCKING:
+ * None.
+ */
+-static void ata_finalize_port_ops(struct ata_port_operations *ops)
++static void ata_finalize_port_ops(const struct ata_port_operations *ops)
+ {
+ static DEFINE_SPINLOCK(lock);
+ const struct ata_port_operations *cur;
+@@ -5767,6 +5767,7 @@ static void ata_finalize_port_ops(struct
+ return;
+
+ spin_lock(&lock);
++ pax_open_kernel();
+
+ for (cur = ops->inherits; cur; cur = cur->inherits) {
+ void **inherit = (void **)cur;
+@@ -5780,8 +5781,9 @@ static void ata_finalize_port_ops(struct
+ if (IS_ERR(*pp))
+ *pp = NULL;
+
+- ops->inherits = NULL;
++ ((struct ata_port_operations *)ops)->inherits = NULL;
+
++ pax_close_kernel();
+ spin_unlock(&lock);
+ }
+
+@@ -5878,7 +5880,7 @@ int ata_host_start(struct ata_host *host
+ */
+ /* KILLME - the only user left is ipr */
+ void ata_host_init(struct ata_host *host, struct device *dev,
+- unsigned long flags, struct ata_port_operations *ops)
++ unsigned long flags, const struct ata_port_operations *ops)
+ {
+ spin_lock_init(&host->lock);
+ mutex_init(&host->eh_mutex);
+@@ -6584,7 +6586,7 @@ static void ata_dummy_error_handler(stru
+ /* truly dummy */
+ }
+
+-struct ata_port_operations ata_dummy_port_ops = {
++const struct ata_port_operations ata_dummy_port_ops = {
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = ata_dummy_qc_issue,
+ .error_handler = ata_dummy_error_handler,
+diff -urNp linux-2.6.38.7/drivers/ata/libata-eh.c linux-2.6.38.7/drivers/ata/libata-eh.c
+--- linux-2.6.38.7/drivers/ata/libata-eh.c 2011-05-22 23:05:18.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/libata-eh.c 2011-05-17 19:31:43.000000000 -0400
+@@ -2478,6 +2478,8 @@ void ata_eh_report(struct ata_port *ap)
+ {
+ struct ata_link *link;
+
++ pax_track_stack();
++
+ ata_for_each_link(link, ap, HOST_FIRST)
+ ata_eh_link_report(link);
+ }
+@@ -3882,7 +3884,7 @@ void ata_do_eh(struct ata_port *ap, ata_
+ */
+ void ata_std_error_handler(struct ata_port *ap)
+ {
+- struct ata_port_operations *ops = ap->ops;
++ const struct ata_port_operations *ops = ap->ops;
+ ata_reset_fn_t hardreset = ops->hardreset;
+
+ /* ignore built-in hardreset if SCR access is not available */
+diff -urNp linux-2.6.38.7/drivers/ata/libata-pmp.c linux-2.6.38.7/drivers/ata/libata-pmp.c
+--- linux-2.6.38.7/drivers/ata/libata-pmp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/libata-pmp.c 2011-04-28 19:34:15.000000000 -0400
+@@ -912,7 +912,7 @@ static int sata_pmp_handle_link_fail(str
+ */
+ static int sata_pmp_eh_recover(struct ata_port *ap)
+ {
+- struct ata_port_operations *ops = ap->ops;
++ const struct ata_port_operations *ops = ap->ops;
+ int pmp_tries, link_tries[SATA_PMP_MAX_PORTS];
+ struct ata_link *pmp_link = &ap->link;
+ struct ata_device *pmp_dev = pmp_link->device;
+diff -urNp linux-2.6.38.7/drivers/ata/pata_acpi.c linux-2.6.38.7/drivers/ata/pata_acpi.c
+--- linux-2.6.38.7/drivers/ata/pata_acpi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_acpi.c 2011-04-28 19:34:15.000000000 -0400
+@@ -216,7 +216,7 @@ static struct scsi_host_template pacpi_s
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations pacpi_ops = {
++static const struct ata_port_operations pacpi_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .qc_issue = pacpi_qc_issue,
+ .cable_detect = pacpi_cable_detect,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_ali.c linux-2.6.38.7/drivers/ata/pata_ali.c
+--- linux-2.6.38.7/drivers/ata/pata_ali.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_ali.c 2011-04-28 19:34:15.000000000 -0400
+@@ -363,7 +363,7 @@ static struct scsi_host_template ali_sht
+ * Port operations for PIO only ALi
+ */
+
+-static struct ata_port_operations ali_early_port_ops = {
++static const struct ata_port_operations ali_early_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = ali_set_piomode,
+@@ -380,7 +380,7 @@ static const struct ata_port_operations
+ * Port operations for DMA capable ALi without cable
+ * detect
+ */
+-static struct ata_port_operations ali_20_port_ops = {
++static const struct ata_port_operations ali_20_port_ops = {
+ .inherits = &ali_dma_base_ops,
+ .cable_detect = ata_cable_40wire,
+ .mode_filter = ali_20_filter,
+@@ -391,7 +391,7 @@ static struct ata_port_operations ali_20
+ /*
+ * Port operations for DMA capable ALi with cable detect
+ */
+-static struct ata_port_operations ali_c2_port_ops = {
++static const struct ata_port_operations ali_c2_port_ops = {
+ .inherits = &ali_dma_base_ops,
+ .check_atapi_dma = ali_check_atapi_dma,
+ .cable_detect = ali_c2_cable_detect,
+@@ -402,7 +402,7 @@ static struct ata_port_operations ali_c2
+ /*
+ * Port operations for DMA capable ALi with cable detect
+ */
+-static struct ata_port_operations ali_c4_port_ops = {
++static const struct ata_port_operations ali_c4_port_ops = {
+ .inherits = &ali_dma_base_ops,
+ .check_atapi_dma = ali_check_atapi_dma,
+ .cable_detect = ali_c2_cable_detect,
+@@ -412,7 +412,7 @@ static struct ata_port_operations ali_c4
+ /*
+ * Port operations for DMA capable ALi with cable detect and LBA48
+ */
+-static struct ata_port_operations ali_c5_port_ops = {
++static const struct ata_port_operations ali_c5_port_ops = {
+ .inherits = &ali_dma_base_ops,
+ .check_atapi_dma = ali_check_atapi_dma,
+ .dev_config = ali_warn_atapi_dma,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_amd.c linux-2.6.38.7/drivers/ata/pata_amd.c
+--- linux-2.6.38.7/drivers/ata/pata_amd.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_amd.c 2011-04-28 19:34:15.000000000 -0400
+@@ -397,28 +397,28 @@ static const struct ata_port_operations
+ .prereset = amd_pre_reset,
+ };
+
+-static struct ata_port_operations amd33_port_ops = {
++static const struct ata_port_operations amd33_port_ops = {
+ .inherits = &amd_base_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = amd33_set_piomode,
+ .set_dmamode = amd33_set_dmamode,
+ };
+
+-static struct ata_port_operations amd66_port_ops = {
++static const struct ata_port_operations amd66_port_ops = {
+ .inherits = &amd_base_port_ops,
+ .cable_detect = ata_cable_unknown,
+ .set_piomode = amd66_set_piomode,
+ .set_dmamode = amd66_set_dmamode,
+ };
+
+-static struct ata_port_operations amd100_port_ops = {
++static const struct ata_port_operations amd100_port_ops = {
+ .inherits = &amd_base_port_ops,
+ .cable_detect = ata_cable_unknown,
+ .set_piomode = amd100_set_piomode,
+ .set_dmamode = amd100_set_dmamode,
+ };
+
+-static struct ata_port_operations amd133_port_ops = {
++static const struct ata_port_operations amd133_port_ops = {
+ .inherits = &amd_base_port_ops,
+ .cable_detect = amd_cable_detect,
+ .set_piomode = amd133_set_piomode,
+@@ -433,13 +433,13 @@ static const struct ata_port_operations
+ .host_stop = nv_host_stop,
+ };
+
+-static struct ata_port_operations nv100_port_ops = {
++static const struct ata_port_operations nv100_port_ops = {
+ .inherits = &nv_base_port_ops,
+ .set_piomode = nv100_set_piomode,
+ .set_dmamode = nv100_set_dmamode,
+ };
+
+-static struct ata_port_operations nv133_port_ops = {
++static const struct ata_port_operations nv133_port_ops = {
+ .inherits = &nv_base_port_ops,
+ .set_piomode = nv133_set_piomode,
+ .set_dmamode = nv133_set_dmamode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_artop.c linux-2.6.38.7/drivers/ata/pata_artop.c
+--- linux-2.6.38.7/drivers/ata/pata_artop.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_artop.c 2011-04-28 19:34:15.000000000 -0400
+@@ -312,7 +312,7 @@ static struct scsi_host_template artop_s
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations artop6210_ops = {
++static const struct ata_port_operations artop6210_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = artop6210_set_piomode,
+@@ -321,7 +321,7 @@ static struct ata_port_operations artop6
+ .qc_defer = artop6210_qc_defer,
+ };
+
+-static struct ata_port_operations artop6260_ops = {
++static const struct ata_port_operations artop6260_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = artop6260_cable_detect,
+ .set_piomode = artop6260_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_at32.c linux-2.6.38.7/drivers/ata/pata_at32.c
+--- linux-2.6.38.7/drivers/ata/pata_at32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_at32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -173,7 +173,7 @@ static struct scsi_host_template at32_sh
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations at32_port_ops = {
++static const struct ata_port_operations at32_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = pata_at32_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_at91.c linux-2.6.38.7/drivers/ata/pata_at91.c
+--- linux-2.6.38.7/drivers/ata/pata_at91.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_at91.c 2011-04-28 19:34:15.000000000 -0400
+@@ -196,7 +196,7 @@ static struct scsi_host_template pata_at
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations pata_at91_port_ops = {
++static const struct ata_port_operations pata_at91_port_ops = {
+ .inherits = &ata_sff_port_ops,
+
+ .sff_data_xfer = pata_at91_data_xfer_noirq,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_atiixp.c linux-2.6.38.7/drivers/ata/pata_atiixp.c
+--- linux-2.6.38.7/drivers/ata/pata_atiixp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_atiixp.c 2011-04-28 19:34:15.000000000 -0400
+@@ -214,7 +214,7 @@ static struct scsi_host_template atiixp_
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+ };
+
+-static struct ata_port_operations atiixp_port_ops = {
++static const struct ata_port_operations atiixp_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .qc_prep = ata_bmdma_dumb_qc_prep,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_atp867x.c linux-2.6.38.7/drivers/ata/pata_atp867x.c
+--- linux-2.6.38.7/drivers/ata/pata_atp867x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_atp867x.c 2011-04-28 19:34:15.000000000 -0400
+@@ -275,7 +275,7 @@ static struct scsi_host_template atp867x
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations atp867x_ops = {
++static const struct ata_port_operations atp867x_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = atp867x_cable_detect,
+ .set_piomode = atp867x_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_bf54x.c linux-2.6.38.7/drivers/ata/pata_bf54x.c
+--- linux-2.6.38.7/drivers/ata/pata_bf54x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_bf54x.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1420,7 +1420,7 @@ static struct scsi_host_template bfin_sh
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ };
+
+-static struct ata_port_operations bfin_pata_ops = {
++static const struct ata_port_operations bfin_pata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .set_piomode = bfin_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_cmd640.c linux-2.6.38.7/drivers/ata/pata_cmd640.c
+--- linux-2.6.38.7/drivers/ata/pata_cmd640.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_cmd640.c 2011-04-28 19:34:15.000000000 -0400
+@@ -176,7 +176,7 @@ static struct scsi_host_template cmd640_
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations cmd640_port_ops = {
++static const struct ata_port_operations cmd640_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ /* In theory xfer_noirq is not needed once we kill the prefetcher */
+ .sff_data_xfer = ata_sff_data_xfer_noirq,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_cmd64x.c linux-2.6.38.7/drivers/ata/pata_cmd64x.c
+--- linux-2.6.38.7/drivers/ata/pata_cmd64x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_cmd64x.c 2011-04-28 19:34:15.000000000 -0400
+@@ -268,18 +268,18 @@ static const struct ata_port_operations
+ .set_dmamode = cmd64x_set_dmamode,
+ };
+
+-static struct ata_port_operations cmd64x_port_ops = {
++static const struct ata_port_operations cmd64x_port_ops = {
+ .inherits = &cmd64x_base_ops,
+ .cable_detect = ata_cable_40wire,
+ };
+
+-static struct ata_port_operations cmd646r1_port_ops = {
++static const struct ata_port_operations cmd646r1_port_ops = {
+ .inherits = &cmd64x_base_ops,
+ .bmdma_stop = cmd646r1_bmdma_stop,
+ .cable_detect = ata_cable_40wire,
+ };
+
+-static struct ata_port_operations cmd648_port_ops = {
++static const struct ata_port_operations cmd648_port_ops = {
+ .inherits = &cmd64x_base_ops,
+ .bmdma_stop = cmd648_bmdma_stop,
+ .cable_detect = cmd648_cable_detect,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_cs5520.c linux-2.6.38.7/drivers/ata/pata_cs5520.c
+--- linux-2.6.38.7/drivers/ata/pata_cs5520.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_cs5520.c 2011-04-28 19:34:15.000000000 -0400
+@@ -108,7 +108,7 @@ static struct scsi_host_template cs5520_
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+ };
+
+-static struct ata_port_operations cs5520_port_ops = {
++static const struct ata_port_operations cs5520_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .qc_prep = ata_bmdma_dumb_qc_prep,
+ .cable_detect = ata_cable_40wire,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_cs5530.c linux-2.6.38.7/drivers/ata/pata_cs5530.c
+--- linux-2.6.38.7/drivers/ata/pata_cs5530.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_cs5530.c 2011-04-28 19:34:15.000000000 -0400
+@@ -164,7 +164,7 @@ static struct scsi_host_template cs5530_
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+ };
+
+-static struct ata_port_operations cs5530_port_ops = {
++static const struct ata_port_operations cs5530_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .qc_prep = ata_bmdma_dumb_qc_prep,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_cs5535.c linux-2.6.38.7/drivers/ata/pata_cs5535.c
+--- linux-2.6.38.7/drivers/ata/pata_cs5535.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_cs5535.c 2011-04-28 19:34:15.000000000 -0400
+@@ -160,7 +160,7 @@ static struct scsi_host_template cs5535_
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations cs5535_port_ops = {
++static const struct ata_port_operations cs5535_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = cs5535_cable_detect,
+ .set_piomode = cs5535_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_cs5536.c linux-2.6.38.7/drivers/ata/pata_cs5536.c
+--- linux-2.6.38.7/drivers/ata/pata_cs5536.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_cs5536.c 2011-04-28 19:34:15.000000000 -0400
+@@ -233,7 +233,7 @@ static struct scsi_host_template cs5536_
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations cs5536_port_ops = {
++static const struct ata_port_operations cs5536_port_ops = {
+ .inherits = &ata_bmdma32_port_ops,
+ .cable_detect = cs5536_cable_detect,
+ .set_piomode = cs5536_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_cypress.c linux-2.6.38.7/drivers/ata/pata_cypress.c
+--- linux-2.6.38.7/drivers/ata/pata_cypress.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_cypress.c 2011-04-28 19:34:15.000000000 -0400
+@@ -115,7 +115,7 @@ static struct scsi_host_template cy82c69
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations cy82c693_port_ops = {
++static const struct ata_port_operations cy82c693_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = cy82c693_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_efar.c linux-2.6.38.7/drivers/ata/pata_efar.c
+--- linux-2.6.38.7/drivers/ata/pata_efar.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_efar.c 2011-04-28 19:34:15.000000000 -0400
+@@ -238,7 +238,7 @@ static struct scsi_host_template efar_sh
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations efar_ops = {
++static const struct ata_port_operations efar_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = efar_cable_detect,
+ .set_piomode = efar_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_hpt366.c linux-2.6.38.7/drivers/ata/pata_hpt366.c
+--- linux-2.6.38.7/drivers/ata/pata_hpt366.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_hpt366.c 2011-04-28 19:34:15.000000000 -0400
+@@ -275,7 +275,7 @@ static struct scsi_host_template hpt36x_
+ * Configuration for HPT366/68
+ */
+
+-static struct ata_port_operations hpt366_port_ops = {
++static const struct ata_port_operations hpt366_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = hpt36x_cable_detect,
+ .mode_filter = hpt366_filter,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_hpt37x.c linux-2.6.38.7/drivers/ata/pata_hpt37x.c
+--- linux-2.6.38.7/drivers/ata/pata_hpt37x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_hpt37x.c 2011-04-28 19:34:15.000000000 -0400
+@@ -587,7 +587,7 @@ static struct scsi_host_template hpt37x_
+ * Configuration for HPT370
+ */
+
+-static struct ata_port_operations hpt370_port_ops = {
++static const struct ata_port_operations hpt370_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .bmdma_stop = hpt370_bmdma_stop,
+@@ -603,7 +603,7 @@ static struct ata_port_operations hpt370
+ * Configuration for HPT370A. Close to 370 but less filters
+ */
+
+-static struct ata_port_operations hpt370a_port_ops = {
++static const struct ata_port_operations hpt370a_port_ops = {
+ .inherits = &hpt370_port_ops,
+ .mode_filter = hpt370a_filter,
+ };
+@@ -613,7 +613,7 @@ static struct ata_port_operations hpt370
+ * mode setting functionality.
+ */
+
+-static struct ata_port_operations hpt302_port_ops = {
++static const struct ata_port_operations hpt302_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .bmdma_stop = hpt37x_bmdma_stop,
+@@ -629,7 +629,7 @@ static struct ata_port_operations hpt302
+ * but we have a mode filter.
+ */
+
+-static struct ata_port_operations hpt372_port_ops = {
++static const struct ata_port_operations hpt372_port_ops = {
+ .inherits = &hpt302_port_ops,
+ .mode_filter = hpt372_filter,
+ };
+@@ -639,7 +639,7 @@ static struct ata_port_operations hpt372
+ * but we have a different cable detection procedure for function 1.
+ */
+
+-static struct ata_port_operations hpt374_fn1_port_ops = {
++static const struct ata_port_operations hpt374_fn1_port_ops = {
+ .inherits = &hpt372_port_ops,
+ .cable_detect = hpt374_fn1_cable_detect,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/pata_hpt3x2n.c linux-2.6.38.7/drivers/ata/pata_hpt3x2n.c
+--- linux-2.6.38.7/drivers/ata/pata_hpt3x2n.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_hpt3x2n.c 2011-04-28 19:34:15.000000000 -0400
+@@ -348,7 +348,7 @@ static struct scsi_host_template hpt3x2n
+ * Configuration for HPT302N/371N.
+ */
+
+-static struct ata_port_operations hpt3xxn_port_ops = {
++static const struct ata_port_operations hpt3xxn_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .bmdma_stop = hpt3x2n_bmdma_stop,
+@@ -366,7 +366,7 @@ static struct ata_port_operations hpt3xx
+ * Configuration for HPT372N. Same as 302N/371N but we have a mode filter.
+ */
+
+-static struct ata_port_operations hpt372n_port_ops = {
++static const struct ata_port_operations hpt372n_port_ops = {
+ .inherits = &hpt3xxn_port_ops,
+ .mode_filter = &hpt372n_filter,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/pata_hpt3x3.c linux-2.6.38.7/drivers/ata/pata_hpt3x3.c
+--- linux-2.6.38.7/drivers/ata/pata_hpt3x3.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_hpt3x3.c 2011-04-28 19:34:15.000000000 -0400
+@@ -141,7 +141,7 @@ static struct scsi_host_template hpt3x3_
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations hpt3x3_port_ops = {
++static const struct ata_port_operations hpt3x3_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = hpt3x3_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_icside.c linux-2.6.38.7/drivers/ata/pata_icside.c
+--- linux-2.6.38.7/drivers/ata/pata_icside.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_icside.c 2011-04-28 19:34:15.000000000 -0400
+@@ -320,7 +320,7 @@ static void pata_icside_postreset(struct
+ }
+ }
+
+-static struct ata_port_operations pata_icside_port_ops = {
++static const struct ata_port_operations pata_icside_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ /* no need to build any PRD tables for DMA */
+ .qc_prep = ata_noop_qc_prep,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_isapnp.c linux-2.6.38.7/drivers/ata/pata_isapnp.c
+--- linux-2.6.38.7/drivers/ata/pata_isapnp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_isapnp.c 2011-04-28 19:34:15.000000000 -0400
+@@ -23,12 +23,12 @@ static struct scsi_host_template isapnp_
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations isapnp_port_ops = {
++static const struct ata_port_operations isapnp_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+ };
+
+-static struct ata_port_operations isapnp_noalt_port_ops = {
++static const struct ata_port_operations isapnp_noalt_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+ /* No altstatus so we don't want to use the lost interrupt poll */
+diff -urNp linux-2.6.38.7/drivers/ata/pata_it8213.c linux-2.6.38.7/drivers/ata/pata_it8213.c
+--- linux-2.6.38.7/drivers/ata/pata_it8213.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_it8213.c 2011-04-28 19:34:15.000000000 -0400
+@@ -233,7 +233,7 @@ static struct scsi_host_template it8213_
+ };
+
+
+-static struct ata_port_operations it8213_ops = {
++static const struct ata_port_operations it8213_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = it8213_cable_detect,
+ .set_piomode = it8213_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_it821x.c linux-2.6.38.7/drivers/ata/pata_it821x.c
+--- linux-2.6.38.7/drivers/ata/pata_it821x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_it821x.c 2011-04-28 19:34:15.000000000 -0400
+@@ -801,7 +801,7 @@ static struct scsi_host_template it821x_
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations it821x_smart_port_ops = {
++static const struct ata_port_operations it821x_smart_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .check_atapi_dma= it821x_check_atapi_dma,
+@@ -815,7 +815,7 @@ static struct ata_port_operations it821x
+ .port_start = it821x_port_start,
+ };
+
+-static struct ata_port_operations it821x_passthru_port_ops = {
++static const struct ata_port_operations it821x_passthru_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .check_atapi_dma= it821x_check_atapi_dma,
+@@ -831,7 +831,7 @@ static struct ata_port_operations it821x
+ .port_start = it821x_port_start,
+ };
+
+-static struct ata_port_operations it821x_rdc_port_ops = {
++static const struct ata_port_operations it821x_rdc_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .check_atapi_dma= it821x_check_atapi_dma,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_ixp4xx_cf.c linux-2.6.38.7/drivers/ata/pata_ixp4xx_cf.c
+--- linux-2.6.38.7/drivers/ata/pata_ixp4xx_cf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_ixp4xx_cf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -89,7 +89,7 @@ static struct scsi_host_template ixp4xx_
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations ixp4xx_port_ops = {
++static const struct ata_port_operations ixp4xx_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_data_xfer = ixp4xx_mmio_data_xfer,
+ .cable_detect = ata_cable_40wire,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_jmicron.c linux-2.6.38.7/drivers/ata/pata_jmicron.c
+--- linux-2.6.38.7/drivers/ata/pata_jmicron.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_jmicron.c 2011-04-28 19:34:15.000000000 -0400
+@@ -111,7 +111,7 @@ static struct scsi_host_template jmicron
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations jmicron_ops = {
++static const struct ata_port_operations jmicron_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .prereset = jmicron_pre_reset,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/pata_legacy.c linux-2.6.38.7/drivers/ata/pata_legacy.c
+--- linux-2.6.38.7/drivers/ata/pata_legacy.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_legacy.c 2011-04-28 19:34:15.000000000 -0400
+@@ -116,7 +116,7 @@ struct legacy_probe {
+
+ struct legacy_controller {
+ const char *name;
+- struct ata_port_operations *ops;
++ const struct ata_port_operations *ops;
+ unsigned int pio_mask;
+ unsigned int flags;
+ unsigned int pflags;
+@@ -239,12 +239,12 @@ static const struct ata_port_operations
+ * pio_mask as well.
+ */
+
+-static struct ata_port_operations simple_port_ops = {
++static const struct ata_port_operations simple_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ };
+
+-static struct ata_port_operations legacy_port_ops = {
++static const struct ata_port_operations legacy_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .set_mode = legacy_set_mode,
+@@ -340,7 +340,7 @@ static unsigned int pdc_data_xfer_vlb(st
+ return buflen;
+ }
+
+-static struct ata_port_operations pdc20230_port_ops = {
++static const struct ata_port_operations pdc20230_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = pdc20230_set_piomode,
+ .sff_data_xfer = pdc_data_xfer_vlb,
+@@ -373,7 +373,7 @@ static void ht6560a_set_piomode(struct a
+ ioread8(ap->ioaddr.status_addr);
+ }
+
+-static struct ata_port_operations ht6560a_port_ops = {
++static const struct ata_port_operations ht6560a_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = ht6560a_set_piomode,
+ };
+@@ -416,7 +416,7 @@ static void ht6560b_set_piomode(struct a
+ ioread8(ap->ioaddr.status_addr);
+ }
+
+-static struct ata_port_operations ht6560b_port_ops = {
++static const struct ata_port_operations ht6560b_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = ht6560b_set_piomode,
+ };
+@@ -515,7 +515,7 @@ static void opti82c611a_set_piomode(stru
+ }
+
+
+-static struct ata_port_operations opti82c611a_port_ops = {
++static const struct ata_port_operations opti82c611a_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = opti82c611a_set_piomode,
+ };
+@@ -625,7 +625,7 @@ static unsigned int opti82c46x_qc_issue(
+ return ata_sff_qc_issue(qc);
+ }
+
+-static struct ata_port_operations opti82c46x_port_ops = {
++static const struct ata_port_operations opti82c46x_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = opti82c46x_set_piomode,
+ .qc_issue = opti82c46x_qc_issue,
+@@ -787,20 +787,20 @@ static int qdi_port(struct platform_devi
+ return 0;
+ }
+
+-static struct ata_port_operations qdi6500_port_ops = {
++static const struct ata_port_operations qdi6500_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6500_set_piomode,
+ .qc_issue = qdi_qc_issue,
+ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+-static struct ata_port_operations qdi6580_port_ops = {
++static const struct ata_port_operations qdi6580_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6580_set_piomode,
+ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+-static struct ata_port_operations qdi6580dp_port_ops = {
++static const struct ata_port_operations qdi6580dp_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6580dp_set_piomode,
+ .qc_issue = qdi_qc_issue,
+@@ -872,7 +872,7 @@ static int winbond_port(struct platform_
+ return 0;
+ }
+
+-static struct ata_port_operations winbond_port_ops = {
++static const struct ata_port_operations winbond_port_ops = {
+ .inherits = &legacy_base_port_ops,
+ .set_piomode = winbond_set_piomode,
+ .sff_data_xfer = vlb32_data_xfer,
+@@ -995,7 +995,7 @@ static __init int legacy_init_one(struct
+ int pio_modes = controller->pio_mask;
+ unsigned long io = probe->port;
+ u32 mask = (1 << probe->slot);
+- struct ata_port_operations *ops = controller->ops;
++ const struct ata_port_operations *ops = controller->ops;
+ struct legacy_data *ld = &legacy_data[probe->slot];
+ struct ata_host *host = NULL;
+ struct ata_port *ap;
+diff -urNp linux-2.6.38.7/drivers/ata/pata_macio.c linux-2.6.38.7/drivers/ata/pata_macio.c
+--- linux-2.6.38.7/drivers/ata/pata_macio.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_macio.c 2011-04-28 19:34:15.000000000 -0400
+@@ -918,9 +918,8 @@ static struct scsi_host_template pata_ma
+ .slave_configure = pata_macio_slave_config,
+ };
+
+-static struct ata_port_operations pata_macio_ops = {
++static const struct ata_port_operations pata_macio_ops = {
+ .inherits = &ata_bmdma_port_ops,
+-
+ .freeze = pata_macio_freeze,
+ .set_piomode = pata_macio_set_timings,
+ .set_dmamode = pata_macio_set_timings,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_marvell.c linux-2.6.38.7/drivers/ata/pata_marvell.c
+--- linux-2.6.38.7/drivers/ata/pata_marvell.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_marvell.c 2011-04-28 19:34:15.000000000 -0400
+@@ -100,7 +100,7 @@ static struct scsi_host_template marvell
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations marvell_ops = {
++static const struct ata_port_operations marvell_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = marvell_cable_detect,
+ .prereset = marvell_pre_reset,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_mpc52xx.c linux-2.6.38.7/drivers/ata/pata_mpc52xx.c
+--- linux-2.6.38.7/drivers/ata/pata_mpc52xx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_mpc52xx.c 2011-04-28 19:34:15.000000000 -0400
+@@ -609,7 +609,7 @@ static struct scsi_host_template mpc52xx
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations mpc52xx_ata_port_ops = {
++static const struct ata_port_operations mpc52xx_ata_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .sff_dev_select = mpc52xx_ata_dev_select,
+ .set_piomode = mpc52xx_ata_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_mpiix.c linux-2.6.38.7/drivers/ata/pata_mpiix.c
+--- linux-2.6.38.7/drivers/ata/pata_mpiix.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_mpiix.c 2011-04-28 19:34:15.000000000 -0400
+@@ -140,7 +140,7 @@ static struct scsi_host_template mpiix_s
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations mpiix_port_ops = {
++static const struct ata_port_operations mpiix_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .qc_issue = mpiix_qc_issue,
+ .cable_detect = ata_cable_40wire,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_netcell.c linux-2.6.38.7/drivers/ata/pata_netcell.c
+--- linux-2.6.38.7/drivers/ata/pata_netcell.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_netcell.c 2011-04-28 19:34:15.000000000 -0400
+@@ -34,7 +34,7 @@ static struct scsi_host_template netcell
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations netcell_ops = {
++static const struct ata_port_operations netcell_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_80wire,
+ .read_id = netcell_read_id,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_ninja32.c linux-2.6.38.7/drivers/ata/pata_ninja32.c
+--- linux-2.6.38.7/drivers/ata/pata_ninja32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_ninja32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -81,7 +81,7 @@ static struct scsi_host_template ninja32
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations ninja32_port_ops = {
++static const struct ata_port_operations ninja32_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .sff_dev_select = ninja32_dev_select,
+ .cable_detect = ata_cable_40wire,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_ns87410.c linux-2.6.38.7/drivers/ata/pata_ns87410.c
+--- linux-2.6.38.7/drivers/ata/pata_ns87410.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_ns87410.c 2011-04-28 19:34:15.000000000 -0400
+@@ -132,7 +132,7 @@ static struct scsi_host_template ns87410
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations ns87410_port_ops = {
++static const struct ata_port_operations ns87410_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .qc_issue = ns87410_qc_issue,
+ .cable_detect = ata_cable_40wire,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_ns87415.c linux-2.6.38.7/drivers/ata/pata_ns87415.c
+--- linux-2.6.38.7/drivers/ata/pata_ns87415.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_ns87415.c 2011-04-28 19:34:15.000000000 -0400
+@@ -299,7 +299,7 @@ static u8 ns87560_bmdma_status(struct at
+ }
+ #endif /* 87560 SuperIO Support */
+
+-static struct ata_port_operations ns87415_pata_ops = {
++static const struct ata_port_operations ns87415_pata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .check_atapi_dma = ns87415_check_atapi_dma,
+@@ -313,7 +313,7 @@ static struct ata_port_operations ns8741
+ };
+
+ #if defined(CONFIG_SUPERIO)
+-static struct ata_port_operations ns87560_pata_ops = {
++static const struct ata_port_operations ns87560_pata_ops = {
+ .inherits = &ns87415_pata_ops,
+ .sff_tf_read = ns87560_tf_read,
+ .sff_check_status = ns87560_check_status,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_octeon_cf.c linux-2.6.38.7/drivers/ata/pata_octeon_cf.c
+--- linux-2.6.38.7/drivers/ata/pata_octeon_cf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_octeon_cf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -780,7 +780,7 @@ static unsigned int octeon_cf_qc_issue(s
+ return 0;
+ }
+
+-static struct ata_port_operations octeon_cf_ops = {
++static struct ata_port_operations octeon_cf_ops = { /* cannot be const */
+ .inherits = &ata_sff_port_ops,
+ .check_atapi_dma = octeon_cf_check_atapi_dma,
+ .qc_prep = ata_noop_qc_prep,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_oldpiix.c linux-2.6.38.7/drivers/ata/pata_oldpiix.c
+--- linux-2.6.38.7/drivers/ata/pata_oldpiix.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_oldpiix.c 2011-04-28 19:34:15.000000000 -0400
+@@ -208,7 +208,7 @@ static struct scsi_host_template oldpiix
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations oldpiix_pata_ops = {
++static const struct ata_port_operations oldpiix_pata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .qc_issue = oldpiix_qc_issue,
+ .cable_detect = ata_cable_40wire,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_opti.c linux-2.6.38.7/drivers/ata/pata_opti.c
+--- linux-2.6.38.7/drivers/ata/pata_opti.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_opti.c 2011-04-28 19:34:15.000000000 -0400
+@@ -152,7 +152,7 @@ static struct scsi_host_template opti_sh
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations opti_port_ops = {
++static const struct ata_port_operations opti_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = opti_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_optidma.c linux-2.6.38.7/drivers/ata/pata_optidma.c
+--- linux-2.6.38.7/drivers/ata/pata_optidma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_optidma.c 2011-04-28 19:34:15.000000000 -0400
+@@ -337,7 +337,7 @@ static struct scsi_host_template optidma
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations optidma_port_ops = {
++static const struct ata_port_operations optidma_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = optidma_set_pio_mode,
+@@ -346,7 +346,7 @@ static struct ata_port_operations optidm
+ .prereset = optidma_pre_reset,
+ };
+
+-static struct ata_port_operations optiplus_port_ops = {
++static const struct ata_port_operations optiplus_port_ops = {
+ .inherits = &optidma_port_ops,
+ .set_piomode = optiplus_set_pio_mode,
+ .set_dmamode = optiplus_set_dma_mode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_palmld.c linux-2.6.38.7/drivers/ata/pata_palmld.c
+--- linux-2.6.38.7/drivers/ata/pata_palmld.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_palmld.c 2011-04-28 19:34:15.000000000 -0400
+@@ -37,7 +37,7 @@ static struct scsi_host_template palmld_
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations palmld_port_ops = {
++static const struct ata_port_operations palmld_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .cable_detect = ata_cable_40wire,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_pcmcia.c linux-2.6.38.7/drivers/ata/pata_pcmcia.c
+--- linux-2.6.38.7/drivers/ata/pata_pcmcia.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_pcmcia.c 2011-04-28 19:34:15.000000000 -0400
+@@ -151,14 +151,14 @@ static struct scsi_host_template pcmcia_
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations pcmcia_port_ops = {
++static const struct ata_port_operations pcmcia_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .cable_detect = ata_cable_40wire,
+ .set_mode = pcmcia_set_mode,
+ };
+
+-static struct ata_port_operations pcmcia_8bit_port_ops = {
++static const struct ata_port_operations pcmcia_8bit_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_data_xfer = ata_data_xfer_8bit,
+ .cable_detect = ata_cable_40wire,
+@@ -205,7 +205,7 @@ static int pcmcia_init_one(struct pcmcia
+ unsigned long io_base, ctl_base;
+ void __iomem *io_addr, *ctl_addr;
+ int n_ports = 1;
+- struct ata_port_operations *ops = &pcmcia_port_ops;
++ const struct ata_port_operations *ops = &pcmcia_port_ops;
+
+ /* Set up attributes in order to probe card and get resources */
+ pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+diff -urNp linux-2.6.38.7/drivers/ata/pata_pdc2027x.c linux-2.6.38.7/drivers/ata/pata_pdc2027x.c
+--- linux-2.6.38.7/drivers/ata/pata_pdc2027x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_pdc2027x.c 2011-04-28 19:34:15.000000000 -0400
+@@ -132,14 +132,14 @@ static struct scsi_host_template pdc2027
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations pdc2027x_pata100_ops = {
++static const struct ata_port_operations pdc2027x_pata100_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .check_atapi_dma = pdc2027x_check_atapi_dma,
+ .cable_detect = pdc2027x_cable_detect,
+ .prereset = pdc2027x_prereset,
+ };
+
+-static struct ata_port_operations pdc2027x_pata133_ops = {
++static const struct ata_port_operations pdc2027x_pata133_ops = {
+ .inherits = &pdc2027x_pata100_ops,
+ .mode_filter = pdc2027x_mode_filter,
+ .set_piomode = pdc2027x_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_pdc202xx_old.c linux-2.6.38.7/drivers/ata/pata_pdc202xx_old.c
+--- linux-2.6.38.7/drivers/ata/pata_pdc202xx_old.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_pdc202xx_old.c 2011-04-28 19:34:15.000000000 -0400
+@@ -295,7 +295,7 @@ static struct scsi_host_template pdc202x
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations pdc2024x_port_ops = {
++static const struct ata_port_operations pdc2024x_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .cable_detect = ata_cable_40wire,
+@@ -306,7 +306,7 @@ static struct ata_port_operations pdc202
+ .sff_irq_check = pdc202xx_irq_check,
+ };
+
+-static struct ata_port_operations pdc2026x_port_ops = {
++static const struct ata_port_operations pdc2026x_port_ops = {
+ .inherits = &pdc2024x_port_ops,
+
+ .check_atapi_dma = pdc2026x_check_atapi_dma,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_piccolo.c linux-2.6.38.7/drivers/ata/pata_piccolo.c
+--- linux-2.6.38.7/drivers/ata/pata_piccolo.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_piccolo.c 2011-04-28 19:34:15.000000000 -0400
+@@ -67,7 +67,7 @@ static struct scsi_host_template tosh_sh
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations tosh_port_ops = {
++static const struct ata_port_operations tosh_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_unknown,
+ .set_piomode = tosh_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_platform.c linux-2.6.38.7/drivers/ata/pata_platform.c
+--- linux-2.6.38.7/drivers/ata/pata_platform.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_platform.c 2011-04-28 19:34:15.000000000 -0400
+@@ -48,7 +48,7 @@ static struct scsi_host_template pata_pl
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations pata_platform_port_ops = {
++static const struct ata_port_operations pata_platform_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .cable_detect = ata_cable_unknown,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_pxa.c linux-2.6.38.7/drivers/ata/pata_pxa.c
+--- linux-2.6.38.7/drivers/ata/pata_pxa.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_pxa.c 2011-04-28 19:34:15.000000000 -0400
+@@ -198,7 +198,7 @@ static struct scsi_host_template pxa_ata
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations pxa_ata_port_ops = {
++static const struct ata_port_operations pxa_ata_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_40wire,
+
+diff -urNp linux-2.6.38.7/drivers/ata/pata_qdi.c linux-2.6.38.7/drivers/ata/pata_qdi.c
+--- linux-2.6.38.7/drivers/ata/pata_qdi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_qdi.c 2011-04-28 19:34:15.000000000 -0400
+@@ -157,7 +157,7 @@ static struct scsi_host_template qdi_sht
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations qdi6500_port_ops = {
++static const struct ata_port_operations qdi6500_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .qc_issue = qdi_qc_issue,
+ .sff_data_xfer = qdi_data_xfer,
+@@ -165,7 +165,7 @@ static struct ata_port_operations qdi650
+ .set_piomode = qdi6500_set_piomode,
+ };
+
+-static struct ata_port_operations qdi6580_port_ops = {
++static const struct ata_port_operations qdi6580_port_ops = {
+ .inherits = &qdi6500_port_ops,
+ .set_piomode = qdi6580_set_piomode,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/pata_radisys.c linux-2.6.38.7/drivers/ata/pata_radisys.c
+--- linux-2.6.38.7/drivers/ata/pata_radisys.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_radisys.c 2011-04-28 19:34:15.000000000 -0400
+@@ -187,7 +187,7 @@ static struct scsi_host_template radisys
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations radisys_pata_ops = {
++static const struct ata_port_operations radisys_pata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .qc_issue = radisys_qc_issue,
+ .cable_detect = ata_cable_unknown,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_rb532_cf.c linux-2.6.38.7/drivers/ata/pata_rb532_cf.c
+--- linux-2.6.38.7/drivers/ata/pata_rb532_cf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_rb532_cf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -69,7 +69,7 @@ static irqreturn_t rb532_pata_irq_handle
+ return IRQ_HANDLED;
+ }
+
+-static struct ata_port_operations rb532_pata_port_ops = {
++static const struct ata_port_operations rb532_pata_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_data_xfer = ata_sff_data_xfer32,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/pata_rdc.c linux-2.6.38.7/drivers/ata/pata_rdc.c
+--- linux-2.6.38.7/drivers/ata/pata_rdc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_rdc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -273,7 +273,7 @@ static void rdc_set_dmamode(struct ata_p
+ pci_write_config_byte(dev, 0x48, udma_enable);
+ }
+
+-static struct ata_port_operations rdc_pata_ops = {
++static const struct ata_port_operations rdc_pata_ops = {
+ .inherits = &ata_bmdma32_port_ops,
+ .cable_detect = rdc_pata_cable_detect,
+ .set_piomode = rdc_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_rz1000.c linux-2.6.38.7/drivers/ata/pata_rz1000.c
+--- linux-2.6.38.7/drivers/ata/pata_rz1000.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_rz1000.c 2011-04-28 19:34:15.000000000 -0400
+@@ -54,7 +54,7 @@ static struct scsi_host_template rz1000_
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations rz1000_port_ops = {
++static const struct ata_port_operations rz1000_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+ .set_mode = rz1000_set_mode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_samsung_cf.c linux-2.6.38.7/drivers/ata/pata_samsung_cf.c
+--- linux-2.6.38.7/drivers/ata/pata_samsung_cf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_samsung_cf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -399,7 +399,7 @@ static struct scsi_host_template pata_s3
+ ATA_PIO_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations pata_s3c_port_ops = {
++static const struct ata_port_operations pata_s3c_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_check_status = pata_s3c_check_status,
+ .sff_check_altstatus = pata_s3c_check_altstatus,
+@@ -413,7 +413,7 @@ static struct ata_port_operations pata_s
+ .set_piomode = pata_s3c_set_piomode,
+ };
+
+-static struct ata_port_operations pata_s5p_port_ops = {
++static const struct ata_port_operations pata_s5p_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .set_piomode = pata_s3c_set_piomode,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/pata_sc1200.c linux-2.6.38.7/drivers/ata/pata_sc1200.c
+--- linux-2.6.38.7/drivers/ata/pata_sc1200.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_sc1200.c 2011-04-28 19:34:15.000000000 -0400
+@@ -207,7 +207,7 @@ static struct scsi_host_template sc1200_
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+ };
+
+-static struct ata_port_operations sc1200_port_ops = {
++static const struct ata_port_operations sc1200_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .qc_prep = ata_bmdma_dumb_qc_prep,
+ .qc_issue = sc1200_qc_issue,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_scc.c linux-2.6.38.7/drivers/ata/pata_scc.c
+--- linux-2.6.38.7/drivers/ata/pata_scc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_scc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -926,7 +926,7 @@ static struct scsi_host_template scc_sht
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations scc_pata_ops = {
++static const struct ata_port_operations scc_pata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .set_piomode = scc_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_sch.c linux-2.6.38.7/drivers/ata/pata_sch.c
+--- linux-2.6.38.7/drivers/ata/pata_sch.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_sch.c 2011-04-28 19:34:15.000000000 -0400
+@@ -75,7 +75,7 @@ static struct scsi_host_template sch_sht
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations sch_pata_ops = {
++static const struct ata_port_operations sch_pata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_unknown,
+ .set_piomode = sch_set_piomode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_serverworks.c linux-2.6.38.7/drivers/ata/pata_serverworks.c
+--- linux-2.6.38.7/drivers/ata/pata_serverworks.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_serverworks.c 2011-04-28 19:34:15.000000000 -0400
+@@ -300,7 +300,7 @@ static struct scsi_host_template serverw
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations serverworks_osb4_port_ops = {
++static const struct ata_port_operations serverworks_osb4_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = serverworks_cable_detect,
+ .mode_filter = serverworks_osb4_filter,
+@@ -308,7 +308,7 @@ static struct ata_port_operations server
+ .set_dmamode = serverworks_set_dmamode,
+ };
+
+-static struct ata_port_operations serverworks_csb_port_ops = {
++static const struct ata_port_operations serverworks_csb_port_ops = {
+ .inherits = &serverworks_osb4_port_ops,
+ .mode_filter = serverworks_csb_filter,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/pata_sil680.c linux-2.6.38.7/drivers/ata/pata_sil680.c
+--- linux-2.6.38.7/drivers/ata/pata_sil680.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_sil680.c 2011-04-28 19:34:15.000000000 -0400
+@@ -225,8 +225,7 @@ static struct scsi_host_template sil680_
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-
+-static struct ata_port_operations sil680_port_ops = {
++static const struct ata_port_operations sil680_port_ops = {
+ .inherits = &ata_bmdma32_port_ops,
+ .sff_exec_command = sil680_sff_exec_command,
+ .sff_irq_check = sil680_sff_irq_check,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_sis.c linux-2.6.38.7/drivers/ata/pata_sis.c
+--- linux-2.6.38.7/drivers/ata/pata_sis.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_sis.c 2011-04-28 19:34:15.000000000 -0400
+@@ -503,47 +503,47 @@ static struct scsi_host_template sis_sht
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations sis_133_for_sata_ops = {
++static const struct ata_port_operations sis_133_for_sata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .set_piomode = sis_133_set_piomode,
+ .set_dmamode = sis_133_set_dmamode,
+ .cable_detect = sis_133_cable_detect,
+ };
+
+-static struct ata_port_operations sis_base_ops = {
++static const struct ata_port_operations sis_base_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .prereset = sis_pre_reset,
+ };
+
+-static struct ata_port_operations sis_133_ops = {
++static const struct ata_port_operations sis_133_ops = {
+ .inherits = &sis_base_ops,
+ .set_piomode = sis_133_set_piomode,
+ .set_dmamode = sis_133_set_dmamode,
+ .cable_detect = sis_133_cable_detect,
+ };
+
+-static struct ata_port_operations sis_133_early_ops = {
++static const struct ata_port_operations sis_133_early_ops = {
+ .inherits = &sis_base_ops,
+ .set_piomode = sis_100_set_piomode,
+ .set_dmamode = sis_133_early_set_dmamode,
+ .cable_detect = sis_66_cable_detect,
+ };
+
+-static struct ata_port_operations sis_100_ops = {
++static const struct ata_port_operations sis_100_ops = {
+ .inherits = &sis_base_ops,
+ .set_piomode = sis_100_set_piomode,
+ .set_dmamode = sis_100_set_dmamode,
+ .cable_detect = sis_66_cable_detect,
+ };
+
+-static struct ata_port_operations sis_66_ops = {
++static const struct ata_port_operations sis_66_ops = {
+ .inherits = &sis_base_ops,
+ .set_piomode = sis_old_set_piomode,
+ .set_dmamode = sis_66_set_dmamode,
+ .cable_detect = sis_66_cable_detect,
+ };
+
+-static struct ata_port_operations sis_old_ops = {
++static const struct ata_port_operations sis_old_ops = {
+ .inherits = &sis_base_ops,
+ .set_piomode = sis_old_set_piomode,
+ .set_dmamode = sis_old_set_dmamode,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_sl82c105.c linux-2.6.38.7/drivers/ata/pata_sl82c105.c
+--- linux-2.6.38.7/drivers/ata/pata_sl82c105.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_sl82c105.c 2011-04-28 19:34:15.000000000 -0400
+@@ -241,7 +241,7 @@ static struct scsi_host_template sl82c10
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations sl82c105_port_ops = {
++static const struct ata_port_operations sl82c105_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .qc_defer = sl82c105_qc_defer,
+ .bmdma_start = sl82c105_bmdma_start,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_triflex.c linux-2.6.38.7/drivers/ata/pata_triflex.c
+--- linux-2.6.38.7/drivers/ata/pata_triflex.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_triflex.c 2011-04-28 19:34:15.000000000 -0400
+@@ -178,7 +178,7 @@ static struct scsi_host_template triflex
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations triflex_port_ops = {
++static const struct ata_port_operations triflex_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .bmdma_start = triflex_bmdma_start,
+ .bmdma_stop = triflex_bmdma_stop,
+diff -urNp linux-2.6.38.7/drivers/ata/pata_via.c linux-2.6.38.7/drivers/ata/pata_via.c
+--- linux-2.6.38.7/drivers/ata/pata_via.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pata_via.c 2011-04-28 19:34:15.000000000 -0400
+@@ -441,7 +441,7 @@ static struct scsi_host_template via_sht
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations via_port_ops = {
++static const struct ata_port_operations via_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = via_cable_detect,
+ .set_piomode = via_set_piomode,
+@@ -452,7 +452,7 @@ static struct ata_port_operations via_po
+ .mode_filter = via_mode_filter,
+ };
+
+-static struct ata_port_operations via_port_ops_noirq = {
++static const struct ata_port_operations via_port_ops_noirq = {
+ .inherits = &via_port_ops,
+ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ };
+diff -urNp linux-2.6.38.7/drivers/ata/pdc_adma.c linux-2.6.38.7/drivers/ata/pdc_adma.c
+--- linux-2.6.38.7/drivers/ata/pdc_adma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/pdc_adma.c 2011-04-28 19:34:15.000000000 -0400
+@@ -146,7 +146,7 @@ static struct scsi_host_template adma_at
+ .dma_boundary = ADMA_DMA_BOUNDARY,
+ };
+
+-static struct ata_port_operations adma_ata_ops = {
++static const struct ata_port_operations adma_ata_ops = {
+ .inherits = &ata_sff_port_ops,
+
+ .lost_interrupt = ATA_OP_NULL,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_dwc_460ex.c linux-2.6.38.7/drivers/ata/sata_dwc_460ex.c
+--- linux-2.6.38.7/drivers/ata/sata_dwc_460ex.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_dwc_460ex.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1560,7 +1560,7 @@ static struct scsi_host_template sata_dw
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ };
+
+-static struct ata_port_operations sata_dwc_ops = {
++static const struct ata_port_operations sata_dwc_ops = {
+ .inherits = &ata_sff_port_ops,
+
+ .error_handler = sata_dwc_error_handler,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_fsl.c linux-2.6.38.7/drivers/ata/sata_fsl.c
+--- linux-2.6.38.7/drivers/ata/sata_fsl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_fsl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1258,7 +1258,7 @@ static struct scsi_host_template sata_fs
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ };
+
+-static struct ata_port_operations sata_fsl_ops = {
++static const struct ata_port_operations sata_fsl_ops = {
+ .inherits = &sata_pmp_port_ops,
+
+ .qc_defer = ata_std_qc_defer,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_inic162x.c linux-2.6.38.7/drivers/ata/sata_inic162x.c
+--- linux-2.6.38.7/drivers/ata/sata_inic162x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_inic162x.c 2011-04-28 19:34:15.000000000 -0400
+@@ -705,7 +705,7 @@ static int inic_port_start(struct ata_po
+ return 0;
+ }
+
+-static struct ata_port_operations inic_port_ops = {
++static const struct ata_port_operations inic_port_ops = {
+ .inherits = &sata_port_ops,
+
+ .check_atapi_dma = inic_check_atapi_dma,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_mv.c linux-2.6.38.7/drivers/ata/sata_mv.c
+--- linux-2.6.38.7/drivers/ata/sata_mv.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_mv.c 2011-04-28 19:34:15.000000000 -0400
+@@ -663,7 +663,7 @@ static struct scsi_host_template mv6_sht
+ .dma_boundary = MV_DMA_BOUNDARY,
+ };
+
+-static struct ata_port_operations mv5_ops = {
++static const struct ata_port_operations mv5_ops = {
+ .inherits = &ata_sff_port_ops,
+
+ .lost_interrupt = ATA_OP_NULL,
+@@ -683,7 +683,7 @@ static struct ata_port_operations mv5_op
+ .port_stop = mv_port_stop,
+ };
+
+-static struct ata_port_operations mv6_ops = {
++static const struct ata_port_operations mv6_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .lost_interrupt = ATA_OP_NULL,
+@@ -717,7 +717,7 @@ static struct ata_port_operations mv6_op
+ .port_stop = mv_port_stop,
+ };
+
+-static struct ata_port_operations mv_iie_ops = {
++static const struct ata_port_operations mv_iie_ops = {
+ .inherits = &mv6_ops,
+ .dev_config = ATA_OP_NULL,
+ .qc_prep = mv_qc_prep_iie,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_nv.c linux-2.6.38.7/drivers/ata/sata_nv.c
+--- linux-2.6.38.7/drivers/ata/sata_nv.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_nv.c 2011-04-28 19:34:15.000000000 -0400
+@@ -465,7 +465,7 @@ static struct scsi_host_template nv_swnc
+ * cases. Define nv_hardreset() which only kicks in for post-boot
+ * probing and use it for all variants.
+ */
+-static struct ata_port_operations nv_generic_ops = {
++static const struct ata_port_operations nv_generic_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .lost_interrupt = ATA_OP_NULL,
+ .scr_read = nv_scr_read,
+@@ -473,20 +473,20 @@ static struct ata_port_operations nv_gen
+ .hardreset = nv_hardreset,
+ };
+
+-static struct ata_port_operations nv_nf2_ops = {
++static const struct ata_port_operations nv_nf2_ops = {
+ .inherits = &nv_generic_ops,
+ .freeze = nv_nf2_freeze,
+ .thaw = nv_nf2_thaw,
+ };
+
+-static struct ata_port_operations nv_ck804_ops = {
++static const struct ata_port_operations nv_ck804_ops = {
+ .inherits = &nv_generic_ops,
+ .freeze = nv_ck804_freeze,
+ .thaw = nv_ck804_thaw,
+ .host_stop = nv_ck804_host_stop,
+ };
+
+-static struct ata_port_operations nv_adma_ops = {
++static const struct ata_port_operations nv_adma_ops = {
+ .inherits = &nv_ck804_ops,
+
+ .check_atapi_dma = nv_adma_check_atapi_dma,
+@@ -510,7 +510,7 @@ static struct ata_port_operations nv_adm
+ .host_stop = nv_adma_host_stop,
+ };
+
+-static struct ata_port_operations nv_swncq_ops = {
++static const struct ata_port_operations nv_swncq_ops = {
+ .inherits = &nv_generic_ops,
+
+ .qc_defer = ata_std_qc_defer,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_promise.c linux-2.6.38.7/drivers/ata/sata_promise.c
+--- linux-2.6.38.7/drivers/ata/sata_promise.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_promise.c 2011-04-28 19:34:15.000000000 -0400
+@@ -196,7 +196,7 @@ static const struct ata_port_operations
+ .error_handler = pdc_error_handler,
+ };
+
+-static struct ata_port_operations pdc_sata_ops = {
++static const struct ata_port_operations pdc_sata_ops = {
+ .inherits = &pdc_common_ops,
+ .cable_detect = pdc_sata_cable_detect,
+ .freeze = pdc_sata_freeze,
+@@ -209,14 +209,14 @@ static struct ata_port_operations pdc_sa
+
+ /* First-generation chips need a more restrictive ->check_atapi_dma op,
+ and ->freeze/thaw that ignore the hotplug controls. */
+-static struct ata_port_operations pdc_old_sata_ops = {
++static const struct ata_port_operations pdc_old_sata_ops = {
+ .inherits = &pdc_sata_ops,
+ .freeze = pdc_freeze,
+ .thaw = pdc_thaw,
+ .check_atapi_dma = pdc_old_sata_check_atapi_dma,
+ };
+
+-static struct ata_port_operations pdc_pata_ops = {
++static const struct ata_port_operations pdc_pata_ops = {
+ .inherits = &pdc_common_ops,
+ .cable_detect = pdc_pata_cable_detect,
+ .freeze = pdc_freeze,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_qstor.c linux-2.6.38.7/drivers/ata/sata_qstor.c
+--- linux-2.6.38.7/drivers/ata/sata_qstor.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_qstor.c 2011-04-28 19:34:15.000000000 -0400
+@@ -131,7 +131,7 @@ static struct scsi_host_template qs_ata_
+ .dma_boundary = QS_DMA_BOUNDARY,
+ };
+
+-static struct ata_port_operations qs_ata_ops = {
++static const struct ata_port_operations qs_ata_ops = {
+ .inherits = &ata_sff_port_ops,
+
+ .check_atapi_dma = qs_check_atapi_dma,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_sil24.c linux-2.6.38.7/drivers/ata/sata_sil24.c
+--- linux-2.6.38.7/drivers/ata/sata_sil24.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_sil24.c 2011-04-28 19:34:15.000000000 -0400
+@@ -389,7 +389,7 @@ static struct scsi_host_template sil24_s
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ };
+
+-static struct ata_port_operations sil24_ops = {
++static const struct ata_port_operations sil24_ops = {
+ .inherits = &sata_pmp_port_ops,
+
+ .qc_defer = sil24_qc_defer,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_sil.c linux-2.6.38.7/drivers/ata/sata_sil.c
+--- linux-2.6.38.7/drivers/ata/sata_sil.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_sil.c 2011-04-28 19:34:15.000000000 -0400
+@@ -182,7 +182,7 @@ static struct scsi_host_template sil_sht
+ .sg_tablesize = ATA_MAX_PRD
+ };
+
+-static struct ata_port_operations sil_ops = {
++static const struct ata_port_operations sil_ops = {
+ .inherits = &ata_bmdma32_port_ops,
+ .dev_config = sil_dev_config,
+ .set_mode = sil_set_mode,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_sis.c linux-2.6.38.7/drivers/ata/sata_sis.c
+--- linux-2.6.38.7/drivers/ata/sata_sis.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_sis.c 2011-04-28 19:34:15.000000000 -0400
+@@ -89,7 +89,7 @@ static struct scsi_host_template sis_sht
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations sis_ops = {
++static const struct ata_port_operations sis_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .scr_read = sis_scr_read,
+ .scr_write = sis_scr_write,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_svw.c linux-2.6.38.7/drivers/ata/sata_svw.c
+--- linux-2.6.38.7/drivers/ata/sata_svw.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_svw.c 2011-04-28 19:34:15.000000000 -0400
+@@ -344,7 +344,7 @@ static struct scsi_host_template k2_sata
+ };
+
+
+-static struct ata_port_operations k2_sata_ops = {
++static const struct ata_port_operations k2_sata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .sff_tf_load = k2_sata_tf_load,
+ .sff_tf_read = k2_sata_tf_read,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_sx4.c linux-2.6.38.7/drivers/ata/sata_sx4.c
+--- linux-2.6.38.7/drivers/ata/sata_sx4.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_sx4.c 2011-04-28 19:34:15.000000000 -0400
+@@ -249,7 +249,7 @@ static struct scsi_host_template pdc_sat
+ };
+
+ /* TODO: inherit from base port_ops after converting to new EH */
+-static struct ata_port_operations pdc_20621_ops = {
++static const struct ata_port_operations pdc_20621_ops = {
+ .inherits = &ata_sff_port_ops,
+
+ .check_atapi_dma = pdc_check_atapi_dma,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_uli.c linux-2.6.38.7/drivers/ata/sata_uli.c
+--- linux-2.6.38.7/drivers/ata/sata_uli.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_uli.c 2011-04-28 19:34:15.000000000 -0400
+@@ -80,7 +80,7 @@ static struct scsi_host_template uli_sht
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations uli_ops = {
++static const struct ata_port_operations uli_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .scr_read = uli_scr_read,
+ .scr_write = uli_scr_write,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_via.c linux-2.6.38.7/drivers/ata/sata_via.c
+--- linux-2.6.38.7/drivers/ata/sata_via.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_via.c 2011-04-28 19:34:15.000000000 -0400
+@@ -115,32 +115,32 @@ static struct scsi_host_template svia_sh
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations svia_base_ops = {
++static const struct ata_port_operations svia_base_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .sff_tf_load = svia_tf_load,
+ };
+
+-static struct ata_port_operations vt6420_sata_ops = {
++static const struct ata_port_operations vt6420_sata_ops = {
+ .inherits = &svia_base_ops,
+ .freeze = svia_noop_freeze,
+ .prereset = vt6420_prereset,
+ .bmdma_start = vt6420_bmdma_start,
+ };
+
+-static struct ata_port_operations vt6421_pata_ops = {
++static const struct ata_port_operations vt6421_pata_ops = {
+ .inherits = &svia_base_ops,
+ .cable_detect = vt6421_pata_cable_detect,
+ .set_piomode = vt6421_set_pio_mode,
+ .set_dmamode = vt6421_set_dma_mode,
+ };
+
+-static struct ata_port_operations vt6421_sata_ops = {
++static const struct ata_port_operations vt6421_sata_ops = {
+ .inherits = &svia_base_ops,
+ .scr_read = svia_scr_read,
+ .scr_write = svia_scr_write,
+ };
+
+-static struct ata_port_operations vt8251_ops = {
++static const struct ata_port_operations vt8251_ops = {
+ .inherits = &svia_base_ops,
+ .hardreset = sata_std_hardreset,
+ .scr_read = vt8251_scr_read,
+diff -urNp linux-2.6.38.7/drivers/ata/sata_vsc.c linux-2.6.38.7/drivers/ata/sata_vsc.c
+--- linux-2.6.38.7/drivers/ata/sata_vsc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ata/sata_vsc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -300,7 +300,7 @@ static struct scsi_host_template vsc_sat
+ };
+
+
+-static struct ata_port_operations vsc_sata_ops = {
++static const struct ata_port_operations vsc_sata_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ /* The IRQ handling is not quite standard SFF behaviour so we
+ cannot use the default lost interrupt handler */
+diff -urNp linux-2.6.38.7/drivers/atm/adummy.c linux-2.6.38.7/drivers/atm/adummy.c
+--- linux-2.6.38.7/drivers/atm/adummy.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/adummy.c 2011-04-28 19:34:15.000000000 -0400
+@@ -114,7 +114,7 @@ adummy_send(struct atm_vcc *vcc, struct
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/drivers/atm/ambassador.c linux-2.6.38.7/drivers/atm/ambassador.c
+--- linux-2.6.38.7/drivers/atm/ambassador.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/ambassador.c 2011-04-28 19:34:15.000000000 -0400
+@@ -454,7 +454,7 @@ static void tx_complete (amb_dev * dev,
+ PRINTD (DBG_FLOW|DBG_TX, "tx_complete %p %p", dev, tx);
+
+ // VC layer stats
+- atomic_inc(&ATM_SKB(skb)->vcc->stats->tx);
++ atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx);
+
+ // free the descriptor
+ kfree (tx_descr);
+@@ -495,7 +495,7 @@ static void rx_complete (amb_dev * dev,
+ dump_skb ("<<<", vc, skb);
+
+ // VC layer stats
+- atomic_inc(&atm_vcc->stats->rx);
++ atomic_inc_unchecked(&atm_vcc->stats->rx);
+ __net_timestamp(skb);
+ // end of our responsability
+ atm_vcc->push (atm_vcc, skb);
+@@ -510,7 +510,7 @@ static void rx_complete (amb_dev * dev,
+ } else {
+ PRINTK (KERN_INFO, "dropped over-size frame");
+ // should we count this?
+- atomic_inc(&atm_vcc->stats->rx_drop);
++ atomic_inc_unchecked(&atm_vcc->stats->rx_drop);
+ }
+
+ } else {
+@@ -1342,7 +1342,7 @@ static int amb_send (struct atm_vcc * at
+ }
+
+ if (check_area (skb->data, skb->len)) {
+- atomic_inc(&atm_vcc->stats->tx_err);
++ atomic_inc_unchecked(&atm_vcc->stats->tx_err);
+ return -ENOMEM; // ?
+ }
+
+diff -urNp linux-2.6.38.7/drivers/atm/atmtcp.c linux-2.6.38.7/drivers/atm/atmtcp.c
+--- linux-2.6.38.7/drivers/atm/atmtcp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/atmtcp.c 2011-04-28 19:34:15.000000000 -0400
+@@ -207,7 +207,7 @@ static int atmtcp_v_send(struct atm_vcc
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb(skb);
+ if (dev_data) return 0;
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ return -ENOLINK;
+ }
+ size = skb->len+sizeof(struct atmtcp_hdr);
+@@ -215,7 +215,7 @@ static int atmtcp_v_send(struct atm_vcc
+ if (!new_skb) {
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb(skb);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ return -ENOBUFS;
+ }
+ hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr));
+@@ -226,8 +226,8 @@ static int atmtcp_v_send(struct atm_vcc
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb(skb);
+ out_vcc->push(out_vcc,new_skb);
+- atomic_inc(&vcc->stats->tx);
+- atomic_inc(&out_vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->tx);
++ atomic_inc_unchecked(&out_vcc->stats->rx);
+ return 0;
+ }
+
+@@ -301,7 +301,7 @@ static int atmtcp_c_send(struct atm_vcc
+ out_vcc = find_vcc(dev, ntohs(hdr->vpi), ntohs(hdr->vci));
+ read_unlock(&vcc_sklist_lock);
+ if (!out_vcc) {
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ goto done;
+ }
+ skb_pull(skb,sizeof(struct atmtcp_hdr));
+@@ -313,8 +313,8 @@ static int atmtcp_c_send(struct atm_vcc
+ __net_timestamp(new_skb);
+ skb_copy_from_linear_data(skb, skb_put(new_skb, skb->len), skb->len);
+ out_vcc->push(out_vcc,new_skb);
+- atomic_inc(&vcc->stats->tx);
+- atomic_inc(&out_vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->tx);
++ atomic_inc_unchecked(&out_vcc->stats->rx);
+ done:
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb(skb);
+diff -urNp linux-2.6.38.7/drivers/atm/eni.c linux-2.6.38.7/drivers/atm/eni.c
+--- linux-2.6.38.7/drivers/atm/eni.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/eni.c 2011-04-28 19:34:15.000000000 -0400
+@@ -526,7 +526,7 @@ static int rx_aal0(struct atm_vcc *vcc)
+ DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n",
+ vcc->dev->number);
+ length = 0;
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ }
+ else {
+ length = ATM_CELL_SIZE-1; /* no HEC */
+@@ -581,7 +581,7 @@ static int rx_aal5(struct atm_vcc *vcc)
+ size);
+ }
+ eff = length = 0;
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ }
+ else {
+ size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2);
+@@ -598,7 +598,7 @@ static int rx_aal5(struct atm_vcc *vcc)
+ "(VCI=%d,length=%ld,size=%ld (descr 0x%lx))\n",
+ vcc->dev->number,vcc->vci,length,size << 2,descr);
+ length = eff = 0;
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ }
+ }
+ skb = eff ? atm_alloc_charge(vcc,eff << 2,GFP_ATOMIC) : NULL;
+@@ -771,7 +771,7 @@ rx_dequeued++;
+ vcc->push(vcc,skb);
+ pushed++;
+ }
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+ wake_up(&eni_dev->rx_wait);
+ }
+@@ -1228,7 +1228,7 @@ static void dequeue_tx(struct atm_dev *d
+ PCI_DMA_TODEVICE);
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb_irq(skb);
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ wake_up(&eni_dev->tx_wait);
+ dma_complete++;
+ }
+diff -urNp linux-2.6.38.7/drivers/atm/firestream.c linux-2.6.38.7/drivers/atm/firestream.c
+--- linux-2.6.38.7/drivers/atm/firestream.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/firestream.c 2011-04-28 19:34:15.000000000 -0400
+@@ -749,7 +749,7 @@ static void process_txdone_queue (struct
+ }
+ }
+
+- atomic_inc(&ATM_SKB(skb)->vcc->stats->tx);
++ atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx);
+
+ fs_dprintk (FS_DEBUG_TXMEM, "i");
+ fs_dprintk (FS_DEBUG_ALLOC, "Free t-skb: %p\n", skb);
+@@ -816,7 +816,7 @@ static void process_incoming (struct fs_
+ #endif
+ skb_put (skb, qe->p1 & 0xffff);
+ ATM_SKB(skb)->vcc = atm_vcc;
+- atomic_inc(&atm_vcc->stats->rx);
++ atomic_inc_unchecked(&atm_vcc->stats->rx);
+ __net_timestamp(skb);
+ fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p (pushed)\n", skb);
+ atm_vcc->push (atm_vcc, skb);
+@@ -837,12 +837,12 @@ static void process_incoming (struct fs_
+ kfree (pe);
+ }
+ if (atm_vcc)
+- atomic_inc(&atm_vcc->stats->rx_drop);
++ atomic_inc_unchecked(&atm_vcc->stats->rx_drop);
+ break;
+ case 0x1f: /* Reassembly abort: no buffers. */
+ /* Silently increment error counter. */
+ if (atm_vcc)
+- atomic_inc(&atm_vcc->stats->rx_drop);
++ atomic_inc_unchecked(&atm_vcc->stats->rx_drop);
+ break;
+ default: /* Hmm. Haven't written the code to handle the others yet... -- REW */
+ printk (KERN_WARNING "Don't know what to do with RX status %x: %s.\n",
+diff -urNp linux-2.6.38.7/drivers/atm/fore200e.c linux-2.6.38.7/drivers/atm/fore200e.c
+--- linux-2.6.38.7/drivers/atm/fore200e.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/fore200e.c 2011-04-28 19:34:15.000000000 -0400
+@@ -933,9 +933,9 @@ fore200e_tx_irq(struct fore200e* fore200
+ #endif
+ /* check error condition */
+ if (*entry->status & STATUS_ERROR)
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ else
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ }
+ }
+
+@@ -1084,7 +1084,7 @@ fore200e_push_rpd(struct fore200e* fore2
+ if (skb == NULL) {
+ DPRINTK(2, "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
+
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ return -ENOMEM;
+ }
+
+@@ -1127,14 +1127,14 @@ fore200e_push_rpd(struct fore200e* fore2
+
+ dev_kfree_skb_any(skb);
+
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ return -ENOMEM;
+ }
+
+ ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
+
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
+
+@@ -1212,7 +1212,7 @@ fore200e_rx_irq(struct fore200e* fore200
+ DPRINTK(2, "damaged PDU on %d.%d.%d\n",
+ fore200e->atm_dev->number,
+ entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ }
+ }
+
+@@ -1657,7 +1657,7 @@ fore200e_send(struct atm_vcc *vcc, struc
+ goto retry_here;
+ }
+
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+
+ fore200e->tx_sat++;
+ DPRINTK(2, "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n",
+diff -urNp linux-2.6.38.7/drivers/atm/he.c linux-2.6.38.7/drivers/atm/he.c
+--- linux-2.6.38.7/drivers/atm/he.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/he.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1709,7 +1709,7 @@ he_service_rbrq(struct he_dev *he_dev, i
+
+ if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) {
+ hprintk("HBUF_ERR! (cid 0x%x)\n", cid);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ goto return_host_buffers;
+ }
+
+@@ -1736,7 +1736,7 @@ he_service_rbrq(struct he_dev *he_dev, i
+ RBRQ_LEN_ERR(he_dev->rbrq_head)
+ ? "LEN_ERR" : "",
+ vcc->vpi, vcc->vci);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto return_host_buffers;
+ }
+
+@@ -1788,7 +1788,7 @@ he_service_rbrq(struct he_dev *he_dev, i
+ vcc->push(vcc, skb);
+ spin_lock(&he_dev->global_lock);
+
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ return_host_buffers:
+ ++pdus_assembled;
+@@ -2114,7 +2114,7 @@ __enqueue_tpd(struct he_dev *he_dev, str
+ tpd->vcc->pop(tpd->vcc, tpd->skb);
+ else
+ dev_kfree_skb_any(tpd->skb);
+- atomic_inc(&tpd->vcc->stats->tx_err);
++ atomic_inc_unchecked(&tpd->vcc->stats->tx_err);
+ }
+ pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
+ return;
+@@ -2526,7 +2526,7 @@ he_send(struct atm_vcc *vcc, struct sk_b
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ return -EINVAL;
+ }
+
+@@ -2537,7 +2537,7 @@ he_send(struct atm_vcc *vcc, struct sk_b
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ return -EINVAL;
+ }
+ #endif
+@@ -2549,7 +2549,7 @@ he_send(struct atm_vcc *vcc, struct sk_b
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ spin_unlock_irqrestore(&he_dev->global_lock, flags);
+ return -ENOMEM;
+ }
+@@ -2591,7 +2591,7 @@ he_send(struct atm_vcc *vcc, struct sk_b
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ spin_unlock_irqrestore(&he_dev->global_lock, flags);
+ return -ENOMEM;
+ }
+@@ -2622,7 +2622,7 @@ he_send(struct atm_vcc *vcc, struct sk_b
+ __enqueue_tpd(he_dev, tpd, cid);
+ spin_unlock_irqrestore(&he_dev->global_lock, flags);
+
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/drivers/atm/horizon.c linux-2.6.38.7/drivers/atm/horizon.c
+--- linux-2.6.38.7/drivers/atm/horizon.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/horizon.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1034,7 +1034,7 @@ static void rx_schedule (hrz_dev * dev,
+ {
+ struct atm_vcc * vcc = ATM_SKB(skb)->vcc;
+ // VC layer stats
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ __net_timestamp(skb);
+ // end of our responsability
+ vcc->push (vcc, skb);
+@@ -1186,7 +1186,7 @@ static void tx_schedule (hrz_dev * const
+ dev->tx_iovec = NULL;
+
+ // VC layer stats
+- atomic_inc(&ATM_SKB(skb)->vcc->stats->tx);
++ atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx);
+
+ // free the skb
+ hrz_kfree_skb (skb);
+diff -urNp linux-2.6.38.7/drivers/atm/idt77252.c linux-2.6.38.7/drivers/atm/idt77252.c
+--- linux-2.6.38.7/drivers/atm/idt77252.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/idt77252.c 2011-04-28 19:34:15.000000000 -0400
+@@ -811,7 +811,7 @@ drain_scq(struct idt77252_dev *card, str
+ else
+ dev_kfree_skb(skb);
+
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ }
+
+ atomic_dec(&scq->used);
+@@ -1074,13 +1074,13 @@ dequeue_rx(struct idt77252_dev *card, st
+ if ((sb = dev_alloc_skb(64)) == NULL) {
+ printk("%s: Can't allocate buffers for aal0.\n",
+ card->name);
+- atomic_add(i, &vcc->stats->rx_drop);
++ atomic_add_unchecked(i, &vcc->stats->rx_drop);
+ break;
+ }
+ if (!atm_charge(vcc, sb->truesize)) {
+ RXPRINTK("%s: atm_charge() dropped aal0 packets.\n",
+ card->name);
+- atomic_add(i - 1, &vcc->stats->rx_drop);
++ atomic_add_unchecked(i - 1, &vcc->stats->rx_drop);
+ dev_kfree_skb(sb);
+ break;
+ }
+@@ -1097,7 +1097,7 @@ dequeue_rx(struct idt77252_dev *card, st
+ ATM_SKB(sb)->vcc = vcc;
+ __net_timestamp(sb);
+ vcc->push(vcc, sb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ cell += ATM_CELL_PAYLOAD;
+ }
+@@ -1134,13 +1134,13 @@ dequeue_rx(struct idt77252_dev *card, st
+ "(CDC: %08x)\n",
+ card->name, len, rpp->len, readl(SAR_REG_CDC));
+ recycle_rx_pool_skb(card, rpp);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ return;
+ }
+ if (stat & SAR_RSQE_CRC) {
+ RXPRINTK("%s: AAL5 CRC error.\n", card->name);
+ recycle_rx_pool_skb(card, rpp);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ return;
+ }
+ if (skb_queue_len(&rpp->queue) > 1) {
+@@ -1151,7 +1151,7 @@ dequeue_rx(struct idt77252_dev *card, st
+ RXPRINTK("%s: Can't alloc RX skb.\n",
+ card->name);
+ recycle_rx_pool_skb(card, rpp);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ return;
+ }
+ if (!atm_charge(vcc, skb->truesize)) {
+@@ -1170,7 +1170,7 @@ dequeue_rx(struct idt77252_dev *card, st
+ __net_timestamp(skb);
+
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ return;
+ }
+@@ -1192,7 +1192,7 @@ dequeue_rx(struct idt77252_dev *card, st
+ __net_timestamp(skb);
+
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ if (skb->truesize > SAR_FB_SIZE_3)
+ add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
+@@ -1304,14 +1304,14 @@ idt77252_rx_raw(struct idt77252_dev *car
+ if (vcc->qos.aal != ATM_AAL0) {
+ RPRINTK("%s: raw cell for non AAL0 vc %u.%u\n",
+ card->name, vpi, vci);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ goto drop;
+ }
+
+ if ((sb = dev_alloc_skb(64)) == NULL) {
+ printk("%s: Can't allocate buffers for AAL0.\n",
+ card->name);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto drop;
+ }
+
+@@ -1330,7 +1330,7 @@ idt77252_rx_raw(struct idt77252_dev *car
+ ATM_SKB(sb)->vcc = vcc;
+ __net_timestamp(sb);
+ vcc->push(vcc, sb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ drop:
+ skb_pull(queue, 64);
+@@ -1955,13 +1955,13 @@ idt77252_send_skb(struct atm_vcc *vcc, s
+
+ if (vc == NULL) {
+ printk("%s: NULL connection in send().\n", card->name);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+ if (!test_bit(VCF_TX, &vc->flags)) {
+ printk("%s: Trying to transmit on a non-tx VC.\n", card->name);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+@@ -1973,14 +1973,14 @@ idt77252_send_skb(struct atm_vcc *vcc, s
+ break;
+ default:
+ printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ if (skb_shinfo(skb)->nr_frags != 0) {
+ printk("%s: No scatter-gather yet.\n", card->name);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+@@ -1988,7 +1988,7 @@ idt77252_send_skb(struct atm_vcc *vcc, s
+
+ err = queue_skb(card, vc, skb, oam);
+ if (err) {
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return err;
+ }
+@@ -2011,7 +2011,7 @@ idt77252_send_oam(struct atm_vcc *vcc, v
+ skb = dev_alloc_skb(64);
+ if (!skb) {
+ printk("%s: Out of memory in send_oam().\n", card->name);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ return -ENOMEM;
+ }
+ atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+diff -urNp linux-2.6.38.7/drivers/atm/iphase.c linux-2.6.38.7/drivers/atm/iphase.c
+--- linux-2.6.38.7/drivers/atm/iphase.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/iphase.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1124,7 +1124,7 @@ static int rx_pkt(struct atm_dev *dev)
+ status = (u_short) (buf_desc_ptr->desc_mode);
+ if (status & (RX_CER | RX_PTE | RX_OFL))
+ {
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ IF_ERR(printk("IA: bad packet, dropping it");)
+ if (status & RX_CER) {
+ IF_ERR(printk(" cause: packet CRC error\n");)
+@@ -1147,7 +1147,7 @@ static int rx_pkt(struct atm_dev *dev)
+ len = dma_addr - buf_addr;
+ if (len > iadev->rx_buf_sz) {
+ printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto out_free_desc;
+ }
+
+@@ -1297,7 +1297,7 @@ static void rx_dle_intr(struct atm_dev *
+ ia_vcc = INPH_IA_VCC(vcc);
+ if (ia_vcc == NULL)
+ {
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ dev_kfree_skb_any(skb);
+ atm_return(vcc, atm_guess_pdu2truesize(len));
+ goto INCR_DLE;
+@@ -1309,7 +1309,7 @@ static void rx_dle_intr(struct atm_dev *
+ if ((length > iadev->rx_buf_sz) || (length >
+ (skb->len - sizeof(struct cpcs_trailer))))
+ {
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)",
+ length, skb->len);)
+ dev_kfree_skb_any(skb);
+@@ -1325,7 +1325,7 @@ static void rx_dle_intr(struct atm_dev *
+
+ IF_RX(printk("rx_dle_intr: skb push");)
+ vcc->push(vcc,skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ iadev->rx_pkt_cnt++;
+ }
+ INCR_DLE:
+@@ -2807,15 +2807,15 @@ static int ia_ioctl(struct atm_dev *dev,
+ {
+ struct k_sonet_stats *stats;
+ stats = &PRIV(_ia_dev[board])->sonet_stats;
+- printk("section_bip: %d\n", atomic_read(&stats->section_bip));
+- printk("line_bip : %d\n", atomic_read(&stats->line_bip));
+- printk("path_bip : %d\n", atomic_read(&stats->path_bip));
+- printk("line_febe : %d\n", atomic_read(&stats->line_febe));
+- printk("path_febe : %d\n", atomic_read(&stats->path_febe));
+- printk("corr_hcs : %d\n", atomic_read(&stats->corr_hcs));
+- printk("uncorr_hcs : %d\n", atomic_read(&stats->uncorr_hcs));
+- printk("tx_cells : %d\n", atomic_read(&stats->tx_cells));
+- printk("rx_cells : %d\n", atomic_read(&stats->rx_cells));
++ printk("section_bip: %d\n", atomic_read_unchecked(&stats->section_bip));
++ printk("line_bip : %d\n", atomic_read_unchecked(&stats->line_bip));
++ printk("path_bip : %d\n", atomic_read_unchecked(&stats->path_bip));
++ printk("line_febe : %d\n", atomic_read_unchecked(&stats->line_febe));
++ printk("path_febe : %d\n", atomic_read_unchecked(&stats->path_febe));
++ printk("corr_hcs : %d\n", atomic_read_unchecked(&stats->corr_hcs));
++ printk("uncorr_hcs : %d\n", atomic_read_unchecked(&stats->uncorr_hcs));
++ printk("tx_cells : %d\n", atomic_read_unchecked(&stats->tx_cells));
++ printk("rx_cells : %d\n", atomic_read_unchecked(&stats->rx_cells));
+ }
+ ia_cmds.status = 0;
+ break;
+@@ -2920,7 +2920,7 @@ static int ia_pkt_tx (struct atm_vcc *vc
+ if ((desc == 0) || (desc > iadev->num_tx_desc))
+ {
+ IF_ERR(printk(DEV_LABEL "invalid desc for send: %d\n", desc);)
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+@@ -3025,14 +3025,14 @@ static int ia_pkt_tx (struct atm_vcc *vc
+ ATM_DESC(skb) = vcc->vci;
+ skb_queue_tail(&iadev->tx_dma_q, skb);
+
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ iadev->tx_pkt_cnt++;
+ /* Increment transaction counter */
+ writel(2, iadev->dma+IPHASE5575_TX_COUNTER);
+
+ #if 0
+ /* add flow control logic */
+- if (atomic_read(&vcc->stats->tx) % 20 == 0) {
++ if (atomic_read_unchecked(&vcc->stats->tx) % 20 == 0) {
+ if (iavcc->vc_desc_cnt > 10) {
+ vcc->tx_quota = vcc->tx_quota * 3 / 4;
+ printk("Tx1: vcc->tx_quota = %d \n", (u32)vcc->tx_quota );
+diff -urNp linux-2.6.38.7/drivers/atm/lanai.c linux-2.6.38.7/drivers/atm/lanai.c
+--- linux-2.6.38.7/drivers/atm/lanai.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/lanai.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1303,7 +1303,7 @@ static void lanai_send_one_aal5(struct l
+ vcc_tx_add_aal5_trailer(lvcc, skb->len, 0, 0);
+ lanai_endtx(lanai, lvcc);
+ lanai_free_skb(lvcc->tx.atmvcc, skb);
+- atomic_inc(&lvcc->tx.atmvcc->stats->tx);
++ atomic_inc_unchecked(&lvcc->tx.atmvcc->stats->tx);
+ }
+
+ /* Try to fill the buffer - don't call unless there is backlog */
+@@ -1426,7 +1426,7 @@ static void vcc_rx_aal5(struct lanai_vcc
+ ATM_SKB(skb)->vcc = lvcc->rx.atmvcc;
+ __net_timestamp(skb);
+ lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb);
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx);
+ out:
+ lvcc->rx.buf.ptr = end;
+ cardvcc_write(lvcc, endptr, vcc_rxreadptr);
+@@ -1668,7 +1668,7 @@ static int handle_service(struct lanai_d
+ DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 "
+ "vcc %d\n", lanai->number, (unsigned int) s, vci);
+ lanai->stats.service_rxnotaal5++;
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err);
+ return 0;
+ }
+ if (likely(!(s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)))) {
+@@ -1680,7 +1680,7 @@ static int handle_service(struct lanai_d
+ int bytes;
+ read_unlock(&vcc_sklist_lock);
+ DPRINTK("got trashed rx pdu on vci %d\n", vci);
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err);
+ lvcc->stats.x.aal5.service_trash++;
+ bytes = (SERVICE_GET_END(s) * 16) -
+ (((unsigned long) lvcc->rx.buf.ptr) -
+@@ -1692,7 +1692,7 @@ static int handle_service(struct lanai_d
+ }
+ if (s & SERVICE_STREAM) {
+ read_unlock(&vcc_sklist_lock);
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err);
+ lvcc->stats.x.aal5.service_stream++;
+ printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream "
+ "PDU on VCI %d!\n", lanai->number, vci);
+@@ -1700,7 +1700,7 @@ static int handle_service(struct lanai_d
+ return 0;
+ }
+ DPRINTK("got rx crc error on vci %d\n", vci);
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err);
+ lvcc->stats.x.aal5.service_rxcrc++;
+ lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4];
+ cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr);
+diff -urNp linux-2.6.38.7/drivers/atm/nicstar.c linux-2.6.38.7/drivers/atm/nicstar.c
+--- linux-2.6.38.7/drivers/atm/nicstar.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/nicstar.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1654,7 +1654,7 @@ static int ns_send(struct atm_vcc *vcc,
+ if ((vc = (vc_map *) vcc->dev_data) == NULL) {
+ printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n",
+ card->index);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+@@ -1662,7 +1662,7 @@ static int ns_send(struct atm_vcc *vcc,
+ if (!vc->tx) {
+ printk("nicstar%d: Trying to transmit on a non-tx VC.\n",
+ card->index);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+@@ -1670,14 +1670,14 @@ static int ns_send(struct atm_vcc *vcc,
+ if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) {
+ printk("nicstar%d: Only AAL0 and AAL5 are supported.\n",
+ card->index);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+
+ if (skb_shinfo(skb)->nr_frags != 0) {
+ printk("nicstar%d: No scatter-gather yet.\n", card->index);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+@@ -1725,11 +1725,11 @@ static int ns_send(struct atm_vcc *vcc,
+ }
+
+ if (push_scqe(card, vc, scq, &scqe, skb) != 0) {
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EIO;
+ }
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+
+ return 0;
+ }
+@@ -2046,14 +2046,14 @@ static void dequeue_rx(ns_dev * card, ns
+ printk
+ ("nicstar%d: Can't allocate buffers for aal0.\n",
+ card->index);
+- atomic_add(i, &vcc->stats->rx_drop);
++ atomic_add_unchecked(i, &vcc->stats->rx_drop);
+ break;
+ }
+ if (!atm_charge(vcc, sb->truesize)) {
+ RXPRINTK
+ ("nicstar%d: atm_charge() dropped aal0 packets.\n",
+ card->index);
+- atomic_add(i - 1, &vcc->stats->rx_drop); /* already increased by 1 */
++ atomic_add_unchecked(i - 1, &vcc->stats->rx_drop); /* already increased by 1 */
+ dev_kfree_skb_any(sb);
+ break;
+ }
+@@ -2068,7 +2068,7 @@ static void dequeue_rx(ns_dev * card, ns
+ ATM_SKB(sb)->vcc = vcc;
+ __net_timestamp(sb);
+ vcc->push(vcc, sb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ cell += ATM_CELL_PAYLOAD;
+ }
+
+@@ -2085,7 +2085,7 @@ static void dequeue_rx(ns_dev * card, ns
+ if (iovb == NULL) {
+ printk("nicstar%d: Out of iovec buffers.\n",
+ card->index);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ recycle_rx_buf(card, skb);
+ return;
+ }
+@@ -2109,7 +2109,7 @@ static void dequeue_rx(ns_dev * card, ns
+ small or large buffer itself. */
+ } else if (NS_PRV_IOVCNT(iovb) >= NS_MAX_IOVECS) {
+ printk("nicstar%d: received too big AAL5 SDU.\n", card->index);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
+ NS_MAX_IOVECS);
+ NS_PRV_IOVCNT(iovb) = 0;
+@@ -2129,7 +2129,7 @@ static void dequeue_rx(ns_dev * card, ns
+ ("nicstar%d: Expected a small buffer, and this is not one.\n",
+ card->index);
+ which_list(card, skb);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ recycle_rx_buf(card, skb);
+ vc->rx_iov = NULL;
+ recycle_iov_buf(card, iovb);
+@@ -2142,7 +2142,7 @@ static void dequeue_rx(ns_dev * card, ns
+ ("nicstar%d: Expected a large buffer, and this is not one.\n",
+ card->index);
+ which_list(card, skb);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
+ NS_PRV_IOVCNT(iovb));
+ vc->rx_iov = NULL;
+@@ -2165,7 +2165,7 @@ static void dequeue_rx(ns_dev * card, ns
+ printk(" - PDU size mismatch.\n");
+ else
+ printk(".\n");
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data,
+ NS_PRV_IOVCNT(iovb));
+ vc->rx_iov = NULL;
+@@ -2179,7 +2179,7 @@ static void dequeue_rx(ns_dev * card, ns
+ /* skb points to a small buffer */
+ if (!atm_charge(vcc, skb->truesize)) {
+ push_rxbufs(card, skb);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ } else {
+ skb_put(skb, len);
+ dequeue_sm_buf(card, skb);
+@@ -2189,7 +2189,7 @@ static void dequeue_rx(ns_dev * card, ns
+ ATM_SKB(skb)->vcc = vcc;
+ __net_timestamp(skb);
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+ } else if (NS_PRV_IOVCNT(iovb) == 2) { /* One small plus one large buffer */
+ struct sk_buff *sb;
+@@ -2200,7 +2200,7 @@ static void dequeue_rx(ns_dev * card, ns
+ if (len <= NS_SMBUFSIZE) {
+ if (!atm_charge(vcc, sb->truesize)) {
+ push_rxbufs(card, sb);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ } else {
+ skb_put(sb, len);
+ dequeue_sm_buf(card, sb);
+@@ -2210,7 +2210,7 @@ static void dequeue_rx(ns_dev * card, ns
+ ATM_SKB(sb)->vcc = vcc;
+ __net_timestamp(sb);
+ vcc->push(vcc, sb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+
+ push_rxbufs(card, skb);
+@@ -2219,7 +2219,7 @@ static void dequeue_rx(ns_dev * card, ns
+
+ if (!atm_charge(vcc, skb->truesize)) {
+ push_rxbufs(card, skb);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ } else {
+ dequeue_lg_buf(card, skb);
+ #ifdef NS_USE_DESTRUCTORS
+@@ -2232,7 +2232,7 @@ static void dequeue_rx(ns_dev * card, ns
+ ATM_SKB(skb)->vcc = vcc;
+ __net_timestamp(skb);
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+
+ push_rxbufs(card, sb);
+@@ -2253,7 +2253,7 @@ static void dequeue_rx(ns_dev * card, ns
+ printk
+ ("nicstar%d: Out of huge buffers.\n",
+ card->index);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ recycle_iovec_rx_bufs(card,
+ (struct iovec *)
+ iovb->data,
+@@ -2304,7 +2304,7 @@ static void dequeue_rx(ns_dev * card, ns
+ card->hbpool.count++;
+ } else
+ dev_kfree_skb_any(hb);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ } else {
+ /* Copy the small buffer to the huge buffer */
+ sb = (struct sk_buff *)iov->iov_base;
+@@ -2341,7 +2341,7 @@ static void dequeue_rx(ns_dev * card, ns
+ #endif /* NS_USE_DESTRUCTORS */
+ __net_timestamp(hb);
+ vcc->push(vcc, hb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+ }
+
+diff -urNp linux-2.6.38.7/drivers/atm/solos-pci.c linux-2.6.38.7/drivers/atm/solos-pci.c
+--- linux-2.6.38.7/drivers/atm/solos-pci.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/solos-pci.c 2011-05-16 21:47:08.000000000 -0400
+@@ -715,7 +715,7 @@ void solos_bh(unsigned long card_arg)
+ }
+ atm_charge(vcc, skb->truesize);
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ break;
+
+ case PKT_STATUS:
+@@ -900,6 +900,8 @@ static int print_buffer(struct sk_buff *
+ char msg[500];
+ char item[10];
+
++ pax_track_stack();
++
+ len = buf->len;
+ for (i = 0; i < len; i++){
+ if(i % 8 == 0)
+@@ -1009,7 +1011,7 @@ static uint32_t fpga_tx(struct solos_car
+ vcc = SKB_CB(oldskb)->vcc;
+
+ if (vcc) {
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ solos_pop(vcc, oldskb);
+ } else
+ dev_kfree_skb_irq(oldskb);
+diff -urNp linux-2.6.38.7/drivers/atm/suni.c linux-2.6.38.7/drivers/atm/suni.c
+--- linux-2.6.38.7/drivers/atm/suni.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/suni.c 2011-04-28 19:34:15.000000000 -0400
+@@ -50,8 +50,8 @@ static DEFINE_SPINLOCK(sunis_lock);
+
+
+ #define ADD_LIMITED(s,v) \
+- atomic_add((v),&stats->s); \
+- if (atomic_read(&stats->s) < 0) atomic_set(&stats->s,INT_MAX);
++ atomic_add_unchecked((v),&stats->s); \
++ if (atomic_read_unchecked(&stats->s) < 0) atomic_set_unchecked(&stats->s,INT_MAX);
+
+
+ static void suni_hz(unsigned long from_timer)
+diff -urNp linux-2.6.38.7/drivers/atm/uPD98402.c linux-2.6.38.7/drivers/atm/uPD98402.c
+--- linux-2.6.38.7/drivers/atm/uPD98402.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/uPD98402.c 2011-04-28 19:34:15.000000000 -0400
+@@ -42,7 +42,7 @@ static int fetch_stats(struct atm_dev *d
+ struct sonet_stats tmp;
+ int error = 0;
+
+- atomic_add(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs);
++ atomic_add_unchecked(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs);
+ sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp);
+ if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp));
+ if (zero && !error) {
+@@ -161,9 +161,9 @@ static int uPD98402_ioctl(struct atm_dev
+
+
+ #define ADD_LIMITED(s,v) \
+- { atomic_add(GET(v),&PRIV(dev)->sonet_stats.s); \
+- if (atomic_read(&PRIV(dev)->sonet_stats.s) < 0) \
+- atomic_set(&PRIV(dev)->sonet_stats.s,INT_MAX); }
++ { atomic_add_unchecked(GET(v),&PRIV(dev)->sonet_stats.s); \
++ if (atomic_read_unchecked(&PRIV(dev)->sonet_stats.s) < 0) \
++ atomic_set_unchecked(&PRIV(dev)->sonet_stats.s,INT_MAX); }
+
+
+ static void stat_event(struct atm_dev *dev)
+@@ -194,7 +194,7 @@ static void uPD98402_int(struct atm_dev
+ if (reason & uPD98402_INT_PFM) stat_event(dev);
+ if (reason & uPD98402_INT_PCO) {
+ (void) GET(PCOCR); /* clear interrupt cause */
+- atomic_add(GET(HECCT),
++ atomic_add_unchecked(GET(HECCT),
+ &PRIV(dev)->sonet_stats.uncorr_hcs);
+ }
+ if ((reason & uPD98402_INT_RFO) &&
+@@ -222,9 +222,9 @@ static int uPD98402_start(struct atm_dev
+ PUT(~(uPD98402_INT_PFM | uPD98402_INT_ALM | uPD98402_INT_RFO |
+ uPD98402_INT_LOS),PIMR); /* enable them */
+ (void) fetch_stats(dev,NULL,1); /* clear kernel counters */
+- atomic_set(&PRIV(dev)->sonet_stats.corr_hcs,-1);
+- atomic_set(&PRIV(dev)->sonet_stats.tx_cells,-1);
+- atomic_set(&PRIV(dev)->sonet_stats.rx_cells,-1);
++ atomic_set_unchecked(&PRIV(dev)->sonet_stats.corr_hcs,-1);
++ atomic_set_unchecked(&PRIV(dev)->sonet_stats.tx_cells,-1);
++ atomic_set_unchecked(&PRIV(dev)->sonet_stats.rx_cells,-1);
+ return 0;
+ }
+
+diff -urNp linux-2.6.38.7/drivers/atm/zatm.c linux-2.6.38.7/drivers/atm/zatm.c
+--- linux-2.6.38.7/drivers/atm/zatm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/atm/zatm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -459,7 +459,7 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy
+ }
+ if (!size) {
+ dev_kfree_skb_irq(skb);
+- if (vcc) atomic_inc(&vcc->stats->rx_err);
++ if (vcc) atomic_inc_unchecked(&vcc->stats->rx_err);
+ continue;
+ }
+ if (!atm_charge(vcc,skb->truesize)) {
+@@ -469,7 +469,7 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy
+ skb->len = size;
+ ATM_SKB(skb)->vcc = vcc;
+ vcc->push(vcc,skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+ zout(pos & 0xffff,MTA(mbx));
+ #if 0 /* probably a stupid idea */
+@@ -733,7 +733,7 @@ if (*ZATM_PRV_DSC(skb) != (uPD98401_TXPD
+ skb_queue_head(&zatm_vcc->backlog,skb);
+ break;
+ }
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ wake_up(&zatm_vcc->tx_wait);
+ }
+
+diff -urNp linux-2.6.38.7/drivers/base/power/wakeup.c linux-2.6.38.7/drivers/base/power/wakeup.c
+--- linux-2.6.38.7/drivers/base/power/wakeup.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/base/power/wakeup.c 2011-04-28 19:57:25.000000000 -0400
+@@ -25,7 +25,7 @@
+ bool events_check_enabled;
+
+ /* The counter of registered wakeup events. */
+-static atomic_t event_count = ATOMIC_INIT(0);
++static atomic_unchecked_t event_count = ATOMIC_INIT(0);
+ /* A preserved old value of event_count. */
+ static unsigned int saved_count;
+ /* The counter of wakeup events being processed. */
+@@ -399,7 +399,7 @@ static void wakeup_source_deactivate(str
+ * pm_save_wakeup_count() don't see the old value of event_count and
+ * events_in_progress equal to zero at the same time.
+ */
+- atomic_inc(&event_count);
++ atomic_inc_unchecked(&event_count);
+ smp_mb__before_atomic_dec();
+ atomic_dec(&events_in_progress);
+ }
+@@ -556,7 +556,7 @@ bool pm_wakeup_pending(void)
+
+ spin_lock_irqsave(&events_lock, flags);
+ if (events_check_enabled) {
+- ret = ((unsigned int)atomic_read(&event_count) != saved_count)
++ ret = ((unsigned int)atomic_read_unchecked(&event_count) != saved_count)
+ || atomic_read(&events_in_progress);
+ events_check_enabled = !ret;
+ }
+@@ -590,7 +590,7 @@ bool pm_get_wakeup_count(unsigned int *c
+ }
+
+ ret = !atomic_read(&events_in_progress);
+- *count = atomic_read(&event_count);
++ *count = atomic_read_unchecked(&event_count);
+ return ret;
+ }
+
+@@ -608,7 +608,7 @@ bool pm_save_wakeup_count(unsigned int c
+ bool ret = false;
+
+ spin_lock_irq(&events_lock);
+- if (count == (unsigned int)atomic_read(&event_count)
++ if (count == (unsigned int)atomic_read_unchecked(&event_count)
+ && !atomic_read(&events_in_progress)) {
+ saved_count = count;
+ events_check_enabled = true;
+diff -urNp linux-2.6.38.7/drivers/block/cciss.c linux-2.6.38.7/drivers/block/cciss.c
+--- linux-2.6.38.7/drivers/block/cciss.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/block/cciss.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1112,6 +1112,8 @@ static int cciss_ioctl32_passthru(struct
+ int err;
+ u32 cp;
+
++ memset(&arg64, 0, sizeof(arg64));
++
+ err = 0;
+ err |=
+ copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+diff -urNp linux-2.6.38.7/drivers/block/cpqarray.c linux-2.6.38.7/drivers/block/cpqarray.c
+--- linux-2.6.38.7/drivers/block/cpqarray.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/block/cpqarray.c 2011-05-16 21:47:08.000000000 -0400
+@@ -911,6 +911,8 @@ static void do_ida_request(struct reques
+ struct scatterlist tmp_sg[SG_MAX];
+ int i, dir, seg;
+
++ pax_track_stack();
++
+ if (blk_queue_plugged(q))
+ goto startio;
+
+diff -urNp linux-2.6.38.7/drivers/block/DAC960.c linux-2.6.38.7/drivers/block/DAC960.c
+--- linux-2.6.38.7/drivers/block/DAC960.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/block/DAC960.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1979,6 +1979,8 @@ static bool DAC960_V1_ReadDeviceConfigur
+ unsigned long flags;
+ int Channel, TargetID;
+
++ pax_track_stack();
++
+ if (!init_dma_loaf(Controller->PCIDevice, &local_dma,
+ DAC960_V1_MaxChannels*(sizeof(DAC960_V1_DCDB_T) +
+ sizeof(DAC960_SCSI_Inquiry_T) +
+diff -urNp linux-2.6.38.7/drivers/block/drbd/drbd_int.h linux-2.6.38.7/drivers/block/drbd/drbd_int.h
+--- linux-2.6.38.7/drivers/block/drbd/drbd_int.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/block/drbd/drbd_int.h 2011-04-28 19:57:25.000000000 -0400
+@@ -742,7 +742,7 @@ struct drbd_request;
+ struct drbd_epoch {
+ struct list_head list;
+ unsigned int barrier_nr;
+- atomic_t epoch_size; /* increased on every request added. */
++ atomic_unchecked_t epoch_size; /* increased on every request added. */
+ atomic_t active; /* increased on every req. added, and dec on every finished. */
+ unsigned long flags;
+ };
+@@ -1083,7 +1083,7 @@ struct drbd_conf {
+ void *int_dig_in;
+ void *int_dig_vv;
+ wait_queue_head_t seq_wait;
+- atomic_t packet_seq;
++ atomic_unchecked_t packet_seq;
+ unsigned int peer_seq;
+ spinlock_t peer_seq_lock;
+ unsigned int minor;
+diff -urNp linux-2.6.38.7/drivers/block/drbd/drbd_main.c linux-2.6.38.7/drivers/block/drbd/drbd_main.c
+--- linux-2.6.38.7/drivers/block/drbd/drbd_main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/block/drbd/drbd_main.c 2011-04-28 19:57:25.000000000 -0400
+@@ -2217,7 +2217,7 @@ static int _drbd_send_ack(struct drbd_co
+ p.sector = sector;
+ p.block_id = block_id;
+ p.blksize = blksize;
+- p.seq_num = cpu_to_be32(atomic_add_return(1, &mdev->packet_seq));
++ p.seq_num = cpu_to_be32(atomic_add_return_unchecked(1, &mdev->packet_seq));
+
+ if (!mdev->meta.socket || mdev->state.conn < C_CONNECTED)
+ return FALSE;
+@@ -2517,7 +2517,7 @@ int drbd_send_dblock(struct drbd_conf *m
+ p.sector = cpu_to_be64(req->sector);
+ p.block_id = (unsigned long)req;
+ p.seq_num = cpu_to_be32(req->seq_num =
+- atomic_add_return(1, &mdev->packet_seq));
++ atomic_add_return_unchecked(1, &mdev->packet_seq));
+
+ dp_flags = bio_flags_to_wire(mdev, req->master_bio->bi_rw);
+
+@@ -2795,7 +2795,7 @@ void drbd_init_set_defaults(struct drbd_
+ atomic_set(&mdev->unacked_cnt, 0);
+ atomic_set(&mdev->local_cnt, 0);
+ atomic_set(&mdev->net_cnt, 0);
+- atomic_set(&mdev->packet_seq, 0);
++ atomic_set_unchecked(&mdev->packet_seq, 0);
+ atomic_set(&mdev->pp_in_use, 0);
+ atomic_set(&mdev->pp_in_use_by_net, 0);
+ atomic_set(&mdev->rs_sect_in, 0);
+@@ -2866,8 +2866,8 @@ void drbd_mdev_cleanup(struct drbd_conf
+ mdev->receiver.t_state);
+
+ /* no need to lock it, I'm the only thread alive */
+- if (atomic_read(&mdev->current_epoch->epoch_size) != 0)
+- dev_err(DEV, "epoch_size:%d\n", atomic_read(&mdev->current_epoch->epoch_size));
++ if (atomic_read_unchecked(&mdev->current_epoch->epoch_size) != 0)
++ dev_err(DEV, "epoch_size:%d\n", atomic_read_unchecked(&mdev->current_epoch->epoch_size));
+ mdev->al_writ_cnt =
+ mdev->bm_writ_cnt =
+ mdev->read_cnt =
+diff -urNp linux-2.6.38.7/drivers/block/drbd/drbd_nl.c linux-2.6.38.7/drivers/block/drbd/drbd_nl.c
+--- linux-2.6.38.7/drivers/block/drbd/drbd_nl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/block/drbd/drbd_nl.c 2011-04-28 19:57:25.000000000 -0400
+@@ -2238,7 +2238,7 @@ static void drbd_connector_callback(stru
+ module_put(THIS_MODULE);
+ }
+
+-static atomic_t drbd_nl_seq = ATOMIC_INIT(2); /* two. */
++static atomic_unchecked_t drbd_nl_seq = ATOMIC_INIT(2); /* two. */
+
+ static unsigned short *
+ __tl_add_blob(unsigned short *tl, enum drbd_tags tag, const void *data,
+@@ -2309,7 +2309,7 @@ void drbd_bcast_state(struct drbd_conf *
+ cn_reply->id.idx = CN_IDX_DRBD;
+ cn_reply->id.val = CN_VAL_DRBD;
+
+- cn_reply->seq = atomic_add_return(1, &drbd_nl_seq);
++ cn_reply->seq = atomic_add_return_unchecked(1, &drbd_nl_seq);
+ cn_reply->ack = 0; /* not used here. */
+ cn_reply->len = sizeof(struct drbd_nl_cfg_reply) +
+ (int)((char *)tl - (char *)reply->tag_list);
+@@ -2341,7 +2341,7 @@ void drbd_bcast_ev_helper(struct drbd_co
+ cn_reply->id.idx = CN_IDX_DRBD;
+ cn_reply->id.val = CN_VAL_DRBD;
+
+- cn_reply->seq = atomic_add_return(1, &drbd_nl_seq);
++ cn_reply->seq = atomic_add_return_unchecked(1, &drbd_nl_seq);
+ cn_reply->ack = 0; /* not used here. */
+ cn_reply->len = sizeof(struct drbd_nl_cfg_reply) +
+ (int)((char *)tl - (char *)reply->tag_list);
+@@ -2416,7 +2416,7 @@ void drbd_bcast_ee(struct drbd_conf *mde
+ cn_reply->id.idx = CN_IDX_DRBD;
+ cn_reply->id.val = CN_VAL_DRBD;
+
+- cn_reply->seq = atomic_add_return(1,&drbd_nl_seq);
++ cn_reply->seq = atomic_add_return_unchecked(1,&drbd_nl_seq);
+ cn_reply->ack = 0; // not used here.
+ cn_reply->len = sizeof(struct drbd_nl_cfg_reply) +
+ (int)((char*)tl - (char*)reply->tag_list);
+@@ -2455,7 +2455,7 @@ void drbd_bcast_sync_progress(struct drb
+ cn_reply->id.idx = CN_IDX_DRBD;
+ cn_reply->id.val = CN_VAL_DRBD;
+
+- cn_reply->seq = atomic_add_return(1, &drbd_nl_seq);
++ cn_reply->seq = atomic_add_return_unchecked(1, &drbd_nl_seq);
+ cn_reply->ack = 0; /* not used here. */
+ cn_reply->len = sizeof(struct drbd_nl_cfg_reply) +
+ (int)((char *)tl - (char *)reply->tag_list);
+diff -urNp linux-2.6.38.7/drivers/block/drbd/drbd_receiver.c linux-2.6.38.7/drivers/block/drbd/drbd_receiver.c
+--- linux-2.6.38.7/drivers/block/drbd/drbd_receiver.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/block/drbd/drbd_receiver.c 2011-04-28 19:57:25.000000000 -0400
+@@ -907,7 +907,7 @@ retry:
+ sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10;
+ sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
+
+- atomic_set(&mdev->packet_seq, 0);
++ atomic_set_unchecked(&mdev->packet_seq, 0);
+ mdev->peer_seq = 0;
+
+ drbd_thread_start(&mdev->asender);
+@@ -1001,7 +1001,7 @@ static enum finish_epoch drbd_may_finish
+ do {
+ next_epoch = NULL;
+
+- epoch_size = atomic_read(&epoch->epoch_size);
++ epoch_size = atomic_read_unchecked(&epoch->epoch_size);
+
+ switch (ev & ~EV_CLEANUP) {
+ case EV_PUT:
+@@ -1036,7 +1036,7 @@ static enum finish_epoch drbd_may_finish
+ rv = FE_DESTROYED;
+ } else {
+ epoch->flags = 0;
+- atomic_set(&epoch->epoch_size, 0);
++ atomic_set_unchecked(&epoch->epoch_size, 0);
+ /* atomic_set(&epoch->active, 0); is already zero */
+ if (rv == FE_STILL_LIVE)
+ rv = FE_RECYCLED;
+@@ -1197,14 +1197,14 @@ static int receive_Barrier(struct drbd_c
+ drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
+ drbd_flush(mdev);
+
+- if (atomic_read(&mdev->current_epoch->epoch_size)) {
++ if (atomic_read_unchecked(&mdev->current_epoch->epoch_size)) {
+ epoch = kmalloc(sizeof(struct drbd_epoch), GFP_NOIO);
+ if (epoch)
+ break;
+ }
+
+ epoch = mdev->current_epoch;
+- wait_event(mdev->ee_wait, atomic_read(&epoch->epoch_size) == 0);
++ wait_event(mdev->ee_wait, atomic_read_unchecked(&epoch->epoch_size) == 0);
+
+ D_ASSERT(atomic_read(&epoch->active) == 0);
+ D_ASSERT(epoch->flags == 0);
+@@ -1216,11 +1216,11 @@ static int receive_Barrier(struct drbd_c
+ }
+
+ epoch->flags = 0;
+- atomic_set(&epoch->epoch_size, 0);
++ atomic_set_unchecked(&epoch->epoch_size, 0);
+ atomic_set(&epoch->active, 0);
+
+ spin_lock(&mdev->epoch_lock);
+- if (atomic_read(&mdev->current_epoch->epoch_size)) {
++ if (atomic_read_unchecked(&mdev->current_epoch->epoch_size)) {
+ list_add(&epoch->list, &mdev->current_epoch->list);
+ mdev->current_epoch = epoch;
+ mdev->epochs++;
+@@ -1663,7 +1663,7 @@ static int receive_Data(struct drbd_conf
+ spin_unlock(&mdev->peer_seq_lock);
+
+ drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
+- atomic_inc(&mdev->current_epoch->epoch_size);
++ atomic_inc_unchecked(&mdev->current_epoch->epoch_size);
+ return drbd_drain_block(mdev, data_size);
+ }
+
+@@ -1683,7 +1683,7 @@ static int receive_Data(struct drbd_conf
+
+ spin_lock(&mdev->epoch_lock);
+ e->epoch = mdev->current_epoch;
+- atomic_inc(&e->epoch->epoch_size);
++ atomic_inc_unchecked(&e->epoch->epoch_size);
+ atomic_inc(&e->epoch->active);
+ spin_unlock(&mdev->epoch_lock);
+
+@@ -1866,7 +1866,7 @@ static int receive_Data(struct drbd_conf
+ out_interrupted:
+ /* yes, the epoch_size now is imbalanced.
+ * but we drop the connection anyways, so we don't have a chance to
+- * receive a barrier... atomic_inc(&mdev->epoch_size); */
++ * receive a barrier... atomic_inc_unchecked(&mdev->epoch_size); */
+ put_ldev(mdev);
+ drbd_free_ee(mdev, e);
+ return FALSE;
+@@ -3821,7 +3821,7 @@ static void drbd_disconnect(struct drbd_
+ D_ASSERT(list_empty(&mdev->done_ee));
+
+ /* ok, no more ee's on the fly, it is safe to reset the epoch_size */
+- atomic_set(&mdev->current_epoch->epoch_size, 0);
++ atomic_set_unchecked(&mdev->current_epoch->epoch_size, 0);
+ D_ASSERT(list_empty(&mdev->current_epoch->list));
+ }
+
+diff -urNp linux-2.6.38.7/drivers/block/nbd.c linux-2.6.38.7/drivers/block/nbd.c
+--- linux-2.6.38.7/drivers/block/nbd.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/block/nbd.c 2011-05-16 21:47:08.000000000 -0400
+@@ -157,6 +157,8 @@ static int sock_xmit(struct nbd_device *
+ struct kvec iov;
+ sigset_t blocked, oldset;
+
++ pax_track_stack();
++
+ if (unlikely(!sock)) {
+ printk(KERN_ERR "%s: Attempted %s on closed socket in sock_xmit\n",
+ lo->disk->disk_name, (send ? "send" : "recv"));
+@@ -571,6 +573,8 @@ static void do_nbd_request(struct reques
+ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
+ unsigned int cmd, unsigned long arg)
+ {
++ pax_track_stack();
++
+ switch (cmd) {
+ case NBD_DISCONNECT: {
+ struct request sreq;
+diff -urNp linux-2.6.38.7/drivers/char/agp/frontend.c linux-2.6.38.7/drivers/char/agp/frontend.c
+--- linux-2.6.38.7/drivers/char/agp/frontend.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/agp/frontend.c 2011-04-28 19:34:15.000000000 -0400
+@@ -817,7 +817,7 @@ static int agpioc_reserve_wrap(struct ag
+ if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
+ return -EFAULT;
+
+- if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
++ if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment_priv))
+ return -EFAULT;
+
+ client = agp_find_client_by_pid(reserve.pid);
+diff -urNp linux-2.6.38.7/drivers/char/briq_panel.c linux-2.6.38.7/drivers/char/briq_panel.c
+--- linux-2.6.38.7/drivers/char/briq_panel.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/briq_panel.c 2011-04-28 19:34:15.000000000 -0400
+@@ -9,6 +9,7 @@
+ #include <linux/types.h>
+ #include <linux/errno.h>
+ #include <linux/tty.h>
++#include <linux/mutex.h>
+ #include <linux/timer.h>
+ #include <linux/kernel.h>
+ #include <linux/wait.h>
+@@ -34,6 +35,7 @@ static int vfd_is_open;
+ static unsigned char vfd[40];
+ static int vfd_cursor;
+ static unsigned char ledpb, led;
++static DEFINE_MUTEX(vfd_mutex);
+
+ static void update_vfd(void)
+ {
+@@ -140,12 +142,15 @@ static ssize_t briq_panel_write(struct f
+ if (!vfd_is_open)
+ return -EBUSY;
+
++ mutex_lock(&vfd_mutex);
+ for (;;) {
+ char c;
+ if (!indx)
+ break;
+- if (get_user(c, buf))
++ if (get_user(c, buf)) {
++ mutex_unlock(&vfd_mutex);
+ return -EFAULT;
++ }
+ if (esc) {
+ set_led(c);
+ esc = 0;
+@@ -175,6 +180,7 @@ static ssize_t briq_panel_write(struct f
+ buf++;
+ }
+ update_vfd();
++ mutex_unlock(&vfd_mutex);
+
+ return len;
+ }
+diff -urNp linux-2.6.38.7/drivers/char/genrtc.c linux-2.6.38.7/drivers/char/genrtc.c
+--- linux-2.6.38.7/drivers/char/genrtc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/genrtc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -273,6 +273,7 @@ static int gen_rtc_ioctl(struct file *fi
+ switch (cmd) {
+
+ case RTC_PLL_GET:
++ memset(&pll, 0, sizeof(pll));
+ if (get_rtc_pll(&pll))
+ return -EINVAL;
+ else
+diff -urNp linux-2.6.38.7/drivers/char/hpet.c linux-2.6.38.7/drivers/char/hpet.c
+--- linux-2.6.38.7/drivers/char/hpet.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/hpet.c 2011-04-28 19:34:15.000000000 -0400
+@@ -553,7 +553,7 @@ static inline unsigned long hpet_time_di
+ }
+
+ static int
+-hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg,
++hpet_ioctl_common(struct hpet_dev *devp, unsigned int cmd, unsigned long arg,
+ struct hpet_info *info)
+ {
+ struct hpet_timer __iomem *timer;
+diff -urNp linux-2.6.38.7/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.38.7/drivers/char/ipmi/ipmi_msghandler.c
+--- linux-2.6.38.7/drivers/char/ipmi/ipmi_msghandler.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/ipmi/ipmi_msghandler.c 2011-05-16 21:47:08.000000000 -0400
+@@ -414,7 +414,7 @@ struct ipmi_smi {
+ struct proc_dir_entry *proc_dir;
+ char proc_dir_name[10];
+
+- atomic_t stats[IPMI_NUM_STATS];
++ atomic_unchecked_t stats[IPMI_NUM_STATS];
+
+ /*
+ * run_to_completion duplicate of smb_info, smi_info
+@@ -447,9 +447,9 @@ static DEFINE_MUTEX(smi_watchers_mutex);
+
+
+ #define ipmi_inc_stat(intf, stat) \
+- atomic_inc(&(intf)->stats[IPMI_STAT_ ## stat])
++ atomic_inc_unchecked(&(intf)->stats[IPMI_STAT_ ## stat])
+ #define ipmi_get_stat(intf, stat) \
+- ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat]))
++ ((unsigned int) atomic_read_unchecked(&(intf)->stats[IPMI_STAT_ ## stat]))
+
+ static int is_lan_addr(struct ipmi_addr *addr)
+ {
+@@ -2844,7 +2844,7 @@ int ipmi_register_smi(struct ipmi_smi_ha
+ INIT_LIST_HEAD(&intf->cmd_rcvrs);
+ init_waitqueue_head(&intf->waitq);
+ for (i = 0; i < IPMI_NUM_STATS; i++)
+- atomic_set(&intf->stats[i], 0);
++ atomic_set_unchecked(&intf->stats[i], 0);
+
+ intf->proc_dir = NULL;
+
+@@ -4196,6 +4196,8 @@ static void send_panic_events(char *str)
+ struct ipmi_smi_msg smi_msg;
+ struct ipmi_recv_msg recv_msg;
+
++ pax_track_stack();
++
+ si = (struct ipmi_system_interface_addr *) &addr;
+ si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+ si->channel = IPMI_BMC_CHANNEL;
+diff -urNp linux-2.6.38.7/drivers/char/ipmi/ipmi_si_intf.c linux-2.6.38.7/drivers/char/ipmi/ipmi_si_intf.c
+--- linux-2.6.38.7/drivers/char/ipmi/ipmi_si_intf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/ipmi/ipmi_si_intf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -285,7 +285,7 @@ struct smi_info {
+ unsigned char slave_addr;
+
+ /* Counters and things for the proc filesystem. */
+- atomic_t stats[SI_NUM_STATS];
++ atomic_unchecked_t stats[SI_NUM_STATS];
+
+ struct task_struct *thread;
+
+@@ -294,9 +294,9 @@ struct smi_info {
+ };
+
+ #define smi_inc_stat(smi, stat) \
+- atomic_inc(&(smi)->stats[SI_STAT_ ## stat])
++ atomic_inc_unchecked(&(smi)->stats[SI_STAT_ ## stat])
+ #define smi_get_stat(smi, stat) \
+- ((unsigned int) atomic_read(&(smi)->stats[SI_STAT_ ## stat]))
++ ((unsigned int) atomic_read_unchecked(&(smi)->stats[SI_STAT_ ## stat]))
+
+ #define SI_MAX_PARMS 4
+
+@@ -3202,7 +3202,7 @@ static int try_smi_init(struct smi_info
+ atomic_set(&new_smi->req_events, 0);
+ new_smi->run_to_completion = 0;
+ for (i = 0; i < SI_NUM_STATS; i++)
+- atomic_set(&new_smi->stats[i], 0);
++ atomic_set_unchecked(&new_smi->stats[i], 0);
+
+ new_smi->interrupt_disabled = 1;
+ atomic_set(&new_smi->stop_operation, 0);
+diff -urNp linux-2.6.38.7/drivers/char/istallion.c linux-2.6.38.7/drivers/char/istallion.c
+--- linux-2.6.38.7/drivers/char/istallion.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/istallion.c 2011-05-16 21:47:08.000000000 -0400
+@@ -186,7 +186,6 @@ static struct ktermios stli_deftermios
+ * re-used for each stats call.
+ */
+ static comstats_t stli_comstats;
+-static combrd_t stli_brdstats;
+ static struct asystats stli_cdkstats;
+
+ /*****************************************************************************/
+@@ -4005,6 +4004,7 @@ static int stli_getbrdstats(combrd_t __u
+ {
+ struct stlibrd *brdp;
+ unsigned int i;
++ combrd_t stli_brdstats;
+
+ if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
+ return -EFAULT;
+@@ -4226,6 +4226,8 @@ static int stli_getportstruct(struct stl
+ struct stliport stli_dummyport;
+ struct stliport *portp;
+
++ pax_track_stack();
++
+ if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport)))
+ return -EFAULT;
+ portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
+@@ -4248,6 +4250,8 @@ static int stli_getbrdstruct(struct stli
+ struct stlibrd stli_dummybrd;
+ struct stlibrd *brdp;
+
++ pax_track_stack();
++
+ if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd)))
+ return -EFAULT;
+ if (stli_dummybrd.brdnr >= STL_MAXBRDS)
+diff -urNp linux-2.6.38.7/drivers/char/Kconfig linux-2.6.38.7/drivers/char/Kconfig
+--- linux-2.6.38.7/drivers/char/Kconfig 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/Kconfig 2011-04-28 19:34:15.000000000 -0400
+@@ -90,7 +90,8 @@ config VT_HW_CONSOLE_BINDING
+
+ config DEVKMEM
+ bool "/dev/kmem virtual device support"
+- default y
++ default n
++ depends on !GRKERNSEC_KMEM
+ help
+ Say Y here if you want to support the /dev/kmem device. The
+ /dev/kmem device is rarely used, but can be used for certain
+@@ -1132,6 +1133,7 @@ config DEVPORT
+ bool
+ depends on !M68K
+ depends on ISA || PCI
++ depends on !GRKERNSEC_KMEM
+ default y
+
+ source "drivers/s390/char/Kconfig"
+diff -urNp linux-2.6.38.7/drivers/char/mem.c linux-2.6.38.7/drivers/char/mem.c
+--- linux-2.6.38.7/drivers/char/mem.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/mem.c 2011-04-28 19:34:15.000000000 -0400
+@@ -18,6 +18,7 @@
+ #include <linux/raw.h>
+ #include <linux/tty.h>
+ #include <linux/capability.h>
++#include <linux/security.h>
+ #include <linux/ptrace.h>
+ #include <linux/device.h>
+ #include <linux/highmem.h>
+@@ -34,6 +35,10 @@
+ # include <linux/efi.h>
+ #endif
+
++#if defined(CONFIG_GRKERNSEC) && !defined(CONFIG_GRKERNSEC_NO_RBAC)
++extern struct file_operations grsec_fops;
++#endif
++
+ static inline unsigned long size_inside_page(unsigned long start,
+ unsigned long size)
+ {
+@@ -68,9 +73,13 @@ static inline int range_is_allowed(unsig
+
+ while (cursor < to) {
+ if (!devmem_is_allowed(pfn)) {
++#ifdef CONFIG_GRKERNSEC_KMEM
++ gr_handle_mem_readwrite(from, to);
++#else
+ printk(KERN_INFO
+ "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
+ current->comm, from, to);
++#endif
+ return 0;
+ }
+ cursor += PAGE_SIZE;
+@@ -78,6 +87,11 @@ static inline int range_is_allowed(unsig
+ }
+ return 1;
+ }
++#elif defined(CONFIG_GRKERNSEC_KMEM)
++static inline int range_is_allowed(unsigned long pfn, unsigned long size)
++{
++ return 0;
++}
+ #else
+ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+ {
+@@ -120,6 +134,7 @@ static ssize_t read_mem(struct file *fil
+
+ while (count > 0) {
+ unsigned long remaining;
++ char *temp;
+
+ sz = size_inside_page(p, count);
+
+@@ -135,7 +150,23 @@ static ssize_t read_mem(struct file *fil
+ if (!ptr)
+ return -EFAULT;
+
+- remaining = copy_to_user(buf, ptr, sz);
++#ifdef CONFIG_PAX_USERCOPY
++ temp = kmalloc(sz, GFP_KERNEL);
++ if (!temp) {
++ unxlate_dev_mem_ptr(p, ptr);
++ return -ENOMEM;
++ }
++ memcpy(temp, ptr, sz);
++#else
++ temp = ptr;
++#endif
++
++ remaining = copy_to_user(buf, temp, sz);
++
++#ifdef CONFIG_PAX_USERCOPY
++ kfree(temp);
++#endif
++
+ unxlate_dev_mem_ptr(p, ptr);
+ if (remaining)
+ return -EFAULT;
+@@ -398,9 +429,8 @@ static ssize_t read_kmem(struct file *fi
+ size_t count, loff_t *ppos)
+ {
+ unsigned long p = *ppos;
+- ssize_t low_count, read, sz;
++ ssize_t low_count, read, sz, err = 0;
+ char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
+- int err = 0;
+
+ read = 0;
+ if (p < (unsigned long) high_memory) {
+@@ -422,6 +452,8 @@ static ssize_t read_kmem(struct file *fi
+ }
+ #endif
+ while (low_count > 0) {
++ char *temp;
++
+ sz = size_inside_page(p, low_count);
+
+ /*
+@@ -431,7 +463,22 @@ static ssize_t read_kmem(struct file *fi
+ */
+ kbuf = xlate_dev_kmem_ptr((char *)p);
+
+- if (copy_to_user(buf, kbuf, sz))
++#ifdef CONFIG_PAX_USERCOPY
++ temp = kmalloc(sz, GFP_KERNEL);
++ if (!temp)
++ return -ENOMEM;
++ memcpy(temp, kbuf, sz);
++#else
++ temp = kbuf;
++#endif
++
++ err = copy_to_user(buf, temp, sz);
++
++#ifdef CONFIG_PAX_USERCOPY
++ kfree(temp);
++#endif
++
++ if (err)
+ return -EFAULT;
+ buf += sz;
+ p += sz;
+@@ -857,6 +904,9 @@ static const struct memdev {
+ #ifdef CONFIG_CRASH_DUMP
+ [12] = { "oldmem", 0, &oldmem_fops, NULL },
+ #endif
++#if defined(CONFIG_GRKERNSEC) && !defined(CONFIG_GRKERNSEC_NO_RBAC)
++ [13] = { "grsec",S_IRUSR | S_IWUGO, &grsec_fops, NULL },
++#endif
+ };
+
+ static int memory_open(struct inode *inode, struct file *filp)
+diff -urNp linux-2.6.38.7/drivers/char/nvram.c linux-2.6.38.7/drivers/char/nvram.c
+--- linux-2.6.38.7/drivers/char/nvram.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/nvram.c 2011-04-28 19:34:15.000000000 -0400
+@@ -246,7 +246,7 @@ static ssize_t nvram_read(struct file *f
+
+ spin_unlock_irq(&rtc_lock);
+
+- if (copy_to_user(buf, contents, tmp - contents))
++ if (tmp - contents > sizeof(contents) || copy_to_user(buf, contents, tmp - contents))
+ return -EFAULT;
+
+ *ppos = i;
+diff -urNp linux-2.6.38.7/drivers/char/pcmcia/ipwireless/tty.c linux-2.6.38.7/drivers/char/pcmcia/ipwireless/tty.c
+--- linux-2.6.38.7/drivers/char/pcmcia/ipwireless/tty.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/pcmcia/ipwireless/tty.c 2011-04-28 19:34:15.000000000 -0400
+@@ -29,6 +29,7 @@
+ #include <linux/tty_driver.h>
+ #include <linux/tty_flip.h>
+ #include <linux/uaccess.h>
++#include <asm/local.h>
+
+ #include "tty.h"
+ #include "network.h"
+@@ -51,7 +52,7 @@ struct ipw_tty {
+ int tty_type;
+ struct ipw_network *network;
+ struct tty_struct *linux_tty;
+- int open_count;
++ local_t open_count;
+ unsigned int control_lines;
+ struct mutex ipw_tty_mutex;
+ int tx_bytes_queued;
+@@ -127,10 +128,10 @@ static int ipw_open(struct tty_struct *l
+ mutex_unlock(&tty->ipw_tty_mutex);
+ return -ENODEV;
+ }
+- if (tty->open_count == 0)
++ if (local_read(&tty->open_count) == 0)
+ tty->tx_bytes_queued = 0;
+
+- tty->open_count++;
++ local_inc(&tty->open_count);
+
+ tty->linux_tty = linux_tty;
+ linux_tty->driver_data = tty;
+@@ -146,9 +147,7 @@ static int ipw_open(struct tty_struct *l
+
+ static void do_ipw_close(struct ipw_tty *tty)
+ {
+- tty->open_count--;
+-
+- if (tty->open_count == 0) {
++ if (local_dec_return(&tty->open_count) == 0) {
+ struct tty_struct *linux_tty = tty->linux_tty;
+
+ if (linux_tty != NULL) {
+@@ -169,7 +168,7 @@ static void ipw_hangup(struct tty_struct
+ return;
+
+ mutex_lock(&tty->ipw_tty_mutex);
+- if (tty->open_count == 0) {
++ if (local_read(&tty->open_count) == 0) {
+ mutex_unlock(&tty->ipw_tty_mutex);
+ return;
+ }
+@@ -198,7 +197,7 @@ void ipwireless_tty_received(struct ipw_
+ return;
+ }
+
+- if (!tty->open_count) {
++ if (!local_read(&tty->open_count)) {
+ mutex_unlock(&tty->ipw_tty_mutex);
+ return;
+ }
+@@ -240,7 +239,7 @@ static int ipw_write(struct tty_struct *
+ return -ENODEV;
+
+ mutex_lock(&tty->ipw_tty_mutex);
+- if (!tty->open_count) {
++ if (!local_read(&tty->open_count)) {
+ mutex_unlock(&tty->ipw_tty_mutex);
+ return -EINVAL;
+ }
+@@ -280,7 +279,7 @@ static int ipw_write_room(struct tty_str
+ if (!tty)
+ return -ENODEV;
+
+- if (!tty->open_count)
++ if (!local_read(&tty->open_count))
+ return -EINVAL;
+
+ room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
+@@ -322,7 +321,7 @@ static int ipw_chars_in_buffer(struct tt
+ if (!tty)
+ return 0;
+
+- if (!tty->open_count)
++ if (!local_read(&tty->open_count))
+ return 0;
+
+ return tty->tx_bytes_queued;
+@@ -403,7 +402,7 @@ static int ipw_tiocmget(struct tty_struc
+ if (!tty)
+ return -ENODEV;
+
+- if (!tty->open_count)
++ if (!local_read(&tty->open_count))
+ return -EINVAL;
+
+ return get_control_lines(tty);
+@@ -419,7 +418,7 @@ ipw_tiocmset(struct tty_struct *linux_tt
+ if (!tty)
+ return -ENODEV;
+
+- if (!tty->open_count)
++ if (!local_read(&tty->open_count))
+ return -EINVAL;
+
+ return set_control_lines(tty, set, clear);
+@@ -433,7 +432,7 @@ static int ipw_ioctl(struct tty_struct *
+ if (!tty)
+ return -ENODEV;
+
+- if (!tty->open_count)
++ if (!local_read(&tty->open_count))
+ return -EINVAL;
+
+ /* FIXME: Exactly how is the tty object locked here .. */
+@@ -582,7 +581,7 @@ void ipwireless_tty_free(struct ipw_tty
+ against a parallel ioctl etc */
+ mutex_lock(&ttyj->ipw_tty_mutex);
+ }
+- while (ttyj->open_count)
++ while (local_read(&ttyj->open_count))
+ do_ipw_close(ttyj);
+ ipwireless_disassociate_network_ttys(network,
+ ttyj->channel_idx);
+diff -urNp linux-2.6.38.7/drivers/char/random.c linux-2.6.38.7/drivers/char/random.c
+--- linux-2.6.38.7/drivers/char/random.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/random.c 2011-04-28 19:34:15.000000000 -0400
+@@ -254,8 +254,13 @@
+ /*
+ * Configuration information
+ */
++#ifdef CONFIG_GRKERNSEC_RANDNET
++#define INPUT_POOL_WORDS 512
++#define OUTPUT_POOL_WORDS 128
++#else
+ #define INPUT_POOL_WORDS 128
+ #define OUTPUT_POOL_WORDS 32
++#endif
+ #define SEC_XFER_SIZE 512
+ #define EXTRACT_SIZE 10
+
+@@ -293,10 +298,17 @@ static struct poolinfo {
+ int poolwords;
+ int tap1, tap2, tap3, tap4, tap5;
+ } poolinfo_table[] = {
++#ifdef CONFIG_GRKERNSEC_RANDNET
++ /* x^512 + x^411 + x^308 + x^208 +x^104 + x + 1 -- 225 */
++ { 512, 411, 308, 208, 104, 1 },
++ /* x^128 + x^103 + x^76 + x^51 + x^25 + x + 1 -- 105 */
++ { 128, 103, 76, 51, 25, 1 },
++#else
+ /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
+ { 128, 103, 76, 51, 25, 1 },
+ /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
+ { 32, 26, 20, 14, 7, 1 },
++#endif
+ #if 0
+ /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
+ { 2048, 1638, 1231, 819, 411, 1 },
+@@ -902,7 +914,7 @@ static ssize_t extract_entropy_user(stru
+
+ extract_buf(r, tmp);
+ i = min_t(int, nbytes, EXTRACT_SIZE);
+- if (copy_to_user(buf, tmp, i)) {
++ if (i > sizeof(tmp) || copy_to_user(buf, tmp, i)) {
+ ret = -EFAULT;
+ break;
+ }
+@@ -1207,7 +1219,7 @@ EXPORT_SYMBOL(generate_random_uuid);
+ #include <linux/sysctl.h>
+
+ static int min_read_thresh = 8, min_write_thresh;
+-static int max_read_thresh = INPUT_POOL_WORDS * 32;
++static int max_read_thresh = OUTPUT_POOL_WORDS * 32;
+ static int max_write_thresh = INPUT_POOL_WORDS * 32;
+ static char sysctl_bootid[16];
+
+diff -urNp linux-2.6.38.7/drivers/char/rocket.c linux-2.6.38.7/drivers/char/rocket.c
+--- linux-2.6.38.7/drivers/char/rocket.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/rocket.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1277,6 +1277,8 @@ static int get_ports(struct r_port *info
+ struct rocket_ports tmp;
+ int board;
+
++ pax_track_stack();
++
+ if (!retports)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof (tmp));
+diff -urNp linux-2.6.38.7/drivers/char/sonypi.c linux-2.6.38.7/drivers/char/sonypi.c
+--- linux-2.6.38.7/drivers/char/sonypi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/sonypi.c 2011-04-28 19:34:15.000000000 -0400
+@@ -55,6 +55,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/system.h>
++#include <asm/local.h>
+
+ #include <linux/sonypi.h>
+
+@@ -491,7 +492,7 @@ static struct sonypi_device {
+ spinlock_t fifo_lock;
+ wait_queue_head_t fifo_proc_list;
+ struct fasync_struct *fifo_async;
+- int open_count;
++ local_t open_count;
+ int model;
+ struct input_dev *input_jog_dev;
+ struct input_dev *input_key_dev;
+@@ -898,7 +899,7 @@ static int sonypi_misc_fasync(int fd, st
+ static int sonypi_misc_release(struct inode *inode, struct file *file)
+ {
+ mutex_lock(&sonypi_device.lock);
+- sonypi_device.open_count--;
++ local_dec(&sonypi_device.open_count);
+ mutex_unlock(&sonypi_device.lock);
+ return 0;
+ }
+@@ -907,9 +908,9 @@ static int sonypi_misc_open(struct inode
+ {
+ mutex_lock(&sonypi_device.lock);
+ /* Flush input queue on first open */
+- if (!sonypi_device.open_count)
++ if (!local_read(&sonypi_device.open_count))
+ kfifo_reset(&sonypi_device.fifo);
+- sonypi_device.open_count++;
++ local_inc(&sonypi_device.open_count);
+ mutex_unlock(&sonypi_device.lock);
+
+ return 0;
+diff -urNp linux-2.6.38.7/drivers/char/stallion.c linux-2.6.38.7/drivers/char/stallion.c
+--- linux-2.6.38.7/drivers/char/stallion.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/stallion.c 2011-05-16 21:47:08.000000000 -0400
+@@ -2407,6 +2407,8 @@ static int stl_getportstruct(struct stlp
+ struct stlport stl_dummyport;
+ struct stlport *portp;
+
++ pax_track_stack();
++
+ if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
+ return -EFAULT;
+ portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
+diff -urNp linux-2.6.38.7/drivers/char/tpm/tpm_bios.c linux-2.6.38.7/drivers/char/tpm/tpm_bios.c
+--- linux-2.6.38.7/drivers/char/tpm/tpm_bios.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/char/tpm/tpm_bios.c 2011-04-28 19:34:15.000000000 -0400
+@@ -173,7 +173,7 @@ static void *tpm_bios_measurements_start
+ event = addr;
+
+ if ((event->event_type == 0 && event->event_size == 0) ||
+- ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
++ (event->event_size >= limit - addr - sizeof(struct tcpa_event)))
+ return NULL;
+
+ return addr;
+@@ -198,7 +198,7 @@ static void *tpm_bios_measurements_next(
+ return NULL;
+
+ if ((event->event_type == 0 && event->event_size == 0) ||
+- ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
++ (event->event_size >= limit - v - sizeof(struct tcpa_event)))
+ return NULL;
+
+ (*pos)++;
+@@ -291,7 +291,8 @@ static int tpm_binary_bios_measurements_
+ int i;
+
+ for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
+- seq_putc(m, data[i]);
++ if (!seq_putc(m, data[i]))
++ return -EFAULT;
+
+ return 0;
+ }
+@@ -410,6 +411,11 @@ static int read_log(struct tpm_bios_log
+ log->bios_event_log_end = log->bios_event_log + len;
+
+ virt = acpi_os_map_memory(start, len);
++ if (!virt) {
++ kfree(log->bios_event_log);
++ log->bios_event_log = NULL;
++ return -EFAULT;
++ }
+
+ memcpy(log->bios_event_log, virt, len);
+
+diff -urNp linux-2.6.38.7/drivers/char/tpm/tpm.c linux-2.6.38.7/drivers/char/tpm/tpm.c
+--- linux-2.6.38.7/drivers/char/tpm/tpm.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/drivers/char/tpm/tpm.c 2011-05-16 21:47:08.000000000 -0400
+@@ -411,7 +411,7 @@ static ssize_t tpm_transmit(struct tpm_c
+ chip->vendor.req_complete_val)
+ goto out_recv;
+
+- if ((status == chip->vendor.req_canceled)) {
++ if (status == chip->vendor.req_canceled) {
+ dev_err(chip->dev, "Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+@@ -844,6 +844,8 @@ ssize_t tpm_show_pubek(struct device *de
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+
++ pax_track_stack();
++
+ tpm_cmd.header.in = tpm_readpubek_header;
+ err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
+ "attempting to read the PUBEK");
+diff -urNp linux-2.6.38.7/drivers/cpuidle/sysfs.c linux-2.6.38.7/drivers/cpuidle/sysfs.c
+--- linux-2.6.38.7/drivers/cpuidle/sysfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/cpuidle/sysfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -300,7 +300,7 @@ static struct kobj_type ktype_state_cpui
+ .release = cpuidle_state_sysfs_release,
+ };
+
+-static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
++static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
+ {
+ kobject_put(&device->kobjs[i]->kobj);
+ wait_for_completion(&device->kobjs[i]->kobj_unregister);
+diff -urNp linux-2.6.38.7/drivers/crypto/hifn_795x.c linux-2.6.38.7/drivers/crypto/hifn_795x.c
+--- linux-2.6.38.7/drivers/crypto/hifn_795x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/crypto/hifn_795x.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1655,6 +1655,8 @@ static int hifn_test(struct hifn_device
+ 0xCA, 0x34, 0x2B, 0x2E};
+ struct scatterlist sg;
+
++ pax_track_stack();
++
+ memset(src, 0, sizeof(src));
+ memset(ctx.key, 0, sizeof(ctx.key));
+
+diff -urNp linux-2.6.38.7/drivers/crypto/padlock-aes.c linux-2.6.38.7/drivers/crypto/padlock-aes.c
+--- linux-2.6.38.7/drivers/crypto/padlock-aes.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/crypto/padlock-aes.c 2011-05-16 21:47:08.000000000 -0400
+@@ -109,6 +109,8 @@ static int aes_set_key(struct crypto_tfm
+ struct crypto_aes_ctx gen_aes;
+ int cpu;
+
++ pax_track_stack();
++
+ if (key_len % 8) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+diff -urNp linux-2.6.38.7/drivers/edac/edac_mc_sysfs.c linux-2.6.38.7/drivers/edac/edac_mc_sysfs.c
+--- linux-2.6.38.7/drivers/edac/edac_mc_sysfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/edac/edac_mc_sysfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -761,7 +761,7 @@ static void edac_inst_grp_release(struct
+ }
+
+ /* Intermediate show/store table */
+-static struct sysfs_ops inst_grp_ops = {
++static const struct sysfs_ops inst_grp_ops = {
+ .show = inst_grp_show,
+ .store = inst_grp_store
+ };
+diff -urNp linux-2.6.38.7/drivers/edac/edac_pci_sysfs.c linux-2.6.38.7/drivers/edac/edac_pci_sysfs.c
+--- linux-2.6.38.7/drivers/edac/edac_pci_sysfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/edac/edac_pci_sysfs.c 2011-04-28 19:57:25.000000000 -0400
+@@ -26,8 +26,8 @@ static int edac_pci_log_pe = 1; /* log
+ static int edac_pci_log_npe = 1; /* log PCI non-parity error errors */
+ static int edac_pci_poll_msec = 1000; /* one second workq period */
+
+-static atomic_t pci_parity_count = ATOMIC_INIT(0);
+-static atomic_t pci_nonparity_count = ATOMIC_INIT(0);
++static atomic_unchecked_t pci_parity_count = ATOMIC_INIT(0);
++static atomic_unchecked_t pci_nonparity_count = ATOMIC_INIT(0);
+
+ static struct kobject *edac_pci_top_main_kobj;
+ static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0);
+@@ -582,7 +582,7 @@ static void edac_pci_dev_parity_test(str
+ edac_printk(KERN_CRIT, EDAC_PCI,
+ "Signaled System Error on %s\n",
+ pci_name(dev));
+- atomic_inc(&pci_nonparity_count);
++ atomic_inc_unchecked(&pci_nonparity_count);
+ }
+
+ if (status & (PCI_STATUS_PARITY)) {
+@@ -590,7 +590,7 @@ static void edac_pci_dev_parity_test(str
+ "Master Data Parity Error on %s\n",
+ pci_name(dev));
+
+- atomic_inc(&pci_parity_count);
++ atomic_inc_unchecked(&pci_parity_count);
+ }
+
+ if (status & (PCI_STATUS_DETECTED_PARITY)) {
+@@ -598,7 +598,7 @@ static void edac_pci_dev_parity_test(str
+ "Detected Parity Error on %s\n",
+ pci_name(dev));
+
+- atomic_inc(&pci_parity_count);
++ atomic_inc_unchecked(&pci_parity_count);
+ }
+ }
+
+@@ -619,7 +619,7 @@ static void edac_pci_dev_parity_test(str
+ edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
+ "Signaled System Error on %s\n",
+ pci_name(dev));
+- atomic_inc(&pci_nonparity_count);
++ atomic_inc_unchecked(&pci_nonparity_count);
+ }
+
+ if (status & (PCI_STATUS_PARITY)) {
+@@ -627,7 +627,7 @@ static void edac_pci_dev_parity_test(str
+ "Master Data Parity Error on "
+ "%s\n", pci_name(dev));
+
+- atomic_inc(&pci_parity_count);
++ atomic_inc_unchecked(&pci_parity_count);
+ }
+
+ if (status & (PCI_STATUS_DETECTED_PARITY)) {
+@@ -635,7 +635,7 @@ static void edac_pci_dev_parity_test(str
+ "Detected Parity Error on %s\n",
+ pci_name(dev));
+
+- atomic_inc(&pci_parity_count);
++ atomic_inc_unchecked(&pci_parity_count);
+ }
+ }
+ }
+@@ -677,7 +677,7 @@ void edac_pci_do_parity_check(void)
+ if (!check_pci_errors)
+ return;
+
+- before_count = atomic_read(&pci_parity_count);
++ before_count = atomic_read_unchecked(&pci_parity_count);
+
+ /* scan all PCI devices looking for a Parity Error on devices and
+ * bridges.
+@@ -689,7 +689,7 @@ void edac_pci_do_parity_check(void)
+ /* Only if operator has selected panic on PCI Error */
+ if (edac_pci_get_panic_on_pe()) {
+ /* If the count is different 'after' from 'before' */
+- if (before_count != atomic_read(&pci_parity_count))
++ if (before_count != atomic_read_unchecked(&pci_parity_count))
+ panic("EDAC: PCI Parity Error");
+ }
+ }
+diff -urNp linux-2.6.38.7/drivers/firewire/core-cdev.c linux-2.6.38.7/drivers/firewire/core-cdev.c
+--- linux-2.6.38.7/drivers/firewire/core-cdev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/firewire/core-cdev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1329,8 +1329,7 @@ static int init_iso_resource(struct clie
+ int ret;
+
+ if ((request->channels == 0 && request->bandwidth == 0) ||
+- request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL ||
+- request->bandwidth < 0)
++ request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL)
+ return -EINVAL;
+
+ r = kmalloc(sizeof(*r), GFP_KERNEL);
+diff -urNp linux-2.6.38.7/drivers/firewire/core-transaction.c linux-2.6.38.7/drivers/firewire/core-transaction.c
+--- linux-2.6.38.7/drivers/firewire/core-transaction.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/firewire/core-transaction.c 2011-05-16 21:47:08.000000000 -0400
+@@ -36,6 +36,7 @@
+ #include <linux/string.h>
+ #include <linux/timer.h>
+ #include <linux/types.h>
++#include <linux/sched.h>
+
+ #include <asm/byteorder.h>
+
+@@ -420,6 +421,8 @@ int fw_run_transaction(struct fw_card *c
+ struct transaction_callback_data d;
+ struct fw_transaction t;
+
++ pax_track_stack();
++
+ init_timer_on_stack(&t.split_timeout_timer);
+ init_completion(&d.done);
+ d.payload = payload;
+diff -urNp linux-2.6.38.7/drivers/firmware/dmi_scan.c linux-2.6.38.7/drivers/firmware/dmi_scan.c
+--- linux-2.6.38.7/drivers/firmware/dmi_scan.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/firmware/dmi_scan.c 2011-04-28 19:34:15.000000000 -0400
+@@ -449,11 +449,6 @@ void __init dmi_scan_machine(void)
+ }
+ }
+ else {
+- /*
+- * no iounmap() for that ioremap(); it would be a no-op, but
+- * it's so early in setup that sucker gets confused into doing
+- * what it shouldn't if we actually call it.
+- */
+ p = dmi_ioremap(0xF0000, 0x10000);
+ if (p == NULL)
+ goto error;
+diff -urNp linux-2.6.38.7/drivers/gpio/vr41xx_giu.c linux-2.6.38.7/drivers/gpio/vr41xx_giu.c
+--- linux-2.6.38.7/drivers/gpio/vr41xx_giu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpio/vr41xx_giu.c 2011-04-28 19:57:25.000000000 -0400
+@@ -204,7 +204,7 @@ static int giu_get_irq(unsigned int irq)
+ printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+ maskl, pendl, maskh, pendh);
+
+- atomic_inc(&irq_err_count);
++ atomic_inc_unchecked(&irq_err_count);
+
+ return -EINVAL;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/drm_crtc_helper.c linux-2.6.38.7/drivers/gpu/drm/drm_crtc_helper.c
+--- linux-2.6.38.7/drivers/gpu/drm/drm_crtc_helper.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/drm_crtc_helper.c 2011-05-16 21:47:08.000000000 -0400
+@@ -276,7 +276,7 @@ static bool drm_encoder_crtc_ok(struct d
+ struct drm_crtc *tmp;
+ int crtc_mask = 1;
+
+- WARN(!crtc, "checking null crtc?\n");
++ BUG_ON(!crtc);
+
+ dev = crtc->dev;
+
+@@ -343,6 +343,8 @@ bool drm_crtc_helper_set_mode(struct drm
+ struct drm_encoder *encoder;
+ bool ret = true;
+
++ pax_track_stack();
++
+ crtc->enabled = drm_helper_crtc_in_use(crtc);
+ if (!crtc->enabled)
+ return true;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/drm_drv.c linux-2.6.38.7/drivers/gpu/drm/drm_drv.c
+--- linux-2.6.38.7/drivers/gpu/drm/drm_drv.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/drm_drv.c 2011-04-28 19:34:15.000000000 -0400
+@@ -425,7 +425,7 @@ long drm_ioctl(struct file *filp,
+
+ dev = file_priv->minor->dev;
+ atomic_inc(&dev->ioctl_count);
+- atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_IOCTLS]);
+ ++file_priv->ioctl_count;
+
+ DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/drm_fops.c linux-2.6.38.7/drivers/gpu/drm/drm_fops.c
+--- linux-2.6.38.7/drivers/gpu/drm/drm_fops.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/drm_fops.c 2011-04-28 19:34:15.000000000 -0400
+@@ -70,7 +70,7 @@ static int drm_setup(struct drm_device *
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
+- atomic_set(&dev->counts[i], 0);
++ atomic_set_unchecked(&dev->counts[i], 0);
+
+ dev->sigdata.lock = NULL;
+
+@@ -134,8 +134,8 @@ int drm_open(struct inode *inode, struct
+
+ retcode = drm_open_helper(inode, filp, dev);
+ if (!retcode) {
+- atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+- if (!dev->open_count++)
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_OPENS]);
++ if (local_inc_return(&dev->open_count) == 1)
+ retcode = drm_setup(dev);
+ }
+ if (!retcode) {
+@@ -472,7 +472,7 @@ int drm_release(struct inode *inode, str
+
+ mutex_lock(&drm_global_mutex);
+
+- DRM_DEBUG("open_count = %d\n", dev->open_count);
++ DRM_DEBUG("open_count = %d\n", local_read(&dev->open_count));
+
+ if (dev->driver->preclose)
+ dev->driver->preclose(dev, file_priv);
+@@ -484,7 +484,7 @@ int drm_release(struct inode *inode, str
+ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+ task_pid_nr(current),
+ (long)old_encode_dev(file_priv->minor->device),
+- dev->open_count);
++ local_read(&dev->open_count));
+
+ /* if the master has gone away we can't do anything with the lock */
+ if (file_priv->minor->master)
+@@ -565,8 +565,8 @@ int drm_release(struct inode *inode, str
+ * End inline drm_release
+ */
+
+- atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
+- if (!--dev->open_count) {
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_CLOSES]);
++ if (local_dec_and_test(&dev->open_count)) {
+ if (atomic_read(&dev->ioctl_count)) {
+ DRM_ERROR("Device busy: %d\n",
+ atomic_read(&dev->ioctl_count));
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/drm_global.c linux-2.6.38.7/drivers/gpu/drm/drm_global.c
+--- linux-2.6.38.7/drivers/gpu/drm/drm_global.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/drm_global.c 2011-04-28 19:34:15.000000000 -0400
+@@ -36,7 +36,7 @@
+ struct drm_global_item {
+ struct mutex mutex;
+ void *object;
+- int refcount;
++ atomic_t refcount;
+ };
+
+ static struct drm_global_item glob[DRM_GLOBAL_NUM];
+@@ -49,7 +49,7 @@ void drm_global_init(void)
+ struct drm_global_item *item = &glob[i];
+ mutex_init(&item->mutex);
+ item->object = NULL;
+- item->refcount = 0;
++ atomic_set(&item->refcount, 0);
+ }
+ }
+
+@@ -59,7 +59,7 @@ void drm_global_release(void)
+ for (i = 0; i < DRM_GLOBAL_NUM; ++i) {
+ struct drm_global_item *item = &glob[i];
+ BUG_ON(item->object != NULL);
+- BUG_ON(item->refcount != 0);
++ BUG_ON(atomic_read(&item->refcount) != 0);
+ }
+ }
+
+@@ -70,7 +70,7 @@ int drm_global_item_ref(struct drm_globa
+ void *object;
+
+ mutex_lock(&item->mutex);
+- if (item->refcount == 0) {
++ if (atomic_read(&item->refcount) == 0) {
+ item->object = kzalloc(ref->size, GFP_KERNEL);
+ if (unlikely(item->object == NULL)) {
+ ret = -ENOMEM;
+@@ -83,7 +83,7 @@ int drm_global_item_ref(struct drm_globa
+ goto out_err;
+
+ }
+- ++item->refcount;
++ atomic_inc(&item->refcount);
+ ref->object = item->object;
+ object = item->object;
+ mutex_unlock(&item->mutex);
+@@ -100,9 +100,9 @@ void drm_global_item_unref(struct drm_gl
+ struct drm_global_item *item = &glob[ref->global_type];
+
+ mutex_lock(&item->mutex);
+- BUG_ON(item->refcount == 0);
++ BUG_ON(atomic_read(&item->refcount) == 0);
+ BUG_ON(ref->object != item->object);
+- if (--item->refcount == 0) {
++ if (atomic_dec_and_test(&item->refcount)) {
+ ref->release(ref);
+ item->object = NULL;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/drm_info.c linux-2.6.38.7/drivers/gpu/drm/drm_info.c
+--- linux-2.6.38.7/drivers/gpu/drm/drm_info.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/drm_info.c 2011-04-28 19:34:15.000000000 -0400
+@@ -86,10 +86,14 @@ int drm_vm_info(struct seq_file *m, void
+ struct drm_local_map *map;
+ struct drm_map_list *r_list;
+
+- /* Hardcoded from _DRM_FRAME_BUFFER,
+- _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
+- _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
+- const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
++ static const char * const types[] = {
++ [_DRM_FRAME_BUFFER] = "FB",
++ [_DRM_REGISTERS] = "REG",
++ [_DRM_SHM] = "SHM",
++ [_DRM_AGP] = "AGP",
++ [_DRM_SCATTER_GATHER] = "SG",
++ [_DRM_CONSISTENT] = "PCI",
++ [_DRM_GEM] = "GEM" };
+ const char *type;
+ int i;
+
+@@ -100,7 +104,7 @@ int drm_vm_info(struct seq_file *m, void
+ map = r_list->map;
+ if (!map)
+ continue;
+- if (map->type < 0 || map->type > 5)
++ if (map->type >= ARRAY_SIZE(types))
+ type = "??";
+ else
+ type = types[map->type];
+@@ -301,7 +305,11 @@ int drm_vma_info(struct seq_file *m, voi
+ vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
+ vma->vm_flags & VM_LOCKED ? 'l' : '-',
+ vma->vm_flags & VM_IO ? 'i' : '-',
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ 0);
++#else
+ vma->vm_pgoff);
++#endif
+
+ #if defined(__i386__)
+ pgprot = pgprot_val(vma->vm_page_prot);
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/drm_ioctl.c linux-2.6.38.7/drivers/gpu/drm/drm_ioctl.c
+--- linux-2.6.38.7/drivers/gpu/drm/drm_ioctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/drm_ioctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -353,7 +353,7 @@ int drm_getstats(struct drm_device *dev,
+ stats->data[i].value =
+ (file_priv->master->lock.hw_lock ? file_priv->master->lock.hw_lock->lock : 0);
+ else
+- stats->data[i].value = atomic_read(&dev->counts[i]);
++ stats->data[i].value = atomic_read_unchecked(&dev->counts[i]);
+ stats->data[i].type = dev->types[i];
+ }
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/drm_lock.c linux-2.6.38.7/drivers/gpu/drm/drm_lock.c
+--- linux-2.6.38.7/drivers/gpu/drm/drm_lock.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/drm_lock.c 2011-04-28 19:34:15.000000000 -0400
+@@ -89,7 +89,7 @@ int drm_lock(struct drm_device *dev, voi
+ if (drm_lock_take(&master->lock, lock->context)) {
+ master->lock.file_priv = file_priv;
+ master->lock.lock_time = jiffies;
+- atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_LOCKS]);
+ break; /* Got lock */
+ }
+
+@@ -160,7 +160,7 @@ int drm_unlock(struct drm_device *dev, v
+ return -EINVAL;
+ }
+
+- atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_UNLOCKS]);
+
+ if (drm_lock_free(&master->lock, lock->context)) {
+ /* FIXME: Should really bail out here. */
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i810/i810_dma.c linux-2.6.38.7/drivers/gpu/drm/i810/i810_dma.c
+--- linux-2.6.38.7/drivers/gpu/drm/i810/i810_dma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i810/i810_dma.c 2011-04-28 19:34:15.000000000 -0400
+@@ -953,8 +953,8 @@ static int i810_dma_vertex(struct drm_de
+ dma->buflist[vertex->idx],
+ vertex->discard, vertex->used);
+
+- atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]);
+- atomic_inc(&dev->counts[_DRM_STAT_DMA]);
++ atomic_add_unchecked(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_DMA]);
+ sarea_priv->last_enqueue = dev_priv->counter - 1;
+ sarea_priv->last_dispatch = (int)hw_status[5];
+
+@@ -1114,8 +1114,8 @@ static int i810_dma_mc(struct drm_device
+ i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used,
+ mc->last_render);
+
+- atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]);
+- atomic_inc(&dev->counts[_DRM_STAT_DMA]);
++ atomic_add_unchecked(mc->used, &dev->counts[_DRM_STAT_SECONDARY]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_DMA]);
+ sarea_priv->last_enqueue = dev_priv->counter - 1;
+ sarea_priv->last_dispatch = (int)hw_status[5];
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i810/i810_drv.h linux-2.6.38.7/drivers/gpu/drm/i810/i810_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/i810/i810_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i810/i810_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -108,8 +108,8 @@ typedef struct drm_i810_private {
+ int page_flipping;
+
+ wait_queue_head_t irq_queue;
+- atomic_t irq_received;
+- atomic_t irq_emitted;
++ atomic_unchecked_t irq_received;
++ atomic_unchecked_t irq_emitted;
+
+ int front_offset;
+ } drm_i810_private_t;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i830/i830_drv.h linux-2.6.38.7/drivers/gpu/drm/i830/i830_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/i830/i830_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i830/i830_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -115,8 +115,8 @@ typedef struct drm_i830_private {
+ int page_flipping;
+
+ wait_queue_head_t irq_queue;
+- atomic_t irq_received;
+- atomic_t irq_emitted;
++ atomic_unchecked_t irq_received;
++ atomic_unchecked_t irq_emitted;
+
+ int use_mi_batchbuffer_start;
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i830/i830_irq.c linux-2.6.38.7/drivers/gpu/drm/i830/i830_irq.c
+--- linux-2.6.38.7/drivers/gpu/drm/i830/i830_irq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i830/i830_irq.c 2011-04-28 19:57:25.000000000 -0400
+@@ -47,7 +47,7 @@ irqreturn_t i830_driver_irq_handler(DRM_
+
+ I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
+
+- atomic_inc(&dev_priv->irq_received);
++ atomic_inc_unchecked(&dev_priv->irq_received);
+ wake_up_interruptible(&dev_priv->irq_queue);
+
+ return IRQ_HANDLED;
+@@ -60,14 +60,14 @@ static int i830_emit_irq(struct drm_devi
+
+ DRM_DEBUG("%s\n", __func__);
+
+- atomic_inc(&dev_priv->irq_emitted);
++ atomic_inc_unchecked(&dev_priv->irq_emitted);
+
+ BEGIN_LP_RING(2);
+ OUT_RING(0);
+ OUT_RING(GFX_OP_USER_INTERRUPT);
+ ADVANCE_LP_RING();
+
+- return atomic_read(&dev_priv->irq_emitted);
++ return atomic_read_unchecked(&dev_priv->irq_emitted);
+ }
+
+ static int i830_wait_irq(struct drm_device *dev, int irq_nr)
+@@ -79,7 +79,7 @@ static int i830_wait_irq(struct drm_devi
+
+ DRM_DEBUG("%s\n", __func__);
+
+- if (atomic_read(&dev_priv->irq_received) >= irq_nr)
++ if (atomic_read_unchecked(&dev_priv->irq_received) >= irq_nr)
+ return 0;
+
+ dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
+@@ -88,7 +88,7 @@ static int i830_wait_irq(struct drm_devi
+
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+- if (atomic_read(&dev_priv->irq_received) >= irq_nr)
++ if (atomic_read_unchecked(&dev_priv->irq_received) >= irq_nr)
+ break;
+ if ((signed)(end - jiffies) <= 0) {
+ DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
+@@ -163,8 +163,8 @@ void i830_driver_irq_preinstall(struct d
+ I830_WRITE16(I830REG_HWSTAM, 0xffff);
+ I830_WRITE16(I830REG_INT_MASK_R, 0x0);
+ I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
+- atomic_set(&dev_priv->irq_received, 0);
+- atomic_set(&dev_priv->irq_emitted, 0);
++ atomic_set_unchecked(&dev_priv->irq_received, 0);
++ atomic_set_unchecked(&dev_priv->irq_emitted, 0);
+ init_waitqueue_head(&dev_priv->irq_queue);
+ }
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ch7017.c linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ch7017.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ch7017.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ch7017.c 2011-04-28 19:34:15.000000000 -0400
+@@ -390,7 +390,7 @@ static void ch7017_destroy(struct intel_
+ }
+ }
+
+-struct intel_dvo_dev_ops ch7017_ops = {
++const struct intel_dvo_dev_ops ch7017_ops = {
+ .init = ch7017_init,
+ .detect = ch7017_detect,
+ .mode_valid = ch7017_mode_valid,
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ch7xxx.c linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ch7xxx.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ch7xxx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ch7xxx.c 2011-04-28 19:34:15.000000000 -0400
+@@ -320,7 +320,7 @@ static void ch7xxx_destroy(struct intel_
+ }
+ }
+
+-struct intel_dvo_dev_ops ch7xxx_ops = {
++const struct intel_dvo_dev_ops ch7xxx_ops = {
+ .init = ch7xxx_init,
+ .detect = ch7xxx_detect,
+ .mode_valid = ch7xxx_mode_valid,
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/dvo.h linux-2.6.38.7/drivers/gpu/drm/i915/dvo.h
+--- linux-2.6.38.7/drivers/gpu/drm/i915/dvo.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/dvo.h 2011-04-28 19:34:15.000000000 -0400
+@@ -122,23 +122,23 @@ struct intel_dvo_dev_ops {
+ *
+ * \return singly-linked list of modes or NULL if no modes found.
+ */
+- struct drm_display_mode *(*get_modes)(struct intel_dvo_device *dvo);
++ struct drm_display_mode *(* const get_modes)(struct intel_dvo_device *dvo);
+
+ /**
+ * Clean up driver-specific bits of the output
+ */
+- void (*destroy) (struct intel_dvo_device *dvo);
++ void (* const destroy) (struct intel_dvo_device *dvo);
+
+ /**
+ * Debugging hook to dump device registers to log file
+ */
+- void (*dump_regs)(struct intel_dvo_device *dvo);
++ void (* const dump_regs)(struct intel_dvo_device *dvo);
+ };
+
+-extern struct intel_dvo_dev_ops sil164_ops;
+-extern struct intel_dvo_dev_ops ch7xxx_ops;
+-extern struct intel_dvo_dev_ops ivch_ops;
+-extern struct intel_dvo_dev_ops tfp410_ops;
+-extern struct intel_dvo_dev_ops ch7017_ops;
++extern const struct intel_dvo_dev_ops sil164_ops;
++extern const struct intel_dvo_dev_ops ch7xxx_ops;
++extern const struct intel_dvo_dev_ops ivch_ops;
++extern const struct intel_dvo_dev_ops tfp410_ops;
++extern const struct intel_dvo_dev_ops ch7017_ops;
+
+ #endif /* _INTEL_DVO_H */
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ivch.c linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ivch.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ivch.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/dvo_ivch.c 2011-04-28 19:34:15.000000000 -0400
+@@ -410,7 +410,7 @@ static void ivch_destroy(struct intel_dv
+ }
+ }
+
+-struct intel_dvo_dev_ops ivch_ops= {
++const struct intel_dvo_dev_ops ivch_ops= {
+ .init = ivch_init,
+ .dpms = ivch_dpms,
+ .mode_valid = ivch_mode_valid,
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/dvo_sil164.c linux-2.6.38.7/drivers/gpu/drm/i915/dvo_sil164.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/dvo_sil164.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/dvo_sil164.c 2011-04-28 19:34:15.000000000 -0400
+@@ -252,7 +252,7 @@ static void sil164_destroy(struct intel_
+ }
+ }
+
+-struct intel_dvo_dev_ops sil164_ops = {
++const struct intel_dvo_dev_ops sil164_ops = {
+ .init = sil164_init,
+ .detect = sil164_detect,
+ .mode_valid = sil164_mode_valid,
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/dvo_tfp410.c linux-2.6.38.7/drivers/gpu/drm/i915/dvo_tfp410.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/dvo_tfp410.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/dvo_tfp410.c 2011-04-28 19:34:15.000000000 -0400
+@@ -293,7 +293,7 @@ static void tfp410_destroy(struct intel_
+ }
+ }
+
+-struct intel_dvo_dev_ops tfp410_ops = {
++const struct intel_dvo_dev_ops tfp410_ops = {
+ .init = tfp410_init,
+ .detect = tfp410_detect,
+ .mode_valid = tfp410_mode_valid,
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/i915_debugfs.c linux-2.6.38.7/drivers/gpu/drm/i915/i915_debugfs.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/i915_debugfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/i915_debugfs.c 2011-04-28 19:57:25.000000000 -0400
+@@ -496,7 +496,7 @@ static int i915_interrupt_info(struct se
+ I915_READ(GTIMR));
+ }
+ seq_printf(m, "Interrupts received: %d\n",
+- atomic_read(&dev_priv->irq_received));
++ atomic_read_unchecked(&dev_priv->irq_received));
+ for (i = 0; i < I915_NUM_RINGS; i++) {
+ if (IS_GEN6(dev)) {
+ seq_printf(m, "Graphics Interrupt mask (%s): %08x\n",
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/i915_dma.c linux-2.6.38.7/drivers/gpu/drm/i915/i915_dma.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/i915_dma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/i915_dma.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1159,7 +1159,7 @@ static bool i915_switcheroo_can_switch(s
+ bool can_switch;
+
+ spin_lock(&dev->count_lock);
+- can_switch = (dev->open_count == 0);
++ can_switch = (local_read(&dev->open_count) == 0);
+ spin_unlock(&dev->count_lock);
+ return can_switch;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/i915_drv.c linux-2.6.38.7/drivers/gpu/drm/i915/i915_drv.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/i915_drv.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/i915_drv.c 2011-04-28 19:34:15.000000000 -0400
+@@ -673,7 +673,7 @@ static const struct dev_pm_ops i915_pm_o
+ .restore = i915_pm_resume,
+ };
+
+-static struct vm_operations_struct i915_gem_vm_ops = {
++static const struct vm_operations_struct i915_gem_vm_ops = {
+ .fault = i915_gem_fault,
+ .open = drm_gem_vm_open,
+ .close = drm_gem_vm_close,
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/i915_drv.h linux-2.6.38.7/drivers/gpu/drm/i915/i915_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/i915/i915_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/i915_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -288,7 +288,7 @@ typedef struct drm_i915_private {
+ int current_page;
+ int page_flipping;
+
+- atomic_t irq_received;
++ atomic_unchecked_t irq_received;
+ u32 trace_irq_seqno;
+
+ /* protects the irq masks */
+@@ -843,7 +843,7 @@ struct drm_i915_gem_object {
+ * will be page flipped away on the next vblank. When it
+ * reaches 0, dev_priv->pending_flip_queue will be woken up.
+ */
+- atomic_t pending_flip;
++ atomic_unchecked_t pending_flip;
+ };
+
+ #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
+@@ -1229,7 +1229,7 @@ extern int intel_setup_gmbus(struct drm_
+ extern void intel_teardown_gmbus(struct drm_device *dev);
+ extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
+ extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
+-extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
++static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
+ {
+ return container_of(adapter, struct intel_gmbus, adapter)->force_bit;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-2.6.38.7/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2011-04-28 19:57:25.000000000 -0400
+@@ -904,7 +904,7 @@ i915_gem_execbuffer_wait_for_flips(struc
+ flips = 0;
+ list_for_each_entry(obj, objects, exec_list) {
+ if (obj->base.write_domain)
+- flips |= atomic_read(&obj->pending_flip);
++ flips |= atomic_read_unchecked(&obj->pending_flip);
+ }
+ if (flips) {
+ int plane, flip_mask, ret;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/i915_irq.c linux-2.6.38.7/drivers/gpu/drm/i915/i915_irq.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/i915_irq.c 2011-04-18 17:27:13.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/i915_irq.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1106,7 +1106,7 @@ irqreturn_t i915_driver_irq_handler(DRM_
+ int irq_received;
+ int ret = IRQ_NONE;
+
+- atomic_inc(&dev_priv->irq_received);
++ atomic_inc_unchecked(&dev_priv->irq_received);
+
+ if (HAS_PCH_SPLIT(dev))
+ return ironlake_irq_handler(dev);
+@@ -1684,7 +1684,7 @@ void i915_driver_irq_preinstall(struct d
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+- atomic_set(&dev_priv->irq_received, 0);
++ atomic_set_unchecked(&dev_priv->irq_received, 0);
+
+ INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+ INIT_WORK(&dev_priv->error_work, i915_error_work_func);
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/i915/intel_display.c linux-2.6.38.7/drivers/gpu/drm/i915/intel_display.c
+--- linux-2.6.38.7/drivers/gpu/drm/i915/intel_display.c 2011-05-22 23:05:18.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/i915/intel_display.c 2011-05-22 23:06:03.000000000 -0400
+@@ -1631,7 +1631,7 @@ intel_pipe_set_base(struct drm_crtc *crt
+
+ wait_event(dev_priv->pending_flip_queue,
+ atomic_read(&dev_priv->mm.wedged) ||
+- atomic_read(&obj->pending_flip) == 0);
++ atomic_read_unchecked(&obj->pending_flip) == 0);
+
+ /* Big Hammer, we also need to ensure that any pending
+ * MI_WAIT_FOR_EVENT inside a user batch buffer on the
+@@ -2042,7 +2042,7 @@ static void intel_crtc_wait_for_pending_
+ obj = to_intel_framebuffer(crtc->fb)->obj;
+ dev_priv = crtc->dev->dev_private;
+ wait_event(dev_priv->pending_flip_queue,
+- atomic_read(&obj->pending_flip) == 0);
++ atomic_read_unchecked(&obj->pending_flip) == 0);
+ }
+
+ static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
+@@ -5428,7 +5428,7 @@ static void do_intel_finish_page_flip(st
+
+ atomic_clear_mask(1 << intel_crtc->plane,
+ &obj->pending_flip.counter);
+- if (atomic_read(&obj->pending_flip) == 0)
++ if (atomic_read_unchecked(&obj->pending_flip) == 0)
+ wake_up(&dev_priv->pending_flip_queue);
+
+ schedule_work(&work->work);
+@@ -5557,7 +5557,7 @@ static int intel_crtc_page_flip(struct d
+ /* Block clients from rendering to the new back buffer until
+ * the flip occurs and the object is no longer visible.
+ */
+- atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
++ atomic_add_unchecked(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
+
+ switch (INTEL_INFO(dev)->gen) {
+ case 2:
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/mga/mga_drv.h linux-2.6.38.7/drivers/gpu/drm/mga/mga_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/mga/mga_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/mga/mga_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -120,9 +120,9 @@ typedef struct drm_mga_private {
+ u32 clear_cmd;
+ u32 maccess;
+
+- atomic_t vbl_received; /**< Number of vblanks received. */
++ atomic_unchecked_t vbl_received; /**< Number of vblanks received. */
+ wait_queue_head_t fence_queue;
+- atomic_t last_fence_retired;
++ atomic_unchecked_t last_fence_retired;
+ u32 next_fence_to_post;
+
+ unsigned int fb_cpp;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/mga/mga_irq.c linux-2.6.38.7/drivers/gpu/drm/mga/mga_irq.c
+--- linux-2.6.38.7/drivers/gpu/drm/mga/mga_irq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/mga/mga_irq.c 2011-04-28 19:57:25.000000000 -0400
+@@ -44,7 +44,7 @@ u32 mga_get_vblank_counter(struct drm_de
+ if (crtc != 0)
+ return 0;
+
+- return atomic_read(&dev_priv->vbl_received);
++ return atomic_read_unchecked(&dev_priv->vbl_received);
+ }
+
+
+@@ -60,7 +60,7 @@ irqreturn_t mga_driver_irq_handler(DRM_I
+ /* VBLANK interrupt */
+ if (status & MGA_VLINEPEN) {
+ MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
+- atomic_inc(&dev_priv->vbl_received);
++ atomic_inc_unchecked(&dev_priv->vbl_received);
+ drm_handle_vblank(dev, 0);
+ handled = 1;
+ }
+@@ -79,7 +79,7 @@ irqreturn_t mga_driver_irq_handler(DRM_I
+ if ((prim_start & ~0x03) != (prim_end & ~0x03))
+ MGA_WRITE(MGA_PRIMEND, prim_end);
+
+- atomic_inc(&dev_priv->last_fence_retired);
++ atomic_inc_unchecked(&dev_priv->last_fence_retired);
+ DRM_WAKEUP(&dev_priv->fence_queue);
+ handled = 1;
+ }
+@@ -130,7 +130,7 @@ int mga_driver_fence_wait(struct drm_dev
+ * using fences.
+ */
+ DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
+- (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
++ (((cur_fence = atomic_read_unchecked(&dev_priv->last_fence_retired))
+ - *sequence) <= (1 << 23)));
+
+ *sequence = cur_fence;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_drv.h linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -226,7 +226,7 @@ struct nouveau_channel {
+ struct list_head pending;
+ uint32_t sequence;
+ uint32_t sequence_ack;
+- atomic_t last_sequence_irq;
++ atomic_unchecked_t last_sequence_irq;
+ } fence;
+
+ /* DMA push buffer */
+@@ -661,7 +661,7 @@ struct drm_nouveau_private {
+ struct drm_global_reference mem_global_ref;
+ struct ttm_bo_global_ref bo_global_ref;
+ struct ttm_bo_device bdev;
+- atomic_t validate_sequence;
++ atomic_unchecked_t validate_sequence;
+ } ttm;
+
+ struct {
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_fence.c linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_fence.c
+--- linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-04-28 19:57:25.000000000 -0400
+@@ -83,7 +83,7 @@ nouveau_fence_update(struct nouveau_chan
+ if (USE_REFCNT(dev))
+ sequence = nvchan_rd32(chan, 0x48);
+ else
+- sequence = atomic_read(&chan->fence.last_sequence_irq);
++ sequence = atomic_read_unchecked(&chan->fence.last_sequence_irq);
+
+ if (chan->fence.sequence_ack == sequence)
+ goto out;
+@@ -490,7 +490,7 @@ nouveau_fence_channel_init(struct nouvea
+
+ INIT_LIST_HEAD(&chan->fence.pending);
+ spin_lock_init(&chan->fence.lock);
+- atomic_set(&chan->fence.last_sequence_irq, 0);
++ atomic_set_unchecked(&chan->fence.last_sequence_irq, 0);
+
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_gem.c linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_gem.c
+--- linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-04-28 19:57:25.000000000 -0400
+@@ -241,7 +241,7 @@ validate_init(struct nouveau_channel *ch
+ int trycnt = 0;
+ int ret, i;
+
+- sequence = atomic_add_return(1, &dev_priv->ttm.validate_sequence);
++ sequence = atomic_add_return_unchecked(1, &dev_priv->ttm.validate_sequence);
+ retry:
+ if (++trycnt > 100000) {
+ NV_ERROR(dev, "%s failed and gave up.\n", __func__);
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_state.c linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_state.c
+--- linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_state.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/nouveau/nouveau_state.c 2011-04-28 19:34:15.000000000 -0400
+@@ -621,7 +621,7 @@ static bool nouveau_switcheroo_can_switc
+ bool can_switch;
+
+ spin_lock(&dev->count_lock);
+- can_switch = (dev->open_count == 0);
++ can_switch = (local_read(&dev->open_count) == 0);
+ spin_unlock(&dev->count_lock);
+ return can_switch;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/nouveau/nv04_graph.c linux-2.6.38.7/drivers/gpu/drm/nouveau/nv04_graph.c
+--- linux-2.6.38.7/drivers/gpu/drm/nouveau/nv04_graph.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/nouveau/nv04_graph.c 2011-04-28 19:57:25.000000000 -0400
+@@ -552,7 +552,7 @@ static int
+ nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
+ u32 class, u32 mthd, u32 data)
+ {
+- atomic_set(&chan->fence.last_sequence_irq, data);
++ atomic_set_unchecked(&chan->fence.last_sequence_irq, data);
+ return 0;
+ }
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/r128/r128_cce.c linux-2.6.38.7/drivers/gpu/drm/r128/r128_cce.c
+--- linux-2.6.38.7/drivers/gpu/drm/r128/r128_cce.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/r128/r128_cce.c 2011-04-28 19:57:25.000000000 -0400
+@@ -377,7 +377,7 @@ static int r128_do_init_cce(struct drm_d
+
+ /* GH: Simple idle check.
+ */
+- atomic_set(&dev_priv->idle_count, 0);
++ atomic_set_unchecked(&dev_priv->idle_count, 0);
+
+ /* We don't support anything other than bus-mastering ring mode,
+ * but the ring can be in either AGP or PCI space for the ring
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/r128/r128_drv.h linux-2.6.38.7/drivers/gpu/drm/r128/r128_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/r128/r128_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/r128/r128_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -90,14 +90,14 @@ typedef struct drm_r128_private {
+ int is_pci;
+ unsigned long cce_buffers_offset;
+
+- atomic_t idle_count;
++ atomic_unchecked_t idle_count;
+
+ int page_flipping;
+ int current_page;
+ u32 crtc_offset;
+ u32 crtc_offset_cntl;
+
+- atomic_t vbl_received;
++ atomic_unchecked_t vbl_received;
+
+ u32 color_fmt;
+ unsigned int front_offset;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/r128/r128_irq.c linux-2.6.38.7/drivers/gpu/drm/r128/r128_irq.c
+--- linux-2.6.38.7/drivers/gpu/drm/r128/r128_irq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/r128/r128_irq.c 2011-04-28 19:57:25.000000000 -0400
+@@ -42,7 +42,7 @@ u32 r128_get_vblank_counter(struct drm_d
+ if (crtc != 0)
+ return 0;
+
+- return atomic_read(&dev_priv->vbl_received);
++ return atomic_read_unchecked(&dev_priv->vbl_received);
+ }
+
+ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+@@ -56,7 +56,7 @@ irqreturn_t r128_driver_irq_handler(DRM_
+ /* VBLANK interrupt */
+ if (status & R128_CRTC_VBLANK_INT) {
+ R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+- atomic_inc(&dev_priv->vbl_received);
++ atomic_inc_unchecked(&dev_priv->vbl_received);
+ drm_handle_vblank(dev, 0);
+ return IRQ_HANDLED;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/r128/r128_state.c linux-2.6.38.7/drivers/gpu/drm/r128/r128_state.c
+--- linux-2.6.38.7/drivers/gpu/drm/r128/r128_state.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/r128/r128_state.c 2011-04-28 19:57:25.000000000 -0400
+@@ -321,10 +321,10 @@ static void r128_clear_box(drm_r128_priv
+
+ static void r128_cce_performance_boxes(drm_r128_private_t *dev_priv)
+ {
+- if (atomic_read(&dev_priv->idle_count) == 0)
++ if (atomic_read_unchecked(&dev_priv->idle_count) == 0)
+ r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
+ else
+- atomic_set(&dev_priv->idle_count, 0);
++ atomic_set_unchecked(&dev_priv->idle_count, 0);
+ }
+
+ #endif
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/atom.c linux-2.6.38.7/drivers/gpu/drm/radeon/atom.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/atom.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/atom.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1245,6 +1245,8 @@ struct atom_context *atom_parse(struct c
+ char name[512];
+ int i;
+
++ pax_track_stack();
++
+ ctx->card = card;
+ ctx->bios = bios;
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/mkregtable.c linux-2.6.38.7/drivers/gpu/drm/radeon/mkregtable.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/mkregtable.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/mkregtable.c 2011-04-28 19:34:15.000000000 -0400
+@@ -637,14 +637,14 @@ static int parser_auth(struct table *t,
+ regex_t mask_rex;
+ regmatch_t match[4];
+ char buf[1024];
+- size_t end;
++ long end;
+ int len;
+ int done = 0;
+ int r;
+ unsigned o;
+ struct offset *offset;
+ char last_reg_s[10];
+- int last_reg;
++ unsigned long last_reg;
+
+ if (regcomp
+ (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) {
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_atombios.c linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_atombios.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_atombios.c 2011-05-22 23:05:18.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_atombios.c 2011-05-22 23:06:03.000000000 -0400
+@@ -545,6 +545,8 @@ bool radeon_get_atom_connector_info_from
+ struct radeon_gpio_rec gpio;
+ struct radeon_hpd hpd;
+
++ pax_track_stack();
++
+ if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
+ return false;
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_device.c linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_device.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_device.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_device.c 2011-04-28 19:34:15.000000000 -0400
+@@ -673,7 +673,7 @@ static bool radeon_switcheroo_can_switch
+ bool can_switch;
+
+ spin_lock(&dev->count_lock);
+- can_switch = (dev->open_count == 0);
++ can_switch = (local_read(&dev->open_count) == 0);
+ spin_unlock(&dev->count_lock);
+ return can_switch;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_display.c linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_display.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_display.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_display.c 2011-05-16 21:47:08.000000000 -0400
+@@ -934,6 +934,8 @@ void radeon_compute_pll_legacy(struct ra
+ uint32_t post_div;
+ u32 pll_out_min, pll_out_max;
+
++ pax_track_stack();
++
+ DRM_DEBUG_KMS("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
+ freq = freq * 1000;
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_drv.h linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -255,7 +255,7 @@ typedef struct drm_radeon_private {
+
+ /* SW interrupt */
+ wait_queue_head_t swi_queue;
+- atomic_t swi_emitted;
++ atomic_unchecked_t swi_emitted;
+ int vblank_crtc;
+ uint32_t irq_enable_reg;
+ uint32_t r500_disp_irq_reg;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_fence.c linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_fence.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_fence.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_fence.c 2011-04-28 19:57:25.000000000 -0400
+@@ -49,7 +49,7 @@ int radeon_fence_emit(struct radeon_devi
+ write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+ return 0;
+ }
+- fence->seq = atomic_add_return(1, &rdev->fence_drv.seq);
++ fence->seq = atomic_add_return_unchecked(1, &rdev->fence_drv.seq);
+ if (!rdev->cp.ready) {
+ /* FIXME: cp is not running assume everythings is done right
+ * away
+@@ -354,7 +354,7 @@ int radeon_fence_driver_init(struct rade
+ return r;
+ }
+ WREG32(rdev->fence_drv.scratch_reg, 0);
+- atomic_set(&rdev->fence_drv.seq, 0);
++ atomic_set_unchecked(&rdev->fence_drv.seq, 0);
+ INIT_LIST_HEAD(&rdev->fence_drv.created);
+ INIT_LIST_HEAD(&rdev->fence_drv.emited);
+ INIT_LIST_HEAD(&rdev->fence_drv.signaled);
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon.h linux-2.6.38.7/drivers/gpu/drm/radeon/radeon.h
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon.h 2011-04-28 19:57:25.000000000 -0400
+@@ -189,7 +189,7 @@ extern int sumo_get_temp(struct radeon_d
+ */
+ struct radeon_fence_driver {
+ uint32_t scratch_reg;
+- atomic_t seq;
++ atomic_unchecked_t seq;
+ uint32_t last_seq;
+ unsigned long last_jiffies;
+ unsigned long last_timeout;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_ioc32.c linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_ioc32.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_ioc32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_ioc32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -359,7 +359,7 @@ static int compat_radeon_cp_setparam(str
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.param, &request->param)
+- || __put_user((void __user *)(unsigned long)req32.value,
++ || __put_user((unsigned long)req32.value,
+ &request->value))
+ return -EFAULT;
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_irq.c linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_irq.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_irq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_irq.c 2011-04-28 19:57:25.000000000 -0400
+@@ -225,8 +225,8 @@ static int radeon_emit_irq(struct drm_de
+ unsigned int ret;
+ RING_LOCALS;
+
+- atomic_inc(&dev_priv->swi_emitted);
+- ret = atomic_read(&dev_priv->swi_emitted);
++ atomic_inc_unchecked(&dev_priv->swi_emitted);
++ ret = atomic_read_unchecked(&dev_priv->swi_emitted);
+
+ BEGIN_RING(4);
+ OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
+@@ -352,7 +352,7 @@ int radeon_driver_irq_postinstall(struct
+ drm_radeon_private_t *dev_priv =
+ (drm_radeon_private_t *) dev->dev_private;
+
+- atomic_set(&dev_priv->swi_emitted, 0);
++ atomic_set_unchecked(&dev_priv->swi_emitted, 0);
+ DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+
+ dev->max_vblank_count = 0x001fffff;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_state.c linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_state.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_state.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_state.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2168,7 +2168,7 @@ static int radeon_cp_clear(struct drm_de
+ if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+ sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+- if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes,
++ if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS || DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes,
+ sarea_priv->nbox * sizeof(depth_boxes[0])))
+ return -EFAULT;
+
+@@ -3031,7 +3031,7 @@ static int radeon_cp_getparam(struct drm
+ {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_getparam_t *param = data;
+- int value;
++ int value = 0;
+
+ DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_ttm.c linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_ttm.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_ttm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/radeon_ttm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -603,8 +603,9 @@ void radeon_ttm_set_active_vram_size(str
+ man->size = size >> PAGE_SHIFT;
+ }
+
+-static struct vm_operations_struct radeon_ttm_vm_ops;
+-static const struct vm_operations_struct *ttm_vm_ops = NULL;
++extern int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
++extern void ttm_bo_vm_open(struct vm_area_struct *vma);
++extern void ttm_bo_vm_close(struct vm_area_struct *vma);
+
+ static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+@@ -612,17 +613,22 @@ static int radeon_ttm_fault(struct vm_ar
+ struct radeon_device *rdev;
+ int r;
+
+- bo = (struct ttm_buffer_object *)vma->vm_private_data;
+- if (bo == NULL) {
++ bo = (struct ttm_buffer_object *)vma->vm_private_data;
++ if (!bo)
+ return VM_FAULT_NOPAGE;
+- }
+ rdev = radeon_get_rdev(bo->bdev);
+ mutex_lock(&rdev->vram_mutex);
+- r = ttm_vm_ops->fault(vma, vmf);
++ r = ttm_bo_vm_fault(vma, vmf);
+ mutex_unlock(&rdev->vram_mutex);
+ return r;
+ }
+
++static const struct vm_operations_struct radeon_ttm_vm_ops = {
++ .fault = radeon_ttm_fault,
++ .open = ttm_bo_vm_open,
++ .close = ttm_bo_vm_close
++};
++
+ int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+ struct drm_file *file_priv;
+@@ -635,18 +641,11 @@ int radeon_mmap(struct file *filp, struc
+
+ file_priv = filp->private_data;
+ rdev = file_priv->minor->dev->dev_private;
+- if (rdev == NULL) {
++ if (!rdev)
+ return -EINVAL;
+- }
+ r = ttm_bo_mmap(filp, vma, &rdev->mman.bdev);
+- if (unlikely(r != 0)) {
++ if (r)
+ return r;
+- }
+- if (unlikely(ttm_vm_ops == NULL)) {
+- ttm_vm_ops = vma->vm_ops;
+- radeon_ttm_vm_ops = *ttm_vm_ops;
+- radeon_ttm_vm_ops.fault = &radeon_ttm_fault;
+- }
+ vma->vm_ops = &radeon_ttm_vm_ops;
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/radeon/rs690.c linux-2.6.38.7/drivers/gpu/drm/radeon/rs690.c
+--- linux-2.6.38.7/drivers/gpu/drm/radeon/rs690.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/radeon/rs690.c 2011-04-28 19:34:15.000000000 -0400
+@@ -304,9 +304,11 @@ void rs690_crtc_bandwidth_compute(struct
+ if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
+ rdev->pm.sideport_bandwidth.full)
+ rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
+- read_delay_latency.full = dfixed_const(370 * 800 * 1000);
++ read_delay_latency.full = dfixed_const(800 * 1000);
+ read_delay_latency.full = dfixed_div(read_delay_latency,
+ rdev->pm.igp_sideport_mclk);
++ a.full = dfixed_const(370);
++ read_delay_latency.full = dfixed_mul(read_delay_latency, a);
+ } else {
+ if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full &&
+ rdev->pm.k8_bandwidth.full)
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/ttm/ttm_bo_vm.c linux-2.6.38.7/drivers/gpu/drm/ttm/ttm_bo_vm.c
+--- linux-2.6.38.7/drivers/gpu/drm/ttm/ttm_bo_vm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/ttm/ttm_bo_vm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -69,11 +69,11 @@ static struct ttm_buffer_object *ttm_bo_
+ return best_bo;
+ }
+
+-static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
+ vma->vm_private_data;
+- struct ttm_bo_device *bdev = bo->bdev;
++ struct ttm_bo_device *bdev;
+ unsigned long page_offset;
+ unsigned long page_last;
+ unsigned long pfn;
+@@ -83,8 +83,12 @@ static int ttm_bo_vm_fault(struct vm_are
+ int i;
+ unsigned long address = (unsigned long)vmf->virtual_address;
+ int retval = VM_FAULT_NOPAGE;
+- struct ttm_mem_type_manager *man =
+- &bdev->man[bo->mem.mem_type];
++ struct ttm_mem_type_manager *man;
++
++ if (!bo)
++ return VM_FAULT_NOPAGE;
++ bdev = bo->bdev;
++ man = &bdev->man[bo->mem.mem_type];
+
+ /*
+ * Work around locking order reversal in fault / nopfn
+@@ -219,22 +223,25 @@ out_unlock:
+ ttm_bo_unreserve(bo);
+ return retval;
+ }
++EXPORT_SYMBOL(ttm_bo_vm_fault);
+
+-static void ttm_bo_vm_open(struct vm_area_struct *vma)
++void ttm_bo_vm_open(struct vm_area_struct *vma)
+ {
+ struct ttm_buffer_object *bo =
+ (struct ttm_buffer_object *)vma->vm_private_data;
+
+ (void)ttm_bo_reference(bo);
+ }
++EXPORT_SYMBOL(ttm_bo_vm_open);
+
+-static void ttm_bo_vm_close(struct vm_area_struct *vma)
++void ttm_bo_vm_close(struct vm_area_struct *vma)
+ {
+ struct ttm_buffer_object *bo = (struct ttm_buffer_object *)vma->vm_private_data;
+
+ ttm_bo_unref(&bo);
+ vma->vm_private_data = NULL;
+ }
++EXPORT_SYMBOL(ttm_bo_vm_close);
+
+ static const struct vm_operations_struct ttm_bo_vm_ops = {
+ .fault = ttm_bo_vm_fault,
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/ttm/ttm_page_alloc.c linux-2.6.38.7/drivers/gpu/drm/ttm/ttm_page_alloc.c
+--- linux-2.6.38.7/drivers/gpu/drm/ttm/ttm_page_alloc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/ttm/ttm_page_alloc.c 2011-04-28 19:57:25.000000000 -0400
+@@ -396,9 +396,9 @@ static int ttm_pool_get_num_unused_pages
+ */
+ static int ttm_pool_mm_shrink(struct shrinker *shrink, int shrink_pages, gfp_t gfp_mask)
+ {
+- static atomic_t start_pool = ATOMIC_INIT(0);
++ static atomic_unchecked_t start_pool = ATOMIC_INIT(0);
+ unsigned i;
+- unsigned pool_offset = atomic_add_return(1, &start_pool);
++ unsigned pool_offset = atomic_add_return_unchecked(1, &start_pool);
+ struct ttm_page_pool *pool;
+
+ pool_offset = pool_offset % NUM_POOLS;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/via/via_drv.h linux-2.6.38.7/drivers/gpu/drm/via/via_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/via/via_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/via/via_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -51,7 +51,7 @@ typedef struct drm_via_ring_buffer {
+ typedef uint32_t maskarray_t[5];
+
+ typedef struct drm_via_irq {
+- atomic_t irq_received;
++ atomic_unchecked_t irq_received;
+ uint32_t pending_mask;
+ uint32_t enable_mask;
+ wait_queue_head_t irq_queue;
+@@ -75,7 +75,7 @@ typedef struct drm_via_private {
+ struct timeval last_vblank;
+ int last_vblank_valid;
+ unsigned usec_per_vblank;
+- atomic_t vbl_received;
++ atomic_unchecked_t vbl_received;
+ drm_via_state_t hc_state;
+ char pci_buf[VIA_PCI_BUF_SIZE];
+ const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/via/via_irq.c linux-2.6.38.7/drivers/gpu/drm/via/via_irq.c
+--- linux-2.6.38.7/drivers/gpu/drm/via/via_irq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/via/via_irq.c 2011-04-28 19:57:25.000000000 -0400
+@@ -102,7 +102,7 @@ u32 via_get_vblank_counter(struct drm_de
+ if (crtc != 0)
+ return 0;
+
+- return atomic_read(&dev_priv->vbl_received);
++ return atomic_read_unchecked(&dev_priv->vbl_received);
+ }
+
+ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+@@ -117,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_I
+
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ if (status & VIA_IRQ_VBLANK_PENDING) {
+- atomic_inc(&dev_priv->vbl_received);
+- if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
++ atomic_inc_unchecked(&dev_priv->vbl_received);
++ if (!(atomic_read_unchecked(&dev_priv->vbl_received) & 0x0F)) {
+ do_gettimeofday(&cur_vblank);
+ if (dev_priv->last_vblank_valid) {
+ dev_priv->usec_per_vblank =
+@@ -128,7 +128,7 @@ irqreturn_t via_driver_irq_handler(DRM_I
+ dev_priv->last_vblank = cur_vblank;
+ dev_priv->last_vblank_valid = 1;
+ }
+- if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
++ if (!(atomic_read_unchecked(&dev_priv->vbl_received) & 0xFF)) {
+ DRM_DEBUG("US per vblank is: %u\n",
+ dev_priv->usec_per_vblank);
+ }
+@@ -138,7 +138,7 @@ irqreturn_t via_driver_irq_handler(DRM_I
+
+ for (i = 0; i < dev_priv->num_irqs; ++i) {
+ if (status & cur_irq->pending_mask) {
+- atomic_inc(&cur_irq->irq_received);
++ atomic_inc_unchecked(&cur_irq->irq_received);
+ DRM_WAKEUP(&cur_irq->irq_queue);
+ handled = 1;
+ if (dev_priv->irq_map[drm_via_irq_dma0_td] == i)
+@@ -243,11 +243,11 @@ via_driver_irq_wait(struct drm_device *d
+ DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+ ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
+ masks[irq][4]));
+- cur_irq_sequence = atomic_read(&cur_irq->irq_received);
++ cur_irq_sequence = atomic_read_unchecked(&cur_irq->irq_received);
+ } else {
+ DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+ (((cur_irq_sequence =
+- atomic_read(&cur_irq->irq_received)) -
++ atomic_read_unchecked(&cur_irq->irq_received)) -
+ *sequence) <= (1 << 23)));
+ }
+ *sequence = cur_irq_sequence;
+@@ -285,7 +285,7 @@ void via_driver_irq_preinstall(struct dr
+ }
+
+ for (i = 0; i < dev_priv->num_irqs; ++i) {
+- atomic_set(&cur_irq->irq_received, 0);
++ atomic_set_unchecked(&cur_irq->irq_received, 0);
+ cur_irq->enable_mask = dev_priv->irq_masks[i][0];
+ cur_irq->pending_mask = dev_priv->irq_masks[i][1];
+ DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
+@@ -367,7 +367,7 @@ int via_wait_irq(struct drm_device *dev,
+ switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
+ case VIA_IRQ_RELATIVE:
+ irqwait->request.sequence +=
+- atomic_read(&cur_irq->irq_received);
++ atomic_read_unchecked(&cur_irq->irq_received);
+ irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
+ case VIA_IRQ_ABSOLUTE:
+ break;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+--- linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -240,7 +240,7 @@ struct vmw_private {
+ * Fencing and IRQs.
+ */
+
+- atomic_t fence_seq;
++ atomic_unchecked_t fence_seq;
+ wait_queue_head_t fence_queue;
+ wait_queue_head_t fifo_queue;
+ atomic_t fence_queue_waiters;
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+--- linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c 2011-04-28 19:57:25.000000000 -0400
+@@ -151,7 +151,7 @@ int vmw_wait_lag(struct vmw_private *dev
+ while (!vmw_lag_lt(queue, us)) {
+ spin_lock(&queue->lock);
+ if (list_empty(&queue->head))
+- sequence = atomic_read(&dev_priv->fence_seq);
++ sequence = atomic_read_unchecked(&dev_priv->fence_seq);
+ else {
+ fence = list_first_entry(&queue->head,
+ struct vmw_fence, head);
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+--- linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c 2011-04-28 19:57:25.000000000 -0400
+@@ -137,7 +137,7 @@ int vmw_fifo_init(struct vmw_private *de
+ (unsigned int) min,
+ (unsigned int) fifo->capabilities);
+
+- atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
++ atomic_set_unchecked(&dev_priv->fence_seq, dev_priv->last_read_sequence);
+ iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
+ vmw_fence_queue_init(&fifo->fence_queue);
+ return vmw_fifo_send_fence(dev_priv, &dummy);
+@@ -476,7 +476,7 @@ int vmw_fifo_send_fence(struct vmw_priva
+
+ fm = vmw_fifo_reserve(dev_priv, bytes);
+ if (unlikely(fm == NULL)) {
+- *sequence = atomic_read(&dev_priv->fence_seq);
++ *sequence = atomic_read_unchecked(&dev_priv->fence_seq);
+ ret = -ENOMEM;
+ (void)vmw_fallback_wait(dev_priv, false, true, *sequence,
+ false, 3*HZ);
+@@ -484,7 +484,7 @@ int vmw_fifo_send_fence(struct vmw_priva
+ }
+
+ do {
+- *sequence = atomic_add_return(1, &dev_priv->fence_seq);
++ *sequence = atomic_add_return_unchecked(1, &dev_priv->fence_seq);
+ } while (*sequence == 0);
+
+ if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {
+@@ -534,7 +534,7 @@ static int vmw_fifo_vm_fault(struct vm_a
+ return VM_FAULT_SIGBUS;
+ }
+
+-static struct vm_operations_struct vmw_fifo_vm_ops = {
++static const struct vm_operations_struct vmw_fifo_vm_ops = {
+ .fault = vmw_fifo_vm_fault,
+ .open = NULL,
+ .close = NULL
+diff -urNp linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+--- linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c 2011-04-28 19:57:25.000000000 -0400
+@@ -100,7 +100,7 @@ bool vmw_fence_signaled(struct vmw_priva
+ * emitted. Then the fence is stale and signaled.
+ */
+
+- ret = ((atomic_read(&dev_priv->fence_seq) - sequence)
++ ret = ((atomic_read_unchecked(&dev_priv->fence_seq) - sequence)
+ > VMW_FENCE_WRAP);
+
+ return ret;
+@@ -131,7 +131,7 @@ int vmw_fallback_wait(struct vmw_private
+
+ if (fifo_idle)
+ down_read(&fifo_state->rwsem);
+- signal_seq = atomic_read(&dev_priv->fence_seq);
++ signal_seq = atomic_read_unchecked(&dev_priv->fence_seq);
+ ret = 0;
+
+ for (;;) {
+diff -urNp linux-2.6.38.7/drivers/hid/hid-core.c linux-2.6.38.7/drivers/hid/hid-core.c
+--- linux-2.6.38.7/drivers/hid/hid-core.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/drivers/hid/hid-core.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1846,7 +1846,7 @@ static bool hid_ignore(struct hid_device
+
+ int hid_add_device(struct hid_device *hdev)
+ {
+- static atomic_t id = ATOMIC_INIT(0);
++ static atomic_unchecked_t id = ATOMIC_INIT(0);
+ int ret;
+
+ if (WARN_ON(hdev->status & HID_STAT_ADDED))
+@@ -1861,7 +1861,7 @@ int hid_add_device(struct hid_device *hd
+ /* XXX hack, any other cleaner solution after the driver core
+ * is converted to allow more than 20 bytes as the device name? */
+ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
+- hdev->vendor, hdev->product, atomic_inc_return(&id));
++ hdev->vendor, hdev->product, atomic_inc_return_unchecked(&id));
+
+ hid_debug_register(hdev, dev_name(&hdev->dev));
+ ret = device_add(&hdev->dev);
+diff -urNp linux-2.6.38.7/drivers/hid/usbhid/hiddev.c linux-2.6.38.7/drivers/hid/usbhid/hiddev.c
+--- linux-2.6.38.7/drivers/hid/usbhid/hiddev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/hid/usbhid/hiddev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -613,7 +613,7 @@ static long hiddev_ioctl(struct file *fi
+ break;
+
+ case HIDIOCAPPLICATION:
+- if (arg < 0 || arg >= hid->maxapplication)
++ if (arg >= hid->maxapplication)
+ break;
+
+ for (i = 0; i < hid->maxcollection; i++)
+diff -urNp linux-2.6.38.7/drivers/hwmon/lis3lv02d.c linux-2.6.38.7/drivers/hwmon/lis3lv02d.c
+--- linux-2.6.38.7/drivers/hwmon/lis3lv02d.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/hwmon/lis3lv02d.c 2011-04-28 19:57:25.000000000 -0400
+@@ -436,7 +436,7 @@ static irqreturn_t lis302dl_interrupt(in
+ * the lid is closed. This leads to interrupts as soon as a little move
+ * is done.
+ */
+- atomic_inc(&lis3_dev.count);
++ atomic_inc_unchecked(&lis3_dev.count);
+
+ wake_up_interruptible(&lis3_dev.misc_wait);
+ kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
+@@ -519,7 +519,7 @@ static int lis3lv02d_misc_open(struct in
+ if (lis3_dev.pm_dev)
+ pm_runtime_get_sync(lis3_dev.pm_dev);
+
+- atomic_set(&lis3_dev.count, 0);
++ atomic_set_unchecked(&lis3_dev.count, 0);
+ return 0;
+ }
+
+@@ -546,7 +546,7 @@ static ssize_t lis3lv02d_misc_read(struc
+ add_wait_queue(&lis3_dev.misc_wait, &wait);
+ while (true) {
+ set_current_state(TASK_INTERRUPTIBLE);
+- data = atomic_xchg(&lis3_dev.count, 0);
++ data = atomic_xchg_unchecked(&lis3_dev.count, 0);
+ if (data)
+ break;
+
+@@ -584,7 +584,7 @@ out:
+ static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
+ {
+ poll_wait(file, &lis3_dev.misc_wait, wait);
+- if (atomic_read(&lis3_dev.count))
++ if (atomic_read_unchecked(&lis3_dev.count))
+ return POLLIN | POLLRDNORM;
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/drivers/hwmon/lis3lv02d.h linux-2.6.38.7/drivers/hwmon/lis3lv02d.h
+--- linux-2.6.38.7/drivers/hwmon/lis3lv02d.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/hwmon/lis3lv02d.h 2011-04-28 19:57:25.000000000 -0400
+@@ -265,7 +265,7 @@ struct lis3lv02d {
+ struct input_polled_dev *idev; /* input device */
+ struct platform_device *pdev; /* platform device */
+ struct regulator_bulk_data regulators[2];
+- atomic_t count; /* interrupt count after last read */
++ atomic_unchecked_t count; /* interrupt count after last read */
+ union axis_conversion ac; /* hw -> logical axis */
+ int mapped_btns[3];
+
+diff -urNp linux-2.6.38.7/drivers/hwmon/sht15.c linux-2.6.38.7/drivers/hwmon/sht15.c
+--- linux-2.6.38.7/drivers/hwmon/sht15.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/drivers/hwmon/sht15.c 2011-04-28 19:57:25.000000000 -0400
+@@ -113,7 +113,7 @@ struct sht15_data {
+ int supply_uV;
+ int supply_uV_valid;
+ struct work_struct update_supply_work;
+- atomic_t interrupt_handled;
++ atomic_unchecked_t interrupt_handled;
+ };
+
+ /**
+@@ -246,13 +246,13 @@ static inline int sht15_update_single_va
+ return ret;
+
+ gpio_direction_input(data->pdata->gpio_data);
+- atomic_set(&data->interrupt_handled, 0);
++ atomic_set_unchecked(&data->interrupt_handled, 0);
+
+ enable_irq(gpio_to_irq(data->pdata->gpio_data));
+ if (gpio_get_value(data->pdata->gpio_data) == 0) {
+ disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
+ /* Only relevant if the interrupt hasn't occured. */
+- if (!atomic_read(&data->interrupt_handled))
++ if (!atomic_read_unchecked(&data->interrupt_handled))
+ schedule_work(&data->read_work);
+ }
+ ret = wait_event_timeout(data->wait_queue,
+@@ -399,7 +399,7 @@ static irqreturn_t sht15_interrupt_fired
+ struct sht15_data *data = d;
+ /* First disable the interrupt */
+ disable_irq_nosync(irq);
+- atomic_inc(&data->interrupt_handled);
++ atomic_inc_unchecked(&data->interrupt_handled);
+ /* Then schedule a reading work struct */
+ if (data->flag != SHT15_READING_NOTHING)
+ schedule_work(&data->read_work);
+@@ -450,11 +450,11 @@ static void sht15_bh_read_data(struct wo
+ here as could have gone low in meantime so verify
+ it hasn't!
+ */
+- atomic_set(&data->interrupt_handled, 0);
++ atomic_set_unchecked(&data->interrupt_handled, 0);
+ enable_irq(gpio_to_irq(data->pdata->gpio_data));
+ /* If still not occured or another handler has been scheduled */
+ if (gpio_get_value(data->pdata->gpio_data)
+- || atomic_read(&data->interrupt_handled))
++ || atomic_read_unchecked(&data->interrupt_handled))
+ return;
+ }
+ /* Read the data back from the device */
+diff -urNp linux-2.6.38.7/drivers/hwmon/w83791d.c linux-2.6.38.7/drivers/hwmon/w83791d.c
+--- linux-2.6.38.7/drivers/hwmon/w83791d.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/hwmon/w83791d.c 2011-04-28 19:34:15.000000000 -0400
+@@ -329,8 +329,8 @@ static int w83791d_detect(struct i2c_cli
+ struct i2c_board_info *info);
+ static int w83791d_remove(struct i2c_client *client);
+
+-static int w83791d_read(struct i2c_client *client, u8 register);
+-static int w83791d_write(struct i2c_client *client, u8 register, u8 value);
++static int w83791d_read(struct i2c_client *client, u8 reg);
++static int w83791d_write(struct i2c_client *client, u8 reg, u8 value);
+ static struct w83791d_data *w83791d_update_device(struct device *dev);
+
+ #ifdef DEBUG
+diff -urNp linux-2.6.38.7/drivers/ide/ide-cd.c linux-2.6.38.7/drivers/ide/ide-cd.c
+--- linux-2.6.38.7/drivers/ide/ide-cd.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ide/ide-cd.c 2011-04-28 19:34:15.000000000 -0400
+@@ -776,7 +776,7 @@ static void cdrom_do_block_pc(ide_drive_
+ alignment = queue_dma_alignment(q) | q->dma_pad_mask;
+ if ((unsigned long)buf & alignment
+ || blk_rq_bytes(rq) & q->dma_pad_mask
+- || object_is_on_stack(buf))
++ || object_starts_on_stack(buf))
+ drive->dma = 0;
+ }
+ }
+diff -urNp linux-2.6.38.7/drivers/ide/ide-floppy.c linux-2.6.38.7/drivers/ide/ide-floppy.c
+--- linux-2.6.38.7/drivers/ide/ide-floppy.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ide/ide-floppy.c 2011-05-16 21:47:08.000000000 -0400
+@@ -379,6 +379,8 @@ static int ide_floppy_get_capacity(ide_d
+ u8 pc_buf[256], header_len, desc_cnt;
+ int i, rc = 1, blocks, length;
+
++ pax_track_stack();
++
+ ide_debug_log(IDE_DBG_FUNC, "enter");
+
+ drive->bios_cyl = 0;
+diff -urNp linux-2.6.38.7/drivers/ide/setup-pci.c linux-2.6.38.7/drivers/ide/setup-pci.c
+--- linux-2.6.38.7/drivers/ide/setup-pci.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/ide/setup-pci.c 2011-05-16 21:47:08.000000000 -0400
+@@ -542,6 +542,8 @@ int ide_pci_init_two(struct pci_dev *dev
+ int ret, i, n_ports = dev2 ? 4 : 2;
+ struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL };
+
++ pax_track_stack();
++
+ for (i = 0; i < n_ports / 2; i++) {
+ ret = ide_setup_pci_controller(pdev[i], d, !i);
+ if (ret < 0)
+diff -urNp linux-2.6.38.7/drivers/infiniband/core/cm.c linux-2.6.38.7/drivers/infiniband/core/cm.c
+--- linux-2.6.38.7/drivers/infiniband/core/cm.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/core/cm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -113,7 +113,7 @@ static char const counter_group_names[CM
+
+ struct cm_counter_group {
+ struct kobject obj;
+- atomic_long_t counter[CM_ATTR_COUNT];
++ atomic_long_unchecked_t counter[CM_ATTR_COUNT];
+ };
+
+ struct cm_counter_attribute {
+@@ -1387,7 +1387,7 @@ static void cm_dup_req_handler(struct cm
+ struct ib_mad_send_buf *msg = NULL;
+ int ret;
+
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_REQ_COUNTER]);
+
+ /* Quick state check to discard duplicate REQs. */
+@@ -1765,7 +1765,7 @@ static void cm_dup_rep_handler(struct cm
+ if (!cm_id_priv)
+ return;
+
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_REP_COUNTER]);
+ ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
+ if (ret)
+@@ -1932,7 +1932,7 @@ static int cm_rtu_handler(struct cm_work
+ if (cm_id_priv->id.state != IB_CM_REP_SENT &&
+ cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
+ spin_unlock_irq(&cm_id_priv->lock);
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_RTU_COUNTER]);
+ goto out;
+ }
+@@ -2111,7 +2111,7 @@ static int cm_dreq_handler(struct cm_wor
+ cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
+ dreq_msg->local_comm_id);
+ if (!cm_id_priv) {
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_DREQ_COUNTER]);
+ cm_issue_drep(work->port, work->mad_recv_wc);
+ return -EINVAL;
+@@ -2132,7 +2132,7 @@ static int cm_dreq_handler(struct cm_wor
+ case IB_CM_MRA_REP_RCVD:
+ break;
+ case IB_CM_TIMEWAIT:
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_DREQ_COUNTER]);
+ if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
+ goto unlock;
+@@ -2146,7 +2146,7 @@ static int cm_dreq_handler(struct cm_wor
+ cm_free_msg(msg);
+ goto deref;
+ case IB_CM_DREQ_RCVD:
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_DREQ_COUNTER]);
+ goto unlock;
+ default:
+@@ -2504,7 +2504,7 @@ static int cm_mra_handler(struct cm_work
+ ib_modify_mad(cm_id_priv->av.port->mad_agent,
+ cm_id_priv->msg, timeout)) {
+ if (cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
+- atomic_long_inc(&work->port->
++ atomic_long_inc_unchecked(&work->port->
+ counter_group[CM_RECV_DUPLICATES].
+ counter[CM_MRA_COUNTER]);
+ goto out;
+@@ -2513,7 +2513,7 @@ static int cm_mra_handler(struct cm_work
+ break;
+ case IB_CM_MRA_REQ_RCVD:
+ case IB_CM_MRA_REP_RCVD:
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_MRA_COUNTER]);
+ /* fall through */
+ default:
+@@ -2675,7 +2675,7 @@ static int cm_lap_handler(struct cm_work
+ case IB_CM_LAP_IDLE:
+ break;
+ case IB_CM_MRA_LAP_SENT:
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_LAP_COUNTER]);
+ if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
+ goto unlock;
+@@ -2691,7 +2691,7 @@ static int cm_lap_handler(struct cm_work
+ cm_free_msg(msg);
+ goto deref;
+ case IB_CM_LAP_RCVD:
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_LAP_COUNTER]);
+ goto unlock;
+ default:
+@@ -2975,7 +2975,7 @@ static int cm_sidr_req_handler(struct cm
+ cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
+ if (cur_cm_id_priv) {
+ spin_unlock_irq(&cm.lock);
+- atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++ atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES].
+ counter[CM_SIDR_REQ_COUNTER]);
+ goto out; /* Duplicate message. */
+ }
+@@ -3187,10 +3187,10 @@ static void cm_send_handler(struct ib_ma
+ if (!msg->context[0] && (attr_index != CM_REJ_COUNTER))
+ msg->retries = 1;
+
+- atomic_long_add(1 + msg->retries,
++ atomic_long_add_unchecked(1 + msg->retries,
+ &port->counter_group[CM_XMIT].counter[attr_index]);
+ if (msg->retries)
+- atomic_long_add(msg->retries,
++ atomic_long_add_unchecked(msg->retries,
+ &port->counter_group[CM_XMIT_RETRIES].
+ counter[attr_index]);
+
+@@ -3400,7 +3400,7 @@ static void cm_recv_handler(struct ib_ma
+ }
+
+ attr_id = be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id);
+- atomic_long_inc(&port->counter_group[CM_RECV].
++ atomic_long_inc_unchecked(&port->counter_group[CM_RECV].
+ counter[attr_id - CM_ATTR_ID_OFFSET]);
+
+ work = kmalloc(sizeof *work + sizeof(struct ib_sa_path_rec) * paths,
+@@ -3598,7 +3598,7 @@ static ssize_t cm_show_counter(struct ko
+ cm_attr = container_of(attr, struct cm_counter_attribute, attr);
+
+ return sprintf(buf, "%ld\n",
+- atomic_long_read(&group->counter[cm_attr->index]));
++ atomic_long_read_unchecked(&group->counter[cm_attr->index]));
+ }
+
+ static const struct sysfs_ops cm_counter_ops = {
+diff -urNp linux-2.6.38.7/drivers/infiniband/core/fmr_pool.c linux-2.6.38.7/drivers/infiniband/core/fmr_pool.c
+--- linux-2.6.38.7/drivers/infiniband/core/fmr_pool.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/core/fmr_pool.c 2011-04-28 19:57:25.000000000 -0400
+@@ -97,8 +97,8 @@ struct ib_fmr_pool {
+
+ struct task_struct *thread;
+
+- atomic_t req_ser;
+- atomic_t flush_ser;
++ atomic_unchecked_t req_ser;
++ atomic_unchecked_t flush_ser;
+
+ wait_queue_head_t force_wait;
+ };
+@@ -179,10 +179,10 @@ static int ib_fmr_cleanup_thread(void *p
+ struct ib_fmr_pool *pool = pool_ptr;
+
+ do {
+- if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
++ if (atomic_read_unchecked(&pool->flush_ser) - atomic_read_unchecked(&pool->req_ser) < 0) {
+ ib_fmr_batch_release(pool);
+
+- atomic_inc(&pool->flush_ser);
++ atomic_inc_unchecked(&pool->flush_ser);
+ wake_up_interruptible(&pool->force_wait);
+
+ if (pool->flush_function)
+@@ -190,7 +190,7 @@ static int ib_fmr_cleanup_thread(void *p
+ }
+
+ set_current_state(TASK_INTERRUPTIBLE);
+- if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
++ if (atomic_read_unchecked(&pool->flush_ser) - atomic_read_unchecked(&pool->req_ser) >= 0 &&
+ !kthread_should_stop())
+ schedule();
+ __set_current_state(TASK_RUNNING);
+@@ -282,8 +282,8 @@ struct ib_fmr_pool *ib_create_fmr_pool(s
+ pool->dirty_watermark = params->dirty_watermark;
+ pool->dirty_len = 0;
+ spin_lock_init(&pool->pool_lock);
+- atomic_set(&pool->req_ser, 0);
+- atomic_set(&pool->flush_ser, 0);
++ atomic_set_unchecked(&pool->req_ser, 0);
++ atomic_set_unchecked(&pool->flush_ser, 0);
+ init_waitqueue_head(&pool->force_wait);
+
+ pool->thread = kthread_run(ib_fmr_cleanup_thread,
+@@ -411,11 +411,11 @@ int ib_flush_fmr_pool(struct ib_fmr_pool
+ }
+ spin_unlock_irq(&pool->pool_lock);
+
+- serial = atomic_inc_return(&pool->req_ser);
++ serial = atomic_inc_return_unchecked(&pool->req_ser);
+ wake_up_process(pool->thread);
+
+ if (wait_event_interruptible(pool->force_wait,
+- atomic_read(&pool->flush_ser) - serial >= 0))
++ atomic_read_unchecked(&pool->flush_ser) - serial >= 0))
+ return -EINTR;
+
+ return 0;
+@@ -525,7 +525,7 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr
+ } else {
+ list_add_tail(&fmr->list, &pool->dirty_list);
+ if (++pool->dirty_len >= pool->dirty_watermark) {
+- atomic_inc(&pool->req_ser);
++ atomic_inc_unchecked(&pool->req_ser);
+ wake_up_process(pool->thread);
+ }
+ }
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/cxgb4/mem.c linux-2.6.38.7/drivers/infiniband/hw/cxgb4/mem.c
+--- linux-2.6.38.7/drivers/infiniband/hw/cxgb4/mem.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/cxgb4/mem.c 2011-04-28 19:57:25.000000000 -0400
+@@ -122,7 +122,7 @@ static int write_tpt_entry(struct c4iw_r
+ int err;
+ struct fw_ri_tpte tpt;
+ u32 stag_idx;
+- static atomic_t key;
++ static atomic_unchecked_t key;
+
+ if (c4iw_fatal_error(rdev))
+ return -EIO;
+@@ -135,7 +135,7 @@ static int write_tpt_entry(struct c4iw_r
+ &rdev->resource.tpt_fifo_lock);
+ if (!stag_idx)
+ return -ENOMEM;
+- *stag = (stag_idx << 8) | (atomic_inc_return(&key) & 0xff);
++ *stag = (stag_idx << 8) | (atomic_inc_return_unchecked(&key) & 0xff);
+ }
+ PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n",
+ __func__, stag_state, type, pdid, stag_idx);
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_fs.c linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_fs.c
+--- linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_fs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_fs.c 2011-05-16 21:47:08.000000000 -0400
+@@ -113,6 +113,8 @@ static ssize_t atomic_counters_read(stru
+ struct infinipath_counters counters;
+ struct ipath_devdata *dd;
+
++ pax_track_stack();
++
+ dd = file->f_path.dentry->d_inode->i_private;
+ dd->ipath_f_read_counters(dd, &counters);
+
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_rc.c linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_rc.c
+--- linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_rc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_rc.c 2011-05-11 18:35:16.000000000 -0400
+@@ -1868,7 +1868,7 @@ void ipath_rc_rcv(struct ipath_ibdev *de
+ struct ib_atomic_eth *ateth;
+ struct ipath_ack_entry *e;
+ u64 vaddr;
+- atomic64_t *maddr;
++ atomic64_unchecked_t *maddr;
+ u64 sdata;
+ u32 rkey;
+ u8 next;
+@@ -1903,11 +1903,11 @@ void ipath_rc_rcv(struct ipath_ibdev *de
+ IB_ACCESS_REMOTE_ATOMIC)))
+ goto nack_acc_unlck;
+ /* Perform atomic OP and save result. */
+- maddr = (atomic64_t *) qp->r_sge.sge.vaddr;
++ maddr = (atomic64_unchecked_t *) qp->r_sge.sge.vaddr;
+ sdata = be64_to_cpu(ateth->swap_data);
+ e = &qp->s_ack_queue[qp->r_head_ack_queue];
+ e->atomic_data = (opcode == OP(FETCH_ADD)) ?
+- (u64) atomic64_add_return(sdata, maddr) - sdata :
++ (u64) atomic64_add_return_unchecked(sdata, maddr) - sdata :
+ (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr,
+ be64_to_cpu(ateth->compare_data),
+ sdata);
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_ruc.c linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_ruc.c
+--- linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_ruc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/ipath/ipath_ruc.c 2011-05-11 18:35:16.000000000 -0400
+@@ -266,7 +266,7 @@ static void ipath_ruc_loopback(struct ip
+ unsigned long flags;
+ struct ib_wc wc;
+ u64 sdata;
+- atomic64_t *maddr;
++ atomic64_unchecked_t *maddr;
+ enum ib_wc_status send_status;
+
+ /*
+@@ -382,11 +382,11 @@ again:
+ IB_ACCESS_REMOTE_ATOMIC)))
+ goto acc_err;
+ /* Perform atomic OP and save result. */
+- maddr = (atomic64_t *) qp->r_sge.sge.vaddr;
++ maddr = (atomic64_unchecked_t *) qp->r_sge.sge.vaddr;
+ sdata = wqe->wr.wr.atomic.compare_add;
+ *(u64 *) sqp->s_sge.sge.vaddr =
+ (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ?
+- (u64) atomic64_add_return(sdata, maddr) - sdata :
++ (u64) atomic64_add_return_unchecked(sdata, maddr) - sdata :
+ (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr,
+ sdata, wqe->wr.wr.atomic.swap);
+ goto send_comp;
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/nes/nes.c linux-2.6.38.7/drivers/infiniband/hw/nes/nes.c
+--- linux-2.6.38.7/drivers/infiniband/hw/nes/nes.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/nes/nes.c 2011-04-28 19:57:25.000000000 -0400
+@@ -103,7 +103,7 @@ MODULE_PARM_DESC(limit_maxrdreqsz, "Limi
+ LIST_HEAD(nes_adapter_list);
+ static LIST_HEAD(nes_dev_list);
+
+-atomic_t qps_destroyed;
++atomic_unchecked_t qps_destroyed;
+
+ static unsigned int ee_flsh_adapter;
+ static unsigned int sysfs_nonidx_addr;
+@@ -274,7 +274,7 @@ static void nes_cqp_rem_ref_callback(str
+ struct nes_qp *nesqp = cqp_request->cqp_callback_pointer;
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
+
+- atomic_inc(&qps_destroyed);
++ atomic_inc_unchecked(&qps_destroyed);
+
+ /* Free the control structures */
+
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/nes/nes_cm.c linux-2.6.38.7/drivers/infiniband/hw/nes/nes_cm.c
+--- linux-2.6.38.7/drivers/infiniband/hw/nes/nes_cm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/nes/nes_cm.c 2011-04-28 19:57:25.000000000 -0400
+@@ -68,14 +68,14 @@ u32 cm_packets_dropped;
+ u32 cm_packets_retrans;
+ u32 cm_packets_created;
+ u32 cm_packets_received;
+-atomic_t cm_listens_created;
+-atomic_t cm_listens_destroyed;
++atomic_unchecked_t cm_listens_created;
++atomic_unchecked_t cm_listens_destroyed;
+ u32 cm_backlog_drops;
+-atomic_t cm_loopbacks;
+-atomic_t cm_nodes_created;
+-atomic_t cm_nodes_destroyed;
+-atomic_t cm_accel_dropped_pkts;
+-atomic_t cm_resets_recvd;
++atomic_unchecked_t cm_loopbacks;
++atomic_unchecked_t cm_nodes_created;
++atomic_unchecked_t cm_nodes_destroyed;
++atomic_unchecked_t cm_accel_dropped_pkts;
++atomic_unchecked_t cm_resets_recvd;
+
+ static inline int mini_cm_accelerated(struct nes_cm_core *,
+ struct nes_cm_node *);
+@@ -151,13 +151,13 @@ static struct nes_cm_ops nes_cm_api = {
+
+ static struct nes_cm_core *g_cm_core;
+
+-atomic_t cm_connects;
+-atomic_t cm_accepts;
+-atomic_t cm_disconnects;
+-atomic_t cm_closes;
+-atomic_t cm_connecteds;
+-atomic_t cm_connect_reqs;
+-atomic_t cm_rejects;
++atomic_unchecked_t cm_connects;
++atomic_unchecked_t cm_accepts;
++atomic_unchecked_t cm_disconnects;
++atomic_unchecked_t cm_closes;
++atomic_unchecked_t cm_connecteds;
++atomic_unchecked_t cm_connect_reqs;
++atomic_unchecked_t cm_rejects;
+
+
+ /**
+@@ -1045,7 +1045,7 @@ static int mini_cm_dec_refcnt_listen(str
+ kfree(listener);
+ listener = NULL;
+ ret = 0;
+- atomic_inc(&cm_listens_destroyed);
++ atomic_inc_unchecked(&cm_listens_destroyed);
+ } else {
+ spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
+ }
+@@ -1242,7 +1242,7 @@ static struct nes_cm_node *make_cm_node(
+ cm_node->rem_mac);
+
+ add_hte_node(cm_core, cm_node);
+- atomic_inc(&cm_nodes_created);
++ atomic_inc_unchecked(&cm_nodes_created);
+
+ return cm_node;
+ }
+@@ -1300,7 +1300,7 @@ static int rem_ref_cm_node(struct nes_cm
+ }
+
+ atomic_dec(&cm_core->node_cnt);
+- atomic_inc(&cm_nodes_destroyed);
++ atomic_inc_unchecked(&cm_nodes_destroyed);
+ nesqp = cm_node->nesqp;
+ if (nesqp) {
+ nesqp->cm_node = NULL;
+@@ -1367,7 +1367,7 @@ static int process_options(struct nes_cm
+
+ static void drop_packet(struct sk_buff *skb)
+ {
+- atomic_inc(&cm_accel_dropped_pkts);
++ atomic_inc_unchecked(&cm_accel_dropped_pkts);
+ dev_kfree_skb_any(skb);
+ }
+
+@@ -1430,7 +1430,7 @@ static void handle_rst_pkt(struct nes_cm
+ {
+
+ int reset = 0; /* whether to send reset in case of err.. */
+- atomic_inc(&cm_resets_recvd);
++ atomic_inc_unchecked(&cm_resets_recvd);
+ nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u."
+ " refcnt=%d\n", cm_node, cm_node->state,
+ atomic_read(&cm_node->ref_count));
+@@ -2059,7 +2059,7 @@ static struct nes_cm_node *mini_cm_conne
+ rem_ref_cm_node(cm_node->cm_core, cm_node);
+ return NULL;
+ }
+- atomic_inc(&cm_loopbacks);
++ atomic_inc_unchecked(&cm_loopbacks);
+ loopbackremotenode->loopbackpartner = cm_node;
+ loopbackremotenode->tcp_cntxt.rcv_wscale =
+ NES_CM_DEFAULT_RCV_WND_SCALE;
+@@ -2334,7 +2334,7 @@ static int mini_cm_recv_pkt(struct nes_c
+ add_ref_cm_node(cm_node);
+ } else if (cm_node->state == NES_CM_STATE_TSA) {
+ rem_ref_cm_node(cm_core, cm_node);
+- atomic_inc(&cm_accel_dropped_pkts);
++ atomic_inc_unchecked(&cm_accel_dropped_pkts);
+ dev_kfree_skb_any(skb);
+ break;
+ }
+@@ -2640,7 +2640,7 @@ static int nes_cm_disconn_true(struct ne
+
+ if ((cm_id) && (cm_id->event_handler)) {
+ if (issue_disconn) {
+- atomic_inc(&cm_disconnects);
++ atomic_inc_unchecked(&cm_disconnects);
+ cm_event.event = IW_CM_EVENT_DISCONNECT;
+ cm_event.status = disconn_status;
+ cm_event.local_addr = cm_id->local_addr;
+@@ -2662,7 +2662,7 @@ static int nes_cm_disconn_true(struct ne
+ }
+
+ if (issue_close) {
+- atomic_inc(&cm_closes);
++ atomic_inc_unchecked(&cm_closes);
+ nes_disconnect(nesqp, 1);
+
+ cm_id->provider_data = nesqp;
+@@ -2793,7 +2793,7 @@ int nes_accept(struct iw_cm_id *cm_id, s
+
+ nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n",
+ nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener);
+- atomic_inc(&cm_accepts);
++ atomic_inc_unchecked(&cm_accepts);
+
+ nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
+ netdev_refcnt_read(nesvnic->netdev));
+@@ -3003,7 +3003,7 @@ int nes_reject(struct iw_cm_id *cm_id, c
+
+ struct nes_cm_core *cm_core;
+
+- atomic_inc(&cm_rejects);
++ atomic_inc_unchecked(&cm_rejects);
+ cm_node = (struct nes_cm_node *) cm_id->provider_data;
+ loopback = cm_node->loopbackpartner;
+ cm_core = cm_node->cm_core;
+@@ -3069,7 +3069,7 @@ int nes_connect(struct iw_cm_id *cm_id,
+ ntohl(cm_id->local_addr.sin_addr.s_addr),
+ ntohs(cm_id->local_addr.sin_port));
+
+- atomic_inc(&cm_connects);
++ atomic_inc_unchecked(&cm_connects);
+ nesqp->active_conn = 1;
+
+ /* cache the cm_id in the qp */
+@@ -3175,7 +3175,7 @@ int nes_create_listen(struct iw_cm_id *c
+ g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
+ return err;
+ }
+- atomic_inc(&cm_listens_created);
++ atomic_inc_unchecked(&cm_listens_created);
+ }
+
+ cm_id->add_ref(cm_id);
+@@ -3280,7 +3280,7 @@ static void cm_event_connected(struct ne
+ if (nesqp->destroyed) {
+ return;
+ }
+- atomic_inc(&cm_connecteds);
++ atomic_inc_unchecked(&cm_connecteds);
+ nes_debug(NES_DBG_CM, "QP%u attempting to connect to 0x%08X:0x%04X on"
+ " local port 0x%04X. jiffies = %lu.\n",
+ nesqp->hwqp.qp_id,
+@@ -3495,7 +3495,7 @@ static void cm_event_reset(struct nes_cm
+
+ cm_id->add_ref(cm_id);
+ ret = cm_id->event_handler(cm_id, &cm_event);
+- atomic_inc(&cm_closes);
++ atomic_inc_unchecked(&cm_closes);
+ cm_event.event = IW_CM_EVENT_CLOSE;
+ cm_event.status = IW_CM_EVENT_STATUS_OK;
+ cm_event.provider_data = cm_id->provider_data;
+@@ -3531,7 +3531,7 @@ static void cm_event_mpa_req(struct nes_
+ return;
+ cm_id = cm_node->cm_id;
+
+- atomic_inc(&cm_connect_reqs);
++ atomic_inc_unchecked(&cm_connect_reqs);
+ nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
+ cm_node, cm_id, jiffies);
+
+@@ -3569,7 +3569,7 @@ static void cm_event_mpa_reject(struct n
+ return;
+ cm_id = cm_node->cm_id;
+
+- atomic_inc(&cm_connect_reqs);
++ atomic_inc_unchecked(&cm_connect_reqs);
+ nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
+ cm_node, cm_id, jiffies);
+
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/nes/nes.h linux-2.6.38.7/drivers/infiniband/hw/nes/nes.h
+--- linux-2.6.38.7/drivers/infiniband/hw/nes/nes.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/nes/nes.h 2011-04-28 19:57:25.000000000 -0400
+@@ -175,17 +175,17 @@ extern unsigned int nes_debug_level;
+ extern unsigned int wqm_quanta;
+ extern struct list_head nes_adapter_list;
+
+-extern atomic_t cm_connects;
+-extern atomic_t cm_accepts;
+-extern atomic_t cm_disconnects;
+-extern atomic_t cm_closes;
+-extern atomic_t cm_connecteds;
+-extern atomic_t cm_connect_reqs;
+-extern atomic_t cm_rejects;
+-extern atomic_t mod_qp_timouts;
+-extern atomic_t qps_created;
+-extern atomic_t qps_destroyed;
+-extern atomic_t sw_qps_destroyed;
++extern atomic_unchecked_t cm_connects;
++extern atomic_unchecked_t cm_accepts;
++extern atomic_unchecked_t cm_disconnects;
++extern atomic_unchecked_t cm_closes;
++extern atomic_unchecked_t cm_connecteds;
++extern atomic_unchecked_t cm_connect_reqs;
++extern atomic_unchecked_t cm_rejects;
++extern atomic_unchecked_t mod_qp_timouts;
++extern atomic_unchecked_t qps_created;
++extern atomic_unchecked_t qps_destroyed;
++extern atomic_unchecked_t sw_qps_destroyed;
+ extern u32 mh_detected;
+ extern u32 mh_pauses_sent;
+ extern u32 cm_packets_sent;
+@@ -194,14 +194,14 @@ extern u32 cm_packets_created;
+ extern u32 cm_packets_received;
+ extern u32 cm_packets_dropped;
+ extern u32 cm_packets_retrans;
+-extern atomic_t cm_listens_created;
+-extern atomic_t cm_listens_destroyed;
++extern atomic_unchecked_t cm_listens_created;
++extern atomic_unchecked_t cm_listens_destroyed;
+ extern u32 cm_backlog_drops;
+-extern atomic_t cm_loopbacks;
+-extern atomic_t cm_nodes_created;
+-extern atomic_t cm_nodes_destroyed;
+-extern atomic_t cm_accel_dropped_pkts;
+-extern atomic_t cm_resets_recvd;
++extern atomic_unchecked_t cm_loopbacks;
++extern atomic_unchecked_t cm_nodes_created;
++extern atomic_unchecked_t cm_nodes_destroyed;
++extern atomic_unchecked_t cm_accel_dropped_pkts;
++extern atomic_unchecked_t cm_resets_recvd;
+
+ extern u32 int_mod_timer_init;
+ extern u32 int_mod_cq_depth_256;
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/nes/nes_nic.c linux-2.6.38.7/drivers/infiniband/hw/nes/nes_nic.c
+--- linux-2.6.38.7/drivers/infiniband/hw/nes/nes_nic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/nes/nes_nic.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1302,31 +1302,31 @@ static void nes_netdev_get_ethtool_stats
+ target_stat_values[++index] = mh_detected;
+ target_stat_values[++index] = mh_pauses_sent;
+ target_stat_values[++index] = nesvnic->endnode_ipv4_tcp_retransmits;
+- target_stat_values[++index] = atomic_read(&cm_connects);
+- target_stat_values[++index] = atomic_read(&cm_accepts);
+- target_stat_values[++index] = atomic_read(&cm_disconnects);
+- target_stat_values[++index] = atomic_read(&cm_connecteds);
+- target_stat_values[++index] = atomic_read(&cm_connect_reqs);
+- target_stat_values[++index] = atomic_read(&cm_rejects);
+- target_stat_values[++index] = atomic_read(&mod_qp_timouts);
+- target_stat_values[++index] = atomic_read(&qps_created);
+- target_stat_values[++index] = atomic_read(&sw_qps_destroyed);
+- target_stat_values[++index] = atomic_read(&qps_destroyed);
+- target_stat_values[++index] = atomic_read(&cm_closes);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_connects);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_accepts);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_disconnects);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_connecteds);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_connect_reqs);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_rejects);
++ target_stat_values[++index] = atomic_read_unchecked(&mod_qp_timouts);
++ target_stat_values[++index] = atomic_read_unchecked(&qps_created);
++ target_stat_values[++index] = atomic_read_unchecked(&sw_qps_destroyed);
++ target_stat_values[++index] = atomic_read_unchecked(&qps_destroyed);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_closes);
+ target_stat_values[++index] = cm_packets_sent;
+ target_stat_values[++index] = cm_packets_bounced;
+ target_stat_values[++index] = cm_packets_created;
+ target_stat_values[++index] = cm_packets_received;
+ target_stat_values[++index] = cm_packets_dropped;
+ target_stat_values[++index] = cm_packets_retrans;
+- target_stat_values[++index] = atomic_read(&cm_listens_created);
+- target_stat_values[++index] = atomic_read(&cm_listens_destroyed);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_listens_created);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_listens_destroyed);
+ target_stat_values[++index] = cm_backlog_drops;
+- target_stat_values[++index] = atomic_read(&cm_loopbacks);
+- target_stat_values[++index] = atomic_read(&cm_nodes_created);
+- target_stat_values[++index] = atomic_read(&cm_nodes_destroyed);
+- target_stat_values[++index] = atomic_read(&cm_accel_dropped_pkts);
+- target_stat_values[++index] = atomic_read(&cm_resets_recvd);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_loopbacks);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_nodes_created);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_nodes_destroyed);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_accel_dropped_pkts);
++ target_stat_values[++index] = atomic_read_unchecked(&cm_resets_recvd);
+ target_stat_values[++index] = nesadapter->free_4kpbl;
+ target_stat_values[++index] = nesadapter->free_256pbl;
+ target_stat_values[++index] = int_mod_timer_init;
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/nes/nes_verbs.c linux-2.6.38.7/drivers/infiniband/hw/nes/nes_verbs.c
+--- linux-2.6.38.7/drivers/infiniband/hw/nes/nes_verbs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/nes/nes_verbs.c 2011-04-28 19:57:25.000000000 -0400
+@@ -46,9 +46,9 @@
+
+ #include <rdma/ib_umem.h>
+
+-atomic_t mod_qp_timouts;
+-atomic_t qps_created;
+-atomic_t sw_qps_destroyed;
++atomic_unchecked_t mod_qp_timouts;
++atomic_unchecked_t qps_created;
++atomic_unchecked_t sw_qps_destroyed;
+
+ static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
+
+@@ -1141,7 +1141,7 @@ static struct ib_qp *nes_create_qp(struc
+ if (init_attr->create_flags)
+ return ERR_PTR(-EINVAL);
+
+- atomic_inc(&qps_created);
++ atomic_inc_unchecked(&qps_created);
+ switch (init_attr->qp_type) {
+ case IB_QPT_RC:
+ if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) {
+@@ -1470,7 +1470,7 @@ static int nes_destroy_qp(struct ib_qp *
+ struct iw_cm_event cm_event;
+ int ret;
+
+- atomic_inc(&sw_qps_destroyed);
++ atomic_inc_unchecked(&sw_qps_destroyed);
+ nesqp->destroyed = 1;
+
+ /* Blow away the connection if it exists. */
+diff -urNp linux-2.6.38.7/drivers/infiniband/hw/qib/qib.h linux-2.6.38.7/drivers/infiniband/hw/qib/qib.h
+--- linux-2.6.38.7/drivers/infiniband/hw/qib/qib.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/infiniband/hw/qib/qib.h 2011-04-28 19:34:15.000000000 -0400
+@@ -51,6 +51,7 @@
+ #include <linux/completion.h>
+ #include <linux/kref.h>
+ #include <linux/sched.h>
++#include <linux/slab.h>
+
+ #include "qib_common.h"
+ #include "qib_verbs.h"
+diff -urNp linux-2.6.38.7/drivers/input/gameport/gameport.c linux-2.6.38.7/drivers/input/gameport/gameport.c
+--- linux-2.6.38.7/drivers/input/gameport/gameport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/input/gameport/gameport.c 2011-04-28 19:57:25.000000000 -0400
+@@ -488,14 +488,14 @@ EXPORT_SYMBOL(gameport_set_phys);
+ */
+ static void gameport_init_port(struct gameport *gameport)
+ {
+- static atomic_t gameport_no = ATOMIC_INIT(0);
++ static atomic_unchecked_t gameport_no = ATOMIC_INIT(0);
+
+ __module_get(THIS_MODULE);
+
+ mutex_init(&gameport->drv_mutex);
+ device_initialize(&gameport->dev);
+ dev_set_name(&gameport->dev, "gameport%lu",
+- (unsigned long)atomic_inc_return(&gameport_no) - 1);
++ (unsigned long)atomic_inc_return_unchecked(&gameport_no) - 1);
+ gameport->dev.bus = &gameport_bus;
+ gameport->dev.release = gameport_release_port;
+ if (gameport->parent)
+diff -urNp linux-2.6.38.7/drivers/input/input.c linux-2.6.38.7/drivers/input/input.c
+--- linux-2.6.38.7/drivers/input/input.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/input/input.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1820,7 +1820,7 @@ static void input_cleanse_bitmasks(struc
+ */
+ int input_register_device(struct input_dev *dev)
+ {
+- static atomic_t input_no = ATOMIC_INIT(0);
++ static atomic_unchecked_t input_no = ATOMIC_INIT(0);
+ struct input_handler *handler;
+ const char *path;
+ int error;
+@@ -1853,7 +1853,7 @@ int input_register_device(struct input_d
+ dev->setkeycode_new = input_default_setkeycode;
+
+ dev_set_name(&dev->dev, "input%ld",
+- (unsigned long) atomic_inc_return(&input_no) - 1);
++ (unsigned long) atomic_inc_return_unchecked(&input_no) - 1);
+
+ error = device_add(&dev->dev);
+ if (error)
+diff -urNp linux-2.6.38.7/drivers/input/joystick/sidewinder.c linux-2.6.38.7/drivers/input/joystick/sidewinder.c
+--- linux-2.6.38.7/drivers/input/joystick/sidewinder.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/input/joystick/sidewinder.c 2011-05-18 20:23:44.000000000 -0400
+@@ -30,6 +30,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/sched.h>
+ #include <linux/init.h>
+ #include <linux/input.h>
+ #include <linux/gameport.h>
+@@ -428,6 +429,8 @@ static int sw_read(struct sw *sw)
+ unsigned char buf[SW_LENGTH];
+ int i;
+
++ pax_track_stack();
++
+ i = sw_read_packet(sw->gameport, buf, sw->length, 0);
+
+ if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) { /* Broken packet, try to fix */
+diff -urNp linux-2.6.38.7/drivers/input/joystick/xpad.c linux-2.6.38.7/drivers/input/joystick/xpad.c
+--- linux-2.6.38.7/drivers/input/joystick/xpad.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/input/joystick/xpad.c 2011-04-28 19:57:25.000000000 -0400
+@@ -689,7 +689,7 @@ static void xpad_led_set(struct led_clas
+
+ static int xpad_led_probe(struct usb_xpad *xpad)
+ {
+- static atomic_t led_seq = ATOMIC_INIT(0);
++ static atomic_unchecked_t led_seq = ATOMIC_INIT(0);
+ long led_no;
+ struct xpad_led *led;
+ struct led_classdev *led_cdev;
+@@ -702,7 +702,7 @@ static int xpad_led_probe(struct usb_xpa
+ if (!led)
+ return -ENOMEM;
+
+- led_no = (long)atomic_inc_return(&led_seq) - 1;
++ led_no = (long)atomic_inc_return_unchecked(&led_seq) - 1;
+
+ snprintf(led->name, sizeof(led->name), "xpad%ld", led_no);
+ led->xpad = xpad;
+diff -urNp linux-2.6.38.7/drivers/input/mousedev.c linux-2.6.38.7/drivers/input/mousedev.c
+--- linux-2.6.38.7/drivers/input/mousedev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/input/mousedev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -764,7 +764,7 @@ static ssize_t mousedev_read(struct file
+
+ spin_unlock_irq(&client->packet_lock);
+
+- if (copy_to_user(buffer, data, count))
++ if (count > sizeof(data) || copy_to_user(buffer, data, count))
+ return -EFAULT;
+
+ return count;
+diff -urNp linux-2.6.38.7/drivers/input/serio/serio.c linux-2.6.38.7/drivers/input/serio/serio.c
+--- linux-2.6.38.7/drivers/input/serio/serio.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/input/serio/serio.c 2011-04-28 19:57:25.000000000 -0400
+@@ -497,7 +497,7 @@ static void serio_release_port(struct de
+ */
+ static void serio_init_port(struct serio *serio)
+ {
+- static atomic_t serio_no = ATOMIC_INIT(0);
++ static atomic_unchecked_t serio_no = ATOMIC_INIT(0);
+
+ __module_get(THIS_MODULE);
+
+@@ -508,7 +508,7 @@ static void serio_init_port(struct serio
+ mutex_init(&serio->drv_mutex);
+ device_initialize(&serio->dev);
+ dev_set_name(&serio->dev, "serio%ld",
+- (long)atomic_inc_return(&serio_no) - 1);
++ (long)atomic_inc_return_unchecked(&serio_no) - 1);
+ serio->dev.bus = &serio_bus;
+ serio->dev.release = serio_release_port;
+ serio->dev.groups = serio_device_attr_groups;
+diff -urNp linux-2.6.38.7/drivers/isdn/capi/capi.c linux-2.6.38.7/drivers/isdn/capi/capi.c
+--- linux-2.6.38.7/drivers/isdn/capi/capi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/capi/capi.c 2011-04-28 19:57:25.000000000 -0400
+@@ -89,8 +89,8 @@ struct capiminor {
+
+ struct capi20_appl *ap;
+ u32 ncci;
+- atomic_t datahandle;
+- atomic_t msgid;
++ atomic_unchecked_t datahandle;
++ atomic_unchecked_t msgid;
+
+ struct tty_port port;
+ int ttyinstop;
+@@ -414,7 +414,7 @@ gen_data_b3_resp_for(struct capiminor *m
+ capimsg_setu16(s, 2, mp->ap->applid);
+ capimsg_setu8 (s, 4, CAPI_DATA_B3);
+ capimsg_setu8 (s, 5, CAPI_RESP);
+- capimsg_setu16(s, 6, atomic_inc_return(&mp->msgid));
++ capimsg_setu16(s, 6, atomic_inc_return_unchecked(&mp->msgid));
+ capimsg_setu32(s, 8, mp->ncci);
+ capimsg_setu16(s, 12, datahandle);
+ }
+@@ -547,14 +547,14 @@ static void handle_minor_send(struct cap
+ mp->outbytes -= len;
+ spin_unlock_bh(&mp->outlock);
+
+- datahandle = atomic_inc_return(&mp->datahandle);
++ datahandle = atomic_inc_return_unchecked(&mp->datahandle);
+ skb_push(skb, CAPI_DATA_B3_REQ_LEN);
+ memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
+ capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
+ capimsg_setu16(skb->data, 2, mp->ap->applid);
+ capimsg_setu8 (skb->data, 4, CAPI_DATA_B3);
+ capimsg_setu8 (skb->data, 5, CAPI_REQ);
+- capimsg_setu16(skb->data, 6, atomic_inc_return(&mp->msgid));
++ capimsg_setu16(skb->data, 6, atomic_inc_return_unchecked(&mp->msgid));
+ capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
+ capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
+ capimsg_setu16(skb->data, 16, len); /* Data length */
+diff -urNp linux-2.6.38.7/drivers/isdn/gigaset/common.c linux-2.6.38.7/drivers/isdn/gigaset/common.c
+--- linux-2.6.38.7/drivers/isdn/gigaset/common.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/gigaset/common.c 2011-04-28 19:34:15.000000000 -0400
+@@ -723,7 +723,7 @@ struct cardstate *gigaset_initcs(struct
+ cs->commands_pending = 0;
+ cs->cur_at_seq = 0;
+ cs->gotfwver = -1;
+- cs->open_count = 0;
++ local_set(&cs->open_count, 0);
+ cs->dev = NULL;
+ cs->tty = NULL;
+ cs->tty_dev = NULL;
+diff -urNp linux-2.6.38.7/drivers/isdn/gigaset/gigaset.h linux-2.6.38.7/drivers/isdn/gigaset/gigaset.h
+--- linux-2.6.38.7/drivers/isdn/gigaset/gigaset.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/gigaset/gigaset.h 2011-04-28 19:34:15.000000000 -0400
+@@ -35,6 +35,7 @@
+ #include <linux/tty_driver.h>
+ #include <linux/list.h>
+ #include <asm/atomic.h>
++#include <asm/local.h>
+
+ #define GIG_VERSION {0, 5, 0, 0}
+ #define GIG_COMPAT {0, 4, 0, 0}
+@@ -433,7 +434,7 @@ struct cardstate {
+ spinlock_t cmdlock;
+ unsigned curlen, cmdbytes;
+
+- unsigned open_count;
++ local_t open_count;
+ struct tty_struct *tty;
+ struct tasklet_struct if_wake_tasklet;
+ unsigned control_state;
+diff -urNp linux-2.6.38.7/drivers/isdn/gigaset/interface.c linux-2.6.38.7/drivers/isdn/gigaset/interface.c
+--- linux-2.6.38.7/drivers/isdn/gigaset/interface.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/gigaset/interface.c 2011-04-28 19:34:15.000000000 -0400
+@@ -160,9 +160,7 @@ static int if_open(struct tty_struct *tt
+ return -ERESTARTSYS;
+ tty->driver_data = cs;
+
+- ++cs->open_count;
+-
+- if (cs->open_count == 1) {
++ if (local_inc_return(&cs->open_count) == 1) {
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->tty = tty;
+ spin_unlock_irqrestore(&cs->lock, flags);
+@@ -190,10 +188,10 @@ static void if_close(struct tty_struct *
+
+ if (!cs->connected)
+ gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */
+- else if (!cs->open_count)
++ else if (!local_read(&cs->open_count))
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
+ else {
+- if (!--cs->open_count) {
++ if (!local_dec_return(&cs->open_count)) {
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->tty = NULL;
+ spin_unlock_irqrestore(&cs->lock, flags);
+@@ -228,7 +226,7 @@ static int if_ioctl(struct tty_struct *t
+ if (!cs->connected) {
+ gig_dbg(DEBUG_IF, "not connected");
+ retval = -ENODEV;
+- } else if (!cs->open_count)
++ } else if (!local_read(&cs->open_count))
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
+ else {
+ retval = 0;
+@@ -358,7 +356,7 @@ static int if_write(struct tty_struct *t
+ retval = -ENODEV;
+ goto done;
+ }
+- if (!cs->open_count) {
++ if (!local_read(&cs->open_count)) {
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
+ retval = -ENODEV;
+ goto done;
+@@ -411,7 +409,7 @@ static int if_write_room(struct tty_stru
+ if (!cs->connected) {
+ gig_dbg(DEBUG_IF, "not connected");
+ retval = -ENODEV;
+- } else if (!cs->open_count)
++ } else if (!local_read(&cs->open_count))
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
+ else if (cs->mstate != MS_LOCKED) {
+ dev_warn(cs->dev, "can't write to unlocked device\n");
+@@ -441,7 +439,7 @@ static int if_chars_in_buffer(struct tty
+
+ if (!cs->connected)
+ gig_dbg(DEBUG_IF, "not connected");
+- else if (!cs->open_count)
++ else if (!local_read(&cs->open_count))
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
+ else if (cs->mstate != MS_LOCKED)
+ dev_warn(cs->dev, "can't write to unlocked device\n");
+@@ -469,7 +467,7 @@ static void if_throttle(struct tty_struc
+
+ if (!cs->connected)
+ gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */
+- else if (!cs->open_count)
++ else if (!local_read(&cs->open_count))
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
+ else
+ gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__);
+@@ -493,7 +491,7 @@ static void if_unthrottle(struct tty_str
+
+ if (!cs->connected)
+ gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */
+- else if (!cs->open_count)
++ else if (!local_read(&cs->open_count))
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
+ else
+ gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__);
+@@ -524,7 +522,7 @@ static void if_set_termios(struct tty_st
+ goto out;
+ }
+
+- if (!cs->open_count) {
++ if (!local_read(&cs->open_count)) {
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
+ goto out;
+ }
+diff -urNp linux-2.6.38.7/drivers/isdn/hardware/avm/b1.c linux-2.6.38.7/drivers/isdn/hardware/avm/b1.c
+--- linux-2.6.38.7/drivers/isdn/hardware/avm/b1.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/hardware/avm/b1.c 2011-04-28 19:34:15.000000000 -0400
+@@ -176,7 +176,7 @@ int b1_load_t4file(avmcard *card, capilo
+ }
+ if (left) {
+ if (t4file->user) {
+- if (copy_from_user(buf, dp, left))
++ if (left > sizeof buf || copy_from_user(buf, dp, left))
+ return -EFAULT;
+ } else {
+ memcpy(buf, dp, left);
+@@ -224,7 +224,7 @@ int b1_load_config(avmcard *card, capilo
+ }
+ if (left) {
+ if (config->user) {
+- if (copy_from_user(buf, dp, left))
++ if (left > sizeof buf || copy_from_user(buf, dp, left))
+ return -EFAULT;
+ } else {
+ memcpy(buf, dp, left);
+diff -urNp linux-2.6.38.7/drivers/isdn/hardware/eicon/capidtmf.c linux-2.6.38.7/drivers/isdn/hardware/eicon/capidtmf.c
+--- linux-2.6.38.7/drivers/isdn/hardware/eicon/capidtmf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/hardware/eicon/capidtmf.c 2011-05-16 21:47:08.000000000 -0400
+@@ -498,6 +498,7 @@ void capidtmf_recv_block (t_capidtmf_sta
+ byte goertzel_result_buffer[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
+ short windowed_sample_buffer[CAPIDTMF_RECV_WINDOWED_SAMPLES];
+
++ pax_track_stack();
+
+ if (p_state->recv.state & CAPIDTMF_RECV_STATE_DTMF_ACTIVE)
+ {
+diff -urNp linux-2.6.38.7/drivers/isdn/hardware/eicon/capifunc.c linux-2.6.38.7/drivers/isdn/hardware/eicon/capifunc.c
+--- linux-2.6.38.7/drivers/isdn/hardware/eicon/capifunc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/hardware/eicon/capifunc.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1055,6 +1055,8 @@ static int divacapi_connect_didd(void)
+ IDI_SYNC_REQ req;
+ DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
++ pax_track_stack();
++
+ DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+ for (x = 0; x < MAX_DESCRIPTORS; x++) {
+diff -urNp linux-2.6.38.7/drivers/isdn/hardware/eicon/diddfunc.c linux-2.6.38.7/drivers/isdn/hardware/eicon/diddfunc.c
+--- linux-2.6.38.7/drivers/isdn/hardware/eicon/diddfunc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/hardware/eicon/diddfunc.c 2011-05-16 21:47:08.000000000 -0400
+@@ -54,6 +54,8 @@ static int DIVA_INIT_FUNCTION connect_di
+ IDI_SYNC_REQ req;
+ DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
++ pax_track_stack();
++
+ DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+ for (x = 0; x < MAX_DESCRIPTORS; x++) {
+diff -urNp linux-2.6.38.7/drivers/isdn/hardware/eicon/divasfunc.c linux-2.6.38.7/drivers/isdn/hardware/eicon/divasfunc.c
+--- linux-2.6.38.7/drivers/isdn/hardware/eicon/divasfunc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/hardware/eicon/divasfunc.c 2011-05-16 21:47:08.000000000 -0400
+@@ -161,6 +161,8 @@ static int DIVA_INIT_FUNCTION connect_di
+ IDI_SYNC_REQ req;
+ DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
++ pax_track_stack();
++
+ DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+ for (x = 0; x < MAX_DESCRIPTORS; x++) {
+diff -urNp linux-2.6.38.7/drivers/isdn/hardware/eicon/idifunc.c linux-2.6.38.7/drivers/isdn/hardware/eicon/idifunc.c
+--- linux-2.6.38.7/drivers/isdn/hardware/eicon/idifunc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/hardware/eicon/idifunc.c 2011-05-16 21:47:08.000000000 -0400
+@@ -188,6 +188,8 @@ static int DIVA_INIT_FUNCTION connect_di
+ IDI_SYNC_REQ req;
+ DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
++ pax_track_stack();
++
+ DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+ for (x = 0; x < MAX_DESCRIPTORS; x++) {
+diff -urNp linux-2.6.38.7/drivers/isdn/hardware/eicon/message.c linux-2.6.38.7/drivers/isdn/hardware/eicon/message.c
+--- linux-2.6.38.7/drivers/isdn/hardware/eicon/message.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/hardware/eicon/message.c 2011-05-16 21:47:08.000000000 -0400
+@@ -4889,6 +4889,8 @@ static void sig_ind(PLCI *plci)
+ dword d;
+ word w;
+
++ pax_track_stack();
++
+ a = plci->adapter;
+ Id = ((word)plci->Id<<8)|a->Id;
+ PUT_WORD(&SS_Ind[4],0x0000);
+@@ -7484,6 +7486,8 @@ static word add_b1(PLCI *plci, API_PARSE
+ word j, n, w;
+ dword d;
+
++ pax_track_stack();
++
+
+ for(i=0;i<8;i++) bp_parms[i].length = 0;
+ for(i=0;i<2;i++) global_config[i].length = 0;
+@@ -7958,6 +7962,8 @@ static word add_b23(PLCI *plci, API_PARS
+ const byte llc3[] = {4,3,2,2,6,6,0};
+ const byte header[] = {0,2,3,3,0,0,0};
+
++ pax_track_stack();
++
+ for(i=0;i<8;i++) bp_parms[i].length = 0;
+ for(i=0;i<6;i++) b2_config_parms[i].length = 0;
+ for(i=0;i<5;i++) b3_config_parms[i].length = 0;
+@@ -14760,6 +14766,8 @@ static void group_optimization(DIVA_CAPI
+ word appl_number_group_type[MAX_APPL];
+ PLCI *auxplci;
+
++ pax_track_stack();
++
+ set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
+
+ if(!a->group_optimization_enabled)
+diff -urNp linux-2.6.38.7/drivers/isdn/hardware/eicon/mntfunc.c linux-2.6.38.7/drivers/isdn/hardware/eicon/mntfunc.c
+--- linux-2.6.38.7/drivers/isdn/hardware/eicon/mntfunc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/hardware/eicon/mntfunc.c 2011-05-16 21:47:08.000000000 -0400
+@@ -79,6 +79,8 @@ static int DIVA_INIT_FUNCTION connect_di
+ IDI_SYNC_REQ req;
+ DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
+
++ pax_track_stack();
++
+ DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
+
+ for (x = 0; x < MAX_DESCRIPTORS; x++) {
+diff -urNp linux-2.6.38.7/drivers/isdn/i4l/isdn_common.c linux-2.6.38.7/drivers/isdn/i4l/isdn_common.c
+--- linux-2.6.38.7/drivers/isdn/i4l/isdn_common.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/i4l/isdn_common.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1292,6 +1292,8 @@ isdn_ioctl(struct file *file, uint cmd,
+ } iocpar;
+ void __user *argp = (void __user *)arg;
+
++ pax_track_stack();
++
+ #define name iocpar.name
+ #define bname iocpar.bname
+ #define iocts iocpar.iocts
+diff -urNp linux-2.6.38.7/drivers/isdn/icn/icn.c linux-2.6.38.7/drivers/isdn/icn/icn.c
+--- linux-2.6.38.7/drivers/isdn/icn/icn.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/isdn/icn/icn.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1045,7 +1045,7 @@ icn_writecmd(const u_char * buf, int len
+ if (count > len)
+ count = len;
+ if (user) {
+- if (copy_from_user(msg, buf, count))
++ if (count > sizeof msg || copy_from_user(msg, buf, count))
+ return -EFAULT;
+ } else
+ memcpy(msg, buf, count);
+diff -urNp linux-2.6.38.7/drivers/lguest/core.c linux-2.6.38.7/drivers/lguest/core.c
+--- linux-2.6.38.7/drivers/lguest/core.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/lguest/core.c 2011-04-28 19:34:15.000000000 -0400
+@@ -92,9 +92,17 @@ static __init int map_switcher(void)
+ * it's worked so far. The end address needs +1 because __get_vm_area
+ * allocates an extra guard page, so we need space for that.
+ */
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
++ VM_ALLOC | VM_KERNEXEC, SWITCHER_ADDR, SWITCHER_ADDR
++ + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
++#else
+ switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
+ VM_ALLOC, SWITCHER_ADDR, SWITCHER_ADDR
+ + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
++#endif
++
+ if (!switcher_vma) {
+ err = -ENOMEM;
+ printk("lguest: could not map switcher pages high\n");
+@@ -119,7 +127,7 @@ static __init int map_switcher(void)
+ * Now the Switcher is mapped at the right address, we can't fail!
+ * Copy in the compiled-in Switcher code (from <arch>_switcher.S).
+ */
+- memcpy(switcher_vma->addr, start_switcher_text,
++ memcpy(switcher_vma->addr, ktla_ktva(start_switcher_text),
+ end_switcher_text - start_switcher_text);
+
+ printk(KERN_INFO "lguest: mapped switcher at %p\n",
+diff -urNp linux-2.6.38.7/drivers/lguest/x86/core.c linux-2.6.38.7/drivers/lguest/x86/core.c
+--- linux-2.6.38.7/drivers/lguest/x86/core.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/lguest/x86/core.c 2011-04-28 19:34:15.000000000 -0400
+@@ -59,7 +59,7 @@ static struct {
+ /* Offset from where switcher.S was compiled to where we've copied it */
+ static unsigned long switcher_offset(void)
+ {
+- return SWITCHER_ADDR - (unsigned long)start_switcher_text;
++ return SWITCHER_ADDR - (unsigned long)ktla_ktva(start_switcher_text);
+ }
+
+ /* This cpu's struct lguest_pages. */
+@@ -100,7 +100,13 @@ static void copy_in_guest_info(struct lg
+ * These copies are pretty cheap, so we do them unconditionally: */
+ /* Save the current Host top-level page directory.
+ */
++
++#ifdef CONFIG_PAX_PER_CPU_PGD
++ pages->state.host_cr3 = read_cr3();
++#else
+ pages->state.host_cr3 = __pa(current->mm->pgd);
++#endif
++
+ /*
+ * Set up the Guest's page tables to see this CPU's pages (and no
+ * other CPU's pages).
+@@ -547,7 +553,7 @@ void __init lguest_arch_host_init(void)
+ * compiled-in switcher code and the high-mapped copy we just made.
+ */
+ for (i = 0; i < IDT_ENTRIES; i++)
+- default_idt_entries[i] += switcher_offset();
++ default_idt_entries[i] = ktla_ktva(default_idt_entries[i]) + switcher_offset();
+
+ /*
+ * Set up the Switcher's per-cpu areas.
+@@ -630,7 +636,7 @@ void __init lguest_arch_host_init(void)
+ * it will be undisturbed when we switch. To change %cs and jump we
+ * need this structure to feed to Intel's "lcall" instruction.
+ */
+- lguest_entry.offset = (long)switch_to_guest + switcher_offset();
++ lguest_entry.offset = (long)ktla_ktva(switch_to_guest) + switcher_offset();
+ lguest_entry.segment = LGUEST_CS;
+
+ /*
+diff -urNp linux-2.6.38.7/drivers/lguest/x86/switcher_32.S linux-2.6.38.7/drivers/lguest/x86/switcher_32.S
+--- linux-2.6.38.7/drivers/lguest/x86/switcher_32.S 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/lguest/x86/switcher_32.S 2011-04-28 19:34:15.000000000 -0400
+@@ -87,6 +87,7 @@
+ #include <asm/page.h>
+ #include <asm/segment.h>
+ #include <asm/lguest.h>
++#include <asm/processor-flags.h>
+
+ // We mark the start of the code to copy
+ // It's placed in .text tho it's never run here
+@@ -149,6 +150,13 @@ ENTRY(switch_to_guest)
+ // Changes type when we load it: damn Intel!
+ // For after we switch over our page tables
+ // That entry will be read-only: we'd crash.
++
++#ifdef CONFIG_PAX_KERNEXEC
++ mov %cr0, %edx
++ xor $X86_CR0_WP, %edx
++ mov %edx, %cr0
++#endif
++
+ movl $(GDT_ENTRY_TSS*8), %edx
+ ltr %dx
+
+@@ -157,9 +165,15 @@ ENTRY(switch_to_guest)
+ // Let's clear it again for our return.
+ // The GDT descriptor of the Host
+ // Points to the table after two "size" bytes
+- movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx
++ movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %eax
+ // Clear "used" from type field (byte 5, bit 2)
+- andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx)
++ andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%eax)
++
++#ifdef CONFIG_PAX_KERNEXEC
++ mov %cr0, %eax
++ xor $X86_CR0_WP, %eax
++ mov %eax, %cr0
++#endif
+
+ // Once our page table's switched, the Guest is live!
+ // The Host fades as we run this final step.
+@@ -295,13 +309,12 @@ deliver_to_host:
+ // I consulted gcc, and it gave
+ // These instructions, which I gladly credit:
+ leal (%edx,%ebx,8), %eax
+- movzwl (%eax),%edx
+- movl 4(%eax), %eax
+- xorw %ax, %ax
+- orl %eax, %edx
++ movl 4(%eax), %edx
++ movw (%eax), %dx
+ // Now the address of the handler's in %edx
+ // We call it now: its "iret" drops us home.
+- jmp *%edx
++ ljmp $__KERNEL_CS, $1f
++1: jmp *%edx
+
+ // Every interrupt can come to us here
+ // But we must truly tell each apart.
+diff -urNp linux-2.6.38.7/drivers/md/dm.c linux-2.6.38.7/drivers/md/dm.c
+--- linux-2.6.38.7/drivers/md/dm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/dm.c 2011-04-28 19:57:25.000000000 -0400
+@@ -162,9 +162,9 @@ struct mapped_device {
+ /*
+ * Event handling.
+ */
+- atomic_t event_nr;
++ atomic_unchecked_t event_nr;
+ wait_queue_head_t eventq;
+- atomic_t uevent_seq;
++ atomic_unchecked_t uevent_seq;
+ struct list_head uevent_list;
+ spinlock_t uevent_lock; /* Protect access to uevent_list */
+
+@@ -1855,8 +1855,8 @@ static struct mapped_device *alloc_dev(i
+ rwlock_init(&md->map_lock);
+ atomic_set(&md->holders, 1);
+ atomic_set(&md->open_count, 0);
+- atomic_set(&md->event_nr, 0);
+- atomic_set(&md->uevent_seq, 0);
++ atomic_set_unchecked(&md->event_nr, 0);
++ atomic_set_unchecked(&md->uevent_seq, 0);
+ INIT_LIST_HEAD(&md->uevent_list);
+ spin_lock_init(&md->uevent_lock);
+
+@@ -1990,7 +1990,7 @@ static void event_callback(void *context
+
+ dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj);
+
+- atomic_inc(&md->event_nr);
++ atomic_inc_unchecked(&md->event_nr);
+ wake_up(&md->eventq);
+ }
+
+@@ -2569,18 +2569,18 @@ int dm_kobject_uevent(struct mapped_devi
+
+ uint32_t dm_next_uevent_seq(struct mapped_device *md)
+ {
+- return atomic_add_return(1, &md->uevent_seq);
++ return atomic_add_return_unchecked(1, &md->uevent_seq);
+ }
+
+ uint32_t dm_get_event_nr(struct mapped_device *md)
+ {
+- return atomic_read(&md->event_nr);
++ return atomic_read_unchecked(&md->event_nr);
+ }
+
+ int dm_wait_event(struct mapped_device *md, int event_nr)
+ {
+ return wait_event_interruptible(md->eventq,
+- (event_nr != atomic_read(&md->event_nr)));
++ (event_nr != atomic_read_unchecked(&md->event_nr)));
+ }
+
+ void dm_uevent_add(struct mapped_device *md, struct list_head *elist)
+diff -urNp linux-2.6.38.7/drivers/md/dm-ioctl.c linux-2.6.38.7/drivers/md/dm-ioctl.c
+--- linux-2.6.38.7/drivers/md/dm-ioctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/dm-ioctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1541,7 +1541,7 @@ static int validate_params(uint cmd, str
+ cmd == DM_LIST_VERSIONS_CMD)
+ return 0;
+
+- if ((cmd == DM_DEV_CREATE_CMD)) {
++ if (cmd == DM_DEV_CREATE_CMD) {
+ if (!*param->name) {
+ DMWARN("name not supplied when creating device");
+ return -EINVAL;
+diff -urNp linux-2.6.38.7/drivers/md/dm-raid1.c linux-2.6.38.7/drivers/md/dm-raid1.c
+--- linux-2.6.38.7/drivers/md/dm-raid1.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/dm-raid1.c 2011-04-28 19:57:25.000000000 -0400
+@@ -42,7 +42,7 @@ enum dm_raid1_error {
+
+ struct mirror {
+ struct mirror_set *ms;
+- atomic_t error_count;
++ atomic_unchecked_t error_count;
+ unsigned long error_type;
+ struct dm_dev *dev;
+ sector_t offset;
+@@ -187,7 +187,7 @@ static struct mirror *get_valid_mirror(s
+ struct mirror *m;
+
+ for (m = ms->mirror; m < ms->mirror + ms->nr_mirrors; m++)
+- if (!atomic_read(&m->error_count))
++ if (!atomic_read_unchecked(&m->error_count))
+ return m;
+
+ return NULL;
+@@ -219,7 +219,7 @@ static void fail_mirror(struct mirror *m
+ * simple way to tell if a device has encountered
+ * errors.
+ */
+- atomic_inc(&m->error_count);
++ atomic_inc_unchecked(&m->error_count);
+
+ if (test_and_set_bit(error_type, &m->error_type))
+ return;
+@@ -410,7 +410,7 @@ static struct mirror *choose_mirror(stru
+ struct mirror *m = get_default_mirror(ms);
+
+ do {
+- if (likely(!atomic_read(&m->error_count)))
++ if (likely(!atomic_read_unchecked(&m->error_count)))
+ return m;
+
+ if (m-- == ms->mirror)
+@@ -424,7 +424,7 @@ static int default_ok(struct mirror *m)
+ {
+ struct mirror *default_mirror = get_default_mirror(m->ms);
+
+- return !atomic_read(&default_mirror->error_count);
++ return !atomic_read_unchecked(&default_mirror->error_count);
+ }
+
+ static int mirror_available(struct mirror_set *ms, struct bio *bio)
+@@ -561,7 +561,7 @@ static void do_reads(struct mirror_set *
+ */
+ if (likely(region_in_sync(ms, region, 1)))
+ m = choose_mirror(ms, bio->bi_sector);
+- else if (m && atomic_read(&m->error_count))
++ else if (m && atomic_read_unchecked(&m->error_count))
+ m = NULL;
+
+ if (likely(m))
+@@ -941,7 +941,7 @@ static int get_mirror(struct mirror_set
+ }
+
+ ms->mirror[mirror].ms = ms;
+- atomic_set(&(ms->mirror[mirror].error_count), 0);
++ atomic_set_unchecked(&(ms->mirror[mirror].error_count), 0);
+ ms->mirror[mirror].error_type = 0;
+ ms->mirror[mirror].offset = offset;
+
+@@ -1349,7 +1349,7 @@ static void mirror_resume(struct dm_targ
+ */
+ static char device_status_char(struct mirror *m)
+ {
+- if (!atomic_read(&(m->error_count)))
++ if (!atomic_read_unchecked(&(m->error_count)))
+ return 'A';
+
+ return (test_bit(DM_RAID1_FLUSH_ERROR, &(m->error_type))) ? 'F' :
+diff -urNp linux-2.6.38.7/drivers/md/dm-stripe.c linux-2.6.38.7/drivers/md/dm-stripe.c
+--- linux-2.6.38.7/drivers/md/dm-stripe.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/dm-stripe.c 2011-04-28 19:57:25.000000000 -0400
+@@ -20,7 +20,7 @@ struct stripe {
+ struct dm_dev *dev;
+ sector_t physical_start;
+
+- atomic_t error_count;
++ atomic_unchecked_t error_count;
+ };
+
+ struct stripe_c {
+@@ -192,7 +192,7 @@ static int stripe_ctr(struct dm_target *
+ kfree(sc);
+ return r;
+ }
+- atomic_set(&(sc->stripe[i].error_count), 0);
++ atomic_set_unchecked(&(sc->stripe[i].error_count), 0);
+ }
+
+ ti->private = sc;
+@@ -314,7 +314,7 @@ static int stripe_status(struct dm_targe
+ DMEMIT("%d ", sc->stripes);
+ for (i = 0; i < sc->stripes; i++) {
+ DMEMIT("%s ", sc->stripe[i].dev->name);
+- buffer[i] = atomic_read(&(sc->stripe[i].error_count)) ?
++ buffer[i] = atomic_read_unchecked(&(sc->stripe[i].error_count)) ?
+ 'D' : 'A';
+ }
+ buffer[i] = '\0';
+@@ -361,8 +361,8 @@ static int stripe_end_io(struct dm_targe
+ */
+ for (i = 0; i < sc->stripes; i++)
+ if (!strcmp(sc->stripe[i].dev->name, major_minor)) {
+- atomic_inc(&(sc->stripe[i].error_count));
+- if (atomic_read(&(sc->stripe[i].error_count)) <
++ atomic_inc_unchecked(&(sc->stripe[i].error_count));
++ if (atomic_read_unchecked(&(sc->stripe[i].error_count)) <
+ DM_IO_ERROR_THRESHOLD)
+ schedule_work(&sc->trigger_event);
+ }
+diff -urNp linux-2.6.38.7/drivers/md/dm-table.c linux-2.6.38.7/drivers/md/dm-table.c
+--- linux-2.6.38.7/drivers/md/dm-table.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/dm-table.c 2011-04-28 19:34:15.000000000 -0400
+@@ -372,7 +372,7 @@ static int device_area_is_invalid(struct
+ if (!dev_size)
+ return 0;
+
+- if ((start >= dev_size) || (start + len > dev_size)) {
++ if ((start >= dev_size) || (len > dev_size - start)) {
+ DMWARN("%s: %s too small for target: "
+ "start=%llu, len=%llu, dev_size=%llu",
+ dm_device_name(ti->table->md), bdevname(bdev, b),
+diff -urNp linux-2.6.38.7/drivers/md/md.c linux-2.6.38.7/drivers/md/md.c
+--- linux-2.6.38.7/drivers/md/md.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/md.c 2011-04-28 19:57:25.000000000 -0400
+@@ -226,10 +226,10 @@ EXPORT_SYMBOL_GPL(bio_clone_mddev);
+ * start build, activate spare
+ */
+ static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
+-static atomic_t md_event_count;
++static atomic_unchecked_t md_event_count;
+ void md_new_event(mddev_t *mddev)
+ {
+- atomic_inc(&md_event_count);
++ atomic_inc_unchecked(&md_event_count);
+ wake_up(&md_event_waiters);
+ }
+ EXPORT_SYMBOL_GPL(md_new_event);
+@@ -239,7 +239,7 @@ EXPORT_SYMBOL_GPL(md_new_event);
+ */
+ static void md_new_event_inintr(mddev_t *mddev)
+ {
+- atomic_inc(&md_event_count);
++ atomic_inc_unchecked(&md_event_count);
+ wake_up(&md_event_waiters);
+ }
+
+@@ -1443,7 +1443,7 @@ static int super_1_load(mdk_rdev_t *rdev
+
+ rdev->preferred_minor = 0xffff;
+ rdev->data_offset = le64_to_cpu(sb->data_offset);
+- atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
++ atomic_set_unchecked(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
+
+ rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
+ bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1;
+@@ -1621,7 +1621,7 @@ static void super_1_sync(mddev_t *mddev,
+ else
+ sb->resync_offset = cpu_to_le64(0);
+
+- sb->cnt_corrected_read = cpu_to_le32(atomic_read(&rdev->corrected_errors));
++ sb->cnt_corrected_read = cpu_to_le32(atomic_read_unchecked(&rdev->corrected_errors));
+
+ sb->raid_disks = cpu_to_le32(mddev->raid_disks);
+ sb->size = cpu_to_le64(mddev->dev_sectors);
+@@ -2403,7 +2403,7 @@ __ATTR(state, S_IRUGO|S_IWUSR, state_sho
+ static ssize_t
+ errors_show(mdk_rdev_t *rdev, char *page)
+ {
+- return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors));
++ return sprintf(page, "%d\n", atomic_read_unchecked(&rdev->corrected_errors));
+ }
+
+ static ssize_t
+@@ -2412,7 +2412,7 @@ errors_store(mdk_rdev_t *rdev, const cha
+ char *e;
+ unsigned long n = simple_strtoul(buf, &e, 10);
+ if (*buf && (*e == 0 || *e == '\n')) {
+- atomic_set(&rdev->corrected_errors, n);
++ atomic_set_unchecked(&rdev->corrected_errors, n);
+ return len;
+ }
+ return -EINVAL;
+@@ -2768,8 +2768,8 @@ void md_rdev_init(mdk_rdev_t *rdev)
+ rdev->last_read_error.tv_sec = 0;
+ rdev->last_read_error.tv_nsec = 0;
+ atomic_set(&rdev->nr_pending, 0);
+- atomic_set(&rdev->read_errors, 0);
+- atomic_set(&rdev->corrected_errors, 0);
++ atomic_set_unchecked(&rdev->read_errors, 0);
++ atomic_set_unchecked(&rdev->corrected_errors, 0);
+
+ INIT_LIST_HEAD(&rdev->same_set);
+ init_waitqueue_head(&rdev->blocked_wait);
+@@ -6373,7 +6373,7 @@ static int md_seq_show(struct seq_file *
+
+ spin_unlock(&pers_lock);
+ seq_printf(seq, "\n");
+- mi->event = atomic_read(&md_event_count);
++ mi->event = atomic_read_unchecked(&md_event_count);
+ return 0;
+ }
+ if (v == (void*)2) {
+@@ -6462,7 +6462,7 @@ static int md_seq_show(struct seq_file *
+ chunk_kb ? "KB" : "B");
+ if (bitmap->file) {
+ seq_printf(seq, ", file: ");
+- seq_path(seq, &bitmap->file->f_path, " \t\n");
++ seq_path(seq, &bitmap->file->f_path, " \t\n\\");
+ }
+
+ seq_printf(seq, "\n");
+@@ -6496,7 +6496,7 @@ static int md_seq_open(struct inode *ino
+ else {
+ struct seq_file *p = file->private_data;
+ p->private = mi;
+- mi->event = atomic_read(&md_event_count);
++ mi->event = atomic_read_unchecked(&md_event_count);
+ }
+ return error;
+ }
+@@ -6512,7 +6512,7 @@ static unsigned int mdstat_poll(struct f
+ /* always allow read */
+ mask = POLLIN | POLLRDNORM;
+
+- if (mi->event != atomic_read(&md_event_count))
++ if (mi->event != atomic_read_unchecked(&md_event_count))
+ mask |= POLLERR | POLLPRI;
+ return mask;
+ }
+@@ -6556,7 +6556,7 @@ static int is_mddev_idle(mddev_t *mddev,
+ struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
+ curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
+ (int)part_stat_read(&disk->part0, sectors[1]) -
+- atomic_read(&disk->sync_io);
++ atomic_read_unchecked(&disk->sync_io);
+ /* sync IO will cause sync_io to increase before the disk_stats
+ * as sync_io is counted when a request starts, and
+ * disk_stats is counted when it completes.
+diff -urNp linux-2.6.38.7/drivers/md/md.h linux-2.6.38.7/drivers/md/md.h
+--- linux-2.6.38.7/drivers/md/md.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/md.h 2011-04-28 19:57:25.000000000 -0400
+@@ -117,13 +117,13 @@ struct mdk_rdev_s
+ * only maintained for arrays that
+ * support hot removal
+ */
+- atomic_t read_errors; /* number of consecutive read errors that
++ atomic_unchecked_t read_errors; /* number of consecutive read errors that
+ * we have tried to ignore.
+ */
+ struct timespec last_read_error; /* monotonic time since our
+ * last read error
+ */
+- atomic_t corrected_errors; /* number of corrected read errors,
++ atomic_unchecked_t corrected_errors; /* number of corrected read errors,
+ * for reporting to userspace and storing
+ * in superblock.
+ */
+@@ -360,7 +360,7 @@ static inline void rdev_dec_pending(mdk_
+
+ static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors)
+ {
+- atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
++ atomic_add_unchecked(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
+ }
+
+ struct mdk_personality
+diff -urNp linux-2.6.38.7/drivers/md/raid10.c linux-2.6.38.7/drivers/md/raid10.c
+--- linux-2.6.38.7/drivers/md/raid10.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/raid10.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1258,7 +1258,7 @@ static void end_sync_read(struct bio *bi
+ if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+ set_bit(R10BIO_Uptodate, &r10_bio->state);
+ else {
+- atomic_add(r10_bio->sectors,
++ atomic_add_unchecked(r10_bio->sectors,
+ &conf->mirrors[d].rdev->corrected_errors);
+ if (!test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
+ md_error(r10_bio->mddev,
+@@ -1466,7 +1466,7 @@ static void check_decay_read_errors(mdde
+ {
+ struct timespec cur_time_mon;
+ unsigned long hours_since_last;
+- unsigned int read_errors = atomic_read(&rdev->read_errors);
++ unsigned int read_errors = atomic_read_unchecked(&rdev->read_errors);
+
+ ktime_get_ts(&cur_time_mon);
+
+@@ -1488,9 +1488,9 @@ static void check_decay_read_errors(mdde
+ * overflowing the shift of read_errors by hours_since_last.
+ */
+ if (hours_since_last >= 8 * sizeof(read_errors))
+- atomic_set(&rdev->read_errors, 0);
++ atomic_set_unchecked(&rdev->read_errors, 0);
+ else
+- atomic_set(&rdev->read_errors, read_errors >> hours_since_last);
++ atomic_set_unchecked(&rdev->read_errors, read_errors >> hours_since_last);
+ }
+
+ /*
+@@ -1525,8 +1525,8 @@ static void fix_read_error(conf_t *conf,
+ }
+
+ check_decay_read_errors(mddev, rdev);
+- atomic_inc(&rdev->read_errors);
+- cur_read_error_count = atomic_read(&rdev->read_errors);
++ atomic_inc_unchecked(&rdev->read_errors);
++ cur_read_error_count = atomic_read_unchecked(&rdev->read_errors);
+ if (cur_read_error_count > max_read_errors) {
+ rcu_read_unlock();
+ printk(KERN_NOTICE
+@@ -1599,7 +1599,7 @@ static void fix_read_error(conf_t *conf,
+ test_bit(In_sync, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+- atomic_add(s, &rdev->corrected_errors);
++ atomic_add_unchecked(s, &rdev->corrected_errors);
+ if (sync_page_io(rdev,
+ r10_bio->devs[sl].addr +
+ sect,
+diff -urNp linux-2.6.38.7/drivers/md/raid1.c linux-2.6.38.7/drivers/md/raid1.c
+--- linux-2.6.38.7/drivers/md/raid1.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/raid1.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1392,7 +1392,7 @@ static void sync_request_write(mddev_t *
+ if (r1_bio->bios[d]->bi_end_io != end_sync_read)
+ continue;
+ rdev = conf->mirrors[d].rdev;
+- atomic_add(s, &rdev->corrected_errors);
++ atomic_add_unchecked(s, &rdev->corrected_errors);
+ if (sync_page_io(rdev,
+ sect,
+ s<<9,
+@@ -1538,7 +1538,7 @@ static void fix_read_error(conf_t *conf,
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ else {
+- atomic_add(s, &rdev->corrected_errors);
++ atomic_add_unchecked(s, &rdev->corrected_errors);
+ printk(KERN_INFO
+ "md/raid1:%s: read error corrected "
+ "(%d sectors at %llu on %s)\n",
+diff -urNp linux-2.6.38.7/drivers/md/raid5.c linux-2.6.38.7/drivers/md/raid5.c
+--- linux-2.6.38.7/drivers/md/raid5.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/md/raid5.c 2011-05-16 21:47:08.000000000 -0400
+@@ -555,7 +555,7 @@ static void ops_run_io(struct stripe_hea
+ bi->bi_next = NULL;
+ if (rw == WRITE &&
+ test_bit(R5_ReWrite, &sh->dev[i].flags))
+- atomic_add(STRIPE_SECTORS,
++ atomic_add_unchecked(STRIPE_SECTORS,
+ &rdev->corrected_errors);
+ generic_make_request(bi);
+ } else {
+@@ -1602,15 +1602,15 @@ static void raid5_end_read_request(struc
+ clear_bit(R5_ReadError, &sh->dev[i].flags);
+ clear_bit(R5_ReWrite, &sh->dev[i].flags);
+ }
+- if (atomic_read(&conf->disks[i].rdev->read_errors))
+- atomic_set(&conf->disks[i].rdev->read_errors, 0);
++ if (atomic_read_unchecked(&conf->disks[i].rdev->read_errors))
++ atomic_set_unchecked(&conf->disks[i].rdev->read_errors, 0);
+ } else {
+ const char *bdn = bdevname(conf->disks[i].rdev->bdev, b);
+ int retry = 0;
+ rdev = conf->disks[i].rdev;
+
+ clear_bit(R5_UPTODATE, &sh->dev[i].flags);
+- atomic_inc(&rdev->read_errors);
++ atomic_inc_unchecked(&rdev->read_errors);
+ if (conf->mddev->degraded >= conf->max_degraded)
+ printk_rl(KERN_WARNING
+ "md/raid:%s: read error not correctable "
+@@ -1628,7 +1628,7 @@ static void raid5_end_read_request(struc
+ (unsigned long long)(sh->sector
+ + rdev->data_offset),
+ bdn);
+- else if (atomic_read(&rdev->read_errors)
++ else if (atomic_read_unchecked(&rdev->read_errors)
+ > conf->max_nr_stripes)
+ printk(KERN_WARNING
+ "md/raid:%s: Too many read errors, failing device %s.\n",
+@@ -1953,6 +1953,7 @@ static sector_t compute_blocknr(struct s
+ sector_t r_sector;
+ struct stripe_head sh2;
+
++ pax_track_stack();
+
+ chunk_offset = sector_div(new_sector, sectors_per_chunk);
+ stripe = new_sector;
+diff -urNp linux-2.6.38.7/drivers/media/common/saa7146_hlp.c linux-2.6.38.7/drivers/media/common/saa7146_hlp.c
+--- linux-2.6.38.7/drivers/media/common/saa7146_hlp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/common/saa7146_hlp.c 2011-05-16 21:47:08.000000000 -0400
+@@ -353,6 +353,8 @@ static void calculate_clipping_registers
+
+ int x[32], y[32], w[32], h[32];
+
++ pax_track_stack();
++
+ /* clear out memory */
+ memset(&line_list[0], 0x00, sizeof(u32)*32);
+ memset(&pixel_list[0], 0x00, sizeof(u32)*32);
+diff -urNp linux-2.6.38.7/drivers/media/dvb/dvb-core/dvb_ca_en50221.c linux-2.6.38.7/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+--- linux-2.6.38.7/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2011-05-16 21:47:08.000000000 -0400
+@@ -590,6 +590,8 @@ static int dvb_ca_en50221_read_data(stru
+ u8 buf[HOST_LINK_BUF_SIZE];
+ int i;
+
++ pax_track_stack();
++
+ dprintk("%s\n", __func__);
+
+ /* check if we have space for a link buf in the rx_buffer */
+@@ -1285,6 +1287,8 @@ static ssize_t dvb_ca_en50221_io_write(s
+ unsigned long timeout;
+ int written;
+
++ pax_track_stack();
++
+ dprintk("%s\n", __func__);
+
+ /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+diff -urNp linux-2.6.38.7/drivers/media/dvb/dvb-core/dvbdev.c linux-2.6.38.7/drivers/media/dvb/dvb-core/dvbdev.c
+--- linux-2.6.38.7/drivers/media/dvb/dvb-core/dvbdev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/dvb/dvb-core/dvbdev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -192,7 +192,7 @@ int dvb_register_device(struct dvb_adapt
+ const struct dvb_device *template, void *priv, int type)
+ {
+ struct dvb_device *dvbdev;
+- struct file_operations *dvbdevfops;
++ struct file_operations *dvbdevfops; /* cannot be const, see this function */
+ struct device *clsdev;
+ int minor;
+ int id;
+diff -urNp linux-2.6.38.7/drivers/media/dvb/dvb-usb/dib0700_core.c linux-2.6.38.7/drivers/media/dvb/dvb-usb/dib0700_core.c
+--- linux-2.6.38.7/drivers/media/dvb/dvb-usb/dib0700_core.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/dvb/dvb-usb/dib0700_core.c 2011-05-16 21:47:08.000000000 -0400
+@@ -366,6 +366,8 @@ int dib0700_download_firmware(struct usb
+
+ u8 buf[260];
+
++ pax_track_stack();
++
+ while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
+ deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",
+ hx.addr, hx.len, hx.chk);
+diff -urNp linux-2.6.38.7/drivers/media/dvb/dvb-usb/lmedm04.c linux-2.6.38.7/drivers/media/dvb/dvb-usb/lmedm04.c
+--- linux-2.6.38.7/drivers/media/dvb/dvb-usb/lmedm04.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/dvb/dvb-usb/lmedm04.c 2011-05-16 21:47:08.000000000 -0400
+@@ -611,6 +611,7 @@ static int lme2510_download_firmware(str
+ packet_size = 0x31;
+ len_in = 1;
+
++ pax_track_stack();
+
+ info("FRM Starting Firmware Download");
+
+@@ -666,6 +667,8 @@ static void lme_coldreset(struct usb_dev
+ int ret = 0, len_in;
+ u8 data[512] = {0};
+
++ pax_track_stack();
++
+ data[0] = 0x0a;
+ len_in = 1;
+ info("FRM Firmware Cold Reset");
+diff -urNp linux-2.6.38.7/drivers/media/dvb/frontends/mb86a16.c linux-2.6.38.7/drivers/media/dvb/frontends/mb86a16.c
+--- linux-2.6.38.7/drivers/media/dvb/frontends/mb86a16.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/dvb/frontends/mb86a16.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1060,6 +1060,8 @@ static int mb86a16_set_fe(struct mb86a16
+ int ret = -1;
+ int sync;
+
++ pax_track_stack();
++
+ dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate);
+
+ fcp = 3000;
+diff -urNp linux-2.6.38.7/drivers/media/dvb/frontends/or51211.c linux-2.6.38.7/drivers/media/dvb/frontends/or51211.c
+--- linux-2.6.38.7/drivers/media/dvb/frontends/or51211.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/dvb/frontends/or51211.c 2011-05-16 21:47:08.000000000 -0400
+@@ -113,6 +113,8 @@ static int or51211_load_firmware (struct
+ u8 tudata[585];
+ int i;
+
++ pax_track_stack();
++
+ dprintk("Firmware is %zd bytes\n",fw->size);
+
+ /* Get eprom data */
+diff -urNp linux-2.6.38.7/drivers/media/radio/radio-cadet.c linux-2.6.38.7/drivers/media/radio/radio-cadet.c
+--- linux-2.6.38.7/drivers/media/radio/radio-cadet.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/radio/radio-cadet.c 2011-04-28 19:34:15.000000000 -0400
+@@ -349,7 +349,7 @@ static ssize_t cadet_read(struct file *f
+ readbuf[i++] = dev->rdsbuf[dev->rdsout++];
+ mutex_unlock(&dev->lock);
+
+- if (copy_to_user(data, readbuf, i))
++ if (i > sizeof readbuf || copy_to_user(data, readbuf, i))
+ return -EFAULT;
+ return i;
+ }
+diff -urNp linux-2.6.38.7/drivers/media/rc/ir-lirc-codec.c linux-2.6.38.7/drivers/media/rc/ir-lirc-codec.c
+--- linux-2.6.38.7/drivers/media/rc/ir-lirc-codec.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/rc/ir-lirc-codec.c 2011-04-28 19:34:15.000000000 -0400
+@@ -277,7 +277,7 @@ static void ir_lirc_close(void *data)
+ return;
+ }
+
+-static struct file_operations lirc_fops = {
++static const struct file_operations lirc_fops = {
+ .owner = THIS_MODULE,
+ .write = ir_lirc_transmit_ir,
+ .unlocked_ioctl = ir_lirc_ioctl,
+diff -urNp linux-2.6.38.7/drivers/media/rc/lirc_dev.c linux-2.6.38.7/drivers/media/rc/lirc_dev.c
+--- linux-2.6.38.7/drivers/media/rc/lirc_dev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/rc/lirc_dev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -151,7 +151,7 @@ static int lirc_thread(void *irctl)
+ }
+
+
+-static struct file_operations lirc_dev_fops = {
++static const struct file_operations lirc_dev_fops = {
+ .owner = THIS_MODULE,
+ .read = lirc_dev_fop_read,
+ .write = lirc_dev_fop_write,
+diff -urNp linux-2.6.38.7/drivers/media/rc/rc-main.c linux-2.6.38.7/drivers/media/rc/rc-main.c
+--- linux-2.6.38.7/drivers/media/rc/rc-main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/rc/rc-main.c 2011-04-28 19:57:25.000000000 -0400
+@@ -994,7 +994,7 @@ EXPORT_SYMBOL_GPL(rc_free_device);
+
+ int rc_register_device(struct rc_dev *dev)
+ {
+- static atomic_t devno = ATOMIC_INIT(0);
++ static atomic_unchecked_t devno = ATOMIC_INIT(0);
+ struct rc_map *rc_map;
+ const char *path;
+ int rc;
+@@ -1017,7 +1017,7 @@ int rc_register_device(struct rc_dev *de
+ if (dev->close)
+ dev->input_dev->close = ir_close;
+
+- dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1);
++ dev->devno = (unsigned long)(atomic_inc_return_unchecked(&devno) - 1);
+ dev_set_name(&dev->dev, "rc%ld", dev->devno);
+ dev_set_drvdata(&dev->dev, dev);
+ rc = device_add(&dev->dev);
+diff -urNp linux-2.6.38.7/drivers/media/video/cx18/cx18-driver.c linux-2.6.38.7/drivers/media/video/cx18/cx18-driver.c
+--- linux-2.6.38.7/drivers/media/video/cx18/cx18-driver.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/cx18/cx18-driver.c 2011-05-16 21:47:08.000000000 -0400
+@@ -60,7 +60,7 @@ static struct pci_device_id cx18_pci_tbl
+
+ MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
+
+-static atomic_t cx18_instance = ATOMIC_INIT(0);
++static atomic_unchecked_t cx18_instance = ATOMIC_INIT(0);
+
+ /* Parameter declarations */
+ static int cardtype[CX18_MAX_CARDS];
+@@ -326,6 +326,8 @@ void cx18_read_eeprom(struct cx18 *cx, s
+ struct i2c_client c;
+ u8 eedata[256];
+
++ pax_track_stack();
++
+ memset(&c, 0, sizeof(c));
+ strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name));
+ c.adapter = &cx->i2c_adap[0];
+@@ -884,7 +886,7 @@ static int __devinit cx18_probe(struct p
+ struct cx18 *cx;
+
+ /* FIXME - module parameter arrays constrain max instances */
+- i = atomic_inc_return(&cx18_instance) - 1;
++ i = atomic_inc_return_unchecked(&cx18_instance) - 1;
+ if (i >= CX18_MAX_CARDS) {
+ printk(KERN_ERR "cx18: cannot manage card %d, driver has a "
+ "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1);
+diff -urNp linux-2.6.38.7/drivers/media/video/cx23885/cx23885-input.c linux-2.6.38.7/drivers/media/video/cx23885/cx23885-input.c
+--- linux-2.6.38.7/drivers/media/video/cx23885/cx23885-input.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/cx23885/cx23885-input.c 2011-05-16 21:47:08.000000000 -0400
+@@ -53,6 +53,8 @@ static void cx23885_input_process_measur
+ bool handle = false;
+ struct ir_raw_event ir_core_event[64];
+
++ pax_track_stack();
++
+ do {
+ num = 0;
+ v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event,
+diff -urNp linux-2.6.38.7/drivers/media/video/ivtv/ivtv-driver.c linux-2.6.38.7/drivers/media/video/ivtv/ivtv-driver.c
+--- linux-2.6.38.7/drivers/media/video/ivtv/ivtv-driver.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/ivtv/ivtv-driver.c 2011-04-28 19:57:25.000000000 -0400
+@@ -80,7 +80,7 @@ static struct pci_device_id ivtv_pci_tbl
+ MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl);
+
+ /* ivtv instance counter */
+-static atomic_t ivtv_instance = ATOMIC_INIT(0);
++static atomic_unchecked_t ivtv_instance = ATOMIC_INIT(0);
+
+ /* Parameter declarations */
+ static int cardtype[IVTV_MAX_CARDS];
+diff -urNp linux-2.6.38.7/drivers/media/video/omap24xxcam.c linux-2.6.38.7/drivers/media/video/omap24xxcam.c
+--- linux-2.6.38.7/drivers/media/video/omap24xxcam.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/omap24xxcam.c 2011-04-28 19:57:25.000000000 -0400
+@@ -402,7 +402,7 @@ static void omap24xxcam_vbq_complete(str
+ spin_unlock_irqrestore(&cam->core_enable_disable_lock, flags);
+
+ do_gettimeofday(&vb->ts);
+- vb->field_count = atomic_add_return(2, &fh->field_count);
++ vb->field_count = atomic_add_return_unchecked(2, &fh->field_count);
+ if (csr & csr_error) {
+ vb->state = VIDEOBUF_ERROR;
+ if (!atomic_read(&fh->cam->in_reset)) {
+diff -urNp linux-2.6.38.7/drivers/media/video/omap24xxcam.h linux-2.6.38.7/drivers/media/video/omap24xxcam.h
+--- linux-2.6.38.7/drivers/media/video/omap24xxcam.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/omap24xxcam.h 2011-04-28 19:57:25.000000000 -0400
+@@ -533,7 +533,7 @@ struct omap24xxcam_fh {
+ spinlock_t vbq_lock; /* spinlock for the videobuf queue */
+ struct videobuf_queue vbq;
+ struct v4l2_pix_format pix; /* serialise pix by vbq->lock */
+- atomic_t field_count; /* field counter for videobuf_buffer */
++ atomic_unchecked_t field_count; /* field counter for videobuf_buffer */
+ /* accessing cam here doesn't need serialisation: it's constant */
+ struct omap24xxcam_device *cam;
+ };
+diff -urNp linux-2.6.38.7/drivers/media/video/pvrusb2/pvrusb2-eeprom.c linux-2.6.38.7/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
+--- linux-2.6.38.7/drivers/media/video/pvrusb2/pvrusb2-eeprom.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/pvrusb2/pvrusb2-eeprom.c 2011-05-16 21:47:08.000000000 -0400
+@@ -120,6 +120,8 @@ int pvr2_eeprom_analyze(struct pvr2_hdw
+ u8 *eeprom;
+ struct tveeprom tvdata;
+
++ pax_track_stack();
++
+ memset(&tvdata,0,sizeof(tvdata));
+
+ eeprom = pvr2_eeprom_fetch(hdw);
+diff -urNp linux-2.6.38.7/drivers/media/video/saa7134/saa6752hs.c linux-2.6.38.7/drivers/media/video/saa7134/saa6752hs.c
+--- linux-2.6.38.7/drivers/media/video/saa7134/saa6752hs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/saa7134/saa6752hs.c 2011-05-16 21:47:08.000000000 -0400
+@@ -682,6 +682,8 @@ static int saa6752hs_init(struct v4l2_su
+ unsigned char localPAT[256];
+ unsigned char localPMT[256];
+
++ pax_track_stack();
++
+ /* Set video format - must be done first as it resets other settings */
+ set_reg8(client, 0x41, h->video_format);
+
+diff -urNp linux-2.6.38.7/drivers/media/video/saa7164/saa7164-cmd.c linux-2.6.38.7/drivers/media/video/saa7164/saa7164-cmd.c
+--- linux-2.6.38.7/drivers/media/video/saa7164/saa7164-cmd.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/saa7164/saa7164-cmd.c 2011-05-16 21:47:08.000000000 -0400
+@@ -88,6 +88,8 @@ int saa7164_irq_dequeue(struct saa7164_d
+ u8 tmp[512];
+ dprintk(DBGLVL_CMD, "%s()\n", __func__);
+
++ pax_track_stack();
++
+ /* While any outstand message on the bus exists... */
+ do {
+
+@@ -141,6 +143,8 @@ int saa7164_cmd_dequeue(struct saa7164_d
+ u8 tmp[512];
+ dprintk(DBGLVL_CMD, "%s()\n", __func__);
+
++ pax_track_stack();
++
+ while (loop) {
+
+ struct tmComResInfo tRsp = { 0, 0, 0, 0, 0, 0 };
+diff -urNp linux-2.6.38.7/drivers/media/video/usbvision/usbvision-core.c linux-2.6.38.7/drivers/media/video/usbvision/usbvision-core.c
+--- linux-2.6.38.7/drivers/media/video/usbvision/usbvision-core.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/usbvision/usbvision-core.c 2011-05-16 21:47:08.000000000 -0400
+@@ -799,6 +799,8 @@ static enum parse_state usbvision_parse_
+ unsigned char rv, gv, bv;
+ static unsigned char *Y, *U, *V;
+
++ pax_track_stack();
++
+ frame = usbvision->cur_frame;
+ image_size = frame->frmwidth * frame->frmheight;
+ if ((frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
+diff -urNp linux-2.6.38.7/drivers/media/video/v4l2-device.c linux-2.6.38.7/drivers/media/video/v4l2-device.c
+--- linux-2.6.38.7/drivers/media/video/v4l2-device.c 2011-05-22 23:05:18.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/v4l2-device.c 2011-05-22 23:06:03.000000000 -0400
+@@ -55,9 +55,9 @@ int v4l2_device_register(struct device *
+ EXPORT_SYMBOL_GPL(v4l2_device_register);
+
+ int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
+- atomic_t *instance)
++ atomic_unchecked_t *instance)
+ {
+- int num = atomic_inc_return(instance) - 1;
++ int num = atomic_inc_return_unchecked(instance) - 1;
+ int len = strlen(basename);
+
+ if (basename[len - 1] >= '0' && basename[len - 1] <= '9')
+diff -urNp linux-2.6.38.7/drivers/media/video/videobuf-dma-sg.c linux-2.6.38.7/drivers/media/video/videobuf-dma-sg.c
+--- linux-2.6.38.7/drivers/media/video/videobuf-dma-sg.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/media/video/videobuf-dma-sg.c 2011-05-16 21:47:08.000000000 -0400
+@@ -606,6 +606,8 @@ void *videobuf_sg_alloc(size_t size)
+ {
+ struct videobuf_queue q;
+
++ pax_track_stack();
++
+ /* Required to make generic handler to call __videobuf_alloc */
+ q.int_ops = &sg_ops;
+
+diff -urNp linux-2.6.38.7/drivers/message/fusion/mptbase.c linux-2.6.38.7/drivers/message/fusion/mptbase.c
+--- linux-2.6.38.7/drivers/message/fusion/mptbase.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/message/fusion/mptbase.c 2011-04-28 19:34:15.000000000 -0400
+@@ -6683,8 +6683,13 @@ static int mpt_iocinfo_proc_show(struct
+ seq_printf(m, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
+ seq_printf(m, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", NULL, NULL);
++#else
+ seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n",
+ (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
++#endif
++
+ /*
+ * Rounding UP to nearest 4-kB boundary here...
+ */
+diff -urNp linux-2.6.38.7/drivers/message/fusion/mptsas.c linux-2.6.38.7/drivers/message/fusion/mptsas.c
+--- linux-2.6.38.7/drivers/message/fusion/mptsas.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/message/fusion/mptsas.c 2011-04-28 19:34:15.000000000 -0400
+@@ -439,6 +439,23 @@ mptsas_is_end_device(struct mptsas_devin
+ return 0;
+ }
+
++static inline void
++mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
++{
++ if (phy_info->port_details) {
++ phy_info->port_details->rphy = rphy;
++ dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
++ ioc->name, rphy));
++ }
++
++ if (rphy) {
++ dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
++ &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
++ dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
++ ioc->name, rphy, rphy->dev.release));
++ }
++}
++
+ /* no mutex */
+ static void
+ mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
+@@ -477,23 +494,6 @@ mptsas_get_rphy(struct mptsas_phyinfo *p
+ return NULL;
+ }
+
+-static inline void
+-mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
+-{
+- if (phy_info->port_details) {
+- phy_info->port_details->rphy = rphy;
+- dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
+- ioc->name, rphy));
+- }
+-
+- if (rphy) {
+- dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
+- &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
+- dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
+- ioc->name, rphy, rphy->dev.release));
+- }
+-}
+-
+ static inline struct sas_port *
+ mptsas_get_port(struct mptsas_phyinfo *phy_info)
+ {
+diff -urNp linux-2.6.38.7/drivers/message/fusion/mptscsih.c linux-2.6.38.7/drivers/message/fusion/mptscsih.c
+--- linux-2.6.38.7/drivers/message/fusion/mptscsih.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/message/fusion/mptscsih.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1268,15 +1268,16 @@ mptscsih_info(struct Scsi_Host *SChost)
+
+ h = shost_priv(SChost);
+
+- if (h) {
+- if (h->info_kbuf == NULL)
+- if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
+- return h->info_kbuf;
+- h->info_kbuf[0] = '\0';
++ if (!h)
++ return NULL;
+
+- mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
+- h->info_kbuf[size-1] = '\0';
+- }
++ if (h->info_kbuf == NULL)
++ if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
++ return h->info_kbuf;
++ h->info_kbuf[0] = '\0';
++
++ mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
++ h->info_kbuf[size-1] = '\0';
+
+ return h->info_kbuf;
+ }
+diff -urNp linux-2.6.38.7/drivers/message/i2o/i2o_config.c linux-2.6.38.7/drivers/message/i2o/i2o_config.c
+--- linux-2.6.38.7/drivers/message/i2o/i2o_config.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/message/i2o/i2o_config.c 2011-05-16 21:47:08.000000000 -0400
+@@ -781,6 +781,8 @@ static int i2o_cfg_passthru(unsigned lon
+ struct i2o_message *msg;
+ unsigned int iop;
+
++ pax_track_stack();
++
+ if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))
+ return -EFAULT;
+
+diff -urNp linux-2.6.38.7/drivers/message/i2o/i2o_proc.c linux-2.6.38.7/drivers/message/i2o/i2o_proc.c
+--- linux-2.6.38.7/drivers/message/i2o/i2o_proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/message/i2o/i2o_proc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -255,13 +255,6 @@ static char *scsi_devices[] = {
+ "Array Controller Device"
+ };
+
+-static char *chtostr(u8 * chars, int n)
+-{
+- char tmp[256];
+- tmp[0] = 0;
+- return strncat(tmp, (char *)chars, n);
+-}
+-
+ static int i2o_report_query_status(struct seq_file *seq, int block_status,
+ char *group)
+ {
+@@ -838,8 +831,7 @@ static int i2o_seq_show_ddm_table(struct
+
+ seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id);
+ seq_printf(seq, "%-#8x", ddm_table.module_id);
+- seq_printf(seq, "%-29s",
+- chtostr(ddm_table.module_name_version, 28));
++ seq_printf(seq, "%-.28s", ddm_table.module_name_version);
+ seq_printf(seq, "%9d ", ddm_table.data_size);
+ seq_printf(seq, "%8d", ddm_table.code_size);
+
+@@ -940,8 +932,8 @@ static int i2o_seq_show_drivers_stored(s
+
+ seq_printf(seq, "%-#7x", dst->i2o_vendor_id);
+ seq_printf(seq, "%-#8x", dst->module_id);
+- seq_printf(seq, "%-29s", chtostr(dst->module_name_version, 28));
+- seq_printf(seq, "%-9s", chtostr(dst->date, 8));
++ seq_printf(seq, "%-.28s", dst->module_name_version);
++ seq_printf(seq, "%-.8s", dst->date);
+ seq_printf(seq, "%8d ", dst->module_size);
+ seq_printf(seq, "%8d ", dst->mpb_size);
+ seq_printf(seq, "0x%04x", dst->module_flags);
+@@ -1272,14 +1264,10 @@ static int i2o_seq_show_dev_identity(str
+ seq_printf(seq, "Device Class : %s\n", i2o_get_class_name(work16[0]));
+ seq_printf(seq, "Owner TID : %0#5x\n", work16[2]);
+ seq_printf(seq, "Parent TID : %0#5x\n", work16[3]);
+- seq_printf(seq, "Vendor info : %s\n",
+- chtostr((u8 *) (work32 + 2), 16));
+- seq_printf(seq, "Product info : %s\n",
+- chtostr((u8 *) (work32 + 6), 16));
+- seq_printf(seq, "Description : %s\n",
+- chtostr((u8 *) (work32 + 10), 16));
+- seq_printf(seq, "Product rev. : %s\n",
+- chtostr((u8 *) (work32 + 14), 8));
++ seq_printf(seq, "Vendor info : %.16s\n", (u8 *) (work32 + 2));
++ seq_printf(seq, "Product info : %.16s\n", (u8 *) (work32 + 6));
++ seq_printf(seq, "Description : %.16s\n", (u8 *) (work32 + 10));
++ seq_printf(seq, "Product rev. : %.8s\n", (u8 *) (work32 + 14));
+
+ seq_printf(seq, "Serial number : ");
+ print_serial_number(seq, (u8 *) (work32 + 16),
+@@ -1324,10 +1312,8 @@ static int i2o_seq_show_ddm_identity(str
+ }
+
+ seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid);
+- seq_printf(seq, "Module name : %s\n",
+- chtostr(result.module_name, 24));
+- seq_printf(seq, "Module revision : %s\n",
+- chtostr(result.module_rev, 8));
++ seq_printf(seq, "Module name : %.24s\n", result.module_name);
++ seq_printf(seq, "Module revision : %.8s\n", result.module_rev);
+
+ seq_printf(seq, "Serial number : ");
+ print_serial_number(seq, result.serial_number, sizeof(result) - 36);
+@@ -1358,14 +1344,10 @@ static int i2o_seq_show_uinfo(struct seq
+ return 0;
+ }
+
+- seq_printf(seq, "Device name : %s\n",
+- chtostr(result.device_name, 64));
+- seq_printf(seq, "Service name : %s\n",
+- chtostr(result.service_name, 64));
+- seq_printf(seq, "Physical name : %s\n",
+- chtostr(result.physical_location, 64));
+- seq_printf(seq, "Instance number : %s\n",
+- chtostr(result.instance_number, 4));
++ seq_printf(seq, "Device name : %.64s\n", result.device_name);
++ seq_printf(seq, "Service name : %.64s\n", result.service_name);
++ seq_printf(seq, "Physical name : %.64s\n", result.physical_location);
++ seq_printf(seq, "Instance number : %.4s\n", result.instance_number);
+
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/drivers/message/i2o/iop.c linux-2.6.38.7/drivers/message/i2o/iop.c
+--- linux-2.6.38.7/drivers/message/i2o/iop.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/message/i2o/iop.c 2011-04-28 19:57:25.000000000 -0400
+@@ -111,10 +111,10 @@ u32 i2o_cntxt_list_add(struct i2o_contro
+
+ spin_lock_irqsave(&c->context_list_lock, flags);
+
+- if (unlikely(atomic_inc_and_test(&c->context_list_counter)))
+- atomic_inc(&c->context_list_counter);
++ if (unlikely(atomic_inc_and_test_unchecked(&c->context_list_counter)))
++ atomic_inc_unchecked(&c->context_list_counter);
+
+- entry->context = atomic_read(&c->context_list_counter);
++ entry->context = atomic_read_unchecked(&c->context_list_counter);
+
+ list_add(&entry->list, &c->context_list);
+
+@@ -1077,7 +1077,7 @@ struct i2o_controller *i2o_iop_alloc(voi
+
+ #if BITS_PER_LONG == 64
+ spin_lock_init(&c->context_list_lock);
+- atomic_set(&c->context_list_counter, 0);
++ atomic_set_unchecked(&c->context_list_counter, 0);
+ INIT_LIST_HEAD(&c->context_list);
+ #endif
+
+diff -urNp linux-2.6.38.7/drivers/mfd/janz-cmodio.c linux-2.6.38.7/drivers/mfd/janz-cmodio.c
+--- linux-2.6.38.7/drivers/mfd/janz-cmodio.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mfd/janz-cmodio.c 2011-04-28 19:34:15.000000000 -0400
+@@ -13,6 +13,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
+ #include <linux/interrupt.h>
+diff -urNp linux-2.6.38.7/drivers/mfd/wm8350-i2c.c linux-2.6.38.7/drivers/mfd/wm8350-i2c.c
+--- linux-2.6.38.7/drivers/mfd/wm8350-i2c.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mfd/wm8350-i2c.c 2011-05-16 21:47:08.000000000 -0400
+@@ -44,6 +44,8 @@ static int wm8350_i2c_write_device(struc
+ u8 msg[(WM8350_MAX_REGISTER << 1) + 1];
+ int ret;
+
++ pax_track_stack();
++
+ if (bytes > ((WM8350_MAX_REGISTER << 1) + 1))
+ return -EINVAL;
+
+diff -urNp linux-2.6.38.7/drivers/misc/kgdbts.c linux-2.6.38.7/drivers/misc/kgdbts.c
+--- linux-2.6.38.7/drivers/misc/kgdbts.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/misc/kgdbts.c 2011-04-28 19:34:15.000000000 -0400
+@@ -118,7 +118,7 @@
+ } while (0)
+ #define MAX_CONFIG_LEN 40
+
+-static struct kgdb_io kgdbts_io_ops;
++static const struct kgdb_io kgdbts_io_ops;
+ static char get_buf[BUFMAX];
+ static int get_buf_cnt;
+ static char put_buf[BUFMAX];
+@@ -1103,7 +1103,7 @@ static void kgdbts_post_exp_handler(void
+ module_put(THIS_MODULE);
+ }
+
+-static struct kgdb_io kgdbts_io_ops = {
++static const struct kgdb_io kgdbts_io_ops = {
+ .name = "kgdbts",
+ .read_char = kgdbts_get_char,
+ .write_char = kgdbts_put_char,
+diff -urNp linux-2.6.38.7/drivers/misc/sgi-gru/gruhandles.c linux-2.6.38.7/drivers/misc/sgi-gru/gruhandles.c
+--- linux-2.6.38.7/drivers/misc/sgi-gru/gruhandles.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/misc/sgi-gru/gruhandles.c 2011-04-28 19:34:15.000000000 -0400
+@@ -44,8 +44,8 @@ static void update_mcs_stats(enum mcs_op
+ unsigned long nsec;
+
+ nsec = CLKS2NSEC(clks);
+- atomic_long_inc(&mcs_op_statistics[op].count);
+- atomic_long_add(nsec, &mcs_op_statistics[op].total);
++ atomic_long_inc_unchecked(&mcs_op_statistics[op].count);
++ atomic_long_add_unchecked(nsec, &mcs_op_statistics[op].total);
+ if (mcs_op_statistics[op].max < nsec)
+ mcs_op_statistics[op].max = nsec;
+ }
+diff -urNp linux-2.6.38.7/drivers/misc/sgi-gru/gruprocfs.c linux-2.6.38.7/drivers/misc/sgi-gru/gruprocfs.c
+--- linux-2.6.38.7/drivers/misc/sgi-gru/gruprocfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/misc/sgi-gru/gruprocfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -32,9 +32,9 @@
+
+ #define printstat(s, f) printstat_val(s, &gru_stats.f, #f)
+
+-static void printstat_val(struct seq_file *s, atomic_long_t *v, char *id)
++static void printstat_val(struct seq_file *s, atomic_long_unchecked_t *v, char *id)
+ {
+- unsigned long val = atomic_long_read(v);
++ unsigned long val = atomic_long_read_unchecked(v);
+
+ seq_printf(s, "%16lu %s\n", val, id);
+ }
+@@ -134,8 +134,8 @@ static int mcs_statistics_show(struct se
+
+ seq_printf(s, "%-20s%12s%12s%12s\n", "#id", "count", "aver-clks", "max-clks");
+ for (op = 0; op < mcsop_last; op++) {
+- count = atomic_long_read(&mcs_op_statistics[op].count);
+- total = atomic_long_read(&mcs_op_statistics[op].total);
++ count = atomic_long_read_unchecked(&mcs_op_statistics[op].count);
++ total = atomic_long_read_unchecked(&mcs_op_statistics[op].total);
+ max = mcs_op_statistics[op].max;
+ seq_printf(s, "%-20s%12ld%12ld%12ld\n", id[op], count,
+ count ? total / count : 0, max);
+diff -urNp linux-2.6.38.7/drivers/misc/sgi-gru/grutables.h linux-2.6.38.7/drivers/misc/sgi-gru/grutables.h
+--- linux-2.6.38.7/drivers/misc/sgi-gru/grutables.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/misc/sgi-gru/grutables.h 2011-04-28 19:34:15.000000000 -0400
+@@ -167,82 +167,82 @@ extern unsigned int gru_max_gids;
+ * GRU statistics.
+ */
+ struct gru_stats_s {
+- atomic_long_t vdata_alloc;
+- atomic_long_t vdata_free;
+- atomic_long_t gts_alloc;
+- atomic_long_t gts_free;
+- atomic_long_t gms_alloc;
+- atomic_long_t gms_free;
+- atomic_long_t gts_double_allocate;
+- atomic_long_t assign_context;
+- atomic_long_t assign_context_failed;
+- atomic_long_t free_context;
+- atomic_long_t load_user_context;
+- atomic_long_t load_kernel_context;
+- atomic_long_t lock_kernel_context;
+- atomic_long_t unlock_kernel_context;
+- atomic_long_t steal_user_context;
+- atomic_long_t steal_kernel_context;
+- atomic_long_t steal_context_failed;
+- atomic_long_t nopfn;
+- atomic_long_t asid_new;
+- atomic_long_t asid_next;
+- atomic_long_t asid_wrap;
+- atomic_long_t asid_reuse;
+- atomic_long_t intr;
+- atomic_long_t intr_cbr;
+- atomic_long_t intr_tfh;
+- atomic_long_t intr_spurious;
+- atomic_long_t intr_mm_lock_failed;
+- atomic_long_t call_os;
+- atomic_long_t call_os_wait_queue;
+- atomic_long_t user_flush_tlb;
+- atomic_long_t user_unload_context;
+- atomic_long_t user_exception;
+- atomic_long_t set_context_option;
+- atomic_long_t check_context_retarget_intr;
+- atomic_long_t check_context_unload;
+- atomic_long_t tlb_dropin;
+- atomic_long_t tlb_preload_page;
+- atomic_long_t tlb_dropin_fail_no_asid;
+- atomic_long_t tlb_dropin_fail_upm;
+- atomic_long_t tlb_dropin_fail_invalid;
+- atomic_long_t tlb_dropin_fail_range_active;
+- atomic_long_t tlb_dropin_fail_idle;
+- atomic_long_t tlb_dropin_fail_fmm;
+- atomic_long_t tlb_dropin_fail_no_exception;
+- atomic_long_t tfh_stale_on_fault;
+- atomic_long_t mmu_invalidate_range;
+- atomic_long_t mmu_invalidate_page;
+- atomic_long_t flush_tlb;
+- atomic_long_t flush_tlb_gru;
+- atomic_long_t flush_tlb_gru_tgh;
+- atomic_long_t flush_tlb_gru_zero_asid;
+-
+- atomic_long_t copy_gpa;
+- atomic_long_t read_gpa;
+-
+- atomic_long_t mesq_receive;
+- atomic_long_t mesq_receive_none;
+- atomic_long_t mesq_send;
+- atomic_long_t mesq_send_failed;
+- atomic_long_t mesq_noop;
+- atomic_long_t mesq_send_unexpected_error;
+- atomic_long_t mesq_send_lb_overflow;
+- atomic_long_t mesq_send_qlimit_reached;
+- atomic_long_t mesq_send_amo_nacked;
+- atomic_long_t mesq_send_put_nacked;
+- atomic_long_t mesq_page_overflow;
+- atomic_long_t mesq_qf_locked;
+- atomic_long_t mesq_qf_noop_not_full;
+- atomic_long_t mesq_qf_switch_head_failed;
+- atomic_long_t mesq_qf_unexpected_error;
+- atomic_long_t mesq_noop_unexpected_error;
+- atomic_long_t mesq_noop_lb_overflow;
+- atomic_long_t mesq_noop_qlimit_reached;
+- atomic_long_t mesq_noop_amo_nacked;
+- atomic_long_t mesq_noop_put_nacked;
+- atomic_long_t mesq_noop_page_overflow;
++ atomic_long_unchecked_t vdata_alloc;
++ atomic_long_unchecked_t vdata_free;
++ atomic_long_unchecked_t gts_alloc;
++ atomic_long_unchecked_t gts_free;
++ atomic_long_unchecked_t gms_alloc;
++ atomic_long_unchecked_t gms_free;
++ atomic_long_unchecked_t gts_double_allocate;
++ atomic_long_unchecked_t assign_context;
++ atomic_long_unchecked_t assign_context_failed;
++ atomic_long_unchecked_t free_context;
++ atomic_long_unchecked_t load_user_context;
++ atomic_long_unchecked_t load_kernel_context;
++ atomic_long_unchecked_t lock_kernel_context;
++ atomic_long_unchecked_t unlock_kernel_context;
++ atomic_long_unchecked_t steal_user_context;
++ atomic_long_unchecked_t steal_kernel_context;
++ atomic_long_unchecked_t steal_context_failed;
++ atomic_long_unchecked_t nopfn;
++ atomic_long_unchecked_t asid_new;
++ atomic_long_unchecked_t asid_next;
++ atomic_long_unchecked_t asid_wrap;
++ atomic_long_unchecked_t asid_reuse;
++ atomic_long_unchecked_t intr;
++ atomic_long_unchecked_t intr_cbr;
++ atomic_long_unchecked_t intr_tfh;
++ atomic_long_unchecked_t intr_spurious;
++ atomic_long_unchecked_t intr_mm_lock_failed;
++ atomic_long_unchecked_t call_os;
++ atomic_long_unchecked_t call_os_wait_queue;
++ atomic_long_unchecked_t user_flush_tlb;
++ atomic_long_unchecked_t user_unload_context;
++ atomic_long_unchecked_t user_exception;
++ atomic_long_unchecked_t set_context_option;
++ atomic_long_unchecked_t check_context_retarget_intr;
++ atomic_long_unchecked_t check_context_unload;
++ atomic_long_unchecked_t tlb_dropin;
++ atomic_long_unchecked_t tlb_preload_page;
++ atomic_long_unchecked_t tlb_dropin_fail_no_asid;
++ atomic_long_unchecked_t tlb_dropin_fail_upm;
++ atomic_long_unchecked_t tlb_dropin_fail_invalid;
++ atomic_long_unchecked_t tlb_dropin_fail_range_active;
++ atomic_long_unchecked_t tlb_dropin_fail_idle;
++ atomic_long_unchecked_t tlb_dropin_fail_fmm;
++ atomic_long_unchecked_t tlb_dropin_fail_no_exception;
++ atomic_long_unchecked_t tfh_stale_on_fault;
++ atomic_long_unchecked_t mmu_invalidate_range;
++ atomic_long_unchecked_t mmu_invalidate_page;
++ atomic_long_unchecked_t flush_tlb;
++ atomic_long_unchecked_t flush_tlb_gru;
++ atomic_long_unchecked_t flush_tlb_gru_tgh;
++ atomic_long_unchecked_t flush_tlb_gru_zero_asid;
++
++ atomic_long_unchecked_t copy_gpa;
++ atomic_long_unchecked_t read_gpa;
++
++ atomic_long_unchecked_t mesq_receive;
++ atomic_long_unchecked_t mesq_receive_none;
++ atomic_long_unchecked_t mesq_send;
++ atomic_long_unchecked_t mesq_send_failed;
++ atomic_long_unchecked_t mesq_noop;
++ atomic_long_unchecked_t mesq_send_unexpected_error;
++ atomic_long_unchecked_t mesq_send_lb_overflow;
++ atomic_long_unchecked_t mesq_send_qlimit_reached;
++ atomic_long_unchecked_t mesq_send_amo_nacked;
++ atomic_long_unchecked_t mesq_send_put_nacked;
++ atomic_long_unchecked_t mesq_page_overflow;
++ atomic_long_unchecked_t mesq_qf_locked;
++ atomic_long_unchecked_t mesq_qf_noop_not_full;
++ atomic_long_unchecked_t mesq_qf_switch_head_failed;
++ atomic_long_unchecked_t mesq_qf_unexpected_error;
++ atomic_long_unchecked_t mesq_noop_unexpected_error;
++ atomic_long_unchecked_t mesq_noop_lb_overflow;
++ atomic_long_unchecked_t mesq_noop_qlimit_reached;
++ atomic_long_unchecked_t mesq_noop_amo_nacked;
++ atomic_long_unchecked_t mesq_noop_put_nacked;
++ atomic_long_unchecked_t mesq_noop_page_overflow;
+
+ };
+
+@@ -251,8 +251,8 @@ enum mcs_op {cchop_allocate, cchop_start
+ tghop_invalidate, mcsop_last};
+
+ struct mcs_op_statistic {
+- atomic_long_t count;
+- atomic_long_t total;
++ atomic_long_unchecked_t count;
++ atomic_long_unchecked_t total;
+ unsigned long max;
+ };
+
+@@ -275,7 +275,7 @@ extern struct mcs_op_statistic mcs_op_st
+
+ #define STAT(id) do { \
+ if (gru_options & OPT_STATS) \
+- atomic_long_inc(&gru_stats.id); \
++ atomic_long_inc_unchecked(&gru_stats.id); \
+ } while (0)
+
+ #ifdef CONFIG_SGI_GRU_DEBUG
+diff -urNp linux-2.6.38.7/drivers/mtd/chips/cfi_cmdset_0001.c linux-2.6.38.7/drivers/mtd/chips/cfi_cmdset_0001.c
+--- linux-2.6.38.7/drivers/mtd/chips/cfi_cmdset_0001.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/chips/cfi_cmdset_0001.c 2011-05-16 21:47:08.000000000 -0400
+@@ -757,6 +757,8 @@ static int chip_ready (struct map_info *
+ struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
+ unsigned long timeo = jiffies + HZ;
+
++ pax_track_stack();
++
+ /* Prevent setting state FL_SYNCING for chip in suspended state. */
+ if (mode == FL_SYNCING && chip->oldstate != FL_READY)
+ goto sleep;
+@@ -1657,6 +1659,8 @@ static int __xipram do_write_buffer(stru
+ unsigned long initial_adr;
+ int initial_len = len;
+
++ pax_track_stack();
++
+ wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
+ adr += chip->start;
+ initial_adr = adr;
+@@ -1875,6 +1879,8 @@ static int __xipram do_erase_oneblock(st
+ int retries = 3;
+ int ret;
+
++ pax_track_stack();
++
+ adr += chip->start;
+
+ retry:
+diff -urNp linux-2.6.38.7/drivers/mtd/chips/cfi_cmdset_0020.c linux-2.6.38.7/drivers/mtd/chips/cfi_cmdset_0020.c
+--- linux-2.6.38.7/drivers/mtd/chips/cfi_cmdset_0020.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/chips/cfi_cmdset_0020.c 2011-05-16 21:47:08.000000000 -0400
+@@ -255,6 +255,8 @@ static inline int do_read_onechip(struct
+ unsigned long cmd_addr;
+ struct cfi_private *cfi = map->fldrv_priv;
+
++ pax_track_stack();
++
+ adr += chip->start;
+
+ /* Ensure cmd read/writes are aligned. */
+@@ -428,6 +430,8 @@ static inline int do_write_buffer(struct
+ DECLARE_WAITQUEUE(wait, current);
+ int wbufsize, z;
+
++ pax_track_stack();
++
+ /* M58LW064A requires bus alignment for buffer wriets -- saw */
+ if (adr & (map_bankwidth(map)-1))
+ return -EINVAL;
+@@ -742,6 +746,8 @@ static inline int do_erase_oneblock(stru
+ DECLARE_WAITQUEUE(wait, current);
+ int ret = 0;
+
++ pax_track_stack();
++
+ adr += chip->start;
+
+ /* Let's determine this according to the interleave only once */
+@@ -1047,6 +1053,8 @@ static inline int do_lock_oneblock(struc
+ unsigned long timeo = jiffies + HZ;
+ DECLARE_WAITQUEUE(wait, current);
+
++ pax_track_stack();
++
+ adr += chip->start;
+
+ /* Let's determine this according to the interleave only once */
+@@ -1196,6 +1204,8 @@ static inline int do_unlock_oneblock(str
+ unsigned long timeo = jiffies + HZ;
+ DECLARE_WAITQUEUE(wait, current);
+
++ pax_track_stack();
++
+ adr += chip->start;
+
+ /* Let's determine this according to the interleave only once */
+diff -urNp linux-2.6.38.7/drivers/mtd/devices/doc2000.c linux-2.6.38.7/drivers/mtd/devices/doc2000.c
+--- linux-2.6.38.7/drivers/mtd/devices/doc2000.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/devices/doc2000.c 2011-04-28 19:34:15.000000000 -0400
+@@ -776,7 +776,7 @@ static int doc_write(struct mtd_info *mt
+
+ /* The ECC will not be calculated correctly if less than 512 is written */
+ /* DBB-
+- if (len != 0x200 && eccbuf)
++ if (len != 0x200)
+ printk(KERN_WARNING
+ "ECC needs a full sector write (adr: %lx size %lx)\n",
+ (long) to, (long) len);
+diff -urNp linux-2.6.38.7/drivers/mtd/devices/doc2001.c linux-2.6.38.7/drivers/mtd/devices/doc2001.c
+--- linux-2.6.38.7/drivers/mtd/devices/doc2001.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/devices/doc2001.c 2011-04-28 19:34:15.000000000 -0400
+@@ -393,7 +393,7 @@ static int doc_read (struct mtd_info *mt
+ struct Nand *mychip = &this->chips[from >> (this->chipshift)];
+
+ /* Don't allow read past end of device */
+- if (from >= this->totlen)
++ if (from >= this->totlen || !len)
+ return -EINVAL;
+
+ /* Don't allow a single read to cross a 512-byte block boundary */
+diff -urNp linux-2.6.38.7/drivers/mtd/ftl.c linux-2.6.38.7/drivers/mtd/ftl.c
+--- linux-2.6.38.7/drivers/mtd/ftl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/ftl.c 2011-05-16 21:47:08.000000000 -0400
+@@ -474,6 +474,8 @@ static int copy_erase_unit(partition_t *
+ loff_t offset;
+ uint16_t srcunitswap = cpu_to_le16(srcunit);
+
++ pax_track_stack();
++
+ eun = &part->EUNInfo[srcunit];
+ xfer = &part->XferInfo[xferunit];
+ DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",
+diff -urNp linux-2.6.38.7/drivers/mtd/inftlcore.c linux-2.6.38.7/drivers/mtd/inftlcore.c
+--- linux-2.6.38.7/drivers/mtd/inftlcore.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/inftlcore.c 2011-05-16 21:47:08.000000000 -0400
+@@ -259,6 +259,8 @@ static u16 INFTL_foldchain(struct INFTLr
+ struct inftl_oob oob;
+ size_t retlen;
+
++ pax_track_stack();
++
+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
+ "pending=%d)\n", inftl, thisVUC, pendingblock);
+
+diff -urNp linux-2.6.38.7/drivers/mtd/inftlmount.c linux-2.6.38.7/drivers/mtd/inftlmount.c
+--- linux-2.6.38.7/drivers/mtd/inftlmount.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/inftlmount.c 2011-05-16 21:47:08.000000000 -0400
+@@ -53,6 +53,8 @@ static int find_boot_record(struct INFTL
+ struct INFTLPartition *ip;
+ size_t retlen;
+
++ pax_track_stack();
++
+ DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl);
+
+ /*
+diff -urNp linux-2.6.38.7/drivers/mtd/lpddr/qinfo_probe.c linux-2.6.38.7/drivers/mtd/lpddr/qinfo_probe.c
+--- linux-2.6.38.7/drivers/mtd/lpddr/qinfo_probe.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/lpddr/qinfo_probe.c 2011-05-16 21:47:08.000000000 -0400
+@@ -106,6 +106,8 @@ static int lpddr_pfow_present(struct map
+ {
+ map_word pfow_val[4];
+
++ pax_track_stack();
++
+ /* Check identification string */
+ pfow_val[0] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_P);
+ pfow_val[1] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_F);
+diff -urNp linux-2.6.38.7/drivers/mtd/mtdchar.c linux-2.6.38.7/drivers/mtd/mtdchar.c
+--- linux-2.6.38.7/drivers/mtd/mtdchar.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/mtdchar.c 2011-05-16 21:47:08.000000000 -0400
+@@ -560,6 +560,8 @@ static int mtd_ioctl(struct file *file,
+ u_long size;
+ struct mtd_info_user info;
+
++ pax_track_stack();
++
+ DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
+
+ size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
+diff -urNp linux-2.6.38.7/drivers/mtd/nand/denali.c linux-2.6.38.7/drivers/mtd/nand/denali.c
+--- linux-2.6.38.7/drivers/mtd/nand/denali.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/nand/denali.c 2011-04-28 19:34:15.000000000 -0400
+@@ -25,6 +25,7 @@
+ #include <linux/pci.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/module.h>
++#include <linux/slab.h>
+
+ #include "denali.h"
+
+diff -urNp linux-2.6.38.7/drivers/mtd/nftlcore.c linux-2.6.38.7/drivers/mtd/nftlcore.c
+--- linux-2.6.38.7/drivers/mtd/nftlcore.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/nftlcore.c 2011-05-16 21:47:08.000000000 -0400
+@@ -264,6 +264,8 @@ static u16 NFTL_foldchain (struct NFTLre
+ int inplace = 1;
+ size_t retlen;
+
++ pax_track_stack();
++
+ memset(BlockMap, 0xff, sizeof(BlockMap));
+ memset(BlockFreeFound, 0, sizeof(BlockFreeFound));
+
+diff -urNp linux-2.6.38.7/drivers/mtd/nftlmount.c linux-2.6.38.7/drivers/mtd/nftlmount.c
+--- linux-2.6.38.7/drivers/mtd/nftlmount.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/nftlmount.c 2011-05-18 20:23:44.000000000 -0400
+@@ -24,6 +24,7 @@
+ #include <asm/errno.h>
+ #include <linux/delay.h>
+ #include <linux/slab.h>
++#include <linux/sched.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mtd/nftl.h>
+@@ -45,6 +46,8 @@ static int find_boot_record(struct NFTLr
+ struct mtd_info *mtd = nftl->mbd.mtd;
+ unsigned int i;
+
++ pax_track_stack();
++
+ /* Assume logical EraseSize == physical erasesize for starting the scan.
+ We'll sort it out later if we find a MediaHeader which says otherwise */
+ /* Actually, we won't. The new DiskOnChip driver has already scanned
+diff -urNp linux-2.6.38.7/drivers/mtd/ubi/build.c linux-2.6.38.7/drivers/mtd/ubi/build.c
+--- linux-2.6.38.7/drivers/mtd/ubi/build.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/mtd/ubi/build.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1285,7 +1285,7 @@ module_exit(ubi_exit);
+ static int __init bytes_str_to_int(const char *str)
+ {
+ char *endp;
+- unsigned long result;
++ unsigned long result, scale = 1;
+
+ result = simple_strtoul(str, &endp, 0);
+ if (str == endp || result >= INT_MAX) {
+@@ -1296,11 +1296,11 @@ static int __init bytes_str_to_int(const
+
+ switch (*endp) {
+ case 'G':
+- result *= 1024;
++ scale *= 1024;
+ case 'M':
+- result *= 1024;
++ scale *= 1024;
+ case 'K':
+- result *= 1024;
++ scale *= 1024;
+ if (endp[1] == 'i' && endp[2] == 'B')
+ endp += 2;
+ case '\0':
+@@ -1311,7 +1311,13 @@ static int __init bytes_str_to_int(const
+ return -EINVAL;
+ }
+
+- return result;
++ if ((intoverflow_t)result*scale >= INT_MAX) {
++ printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n",
++ str);
++ return -EINVAL;
++ }
++
++ return result*scale;
+ }
+
+ /**
+diff -urNp linux-2.6.38.7/drivers/net/bnx2.c linux-2.6.38.7/drivers/net/bnx2.c
+--- linux-2.6.38.7/drivers/net/bnx2.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/bnx2.c 2011-05-16 21:47:08.000000000 -0400
+@@ -5826,6 +5826,8 @@ bnx2_test_nvram(struct bnx2 *bp)
+ int rc = 0;
+ u32 magic, csum;
+
++ pax_track_stack();
++
+ if ((rc = bnx2_nvram_read(bp, 0, data, 4)) != 0)
+ goto test_nvram_done;
+
+diff -urNp linux-2.6.38.7/drivers/net/bnx2x/bnx2x_ethtool.c linux-2.6.38.7/drivers/net/bnx2x/bnx2x_ethtool.c
+--- linux-2.6.38.7/drivers/net/bnx2x/bnx2x_ethtool.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/bnx2x/bnx2x_ethtool.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1788,6 +1788,8 @@ static int bnx2x_test_nvram(struct bnx2x
+ int i, rc;
+ u32 magic, crc;
+
++ pax_track_stack();
++
+ if (BP_NOMCP(bp))
+ return 0;
+
+diff -urNp linux-2.6.38.7/drivers/net/cxgb4/cxgb4_main.c linux-2.6.38.7/drivers/net/cxgb4/cxgb4_main.c
+--- linux-2.6.38.7/drivers/net/cxgb4/cxgb4_main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/cxgb4/cxgb4_main.c 2011-05-16 21:47:08.000000000 -0400
+@@ -3429,6 +3429,8 @@ static int __devinit enable_msix(struct
+ unsigned int nchan = adap->params.nports;
+ struct msix_entry entries[MAX_INGQ + 1];
+
++ pax_track_stack();
++
+ for (i = 0; i < ARRAY_SIZE(entries); ++i)
+ entries[i].entry = i;
+
+diff -urNp linux-2.6.38.7/drivers/net/cxgb4/t4_hw.c linux-2.6.38.7/drivers/net/cxgb4/t4_hw.c
+--- linux-2.6.38.7/drivers/net/cxgb4/t4_hw.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/cxgb4/t4_hw.c 2011-05-16 21:47:08.000000000 -0400
+@@ -362,6 +362,8 @@ static int get_vpd_params(struct adapter
+ u8 vpd[VPD_LEN], csum;
+ unsigned int vpdr_len, kw_offset, id_len;
+
++ pax_track_stack();
++
+ ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd);
+ if (ret < 0)
+ return ret;
+diff -urNp linux-2.6.38.7/drivers/net/e1000e/82571.c linux-2.6.38.7/drivers/net/e1000e/82571.c
+--- linux-2.6.38.7/drivers/net/e1000e/82571.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/e1000e/82571.c 2011-04-28 19:34:15.000000000 -0400
+@@ -239,7 +239,7 @@ static s32 e1000_init_mac_params_82571(s
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ struct e1000_mac_info *mac = &hw->mac;
+- struct e1000_mac_operations *func = &mac->ops;
++ struct e1000_mac_operations *func = &mac->ops; /* cannot be const */
+ u32 swsm = 0;
+ u32 swsm2 = 0;
+ bool force_clear_smbi = false;
+@@ -1930,7 +1930,7 @@ static void e1000_clear_hw_cntrs_82571(s
+ er32(ICRXDMTC);
+ }
+
+-static struct e1000_mac_operations e82571_mac_ops = {
++static const struct e1000_mac_operations e82571_mac_ops = {
+ /* .check_mng_mode: mac type dependent */
+ /* .check_for_link: media type dependent */
+ .id_led_init = e1000e_id_led_init,
+@@ -1952,7 +1952,7 @@ static struct e1000_mac_operations e8257
+ .read_mac_addr = e1000_read_mac_addr_82571,
+ };
+
+-static struct e1000_phy_operations e82_phy_ops_igp = {
++static const struct e1000_phy_operations e82_phy_ops_igp = {
+ .acquire = e1000_get_hw_semaphore_82571,
+ .check_polarity = e1000_check_polarity_igp,
+ .check_reset_block = e1000e_check_reset_block_generic,
+@@ -1970,7 +1970,7 @@ static struct e1000_phy_operations e82_p
+ .cfg_on_link_up = NULL,
+ };
+
+-static struct e1000_phy_operations e82_phy_ops_m88 = {
++static const struct e1000_phy_operations e82_phy_ops_m88 = {
+ .acquire = e1000_get_hw_semaphore_82571,
+ .check_polarity = e1000_check_polarity_m88,
+ .check_reset_block = e1000e_check_reset_block_generic,
+@@ -1988,7 +1988,7 @@ static struct e1000_phy_operations e82_p
+ .cfg_on_link_up = NULL,
+ };
+
+-static struct e1000_phy_operations e82_phy_ops_bm = {
++static const struct e1000_phy_operations e82_phy_ops_bm = {
+ .acquire = e1000_get_hw_semaphore_82571,
+ .check_polarity = e1000_check_polarity_m88,
+ .check_reset_block = e1000e_check_reset_block_generic,
+@@ -2006,7 +2006,7 @@ static struct e1000_phy_operations e82_p
+ .cfg_on_link_up = NULL,
+ };
+
+-static struct e1000_nvm_operations e82571_nvm_ops = {
++static const struct e1000_nvm_operations e82571_nvm_ops = {
+ .acquire = e1000_acquire_nvm_82571,
+ .read = e1000e_read_nvm_eerd,
+ .release = e1000_release_nvm_82571,
+diff -urNp linux-2.6.38.7/drivers/net/e1000e/e1000.h linux-2.6.38.7/drivers/net/e1000e/e1000.h
+--- linux-2.6.38.7/drivers/net/e1000e/e1000.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/e1000e/e1000.h 2011-04-28 19:34:15.000000000 -0400
+@@ -408,9 +408,9 @@ struct e1000_info {
+ u32 pba;
+ u32 max_hw_frame_size;
+ s32 (*get_variants)(struct e1000_adapter *);
+- struct e1000_mac_operations *mac_ops;
+- struct e1000_phy_operations *phy_ops;
+- struct e1000_nvm_operations *nvm_ops;
++ const struct e1000_mac_operations *mac_ops;
++ const struct e1000_phy_operations *phy_ops;
++ const struct e1000_nvm_operations *nvm_ops;
+ };
+
+ /* hardware capability, feature, and workaround flags */
+diff -urNp linux-2.6.38.7/drivers/net/e1000e/es2lan.c linux-2.6.38.7/drivers/net/e1000e/es2lan.c
+--- linux-2.6.38.7/drivers/net/e1000e/es2lan.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/e1000e/es2lan.c 2011-04-28 19:34:15.000000000 -0400
+@@ -205,7 +205,7 @@ static s32 e1000_init_mac_params_80003es
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ struct e1000_mac_info *mac = &hw->mac;
+- struct e1000_mac_operations *func = &mac->ops;
++ struct e1000_mac_operations *func = &mac->ops; /* cannot be const */
+
+ /* Set media type */
+ switch (adapter->pdev->device) {
+@@ -1431,7 +1431,7 @@ static void e1000_clear_hw_cntrs_80003es
+ er32(ICRXDMTC);
+ }
+
+-static struct e1000_mac_operations es2_mac_ops = {
++static const struct e1000_mac_operations es2_mac_ops = {
+ .read_mac_addr = e1000_read_mac_addr_80003es2lan,
+ .id_led_init = e1000e_id_led_init,
+ .check_mng_mode = e1000e_check_mng_mode_generic,
+@@ -1453,7 +1453,7 @@ static struct e1000_mac_operations es2_m
+ .setup_led = e1000e_setup_led_generic,
+ };
+
+-static struct e1000_phy_operations es2_phy_ops = {
++static const struct e1000_phy_operations es2_phy_ops = {
+ .acquire = e1000_acquire_phy_80003es2lan,
+ .check_polarity = e1000_check_polarity_m88,
+ .check_reset_block = e1000e_check_reset_block_generic,
+@@ -1471,7 +1471,7 @@ static struct e1000_phy_operations es2_p
+ .cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan,
+ };
+
+-static struct e1000_nvm_operations es2_nvm_ops = {
++static const struct e1000_nvm_operations es2_nvm_ops = {
+ .acquire = e1000_acquire_nvm_80003es2lan,
+ .read = e1000e_read_nvm_eerd,
+ .release = e1000_release_nvm_80003es2lan,
+diff -urNp linux-2.6.38.7/drivers/net/e1000e/hw.h linux-2.6.38.7/drivers/net/e1000e/hw.h
+--- linux-2.6.38.7/drivers/net/e1000e/hw.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/e1000e/hw.h 2011-04-28 19:34:15.000000000 -0400
+@@ -801,16 +801,17 @@ struct e1000_phy_operations {
+
+ /* Function pointers for the NVM. */
+ struct e1000_nvm_operations {
+- s32 (*acquire)(struct e1000_hw *);
+- s32 (*read)(struct e1000_hw *, u16, u16, u16 *);
+- void (*release)(struct e1000_hw *);
+- s32 (*update)(struct e1000_hw *);
+- s32 (*valid_led_default)(struct e1000_hw *, u16 *);
+- s32 (*validate)(struct e1000_hw *);
+- s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
++ s32 (* acquire)(struct e1000_hw *); /* cannot be const, see drivers/net/e1000e/82571.c e1000_init_nvm_params_82571() */
++ s32 (* const read)(struct e1000_hw *, u16, u16, u16 *);
++ void (* release)(struct e1000_hw *); /* cannot be const, see drivers/net/e1000e/82571.c e1000_init_nvm_params_82571() */
++ s32 (* const update)(struct e1000_hw *);
++ s32 (* const valid_led_default)(struct e1000_hw *, u16 *);
++ s32 (* const validate)(struct e1000_hw *);
++ s32 (* const write)(struct e1000_hw *, u16, u16, u16 *);
+ };
+
+ struct e1000_mac_info {
++ /* cannot be const see e1000_init_mac_params_ich8lan */
+ struct e1000_mac_operations ops;
+
+ u8 addr[6];
+@@ -853,6 +854,7 @@ struct e1000_mac_info {
+ };
+
+ struct e1000_phy_info {
++ /* Cannot be const see e1000_init_phy_params_82571() */
+ struct e1000_phy_operations ops;
+
+ enum e1000_phy_type type;
+@@ -887,6 +889,7 @@ struct e1000_phy_info {
+ };
+
+ struct e1000_nvm_info {
++ /* cannot be const */
+ struct e1000_nvm_operations ops;
+
+ enum e1000_nvm_type type;
+diff -urNp linux-2.6.38.7/drivers/net/e1000e/ich8lan.c linux-2.6.38.7/drivers/net/e1000e/ich8lan.c
+--- linux-2.6.38.7/drivers/net/e1000e/ich8lan.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/e1000e/ich8lan.c 2011-04-28 19:34:15.000000000 -0400
+@@ -3840,7 +3840,7 @@ static void e1000_clear_hw_cntrs_ich8lan
+ }
+ }
+
+-static struct e1000_mac_operations ich8_mac_ops = {
++static const struct e1000_mac_operations ich8_mac_ops = {
+ .id_led_init = e1000e_id_led_init,
+ /* check_mng_mode dependent on mac type */
+ .check_for_link = e1000_check_for_copper_link_ich8lan,
+@@ -3859,7 +3859,7 @@ static struct e1000_mac_operations ich8_
+ /* id_led_init dependent on mac type */
+ };
+
+-static struct e1000_phy_operations ich8_phy_ops = {
++static const struct e1000_phy_operations ich8_phy_ops = {
+ .acquire = e1000_acquire_swflag_ich8lan,
+ .check_reset_block = e1000_check_reset_block_ich8lan,
+ .commit = NULL,
+@@ -3873,7 +3873,7 @@ static struct e1000_phy_operations ich8_
+ .write_reg = e1000e_write_phy_reg_igp,
+ };
+
+-static struct e1000_nvm_operations ich8_nvm_ops = {
++static const struct e1000_nvm_operations ich8_nvm_ops = {
+ .acquire = e1000_acquire_nvm_ich8lan,
+ .read = e1000_read_nvm_ich8lan,
+ .release = e1000_release_nvm_ich8lan,
+diff -urNp linux-2.6.38.7/drivers/net/hamradio/6pack.c linux-2.6.38.7/drivers/net/hamradio/6pack.c
+--- linux-2.6.38.7/drivers/net/hamradio/6pack.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/hamradio/6pack.c 2011-05-16 21:47:08.000000000 -0400
+@@ -463,6 +463,8 @@ static void sixpack_receive_buf(struct t
+ unsigned char buf[512];
+ int count1;
+
++ pax_track_stack();
++
+ if (!count)
+ return;
+
+diff -urNp linux-2.6.38.7/drivers/net/igb/e1000_82575.c linux-2.6.38.7/drivers/net/igb/e1000_82575.c
+--- linux-2.6.38.7/drivers/net/igb/e1000_82575.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/igb/e1000_82575.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1747,7 +1747,7 @@ u16 igb_rxpbs_adjust_82580(u32 data)
+ return ret_val;
+ }
+
+-static struct e1000_mac_operations e1000_mac_ops_82575 = {
++static const struct e1000_mac_operations e1000_mac_ops_82575 = {
+ .init_hw = igb_init_hw_82575,
+ .check_for_link = igb_check_for_link_82575,
+ .rar_set = igb_rar_set,
+@@ -1755,13 +1755,13 @@ static struct e1000_mac_operations e1000
+ .get_speed_and_duplex = igb_get_speed_and_duplex_copper,
+ };
+
+-static struct e1000_phy_operations e1000_phy_ops_82575 = {
++static const struct e1000_phy_operations e1000_phy_ops_82575 = {
+ .acquire = igb_acquire_phy_82575,
+ .get_cfg_done = igb_get_cfg_done_82575,
+ .release = igb_release_phy_82575,
+ };
+
+-static struct e1000_nvm_operations e1000_nvm_ops_82575 = {
++static const struct e1000_nvm_operations e1000_nvm_ops_82575 = {
+ .acquire = igb_acquire_nvm_82575,
+ .read = igb_read_nvm_eerd,
+ .release = igb_release_nvm_82575,
+diff -urNp linux-2.6.38.7/drivers/net/igb/e1000_hw.h linux-2.6.38.7/drivers/net/igb/e1000_hw.h
+--- linux-2.6.38.7/drivers/net/igb/e1000_hw.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/igb/e1000_hw.h 2011-04-28 19:34:15.000000000 -0400
+@@ -327,22 +327,23 @@ struct e1000_phy_operations {
+ };
+
+ struct e1000_nvm_operations {
+- s32 (*acquire)(struct e1000_hw *);
+- s32 (*read)(struct e1000_hw *, u16, u16, u16 *);
+- void (*release)(struct e1000_hw *);
+- s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
++ s32 (* const acquire)(struct e1000_hw *);
++ s32 (* const read)(struct e1000_hw *, u16, u16, u16 *);
++ void (* const release)(struct e1000_hw *);
++ s32 (* const write)(struct e1000_hw *, u16, u16, u16 *);
+ };
+
+ struct e1000_info {
+ s32 (*get_invariants)(struct e1000_hw *);
+- struct e1000_mac_operations *mac_ops;
+- struct e1000_phy_operations *phy_ops;
+- struct e1000_nvm_operations *nvm_ops;
++ const struct e1000_mac_operations *mac_ops;
++ const struct e1000_phy_operations *phy_ops;
++ const struct e1000_nvm_operations *nvm_ops;
+ };
+
+ extern const struct e1000_info e1000_82575_info;
+
+ struct e1000_mac_info {
++ /* cannot be const see igb_get_invariants_82575() */
+ struct e1000_mac_operations ops;
+
+ u8 addr[6];
+@@ -381,6 +382,7 @@ struct e1000_mac_info {
+ };
+
+ struct e1000_phy_info {
++ /* cannot be const see igb_get_invariants_82575() */
+ struct e1000_phy_operations ops;
+
+ enum e1000_phy_type type;
+@@ -416,6 +418,7 @@ struct e1000_phy_info {
+ };
+
+ struct e1000_nvm_info {
++ /* cannot be const */
+ struct e1000_nvm_operations ops;
+
+ enum e1000_nvm_type type;
+diff -urNp linux-2.6.38.7/drivers/net/igbvf/vf.h linux-2.6.38.7/drivers/net/igbvf/vf.h
+--- linux-2.6.38.7/drivers/net/igbvf/vf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/igbvf/vf.h 2011-04-28 19:34:15.000000000 -0400
+@@ -191,6 +191,7 @@ struct e1000_mac_operations {
+ };
+
+ struct e1000_mac_info {
++ /* cannot be const see e1000_init_mac_params_vf() */
+ struct e1000_mac_operations ops;
+ u8 addr[6];
+ u8 perm_addr[6];
+diff -urNp linux-2.6.38.7/drivers/net/ixgb/ixgb_main.c linux-2.6.38.7/drivers/net/ixgb/ixgb_main.c
+--- linux-2.6.38.7/drivers/net/ixgb/ixgb_main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/ixgb/ixgb_main.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1072,6 +1072,8 @@ ixgb_set_multi(struct net_device *netdev
+ u32 rctl;
+ int i;
+
++ pax_track_stack();
++
+ /* Check for Promiscuous and All Multicast modes */
+
+ rctl = IXGB_READ_REG(hw, RCTL);
+diff -urNp linux-2.6.38.7/drivers/net/ixgb/ixgb_param.c linux-2.6.38.7/drivers/net/ixgb/ixgb_param.c
+--- linux-2.6.38.7/drivers/net/ixgb/ixgb_param.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/ixgb/ixgb_param.c 2011-05-16 21:47:08.000000000 -0400
+@@ -261,6 +261,9 @@ void __devinit
+ ixgb_check_options(struct ixgb_adapter *adapter)
+ {
+ int bd = adapter->bd_number;
++
++ pax_track_stack();
++
+ if (bd >= IXGB_MAX_NIC) {
+ pr_notice("Warning: no configuration for board #%i\n", bd);
+ pr_notice("Using defaults for all values\n");
+diff -urNp linux-2.6.38.7/drivers/net/ksz884x.c linux-2.6.38.7/drivers/net/ksz884x.c
+--- linux-2.6.38.7/drivers/net/ksz884x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/ksz884x.c 2011-05-16 21:47:08.000000000 -0400
+@@ -6536,6 +6536,8 @@ static void netdev_get_ethtool_stats(str
+ int rc;
+ u64 counter[TOTAL_PORT_COUNTER_NUM];
+
++ pax_track_stack();
++
+ mutex_lock(&hw_priv->lock);
+ n = SWITCH_PORT_NUM;
+ for (i = 0, p = port->first_port; i < port->mib_port_cnt; i++, p++) {
+diff -urNp linux-2.6.38.7/drivers/net/mlx4/main.c linux-2.6.38.7/drivers/net/mlx4/main.c
+--- linux-2.6.38.7/drivers/net/mlx4/main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/mlx4/main.c 2011-05-18 20:23:44.000000000 -0400
+@@ -39,6 +39,7 @@
+ #include <linux/pci.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/slab.h>
++#include <linux/sched.h>
+
+ #include <linux/mlx4/device.h>
+ #include <linux/mlx4/doorbell.h>
+@@ -737,6 +738,8 @@ static int mlx4_init_hca(struct mlx4_dev
+ u64 icm_size;
+ int err;
+
++ pax_track_stack();
++
+ err = mlx4_QUERY_FW(dev);
+ if (err) {
+ if (err == -EACCES)
+diff -urNp linux-2.6.38.7/drivers/net/niu.c linux-2.6.38.7/drivers/net/niu.c
+--- linux-2.6.38.7/drivers/net/niu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/niu.c 2011-05-16 21:47:08.000000000 -0400
+@@ -9067,6 +9067,8 @@ static void __devinit niu_try_msix(struc
+ int i, num_irqs, err;
+ u8 first_ldg;
+
++ pax_track_stack();
++
+ first_ldg = (NIU_NUM_LDG / parent->num_ports) * np->port;
+ for (i = 0; i < (NIU_NUM_LDG / parent->num_ports); i++)
+ ldg_num_map[i] = first_ldg + i;
+diff -urNp linux-2.6.38.7/drivers/net/pcnet32.c linux-2.6.38.7/drivers/net/pcnet32.c
+--- linux-2.6.38.7/drivers/net/pcnet32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/pcnet32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -82,7 +82,7 @@ static int cards_found;
+ /*
+ * VLB I/O addresses
+ */
+-static unsigned int pcnet32_portlist[] __initdata =
++static unsigned int pcnet32_portlist[] __devinitdata =
+ { 0x300, 0x320, 0x340, 0x360, 0 };
+
+ static int pcnet32_debug;
+diff -urNp linux-2.6.38.7/drivers/net/ppp_generic.c linux-2.6.38.7/drivers/net/ppp_generic.c
+--- linux-2.6.38.7/drivers/net/ppp_generic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/ppp_generic.c 2011-04-28 19:34:15.000000000 -0400
+@@ -986,7 +986,6 @@ ppp_net_ioctl(struct net_device *dev, st
+ void __user *addr = (void __user *) ifr->ifr_ifru.ifru_data;
+ struct ppp_stats stats;
+ struct ppp_comp_stats cstats;
+- char *vers;
+
+ switch (cmd) {
+ case SIOCGPPPSTATS:
+@@ -1008,8 +1007,7 @@ ppp_net_ioctl(struct net_device *dev, st
+ break;
+
+ case SIOCGPPPVER:
+- vers = PPP_VERSION;
+- if (copy_to_user(addr, vers, strlen(vers) + 1))
++ if (copy_to_user(addr, PPP_VERSION, sizeof(PPP_VERSION)))
+ break;
+ err = 0;
+ break;
+diff -urNp linux-2.6.38.7/drivers/net/tg3.c linux-2.6.38.7/drivers/net/tg3.c
+--- linux-2.6.38.7/drivers/net/tg3.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/tg3.c 2011-05-11 18:35:16.000000000 -0400
+@@ -13003,7 +13003,7 @@ done:
+
+ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
+
+-static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
++static inline void vlan_features_add(struct net_device *dev, unsigned long flags)
+ {
+ dev->vlan_features |= flags;
+ }
+diff -urNp linux-2.6.38.7/drivers/net/tg3.h linux-2.6.38.7/drivers/net/tg3.h
+--- linux-2.6.38.7/drivers/net/tg3.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/tg3.h 2011-04-28 19:34:15.000000000 -0400
+@@ -131,6 +131,7 @@
+ #define CHIPREV_ID_5750_A0 0x4000
+ #define CHIPREV_ID_5750_A1 0x4001
+ #define CHIPREV_ID_5750_A3 0x4003
++#define CHIPREV_ID_5750_C1 0x4201
+ #define CHIPREV_ID_5750_C2 0x4202
+ #define CHIPREV_ID_5752_A0_HW 0x5000
+ #define CHIPREV_ID_5752_A0 0x6000
+diff -urNp linux-2.6.38.7/drivers/net/tulip/de2104x.c linux-2.6.38.7/drivers/net/tulip/de2104x.c
+--- linux-2.6.38.7/drivers/net/tulip/de2104x.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/tulip/de2104x.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1817,6 +1817,8 @@ static void __devinit de21041_get_srom_i
+ struct de_srom_info_leaf *il;
+ void *bufp;
+
++ pax_track_stack();
++
+ /* download entire eeprom */
+ for (i = 0; i < DE_EEPROM_WORDS; i++)
+ ((__le16 *)ee_data)[i] =
+diff -urNp linux-2.6.38.7/drivers/net/tulip/de4x5.c linux-2.6.38.7/drivers/net/tulip/de4x5.c
+--- linux-2.6.38.7/drivers/net/tulip/de4x5.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/tulip/de4x5.c 2011-04-28 19:34:15.000000000 -0400
+@@ -5401,7 +5401,7 @@ de4x5_ioctl(struct net_device *dev, stru
+ for (i=0; i<ETH_ALEN; i++) {
+ tmp.addr[i] = dev->dev_addr[i];
+ }
+- if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
++ if (ioc->len > sizeof tmp.addr || copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
+ break;
+
+ case DE4X5_SET_HWADDR: /* Set the hardware address */
+@@ -5441,7 +5441,7 @@ de4x5_ioctl(struct net_device *dev, stru
+ spin_lock_irqsave(&lp->lock, flags);
+ memcpy(&statbuf, &lp->pktStats, ioc->len);
+ spin_unlock_irqrestore(&lp->lock, flags);
+- if (copy_to_user(ioc->data, &statbuf, ioc->len))
++ if (ioc->len > sizeof statbuf || copy_to_user(ioc->data, &statbuf, ioc->len))
+ return -EFAULT;
+ break;
+ }
+diff -urNp linux-2.6.38.7/drivers/net/usb/hso.c linux-2.6.38.7/drivers/net/usb/hso.c
+--- linux-2.6.38.7/drivers/net/usb/hso.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/usb/hso.c 2011-04-28 19:34:15.000000000 -0400
+@@ -71,7 +71,7 @@
+ #include <asm/byteorder.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial.h>
+-
++#include <asm/local.h>
+
+ #define MOD_AUTHOR "Option Wireless"
+ #define MOD_DESCRIPTION "USB High Speed Option driver"
+@@ -257,7 +257,7 @@ struct hso_serial {
+
+ /* from usb_serial_port */
+ struct tty_struct *tty;
+- int open_count;
++ local_t open_count;
+ spinlock_t serial_lock;
+
+ int (*write_data) (struct hso_serial *serial);
+@@ -1190,7 +1190,7 @@ static void put_rxbuf_data_and_resubmit_
+ struct urb *urb;
+
+ urb = serial->rx_urb[0];
+- if (serial->open_count > 0) {
++ if (local_read(&serial->open_count) > 0) {
+ count = put_rxbuf_data(urb, serial);
+ if (count == -1)
+ return;
+@@ -1226,7 +1226,7 @@ static void hso_std_serial_read_bulk_cal
+ DUMP1(urb->transfer_buffer, urb->actual_length);
+
+ /* Anyone listening? */
+- if (serial->open_count == 0)
++ if (local_read(&serial->open_count) == 0)
+ return;
+
+ if (status == 0) {
+@@ -1311,8 +1311,7 @@ static int hso_serial_open(struct tty_st
+ spin_unlock_irq(&serial->serial_lock);
+
+ /* check for port already opened, if not set the termios */
+- serial->open_count++;
+- if (serial->open_count == 1) {
++ if (local_inc_return(&serial->open_count) == 1) {
+ serial->rx_state = RX_IDLE;
+ /* Force default termio settings */
+ _hso_serial_set_termios(tty, NULL);
+@@ -1324,7 +1323,7 @@ static int hso_serial_open(struct tty_st
+ result = hso_start_serial_device(serial->parent, GFP_KERNEL);
+ if (result) {
+ hso_stop_serial_device(serial->parent);
+- serial->open_count--;
++ local_dec(&serial->open_count);
+ kref_put(&serial->parent->ref, hso_serial_ref_free);
+ }
+ } else {
+@@ -1361,10 +1360,10 @@ static void hso_serial_close(struct tty_
+
+ /* reset the rts and dtr */
+ /* do the actual close */
+- serial->open_count--;
++ local_dec(&serial->open_count);
+
+- if (serial->open_count <= 0) {
+- serial->open_count = 0;
++ if (local_read(&serial->open_count) <= 0) {
++ local_set(&serial->open_count, 0);
+ spin_lock_irq(&serial->serial_lock);
+ if (serial->tty == tty) {
+ serial->tty->driver_data = NULL;
+@@ -1446,7 +1445,7 @@ static void hso_serial_set_termios(struc
+
+ /* the actual setup */
+ spin_lock_irqsave(&serial->serial_lock, flags);
+- if (serial->open_count)
++ if (local_read(&serial->open_count))
+ _hso_serial_set_termios(tty, old);
+ else
+ tty->termios = old;
+@@ -1905,7 +1904,7 @@ static void intr_callback(struct urb *ur
+ D1("Pending read interrupt on port %d\n", i);
+ spin_lock(&serial->serial_lock);
+ if (serial->rx_state == RX_IDLE &&
+- serial->open_count > 0) {
++ local_read(&serial->open_count) > 0) {
+ /* Setup and send a ctrl req read on
+ * port i */
+ if (!serial->rx_urb_filled[0]) {
+@@ -3097,7 +3096,7 @@ static int hso_resume(struct usb_interfa
+ /* Start all serial ports */
+ for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
+ if (serial_table[i] && (serial_table[i]->interface == iface)) {
+- if (dev2ser(serial_table[i])->open_count) {
++ if (local_read(&dev2ser(serial_table[i])->open_count)) {
+ result =
+ hso_start_serial_device(serial_table[i], GFP_NOIO);
+ hso_kick_transmit(dev2ser(serial_table[i]));
+diff -urNp linux-2.6.38.7/drivers/net/vmxnet3/vmxnet3_ethtool.c linux-2.6.38.7/drivers/net/vmxnet3/vmxnet3_ethtool.c
+--- linux-2.6.38.7/drivers/net/vmxnet3/vmxnet3_ethtool.c 2011-05-22 23:05:19.000000000 -0400
++++ linux-2.6.38.7/drivers/net/vmxnet3/vmxnet3_ethtool.c 2011-05-22 23:06:03.000000000 -0400
+@@ -631,8 +631,7 @@ vmxnet3_set_rss_indir(struct net_device
+ * Return with error code if any of the queue indices
+ * is out of range
+ */
+- if (p->ring_index[i] < 0 ||
+- p->ring_index[i] >= adapter->num_rx_queues)
++ if (p->ring_index[i] >= adapter->num_rx_queues)
+ return -EINVAL;
+ }
+
+diff -urNp linux-2.6.38.7/drivers/net/vxge/vxge-main.c linux-2.6.38.7/drivers/net/vxge/vxge-main.c
+--- linux-2.6.38.7/drivers/net/vxge/vxge-main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/vxge/vxge-main.c 2011-05-16 21:47:08.000000000 -0400
+@@ -97,6 +97,8 @@ static inline void VXGE_COMPLETE_VPATH_T
+ struct sk_buff *completed[NR_SKB_COMPLETED];
+ int more;
+
++ pax_track_stack();
++
+ do {
+ more = 0;
+ skb_ptr = completed;
+@@ -1889,6 +1891,8 @@ static enum vxge_hw_status vxge_rth_conf
+ u8 mtable[256] = {0}; /* CPU to vpath mapping */
+ int index;
+
++ pax_track_stack();
++
+ /*
+ * Filling
+ * - itable with bucket numbers
+diff -urNp linux-2.6.38.7/drivers/net/wan/cycx_x25.c linux-2.6.38.7/drivers/net/wan/cycx_x25.c
+--- linux-2.6.38.7/drivers/net/wan/cycx_x25.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wan/cycx_x25.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1018,6 +1018,8 @@ static void hex_dump(char *msg, unsigned
+ unsigned char hex[1024],
+ * phex = hex;
+
++ pax_track_stack();
++
+ if (len >= (sizeof(hex) / 2))
+ len = (sizeof(hex) / 2) - 1;
+
+diff -urNp linux-2.6.38.7/drivers/net/wimax/i2400m/usb-fw.c linux-2.6.38.7/drivers/net/wimax/i2400m/usb-fw.c
+--- linux-2.6.38.7/drivers/net/wimax/i2400m/usb-fw.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wimax/i2400m/usb-fw.c 2011-05-16 21:47:08.000000000 -0400
+@@ -287,6 +287,8 @@ ssize_t i2400mu_bus_bm_wait_for_ack(stru
+ int do_autopm = 1;
+ DECLARE_COMPLETION_ONSTACK(notif_completion);
+
++ pax_track_stack();
++
+ d_fnstart(8, dev, "(i2400m %p ack %p size %zu)\n",
+ i2400m, ack, ack_size);
+ BUG_ON(_ack == i2400m->bm_ack_buf);
+diff -urNp linux-2.6.38.7/drivers/net/wireless/airo.c linux-2.6.38.7/drivers/net/wireless/airo.c
+--- linux-2.6.38.7/drivers/net/wireless/airo.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/airo.c 2011-05-16 21:47:08.000000000 -0400
+@@ -3001,6 +3001,8 @@ static void airo_process_scan_results (s
+ BSSListElement * loop_net;
+ BSSListElement * tmp_net;
+
++ pax_track_stack();
++
+ /* Blow away current list of scan results */
+ list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) {
+ list_move_tail (&loop_net->list, &ai->network_free_list);
+@@ -3792,6 +3794,8 @@ static u16 setup_card(struct airo_info *
+ WepKeyRid wkr;
+ int rc;
+
++ pax_track_stack();
++
+ memset( &mySsid, 0, sizeof( mySsid ) );
+ kfree (ai->flash);
+ ai->flash = NULL;
+@@ -4760,6 +4764,8 @@ static int proc_stats_rid_open( struct i
+ __le32 *vals = stats.vals;
+ int len;
+
++ pax_track_stack();
++
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ data = file->private_data;
+@@ -5483,6 +5489,8 @@ static int proc_BSSList_open( struct ino
+ /* If doLoseSync is not 1, we won't do a Lose Sync */
+ int doLoseSync = -1;
+
++ pax_track_stack();
++
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ data = file->private_data;
+@@ -7190,6 +7198,8 @@ static int airo_get_aplist(struct net_de
+ int i;
+ int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
+
++ pax_track_stack();
++
+ qual = kmalloc(IW_MAX_AP * sizeof(*qual), GFP_KERNEL);
+ if (!qual)
+ return -ENOMEM;
+@@ -7750,6 +7760,8 @@ static void airo_read_wireless_stats(str
+ CapabilityRid cap_rid;
+ __le32 *vals = stats_rid.vals;
+
++ pax_track_stack();
++
+ /* Get stats out of the card */
+ clear_bit(JOB_WSTATS, &local->jobs);
+ if (local->power.event) {
+diff -urNp linux-2.6.38.7/drivers/net/wireless/ath/ath5k/debug.c linux-2.6.38.7/drivers/net/wireless/ath/ath5k/debug.c
+--- linux-2.6.38.7/drivers/net/wireless/ath/ath5k/debug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/ath/ath5k/debug.c 2011-05-16 21:47:08.000000000 -0400
+@@ -204,6 +204,8 @@ static ssize_t read_file_beacon(struct f
+ unsigned int v;
+ u64 tsf;
+
++ pax_track_stack();
++
+ v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
+@@ -325,6 +327,8 @@ static ssize_t read_file_debug(struct fi
+ unsigned int len = 0;
+ unsigned int i;
+
++ pax_track_stack();
++
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
+
+@@ -386,6 +390,8 @@ static ssize_t read_file_antenna(struct
+ unsigned int i;
+ unsigned int v;
+
++ pax_track_stack();
++
+ len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n",
+ sc->ah->ah_ant_mode);
+ len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n",
+@@ -496,6 +502,8 @@ static ssize_t read_file_misc(struct fil
+ unsigned int len = 0;
+ u32 filt = ath5k_hw_get_rx_filter(sc->ah);
+
++ pax_track_stack();
++
+ len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n",
+ sc->bssidmask);
+ len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ",
+@@ -552,6 +560,8 @@ static ssize_t read_file_frameerrors(str
+ unsigned int len = 0;
+ int i;
+
++ pax_track_stack();
++
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "RX\n---------------------\n");
+ len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n",
+@@ -669,6 +679,8 @@ static ssize_t read_file_ani(struct file
+ char buf[700];
+ unsigned int len = 0;
+
++ pax_track_stack();
++
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "HW has PHY error counters:\t%s\n",
+ sc->ah->ah_capabilities.cap_has_phyerr_counters ?
+@@ -829,6 +841,8 @@ static ssize_t read_file_queue(struct fi
+ struct ath5k_buf *bf, *bf0;
+ int i, n;
+
++ pax_track_stack();
++
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "available txbuffers: %d\n", sc->txbuf_len);
+
+diff -urNp linux-2.6.38.7/drivers/net/wireless/ath/ath9k/ar9003_calib.c linux-2.6.38.7/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+--- linux-2.6.38.7/drivers/net/wireless/ath/ath9k/ar9003_calib.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/ath/ath9k/ar9003_calib.c 2011-05-16 21:47:08.000000000 -0400
+@@ -734,6 +734,8 @@ static void ar9003_hw_tx_iq_cal(struct a
+ s32 i, j, ip, im, nmeasurement;
+ u8 nchains = get_streams(common->tx_chainmask);
+
++ pax_track_stack();
++
+ for (ip = 0; ip < MPASS; ip++) {
+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
+ AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
+@@ -856,6 +858,8 @@ static void ar9003_hw_tx_iq_cal_post_pro
+ int i, ip, im, j;
+ int nmeasurement;
+
++ pax_track_stack();
++
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (ah->txchainmask & (1 << i))
+ num_chains++;
+diff -urNp linux-2.6.38.7/drivers/net/wireless/ath/ath9k/ar9003_paprd.c linux-2.6.38.7/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+--- linux-2.6.38.7/drivers/net/wireless/ath/ath9k/ar9003_paprd.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/ath/ath9k/ar9003_paprd.c 2011-05-16 21:47:08.000000000 -0400
+@@ -356,6 +356,8 @@ static bool create_pa_curve(u32 *data_L,
+ int theta_low_bin = 0;
+ int i;
+
++ pax_track_stack();
++
+ /* disregard any bin that contains <= 16 samples */
+ thresh_accum_cnt = 16;
+ scale_factor = 5;
+diff -urNp linux-2.6.38.7/drivers/net/wireless/ath/ath9k/debug.c linux-2.6.38.7/drivers/net/wireless/ath/ath9k/debug.c
+--- linux-2.6.38.7/drivers/net/wireless/ath/ath9k/debug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/ath/ath9k/debug.c 2011-05-16 21:47:08.000000000 -0400
+@@ -321,6 +321,8 @@ static ssize_t read_file_interrupt(struc
+ char buf[512];
+ unsigned int len = 0;
+
++ pax_track_stack();
++
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp);
+@@ -410,6 +412,8 @@ static ssize_t read_file_wiphy(struct fi
+ u8 addr[ETH_ALEN];
+ u32 tmp;
+
++ pax_track_stack();
++
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "primary: %s (%s chan=%d ht=%d)\n",
+ wiphy_name(sc->pri_wiphy->hw->wiphy),
+diff -urNp linux-2.6.38.7/drivers/net/wireless/ath/ath9k/htc_drv_main.c linux-2.6.38.7/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+--- linux-2.6.38.7/drivers/net/wireless/ath/ath9k/htc_drv_main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/ath/ath9k/htc_drv_main.c 2011-05-16 21:47:08.000000000 -0400
+@@ -620,6 +620,8 @@ static ssize_t read_file_tgt_stats(struc
+ unsigned int len = 0;
+ int ret = 0;
+
++ pax_track_stack();
++
+ memset(&cmd_rsp, 0, sizeof(cmd_rsp));
+
+ WMI_CMD(WMI_TGT_STATS_CMDID);
+@@ -665,6 +667,8 @@ static ssize_t read_file_xmit(struct fil
+ char buf[512];
+ unsigned int len = 0;
+
++ pax_track_stack();
++
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "Buffers queued",
+ priv->debug.tx_stats.buf_queued);
+@@ -714,6 +718,8 @@ static ssize_t read_file_recv(struct fil
+ char buf[512];
+ unsigned int len = 0;
+
++ pax_track_stack();
++
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "SKBs allocated",
+ priv->debug.rx_stats.skb_allocated);
+diff -urNp linux-2.6.38.7/drivers/net/wireless/b43/debugfs.c linux-2.6.38.7/drivers/net/wireless/b43/debugfs.c
+--- linux-2.6.38.7/drivers/net/wireless/b43/debugfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/b43/debugfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -43,7 +43,7 @@ static struct dentry *rootdir;
+ struct b43_debugfs_fops {
+ ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize);
+ int (*write)(struct b43_wldev *dev, const char *buf, size_t count);
+- struct file_operations fops;
++ const struct file_operations fops;
+ /* Offset of struct b43_dfs_file in struct b43_dfsentry */
+ size_t file_struct_offset;
+ };
+diff -urNp linux-2.6.38.7/drivers/net/wireless/b43legacy/debugfs.c linux-2.6.38.7/drivers/net/wireless/b43legacy/debugfs.c
+--- linux-2.6.38.7/drivers/net/wireless/b43legacy/debugfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/b43legacy/debugfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -44,7 +44,7 @@ static struct dentry *rootdir;
+ struct b43legacy_debugfs_fops {
+ ssize_t (*read)(struct b43legacy_wldev *dev, char *buf, size_t bufsize);
+ int (*write)(struct b43legacy_wldev *dev, const char *buf, size_t count);
+- struct file_operations fops;
++ const struct file_operations fops;
+ /* Offset of struct b43legacy_dfs_file in struct b43legacy_dfsentry */
+ size_t file_struct_offset;
+ /* Take wl->irq_lock before calling read/write? */
+diff -urNp linux-2.6.38.7/drivers/net/wireless/ipw2x00/ipw2100.c linux-2.6.38.7/drivers/net/wireless/ipw2x00/ipw2100.c
+--- linux-2.6.38.7/drivers/net/wireless/ipw2x00/ipw2100.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/ipw2x00/ipw2100.c 2011-05-16 21:47:08.000000000 -0400
+@@ -2101,6 +2101,8 @@ static int ipw2100_set_essid(struct ipw2
+ int err;
+ DECLARE_SSID_BUF(ssid);
+
++ pax_track_stack();
++
+ IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len));
+
+ if (ssid_len)
+@@ -5455,6 +5457,8 @@ static int ipw2100_set_key(struct ipw210
+ struct ipw2100_wep_key *wep_key = (void *)cmd.host_command_parameters;
+ int err;
+
++ pax_track_stack();
++
+ IPW_DEBUG_HC("WEP_KEY_INFO: index = %d, len = %d/%d\n",
+ idx, keylen, len);
+
+diff -urNp linux-2.6.38.7/drivers/net/wireless/ipw2x00/libipw_rx.c linux-2.6.38.7/drivers/net/wireless/ipw2x00/libipw_rx.c
+--- linux-2.6.38.7/drivers/net/wireless/ipw2x00/libipw_rx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/ipw2x00/libipw_rx.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1565,6 +1565,8 @@ static void libipw_process_probe_respons
+ unsigned long flags;
+ DECLARE_SSID_BUF(ssid);
+
++ pax_track_stack();
++
+ LIBIPW_DEBUG_SCAN("'%s' (%pM"
+ "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ print_ssid(ssid, info_element->data, info_element->len),
+diff -urNp linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-agn-rs.c linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+--- linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-agn-rs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-agn-rs.c 2011-05-16 21:47:08.000000000 -0400
+@@ -883,6 +883,8 @@ static void rs_tx_status(void *priv_r, s
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
++ pax_track_stack();
++
+ IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
+
+ /* Treat uninitialized rate scaling data same as non-existing. */
+@@ -2892,6 +2894,8 @@ static void rs_fill_link_cmd(struct iwl_
+ u8 valid_tx_ant = 0;
+ struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq;
+
++ pax_track_stack();
++
+ /* Override starting rate (index 0) if needed for debug purposes */
+ rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+diff -urNp linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-debugfs.c linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+--- linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-debugfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-debugfs.c 2011-05-16 21:47:08.000000000 -0400
+@@ -518,6 +518,8 @@ static ssize_t iwl_dbgfs_status_read(str
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+
++ pax_track_stack();
++
+ pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
+ test_bit(STATUS_HCMD_ACTIVE, &priv->status));
+ pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
+@@ -650,6 +652,8 @@ static ssize_t iwl_dbgfs_qos_read(struct
+ char buf[256 * NUM_IWL_RXON_CTX];
+ const size_t bufsz = sizeof(buf);
+
++ pax_track_stack();
++
+ for_each_context(priv, ctx) {
+ pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
+ ctx->ctxid);
+diff -urNp linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-debug.h linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-debug.h
+--- linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-debug.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/iwlwifi/iwl-debug.h 2011-04-28 19:34:15.000000000 -0400
+@@ -68,8 +68,8 @@ do {
+ } while (0)
+
+ #else
+-#define IWL_DEBUG(__priv, level, fmt, args...)
+-#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
++#define IWL_DEBUG(__priv, level, fmt, args...) do {} while (0)
++#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) do {} while (0)
+ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
+ const void *p, u32 len)
+ {}
+diff -urNp linux-2.6.38.7/drivers/net/wireless/iwmc3200wifi/debugfs.c linux-2.6.38.7/drivers/net/wireless/iwmc3200wifi/debugfs.c
+--- linux-2.6.38.7/drivers/net/wireless/iwmc3200wifi/debugfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/iwmc3200wifi/debugfs.c 2011-05-16 21:47:08.000000000 -0400
+@@ -327,6 +327,8 @@ static ssize_t iwm_debugfs_fw_err_read(s
+ int buf_len = 512;
+ size_t len = 0;
+
++ pax_track_stack();
++
+ if (*ppos != 0)
+ return 0;
+ if (count < sizeof(buf))
+diff -urNp linux-2.6.38.7/drivers/net/wireless/libertas/debugfs.c linux-2.6.38.7/drivers/net/wireless/libertas/debugfs.c
+--- linux-2.6.38.7/drivers/net/wireless/libertas/debugfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/libertas/debugfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -702,7 +702,7 @@ out_unlock:
+ struct lbs_debugfs_files {
+ const char *name;
+ int perm;
+- struct file_operations fops;
++ const struct file_operations fops;
+ };
+
+ static const struct lbs_debugfs_files debugfs_files[] = {
+diff -urNp linux-2.6.38.7/drivers/net/wireless/rndis_wlan.c linux-2.6.38.7/drivers/net/wireless/rndis_wlan.c
+--- linux-2.6.38.7/drivers/net/wireless/rndis_wlan.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/rndis_wlan.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1277,7 +1277,7 @@ static int set_rts_threshold(struct usbn
+
+ netdev_dbg(usbdev->net, "%s(): %i\n", __func__, rts_threshold);
+
+- if (rts_threshold < 0 || rts_threshold > 2347)
++ if (rts_threshold > 2347)
+ rts_threshold = 2347;
+
+ tmp = cpu_to_le32(rts_threshold);
+diff -urNp linux-2.6.38.7/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c linux-2.6.38.7/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+--- linux-2.6.38.7/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1277,6 +1277,8 @@ static bool _rtl92c_phy_sw_chnl_step_by_
+ u8 rfpath;
+ u8 num_total_rfpath = rtlphy->num_total_rfpath;
+
++ pax_track_stack();
++
+ precommoncmdcnt = 0;
+ _rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+ MAX_PRECMD_CNT,
+diff -urNp linux-2.6.38.7/drivers/net/wireless/wl12xx/spi.c linux-2.6.38.7/drivers/net/wireless/wl12xx/spi.c
+--- linux-2.6.38.7/drivers/net/wireless/wl12xx/spi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/net/wireless/wl12xx/spi.c 2011-05-16 21:47:08.000000000 -0400
+@@ -279,6 +279,8 @@ static void wl1271_spi_raw_write(struct
+ u32 chunk_len;
+ int i;
+
++ pax_track_stack();
++
+ WARN_ON(len > WL1271_AGGR_BUFFER_SIZE);
+
+ spi_message_init(&m);
+diff -urNp linux-2.6.38.7/drivers/oprofile/buffer_sync.c linux-2.6.38.7/drivers/oprofile/buffer_sync.c
+--- linux-2.6.38.7/drivers/oprofile/buffer_sync.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/oprofile/buffer_sync.c 2011-04-28 19:34:15.000000000 -0400
+@@ -342,7 +342,7 @@ static void add_data(struct op_entry *en
+ if (cookie == NO_COOKIE)
+ offset = pc;
+ if (cookie == INVALID_COOKIE) {
+- atomic_inc(&oprofile_stats.sample_lost_no_mapping);
++ atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mapping);
+ offset = pc;
+ }
+ if (cookie != last_cookie) {
+@@ -386,14 +386,14 @@ add_sample(struct mm_struct *mm, struct
+ /* add userspace sample */
+
+ if (!mm) {
+- atomic_inc(&oprofile_stats.sample_lost_no_mm);
++ atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mm);
+ return 0;
+ }
+
+ cookie = lookup_dcookie(mm, s->eip, &offset);
+
+ if (cookie == INVALID_COOKIE) {
+- atomic_inc(&oprofile_stats.sample_lost_no_mapping);
++ atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mapping);
+ return 0;
+ }
+
+@@ -562,7 +562,7 @@ void sync_buffer(int cpu)
+ /* ignore backtraces if failed to add a sample */
+ if (state == sb_bt_start) {
+ state = sb_bt_ignore;
+- atomic_inc(&oprofile_stats.bt_lost_no_mapping);
++ atomic_inc_unchecked(&oprofile_stats.bt_lost_no_mapping);
+ }
+ }
+ release_mm(mm);
+diff -urNp linux-2.6.38.7/drivers/oprofile/event_buffer.c linux-2.6.38.7/drivers/oprofile/event_buffer.c
+--- linux-2.6.38.7/drivers/oprofile/event_buffer.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/oprofile/event_buffer.c 2011-04-28 19:34:15.000000000 -0400
+@@ -53,7 +53,7 @@ void add_event_entry(unsigned long value
+ }
+
+ if (buffer_pos == buffer_size) {
+- atomic_inc(&oprofile_stats.event_lost_overflow);
++ atomic_inc_unchecked(&oprofile_stats.event_lost_overflow);
+ return;
+ }
+
+diff -urNp linux-2.6.38.7/drivers/oprofile/oprof.c linux-2.6.38.7/drivers/oprofile/oprof.c
+--- linux-2.6.38.7/drivers/oprofile/oprof.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/oprofile/oprof.c 2011-04-28 19:34:15.000000000 -0400
+@@ -110,7 +110,7 @@ static void switch_worker(struct work_st
+ if (oprofile_ops.switch_events())
+ return;
+
+- atomic_inc(&oprofile_stats.multiplex_counter);
++ atomic_inc_unchecked(&oprofile_stats.multiplex_counter);
+ start_switch_worker();
+ }
+
+diff -urNp linux-2.6.38.7/drivers/oprofile/oprofilefs.c linux-2.6.38.7/drivers/oprofile/oprofilefs.c
+--- linux-2.6.38.7/drivers/oprofile/oprofilefs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/oprofile/oprofilefs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -186,7 +186,7 @@ static const struct file_operations atom
+
+
+ int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root,
+- char const *name, atomic_t *val)
++ char const *name, atomic_unchecked_t *val)
+ {
+ return __oprofilefs_create_file(sb, root, name,
+ &atomic_ro_fops, 0444, val);
+diff -urNp linux-2.6.38.7/drivers/oprofile/oprofile_stats.c linux-2.6.38.7/drivers/oprofile/oprofile_stats.c
+--- linux-2.6.38.7/drivers/oprofile/oprofile_stats.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/oprofile/oprofile_stats.c 2011-04-28 19:34:15.000000000 -0400
+@@ -30,11 +30,11 @@ void oprofile_reset_stats(void)
+ cpu_buf->sample_invalid_eip = 0;
+ }
+
+- atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
+- atomic_set(&oprofile_stats.sample_lost_no_mapping, 0);
+- atomic_set(&oprofile_stats.event_lost_overflow, 0);
+- atomic_set(&oprofile_stats.bt_lost_no_mapping, 0);
+- atomic_set(&oprofile_stats.multiplex_counter, 0);
++ atomic_set_unchecked(&oprofile_stats.sample_lost_no_mm, 0);
++ atomic_set_unchecked(&oprofile_stats.sample_lost_no_mapping, 0);
++ atomic_set_unchecked(&oprofile_stats.event_lost_overflow, 0);
++ atomic_set_unchecked(&oprofile_stats.bt_lost_no_mapping, 0);
++ atomic_set_unchecked(&oprofile_stats.multiplex_counter, 0);
+ }
+
+
+diff -urNp linux-2.6.38.7/drivers/oprofile/oprofile_stats.h linux-2.6.38.7/drivers/oprofile/oprofile_stats.h
+--- linux-2.6.38.7/drivers/oprofile/oprofile_stats.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/oprofile/oprofile_stats.h 2011-04-28 19:34:15.000000000 -0400
+@@ -13,11 +13,11 @@
+ #include <asm/atomic.h>
+
+ struct oprofile_stat_struct {
+- atomic_t sample_lost_no_mm;
+- atomic_t sample_lost_no_mapping;
+- atomic_t bt_lost_no_mapping;
+- atomic_t event_lost_overflow;
+- atomic_t multiplex_counter;
++ atomic_unchecked_t sample_lost_no_mm;
++ atomic_unchecked_t sample_lost_no_mapping;
++ atomic_unchecked_t bt_lost_no_mapping;
++ atomic_unchecked_t event_lost_overflow;
++ atomic_unchecked_t multiplex_counter;
+ };
+
+ extern struct oprofile_stat_struct oprofile_stats;
+diff -urNp linux-2.6.38.7/drivers/parport/procfs.c linux-2.6.38.7/drivers/parport/procfs.c
+--- linux-2.6.38.7/drivers/parport/procfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/parport/procfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -64,7 +64,7 @@ static int do_active_device(ctl_table *t
+
+ *ppos += len;
+
+- return copy_to_user(result, buffer, len) ? -EFAULT : 0;
++ return (len > sizeof buffer || copy_to_user(result, buffer, len)) ? -EFAULT : 0;
+ }
+
+ #ifdef CONFIG_PARPORT_1284
+@@ -106,7 +106,7 @@ static int do_autoprobe(ctl_table *table
+
+ *ppos += len;
+
+- return copy_to_user (result, buffer, len) ? -EFAULT : 0;
++ return (len > sizeof buffer || copy_to_user (result, buffer, len)) ? -EFAULT : 0;
+ }
+ #endif /* IEEE1284.3 support. */
+
+diff -urNp linux-2.6.38.7/drivers/pci/hotplug/acpiphp_glue.c linux-2.6.38.7/drivers/pci/hotplug/acpiphp_glue.c
+--- linux-2.6.38.7/drivers/pci/hotplug/acpiphp_glue.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/drivers/pci/hotplug/acpiphp_glue.c 2011-04-28 19:34:15.000000000 -0400
+@@ -110,7 +110,7 @@ static int post_dock_fixups(struct notif
+ }
+
+
+-static struct acpi_dock_ops acpiphp_dock_ops = {
++static const struct acpi_dock_ops acpiphp_dock_ops = {
+ .handler = handle_hotplug_event_func,
+ };
+
+diff -urNp linux-2.6.38.7/drivers/pci/hotplug/cpqphp_nvram.c linux-2.6.38.7/drivers/pci/hotplug/cpqphp_nvram.c
+--- linux-2.6.38.7/drivers/pci/hotplug/cpqphp_nvram.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/pci/hotplug/cpqphp_nvram.c 2011-04-28 19:34:15.000000000 -0400
+@@ -428,9 +428,13 @@ static u32 store_HRT (void __iomem *rom_
+
+ void compaq_nvram_init (void __iomem *rom_start)
+ {
++
++#ifndef CONFIG_PAX_KERNEXEC
+ if (rom_start) {
+ compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
+ }
++#endif
++
+ dbg("int15 entry = %p\n", compaq_int15_entry_point);
+
+ /* initialize our int15 lock */
+diff -urNp linux-2.6.38.7/drivers/pci/intel-iommu.c linux-2.6.38.7/drivers/pci/intel-iommu.c
+--- linux-2.6.38.7/drivers/pci/intel-iommu.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/drivers/pci/intel-iommu.c 2011-05-10 22:06:56.000000000 -0400
+@@ -2934,7 +2934,7 @@ static int intel_mapping_error(struct de
+ return !dma_addr;
+ }
+
+-struct dma_map_ops intel_dma_ops = {
++const struct dma_map_ops intel_dma_ops = {
+ .alloc_coherent = intel_alloc_coherent,
+ .free_coherent = intel_free_coherent,
+ .map_sg = intel_map_sg,
+diff -urNp linux-2.6.38.7/drivers/pci/pcie/aspm.c linux-2.6.38.7/drivers/pci/pcie/aspm.c
+--- linux-2.6.38.7/drivers/pci/pcie/aspm.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/drivers/pci/pcie/aspm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -27,9 +27,9 @@
+ #define MODULE_PARAM_PREFIX "pcie_aspm."
+
+ /* Note: those are not register definitions */
+-#define ASPM_STATE_L0S_UP (1) /* Upstream direction L0s state */
+-#define ASPM_STATE_L0S_DW (2) /* Downstream direction L0s state */
+-#define ASPM_STATE_L1 (4) /* L1 state */
++#define ASPM_STATE_L0S_UP (1U) /* Upstream direction L0s state */
++#define ASPM_STATE_L0S_DW (2U) /* Downstream direction L0s state */
++#define ASPM_STATE_L1 (4U) /* L1 state */
+ #define ASPM_STATE_L0S (ASPM_STATE_L0S_UP | ASPM_STATE_L0S_DW)
+ #define ASPM_STATE_ALL (ASPM_STATE_L0S | ASPM_STATE_L1)
+
+diff -urNp linux-2.6.38.7/drivers/pci/probe.c linux-2.6.38.7/drivers/pci/probe.c
+--- linux-2.6.38.7/drivers/pci/probe.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/pci/probe.c 2011-04-28 19:34:15.000000000 -0400
+@@ -62,14 +62,14 @@ static ssize_t pci_bus_show_cpuaffinity(
+ return ret;
+ }
+
+-static ssize_t inline pci_bus_show_cpumaskaffinity(struct device *dev,
++static inline ssize_t pci_bus_show_cpumaskaffinity(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+ {
+ return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
+ }
+
+-static ssize_t inline pci_bus_show_cpulistaffinity(struct device *dev,
++static inline ssize_t pci_bus_show_cpulistaffinity(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+ {
+@@ -165,7 +165,7 @@ int __pci_read_base(struct pci_dev *dev,
+ u32 l, sz, mask;
+ u16 orig_cmd;
+
+- mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
++ mask = type ? (u32)PCI_ROM_ADDRESS_MASK : ~0;
+
+ if (!dev->mmio_always_on) {
+ pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
+diff -urNp linux-2.6.38.7/drivers/pci/proc.c linux-2.6.38.7/drivers/pci/proc.c
+--- linux-2.6.38.7/drivers/pci/proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/pci/proc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -476,7 +476,16 @@ static const struct file_operations proc
+ static int __init pci_proc_init(void)
+ {
+ struct pci_dev *dev = NULL;
++
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ proc_bus_pci_dir = proc_mkdir_mode("bus/pci", S_IRUSR | S_IXUSR, NULL);
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ proc_bus_pci_dir = proc_mkdir_mode("bus/pci", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
++#endif
++#else
+ proc_bus_pci_dir = proc_mkdir("bus/pci", NULL);
++#endif
+ proc_create("devices", 0, proc_bus_pci_dir,
+ &proc_bus_pci_dev_operations);
+ proc_initialized = 1;
+diff -urNp linux-2.6.38.7/drivers/pci/xen-pcifront.c linux-2.6.38.7/drivers/pci/xen-pcifront.c
+--- linux-2.6.38.7/drivers/pci/xen-pcifront.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/pci/xen-pcifront.c 2011-05-16 21:47:08.000000000 -0400
+@@ -187,6 +187,8 @@ static int pcifront_bus_read(struct pci_
+ struct pcifront_sd *sd = bus->sysdata;
+ struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
++ pax_track_stack();
++
+ if (verbose_request)
+ dev_info(&pdev->xdev->dev,
+ "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n",
+@@ -226,6 +228,8 @@ static int pcifront_bus_write(struct pci
+ struct pcifront_sd *sd = bus->sysdata;
+ struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
++ pax_track_stack();
++
+ if (verbose_request)
+ dev_info(&pdev->xdev->dev,
+ "write dev=%04x:%02x:%02x.%01x - "
+@@ -258,6 +262,8 @@ static int pci_frontend_enable_msix(stru
+ struct pcifront_device *pdev = pcifront_get_pdev(sd);
+ struct msi_desc *entry;
+
++ pax_track_stack();
++
+ if (nvec > SH_INFO_MAX_VEC) {
+ dev_err(&dev->dev, "too much vector for pci frontend: %x."
+ " Increase SH_INFO_MAX_VEC.\n", nvec);
+@@ -303,6 +309,8 @@ static void pci_frontend_disable_msix(st
+ struct pcifront_sd *sd = dev->bus->sysdata;
+ struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
++ pax_track_stack();
++
+ err = do_pci_op(pdev, &op);
+
+ /* What should do for error ? */
+@@ -322,6 +330,8 @@ static int pci_frontend_enable_msi(struc
+ struct pcifront_sd *sd = dev->bus->sysdata;
+ struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
++ pax_track_stack();
++
+ err = do_pci_op(pdev, &op);
+ if (likely(!err)) {
+ *(*vector) = op.value;
+diff -urNp linux-2.6.38.7/drivers/platform/x86/asus-laptop.c linux-2.6.38.7/drivers/platform/x86/asus-laptop.c
+--- linux-2.6.38.7/drivers/platform/x86/asus-laptop.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/platform/x86/asus-laptop.c 2011-04-28 19:34:15.000000000 -0400
+@@ -243,7 +243,6 @@ struct asus_laptop {
+ struct asus_led gled;
+ struct asus_led kled;
+ struct workqueue_struct *led_workqueue;
+-
+ int wireless_status;
+ bool have_rsts;
+ int lcd_state;
+diff -urNp linux-2.6.38.7/drivers/pnp/pnpbios/bioscalls.c linux-2.6.38.7/drivers/pnp/pnpbios/bioscalls.c
+--- linux-2.6.38.7/drivers/pnp/pnpbios/bioscalls.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/pnp/pnpbios/bioscalls.c 2011-04-28 19:34:15.000000000 -0400
+@@ -59,7 +59,7 @@ do { \
+ set_desc_limit(&gdt[(selname) >> 3], (size) - 1); \
+ } while(0)
+
+-static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
++static const struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4093,
+ (unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1);
+
+ /*
+@@ -96,7 +96,10 @@ static inline u16 call_pnp_bios(u16 func
+
+ cpu = get_cpu();
+ save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8];
++
++ pax_open_kernel();
+ get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc;
++ pax_close_kernel();
+
+ /* On some boxes IRQ's during PnP BIOS calls are deadly. */
+ spin_lock_irqsave(&pnp_bios_lock, flags);
+@@ -134,7 +137,10 @@ static inline u16 call_pnp_bios(u16 func
+ :"memory");
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
+
++ pax_open_kernel();
+ get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
++ pax_close_kernel();
++
+ put_cpu();
+
+ /* If we get here and this is set then the PnP BIOS faulted on us. */
+@@ -468,7 +474,7 @@ int pnp_bios_read_escd(char *data, u32 n
+ return status;
+ }
+
+-void pnpbios_calls_init(union pnp_bios_install_struct *header)
++void __init pnpbios_calls_init(union pnp_bios_install_struct *header)
+ {
+ int i;
+
+@@ -476,6 +482,8 @@ void pnpbios_calls_init(union pnp_bios_i
+ pnp_bios_callpoint.offset = header->fields.pm16offset;
+ pnp_bios_callpoint.segment = PNP_CS16;
+
++ pax_open_kernel();
++
+ for_each_possible_cpu(i) {
+ struct desc_struct *gdt = get_cpu_gdt_table(i);
+ if (!gdt)
+@@ -487,4 +495,6 @@ void pnpbios_calls_init(union pnp_bios_i
+ set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_DS],
+ (unsigned long)__va(header->fields.pm16dseg));
+ }
++
++ pax_close_kernel();
+ }
+diff -urNp linux-2.6.38.7/drivers/pnp/resource.c linux-2.6.38.7/drivers/pnp/resource.c
+--- linux-2.6.38.7/drivers/pnp/resource.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/pnp/resource.c 2011-04-28 19:34:15.000000000 -0400
+@@ -360,7 +360,7 @@ int pnp_check_irq(struct pnp_dev *dev, s
+ return 1;
+
+ /* check if the resource is valid */
+- if (*irq < 0 || *irq > 15)
++ if (*irq > 15)
+ return 0;
+
+ /* check if the resource is reserved */
+@@ -424,7 +424,7 @@ int pnp_check_dma(struct pnp_dev *dev, s
+ return 1;
+
+ /* check if the resource is valid */
+- if (*dma < 0 || *dma == 4 || *dma > 7)
++ if (*dma == 4 || *dma > 7)
+ return 0;
+
+ /* check if the resource is reserved */
+diff -urNp linux-2.6.38.7/drivers/rtc/rtc-dev.c linux-2.6.38.7/drivers/rtc/rtc-dev.c
+--- linux-2.6.38.7/drivers/rtc/rtc-dev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/rtc/rtc-dev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -14,6 +14,7 @@
+ #include <linux/module.h>
+ #include <linux/rtc.h>
+ #include <linux/sched.h>
++#include <linux/grsecurity.h>
+ #include "rtc-core.h"
+
+ static dev_t rtc_devt;
+@@ -345,6 +346,8 @@ static long rtc_dev_ioctl(struct file *f
+ if (copy_from_user(&tm, uarg, sizeof(tm)))
+ return -EFAULT;
+
++ gr_log_timechange();
++
+ return rtc_set_time(rtc, &tm);
+
+ case RTC_PIE_ON:
+diff -urNp linux-2.6.38.7/drivers/s390/cio/qdio_debug.c linux-2.6.38.7/drivers/s390/cio/qdio_debug.c
+--- linux-2.6.38.7/drivers/s390/cio/qdio_debug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/s390/cio/qdio_debug.c 2011-04-28 19:34:15.000000000 -0400
+@@ -225,7 +225,7 @@ static int qperf_seq_open(struct inode *
+ filp->f_path.dentry->d_inode->i_private);
+ }
+
+-static struct file_operations debugfs_perf_fops = {
++static const struct file_operations debugfs_perf_fops = {
+ .owner = THIS_MODULE,
+ .open = qperf_seq_open,
+ .read = seq_read,
+diff -urNp linux-2.6.38.7/drivers/scsi/aacraid/commctrl.c linux-2.6.38.7/drivers/scsi/aacraid/commctrl.c
+--- linux-2.6.38.7/drivers/scsi/aacraid/commctrl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/aacraid/commctrl.c 2011-05-16 21:47:08.000000000 -0400
+@@ -481,6 +481,7 @@ static int aac_send_raw_srb(struct aac_d
+ u32 actual_fibsize64, actual_fibsize = 0;
+ int i;
+
++ pax_track_stack();
+
+ if (dev->in_reset) {
+ dprintk((KERN_DEBUG"aacraid: send raw srb -EBUSY\n"));
+diff -urNp linux-2.6.38.7/drivers/scsi/aic94xx/aic94xx_init.c linux-2.6.38.7/drivers/scsi/aic94xx/aic94xx_init.c
+--- linux-2.6.38.7/drivers/scsi/aic94xx/aic94xx_init.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/aic94xx/aic94xx_init.c 2011-04-28 19:34:15.000000000 -0400
+@@ -486,7 +486,7 @@ static ssize_t asd_show_update_bios(stru
+ flash_error_table[i].reason);
+ }
+
+-static DEVICE_ATTR(update_bios, S_IRUGO|S_IWUGO,
++static DEVICE_ATTR(update_bios, S_IRUGO|S_IWUSR,
+ asd_show_update_bios, asd_store_update_bios);
+
+ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
+diff -urNp linux-2.6.38.7/drivers/scsi/bfa/bfad.c linux-2.6.38.7/drivers/scsi/bfa/bfad.c
+--- linux-2.6.38.7/drivers/scsi/bfa/bfad.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/bfa/bfad.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1027,6 +1027,8 @@ bfad_start_ops(struct bfad_s *bfad) {
+ struct bfad_vport_s *vport, *vport_new;
+ struct bfa_fcs_driver_info_s driver_info;
+
++ pax_track_stack();
++
+ /* Fill the driver_info info to fcs*/
+ memset(&driver_info, 0, sizeof(driver_info));
+ strncpy(driver_info.version, BFAD_DRIVER_VERSION,
+diff -urNp linux-2.6.38.7/drivers/scsi/bfa/bfa_fcs_lport.c linux-2.6.38.7/drivers/scsi/bfa/bfa_fcs_lport.c
+--- linux-2.6.38.7/drivers/scsi/bfa/bfa_fcs_lport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/bfa/bfa_fcs_lport.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1559,6 +1559,8 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struc
+ u16 len, count;
+ u16 templen;
+
++ pax_track_stack();
++
+ /*
+ * get hba attributes
+ */
+@@ -1836,6 +1838,8 @@ bfa_fcs_lport_fdmi_build_portattr_block(
+ u8 count = 0;
+ u16 templen;
+
++ pax_track_stack();
++
+ /*
+ * get port attributes
+ */
+diff -urNp linux-2.6.38.7/drivers/scsi/bfa/bfa_fcs_rport.c linux-2.6.38.7/drivers/scsi/bfa/bfa_fcs_rport.c
+--- linux-2.6.38.7/drivers/scsi/bfa/bfa_fcs_rport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/bfa/bfa_fcs_rport.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1844,6 +1844,8 @@ bfa_fcs_rport_process_rpsc(struct bfa_fc
+ struct fc_rpsc_speed_info_s speeds;
+ struct bfa_port_attr_s pport_attr;
+
++ pax_track_stack();
++
+ bfa_trc(port->fcs, rx_fchs->s_id);
+ bfa_trc(port->fcs, rx_fchs->d_id);
+
+diff -urNp linux-2.6.38.7/drivers/scsi/BusLogic.c linux-2.6.38.7/drivers/scsi/BusLogic.c
+--- linux-2.6.38.7/drivers/scsi/BusLogic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/BusLogic.c 2011-05-16 21:47:08.000000000 -0400
+@@ -962,6 +962,8 @@ static int __init BusLogic_InitializeFla
+ static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
+ *PrototypeHostAdapter)
+ {
++ pax_track_stack();
++
+ /*
+ If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
+ Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
+diff -urNp linux-2.6.38.7/drivers/scsi/dpt_i2o.c linux-2.6.38.7/drivers/scsi/dpt_i2o.c
+--- linux-2.6.38.7/drivers/scsi/dpt_i2o.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/dpt_i2o.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1811,6 +1811,8 @@ static int adpt_i2o_passthru(adpt_hba* p
+ dma_addr_t addr;
+ ulong flags = 0;
+
++ pax_track_stack();
++
+ memset(&msg, 0, MAX_MESSAGE_SIZE*4);
+ // get user msg size in u32s
+ if(get_user(size, &user_msg[0])){
+@@ -2317,6 +2319,8 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pH
+ s32 rcode;
+ dma_addr_t addr;
+
++ pax_track_stack();
++
+ memset(msg, 0 , sizeof(msg));
+ len = scsi_bufflen(cmd);
+ direction = 0x00000000;
+diff -urNp linux-2.6.38.7/drivers/scsi/eata.c linux-2.6.38.7/drivers/scsi/eata.c
+--- linux-2.6.38.7/drivers/scsi/eata.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/eata.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1087,6 +1087,8 @@ static int port_detect(unsigned long por
+ struct hostdata *ha;
+ char name[16];
+
++ pax_track_stack();
++
+ sprintf(name, "%s%d", driver_name, j);
+
+ if (!request_region(port_base, REGION_SIZE, driver_name)) {
+diff -urNp linux-2.6.38.7/drivers/scsi/fcoe/libfcoe.c linux-2.6.38.7/drivers/scsi/fcoe/libfcoe.c
+--- linux-2.6.38.7/drivers/scsi/fcoe/libfcoe.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/fcoe/libfcoe.c 2011-05-16 21:47:08.000000000 -0400
+@@ -2484,6 +2484,8 @@ static int fcoe_ctlr_vn_recv(struct fcoe
+ } buf;
+ int rc;
+
++ pax_track_stack();
++
+ fiph = (struct fip_header *)skb->data;
+ sub = fiph->fip_subcode;
+
+diff -urNp linux-2.6.38.7/drivers/scsi/gdth.c linux-2.6.38.7/drivers/scsi/gdth.c
+--- linux-2.6.38.7/drivers/scsi/gdth.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/gdth.c 2011-05-16 21:47:08.000000000 -0400
+@@ -4107,6 +4107,8 @@ static int ioc_lockdrv(void __user *arg)
+ unsigned long flags;
+ gdth_ha_str *ha;
+
++ pax_track_stack();
++
+ if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv)))
+ return -EFAULT;
+ ha = gdth_find_ha(ldrv.ionode);
+@@ -4139,6 +4141,8 @@ static int ioc_resetdrv(void __user *arg
+ gdth_ha_str *ha;
+ int rval;
+
++ pax_track_stack();
++
+ if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) ||
+ res.number >= MAX_HDRIVES)
+ return -EFAULT;
+@@ -4174,6 +4178,8 @@ static int ioc_general(void __user *arg,
+ gdth_ha_str *ha;
+ int rval;
+
++ pax_track_stack();
++
+ if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)))
+ return -EFAULT;
+ ha = gdth_find_ha(gen.ionode);
+@@ -4642,6 +4648,9 @@ static void gdth_flush(gdth_ha_str *ha)
+ int i;
+ gdth_cmd_str gdtcmd;
+ char cmnd[MAX_COMMAND_SIZE];
++
++ pax_track_stack();
++
+ memset(cmnd, 0xff, MAX_COMMAND_SIZE);
+
+ TRACE2(("gdth_flush() hanum %d\n", ha->hanum));
+diff -urNp linux-2.6.38.7/drivers/scsi/gdth_proc.c linux-2.6.38.7/drivers/scsi/gdth_proc.c
+--- linux-2.6.38.7/drivers/scsi/gdth_proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/gdth_proc.c 2011-05-16 21:47:08.000000000 -0400
+@@ -47,6 +47,9 @@ static int gdth_set_asc_info(struct Scsi
+ u64 paddr;
+
+ char cmnd[MAX_COMMAND_SIZE];
++
++ pax_track_stack();
++
+ memset(cmnd, 0xff, 12);
+ memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
+
+@@ -175,6 +178,8 @@ static int gdth_get_info(char *buffer,ch
+ gdth_hget_str *phg;
+ char cmnd[MAX_COMMAND_SIZE];
+
++ pax_track_stack();
++
+ gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL);
+ estr = kmalloc(sizeof(*estr), GFP_KERNEL);
+ if (!gdtcmd || !estr)
+diff -urNp linux-2.6.38.7/drivers/scsi/hosts.c linux-2.6.38.7/drivers/scsi/hosts.c
+--- linux-2.6.38.7/drivers/scsi/hosts.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/hosts.c 2011-04-28 19:57:25.000000000 -0400
+@@ -42,7 +42,7 @@
+ #include "scsi_logging.h"
+
+
+-static atomic_t scsi_host_next_hn; /* host_no for next new host */
++static atomic_unchecked_t scsi_host_next_hn; /* host_no for next new host */
+
+
+ static void scsi_host_cls_release(struct device *dev)
+@@ -354,7 +354,7 @@ struct Scsi_Host *scsi_host_alloc(struct
+ * subtract one because we increment first then return, but we need to
+ * know what the next host number was before increment
+ */
+- shost->host_no = atomic_inc_return(&scsi_host_next_hn) - 1;
++ shost->host_no = atomic_inc_return_unchecked(&scsi_host_next_hn) - 1;
+ shost->dma_channel = 0xff;
+
+ /* These three are default values which can be overridden */
+diff -urNp linux-2.6.38.7/drivers/scsi/hpsa.c linux-2.6.38.7/drivers/scsi/hpsa.c
+--- linux-2.6.38.7/drivers/scsi/hpsa.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/hpsa.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2281,6 +2281,8 @@ static int hpsa_ioctl32_passthru(struct
+ int err;
+ u32 cp;
+
++ memset(&arg64, 0, sizeof(arg64));
++
+ err = 0;
+ err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+ sizeof(arg64.LUN_info));
+diff -urNp linux-2.6.38.7/drivers/scsi/ipr.c linux-2.6.38.7/drivers/scsi/ipr.c
+--- linux-2.6.38.7/drivers/scsi/ipr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/ipr.c 2011-04-28 19:34:15.000000000 -0400
+@@ -6207,7 +6207,7 @@ static bool ipr_qc_fill_rtf(struct ata_q
+ return true;
+ }
+
+-static struct ata_port_operations ipr_sata_ops = {
++static const struct ata_port_operations ipr_sata_ops = {
+ .phy_reset = ipr_ata_phy_reset,
+ .hardreset = ipr_sata_reset,
+ .post_internal_cmd = ipr_ata_post_internal,
+diff -urNp linux-2.6.38.7/drivers/scsi/libfc/fc_exch.c linux-2.6.38.7/drivers/scsi/libfc/fc_exch.c
+--- linux-2.6.38.7/drivers/scsi/libfc/fc_exch.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/libfc/fc_exch.c 2011-04-28 19:34:15.000000000 -0400
+@@ -105,12 +105,12 @@ struct fc_exch_mgr {
+ * all together if not used XXX
+ */
+ struct {
+- atomic_t no_free_exch;
+- atomic_t no_free_exch_xid;
+- atomic_t xid_not_found;
+- atomic_t xid_busy;
+- atomic_t seq_not_found;
+- atomic_t non_bls_resp;
++ atomic_unchecked_t no_free_exch;
++ atomic_unchecked_t no_free_exch_xid;
++ atomic_unchecked_t xid_not_found;
++ atomic_unchecked_t xid_busy;
++ atomic_unchecked_t seq_not_found;
++ atomic_unchecked_t non_bls_resp;
+ } stats;
+ };
+
+@@ -687,7 +687,7 @@ static struct fc_exch *fc_exch_em_alloc(
+ /* allocate memory for exchange */
+ ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC);
+ if (!ep) {
+- atomic_inc(&mp->stats.no_free_exch);
++ atomic_inc_unchecked(&mp->stats.no_free_exch);
+ goto out;
+ }
+ memset(ep, 0, sizeof(*ep));
+@@ -748,7 +748,7 @@ out:
+ return ep;
+ err:
+ spin_unlock_bh(&pool->lock);
+- atomic_inc(&mp->stats.no_free_exch_xid);
++ atomic_inc_unchecked(&mp->stats.no_free_exch_xid);
+ mempool_free(ep, mp->ep_pool);
+ return NULL;
+ }
+@@ -893,7 +893,7 @@ static enum fc_pf_rjt_reason fc_seq_look
+ xid = ntohs(fh->fh_ox_id); /* we originated exch */
+ ep = fc_exch_find(mp, xid);
+ if (!ep) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ reject = FC_RJT_OX_ID;
+ goto out;
+ }
+@@ -923,7 +923,7 @@ static enum fc_pf_rjt_reason fc_seq_look
+ ep = fc_exch_find(mp, xid);
+ if ((f_ctl & FC_FC_FIRST_SEQ) && fc_sof_is_init(fr_sof(fp))) {
+ if (ep) {
+- atomic_inc(&mp->stats.xid_busy);
++ atomic_inc_unchecked(&mp->stats.xid_busy);
+ reject = FC_RJT_RX_ID;
+ goto rel;
+ }
+@@ -934,7 +934,7 @@ static enum fc_pf_rjt_reason fc_seq_look
+ }
+ xid = ep->xid; /* get our XID */
+ } else if (!ep) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ reject = FC_RJT_RX_ID; /* XID not found */
+ goto out;
+ }
+@@ -951,7 +951,7 @@ static enum fc_pf_rjt_reason fc_seq_look
+ } else {
+ sp = &ep->seq;
+ if (sp->id != fh->fh_seq_id) {
+- atomic_inc(&mp->stats.seq_not_found);
++ atomic_inc_unchecked(&mp->stats.seq_not_found);
+ reject = FC_RJT_SEQ_ID; /* sequence/exch should exist */
+ goto rel;
+ }
+@@ -1368,22 +1368,22 @@ static void fc_exch_recv_seq_resp(struct
+
+ ep = fc_exch_find(mp, ntohs(fh->fh_ox_id));
+ if (!ep) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ goto out;
+ }
+ if (ep->esb_stat & ESB_ST_COMPLETE) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ goto rel;
+ }
+ if (ep->rxid == FC_XID_UNKNOWN)
+ ep->rxid = ntohs(fh->fh_rx_id);
+ if (ep->sid != 0 && ep->sid != ntoh24(fh->fh_d_id)) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ goto rel;
+ }
+ if (ep->did != ntoh24(fh->fh_s_id) &&
+ ep->did != FC_FID_FLOGI) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ goto rel;
+ }
+ sof = fr_sof(fp);
+@@ -1392,7 +1392,7 @@ static void fc_exch_recv_seq_resp(struct
+ sp->ssb_stat |= SSB_ST_RESP;
+ sp->id = fh->fh_seq_id;
+ } else if (sp->id != fh->fh_seq_id) {
+- atomic_inc(&mp->stats.seq_not_found);
++ atomic_inc_unchecked(&mp->stats.seq_not_found);
+ goto rel;
+ }
+
+@@ -1455,9 +1455,9 @@ static void fc_exch_recv_resp(struct fc_
+ sp = fc_seq_lookup_orig(mp, fp); /* doesn't hold sequence */
+
+ if (!sp)
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ else
+- atomic_inc(&mp->stats.non_bls_resp);
++ atomic_inc_unchecked(&mp->stats.non_bls_resp);
+
+ fc_frame_free(fp);
+ }
+diff -urNp linux-2.6.38.7/drivers/scsi/libsas/sas_ata.c linux-2.6.38.7/drivers/scsi/libsas/sas_ata.c
+--- linux-2.6.38.7/drivers/scsi/libsas/sas_ata.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/libsas/sas_ata.c 2011-04-28 19:34:15.000000000 -0400
+@@ -348,7 +348,7 @@ static int sas_ata_scr_read(struct ata_l
+ }
+ }
+
+-static struct ata_port_operations sas_sata_ops = {
++static const struct ata_port_operations sas_sata_ops = {
+ .phy_reset = sas_ata_phy_reset,
+ .post_internal_cmd = sas_ata_post_internal,
+ .qc_defer = ata_std_qc_defer,
+diff -urNp linux-2.6.38.7/drivers/scsi/lpfc/lpfc_debugfs.c linux-2.6.38.7/drivers/scsi/lpfc/lpfc_debugfs.c
+--- linux-2.6.38.7/drivers/scsi/lpfc/lpfc_debugfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/lpfc/lpfc_debugfs.c 2011-05-16 21:47:08.000000000 -0400
+@@ -125,7 +125,7 @@ struct lpfc_debug {
+ int len;
+ };
+
+-static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
++static atomic_unchecked_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
+ static unsigned long lpfc_debugfs_start_time = 0L;
+
+ /**
+@@ -159,7 +159,7 @@ lpfc_debugfs_disc_trc_data(struct lpfc_v
+ lpfc_debugfs_enable = 0;
+
+ len = 0;
+- index = (atomic_read(&vport->disc_trc_cnt) + 1) &
++ index = (atomic_read_unchecked(&vport->disc_trc_cnt) + 1) &
+ (lpfc_debugfs_max_disc_trc - 1);
+ for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
+ dtp = vport->disc_trc + i;
+@@ -220,7 +220,7 @@ lpfc_debugfs_slow_ring_trc_data(struct l
+ lpfc_debugfs_enable = 0;
+
+ len = 0;
+- index = (atomic_read(&phba->slow_ring_trc_cnt) + 1) &
++ index = (atomic_read_unchecked(&phba->slow_ring_trc_cnt) + 1) &
+ (lpfc_debugfs_max_slow_ring_trc - 1);
+ for (i = index; i < lpfc_debugfs_max_slow_ring_trc; i++) {
+ dtp = phba->slow_ring_trc + i;
+@@ -398,6 +398,8 @@ lpfc_debugfs_dumpHBASlim_data(struct lpf
+ uint32_t *ptr;
+ char buffer[1024];
+
++ pax_track_stack();
++
+ off = 0;
+ spin_lock_irq(&phba->hbalock);
+
+@@ -635,14 +637,14 @@ lpfc_debugfs_disc_trc(struct lpfc_vport
+ !vport || !vport->disc_trc)
+ return;
+
+- index = atomic_inc_return(&vport->disc_trc_cnt) &
++ index = atomic_inc_return_unchecked(&vport->disc_trc_cnt) &
+ (lpfc_debugfs_max_disc_trc - 1);
+ dtp = vport->disc_trc + index;
+ dtp->fmt = fmt;
+ dtp->data1 = data1;
+ dtp->data2 = data2;
+ dtp->data3 = data3;
+- dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
++ dtp->seq_cnt = atomic_inc_return_unchecked(&lpfc_debugfs_seq_trc_cnt);
+ dtp->jif = jiffies;
+ #endif
+ return;
+@@ -673,14 +675,14 @@ lpfc_debugfs_slow_ring_trc(struct lpfc_h
+ !phba || !phba->slow_ring_trc)
+ return;
+
+- index = atomic_inc_return(&phba->slow_ring_trc_cnt) &
++ index = atomic_inc_return_unchecked(&phba->slow_ring_trc_cnt) &
+ (lpfc_debugfs_max_slow_ring_trc - 1);
+ dtp = phba->slow_ring_trc + index;
+ dtp->fmt = fmt;
+ dtp->data1 = data1;
+ dtp->data2 = data2;
+ dtp->data3 = data3;
+- dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt);
++ dtp->seq_cnt = atomic_inc_return_unchecked(&lpfc_debugfs_seq_trc_cnt);
+ dtp->jif = jiffies;
+ #endif
+ return;
+@@ -1365,7 +1367,7 @@ lpfc_debugfs_initialize(struct lpfc_vpor
+ "slow_ring buffer\n");
+ goto debug_failed;
+ }
+- atomic_set(&phba->slow_ring_trc_cnt, 0);
++ atomic_set_unchecked(&phba->slow_ring_trc_cnt, 0);
+ memset(phba->slow_ring_trc, 0,
+ (sizeof(struct lpfc_debugfs_trc) *
+ lpfc_debugfs_max_slow_ring_trc));
+@@ -1411,7 +1413,7 @@ lpfc_debugfs_initialize(struct lpfc_vpor
+ "buffer\n");
+ goto debug_failed;
+ }
+- atomic_set(&vport->disc_trc_cnt, 0);
++ atomic_set_unchecked(&vport->disc_trc_cnt, 0);
+
+ snprintf(name, sizeof(name), "discovery_trace");
+ vport->debug_disc_trc =
+diff -urNp linux-2.6.38.7/drivers/scsi/lpfc/lpfc.h linux-2.6.38.7/drivers/scsi/lpfc/lpfc.h
+--- linux-2.6.38.7/drivers/scsi/lpfc/lpfc.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/lpfc/lpfc.h 2011-04-28 19:57:25.000000000 -0400
+@@ -414,7 +414,7 @@ struct lpfc_vport {
+ struct dentry *debug_nodelist;
+ struct dentry *vport_debugfs_root;
+ struct lpfc_debugfs_trc *disc_trc;
+- atomic_t disc_trc_cnt;
++ atomic_unchecked_t disc_trc_cnt;
+ #endif
+ uint8_t stat_data_enabled;
+ uint8_t stat_data_blocked;
+@@ -776,8 +776,8 @@ struct lpfc_hba {
+ struct timer_list fabric_block_timer;
+ unsigned long bit_flags;
+ #define FABRIC_COMANDS_BLOCKED 0
+- atomic_t num_rsrc_err;
+- atomic_t num_cmd_success;
++ atomic_unchecked_t num_rsrc_err;
++ atomic_unchecked_t num_cmd_success;
+ unsigned long last_rsrc_error_time;
+ unsigned long last_ramp_down_time;
+ unsigned long last_ramp_up_time;
+@@ -791,7 +791,7 @@ struct lpfc_hba {
+ struct dentry *debug_dumpDif; /* BlockGuard BPL*/
+ struct dentry *debug_slow_ring_trc;
+ struct lpfc_debugfs_trc *slow_ring_trc;
+- atomic_t slow_ring_trc_cnt;
++ atomic_unchecked_t slow_ring_trc_cnt;
+ #endif
+
+ /* Used for deferred freeing of ELS data buffers */
+diff -urNp linux-2.6.38.7/drivers/scsi/lpfc/lpfc_scsi.c linux-2.6.38.7/drivers/scsi/lpfc/lpfc_scsi.c
+--- linux-2.6.38.7/drivers/scsi/lpfc/lpfc_scsi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/lpfc/lpfc_scsi.c 2011-04-28 19:57:25.000000000 -0400
+@@ -297,7 +297,7 @@ lpfc_rampdown_queue_depth(struct lpfc_hb
+ uint32_t evt_posted;
+
+ spin_lock_irqsave(&phba->hbalock, flags);
+- atomic_inc(&phba->num_rsrc_err);
++ atomic_inc_unchecked(&phba->num_rsrc_err);
+ phba->last_rsrc_error_time = jiffies;
+
+ if ((phba->last_ramp_down_time + QUEUE_RAMP_DOWN_INTERVAL) > jiffies) {
+@@ -338,7 +338,7 @@ lpfc_rampup_queue_depth(struct lpfc_vpor
+ unsigned long flags;
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t evt_posted;
+- atomic_inc(&phba->num_cmd_success);
++ atomic_inc_unchecked(&phba->num_cmd_success);
+
+ if (vport->cfg_lun_queue_depth <= queue_depth)
+ return;
+@@ -382,8 +382,8 @@ lpfc_ramp_down_queue_handler(struct lpfc
+ unsigned long num_rsrc_err, num_cmd_success;
+ int i;
+
+- num_rsrc_err = atomic_read(&phba->num_rsrc_err);
+- num_cmd_success = atomic_read(&phba->num_cmd_success);
++ num_rsrc_err = atomic_read_unchecked(&phba->num_rsrc_err);
++ num_cmd_success = atomic_read_unchecked(&phba->num_cmd_success);
+
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports != NULL)
+@@ -403,8 +403,8 @@ lpfc_ramp_down_queue_handler(struct lpfc
+ }
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+- atomic_set(&phba->num_rsrc_err, 0);
+- atomic_set(&phba->num_cmd_success, 0);
++ atomic_set_unchecked(&phba->num_rsrc_err, 0);
++ atomic_set_unchecked(&phba->num_cmd_success, 0);
+ }
+
+ /**
+@@ -438,8 +438,8 @@ lpfc_ramp_up_queue_handler(struct lpfc_h
+ }
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+- atomic_set(&phba->num_rsrc_err, 0);
+- atomic_set(&phba->num_cmd_success, 0);
++ atomic_set_unchecked(&phba->num_rsrc_err, 0);
++ atomic_set_unchecked(&phba->num_cmd_success, 0);
+ }
+
+ /**
+diff -urNp linux-2.6.38.7/drivers/scsi/megaraid/megaraid_mbox.c linux-2.6.38.7/drivers/scsi/megaraid/megaraid_mbox.c
+--- linux-2.6.38.7/drivers/scsi/megaraid/megaraid_mbox.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/megaraid/megaraid_mbox.c 2011-05-16 21:47:08.000000000 -0400
+@@ -3510,6 +3510,8 @@ megaraid_cmm_register(adapter_t *adapter
+ int rval;
+ int i;
+
++ pax_track_stack();
++
+ // Allocate memory for the base list of scb for management module.
+ adapter->uscb_list = kcalloc(MBOX_MAX_USER_CMDS, sizeof(scb_t), GFP_KERNEL);
+
+diff -urNp linux-2.6.38.7/drivers/scsi/osd/osd_initiator.c linux-2.6.38.7/drivers/scsi/osd/osd_initiator.c
+--- linux-2.6.38.7/drivers/scsi/osd/osd_initiator.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/osd/osd_initiator.c 2011-05-16 21:47:08.000000000 -0400
+@@ -97,6 +97,8 @@ static int _osd_get_print_system_info(st
+ int nelem = ARRAY_SIZE(get_attrs), a = 0;
+ int ret;
+
++ pax_track_stack();
++
+ or = osd_start_request(od, GFP_KERNEL);
+ if (!or)
+ return -ENOMEM;
+diff -urNp linux-2.6.38.7/drivers/scsi/pmcraid.c linux-2.6.38.7/drivers/scsi/pmcraid.c
+--- linux-2.6.38.7/drivers/scsi/pmcraid.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/pmcraid.c 2011-05-10 22:08:57.000000000 -0400
+@@ -201,8 +201,8 @@ static int pmcraid_slave_alloc(struct sc
+ res->scsi_dev = scsi_dev;
+ scsi_dev->hostdata = res;
+ res->change_detected = 0;
+- atomic_set(&res->read_failures, 0);
+- atomic_set(&res->write_failures, 0);
++ atomic_set_unchecked(&res->read_failures, 0);
++ atomic_set_unchecked(&res->write_failures, 0);
+ rc = 0;
+ }
+ spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags);
+@@ -2677,9 +2677,9 @@ static int pmcraid_error_handler(struct
+
+ /* If this was a SCSI read/write command keep count of errors */
+ if (SCSI_CMD_TYPE(scsi_cmd->cmnd[0]) == SCSI_READ_CMD)
+- atomic_inc(&res->read_failures);
++ atomic_inc_unchecked(&res->read_failures);
+ else if (SCSI_CMD_TYPE(scsi_cmd->cmnd[0]) == SCSI_WRITE_CMD)
+- atomic_inc(&res->write_failures);
++ atomic_inc_unchecked(&res->write_failures);
+
+ if (!RES_IS_GSCSI(res->cfg_entry) &&
+ masked_ioasc != PMCRAID_IOASC_HW_DEVICE_BUS_STATUS_ERROR) {
+@@ -3535,7 +3535,7 @@ static int pmcraid_queuecommand_lck(
+ * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses
+ * hrrq_id assigned here in queuecommand
+ */
+- ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) %
++ ioarcb->hrrq_id = atomic_add_return_unchecked(1, &(pinstance->last_message_id)) %
+ pinstance->num_hrrq;
+ cmd->cmd_done = pmcraid_io_done;
+
+@@ -3860,7 +3860,7 @@ static long pmcraid_ioctl_passthrough(
+ * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses
+ * hrrq_id assigned here in queuecommand
+ */
+- ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) %
++ ioarcb->hrrq_id = atomic_add_return_unchecked(1, &(pinstance->last_message_id)) %
+ pinstance->num_hrrq;
+
+ if (request_size) {
+@@ -4495,7 +4495,7 @@ static void pmcraid_worker_function(stru
+
+ pinstance = container_of(workp, struct pmcraid_instance, worker_q);
+ /* add resources only after host is added into system */
+- if (!atomic_read(&pinstance->expose_resources))
++ if (!atomic_read_unchecked(&pinstance->expose_resources))
+ return;
+
+ fw_version = be16_to_cpu(pinstance->inq_data->fw_version);
+@@ -5329,8 +5329,8 @@ static int __devinit pmcraid_init_instan
+ init_waitqueue_head(&pinstance->reset_wait_q);
+
+ atomic_set(&pinstance->outstanding_cmds, 0);
+- atomic_set(&pinstance->last_message_id, 0);
+- atomic_set(&pinstance->expose_resources, 0);
++ atomic_set_unchecked(&pinstance->last_message_id, 0);
++ atomic_set_unchecked(&pinstance->expose_resources, 0);
+
+ INIT_LIST_HEAD(&pinstance->free_res_q);
+ INIT_LIST_HEAD(&pinstance->used_res_q);
+@@ -6045,7 +6045,7 @@ static int __devinit pmcraid_probe(
+ /* Schedule worker thread to handle CCN and take care of adding and
+ * removing devices to OS
+ */
+- atomic_set(&pinstance->expose_resources, 1);
++ atomic_set_unchecked(&pinstance->expose_resources, 1);
+ schedule_work(&pinstance->worker_q);
+ return rc;
+
+diff -urNp linux-2.6.38.7/drivers/scsi/pmcraid.h linux-2.6.38.7/drivers/scsi/pmcraid.h
+--- linux-2.6.38.7/drivers/scsi/pmcraid.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/pmcraid.h 2011-04-28 19:57:25.000000000 -0400
+@@ -750,7 +750,7 @@ struct pmcraid_instance {
+ struct pmcraid_isr_param hrrq_vector[PMCRAID_NUM_MSIX_VECTORS];
+
+ /* Message id as filled in last fired IOARCB, used to identify HRRQ */
+- atomic_t last_message_id;
++ atomic_unchecked_t last_message_id;
+
+ /* configuration table */
+ struct pmcraid_config_table *cfg_table;
+@@ -779,7 +779,7 @@ struct pmcraid_instance {
+ atomic_t outstanding_cmds;
+
+ /* should add/delete resources to mid-layer now ?*/
+- atomic_t expose_resources;
++ atomic_unchecked_t expose_resources;
+
+
+
+@@ -815,8 +815,8 @@ struct pmcraid_resource_entry {
+ struct pmcraid_config_table_entry_ext cfg_entry_ext;
+ };
+ struct scsi_device *scsi_dev; /* Link scsi_device structure */
+- atomic_t read_failures; /* count of failed READ commands */
+- atomic_t write_failures; /* count of failed WRITE commands */
++ atomic_unchecked_t read_failures; /* count of failed READ commands */
++ atomic_unchecked_t write_failures; /* count of failed WRITE commands */
+
+ /* To indicate add/delete/modify during CCN */
+ u8 change_detected;
+diff -urNp linux-2.6.38.7/drivers/scsi/qla2xxx/qla_os.c linux-2.6.38.7/drivers/scsi/qla2xxx/qla_os.c
+--- linux-2.6.38.7/drivers/scsi/qla2xxx/qla_os.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/qla2xxx/qla_os.c 2011-04-28 19:34:15.000000000 -0400
+@@ -4096,7 +4096,7 @@ static struct pci_driver qla2xxx_pci_dri
+ .err_handler = &qla2xxx_err_handler,
+ };
+
+-static struct file_operations apidev_fops = {
++static const struct file_operations apidev_fops = {
+ .owner = THIS_MODULE,
+ .llseek = noop_llseek,
+ };
+diff -urNp linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_def.h linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_def.h
+--- linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_def.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_def.h 2011-04-28 19:57:25.000000000 -0400
+@@ -256,7 +256,7 @@ struct ddb_entry {
+ atomic_t retry_relogin_timer; /* Min Time between relogins
+ * (4000 only) */
+ atomic_t relogin_timer; /* Max Time to wait for relogin to complete */
+- atomic_t relogin_retry_count; /* Num of times relogin has been
++ atomic_unchecked_t relogin_retry_count; /* Num of times relogin has been
+ * retried */
+
+ uint16_t port;
+diff -urNp linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_init.c linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_init.c
+--- linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_init.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_init.c 2011-04-28 19:57:25.000000000 -0400
+@@ -680,7 +680,7 @@ static struct ddb_entry * qla4xxx_alloc_
+ ddb_entry->fw_ddb_index = fw_ddb_index;
+ atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
+ atomic_set(&ddb_entry->relogin_timer, 0);
+- atomic_set(&ddb_entry->relogin_retry_count, 0);
++ atomic_set_unchecked(&ddb_entry->relogin_retry_count, 0);
+ atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
+ list_add_tail(&ddb_entry->list, &ha->ddb_list);
+ ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
+@@ -1570,7 +1570,7 @@ int qla4xxx_process_ddb_changed(struct s
+ /* Device is back online. */
+ if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
+ atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
+- atomic_set(&ddb_entry->relogin_retry_count, 0);
++ atomic_set_unchecked(&ddb_entry->relogin_retry_count, 0);
+ atomic_set(&ddb_entry->relogin_timer, 0);
+ clear_bit(DF_RELOGIN, &ddb_entry->flags);
+ clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
+diff -urNp linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_os.c linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_os.c
+--- linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_os.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/qla4xxx/ql4_os.c 2011-04-28 19:57:25.000000000 -0400
+@@ -801,13 +801,13 @@ static void qla4xxx_timer(struct scsi_ql
+ ddb_entry->fw_ddb_device_state ==
+ DDB_DS_SESSION_FAILED) {
+ /* Reset retry relogin timer */
+- atomic_inc(&ddb_entry->relogin_retry_count);
++ atomic_inc_unchecked(&ddb_entry->relogin_retry_count);
+ DEBUG2(printk("scsi%ld: ddb [%d] relogin"
+ " timed out-retrying"
+ " relogin (%d)\n",
+ ha->host_no,
+ ddb_entry->fw_ddb_index,
+- atomic_read(&ddb_entry->
++ atomic_read_unchecked(&ddb_entry->
+ relogin_retry_count))
+ );
+ start_dpc++;
+diff -urNp linux-2.6.38.7/drivers/scsi/scsi.c linux-2.6.38.7/drivers/scsi/scsi.c
+--- linux-2.6.38.7/drivers/scsi/scsi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/scsi.c 2011-04-28 19:57:25.000000000 -0400
+@@ -655,7 +655,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
+ unsigned long timeout;
+ int rtn = 0;
+
+- atomic_inc(&cmd->device->iorequest_cnt);
++ atomic_inc_unchecked(&cmd->device->iorequest_cnt);
+
+ /* check if the device is still usable */
+ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
+diff -urNp linux-2.6.38.7/drivers/scsi/scsi_debug.c linux-2.6.38.7/drivers/scsi/scsi_debug.c
+--- linux-2.6.38.7/drivers/scsi/scsi_debug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/scsi_debug.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1476,6 +1476,8 @@ static int resp_mode_select(struct scsi_
+ unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
+ unsigned char *cmd = (unsigned char *)scp->cmnd;
+
++ pax_track_stack();
++
+ if ((errsts = check_readiness(scp, 1, devip)))
+ return errsts;
+ memset(arr, 0, sizeof(arr));
+@@ -1573,6 +1575,8 @@ static int resp_log_sense(struct scsi_cm
+ unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
+ unsigned char *cmd = (unsigned char *)scp->cmnd;
+
++ pax_track_stack();
++
+ if ((errsts = check_readiness(scp, 1, devip)))
+ return errsts;
+ memset(arr, 0, sizeof(arr));
+diff -urNp linux-2.6.38.7/drivers/scsi/scsi_lib.c linux-2.6.38.7/drivers/scsi/scsi_lib.c
+--- linux-2.6.38.7/drivers/scsi/scsi_lib.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/scsi_lib.c 2011-05-10 22:08:57.000000000 -0400
+@@ -1381,7 +1381,7 @@ static void scsi_kill_request(struct req
+ shost = sdev->host;
+ scsi_init_cmd_errh(cmd);
+ cmd->result = DID_NO_CONNECT << 16;
+- atomic_inc(&cmd->device->iorequest_cnt);
++ atomic_inc_unchecked(&cmd->device->iorequest_cnt);
+
+ /*
+ * SCSI request completion path will do scsi_device_unbusy(),
+@@ -1407,9 +1407,9 @@ static void scsi_softirq_done(struct req
+
+ INIT_LIST_HEAD(&cmd->eh_entry);
+
+- atomic_inc(&cmd->device->iodone_cnt);
++ atomic_inc_unchecked(&cmd->device->iodone_cnt);
+ if (cmd->result)
+- atomic_inc(&cmd->device->ioerr_cnt);
++ atomic_inc_unchecked(&cmd->device->ioerr_cnt);
+
+ disposition = scsi_decide_disposition(cmd);
+ if (disposition != SUCCESS &&
+diff -urNp linux-2.6.38.7/drivers/scsi/scsi_sysfs.c linux-2.6.38.7/drivers/scsi/scsi_sysfs.c
+--- linux-2.6.38.7/drivers/scsi/scsi_sysfs.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/scsi_sysfs.c 2011-05-10 22:08:57.000000000 -0400
+@@ -621,7 +621,7 @@ show_iostat_##field(struct device *dev,
+ char *buf) \
+ { \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+- unsigned long long count = atomic_read(&sdev->field); \
++ unsigned long long count = atomic_read_unchecked(&sdev->field); \
+ return snprintf(buf, 20, "0x%llx\n", count); \
+ } \
+ static DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL)
+diff -urNp linux-2.6.38.7/drivers/scsi/scsi_transport_fc.c linux-2.6.38.7/drivers/scsi/scsi_transport_fc.c
+--- linux-2.6.38.7/drivers/scsi/scsi_transport_fc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/scsi_transport_fc.c 2011-04-28 19:57:25.000000000 -0400
+@@ -485,7 +485,7 @@ static DECLARE_TRANSPORT_CLASS(fc_vport_
+ * Netlink Infrastructure
+ */
+
+-static atomic_t fc_event_seq;
++static atomic_unchecked_t fc_event_seq;
+
+ /**
+ * fc_get_event_number - Obtain the next sequential FC event number
+@@ -498,7 +498,7 @@ static atomic_t fc_event_seq;
+ u32
+ fc_get_event_number(void)
+ {
+- return atomic_add_return(1, &fc_event_seq);
++ return atomic_add_return_unchecked(1, &fc_event_seq);
+ }
+ EXPORT_SYMBOL(fc_get_event_number);
+
+@@ -646,7 +646,7 @@ static __init int fc_transport_init(void
+ {
+ int error;
+
+- atomic_set(&fc_event_seq, 0);
++ atomic_set_unchecked(&fc_event_seq, 0);
+
+ error = transport_class_register(&fc_host_class);
+ if (error)
+@@ -836,7 +836,7 @@ static int fc_str_to_dev_loss(const char
+ char *cp;
+
+ *val = simple_strtoul(buf, &cp, 0);
+- if ((*cp && (*cp != '\n')) || (*val < 0))
++ if (*cp && (*cp != '\n'))
+ return -EINVAL;
+ /*
+ * Check for overflow; dev_loss_tmo is u32
+diff -urNp linux-2.6.38.7/drivers/scsi/scsi_transport_iscsi.c linux-2.6.38.7/drivers/scsi/scsi_transport_iscsi.c
+--- linux-2.6.38.7/drivers/scsi/scsi_transport_iscsi.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/scsi_transport_iscsi.c 2011-04-28 19:57:25.000000000 -0400
+@@ -83,7 +83,7 @@ struct iscsi_internal {
+ struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
+ };
+
+-static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
++static atomic_unchecked_t iscsi_session_nr; /* sysfs session id for next new session */
+ static struct workqueue_struct *iscsi_eh_timer_workq;
+
+ /*
+@@ -761,7 +761,7 @@ int iscsi_add_session(struct iscsi_cls_s
+ int err;
+
+ ihost = shost->shost_data;
+- session->sid = atomic_add_return(1, &iscsi_session_nr);
++ session->sid = atomic_add_return_unchecked(1, &iscsi_session_nr);
+
+ if (id == ISCSI_MAX_TARGET) {
+ for (id = 0; id < ISCSI_MAX_TARGET; id++) {
+@@ -2130,7 +2130,7 @@ static __init int iscsi_transport_init(v
+ printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
+ ISCSI_TRANSPORT_VERSION);
+
+- atomic_set(&iscsi_session_nr, 0);
++ atomic_set_unchecked(&iscsi_session_nr, 0);
+
+ err = class_register(&iscsi_transport_class);
+ if (err)
+diff -urNp linux-2.6.38.7/drivers/scsi/scsi_transport_srp.c linux-2.6.38.7/drivers/scsi/scsi_transport_srp.c
+--- linux-2.6.38.7/drivers/scsi/scsi_transport_srp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/scsi_transport_srp.c 2011-04-28 19:57:25.000000000 -0400
+@@ -33,7 +33,7 @@
+ #include "scsi_transport_srp_internal.h"
+
+ struct srp_host_attrs {
+- atomic_t next_port_id;
++ atomic_unchecked_t next_port_id;
+ };
+ #define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data)
+
+@@ -62,7 +62,7 @@ static int srp_host_setup(struct transpo
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct srp_host_attrs *srp_host = to_srp_host_attrs(shost);
+
+- atomic_set(&srp_host->next_port_id, 0);
++ atomic_set_unchecked(&srp_host->next_port_id, 0);
+ return 0;
+ }
+
+@@ -211,7 +211,7 @@ struct srp_rport *srp_rport_add(struct S
+ memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id));
+ rport->roles = ids->roles;
+
+- id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id);
++ id = atomic_inc_return_unchecked(&to_srp_host_attrs(shost)->next_port_id);
+ dev_set_name(&rport->dev, "port-%d:%d", shost->host_no, id);
+
+ transport_setup_device(&rport->dev);
+diff -urNp linux-2.6.38.7/drivers/scsi/sg.c linux-2.6.38.7/drivers/scsi/sg.c
+--- linux-2.6.38.7/drivers/scsi/sg.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/sg.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2310,7 +2310,7 @@ struct sg_proc_leaf {
+ const struct file_operations * fops;
+ };
+
+-static struct sg_proc_leaf sg_proc_leaf_arr[] = {
++static const struct sg_proc_leaf sg_proc_leaf_arr[] = {
+ {"allow_dio", &adio_fops},
+ {"debug", &debug_fops},
+ {"def_reserved_size", &dressz_fops},
+@@ -2325,7 +2325,7 @@ sg_proc_init(void)
+ {
+ int k, mask;
+ int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr);
+- struct sg_proc_leaf * leaf;
++ const struct sg_proc_leaf * leaf;
+
+ sg_proc_sgp = proc_mkdir(sg_proc_sg_dirname, NULL);
+ if (!sg_proc_sgp)
+diff -urNp linux-2.6.38.7/drivers/scsi/sym53c8xx_2/sym_glue.c linux-2.6.38.7/drivers/scsi/sym53c8xx_2/sym_glue.c
+--- linux-2.6.38.7/drivers/scsi/sym53c8xx_2/sym_glue.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/sym53c8xx_2/sym_glue.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1756,6 +1756,8 @@ static int __devinit sym2_probe(struct p
+ int do_iounmap = 0;
+ int do_disable_device = 1;
+
++ pax_track_stack();
++
+ memset(&sym_dev, 0, sizeof(sym_dev));
+ memset(&nvram, 0, sizeof(nvram));
+ sym_dev.pdev = pdev;
+diff -urNp linux-2.6.38.7/drivers/scsi/vmw_pvscsi.c linux-2.6.38.7/drivers/scsi/vmw_pvscsi.c
+--- linux-2.6.38.7/drivers/scsi/vmw_pvscsi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/scsi/vmw_pvscsi.c 2011-05-16 21:47:08.000000000 -0400
+@@ -447,6 +447,8 @@ static void pvscsi_setup_all_rings(const
+ dma_addr_t base;
+ unsigned i;
+
++ pax_track_stack();
++
+ cmd.ringsStatePPN = adapter->ringStatePA >> PAGE_SHIFT;
+ cmd.reqRingNumPages = adapter->req_pages;
+ cmd.cmpRingNumPages = adapter->cmp_pages;
+diff -urNp linux-2.6.38.7/drivers/spi/spi.c linux-2.6.38.7/drivers/spi/spi.c
+--- linux-2.6.38.7/drivers/spi/spi.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/spi/spi.c 2011-05-11 18:34:57.000000000 -0400
+@@ -1023,7 +1023,7 @@ int spi_bus_unlock(struct spi_master *ma
+ EXPORT_SYMBOL_GPL(spi_bus_unlock);
+
+ /* portable code must never pass more than 32 bytes */
+-#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
++#define SPI_BUFSIZ max(32U,SMP_CACHE_BYTES)
+
+ static u8 *buf;
+
+diff -urNp linux-2.6.38.7/drivers/staging/autofs/root.c linux-2.6.38.7/drivers/staging/autofs/root.c
+--- linux-2.6.38.7/drivers/staging/autofs/root.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/autofs/root.c 2011-04-28 19:34:15.000000000 -0400
+@@ -311,7 +311,8 @@ static int autofs_root_symlink(struct in
+ set_bit(n,sbi->symlink_bitmap);
+ sl = &sbi->symlink[n];
+ sl->len = strlen(symname);
+- sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
++ slsize = sl->len+1;
++ sl->data = kmalloc(slsize, GFP_KERNEL);
+ if (!sl->data) {
+ clear_bit(n,sbi->symlink_bitmap);
+ unlock_kernel();
+diff -urNp linux-2.6.38.7/drivers/staging/bcm/Bcmchar.c linux-2.6.38.7/drivers/staging/bcm/Bcmchar.c
+--- linux-2.6.38.7/drivers/staging/bcm/Bcmchar.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/bcm/Bcmchar.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2093,7 +2093,7 @@ static long bcm_char_ioctl(struct file *
+ }
+
+
+-static struct file_operations bcm_fops = {
++static const struct file_operations bcm_fops = {
+ .owner = THIS_MODULE,
+ .open = bcm_char_open,
+ .release = bcm_char_release,
+diff -urNp linux-2.6.38.7/drivers/staging/brcm80211/brcmfmac/dhd_linux.c linux-2.6.38.7/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+--- linux-2.6.38.7/drivers/staging/brcm80211/brcmfmac/dhd_linux.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/brcm80211/brcmfmac/dhd_linux.c 2011-04-28 19:34:15.000000000 -0400
+@@ -863,14 +863,14 @@ static void dhd_op_if(dhd_if_t *ifp)
+ free_netdev(ifp->net);
+ }
+ /* Allocate etherdev, including space for private structure */
+- ifp->net = alloc_etherdev(sizeof(dhd));
++ ifp->net = alloc_etherdev(sizeof(*dhd));
+ if (!ifp->net) {
+ DHD_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+ ret = -ENOMEM;
+ }
+ if (ret == 0) {
+ strcpy(ifp->net->name, ifp->name);
+- memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd));
++ memcpy(netdev_priv(ifp->net), dhd, sizeof(*dhd));
+ err = dhd_net_attach(&dhd->pub, ifp->idx);
+ if (err != 0) {
+ DHD_ERROR(("%s: dhd_net_attach failed, "
+@@ -1969,25 +1969,23 @@ dhd_pub_t *dhd_attach(struct osl_info *o
+ strcpy(nv_path, nvram_path);
+
+ /* Allocate etherdev, including space for private structure */
+- net = alloc_etherdev(sizeof(dhd));
++ net = alloc_etherdev(sizeof(*dhd));
+ if (!net) {
+ DHD_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+ goto fail;
+ }
+
+ /* Allocate primary dhd_info */
+- dhd = kmalloc(sizeof(dhd_info_t), GFP_ATOMIC);
++ dhd = kzalloc(sizeof(dhd_info_t), GFP_ATOMIC);
+ if (!dhd) {
+ DHD_ERROR(("%s: OOM - alloc dhd_info\n", __func__));
+ goto fail;
+ }
+
+- memset(dhd, 0, sizeof(dhd_info_t));
+-
+ /*
+ * Save the dhd_info into the priv
+ */
+- memcpy(netdev_priv(net), &dhd, sizeof(dhd));
++ memcpy(netdev_priv(net), dhd, sizeof(*dhd));
+ dhd->pub.osh = osh;
+
+ /* Set network interface name if it was provided as module parameter */
+@@ -2105,7 +2103,7 @@ dhd_pub_t *dhd_attach(struct osl_info *o
+ /*
+ * Save the dhd_info into the priv
+ */
+- memcpy(netdev_priv(net), &dhd, sizeof(dhd));
++ memcpy(netdev_priv(net), dhd, sizeof(*dhd));
+
+ #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+ g_bus = bus;
+diff -urNp linux-2.6.38.7/drivers/staging/brcm80211/brcmfmac/wl_iw.c linux-2.6.38.7/drivers/staging/brcm80211/brcmfmac/wl_iw.c
+--- linux-2.6.38.7/drivers/staging/brcm80211/brcmfmac/wl_iw.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/brcm80211/brcmfmac/wl_iw.c 2011-04-28 19:34:15.000000000 -0400
+@@ -513,7 +513,7 @@ wl_iw_get_range(struct net_device *dev,
+ list = (wl_u32_list_t *) channels;
+
+ dwrq->length = sizeof(struct iw_range);
+- memset(range, 0, sizeof(range));
++ memset(range, 0, sizeof(*range));
+
+ range->min_nwid = range->max_nwid = 0;
+
+diff -urNp linux-2.6.38.7/drivers/staging/comedi/comedi_fops.c linux-2.6.38.7/drivers/staging/comedi/comedi_fops.c
+--- linux-2.6.38.7/drivers/staging/comedi/comedi_fops.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/comedi/comedi_fops.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1426,7 +1426,7 @@ static void comedi_unmap(struct vm_area_
+ mutex_unlock(&dev->mutex);
+ }
+
+-static struct vm_operations_struct comedi_vm_ops = {
++static const struct vm_operations_struct comedi_vm_ops = {
+ .close = comedi_unmap,
+ };
+
+diff -urNp linux-2.6.38.7/drivers/staging/et131x/et1310_tx.c linux-2.6.38.7/drivers/staging/et131x/et1310_tx.c
+--- linux-2.6.38.7/drivers/staging/et131x/et1310_tx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/et131x/et1310_tx.c 2011-04-28 19:57:25.000000000 -0400
+@@ -635,11 +635,11 @@ inline void et131x_free_send_packet(stru
+ struct net_device_stats *stats = &etdev->net_stats;
+
+ if (tcb->flags & fMP_DEST_BROAD)
+- atomic_inc(&etdev->Stats.brdcstxmt);
++ atomic_inc_unchecked(&etdev->Stats.brdcstxmt);
+ else if (tcb->flags & fMP_DEST_MULTI)
+- atomic_inc(&etdev->Stats.multixmt);
++ atomic_inc_unchecked(&etdev->Stats.multixmt);
+ else
+- atomic_inc(&etdev->Stats.unixmt);
++ atomic_inc_unchecked(&etdev->Stats.unixmt);
+
+ if (tcb->skb) {
+ stats->tx_bytes += tcb->skb->len;
+diff -urNp linux-2.6.38.7/drivers/staging/et131x/et131x_adapter.h linux-2.6.38.7/drivers/staging/et131x/et131x_adapter.h
+--- linux-2.6.38.7/drivers/staging/et131x/et131x_adapter.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/et131x/et131x_adapter.h 2011-04-28 19:57:25.000000000 -0400
+@@ -112,11 +112,11 @@ typedef struct _ce_stats_t {
+ * operations
+ */
+ u32 unircv; /* # multicast packets received */
+- atomic_t unixmt; /* # multicast packets for Tx */
++ atomic_unchecked_t unixmt; /* # multicast packets for Tx */
+ u32 multircv; /* # multicast packets received */
+- atomic_t multixmt; /* # multicast packets for Tx */
++ atomic_unchecked_t multixmt; /* # multicast packets for Tx */
+ u32 brdcstrcv; /* # broadcast packets received */
+- atomic_t brdcstxmt; /* # broadcast packets for Tx */
++ atomic_unchecked_t brdcstxmt; /* # broadcast packets for Tx */
+ u32 norcvbuf; /* # Rx packets discarded */
+ u32 noxmtbuf; /* # Tx packets discarded */
+
+diff -urNp linux-2.6.38.7/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c linux-2.6.38.7/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
+--- linux-2.6.38.7/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c 2011-04-28 19:34:15.000000000 -0400
+@@ -55,7 +55,7 @@ int numofmsgbuf = 0;
+ //
+ // Table of entry-point routines for char device
+ //
+-static struct file_operations ft1000fops =
++static const struct file_operations ft1000fops =
+ {
+ .unlocked_ioctl = ft1000_ioctl,
+ .poll = ft1000_poll_dev,
+diff -urNp linux-2.6.38.7/drivers/staging/go7007/go7007-v4l2.c linux-2.6.38.7/drivers/staging/go7007/go7007-v4l2.c
+--- linux-2.6.38.7/drivers/staging/go7007/go7007-v4l2.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/go7007/go7007-v4l2.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1672,7 +1672,7 @@ static int go7007_vm_fault(struct vm_are
+ return 0;
+ }
+
+-static struct vm_operations_struct go7007_vm_ops = {
++static const struct vm_operations_struct go7007_vm_ops = {
+ .open = go7007_vm_open,
+ .close = go7007_vm_close,
+ .fault = go7007_vm_fault,
+diff -urNp linux-2.6.38.7/drivers/staging/hv/channel.c linux-2.6.38.7/drivers/staging/hv/channel.c
+--- linux-2.6.38.7/drivers/staging/hv/channel.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/hv/channel.c 2011-04-28 19:57:25.000000000 -0400
+@@ -501,8 +501,8 @@ int vmbus_establish_gpadl(struct vmbus_c
+ unsigned long flags;
+ int ret = 0;
+
+- next_gpadl_handle = atomic_read(&gVmbusConnection.NextGpadlHandle);
+- atomic_inc(&gVmbusConnection.NextGpadlHandle);
++ next_gpadl_handle = atomic_read_unchecked(&gVmbusConnection.NextGpadlHandle);
++ atomic_inc_unchecked(&gVmbusConnection.NextGpadlHandle);
+
+ ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
+ if (ret)
+diff -urNp linux-2.6.38.7/drivers/staging/hv/hv.c linux-2.6.38.7/drivers/staging/hv/hv.c
+--- linux-2.6.38.7/drivers/staging/hv/hv.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/hv/hv.c 2011-04-28 19:34:15.000000000 -0400
+@@ -163,7 +163,7 @@ static u64 do_hypercall(u64 control, voi
+ u64 output_address = (output) ? virt_to_phys(output) : 0;
+ u32 output_address_hi = output_address >> 32;
+ u32 output_address_lo = output_address & 0xFFFFFFFF;
+- volatile void *hypercall_page = hv_context.hypercall_page;
++ volatile void *hypercall_page = ktva_ktla(hv_context.hypercall_page);
+
+ DPRINT_DBG(VMBUS, "Hypercall <control %llx input %p output %p>",
+ control, input, output);
+diff -urNp linux-2.6.38.7/drivers/staging/hv/rndis_filter.c linux-2.6.38.7/drivers/staging/hv/rndis_filter.c
+--- linux-2.6.38.7/drivers/staging/hv/rndis_filter.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/hv/rndis_filter.c 2011-04-28 19:57:25.000000000 -0400
+@@ -47,7 +47,7 @@ struct rndis_device {
+
+ enum rndis_device_state state;
+ u32 link_stat;
+- atomic_t new_req_id;
++ atomic_unchecked_t new_req_id;
+
+ spinlock_t request_lock;
+ struct list_head req_list;
+@@ -145,7 +145,7 @@ static struct rndis_request *get_rndis_r
+ * template
+ */
+ set = &rndis_msg->msg.set_req;
+- set->req_id = atomic_inc_return(&dev->new_req_id);
++ set->req_id = atomic_inc_return_unchecked(&dev->new_req_id);
+
+ /* Add to the request list */
+ spin_lock_irqsave(&dev->request_lock, flags);
+@@ -707,7 +707,7 @@ static void rndis_filter_halt_device(str
+
+ /* Setup the rndis set */
+ halt = &request->request_msg.msg.halt_req;
+- halt->req_id = atomic_inc_return(&dev->new_req_id);
++ halt->req_id = atomic_inc_return_unchecked(&dev->new_req_id);
+
+ /* Ignore return since this msg is optional. */
+ rndis_filter_send_request(dev, request);
+diff -urNp linux-2.6.38.7/drivers/staging/hv/vmbus_drv.c linux-2.6.38.7/drivers/staging/hv/vmbus_drv.c
+--- linux-2.6.38.7/drivers/staging/hv/vmbus_drv.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/hv/vmbus_drv.c 2011-04-28 19:57:25.000000000 -0400
+@@ -727,14 +727,14 @@ int vmbus_child_device_register(struct h
+ to_vm_device(root_device_obj);
+ struct vm_device *child_device_ctx =
+ to_vm_device(child_device_obj);
+- static atomic_t device_num = ATOMIC_INIT(0);
++ static atomic_unchecked_t device_num = ATOMIC_INIT(0);
+
+ DPRINT_DBG(VMBUS_DRV, "child device (%p) registering",
+ child_device_ctx);
+
+ /* Set the device name. Otherwise, device_register() will fail. */
+ dev_set_name(&child_device_ctx->device, "vmbus_0_%d",
+- atomic_inc_return(&device_num));
++ atomic_inc_return_unchecked(&device_num));
+
+ /* The new device belongs to this bus */
+ child_device_ctx->device.bus = &g_vmbus_drv.bus; /* device->dev.bus; */
+diff -urNp linux-2.6.38.7/drivers/staging/hv/vmbus_private.h linux-2.6.38.7/drivers/staging/hv/vmbus_private.h
+--- linux-2.6.38.7/drivers/staging/hv/vmbus_private.h 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/hv/vmbus_private.h 2011-04-28 19:57:25.000000000 -0400
+@@ -58,7 +58,7 @@ enum VMBUS_CONNECT_STATE {
+ struct VMBUS_CONNECTION {
+ enum VMBUS_CONNECT_STATE ConnectState;
+
+- atomic_t NextGpadlHandle;
++ atomic_unchecked_t NextGpadlHandle;
+
+ /*
+ * Represents channel interrupts. Each bit position represents a
+diff -urNp linux-2.6.38.7/drivers/staging/octeon/ethernet.c linux-2.6.38.7/drivers/staging/octeon/ethernet.c
+--- linux-2.6.38.7/drivers/staging/octeon/ethernet.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/octeon/ethernet.c 2011-04-28 19:57:25.000000000 -0400
+@@ -258,11 +258,11 @@ static struct net_device_stats *cvm_oct_
+ * since the RX tasklet also increments it.
+ */
+ #ifdef CONFIG_64BIT
+- atomic64_add(rx_status.dropped_packets,
+- (atomic64_t *)&priv->stats.rx_dropped);
++ atomic64_add_unchecked(rx_status.dropped_packets,
++ (atomic64_unchecked_t *)&priv->stats.rx_dropped);
+ #else
+- atomic_add(rx_status.dropped_packets,
+- (atomic_t *)&priv->stats.rx_dropped);
++ atomic_add_unchecked(rx_status.dropped_packets,
++ (atomic_unchecked_t *)&priv->stats.rx_dropped);
+ #endif
+ }
+
+diff -urNp linux-2.6.38.7/drivers/staging/octeon/ethernet-rx.c linux-2.6.38.7/drivers/staging/octeon/ethernet-rx.c
+--- linux-2.6.38.7/drivers/staging/octeon/ethernet-rx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/octeon/ethernet-rx.c 2011-04-28 19:57:25.000000000 -0400
+@@ -417,11 +417,11 @@ static int cvm_oct_napi_poll(struct napi
+ /* Increment RX stats for virtual ports */
+ if (work->ipprt >= CVMX_PIP_NUM_INPUT_PORTS) {
+ #ifdef CONFIG_64BIT
+- atomic64_add(1, (atomic64_t *)&priv->stats.rx_packets);
+- atomic64_add(skb->len, (atomic64_t *)&priv->stats.rx_bytes);
++ atomic64_add_unchecked(1, (atomic64_unchecked_t *)&priv->stats.rx_packets);
++ atomic64_add_unchecked(skb->len, (atomic64_unchecked_t *)&priv->stats.rx_bytes);
+ #else
+- atomic_add(1, (atomic_t *)&priv->stats.rx_packets);
+- atomic_add(skb->len, (atomic_t *)&priv->stats.rx_bytes);
++ atomic_add_unchecked(1, (atomic_unchecked_t *)&priv->stats.rx_packets);
++ atomic_add_unchecked(skb->len, (atomic_unchecked_t *)&priv->stats.rx_bytes);
+ #endif
+ }
+ netif_receive_skb(skb);
+@@ -433,9 +433,9 @@ static int cvm_oct_napi_poll(struct napi
+ dev->name);
+ */
+ #ifdef CONFIG_64BIT
+- atomic64_add(1, (atomic64_t *)&priv->stats.rx_dropped);
++ atomic64_unchecked_add(1, (atomic64_unchecked_t *)&priv->stats.rx_dropped);
+ #else
+- atomic_add(1, (atomic_t *)&priv->stats.rx_dropped);
++ atomic_add_unchecked(1, (atomic_unchecked_t *)&priv->stats.rx_dropped);
+ #endif
+ dev_kfree_skb_irq(skb);
+ }
+diff -urNp linux-2.6.38.7/drivers/staging/phison/phison.c linux-2.6.38.7/drivers/staging/phison/phison.c
+--- linux-2.6.38.7/drivers/staging/phison/phison.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/phison/phison.c 2011-04-28 19:34:15.000000000 -0400
+@@ -43,7 +43,7 @@ static struct scsi_host_template phison_
+ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations phison_ops = {
++static const struct ata_port_operations phison_ops = {
+ .inherits = &ata_bmdma_port_ops,
+ .prereset = phison_pre_reset,
+ };
+diff -urNp linux-2.6.38.7/drivers/staging/pohmelfs/inode.c linux-2.6.38.7/drivers/staging/pohmelfs/inode.c
+--- linux-2.6.38.7/drivers/staging/pohmelfs/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/pohmelfs/inode.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1855,7 +1855,7 @@ static int pohmelfs_fill_super(struct su
+ mutex_init(&psb->mcache_lock);
+ psb->mcache_root = RB_ROOT;
+ psb->mcache_timeout = msecs_to_jiffies(5000);
+- atomic_long_set(&psb->mcache_gen, 0);
++ atomic_long_set_unchecked(&psb->mcache_gen, 0);
+
+ psb->trans_max_pages = 100;
+
+@@ -1870,7 +1870,7 @@ static int pohmelfs_fill_super(struct su
+ INIT_LIST_HEAD(&psb->crypto_ready_list);
+ INIT_LIST_HEAD(&psb->crypto_active_list);
+
+- atomic_set(&psb->trans_gen, 1);
++ atomic_set_unchecked(&psb->trans_gen, 1);
+ atomic_long_set(&psb->total_inodes, 0);
+
+ mutex_init(&psb->state_lock);
+diff -urNp linux-2.6.38.7/drivers/staging/pohmelfs/mcache.c linux-2.6.38.7/drivers/staging/pohmelfs/mcache.c
+--- linux-2.6.38.7/drivers/staging/pohmelfs/mcache.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/pohmelfs/mcache.c 2011-04-28 19:34:15.000000000 -0400
+@@ -121,7 +121,7 @@ struct pohmelfs_mcache *pohmelfs_mcache_
+ m->data = data;
+ m->start = start;
+ m->size = size;
+- m->gen = atomic_long_inc_return(&psb->mcache_gen);
++ m->gen = atomic_long_inc_return_unchecked(&psb->mcache_gen);
+
+ mutex_lock(&psb->mcache_lock);
+ err = pohmelfs_mcache_insert(psb, m);
+diff -urNp linux-2.6.38.7/drivers/staging/pohmelfs/netfs.h linux-2.6.38.7/drivers/staging/pohmelfs/netfs.h
+--- linux-2.6.38.7/drivers/staging/pohmelfs/netfs.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/pohmelfs/netfs.h 2011-04-28 19:57:25.000000000 -0400
+@@ -571,14 +571,14 @@ struct pohmelfs_config;
+ struct pohmelfs_sb {
+ struct rb_root mcache_root;
+ struct mutex mcache_lock;
+- atomic_long_t mcache_gen;
++ atomic_long_unchecked_t mcache_gen;
+ unsigned long mcache_timeout;
+
+ unsigned int idx;
+
+ unsigned int trans_retries;
+
+- atomic_t trans_gen;
++ atomic_unchecked_t trans_gen;
+
+ unsigned int crypto_attached_size;
+ unsigned int crypto_align_size;
+diff -urNp linux-2.6.38.7/drivers/staging/pohmelfs/trans.c linux-2.6.38.7/drivers/staging/pohmelfs/trans.c
+--- linux-2.6.38.7/drivers/staging/pohmelfs/trans.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/pohmelfs/trans.c 2011-04-28 19:57:25.000000000 -0400
+@@ -492,7 +492,7 @@ int netfs_trans_finish(struct netfs_tran
+ int err;
+ struct netfs_cmd *cmd = t->iovec.iov_base;
+
+- t->gen = atomic_inc_return(&psb->trans_gen);
++ t->gen = atomic_inc_return_unchecked(&psb->trans_gen);
+
+ cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) +
+ t->attached_size + t->attached_pages * sizeof(struct netfs_cmd);
+diff -urNp linux-2.6.38.7/drivers/staging/rtl8192u/ieee80211/proc.c linux-2.6.38.7/drivers/staging/rtl8192u/ieee80211/proc.c
+--- linux-2.6.38.7/drivers/staging/rtl8192u/ieee80211/proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/rtl8192u/ieee80211/proc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -99,7 +99,7 @@ static int crypto_info_open(struct inode
+ return seq_open(file, &crypto_seq_ops);
+ }
+
+-static struct file_operations proc_crypto_ops = {
++static const struct file_operations proc_crypto_ops = {
+ .open = crypto_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+diff -urNp linux-2.6.38.7/drivers/staging/spectra/ffsport.c linux-2.6.38.7/drivers/staging/spectra/ffsport.c
+--- linux-2.6.38.7/drivers/staging/spectra/ffsport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/spectra/ffsport.c 2011-04-28 19:34:15.000000000 -0400
+@@ -604,7 +604,7 @@ int GLOB_SBD_unlocked_ioctl(struct block
+ return ret;
+ }
+
+-static struct block_device_operations GLOB_SBD_ops = {
++static const struct block_device_operations GLOB_SBD_ops = {
+ .owner = THIS_MODULE,
+ .open = GLOB_SBD_open,
+ .release = GLOB_SBD_release,
+diff -urNp linux-2.6.38.7/drivers/staging/usbip/vhci.h linux-2.6.38.7/drivers/staging/usbip/vhci.h
+--- linux-2.6.38.7/drivers/staging/usbip/vhci.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/usbip/vhci.h 2011-04-28 19:57:25.000000000 -0400
+@@ -92,7 +92,7 @@ struct vhci_hcd {
+ unsigned resuming:1;
+ unsigned long re_timeout;
+
+- atomic_t seqnum;
++ atomic_unchecked_t seqnum;
+
+ /*
+ * NOTE:
+diff -urNp linux-2.6.38.7/drivers/staging/usbip/vhci_hcd.c linux-2.6.38.7/drivers/staging/usbip/vhci_hcd.c
+--- linux-2.6.38.7/drivers/staging/usbip/vhci_hcd.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/usbip/vhci_hcd.c 2011-05-10 22:08:57.000000000 -0400
+@@ -535,7 +535,7 @@ static void vhci_tx_urb(struct urb *urb)
+ return;
+ }
+
+- priv->seqnum = atomic_inc_return(&the_controller->seqnum);
++ priv->seqnum = atomic_inc_return_unchecked(&the_controller->seqnum);
+ if (priv->seqnum == 0xffff)
+ usbip_uinfo("seqnum max\n");
+
+@@ -794,7 +794,7 @@ static int vhci_urb_dequeue(struct usb_h
+ return -ENOMEM;
+ }
+
+- unlink->seqnum = atomic_inc_return(&the_controller->seqnum);
++ unlink->seqnum = atomic_inc_return_unchecked(&the_controller->seqnum);
+ if (unlink->seqnum == 0xffff)
+ usbip_uinfo("seqnum max\n");
+
+@@ -989,7 +989,7 @@ static int vhci_start(struct usb_hcd *hc
+ vdev->rhport = rhport;
+ }
+
+- atomic_set(&vhci->seqnum, 0);
++ atomic_set_unchecked(&vhci->seqnum, 0);
+ spin_lock_init(&vhci->lock);
+
+
+diff -urNp linux-2.6.38.7/drivers/staging/usbip/vhci_rx.c linux-2.6.38.7/drivers/staging/usbip/vhci_rx.c
+--- linux-2.6.38.7/drivers/staging/usbip/vhci_rx.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/usbip/vhci_rx.c 2011-04-28 19:57:25.000000000 -0400
+@@ -80,7 +80,7 @@ static void vhci_recv_ret_submit(struct
+ usbip_uerr("cannot find a urb of seqnum %u\n",
+ pdu->base.seqnum);
+ usbip_uinfo("max seqnum %d\n",
+- atomic_read(&the_controller->seqnum));
++ atomic_read_unchecked(&the_controller->seqnum));
+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+ return;
+ }
+diff -urNp linux-2.6.38.7/drivers/staging/vme/devices/vme_user.c linux-2.6.38.7/drivers/staging/vme/devices/vme_user.c
+--- linux-2.6.38.7/drivers/staging/vme/devices/vme_user.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/vme/devices/vme_user.c 2011-04-28 19:34:15.000000000 -0400
+@@ -138,7 +138,7 @@ static long vme_user_unlocked_ioctl(stru
+ static int __devinit vme_user_probe(struct device *, int, int);
+ static int __devexit vme_user_remove(struct device *, int, int);
+
+-static struct file_operations vme_user_fops = {
++static const struct file_operations vme_user_fops = {
+ .open = vme_user_open,
+ .release = vme_user_release,
+ .read = vme_user_read,
+diff -urNp linux-2.6.38.7/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c linux-2.6.38.7/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c
+--- linux-2.6.38.7/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c 2011-04-28 19:34:15.000000000 -0400
+@@ -426,7 +426,7 @@ int cyasblkdev_revalidate_disk(struct ge
+
+
+ /*standard block device driver interface */
+-static struct block_device_operations cyasblkdev_bdops = {
++static const struct block_device_operations cyasblkdev_bdops = {
+ .open = cyasblkdev_blk_open,
+ .release = cyasblkdev_blk_release,
+ .ioctl = cyasblkdev_blk_ioctl,
+diff -urNp linux-2.6.38.7/drivers/target/target_core_alua.c linux-2.6.38.7/drivers/target/target_core_alua.c
+--- linux-2.6.38.7/drivers/target/target_core_alua.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/target/target_core_alua.c 2011-05-16 21:47:08.000000000 -0400
+@@ -675,6 +675,8 @@ static int core_alua_update_tpg_primary_
+ char path[ALUA_METADATA_PATH_LEN];
+ int len;
+
++ pax_track_stack();
++
+ memset(path, 0, ALUA_METADATA_PATH_LEN);
+
+ len = snprintf(md_buf, tg_pt_gp->tg_pt_gp_md_buf_len,
+@@ -938,6 +940,8 @@ static int core_alua_update_tpg_secondar
+ char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN];
+ int len;
+
++ pax_track_stack();
++
+ memset(path, 0, ALUA_METADATA_PATH_LEN);
+ memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN);
+
+diff -urNp linux-2.6.38.7/drivers/target/target_core_cdb.c linux-2.6.38.7/drivers/target/target_core_cdb.c
+--- linux-2.6.38.7/drivers/target/target_core_cdb.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/drivers/target/target_core_cdb.c 2011-05-16 21:47:08.000000000 -0400
+@@ -838,6 +838,8 @@ target_emulate_modesense(struct se_cmd *
+ int length = 0;
+ unsigned char buf[SE_MODE_PAGE_BUF];
+
++ pax_track_stack();
++
+ memset(buf, 0, SE_MODE_PAGE_BUF);
+
+ switch (cdb[2] & 0x3f) {
+diff -urNp linux-2.6.38.7/drivers/target/target_core_configfs.c linux-2.6.38.7/drivers/target/target_core_configfs.c
+--- linux-2.6.38.7/drivers/target/target_core_configfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/target/target_core_configfs.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1279,6 +1279,8 @@ static ssize_t target_core_dev_pr_show_a
+ ssize_t len = 0;
+ int reg_count = 0, prf_isid;
+
++ pax_track_stack();
++
+ if (!(su_dev->se_dev_ptr))
+ return -ENODEV;
+
+diff -urNp linux-2.6.38.7/drivers/target/target_core_pr.c linux-2.6.38.7/drivers/target/target_core_pr.c
+--- linux-2.6.38.7/drivers/target/target_core_pr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/target/target_core_pr.c 2011-05-16 21:47:08.000000000 -0400
+@@ -918,6 +918,8 @@ static int __core_scsi3_check_aptpl_regi
+ unsigned char t_port[PR_APTPL_MAX_TPORT_LEN];
+ u16 tpgt;
+
++ pax_track_stack();
++
+ memset(i_port, 0, PR_APTPL_MAX_IPORT_LEN);
+ memset(t_port, 0, PR_APTPL_MAX_TPORT_LEN);
+ /*
+@@ -1861,6 +1863,8 @@ static int __core_scsi3_update_aptpl_buf
+ ssize_t len = 0;
+ int reg_count = 0;
+
++ pax_track_stack();
++
+ memset(buf, 0, pr_aptpl_buf_len);
+ /*
+ * Called to clear metadata once APTPL has been deactivated.
+@@ -1983,6 +1987,8 @@ static int __core_scsi3_write_aptpl_to_f
+ char path[512];
+ int ret;
+
++ pax_track_stack();
++
+ memset(iov, 0, sizeof(struct iovec));
+ memset(path, 0, 512);
+
+diff -urNp linux-2.6.38.7/drivers/target/target_core_tmr.c linux-2.6.38.7/drivers/target/target_core_tmr.c
+--- linux-2.6.38.7/drivers/target/target_core_tmr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/target/target_core_tmr.c 2011-04-28 19:57:25.000000000 -0400
+@@ -262,7 +262,7 @@ int core_tmr_lun_reset(
+ CMD_TFO(cmd)->get_task_tag(cmd), cmd->pr_res_key,
+ T_TASK(cmd)->t_task_cdbs,
+ atomic_read(&T_TASK(cmd)->t_task_cdbs_left),
+- atomic_read(&T_TASK(cmd)->t_task_cdbs_sent),
++ atomic_read_unchecked(&T_TASK(cmd)->t_task_cdbs_sent),
+ atomic_read(&T_TASK(cmd)->t_transport_active),
+ atomic_read(&T_TASK(cmd)->t_transport_stop),
+ atomic_read(&T_TASK(cmd)->t_transport_sent));
+@@ -304,7 +304,7 @@ int core_tmr_lun_reset(
+ DEBUG_LR("LUN_RESET: got t_transport_active = 1 for"
+ " task: %p, t_fe_count: %d dev: %p\n", task,
+ fe_count, dev);
+- atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
++ atomic_set_unchecked(&T_TASK(cmd)->t_transport_aborted, 1);
+ spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+ flags);
+ core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
+@@ -314,7 +314,7 @@ int core_tmr_lun_reset(
+ }
+ DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p,"
+ " t_fe_count: %d dev: %p\n", task, fe_count, dev);
+- atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
++ atomic_set_unchecked(&T_TASK(cmd)->t_transport_aborted, 1);
+ spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+ core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
+
+diff -urNp linux-2.6.38.7/drivers/target/target_core_transport.c linux-2.6.38.7/drivers/target/target_core_transport.c
+--- linux-2.6.38.7/drivers/target/target_core_transport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/target/target_core_transport.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1678,7 +1678,7 @@ struct se_device *transport_add_device_t
+
+ dev->queue_depth = dev_limits->queue_depth;
+ atomic_set(&dev->depth_left, dev->queue_depth);
+- atomic_set(&dev->dev_ordered_id, 0);
++ atomic_set_unchecked(&dev->dev_ordered_id, 0);
+
+ se_dev_set_default_attribs(dev, dev_limits);
+
+@@ -1880,7 +1880,7 @@ static int transport_check_alloc_task_at
+ * Used to determine when ORDERED commands should go from
+ * Dormant to Active status.
+ */
+- cmd->se_ordered_id = atomic_inc_return(&SE_DEV(cmd)->dev_ordered_id);
++ cmd->se_ordered_id = atomic_inc_return_unchecked(&SE_DEV(cmd)->dev_ordered_id);
+ smp_mb__after_atomic_inc();
+ DEBUG_STA("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n",
+ cmd->se_ordered_id, cmd->sam_task_attr,
+@@ -2160,7 +2160,7 @@ static void transport_generic_request_fa
+ " t_transport_active: %d t_transport_stop: %d"
+ " t_transport_sent: %d\n", T_TASK(cmd)->t_task_cdbs,
+ atomic_read(&T_TASK(cmd)->t_task_cdbs_left),
+- atomic_read(&T_TASK(cmd)->t_task_cdbs_sent),
++ atomic_read_unchecked(&T_TASK(cmd)->t_task_cdbs_sent),
+ atomic_read(&T_TASK(cmd)->t_task_cdbs_ex_left),
+ atomic_read(&T_TASK(cmd)->t_transport_active),
+ atomic_read(&T_TASK(cmd)->t_transport_stop),
+@@ -2664,9 +2664,9 @@ check_depth:
+ spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+ atomic_set(&task->task_active, 1);
+ atomic_set(&task->task_sent, 1);
+- atomic_inc(&T_TASK(cmd)->t_task_cdbs_sent);
++ atomic_inc_unchecked(&T_TASK(cmd)->t_task_cdbs_sent);
+
+- if (atomic_read(&T_TASK(cmd)->t_task_cdbs_sent) ==
++ if (atomic_read_unchecked(&T_TASK(cmd)->t_task_cdbs_sent) ==
+ T_TASK(cmd)->t_task_cdbs)
+ atomic_set(&cmd->transport_sent, 1);
+
+@@ -5550,7 +5550,7 @@ static void transport_generic_wait_for_t
+ atomic_set(&T_TASK(cmd)->transport_lun_stop, 0);
+ }
+ if (!atomic_read(&T_TASK(cmd)->t_transport_active) ||
+- atomic_read(&T_TASK(cmd)->t_transport_aborted))
++ atomic_read_unchecked(&T_TASK(cmd)->t_transport_aborted))
+ goto remove;
+
+ atomic_set(&T_TASK(cmd)->t_transport_stop, 1);
+@@ -5779,7 +5779,7 @@ int transport_check_aborted_status(struc
+ {
+ int ret = 0;
+
+- if (atomic_read(&T_TASK(cmd)->t_transport_aborted) != 0) {
++ if (atomic_read_unchecked(&T_TASK(cmd)->t_transport_aborted) != 0) {
+ if (!(send_status) ||
+ (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS))
+ return 1;
+@@ -5807,7 +5807,7 @@ void transport_send_task_abort(struct se
+ */
+ if (cmd->data_direction == DMA_TO_DEVICE) {
+ if (CMD_TFO(cmd)->write_pending_status(cmd) != 0) {
+- atomic_inc(&T_TASK(cmd)->t_transport_aborted);
++ atomic_inc_unchecked(&T_TASK(cmd)->t_transport_aborted);
+ smp_mb__after_atomic_inc();
+ cmd->scsi_status = SAM_STAT_TASK_ABORTED;
+ transport_new_cmd_failure(cmd);
+@@ -5936,7 +5936,7 @@ static void transport_processing_shutdow
+ CMD_TFO(cmd)->get_task_tag(cmd),
+ T_TASK(cmd)->t_task_cdbs,
+ atomic_read(&T_TASK(cmd)->t_task_cdbs_left),
+- atomic_read(&T_TASK(cmd)->t_task_cdbs_sent),
++ atomic_read_unchecked(&T_TASK(cmd)->t_task_cdbs_sent),
+ atomic_read(&T_TASK(cmd)->t_transport_active),
+ atomic_read(&T_TASK(cmd)->t_transport_stop),
+ atomic_read(&T_TASK(cmd)->t_transport_sent));
+diff -urNp linux-2.6.38.7/drivers/telephony/ixj.c linux-2.6.38.7/drivers/telephony/ixj.c
+--- linux-2.6.38.7/drivers/telephony/ixj.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/telephony/ixj.c 2011-05-16 21:47:08.000000000 -0400
+@@ -4976,6 +4976,8 @@ static int ixj_daa_cid_read(IXJ *j)
+ bool mContinue;
+ char *pIn, *pOut;
+
++ pax_track_stack();
++
+ if (!SCI_Prepare(j))
+ return 0;
+
+diff -urNp linux-2.6.38.7/drivers/tty/hvc/hvc_console.h linux-2.6.38.7/drivers/tty/hvc/hvc_console.h
+--- linux-2.6.38.7/drivers/tty/hvc/hvc_console.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/hvc/hvc_console.h 2011-04-28 19:34:15.000000000 -0400
+@@ -82,6 +82,7 @@ extern int hvc_instantiate(uint32_t vter
+ /* register a vterm for hvc tty operation (module_init or hotplug add) */
+ extern struct hvc_struct * hvc_alloc(uint32_t vtermno, int data,
+ const struct hv_ops *ops, int outbuf_size);
++
+ /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */
+ extern int hvc_remove(struct hvc_struct *hp);
+
+diff -urNp linux-2.6.38.7/drivers/tty/hvc/hvcs.c linux-2.6.38.7/drivers/tty/hvc/hvcs.c
+--- linux-2.6.38.7/drivers/tty/hvc/hvcs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/hvc/hvcs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -83,6 +83,7 @@
+ #include <asm/hvcserver.h>
+ #include <asm/uaccess.h>
+ #include <asm/vio.h>
++#include <asm/local.h>
+
+ /*
+ * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00).
+@@ -270,7 +271,7 @@ struct hvcs_struct {
+ unsigned int index;
+
+ struct tty_struct *tty;
+- int open_count;
++ local_t open_count;
+
+ /*
+ * Used to tell the driver kernel_thread what operations need to take
+@@ -420,7 +421,7 @@ static ssize_t hvcs_vterm_state_store(st
+
+ spin_lock_irqsave(&hvcsd->lock, flags);
+
+- if (hvcsd->open_count > 0) {
++ if (local_read(&hvcsd->open_count) > 0) {
+ spin_unlock_irqrestore(&hvcsd->lock, flags);
+ printk(KERN_INFO "HVCS: vterm state unchanged. "
+ "The hvcs device node is still in use.\n");
+@@ -1136,7 +1137,7 @@ static int hvcs_open(struct tty_struct *
+ if ((retval = hvcs_partner_connect(hvcsd)))
+ goto error_release;
+
+- hvcsd->open_count = 1;
++ local_set(&hvcsd->open_count, 1);
+ hvcsd->tty = tty;
+ tty->driver_data = hvcsd;
+
+@@ -1170,7 +1171,7 @@ fast_open:
+
+ spin_lock_irqsave(&hvcsd->lock, flags);
+ kref_get(&hvcsd->kref);
+- hvcsd->open_count++;
++ local_inc(&hvcsd->open_count);
+ hvcsd->todo_mask |= HVCS_SCHED_READ;
+ spin_unlock_irqrestore(&hvcsd->lock, flags);
+
+@@ -1214,7 +1215,7 @@ static void hvcs_close(struct tty_struct
+ hvcsd = tty->driver_data;
+
+ spin_lock_irqsave(&hvcsd->lock, flags);
+- if (--hvcsd->open_count == 0) {
++ if (local_dec_and_test(&hvcsd->open_count)) {
+
+ vio_disable_interrupts(hvcsd->vdev);
+
+@@ -1240,10 +1241,10 @@ static void hvcs_close(struct tty_struct
+ free_irq(irq, hvcsd);
+ kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ return;
+- } else if (hvcsd->open_count < 0) {
++ } else if (local_read(&hvcsd->open_count) < 0) {
+ printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
+ " is missmanaged.\n",
+- hvcsd->vdev->unit_address, hvcsd->open_count);
++ hvcsd->vdev->unit_address, local_read(&hvcsd->open_count));
+ }
+
+ spin_unlock_irqrestore(&hvcsd->lock, flags);
+@@ -1259,7 +1260,7 @@ static void hvcs_hangup(struct tty_struc
+
+ spin_lock_irqsave(&hvcsd->lock, flags);
+ /* Preserve this so that we know how many kref refs to put */
+- temp_open_count = hvcsd->open_count;
++ temp_open_count = local_read(&hvcsd->open_count);
+
+ /*
+ * Don't kref put inside the spinlock because the destruction
+@@ -1274,7 +1275,7 @@ static void hvcs_hangup(struct tty_struc
+ hvcsd->tty->driver_data = NULL;
+ hvcsd->tty = NULL;
+
+- hvcsd->open_count = 0;
++ local_set(&hvcsd->open_count, 0);
+
+ /* This will drop any buffered data on the floor which is OK in a hangup
+ * scenario. */
+@@ -1345,7 +1346,7 @@ static int hvcs_write(struct tty_struct
+ * the middle of a write operation? This is a crummy place to do this
+ * but we want to keep it all in the spinlock.
+ */
+- if (hvcsd->open_count <= 0) {
++ if (local_read(&hvcsd->open_count) <= 0) {
+ spin_unlock_irqrestore(&hvcsd->lock, flags);
+ return -ENODEV;
+ }
+@@ -1419,7 +1420,7 @@ static int hvcs_write_room(struct tty_st
+ {
+ struct hvcs_struct *hvcsd = tty->driver_data;
+
+- if (!hvcsd || hvcsd->open_count <= 0)
++ if (!hvcsd || local_read(&hvcsd->open_count) <= 0)
+ return 0;
+
+ return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
+diff -urNp linux-2.6.38.7/drivers/tty/hvc/hvc_xen.c linux-2.6.38.7/drivers/tty/hvc/hvc_xen.c
+--- linux-2.6.38.7/drivers/tty/hvc/hvc_xen.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/hvc/hvc_xen.c 2011-04-28 19:34:15.000000000 -0400
+@@ -123,7 +123,7 @@ static int domU_read_console(uint32_t vt
+ return recv;
+ }
+
+-static struct hv_ops domU_hvc_ops = {
++static const struct hv_ops domU_hvc_ops = {
+ .get_chars = domU_read_console,
+ .put_chars = domU_write_console,
+ .notifier_add = notifier_add_irq,
+@@ -149,7 +149,7 @@ static int dom0_write_console(uint32_t v
+ return len;
+ }
+
+-static struct hv_ops dom0_hvc_ops = {
++static const struct hv_ops dom0_hvc_ops = {
+ .get_chars = dom0_read_console,
+ .put_chars = dom0_write_console,
+ .notifier_add = notifier_add_irq,
+@@ -160,7 +160,7 @@ static struct hv_ops dom0_hvc_ops = {
+ static int __init xen_hvc_init(void)
+ {
+ struct hvc_struct *hp;
+- struct hv_ops *ops;
++ const struct hv_ops *ops;
+
+ if (!xen_pv_domain())
+ return -ENODEV;
+@@ -203,7 +203,7 @@ static void __exit xen_hvc_fini(void)
+
+ static int xen_cons_init(void)
+ {
+- struct hv_ops *ops;
++ const struct hv_ops *ops;
+
+ if (!xen_pv_domain())
+ return 0;
+diff -urNp linux-2.6.38.7/drivers/tty/n_gsm.c linux-2.6.38.7/drivers/tty/n_gsm.c
+--- linux-2.6.38.7/drivers/tty/n_gsm.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/n_gsm.c 2011-05-10 22:06:56.000000000 -0400
+@@ -1589,7 +1589,7 @@ static struct gsm_dlci *gsm_dlci_alloc(s
+ return NULL;
+ spin_lock_init(&dlci->lock);
+ dlci->fifo = &dlci->_fifo;
+- if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) {
++ if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL)) {
+ kfree(dlci);
+ return NULL;
+ }
+diff -urNp linux-2.6.38.7/drivers/tty/n_tty.c linux-2.6.38.7/drivers/tty/n_tty.c
+--- linux-2.6.38.7/drivers/tty/n_tty.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/n_tty.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2116,6 +2116,7 @@ void n_tty_inherit_ops(struct tty_ldisc_
+ {
+ *ops = tty_ldisc_N_TTY;
+ ops->owner = NULL;
+- ops->refcount = ops->flags = 0;
++ atomic_set(&ops->refcount, 0);
++ ops->flags = 0;
+ }
+ EXPORT_SYMBOL_GPL(n_tty_inherit_ops);
+diff -urNp linux-2.6.38.7/drivers/tty/pty.c linux-2.6.38.7/drivers/tty/pty.c
+--- linux-2.6.38.7/drivers/tty/pty.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/pty.c 2011-04-28 19:34:15.000000000 -0400
+@@ -700,7 +700,18 @@ out:
+ return retval;
+ }
+
+-static struct file_operations ptmx_fops;
++static const struct file_operations ptmx_fops = {
++ .llseek = no_llseek,
++ .read = tty_read,
++ .write = tty_write,
++ .poll = tty_poll,
++ .unlocked_ioctl = tty_ioctl,
++ .compat_ioctl = tty_compat_ioctl,
++ .open = ptmx_open,
++ .release = tty_release,
++ .fasync = tty_fasync,
++};
++
+
+ static void __init unix98_pty_init(void)
+ {
+@@ -753,10 +764,6 @@ static void __init unix98_pty_init(void)
+
+ register_sysctl_table(pty_root_table);
+
+- /* Now create the /dev/ptmx special device */
+- tty_default_fops(&ptmx_fops);
+- ptmx_fops.open = ptmx_open;
+-
+ cdev_init(&ptmx_cdev, &ptmx_fops);
+ if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
+ register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
+diff -urNp linux-2.6.38.7/drivers/tty/serial/kgdboc.c linux-2.6.38.7/drivers/tty/serial/kgdboc.c
+--- linux-2.6.38.7/drivers/tty/serial/kgdboc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/serial/kgdboc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -22,7 +22,7 @@
+
+ #define MAX_CONFIG_LEN 40
+
+-static struct kgdb_io kgdboc_io_ops;
++static struct kgdb_io kgdboc_io_ops; /* cannot be const, see configure_kgdboc() */
+
+ /* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
+ static int configured = -1;
+@@ -293,7 +293,7 @@ static void kgdboc_post_exp_handler(void
+ kgdboc_restore_input();
+ }
+
+-static struct kgdb_io kgdboc_io_ops = {
++static struct kgdb_io kgdboc_io_ops = { /* cannot be const, see configure_kgdboc() */
+ .name = "kgdboc",
+ .read_char = kgdboc_get_char,
+ .write_char = kgdboc_put_char,
+diff -urNp linux-2.6.38.7/drivers/tty/serial/mrst_max3110.c linux-2.6.38.7/drivers/tty/serial/mrst_max3110.c
+--- linux-2.6.38.7/drivers/tty/serial/mrst_max3110.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/serial/mrst_max3110.c 2011-05-16 21:47:08.000000000 -0400
+@@ -393,6 +393,8 @@ static void max3110_con_receive(struct u
+ int loop = 1, num, total = 0;
+ u8 recv_buf[512], *pbuf;
+
++ pax_track_stack();
++
+ pbuf = recv_buf;
+ do {
+ num = max3110_read_multi(max, pbuf);
+diff -urNp linux-2.6.38.7/drivers/tty/tty_io.c linux-2.6.38.7/drivers/tty/tty_io.c
+--- linux-2.6.38.7/drivers/tty/tty_io.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/tty_io.c 2011-04-28 19:34:15.000000000 -0400
+@@ -140,21 +140,11 @@ EXPORT_SYMBOL(tty_mutex);
+ /* Spinlock to protect the tty->tty_files list */
+ DEFINE_SPINLOCK(tty_files_lock);
+
+-static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
+-static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
+ ssize_t redirected_tty_write(struct file *, const char __user *,
+ size_t, loff_t *);
+-static unsigned int tty_poll(struct file *, poll_table *);
+ static int tty_open(struct inode *, struct file *);
+ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+-#ifdef CONFIG_COMPAT
+-static long tty_compat_ioctl(struct file *file, unsigned int cmd,
+- unsigned long arg);
+-#else
+-#define tty_compat_ioctl NULL
+-#endif
+ static int __tty_fasync(int fd, struct file *filp, int on);
+-static int tty_fasync(int fd, struct file *filp, int on);
+ static void release_tty(struct tty_struct *tty, int idx);
+ static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+@@ -938,7 +928,7 @@ EXPORT_SYMBOL(start_tty);
+ * read calls may be outstanding in parallel.
+ */
+
+-static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
++ssize_t tty_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+ {
+ int i;
+@@ -964,6 +954,8 @@ static ssize_t tty_read(struct file *fil
+ return i;
+ }
+
++EXPORT_SYMBOL(tty_read);
++
+ void tty_write_unlock(struct tty_struct *tty)
+ {
+ mutex_unlock(&tty->atomic_write_lock);
+@@ -1113,7 +1105,7 @@ void tty_write_message(struct tty_struct
+ * write method will not be invoked in parallel for each device.
+ */
+
+-static ssize_t tty_write(struct file *file, const char __user *buf,
++ssize_t tty_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ struct inode *inode = file->f_path.dentry->d_inode;
+@@ -1139,6 +1131,8 @@ static ssize_t tty_write(struct file *fi
+ return ret;
+ }
+
++EXPORT_SYMBOL(tty_write);
++
+ ssize_t redirected_tty_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+@@ -1778,6 +1772,8 @@ int tty_release(struct inode *inode, str
+ return 0;
+ }
+
++EXPORT_SYMBOL(tty_release);
++
+ /**
+ * tty_open - open a tty device
+ * @inode: inode of device file
+@@ -1969,7 +1965,7 @@ got_driver:
+ * may be re-entered freely by other callers.
+ */
+
+-static unsigned int tty_poll(struct file *filp, poll_table *wait)
++unsigned int tty_poll(struct file *filp, poll_table *wait)
+ {
+ struct tty_struct *tty = file_tty(filp);
+ struct tty_ldisc *ld;
+@@ -1985,6 +1981,8 @@ static unsigned int tty_poll(struct file
+ return ret;
+ }
+
++EXPORT_SYMBOL(tty_poll);
++
+ static int __tty_fasync(int fd, struct file *filp, int on)
+ {
+ struct tty_struct *tty = file_tty(filp);
+@@ -2026,7 +2024,7 @@ out:
+ return retval;
+ }
+
+-static int tty_fasync(int fd, struct file *filp, int on)
++int tty_fasync(int fd, struct file *filp, int on)
+ {
+ int retval;
+ tty_lock();
+@@ -2035,6 +2033,8 @@ static int tty_fasync(int fd, struct fil
+ return retval;
+ }
+
++EXPORT_SYMBOL(tty_fasync);
++
+ /**
+ * tiocsti - fake input character
+ * @tty: tty to fake input into
+@@ -2692,8 +2692,10 @@ long tty_ioctl(struct file *file, unsign
+ return retval;
+ }
+
++EXPORT_SYMBOL(tty_ioctl);
++
+ #ifdef CONFIG_COMPAT
+-static long tty_compat_ioctl(struct file *file, unsigned int cmd,
++long tty_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+ {
+ struct inode *inode = file->f_dentry->d_inode;
+@@ -2717,6 +2719,9 @@ static long tty_compat_ioctl(struct file
+
+ return retval;
+ }
++
++EXPORT_SYMBOL(tty_compat_ioctl);
++
+ #endif
+
+ /*
+@@ -3195,11 +3200,6 @@ struct tty_struct *get_current_tty(void)
+ }
+ EXPORT_SYMBOL_GPL(get_current_tty);
+
+-void tty_default_fops(struct file_operations *fops)
+-{
+- *fops = tty_fops;
+-}
+-
+ /*
+ * Initialize the console device. This is called *early*, so
+ * we can't necessarily depend on lots of kernel help here.
+diff -urNp linux-2.6.38.7/drivers/tty/tty_ldisc.c linux-2.6.38.7/drivers/tty/tty_ldisc.c
+--- linux-2.6.38.7/drivers/tty/tty_ldisc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/tty_ldisc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -76,7 +76,7 @@ static void put_ldisc(struct tty_ldisc *
+ if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
+ struct tty_ldisc_ops *ldo = ld->ops;
+
+- ldo->refcount--;
++ atomic_dec(&ldo->refcount);
+ module_put(ldo->owner);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+@@ -111,7 +111,7 @@ int tty_register_ldisc(int disc, struct
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ tty_ldiscs[disc] = new_ldisc;
+ new_ldisc->num = disc;
+- new_ldisc->refcount = 0;
++ atomic_set(&new_ldisc->refcount, 0);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ return ret;
+@@ -139,7 +139,7 @@ int tty_unregister_ldisc(int disc)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+- if (tty_ldiscs[disc]->refcount)
++ if (atomic_read(&tty_ldiscs[disc]->refcount))
+ ret = -EBUSY;
+ else
+ tty_ldiscs[disc] = NULL;
+@@ -160,7 +160,7 @@ static struct tty_ldisc_ops *get_ldops(i
+ if (ldops) {
+ ret = ERR_PTR(-EAGAIN);
+ if (try_module_get(ldops->owner)) {
+- ldops->refcount++;
++ atomic_inc(&ldops->refcount);
+ ret = ldops;
+ }
+ }
+@@ -173,7 +173,7 @@ static void put_ldops(struct tty_ldisc_o
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+- ldops->refcount--;
++ atomic_dec(&ldops->refcount);
+ module_put(ldops->owner);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ }
+diff -urNp linux-2.6.38.7/drivers/tty/vt/keyboard.c linux-2.6.38.7/drivers/tty/vt/keyboard.c
+--- linux-2.6.38.7/drivers/tty/vt/keyboard.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/vt/keyboard.c 2011-04-28 19:34:15.000000000 -0400
+@@ -657,6 +657,16 @@ static void k_spec(struct vc_data *vc, u
+ kbd->kbdmode == VC_MEDIUMRAW) &&
+ value != KVAL(K_SAK))
+ return; /* SAK is allowed even in raw mode */
++
++#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
++ {
++ void *func = fn_handler[value];
++ if (func == fn_show_state || func == fn_show_ptregs ||
++ func == fn_show_mem)
++ return;
++ }
++#endif
++
+ fn_handler[value](vc);
+ }
+
+diff -urNp linux-2.6.38.7/drivers/tty/vt/vt.c linux-2.6.38.7/drivers/tty/vt/vt.c
+--- linux-2.6.38.7/drivers/tty/vt/vt.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/vt/vt.c 2011-04-28 19:34:15.000000000 -0400
+@@ -262,7 +262,7 @@ EXPORT_SYMBOL_GPL(unregister_vt_notifier
+
+ static void notify_write(struct vc_data *vc, unsigned int unicode)
+ {
+- struct vt_notifier_param param = { .vc = vc, unicode = unicode };
++ struct vt_notifier_param param = { .vc = vc, .c = unicode };
+ atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, &param);
+ }
+
+diff -urNp linux-2.6.38.7/drivers/tty/vt/vt_ioctl.c linux-2.6.38.7/drivers/tty/vt/vt_ioctl.c
+--- linux-2.6.38.7/drivers/tty/vt/vt_ioctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/tty/vt/vt_ioctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -210,9 +210,6 @@ do_kdsk_ioctl(int cmd, struct kbentry __
+ if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
+ return -EFAULT;
+
+- if (!capable(CAP_SYS_TTY_CONFIG))
+- perm = 0;
+-
+ switch (cmd) {
+ case KDGKBENT:
+ key_map = key_maps[s];
+@@ -224,6 +221,9 @@ do_kdsk_ioctl(int cmd, struct kbentry __
+ val = (i ? K_HOLE : K_NOSUCHMAP);
+ return put_user(val, &user_kbe->kb_value);
+ case KDSKBENT:
++ if (!capable(CAP_SYS_TTY_CONFIG))
++ perm = 0;
++
+ if (!perm)
+ return -EPERM;
+ if (!i && v == K_NOSUCHMAP) {
+@@ -325,9 +325,6 @@ do_kdgkb_ioctl(int cmd, struct kbsentry
+ int i, j, k;
+ int ret;
+
+- if (!capable(CAP_SYS_TTY_CONFIG))
+- perm = 0;
+-
+ kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
+ if (!kbs) {
+ ret = -ENOMEM;
+@@ -361,6 +358,9 @@ do_kdgkb_ioctl(int cmd, struct kbsentry
+ kfree(kbs);
+ return ((p && *p) ? -EOVERFLOW : 0);
+ case KDSKBSENT:
++ if (!capable(CAP_SYS_TTY_CONFIG))
++ perm = 0;
++
+ if (!perm) {
+ ret = -EPERM;
+ goto reterr;
+diff -urNp linux-2.6.38.7/drivers/uio/uio.c linux-2.6.38.7/drivers/uio/uio.c
+--- linux-2.6.38.7/drivers/uio/uio.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/uio/uio.c 2011-04-28 19:57:25.000000000 -0400
+@@ -25,6 +25,7 @@
+ #include <linux/kobject.h>
+ #include <linux/cdev.h>
+ #include <linux/uio_driver.h>
++#include <asm/local.h>
+
+ #define UIO_MAX_DEVICES (1U << MINORBITS)
+
+@@ -32,10 +33,10 @@ struct uio_device {
+ struct module *owner;
+ struct device *dev;
+ int minor;
+- atomic_t event;
++ atomic_unchecked_t event;
+ struct fasync_struct *async_queue;
+ wait_queue_head_t wait;
+- int vma_count;
++ local_t vma_count;
+ struct uio_info *info;
+ struct kobject *map_dir;
+ struct kobject *portio_dir;
+@@ -242,7 +243,7 @@ static ssize_t show_event(struct device
+ struct device_attribute *attr, char *buf)
+ {
+ struct uio_device *idev = dev_get_drvdata(dev);
+- return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
++ return sprintf(buf, "%u\n", (unsigned int)atomic_read_unchecked(&idev->event));
+ }
+
+ static struct device_attribute uio_class_attributes[] = {
+@@ -402,7 +403,7 @@ void uio_event_notify(struct uio_info *i
+ {
+ struct uio_device *idev = info->uio_dev;
+
+- atomic_inc(&idev->event);
++ atomic_inc_unchecked(&idev->event);
+ wake_up_interruptible(&idev->wait);
+ kill_fasync(&idev->async_queue, SIGIO, POLL_IN);
+ }
+@@ -455,7 +456,7 @@ static int uio_open(struct inode *inode,
+ }
+
+ listener->dev = idev;
+- listener->event_count = atomic_read(&idev->event);
++ listener->event_count = atomic_read_unchecked(&idev->event);
+ filep->private_data = listener;
+
+ if (idev->info->open) {
+@@ -506,7 +507,7 @@ static unsigned int uio_poll(struct file
+ return -EIO;
+
+ poll_wait(filep, &idev->wait, wait);
+- if (listener->event_count != atomic_read(&idev->event))
++ if (listener->event_count != atomic_read_unchecked(&idev->event))
+ return POLLIN | POLLRDNORM;
+ return 0;
+ }
+@@ -531,7 +532,7 @@ static ssize_t uio_read(struct file *fil
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+- event_count = atomic_read(&idev->event);
++ event_count = atomic_read_unchecked(&idev->event);
+ if (event_count != listener->event_count) {
+ if (copy_to_user(buf, &event_count, count))
+ retval = -EFAULT;
+@@ -602,13 +603,13 @@ static int uio_find_mem_index(struct vm_
+ static void uio_vma_open(struct vm_area_struct *vma)
+ {
+ struct uio_device *idev = vma->vm_private_data;
+- idev->vma_count++;
++ local_inc(&idev->vma_count);
+ }
+
+ static void uio_vma_close(struct vm_area_struct *vma)
+ {
+ struct uio_device *idev = vma->vm_private_data;
+- idev->vma_count--;
++ local_dec(&idev->vma_count);
+ }
+
+ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+@@ -819,7 +820,7 @@ int __uio_register_device(struct module
+ idev->owner = owner;
+ idev->info = info;
+ init_waitqueue_head(&idev->wait);
+- atomic_set(&idev->event, 0);
++ atomic_set_unchecked(&idev->event, 0);
+
+ ret = uio_get_minor(idev);
+ if (ret)
+diff -urNp linux-2.6.38.7/drivers/usb/atm/cxacru.c linux-2.6.38.7/drivers/usb/atm/cxacru.c
+--- linux-2.6.38.7/drivers/usb/atm/cxacru.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/atm/cxacru.c 2011-04-28 19:34:15.000000000 -0400
+@@ -473,7 +473,7 @@ static ssize_t cxacru_sysfs_store_adsl_c
+ ret = sscanf(buf + pos, "%x=%x%n", &index, &value, &tmp);
+ if (ret < 2)
+ return -EINVAL;
+- if (index < 0 || index > 0x7f)
++ if (index > 0x7f)
+ return -EINVAL;
+ pos += tmp;
+
+diff -urNp linux-2.6.38.7/drivers/usb/atm/usbatm.c linux-2.6.38.7/drivers/usb/atm/usbatm.c
+--- linux-2.6.38.7/drivers/usb/atm/usbatm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/atm/usbatm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -332,7 +332,7 @@ static void usbatm_extract_one_cell(stru
+ if (printk_ratelimit())
+ atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
+ __func__, vpi, vci);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ return;
+ }
+
+@@ -360,7 +360,7 @@ static void usbatm_extract_one_cell(stru
+ if (length > ATM_MAX_AAL5_PDU) {
+ atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
+ __func__, length, vcc);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto out;
+ }
+
+@@ -369,14 +369,14 @@ static void usbatm_extract_one_cell(stru
+ if (sarb->len < pdu_length) {
+ atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
+ __func__, pdu_length, sarb->len, vcc);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto out;
+ }
+
+ if (crc32_be(~0, skb_tail_pointer(sarb) - pdu_length, pdu_length) != 0xc704dd7b) {
+ atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
+ __func__, vcc);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto out;
+ }
+
+@@ -386,7 +386,7 @@ static void usbatm_extract_one_cell(stru
+ if (printk_ratelimit())
+ atm_err(instance, "%s: no memory for skb (length: %u)!\n",
+ __func__, length);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ goto out;
+ }
+
+@@ -411,7 +411,7 @@ static void usbatm_extract_one_cell(stru
+
+ vcc->push(vcc, skb);
+
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ out:
+ skb_trim(sarb, 0);
+ }
+@@ -614,7 +614,7 @@ static void usbatm_tx_process(unsigned l
+ struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc;
+
+ usbatm_pop(vcc, skb);
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+
+ skb = skb_dequeue(&instance->sndqueue);
+ }
+@@ -773,11 +773,11 @@ static int usbatm_atm_proc_read(struct a
+ if (!left--)
+ return sprintf(page,
+ "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n",
+- atomic_read(&atm_dev->stats.aal5.tx),
+- atomic_read(&atm_dev->stats.aal5.tx_err),
+- atomic_read(&atm_dev->stats.aal5.rx),
+- atomic_read(&atm_dev->stats.aal5.rx_err),
+- atomic_read(&atm_dev->stats.aal5.rx_drop));
++ atomic_read_unchecked(&atm_dev->stats.aal5.tx),
++ atomic_read_unchecked(&atm_dev->stats.aal5.tx_err),
++ atomic_read_unchecked(&atm_dev->stats.aal5.rx),
++ atomic_read_unchecked(&atm_dev->stats.aal5.rx_err),
++ atomic_read_unchecked(&atm_dev->stats.aal5.rx_drop));
+
+ if (!left--) {
+ if (instance->disconnected)
+diff -urNp linux-2.6.38.7/drivers/usb/core/devices.c linux-2.6.38.7/drivers/usb/core/devices.c
+--- linux-2.6.38.7/drivers/usb/core/devices.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/core/devices.c 2011-04-28 19:57:25.000000000 -0400
+@@ -126,7 +126,7 @@ static const char *format_endpt =
+ * time it gets called.
+ */
+ static struct device_connect_event {
+- atomic_t count;
++ atomic_unchecked_t count;
+ wait_queue_head_t wait;
+ } device_event = {
+ .count = ATOMIC_INIT(1),
+@@ -164,7 +164,7 @@ static const struct class_info clas_info
+
+ void usbfs_conn_disc_event(void)
+ {
+- atomic_add(2, &device_event.count);
++ atomic_add_unchecked(2, &device_event.count);
+ wake_up(&device_event.wait);
+ }
+
+@@ -648,7 +648,7 @@ static unsigned int usb_device_poll(stru
+
+ poll_wait(file, &device_event.wait, wait);
+
+- event_count = atomic_read(&device_event.count);
++ event_count = atomic_read_unchecked(&device_event.count);
+ if (file->f_version != event_count) {
+ file->f_version = event_count;
+ return POLLIN | POLLRDNORM;
+diff -urNp linux-2.6.38.7/drivers/usb/core/hcd.c linux-2.6.38.7/drivers/usb/core/hcd.c
+--- linux-2.6.38.7/drivers/usb/core/hcd.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/core/hcd.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2457,7 +2457,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_platform_shutd
+
+ #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+
+-struct usb_mon_operations *mon_ops;
++const struct usb_mon_operations *mon_ops;
+
+ /*
+ * The registration is unlocked.
+@@ -2467,7 +2467,7 @@ struct usb_mon_operations *mon_ops;
+ * symbols from usbcore, usbcore gets referenced and cannot be unloaded first.
+ */
+
+-int usb_mon_register (struct usb_mon_operations *ops)
++int usb_mon_register (const struct usb_mon_operations *ops)
+ {
+
+ if (mon_ops)
+diff -urNp linux-2.6.38.7/drivers/usb/core/message.c linux-2.6.38.7/drivers/usb/core/message.c
+--- linux-2.6.38.7/drivers/usb/core/message.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/core/message.c 2011-04-28 19:34:15.000000000 -0400
+@@ -869,8 +869,8 @@ char *usb_cache_string(struct usb_device
+ buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO);
+ if (buf) {
+ len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE);
+- if (len > 0) {
+- smallbuf = kmalloc(++len, GFP_NOIO);
++ if (len++ > 0) {
++ smallbuf = kmalloc(len, GFP_NOIO);
+ if (!smallbuf)
+ return buf;
+ memcpy(smallbuf, buf, len);
+diff -urNp linux-2.6.38.7/drivers/usb/early/ehci-dbgp.c linux-2.6.38.7/drivers/usb/early/ehci-dbgp.c
+--- linux-2.6.38.7/drivers/usb/early/ehci-dbgp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/early/ehci-dbgp.c 2011-04-28 19:34:15.000000000 -0400
+@@ -96,7 +96,7 @@ static inline u32 dbgp_len_update(u32 x,
+ }
+
+ #ifdef CONFIG_KGDB
+-static struct kgdb_io kgdbdbgp_io_ops;
++static struct kgdb_io kgdbdbgp_io_ops; /* cannot be const, see kgdbdbgp_parse_config */
+ #define dbgp_kgdb_mode (dbg_io_ops == &kgdbdbgp_io_ops)
+ #else
+ #define dbgp_kgdb_mode (0)
+@@ -1026,7 +1026,7 @@ static void kgdbdbgp_write_char(u8 chr)
+ early_dbgp_write(NULL, &chr, 1);
+ }
+
+-static struct kgdb_io kgdbdbgp_io_ops = {
++static struct kgdb_io kgdbdbgp_io_ops = { /* cannot be const, see kgdbdbgp_parse_config() */
+ .name = "kgdbdbgp",
+ .read_char = kgdbdbgp_read_char,
+ .write_char = kgdbdbgp_write_char,
+diff -urNp linux-2.6.38.7/drivers/usb/host/xhci-mem.c linux-2.6.38.7/drivers/usb/host/xhci-mem.c
+--- linux-2.6.38.7/drivers/usb/host/xhci-mem.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/host/xhci-mem.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1616,6 +1616,8 @@ static int xhci_check_trb_in_td_math(str
+ unsigned int num_tests;
+ int i, ret;
+
++ pax_track_stack();
++
+ num_tests = ARRAY_SIZE(simple_test_vector);
+ for (i = 0; i < num_tests; i++) {
+ ret = xhci_test_trb_in_td(xhci,
+diff -urNp linux-2.6.38.7/drivers/usb/mon/mon_main.c linux-2.6.38.7/drivers/usb/mon/mon_main.c
+--- linux-2.6.38.7/drivers/usb/mon/mon_main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/mon/mon_main.c 2011-04-28 19:34:15.000000000 -0400
+@@ -238,7 +238,7 @@ static struct notifier_block mon_nb = {
+ /*
+ * Ops
+ */
+-static struct usb_mon_operations mon_ops_0 = {
++static const struct usb_mon_operations mon_ops_0 = {
+ .urb_submit = mon_submit,
+ .urb_submit_error = mon_submit_error,
+ .urb_complete = mon_complete,
+diff -urNp linux-2.6.38.7/drivers/usb/wusbcore/wa-hc.h linux-2.6.38.7/drivers/usb/wusbcore/wa-hc.h
+--- linux-2.6.38.7/drivers/usb/wusbcore/wa-hc.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/wusbcore/wa-hc.h 2011-04-28 19:57:25.000000000 -0400
+@@ -192,7 +192,7 @@ struct wahc {
+ struct list_head xfer_delayed_list;
+ spinlock_t xfer_list_lock;
+ struct work_struct xfer_work;
+- atomic_t xfer_id_count;
++ atomic_unchecked_t xfer_id_count;
+ };
+
+
+@@ -246,7 +246,7 @@ static inline void wa_init(struct wahc *
+ INIT_LIST_HEAD(&wa->xfer_delayed_list);
+ spin_lock_init(&wa->xfer_list_lock);
+ INIT_WORK(&wa->xfer_work, wa_urb_enqueue_run);
+- atomic_set(&wa->xfer_id_count, 1);
++ atomic_set_unchecked(&wa->xfer_id_count, 1);
+ }
+
+ /**
+diff -urNp linux-2.6.38.7/drivers/usb/wusbcore/wa-xfer.c linux-2.6.38.7/drivers/usb/wusbcore/wa-xfer.c
+--- linux-2.6.38.7/drivers/usb/wusbcore/wa-xfer.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/usb/wusbcore/wa-xfer.c 2011-04-28 19:57:25.000000000 -0400
+@@ -294,7 +294,7 @@ out:
+ */
+ static void wa_xfer_id_init(struct wa_xfer *xfer)
+ {
+- xfer->id = atomic_add_return(1, &xfer->wa->xfer_id_count);
++ xfer->id = atomic_add_return_unchecked(1, &xfer->wa->xfer_id_count);
+ }
+
+ /*
+diff -urNp linux-2.6.38.7/drivers/vhost/vhost.c linux-2.6.38.7/drivers/vhost/vhost.c
+--- linux-2.6.38.7/drivers/vhost/vhost.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/vhost/vhost.c 2011-04-28 19:34:15.000000000 -0400
+@@ -565,7 +565,7 @@ static int init_used(struct vhost_virtqu
+ return get_user(vq->last_used_idx, &used->idx);
+ }
+
+-static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
++static long vhost_set_vring(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
+ {
+ struct file *eventfp, *filep = NULL,
+ *pollstart = NULL, *pollstop = NULL;
+diff -urNp linux-2.6.38.7/drivers/video/fbcmap.c linux-2.6.38.7/drivers/video/fbcmap.c
+--- linux-2.6.38.7/drivers/video/fbcmap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/video/fbcmap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -285,8 +285,7 @@ int fb_set_user_cmap(struct fb_cmap_user
+ rc = -ENODEV;
+ goto out;
+ }
+- if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
+- !info->fbops->fb_setcmap)) {
++ if (!info->fbops->fb_setcolreg && !info->fbops->fb_setcmap) {
+ rc = -EINVAL;
+ goto out1;
+ }
+diff -urNp linux-2.6.38.7/drivers/video/fbmem.c linux-2.6.38.7/drivers/video/fbmem.c
+--- linux-2.6.38.7/drivers/video/fbmem.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/video/fbmem.c 2011-05-16 21:47:08.000000000 -0400
+@@ -403,7 +403,7 @@ static void fb_do_show_logo(struct fb_in
+ image->dx += image->width + 8;
+ }
+ } else if (rotate == FB_ROTATE_UD) {
+- for (x = 0; x < num && image->dx >= 0; x++) {
++ for (x = 0; x < num && (__s32)image->dx >= 0; x++) {
+ info->fbops->fb_imageblit(info, image);
+ image->dx -= image->width + 8;
+ }
+@@ -415,7 +415,7 @@ static void fb_do_show_logo(struct fb_in
+ image->dy += image->height + 8;
+ }
+ } else if (rotate == FB_ROTATE_CCW) {
+- for (x = 0; x < num && image->dy >= 0; x++) {
++ for (x = 0; x < num && (__s32)image->dy >= 0; x++) {
+ info->fbops->fb_imageblit(info, image);
+ image->dy -= image->height + 8;
+ }
+@@ -897,6 +897,8 @@ fb_set_var(struct fb_info *info, struct
+ int flags = info->flags;
+ int ret = 0;
+
++ pax_track_stack();
++
+ if (var->activate & FB_ACTIVATE_INV_MODE) {
+ struct fb_videomode mode1, mode2;
+
+@@ -1022,6 +1024,8 @@ static long do_fb_ioctl(struct fb_info *
+ void __user *argp = (void __user *)arg;
+ long ret = 0;
+
++ pax_track_stack();
++
+ switch (cmd) {
+ case FBIOGET_VSCREENINFO:
+ if (!lock_fb_info(info))
+@@ -1101,7 +1105,7 @@ static long do_fb_ioctl(struct fb_info *
+ return -EFAULT;
+ if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+ return -EINVAL;
+- if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
++ if (con2fb.framebuffer >= FB_MAX)
+ return -EINVAL;
+ if (!registered_fb[con2fb.framebuffer])
+ request_module("fb%d", con2fb.framebuffer);
+diff -urNp linux-2.6.38.7/drivers/video/i810/i810_accel.c linux-2.6.38.7/drivers/video/i810/i810_accel.c
+--- linux-2.6.38.7/drivers/video/i810/i810_accel.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/video/i810/i810_accel.c 2011-04-28 19:34:15.000000000 -0400
+@@ -73,6 +73,7 @@ static inline int wait_for_space(struct
+ }
+ }
+ printk("ringbuffer lockup!!!\n");
++ printk("head:%u tail:%u iring.size:%u space:%u\n", head, tail, par->iring.size, space);
+ i810_report_error(mmio);
+ par->dev_flags |= LOCKUP;
+ info->pixmap.scan_align = 1;
+diff -urNp linux-2.6.38.7/drivers/video/pxa3xx-gcu.c linux-2.6.38.7/drivers/video/pxa3xx-gcu.c
+--- linux-2.6.38.7/drivers/video/pxa3xx-gcu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/video/pxa3xx-gcu.c 2011-04-28 19:34:15.000000000 -0400
+@@ -103,7 +103,7 @@ struct pxa3xx_gcu_priv {
+ dma_addr_t shared_phys;
+ struct resource *resource_mem;
+ struct miscdevice misc_dev;
+- struct file_operations misc_fops;
++ const struct file_operations misc_fops;
+ wait_queue_head_t wait_idle;
+ wait_queue_head_t wait_free;
+ spinlock_t spinlock;
+diff -urNp linux-2.6.38.7/drivers/video/udlfb.c linux-2.6.38.7/drivers/video/udlfb.c
+--- linux-2.6.38.7/drivers/video/udlfb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/video/udlfb.c 2011-04-28 19:57:25.000000000 -0400
+@@ -584,11 +584,11 @@ int dlfb_handle_damage(struct dlfb_data
+ dlfb_urb_completion(urb);
+
+ error:
+- atomic_add(bytes_sent, &dev->bytes_sent);
+- atomic_add(bytes_identical, &dev->bytes_identical);
+- atomic_add(width*height*2, &dev->bytes_rendered);
++ atomic_add_unchecked(bytes_sent, &dev->bytes_sent);
++ atomic_add_unchecked(bytes_identical, &dev->bytes_identical);
++ atomic_add_unchecked(width*height*2, &dev->bytes_rendered);
+ end_cycles = get_cycles();
+- atomic_add(((unsigned int) ((end_cycles - start_cycles)
++ atomic_add_unchecked(((unsigned int) ((end_cycles - start_cycles)
+ >> 10)), /* Kcycles */
+ &dev->cpu_kcycles_used);
+
+@@ -709,11 +709,11 @@ static void dlfb_dpy_deferred_io(struct
+ dlfb_urb_completion(urb);
+
+ error:
+- atomic_add(bytes_sent, &dev->bytes_sent);
+- atomic_add(bytes_identical, &dev->bytes_identical);
+- atomic_add(bytes_rendered, &dev->bytes_rendered);
++ atomic_add_unchecked(bytes_sent, &dev->bytes_sent);
++ atomic_add_unchecked(bytes_identical, &dev->bytes_identical);
++ atomic_add_unchecked(bytes_rendered, &dev->bytes_rendered);
+ end_cycles = get_cycles();
+- atomic_add(((unsigned int) ((end_cycles - start_cycles)
++ atomic_add_unchecked(((unsigned int) ((end_cycles - start_cycles)
+ >> 10)), /* Kcycles */
+ &dev->cpu_kcycles_used);
+ }
+@@ -1301,7 +1301,7 @@ static ssize_t metrics_bytes_rendered_sh
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+- atomic_read(&dev->bytes_rendered));
++ atomic_read_unchecked(&dev->bytes_rendered));
+ }
+
+ static ssize_t metrics_bytes_identical_show(struct device *fbdev,
+@@ -1309,7 +1309,7 @@ static ssize_t metrics_bytes_identical_s
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+- atomic_read(&dev->bytes_identical));
++ atomic_read_unchecked(&dev->bytes_identical));
+ }
+
+ static ssize_t metrics_bytes_sent_show(struct device *fbdev,
+@@ -1317,7 +1317,7 @@ static ssize_t metrics_bytes_sent_show(s
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+- atomic_read(&dev->bytes_sent));
++ atomic_read_unchecked(&dev->bytes_sent));
+ }
+
+ static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
+@@ -1325,7 +1325,7 @@ static ssize_t metrics_cpu_kcycles_used_
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+- atomic_read(&dev->cpu_kcycles_used));
++ atomic_read_unchecked(&dev->cpu_kcycles_used));
+ }
+
+ static ssize_t edid_show(
+@@ -1382,10 +1382,10 @@ static ssize_t metrics_reset_store(struc
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+
+- atomic_set(&dev->bytes_rendered, 0);
+- atomic_set(&dev->bytes_identical, 0);
+- atomic_set(&dev->bytes_sent, 0);
+- atomic_set(&dev->cpu_kcycles_used, 0);
++ atomic_set_unchecked(&dev->bytes_rendered, 0);
++ atomic_set_unchecked(&dev->bytes_identical, 0);
++ atomic_set_unchecked(&dev->bytes_sent, 0);
++ atomic_set_unchecked(&dev->cpu_kcycles_used, 0);
+
+ return count;
+ }
+diff -urNp linux-2.6.38.7/drivers/video/uvesafb.c linux-2.6.38.7/drivers/video/uvesafb.c
+--- linux-2.6.38.7/drivers/video/uvesafb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/video/uvesafb.c 2011-04-28 19:34:15.000000000 -0400
+@@ -19,6 +19,7 @@
+ #include <linux/io.h>
+ #include <linux/mutex.h>
+ #include <linux/slab.h>
++#include <linux/moduleloader.h>
+ #include <video/edid.h>
+ #include <video/uvesafb.h>
+ #ifdef CONFIG_X86
+@@ -121,7 +122,7 @@ static int uvesafb_helper_start(void)
+ NULL,
+ };
+
+- return call_usermodehelper(v86d_path, argv, envp, 1);
++ return call_usermodehelper(v86d_path, argv, envp, UMH_WAIT_PROC);
+ }
+
+ /*
+@@ -569,10 +570,32 @@ static int __devinit uvesafb_vbe_getpmi(
+ if ((task->t.regs.eax & 0xffff) != 0x4f || task->t.regs.es < 0xc000) {
+ par->pmi_setpal = par->ypan = 0;
+ } else {
++
++#ifdef CONFIG_PAX_KERNEXEC
++#ifdef CONFIG_MODULES
++ par->pmi_code = module_alloc_exec((u16)task->t.regs.ecx);
++#endif
++ if (!par->pmi_code) {
++ par->pmi_setpal = par->ypan = 0;
++ return 0;
++ }
++#endif
++
+ par->pmi_base = (u16 *)phys_to_virt(((u32)task->t.regs.es << 4)
+ + task->t.regs.edi);
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
++ pax_open_kernel();
++ memcpy(par->pmi_code, par->pmi_base, (u16)task->t.regs.ecx);
++ pax_close_kernel();
++
++ par->pmi_start = ktva_ktla(par->pmi_code + par->pmi_base[1]);
++ par->pmi_pal = ktva_ktla(par->pmi_code + par->pmi_base[2]);
++#else
+ par->pmi_start = (u8 *)par->pmi_base + par->pmi_base[1];
+ par->pmi_pal = (u8 *)par->pmi_base + par->pmi_base[2];
++#endif
++
+ printk(KERN_INFO "uvesafb: protected mode interface info at "
+ "%04x:%04x\n",
+ (u16)task->t.regs.es, (u16)task->t.regs.edi);
+@@ -1800,6 +1823,11 @@ out:
+ if (par->vbe_modes)
+ kfree(par->vbe_modes);
+
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
++ if (par->pmi_code)
++ module_free_exec(NULL, par->pmi_code);
++#endif
++
+ framebuffer_release(info);
+ return err;
+ }
+@@ -1826,6 +1854,12 @@ static int uvesafb_remove(struct platfor
+ kfree(par->vbe_state_orig);
+ if (par->vbe_state_saved)
+ kfree(par->vbe_state_saved);
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
++ if (par->pmi_code)
++ module_free_exec(NULL, par->pmi_code);
++#endif
++
+ }
+
+ framebuffer_release(info);
+diff -urNp linux-2.6.38.7/drivers/video/vesafb.c linux-2.6.38.7/drivers/video/vesafb.c
+--- linux-2.6.38.7/drivers/video/vesafb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/video/vesafb.c 2011-04-28 19:34:15.000000000 -0400
+@@ -9,6 +9,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/moduleloader.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+@@ -52,8 +53,8 @@ static int vram_remap __initdata; /*
+ static int vram_total __initdata; /* Set total amount of memory */
+ static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */
+ static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */
+-static void (*pmi_start)(void) __read_mostly;
+-static void (*pmi_pal) (void) __read_mostly;
++static void (*pmi_start)(void) __read_only;
++static void (*pmi_pal) (void) __read_only;
+ static int depth __read_mostly;
+ static int vga_compat __read_mostly;
+ /* --------------------------------------------------------------------- */
+@@ -232,6 +233,7 @@ static int __init vesafb_probe(struct pl
+ unsigned int size_vmode;
+ unsigned int size_remap;
+ unsigned int size_total;
++ void *pmi_code = NULL;
+
+ if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
+ return -ENODEV;
+@@ -274,10 +276,6 @@ static int __init vesafb_probe(struct pl
+ size_remap = size_total;
+ vesafb_fix.smem_len = size_remap;
+
+-#ifndef __i386__
+- screen_info.vesapm_seg = 0;
+-#endif
+-
+ if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
+ printk(KERN_WARNING
+ "vesafb: cannot reserve video memory at 0x%lx\n",
+@@ -319,9 +317,21 @@ static int __init vesafb_probe(struct pl
+ printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+ vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages);
+
++#ifdef __i386__
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
++ pmi_code = module_alloc_exec(screen_info.vesapm_size);
++ if (!pmi_code)
++#elif !defined(CONFIG_PAX_KERNEXEC)
++ if (0)
++#endif
++
++#endif
++ screen_info.vesapm_seg = 0;
++
+ if (screen_info.vesapm_seg) {
+- printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
+- screen_info.vesapm_seg,screen_info.vesapm_off);
++ printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x %04x bytes\n",
++ screen_info.vesapm_seg,screen_info.vesapm_off,screen_info.vesapm_size);
+ }
+
+ if (screen_info.vesapm_seg < 0xc000)
+@@ -329,9 +339,25 @@ static int __init vesafb_probe(struct pl
+
+ if (ypan || pmi_setpal) {
+ unsigned short *pmi_base;
+- pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
+- pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
+- pmi_pal = (void*)((char*)pmi_base + pmi_base[2]);
++
++ pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
++ pax_open_kernel();
++ memcpy(pmi_code, pmi_base, screen_info.vesapm_size);
++#else
++ pmi_code = pmi_base;
++#endif
++
++ pmi_start = (void*)((char*)pmi_code + pmi_base[1]);
++ pmi_pal = (void*)((char*)pmi_code + pmi_base[2]);
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
++ pmi_start = ktva_ktla(pmi_start);
++ pmi_pal = ktva_ktla(pmi_pal);
++ pax_close_kernel();
++#endif
++
+ printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
+ if (pmi_base[3]) {
+ printk(KERN_INFO "vesafb: pmi: ports = ");
+@@ -473,6 +499,11 @@ static int __init vesafb_probe(struct pl
+ info->node, info->fix.id);
+ return 0;
+ err:
++
++#if defined(__i386__) && defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
++ module_free_exec(NULL, pmi_code);
++#endif
++
+ if (info->screen_base)
+ iounmap(info->screen_base);
+ framebuffer_release(info);
+diff -urNp linux-2.6.38.7/drivers/virtio/virtio_balloon.c linux-2.6.38.7/drivers/virtio/virtio_balloon.c
+--- linux-2.6.38.7/drivers/virtio/virtio_balloon.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/drivers/virtio/virtio_balloon.c 2011-05-16 21:47:08.000000000 -0400
+@@ -176,6 +176,8 @@ static void update_balloon_stats(struct
+ struct sysinfo i;
+ int idx = 0;
+
++ pax_track_stack();
++
+ all_vm_events(events);
+ si_meminfo(&i);
+
+diff -urNp linux-2.6.38.7/fs/9p/vfs_inode.c linux-2.6.38.7/fs/9p/vfs_inode.c
+--- linux-2.6.38.7/fs/9p/vfs_inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/9p/vfs_inode.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1094,7 +1094,7 @@ static void *v9fs_vfs_follow_link(struct
+ void
+ v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+ {
+- char *s = nd_get_link(nd);
++ const char *s = nd_get_link(nd);
+
+ P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name,
+ IS_ERR(s) ? "<error>" : s);
+diff -urNp linux-2.6.38.7/fs/aio.c linux-2.6.38.7/fs/aio.c
+--- linux-2.6.38.7/fs/aio.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/fs/aio.c 2011-05-16 21:47:08.000000000 -0400
+@@ -130,7 +130,7 @@ static int aio_setup_ring(struct kioctx
+ size += sizeof(struct io_event) * nr_events;
+ nr_pages = (size + PAGE_SIZE-1) >> PAGE_SHIFT;
+
+- if (nr_pages < 0)
++ if (nr_pages <= 0)
+ return -EINVAL;
+
+ nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring)) / sizeof(struct io_event);
+@@ -1099,6 +1099,8 @@ static int read_events(struct kioctx *ct
+ struct aio_timeout to;
+ int retry = 0;
+
++ pax_track_stack();
++
+ /* needed to zero any padding within an entry (there shouldn't be
+ * any, but C is fun!
+ */
+diff -urNp linux-2.6.38.7/fs/attr.c linux-2.6.38.7/fs/attr.c
+--- linux-2.6.38.7/fs/attr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/attr.c 2011-04-28 19:34:15.000000000 -0400
+@@ -98,6 +98,7 @@ int inode_newsize_ok(const struct inode
+ unsigned long limit;
+
+ limit = rlimit(RLIMIT_FSIZE);
++ gr_learn_resource(current, RLIMIT_FSIZE, (unsigned long)offset, 1);
+ if (limit != RLIM_INFINITY && offset > limit)
+ goto out_sig;
+ if (offset > inode->i_sb->s_maxbytes)
+diff -urNp linux-2.6.38.7/fs/befs/linuxvfs.c linux-2.6.38.7/fs/befs/linuxvfs.c
+--- linux-2.6.38.7/fs/befs/linuxvfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/befs/linuxvfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -499,7 +499,7 @@ static void befs_put_link(struct dentry
+ {
+ befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+ if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
+- char *link = nd_get_link(nd);
++ const char *link = nd_get_link(nd);
+ if (!IS_ERR(link))
+ kfree(link);
+ }
+diff -urNp linux-2.6.38.7/fs/binfmt_aout.c linux-2.6.38.7/fs/binfmt_aout.c
+--- linux-2.6.38.7/fs/binfmt_aout.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/binfmt_aout.c 2011-04-28 19:34:15.000000000 -0400
+@@ -16,6 +16,7 @@
+ #include <linux/string.h>
+ #include <linux/fs.h>
+ #include <linux/file.h>
++#include <linux/security.h>
+ #include <linux/stat.h>
+ #include <linux/fcntl.h>
+ #include <linux/ptrace.h>
+@@ -86,6 +87,8 @@ static int aout_core_dump(struct coredum
+ #endif
+ # define START_STACK(u) ((void __user *)u.start_stack)
+
++ memset(&dump, 0, sizeof(dump));
++
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ has_dumped = 1;
+@@ -97,10 +100,12 @@ static int aout_core_dump(struct coredum
+
+ /* If the size of the dump file exceeds the rlimit, then see what would happen
+ if we wrote the stack, but not the data area. */
++ gr_learn_resource(current, RLIMIT_CORE, (dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE, 1);
+ if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > cprm->limit)
+ dump.u_dsize = 0;
+
+ /* Make sure we have enough room to write the stack and data areas. */
++ gr_learn_resource(current, RLIMIT_CORE, (dump.u_ssize + 1) * PAGE_SIZE, 1);
+ if ((dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)
+ dump.u_ssize = 0;
+
+@@ -234,6 +239,8 @@ static int load_aout_binary(struct linux
+ rlim = rlimit(RLIMIT_DATA);
+ if (rlim >= RLIM_INFINITY)
+ rlim = ~0;
++
++ gr_learn_resource(current, RLIMIT_DATA, ex.a_data + ex.a_bss, 1);
+ if (ex.a_data + ex.a_bss > rlim)
+ return -ENOMEM;
+
+@@ -262,6 +269,27 @@ static int load_aout_binary(struct linux
+ install_exec_creds(bprm);
+ current->flags &= ~PF_FORKNOEXEC;
+
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
++ current->mm->pax_flags = 0UL;
++#endif
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) {
++ current->mm->pax_flags |= MF_PAX_PAGEEXEC;
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ if (N_FLAGS(ex) & F_PAX_EMUTRAMP)
++ current->mm->pax_flags |= MF_PAX_EMUTRAMP;
++#endif
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (!(N_FLAGS(ex) & F_PAX_MPROTECT))
++ current->mm->pax_flags |= MF_PAX_MPROTECT;
++#endif
++
++ }
++#endif
++
+ if (N_MAGIC(ex) == OMAGIC) {
+ unsigned long text_addr, map_size;
+ loff_t pos;
+@@ -334,7 +362,7 @@ static int load_aout_binary(struct linux
+
+ down_write(&current->mm->mmap_sem);
+ error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
+- PROT_READ | PROT_WRITE | PROT_EXEC,
++ PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+ fd_offset + ex.a_text);
+ up_write(&current->mm->mmap_sem);
+diff -urNp linux-2.6.38.7/fs/binfmt_elf.c linux-2.6.38.7/fs/binfmt_elf.c
+--- linux-2.6.38.7/fs/binfmt_elf.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/fs/binfmt_elf.c 2011-05-16 21:47:08.000000000 -0400
+@@ -51,6 +51,10 @@ static int elf_core_dump(struct coredump
+ #define elf_core_dump NULL
+ #endif
+
++#ifdef CONFIG_PAX_MPROTECT
++static void elf_handle_mprotect(struct vm_area_struct *vma, unsigned long newflags);
++#endif
++
+ #if ELF_EXEC_PAGESIZE > PAGE_SIZE
+ #define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE
+ #else
+@@ -70,6 +74,11 @@ static struct linux_binfmt elf_format =
+ .load_binary = load_elf_binary,
+ .load_shlib = load_elf_library,
+ .core_dump = elf_core_dump,
++
++#ifdef CONFIG_PAX_MPROTECT
++ .handle_mprotect= elf_handle_mprotect,
++#endif
++
+ .min_coredump = ELF_EXEC_PAGESIZE,
+ };
+
+@@ -77,6 +86,8 @@ static struct linux_binfmt elf_format =
+
+ static int set_brk(unsigned long start, unsigned long end)
+ {
++ unsigned long e = end;
++
+ start = ELF_PAGEALIGN(start);
+ end = ELF_PAGEALIGN(end);
+ if (end > start) {
+@@ -87,7 +98,7 @@ static int set_brk(unsigned long start,
+ if (BAD_ADDR(addr))
+ return addr;
+ }
+- current->mm->start_brk = current->mm->brk = end;
++ current->mm->start_brk = current->mm->brk = e;
+ return 0;
+ }
+
+@@ -148,12 +159,15 @@ create_elf_tables(struct linux_binprm *b
+ elf_addr_t __user *u_rand_bytes;
+ const char *k_platform = ELF_PLATFORM;
+ const char *k_base_platform = ELF_BASE_PLATFORM;
+- unsigned char k_rand_bytes[16];
++ u32 k_rand_bytes[4];
+ int items;
+ elf_addr_t *elf_info;
+ int ei_index = 0;
+ const struct cred *cred = current_cred();
+ struct vm_area_struct *vma;
++ unsigned long saved_auxv[AT_VECTOR_SIZE];
++
++ pax_track_stack();
+
+ /*
+ * In some cases (e.g. Hyper-Threading), we want to avoid L1
+@@ -195,8 +209,12 @@ create_elf_tables(struct linux_binprm *b
+ * Generate 16 random bytes for userspace PRNG seeding.
+ */
+ get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
+- u_rand_bytes = (elf_addr_t __user *)
+- STACK_ALLOC(p, sizeof(k_rand_bytes));
++ srandom32(k_rand_bytes[0] ^ random32());
++ srandom32(k_rand_bytes[1] ^ random32());
++ srandom32(k_rand_bytes[2] ^ random32());
++ srandom32(k_rand_bytes[3] ^ random32());
++ p = STACK_ROUND(p, sizeof(k_rand_bytes));
++ u_rand_bytes = (elf_addr_t __user *) p;
+ if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
+ return -EFAULT;
+
+@@ -308,9 +326,11 @@ create_elf_tables(struct linux_binprm *b
+ return -EFAULT;
+ current->mm->env_end = p;
+
++ memcpy(saved_auxv, elf_info, ei_index * sizeof(elf_addr_t));
++
+ /* Put the elf_info on the stack in the right place. */
+ sp = (elf_addr_t __user *)envp + 1;
+- if (copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t)))
++ if (copy_to_user(sp, saved_auxv, ei_index * sizeof(elf_addr_t)))
+ return -EFAULT;
+ return 0;
+ }
+@@ -381,10 +401,10 @@ static unsigned long load_elf_interp(str
+ {
+ struct elf_phdr *elf_phdata;
+ struct elf_phdr *eppnt;
+- unsigned long load_addr = 0;
++ unsigned long load_addr = 0, pax_task_size = TASK_SIZE;
+ int load_addr_set = 0;
+ unsigned long last_bss = 0, elf_bss = 0;
+- unsigned long error = ~0UL;
++ unsigned long error = -EINVAL;
+ unsigned long total_size;
+ int retval, i, size;
+
+@@ -430,6 +450,11 @@ static unsigned long load_elf_interp(str
+ goto out_close;
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
+ eppnt = elf_phdata;
+ for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
+ if (eppnt->p_type == PT_LOAD) {
+@@ -473,8 +498,8 @@ static unsigned long load_elf_interp(str
+ k = load_addr + eppnt->p_vaddr;
+ if (BAD_ADDR(k) ||
+ eppnt->p_filesz > eppnt->p_memsz ||
+- eppnt->p_memsz > TASK_SIZE ||
+- TASK_SIZE - eppnt->p_memsz < k) {
++ eppnt->p_memsz > pax_task_size ||
++ pax_task_size - eppnt->p_memsz < k) {
+ error = -ENOMEM;
+ goto out_close;
+ }
+@@ -528,6 +553,193 @@ out:
+ return error;
+ }
+
++#if (defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)) && defined(CONFIG_PAX_SOFTMODE)
++static unsigned long pax_parse_softmode(const struct elf_phdr * const elf_phdata)
++{
++ unsigned long pax_flags = 0UL;
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (elf_phdata->p_flags & PF_PAGEEXEC)
++ pax_flags |= MF_PAX_PAGEEXEC;
++#endif
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (elf_phdata->p_flags & PF_SEGMEXEC)
++ pax_flags |= MF_PAX_SEGMEXEC;
++#endif
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC)
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
++ if ((__supported_pte_mask & _PAGE_NX))
++ pax_flags &= ~MF_PAX_SEGMEXEC;
++ else
++ pax_flags &= ~MF_PAX_PAGEEXEC;
++ }
++#endif
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ if (elf_phdata->p_flags & PF_EMUTRAMP)
++ pax_flags |= MF_PAX_EMUTRAMP;
++#endif
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (elf_phdata->p_flags & PF_MPROTECT)
++ pax_flags |= MF_PAX_MPROTECT;
++#endif
++
++#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
++ if (randomize_va_space && (elf_phdata->p_flags & PF_RANDMMAP))
++ pax_flags |= MF_PAX_RANDMMAP;
++#endif
++
++ return pax_flags;
++}
++#endif
++
++#ifdef CONFIG_PAX_PT_PAX_FLAGS
++static unsigned long pax_parse_hardmode(const struct elf_phdr * const elf_phdata)
++{
++ unsigned long pax_flags = 0UL;
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (!(elf_phdata->p_flags & PF_NOPAGEEXEC))
++ pax_flags |= MF_PAX_PAGEEXEC;
++#endif
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (!(elf_phdata->p_flags & PF_NOSEGMEXEC))
++ pax_flags |= MF_PAX_SEGMEXEC;
++#endif
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC)
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
++ if ((__supported_pte_mask & _PAGE_NX))
++ pax_flags &= ~MF_PAX_SEGMEXEC;
++ else
++ pax_flags &= ~MF_PAX_PAGEEXEC;
++ }
++#endif
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ if (!(elf_phdata->p_flags & PF_NOEMUTRAMP))
++ pax_flags |= MF_PAX_EMUTRAMP;
++#endif
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (!(elf_phdata->p_flags & PF_NOMPROTECT))
++ pax_flags |= MF_PAX_MPROTECT;
++#endif
++
++#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
++ if (randomize_va_space && !(elf_phdata->p_flags & PF_NORANDMMAP))
++ pax_flags |= MF_PAX_RANDMMAP;
++#endif
++
++ return pax_flags;
++}
++#endif
++
++#ifdef CONFIG_PAX_EI_PAX
++static unsigned long pax_parse_ei_pax(const struct elfhdr * const elf_ex)
++{
++ unsigned long pax_flags = 0UL;
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_PAGEEXEC))
++ pax_flags |= MF_PAX_PAGEEXEC;
++#endif
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC))
++ pax_flags |= MF_PAX_SEGMEXEC;
++#endif
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC)
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
++ if ((__supported_pte_mask & _PAGE_NX))
++ pax_flags &= ~MF_PAX_SEGMEXEC;
++ else
++ pax_flags &= ~MF_PAX_PAGEEXEC;
++ }
++#endif
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP))
++ pax_flags |= MF_PAX_EMUTRAMP;
++#endif
++
++#ifdef CONFIG_PAX_MPROTECT
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && !(elf_ex->e_ident[EI_PAX] & EF_PAX_MPROTECT))
++ pax_flags |= MF_PAX_MPROTECT;
++#endif
++
++#ifdef CONFIG_PAX_ASLR
++ if (randomize_va_space && !(elf_ex->e_ident[EI_PAX] & EF_PAX_RANDMMAP))
++ pax_flags |= MF_PAX_RANDMMAP;
++#endif
++
++ return pax_flags;
++}
++#endif
++
++#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
++static long pax_parse_elf_flags(const struct elfhdr * const elf_ex, const struct elf_phdr * const elf_phdata)
++{
++ unsigned long pax_flags = 0UL;
++
++#ifdef CONFIG_PAX_PT_PAX_FLAGS
++ unsigned long i;
++ int found_flags = 0;
++#endif
++
++#ifdef CONFIG_PAX_EI_PAX
++ pax_flags = pax_parse_ei_pax(elf_ex);
++#endif
++
++#ifdef CONFIG_PAX_PT_PAX_FLAGS
++ for (i = 0UL; i < elf_ex->e_phnum; i++)
++ if (elf_phdata[i].p_type == PT_PAX_FLAGS) {
++ if (((elf_phdata[i].p_flags & PF_PAGEEXEC) && (elf_phdata[i].p_flags & PF_NOPAGEEXEC)) ||
++ ((elf_phdata[i].p_flags & PF_SEGMEXEC) && (elf_phdata[i].p_flags & PF_NOSEGMEXEC)) ||
++ ((elf_phdata[i].p_flags & PF_EMUTRAMP) && (elf_phdata[i].p_flags & PF_NOEMUTRAMP)) ||
++ ((elf_phdata[i].p_flags & PF_MPROTECT) && (elf_phdata[i].p_flags & PF_NOMPROTECT)) ||
++ ((elf_phdata[i].p_flags & PF_RANDMMAP) && (elf_phdata[i].p_flags & PF_NORANDMMAP)))
++ return -EINVAL;
++
++#ifdef CONFIG_PAX_SOFTMODE
++ if (pax_softmode)
++ pax_flags = pax_parse_softmode(&elf_phdata[i]);
++ else
++#endif
++
++ pax_flags = pax_parse_hardmode(&elf_phdata[i]);
++ found_flags = 1;
++ break;
++ }
++#endif
++
++#if !defined(CONFIG_PAX_EI_PAX) && defined(CONFIG_PAX_PT_PAX_FLAGS)
++ if (found_flags == 0) {
++ struct elf_phdr phdr;
++ memset(&phdr, 0, sizeof(phdr));
++ phdr.p_flags = PF_NOEMUTRAMP;
++#ifdef CONFIG_PAX_SOFTMODE
++ if (pax_softmode)
++ pax_flags = pax_parse_softmode(&phdr);
++ else
++#endif
++ pax_flags = pax_parse_hardmode(&phdr);
++ }
++#endif
++
++ if (0 > pax_check_flags(&pax_flags))
++ return -EINVAL;
++
++ current->mm->pax_flags = pax_flags;
++ return 0;
++}
++#endif
++
+ /*
+ * These are the functions used to load ELF style executables and shared
+ * libraries. There is no binary dependent code anywhere else.
+@@ -544,6 +756,11 @@ static unsigned long randomize_stack_top
+ {
+ unsigned int random_variable = 0;
+
++#ifdef CONFIG_PAX_RANDUSTACK
++ if (randomize_va_space)
++ return stack_top - current->mm->delta_stack;
++#endif
++
+ if ((current->flags & PF_RANDOMIZE) &&
+ !(current->personality & ADDR_NO_RANDOMIZE)) {
+ random_variable = get_random_int() & STACK_RND_MASK;
+@@ -562,7 +779,7 @@ static int load_elf_binary(struct linux_
+ unsigned long load_addr = 0, load_bias = 0;
+ int load_addr_set = 0;
+ char * elf_interpreter = NULL;
+- unsigned long error;
++ unsigned long error = 0;
+ struct elf_phdr *elf_ppnt, *elf_phdata;
+ unsigned long elf_bss, elf_brk;
+ int retval, i;
+@@ -572,11 +789,11 @@ static int load_elf_binary(struct linux_
+ unsigned long start_code, end_code, start_data, end_data;
+ unsigned long reloc_func_desc = 0;
+ int executable_stack = EXSTACK_DEFAULT;
+- unsigned long def_flags = 0;
+ struct {
+ struct elfhdr elf_ex;
+ struct elfhdr interp_elf_ex;
+ } *loc;
++ unsigned long pax_task_size = TASK_SIZE;
+
+ loc = kmalloc(sizeof(*loc), GFP_KERNEL);
+ if (!loc) {
+@@ -714,11 +931,81 @@ static int load_elf_binary(struct linux_
+
+ /* OK, This is the point of no return */
+ current->flags &= ~PF_FORKNOEXEC;
+- current->mm->def_flags = def_flags;
++
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
++ current->mm->pax_flags = 0UL;
++#endif
++
++#ifdef CONFIG_PAX_DLRESOLVE
++ current->mm->call_dl_resolve = 0UL;
++#endif
++
++#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
++ current->mm->call_syscall = 0UL;
++#endif
++
++#ifdef CONFIG_PAX_ASLR
++ current->mm->delta_mmap = 0UL;
++ current->mm->delta_stack = 0UL;
++#endif
++
++ current->mm->def_flags = 0;
++
++#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
++ if (0 > pax_parse_elf_flags(&loc->elf_ex, elf_phdata)) {
++ send_sig(SIGKILL, current, 0);
++ goto out_free_dentry;
++ }
++#endif
++
++#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
++ pax_set_initial_flags(bprm);
++#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
++ if (pax_set_initial_flags_func)
++ (pax_set_initial_flags_func)(bprm);
++#endif
++
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
++ if ((current->mm->pax_flags & MF_PAX_PAGEEXEC) && !(__supported_pte_mask & _PAGE_NX)) {
++ current->mm->context.user_cs_limit = PAGE_SIZE;
++ current->mm->def_flags |= VM_PAGEEXEC;
++ }
++#endif
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
++ current->mm->context.user_cs_base = SEGMEXEC_TASK_SIZE;
++ current->mm->context.user_cs_limit = TASK_SIZE-SEGMEXEC_TASK_SIZE;
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++ current->mm->def_flags |= VM_NOHUGEPAGE;
++ }
++#endif
++
++#if defined(CONFIG_ARCH_TRACK_EXEC_LIMIT) || defined(CONFIG_PAX_SEGMEXEC)
++ if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
++ set_user_cs(current->mm->context.user_cs_base, current->mm->context.user_cs_limit, get_cpu());
++ put_cpu();
++ }
++#endif
+
+ /* Do this immediately, since STACK_TOP as used in setup_arg_pages
+ may depend on the personality. */
+ SET_PERSONALITY(loc->elf_ex);
++
++#ifdef CONFIG_PAX_ASLR
++ if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
++ current->mm->delta_mmap = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN)-1)) << PAGE_SHIFT;
++ current->mm->delta_stack = (pax_get_random_long() & ((1UL << PAX_DELTA_STACK_LEN)-1)) << PAGE_SHIFT;
++ }
++#endif
++
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++ if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
++ executable_stack = EXSTACK_DISABLE_X;
++ current->personality &= ~READ_IMPLIES_EXEC;
++ } else
++#endif
++
+ if (elf_read_implies_exec(loc->elf_ex, executable_stack))
+ current->personality |= READ_IMPLIES_EXEC;
+
+@@ -800,6 +1087,20 @@ static int load_elf_binary(struct linux_
+ #else
+ load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
+ #endif
++
++#ifdef CONFIG_PAX_RANDMMAP
++ /* PaX: randomize base address at the default exe base if requested */
++ if ((current->mm->pax_flags & MF_PAX_RANDMMAP) && elf_interpreter) {
++#ifdef CONFIG_SPARC64
++ load_bias = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN) - 1)) << (PAGE_SHIFT+1);
++#else
++ load_bias = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN) - 1)) << PAGE_SHIFT;
++#endif
++ load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE - vaddr + load_bias);
++ elf_flags |= MAP_FIXED;
++ }
++#endif
++
+ }
+
+ error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
+@@ -832,9 +1133,9 @@ static int load_elf_binary(struct linux_
+ * allowed task size. Note that p_filesz must always be
+ * <= p_memsz so it is only necessary to check p_memsz.
+ */
+- if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
+- elf_ppnt->p_memsz > TASK_SIZE ||
+- TASK_SIZE - elf_ppnt->p_memsz < k) {
++ if (k >= pax_task_size || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
++ elf_ppnt->p_memsz > pax_task_size ||
++ pax_task_size - elf_ppnt->p_memsz < k) {
+ /* set_brk can never work. Avoid overflows. */
+ send_sig(SIGKILL, current, 0);
+ retval = -EINVAL;
+@@ -862,6 +1163,11 @@ static int load_elf_binary(struct linux_
+ start_data += load_bias;
+ end_data += load_bias;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (current->mm->pax_flags & MF_PAX_RANDMMAP)
++ elf_brk += PAGE_SIZE + ((pax_get_random_long() & ~PAGE_MASK) << 4);
++#endif
++
+ /* Calling set_brk effectively mmaps the pages that we need
+ * for the bss and break sections. We must do this before
+ * mapping in the interpreter, to make sure it doesn't wind
+@@ -873,9 +1179,11 @@ static int load_elf_binary(struct linux_
+ goto out_free_dentry;
+ }
+ if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
+- send_sig(SIGSEGV, current, 0);
+- retval = -EFAULT; /* Nobody gets to see this, but.. */
+- goto out_free_dentry;
++ /*
++ * This bss-zeroing can fail if the ELF
++ * file specifies odd protections. So
++ * we don't check the return value
++ */
+ }
+
+ if (elf_interpreter) {
+@@ -1090,7 +1398,7 @@ out:
+ * Decide what to dump of a segment, part, all or none.
+ */
+ static unsigned long vma_dump_size(struct vm_area_struct *vma,
+- unsigned long mm_flags)
++ unsigned long mm_flags, long signr)
+ {
+ #define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type))
+
+@@ -1124,7 +1432,7 @@ static unsigned long vma_dump_size(struc
+ if (vma->vm_file == NULL)
+ return 0;
+
+- if (FILTER(MAPPED_PRIVATE))
++ if (signr == SIGKILL || FILTER(MAPPED_PRIVATE))
+ goto whole;
+
+ /*
+@@ -1346,9 +1654,9 @@ static void fill_auxv_note(struct memelf
+ {
+ elf_addr_t *auxv = (elf_addr_t *) mm->saved_auxv;
+ int i = 0;
+- do
++ do {
+ i += 2;
+- while (auxv[i - 2] != AT_NULL);
++ } while (auxv[i - 2] != AT_NULL);
+ fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv);
+ }
+
+@@ -1854,14 +2162,14 @@ static void fill_extnum_info(struct elfh
+ }
+
+ static size_t elf_core_vma_data_size(struct vm_area_struct *gate_vma,
+- unsigned long mm_flags)
++ struct coredump_params *cprm)
+ {
+ struct vm_area_struct *vma;
+ size_t size = 0;
+
+ for (vma = first_vma(current, gate_vma); vma != NULL;
+ vma = next_vma(vma, gate_vma))
+- size += vma_dump_size(vma, mm_flags);
++ size += vma_dump_size(vma, cprm->mm_flags, cprm->signr);
+ return size;
+ }
+
+@@ -1955,7 +2263,7 @@ static int elf_core_dump(struct coredump
+
+ dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
+
+- offset += elf_core_vma_data_size(gate_vma, cprm->mm_flags);
++ offset += elf_core_vma_data_size(gate_vma, cprm);
+ offset += elf_core_extra_data_size();
+ e_shoff = offset;
+
+@@ -1969,10 +2277,12 @@ static int elf_core_dump(struct coredump
+ offset = dataoff;
+
+ size += sizeof(*elf);
++ gr_learn_resource(current, RLIMIT_CORE, size, 1);
+ if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
+ goto end_coredump;
+
+ size += sizeof(*phdr4note);
++ gr_learn_resource(current, RLIMIT_CORE, size, 1);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
+ goto end_coredump;
+@@ -1986,7 +2296,7 @@ static int elf_core_dump(struct coredump
+ phdr.p_offset = offset;
+ phdr.p_vaddr = vma->vm_start;
+ phdr.p_paddr = 0;
+- phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags);
++ phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags, cprm->signr);
+ phdr.p_memsz = vma->vm_end - vma->vm_start;
+ offset += phdr.p_filesz;
+ phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
+@@ -1997,6 +2307,7 @@ static int elf_core_dump(struct coredump
+ phdr.p_align = ELF_EXEC_PAGESIZE;
+
+ size += sizeof(phdr);
++ gr_learn_resource(current, RLIMIT_CORE, size, 1);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, &phdr, sizeof(phdr)))
+ goto end_coredump;
+@@ -2021,7 +2332,7 @@ static int elf_core_dump(struct coredump
+ unsigned long addr;
+ unsigned long end;
+
+- end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags);
++ end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags, cprm->signr);
+
+ for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
+ struct page *page;
+@@ -2030,6 +2341,7 @@ static int elf_core_dump(struct coredump
+ page = get_dump_page(addr);
+ if (page) {
+ void *kaddr = kmap(page);
++ gr_learn_resource(current, RLIMIT_CORE, size + PAGE_SIZE, 1);
+ stop = ((size += PAGE_SIZE) > cprm->limit) ||
+ !dump_write(cprm->file, kaddr,
+ PAGE_SIZE);
+@@ -2047,6 +2359,7 @@ static int elf_core_dump(struct coredump
+
+ if (e_phnum == PN_XNUM) {
+ size += sizeof(*shdr4extnum);
++ gr_learn_resource(current, RLIMIT_CORE, size, 1);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, shdr4extnum,
+ sizeof(*shdr4extnum)))
+@@ -2067,6 +2380,97 @@ out:
+
+ #endif /* CONFIG_ELF_CORE */
+
++#ifdef CONFIG_PAX_MPROTECT
++/* PaX: non-PIC ELF libraries need relocations on their executable segments
++ * therefore we'll grant them VM_MAYWRITE once during their life. Similarly
++ * we'll remove VM_MAYWRITE for good on RELRO segments.
++ *
++ * The checks favour ld-linux.so behaviour which operates on a per ELF segment
++ * basis because we want to allow the common case and not the special ones.
++ */
++static void elf_handle_mprotect(struct vm_area_struct *vma, unsigned long newflags)
++{
++ struct elfhdr elf_h;
++ struct elf_phdr elf_p;
++ unsigned long i;
++ unsigned long oldflags;
++ bool is_textrel_rw, is_textrel_rx, is_relro;
++
++ if (!(vma->vm_mm->pax_flags & MF_PAX_MPROTECT))
++ return;
++
++ oldflags = vma->vm_flags & (VM_MAYEXEC | VM_MAYWRITE | VM_MAYREAD | VM_EXEC | VM_WRITE | VM_READ);
++ newflags &= VM_MAYEXEC | VM_MAYWRITE | VM_MAYREAD | VM_EXEC | VM_WRITE | VM_READ;
++
++#ifdef CONFIG_PAX_ELFRELOCS
++ /* possible TEXTREL */
++ is_textrel_rw = vma->vm_file && !vma->anon_vma && oldflags == (VM_MAYEXEC | VM_MAYREAD | VM_EXEC | VM_READ) && newflags == (VM_WRITE | VM_READ);
++ is_textrel_rx = vma->vm_file && vma->anon_vma && oldflags == (VM_MAYEXEC | VM_MAYWRITE | VM_MAYREAD | VM_WRITE | VM_READ) && newflags == (VM_EXEC | VM_READ);
++#else
++ is_textrel_rw = false;
++ is_textrel_rx = false;
++#endif
++
++ /* possible RELRO */
++ is_relro = vma->vm_file && vma->anon_vma && oldflags == (VM_MAYWRITE | VM_MAYREAD | VM_READ) && newflags == (VM_MAYWRITE | VM_MAYREAD | VM_READ);
++
++ if (!is_textrel_rw && !is_textrel_rx && !is_relro)
++ return;
++
++ if (sizeof(elf_h) != kernel_read(vma->vm_file, 0UL, (char *)&elf_h, sizeof(elf_h)) ||
++ memcmp(elf_h.e_ident, ELFMAG, SELFMAG) ||
++
++#ifdef CONFIG_PAX_ETEXECRELOCS
++ ((is_textrel_rw || is_textrel_rx) && (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC)) ||
++#else
++ ((is_textrel_rw || is_textrel_rx) && elf_h.e_type != ET_DYN) ||
++#endif
++
++ (is_relro && (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC)) ||
++ !elf_check_arch(&elf_h) ||
++ elf_h.e_phentsize != sizeof(struct elf_phdr) ||
++ elf_h.e_phnum > 65536UL / sizeof(struct elf_phdr))
++ return;
++
++ for (i = 0UL; i < elf_h.e_phnum; i++) {
++ if (sizeof(elf_p) != kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char *)&elf_p, sizeof(elf_p)))
++ return;
++ switch (elf_p.p_type) {
++ case PT_DYNAMIC:
++ if (!is_textrel_rw && !is_textrel_rx)
++ continue;
++ i = 0UL;
++ while ((i+1) * sizeof(elf_dyn) <= elf_p.p_filesz) {
++ elf_dyn dyn;
++
++ if (sizeof(dyn) != kernel_read(vma->vm_file, elf_p.p_offset + i*sizeof(dyn), (char *)&dyn, sizeof(dyn)))
++ return;
++ if (dyn.d_tag == DT_NULL)
++ return;
++ if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) {
++ gr_log_textrel(vma);
++ if (is_textrel_rw)
++ vma->vm_flags |= VM_MAYWRITE;
++ else
++ /* PaX: disallow write access after relocs are done, hopefully noone else needs it... */
++ vma->vm_flags &= ~VM_MAYWRITE;
++ return;
++ }
++ i++;
++ }
++ return;
++
++ case PT_GNU_RELRO:
++ if (!is_relro)
++ continue;
++ if ((elf_p.p_offset >> PAGE_SHIFT) == vma->vm_pgoff && ELF_PAGEALIGN(elf_p.p_memsz) == vma->vm_end - vma->vm_start)
++ vma->vm_flags &= ~VM_MAYWRITE;
++ return;
++ }
++ }
++}
++#endif
++
+ static int __init init_elf_binfmt(void)
+ {
+ return register_binfmt(&elf_format);
+diff -urNp linux-2.6.38.7/fs/binfmt_flat.c linux-2.6.38.7/fs/binfmt_flat.c
+--- linux-2.6.38.7/fs/binfmt_flat.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/binfmt_flat.c 2011-04-28 19:34:15.000000000 -0400
+@@ -567,7 +567,9 @@ static int load_flat_file(struct linux_b
+ realdatastart = (unsigned long) -ENOMEM;
+ printk("Unable to allocate RAM for process data, errno %d\n",
+ (int)-realdatastart);
++ down_write(&current->mm->mmap_sem);
+ do_munmap(current->mm, textpos, text_len);
++ up_write(&current->mm->mmap_sem);
+ ret = realdatastart;
+ goto err;
+ }
+@@ -591,8 +593,10 @@ static int load_flat_file(struct linux_b
+ }
+ if (IS_ERR_VALUE(result)) {
+ printk("Unable to read data+bss, errno %d\n", (int)-result);
++ down_write(&current->mm->mmap_sem);
+ do_munmap(current->mm, textpos, text_len);
+ do_munmap(current->mm, realdatastart, len);
++ up_write(&current->mm->mmap_sem);
+ ret = result;
+ goto err;
+ }
+@@ -661,8 +665,10 @@ static int load_flat_file(struct linux_b
+ }
+ if (IS_ERR_VALUE(result)) {
+ printk("Unable to read code+data+bss, errno %d\n",(int)-result);
++ down_write(&current->mm->mmap_sem);
+ do_munmap(current->mm, textpos, text_len + data_len + extra +
+ MAX_SHARED_LIBS * sizeof(unsigned long));
++ up_write(&current->mm->mmap_sem);
+ ret = result;
+ goto err;
+ }
+diff -urNp linux-2.6.38.7/fs/bio.c linux-2.6.38.7/fs/bio.c
+--- linux-2.6.38.7/fs/bio.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/bio.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1233,7 +1233,7 @@ static void bio_copy_kern_endio(struct b
+ const int read = bio_data_dir(bio) == READ;
+ struct bio_map_data *bmd = bio->bi_private;
+ int i;
+- char *p = bmd->sgvecs[0].iov_base;
++ char *p = (__force char *)bmd->sgvecs[0].iov_base;
+
+ __bio_for_each_segment(bvec, bio, i, 0) {
+ char *addr = page_address(bvec->bv_page);
+diff -urNp linux-2.6.38.7/fs/block_dev.c linux-2.6.38.7/fs/block_dev.c
+--- linux-2.6.38.7/fs/block_dev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/block_dev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -669,7 +669,7 @@ static bool bd_may_claim(struct block_de
+ else if (bdev->bd_contains == bdev)
+ return true; /* is a whole device which isn't held */
+
+- else if (whole->bd_holder == bd_may_claim)
++ else if (whole->bd_holder == (void *)bd_may_claim)
+ return true; /* is a partition of a device that is being partitioned */
+ else if (whole->bd_holder != NULL)
+ return false; /* is a partition of a held device */
+diff -urNp linux-2.6.38.7/fs/btrfs/ctree.c linux-2.6.38.7/fs/btrfs/ctree.c
+--- linux-2.6.38.7/fs/btrfs/ctree.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/btrfs/ctree.c 2011-04-28 19:34:15.000000000 -0400
+@@ -468,9 +468,12 @@ static noinline int __btrfs_cow_block(st
+ free_extent_buffer(buf);
+ add_root_to_dirty_list(root);
+ } else {
+- if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)
+- parent_start = parent->start;
+- else
++ if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
++ if (parent)
++ parent_start = parent->start;
++ else
++ parent_start = 0;
++ } else
+ parent_start = 0;
+
+ WARN_ON(trans->transid != btrfs_header_generation(parent));
+@@ -3776,7 +3779,6 @@ setup_items_for_insert(struct btrfs_tran
+
+ ret = 0;
+ if (slot == 0) {
+- struct btrfs_disk_key disk_key;
+ btrfs_cpu_key_to_disk(&disk_key, cpu_key);
+ ret = fixup_low_keys(trans, root, path, &disk_key, 1);
+ }
+diff -urNp linux-2.6.38.7/fs/btrfs/disk-io.c linux-2.6.38.7/fs/btrfs/disk-io.c
+--- linux-2.6.38.7/fs/btrfs/disk-io.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/fs/btrfs/disk-io.c 2011-04-28 19:34:15.000000000 -0400
+@@ -41,7 +41,7 @@
+ #include "tree-log.h"
+ #include "free-space-cache.h"
+
+-static struct extent_io_ops btree_extent_io_ops;
++static const struct extent_io_ops btree_extent_io_ops;
+ static void end_workqueue_fn(struct btrfs_work *work);
+ static void free_fs_root(struct btrfs_root *root);
+ static void btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
+@@ -3030,7 +3030,7 @@ static int btrfs_cleanup_transaction(str
+ return 0;
+ }
+
+-static struct extent_io_ops btree_extent_io_ops = {
++static const struct extent_io_ops btree_extent_io_ops = {
+ .write_cache_pages_lock_hook = btree_lock_page_hook,
+ .readpage_end_io_hook = btree_readpage_end_io_hook,
+ .submit_bio_hook = btree_submit_bio_hook,
+diff -urNp linux-2.6.38.7/fs/btrfs/extent_io.h linux-2.6.38.7/fs/btrfs/extent_io.h
+--- linux-2.6.38.7/fs/btrfs/extent_io.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/btrfs/extent_io.h 2011-04-28 19:34:15.000000000 -0400
+@@ -55,36 +55,36 @@ typedef int (extent_submit_bio_hook_t)(s
+ struct bio *bio, int mirror_num,
+ unsigned long bio_flags, u64 bio_offset);
+ struct extent_io_ops {
+- int (*fill_delalloc)(struct inode *inode, struct page *locked_page,
++ int (* const fill_delalloc)(struct inode *inode, struct page *locked_page,
+ u64 start, u64 end, int *page_started,
+ unsigned long *nr_written);
+- int (*writepage_start_hook)(struct page *page, u64 start, u64 end);
+- int (*writepage_io_hook)(struct page *page, u64 start, u64 end);
++ int (* const writepage_start_hook)(struct page *page, u64 start, u64 end);
++ int (* const writepage_io_hook)(struct page *page, u64 start, u64 end);
+ extent_submit_bio_hook_t *submit_bio_hook;
+- int (*merge_bio_hook)(struct page *page, unsigned long offset,
++ int (* const merge_bio_hook)(struct page *page, unsigned long offset,
+ size_t size, struct bio *bio,
+ unsigned long bio_flags);
+- int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
+- int (*readpage_io_failed_hook)(struct bio *bio, struct page *page,
++ int (* const readpage_io_hook)(struct page *page, u64 start, u64 end);
++ int (* const readpage_io_failed_hook)(struct bio *bio, struct page *page,
+ u64 start, u64 end,
+ struct extent_state *state);
+- int (*writepage_io_failed_hook)(struct bio *bio, struct page *page,
++ int (* const writepage_io_failed_hook)(struct bio *bio, struct page *page,
+ u64 start, u64 end,
+ struct extent_state *state);
+- int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end,
++ int (* const readpage_end_io_hook)(struct page *page, u64 start, u64 end,
+ struct extent_state *state);
+- int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end,
++ int (* const writepage_end_io_hook)(struct page *page, u64 start, u64 end,
+ struct extent_state *state, int uptodate);
+- int (*set_bit_hook)(struct inode *inode, struct extent_state *state,
++ int (* const set_bit_hook)(struct inode *inode, struct extent_state *state,
+ int *bits);
+- int (*clear_bit_hook)(struct inode *inode, struct extent_state *state,
++ int (* const clear_bit_hook)(struct inode *inode, struct extent_state *state,
+ int *bits);
+- int (*merge_extent_hook)(struct inode *inode,
++ int (* const merge_extent_hook)(struct inode *inode,
+ struct extent_state *new,
+ struct extent_state *other);
+- int (*split_extent_hook)(struct inode *inode,
++ int (* const split_extent_hook)(struct inode *inode,
+ struct extent_state *orig, u64 split);
+- int (*write_cache_pages_lock_hook)(struct page *page);
++ int (* const write_cache_pages_lock_hook)(struct page *page);
+ };
+
+ struct extent_io_tree {
+@@ -94,7 +94,7 @@ struct extent_io_tree {
+ u64 dirty_bytes;
+ spinlock_t lock;
+ spinlock_t buffer_lock;
+- struct extent_io_ops *ops;
++ const struct extent_io_ops *ops;
+ };
+
+ struct extent_state {
+diff -urNp linux-2.6.38.7/fs/btrfs/free-space-cache.c linux-2.6.38.7/fs/btrfs/free-space-cache.c
+--- linux-2.6.38.7/fs/btrfs/free-space-cache.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/btrfs/free-space-cache.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1855,8 +1855,6 @@ u64 btrfs_alloc_from_cluster(struct btrf
+
+ while(1) {
+ if (entry->bytes < bytes || entry->offset < min_start) {
+- struct rb_node *node;
+-
+ node = rb_next(&entry->offset_index);
+ if (!node)
+ break;
+@@ -2018,7 +2016,7 @@ again:
+ */
+ while (entry->bitmap || found_bitmap ||
+ (!entry->bitmap && entry->bytes < min_bytes)) {
+- struct rb_node *node = rb_next(&entry->offset_index);
++ node = rb_next(&entry->offset_index);
+
+ if (entry->bitmap && entry->bytes > bytes + empty_size) {
+ ret = btrfs_bitmap_cluster(block_group, entry, cluster,
+diff -urNp linux-2.6.38.7/fs/btrfs/inode.c linux-2.6.38.7/fs/btrfs/inode.c
+--- linux-2.6.38.7/fs/btrfs/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/btrfs/inode.c 2011-04-28 19:34:15.000000000 -0400
+@@ -64,7 +64,7 @@ static const struct inode_operations btr
+ static const struct address_space_operations btrfs_aops;
+ static const struct address_space_operations btrfs_symlink_aops;
+ static const struct file_operations btrfs_dir_file_operations;
+-static struct extent_io_ops btrfs_extent_io_ops;
++static const struct extent_io_ops btrfs_extent_io_ops;
+
+ static struct kmem_cache *btrfs_inode_cachep;
+ struct kmem_cache *btrfs_trans_handle_cachep;
+@@ -6796,7 +6796,7 @@ fail:
+ return -ENOMEM;
+ }
+
+-static int btrfs_getattr(struct vfsmount *mnt,
++int btrfs_getattr(struct vfsmount *mnt,
+ struct dentry *dentry, struct kstat *stat)
+ {
+ struct inode *inode = dentry->d_inode;
+@@ -6808,6 +6808,14 @@ static int btrfs_getattr(struct vfsmount
+ return 0;
+ }
+
++EXPORT_SYMBOL(btrfs_getattr);
++
++dev_t get_btrfs_dev_from_inode(struct inode *inode)
++{
++ return BTRFS_I(inode)->root->anon_super.s_dev;
++}
++EXPORT_SYMBOL(get_btrfs_dev_from_inode);
++
+ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+ {
+@@ -7311,7 +7319,7 @@ static const struct file_operations btrf
+ .fsync = btrfs_sync_file,
+ };
+
+-static struct extent_io_ops btrfs_extent_io_ops = {
++static const struct extent_io_ops btrfs_extent_io_ops = {
+ .fill_delalloc = run_delalloc_range,
+ .submit_bio_hook = btrfs_submit_bio_hook,
+ .merge_bio_hook = btrfs_merge_bio_hook,
+diff -urNp linux-2.6.38.7/fs/btrfs/ioctl.c linux-2.6.38.7/fs/btrfs/ioctl.c
+--- linux-2.6.38.7/fs/btrfs/ioctl.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/fs/btrfs/ioctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2274,9 +2274,12 @@ long btrfs_ioctl_space_info(struct btrfs
+ for (i = 0; i < num_types; i++) {
+ struct btrfs_space_info *tmp;
+
++ /* Don't copy in more than we allocated */
+ if (!slot_count)
+ break;
+
++ slot_count--;
++
+ info = NULL;
+ rcu_read_lock();
+ list_for_each_entry_rcu(tmp, &root->fs_info->space_info,
+@@ -2298,10 +2301,7 @@ long btrfs_ioctl_space_info(struct btrfs
+ memcpy(dest, &space, sizeof(space));
+ dest++;
+ space_args.total_spaces++;
+- slot_count--;
+ }
+- if (!slot_count)
+- break;
+ }
+ up_read(&info->groups_sem);
+ }
+diff -urNp linux-2.6.38.7/fs/btrfs/relocation.c linux-2.6.38.7/fs/btrfs/relocation.c
+--- linux-2.6.38.7/fs/btrfs/relocation.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/btrfs/relocation.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1239,7 +1239,7 @@ static int __update_reloc_root(struct bt
+ }
+ spin_unlock(&rc->reloc_root_tree.lock);
+
+- BUG_ON((struct btrfs_root *)node->data != root);
++ BUG_ON(!node || (struct btrfs_root *)node->data != root);
+
+ if (!del) {
+ spin_lock(&rc->reloc_root_tree.lock);
+diff -urNp linux-2.6.38.7/fs/cachefiles/bind.c linux-2.6.38.7/fs/cachefiles/bind.c
+--- linux-2.6.38.7/fs/cachefiles/bind.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cachefiles/bind.c 2011-04-28 19:34:15.000000000 -0400
+@@ -39,13 +39,11 @@ int cachefiles_daemon_bind(struct cachef
+ args);
+
+ /* start by checking things over */
+- ASSERT(cache->fstop_percent >= 0 &&
+- cache->fstop_percent < cache->fcull_percent &&
++ ASSERT(cache->fstop_percent < cache->fcull_percent &&
+ cache->fcull_percent < cache->frun_percent &&
+ cache->frun_percent < 100);
+
+- ASSERT(cache->bstop_percent >= 0 &&
+- cache->bstop_percent < cache->bcull_percent &&
++ ASSERT(cache->bstop_percent < cache->bcull_percent &&
+ cache->bcull_percent < cache->brun_percent &&
+ cache->brun_percent < 100);
+
+diff -urNp linux-2.6.38.7/fs/cachefiles/daemon.c linux-2.6.38.7/fs/cachefiles/daemon.c
+--- linux-2.6.38.7/fs/cachefiles/daemon.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cachefiles/daemon.c 2011-04-28 19:34:15.000000000 -0400
+@@ -196,7 +196,7 @@ static ssize_t cachefiles_daemon_read(st
+ if (n > buflen)
+ return -EMSGSIZE;
+
+- if (copy_to_user(_buffer, buffer, n) != 0)
++ if (n > sizeof(buffer) || copy_to_user(_buffer, buffer, n) != 0)
+ return -EFAULT;
+
+ return n;
+@@ -222,7 +222,7 @@ static ssize_t cachefiles_daemon_write(s
+ if (test_bit(CACHEFILES_DEAD, &cache->flags))
+ return -EIO;
+
+- if (datalen < 0 || datalen > PAGE_SIZE - 1)
++ if (datalen > PAGE_SIZE - 1)
+ return -EOPNOTSUPP;
+
+ /* drag the command string into the kernel so we can parse it */
+@@ -386,7 +386,7 @@ static int cachefiles_daemon_fstop(struc
+ if (args[0] != '%' || args[1] != '\0')
+ return -EINVAL;
+
+- if (fstop < 0 || fstop >= cache->fcull_percent)
++ if (fstop >= cache->fcull_percent)
+ return cachefiles_daemon_range_error(cache, args);
+
+ cache->fstop_percent = fstop;
+@@ -458,7 +458,7 @@ static int cachefiles_daemon_bstop(struc
+ if (args[0] != '%' || args[1] != '\0')
+ return -EINVAL;
+
+- if (bstop < 0 || bstop >= cache->bcull_percent)
++ if (bstop >= cache->bcull_percent)
+ return cachefiles_daemon_range_error(cache, args);
+
+ cache->bstop_percent = bstop;
+diff -urNp linux-2.6.38.7/fs/cachefiles/internal.h linux-2.6.38.7/fs/cachefiles/internal.h
+--- linux-2.6.38.7/fs/cachefiles/internal.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cachefiles/internal.h 2011-04-28 19:57:25.000000000 -0400
+@@ -57,7 +57,7 @@ struct cachefiles_cache {
+ wait_queue_head_t daemon_pollwq; /* poll waitqueue for daemon */
+ struct rb_root active_nodes; /* active nodes (can't be culled) */
+ rwlock_t active_lock; /* lock for active_nodes */
+- atomic_t gravecounter; /* graveyard uniquifier */
++ atomic_unchecked_t gravecounter; /* graveyard uniquifier */
+ unsigned frun_percent; /* when to stop culling (% files) */
+ unsigned fcull_percent; /* when to start culling (% files) */
+ unsigned fstop_percent; /* when to stop allocating (% files) */
+@@ -169,19 +169,19 @@ extern int cachefiles_check_in_use(struc
+ * proc.c
+ */
+ #ifdef CONFIG_CACHEFILES_HISTOGRAM
+-extern atomic_t cachefiles_lookup_histogram[HZ];
+-extern atomic_t cachefiles_mkdir_histogram[HZ];
+-extern atomic_t cachefiles_create_histogram[HZ];
++extern atomic_unchecked_t cachefiles_lookup_histogram[HZ];
++extern atomic_unchecked_t cachefiles_mkdir_histogram[HZ];
++extern atomic_unchecked_t cachefiles_create_histogram[HZ];
+
+ extern int __init cachefiles_proc_init(void);
+ extern void cachefiles_proc_cleanup(void);
+ static inline
+-void cachefiles_hist(atomic_t histogram[], unsigned long start_jif)
++void cachefiles_hist(atomic_unchecked_t histogram[], unsigned long start_jif)
+ {
+ unsigned long jif = jiffies - start_jif;
+ if (jif >= HZ)
+ jif = HZ - 1;
+- atomic_inc(&histogram[jif]);
++ atomic_inc_unchecked(&histogram[jif]);
+ }
+
+ #else
+diff -urNp linux-2.6.38.7/fs/cachefiles/namei.c linux-2.6.38.7/fs/cachefiles/namei.c
+--- linux-2.6.38.7/fs/cachefiles/namei.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cachefiles/namei.c 2011-04-28 19:57:25.000000000 -0400
+@@ -309,7 +309,7 @@ try_again:
+ /* first step is to make up a grave dentry in the graveyard */
+ sprintf(nbuffer, "%08x%08x",
+ (uint32_t) get_seconds(),
+- (uint32_t) atomic_inc_return(&cache->gravecounter));
++ (uint32_t) atomic_inc_return_unchecked(&cache->gravecounter));
+
+ /* do the multiway lock magic */
+ trap = lock_rename(cache->graveyard, dir);
+diff -urNp linux-2.6.38.7/fs/cachefiles/proc.c linux-2.6.38.7/fs/cachefiles/proc.c
+--- linux-2.6.38.7/fs/cachefiles/proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cachefiles/proc.c 2011-04-28 19:57:25.000000000 -0400
+@@ -14,9 +14,9 @@
+ #include <linux/seq_file.h>
+ #include "internal.h"
+
+-atomic_t cachefiles_lookup_histogram[HZ];
+-atomic_t cachefiles_mkdir_histogram[HZ];
+-atomic_t cachefiles_create_histogram[HZ];
++atomic_unchecked_t cachefiles_lookup_histogram[HZ];
++atomic_unchecked_t cachefiles_mkdir_histogram[HZ];
++atomic_unchecked_t cachefiles_create_histogram[HZ];
+
+ /*
+ * display the latency histogram
+@@ -35,9 +35,9 @@ static int cachefiles_histogram_show(str
+ return 0;
+ default:
+ index = (unsigned long) v - 3;
+- x = atomic_read(&cachefiles_lookup_histogram[index]);
+- y = atomic_read(&cachefiles_mkdir_histogram[index]);
+- z = atomic_read(&cachefiles_create_histogram[index]);
++ x = atomic_read_unchecked(&cachefiles_lookup_histogram[index]);
++ y = atomic_read_unchecked(&cachefiles_mkdir_histogram[index]);
++ z = atomic_read_unchecked(&cachefiles_create_histogram[index]);
+ if (x == 0 && y == 0 && z == 0)
+ return 0;
+
+diff -urNp linux-2.6.38.7/fs/cachefiles/rdwr.c linux-2.6.38.7/fs/cachefiles/rdwr.c
+--- linux-2.6.38.7/fs/cachefiles/rdwr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cachefiles/rdwr.c 2011-04-28 19:34:15.000000000 -0400
+@@ -945,7 +945,7 @@ int cachefiles_write_page(struct fscache
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = file->f_op->write(
+- file, (const void __user *) data, len, &pos);
++ file, (__force const void __user *) data, len, &pos);
+ set_fs(old_fs);
+ kunmap(page);
+ if (ret != len)
+diff -urNp linux-2.6.38.7/fs/ceph/dir.c linux-2.6.38.7/fs/ceph/dir.c
+--- linux-2.6.38.7/fs/ceph/dir.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ceph/dir.c 2011-04-28 19:34:15.000000000 -0400
+@@ -226,7 +226,7 @@ static int ceph_readdir(struct file *fil
+ struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_mds_client *mdsc = fsc->mdsc;
+ unsigned frag = fpos_frag(filp->f_pos);
+- int off = fpos_off(filp->f_pos);
++ unsigned int off = fpos_off(filp->f_pos);
+ int err;
+ u32 ftype;
+ struct ceph_mds_reply_info_parsed *rinfo;
+@@ -358,7 +358,7 @@ more:
+ rinfo = &fi->last_readdir->r_reply_info;
+ dout("readdir frag %x num %d off %d chunkoff %d\n", frag,
+ rinfo->dir_nr, off, fi->offset);
+- while (off - fi->offset >= 0 && off - fi->offset < rinfo->dir_nr) {
++ while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) {
+ u64 pos = ceph_make_fpos(frag, off);
+ struct ceph_mds_reply_inode *in =
+ rinfo->dir_in[off - fi->offset].in;
+diff -urNp linux-2.6.38.7/fs/cifs/cifs_debug.c linux-2.6.38.7/fs/cifs/cifs_debug.c
+--- linux-2.6.38.7/fs/cifs/cifs_debug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cifs/cifs_debug.c 2011-04-28 19:57:25.000000000 -0400
+@@ -279,25 +279,25 @@ static ssize_t cifs_stats_proc_write(str
+ tcon = list_entry(tmp3,
+ struct cifsTconInfo,
+ tcon_list);
+- atomic_set(&tcon->num_smbs_sent, 0);
+- atomic_set(&tcon->num_writes, 0);
+- atomic_set(&tcon->num_reads, 0);
+- atomic_set(&tcon->num_oplock_brks, 0);
+- atomic_set(&tcon->num_opens, 0);
+- atomic_set(&tcon->num_posixopens, 0);
+- atomic_set(&tcon->num_posixmkdirs, 0);
+- atomic_set(&tcon->num_closes, 0);
+- atomic_set(&tcon->num_deletes, 0);
+- atomic_set(&tcon->num_mkdirs, 0);
+- atomic_set(&tcon->num_rmdirs, 0);
+- atomic_set(&tcon->num_renames, 0);
+- atomic_set(&tcon->num_t2renames, 0);
+- atomic_set(&tcon->num_ffirst, 0);
+- atomic_set(&tcon->num_fnext, 0);
+- atomic_set(&tcon->num_fclose, 0);
+- atomic_set(&tcon->num_hardlinks, 0);
+- atomic_set(&tcon->num_symlinks, 0);
+- atomic_set(&tcon->num_locks, 0);
++ atomic_set_unchecked(&tcon->num_smbs_sent, 0);
++ atomic_set_unchecked(&tcon->num_writes, 0);
++ atomic_set_unchecked(&tcon->num_reads, 0);
++ atomic_set_unchecked(&tcon->num_oplock_brks, 0);
++ atomic_set_unchecked(&tcon->num_opens, 0);
++ atomic_set_unchecked(&tcon->num_posixopens, 0);
++ atomic_set_unchecked(&tcon->num_posixmkdirs, 0);
++ atomic_set_unchecked(&tcon->num_closes, 0);
++ atomic_set_unchecked(&tcon->num_deletes, 0);
++ atomic_set_unchecked(&tcon->num_mkdirs, 0);
++ atomic_set_unchecked(&tcon->num_rmdirs, 0);
++ atomic_set_unchecked(&tcon->num_renames, 0);
++ atomic_set_unchecked(&tcon->num_t2renames, 0);
++ atomic_set_unchecked(&tcon->num_ffirst, 0);
++ atomic_set_unchecked(&tcon->num_fnext, 0);
++ atomic_set_unchecked(&tcon->num_fclose, 0);
++ atomic_set_unchecked(&tcon->num_hardlinks, 0);
++ atomic_set_unchecked(&tcon->num_symlinks, 0);
++ atomic_set_unchecked(&tcon->num_locks, 0);
+ }
+ }
+ }
+@@ -357,41 +357,41 @@ static int cifs_stats_proc_show(struct s
+ if (tcon->need_reconnect)
+ seq_puts(m, "\tDISCONNECTED ");
+ seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
+- atomic_read(&tcon->num_smbs_sent),
+- atomic_read(&tcon->num_oplock_brks));
++ atomic_read_unchecked(&tcon->num_smbs_sent),
++ atomic_read_unchecked(&tcon->num_oplock_brks));
+ seq_printf(m, "\nReads: %d Bytes: %lld",
+- atomic_read(&tcon->num_reads),
++ atomic_read_unchecked(&tcon->num_reads),
+ (long long)(tcon->bytes_read));
+ seq_printf(m, "\nWrites: %d Bytes: %lld",
+- atomic_read(&tcon->num_writes),
++ atomic_read_unchecked(&tcon->num_writes),
+ (long long)(tcon->bytes_written));
+ seq_printf(m, "\nFlushes: %d",
+- atomic_read(&tcon->num_flushes));
++ atomic_read_unchecked(&tcon->num_flushes));
+ seq_printf(m, "\nLocks: %d HardLinks: %d "
+ "Symlinks: %d",
+- atomic_read(&tcon->num_locks),
+- atomic_read(&tcon->num_hardlinks),
+- atomic_read(&tcon->num_symlinks));
++ atomic_read_unchecked(&tcon->num_locks),
++ atomic_read_unchecked(&tcon->num_hardlinks),
++ atomic_read_unchecked(&tcon->num_symlinks));
+ seq_printf(m, "\nOpens: %d Closes: %d "
+ "Deletes: %d",
+- atomic_read(&tcon->num_opens),
+- atomic_read(&tcon->num_closes),
+- atomic_read(&tcon->num_deletes));
++ atomic_read_unchecked(&tcon->num_opens),
++ atomic_read_unchecked(&tcon->num_closes),
++ atomic_read_unchecked(&tcon->num_deletes));
+ seq_printf(m, "\nPosix Opens: %d "
+ "Posix Mkdirs: %d",
+- atomic_read(&tcon->num_posixopens),
+- atomic_read(&tcon->num_posixmkdirs));
++ atomic_read_unchecked(&tcon->num_posixopens),
++ atomic_read_unchecked(&tcon->num_posixmkdirs));
+ seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
+- atomic_read(&tcon->num_mkdirs),
+- atomic_read(&tcon->num_rmdirs));
++ atomic_read_unchecked(&tcon->num_mkdirs),
++ atomic_read_unchecked(&tcon->num_rmdirs));
+ seq_printf(m, "\nRenames: %d T2 Renames %d",
+- atomic_read(&tcon->num_renames),
+- atomic_read(&tcon->num_t2renames));
++ atomic_read_unchecked(&tcon->num_renames),
++ atomic_read_unchecked(&tcon->num_t2renames));
+ seq_printf(m, "\nFindFirst: %d FNext %d "
+ "FClose %d",
+- atomic_read(&tcon->num_ffirst),
+- atomic_read(&tcon->num_fnext),
+- atomic_read(&tcon->num_fclose));
++ atomic_read_unchecked(&tcon->num_ffirst),
++ atomic_read_unchecked(&tcon->num_fnext),
++ atomic_read_unchecked(&tcon->num_fclose));
+ }
+ }
+ }
+diff -urNp linux-2.6.38.7/fs/cifs/cifsglob.h linux-2.6.38.7/fs/cifs/cifsglob.h
+--- linux-2.6.38.7/fs/cifs/cifsglob.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cifs/cifsglob.h 2011-04-28 19:57:25.000000000 -0400
+@@ -305,28 +305,28 @@ struct cifsTconInfo {
+ __u16 Flags; /* optional support bits */
+ enum statusEnum tidStatus;
+ #ifdef CONFIG_CIFS_STATS
+- atomic_t num_smbs_sent;
+- atomic_t num_writes;
+- atomic_t num_reads;
+- atomic_t num_flushes;
+- atomic_t num_oplock_brks;
+- atomic_t num_opens;
+- atomic_t num_closes;
+- atomic_t num_deletes;
+- atomic_t num_mkdirs;
+- atomic_t num_posixopens;
+- atomic_t num_posixmkdirs;
+- atomic_t num_rmdirs;
+- atomic_t num_renames;
+- atomic_t num_t2renames;
+- atomic_t num_ffirst;
+- atomic_t num_fnext;
+- atomic_t num_fclose;
+- atomic_t num_hardlinks;
+- atomic_t num_symlinks;
+- atomic_t num_locks;
+- atomic_t num_acl_get;
+- atomic_t num_acl_set;
++ atomic_unchecked_t num_smbs_sent;
++ atomic_unchecked_t num_writes;
++ atomic_unchecked_t num_reads;
++ atomic_unchecked_t num_flushes;
++ atomic_unchecked_t num_oplock_brks;
++ atomic_unchecked_t num_opens;
++ atomic_unchecked_t num_closes;
++ atomic_unchecked_t num_deletes;
++ atomic_unchecked_t num_mkdirs;
++ atomic_unchecked_t num_posixopens;
++ atomic_unchecked_t num_posixmkdirs;
++ atomic_unchecked_t num_rmdirs;
++ atomic_unchecked_t num_renames;
++ atomic_unchecked_t num_t2renames;
++ atomic_unchecked_t num_ffirst;
++ atomic_unchecked_t num_fnext;
++ atomic_unchecked_t num_fclose;
++ atomic_unchecked_t num_hardlinks;
++ atomic_unchecked_t num_symlinks;
++ atomic_unchecked_t num_locks;
++ atomic_unchecked_t num_acl_get;
++ atomic_unchecked_t num_acl_set;
+ #ifdef CONFIG_CIFS_STATS2
+ unsigned long long time_writes;
+ unsigned long long time_reads;
+@@ -509,7 +509,7 @@ static inline char CIFS_DIR_SEP(const st
+ }
+
+ #ifdef CONFIG_CIFS_STATS
+-#define cifs_stats_inc atomic_inc
++#define cifs_stats_inc atomic_inc_unchecked
+
+ static inline void cifs_stats_bytes_written(struct cifsTconInfo *tcon,
+ unsigned int bytes)
+diff -urNp linux-2.6.38.7/fs/cifs/link.c linux-2.6.38.7/fs/cifs/link.c
+--- linux-2.6.38.7/fs/cifs/link.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/cifs/link.c 2011-04-28 19:34:15.000000000 -0400
+@@ -577,7 +577,7 @@ symlink_exit:
+
+ void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
+ {
+- char *p = nd_get_link(nd);
++ const char *p = nd_get_link(nd);
+ if (!IS_ERR(p))
+ kfree(p);
+ }
+diff -urNp linux-2.6.38.7/fs/coda/cache.c linux-2.6.38.7/fs/coda/cache.c
+--- linux-2.6.38.7/fs/coda/cache.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/coda/cache.c 2011-04-28 19:57:25.000000000 -0400
+@@ -24,7 +24,7 @@
+ #include "coda_linux.h"
+ #include "coda_cache.h"
+
+-static atomic_t permission_epoch = ATOMIC_INIT(0);
++static atomic_unchecked_t permission_epoch = ATOMIC_INIT(0);
+
+ /* replace or extend an acl cache hit */
+ void coda_cache_enter(struct inode *inode, int mask)
+@@ -32,7 +32,7 @@ void coda_cache_enter(struct inode *inod
+ struct coda_inode_info *cii = ITOC(inode);
+
+ spin_lock(&cii->c_lock);
+- cii->c_cached_epoch = atomic_read(&permission_epoch);
++ cii->c_cached_epoch = atomic_read_unchecked(&permission_epoch);
+ if (cii->c_uid != current_fsuid()) {
+ cii->c_uid = current_fsuid();
+ cii->c_cached_perm = mask;
+@@ -46,14 +46,14 @@ void coda_cache_clear_inode(struct inode
+ {
+ struct coda_inode_info *cii = ITOC(inode);
+ spin_lock(&cii->c_lock);
+- cii->c_cached_epoch = atomic_read(&permission_epoch) - 1;
++ cii->c_cached_epoch = atomic_read_unchecked(&permission_epoch) - 1;
+ spin_unlock(&cii->c_lock);
+ }
+
+ /* remove all acl caches */
+ void coda_cache_clear_all(struct super_block *sb)
+ {
+- atomic_inc(&permission_epoch);
++ atomic_inc_unchecked(&permission_epoch);
+ }
+
+
+@@ -66,7 +66,7 @@ int coda_cache_check(struct inode *inode
+ spin_lock(&cii->c_lock);
+ hit = (mask & cii->c_cached_perm) == mask &&
+ cii->c_uid == current_fsuid() &&
+- cii->c_cached_epoch == atomic_read(&permission_epoch);
++ cii->c_cached_epoch == atomic_read_unchecked(&permission_epoch);
+ spin_unlock(&cii->c_lock);
+
+ return hit;
+diff -urNp linux-2.6.38.7/fs/compat_binfmt_elf.c linux-2.6.38.7/fs/compat_binfmt_elf.c
+--- linux-2.6.38.7/fs/compat_binfmt_elf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/compat_binfmt_elf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -30,11 +30,13 @@
+ #undef elf_phdr
+ #undef elf_shdr
+ #undef elf_note
++#undef elf_dyn
+ #undef elf_addr_t
+ #define elfhdr elf32_hdr
+ #define elf_phdr elf32_phdr
+ #define elf_shdr elf32_shdr
+ #define elf_note elf32_note
++#define elf_dyn Elf32_Dyn
+ #define elf_addr_t Elf32_Addr
+
+ /*
+diff -urNp linux-2.6.38.7/fs/compat.c linux-2.6.38.7/fs/compat.c
+--- linux-2.6.38.7/fs/compat.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/compat.c 2011-05-16 21:47:08.000000000 -0400
+@@ -594,7 +594,7 @@ ssize_t compat_rw_copy_check_uvector(int
+ goto out;
+
+ ret = -EINVAL;
+- if (nr_segs > UIO_MAXIOV || nr_segs < 0)
++ if (nr_segs > UIO_MAXIOV)
+ goto out;
+ if (nr_segs > fast_segs) {
+ ret = -ENOMEM;
+@@ -876,6 +876,7 @@ struct compat_old_linux_dirent {
+
+ struct compat_readdir_callback {
+ struct compat_old_linux_dirent __user *dirent;
++ struct file * file;
+ int result;
+ };
+
+@@ -893,6 +894,10 @@ static int compat_fillonedir(void *__buf
+ buf->result = -EOVERFLOW;
+ return -EOVERFLOW;
+ }
++
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
++ return 0;
++
+ buf->result++;
+ dirent = buf->dirent;
+ if (!access_ok(VERIFY_WRITE, dirent,
+@@ -925,6 +930,7 @@ asmlinkage long compat_sys_old_readdir(u
+
+ buf.result = 0;
+ buf.dirent = dirent;
++ buf.file = file;
+
+ error = vfs_readdir(file, compat_fillonedir, &buf);
+ if (buf.result)
+@@ -945,6 +951,7 @@ struct compat_linux_dirent {
+ struct compat_getdents_callback {
+ struct compat_linux_dirent __user *current_dir;
+ struct compat_linux_dirent __user *previous;
++ struct file * file;
+ int count;
+ int error;
+ };
+@@ -966,6 +973,10 @@ static int compat_filldir(void *__buf, c
+ buf->error = -EOVERFLOW;
+ return -EOVERFLOW;
+ }
++
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
++ return 0;
++
+ dirent = buf->previous;
+ if (dirent) {
+ if (__put_user(offset, &dirent->d_off))
+@@ -1013,6 +1024,7 @@ asmlinkage long compat_sys_getdents(unsi
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
++ buf.file = file;
+
+ error = vfs_readdir(file, compat_filldir, &buf);
+ if (error >= 0)
+@@ -1034,6 +1046,7 @@ out:
+ struct compat_getdents_callback64 {
+ struct linux_dirent64 __user *current_dir;
+ struct linux_dirent64 __user *previous;
++ struct file * file;
+ int count;
+ int error;
+ };
+@@ -1050,6 +1063,10 @@ static int compat_filldir64(void * __buf
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
++
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
++ return 0;
++
+ dirent = buf->previous;
+
+ if (dirent) {
+@@ -1101,6 +1118,7 @@ asmlinkage long compat_sys_getdents64(un
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
++ buf.file = file;
+
+ error = vfs_readdir(file, compat_filldir64, &buf);
+ if (error >= 0)
+@@ -1464,6 +1482,11 @@ int compat_do_execve(char * filename,
+ compat_uptr_t __user *envp,
+ struct pt_regs * regs)
+ {
++#ifdef CONFIG_GRKERNSEC
++ struct file *old_exec_file;
++ struct acl_subject_label *old_acl;
++ struct rlimit old_rlim[RLIM_NLIMITS];
++#endif
+ struct linux_binprm *bprm;
+ struct file *file;
+ struct files_struct *displaced;
+@@ -1500,6 +1523,19 @@ int compat_do_execve(char * filename,
+ bprm->filename = filename;
+ bprm->interp = filename;
+
++ if (gr_process_user_ban()) {
++ retval = -EPERM;
++ goto out_file;
++ }
++
++ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->cred->user->processes), 1);
++ retval = -EAGAIN;
++ if (gr_handle_nproc())
++ goto out_file;
++ retval = -EACCES;
++ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt))
++ goto out_file;
++
+ retval = bprm_mm_init(bprm);
+ if (retval)
+ goto out_file;
+@@ -1529,9 +1565,40 @@ int compat_do_execve(char * filename,
+ if (retval < 0)
+ goto out;
+
++ if (!gr_tpe_allow(file)) {
++ retval = -EACCES;
++ goto out;
++ }
++
++ if (gr_check_crash_exec(file)) {
++ retval = -EACCES;
++ goto out;
++ }
++
++ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
++
++ gr_handle_exec_args_compat(bprm, argv);
++
++#ifdef CONFIG_GRKERNSEC
++ old_acl = current->acl;
++ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
++ old_exec_file = current->exec_file;
++ get_file(file);
++ current->exec_file = file;
++#endif
++
++ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt,
++ bprm->unsafe & LSM_UNSAFE_SHARE);
++ if (retval < 0)
++ goto out_fail;
++
+ retval = search_binary_handler(bprm, regs);
+ if (retval < 0)
+- goto out;
++ goto out_fail;
++#ifdef CONFIG_GRKERNSEC
++ if (old_exec_file)
++ fput(old_exec_file);
++#endif
+
+ /* execve succeeded */
+ current->fs->in_exec = 0;
+@@ -1542,6 +1609,14 @@ int compat_do_execve(char * filename,
+ put_files_struct(displaced);
+ return retval;
+
++out_fail:
++#ifdef CONFIG_GRKERNSEC
++ current->acl = old_acl;
++ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
++ fput(current->exec_file);
++ current->exec_file = old_exec_file;
++#endif
++
+ out:
+ if (bprm->mm) {
+ acct_arg_size(bprm, 0);
+@@ -1712,6 +1787,8 @@ int compat_core_sys_select(int n, compat
+ struct fdtable *fdt;
+ long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
+
++ pax_track_stack();
++
+ if (n < 0)
+ goto out_nofds;
+
+diff -urNp linux-2.6.38.7/fs/compat_ioctl.c linux-2.6.38.7/fs/compat_ioctl.c
+--- linux-2.6.38.7/fs/compat_ioctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/compat_ioctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -208,6 +208,8 @@ static int do_video_set_spu_palette(unsi
+
+ err = get_user(palp, &up->palette);
+ err |= get_user(length, &up->length);
++ if (err)
++ return -EFAULT;
+
+ up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));
+ err = put_user(compat_ptr(palp), &up_native->palette);
+@@ -1638,8 +1640,8 @@ asmlinkage long compat_sys_ioctl(unsigne
+ static int __init init_sys32_ioctl_cmp(const void *p, const void *q)
+ {
+ unsigned int a, b;
+- a = *(unsigned int *)p;
+- b = *(unsigned int *)q;
++ a = *(const unsigned int *)p;
++ b = *(const unsigned int *)q;
+ if (a > b)
+ return 1;
+ if (a < b)
+diff -urNp linux-2.6.38.7/fs/configfs/dir.c linux-2.6.38.7/fs/configfs/dir.c
+--- linux-2.6.38.7/fs/configfs/dir.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/configfs/dir.c 2011-05-11 18:34:57.000000000 -0400
+@@ -1571,7 +1571,8 @@ static int configfs_readdir(struct file
+ }
+ for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
+ struct configfs_dirent *next;
+- const char * name;
++ const unsigned char * name;
++ char d_name[sizeof(next->s_dentry->d_iname)];
+ int len;
+
+ next = list_entry(p, struct configfs_dirent,
+@@ -1580,7 +1581,12 @@ static int configfs_readdir(struct file
+ continue;
+
+ name = configfs_get_name(next);
+- len = strlen(name);
++ if (next->s_dentry && name == next->s_dentry->d_iname) {
++ len = next->s_dentry->d_name.len;
++ memcpy(d_name, name, len);
++ name = d_name;
++ } else
++ len = strlen(name);
+ if (next->s_dentry)
+ ino = next->s_dentry->d_inode->i_ino;
+ else
+diff -urNp linux-2.6.38.7/fs/dcache.c linux-2.6.38.7/fs/dcache.c
+--- linux-2.6.38.7/fs/dcache.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/fs/dcache.c 2011-04-28 19:34:15.000000000 -0400
+@@ -3092,7 +3092,7 @@ void __init vfs_caches_init(unsigned lon
+ mempages -= reserve;
+
+ names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
+- SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
++ SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_USERCOPY, NULL);
+
+ dcache_init();
+ inode_init();
+diff -urNp linux-2.6.38.7/fs/dlm/lockspace.c linux-2.6.38.7/fs/dlm/lockspace.c
+--- linux-2.6.38.7/fs/dlm/lockspace.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/dlm/lockspace.c 2011-04-28 19:34:15.000000000 -0400
+@@ -200,7 +200,7 @@ static int dlm_uevent(struct kset *kset,
+ return 0;
+ }
+
+-static struct kset_uevent_ops dlm_uevent_ops = {
++static const struct kset_uevent_ops dlm_uevent_ops = {
+ .uevent = dlm_uevent,
+ };
+
+diff -urNp linux-2.6.38.7/fs/ecryptfs/inode.c linux-2.6.38.7/fs/ecryptfs/inode.c
+--- linux-2.6.38.7/fs/ecryptfs/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ecryptfs/inode.c 2011-04-28 19:34:15.000000000 -0400
+@@ -658,7 +658,7 @@ static int ecryptfs_readlink_lower(struc
+ old_fs = get_fs();
+ set_fs(get_ds());
+ rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
+- (char __user *)lower_buf,
++ (__force char __user *)lower_buf,
+ lower_bufsiz);
+ set_fs(old_fs);
+ if (rc < 0)
+@@ -704,7 +704,7 @@ static void *ecryptfs_follow_link(struct
+ }
+ old_fs = get_fs();
+ set_fs(get_ds());
+- rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
++ rc = dentry->d_inode->i_op->readlink(dentry, (__force char __user *)buf, len);
+ set_fs(old_fs);
+ if (rc < 0) {
+ kfree(buf);
+@@ -719,7 +719,7 @@ out:
+ static void
+ ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr)
+ {
+- char *buf = nd_get_link(nd);
++ const char *buf = nd_get_link(nd);
+ if (!IS_ERR(buf)) {
+ /* Free the char* */
+ kfree(buf);
+diff -urNp linux-2.6.38.7/fs/ecryptfs/miscdev.c linux-2.6.38.7/fs/ecryptfs/miscdev.c
+--- linux-2.6.38.7/fs/ecryptfs/miscdev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ecryptfs/miscdev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -328,7 +328,7 @@ check_list:
+ goto out_unlock_msg_ctx;
+ i = 5;
+ if (msg_ctx->msg) {
+- if (copy_to_user(&buf[i], packet_length, packet_length_size))
++ if (packet_length_size > sizeof(packet_length) || copy_to_user(&buf[i], packet_length, packet_length_size))
+ goto out_unlock_msg_ctx;
+ i += packet_length_size;
+ if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size))
+diff -urNp linux-2.6.38.7/fs/exec.c linux-2.6.38.7/fs/exec.c
+--- linux-2.6.38.7/fs/exec.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/exec.c 2011-04-28 19:57:25.000000000 -0400
+@@ -55,12 +55,24 @@
+ #include <linux/fs_struct.h>
+ #include <linux/pipe_fs_i.h>
+ #include <linux/oom.h>
++#include <linux/random.h>
++#include <linux/seq_file.h>
++
++#ifdef CONFIG_PAX_REFCOUNT
++#include <linux/kallsyms.h>
++#include <linux/kdebug.h>
++#endif
+
+ #include <asm/uaccess.h>
+ #include <asm/mmu_context.h>
+ #include <asm/tlb.h>
+ #include "internal.h"
+
++#ifdef CONFIG_PAX_HOOK_ACL_FLAGS
++void (*pax_set_initial_flags_func)(struct linux_binprm *bprm);
++EXPORT_SYMBOL(pax_set_initial_flags_func);
++#endif
++
+ int core_uses_pid;
+ char core_pattern[CORENAME_MAX_SIZE] = "core";
+ unsigned int core_pipe_limit;
+@@ -70,7 +82,7 @@ struct core_name {
+ char *corename;
+ int used, size;
+ };
+-static atomic_t call_count = ATOMIC_INIT(1);
++static atomic_unchecked_t call_count = ATOMIC_INIT(1);
+
+ /* The maximal length of core_pattern is also specified in sysctl.c */
+
+@@ -120,7 +132,7 @@ SYSCALL_DEFINE1(uselib, const char __use
+ goto out;
+
+ file = do_filp_open(AT_FDCWD, tmp,
+- O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0,
++ O_LARGEFILE | O_RDONLY | __FMODE_EXEC | FMODE_GREXEC, 0,
+ MAY_READ | MAY_EXEC | MAY_OPEN);
+ putname(tmp);
+ error = PTR_ERR(file);
+@@ -187,18 +199,10 @@ struct page *get_arg_page(struct linux_b
+ int write)
+ {
+ struct page *page;
+- int ret;
+
+-#ifdef CONFIG_STACK_GROWSUP
+- if (write) {
+- ret = expand_stack_downwards(bprm->vma, pos);
+- if (ret < 0)
+- return NULL;
+- }
+-#endif
+- ret = get_user_pages(current, bprm->mm, pos,
+- 1, write, 1, &page, NULL);
+- if (ret <= 0)
++ if (0 > expand_stack_downwards(bprm->vma, pos))
++ return NULL;
++ if (0 >= get_user_pages(current, bprm->mm, pos, 1, write, 1, &page, NULL))
+ return NULL;
+
+ if (write) {
+@@ -273,6 +277,11 @@ static int __bprm_mm_init(struct linux_b
+ vma->vm_end = STACK_TOP_MAX;
+ vma->vm_start = vma->vm_end - PAGE_SIZE;
+ vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ vma->vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
++#endif
++
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
+
+@@ -287,6 +296,12 @@ static int __bprm_mm_init(struct linux_b
+ mm->stack_vm = mm->total_vm = 1;
+ up_write(&mm->mmap_sem);
+ bprm->p = vma->vm_end - sizeof(void *);
++
++#ifdef CONFIG_PAX_RANDUSTACK
++ if (randomize_va_space)
++ bprm->p ^= (pax_get_random_long() & ~15) & ~PAGE_MASK;
++#endif
++
+ return 0;
+ err:
+ up_write(&mm->mmap_sem);
+@@ -522,7 +537,7 @@ int copy_strings_kernel(int argc, const
+ int r;
+ mm_segment_t oldfs = get_fs();
+ set_fs(KERNEL_DS);
+- r = copy_strings(argc, (const char __user *const __user *)argv, bprm);
++ r = copy_strings(argc, (__force const char __user *const __user *)argv, bprm);
+ set_fs(oldfs);
+ return r;
+ }
+@@ -552,7 +567,8 @@ static int shift_arg_pages(struct vm_are
+ unsigned long new_end = old_end - shift;
+ struct mmu_gather *tlb;
+
+- BUG_ON(new_start > new_end);
++ if (new_start >= new_end || new_start < mmap_min_addr)
++ return -ENOMEM;
+
+ /*
+ * ensure there are no vmas between where we want to go
+@@ -561,6 +577,10 @@ static int shift_arg_pages(struct vm_are
+ if (vma != find_vma(mm, new_start))
+ return -EFAULT;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ BUG_ON(pax_find_mirror_vma(vma));
++#endif
++
+ /*
+ * cover the whole range: [new_start, old_end)
+ */
+@@ -641,10 +661,6 @@ int setup_arg_pages(struct linux_binprm
+ stack_top = arch_align_stack(stack_top);
+ stack_top = PAGE_ALIGN(stack_top);
+
+- if (unlikely(stack_top < mmap_min_addr) ||
+- unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
+- return -ENOMEM;
+-
+ stack_shift = vma->vm_end - stack_top;
+
+ bprm->p -= stack_shift;
+@@ -656,8 +672,28 @@ int setup_arg_pages(struct linux_binprm
+ bprm->exec -= stack_shift;
+
+ down_write(&mm->mmap_sem);
++
++ /* Move stack pages down in memory. */
++ if (stack_shift) {
++ ret = shift_arg_pages(vma, stack_shift);
++ if (ret)
++ goto out_unlock;
++ }
++
+ vm_flags = VM_STACK_FLAGS;
+
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
++ vm_flags &= ~VM_EXEC;
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (mm->pax_flags & MF_PAX_MPROTECT)
++ vm_flags &= ~VM_MAYEXEC;
++#endif
++
++ }
++#endif
++
+ /*
+ * Adjust stack execute permissions; explicitly enable for
+ * EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X and leave alone
+@@ -676,13 +712,6 @@ int setup_arg_pages(struct linux_binprm
+ goto out_unlock;
+ BUG_ON(prev != vma);
+
+- /* Move stack pages down in memory. */
+- if (stack_shift) {
+- ret = shift_arg_pages(vma, stack_shift);
+- if (ret)
+- goto out_unlock;
+- }
+-
+ /* mprotect_fixup is overkill to remove the temporary stack flags */
+ vma->vm_flags &= ~VM_STACK_INCOMPLETE_SETUP;
+
+@@ -723,7 +752,7 @@ struct file *open_exec(const char *name)
+ int err;
+
+ file = do_filp_open(AT_FDCWD, name,
+- O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0,
++ O_LARGEFILE | O_RDONLY | __FMODE_EXEC | FMODE_GREXEC, 0,
+ MAY_EXEC | MAY_OPEN);
+ if (IS_ERR(file))
+ goto out;
+@@ -760,7 +789,7 @@ int kernel_read(struct file *file, loff_
+ old_fs = get_fs();
+ set_fs(get_ds());
+ /* The cast to a user pointer is valid due to the set_fs() */
+- result = vfs_read(file, (void __user *)addr, count, &pos);
++ result = vfs_read(file, (__force void __user *)addr, count, &pos);
+ set_fs(old_fs);
+ return result;
+ }
+@@ -1182,7 +1211,7 @@ int check_unsafe_exec(struct linux_binpr
+ }
+ rcu_read_unlock();
+
+- if (p->fs->users > n_fs) {
++ if (atomic_read(&p->fs->users) > n_fs) {
+ bprm->unsafe |= LSM_UNSAFE_SHARE;
+ } else {
+ res = -EAGAIN;
+@@ -1378,6 +1407,11 @@ int do_execve(const char * filename,
+ const char __user *const __user *envp,
+ struct pt_regs * regs)
+ {
++#ifdef CONFIG_GRKERNSEC
++ struct file *old_exec_file;
++ struct acl_subject_label *old_acl;
++ struct rlimit old_rlim[RLIM_NLIMITS];
++#endif
+ struct linux_binprm *bprm;
+ struct file *file;
+ struct files_struct *displaced;
+@@ -1414,6 +1448,23 @@ int do_execve(const char * filename,
+ bprm->filename = filename;
+ bprm->interp = filename;
+
++ if (gr_process_user_ban()) {
++ retval = -EPERM;
++ goto out_file;
++ }
++
++ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->cred->user->processes), 1);
++
++ if (gr_handle_nproc()) {
++ retval = -EAGAIN;
++ goto out_file;
++ }
++
++ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) {
++ retval = -EACCES;
++ goto out_file;
++ }
++
+ retval = bprm_mm_init(bprm);
+ if (retval)
+ goto out_file;
+@@ -1443,9 +1494,40 @@ int do_execve(const char * filename,
+ if (retval < 0)
+ goto out;
+
++ if (!gr_tpe_allow(file)) {
++ retval = -EACCES;
++ goto out;
++ }
++
++ if (gr_check_crash_exec(file)) {
++ retval = -EACCES;
++ goto out;
++ }
++
++ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
++
++ gr_handle_exec_args(bprm, argv);
++
++#ifdef CONFIG_GRKERNSEC
++ old_acl = current->acl;
++ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
++ old_exec_file = current->exec_file;
++ get_file(file);
++ current->exec_file = file;
++#endif
++
++ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt,
++ bprm->unsafe & LSM_UNSAFE_SHARE);
++ if (retval < 0)
++ goto out_fail;
++
+ retval = search_binary_handler(bprm,regs);
+ if (retval < 0)
+- goto out;
++ goto out_fail;
++#ifdef CONFIG_GRKERNSEC
++ if (old_exec_file)
++ fput(old_exec_file);
++#endif
+
+ /* execve succeeded */
+ current->fs->in_exec = 0;
+@@ -1456,6 +1538,14 @@ int do_execve(const char * filename,
+ put_files_struct(displaced);
+ return retval;
+
++out_fail:
++#ifdef CONFIG_GRKERNSEC
++ current->acl = old_acl;
++ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
++ fput(current->exec_file);
++ current->exec_file = old_exec_file;
++#endif
++
+ out:
+ if (bprm->mm) {
+ acct_arg_size(bprm, 0);
+@@ -1501,7 +1591,7 @@ static int expand_corename(struct core_n
+ {
+ char *old_corename = cn->corename;
+
+- cn->size = CORENAME_MAX_SIZE * atomic_inc_return(&call_count);
++ cn->size = CORENAME_MAX_SIZE * atomic_inc_return_unchecked(&call_count);
+ cn->corename = krealloc(old_corename, cn->size, GFP_KERNEL);
+
+ if (!cn->corename) {
+@@ -1554,7 +1644,7 @@ static int format_corename(struct core_n
+ int pid_in_pattern = 0;
+ int err = 0;
+
+- cn->size = CORENAME_MAX_SIZE * atomic_read(&call_count);
++ cn->size = CORENAME_MAX_SIZE * atomic_read_unchecked(&call_count);
+ cn->corename = kmalloc(cn->size, GFP_KERNEL);
+ cn->used = 0;
+
+@@ -1642,6 +1732,208 @@ out:
+ return ispipe;
+ }
+
++int pax_check_flags(unsigned long *flags)
++{
++ int retval = 0;
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_SEGMEXEC)
++ if (*flags & MF_PAX_SEGMEXEC)
++ {
++ *flags &= ~MF_PAX_SEGMEXEC;
++ retval = -EINVAL;
++ }
++#endif
++
++ if ((*flags & MF_PAX_PAGEEXEC)
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ && (*flags & MF_PAX_SEGMEXEC)
++#endif
++
++ )
++ {
++ *flags &= ~MF_PAX_PAGEEXEC;
++ retval = -EINVAL;
++ }
++
++ if ((*flags & MF_PAX_MPROTECT)
++
++#ifdef CONFIG_PAX_MPROTECT
++ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
++#endif
++
++ )
++ {
++ *flags &= ~MF_PAX_MPROTECT;
++ retval = -EINVAL;
++ }
++
++ if ((*flags & MF_PAX_EMUTRAMP)
++
++#ifdef CONFIG_PAX_EMUTRAMP
++ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
++#endif
++
++ )
++ {
++ *flags &= ~MF_PAX_EMUTRAMP;
++ retval = -EINVAL;
++ }
++
++ return retval;
++}
++
++EXPORT_SYMBOL(pax_check_flags);
++
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++void pax_report_fault(struct pt_regs *regs, void *pc, void *sp)
++{
++ struct task_struct *tsk = current;
++ struct mm_struct *mm = current->mm;
++ char *buffer_exec = (char *)__get_free_page(GFP_KERNEL);
++ char *buffer_fault = (char *)__get_free_page(GFP_KERNEL);
++ char *path_exec = NULL;
++ char *path_fault = NULL;
++ unsigned long start = 0UL, end = 0UL, offset = 0UL;
++
++ if (buffer_exec && buffer_fault) {
++ struct vm_area_struct *vma, *vma_exec = NULL, *vma_fault = NULL;
++
++ down_read(&mm->mmap_sem);
++ vma = mm->mmap;
++ while (vma && (!vma_exec || !vma_fault)) {
++ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
++ vma_exec = vma;
++ if (vma->vm_start <= (unsigned long)pc && (unsigned long)pc < vma->vm_end)
++ vma_fault = vma;
++ vma = vma->vm_next;
++ }
++ if (vma_exec) {
++ path_exec = d_path(&vma_exec->vm_file->f_path, buffer_exec, PAGE_SIZE);
++ if (IS_ERR(path_exec))
++ path_exec = "<path too long>";
++ else {
++ path_exec = mangle_path(buffer_exec, path_exec, "\t\n\\");
++ if (path_exec) {
++ *path_exec = 0;
++ path_exec = buffer_exec;
++ } else
++ path_exec = "<path too long>";
++ }
++ }
++ if (vma_fault) {
++ start = vma_fault->vm_start;
++ end = vma_fault->vm_end;
++ offset = vma_fault->vm_pgoff << PAGE_SHIFT;
++ if (vma_fault->vm_file) {
++ path_fault = d_path(&vma_fault->vm_file->f_path, buffer_fault, PAGE_SIZE);
++ if (IS_ERR(path_fault))
++ path_fault = "<path too long>";
++ else {
++ path_fault = mangle_path(buffer_fault, path_fault, "\t\n\\");
++ if (path_fault) {
++ *path_fault = 0;
++ path_fault = buffer_fault;
++ } else
++ path_fault = "<path too long>";
++ }
++ } else
++ path_fault = "<anonymous mapping>";
++ }
++ up_read(&mm->mmap_sem);
++ }
++ if (tsk->signal->curr_ip)
++ printk(KERN_ERR "PAX: From %pI4: execution attempt in: %s, %08lx-%08lx %08lx\n", &tsk->signal->curr_ip, path_fault, start, end, offset);
++ else
++ printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset);
++ printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, "
++ "PC: %p, SP: %p\n", path_exec, tsk->comm, task_pid_nr(tsk),
++ task_uid(tsk), task_euid(tsk), pc, sp);
++ free_page((unsigned long)buffer_exec);
++ free_page((unsigned long)buffer_fault);
++ pax_report_insns(pc, sp);
++ do_coredump(SIGKILL, SIGKILL, regs);
++}
++#endif
++
++#ifdef CONFIG_PAX_REFCOUNT
++void pax_report_refcount_overflow(struct pt_regs *regs)
++{
++ if (current->signal->curr_ip)
++ printk(KERN_ERR "PAX: From %pI4: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n",
++ &current->signal->curr_ip, current->comm, task_pid_nr(current), current_uid(), current_euid());
++ else
++ printk(KERN_ERR "PAX: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n",
++ current->comm, task_pid_nr(current), current_uid(), current_euid());
++ print_symbol(KERN_ERR "PAX: refcount overflow occured at: %s\n", instruction_pointer(regs));
++ show_regs(regs);
++ force_sig_info(SIGKILL, SEND_SIG_FORCED, current);
++}
++#endif
++
++#ifdef CONFIG_PAX_USERCOPY
++/* 0: not at all, 1: fully, 2: fully inside frame, -1: partially (implies an error) */
++int object_is_on_stack(const void *obj, unsigned long len)
++{
++ const void * const stack = task_stack_page(current);
++ const void * const stackend = stack + THREAD_SIZE;
++
++#if defined(CONFIG_FRAME_POINTER) && defined(CONFIG_X86)
++ const void *frame = NULL;
++ const void *oldframe;
++#endif
++
++ if (obj + len < obj)
++ return -1;
++
++ if (obj + len <= stack || stackend <= obj)
++ return 0;
++
++ if (obj < stack || stackend < obj + len)
++ return -1;
++
++#if defined(CONFIG_FRAME_POINTER) && defined(CONFIG_X86)
++ oldframe = __builtin_frame_address(1);
++ if (oldframe)
++ frame = __builtin_frame_address(2);
++ /*
++ low ----------------------------------------------> high
++ [saved bp][saved ip][args][local vars][saved bp][saved ip]
++ ^----------------^
++ allow copies only within here
++ */
++ while (stack <= frame && frame < stackend) {
++ /* if obj + len extends past the last frame, this
++ check won't pass and the next frame will be 0,
++ causing us to bail out and correctly report
++ the copy as invalid
++ */
++ if (obj + len <= frame)
++ return obj >= oldframe + 2 * sizeof(void *) ? 2 : -1;
++ oldframe = frame;
++ frame = *(const void * const *)frame;
++ }
++ return -1;
++#else
++ return 1;
++#endif
++}
++
++
++void pax_report_usercopy(const void *ptr, unsigned long len, bool to, const char *type)
++{
++ if (current->signal->curr_ip)
++ printk(KERN_ERR "PAX: From %pI4: kernel memory %s attempt detected %s %p (%s) (%lu bytes)\n",
++ &current->signal->curr_ip, to ? "leak" : "overwrite", to ? "from" : "to", ptr, type ? : "unknown", len);
++ else
++ printk(KERN_ERR "PAX: kernel memory %s attempt detected %s %p (%s) (%lu bytes)\n",
++ to ? "leak" : "overwrite", to ? "from" : "to", ptr, type ? : "unknown", len);
++ dump_stack();
++ gr_handle_kernel_exploit();
++ do_group_exit(SIGKILL);
++}
++#endif
++
+ static int zap_process(struct task_struct *start, int exit_code)
+ {
+ struct task_struct *t;
+@@ -1852,17 +2144,17 @@ static void wait_for_dump_helpers(struct
+ pipe = file->f_path.dentry->d_inode->i_pipe;
+
+ pipe_lock(pipe);
+- pipe->readers++;
+- pipe->writers--;
++ atomic_inc(&pipe->readers);
++ atomic_dec(&pipe->writers);
+
+- while ((pipe->readers > 1) && (!signal_pending(current))) {
++ while ((atomic_read(&pipe->readers) > 1) && (!signal_pending(current))) {
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+ pipe_wait(pipe);
+ }
+
+- pipe->readers--;
+- pipe->writers++;
++ atomic_dec(&pipe->readers);
++ atomic_inc(&pipe->writers);
+ pipe_unlock(pipe);
+
+ }
+@@ -1923,7 +2215,7 @@ void do_coredump(long signr, int exit_co
+ int retval = 0;
+ int flag = 0;
+ int ispipe;
+- static atomic_t core_dump_count = ATOMIC_INIT(0);
++ static atomic_unchecked_t core_dump_count = ATOMIC_INIT(0);
+ struct coredump_params cprm = {
+ .signr = signr,
+ .regs = regs,
+@@ -1938,6 +2230,9 @@ void do_coredump(long signr, int exit_co
+
+ audit_core_dumps(signr);
+
++ if (signr == SIGSEGV || signr == SIGBUS || signr == SIGKILL || signr == SIGILL)
++ gr_handle_brute_attach(current, cprm.mm_flags);
++
+ binfmt = mm->binfmt;
+ if (!binfmt || !binfmt->core_dump)
+ goto fail;
+@@ -1978,6 +2273,8 @@ void do_coredump(long signr, int exit_co
+ goto fail_corename;
+ }
+
++ gr_learn_resource(current, RLIMIT_CORE, binfmt->min_coredump, 1);
++
+ if (ispipe) {
+ int dump_count;
+ char **helper_argv;
+@@ -2005,7 +2302,7 @@ void do_coredump(long signr, int exit_co
+ }
+ cprm.limit = RLIM_INFINITY;
+
+- dump_count = atomic_inc_return(&core_dump_count);
++ dump_count = atomic_inc_return_unchecked(&core_dump_count);
+ if (core_pipe_limit && (core_pipe_limit < dump_count)) {
+ printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n",
+ task_tgid_vnr(current), current->comm);
+@@ -2075,7 +2372,7 @@ close_fail:
+ filp_close(cprm.file, NULL);
+ fail_dropcount:
+ if (ispipe)
+- atomic_dec(&core_dump_count);
++ atomic_dec_unchecked(&core_dump_count);
+ fail_unlock:
+ kfree(cn.corename);
+ fail_corename:
+diff -urNp linux-2.6.38.7/fs/ext2/balloc.c linux-2.6.38.7/fs/ext2/balloc.c
+--- linux-2.6.38.7/fs/ext2/balloc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ext2/balloc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1192,7 +1192,7 @@ static int ext2_has_free_blocks(struct e
+
+ free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+ root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
+- if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
++ if (free_blocks < root_blocks + 1 && !capable_nolog(CAP_SYS_RESOURCE) &&
+ sbi->s_resuid != current_fsuid() &&
+ (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+ return 0;
+diff -urNp linux-2.6.38.7/fs/ext3/balloc.c linux-2.6.38.7/fs/ext3/balloc.c
+--- linux-2.6.38.7/fs/ext3/balloc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ext3/balloc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1441,7 +1441,7 @@ static int ext3_has_free_blocks(struct e
+
+ free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
+ root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
+- if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
++ if (free_blocks < root_blocks + 1 && !capable_nolog(CAP_SYS_RESOURCE) &&
+ sbi->s_resuid != current_fsuid() &&
+ (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+ return 0;
+diff -urNp linux-2.6.38.7/fs/ext4/balloc.c linux-2.6.38.7/fs/ext4/balloc.c
+--- linux-2.6.38.7/fs/ext4/balloc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ext4/balloc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -519,7 +519,7 @@ static int ext4_has_free_blocks(struct e
+ /* Hm, nope. Are (enough) root reserved blocks available? */
+ if (sbi->s_resuid == current_fsuid() ||
+ ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) ||
+- capable(CAP_SYS_RESOURCE)) {
++ capable_nolog(CAP_SYS_RESOURCE)) {
+ if (free_blocks >= (nblocks + dirty_blocks))
+ return 1;
+ }
+diff -urNp linux-2.6.38.7/fs/ext4/ext4.h linux-2.6.38.7/fs/ext4/ext4.h
+--- linux-2.6.38.7/fs/ext4/ext4.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ext4/ext4.h 2011-04-28 19:34:15.000000000 -0400
+@@ -1166,19 +1166,19 @@ struct ext4_sb_info {
+ unsigned long s_mb_last_start;
+
+ /* stats for buddy allocator */
+- atomic_t s_bal_reqs; /* number of reqs with len > 1 */
+- atomic_t s_bal_success; /* we found long enough chunks */
+- atomic_t s_bal_allocated; /* in blocks */
+- atomic_t s_bal_ex_scanned; /* total extents scanned */
+- atomic_t s_bal_goals; /* goal hits */
+- atomic_t s_bal_breaks; /* too long searches */
+- atomic_t s_bal_2orders; /* 2^order hits */
++ atomic_unchecked_t s_bal_reqs; /* number of reqs with len > 1 */
++ atomic_unchecked_t s_bal_success; /* we found long enough chunks */
++ atomic_unchecked_t s_bal_allocated; /* in blocks */
++ atomic_unchecked_t s_bal_ex_scanned; /* total extents scanned */
++ atomic_unchecked_t s_bal_goals; /* goal hits */
++ atomic_unchecked_t s_bal_breaks; /* too long searches */
++ atomic_unchecked_t s_bal_2orders; /* 2^order hits */
+ spinlock_t s_bal_lock;
+ unsigned long s_mb_buddies_generated;
+ unsigned long long s_mb_generation_time;
+- atomic_t s_mb_lost_chunks;
+- atomic_t s_mb_preallocated;
+- atomic_t s_mb_discarded;
++ atomic_unchecked_t s_mb_lost_chunks;
++ atomic_unchecked_t s_mb_preallocated;
++ atomic_unchecked_t s_mb_discarded;
+ atomic_t s_lock_busy;
+
+ /* locality groups */
+diff -urNp linux-2.6.38.7/fs/ext4/mballoc.c linux-2.6.38.7/fs/ext4/mballoc.c
+--- linux-2.6.38.7/fs/ext4/mballoc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ext4/mballoc.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1846,7 +1846,7 @@ void ext4_mb_simple_scan_group(struct ex
+ BUG_ON(ac->ac_b_ex.fe_len != ac->ac_g_ex.fe_len);
+
+ if (EXT4_SB(sb)->s_mb_stats)
+- atomic_inc(&EXT4_SB(sb)->s_bal_2orders);
++ atomic_inc_unchecked(&EXT4_SB(sb)->s_bal_2orders);
+
+ break;
+ }
+@@ -2140,7 +2140,7 @@ repeat:
+ ac->ac_status = AC_STATUS_CONTINUE;
+ ac->ac_flags |= EXT4_MB_HINT_FIRST;
+ cr = 3;
+- atomic_inc(&sbi->s_mb_lost_chunks);
++ atomic_inc_unchecked(&sbi->s_mb_lost_chunks);
+ goto repeat;
+ }
+ }
+@@ -2183,6 +2183,8 @@ static int ext4_mb_seq_groups_show(struc
+ ext4_grpblk_t counters[16];
+ } sg;
+
++ pax_track_stack();
++
+ group--;
+ if (group == 0)
+ seq_printf(seq, "#%-5s: %-5s %-5s %-5s "
+@@ -2606,25 +2608,25 @@ int ext4_mb_release(struct super_block *
+ if (sbi->s_mb_stats) {
+ printk(KERN_INFO
+ "EXT4-fs: mballoc: %u blocks %u reqs (%u success)\n",
+- atomic_read(&sbi->s_bal_allocated),
+- atomic_read(&sbi->s_bal_reqs),
+- atomic_read(&sbi->s_bal_success));
++ atomic_read_unchecked(&sbi->s_bal_allocated),
++ atomic_read_unchecked(&sbi->s_bal_reqs),
++ atomic_read_unchecked(&sbi->s_bal_success));
+ printk(KERN_INFO
+ "EXT4-fs: mballoc: %u extents scanned, %u goal hits, "
+ "%u 2^N hits, %u breaks, %u lost\n",
+- atomic_read(&sbi->s_bal_ex_scanned),
+- atomic_read(&sbi->s_bal_goals),
+- atomic_read(&sbi->s_bal_2orders),
+- atomic_read(&sbi->s_bal_breaks),
+- atomic_read(&sbi->s_mb_lost_chunks));
++ atomic_read_unchecked(&sbi->s_bal_ex_scanned),
++ atomic_read_unchecked(&sbi->s_bal_goals),
++ atomic_read_unchecked(&sbi->s_bal_2orders),
++ atomic_read_unchecked(&sbi->s_bal_breaks),
++ atomic_read_unchecked(&sbi->s_mb_lost_chunks));
+ printk(KERN_INFO
+ "EXT4-fs: mballoc: %lu generated and it took %Lu\n",
+ sbi->s_mb_buddies_generated++,
+ sbi->s_mb_generation_time);
+ printk(KERN_INFO
+ "EXT4-fs: mballoc: %u preallocated, %u discarded\n",
+- atomic_read(&sbi->s_mb_preallocated),
+- atomic_read(&sbi->s_mb_discarded));
++ atomic_read_unchecked(&sbi->s_mb_preallocated),
++ atomic_read_unchecked(&sbi->s_mb_discarded));
+ }
+
+ free_percpu(sbi->s_locality_groups);
+@@ -3100,16 +3102,16 @@ static void ext4_mb_collect_stats(struct
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+
+ if (sbi->s_mb_stats && ac->ac_g_ex.fe_len > 1) {
+- atomic_inc(&sbi->s_bal_reqs);
+- atomic_add(ac->ac_b_ex.fe_len, &sbi->s_bal_allocated);
++ atomic_inc_unchecked(&sbi->s_bal_reqs);
++ atomic_add_unchecked(ac->ac_b_ex.fe_len, &sbi->s_bal_allocated);
+ if (ac->ac_b_ex.fe_len >= ac->ac_o_ex.fe_len)
+- atomic_inc(&sbi->s_bal_success);
+- atomic_add(ac->ac_found, &sbi->s_bal_ex_scanned);
++ atomic_inc_unchecked(&sbi->s_bal_success);
++ atomic_add_unchecked(ac->ac_found, &sbi->s_bal_ex_scanned);
+ if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start &&
+ ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group)
+- atomic_inc(&sbi->s_bal_goals);
++ atomic_inc_unchecked(&sbi->s_bal_goals);
+ if (ac->ac_found > sbi->s_mb_max_to_scan)
+- atomic_inc(&sbi->s_bal_breaks);
++ atomic_inc_unchecked(&sbi->s_bal_breaks);
+ }
+
+ if (ac->ac_op == EXT4_MB_HISTORY_ALLOC)
+@@ -3507,7 +3509,7 @@ ext4_mb_new_inode_pa(struct ext4_allocat
+ trace_ext4_mb_new_inode_pa(ac, pa);
+
+ ext4_mb_use_inode_pa(ac, pa);
+- atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
++ atomic_add_unchecked(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+
+ ei = EXT4_I(ac->ac_inode);
+ grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
+@@ -3567,7 +3569,7 @@ ext4_mb_new_group_pa(struct ext4_allocat
+ trace_ext4_mb_new_group_pa(ac, pa);
+
+ ext4_mb_use_group_pa(ac, pa);
+- atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
++ atomic_add_unchecked(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+
+ grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
+ lg = ac->ac_lg;
+@@ -3654,7 +3656,7 @@ ext4_mb_release_inode_pa(struct ext4_bud
+ * from the bitmap and continue.
+ */
+ }
+- atomic_add(free, &sbi->s_mb_discarded);
++ atomic_add_unchecked(free, &sbi->s_mb_discarded);
+
+ return err;
+ }
+@@ -3672,7 +3674,7 @@ ext4_mb_release_group_pa(struct ext4_bud
+ ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
+ BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
+ mb_free_blocks(pa->pa_inode, e4b, bit, pa->pa_len);
+- atomic_add(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded);
++ atomic_add_unchecked(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded);
+ trace_ext4_mballoc_discard(sb, NULL, group, bit, pa->pa_len);
+
+ return 0;
+diff -urNp linux-2.6.38.7/fs/fcntl.c linux-2.6.38.7/fs/fcntl.c
+--- linux-2.6.38.7/fs/fcntl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fcntl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -224,6 +224,11 @@ int __f_setown(struct file *filp, struct
+ if (err)
+ return err;
+
++ if (gr_handle_chroot_fowner(pid, type))
++ return -ENOENT;
++ if (gr_check_protected_task_fowner(pid, type))
++ return -EACCES;
++
+ f_modown(filp, pid, type, force);
+ return 0;
+ }
+@@ -348,6 +353,7 @@ static long do_fcntl(int fd, unsigned in
+ switch (cmd) {
+ case F_DUPFD:
+ case F_DUPFD_CLOEXEC:
++ gr_learn_resource(current, RLIMIT_NOFILE, arg, 0);
+ if (arg >= rlimit(RLIMIT_NOFILE))
+ break;
+ err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0);
+@@ -808,14 +814,14 @@ static int __init fcntl_init(void)
+ * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
+ * is defined as O_NONBLOCK on some platforms and not on others.
+ */
+- BUILD_BUG_ON(18 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
++ BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
+ O_RDONLY | O_WRONLY | O_RDWR |
+ O_CREAT | O_EXCL | O_NOCTTY |
+ O_TRUNC | O_APPEND | /* O_NONBLOCK | */
+ __O_SYNC | O_DSYNC | FASYNC |
+ O_DIRECT | O_LARGEFILE | O_DIRECTORY |
+ O_NOFOLLOW | O_NOATIME | O_CLOEXEC |
+- __FMODE_EXEC
++ __FMODE_EXEC | FMODE_GREXEC
+ ));
+
+ fasync_cache = kmem_cache_create("fasync_cache",
+diff -urNp linux-2.6.38.7/fs/fifo.c linux-2.6.38.7/fs/fifo.c
+--- linux-2.6.38.7/fs/fifo.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fifo.c 2011-04-28 19:34:15.000000000 -0400
+@@ -58,10 +58,10 @@ static int fifo_open(struct inode *inode
+ */
+ filp->f_op = &read_pipefifo_fops;
+ pipe->r_counter++;
+- if (pipe->readers++ == 0)
++ if (atomic_inc_return(&pipe->readers) == 1)
+ wake_up_partner(inode);
+
+- if (!pipe->writers) {
++ if (!atomic_read(&pipe->writers)) {
+ if ((filp->f_flags & O_NONBLOCK)) {
+ /* suppress POLLHUP until we have
+ * seen a writer */
+@@ -82,15 +82,15 @@ static int fifo_open(struct inode *inode
+ * errno=ENXIO when there is no process reading the FIFO.
+ */
+ ret = -ENXIO;
+- if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
++ if ((filp->f_flags & O_NONBLOCK) && !atomic_read(&pipe->readers))
+ goto err;
+
+ filp->f_op = &write_pipefifo_fops;
+ pipe->w_counter++;
+- if (!pipe->writers++)
++ if (atomic_inc_return(&pipe->writers) == 1)
+ wake_up_partner(inode);
+
+- if (!pipe->readers) {
++ if (!atomic_read(&pipe->readers)) {
+ wait_for_partner(inode, &pipe->r_counter);
+ if (signal_pending(current))
+ goto err_wr;
+@@ -106,11 +106,11 @@ static int fifo_open(struct inode *inode
+ */
+ filp->f_op = &rdwr_pipefifo_fops;
+
+- pipe->readers++;
+- pipe->writers++;
++ atomic_inc(&pipe->readers);
++ atomic_inc(&pipe->writers);
+ pipe->r_counter++;
+ pipe->w_counter++;
+- if (pipe->readers == 1 || pipe->writers == 1)
++ if (atomic_read(&pipe->readers) == 1 || atomic_read(&pipe->writers) == 1)
+ wake_up_partner(inode);
+ break;
+
+@@ -124,19 +124,19 @@ static int fifo_open(struct inode *inode
+ return 0;
+
+ err_rd:
+- if (!--pipe->readers)
++ if (atomic_dec_and_test(&pipe->readers))
+ wake_up_interruptible(&pipe->wait);
+ ret = -ERESTARTSYS;
+ goto err;
+
+ err_wr:
+- if (!--pipe->writers)
++ if (atomic_dec_and_test(&pipe->writers))
+ wake_up_interruptible(&pipe->wait);
+ ret = -ERESTARTSYS;
+ goto err;
+
+ err:
+- if (!pipe->readers && !pipe->writers)
++ if (!atomic_read(&pipe->readers) && !atomic_read(&pipe->writers))
+ free_pipe_info(inode);
+
+ err_nocleanup:
+diff -urNp linux-2.6.38.7/fs/file.c linux-2.6.38.7/fs/file.c
+--- linux-2.6.38.7/fs/file.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/fs/file.c 2011-05-10 22:06:56.000000000 -0400
+@@ -15,6 +15,7 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/file.h>
++#include <linux/security.h>
+ #include <linux/fdtable.h>
+ #include <linux/bitops.h>
+ #include <linux/interrupt.h>
+@@ -254,6 +255,7 @@ int expand_files(struct files_struct *fi
+ * N.B. For clone tasks sharing a files structure, this test
+ * will limit the total number of files that can be opened.
+ */
++ gr_learn_resource(current, RLIMIT_NOFILE, nr, 0);
+ if (nr >= rlimit(RLIMIT_NOFILE))
+ return -EMFILE;
+
+diff -urNp linux-2.6.38.7/fs/filesystems.c linux-2.6.38.7/fs/filesystems.c
+--- linux-2.6.38.7/fs/filesystems.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/filesystems.c 2011-04-28 19:34:15.000000000 -0400
+@@ -275,7 +275,12 @@ struct file_system_type *get_fs_type(con
+ int len = dot ? dot - name : strlen(name);
+
+ fs = __get_fs_type(name, len);
++
++#ifdef CONFIG_GRKERNSEC_MODHARDEN
++ if (!fs && (___request_module(true, "grsec_modharden_fs", "%.*s", len, name) == 0))
++#else
+ if (!fs && (request_module("%.*s", len, name) == 0))
++#endif
+ fs = __get_fs_type(name, len);
+
+ if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
+diff -urNp linux-2.6.38.7/fs/fscache/cookie.c linux-2.6.38.7/fs/fscache/cookie.c
+--- linux-2.6.38.7/fs/fscache/cookie.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fscache/cookie.c 2011-04-28 19:57:25.000000000 -0400
+@@ -68,11 +68,11 @@ struct fscache_cookie *__fscache_acquire
+ parent ? (char *) parent->def->name : "<no-parent>",
+ def->name, netfs_data);
+
+- fscache_stat(&fscache_n_acquires);
++ fscache_stat_unchecked(&fscache_n_acquires);
+
+ /* if there's no parent cookie, then we don't create one here either */
+ if (!parent) {
+- fscache_stat(&fscache_n_acquires_null);
++ fscache_stat_unchecked(&fscache_n_acquires_null);
+ _leave(" [no parent]");
+ return NULL;
+ }
+@@ -87,7 +87,7 @@ struct fscache_cookie *__fscache_acquire
+ /* allocate and initialise a cookie */
+ cookie = kmem_cache_alloc(fscache_cookie_jar, GFP_KERNEL);
+ if (!cookie) {
+- fscache_stat(&fscache_n_acquires_oom);
++ fscache_stat_unchecked(&fscache_n_acquires_oom);
+ _leave(" [ENOMEM]");
+ return NULL;
+ }
+@@ -109,13 +109,13 @@ struct fscache_cookie *__fscache_acquire
+
+ switch (cookie->def->type) {
+ case FSCACHE_COOKIE_TYPE_INDEX:
+- fscache_stat(&fscache_n_cookie_index);
++ fscache_stat_unchecked(&fscache_n_cookie_index);
+ break;
+ case FSCACHE_COOKIE_TYPE_DATAFILE:
+- fscache_stat(&fscache_n_cookie_data);
++ fscache_stat_unchecked(&fscache_n_cookie_data);
+ break;
+ default:
+- fscache_stat(&fscache_n_cookie_special);
++ fscache_stat_unchecked(&fscache_n_cookie_special);
+ break;
+ }
+
+@@ -126,13 +126,13 @@ struct fscache_cookie *__fscache_acquire
+ if (fscache_acquire_non_index_cookie(cookie) < 0) {
+ atomic_dec(&parent->n_children);
+ __fscache_cookie_put(cookie);
+- fscache_stat(&fscache_n_acquires_nobufs);
++ fscache_stat_unchecked(&fscache_n_acquires_nobufs);
+ _leave(" = NULL");
+ return NULL;
+ }
+ }
+
+- fscache_stat(&fscache_n_acquires_ok);
++ fscache_stat_unchecked(&fscache_n_acquires_ok);
+ _leave(" = %p", cookie);
+ return cookie;
+ }
+@@ -168,7 +168,7 @@ static int fscache_acquire_non_index_coo
+ cache = fscache_select_cache_for_object(cookie->parent);
+ if (!cache) {
+ up_read(&fscache_addremove_sem);
+- fscache_stat(&fscache_n_acquires_no_cache);
++ fscache_stat_unchecked(&fscache_n_acquires_no_cache);
+ _leave(" = -ENOMEDIUM [no cache]");
+ return -ENOMEDIUM;
+ }
+@@ -256,12 +256,12 @@ static int fscache_alloc_object(struct f
+ object = cache->ops->alloc_object(cache, cookie);
+ fscache_stat_d(&fscache_n_cop_alloc_object);
+ if (IS_ERR(object)) {
+- fscache_stat(&fscache_n_object_no_alloc);
++ fscache_stat_unchecked(&fscache_n_object_no_alloc);
+ ret = PTR_ERR(object);
+ goto error;
+ }
+
+- fscache_stat(&fscache_n_object_alloc);
++ fscache_stat_unchecked(&fscache_n_object_alloc);
+
+ object->debug_id = atomic_inc_return(&fscache_object_debug_id);
+
+@@ -377,10 +377,10 @@ void __fscache_update_cookie(struct fsca
+ struct fscache_object *object;
+ struct hlist_node *_p;
+
+- fscache_stat(&fscache_n_updates);
++ fscache_stat_unchecked(&fscache_n_updates);
+
+ if (!cookie) {
+- fscache_stat(&fscache_n_updates_null);
++ fscache_stat_unchecked(&fscache_n_updates_null);
+ _leave(" [no cookie]");
+ return;
+ }
+@@ -414,12 +414,12 @@ void __fscache_relinquish_cookie(struct
+ struct fscache_object *object;
+ unsigned long event;
+
+- fscache_stat(&fscache_n_relinquishes);
++ fscache_stat_unchecked(&fscache_n_relinquishes);
+ if (retire)
+- fscache_stat(&fscache_n_relinquishes_retire);
++ fscache_stat_unchecked(&fscache_n_relinquishes_retire);
+
+ if (!cookie) {
+- fscache_stat(&fscache_n_relinquishes_null);
++ fscache_stat_unchecked(&fscache_n_relinquishes_null);
+ _leave(" [no cookie]");
+ return;
+ }
+@@ -435,7 +435,7 @@ void __fscache_relinquish_cookie(struct
+
+ /* wait for the cookie to finish being instantiated (or to fail) */
+ if (test_bit(FSCACHE_COOKIE_CREATING, &cookie->flags)) {
+- fscache_stat(&fscache_n_relinquishes_waitcrt);
++ fscache_stat_unchecked(&fscache_n_relinquishes_waitcrt);
+ wait_on_bit(&cookie->flags, FSCACHE_COOKIE_CREATING,
+ fscache_wait_bit, TASK_UNINTERRUPTIBLE);
+ }
+diff -urNp linux-2.6.38.7/fs/fscache/internal.h linux-2.6.38.7/fs/fscache/internal.h
+--- linux-2.6.38.7/fs/fscache/internal.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fscache/internal.h 2011-05-02 19:07:09.000000000 -0400
+@@ -144,94 +144,94 @@ extern void fscache_proc_cleanup(void);
+ extern atomic_t fscache_n_ops_processed[FSCACHE_MAX_THREADS];
+ extern atomic_t fscache_n_objs_processed[FSCACHE_MAX_THREADS];
+
+-extern atomic_t fscache_n_op_pend;
+-extern atomic_t fscache_n_op_run;
+-extern atomic_t fscache_n_op_enqueue;
+-extern atomic_t fscache_n_op_deferred_release;
+-extern atomic_t fscache_n_op_release;
+-extern atomic_t fscache_n_op_gc;
+-extern atomic_t fscache_n_op_cancelled;
+-extern atomic_t fscache_n_op_rejected;
+-
+-extern atomic_t fscache_n_attr_changed;
+-extern atomic_t fscache_n_attr_changed_ok;
+-extern atomic_t fscache_n_attr_changed_nobufs;
+-extern atomic_t fscache_n_attr_changed_nomem;
+-extern atomic_t fscache_n_attr_changed_calls;
+-
+-extern atomic_t fscache_n_allocs;
+-extern atomic_t fscache_n_allocs_ok;
+-extern atomic_t fscache_n_allocs_wait;
+-extern atomic_t fscache_n_allocs_nobufs;
+-extern atomic_t fscache_n_allocs_intr;
+-extern atomic_t fscache_n_allocs_object_dead;
+-extern atomic_t fscache_n_alloc_ops;
+-extern atomic_t fscache_n_alloc_op_waits;
+-
+-extern atomic_t fscache_n_retrievals;
+-extern atomic_t fscache_n_retrievals_ok;
+-extern atomic_t fscache_n_retrievals_wait;
+-extern atomic_t fscache_n_retrievals_nodata;
+-extern atomic_t fscache_n_retrievals_nobufs;
+-extern atomic_t fscache_n_retrievals_intr;
+-extern atomic_t fscache_n_retrievals_nomem;
+-extern atomic_t fscache_n_retrievals_object_dead;
+-extern atomic_t fscache_n_retrieval_ops;
+-extern atomic_t fscache_n_retrieval_op_waits;
+-
+-extern atomic_t fscache_n_stores;
+-extern atomic_t fscache_n_stores_ok;
+-extern atomic_t fscache_n_stores_again;
+-extern atomic_t fscache_n_stores_nobufs;
+-extern atomic_t fscache_n_stores_oom;
+-extern atomic_t fscache_n_store_ops;
+-extern atomic_t fscache_n_store_calls;
+-extern atomic_t fscache_n_store_pages;
+-extern atomic_t fscache_n_store_radix_deletes;
+-extern atomic_t fscache_n_store_pages_over_limit;
+-
+-extern atomic_t fscache_n_store_vmscan_not_storing;
+-extern atomic_t fscache_n_store_vmscan_gone;
+-extern atomic_t fscache_n_store_vmscan_busy;
+-extern atomic_t fscache_n_store_vmscan_cancelled;
+-
+-extern atomic_t fscache_n_marks;
+-extern atomic_t fscache_n_uncaches;
+-
+-extern atomic_t fscache_n_acquires;
+-extern atomic_t fscache_n_acquires_null;
+-extern atomic_t fscache_n_acquires_no_cache;
+-extern atomic_t fscache_n_acquires_ok;
+-extern atomic_t fscache_n_acquires_nobufs;
+-extern atomic_t fscache_n_acquires_oom;
+-
+-extern atomic_t fscache_n_updates;
+-extern atomic_t fscache_n_updates_null;
+-extern atomic_t fscache_n_updates_run;
+-
+-extern atomic_t fscache_n_relinquishes;
+-extern atomic_t fscache_n_relinquishes_null;
+-extern atomic_t fscache_n_relinquishes_waitcrt;
+-extern atomic_t fscache_n_relinquishes_retire;
+-
+-extern atomic_t fscache_n_cookie_index;
+-extern atomic_t fscache_n_cookie_data;
+-extern atomic_t fscache_n_cookie_special;
+-
+-extern atomic_t fscache_n_object_alloc;
+-extern atomic_t fscache_n_object_no_alloc;
+-extern atomic_t fscache_n_object_lookups;
+-extern atomic_t fscache_n_object_lookups_negative;
+-extern atomic_t fscache_n_object_lookups_positive;
+-extern atomic_t fscache_n_object_lookups_timed_out;
+-extern atomic_t fscache_n_object_created;
+-extern atomic_t fscache_n_object_avail;
+-extern atomic_t fscache_n_object_dead;
+-
+-extern atomic_t fscache_n_checkaux_none;
+-extern atomic_t fscache_n_checkaux_okay;
+-extern atomic_t fscache_n_checkaux_update;
+-extern atomic_t fscache_n_checkaux_obsolete;
++extern atomic_unchecked_t fscache_n_op_pend;
++extern atomic_unchecked_t fscache_n_op_run;
++extern atomic_unchecked_t fscache_n_op_enqueue;
++extern atomic_unchecked_t fscache_n_op_deferred_release;
++extern atomic_unchecked_t fscache_n_op_release;
++extern atomic_unchecked_t fscache_n_op_gc;
++extern atomic_unchecked_t fscache_n_op_cancelled;
++extern atomic_unchecked_t fscache_n_op_rejected;
++
++extern atomic_unchecked_t fscache_n_attr_changed;
++extern atomic_unchecked_t fscache_n_attr_changed_ok;
++extern atomic_unchecked_t fscache_n_attr_changed_nobufs;
++extern atomic_unchecked_t fscache_n_attr_changed_nomem;
++extern atomic_unchecked_t fscache_n_attr_changed_calls;
++
++extern atomic_unchecked_t fscache_n_allocs;
++extern atomic_unchecked_t fscache_n_allocs_ok;
++extern atomic_unchecked_t fscache_n_allocs_wait;
++extern atomic_unchecked_t fscache_n_allocs_nobufs;
++extern atomic_unchecked_t fscache_n_allocs_intr;
++extern atomic_unchecked_t fscache_n_allocs_object_dead;
++extern atomic_unchecked_t fscache_n_alloc_ops;
++extern atomic_unchecked_t fscache_n_alloc_op_waits;
++
++extern atomic_unchecked_t fscache_n_retrievals;
++extern atomic_unchecked_t fscache_n_retrievals_ok;
++extern atomic_unchecked_t fscache_n_retrievals_wait;
++extern atomic_unchecked_t fscache_n_retrievals_nodata;
++extern atomic_unchecked_t fscache_n_retrievals_nobufs;
++extern atomic_unchecked_t fscache_n_retrievals_intr;
++extern atomic_unchecked_t fscache_n_retrievals_nomem;
++extern atomic_unchecked_t fscache_n_retrievals_object_dead;
++extern atomic_unchecked_t fscache_n_retrieval_ops;
++extern atomic_unchecked_t fscache_n_retrieval_op_waits;
++
++extern atomic_unchecked_t fscache_n_stores;
++extern atomic_unchecked_t fscache_n_stores_ok;
++extern atomic_unchecked_t fscache_n_stores_again;
++extern atomic_unchecked_t fscache_n_stores_nobufs;
++extern atomic_unchecked_t fscache_n_stores_oom;
++extern atomic_unchecked_t fscache_n_store_ops;
++extern atomic_unchecked_t fscache_n_store_calls;
++extern atomic_unchecked_t fscache_n_store_pages;
++extern atomic_unchecked_t fscache_n_store_radix_deletes;
++extern atomic_unchecked_t fscache_n_store_pages_over_limit;
++
++extern atomic_unchecked_t fscache_n_store_vmscan_not_storing;
++extern atomic_unchecked_t fscache_n_store_vmscan_gone;
++extern atomic_unchecked_t fscache_n_store_vmscan_busy;
++extern atomic_unchecked_t fscache_n_store_vmscan_cancelled;
++
++extern atomic_unchecked_t fscache_n_marks;
++extern atomic_unchecked_t fscache_n_uncaches;
++
++extern atomic_unchecked_t fscache_n_acquires;
++extern atomic_unchecked_t fscache_n_acquires_null;
++extern atomic_unchecked_t fscache_n_acquires_no_cache;
++extern atomic_unchecked_t fscache_n_acquires_ok;
++extern atomic_unchecked_t fscache_n_acquires_nobufs;
++extern atomic_unchecked_t fscache_n_acquires_oom;
++
++extern atomic_unchecked_t fscache_n_updates;
++extern atomic_unchecked_t fscache_n_updates_null;
++extern atomic_unchecked_t fscache_n_updates_run;
++
++extern atomic_unchecked_t fscache_n_relinquishes;
++extern atomic_unchecked_t fscache_n_relinquishes_null;
++extern atomic_unchecked_t fscache_n_relinquishes_waitcrt;
++extern atomic_unchecked_t fscache_n_relinquishes_retire;
++
++extern atomic_unchecked_t fscache_n_cookie_index;
++extern atomic_unchecked_t fscache_n_cookie_data;
++extern atomic_unchecked_t fscache_n_cookie_special;
++
++extern atomic_unchecked_t fscache_n_object_alloc;
++extern atomic_unchecked_t fscache_n_object_no_alloc;
++extern atomic_unchecked_t fscache_n_object_lookups;
++extern atomic_unchecked_t fscache_n_object_lookups_negative;
++extern atomic_unchecked_t fscache_n_object_lookups_positive;
++extern atomic_unchecked_t fscache_n_object_lookups_timed_out;
++extern atomic_unchecked_t fscache_n_object_created;
++extern atomic_unchecked_t fscache_n_object_avail;
++extern atomic_unchecked_t fscache_n_object_dead;
++
++extern atomic_unchecked_t fscache_n_checkaux_none;
++extern atomic_unchecked_t fscache_n_checkaux_okay;
++extern atomic_unchecked_t fscache_n_checkaux_update;
++extern atomic_unchecked_t fscache_n_checkaux_obsolete;
+
+ extern atomic_t fscache_n_cop_alloc_object;
+ extern atomic_t fscache_n_cop_lookup_object;
+@@ -255,6 +255,11 @@ static inline void fscache_stat(atomic_t
+ atomic_inc(stat);
+ }
+
++static inline void fscache_stat_unchecked(atomic_unchecked_t *stat)
++{
++ atomic_inc_unchecked(stat);
++}
++
+ static inline void fscache_stat_d(atomic_t *stat)
+ {
+ atomic_dec(stat);
+@@ -267,6 +272,7 @@ extern const struct file_operations fsca
+
+ #define __fscache_stat(stat) (NULL)
+ #define fscache_stat(stat) do {} while (0)
++#define fscache_stat_unchecked(stat) do {} while (0)
+ #define fscache_stat_d(stat) do {} while (0)
+ #endif
+
+diff -urNp linux-2.6.38.7/fs/fscache/object.c linux-2.6.38.7/fs/fscache/object.c
+--- linux-2.6.38.7/fs/fscache/object.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fscache/object.c 2011-04-28 19:57:25.000000000 -0400
+@@ -128,7 +128,7 @@ static void fscache_object_state_machine
+ /* update the object metadata on disk */
+ case FSCACHE_OBJECT_UPDATING:
+ clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events);
+- fscache_stat(&fscache_n_updates_run);
++ fscache_stat_unchecked(&fscache_n_updates_run);
+ fscache_stat(&fscache_n_cop_update_object);
+ object->cache->ops->update_object(object);
+ fscache_stat_d(&fscache_n_cop_update_object);
+@@ -217,7 +217,7 @@ static void fscache_object_state_machine
+ spin_lock(&object->lock);
+ object->state = FSCACHE_OBJECT_DEAD;
+ spin_unlock(&object->lock);
+- fscache_stat(&fscache_n_object_dead);
++ fscache_stat_unchecked(&fscache_n_object_dead);
+ goto terminal_transit;
+
+ /* handle the parent cache of this object being withdrawn from
+@@ -232,7 +232,7 @@ static void fscache_object_state_machine
+ spin_lock(&object->lock);
+ object->state = FSCACHE_OBJECT_DEAD;
+ spin_unlock(&object->lock);
+- fscache_stat(&fscache_n_object_dead);
++ fscache_stat_unchecked(&fscache_n_object_dead);
+ goto terminal_transit;
+
+ /* complain about the object being woken up once it is
+@@ -461,7 +461,7 @@ static void fscache_lookup_object(struct
+ parent->cookie->def->name, cookie->def->name,
+ object->cache->tag->name);
+
+- fscache_stat(&fscache_n_object_lookups);
++ fscache_stat_unchecked(&fscache_n_object_lookups);
+ fscache_stat(&fscache_n_cop_lookup_object);
+ ret = object->cache->ops->lookup_object(object);
+ fscache_stat_d(&fscache_n_cop_lookup_object);
+@@ -472,7 +472,7 @@ static void fscache_lookup_object(struct
+ if (ret == -ETIMEDOUT) {
+ /* probably stuck behind another object, so move this one to
+ * the back of the queue */
+- fscache_stat(&fscache_n_object_lookups_timed_out);
++ fscache_stat_unchecked(&fscache_n_object_lookups_timed_out);
+ set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
+ }
+
+@@ -495,7 +495,7 @@ void fscache_object_lookup_negative(stru
+
+ spin_lock(&object->lock);
+ if (object->state == FSCACHE_OBJECT_LOOKING_UP) {
+- fscache_stat(&fscache_n_object_lookups_negative);
++ fscache_stat_unchecked(&fscache_n_object_lookups_negative);
+
+ /* transit here to allow write requests to begin stacking up
+ * and read requests to begin returning ENODATA */
+@@ -541,7 +541,7 @@ void fscache_obtained_object(struct fsca
+ * result, in which case there may be data available */
+ spin_lock(&object->lock);
+ if (object->state == FSCACHE_OBJECT_LOOKING_UP) {
+- fscache_stat(&fscache_n_object_lookups_positive);
++ fscache_stat_unchecked(&fscache_n_object_lookups_positive);
+
+ clear_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
+
+@@ -555,7 +555,7 @@ void fscache_obtained_object(struct fsca
+ set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
+ } else {
+ ASSERTCMP(object->state, ==, FSCACHE_OBJECT_CREATING);
+- fscache_stat(&fscache_n_object_created);
++ fscache_stat_unchecked(&fscache_n_object_created);
+
+ object->state = FSCACHE_OBJECT_AVAILABLE;
+ spin_unlock(&object->lock);
+@@ -602,7 +602,7 @@ static void fscache_object_available(str
+ fscache_enqueue_dependents(object);
+
+ fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif);
+- fscache_stat(&fscache_n_object_avail);
++ fscache_stat_unchecked(&fscache_n_object_avail);
+
+ _leave("");
+ }
+@@ -861,7 +861,7 @@ enum fscache_checkaux fscache_check_aux(
+ enum fscache_checkaux result;
+
+ if (!object->cookie->def->check_aux) {
+- fscache_stat(&fscache_n_checkaux_none);
++ fscache_stat_unchecked(&fscache_n_checkaux_none);
+ return FSCACHE_CHECKAUX_OKAY;
+ }
+
+@@ -870,17 +870,17 @@ enum fscache_checkaux fscache_check_aux(
+ switch (result) {
+ /* entry okay as is */
+ case FSCACHE_CHECKAUX_OKAY:
+- fscache_stat(&fscache_n_checkaux_okay);
++ fscache_stat_unchecked(&fscache_n_checkaux_okay);
+ break;
+
+ /* entry requires update */
+ case FSCACHE_CHECKAUX_NEEDS_UPDATE:
+- fscache_stat(&fscache_n_checkaux_update);
++ fscache_stat_unchecked(&fscache_n_checkaux_update);
+ break;
+
+ /* entry requires deletion */
+ case FSCACHE_CHECKAUX_OBSOLETE:
+- fscache_stat(&fscache_n_checkaux_obsolete);
++ fscache_stat_unchecked(&fscache_n_checkaux_obsolete);
+ break;
+
+ default:
+diff -urNp linux-2.6.38.7/fs/fscache/operation.c linux-2.6.38.7/fs/fscache/operation.c
+--- linux-2.6.38.7/fs/fscache/operation.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fscache/operation.c 2011-04-28 19:57:25.000000000 -0400
+@@ -17,7 +17,7 @@
+ #include <linux/slab.h>
+ #include "internal.h"
+
+-atomic_t fscache_op_debug_id;
++atomic_unchecked_t fscache_op_debug_id;
+ EXPORT_SYMBOL(fscache_op_debug_id);
+
+ /**
+@@ -40,7 +40,7 @@ void fscache_enqueue_operation(struct fs
+ ASSERTCMP(op->object->state, >=, FSCACHE_OBJECT_AVAILABLE);
+ ASSERTCMP(atomic_read(&op->usage), >, 0);
+
+- fscache_stat(&fscache_n_op_enqueue);
++ fscache_stat_unchecked(&fscache_n_op_enqueue);
+ switch (op->flags & FSCACHE_OP_TYPE) {
+ case FSCACHE_OP_ASYNC:
+ _debug("queue async");
+@@ -73,7 +73,7 @@ static void fscache_run_op(struct fscach
+ wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
+ if (op->processor)
+ fscache_enqueue_operation(op);
+- fscache_stat(&fscache_n_op_run);
++ fscache_stat_unchecked(&fscache_n_op_run);
+ }
+
+ /*
+@@ -104,11 +104,11 @@ int fscache_submit_exclusive_op(struct f
+ if (object->n_ops > 1) {
+ atomic_inc(&op->usage);
+ list_add_tail(&op->pend_link, &object->pending_ops);
+- fscache_stat(&fscache_n_op_pend);
++ fscache_stat_unchecked(&fscache_n_op_pend);
+ } else if (!list_empty(&object->pending_ops)) {
+ atomic_inc(&op->usage);
+ list_add_tail(&op->pend_link, &object->pending_ops);
+- fscache_stat(&fscache_n_op_pend);
++ fscache_stat_unchecked(&fscache_n_op_pend);
+ fscache_start_operations(object);
+ } else {
+ ASSERTCMP(object->n_in_progress, ==, 0);
+@@ -124,7 +124,7 @@ int fscache_submit_exclusive_op(struct f
+ object->n_exclusive++; /* reads and writes must wait */
+ atomic_inc(&op->usage);
+ list_add_tail(&op->pend_link, &object->pending_ops);
+- fscache_stat(&fscache_n_op_pend);
++ fscache_stat_unchecked(&fscache_n_op_pend);
+ ret = 0;
+ } else {
+ /* not allowed to submit ops in any other state */
+@@ -211,11 +211,11 @@ int fscache_submit_op(struct fscache_obj
+ if (object->n_exclusive > 0) {
+ atomic_inc(&op->usage);
+ list_add_tail(&op->pend_link, &object->pending_ops);
+- fscache_stat(&fscache_n_op_pend);
++ fscache_stat_unchecked(&fscache_n_op_pend);
+ } else if (!list_empty(&object->pending_ops)) {
+ atomic_inc(&op->usage);
+ list_add_tail(&op->pend_link, &object->pending_ops);
+- fscache_stat(&fscache_n_op_pend);
++ fscache_stat_unchecked(&fscache_n_op_pend);
+ fscache_start_operations(object);
+ } else {
+ ASSERTCMP(object->n_exclusive, ==, 0);
+@@ -227,12 +227,12 @@ int fscache_submit_op(struct fscache_obj
+ object->n_ops++;
+ atomic_inc(&op->usage);
+ list_add_tail(&op->pend_link, &object->pending_ops);
+- fscache_stat(&fscache_n_op_pend);
++ fscache_stat_unchecked(&fscache_n_op_pend);
+ ret = 0;
+ } else if (object->state == FSCACHE_OBJECT_DYING ||
+ object->state == FSCACHE_OBJECT_LC_DYING ||
+ object->state == FSCACHE_OBJECT_WITHDRAWING) {
+- fscache_stat(&fscache_n_op_rejected);
++ fscache_stat_unchecked(&fscache_n_op_rejected);
+ ret = -ENOBUFS;
+ } else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) {
+ fscache_report_unexpected_submission(object, op, ostate);
+@@ -302,7 +302,7 @@ int fscache_cancel_op(struct fscache_ope
+
+ ret = -EBUSY;
+ if (!list_empty(&op->pend_link)) {
+- fscache_stat(&fscache_n_op_cancelled);
++ fscache_stat_unchecked(&fscache_n_op_cancelled);
+ list_del_init(&op->pend_link);
+ object->n_ops--;
+ if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
+@@ -341,7 +341,7 @@ void fscache_put_operation(struct fscach
+ if (test_and_set_bit(FSCACHE_OP_DEAD, &op->flags))
+ BUG();
+
+- fscache_stat(&fscache_n_op_release);
++ fscache_stat_unchecked(&fscache_n_op_release);
+
+ if (op->release) {
+ op->release(op);
+@@ -358,7 +358,7 @@ void fscache_put_operation(struct fscach
+ * lock, and defer it otherwise */
+ if (!spin_trylock(&object->lock)) {
+ _debug("defer put");
+- fscache_stat(&fscache_n_op_deferred_release);
++ fscache_stat_unchecked(&fscache_n_op_deferred_release);
+
+ cache = object->cache;
+ spin_lock(&cache->op_gc_list_lock);
+@@ -420,7 +420,7 @@ void fscache_operation_gc(struct work_st
+
+ _debug("GC DEFERRED REL OBJ%x OP%x",
+ object->debug_id, op->debug_id);
+- fscache_stat(&fscache_n_op_gc);
++ fscache_stat_unchecked(&fscache_n_op_gc);
+
+ ASSERTCMP(atomic_read(&op->usage), ==, 0);
+
+diff -urNp linux-2.6.38.7/fs/fscache/page.c linux-2.6.38.7/fs/fscache/page.c
+--- linux-2.6.38.7/fs/fscache/page.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fscache/page.c 2011-04-28 19:57:25.000000000 -0400
+@@ -60,7 +60,7 @@ bool __fscache_maybe_release_page(struct
+ val = radix_tree_lookup(&cookie->stores, page->index);
+ if (!val) {
+ rcu_read_unlock();
+- fscache_stat(&fscache_n_store_vmscan_not_storing);
++ fscache_stat_unchecked(&fscache_n_store_vmscan_not_storing);
+ __fscache_uncache_page(cookie, page);
+ return true;
+ }
+@@ -90,11 +90,11 @@ bool __fscache_maybe_release_page(struct
+ spin_unlock(&cookie->stores_lock);
+
+ if (xpage) {
+- fscache_stat(&fscache_n_store_vmscan_cancelled);
+- fscache_stat(&fscache_n_store_radix_deletes);
++ fscache_stat_unchecked(&fscache_n_store_vmscan_cancelled);
++ fscache_stat_unchecked(&fscache_n_store_radix_deletes);
+ ASSERTCMP(xpage, ==, page);
+ } else {
+- fscache_stat(&fscache_n_store_vmscan_gone);
++ fscache_stat_unchecked(&fscache_n_store_vmscan_gone);
+ }
+
+ wake_up_bit(&cookie->flags, 0);
+@@ -107,7 +107,7 @@ page_busy:
+ /* we might want to wait here, but that could deadlock the allocator as
+ * the work threads writing to the cache may all end up sleeping
+ * on memory allocation */
+- fscache_stat(&fscache_n_store_vmscan_busy);
++ fscache_stat_unchecked(&fscache_n_store_vmscan_busy);
+ return false;
+ }
+ EXPORT_SYMBOL(__fscache_maybe_release_page);
+@@ -131,7 +131,7 @@ static void fscache_end_page_write(struc
+ FSCACHE_COOKIE_STORING_TAG);
+ if (!radix_tree_tag_get(&cookie->stores, page->index,
+ FSCACHE_COOKIE_PENDING_TAG)) {
+- fscache_stat(&fscache_n_store_radix_deletes);
++ fscache_stat_unchecked(&fscache_n_store_radix_deletes);
+ xpage = radix_tree_delete(&cookie->stores, page->index);
+ }
+ spin_unlock(&cookie->stores_lock);
+@@ -152,7 +152,7 @@ static void fscache_attr_changed_op(stru
+
+ _enter("{OBJ%x OP%x}", object->debug_id, op->debug_id);
+
+- fscache_stat(&fscache_n_attr_changed_calls);
++ fscache_stat_unchecked(&fscache_n_attr_changed_calls);
+
+ if (fscache_object_is_active(object)) {
+ fscache_set_op_state(op, "CallFS");
+@@ -179,11 +179,11 @@ int __fscache_attr_changed(struct fscach
+
+ ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
+
+- fscache_stat(&fscache_n_attr_changed);
++ fscache_stat_unchecked(&fscache_n_attr_changed);
+
+ op = kzalloc(sizeof(*op), GFP_KERNEL);
+ if (!op) {
+- fscache_stat(&fscache_n_attr_changed_nomem);
++ fscache_stat_unchecked(&fscache_n_attr_changed_nomem);
+ _leave(" = -ENOMEM");
+ return -ENOMEM;
+ }
+@@ -202,7 +202,7 @@ int __fscache_attr_changed(struct fscach
+ if (fscache_submit_exclusive_op(object, op) < 0)
+ goto nobufs;
+ spin_unlock(&cookie->lock);
+- fscache_stat(&fscache_n_attr_changed_ok);
++ fscache_stat_unchecked(&fscache_n_attr_changed_ok);
+ fscache_put_operation(op);
+ _leave(" = 0");
+ return 0;
+@@ -210,7 +210,7 @@ int __fscache_attr_changed(struct fscach
+ nobufs:
+ spin_unlock(&cookie->lock);
+ kfree(op);
+- fscache_stat(&fscache_n_attr_changed_nobufs);
++ fscache_stat_unchecked(&fscache_n_attr_changed_nobufs);
+ _leave(" = %d", -ENOBUFS);
+ return -ENOBUFS;
+ }
+@@ -246,7 +246,7 @@ static struct fscache_retrieval *fscache
+ /* allocate a retrieval operation and attempt to submit it */
+ op = kzalloc(sizeof(*op), GFP_NOIO);
+ if (!op) {
+- fscache_stat(&fscache_n_retrievals_nomem);
++ fscache_stat_unchecked(&fscache_n_retrievals_nomem);
+ return NULL;
+ }
+
+@@ -275,13 +275,13 @@ static int fscache_wait_for_deferred_loo
+ return 0;
+ }
+
+- fscache_stat(&fscache_n_retrievals_wait);
++ fscache_stat_unchecked(&fscache_n_retrievals_wait);
+
+ jif = jiffies;
+ if (wait_on_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP,
+ fscache_wait_bit_interruptible,
+ TASK_INTERRUPTIBLE) != 0) {
+- fscache_stat(&fscache_n_retrievals_intr);
++ fscache_stat_unchecked(&fscache_n_retrievals_intr);
+ _leave(" = -ERESTARTSYS");
+ return -ERESTARTSYS;
+ }
+@@ -299,8 +299,8 @@ static int fscache_wait_for_deferred_loo
+ */
+ static int fscache_wait_for_retrieval_activation(struct fscache_object *object,
+ struct fscache_retrieval *op,
+- atomic_t *stat_op_waits,
+- atomic_t *stat_object_dead)
++ atomic_unchecked_t *stat_op_waits,
++ atomic_unchecked_t *stat_object_dead)
+ {
+ int ret;
+
+@@ -308,7 +308,7 @@ static int fscache_wait_for_retrieval_ac
+ goto check_if_dead;
+
+ _debug(">>> WT");
+- fscache_stat(stat_op_waits);
++ fscache_stat_unchecked(stat_op_waits);
+ if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
+ fscache_wait_bit_interruptible,
+ TASK_INTERRUPTIBLE) < 0) {
+@@ -325,7 +325,7 @@ static int fscache_wait_for_retrieval_ac
+
+ check_if_dead:
+ if (unlikely(fscache_object_is_dead(object))) {
+- fscache_stat(stat_object_dead);
++ fscache_stat_unchecked(stat_object_dead);
+ return -ENOBUFS;
+ }
+ return 0;
+@@ -352,7 +352,7 @@ int __fscache_read_or_alloc_page(struct
+
+ _enter("%p,%p,,,", cookie, page);
+
+- fscache_stat(&fscache_n_retrievals);
++ fscache_stat_unchecked(&fscache_n_retrievals);
+
+ if (hlist_empty(&cookie->backing_objects))
+ goto nobufs;
+@@ -386,7 +386,7 @@ int __fscache_read_or_alloc_page(struct
+ goto nobufs_unlock;
+ spin_unlock(&cookie->lock);
+
+- fscache_stat(&fscache_n_retrieval_ops);
++ fscache_stat_unchecked(&fscache_n_retrieval_ops);
+
+ /* pin the netfs read context in case we need to do the actual netfs
+ * read because we've encountered a cache read failure */
+@@ -416,15 +416,15 @@ int __fscache_read_or_alloc_page(struct
+
+ error:
+ if (ret == -ENOMEM)
+- fscache_stat(&fscache_n_retrievals_nomem);
++ fscache_stat_unchecked(&fscache_n_retrievals_nomem);
+ else if (ret == -ERESTARTSYS)
+- fscache_stat(&fscache_n_retrievals_intr);
++ fscache_stat_unchecked(&fscache_n_retrievals_intr);
+ else if (ret == -ENODATA)
+- fscache_stat(&fscache_n_retrievals_nodata);
++ fscache_stat_unchecked(&fscache_n_retrievals_nodata);
+ else if (ret < 0)
+- fscache_stat(&fscache_n_retrievals_nobufs);
++ fscache_stat_unchecked(&fscache_n_retrievals_nobufs);
+ else
+- fscache_stat(&fscache_n_retrievals_ok);
++ fscache_stat_unchecked(&fscache_n_retrievals_ok);
+
+ fscache_put_retrieval(op);
+ _leave(" = %d", ret);
+@@ -434,7 +434,7 @@ nobufs_unlock:
+ spin_unlock(&cookie->lock);
+ kfree(op);
+ nobufs:
+- fscache_stat(&fscache_n_retrievals_nobufs);
++ fscache_stat_unchecked(&fscache_n_retrievals_nobufs);
+ _leave(" = -ENOBUFS");
+ return -ENOBUFS;
+ }
+@@ -472,7 +472,7 @@ int __fscache_read_or_alloc_pages(struct
+
+ _enter("%p,,%d,,,", cookie, *nr_pages);
+
+- fscache_stat(&fscache_n_retrievals);
++ fscache_stat_unchecked(&fscache_n_retrievals);
+
+ if (hlist_empty(&cookie->backing_objects))
+ goto nobufs;
+@@ -503,7 +503,7 @@ int __fscache_read_or_alloc_pages(struct
+ goto nobufs_unlock;
+ spin_unlock(&cookie->lock);
+
+- fscache_stat(&fscache_n_retrieval_ops);
++ fscache_stat_unchecked(&fscache_n_retrieval_ops);
+
+ /* pin the netfs read context in case we need to do the actual netfs
+ * read because we've encountered a cache read failure */
+@@ -533,15 +533,15 @@ int __fscache_read_or_alloc_pages(struct
+
+ error:
+ if (ret == -ENOMEM)
+- fscache_stat(&fscache_n_retrievals_nomem);
++ fscache_stat_unchecked(&fscache_n_retrievals_nomem);
+ else if (ret == -ERESTARTSYS)
+- fscache_stat(&fscache_n_retrievals_intr);
++ fscache_stat_unchecked(&fscache_n_retrievals_intr);
+ else if (ret == -ENODATA)
+- fscache_stat(&fscache_n_retrievals_nodata);
++ fscache_stat_unchecked(&fscache_n_retrievals_nodata);
+ else if (ret < 0)
+- fscache_stat(&fscache_n_retrievals_nobufs);
++ fscache_stat_unchecked(&fscache_n_retrievals_nobufs);
+ else
+- fscache_stat(&fscache_n_retrievals_ok);
++ fscache_stat_unchecked(&fscache_n_retrievals_ok);
+
+ fscache_put_retrieval(op);
+ _leave(" = %d", ret);
+@@ -551,7 +551,7 @@ nobufs_unlock:
+ spin_unlock(&cookie->lock);
+ kfree(op);
+ nobufs:
+- fscache_stat(&fscache_n_retrievals_nobufs);
++ fscache_stat_unchecked(&fscache_n_retrievals_nobufs);
+ _leave(" = -ENOBUFS");
+ return -ENOBUFS;
+ }
+@@ -575,7 +575,7 @@ int __fscache_alloc_page(struct fscache_
+
+ _enter("%p,%p,,,", cookie, page);
+
+- fscache_stat(&fscache_n_allocs);
++ fscache_stat_unchecked(&fscache_n_allocs);
+
+ if (hlist_empty(&cookie->backing_objects))
+ goto nobufs;
+@@ -602,7 +602,7 @@ int __fscache_alloc_page(struct fscache_
+ goto nobufs_unlock;
+ spin_unlock(&cookie->lock);
+
+- fscache_stat(&fscache_n_alloc_ops);
++ fscache_stat_unchecked(&fscache_n_alloc_ops);
+
+ ret = fscache_wait_for_retrieval_activation(
+ object, op,
+@@ -618,11 +618,11 @@ int __fscache_alloc_page(struct fscache_
+
+ error:
+ if (ret == -ERESTARTSYS)
+- fscache_stat(&fscache_n_allocs_intr);
++ fscache_stat_unchecked(&fscache_n_allocs_intr);
+ else if (ret < 0)
+- fscache_stat(&fscache_n_allocs_nobufs);
++ fscache_stat_unchecked(&fscache_n_allocs_nobufs);
+ else
+- fscache_stat(&fscache_n_allocs_ok);
++ fscache_stat_unchecked(&fscache_n_allocs_ok);
+
+ fscache_put_retrieval(op);
+ _leave(" = %d", ret);
+@@ -632,7 +632,7 @@ nobufs_unlock:
+ spin_unlock(&cookie->lock);
+ kfree(op);
+ nobufs:
+- fscache_stat(&fscache_n_allocs_nobufs);
++ fscache_stat_unchecked(&fscache_n_allocs_nobufs);
+ _leave(" = -ENOBUFS");
+ return -ENOBUFS;
+ }
+@@ -675,7 +675,7 @@ static void fscache_write_op(struct fsca
+
+ spin_lock(&cookie->stores_lock);
+
+- fscache_stat(&fscache_n_store_calls);
++ fscache_stat_unchecked(&fscache_n_store_calls);
+
+ /* find a page to store */
+ page = NULL;
+@@ -686,7 +686,7 @@ static void fscache_write_op(struct fsca
+ page = results[0];
+ _debug("gang %d [%lx]", n, page->index);
+ if (page->index > op->store_limit) {
+- fscache_stat(&fscache_n_store_pages_over_limit);
++ fscache_stat_unchecked(&fscache_n_store_pages_over_limit);
+ goto superseded;
+ }
+
+@@ -699,7 +699,7 @@ static void fscache_write_op(struct fsca
+ spin_unlock(&object->lock);
+
+ fscache_set_op_state(&op->op, "Store");
+- fscache_stat(&fscache_n_store_pages);
++ fscache_stat_unchecked(&fscache_n_store_pages);
+ fscache_stat(&fscache_n_cop_write_page);
+ ret = object->cache->ops->write_page(op, page);
+ fscache_stat_d(&fscache_n_cop_write_page);
+@@ -769,7 +769,7 @@ int __fscache_write_page(struct fscache_
+ ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
+ ASSERT(PageFsCache(page));
+
+- fscache_stat(&fscache_n_stores);
++ fscache_stat_unchecked(&fscache_n_stores);
+
+ op = kzalloc(sizeof(*op), GFP_NOIO);
+ if (!op)
+@@ -821,7 +821,7 @@ int __fscache_write_page(struct fscache_
+ spin_unlock(&cookie->stores_lock);
+ spin_unlock(&object->lock);
+
+- op->op.debug_id = atomic_inc_return(&fscache_op_debug_id);
++ op->op.debug_id = atomic_inc_return_unchecked(&fscache_op_debug_id);
+ op->store_limit = object->store_limit;
+
+ if (fscache_submit_op(object, &op->op) < 0)
+@@ -829,8 +829,8 @@ int __fscache_write_page(struct fscache_
+
+ spin_unlock(&cookie->lock);
+ radix_tree_preload_end();
+- fscache_stat(&fscache_n_store_ops);
+- fscache_stat(&fscache_n_stores_ok);
++ fscache_stat_unchecked(&fscache_n_store_ops);
++ fscache_stat_unchecked(&fscache_n_stores_ok);
+
+ /* the work queue now carries its own ref on the object */
+ fscache_put_operation(&op->op);
+@@ -838,14 +838,14 @@ int __fscache_write_page(struct fscache_
+ return 0;
+
+ already_queued:
+- fscache_stat(&fscache_n_stores_again);
++ fscache_stat_unchecked(&fscache_n_stores_again);
+ already_pending:
+ spin_unlock(&cookie->stores_lock);
+ spin_unlock(&object->lock);
+ spin_unlock(&cookie->lock);
+ radix_tree_preload_end();
+ kfree(op);
+- fscache_stat(&fscache_n_stores_ok);
++ fscache_stat_unchecked(&fscache_n_stores_ok);
+ _leave(" = 0");
+ return 0;
+
+@@ -864,14 +864,14 @@ nobufs:
+ spin_unlock(&cookie->lock);
+ radix_tree_preload_end();
+ kfree(op);
+- fscache_stat(&fscache_n_stores_nobufs);
++ fscache_stat_unchecked(&fscache_n_stores_nobufs);
+ _leave(" = -ENOBUFS");
+ return -ENOBUFS;
+
+ nomem_free:
+ kfree(op);
+ nomem:
+- fscache_stat(&fscache_n_stores_oom);
++ fscache_stat_unchecked(&fscache_n_stores_oom);
+ _leave(" = -ENOMEM");
+ return -ENOMEM;
+ }
+@@ -889,7 +889,7 @@ void __fscache_uncache_page(struct fscac
+ ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
+ ASSERTCMP(page, !=, NULL);
+
+- fscache_stat(&fscache_n_uncaches);
++ fscache_stat_unchecked(&fscache_n_uncaches);
+
+ /* cache withdrawal may beat us to it */
+ if (!PageFsCache(page))
+@@ -942,7 +942,7 @@ void fscache_mark_pages_cached(struct fs
+ unsigned long loop;
+
+ #ifdef CONFIG_FSCACHE_STATS
+- atomic_add(pagevec->nr, &fscache_n_marks);
++ atomic_add_unchecked(pagevec->nr, &fscache_n_marks);
+ #endif
+
+ for (loop = 0; loop < pagevec->nr; loop++) {
+diff -urNp linux-2.6.38.7/fs/fscache/stats.c linux-2.6.38.7/fs/fscache/stats.c
+--- linux-2.6.38.7/fs/fscache/stats.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fscache/stats.c 2011-04-28 19:57:25.000000000 -0400
+@@ -18,95 +18,95 @@
+ /*
+ * operation counters
+ */
+-atomic_t fscache_n_op_pend;
+-atomic_t fscache_n_op_run;
+-atomic_t fscache_n_op_enqueue;
+-atomic_t fscache_n_op_requeue;
+-atomic_t fscache_n_op_deferred_release;
+-atomic_t fscache_n_op_release;
+-atomic_t fscache_n_op_gc;
+-atomic_t fscache_n_op_cancelled;
+-atomic_t fscache_n_op_rejected;
+-
+-atomic_t fscache_n_attr_changed;
+-atomic_t fscache_n_attr_changed_ok;
+-atomic_t fscache_n_attr_changed_nobufs;
+-atomic_t fscache_n_attr_changed_nomem;
+-atomic_t fscache_n_attr_changed_calls;
+-
+-atomic_t fscache_n_allocs;
+-atomic_t fscache_n_allocs_ok;
+-atomic_t fscache_n_allocs_wait;
+-atomic_t fscache_n_allocs_nobufs;
+-atomic_t fscache_n_allocs_intr;
+-atomic_t fscache_n_allocs_object_dead;
+-atomic_t fscache_n_alloc_ops;
+-atomic_t fscache_n_alloc_op_waits;
+-
+-atomic_t fscache_n_retrievals;
+-atomic_t fscache_n_retrievals_ok;
+-atomic_t fscache_n_retrievals_wait;
+-atomic_t fscache_n_retrievals_nodata;
+-atomic_t fscache_n_retrievals_nobufs;
+-atomic_t fscache_n_retrievals_intr;
+-atomic_t fscache_n_retrievals_nomem;
+-atomic_t fscache_n_retrievals_object_dead;
+-atomic_t fscache_n_retrieval_ops;
+-atomic_t fscache_n_retrieval_op_waits;
+-
+-atomic_t fscache_n_stores;
+-atomic_t fscache_n_stores_ok;
+-atomic_t fscache_n_stores_again;
+-atomic_t fscache_n_stores_nobufs;
+-atomic_t fscache_n_stores_oom;
+-atomic_t fscache_n_store_ops;
+-atomic_t fscache_n_store_calls;
+-atomic_t fscache_n_store_pages;
+-atomic_t fscache_n_store_radix_deletes;
+-atomic_t fscache_n_store_pages_over_limit;
+-
+-atomic_t fscache_n_store_vmscan_not_storing;
+-atomic_t fscache_n_store_vmscan_gone;
+-atomic_t fscache_n_store_vmscan_busy;
+-atomic_t fscache_n_store_vmscan_cancelled;
+-
+-atomic_t fscache_n_marks;
+-atomic_t fscache_n_uncaches;
+-
+-atomic_t fscache_n_acquires;
+-atomic_t fscache_n_acquires_null;
+-atomic_t fscache_n_acquires_no_cache;
+-atomic_t fscache_n_acquires_ok;
+-atomic_t fscache_n_acquires_nobufs;
+-atomic_t fscache_n_acquires_oom;
+-
+-atomic_t fscache_n_updates;
+-atomic_t fscache_n_updates_null;
+-atomic_t fscache_n_updates_run;
+-
+-atomic_t fscache_n_relinquishes;
+-atomic_t fscache_n_relinquishes_null;
+-atomic_t fscache_n_relinquishes_waitcrt;
+-atomic_t fscache_n_relinquishes_retire;
+-
+-atomic_t fscache_n_cookie_index;
+-atomic_t fscache_n_cookie_data;
+-atomic_t fscache_n_cookie_special;
+-
+-atomic_t fscache_n_object_alloc;
+-atomic_t fscache_n_object_no_alloc;
+-atomic_t fscache_n_object_lookups;
+-atomic_t fscache_n_object_lookups_negative;
+-atomic_t fscache_n_object_lookups_positive;
+-atomic_t fscache_n_object_lookups_timed_out;
+-atomic_t fscache_n_object_created;
+-atomic_t fscache_n_object_avail;
+-atomic_t fscache_n_object_dead;
+-
+-atomic_t fscache_n_checkaux_none;
+-atomic_t fscache_n_checkaux_okay;
+-atomic_t fscache_n_checkaux_update;
+-atomic_t fscache_n_checkaux_obsolete;
++atomic_unchecked_t fscache_n_op_pend;
++atomic_unchecked_t fscache_n_op_run;
++atomic_unchecked_t fscache_n_op_enqueue;
++atomic_unchecked_t fscache_n_op_requeue;
++atomic_unchecked_t fscache_n_op_deferred_release;
++atomic_unchecked_t fscache_n_op_release;
++atomic_unchecked_t fscache_n_op_gc;
++atomic_unchecked_t fscache_n_op_cancelled;
++atomic_unchecked_t fscache_n_op_rejected;
++
++atomic_unchecked_t fscache_n_attr_changed;
++atomic_unchecked_t fscache_n_attr_changed_ok;
++atomic_unchecked_t fscache_n_attr_changed_nobufs;
++atomic_unchecked_t fscache_n_attr_changed_nomem;
++atomic_unchecked_t fscache_n_attr_changed_calls;
++
++atomic_unchecked_t fscache_n_allocs;
++atomic_unchecked_t fscache_n_allocs_ok;
++atomic_unchecked_t fscache_n_allocs_wait;
++atomic_unchecked_t fscache_n_allocs_nobufs;
++atomic_unchecked_t fscache_n_allocs_intr;
++atomic_unchecked_t fscache_n_allocs_object_dead;
++atomic_unchecked_t fscache_n_alloc_ops;
++atomic_unchecked_t fscache_n_alloc_op_waits;
++
++atomic_unchecked_t fscache_n_retrievals;
++atomic_unchecked_t fscache_n_retrievals_ok;
++atomic_unchecked_t fscache_n_retrievals_wait;
++atomic_unchecked_t fscache_n_retrievals_nodata;
++atomic_unchecked_t fscache_n_retrievals_nobufs;
++atomic_unchecked_t fscache_n_retrievals_intr;
++atomic_unchecked_t fscache_n_retrievals_nomem;
++atomic_unchecked_t fscache_n_retrievals_object_dead;
++atomic_unchecked_t fscache_n_retrieval_ops;
++atomic_unchecked_t fscache_n_retrieval_op_waits;
++
++atomic_unchecked_t fscache_n_stores;
++atomic_unchecked_t fscache_n_stores_ok;
++atomic_unchecked_t fscache_n_stores_again;
++atomic_unchecked_t fscache_n_stores_nobufs;
++atomic_unchecked_t fscache_n_stores_oom;
++atomic_unchecked_t fscache_n_store_ops;
++atomic_unchecked_t fscache_n_store_calls;
++atomic_unchecked_t fscache_n_store_pages;
++atomic_unchecked_t fscache_n_store_radix_deletes;
++atomic_unchecked_t fscache_n_store_pages_over_limit;
++
++atomic_unchecked_t fscache_n_store_vmscan_not_storing;
++atomic_unchecked_t fscache_n_store_vmscan_gone;
++atomic_unchecked_t fscache_n_store_vmscan_busy;
++atomic_unchecked_t fscache_n_store_vmscan_cancelled;
++
++atomic_unchecked_t fscache_n_marks;
++atomic_unchecked_t fscache_n_uncaches;
++
++atomic_unchecked_t fscache_n_acquires;
++atomic_unchecked_t fscache_n_acquires_null;
++atomic_unchecked_t fscache_n_acquires_no_cache;
++atomic_unchecked_t fscache_n_acquires_ok;
++atomic_unchecked_t fscache_n_acquires_nobufs;
++atomic_unchecked_t fscache_n_acquires_oom;
++
++atomic_unchecked_t fscache_n_updates;
++atomic_unchecked_t fscache_n_updates_null;
++atomic_unchecked_t fscache_n_updates_run;
++
++atomic_unchecked_t fscache_n_relinquishes;
++atomic_unchecked_t fscache_n_relinquishes_null;
++atomic_unchecked_t fscache_n_relinquishes_waitcrt;
++atomic_unchecked_t fscache_n_relinquishes_retire;
++
++atomic_unchecked_t fscache_n_cookie_index;
++atomic_unchecked_t fscache_n_cookie_data;
++atomic_unchecked_t fscache_n_cookie_special;
++
++atomic_unchecked_t fscache_n_object_alloc;
++atomic_unchecked_t fscache_n_object_no_alloc;
++atomic_unchecked_t fscache_n_object_lookups;
++atomic_unchecked_t fscache_n_object_lookups_negative;
++atomic_unchecked_t fscache_n_object_lookups_positive;
++atomic_unchecked_t fscache_n_object_lookups_timed_out;
++atomic_unchecked_t fscache_n_object_created;
++atomic_unchecked_t fscache_n_object_avail;
++atomic_unchecked_t fscache_n_object_dead;
++
++atomic_unchecked_t fscache_n_checkaux_none;
++atomic_unchecked_t fscache_n_checkaux_okay;
++atomic_unchecked_t fscache_n_checkaux_update;
++atomic_unchecked_t fscache_n_checkaux_obsolete;
+
+ atomic_t fscache_n_cop_alloc_object;
+ atomic_t fscache_n_cop_lookup_object;
+@@ -133,113 +133,113 @@ static int fscache_stats_show(struct seq
+ seq_puts(m, "FS-Cache statistics\n");
+
+ seq_printf(m, "Cookies: idx=%u dat=%u spc=%u\n",
+- atomic_read(&fscache_n_cookie_index),
+- atomic_read(&fscache_n_cookie_data),
+- atomic_read(&fscache_n_cookie_special));
++ atomic_read_unchecked(&fscache_n_cookie_index),
++ atomic_read_unchecked(&fscache_n_cookie_data),
++ atomic_read_unchecked(&fscache_n_cookie_special));
+
+ seq_printf(m, "Objects: alc=%u nal=%u avl=%u ded=%u\n",
+- atomic_read(&fscache_n_object_alloc),
+- atomic_read(&fscache_n_object_no_alloc),
+- atomic_read(&fscache_n_object_avail),
+- atomic_read(&fscache_n_object_dead));
++ atomic_read_unchecked(&fscache_n_object_alloc),
++ atomic_read_unchecked(&fscache_n_object_no_alloc),
++ atomic_read_unchecked(&fscache_n_object_avail),
++ atomic_read_unchecked(&fscache_n_object_dead));
+ seq_printf(m, "ChkAux : non=%u ok=%u upd=%u obs=%u\n",
+- atomic_read(&fscache_n_checkaux_none),
+- atomic_read(&fscache_n_checkaux_okay),
+- atomic_read(&fscache_n_checkaux_update),
+- atomic_read(&fscache_n_checkaux_obsolete));
++ atomic_read_unchecked(&fscache_n_checkaux_none),
++ atomic_read_unchecked(&fscache_n_checkaux_okay),
++ atomic_read_unchecked(&fscache_n_checkaux_update),
++ atomic_read_unchecked(&fscache_n_checkaux_obsolete));
+
+ seq_printf(m, "Pages : mrk=%u unc=%u\n",
+- atomic_read(&fscache_n_marks),
+- atomic_read(&fscache_n_uncaches));
++ atomic_read_unchecked(&fscache_n_marks),
++ atomic_read_unchecked(&fscache_n_uncaches));
+
+ seq_printf(m, "Acquire: n=%u nul=%u noc=%u ok=%u nbf=%u"
+ " oom=%u\n",
+- atomic_read(&fscache_n_acquires),
+- atomic_read(&fscache_n_acquires_null),
+- atomic_read(&fscache_n_acquires_no_cache),
+- atomic_read(&fscache_n_acquires_ok),
+- atomic_read(&fscache_n_acquires_nobufs),
+- atomic_read(&fscache_n_acquires_oom));
++ atomic_read_unchecked(&fscache_n_acquires),
++ atomic_read_unchecked(&fscache_n_acquires_null),
++ atomic_read_unchecked(&fscache_n_acquires_no_cache),
++ atomic_read_unchecked(&fscache_n_acquires_ok),
++ atomic_read_unchecked(&fscache_n_acquires_nobufs),
++ atomic_read_unchecked(&fscache_n_acquires_oom));
+
+ seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u tmo=%u\n",
+- atomic_read(&fscache_n_object_lookups),
+- atomic_read(&fscache_n_object_lookups_negative),
+- atomic_read(&fscache_n_object_lookups_positive),
+- atomic_read(&fscache_n_object_created),
+- atomic_read(&fscache_n_object_lookups_timed_out));
++ atomic_read_unchecked(&fscache_n_object_lookups),
++ atomic_read_unchecked(&fscache_n_object_lookups_negative),
++ atomic_read_unchecked(&fscache_n_object_lookups_positive),
++ atomic_read_unchecked(&fscache_n_object_created),
++ atomic_read_unchecked(&fscache_n_object_lookups_timed_out));
+
+ seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
+- atomic_read(&fscache_n_updates),
+- atomic_read(&fscache_n_updates_null),
+- atomic_read(&fscache_n_updates_run));
++ atomic_read_unchecked(&fscache_n_updates),
++ atomic_read_unchecked(&fscache_n_updates_null),
++ atomic_read_unchecked(&fscache_n_updates_run));
+
+ seq_printf(m, "Relinqs: n=%u nul=%u wcr=%u rtr=%u\n",
+- atomic_read(&fscache_n_relinquishes),
+- atomic_read(&fscache_n_relinquishes_null),
+- atomic_read(&fscache_n_relinquishes_waitcrt),
+- atomic_read(&fscache_n_relinquishes_retire));
++ atomic_read_unchecked(&fscache_n_relinquishes),
++ atomic_read_unchecked(&fscache_n_relinquishes_null),
++ atomic_read_unchecked(&fscache_n_relinquishes_waitcrt),
++ atomic_read_unchecked(&fscache_n_relinquishes_retire));
+
+ seq_printf(m, "AttrChg: n=%u ok=%u nbf=%u oom=%u run=%u\n",
+- atomic_read(&fscache_n_attr_changed),
+- atomic_read(&fscache_n_attr_changed_ok),
+- atomic_read(&fscache_n_attr_changed_nobufs),
+- atomic_read(&fscache_n_attr_changed_nomem),
+- atomic_read(&fscache_n_attr_changed_calls));
++ atomic_read_unchecked(&fscache_n_attr_changed),
++ atomic_read_unchecked(&fscache_n_attr_changed_ok),
++ atomic_read_unchecked(&fscache_n_attr_changed_nobufs),
++ atomic_read_unchecked(&fscache_n_attr_changed_nomem),
++ atomic_read_unchecked(&fscache_n_attr_changed_calls));
+
+ seq_printf(m, "Allocs : n=%u ok=%u wt=%u nbf=%u int=%u\n",
+- atomic_read(&fscache_n_allocs),
+- atomic_read(&fscache_n_allocs_ok),
+- atomic_read(&fscache_n_allocs_wait),
+- atomic_read(&fscache_n_allocs_nobufs),
+- atomic_read(&fscache_n_allocs_intr));
++ atomic_read_unchecked(&fscache_n_allocs),
++ atomic_read_unchecked(&fscache_n_allocs_ok),
++ atomic_read_unchecked(&fscache_n_allocs_wait),
++ atomic_read_unchecked(&fscache_n_allocs_nobufs),
++ atomic_read_unchecked(&fscache_n_allocs_intr));
+ seq_printf(m, "Allocs : ops=%u owt=%u abt=%u\n",
+- atomic_read(&fscache_n_alloc_ops),
+- atomic_read(&fscache_n_alloc_op_waits),
+- atomic_read(&fscache_n_allocs_object_dead));
++ atomic_read_unchecked(&fscache_n_alloc_ops),
++ atomic_read_unchecked(&fscache_n_alloc_op_waits),
++ atomic_read_unchecked(&fscache_n_allocs_object_dead));
+
+ seq_printf(m, "Retrvls: n=%u ok=%u wt=%u nod=%u nbf=%u"
+ " int=%u oom=%u\n",
+- atomic_read(&fscache_n_retrievals),
+- atomic_read(&fscache_n_retrievals_ok),
+- atomic_read(&fscache_n_retrievals_wait),
+- atomic_read(&fscache_n_retrievals_nodata),
+- atomic_read(&fscache_n_retrievals_nobufs),
+- atomic_read(&fscache_n_retrievals_intr),
+- atomic_read(&fscache_n_retrievals_nomem));
++ atomic_read_unchecked(&fscache_n_retrievals),
++ atomic_read_unchecked(&fscache_n_retrievals_ok),
++ atomic_read_unchecked(&fscache_n_retrievals_wait),
++ atomic_read_unchecked(&fscache_n_retrievals_nodata),
++ atomic_read_unchecked(&fscache_n_retrievals_nobufs),
++ atomic_read_unchecked(&fscache_n_retrievals_intr),
++ atomic_read_unchecked(&fscache_n_retrievals_nomem));
+ seq_printf(m, "Retrvls: ops=%u owt=%u abt=%u\n",
+- atomic_read(&fscache_n_retrieval_ops),
+- atomic_read(&fscache_n_retrieval_op_waits),
+- atomic_read(&fscache_n_retrievals_object_dead));
++ atomic_read_unchecked(&fscache_n_retrieval_ops),
++ atomic_read_unchecked(&fscache_n_retrieval_op_waits),
++ atomic_read_unchecked(&fscache_n_retrievals_object_dead));
+
+ seq_printf(m, "Stores : n=%u ok=%u agn=%u nbf=%u oom=%u\n",
+- atomic_read(&fscache_n_stores),
+- atomic_read(&fscache_n_stores_ok),
+- atomic_read(&fscache_n_stores_again),
+- atomic_read(&fscache_n_stores_nobufs),
+- atomic_read(&fscache_n_stores_oom));
++ atomic_read_unchecked(&fscache_n_stores),
++ atomic_read_unchecked(&fscache_n_stores_ok),
++ atomic_read_unchecked(&fscache_n_stores_again),
++ atomic_read_unchecked(&fscache_n_stores_nobufs),
++ atomic_read_unchecked(&fscache_n_stores_oom));
+ seq_printf(m, "Stores : ops=%u run=%u pgs=%u rxd=%u olm=%u\n",
+- atomic_read(&fscache_n_store_ops),
+- atomic_read(&fscache_n_store_calls),
+- atomic_read(&fscache_n_store_pages),
+- atomic_read(&fscache_n_store_radix_deletes),
+- atomic_read(&fscache_n_store_pages_over_limit));
++ atomic_read_unchecked(&fscache_n_store_ops),
++ atomic_read_unchecked(&fscache_n_store_calls),
++ atomic_read_unchecked(&fscache_n_store_pages),
++ atomic_read_unchecked(&fscache_n_store_radix_deletes),
++ atomic_read_unchecked(&fscache_n_store_pages_over_limit));
+
+ seq_printf(m, "VmScan : nos=%u gon=%u bsy=%u can=%u\n",
+- atomic_read(&fscache_n_store_vmscan_not_storing),
+- atomic_read(&fscache_n_store_vmscan_gone),
+- atomic_read(&fscache_n_store_vmscan_busy),
+- atomic_read(&fscache_n_store_vmscan_cancelled));
++ atomic_read_unchecked(&fscache_n_store_vmscan_not_storing),
++ atomic_read_unchecked(&fscache_n_store_vmscan_gone),
++ atomic_read_unchecked(&fscache_n_store_vmscan_busy),
++ atomic_read_unchecked(&fscache_n_store_vmscan_cancelled));
+
+ seq_printf(m, "Ops : pend=%u run=%u enq=%u can=%u rej=%u\n",
+- atomic_read(&fscache_n_op_pend),
+- atomic_read(&fscache_n_op_run),
+- atomic_read(&fscache_n_op_enqueue),
+- atomic_read(&fscache_n_op_cancelled),
+- atomic_read(&fscache_n_op_rejected));
++ atomic_read_unchecked(&fscache_n_op_pend),
++ atomic_read_unchecked(&fscache_n_op_run),
++ atomic_read_unchecked(&fscache_n_op_enqueue),
++ atomic_read_unchecked(&fscache_n_op_cancelled),
++ atomic_read_unchecked(&fscache_n_op_rejected));
+ seq_printf(m, "Ops : dfr=%u rel=%u gc=%u\n",
+- atomic_read(&fscache_n_op_deferred_release),
+- atomic_read(&fscache_n_op_release),
+- atomic_read(&fscache_n_op_gc));
++ atomic_read_unchecked(&fscache_n_op_deferred_release),
++ atomic_read_unchecked(&fscache_n_op_release),
++ atomic_read_unchecked(&fscache_n_op_gc));
+
+ seq_printf(m, "CacheOp: alo=%d luo=%d luc=%d gro=%d\n",
+ atomic_read(&fscache_n_cop_alloc_object),
+diff -urNp linux-2.6.38.7/fs/fs_struct.c linux-2.6.38.7/fs/fs_struct.c
+--- linux-2.6.38.7/fs/fs_struct.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fs_struct.c 2011-04-28 19:34:15.000000000 -0400
+@@ -4,6 +4,7 @@
+ #include <linux/path.h>
+ #include <linux/slab.h>
+ #include <linux/fs_struct.h>
++#include <linux/grsecurity.h>
+ #include "internal.h"
+
+ static inline void path_get_longterm(struct path *path)
+@@ -31,6 +32,7 @@ void set_fs_root(struct fs_struct *fs, s
+ old_root = fs->root;
+ fs->root = *path;
+ path_get_longterm(path);
++ gr_set_chroot_entries(current, path);
+ write_seqcount_end(&fs->seq);
+ spin_unlock(&fs->lock);
+ if (old_root.dentry)
+@@ -74,6 +76,7 @@ void chroot_fs_refs(struct path *old_roo
+ && fs->root.mnt == old_root->mnt) {
+ path_get_longterm(new_root);
+ fs->root = *new_root;
++ gr_set_chroot_entries(p, new_root);
+ count++;
+ }
+ if (fs->pwd.dentry == old_root->dentry
+@@ -109,7 +112,8 @@ void exit_fs(struct task_struct *tsk)
+ spin_lock(&fs->lock);
+ write_seqcount_begin(&fs->seq);
+ tsk->fs = NULL;
+- kill = !--fs->users;
++ gr_clear_chroot_entries(tsk);
++ kill = !atomic_dec_return(&fs->users);
+ write_seqcount_end(&fs->seq);
+ spin_unlock(&fs->lock);
+ task_unlock(tsk);
+@@ -123,7 +127,7 @@ struct fs_struct *copy_fs_struct(struct
+ struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
+ /* We don't need to lock fs - think why ;-) */
+ if (fs) {
+- fs->users = 1;
++ atomic_set(&fs->users, 1);
+ fs->in_exec = 0;
+ spin_lock_init(&fs->lock);
+ seqcount_init(&fs->seq);
+@@ -132,6 +136,9 @@ struct fs_struct *copy_fs_struct(struct
+ spin_lock(&old->lock);
+ fs->root = old->root;
+ path_get_longterm(&fs->root);
++ /* instead of calling gr_set_chroot_entries here,
++ we call it from every caller of this function
++ */
+ fs->pwd = old->pwd;
+ path_get_longterm(&fs->pwd);
+ spin_unlock(&old->lock);
+@@ -150,8 +157,9 @@ int unshare_fs_struct(void)
+
+ task_lock(current);
+ spin_lock(&fs->lock);
+- kill = !--fs->users;
++ kill = !atomic_dec_return(&fs->users);
+ current->fs = new_fs;
++ gr_set_chroot_entries(current, &new_fs->root);
+ spin_unlock(&fs->lock);
+ task_unlock(current);
+
+@@ -170,7 +178,7 @@ EXPORT_SYMBOL(current_umask);
+
+ /* to be mentioned only in INIT_TASK */
+ struct fs_struct init_fs = {
+- .users = 1,
++ .users = ATOMIC_INIT(1),
+ .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock),
+ .seq = SEQCNT_ZERO,
+ .umask = 0022,
+@@ -186,12 +194,13 @@ void daemonize_fs_struct(void)
+ task_lock(current);
+
+ spin_lock(&init_fs.lock);
+- init_fs.users++;
++ atomic_inc(&init_fs.users);
+ spin_unlock(&init_fs.lock);
+
+ spin_lock(&fs->lock);
+ current->fs = &init_fs;
+- kill = !--fs->users;
++ gr_set_chroot_entries(current, &current->fs->root);
++ kill = !atomic_dec_return(&fs->users);
+ spin_unlock(&fs->lock);
+
+ task_unlock(current);
+diff -urNp linux-2.6.38.7/fs/fuse/cuse.c linux-2.6.38.7/fs/fuse/cuse.c
+--- linux-2.6.38.7/fs/fuse/cuse.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fuse/cuse.c 2011-04-28 19:34:15.000000000 -0400
+@@ -530,8 +530,18 @@ static int cuse_channel_release(struct i
+ return rc;
+ }
+
+-static struct file_operations cuse_channel_fops; /* initialized during init */
+-
++static const struct file_operations cuse_channel_fops = { /* initialized during init */
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .read = do_sync_read,
++ .aio_read = fuse_dev_read,
++ .write = do_sync_write,
++ .aio_write = fuse_dev_write,
++ .poll = fuse_dev_poll,
++ .open = cuse_channel_open,
++ .release = cuse_channel_release,
++ .fasync = fuse_dev_fasync,
++};
+
+ /**************************************************************************
+ * Misc stuff and module initializatiion
+@@ -577,12 +587,6 @@ static int __init cuse_init(void)
+ for (i = 0; i < CUSE_CONNTBL_LEN; i++)
+ INIT_LIST_HEAD(&cuse_conntbl[i]);
+
+- /* inherit and extend fuse_dev_operations */
+- cuse_channel_fops = fuse_dev_operations;
+- cuse_channel_fops.owner = THIS_MODULE;
+- cuse_channel_fops.open = cuse_channel_open;
+- cuse_channel_fops.release = cuse_channel_release;
+-
+ cuse_class = class_create(THIS_MODULE, "cuse");
+ if (IS_ERR(cuse_class))
+ return PTR_ERR(cuse_class);
+diff -urNp linux-2.6.38.7/fs/fuse/dev.c linux-2.6.38.7/fs/fuse/dev.c
+--- linux-2.6.38.7/fs/fuse/dev.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fuse/dev.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1183,7 +1183,7 @@ static ssize_t fuse_dev_do_read(struct f
+ return err;
+ }
+
+-static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
++ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+ {
+ struct fuse_copy_state cs;
+@@ -1197,6 +1197,8 @@ static ssize_t fuse_dev_read(struct kioc
+ return fuse_dev_do_read(fc, file, &cs, iov_length(iov, nr_segs));
+ }
+
++EXPORT_SYMBOL_GPL(fuse_dev_read);
++
+ static int fuse_dev_pipe_buf_steal(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+ {
+@@ -1240,7 +1242,7 @@ static ssize_t fuse_dev_splice_read(stru
+ ret = 0;
+ pipe_lock(pipe);
+
+- if (!pipe->readers) {
++ if (!atomic_read(&pipe->readers)) {
+ send_sig(SIGPIPE, current, 0);
+ if (!ret)
+ ret = -EPIPE;
+@@ -1733,7 +1735,7 @@ static ssize_t fuse_dev_do_write(struct
+ return err;
+ }
+
+-static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
++ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+ {
+ struct fuse_copy_state cs;
+@@ -1746,6 +1748,8 @@ static ssize_t fuse_dev_write(struct kio
+ return fuse_dev_do_write(fc, &cs, iov_length(iov, nr_segs));
+ }
+
++EXPORT_SYMBOL_GPL(fuse_dev_write);
++
+ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
+ struct file *out, loff_t *ppos,
+ size_t len, unsigned int flags)
+@@ -1824,7 +1828,7 @@ out:
+ return ret;
+ }
+
+-static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
++unsigned fuse_dev_poll(struct file *file, poll_table *wait)
+ {
+ unsigned mask = POLLOUT | POLLWRNORM;
+ struct fuse_conn *fc = fuse_get_conn(file);
+@@ -1843,6 +1847,8 @@ static unsigned fuse_dev_poll(struct fil
+ return mask;
+ }
+
++EXPORT_SYMBOL_GPL(fuse_dev_poll);
++
+ /*
+ * Abort all requests on the given list (pending or processing)
+ *
+@@ -1962,7 +1968,7 @@ int fuse_dev_release(struct inode *inode
+ }
+ EXPORT_SYMBOL_GPL(fuse_dev_release);
+
+-static int fuse_dev_fasync(int fd, struct file *file, int on)
++int fuse_dev_fasync(int fd, struct file *file, int on)
+ {
+ struct fuse_conn *fc = fuse_get_conn(file);
+ if (!fc)
+@@ -1972,6 +1978,8 @@ static int fuse_dev_fasync(int fd, struc
+ return fasync_helper(fd, file, on, &fc->fasync);
+ }
+
++EXPORT_SYMBOL_GPL(fuse_dev_fasync);
++
+ const struct file_operations fuse_dev_operations = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+diff -urNp linux-2.6.38.7/fs/fuse/dir.c linux-2.6.38.7/fs/fuse/dir.c
+--- linux-2.6.38.7/fs/fuse/dir.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fuse/dir.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1133,7 +1133,7 @@ static char *read_link(struct dentry *de
+ return link;
+ }
+
+-static void free_link(char *link)
++static void free_link(const char *link)
+ {
+ if (!IS_ERR(link))
+ free_page((unsigned long) link);
+diff -urNp linux-2.6.38.7/fs/fuse/fuse_i.h linux-2.6.38.7/fs/fuse/fuse_i.h
+--- linux-2.6.38.7/fs/fuse/fuse_i.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/fuse/fuse_i.h 2011-04-28 19:34:15.000000000 -0400
+@@ -541,6 +541,16 @@ extern const struct file_operations fuse
+
+ extern const struct dentry_operations fuse_dentry_operations;
+
++extern ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
++ unsigned long nr_segs, loff_t pos);
++
++extern ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
++ unsigned long nr_segs, loff_t pos);
++
++extern unsigned fuse_dev_poll(struct file *file, poll_table *wait);
++
++extern int fuse_dev_fasync(int fd, struct file *file, int on);
++
+ /**
+ * Inode to nodeid comparison.
+ */
+diff -urNp linux-2.6.38.7/fs/gfs2/ops_inode.c linux-2.6.38.7/fs/gfs2/ops_inode.c
+--- linux-2.6.38.7/fs/gfs2/ops_inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/gfs2/ops_inode.c 2011-05-16 21:47:08.000000000 -0400
+@@ -740,6 +740,8 @@ static int gfs2_rename(struct inode *odi
+ unsigned int x;
+ int error;
+
++ pax_track_stack();
++
+ if (ndentry->d_inode) {
+ nip = GFS2_I(ndentry->d_inode);
+ if (ip == nip)
+@@ -1019,7 +1021,7 @@ out:
+
+ static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+ {
+- char *s = nd_get_link(nd);
++ const char *s = nd_get_link(nd);
+ if (!IS_ERR(s))
+ kfree(s);
+ }
+diff -urNp linux-2.6.38.7/fs/hfsplus/catalog.c linux-2.6.38.7/fs/hfsplus/catalog.c
+--- linux-2.6.38.7/fs/hfsplus/catalog.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/hfsplus/catalog.c 2011-05-16 21:47:08.000000000 -0400
+@@ -179,6 +179,8 @@ int hfsplus_find_cat(struct super_block
+ int err;
+ u16 type;
+
++ pax_track_stack();
++
+ hfsplus_cat_build_key(sb, fd->search_key, cnid, NULL);
+ err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
+ if (err)
+@@ -210,6 +212,8 @@ int hfsplus_create_cat(u32 cnid, struct
+ int entry_size;
+ int err;
+
++ pax_track_stack();
++
+ dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n",
+ str->name, cnid, inode->i_nlink);
+ hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+@@ -349,6 +353,8 @@ int hfsplus_rename_cat(u32 cnid,
+ int entry_size, type;
+ int err = 0;
+
++ pax_track_stack();
++
+ dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n",
+ cnid, src_dir->i_ino, src_name->name,
+ dst_dir->i_ino, dst_name->name);
+diff -urNp linux-2.6.38.7/fs/hfsplus/dir.c linux-2.6.38.7/fs/hfsplus/dir.c
+--- linux-2.6.38.7/fs/hfsplus/dir.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/hfsplus/dir.c 2011-05-16 21:47:08.000000000 -0400
+@@ -129,6 +129,8 @@ static int hfsplus_readdir(struct file *
+ struct hfsplus_readdir_data *rd;
+ u16 type;
+
++ pax_track_stack();
++
+ if (filp->f_pos >= inode->i_size)
+ return 0;
+
+diff -urNp linux-2.6.38.7/fs/hfsplus/inode.c linux-2.6.38.7/fs/hfsplus/inode.c
+--- linux-2.6.38.7/fs/hfsplus/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/hfsplus/inode.c 2011-05-16 21:47:08.000000000 -0400
+@@ -491,6 +491,8 @@ int hfsplus_cat_read_inode(struct inode
+ int res = 0;
+ u16 type;
+
++ pax_track_stack();
++
+ type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
+
+ HFSPLUS_I(inode)->linkid = 0;
+@@ -554,6 +556,8 @@ int hfsplus_cat_write_inode(struct inode
+ struct hfs_find_data fd;
+ hfsplus_cat_entry entry;
+
++ pax_track_stack();
++
+ if (HFSPLUS_IS_RSRC(inode))
+ main_inode = HFSPLUS_I(inode)->rsrc_inode;
+
+diff -urNp linux-2.6.38.7/fs/hfsplus/ioctl.c linux-2.6.38.7/fs/hfsplus/ioctl.c
+--- linux-2.6.38.7/fs/hfsplus/ioctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/hfsplus/ioctl.c 2011-05-16 21:47:08.000000000 -0400
+@@ -122,6 +122,8 @@ int hfsplus_setxattr(struct dentry *dent
+ struct hfsplus_cat_file *file;
+ int res;
+
++ pax_track_stack();
++
+ if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
+ return -EOPNOTSUPP;
+
+@@ -166,6 +168,8 @@ ssize_t hfsplus_getxattr(struct dentry *
+ struct hfsplus_cat_file *file;
+ ssize_t res = 0;
+
++ pax_track_stack();
++
+ if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
+ return -EOPNOTSUPP;
+
+diff -urNp linux-2.6.38.7/fs/hfsplus/super.c linux-2.6.38.7/fs/hfsplus/super.c
+--- linux-2.6.38.7/fs/hfsplus/super.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/hfsplus/super.c 2011-05-16 21:47:08.000000000 -0400
+@@ -340,6 +340,8 @@ static int hfsplus_fill_super(struct sup
+ struct nls_table *nls = NULL;
+ int err;
+
++ pax_track_stack();
++
+ err = -EINVAL;
+ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+ if (!sbi)
+diff -urNp linux-2.6.38.7/fs/hugetlbfs/inode.c linux-2.6.38.7/fs/hugetlbfs/inode.c
+--- linux-2.6.38.7/fs/hugetlbfs/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/hugetlbfs/inode.c 2011-04-28 19:34:15.000000000 -0400
+@@ -915,7 +915,7 @@ static struct file_system_type hugetlbfs
+ .kill_sb = kill_litter_super,
+ };
+
+-static struct vfsmount *hugetlbfs_vfsmount;
++struct vfsmount *hugetlbfs_vfsmount;
+
+ static int can_do_hugetlb_shm(void)
+ {
+diff -urNp linux-2.6.38.7/fs/inode.c linux-2.6.38.7/fs/inode.c
+--- linux-2.6.38.7/fs/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/inode.c 2011-04-28 19:34:15.000000000 -0400
+@@ -801,8 +801,8 @@ unsigned int get_next_ino(void)
+
+ #ifdef CONFIG_SMP
+ if (unlikely((res & (LAST_INO_BATCH-1)) == 0)) {
+- static atomic_t shared_last_ino;
+- int next = atomic_add_return(LAST_INO_BATCH, &shared_last_ino);
++ static atomic_unchecked_t shared_last_ino;
++ int next = atomic_add_return_unchecked(LAST_INO_BATCH, &shared_last_ino);
+
+ res = next - LAST_INO_BATCH;
+ }
+diff -urNp linux-2.6.38.7/fs/jbd/checkpoint.c linux-2.6.38.7/fs/jbd/checkpoint.c
+--- linux-2.6.38.7/fs/jbd/checkpoint.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/jbd/checkpoint.c 2011-05-16 21:47:08.000000000 -0400
+@@ -350,6 +350,8 @@ int log_do_checkpoint(journal_t *journal
+ tid_t this_tid;
+ int result;
+
++ pax_track_stack();
++
+ jbd_debug(1, "Start checkpoint\n");
+
+ /*
+diff -urNp linux-2.6.38.7/fs/jffs2/compr_rtime.c linux-2.6.38.7/fs/jffs2/compr_rtime.c
+--- linux-2.6.38.7/fs/jffs2/compr_rtime.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/jffs2/compr_rtime.c 2011-05-16 21:47:08.000000000 -0400
+@@ -37,6 +37,8 @@ static int jffs2_rtime_compress(unsigned
+ int outpos = 0;
+ int pos=0;
+
++ pax_track_stack();
++
+ memset(positions,0,sizeof(positions));
+
+ while (pos < (*sourcelen) && outpos <= (*dstlen)-2) {
+@@ -78,6 +80,8 @@ static int jffs2_rtime_decompress(unsign
+ int outpos = 0;
+ int pos=0;
+
++ pax_track_stack();
++
+ memset(positions,0,sizeof(positions));
+
+ while (outpos<destlen) {
+diff -urNp linux-2.6.38.7/fs/jffs2/compr_rubin.c linux-2.6.38.7/fs/jffs2/compr_rubin.c
+--- linux-2.6.38.7/fs/jffs2/compr_rubin.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/jffs2/compr_rubin.c 2011-05-16 21:47:08.000000000 -0400
+@@ -314,6 +314,8 @@ static int jffs2_dynrubin_compress(unsig
+ int ret;
+ uint32_t mysrclen, mydstlen;
+
++ pax_track_stack();
++
+ mysrclen = *sourcelen;
+ mydstlen = *dstlen - 8;
+
+diff -urNp linux-2.6.38.7/fs/jffs2/erase.c linux-2.6.38.7/fs/jffs2/erase.c
+--- linux-2.6.38.7/fs/jffs2/erase.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/jffs2/erase.c 2011-04-28 19:34:15.000000000 -0400
+@@ -439,7 +439,8 @@ static void jffs2_mark_erased_block(stru
+ struct jffs2_unknown_node marker = {
+ .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK),
+ .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
+- .totlen = cpu_to_je32(c->cleanmarker_size)
++ .totlen = cpu_to_je32(c->cleanmarker_size),
++ .hdr_crc = cpu_to_je32(0)
+ };
+
+ jffs2_prealloc_raw_node_refs(c, jeb, 1);
+diff -urNp linux-2.6.38.7/fs/jffs2/wbuf.c linux-2.6.38.7/fs/jffs2/wbuf.c
+--- linux-2.6.38.7/fs/jffs2/wbuf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/jffs2/wbuf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1012,7 +1012,8 @@ static const struct jffs2_unknown_node o
+ {
+ .magic = constant_cpu_to_je16(JFFS2_MAGIC_BITMASK),
+ .nodetype = constant_cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
+- .totlen = constant_cpu_to_je32(8)
++ .totlen = constant_cpu_to_je32(8),
++ .hdr_crc = constant_cpu_to_je32(0)
+ };
+
+ /*
+diff -urNp linux-2.6.38.7/fs/jffs2/xattr.c linux-2.6.38.7/fs/jffs2/xattr.c
+--- linux-2.6.38.7/fs/jffs2/xattr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/jffs2/xattr.c 2011-05-16 21:47:08.000000000 -0400
+@@ -773,6 +773,8 @@ void jffs2_build_xattr_subsystem(struct
+
+ BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
+
++ pax_track_stack();
++
+ /* Phase.1 : Merge same xref */
+ for (i=0; i < XREF_TMPHASH_SIZE; i++)
+ xref_tmphash[i] = NULL;
+diff -urNp linux-2.6.38.7/fs/Kconfig.binfmt linux-2.6.38.7/fs/Kconfig.binfmt
+--- linux-2.6.38.7/fs/Kconfig.binfmt 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/Kconfig.binfmt 2011-04-28 19:34:15.000000000 -0400
+@@ -86,7 +86,7 @@ config HAVE_AOUT
+
+ config BINFMT_AOUT
+ tristate "Kernel support for a.out and ECOFF binaries"
+- depends on HAVE_AOUT
++ depends on HAVE_AOUT && BROKEN
+ ---help---
+ A.out (Assembler.OUTput) is a set of formats for libraries and
+ executables used in the earliest versions of UNIX. Linux used
+diff -urNp linux-2.6.38.7/fs/libfs.c linux-2.6.38.7/fs/libfs.c
+--- linux-2.6.38.7/fs/libfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/libfs.c 2011-05-11 18:34:57.000000000 -0400
+@@ -163,6 +163,9 @@ int dcache_readdir(struct file * filp, v
+
+ for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
+ struct dentry *next;
++ char d_name[sizeof(next->d_iname)];
++ const unsigned char *name;
++
+ next = list_entry(p, struct dentry, d_u.d_child);
+ spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
+ if (!simple_positive(next)) {
+@@ -172,7 +175,12 @@ int dcache_readdir(struct file * filp, v
+
+ spin_unlock(&next->d_lock);
+ spin_unlock(&dentry->d_lock);
+- if (filldir(dirent, next->d_name.name,
++ name = next->d_name.name;
++ if (name == next->d_iname) {
++ memcpy(d_name, name, next->d_name.len);
++ name = d_name;
++ }
++ if (filldir(dirent, name,
+ next->d_name.len, filp->f_pos,
+ next->d_inode->i_ino,
+ dt_type(next->d_inode)) < 0)
+diff -urNp linux-2.6.38.7/fs/lockd/clntproc.c linux-2.6.38.7/fs/lockd/clntproc.c
+--- linux-2.6.38.7/fs/lockd/clntproc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/lockd/clntproc.c 2011-05-16 21:47:08.000000000 -0400
+@@ -36,11 +36,11 @@ static const struct rpc_call_ops nlmclnt
+ /*
+ * Cookie counter for NLM requests
+ */
+-static atomic_t nlm_cookie = ATOMIC_INIT(0x1234);
++static atomic_unchecked_t nlm_cookie = ATOMIC_INIT(0x1234);
+
+ void nlmclnt_next_cookie(struct nlm_cookie *c)
+ {
+- u32 cookie = atomic_inc_return(&nlm_cookie);
++ u32 cookie = atomic_inc_return_unchecked(&nlm_cookie);
+
+ memcpy(c->data, &cookie, 4);
+ c->len=4;
+@@ -620,6 +620,8 @@ nlmclnt_reclaim(struct nlm_host *host, s
+ struct nlm_rqst reqst, *req;
+ int status;
+
++ pax_track_stack();
++
+ req = &reqst;
+ memset(req, 0, sizeof(*req));
+ locks_init_lock(&req->a_args.lock.fl);
+diff -urNp linux-2.6.38.7/fs/lockd/svc.c linux-2.6.38.7/fs/lockd/svc.c
+--- linux-2.6.38.7/fs/lockd/svc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/lockd/svc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -41,7 +41,7 @@
+
+ static struct svc_program nlmsvc_program;
+
+-struct nlmsvc_binding * nlmsvc_ops;
++const struct nlmsvc_binding * nlmsvc_ops;
+ EXPORT_SYMBOL_GPL(nlmsvc_ops);
+
+ static DEFINE_MUTEX(nlmsvc_mutex);
+diff -urNp linux-2.6.38.7/fs/locks.c linux-2.6.38.7/fs/locks.c
+--- linux-2.6.38.7/fs/locks.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/locks.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2044,16 +2044,16 @@ void locks_remove_flock(struct file *fil
+ return;
+
+ if (filp->f_op && filp->f_op->flock) {
+- struct file_lock fl = {
++ struct file_lock flock = {
+ .fl_pid = current->tgid,
+ .fl_file = filp,
+ .fl_flags = FL_FLOCK,
+ .fl_type = F_UNLCK,
+ .fl_end = OFFSET_MAX,
+ };
+- filp->f_op->flock(filp, F_SETLKW, &fl);
+- if (fl.fl_ops && fl.fl_ops->fl_release_private)
+- fl.fl_ops->fl_release_private(&fl);
++ filp->f_op->flock(filp, F_SETLKW, &flock);
++ if (flock.fl_ops && flock.fl_ops->fl_release_private)
++ flock.fl_ops->fl_release_private(&flock);
+ }
+
+ lock_flocks();
+diff -urNp linux-2.6.38.7/fs/logfs/super.c linux-2.6.38.7/fs/logfs/super.c
+--- linux-2.6.38.7/fs/logfs/super.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/logfs/super.c 2011-05-16 21:47:08.000000000 -0400
+@@ -266,6 +266,8 @@ static int logfs_recover_sb(struct super
+ struct logfs_disk_super _ds1, *ds1 = &_ds1;
+ int err, valid0, valid1;
+
++ pax_track_stack();
++
+ /* read first superblock */
+ err = wbuf_read(sb, super->s_sb_ofs[0], sizeof(*ds0), ds0);
+ if (err)
+diff -urNp linux-2.6.38.7/fs/namei.c linux-2.6.38.7/fs/namei.c
+--- linux-2.6.38.7/fs/namei.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/fs/namei.c 2011-05-22 16:14:10.000000000 -0400
+@@ -226,20 +226,30 @@ int generic_permission(struct inode *ino
+ return ret;
+
+ /*
+- * Read/write DACs are always overridable.
+- * Executable DACs are overridable if at least one exec bit is set.
++ * Searching includes executable on directories, else just read.
+ */
+- if (!(mask & MAY_EXEC) || execute_ok(inode))
+- if (capable(CAP_DAC_OVERRIDE))
++ mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
++ if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) {
++#ifdef CONFIG_GRKERNSEC
++ if (flags & IPERM_FLAG_RCU)
++ return -ECHILD;
++#endif
++ if (capable(CAP_DAC_READ_SEARCH))
+ return 0;
++ }
+
+ /*
+- * Searching includes executable on directories, else just read.
++ * Read/write DACs are always overridable.
++ * Executable DACs are overridable if at least one exec bit is set.
+ */
+- mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
+- if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
+- if (capable(CAP_DAC_READ_SEARCH))
++ if (!(mask & MAY_EXEC) || execute_ok(inode)) {
++#ifdef CONFIG_GRKERNSEC
++ if (flags & IPERM_FLAG_RCU)
++ return -ECHILD;
++#endif
++ if (capable(CAP_DAC_OVERRIDE))
+ return 0;
++ }
+
+ return -EACCES;
+ }
+@@ -687,8 +697,17 @@ static inline int exec_permission(struct
+ if (ret == -ECHILD)
+ return ret;
+
+- if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH))
++ if (capable_nolog(CAP_DAC_OVERRIDE))
++ goto ok;
++ else {
++#ifdef CONFIG_GRKERNSEC
++ if (flags & IPERM_FLAG_RCU)
++ return -ECHILD;
++#endif
++ if (capable(CAP_DAC_READ_SEARCH) ||
++ capable(CAP_DAC_OVERRIDE))
+ goto ok;
++ }
+
+ return ret;
+ ok:
+@@ -776,7 +795,7 @@ __do_follow_link(const struct path *link
+ *p = dentry->d_inode->i_op->follow_link(dentry, nd);
+ error = PTR_ERR(*p);
+ if (!IS_ERR(*p)) {
+- char *s = nd_get_link(nd);
++ const char *s = nd_get_link(nd);
+ error = 0;
+ if (s)
+ error = __vfs_follow_link(nd, s);
+@@ -815,6 +834,13 @@ static inline int do_follow_link(struct
+ err = security_inode_follow_link(path->dentry, nd);
+ if (err)
+ goto loop;
++
++ if (gr_handle_follow_link(path->dentry->d_parent->d_inode,
++ path->dentry->d_inode, path->dentry, nd->path.mnt)) {
++ err = -EACCES;
++ goto loop;
++ }
++
+ current->link_count++;
+ current->total_link_count++;
+ nd->depth++;
+@@ -1506,13 +1532,36 @@ return_reval:
+ return_base:
+ if (nameidata_drop_rcu_last_maybe(nd))
+ return -ECHILD;
++
++ if (!(nd->flags & LOOKUP_PARENT) && !gr_acl_handle_hidden_file(nd->path.dentry, nd->path.mnt)) {
++ err = -ENOENT;
++ goto err_and_ret;
++ }
++
+ return 0;
+ out_dput:
+ if (!(nd->flags & LOOKUP_RCU))
+ path_put_conditional(&next, nd);
+ break;
+ }
++#ifdef CONFIG_GRKERNSEC
++ /* we do this because we can't operate here on an rcu'd dentry,
++ acquire a properly-referenced copy
++ */
++ if (nameidata_drop_rcu_last_maybe(nd))
++ return -ECHILD;
++#endif
++
++ if (!(nd->flags & LOOKUP_PARENT) && !gr_acl_handle_hidden_file(nd->path.dentry, nd->path.mnt))
++ err = -ENOENT;
++
++err_and_ret:
++#ifndef CONFIG_GRKERNSEC
++ /* since we convert to ref-walk above, always put the path if we reach
++ here
++ */
+ if (!(nd->flags & LOOKUP_RCU))
++#endif
+ path_put(&nd->path);
+ return_err:
+ return err;
+@@ -1739,6 +1788,9 @@ static int do_path_lookup(int dfd, const
+ }
+
+ if (likely(!retval)) {
++ if (*name != '/' && nd->path.dentry && nd->inode && !gr_chroot_fchdir(nd->path.dentry, nd->path.mnt))
++ return -ENOENT;
++
+ if (unlikely(!audit_dummy_context())) {
+ if (nd->path.dentry && nd->inode)
+ audit_inode(name, nd->path.dentry);
+@@ -2079,6 +2131,30 @@ int vfs_create(struct inode *dir, struct
+ return error;
+ }
+
++/*
++ * Note that while the flag value (low two bits) for sys_open means:
++ * 00 - read-only
++ * 01 - write-only
++ * 10 - read-write
++ * 11 - special
++ * it is changed into
++ * 00 - no permissions needed
++ * 01 - read-permission
++ * 10 - write-permission
++ * 11 - read-write
++ * for the internal routines (ie open_namei()/follow_link() etc)
++ * This is more logical, and also allows the 00 "no perm needed"
++ * to be used for symlinks (where the permissions are checked
++ * later).
++ *
++*/
++static inline int open_to_namei_flags(int flag)
++{
++ if ((flag+1) & O_ACCMODE)
++ flag++;
++ return flag;
++}
++
+ int may_open(struct path *path, int acc_mode, int flag)
+ {
+ struct dentry *dentry = path->dentry;
+@@ -2127,7 +2203,27 @@ int may_open(struct path *path, int acc_
+ /*
+ * Ensure there are no outstanding leases on the file.
+ */
+- return break_lease(inode, flag);
++ error = break_lease(inode, flag);
++
++ if (error)
++ return error;
++
++ if (gr_handle_rofs_blockwrite(dentry, path->mnt, acc_mode)) {
++ error = -EPERM;
++ goto exit;
++ }
++
++ if (gr_handle_rawio(inode)) {
++ error = -EPERM;
++ goto exit;
++ }
++
++ if (!gr_acl_handle_open(dentry, path->mnt, open_to_namei_flags(flag))) {
++ error = -EACCES;
++ goto exit;
++ }
++exit:
++ return error;
+ }
+
+ static int handle_truncate(struct file *filp)
+@@ -2162,6 +2258,12 @@ static int __open_namei_create(struct na
+ {
+ int error;
+ struct dentry *dir = nd->path.dentry;
++ int flag = open_to_namei_flags(open_flag);
++
++ if (!gr_acl_handle_creat(path->dentry, nd->path.dentry, nd->path.mnt, flag, mode)) {
++ error = -EACCES;
++ goto out_unlock;
++ }
+
+ if (!IS_POSIXACL(dir->d_inode))
+ mode &= ~current_umask();
+@@ -2169,6 +2271,8 @@ static int __open_namei_create(struct na
+ if (error)
+ goto out_unlock;
+ error = vfs_create(dir->d_inode, path->dentry, mode, nd);
++ if (!error)
++ gr_handle_create(path->dentry, nd->path.mnt);
+ out_unlock:
+ mutex_unlock(&dir->d_inode->i_mutex);
+ dput(nd->path.dentry);
+@@ -2180,30 +2284,6 @@ out_unlock:
+ return may_open(&nd->path, 0, open_flag & ~O_TRUNC);
+ }
+
+-/*
+- * Note that while the flag value (low two bits) for sys_open means:
+- * 00 - read-only
+- * 01 - write-only
+- * 10 - read-write
+- * 11 - special
+- * it is changed into
+- * 00 - no permissions needed
+- * 01 - read-permission
+- * 10 - write-permission
+- * 11 - read-write
+- * for the internal routines (ie open_namei()/follow_link() etc)
+- * This is more logical, and also allows the 00 "no perm needed"
+- * to be used for symlinks (where the permissions are checked
+- * later).
+- *
+-*/
+-static inline int open_to_namei_flags(int flag)
+-{
+- if ((flag+1) & O_ACCMODE)
+- flag++;
+- return flag;
+-}
+-
+ static int open_will_truncate(int flag, struct inode *inode)
+ {
+ /*
+@@ -2274,6 +2354,7 @@ static struct file *do_last(struct namei
+ int mode, const char *pathname)
+ {
+ struct dentry *dir = nd->path.dentry;
++ int flag = open_to_namei_flags(open_flag);
+ struct file *filp;
+ int error = -EISDIR;
+
+@@ -2352,6 +2433,14 @@ static struct file *do_last(struct namei
+ /*
+ * It already exists.
+ */
++
++ /* only check if O_CREAT is specified, all other checks need to go
++ into may_open */
++ if (gr_handle_fifo(path->dentry, path->mnt, dir, flag, acc_mode)) {
++ error = -EACCES;
++ goto exit_mutex_unlock;
++ }
++
+ mutex_unlock(&dir->d_inode->i_mutex);
+ audit_inode(pathname, path->dentry);
+
+@@ -2535,6 +2624,11 @@ reval:
+ error = security_inode_follow_link(link.dentry, &nd);
+ if (error)
+ goto exit_dput;
++ if (gr_handle_follow_link(link.dentry->d_parent->d_inode,
++ link.dentry->d_inode, link.dentry, nd.path.mnt)) {
++ error = -EACCES;
++ goto exit_dput;
++ }
+ error = __do_follow_link(&link, &nd, &cookie);
+ if (unlikely(error)) {
+ if (!IS_ERR(cookie) && linki->i_op->put_link)
+@@ -2705,6 +2799,17 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const
+ error = may_mknod(mode);
+ if (error)
+ goto out_dput;
++
++ if (gr_handle_chroot_mknod(dentry, nd.path.mnt, mode)) {
++ error = -EPERM;
++ goto out_dput;
++ }
++
++ if (!gr_acl_handle_mknod(dentry, nd.path.dentry, nd.path.mnt, mode)) {
++ error = -EACCES;
++ goto out_dput;
++ }
++
+ error = mnt_want_write(nd.path.mnt);
+ if (error)
+ goto out_dput;
+@@ -2725,6 +2830,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const
+ }
+ out_drop_write:
+ mnt_drop_write(nd.path.mnt);
++
++ if (!error)
++ gr_handle_create(dentry, nd.path.mnt);
+ out_dput:
+ dput(dentry);
+ out_unlock:
+@@ -2777,6 +2885,11 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const
+ if (IS_ERR(dentry))
+ goto out_unlock;
+
++ if (!gr_acl_handle_mkdir(dentry, nd.path.dentry, nd.path.mnt)) {
++ error = -EACCES;
++ goto out_dput;
++ }
++
+ if (!IS_POSIXACL(nd.path.dentry->d_inode))
+ mode &= ~current_umask();
+ error = mnt_want_write(nd.path.mnt);
+@@ -2788,6 +2901,10 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const
+ error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
+ out_drop_write:
+ mnt_drop_write(nd.path.mnt);
++
++ if (!error)
++ gr_handle_create(dentry, nd.path.mnt);
++
+ out_dput:
+ dput(dentry);
+ out_unlock:
+@@ -2867,6 +2984,8 @@ static long do_rmdir(int dfd, const char
+ char * name;
+ struct dentry *dentry;
+ struct nameidata nd;
++ ino_t saved_ino = 0;
++ dev_t saved_dev = 0;
+
+ error = user_path_parent(dfd, pathname, &nd, &name);
+ if (error)
+@@ -2891,6 +3010,19 @@ static long do_rmdir(int dfd, const char
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ goto exit2;
++
++ if (dentry->d_inode != NULL) {
++ if (dentry->d_inode->i_nlink <= 1) {
++ saved_ino = dentry->d_inode->i_ino;
++ saved_dev = gr_get_dev_from_dentry(dentry);
++ }
++
++ if (!gr_acl_handle_rmdir(dentry, nd.path.mnt)) {
++ error = -EACCES;
++ goto exit3;
++ }
++ }
++
+ error = mnt_want_write(nd.path.mnt);
+ if (error)
+ goto exit3;
+@@ -2898,6 +3030,8 @@ static long do_rmdir(int dfd, const char
+ if (error)
+ goto exit4;
+ error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
++ if (!error && (saved_dev || saved_ino))
++ gr_handle_delete(saved_ino, saved_dev);
+ exit4:
+ mnt_drop_write(nd.path.mnt);
+ exit3:
+@@ -2960,6 +3094,8 @@ static long do_unlinkat(int dfd, const c
+ struct dentry *dentry;
+ struct nameidata nd;
+ struct inode *inode = NULL;
++ ino_t saved_ino = 0;
++ dev_t saved_dev = 0;
+
+ error = user_path_parent(dfd, pathname, &nd, &name);
+ if (error)
+@@ -2979,8 +3115,17 @@ static long do_unlinkat(int dfd, const c
+ if (nd.last.name[nd.last.len])
+ goto slashes;
+ inode = dentry->d_inode;
+- if (inode)
++ if (inode) {
+ ihold(inode);
++ if (inode->i_nlink <= 1) {
++ saved_ino = inode->i_ino;
++ saved_dev = gr_get_dev_from_dentry(dentry);
++ }
++ if (!gr_acl_handle_unlink(dentry, nd.path.mnt)) {
++ error = -EACCES;
++ goto exit2;
++ }
++ }
+ error = mnt_want_write(nd.path.mnt);
+ if (error)
+ goto exit2;
+@@ -2988,6 +3133,8 @@ static long do_unlinkat(int dfd, const c
+ if (error)
+ goto exit3;
+ error = vfs_unlink(nd.path.dentry->d_inode, dentry);
++ if (!error && (saved_ino || saved_dev))
++ gr_handle_delete(saved_ino, saved_dev);
+ exit3:
+ mnt_drop_write(nd.path.mnt);
+ exit2:
+@@ -3065,6 +3212,11 @@ SYSCALL_DEFINE3(symlinkat, const char __
+ if (IS_ERR(dentry))
+ goto out_unlock;
+
++ if (!gr_acl_handle_symlink(dentry, nd.path.dentry, nd.path.mnt, from)) {
++ error = -EACCES;
++ goto out_dput;
++ }
++
+ error = mnt_want_write(nd.path.mnt);
+ if (error)
+ goto out_dput;
+@@ -3072,6 +3224,8 @@ SYSCALL_DEFINE3(symlinkat, const char __
+ if (error)
+ goto out_drop_write;
+ error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
++ if (!error)
++ gr_handle_create(dentry, nd.path.mnt);
+ out_drop_write:
+ mnt_drop_write(nd.path.mnt);
+ out_dput:
+@@ -3164,6 +3318,20 @@ SYSCALL_DEFINE5(linkat, int, olddfd, con
+ error = PTR_ERR(new_dentry);
+ if (IS_ERR(new_dentry))
+ goto out_unlock;
++
++ if (gr_handle_hardlink(old_path.dentry, old_path.mnt,
++ old_path.dentry->d_inode,
++ old_path.dentry->d_inode->i_mode, to)) {
++ error = -EACCES;
++ goto out_dput;
++ }
++
++ if (!gr_acl_handle_link(new_dentry, nd.path.dentry, nd.path.mnt,
++ old_path.dentry, old_path.mnt, to)) {
++ error = -EACCES;
++ goto out_dput;
++ }
++
+ error = mnt_want_write(nd.path.mnt);
+ if (error)
+ goto out_dput;
+@@ -3171,6 +3339,8 @@ SYSCALL_DEFINE5(linkat, int, olddfd, con
+ if (error)
+ goto out_drop_write;
+ error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
++ if (!error)
++ gr_handle_create(new_dentry, nd.path.mnt);
+ out_drop_write:
+ mnt_drop_write(nd.path.mnt);
+ out_dput:
+@@ -3348,6 +3518,8 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c
+ char *to;
+ int error;
+
++ pax_track_stack();
++
+ error = user_path_parent(olddfd, oldname, &oldnd, &from);
+ if (error)
+ goto exit;
+@@ -3404,6 +3576,12 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c
+ if (new_dentry == trap)
+ goto exit5;
+
++ error = gr_acl_handle_rename(new_dentry, new_dir, newnd.path.mnt,
++ old_dentry, old_dir->d_inode, oldnd.path.mnt,
++ to);
++ if (error)
++ goto exit5;
++
+ error = mnt_want_write(oldnd.path.mnt);
+ if (error)
+ goto exit5;
+@@ -3413,6 +3591,9 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c
+ goto exit6;
+ error = vfs_rename(old_dir->d_inode, old_dentry,
+ new_dir->d_inode, new_dentry);
++ if (!error)
++ gr_handle_rename(old_dir->d_inode, new_dir->d_inode, old_dentry,
++ new_dentry, oldnd.path.mnt, new_dentry->d_inode ? 1 : 0);
+ exit6:
+ mnt_drop_write(oldnd.path.mnt);
+ exit5:
+@@ -3438,6 +3619,8 @@ SYSCALL_DEFINE2(rename, const char __use
+
+ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link)
+ {
++ char tmpbuf[64];
++ const char *newlink;
+ int len;
+
+ len = PTR_ERR(link);
+@@ -3447,7 +3630,14 @@ int vfs_readlink(struct dentry *dentry,
+ len = strlen(link);
+ if (len > (unsigned) buflen)
+ len = buflen;
+- if (copy_to_user(buffer, link, len))
++
++ if (len < sizeof(tmpbuf)) {
++ memcpy(tmpbuf, link, len);
++ newlink = tmpbuf;
++ } else
++ newlink = link;
++
++ if (copy_to_user(buffer, newlink, len))
+ len = -EFAULT;
+ out:
+ return len;
+diff -urNp linux-2.6.38.7/fs/namespace.c linux-2.6.38.7/fs/namespace.c
+--- linux-2.6.38.7/fs/namespace.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/fs/namespace.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1285,6 +1285,9 @@ static int do_umount(struct vfsmount *mn
+ if (!(sb->s_flags & MS_RDONLY))
+ retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
+ up_write(&sb->s_umount);
++
++ gr_log_remount(mnt->mnt_devname, retval);
++
+ return retval;
+ }
+
+@@ -1304,6 +1307,9 @@ static int do_umount(struct vfsmount *mn
+ br_write_unlock(vfsmount_lock);
+ up_write(&namespace_sem);
+ release_mounts(&umount_list);
++
++ gr_log_unmount(mnt->mnt_devname, retval);
++
+ return retval;
+ }
+
+@@ -2241,6 +2247,16 @@ long do_mount(char *dev_name, char *dir_
+ MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
+ MS_STRICTATIME);
+
++ if (gr_handle_rofs_mount(path.dentry, path.mnt, mnt_flags)) {
++ retval = -EPERM;
++ goto dput_out;
++ }
++
++ if (gr_handle_chroot_mount(path.dentry, path.mnt, dev_name)) {
++ retval = -EPERM;
++ goto dput_out;
++ }
++
+ if (flags & MS_REMOUNT)
+ retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
+ data_page);
+@@ -2255,6 +2271,9 @@ long do_mount(char *dev_name, char *dir_
+ dev_name, data_page);
+ dput_out:
+ path_put(&path);
++
++ gr_log_mount(dev_name, dir_name, retval);
++
+ return retval;
+ }
+
+@@ -2480,6 +2499,12 @@ SYSCALL_DEFINE2(pivot_root, const char _
+ goto out1;
+ }
+
++ if (gr_handle_chroot_pivot()) {
++ error = -EPERM;
++ path_put(&old);
++ goto out1;
++ }
++
+ get_fs_root(current->fs, &root);
+ down_write(&namespace_sem);
+ mutex_lock(&old.dentry->d_inode->i_mutex);
+diff -urNp linux-2.6.38.7/fs/ncpfs/dir.c linux-2.6.38.7/fs/ncpfs/dir.c
+--- linux-2.6.38.7/fs/ncpfs/dir.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ncpfs/dir.c 2011-05-16 21:47:09.000000000 -0400
+@@ -299,6 +299,8 @@ ncp_lookup_validate(struct dentry *dentr
+ int res, val = 0, len;
+ __u8 __name[NCP_MAXPATHLEN + 1];
+
++ pax_track_stack();
++
+ if (dentry == dentry->d_sb->s_root)
+ return 1;
+
+@@ -844,6 +846,8 @@ static struct dentry *ncp_lookup(struct
+ int error, res, len;
+ __u8 __name[NCP_MAXPATHLEN + 1];
+
++ pax_track_stack();
++
+ error = -EIO;
+ if (!ncp_conn_valid(server))
+ goto finished;
+@@ -931,6 +935,8 @@ int ncp_create_new(struct inode *dir, st
+ PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name, mode);
+
++ pax_track_stack();
++
+ ncp_age_dentry(server, dentry);
+ len = sizeof(__name);
+ error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+@@ -992,6 +998,8 @@ static int ncp_mkdir(struct inode *dir,
+ int error, len;
+ __u8 __name[NCP_MAXPATHLEN + 1];
+
++ pax_track_stack();
++
+ DPRINTK("ncp_mkdir: making %s/%s\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+
+@@ -1135,6 +1143,8 @@ static int ncp_rename(struct inode *old_
+ int old_len, new_len;
+ __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
+
++ pax_track_stack();
++
+ DPRINTK("ncp_rename: %s/%s to %s/%s\n",
+ old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
+ new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
+diff -urNp linux-2.6.38.7/fs/ncpfs/inode.c linux-2.6.38.7/fs/ncpfs/inode.c
+--- linux-2.6.38.7/fs/ncpfs/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ncpfs/inode.c 2011-05-16 21:47:09.000000000 -0400
+@@ -461,6 +461,8 @@ static int ncp_fill_super(struct super_b
+ #endif
+ struct ncp_entry_info finfo;
+
++ pax_track_stack();
++
+ data.wdog_pid = NULL;
+ server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
+ if (!server)
+diff -urNp linux-2.6.38.7/fs/nfs/inode.c linux-2.6.38.7/fs/nfs/inode.c
+--- linux-2.6.38.7/fs/nfs/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/nfs/inode.c 2011-04-28 19:34:15.000000000 -0400
+@@ -998,16 +998,16 @@ static int nfs_size_need_update(const st
+ return nfs_size_to_loff_t(fattr->size) > i_size_read(inode);
+ }
+
+-static atomic_long_t nfs_attr_generation_counter;
++static atomic_long_unchecked_t nfs_attr_generation_counter;
+
+ static unsigned long nfs_read_attr_generation_counter(void)
+ {
+- return atomic_long_read(&nfs_attr_generation_counter);
++ return atomic_long_read_unchecked(&nfs_attr_generation_counter);
+ }
+
+ unsigned long nfs_inc_attr_generation_counter(void)
+ {
+- return atomic_long_inc_return(&nfs_attr_generation_counter);
++ return atomic_long_inc_return_unchecked(&nfs_attr_generation_counter);
+ }
+
+ void nfs_fattr_init(struct nfs_fattr *fattr)
+diff -urNp linux-2.6.38.7/fs/nfsd/lockd.c linux-2.6.38.7/fs/nfsd/lockd.c
+--- linux-2.6.38.7/fs/nfsd/lockd.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/fs/nfsd/lockd.c 2011-04-28 19:34:15.000000000 -0400
+@@ -60,7 +60,7 @@ nlm_fclose(struct file *filp)
+ fput(filp);
+ }
+
+-static struct nlmsvc_binding nfsd_nlm_ops = {
++static const struct nlmsvc_binding nfsd_nlm_ops = {
+ .fopen = nlm_fopen, /* open file for locking */
+ .fclose = nlm_fclose, /* close file */
+ };
+diff -urNp linux-2.6.38.7/fs/nfsd/nfs4state.c linux-2.6.38.7/fs/nfsd/nfs4state.c
+--- linux-2.6.38.7/fs/nfsd/nfs4state.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/fs/nfsd/nfs4state.c 2011-05-16 21:47:09.000000000 -0400
+@@ -3783,6 +3783,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
+ unsigned int strhashval;
+ int err;
+
++ pax_track_stack();
++
+ dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
+ (long long) lock->lk_offset,
+ (long long) lock->lk_length);
+diff -urNp linux-2.6.38.7/fs/nfsd/nfs4xdr.c linux-2.6.38.7/fs/nfsd/nfs4xdr.c
+--- linux-2.6.38.7/fs/nfsd/nfs4xdr.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/fs/nfsd/nfs4xdr.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1793,6 +1793,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
+ .dentry = dentry,
+ };
+
++ pax_track_stack();
++
+ BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
+ BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
+ BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
+diff -urNp linux-2.6.38.7/fs/nfsd/nfsctl.c linux-2.6.38.7/fs/nfsd/nfsctl.c
+--- linux-2.6.38.7/fs/nfsd/nfsctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/nfsd/nfsctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -180,7 +180,7 @@ static int export_features_open(struct i
+ return single_open(file, export_features_show, NULL);
+ }
+
+-static struct file_operations export_features_operations = {
++static const struct file_operations export_features_operations = {
+ .open = export_features_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+diff -urNp linux-2.6.38.7/fs/nfsd/vfs.c linux-2.6.38.7/fs/nfsd/vfs.c
+--- linux-2.6.38.7/fs/nfsd/vfs.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/fs/nfsd/vfs.c 2011-05-10 22:08:57.000000000 -0400
+@@ -898,7 +898,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, st
+ } else {
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+- host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset);
++ host_err = vfs_readv(file, (__force struct iovec __user *)vec, vlen, &offset);
+ set_fs(oldfs);
+ }
+
+@@ -1002,7 +1002,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
+
+ /* Write the data. */
+ oldfs = get_fs(); set_fs(KERNEL_DS);
+- host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
++ host_err = vfs_writev(file, (__force struct iovec __user *)vec, vlen, &offset);
+ set_fs(oldfs);
+ if (host_err < 0)
+ goto out_nfserr;
+@@ -1525,7 +1525,7 @@ nfsd_readlink(struct svc_rqst *rqstp, st
+ */
+
+ oldfs = get_fs(); set_fs(KERNEL_DS);
+- host_err = inode->i_op->readlink(dentry, buf, *lenp);
++ host_err = inode->i_op->readlink(dentry, (__force char __user *)buf, *lenp);
+ set_fs(oldfs);
+
+ if (host_err < 0)
+diff -urNp linux-2.6.38.7/fs/notify/dnotify/dnotify.c linux-2.6.38.7/fs/notify/dnotify/dnotify.c
+--- linux-2.6.38.7/fs/notify/dnotify/dnotify.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/notify/dnotify/dnotify.c 2011-04-28 19:34:15.000000000 -0400
+@@ -151,7 +151,7 @@ static void dnotify_free_mark(struct fsn
+ kmem_cache_free(dnotify_mark_cache, dn_mark);
+ }
+
+-static struct fsnotify_ops dnotify_fsnotify_ops = {
++static const struct fsnotify_ops dnotify_fsnotify_ops = {
+ .handle_event = dnotify_handle_event,
+ .should_send_event = dnotify_should_send_event,
+ .free_group_priv = NULL,
+diff -urNp linux-2.6.38.7/fs/notify/notification.c linux-2.6.38.7/fs/notify/notification.c
+--- linux-2.6.38.7/fs/notify/notification.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/notify/notification.c 2011-04-28 19:57:25.000000000 -0400
+@@ -57,7 +57,7 @@ static struct kmem_cache *fsnotify_event
+ * get set to 0 so it will never get 'freed'
+ */
+ static struct fsnotify_event *q_overflow_event;
+-static atomic_t fsnotify_sync_cookie = ATOMIC_INIT(0);
++static atomic_unchecked_t fsnotify_sync_cookie = ATOMIC_INIT(0);
+
+ /**
+ * fsnotify_get_cookie - return a unique cookie for use in synchronizing events.
+@@ -65,7 +65,7 @@ static atomic_t fsnotify_sync_cookie = A
+ */
+ u32 fsnotify_get_cookie(void)
+ {
+- return atomic_inc_return(&fsnotify_sync_cookie);
++ return atomic_inc_return_unchecked(&fsnotify_sync_cookie);
+ }
+ EXPORT_SYMBOL_GPL(fsnotify_get_cookie);
+
+diff -urNp linux-2.6.38.7/fs/ntfs/dir.c linux-2.6.38.7/fs/ntfs/dir.c
+--- linux-2.6.38.7/fs/ntfs/dir.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ntfs/dir.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1329,7 +1329,7 @@ find_next_index_buffer:
+ ia = (INDEX_ALLOCATION*)(kaddr + (ia_pos & ~PAGE_CACHE_MASK &
+ ~(s64)(ndir->itype.index.block_size - 1)));
+ /* Bounds checks. */
+- if (unlikely((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE)) {
++ if (unlikely(!kaddr || (u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE)) {
+ ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
+ "inode 0x%lx or driver bug.", vdir->i_ino);
+ goto err_out;
+diff -urNp linux-2.6.38.7/fs/ntfs/file.c linux-2.6.38.7/fs/ntfs/file.c
+--- linux-2.6.38.7/fs/ntfs/file.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ntfs/file.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2222,6 +2222,6 @@ const struct inode_operations ntfs_file_
+ #endif /* NTFS_RW */
+ };
+
+-const struct file_operations ntfs_empty_file_ops = {};
++const struct file_operations ntfs_empty_file_ops __read_only;
+
+-const struct inode_operations ntfs_empty_inode_ops = {};
++const struct inode_operations ntfs_empty_inode_ops __read_only;
+diff -urNp linux-2.6.38.7/fs/ocfs2/localalloc.c linux-2.6.38.7/fs/ocfs2/localalloc.c
+--- linux-2.6.38.7/fs/ocfs2/localalloc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ocfs2/localalloc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1307,7 +1307,7 @@ static int ocfs2_local_alloc_slide_windo
+ goto bail;
+ }
+
+- atomic_inc(&osb->alloc_stats.moves);
++ atomic_inc_unchecked(&osb->alloc_stats.moves);
+
+ bail:
+ if (handle)
+diff -urNp linux-2.6.38.7/fs/ocfs2/namei.c linux-2.6.38.7/fs/ocfs2/namei.c
+--- linux-2.6.38.7/fs/ocfs2/namei.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ocfs2/namei.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1064,6 +1064,8 @@ static int ocfs2_rename(struct inode *ol
+ struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
+ struct ocfs2_dir_lookup_result target_insert = { NULL, };
+
++ pax_track_stack();
++
+ /* At some point it might be nice to break this function up a
+ * bit. */
+
+diff -urNp linux-2.6.38.7/fs/ocfs2/ocfs2.h linux-2.6.38.7/fs/ocfs2/ocfs2.h
+--- linux-2.6.38.7/fs/ocfs2/ocfs2.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ocfs2/ocfs2.h 2011-04-28 19:34:15.000000000 -0400
+@@ -230,11 +230,11 @@ enum ocfs2_vol_state
+
+ struct ocfs2_alloc_stats
+ {
+- atomic_t moves;
+- atomic_t local_data;
+- atomic_t bitmap_data;
+- atomic_t bg_allocs;
+- atomic_t bg_extends;
++ atomic_unchecked_t moves;
++ atomic_unchecked_t local_data;
++ atomic_unchecked_t bitmap_data;
++ atomic_unchecked_t bg_allocs;
++ atomic_unchecked_t bg_extends;
+ };
+
+ enum ocfs2_local_alloc_state
+diff -urNp linux-2.6.38.7/fs/ocfs2/suballoc.c linux-2.6.38.7/fs/ocfs2/suballoc.c
+--- linux-2.6.38.7/fs/ocfs2/suballoc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ocfs2/suballoc.c 2011-05-11 18:34:57.000000000 -0400
+@@ -877,7 +877,7 @@ static int ocfs2_reserve_suballoc_bits(s
+ mlog_errno(status);
+ goto bail;
+ }
+- atomic_inc(&osb->alloc_stats.bg_extends);
++ atomic_inc_unchecked(&osb->alloc_stats.bg_extends);
+
+ /* You should never ask for this much metadata */
+ BUG_ON(bits_wanted >
+@@ -2012,7 +2012,7 @@ int ocfs2_claim_metadata(handle_t *handl
+ mlog_errno(status);
+ goto bail;
+ }
+- atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
++ atomic_inc_unchecked(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
+
+ *suballoc_loc = res.sr_bg_blkno;
+ *suballoc_bit_start = res.sr_bit_offset;
+@@ -2175,7 +2175,7 @@ int ocfs2_claim_new_inode_at_loc(handle_
+ mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits,
+ (unsigned long long)di_blkno);
+
+- atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
++ atomic_inc_unchecked(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
+
+ BUG_ON(res->sr_bits != 1);
+
+@@ -2219,7 +2219,7 @@ int ocfs2_claim_new_inode(handle_t *hand
+ mlog_errno(status);
+ goto bail;
+ }
+- atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
++ atomic_inc_unchecked(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
+
+ BUG_ON(res.sr_bits != 1);
+
+@@ -2324,7 +2324,7 @@ int __ocfs2_claim_clusters(handle_t *han
+ cluster_start,
+ num_clusters);
+ if (!status)
+- atomic_inc(&osb->alloc_stats.local_data);
++ atomic_inc_unchecked(&osb->alloc_stats.local_data);
+ } else {
+ if (min_clusters > (osb->bitmap_cpg - 1)) {
+ /* The only paths asking for contiguousness
+@@ -2350,7 +2350,7 @@ int __ocfs2_claim_clusters(handle_t *han
+ ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode,
+ res.sr_bg_blkno,
+ res.sr_bit_offset);
+- atomic_inc(&osb->alloc_stats.bitmap_data);
++ atomic_inc_unchecked(&osb->alloc_stats.bitmap_data);
+ *num_clusters = res.sr_bits;
+ }
+ }
+diff -urNp linux-2.6.38.7/fs/ocfs2/super.c linux-2.6.38.7/fs/ocfs2/super.c
+--- linux-2.6.38.7/fs/ocfs2/super.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ocfs2/super.c 2011-04-28 19:34:15.000000000 -0400
+@@ -297,11 +297,11 @@ static int ocfs2_osb_dump(struct ocfs2_s
+ "%10s => GlobalAllocs: %d LocalAllocs: %d "
+ "SubAllocs: %d LAWinMoves: %d SAExtends: %d\n",
+ "Stats",
+- atomic_read(&osb->alloc_stats.bitmap_data),
+- atomic_read(&osb->alloc_stats.local_data),
+- atomic_read(&osb->alloc_stats.bg_allocs),
+- atomic_read(&osb->alloc_stats.moves),
+- atomic_read(&osb->alloc_stats.bg_extends));
++ atomic_read_unchecked(&osb->alloc_stats.bitmap_data),
++ atomic_read_unchecked(&osb->alloc_stats.local_data),
++ atomic_read_unchecked(&osb->alloc_stats.bg_allocs),
++ atomic_read_unchecked(&osb->alloc_stats.moves),
++ atomic_read_unchecked(&osb->alloc_stats.bg_extends));
+
+ out += snprintf(buf + out, len - out,
+ "%10s => State: %u Descriptor: %llu Size: %u bits "
+@@ -2141,11 +2141,11 @@ static int ocfs2_initialize_super(struct
+ spin_lock_init(&osb->osb_xattr_lock);
+ ocfs2_init_steal_slots(osb);
+
+- atomic_set(&osb->alloc_stats.moves, 0);
+- atomic_set(&osb->alloc_stats.local_data, 0);
+- atomic_set(&osb->alloc_stats.bitmap_data, 0);
+- atomic_set(&osb->alloc_stats.bg_allocs, 0);
+- atomic_set(&osb->alloc_stats.bg_extends, 0);
++ atomic_set_unchecked(&osb->alloc_stats.moves, 0);
++ atomic_set_unchecked(&osb->alloc_stats.local_data, 0);
++ atomic_set_unchecked(&osb->alloc_stats.bitmap_data, 0);
++ atomic_set_unchecked(&osb->alloc_stats.bg_allocs, 0);
++ atomic_set_unchecked(&osb->alloc_stats.bg_extends, 0);
+
+ /* Copy the blockcheck stats from the superblock probe */
+ osb->osb_ecc_stats = *stats;
+diff -urNp linux-2.6.38.7/fs/ocfs2/symlink.c linux-2.6.38.7/fs/ocfs2/symlink.c
+--- linux-2.6.38.7/fs/ocfs2/symlink.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/ocfs2/symlink.c 2011-04-28 19:34:15.000000000 -0400
+@@ -148,7 +148,7 @@ bail:
+
+ static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+ {
+- char *link = nd_get_link(nd);
++ const char *link = nd_get_link(nd);
+ if (!IS_ERR(link))
+ kfree(link);
+ }
+diff -urNp linux-2.6.38.7/fs/open.c linux-2.6.38.7/fs/open.c
+--- linux-2.6.38.7/fs/open.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/open.c 2011-04-28 19:34:15.000000000 -0400
+@@ -112,6 +112,10 @@ static long do_sys_truncate(const char _
+ error = locks_verify_truncate(inode, NULL, length);
+ if (!error)
+ error = security_path_truncate(&path);
++
++ if (!error && !gr_acl_handle_truncate(path.dentry, path.mnt))
++ error = -EACCES;
++
+ if (!error)
+ error = do_truncate(path.dentry, length, 0, NULL);
+
+@@ -358,6 +362,9 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con
+ if (__mnt_is_readonly(path.mnt))
+ res = -EROFS;
+
++ if (!res && !gr_acl_handle_access(path.dentry, path.mnt, mode))
++ res = -EACCES;
++
+ out_path_release:
+ path_put(&path);
+ out:
+@@ -384,6 +391,8 @@ SYSCALL_DEFINE1(chdir, const char __user
+ if (error)
+ goto dput_and_out;
+
++ gr_log_chdir(path.dentry, path.mnt);
++
+ set_fs_pwd(current->fs, &path);
+
+ dput_and_out:
+@@ -410,6 +419,13 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd
+ goto out_putf;
+
+ error = inode_permission(inode, MAY_EXEC | MAY_CHDIR);
++
++ if (!error && !gr_chroot_fchdir(file->f_path.dentry, file->f_path.mnt))
++ error = -EPERM;
++
++ if (!error)
++ gr_log_chdir(file->f_path.dentry, file->f_path.mnt);
++
+ if (!error)
+ set_fs_pwd(current->fs, &file->f_path);
+ out_putf:
+@@ -438,7 +454,18 @@ SYSCALL_DEFINE1(chroot, const char __use
+ if (error)
+ goto dput_and_out;
+
++ if (gr_handle_chroot_chroot(path.dentry, path.mnt))
++ goto dput_and_out;
++
++ if (gr_handle_chroot_caps(&path)) {
++ error = -ENOMEM;
++ goto dput_and_out;
++ }
++
+ set_fs_root(current->fs, &path);
++
++ gr_handle_chroot_chdir(&path);
++
+ error = 0;
+ dput_and_out:
+ path_put(&path);
+@@ -466,12 +493,25 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd
+ err = mnt_want_write_file(file);
+ if (err)
+ goto out_putf;
++
+ mutex_lock(&inode->i_mutex);
++
++ if (!gr_acl_handle_fchmod(dentry, file->f_vfsmnt, mode)) {
++ err = -EACCES;
++ goto out_unlock;
++ }
++
+ err = security_path_chmod(dentry, file->f_vfsmnt, mode);
+ if (err)
+ goto out_unlock;
+ if (mode == (mode_t) -1)
+ mode = inode->i_mode;
++
++ if (gr_handle_chroot_chmod(dentry, file->f_vfsmnt, mode)) {
++ err = -EACCES;
++ goto out_unlock;
++ }
++
+ newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+ err = notify_change(dentry, &newattrs);
+@@ -499,12 +539,25 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons
+ error = mnt_want_write(path.mnt);
+ if (error)
+ goto dput_and_out;
++
+ mutex_lock(&inode->i_mutex);
++
++ if (!gr_acl_handle_chmod(path.dentry, path.mnt, mode)) {
++ error = -EACCES;
++ goto out_unlock;
++ }
++
+ error = security_path_chmod(path.dentry, path.mnt, mode);
+ if (error)
+ goto out_unlock;
+ if (mode == (mode_t) -1)
+ mode = inode->i_mode;
++
++ if (gr_handle_chroot_chmod(path.dentry, path.mnt, mode)) {
++ error = -EACCES;
++ goto out_unlock;
++ }
++
+ newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+ error = notify_change(path.dentry, &newattrs);
+@@ -528,6 +581,9 @@ static int chown_common(struct path *pat
+ int error;
+ struct iattr newattrs;
+
++ if (!gr_acl_handle_chown(path->dentry, path->mnt))
++ return -EACCES;
++
+ newattrs.ia_valid = ATTR_CTIME;
+ if (user != (uid_t) -1) {
+ newattrs.ia_valid |= ATTR_UID;
+@@ -898,7 +954,10 @@ long do_sys_open(int dfd, const char __u
+ if (!IS_ERR(tmp)) {
+ fd = get_unused_fd_flags(flags);
+ if (fd >= 0) {
+- struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
++ struct file *f;
++ /* don't allow to be set by userland */
++ flags &= ~FMODE_GREXEC;
++ f = do_filp_open(dfd, tmp, flags, mode, 0);
+ if (IS_ERR(f)) {
+ put_unused_fd(fd);
+ fd = PTR_ERR(f);
+diff -urNp linux-2.6.38.7/fs/partitions/ldm.c linux-2.6.38.7/fs/partitions/ldm.c
+--- linux-2.6.38.7/fs/partitions/ldm.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/fs/partitions/ldm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1311,6 +1311,7 @@ static bool ldm_frag_add (const u8 *data
+ ldm_error ("A VBLK claims to have %d parts.", num);
+ return false;
+ }
++
+ if (rec >= num) {
+ ldm_error("REC value (%d) exceeds NUM value (%d)", rec, num);
+ return false;
+@@ -1322,7 +1323,7 @@ static bool ldm_frag_add (const u8 *data
+ goto found;
+ }
+
+- f = kmalloc (sizeof (*f) + size*num, GFP_KERNEL);
++ f = kmalloc (size*num + sizeof (*f), GFP_KERNEL);
+ if (!f) {
+ ldm_crit ("Out of memory.");
+ return false;
+diff -urNp linux-2.6.38.7/fs/pipe.c linux-2.6.38.7/fs/pipe.c
+--- linux-2.6.38.7/fs/pipe.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/pipe.c 2011-04-28 19:34:15.000000000 -0400
+@@ -420,9 +420,9 @@ redo:
+ }
+ if (bufs) /* More to do? */
+ continue;
+- if (!pipe->writers)
++ if (!atomic_read(&pipe->writers))
+ break;
+- if (!pipe->waiting_writers) {
++ if (!atomic_read(&pipe->waiting_writers)) {
+ /* syscall merging: Usually we must not sleep
+ * if O_NONBLOCK is set, or if we got some data.
+ * But if a writer sleeps in kernel space, then
+@@ -481,7 +481,7 @@ pipe_write(struct kiocb *iocb, const str
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
+
+- if (!pipe->readers) {
++ if (!atomic_read(&pipe->readers)) {
+ send_sig(SIGPIPE, current, 0);
+ ret = -EPIPE;
+ goto out;
+@@ -530,7 +530,7 @@ redo1:
+ for (;;) {
+ int bufs;
+
+- if (!pipe->readers) {
++ if (!atomic_read(&pipe->readers)) {
+ send_sig(SIGPIPE, current, 0);
+ if (!ret)
+ ret = -EPIPE;
+@@ -616,9 +616,9 @@ redo2:
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+ do_wakeup = 0;
+ }
+- pipe->waiting_writers++;
++ atomic_inc(&pipe->waiting_writers);
+ pipe_wait(pipe);
+- pipe->waiting_writers--;
++ atomic_dec(&pipe->waiting_writers);
+ }
+ out:
+ mutex_unlock(&inode->i_mutex);
+@@ -685,7 +685,7 @@ pipe_poll(struct file *filp, poll_table
+ mask = 0;
+ if (filp->f_mode & FMODE_READ) {
+ mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0;
+- if (!pipe->writers && filp->f_version != pipe->w_counter)
++ if (!atomic_read(&pipe->writers) && filp->f_version != pipe->w_counter)
+ mask |= POLLHUP;
+ }
+
+@@ -695,7 +695,7 @@ pipe_poll(struct file *filp, poll_table
+ * Most Unices do not set POLLERR for FIFOs but on Linux they
+ * behave exactly like pipes for poll().
+ */
+- if (!pipe->readers)
++ if (!atomic_read(&pipe->readers))
+ mask |= POLLERR;
+ }
+
+@@ -709,10 +709,10 @@ pipe_release(struct inode *inode, int de
+
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
+- pipe->readers -= decr;
+- pipe->writers -= decw;
++ atomic_sub(decr, &pipe->readers);
++ atomic_sub(decw, &pipe->writers);
+
+- if (!pipe->readers && !pipe->writers) {
++ if (!atomic_read(&pipe->readers) && !atomic_read(&pipe->writers)) {
+ free_pipe_info(inode);
+ } else {
+ wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM | POLLERR | POLLHUP);
+@@ -802,7 +802,7 @@ pipe_read_open(struct inode *inode, stru
+
+ if (inode->i_pipe) {
+ ret = 0;
+- inode->i_pipe->readers++;
++ atomic_inc(&inode->i_pipe->readers);
+ }
+
+ mutex_unlock(&inode->i_mutex);
+@@ -819,7 +819,7 @@ pipe_write_open(struct inode *inode, str
+
+ if (inode->i_pipe) {
+ ret = 0;
+- inode->i_pipe->writers++;
++ atomic_inc(&inode->i_pipe->writers);
+ }
+
+ mutex_unlock(&inode->i_mutex);
+@@ -837,9 +837,9 @@ pipe_rdwr_open(struct inode *inode, stru
+ if (inode->i_pipe) {
+ ret = 0;
+ if (filp->f_mode & FMODE_READ)
+- inode->i_pipe->readers++;
++ atomic_inc(&inode->i_pipe->readers);
+ if (filp->f_mode & FMODE_WRITE)
+- inode->i_pipe->writers++;
++ atomic_inc(&inode->i_pipe->writers);
+ }
+
+ mutex_unlock(&inode->i_mutex);
+@@ -931,7 +931,7 @@ void free_pipe_info(struct inode *inode)
+ inode->i_pipe = NULL;
+ }
+
+-static struct vfsmount *pipe_mnt __read_mostly;
++struct vfsmount *pipe_mnt __read_mostly;
+
+ /*
+ * pipefs_dname() is called from d_path().
+@@ -961,7 +961,8 @@ static struct inode * get_pipe_inode(voi
+ goto fail_iput;
+ inode->i_pipe = pipe;
+
+- pipe->readers = pipe->writers = 1;
++ atomic_set(&pipe->readers, 1);
++ atomic_set(&pipe->writers, 1);
+ inode->i_fop = &rdwr_pipefifo_fops;
+
+ /*
+diff -urNp linux-2.6.38.7/fs/proc/array.c linux-2.6.38.7/fs/proc/array.c
+--- linux-2.6.38.7/fs/proc/array.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/fs/proc/array.c 2011-05-16 21:47:08.000000000 -0400
+@@ -60,6 +60,7 @@
+ #include <linux/tty.h>
+ #include <linux/string.h>
+ #include <linux/mman.h>
++#include <linux/grsecurity.h>
+ #include <linux/proc_fs.h>
+ #include <linux/ioport.h>
+ #include <linux/uaccess.h>
+@@ -337,6 +338,21 @@ static void task_cpus_allowed(struct seq
+ seq_putc(m, '\n');
+ }
+
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
++static inline void task_pax(struct seq_file *m, struct task_struct *p)
++{
++ if (p->mm)
++ seq_printf(m, "PaX:\t%c%c%c%c%c\n",
++ p->mm->pax_flags & MF_PAX_PAGEEXEC ? 'P' : 'p',
++ p->mm->pax_flags & MF_PAX_EMUTRAMP ? 'E' : 'e',
++ p->mm->pax_flags & MF_PAX_MPROTECT ? 'M' : 'm',
++ p->mm->pax_flags & MF_PAX_RANDMMAP ? 'R' : 'r',
++ p->mm->pax_flags & MF_PAX_SEGMEXEC ? 'S' : 's');
++ else
++ seq_printf(m, "PaX:\t-----\n");
++}
++#endif
++
+ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task)
+ {
+@@ -354,9 +370,24 @@ int proc_pid_status(struct seq_file *m,
+ task_cpus_allowed(m, task);
+ cpuset_task_status_allowed(m, task);
+ task_context_switch_counts(m, task);
++
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
++ task_pax(m, task);
++#endif
++
++#if defined(CONFIG_GRKERNSEC) && !defined(CONFIG_GRKERNSEC_NO_RBAC)
++ task_grsec_rbac(m, task);
++#endif
++
+ return 0;
+ }
+
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
++ (_mm->pax_flags & MF_PAX_RANDMMAP || \
++ _mm->pax_flags & MF_PAX_SEGMEXEC))
++#endif
++
+ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task, int whole)
+ {
+@@ -375,9 +406,11 @@ static int do_task_stat(struct seq_file
+ cputime_t cutime, cstime, utime, stime;
+ cputime_t cgtime, gtime;
+ unsigned long rsslim = 0;
+- char tcomm[sizeof(task->comm)];
++ char tcomm[sizeof(task->comm)] = { 0 };
+ unsigned long flags;
+
++ pax_track_stack();
++
+ state = *get_task_state(task);
+ vsize = eip = esp = 0;
+ permitted = ptrace_may_access(task, PTRACE_MODE_READ);
+@@ -449,6 +482,19 @@ static int do_task_stat(struct seq_file
+ gtime = task->gtime;
+ }
+
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ if (PAX_RAND_FLAGS(mm)) {
++ eip = 0;
++ esp = 0;
++ wchan = 0;
++ }
++#endif
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ wchan = 0;
++ eip =0;
++ esp =0;
++#endif
++
+ /* scale priority and nice values from timeslices to -20..20 */
+ /* to make it look like a "normal" Unix priority/nice value */
+ priority = task_prio(task);
+@@ -489,9 +535,15 @@ static int do_task_stat(struct seq_file
+ vsize,
+ mm ? get_mm_rss(mm) : 0,
+ rsslim,
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ PAX_RAND_FLAGS(mm) ? 1 : (mm ? (permitted ? mm->start_code : 1) : 0),
++ PAX_RAND_FLAGS(mm) ? 1 : (mm ? (permitted ? mm->end_code : 1) : 0),
++ PAX_RAND_FLAGS(mm) ? 0 : ((permitted && mm) ? mm->start_stack : 0),
++#else
+ mm ? (permitted ? mm->start_code : 1) : 0,
+ mm ? (permitted ? mm->end_code : 1) : 0,
+ (permitted && mm) ? mm->start_stack : 0,
++#endif
+ esp,
+ eip,
+ /* The signal information here is obsolete.
+@@ -544,3 +596,18 @@ int proc_pid_statm(struct seq_file *m, s
+
+ return 0;
+ }
++
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
++int proc_pid_ipaddr(struct task_struct *task, char *buffer)
++{
++ u32 curr_ip = 0;
++ unsigned long flags;
++
++ if (lock_task_sighand(task, &flags)) {
++ curr_ip = task->signal->curr_ip;
++ unlock_task_sighand(task, &flags);
++ }
++
++ return sprintf(buffer, "%pI4\n", &curr_ip);
++}
++#endif
+diff -urNp linux-2.6.38.7/fs/proc/base.c linux-2.6.38.7/fs/proc/base.c
+--- linux-2.6.38.7/fs/proc/base.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/fs/proc/base.c 2011-04-28 19:34:15.000000000 -0400
+@@ -104,6 +104,22 @@ struct pid_entry {
+ union proc_op op;
+ };
+
++struct getdents_callback {
++ struct linux_dirent __user * current_dir;
++ struct linux_dirent __user * previous;
++ struct file * file;
++ int count;
++ int error;
++};
++
++static int gr_fake_filldir(void * __buf, const char *name, int namlen,
++ loff_t offset, u64 ino, unsigned int d_type)
++{
++ struct getdents_callback * buf = (struct getdents_callback *) __buf;
++ buf->error = -EINVAL;
++ return 0;
++}
++
+ #define NOD(NAME, MODE, IOP, FOP, OP) { \
+ .name = (NAME), \
+ .len = sizeof(NAME) - 1, \
+@@ -203,6 +219,9 @@ static int check_mem_permission(struct t
+ if (task == current)
+ return 0;
+
++ if (gr_handle_proc_ptrace(task) || gr_acl_handle_procpidmem(task))
++ return -EPERM;
++
+ /*
+ * If current is actively ptrace'ing, and would also be
+ * permitted to freshly attach with ptrace now, permit it.
+@@ -250,6 +269,9 @@ static int proc_pid_cmdline(struct task_
+ if (!mm->arg_end)
+ goto out_mm; /* Shh! No looking before we're done */
+
++ if (gr_acl_handle_procpidmem(task))
++ goto out_mm;
++
+ len = mm->arg_end - mm->arg_start;
+
+ if (len > PAGE_SIZE)
+@@ -277,12 +299,28 @@ out:
+ return res;
+ }
+
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
++ (_mm->pax_flags & MF_PAX_RANDMMAP || \
++ _mm->pax_flags & MF_PAX_SEGMEXEC))
++#endif
++
+ static int proc_pid_auxv(struct task_struct *task, char *buffer)
+ {
+ int res = 0;
+ struct mm_struct *mm = get_task_mm(task);
+ if (mm) {
+ unsigned int nwords = 0;
++
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ /* allow if we're currently ptracing this task */
++ if (PAX_RAND_FLAGS(mm) &&
++ (!(task->ptrace & PT_PTRACED) || (task->parent != current))) {
++ mmput(mm);
++ return res;
++ }
++#endif
++
+ do {
+ nwords += 2;
+ } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
+@@ -296,7 +334,7 @@ static int proc_pid_auxv(struct task_str
+ }
+
+
+-#ifdef CONFIG_KALLSYMS
++#if defined(CONFIG_KALLSYMS) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ /*
+ * Provides a wchan file via kallsyms in a proper one-value-per-file format.
+ * Returns the resolved symbol. If that fails, simply return the address.
+@@ -318,7 +356,7 @@ static int proc_pid_wchan(struct task_st
+ }
+ #endif /* CONFIG_KALLSYMS */
+
+-#ifdef CONFIG_STACKTRACE
++#if defined(CONFIG_STACKTRACE) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+
+ #define MAX_STACK_TRACE_DEPTH 64
+
+@@ -503,7 +541,7 @@ static int proc_pid_limits(struct task_s
+ return count;
+ }
+
+-#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
++#if defined(CONFIG_HAVE_ARCH_TRACEHOOK) && !defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
+ static int proc_pid_syscall(struct task_struct *task, char *buffer)
+ {
+ long nr;
+@@ -528,7 +566,7 @@ static int proc_pid_syscall(struct task_
+ /************************************************************************/
+
+ /* permission checks */
+-static int proc_fd_access_allowed(struct inode *inode)
++static int proc_fd_access_allowed(struct inode *inode, unsigned int log)
+ {
+ struct task_struct *task;
+ int allowed = 0;
+@@ -538,7 +576,10 @@ static int proc_fd_access_allowed(struct
+ */
+ task = get_proc_task(inode);
+ if (task) {
+- allowed = ptrace_may_access(task, PTRACE_MODE_READ);
++ if (log)
++ allowed = ptrace_may_access_log(task, PTRACE_MODE_READ);
++ else
++ allowed = ptrace_may_access(task, PTRACE_MODE_READ);
+ put_task_struct(task);
+ }
+ return allowed;
+@@ -917,6 +958,9 @@ static ssize_t environ_read(struct file
+ if (!task)
+ goto out_no_task;
+
++ if (gr_acl_handle_procpidmem(task))
++ goto out;
++
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
+ goto out;
+
+@@ -1606,7 +1650,7 @@ static void *proc_pid_follow_link(struct
+ path_put(&nd->path);
+
+ /* Are we allowed to snoop on the tasks file descriptors? */
+- if (!proc_fd_access_allowed(inode))
++ if (!proc_fd_access_allowed(inode,0))
+ goto out;
+
+ error = PROC_I(inode)->op.proc_get_link(inode, &nd->path);
+@@ -1645,8 +1689,18 @@ static int proc_pid_readlink(struct dent
+ struct path path;
+
+ /* Are we allowed to snoop on the tasks file descriptors? */
+- if (!proc_fd_access_allowed(inode))
+- goto out;
++ /* logging this is needed for learning on chromium to work properly,
++ but we don't want to flood the logs from 'ps' which does a readlink
++ on /proc/fd/2 of tasks in the listing, nor do we want 'ps' to learn
++ CAP_SYS_PTRACE as it's not necessary for its basic functionality
++ */
++ if (dentry->d_name.name[0] == '2' && dentry->d_name.name[1] == '\0') {
++ if (!proc_fd_access_allowed(inode,0))
++ goto out;
++ } else {
++ if (!proc_fd_access_allowed(inode,1))
++ goto out;
++ }
+
+ error = PROC_I(inode)->op.proc_get_link(inode, &path);
+ if (error)
+@@ -1712,7 +1766,11 @@ static struct inode *proc_pid_make_inode
+ rcu_read_lock();
+ cred = __task_cred(task);
+ inode->i_uid = cred->euid;
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
++#else
+ inode->i_gid = cred->egid;
++#endif
+ rcu_read_unlock();
+ }
+ security_task_to_inode(task, inode);
+@@ -1730,6 +1788,9 @@ static int pid_getattr(struct vfsmount *
+ struct inode *inode = dentry->d_inode;
+ struct task_struct *task;
+ const struct cred *cred;
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ const struct cred *tmpcred = current_cred();
++#endif
+
+ generic_fillattr(inode, stat);
+
+@@ -1737,12 +1798,34 @@ static int pid_getattr(struct vfsmount *
+ stat->uid = 0;
+ stat->gid = 0;
+ task = pid_task(proc_pid(inode), PIDTYPE_PID);
++
++ if (task && (gr_pid_is_chrooted(task) || gr_check_hidden_task(task))) {
++ rcu_read_unlock();
++ return -ENOENT;
++ }
++
+ if (task) {
++ cred = __task_cred(task);
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ if (!tmpcred->uid || (tmpcred->uid == cred->uid)
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
++ || in_group_p(CONFIG_GRKERNSEC_PROC_GID)
++#endif
++ )
++#endif
+ if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IXUSR)) ||
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP)) ||
++#endif
+ task_dumpable(task)) {
+- cred = __task_cred(task);
+ stat->uid = cred->euid;
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
++ stat->gid = CONFIG_GRKERNSEC_PROC_GID;
++#else
+ stat->gid = cred->egid;
++#endif
+ }
+ }
+ rcu_read_unlock();
+@@ -1780,11 +1863,20 @@ static int pid_revalidate(struct dentry
+
+ if (task) {
+ if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IXUSR)) ||
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP)) ||
++#endif
+ task_dumpable(task)) {
+ rcu_read_lock();
+ cred = __task_cred(task);
+ inode->i_uid = cred->euid;
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
++#else
+ inode->i_gid = cred->egid;
++#endif
+ rcu_read_unlock();
+ } else {
+ inode->i_uid = 0;
+@@ -1905,7 +1997,8 @@ static int proc_fd_info(struct inode *in
+ int fd = proc_fd(inode);
+
+ if (task) {
+- files = get_files_struct(task);
++ if (!gr_acl_handle_procpidmem(task))
++ files = get_files_struct(task);
+ put_task_struct(task);
+ }
+ if (files) {
+@@ -2165,15 +2258,25 @@ static const struct file_operations proc
+ */
+ static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags)
+ {
++ struct task_struct *task;
+ int rv;
+
+ if (flags & IPERM_FLAG_RCU)
+ return -ECHILD;
+ rv = generic_permission(inode, mask, flags, NULL);
+- if (rv == 0)
+- return 0;
++
+ if (task_pid(current) == proc_pid(inode))
+ rv = 0;
++
++ task = get_proc_task(inode);
++ if (task == NULL)
++ return rv;
++
++ if (gr_acl_handle_procpidmem(task))
++ rv = -EACCES;
++
++ put_task_struct(task);
++
+ return rv;
+ }
+
+@@ -2283,6 +2386,9 @@ static struct dentry *proc_pident_lookup
+ if (!task)
+ goto out_no_task;
+
++ if (gr_pid_is_chrooted(task) || gr_check_hidden_task(task))
++ goto out;
++
+ /*
+ * Yes, it does not scale. And it should not. Don't add
+ * new entries into /proc/<tgid>/ without very good reasons.
+@@ -2327,6 +2433,9 @@ static int proc_pident_readdir(struct fi
+ if (!task)
+ goto out_no_task;
+
++ if (gr_pid_is_chrooted(task) || gr_check_hidden_task(task))
++ goto out;
++
+ ret = 0;
+ i = filp->f_pos;
+ switch (i) {
+@@ -2597,7 +2706,7 @@ static void *proc_self_follow_link(struc
+ static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
+ void *cookie)
+ {
+- char *s = nd_get_link(nd);
++ const char *s = nd_get_link(nd);
+ if (!IS_ERR(s))
+ __putname(s);
+ }
+@@ -2777,7 +2886,7 @@ static const struct pid_entry tgid_base_
+ REG("autogroup", S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
+ #endif
+ REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
+-#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
++#if defined(CONFIG_HAVE_ARCH_TRACEHOOK) && !defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
+ INF("syscall", S_IRUSR, proc_pid_syscall),
+ #endif
+ INF("cmdline", S_IRUGO, proc_pid_cmdline),
+@@ -2802,10 +2911,10 @@ static const struct pid_entry tgid_base_
+ #ifdef CONFIG_SECURITY
+ DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
+ #endif
+-#ifdef CONFIG_KALLSYMS
++#if defined(CONFIG_KALLSYMS) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ INF("wchan", S_IRUGO, proc_pid_wchan),
+ #endif
+-#ifdef CONFIG_STACKTRACE
++#if defined(CONFIG_STACKTRACE) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ ONE("stack", S_IRUSR, proc_pid_stack),
+ #endif
+ #ifdef CONFIG_SCHEDSTATS
+@@ -2836,6 +2945,9 @@ static const struct pid_entry tgid_base_
+ #ifdef CONFIG_TASK_IO_ACCOUNTING
+ INF("io", S_IRUGO, proc_tgid_io_accounting),
+ #endif
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
++ INF("ipaddr", S_IRUSR, proc_pid_ipaddr),
++#endif
+ };
+
+ static int proc_tgid_base_readdir(struct file * filp,
+@@ -2961,7 +3073,14 @@ static struct dentry *proc_pid_instantia
+ if (!inode)
+ goto out;
+
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR;
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
++ inode->i_mode = S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP;
++#else
+ inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
++#endif
+ inode->i_op = &proc_tgid_base_inode_operations;
+ inode->i_fop = &proc_tgid_base_operations;
+ inode->i_flags|=S_IMMUTABLE;
+@@ -3003,7 +3122,11 @@ struct dentry *proc_pid_lookup(struct in
+ if (!task)
+ goto out;
+
++ if (gr_pid_is_chrooted(task) || gr_check_hidden_task(task))
++ goto out_put_task;
++
+ result = proc_pid_instantiate(dir, dentry, task, NULL);
++out_put_task:
+ put_task_struct(task);
+ out:
+ return result;
+@@ -3068,6 +3191,11 @@ int proc_pid_readdir(struct file * filp,
+ {
+ unsigned int nr;
+ struct task_struct *reaper;
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ const struct cred *tmpcred = current_cred();
++ const struct cred *itercred;
++#endif
++ filldir_t __filldir = filldir;
+ struct tgid_iter iter;
+ struct pid_namespace *ns;
+
+@@ -3091,8 +3219,27 @@ int proc_pid_readdir(struct file * filp,
+ for (iter = next_tgid(ns, iter);
+ iter.task;
+ iter.tgid += 1, iter = next_tgid(ns, iter)) {
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ rcu_read_lock();
++ itercred = __task_cred(iter.task);
++#endif
++ if (gr_pid_is_chrooted(iter.task) || gr_check_hidden_task(iter.task)
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ || (tmpcred->uid && (itercred->uid != tmpcred->uid)
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
++ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
++#endif
++ )
++#endif
++ )
++ __filldir = &gr_fake_filldir;
++ else
++ __filldir = filldir;
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ rcu_read_unlock();
++#endif
+ filp->f_pos = iter.tgid + TGID_OFFSET;
+- if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
++ if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) {
+ put_task_struct(iter.task);
+ goto out;
+ }
+@@ -3119,7 +3266,7 @@ static const struct pid_entry tid_base_s
+ REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
+ #endif
+ REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
+-#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
++#if defined(CONFIG_HAVE_ARCH_TRACEHOOK) && !defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
+ INF("syscall", S_IRUSR, proc_pid_syscall),
+ #endif
+ INF("cmdline", S_IRUGO, proc_pid_cmdline),
+@@ -3143,10 +3290,10 @@ static const struct pid_entry tid_base_s
+ #ifdef CONFIG_SECURITY
+ DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
+ #endif
+-#ifdef CONFIG_KALLSYMS
++#if defined(CONFIG_KALLSYMS) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ INF("wchan", S_IRUGO, proc_pid_wchan),
+ #endif
+-#ifdef CONFIG_STACKTRACE
++#if defined(CONFIG_STACKTRACE) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ ONE("stack", S_IRUSR, proc_pid_stack),
+ #endif
+ #ifdef CONFIG_SCHEDSTATS
+diff -urNp linux-2.6.38.7/fs/proc/cmdline.c linux-2.6.38.7/fs/proc/cmdline.c
+--- linux-2.6.38.7/fs/proc/cmdline.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/cmdline.c 2011-04-28 19:34:15.000000000 -0400
+@@ -23,7 +23,11 @@ static const struct file_operations cmdl
+
+ static int __init proc_cmdline_init(void)
+ {
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ proc_create_grsec("cmdline", 0, NULL, &cmdline_proc_fops);
++#else
+ proc_create("cmdline", 0, NULL, &cmdline_proc_fops);
++#endif
+ return 0;
+ }
+ module_init(proc_cmdline_init);
+diff -urNp linux-2.6.38.7/fs/proc/devices.c linux-2.6.38.7/fs/proc/devices.c
+--- linux-2.6.38.7/fs/proc/devices.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/devices.c 2011-04-28 19:34:15.000000000 -0400
+@@ -64,7 +64,11 @@ static const struct file_operations proc
+
+ static int __init proc_devices_init(void)
+ {
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ proc_create_grsec("devices", 0, NULL, &proc_devinfo_operations);
++#else
+ proc_create("devices", 0, NULL, &proc_devinfo_operations);
++#endif
+ return 0;
+ }
+ module_init(proc_devices_init);
+diff -urNp linux-2.6.38.7/fs/proc/inode.c linux-2.6.38.7/fs/proc/inode.c
+--- linux-2.6.38.7/fs/proc/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/inode.c 2011-04-28 19:34:15.000000000 -0400
+@@ -435,7 +435,11 @@ struct inode *proc_get_inode(struct supe
+ if (de->mode) {
+ inode->i_mode = de->mode;
+ inode->i_uid = de->uid;
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
++#else
+ inode->i_gid = de->gid;
++#endif
+ }
+ if (de->size)
+ inode->i_size = de->size;
+diff -urNp linux-2.6.38.7/fs/proc/internal.h linux-2.6.38.7/fs/proc/internal.h
+--- linux-2.6.38.7/fs/proc/internal.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/internal.h 2011-04-28 19:34:15.000000000 -0400
+@@ -51,6 +51,9 @@ extern int proc_pid_status(struct seq_fi
+ struct pid *pid, struct task_struct *task);
+ extern int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task);
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
++extern int proc_pid_ipaddr(struct task_struct *task, char *buffer);
++#endif
+ extern loff_t mem_lseek(struct file *file, loff_t offset, int orig);
+
+ extern const struct file_operations proc_maps_operations;
+diff -urNp linux-2.6.38.7/fs/proc/Kconfig linux-2.6.38.7/fs/proc/Kconfig
+--- linux-2.6.38.7/fs/proc/Kconfig 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/Kconfig 2011-04-28 19:34:15.000000000 -0400
+@@ -30,12 +30,12 @@ config PROC_FS
+
+ config PROC_KCORE
+ bool "/proc/kcore support" if !ARM
+- depends on PROC_FS && MMU
++ depends on PROC_FS && MMU && !GRKERNSEC_PROC_ADD
+
+ config PROC_VMCORE
+ bool "/proc/vmcore support"
+- depends on PROC_FS && CRASH_DUMP
+- default y
++ depends on PROC_FS && CRASH_DUMP && !GRKERNSEC
++ default n
+ help
+ Exports the dump image of crashed kernel in ELF format.
+
+@@ -59,8 +59,8 @@ config PROC_SYSCTL
+ limited in memory.
+
+ config PROC_PAGE_MONITOR
+- default y
+- depends on PROC_FS && MMU
++ default n
++ depends on PROC_FS && MMU && !GRKERNSEC
+ bool "Enable /proc page monitoring" if EXPERT
+ help
+ Various /proc files exist to monitor process memory utilization:
+diff -urNp linux-2.6.38.7/fs/proc/kcore.c linux-2.6.38.7/fs/proc/kcore.c
+--- linux-2.6.38.7/fs/proc/kcore.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/kcore.c 2011-05-16 21:47:08.000000000 -0400
+@@ -321,6 +321,8 @@ static void elf_kcore_store_hdr(char *bu
+ off_t offset = 0;
+ struct kcore_list *m;
+
++ pax_track_stack();
++
+ /* setup ELF header */
+ elf = (struct elfhdr *) bufp;
+ bufp += sizeof(struct elfhdr);
+@@ -478,9 +480,10 @@ read_kcore(struct file *file, char __use
+ * the addresses in the elf_phdr on our list.
+ */
+ start = kc_offset_to_vaddr(*fpos - elf_buflen);
+- if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
++ tsz = PAGE_SIZE - (start & ~PAGE_MASK);
++ if (tsz > buflen)
+ tsz = buflen;
+-
++
+ while (buflen) {
+ struct kcore_list *m;
+
+@@ -509,20 +512,23 @@ read_kcore(struct file *file, char __use
+ kfree(elf_buf);
+ } else {
+ if (kern_addr_valid(start)) {
+- unsigned long n;
++ char *elf_buf;
++ mm_segment_t oldfs;
+
+- n = copy_to_user(buffer, (char *)start, tsz);
+- /*
+- * We cannot distingush between fault on source
+- * and fault on destination. When this happens
+- * we clear too and hope it will trigger the
+- * EFAULT again.
+- */
+- if (n) {
+- if (clear_user(buffer + tsz - n,
+- n))
++ elf_buf = kmalloc(tsz, GFP_KERNEL);
++ if (!elf_buf)
++ return -ENOMEM;
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ if (!__copy_from_user(elf_buf, (const void __user *)start, tsz)) {
++ set_fs(oldfs);
++ if (copy_to_user(buffer, elf_buf, tsz)) {
++ kfree(elf_buf);
+ return -EFAULT;
++ }
+ }
++ set_fs(oldfs);
++ kfree(elf_buf);
+ } else {
+ if (clear_user(buffer, tsz))
+ return -EFAULT;
+@@ -542,6 +548,9 @@ read_kcore(struct file *file, char __use
+
+ static int open_kcore(struct inode *inode, struct file *filp)
+ {
++#if defined(CONFIG_GRKERNSEC_PROC_ADD) || defined(CONFIG_GRKERNSEC_HIDESYM)
++ return -EPERM;
++#endif
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ if (kcore_need_update)
+diff -urNp linux-2.6.38.7/fs/proc/meminfo.c linux-2.6.38.7/fs/proc/meminfo.c
+--- linux-2.6.38.7/fs/proc/meminfo.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/meminfo.c 2011-05-16 21:47:08.000000000 -0400
+@@ -29,6 +29,8 @@ static int meminfo_proc_show(struct seq_
+ unsigned long pages[NR_LRU_LISTS];
+ int lru;
+
++ pax_track_stack();
++
+ /*
+ * display in kilobytes.
+ */
+@@ -157,7 +159,7 @@ static int meminfo_proc_show(struct seq_
+ vmi.used >> 10,
+ vmi.largest_chunk >> 10
+ #ifdef CONFIG_MEMORY_FAILURE
+- ,atomic_long_read(&mce_bad_pages) << (PAGE_SHIFT - 10)
++ ,atomic_long_read_unchecked(&mce_bad_pages) << (PAGE_SHIFT - 10)
+ #endif
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ ,K(global_page_state(NR_ANON_TRANSPARENT_HUGEPAGES) *
+diff -urNp linux-2.6.38.7/fs/proc/nommu.c linux-2.6.38.7/fs/proc/nommu.c
+--- linux-2.6.38.7/fs/proc/nommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/nommu.c 2011-04-28 19:34:15.000000000 -0400
+@@ -66,7 +66,7 @@ static int nommu_region_show(struct seq_
+ if (len < 1)
+ len = 1;
+ seq_printf(m, "%*c", len, ' ');
+- seq_path(m, &file->f_path, "");
++ seq_path(m, &file->f_path, "\n\\");
+ }
+
+ seq_putc(m, '\n');
+diff -urNp linux-2.6.38.7/fs/proc/proc_net.c linux-2.6.38.7/fs/proc/proc_net.c
+--- linux-2.6.38.7/fs/proc/proc_net.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/proc_net.c 2011-04-28 19:34:15.000000000 -0400
+@@ -105,6 +105,17 @@ static struct net *get_proc_task_net(str
+ struct task_struct *task;
+ struct nsproxy *ns;
+ struct net *net = NULL;
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ const struct cred *cred = current_cred();
++#endif
++
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ if (cred->fsuid)
++ return net;
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ if (cred->fsuid && !in_group_p(CONFIG_GRKERNSEC_PROC_GID))
++ return net;
++#endif
+
+ rcu_read_lock();
+ task = pid_task(proc_pid(dir), PIDTYPE_PID);
+diff -urNp linux-2.6.38.7/fs/proc/proc_sysctl.c linux-2.6.38.7/fs/proc/proc_sysctl.c
+--- linux-2.6.38.7/fs/proc/proc_sysctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/proc_sysctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -8,6 +8,8 @@
+ #include <linux/namei.h>
+ #include "internal.h"
+
++extern __u32 gr_handle_sysctl(const struct ctl_table *table, const int op);
++
+ static const struct dentry_operations proc_sys_dentry_operations;
+ static const struct file_operations proc_sys_file_operations;
+ static const struct inode_operations proc_sys_inode_operations;
+@@ -112,6 +114,9 @@ static struct dentry *proc_sys_lookup(st
+ if (!p)
+ goto out;
+
++ if (gr_handle_sysctl(p, MAY_EXEC))
++ goto out;
++
+ err = ERR_PTR(-ENOMEM);
+ inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
+ if (h)
+@@ -231,6 +236,9 @@ static int scan(struct ctl_table_header
+ if (*pos < file->f_pos)
+ continue;
+
++ if (gr_handle_sysctl(table, 0))
++ continue;
++
+ res = proc_sys_fill_cache(file, dirent, filldir, head, table);
+ if (res)
+ return res;
+@@ -359,6 +367,9 @@ static int proc_sys_getattr(struct vfsmo
+ if (IS_ERR(head))
+ return PTR_ERR(head);
+
++ if (table && gr_handle_sysctl(table, MAY_EXEC))
++ return -ENOENT;
++
+ generic_fillattr(inode, stat);
+ if (table)
+ stat->mode = (stat->mode & S_IFMT) | table->mode;
+diff -urNp linux-2.6.38.7/fs/proc/root.c linux-2.6.38.7/fs/proc/root.c
+--- linux-2.6.38.7/fs/proc/root.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/root.c 2011-04-28 19:34:15.000000000 -0400
+@@ -132,7 +132,15 @@ void __init proc_root_init(void)
+ #ifdef CONFIG_PROC_DEVICETREE
+ proc_device_tree_init();
+ #endif
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ proc_mkdir_mode("bus", S_IRUSR | S_IXUSR, NULL);
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ proc_mkdir_mode("bus", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
++#endif
++#else
+ proc_mkdir("bus", NULL);
++#endif
+ proc_sys_init();
+ }
+
+diff -urNp linux-2.6.38.7/fs/proc/task_mmu.c linux-2.6.38.7/fs/proc/task_mmu.c
+--- linux-2.6.38.7/fs/proc/task_mmu.c 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/fs/proc/task_mmu.c 2011-05-22 23:06:04.000000000 -0400
+@@ -49,8 +49,13 @@ void task_mem(struct seq_file *m, struct
+ "VmExe:\t%8lu kB\n"
+ "VmLib:\t%8lu kB\n"
+ "VmPTE:\t%8lu kB\n"
+- "VmSwap:\t%8lu kB\n",
+- hiwater_vm << (PAGE_SHIFT-10),
++ "VmSwap:\t%8lu kB\n"
++
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
++ "CsBase:\t%8lx\nCsLim:\t%8lx\n"
++#endif
++
++ ,hiwater_vm << (PAGE_SHIFT-10),
+ (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
+ mm->locked_vm << (PAGE_SHIFT-10),
+ hiwater_rss << (PAGE_SHIFT-10),
+@@ -58,7 +63,13 @@ void task_mem(struct seq_file *m, struct
+ data << (PAGE_SHIFT-10),
+ mm->stack_vm << (PAGE_SHIFT-10), text, lib,
+ (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10,
+- swap << (PAGE_SHIFT-10));
++ swap << (PAGE_SHIFT-10)
++
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
++ , mm->context.user_cs_base, mm->context.user_cs_limit
++#endif
++
++ );
+ }
+
+ unsigned long task_vsize(struct mm_struct *mm)
+@@ -180,7 +191,8 @@ static void m_stop(struct seq_file *m, v
+ struct proc_maps_private *priv = m->private;
+ struct vm_area_struct *vma = v;
+
+- vma_stop(priv, vma);
++ if (!IS_ERR(vma))
++ vma_stop(priv, vma);
+ if (priv->task)
+ put_task_struct(priv->task);
+ }
+@@ -204,6 +216,12 @@ static int do_maps_open(struct inode *in
+ return ret;
+ }
+
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
++ (_mm->pax_flags & MF_PAX_RANDMMAP || \
++ _mm->pax_flags & MF_PAX_SEGMEXEC))
++#endif
++
+ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
+ {
+ struct mm_struct *mm = vma->vm_mm;
+@@ -211,7 +229,6 @@ static void show_map_vma(struct seq_file
+ int flags = vma->vm_flags;
+ unsigned long ino = 0;
+ unsigned long long pgoff = 0;
+- unsigned long start, end;
+ dev_t dev = 0;
+ int len;
+
+@@ -222,22 +239,23 @@ static void show_map_vma(struct seq_file
+ pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
+ }
+
+- /* We don't show the stack guard page in /proc/maps */
+- start = vma->vm_start;
+- if (stack_guard_page_start(vma, start))
+- start += PAGE_SIZE;
+- end = vma->vm_end;
+- if (stack_guard_page_end(vma, end))
+- end -= PAGE_SIZE;
+-
+ seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
+- start,
+- end,
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_start,
++ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_end,
++#else
++ vma->vm_start,
++ vma->vm_end,
++#endif
+ flags & VM_READ ? 'r' : '-',
+ flags & VM_WRITE ? 'w' : '-',
+ flags & VM_EXEC ? 'x' : '-',
+ flags & VM_MAYSHARE ? 's' : 'p',
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ PAX_RAND_FLAGS(mm) ? 0UL : pgoff,
++#else
+ pgoff,
++#endif
+ MAJOR(dev), MINOR(dev), ino, &len);
+
+ /*
+@@ -246,16 +264,16 @@ static void show_map_vma(struct seq_file
+ */
+ if (file) {
+ pad_len_spaces(m, len);
+- seq_path(m, &file->f_path, "\n");
++ seq_path(m, &file->f_path, "\n\\");
+ } else {
+ const char *name = arch_vma_name(vma);
+ if (!name) {
+ if (mm) {
+- if (vma->vm_start <= mm->brk &&
+- vma->vm_end >= mm->start_brk) {
++ if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
+ name = "[heap]";
+- } else if (vma->vm_start <= mm->start_stack &&
+- vma->vm_end >= mm->start_stack) {
++ } else if ((vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP)) ||
++ (vma->vm_start <= mm->start_stack &&
++ vma->vm_end >= mm->start_stack)) {
+ name = "[stack]";
+ }
+ } else {
+@@ -401,11 +419,16 @@ static int show_smap(struct seq_file *m,
+ };
+
+ memset(&mss, 0, sizeof mss);
+- mss.vma = vma;
+- /* mmap_sem is held in m_start */
+- if (vma->vm_mm && !is_vm_hugetlb_page(vma))
+- walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
+-
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ if (!PAX_RAND_FLAGS(vma->vm_mm)) {
++#endif
++ mss.vma = vma;
++ /* mmap_sem is held in m_start */
++ if (vma->vm_mm && !is_vm_hugetlb_page(vma))
++ walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ }
++#endif
+ show_map_vma(m, vma);
+
+ seq_printf(m,
+@@ -422,7 +445,11 @@ static int show_smap(struct seq_file *m,
+ "KernelPageSize: %8lu kB\n"
+ "MMUPageSize: %8lu kB\n"
+ "Locked: %8lu kB\n",
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ PAX_RAND_FLAGS(vma->vm_mm) ? 0UL : (vma->vm_end - vma->vm_start) >> 10,
++#else
+ (vma->vm_end - vma->vm_start) >> 10,
++#endif
+ mss.resident >> 10,
+ (unsigned long)(mss.pss >> (10 + PSS_SHIFT)),
+ mss.shared_clean >> 10,
+diff -urNp linux-2.6.38.7/fs/proc/task_nommu.c linux-2.6.38.7/fs/proc/task_nommu.c
+--- linux-2.6.38.7/fs/proc/task_nommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/proc/task_nommu.c 2011-04-28 19:34:15.000000000 -0400
+@@ -51,7 +51,7 @@ void task_mem(struct seq_file *m, struct
+ else
+ bytes += kobjsize(mm);
+
+- if (current->fs && current->fs->users > 1)
++ if (current->fs && atomic_read(&current->fs->users) > 1)
+ sbytes += kobjsize(current->fs);
+ else
+ bytes += kobjsize(current->fs);
+@@ -166,7 +166,7 @@ static int nommu_vma_show(struct seq_fil
+
+ if (file) {
+ pad_len_spaces(m, len);
+- seq_path(m, &file->f_path, "");
++ seq_path(m, &file->f_path, "\n\\");
+ } else if (mm) {
+ if (vma->vm_start <= mm->start_stack &&
+ vma->vm_end >= mm->start_stack) {
+diff -urNp linux-2.6.38.7/fs/quota/netlink.c linux-2.6.38.7/fs/quota/netlink.c
+--- linux-2.6.38.7/fs/quota/netlink.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/quota/netlink.c 2011-04-28 19:57:25.000000000 -0400
+@@ -33,7 +33,7 @@ static struct genl_family quota_genl_fam
+ void quota_send_warning(short type, unsigned int id, dev_t dev,
+ const char warntype)
+ {
+- static atomic_t seq;
++ static atomic_unchecked_t seq;
+ struct sk_buff *skb;
+ void *msg_head;
+ int ret;
+@@ -49,7 +49,7 @@ void quota_send_warning(short type, unsi
+ "VFS: Not enough memory to send quota warning.\n");
+ return;
+ }
+- msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
++ msg_head = genlmsg_put(skb, 0, atomic_add_return_unchecked(1, &seq),
+ &quota_genl_family, 0, QUOTA_NL_C_WARNING);
+ if (!msg_head) {
+ printk(KERN_ERR
+diff -urNp linux-2.6.38.7/fs/readdir.c linux-2.6.38.7/fs/readdir.c
+--- linux-2.6.38.7/fs/readdir.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/readdir.c 2011-04-28 19:34:15.000000000 -0400
+@@ -17,6 +17,7 @@
+ #include <linux/security.h>
+ #include <linux/syscalls.h>
+ #include <linux/unistd.h>
++#include <linux/namei.h>
+
+ #include <asm/uaccess.h>
+
+@@ -67,6 +68,7 @@ struct old_linux_dirent {
+
+ struct readdir_callback {
+ struct old_linux_dirent __user * dirent;
++ struct file * file;
+ int result;
+ };
+
+@@ -84,6 +86,10 @@ static int fillonedir(void * __buf, cons
+ buf->result = -EOVERFLOW;
+ return -EOVERFLOW;
+ }
++
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
++ return 0;
++
+ buf->result++;
+ dirent = buf->dirent;
+ if (!access_ok(VERIFY_WRITE, dirent,
+@@ -116,6 +122,7 @@ SYSCALL_DEFINE3(old_readdir, unsigned in
+
+ buf.result = 0;
+ buf.dirent = dirent;
++ buf.file = file;
+
+ error = vfs_readdir(file, fillonedir, &buf);
+ if (buf.result)
+@@ -142,6 +149,7 @@ struct linux_dirent {
+ struct getdents_callback {
+ struct linux_dirent __user * current_dir;
+ struct linux_dirent __user * previous;
++ struct file * file;
+ int count;
+ int error;
+ };
+@@ -163,6 +171,10 @@ static int filldir(void * __buf, const c
+ buf->error = -EOVERFLOW;
+ return -EOVERFLOW;
+ }
++
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
++ return 0;
++
+ dirent = buf->previous;
+ if (dirent) {
+ if (__put_user(offset, &dirent->d_off))
+@@ -210,6 +222,7 @@ SYSCALL_DEFINE3(getdents, unsigned int,
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
++ buf.file = file;
+
+ error = vfs_readdir(file, filldir, &buf);
+ if (error >= 0)
+@@ -229,6 +242,7 @@ out:
+ struct getdents_callback64 {
+ struct linux_dirent64 __user * current_dir;
+ struct linux_dirent64 __user * previous;
++ struct file *file;
+ int count;
+ int error;
+ };
+@@ -244,6 +258,10 @@ static int filldir64(void * __buf, const
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
++
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
++ return 0;
++
+ dirent = buf->previous;
+ if (dirent) {
+ if (__put_user(offset, &dirent->d_off))
+@@ -291,6 +309,7 @@ SYSCALL_DEFINE3(getdents64, unsigned int
+
+ buf.current_dir = dirent;
+ buf.previous = NULL;
++ buf.file = file;
+ buf.count = count;
+ buf.error = 0;
+
+diff -urNp linux-2.6.38.7/fs/reiserfs/dir.c linux-2.6.38.7/fs/reiserfs/dir.c
+--- linux-2.6.38.7/fs/reiserfs/dir.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/reiserfs/dir.c 2011-05-16 21:47:09.000000000 -0400
+@@ -66,6 +66,8 @@ int reiserfs_readdir_dentry(struct dentr
+ struct reiserfs_dir_entry de;
+ int ret = 0;
+
++ pax_track_stack();
++
+ reiserfs_write_lock(inode->i_sb);
+
+ reiserfs_check_lock_depth(inode->i_sb, "readdir");
+diff -urNp linux-2.6.38.7/fs/reiserfs/do_balan.c linux-2.6.38.7/fs/reiserfs/do_balan.c
+--- linux-2.6.38.7/fs/reiserfs/do_balan.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/reiserfs/do_balan.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2051,7 +2051,7 @@ void do_balance(struct tree_balance *tb,
+ return;
+ }
+
+- atomic_inc(&(fs_generation(tb->tb_sb)));
++ atomic_inc_unchecked(&(fs_generation(tb->tb_sb)));
+ do_balance_starts(tb);
+
+ /* balance leaf returns 0 except if combining L R and S into
+diff -urNp linux-2.6.38.7/fs/reiserfs/item_ops.c linux-2.6.38.7/fs/reiserfs/item_ops.c
+--- linux-2.6.38.7/fs/reiserfs/item_ops.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/reiserfs/item_ops.c 2011-04-28 19:34:15.000000000 -0400
+@@ -102,7 +102,7 @@ static void sd_print_vi(struct virtual_i
+ vi->vi_index, vi->vi_type, vi->vi_ih);
+ }
+
+-static struct item_operations stat_data_ops = {
++static const struct item_operations stat_data_ops = {
+ .bytes_number = sd_bytes_number,
+ .decrement_key = sd_decrement_key,
+ .is_left_mergeable = sd_is_left_mergeable,
+@@ -196,7 +196,7 @@ static void direct_print_vi(struct virtu
+ vi->vi_index, vi->vi_type, vi->vi_ih);
+ }
+
+-static struct item_operations direct_ops = {
++static const struct item_operations direct_ops = {
+ .bytes_number = direct_bytes_number,
+ .decrement_key = direct_decrement_key,
+ .is_left_mergeable = direct_is_left_mergeable,
+@@ -341,7 +341,7 @@ static void indirect_print_vi(struct vir
+ vi->vi_index, vi->vi_type, vi->vi_ih);
+ }
+
+-static struct item_operations indirect_ops = {
++static const struct item_operations indirect_ops = {
+ .bytes_number = indirect_bytes_number,
+ .decrement_key = indirect_decrement_key,
+ .is_left_mergeable = indirect_is_left_mergeable,
+@@ -628,7 +628,7 @@ static void direntry_print_vi(struct vir
+ printk("\n");
+ }
+
+-static struct item_operations direntry_ops = {
++static const struct item_operations direntry_ops = {
+ .bytes_number = direntry_bytes_number,
+ .decrement_key = direntry_decrement_key,
+ .is_left_mergeable = direntry_is_left_mergeable,
+@@ -724,7 +724,7 @@ static void errcatch_print_vi(struct vir
+ "Invalid item type observed, run fsck ASAP");
+ }
+
+-static struct item_operations errcatch_ops = {
++static const struct item_operations errcatch_ops = {
+ errcatch_bytes_number,
+ errcatch_decrement_key,
+ errcatch_is_left_mergeable,
+@@ -746,7 +746,7 @@ static struct item_operations errcatch_o
+ #error Item types must use disk-format assigned values.
+ #endif
+
+-struct item_operations *item_ops[TYPE_ANY + 1] = {
++const struct item_operations * const item_ops[TYPE_ANY + 1] = {
+ &stat_data_ops,
+ &indirect_ops,
+ &direct_ops,
+diff -urNp linux-2.6.38.7/fs/reiserfs/journal.c linux-2.6.38.7/fs/reiserfs/journal.c
+--- linux-2.6.38.7/fs/reiserfs/journal.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/reiserfs/journal.c 2011-05-16 21:47:09.000000000 -0400
+@@ -2299,6 +2299,8 @@ static struct buffer_head *reiserfs_brea
+ struct buffer_head *bh;
+ int i, j;
+
++ pax_track_stack();
++
+ bh = __getblk(dev, block, bufsize);
+ if (buffer_uptodate(bh))
+ return (bh);
+diff -urNp linux-2.6.38.7/fs/reiserfs/namei.c linux-2.6.38.7/fs/reiserfs/namei.c
+--- linux-2.6.38.7/fs/reiserfs/namei.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/reiserfs/namei.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1228,6 +1228,8 @@ static int reiserfs_rename(struct inode
+ unsigned long savelink = 1;
+ struct timespec ctime;
+
++ pax_track_stack();
++
+ /* three balancings: (1) old name removal, (2) new name insertion
+ and (3) maybe "save" link insertion
+ stat data updates: (1) old directory,
+diff -urNp linux-2.6.38.7/fs/reiserfs/procfs.c linux-2.6.38.7/fs/reiserfs/procfs.c
+--- linux-2.6.38.7/fs/reiserfs/procfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/reiserfs/procfs.c 2011-05-16 21:47:08.000000000 -0400
+@@ -113,7 +113,7 @@ static int show_super(struct seq_file *m
+ "SMALL_TAILS " : "NO_TAILS ",
+ replay_only(sb) ? "REPLAY_ONLY " : "",
+ convert_reiserfs(sb) ? "CONV " : "",
+- atomic_read(&r->s_generation_counter),
++ atomic_read_unchecked(&r->s_generation_counter),
+ SF(s_disk_reads), SF(s_disk_writes), SF(s_fix_nodes),
+ SF(s_do_balance), SF(s_unneeded_left_neighbor),
+ SF(s_good_search_by_key_reada), SF(s_bmaps),
+@@ -299,6 +299,8 @@ static int show_journal(struct seq_file
+ struct journal_params *jp = &rs->s_v1.s_journal;
+ char b[BDEVNAME_SIZE];
+
++ pax_track_stack();
++
+ seq_printf(m, /* on-disk fields */
+ "jp_journal_1st_block: \t%i\n"
+ "jp_journal_dev: \t%s[%x]\n"
+diff -urNp linux-2.6.38.7/fs/reiserfs/stree.c linux-2.6.38.7/fs/reiserfs/stree.c
+--- linux-2.6.38.7/fs/reiserfs/stree.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/reiserfs/stree.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1196,6 +1196,8 @@ int reiserfs_delete_item(struct reiserfs
+ int iter = 0;
+ #endif
+
++ pax_track_stack();
++
+ BUG_ON(!th->t_trans_id);
+
+ init_tb_struct(th, &s_del_balance, sb, path,
+@@ -1333,6 +1335,8 @@ void reiserfs_delete_solid_item(struct r
+ int retval;
+ int quota_cut_bytes = 0;
+
++ pax_track_stack();
++
+ BUG_ON(!th->t_trans_id);
+
+ le_key2cpu_key(&cpu_key, key);
+@@ -1562,6 +1566,8 @@ int reiserfs_cut_from_item(struct reiser
+ int quota_cut_bytes;
+ loff_t tail_pos = 0;
+
++ pax_track_stack();
++
+ BUG_ON(!th->t_trans_id);
+
+ init_tb_struct(th, &s_cut_balance, inode->i_sb, path,
+@@ -1957,6 +1963,8 @@ int reiserfs_paste_into_item(struct reis
+ int retval;
+ int fs_gen;
+
++ pax_track_stack();
++
+ BUG_ON(!th->t_trans_id);
+
+ fs_gen = get_generation(inode->i_sb);
+@@ -2045,6 +2053,8 @@ int reiserfs_insert_item(struct reiserfs
+ int fs_gen = 0;
+ int quota_bytes = 0;
+
++ pax_track_stack();
++
+ BUG_ON(!th->t_trans_id);
+
+ if (inode) { /* Do we count quotas for item? */
+diff -urNp linux-2.6.38.7/fs/reiserfs/super.c linux-2.6.38.7/fs/reiserfs/super.c
+--- linux-2.6.38.7/fs/reiserfs/super.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/reiserfs/super.c 2011-05-16 21:47:09.000000000 -0400
+@@ -927,6 +927,8 @@ static int reiserfs_parse_options(struct
+ {.option_name = NULL}
+ };
+
++ pax_track_stack();
++
+ *blocks = 0;
+ if (!options || !*options)
+ /* use default configuration: create tails, journaling on, no
+diff -urNp linux-2.6.38.7/fs/select.c linux-2.6.38.7/fs/select.c
+--- linux-2.6.38.7/fs/select.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/select.c 2011-05-16 21:47:08.000000000 -0400
+@@ -20,6 +20,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/poll.h>
++#include <linux/security.h>
+ #include <linux/personality.h> /* for STICKY_TIMEOUTS */
+ #include <linux/file.h>
+ #include <linux/fdtable.h>
+@@ -403,6 +404,8 @@ int do_select(int n, fd_set_bits *fds, s
+ int retval, i, timed_out = 0;
+ unsigned long slack = 0;
+
++ pax_track_stack();
++
+ rcu_read_lock();
+ retval = max_select_fd(n, fds);
+ rcu_read_unlock();
+@@ -531,6 +534,8 @@ int core_sys_select(int n, fd_set __user
+ /* Allocate small arguments on the stack to save memory and be faster */
+ long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
+
++ pax_track_stack();
++
+ ret = -EINVAL;
+ if (n < 0)
+ goto out_nofds;
+@@ -840,6 +845,9 @@ int do_sys_poll(struct pollfd __user *uf
+ struct poll_list *walk = head;
+ unsigned long todo = nfds;
+
++ pax_track_stack();
++
++ gr_learn_resource(current, RLIMIT_NOFILE, nfds, 1);
+ if (nfds > rlimit(RLIMIT_NOFILE))
+ return -EINVAL;
+
+diff -urNp linux-2.6.38.7/fs/seq_file.c linux-2.6.38.7/fs/seq_file.c
+--- linux-2.6.38.7/fs/seq_file.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/seq_file.c 2011-04-28 19:34:15.000000000 -0400
+@@ -76,7 +76,8 @@ static int traverse(struct seq_file *m,
+ return 0;
+ }
+ if (!m->buf) {
+- m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
++ m->size = PAGE_SIZE;
++ m->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!m->buf)
+ return -ENOMEM;
+ }
+@@ -116,7 +117,8 @@ static int traverse(struct seq_file *m,
+ Eoverflow:
+ m->op->stop(m, p);
+ kfree(m->buf);
+- m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
++ m->size <<= 1;
++ m->buf = kmalloc(m->size, GFP_KERNEL);
+ return !m->buf ? -ENOMEM : -EAGAIN;
+ }
+
+@@ -169,7 +171,8 @@ ssize_t seq_read(struct file *file, char
+ m->version = file->f_version;
+ /* grab buffer if we didn't have one */
+ if (!m->buf) {
+- m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
++ m->size = PAGE_SIZE;
++ m->buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!m->buf)
+ goto Enomem;
+ }
+@@ -210,7 +213,8 @@ ssize_t seq_read(struct file *file, char
+ goto Fill;
+ m->op->stop(m, p);
+ kfree(m->buf);
+- m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
++ m->size <<= 1;
++ m->buf = kmalloc(m->size, GFP_KERNEL);
+ if (!m->buf)
+ goto Enomem;
+ m->count = 0;
+diff -urNp linux-2.6.38.7/fs/splice.c linux-2.6.38.7/fs/splice.c
+--- linux-2.6.38.7/fs/splice.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/splice.c 2011-05-16 21:47:08.000000000 -0400
+@@ -186,7 +186,7 @@ ssize_t splice_to_pipe(struct pipe_inode
+ pipe_lock(pipe);
+
+ for (;;) {
+- if (!pipe->readers) {
++ if (!atomic_read(&pipe->readers)) {
+ send_sig(SIGPIPE, current, 0);
+ if (!ret)
+ ret = -EPIPE;
+@@ -240,9 +240,9 @@ ssize_t splice_to_pipe(struct pipe_inode
+ do_wakeup = 0;
+ }
+
+- pipe->waiting_writers++;
++ atomic_inc(&pipe->waiting_writers);
+ pipe_wait(pipe);
+- pipe->waiting_writers--;
++ atomic_dec(&pipe->waiting_writers);
+ }
+
+ pipe_unlock(pipe);
+@@ -316,6 +316,8 @@ __generic_file_splice_read(struct file *
+ .spd_release = spd_release_page,
+ };
+
++ pax_track_stack();
++
+ if (splice_grow_spd(pipe, &spd))
+ return -ENOMEM;
+
+@@ -556,7 +558,7 @@ static ssize_t kernel_readv(struct file
+ old_fs = get_fs();
+ set_fs(get_ds());
+ /* The cast to a user pointer is valid due to the set_fs() */
+- res = vfs_readv(file, (const struct iovec __user *)vec, vlen, &pos);
++ res = vfs_readv(file, (__force const struct iovec __user *)vec, vlen, &pos);
+ set_fs(old_fs);
+
+ return res;
+@@ -571,7 +573,7 @@ static ssize_t kernel_write(struct file
+ old_fs = get_fs();
+ set_fs(get_ds());
+ /* The cast to a user pointer is valid due to the set_fs() */
+- res = vfs_write(file, (const char __user *)buf, count, &pos);
++ res = vfs_write(file, (__force const char __user *)buf, count, &pos);
+ set_fs(old_fs);
+
+ return res;
+@@ -599,6 +601,8 @@ ssize_t default_file_splice_read(struct
+ .spd_release = spd_release_page,
+ };
+
++ pax_track_stack();
++
+ if (splice_grow_spd(pipe, &spd))
+ return -ENOMEM;
+
+@@ -622,7 +626,7 @@ ssize_t default_file_splice_read(struct
+ goto err;
+
+ this_len = min_t(size_t, len, PAGE_CACHE_SIZE - offset);
+- vec[i].iov_base = (void __user *) page_address(page);
++ vec[i].iov_base = (__force void __user *) page_address(page);
+ vec[i].iov_len = this_len;
+ spd.pages[i] = page;
+ spd.nr_pages++;
+@@ -842,10 +846,10 @@ EXPORT_SYMBOL(splice_from_pipe_feed);
+ int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_desc *sd)
+ {
+ while (!pipe->nrbufs) {
+- if (!pipe->writers)
++ if (!atomic_read(&pipe->writers))
+ return 0;
+
+- if (!pipe->waiting_writers && sd->num_spliced)
++ if (!atomic_read(&pipe->waiting_writers) && sd->num_spliced)
+ return 0;
+
+ if (sd->flags & SPLICE_F_NONBLOCK)
+@@ -1178,7 +1182,7 @@ ssize_t splice_direct_to_actor(struct fi
+ * out of the pipe right after the splice_to_pipe(). So set
+ * PIPE_READERS appropriately.
+ */
+- pipe->readers = 1;
++ atomic_set(&pipe->readers, 1);
+
+ current->splice_pipe = pipe;
+ }
+@@ -1615,6 +1619,8 @@ static long vmsplice_to_pipe(struct file
+ };
+ long ret;
+
++ pax_track_stack();
++
+ pipe = get_pipe_info(file);
+ if (!pipe)
+ return -EBADF;
+@@ -1730,9 +1736,9 @@ static int ipipe_prep(struct pipe_inode_
+ ret = -ERESTARTSYS;
+ break;
+ }
+- if (!pipe->writers)
++ if (!atomic_read(&pipe->writers))
+ break;
+- if (!pipe->waiting_writers) {
++ if (!atomic_read(&pipe->waiting_writers)) {
+ if (flags & SPLICE_F_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+@@ -1764,7 +1770,7 @@ static int opipe_prep(struct pipe_inode_
+ pipe_lock(pipe);
+
+ while (pipe->nrbufs >= pipe->buffers) {
+- if (!pipe->readers) {
++ if (!atomic_read(&pipe->readers)) {
+ send_sig(SIGPIPE, current, 0);
+ ret = -EPIPE;
+ break;
+@@ -1777,9 +1783,9 @@ static int opipe_prep(struct pipe_inode_
+ ret = -ERESTARTSYS;
+ break;
+ }
+- pipe->waiting_writers++;
++ atomic_inc(&pipe->waiting_writers);
+ pipe_wait(pipe);
+- pipe->waiting_writers--;
++ atomic_dec(&pipe->waiting_writers);
+ }
+
+ pipe_unlock(pipe);
+@@ -1815,14 +1821,14 @@ retry:
+ pipe_double_lock(ipipe, opipe);
+
+ do {
+- if (!opipe->readers) {
++ if (!atomic_read(&opipe->readers)) {
+ send_sig(SIGPIPE, current, 0);
+ if (!ret)
+ ret = -EPIPE;
+ break;
+ }
+
+- if (!ipipe->nrbufs && !ipipe->writers)
++ if (!ipipe->nrbufs && !atomic_read(&ipipe->writers))
+ break;
+
+ /*
+@@ -1922,7 +1928,7 @@ static int link_pipe(struct pipe_inode_i
+ pipe_double_lock(ipipe, opipe);
+
+ do {
+- if (!opipe->readers) {
++ if (!atomic_read(&opipe->readers)) {
+ send_sig(SIGPIPE, current, 0);
+ if (!ret)
+ ret = -EPIPE;
+@@ -1967,7 +1973,7 @@ static int link_pipe(struct pipe_inode_i
+ * return EAGAIN if we have the potential of some data in the
+ * future, otherwise just return 0
+ */
+- if (!ret && ipipe->waiting_writers && (flags & SPLICE_F_NONBLOCK))
++ if (!ret && atomic_read(&ipipe->waiting_writers) && (flags & SPLICE_F_NONBLOCK))
+ ret = -EAGAIN;
+
+ pipe_unlock(ipipe);
+diff -urNp linux-2.6.38.7/fs/sysfs/file.c linux-2.6.38.7/fs/sysfs/file.c
+--- linux-2.6.38.7/fs/sysfs/file.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/sysfs/file.c 2011-04-28 19:57:25.000000000 -0400
+@@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(sysfs_open_dirent
+
+ struct sysfs_open_dirent {
+ atomic_t refcnt;
+- atomic_t event;
++ atomic_unchecked_t event;
+ wait_queue_head_t poll;
+ struct list_head buffers; /* goes through sysfs_buffer.list */
+ };
+@@ -88,7 +88,7 @@ static int fill_read_buffer(struct dentr
+ if (!sysfs_get_active(attr_sd))
+ return -ENODEV;
+
+- buffer->event = atomic_read(&attr_sd->s_attr.open->event);
++ buffer->event = atomic_read_unchecked(&attr_sd->s_attr.open->event);
+ count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);
+
+ sysfs_put_active(attr_sd);
+@@ -294,7 +294,7 @@ static int sysfs_get_open_dirent(struct
+ return -ENOMEM;
+
+ atomic_set(&new_od->refcnt, 0);
+- atomic_set(&new_od->event, 1);
++ atomic_set_unchecked(&new_od->event, 1);
+ init_waitqueue_head(&new_od->poll);
+ INIT_LIST_HEAD(&new_od->buffers);
+ goto retry;
+@@ -444,7 +444,7 @@ static unsigned int sysfs_poll(struct fi
+
+ sysfs_put_active(attr_sd);
+
+- if (buffer->event != atomic_read(&od->event))
++ if (buffer->event != atomic_read_unchecked(&od->event))
+ goto trigger;
+
+ return DEFAULT_POLLMASK;
+@@ -463,7 +463,7 @@ void sysfs_notify_dirent(struct sysfs_di
+
+ od = sd->s_attr.open;
+ if (od) {
+- atomic_inc(&od->event);
++ atomic_inc_unchecked(&od->event);
+ wake_up_interruptible(&od->poll);
+ }
+
+diff -urNp linux-2.6.38.7/fs/sysfs/mount.c linux-2.6.38.7/fs/sysfs/mount.c
+--- linux-2.6.38.7/fs/sysfs/mount.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/sysfs/mount.c 2011-04-28 19:34:15.000000000 -0400
+@@ -36,7 +36,11 @@ struct sysfs_dirent sysfs_root = {
+ .s_name = "",
+ .s_count = ATOMIC_INIT(1),
+ .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT),
++#ifdef CONFIG_GRKERNSEC_SYSFS_RESTRICT
++ .s_mode = S_IFDIR | S_IRWXU,
++#else
+ .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
++#endif
+ .s_ino = 1,
+ };
+
+diff -urNp linux-2.6.38.7/fs/sysfs/symlink.c linux-2.6.38.7/fs/sysfs/symlink.c
+--- linux-2.6.38.7/fs/sysfs/symlink.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/sysfs/symlink.c 2011-04-28 19:34:15.000000000 -0400
+@@ -286,7 +286,7 @@ static void *sysfs_follow_link(struct de
+
+ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+ {
+- char *page = nd_get_link(nd);
++ const char *page = nd_get_link(nd);
+ if (!IS_ERR(page))
+ free_page((unsigned long)page);
+ }
+diff -urNp linux-2.6.38.7/fs/udf/inode.c linux-2.6.38.7/fs/udf/inode.c
+--- linux-2.6.38.7/fs/udf/inode.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/udf/inode.c 2011-05-16 21:47:09.000000000 -0400
+@@ -477,6 +477,8 @@ static struct buffer_head *inode_getblk(
+ int goal = 0, pgoal = iinfo->i_location.logicalBlockNum;
+ int lastblock = 0;
+
++ pax_track_stack();
++
+ prev_epos.offset = udf_file_entry_alloc_offset(inode);
+ prev_epos.block = iinfo->i_location;
+ prev_epos.bh = NULL;
+diff -urNp linux-2.6.38.7/fs/udf/misc.c linux-2.6.38.7/fs/udf/misc.c
+--- linux-2.6.38.7/fs/udf/misc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/udf/misc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -286,7 +286,7 @@ void udf_new_tag(char *data, uint16_t id
+
+ u8 udf_tag_checksum(const struct tag *t)
+ {
+- u8 *data = (u8 *)t;
++ const u8 *data = (const u8 *)t;
+ u8 checksum = 0;
+ int i;
+ for (i = 0; i < sizeof(struct tag); ++i)
+diff -urNp linux-2.6.38.7/fs/utimes.c linux-2.6.38.7/fs/utimes.c
+--- linux-2.6.38.7/fs/utimes.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/utimes.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1,6 +1,7 @@
+ #include <linux/compiler.h>
+ #include <linux/file.h>
+ #include <linux/fs.h>
++#include <linux/security.h>
+ #include <linux/linkage.h>
+ #include <linux/mount.h>
+ #include <linux/namei.h>
+@@ -101,6 +102,12 @@ static int utimes_common(struct path *pa
+ goto mnt_drop_write_and_out;
+ }
+ }
++
++ if (!gr_acl_handle_utime(path->dentry, path->mnt)) {
++ error = -EACCES;
++ goto mnt_drop_write_and_out;
++ }
++
+ mutex_lock(&inode->i_mutex);
+ error = notify_change(path->dentry, &newattrs);
+ mutex_unlock(&inode->i_mutex);
+diff -urNp linux-2.6.38.7/fs/xattr_acl.c linux-2.6.38.7/fs/xattr_acl.c
+--- linux-2.6.38.7/fs/xattr_acl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/xattr_acl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -17,8 +17,8 @@
+ struct posix_acl *
+ posix_acl_from_xattr(const void *value, size_t size)
+ {
+- posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
+- posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
++ const posix_acl_xattr_header *header = (const posix_acl_xattr_header *)value;
++ const posix_acl_xattr_entry *entry = (const posix_acl_xattr_entry *)(header+1), *end;
+ int count;
+ struct posix_acl *acl;
+ struct posix_acl_entry *acl_e;
+diff -urNp linux-2.6.38.7/fs/xattr.c linux-2.6.38.7/fs/xattr.c
+--- linux-2.6.38.7/fs/xattr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/xattr.c 2011-04-28 19:34:15.000000000 -0400
+@@ -247,7 +247,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
+ * Extended attribute SET operations
+ */
+ static long
+-setxattr(struct dentry *d, const char __user *name, const void __user *value,
++setxattr(struct path *path, const char __user *name, const void __user *value,
+ size_t size, int flags)
+ {
+ int error;
+@@ -271,7 +271,13 @@ setxattr(struct dentry *d, const char __
+ return PTR_ERR(kvalue);
+ }
+
+- error = vfs_setxattr(d, kname, kvalue, size, flags);
++ if (!gr_acl_handle_setxattr(path->dentry, path->mnt)) {
++ error = -EACCES;
++ goto out;
++ }
++
++ error = vfs_setxattr(path->dentry, kname, kvalue, size, flags);
++out:
+ kfree(kvalue);
+ return error;
+ }
+@@ -288,7 +294,7 @@ SYSCALL_DEFINE5(setxattr, const char __u
+ return error;
+ error = mnt_want_write(path.mnt);
+ if (!error) {
+- error = setxattr(path.dentry, name, value, size, flags);
++ error = setxattr(&path, name, value, size, flags);
+ mnt_drop_write(path.mnt);
+ }
+ path_put(&path);
+@@ -307,7 +313,7 @@ SYSCALL_DEFINE5(lsetxattr, const char __
+ return error;
+ error = mnt_want_write(path.mnt);
+ if (!error) {
+- error = setxattr(path.dentry, name, value, size, flags);
++ error = setxattr(&path, name, value, size, flags);
+ mnt_drop_write(path.mnt);
+ }
+ path_put(&path);
+@@ -318,17 +324,15 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, cons
+ const void __user *,value, size_t, size, int, flags)
+ {
+ struct file *f;
+- struct dentry *dentry;
+ int error = -EBADF;
+
+ f = fget(fd);
+ if (!f)
+ return error;
+- dentry = f->f_path.dentry;
+- audit_inode(NULL, dentry);
++ audit_inode(NULL, f->f_path.dentry);
+ error = mnt_want_write_file(f);
+ if (!error) {
+- error = setxattr(dentry, name, value, size, flags);
++ error = setxattr(&f->f_path, name, value, size, flags);
+ mnt_drop_write(f->f_path.mnt);
+ }
+ fput(f);
+diff -urNp linux-2.6.38.7/fs/xfs/linux-2.6/xfs_ioctl32.c linux-2.6.38.7/fs/xfs/linux-2.6/xfs_ioctl32.c
+--- linux-2.6.38.7/fs/xfs/linux-2.6/xfs_ioctl32.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/xfs/linux-2.6/xfs_ioctl32.c 2011-04-28 19:34:15.000000000 -0400
+@@ -73,6 +73,7 @@ xfs_compat_ioc_fsgeometry_v1(
+ xfs_fsop_geom_t fsgeo;
+ int error;
+
++ memset(&fsgeo, 0, sizeof(fsgeo));
+ error = xfs_fs_geometry(mp, &fsgeo, 3);
+ if (error)
+ return -error;
+diff -urNp linux-2.6.38.7/fs/xfs/linux-2.6/xfs_ioctl.c linux-2.6.38.7/fs/xfs/linux-2.6/xfs_ioctl.c
+--- linux-2.6.38.7/fs/xfs/linux-2.6/xfs_ioctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/xfs/linux-2.6/xfs_ioctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -128,7 +128,7 @@ xfs_find_handle(
+ }
+
+ error = -EFAULT;
+- if (copy_to_user(hreq->ohandle, &handle, hsize) ||
++ if (hsize > sizeof handle || copy_to_user(hreq->ohandle, &handle, hsize) ||
+ copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
+ goto out_put;
+
+diff -urNp linux-2.6.38.7/fs/xfs/linux-2.6/xfs_iops.c linux-2.6.38.7/fs/xfs/linux-2.6/xfs_iops.c
+--- linux-2.6.38.7/fs/xfs/linux-2.6/xfs_iops.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/xfs/linux-2.6/xfs_iops.c 2011-04-28 19:34:15.000000000 -0400
+@@ -436,7 +436,7 @@ xfs_vn_put_link(
+ struct nameidata *nd,
+ void *p)
+ {
+- char *s = nd_get_link(nd);
++ const char *s = nd_get_link(nd);
+
+ if (!IS_ERR(s))
+ kfree(s);
+diff -urNp linux-2.6.38.7/fs/xfs/xfs_bmap.c linux-2.6.38.7/fs/xfs/xfs_bmap.c
+--- linux-2.6.38.7/fs/xfs/xfs_bmap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/xfs/xfs_bmap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -287,7 +287,7 @@ xfs_bmap_validate_ret(
+ int nmap,
+ int ret_nmap);
+ #else
+-#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
++#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap) do {} while (0)
+ #endif /* DEBUG */
+
+ STATIC int
+diff -urNp linux-2.6.38.7/fs/xfs/xfs_dir2_sf.c linux-2.6.38.7/fs/xfs/xfs_dir2_sf.c
+--- linux-2.6.38.7/fs/xfs/xfs_dir2_sf.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/fs/xfs/xfs_dir2_sf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -780,7 +780,15 @@ xfs_dir2_sf_getdents(
+ }
+
+ ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
+- if (filldir(dirent, (char *)sfep->name, sfep->namelen,
++ if (dp->i_df.if_u1.if_data == dp->i_df.if_u2.if_inline_data) {
++ char name[sfep->namelen];
++ memcpy(name, sfep->name, sfep->namelen);
++ if (filldir(dirent, name, sfep->namelen,
++ off & 0x7fffffff, ino, DT_UNKNOWN)) {
++ *offset = off & 0x7fffffff;
++ return 0;
++ }
++ } else if (filldir(dirent, (char *)sfep->name, sfep->namelen,
+ off & 0x7fffffff, ino, DT_UNKNOWN)) {
+ *offset = off & 0x7fffffff;
+ return 0;
+diff -urNp linux-2.6.38.7/grsecurity/gracl_alloc.c linux-2.6.38.7/grsecurity/gracl_alloc.c
+--- linux-2.6.38.7/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl_alloc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,105 @@
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++
++static unsigned long alloc_stack_next = 1;
++static unsigned long alloc_stack_size = 1;
++static void **alloc_stack;
++
++static __inline__ int
++alloc_pop(void)
++{
++ if (alloc_stack_next == 1)
++ return 0;
++
++ kfree(alloc_stack[alloc_stack_next - 2]);
++
++ alloc_stack_next--;
++
++ return 1;
++}
++
++static __inline__ int
++alloc_push(void *buf)
++{
++ if (alloc_stack_next >= alloc_stack_size)
++ return 1;
++
++ alloc_stack[alloc_stack_next - 1] = buf;
++
++ alloc_stack_next++;
++
++ return 0;
++}
++
++void *
++acl_alloc(unsigned long len)
++{
++ void *ret = NULL;
++
++ if (!len || len > PAGE_SIZE)
++ goto out;
++
++ ret = kmalloc(len, GFP_KERNEL);
++
++ if (ret) {
++ if (alloc_push(ret)) {
++ kfree(ret);
++ ret = NULL;
++ }
++ }
++
++out:
++ return ret;
++}
++
++void *
++acl_alloc_num(unsigned long num, unsigned long len)
++{
++ if (!len || (num > (PAGE_SIZE / len)))
++ return NULL;
++
++ return acl_alloc(num * len);
++}
++
++void
++acl_free_all(void)
++{
++ if (gr_acl_is_enabled() || !alloc_stack)
++ return;
++
++ while (alloc_pop()) ;
++
++ if (alloc_stack) {
++ if ((alloc_stack_size * sizeof (void *)) <= PAGE_SIZE)
++ kfree(alloc_stack);
++ else
++ vfree(alloc_stack);
++ }
++
++ alloc_stack = NULL;
++ alloc_stack_size = 1;
++ alloc_stack_next = 1;
++
++ return;
++}
++
++int
++acl_alloc_stack_init(unsigned long size)
++{
++ if ((size * sizeof (void *)) <= PAGE_SIZE)
++ alloc_stack =
++ (void **) kmalloc(size * sizeof (void *), GFP_KERNEL);
++ else
++ alloc_stack = (void **) vmalloc(size * sizeof (void *));
++
++ alloc_stack_size = size;
++
++ if (!alloc_stack)
++ return 0;
++ else
++ return 1;
++}
+diff -urNp linux-2.6.38.7/grsecurity/gracl.c linux-2.6.38.7/grsecurity/gracl.c
+--- linux-2.6.38.7/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl.c 2011-05-17 17:30:19.000000000 -0400
+@@ -0,0 +1,4098 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/namei.h>
++#include <linux/mount.h>
++#include <linux/tty.h>
++#include <linux/proc_fs.h>
++#include <linux/smp_lock.h>
++#include <linux/lglock.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/types.h>
++#include <linux/sysctl.h>
++#include <linux/netdevice.h>
++#include <linux/ptrace.h>
++#include <linux/gracl.h>
++#include <linux/gralloc.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++#include <linux/pid_namespace.h>
++#include <linux/fdtable.h>
++#include <linux/percpu.h>
++
++#include <asm/uaccess.h>
++#include <asm/errno.h>
++#include <asm/mman.h>
++
++static struct acl_role_db acl_role_set;
++static struct name_db name_set;
++static struct inodev_db inodev_set;
++
++/* for keeping track of userspace pointers used for subjects, so we
++ can share references in the kernel as well
++*/
++
++static struct path real_root;
++
++static struct acl_subj_map_db subj_map_set;
++
++static struct acl_role_label *default_role;
++
++static struct acl_role_label *role_list;
++
++static u16 acl_sp_role_value;
++
++extern char *gr_shared_page[4];
++static DEFINE_MUTEX(gr_dev_mutex);
++DEFINE_RWLOCK(gr_inode_lock);
++
++struct gr_arg *gr_usermode;
++
++static unsigned int gr_status __read_only = GR_STATUS_INIT;
++
++extern int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum);
++extern void gr_clear_learn_entries(void);
++
++#ifdef CONFIG_GRKERNSEC_RESLOG
++extern void gr_log_resource(const struct task_struct *task,
++ const int res, const unsigned long wanted, const int gt);
++#endif
++
++unsigned char *gr_system_salt;
++unsigned char *gr_system_sum;
++
++static struct sprole_pw **acl_special_roles = NULL;
++static __u16 num_sprole_pws = 0;
++
++static struct acl_role_label *kernel_role = NULL;
++
++static unsigned int gr_auth_attempts = 0;
++static unsigned long gr_auth_expires = 0UL;
++
++extern struct vfsmount *sock_mnt;
++extern struct vfsmount *pipe_mnt;
++extern struct vfsmount *shm_mnt;
++#ifdef CONFIG_HUGETLBFS
++extern struct vfsmount *hugetlbfs_vfsmount;
++#endif
++
++static struct acl_object_label *fakefs_obj;
++
++extern int gr_init_uidset(void);
++extern void gr_free_uidset(void);
++extern void gr_remove_uid(uid_t uid);
++extern int gr_find_uid(uid_t uid);
++
++DECLARE_BRLOCK(vfsmount_lock);
++
++__inline__ int
++gr_acl_is_enabled(void)
++{
++ return (gr_status & GR_READY);
++}
++
++#ifdef CONFIG_BTRFS_FS
++extern dev_t get_btrfs_dev_from_inode(struct inode *inode);
++extern int btrfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
++#endif
++
++static inline dev_t __get_dev(const struct dentry *dentry)
++{
++#ifdef CONFIG_BTRFS_FS
++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->getattr == &btrfs_getattr)
++ return get_btrfs_dev_from_inode(dentry->d_inode);
++ else
++#endif
++ return dentry->d_inode->i_sb->s_dev;
++}
++
++dev_t gr_get_dev_from_dentry(struct dentry *dentry)
++{
++ return __get_dev(dentry);
++}
++
++static char gr_task_roletype_to_char(struct task_struct *task)
++{
++ switch (task->role->roletype &
++ (GR_ROLE_DEFAULT | GR_ROLE_USER | GR_ROLE_GROUP |
++ GR_ROLE_SPECIAL)) {
++ case GR_ROLE_DEFAULT:
++ return 'D';
++ case GR_ROLE_USER:
++ return 'U';
++ case GR_ROLE_GROUP:
++ return 'G';
++ case GR_ROLE_SPECIAL:
++ return 'S';
++ }
++
++ return 'X';
++}
++
++char gr_roletype_to_char(void)
++{
++ return gr_task_roletype_to_char(current);
++}
++
++__inline__ int
++gr_acl_tpe_check(void)
++{
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++ if (current->role->roletype & GR_ROLE_TPE)
++ return 1;
++ else
++ return 0;
++}
++
++int
++gr_handle_rawio(const struct inode *inode)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ if (inode && S_ISBLK(inode->i_mode) &&
++ grsec_enable_chroot_caps && proc_is_chrooted(current) &&
++ !capable(CAP_SYS_RAWIO))
++ return 1;
++#endif
++ return 0;
++}
++
++static int
++gr_streq(const char *a, const char *b, const unsigned int lena, const unsigned int lenb)
++{
++ if (likely(lena != lenb))
++ return 0;
++
++ return !memcmp(a, b, lena);
++}
++
++static int prepend(char **buffer, int *buflen, const char *str, int namelen)
++{
++ *buflen -= namelen;
++ if (*buflen < 0)
++ return -ENAMETOOLONG;
++ *buffer -= namelen;
++ memcpy(*buffer, str, namelen);
++ return 0;
++}
++
++static int prepend_name(char **buffer, int *buflen, struct qstr *name)
++{
++ return prepend(buffer, buflen, name->name, name->len);
++}
++
++static int prepend_path(const struct path *path, struct path *root,
++ char **buffer, int *buflen)
++{
++ struct dentry *dentry = path->dentry;
++ struct vfsmount *vfsmnt = path->mnt;
++ bool slash = false;
++ int error = 0;
++
++ while (dentry != root->dentry || vfsmnt != root->mnt) {
++ struct dentry * parent;
++
++ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
++ /* Global root? */
++ if (vfsmnt->mnt_parent == vfsmnt) {
++ goto out;
++ }
++ dentry = vfsmnt->mnt_mountpoint;
++ vfsmnt = vfsmnt->mnt_parent;
++ continue;
++ }
++ parent = dentry->d_parent;
++ prefetch(parent);
++ spin_lock(&dentry->d_lock);
++ error = prepend_name(buffer, buflen, &dentry->d_name);
++ spin_unlock(&dentry->d_lock);
++ if (!error)
++ error = prepend(buffer, buflen, "/", 1);
++ if (error)
++ break;
++
++ slash = true;
++ dentry = parent;
++ }
++
++out:
++ if (!error && !slash)
++ error = prepend(buffer, buflen, "/", 1);
++
++ return error;
++}
++
++/* this must be called with vfsmount_lock and rename_lock held */
++
++static char *__our_d_path(const struct path *path, struct path *root,
++ char *buf, int buflen)
++{
++ char *res = buf + buflen;
++ int error;
++
++ prepend(&res, &buflen, "\0", 1);
++ error = prepend_path(path, root, &res, &buflen);
++ if (error)
++ return ERR_PTR(error);
++
++ return res;
++}
++
++static char *
++gen_full_path(struct path *path, struct path *root, char *buf, int buflen)
++{
++ char *retval;
++
++ retval = __our_d_path(path, root, buf, buflen);
++ if (unlikely(IS_ERR(retval)))
++ retval = strcpy(buf, "<path too long>");
++ else if (unlikely(retval[1] == '/' && retval[2] == '\0'))
++ retval[1] = '\0';
++
++ return retval;
++}
++
++static char *
++__d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
++ char *buf, int buflen)
++{
++ struct path path;
++ char *res;
++
++ path.dentry = (struct dentry *)dentry;
++ path.mnt = (struct vfsmount *)vfsmnt;
++
++ /* we can use real_root.dentry, real_root.mnt, because this is only called
++ by the RBAC system */
++ res = gen_full_path(&path, &real_root, buf, buflen);
++
++ return res;
++}
++
++static char *
++d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
++ char *buf, int buflen)
++{
++ char *res;
++ struct path path;
++ struct path root;
++ struct task_struct *reaper = &init_task;
++
++ path.dentry = (struct dentry *)dentry;
++ path.mnt = (struct vfsmount *)vfsmnt;
++
++ /* we can't use real_root.dentry, real_root.mnt, because they belong only to the RBAC system */
++ get_fs_root(reaper->fs, &root);
++
++ write_seqlock(&rename_lock);
++ br_read_lock(vfsmount_lock);
++ res = gen_full_path(&path, &root, buf, buflen);
++ br_read_unlock(vfsmount_lock);
++ write_sequnlock(&rename_lock);
++
++ path_put(&root);
++ return res;
++}
++
++static char *
++gr_to_filename_rbac(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ char *ret;
++ write_seqlock(&rename_lock);
++ br_read_lock(vfsmount_lock);
++ ret = __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
++ PAGE_SIZE);
++ br_read_unlock(vfsmount_lock);
++ write_sequnlock(&rename_lock);
++ return ret;
++}
++
++char *
++gr_to_filename_nolock(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
++ PAGE_SIZE);
++}
++
++char *
++gr_to_filename(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
++ PAGE_SIZE);
++}
++
++char *
++gr_to_filename1(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[1], smp_processor_id()),
++ PAGE_SIZE);
++}
++
++char *
++gr_to_filename2(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[2], smp_processor_id()),
++ PAGE_SIZE);
++}
++
++char *
++gr_to_filename3(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[3], smp_processor_id()),
++ PAGE_SIZE);
++}
++
++__inline__ __u32
++to_gr_audit(const __u32 reqmode)
++{
++ /* masks off auditable permission flags, then shifts them to create
++ auditing flags, and adds the special case of append auditing if
++ we're requesting write */
++ return (((reqmode & ~GR_AUDITS) << 10) | ((reqmode & GR_WRITE) ? GR_AUDIT_APPEND : 0));
++}
++
++struct acl_subject_label *
++lookup_subject_map(const struct acl_subject_label *userp)
++{
++ unsigned int index = shash(userp, subj_map_set.s_size);
++ struct subject_map *match;
++
++ match = subj_map_set.s_hash[index];
++
++ while (match && match->user != userp)
++ match = match->next;
++
++ if (match != NULL)
++ return match->kernel;
++ else
++ return NULL;
++}
++
++static void
++insert_subj_map_entry(struct subject_map *subjmap)
++{
++ unsigned int index = shash(subjmap->user, subj_map_set.s_size);
++ struct subject_map **curr;
++
++ subjmap->prev = NULL;
++
++ curr = &subj_map_set.s_hash[index];
++ if (*curr != NULL)
++ (*curr)->prev = subjmap;
++
++ subjmap->next = *curr;
++ *curr = subjmap;
++
++ return;
++}
++
++static struct acl_role_label *
++lookup_acl_role_label(const struct task_struct *task, const uid_t uid,
++ const gid_t gid)
++{
++ unsigned int index = rhash(uid, GR_ROLE_USER, acl_role_set.r_size);
++ struct acl_role_label *match;
++ struct role_allowed_ip *ipp;
++ unsigned int x;
++ u32 curr_ip = task->signal->curr_ip;
++
++ task->signal->saved_ip = curr_ip;
++
++ match = acl_role_set.r_hash[index];
++
++ while (match) {
++ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_USER)) == (GR_ROLE_DOMAIN | GR_ROLE_USER)) {
++ for (x = 0; x < match->domain_child_num; x++) {
++ if (match->domain_children[x] == uid)
++ goto found;
++ }
++ } else if (match->uidgid == uid && match->roletype & GR_ROLE_USER)
++ break;
++ match = match->next;
++ }
++found:
++ if (match == NULL) {
++ try_group:
++ index = rhash(gid, GR_ROLE_GROUP, acl_role_set.r_size);
++ match = acl_role_set.r_hash[index];
++
++ while (match) {
++ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) == (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) {
++ for (x = 0; x < match->domain_child_num; x++) {
++ if (match->domain_children[x] == gid)
++ goto found2;
++ }
++ } else if (match->uidgid == gid && match->roletype & GR_ROLE_GROUP)
++ break;
++ match = match->next;
++ }
++found2:
++ if (match == NULL)
++ match = default_role;
++ if (match->allowed_ips == NULL)
++ return match;
++ else {
++ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
++ if (likely
++ ((ntohl(curr_ip) & ipp->netmask) ==
++ (ntohl(ipp->addr) & ipp->netmask)))
++ return match;
++ }
++ match = default_role;
++ }
++ } else if (match->allowed_ips == NULL) {
++ return match;
++ } else {
++ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
++ if (likely
++ ((ntohl(curr_ip) & ipp->netmask) ==
++ (ntohl(ipp->addr) & ipp->netmask)))
++ return match;
++ }
++ goto try_group;
++ }
++
++ return match;
++}
++
++struct acl_subject_label *
++lookup_acl_subj_label(const ino_t ino, const dev_t dev,
++ const struct acl_role_label *role)
++{
++ unsigned int index = fhash(ino, dev, role->subj_hash_size);
++ struct acl_subject_label *match;
++
++ match = role->subj_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ (match->mode & GR_DELETED))) {
++ match = match->next;
++ }
++
++ if (match && !(match->mode & GR_DELETED))
++ return match;
++ else
++ return NULL;
++}
++
++struct acl_subject_label *
++lookup_acl_subj_label_deleted(const ino_t ino, const dev_t dev,
++ const struct acl_role_label *role)
++{
++ unsigned int index = fhash(ino, dev, role->subj_hash_size);
++ struct acl_subject_label *match;
++
++ match = role->subj_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ !(match->mode & GR_DELETED))) {
++ match = match->next;
++ }
++
++ if (match && (match->mode & GR_DELETED))
++ return match;
++ else
++ return NULL;
++}
++
++static struct acl_object_label *
++lookup_acl_obj_label(const ino_t ino, const dev_t dev,
++ const struct acl_subject_label *subj)
++{
++ unsigned int index = fhash(ino, dev, subj->obj_hash_size);
++ struct acl_object_label *match;
++
++ match = subj->obj_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ (match->mode & GR_DELETED))) {
++ match = match->next;
++ }
++
++ if (match && !(match->mode & GR_DELETED))
++ return match;
++ else
++ return NULL;
++}
++
++static struct acl_object_label *
++lookup_acl_obj_label_create(const ino_t ino, const dev_t dev,
++ const struct acl_subject_label *subj)
++{
++ unsigned int index = fhash(ino, dev, subj->obj_hash_size);
++ struct acl_object_label *match;
++
++ match = subj->obj_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ !(match->mode & GR_DELETED))) {
++ match = match->next;
++ }
++
++ if (match && (match->mode & GR_DELETED))
++ return match;
++
++ match = subj->obj_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ (match->mode & GR_DELETED))) {
++ match = match->next;
++ }
++
++ if (match && !(match->mode & GR_DELETED))
++ return match;
++ else
++ return NULL;
++}
++
++static struct name_entry *
++lookup_name_entry(const char *name)
++{
++ unsigned int len = strlen(name);
++ unsigned int key = full_name_hash(name, len);
++ unsigned int index = key % name_set.n_size;
++ struct name_entry *match;
++
++ match = name_set.n_hash[index];
++
++ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len)))
++ match = match->next;
++
++ return match;
++}
++
++static struct name_entry *
++lookup_name_entry_create(const char *name)
++{
++ unsigned int len = strlen(name);
++ unsigned int key = full_name_hash(name, len);
++ unsigned int index = key % name_set.n_size;
++ struct name_entry *match;
++
++ match = name_set.n_hash[index];
++
++ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len) ||
++ !match->deleted))
++ match = match->next;
++
++ if (match && match->deleted)
++ return match;
++
++ match = name_set.n_hash[index];
++
++ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len) ||
++ match->deleted))
++ match = match->next;
++
++ if (match && !match->deleted)
++ return match;
++ else
++ return NULL;
++}
++
++static struct inodev_entry *
++lookup_inodev_entry(const ino_t ino, const dev_t dev)
++{
++ unsigned int index = fhash(ino, dev, inodev_set.i_size);
++ struct inodev_entry *match;
++
++ match = inodev_set.i_hash[index];
++
++ while (match && (match->nentry->inode != ino || match->nentry->device != dev))
++ match = match->next;
++
++ return match;
++}
++
++static void
++insert_inodev_entry(struct inodev_entry *entry)
++{
++ unsigned int index = fhash(entry->nentry->inode, entry->nentry->device,
++ inodev_set.i_size);
++ struct inodev_entry **curr;
++
++ entry->prev = NULL;
++
++ curr = &inodev_set.i_hash[index];
++ if (*curr != NULL)
++ (*curr)->prev = entry;
++
++ entry->next = *curr;
++ *curr = entry;
++
++ return;
++}
++
++static void
++__insert_acl_role_label(struct acl_role_label *role, uid_t uidgid)
++{
++ unsigned int index =
++ rhash(uidgid, role->roletype & (GR_ROLE_USER | GR_ROLE_GROUP), acl_role_set.r_size);
++ struct acl_role_label **curr;
++ struct acl_role_label *tmp;
++
++ curr = &acl_role_set.r_hash[index];
++
++ /* if role was already inserted due to domains and already has
++ a role in the same bucket as it attached, then we need to
++ combine these two buckets
++ */
++ if (role->next) {
++ tmp = role->next;
++ while (tmp->next)
++ tmp = tmp->next;
++ tmp->next = *curr;
++ } else
++ role->next = *curr;
++ *curr = role;
++
++ return;
++}
++
++static void
++insert_acl_role_label(struct acl_role_label *role)
++{
++ int i;
++
++ if (role_list == NULL) {
++ role_list = role;
++ role->prev = NULL;
++ } else {
++ role->prev = role_list;
++ role_list = role;
++ }
++
++ /* used for hash chains */
++ role->next = NULL;
++
++ if (role->roletype & GR_ROLE_DOMAIN) {
++ for (i = 0; i < role->domain_child_num; i++)
++ __insert_acl_role_label(role, role->domain_children[i]);
++ } else
++ __insert_acl_role_label(role, role->uidgid);
++}
++
++static int
++insert_name_entry(char *name, const ino_t inode, const dev_t device, __u8 deleted)
++{
++ struct name_entry **curr, *nentry;
++ struct inodev_entry *ientry;
++ unsigned int len = strlen(name);
++ unsigned int key = full_name_hash(name, len);
++ unsigned int index = key % name_set.n_size;
++
++ curr = &name_set.n_hash[index];
++
++ while (*curr && ((*curr)->key != key || !gr_streq((*curr)->name, name, (*curr)->len, len)))
++ curr = &((*curr)->next);
++
++ if (*curr != NULL)
++ return 1;
++
++ nentry = acl_alloc(sizeof (struct name_entry));
++ if (nentry == NULL)
++ return 0;
++ ientry = acl_alloc(sizeof (struct inodev_entry));
++ if (ientry == NULL)
++ return 0;
++ ientry->nentry = nentry;
++
++ nentry->key = key;
++ nentry->name = name;
++ nentry->inode = inode;
++ nentry->device = device;
++ nentry->len = len;
++ nentry->deleted = deleted;
++
++ nentry->prev = NULL;
++ curr = &name_set.n_hash[index];
++ if (*curr != NULL)
++ (*curr)->prev = nentry;
++ nentry->next = *curr;
++ *curr = nentry;
++
++ /* insert us into the table searchable by inode/dev */
++ insert_inodev_entry(ientry);
++
++ return 1;
++}
++
++static void
++insert_acl_obj_label(struct acl_object_label *obj,
++ struct acl_subject_label *subj)
++{
++ unsigned int index =
++ fhash(obj->inode, obj->device, subj->obj_hash_size);
++ struct acl_object_label **curr;
++
++
++ obj->prev = NULL;
++
++ curr = &subj->obj_hash[index];
++ if (*curr != NULL)
++ (*curr)->prev = obj;
++
++ obj->next = *curr;
++ *curr = obj;
++
++ return;
++}
++
++static void
++insert_acl_subj_label(struct acl_subject_label *obj,
++ struct acl_role_label *role)
++{
++ unsigned int index = fhash(obj->inode, obj->device, role->subj_hash_size);
++ struct acl_subject_label **curr;
++
++ obj->prev = NULL;
++
++ curr = &role->subj_hash[index];
++ if (*curr != NULL)
++ (*curr)->prev = obj;
++
++ obj->next = *curr;
++ *curr = obj;
++
++ return;
++}
++
++/* allocating chained hash tables, so optimal size is where lambda ~ 1 */
++
++static void *
++create_table(__u32 * len, int elementsize)
++{
++ unsigned int table_sizes[] = {
++ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
++ 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
++ 4194301, 8388593, 16777213, 33554393, 67108859
++ };
++ void *newtable = NULL;
++ unsigned int pwr = 0;
++
++ while ((pwr < ((sizeof (table_sizes) / sizeof (table_sizes[0])) - 1)) &&
++ table_sizes[pwr] <= *len)
++ pwr++;
++
++ if (table_sizes[pwr] <= *len || (table_sizes[pwr] > ULONG_MAX / elementsize))
++ return newtable;
++
++ if ((table_sizes[pwr] * elementsize) <= PAGE_SIZE)
++ newtable =
++ kmalloc(table_sizes[pwr] * elementsize, GFP_KERNEL);
++ else
++ newtable = vmalloc(table_sizes[pwr] * elementsize);
++
++ *len = table_sizes[pwr];
++
++ return newtable;
++}
++
++static int
++init_variables(const struct gr_arg *arg)
++{
++ struct task_struct *reaper = &init_task;
++ unsigned int stacksize;
++
++ subj_map_set.s_size = arg->role_db.num_subjects;
++ acl_role_set.r_size = arg->role_db.num_roles + arg->role_db.num_domain_children;
++ name_set.n_size = arg->role_db.num_objects;
++ inodev_set.i_size = arg->role_db.num_objects;
++
++ if (!subj_map_set.s_size || !acl_role_set.r_size ||
++ !name_set.n_size || !inodev_set.i_size)
++ return 1;
++
++ if (!gr_init_uidset())
++ return 1;
++
++ /* set up the stack that holds allocation info */
++
++ stacksize = arg->role_db.num_pointers + 5;
++
++ if (!acl_alloc_stack_init(stacksize))
++ return 1;
++
++ /* grab reference for the real root dentry and vfsmount */
++ get_fs_root(reaper->fs, &real_root);
++
++#ifdef CONFIG_GRKERNSEC_RBAC_DEBUG
++ printk(KERN_ALERT "Obtained real root device=%d, inode=%lu\n", __get_dev(real_root.dentry), real_root.dentry->d_inode->i_ino);
++#endif
++
++ fakefs_obj = acl_alloc(sizeof(struct acl_object_label));
++ if (fakefs_obj == NULL)
++ return 1;
++ fakefs_obj->mode = GR_FIND | GR_READ | GR_WRITE | GR_EXEC;
++
++ subj_map_set.s_hash =
++ (struct subject_map **) create_table(&subj_map_set.s_size, sizeof(void *));
++ acl_role_set.r_hash =
++ (struct acl_role_label **) create_table(&acl_role_set.r_size, sizeof(void *));
++ name_set.n_hash = (struct name_entry **) create_table(&name_set.n_size, sizeof(void *));
++ inodev_set.i_hash =
++ (struct inodev_entry **) create_table(&inodev_set.i_size, sizeof(void *));
++
++ if (!subj_map_set.s_hash || !acl_role_set.r_hash ||
++ !name_set.n_hash || !inodev_set.i_hash)
++ return 1;
++
++ memset(subj_map_set.s_hash, 0,
++ sizeof(struct subject_map *) * subj_map_set.s_size);
++ memset(acl_role_set.r_hash, 0,
++ sizeof (struct acl_role_label *) * acl_role_set.r_size);
++ memset(name_set.n_hash, 0,
++ sizeof (struct name_entry *) * name_set.n_size);
++ memset(inodev_set.i_hash, 0,
++ sizeof (struct inodev_entry *) * inodev_set.i_size);
++
++ return 0;
++}
++
++/* free information not needed after startup
++ currently contains user->kernel pointer mappings for subjects
++*/
++
++static void
++free_init_variables(void)
++{
++ __u32 i;
++
++ if (subj_map_set.s_hash) {
++ for (i = 0; i < subj_map_set.s_size; i++) {
++ if (subj_map_set.s_hash[i]) {
++ kfree(subj_map_set.s_hash[i]);
++ subj_map_set.s_hash[i] = NULL;
++ }
++ }
++
++ if ((subj_map_set.s_size * sizeof (struct subject_map *)) <=
++ PAGE_SIZE)
++ kfree(subj_map_set.s_hash);
++ else
++ vfree(subj_map_set.s_hash);
++ }
++
++ return;
++}
++
++static void
++free_variables(void)
++{
++ struct acl_subject_label *s;
++ struct acl_role_label *r;
++ struct task_struct *task, *task2;
++ unsigned int x;
++
++ gr_clear_learn_entries();
++
++ read_lock(&tasklist_lock);
++ do_each_thread(task2, task) {
++ task->acl_sp_role = 0;
++ task->acl_role_id = 0;
++ task->acl = NULL;
++ task->role = NULL;
++ } while_each_thread(task2, task);
++ read_unlock(&tasklist_lock);
++
++ /* release the reference to the real root dentry and vfsmount */
++ path_put(&real_root);
++
++ /* free all object hash tables */
++
++ FOR_EACH_ROLE_START(r)
++ if (r->subj_hash == NULL)
++ goto next_role;
++ FOR_EACH_SUBJECT_START(r, s, x)
++ if (s->obj_hash == NULL)
++ break;
++ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
++ kfree(s->obj_hash);
++ else
++ vfree(s->obj_hash);
++ FOR_EACH_SUBJECT_END(s, x)
++ FOR_EACH_NESTED_SUBJECT_START(r, s)
++ if (s->obj_hash == NULL)
++ break;
++ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
++ kfree(s->obj_hash);
++ else
++ vfree(s->obj_hash);
++ FOR_EACH_NESTED_SUBJECT_END(s)
++ if ((r->subj_hash_size * sizeof (struct acl_subject_label *)) <= PAGE_SIZE)
++ kfree(r->subj_hash);
++ else
++ vfree(r->subj_hash);
++ r->subj_hash = NULL;
++next_role:
++ FOR_EACH_ROLE_END(r)
++
++ acl_free_all();
++
++ if (acl_role_set.r_hash) {
++ if ((acl_role_set.r_size * sizeof (struct acl_role_label *)) <=
++ PAGE_SIZE)
++ kfree(acl_role_set.r_hash);
++ else
++ vfree(acl_role_set.r_hash);
++ }
++ if (name_set.n_hash) {
++ if ((name_set.n_size * sizeof (struct name_entry *)) <=
++ PAGE_SIZE)
++ kfree(name_set.n_hash);
++ else
++ vfree(name_set.n_hash);
++ }
++
++ if (inodev_set.i_hash) {
++ if ((inodev_set.i_size * sizeof (struct inodev_entry *)) <=
++ PAGE_SIZE)
++ kfree(inodev_set.i_hash);
++ else
++ vfree(inodev_set.i_hash);
++ }
++
++ gr_free_uidset();
++
++ memset(&name_set, 0, sizeof (struct name_db));
++ memset(&inodev_set, 0, sizeof (struct inodev_db));
++ memset(&acl_role_set, 0, sizeof (struct acl_role_db));
++ memset(&subj_map_set, 0, sizeof (struct acl_subj_map_db));
++
++ default_role = NULL;
++ role_list = NULL;
++
++ return;
++}
++
++static __u32
++count_user_objs(struct acl_object_label *userp)
++{
++ struct acl_object_label o_tmp;
++ __u32 num = 0;
++
++ while (userp) {
++ if (copy_from_user(&o_tmp, userp,
++ sizeof (struct acl_object_label)))
++ break;
++
++ userp = o_tmp.prev;
++ num++;
++ }
++
++ return num;
++}
++
++static struct acl_subject_label *
++do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role);
++
++static int
++copy_user_glob(struct acl_object_label *obj)
++{
++ struct acl_object_label *g_tmp, **guser;
++ unsigned int len;
++ char *tmp;
++
++ if (obj->globbed == NULL)
++ return 0;
++
++ guser = &obj->globbed;
++ while (*guser) {
++ g_tmp = (struct acl_object_label *)
++ acl_alloc(sizeof (struct acl_object_label));
++ if (g_tmp == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(g_tmp, *guser,
++ sizeof (struct acl_object_label)))
++ return -EFAULT;
++
++ len = strnlen_user(g_tmp->filename, PATH_MAX);
++
++ if (!len || len >= PATH_MAX)
++ return -EINVAL;
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(tmp, g_tmp->filename, len))
++ return -EFAULT;
++ tmp[len-1] = '\0';
++ g_tmp->filename = tmp;
++
++ *guser = g_tmp;
++ guser = &(g_tmp->next);
++ }
++
++ return 0;
++}
++
++static int
++copy_user_objs(struct acl_object_label *userp, struct acl_subject_label *subj,
++ struct acl_role_label *role)
++{
++ struct acl_object_label *o_tmp;
++ unsigned int len;
++ int ret;
++ char *tmp;
++
++ while (userp) {
++ if ((o_tmp = (struct acl_object_label *)
++ acl_alloc(sizeof (struct acl_object_label))) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(o_tmp, userp,
++ sizeof (struct acl_object_label)))
++ return -EFAULT;
++
++ userp = o_tmp->prev;
++
++ len = strnlen_user(o_tmp->filename, PATH_MAX);
++
++ if (!len || len >= PATH_MAX)
++ return -EINVAL;
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(tmp, o_tmp->filename, len))
++ return -EFAULT;
++ tmp[len-1] = '\0';
++ o_tmp->filename = tmp;
++
++ insert_acl_obj_label(o_tmp, subj);
++ if (!insert_name_entry(o_tmp->filename, o_tmp->inode,
++ o_tmp->device, (o_tmp->mode & GR_DELETED) ? 1 : 0))
++ return -ENOMEM;
++
++ ret = copy_user_glob(o_tmp);
++ if (ret)
++ return ret;
++
++ if (o_tmp->nested) {
++ o_tmp->nested = do_copy_user_subj(o_tmp->nested, role);
++ if (IS_ERR(o_tmp->nested))
++ return PTR_ERR(o_tmp->nested);
++
++ /* insert into nested subject list */
++ o_tmp->nested->next = role->hash->first;
++ role->hash->first = o_tmp->nested;
++ }
++ }
++
++ return 0;
++}
++
++static __u32
++count_user_subjs(struct acl_subject_label *userp)
++{
++ struct acl_subject_label s_tmp;
++ __u32 num = 0;
++
++ while (userp) {
++ if (copy_from_user(&s_tmp, userp,
++ sizeof (struct acl_subject_label)))
++ break;
++
++ userp = s_tmp.prev;
++ /* do not count nested subjects against this count, since
++ they are not included in the hash table, but are
++ attached to objects. We have already counted
++ the subjects in userspace for the allocation
++ stack
++ */
++ if (!(s_tmp.mode & GR_NESTED))
++ num++;
++ }
++
++ return num;
++}
++
++static int
++copy_user_allowedips(struct acl_role_label *rolep)
++{
++ struct role_allowed_ip *ruserip, *rtmp = NULL, *rlast;
++
++ ruserip = rolep->allowed_ips;
++
++ while (ruserip) {
++ rlast = rtmp;
++
++ if ((rtmp = (struct role_allowed_ip *)
++ acl_alloc(sizeof (struct role_allowed_ip))) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(rtmp, ruserip,
++ sizeof (struct role_allowed_ip)))
++ return -EFAULT;
++
++ ruserip = rtmp->prev;
++
++ if (!rlast) {
++ rtmp->prev = NULL;
++ rolep->allowed_ips = rtmp;
++ } else {
++ rlast->next = rtmp;
++ rtmp->prev = rlast;
++ }
++
++ if (!ruserip)
++ rtmp->next = NULL;
++ }
++
++ return 0;
++}
++
++static int
++copy_user_transitions(struct acl_role_label *rolep)
++{
++ struct role_transition *rusertp, *rtmp = NULL, *rlast;
++
++ unsigned int len;
++ char *tmp;
++
++ rusertp = rolep->transitions;
++
++ while (rusertp) {
++ rlast = rtmp;
++
++ if ((rtmp = (struct role_transition *)
++ acl_alloc(sizeof (struct role_transition))) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(rtmp, rusertp,
++ sizeof (struct role_transition)))
++ return -EFAULT;
++
++ rusertp = rtmp->prev;
++
++ len = strnlen_user(rtmp->rolename, GR_SPROLE_LEN);
++
++ if (!len || len >= GR_SPROLE_LEN)
++ return -EINVAL;
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(tmp, rtmp->rolename, len))
++ return -EFAULT;
++ tmp[len-1] = '\0';
++ rtmp->rolename = tmp;
++
++ if (!rlast) {
++ rtmp->prev = NULL;
++ rolep->transitions = rtmp;
++ } else {
++ rlast->next = rtmp;
++ rtmp->prev = rlast;
++ }
++
++ if (!rusertp)
++ rtmp->next = NULL;
++ }
++
++ return 0;
++}
++
++static struct acl_subject_label *
++do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role)
++{
++ struct acl_subject_label *s_tmp = NULL, *s_tmp2;
++ unsigned int len;
++ char *tmp;
++ __u32 num_objs;
++ struct acl_ip_label **i_tmp, *i_utmp2;
++ struct gr_hash_struct ghash;
++ struct subject_map *subjmap;
++ unsigned int i_num;
++ int err;
++
++ s_tmp = lookup_subject_map(userp);
++
++ /* we've already copied this subject into the kernel, just return
++ the reference to it, and don't copy it over again
++ */
++ if (s_tmp)
++ return(s_tmp);
++
++ if ((s_tmp = (struct acl_subject_label *)
++ acl_alloc(sizeof (struct acl_subject_label))) == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ subjmap = (struct subject_map *)kmalloc(sizeof (struct subject_map), GFP_KERNEL);
++ if (subjmap == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ subjmap->user = userp;
++ subjmap->kernel = s_tmp;
++ insert_subj_map_entry(subjmap);
++
++ if (copy_from_user(s_tmp, userp,
++ sizeof (struct acl_subject_label)))
++ return ERR_PTR(-EFAULT);
++
++ len = strnlen_user(s_tmp->filename, PATH_MAX);
++
++ if (!len || len >= PATH_MAX)
++ return ERR_PTR(-EINVAL);
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ if (copy_from_user(tmp, s_tmp->filename, len))
++ return ERR_PTR(-EFAULT);
++ tmp[len-1] = '\0';
++ s_tmp->filename = tmp;
++
++ if (!strcmp(s_tmp->filename, "/"))
++ role->root_label = s_tmp;
++
++ if (copy_from_user(&ghash, s_tmp->hash, sizeof(struct gr_hash_struct)))
++ return ERR_PTR(-EFAULT);
++
++ /* copy user and group transition tables */
++
++ if (s_tmp->user_trans_num) {
++ uid_t *uidlist;
++
++ uidlist = (uid_t *)acl_alloc_num(s_tmp->user_trans_num, sizeof(uid_t));
++ if (uidlist == NULL)
++ return ERR_PTR(-ENOMEM);
++ if (copy_from_user(uidlist, s_tmp->user_transitions, s_tmp->user_trans_num * sizeof(uid_t)))
++ return ERR_PTR(-EFAULT);
++
++ s_tmp->user_transitions = uidlist;
++ }
++
++ if (s_tmp->group_trans_num) {
++ gid_t *gidlist;
++
++ gidlist = (gid_t *)acl_alloc_num(s_tmp->group_trans_num, sizeof(gid_t));
++ if (gidlist == NULL)
++ return ERR_PTR(-ENOMEM);
++ if (copy_from_user(gidlist, s_tmp->group_transitions, s_tmp->group_trans_num * sizeof(gid_t)))
++ return ERR_PTR(-EFAULT);
++
++ s_tmp->group_transitions = gidlist;
++ }
++
++ /* set up object hash table */
++ num_objs = count_user_objs(ghash.first);
++
++ s_tmp->obj_hash_size = num_objs;
++ s_tmp->obj_hash =
++ (struct acl_object_label **)
++ create_table(&(s_tmp->obj_hash_size), sizeof(void *));
++
++ if (!s_tmp->obj_hash)
++ return ERR_PTR(-ENOMEM);
++
++ memset(s_tmp->obj_hash, 0,
++ s_tmp->obj_hash_size *
++ sizeof (struct acl_object_label *));
++
++ /* add in objects */
++ err = copy_user_objs(ghash.first, s_tmp, role);
++
++ if (err)
++ return ERR_PTR(err);
++
++ /* set pointer for parent subject */
++ if (s_tmp->parent_subject) {
++ s_tmp2 = do_copy_user_subj(s_tmp->parent_subject, role);
++
++ if (IS_ERR(s_tmp2))
++ return s_tmp2;
++
++ s_tmp->parent_subject = s_tmp2;
++ }
++
++ /* add in ip acls */
++
++ if (!s_tmp->ip_num) {
++ s_tmp->ips = NULL;
++ goto insert;
++ }
++
++ i_tmp =
++ (struct acl_ip_label **) acl_alloc_num(s_tmp->ip_num,
++ sizeof (struct acl_ip_label *));
++
++ if (!i_tmp)
++ return ERR_PTR(-ENOMEM);
++
++ for (i_num = 0; i_num < s_tmp->ip_num; i_num++) {
++ *(i_tmp + i_num) =
++ (struct acl_ip_label *)
++ acl_alloc(sizeof (struct acl_ip_label));
++ if (!*(i_tmp + i_num))
++ return ERR_PTR(-ENOMEM);
++
++ if (copy_from_user
++ (&i_utmp2, s_tmp->ips + i_num,
++ sizeof (struct acl_ip_label *)))
++ return ERR_PTR(-EFAULT);
++
++ if (copy_from_user
++ (*(i_tmp + i_num), i_utmp2,
++ sizeof (struct acl_ip_label)))
++ return ERR_PTR(-EFAULT);
++
++ if ((*(i_tmp + i_num))->iface == NULL)
++ continue;
++
++ len = strnlen_user((*(i_tmp + i_num))->iface, IFNAMSIZ);
++ if (!len || len >= IFNAMSIZ)
++ return ERR_PTR(-EINVAL);
++ tmp = acl_alloc(len);
++ if (tmp == NULL)
++ return ERR_PTR(-ENOMEM);
++ if (copy_from_user(tmp, (*(i_tmp + i_num))->iface, len))
++ return ERR_PTR(-EFAULT);
++ (*(i_tmp + i_num))->iface = tmp;
++ }
++
++ s_tmp->ips = i_tmp;
++
++insert:
++ if (!insert_name_entry(s_tmp->filename, s_tmp->inode,
++ s_tmp->device, (s_tmp->mode & GR_DELETED) ? 1 : 0))
++ return ERR_PTR(-ENOMEM);
++
++ return s_tmp;
++}
++
++static int
++copy_user_subjs(struct acl_subject_label *userp, struct acl_role_label *role)
++{
++ struct acl_subject_label s_pre;
++ struct acl_subject_label * ret;
++ int err;
++
++ while (userp) {
++ if (copy_from_user(&s_pre, userp,
++ sizeof (struct acl_subject_label)))
++ return -EFAULT;
++
++ /* do not add nested subjects here, add
++ while parsing objects
++ */
++
++ if (s_pre.mode & GR_NESTED) {
++ userp = s_pre.prev;
++ continue;
++ }
++
++ ret = do_copy_user_subj(userp, role);
++
++ err = PTR_ERR(ret);
++ if (IS_ERR(ret))
++ return err;
++
++ insert_acl_subj_label(ret, role);
++
++ userp = s_pre.prev;
++ }
++
++ return 0;
++}
++
++static int
++copy_user_acl(struct gr_arg *arg)
++{
++ struct acl_role_label *r_tmp = NULL, **r_utmp, *r_utmp2;
++ struct sprole_pw *sptmp;
++ struct gr_hash_struct *ghash;
++ uid_t *domainlist;
++ unsigned int r_num;
++ unsigned int len;
++ char *tmp;
++ int err = 0;
++ __u16 i;
++ __u32 num_subjs;
++
++ /* we need a default and kernel role */
++ if (arg->role_db.num_roles < 2)
++ return -EINVAL;
++
++ /* copy special role authentication info from userspace */
++
++ num_sprole_pws = arg->num_sprole_pws;
++ acl_special_roles = (struct sprole_pw **) acl_alloc_num(num_sprole_pws, sizeof(struct sprole_pw *));
++
++ if (!acl_special_roles) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++
++ for (i = 0; i < num_sprole_pws; i++) {
++ sptmp = (struct sprole_pw *) acl_alloc(sizeof(struct sprole_pw));
++ if (!sptmp) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++ if (copy_from_user(sptmp, arg->sprole_pws + i,
++ sizeof (struct sprole_pw))) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++
++ len =
++ strnlen_user(sptmp->rolename, GR_SPROLE_LEN);
++
++ if (!len || len >= GR_SPROLE_LEN) {
++ err = -EINVAL;
++ goto cleanup;
++ }
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++
++ if (copy_from_user(tmp, sptmp->rolename, len)) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++ tmp[len-1] = '\0';
++#ifdef CONFIG_GRKERNSEC_RBAC_DEBUG
++ printk(KERN_ALERT "Copying special role %s\n", tmp);
++#endif
++ sptmp->rolename = tmp;
++ acl_special_roles[i] = sptmp;
++ }
++
++ r_utmp = (struct acl_role_label **) arg->role_db.r_table;
++
++ for (r_num = 0; r_num < arg->role_db.num_roles; r_num++) {
++ r_tmp = acl_alloc(sizeof (struct acl_role_label));
++
++ if (!r_tmp) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++
++ if (copy_from_user(&r_utmp2, r_utmp + r_num,
++ sizeof (struct acl_role_label *))) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++
++ if (copy_from_user(r_tmp, r_utmp2,
++ sizeof (struct acl_role_label))) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++
++ len = strnlen_user(r_tmp->rolename, GR_SPROLE_LEN);
++
++ if (!len || len >= PATH_MAX) {
++ err = -EINVAL;
++ goto cleanup;
++ }
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++ if (copy_from_user(tmp, r_tmp->rolename, len)) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++ tmp[len-1] = '\0';
++ r_tmp->rolename = tmp;
++
++ if (!strcmp(r_tmp->rolename, "default")
++ && (r_tmp->roletype & GR_ROLE_DEFAULT)) {
++ default_role = r_tmp;
++ } else if (!strcmp(r_tmp->rolename, ":::kernel:::")) {
++ kernel_role = r_tmp;
++ }
++
++ if ((ghash = (struct gr_hash_struct *) acl_alloc(sizeof(struct gr_hash_struct))) == NULL) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++ if (copy_from_user(ghash, r_tmp->hash, sizeof(struct gr_hash_struct))) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++
++ r_tmp->hash = ghash;
++
++ num_subjs = count_user_subjs(r_tmp->hash->first);
++
++ r_tmp->subj_hash_size = num_subjs;
++ r_tmp->subj_hash =
++ (struct acl_subject_label **)
++ create_table(&(r_tmp->subj_hash_size), sizeof(void *));
++
++ if (!r_tmp->subj_hash) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++
++ err = copy_user_allowedips(r_tmp);
++ if (err)
++ goto cleanup;
++
++ /* copy domain info */
++ if (r_tmp->domain_children != NULL) {
++ domainlist = acl_alloc_num(r_tmp->domain_child_num, sizeof(uid_t));
++ if (domainlist == NULL) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++ if (copy_from_user(domainlist, r_tmp->domain_children, r_tmp->domain_child_num * sizeof(uid_t))) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++ r_tmp->domain_children = domainlist;
++ }
++
++ err = copy_user_transitions(r_tmp);
++ if (err)
++ goto cleanup;
++
++ memset(r_tmp->subj_hash, 0,
++ r_tmp->subj_hash_size *
++ sizeof (struct acl_subject_label *));
++
++ err = copy_user_subjs(r_tmp->hash->first, r_tmp);
++
++ if (err)
++ goto cleanup;
++
++ /* set nested subject list to null */
++ r_tmp->hash->first = NULL;
++
++ insert_acl_role_label(r_tmp);
++ }
++
++ goto return_err;
++ cleanup:
++ free_variables();
++ return_err:
++ return err;
++
++}
++
++static int
++gracl_init(struct gr_arg *args)
++{
++ int error = 0;
++
++ memcpy(gr_system_salt, args->salt, GR_SALT_LEN);
++ memcpy(gr_system_sum, args->sum, GR_SHA_LEN);
++
++ if (init_variables(args)) {
++ gr_log_str(GR_DONT_AUDIT_GOOD, GR_INITF_ACL_MSG, GR_VERSION);
++ error = -ENOMEM;
++ free_variables();
++ goto out;
++ }
++
++ error = copy_user_acl(args);
++ free_init_variables();
++ if (error) {
++ free_variables();
++ goto out;
++ }
++
++ if ((error = gr_set_acls(0))) {
++ free_variables();
++ goto out;
++ }
++
++ pax_open_kernel();
++ gr_status |= GR_READY;
++ pax_close_kernel();
++
++ out:
++ return error;
++}
++
++/* derived from glibc fnmatch() 0: match, 1: no match*/
++
++static int
++glob_match(const char *p, const char *n)
++{
++ char c;
++
++ while ((c = *p++) != '\0') {
++ switch (c) {
++ case '?':
++ if (*n == '\0')
++ return 1;
++ else if (*n == '/')
++ return 1;
++ break;
++ case '\\':
++ if (*n != c)
++ return 1;
++ break;
++ case '*':
++ for (c = *p++; c == '?' || c == '*'; c = *p++) {
++ if (*n == '/')
++ return 1;
++ else if (c == '?') {
++ if (*n == '\0')
++ return 1;
++ else
++ ++n;
++ }
++ }
++ if (c == '\0') {
++ return 0;
++ } else {
++ const char *endp;
++
++ if ((endp = strchr(n, '/')) == NULL)
++ endp = n + strlen(n);
++
++ if (c == '[') {
++ for (--p; n < endp; ++n)
++ if (!glob_match(p, n))
++ return 0;
++ } else if (c == '/') {
++ while (*n != '\0' && *n != '/')
++ ++n;
++ if (*n == '/' && !glob_match(p, n + 1))
++ return 0;
++ } else {
++ for (--p; n < endp; ++n)
++ if (*n == c && !glob_match(p, n))
++ return 0;
++ }
++
++ return 1;
++ }
++ case '[':
++ {
++ int not;
++ char cold;
++
++ if (*n == '\0' || *n == '/')
++ return 1;
++
++ not = (*p == '!' || *p == '^');
++ if (not)
++ ++p;
++
++ c = *p++;
++ for (;;) {
++ unsigned char fn = (unsigned char)*n;
++
++ if (c == '\0')
++ return 1;
++ else {
++ if (c == fn)
++ goto matched;
++ cold = c;
++ c = *p++;
++
++ if (c == '-' && *p != ']') {
++ unsigned char cend = *p++;
++
++ if (cend == '\0')
++ return 1;
++
++ if (cold <= fn && fn <= cend)
++ goto matched;
++
++ c = *p++;
++ }
++ }
++
++ if (c == ']')
++ break;
++ }
++ if (!not)
++ return 1;
++ break;
++ matched:
++ while (c != ']') {
++ if (c == '\0')
++ return 1;
++
++ c = *p++;
++ }
++ if (not)
++ return 1;
++ }
++ break;
++ default:
++ if (c != *n)
++ return 1;
++ }
++
++ ++n;
++ }
++
++ if (*n == '\0')
++ return 0;
++
++ if (*n == '/')
++ return 0;
++
++ return 1;
++}
++
++static struct acl_object_label *
++chk_glob_label(struct acl_object_label *globbed,
++ struct dentry *dentry, struct vfsmount *mnt, char **path)
++{
++ struct acl_object_label *tmp;
++
++ if (*path == NULL)
++ *path = gr_to_filename_nolock(dentry, mnt);
++
++ tmp = globbed;
++
++ while (tmp) {
++ if (!glob_match(tmp->filename, *path))
++ return tmp;
++ tmp = tmp->next;
++ }
++
++ return NULL;
++}
++
++static struct acl_object_label *
++__full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
++ const ino_t curr_ino, const dev_t curr_dev,
++ const struct acl_subject_label *subj, char **path, const int checkglob)
++{
++ struct acl_subject_label *tmpsubj;
++ struct acl_object_label *retval;
++ struct acl_object_label *retval2;
++
++ tmpsubj = (struct acl_subject_label *) subj;
++ read_lock(&gr_inode_lock);
++ do {
++ retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj);
++ if (retval) {
++ if (checkglob && retval->globbed) {
++ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry,
++ (struct vfsmount *)orig_mnt, path);
++ if (retval2)
++ retval = retval2;
++ }
++ break;
++ }
++ } while ((tmpsubj = tmpsubj->parent_subject));
++ read_unlock(&gr_inode_lock);
++
++ return retval;
++}
++
++static __inline__ struct acl_object_label *
++full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
++ struct dentry *curr_dentry,
++ const struct acl_subject_label *subj, char **path, const int checkglob)
++{
++ int newglob = checkglob;
++ ino_t inode;
++ dev_t device;
++
++ /* if we aren't checking a subdirectory of the original path yet, don't do glob checking
++ as we don't want a / * rule to match instead of the / object
++ don't do this for create lookups that call this function though, since they're looking up
++ on the parent and thus need globbing checks on all paths
++ */
++ if (orig_dentry == curr_dentry && newglob != GR_CREATE_GLOB)
++ newglob = GR_NO_GLOB;
++
++ spin_lock(&curr_dentry->d_lock);
++ inode = curr_dentry->d_inode->i_ino;
++ device = __get_dev(curr_dentry);
++ spin_unlock(&curr_dentry->d_lock);
++
++ return __full_lookup(orig_dentry, orig_mnt, inode, device, subj, path, newglob);
++}
++
++static struct acl_object_label *
++__chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
++ const struct acl_subject_label *subj, char *path, const int checkglob)
++{
++ struct dentry *dentry = (struct dentry *) l_dentry;
++ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
++ struct acl_object_label *retval;
++ struct dentry *parent;
++
++ write_seqlock(&rename_lock);
++ br_read_lock(vfsmount_lock);
++
++ if (unlikely((mnt == shm_mnt && dentry->d_inode->i_nlink == 0) || mnt == pipe_mnt || mnt == sock_mnt ||
++#ifdef CONFIG_HUGETLBFS
++ (mnt == hugetlbfs_vfsmount && dentry->d_inode->i_nlink == 0) ||
++#endif
++ /* ignore Eric Biederman */
++ IS_PRIVATE(l_dentry->d_inode))) {
++ retval = fakefs_obj;
++ goto out;
++ }
++
++ for (;;) {
++ if (dentry == real_root.dentry && mnt == real_root.mnt)
++ break;
++
++ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
++ if (mnt->mnt_parent == mnt)
++ break;
++
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path, checkglob);
++ if (retval != NULL)
++ goto out;
++
++ dentry = mnt->mnt_mountpoint;
++ mnt = mnt->mnt_parent;
++ continue;
++ }
++
++ parent = dentry->d_parent;
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path, checkglob);
++ if (retval != NULL)
++ goto out;
++
++ dentry = parent;
++ }
++
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path, checkglob);
++
++ /* real_root is pinned so we don't have to hold a reference */
++ if (retval == NULL)
++ retval = full_lookup(l_dentry, l_mnt, real_root.dentry, subj, &path, checkglob);
++out:
++ br_read_unlock(vfsmount_lock);
++ write_sequnlock(&rename_lock);
++
++ BUG_ON(retval == NULL);
++
++ return retval;
++}
++
++static __inline__ struct acl_object_label *
++chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
++ const struct acl_subject_label *subj)
++{
++ char *path = NULL;
++ return __chk_obj_label(l_dentry, l_mnt, subj, path, GR_REG_GLOB);
++}
++
++static __inline__ struct acl_object_label *
++chk_obj_label_noglob(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
++ const struct acl_subject_label *subj)
++{
++ char *path = NULL;
++ return __chk_obj_label(l_dentry, l_mnt, subj, path, GR_NO_GLOB);
++}
++
++static __inline__ struct acl_object_label *
++chk_obj_create_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
++ const struct acl_subject_label *subj, char *path)
++{
++ return __chk_obj_label(l_dentry, l_mnt, subj, path, GR_CREATE_GLOB);
++}
++
++static struct acl_subject_label *
++chk_subj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
++ const struct acl_role_label *role)
++{
++ struct dentry *dentry = (struct dentry *) l_dentry;
++ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
++ struct acl_subject_label *retval;
++ struct dentry *parent;
++
++ write_seqlock(&rename_lock);
++ br_read_lock(vfsmount_lock);
++
++ for (;;) {
++ if (dentry == real_root.dentry && mnt == real_root.mnt)
++ break;
++ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
++ if (mnt->mnt_parent == mnt)
++ break;
++
++ spin_lock(&dentry->d_lock);
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_subj_label(dentry->d_inode->i_ino,
++ __get_dev(dentry), role);
++ read_unlock(&gr_inode_lock);
++ spin_unlock(&dentry->d_lock);
++ if (retval != NULL)
++ goto out;
++
++ dentry = mnt->mnt_mountpoint;
++ mnt = mnt->mnt_parent;
++ continue;
++ }
++
++ spin_lock(&dentry->d_lock);
++ read_lock(&gr_inode_lock);
++ retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
++ __get_dev(dentry), role);
++ read_unlock(&gr_inode_lock);
++ parent = dentry->d_parent;
++ spin_unlock(&dentry->d_lock);
++
++ if (retval != NULL)
++ goto out;
++
++ dentry = parent;
++ }
++
++ spin_lock(&dentry->d_lock);
++ read_lock(&gr_inode_lock);
++ retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
++ __get_dev(dentry), role);
++ read_unlock(&gr_inode_lock);
++ spin_unlock(&dentry->d_lock);
++
++ if (unlikely(retval == NULL)) {
++ /* real_root is pinned, we don't need to hold a reference */
++ read_lock(&gr_inode_lock);
++ retval = lookup_acl_subj_label(real_root.dentry->d_inode->i_ino,
++ __get_dev(real_root.dentry), role);
++ read_unlock(&gr_inode_lock);
++ }
++out:
++ br_read_unlock(vfsmount_lock);
++ write_sequnlock(&rename_lock);
++
++ BUG_ON(retval == NULL);
++
++ return retval;
++}
++
++static void
++gr_log_learn(const struct dentry *dentry, const struct vfsmount *mnt, const __u32 mode)
++{
++ struct task_struct *task = current;
++ const struct cred *cred = current_cred();
++
++ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype,
++ cred->uid, cred->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
++ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename,
++ 1UL, 1UL, gr_to_filename(dentry, mnt), (unsigned long) mode, &task->signal->saved_ip);
++
++ return;
++}
++
++static void
++gr_log_learn_sysctl(const char *path, const __u32 mode)
++{
++ struct task_struct *task = current;
++ const struct cred *cred = current_cred();
++
++ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype,
++ cred->uid, cred->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
++ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename,
++ 1UL, 1UL, path, (unsigned long) mode, &task->signal->saved_ip);
++
++ return;
++}
++
++static void
++gr_log_learn_id_change(const char type, const unsigned int real,
++ const unsigned int effective, const unsigned int fs)
++{
++ struct task_struct *task = current;
++ const struct cred *cred = current_cred();
++
++ security_learn(GR_ID_LEARN_MSG, task->role->rolename, task->role->roletype,
++ cred->uid, cred->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
++ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename,
++ type, real, effective, fs, &task->signal->saved_ip);
++
++ return;
++}
++
++__u32
++gr_check_link(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const struct dentry * old_dentry, const struct vfsmount * old_mnt)
++{
++ struct acl_object_label *obj;
++ __u32 oldmode, newmode;
++ __u32 needmode;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return (GR_CREATE | GR_LINK);
++
++ obj = chk_obj_label(old_dentry, old_mnt, current->acl);
++ oldmode = obj->mode;
++
++ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
++ oldmode |= (GR_CREATE | GR_LINK);
++
++ needmode = GR_CREATE | GR_AUDIT_CREATE | GR_SUPPRESS;
++ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
++ needmode |= GR_SETID | GR_AUDIT_SETID;
++
++ newmode =
++ gr_check_create(new_dentry, parent_dentry, parent_mnt,
++ oldmode | needmode);
++
++ needmode = newmode & (GR_FIND | GR_APPEND | GR_WRITE | GR_EXEC |
++ GR_SETID | GR_READ | GR_FIND | GR_DELETE |
++ GR_INHERIT | GR_AUDIT_INHERIT);
++
++ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID) && !(newmode & GR_SETID))
++ goto bad;
++
++ if ((oldmode & needmode) != needmode)
++ goto bad;
++
++ needmode = oldmode & (GR_NOPTRACE | GR_PTRACERD | GR_INHERIT | GR_AUDITS);
++ if ((newmode & needmode) != needmode)
++ goto bad;
++
++ if ((newmode & (GR_CREATE | GR_LINK)) == (GR_CREATE | GR_LINK))
++ return newmode;
++bad:
++ needmode = oldmode;
++ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
++ needmode |= GR_SETID;
++
++ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) {
++ gr_log_learn(old_dentry, old_mnt, needmode);
++ return (GR_CREATE | GR_LINK);
++ } else if (newmode & GR_SUPPRESS)
++ return GR_SUPPRESS;
++ else
++ return 0;
++}
++
++__u32
++gr_search_file(const struct dentry * dentry, const __u32 mode,
++ const struct vfsmount * mnt)
++{
++ __u32 retval = mode;
++ struct acl_subject_label *curracl;
++ struct acl_object_label *currobj;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return (mode & ~GR_AUDITS);
++
++ curracl = current->acl;
++
++ currobj = chk_obj_label(dentry, mnt, curracl);
++ retval = currobj->mode & mode;
++
++ /* if we're opening a specified transfer file for writing
++ (e.g. /dev/initctl), then transfer our role to init
++ */
++ if (unlikely(currobj->mode & GR_INIT_TRANSFER && retval & GR_WRITE &&
++ current->role->roletype & GR_ROLE_PERSIST)) {
++ struct task_struct *task = init_pid_ns.child_reaper;
++
++ if (task->role != current->role) {
++ task->acl_sp_role = 0;
++ task->acl_role_id = current->acl_role_id;
++ task->role = current->role;
++ rcu_read_lock();
++ read_lock(&grsec_exec_file_lock);
++ gr_apply_subject_to_task(task);
++ read_unlock(&grsec_exec_file_lock);
++ rcu_read_unlock();
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_INIT_TRANSFER_MSG);
++ }
++ }
++
++ if (unlikely
++ ((curracl->mode & (GR_LEARN | GR_INHERITLEARN)) && !(mode & GR_NOPTRACE)
++ && (retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))))) {
++ __u32 new_mode = mode;
++
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
++
++ retval = new_mode;
++
++ if (new_mode & GR_EXEC && curracl->mode & GR_INHERITLEARN)
++ new_mode |= GR_INHERIT;
++
++ if (!(mode & GR_NOLEARN))
++ gr_log_learn(dentry, mnt, new_mode);
++ }
++
++ return retval;
++}
++
++__u32
++gr_check_create(const struct dentry * new_dentry, const struct dentry * parent,
++ const struct vfsmount * mnt, const __u32 mode)
++{
++ struct name_entry *match;
++ struct acl_object_label *matchpo;
++ struct acl_subject_label *curracl;
++ char *path;
++ __u32 retval;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return (mode & ~GR_AUDITS);
++
++ preempt_disable();
++ path = gr_to_filename_rbac(new_dentry, mnt);
++ match = lookup_name_entry_create(path);
++
++ if (!match)
++ goto check_parent;
++
++ curracl = current->acl;
++
++ read_lock(&gr_inode_lock);
++ matchpo = lookup_acl_obj_label_create(match->inode, match->device, curracl);
++ read_unlock(&gr_inode_lock);
++
++ if (matchpo) {
++ if ((matchpo->mode & mode) !=
++ (mode & ~(GR_AUDITS | GR_SUPPRESS))
++ && curracl->mode & (GR_LEARN | GR_INHERITLEARN)) {
++ __u32 new_mode = mode;
++
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
++
++ gr_log_learn(new_dentry, mnt, new_mode);
++
++ preempt_enable();
++ return new_mode;
++ }
++ preempt_enable();
++ return (matchpo->mode & mode);
++ }
++
++ check_parent:
++ curracl = current->acl;
++
++ matchpo = chk_obj_create_label(parent, mnt, curracl, path);
++ retval = matchpo->mode & mode;
++
++ if ((retval != (mode & ~(GR_AUDITS | GR_SUPPRESS)))
++ && (curracl->mode & (GR_LEARN | GR_INHERITLEARN))) {
++ __u32 new_mode = mode;
++
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
++
++ gr_log_learn(new_dentry, mnt, new_mode);
++ preempt_enable();
++ return new_mode;
++ }
++
++ preempt_enable();
++ return retval;
++}
++
++int
++gr_check_hidden_task(const struct task_struct *task)
++{
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ if (!(task->acl->mode & GR_PROCFIND) && !(current->acl->mode & GR_VIEW))
++ return 1;
++
++ return 0;
++}
++
++int
++gr_check_protected_task(const struct task_struct *task)
++{
++ if (unlikely(!(gr_status & GR_READY) || !task))
++ return 0;
++
++ if ((task->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL) &&
++ task->acl != current->acl)
++ return 1;
++
++ return 0;
++}
++
++int
++gr_check_protected_task_fowner(struct pid *pid, enum pid_type type)
++{
++ struct task_struct *p;
++ int ret = 0;
++
++ if (unlikely(!(gr_status & GR_READY) || !pid))
++ return ret;
++
++ read_lock(&tasklist_lock);
++ do_each_pid_task(pid, type, p) {
++ if ((p->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL) &&
++ p->acl != current->acl) {
++ ret = 1;
++ goto out;
++ }
++ } while_each_pid_task(pid, type, p);
++out:
++ read_unlock(&tasklist_lock);
++
++ return ret;
++}
++
++void
++gr_copy_label(struct task_struct *tsk)
++{
++ tsk->signal->used_accept = 0;
++ tsk->acl_sp_role = 0;
++ tsk->acl_role_id = current->acl_role_id;
++ tsk->acl = current->acl;
++ tsk->role = current->role;
++ tsk->signal->curr_ip = current->signal->curr_ip;
++ tsk->signal->saved_ip = current->signal->saved_ip;
++ if (current->exec_file)
++ get_file(current->exec_file);
++ tsk->exec_file = current->exec_file;
++ tsk->is_writable = current->is_writable;
++ if (unlikely(current->signal->used_accept)) {
++ current->signal->curr_ip = 0;
++ current->signal->saved_ip = 0;
++ }
++
++ return;
++}
++
++static void
++gr_set_proc_res(struct task_struct *task)
++{
++ struct acl_subject_label *proc;
++ unsigned short i;
++
++ proc = task->acl;
++
++ if (proc->mode & (GR_LEARN | GR_INHERITLEARN))
++ return;
++
++ for (i = 0; i < RLIM_NLIMITS; i++) {
++ if (!(proc->resmask & (1 << i)))
++ continue;
++
++ task->signal->rlim[i].rlim_cur = proc->res[i].rlim_cur;
++ task->signal->rlim[i].rlim_max = proc->res[i].rlim_max;
++ }
++
++ return;
++}
++
++extern int __gr_process_user_ban(struct user_struct *user);
++
++int
++gr_check_user_change(int real, int effective, int fs)
++{
++ unsigned int i;
++ __u16 num;
++ uid_t *uidlist;
++ int curuid;
++ int realok = 0;
++ int effectiveok = 0;
++ int fsok = 0;
++
++#if defined(CONFIG_GRKERNSEC_KERN_LOCKOUT) || defined(CONFIG_GRKERNSEC_BRUTE)
++ struct user_struct *user;
++
++ if (real == -1)
++ goto skipit;
++
++ user = find_user(real);
++ if (user == NULL)
++ goto skipit;
++
++ if (__gr_process_user_ban(user)) {
++ /* for find_user */
++ free_uid(user);
++ return 1;
++ }
++
++ /* for find_user */
++ free_uid(user);
++
++skipit:
++#endif
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
++ gr_log_learn_id_change('u', real, effective, fs);
++
++ num = current->acl->user_trans_num;
++ uidlist = current->acl->user_transitions;
++
++ if (uidlist == NULL)
++ return 0;
++
++ if (real == -1)
++ realok = 1;
++ if (effective == -1)
++ effectiveok = 1;
++ if (fs == -1)
++ fsok = 1;
++
++ if (current->acl->user_trans_type & GR_ID_ALLOW) {
++ for (i = 0; i < num; i++) {
++ curuid = (int)uidlist[i];
++ if (real == curuid)
++ realok = 1;
++ if (effective == curuid)
++ effectiveok = 1;
++ if (fs == curuid)
++ fsok = 1;
++ }
++ } else if (current->acl->user_trans_type & GR_ID_DENY) {
++ for (i = 0; i < num; i++) {
++ curuid = (int)uidlist[i];
++ if (real == curuid)
++ break;
++ if (effective == curuid)
++ break;
++ if (fs == curuid)
++ break;
++ }
++ /* not in deny list */
++ if (i == num) {
++ realok = 1;
++ effectiveok = 1;
++ fsok = 1;
++ }
++ }
++
++ if (realok && effectiveok && fsok)
++ return 0;
++ else {
++ gr_log_int(GR_DONT_AUDIT, GR_USRCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
++ return 1;
++ }
++}
++
++int
++gr_check_group_change(int real, int effective, int fs)
++{
++ unsigned int i;
++ __u16 num;
++ gid_t *gidlist;
++ int curgid;
++ int realok = 0;
++ int effectiveok = 0;
++ int fsok = 0;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
++ gr_log_learn_id_change('g', real, effective, fs);
++
++ num = current->acl->group_trans_num;
++ gidlist = current->acl->group_transitions;
++
++ if (gidlist == NULL)
++ return 0;
++
++ if (real == -1)
++ realok = 1;
++ if (effective == -1)
++ effectiveok = 1;
++ if (fs == -1)
++ fsok = 1;
++
++ if (current->acl->group_trans_type & GR_ID_ALLOW) {
++ for (i = 0; i < num; i++) {
++ curgid = (int)gidlist[i];
++ if (real == curgid)
++ realok = 1;
++ if (effective == curgid)
++ effectiveok = 1;
++ if (fs == curgid)
++ fsok = 1;
++ }
++ } else if (current->acl->group_trans_type & GR_ID_DENY) {
++ for (i = 0; i < num; i++) {
++ curgid = (int)gidlist[i];
++ if (real == curgid)
++ break;
++ if (effective == curgid)
++ break;
++ if (fs == curgid)
++ break;
++ }
++ /* not in deny list */
++ if (i == num) {
++ realok = 1;
++ effectiveok = 1;
++ fsok = 1;
++ }
++ }
++
++ if (realok && effectiveok && fsok)
++ return 0;
++ else {
++ gr_log_int(GR_DONT_AUDIT, GR_GRPCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
++ return 1;
++ }
++}
++
++void
++gr_set_role_label(struct task_struct *task, const uid_t uid, const uid_t gid)
++{
++ struct acl_role_label *role = task->role;
++ struct acl_subject_label *subj = NULL;
++ struct acl_object_label *obj;
++ struct file *filp;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ filp = task->exec_file;
++
++ /* kernel process, we'll give them the kernel role */
++ if (unlikely(!filp)) {
++ task->role = kernel_role;
++ task->acl = kernel_role->root_label;
++ return;
++ } else if (!task->role || !(task->role->roletype & GR_ROLE_SPECIAL))
++ role = lookup_acl_role_label(task, uid, gid);
++
++ /* perform subject lookup in possibly new role
++ we can use this result below in the case where role == task->role
++ */
++ subj = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt, role);
++
++ /* if we changed uid/gid, but result in the same role
++ and are using inheritance, don't lose the inherited subject
++ if current subject is other than what normal lookup
++ would result in, we arrived via inheritance, don't
++ lose subject
++ */
++ if (role != task->role || (!(task->acl->mode & GR_INHERITLEARN) &&
++ (subj == task->acl)))
++ task->acl = subj;
++
++ task->role = role;
++
++ task->is_writable = 0;
++
++ /* ignore additional mmap checks for processes that are writable
++ by the default ACL */
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, default_role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, task->role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++
++#ifdef CONFIG_GRKERNSEC_RBAC_DEBUG
++ printk(KERN_ALERT "Set role label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
++#endif
++
++ gr_set_proc_res(task);
++
++ return;
++}
++
++int
++gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt,
++ const int unsafe_share)
++{
++ struct task_struct *task = current;
++ struct acl_subject_label *newacl;
++ struct acl_object_label *obj;
++ __u32 retmode;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ newacl = chk_subj_label(dentry, mnt, task->role);
++
++ task_lock(task);
++ if ((((task->ptrace & PT_PTRACED) || unsafe_share) &&
++ !(task->acl->mode & GR_POVERRIDE) && (task->acl != newacl) &&
++ !(task->role->roletype & GR_ROLE_GOD) &&
++ !gr_search_file(dentry, GR_PTRACERD, mnt) &&
++ !(task->acl->mode & (GR_LEARN | GR_INHERITLEARN)))) {
++ task_unlock(task);
++ if (unsafe_share)
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_UNSAFESHARE_EXEC_ACL_MSG, dentry, mnt);
++ else
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_PTRACE_EXEC_ACL_MSG, dentry, mnt);
++ return -EACCES;
++ }
++ task_unlock(task);
++
++ obj = chk_obj_label(dentry, mnt, task->acl);
++ retmode = obj->mode & (GR_INHERIT | GR_AUDIT_INHERIT);
++
++ if (!(task->acl->mode & GR_INHERITLEARN) &&
++ ((newacl->mode & GR_LEARN) || !(retmode & GR_INHERIT))) {
++ if (obj->nested)
++ task->acl = obj->nested;
++ else
++ task->acl = newacl;
++ } else if (retmode & GR_INHERIT && retmode & GR_AUDIT_INHERIT)
++ gr_log_str_fs(GR_DO_AUDIT, GR_INHERIT_ACL_MSG, task->acl->filename, dentry, mnt);
++
++ task->is_writable = 0;
++
++ /* ignore additional mmap checks for processes that are writable
++ by the default ACL */
++ obj = chk_obj_label(dentry, mnt, default_role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++ obj = chk_obj_label(dentry, mnt, task->role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++
++ gr_set_proc_res(task);
++
++#ifdef CONFIG_GRKERNSEC_RBAC_DEBUG
++ printk(KERN_ALERT "Set subject label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
++#endif
++ return 0;
++}
++
++/* always called with valid inodev ptr */
++static void
++do_handle_delete(struct inodev_entry *inodev, const ino_t ino, const dev_t dev)
++{
++ struct acl_object_label *matchpo;
++ struct acl_subject_label *matchps;
++ struct acl_subject_label *subj;
++ struct acl_role_label *role;
++ unsigned int x;
++
++ FOR_EACH_ROLE_START(role)
++ FOR_EACH_SUBJECT_START(role, subj, x)
++ if ((matchpo = lookup_acl_obj_label(ino, dev, subj)) != NULL)
++ matchpo->mode |= GR_DELETED;
++ FOR_EACH_SUBJECT_END(subj,x)
++ FOR_EACH_NESTED_SUBJECT_START(role, subj)
++ if (subj->inode == ino && subj->device == dev)
++ subj->mode |= GR_DELETED;
++ FOR_EACH_NESTED_SUBJECT_END(subj)
++ if ((matchps = lookup_acl_subj_label(ino, dev, role)) != NULL)
++ matchps->mode |= GR_DELETED;
++ FOR_EACH_ROLE_END(role)
++
++ inodev->nentry->deleted = 1;
++
++ return;
++}
++
++void
++gr_handle_delete(const ino_t ino, const dev_t dev)
++{
++ struct inodev_entry *inodev;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ write_lock(&gr_inode_lock);
++ inodev = lookup_inodev_entry(ino, dev);
++ if (inodev != NULL)
++ do_handle_delete(inodev, ino, dev);
++ write_unlock(&gr_inode_lock);
++
++ return;
++}
++
++static void
++update_acl_obj_label(const ino_t oldinode, const dev_t olddevice,
++ const ino_t newinode, const dev_t newdevice,
++ struct acl_subject_label *subj)
++{
++ unsigned int index = fhash(oldinode, olddevice, subj->obj_hash_size);
++ struct acl_object_label *match;
++
++ match = subj->obj_hash[index];
++
++ while (match && (match->inode != oldinode ||
++ match->device != olddevice ||
++ !(match->mode & GR_DELETED)))
++ match = match->next;
++
++ if (match && (match->inode == oldinode)
++ && (match->device == olddevice)
++ && (match->mode & GR_DELETED)) {
++ if (match->prev == NULL) {
++ subj->obj_hash[index] = match->next;
++ if (match->next != NULL)
++ match->next->prev = NULL;
++ } else {
++ match->prev->next = match->next;
++ if (match->next != NULL)
++ match->next->prev = match->prev;
++ }
++ match->prev = NULL;
++ match->next = NULL;
++ match->inode = newinode;
++ match->device = newdevice;
++ match->mode &= ~GR_DELETED;
++
++ insert_acl_obj_label(match, subj);
++ }
++
++ return;
++}
++
++static void
++update_acl_subj_label(const ino_t oldinode, const dev_t olddevice,
++ const ino_t newinode, const dev_t newdevice,
++ struct acl_role_label *role)
++{
++ unsigned int index = fhash(oldinode, olddevice, role->subj_hash_size);
++ struct acl_subject_label *match;
++
++ match = role->subj_hash[index];
++
++ while (match && (match->inode != oldinode ||
++ match->device != olddevice ||
++ !(match->mode & GR_DELETED)))
++ match = match->next;
++
++ if (match && (match->inode == oldinode)
++ && (match->device == olddevice)
++ && (match->mode & GR_DELETED)) {
++ if (match->prev == NULL) {
++ role->subj_hash[index] = match->next;
++ if (match->next != NULL)
++ match->next->prev = NULL;
++ } else {
++ match->prev->next = match->next;
++ if (match->next != NULL)
++ match->next->prev = match->prev;
++ }
++ match->prev = NULL;
++ match->next = NULL;
++ match->inode = newinode;
++ match->device = newdevice;
++ match->mode &= ~GR_DELETED;
++
++ insert_acl_subj_label(match, role);
++ }
++
++ return;
++}
++
++static void
++update_inodev_entry(const ino_t oldinode, const dev_t olddevice,
++ const ino_t newinode, const dev_t newdevice)
++{
++ unsigned int index = fhash(oldinode, olddevice, inodev_set.i_size);
++ struct inodev_entry *match;
++
++ match = inodev_set.i_hash[index];
++
++ while (match && (match->nentry->inode != oldinode ||
++ match->nentry->device != olddevice || !match->nentry->deleted))
++ match = match->next;
++
++ if (match && (match->nentry->inode == oldinode)
++ && (match->nentry->device == olddevice) &&
++ match->nentry->deleted) {
++ if (match->prev == NULL) {
++ inodev_set.i_hash[index] = match->next;
++ if (match->next != NULL)
++ match->next->prev = NULL;
++ } else {
++ match->prev->next = match->next;
++ if (match->next != NULL)
++ match->next->prev = match->prev;
++ }
++ match->prev = NULL;
++ match->next = NULL;
++ match->nentry->inode = newinode;
++ match->nentry->device = newdevice;
++ match->nentry->deleted = 0;
++
++ insert_inodev_entry(match);
++ }
++
++ return;
++}
++
++static void
++do_handle_create(const struct name_entry *matchn, const struct dentry *dentry,
++ const struct vfsmount *mnt)
++{
++ struct acl_subject_label *subj;
++ struct acl_role_label *role;
++ unsigned int x;
++ ino_t ino = dentry->d_inode->i_ino;
++ dev_t dev = __get_dev(dentry);
++
++ FOR_EACH_ROLE_START(role)
++ update_acl_subj_label(matchn->inode, matchn->device, ino, dev, role);
++
++ FOR_EACH_NESTED_SUBJECT_START(role, subj)
++ if ((subj->inode == ino) && (subj->device == dev)) {
++ subj->inode = ino;
++ subj->device = dev;
++ }
++ FOR_EACH_NESTED_SUBJECT_END(subj)
++ FOR_EACH_SUBJECT_START(role, subj, x)
++ update_acl_obj_label(matchn->inode, matchn->device,
++ ino, dev, subj);
++ FOR_EACH_SUBJECT_END(subj,x)
++ FOR_EACH_ROLE_END(role)
++
++ update_inodev_entry(matchn->inode, matchn->device, ino, dev);
++
++ return;
++}
++
++void
++gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ struct name_entry *matchn;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ preempt_disable();
++ matchn = lookup_name_entry(gr_to_filename_rbac(dentry, mnt));
++
++ if (unlikely((unsigned long)matchn)) {
++ write_lock(&gr_inode_lock);
++ do_handle_create(matchn, dentry, mnt);
++ write_unlock(&gr_inode_lock);
++ }
++ preempt_enable();
++
++ return;
++}
++
++void
++gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
++ struct dentry *old_dentry,
++ struct dentry *new_dentry,
++ struct vfsmount *mnt, const __u8 replace)
++{
++ struct name_entry *matchn;
++ struct inodev_entry *inodev;
++ ino_t old_ino = old_dentry->d_inode->i_ino;
++ dev_t old_dev = __get_dev(old_dentry);
++
++ /* vfs_rename swaps the name and parent link for old_dentry and
++ new_dentry
++ at this point, old_dentry has the new name, parent link, and inode
++ for the renamed file
++ if a file is being replaced by a rename, new_dentry has the inode
++ and name for the replaced file
++ */
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ preempt_disable();
++ matchn = lookup_name_entry(gr_to_filename_rbac(old_dentry, mnt));
++
++ /* we wouldn't have to check d_inode if it weren't for
++ NFS silly-renaming
++ */
++
++ write_lock(&gr_inode_lock);
++ if (unlikely(replace && new_dentry->d_inode)) {
++ ino_t new_ino = new_dentry->d_inode->i_ino;
++ dev_t new_dev = __get_dev(new_dentry);
++
++ inodev = lookup_inodev_entry(new_ino, new_dev);
++ if (inodev != NULL && (new_dentry->d_inode->i_nlink <= 1))
++ do_handle_delete(inodev, new_ino, new_dev);
++ }
++
++ inodev = lookup_inodev_entry(old_ino, old_dev);
++ if (inodev != NULL && (old_dentry->d_inode->i_nlink <= 1))
++ do_handle_delete(inodev, old_ino, old_dev);
++
++ if (unlikely((unsigned long)matchn))
++ do_handle_create(matchn, old_dentry, mnt);
++
++ write_unlock(&gr_inode_lock);
++ preempt_enable();
++
++ return;
++}
++
++static int
++lookup_special_role_auth(__u16 mode, const char *rolename, unsigned char **salt,
++ unsigned char **sum)
++{
++ struct acl_role_label *r;
++ struct role_allowed_ip *ipp;
++ struct role_transition *trans;
++ unsigned int i;
++ int found = 0;
++ u32 curr_ip = current->signal->curr_ip;
++
++ current->signal->saved_ip = curr_ip;
++
++ /* check transition table */
++
++ for (trans = current->role->transitions; trans; trans = trans->next) {
++ if (!strcmp(rolename, trans->rolename)) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found)
++ return 0;
++
++ /* handle special roles that do not require authentication
++ and check ip */
++
++ FOR_EACH_ROLE_START(r)
++ if (!strcmp(rolename, r->rolename) &&
++ (r->roletype & GR_ROLE_SPECIAL)) {
++ found = 0;
++ if (r->allowed_ips != NULL) {
++ for (ipp = r->allowed_ips; ipp; ipp = ipp->next) {
++ if ((ntohl(curr_ip) & ipp->netmask) ==
++ (ntohl(ipp->addr) & ipp->netmask))
++ found = 1;
++ }
++ } else
++ found = 2;
++ if (!found)
++ return 0;
++
++ if (((mode == GR_SPROLE) && (r->roletype & GR_ROLE_NOPW)) ||
++ ((mode == GR_SPROLEPAM) && (r->roletype & GR_ROLE_PAM))) {
++ *salt = NULL;
++ *sum = NULL;
++ return 1;
++ }
++ }
++ FOR_EACH_ROLE_END(r)
++
++ for (i = 0; i < num_sprole_pws; i++) {
++ if (!strcmp(rolename, acl_special_roles[i]->rolename)) {
++ *salt = acl_special_roles[i]->salt;
++ *sum = acl_special_roles[i]->sum;
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++static void
++assign_special_role(char *rolename)
++{
++ struct acl_object_label *obj;
++ struct acl_role_label *r;
++ struct acl_role_label *assigned = NULL;
++ struct task_struct *tsk;
++ struct file *filp;
++
++ FOR_EACH_ROLE_START(r)
++ if (!strcmp(rolename, r->rolename) &&
++ (r->roletype & GR_ROLE_SPECIAL)) {
++ assigned = r;
++ break;
++ }
++ FOR_EACH_ROLE_END(r)
++
++ if (!assigned)
++ return;
++
++ read_lock(&tasklist_lock);
++ read_lock(&grsec_exec_file_lock);
++
++ tsk = current->real_parent;
++ if (tsk == NULL)
++ goto out_unlock;
++
++ filp = tsk->exec_file;
++ if (filp == NULL)
++ goto out_unlock;
++
++ tsk->is_writable = 0;
++
++ tsk->acl_sp_role = 1;
++ tsk->acl_role_id = ++acl_sp_role_value;
++ tsk->role = assigned;
++ tsk->acl = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt, tsk->role);
++
++ /* ignore additional mmap checks for processes that are writable
++ by the default ACL */
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, default_role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ tsk->is_writable = 1;
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, tsk->role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ tsk->is_writable = 1;
++
++#ifdef CONFIG_GRKERNSEC_RBAC_DEBUG
++ printk(KERN_ALERT "Assigning special role:%s subject:%s to process (%s:%d)\n", tsk->role->rolename, tsk->acl->filename, tsk->comm, tsk->pid);
++#endif
++
++out_unlock:
++ read_unlock(&grsec_exec_file_lock);
++ read_unlock(&tasklist_lock);
++ return;
++}
++
++int gr_check_secure_terminal(struct task_struct *task)
++{
++ struct task_struct *p, *p2, *p3;
++ struct files_struct *files;
++ struct fdtable *fdt;
++ struct file *our_file = NULL, *file;
++ int i;
++
++ if (task->signal->tty == NULL)
++ return 1;
++
++ files = get_files_struct(task);
++ if (files != NULL) {
++ rcu_read_lock();
++ fdt = files_fdtable(files);
++ for (i=0; i < fdt->max_fds; i++) {
++ file = fcheck_files(files, i);
++ if (file && (our_file == NULL) && (file->private_data == task->signal->tty)) {
++ get_file(file);
++ our_file = file;
++ }
++ }
++ rcu_read_unlock();
++ put_files_struct(files);
++ }
++
++ if (our_file == NULL)
++ return 1;
++
++ read_lock(&tasklist_lock);
++ do_each_thread(p2, p) {
++ files = get_files_struct(p);
++ if (files == NULL ||
++ (p->signal && p->signal->tty == task->signal->tty)) {
++ if (files != NULL)
++ put_files_struct(files);
++ continue;
++ }
++ rcu_read_lock();
++ fdt = files_fdtable(files);
++ for (i=0; i < fdt->max_fds; i++) {
++ file = fcheck_files(files, i);
++ if (file && S_ISCHR(file->f_path.dentry->d_inode->i_mode) &&
++ file->f_path.dentry->d_inode->i_rdev == our_file->f_path.dentry->d_inode->i_rdev) {
++ p3 = task;
++ while (p3->pid > 0) {
++ if (p3 == p)
++ break;
++ p3 = p3->real_parent;
++ }
++ if (p3 == p)
++ break;
++ gr_log_ttysniff(GR_DONT_AUDIT_GOOD, GR_TTYSNIFF_ACL_MSG, p);
++ gr_handle_alertkill(p);
++ rcu_read_unlock();
++ put_files_struct(files);
++ read_unlock(&tasklist_lock);
++ fput(our_file);
++ return 0;
++ }
++ }
++ rcu_read_unlock();
++ put_files_struct(files);
++ } while_each_thread(p2, p);
++ read_unlock(&tasklist_lock);
++
++ fput(our_file);
++ return 1;
++}
++
++ssize_t
++write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos)
++{
++ struct gr_arg_wrapper uwrap;
++ unsigned char *sprole_salt = NULL;
++ unsigned char *sprole_sum = NULL;
++ int error = sizeof (struct gr_arg_wrapper);
++ int error2 = 0;
++
++ mutex_lock(&gr_dev_mutex);
++
++ if ((gr_status & GR_READY) && !(current->acl->mode & GR_KERNELAUTH)) {
++ error = -EPERM;
++ goto out;
++ }
++
++ if (count != sizeof (struct gr_arg_wrapper)) {
++ gr_log_int_int(GR_DONT_AUDIT_GOOD, GR_DEV_ACL_MSG, (int)count, (int)sizeof(struct gr_arg_wrapper));
++ error = -EINVAL;
++ goto out;
++ }
++
++
++ if (gr_auth_expires && time_after_eq(get_seconds(), gr_auth_expires)) {
++ gr_auth_expires = 0;
++ gr_auth_attempts = 0;
++ }
++
++ if (copy_from_user(&uwrap, buf, sizeof (struct gr_arg_wrapper))) {
++ error = -EFAULT;
++ goto out;
++ }
++
++ if ((uwrap.version != GRSECURITY_VERSION) || (uwrap.size != sizeof(struct gr_arg))) {
++ error = -EINVAL;
++ goto out;
++ }
++
++ if (copy_from_user(gr_usermode, uwrap.arg, sizeof (struct gr_arg))) {
++ error = -EFAULT;
++ goto out;
++ }
++
++ if (gr_usermode->mode != GR_SPROLE && gr_usermode->mode != GR_SPROLEPAM &&
++ gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
++ time_after(gr_auth_expires, get_seconds())) {
++ error = -EBUSY;
++ goto out;
++ }
++
++ /* if non-root trying to do anything other than use a special role,
++ do not attempt authentication, do not count towards authentication
++ locking
++ */
++
++ if (gr_usermode->mode != GR_SPROLE && gr_usermode->mode != GR_STATUS &&
++ gr_usermode->mode != GR_UNSPROLE && gr_usermode->mode != GR_SPROLEPAM &&
++ current_uid()) {
++ error = -EPERM;
++ goto out;
++ }
++
++ /* ensure pw and special role name are null terminated */
++
++ gr_usermode->pw[GR_PW_LEN - 1] = '\0';
++ gr_usermode->sp_role[GR_SPROLE_LEN - 1] = '\0';
++
++ /* Okay.
++ * We have our enough of the argument structure..(we have yet
++ * to copy_from_user the tables themselves) . Copy the tables
++ * only if we need them, i.e. for loading operations. */
++
++ switch (gr_usermode->mode) {
++ case GR_STATUS:
++ if (gr_status & GR_READY) {
++ error = 1;
++ if (!gr_check_secure_terminal(current))
++ error = 3;
++ } else
++ error = 2;
++ goto out;
++ case GR_SHUTDOWN:
++ if ((gr_status & GR_READY)
++ && !(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
++ pax_open_kernel();
++ gr_status &= ~GR_READY;
++ pax_close_kernel();
++
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTS_ACL_MSG);
++ free_variables();
++ memset(gr_usermode, 0, sizeof (struct gr_arg));
++ memset(gr_system_salt, 0, GR_SALT_LEN);
++ memset(gr_system_sum, 0, GR_SHA_LEN);
++ } else if (gr_status & GR_READY) {
++ gr_log_noargs(GR_DONT_AUDIT, GR_SHUTF_ACL_MSG);
++ error = -EPERM;
++ } else {
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTI_ACL_MSG);
++ error = -EAGAIN;
++ }
++ break;
++ case GR_ENABLE:
++ if (!(gr_status & GR_READY) && !(error2 = gracl_init(gr_usermode)))
++ gr_log_str(GR_DONT_AUDIT_GOOD, GR_ENABLE_ACL_MSG, GR_VERSION);
++ else {
++ if (gr_status & GR_READY)
++ error = -EAGAIN;
++ else
++ error = error2;
++ gr_log_str(GR_DONT_AUDIT, GR_ENABLEF_ACL_MSG, GR_VERSION);
++ }
++ break;
++ case GR_RELOAD:
++ if (!(gr_status & GR_READY)) {
++ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOADI_ACL_MSG, GR_VERSION);
++ error = -EAGAIN;
++ } else if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
++ preempt_disable();
++
++ pax_open_kernel();
++ gr_status &= ~GR_READY;
++ pax_close_kernel();
++
++ free_variables();
++ if (!(error2 = gracl_init(gr_usermode))) {
++ preempt_enable();
++ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOAD_ACL_MSG, GR_VERSION);
++ } else {
++ preempt_enable();
++ error = error2;
++ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
++ }
++ } else {
++ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
++ error = -EPERM;
++ }
++ break;
++ case GR_SEGVMOD:
++ if (unlikely(!(gr_status & GR_READY))) {
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODI_ACL_MSG);
++ error = -EAGAIN;
++ break;
++ }
++
++ if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODS_ACL_MSG);
++ if (gr_usermode->segv_device && gr_usermode->segv_inode) {
++ struct acl_subject_label *segvacl;
++ segvacl =
++ lookup_acl_subj_label(gr_usermode->segv_inode,
++ gr_usermode->segv_device,
++ current->role);
++ if (segvacl) {
++ segvacl->crashes = 0;
++ segvacl->expires = 0;
++ }
++ } else if (gr_find_uid(gr_usermode->segv_uid) >= 0) {
++ gr_remove_uid(gr_usermode->segv_uid);
++ }
++ } else {
++ gr_log_noargs(GR_DONT_AUDIT, GR_SEGVMODF_ACL_MSG);
++ error = -EPERM;
++ }
++ break;
++ case GR_SPROLE:
++ case GR_SPROLEPAM:
++ if (unlikely(!(gr_status & GR_READY))) {
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SPROLEI_ACL_MSG);
++ error = -EAGAIN;
++ break;
++ }
++
++ if (current->role->expires && time_after_eq(get_seconds(), current->role->expires)) {
++ current->role->expires = 0;
++ current->role->auth_attempts = 0;
++ }
++
++ if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
++ time_after(current->role->expires, get_seconds())) {
++ error = -EBUSY;
++ goto out;
++ }
++
++ if (lookup_special_role_auth
++ (gr_usermode->mode, gr_usermode->sp_role, &sprole_salt, &sprole_sum)
++ && ((!sprole_salt && !sprole_sum)
++ || !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) {
++ char *p = "";
++ assign_special_role(gr_usermode->sp_role);
++ read_lock(&tasklist_lock);
++ if (current->real_parent)
++ p = current->real_parent->role->rolename;
++ read_unlock(&tasklist_lock);
++ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLES_ACL_MSG,
++ p, acl_sp_role_value);
++ } else {
++ gr_log_str(GR_DONT_AUDIT, GR_SPROLEF_ACL_MSG, gr_usermode->sp_role);
++ error = -EPERM;
++ if(!(current->role->auth_attempts++))
++ current->role->expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
++
++ goto out;
++ }
++ break;
++ case GR_UNSPROLE:
++ if (unlikely(!(gr_status & GR_READY))) {
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_UNSPROLEI_ACL_MSG);
++ error = -EAGAIN;
++ break;
++ }
++
++ if (current->role->roletype & GR_ROLE_SPECIAL) {
++ char *p = "";
++ int i = 0;
++
++ read_lock(&tasklist_lock);
++ if (current->real_parent) {
++ p = current->real_parent->role->rolename;
++ i = current->real_parent->acl_role_id;
++ }
++ read_unlock(&tasklist_lock);
++
++ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_UNSPROLES_ACL_MSG, p, i);
++ gr_set_acls(1);
++ } else {
++ error = -EPERM;
++ goto out;
++ }
++ break;
++ default:
++ gr_log_int(GR_DONT_AUDIT, GR_INVMODE_ACL_MSG, gr_usermode->mode);
++ error = -EINVAL;
++ break;
++ }
++
++ if (error != -EPERM)
++ goto out;
++
++ if(!(gr_auth_attempts++))
++ gr_auth_expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
++
++ out:
++ mutex_unlock(&gr_dev_mutex);
++ return error;
++}
++
++/* must be called with
++ rcu_read_lock();
++ read_lock(&tasklist_lock);
++ read_lock(&grsec_exec_file_lock);
++*/
++int gr_apply_subject_to_task(struct task_struct *task)
++{
++ struct acl_object_label *obj;
++ char *tmpname;
++ struct acl_subject_label *tmpsubj;
++ struct file *filp;
++ struct name_entry *nmatch;
++
++ filp = task->exec_file;
++ if (filp == NULL)
++ return 0;
++
++ /* the following is to apply the correct subject
++ on binaries running when the RBAC system
++ is enabled, when the binaries have been
++ replaced or deleted since their execution
++ -----
++ when the RBAC system starts, the inode/dev
++ from exec_file will be one the RBAC system
++ is unaware of. It only knows the inode/dev
++ of the present file on disk, or the absence
++ of it.
++ */
++ preempt_disable();
++ tmpname = gr_to_filename_rbac(filp->f_path.dentry, filp->f_path.mnt);
++
++ nmatch = lookup_name_entry(tmpname);
++ preempt_enable();
++ tmpsubj = NULL;
++ if (nmatch) {
++ if (nmatch->deleted)
++ tmpsubj = lookup_acl_subj_label_deleted(nmatch->inode, nmatch->device, task->role);
++ else
++ tmpsubj = lookup_acl_subj_label(nmatch->inode, nmatch->device, task->role);
++ if (tmpsubj != NULL)
++ task->acl = tmpsubj;
++ }
++ if (tmpsubj == NULL)
++ task->acl = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt,
++ task->role);
++ if (task->acl) {
++ struct acl_subject_label *curr;
++ curr = task->acl;
++
++ task->is_writable = 0;
++ /* ignore additional mmap checks for processes that are writable
++ by the default ACL */
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, default_role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, task->role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++
++ gr_set_proc_res(task);
++
++#ifdef CONFIG_GRKERNSEC_RBAC_DEBUG
++ printk(KERN_ALERT "gr_set_acls for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
++#endif
++ } else {
++ return 1;
++ }
++
++ return 0;
++}
++
++int
++gr_set_acls(const int type)
++{
++ struct task_struct *task, *task2;
++ struct acl_role_label *role = current->role;
++ __u16 acl_role_id = current->acl_role_id;
++ const struct cred *cred;
++ int ret;
++
++ rcu_read_lock();
++ read_lock(&tasklist_lock);
++ read_lock(&grsec_exec_file_lock);
++ do_each_thread(task2, task) {
++ /* check to see if we're called from the exit handler,
++ if so, only replace ACLs that have inherited the admin
++ ACL */
++
++ if (type && (task->role != role ||
++ task->acl_role_id != acl_role_id))
++ continue;
++
++ task->acl_role_id = 0;
++ task->acl_sp_role = 0;
++
++ if (task->exec_file) {
++ cred = __task_cred(task);
++ task->role = lookup_acl_role_label(task, cred->uid, cred->gid);
++ ret = gr_apply_subject_to_task(task);
++ if (ret) {
++ read_unlock(&grsec_exec_file_lock);
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_DEFACL_MSG, task->comm, task->pid);
++ return ret;
++ }
++ } else {
++ // it's a kernel process
++ task->role = kernel_role;
++ task->acl = kernel_role->root_label;
++#ifdef CONFIG_GRKERNSEC_ACL_HIDEKERN
++ task->acl->mode &= ~GR_PROCFIND;
++#endif
++ }
++ } while_each_thread(task2, task);
++ read_unlock(&grsec_exec_file_lock);
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++
++ return 0;
++}
++
++void
++gr_learn_resource(const struct task_struct *task,
++ const int res, const unsigned long wanted, const int gt)
++{
++ struct acl_subject_label *acl;
++ const struct cred *cred;
++
++ if (unlikely((gr_status & GR_READY) &&
++ task->acl && (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))))
++ goto skip_reslog;
++
++#ifdef CONFIG_GRKERNSEC_RESLOG
++ gr_log_resource(task, res, wanted, gt);
++#endif
++ skip_reslog:
++
++ if (unlikely(!(gr_status & GR_READY) || !wanted || res >= GR_NLIMITS))
++ return;
++
++ acl = task->acl;
++
++ if (likely(!acl || !(acl->mode & (GR_LEARN | GR_INHERITLEARN)) ||
++ !(acl->resmask & (1 << (unsigned short) res))))
++ return;
++
++ if (wanted >= acl->res[res].rlim_cur) {
++ unsigned long res_add;
++
++ res_add = wanted;
++ switch (res) {
++ case RLIMIT_CPU:
++ res_add += GR_RLIM_CPU_BUMP;
++ break;
++ case RLIMIT_FSIZE:
++ res_add += GR_RLIM_FSIZE_BUMP;
++ break;
++ case RLIMIT_DATA:
++ res_add += GR_RLIM_DATA_BUMP;
++ break;
++ case RLIMIT_STACK:
++ res_add += GR_RLIM_STACK_BUMP;
++ break;
++ case RLIMIT_CORE:
++ res_add += GR_RLIM_CORE_BUMP;
++ break;
++ case RLIMIT_RSS:
++ res_add += GR_RLIM_RSS_BUMP;
++ break;
++ case RLIMIT_NPROC:
++ res_add += GR_RLIM_NPROC_BUMP;
++ break;
++ case RLIMIT_NOFILE:
++ res_add += GR_RLIM_NOFILE_BUMP;
++ break;
++ case RLIMIT_MEMLOCK:
++ res_add += GR_RLIM_MEMLOCK_BUMP;
++ break;
++ case RLIMIT_AS:
++ res_add += GR_RLIM_AS_BUMP;
++ break;
++ case RLIMIT_LOCKS:
++ res_add += GR_RLIM_LOCKS_BUMP;
++ break;
++ case RLIMIT_SIGPENDING:
++ res_add += GR_RLIM_SIGPENDING_BUMP;
++ break;
++ case RLIMIT_MSGQUEUE:
++ res_add += GR_RLIM_MSGQUEUE_BUMP;
++ break;
++ case RLIMIT_NICE:
++ res_add += GR_RLIM_NICE_BUMP;
++ break;
++ case RLIMIT_RTPRIO:
++ res_add += GR_RLIM_RTPRIO_BUMP;
++ break;
++ case RLIMIT_RTTIME:
++ res_add += GR_RLIM_RTTIME_BUMP;
++ break;
++ }
++
++ acl->res[res].rlim_cur = res_add;
++
++ if (wanted > acl->res[res].rlim_max)
++ acl->res[res].rlim_max = res_add;
++
++ /* only log the subject filename, since resource logging is supported for
++ single-subject learning only */
++ rcu_read_lock();
++ cred = __task_cred(task);
++ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
++ task->role->roletype, cred->uid, cred->gid, acl->filename,
++ acl->filename, acl->res[res].rlim_cur, acl->res[res].rlim_max,
++ "", (unsigned long) res, &task->signal->saved_ip);
++ rcu_read_unlock();
++ }
++
++ return;
++}
++
++#if defined(CONFIG_PAX_HAVE_ACL_FLAGS) && (defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR))
++void
++pax_set_initial_flags(struct linux_binprm *bprm)
++{
++ struct task_struct *task = current;
++ struct acl_subject_label *proc;
++ unsigned long flags;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ flags = pax_get_flags(task);
++
++ proc = task->acl;
++
++ if (proc->pax_flags & GR_PAX_DISABLE_PAGEEXEC)
++ flags &= ~MF_PAX_PAGEEXEC;
++ if (proc->pax_flags & GR_PAX_DISABLE_SEGMEXEC)
++ flags &= ~MF_PAX_SEGMEXEC;
++ if (proc->pax_flags & GR_PAX_DISABLE_RANDMMAP)
++ flags &= ~MF_PAX_RANDMMAP;
++ if (proc->pax_flags & GR_PAX_DISABLE_EMUTRAMP)
++ flags &= ~MF_PAX_EMUTRAMP;
++ if (proc->pax_flags & GR_PAX_DISABLE_MPROTECT)
++ flags &= ~MF_PAX_MPROTECT;
++
++ if (proc->pax_flags & GR_PAX_ENABLE_PAGEEXEC)
++ flags |= MF_PAX_PAGEEXEC;
++ if (proc->pax_flags & GR_PAX_ENABLE_SEGMEXEC)
++ flags |= MF_PAX_SEGMEXEC;
++ if (proc->pax_flags & GR_PAX_ENABLE_RANDMMAP)
++ flags |= MF_PAX_RANDMMAP;
++ if (proc->pax_flags & GR_PAX_ENABLE_EMUTRAMP)
++ flags |= MF_PAX_EMUTRAMP;
++ if (proc->pax_flags & GR_PAX_ENABLE_MPROTECT)
++ flags |= MF_PAX_MPROTECT;
++
++ pax_set_flags(task, flags);
++
++ return;
++}
++#endif
++
++#ifdef CONFIG_SYSCTL
++/* Eric Biederman likes breaking userland ABI and every inode-based security
++ system to save 35kb of memory */
++
++/* we modify the passed in filename, but adjust it back before returning */
++static struct acl_object_label *gr_lookup_by_name(char *name, unsigned int len)
++{
++ struct name_entry *nmatch;
++ char *p, *lastp = NULL;
++ struct acl_object_label *obj = NULL, *tmp;
++ struct acl_subject_label *tmpsubj;
++ char c = '\0';
++
++ read_lock(&gr_inode_lock);
++
++ p = name + len - 1;
++ do {
++ nmatch = lookup_name_entry(name);
++ if (lastp != NULL)
++ *lastp = c;
++
++ if (nmatch == NULL)
++ goto next_component;
++ tmpsubj = current->acl;
++ do {
++ obj = lookup_acl_obj_label(nmatch->inode, nmatch->device, tmpsubj);
++ if (obj != NULL) {
++ tmp = obj->globbed;
++ while (tmp) {
++ if (!glob_match(tmp->filename, name)) {
++ obj = tmp;
++ goto found_obj;
++ }
++ tmp = tmp->next;
++ }
++ goto found_obj;
++ }
++ } while ((tmpsubj = tmpsubj->parent_subject));
++next_component:
++ /* end case */
++ if (p == name)
++ break;
++
++ while (*p != '/')
++ p--;
++ if (p == name)
++ lastp = p + 1;
++ else {
++ lastp = p;
++ p--;
++ }
++ c = *lastp;
++ *lastp = '\0';
++ } while (1);
++found_obj:
++ read_unlock(&gr_inode_lock);
++ /* obj returned will always be non-null */
++ return obj;
++}
++
++/* returns 0 when allowing, non-zero on error
++ op of 0 is used for readdir, so we don't log the names of hidden files
++*/
++__u32
++gr_handle_sysctl(const struct ctl_table *table, const int op)
++{
++ struct ctl_table *tmp;
++ const char *proc_sys = "/proc/sys";
++ char *path;
++ struct acl_object_label *obj;
++ unsigned short len = 0, pos = 0, depth = 0, i;
++ __u32 err = 0;
++ __u32 mode = 0;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ /* for now, ignore operations on non-sysctl entries if it's not a
++ readdir*/
++ if (table->child != NULL && op != 0)
++ return 0;
++
++ mode |= GR_FIND;
++ /* it's only a read if it's an entry, read on dirs is for readdir */
++ if (op & MAY_READ)
++ mode |= GR_READ;
++ if (op & MAY_WRITE)
++ mode |= GR_WRITE;
++
++ preempt_disable();
++
++ path = per_cpu_ptr(gr_shared_page[0], smp_processor_id());
++
++ /* it's only a read/write if it's an actual entry, not a dir
++ (which are opened for readdir)
++ */
++
++ /* convert the requested sysctl entry into a pathname */
++
++ for (tmp = (struct ctl_table *)table; tmp != NULL; tmp = tmp->parent) {
++ len += strlen(tmp->procname);
++ len++;
++ depth++;
++ }
++
++ if ((len + depth + strlen(proc_sys) + 1) > PAGE_SIZE) {
++ /* deny */
++ goto out;
++ }
++
++ memset(path, 0, PAGE_SIZE);
++
++ memcpy(path, proc_sys, strlen(proc_sys));
++
++ pos += strlen(proc_sys);
++
++ for (; depth > 0; depth--) {
++ path[pos] = '/';
++ pos++;
++ for (i = 1, tmp = (struct ctl_table *)table; tmp != NULL; tmp = tmp->parent) {
++ if (depth == i) {
++ memcpy(path + pos, tmp->procname,
++ strlen(tmp->procname));
++ pos += strlen(tmp->procname);
++ }
++ i++;
++ }
++ }
++
++ obj = gr_lookup_by_name(path, pos);
++ err = obj->mode & (mode | to_gr_audit(mode) | GR_SUPPRESS);
++
++ if (unlikely((current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) &&
++ ((err & mode) != mode))) {
++ __u32 new_mode = mode;
++
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
++
++ err = 0;
++ gr_log_learn_sysctl(path, new_mode);
++ } else if (!(err & GR_FIND) && !(err & GR_SUPPRESS) && op != 0) {
++ gr_log_hidden_sysctl(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, path);
++ err = -ENOENT;
++ } else if (!(err & GR_FIND)) {
++ err = -ENOENT;
++ } else if (((err & mode) & ~GR_FIND) != (mode & ~GR_FIND) && !(err & GR_SUPPRESS)) {
++ gr_log_str4(GR_DONT_AUDIT, GR_SYSCTL_ACL_MSG, "denied",
++ path, (mode & GR_READ) ? " reading" : "",
++ (mode & GR_WRITE) ? " writing" : "");
++ err = -EACCES;
++ } else if ((err & mode) != mode) {
++ err = -EACCES;
++ } else if ((((err & mode) & ~GR_FIND) == (mode & ~GR_FIND)) && (err & GR_AUDITS)) {
++ gr_log_str4(GR_DO_AUDIT, GR_SYSCTL_ACL_MSG, "successful",
++ path, (mode & GR_READ) ? " reading" : "",
++ (mode & GR_WRITE) ? " writing" : "");
++ err = 0;
++ } else
++ err = 0;
++
++ out:
++ preempt_enable();
++
++ return err;
++}
++#endif
++
++int
++gr_handle_proc_ptrace(struct task_struct *task)
++{
++ struct file *filp;
++ struct task_struct *tmp = task;
++ struct task_struct *curtemp = current;
++ __u32 retmode;
++
++#ifndef CONFIG_GRKERNSEC_HARDEN_PTRACE
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++#endif
++
++ read_lock(&tasklist_lock);
++ read_lock(&grsec_exec_file_lock);
++ filp = task->exec_file;
++
++ while (tmp->pid > 0) {
++ if (tmp == curtemp)
++ break;
++ tmp = tmp->real_parent;
++ }
++
++ if (!filp || (tmp->pid == 0 && ((grsec_enable_harden_ptrace && current_uid() && !(gr_status & GR_READY)) ||
++ ((gr_status & GR_READY) && !(current->acl->mode & GR_RELAXPTRACE))))) {
++ read_unlock(&grsec_exec_file_lock);
++ read_unlock(&tasklist_lock);
++ return 1;
++ }
++
++#ifdef CONFIG_GRKERNSEC_HARDEN_PTRACE
++ if (!(gr_status & GR_READY)) {
++ read_unlock(&grsec_exec_file_lock);
++ read_unlock(&tasklist_lock);
++ return 0;
++ }
++#endif
++
++ retmode = gr_search_file(filp->f_path.dentry, GR_NOPTRACE, filp->f_path.mnt);
++ read_unlock(&grsec_exec_file_lock);
++ read_unlock(&tasklist_lock);
++
++ if (retmode & GR_NOPTRACE)
++ return 1;
++
++ if (!(current->acl->mode & GR_POVERRIDE) && !(current->role->roletype & GR_ROLE_GOD)
++ && (current->acl != task->acl || (current->acl != current->role->root_label
++ && current->pid != task->pid)))
++ return 1;
++
++ return 0;
++}
++
++void task_grsec_rbac(struct seq_file *m, struct task_struct *p)
++{
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ if (!(current->role->roletype & GR_ROLE_GOD))
++ return;
++
++ seq_printf(m, "RBAC:\t%.64s:%c:%.950s\n",
++ p->role->rolename, gr_task_roletype_to_char(p),
++ p->acl->filename);
++}
++
++int
++gr_handle_ptrace(struct task_struct *task, const long request)
++{
++ struct task_struct *tmp = task;
++ struct task_struct *curtemp = current;
++ __u32 retmode;
++
++#ifndef CONFIG_GRKERNSEC_HARDEN_PTRACE
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++#endif
++
++ read_lock(&tasklist_lock);
++ while (tmp->pid > 0) {
++ if (tmp == curtemp)
++ break;
++ tmp = tmp->real_parent;
++ }
++
++ if (tmp->pid == 0 && ((grsec_enable_harden_ptrace && current_uid() && !(gr_status & GR_READY)) ||
++ ((gr_status & GR_READY) && !(current->acl->mode & GR_RELAXPTRACE)))) {
++ read_unlock(&tasklist_lock);
++ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
++ return 1;
++ }
++ read_unlock(&tasklist_lock);
++
++#ifdef CONFIG_GRKERNSEC_HARDEN_PTRACE
++ if (!(gr_status & GR_READY))
++ return 0;
++#endif
++
++ read_lock(&grsec_exec_file_lock);
++ if (unlikely(!task->exec_file)) {
++ read_unlock(&grsec_exec_file_lock);
++ return 0;
++ }
++
++ retmode = gr_search_file(task->exec_file->f_path.dentry, GR_PTRACERD | GR_NOPTRACE, task->exec_file->f_path.mnt);
++ read_unlock(&grsec_exec_file_lock);
++
++ if (retmode & GR_NOPTRACE) {
++ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
++ return 1;
++ }
++
++ if (retmode & GR_PTRACERD) {
++ switch (request) {
++ case PTRACE_POKETEXT:
++ case PTRACE_POKEDATA:
++ case PTRACE_POKEUSR:
++#if !defined(CONFIG_PPC32) && !defined(CONFIG_PPC64) && !defined(CONFIG_PARISC) && !defined(CONFIG_ALPHA) && !defined(CONFIG_IA64)
++ case PTRACE_SETREGS:
++ case PTRACE_SETFPREGS:
++#endif
++#ifdef CONFIG_X86
++ case PTRACE_SETFPXREGS:
++#endif
++#ifdef CONFIG_ALTIVEC
++ case PTRACE_SETVRREGS:
++#endif
++ return 1;
++ default:
++ return 0;
++ }
++ } else if (!(current->acl->mode & GR_POVERRIDE) &&
++ !(current->role->roletype & GR_ROLE_GOD) &&
++ (current->acl != task->acl)) {
++ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
++ return 1;
++ }
++
++ return 0;
++}
++
++static int is_writable_mmap(const struct file *filp)
++{
++ struct task_struct *task = current;
++ struct acl_object_label *obj, *obj2;
++
++ if (gr_status & GR_READY && !(task->acl->mode & GR_OVERRIDE) &&
++ !task->is_writable && S_ISREG(filp->f_path.dentry->d_inode->i_mode) && (filp->f_path.mnt != shm_mnt || (filp->f_path.dentry->d_inode->i_nlink > 0))) {
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, default_role->root_label);
++ obj2 = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt,
++ task->role->root_label);
++ if (unlikely((obj->mode & GR_WRITE) || (obj2->mode & GR_WRITE))) {
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_WRITLIB_ACL_MSG, filp->f_path.dentry, filp->f_path.mnt);
++ return 1;
++ }
++ }
++ return 0;
++}
++
++int
++gr_acl_handle_mmap(const struct file *file, const unsigned long prot)
++{
++ __u32 mode;
++
++ if (unlikely(!file || !(prot & PROT_EXEC)))
++ return 1;
++
++ if (is_writable_mmap(file))
++ return 0;
++
++ mode =
++ gr_search_file(file->f_path.dentry,
++ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
++ file->f_path.mnt);
++
++ if (!gr_tpe_allow(file))
++ return 0;
++
++ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MMAP_ACL_MSG, file->f_path.dentry, file->f_path.mnt);
++ return 0;
++ } else if (unlikely(!(mode & GR_EXEC))) {
++ return 0;
++ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MMAP_ACL_MSG, file->f_path.dentry, file->f_path.mnt);
++ return 1;
++ }
++
++ return 1;
++}
++
++int
++gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
++{
++ __u32 mode;
++
++ if (unlikely(!file || !(prot & PROT_EXEC)))
++ return 1;
++
++ if (is_writable_mmap(file))
++ return 0;
++
++ mode =
++ gr_search_file(file->f_path.dentry,
++ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
++ file->f_path.mnt);
++
++ if (!gr_tpe_allow(file))
++ return 0;
++
++ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MPROTECT_ACL_MSG, file->f_path.dentry, file->f_path.mnt);
++ return 0;
++ } else if (unlikely(!(mode & GR_EXEC))) {
++ return 0;
++ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MPROTECT_ACL_MSG, file->f_path.dentry, file->f_path.mnt);
++ return 1;
++ }
++
++ return 1;
++}
++
++void
++gr_acl_handle_psacct(struct task_struct *task, const long code)
++{
++ unsigned long runtime;
++ unsigned long cputime;
++ unsigned int wday, cday;
++ __u8 whr, chr;
++ __u8 wmin, cmin;
++ __u8 wsec, csec;
++ struct timespec timeval;
++
++ if (unlikely(!(gr_status & GR_READY) || !task->acl ||
++ !(task->acl->mode & GR_PROCACCT)))
++ return;
++
++ do_posix_clock_monotonic_gettime(&timeval);
++ runtime = timeval.tv_sec - task->start_time.tv_sec;
++ wday = runtime / (3600 * 24);
++ runtime -= wday * (3600 * 24);
++ whr = runtime / 3600;
++ runtime -= whr * 3600;
++ wmin = runtime / 60;
++ runtime -= wmin * 60;
++ wsec = runtime;
++
++ cputime = (task->utime + task->stime) / HZ;
++ cday = cputime / (3600 * 24);
++ cputime -= cday * (3600 * 24);
++ chr = cputime / 3600;
++ cputime -= chr * 3600;
++ cmin = cputime / 60;
++ cputime -= cmin * 60;
++ csec = cputime;
++
++ gr_log_procacct(GR_DO_AUDIT, GR_ACL_PROCACCT_MSG, task, wday, whr, wmin, wsec, cday, chr, cmin, csec, code);
++
++ return;
++}
++
++void gr_set_kernel_label(struct task_struct *task)
++{
++ if (gr_status & GR_READY) {
++ task->role = kernel_role;
++ task->acl = kernel_role->root_label;
++ }
++ return;
++}
++
++#ifdef CONFIG_TASKSTATS
++int gr_is_taskstats_denied(int pid)
++{
++ struct task_struct *task;
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ const struct cred *cred;
++#endif
++ int ret = 0;
++
++ /* restrict taskstats viewing to un-chrooted root users
++ who have the 'view' subject flag if the RBAC system is enabled
++ */
++
++ rcu_read_lock();
++ read_lock(&tasklist_lock);
++ task = find_task_by_vpid(pid);
++ if (task) {
++#ifdef CONFIG_GRKERNSEC_CHROOT
++ if (proc_is_chrooted(task))
++ ret = -EACCES;
++#endif
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ cred = __task_cred(task);
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ if (cred->uid != 0)
++ ret = -EACCES;
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ if (cred->uid != 0 && !groups_search(cred->group_info, CONFIG_GRKERNSEC_PROC_GID))
++ ret = -EACCES;
++#endif
++#endif
++ if (gr_status & GR_READY) {
++ if (!(task->acl->mode & GR_VIEW))
++ ret = -EACCES;
++ }
++ } else
++ ret = -ENOENT;
++
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++
++ return ret;
++}
++#endif
++
++/* AUXV entries are filled via a descendant of search_binary_handler
++ after we've already applied the subject for the target
++*/
++int gr_acl_enable_at_secure(void)
++{
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ if (current->acl->mode & GR_ATSECURE)
++ return 1;
++
++ return 0;
++}
++
++int gr_acl_handle_filldir(const struct file *file, const char *name, const unsigned int namelen, const ino_t ino)
++{
++ struct task_struct *task = current;
++ struct dentry *dentry = file->f_path.dentry;
++ struct vfsmount *mnt = file->f_path.mnt;
++ struct acl_object_label *obj, *tmp;
++ struct acl_subject_label *subj;
++ unsigned int bufsize;
++ int is_not_root;
++ char *path;
++ dev_t dev = __get_dev(dentry);
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return 1;
++
++ if (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))
++ return 1;
++
++ /* ignore Eric Biederman */
++ if (IS_PRIVATE(dentry->d_inode))
++ return 1;
++
++ subj = task->acl;
++ do {
++ obj = lookup_acl_obj_label(ino, dev, subj);
++ if (obj != NULL)
++ return (obj->mode & GR_FIND) ? 1 : 0;
++ } while ((subj = subj->parent_subject));
++
++ /* this is purely an optimization since we're looking for an object
++ for the directory we're doing a readdir on
++ if it's possible for any globbed object to match the entry we're
++ filling into the directory, then the object we find here will be
++ an anchor point with attached globbed objects
++ */
++ obj = chk_obj_label_noglob(dentry, mnt, task->acl);
++ if (obj->globbed == NULL)
++ return (obj->mode & GR_FIND) ? 1 : 0;
++
++ is_not_root = ((obj->filename[0] == '/') &&
++ (obj->filename[1] == '\0')) ? 0 : 1;
++ bufsize = PAGE_SIZE - namelen - is_not_root;
++
++ /* check bufsize > PAGE_SIZE || bufsize == 0 */
++ if (unlikely((bufsize - 1) > (PAGE_SIZE - 1)))
++ return 1;
++
++ preempt_disable();
++ path = d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
++ bufsize);
++
++ bufsize = strlen(path);
++
++ /* if base is "/", don't append an additional slash */
++ if (is_not_root)
++ *(path + bufsize) = '/';
++ memcpy(path + bufsize + is_not_root, name, namelen);
++ *(path + bufsize + namelen + is_not_root) = '\0';
++
++ tmp = obj->globbed;
++ while (tmp) {
++ if (!glob_match(tmp->filename, path)) {
++ preempt_enable();
++ return (tmp->mode & GR_FIND) ? 1 : 0;
++ }
++ tmp = tmp->next;
++ }
++ preempt_enable();
++ return (obj->mode & GR_FIND) ? 1 : 0;
++}
++
++#ifdef CONFIG_NETFILTER_XT_MATCH_GRADM_MODULE
++EXPORT_SYMBOL(gr_acl_is_enabled);
++#endif
++EXPORT_SYMBOL(gr_learn_resource);
++EXPORT_SYMBOL(gr_set_kernel_label);
++#ifdef CONFIG_SECURITY
++EXPORT_SYMBOL(gr_check_user_change);
++EXPORT_SYMBOL(gr_check_group_change);
++#endif
++
+diff -urNp linux-2.6.38.7/grsecurity/gracl_cap.c linux-2.6.38.7/grsecurity/gracl_cap.c
+--- linux-2.6.38.7/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl_cap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,139 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++static const char *captab_log[] = {
++ "CAP_CHOWN",
++ "CAP_DAC_OVERRIDE",
++ "CAP_DAC_READ_SEARCH",
++ "CAP_FOWNER",
++ "CAP_FSETID",
++ "CAP_KILL",
++ "CAP_SETGID",
++ "CAP_SETUID",
++ "CAP_SETPCAP",
++ "CAP_LINUX_IMMUTABLE",
++ "CAP_NET_BIND_SERVICE",
++ "CAP_NET_BROADCAST",
++ "CAP_NET_ADMIN",
++ "CAP_NET_RAW",
++ "CAP_IPC_LOCK",
++ "CAP_IPC_OWNER",
++ "CAP_SYS_MODULE",
++ "CAP_SYS_RAWIO",
++ "CAP_SYS_CHROOT",
++ "CAP_SYS_PTRACE",
++ "CAP_SYS_PACCT",
++ "CAP_SYS_ADMIN",
++ "CAP_SYS_BOOT",
++ "CAP_SYS_NICE",
++ "CAP_SYS_RESOURCE",
++ "CAP_SYS_TIME",
++ "CAP_SYS_TTY_CONFIG",
++ "CAP_MKNOD",
++ "CAP_LEASE",
++ "CAP_AUDIT_WRITE",
++ "CAP_AUDIT_CONTROL",
++ "CAP_SETFCAP",
++ "CAP_MAC_OVERRIDE",
++ "CAP_MAC_ADMIN",
++ "CAP_SYSLOG"
++};
++
++EXPORT_SYMBOL(gr_is_capable);
++EXPORT_SYMBOL(gr_is_capable_nolog);
++
++int
++gr_is_capable(const int cap)
++{
++ struct task_struct *task = current;
++ const struct cred *cred = current_cred();
++ struct acl_subject_label *curracl;
++ kernel_cap_t cap_drop = __cap_empty_set, cap_mask = __cap_empty_set;
++ kernel_cap_t cap_audit = __cap_empty_set;
++
++ if (!gr_acl_is_enabled())
++ return 1;
++
++ curracl = task->acl;
++
++ cap_drop = curracl->cap_lower;
++ cap_mask = curracl->cap_mask;
++ cap_audit = curracl->cap_invert_audit;
++
++ while ((curracl = curracl->parent_subject)) {
++ /* if the cap isn't specified in the current computed mask but is specified in the
++ current level subject, and is lowered in the current level subject, then add
++ it to the set of dropped capabilities
++ otherwise, add the current level subject's mask to the current computed mask
++ */
++ if (!cap_raised(cap_mask, cap) && cap_raised(curracl->cap_mask, cap)) {
++ cap_raise(cap_mask, cap);
++ if (cap_raised(curracl->cap_lower, cap))
++ cap_raise(cap_drop, cap);
++ if (cap_raised(curracl->cap_invert_audit, cap))
++ cap_raise(cap_audit, cap);
++ }
++ }
++
++ if (!cap_raised(cap_drop, cap)) {
++ if (cap_raised(cap_audit, cap))
++ gr_log_cap(GR_DO_AUDIT, GR_CAP_ACL_MSG2, task, captab_log[cap]);
++ return 1;
++ }
++
++ curracl = task->acl;
++
++ if ((curracl->mode & (GR_LEARN | GR_INHERITLEARN))
++ && cap_raised(cred->cap_effective, cap)) {
++ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
++ task->role->roletype, cred->uid,
++ cred->gid, task->exec_file ?
++ gr_to_filename(task->exec_file->f_path.dentry,
++ task->exec_file->f_path.mnt) : curracl->filename,
++ curracl->filename, 0UL,
++ 0UL, "", (unsigned long) cap, &task->signal->saved_ip);
++ return 1;
++ }
++
++ if ((cap >= 0) && (cap < (sizeof(captab_log)/sizeof(captab_log[0]))) && cap_raised(cred->cap_effective, cap) && !cap_raised(cap_audit, cap))
++ gr_log_cap(GR_DONT_AUDIT, GR_CAP_ACL_MSG, task, captab_log[cap]);
++ return 0;
++}
++
++int
++gr_is_capable_nolog(const int cap)
++{
++ struct acl_subject_label *curracl;
++ kernel_cap_t cap_drop = __cap_empty_set, cap_mask = __cap_empty_set;
++
++ if (!gr_acl_is_enabled())
++ return 1;
++
++ curracl = current->acl;
++
++ cap_drop = curracl->cap_lower;
++ cap_mask = curracl->cap_mask;
++
++ while ((curracl = curracl->parent_subject)) {
++ /* if the cap isn't specified in the current computed mask but is specified in the
++ current level subject, and is lowered in the current level subject, then add
++ it to the set of dropped capabilities
++ otherwise, add the current level subject's mask to the current computed mask
++ */
++ if (!cap_raised(cap_mask, cap) && cap_raised(curracl->cap_mask, cap)) {
++ cap_raise(cap_mask, cap);
++ if (cap_raised(curracl->cap_lower, cap))
++ cap_raise(cap_drop, cap);
++ }
++ }
++
++ if (!cap_raised(cap_drop, cap))
++ return 1;
++
++ return 0;
++}
++
+diff -urNp linux-2.6.38.7/grsecurity/gracl_fs.c linux-2.6.38.7/grsecurity/gracl_fs.c
+--- linux-2.6.38.7/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl_fs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,431 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/stat.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++#include <linux/gracl.h>
++
++__u32
++gr_acl_handle_hidden_file(const struct dentry * dentry,
++ const struct vfsmount * mnt)
++{
++ __u32 mode;
++
++ if (unlikely(!dentry->d_inode))
++ return GR_FIND;
++
++ mode =
++ gr_search_file(dentry, GR_FIND | GR_AUDIT_FIND | GR_SUPPRESS, mnt);
++
++ if (unlikely(mode & GR_FIND && mode & GR_AUDIT_FIND)) {
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
++ return mode;
++ } else if (unlikely(!(mode & GR_FIND) && !(mode & GR_SUPPRESS))) {
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
++ return 0;
++ } else if (unlikely(!(mode & GR_FIND)))
++ return 0;
++
++ return GR_FIND;
++}
++
++__u32
++gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
++ const int fmode)
++{
++ __u32 reqmode = GR_FIND;
++ __u32 mode;
++
++ if (unlikely(!dentry->d_inode))
++ return reqmode;
++
++ if (unlikely(fmode & O_APPEND))
++ reqmode |= GR_APPEND;
++ else if (unlikely(fmode & FMODE_WRITE))
++ reqmode |= GR_WRITE;
++ if (likely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
++ reqmode |= GR_READ;
++ if ((fmode & FMODE_GREXEC) && (fmode & __FMODE_EXEC))
++ reqmode &= ~GR_READ;
++ mode =
++ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
++ mnt);
++
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
++ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : reqmode &
++ GR_APPEND ? " appending" : "");
++ return reqmode;
++ } else
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
++ {
++ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : reqmode &
++ GR_APPEND ? " appending" : "");
++ return 0;
++ } else if (unlikely((mode & reqmode) != reqmode))
++ return 0;
++
++ return reqmode;
++}
++
++__u32
++gr_acl_handle_creat(const struct dentry * dentry,
++ const struct dentry * p_dentry,
++ const struct vfsmount * p_mnt, const int fmode,
++ const int imode)
++{
++ __u32 reqmode = GR_WRITE | GR_CREATE;
++ __u32 mode;
++
++ if (unlikely(fmode & O_APPEND))
++ reqmode |= GR_APPEND;
++ if (unlikely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
++ reqmode |= GR_READ;
++ if (unlikely((fmode & O_CREAT) && (imode & (S_ISUID | S_ISGID))))
++ reqmode |= GR_SETID;
++
++ mode =
++ gr_check_create(dentry, p_dentry, p_mnt,
++ reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
++
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
++ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : reqmode &
++ GR_APPEND ? " appending" : "");
++ return reqmode;
++ } else
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
++ {
++ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : reqmode &
++ GR_APPEND ? " appending" : "");
++ return 0;
++ } else if (unlikely((mode & reqmode) != reqmode))
++ return 0;
++
++ return reqmode;
++}
++
++__u32
++gr_acl_handle_access(const struct dentry * dentry, const struct vfsmount * mnt,
++ const int fmode)
++{
++ __u32 mode, reqmode = GR_FIND;
++
++ if ((fmode & S_IXOTH) && !S_ISDIR(dentry->d_inode->i_mode))
++ reqmode |= GR_EXEC;
++ if (fmode & S_IWOTH)
++ reqmode |= GR_WRITE;
++ if (fmode & S_IROTH)
++ reqmode |= GR_READ;
++
++ mode =
++ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
++ mnt);
++
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
++ gr_log_fs_rbac_mode3(GR_DO_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : "",
++ reqmode & GR_EXEC ? " executing" : "");
++ return reqmode;
++ } else
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
++ {
++ gr_log_fs_rbac_mode3(GR_DONT_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : "",
++ reqmode & GR_EXEC ? " executing" : "");
++ return 0;
++ } else if (unlikely((mode & reqmode) != reqmode))
++ return 0;
++
++ return reqmode;
++}
++
++static __u32 generic_fs_handler(const struct dentry *dentry, const struct vfsmount *mnt, __u32 reqmode, const char *fmt)
++{
++ __u32 mode;
++
++ mode = gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, mnt);
++
++ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, dentry, mnt);
++ return mode;
++ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, dentry, mnt);
++ return 0;
++ } else if (unlikely((mode & (reqmode)) != (reqmode)))
++ return 0;
++
++ return (reqmode);
++}
++
++__u32
++gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_RMDIR_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_unlink(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_UNLINK_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_truncate(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_TRUNCATE_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_utime(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_ATIME_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_fchmod(const struct dentry *dentry, const struct vfsmount *mnt,
++ mode_t mode)
++{
++ if (unlikely(dentry->d_inode && S_ISSOCK(dentry->d_inode->i_mode)))
++ return 1;
++
++ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
++ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
++ GR_FCHMOD_ACL_MSG);
++ } else {
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_FCHMOD_ACL_MSG);
++ }
++}
++
++__u32
++gr_acl_handle_chmod(const struct dentry *dentry, const struct vfsmount *mnt,
++ mode_t mode)
++{
++ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
++ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
++ GR_CHMOD_ACL_MSG);
++ } else {
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHMOD_ACL_MSG);
++ }
++}
++
++__u32
++gr_acl_handle_chown(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHOWN_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_setxattr(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_SETXATTR_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_execve(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return generic_fs_handler(dentry, mnt, GR_EXEC, GR_EXEC_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_unix(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return generic_fs_handler(dentry, mnt, GR_READ | GR_WRITE,
++ GR_UNIXCONNECT_ACL_MSG);
++}
++
++/* hardlinks require at minimum create permission,
++ any additional privilege required is based on the
++ privilege of the file being linked to
++*/
++__u32
++gr_acl_handle_link(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const struct dentry * old_dentry,
++ const struct vfsmount * old_mnt, const char *to)
++{
++ __u32 mode;
++ __u32 needmode = GR_CREATE | GR_LINK;
++ __u32 needaudit = GR_AUDIT_CREATE | GR_AUDIT_LINK;
++
++ mode =
++ gr_check_link(new_dentry, parent_dentry, parent_mnt, old_dentry,
++ old_mnt);
++
++ if (unlikely(((mode & needmode) == needmode) && (mode & needaudit))) {
++ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
++ return mode;
++ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
++ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
++ return 0;
++ } else if (unlikely((mode & needmode) != needmode))
++ return 0;
++
++ return 1;
++}
++
++__u32
++gr_acl_handle_symlink(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt, const char *from)
++{
++ __u32 needmode = GR_WRITE | GR_CREATE;
++ __u32 mode;
++
++ mode =
++ gr_check_create(new_dentry, parent_dentry, parent_mnt,
++ GR_CREATE | GR_AUDIT_CREATE |
++ GR_WRITE | GR_AUDIT_WRITE | GR_SUPPRESS);
++
++ if (unlikely(mode & GR_WRITE && mode & GR_AUDITS)) {
++ gr_log_fs_str_rbac(GR_DO_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
++ return mode;
++ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
++ gr_log_fs_str_rbac(GR_DONT_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
++ return 0;
++ } else if (unlikely((mode & needmode) != needmode))
++ return 0;
++
++ return (GR_WRITE | GR_CREATE);
++}
++
++static __u32 generic_fs_create_handler(const struct dentry *new_dentry, const struct dentry *parent_dentry, const struct vfsmount *parent_mnt, __u32 reqmode, const char *fmt)
++{
++ __u32 mode;
++
++ mode = gr_check_create(new_dentry, parent_dentry, parent_mnt, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
++
++ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, new_dentry, parent_mnt);
++ return mode;
++ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, new_dentry, parent_mnt);
++ return 0;
++ } else if (unlikely((mode & (reqmode)) != (reqmode)))
++ return 0;
++
++ return (reqmode);
++}
++
++__u32
++gr_acl_handle_mknod(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const int mode)
++{
++ __u32 reqmode = GR_WRITE | GR_CREATE;
++ if (unlikely(mode & (S_ISUID | S_ISGID)))
++ reqmode |= GR_SETID;
++
++ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
++ reqmode, GR_MKNOD_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_mkdir(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt)
++{
++ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
++ GR_WRITE | GR_CREATE, GR_MKDIR_ACL_MSG);
++}
++
++#define RENAME_CHECK_SUCCESS(old, new) \
++ (((old & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)) && \
++ ((new & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)))
++
++int
++gr_acl_handle_rename(struct dentry *new_dentry,
++ struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ struct dentry *old_dentry,
++ struct inode *old_parent_inode,
++ struct vfsmount *old_mnt, const char *newname)
++{
++ __u32 comp1, comp2;
++ int error = 0;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return 0;
++
++ if (!new_dentry->d_inode) {
++ comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt,
++ GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ |
++ GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS);
++ comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE |
++ GR_DELETE | GR_AUDIT_DELETE |
++ GR_AUDIT_READ | GR_AUDIT_WRITE |
++ GR_SUPPRESS, old_mnt);
++ } else {
++ comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE |
++ GR_CREATE | GR_DELETE |
++ GR_AUDIT_CREATE | GR_AUDIT_DELETE |
++ GR_AUDIT_READ | GR_AUDIT_WRITE |
++ GR_SUPPRESS, parent_mnt);
++ comp2 =
++ gr_search_file(old_dentry,
++ GR_READ | GR_WRITE | GR_AUDIT_READ |
++ GR_DELETE | GR_AUDIT_DELETE |
++ GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt);
++ }
++
++ if (RENAME_CHECK_SUCCESS(comp1, comp2) &&
++ ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS)))
++ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
++ else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS)
++ && !(comp2 & GR_SUPPRESS)) {
++ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
++ error = -EACCES;
++ } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2)))
++ error = -EACCES;
++
++ return error;
++}
++
++void
++gr_acl_handle_exit(void)
++{
++ u16 id;
++ char *rolename;
++ struct file *exec_file;
++
++ if (unlikely(current->acl_sp_role && gr_acl_is_enabled() &&
++ !(current->role->roletype & GR_ROLE_PERSIST))) {
++ id = current->acl_role_id;
++ rolename = current->role->rolename;
++ gr_set_acls(1);
++ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLEL_ACL_MSG, rolename, id);
++ }
++
++ write_lock(&grsec_exec_file_lock);
++ exec_file = current->exec_file;
++ current->exec_file = NULL;
++ write_unlock(&grsec_exec_file_lock);
++
++ if (exec_file)
++ fput(exec_file);
++}
++
++int
++gr_acl_handle_procpidmem(const struct task_struct *task)
++{
++ if (unlikely(!gr_acl_is_enabled()))
++ return 0;
++
++ if (task != current && task->acl->mode & GR_PROTPROCFD)
++ return -EACCES;
++
++ return 0;
++}
+diff -urNp linux-2.6.38.7/grsecurity/gracl_ip.c linux-2.6.38.7/grsecurity/gracl_ip.c
+--- linux-2.6.38.7/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl_ip.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,382 @@
++#include <linux/kernel.h>
++#include <asm/uaccess.h>
++#include <asm/errno.h>
++#include <net/sock.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/udp.h>
++#include <linux/smp_lock.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++#define GR_BIND 0x01
++#define GR_CONNECT 0x02
++#define GR_INVERT 0x04
++#define GR_BINDOVERRIDE 0x08
++#define GR_CONNECTOVERRIDE 0x10
++#define GR_SOCK_FAMILY 0x20
++
++static const char * gr_protocols[IPPROTO_MAX] = {
++ "ip", "icmp", "igmp", "ggp", "ipencap", "st", "tcp", "cbt",
++ "egp", "igp", "bbn-rcc", "nvp", "pup", "argus", "emcon", "xnet",
++ "chaos", "udp", "mux", "dcn", "hmp", "prm", "xns-idp", "trunk-1",
++ "trunk-2", "leaf-1", "leaf-2", "rdp", "irtp", "iso-tp4", "netblt", "mfe-nsp",
++ "merit-inp", "sep", "3pc", "idpr", "xtp", "ddp", "idpr-cmtp", "tp++",
++ "il", "ipv6", "sdrp", "ipv6-route", "ipv6-frag", "idrp", "rsvp", "gre",
++ "mhrp", "bna", "ipv6-crypt", "ipv6-auth", "i-nlsp", "swipe", "narp", "mobile",
++ "tlsp", "skip", "ipv6-icmp", "ipv6-nonxt", "ipv6-opts", "unknown:61", "cftp", "unknown:63",
++ "sat-expak", "kryptolan", "rvd", "ippc", "unknown:68", "sat-mon", "visa", "ipcv",
++ "cpnx", "cphb", "wsn", "pvp", "br-sat-mon", "sun-nd", "wb-mon", "wb-expak",
++ "iso-ip", "vmtp", "secure-vmtp", "vines", "ttp", "nfsnet-igp", "dgp", "tcf",
++ "eigrp", "ospf", "sprite-rpc", "larp", "mtp", "ax.25", "ipip", "micp",
++ "scc-sp", "etherip", "encap", "unknown:99", "gmtp", "ifmp", "pnni", "pim",
++ "aris", "scps", "qnx", "a/n", "ipcomp", "snp", "compaq-peer", "ipx-in-ip",
++ "vrrp", "pgm", "unknown:114", "l2tp", "ddx", "iatp", "stp", "srp",
++ "uti", "smp", "sm", "ptp", "isis", "fire", "crtp", "crdup",
++ "sscopmce", "iplt", "sps", "pipe", "sctp", "fc", "unkown:134", "unknown:135",
++ "unknown:136", "unknown:137", "unknown:138", "unknown:139", "unknown:140", "unknown:141", "unknown:142", "unknown:143",
++ "unknown:144", "unknown:145", "unknown:146", "unknown:147", "unknown:148", "unknown:149", "unknown:150", "unknown:151",
++ "unknown:152", "unknown:153", "unknown:154", "unknown:155", "unknown:156", "unknown:157", "unknown:158", "unknown:159",
++ "unknown:160", "unknown:161", "unknown:162", "unknown:163", "unknown:164", "unknown:165", "unknown:166", "unknown:167",
++ "unknown:168", "unknown:169", "unknown:170", "unknown:171", "unknown:172", "unknown:173", "unknown:174", "unknown:175",
++ "unknown:176", "unknown:177", "unknown:178", "unknown:179", "unknown:180", "unknown:181", "unknown:182", "unknown:183",
++ "unknown:184", "unknown:185", "unknown:186", "unknown:187", "unknown:188", "unknown:189", "unknown:190", "unknown:191",
++ "unknown:192", "unknown:193", "unknown:194", "unknown:195", "unknown:196", "unknown:197", "unknown:198", "unknown:199",
++ "unknown:200", "unknown:201", "unknown:202", "unknown:203", "unknown:204", "unknown:205", "unknown:206", "unknown:207",
++ "unknown:208", "unknown:209", "unknown:210", "unknown:211", "unknown:212", "unknown:213", "unknown:214", "unknown:215",
++ "unknown:216", "unknown:217", "unknown:218", "unknown:219", "unknown:220", "unknown:221", "unknown:222", "unknown:223",
++ "unknown:224", "unknown:225", "unknown:226", "unknown:227", "unknown:228", "unknown:229", "unknown:230", "unknown:231",
++ "unknown:232", "unknown:233", "unknown:234", "unknown:235", "unknown:236", "unknown:237", "unknown:238", "unknown:239",
++ "unknown:240", "unknown:241", "unknown:242", "unknown:243", "unknown:244", "unknown:245", "unknown:246", "unknown:247",
++ "unknown:248", "unknown:249", "unknown:250", "unknown:251", "unknown:252", "unknown:253", "unknown:254", "unknown:255",
++ };
++
++static const char * gr_socktypes[SOCK_MAX] = {
++ "unknown:0", "stream", "dgram", "raw", "rdm", "seqpacket", "unknown:6",
++ "unknown:7", "unknown:8", "unknown:9", "packet"
++ };
++
++static const char * gr_sockfamilies[AF_MAX+1] = {
++ "unspec", "unix", "inet", "ax25", "ipx", "appletalk", "netrom", "bridge", "atmpvc", "x25",
++ "inet6", "rose", "decnet", "netbeui", "security", "key", "netlink", "packet", "ash",
++ "econet", "atmsvc", "rds", "sna", "irda", "ppox", "wanpipe", "llc", "fam_27", "fam_28",
++ "tipc", "bluetooth", "iucv", "rxrpc", "isdn", "phonet", "ieee802154", "ciaf"
++ };
++
++const char *
++gr_proto_to_name(unsigned char proto)
++{
++ return gr_protocols[proto];
++}
++
++const char *
++gr_socktype_to_name(unsigned char type)
++{
++ return gr_socktypes[type];
++}
++
++const char *
++gr_sockfamily_to_name(unsigned char family)
++{
++ return gr_sockfamilies[family];
++}
++
++int
++gr_search_socket(const int domain, const int type, const int protocol)
++{
++ struct acl_subject_label *curr;
++ const struct cred *cred = current_cred();
++
++ if (unlikely(!gr_acl_is_enabled()))
++ goto exit;
++
++ if ((domain < 0) || (type < 0) || (protocol < 0) ||
++ (domain >= AF_MAX) || (type >= SOCK_MAX) || (protocol >= IPPROTO_MAX))
++ goto exit; // let the kernel handle it
++
++ curr = current->acl;
++
++ if (curr->sock_families[domain / 32] & (1 << (domain % 32))) {
++ /* the family is allowed, if this is PF_INET allow it only if
++ the extra sock type/protocol checks pass */
++ if (domain == PF_INET)
++ goto inet_check;
++ goto exit;
++ } else {
++ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
++ __u32 fakeip = 0;
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
++ current->role->roletype, cred->uid,
++ cred->gid, current->exec_file ?
++ gr_to_filename(current->exec_file->f_path.dentry,
++ current->exec_file->f_path.mnt) :
++ curr->filename, curr->filename,
++ &fakeip, domain, 0, 0, GR_SOCK_FAMILY,
++ &current->signal->saved_ip);
++ goto exit;
++ }
++ goto exit_fail;
++ }
++
++inet_check:
++ /* the rest of this checking is for IPv4 only */
++ if (!curr->ips)
++ goto exit;
++
++ if ((curr->ip_type & (1 << type)) &&
++ (curr->ip_proto[protocol / 32] & (1 << (protocol % 32))))
++ goto exit;
++
++ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
++ /* we don't place acls on raw sockets , and sometimes
++ dgram/ip sockets are opened for ioctl and not
++ bind/connect, so we'll fake a bind learn log */
++ if (type == SOCK_RAW || type == SOCK_PACKET) {
++ __u32 fakeip = 0;
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
++ current->role->roletype, cred->uid,
++ cred->gid, current->exec_file ?
++ gr_to_filename(current->exec_file->f_path.dentry,
++ current->exec_file->f_path.mnt) :
++ curr->filename, curr->filename,
++ &fakeip, 0, type,
++ protocol, GR_CONNECT, &current->signal->saved_ip);
++ } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) {
++ __u32 fakeip = 0;
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
++ current->role->roletype, cred->uid,
++ cred->gid, current->exec_file ?
++ gr_to_filename(current->exec_file->f_path.dentry,
++ current->exec_file->f_path.mnt) :
++ curr->filename, curr->filename,
++ &fakeip, 0, type,
++ protocol, GR_BIND, &current->signal->saved_ip);
++ }
++ /* we'll log when they use connect or bind */
++ goto exit;
++ }
++
++exit_fail:
++ if (domain == PF_INET)
++ gr_log_str3(GR_DONT_AUDIT, GR_SOCK_MSG, gr_sockfamily_to_name(domain),
++ gr_socktype_to_name(type), gr_proto_to_name(protocol));
++ else
++ gr_log_str2_int(GR_DONT_AUDIT, GR_SOCK_NOINET_MSG, gr_sockfamily_to_name(domain),
++ gr_socktype_to_name(type), protocol);
++
++ return 0;
++exit:
++ return 1;
++}
++
++int check_ip_policy(struct acl_ip_label *ip, __u32 ip_addr, __u16 ip_port, __u8 protocol, const int mode, const int type, __u32 our_addr, __u32 our_netmask)
++{
++ if ((ip->mode & mode) &&
++ (ip_port >= ip->low) &&
++ (ip_port <= ip->high) &&
++ ((ntohl(ip_addr) & our_netmask) ==
++ (ntohl(our_addr) & our_netmask))
++ && (ip->proto[protocol / 32] & (1 << (protocol % 32)))
++ && (ip->type & (1 << type))) {
++ if (ip->mode & GR_INVERT)
++ return 2; // specifically denied
++ else
++ return 1; // allowed
++ }
++
++ return 0; // not specifically allowed, may continue parsing
++}
++
++static int
++gr_search_connectbind(const int full_mode, struct sock *sk,
++ struct sockaddr_in *addr, const int type)
++{
++ char iface[IFNAMSIZ] = {0};
++ struct acl_subject_label *curr;
++ struct acl_ip_label *ip;
++ struct inet_sock *isk;
++ struct net_device *dev;
++ struct in_device *idev;
++ unsigned long i;
++ int ret;
++ int mode = full_mode & (GR_BIND | GR_CONNECT);
++ __u32 ip_addr = 0;
++ __u32 our_addr;
++ __u32 our_netmask;
++ char *p;
++ __u16 ip_port = 0;
++ const struct cred *cred = current_cred();
++
++ if (unlikely(!gr_acl_is_enabled() || sk->sk_family != PF_INET))
++ return 0;
++
++ curr = current->acl;
++ isk = inet_sk(sk);
++
++ /* INADDR_ANY overriding for binds, inaddr_any_override is already in network order */
++ if ((full_mode & GR_BINDOVERRIDE) && addr->sin_addr.s_addr == htonl(INADDR_ANY) && curr->inaddr_any_override != 0)
++ addr->sin_addr.s_addr = curr->inaddr_any_override;
++ if ((full_mode & GR_CONNECT) && isk->inet_saddr == htonl(INADDR_ANY) && curr->inaddr_any_override != 0) {
++ struct sockaddr_in saddr;
++ int err;
++
++ saddr.sin_family = AF_INET;
++ saddr.sin_addr.s_addr = curr->inaddr_any_override;
++ saddr.sin_port = isk->inet_sport;
++
++ err = security_socket_bind(sk->sk_socket, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
++ if (err)
++ return err;
++
++ err = sk->sk_socket->ops->bind(sk->sk_socket, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
++ if (err)
++ return err;
++ }
++
++ if (!curr->ips)
++ return 0;
++
++ ip_addr = addr->sin_addr.s_addr;
++ ip_port = ntohs(addr->sin_port);
++
++ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
++ current->role->roletype, cred->uid,
++ cred->gid, current->exec_file ?
++ gr_to_filename(current->exec_file->f_path.dentry,
++ current->exec_file->f_path.mnt) :
++ curr->filename, curr->filename,
++ &ip_addr, ip_port, type,
++ sk->sk_protocol, mode, &current->signal->saved_ip);
++ return 0;
++ }
++
++ for (i = 0; i < curr->ip_num; i++) {
++ ip = *(curr->ips + i);
++ if (ip->iface != NULL) {
++ strncpy(iface, ip->iface, IFNAMSIZ - 1);
++ p = strchr(iface, ':');
++ if (p != NULL)
++ *p = '\0';
++ dev = dev_get_by_name(sock_net(sk), iface);
++ if (dev == NULL)
++ continue;
++ idev = in_dev_get(dev);
++ if (idev == NULL) {
++ dev_put(dev);
++ continue;
++ }
++ rcu_read_lock();
++ for_ifa(idev) {
++ if (!strcmp(ip->iface, ifa->ifa_label)) {
++ our_addr = ifa->ifa_address;
++ our_netmask = 0xffffffff;
++ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
++ if (ret == 1) {
++ rcu_read_unlock();
++ in_dev_put(idev);
++ dev_put(dev);
++ return 0;
++ } else if (ret == 2) {
++ rcu_read_unlock();
++ in_dev_put(idev);
++ dev_put(dev);
++ goto denied;
++ }
++ }
++ } endfor_ifa(idev);
++ rcu_read_unlock();
++ in_dev_put(idev);
++ dev_put(dev);
++ } else {
++ our_addr = ip->addr;
++ our_netmask = ip->netmask;
++ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
++ if (ret == 1)
++ return 0;
++ else if (ret == 2)
++ goto denied;
++ }
++ }
++
++denied:
++ if (mode == GR_BIND)
++ gr_log_int5_str2(GR_DONT_AUDIT, GR_BIND_ACL_MSG, &ip_addr, ip_port, gr_socktype_to_name(type), gr_proto_to_name(sk->sk_protocol));
++ else if (mode == GR_CONNECT)
++ gr_log_int5_str2(GR_DONT_AUDIT, GR_CONNECT_ACL_MSG, &ip_addr, ip_port, gr_socktype_to_name(type), gr_proto_to_name(sk->sk_protocol));
++
++ return -EACCES;
++}
++
++int
++gr_search_connect(struct socket *sock, struct sockaddr_in *addr)
++{
++ return gr_search_connectbind(GR_CONNECT | GR_CONNECTOVERRIDE, sock->sk, addr, sock->type);
++}
++
++int
++gr_search_bind(struct socket *sock, struct sockaddr_in *addr)
++{
++ return gr_search_connectbind(GR_BIND | GR_BINDOVERRIDE, sock->sk, addr, sock->type);
++}
++
++int gr_search_listen(struct socket *sock)
++{
++ struct sock *sk = sock->sk;
++ struct sockaddr_in addr;
++
++ addr.sin_addr.s_addr = inet_sk(sk)->inet_saddr;
++ addr.sin_port = inet_sk(sk)->inet_sport;
++
++ return gr_search_connectbind(GR_BIND | GR_CONNECTOVERRIDE, sock->sk, &addr, sock->type);
++}
++
++int gr_search_accept(struct socket *sock)
++{
++ struct sock *sk = sock->sk;
++ struct sockaddr_in addr;
++
++ addr.sin_addr.s_addr = inet_sk(sk)->inet_saddr;
++ addr.sin_port = inet_sk(sk)->inet_sport;
++
++ return gr_search_connectbind(GR_BIND | GR_CONNECTOVERRIDE, sock->sk, &addr, sock->type);
++}
++
++int
++gr_search_udp_sendmsg(struct sock *sk, struct sockaddr_in *addr)
++{
++ if (addr)
++ return gr_search_connectbind(GR_CONNECT, sk, addr, SOCK_DGRAM);
++ else {
++ struct sockaddr_in sin;
++ const struct inet_sock *inet = inet_sk(sk);
++
++ sin.sin_addr.s_addr = inet->inet_daddr;
++ sin.sin_port = inet->inet_dport;
++
++ return gr_search_connectbind(GR_CONNECT | GR_CONNECTOVERRIDE, sk, &sin, SOCK_DGRAM);
++ }
++}
++
++int
++gr_search_udp_recvmsg(struct sock *sk, const struct sk_buff *skb)
++{
++ struct sockaddr_in sin;
++
++ if (unlikely(skb->len < sizeof (struct udphdr)))
++ return 0; // skip this packet
++
++ sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
++ sin.sin_port = udp_hdr(skb)->source;
++
++ return gr_search_connectbind(GR_CONNECT | GR_CONNECTOVERRIDE, sk, &sin, SOCK_DGRAM);
++}
+diff -urNp linux-2.6.38.7/grsecurity/gracl_learn.c linux-2.6.38.7/grsecurity/gracl_learn.c
+--- linux-2.6.38.7/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl_learn.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,211 @@
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/smp_lock.h>
++#include <linux/string.h>
++#include <linux/file.h>
++#include <linux/types.h>
++#include <linux/vmalloc.h>
++#include <linux/grinternal.h>
++
++extern ssize_t write_grsec_handler(struct file * file, const char __user * buf,
++ size_t count, loff_t *ppos);
++extern int gr_acl_is_enabled(void);
++
++static DECLARE_WAIT_QUEUE_HEAD(learn_wait);
++static int gr_learn_attached;
++
++/* use a 512k buffer */
++#define LEARN_BUFFER_SIZE (512 * 1024)
++
++static DEFINE_SPINLOCK(gr_learn_lock);
++static DEFINE_MUTEX(gr_learn_user_mutex);
++
++/* we need to maintain two buffers, so that the kernel context of grlearn
++ uses a semaphore around the userspace copying, and the other kernel contexts
++ use a spinlock when copying into the buffer, since they cannot sleep
++*/
++static char *learn_buffer;
++static char *learn_buffer_user;
++static int learn_buffer_len;
++static int learn_buffer_user_len;
++
++static ssize_t
++read_learn(struct file *file, char __user * buf, size_t count, loff_t * ppos)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ ssize_t retval = 0;
++
++ add_wait_queue(&learn_wait, &wait);
++ set_current_state(TASK_INTERRUPTIBLE);
++ do {
++ mutex_lock(&gr_learn_user_mutex);
++ spin_lock(&gr_learn_lock);
++ if (learn_buffer_len)
++ break;
++ spin_unlock(&gr_learn_lock);
++ mutex_unlock(&gr_learn_user_mutex);
++ if (file->f_flags & O_NONBLOCK) {
++ retval = -EAGAIN;
++ goto out;
++ }
++ if (signal_pending(current)) {
++ retval = -ERESTARTSYS;
++ goto out;
++ }
++
++ schedule();
++ } while (1);
++
++ memcpy(learn_buffer_user, learn_buffer, learn_buffer_len);
++ learn_buffer_user_len = learn_buffer_len;
++ retval = learn_buffer_len;
++ learn_buffer_len = 0;
++
++ spin_unlock(&gr_learn_lock);
++
++ if (copy_to_user(buf, learn_buffer_user, learn_buffer_user_len))
++ retval = -EFAULT;
++
++ mutex_unlock(&gr_learn_user_mutex);
++out:
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&learn_wait, &wait);
++ return retval;
++}
++
++static unsigned int
++poll_learn(struct file * file, poll_table * wait)
++{
++ poll_wait(file, &learn_wait, wait);
++
++ if (learn_buffer_len)
++ return (POLLIN | POLLRDNORM);
++
++ return 0;
++}
++
++void
++gr_clear_learn_entries(void)
++{
++ char *tmp;
++
++ mutex_lock(&gr_learn_user_mutex);
++ if (learn_buffer != NULL) {
++ spin_lock(&gr_learn_lock);
++ tmp = learn_buffer;
++ learn_buffer = NULL;
++ spin_unlock(&gr_learn_lock);
++ vfree(learn_buffer);
++ }
++ if (learn_buffer_user != NULL) {
++ vfree(learn_buffer_user);
++ learn_buffer_user = NULL;
++ }
++ learn_buffer_len = 0;
++ mutex_unlock(&gr_learn_user_mutex);
++
++ return;
++}
++
++void
++gr_add_learn_entry(const char *fmt, ...)
++{
++ va_list args;
++ unsigned int len;
++
++ if (!gr_learn_attached)
++ return;
++
++ spin_lock(&gr_learn_lock);
++
++ /* leave a gap at the end so we know when it's "full" but don't have to
++ compute the exact length of the string we're trying to append
++ */
++ if (learn_buffer_len > LEARN_BUFFER_SIZE - 16384) {
++ spin_unlock(&gr_learn_lock);
++ wake_up_interruptible(&learn_wait);
++ return;
++ }
++ if (learn_buffer == NULL) {
++ spin_unlock(&gr_learn_lock);
++ return;
++ }
++
++ va_start(args, fmt);
++ len = vsnprintf(learn_buffer + learn_buffer_len, LEARN_BUFFER_SIZE - learn_buffer_len, fmt, args);
++ va_end(args);
++
++ learn_buffer_len += len + 1;
++
++ spin_unlock(&gr_learn_lock);
++ wake_up_interruptible(&learn_wait);
++
++ return;
++}
++
++static int
++open_learn(struct inode *inode, struct file *file)
++{
++ if (file->f_mode & FMODE_READ && gr_learn_attached)
++ return -EBUSY;
++ if (file->f_mode & FMODE_READ) {
++ int retval = 0;
++ mutex_lock(&gr_learn_user_mutex);
++ if (learn_buffer == NULL)
++ learn_buffer = vmalloc(LEARN_BUFFER_SIZE);
++ if (learn_buffer_user == NULL)
++ learn_buffer_user = vmalloc(LEARN_BUFFER_SIZE);
++ if (learn_buffer == NULL) {
++ retval = -ENOMEM;
++ goto out_error;
++ }
++ if (learn_buffer_user == NULL) {
++ retval = -ENOMEM;
++ goto out_error;
++ }
++ learn_buffer_len = 0;
++ learn_buffer_user_len = 0;
++ gr_learn_attached = 1;
++out_error:
++ mutex_unlock(&gr_learn_user_mutex);
++ return retval;
++ }
++ return 0;
++}
++
++static int
++close_learn(struct inode *inode, struct file *file)
++{
++ char *tmp;
++
++ if (file->f_mode & FMODE_READ) {
++ mutex_lock(&gr_learn_user_mutex);
++ if (learn_buffer != NULL) {
++ spin_lock(&gr_learn_lock);
++ tmp = learn_buffer;
++ learn_buffer = NULL;
++ spin_unlock(&gr_learn_lock);
++ vfree(tmp);
++ }
++ if (learn_buffer_user != NULL) {
++ vfree(learn_buffer_user);
++ learn_buffer_user = NULL;
++ }
++ learn_buffer_len = 0;
++ learn_buffer_user_len = 0;
++ gr_learn_attached = 0;
++ mutex_unlock(&gr_learn_user_mutex);
++ }
++
++ return 0;
++}
++
++const struct file_operations grsec_fops = {
++ .read = read_learn,
++ .write = write_grsec_handler,
++ .open = open_learn,
++ .release = close_learn,
++ .poll = poll_learn,
++};
+diff -urNp linux-2.6.38.7/grsecurity/gracl_res.c linux-2.6.38.7/grsecurity/gracl_res.c
+--- linux-2.6.38.7/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl_res.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,68 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/gracl.h>
++#include <linux/grinternal.h>
++
++static const char *restab_log[] = {
++ [RLIMIT_CPU] = "RLIMIT_CPU",
++ [RLIMIT_FSIZE] = "RLIMIT_FSIZE",
++ [RLIMIT_DATA] = "RLIMIT_DATA",
++ [RLIMIT_STACK] = "RLIMIT_STACK",
++ [RLIMIT_CORE] = "RLIMIT_CORE",
++ [RLIMIT_RSS] = "RLIMIT_RSS",
++ [RLIMIT_NPROC] = "RLIMIT_NPROC",
++ [RLIMIT_NOFILE] = "RLIMIT_NOFILE",
++ [RLIMIT_MEMLOCK] = "RLIMIT_MEMLOCK",
++ [RLIMIT_AS] = "RLIMIT_AS",
++ [RLIMIT_LOCKS] = "RLIMIT_LOCKS",
++ [RLIMIT_SIGPENDING] = "RLIMIT_SIGPENDING",
++ [RLIMIT_MSGQUEUE] = "RLIMIT_MSGQUEUE",
++ [RLIMIT_NICE] = "RLIMIT_NICE",
++ [RLIMIT_RTPRIO] = "RLIMIT_RTPRIO",
++ [RLIMIT_RTTIME] = "RLIMIT_RTTIME",
++ [GR_CRASH_RES] = "RLIMIT_CRASH"
++};
++
++void
++gr_log_resource(const struct task_struct *task,
++ const int res, const unsigned long wanted, const int gt)
++{
++ const struct cred *cred;
++ unsigned long rlim;
++
++ if (!gr_acl_is_enabled() && !grsec_resource_logging)
++ return;
++
++ // not yet supported resource
++ if (unlikely(!restab_log[res]))
++ return;
++
++ if (res == RLIMIT_CPU || res == RLIMIT_RTTIME)
++ rlim = task_rlimit_max(task, res);
++ else
++ rlim = task_rlimit(task, res);
++
++ if (likely((rlim == RLIM_INFINITY) || (gt && wanted <= rlim) || (!gt && wanted < rlim)))
++ return;
++
++ rcu_read_lock();
++ cred = __task_cred(task);
++
++ if (res == RLIMIT_NPROC &&
++ (cap_raised(cred->cap_effective, CAP_SYS_ADMIN) ||
++ cap_raised(cred->cap_effective, CAP_SYS_RESOURCE)))
++ goto out_rcu_unlock;
++ else if (res == RLIMIT_MEMLOCK &&
++ cap_raised(cred->cap_effective, CAP_IPC_LOCK))
++ goto out_rcu_unlock;
++ else if (res == RLIMIT_NICE && cap_raised(cred->cap_effective, CAP_SYS_NICE))
++ goto out_rcu_unlock;
++ rcu_read_unlock();
++
++ gr_log_res_ulong2_str(GR_DONT_AUDIT, GR_RESOURCE_MSG, task, wanted, restab_log[res], rlim);
++
++ return;
++out_rcu_unlock:
++ rcu_read_unlock();
++ return;
++}
+diff -urNp linux-2.6.38.7/grsecurity/gracl_segv.c linux-2.6.38.7/grsecurity/gracl_segv.c
+--- linux-2.6.38.7/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl_segv.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,300 @@
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <asm/uaccess.h>
++#include <asm/errno.h>
++#include <asm/mman.h>
++#include <net/sock.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++static struct crash_uid *uid_set;
++static unsigned short uid_used;
++static DEFINE_SPINLOCK(gr_uid_lock);
++extern rwlock_t gr_inode_lock;
++extern struct acl_subject_label *
++ lookup_acl_subj_label(const ino_t inode, const dev_t dev,
++ struct acl_role_label *role);
++
++#ifdef CONFIG_BTRFS_FS
++extern dev_t get_btrfs_dev_from_inode(struct inode *inode);
++extern int btrfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
++#endif
++
++static inline dev_t __get_dev(const struct dentry *dentry)
++{
++#ifdef CONFIG_BTRFS_FS
++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->getattr == &btrfs_getattr)
++ return get_btrfs_dev_from_inode(dentry->d_inode);
++ else
++#endif
++ return dentry->d_inode->i_sb->s_dev;
++}
++
++int
++gr_init_uidset(void)
++{
++ uid_set =
++ kmalloc(GR_UIDTABLE_MAX * sizeof (struct crash_uid), GFP_KERNEL);
++ uid_used = 0;
++
++ return uid_set ? 1 : 0;
++}
++
++void
++gr_free_uidset(void)
++{
++ if (uid_set)
++ kfree(uid_set);
++
++ return;
++}
++
++int
++gr_find_uid(const uid_t uid)
++{
++ struct crash_uid *tmp = uid_set;
++ uid_t buid;
++ int low = 0, high = uid_used - 1, mid;
++
++ while (high >= low) {
++ mid = (low + high) >> 1;
++ buid = tmp[mid].uid;
++ if (buid == uid)
++ return mid;
++ if (buid > uid)
++ high = mid - 1;
++ if (buid < uid)
++ low = mid + 1;
++ }
++
++ return -1;
++}
++
++static __inline__ void
++gr_insertsort(void)
++{
++ unsigned short i, j;
++ struct crash_uid index;
++
++ for (i = 1; i < uid_used; i++) {
++ index = uid_set[i];
++ j = i;
++ while ((j > 0) && uid_set[j - 1].uid > index.uid) {
++ uid_set[j] = uid_set[j - 1];
++ j--;
++ }
++ uid_set[j] = index;
++ }
++
++ return;
++}
++
++static __inline__ void
++gr_insert_uid(const uid_t uid, const unsigned long expires)
++{
++ int loc;
++
++ if (uid_used == GR_UIDTABLE_MAX)
++ return;
++
++ loc = gr_find_uid(uid);
++
++ if (loc >= 0) {
++ uid_set[loc].expires = expires;
++ return;
++ }
++
++ uid_set[uid_used].uid = uid;
++ uid_set[uid_used].expires = expires;
++ uid_used++;
++
++ gr_insertsort();
++
++ return;
++}
++
++void
++gr_remove_uid(const unsigned short loc)
++{
++ unsigned short i;
++
++ for (i = loc + 1; i < uid_used; i++)
++ uid_set[i - 1] = uid_set[i];
++
++ uid_used--;
++
++ return;
++}
++
++int
++gr_check_crash_uid(const uid_t uid)
++{
++ int loc;
++ int ret = 0;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return 0;
++
++ spin_lock(&gr_uid_lock);
++ loc = gr_find_uid(uid);
++
++ if (loc < 0)
++ goto out_unlock;
++
++ if (time_before_eq(uid_set[loc].expires, get_seconds()))
++ gr_remove_uid(loc);
++ else
++ ret = 1;
++
++out_unlock:
++ spin_unlock(&gr_uid_lock);
++ return ret;
++}
++
++static __inline__ int
++proc_is_setxid(const struct cred *cred)
++{
++ if (cred->uid != cred->euid || cred->uid != cred->suid ||
++ cred->uid != cred->fsuid)
++ return 1;
++ if (cred->gid != cred->egid || cred->gid != cred->sgid ||
++ cred->gid != cred->fsgid)
++ return 1;
++
++ return 0;
++}
++
++extern int gr_fake_force_sig(int sig, struct task_struct *t);
++
++void
++gr_handle_crash(struct task_struct *task, const int sig)
++{
++ struct acl_subject_label *curr;
++ struct acl_subject_label *curr2;
++ struct task_struct *tsk, *tsk2;
++ const struct cred *cred;
++ const struct cred *cred2;
++
++ if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL)
++ return;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return;
++
++ curr = task->acl;
++
++ if (!(curr->resmask & (1 << GR_CRASH_RES)))
++ return;
++
++ if (time_before_eq(curr->expires, get_seconds())) {
++ curr->expires = 0;
++ curr->crashes = 0;
++ }
++
++ curr->crashes++;
++
++ if (!curr->expires)
++ curr->expires = get_seconds() + curr->res[GR_CRASH_RES].rlim_max;
++
++ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
++ time_after(curr->expires, get_seconds())) {
++ rcu_read_lock();
++ cred = __task_cred(task);
++ if (cred->uid && proc_is_setxid(cred)) {
++ gr_log_crash1(GR_DONT_AUDIT, GR_SEGVSTART_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
++ spin_lock(&gr_uid_lock);
++ gr_insert_uid(cred->uid, curr->expires);
++ spin_unlock(&gr_uid_lock);
++ curr->expires = 0;
++ curr->crashes = 0;
++ read_lock(&tasklist_lock);
++ do_each_thread(tsk2, tsk) {
++ cred2 = __task_cred(tsk);
++ if (tsk != task && cred2->uid == cred->uid)
++ gr_fake_force_sig(SIGKILL, tsk);
++ } while_each_thread(tsk2, tsk);
++ read_unlock(&tasklist_lock);
++ } else {
++ gr_log_crash2(GR_DONT_AUDIT, GR_SEGVNOSUID_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
++ read_lock(&tasklist_lock);
++ do_each_thread(tsk2, tsk) {
++ if (likely(tsk != task)) {
++ curr2 = tsk->acl;
++
++ if (curr2->device == curr->device &&
++ curr2->inode == curr->inode)
++ gr_fake_force_sig(SIGKILL, tsk);
++ }
++ } while_each_thread(tsk2, tsk);
++ read_unlock(&tasklist_lock);
++ }
++ rcu_read_unlock();
++ }
++
++ return;
++}
++
++int
++gr_check_crash_exec(const struct file *filp)
++{
++ struct acl_subject_label *curr;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return 0;
++
++ read_lock(&gr_inode_lock);
++ curr = lookup_acl_subj_label(filp->f_path.dentry->d_inode->i_ino,
++ __get_dev(filp->f_path.dentry),
++ current->role);
++ read_unlock(&gr_inode_lock);
++
++ if (!curr || !(curr->resmask & (1 << GR_CRASH_RES)) ||
++ (!curr->crashes && !curr->expires))
++ return 0;
++
++ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
++ time_after(curr->expires, get_seconds()))
++ return 1;
++ else if (time_before_eq(curr->expires, get_seconds())) {
++ curr->crashes = 0;
++ curr->expires = 0;
++ }
++
++ return 0;
++}
++
++void
++gr_handle_alertkill(struct task_struct *task)
++{
++ struct acl_subject_label *curracl;
++ __u32 curr_ip;
++ struct task_struct *p, *p2;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return;
++
++ curracl = task->acl;
++ curr_ip = task->signal->curr_ip;
++
++ if ((curracl->mode & GR_KILLIPPROC) && curr_ip) {
++ read_lock(&tasklist_lock);
++ do_each_thread(p2, p) {
++ if (p->signal->curr_ip == curr_ip)
++ gr_fake_force_sig(SIGKILL, p);
++ } while_each_thread(p2, p);
++ read_unlock(&tasklist_lock);
++ } else if (curracl->mode & GR_KILLPROC)
++ gr_fake_force_sig(SIGKILL, task);
++
++ return;
++}
+diff -urNp linux-2.6.38.7/grsecurity/gracl_shm.c linux-2.6.38.7/grsecurity/gracl_shm.c
+--- linux-2.6.38.7/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/gracl_shm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,40 @@
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/ipc.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime, const uid_t cuid, const int shmid)
++{
++ struct task_struct *task;
++
++ if (!gr_acl_is_enabled())
++ return 1;
++
++ rcu_read_lock();
++ read_lock(&tasklist_lock);
++
++ task = find_task_by_vpid(shm_cprid);
++
++ if (unlikely(!task))
++ task = find_task_by_vpid(shm_lapid);
++
++ if (unlikely(task && (time_before_eq((unsigned long)task->start_time.tv_sec, (unsigned long)shm_createtime) ||
++ (task->pid == shm_lapid)) &&
++ (task->acl->mode & GR_PROTSHM) &&
++ (task->acl != current->acl))) {
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++ gr_log_int3(GR_DONT_AUDIT, GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid);
++ return 0;
++ }
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++
++ return 1;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_chdir.c linux-2.6.38.7/grsecurity/grsec_chdir.c
+--- linux-2.6.38.7/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_chdir.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,19 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++void
++gr_log_chdir(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
++ if ((grsec_enable_chdir && grsec_enable_group &&
++ in_group_p(grsec_audit_gid)) || (grsec_enable_chdir &&
++ !grsec_enable_group)) {
++ gr_log_fs_generic(GR_DO_AUDIT, GR_CHDIR_AUDIT_MSG, dentry, mnt);
++ }
++#endif
++ return;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_chroot.c linux-2.6.38.7/grsecurity/grsec_chroot.c
+--- linux-2.6.38.7/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_chroot.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,355 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/types.h>
++#include <linux/pid_namespace.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++void gr_set_chroot_entries(struct task_struct *task, struct path *path)
++{
++#ifdef CONFIG_GRKERNSEC
++ if (task->pid > 1 && path->dentry != init_task.fs->root.dentry &&
++ path->dentry != task->nsproxy->mnt_ns->root->mnt_root)
++ task->gr_is_chrooted = 1;
++ else
++ task->gr_is_chrooted = 0;
++
++ task->gr_chroot_dentry = path->dentry;
++#endif
++ return;
++}
++
++void gr_clear_chroot_entries(struct task_struct *task)
++{
++#ifdef CONFIG_GRKERNSEC
++ task->gr_is_chrooted = 0;
++ task->gr_chroot_dentry = NULL;
++#endif
++ return;
++}
++
++int
++gr_handle_chroot_unix(struct pid *pid)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
++ struct task_struct *p;
++
++ if (unlikely(!grsec_enable_chroot_unix))
++ return 1;
++
++ if (likely(!proc_is_chrooted(current)))
++ return 1;
++
++ rcu_read_lock();
++ read_lock(&tasklist_lock);
++ p = pid_task(pid, PIDTYPE_PID);
++ if (unlikely(p && !have_same_root(current, p))) {
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++ gr_log_noargs(GR_DONT_AUDIT, GR_UNIX_CHROOT_MSG);
++ return 0;
++ }
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++#endif
++ return 1;
++}
++
++int
++gr_handle_chroot_nice(void)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
++ if (grsec_enable_chroot_nice && proc_is_chrooted(current)) {
++ gr_log_noargs(GR_DONT_AUDIT, GR_NICE_CHROOT_MSG);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_setpriority(struct task_struct *p, const int niceval)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
++ if (grsec_enable_chroot_nice && (niceval < task_nice(p))
++ && proc_is_chrooted(current)) {
++ gr_log_str_int(GR_DONT_AUDIT, GR_PRIORITY_CHROOT_MSG, p->comm, p->pid);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_rawio(const struct inode *inode)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ if (grsec_enable_chroot_caps && proc_is_chrooted(current) &&
++ inode && S_ISBLK(inode->i_mode) && !capable(CAP_SYS_RAWIO))
++ return 1;
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_fowner(struct pid *pid, enum pid_type type)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
++ struct task_struct *p;
++ int ret = 0;
++ if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || !pid)
++ return ret;
++
++ read_lock(&tasklist_lock);
++ do_each_pid_task(pid, type, p) {
++ if (!have_same_root(current, p)) {
++ ret = 1;
++ goto out;
++ }
++ } while_each_pid_task(pid, type, p);
++out:
++ read_unlock(&tasklist_lock);
++ return ret;
++#endif
++ return 0;
++}
++
++int
++gr_pid_is_chrooted(struct task_struct *p)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
++ if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || p == NULL)
++ return 0;
++
++ if ((p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) ||
++ !have_same_root(current, p)) {
++ return 1;
++ }
++#endif
++ return 0;
++}
++
++EXPORT_SYMBOL(gr_pid_is_chrooted);
++
++#if defined(CONFIG_GRKERNSEC_CHROOT_DOUBLE) || defined(CONFIG_GRKERNSEC_CHROOT_FCHDIR)
++int gr_is_outside_chroot(const struct dentry *u_dentry, const struct vfsmount *u_mnt)
++{
++ struct path path, currentroot;
++ int ret = 0;
++
++ path.dentry = (struct dentry *)u_dentry;
++ path.mnt = (struct vfsmount *)u_mnt;
++ get_fs_root(current->fs, &currentroot);
++ if (path_is_under(&path, &currentroot))
++ ret = 1;
++ path_put(&currentroot);
++
++ return ret;
++}
++#endif
++
++int
++gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
++ if (!grsec_enable_chroot_fchdir)
++ return 1;
++
++ if (!proc_is_chrooted(current))
++ return 1;
++ else if (!gr_is_outside_chroot(u_dentry, u_mnt)) {
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_FCHDIR_MSG, u_dentry, u_mnt);
++ return 0;
++ }
++#endif
++ return 1;
++}
++
++int
++gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
++ struct pid *pid = NULL;
++ time_t starttime;
++
++ if (unlikely(!grsec_enable_chroot_shmat))
++ return 1;
++
++ if (likely(!proc_is_chrooted(current)))
++ return 1;
++
++ rcu_read_lock();
++ read_lock(&tasklist_lock);
++
++ pid = find_vpid(shm_cprid);
++ if (pid) {
++ struct task_struct *p;
++ p = pid_task(pid, PIDTYPE_PID);
++ if (p == NULL)
++ goto unlock;
++ starttime = p->start_time.tv_sec;
++ if (unlikely(!have_same_root(current, p) &&
++ time_before_eq((unsigned long)starttime, (unsigned long)shm_createtime))) {
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
++ return 0;
++ }
++ } else {
++ pid = find_vpid(shm_lapid);
++ if (pid) {
++ struct task_struct *p;
++ p = pid_task(pid, PIDTYPE_PID);
++ if (p == NULL)
++ goto unlock;
++ if (unlikely(!have_same_root(current, p))) {
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
++ return 0;
++ }
++ }
++ }
++unlock:
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++#endif
++ return 1;
++}
++
++void
++gr_log_chroot_exec(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
++ if (grsec_enable_chroot_execlog && proc_is_chrooted(current))
++ gr_log_fs_generic(GR_DO_AUDIT, GR_EXEC_CHROOT_MSG, dentry, mnt);
++#endif
++ return;
++}
++
++int
++gr_handle_chroot_mknod(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int mode)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
++ if (grsec_enable_chroot_mknod && !S_ISFIFO(mode) && !S_ISREG(mode) &&
++ proc_is_chrooted(current)) {
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_MKNOD_CHROOT_MSG, dentry, mnt);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_mount(const struct dentry *dentry,
++ const struct vfsmount *mnt, const char *dev_name)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
++ if (grsec_enable_chroot_mount && proc_is_chrooted(current)) {
++ gr_log_str_fs(GR_DONT_AUDIT, GR_MOUNT_CHROOT_MSG, dev_name, dentry, mnt);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_pivot(void)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
++ if (grsec_enable_chroot_pivot && proc_is_chrooted(current)) {
++ gr_log_noargs(GR_DONT_AUDIT, GR_PIVOT_CHROOT_MSG);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_chroot(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
++ if (grsec_enable_chroot_double && proc_is_chrooted(current) &&
++ !gr_is_outside_chroot(dentry, mnt)) {
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_CHROOT_MSG, dentry, mnt);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_caps(struct path *path)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ if (grsec_enable_chroot_caps && current->pid > 1 && current->fs != NULL &&
++ (init_task.fs->root.dentry != path->dentry) &&
++ (current->nsproxy->mnt_ns->root->mnt_root != path->dentry)) {
++
++ kernel_cap_t chroot_caps = GR_CHROOT_CAPS;
++ const struct cred *old = current_cred();
++ struct cred *new = prepare_creds();
++ if (new == NULL)
++ return 1;
++
++ new->cap_permitted = cap_drop(old->cap_permitted,
++ chroot_caps);
++ new->cap_inheritable = cap_drop(old->cap_inheritable,
++ chroot_caps);
++ new->cap_effective = cap_drop(old->cap_effective,
++ chroot_caps);
++
++ commit_creds(new);
++
++ return 0;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_sysctl(const int op)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
++ if (grsec_enable_chroot_sysctl && (op & MAY_WRITE) &&
++ proc_is_chrooted(current))
++ return -EACCES;
++#endif
++ return 0;
++}
++
++void
++gr_handle_chroot_chdir(struct path *path)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
++ if (grsec_enable_chroot_chdir)
++ set_fs_pwd(current->fs, path);
++#endif
++ return;
++}
++
++int
++gr_handle_chroot_chmod(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int mode)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
++ /* allow chmod +s on directories, but not files */
++ if (grsec_enable_chroot_chmod && !S_ISDIR(dentry->d_inode->i_mode) &&
++ ((mode & S_ISUID) || ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) &&
++ proc_is_chrooted(current)) {
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHMOD_CHROOT_MSG, dentry, mnt);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_SECURITY
++EXPORT_SYMBOL(gr_handle_chroot_caps);
++#endif
+diff -urNp linux-2.6.38.7/grsecurity/grsec_disabled.c linux-2.6.38.7/grsecurity/grsec_disabled.c
+--- linux-2.6.38.7/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_disabled.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,447 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/kdev_t.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/sysctl.h>
++
++#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
++void
++pax_set_initial_flags(struct linux_binprm *bprm)
++{
++ return;
++}
++#endif
++
++#ifdef CONFIG_SYSCTL
++__u32
++gr_handle_sysctl(const struct ctl_table * table, const int op)
++{
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_TASKSTATS
++int gr_is_taskstats_denied(int pid)
++{
++ return 0;
++}
++#endif
++
++int
++gr_acl_is_enabled(void)
++{
++ return 0;
++}
++
++int
++gr_handle_rawio(const struct inode *inode)
++{
++ return 0;
++}
++
++void
++gr_acl_handle_psacct(struct task_struct *task, const long code)
++{
++ return;
++}
++
++int
++gr_handle_ptrace(struct task_struct *task, const long request)
++{
++ return 0;
++}
++
++int
++gr_handle_proc_ptrace(struct task_struct *task)
++{
++ return 0;
++}
++
++void
++gr_learn_resource(const struct task_struct *task,
++ const int res, const unsigned long wanted, const int gt)
++{
++ return;
++}
++
++int
++gr_set_acls(const int type)
++{
++ return 0;
++}
++
++int
++gr_check_hidden_task(const struct task_struct *tsk)
++{
++ return 0;
++}
++
++int
++gr_check_protected_task(const struct task_struct *task)
++{
++ return 0;
++}
++
++int
++gr_check_protected_task_fowner(struct pid *pid, enum pid_type type)
++{
++ return 0;
++}
++
++void
++gr_copy_label(struct task_struct *tsk)
++{
++ return;
++}
++
++void
++gr_set_pax_flags(struct task_struct *task)
++{
++ return;
++}
++
++int
++gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt,
++ const int unsafe_share)
++{
++ return 0;
++}
++
++void
++gr_handle_delete(const ino_t ino, const dev_t dev)
++{
++ return;
++}
++
++void
++gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return;
++}
++
++void
++gr_handle_crash(struct task_struct *task, const int sig)
++{
++ return;
++}
++
++int
++gr_check_crash_exec(const struct file *filp)
++{
++ return 0;
++}
++
++int
++gr_check_crash_uid(const uid_t uid)
++{
++ return 0;
++}
++
++void
++gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
++ struct dentry *old_dentry,
++ struct dentry *new_dentry,
++ struct vfsmount *mnt, const __u8 replace)
++{
++ return;
++}
++
++int
++gr_search_socket(const int family, const int type, const int protocol)
++{
++ return 1;
++}
++
++int
++gr_search_connectbind(const int mode, const struct socket *sock,
++ const struct sockaddr_in *addr)
++{
++ return 0;
++}
++
++int
++gr_is_capable(const int cap)
++{
++ return 1;
++}
++
++int
++gr_is_capable_nolog(const int cap)
++{
++ return 1;
++}
++
++void
++gr_handle_alertkill(struct task_struct *task)
++{
++ return;
++}
++
++__u32
++gr_acl_handle_execve(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_hidden_file(const struct dentry * dentry,
++ const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
++ const int fmode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_unlink(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++int
++gr_acl_handle_mmap(const struct file *file, const unsigned long prot,
++ unsigned int *vm_flags)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_truncate(const struct dentry * dentry,
++ const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_utime(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_access(const struct dentry * dentry,
++ const struct vfsmount * mnt, const int fmode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_fchmod(const struct dentry * dentry, const struct vfsmount * mnt,
++ mode_t mode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_chmod(const struct dentry * dentry, const struct vfsmount * mnt,
++ mode_t mode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_chown(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_setxattr(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++void
++grsecurity_init(void)
++{
++ return;
++}
++
++__u32
++gr_acl_handle_mknod(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const int mode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_mkdir(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_symlink(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt, const char *from)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_link(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const struct dentry * old_dentry,
++ const struct vfsmount * old_mnt, const char *to)
++{
++ return 1;
++}
++
++int
++gr_acl_handle_rename(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const struct dentry *old_dentry,
++ const struct inode *old_parent_inode,
++ const struct vfsmount *old_mnt, const char *newname)
++{
++ return 0;
++}
++
++int
++gr_acl_handle_filldir(const struct file *file, const char *name,
++ const int namelen, const ino_t ino)
++{
++ return 1;
++}
++
++int
++gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime, const uid_t cuid, const int shmid)
++{
++ return 1;
++}
++
++int
++gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
++{
++ return 0;
++}
++
++int
++gr_search_accept(const struct socket *sock)
++{
++ return 0;
++}
++
++int
++gr_search_listen(const struct socket *sock)
++{
++ return 0;
++}
++
++int
++gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
++{
++ return 0;
++}
++
++__u32
++gr_acl_handle_unix(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_creat(const struct dentry * dentry,
++ const struct dentry * p_dentry,
++ const struct vfsmount * p_mnt, const int fmode,
++ const int imode)
++{
++ return 1;
++}
++
++void
++gr_acl_handle_exit(void)
++{
++ return;
++}
++
++int
++gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
++{
++ return 1;
++}
++
++void
++gr_set_role_label(const uid_t uid, const gid_t gid)
++{
++ return;
++}
++
++int
++gr_acl_handle_procpidmem(const struct task_struct *task)
++{
++ return 0;
++}
++
++int
++gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
++{
++ return 0;
++}
++
++int
++gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
++{
++ return 0;
++}
++
++void
++gr_set_kernel_label(struct task_struct *task)
++{
++ return;
++}
++
++int
++gr_check_user_change(int real, int effective, int fs)
++{
++ return 0;
++}
++
++int
++gr_check_group_change(int real, int effective, int fs)
++{
++ return 0;
++}
++
++int gr_acl_enable_at_secure(void)
++{
++ return 0;
++}
++
++dev_t gr_get_dev_from_dentry(struct dentry *dentry)
++{
++ return dentry->d_inode->i_sb->s_dev;
++}
++
++EXPORT_SYMBOL(gr_is_capable);
++EXPORT_SYMBOL(gr_is_capable_nolog);
++EXPORT_SYMBOL(gr_learn_resource);
++EXPORT_SYMBOL(gr_set_kernel_label);
++#ifdef CONFIG_SECURITY
++EXPORT_SYMBOL(gr_check_user_change);
++EXPORT_SYMBOL(gr_check_group_change);
++#endif
+diff -urNp linux-2.6.38.7/grsecurity/grsec_exec.c linux-2.6.38.7/grsecurity/grsec_exec.c
+--- linux-2.6.38.7/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_exec.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,147 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/binfmts.h>
++#include <linux/smp_lock.h>
++#include <linux/fs.h>
++#include <linux/types.h>
++#include <linux/grdefs.h>
++#include <linux/grinternal.h>
++#include <linux/capability.h>
++#include <linux/compat.h>
++
++#include <asm/uaccess.h>
++
++#ifdef CONFIG_GRKERNSEC_EXECLOG
++static char gr_exec_arg_buf[132];
++static DEFINE_MUTEX(gr_exec_arg_mutex);
++#endif
++
++int
++gr_handle_nproc(void)
++{
++#ifdef CONFIG_GRKERNSEC_EXECVE
++ const struct cred *cred = current_cred();
++ if (grsec_enable_execve && cred->user &&
++ (atomic_read(&cred->user->processes) > rlimit(RLIMIT_NPROC)) &&
++ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) {
++ gr_log_noargs(GR_DONT_AUDIT, GR_NPROC_MSG);
++ return -EAGAIN;
++ }
++#endif
++ return 0;
++}
++
++void
++gr_handle_exec_args(struct linux_binprm *bprm, const char __user *const __user *argv)
++{
++#ifdef CONFIG_GRKERNSEC_EXECLOG
++ char *grarg = gr_exec_arg_buf;
++ unsigned int i, x, execlen = 0;
++ char c;
++
++ if (!((grsec_enable_execlog && grsec_enable_group &&
++ in_group_p(grsec_audit_gid))
++ || (grsec_enable_execlog && !grsec_enable_group)))
++ return;
++
++ mutex_lock(&gr_exec_arg_mutex);
++ memset(grarg, 0, sizeof(gr_exec_arg_buf));
++
++ if (unlikely(argv == NULL))
++ goto log;
++
++ for (i = 0; i < bprm->argc && execlen < 128; i++) {
++ const char __user *p;
++ unsigned int len;
++
++ if (copy_from_user(&p, argv + i, sizeof(p)))
++ goto log;
++ if (!p)
++ goto log;
++ len = strnlen_user(p, 128 - execlen);
++ if (len > 128 - execlen)
++ len = 128 - execlen;
++ else if (len > 0)
++ len--;
++ if (copy_from_user(grarg + execlen, p, len))
++ goto log;
++
++ /* rewrite unprintable characters */
++ for (x = 0; x < len; x++) {
++ c = *(grarg + execlen + x);
++ if (c < 32 || c > 126)
++ *(grarg + execlen + x) = ' ';
++ }
++
++ execlen += len;
++ *(grarg + execlen) = ' ';
++ *(grarg + execlen + 1) = '\0';
++ execlen++;
++ }
++
++ log:
++ gr_log_fs_str(GR_DO_AUDIT, GR_EXEC_AUDIT_MSG, bprm->file->f_path.dentry,
++ bprm->file->f_path.mnt, grarg);
++ mutex_unlock(&gr_exec_arg_mutex);
++#endif
++ return;
++}
++
++#ifdef CONFIG_COMPAT
++void
++gr_handle_exec_args_compat(struct linux_binprm *bprm, compat_uptr_t __user *argv)
++{
++#ifdef CONFIG_GRKERNSEC_EXECLOG
++ char *grarg = gr_exec_arg_buf;
++ unsigned int i, x, execlen = 0;
++ char c;
++
++ if (!((grsec_enable_execlog && grsec_enable_group &&
++ in_group_p(grsec_audit_gid))
++ || (grsec_enable_execlog && !grsec_enable_group)))
++ return;
++
++ mutex_lock(&gr_exec_arg_mutex);
++ memset(grarg, 0, sizeof(gr_exec_arg_buf));
++
++ if (unlikely(argv == NULL))
++ goto log;
++
++ for (i = 0; i < bprm->argc && execlen < 128; i++) {
++ compat_uptr_t p;
++ unsigned int len;
++
++ if (get_user(p, argv + i))
++ goto log;
++ len = strnlen_user(compat_ptr(p), 128 - execlen);
++ if (len > 128 - execlen)
++ len = 128 - execlen;
++ else if (len > 0)
++ len--;
++ else
++ goto log;
++ if (copy_from_user(grarg + execlen, compat_ptr(p), len))
++ goto log;
++
++ /* rewrite unprintable characters */
++ for (x = 0; x < len; x++) {
++ c = *(grarg + execlen + x);
++ if (c < 32 || c > 126)
++ *(grarg + execlen + x) = ' ';
++ }
++
++ execlen += len;
++ *(grarg + execlen) = ' ';
++ *(grarg + execlen + 1) = '\0';
++ execlen++;
++ }
++
++ log:
++ gr_log_fs_str(GR_DO_AUDIT, GR_EXEC_AUDIT_MSG, bprm->file->f_path.dentry,
++ bprm->file->f_path.mnt, grarg);
++ mutex_unlock(&gr_exec_arg_mutex);
++#endif
++ return;
++}
++#endif
+diff -urNp linux-2.6.38.7/grsecurity/grsec_fifo.c linux-2.6.38.7/grsecurity/grsec_fifo.c
+--- linux-2.6.38.7/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_fifo.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,24 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_fifo(const struct dentry *dentry, const struct vfsmount *mnt,
++ const struct dentry *dir, const int flag, const int acc_mode)
++{
++#ifdef CONFIG_GRKERNSEC_FIFO
++ const struct cred *cred = current_cred();
++
++ if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) &&
++ !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) &&
++ (dentry->d_inode->i_uid != dir->d_inode->i_uid) &&
++ (cred->fsuid != dentry->d_inode->i_uid)) {
++ if (!inode_permission(dentry->d_inode, acc_mode))
++ gr_log_fs_int2(GR_DONT_AUDIT, GR_FIFO_MSG, dentry, mnt, dentry->d_inode->i_uid, dentry->d_inode->i_gid);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_fork.c linux-2.6.38.7/grsecurity/grsec_fork.c
+--- linux-2.6.38.7/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_fork.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,23 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++#include <linux/errno.h>
++
++void
++gr_log_forkfail(const int retval)
++{
++#ifdef CONFIG_GRKERNSEC_FORKFAIL
++ if (grsec_enable_forkfail && (retval == -EAGAIN || retval == -ENOMEM)) {
++ switch (retval) {
++ case -EAGAIN:
++ gr_log_str(GR_DONT_AUDIT, GR_FAILFORK_MSG, "EAGAIN");
++ break;
++ case -ENOMEM:
++ gr_log_str(GR_DONT_AUDIT, GR_FAILFORK_MSG, "ENOMEM");
++ break;
++ }
++ }
++#endif
++ return;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_init.c linux-2.6.38.7/grsecurity/grsec_init.c
+--- linux-2.6.38.7/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_init.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,270 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/smp_lock.h>
++#include <linux/gracl.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/percpu.h>
++#include <linux/module.h>
++
++int grsec_enable_link;
++int grsec_enable_dmesg;
++int grsec_enable_harden_ptrace;
++int grsec_enable_fifo;
++int grsec_enable_execve;
++int grsec_enable_execlog;
++int grsec_enable_signal;
++int grsec_enable_forkfail;
++int grsec_enable_audit_ptrace;
++int grsec_enable_time;
++int grsec_enable_audit_textrel;
++int grsec_enable_group;
++int grsec_audit_gid;
++int grsec_enable_chdir;
++int grsec_enable_mount;
++int grsec_enable_rofs;
++int grsec_enable_chroot_findtask;
++int grsec_enable_chroot_mount;
++int grsec_enable_chroot_shmat;
++int grsec_enable_chroot_fchdir;
++int grsec_enable_chroot_double;
++int grsec_enable_chroot_pivot;
++int grsec_enable_chroot_chdir;
++int grsec_enable_chroot_chmod;
++int grsec_enable_chroot_mknod;
++int grsec_enable_chroot_nice;
++int grsec_enable_chroot_execlog;
++int grsec_enable_chroot_caps;
++int grsec_enable_chroot_sysctl;
++int grsec_enable_chroot_unix;
++int grsec_enable_tpe;
++int grsec_tpe_gid;
++int grsec_enable_blackhole;
++#ifdef CONFIG_IPV6_MODULE
++EXPORT_SYMBOL(grsec_enable_blackhole);
++#endif
++int grsec_lastack_retries;
++int grsec_enable_tpe_all;
++int grsec_enable_tpe_invert;
++int grsec_enable_socket_all;
++int grsec_socket_all_gid;
++int grsec_enable_socket_client;
++int grsec_socket_client_gid;
++int grsec_enable_socket_server;
++int grsec_socket_server_gid;
++int grsec_resource_logging;
++int grsec_disable_privio;
++int grsec_enable_log_rwxmaps;
++int grsec_lock;
++
++DEFINE_SPINLOCK(grsec_alert_lock);
++unsigned long grsec_alert_wtime = 0;
++unsigned long grsec_alert_fyet = 0;
++
++DEFINE_SPINLOCK(grsec_audit_lock);
++
++DEFINE_RWLOCK(grsec_exec_file_lock);
++
++char *gr_shared_page[4];
++
++char *gr_alert_log_fmt;
++char *gr_audit_log_fmt;
++char *gr_alert_log_buf;
++char *gr_audit_log_buf;
++
++extern struct gr_arg *gr_usermode;
++extern unsigned char *gr_system_salt;
++extern unsigned char *gr_system_sum;
++
++void __init
++grsecurity_init(void)
++{
++ int j;
++ /* create the per-cpu shared pages */
++
++#ifdef CONFIG_X86
++ memset((char *)(0x41a + PAGE_OFFSET), 0, 36);
++#endif
++
++ for (j = 0; j < 4; j++) {
++ gr_shared_page[j] = (char *)__alloc_percpu(PAGE_SIZE, __alignof__(unsigned long long));
++ if (gr_shared_page[j] == NULL) {
++ panic("Unable to allocate grsecurity shared page");
++ return;
++ }
++ }
++
++ /* allocate log buffers */
++ gr_alert_log_fmt = kmalloc(512, GFP_KERNEL);
++ if (!gr_alert_log_fmt) {
++ panic("Unable to allocate grsecurity alert log format buffer");
++ return;
++ }
++ gr_audit_log_fmt = kmalloc(512, GFP_KERNEL);
++ if (!gr_audit_log_fmt) {
++ panic("Unable to allocate grsecurity audit log format buffer");
++ return;
++ }
++ gr_alert_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
++ if (!gr_alert_log_buf) {
++ panic("Unable to allocate grsecurity alert log buffer");
++ return;
++ }
++ gr_audit_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
++ if (!gr_audit_log_buf) {
++ panic("Unable to allocate grsecurity audit log buffer");
++ return;
++ }
++
++ /* allocate memory for authentication structure */
++ gr_usermode = kmalloc(sizeof(struct gr_arg), GFP_KERNEL);
++ gr_system_salt = kmalloc(GR_SALT_LEN, GFP_KERNEL);
++ gr_system_sum = kmalloc(GR_SHA_LEN, GFP_KERNEL);
++
++ if (!gr_usermode || !gr_system_salt || !gr_system_sum) {
++ panic("Unable to allocate grsecurity authentication structure");
++ return;
++ }
++
++
++#ifdef CONFIG_GRKERNSEC_IO
++#if !defined(CONFIG_GRKERNSEC_SYSCTL_DISTRO)
++ grsec_disable_privio = 1;
++#elif defined(CONFIG_GRKERNSEC_SYSCTL_ON)
++ grsec_disable_privio = 1;
++#else
++ grsec_disable_privio = 0;
++#endif
++#endif
++
++#ifdef CONFIG_GRKERNSEC_TPE_INVERT
++ /* for backward compatibility, tpe_invert always defaults to on if
++ enabled in the kernel
++ */
++ grsec_enable_tpe_invert = 1;
++#endif
++
++#if !defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_SYSCTL_ON)
++#ifndef CONFIG_GRKERNSEC_SYSCTL
++ grsec_lock = 1;
++#endif
++
++#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
++ grsec_enable_audit_textrel = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_RWXMAP_LOG
++ grsec_enable_log_rwxmaps = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
++ grsec_enable_group = 1;
++ grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID;
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
++ grsec_enable_chdir = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_HARDEN_PTRACE
++ grsec_enable_harden_ptrace = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ grsec_enable_mount = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_LINK
++ grsec_enable_link = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_DMESG
++ grsec_enable_dmesg = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ grsec_enable_blackhole = 1;
++ grsec_lastack_retries = 4;
++#endif
++#ifdef CONFIG_GRKERNSEC_FIFO
++ grsec_enable_fifo = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_EXECVE
++ grsec_enable_execve = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_EXECLOG
++ grsec_enable_execlog = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_SIGNAL
++ grsec_enable_signal = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_FORKFAIL
++ grsec_enable_forkfail = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_TIME
++ grsec_enable_time = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_RESLOG
++ grsec_resource_logging = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
++ grsec_enable_chroot_findtask = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
++ grsec_enable_chroot_unix = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
++ grsec_enable_chroot_mount = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
++ grsec_enable_chroot_fchdir = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
++ grsec_enable_chroot_shmat = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_PTRACE
++ grsec_enable_audit_ptrace = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
++ grsec_enable_chroot_double = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
++ grsec_enable_chroot_pivot = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
++ grsec_enable_chroot_chdir = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
++ grsec_enable_chroot_chmod = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
++ grsec_enable_chroot_mknod = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
++ grsec_enable_chroot_nice = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
++ grsec_enable_chroot_execlog = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ grsec_enable_chroot_caps = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
++ grsec_enable_chroot_sysctl = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_TPE
++ grsec_enable_tpe = 1;
++ grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID;
++#ifdef CONFIG_GRKERNSEC_TPE_ALL
++ grsec_enable_tpe_all = 1;
++#endif
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
++ grsec_enable_socket_all = 1;
++ grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID;
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
++ grsec_enable_socket_client = 1;
++ grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID;
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
++ grsec_enable_socket_server = 1;
++ grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID;
++#endif
++#endif
++
++ return;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_link.c linux-2.6.38.7/grsecurity/grsec_link.c
+--- linux-2.6.38.7/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_link.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,43 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_follow_link(const struct inode *parent,
++ const struct inode *inode,
++ const struct dentry *dentry, const struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_LINK
++ const struct cred *cred = current_cred();
++
++ if (grsec_enable_link && S_ISLNK(inode->i_mode) &&
++ (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) &&
++ (parent->i_mode & S_IWOTH) && (cred->fsuid != inode->i_uid)) {
++ gr_log_fs_int2(GR_DONT_AUDIT, GR_SYMLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_hardlink(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ struct inode *inode, const int mode, const char *to)
++{
++#ifdef CONFIG_GRKERNSEC_LINK
++ const struct cred *cred = current_cred();
++
++ if (grsec_enable_link && cred->fsuid != inode->i_uid &&
++ (!S_ISREG(mode) || (mode & S_ISUID) ||
++ ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
++ (inode_permission(inode, MAY_READ | MAY_WRITE))) &&
++ !capable(CAP_FOWNER) && cred->uid) {
++ gr_log_fs_int2_str(GR_DONT_AUDIT, GR_HARDLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid, to);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_log.c linux-2.6.38.7/grsecurity/grsec_log.c
+--- linux-2.6.38.7/grsecurity/grsec_log.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_log.c 2011-05-10 21:15:15.000000000 -0400
+@@ -0,0 +1,310 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/tty.h>
++#include <linux/fs.h>
++#include <linux/grinternal.h>
++
++#ifdef CONFIG_TREE_PREEMPT_RCU
++#define DISABLE_PREEMPT() preempt_disable()
++#define ENABLE_PREEMPT() preempt_enable()
++#else
++#define DISABLE_PREEMPT()
++#define ENABLE_PREEMPT()
++#endif
++
++#define BEGIN_LOCKS(x) \
++ DISABLE_PREEMPT(); \
++ rcu_read_lock(); \
++ read_lock(&tasklist_lock); \
++ read_lock(&grsec_exec_file_lock); \
++ if (x != GR_DO_AUDIT) \
++ spin_lock(&grsec_alert_lock); \
++ else \
++ spin_lock(&grsec_audit_lock)
++
++#define END_LOCKS(x) \
++ if (x != GR_DO_AUDIT) \
++ spin_unlock(&grsec_alert_lock); \
++ else \
++ spin_unlock(&grsec_audit_lock); \
++ read_unlock(&grsec_exec_file_lock); \
++ read_unlock(&tasklist_lock); \
++ rcu_read_unlock(); \
++ ENABLE_PREEMPT(); \
++ if (x == GR_DONT_AUDIT) \
++ gr_handle_alertkill(current)
++
++enum {
++ FLOODING,
++ NO_FLOODING
++};
++
++extern char *gr_alert_log_fmt;
++extern char *gr_audit_log_fmt;
++extern char *gr_alert_log_buf;
++extern char *gr_audit_log_buf;
++
++static int gr_log_start(int audit)
++{
++ char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT;
++ char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt;
++ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
++
++ if (audit == GR_DO_AUDIT)
++ goto set_fmt;
++
++ if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) {
++ grsec_alert_wtime = jiffies;
++ grsec_alert_fyet = 0;
++ } else if ((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) {
++ grsec_alert_fyet++;
++ } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) {
++ grsec_alert_wtime = jiffies;
++ grsec_alert_fyet++;
++ printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME);
++ return FLOODING;
++ } else return FLOODING;
++
++set_fmt:
++ memset(buf, 0, PAGE_SIZE);
++ if (current->signal->curr_ip && gr_acl_is_enabled()) {
++ sprintf(fmt, "%s%s", loglevel, "grsec: From %pI4: (%.64s:%c:%.950s) ");
++ snprintf(buf, PAGE_SIZE - 1, fmt, &current->signal->curr_ip, current->role->rolename, gr_roletype_to_char(), current->acl->filename);
++ } else if (current->signal->curr_ip) {
++ sprintf(fmt, "%s%s", loglevel, "grsec: From %pI4: ");
++ snprintf(buf, PAGE_SIZE - 1, fmt, &current->signal->curr_ip);
++ } else if (gr_acl_is_enabled()) {
++ sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) ");
++ snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename);
++ } else {
++ sprintf(fmt, "%s%s", loglevel, "grsec: ");
++ strcpy(buf, fmt);
++ }
++
++ return NO_FLOODING;
++}
++
++static void gr_log_middle(int audit, const char *msg, va_list ap)
++ __attribute__ ((format (printf, 2, 0)));
++
++static void gr_log_middle(int audit, const char *msg, va_list ap)
++{
++ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
++ unsigned int len = strlen(buf);
++
++ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
++
++ return;
++}
++
++static void gr_log_middle_varargs(int audit, const char *msg, ...)
++ __attribute__ ((format (printf, 2, 3)));
++
++static void gr_log_middle_varargs(int audit, const char *msg, ...)
++{
++ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
++ unsigned int len = strlen(buf);
++ va_list ap;
++
++ va_start(ap, msg);
++ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
++ va_end(ap);
++
++ return;
++}
++
++static void gr_log_end(int audit)
++{
++ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
++ unsigned int len = strlen(buf);
++
++ snprintf(buf + len, PAGE_SIZE - len - 1, DEFAULTSECMSG, DEFAULTSECARGS(current, current_cred(), __task_cred(current->real_parent)));
++ printk("%s\n", buf);
++
++ return;
++}
++
++void gr_log_varargs(int audit, const char *msg, int argtypes, ...)
++{
++ int logtype;
++ char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied";
++ char *str1 = NULL, *str2 = NULL, *str3 = NULL;
++ void *voidptr = NULL;
++ int num1 = 0, num2 = 0;
++ unsigned long ulong1 = 0, ulong2 = 0;
++ struct dentry *dentry = NULL;
++ struct vfsmount *mnt = NULL;
++ struct file *file = NULL;
++ struct task_struct *task = NULL;
++ const struct cred *cred, *pcred;
++ va_list ap;
++
++ BEGIN_LOCKS(audit);
++ logtype = gr_log_start(audit);
++ if (logtype == FLOODING) {
++ END_LOCKS(audit);
++ return;
++ }
++ va_start(ap, argtypes);
++ switch (argtypes) {
++ case GR_TTYSNIFF:
++ task = va_arg(ap, struct task_struct *);
++ gr_log_middle_varargs(audit, msg, &task->signal->curr_ip, gr_task_fullpath0(task), task->comm, task->pid, gr_parent_task_fullpath0(task), task->real_parent->comm, task->real_parent->pid);
++ break;
++ case GR_SYSCTL_HIDDEN:
++ str1 = va_arg(ap, char *);
++ gr_log_middle_varargs(audit, msg, result, str1);
++ break;
++ case GR_RBAC:
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt));
++ break;
++ case GR_RBAC_STR:
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ str1 = va_arg(ap, char *);
++ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1);
++ break;
++ case GR_STR_RBAC:
++ str1 = va_arg(ap, char *);
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ gr_log_middle_varargs(audit, msg, result, str1, gr_to_filename(dentry, mnt));
++ break;
++ case GR_RBAC_MODE2:
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ str1 = va_arg(ap, char *);
++ str2 = va_arg(ap, char *);
++ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2);
++ break;
++ case GR_RBAC_MODE3:
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ str1 = va_arg(ap, char *);
++ str2 = va_arg(ap, char *);
++ str3 = va_arg(ap, char *);
++ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2, str3);
++ break;
++ case GR_FILENAME:
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt));
++ break;
++ case GR_STR_FILENAME:
++ str1 = va_arg(ap, char *);
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ gr_log_middle_varargs(audit, msg, str1, gr_to_filename(dentry, mnt));
++ break;
++ case GR_FILENAME_STR:
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ str1 = va_arg(ap, char *);
++ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), str1);
++ break;
++ case GR_FILENAME_TWO_INT:
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ num1 = va_arg(ap, int);
++ num2 = va_arg(ap, int);
++ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2);
++ break;
++ case GR_FILENAME_TWO_INT_STR:
++ dentry = va_arg(ap, struct dentry *);
++ mnt = va_arg(ap, struct vfsmount *);
++ num1 = va_arg(ap, int);
++ num2 = va_arg(ap, int);
++ str1 = va_arg(ap, char *);
++ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2, str1);
++ break;
++ case GR_TEXTREL:
++ file = va_arg(ap, struct file *);
++ ulong1 = va_arg(ap, unsigned long);
++ ulong2 = va_arg(ap, unsigned long);
++ gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_path.dentry, file->f_path.mnt) : "<anonymous mapping>", ulong1, ulong2);
++ break;
++ case GR_PTRACE:
++ task = va_arg(ap, struct task_struct *);
++ gr_log_middle_varargs(audit, msg, task->exec_file ? gr_to_filename(task->exec_file->f_path.dentry, task->exec_file->f_path.mnt) : "(none)", task->comm, task->pid);
++ break;
++ case GR_RESOURCE:
++ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->real_parent);
++ ulong1 = va_arg(ap, unsigned long);
++ str1 = va_arg(ap, char *);
++ ulong2 = va_arg(ap, unsigned long);
++ gr_log_middle_varargs(audit, msg, ulong1, str1, ulong2, gr_task_fullpath(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath(task), task->real_parent->comm, task->real_parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid);
++ break;
++ case GR_CAP:
++ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->real_parent);
++ str1 = va_arg(ap, char *);
++ gr_log_middle_varargs(audit, msg, str1, gr_task_fullpath(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath(task), task->real_parent->comm, task->real_parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid);
++ break;
++ case GR_SIG:
++ str1 = va_arg(ap, char *);
++ voidptr = va_arg(ap, void *);
++ gr_log_middle_varargs(audit, msg, str1, voidptr);
++ break;
++ case GR_SIG2:
++ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->real_parent);
++ num1 = va_arg(ap, int);
++ gr_log_middle_varargs(audit, msg, num1, gr_task_fullpath0(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath0(task), task->real_parent->comm, task->real_parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid);
++ break;
++ case GR_CRASH1:
++ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->real_parent);
++ ulong1 = va_arg(ap, unsigned long);
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath(task), task->real_parent->comm, task->real_parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid, cred->uid, ulong1);
++ break;
++ case GR_CRASH2:
++ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->real_parent);
++ ulong1 = va_arg(ap, unsigned long);
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath(task), task->real_parent->comm, task->real_parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid, ulong1);
++ break;
++ case GR_RWXMAP:
++ file = va_arg(ap, struct file *);
++ gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_path.dentry, file->f_path.mnt) : "<anonymous mapping>");
++ break;
++ case GR_PSACCT:
++ {
++ unsigned int wday, cday;
++ __u8 whr, chr;
++ __u8 wmin, cmin;
++ __u8 wsec, csec;
++ char cur_tty[64] = { 0 };
++ char parent_tty[64] = { 0 };
++
++ task = va_arg(ap, struct task_struct *);
++ wday = va_arg(ap, unsigned int);
++ cday = va_arg(ap, unsigned int);
++ whr = va_arg(ap, int);
++ chr = va_arg(ap, int);
++ wmin = va_arg(ap, int);
++ cmin = va_arg(ap, int);
++ wsec = va_arg(ap, int);
++ csec = va_arg(ap, int);
++ ulong1 = va_arg(ap, unsigned long);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->real_parent);
++
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, &task->signal->curr_ip, tty_name(task->signal->tty, cur_tty), cred->uid, cred->euid, cred->gid, cred->egid, wday, whr, wmin, wsec, cday, chr, cmin, csec, (task->flags & PF_SIGNALED) ? "killed by signal" : "exited", ulong1, gr_parent_task_fullpath(task), task->real_parent->comm, task->real_parent->pid, &task->real_parent->signal->curr_ip, tty_name(task->real_parent->signal->tty, parent_tty), pcred->uid, pcred->euid, pcred->gid, pcred->egid);
++ }
++ break;
++ default:
++ gr_log_middle(audit, msg, ap);
++ }
++ va_end(ap);
++ gr_log_end(audit);
++ END_LOCKS(audit);
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_mem.c linux-2.6.38.7/grsecurity/grsec_mem.c
+--- linux-2.6.38.7/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_mem.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,33 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include <linux/grinternal.h>
++
++void
++gr_handle_ioperm(void)
++{
++ gr_log_noargs(GR_DONT_AUDIT, GR_IOPERM_MSG);
++ return;
++}
++
++void
++gr_handle_iopl(void)
++{
++ gr_log_noargs(GR_DONT_AUDIT, GR_IOPL_MSG);
++ return;
++}
++
++void
++gr_handle_mem_readwrite(u64 from, u64 to)
++{
++ gr_log_two_u64(GR_DONT_AUDIT, GR_MEM_READWRITE_MSG, from, to);
++ return;
++}
++
++void
++gr_handle_vm86(void)
++{
++ gr_log_noargs(GR_DONT_AUDIT, GR_VM86_MSG);
++ return;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_mount.c linux-2.6.38.7/grsecurity/grsec_mount.c
+--- linux-2.6.38.7/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_mount.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,62 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mount.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++void
++gr_log_remount(const char *devname, const int retval)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ if (grsec_enable_mount && (retval >= 0))
++ gr_log_str(GR_DO_AUDIT, GR_REMOUNT_AUDIT_MSG, devname ? devname : "none");
++#endif
++ return;
++}
++
++void
++gr_log_unmount(const char *devname, const int retval)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ if (grsec_enable_mount && (retval >= 0))
++ gr_log_str(GR_DO_AUDIT, GR_UNMOUNT_AUDIT_MSG, devname ? devname : "none");
++#endif
++ return;
++}
++
++void
++gr_log_mount(const char *from, const char *to, const int retval)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ if (grsec_enable_mount && (retval >= 0))
++ gr_log_str_str(GR_DO_AUDIT, GR_MOUNT_AUDIT_MSG, from, to);
++#endif
++ return;
++}
++
++int
++gr_handle_rofs_mount(struct dentry *dentry, struct vfsmount *mnt, int mnt_flags)
++{
++#ifdef CONFIG_GRKERNSEC_ROFS
++ if (grsec_enable_rofs && !(mnt_flags & MNT_READONLY)) {
++ gr_log_fs_generic(GR_DO_AUDIT, GR_ROFS_MOUNT_MSG, dentry, mnt);
++ return -EPERM;
++ } else
++ return 0;
++#endif
++ return 0;
++}
++
++int
++gr_handle_rofs_blockwrite(struct dentry *dentry, struct vfsmount *mnt, int acc_mode)
++{
++#ifdef CONFIG_GRKERNSEC_ROFS
++ if (grsec_enable_rofs && (acc_mode & MAY_WRITE) &&
++ dentry->d_inode && S_ISBLK(dentry->d_inode->i_mode)) {
++ gr_log_fs_generic(GR_DO_AUDIT, GR_ROFS_BLOCKWRITE_MSG, dentry, mnt);
++ return -EPERM;
++ } else
++ return 0;
++#endif
++ return 0;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_pax.c linux-2.6.38.7/grsecurity/grsec_pax.c
+--- linux-2.6.38.7/grsecurity/grsec_pax.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_pax.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,36 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/file.h>
++#include <linux/grinternal.h>
++#include <linux/grsecurity.h>
++
++void
++gr_log_textrel(struct vm_area_struct * vma)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
++ if (grsec_enable_audit_textrel)
++ gr_log_textrel_ulong_ulong(GR_DO_AUDIT, GR_TEXTREL_AUDIT_MSG, vma->vm_file, vma->vm_start, vma->vm_pgoff);
++#endif
++ return;
++}
++
++void
++gr_log_rwxmmap(struct file *file)
++{
++#ifdef CONFIG_GRKERNSEC_RWXMAP_LOG
++ if (grsec_enable_log_rwxmaps)
++ gr_log_rwxmap(GR_DONT_AUDIT, GR_RWXMMAP_MSG, file);
++#endif
++ return;
++}
++
++void
++gr_log_rwxmprotect(struct file *file)
++{
++#ifdef CONFIG_GRKERNSEC_RWXMAP_LOG
++ if (grsec_enable_log_rwxmaps)
++ gr_log_rwxmap(GR_DONT_AUDIT, GR_RWXMPROTECT_MSG, file);
++#endif
++ return;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_ptrace.c linux-2.6.38.7/grsecurity/grsec_ptrace.c
+--- linux-2.6.38.7/grsecurity/grsec_ptrace.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_ptrace.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,14 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/grinternal.h>
++#include <linux/grsecurity.h>
++
++void
++gr_audit_ptrace(struct task_struct *task)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_PTRACE
++ if (grsec_enable_audit_ptrace)
++ gr_log_ptrace(GR_DO_AUDIT, GR_PTRACE_AUDIT_MSG, task);
++#endif
++ return;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_sig.c linux-2.6.38.7/grsecurity/grsec_sig.c
+--- linux-2.6.38.7/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_sig.c 2011-05-17 17:30:33.000000000 -0400
+@@ -0,0 +1,203 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++#include <linux/hardirq.h>
++
++char *signames[] = {
++ [SIGSEGV] = "Segmentation fault",
++ [SIGILL] = "Illegal instruction",
++ [SIGABRT] = "Abort",
++ [SIGBUS] = "Invalid alignment/Bus error"
++};
++
++void
++gr_log_signal(const int sig, const void *addr, const struct task_struct *t)
++{
++#ifdef CONFIG_GRKERNSEC_SIGNAL
++ if (grsec_enable_signal && ((sig == SIGSEGV) || (sig == SIGILL) ||
++ (sig == SIGABRT) || (sig == SIGBUS))) {
++ if (t->pid == current->pid) {
++ gr_log_sig_addr(GR_DONT_AUDIT_GOOD, GR_UNISIGLOG_MSG, signames[sig], addr);
++ } else {
++ gr_log_sig_task(GR_DONT_AUDIT_GOOD, GR_DUALSIGLOG_MSG, t, sig);
++ }
++ }
++#endif
++ return;
++}
++
++int
++gr_handle_signal(const struct task_struct *p, const int sig)
++{
++#ifdef CONFIG_GRKERNSEC
++ if (current->pid > 1 && gr_check_protected_task(p)) {
++ gr_log_sig_task(GR_DONT_AUDIT, GR_SIG_ACL_MSG, p, sig);
++ return -EPERM;
++ } else if (gr_pid_is_chrooted((struct task_struct *)p)) {
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_GRKERNSEC
++extern int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t);
++
++int gr_fake_force_sig(int sig, struct task_struct *t)
++{
++ unsigned long int flags;
++ int ret, blocked, ignored;
++ struct k_sigaction *action;
++
++ spin_lock_irqsave(&t->sighand->siglock, flags);
++ action = &t->sighand->action[sig-1];
++ ignored = action->sa.sa_handler == SIG_IGN;
++ blocked = sigismember(&t->blocked, sig);
++ if (blocked || ignored) {
++ action->sa.sa_handler = SIG_DFL;
++ if (blocked) {
++ sigdelset(&t->blocked, sig);
++ recalc_sigpending_and_wake(t);
++ }
++ }
++ if (action->sa.sa_handler == SIG_DFL)
++ t->signal->flags &= ~SIGNAL_UNKILLABLE;
++ ret = specific_send_sig_info(sig, SEND_SIG_PRIV, t);
++
++ spin_unlock_irqrestore(&t->sighand->siglock, flags);
++
++ return ret;
++}
++#endif
++
++#ifdef CONFIG_GRKERNSEC_BRUTE
++#define GR_USER_BAN_TIME (15 * 60)
++
++static int __get_dumpable(unsigned long mm_flags)
++{
++ int ret;
++
++ ret = mm_flags & MMF_DUMPABLE_MASK;
++ return (ret >= 2) ? 2 : ret;
++}
++#endif
++
++void gr_handle_brute_attach(struct task_struct *p, unsigned long mm_flags)
++{
++#ifdef CONFIG_GRKERNSEC_BRUTE
++ uid_t uid = 0;
++
++ rcu_read_lock();
++ read_lock(&tasklist_lock);
++ read_lock(&grsec_exec_file_lock);
++ if (p->real_parent && p->real_parent->exec_file == p->exec_file)
++ p->real_parent->brute = 1;
++ else {
++ const struct cred *cred = __task_cred(p), *cred2;
++ struct task_struct *tsk, *tsk2;
++
++ if (!__get_dumpable(mm_flags) && cred->uid) {
++ struct user_struct *user;
++
++ uid = cred->uid;
++
++ /* this is put upon execution past expiration */
++ user = find_user(uid);
++ if (user == NULL)
++ goto unlock;
++ user->banned = 1;
++ user->ban_expires = get_seconds() + GR_USER_BAN_TIME;
++ if (user->ban_expires == ~0UL)
++ user->ban_expires--;
++
++ do_each_thread(tsk2, tsk) {
++ cred2 = __task_cred(tsk);
++ if (tsk != p && cred2->uid == uid)
++ gr_fake_force_sig(SIGKILL, tsk);
++ } while_each_thread(tsk2, tsk);
++ }
++ }
++unlock:
++ read_unlock(&grsec_exec_file_lock);
++ read_unlock(&tasklist_lock);
++ rcu_read_unlock();
++
++ if (uid)
++ printk(KERN_ALERT "grsec: bruteforce prevention initiated against uid %u, banning for %d minutes\n", uid, GR_USER_BAN_TIME / 60);
++
++#endif
++ return;
++}
++
++void gr_handle_brute_check(void)
++{
++#ifdef CONFIG_GRKERNSEC_BRUTE
++ if (current->brute)
++ msleep(30 * 1000);
++#endif
++ return;
++}
++
++void gr_handle_kernel_exploit(void)
++{
++#ifdef CONFIG_GRKERNSEC_KERN_LOCKOUT
++ const struct cred *cred;
++ struct task_struct *tsk, *tsk2;
++ struct user_struct *user;
++ uid_t uid;
++
++ if (in_irq() || in_serving_softirq() || in_nmi())
++ panic("grsec: halting the system due to suspicious kernel crash caused in interrupt context");
++
++ uid = current_uid();
++
++ if (uid == 0)
++ panic("grsec: halting the system due to suspicious kernel crash caused by root");
++ else {
++ /* kill all the processes of this user, hold a reference
++ to their creds struct, and prevent them from creating
++ another process until system reset
++ */
++ printk(KERN_ALERT "grsec: banning user with uid %u until system restart for suspicious kernel crash\n", uid);
++ /* we intentionally leak this ref */
++ user = get_uid(current->cred->user);
++ if (user) {
++ user->banned = 1;
++ user->ban_expires = ~0UL;
++ }
++
++ read_lock(&tasklist_lock);
++ do_each_thread(tsk2, tsk) {
++ cred = __task_cred(tsk);
++ if (cred->uid == uid)
++ gr_fake_force_sig(SIGKILL, tsk);
++ } while_each_thread(tsk2, tsk);
++ read_unlock(&tasklist_lock);
++ }
++#endif
++}
++
++int __gr_process_user_ban(struct user_struct *user)
++{
++#if defined(CONFIG_GRKERNSEC_KERN_LOCKOUT) || defined(CONFIG_GRKERNSEC_BRUTE)
++ if (unlikely(user->banned)) {
++ if (user->ban_expires != ~0UL && time_after_eq(get_seconds(), user->ban_expires)) {
++ user->banned = 0;
++ user->ban_expires = 0;
++ free_uid(user);
++ } else
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int gr_process_user_ban(void)
++{
++#if defined(CONFIG_GRKERNSEC_KERN_LOCKOUT) || defined(CONFIG_GRKERNSEC_BRUTE)
++ return __gr_process_user_ban(current->cred->user);
++#endif
++ return 0;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_sock.c linux-2.6.38.7/grsecurity/grsec_sock.c
+--- linux-2.6.38.7/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_sock.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,275 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <net/sock.h>
++#include <net/inet_sock.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++#include <linux/gracl.h>
++
++kernel_cap_t gr_cap_rtnetlink(struct sock *sock);
++EXPORT_SYMBOL(gr_cap_rtnetlink);
++
++extern int gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb);
++extern int gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr);
++
++EXPORT_SYMBOL(gr_search_udp_recvmsg);
++EXPORT_SYMBOL(gr_search_udp_sendmsg);
++
++#ifdef CONFIG_UNIX_MODULE
++EXPORT_SYMBOL(gr_acl_handle_unix);
++EXPORT_SYMBOL(gr_acl_handle_mknod);
++EXPORT_SYMBOL(gr_handle_chroot_unix);
++EXPORT_SYMBOL(gr_handle_create);
++#endif
++
++#ifdef CONFIG_GRKERNSEC
++#define gr_conn_table_size 32749
++struct conn_table_entry {
++ struct conn_table_entry *next;
++ struct signal_struct *sig;
++};
++
++struct conn_table_entry *gr_conn_table[gr_conn_table_size];
++DEFINE_SPINLOCK(gr_conn_table_lock);
++
++extern const char * gr_socktype_to_name(unsigned char type);
++extern const char * gr_proto_to_name(unsigned char proto);
++extern const char * gr_sockfamily_to_name(unsigned char family);
++
++static __inline__ int
++conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size)
++{
++ return ((daddr + saddr + (sport << 8) + (dport << 16)) % size);
++}
++
++static __inline__ int
++conn_match(const struct signal_struct *sig, __u32 saddr, __u32 daddr,
++ __u16 sport, __u16 dport)
++{
++ if (unlikely(sig->gr_saddr == saddr && sig->gr_daddr == daddr &&
++ sig->gr_sport == sport && sig->gr_dport == dport))
++ return 1;
++ else
++ return 0;
++}
++
++static void gr_add_to_task_ip_table_nolock(struct signal_struct *sig, struct conn_table_entry *newent)
++{
++ struct conn_table_entry **match;
++ unsigned int index;
++
++ index = conn_hash(sig->gr_saddr, sig->gr_daddr,
++ sig->gr_sport, sig->gr_dport,
++ gr_conn_table_size);
++
++ newent->sig = sig;
++
++ match = &gr_conn_table[index];
++ newent->next = *match;
++ *match = newent;
++
++ return;
++}
++
++static void gr_del_task_from_ip_table_nolock(struct signal_struct *sig)
++{
++ struct conn_table_entry *match, *last = NULL;
++ unsigned int index;
++
++ index = conn_hash(sig->gr_saddr, sig->gr_daddr,
++ sig->gr_sport, sig->gr_dport,
++ gr_conn_table_size);
++
++ match = gr_conn_table[index];
++ while (match && !conn_match(match->sig,
++ sig->gr_saddr, sig->gr_daddr, sig->gr_sport,
++ sig->gr_dport)) {
++ last = match;
++ match = match->next;
++ }
++
++ if (match) {
++ if (last)
++ last->next = match->next;
++ else
++ gr_conn_table[index] = NULL;
++ kfree(match);
++ }
++
++ return;
++}
++
++static struct signal_struct * gr_lookup_task_ip_table(__u32 saddr, __u32 daddr,
++ __u16 sport, __u16 dport)
++{
++ struct conn_table_entry *match;
++ unsigned int index;
++
++ index = conn_hash(saddr, daddr, sport, dport, gr_conn_table_size);
++
++ match = gr_conn_table[index];
++ while (match && !conn_match(match->sig, saddr, daddr, sport, dport))
++ match = match->next;
++
++ if (match)
++ return match->sig;
++ else
++ return NULL;
++}
++
++#endif
++
++void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet)
++{
++#ifdef CONFIG_GRKERNSEC
++ struct signal_struct *sig = task->signal;
++ struct conn_table_entry *newent;
++
++ newent = kmalloc(sizeof(struct conn_table_entry), GFP_ATOMIC);
++ if (newent == NULL)
++ return;
++ /* no bh lock needed since we are called with bh disabled */
++ spin_lock(&gr_conn_table_lock);
++ gr_del_task_from_ip_table_nolock(sig);
++ sig->gr_saddr = inet->inet_rcv_saddr;
++ sig->gr_daddr = inet->inet_daddr;
++ sig->gr_sport = inet->inet_sport;
++ sig->gr_dport = inet->inet_dport;
++ gr_add_to_task_ip_table_nolock(sig, newent);
++ spin_unlock(&gr_conn_table_lock);
++#endif
++ return;
++}
++
++void gr_del_task_from_ip_table(struct task_struct *task)
++{
++#ifdef CONFIG_GRKERNSEC
++ spin_lock_bh(&gr_conn_table_lock);
++ gr_del_task_from_ip_table_nolock(task->signal);
++ spin_unlock_bh(&gr_conn_table_lock);
++#endif
++ return;
++}
++
++void
++gr_attach_curr_ip(const struct sock *sk)
++{
++#ifdef CONFIG_GRKERNSEC
++ struct signal_struct *p, *set;
++ const struct inet_sock *inet = inet_sk(sk);
++
++ if (unlikely(sk->sk_protocol != IPPROTO_TCP))
++ return;
++
++ set = current->signal;
++
++ spin_lock_bh(&gr_conn_table_lock);
++ p = gr_lookup_task_ip_table(inet->inet_daddr, inet->inet_rcv_saddr,
++ inet->inet_dport, inet->inet_sport);
++ if (unlikely(p != NULL)) {
++ set->curr_ip = p->curr_ip;
++ set->used_accept = 1;
++ gr_del_task_from_ip_table_nolock(p);
++ spin_unlock_bh(&gr_conn_table_lock);
++ return;
++ }
++ spin_unlock_bh(&gr_conn_table_lock);
++
++ set->curr_ip = inet->inet_daddr;
++ set->used_accept = 1;
++#endif
++ return;
++}
++
++int
++gr_handle_sock_all(const int family, const int type, const int protocol)
++{
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
++ if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) &&
++ (family != AF_UNIX)) {
++ if (family == AF_INET)
++ gr_log_str3(GR_DONT_AUDIT, GR_SOCK_MSG, gr_sockfamily_to_name(family), gr_socktype_to_name(type), gr_proto_to_name(protocol));
++ else
++ gr_log_str2_int(GR_DONT_AUDIT, GR_SOCK_NOINET_MSG, gr_sockfamily_to_name(family), gr_socktype_to_name(type), protocol);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_sock_server(const struct sockaddr *sck)
++{
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
++ if (grsec_enable_socket_server &&
++ in_group_p(grsec_socket_server_gid) &&
++ sck && (sck->sa_family != AF_UNIX) &&
++ (sck->sa_family != AF_LOCAL)) {
++ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_sock_server_other(const struct sock *sck)
++{
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
++ if (grsec_enable_socket_server &&
++ in_group_p(grsec_socket_server_gid) &&
++ sck && (sck->sk_family != AF_UNIX) &&
++ (sck->sk_family != AF_LOCAL)) {
++ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_sock_client(const struct sockaddr *sck)
++{
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
++ if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) &&
++ sck && (sck->sa_family != AF_UNIX) &&
++ (sck->sa_family != AF_LOCAL)) {
++ gr_log_noargs(GR_DONT_AUDIT, GR_CONNECT_MSG);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++kernel_cap_t
++gr_cap_rtnetlink(struct sock *sock)
++{
++#ifdef CONFIG_GRKERNSEC
++ if (!gr_acl_is_enabled())
++ return current_cap();
++ else if (sock->sk_protocol == NETLINK_ISCSI &&
++ cap_raised(current_cap(), CAP_SYS_ADMIN) &&
++ gr_is_capable(CAP_SYS_ADMIN))
++ return current_cap();
++ else if (sock->sk_protocol == NETLINK_AUDIT &&
++ cap_raised(current_cap(), CAP_AUDIT_WRITE) &&
++ gr_is_capable(CAP_AUDIT_WRITE) &&
++ cap_raised(current_cap(), CAP_AUDIT_CONTROL) &&
++ gr_is_capable(CAP_AUDIT_CONTROL))
++ return current_cap();
++ else if (cap_raised(current_cap(), CAP_NET_ADMIN) &&
++ ((sock->sk_protocol == NETLINK_ROUTE) ?
++ gr_is_capable_nolog(CAP_NET_ADMIN) :
++ gr_is_capable(CAP_NET_ADMIN)))
++ return current_cap();
++ else
++ return __cap_empty_set;
++#else
++ return current_cap();
++#endif
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsec_sysctl.c linux-2.6.38.7/grsecurity/grsec_sysctl.c
+--- linux-2.6.38.7/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_sysctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,433 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/sysctl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_sysctl_mod(const char *dirname, const char *name, const int op)
++{
++#ifdef CONFIG_GRKERNSEC_SYSCTL
++ if (!strcmp(dirname, "grsecurity") && grsec_lock && (op & MAY_WRITE)) {
++ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_GRKERNSEC_ROFS
++static int __maybe_unused one = 1;
++#endif
++
++#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_ROFS)
++struct ctl_table grsecurity_table[] = {
++#ifdef CONFIG_GRKERNSEC_SYSCTL
++#ifdef CONFIG_GRKERNSEC_SYSCTL_DISTRO
++#ifdef CONFIG_GRKERNSEC_IO
++ {
++ .procname = "disable_priv_io",
++ .data = &grsec_disable_privio,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#endif
++#ifdef CONFIG_GRKERNSEC_LINK
++ {
++ .procname = "linking_restrictions",
++ .data = &grsec_enable_link,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_FIFO
++ {
++ .procname = "fifo_restrictions",
++ .data = &grsec_enable_fifo,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_EXECVE
++ {
++ .procname = "execve_limiting",
++ .data = &grsec_enable_execve,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ {
++ .procname = "ip_blackhole",
++ .data = &grsec_enable_blackhole,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .procname = "lastack_retries",
++ .data = &grsec_lastack_retries,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_EXECLOG
++ {
++ .procname = "exec_logging",
++ .data = &grsec_enable_execlog,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_RWXMAP_LOG
++ {
++ .procname = "rwxmap_logging",
++ .data = &grsec_enable_log_rwxmaps,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_SIGNAL
++ {
++ .procname = "signal_logging",
++ .data = &grsec_enable_signal,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_FORKFAIL
++ {
++ .procname = "forkfail_logging",
++ .data = &grsec_enable_forkfail,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_TIME
++ {
++ .procname = "timechange_logging",
++ .data = &grsec_enable_time,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
++ {
++ .procname = "chroot_deny_shmat",
++ .data = &grsec_enable_chroot_shmat,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
++ {
++ .procname = "chroot_deny_unix",
++ .data = &grsec_enable_chroot_unix,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
++ {
++ .procname = "chroot_deny_mount",
++ .data = &grsec_enable_chroot_mount,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
++ {
++ .procname = "chroot_deny_fchdir",
++ .data = &grsec_enable_chroot_fchdir,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
++ {
++ .procname = "chroot_deny_chroot",
++ .data = &grsec_enable_chroot_double,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
++ {
++ .procname = "chroot_deny_pivot",
++ .data = &grsec_enable_chroot_pivot,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
++ {
++ .procname = "chroot_enforce_chdir",
++ .data = &grsec_enable_chroot_chdir,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
++ {
++ .procname = "chroot_deny_chmod",
++ .data = &grsec_enable_chroot_chmod,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
++ {
++ .procname = "chroot_deny_mknod",
++ .data = &grsec_enable_chroot_mknod,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
++ {
++ .procname = "chroot_restrict_nice",
++ .data = &grsec_enable_chroot_nice,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
++ {
++ .procname = "chroot_execlog",
++ .data = &grsec_enable_chroot_execlog,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ {
++ .procname = "chroot_caps",
++ .data = &grsec_enable_chroot_caps,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
++ {
++ .procname = "chroot_deny_sysctl",
++ .data = &grsec_enable_chroot_sysctl,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_TPE
++ {
++ .procname = "tpe",
++ .data = &grsec_enable_tpe,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .procname = "tpe_gid",
++ .data = &grsec_tpe_gid,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_TPE_INVERT
++ {
++ .procname = "tpe_invert",
++ .data = &grsec_enable_tpe_invert,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_TPE_ALL
++ {
++ .procname = "tpe_restrict_all",
++ .data = &grsec_enable_tpe_all,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
++ {
++ .procname = "socket_all",
++ .data = &grsec_enable_socket_all,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .procname = "socket_all_gid",
++ .data = &grsec_socket_all_gid,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
++ {
++ .procname = "socket_client",
++ .data = &grsec_enable_socket_client,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .procname = "socket_client_gid",
++ .data = &grsec_socket_client_gid,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
++ {
++ .procname = "socket_server",
++ .data = &grsec_enable_socket_server,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .procname = "socket_server_gid",
++ .data = &grsec_socket_server_gid,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
++ {
++ .procname = "audit_group",
++ .data = &grsec_enable_group,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++ {
++ .procname = "audit_gid",
++ .data = &grsec_audit_gid,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
++ {
++ .procname = "audit_chdir",
++ .data = &grsec_enable_chdir,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ {
++ .procname = "audit_mount",
++ .data = &grsec_enable_mount,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
++ {
++ .procname = "audit_textrel",
++ .data = &grsec_enable_audit_textrel,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_DMESG
++ {
++ .procname = "dmesg",
++ .data = &grsec_enable_dmesg,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
++ {
++ .procname = "chroot_findtask",
++ .data = &grsec_enable_chroot_findtask,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_RESLOG
++ {
++ .procname = "resource_logging",
++ .data = &grsec_resource_logging,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_PTRACE
++ {
++ .procname = "audit_ptrace",
++ .data = &grsec_enable_audit_ptrace,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_HARDEN_PTRACE
++ {
++ .procname = "harden_ptrace",
++ .data = &grsec_enable_harden_ptrace,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++ {
++ .procname = "grsec_lock",
++ .data = &grsec_lock,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
++#ifdef CONFIG_GRKERNSEC_ROFS
++ {
++ .procname = "romount_protect",
++ .data = &grsec_enable_rofs,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec_minmax,
++ .extra1 = &one,
++ .extra2 = &one,
++ },
++#endif
++ { }
++};
++#endif
+diff -urNp linux-2.6.38.7/grsecurity/grsec_time.c linux-2.6.38.7/grsecurity/grsec_time.c
+--- linux-2.6.38.7/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_time.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,16 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/grinternal.h>
++#include <linux/module.h>
++
++void
++gr_log_timechange(void)
++{
++#ifdef CONFIG_GRKERNSEC_TIME
++ if (grsec_enable_time)
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_TIME_MSG);
++#endif
++ return;
++}
++
++EXPORT_SYMBOL(gr_log_timechange);
+diff -urNp linux-2.6.38.7/grsecurity/grsec_tpe.c linux-2.6.38.7/grsecurity/grsec_tpe.c
+--- linux-2.6.38.7/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsec_tpe.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,39 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/grinternal.h>
++
++extern int gr_acl_tpe_check(void);
++
++int
++gr_tpe_allow(const struct file *file)
++{
++#ifdef CONFIG_GRKERNSEC
++ struct inode *inode = file->f_path.dentry->d_parent->d_inode;
++ const struct cred *cred = current_cred();
++
++ if (cred->uid && ((grsec_enable_tpe &&
++#ifdef CONFIG_GRKERNSEC_TPE_INVERT
++ ((grsec_enable_tpe_invert && !in_group_p(grsec_tpe_gid)) ||
++ (!grsec_enable_tpe_invert && in_group_p(grsec_tpe_gid)))
++#else
++ in_group_p(grsec_tpe_gid)
++#endif
++ ) || gr_acl_tpe_check()) &&
++ (inode->i_uid || (!inode->i_uid && ((inode->i_mode & S_IWGRP) ||
++ (inode->i_mode & S_IWOTH))))) {
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_path.dentry, file->f_path.mnt);
++ return 0;
++ }
++#ifdef CONFIG_GRKERNSEC_TPE_ALL
++ if (cred->uid && grsec_enable_tpe && grsec_enable_tpe_all &&
++ ((inode->i_uid && (inode->i_uid != cred->uid)) ||
++ (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) {
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_path.dentry, file->f_path.mnt);
++ return 0;
++ }
++#endif
++#endif
++ return 1;
++}
+diff -urNp linux-2.6.38.7/grsecurity/grsum.c linux-2.6.38.7/grsecurity/grsum.c
+--- linux-2.6.38.7/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/grsum.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,61 @@
++#include <linux/err.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/scatterlist.h>
++#include <linux/crypto.h>
++#include <linux/gracl.h>
++
++
++#if !defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) || !defined(CONFIG_CRYPTO_SHA256) || defined(CONFIG_CRYPTO_SHA256_MODULE)
++#error "crypto and sha256 must be built into the kernel"
++#endif
++
++int
++chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum)
++{
++ char *p;
++ struct crypto_hash *tfm;
++ struct hash_desc desc;
++ struct scatterlist sg;
++ unsigned char temp_sum[GR_SHA_LEN];
++ volatile int retval = 0;
++ volatile int dummy = 0;
++ unsigned int i;
++
++ sg_init_table(&sg, 1);
++
++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
++ if (IS_ERR(tfm)) {
++ /* should never happen, since sha256 should be built in */
++ return 1;
++ }
++
++ desc.tfm = tfm;
++ desc.flags = 0;
++
++ crypto_hash_init(&desc);
++
++ p = salt;
++ sg_set_buf(&sg, p, GR_SALT_LEN);
++ crypto_hash_update(&desc, &sg, sg.length);
++
++ p = entry->pw;
++ sg_set_buf(&sg, p, strlen(p));
++
++ crypto_hash_update(&desc, &sg, sg.length);
++
++ crypto_hash_final(&desc, temp_sum);
++
++ memset(entry->pw, 0, GR_PW_LEN);
++
++ for (i = 0; i < GR_SHA_LEN; i++)
++ if (sum[i] != temp_sum[i])
++ retval = 1;
++ else
++ dummy = 1; // waste a cycle
++
++ crypto_free_hash(tfm);
++
++ return retval;
++}
+diff -urNp linux-2.6.38.7/grsecurity/Kconfig linux-2.6.38.7/grsecurity/Kconfig
+--- linux-2.6.38.7/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/Kconfig 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,1045 @@
++#
++# grecurity configuration
++#
++
++menu "Grsecurity"
++
++config GRKERNSEC
++ bool "Grsecurity"
++ select CRYPTO
++ select CRYPTO_SHA256
++ help
++ If you say Y here, you will be able to configure many features
++ that will enhance the security of your system. It is highly
++ recommended that you say Y here and read through the help
++ for each option so that you fully understand the features and
++ can evaluate their usefulness for your machine.
++
++choice
++ prompt "Security Level"
++ depends on GRKERNSEC
++ default GRKERNSEC_CUSTOM
++
++config GRKERNSEC_LOW
++ bool "Low"
++ select GRKERNSEC_LINK
++ select GRKERNSEC_FIFO
++ select GRKERNSEC_EXECVE
++ select GRKERNSEC_RANDNET
++ select GRKERNSEC_DMESG
++ select GRKERNSEC_CHROOT
++ select GRKERNSEC_CHROOT_CHDIR
++
++ help
++ If you choose this option, several of the grsecurity options will
++ be enabled that will give you greater protection against a number
++ of attacks, while assuring that none of your software will have any
++ conflicts with the additional security measures. If you run a lot
++ of unusual software, or you are having problems with the higher
++ security levels, you should say Y here. With this option, the
++ following features are enabled:
++
++ - Linking restrictions
++ - FIFO restrictions
++ - Enforcing RLIMIT_NPROC on execve
++ - Restricted dmesg
++ - Enforced chdir("/") on chroot
++ - Runtime module disabling
++
++config GRKERNSEC_MEDIUM
++ bool "Medium"
++ select PAX
++ select PAX_EI_PAX
++ select PAX_PT_PAX_FLAGS
++ select PAX_HAVE_ACL_FLAGS
++ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
++ select GRKERNSEC_CHROOT
++ select GRKERNSEC_CHROOT_SYSCTL
++ select GRKERNSEC_LINK
++ select GRKERNSEC_FIFO
++ select GRKERNSEC_EXECVE
++ select GRKERNSEC_DMESG
++ select GRKERNSEC_RANDNET
++ select GRKERNSEC_FORKFAIL
++ select GRKERNSEC_TIME
++ select GRKERNSEC_SIGNAL
++ select GRKERNSEC_CHROOT
++ select GRKERNSEC_CHROOT_UNIX
++ select GRKERNSEC_CHROOT_MOUNT
++ select GRKERNSEC_CHROOT_PIVOT
++ select GRKERNSEC_CHROOT_DOUBLE
++ select GRKERNSEC_CHROOT_CHDIR
++ select GRKERNSEC_CHROOT_MKNOD
++ select GRKERNSEC_PROC
++ select GRKERNSEC_PROC_USERGROUP
++ select PAX_RANDUSTACK
++ select PAX_ASLR
++ select PAX_RANDMMAP
++ select PAX_REFCOUNT if (X86 || SPARC64)
++ select PAX_USERCOPY if ((X86 || SPARC32 || SPARC64 || PPC) && (SLAB || SLUB || SLOB))
++
++ help
++ If you say Y here, several features in addition to those included
++ in the low additional security level will be enabled. These
++ features provide even more security to your system, though in rare
++ cases they may be incompatible with very old or poorly written
++ software. If you enable this option, make sure that your auth
++ service (identd) is running as gid 1001. With this option,
++ the following features (in addition to those provided in the
++ low additional security level) will be enabled:
++
++ - Failed fork logging
++ - Time change logging
++ - Signal logging
++ - Deny mounts in chroot
++ - Deny double chrooting
++ - Deny sysctl writes in chroot
++ - Deny mknod in chroot
++ - Deny access to abstract AF_UNIX sockets out of chroot
++ - Deny pivot_root in chroot
++ - Denied writes of /dev/kmem, /dev/mem, and /dev/port
++ - /proc restrictions with special GID set to 10 (usually wheel)
++ - Address Space Layout Randomization (ASLR)
++ - Prevent exploitation of most refcount overflows
++ - Bounds checking of copying between the kernel and userland
++
++config GRKERNSEC_HIGH
++ bool "High"
++ select GRKERNSEC_LINK
++ select GRKERNSEC_FIFO
++ select GRKERNSEC_EXECVE
++ select GRKERNSEC_DMESG
++ select GRKERNSEC_FORKFAIL
++ select GRKERNSEC_TIME
++ select GRKERNSEC_SIGNAL
++ select GRKERNSEC_CHROOT
++ select GRKERNSEC_CHROOT_SHMAT
++ select GRKERNSEC_CHROOT_UNIX
++ select GRKERNSEC_CHROOT_MOUNT
++ select GRKERNSEC_CHROOT_FCHDIR
++ select GRKERNSEC_CHROOT_PIVOT
++ select GRKERNSEC_CHROOT_DOUBLE
++ select GRKERNSEC_CHROOT_CHDIR
++ select GRKERNSEC_CHROOT_MKNOD
++ select GRKERNSEC_CHROOT_CAPS
++ select GRKERNSEC_CHROOT_SYSCTL
++ select GRKERNSEC_CHROOT_FINDTASK
++ select GRKERNSEC_SYSFS_RESTRICT
++ select GRKERNSEC_PROC
++ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
++ select GRKERNSEC_HIDESYM
++ select GRKERNSEC_BRUTE
++ select GRKERNSEC_PROC_USERGROUP
++ select GRKERNSEC_KMEM
++ select GRKERNSEC_RESLOG
++ select GRKERNSEC_RANDNET
++ select GRKERNSEC_PROC_ADD
++ select GRKERNSEC_CHROOT_CHMOD
++ select GRKERNSEC_CHROOT_NICE
++ select GRKERNSEC_AUDIT_MOUNT
++ select GRKERNSEC_MODHARDEN if (MODULES)
++ select GRKERNSEC_HARDEN_PTRACE
++ select GRKERNSEC_VM86 if (X86_32)
++ select GRKERNSEC_KERN_LOCKOUT if (X86)
++ select PAX
++ select PAX_RANDUSTACK
++ select PAX_ASLR
++ select PAX_RANDMMAP
++ select PAX_NOEXEC
++ select PAX_MPROTECT
++ select PAX_EI_PAX
++ select PAX_PT_PAX_FLAGS
++ select PAX_HAVE_ACL_FLAGS
++ select PAX_KERNEXEC if ((PPC || X86) && (!X86_32 || X86_WP_WORKS_OK) && !XEN)
++ select PAX_MEMORY_UDEREF if (X86 && !XEN)
++ select PAX_RANDKSTACK if (X86_TSC && X86)
++ select PAX_SEGMEXEC if (X86_32)
++ select PAX_PAGEEXEC
++ select PAX_EMUPLT if (ALPHA || PARISC || SPARC32 || SPARC64)
++ select PAX_EMUTRAMP if (PARISC)
++ select PAX_EMUSIGRT if (PARISC)
++ select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC)
++ select PAX_ELFRELOCS if (PAX_ETEXECRELOCS || (IA64 || PPC || X86))
++ select PAX_REFCOUNT if (X86 || SPARC64)
++ select PAX_USERCOPY if ((X86 || PPC || SPARC32 || SPARC64) && (SLAB || SLUB || SLOB))
++ help
++ If you say Y here, many of the features of grsecurity will be
++ enabled, which will protect you against many kinds of attacks
++ against your system. The heightened security comes at a cost
++ of an increased chance of incompatibilities with rare software
++ on your machine. Since this security level enables PaX, you should
++ view <http://pax.grsecurity.net> and read about the PaX
++ project. While you are there, download chpax and run it on
++ binaries that cause problems with PaX. Also remember that
++ since the /proc restrictions are enabled, you must run your
++ identd as gid 1001. This security level enables the following
++ features in addition to those listed in the low and medium
++ security levels:
++
++ - Additional /proc restrictions
++ - Chmod restrictions in chroot
++ - No signals, ptrace, or viewing of processes outside of chroot
++ - Capability restrictions in chroot
++ - Deny fchdir out of chroot
++ - Priority restrictions in chroot
++ - Segmentation-based implementation of PaX
++ - Mprotect restrictions
++ - Removal of addresses from /proc/<pid>/[smaps|maps|stat]
++ - Kernel stack randomization
++ - Mount/unmount/remount logging
++ - Kernel symbol hiding
++ - Prevention of memory exhaustion-based exploits
++ - Hardening of module auto-loading
++ - Ptrace restrictions
++ - Restricted vm86 mode
++ - Restricted sysfs/debugfs
++ - Active kernel exploit response
++
++config GRKERNSEC_CUSTOM
++ bool "Custom"
++ help
++ If you say Y here, you will be able to configure every grsecurity
++ option, which allows you to enable many more features that aren't
++ covered in the basic security levels. These additional features
++ include TPE, socket restrictions, and the sysctl system for
++ grsecurity. It is advised that you read through the help for
++ each option to determine its usefulness in your situation.
++
++endchoice
++
++menu "Address Space Protection"
++depends on GRKERNSEC
++
++config GRKERNSEC_KMEM
++ bool "Deny writing to /dev/kmem, /dev/mem, and /dev/port"
++ select STRICT_DEVMEM if (X86 || ARM || TILE || S390)
++ help
++ If you say Y here, /dev/kmem and /dev/mem won't be allowed to
++ be written to via mmap or otherwise to modify the running kernel.
++ /dev/port will also not be allowed to be opened. If you have module
++ support disabled, enabling this will close up four ways that are
++ currently used to insert malicious code into the running kernel.
++ Even with all these features enabled, we still highly recommend that
++ you use the RBAC system, as it is still possible for an attacker to
++ modify the running kernel through privileged I/O granted by ioperm/iopl.
++ If you are not using XFree86, you may be able to stop this additional
++ case by enabling the 'Disable privileged I/O' option. Though nothing
++ legitimately writes to /dev/kmem, XFree86 does need to write to /dev/mem,
++ but only to video memory, which is the only writing we allow in this
++ case. If /dev/kmem or /dev/mem are mmaped without PROT_WRITE, they will
++ not be allowed to mprotect it with PROT_WRITE later.
++ It is highly recommended that you say Y here if you meet all the
++ conditions above.
++
++config GRKERNSEC_VM86
++ bool "Restrict VM86 mode"
++ depends on X86_32
++
++ help
++ If you say Y here, only processes with CAP_SYS_RAWIO will be able to
++ make use of a special execution mode on 32bit x86 processors called
++ Virtual 8086 (VM86) mode. XFree86 may need vm86 mode for certain
++ video cards and will still work with this option enabled. The purpose
++ of the option is to prevent exploitation of emulation errors in
++ virtualization of vm86 mode like the one discovered in VMWare in 2009.
++ Nearly all users should be able to enable this option.
++
++config GRKERNSEC_IO
++ bool "Disable privileged I/O"
++ depends on X86
++ select RTC_CLASS
++ select RTC_INTF_DEV
++ select RTC_DRV_CMOS
++
++ help
++ If you say Y here, all ioperm and iopl calls will return an error.
++ Ioperm and iopl can be used to modify the running kernel.
++ Unfortunately, some programs need this access to operate properly,
++ the most notable of which are XFree86 and hwclock. hwclock can be
++ remedied by having RTC support in the kernel, so real-time
++ clock support is enabled if this option is enabled, to ensure
++ that hwclock operates correctly. XFree86 still will not
++ operate correctly with this option enabled, so DO NOT CHOOSE Y
++ IF YOU USE XFree86. If you use XFree86 and you still want to
++ protect your kernel against modification, use the RBAC system.
++
++config GRKERNSEC_PROC_MEMMAP
++ bool "Remove addresses from /proc/<pid>/[smaps|maps|stat]"
++ default y if (PAX_NOEXEC || PAX_ASLR)
++ depends on PAX_NOEXEC || PAX_ASLR
++ help
++ If you say Y here, the /proc/<pid>/maps and /proc/<pid>/stat files will
++ give no information about the addresses of its mappings if
++ PaX features that rely on random addresses are enabled on the task.
++ If you use PaX it is greatly recommended that you say Y here as it
++ closes up a hole that makes the full ASLR useless for suid
++ binaries.
++
++config GRKERNSEC_BRUTE
++ bool "Deter exploit bruteforcing"
++ help
++ If you say Y here, attempts to bruteforce exploits against forking
++ daemons such as apache or sshd, as well as against suid/sgid binaries
++ will be deterred. When a child of a forking daemon is killed by PaX
++ or crashes due to an illegal instruction or other suspicious signal,
++ the parent process will be delayed 30 seconds upon every subsequent
++ fork until the administrator is able to assess the situation and
++ restart the daemon.
++ In the suid/sgid case, the attempt is logged, the user has all their
++ processes terminated, and they are prevented from executing any further
++ processes for 15 minutes.
++ It is recommended that you also enable signal logging in the auditing
++ section so that logs are generated when a process triggers a suspicious
++ signal.
++
++config GRKERNSEC_MODHARDEN
++ bool "Harden module auto-loading"
++ depends on MODULES
++ help
++ If you say Y here, module auto-loading in response to use of some
++ feature implemented by an unloaded module will be restricted to
++ root users. Enabling this option helps defend against attacks
++ by unprivileged users who abuse the auto-loading behavior to
++ cause a vulnerable module to load that is then exploited.
++
++ If this option prevents a legitimate use of auto-loading for a
++ non-root user, the administrator can execute modprobe manually
++ with the exact name of the module mentioned in the alert log.
++ Alternatively, the administrator can add the module to the list
++ of modules loaded at boot by modifying init scripts.
++
++ Modification of init scripts will most likely be needed on
++ Ubuntu servers with encrypted home directory support enabled,
++ as the first non-root user logging in will cause the ecb(aes),
++ ecb(aes)-all, cbc(aes), and cbc(aes)-all modules to be loaded.
++
++config GRKERNSEC_HIDESYM
++ bool "Hide kernel symbols"
++ help
++ If you say Y here, getting information on loaded modules, and
++ displaying all kernel symbols through a syscall will be restricted
++ to users with CAP_SYS_MODULE. For software compatibility reasons,
++ /proc/kallsyms will be restricted to the root user. The RBAC
++ system can hide that entry even from root.
++
++ This option also prevents leaking of kernel addresses through
++ several /proc entries.
++
++ Note that this option is only effective provided the following
++ conditions are met:
++ 1) The kernel using grsecurity is not precompiled by some distribution
++ 2) You have also enabled GRKERNSEC_DMESG
++ 3) You are using the RBAC system and hiding other files such as your
++ kernel image and System.map. Alternatively, enabling this option
++ causes the permissions on /boot, /lib/modules, and the kernel
++ source directory to change at compile time to prevent
++ reading by non-root users.
++ If the above conditions are met, this option will aid in providing a
++ useful protection against local kernel exploitation of overflows
++ and arbitrary read/write vulnerabilities.
++
++config GRKERNSEC_KERN_LOCKOUT
++ bool "Active kernel exploit response"
++ depends on X86
++ help
++ If you say Y here, when a PaX alert is triggered due to suspicious
++ activity in the kernel (from KERNEXEC/UDEREF/USERCOPY)
++ or an OOPs occurs due to bad memory accesses, instead of just
++ terminating the offending process (and potentially allowing
++ a subsequent exploit from the same user), we will take one of two
++ actions:
++ If the user was root, we will panic the system
++ If the user was non-root, we will log the attempt, terminate
++ all processes owned by the user, then prevent them from creating
++ any new processes until the system is restarted
++ This deters repeated kernel exploitation/bruteforcing attempts
++ and is useful for later forensics.
++
++endmenu
++menu "Role Based Access Control Options"
++depends on GRKERNSEC
++
++config GRKERNSEC_RBAC_DEBUG
++ bool
++
++config GRKERNSEC_NO_RBAC
++ bool "Disable RBAC system"
++ help
++ If you say Y here, the /dev/grsec device will be removed from the kernel,
++ preventing the RBAC system from being enabled. You should only say Y
++ here if you have no intention of using the RBAC system, so as to prevent
++ an attacker with root access from misusing the RBAC system to hide files
++ and processes when loadable module support and /dev/[k]mem have been
++ locked down.
++
++config GRKERNSEC_ACL_HIDEKERN
++ bool "Hide kernel processes"
++ help
++ If you say Y here, all kernel threads will be hidden to all
++ processes but those whose subject has the "view hidden processes"
++ flag.
++
++config GRKERNSEC_ACL_MAXTRIES
++ int "Maximum tries before password lockout"
++ default 3
++ help
++ This option enforces the maximum number of times a user can attempt
++ to authorize themselves with the grsecurity RBAC system before being
++ denied the ability to attempt authorization again for a specified time.
++ The lower the number, the harder it will be to brute-force a password.
++
++config GRKERNSEC_ACL_TIMEOUT
++ int "Time to wait after max password tries, in seconds"
++ default 30
++ help
++ This option specifies the time the user must wait after attempting to
++ authorize to the RBAC system with the maximum number of invalid
++ passwords. The higher the number, the harder it will be to brute-force
++ a password.
++
++endmenu
++menu "Filesystem Protections"
++depends on GRKERNSEC
++
++config GRKERNSEC_PROC
++ bool "Proc restrictions"
++ help
++ If you say Y here, the permissions of the /proc filesystem
++ will be altered to enhance system security and privacy. You MUST
++ choose either a user only restriction or a user and group restriction.
++ Depending upon the option you choose, you can either restrict users to
++ see only the processes they themselves run, or choose a group that can
++ view all processes and files normally restricted to root if you choose
++ the "restrict to user only" option. NOTE: If you're running identd as
++ a non-root user, you will have to run it as the group you specify here.
++
++config GRKERNSEC_PROC_USER
++ bool "Restrict /proc to user only"
++ depends on GRKERNSEC_PROC
++ help
++ If you say Y here, non-root users will only be able to view their own
++ processes, and restricts them from viewing network-related information,
++ and viewing kernel symbol and module information.
++
++config GRKERNSEC_PROC_USERGROUP
++ bool "Allow special group"
++ depends on GRKERNSEC_PROC && !GRKERNSEC_PROC_USER
++ help
++ If you say Y here, you will be able to select a group that will be
++ able to view all processes and network-related information. If you've
++ enabled GRKERNSEC_HIDESYM, kernel and symbol information may still
++ remain hidden. This option is useful if you want to run identd as
++ a non-root user.
++
++config GRKERNSEC_PROC_GID
++ int "GID for special group"
++ depends on GRKERNSEC_PROC_USERGROUP
++ default 1001
++
++config GRKERNSEC_PROC_ADD
++ bool "Additional restrictions"
++ depends on GRKERNSEC_PROC_USER || GRKERNSEC_PROC_USERGROUP
++ help
++ If you say Y here, additional restrictions will be placed on
++ /proc that keep normal users from viewing device information and
++ slabinfo information that could be useful for exploits.
++
++config GRKERNSEC_LINK
++ bool "Linking restrictions"
++ help
++ If you say Y here, /tmp race exploits will be prevented, since users
++ will no longer be able to follow symlinks owned by other users in
++ world-writable +t directories (e.g. /tmp), unless the owner of the
++ symlink is the owner of the directory. users will also not be
++ able to hardlink to files they do not own. If the sysctl option is
++ enabled, a sysctl option with name "linking_restrictions" is created.
++
++config GRKERNSEC_FIFO
++ bool "FIFO restrictions"
++ help
++ If you say Y here, users will not be able to write to FIFOs they don't
++ own in world-writable +t directories (e.g. /tmp), unless the owner of
++ the FIFO is the same owner of the directory it's held in. If the sysctl
++ option is enabled, a sysctl option with name "fifo_restrictions" is
++ created.
++
++config GRKERNSEC_SYSFS_RESTRICT
++ bool "Sysfs/debugfs restriction"
++ depends on SYSFS
++ help
++ If you say Y here, sysfs (the pseudo-filesystem mounted at /sys) and
++ any filesystem normally mounted under it (e.g. debugfs) will only
++ be accessible by root. These filesystems generally provide access
++ to hardware and debug information that isn't appropriate for unprivileged
++ users of the system. Sysfs and debugfs have also become a large source
++ of new vulnerabilities, ranging from infoleaks to local compromise.
++ There has been very little oversight with an eye toward security involved
++ in adding new exporters of information to these filesystems, so their
++ use is discouraged.
++ This option is equivalent to a chmod 0700 of the mount paths.
++
++config GRKERNSEC_ROFS
++ bool "Runtime read-only mount protection"
++ help
++ If you say Y here, a sysctl option with name "romount_protect" will
++ be created. By setting this option to 1 at runtime, filesystems
++ will be protected in the following ways:
++ * No new writable mounts will be allowed
++ * Existing read-only mounts won't be able to be remounted read/write
++ * Write operations will be denied on all block devices
++ This option acts independently of grsec_lock: once it is set to 1,
++ it cannot be turned off. Therefore, please be mindful of the resulting
++ behavior if this option is enabled in an init script on a read-only
++ filesystem. This feature is mainly intended for secure embedded systems.
++
++config GRKERNSEC_CHROOT
++ bool "Chroot jail restrictions"
++ help
++ If you say Y here, you will be able to choose several options that will
++ make breaking out of a chrooted jail much more difficult. If you
++ encounter no software incompatibilities with the following options, it
++ is recommended that you enable each one.
++
++config GRKERNSEC_CHROOT_MOUNT
++ bool "Deny mounts"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be able to
++ mount or remount filesystems. If the sysctl option is enabled, a
++ sysctl option with name "chroot_deny_mount" is created.
++
++config GRKERNSEC_CHROOT_DOUBLE
++ bool "Deny double-chroots"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be able to chroot
++ again outside the chroot. This is a widely used method of breaking
++ out of a chroot jail and should not be allowed. If the sysctl
++ option is enabled, a sysctl option with name
++ "chroot_deny_chroot" is created.
++
++config GRKERNSEC_CHROOT_PIVOT
++ bool "Deny pivot_root in chroot"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be able to use
++ a function called pivot_root() that was introduced in Linux 2.3.41. It
++ works similar to chroot in that it changes the root filesystem. This
++ function could be misused in a chrooted process to attempt to break out
++ of the chroot, and therefore should not be allowed. If the sysctl
++ option is enabled, a sysctl option with name "chroot_deny_pivot" is
++ created.
++
++config GRKERNSEC_CHROOT_CHDIR
++ bool "Enforce chdir(\"/\") on all chroots"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, the current working directory of all newly-chrooted
++ applications will be set to the the root directory of the chroot.
++ The man page on chroot(2) states:
++ Note that this call does not change the current working
++ directory, so that `.' can be outside the tree rooted at
++ `/'. In particular, the super-user can escape from a
++ `chroot jail' by doing `mkdir foo; chroot foo; cd ..'.
++
++ It is recommended that you say Y here, since it's not known to break
++ any software. If the sysctl option is enabled, a sysctl option with
++ name "chroot_enforce_chdir" is created.
++
++config GRKERNSEC_CHROOT_CHMOD
++ bool "Deny (f)chmod +s"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be able to chmod
++ or fchmod files to make them have suid or sgid bits. This protects
++ against another published method of breaking a chroot. If the sysctl
++ option is enabled, a sysctl option with name "chroot_deny_chmod" is
++ created.
++
++config GRKERNSEC_CHROOT_FCHDIR
++ bool "Deny fchdir out of chroot"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, a well-known method of breaking chroots by fchdir'ing
++ to a file descriptor of the chrooting process that points to a directory
++ outside the filesystem will be stopped. If the sysctl option
++ is enabled, a sysctl option with name "chroot_deny_fchdir" is created.
++
++config GRKERNSEC_CHROOT_MKNOD
++ bool "Deny mknod"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be allowed to
++ mknod. The problem with using mknod inside a chroot is that it
++ would allow an attacker to create a device entry that is the same
++ as one on the physical root of your system, which could range from
++ anything from the console device to a device for your harddrive (which
++ they could then use to wipe the drive or steal data). It is recommended
++ that you say Y here, unless you run into software incompatibilities.
++ If the sysctl option is enabled, a sysctl option with name
++ "chroot_deny_mknod" is created.
++
++config GRKERNSEC_CHROOT_SHMAT
++ bool "Deny shmat() out of chroot"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be able to attach
++ to shared memory segments that were created outside of the chroot jail.
++ It is recommended that you say Y here. If the sysctl option is enabled,
++ a sysctl option with name "chroot_deny_shmat" is created.
++
++config GRKERNSEC_CHROOT_UNIX
++ bool "Deny access to abstract AF_UNIX sockets out of chroot"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be able to
++ connect to abstract (meaning not belonging to a filesystem) Unix
++ domain sockets that were bound outside of a chroot. It is recommended
++ that you say Y here. If the sysctl option is enabled, a sysctl option
++ with name "chroot_deny_unix" is created.
++
++config GRKERNSEC_CHROOT_FINDTASK
++ bool "Protect outside processes"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be able to
++ kill, send signals with fcntl, ptrace, capget, getpgid, setpgid,
++ getsid, or view any process outside of the chroot. If the sysctl
++ option is enabled, a sysctl option with name "chroot_findtask" is
++ created.
++
++config GRKERNSEC_CHROOT_NICE
++ bool "Restrict priority changes"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, processes inside a chroot will not be able to raise
++ the priority of processes in the chroot, or alter the priority of
++ processes outside the chroot. This provides more security than simply
++ removing CAP_SYS_NICE from the process' capability set. If the
++ sysctl option is enabled, a sysctl option with name "chroot_restrict_nice"
++ is created.
++
++config GRKERNSEC_CHROOT_SYSCTL
++ bool "Deny sysctl writes"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, an attacker in a chroot will not be able to
++ write to sysctl entries, either by sysctl(2) or through a /proc
++ interface. It is strongly recommended that you say Y here. If the
++ sysctl option is enabled, a sysctl option with name
++ "chroot_deny_sysctl" is created.
++
++config GRKERNSEC_CHROOT_CAPS
++ bool "Capability restrictions"
++ depends on GRKERNSEC_CHROOT
++ help
++ If you say Y here, the capabilities on all root processes within a
++ chroot jail will be lowered to stop module insertion, raw i/o,
++ system and net admin tasks, rebooting the system, modifying immutable
++ files, modifying IPC owned by another, and changing the system time.
++ This is left an option because it can break some apps. Disable this
++ if your chrooted apps are having problems performing those kinds of
++ tasks. If the sysctl option is enabled, a sysctl option with
++ name "chroot_caps" is created.
++
++endmenu
++menu "Kernel Auditing"
++depends on GRKERNSEC
++
++config GRKERNSEC_AUDIT_GROUP
++ bool "Single group for auditing"
++ help
++ If you say Y here, the exec, chdir, and (un)mount logging features
++ will only operate on a group you specify. This option is recommended
++ if you only want to watch certain users instead of having a large
++ amount of logs from the entire system. If the sysctl option is enabled,
++ a sysctl option with name "audit_group" is created.
++
++config GRKERNSEC_AUDIT_GID
++ int "GID for auditing"
++ depends on GRKERNSEC_AUDIT_GROUP
++ default 1007
++
++config GRKERNSEC_EXECLOG
++ bool "Exec logging"
++ help
++ If you say Y here, all execve() calls will be logged (since the
++ other exec*() calls are frontends to execve(), all execution
++ will be logged). Useful for shell-servers that like to keep track
++ of their users. If the sysctl option is enabled, a sysctl option with
++ name "exec_logging" is created.
++ WARNING: This option when enabled will produce a LOT of logs, especially
++ on an active system.
++
++config GRKERNSEC_RESLOG
++ bool "Resource logging"
++ help
++ If you say Y here, all attempts to overstep resource limits will
++ be logged with the resource name, the requested size, and the current
++ limit. It is highly recommended that you say Y here. If the sysctl
++ option is enabled, a sysctl option with name "resource_logging" is
++ created. If the RBAC system is enabled, the sysctl value is ignored.
++
++config GRKERNSEC_CHROOT_EXECLOG
++ bool "Log execs within chroot"
++ help
++ If you say Y here, all executions inside a chroot jail will be logged
++ to syslog. This can cause a large amount of logs if certain
++ applications (eg. djb's daemontools) are installed on the system, and
++ is therefore left as an option. If the sysctl option is enabled, a
++ sysctl option with name "chroot_execlog" is created.
++
++config GRKERNSEC_AUDIT_PTRACE
++ bool "Ptrace logging"
++ help
++ If you say Y here, all attempts to attach to a process via ptrace
++ will be logged. If the sysctl option is enabled, a sysctl option
++ with name "audit_ptrace" is created.
++
++config GRKERNSEC_AUDIT_CHDIR
++ bool "Chdir logging"
++ help
++ If you say Y here, all chdir() calls will be logged. If the sysctl
++ option is enabled, a sysctl option with name "audit_chdir" is created.
++
++config GRKERNSEC_AUDIT_MOUNT
++ bool "(Un)Mount logging"
++ help
++ If you say Y here, all mounts and unmounts will be logged. If the
++ sysctl option is enabled, a sysctl option with name "audit_mount" is
++ created.
++
++config GRKERNSEC_SIGNAL
++ bool "Signal logging"
++ help
++ If you say Y here, certain important signals will be logged, such as
++ SIGSEGV, which will as a result inform you of when a error in a program
++ occurred, which in some cases could mean a possible exploit attempt.
++ If the sysctl option is enabled, a sysctl option with name
++ "signal_logging" is created.
++
++config GRKERNSEC_FORKFAIL
++ bool "Fork failure logging"
++ help
++ If you say Y here, all failed fork() attempts will be logged.
++ This could suggest a fork bomb, or someone attempting to overstep
++ their process limit. If the sysctl option is enabled, a sysctl option
++ with name "forkfail_logging" is created.
++
++config GRKERNSEC_TIME
++ bool "Time change logging"
++ help
++ If you say Y here, any changes of the system clock will be logged.
++ If the sysctl option is enabled, a sysctl option with name
++ "timechange_logging" is created.
++
++config GRKERNSEC_PROC_IPADDR
++ bool "/proc/<pid>/ipaddr support"
++ help
++ If you say Y here, a new entry will be added to each /proc/<pid>
++ directory that contains the IP address of the person using the task.
++ The IP is carried across local TCP and AF_UNIX stream sockets.
++ This information can be useful for IDS/IPSes to perform remote response
++ to a local attack. The entry is readable by only the owner of the
++ process (and root if he has CAP_DAC_OVERRIDE, which can be removed via
++ the RBAC system), and thus does not create privacy concerns.
++
++config GRKERNSEC_RWXMAP_LOG
++ bool 'Denied RWX mmap/mprotect logging'
++ depends on PAX_MPROTECT && !PAX_EMUPLT && !PAX_EMUSIGRT
++ help
++ If you say Y here, calls to mmap() and mprotect() with explicit
++ usage of PROT_WRITE and PROT_EXEC together will be logged when
++ denied by the PAX_MPROTECT feature. If the sysctl option is
++ enabled, a sysctl option with name "rwxmap_logging" is created.
++
++config GRKERNSEC_AUDIT_TEXTREL
++ bool 'ELF text relocations logging (READ HELP)'
++ depends on PAX_MPROTECT
++ help
++ If you say Y here, text relocations will be logged with the filename
++ of the offending library or binary. The purpose of the feature is
++ to help Linux distribution developers get rid of libraries and
++ binaries that need text relocations which hinder the future progress
++ of PaX. Only Linux distribution developers should say Y here, and
++ never on a production machine, as this option creates an information
++ leak that could aid an attacker in defeating the randomization of
++ a single memory region. If the sysctl option is enabled, a sysctl
++ option with name "audit_textrel" is created.
++
++endmenu
++
++menu "Executable Protections"
++depends on GRKERNSEC
++
++config GRKERNSEC_EXECVE
++ bool "Enforce RLIMIT_NPROC on execs"
++ help
++ If you say Y here, users with a resource limit on processes will
++ have the value checked during execve() calls. The current system
++ only checks the system limit during fork() calls. If the sysctl option
++ is enabled, a sysctl option with name "execve_limiting" is created.
++
++config GRKERNSEC_DMESG
++ bool "Dmesg(8) restriction"
++ help
++ If you say Y here, non-root users will not be able to use dmesg(8)
++ to view up to the last 4kb of messages in the kernel's log buffer.
++ The kernel's log buffer often contains kernel addresses and other
++ identifying information useful to an attacker in fingerprinting a
++ system for a targeted exploit.
++ If the sysctl option is enabled, a sysctl option with name "dmesg" is
++ created.
++
++config GRKERNSEC_HARDEN_PTRACE
++ bool "Deter ptrace-based process snooping"
++ help
++ If you say Y here, TTY sniffers and other malicious monitoring
++ programs implemented through ptrace will be defeated. If you
++ have been using the RBAC system, this option has already been
++ enabled for several years for all users, with the ability to make
++ fine-grained exceptions.
++
++ This option only affects the ability of non-root users to ptrace
++ processes that are not a descendent of the ptracing process.
++ This means that strace ./binary and gdb ./binary will still work,
++ but attaching to arbitrary processes will not. If the sysctl
++ option is enabled, a sysctl option with name "harden_ptrace" is
++ created.
++
++config GRKERNSEC_TPE
++ bool "Trusted Path Execution (TPE)"
++ help
++ If you say Y here, you will be able to choose a gid to add to the
++ supplementary groups of users you want to mark as "untrusted."
++ These users will not be able to execute any files that are not in
++ root-owned directories writable only by root. If the sysctl option
++ is enabled, a sysctl option with name "tpe" is created.
++
++config GRKERNSEC_TPE_ALL
++ bool "Partially restrict all non-root users"
++ depends on GRKERNSEC_TPE
++ help
++ If you say Y here, all non-root users will be covered under
++ a weaker TPE restriction. This is separate from, and in addition to,
++ the main TPE options that you have selected elsewhere. Thus, if a
++ "trusted" GID is chosen, this restriction applies to even that GID.
++ Under this restriction, all non-root users will only be allowed to
++ execute files in directories they own that are not group or
++ world-writable, or in directories owned by root and writable only by
++ root. If the sysctl option is enabled, a sysctl option with name
++ "tpe_restrict_all" is created.
++
++config GRKERNSEC_TPE_INVERT
++ bool "Invert GID option"
++ depends on GRKERNSEC_TPE
++ help
++ If you say Y here, the group you specify in the TPE configuration will
++ decide what group TPE restrictions will be *disabled* for. This
++ option is useful if you want TPE restrictions to be applied to most
++ users on the system. If the sysctl option is enabled, a sysctl option
++ with name "tpe_invert" is created. Unlike other sysctl options, this
++ entry will default to on for backward-compatibility.
++
++config GRKERNSEC_TPE_GID
++ int "GID for untrusted users"
++ depends on GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT
++ default 1005
++ help
++ Setting this GID determines what group TPE restrictions will be
++ *enabled* for. If the sysctl option is enabled, a sysctl option
++ with name "tpe_gid" is created.
++
++config GRKERNSEC_TPE_GID
++ int "GID for trusted users"
++ depends on GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT
++ default 1005
++ help
++ Setting this GID determines what group TPE restrictions will be
++ *disabled* for. If the sysctl option is enabled, a sysctl option
++ with name "tpe_gid" is created.
++
++endmenu
++menu "Network Protections"
++depends on GRKERNSEC
++
++config GRKERNSEC_RANDNET
++ bool "Larger entropy pools"
++ help
++ If you say Y here, the entropy pools used for many features of Linux
++ and grsecurity will be doubled in size. Since several grsecurity
++ features use additional randomness, it is recommended that you say Y
++ here. Saying Y here has a similar effect as modifying
++ /proc/sys/kernel/random/poolsize.
++
++config GRKERNSEC_BLACKHOLE
++ bool "TCP/UDP blackhole and LAST_ACK DoS prevention"
++ help
++ If you say Y here, neither TCP resets nor ICMP
++ destination-unreachable packets will be sent in response to packets
++ sent to ports for which no associated listening process exists.
++ This feature supports both IPV4 and IPV6 and exempts the
++ loopback interface from blackholing. Enabling this feature
++ makes a host more resilient to DoS attacks and reduces network
++ visibility against scanners.
++
++ The blackhole feature as-implemented is equivalent to the FreeBSD
++ blackhole feature, as it prevents RST responses to all packets, not
++ just SYNs. Under most application behavior this causes no
++ problems, but applications (like haproxy) may not close certain
++ connections in a way that cleanly terminates them on the remote
++ end, leaving the remote host in LAST_ACK state. Because of this
++ side-effect and to prevent intentional LAST_ACK DoSes, this
++ feature also adds automatic mitigation against such attacks.
++ The mitigation drastically reduces the amount of time a socket
++ can spend in LAST_ACK state. If you're using haproxy and not
++ all servers it connects to have this option enabled, consider
++ disabling this feature on the haproxy host.
++
++ If the sysctl option is enabled, two sysctl options with names
++ "ip_blackhole" and "lastack_retries" will be created.
++ While "ip_blackhole" takes the standard zero/non-zero on/off
++ toggle, "lastack_retries" uses the same kinds of values as
++ "tcp_retries1" and "tcp_retries2". The default value of 4
++ prevents a socket from lasting more than 45 seconds in LAST_ACK
++ state.
++
++config GRKERNSEC_SOCKET
++ bool "Socket restrictions"
++ help
++ If you say Y here, you will be able to choose from several options.
++ If you assign a GID on your system and add it to the supplementary
++ groups of users you want to restrict socket access to, this patch
++ will perform up to three things, based on the option(s) you choose.
++
++config GRKERNSEC_SOCKET_ALL
++ bool "Deny any sockets to group"
++ depends on GRKERNSEC_SOCKET
++ help
++ If you say Y here, you will be able to choose a GID of whose users will
++ be unable to connect to other hosts from your machine or run server
++ applications from your machine. If the sysctl option is enabled, a
++ sysctl option with name "socket_all" is created.
++
++config GRKERNSEC_SOCKET_ALL_GID
++ int "GID to deny all sockets for"
++ depends on GRKERNSEC_SOCKET_ALL
++ default 1004
++ help
++ Here you can choose the GID to disable socket access for. Remember to
++ add the users you want socket access disabled for to the GID
++ specified here. If the sysctl option is enabled, a sysctl option
++ with name "socket_all_gid" is created.
++
++config GRKERNSEC_SOCKET_CLIENT
++ bool "Deny client sockets to group"
++ depends on GRKERNSEC_SOCKET
++ help
++ If you say Y here, you will be able to choose a GID of whose users will
++ be unable to connect to other hosts from your machine, but will be
++ able to run servers. If this option is enabled, all users in the group
++ you specify will have to use passive mode when initiating ftp transfers
++ from the shell on your machine. If the sysctl option is enabled, a
++ sysctl option with name "socket_client" is created.
++
++config GRKERNSEC_SOCKET_CLIENT_GID
++ int "GID to deny client sockets for"
++ depends on GRKERNSEC_SOCKET_CLIENT
++ default 1003
++ help
++ Here you can choose the GID to disable client socket access for.
++ Remember to add the users you want client socket access disabled for to
++ the GID specified here. If the sysctl option is enabled, a sysctl
++ option with name "socket_client_gid" is created.
++
++config GRKERNSEC_SOCKET_SERVER
++ bool "Deny server sockets to group"
++ depends on GRKERNSEC_SOCKET
++ help
++ If you say Y here, you will be able to choose a GID of whose users will
++ be unable to run server applications from your machine. If the sysctl
++ option is enabled, a sysctl option with name "socket_server" is created.
++
++config GRKERNSEC_SOCKET_SERVER_GID
++ int "GID to deny server sockets for"
++ depends on GRKERNSEC_SOCKET_SERVER
++ default 1002
++ help
++ Here you can choose the GID to disable server socket access for.
++ Remember to add the users you want server socket access disabled for to
++ the GID specified here. If the sysctl option is enabled, a sysctl
++ option with name "socket_server_gid" is created.
++
++endmenu
++menu "Sysctl support"
++depends on GRKERNSEC && SYSCTL
++
++config GRKERNSEC_SYSCTL
++ bool "Sysctl support"
++ help
++ If you say Y here, you will be able to change the options that
++ grsecurity runs with at bootup, without having to recompile your
++ kernel. You can echo values to files in /proc/sys/kernel/grsecurity
++ to enable (1) or disable (0) various features. All the sysctl entries
++ are mutable until the "grsec_lock" entry is set to a non-zero value.
++ All features enabled in the kernel configuration are disabled at boot
++ if you do not say Y to the "Turn on features by default" option.
++ All options should be set at startup, and the grsec_lock entry should
++ be set to a non-zero value after all the options are set.
++ *THIS IS EXTREMELY IMPORTANT*
++
++config GRKERNSEC_SYSCTL_DISTRO
++ bool "Extra sysctl support for distro makers (READ HELP)"
++ depends on GRKERNSEC_SYSCTL && GRKERNSEC_IO
++ help
++ If you say Y here, additional sysctl options will be created
++ for features that affect processes running as root. Therefore,
++ it is critical when using this option that the grsec_lock entry be
++ enabled after boot. Only distros with prebuilt kernel packages
++ with this option enabled that can ensure grsec_lock is enabled
++ after boot should use this option.
++ *Failure to set grsec_lock after boot makes all grsec features
++ this option covers useless*
++
++ Currently this option creates the following sysctl entries:
++ "Disable Privileged I/O": "disable_priv_io"
++
++config GRKERNSEC_SYSCTL_ON
++ bool "Turn on features by default"
++ depends on GRKERNSEC_SYSCTL
++ help
++ If you say Y here, instead of having all features enabled in the
++ kernel configuration disabled at boot time, the features will be
++ enabled at boot time. It is recommended you say Y here unless
++ there is some reason you would want all sysctl-tunable features to
++ be disabled by default. As mentioned elsewhere, it is important
++ to enable the grsec_lock entry once you have finished modifying
++ the sysctl entries.
++
++endmenu
++menu "Logging Options"
++depends on GRKERNSEC
++
++config GRKERNSEC_FLOODTIME
++ int "Seconds in between log messages (minimum)"
++ default 10
++ help
++ This option allows you to enforce the number of seconds between
++ grsecurity log messages. The default should be suitable for most
++ people, however, if you choose to change it, choose a value small enough
++ to allow informative logs to be produced, but large enough to
++ prevent flooding.
++
++config GRKERNSEC_FLOODBURST
++ int "Number of messages in a burst (maximum)"
++ default 4
++ help
++ This option allows you to choose the maximum number of messages allowed
++ within the flood time interval you chose in a separate option. The
++ default should be suitable for most people, however if you find that
++ many of your logs are being interpreted as flooding, you may want to
++ raise this value.
++
++endmenu
++
++endmenu
+diff -urNp linux-2.6.38.7/grsecurity/Makefile linux-2.6.38.7/grsecurity/Makefile
+--- linux-2.6.38.7/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/grsecurity/Makefile 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,29 @@
++# grsecurity's ACL system was originally written in 2001 by Michael Dalton
++# during 2001-2009 it has been completely redesigned by Brad Spengler
++# into an RBAC system
++#
++# All code in this directory and various hooks inserted throughout the kernel
++# are copyright Brad Spengler - Open Source Security, Inc., and released
++# under the GPL v2 or higher
++
++obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \
++ grsec_mount.o grsec_sig.o grsec_sock.o grsec_sysctl.o \
++ grsec_time.o grsec_tpe.o grsec_link.o grsec_pax.o grsec_ptrace.o
++
++obj-$(CONFIG_GRKERNSEC) += grsec_init.o grsum.o gracl.o gracl_ip.o gracl_segv.o \
++ gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \
++ gracl_learn.o grsec_log.o
++obj-$(CONFIG_GRKERNSEC_RESLOG) += gracl_res.o
++
++ifndef CONFIG_GRKERNSEC
++obj-y += grsec_disabled.o
++endif
++
++ifdef CONFIG_GRKERNSEC_HIDESYM
++extra-y := grsec_hidesym.o
++$(obj)/grsec_hidesym.o:
++ @-chmod -f 500 /boot
++ @-chmod -f 500 /lib/modules
++ @-chmod -f 700 .
++ @echo ' grsec: protected kernel image paths'
++endif
+diff -urNp linux-2.6.38.7/include/acpi/acpi_drivers.h linux-2.6.38.7/include/acpi/acpi_drivers.h
+--- linux-2.6.38.7/include/acpi/acpi_drivers.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/acpi/acpi_drivers.h 2011-04-28 19:34:15.000000000 -0400
+@@ -119,8 +119,8 @@ void pci_acpi_crs_quirks(void);
+ Dock Station
+ -------------------------------------------------------------------------- */
+ struct acpi_dock_ops {
+- acpi_notify_handler handler;
+- acpi_notify_handler uevent;
++ const acpi_notify_handler handler;
++ const acpi_notify_handler uevent;
+ };
+
+ #if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
+@@ -128,7 +128,7 @@ extern int is_dock_device(acpi_handle ha
+ extern int register_dock_notifier(struct notifier_block *nb);
+ extern void unregister_dock_notifier(struct notifier_block *nb);
+ extern int register_hotplug_dock_device(acpi_handle handle,
+- struct acpi_dock_ops *ops,
++ const struct acpi_dock_ops *ops,
+ void *context);
+ extern void unregister_hotplug_dock_device(acpi_handle handle);
+ #else
+@@ -144,7 +144,7 @@ static inline void unregister_dock_notif
+ {
+ }
+ static inline int register_hotplug_dock_device(acpi_handle handle,
+- struct acpi_dock_ops *ops,
++ const struct acpi_dock_ops *ops,
+ void *context)
+ {
+ return -ENODEV;
+diff -urNp linux-2.6.38.7/include/asm-generic/atomic-long.h linux-2.6.38.7/include/asm-generic/atomic-long.h
+--- linux-2.6.38.7/include/asm-generic/atomic-long.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/atomic-long.h 2011-05-16 21:47:08.000000000 -0400
+@@ -22,6 +22,12 @@
+
+ typedef atomic64_t atomic_long_t;
+
++#ifdef CONFIG_PAX_REFCOUNT
++typedef atomic64_unchecked_t atomic_long_unchecked_t;
++#else
++typedef atomic64_t atomic_long_unchecked_t;
++#endif
++
+ #define ATOMIC_LONG_INIT(i) ATOMIC64_INIT(i)
+
+ static inline long atomic_long_read(atomic_long_t *l)
+@@ -31,6 +37,15 @@ static inline long atomic_long_read(atom
+ return (long)atomic64_read(v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline long atomic_long_read_unchecked(atomic_long_unchecked_t *l)
++{
++ atomic64_unchecked_t *v = (atomic64_unchecked_t *)l;
++
++ return (long)atomic64_read_unchecked(v);
++}
++#endif
++
+ static inline void atomic_long_set(atomic_long_t *l, long i)
+ {
+ atomic64_t *v = (atomic64_t *)l;
+@@ -38,6 +53,15 @@ static inline void atomic_long_set(atomi
+ atomic64_set(v, i);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_set_unchecked(atomic_long_unchecked_t *l, long i)
++{
++ atomic64_unchecked_t *v = (atomic64_unchecked_t *)l;
++
++ atomic64_set_unchecked(v, i);
++}
++#endif
++
+ static inline void atomic_long_inc(atomic_long_t *l)
+ {
+ atomic64_t *v = (atomic64_t *)l;
+@@ -45,6 +69,15 @@ static inline void atomic_long_inc(atomi
+ atomic64_inc(v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_inc_unchecked(atomic_long_unchecked_t *l)
++{
++ atomic64_unchecked_t *v = (atomic64_unchecked_t *)l;
++
++ atomic64_inc_unchecked(v);
++}
++#endif
++
+ static inline void atomic_long_dec(atomic_long_t *l)
+ {
+ atomic64_t *v = (atomic64_t *)l;
+@@ -52,6 +85,15 @@ static inline void atomic_long_dec(atomi
+ atomic64_dec(v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_dec_unchecked(atomic_long_unchecked_t *l)
++{
++ atomic64_unchecked_t *v = (atomic64_unchecked_t *)l;
++
++ atomic64_dec_unchecked(v);
++}
++#endif
++
+ static inline void atomic_long_add(long i, atomic_long_t *l)
+ {
+ atomic64_t *v = (atomic64_t *)l;
+@@ -59,6 +101,15 @@ static inline void atomic_long_add(long
+ atomic64_add(i, v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_add_unchecked(long i, atomic_long_unchecked_t *l)
++{
++ atomic64_unchecked_t *v = (atomic64_unchecked_t *)l;
++
++ atomic64_add_unchecked(i, v);
++}
++#endif
++
+ static inline void atomic_long_sub(long i, atomic_long_t *l)
+ {
+ atomic64_t *v = (atomic64_t *)l;
+@@ -66,6 +117,15 @@ static inline void atomic_long_sub(long
+ atomic64_sub(i, v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_sub_unchecked(long i, atomic_long_unchecked_t *l)
++{
++ atomic64_unchecked_t *v = (atomic64_unchecked_t *)l;
++
++ atomic64_sub_unchecked(i, v);
++}
++#endif
++
+ static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
+ {
+ atomic64_t *v = (atomic64_t *)l;
+@@ -115,6 +175,15 @@ static inline long atomic_long_inc_retur
+ return (long)atomic64_inc_return(v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline long atomic_long_inc_return_unchecked(atomic_long_unchecked_t *l)
++{
++ atomic64_unchecked_t *v = (atomic64_unchecked_t *)l;
++
++ return (long)atomic64_inc_return_unchecked(v);
++}
++#endif
++
+ static inline long atomic_long_dec_return(atomic_long_t *l)
+ {
+ atomic64_t *v = (atomic64_t *)l;
+@@ -140,6 +209,12 @@ static inline long atomic_long_add_unles
+
+ typedef atomic_t atomic_long_t;
+
++#ifdef CONFIG_PAX_REFCOUNT
++typedef atomic_unchecked_t atomic_long_unchecked_t;
++#else
++typedef atomic_t atomic_long_unchecked_t;
++#endif
++
+ #define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i)
+ static inline long atomic_long_read(atomic_long_t *l)
+ {
+@@ -148,6 +223,15 @@ static inline long atomic_long_read(atom
+ return (long)atomic_read(v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline long atomic_long_read_unchecked(atomic_long_unchecked_t *l)
++{
++ atomic_unchecked_t *v = (atomic_unchecked_t *)l;
++
++ return (long)atomic_read_unchecked(v);
++}
++#endif
++
+ static inline void atomic_long_set(atomic_long_t *l, long i)
+ {
+ atomic_t *v = (atomic_t *)l;
+@@ -155,6 +239,15 @@ static inline void atomic_long_set(atomi
+ atomic_set(v, i);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_set_unchecked(atomic_long_unchecked_t *l, long i)
++{
++ atomic_unchecked_t *v = (atomic_unchecked_t *)l;
++
++ atomic_set_unchecked(v, i);
++}
++#endif
++
+ static inline void atomic_long_inc(atomic_long_t *l)
+ {
+ atomic_t *v = (atomic_t *)l;
+@@ -162,6 +255,15 @@ static inline void atomic_long_inc(atomi
+ atomic_inc(v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_inc_unchecked(atomic_long_unchecked_t *l)
++{
++ atomic_unchecked_t *v = (atomic_unchecked_t *)l;
++
++ atomic_inc_unchecked(v);
++}
++#endif
++
+ static inline void atomic_long_dec(atomic_long_t *l)
+ {
+ atomic_t *v = (atomic_t *)l;
+@@ -169,6 +271,15 @@ static inline void atomic_long_dec(atomi
+ atomic_dec(v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_dec_unchecked(atomic_long_unchecked_t *l)
++{
++ atomic_unchecked_t *v = (atomic_unchecked_t *)l;
++
++ atomic_dec_unchecked(v);
++}
++#endif
++
+ static inline void atomic_long_add(long i, atomic_long_t *l)
+ {
+ atomic_t *v = (atomic_t *)l;
+@@ -176,6 +287,15 @@ static inline void atomic_long_add(long
+ atomic_add(i, v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_add_unchecked(long i, atomic_long_unchecked_t *l)
++{
++ atomic_unchecked_t *v = (atomic_unchecked_t *)l;
++
++ atomic_add_unchecked(i, v);
++}
++#endif
++
+ static inline void atomic_long_sub(long i, atomic_long_t *l)
+ {
+ atomic_t *v = (atomic_t *)l;
+@@ -183,6 +303,15 @@ static inline void atomic_long_sub(long
+ atomic_sub(i, v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void atomic_long_sub_unchecked(long i, atomic_long_unchecked_t *l)
++{
++ atomic_unchecked_t *v = (atomic_unchecked_t *)l;
++
++ atomic_sub_unchecked(i, v);
++}
++#endif
++
+ static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
+ {
+ atomic_t *v = (atomic_t *)l;
+@@ -232,6 +361,15 @@ static inline long atomic_long_inc_retur
+ return (long)atomic_inc_return(v);
+ }
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline long atomic_long_inc_return_unchecked(atomic_long_unchecked_t *l)
++{
++ atomic_unchecked_t *v = (atomic_unchecked_t *)l;
++
++ return (long)atomic_inc_return_unchecked(v);
++}
++#endif
++
+ static inline long atomic_long_dec_return(atomic_long_t *l)
+ {
+ atomic_t *v = (atomic_t *)l;
+@@ -255,4 +393,49 @@ static inline long atomic_long_add_unles
+
+ #endif /* BITS_PER_LONG == 64 */
+
++#ifdef CONFIG_PAX_REFCOUNT
++static inline void pax_refcount_needs_these_functions(void)
++{
++ atomic_read_unchecked((atomic_unchecked_t *)NULL);
++ atomic_set_unchecked((atomic_unchecked_t *)NULL, 0);
++ atomic_add_unchecked(0, (atomic_unchecked_t *)NULL);
++ atomic_sub_unchecked(0, (atomic_unchecked_t *)NULL);
++ atomic_inc_unchecked((atomic_unchecked_t *)NULL);
++ atomic_inc_and_test_unchecked((atomic_unchecked_t *)NULL);
++ atomic_inc_return_unchecked((atomic_unchecked_t *)NULL);
++ atomic_add_return_unchecked(0, (atomic_unchecked_t *)NULL);
++ atomic_dec_unchecked((atomic_unchecked_t *)NULL);
++ atomic_cmpxchg_unchecked((atomic_unchecked_t *)NULL, 0, 0);
++ atomic_xchg_unchecked((atomic_unchecked_t *)NULL, 0);
++
++ atomic_long_read_unchecked((atomic_long_unchecked_t *)NULL);
++ atomic_long_set_unchecked((atomic_long_unchecked_t *)NULL, 0);
++ atomic_long_add_unchecked(0, (atomic_long_unchecked_t *)NULL);
++ atomic_long_sub_unchecked(0, (atomic_long_unchecked_t *)NULL);
++ atomic_long_inc_unchecked((atomic_long_unchecked_t *)NULL);
++ atomic_long_inc_return_unchecked((atomic_long_unchecked_t *)NULL);
++ atomic_long_dec_unchecked((atomic_long_unchecked_t *)NULL);
++}
++#else
++#define atomic_read_unchecked(v) atomic_read(v)
++#define atomic_set_unchecked(v, i) atomic_set((v), (i))
++#define atomic_add_unchecked(i, v) atomic_add((i), (v))
++#define atomic_sub_unchecked(i, v) atomic_sub((i), (v))
++#define atomic_inc_unchecked(v) atomic_inc(v)
++#define atomic_inc_and_test_unchecked(v) atomic_inc_and_test(v)
++#define atomic_inc_return_unchecked(v) atomic_inc_return(v)
++#define atomic_add_return_unchecked(i, v) atomic_add_return((i), (v))
++#define atomic_dec_unchecked(v) atomic_dec(v)
++#define atomic_cmpxchg_unchecked(v, o, n) atomic_cmpxchg((v), (o), (n))
++#define atomic_xchg_unchecked(v, i) atomic_xchg((v), (i))
++
++#define atomic_long_read_unchecked(v) atomic_long_read(v)
++#define atomic_long_set_unchecked(v, i) atomic_long_set((v), (i))
++#define atomic_long_add_unchecked(i, v) atomic_long_add((i), (v))
++#define atomic_long_sub_unchecked(i, v) atomic_long_sub((i), (v))
++#define atomic_long_inc_unchecked(v) atomic_long_inc(v)
++#define atomic_long_inc_return_unchecked(v) atomic_long_inc_return(v)
++#define atomic_long_dec_unchecked(v) atomic_long_dec(v)
++#endif
++
+ #endif /* _ASM_GENERIC_ATOMIC_LONG_H */
+diff -urNp linux-2.6.38.7/include/asm-generic/cache.h linux-2.6.38.7/include/asm-generic/cache.h
+--- linux-2.6.38.7/include/asm-generic/cache.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/cache.h 2011-04-28 19:57:25.000000000 -0400
+@@ -6,7 +6,7 @@
+ * cache lines need to provide their own cache.h.
+ */
+
+-#define L1_CACHE_SHIFT 5
+-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
++#define L1_CACHE_SHIFT 5U
++#define L1_CACHE_BYTES (1U << L1_CACHE_SHIFT)
+
+ #endif /* __ASM_GENERIC_CACHE_H */
+diff -urNp linux-2.6.38.7/include/asm-generic/dma-mapping-common.h linux-2.6.38.7/include/asm-generic/dma-mapping-common.h
+--- linux-2.6.38.7/include/asm-generic/dma-mapping-common.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/dma-mapping-common.h 2011-04-28 19:34:15.000000000 -0400
+@@ -11,7 +11,7 @@ static inline dma_addr_t dma_map_single_
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ dma_addr_t addr;
+
+ kmemcheck_mark_initialized(ptr, size);
+@@ -30,7 +30,7 @@ static inline void dma_unmap_single_attr
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ if (ops->unmap_page)
+@@ -42,7 +42,7 @@ static inline int dma_map_sg_attrs(struc
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ int i, ents;
+ struct scatterlist *s;
+
+@@ -59,7 +59,7 @@ static inline void dma_unmap_sg_attrs(st
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ debug_dma_unmap_sg(dev, sg, nents, dir);
+@@ -71,7 +71,7 @@ static inline dma_addr_t dma_map_page(st
+ size_t offset, size_t size,
+ enum dma_data_direction dir)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+ dma_addr_t addr;
+
+ kmemcheck_mark_initialized(page_address(page) + offset, size);
+@@ -85,7 +85,7 @@ static inline dma_addr_t dma_map_page(st
+ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ if (ops->unmap_page)
+@@ -97,7 +97,7 @@ static inline void dma_sync_single_for_c
+ size_t size,
+ enum dma_data_direction dir)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ if (ops->sync_single_for_cpu)
+@@ -109,7 +109,7 @@ static inline void dma_sync_single_for_d
+ dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ if (ops->sync_single_for_device)
+@@ -139,7 +139,7 @@ static inline void
+ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+ int nelems, enum dma_data_direction dir)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ if (ops->sync_sg_for_cpu)
+@@ -151,7 +151,7 @@ static inline void
+ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+ int nelems, enum dma_data_direction dir)
+ {
+- struct dma_map_ops *ops = get_dma_ops(dev);
++ const struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ if (ops->sync_sg_for_device)
+diff -urNp linux-2.6.38.7/include/asm-generic/futex.h linux-2.6.38.7/include/asm-generic/futex.h
+--- linux-2.6.38.7/include/asm-generic/futex.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/futex.h 2011-04-28 19:34:15.000000000 -0400
+@@ -6,7 +6,7 @@
+ #include <asm/errno.h>
+
+ static inline int
+-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
++futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+ {
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+@@ -48,7 +48,7 @@ futex_atomic_op_inuser (int encoded_op,
+ }
+
+ static inline int
+-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
++futex_atomic_cmpxchg_inatomic(u32 __user *uaddr, int oldval, int newval)
+ {
+ return -ENOSYS;
+ }
+diff -urNp linux-2.6.38.7/include/asm-generic/int-l64.h linux-2.6.38.7/include/asm-generic/int-l64.h
+--- linux-2.6.38.7/include/asm-generic/int-l64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/int-l64.h 2011-04-28 19:34:15.000000000 -0400
+@@ -46,6 +46,8 @@ typedef unsigned int u32;
+ typedef signed long s64;
+ typedef unsigned long u64;
+
++typedef unsigned int intoverflow_t __attribute__ ((mode(TI)));
++
+ #define S8_C(x) x
+ #define U8_C(x) x ## U
+ #define S16_C(x) x
+diff -urNp linux-2.6.38.7/include/asm-generic/int-ll64.h linux-2.6.38.7/include/asm-generic/int-ll64.h
+--- linux-2.6.38.7/include/asm-generic/int-ll64.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/int-ll64.h 2011-04-28 19:34:15.000000000 -0400
+@@ -51,6 +51,8 @@ typedef unsigned int u32;
+ typedef signed long long s64;
+ typedef unsigned long long u64;
+
++typedef unsigned long long intoverflow_t;
++
+ #define S8_C(x) x
+ #define U8_C(x) x ## U
+ #define S16_C(x) x
+diff -urNp linux-2.6.38.7/include/asm-generic/kmap_types.h linux-2.6.38.7/include/asm-generic/kmap_types.h
+--- linux-2.6.38.7/include/asm-generic/kmap_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/kmap_types.h 2011-04-28 19:34:15.000000000 -0400
+@@ -29,10 +29,11 @@ KMAP_D(16) KM_IRQ_PTE,
+ KMAP_D(17) KM_NMI,
+ KMAP_D(18) KM_NMI_PTE,
+ KMAP_D(19) KM_KDB,
++KMAP_D(20) KM_CLEARPAGE,
+ /*
+ * Remember to update debug_kmap_atomic() when adding new kmap types!
+ */
+-KMAP_D(20) KM_TYPE_NR
++KMAP_D(21) KM_TYPE_NR
+ };
+
+ #undef KMAP_D
+diff -urNp linux-2.6.38.7/include/asm-generic/pgtable.h linux-2.6.38.7/include/asm-generic/pgtable.h
+--- linux-2.6.38.7/include/asm-generic/pgtable.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/pgtable.h 2011-04-28 19:34:15.000000000 -0400
+@@ -447,6 +447,14 @@ static inline int pmd_write(pmd_t pmd)
+ #endif /* __HAVE_ARCH_PMD_WRITE */
+ #endif
+
++#ifndef __HAVE_ARCH_PAX_OPEN_KERNEL
++static inline unsigned long pax_open_kernel(void) { return 0; }
++#endif
++
++#ifndef __HAVE_ARCH_PAX_CLOSE_KERNEL
++static inline unsigned long pax_close_kernel(void) { return 0; }
++#endif
++
+ #endif /* !__ASSEMBLY__ */
+
+ #endif /* _ASM_GENERIC_PGTABLE_H */
+diff -urNp linux-2.6.38.7/include/asm-generic/pgtable-nopmd.h linux-2.6.38.7/include/asm-generic/pgtable-nopmd.h
+--- linux-2.6.38.7/include/asm-generic/pgtable-nopmd.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/pgtable-nopmd.h 2011-04-28 19:34:15.000000000 -0400
+@@ -1,14 +1,19 @@
+ #ifndef _PGTABLE_NOPMD_H
+ #define _PGTABLE_NOPMD_H
+
+-#ifndef __ASSEMBLY__
+-
+ #include <asm-generic/pgtable-nopud.h>
+
+-struct mm_struct;
+-
+ #define __PAGETABLE_PMD_FOLDED
+
++#define PMD_SHIFT PUD_SHIFT
++#define PTRS_PER_PMD 1
++#define PMD_SIZE (_AC(1,UL) << PMD_SHIFT)
++#define PMD_MASK (~(PMD_SIZE-1))
++
++#ifndef __ASSEMBLY__
++
++struct mm_struct;
++
+ /*
+ * Having the pmd type consist of a pud gets the size right, and allows
+ * us to conceptually access the pud entry that this pmd is folded into
+@@ -16,11 +21,6 @@ struct mm_struct;
+ */
+ typedef struct { pud_t pud; } pmd_t;
+
+-#define PMD_SHIFT PUD_SHIFT
+-#define PTRS_PER_PMD 1
+-#define PMD_SIZE (1UL << PMD_SHIFT)
+-#define PMD_MASK (~(PMD_SIZE-1))
+-
+ /*
+ * The "pud_xxx()" functions here are trivial for a folded two-level
+ * setup: the pmd is never bad, and a pmd always exists (as it's folded
+diff -urNp linux-2.6.38.7/include/asm-generic/pgtable-nopud.h linux-2.6.38.7/include/asm-generic/pgtable-nopud.h
+--- linux-2.6.38.7/include/asm-generic/pgtable-nopud.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/pgtable-nopud.h 2011-04-28 19:34:15.000000000 -0400
+@@ -1,10 +1,15 @@
+ #ifndef _PGTABLE_NOPUD_H
+ #define _PGTABLE_NOPUD_H
+
+-#ifndef __ASSEMBLY__
+-
+ #define __PAGETABLE_PUD_FOLDED
+
++#define PUD_SHIFT PGDIR_SHIFT
++#define PTRS_PER_PUD 1
++#define PUD_SIZE (_AC(1,UL) << PUD_SHIFT)
++#define PUD_MASK (~(PUD_SIZE-1))
++
++#ifndef __ASSEMBLY__
++
+ /*
+ * Having the pud type consist of a pgd gets the size right, and allows
+ * us to conceptually access the pgd entry that this pud is folded into
+@@ -12,11 +17,6 @@
+ */
+ typedef struct { pgd_t pgd; } pud_t;
+
+-#define PUD_SHIFT PGDIR_SHIFT
+-#define PTRS_PER_PUD 1
+-#define PUD_SIZE (1UL << PUD_SHIFT)
+-#define PUD_MASK (~(PUD_SIZE-1))
+-
+ /*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pud is never bad, and a pud always exists (as it's folded
+diff -urNp linux-2.6.38.7/include/asm-generic/vmlinux.lds.h linux-2.6.38.7/include/asm-generic/vmlinux.lds.h
+--- linux-2.6.38.7/include/asm-generic/vmlinux.lds.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/asm-generic/vmlinux.lds.h 2011-04-28 19:34:15.000000000 -0400
+@@ -213,6 +213,7 @@
+ .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start_rodata) = .; \
+ *(.rodata) *(.rodata.*) \
++ *(.data..read_only) \
+ *(__vermagic) /* Kernel version magic */ \
+ . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .; \
+@@ -696,14 +697,15 @@
+ * section in the linker script will go there too. @phdr should have
+ * a leading colon.
+ *
+- * Note that this macros defines __per_cpu_load as an absolute symbol.
++ * Note that this macros defines per_cpu_load as an absolute symbol.
+ * If there is no need to put the percpu section at a predetermined
+ * address, use PERCPU().
+ */
+ #define PERCPU_VADDR(vaddr, phdr) \
+- VMLINUX_SYMBOL(__per_cpu_load) = .; \
+- .data..percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \
++ per_cpu_load = .; \
++ .data..percpu vaddr : AT(VMLINUX_SYMBOL(per_cpu_load) \
+ - LOAD_OFFSET) { \
++ VMLINUX_SYMBOL(__per_cpu_load) = . + per_cpu_load; \
+ VMLINUX_SYMBOL(__per_cpu_start) = .; \
+ *(.data..percpu..first) \
+ . = ALIGN(PAGE_SIZE); \
+@@ -713,7 +715,7 @@
+ *(.data..percpu..shared_aligned) \
+ VMLINUX_SYMBOL(__per_cpu_end) = .; \
+ } phdr \
+- . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data..percpu);
++ . = VMLINUX_SYMBOL(per_cpu_load) + SIZEOF(.data..percpu);
+
+ /**
+ * PERCPU - define output section for percpu area, simple version
+diff -urNp linux-2.6.38.7/include/drm/drmP.h linux-2.6.38.7/include/drm/drmP.h
+--- linux-2.6.38.7/include/drm/drmP.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/drm/drmP.h 2011-04-28 19:34:15.000000000 -0400
+@@ -73,6 +73,7 @@
+ #include <linux/workqueue.h>
+ #include <linux/poll.h>
+ #include <asm/pgalloc.h>
++#include <asm/local.h>
+ #include "drm.h"
+
+ #include <linux/idr.h>
+@@ -881,7 +882,7 @@ struct drm_driver {
+ void (*vgaarb_irq)(struct drm_device *dev, bool state);
+
+ /* Driver private ops for this object */
+- struct vm_operations_struct *gem_vm_ops;
++ const struct vm_operations_struct *gem_vm_ops;
+
+ int major;
+ int minor;
+@@ -894,7 +895,7 @@ struct drm_driver {
+ int dev_priv_size;
+ struct drm_ioctl_desc *ioctls;
+ int num_ioctls;
+- struct file_operations fops;
++ const struct file_operations fops;
+ struct pci_driver pci_driver;
+ struct platform_device *platform_device;
+ /* List of devices hanging off this driver */
+@@ -991,7 +992,7 @@ struct drm_device {
+
+ /** \name Usage Counters */
+ /*@{ */
+- int open_count; /**< Outstanding files open */
++ local_t open_count; /**< Outstanding files open */
+ atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
+ atomic_t vma_count; /**< Outstanding vma areas open */
+ int buf_use; /**< Buffers in use -- cannot alloc */
+@@ -1002,7 +1003,7 @@ struct drm_device {
+ /*@{ */
+ unsigned long counters;
+ enum drm_stat_type types[15];
+- atomic_t counts[15];
++ atomic_unchecked_t counts[15];
+ /*@} */
+
+ struct list_head filelist;
+@@ -1101,7 +1102,7 @@ struct drm_device {
+ struct platform_device *platformdev; /**< Platform device struture */
+
+ struct drm_sg_mem *sg; /**< Scatter gather memory */
+- unsigned int num_crtcs; /**< Number of CRTCs on this device */
++ unsigned int num_crtcs; /**< Number of CRTCs on this device */
+ void *dev_private; /**< device private data */
+ void *mm_private;
+ struct address_space *dev_mapping;
+diff -urNp linux-2.6.38.7/include/linux/a.out.h linux-2.6.38.7/include/linux/a.out.h
+--- linux-2.6.38.7/include/linux/a.out.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/a.out.h 2011-04-28 19:34:15.000000000 -0400
+@@ -39,6 +39,14 @@ enum machine_type {
+ M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
+ };
+
++/* Constants for the N_FLAGS field */
++#define F_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
++#define F_PAX_EMUTRAMP 2 /* Emulate trampolines */
++#define F_PAX_MPROTECT 4 /* Restrict mprotect() */
++#define F_PAX_RANDMMAP 8 /* Randomize mmap() base */
++/*#define F_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
++#define F_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
++
+ #if !defined (N_MAGIC)
+ #define N_MAGIC(exec) ((exec).a_info & 0xffff)
+ #endif
+diff -urNp linux-2.6.38.7/include/linux/atmdev.h linux-2.6.38.7/include/linux/atmdev.h
+--- linux-2.6.38.7/include/linux/atmdev.h 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/include/linux/atmdev.h 2011-04-28 19:34:15.000000000 -0400
+@@ -237,7 +237,7 @@ struct compat_atm_iobuf {
+ #endif
+
+ struct k_atm_aal_stats {
+-#define __HANDLE_ITEM(i) atomic_t i
++#define __HANDLE_ITEM(i) atomic_unchecked_t i
+ __AAL_STAT_ITEMS
+ #undef __HANDLE_ITEM
+ };
+diff -urNp linux-2.6.38.7/include/linux/binfmts.h linux-2.6.38.7/include/linux/binfmts.h
+--- linux-2.6.38.7/include/linux/binfmts.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/binfmts.h 2011-04-28 19:34:15.000000000 -0400
+@@ -92,6 +92,7 @@ struct linux_binfmt {
+ int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
+ int (*load_shlib)(struct file *);
+ int (*core_dump)(struct coredump_params *cprm);
++ void (*handle_mprotect)(struct vm_area_struct *vma, unsigned long newflags);
+ unsigned long min_coredump; /* minimal dump size */
+ };
+
+diff -urNp linux-2.6.38.7/include/linux/blkdev.h linux-2.6.38.7/include/linux/blkdev.h
+--- linux-2.6.38.7/include/linux/blkdev.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/blkdev.h 2011-04-28 19:34:15.000000000 -0400
+@@ -1247,22 +1247,22 @@ queue_max_integrity_segments(struct requ
+ #endif /* CONFIG_BLK_DEV_INTEGRITY */
+
+ struct block_device_operations {
+- int (*open) (struct block_device *, fmode_t);
+- int (*release) (struct gendisk *, fmode_t);
+- int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
+- int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
+- int (*direct_access) (struct block_device *, sector_t,
++ int (* const open) (struct block_device *, fmode_t);
++ int (* const release) (struct gendisk *, fmode_t);
++ int (* const ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
++ int (* const compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
++ int (* const direct_access) (struct block_device *, sector_t,
+ void **, unsigned long *);
+- unsigned int (*check_events) (struct gendisk *disk,
++ unsigned int (* const check_events) (struct gendisk *disk,
+ unsigned int clearing);
+ /* ->media_changed() is DEPRECATED, use ->check_events() instead */
+- int (*media_changed) (struct gendisk *);
+- void (*unlock_native_capacity) (struct gendisk *);
+- int (*revalidate_disk) (struct gendisk *);
+- int (*getgeo)(struct block_device *, struct hd_geometry *);
++ int (* const media_changed) (struct gendisk *);
++ void (* const unlock_native_capacity) (struct gendisk *);
++ int (* const revalidate_disk) (struct gendisk *);
++ int (* const getgeo)(struct block_device *, struct hd_geometry *);
+ /* this callback is with swap_lock and sometimes page table lock held */
+- void (*swap_slot_free_notify) (struct block_device *, unsigned long);
+- struct module *owner;
++ void (* const swap_slot_free_notify) (struct block_device *, unsigned long);
++ struct module * const owner;
+ };
+
+ extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int,
+diff -urNp linux-2.6.38.7/include/linux/blktrace_api.h linux-2.6.38.7/include/linux/blktrace_api.h
+--- linux-2.6.38.7/include/linux/blktrace_api.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/blktrace_api.h 2011-04-28 19:57:25.000000000 -0400
+@@ -161,7 +161,7 @@ struct blk_trace {
+ struct dentry *dir;
+ struct dentry *dropped_file;
+ struct dentry *msg_file;
+- atomic_t dropped;
++ atomic_unchecked_t dropped;
+ };
+
+ extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
+diff -urNp linux-2.6.38.7/include/linux/byteorder/little_endian.h linux-2.6.38.7/include/linux/byteorder/little_endian.h
+--- linux-2.6.38.7/include/linux/byteorder/little_endian.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/byteorder/little_endian.h 2011-04-28 19:34:15.000000000 -0400
+@@ -42,51 +42,51 @@
+
+ static inline __le64 __cpu_to_le64p(const __u64 *p)
+ {
+- return (__force __le64)*p;
++ return (__force const __le64)*p;
+ }
+ static inline __u64 __le64_to_cpup(const __le64 *p)
+ {
+- return (__force __u64)*p;
++ return (__force const __u64)*p;
+ }
+ static inline __le32 __cpu_to_le32p(const __u32 *p)
+ {
+- return (__force __le32)*p;
++ return (__force const __le32)*p;
+ }
+ static inline __u32 __le32_to_cpup(const __le32 *p)
+ {
+- return (__force __u32)*p;
++ return (__force const __u32)*p;
+ }
+ static inline __le16 __cpu_to_le16p(const __u16 *p)
+ {
+- return (__force __le16)*p;
++ return (__force const __le16)*p;
+ }
+ static inline __u16 __le16_to_cpup(const __le16 *p)
+ {
+- return (__force __u16)*p;
++ return (__force const __u16)*p;
+ }
+ static inline __be64 __cpu_to_be64p(const __u64 *p)
+ {
+- return (__force __be64)__swab64p(p);
++ return (__force const __be64)__swab64p(p);
+ }
+ static inline __u64 __be64_to_cpup(const __be64 *p)
+ {
+- return __swab64p((__u64 *)p);
++ return __swab64p((const __u64 *)p);
+ }
+ static inline __be32 __cpu_to_be32p(const __u32 *p)
+ {
+- return (__force __be32)__swab32p(p);
++ return (__force const __be32)__swab32p(p);
+ }
+ static inline __u32 __be32_to_cpup(const __be32 *p)
+ {
+- return __swab32p((__u32 *)p);
++ return __swab32p((const __u32 *)p);
+ }
+ static inline __be16 __cpu_to_be16p(const __u16 *p)
+ {
+- return (__force __be16)__swab16p(p);
++ return (__force const __be16)__swab16p(p);
+ }
+ static inline __u16 __be16_to_cpup(const __be16 *p)
+ {
+- return __swab16p((__u16 *)p);
++ return __swab16p((const __u16 *)p);
+ }
+ #define __cpu_to_le64s(x) do { (void)(x); } while (0)
+ #define __le64_to_cpus(x) do { (void)(x); } while (0)
+diff -urNp linux-2.6.38.7/include/linux/cache.h linux-2.6.38.7/include/linux/cache.h
+--- linux-2.6.38.7/include/linux/cache.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/cache.h 2011-04-28 19:34:15.000000000 -0400
+@@ -16,6 +16,10 @@
+ #define __read_mostly
+ #endif
+
++#ifndef __read_only
++#define __read_only __read_mostly
++#endif
++
+ #ifndef ____cacheline_aligned
+ #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
+ #endif
+diff -urNp linux-2.6.38.7/include/linux/capability.h linux-2.6.38.7/include/linux/capability.h
+--- linux-2.6.38.7/include/linux/capability.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/capability.h 2011-04-28 19:34:15.000000000 -0400
+@@ -561,6 +561,7 @@ extern const kernel_cap_t __cap_init_eff
+ (security_real_capable_noaudit((t), (cap)) == 0)
+
+ extern int capable(int cap);
++int capable_nolog(int cap);
+
+ /* audit system wants to get cap info from files as well */
+ struct dentry;
+diff -urNp linux-2.6.38.7/include/linux/compiler-gcc4.h linux-2.6.38.7/include/linux/compiler-gcc4.h
+--- linux-2.6.38.7/include/linux/compiler-gcc4.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/compiler-gcc4.h 2011-04-28 19:34:15.000000000 -0400
+@@ -54,6 +54,10 @@
+
+ #endif
+
++#define __alloc_size(...) __attribute((alloc_size(__VA_ARGS__)))
++#define __bos(ptr, arg) __builtin_object_size((ptr), (arg))
++#define __bos0(ptr) __bos((ptr), 0)
++#define __bos1(ptr) __bos((ptr), 1)
+ #endif
+
+ #if __GNUC_MINOR__ > 0
+diff -urNp linux-2.6.38.7/include/linux/compiler.h linux-2.6.38.7/include/linux/compiler.h
+--- linux-2.6.38.7/include/linux/compiler.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/compiler.h 2011-04-28 19:34:15.000000000 -0400
+@@ -273,6 +273,22 @@ void ftrace_likely_update(struct ftrace_
+ #define __cold
+ #endif
+
++#ifndef __alloc_size
++#define __alloc_size
++#endif
++
++#ifndef __bos
++#define __bos
++#endif
++
++#ifndef __bos0
++#define __bos0
++#endif
++
++#ifndef __bos1
++#define __bos1
++#endif
++
+ /* Simple shorthand for a section definition */
+ #ifndef __section
+ # define __section(S) __attribute__ ((__section__(#S)))
+@@ -306,6 +322,7 @@ void ftrace_likely_update(struct ftrace_
+ * use is to mediate communication between process-level code and irq/NMI
+ * handlers, all running on the same CPU.
+ */
+-#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
++#define ACCESS_ONCE(x) (*(volatile const typeof(x) *)&(x))
++#define ACCESS_ONCE_RW(x) (*(volatile typeof(x) *)&(x))
+
+ #endif /* __LINUX_COMPILER_H */
+diff -urNp linux-2.6.38.7/include/linux/cpuset.h linux-2.6.38.7/include/linux/cpuset.h
+--- linux-2.6.38.7/include/linux/cpuset.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/cpuset.h 2011-04-28 19:34:15.000000000 -0400
+@@ -118,7 +118,7 @@ static inline void put_mems_allowed(void
+ * nodemask.
+ */
+ smp_mb();
+- --ACCESS_ONCE(current->mems_allowed_change_disable);
++ --ACCESS_ONCE_RW(current->mems_allowed_change_disable);
+ }
+
+ static inline void set_mems_allowed(nodemask_t nodemask)
+diff -urNp linux-2.6.38.7/include/linux/decompress/mm.h linux-2.6.38.7/include/linux/decompress/mm.h
+--- linux-2.6.38.7/include/linux/decompress/mm.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/decompress/mm.h 2011-04-28 19:34:15.000000000 -0400
+@@ -77,7 +77,7 @@ static void free(void *where)
+ * warnings when not needed (indeed large_malloc / large_free are not
+ * needed by inflate */
+
+-#define malloc(a) kmalloc(a, GFP_KERNEL)
++#define malloc(a) kmalloc((a), GFP_KERNEL)
+ #define free(a) kfree(a)
+
+ #define large_malloc(a) vmalloc(a)
+diff -urNp linux-2.6.38.7/include/linux/dma-mapping.h linux-2.6.38.7/include/linux/dma-mapping.h
+--- linux-2.6.38.7/include/linux/dma-mapping.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/dma-mapping.h 2011-04-28 19:34:15.000000000 -0400
+@@ -16,40 +16,40 @@ enum dma_data_direction {
+ };
+
+ struct dma_map_ops {
+- void* (*alloc_coherent)(struct device *dev, size_t size,
++ void* (* const alloc_coherent)(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp);
+- void (*free_coherent)(struct device *dev, size_t size,
++ void (* const free_coherent)(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle);
+- dma_addr_t (*map_page)(struct device *dev, struct page *page,
++ dma_addr_t (* const map_page)(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+- void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
++ void (* const unmap_page)(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+- int (*map_sg)(struct device *dev, struct scatterlist *sg,
++ int (* const map_sg)(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+- void (*unmap_sg)(struct device *dev,
++ void (* const unmap_sg)(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+- void (*sync_single_for_cpu)(struct device *dev,
++ void (* const sync_single_for_cpu)(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir);
+- void (*sync_single_for_device)(struct device *dev,
++ void (* const sync_single_for_device)(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir);
+- void (*sync_sg_for_cpu)(struct device *dev,
++ void (* const sync_sg_for_cpu)(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir);
+- void (*sync_sg_for_device)(struct device *dev,
++ void (* const sync_sg_for_device)(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir);
+- int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
+- int (*dma_supported)(struct device *dev, u64 mask);
+- int (*set_dma_mask)(struct device *dev, u64 mask);
+- int is_phys;
++ int (* const mapping_error)(struct device *dev, dma_addr_t dma_addr);
++ int (* const dma_supported)(struct device *dev, u64 mask);
++ int (* set_dma_mask)(struct device *dev, u64 mask);
++ const int is_phys;
+ };
+
+ #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
+diff -urNp linux-2.6.38.7/include/linux/elf.h linux-2.6.38.7/include/linux/elf.h
+--- linux-2.6.38.7/include/linux/elf.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/elf.h 2011-04-28 19:34:15.000000000 -0400
+@@ -49,6 +49,17 @@ typedef __s64 Elf64_Sxword;
+ #define PT_GNU_EH_FRAME 0x6474e550
+
+ #define PT_GNU_STACK (PT_LOOS + 0x474e551)
++#define PT_GNU_RELRO (PT_LOOS + 0x474e552)
++
++#define PT_PAX_FLAGS (PT_LOOS + 0x5041580)
++
++/* Constants for the e_flags field */
++#define EF_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
++#define EF_PAX_EMUTRAMP 2 /* Emulate trampolines */
++#define EF_PAX_MPROTECT 4 /* Restrict mprotect() */
++#define EF_PAX_RANDMMAP 8 /* Randomize mmap() base */
++/*#define EF_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
++#define EF_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
+
+ /*
+ * Extended Numbering
+@@ -106,6 +117,8 @@ typedef __s64 Elf64_Sxword;
+ #define DT_DEBUG 21
+ #define DT_TEXTREL 22
+ #define DT_JMPREL 23
++#define DT_FLAGS 30
++ #define DF_TEXTREL 0x00000004
+ #define DT_ENCODING 32
+ #define OLD_DT_LOOS 0x60000000
+ #define DT_LOOS 0x6000000d
+@@ -252,6 +265,19 @@ typedef struct elf64_hdr {
+ #define PF_W 0x2
+ #define PF_X 0x1
+
++#define PF_PAGEEXEC (1U << 4) /* Enable PAGEEXEC */
++#define PF_NOPAGEEXEC (1U << 5) /* Disable PAGEEXEC */
++#define PF_SEGMEXEC (1U << 6) /* Enable SEGMEXEC */
++#define PF_NOSEGMEXEC (1U << 7) /* Disable SEGMEXEC */
++#define PF_MPROTECT (1U << 8) /* Enable MPROTECT */
++#define PF_NOMPROTECT (1U << 9) /* Disable MPROTECT */
++/*#define PF_RANDEXEC (1U << 10)*/ /* Enable RANDEXEC */
++/*#define PF_NORANDEXEC (1U << 11)*/ /* Disable RANDEXEC */
++#define PF_EMUTRAMP (1U << 12) /* Enable EMUTRAMP */
++#define PF_NOEMUTRAMP (1U << 13) /* Disable EMUTRAMP */
++#define PF_RANDMMAP (1U << 14) /* Enable RANDMMAP */
++#define PF_NORANDMMAP (1U << 15) /* Disable RANDMMAP */
++
+ typedef struct elf32_phdr{
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+@@ -344,6 +370,8 @@ typedef struct elf64_shdr {
+ #define EI_OSABI 7
+ #define EI_PAD 8
+
++#define EI_PAX 14
++
+ #define ELFMAG0 0x7f /* EI_MAG */
+ #define ELFMAG1 'E'
+ #define ELFMAG2 'L'
+@@ -421,6 +449,7 @@ extern Elf32_Dyn _DYNAMIC [];
+ #define elf_note elf32_note
+ #define elf_addr_t Elf32_Off
+ #define Elf_Half Elf32_Half
++#define elf_dyn Elf32_Dyn
+
+ #else
+
+@@ -431,6 +460,7 @@ extern Elf64_Dyn _DYNAMIC [];
+ #define elf_note elf64_note
+ #define elf_addr_t Elf64_Off
+ #define Elf_Half Elf64_Half
++#define elf_dyn Elf64_Dyn
+
+ #endif
+
+diff -urNp linux-2.6.38.7/include/linux/fscache-cache.h linux-2.6.38.7/include/linux/fscache-cache.h
+--- linux-2.6.38.7/include/linux/fscache-cache.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/fscache-cache.h 2011-04-28 19:57:25.000000000 -0400
+@@ -113,7 +113,7 @@ struct fscache_operation {
+ #endif
+ };
+
+-extern atomic_t fscache_op_debug_id;
++extern atomic_unchecked_t fscache_op_debug_id;
+ extern void fscache_op_work_func(struct work_struct *work);
+
+ extern void fscache_enqueue_operation(struct fscache_operation *);
+@@ -133,7 +133,7 @@ static inline void fscache_operation_ini
+ {
+ INIT_WORK(&op->work, fscache_op_work_func);
+ atomic_set(&op->usage, 1);
+- op->debug_id = atomic_inc_return(&fscache_op_debug_id);
++ op->debug_id = atomic_inc_return_unchecked(&fscache_op_debug_id);
+ op->processor = processor;
+ op->release = release;
+ INIT_LIST_HEAD(&op->pend_link);
+diff -urNp linux-2.6.38.7/include/linux/fs.h linux-2.6.38.7/include/linux/fs.h
+--- linux-2.6.38.7/include/linux/fs.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/fs.h 2011-04-28 19:34:15.000000000 -0400
+@@ -105,6 +105,11 @@ struct inodes_stat_t {
+ /* File was opened by fanotify and shouldn't generate fanotify events */
+ #define FMODE_NONOTIFY ((__force fmode_t)0x1000000)
+
++/* Hack for grsec so as not to require read permission simply to execute
++ * a binary
++ */
++#define FMODE_GREXEC ((__force fmode_t)0x2000000)
++
+ /*
+ * The below are the various read and write types that we support. Some of
+ * them include behavioral modifiers that send information down to the
+@@ -581,42 +586,42 @@ typedef int (*read_actor_t)(read_descrip
+ unsigned long, unsigned long);
+
+ struct address_space_operations {
+- int (*writepage)(struct page *page, struct writeback_control *wbc);
+- int (*readpage)(struct file *, struct page *);
+- void (*sync_page)(struct page *);
++ int (* const writepage)(struct page *page, struct writeback_control *wbc);
++ int (* const readpage)(struct file *, struct page *);
++ void (* const sync_page)(struct page *);
+
+ /* Write back some dirty pages from this mapping. */
+- int (*writepages)(struct address_space *, struct writeback_control *);
++ int (* const writepages)(struct address_space *, struct writeback_control *);
+
+ /* Set a page dirty. Return true if this dirtied it */
+- int (*set_page_dirty)(struct page *page);
++ int (* const set_page_dirty)(struct page *page);
+
+- int (*readpages)(struct file *filp, struct address_space *mapping,
++ int (* const readpages)(struct file *filp, struct address_space *mapping,
+ struct list_head *pages, unsigned nr_pages);
+
+- int (*write_begin)(struct file *, struct address_space *mapping,
++ int (* const write_begin)(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata);
+- int (*write_end)(struct file *, struct address_space *mapping,
++ int (* const write_end)(struct file *, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata);
+
+ /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
+- sector_t (*bmap)(struct address_space *, sector_t);
+- void (*invalidatepage) (struct page *, unsigned long);
+- int (*releasepage) (struct page *, gfp_t);
+- void (*freepage)(struct page *);
+- ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
++ sector_t (* const bmap)(struct address_space *, sector_t);
++ void (* const invalidatepage) (struct page *, unsigned long);
++ int (* const releasepage) (struct page *, gfp_t);
++ void (* const freepage)(struct page *);
++ ssize_t (* const direct_IO)(int, struct kiocb *, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs);
+- int (*get_xip_mem)(struct address_space *, pgoff_t, int,
++ int (* const get_xip_mem)(struct address_space *, pgoff_t, int,
+ void **, unsigned long *);
+ /* migrate the contents of a page to the specified target */
+- int (*migratepage) (struct address_space *,
++ int (* const migratepage) (struct address_space *,
+ struct page *, struct page *);
+- int (*launder_page) (struct page *);
+- int (*is_partially_uptodate) (struct page *, read_descriptor_t *,
++ int (* const launder_page) (struct page *);
++ int (* const is_partially_uptodate) (struct page *, read_descriptor_t *,
+ unsigned long);
+- int (*error_remove_page)(struct address_space *, struct page *);
++ int (* const error_remove_page)(struct address_space *, struct page *);
+ };
+
+ /*
+@@ -1059,17 +1064,17 @@ static inline int file_check_writeable(s
+ typedef struct files_struct *fl_owner_t;
+
+ struct file_lock_operations {
+- void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
+- void (*fl_release_private)(struct file_lock *);
++ void (* const fl_copy_lock)(struct file_lock *, struct file_lock *);
++ void (* const fl_release_private)(struct file_lock *);
+ };
+
+ struct lock_manager_operations {
+- int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
+- void (*fl_notify)(struct file_lock *); /* unblock callback */
+- int (*fl_grant)(struct file_lock *, struct file_lock *, int);
+- void (*fl_release_private)(struct file_lock *);
+- void (*fl_break)(struct file_lock *);
+- int (*fl_change)(struct file_lock **, int);
++ int (* const fl_compare_owner)(struct file_lock *, struct file_lock *);
++ void (* const fl_notify)(struct file_lock *); /* unblock callback */
++ int (* const fl_grant)(struct file_lock *, struct file_lock *, int);
++ void (* const fl_release_private)(struct file_lock *);
++ void (* const fl_break)(struct file_lock *);
++ int (* const fl_change)(struct file_lock **, int);
+ };
+
+ struct lock_manager {
+@@ -1604,29 +1609,29 @@ extern ssize_t vfs_writev(struct file *,
+ unsigned long, loff_t *);
+
+ struct super_operations {
+- struct inode *(*alloc_inode)(struct super_block *sb);
+- void (*destroy_inode)(struct inode *);
++ struct inode *(* const alloc_inode)(struct super_block *sb);
++ void (* const destroy_inode)(struct inode *);
+
+- void (*dirty_inode) (struct inode *);
+- int (*write_inode) (struct inode *, struct writeback_control *wbc);
+- int (*drop_inode) (struct inode *);
+- void (*evict_inode) (struct inode *);
+- void (*put_super) (struct super_block *);
+- void (*write_super) (struct super_block *);
+- int (*sync_fs)(struct super_block *sb, int wait);
+- int (*freeze_fs) (struct super_block *);
+- int (*unfreeze_fs) (struct super_block *);
+- int (*statfs) (struct dentry *, struct kstatfs *);
+- int (*remount_fs) (struct super_block *, int *, char *);
+- void (*umount_begin) (struct super_block *);
++ void (* const dirty_inode) (struct inode *);
++ int (* const write_inode) (struct inode *, struct writeback_control *wbc);
++ int (* const drop_inode) (struct inode *);
++ void (* const evict_inode) (struct inode *);
++ void (* const put_super) (struct super_block *);
++ void (* const write_super) (struct super_block *);
++ int (* const sync_fs)(struct super_block *sb, int wait);
++ int (* const freeze_fs) (struct super_block *);
++ int (* const unfreeze_fs) (struct super_block *);
++ int (* const statfs) (struct dentry *, struct kstatfs *);
++ int (* const remount_fs) (struct super_block *, int *, char *);
++ void (* const umount_begin) (struct super_block *);
+
+- int (*show_options)(struct seq_file *, struct vfsmount *);
+- int (*show_stats)(struct seq_file *, struct vfsmount *);
++ int (* const show_options)(struct seq_file *, struct vfsmount *);
++ int (* const show_stats)(struct seq_file *, struct vfsmount *);
+ #ifdef CONFIG_QUOTA
+- ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
+- ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
++ ssize_t (* const quota_read)(struct super_block *, int, char *, size_t, loff_t);
++ ssize_t (* const quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+ #endif
+- int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
++ int (* const bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+ };
+
+ /*
+diff -urNp linux-2.6.38.7/include/linux/fs_struct.h linux-2.6.38.7/include/linux/fs_struct.h
+--- linux-2.6.38.7/include/linux/fs_struct.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/fs_struct.h 2011-04-28 19:34:15.000000000 -0400
+@@ -6,7 +6,7 @@
+ #include <linux/seqlock.h>
+
+ struct fs_struct {
+- int users;
++ atomic_t users;
+ spinlock_t lock;
+ seqcount_t seq;
+ int umask;
+diff -urNp linux-2.6.38.7/include/linux/ftrace_event.h linux-2.6.38.7/include/linux/ftrace_event.h
+--- linux-2.6.38.7/include/linux/ftrace_event.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/ftrace_event.h 2011-05-02 19:07:09.000000000 -0400
+@@ -236,7 +236,7 @@ extern int trace_define_field(struct ftr
+ extern int trace_add_event_call(struct ftrace_event_call *call);
+ extern void trace_remove_event_call(struct ftrace_event_call *call);
+
+-#define is_signed_type(type) (((type)(-1)) < 0)
++#define is_signed_type(type) (((type)(-1)) < (type)1)
+
+ int trace_set_clr_event(const char *system, const char *event, int set);
+
+diff -urNp linux-2.6.38.7/include/linux/genhd.h linux-2.6.38.7/include/linux/genhd.h
+--- linux-2.6.38.7/include/linux/genhd.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/genhd.h 2011-04-28 19:34:15.000000000 -0400
+@@ -183,7 +183,7 @@ struct gendisk {
+ struct kobject *slave_dir;
+
+ struct timer_rand_state *random;
+- atomic_t sync_io; /* RAID */
++ atomic_unchecked_t sync_io; /* RAID */
+ struct disk_events *ev;
+ #ifdef CONFIG_BLK_DEV_INTEGRITY
+ struct blk_integrity *integrity;
+diff -urNp linux-2.6.38.7/include/linux/gracl.h linux-2.6.38.7/include/linux/gracl.h
+--- linux-2.6.38.7/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/include/linux/gracl.h 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,317 @@
++#ifndef GR_ACL_H
++#define GR_ACL_H
++
++#include <linux/grdefs.h>
++#include <linux/resource.h>
++#include <linux/capability.h>
++#include <linux/dcache.h>
++#include <asm/resource.h>
++
++/* Major status information */
++
++#define GR_VERSION "grsecurity 2.2.2"
++#define GRSECURITY_VERSION 0x2202
++
++enum {
++ GR_SHUTDOWN = 0,
++ GR_ENABLE = 1,
++ GR_SPROLE = 2,
++ GR_RELOAD = 3,
++ GR_SEGVMOD = 4,
++ GR_STATUS = 5,
++ GR_UNSPROLE = 6,
++ GR_PASSSET = 7,
++ GR_SPROLEPAM = 8,
++};
++
++/* Password setup definitions
++ * kernel/grhash.c */
++enum {
++ GR_PW_LEN = 128,
++ GR_SALT_LEN = 16,
++ GR_SHA_LEN = 32,
++};
++
++enum {
++ GR_SPROLE_LEN = 64,
++};
++
++enum {
++ GR_NO_GLOB = 0,
++ GR_REG_GLOB,
++ GR_CREATE_GLOB
++};
++
++#define GR_NLIMITS 32
++
++/* Begin Data Structures */
++
++struct sprole_pw {
++ unsigned char *rolename;
++ unsigned char salt[GR_SALT_LEN];
++ unsigned char sum[GR_SHA_LEN]; /* 256-bit SHA hash of the password */
++};
++
++struct name_entry {
++ __u32 key;
++ ino_t inode;
++ dev_t device;
++ char *name;
++ __u16 len;
++ __u8 deleted;
++ struct name_entry *prev;
++ struct name_entry *next;
++};
++
++struct inodev_entry {
++ struct name_entry *nentry;
++ struct inodev_entry *prev;
++ struct inodev_entry *next;
++};
++
++struct acl_role_db {
++ struct acl_role_label **r_hash;
++ __u32 r_size;
++};
++
++struct inodev_db {
++ struct inodev_entry **i_hash;
++ __u32 i_size;
++};
++
++struct name_db {
++ struct name_entry **n_hash;
++ __u32 n_size;
++};
++
++struct crash_uid {
++ uid_t uid;
++ unsigned long expires;
++};
++
++struct gr_hash_struct {
++ void **table;
++ void **nametable;
++ void *first;
++ __u32 table_size;
++ __u32 used_size;
++ int type;
++};
++
++/* Userspace Grsecurity ACL data structures */
++
++struct acl_subject_label {
++ char *filename;
++ ino_t inode;
++ dev_t device;
++ __u32 mode;
++ kernel_cap_t cap_mask;
++ kernel_cap_t cap_lower;
++ kernel_cap_t cap_invert_audit;
++
++ struct rlimit res[GR_NLIMITS];
++ __u32 resmask;
++
++ __u8 user_trans_type;
++ __u8 group_trans_type;
++ uid_t *user_transitions;
++ gid_t *group_transitions;
++ __u16 user_trans_num;
++ __u16 group_trans_num;
++
++ __u32 sock_families[2];
++ __u32 ip_proto[8];
++ __u32 ip_type;
++ struct acl_ip_label **ips;
++ __u32 ip_num;
++ __u32 inaddr_any_override;
++
++ __u32 crashes;
++ unsigned long expires;
++
++ struct acl_subject_label *parent_subject;
++ struct gr_hash_struct *hash;
++ struct acl_subject_label *prev;
++ struct acl_subject_label *next;
++
++ struct acl_object_label **obj_hash;
++ __u32 obj_hash_size;
++ __u16 pax_flags;
++};
++
++struct role_allowed_ip {
++ __u32 addr;
++ __u32 netmask;
++
++ struct role_allowed_ip *prev;
++ struct role_allowed_ip *next;
++};
++
++struct role_transition {
++ char *rolename;
++
++ struct role_transition *prev;
++ struct role_transition *next;
++};
++
++struct acl_role_label {
++ char *rolename;
++ uid_t uidgid;
++ __u16 roletype;
++
++ __u16 auth_attempts;
++ unsigned long expires;
++
++ struct acl_subject_label *root_label;
++ struct gr_hash_struct *hash;
++
++ struct acl_role_label *prev;
++ struct acl_role_label *next;
++
++ struct role_transition *transitions;
++ struct role_allowed_ip *allowed_ips;
++ uid_t *domain_children;
++ __u16 domain_child_num;
++
++ struct acl_subject_label **subj_hash;
++ __u32 subj_hash_size;
++};
++
++struct user_acl_role_db {
++ struct acl_role_label **r_table;
++ __u32 num_pointers; /* Number of allocations to track */
++ __u32 num_roles; /* Number of roles */
++ __u32 num_domain_children; /* Number of domain children */
++ __u32 num_subjects; /* Number of subjects */
++ __u32 num_objects; /* Number of objects */
++};
++
++struct acl_object_label {
++ char *filename;
++ ino_t inode;
++ dev_t device;
++ __u32 mode;
++
++ struct acl_subject_label *nested;
++ struct acl_object_label *globbed;
++
++ /* next two structures not used */
++
++ struct acl_object_label *prev;
++ struct acl_object_label *next;
++};
++
++struct acl_ip_label {
++ char *iface;
++ __u32 addr;
++ __u32 netmask;
++ __u16 low, high;
++ __u8 mode;
++ __u32 type;
++ __u32 proto[8];
++
++ /* next two structures not used */
++
++ struct acl_ip_label *prev;
++ struct acl_ip_label *next;
++};
++
++struct gr_arg {
++ struct user_acl_role_db role_db;
++ unsigned char pw[GR_PW_LEN];
++ unsigned char salt[GR_SALT_LEN];
++ unsigned char sum[GR_SHA_LEN];
++ unsigned char sp_role[GR_SPROLE_LEN];
++ struct sprole_pw *sprole_pws;
++ dev_t segv_device;
++ ino_t segv_inode;
++ uid_t segv_uid;
++ __u16 num_sprole_pws;
++ __u16 mode;
++};
++
++struct gr_arg_wrapper {
++ struct gr_arg *arg;
++ __u32 version;
++ __u32 size;
++};
++
++struct subject_map {
++ struct acl_subject_label *user;
++ struct acl_subject_label *kernel;
++ struct subject_map *prev;
++ struct subject_map *next;
++};
++
++struct acl_subj_map_db {
++ struct subject_map **s_hash;
++ __u32 s_size;
++};
++
++/* End Data Structures Section */
++
++/* Hash functions generated by empirical testing by Brad Spengler
++ Makes good use of the low bits of the inode. Generally 0-1 times
++ in loop for successful match. 0-3 for unsuccessful match.
++ Shift/add algorithm with modulus of table size and an XOR*/
++
++static __inline__ unsigned int
++rhash(const uid_t uid, const __u16 type, const unsigned int sz)
++{
++ return ((((uid + type) << (16 + type)) ^ uid) % sz);
++}
++
++ static __inline__ unsigned int
++shash(const struct acl_subject_label *userp, const unsigned int sz)
++{
++ return ((const unsigned long)userp % sz);
++}
++
++static __inline__ unsigned int
++fhash(const ino_t ino, const dev_t dev, const unsigned int sz)
++{
++ return (((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9))) % sz);
++}
++
++static __inline__ unsigned int
++nhash(const char *name, const __u16 len, const unsigned int sz)
++{
++ return full_name_hash((const unsigned char *)name, len) % sz;
++}
++
++#define FOR_EACH_ROLE_START(role) \
++ role = role_list; \
++ while (role) {
++
++#define FOR_EACH_ROLE_END(role) \
++ role = role->prev; \
++ }
++
++#define FOR_EACH_SUBJECT_START(role,subj,iter) \
++ subj = NULL; \
++ iter = 0; \
++ while (iter < role->subj_hash_size) { \
++ if (subj == NULL) \
++ subj = role->subj_hash[iter]; \
++ if (subj == NULL) { \
++ iter++; \
++ continue; \
++ }
++
++#define FOR_EACH_SUBJECT_END(subj,iter) \
++ subj = subj->next; \
++ if (subj == NULL) \
++ iter++; \
++ }
++
++
++#define FOR_EACH_NESTED_SUBJECT_START(role,subj) \
++ subj = role->hash->first; \
++ while (subj != NULL) {
++
++#define FOR_EACH_NESTED_SUBJECT_END(subj) \
++ subj = subj->next; \
++ }
++
++#endif
++
+diff -urNp linux-2.6.38.7/include/linux/gralloc.h linux-2.6.38.7/include/linux/gralloc.h
+--- linux-2.6.38.7/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/include/linux/gralloc.h 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,9 @@
++#ifndef __GRALLOC_H
++#define __GRALLOC_H
++
++void acl_free_all(void);
++int acl_alloc_stack_init(unsigned long size);
++void *acl_alloc(unsigned long len);
++void *acl_alloc_num(unsigned long num, unsigned long len);
++
++#endif
+diff -urNp linux-2.6.38.7/include/linux/grdefs.h linux-2.6.38.7/include/linux/grdefs.h
+--- linux-2.6.38.7/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/include/linux/grdefs.h 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,139 @@
++#ifndef GRDEFS_H
++#define GRDEFS_H
++
++/* Begin grsecurity status declarations */
++
++enum {
++ GR_READY = 0x01,
++ GR_STATUS_INIT = 0x00 // disabled state
++};
++
++/* Begin ACL declarations */
++
++/* Role flags */
++
++enum {
++ GR_ROLE_USER = 0x0001,
++ GR_ROLE_GROUP = 0x0002,
++ GR_ROLE_DEFAULT = 0x0004,
++ GR_ROLE_SPECIAL = 0x0008,
++ GR_ROLE_AUTH = 0x0010,
++ GR_ROLE_NOPW = 0x0020,
++ GR_ROLE_GOD = 0x0040,
++ GR_ROLE_LEARN = 0x0080,
++ GR_ROLE_TPE = 0x0100,
++ GR_ROLE_DOMAIN = 0x0200,
++ GR_ROLE_PAM = 0x0400,
++ GR_ROLE_PERSIST = 0x0800
++};
++
++/* ACL Subject and Object mode flags */
++enum {
++ GR_DELETED = 0x80000000
++};
++
++/* ACL Object-only mode flags */
++enum {
++ GR_READ = 0x00000001,
++ GR_APPEND = 0x00000002,
++ GR_WRITE = 0x00000004,
++ GR_EXEC = 0x00000008,
++ GR_FIND = 0x00000010,
++ GR_INHERIT = 0x00000020,
++ GR_SETID = 0x00000040,
++ GR_CREATE = 0x00000080,
++ GR_DELETE = 0x00000100,
++ GR_LINK = 0x00000200,
++ GR_AUDIT_READ = 0x00000400,
++ GR_AUDIT_APPEND = 0x00000800,
++ GR_AUDIT_WRITE = 0x00001000,
++ GR_AUDIT_EXEC = 0x00002000,
++ GR_AUDIT_FIND = 0x00004000,
++ GR_AUDIT_INHERIT= 0x00008000,
++ GR_AUDIT_SETID = 0x00010000,
++ GR_AUDIT_CREATE = 0x00020000,
++ GR_AUDIT_DELETE = 0x00040000,
++ GR_AUDIT_LINK = 0x00080000,
++ GR_PTRACERD = 0x00100000,
++ GR_NOPTRACE = 0x00200000,
++ GR_SUPPRESS = 0x00400000,
++ GR_NOLEARN = 0x00800000,
++ GR_INIT_TRANSFER= 0x01000000
++};
++
++#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \
++ GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \
++ GR_AUDIT_CREATE | GR_AUDIT_DELETE | GR_AUDIT_LINK)
++
++/* ACL subject-only mode flags */
++enum {
++ GR_KILL = 0x00000001,
++ GR_VIEW = 0x00000002,
++ GR_PROTECTED = 0x00000004,
++ GR_LEARN = 0x00000008,
++ GR_OVERRIDE = 0x00000010,
++ /* just a placeholder, this mode is only used in userspace */
++ GR_DUMMY = 0x00000020,
++ GR_PROTSHM = 0x00000040,
++ GR_KILLPROC = 0x00000080,
++ GR_KILLIPPROC = 0x00000100,
++ /* just a placeholder, this mode is only used in userspace */
++ GR_NOTROJAN = 0x00000200,
++ GR_PROTPROCFD = 0x00000400,
++ GR_PROCACCT = 0x00000800,
++ GR_RELAXPTRACE = 0x00001000,
++ GR_NESTED = 0x00002000,
++ GR_INHERITLEARN = 0x00004000,
++ GR_PROCFIND = 0x00008000,
++ GR_POVERRIDE = 0x00010000,
++ GR_KERNELAUTH = 0x00020000,
++ GR_ATSECURE = 0x00040000
++};
++
++enum {
++ GR_PAX_ENABLE_SEGMEXEC = 0x0001,
++ GR_PAX_ENABLE_PAGEEXEC = 0x0002,
++ GR_PAX_ENABLE_MPROTECT = 0x0004,
++ GR_PAX_ENABLE_RANDMMAP = 0x0008,
++ GR_PAX_ENABLE_EMUTRAMP = 0x0010,
++ GR_PAX_DISABLE_SEGMEXEC = 0x0100,
++ GR_PAX_DISABLE_PAGEEXEC = 0x0200,
++ GR_PAX_DISABLE_MPROTECT = 0x0400,
++ GR_PAX_DISABLE_RANDMMAP = 0x0800,
++ GR_PAX_DISABLE_EMUTRAMP = 0x1000,
++};
++
++enum {
++ GR_ID_USER = 0x01,
++ GR_ID_GROUP = 0x02,
++};
++
++enum {
++ GR_ID_ALLOW = 0x01,
++ GR_ID_DENY = 0x02,
++};
++
++#define GR_CRASH_RES 31
++#define GR_UIDTABLE_MAX 500
++
++/* begin resource learning section */
++enum {
++ GR_RLIM_CPU_BUMP = 60,
++ GR_RLIM_FSIZE_BUMP = 50000,
++ GR_RLIM_DATA_BUMP = 10000,
++ GR_RLIM_STACK_BUMP = 1000,
++ GR_RLIM_CORE_BUMP = 10000,
++ GR_RLIM_RSS_BUMP = 500000,
++ GR_RLIM_NPROC_BUMP = 1,
++ GR_RLIM_NOFILE_BUMP = 5,
++ GR_RLIM_MEMLOCK_BUMP = 50000,
++ GR_RLIM_AS_BUMP = 500000,
++ GR_RLIM_LOCKS_BUMP = 2,
++ GR_RLIM_SIGPENDING_BUMP = 5,
++ GR_RLIM_MSGQUEUE_BUMP = 10000,
++ GR_RLIM_NICE_BUMP = 1,
++ GR_RLIM_RTPRIO_BUMP = 1,
++ GR_RLIM_RTTIME_BUMP = 1000000
++};
++
++#endif
+diff -urNp linux-2.6.38.7/include/linux/grinternal.h linux-2.6.38.7/include/linux/grinternal.h
+--- linux-2.6.38.7/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/include/linux/grinternal.h 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,219 @@
++#ifndef __GRINTERNAL_H
++#define __GRINTERNAL_H
++
++#ifdef CONFIG_GRKERNSEC
++
++#include <linux/fs.h>
++#include <linux/mnt_namespace.h>
++#include <linux/nsproxy.h>
++#include <linux/gracl.h>
++#include <linux/grdefs.h>
++#include <linux/grmsg.h>
++
++void gr_add_learn_entry(const char *fmt, ...)
++ __attribute__ ((format (printf, 1, 2)));
++__u32 gr_search_file(const struct dentry *dentry, const __u32 mode,
++ const struct vfsmount *mnt);
++__u32 gr_check_create(const struct dentry *new_dentry,
++ const struct dentry *parent,
++ const struct vfsmount *mnt, const __u32 mode);
++int gr_check_protected_task(const struct task_struct *task);
++__u32 to_gr_audit(const __u32 reqmode);
++int gr_set_acls(const int type);
++int gr_apply_subject_to_task(struct task_struct *task);
++int gr_acl_is_enabled(void);
++char gr_roletype_to_char(void);
++
++void gr_handle_alertkill(struct task_struct *task);
++char *gr_to_filename(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++char *gr_to_filename1(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++char *gr_to_filename2(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++char *gr_to_filename3(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++
++extern int grsec_enable_harden_ptrace;
++extern int grsec_enable_link;
++extern int grsec_enable_fifo;
++extern int grsec_enable_execve;
++extern int grsec_enable_shm;
++extern int grsec_enable_execlog;
++extern int grsec_enable_signal;
++extern int grsec_enable_audit_ptrace;
++extern int grsec_enable_forkfail;
++extern int grsec_enable_time;
++extern int grsec_enable_rofs;
++extern int grsec_enable_chroot_shmat;
++extern int grsec_enable_chroot_findtask;
++extern int grsec_enable_chroot_mount;
++extern int grsec_enable_chroot_double;
++extern int grsec_enable_chroot_pivot;
++extern int grsec_enable_chroot_chdir;
++extern int grsec_enable_chroot_chmod;
++extern int grsec_enable_chroot_mknod;
++extern int grsec_enable_chroot_fchdir;
++extern int grsec_enable_chroot_nice;
++extern int grsec_enable_chroot_execlog;
++extern int grsec_enable_chroot_caps;
++extern int grsec_enable_chroot_sysctl;
++extern int grsec_enable_chroot_unix;
++extern int grsec_enable_tpe;
++extern int grsec_tpe_gid;
++extern int grsec_enable_tpe_all;
++extern int grsec_enable_tpe_invert;
++extern int grsec_enable_socket_all;
++extern int grsec_socket_all_gid;
++extern int grsec_enable_socket_client;
++extern int grsec_socket_client_gid;
++extern int grsec_enable_socket_server;
++extern int grsec_socket_server_gid;
++extern int grsec_audit_gid;
++extern int grsec_enable_group;
++extern int grsec_enable_audit_textrel;
++extern int grsec_enable_log_rwxmaps;
++extern int grsec_enable_mount;
++extern int grsec_enable_chdir;
++extern int grsec_resource_logging;
++extern int grsec_enable_blackhole;
++extern int grsec_lastack_retries;
++extern int grsec_lock;
++
++extern spinlock_t grsec_alert_lock;
++extern unsigned long grsec_alert_wtime;
++extern unsigned long grsec_alert_fyet;
++
++extern spinlock_t grsec_audit_lock;
++
++extern rwlock_t grsec_exec_file_lock;
++
++#define gr_task_fullpath(tsk) ((tsk)->exec_file ? \
++ gr_to_filename2((tsk)->exec_file->f_path.dentry, \
++ (tsk)->exec_file->f_vfsmnt) : "/")
++
++#define gr_parent_task_fullpath(tsk) ((tsk)->real_parent->exec_file ? \
++ gr_to_filename3((tsk)->real_parent->exec_file->f_path.dentry, \
++ (tsk)->real_parent->exec_file->f_vfsmnt) : "/")
++
++#define gr_task_fullpath0(tsk) ((tsk)->exec_file ? \
++ gr_to_filename((tsk)->exec_file->f_path.dentry, \
++ (tsk)->exec_file->f_vfsmnt) : "/")
++
++#define gr_parent_task_fullpath0(tsk) ((tsk)->real_parent->exec_file ? \
++ gr_to_filename1((tsk)->real_parent->exec_file->f_path.dentry, \
++ (tsk)->real_parent->exec_file->f_vfsmnt) : "/")
++
++#define proc_is_chrooted(tsk_a) ((tsk_a)->gr_is_chrooted)
++
++#define have_same_root(tsk_a,tsk_b) ((tsk_a)->gr_chroot_dentry == (tsk_b)->gr_chroot_dentry)
++
++#define DEFAULTSECARGS(task, cred, pcred) gr_task_fullpath(task), (task)->comm, \
++ (task)->pid, (cred)->uid, \
++ (cred)->euid, (cred)->gid, (cred)->egid, \
++ gr_parent_task_fullpath(task), \
++ (task)->real_parent->comm, (task)->real_parent->pid, \
++ (pcred)->uid, (pcred)->euid, \
++ (pcred)->gid, (pcred)->egid
++
++#define GR_CHROOT_CAPS {{ \
++ CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \
++ CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \
++ CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \
++ CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \
++ CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \
++ CAP_TO_MASK(CAP_IPC_OWNER) , 0 }}
++
++#define security_learn(normal_msg,args...) \
++({ \
++ read_lock(&grsec_exec_file_lock); \
++ gr_add_learn_entry(normal_msg "\n", ## args); \
++ read_unlock(&grsec_exec_file_lock); \
++})
++
++enum {
++ GR_DO_AUDIT,
++ GR_DONT_AUDIT,
++ /* used for non-audit messages that we shouldn't kill the task on */
++ GR_DONT_AUDIT_GOOD
++};
++
++enum {
++ GR_TTYSNIFF,
++ GR_RBAC,
++ GR_RBAC_STR,
++ GR_STR_RBAC,
++ GR_RBAC_MODE2,
++ GR_RBAC_MODE3,
++ GR_FILENAME,
++ GR_SYSCTL_HIDDEN,
++ GR_NOARGS,
++ GR_ONE_INT,
++ GR_ONE_INT_TWO_STR,
++ GR_ONE_STR,
++ GR_STR_INT,
++ GR_TWO_STR_INT,
++ GR_TWO_INT,
++ GR_TWO_U64,
++ GR_THREE_INT,
++ GR_FIVE_INT_TWO_STR,
++ GR_TWO_STR,
++ GR_THREE_STR,
++ GR_FOUR_STR,
++ GR_STR_FILENAME,
++ GR_FILENAME_STR,
++ GR_FILENAME_TWO_INT,
++ GR_FILENAME_TWO_INT_STR,
++ GR_TEXTREL,
++ GR_PTRACE,
++ GR_RESOURCE,
++ GR_CAP,
++ GR_SIG,
++ GR_SIG2,
++ GR_CRASH1,
++ GR_CRASH2,
++ GR_PSACCT,
++ GR_RWXMAP
++};
++
++#define gr_log_hidden_sysctl(audit, msg, str) gr_log_varargs(audit, msg, GR_SYSCTL_HIDDEN, str)
++#define gr_log_ttysniff(audit, msg, task) gr_log_varargs(audit, msg, GR_TTYSNIFF, task)
++#define gr_log_fs_rbac_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_RBAC, dentry, mnt)
++#define gr_log_fs_rbac_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_RBAC_STR, dentry, mnt, str)
++#define gr_log_fs_str_rbac(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_RBAC, str, dentry, mnt)
++#define gr_log_fs_rbac_mode2(audit, msg, dentry, mnt, str1, str2) gr_log_varargs(audit, msg, GR_RBAC_MODE2, dentry, mnt, str1, str2)
++#define gr_log_fs_rbac_mode3(audit, msg, dentry, mnt, str1, str2, str3) gr_log_varargs(audit, msg, GR_RBAC_MODE3, dentry, mnt, str1, str2, str3)
++#define gr_log_fs_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_FILENAME, dentry, mnt)
++#define gr_log_noargs(audit, msg) gr_log_varargs(audit, msg, GR_NOARGS)
++#define gr_log_int(audit, msg, num) gr_log_varargs(audit, msg, GR_ONE_INT, num)
++#define gr_log_int_str2(audit, msg, num, str1, str2) gr_log_varargs(audit, msg, GR_ONE_INT_TWO_STR, num, str1, str2)
++#define gr_log_str(audit, msg, str) gr_log_varargs(audit, msg, GR_ONE_STR, str)
++#define gr_log_str_int(audit, msg, str, num) gr_log_varargs(audit, msg, GR_STR_INT, str, num)
++#define gr_log_int_int(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_INT, num1, num2)
++#define gr_log_two_u64(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_U64, num1, num2)
++#define gr_log_int3(audit, msg, num1, num2, num3) gr_log_varargs(audit, msg, GR_THREE_INT, num1, num2, num3)
++#define gr_log_int5_str2(audit, msg, num1, num2, str1, str2) gr_log_varargs(audit, msg, GR_FIVE_INT_TWO_STR, num1, num2, str1, str2)
++#define gr_log_str_str(audit, msg, str1, str2) gr_log_varargs(audit, msg, GR_TWO_STR, str1, str2)
++#define gr_log_str2_int(audit, msg, str1, str2, num) gr_log_varargs(audit, msg, GR_TWO_STR_INT, str1, str2, num)
++#define gr_log_str3(audit, msg, str1, str2, str3) gr_log_varargs(audit, msg, GR_THREE_STR, str1, str2, str3)
++#define gr_log_str4(audit, msg, str1, str2, str3, str4) gr_log_varargs(audit, msg, GR_FOUR_STR, str1, str2, str3, str4)
++#define gr_log_str_fs(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_FILENAME, str, dentry, mnt)
++#define gr_log_fs_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_FILENAME_STR, dentry, mnt, str)
++#define gr_log_fs_int2(audit, msg, dentry, mnt, num1, num2) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT, dentry, mnt, num1, num2)
++#define gr_log_fs_int2_str(audit, msg, dentry, mnt, num1, num2, str) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT_STR, dentry, mnt, num1, num2, str)
++#define gr_log_textrel_ulong_ulong(audit, msg, file, ulong1, ulong2) gr_log_varargs(audit, msg, GR_TEXTREL, file, ulong1, ulong2)
++#define gr_log_ptrace(audit, msg, task) gr_log_varargs(audit, msg, GR_PTRACE, task)
++#define gr_log_res_ulong2_str(audit, msg, task, ulong1, str, ulong2) gr_log_varargs(audit, msg, GR_RESOURCE, task, ulong1, str, ulong2)
++#define gr_log_cap(audit, msg, task, str) gr_log_varargs(audit, msg, GR_CAP, task, str)
++#define gr_log_sig_addr(audit, msg, str, addr) gr_log_varargs(audit, msg, GR_SIG, str, addr)
++#define gr_log_sig_task(audit, msg, task, num) gr_log_varargs(audit, msg, GR_SIG2, task, num)
++#define gr_log_crash1(audit, msg, task, ulong) gr_log_varargs(audit, msg, GR_CRASH1, task, ulong)
++#define gr_log_crash2(audit, msg, task, ulong1) gr_log_varargs(audit, msg, GR_CRASH2, task, ulong1)
++#define gr_log_procacct(audit, msg, task, num1, num2, num3, num4, num5, num6, num7, num8, num9) gr_log_varargs(audit, msg, GR_PSACCT, task, num1, num2, num3, num4, num5, num6, num7, num8, num9)
++#define gr_log_rwxmap(audit, msg, str) gr_log_varargs(audit, msg, GR_RWXMAP, str)
++
++void gr_log_varargs(int audit, const char *msg, int argtypes, ...);
++
++#endif
++
++#endif
+diff -urNp linux-2.6.38.7/include/linux/grmsg.h linux-2.6.38.7/include/linux/grmsg.h
+--- linux-2.6.38.7/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/include/linux/grmsg.h 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,108 @@
++#define DEFAULTSECMSG "%.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u, parent %.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u"
++#define GR_ACL_PROCACCT_MSG "%.256s[%.16s:%d] IP:%pI4 TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u run time:[%ud %uh %um %us] cpu time:[%ud %uh %um %us] %s with exit code %ld, parent %.256s[%.16s:%d] IP:%pI4 TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u"
++#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by "
++#define GR_STOPMOD_MSG "denied modification of module state by "
++#define GR_ROFS_BLOCKWRITE_MSG "denied write to block device %.950s by "
++#define GR_ROFS_MOUNT_MSG "denied writable mount of %.950s by "
++#define GR_IOPERM_MSG "denied use of ioperm() by "
++#define GR_IOPL_MSG "denied use of iopl() by "
++#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by "
++#define GR_UNIX_CHROOT_MSG "denied connect() to abstract AF_UNIX socket outside of chroot by "
++#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by "
++#define GR_MEM_READWRITE_MSG "denied access of range %Lx -> %Lx in /dev/mem by "
++#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by "
++#define GR_LEARN_AUDIT_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%lu\t%lu\t%.4095s\t%lu\t%pI4"
++#define GR_ID_LEARN_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%c\t%d\t%d\t%d\t%pI4"
++#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by "
++#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by "
++#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by "
++#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by "
++#define GR_MKNOD_CHROOT_MSG "denied mknod of %.950s from chroot by "
++#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by "
++#define GR_UNIXCONNECT_ACL_MSG "%s connect() to the unix domain socket %.950s by "
++#define GR_TTYSNIFF_ACL_MSG "terminal being sniffed by IP:%pI4 %.480s[%.16s:%d], parent %.480s[%.16s:%d] against "
++#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by "
++#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by "
++#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by "
++#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by "
++#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for "
++#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by "
++#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by "
++#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by "
++#define GR_UNSAFESHARE_EXEC_ACL_MSG "denied exec with cloned fs of %.950s by "
++#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by "
++#define GR_NPROC_MSG "denied overstep of process limit by "
++#define GR_EXEC_ACL_MSG "%s execution of %.950s by "
++#define GR_EXEC_TPE_MSG "denied untrusted exec of %.950s by "
++#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning uid %u from login for %lu seconds"
++#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning execution for %lu seconds"
++#define GR_MOUNT_CHROOT_MSG "denied mount of %.256s as %.930s from chroot by "
++#define GR_PIVOT_CHROOT_MSG "denied pivot_root from chroot by "
++#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by "
++#define GR_ATIME_ACL_MSG "%s access time change of %.950s by "
++#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by "
++#define GR_CHROOT_CHROOT_MSG "denied double chroot to %.950s by "
++#define GR_FCHMOD_ACL_MSG "%s fchmod of %.950s by "
++#define GR_CHMOD_CHROOT_MSG "denied chmod +s of %.950s by "
++#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by "
++#define GR_CHROOT_FCHDIR_MSG "denied fchdir outside of chroot to %.950s by "
++#define GR_CHOWN_ACL_MSG "%s chown of %.950s by "
++#define GR_SETXATTR_ACL_MSG "%s setting extended attributes of %.950s by "
++#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by "
++#define GR_INITF_ACL_MSG "init_variables() failed %s by "
++#define GR_DISABLED_ACL_MSG "Error loading %s, trying to run kernel with acls disabled. To disable acls at startup use <kernel image name> gracl=off from your boot loader"
++#define GR_DEV_ACL_MSG "/dev/grsec: %d bytes sent %d required, being fed garbaged by "
++#define GR_SHUTS_ACL_MSG "shutdown auth success for "
++#define GR_SHUTF_ACL_MSG "shutdown auth failure for "
++#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for "
++#define GR_SEGVMODS_ACL_MSG "segvmod auth success for "
++#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for "
++#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for "
++#define GR_ENABLE_ACL_MSG "%s RBAC system loaded by "
++#define GR_ENABLEF_ACL_MSG "unable to load %s for "
++#define GR_RELOADI_ACL_MSG "ignoring reload request for disabled RBAC system"
++#define GR_RELOAD_ACL_MSG "%s RBAC system reloaded by "
++#define GR_RELOADF_ACL_MSG "failed reload of %s for "
++#define GR_SPROLEI_ACL_MSG "ignoring change to special role for disabled RBAC system for "
++#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by "
++#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by "
++#define GR_SPROLEF_ACL_MSG "special role %s failure for "
++#define GR_UNSPROLEI_ACL_MSG "ignoring unauth of special role for disabled RBAC system for "
++#define GR_UNSPROLES_ACL_MSG "successful unauth of special role %s (id %d) by "
++#define GR_INVMODE_ACL_MSG "invalid mode %d by "
++#define GR_PRIORITY_CHROOT_MSG "denied priority change of process (%.16s:%d) by "
++#define GR_FAILFORK_MSG "failed fork with errno %s by "
++#define GR_NICE_CHROOT_MSG "denied priority change by "
++#define GR_UNISIGLOG_MSG "%.32s occurred at %p in "
++#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by "
++#define GR_SIG_ACL_MSG "denied send of signal %d to protected task " DEFAULTSECMSG " by "
++#define GR_SYSCTL_MSG "denied modification of grsecurity sysctl value : %.32s by "
++#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by "
++#define GR_TIME_MSG "time set by "
++#define GR_DEFACL_MSG "fatal: unable to find subject for (%.16s:%d), loaded by "
++#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by "
++#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by "
++#define GR_SOCK_MSG "denied socket(%.16s,%.16s,%.16s) by "
++#define GR_SOCK_NOINET_MSG "denied socket(%.16s,%.16s,%d) by "
++#define GR_BIND_MSG "denied bind() by "
++#define GR_CONNECT_MSG "denied connect() by "
++#define GR_BIND_ACL_MSG "denied bind() to %pI4 port %u sock type %.16s protocol %.16s by "
++#define GR_CONNECT_ACL_MSG "denied connect() to %pI4 port %u sock type %.16s protocol %.16s by "
++#define GR_IP_LEARN_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%pI4\t%u\t%u\t%u\t%u\t%pI4"
++#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process "
++#define GR_CAP_ACL_MSG "use of %s denied for "
++#define GR_CAP_ACL_MSG2 "use of %s permitted for "
++#define GR_USRCHANGE_ACL_MSG "change to uid %u denied for "
++#define GR_GRPCHANGE_ACL_MSG "change to gid %u denied for "
++#define GR_REMOUNT_AUDIT_MSG "remount of %.256s by "
++#define GR_UNMOUNT_AUDIT_MSG "unmount of %.256s by "
++#define GR_MOUNT_AUDIT_MSG "mount of %.256s to %.256s by "
++#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by "
++#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.128s) by "
++#define GR_RESOURCE_MSG "denied resource overstep by requesting %lu for %.16s against limit %lu for "
++#define GR_RWXMMAP_MSG "denied RWX mmap of %.950s by "
++#define GR_RWXMPROTECT_MSG "denied RWX mprotect of %.950s by "
++#define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by "
++#define GR_VM86_MSG "denied use of vm86 by "
++#define GR_PTRACE_AUDIT_MSG "process %.950s(%.16s:%d) attached to via ptrace by "
++#define GR_INIT_TRANSFER_MSG "persistent special role transferred privilege to init by "
+diff -urNp linux-2.6.38.7/include/linux/grsecurity.h linux-2.6.38.7/include/linux/grsecurity.h
+--- linux-2.6.38.7/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/include/linux/grsecurity.h 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,212 @@
++#ifndef GR_SECURITY_H
++#define GR_SECURITY_H
++#include <linux/fs.h>
++#include <linux/fs_struct.h>
++#include <linux/binfmts.h>
++#include <linux/gracl.h>
++#include <linux/compat.h>
++
++/* notify of brain-dead configs */
++#if defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_PAX_SEGMEXEC) && !defined(CONFIG_PAX_KERNEXEC)
++#error "CONFIG_PAX_NOEXEC enabled, but PAGEEXEC, SEGMEXEC, and KERNEXEC are disabled."
++#endif
++#if defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_EI_PAX) && !defined(CONFIG_PAX_PT_PAX_FLAGS)
++#error "CONFIG_PAX_NOEXEC enabled, but neither CONFIG_PAX_EI_PAX nor CONFIG_PAX_PT_PAX_FLAGS are enabled."
++#endif
++#if defined(CONFIG_PAX_ASLR) && (defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)) && !defined(CONFIG_PAX_EI_PAX) && !defined(CONFIG_PAX_PT_PAX_FLAGS)
++#error "CONFIG_PAX_ASLR enabled, but neither CONFIG_PAX_EI_PAX nor CONFIG_PAX_PT_PAX_FLAGS are enabled."
++#endif
++#if defined(CONFIG_PAX_ASLR) && !defined(CONFIG_PAX_RANDKSTACK) && !defined(CONFIG_PAX_RANDUSTACK) && !defined(CONFIG_PAX_RANDMMAP)
++#error "CONFIG_PAX_ASLR enabled, but RANDKSTACK, RANDUSTACK, and RANDMMAP are disabled."
++#endif
++#if defined(CONFIG_PAX) && !defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_ASLR)
++#error "CONFIG_PAX enabled, but no PaX options are enabled."
++#endif
++
++void gr_handle_brute_attach(struct task_struct *p, unsigned long mm_flags);
++void gr_handle_brute_check(void);
++void gr_handle_kernel_exploit(void);
++int gr_process_user_ban(void);
++
++char gr_roletype_to_char(void);
++
++int gr_acl_enable_at_secure(void);
++
++int gr_check_user_change(int real, int effective, int fs);
++int gr_check_group_change(int real, int effective, int fs);
++
++void gr_del_task_from_ip_table(struct task_struct *p);
++
++int gr_pid_is_chrooted(struct task_struct *p);
++int gr_handle_chroot_fowner(struct pid *pid, enum pid_type type);
++int gr_handle_chroot_nice(void);
++int gr_handle_chroot_sysctl(const int op);
++int gr_handle_chroot_setpriority(struct task_struct *p,
++ const int niceval);
++int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt);
++int gr_handle_chroot_chroot(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++int gr_handle_chroot_caps(struct path *path);
++void gr_handle_chroot_chdir(struct path *path);
++int gr_handle_chroot_chmod(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int mode);
++int gr_handle_chroot_mknod(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int mode);
++int gr_handle_chroot_mount(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ const char *dev_name);
++int gr_handle_chroot_pivot(void);
++int gr_handle_chroot_unix(struct pid *pid);
++
++int gr_handle_rawio(const struct inode *inode);
++int gr_handle_nproc(void);
++
++void gr_handle_ioperm(void);
++void gr_handle_iopl(void);
++
++int gr_tpe_allow(const struct file *file);
++
++void gr_set_chroot_entries(struct task_struct *task, struct path *path);
++void gr_clear_chroot_entries(struct task_struct *task);
++
++void gr_log_forkfail(const int retval);
++void gr_log_timechange(void);
++void gr_log_signal(const int sig, const void *addr, const struct task_struct *t);
++void gr_log_chdir(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++void gr_log_chroot_exec(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++void gr_handle_exec_args(struct linux_binprm *bprm, const char __user *const __user *argv);
++#ifdef CONFIG_COMPAT
++void gr_handle_exec_args_compat(struct linux_binprm *bprm, compat_uptr_t __user *argv);
++#endif
++void gr_log_remount(const char *devname, const int retval);
++void gr_log_unmount(const char *devname, const int retval);
++void gr_log_mount(const char *from, const char *to, const int retval);
++void gr_log_textrel(struct vm_area_struct *vma);
++void gr_log_rwxmmap(struct file *file);
++void gr_log_rwxmprotect(struct file *file);
++
++int gr_handle_follow_link(const struct inode *parent,
++ const struct inode *inode,
++ const struct dentry *dentry,
++ const struct vfsmount *mnt);
++int gr_handle_fifo(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ const struct dentry *dir, const int flag,
++ const int acc_mode);
++int gr_handle_hardlink(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ struct inode *inode,
++ const int mode, const char *to);
++
++int gr_is_capable(const int cap);
++int gr_is_capable_nolog(const int cap);
++void gr_learn_resource(const struct task_struct *task, const int limit,
++ const unsigned long wanted, const int gt);
++void gr_copy_label(struct task_struct *tsk);
++void gr_handle_crash(struct task_struct *task, const int sig);
++int gr_handle_signal(const struct task_struct *p, const int sig);
++int gr_check_crash_uid(const uid_t uid);
++int gr_check_protected_task(const struct task_struct *task);
++int gr_check_protected_task_fowner(struct pid *pid, enum pid_type type);
++int gr_acl_handle_mmap(const struct file *file,
++ const unsigned long prot);
++int gr_acl_handle_mprotect(const struct file *file,
++ const unsigned long prot);
++int gr_check_hidden_task(const struct task_struct *tsk);
++__u32 gr_acl_handle_truncate(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++__u32 gr_acl_handle_utime(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++__u32 gr_acl_handle_access(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int fmode);
++__u32 gr_acl_handle_fchmod(const struct dentry *dentry,
++ const struct vfsmount *mnt, mode_t mode);
++__u32 gr_acl_handle_chmod(const struct dentry *dentry,
++ const struct vfsmount *mnt, mode_t mode);
++__u32 gr_acl_handle_chown(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++__u32 gr_acl_handle_setxattr(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++int gr_handle_ptrace(struct task_struct *task, const long request);
++int gr_handle_proc_ptrace(struct task_struct *task);
++__u32 gr_acl_handle_execve(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++int gr_check_crash_exec(const struct file *filp);
++int gr_acl_is_enabled(void);
++void gr_set_kernel_label(struct task_struct *task);
++void gr_set_role_label(struct task_struct *task, const uid_t uid,
++ const gid_t gid);
++int gr_set_proc_label(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ const int unsafe_share);
++__u32 gr_acl_handle_hidden_file(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++__u32 gr_acl_handle_open(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int fmode);
++__u32 gr_acl_handle_creat(const struct dentry *dentry,
++ const struct dentry *p_dentry,
++ const struct vfsmount *p_mnt, const int fmode,
++ const int imode);
++void gr_handle_create(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++__u32 gr_acl_handle_mknod(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const int mode);
++__u32 gr_acl_handle_mkdir(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt);
++__u32 gr_acl_handle_rmdir(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++void gr_handle_delete(const ino_t ino, const dev_t dev);
++__u32 gr_acl_handle_unlink(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++__u32 gr_acl_handle_symlink(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const char *from);
++__u32 gr_acl_handle_link(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const struct dentry *old_dentry,
++ const struct vfsmount *old_mnt, const char *to);
++int gr_acl_handle_rename(struct dentry *new_dentry,
++ struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ struct dentry *old_dentry,
++ struct inode *old_parent_inode,
++ struct vfsmount *old_mnt, const char *newname);
++void gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
++ struct dentry *old_dentry,
++ struct dentry *new_dentry,
++ struct vfsmount *mnt, const __u8 replace);
++__u32 gr_check_link(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const struct dentry *old_dentry,
++ const struct vfsmount *old_mnt);
++int gr_acl_handle_filldir(const struct file *file, const char *name,
++ const unsigned int namelen, const ino_t ino);
++
++__u32 gr_acl_handle_unix(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++void gr_acl_handle_exit(void);
++void gr_acl_handle_psacct(struct task_struct *task, const long code);
++int gr_acl_handle_procpidmem(const struct task_struct *task);
++int gr_handle_rofs_mount(struct dentry *dentry, struct vfsmount *mnt, int mnt_flags);
++int gr_handle_rofs_blockwrite(struct dentry *dentry, struct vfsmount *mnt, int acc_mode);
++void gr_audit_ptrace(struct task_struct *task);
++dev_t gr_get_dev_from_dentry(struct dentry *dentry);
++
++#ifdef CONFIG_GRKERNSEC
++void task_grsec_rbac(struct seq_file *m, struct task_struct *p);
++void gr_handle_vm86(void);
++void gr_handle_mem_readwrite(u64 from, u64 to);
++
++extern int grsec_enable_dmesg;
++extern int grsec_disable_privio;
++#endif
++
++#endif
+diff -urNp linux-2.6.38.7/include/linux/grsock.h linux-2.6.38.7/include/linux/grsock.h
+--- linux-2.6.38.7/include/linux/grsock.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/include/linux/grsock.h 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,19 @@
++#ifndef __GRSOCK_H
++#define __GRSOCK_H
++
++extern void gr_attach_curr_ip(const struct sock *sk);
++extern int gr_handle_sock_all(const int family, const int type,
++ const int protocol);
++extern int gr_handle_sock_server(const struct sockaddr *sck);
++extern int gr_handle_sock_server_other(const struct sock *sck);
++extern int gr_handle_sock_client(const struct sockaddr *sck);
++extern int gr_search_connect(struct socket * sock,
++ struct sockaddr_in * addr);
++extern int gr_search_bind(struct socket * sock,
++ struct sockaddr_in * addr);
++extern int gr_search_listen(struct socket * sock);
++extern int gr_search_accept(struct socket * sock);
++extern int gr_search_socket(const int domain, const int type,
++ const int protocol);
++
++#endif
+diff -urNp linux-2.6.38.7/include/linux/highmem.h linux-2.6.38.7/include/linux/highmem.h
+--- linux-2.6.38.7/include/linux/highmem.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/highmem.h 2011-04-28 19:34:15.000000000 -0400
+@@ -185,6 +185,18 @@ static inline void clear_highpage(struct
+ kunmap_atomic(kaddr, KM_USER0);
+ }
+
++static inline void sanitize_highpage(struct page *page)
++{
++ void *kaddr;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ kaddr = kmap_atomic(page, KM_CLEARPAGE);
++ clear_page(kaddr);
++ kunmap_atomic(kaddr, KM_CLEARPAGE);
++ local_irq_restore(flags);
++}
++
+ static inline void zero_user_segments(struct page *page,
+ unsigned start1, unsigned end1,
+ unsigned start2, unsigned end2)
+diff -urNp linux-2.6.38.7/include/linux/i2o.h linux-2.6.38.7/include/linux/i2o.h
+--- linux-2.6.38.7/include/linux/i2o.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/i2o.h 2011-04-28 19:57:25.000000000 -0400
+@@ -564,7 +564,7 @@ struct i2o_controller {
+ struct i2o_device *exec; /* Executive */
+ #if BITS_PER_LONG == 64
+ spinlock_t context_list_lock; /* lock for context_list */
+- atomic_t context_list_counter; /* needed for unique contexts */
++ atomic_unchecked_t context_list_counter; /* needed for unique contexts */
+ struct list_head context_list; /* list of context id's
+ and pointers */
+ #endif
+diff -urNp linux-2.6.38.7/include/linux/init.h linux-2.6.38.7/include/linux/init.h
+--- linux-2.6.38.7/include/linux/init.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/init.h 2011-04-28 19:34:15.000000000 -0400
+@@ -293,13 +293,13 @@ void __init parse_early_options(char *cm
+
+ /* Each module must use one module_init(). */
+ #define module_init(initfn) \
+- static inline initcall_t __inittest(void) \
++ static inline __used initcall_t __inittest(void) \
+ { return initfn; } \
+ int init_module(void) __attribute__((alias(#initfn)));
+
+ /* This is only required if you want to be unloadable. */
+ #define module_exit(exitfn) \
+- static inline exitcall_t __exittest(void) \
++ static inline __used exitcall_t __exittest(void) \
+ { return exitfn; } \
+ void cleanup_module(void) __attribute__((alias(#exitfn)));
+
+diff -urNp linux-2.6.38.7/include/linux/init_task.h linux-2.6.38.7/include/linux/init_task.h
+--- linux-2.6.38.7/include/linux/init_task.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/init_task.h 2011-04-30 19:59:43.000000000 -0400
+@@ -83,6 +83,12 @@ extern struct group_info init_groups;
+ #define INIT_IDS
+ #endif
+
++#ifdef CONFIG_X86
++#define INIT_TASK_THREAD_INFO .tinfo = INIT_THREAD_INFO,
++#else
++#define INIT_TASK_THREAD_INFO
++#endif
++
+ /*
+ * Because of the reduced scope of CAP_SETPCAP when filesystem
+ * capabilities are in effect, it is safe to allow CAP_SETPCAP to
+@@ -163,6 +169,7 @@ extern struct cred init_cred;
+ RCU_INIT_POINTER(.cred, &init_cred), \
+ .comm = "swapper", \
+ .thread = INIT_THREAD, \
++ INIT_TASK_THREAD_INFO \
+ .fs = &init_fs, \
+ .files = &init_files, \
+ .signal = &init_signals, \
+diff -urNp linux-2.6.38.7/include/linux/interrupt.h linux-2.6.38.7/include/linux/interrupt.h
+--- linux-2.6.38.7/include/linux/interrupt.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/interrupt.h 2011-04-28 19:34:15.000000000 -0400
+@@ -393,7 +393,7 @@ enum
+ /* map softirq index to softirq name. update 'softirq_to_name' in
+ * kernel/softirq.c when adding a new softirq.
+ */
+-extern char *softirq_to_name[NR_SOFTIRQS];
++extern const char * const softirq_to_name[NR_SOFTIRQS];
+
+ /* softirq mask and active fields moved to irq_cpustat_t in
+ * asm/hardirq.h to get better cache usage. KAO
+@@ -401,12 +401,12 @@ extern char *softirq_to_name[NR_SOFTIRQS
+
+ struct softirq_action
+ {
+- void (*action)(struct softirq_action *);
++ void (*action)(void);
+ };
+
+ asmlinkage void do_softirq(void);
+ asmlinkage void __do_softirq(void);
+-extern void open_softirq(int nr, void (*action)(struct softirq_action *));
++extern void open_softirq(int nr, void (*action)(void));
+ extern void softirq_init(void);
+ static inline void __raise_softirq_irqoff(unsigned int nr)
+ {
+diff -urNp linux-2.6.38.7/include/linux/kallsyms.h linux-2.6.38.7/include/linux/kallsyms.h
+--- linux-2.6.38.7/include/linux/kallsyms.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/kallsyms.h 2011-04-28 19:34:15.000000000 -0400
+@@ -15,7 +15,8 @@
+
+ struct module;
+
+-#ifdef CONFIG_KALLSYMS
++#if !defined(__INCLUDED_BY_HIDESYM) || !defined(CONFIG_KALLSYMS)
++#if defined(CONFIG_KALLSYMS) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ /* Lookup the address for a symbol. Returns 0 if not found. */
+ unsigned long kallsyms_lookup_name(const char *name);
+
+@@ -92,6 +93,15 @@ static inline int lookup_symbol_attrs(un
+ /* Stupid that this does nothing, but I didn't create this mess. */
+ #define __print_symbol(fmt, addr)
+ #endif /*CONFIG_KALLSYMS*/
++#else /* when included by kallsyms.c, vsnprintf.c, or
++ arch/x86/kernel/dumpstack.c, with HIDESYM enabled */
++extern void __print_symbol(const char *fmt, unsigned long address);
++extern int sprint_symbol(char *buffer, unsigned long address);
++const char *kallsyms_lookup(unsigned long addr,
++ unsigned long *symbolsize,
++ unsigned long *offset,
++ char **modname, char *namebuf);
++#endif
+
+ /* This macro allows us to keep printk typechecking */
+ static void __check_printsym_format(const char *fmt, ...)
+diff -urNp linux-2.6.38.7/include/linux/kgdb.h linux-2.6.38.7/include/linux/kgdb.h
+--- linux-2.6.38.7/include/linux/kgdb.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/kgdb.h 2011-04-28 19:57:25.000000000 -0400
+@@ -53,7 +53,7 @@ extern int kgdb_connected;
+ extern int kgdb_io_module_registered;
+
+ extern atomic_t kgdb_setting_breakpoint;
+-extern atomic_t kgdb_cpu_doing_single_step;
++extern atomic_unchecked_t kgdb_cpu_doing_single_step;
+
+ extern struct task_struct *kgdb_usethread;
+ extern struct task_struct *kgdb_contthread;
+@@ -269,22 +269,22 @@ struct kgdb_arch {
+ */
+ struct kgdb_io {
+ const char *name;
+- int (*read_char) (void);
+- void (*write_char) (u8);
+- void (*flush) (void);
+- int (*init) (void);
+- void (*pre_exception) (void);
+- void (*post_exception) (void);
++ int (* const read_char) (void);
++ void (* const write_char) (u8);
++ void (* const flush) (void);
++ int (* const init) (void);
++ void (* const pre_exception) (void);
++ void (* const post_exception) (void);
+ int is_console;
+ };
+
+-extern struct kgdb_arch arch_kgdb_ops;
++extern const struct kgdb_arch arch_kgdb_ops;
+
+ extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs);
+
+-extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
+-extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
+-extern struct kgdb_io *dbg_io_ops;
++extern int kgdb_register_io_module(const struct kgdb_io *local_kgdb_io_ops);
++extern void kgdb_unregister_io_module(const struct kgdb_io *local_kgdb_io_ops);
++extern const struct kgdb_io *dbg_io_ops;
+
+ extern int kgdb_hex2long(char **ptr, unsigned long *long_val);
+ extern char *kgdb_mem2hex(char *mem, char *buf, int count);
+diff -urNp linux-2.6.38.7/include/linux/kmod.h linux-2.6.38.7/include/linux/kmod.h
+--- linux-2.6.38.7/include/linux/kmod.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/kmod.h 2011-04-28 19:34:15.000000000 -0400
+@@ -33,6 +33,8 @@ extern char modprobe_path[]; /* for sysc
+ * usually useless though. */
+ extern int __request_module(bool wait, const char *name, ...) \
+ __attribute__((format(printf, 2, 3)));
++extern int ___request_module(bool wait, char *param_name, const char *name, ...) \
++ __attribute__((format(printf, 3, 4)));
+ #define request_module(mod...) __request_module(true, mod)
+ #define request_module_nowait(mod...) __request_module(false, mod)
+ #define try_then_request_module(x, mod...) \
+diff -urNp linux-2.6.38.7/include/linux/kvm_host.h linux-2.6.38.7/include/linux/kvm_host.h
+--- linux-2.6.38.7/include/linux/kvm_host.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/kvm_host.h 2011-04-28 19:34:15.000000000 -0400
+@@ -288,7 +288,7 @@ void kvm_vcpu_uninit(struct kvm_vcpu *vc
+ void vcpu_load(struct kvm_vcpu *vcpu);
+ void vcpu_put(struct kvm_vcpu *vcpu);
+
+-int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
++int kvm_init(const void *opaque, unsigned vcpu_size, unsigned vcpu_align,
+ struct module *module);
+ void kvm_exit(void);
+
+@@ -428,7 +428,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(
+ struct kvm_guest_debug *dbg);
+ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
+
+-int kvm_arch_init(void *opaque);
++int kvm_arch_init(const void *opaque);
+ void kvm_arch_exit(void);
+
+ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu);
+diff -urNp linux-2.6.38.7/include/linux/libata.h linux-2.6.38.7/include/linux/libata.h
+--- linux-2.6.38.7/include/linux/libata.h 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/include/linux/libata.h 2011-05-10 22:06:56.000000000 -0400
+@@ -531,11 +531,11 @@ struct ata_ioports {
+
+ struct ata_host {
+ spinlock_t lock;
+- struct device *dev;
++ struct device *dev;
+ void __iomem * const *iomap;
+ unsigned int n_ports;
+ void *private_data;
+- struct ata_port_operations *ops;
++ const struct ata_port_operations *ops;
+ unsigned long flags;
+
+ struct mutex eh_mutex;
+@@ -726,7 +726,7 @@ struct ata_link {
+
+ struct ata_port {
+ struct Scsi_Host *scsi_host; /* our co-allocated scsi host */
+- struct ata_port_operations *ops;
++ const struct ata_port_operations *ops;
+ spinlock_t *lock;
+ /* Flags owned by the EH context. Only EH should touch these once the
+ port is active */
+@@ -914,7 +914,7 @@ struct ata_port_info {
+ unsigned long pio_mask;
+ unsigned long mwdma_mask;
+ unsigned long udma_mask;
+- struct ata_port_operations *port_ops;
++ const struct ata_port_operations *port_ops;
+ void *private_data;
+ };
+
+@@ -938,7 +938,7 @@ extern const unsigned long sata_deb_timi
+ extern const unsigned long sata_deb_timing_hotplug[];
+ extern const unsigned long sata_deb_timing_long[];
+
+-extern struct ata_port_operations ata_dummy_port_ops;
++extern const struct ata_port_operations ata_dummy_port_ops;
+ extern const struct ata_port_info ata_dummy_port_info;
+
+ static inline const unsigned long *
+@@ -984,7 +984,7 @@ extern int ata_host_activate(struct ata_
+ struct scsi_host_template *sht);
+ extern void ata_host_detach(struct ata_host *host);
+ extern void ata_host_init(struct ata_host *, struct device *,
+- unsigned long, struct ata_port_operations *);
++ unsigned long, const struct ata_port_operations *);
+ extern int ata_scsi_detect(struct scsi_host_template *sht);
+ extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
+ extern int ata_scsi_queuecmd(struct Scsi_Host *h, struct scsi_cmnd *cmd);
+diff -urNp linux-2.6.38.7/include/linux/lockd/bind.h linux-2.6.38.7/include/linux/lockd/bind.h
+--- linux-2.6.38.7/include/linux/lockd/bind.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/lockd/bind.h 2011-04-28 19:34:15.000000000 -0400
+@@ -23,13 +23,13 @@ struct svc_rqst;
+ * This is the set of functions for lockd->nfsd communication
+ */
+ struct nlmsvc_binding {
+- __be32 (*fopen)(struct svc_rqst *,
++ __be32 (* const fopen)(struct svc_rqst *,
+ struct nfs_fh *,
+ struct file **);
+- void (*fclose)(struct file *);
++ void (* const fclose)(struct file *);
+ };
+
+-extern struct nlmsvc_binding * nlmsvc_ops;
++extern const struct nlmsvc_binding * nlmsvc_ops;
+
+ /*
+ * Similar to nfs_client_initdata, but without the NFS-specific
+diff -urNp linux-2.6.38.7/include/linux/mm.h linux-2.6.38.7/include/linux/mm.h
+--- linux-2.6.38.7/include/linux/mm.h 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/include/linux/mm.h 2011-05-22 23:06:04.000000000 -0400
+@@ -113,7 +113,14 @@ extern unsigned int kobjsize(const void
+
+ #define VM_CAN_NONLINEAR 0x08000000 /* Has ->fault & does nonlinear pages */
+ #define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
++#define VM_SAO 0x00000000 /* Strong Access Ordering (powerpc) */
++#define VM_PAGEEXEC 0x20000000 /* vma->vm_page_prot needs special handling */
++#else
+ #define VM_SAO 0x20000000 /* Strong Access Ordering (powerpc) */
++#endif
++
+ #define VM_PFN_AT_MMAP 0x40000000 /* PFNMAP vma that is fully mapped at mmap time */
+ #define VM_MERGEABLE 0x80000000 /* KSM may merge identical pages */
+
+@@ -993,34 +1000,6 @@ int set_page_dirty(struct page *page);
+ int set_page_dirty_lock(struct page *page);
+ int clear_page_dirty_for_io(struct page *page);
+
+-/* Is the vma a continuation of the stack vma above it? */
+-static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
+-{
+- return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
+-}
+-
+-static inline int stack_guard_page_start(struct vm_area_struct *vma,
+- unsigned long addr)
+-{
+- return (vma->vm_flags & VM_GROWSDOWN) &&
+- (vma->vm_start == addr) &&
+- !vma_growsdown(vma->vm_prev, addr);
+-}
+-
+-/* Is the vma a continuation of the stack vma below it? */
+-static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr)
+-{
+- return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP);
+-}
+-
+-static inline int stack_guard_page_end(struct vm_area_struct *vma,
+- unsigned long addr)
+-{
+- return (vma->vm_flags & VM_GROWSUP) &&
+- (vma->vm_end == addr) &&
+- !vma_growsup(vma->vm_next, addr);
+-}
+-
+ extern unsigned long move_page_tables(struct vm_area_struct *vma,
+ unsigned long old_addr, struct vm_area_struct *new_vma,
+ unsigned long new_addr, unsigned long len);
+@@ -1172,6 +1151,15 @@ struct shrinker {
+ extern void register_shrinker(struct shrinker *);
+ extern void unregister_shrinker(struct shrinker *);
+
++#ifdef CONFIG_MMU
++pgprot_t vm_get_page_prot(unsigned long vm_flags);
++#else
++static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
++{
++ return __pgprot(0);
++}
++#endif
++
+ int vma_wants_writenotify(struct vm_area_struct *vma);
+
+ extern pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr,
+@@ -1461,6 +1449,7 @@ out:
+ }
+
+ extern int do_munmap(struct mm_struct *, unsigned long, size_t);
++extern int __do_munmap(struct mm_struct *, unsigned long, size_t);
+
+ extern unsigned long do_brk(unsigned long, unsigned long);
+
+@@ -1517,6 +1506,10 @@ extern struct vm_area_struct * find_vma(
+ extern struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
+ struct vm_area_struct **pprev);
+
++extern struct vm_area_struct *pax_find_mirror_vma(struct vm_area_struct *vma);
++extern __must_check long pax_mirror_vma(struct vm_area_struct *vma_m, struct vm_area_struct *vma);
++extern void pax_mirror_file_pte(struct vm_area_struct *vma, unsigned long address, struct page *page_m, spinlock_t *ptl);
++
+ /* Look up the first VMA which intersects the interval start_addr..end_addr-1,
+ NULL if none. Assume start_addr < end_addr. */
+ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr)
+@@ -1533,15 +1526,6 @@ static inline unsigned long vma_pages(st
+ return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ }
+
+-#ifdef CONFIG_MMU
+-pgprot_t vm_get_page_prot(unsigned long vm_flags);
+-#else
+-static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
+-{
+- return __pgprot(0);
+-}
+-#endif
+-
+ struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr);
+ int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
+ unsigned long pfn, unsigned long size, pgprot_t);
+@@ -1650,7 +1634,7 @@ extern int unpoison_memory(unsigned long
+ extern int sysctl_memory_failure_early_kill;
+ extern int sysctl_memory_failure_recovery;
+ extern void shake_page(struct page *p, int access);
+-extern atomic_long_t mce_bad_pages;
++extern atomic_long_unchecked_t mce_bad_pages;
+ extern int soft_offline_page(struct page *page, int flags);
+ #ifdef CONFIG_MEMORY_FAILURE
+ int is_hwpoison_address(unsigned long addr);
+@@ -1672,5 +1656,11 @@ extern void copy_user_huge_page(struct p
+ unsigned int pages_per_huge_page);
+ #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
+
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
++extern void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot);
++#else
++static inline void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot) {}
++#endif
++
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_MM_H */
+diff -urNp linux-2.6.38.7/include/linux/mm_types.h linux-2.6.38.7/include/linux/mm_types.h
+--- linux-2.6.38.7/include/linux/mm_types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/mm_types.h 2011-04-28 19:34:15.000000000 -0400
+@@ -183,6 +183,8 @@ struct vm_area_struct {
+ #ifdef CONFIG_NUMA
+ struct mempolicy *vm_policy; /* NUMA policy for the VMA */
+ #endif
++
++ struct vm_area_struct *vm_mirror;/* PaX: mirror vma or NULL */
+ };
+
+ struct core_thread {
+@@ -315,6 +317,24 @@ struct mm_struct {
+ #endif
+ /* How many tasks sharing this mm are OOM_DISABLE */
+ atomic_t oom_disable_count;
++
++#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) || defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
++ unsigned long pax_flags;
++#endif
++
++#ifdef CONFIG_PAX_DLRESOLVE
++ unsigned long call_dl_resolve;
++#endif
++
++#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
++ unsigned long call_syscall;
++#endif
++
++#ifdef CONFIG_PAX_ASLR
++ unsigned long delta_mmap; /* randomized offset */
++ unsigned long delta_stack; /* randomized offset */
++#endif
++
+ };
+
+ /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */
+diff -urNp linux-2.6.38.7/include/linux/mmu_notifier.h linux-2.6.38.7/include/linux/mmu_notifier.h
+--- linux-2.6.38.7/include/linux/mmu_notifier.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/mmu_notifier.h 2011-04-28 19:34:15.000000000 -0400
+@@ -255,12 +255,12 @@ static inline void mmu_notifier_mm_destr
+ */
+ #define ptep_clear_flush_notify(__vma, __address, __ptep) \
+ ({ \
+- pte_t __pte; \
++ pte_t ___pte; \
+ struct vm_area_struct *___vma = __vma; \
+ unsigned long ___address = __address; \
+- __pte = ptep_clear_flush(___vma, ___address, __ptep); \
++ ___pte = ptep_clear_flush(___vma, ___address, __ptep); \
+ mmu_notifier_invalidate_page(___vma->vm_mm, ___address); \
+- __pte; \
++ ___pte; \
+ })
+
+ #define pmdp_clear_flush_notify(__vma, __address, __pmdp) \
+diff -urNp linux-2.6.38.7/include/linux/mmzone.h linux-2.6.38.7/include/linux/mmzone.h
+--- linux-2.6.38.7/include/linux/mmzone.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/mmzone.h 2011-04-28 19:34:15.000000000 -0400
+@@ -355,7 +355,7 @@ struct zone {
+ unsigned long flags; /* zone flags, see below */
+
+ /* Zone statistics */
+- atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
++ atomic_long_unchecked_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+
+ /*
+ * The target ratio of ACTIVE_ANON to INACTIVE_ANON pages on
+diff -urNp linux-2.6.38.7/include/linux/mod_devicetable.h linux-2.6.38.7/include/linux/mod_devicetable.h
+--- linux-2.6.38.7/include/linux/mod_devicetable.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/mod_devicetable.h 2011-04-28 19:34:15.000000000 -0400
+@@ -12,7 +12,7 @@
+ typedef unsigned long kernel_ulong_t;
+ #endif
+
+-#define PCI_ANY_ID (~0)
++#define PCI_ANY_ID ((__u16)~0)
+
+ struct pci_device_id {
+ __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
+@@ -131,7 +131,7 @@ struct usb_device_id {
+ #define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
+ #define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
+
+-#define HID_ANY_ID (~0)
++#define HID_ANY_ID (~0U)
+
+ struct hid_device_id {
+ __u16 bus;
+diff -urNp linux-2.6.38.7/include/linux/module.h linux-2.6.38.7/include/linux/module.h
+--- linux-2.6.38.7/include/linux/module.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/module.h 2011-04-28 19:34:15.000000000 -0400
+@@ -324,19 +324,16 @@ struct module
+ int (*init)(void);
+
+ /* If this is non-NULL, vfree after init() returns */
+- void *module_init;
++ void *module_init_rx, *module_init_rw;
+
+ /* Here is the actual code + data, vfree'd on unload. */
+- void *module_core;
++ void *module_core_rx, *module_core_rw;
+
+ /* Here are the sizes of the init and core sections */
+- unsigned int init_size, core_size;
++ unsigned int init_size_rw, core_size_rw;
+
+ /* The size of the executable code in each section. */
+- unsigned int init_text_size, core_text_size;
+-
+- /* Size of RO sections of the module (text+rodata) */
+- unsigned int init_ro_size, core_ro_size;
++ unsigned int init_size_rx, core_size_rx;
+
+ /* Arch-specific module values */
+ struct mod_arch_specific arch;
+@@ -441,16 +438,46 @@ bool is_module_address(unsigned long add
+ bool is_module_percpu_address(unsigned long addr);
+ bool is_module_text_address(unsigned long addr);
+
++static inline int within_module_range(unsigned long addr, void *start, unsigned long size)
++{
++
++#ifdef CONFIG_PAX_KERNEXEC
++ if (ktla_ktva(addr) >= (unsigned long)start &&
++ ktla_ktva(addr) < (unsigned long)start + size)
++ return 1;
++#endif
++
++ return ((void *)addr >= start && (void *)addr < start + size);
++}
++
++static inline int within_module_core_rx(unsigned long addr, struct module *mod)
++{
++ return within_module_range(addr, mod->module_core_rx, mod->core_size_rx);
++}
++
++static inline int within_module_core_rw(unsigned long addr, struct module *mod)
++{
++ return within_module_range(addr, mod->module_core_rw, mod->core_size_rw);
++}
++
++static inline int within_module_init_rx(unsigned long addr, struct module *mod)
++{
++ return within_module_range(addr, mod->module_init_rx, mod->init_size_rx);
++}
++
++static inline int within_module_init_rw(unsigned long addr, struct module *mod)
++{
++ return within_module_range(addr, mod->module_init_rw, mod->init_size_rw);
++}
++
+ static inline int within_module_core(unsigned long addr, struct module *mod)
+ {
+- return (unsigned long)mod->module_core <= addr &&
+- addr < (unsigned long)mod->module_core + mod->core_size;
++ return within_module_core_rx(addr, mod) || within_module_core_rw(addr, mod);
+ }
+
+ static inline int within_module_init(unsigned long addr, struct module *mod)
+ {
+- return (unsigned long)mod->module_init <= addr &&
+- addr < (unsigned long)mod->module_init + mod->init_size;
++ return within_module_init_rx(addr, mod) || within_module_init_rw(addr, mod);
+ }
+
+ /* Search for module by name: must hold module_mutex. */
+diff -urNp linux-2.6.38.7/include/linux/moduleloader.h linux-2.6.38.7/include/linux/moduleloader.h
+--- linux-2.6.38.7/include/linux/moduleloader.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/moduleloader.h 2011-04-28 19:34:15.000000000 -0400
+@@ -20,9 +20,21 @@ unsigned int arch_mod_section_prepend(st
+ sections. Returns NULL on failure. */
+ void *module_alloc(unsigned long size);
+
++#ifdef CONFIG_PAX_KERNEXEC
++void *module_alloc_exec(unsigned long size);
++#else
++#define module_alloc_exec(x) module_alloc(x)
++#endif
++
+ /* Free memory returned from module_alloc. */
+ void module_free(struct module *mod, void *module_region);
+
++#ifdef CONFIG_PAX_KERNEXEC
++void module_free_exec(struct module *mod, void *module_region);
++#else
++#define module_free_exec(x, y) module_free((x), (y))
++#endif
++
+ /* Apply the given relocation to the (simplified) ELF. Return -error
+ or 0. */
+ int apply_relocate(Elf_Shdr *sechdrs,
+diff -urNp linux-2.6.38.7/include/linux/moduleparam.h linux-2.6.38.7/include/linux/moduleparam.h
+--- linux-2.6.38.7/include/linux/moduleparam.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/moduleparam.h 2011-04-28 19:34:15.000000000 -0400
+@@ -255,7 +255,7 @@ static inline void __kernel_param_unlock
+ * @len is usually just sizeof(string).
+ */
+ #define module_param_string(name, string, len, perm) \
+- static const struct kparam_string __param_string_##name \
++ static const struct kparam_string __param_string_##name __used \
+ = { len, string }; \
+ __module_param_call(MODULE_PARAM_PREFIX, name, \
+ &param_ops_string, \
+@@ -370,7 +370,7 @@ extern int param_get_invbool(char *buffe
+ * module_param_named() for why this might be necessary.
+ */
+ #define module_param_array_named(name, array, type, nump, perm) \
+- static const struct kparam_array __param_arr_##name \
++ static const struct kparam_array __param_arr_##name __used \
+ = { ARRAY_SIZE(array), nump, &param_ops_##type, \
+ sizeof(array[0]), array }; \
+ __module_param_call(MODULE_PARAM_PREFIX, name, \
+diff -urNp linux-2.6.38.7/include/linux/mutex.h linux-2.6.38.7/include/linux/mutex.h
+--- linux-2.6.38.7/include/linux/mutex.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/mutex.h 2011-04-28 19:34:15.000000000 -0400
+@@ -51,7 +51,7 @@ struct mutex {
+ spinlock_t wait_lock;
+ struct list_head wait_list;
+ #if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
+- struct thread_info *owner;
++ struct task_struct *owner;
+ #endif
+ #ifdef CONFIG_DEBUG_MUTEXES
+ const char *name;
+diff -urNp linux-2.6.38.7/include/linux/namei.h linux-2.6.38.7/include/linux/namei.h
+--- linux-2.6.38.7/include/linux/namei.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/namei.h 2011-04-28 19:34:15.000000000 -0400
+@@ -25,7 +25,7 @@ struct nameidata {
+ unsigned seq;
+ int last_type;
+ unsigned depth;
+- char *saved_names[MAX_NESTED_LINKS + 1];
++ const char *saved_names[MAX_NESTED_LINKS + 1];
+
+ /* Intent data */
+ union {
+@@ -88,12 +88,12 @@ extern int follow_up(struct path *);
+ extern struct dentry *lock_rename(struct dentry *, struct dentry *);
+ extern void unlock_rename(struct dentry *, struct dentry *);
+
+-static inline void nd_set_link(struct nameidata *nd, char *path)
++static inline void nd_set_link(struct nameidata *nd, const char *path)
+ {
+ nd->saved_names[nd->depth] = path;
+ }
+
+-static inline char *nd_get_link(struct nameidata *nd)
++static inline const char *nd_get_link(const struct nameidata *nd)
+ {
+ return nd->saved_names[nd->depth];
+ }
+diff -urNp linux-2.6.38.7/include/linux/netfilter/xt_gradm.h linux-2.6.38.7/include/linux/netfilter/xt_gradm.h
+--- linux-2.6.38.7/include/linux/netfilter/xt_gradm.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/include/linux/netfilter/xt_gradm.h 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,9 @@
++#ifndef _LINUX_NETFILTER_XT_GRADM_H
++#define _LINUX_NETFILTER_XT_GRADM_H 1
++
++struct xt_gradm_mtinfo {
++ __u16 flags;
++ __u16 invflags;
++};
++
++#endif
+diff -urNp linux-2.6.38.7/include/linux/oprofile.h linux-2.6.38.7/include/linux/oprofile.h
+--- linux-2.6.38.7/include/linux/oprofile.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/oprofile.h 2011-04-28 19:34:15.000000000 -0400
+@@ -132,9 +132,9 @@ int oprofilefs_create_ulong(struct super
+ int oprofilefs_create_ro_ulong(struct super_block * sb, struct dentry * root,
+ char const * name, ulong * val);
+
+-/** Create a file for read-only access to an atomic_t. */
++/** Create a file for read-only access to an atomic_unchecked_t. */
+ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
+- char const * name, atomic_t * val);
++ char const * name, atomic_unchecked_t * val);
+
+ /** create a directory */
+ struct dentry * oprofilefs_mkdir(struct super_block * sb, struct dentry * root,
+diff -urNp linux-2.6.38.7/include/linux/padata.h linux-2.6.38.7/include/linux/padata.h
+--- linux-2.6.38.7/include/linux/padata.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/padata.h 2011-04-28 19:57:25.000000000 -0400
+@@ -129,7 +129,7 @@ struct parallel_data {
+ struct padata_instance *pinst;
+ struct padata_parallel_queue __percpu *pqueue;
+ struct padata_serial_queue __percpu *squeue;
+- atomic_t seq_nr;
++ atomic_unchecked_t seq_nr;
+ atomic_t reorder_objects;
+ atomic_t refcnt;
+ unsigned int max_seq_nr;
+diff -urNp linux-2.6.38.7/include/linux/perf_event.h linux-2.6.38.7/include/linux/perf_event.h
+--- linux-2.6.38.7/include/linux/perf_event.h 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/include/linux/perf_event.h 2011-04-28 19:57:25.000000000 -0400
+@@ -732,8 +732,8 @@ struct perf_event {
+
+ enum perf_event_active_state state;
+ unsigned int attach_state;
+- local64_t count;
+- atomic64_t child_count;
++ local64_t count; /* PaX: fix it one day */
++ atomic64_unchecked_t child_count;
+
+ /*
+ * These are the total time in nanoseconds that the event
+@@ -784,8 +784,8 @@ struct perf_event {
+ * These accumulate total time (in nanoseconds) that children
+ * events have been enabled and running, respectively.
+ */
+- atomic64_t child_total_time_enabled;
+- atomic64_t child_total_time_running;
++ atomic64_unchecked_t child_total_time_enabled;
++ atomic64_unchecked_t child_total_time_running;
+
+ /*
+ * Protect attach/detach and child_list:
+diff -urNp linux-2.6.38.7/include/linux/pipe_fs_i.h linux-2.6.38.7/include/linux/pipe_fs_i.h
+--- linux-2.6.38.7/include/linux/pipe_fs_i.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/pipe_fs_i.h 2011-04-28 19:34:15.000000000 -0400
+@@ -46,9 +46,9 @@ struct pipe_buffer {
+ struct pipe_inode_info {
+ wait_queue_head_t wait;
+ unsigned int nrbufs, curbuf, buffers;
+- unsigned int readers;
+- unsigned int writers;
+- unsigned int waiting_writers;
++ atomic_t readers;
++ atomic_t writers;
++ atomic_t waiting_writers;
+ unsigned int r_counter;
+ unsigned int w_counter;
+ struct page *tmp_page;
+diff -urNp linux-2.6.38.7/include/linux/pm_runtime.h linux-2.6.38.7/include/linux/pm_runtime.h
+--- linux-2.6.38.7/include/linux/pm_runtime.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/pm_runtime.h 2011-04-28 19:34:15.000000000 -0400
+@@ -89,7 +89,7 @@ static inline bool pm_runtime_enabled(st
+
+ static inline void pm_runtime_mark_last_busy(struct device *dev)
+ {
+- ACCESS_ONCE(dev->power.last_busy) = jiffies;
++ ACCESS_ONCE_RW(dev->power.last_busy) = jiffies;
+ }
+
+ #else /* !CONFIG_PM_RUNTIME */
+diff -urNp linux-2.6.38.7/include/linux/poison.h linux-2.6.38.7/include/linux/poison.h
+--- linux-2.6.38.7/include/linux/poison.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/poison.h 2011-04-28 19:34:15.000000000 -0400
+@@ -19,8 +19,8 @@
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+-#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
+-#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
++#define LIST_POISON1 ((void *) (long)0xFFFFFF01)
++#define LIST_POISON2 ((void *) (long)0xFFFFFF02)
+
+ /********** include/linux/timer.h **********/
+ /*
+diff -urNp linux-2.6.38.7/include/linux/proc_fs.h linux-2.6.38.7/include/linux/proc_fs.h
+--- linux-2.6.38.7/include/linux/proc_fs.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/proc_fs.h 2011-04-28 19:34:15.000000000 -0400
+@@ -155,6 +155,19 @@ static inline struct proc_dir_entry *pro
+ return proc_create_data(name, mode, parent, proc_fops, NULL);
+ }
+
++static inline struct proc_dir_entry *proc_create_grsec(const char *name, mode_t mode,
++ struct proc_dir_entry *parent, const struct file_operations *proc_fops)
++{
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ return proc_create_data(name, S_IRUSR, parent, proc_fops, NULL);
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ return proc_create_data(name, S_IRUSR | S_IRGRP, parent, proc_fops, NULL);
++#else
++ return proc_create_data(name, mode, parent, proc_fops, NULL);
++#endif
++}
++
++
+ static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+ mode_t mode, struct proc_dir_entry *base,
+ read_proc_t *read_proc, void * data)
+diff -urNp linux-2.6.38.7/include/linux/ptrace.h linux-2.6.38.7/include/linux/ptrace.h
+--- linux-2.6.38.7/include/linux/ptrace.h 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/include/linux/ptrace.h 2011-05-22 23:06:04.000000000 -0400
+@@ -115,10 +115,10 @@ extern void __ptrace_unlink(struct task_
+ extern void exit_ptrace(struct task_struct *tracer);
+ #define PTRACE_MODE_READ 1
+ #define PTRACE_MODE_ATTACH 2
+-/* Returns 0 on success, -errno on denial. */
+-extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
+ /* Returns true on success, false on denial. */
+ extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
++/* Returns true on success, false on denial. */
++extern bool ptrace_may_access_log(struct task_struct *task, unsigned int mode);
+
+ static inline int ptrace_reparented(struct task_struct *child)
+ {
+diff -urNp linux-2.6.38.7/include/linux/random.h linux-2.6.38.7/include/linux/random.h
+--- linux-2.6.38.7/include/linux/random.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/random.h 2011-04-28 19:34:15.000000000 -0400
+@@ -80,12 +80,17 @@ void srandom32(u32 seed);
+
+ u32 prandom32(struct rnd_state *);
+
++static inline unsigned long pax_get_random_long(void)
++{
++ return random32() + (sizeof(long) > 4 ? (unsigned long)random32() << 32 : 0);
++}
++
+ /*
+ * Handle minimum values for seeds
+ */
+ static inline u32 __seed(u32 x, u32 m)
+ {
+- return (x < m) ? x + m : x;
++ return (x <= m) ? x + m + 1 : x;
+ }
+
+ /**
+diff -urNp linux-2.6.38.7/include/linux/reboot.h linux-2.6.38.7/include/linux/reboot.h
+--- linux-2.6.38.7/include/linux/reboot.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/reboot.h 2011-05-22 23:03:34.000000000 -0400
+@@ -47,9 +47,9 @@ extern int unregister_reboot_notifier(st
+ * Architecture-specific implementations of sys_reboot commands.
+ */
+
+-extern void machine_restart(char *cmd);
+-extern void machine_halt(void);
+-extern void machine_power_off(void);
++extern void machine_restart(char *cmd) __noreturn;
++extern void machine_halt(void) __noreturn;
++extern void machine_power_off(void) __noreturn;
+
+ extern void machine_shutdown(void);
+ struct pt_regs;
+@@ -60,9 +60,9 @@ extern void machine_crash_shutdown(struc
+ */
+
+ extern void kernel_restart_prepare(char *cmd);
+-extern void kernel_restart(char *cmd);
+-extern void kernel_halt(void);
+-extern void kernel_power_off(void);
++extern void kernel_restart(char *cmd) __noreturn;
++extern void kernel_halt(void) __noreturn;
++extern void kernel_power_off(void) __noreturn;
+
+ extern int C_A_D; /* for sysctl */
+ void ctrl_alt_del(void);
+@@ -76,7 +76,7 @@ extern int orderly_poweroff(bool force);
+ * Emergency restart, callable from an interrupt handler.
+ */
+
+-extern void emergency_restart(void);
++extern void emergency_restart(void) __noreturn;
+ #include <asm/emergency-restart.h>
+
+ #endif
+diff -urNp linux-2.6.38.7/include/linux/reiserfs_fs.h linux-2.6.38.7/include/linux/reiserfs_fs.h
+--- linux-2.6.38.7/include/linux/reiserfs_fs.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/reiserfs_fs.h 2011-04-28 19:34:15.000000000 -0400
+@@ -1403,7 +1403,7 @@ static inline loff_t max_reiserfs_offset
+ #define REISERFS_USER_MEM 1 /* reiserfs user memory mode */
+
+ #define fs_generation(s) (REISERFS_SB(s)->s_generation_counter)
+-#define get_generation(s) atomic_read (&fs_generation(s))
++#define get_generation(s) atomic_read_unchecked (&fs_generation(s))
+ #define FILESYSTEM_CHANGED_TB(tb) (get_generation((tb)->tb_sb) != (tb)->fs_gen)
+ #define __fs_changed(gen,s) (gen != get_generation (s))
+ #define fs_changed(gen,s) \
+@@ -1615,24 +1615,24 @@ static inline struct super_block *sb_fro
+ */
+
+ struct item_operations {
+- int (*bytes_number) (struct item_head * ih, int block_size);
+- void (*decrement_key) (struct cpu_key *);
+- int (*is_left_mergeable) (struct reiserfs_key * ih,
++ int (* const bytes_number) (struct item_head * ih, int block_size);
++ void (* const decrement_key) (struct cpu_key *);
++ int (* const is_left_mergeable) (struct reiserfs_key * ih,
+ unsigned long bsize);
+- void (*print_item) (struct item_head *, char *item);
+- void (*check_item) (struct item_head *, char *item);
++ void (* const print_item) (struct item_head *, char *item);
++ void (* const check_item) (struct item_head *, char *item);
+
+- int (*create_vi) (struct virtual_node * vn, struct virtual_item * vi,
++ int (* const create_vi) (struct virtual_node * vn, struct virtual_item * vi,
+ int is_affected, int insert_size);
+- int (*check_left) (struct virtual_item * vi, int free,
++ int (* const check_left) (struct virtual_item * vi, int free,
+ int start_skip, int end_skip);
+- int (*check_right) (struct virtual_item * vi, int free);
+- int (*part_size) (struct virtual_item * vi, int from, int to);
+- int (*unit_num) (struct virtual_item * vi);
+- void (*print_vi) (struct virtual_item * vi);
++ int (* const check_right) (struct virtual_item * vi, int free);
++ int (* const part_size) (struct virtual_item * vi, int from, int to);
++ int (* const unit_num) (struct virtual_item * vi);
++ void (* const print_vi) (struct virtual_item * vi);
+ };
+
+-extern struct item_operations *item_ops[TYPE_ANY + 1];
++extern const struct item_operations * const item_ops[TYPE_ANY + 1];
+
+ #define op_bytes_number(ih,bsize) item_ops[le_ih_k_type (ih)]->bytes_number (ih, bsize)
+ #define op_is_left_mergeable(key,bsize) item_ops[le_key_k_type (le_key_version (key), key)]->is_left_mergeable (key, bsize)
+diff -urNp linux-2.6.38.7/include/linux/reiserfs_fs_sb.h linux-2.6.38.7/include/linux/reiserfs_fs_sb.h
+--- linux-2.6.38.7/include/linux/reiserfs_fs_sb.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/reiserfs_fs_sb.h 2011-04-28 19:34:15.000000000 -0400
+@@ -386,7 +386,7 @@ struct reiserfs_sb_info {
+ /* Comment? -Hans */
+ wait_queue_head_t s_wait;
+ /* To be obsoleted soon by per buffer seals.. -Hans */
+- atomic_t s_generation_counter; // increased by one every time the
++ atomic_unchecked_t s_generation_counter; // increased by one every time the
+ // tree gets re-balanced
+ unsigned long s_properties; /* File system properties. Currently holds
+ on-disk FS format */
+diff -urNp linux-2.6.38.7/include/linux/rmap.h linux-2.6.38.7/include/linux/rmap.h
+--- linux-2.6.38.7/include/linux/rmap.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/rmap.h 2011-04-28 19:34:15.000000000 -0400
+@@ -145,8 +145,8 @@ static inline void anon_vma_unlock(struc
+ void anon_vma_init(void); /* create anon_vma_cachep */
+ int anon_vma_prepare(struct vm_area_struct *);
+ void unlink_anon_vmas(struct vm_area_struct *);
+-int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
+-int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
++int anon_vma_clone(struct vm_area_struct *, const struct vm_area_struct *);
++int anon_vma_fork(struct vm_area_struct *, const struct vm_area_struct *);
+ void __anon_vma_link(struct vm_area_struct *);
+ void anon_vma_free(struct anon_vma *);
+
+diff -urNp linux-2.6.38.7/include/linux/sched.h linux-2.6.38.7/include/linux/sched.h
+--- linux-2.6.38.7/include/linux/sched.h 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/include/linux/sched.h 2011-05-22 23:06:04.000000000 -0400
+@@ -99,6 +99,7 @@ struct robust_list_head;
+ struct bio_list;
+ struct fs_struct;
+ struct perf_event_context;
++struct linux_binprm;
+
+ /*
+ * List of flags we want to share for kernel threads,
+@@ -359,7 +360,7 @@ extern signed long schedule_timeout_inte
+ extern signed long schedule_timeout_killable(signed long timeout);
+ extern signed long schedule_timeout_uninterruptible(signed long timeout);
+ asmlinkage void schedule(void);
+-extern int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner);
++extern int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner);
+
+ struct nsproxy;
+ struct user_namespace;
+@@ -380,10 +381,13 @@ struct user_namespace;
+ #define DEFAULT_MAX_MAP_COUNT (USHRT_MAX - MAPCOUNT_ELF_CORE_MARGIN)
+
+ extern int sysctl_max_map_count;
++extern unsigned long sysctl_heap_stack_gap;
+
+ #include <linux/aio.h>
+
+ #ifdef CONFIG_MMU
++extern bool check_heap_stack_gap(const struct vm_area_struct *vma, unsigned long addr, unsigned long len);
++extern unsigned long skip_heap_stack_gap(const struct vm_area_struct *vma, unsigned long len);
+ extern void arch_pick_mmap_layout(struct mm_struct *mm);
+ extern unsigned long
+ arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
+@@ -628,6 +632,17 @@ struct signal_struct {
+ #ifdef CONFIG_TASKSTATS
+ struct taskstats *stats;
+ #endif
++
++#ifdef CONFIG_GRKERNSEC
++ u32 curr_ip;
++ u32 saved_ip;
++ u32 gr_saddr;
++ u32 gr_daddr;
++ u16 gr_sport;
++ u16 gr_dport;
++ u8 used_accept:1;
++#endif
++
+ #ifdef CONFIG_AUDIT
+ unsigned audit_tty;
+ struct tty_audit_buf *tty_audit_buf;
+@@ -700,6 +715,11 @@ struct user_struct {
+ struct key *session_keyring; /* UID's default session keyring */
+ #endif
+
++#if defined(CONFIG_GRKERNSEC_KERN_LOCKOUT) || defined(CONFIG_GRKERNSEC_BRUTE)
++ unsigned int banned;
++ unsigned long ban_expires;
++#endif
++
+ /* Hash table maintenance information */
+ struct hlist_node uidhash_node;
+ uid_t uid;
+@@ -1310,8 +1330,8 @@ struct task_struct {
+ struct list_head thread_group;
+
+ struct completion *vfork_done; /* for vfork() */
+- int __user *set_child_tid; /* CLONE_CHILD_SETTID */
+- int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */
++ pid_t __user *set_child_tid; /* CLONE_CHILD_SETTID */
++ pid_t __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */
+
+ cputime_t utime, stime, utimescaled, stimescaled;
+ cputime_t gtime;
+@@ -1327,13 +1347,6 @@ struct task_struct {
+ struct task_cputime cputime_expires;
+ struct list_head cpu_timers[3];
+
+-/* process credentials */
+- const struct cred __rcu *real_cred; /* objective and real subjective task
+- * credentials (COW) */
+- const struct cred __rcu *cred; /* effective (overridable) subjective task
+- * credentials (COW) */
+- struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */
+-
+ char comm[TASK_COMM_LEN]; /* executable name excluding path
+ - access with [gs]et_task_comm (which lock
+ it with task_lock())
+@@ -1350,8 +1363,16 @@ struct task_struct {
+ #endif
+ /* CPU-specific state of this task */
+ struct thread_struct thread;
++/* thread_info moved to task_struct */
++#ifdef CONFIG_X86
++ struct thread_info tinfo;
++#endif
+ /* filesystem information */
+ struct fs_struct *fs;
++
++ const struct cred __rcu *cred; /* effective (overridable) subjective task
++ * credentials (COW) */
++
+ /* open file information */
+ struct files_struct *files;
+ /* namespaces */
+@@ -1398,6 +1419,11 @@ struct task_struct {
+ struct rt_mutex_waiter *pi_blocked_on;
+ #endif
+
++/* process credentials */
++ const struct cred __rcu *real_cred; /* objective and real subjective task
++ * credentials (COW) */
++ struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */
++
+ #ifdef CONFIG_DEBUG_MUTEXES
+ /* mutex deadlock detection */
+ struct mutex_waiter *blocked_on;
+@@ -1502,6 +1528,21 @@ struct task_struct {
+ unsigned long default_timer_slack_ns;
+
+ struct list_head *scm_work_list;
++
++#ifdef CONFIG_GRKERNSEC
++ /* grsecurity */
++ struct dentry *gr_chroot_dentry;
++ struct acl_subject_label *acl;
++ struct acl_role_label *role;
++ struct file *exec_file;
++ u16 acl_role_id;
++ /* is this the task that authenticated to the special role */
++ u8 acl_sp_role;
++ u8 is_writable;
++ u8 brute;
++ u8 gr_is_chrooted;
++#endif
++
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ /* Index of current stored address in ret_stack */
+ int curr_ret_stack;
+@@ -1536,6 +1577,63 @@ struct task_struct {
+ #endif
+ };
+
++#define MF_PAX_PAGEEXEC 0x01000000 /* Paging based non-executable pages */
++#define MF_PAX_EMUTRAMP 0x02000000 /* Emulate trampolines */
++#define MF_PAX_MPROTECT 0x04000000 /* Restrict mprotect() */
++#define MF_PAX_RANDMMAP 0x08000000 /* Randomize mmap() base */
++/*#define MF_PAX_RANDEXEC 0x10000000*/ /* Randomize ET_EXEC base */
++#define MF_PAX_SEGMEXEC 0x20000000 /* Segmentation based non-executable pages */
++
++#ifdef CONFIG_PAX_SOFTMODE
++extern unsigned int pax_softmode;
++#endif
++
++extern int pax_check_flags(unsigned long *);
++
++/* if tsk != current then task_lock must be held on it */
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
++static inline unsigned long pax_get_flags(struct task_struct *tsk)
++{
++ if (likely(tsk->mm))
++ return tsk->mm->pax_flags;
++ else
++ return 0UL;
++}
++
++/* if tsk != current then task_lock must be held on it */
++static inline long pax_set_flags(struct task_struct *tsk, unsigned long flags)
++{
++ if (likely(tsk->mm)) {
++ tsk->mm->pax_flags = flags;
++ return 0;
++ }
++ return -EINVAL;
++}
++#endif
++
++#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
++extern void pax_set_initial_flags(struct linux_binprm *bprm);
++#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
++extern void (*pax_set_initial_flags_func)(struct linux_binprm *bprm);
++#endif
++
++void pax_report_fault(struct pt_regs *regs, void *pc, void *sp);
++void pax_report_insns(void *pc, void *sp);
++void pax_report_refcount_overflow(struct pt_regs *regs);
++void pax_report_usercopy(const void *ptr, unsigned long len, bool to, const char *type);
++
++static inline void pax_track_stack(void)
++{
++
++#ifdef CONFIG_PAX_MEMORY_STACKLEAK
++ unsigned long sp = current_stack_pointer;
++ if (current_thread_info()->lowest_stack > sp &&
++ (unsigned long)task_stack_page(current) < sp)
++ current_thread_info()->lowest_stack = sp;
++#endif
++
++}
++
+ /* Future-safe accessor for struct task_struct's cpus_allowed. */
+ #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
+
+@@ -2005,7 +2103,9 @@ void yield(void);
+ extern struct exec_domain default_exec_domain;
+
+ union thread_union {
++#ifndef CONFIG_X86
+ struct thread_info thread_info;
++#endif
+ unsigned long stack[THREAD_SIZE/sizeof(long)];
+ };
+
+@@ -2175,7 +2275,7 @@ extern void __cleanup_sighand(struct sig
+ extern void exit_itimers(struct signal_struct *);
+ extern void flush_itimer_signals(void);
+
+-extern NORET_TYPE void do_group_exit(int);
++extern NORET_TYPE void do_group_exit(int) ATTRIB_NORET;
+
+ extern void daemonize(const char *, ...);
+ extern int allow_signal(int);
+@@ -2316,13 +2416,17 @@ static inline unsigned long *end_of_stac
+
+ #endif
+
+-static inline int object_is_on_stack(void *obj)
++static inline int object_starts_on_stack(void *obj)
+ {
+- void *stack = task_stack_page(current);
++ const void *stack = task_stack_page(current);
+
+ return (obj >= stack) && (obj < (stack + THREAD_SIZE));
+ }
+
++#ifdef CONFIG_PAX_USERCOPY
++extern int object_is_on_stack(const void *obj, unsigned long len);
++#endif
++
+ extern void thread_info_cache_init(void);
+
+ #ifdef CONFIG_DEBUG_STACK_USAGE
+diff -urNp linux-2.6.38.7/include/linux/screen_info.h linux-2.6.38.7/include/linux/screen_info.h
+--- linux-2.6.38.7/include/linux/screen_info.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/screen_info.h 2011-04-28 19:34:15.000000000 -0400
+@@ -43,7 +43,8 @@ struct screen_info {
+ __u16 pages; /* 0x32 */
+ __u16 vesa_attributes; /* 0x34 */
+ __u32 capabilities; /* 0x36 */
+- __u8 _reserved[6]; /* 0x3a */
++ __u16 vesapm_size; /* 0x3a */
++ __u8 _reserved[4]; /* 0x3c */
+ } __attribute__((packed));
+
+ #define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */
+diff -urNp linux-2.6.38.7/include/linux/security.h linux-2.6.38.7/include/linux/security.h
+--- linux-2.6.38.7/include/linux/security.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/security.h 2011-04-28 19:34:15.000000000 -0400
+@@ -35,6 +35,7 @@
+ #include <linux/key.h>
+ #include <linux/xfrm.h>
+ #include <linux/slab.h>
++#include <linux/grsecurity.h>
+ #include <net/flow.h>
+
+ /* Maximum number of letters for an LSM name string */
+diff -urNp linux-2.6.38.7/include/linux/shm.h linux-2.6.38.7/include/linux/shm.h
+--- linux-2.6.38.7/include/linux/shm.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/shm.h 2011-04-28 19:34:15.000000000 -0400
+@@ -95,6 +95,10 @@ struct shmid_kernel /* private to the ke
+ pid_t shm_cprid;
+ pid_t shm_lprid;
+ struct user_struct *mlock_user;
++#ifdef CONFIG_GRKERNSEC
++ time_t shm_createtime;
++ pid_t shm_lapid;
++#endif
+ };
+
+ /* shm_mode upper byte flags */
+diff -urNp linux-2.6.38.7/include/linux/skbuff.h linux-2.6.38.7/include/linux/skbuff.h
+--- linux-2.6.38.7/include/linux/skbuff.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/skbuff.h 2011-04-28 19:57:25.000000000 -0400
+@@ -589,7 +589,7 @@ static inline struct skb_shared_hwtstamp
+ */
+ static inline int skb_queue_empty(const struct sk_buff_head *list)
+ {
+- return list->next == (struct sk_buff *)list;
++ return list->next == (const struct sk_buff *)list;
+ }
+
+ /**
+@@ -602,7 +602,7 @@ static inline int skb_queue_empty(const
+ static inline bool skb_queue_is_last(const struct sk_buff_head *list,
+ const struct sk_buff *skb)
+ {
+- return skb->next == (struct sk_buff *)list;
++ return skb->next == (const struct sk_buff *)list;
+ }
+
+ /**
+@@ -615,7 +615,7 @@ static inline bool skb_queue_is_last(con
+ static inline bool skb_queue_is_first(const struct sk_buff_head *list,
+ const struct sk_buff *skb)
+ {
+- return skb->prev == (struct sk_buff *)list;
++ return skb->prev == (const struct sk_buff *)list;
+ }
+
+ /**
+@@ -1432,7 +1432,7 @@ static inline int pskb_network_may_pull(
+ * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
+ */
+ #ifndef NET_SKB_PAD
+-#define NET_SKB_PAD max(32, L1_CACHE_BYTES)
++#define NET_SKB_PAD max(_AC(32,U), L1_CACHE_BYTES)
+ #endif
+
+ extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
+diff -urNp linux-2.6.38.7/include/linux/slab_def.h linux-2.6.38.7/include/linux/slab_def.h
+--- linux-2.6.38.7/include/linux/slab_def.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/slab_def.h 2011-04-28 19:57:25.000000000 -0400
+@@ -96,10 +96,10 @@ struct kmem_cache {
+ unsigned long node_allocs;
+ unsigned long node_frees;
+ unsigned long node_overflow;
+- atomic_t allochit;
+- atomic_t allocmiss;
+- atomic_t freehit;
+- atomic_t freemiss;
++ atomic_unchecked_t allochit;
++ atomic_unchecked_t allocmiss;
++ atomic_unchecked_t freehit;
++ atomic_unchecked_t freemiss;
+
+ /*
+ * If debugging is enabled, then the allocator can add additional
+diff -urNp linux-2.6.38.7/include/linux/slab.h linux-2.6.38.7/include/linux/slab.h
+--- linux-2.6.38.7/include/linux/slab.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/slab.h 2011-04-28 19:34:15.000000000 -0400
+@@ -11,12 +11,20 @@
+
+ #include <linux/gfp.h>
+ #include <linux/types.h>
++#include <linux/err.h>
+
+ /*
+ * Flags to pass to kmem_cache_create().
+ * The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
+ */
+ #define SLAB_DEBUG_FREE 0x00000100UL /* DEBUG: Perform (expensive) checks on free */
++
++#ifdef CONFIG_PAX_USERCOPY
++#define SLAB_USERCOPY 0x00000200UL /* PaX: Allow copying objs to/from userland */
++#else
++#define SLAB_USERCOPY 0x00000000UL
++#endif
++
+ #define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */
+ #define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */
+ #define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */
+@@ -87,10 +95,13 @@
+ * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
+ * Both make kfree a no-op.
+ */
+-#define ZERO_SIZE_PTR ((void *)16)
++#define ZERO_SIZE_PTR \
++({ \
++ BUILD_BUG_ON(!(MAX_ERRNO & ~PAGE_MASK));\
++ (void *)(-MAX_ERRNO-1L); \
++})
+
+-#define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) <= \
+- (unsigned long)ZERO_SIZE_PTR)
++#define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) - 1 >= (unsigned long)ZERO_SIZE_PTR - 1)
+
+ /*
+ * struct kmem_cache related prototypes
+@@ -142,6 +153,7 @@ void * __must_check krealloc(const void
+ void kfree(const void *);
+ void kzfree(const void *);
+ size_t ksize(const void *);
++void check_object_size(const void *ptr, unsigned long n, bool to);
+
+ /*
+ * Allocator specific definitions. These are mainly used to establish optimized
+@@ -334,4 +346,37 @@ static inline void *kzalloc_node(size_t
+
+ void __init kmem_cache_init_late(void);
+
++#define kmalloc(x, y) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "kmalloc size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = kmalloc((size_t)___x, (y)); \
++ ___retval; \
++})
++
++#define kmalloc_node(x, y, z) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "kmalloc_node size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = kmalloc_node((size_t)___x, (y), (z));\
++ ___retval; \
++})
++
++#define kzalloc(x, y) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "kzalloc size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = kzalloc((size_t)___x, (y)); \
++ ___retval; \
++})
++
+ #endif /* _LINUX_SLAB_H */
+diff -urNp linux-2.6.38.7/include/linux/slub_def.h linux-2.6.38.7/include/linux/slub_def.h
+--- linux-2.6.38.7/include/linux/slub_def.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/slub_def.h 2011-04-28 19:34:15.000000000 -0400
+@@ -79,7 +79,7 @@ struct kmem_cache {
+ struct kmem_cache_order_objects max;
+ struct kmem_cache_order_objects min;
+ gfp_t allocflags; /* gfp flags to use on each alloc */
+- int refcount; /* Refcount for slab cache destroy */
++ atomic_t refcount; /* Refcount for slab cache destroy */
+ void (*ctor)(void *);
+ int inuse; /* Offset to metadata */
+ int align; /* Alignment */
+diff -urNp linux-2.6.38.7/include/linux/sonet.h linux-2.6.38.7/include/linux/sonet.h
+--- linux-2.6.38.7/include/linux/sonet.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/sonet.h 2011-04-28 19:34:15.000000000 -0400
+@@ -61,7 +61,7 @@ struct sonet_stats {
+ #include <asm/atomic.h>
+
+ struct k_sonet_stats {
+-#define __HANDLE_ITEM(i) atomic_t i
++#define __HANDLE_ITEM(i) atomic_unchecked_t i
+ __SONET_ITEMS
+ #undef __HANDLE_ITEM
+ };
+diff -urNp linux-2.6.38.7/include/linux/sunrpc/clnt.h linux-2.6.38.7/include/linux/sunrpc/clnt.h
+--- linux-2.6.38.7/include/linux/sunrpc/clnt.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/sunrpc/clnt.h 2011-04-28 19:34:15.000000000 -0400
+@@ -168,9 +168,9 @@ static inline unsigned short rpc_get_por
+ {
+ switch (sap->sa_family) {
+ case AF_INET:
+- return ntohs(((struct sockaddr_in *)sap)->sin_port);
++ return ntohs(((const struct sockaddr_in *)sap)->sin_port);
+ case AF_INET6:
+- return ntohs(((struct sockaddr_in6 *)sap)->sin6_port);
++ return ntohs(((const struct sockaddr_in6 *)sap)->sin6_port);
+ }
+ return 0;
+ }
+@@ -203,7 +203,7 @@ static inline bool __rpc_cmp_addr4(const
+ static inline bool __rpc_copy_addr4(struct sockaddr *dst,
+ const struct sockaddr *src)
+ {
+- const struct sockaddr_in *ssin = (struct sockaddr_in *) src;
++ const struct sockaddr_in *ssin = (const struct sockaddr_in *) src;
+ struct sockaddr_in *dsin = (struct sockaddr_in *) dst;
+
+ dsin->sin_family = ssin->sin_family;
+@@ -300,7 +300,7 @@ static inline u32 rpc_get_scope_id(const
+ if (sa->sa_family != AF_INET6)
+ return 0;
+
+- return ((struct sockaddr_in6 *) sa)->sin6_scope_id;
++ return ((const struct sockaddr_in6 *) sa)->sin6_scope_id;
+ }
+
+ #endif /* __KERNEL__ */
+diff -urNp linux-2.6.38.7/include/linux/sunrpc/svc_rdma.h linux-2.6.38.7/include/linux/sunrpc/svc_rdma.h
+--- linux-2.6.38.7/include/linux/sunrpc/svc_rdma.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/sunrpc/svc_rdma.h 2011-04-28 19:57:25.000000000 -0400
+@@ -53,15 +53,15 @@ extern unsigned int svcrdma_ord;
+ extern unsigned int svcrdma_max_requests;
+ extern unsigned int svcrdma_max_req_size;
+
+-extern atomic_t rdma_stat_recv;
+-extern atomic_t rdma_stat_read;
+-extern atomic_t rdma_stat_write;
+-extern atomic_t rdma_stat_sq_starve;
+-extern atomic_t rdma_stat_rq_starve;
+-extern atomic_t rdma_stat_rq_poll;
+-extern atomic_t rdma_stat_rq_prod;
+-extern atomic_t rdma_stat_sq_poll;
+-extern atomic_t rdma_stat_sq_prod;
++extern atomic_unchecked_t rdma_stat_recv;
++extern atomic_unchecked_t rdma_stat_read;
++extern atomic_unchecked_t rdma_stat_write;
++extern atomic_unchecked_t rdma_stat_sq_starve;
++extern atomic_unchecked_t rdma_stat_rq_starve;
++extern atomic_unchecked_t rdma_stat_rq_poll;
++extern atomic_unchecked_t rdma_stat_rq_prod;
++extern atomic_unchecked_t rdma_stat_sq_poll;
++extern atomic_unchecked_t rdma_stat_sq_prod;
+
+ #define RPCRDMA_VERSION 1
+
+diff -urNp linux-2.6.38.7/include/linux/suspend.h linux-2.6.38.7/include/linux/suspend.h
+--- linux-2.6.38.7/include/linux/suspend.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/suspend.h 2011-04-28 19:34:15.000000000 -0400
+@@ -106,15 +106,15 @@ typedef int __bitwise suspend_state_t;
+ * which require special recovery actions in that situation.
+ */
+ struct platform_suspend_ops {
+- int (*valid)(suspend_state_t state);
+- int (*begin)(suspend_state_t state);
+- int (*prepare)(void);
+- int (*prepare_late)(void);
+- int (*enter)(suspend_state_t state);
+- void (*wake)(void);
+- void (*finish)(void);
+- void (*end)(void);
+- void (*recover)(void);
++ int (* const valid)(suspend_state_t state);
++ int (* const begin)(suspend_state_t state);
++ int (* const prepare)(void);
++ int (* const prepare_late)(void);
++ int (* const enter)(suspend_state_t state);
++ void (* const wake)(void);
++ void (* const finish)(void);
++ void (* const end)(void);
++ void (* const recover)(void);
+ };
+
+ #ifdef CONFIG_SUSPEND
+@@ -217,16 +217,16 @@ extern void mark_free_pages(struct zone
+ * platforms which require special recovery actions in that situation.
+ */
+ struct platform_hibernation_ops {
+- int (*begin)(void);
+- void (*end)(void);
+- int (*pre_snapshot)(void);
+- void (*finish)(void);
+- int (*prepare)(void);
+- int (*enter)(void);
+- void (*leave)(void);
+- int (*pre_restore)(void);
+- void (*restore_cleanup)(void);
+- void (*recover)(void);
++ int (* const begin)(void);
++ void (* const end)(void);
++ int (* const pre_snapshot)(void);
++ void (* const finish)(void);
++ int (* const prepare)(void);
++ int (* const enter)(void);
++ void (* const leave)(void);
++ int (* const pre_restore)(void);
++ void (* const restore_cleanup)(void);
++ void (* const recover)(void);
+ };
+
+ #ifdef CONFIG_HIBERNATION
+diff -urNp linux-2.6.38.7/include/linux/sysctl.h linux-2.6.38.7/include/linux/sysctl.h
+--- linux-2.6.38.7/include/linux/sysctl.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/sysctl.h 2011-04-28 19:34:15.000000000 -0400
+@@ -155,7 +155,11 @@ enum
+ KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
+ };
+
+-
++#ifdef CONFIG_PAX_SOFTMODE
++enum {
++ PAX_SOFTMODE=1 /* PaX: disable/enable soft mode */
++};
++#endif
+
+ /* CTL_VM names: */
+ enum
+@@ -967,6 +971,8 @@ typedef int proc_handler (struct ctl_tab
+
+ extern int proc_dostring(struct ctl_table *, int,
+ void __user *, size_t *, loff_t *);
++extern int proc_dostring_modpriv(struct ctl_table *, int,
++ void __user *, size_t *, loff_t *);
+ extern int proc_dointvec(struct ctl_table *, int,
+ void __user *, size_t *, loff_t *);
+ extern int proc_dointvec_minmax(struct ctl_table *, int,
+diff -urNp linux-2.6.38.7/include/linux/sysfs.h linux-2.6.38.7/include/linux/sysfs.h
+--- linux-2.6.38.7/include/linux/sysfs.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/sysfs.h 2011-04-28 19:34:15.000000000 -0400
+@@ -110,8 +110,8 @@ struct bin_attribute {
+ #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
+
+ struct sysfs_ops {
+- ssize_t (*show)(struct kobject *, struct attribute *,char *);
+- ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
++ ssize_t (* const show)(struct kobject *, struct attribute *,char *);
++ ssize_t (* const store)(struct kobject *,struct attribute *,const char *, size_t);
+ };
+
+ struct sysfs_dirent;
+diff -urNp linux-2.6.38.7/include/linux/tty.h linux-2.6.38.7/include/linux/tty.h
+--- linux-2.6.38.7/include/linux/tty.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/tty.h 2011-04-28 19:34:15.000000000 -0400
+@@ -13,6 +13,8 @@
+ #include <linux/tty_driver.h>
+ #include <linux/tty_ldisc.h>
+ #include <linux/mutex.h>
++#include <linux/poll.h>
++#include <linux/smp_lock.h>
+
+ #include <asm/system.h>
+
+@@ -465,7 +467,6 @@ extern int tty_perform_flush(struct tty_
+ extern dev_t tty_devnum(struct tty_struct *tty);
+ extern void proc_clear_tty(struct task_struct *p);
+ extern struct tty_struct *get_current_tty(void);
+-extern void tty_default_fops(struct file_operations *fops);
+ extern struct tty_struct *alloc_tty_struct(void);
+ extern int tty_add_file(struct tty_struct *tty, struct file *file);
+ extern void free_tty_struct(struct tty_struct *tty);
+@@ -528,6 +529,18 @@ extern void tty_ldisc_begin(void);
+ /* This last one is just for the tty layer internals and shouldn't be used elsewhere */
+ extern void tty_ldisc_enable(struct tty_struct *tty);
+
++/* tty_io.c */
++extern ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
++extern ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
++extern unsigned int tty_poll(struct file *, poll_table *);
++#ifdef CONFIG_COMPAT
++extern long tty_compat_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg);
++#else
++#define tty_compat_ioctl NULL
++#endif
++extern int tty_release(struct inode *, struct file *);
++extern int tty_fasync(int fd, struct file *filp, int on);
+
+ /* n_tty.c */
+ extern struct tty_ldisc_ops tty_ldisc_N_TTY;
+diff -urNp linux-2.6.38.7/include/linux/tty_ldisc.h linux-2.6.38.7/include/linux/tty_ldisc.h
+--- linux-2.6.38.7/include/linux/tty_ldisc.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/tty_ldisc.h 2011-04-28 19:34:15.000000000 -0400
+@@ -148,7 +148,7 @@ struct tty_ldisc_ops {
+
+ struct module *owner;
+
+- int refcount;
++ atomic_t refcount;
+ };
+
+ struct tty_ldisc {
+diff -urNp linux-2.6.38.7/include/linux/types.h linux-2.6.38.7/include/linux/types.h
+--- linux-2.6.38.7/include/linux/types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/types.h 2011-04-28 19:34:15.000000000 -0400
+@@ -207,10 +207,26 @@ typedef struct {
+ int counter;
+ } atomic_t;
+
++#ifdef CONFIG_PAX_REFCOUNT
++typedef struct {
++ int counter;
++} atomic_unchecked_t;
++#else
++typedef atomic_t atomic_unchecked_t;
++#endif
++
+ #ifdef CONFIG_64BIT
+ typedef struct {
+ long counter;
+ } atomic64_t;
++
++#ifdef CONFIG_PAX_REFCOUNT
++typedef struct {
++ long counter;
++} atomic64_unchecked_t;
++#else
++typedef atomic64_t atomic64_unchecked_t;
++#endif
+ #endif
+
+ struct list_head {
+diff -urNp linux-2.6.38.7/include/linux/uaccess.h linux-2.6.38.7/include/linux/uaccess.h
+--- linux-2.6.38.7/include/linux/uaccess.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/uaccess.h 2011-04-28 19:34:15.000000000 -0400
+@@ -76,11 +76,11 @@ static inline unsigned long __copy_from_
+ long ret; \
+ mm_segment_t old_fs = get_fs(); \
+ \
+- set_fs(KERNEL_DS); \
+ pagefault_disable(); \
++ set_fs(KERNEL_DS); \
+ ret = __copy_from_user_inatomic(&(retval), (__force typeof(retval) __user *)(addr), sizeof(retval)); \
+- pagefault_enable(); \
+ set_fs(old_fs); \
++ pagefault_enable(); \
+ ret; \
+ })
+
+@@ -93,8 +93,8 @@ static inline unsigned long __copy_from_
+ * Safely read from address @src to the buffer at @dst. If a kernel fault
+ * happens, handle that and return -EFAULT.
+ */
+-extern long probe_kernel_read(void *dst, void *src, size_t size);
+-extern long __probe_kernel_read(void *dst, void *src, size_t size);
++extern long probe_kernel_read(void *dst, const void *src, size_t size);
++extern long __probe_kernel_read(void *dst, const void *src, size_t size);
+
+ /*
+ * probe_kernel_write(): safely attempt to write to a location
+@@ -105,7 +105,7 @@ extern long __probe_kernel_read(void *ds
+ * Safely write to address @dst from the buffer at @src. If a kernel fault
+ * happens, handle that and return -EFAULT.
+ */
+-extern long notrace probe_kernel_write(void *dst, void *src, size_t size);
+-extern long notrace __probe_kernel_write(void *dst, void *src, size_t size);
++extern long notrace probe_kernel_write(void *dst, const void *src, size_t size);
++extern long notrace __probe_kernel_write(void *dst, const void *src, size_t size);
+
+ #endif /* __LINUX_UACCESS_H__ */
+diff -urNp linux-2.6.38.7/include/linux/unaligned/access_ok.h linux-2.6.38.7/include/linux/unaligned/access_ok.h
+--- linux-2.6.38.7/include/linux/unaligned/access_ok.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/unaligned/access_ok.h 2011-04-28 19:34:15.000000000 -0400
+@@ -6,32 +6,32 @@
+
+ static inline u16 get_unaligned_le16(const void *p)
+ {
+- return le16_to_cpup((__le16 *)p);
++ return le16_to_cpup((const __le16 *)p);
+ }
+
+ static inline u32 get_unaligned_le32(const void *p)
+ {
+- return le32_to_cpup((__le32 *)p);
++ return le32_to_cpup((const __le32 *)p);
+ }
+
+ static inline u64 get_unaligned_le64(const void *p)
+ {
+- return le64_to_cpup((__le64 *)p);
++ return le64_to_cpup((const __le64 *)p);
+ }
+
+ static inline u16 get_unaligned_be16(const void *p)
+ {
+- return be16_to_cpup((__be16 *)p);
++ return be16_to_cpup((const __be16 *)p);
+ }
+
+ static inline u32 get_unaligned_be32(const void *p)
+ {
+- return be32_to_cpup((__be32 *)p);
++ return be32_to_cpup((const __be32 *)p);
+ }
+
+ static inline u64 get_unaligned_be64(const void *p)
+ {
+- return be64_to_cpup((__be64 *)p);
++ return be64_to_cpup((const __be64 *)p);
+ }
+
+ static inline void put_unaligned_le16(u16 val, void *p)
+diff -urNp linux-2.6.38.7/include/linux/usb/hcd.h linux-2.6.38.7/include/linux/usb/hcd.h
+--- linux-2.6.38.7/include/linux/usb/hcd.h 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/include/linux/usb/hcd.h 2011-04-28 19:34:15.000000000 -0400
+@@ -589,7 +589,7 @@ struct usb_mon_operations {
+ /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
+ };
+
+-extern struct usb_mon_operations *mon_ops;
++extern const struct usb_mon_operations *mon_ops;
+
+ static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb)
+ {
+@@ -611,7 +611,7 @@ static inline void usbmon_urb_complete(s
+ (*mon_ops->urb_complete)(bus, urb, status);
+ }
+
+-int usb_mon_register(struct usb_mon_operations *ops);
++int usb_mon_register(const struct usb_mon_operations *ops);
+ void usb_mon_deregister(void);
+
+ #else
+diff -urNp linux-2.6.38.7/include/linux/vmalloc.h linux-2.6.38.7/include/linux/vmalloc.h
+--- linux-2.6.38.7/include/linux/vmalloc.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/vmalloc.h 2011-04-28 19:34:15.000000000 -0400
+@@ -13,6 +13,11 @@ struct vm_area_struct; /* vma defining
+ #define VM_MAP 0x00000004 /* vmap()ed pages */
+ #define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */
+ #define VM_VPAGES 0x00000010 /* buffer for pages was vmalloc'ed */
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86) && defined(CONFIG_PAX_KERNEXEC)
++#define VM_KERNEXEC 0x00000020 /* allocate from executable kernel memory range */
++#endif
++
+ /* bits [20..32] reserved for arch specific ioremap internals */
+
+ /*
+@@ -123,4 +128,103 @@ struct vm_struct **pcpu_get_vm_areas(con
+ void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms);
+ #endif
+
++#define vmalloc(x) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "vmalloc size overflow\n")) \
++ ___retval = NULL; \
++ else \
++ ___retval = vmalloc((unsigned long)___x); \
++ ___retval; \
++})
++
++#define vzalloc(x) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "vzalloc size overflow\n")) \
++ ___retval = NULL; \
++ else \
++ ___retval = vzalloc((unsigned long)___x); \
++ ___retval; \
++})
++
++#define __vmalloc(x, y, z) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "__vmalloc size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = __vmalloc((unsigned long)___x, (y), (z));\
++ ___retval; \
++})
++
++#define vmalloc_user(x) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "vmalloc_user size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = vmalloc_user((unsigned long)___x); \
++ ___retval; \
++})
++
++#define vmalloc_exec(x) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "vmalloc_exec size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = vmalloc_exec((unsigned long)___x); \
++ ___retval; \
++})
++
++#define vmalloc_node(x, y) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "vmalloc_node size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = vmalloc_node((unsigned long)___x, (y));\
++ ___retval; \
++})
++
++#define vzalloc_node(x, y) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "vzalloc_node size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = vzalloc_node((unsigned long)___x, (y));\
++ ___retval; \
++})
++
++#define vmalloc_32(x) \
++({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "vmalloc_32 size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = vmalloc_32((unsigned long)___x); \
++ ___retval; \
++})
++
++#define vmalloc_32_user(x) \
++({ \
++void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (WARN(___x > ULONG_MAX, "vmalloc_32_user size overflow\n"))\
++ ___retval = NULL; \
++ else \
++ ___retval = vmalloc_32_user((unsigned long)___x);\
++ ___retval; \
++})
++
+ #endif /* _LINUX_VMALLOC_H */
+diff -urNp linux-2.6.38.7/include/linux/vmstat.h linux-2.6.38.7/include/linux/vmstat.h
+--- linux-2.6.38.7/include/linux/vmstat.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/linux/vmstat.h 2011-04-28 19:34:15.000000000 -0400
+@@ -140,18 +140,18 @@ static inline void vm_events_fold_cpu(in
+ /*
+ * Zone based page accounting with per cpu differentials.
+ */
+-extern atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
++extern atomic_long_unchecked_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+
+ static inline void zone_page_state_add(long x, struct zone *zone,
+ enum zone_stat_item item)
+ {
+- atomic_long_add(x, &zone->vm_stat[item]);
+- atomic_long_add(x, &vm_stat[item]);
++ atomic_long_add_unchecked(x, &zone->vm_stat[item]);
++ atomic_long_add_unchecked(x, &vm_stat[item]);
+ }
+
+ static inline unsigned long global_page_state(enum zone_stat_item item)
+ {
+- long x = atomic_long_read(&vm_stat[item]);
++ long x = atomic_long_read_unchecked(&vm_stat[item]);
+ #ifdef CONFIG_SMP
+ if (x < 0)
+ x = 0;
+@@ -162,7 +162,7 @@ static inline unsigned long global_page_
+ static inline unsigned long zone_page_state(struct zone *zone,
+ enum zone_stat_item item)
+ {
+- long x = atomic_long_read(&zone->vm_stat[item]);
++ long x = atomic_long_read_unchecked(&zone->vm_stat[item]);
+ #ifdef CONFIG_SMP
+ if (x < 0)
+ x = 0;
+@@ -179,7 +179,7 @@ static inline unsigned long zone_page_st
+ static inline unsigned long zone_page_state_snapshot(struct zone *zone,
+ enum zone_stat_item item)
+ {
+- long x = atomic_long_read(&zone->vm_stat[item]);
++ long x = atomic_long_read_unchecked(&zone->vm_stat[item]);
+
+ #ifdef CONFIG_SMP
+ int cpu;
+@@ -273,8 +273,8 @@ static inline void __mod_zone_page_state
+
+ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
+ {
+- atomic_long_inc(&zone->vm_stat[item]);
+- atomic_long_inc(&vm_stat[item]);
++ atomic_long_inc_unchecked(&zone->vm_stat[item]);
++ atomic_long_inc_unchecked(&vm_stat[item]);
+ }
+
+ static inline void __inc_zone_page_state(struct page *page,
+@@ -285,8 +285,8 @@ static inline void __inc_zone_page_state
+
+ static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
+ {
+- atomic_long_dec(&zone->vm_stat[item]);
+- atomic_long_dec(&vm_stat[item]);
++ atomic_long_dec_unchecked(&zone->vm_stat[item]);
++ atomic_long_dec_unchecked(&vm_stat[item]);
+ }
+
+ static inline void __dec_zone_page_state(struct page *page,
+diff -urNp linux-2.6.38.7/include/media/v4l2-device.h linux-2.6.38.7/include/media/v4l2-device.h
+--- linux-2.6.38.7/include/media/v4l2-device.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/media/v4l2-device.h 2011-04-28 19:57:25.000000000 -0400
+@@ -77,7 +77,7 @@ int __must_check v4l2_device_register(st
+ this function returns 0. If the name ends with a digit (e.g. cx18),
+ then the name will be set to cx18-0 since cx180 looks really odd. */
+ int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
+- atomic_t *instance);
++ atomic_unchecked_t *instance);
+
+ /* Set v4l2_dev->dev to NULL. Call when the USB parent disconnects.
+ Since the parent disappears this ensures that v4l2_dev doesn't have an
+diff -urNp linux-2.6.38.7/include/net/caif/cfctrl.h linux-2.6.38.7/include/net/caif/cfctrl.h
+--- linux-2.6.38.7/include/net/caif/cfctrl.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/caif/cfctrl.h 2011-04-28 19:57:25.000000000 -0400
+@@ -101,8 +101,8 @@ struct cfctrl_request_info {
+ struct cfctrl {
+ struct cfsrvl serv;
+ struct cfctrl_rsp res;
+- atomic_t req_seq_no;
+- atomic_t rsp_seq_no;
++ atomic_unchecked_t req_seq_no;
++ atomic_unchecked_t rsp_seq_no;
+ struct list_head list;
+ /* Protects from simultaneous access to first_req list */
+ spinlock_t info_list_lock;
+diff -urNp linux-2.6.38.7/include/net/flow.h linux-2.6.38.7/include/net/flow.h
+--- linux-2.6.38.7/include/net/flow.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/flow.h 2011-04-28 19:57:25.000000000 -0400
+@@ -109,7 +109,7 @@ extern struct flow_cache_object *flow_ca
+ u8 dir, flow_resolve_t resolver, void *ctx);
+
+ extern void flow_cache_flush(void);
+-extern atomic_t flow_cache_genid;
++extern atomic_unchecked_t flow_cache_genid;
+
+ static inline int flow_cache_uli_match(struct flowi *fl1, struct flowi *fl2)
+ {
+diff -urNp linux-2.6.38.7/include/net/inetpeer.h linux-2.6.38.7/include/net/inetpeer.h
+--- linux-2.6.38.7/include/net/inetpeer.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/inetpeer.h 2011-04-28 19:34:15.000000000 -0400
+@@ -38,8 +38,8 @@ struct inet_peer {
+ */
+ union {
+ struct {
+- atomic_t rid; /* Frag reception counter */
+- atomic_t ip_id_count; /* IP ID for the next packet */
++ atomic_unchecked_t rid; /* Frag reception counter */
++ atomic_unchecked_t ip_id_count; /* IP ID for the next packet */
+ __u32 tcp_ts;
+ __u32 tcp_ts_stamp;
+ };
+@@ -88,7 +88,7 @@ static inline __u16 inet_getid(struct in
+ {
+ more++;
+ inet_peer_refcheck(p);
+- return atomic_add_return(more, &p->ip_id_count) - more;
++ return atomic_add_return_unchecked(more, &p->ip_id_count) - more;
+ }
+
+ #endif /* _NET_INETPEER_H */
+diff -urNp linux-2.6.38.7/include/net/ip_vs.h linux-2.6.38.7/include/net/ip_vs.h
+--- linux-2.6.38.7/include/net/ip_vs.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/ip_vs.h 2011-04-28 19:57:25.000000000 -0400
+@@ -404,7 +404,7 @@ struct ip_vs_conn {
+ struct ip_vs_conn *control; /* Master control connection */
+ atomic_t n_control; /* Number of controlled ones */
+ struct ip_vs_dest *dest; /* real server */
+- atomic_t in_pkts; /* incoming packet counter */
++ atomic_unchecked_t in_pkts; /* incoming packet counter */
+
+ /* packet transmitter for different forwarding methods. If it
+ mangles the packet, it must return NF_DROP or better NF_STOLEN,
+@@ -513,7 +513,7 @@ struct ip_vs_dest {
+ union nf_inet_addr addr; /* IP address of the server */
+ __be16 port; /* port number of the server */
+ volatile unsigned flags; /* dest status flags */
+- atomic_t conn_flags; /* flags to copy to conn */
++ atomic_unchecked_t conn_flags; /* flags to copy to conn */
+ atomic_t weight; /* server weight */
+
+ atomic_t refcnt; /* reference counter */
+diff -urNp linux-2.6.38.7/include/net/irda/ircomm_tty.h linux-2.6.38.7/include/net/irda/ircomm_tty.h
+--- linux-2.6.38.7/include/net/irda/ircomm_tty.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/irda/ircomm_tty.h 2011-04-28 19:34:15.000000000 -0400
+@@ -35,6 +35,7 @@
+ #include <linux/termios.h>
+ #include <linux/timer.h>
+ #include <linux/tty.h> /* struct tty_struct */
++#include <asm/local.h>
+
+ #include <net/irda/irias_object.h>
+ #include <net/irda/ircomm_core.h>
+@@ -105,8 +106,8 @@ struct ircomm_tty_cb {
+ unsigned short close_delay;
+ unsigned short closing_wait; /* time to wait before closing */
+
+- int open_count;
+- int blocked_open; /* # of blocked opens */
++ local_t open_count;
++ local_t blocked_open; /* # of blocked opens */
+
+ /* Protect concurent access to :
+ * o self->open_count
+diff -urNp linux-2.6.38.7/include/net/iucv/af_iucv.h linux-2.6.38.7/include/net/iucv/af_iucv.h
+--- linux-2.6.38.7/include/net/iucv/af_iucv.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/iucv/af_iucv.h 2011-04-28 19:57:25.000000000 -0400
+@@ -87,7 +87,7 @@ struct iucv_sock {
+ struct iucv_sock_list {
+ struct hlist_head head;
+ rwlock_t lock;
+- atomic_t autobind_name;
++ atomic_unchecked_t autobind_name;
+ };
+
+ unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
+diff -urNp linux-2.6.38.7/include/net/neighbour.h linux-2.6.38.7/include/net/neighbour.h
+--- linux-2.6.38.7/include/net/neighbour.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/neighbour.h 2011-04-28 19:34:15.000000000 -0400
+@@ -118,12 +118,12 @@ struct neighbour {
+
+ struct neigh_ops {
+ int family;
+- void (*solicit)(struct neighbour *, struct sk_buff*);
+- void (*error_report)(struct neighbour *, struct sk_buff*);
+- int (*output)(struct sk_buff*);
+- int (*connected_output)(struct sk_buff*);
+- int (*hh_output)(struct sk_buff*);
+- int (*queue_xmit)(struct sk_buff*);
++ void (* const solicit)(struct neighbour *, struct sk_buff*);
++ void (* const error_report)(struct neighbour *, struct sk_buff*);
++ int (* const output)(struct sk_buff*);
++ int (* const connected_output)(struct sk_buff*);
++ int (* const hh_output)(struct sk_buff*);
++ int (* const queue_xmit)(struct sk_buff*);
+ };
+
+ struct pneigh_entry {
+diff -urNp linux-2.6.38.7/include/net/netlink.h linux-2.6.38.7/include/net/netlink.h
+--- linux-2.6.38.7/include/net/netlink.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/netlink.h 2011-04-28 19:34:15.000000000 -0400
+@@ -562,7 +562,7 @@ static inline void *nlmsg_get_pos(struct
+ static inline void nlmsg_trim(struct sk_buff *skb, const void *mark)
+ {
+ if (mark)
+- skb_trim(skb, (unsigned char *) mark - skb->data);
++ skb_trim(skb, (const unsigned char *) mark - skb->data);
+ }
+
+ /**
+diff -urNp linux-2.6.38.7/include/net/netns/ipv4.h linux-2.6.38.7/include/net/netns/ipv4.h
+--- linux-2.6.38.7/include/net/netns/ipv4.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/netns/ipv4.h 2011-04-28 19:57:25.000000000 -0400
+@@ -55,7 +55,7 @@ struct netns_ipv4 {
+ int sysctl_rt_cache_rebuild_count;
+ int current_rt_cache_rebuild_count;
+
+- atomic_t rt_genid;
++ atomic_unchecked_t rt_genid;
+
+ #ifdef CONFIG_IP_MROUTE
+ #ifndef CONFIG_IP_MROUTE_MULTIPLE_TABLES
+diff -urNp linux-2.6.38.7/include/net/sctp/sctp.h linux-2.6.38.7/include/net/sctp/sctp.h
+--- linux-2.6.38.7/include/net/sctp/sctp.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/sctp/sctp.h 2011-04-28 19:34:15.000000000 -0400
+@@ -316,9 +316,9 @@ do { \
+
+ #else /* SCTP_DEBUG */
+
+-#define SCTP_DEBUG_PRINTK(whatever...)
+-#define SCTP_DEBUG_PRINTK_CONT(fmt, args...)
+-#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
++#define SCTP_DEBUG_PRINTK(whatever...) do {} while (0)
++#define SCTP_DEBUG_PRINTK_CONT(fmt, args...) do {} while (0)
++#define SCTP_DEBUG_PRINTK_IPADDR(whatever...) do {} while (0)
+ #define SCTP_ENABLE_DEBUG
+ #define SCTP_DISABLE_DEBUG
+ #define SCTP_ASSERT(expr, str, func)
+diff -urNp linux-2.6.38.7/include/net/sock.h linux-2.6.38.7/include/net/sock.h
+--- linux-2.6.38.7/include/net/sock.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/sock.h 2011-04-28 19:57:25.000000000 -0400
+@@ -277,7 +277,7 @@ struct sock {
+ #ifdef CONFIG_RPS
+ __u32 sk_rxhash;
+ #endif
+- atomic_t sk_drops;
++ atomic_unchecked_t sk_drops;
+ int sk_rcvbuf;
+
+ struct sk_filter __rcu *sk_filter;
+diff -urNp linux-2.6.38.7/include/net/tcp.h linux-2.6.38.7/include/net/tcp.h
+--- linux-2.6.38.7/include/net/tcp.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/tcp.h 2011-04-28 19:34:15.000000000 -0400
+@@ -1382,7 +1382,7 @@ enum tcp_seq_states {
+ struct tcp_seq_afinfo {
+ char *name;
+ sa_family_t family;
+- struct file_operations seq_fops;
++ struct file_operations seq_fops; /* cannot be const */
+ struct seq_operations seq_ops;
+ };
+
+diff -urNp linux-2.6.38.7/include/net/udp.h linux-2.6.38.7/include/net/udp.h
+--- linux-2.6.38.7/include/net/udp.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/udp.h 2011-04-28 19:34:15.000000000 -0400
+@@ -223,7 +223,7 @@ struct udp_seq_afinfo {
+ char *name;
+ sa_family_t family;
+ struct udp_table *udp_table;
+- struct file_operations seq_fops;
++ struct file_operations seq_fops; /* cannot be const */
+ struct seq_operations seq_ops;
+ };
+
+diff -urNp linux-2.6.38.7/include/net/xfrm.h linux-2.6.38.7/include/net/xfrm.h
+--- linux-2.6.38.7/include/net/xfrm.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/net/xfrm.h 2011-04-28 19:57:25.000000000 -0400
+@@ -484,7 +484,7 @@ struct xfrm_policy {
+ struct timer_list timer;
+
+ struct flow_cache_object flo;
+- atomic_t genid;
++ atomic_unchecked_t genid;
+ u32 priority;
+ u32 index;
+ struct xfrm_mark mark;
+diff -urNp linux-2.6.38.7/include/scsi/scsi_device.h linux-2.6.38.7/include/scsi/scsi_device.h
+--- linux-2.6.38.7/include/scsi/scsi_device.h 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/include/scsi/scsi_device.h 2011-04-28 19:57:25.000000000 -0400
+@@ -161,9 +161,9 @@ struct scsi_device {
+ unsigned int max_device_blocked; /* what device_blocked counts down from */
+ #define SCSI_DEFAULT_DEVICE_BLOCKED 3
+
+- atomic_t iorequest_cnt;
+- atomic_t iodone_cnt;
+- atomic_t ioerr_cnt;
++ atomic_unchecked_t iorequest_cnt;
++ atomic_unchecked_t iodone_cnt;
++ atomic_unchecked_t ioerr_cnt;
+
+ struct device sdev_gendev,
+ sdev_dev;
+diff -urNp linux-2.6.38.7/include/sound/ac97_codec.h linux-2.6.38.7/include/sound/ac97_codec.h
+--- linux-2.6.38.7/include/sound/ac97_codec.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/sound/ac97_codec.h 2011-04-28 19:34:15.000000000 -0400
+@@ -419,15 +419,15 @@
+ struct snd_ac97;
+
+ struct snd_ac97_build_ops {
+- int (*build_3d) (struct snd_ac97 *ac97);
+- int (*build_specific) (struct snd_ac97 *ac97);
+- int (*build_spdif) (struct snd_ac97 *ac97);
+- int (*build_post_spdif) (struct snd_ac97 *ac97);
++ int (* const build_3d) (struct snd_ac97 *ac97);
++ int (* const build_specific) (struct snd_ac97 *ac97);
++ int (* const build_spdif) (struct snd_ac97 *ac97);
++ int (* const build_post_spdif) (struct snd_ac97 *ac97);
+ #ifdef CONFIG_PM
+- void (*suspend) (struct snd_ac97 *ac97);
+- void (*resume) (struct snd_ac97 *ac97);
++ void (* const suspend) (struct snd_ac97 *ac97);
++ void (* const resume) (struct snd_ac97 *ac97);
+ #endif
+- void (*update_jacks) (struct snd_ac97 *ac97); /* for jack-sharing */
++ void (* const update_jacks) (struct snd_ac97 *ac97); /* for jack-sharing */
+ };
+
+ struct snd_ac97_bus_ops {
+diff -urNp linux-2.6.38.7/include/sound/ymfpci.h linux-2.6.38.7/include/sound/ymfpci.h
+--- linux-2.6.38.7/include/sound/ymfpci.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/sound/ymfpci.h 2011-04-28 19:57:25.000000000 -0400
+@@ -358,7 +358,7 @@ struct snd_ymfpci {
+ spinlock_t reg_lock;
+ spinlock_t voice_lock;
+ wait_queue_head_t interrupt_sleep;
+- atomic_t interrupt_sleep_count;
++ atomic_unchecked_t interrupt_sleep_count;
+ struct snd_info_entry *proc_entry;
+ const struct firmware *dsp_microcode;
+ const struct firmware *controller_microcode;
+diff -urNp linux-2.6.38.7/include/target/target_core_base.h linux-2.6.38.7/include/target/target_core_base.h
+--- linux-2.6.38.7/include/target/target_core_base.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/target/target_core_base.h 2011-04-28 19:57:25.000000000 -0400
+@@ -431,8 +431,8 @@ struct se_transport_task {
+ atomic_t t_task_cdbs_left;
+ atomic_t t_task_cdbs_ex_left;
+ atomic_t t_task_cdbs_timeout_left;
+- atomic_t t_task_cdbs_sent;
+- atomic_t t_transport_aborted;
++ atomic_unchecked_t t_task_cdbs_sent;
++ atomic_unchecked_t t_transport_aborted;
+ atomic_t t_transport_active;
+ atomic_t t_transport_complete;
+ atomic_t t_transport_queue_active;
+@@ -753,7 +753,7 @@ struct se_device {
+ atomic_t active_cmds;
+ atomic_t simple_cmds;
+ atomic_t depth_left;
+- atomic_t dev_ordered_id;
++ atomic_unchecked_t dev_ordered_id;
+ atomic_t dev_tur_active;
+ atomic_t execute_tasks;
+ atomic_t dev_status_thr_count;
+diff -urNp linux-2.6.38.7/include/trace/events/irq.h linux-2.6.38.7/include/trace/events/irq.h
+--- linux-2.6.38.7/include/trace/events/irq.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/trace/events/irq.h 2011-04-28 19:34:15.000000000 -0400
+@@ -36,7 +36,7 @@ struct softirq_action;
+ */
+ TRACE_EVENT(irq_handler_entry,
+
+- TP_PROTO(int irq, struct irqaction *action),
++ TP_PROTO(int irq, const struct irqaction *action),
+
+ TP_ARGS(irq, action),
+
+@@ -66,7 +66,7 @@ TRACE_EVENT(irq_handler_entry,
+ */
+ TRACE_EVENT(irq_handler_exit,
+
+- TP_PROTO(int irq, struct irqaction *action, int ret),
++ TP_PROTO(int irq, const struct irqaction *action, int ret),
+
+ TP_ARGS(irq, action, ret),
+
+diff -urNp linux-2.6.38.7/include/video/udlfb.h linux-2.6.38.7/include/video/udlfb.h
+--- linux-2.6.38.7/include/video/udlfb.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/video/udlfb.h 2011-04-28 19:57:25.000000000 -0400
+@@ -51,10 +51,10 @@ struct dlfb_data {
+ int base8;
+ u32 pseudo_palette[256];
+ /* blit-only rendering path metrics, exposed through sysfs */
+- atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */
+- atomic_t bytes_identical; /* saved effort with backbuffer comparison */
+- atomic_t bytes_sent; /* to usb, after compression including overhead */
+- atomic_t cpu_kcycles_used; /* transpired during pixel processing */
++ atomic_unchecked_t bytes_rendered; /* raw pixel-bytes driver asked to render */
++ atomic_unchecked_t bytes_identical; /* saved effort with backbuffer comparison */
++ atomic_unchecked_t bytes_sent; /* to usb, after compression including overhead */
++ atomic_unchecked_t cpu_kcycles_used; /* transpired during pixel processing */
+ };
+
+ #define NR_USB_REQUEST_I2C_SUB_IO 0x02
+diff -urNp linux-2.6.38.7/include/video/uvesafb.h linux-2.6.38.7/include/video/uvesafb.h
+--- linux-2.6.38.7/include/video/uvesafb.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/include/video/uvesafb.h 2011-04-28 19:34:15.000000000 -0400
+@@ -177,6 +177,7 @@ struct uvesafb_par {
+ u8 ypan; /* 0 - nothing, 1 - ypan, 2 - ywrap */
+ u8 pmi_setpal; /* PMI for palette changes */
+ u16 *pmi_base; /* protected mode interface location */
++ u8 *pmi_code; /* protected mode code location */
+ void *pmi_start;
+ void *pmi_pal;
+ u8 *vbe_state_orig; /*
+diff -urNp linux-2.6.38.7/init/do_mounts.c linux-2.6.38.7/init/do_mounts.c
+--- linux-2.6.38.7/init/do_mounts.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/init/do_mounts.c 2011-04-28 19:34:15.000000000 -0400
+@@ -287,7 +287,7 @@ static void __init get_fs_names(char *pa
+
+ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
+ {
+- int err = sys_mount(name, "/root", fs, flags, data);
++ int err = sys_mount((__force char __user *)name, (__force char __user *)"/root", (__force char __user *)fs, flags, (__force void __user *)data);
+ if (err)
+ return err;
+
+@@ -382,18 +382,18 @@ void __init change_floppy(char *fmt, ...
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+- fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0);
++ fd = sys_open((char __user *)"/dev/root", O_RDWR | O_NDELAY, 0);
+ if (fd >= 0) {
+ sys_ioctl(fd, FDEJECT, 0);
+ sys_close(fd);
+ }
+ printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf);
+- fd = sys_open("/dev/console", O_RDWR, 0);
++ fd = sys_open((__force const char __user *)"/dev/console", O_RDWR, 0);
+ if (fd >= 0) {
+ sys_ioctl(fd, TCGETS, (long)&termios);
+ termios.c_lflag &= ~ICANON;
+ sys_ioctl(fd, TCSETSF, (long)&termios);
+- sys_read(fd, &c, 1);
++ sys_read(fd, (char __user *)&c, 1);
+ termios.c_lflag |= ICANON;
+ sys_ioctl(fd, TCSETSF, (long)&termios);
+ sys_close(fd);
+@@ -487,6 +487,6 @@ void __init prepare_namespace(void)
+ mount_root();
+ out:
+ devtmpfs_mount("dev");
+- sys_mount(".", "/", NULL, MS_MOVE, NULL);
++ sys_mount((__force char __user *)".", (__force char __user *)"/", NULL, MS_MOVE, NULL);
+ sys_chroot((const char __user __force *)".");
+ }
+diff -urNp linux-2.6.38.7/init/do_mounts.h linux-2.6.38.7/init/do_mounts.h
+--- linux-2.6.38.7/init/do_mounts.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/init/do_mounts.h 2011-04-28 19:34:15.000000000 -0400
+@@ -15,15 +15,15 @@ extern int root_mountflags;
+
+ static inline int create_dev(char *name, dev_t dev)
+ {
+- sys_unlink(name);
+- return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev));
++ sys_unlink((__force char __user *)name);
++ return sys_mknod((__force char __user *)name, S_IFBLK|0600, new_encode_dev(dev));
+ }
+
+ #if BITS_PER_LONG == 32
+ static inline u32 bstat(char *name)
+ {
+ struct stat64 stat;
+- if (sys_stat64(name, &stat) != 0)
++ if (sys_stat64((__force char __user *)name, (__force struct stat64 __user *)&stat) != 0)
+ return 0;
+ if (!S_ISBLK(stat.st_mode))
+ return 0;
+diff -urNp linux-2.6.38.7/init/do_mounts_initrd.c linux-2.6.38.7/init/do_mounts_initrd.c
+--- linux-2.6.38.7/init/do_mounts_initrd.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/init/do_mounts_initrd.c 2011-04-28 19:34:15.000000000 -0400
+@@ -44,13 +44,13 @@ static void __init handle_initrd(void)
+ create_dev("/dev/root.old", Root_RAM0);
+ /* mount initrd on rootfs' /root */
+ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
+- sys_mkdir("/old", 0700);
+- root_fd = sys_open("/", 0, 0);
+- old_fd = sys_open("/old", 0, 0);
++ sys_mkdir((__force const char __user *)"/old", 0700);
++ root_fd = sys_open((__force const char __user *)"/", 0, 0);
++ old_fd = sys_open((__force const char __user *)"/old", 0, 0);
+ /* move initrd over / and chdir/chroot in initrd root */
+- sys_chdir("/root");
+- sys_mount(".", "/", NULL, MS_MOVE, NULL);
+- sys_chroot(".");
++ sys_chdir((__force const char __user *)"/root");
++ sys_mount((__force char __user *)".", (__force char __user *)"/", NULL, MS_MOVE, NULL);
++ sys_chroot((__force const char __user *)".");
+
+ /*
+ * In case that a resume from disk is carried out by linuxrc or one of
+@@ -67,15 +67,15 @@ static void __init handle_initrd(void)
+
+ /* move initrd to rootfs' /old */
+ sys_fchdir(old_fd);
+- sys_mount("/", ".", NULL, MS_MOVE, NULL);
++ sys_mount((__force char __user *)"/", (__force char __user *)".", NULL, MS_MOVE, NULL);
+ /* switch root and cwd back to / of rootfs */
+ sys_fchdir(root_fd);
+- sys_chroot(".");
++ sys_chroot((__force const char __user *)".");
+ sys_close(old_fd);
+ sys_close(root_fd);
+
+ if (new_decode_dev(real_root_dev) == Root_RAM0) {
+- sys_chdir("/old");
++ sys_chdir((__force const char __user *)"/old");
+ return;
+ }
+
+@@ -83,17 +83,17 @@ static void __init handle_initrd(void)
+ mount_root();
+
+ printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
+- error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
++ error = sys_mount((__force char __user *)"/old", (__force char __user *)"/root/initrd", NULL, MS_MOVE, NULL);
+ if (!error)
+ printk("okay\n");
+ else {
+- int fd = sys_open("/dev/root.old", O_RDWR, 0);
++ int fd = sys_open((__force const char __user *)"/dev/root.old", O_RDWR, 0);
+ if (error == -ENOENT)
+ printk("/initrd does not exist. Ignored.\n");
+ else
+ printk("failed\n");
+ printk(KERN_NOTICE "Unmounting old root\n");
+- sys_umount("/old", MNT_DETACH);
++ sys_umount((__force char __user *)"/old", MNT_DETACH);
+ printk(KERN_NOTICE "Trying to free ramdisk memory ... ");
+ if (fd < 0) {
+ error = fd;
+@@ -116,11 +116,11 @@ int __init initrd_load(void)
+ * mounted in the normal path.
+ */
+ if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {
+- sys_unlink("/initrd.image");
++ sys_unlink((__force const char __user *)"/initrd.image");
+ handle_initrd();
+ return 1;
+ }
+ }
+- sys_unlink("/initrd.image");
++ sys_unlink((__force const char __user *)"/initrd.image");
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/init/do_mounts_md.c linux-2.6.38.7/init/do_mounts_md.c
+--- linux-2.6.38.7/init/do_mounts_md.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/init/do_mounts_md.c 2011-04-28 19:34:15.000000000 -0400
+@@ -170,7 +170,7 @@ static void __init md_setup_drive(void)
+ partitioned ? "_d" : "", minor,
+ md_setup_args[ent].device_names);
+
+- fd = sys_open(name, 0, 0);
++ fd = sys_open((__force char __user *)name, 0, 0);
+ if (fd < 0) {
+ printk(KERN_ERR "md: open failed - cannot start "
+ "array %s\n", name);
+@@ -233,7 +233,7 @@ static void __init md_setup_drive(void)
+ * array without it
+ */
+ sys_close(fd);
+- fd = sys_open(name, 0, 0);
++ fd = sys_open((__force char __user *)name, 0, 0);
+ sys_ioctl(fd, BLKRRPART, 0);
+ }
+ sys_close(fd);
+diff -urNp linux-2.6.38.7/init/initramfs.c linux-2.6.38.7/init/initramfs.c
+--- linux-2.6.38.7/init/initramfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/init/initramfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -74,7 +74,7 @@ static void __init free_hash(void)
+ }
+ }
+
+-static long __init do_utime(char __user *filename, time_t mtime)
++static long __init do_utime(__force char __user *filename, time_t mtime)
+ {
+ struct timespec t[2];
+
+@@ -109,7 +109,7 @@ static void __init dir_utime(void)
+ struct dir_entry *de, *tmp;
+ list_for_each_entry_safe(de, tmp, &dir_list, list) {
+ list_del(&de->list);
+- do_utime(de->name, de->mtime);
++ do_utime((__force char __user *)de->name, de->mtime);
+ kfree(de->name);
+ kfree(de);
+ }
+@@ -271,7 +271,7 @@ static int __init maybe_link(void)
+ if (nlink >= 2) {
+ char *old = find_link(major, minor, ino, mode, collected);
+ if (old)
+- return (sys_link(old, collected) < 0) ? -1 : 1;
++ return (sys_link((__force char __user *)old, (__force char __user *)collected) < 0) ? -1 : 1;
+ }
+ return 0;
+ }
+@@ -280,11 +280,11 @@ static void __init clean_path(char *path
+ {
+ struct stat st;
+
+- if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) {
++ if (!sys_newlstat((__force char __user *)path, (__force struct stat __user *)&st) && (st.st_mode^mode) & S_IFMT) {
+ if (S_ISDIR(st.st_mode))
+- sys_rmdir(path);
++ sys_rmdir((__force char __user *)path);
+ else
+- sys_unlink(path);
++ sys_unlink((__force char __user *)path);
+ }
+ }
+
+@@ -305,7 +305,7 @@ static int __init do_name(void)
+ int openflags = O_WRONLY|O_CREAT;
+ if (ml != 1)
+ openflags |= O_TRUNC;
+- wfd = sys_open(collected, openflags, mode);
++ wfd = sys_open((__force char __user *)collected, openflags, mode);
+
+ if (wfd >= 0) {
+ sys_fchown(wfd, uid, gid);
+@@ -317,17 +317,17 @@ static int __init do_name(void)
+ }
+ }
+ } else if (S_ISDIR(mode)) {
+- sys_mkdir(collected, mode);
+- sys_chown(collected, uid, gid);
+- sys_chmod(collected, mode);
++ sys_mkdir((__force char __user *)collected, mode);
++ sys_chown((__force char __user *)collected, uid, gid);
++ sys_chmod((__force char __user *)collected, mode);
+ dir_add(collected, mtime);
+ } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
+ S_ISFIFO(mode) || S_ISSOCK(mode)) {
+ if (maybe_link() == 0) {
+- sys_mknod(collected, mode, rdev);
+- sys_chown(collected, uid, gid);
+- sys_chmod(collected, mode);
+- do_utime(collected, mtime);
++ sys_mknod((__force char __user *)collected, mode, rdev);
++ sys_chown((__force char __user *)collected, uid, gid);
++ sys_chmod((__force char __user *)collected, mode);
++ do_utime((__force char __user *)collected, mtime);
+ }
+ }
+ return 0;
+@@ -336,15 +336,15 @@ static int __init do_name(void)
+ static int __init do_copy(void)
+ {
+ if (count >= body_len) {
+- sys_write(wfd, victim, body_len);
++ sys_write(wfd, (__force char __user *)victim, body_len);
+ sys_close(wfd);
+- do_utime(vcollected, mtime);
++ do_utime((__force char __user *)vcollected, mtime);
+ kfree(vcollected);
+ eat(body_len);
+ state = SkipIt;
+ return 0;
+ } else {
+- sys_write(wfd, victim, count);
++ sys_write(wfd, (__force char __user *)victim, count);
+ body_len -= count;
+ eat(count);
+ return 1;
+@@ -355,9 +355,9 @@ static int __init do_symlink(void)
+ {
+ collected[N_ALIGN(name_len) + body_len] = '\0';
+ clean_path(collected, 0);
+- sys_symlink(collected + N_ALIGN(name_len), collected);
+- sys_lchown(collected, uid, gid);
+- do_utime(collected, mtime);
++ sys_symlink((__force char __user *)collected + N_ALIGN(name_len), (__force char __user *)collected);
++ sys_lchown((__force char __user *)collected, uid, gid);
++ do_utime((__force char __user *)collected, mtime);
+ state = SkipIt;
+ next_state = Reset;
+ return 0;
+diff -urNp linux-2.6.38.7/init/Kconfig linux-2.6.38.7/init/Kconfig
+--- linux-2.6.38.7/init/Kconfig 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/init/Kconfig 2011-05-10 22:06:56.000000000 -0400
+@@ -1185,7 +1185,7 @@ config SLUB_DEBUG
+
+ config COMPAT_BRK
+ bool "Disable heap randomization"
+- default y
++ default n
+ help
+ Randomizing heap placement makes heap exploits harder, but it
+ also breaks ancient binaries (including anything libc5 based).
+diff -urNp linux-2.6.38.7/init/main.c linux-2.6.38.7/init/main.c
+--- linux-2.6.38.7/init/main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/init/main.c 2011-05-22 23:03:34.000000000 -0400
+@@ -96,6 +96,8 @@ static inline void mark_rodata_ro(void)
+ extern void tc_init(void);
+ #endif
+
++extern void grsecurity_init(void);
++
+ /*
+ * Debug helper: via this flag we know that we are in 'early bootup code'
+ * where only the boot processor is running with IRQ disabled. This means
+@@ -206,6 +208,49 @@ static int __init set_reset_devices(char
+
+ __setup("reset_devices", set_reset_devices);
+
++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
++extern char pax_enter_kernel_user[];
++extern char pax_exit_kernel_user[];
++extern pgdval_t clone_pgd_mask;
++#endif
++
++#if defined(CONFIG_X86) && defined(CONFIG_PAX_MEMORY_UDEREF)
++static int __init setup_pax_nouderef(char *str)
++{
++#ifdef CONFIG_X86_32
++ unsigned int cpu;
++ struct desc_struct *gdt;
++
++ for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ gdt = get_cpu_gdt_table(cpu);
++ gdt[GDT_ENTRY_KERNEL_DS].type = 3;
++ gdt[GDT_ENTRY_KERNEL_DS].limit = 0xf;
++ gdt[GDT_ENTRY_DEFAULT_USER_CS].limit = 0xf;
++ gdt[GDT_ENTRY_DEFAULT_USER_DS].limit = 0xf;
++ }
++ asm("mov %0, %%ds; mov %0, %%es; mov %0, %%ss" : : "r" (__KERNEL_DS) : "memory");
++#else
++ memcpy(pax_enter_kernel_user, (unsigned char []){0xc3}, 1);
++ memcpy(pax_exit_kernel_user, (unsigned char []){0xc3}, 1);
++ clone_pgd_mask = ~(pgdval_t)0UL;
++#endif
++
++ return 0;
++}
++early_param("pax_nouderef", setup_pax_nouderef);
++#endif
++
++#ifdef CONFIG_PAX_SOFTMODE
++unsigned int pax_softmode;
++
++static int __init setup_pax_softmode(char *str)
++{
++ get_option(&str, &pax_softmode);
++ return 1;
++}
++__setup("pax_softmode=", setup_pax_softmode);
++#endif
++
+ static const char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
+ const char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
+ static const char *panic_later, *panic_param;
+@@ -751,6 +796,7 @@ int __init_or_module do_one_initcall(ini
+ {
+ int count = preempt_count();
+ int ret;
++ const char *msg1 = "", *msg2 = "";
+
+ if (initcall_debug)
+ ret = do_one_initcall_debug(fn);
+@@ -763,15 +809,15 @@ int __init_or_module do_one_initcall(ini
+ sprintf(msgbuf, "error code %d ", ret);
+
+ if (preempt_count() != count) {
+- strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
++ msg1 = " preemption imbalance";
+ preempt_count() = count;
+ }
+ if (irqs_disabled()) {
+- strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
++ msg2 = " disabled interrupts";
+ local_irq_enable();
+ }
+- if (msgbuf[0]) {
+- printk("initcall %pF returned with %s\n", fn, msgbuf);
++ if (msgbuf[0] || *msg1 || *msg2) {
++ printk("initcall %pF returned with %s%s%s\n", fn, msgbuf, msg1, msg2);
+ }
+
+ return ret;
+@@ -898,7 +944,7 @@ static int __init kernel_init(void * unu
+ do_basic_setup();
+
+ /* Open the /dev/console on the rootfs, this should never fail */
+- if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
++ if (sys_open((__force const char __user *) "/dev/console", O_RDWR, 0) < 0)
+ printk(KERN_WARNING "Warning: unable to open an initial console.\n");
+
+ (void) sys_dup(0);
+@@ -911,11 +957,13 @@ static int __init kernel_init(void * unu
+ if (!ramdisk_execute_command)
+ ramdisk_execute_command = "/init";
+
+- if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
++ if (sys_access((__force const char __user *) ramdisk_execute_command, 0) != 0) {
+ ramdisk_execute_command = NULL;
+ prepare_namespace();
+ }
+
++ grsecurity_init();
++
+ /*
+ * Ok, we have completed the initial bootup, and
+ * we're essentially up and running. Get rid of the
+diff -urNp linux-2.6.38.7/ipc/mqueue.c linux-2.6.38.7/ipc/mqueue.c
+--- linux-2.6.38.7/ipc/mqueue.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/ipc/mqueue.c 2011-04-28 19:34:15.000000000 -0400
+@@ -154,6 +154,7 @@ static struct inode *mqueue_get_inode(st
+ mq_bytes = (mq_msg_tblsz +
+ (info->attr.mq_maxmsg * info->attr.mq_msgsize));
+
++ gr_learn_resource(current, RLIMIT_MSGQUEUE, u->mq_bytes + mq_bytes, 1);
+ spin_lock(&mq_lock);
+ if (u->mq_bytes + mq_bytes < u->mq_bytes ||
+ u->mq_bytes + mq_bytes >
+diff -urNp linux-2.6.38.7/ipc/sem.c linux-2.6.38.7/ipc/sem.c
+--- linux-2.6.38.7/ipc/sem.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/ipc/sem.c 2011-05-16 21:47:08.000000000 -0400
+@@ -854,6 +854,8 @@ static int semctl_main(struct ipc_namesp
+ int nsems;
+ struct list_head tasks;
+
++ pax_track_stack();
++
+ sma = sem_lock_check(ns, semid);
+ if (IS_ERR(sma))
+ return PTR_ERR(sma);
+@@ -1299,6 +1301,8 @@ SYSCALL_DEFINE4(semtimedop, int, semid,
+ struct ipc_namespace *ns;
+ struct list_head tasks;
+
++ pax_track_stack();
++
+ ns = current->nsproxy->ipc_ns;
+
+ if (nsops < 1 || semid < 0)
+diff -urNp linux-2.6.38.7/ipc/shm.c linux-2.6.38.7/ipc/shm.c
+--- linux-2.6.38.7/ipc/shm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/ipc/shm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -69,6 +69,14 @@ static void shm_destroy (struct ipc_name
+ static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
+ #endif
+
++#ifdef CONFIG_GRKERNSEC
++extern int gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime, const uid_t cuid,
++ const int shmid);
++extern int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime);
++#endif
++
+ void shm_init_ns(struct ipc_namespace *ns)
+ {
+ ns->shm_ctlmax = SHMMAX;
+@@ -401,6 +409,14 @@ static int newseg(struct ipc_namespace *
+ shp->shm_lprid = 0;
+ shp->shm_atim = shp->shm_dtim = 0;
+ shp->shm_ctim = get_seconds();
++#ifdef CONFIG_GRKERNSEC
++ {
++ struct timespec timeval;
++ do_posix_clock_monotonic_gettime(&timeval);
++
++ shp->shm_createtime = timeval.tv_sec;
++ }
++#endif
+ shp->shm_segsz = size;
+ shp->shm_nattch = 0;
+ shp->shm_file = file;
+@@ -761,8 +777,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int,
+ case SHM_LOCK:
+ case SHM_UNLOCK:
+ {
+- struct file *uninitialized_var(shm_file);
+-
+ lru_add_drain_all(); /* drain pagevecs to lru lists */
+
+ shp = shm_lock_check(ns, shmid);
+@@ -895,9 +909,21 @@ long do_shmat(int shmid, char __user *sh
+ if (err)
+ goto out_unlock;
+
++#ifdef CONFIG_GRKERNSEC
++ if (!gr_handle_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime,
++ shp->shm_perm.cuid, shmid) ||
++ !gr_chroot_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime)) {
++ err = -EACCES;
++ goto out_unlock;
++ }
++#endif
++
+ path = shp->shm_file->f_path;
+ path_get(&path);
+ shp->shm_nattch++;
++#ifdef CONFIG_GRKERNSEC
++ shp->shm_lapid = current->pid;
++#endif
+ size = i_size_read(path.dentry->d_inode);
+ shm_unlock(shp);
+
+diff -urNp linux-2.6.38.7/kernel/acct.c linux-2.6.38.7/kernel/acct.c
+--- linux-2.6.38.7/kernel/acct.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/acct.c 2011-04-28 19:34:15.000000000 -0400
+@@ -570,7 +570,7 @@ static void do_acct_process(struct bsd_a
+ */
+ flim = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+ current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
+- file->f_op->write(file, (char *)&ac,
++ file->f_op->write(file, (__force char __user *)&ac,
+ sizeof(acct_t), &file->f_pos);
+ current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim;
+ set_fs(fs);
+diff -urNp linux-2.6.38.7/kernel/audit.c linux-2.6.38.7/kernel/audit.c
+--- linux-2.6.38.7/kernel/audit.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/audit.c 2011-04-28 19:57:25.000000000 -0400
+@@ -110,7 +110,7 @@ u32 audit_sig_sid = 0;
+ 3) suppressed due to audit_rate_limit
+ 4) suppressed due to audit_backlog_limit
+ */
+-static atomic_t audit_lost = ATOMIC_INIT(0);
++static atomic_unchecked_t audit_lost = ATOMIC_INIT(0);
+
+ /* The netlink socket. */
+ static struct sock *audit_sock;
+@@ -232,7 +232,7 @@ void audit_log_lost(const char *message)
+ unsigned long now;
+ int print;
+
+- atomic_inc(&audit_lost);
++ atomic_inc_unchecked(&audit_lost);
+
+ print = (audit_failure == AUDIT_FAIL_PANIC || !audit_rate_limit);
+
+@@ -251,7 +251,7 @@ void audit_log_lost(const char *message)
+ printk(KERN_WARNING
+ "audit: audit_lost=%d audit_rate_limit=%d "
+ "audit_backlog_limit=%d\n",
+- atomic_read(&audit_lost),
++ atomic_read_unchecked(&audit_lost),
+ audit_rate_limit,
+ audit_backlog_limit);
+ audit_panic(message);
+@@ -684,7 +684,7 @@ static int audit_receive_msg(struct sk_b
+ status_set.pid = audit_pid;
+ status_set.rate_limit = audit_rate_limit;
+ status_set.backlog_limit = audit_backlog_limit;
+- status_set.lost = atomic_read(&audit_lost);
++ status_set.lost = atomic_read_unchecked(&audit_lost);
+ status_set.backlog = skb_queue_len(&audit_skb_queue);
+ audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0,
+ &status_set, sizeof(status_set));
+diff -urNp linux-2.6.38.7/kernel/auditsc.c linux-2.6.38.7/kernel/auditsc.c
+--- linux-2.6.38.7/kernel/auditsc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/auditsc.c 2011-04-28 19:57:25.000000000 -0400
+@@ -2111,7 +2111,7 @@ int auditsc_get_stamp(struct audit_conte
+ }
+
+ /* global counter which is incremented every time something logs in */
+-static atomic_t session_id = ATOMIC_INIT(0);
++static atomic_unchecked_t session_id = ATOMIC_INIT(0);
+
+ /**
+ * audit_set_loginuid - set a task's audit_context loginuid
+@@ -2124,7 +2124,7 @@ static atomic_t session_id = ATOMIC_INIT
+ */
+ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
+ {
+- unsigned int sessionid = atomic_inc_return(&session_id);
++ unsigned int sessionid = atomic_inc_return_unchecked(&session_id);
+ struct audit_context *context = task->audit_context;
+
+ if (context && context->in_syscall) {
+diff -urNp linux-2.6.38.7/kernel/capability.c linux-2.6.38.7/kernel/capability.c
+--- linux-2.6.38.7/kernel/capability.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/capability.c 2011-04-28 19:34:15.000000000 -0400
+@@ -205,6 +205,9 @@ SYSCALL_DEFINE2(capget, cap_user_header_
+ * before modification is attempted and the application
+ * fails.
+ */
++ if (tocopy > ARRAY_SIZE(kdata))
++ return -EFAULT;
++
+ if (copy_to_user(dataptr, kdata, tocopy
+ * sizeof(struct __user_cap_data_struct))) {
+ return -EFAULT;
+@@ -306,10 +309,26 @@ int capable(int cap)
+ BUG();
+ }
+
+- if (security_capable(current_cred(), cap) == 0) {
++ if (security_capable(current_cred(), cap) == 0 && gr_is_capable(cap)) {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+ return 0;
+ }
++
++int capable_nolog(int cap)
++{
++ if (unlikely(!cap_valid(cap))) {
++ printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap);
++ BUG();
++ }
++
++ if (security_capable(current_cred(), cap) == 0 && gr_is_capable_nolog(cap)) {
++ current->flags |= PF_SUPERPRIV;
++ return 1;
++ }
++ return 0;
++}
++
+ EXPORT_SYMBOL(capable);
++EXPORT_SYMBOL(capable_nolog);
+diff -urNp linux-2.6.38.7/kernel/cgroup.c linux-2.6.38.7/kernel/cgroup.c
+--- linux-2.6.38.7/kernel/cgroup.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/kernel/cgroup.c 2011-05-16 21:47:09.000000000 -0400
+@@ -598,6 +598,8 @@ static struct css_set *find_css_set(
+ struct hlist_head *hhead;
+ struct cg_cgroup_link *link;
+
++ pax_track_stack();
++
+ /* First see if we already have a cgroup group that matches
+ * the desired set */
+ read_lock(&css_set_lock);
+diff -urNp linux-2.6.38.7/kernel/compat.c linux-2.6.38.7/kernel/compat.c
+--- linux-2.6.38.7/kernel/compat.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/compat.c 2011-04-28 19:34:15.000000000 -0400
+@@ -13,6 +13,7 @@
+
+ #include <linux/linkage.h>
+ #include <linux/compat.h>
++#include <linux/module.h>
+ #include <linux/errno.h>
+ #include <linux/time.h>
+ #include <linux/signal.h>
+diff -urNp linux-2.6.38.7/kernel/configs.c linux-2.6.38.7/kernel/configs.c
+--- linux-2.6.38.7/kernel/configs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/configs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -74,8 +74,19 @@ static int __init ikconfig_init(void)
+ struct proc_dir_entry *entry;
+
+ /* create the current config file */
++#if defined(CONFIG_GRKERNSEC_PROC_ADD) || defined(CONFIG_GRKERNSEC_HIDESYM)
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_HIDESYM)
++ entry = proc_create("config.gz", S_IFREG | S_IRUSR, NULL,
++ &ikconfig_file_ops);
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ entry = proc_create("config.gz", S_IFREG | S_IRUSR | S_IRGRP, NULL,
++ &ikconfig_file_ops);
++#endif
++#else
+ entry = proc_create("config.gz", S_IFREG | S_IRUGO, NULL,
+ &ikconfig_file_ops);
++#endif
++
+ if (!entry)
+ return -ENOMEM;
+
+diff -urNp linux-2.6.38.7/kernel/cred.c linux-2.6.38.7/kernel/cred.c
+--- linux-2.6.38.7/kernel/cred.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/cred.c 2011-05-17 19:31:43.000000000 -0400
+@@ -157,6 +157,8 @@ static void put_cred_rcu(struct rcu_head
+ */
+ void __put_cred(struct cred *cred)
+ {
++ pax_track_stack();
++
+ kdebug("__put_cred(%p{%d,%d})", cred,
+ atomic_read(&cred->usage),
+ read_cred_subscribers(cred));
+@@ -181,6 +183,8 @@ void exit_creds(struct task_struct *tsk)
+ {
+ struct cred *cred;
+
++ pax_track_stack();
++
+ kdebug("exit_creds(%u,%p,%p,{%d,%d})", tsk->pid, tsk->real_cred, tsk->cred,
+ atomic_read(&tsk->cred->usage),
+ read_cred_subscribers(tsk->cred));
+@@ -219,6 +223,8 @@ const struct cred *get_task_cred(struct
+ {
+ const struct cred *cred;
+
++ pax_track_stack();
++
+ rcu_read_lock();
+
+ do {
+@@ -238,6 +244,8 @@ struct cred *cred_alloc_blank(void)
+ {
+ struct cred *new;
+
++ pax_track_stack();
++
+ new = kmem_cache_zalloc(cred_jar, GFP_KERNEL);
+ if (!new)
+ return NULL;
+@@ -286,6 +294,8 @@ struct cred *prepare_creds(void)
+ const struct cred *old;
+ struct cred *new;
+
++ pax_track_stack();
++
+ validate_process_creds();
+
+ new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
+@@ -332,6 +342,8 @@ struct cred *prepare_exec_creds(void)
+ struct thread_group_cred *tgcred = NULL;
+ struct cred *new;
+
++ pax_track_stack();
++
+ #ifdef CONFIG_KEYS
+ tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
+ if (!tgcred)
+@@ -384,6 +396,8 @@ int copy_creds(struct task_struct *p, un
+ struct cred *new;
+ int ret;
+
++ pax_track_stack();
++
+ if (
+ #ifdef CONFIG_KEYS
+ !p->cred->thread_keyring &&
+@@ -469,6 +483,8 @@ int commit_creds(struct cred *new)
+ struct task_struct *task = current;
+ const struct cred *old = task->real_cred;
+
++ pax_track_stack();
++
+ kdebug("commit_creds(%p{%d,%d})", new,
+ atomic_read(&new->usage),
+ read_cred_subscribers(new));
+@@ -483,6 +499,8 @@ int commit_creds(struct cred *new)
+
+ get_cred(new); /* we will require a ref for the subj creds too */
+
++ gr_set_role_label(task, new->uid, new->gid);
++
+ /* dumpability changes */
+ if (old->euid != new->euid ||
+ old->egid != new->egid ||
+@@ -545,6 +563,8 @@ EXPORT_SYMBOL(commit_creds);
+ */
+ void abort_creds(struct cred *new)
+ {
++ pax_track_stack();
++
+ kdebug("abort_creds(%p{%d,%d})", new,
+ atomic_read(&new->usage),
+ read_cred_subscribers(new));
+@@ -568,6 +588,8 @@ const struct cred *override_creds(const
+ {
+ const struct cred *old = current->cred;
+
++ pax_track_stack();
++
+ kdebug("override_creds(%p{%d,%d})", new,
+ atomic_read(&new->usage),
+ read_cred_subscribers(new));
+@@ -597,6 +619,8 @@ void revert_creds(const struct cred *old
+ {
+ const struct cred *override = current->cred;
+
++ pax_track_stack();
++
+ kdebug("revert_creds(%p{%d,%d})", old,
+ atomic_read(&old->usage),
+ read_cred_subscribers(old));
+@@ -643,6 +667,8 @@ struct cred *prepare_kernel_cred(struct
+ const struct cred *old;
+ struct cred *new;
+
++ pax_track_stack();
++
+ new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
+ if (!new)
+ return NULL;
+@@ -697,6 +723,8 @@ EXPORT_SYMBOL(prepare_kernel_cred);
+ */
+ int set_security_override(struct cred *new, u32 secid)
+ {
++ pax_track_stack();
++
+ return security_kernel_act_as(new, secid);
+ }
+ EXPORT_SYMBOL(set_security_override);
+@@ -716,6 +744,8 @@ int set_security_override_from_ctx(struc
+ u32 secid;
+ int ret;
+
++ pax_track_stack();
++
+ ret = security_secctx_to_secid(secctx, strlen(secctx), &secid);
+ if (ret < 0)
+ return ret;
+diff -urNp linux-2.6.38.7/kernel/debug/debug_core.c linux-2.6.38.7/kernel/debug/debug_core.c
+--- linux-2.6.38.7/kernel/debug/debug_core.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/debug/debug_core.c 2011-04-28 19:57:25.000000000 -0400
+@@ -72,7 +72,7 @@ int kgdb_io_module_registered;
+ /* Guard for recursive entry */
+ static int exception_level;
+
+-struct kgdb_io *dbg_io_ops;
++const struct kgdb_io *dbg_io_ops;
+ static DEFINE_SPINLOCK(kgdb_registration_lock);
+
+ /* kgdb console driver is loaded */
+@@ -119,7 +119,7 @@ static DEFINE_RAW_SPINLOCK(dbg_slave_loc
+ */
+ static atomic_t masters_in_kgdb;
+ static atomic_t slaves_in_kgdb;
+-static atomic_t kgdb_break_tasklet_var;
++static atomic_unchecked_t kgdb_break_tasklet_var;
+ atomic_t kgdb_setting_breakpoint;
+
+ struct task_struct *kgdb_usethread;
+@@ -129,7 +129,7 @@ int kgdb_single_step;
+ static pid_t kgdb_sstep_pid;
+
+ /* to keep track of the CPU which is doing the single stepping*/
+-atomic_t kgdb_cpu_doing_single_step = ATOMIC_INIT(-1);
++atomic_unchecked_t kgdb_cpu_doing_single_step = ATOMIC_INIT(-1);
+
+ /*
+ * If you are debugging a problem where roundup (the collection of
+@@ -542,7 +542,7 @@ return_normal:
+ * kernel will only try for the value of sstep_tries before
+ * giving up and continuing on.
+ */
+- if (atomic_read(&kgdb_cpu_doing_single_step) != -1 &&
++ if (atomic_read_unchecked(&kgdb_cpu_doing_single_step) != -1 &&
+ (kgdb_info[cpu].task &&
+ kgdb_info[cpu].task->pid != kgdb_sstep_pid) && --sstep_tries) {
+ atomic_set(&kgdb_active, -1);
+@@ -636,8 +636,8 @@ cpu_master_loop:
+ }
+
+ kgdb_restore:
+- if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
+- int sstep_cpu = atomic_read(&kgdb_cpu_doing_single_step);
++ if (atomic_read_unchecked(&kgdb_cpu_doing_single_step) != -1) {
++ int sstep_cpu = atomic_read_unchecked(&kgdb_cpu_doing_single_step);
+ if (kgdb_info[sstep_cpu].task)
+ kgdb_sstep_pid = kgdb_info[sstep_cpu].task->pid;
+ else
+@@ -834,18 +834,18 @@ static void kgdb_unregister_callbacks(vo
+ static void kgdb_tasklet_bpt(unsigned long ing)
+ {
+ kgdb_breakpoint();
+- atomic_set(&kgdb_break_tasklet_var, 0);
++ atomic_set_unchecked(&kgdb_break_tasklet_var, 0);
+ }
+
+ static DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt, 0);
+
+ void kgdb_schedule_breakpoint(void)
+ {
+- if (atomic_read(&kgdb_break_tasklet_var) ||
++ if (atomic_read_unchecked(&kgdb_break_tasklet_var) ||
+ atomic_read(&kgdb_active) != -1 ||
+ atomic_read(&kgdb_setting_breakpoint))
+ return;
+- atomic_inc(&kgdb_break_tasklet_var);
++ atomic_inc_unchecked(&kgdb_break_tasklet_var);
+ tasklet_schedule(&kgdb_tasklet_breakpoint);
+ }
+ EXPORT_SYMBOL_GPL(kgdb_schedule_breakpoint);
+@@ -864,7 +864,7 @@ static void kgdb_initial_breakpoint(void
+ *
+ * Register it with the KGDB core.
+ */
+-int kgdb_register_io_module(struct kgdb_io *new_dbg_io_ops)
++int kgdb_register_io_module(const struct kgdb_io *new_dbg_io_ops)
+ {
+ int err;
+
+@@ -909,7 +909,7 @@ EXPORT_SYMBOL_GPL(kgdb_register_io_modul
+ *
+ * Unregister it with the KGDB core.
+ */
+-void kgdb_unregister_io_module(struct kgdb_io *old_dbg_io_ops)
++void kgdb_unregister_io_module(const struct kgdb_io *old_dbg_io_ops)
+ {
+ BUG_ON(kgdb_connected);
+
+diff -urNp linux-2.6.38.7/kernel/debug/kdb/kdb_main.c linux-2.6.38.7/kernel/debug/kdb/kdb_main.c
+--- linux-2.6.38.7/kernel/debug/kdb/kdb_main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/debug/kdb/kdb_main.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1980,7 +1980,7 @@ static int kdb_lsmod(int argc, const cha
+ list_for_each_entry(mod, kdb_modules, list) {
+
+ kdb_printf("%-20s%8u 0x%p ", mod->name,
+- mod->core_size, (void *)mod);
++ mod->core_size_rx + mod->core_size_rw, (void *)mod);
+ #ifdef CONFIG_MODULE_UNLOAD
+ kdb_printf("%4d ", module_refcount(mod));
+ #endif
+@@ -1990,7 +1990,7 @@ static int kdb_lsmod(int argc, const cha
+ kdb_printf(" (Loading)");
+ else
+ kdb_printf(" (Live)");
+- kdb_printf(" 0x%p", mod->module_core);
++ kdb_printf(" 0x%p 0x%p", mod->module_core_rx, mod->module_core_rw);
+
+ #ifdef CONFIG_MODULE_UNLOAD
+ {
+diff -urNp linux-2.6.38.7/kernel/exit.c linux-2.6.38.7/kernel/exit.c
+--- linux-2.6.38.7/kernel/exit.c 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/kernel/exit.c 2011-05-22 23:06:04.000000000 -0400
+@@ -57,6 +57,10 @@
+ #include <asm/pgtable.h>
+ #include <asm/mmu_context.h>
+
++#ifdef CONFIG_GRKERNSEC
++extern rwlock_t grsec_exec_file_lock;
++#endif
++
+ static void exit_mm(struct task_struct * tsk);
+
+ static void __unhash_process(struct task_struct *p, bool group_dead)
+@@ -169,6 +173,8 @@ void release_task(struct task_struct * p
+ struct task_struct *leader;
+ int zap_leader;
+ repeat:
++ gr_del_task_from_ip_table(p);
++
+ tracehook_prepare_release_task(p);
+ /* don't need to get the RCU readlock here - the process is dead and
+ * can't be modifying its own credentials. But shut RCU-lockdep up */
+@@ -338,11 +344,22 @@ static void reparent_to_kthreadd(void)
+ {
+ write_lock_irq(&tasklist_lock);
+
++#ifdef CONFIG_GRKERNSEC
++ write_lock(&grsec_exec_file_lock);
++ if (current->exec_file) {
++ fput(current->exec_file);
++ current->exec_file = NULL;
++ }
++ write_unlock(&grsec_exec_file_lock);
++#endif
++
+ ptrace_unlink(current);
+ /* Reparent to init */
+ current->real_parent = current->parent = kthreadd_task;
+ list_move_tail(&current->sibling, &current->real_parent->children);
+
++ gr_set_kernel_label(current);
++
+ /* Set the exit signal to SIGCHLD so we signal init on exit */
+ current->exit_signal = SIGCHLD;
+
+@@ -394,7 +411,7 @@ int allow_signal(int sig)
+ * know it'll be handled, so that they don't get converted to
+ * SIGKILL or just silently dropped.
+ */
+- current->sighand->action[(sig)-1].sa.sa_handler = (void __user *)2;
++ current->sighand->action[(sig)-1].sa.sa_handler = (__force void __user *)2;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ return 0;
+@@ -430,6 +447,17 @@ void daemonize(const char *name, ...)
+ vsnprintf(current->comm, sizeof(current->comm), name, args);
+ va_end(args);
+
++#ifdef CONFIG_GRKERNSEC
++ write_lock(&grsec_exec_file_lock);
++ if (current->exec_file) {
++ fput(current->exec_file);
++ current->exec_file = NULL;
++ }
++ write_unlock(&grsec_exec_file_lock);
++#endif
++
++ gr_set_kernel_label(current);
++
+ /*
+ * If we were started as result of loading a module, close all of the
+ * user space pages. We don't need them, and if we didn't close them
+@@ -905,17 +933,17 @@ NORET_TYPE void do_exit(long code)
+ struct task_struct *tsk = current;
+ int group_dead;
+
+- profile_task_exit(tsk);
+-
+- WARN_ON(atomic_read(&tsk->fs_excl));
+-
++ /*
++ * Check this first since set_fs() below depends on
++ * current_thread_info(), which we better not access when we're in
++ * interrupt context. Other than that, we want to do the set_fs()
++ * as early as possible.
++ */
+ if (unlikely(in_interrupt()))
+ panic("Aiee, killing interrupt handler!");
+- if (unlikely(!tsk->pid))
+- panic("Attempted to kill the idle task!");
+
+ /*
+- * If do_exit is called because this processes oopsed, it's possible
++ * If do_exit is called because this processes Oops'ed, it's possible
+ * that get_fs() was left as KERNEL_DS, so reset it to USER_DS before
+ * continuing. Amongst other possible reasons, this is to prevent
+ * mm_release()->clear_child_tid() from writing to a user-controlled
+@@ -923,6 +951,13 @@ NORET_TYPE void do_exit(long code)
+ */
+ set_fs(USER_DS);
+
++ profile_task_exit(tsk);
++
++ WARN_ON(atomic_read(&tsk->fs_excl));
++
++ if (unlikely(!tsk->pid))
++ panic("Attempted to kill the idle task!");
++
+ tracehook_report_exit(&code);
+
+ validate_creds_for_do_exit(tsk);
+@@ -983,6 +1018,9 @@ NORET_TYPE void do_exit(long code)
+ tsk->exit_code = code;
+ taskstats_exit(tsk, group_dead);
+
++ gr_acl_handle_psacct(tsk, code);
++ gr_acl_handle_exit();
++
+ exit_mm(tsk);
+
+ if (group_dead)
+diff -urNp linux-2.6.38.7/kernel/fork.c linux-2.6.38.7/kernel/fork.c
+--- linux-2.6.38.7/kernel/fork.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/fork.c 2011-04-28 19:34:15.000000000 -0400
+@@ -280,7 +280,7 @@ static struct task_struct *dup_task_stru
+ *stackend = STACK_END_MAGIC; /* for overflow detection */
+
+ #ifdef CONFIG_CC_STACKPROTECTOR
+- tsk->stack_canary = get_random_int();
++ tsk->stack_canary = pax_get_random_long();
+ #endif
+
+ /* One for us, one for whoever does the "release_task()" (usually parent) */
+@@ -302,13 +302,78 @@ out:
+ }
+
+ #ifdef CONFIG_MMU
++static struct vm_area_struct *dup_vma(struct mm_struct *mm, struct vm_area_struct *mpnt)
++{
++ struct vm_area_struct *tmp;
++ unsigned long charge;
++ struct mempolicy *pol;
++ struct file *file;
++
++ charge = 0;
++ if (mpnt->vm_flags & VM_ACCOUNT) {
++ unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
++ if (security_vm_enough_memory(len))
++ goto fail_nomem;
++ charge = len;
++ }
++ tmp = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
++ if (!tmp)
++ goto fail_nomem;
++ *tmp = *mpnt;
++ tmp->vm_mm = mm;
++ INIT_LIST_HEAD(&tmp->anon_vma_chain);
++ pol = mpol_dup(vma_policy(mpnt));
++ if (IS_ERR(pol))
++ goto fail_nomem_policy;
++ vma_set_policy(tmp, pol);
++ if (anon_vma_fork(tmp, mpnt))
++ goto fail_nomem_anon_vma_fork;
++ tmp->vm_flags &= ~VM_LOCKED;
++ tmp->vm_next = tmp->vm_prev = NULL;
++ tmp->vm_mirror = NULL;
++ file = tmp->vm_file;
++ if (file) {
++ struct inode *inode = file->f_path.dentry->d_inode;
++ struct address_space *mapping = file->f_mapping;
++
++ get_file(file);
++ if (tmp->vm_flags & VM_DENYWRITE)
++ atomic_dec(&inode->i_writecount);
++ spin_lock(&mapping->i_mmap_lock);
++ if (tmp->vm_flags & VM_SHARED)
++ mapping->i_mmap_writable++;
++ tmp->vm_truncate_count = mpnt->vm_truncate_count;
++ flush_dcache_mmap_lock(mapping);
++ /* insert tmp into the share list, just after mpnt */
++ vma_prio_tree_add(tmp, mpnt);
++ flush_dcache_mmap_unlock(mapping);
++ spin_unlock(&mapping->i_mmap_lock);
++ }
++
++ /*
++ * Clear hugetlb-related page reserves for children. This only
++ * affects MAP_PRIVATE mappings. Faults generated by the child
++ * are not guaranteed to succeed, even if read-only
++ */
++ if (is_vm_hugetlb_page(tmp))
++ reset_vma_resv_huge_pages(tmp);
++
++ return tmp;
++
++fail_nomem_anon_vma_fork:
++ mpol_put(pol);
++fail_nomem_policy:
++ kmem_cache_free(vm_area_cachep, tmp);
++fail_nomem:
++ vm_unacct_memory(charge);
++ return NULL;
++}
++
+ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+ {
+ struct vm_area_struct *mpnt, *tmp, *prev, **pprev;
+ struct rb_node **rb_link, *rb_parent;
+ int retval;
+- unsigned long charge;
+- struct mempolicy *pol;
+
+ down_write(&oldmm->mmap_sem);
+ flush_cache_dup_mm(oldmm);
+@@ -320,8 +385,8 @@ static int dup_mmap(struct mm_struct *mm
+ mm->locked_vm = 0;
+ mm->mmap = NULL;
+ mm->mmap_cache = NULL;
+- mm->free_area_cache = oldmm->mmap_base;
+- mm->cached_hole_size = ~0UL;
++ mm->free_area_cache = oldmm->free_area_cache;
++ mm->cached_hole_size = oldmm->cached_hole_size;
+ mm->map_count = 0;
+ cpumask_clear(mm_cpumask(mm));
+ mm->mm_rb = RB_ROOT;
+@@ -337,8 +402,6 @@ static int dup_mmap(struct mm_struct *mm
+
+ prev = NULL;
+ for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) {
+- struct file *file;
+-
+ if (mpnt->vm_flags & VM_DONTCOPY) {
+ long pages = vma_pages(mpnt);
+ mm->total_vm -= pages;
+@@ -346,56 +409,13 @@ static int dup_mmap(struct mm_struct *mm
+ -pages);
+ continue;
+ }
+- charge = 0;
+- if (mpnt->vm_flags & VM_ACCOUNT) {
+- unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+- if (security_vm_enough_memory(len))
+- goto fail_nomem;
+- charge = len;
+- }
+- tmp = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+- if (!tmp)
+- goto fail_nomem;
+- *tmp = *mpnt;
+- INIT_LIST_HEAD(&tmp->anon_vma_chain);
+- pol = mpol_dup(vma_policy(mpnt));
+- retval = PTR_ERR(pol);
+- if (IS_ERR(pol))
+- goto fail_nomem_policy;
+- vma_set_policy(tmp, pol);
+- tmp->vm_mm = mm;
+- if (anon_vma_fork(tmp, mpnt))
+- goto fail_nomem_anon_vma_fork;
+- tmp->vm_flags &= ~VM_LOCKED;
+- tmp->vm_next = tmp->vm_prev = NULL;
+- file = tmp->vm_file;
+- if (file) {
+- struct inode *inode = file->f_path.dentry->d_inode;
+- struct address_space *mapping = file->f_mapping;
+-
+- get_file(file);
+- if (tmp->vm_flags & VM_DENYWRITE)
+- atomic_dec(&inode->i_writecount);
+- spin_lock(&mapping->i_mmap_lock);
+- if (tmp->vm_flags & VM_SHARED)
+- mapping->i_mmap_writable++;
+- tmp->vm_truncate_count = mpnt->vm_truncate_count;
+- flush_dcache_mmap_lock(mapping);
+- /* insert tmp into the share list, just after mpnt */
+- vma_prio_tree_add(tmp, mpnt);
+- flush_dcache_mmap_unlock(mapping);
+- spin_unlock(&mapping->i_mmap_lock);
++ tmp = dup_vma(mm, mpnt);
++ if (!tmp) {
++ retval = -ENOMEM;
++ goto out;
+ }
+
+ /*
+- * Clear hugetlb-related page reserves for children. This only
+- * affects MAP_PRIVATE mappings. Faults generated by the child
+- * are not guaranteed to succeed, even if read-only
+- */
+- if (is_vm_hugetlb_page(tmp))
+- reset_vma_resv_huge_pages(tmp);
+-
+- /*
+ * Link in the new vma and copy the page table entries.
+ */
+ *pprev = tmp;
+@@ -416,6 +436,31 @@ static int dup_mmap(struct mm_struct *mm
+ if (retval)
+ goto out;
+ }
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (oldmm->pax_flags & MF_PAX_SEGMEXEC) {
++ struct vm_area_struct *mpnt_m;
++
++ for (mpnt = oldmm->mmap, mpnt_m = mm->mmap; mpnt; mpnt = mpnt->vm_next, mpnt_m = mpnt_m->vm_next) {
++ BUG_ON(!mpnt_m || mpnt_m->vm_mirror || mpnt->vm_mm != oldmm || mpnt_m->vm_mm != mm);
++
++ if (!mpnt->vm_mirror)
++ continue;
++
++ if (mpnt->vm_end <= SEGMEXEC_TASK_SIZE) {
++ BUG_ON(mpnt->vm_mirror->vm_mirror != mpnt);
++ mpnt->vm_mirror = mpnt_m;
++ } else {
++ BUG_ON(mpnt->vm_mirror->vm_mirror == mpnt || mpnt->vm_mirror->vm_mirror->vm_mm != mm);
++ mpnt_m->vm_mirror = mpnt->vm_mirror->vm_mirror;
++ mpnt_m->vm_mirror->vm_mirror = mpnt_m;
++ mpnt->vm_mirror->vm_mirror = mpnt;
++ }
++ }
++ BUG_ON(mpnt_m);
++ }
++#endif
++
+ /* a new mm has just been created */
+ arch_dup_mmap(oldmm, mm);
+ retval = 0;
+@@ -424,14 +469,6 @@ out:
+ flush_tlb_mm(oldmm);
+ up_write(&oldmm->mmap_sem);
+ return retval;
+-fail_nomem_anon_vma_fork:
+- mpol_put(pol);
+-fail_nomem_policy:
+- kmem_cache_free(vm_area_cachep, tmp);
+-fail_nomem:
+- retval = -ENOMEM;
+- vm_unacct_memory(charge);
+- goto out;
+ }
+
+ static inline int mm_alloc_pgd(struct mm_struct * mm)
+@@ -778,13 +815,14 @@ static int copy_fs(unsigned long clone_f
+ spin_unlock(&fs->lock);
+ return -EAGAIN;
+ }
+- fs->users++;
++ atomic_inc(&fs->users);
+ spin_unlock(&fs->lock);
+ return 0;
+ }
+ tsk->fs = copy_fs_struct(fs);
+ if (!tsk->fs)
+ return -ENOMEM;
++ gr_set_chroot_entries(tsk, &tsk->fs->root);
+ return 0;
+ }
+
+@@ -1042,10 +1080,13 @@ static struct task_struct *copy_process(
+ DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
+ #endif
+ retval = -EAGAIN;
++
++ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->real_cred->user->processes), 0);
++
+ if (atomic_read(&p->real_cred->user->processes) >=
+ task_rlimit(p, RLIMIT_NPROC)) {
+- if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
+- p->real_cred->user != INIT_USER)
++ if (p->real_cred->user != INIT_USER &&
++ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
+ goto bad_fork_free;
+ }
+
+@@ -1199,6 +1240,8 @@ static struct task_struct *copy_process(
+ goto bad_fork_free_pid;
+ }
+
++ gr_copy_label(p);
++
+ p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
+ /*
+ * Clear TID on mm_release()?
+@@ -1356,6 +1399,8 @@ bad_fork_cleanup_count:
+ bad_fork_free:
+ free_task(p);
+ fork_out:
++ gr_log_forkfail(retval);
++
+ return ERR_PTR(retval);
+ }
+
+@@ -1444,6 +1489,8 @@ long do_fork(unsigned long clone_flags,
+ if (clone_flags & CLONE_PARENT_SETTID)
+ put_user(nr, parent_tidptr);
+
++ gr_handle_brute_check();
++
+ if (clone_flags & CLONE_VFORK) {
+ p->vfork_done = &vfork;
+ init_completion(&vfork);
+@@ -1559,7 +1606,7 @@ static int unshare_fs(unsigned long unsh
+ return 0;
+
+ /* don't need lock here; in the worst case we'll do useless copy */
+- if (fs->users == 1)
++ if (atomic_read(&fs->users) == 1)
+ return 0;
+
+ *new_fsp = copy_fs_struct(fs);
+@@ -1682,7 +1729,8 @@ SYSCALL_DEFINE1(unshare, unsigned long,
+ fs = current->fs;
+ spin_lock(&fs->lock);
+ current->fs = new_fs;
+- if (--fs->users)
++ gr_set_chroot_entries(current, &current->fs->root);
++ if (atomic_dec_return(&fs->users))
+ new_fs = NULL;
+ else
+ new_fs = fs;
+diff -urNp linux-2.6.38.7/kernel/futex.c linux-2.6.38.7/kernel/futex.c
+--- linux-2.6.38.7/kernel/futex.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/kernel/futex.c 2011-05-16 21:47:08.000000000 -0400
+@@ -54,6 +54,7 @@
+ #include <linux/mount.h>
+ #include <linux/pagemap.h>
+ #include <linux/syscalls.h>
++#include <linux/ptrace.h>
+ #include <linux/signal.h>
+ #include <linux/module.h>
+ #include <linux/magic.h>
+@@ -236,6 +237,11 @@ get_futex_key(u32 __user *uaddr, int fsh
+ struct page *page, *page_head;
+ int err;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && address >= SEGMEXEC_TASK_SIZE)
++ return -EFAULT;
++#endif
++
+ /*
+ * The futex address must be "naturally" aligned.
+ */
+@@ -1833,6 +1839,8 @@ static int futex_wait(u32 __user *uaddr,
+ struct futex_q q = futex_q_init;
+ int ret;
+
++ pax_track_stack();
++
+ if (!bitset)
+ return -EINVAL;
+ q.bitset = bitset;
+@@ -2232,6 +2240,8 @@ static int futex_wait_requeue_pi(u32 __u
+ struct futex_q q = futex_q_init;
+ int res, ret;
+
++ pax_track_stack();
++
+ if (!bitset)
+ return -EINVAL;
+
+@@ -2404,7 +2414,9 @@ SYSCALL_DEFINE3(get_robust_list, int, pi
+ {
+ struct robust_list_head __user *head;
+ unsigned long ret;
++#ifndef CONFIG_GRKERNSEC_PROC_MEMMAP
+ const struct cred *cred = current_cred(), *pcred;
++#endif
+
+ if (!futex_cmpxchg_enabled)
+ return -ENOSYS;
+@@ -2420,11 +2432,16 @@ SYSCALL_DEFINE3(get_robust_list, int, pi
+ if (!p)
+ goto err_unlock;
+ ret = -EPERM;
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ if (!ptrace_may_access(p, PTRACE_MODE_READ))
++ goto err_unlock;
++#else
+ pcred = __task_cred(p);
+ if (cred->euid != pcred->euid &&
+ cred->euid != pcred->uid &&
+ !capable(CAP_SYS_PTRACE))
+ goto err_unlock;
++#endif
+ head = p->robust_list;
+ rcu_read_unlock();
+ }
+@@ -2667,6 +2684,7 @@ static int __init futex_init(void)
+ {
+ u32 curval;
+ int i;
++ mm_segment_t oldfs;
+
+ /*
+ * This will fail and we want it. Some arch implementations do
+@@ -2678,7 +2696,10 @@ static int __init futex_init(void)
+ * implementation, the non-functional ones will return
+ * -ENOSYS.
+ */
++ oldfs = get_fs();
++ set_fs(USER_DS);
+ curval = cmpxchg_futex_value_locked(NULL, 0, 0);
++ set_fs(oldfs);
+ if (curval == -EFAULT)
+ futex_cmpxchg_enabled = 1;
+
+diff -urNp linux-2.6.38.7/kernel/futex_compat.c linux-2.6.38.7/kernel/futex_compat.c
+--- linux-2.6.38.7/kernel/futex_compat.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/futex_compat.c 2011-04-28 19:34:15.000000000 -0400
+@@ -10,6 +10,7 @@
+ #include <linux/compat.h>
+ #include <linux/nsproxy.h>
+ #include <linux/futex.h>
++#include <linux/ptrace.h>
+
+ #include <asm/uaccess.h>
+
+@@ -136,7 +137,10 @@ compat_sys_get_robust_list(int pid, comp
+ {
+ struct compat_robust_list_head __user *head;
+ unsigned long ret;
+- const struct cred *cred = current_cred(), *pcred;
++#ifndef CONFIG_GRKERNSEC_PROC_MEMMAP
++ const struct cred *cred = current_cred();
++ const struct cred *pcred;
++#endif
+
+ if (!futex_cmpxchg_enabled)
+ return -ENOSYS;
+@@ -152,11 +156,16 @@ compat_sys_get_robust_list(int pid, comp
+ if (!p)
+ goto err_unlock;
+ ret = -EPERM;
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ if (!ptrace_may_access(p, PTRACE_MODE_READ))
++ goto err_unlock;
++#else
+ pcred = __task_cred(p);
+ if (cred->euid != pcred->euid &&
+ cred->euid != pcred->uid &&
+ !capable(CAP_SYS_PTRACE))
+ goto err_unlock;
++#endif
+ head = p->compat_robust_list;
+ rcu_read_unlock();
+ }
+diff -urNp linux-2.6.38.7/kernel/gcov/base.c linux-2.6.38.7/kernel/gcov/base.c
+--- linux-2.6.38.7/kernel/gcov/base.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/gcov/base.c 2011-04-28 19:34:15.000000000 -0400
+@@ -102,11 +102,6 @@ void gcov_enable_events(void)
+ }
+
+ #ifdef CONFIG_MODULES
+-static inline int within(void *addr, void *start, unsigned long size)
+-{
+- return ((addr >= start) && (addr < start + size));
+-}
+-
+ /* Update list and generate events when modules are unloaded. */
+ static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,
+ void *data)
+@@ -121,7 +116,7 @@ static int gcov_module_notifier(struct n
+ prev = NULL;
+ /* Remove entries located in module from linked list. */
+ for (info = gcov_info_head; info; info = info->next) {
+- if (within(info, mod->module_core, mod->core_size)) {
++ if (within_module_core_rw((unsigned long)info, mod)) {
+ if (prev)
+ prev->next = info->next;
+ else
+diff -urNp linux-2.6.38.7/kernel/hrtimer.c linux-2.6.38.7/kernel/hrtimer.c
+--- linux-2.6.38.7/kernel/hrtimer.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/hrtimer.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1371,7 +1371,7 @@ void hrtimer_peek_ahead_timers(void)
+ local_irq_restore(flags);
+ }
+
+-static void run_hrtimer_softirq(struct softirq_action *h)
++static void run_hrtimer_softirq(void)
+ {
+ hrtimer_peek_ahead_timers();
+ }
+diff -urNp linux-2.6.38.7/kernel/jump_label.c linux-2.6.38.7/kernel/jump_label.c
+--- linux-2.6.38.7/kernel/jump_label.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/jump_label.c 2011-04-28 19:34:15.000000000 -0400
+@@ -49,6 +49,17 @@ void jump_label_unlock(void)
+ mutex_unlock(&jump_label_mutex);
+ }
+
++static void jump_label_swap(void *a, void *b, int size)
++{
++ struct jump_entry t;
++
++ t = *(struct jump_entry *)a;
++ pax_open_kernel();
++ *(struct jump_entry *)a = *(struct jump_entry *)b;
++ *(struct jump_entry *)b = t;
++ pax_close_kernel();
++}
++
+ static int jump_label_cmp(const void *a, const void *b)
+ {
+ const struct jump_entry *jea = a;
+@@ -70,7 +81,7 @@ sort_jump_label_entries(struct jump_entr
+
+ size = (((unsigned long)stop - (unsigned long)start)
+ / sizeof(struct jump_entry));
+- sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL);
++ sort(start, size, sizeof(struct jump_entry), jump_label_cmp, jump_label_swap);
+ }
+
+ static struct jump_label_entry *get_jump_label_entry(jump_label_t key)
+@@ -407,8 +418,11 @@ static void remove_jump_label_module_ini
+ count = e_module->nr_entries;
+ iter = e_module->table;
+ while (count--) {
+- if (within_module_init(iter->code, mod))
++ if (within_module_init(iter->code, mod)) {
++ pax_open_kernel();
+ iter->key = 0;
++ pax_close_kernel();
++ }
+ iter++;
+ }
+ }
+diff -urNp linux-2.6.38.7/kernel/kallsyms.c linux-2.6.38.7/kernel/kallsyms.c
+--- linux-2.6.38.7/kernel/kallsyms.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/kallsyms.c 2011-04-28 19:34:15.000000000 -0400
+@@ -11,6 +11,9 @@
+ * Changed the compression method from stem compression to "table lookup"
+ * compression (see scripts/kallsyms.c for a more complete description)
+ */
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++#define __INCLUDED_BY_HIDESYM 1
++#endif
+ #include <linux/kallsyms.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -53,12 +56,33 @@ extern const unsigned long kallsyms_mark
+
+ static inline int is_kernel_inittext(unsigned long addr)
+ {
++ if (system_state != SYSTEM_BOOTING)
++ return 0;
++
+ if (addr >= (unsigned long)_sinittext
+ && addr <= (unsigned long)_einittext)
+ return 1;
+ return 0;
+ }
+
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++#ifdef CONFIG_MODULES
++static inline int is_module_text(unsigned long addr)
++{
++ if ((unsigned long)MODULES_EXEC_VADDR <= addr && addr <= (unsigned long)MODULES_EXEC_END)
++ return 1;
++
++ addr = ktla_ktva(addr);
++ return (unsigned long)MODULES_EXEC_VADDR <= addr && addr <= (unsigned long)MODULES_EXEC_END;
++}
++#else
++static inline int is_module_text(unsigned long addr)
++{
++ return 0;
++}
++#endif
++#endif
++
+ static inline int is_kernel_text(unsigned long addr)
+ {
+ if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) ||
+@@ -69,13 +93,28 @@ static inline int is_kernel_text(unsigne
+
+ static inline int is_kernel(unsigned long addr)
+ {
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ if (is_kernel_text(addr) || is_kernel_inittext(addr))
++ return 1;
++
++ if (ktla_ktva((unsigned long)_text) <= addr && addr < (unsigned long)_end)
++#else
+ if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
++#endif
++
+ return 1;
+ return in_gate_area_no_task(addr);
+ }
+
+ static int is_ksym_addr(unsigned long addr)
+ {
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ if (is_module_text(addr))
++ return 0;
++#endif
++
+ if (all_var)
+ return is_kernel(addr);
+
+@@ -416,7 +455,6 @@ static unsigned long get_ksymbol_core(st
+
+ static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
+ {
+- iter->name[0] = '\0';
+ iter->nameoff = get_symbol_offset(new_pos);
+ iter->pos = new_pos;
+ }
+@@ -464,6 +502,11 @@ static int s_show(struct seq_file *m, vo
+ {
+ struct kallsym_iter *iter = m->private;
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ if (current_uid())
++ return 0;
++#endif
++
+ /* Some debugging symbols have no name. Ignore them. */
+ if (!iter->name[0])
+ return 0;
+@@ -504,7 +547,7 @@ static int kallsyms_open(struct inode *i
+ struct kallsym_iter *iter;
+ int ret;
+
+- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
++ iter = kzalloc(sizeof(*iter), GFP_KERNEL);
+ if (!iter)
+ return -ENOMEM;
+ reset_iter(iter, 0);
+diff -urNp linux-2.6.38.7/kernel/kmod.c linux-2.6.38.7/kernel/kmod.c
+--- linux-2.6.38.7/kernel/kmod.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/kmod.c 2011-04-28 19:34:15.000000000 -0400
+@@ -65,13 +65,12 @@ char modprobe_path[KMOD_PATH_LEN] = "/sb
+ * If module auto-loading support is disabled then this function
+ * becomes a no-operation.
+ */
+-int __request_module(bool wait, const char *fmt, ...)
++static int ____request_module(bool wait, char *module_param, const char *fmt, va_list ap)
+ {
+- va_list args;
+ char module_name[MODULE_NAME_LEN];
+ unsigned int max_modprobes;
+ int ret;
+- char *argv[] = { modprobe_path, "-q", "--", module_name, NULL };
++ char *argv[] = { modprobe_path, "-q", "--", module_name, module_param, NULL };
+ static char *envp[] = { "HOME=/",
+ "TERM=linux",
+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+@@ -80,9 +79,7 @@ int __request_module(bool wait, const ch
+ #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
+ static int kmod_loop_msg;
+
+- va_start(args, fmt);
+- ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
+- va_end(args);
++ ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, ap);
+ if (ret >= MODULE_NAME_LEN)
+ return -ENAMETOOLONG;
+
+@@ -90,6 +87,20 @@ int __request_module(bool wait, const ch
+ if (ret)
+ return ret;
+
++#ifdef CONFIG_GRKERNSEC_MODHARDEN
++ if (!current_uid()) {
++ /* hack to workaround consolekit/udisks stupidity */
++ read_lock(&tasklist_lock);
++ if (!strcmp(current->comm, "mount") &&
++ current->real_parent && !strncmp(current->real_parent->comm, "udisk", 5)) {
++ read_unlock(&tasklist_lock);
++ printk(KERN_ALERT "grsec: denied attempt to auto-load fs module %.64s by udisks\n", module_name);
++ return -EPERM;
++ }
++ read_unlock(&tasklist_lock);
++ }
++#endif
++
+ /* If modprobe needs a service that is in a module, we get a recursive
+ * loop. Limit the number of running kmod threads to max_threads/2 or
+ * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
+@@ -123,6 +134,47 @@ int __request_module(bool wait, const ch
+ atomic_dec(&kmod_concurrent);
+ return ret;
+ }
++
++int ___request_module(bool wait, char *module_param, const char *fmt, ...)
++{
++ va_list args;
++ int ret;
++
++ va_start(args, fmt);
++ ret = ____request_module(wait, module_param, fmt, args);
++ va_end(args);
++
++ return ret;
++}
++
++int __request_module(bool wait, const char *fmt, ...)
++{
++ va_list args;
++ int ret;
++
++#ifdef CONFIG_GRKERNSEC_MODHARDEN
++ if (current_uid()) {
++ char module_param[MODULE_NAME_LEN];
++
++ memset(module_param, 0, sizeof(module_param));
++
++ snprintf(module_param, sizeof(module_param) - 1, "grsec_modharden_normal%u_", current_uid());
++
++ va_start(args, fmt);
++ ret = ____request_module(wait, module_param, fmt, args);
++ va_end(args);
++
++ return ret;
++ }
++#endif
++
++ va_start(args, fmt);
++ ret = ____request_module(wait, NULL, fmt, args);
++ va_end(args);
++
++ return ret;
++}
++
+ EXPORT_SYMBOL(__request_module);
+ #endif /* CONFIG_MODULES */
+
+diff -urNp linux-2.6.38.7/kernel/kprobes.c linux-2.6.38.7/kernel/kprobes.c
+--- linux-2.6.38.7/kernel/kprobes.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/kprobes.c 2011-04-28 19:34:15.000000000 -0400
+@@ -185,7 +185,7 @@ static kprobe_opcode_t __kprobes *__get_
+ * kernel image and loaded module images reside. This is required
+ * so x86_64 can correctly handle the %rip-relative fixups.
+ */
+- kip->insns = module_alloc(PAGE_SIZE);
++ kip->insns = module_alloc_exec(PAGE_SIZE);
+ if (!kip->insns) {
+ kfree(kip);
+ return NULL;
+@@ -225,7 +225,7 @@ static int __kprobes collect_one_slot(st
+ */
+ if (!list_is_singular(&kip->list)) {
+ list_del(&kip->list);
+- module_free(NULL, kip->insns);
++ module_free_exec(NULL, kip->insns);
+ kfree(kip);
+ }
+ return 1;
+@@ -1936,7 +1936,7 @@ static int __init init_kprobes(void)
+ {
+ int i, err = 0;
+ unsigned long offset = 0, size = 0;
+- char *modname, namebuf[128];
++ char *modname, namebuf[KSYM_NAME_LEN];
+ const char *symbol_name;
+ void *addr;
+ struct kprobe_blackpoint *kb;
+@@ -2062,7 +2062,7 @@ static int __kprobes show_kprobe_addr(st
+ const char *sym = NULL;
+ unsigned int i = *(loff_t *) v;
+ unsigned long offset = 0;
+- char *modname, namebuf[128];
++ char *modname, namebuf[KSYM_NAME_LEN];
+
+ head = &kprobe_table[i];
+ preempt_disable();
+diff -urNp linux-2.6.38.7/kernel/lockdep.c linux-2.6.38.7/kernel/lockdep.c
+--- linux-2.6.38.7/kernel/lockdep.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/lockdep.c 2011-04-28 19:34:15.000000000 -0400
+@@ -571,6 +571,10 @@ static int static_obj(void *obj)
+ end = (unsigned long) &_end,
+ addr = (unsigned long) obj;
+
++#ifdef CONFIG_PAX_KERNEXEC
++ start = ktla_ktva(start);
++#endif
++
+ /*
+ * static variable?
+ */
+@@ -706,6 +710,7 @@ register_lock_class(struct lockdep_map *
+ if (!static_obj(lock->key)) {
+ debug_locks_off();
+ printk("INFO: trying to register non-static key.\n");
++ printk("lock:%pS key:%pS.\n", lock, lock->key);
+ printk("the code is fine but needs lockdep annotation.\n");
+ printk("turning off the locking correctness validator.\n");
+ dump_stack();
+@@ -2752,7 +2757,7 @@ static int __lock_acquire(struct lockdep
+ if (!class)
+ return 0;
+ }
+- atomic_inc((atomic_t *)&class->ops);
++ atomic_inc_unchecked((atomic_unchecked_t *)&class->ops);
+ if (very_verbose(class)) {
+ printk("\nacquire class [%p] %s", class->key, class->name);
+ if (class->name_version > 1)
+diff -urNp linux-2.6.38.7/kernel/lockdep_proc.c linux-2.6.38.7/kernel/lockdep_proc.c
+--- linux-2.6.38.7/kernel/lockdep_proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/lockdep_proc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -39,7 +39,7 @@ static void l_stop(struct seq_file *m, v
+
+ static void print_name(struct seq_file *m, struct lock_class *class)
+ {
+- char str[128];
++ char str[KSYM_NAME_LEN];
+ const char *name = class->name;
+
+ if (!name) {
+diff -urNp linux-2.6.38.7/kernel/module.c linux-2.6.38.7/kernel/module.c
+--- linux-2.6.38.7/kernel/module.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/module.c 2011-04-29 18:46:41.000000000 -0400
+@@ -57,6 +57,7 @@
+ #include <linux/kmemleak.h>
+ #include <linux/jump_label.h>
+ #include <linux/pfn.h>
++#include <linux/grsecurity.h>
+
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/module.h>
+@@ -118,7 +119,8 @@ static BLOCKING_NOTIFIER_HEAD(module_not
+
+ /* Bounds of module allocation, for speeding __module_address.
+ * Protected by module_mutex. */
+-static unsigned long module_addr_min = -1UL, module_addr_max = 0;
++static unsigned long module_addr_min_rw = -1UL, module_addr_max_rw = 0;
++static unsigned long module_addr_min_rx = -1UL, module_addr_max_rx = 0;
+
+ int register_module_notifier(struct notifier_block * nb)
+ {
+@@ -282,7 +284,7 @@ bool each_symbol(bool (*fn)(const struct
+ return true;
+
+ list_for_each_entry_rcu(mod, &modules, list) {
+- struct symsearch arr[] = {
++ struct symsearch modarr[] = {
+ { mod->syms, mod->syms + mod->num_syms, mod->crcs,
+ NOT_GPL_ONLY, false },
+ { mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,
+@@ -304,7 +306,7 @@ bool each_symbol(bool (*fn)(const struct
+ #endif
+ };
+
+- if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))
++ if (each_symbol_in_section(modarr, ARRAY_SIZE(modarr), mod, fn, data))
+ return true;
+ }
+ return false;
+@@ -415,7 +417,7 @@ static inline void __percpu *mod_percpu(
+ static int percpu_modalloc(struct module *mod,
+ unsigned long size, unsigned long align)
+ {
+- if (align > PAGE_SIZE) {
++ if (align-1 >= PAGE_SIZE) {
+ printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
+ mod->name, align, PAGE_SIZE);
+ align = PAGE_SIZE;
+@@ -1143,7 +1145,7 @@ resolve_symbol_wait(struct module *mod,
+ */
+ #ifdef CONFIG_SYSFS
+
+-#ifdef CONFIG_KALLSYMS
++#if defined(CONFIG_KALLSYMS) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ static inline bool sect_empty(const Elf_Shdr *sect)
+ {
+ return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0;
+@@ -1612,17 +1614,17 @@ void unset_section_ro_nx(struct module *
+ {
+ unsigned long total_pages;
+
+- if (mod->module_core == module_region) {
++ if (mod->module_core_rx == module_region) {
+ /* Set core as NX+RW */
+- total_pages = MOD_NUMBER_OF_PAGES(mod->module_core, mod->core_size);
+- set_memory_nx((unsigned long)mod->module_core, total_pages);
+- set_memory_rw((unsigned long)mod->module_core, total_pages);
++ total_pages = MOD_NUMBER_OF_PAGES(mod->module_core_rx, mod->core_size_rx);
++ set_memory_nx((unsigned long)mod->module_core_rx, total_pages);
++ set_memory_rw((unsigned long)mod->module_core_rx, total_pages);
+
+- } else if (mod->module_init == module_region) {
++ } else if (mod->module_init_rx == module_region) {
+ /* Set init as NX+RW */
+- total_pages = MOD_NUMBER_OF_PAGES(mod->module_init, mod->init_size);
+- set_memory_nx((unsigned long)mod->module_init, total_pages);
+- set_memory_rw((unsigned long)mod->module_init, total_pages);
++ total_pages = MOD_NUMBER_OF_PAGES(mod->module_init_rx, mod->init_size_rx);
++ set_memory_nx((unsigned long)mod->module_init_rx, total_pages);
++ set_memory_rw((unsigned long)mod->module_init_rx, total_pages);
+ }
+ }
+
+@@ -1633,14 +1635,14 @@ void set_all_modules_text_rw()
+
+ mutex_lock(&module_mutex);
+ list_for_each_entry_rcu(mod, &modules, list) {
+- if ((mod->module_core) && (mod->core_text_size)) {
+- set_page_attributes(mod->module_core,
+- mod->module_core + mod->core_text_size,
++ if ((mod->module_core_rx) && (mod->core_size_rx)) {
++ set_page_attributes(mod->module_core_rx,
++ mod->module_core_rx + mod->core_size_rx,
+ set_memory_rw);
+ }
+- if ((mod->module_init) && (mod->init_text_size)) {
+- set_page_attributes(mod->module_init,
+- mod->module_init + mod->init_text_size,
++ if ((mod->module_init_rx) && (mod->init_size_rx)) {
++ set_page_attributes(mod->module_init_rx,
++ mod->module_init_rx + mod->init_size_rx,
+ set_memory_rw);
+ }
+ }
+@@ -1654,14 +1656,14 @@ void set_all_modules_text_ro()
+
+ mutex_lock(&module_mutex);
+ list_for_each_entry_rcu(mod, &modules, list) {
+- if ((mod->module_core) && (mod->core_text_size)) {
+- set_page_attributes(mod->module_core,
+- mod->module_core + mod->core_text_size,
++ if ((mod->module_core_rx) && (mod->core_size_rx)) {
++ set_page_attributes(mod->module_core_rx,
++ mod->module_core_rx + mod->core_size_rx,
+ set_memory_ro);
+ }
+- if ((mod->module_init) && (mod->init_text_size)) {
+- set_page_attributes(mod->module_init,
+- mod->module_init + mod->init_text_size,
++ if ((mod->module_init_rx) && (mod->init_size_rx)) {
++ set_page_attributes(mod->module_init_rx,
++ mod->module_init_rx + mod->init_size_rx,
+ set_memory_ro);
+ }
+ }
+@@ -1696,17 +1698,20 @@ static void free_module(struct module *m
+ destroy_params(mod->kp, mod->num_kp);
+
+ /* This may be NULL, but that's OK */
+- unset_section_ro_nx(mod, mod->module_init);
+- module_free(mod, mod->module_init);
++ unset_section_ro_nx(mod, mod->module_init_rx);
++ module_free(mod, mod->module_init_rw);
++ module_free_exec(mod, mod->module_init_rx);
+ kfree(mod->args);
+ percpu_modfree(mod);
+
+ /* Free lock-classes: */
+- lockdep_free_key_range(mod->module_core, mod->core_size);
++ lockdep_free_key_range(mod->module_core_rx, mod->core_size_rx);
++ lockdep_free_key_range(mod->module_core_rw, mod->core_size_rw);
+
+ /* Finally, free the core (containing the module structure) */
+- unset_section_ro_nx(mod, mod->module_core);
+- module_free(mod, mod->module_core);
++ unset_section_ro_nx(mod, mod->module_core_rx);
++ module_free_exec(mod, mod->module_core_rx);
++ module_free(mod, mod->module_core_rw);
+
+ #ifdef CONFIG_MPU
+ update_protections(current->mm);
+@@ -1775,10 +1780,31 @@ static int simplify_symbols(struct modul
+ unsigned int i;
+ int ret = 0;
+ const struct kernel_symbol *ksym;
++#ifdef CONFIG_GRKERNSEC_MODHARDEN
++ int is_fs_load = 0;
++ int register_filesystem_found = 0;
++ char *p;
++
++ p = strstr(mod->args, "grsec_modharden_fs");
++ if (p) {
++ char *endptr = p + strlen("grsec_modharden_fs");
++ /* copy \0 as well */
++ memmove(p, endptr, strlen(mod->args) - (unsigned int)(endptr - mod->args) + 1);
++ is_fs_load = 1;
++ }
++#endif
+
+ for (i = 1; i < symsec->sh_size / sizeof(Elf_Sym); i++) {
+ const char *name = info->strtab + sym[i].st_name;
+
++#ifdef CONFIG_GRKERNSEC_MODHARDEN
++ /* it's a real shame this will never get ripped and copied
++ upstream! ;(
++ */
++ if (is_fs_load && !strcmp(name, "register_filesystem"))
++ register_filesystem_found = 1;
++#endif
++
+ switch (sym[i].st_shndx) {
+ case SHN_COMMON:
+ /* We compiled with -fno-common. These are not
+@@ -1799,7 +1825,9 @@ static int simplify_symbols(struct modul
+ ksym = resolve_symbol_wait(mod, info, name);
+ /* Ok if resolved. */
+ if (ksym && !IS_ERR(ksym)) {
++ pax_open_kernel();
+ sym[i].st_value = ksym->value;
++ pax_close_kernel();
+ break;
+ }
+
+@@ -1818,11 +1846,20 @@ static int simplify_symbols(struct modul
+ secbase = (unsigned long)mod_percpu(mod);
+ else
+ secbase = info->sechdrs[sym[i].st_shndx].sh_addr;
++ pax_open_kernel();
+ sym[i].st_value += secbase;
++ pax_close_kernel();
+ break;
+ }
+ }
+
++#ifdef CONFIG_GRKERNSEC_MODHARDEN
++ if (is_fs_load && !register_filesystem_found) {
++ printk(KERN_ALERT "grsec: Denied attempt to load non-fs module %.64s through mount\n", mod->name);
++ ret = -EPERM;
++ }
++#endif
++
+ return ret;
+ }
+
+@@ -1906,22 +1943,12 @@ static void layout_sections(struct modul
+ || s->sh_entsize != ~0UL
+ || strstarts(sname, ".init"))
+ continue;
+- s->sh_entsize = get_offset(mod, &mod->core_size, s, i);
++ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
++ s->sh_entsize = get_offset(mod, &mod->core_size_rw, s, i);
++ else
++ s->sh_entsize = get_offset(mod, &mod->core_size_rx, s, i);
+ DEBUGP("\t%s\n", name);
+ }
+- switch (m) {
+- case 0: /* executable */
+- mod->core_size = debug_align(mod->core_size);
+- mod->core_text_size = mod->core_size;
+- break;
+- case 1: /* RO: text and ro-data */
+- mod->core_size = debug_align(mod->core_size);
+- mod->core_ro_size = mod->core_size;
+- break;
+- case 3: /* whole core */
+- mod->core_size = debug_align(mod->core_size);
+- break;
+- }
+ }
+
+ DEBUGP("Init section allocation order:\n");
+@@ -1935,23 +1962,13 @@ static void layout_sections(struct modul
+ || s->sh_entsize != ~0UL
+ || !strstarts(sname, ".init"))
+ continue;
+- s->sh_entsize = (get_offset(mod, &mod->init_size, s, i)
+- | INIT_OFFSET_MASK);
++ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
++ s->sh_entsize = get_offset(mod, &mod->init_size_rw, s, i);
++ else
++ s->sh_entsize = get_offset(mod, &mod->init_size_rx, s, i);
++ s->sh_entsize |= INIT_OFFSET_MASK;
+ DEBUGP("\t%s\n", sname);
+ }
+- switch (m) {
+- case 0: /* executable */
+- mod->init_size = debug_align(mod->init_size);
+- mod->init_text_size = mod->init_size;
+- break;
+- case 1: /* RO: text and ro-data */
+- mod->init_size = debug_align(mod->init_size);
+- mod->init_ro_size = mod->init_size;
+- break;
+- case 3: /* whole init */
+- mod->init_size = debug_align(mod->init_size);
+- break;
+- }
+ }
+ }
+
+@@ -2119,7 +2136,7 @@ static void layout_symtab(struct module
+
+ /* Put symbol section at end of init part of module. */
+ symsect->sh_flags |= SHF_ALLOC;
+- symsect->sh_entsize = get_offset(mod, &mod->init_size, symsect,
++ symsect->sh_entsize = get_offset(mod, &mod->init_size_rx, symsect,
+ info->index.sym) | INIT_OFFSET_MASK;
+ DEBUGP("\t%s\n", info->secstrings + symsect->sh_name);
+
+@@ -2136,19 +2153,19 @@ static void layout_symtab(struct module
+ }
+
+ /* Append room for core symbols at end of core part. */
+- info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
+- mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym);
++ info->symoffs = ALIGN(mod->core_size_rx, symsect->sh_addralign ?: 1);
++ mod->core_size_rx = info->symoffs + ndst * sizeof(Elf_Sym);
+
+ /* Put string table section at end of init part of module. */
+ strsect->sh_flags |= SHF_ALLOC;
+- strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
++ strsect->sh_entsize = get_offset(mod, &mod->init_size_rx, strsect,
+ info->index.str) | INIT_OFFSET_MASK;
+ DEBUGP("\t%s\n", info->secstrings + strsect->sh_name);
+
+ /* Append room for core symbols' strings at end of core part. */
+- info->stroffs = mod->core_size;
++ info->stroffs = mod->core_size_rx;
+ __set_bit(0, info->strmap);
+- mod->core_size += bitmap_weight(info->strmap, strsect->sh_size);
++ mod->core_size_rx += bitmap_weight(info->strmap, strsect->sh_size);
+ }
+
+ static void add_kallsyms(struct module *mod, const struct load_info *info)
+@@ -2164,11 +2181,13 @@ static void add_kallsyms(struct module *
+ /* Make sure we get permanent strtab: don't use info->strtab. */
+ mod->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
+
++ pax_open_kernel();
++
+ /* Set types up while we still have access to sections. */
+ for (i = 0; i < mod->num_symtab; i++)
+ mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
+
+- mod->core_symtab = dst = mod->module_core + info->symoffs;
++ mod->core_symtab = dst = mod->module_core_rx + info->symoffs;
+ src = mod->symtab;
+ *dst = *src;
+ for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
+@@ -2181,10 +2200,12 @@ static void add_kallsyms(struct module *
+ }
+ mod->core_num_syms = ndst;
+
+- mod->core_strtab = s = mod->module_core + info->stroffs;
++ mod->core_strtab = s = mod->module_core_rx + info->stroffs;
+ for (*s = 0, i = 1; i < info->sechdrs[info->index.str].sh_size; ++i)
+ if (test_bit(i, info->strmap))
+ *++s = mod->strtab[i];
++
++ pax_close_kernel();
+ }
+ #else
+ static inline void layout_symtab(struct module *mod, struct load_info *info)
+@@ -2213,17 +2234,33 @@ static void dynamic_debug_remove(struct
+ ddebug_remove_module(debug->modname);
+ }
+
+-static void *module_alloc_update_bounds(unsigned long size)
++static void *module_alloc_update_bounds_rw(unsigned long size)
+ {
+ void *ret = module_alloc(size);
+
+ if (ret) {
+ mutex_lock(&module_mutex);
+ /* Update module bounds. */
+- if ((unsigned long)ret < module_addr_min)
+- module_addr_min = (unsigned long)ret;
+- if ((unsigned long)ret + size > module_addr_max)
+- module_addr_max = (unsigned long)ret + size;
++ if ((unsigned long)ret < module_addr_min_rw)
++ module_addr_min_rw = (unsigned long)ret;
++ if ((unsigned long)ret + size > module_addr_max_rw)
++ module_addr_max_rw = (unsigned long)ret + size;
++ mutex_unlock(&module_mutex);
++ }
++ return ret;
++}
++
++static void *module_alloc_update_bounds_rx(unsigned long size)
++{
++ void *ret = module_alloc_exec(size);
++
++ if (ret) {
++ mutex_lock(&module_mutex);
++ /* Update module bounds. */
++ if ((unsigned long)ret < module_addr_min_rx)
++ module_addr_min_rx = (unsigned long)ret;
++ if ((unsigned long)ret + size > module_addr_max_rx)
++ module_addr_max_rx = (unsigned long)ret + size;
+ mutex_unlock(&module_mutex);
+ }
+ return ret;
+@@ -2516,7 +2553,7 @@ static int move_module(struct module *mo
+ void *ptr;
+
+ /* Do the allocs. */
+- ptr = module_alloc_update_bounds(mod->core_size);
++ ptr = module_alloc_update_bounds_rw(mod->core_size_rw);
+ /*
+ * The pointer to this block is stored in the module structure
+ * which is inside the block. Just mark it as not being a
+@@ -2526,23 +2563,50 @@ static int move_module(struct module *mo
+ if (!ptr)
+ return -ENOMEM;
+
+- memset(ptr, 0, mod->core_size);
+- mod->module_core = ptr;
++ memset(ptr, 0, mod->core_size_rw);
++ mod->module_core_rw = ptr;
+
+- ptr = module_alloc_update_bounds(mod->init_size);
++ ptr = module_alloc_update_bounds_rw(mod->init_size_rw);
+ /*
+ * The pointer to this block is stored in the module structure
+ * which is inside the block. This block doesn't need to be
+ * scanned as it contains data and code that will be freed
+ * after the module is initialized.
+ */
+- kmemleak_ignore(ptr);
+- if (!ptr && mod->init_size) {
+- module_free(mod, mod->module_core);
++ kmemleak_not_leak(ptr);
++ if (!ptr && mod->init_size_rw) {
++ module_free(mod, mod->module_core_rw);
+ return -ENOMEM;
+ }
+- memset(ptr, 0, mod->init_size);
+- mod->module_init = ptr;
++ memset(ptr, 0, mod->init_size_rw);
++ mod->module_init_rw = ptr;
++
++ ptr = module_alloc_update_bounds_rx(mod->core_size_rx);
++ kmemleak_not_leak(ptr);
++ if (!ptr) {
++ module_free(mod, mod->module_init_rw);
++ module_free(mod, mod->module_core_rw);
++ return -ENOMEM;
++ }
++
++ pax_open_kernel();
++ memset(ptr, 0, mod->core_size_rx);
++ pax_close_kernel();
++ mod->module_core_rx = ptr;
++
++ ptr = module_alloc_update_bounds_rx(mod->init_size_rx);
++ kmemleak_not_leak(ptr);
++ if (!ptr && mod->init_size_rx) {
++ module_free_exec(mod, mod->module_core_rx);
++ module_free(mod, mod->module_init_rw);
++ module_free(mod, mod->module_core_rw);
++ return -ENOMEM;
++ }
++
++ pax_open_kernel();
++ memset(ptr, 0, mod->init_size_rx);
++ pax_close_kernel();
++ mod->module_init_rx = ptr;
+
+ /* Transfer each section which specifies SHF_ALLOC */
+ DEBUGP("final section addresses:\n");
+@@ -2553,16 +2617,45 @@ static int move_module(struct module *mo
+ if (!(shdr->sh_flags & SHF_ALLOC))
+ continue;
+
+- if (shdr->sh_entsize & INIT_OFFSET_MASK)
+- dest = mod->module_init
+- + (shdr->sh_entsize & ~INIT_OFFSET_MASK);
+- else
+- dest = mod->module_core + shdr->sh_entsize;
++ if (shdr->sh_entsize & INIT_OFFSET_MASK) {
++ if ((shdr->sh_flags & SHF_WRITE) || !(shdr->sh_flags & SHF_ALLOC))
++ dest = mod->module_init_rw
++ + (shdr->sh_entsize & ~INIT_OFFSET_MASK);
++ else
++ dest = mod->module_init_rx
++ + (shdr->sh_entsize & ~INIT_OFFSET_MASK);
++ } else {
++ if ((shdr->sh_flags & SHF_WRITE) || !(shdr->sh_flags & SHF_ALLOC))
++ dest = mod->module_core_rw + shdr->sh_entsize;
++ else
++ dest = mod->module_core_rx + shdr->sh_entsize;
++ }
++
++ if (shdr->sh_type != SHT_NOBITS) {
++
++#ifdef CONFIG_PAX_KERNEXEC
++#ifdef CONFIG_X86_64
++ if ((shdr->sh_flags & SHF_WRITE) && (shdr->sh_flags & SHF_EXECINSTR))
++ set_memory_x((unsigned long)dest, (shdr->sh_size + PAGE_SIZE) >> PAGE_SHIFT);
++#endif
++ if (!(shdr->sh_flags & SHF_WRITE) && (shdr->sh_flags & SHF_ALLOC)) {
++ pax_open_kernel();
++ memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);
++ pax_close_kernel();
++ } else
++#endif
+
+- if (shdr->sh_type != SHT_NOBITS)
+ memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);
++ }
+ /* Update sh_addr to point to copy in image. */
+- shdr->sh_addr = (unsigned long)dest;
++
++#ifdef CONFIG_PAX_KERNEXEC
++ if (shdr->sh_flags & SHF_EXECINSTR)
++ shdr->sh_addr = ktva_ktla((unsigned long)dest);
++ else
++#endif
++
++ shdr->sh_addr = (unsigned long)dest;
+ DEBUGP("\t0x%lx %s\n",
+ shdr->sh_addr, info->secstrings + shdr->sh_name);
+ }
+@@ -2613,12 +2706,12 @@ static void flush_module_icache(const st
+ * Do it before processing of module parameters, so the module
+ * can provide parameter accessor functions of its own.
+ */
+- if (mod->module_init)
+- flush_icache_range((unsigned long)mod->module_init,
+- (unsigned long)mod->module_init
+- + mod->init_size);
+- flush_icache_range((unsigned long)mod->module_core,
+- (unsigned long)mod->module_core + mod->core_size);
++ if (mod->module_init_rx)
++ flush_icache_range((unsigned long)mod->module_init_rx,
++ (unsigned long)mod->module_init_rx
++ + mod->init_size_rx);
++ flush_icache_range((unsigned long)mod->module_core_rx,
++ (unsigned long)mod->module_core_rx + mod->core_size_rx);
+
+ set_fs(old_fs);
+ }
+@@ -2690,8 +2783,10 @@ static void module_deallocate(struct mod
+ {
+ kfree(info->strmap);
+ percpu_modfree(mod);
+- module_free(mod, mod->module_init);
+- module_free(mod, mod->module_core);
++ module_free_exec(mod, mod->module_init_rx);
++ module_free_exec(mod, mod->module_core_rx);
++ module_free(mod, mod->module_init_rw);
++ module_free(mod, mod->module_core_rw);
+ }
+
+ static int post_relocation(struct module *mod, const struct load_info *info)
+@@ -2748,9 +2843,38 @@ static struct module *load_module(void _
+ if (err)
+ goto free_unload;
+
++ /* Now copy in args */
++ mod->args = strndup_user(uargs, ~0UL >> 1);
++ if (IS_ERR(mod->args)) {
++ err = PTR_ERR(mod->args);
++ goto free_unload;
++ }
++
+ /* Set up MODINFO_ATTR fields */
+ setup_modinfo(mod, &info);
+
++#ifdef CONFIG_GRKERNSEC_MODHARDEN
++ {
++ char *p, *p2;
++
++ if (strstr(mod->args, "grsec_modharden_netdev")) {
++ printk(KERN_ALERT "grsec: denied auto-loading kernel module for a network device with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%.64s instead.", mod->name);
++ err = -EPERM;
++ goto free_modinfo;
++ } else if ((p = strstr(mod->args, "grsec_modharden_normal"))) {
++ p += strlen("grsec_modharden_normal");
++ p2 = strstr(p, "_");
++ if (p2) {
++ *p2 = '\0';
++ printk(KERN_ALERT "grsec: denied kernel module auto-load of %.64s by uid %.9s\n", mod->name, p);
++ *p2 = '_';
++ }
++ err = -EPERM;
++ goto free_modinfo;
++ }
++ }
++#endif
++
+ /* Fix up syms, so that st_value is a pointer to location. */
+ err = simplify_symbols(mod, &info);
+ if (err < 0)
+@@ -2766,13 +2890,6 @@ static struct module *load_module(void _
+
+ flush_module_icache(mod);
+
+- /* Now copy in args */
+- mod->args = strndup_user(uargs, ~0UL >> 1);
+- if (IS_ERR(mod->args)) {
+- err = PTR_ERR(mod->args);
+- goto free_arch_cleanup;
+- }
+-
+ /* Mark state as coming so strong_try_module_get() ignores us. */
+ mod->state = MODULE_STATE_COMING;
+
+@@ -2832,11 +2949,10 @@ static struct module *load_module(void _
+ unlock:
+ mutex_unlock(&module_mutex);
+ synchronize_sched();
+- kfree(mod->args);
+- free_arch_cleanup:
+ module_arch_cleanup(mod);
+ free_modinfo:
+ free_modinfo(mod);
++ kfree(mod->args);
+ free_unload:
+ module_unload_free(mod);
+ free_module:
+@@ -2877,16 +2993,16 @@ SYSCALL_DEFINE3(init_module, void __user
+ MODULE_STATE_COMING, mod);
+
+ /* Set RO and NX regions for core */
+- set_section_ro_nx(mod->module_core,
+- mod->core_text_size,
+- mod->core_ro_size,
+- mod->core_size);
++ set_section_ro_nx(mod->module_core_rx,
++ mod->core_size_rx,
++ mod->core_size_rx,
++ mod->core_size_rx);
+
+ /* Set RO and NX regions for init */
+- set_section_ro_nx(mod->module_init,
+- mod->init_text_size,
+- mod->init_ro_size,
+- mod->init_size);
++ set_section_ro_nx(mod->module_init_rx,
++ mod->init_size_rx,
++ mod->init_size_rx,
++ mod->init_size_rx);
+
+ do_mod_ctors(mod);
+ /* Start the module */
+@@ -2931,11 +3047,13 @@ SYSCALL_DEFINE3(init_module, void __user
+ mod->symtab = mod->core_symtab;
+ mod->strtab = mod->core_strtab;
+ #endif
+- unset_section_ro_nx(mod, mod->module_init);
+- module_free(mod, mod->module_init);
+- mod->module_init = NULL;
+- mod->init_size = 0;
+- mod->init_text_size = 0;
++ unset_section_ro_nx(mod, mod->module_init_rx);
++ module_free(mod, mod->module_init_rw);
++ module_free_exec(mod, mod->module_init_rx);
++ mod->module_init_rw = NULL;
++ mod->module_init_rx = NULL;
++ mod->init_size_rw = 0;
++ mod->init_size_rx = 0;
+ mutex_unlock(&module_mutex);
+
+ return 0;
+@@ -2966,10 +3084,16 @@ static const char *get_ksymbol(struct mo
+ unsigned long nextval;
+
+ /* At worse, next value is at end of module */
+- if (within_module_init(addr, mod))
+- nextval = (unsigned long)mod->module_init+mod->init_text_size;
++ if (within_module_init_rx(addr, mod))
++ nextval = (unsigned long)mod->module_init_rx+mod->init_size_rx;
++ else if (within_module_init_rw(addr, mod))
++ nextval = (unsigned long)mod->module_init_rw+mod->init_size_rw;
++ else if (within_module_core_rx(addr, mod))
++ nextval = (unsigned long)mod->module_core_rx+mod->core_size_rx;
++ else if (within_module_core_rw(addr, mod))
++ nextval = (unsigned long)mod->module_core_rw+mod->core_size_rw;
+ else
+- nextval = (unsigned long)mod->module_core+mod->core_text_size;
++ return NULL;
+
+ /* Scan for closest preceeding symbol, and next symbol. (ELF
+ starts real symbols at 1). */
+@@ -3215,7 +3339,7 @@ static int m_show(struct seq_file *m, vo
+ char buf[8];
+
+ seq_printf(m, "%s %u",
+- mod->name, mod->init_size + mod->core_size);
++ mod->name, mod->init_size_rx + mod->init_size_rw + mod->core_size_rx + mod->core_size_rw);
+ print_unload_info(m, mod);
+
+ /* Informative for users. */
+@@ -3224,7 +3348,7 @@ static int m_show(struct seq_file *m, vo
+ mod->state == MODULE_STATE_COMING ? "Loading":
+ "Live");
+ /* Used by oprofile and other similar tools. */
+- seq_printf(m, " 0x%p", mod->module_core);
++ seq_printf(m, " 0x%p 0x%p", mod->module_core_rx, mod->module_core_rw);
+
+ /* Taints info */
+ if (mod->taints)
+@@ -3260,7 +3384,17 @@ static const struct file_operations proc
+
+ static int __init proc_modules_init(void)
+ {
++#ifndef CONFIG_GRKERNSEC_HIDESYM
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ proc_create("modules", S_IRUSR, NULL, &proc_modules_operations);
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ proc_create("modules", S_IRUSR | S_IRGRP, NULL, &proc_modules_operations);
++#else
+ proc_create("modules", 0, NULL, &proc_modules_operations);
++#endif
++#else
++ proc_create("modules", S_IRUSR, NULL, &proc_modules_operations);
++#endif
+ return 0;
+ }
+ module_init(proc_modules_init);
+@@ -3319,12 +3453,12 @@ struct module *__module_address(unsigned
+ {
+ struct module *mod;
+
+- if (addr < module_addr_min || addr > module_addr_max)
++ if ((addr < module_addr_min_rx || addr > module_addr_max_rx) &&
++ (addr < module_addr_min_rw || addr > module_addr_max_rw))
+ return NULL;
+
+ list_for_each_entry_rcu(mod, &modules, list)
+- if (within_module_core(addr, mod)
+- || within_module_init(addr, mod))
++ if (within_module_init(addr, mod) || within_module_core(addr, mod))
+ return mod;
+ return NULL;
+ }
+@@ -3358,11 +3492,20 @@ bool is_module_text_address(unsigned lon
+ */
+ struct module *__module_text_address(unsigned long addr)
+ {
+- struct module *mod = __module_address(addr);
++ struct module *mod;
++
++#ifdef CONFIG_X86_32
++ addr = ktla_ktva(addr);
++#endif
++
++ if (addr < module_addr_min_rx || addr > module_addr_max_rx)
++ return NULL;
++
++ mod = __module_address(addr);
++
+ if (mod) {
+ /* Make sure it's within the text section. */
+- if (!within(addr, mod->module_init, mod->init_text_size)
+- && !within(addr, mod->module_core, mod->core_text_size))
++ if (!within_module_init_rx(addr, mod) && !within_module_core_rx(addr, mod))
+ mod = NULL;
+ }
+ return mod;
+diff -urNp linux-2.6.38.7/kernel/mutex.c linux-2.6.38.7/kernel/mutex.c
+--- linux-2.6.38.7/kernel/mutex.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/mutex.c 2011-05-22 13:38:03.000000000 -0400
+@@ -160,7 +160,7 @@ __mutex_lock_common(struct mutex *lock,
+ */
+
+ for (;;) {
+- struct thread_info *owner;
++ struct task_struct *owner;
+
+ /*
+ * If we own the BKL, then don't spin. The owner of
+@@ -205,7 +205,7 @@ __mutex_lock_common(struct mutex *lock,
+ spin_lock_mutex(&lock->wait_lock, flags);
+
+ debug_mutex_lock_common(lock, &waiter);
+- debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));
++ debug_mutex_add_waiter(lock, &waiter, task);
+
+ /* add waiting tasks to the end of the waitqueue (FIFO): */
+ list_add_tail(&waiter.list, &lock->wait_list);
+@@ -234,8 +234,7 @@ __mutex_lock_common(struct mutex *lock,
+ * TASK_UNINTERRUPTIBLE case.)
+ */
+ if (unlikely(signal_pending_state(state, task))) {
+- mutex_remove_waiter(lock, &waiter,
+- task_thread_info(task));
++ mutex_remove_waiter(lock, &waiter, task);
+ mutex_release(&lock->dep_map, 1, ip);
+ spin_unlock_mutex(&lock->wait_lock, flags);
+
+@@ -256,7 +255,7 @@ __mutex_lock_common(struct mutex *lock,
+ done:
+ lock_acquired(&lock->dep_map, ip);
+ /* got the lock - rejoice! */
+- mutex_remove_waiter(lock, &waiter, current_thread_info());
++ mutex_remove_waiter(lock, &waiter, task);
+ mutex_set_owner(lock);
+
+ /* set it to 0 if there are no waiters left: */
+diff -urNp linux-2.6.38.7/kernel/mutex-debug.c linux-2.6.38.7/kernel/mutex-debug.c
+--- linux-2.6.38.7/kernel/mutex-debug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/mutex-debug.c 2011-05-22 13:31:07.000000000 -0400
+@@ -49,21 +49,21 @@ void debug_mutex_free_waiter(struct mute
+ }
+
+ void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+- struct thread_info *ti)
++ struct task_struct *task)
+ {
+ SMP_DEBUG_LOCKS_WARN_ON(!spin_is_locked(&lock->wait_lock));
+
+ /* Mark the current thread as blocked on the lock: */
+- ti->task->blocked_on = waiter;
++ task->blocked_on = waiter;
+ }
+
+ void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+- struct thread_info *ti)
++ struct task_struct *task)
+ {
+ DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list));
+- DEBUG_LOCKS_WARN_ON(waiter->task != ti->task);
+- DEBUG_LOCKS_WARN_ON(ti->task->blocked_on != waiter);
+- ti->task->blocked_on = NULL;
++ DEBUG_LOCKS_WARN_ON(waiter->task != task);
++ DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter);
++ task->blocked_on = NULL;
+
+ list_del_init(&waiter->list);
+ waiter->task = NULL;
+@@ -75,7 +75,7 @@ void debug_mutex_unlock(struct mutex *lo
+ return;
+
+ DEBUG_LOCKS_WARN_ON(lock->magic != lock);
+- DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info());
++ DEBUG_LOCKS_WARN_ON(lock->owner != current);
+ DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
+ mutex_clear_owner(lock);
+ }
+diff -urNp linux-2.6.38.7/kernel/mutex-debug.h linux-2.6.38.7/kernel/mutex-debug.h
+--- linux-2.6.38.7/kernel/mutex-debug.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/mutex-debug.h 2011-04-28 19:34:15.000000000 -0400
+@@ -20,16 +20,16 @@ extern void debug_mutex_wake_waiter(stru
+ extern void debug_mutex_free_waiter(struct mutex_waiter *waiter);
+ extern void debug_mutex_add_waiter(struct mutex *lock,
+ struct mutex_waiter *waiter,
+- struct thread_info *ti);
++ struct task_struct *task);
+ extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+- struct thread_info *ti);
++ struct task_struct *task);
+ extern void debug_mutex_unlock(struct mutex *lock);
+ extern void debug_mutex_init(struct mutex *lock, const char *name,
+ struct lock_class_key *key);
+
+ static inline void mutex_set_owner(struct mutex *lock)
+ {
+- lock->owner = current_thread_info();
++ lock->owner = current;
+ }
+
+ static inline void mutex_clear_owner(struct mutex *lock)
+diff -urNp linux-2.6.38.7/kernel/mutex.h linux-2.6.38.7/kernel/mutex.h
+--- linux-2.6.38.7/kernel/mutex.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/mutex.h 2011-04-28 19:34:15.000000000 -0400
+@@ -19,7 +19,7 @@
+ #ifdef CONFIG_SMP
+ static inline void mutex_set_owner(struct mutex *lock)
+ {
+- lock->owner = current_thread_info();
++ lock->owner = current;
+ }
+
+ static inline void mutex_clear_owner(struct mutex *lock)
+diff -urNp linux-2.6.38.7/kernel/padata.c linux-2.6.38.7/kernel/padata.c
+--- linux-2.6.38.7/kernel/padata.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/padata.c 2011-04-28 19:57:25.000000000 -0400
+@@ -132,10 +132,10 @@ int padata_do_parallel(struct padata_ins
+ padata->pd = pd;
+ padata->cb_cpu = cb_cpu;
+
+- if (unlikely(atomic_read(&pd->seq_nr) == pd->max_seq_nr))
+- atomic_set(&pd->seq_nr, -1);
++ if (unlikely(atomic_read_unchecked(&pd->seq_nr) == pd->max_seq_nr))
++ atomic_set_unchecked(&pd->seq_nr, -1);
+
+- padata->seq_nr = atomic_inc_return(&pd->seq_nr);
++ padata->seq_nr = atomic_inc_return_unchecked(&pd->seq_nr);
+
+ target_cpu = padata_cpu_hash(padata);
+ queue = per_cpu_ptr(pd->pqueue, target_cpu);
+@@ -444,7 +444,7 @@ static struct parallel_data *padata_allo
+ padata_init_pqueues(pd);
+ padata_init_squeues(pd);
+ setup_timer(&pd->timer, padata_reorder_timer, (unsigned long)pd);
+- atomic_set(&pd->seq_nr, -1);
++ atomic_set_unchecked(&pd->seq_nr, -1);
+ atomic_set(&pd->reorder_objects, 0);
+ atomic_set(&pd->refcnt, 0);
+ pd->pinst = pinst;
+diff -urNp linux-2.6.38.7/kernel/panic.c linux-2.6.38.7/kernel/panic.c
+--- linux-2.6.38.7/kernel/panic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/panic.c 2011-04-28 19:34:15.000000000 -0400
+@@ -369,7 +369,7 @@ static void warn_slowpath_common(const c
+ const char *board;
+
+ printk(KERN_WARNING "------------[ cut here ]------------\n");
+- printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller);
++ printk(KERN_WARNING "WARNING: at %s:%d %pA()\n", file, line, caller);
+ board = dmi_get_system_info(DMI_PRODUCT_NAME);
+ if (board)
+ printk(KERN_WARNING "Hardware name: %s\n", board);
+@@ -424,7 +424,8 @@ EXPORT_SYMBOL(warn_slowpath_null);
+ */
+ void __stack_chk_fail(void)
+ {
+- panic("stack-protector: Kernel stack is corrupted in: %p\n",
++ dump_stack();
++ panic("stack-protector: Kernel stack is corrupted in: %pA\n",
+ __builtin_return_address(0));
+ }
+ EXPORT_SYMBOL(__stack_chk_fail);
+diff -urNp linux-2.6.38.7/kernel/perf_event.c linux-2.6.38.7/kernel/perf_event.c
+--- linux-2.6.38.7/kernel/perf_event.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/kernel/perf_event.c 2011-04-28 19:57:25.000000000 -0400
+@@ -70,7 +70,7 @@ int sysctl_perf_event_mlock __read_mostl
+ */
+ int sysctl_perf_event_sample_rate __read_mostly = 100000;
+
+-static atomic64_t perf_event_id;
++static atomic64_unchecked_t perf_event_id;
+
+ static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
+ enum event_type_t event_type);
+@@ -1923,7 +1923,7 @@ static void __perf_event_read(void *info
+
+ static inline u64 perf_event_count(struct perf_event *event)
+ {
+- return local64_read(&event->count) + atomic64_read(&event->child_count);
++ return local64_read(&event->count) + atomic64_read_unchecked(&event->child_count);
+ }
+
+ static u64 perf_event_read(struct perf_event *event)
+@@ -2442,9 +2442,9 @@ u64 perf_event_read_value(struct perf_ev
+ mutex_lock(&event->child_mutex);
+ total += perf_event_read(event);
+ *enabled += event->total_time_enabled +
+- atomic64_read(&event->child_total_time_enabled);
++ atomic64_read_unchecked(&event->child_total_time_enabled);
+ *running += event->total_time_running +
+- atomic64_read(&event->child_total_time_running);
++ atomic64_read_unchecked(&event->child_total_time_running);
+
+ list_for_each_entry(child, &event->child_list, child_list) {
+ total += perf_event_read(child);
+@@ -2807,10 +2807,10 @@ void perf_event_update_userpage(struct p
+ userpg->offset -= local64_read(&event->hw.prev_count);
+
+ userpg->time_enabled = event->total_time_enabled +
+- atomic64_read(&event->child_total_time_enabled);
++ atomic64_read_unchecked(&event->child_total_time_enabled);
+
+ userpg->time_running = event->total_time_running +
+- atomic64_read(&event->child_total_time_running);
++ atomic64_read_unchecked(&event->child_total_time_running);
+
+ barrier();
+ ++userpg->lock;
+@@ -3607,11 +3607,11 @@ static void perf_output_read_one(struct
+ values[n++] = perf_event_count(event);
+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+ values[n++] = enabled +
+- atomic64_read(&event->child_total_time_enabled);
++ atomic64_read_unchecked(&event->child_total_time_enabled);
+ }
+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+ values[n++] = running +
+- atomic64_read(&event->child_total_time_running);
++ atomic64_read_unchecked(&event->child_total_time_running);
+ }
+ if (read_format & PERF_FORMAT_ID)
+ values[n++] = primary_event_id(event);
+@@ -5597,7 +5597,7 @@ perf_event_alloc(struct perf_event_attr
+ event->parent = parent_event;
+
+ event->ns = get_pid_ns(current->nsproxy->pid_ns);
+- event->id = atomic64_inc_return(&perf_event_id);
++ event->id = atomic64_inc_return_unchecked(&perf_event_id);
+
+ event->state = PERF_EVENT_STATE_INACTIVE;
+
+@@ -6095,10 +6095,10 @@ static void sync_child_event(struct perf
+ /*
+ * Add back the child's count to the parent's count:
+ */
+- atomic64_add(child_val, &parent_event->child_count);
+- atomic64_add(child_event->total_time_enabled,
++ atomic64_add_unchecked(child_val, &parent_event->child_count);
++ atomic64_add_unchecked(child_event->total_time_enabled,
+ &parent_event->child_total_time_enabled);
+- atomic64_add(child_event->total_time_running,
++ atomic64_add_unchecked(child_event->total_time_running,
+ &parent_event->child_total_time_running);
+
+ /*
+diff -urNp linux-2.6.38.7/kernel/pid.c linux-2.6.38.7/kernel/pid.c
+--- linux-2.6.38.7/kernel/pid.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/kernel/pid.c 2011-04-28 19:34:15.000000000 -0400
+@@ -33,6 +33,7 @@
+ #include <linux/rculist.h>
+ #include <linux/bootmem.h>
+ #include <linux/hash.h>
++#include <linux/security.h>
+ #include <linux/pid_namespace.h>
+ #include <linux/init_task.h>
+ #include <linux/syscalls.h>
+@@ -45,7 +46,7 @@ struct pid init_struct_pid = INIT_STRUCT
+
+ int pid_max = PID_MAX_DEFAULT;
+
+-#define RESERVED_PIDS 300
++#define RESERVED_PIDS 500
+
+ int pid_max_min = RESERVED_PIDS + 1;
+ int pid_max_max = PID_MAX_LIMIT;
+@@ -419,8 +420,15 @@ EXPORT_SYMBOL(pid_task);
+ */
+ struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
+ {
++ struct task_struct *task;
++
+ rcu_lockdep_assert(rcu_read_lock_held());
+- return pid_task(find_pid_ns(nr, ns), PIDTYPE_PID);
++ task = pid_task(find_pid_ns(nr, ns), PIDTYPE_PID);
++
++ if (gr_pid_is_chrooted(task))
++ return NULL;
++
++ return task;
+ }
+
+ struct task_struct *find_task_by_vpid(pid_t vnr)
+diff -urNp linux-2.6.38.7/kernel/posix-cpu-timers.c linux-2.6.38.7/kernel/posix-cpu-timers.c
+--- linux-2.6.38.7/kernel/posix-cpu-timers.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/posix-cpu-timers.c 2011-04-28 19:34:15.000000000 -0400
+@@ -6,6 +6,7 @@
+ #include <linux/posix-timers.h>
+ #include <linux/errno.h>
+ #include <linux/math64.h>
++#include <linux/security.h>
+ #include <asm/uaccess.h>
+ #include <linux/kernel_stat.h>
+ #include <trace/events/timer.h>
+diff -urNp linux-2.6.38.7/kernel/posix-timers.c linux-2.6.38.7/kernel/posix-timers.c
+--- linux-2.6.38.7/kernel/posix-timers.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/posix-timers.c 2011-05-16 21:47:09.000000000 -0400
+@@ -42,6 +42,7 @@
+ #include <linux/compiler.h>
+ #include <linux/idr.h>
+ #include <linux/posix-timers.h>
++#include <linux/grsecurity.h>
+ #include <linux/syscalls.h>
+ #include <linux/wait.h>
+ #include <linux/workqueue.h>
+@@ -302,6 +303,8 @@ static __init int init_posix_timers(void
+ .nsleep = no_nsleep,
+ };
+
++ pax_track_stack();
++
+ register_posix_clock(CLOCK_REALTIME, &clock_realtime);
+ register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic);
+ register_posix_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw);
+@@ -955,6 +958,13 @@ SYSCALL_DEFINE2(clock_settime, const clo
+ if (copy_from_user(&new_tp, tp, sizeof (*tp)))
+ return -EFAULT;
+
++ /* only the CLOCK_REALTIME clock can be set, all other clocks
++ have their clock_set fptr set to a nosettime dummy function
++ CLOCK_REALTIME has a NULL clock_set fptr which causes it to
++ call common_clock_set, which calls do_sys_settimeofday, which
++ we hook
++ */
++
+ return CLOCK_DISPATCH(which_clock, clock_set, (which_clock, &new_tp));
+ }
+
+diff -urNp linux-2.6.38.7/kernel/power/poweroff.c linux-2.6.38.7/kernel/power/poweroff.c
+--- linux-2.6.38.7/kernel/power/poweroff.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/power/poweroff.c 2011-04-28 19:34:15.000000000 -0400
+@@ -37,7 +37,7 @@ static struct sysrq_key_op sysrq_powerof
+ .enable_mask = SYSRQ_ENABLE_BOOT,
+ };
+
+-static int pm_sysrq_init(void)
++static int __init pm_sysrq_init(void)
+ {
+ register_sysrq_key('o', &sysrq_poweroff_op);
+ return 0;
+diff -urNp linux-2.6.38.7/kernel/power/process.c linux-2.6.38.7/kernel/power/process.c
+--- linux-2.6.38.7/kernel/power/process.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/power/process.c 2011-04-28 19:34:15.000000000 -0400
+@@ -41,6 +41,7 @@ static int try_to_freeze_tasks(bool sig_
+ u64 elapsed_csecs64;
+ unsigned int elapsed_csecs;
+ bool wakeup = false;
++ bool timedout = false;
+
+ do_gettimeofday(&start);
+
+@@ -51,6 +52,8 @@ static int try_to_freeze_tasks(bool sig_
+
+ while (true) {
+ todo = 0;
++ if (time_after(jiffies, end_time))
++ timedout = true;
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ if (frozen(p) || !freezable(p))
+@@ -71,9 +74,13 @@ static int try_to_freeze_tasks(bool sig_
+ * try_to_stop() after schedule() in ptrace/signal
+ * stop sees TIF_FREEZE.
+ */
+- if (!task_is_stopped_or_traced(p) &&
+- !freezer_should_skip(p))
++ if (!task_is_stopped_or_traced(p) && !freezer_should_skip(p)) {
+ todo++;
++ if (timedout) {
++ printk(KERN_ERR "Task refusing to freeze:\n");
++ sched_show_task(p);
++ }
++ }
+ } while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+
+@@ -82,7 +89,7 @@ static int try_to_freeze_tasks(bool sig_
+ todo += wq_busy;
+ }
+
+- if (!todo || time_after(jiffies, end_time))
++ if (!todo || timedout)
+ break;
+
+ if (pm_wakeup_pending()) {
+diff -urNp linux-2.6.38.7/kernel/printk.c linux-2.6.38.7/kernel/printk.c
+--- linux-2.6.38.7/kernel/printk.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/printk.c 2011-04-28 19:34:15.000000000 -0400
+@@ -279,12 +279,17 @@ static int check_syslog_permissions(int
+ if (from_file && type != SYSLOG_ACTION_OPEN)
+ return 0;
+
++#ifdef CONFIG_GRKERNSEC_DMESG
++ if (grsec_enable_dmesg && !capable(CAP_SYSLOG) && !capable_nolog(CAP_SYS_ADMIN))
++ return -EPERM;
++#endif
++
+ if (syslog_action_restricted(type)) {
+ if (capable(CAP_SYSLOG))
+ return 0;
+ /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
+ if (capable(CAP_SYS_ADMIN)) {
+- WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN "
++ printk_once(KERN_WARNING "Attempt to access syslog with CAP_SYS_ADMIN "
+ "but no CAP_SYSLOG (deprecated).\n");
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/kernel/profile.c linux-2.6.38.7/kernel/profile.c
+--- linux-2.6.38.7/kernel/profile.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/profile.c 2011-04-28 19:57:25.000000000 -0400
+@@ -39,7 +39,7 @@ struct profile_hit {
+ /* Oprofile timer tick hook */
+ static int (*timer_hook)(struct pt_regs *) __read_mostly;
+
+-static atomic_t *prof_buffer;
++static atomic_unchecked_t *prof_buffer;
+ static unsigned long prof_len, prof_shift;
+
+ int prof_on __read_mostly;
+@@ -283,7 +283,7 @@ static void profile_flip_buffers(void)
+ hits[i].pc = 0;
+ continue;
+ }
+- atomic_add(hits[i].hits, &prof_buffer[hits[i].pc]);
++ atomic_add_unchecked(hits[i].hits, &prof_buffer[hits[i].pc]);
+ hits[i].hits = hits[i].pc = 0;
+ }
+ }
+@@ -346,9 +346,9 @@ void profile_hits(int type, void *__pc,
+ * Add the current hit(s) and flush the write-queue out
+ * to the global buffer:
+ */
+- atomic_add(nr_hits, &prof_buffer[pc]);
++ atomic_add_unchecked(nr_hits, &prof_buffer[pc]);
+ for (i = 0; i < NR_PROFILE_HIT; ++i) {
+- atomic_add(hits[i].hits, &prof_buffer[hits[i].pc]);
++ atomic_add_unchecked(hits[i].hits, &prof_buffer[hits[i].pc]);
+ hits[i].pc = hits[i].hits = 0;
+ }
+ out:
+@@ -426,7 +426,7 @@ void profile_hits(int type, void *__pc,
+ if (prof_on != type || !prof_buffer)
+ return;
+ pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift;
+- atomic_add(nr_hits, &prof_buffer[min(pc, prof_len - 1)]);
++ atomic_add_unchecked(nr_hits, &prof_buffer[min(pc, prof_len - 1)]);
+ }
+ #endif /* !CONFIG_SMP */
+ EXPORT_SYMBOL_GPL(profile_hits);
+@@ -517,7 +517,7 @@ read_profile(struct file *file, char __u
+ return -EFAULT;
+ buf++; p++; count--; read++;
+ }
+- pnt = (char *)prof_buffer + p - sizeof(atomic_t);
++ pnt = (char *)prof_buffer + p - sizeof(atomic_unchecked_t);
+ if (copy_to_user(buf, (void *)pnt, count))
+ return -EFAULT;
+ read += count;
+@@ -548,7 +548,7 @@ static ssize_t write_profile(struct file
+ }
+ #endif
+ profile_discard_flip_buffers();
+- memset(prof_buffer, 0, prof_len * sizeof(atomic_t));
++ memset(prof_buffer, 0, prof_len * sizeof(atomic_unchecked_t));
+ return count;
+ }
+
+diff -urNp linux-2.6.38.7/kernel/ptrace.c linux-2.6.38.7/kernel/ptrace.c
+--- linux-2.6.38.7/kernel/ptrace.c 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/kernel/ptrace.c 2011-05-22 23:06:04.000000000 -0400
+@@ -117,7 +117,8 @@ int ptrace_check_attach(struct task_stru
+ return ret;
+ }
+
+-int __ptrace_may_access(struct task_struct *task, unsigned int mode)
++static int __ptrace_may_access(struct task_struct *task, unsigned int mode,
++ unsigned int log)
+ {
+ const struct cred *cred = current_cred(), *tcred;
+
+@@ -141,7 +142,9 @@ int __ptrace_may_access(struct task_stru
+ cred->gid != tcred->egid ||
+ cred->gid != tcred->sgid ||
+ cred->gid != tcred->gid) &&
+- !capable(CAP_SYS_PTRACE)) {
++ ((!log && !capable_nolog(CAP_SYS_PTRACE)) ||
++ (log && !capable(CAP_SYS_PTRACE)))
++ ) {
+ rcu_read_unlock();
+ return -EPERM;
+ }
+@@ -149,7 +152,9 @@ int __ptrace_may_access(struct task_stru
+ smp_rmb();
+ if (task->mm)
+ dumpable = get_dumpable(task->mm);
+- if (!dumpable && !capable(CAP_SYS_PTRACE))
++ if (!dumpable &&
++ ((!log && !capable_nolog(CAP_SYS_PTRACE)) ||
++ (log && !capable(CAP_SYS_PTRACE))))
+ return -EPERM;
+
+ return security_ptrace_access_check(task, mode);
+@@ -159,7 +164,16 @@ bool ptrace_may_access(struct task_struc
+ {
+ int err;
+ task_lock(task);
+- err = __ptrace_may_access(task, mode);
++ err = __ptrace_may_access(task, mode, 0);
++ task_unlock(task);
++ return !err;
++}
++
++bool ptrace_may_access_log(struct task_struct *task, unsigned int mode)
++{
++ int err;
++ task_lock(task);
++ err = __ptrace_may_access(task, mode, 1);
+ task_unlock(task);
+ return !err;
+ }
+@@ -186,7 +200,7 @@ static int ptrace_attach(struct task_str
+ goto out;
+
+ task_lock(task);
+- retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
++ retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH, 1);
+ task_unlock(task);
+ if (retval)
+ goto unlock_creds;
+@@ -199,7 +213,7 @@ static int ptrace_attach(struct task_str
+ goto unlock_tasklist;
+
+ task->ptrace = PT_PTRACED;
+- if (capable(CAP_SYS_PTRACE))
++ if (capable_nolog(CAP_SYS_PTRACE))
+ task->ptrace |= PT_PTRACE_CAP;
+
+ __ptrace_link(task, current);
+@@ -359,6 +373,8 @@ int ptrace_readdata(struct task_struct *
+ {
+ int copied = 0;
+
++ pax_track_stack();
++
+ while (len > 0) {
+ char buf[128];
+ int this_len, retval;
+@@ -370,7 +386,7 @@ int ptrace_readdata(struct task_struct *
+ break;
+ return -EIO;
+ }
+- if (copy_to_user(dst, buf, retval))
++ if (retval > sizeof(buf) || copy_to_user(dst, buf, retval))
+ return -EFAULT;
+ copied += retval;
+ src += retval;
+@@ -384,6 +400,8 @@ int ptrace_writedata(struct task_struct
+ {
+ int copied = 0;
+
++ pax_track_stack();
++
+ while (len > 0) {
+ char buf[128];
+ int this_len, retval;
+@@ -566,9 +584,11 @@ int ptrace_request(struct task_struct *c
+ {
+ int ret = -EIO;
+ siginfo_t siginfo;
+- void __user *datavp = (void __user *) data;
++ void __user *datavp = (__force void __user *) data;
+ unsigned long __user *datalp = datavp;
+
++ pax_track_stack();
++
+ switch (request) {
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKDATA:
+@@ -714,14 +734,21 @@ SYSCALL_DEFINE4(ptrace, long, request, l
+ goto out;
+ }
+
++ if (gr_handle_ptrace(child, request)) {
++ ret = -EPERM;
++ goto out_put_task_struct;
++ }
++
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ /*
+ * Some architectures need to do book-keeping after
+ * a ptrace attach.
+ */
+- if (!ret)
++ if (!ret) {
+ arch_ptrace_attach(child);
++ gr_audit_ptrace(child);
++ }
+ goto out_put_task_struct;
+ }
+
+@@ -746,7 +773,7 @@ int generic_ptrace_peekdata(struct task_
+ copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
+ if (copied != sizeof(tmp))
+ return -EIO;
+- return put_user(tmp, (unsigned long __user *)data);
++ return put_user(tmp, (__force unsigned long __user *)data);
+ }
+
+ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
+@@ -769,6 +796,8 @@ int compat_ptrace_request(struct task_st
+ siginfo_t siginfo;
+ int ret;
+
++ pax_track_stack();
++
+ switch (request) {
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKDATA:
+@@ -856,14 +885,21 @@ asmlinkage long compat_sys_ptrace(compat
+ goto out;
+ }
+
++ if (gr_handle_ptrace(child, request)) {
++ ret = -EPERM;
++ goto out_put_task_struct;
++ }
++
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ /*
+ * Some architectures need to do book-keeping after
+ * a ptrace attach.
+ */
+- if (!ret)
++ if (!ret) {
+ arch_ptrace_attach(child);
++ gr_audit_ptrace(child);
++ }
+ goto out_put_task_struct;
+ }
+
+diff -urNp linux-2.6.38.7/kernel/rcutorture.c linux-2.6.38.7/kernel/rcutorture.c
+--- linux-2.6.38.7/kernel/rcutorture.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/rcutorture.c 2011-04-28 19:57:25.000000000 -0400
+@@ -139,12 +139,12 @@ static DEFINE_PER_CPU(long [RCU_TORTURE_
+ { 0 };
+ static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) =
+ { 0 };
+-static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
+-static atomic_t n_rcu_torture_alloc;
+-static atomic_t n_rcu_torture_alloc_fail;
+-static atomic_t n_rcu_torture_free;
+-static atomic_t n_rcu_torture_mberror;
+-static atomic_t n_rcu_torture_error;
++static atomic_unchecked_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
++static atomic_unchecked_t n_rcu_torture_alloc;
++static atomic_unchecked_t n_rcu_torture_alloc_fail;
++static atomic_unchecked_t n_rcu_torture_free;
++static atomic_unchecked_t n_rcu_torture_mberror;
++static atomic_unchecked_t n_rcu_torture_error;
+ static long n_rcu_torture_boost_ktrerror;
+ static long n_rcu_torture_boost_rterror;
+ static long n_rcu_torture_boost_allocerror;
+@@ -226,11 +226,11 @@ rcu_torture_alloc(void)
+
+ spin_lock_bh(&rcu_torture_lock);
+ if (list_empty(&rcu_torture_freelist)) {
+- atomic_inc(&n_rcu_torture_alloc_fail);
++ atomic_inc_unchecked(&n_rcu_torture_alloc_fail);
+ spin_unlock_bh(&rcu_torture_lock);
+ return NULL;
+ }
+- atomic_inc(&n_rcu_torture_alloc);
++ atomic_inc_unchecked(&n_rcu_torture_alloc);
+ p = rcu_torture_freelist.next;
+ list_del_init(p);
+ spin_unlock_bh(&rcu_torture_lock);
+@@ -243,7 +243,7 @@ rcu_torture_alloc(void)
+ static void
+ rcu_torture_free(struct rcu_torture *p)
+ {
+- atomic_inc(&n_rcu_torture_free);
++ atomic_inc_unchecked(&n_rcu_torture_free);
+ spin_lock_bh(&rcu_torture_lock);
+ list_add_tail(&p->rtort_free, &rcu_torture_freelist);
+ spin_unlock_bh(&rcu_torture_lock);
+@@ -363,7 +363,7 @@ rcu_torture_cb(struct rcu_head *p)
+ i = rp->rtort_pipe_count;
+ if (i > RCU_TORTURE_PIPE_LEN)
+ i = RCU_TORTURE_PIPE_LEN;
+- atomic_inc(&rcu_torture_wcount[i]);
++ atomic_inc_unchecked(&rcu_torture_wcount[i]);
+ if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
+ rp->rtort_mbtest = 0;
+ rcu_torture_free(rp);
+@@ -410,7 +410,7 @@ static void rcu_sync_torture_deferred_fr
+ i = rp->rtort_pipe_count;
+ if (i > RCU_TORTURE_PIPE_LEN)
+ i = RCU_TORTURE_PIPE_LEN;
+- atomic_inc(&rcu_torture_wcount[i]);
++ atomic_inc_unchecked(&rcu_torture_wcount[i]);
+ if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
+ rp->rtort_mbtest = 0;
+ list_del(&rp->rtort_free);
+@@ -883,7 +883,7 @@ rcu_torture_writer(void *arg)
+ i = old_rp->rtort_pipe_count;
+ if (i > RCU_TORTURE_PIPE_LEN)
+ i = RCU_TORTURE_PIPE_LEN;
+- atomic_inc(&rcu_torture_wcount[i]);
++ atomic_inc_unchecked(&rcu_torture_wcount[i]);
+ old_rp->rtort_pipe_count++;
+ cur_ops->deferred_free(old_rp);
+ }
+@@ -952,7 +952,7 @@ static void rcu_torture_timer(unsigned l
+ return;
+ }
+ if (p->rtort_mbtest == 0)
+- atomic_inc(&n_rcu_torture_mberror);
++ atomic_inc_unchecked(&n_rcu_torture_mberror);
+ spin_lock(&rand_lock);
+ cur_ops->read_delay(&rand);
+ n_rcu_torture_timers++;
+@@ -1014,7 +1014,7 @@ rcu_torture_reader(void *arg)
+ continue;
+ }
+ if (p->rtort_mbtest == 0)
+- atomic_inc(&n_rcu_torture_mberror);
++ atomic_inc_unchecked(&n_rcu_torture_mberror);
+ cur_ops->read_delay(&rand);
+ preempt_disable();
+ pipe_count = p->rtort_pipe_count;
+@@ -1073,10 +1073,10 @@ rcu_torture_printk(char *page)
+ rcu_torture_current,
+ rcu_torture_current_version,
+ list_empty(&rcu_torture_freelist),
+- atomic_read(&n_rcu_torture_alloc),
+- atomic_read(&n_rcu_torture_alloc_fail),
+- atomic_read(&n_rcu_torture_free),
+- atomic_read(&n_rcu_torture_mberror),
++ atomic_read_unchecked(&n_rcu_torture_alloc),
++ atomic_read_unchecked(&n_rcu_torture_alloc_fail),
++ atomic_read_unchecked(&n_rcu_torture_free),
++ atomic_read_unchecked(&n_rcu_torture_mberror),
+ n_rcu_torture_boost_ktrerror,
+ n_rcu_torture_boost_rterror,
+ n_rcu_torture_boost_allocerror,
+@@ -1084,7 +1084,7 @@ rcu_torture_printk(char *page)
+ n_rcu_torture_boost_failure,
+ n_rcu_torture_boosts,
+ n_rcu_torture_timers);
+- if (atomic_read(&n_rcu_torture_mberror) != 0 ||
++ if (atomic_read_unchecked(&n_rcu_torture_mberror) != 0 ||
+ n_rcu_torture_boost_ktrerror != 0 ||
+ n_rcu_torture_boost_rterror != 0 ||
+ n_rcu_torture_boost_allocerror != 0 ||
+@@ -1094,7 +1094,7 @@ rcu_torture_printk(char *page)
+ cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
+ if (i > 1) {
+ cnt += sprintf(&page[cnt], "!!! ");
+- atomic_inc(&n_rcu_torture_error);
++ atomic_inc_unchecked(&n_rcu_torture_error);
+ WARN_ON_ONCE(1);
+ }
+ cnt += sprintf(&page[cnt], "Reader Pipe: ");
+@@ -1108,7 +1108,7 @@ rcu_torture_printk(char *page)
+ cnt += sprintf(&page[cnt], "Free-Block Circulation: ");
+ for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
+ cnt += sprintf(&page[cnt], " %d",
+- atomic_read(&rcu_torture_wcount[i]));
++ atomic_read_unchecked(&rcu_torture_wcount[i]));
+ }
+ cnt += sprintf(&page[cnt], "\n");
+ if (cur_ops->stats)
+@@ -1416,7 +1416,7 @@ rcu_torture_cleanup(void)
+
+ if (cur_ops->cleanup)
+ cur_ops->cleanup();
+- if (atomic_read(&n_rcu_torture_error))
++ if (atomic_read_unchecked(&n_rcu_torture_error))
+ rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
+ else
+ rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
+@@ -1480,11 +1480,11 @@ rcu_torture_init(void)
+
+ rcu_torture_current = NULL;
+ rcu_torture_current_version = 0;
+- atomic_set(&n_rcu_torture_alloc, 0);
+- atomic_set(&n_rcu_torture_alloc_fail, 0);
+- atomic_set(&n_rcu_torture_free, 0);
+- atomic_set(&n_rcu_torture_mberror, 0);
+- atomic_set(&n_rcu_torture_error, 0);
++ atomic_set_unchecked(&n_rcu_torture_alloc, 0);
++ atomic_set_unchecked(&n_rcu_torture_alloc_fail, 0);
++ atomic_set_unchecked(&n_rcu_torture_free, 0);
++ atomic_set_unchecked(&n_rcu_torture_mberror, 0);
++ atomic_set_unchecked(&n_rcu_torture_error, 0);
+ n_rcu_torture_boost_ktrerror = 0;
+ n_rcu_torture_boost_rterror = 0;
+ n_rcu_torture_boost_allocerror = 0;
+@@ -1492,7 +1492,7 @@ rcu_torture_init(void)
+ n_rcu_torture_boost_failure = 0;
+ n_rcu_torture_boosts = 0;
+ for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
+- atomic_set(&rcu_torture_wcount[i], 0);
++ atomic_set_unchecked(&rcu_torture_wcount[i], 0);
+ for_each_possible_cpu(cpu) {
+ for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
+ per_cpu(rcu_torture_count, cpu)[i] = 0;
+diff -urNp linux-2.6.38.7/kernel/rcutree.c linux-2.6.38.7/kernel/rcutree.c
+--- linux-2.6.38.7/kernel/rcutree.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/rcutree.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1389,7 +1389,7 @@ __rcu_process_callbacks(struct rcu_state
+ /*
+ * Do softirq processing for the current CPU.
+ */
+-static void rcu_process_callbacks(struct softirq_action *unused)
++static void rcu_process_callbacks(void)
+ {
+ /*
+ * Memory references from any prior RCU read-side critical sections
+diff -urNp linux-2.6.38.7/kernel/rcutree_plugin.h linux-2.6.38.7/kernel/rcutree_plugin.h
+--- linux-2.6.38.7/kernel/rcutree_plugin.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/rcutree_plugin.h 2011-04-28 19:57:25.000000000 -0400
+@@ -730,7 +730,7 @@ void synchronize_rcu_expedited(void)
+
+ /* Clean up and exit. */
+ smp_mb(); /* ensure expedited GP seen before counter increment. */
+- ACCESS_ONCE(sync_rcu_preempt_exp_count)++;
++ ACCESS_ONCE_RW(sync_rcu_preempt_exp_count)++;
+ unlock_mb_ret:
+ mutex_unlock(&sync_rcu_preempt_exp_mutex);
+ mb_ret:
+@@ -1025,8 +1025,8 @@ EXPORT_SYMBOL_GPL(synchronize_sched_expe
+
+ #else /* #ifndef CONFIG_SMP */
+
+-static atomic_t sync_sched_expedited_started = ATOMIC_INIT(0);
+-static atomic_t sync_sched_expedited_done = ATOMIC_INIT(0);
++static atomic_unchecked_t sync_sched_expedited_started = ATOMIC_INIT(0);
++static atomic_unchecked_t sync_sched_expedited_done = ATOMIC_INIT(0);
+
+ static int synchronize_sched_expedited_cpu_stop(void *data)
+ {
+@@ -1081,7 +1081,7 @@ void synchronize_sched_expedited(void)
+ int firstsnap, s, snap, trycount = 0;
+
+ /* Note that atomic_inc_return() implies full memory barrier. */
+- firstsnap = snap = atomic_inc_return(&sync_sched_expedited_started);
++ firstsnap = snap = atomic_inc_return_unchecked(&sync_sched_expedited_started);
+ get_online_cpus();
+
+ /*
+@@ -1102,7 +1102,7 @@ void synchronize_sched_expedited(void)
+ }
+
+ /* Check to see if someone else did our work for us. */
+- s = atomic_read(&sync_sched_expedited_done);
++ s = atomic_read_unchecked(&sync_sched_expedited_done);
+ if (UINT_CMP_GE((unsigned)s, (unsigned)firstsnap)) {
+ smp_mb(); /* ensure test happens before caller kfree */
+ return;
+@@ -1117,7 +1117,7 @@ void synchronize_sched_expedited(void)
+ * grace period works for us.
+ */
+ get_online_cpus();
+- snap = atomic_read(&sync_sched_expedited_started) - 1;
++ snap = atomic_read_unchecked(&sync_sched_expedited_started) - 1;
+ smp_mb(); /* ensure read is before try_stop_cpus(). */
+ }
+
+@@ -1128,12 +1128,12 @@ void synchronize_sched_expedited(void)
+ * than we did beat us to the punch.
+ */
+ do {
+- s = atomic_read(&sync_sched_expedited_done);
++ s = atomic_read_unchecked(&sync_sched_expedited_done);
+ if (UINT_CMP_GE((unsigned)s, (unsigned)snap)) {
+ smp_mb(); /* ensure test happens before caller kfree */
+ break;
+ }
+- } while (atomic_cmpxchg(&sync_sched_expedited_done, s, snap) != s);
++ } while (atomic_cmpxchg_unchecked(&sync_sched_expedited_done, s, snap) != s);
+
+ put_online_cpus();
+ }
+diff -urNp linux-2.6.38.7/kernel/relay.c linux-2.6.38.7/kernel/relay.c
+--- linux-2.6.38.7/kernel/relay.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/relay.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1236,6 +1236,8 @@ static ssize_t subbuf_splice_actor(struc
+ };
+ ssize_t ret;
+
++ pax_track_stack();
++
+ if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
+ return 0;
+ if (splice_grow_spd(pipe, &spd))
+diff -urNp linux-2.6.38.7/kernel/resource.c linux-2.6.38.7/kernel/resource.c
+--- linux-2.6.38.7/kernel/resource.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/resource.c 2011-04-28 19:34:15.000000000 -0400
+@@ -133,8 +133,18 @@ static const struct file_operations proc
+
+ static int __init ioresources_init(void)
+ {
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ proc_create("ioports", S_IRUSR, NULL, &proc_ioports_operations);
++ proc_create("iomem", S_IRUSR, NULL, &proc_iomem_operations);
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ proc_create("ioports", S_IRUSR | S_IRGRP, NULL, &proc_ioports_operations);
++ proc_create("iomem", S_IRUSR | S_IRGRP, NULL, &proc_iomem_operations);
++#endif
++#else
+ proc_create("ioports", 0, NULL, &proc_ioports_operations);
+ proc_create("iomem", 0, NULL, &proc_iomem_operations);
++#endif
+ return 0;
+ }
+ __initcall(ioresources_init);
+diff -urNp linux-2.6.38.7/kernel/rtmutex.c linux-2.6.38.7/kernel/rtmutex.c
+--- linux-2.6.38.7/kernel/rtmutex.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/rtmutex.c 2011-04-28 19:34:15.000000000 -0400
+@@ -511,7 +511,7 @@ static void wakeup_next_waiter(struct rt
+ */
+ raw_spin_lock_irqsave(&pendowner->pi_lock, flags);
+
+- WARN_ON(!pendowner->pi_blocked_on);
++ BUG_ON(!pendowner->pi_blocked_on);
+ WARN_ON(pendowner->pi_blocked_on != waiter);
+ WARN_ON(pendowner->pi_blocked_on->lock != lock);
+
+diff -urNp linux-2.6.38.7/kernel/rtmutex-tester.c linux-2.6.38.7/kernel/rtmutex-tester.c
+--- linux-2.6.38.7/kernel/rtmutex-tester.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/rtmutex-tester.c 2011-04-28 19:57:25.000000000 -0400
+@@ -21,7 +21,7 @@
+ #define MAX_RT_TEST_MUTEXES 8
+
+ static spinlock_t rttest_lock;
+-static atomic_t rttest_event;
++static atomic_unchecked_t rttest_event;
+
+ struct test_thread_data {
+ int opcode;
+@@ -64,7 +64,7 @@ static int handle_op(struct test_thread_
+
+ case RTTEST_LOCKCONT:
+ td->mutexes[td->opdata] = 1;
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ return 0;
+
+ case RTTEST_RESET:
+@@ -84,7 +84,7 @@ static int handle_op(struct test_thread_
+ return 0;
+
+ case RTTEST_RESETEVENT:
+- atomic_set(&rttest_event, 0);
++ atomic_set_unchecked(&rttest_event, 0);
+ return 0;
+
+ default:
+@@ -101,9 +101,9 @@ static int handle_op(struct test_thread_
+ return ret;
+
+ td->mutexes[id] = 1;
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ rt_mutex_lock(&mutexes[id]);
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ td->mutexes[id] = 4;
+ return 0;
+
+@@ -114,9 +114,9 @@ static int handle_op(struct test_thread_
+ return ret;
+
+ td->mutexes[id] = 1;
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ ret = rt_mutex_lock_interruptible(&mutexes[id], 0);
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ td->mutexes[id] = ret ? 0 : 4;
+ return ret ? -EINTR : 0;
+
+@@ -125,9 +125,9 @@ static int handle_op(struct test_thread_
+ if (id < 0 || id >= MAX_RT_TEST_MUTEXES || td->mutexes[id] != 4)
+ return ret;
+
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ rt_mutex_unlock(&mutexes[id]);
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ td->mutexes[id] = 0;
+ return 0;
+
+@@ -193,7 +193,7 @@ void schedule_rt_mutex_test(struct rt_mu
+ break;
+
+ td->mutexes[dat] = 2;
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ break;
+
+ case RTTEST_LOCKBKL:
+@@ -214,7 +214,7 @@ void schedule_rt_mutex_test(struct rt_mu
+ return;
+
+ td->mutexes[dat] = 3;
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ break;
+
+ case RTTEST_LOCKNOWAIT:
+@@ -226,7 +226,7 @@ void schedule_rt_mutex_test(struct rt_mu
+ return;
+
+ td->mutexes[dat] = 1;
+- td->event = atomic_add_return(1, &rttest_event);
++ td->event = atomic_add_return_unchecked(1, &rttest_event);
+ return;
+
+ case RTTEST_LOCKBKL:
+diff -urNp linux-2.6.38.7/kernel/sched_autogroup.c linux-2.6.38.7/kernel/sched_autogroup.c
+--- linux-2.6.38.7/kernel/sched_autogroup.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/sched_autogroup.c 2011-04-28 19:57:25.000000000 -0400
+@@ -7,7 +7,7 @@
+
+ unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
+ static struct autogroup autogroup_default;
+-static atomic_t autogroup_seq_nr;
++static atomic_unchecked_t autogroup_seq_nr;
+
+ static void __init autogroup_init(struct task_struct *init_task)
+ {
+@@ -79,7 +79,7 @@ static inline struct autogroup *autogrou
+
+ kref_init(&ag->kref);
+ init_rwsem(&ag->lock);
+- ag->id = atomic_inc_return(&autogroup_seq_nr);
++ ag->id = atomic_inc_return_unchecked(&autogroup_seq_nr);
+ ag->tg = tg;
+ #ifdef CONFIG_RT_GROUP_SCHED
+ /*
+diff -urNp linux-2.6.38.7/kernel/sched.c linux-2.6.38.7/kernel/sched.c
+--- linux-2.6.38.7/kernel/sched.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/kernel/sched.c 2011-05-22 23:03:34.000000000 -0400
+@@ -3938,6 +3938,8 @@ asmlinkage void __sched schedule(void)
+ struct rq *rq;
+ int cpu;
+
++ pax_track_stack();
++
+ need_resched:
+ preempt_disable();
+ cpu = smp_processor_id();
+@@ -4024,7 +4026,7 @@ EXPORT_SYMBOL(schedule);
+ * Look out! "owner" is an entirely speculative pointer
+ * access and not reliable.
+ */
+-int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
++int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
+ {
+ unsigned int cpu;
+ struct rq *rq;
+@@ -4038,10 +4040,10 @@ int mutex_spin_on_owner(struct mutex *lo
+ * DEBUG_PAGEALLOC could have unmapped it if
+ * the mutex owner just released it and exited.
+ */
+- if (probe_kernel_address(&owner->cpu, cpu))
++ if (probe_kernel_address(&task_thread_info(owner)->cpu, cpu))
+ return 0;
+ #else
+- cpu = owner->cpu;
++ cpu = task_thread_info(owner)->cpu;
+ #endif
+
+ /*
+@@ -4078,7 +4080,7 @@ int mutex_spin_on_owner(struct mutex *lo
+ /*
+ * Is that owner really running on that cpu?
+ */
+- if (task_thread_info(rq->curr) != owner || need_resched())
++ if (rq->curr != owner || need_resched())
+ return 0;
+
+ arch_mutex_cpu_relax();
+@@ -4638,6 +4640,8 @@ int can_nice(const struct task_struct *p
+ /* convert nice value [19,-20] to rlimit style value [1,40] */
+ int nice_rlim = 20 - nice;
+
++ gr_learn_resource(p, RLIMIT_NICE, nice_rlim, 1);
++
+ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
+ capable(CAP_SYS_NICE));
+ }
+@@ -4671,7 +4675,8 @@ SYSCALL_DEFINE1(nice, int, increment)
+ if (nice > 19)
+ nice = 19;
+
+- if (increment < 0 && !can_nice(current, nice))
++ if (increment < 0 && (!can_nice(current, nice) ||
++ gr_handle_chroot_nice()))
+ return -EPERM;
+
+ retval = security_task_setnice(current, nice);
+@@ -4814,6 +4819,7 @@ recheck:
+ unsigned long rlim_rtprio =
+ task_rlimit(p, RLIMIT_RTPRIO);
+
++ gr_learn_resource(p, RLIMIT_RTPRIO, param->sched_priority, 1);
+ /* can't set/change the rt policy */
+ if (policy != p->policy && !rlim_rtprio)
+ return -EPERM;
+@@ -6942,7 +6948,7 @@ static void init_sched_groups_power(int
+ long power;
+ int weight;
+
+- WARN_ON(!sd || !sd->groups);
++ BUG_ON(!sd || !sd->groups);
+
+ if (cpu != group_first_cpu(sd->groups))
+ return;
+diff -urNp linux-2.6.38.7/kernel/sched_fair.c linux-2.6.38.7/kernel/sched_fair.c
+--- linux-2.6.38.7/kernel/sched_fair.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/kernel/sched_fair.c 2011-04-28 19:34:15.000000000 -0400
+@@ -3957,7 +3957,7 @@ static void nohz_idle_balance(int this_c
+ * run_rebalance_domains is triggered when needed from the scheduler tick.
+ * Also triggered for nohz idle balancing (with nohz_balancing_kick set).
+ */
+-static void run_rebalance_domains(struct softirq_action *h)
++static void run_rebalance_domains(void)
+ {
+ int this_cpu = smp_processor_id();
+ struct rq *this_rq = cpu_rq(this_cpu);
+diff -urNp linux-2.6.38.7/kernel/signal.c linux-2.6.38.7/kernel/signal.c
+--- linux-2.6.38.7/kernel/signal.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/kernel/signal.c 2011-05-22 23:03:34.000000000 -0400
+@@ -45,12 +45,12 @@ static struct kmem_cache *sigqueue_cache
+
+ int print_fatal_signals __read_mostly;
+
+-static void __user *sig_handler(struct task_struct *t, int sig)
++static __sighandler_t sig_handler(struct task_struct *t, int sig)
+ {
+ return t->sighand->action[sig - 1].sa.sa_handler;
+ }
+
+-static int sig_handler_ignored(void __user *handler, int sig)
++static int sig_handler_ignored(__sighandler_t handler, int sig)
+ {
+ /* Is it explicitly or implicitly ignored? */
+ return handler == SIG_IGN ||
+@@ -60,7 +60,7 @@ static int sig_handler_ignored(void __us
+ static int sig_task_ignored(struct task_struct *t, int sig,
+ int from_ancestor_ns)
+ {
+- void __user *handler;
++ __sighandler_t handler;
+
+ handler = sig_handler(t, sig);
+
+@@ -243,6 +243,9 @@ __sigqueue_alloc(int sig, struct task_st
+ atomic_inc(&user->sigpending);
+ rcu_read_unlock();
+
++ if (!override_rlimit)
++ gr_learn_resource(t, RLIMIT_SIGPENDING, atomic_read(&user->sigpending), 1);
++
+ if (override_rlimit ||
+ atomic_read(&user->sigpending) <=
+ task_rlimit(t, RLIMIT_SIGPENDING)) {
+@@ -367,7 +370,7 @@ flush_signal_handlers(struct task_struct
+
+ int unhandled_signal(struct task_struct *tsk, int sig)
+ {
+- void __user *handler = tsk->sighand->action[sig-1].sa.sa_handler;
++ __sighandler_t handler = tsk->sighand->action[sig-1].sa.sa_handler;
+ if (is_global_init(tsk))
+ return 1;
+ if (handler != SIG_IGN && handler != SIG_DFL)
+@@ -678,6 +681,9 @@ static int check_kill_permission(int sig
+ }
+ }
+
++ if (gr_handle_signal(t, sig))
++ return -EPERM;
++
+ return security_task_kill(t, info, sig, 0);
+ }
+
+@@ -1025,7 +1031,7 @@ __group_send_sig_info(int sig, struct si
+ return send_signal(sig, info, p, 1);
+ }
+
+-static int
++int
+ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
+ {
+ return send_signal(sig, info, t, 0);
+@@ -1062,6 +1068,7 @@ force_sig_info(int sig, struct siginfo *
+ unsigned long int flags;
+ int ret, blocked, ignored;
+ struct k_sigaction *action;
++ int is_unhandled = 0;
+
+ spin_lock_irqsave(&t->sighand->siglock, flags);
+ action = &t->sighand->action[sig-1];
+@@ -1076,9 +1083,18 @@ force_sig_info(int sig, struct siginfo *
+ }
+ if (action->sa.sa_handler == SIG_DFL)
+ t->signal->flags &= ~SIGNAL_UNKILLABLE;
++ if (action->sa.sa_handler == SIG_IGN || action->sa.sa_handler == SIG_DFL)
++ is_unhandled = 1;
+ ret = specific_send_sig_info(sig, info, t);
+ spin_unlock_irqrestore(&t->sighand->siglock, flags);
+
++ /* only deal with unhandled signals, java etc trigger SIGSEGV during
++ normal operation */
++ if (is_unhandled) {
++ gr_log_signal(sig, !is_si_special(info) ? info->si_addr : NULL, t);
++ gr_handle_crash(t, sig);
++ }
++
+ return ret;
+ }
+
+@@ -1137,8 +1153,11 @@ int group_send_sig_info(int sig, struct
+ ret = check_kill_permission(sig, info, p);
+ rcu_read_unlock();
+
+- if (!ret && sig)
++ if (!ret && sig) {
+ ret = do_send_sig_info(sig, info, p, true);
++ if (!ret)
++ gr_log_signal(sig, !is_si_special(info) ? info->si_addr : NULL, p);
++ }
+
+ return ret;
+ }
+@@ -1704,6 +1723,8 @@ void ptrace_notify(int exit_code)
+ {
+ siginfo_t info;
+
++ pax_track_stack();
++
+ BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
+
+ memset(&info, 0, sizeof info);
+diff -urNp linux-2.6.38.7/kernel/smp.c linux-2.6.38.7/kernel/smp.c
+--- linux-2.6.38.7/kernel/smp.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/kernel/smp.c 2011-04-28 19:34:15.000000000 -0400
+@@ -583,22 +583,22 @@ int smp_call_function(smp_call_func_t fu
+ }
+ EXPORT_SYMBOL(smp_call_function);
+
+-void ipi_call_lock(void)
++void ipi_call_lock(void) __acquires(call_function.lock)
+ {
+ raw_spin_lock(&call_function.lock);
+ }
+
+-void ipi_call_unlock(void)
++void ipi_call_unlock(void) __releases(call_function.lock)
+ {
+ raw_spin_unlock(&call_function.lock);
+ }
+
+-void ipi_call_lock_irq(void)
++void ipi_call_lock_irq(void) __acquires(call_function.lock)
+ {
+ raw_spin_lock_irq(&call_function.lock);
+ }
+
+-void ipi_call_unlock_irq(void)
++void ipi_call_unlock_irq(void) __releases(call_function.lock)
+ {
+ raw_spin_unlock_irq(&call_function.lock);
+ }
+diff -urNp linux-2.6.38.7/kernel/softirq.c linux-2.6.38.7/kernel/softirq.c
+--- linux-2.6.38.7/kernel/softirq.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/softirq.c 2011-04-28 19:34:15.000000000 -0400
+@@ -56,7 +56,7 @@ static struct softirq_action softirq_vec
+
+ static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
+
+-char *softirq_to_name[NR_SOFTIRQS] = {
++const char * const softirq_to_name[NR_SOFTIRQS] = {
+ "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
+ "TASKLET", "SCHED", "HRTIMER", "RCU"
+ };
+@@ -206,7 +206,7 @@ EXPORT_SYMBOL(local_bh_enable_ip);
+
+ asmlinkage void __do_softirq(void)
+ {
+- struct softirq_action *h;
++ const struct softirq_action *h;
+ __u32 pending;
+ int max_restart = MAX_SOFTIRQ_RESTART;
+ int cpu;
+@@ -235,7 +235,7 @@ restart:
+ kstat_incr_softirqs_this_cpu(vec_nr);
+
+ trace_softirq_entry(vec_nr);
+- h->action(h);
++ h->action();
+ trace_softirq_exit(vec_nr);
+ if (unlikely(prev_count != preempt_count())) {
+ printk(KERN_ERR "huh, entered softirq %u %s %p"
+@@ -365,7 +365,7 @@ void raise_softirq(unsigned int nr)
+ local_irq_restore(flags);
+ }
+
+-void open_softirq(int nr, void (*action)(struct softirq_action *))
++void open_softirq(int nr, void (*action)(void))
+ {
+ softirq_vec[nr].action = action;
+ }
+@@ -421,7 +421,7 @@ void __tasklet_hi_schedule_first(struct
+
+ EXPORT_SYMBOL(__tasklet_hi_schedule_first);
+
+-static void tasklet_action(struct softirq_action *a)
++static void tasklet_action(void)
+ {
+ struct tasklet_struct *list;
+
+@@ -456,7 +456,7 @@ static void tasklet_action(struct softir
+ }
+ }
+
+-static void tasklet_hi_action(struct softirq_action *a)
++static void tasklet_hi_action(void)
+ {
+ struct tasklet_struct *list;
+
+diff -urNp linux-2.6.38.7/kernel/sys.c linux-2.6.38.7/kernel/sys.c
+--- linux-2.6.38.7/kernel/sys.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/sys.c 2011-04-28 19:34:15.000000000 -0400
+@@ -136,6 +136,12 @@ static int set_one_prio(struct task_stru
+ error = -EACCES;
+ goto out;
+ }
++
++ if (gr_handle_chroot_setpriority(p, niceval)) {
++ error = -EACCES;
++ goto out;
++ }
++
+ no_nice = security_task_setnice(p, niceval);
+ if (no_nice) {
+ error = no_nice;
+@@ -517,6 +523,9 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, g
+ goto error;
+ }
+
++ if (gr_check_group_change(new->gid, new->egid, -1))
++ goto error;
++
+ if (rgid != (gid_t) -1 ||
+ (egid != (gid_t) -1 && egid != old->gid))
+ new->sgid = new->egid;
+@@ -546,6 +555,10 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
+ old = current_cred();
+
+ retval = -EPERM;
++
++ if (gr_check_group_change(gid, gid, gid))
++ goto error;
++
+ if (capable(CAP_SETGID))
+ new->gid = new->egid = new->sgid = new->fsgid = gid;
+ else if (gid == old->gid || gid == old->sgid)
+@@ -626,6 +639,9 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, u
+ goto error;
+ }
+
++ if (gr_check_user_change(new->uid, new->euid, -1))
++ goto error;
++
+ if (new->uid != old->uid) {
+ retval = set_user(new);
+ if (retval < 0)
+@@ -670,6 +686,12 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
+ old = current_cred();
+
+ retval = -EPERM;
++
++ if (gr_check_crash_uid(uid))
++ goto error;
++ if (gr_check_user_change(uid, uid, uid))
++ goto error;
++
+ if (capable(CAP_SETUID)) {
+ new->suid = new->uid = uid;
+ if (uid != old->uid) {
+@@ -724,6 +746,9 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid,
+ goto error;
+ }
+
++ if (gr_check_user_change(ruid, euid, -1))
++ goto error;
++
+ if (ruid != (uid_t) -1) {
+ new->uid = ruid;
+ if (ruid != old->uid) {
+@@ -788,6 +813,9 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid,
+ goto error;
+ }
+
++ if (gr_check_group_change(rgid, egid, -1))
++ goto error;
++
+ if (rgid != (gid_t) -1)
+ new->gid = rgid;
+ if (egid != (gid_t) -1)
+@@ -834,6 +862,9 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
+ old = current_cred();
+ old_fsuid = old->fsuid;
+
++ if (gr_check_user_change(-1, -1, uid))
++ goto error;
++
+ if (uid == old->uid || uid == old->euid ||
+ uid == old->suid || uid == old->fsuid ||
+ capable(CAP_SETUID)) {
+@@ -844,6 +875,7 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
+ }
+ }
+
++error:
+ abort_creds(new);
+ return old_fsuid;
+
+@@ -870,12 +902,16 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
+ if (gid == old->gid || gid == old->egid ||
+ gid == old->sgid || gid == old->fsgid ||
+ capable(CAP_SETGID)) {
++ if (gr_check_group_change(-1, -1, gid))
++ goto error;
++
+ if (gid != old_fsgid) {
+ new->fsgid = gid;
+ goto change_okay;
+ }
+ }
+
++error:
+ abort_creds(new);
+ return old_fsgid;
+
+@@ -1616,7 +1652,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
+ error = get_dumpable(me->mm);
+ break;
+ case PR_SET_DUMPABLE:
+- if (arg2 < 0 || arg2 > 1) {
++ if (arg2 > 1) {
+ error = -EINVAL;
+ break;
+ }
+diff -urNp linux-2.6.38.7/kernel/sysctl.c linux-2.6.38.7/kernel/sysctl.c
+--- linux-2.6.38.7/kernel/sysctl.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/kernel/sysctl.c 2011-04-28 19:34:15.000000000 -0400
+@@ -84,6 +84,13 @@
+
+
+ #if defined(CONFIG_SYSCTL)
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++extern __u32 gr_handle_sysctl(const ctl_table *table, const int op);
++extern int gr_handle_sysctl_mod(const char *dirname, const char *name,
++ const int op);
++extern int gr_handle_chroot_sysctl(const int op);
+
+ /* External variables not in a header file. */
+ extern int sysctl_overcommit_memory;
+@@ -195,6 +202,7 @@ static int sysrq_sysctl_handler(ctl_tabl
+ }
+
+ #endif
++extern struct ctl_table grsecurity_table[];
+
+ static struct ctl_table root_table[];
+ static struct ctl_table_root sysctl_table_root;
+@@ -224,6 +232,20 @@ extern struct ctl_table epoll_table[];
+ int sysctl_legacy_va_layout;
+ #endif
+
++#ifdef CONFIG_PAX_SOFTMODE
++static ctl_table pax_table[] = {
++ {
++ .procname = "softmode",
++ .data = &pax_softmode,
++ .maxlen = sizeof(unsigned int),
++ .mode = 0600,
++ .proc_handler = &proc_dointvec,
++ },
++
++ { }
++};
++#endif
++
+ /* The default sysctl tables: */
+
+ static struct ctl_table root_table[] = {
+@@ -270,6 +292,22 @@ static int max_extfrag_threshold = 1000;
+ #endif
+
+ static struct ctl_table kern_table[] = {
++#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_ROFS)
++ {
++ .procname = "grsecurity",
++ .mode = 0500,
++ .child = grsecurity_table,
++ },
++#endif
++
++#ifdef CONFIG_PAX_SOFTMODE
++ {
++ .procname = "pax",
++ .mode = 0500,
++ .child = pax_table,
++ },
++#endif
++
+ {
+ .procname = "sched_child_runs_first",
+ .data = &sysctl_sched_child_runs_first,
+@@ -551,7 +589,7 @@ static struct ctl_table kern_table[] = {
+ .data = &modprobe_path,
+ .maxlen = KMOD_PATH_LEN,
+ .mode = 0644,
+- .proc_handler = proc_dostring,
++ .proc_handler = proc_dostring_modpriv,
+ },
+ {
+ .procname = "modules_disabled",
+@@ -713,16 +751,20 @@ static struct ctl_table kern_table[] = {
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
++#endif
+ {
+ .procname = "kptr_restrict",
+ .data = &kptr_restrict,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dmesg_restrict,
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ .extra1 = &two,
++#else
+ .extra1 = &zero,
++#endif
+ .extra2 = &two,
+ },
+-#endif
+ {
+ .procname = "ngroups_max",
+ .data = &ngroups_max,
+@@ -1187,6 +1229,13 @@ static struct ctl_table vm_table[] = {
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ },
++ {
++ .procname = "heap_stack_gap",
++ .data = &sysctl_heap_stack_gap,
++ .maxlen = sizeof(sysctl_heap_stack_gap),
++ .mode = 0644,
++ .proc_handler = proc_doulongvec_minmax,
++ },
+ #else
+ {
+ .procname = "nr_trim_pages",
+@@ -1698,6 +1747,16 @@ int sysctl_perm(struct ctl_table_root *r
+ int error;
+ int mode;
+
++ if (table->parent != NULL && table->parent->procname != NULL &&
++ table->procname != NULL &&
++ gr_handle_sysctl_mod(table->parent->procname, table->procname, op))
++ return -EACCES;
++ if (gr_handle_chroot_sysctl(op))
++ return -EACCES;
++ error = gr_handle_sysctl(table, op);
++ if (error)
++ return error;
++
+ error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC));
+ if (error)
+ return error;
+@@ -2105,6 +2164,16 @@ int proc_dostring(struct ctl_table *tabl
+ buffer, lenp, ppos);
+ }
+
++int proc_dostring_modpriv(struct ctl_table *table, int write,
++ void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++ if (write && !capable(CAP_SYS_MODULE))
++ return -EPERM;
++
++ return _proc_do_string(table->data, table->maxlen, write,
++ buffer, lenp, ppos);
++}
++
+ static size_t proc_skip_spaces(char **buf)
+ {
+ size_t ret;
+@@ -2210,6 +2279,8 @@ static int proc_put_long(void __user **b
+ len = strlen(tmp);
+ if (len > *size)
+ len = *size;
++ if (len > sizeof(tmp))
++ len = sizeof(tmp);
+ if (copy_to_user(*buf, tmp, len))
+ return -EFAULT;
+ *size -= len;
+@@ -2526,8 +2597,11 @@ static int __do_proc_doulongvec_minmax(v
+ *i = val;
+ } else {
+ val = convdiv * (*i) / convmul;
+- if (!first)
++ if (!first) {
+ err = proc_put_char(&buffer, &left, '\t');
++ if (err)
++ break;
++ }
+ err = proc_put_long(&buffer, &left, val, false);
+ if (err)
+ break;
+@@ -2922,6 +2996,12 @@ int proc_dostring(struct ctl_table *tabl
+ return -ENOSYS;
+ }
+
++int proc_dostring_modpriv(struct ctl_table *table, int write,
++ void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++ return -ENOSYS;
++}
++
+ int proc_dointvec(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+@@ -2978,6 +3058,7 @@ EXPORT_SYMBOL(proc_dointvec_minmax);
+ EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
+ EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
+ EXPORT_SYMBOL(proc_dostring);
++EXPORT_SYMBOL(proc_dostring_modpriv);
+ EXPORT_SYMBOL(proc_doulongvec_minmax);
+ EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
+ EXPORT_SYMBOL(register_sysctl_table);
+diff -urNp linux-2.6.38.7/kernel/sysctl_check.c linux-2.6.38.7/kernel/sysctl_check.c
+--- linux-2.6.38.7/kernel/sysctl_check.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/sysctl_check.c 2011-04-28 19:34:15.000000000 -0400
+@@ -131,6 +131,7 @@ int sysctl_check_table(struct nsproxy *n
+ set_fail(&fail, table, "Directory with extra2");
+ } else {
+ if ((table->proc_handler == proc_dostring) ||
++ (table->proc_handler == proc_dostring_modpriv) ||
+ (table->proc_handler == proc_dointvec) ||
+ (table->proc_handler == proc_dointvec_minmax) ||
+ (table->proc_handler == proc_dointvec_jiffies) ||
+diff -urNp linux-2.6.38.7/kernel/taskstats.c linux-2.6.38.7/kernel/taskstats.c
+--- linux-2.6.38.7/kernel/taskstats.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/taskstats.c 2011-04-28 19:34:15.000000000 -0400
+@@ -27,9 +27,12 @@
+ #include <linux/cgroup.h>
+ #include <linux/fs.h>
+ #include <linux/file.h>
++#include <linux/grsecurity.h>
+ #include <net/genetlink.h>
+ #include <asm/atomic.h>
+
++extern int gr_is_taskstats_denied(int pid);
++
+ /*
+ * Maximum length of a cpumask that can be specified in
+ * the TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK attribute
+@@ -549,6 +552,9 @@ err:
+
+ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
+ {
++ if (gr_is_taskstats_denied(current->pid))
++ return -EACCES;
++
+ if (info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK])
+ return cmd_attr_register_cpumask(info);
+ else if (info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK])
+diff -urNp linux-2.6.38.7/kernel/time/tick-broadcast.c linux-2.6.38.7/kernel/time/tick-broadcast.c
+--- linux-2.6.38.7/kernel/time/tick-broadcast.c 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/kernel/time/tick-broadcast.c 2011-05-22 23:06:04.000000000 -0400
+@@ -116,7 +116,7 @@ int tick_device_uses_broadcast(struct cl
+ * then clear the broadcast bit.
+ */
+ if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
+- int cpu = smp_processor_id();
++ cpu = smp_processor_id();
+
+ cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
+ tick_broadcast_clear_oneshot(cpu);
+diff -urNp linux-2.6.38.7/kernel/time/timekeeping.c linux-2.6.38.7/kernel/time/timekeeping.c
+--- linux-2.6.38.7/kernel/time/timekeeping.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/time/timekeeping.c 2011-04-28 19:34:15.000000000 -0400
+@@ -14,6 +14,7 @@
+ #include <linux/init.h>
+ #include <linux/mm.h>
+ #include <linux/sched.h>
++#include <linux/grsecurity.h>
+ #include <linux/sysdev.h>
+ #include <linux/clocksource.h>
+ #include <linux/jiffies.h>
+@@ -361,6 +362,8 @@ int do_settimeofday(struct timespec *tv)
+ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ return -EINVAL;
+
++ gr_log_timechange();
++
+ write_seqlock_irqsave(&xtime_lock, flags);
+
+ timekeeping_forward_now();
+diff -urNp linux-2.6.38.7/kernel/time/timer_list.c linux-2.6.38.7/kernel/time/timer_list.c
+--- linux-2.6.38.7/kernel/time/timer_list.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/time/timer_list.c 2011-04-28 19:34:15.000000000 -0400
+@@ -38,12 +38,16 @@ DECLARE_PER_CPU(struct hrtimer_cpu_base,
+
+ static void print_name_offset(struct seq_file *m, void *sym)
+ {
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ SEQ_printf(m, "<%p>", NULL);
++#else
+ char symname[KSYM_NAME_LEN];
+
+ if (lookup_symbol_name((unsigned long)sym, symname) < 0)
+ SEQ_printf(m, "<%pK>", sym);
+ else
+ SEQ_printf(m, "%s", symname);
++#endif
+ }
+
+ static void
+@@ -112,7 +116,11 @@ next_one:
+ static void
+ print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now)
+ {
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ SEQ_printf(m, " .base: %p\n", NULL);
++#else
+ SEQ_printf(m, " .base: %pK\n", base);
++#endif
+ SEQ_printf(m, " .index: %d\n",
+ base->index);
+ SEQ_printf(m, " .resolution: %Lu nsecs\n",
+@@ -293,7 +301,11 @@ static int __init init_timer_list_procfs
+ {
+ struct proc_dir_entry *pe;
+
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ pe = proc_create("timer_list", 0400, NULL, &timer_list_fops);
++#else
+ pe = proc_create("timer_list", 0444, NULL, &timer_list_fops);
++#endif
+ if (!pe)
+ return -ENOMEM;
+ return 0;
+diff -urNp linux-2.6.38.7/kernel/time/timer_stats.c linux-2.6.38.7/kernel/time/timer_stats.c
+--- linux-2.6.38.7/kernel/time/timer_stats.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/time/timer_stats.c 2011-04-28 19:57:25.000000000 -0400
+@@ -116,7 +116,7 @@ static ktime_t time_start, time_stop;
+ static unsigned long nr_entries;
+ static struct entry entries[MAX_ENTRIES];
+
+-static atomic_t overflow_count;
++static atomic_unchecked_t overflow_count;
+
+ /*
+ * The entries are in a hash-table, for fast lookup:
+@@ -140,7 +140,7 @@ static void reset_entries(void)
+ nr_entries = 0;
+ memset(entries, 0, sizeof(entries));
+ memset(tstat_hash_table, 0, sizeof(tstat_hash_table));
+- atomic_set(&overflow_count, 0);
++ atomic_set_unchecked(&overflow_count, 0);
+ }
+
+ static struct entry *alloc_entry(void)
+@@ -261,7 +261,7 @@ void timer_stats_update_stats(void *time
+ if (likely(entry))
+ entry->count++;
+ else
+- atomic_inc(&overflow_count);
++ atomic_inc_unchecked(&overflow_count);
+
+ out_unlock:
+ raw_spin_unlock_irqrestore(lock, flags);
+@@ -269,12 +269,16 @@ void timer_stats_update_stats(void *time
+
+ static void print_name_offset(struct seq_file *m, unsigned long addr)
+ {
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ seq_printf(m, "<%p>", NULL);
++#else
+ char symname[KSYM_NAME_LEN];
+
+ if (lookup_symbol_name(addr, symname) < 0)
+ seq_printf(m, "<%p>", (void *)addr);
+ else
+ seq_printf(m, "%s", symname);
++#endif
+ }
+
+ static int tstats_show(struct seq_file *m, void *v)
+@@ -300,9 +304,9 @@ static int tstats_show(struct seq_file *
+
+ seq_puts(m, "Timer Stats Version: v0.2\n");
+ seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
+- if (atomic_read(&overflow_count))
++ if (atomic_read_unchecked(&overflow_count))
+ seq_printf(m, "Overflow: %d entries\n",
+- atomic_read(&overflow_count));
++ atomic_read_unchecked(&overflow_count));
+
+ for (i = 0; i < nr_entries; i++) {
+ entry = entries + i;
+@@ -417,7 +421,11 @@ static int __init init_tstats_procfs(voi
+ {
+ struct proc_dir_entry *pe;
+
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ pe = proc_create("timer_stats", 0600, NULL, &tstats_fops);
++#else
+ pe = proc_create("timer_stats", 0644, NULL, &tstats_fops);
++#endif
+ if (!pe)
+ return -ENOMEM;
+ return 0;
+diff -urNp linux-2.6.38.7/kernel/time.c linux-2.6.38.7/kernel/time.c
+--- linux-2.6.38.7/kernel/time.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/time.c 2011-04-28 19:34:15.000000000 -0400
+@@ -163,6 +163,11 @@ int do_sys_settimeofday(struct timespec
+ return error;
+
+ if (tz) {
++ /* we log in do_settimeofday called below, so don't log twice
++ */
++ if (!tv)
++ gr_log_timechange();
++
+ /* SMP safe, global irq locking makes it work. */
+ sys_tz = *tz;
+ update_vsyscall_tz();
+diff -urNp linux-2.6.38.7/kernel/timer.c linux-2.6.38.7/kernel/timer.c
+--- linux-2.6.38.7/kernel/timer.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/timer.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1276,7 +1276,7 @@ void update_process_times(int user_tick)
+ /*
+ * This function runs timers and the timer-tq in bottom half context.
+ */
+-static void run_timer_softirq(struct softirq_action *h)
++static void run_timer_softirq(void)
+ {
+ struct tvec_base *base = __this_cpu_read(tvec_bases);
+
+diff -urNp linux-2.6.38.7/kernel/trace/blktrace.c linux-2.6.38.7/kernel/trace/blktrace.c
+--- linux-2.6.38.7/kernel/trace/blktrace.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/blktrace.c 2011-04-28 19:57:25.000000000 -0400
+@@ -321,7 +321,7 @@ static ssize_t blk_dropped_read(struct f
+ struct blk_trace *bt = filp->private_data;
+ char buf[16];
+
+- snprintf(buf, sizeof(buf), "%u\n", atomic_read(&bt->dropped));
++ snprintf(buf, sizeof(buf), "%u\n", atomic_read_unchecked(&bt->dropped));
+
+ return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
+ }
+@@ -386,7 +386,7 @@ static int blk_subbuf_start_callback(str
+ return 1;
+
+ bt = buf->chan->private_data;
+- atomic_inc(&bt->dropped);
++ atomic_inc_unchecked(&bt->dropped);
+ return 0;
+ }
+
+@@ -487,7 +487,7 @@ int do_blk_trace_setup(struct request_qu
+
+ bt->dir = dir;
+ bt->dev = dev;
+- atomic_set(&bt->dropped, 0);
++ atomic_set_unchecked(&bt->dropped, 0);
+
+ ret = -EIO;
+ bt->dropped_file = debugfs_create_file("dropped", 0444, dir, bt,
+diff -urNp linux-2.6.38.7/kernel/trace/ftrace.c linux-2.6.38.7/kernel/trace/ftrace.c
+--- linux-2.6.38.7/kernel/trace/ftrace.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/ftrace.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1107,13 +1107,18 @@ ftrace_code_disable(struct module *mod,
+
+ ip = rec->ip;
+
++ ret = ftrace_arch_code_modify_prepare();
++ FTRACE_WARN_ON(ret);
++ if (ret)
++ return 0;
++
+ ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
++ FTRACE_WARN_ON(ftrace_arch_code_modify_post_process());
+ if (ret) {
+ ftrace_bug(ret, ip);
+ rec->flags |= FTRACE_FL_FAILED;
+- return 0;
+ }
+- return 1;
++ return ret ? 0 : 1;
+ }
+
+ /*
+diff -urNp linux-2.6.38.7/kernel/trace/ring_buffer.c linux-2.6.38.7/kernel/trace/ring_buffer.c
+--- linux-2.6.38.7/kernel/trace/ring_buffer.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/ring_buffer.c 2011-04-28 19:34:15.000000000 -0400
+@@ -669,7 +669,7 @@ static struct list_head *rb_list_head(st
+ * the reader page). But if the next page is a header page,
+ * its flags will be non zero.
+ */
+-static int inline
++static inline int
+ rb_is_head_page(struct ring_buffer_per_cpu *cpu_buffer,
+ struct buffer_page *page, struct list_head *list)
+ {
+diff -urNp linux-2.6.38.7/kernel/trace/trace.c linux-2.6.38.7/kernel/trace/trace.c
+--- linux-2.6.38.7/kernel/trace/trace.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/trace.c 2011-05-16 21:47:08.000000000 -0400
+@@ -3316,6 +3316,8 @@ static ssize_t tracing_splice_read_pipe(
+ size_t rem;
+ unsigned int i;
+
++ pax_track_stack();
++
+ if (splice_grow_spd(pipe, &spd))
+ return -ENOMEM;
+
+@@ -3799,6 +3801,8 @@ tracing_buffers_splice_read(struct file
+ int entries, size, i;
+ size_t ret;
+
++ pax_track_stack();
++
+ if (splice_grow_spd(pipe, &spd))
+ return -ENOMEM;
+
+@@ -3967,10 +3971,9 @@ static const struct file_operations trac
+ };
+ #endif
+
+-static struct dentry *d_tracer;
+-
+ struct dentry *tracing_init_dentry(void)
+ {
++ static struct dentry *d_tracer;
+ static int once;
+
+ if (d_tracer)
+@@ -3990,10 +3993,9 @@ struct dentry *tracing_init_dentry(void)
+ return d_tracer;
+ }
+
+-static struct dentry *d_percpu;
+-
+ struct dentry *tracing_dentry_percpu(void)
+ {
++ static struct dentry *d_percpu;
+ static int once;
+ struct dentry *d_tracer;
+
+diff -urNp linux-2.6.38.7/kernel/trace/trace_events.c linux-2.6.38.7/kernel/trace/trace_events.c
+--- linux-2.6.38.7/kernel/trace/trace_events.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/trace_events.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1240,10 +1240,10 @@ static LIST_HEAD(ftrace_module_file_list
+ struct ftrace_module_file_ops {
+ struct list_head list;
+ struct module *mod;
+- struct file_operations id;
+- struct file_operations enable;
+- struct file_operations format;
+- struct file_operations filter;
++ struct file_operations id; /* cannot be const, see trace_create_file_ops() */
++ struct file_operations enable; /* cannot be const, see trace_create_file_ops() */
++ struct file_operations format; /* cannot be const, see trace_create_file_ops() */
++ struct file_operations filter; /* cannot be const, see trace_create_file_ops() */
+ };
+
+ static struct ftrace_module_file_ops *
+diff -urNp linux-2.6.38.7/kernel/trace/trace_mmiotrace.c linux-2.6.38.7/kernel/trace/trace_mmiotrace.c
+--- linux-2.6.38.7/kernel/trace/trace_mmiotrace.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/trace_mmiotrace.c 2011-04-28 19:57:25.000000000 -0400
+@@ -24,7 +24,7 @@ struct header_iter {
+ static struct trace_array *mmio_trace_array;
+ static bool overrun_detected;
+ static unsigned long prev_overruns;
+-static atomic_t dropped_count;
++static atomic_unchecked_t dropped_count;
+
+ static void mmio_reset_data(struct trace_array *tr)
+ {
+@@ -127,7 +127,7 @@ static void mmio_close(struct trace_iter
+
+ static unsigned long count_overruns(struct trace_iterator *iter)
+ {
+- unsigned long cnt = atomic_xchg(&dropped_count, 0);
++ unsigned long cnt = atomic_xchg_unchecked(&dropped_count, 0);
+ unsigned long over = ring_buffer_overruns(iter->tr->buffer);
+
+ if (over > prev_overruns)
+@@ -317,7 +317,7 @@ static void __trace_mmiotrace_rw(struct
+ event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_RW,
+ sizeof(*entry), 0, pc);
+ if (!event) {
+- atomic_inc(&dropped_count);
++ atomic_inc_unchecked(&dropped_count);
+ return;
+ }
+ entry = ring_buffer_event_data(event);
+@@ -347,7 +347,7 @@ static void __trace_mmiotrace_map(struct
+ event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_MAP,
+ sizeof(*entry), 0, pc);
+ if (!event) {
+- atomic_inc(&dropped_count);
++ atomic_inc_unchecked(&dropped_count);
+ return;
+ }
+ entry = ring_buffer_event_data(event);
+diff -urNp linux-2.6.38.7/kernel/trace/trace_output.c linux-2.6.38.7/kernel/trace/trace_output.c
+--- linux-2.6.38.7/kernel/trace/trace_output.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/trace_output.c 2011-04-28 19:34:15.000000000 -0400
+@@ -278,7 +278,7 @@ int trace_seq_path(struct trace_seq *s,
+
+ p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
+ if (!IS_ERR(p)) {
+- p = mangle_path(s->buffer + s->len, p, "\n");
++ p = mangle_path(s->buffer + s->len, p, "\n\\");
+ if (p) {
+ s->len = p - s->buffer;
+ return 1;
+diff -urNp linux-2.6.38.7/kernel/trace/trace_stack.c linux-2.6.38.7/kernel/trace/trace_stack.c
+--- linux-2.6.38.7/kernel/trace/trace_stack.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/trace_stack.c 2011-04-28 19:34:15.000000000 -0400
+@@ -50,7 +50,7 @@ static inline void check_stack(void)
+ return;
+
+ /* we do not handle interrupt stacks yet */
+- if (!object_is_on_stack(&this_size))
++ if (!object_starts_on_stack(&this_size))
+ return;
+
+ local_irq_save(flags);
+diff -urNp linux-2.6.38.7/kernel/trace/trace_workqueue.c linux-2.6.38.7/kernel/trace/trace_workqueue.c
+--- linux-2.6.38.7/kernel/trace/trace_workqueue.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/kernel/trace/trace_workqueue.c 2011-04-28 19:34:15.000000000 -0400
+@@ -22,7 +22,7 @@ struct cpu_workqueue_stats {
+ int cpu;
+ pid_t pid;
+ /* Can be inserted from interrupt or user context, need to be atomic */
+- atomic_t inserted;
++ atomic_unchecked_t inserted;
+ /*
+ * Don't need to be atomic, works are serialized in a single workqueue thread
+ * on a single CPU.
+@@ -60,7 +60,7 @@ probe_workqueue_insertion(void *ignore,
+ spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
+ list_for_each_entry(node, &workqueue_cpu_stat(cpu)->list, list) {
+ if (node->pid == wq_thread->pid) {
+- atomic_inc(&node->inserted);
++ atomic_inc_unchecked(&node->inserted);
+ goto found;
+ }
+ }
+@@ -210,7 +210,7 @@ static int workqueue_stat_show(struct se
+ tsk = get_pid_task(pid, PIDTYPE_PID);
+ if (tsk) {
+ seq_printf(s, "%3d %6d %6u %s\n", cws->cpu,
+- atomic_read(&cws->inserted), cws->executed,
++ atomic_read_unchecked(&cws->inserted), cws->executed,
+ tsk->comm);
+ put_task_struct(tsk);
+ }
+diff -urNp linux-2.6.38.7/lib/bug.c linux-2.6.38.7/lib/bug.c
+--- linux-2.6.38.7/lib/bug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/lib/bug.c 2011-04-28 19:34:15.000000000 -0400
+@@ -133,6 +133,8 @@ enum bug_trap_type report_bug(unsigned l
+ return BUG_TRAP_TYPE_NONE;
+
+ bug = find_bug(bugaddr);
++ if (!bug)
++ return BUG_TRAP_TYPE_NONE;
+
+ file = NULL;
+ line = 0;
+diff -urNp linux-2.6.38.7/lib/debugobjects.c linux-2.6.38.7/lib/debugobjects.c
+--- linux-2.6.38.7/lib/debugobjects.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/lib/debugobjects.c 2011-04-28 19:34:15.000000000 -0400
+@@ -281,7 +281,7 @@ static void debug_object_is_on_stack(voi
+ if (limit > 4)
+ return;
+
+- is_on_stack = object_is_on_stack(addr);
++ is_on_stack = object_starts_on_stack(addr);
+ if (is_on_stack == onstack)
+ return;
+
+diff -urNp linux-2.6.38.7/lib/dma-debug.c linux-2.6.38.7/lib/dma-debug.c
+--- linux-2.6.38.7/lib/dma-debug.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/lib/dma-debug.c 2011-04-28 19:34:15.000000000 -0400
+@@ -862,7 +862,7 @@ out:
+
+ static void check_for_stack(struct device *dev, void *addr)
+ {
+- if (object_is_on_stack(addr))
++ if (object_starts_on_stack(addr))
+ err_printk(dev, NULL, "DMA-API: device driver maps memory from"
+ "stack [addr=%p]\n", addr);
+ }
+diff -urNp linux-2.6.38.7/lib/inflate.c linux-2.6.38.7/lib/inflate.c
+--- linux-2.6.38.7/lib/inflate.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/lib/inflate.c 2011-04-28 19:34:15.000000000 -0400
+@@ -269,7 +269,7 @@ static void free(void *where)
+ malloc_ptr = free_mem_ptr;
+ }
+ #else
+-#define malloc(a) kmalloc(a, GFP_KERNEL)
++#define malloc(a) kmalloc((a), GFP_KERNEL)
+ #define free(a) kfree(a)
+ #endif
+
+diff -urNp linux-2.6.38.7/lib/Kconfig.debug linux-2.6.38.7/lib/Kconfig.debug
+--- linux-2.6.38.7/lib/Kconfig.debug 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/lib/Kconfig.debug 2011-04-28 19:34:15.000000000 -0400
+@@ -1066,6 +1066,7 @@ config LATENCYTOP
+ depends on DEBUG_KERNEL
+ depends on STACKTRACE_SUPPORT
+ depends on PROC_FS
++ depends on !GRKERNSEC_HIDESYM
+ select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE
+ select KALLSYMS
+ select KALLSYMS_ALL
+diff -urNp linux-2.6.38.7/lib/kref.c linux-2.6.38.7/lib/kref.c
+--- linux-2.6.38.7/lib/kref.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/lib/kref.c 2011-04-28 19:34:15.000000000 -0400
+@@ -52,7 +52,7 @@ void kref_get(struct kref *kref)
+ */
+ int kref_put(struct kref *kref, void (*release)(struct kref *kref))
+ {
+- WARN_ON(release == NULL);
++ BUG_ON(release == NULL);
+ WARN_ON(release == (void (*)(struct kref *))kfree);
+
+ if (atomic_dec_and_test(&kref->refcount)) {
+diff -urNp linux-2.6.38.7/lib/radix-tree.c linux-2.6.38.7/lib/radix-tree.c
+--- linux-2.6.38.7/lib/radix-tree.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/lib/radix-tree.c 2011-04-28 19:34:15.000000000 -0400
+@@ -80,7 +80,7 @@ struct radix_tree_preload {
+ int nr;
+ struct radix_tree_node *nodes[RADIX_TREE_MAX_PATH];
+ };
+-static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, };
++static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads);
+
+ static inline void *ptr_to_indirect(void *ptr)
+ {
+diff -urNp linux-2.6.38.7/lib/vsprintf.c linux-2.6.38.7/lib/vsprintf.c
+--- linux-2.6.38.7/lib/vsprintf.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/lib/vsprintf.c 2011-04-28 19:34:15.000000000 -0400
+@@ -16,6 +16,9 @@
+ * - scnprintf and vscnprintf
+ */
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++#define __INCLUDED_BY_HIDESYM 1
++#endif
+ #include <stdarg.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+@@ -433,7 +436,7 @@ char *symbol_string(char *buf, char *end
+ unsigned long value = (unsigned long) ptr;
+ #ifdef CONFIG_KALLSYMS
+ char sym[KSYM_SYMBOL_LEN];
+- if (ext != 'f' && ext != 's')
++ if (ext != 'f' && ext != 's' && ext != 'a')
+ sprint_symbol(sym, value);
+ else
+ kallsyms_lookup(value, NULL, NULL, NULL, sym);
+@@ -795,7 +798,11 @@ char *uuid_string(char *buf, char *end,
+ return string(buf, end, uuid, spec);
+ }
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++int kptr_restrict = 2;
++#else
+ int kptr_restrict = 1;
++#endif
+
+ /*
+ * Show a '%p' thing. A kernel extension is that the '%p' is followed
+@@ -808,6 +815,8 @@ int kptr_restrict = 1;
+ * - 'f' For simple symbolic function names without offset
+ * - 'S' For symbolic direct pointers with offset
+ * - 's' For symbolic direct pointers without offset
++ * - 'A' For symbolic direct pointers with offset approved for use with GRKERNSEC_HIDESYM
++ * - 'a' For symbolic direct pointers without offset approved for use with GRKERNSEC_HIDESYM
+ * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
+ * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
+ * - 'M' For a 6-byte MAC address, it prints the address in the
+@@ -852,12 +861,12 @@ char *pointer(const char *fmt, char *buf
+ {
+ if (!ptr) {
+ /*
+- * Print (null) with the same width as a pointer so it makes
++ * Print (nil) with the same width as a pointer so it makes
+ * tabular output look nice.
+ */
+ if (spec.field_width == -1)
+ spec.field_width = 2 * sizeof(void *);
+- return string(buf, end, "(null)", spec);
++ return string(buf, end, "(nil)", spec);
+ }
+
+ switch (*fmt) {
+@@ -867,6 +876,13 @@ char *pointer(const char *fmt, char *buf
+ /* Fallthrough */
+ case 'S':
+ case 's':
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ break;
++#else
++ return symbol_string(buf, end, ptr, spec, *fmt);
++#endif
++ case 'A':
++ case 'a':
+ return symbol_string(buf, end, ptr, spec, *fmt);
+ case 'R':
+ case 'r':
+@@ -1631,11 +1647,11 @@ int bstr_printf(char *buf, size_t size,
+ typeof(type) value; \
+ if (sizeof(type) == 8) { \
+ args = PTR_ALIGN(args, sizeof(u32)); \
+- *(u32 *)&value = *(u32 *)args; \
+- *((u32 *)&value + 1) = *(u32 *)(args + 4); \
++ *(u32 *)&value = *(const u32 *)args; \
++ *((u32 *)&value + 1) = *(const u32 *)(args + 4); \
+ } else { \
+ args = PTR_ALIGN(args, sizeof(type)); \
+- value = *(typeof(type) *)args; \
++ value = *(const typeof(type) *)args; \
+ } \
+ args += sizeof(type); \
+ value; \
+@@ -1698,7 +1714,7 @@ int bstr_printf(char *buf, size_t size,
+ case FORMAT_TYPE_STR: {
+ const char *str_arg = args;
+ args += strlen(str_arg) + 1;
+- str = string(str, end, (char *)str_arg, spec);
++ str = string(str, end, str_arg, spec);
+ break;
+ }
+
+diff -urNp linux-2.6.38.7/localversion-grsec linux-2.6.38.7/localversion-grsec
+--- linux-2.6.38.7/localversion-grsec 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/localversion-grsec 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1 @@
++-grsec
+diff -urNp linux-2.6.38.7/Makefile linux-2.6.38.7/Makefile
+--- linux-2.6.38.7/Makefile 2011-05-22 23:05:17.000000000 -0400
++++ linux-2.6.38.7/Makefile 2011-05-22 23:05:53.000000000 -0400
+@@ -233,8 +233,8 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH"
+
+ HOSTCC = gcc
+ HOSTCXX = g++
+-HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
+-HOSTCXXFLAGS = -O2
++HOSTCFLAGS = -Wall -W -Wmissing-prototypes -Wstrict-prototypes -Wno-empty-body -Wno-unused-parameter -Wno-missing-field-initializers -O2 -fomit-frame-pointer -fno-delete-null-pointer-checks
++HOSTCXXFLAGS = -O2 -fno-delete-null-pointer-checks
+
+ # Decide whether to build built-in, modular, or both.
+ # Normally, just do built-in.
+@@ -352,6 +352,7 @@ LINUXINCLUDE := -I$(srctree)/arch/$(h
+ KBUILD_CPPFLAGS := -D__KERNEL__
+
+ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
++ -W -Wno-empty-body -Wno-unused-parameter -Wno-missing-field-initializers \
+ -fno-strict-aliasing -fno-common \
+ -Werror-implicit-function-declaration \
+ -Wno-format-security \
+@@ -681,7 +682,7 @@ export mod_strip_cmd
+
+
+ ifeq ($(KBUILD_EXTMOD),)
+-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
++core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
+
+ vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
+ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
+diff -urNp linux-2.6.38.7/mm/bootmem.c linux-2.6.38.7/mm/bootmem.c
+--- linux-2.6.38.7/mm/bootmem.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/bootmem.c 2011-04-28 19:34:15.000000000 -0400
+@@ -201,19 +201,30 @@ static void __init __free_pages_memory(u
+ unsigned long __init free_all_memory_core_early(int nodeid)
+ {
+ int i;
+- u64 start, end;
++ u64 start, end, startrange, endrange;
+ unsigned long count = 0;
+- struct range *range = NULL;
++ struct range *range = NULL, rangerange = { 0, 0 };
+ int nr_range;
+
+ nr_range = get_free_all_memory_range(&range, nodeid);
++ startrange = __pa(range) >> PAGE_SHIFT;
++ endrange = (__pa(range + nr_range) - 1) >> PAGE_SHIFT;
+
+ for (i = 0; i < nr_range; i++) {
+ start = range[i].start;
+ end = range[i].end;
++ if (start <= endrange && startrange < end) {
++ BUG_ON(rangerange.start | rangerange.end);
++ rangerange = range[i];
++ continue;
++ }
+ count += end - start;
+ __free_pages_memory(start, end);
+ }
++ start = rangerange.start;
++ end = rangerange.end;
++ count += end - start;
++ __free_pages_memory(start, end);
+
+ return count;
+ }
+diff -urNp linux-2.6.38.7/mm/filemap.c linux-2.6.38.7/mm/filemap.c
+--- linux-2.6.38.7/mm/filemap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/filemap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1664,7 +1664,7 @@ int generic_file_mmap(struct file * file
+ struct address_space *mapping = file->f_mapping;
+
+ if (!mapping->a_ops->readpage)
+- return -ENOEXEC;
++ return -ENODEV;
+ file_accessed(file);
+ vma->vm_ops = &generic_file_vm_ops;
+ vma->vm_flags |= VM_CAN_NONLINEAR;
+@@ -2060,6 +2060,7 @@ inline int generic_write_checks(struct f
+ *pos = i_size_read(inode);
+
+ if (limit != RLIM_INFINITY) {
++ gr_learn_resource(current, RLIMIT_FSIZE,*pos, 0);
+ if (*pos >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ return -EFBIG;
+diff -urNp linux-2.6.38.7/mm/fremap.c linux-2.6.38.7/mm/fremap.c
+--- linux-2.6.38.7/mm/fremap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/fremap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -156,6 +156,11 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
+ retry:
+ vma = find_vma(mm, start);
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma && (mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_flags & VM_MAYEXEC))
++ goto out;
++#endif
++
+ /*
+ * Make sure the vma is shared, that it supports prefaulting,
+ * and that the remapped range is valid and fully within
+@@ -224,7 +229,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
+ /*
+ * drop PG_Mlocked flag for over-mapped range
+ */
+- unsigned int saved_flags = vma->vm_flags;
++ unsigned long saved_flags = vma->vm_flags;
+ munlock_vma_pages_range(vma, start, start + size);
+ vma->vm_flags = saved_flags;
+ }
+diff -urNp linux-2.6.38.7/mm/highmem.c linux-2.6.38.7/mm/highmem.c
+--- linux-2.6.38.7/mm/highmem.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/highmem.c 2011-04-28 19:34:15.000000000 -0400
+@@ -125,9 +125,10 @@ static void flush_all_zero_pkmaps(void)
+ * So no dangers, even with speculative execution.
+ */
+ page = pte_page(pkmap_page_table[i]);
++ pax_open_kernel();
+ pte_clear(&init_mm, (unsigned long)page_address(page),
+ &pkmap_page_table[i]);
+-
++ pax_close_kernel();
+ set_page_address(page, NULL);
+ need_flush = 1;
+ }
+@@ -186,9 +187,11 @@ start:
+ }
+ }
+ vaddr = PKMAP_ADDR(last_pkmap_nr);
++
++ pax_open_kernel();
+ set_pte_at(&init_mm, vaddr,
+ &(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot));
+-
++ pax_close_kernel();
+ pkmap_count[last_pkmap_nr] = 1;
+ set_page_address(page, (void *)vaddr);
+
+diff -urNp linux-2.6.38.7/mm/huge_memory.c linux-2.6.38.7/mm/huge_memory.c
+--- linux-2.6.38.7/mm/huge_memory.c 2011-05-10 22:06:27.000000000 -0400
++++ linux-2.6.38.7/mm/huge_memory.c 2011-05-10 22:06:56.000000000 -0400
+@@ -698,7 +698,7 @@ out:
+ * run pte_offset_map on the pmd, if an huge pmd could
+ * materialize from under us from a different thread.
+ */
+- if (unlikely(__pte_alloc(mm, vma, pmd, address)))
++ if (unlikely(pmd_none(*pmd) && __pte_alloc(mm, vma, pmd, address)))
+ return VM_FAULT_OOM;
+ /* if an huge pmd materialized from under us just retry later */
+ if (unlikely(pmd_trans_huge(*pmd)))
+diff -urNp linux-2.6.38.7/mm/hugetlb.c linux-2.6.38.7/mm/hugetlb.c
+--- linux-2.6.38.7/mm/hugetlb.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/hugetlb.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2333,6 +2333,27 @@ static int unmap_ref_private(struct mm_s
+ return 1;
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++static void pax_mirror_huge_pte(struct vm_area_struct *vma, unsigned long address, struct page *page_m)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ struct vm_area_struct *vma_m;
++ unsigned long address_m;
++ pte_t *ptep_m;
++
++ vma_m = pax_find_mirror_vma(vma);
++ if (!vma_m)
++ return;
++
++ BUG_ON(address >= SEGMEXEC_TASK_SIZE);
++ address_m = address + SEGMEXEC_TASK_SIZE;
++ ptep_m = huge_pte_offset(mm, address_m & HPAGE_MASK);
++ get_page(page_m);
++ hugepage_add_anon_rmap(page_m, vma_m, address_m);
++ set_huge_pte_at(mm, address_m, ptep_m, make_huge_pte(vma_m, page_m, 0));
++}
++#endif
++
+ /*
+ * Hugetlb_cow() should be called with page lock of the original hugepage held.
+ */
+@@ -2434,6 +2455,11 @@ retry_avoidcopy:
+ make_huge_pte(vma, new_page, 1));
+ page_remove_rmap(old_page);
+ hugepage_add_new_anon_rmap(new_page, vma, address);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ pax_mirror_huge_pte(vma, address, new_page);
++#endif
++
+ /* Make the old page be freed below */
+ new_page = old_page;
+ mmu_notifier_invalidate_range_end(mm,
+@@ -2585,6 +2611,10 @@ retry:
+ && (vma->vm_flags & VM_SHARED)));
+ set_huge_pte_at(mm, address, ptep, new_pte);
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ pax_mirror_huge_pte(vma, address, page);
++#endif
++
+ if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED)) {
+ /* Optimization, do the COW without a second fault */
+ ret = hugetlb_cow(mm, vma, address, ptep, new_pte, page);
+@@ -2614,6 +2644,10 @@ int hugetlb_fault(struct mm_struct *mm,
+ static DEFINE_MUTEX(hugetlb_instantiation_mutex);
+ struct hstate *h = hstate_vma(vma);
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m;
++#endif
++
+ ptep = huge_pte_offset(mm, address);
+ if (ptep) {
+ entry = huge_ptep_get(ptep);
+@@ -2625,6 +2659,26 @@ int hugetlb_fault(struct mm_struct *mm,
+ VM_FAULT_SET_HINDEX(h - hstates);
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ vma_m = pax_find_mirror_vma(vma);
++ if (vma_m) {
++ unsigned long address_m;
++
++ if (vma->vm_start > vma_m->vm_start) {
++ address_m = address;
++ address -= SEGMEXEC_TASK_SIZE;
++ vma = vma_m;
++ h = hstate_vma(vma);
++ } else
++ address_m = address + SEGMEXEC_TASK_SIZE;
++
++ if (!huge_pte_alloc(mm, address_m, huge_page_size(h)))
++ return VM_FAULT_OOM;
++ address_m &= HPAGE_MASK;
++ unmap_hugepage_range(vma, address_m, address_m + HPAGE_SIZE, NULL);
++ }
++#endif
++
+ ptep = huge_pte_alloc(mm, address, huge_page_size(h));
+ if (!ptep)
+ return VM_FAULT_OOM;
+diff -urNp linux-2.6.38.7/mm/Kconfig linux-2.6.38.7/mm/Kconfig
+--- linux-2.6.38.7/mm/Kconfig 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/Kconfig 2011-04-28 19:34:15.000000000 -0400
+@@ -240,7 +240,7 @@ config KSM
+ config DEFAULT_MMAP_MIN_ADDR
+ int "Low address space to protect from user allocation"
+ depends on MMU
+- default 4096
++ default 65536
+ help
+ This is the portion of low virtual memory which should be protected
+ from userspace allocation. Keeping a user from writing to low pages
+diff -urNp linux-2.6.38.7/mm/kmemleak.c linux-2.6.38.7/mm/kmemleak.c
+--- linux-2.6.38.7/mm/kmemleak.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/kmemleak.c 2011-04-28 19:34:15.000000000 -0400
+@@ -357,7 +357,7 @@ static void print_unreferenced(struct se
+
+ for (i = 0; i < object->trace_len; i++) {
+ void *ptr = (void *)object->trace[i];
+- seq_printf(seq, " [<%p>] %pS\n", ptr, ptr);
++ seq_printf(seq, " [<%p>] %pA\n", ptr, ptr);
+ }
+ }
+
+diff -urNp linux-2.6.38.7/mm/maccess.c linux-2.6.38.7/mm/maccess.c
+--- linux-2.6.38.7/mm/maccess.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/maccess.c 2011-04-28 19:34:15.000000000 -0400
+@@ -15,10 +15,10 @@
+ * happens, handle that and return -EFAULT.
+ */
+
+-long __weak probe_kernel_read(void *dst, void *src, size_t size)
++long __weak probe_kernel_read(void *dst, const void *src, size_t size)
+ __attribute__((alias("__probe_kernel_read")));
+
+-long __probe_kernel_read(void *dst, void *src, size_t size)
++long __probe_kernel_read(void *dst, const void *src, size_t size)
+ {
+ long ret;
+ mm_segment_t old_fs = get_fs();
+@@ -43,10 +43,10 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
+ * Safely write to address @dst from the buffer at @src. If a kernel fault
+ * happens, handle that and return -EFAULT.
+ */
+-long __weak probe_kernel_write(void *dst, void *src, size_t size)
++long __weak probe_kernel_write(void *dst, const void *src, size_t size)
+ __attribute__((alias("__probe_kernel_write")));
+
+-long __probe_kernel_write(void *dst, void *src, size_t size)
++long __probe_kernel_write(void *dst, const void *src, size_t size)
+ {
+ long ret;
+ mm_segment_t old_fs = get_fs();
+diff -urNp linux-2.6.38.7/mm/madvise.c linux-2.6.38.7/mm/madvise.c
+--- linux-2.6.38.7/mm/madvise.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/madvise.c 2011-04-28 19:34:15.000000000 -0400
+@@ -45,6 +45,10 @@ static long madvise_behavior(struct vm_a
+ pgoff_t pgoff;
+ unsigned long new_flags = vma->vm_flags;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m;
++#endif
++
+ switch (behavior) {
+ case MADV_NORMAL:
+ new_flags = new_flags & ~VM_RAND_READ & ~VM_SEQ_READ;
+@@ -110,6 +114,13 @@ success:
+ /*
+ * vm_flags is protected by the mmap_sem held in write mode.
+ */
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ vma_m = pax_find_mirror_vma(vma);
++ if (vma_m)
++ vma_m->vm_flags = new_flags & ~(VM_WRITE | VM_MAYWRITE | VM_ACCOUNT);
++#endif
++
+ vma->vm_flags = new_flags;
+
+ out:
+@@ -168,6 +179,11 @@ static long madvise_dontneed(struct vm_a
+ struct vm_area_struct ** prev,
+ unsigned long start, unsigned long end)
+ {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m;
++#endif
++
+ *prev = vma;
+ if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP))
+ return -EINVAL;
+@@ -180,6 +196,21 @@ static long madvise_dontneed(struct vm_a
+ zap_page_range(vma, start, end - start, &details);
+ } else
+ zap_page_range(vma, start, end - start, NULL);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ vma_m = pax_find_mirror_vma(vma);
++ if (vma_m) {
++ if (unlikely(vma->vm_flags & VM_NONLINEAR)) {
++ struct zap_details details = {
++ .nonlinear_vma = vma_m,
++ .last_index = ULONG_MAX,
++ };
++ zap_page_range(vma, start + SEGMEXEC_TASK_SIZE, end - start, &details);
++ } else
++ zap_page_range(vma, start + SEGMEXEC_TASK_SIZE, end - start, NULL);
++ }
++#endif
++
+ return 0;
+ }
+
+@@ -376,6 +407,16 @@ SYSCALL_DEFINE3(madvise, unsigned long,
+ if (end < start)
+ goto out;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
++ if (end > SEGMEXEC_TASK_SIZE)
++ goto out;
++ } else
++#endif
++
++ if (end > TASK_SIZE)
++ goto out;
++
+ error = 0;
+ if (end == start)
+ goto out;
+diff -urNp linux-2.6.38.7/mm/memory.c linux-2.6.38.7/mm/memory.c
+--- linux-2.6.38.7/mm/memory.c 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/mm/memory.c 2011-05-22 23:08:56.000000000 -0400
+@@ -259,8 +259,12 @@ static inline void free_pmd_range(struct
+ return;
+
+ pmd = pmd_offset(pud, start);
++
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_PER_CPU_PGD)
+ pud_clear(pud);
+ pmd_free_tlb(tlb, pmd, start);
++#endif
++
+ }
+
+ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
+@@ -291,9 +295,12 @@ static inline void free_pud_range(struct
+ if (end - 1 > ceiling - 1)
+ return;
+
++#if !defined(CONFIG_X86_64) || !defined(CONFIG_PAX_PER_CPU_PGD)
+ pud = pud_offset(pgd, start);
+ pgd_clear(pgd);
+ pud_free_tlb(tlb, pud, start);
++#endif
++
+ }
+
+ /*
+@@ -1410,12 +1417,6 @@ no_page_table:
+ return page;
+ }
+
+-static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
+-{
+- return stack_guard_page_start(vma, addr) ||
+- stack_guard_page_end(vma, addr+PAGE_SIZE);
+-}
+-
+ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long start, int nr_pages, unsigned int gup_flags,
+ struct page **pages, struct vm_area_struct **vmas,
+@@ -1439,10 +1440,10 @@ int __get_user_pages(struct task_struct
+ (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
+ i = 0;
+
+- do {
++ while (nr_pages) {
+ struct vm_area_struct *vma;
+
+- vma = find_extend_vma(mm, start);
++ vma = find_vma(mm, start);
+ if (!vma && in_gate_area(tsk, start)) {
+ unsigned long pg = start & PAGE_MASK;
+ pgd_t *pgd;
+@@ -1490,7 +1491,7 @@ int __get_user_pages(struct task_struct
+ goto next_page;
+ }
+
+- if (!vma ||
++ if (!vma || start < vma->vm_start ||
+ (vma->vm_flags & (VM_IO | VM_PFNMAP)) ||
+ !(vm_flags & vma->vm_flags))
+ return i ? : -EFAULT;
+@@ -1517,11 +1518,6 @@ int __get_user_pages(struct task_struct
+ int ret;
+ unsigned int fault_flags = 0;
+
+- /* For mlock, just skip the stack guard page. */
+- if (foll_flags & FOLL_MLOCK) {
+- if (stack_guard_page(vma, start))
+- goto next_page;
+- }
+ if (foll_flags & FOLL_WRITE)
+ fault_flags |= FAULT_FLAG_WRITE;
+ if (nonblocking)
+@@ -1582,7 +1578,7 @@ next_page:
+ start += PAGE_SIZE;
+ nr_pages--;
+ } while (nr_pages && start < vma->vm_end);
+- } while (nr_pages);
++ }
+ return i;
+ }
+
+@@ -1731,6 +1727,10 @@ static int insert_page(struct vm_area_st
+ page_add_file_rmap(page);
+ set_pte_at(mm, addr, pte, mk_pte(page, prot));
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ pax_mirror_file_pte(vma, addr, page, ptl);
++#endif
++
+ retval = 0;
+ pte_unmap_unlock(pte, ptl);
+ return retval;
+@@ -1765,10 +1765,22 @@ out:
+ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
+ struct page *page)
+ {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m;
++#endif
++
+ if (addr < vma->vm_start || addr >= vma->vm_end)
+ return -EFAULT;
+ if (!page_count(page))
+ return -EINVAL;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ vma_m = pax_find_mirror_vma(vma);
++ if (vma_m)
++ vma_m->vm_flags |= VM_INSERTPAGE;
++#endif
++
+ vma->vm_flags |= VM_INSERTPAGE;
+ return insert_page(vma, addr, page, vma->vm_page_prot);
+ }
+@@ -1854,6 +1866,7 @@ int vm_insert_mixed(struct vm_area_struc
+ unsigned long pfn)
+ {
+ BUG_ON(!(vma->vm_flags & VM_MIXEDMAP));
++ BUG_ON(vma->vm_mirror);
+
+ if (addr < vma->vm_start || addr >= vma->vm_end)
+ return -EFAULT;
+@@ -2169,6 +2182,186 @@ static inline void cow_user_page(struct
+ copy_user_highpage(dst, src, va, vma);
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++static void pax_unmap_mirror_pte(struct vm_area_struct *vma, unsigned long address, pmd_t *pmd)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ spinlock_t *ptl;
++ pte_t *pte, entry;
++
++ pte = pte_offset_map_lock(mm, pmd, address, &ptl);
++ entry = *pte;
++ if (!pte_present(entry)) {
++ if (!pte_none(entry)) {
++ BUG_ON(pte_file(entry));
++ free_swap_and_cache(pte_to_swp_entry(entry));
++ pte_clear_not_present_full(mm, address, pte, 0);
++ }
++ } else {
++ struct page *page;
++
++ flush_cache_page(vma, address, pte_pfn(entry));
++ entry = ptep_clear_flush(vma, address, pte);
++ BUG_ON(pte_dirty(entry));
++ page = vm_normal_page(vma, address, entry);
++ if (page) {
++ update_hiwater_rss(mm);
++ if (PageAnon(page))
++ dec_mm_counter_fast(mm, MM_ANONPAGES);
++ else
++ dec_mm_counter_fast(mm, MM_FILEPAGES);
++ page_remove_rmap(page);
++ page_cache_release(page);
++ }
++ }
++ pte_unmap_unlock(pte, ptl);
++}
++
++/* PaX: if vma is mirrored, synchronize the mirror's PTE
++ *
++ * the ptl of the lower mapped page is held on entry and is not released on exit
++ * or inside to ensure atomic changes to the PTE states (swapout, mremap, munmap, etc)
++ */
++static void pax_mirror_anon_pte(struct vm_area_struct *vma, unsigned long address, struct page *page_m, spinlock_t *ptl)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ unsigned long address_m;
++ spinlock_t *ptl_m;
++ struct vm_area_struct *vma_m;
++ pmd_t *pmd_m;
++ pte_t *pte_m, entry_m;
++
++ BUG_ON(!page_m || !PageAnon(page_m));
++
++ vma_m = pax_find_mirror_vma(vma);
++ if (!vma_m)
++ return;
++
++ BUG_ON(!PageLocked(page_m));
++ BUG_ON(address >= SEGMEXEC_TASK_SIZE);
++ address_m = address + SEGMEXEC_TASK_SIZE;
++ pmd_m = pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m);
++ pte_m = pte_offset_map(pmd_m, address_m);
++ ptl_m = pte_lockptr(mm, pmd_m);
++ if (ptl != ptl_m) {
++ spin_lock_nested(ptl_m, SINGLE_DEPTH_NESTING);
++ if (!pte_none(*pte_m))
++ goto out;
++ }
++
++ entry_m = pfn_pte(page_to_pfn(page_m), vma_m->vm_page_prot);
++ page_cache_get(page_m);
++ page_add_anon_rmap(page_m, vma_m, address_m);
++ inc_mm_counter_fast(mm, MM_ANONPAGES);
++ set_pte_at(mm, address_m, pte_m, entry_m);
++ update_mmu_cache(vma_m, address_m, entry_m);
++out:
++ if (ptl != ptl_m)
++ spin_unlock(ptl_m);
++ pte_unmap(pte_m);
++ unlock_page(page_m);
++}
++
++void pax_mirror_file_pte(struct vm_area_struct *vma, unsigned long address, struct page *page_m, spinlock_t *ptl)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ unsigned long address_m;
++ spinlock_t *ptl_m;
++ struct vm_area_struct *vma_m;
++ pmd_t *pmd_m;
++ pte_t *pte_m, entry_m;
++
++ BUG_ON(!page_m || PageAnon(page_m));
++
++ vma_m = pax_find_mirror_vma(vma);
++ if (!vma_m)
++ return;
++
++ BUG_ON(address >= SEGMEXEC_TASK_SIZE);
++ address_m = address + SEGMEXEC_TASK_SIZE;
++ pmd_m = pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m);
++ pte_m = pte_offset_map(pmd_m, address_m);
++ ptl_m = pte_lockptr(mm, pmd_m);
++ if (ptl != ptl_m) {
++ spin_lock_nested(ptl_m, SINGLE_DEPTH_NESTING);
++ if (!pte_none(*pte_m))
++ goto out;
++ }
++
++ entry_m = pfn_pte(page_to_pfn(page_m), vma_m->vm_page_prot);
++ page_cache_get(page_m);
++ page_add_file_rmap(page_m);
++ inc_mm_counter_fast(mm, MM_FILEPAGES);
++ set_pte_at(mm, address_m, pte_m, entry_m);
++ update_mmu_cache(vma_m, address_m, entry_m);
++out:
++ if (ptl != ptl_m)
++ spin_unlock(ptl_m);
++ pte_unmap(pte_m);
++}
++
++static void pax_mirror_pfn_pte(struct vm_area_struct *vma, unsigned long address, unsigned long pfn_m, spinlock_t *ptl)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ unsigned long address_m;
++ spinlock_t *ptl_m;
++ struct vm_area_struct *vma_m;
++ pmd_t *pmd_m;
++ pte_t *pte_m, entry_m;
++
++ vma_m = pax_find_mirror_vma(vma);
++ if (!vma_m)
++ return;
++
++ BUG_ON(address >= SEGMEXEC_TASK_SIZE);
++ address_m = address + SEGMEXEC_TASK_SIZE;
++ pmd_m = pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m);
++ pte_m = pte_offset_map(pmd_m, address_m);
++ ptl_m = pte_lockptr(mm, pmd_m);
++ if (ptl != ptl_m) {
++ spin_lock_nested(ptl_m, SINGLE_DEPTH_NESTING);
++ if (!pte_none(*pte_m))
++ goto out;
++ }
++
++ entry_m = pfn_pte(pfn_m, vma_m->vm_page_prot);
++ set_pte_at(mm, address_m, pte_m, entry_m);
++out:
++ if (ptl != ptl_m)
++ spin_unlock(ptl_m);
++ pte_unmap(pte_m);
++}
++
++static void pax_mirror_pte(struct vm_area_struct *vma, unsigned long address, pte_t *pte, pmd_t *pmd, spinlock_t *ptl)
++{
++ struct page *page_m;
++ pte_t entry;
++
++ if (!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC))
++ goto out;
++
++ entry = *pte;
++ page_m = vm_normal_page(vma, address, entry);
++ if (!page_m)
++ pax_mirror_pfn_pte(vma, address, pte_pfn(entry), ptl);
++ else if (PageAnon(page_m)) {
++ if (pax_find_mirror_vma(vma)) {
++ pte_unmap_unlock(pte, ptl);
++ lock_page(page_m);
++ pte = pte_offset_map_lock(vma->vm_mm, pmd, address, &ptl);
++ if (pte_same(entry, *pte))
++ pax_mirror_anon_pte(vma, address, page_m, ptl);
++ else
++ unlock_page(page_m);
++ }
++ } else
++ pax_mirror_file_pte(vma, address, page_m, ptl);
++
++out:
++ pte_unmap_unlock(pte, ptl);
++}
++#endif
++
+ /*
+ * This routine handles present pages, when users try to write
+ * to a shared page. It is done by copying the page to a new address
+@@ -2380,6 +2573,12 @@ gotten:
+ */
+ page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
+ if (likely(pte_same(*page_table, orig_pte))) {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (pax_find_mirror_vma(vma))
++ BUG_ON(!trylock_page(new_page));
++#endif
++
+ if (old_page) {
+ if (!PageAnon(old_page)) {
+ dec_mm_counter_fast(mm, MM_FILEPAGES);
+@@ -2431,6 +2630,10 @@ gotten:
+ page_remove_rmap(old_page);
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ pax_mirror_anon_pte(vma, address, new_page, ptl);
++#endif
++
+ /* Free the old page.. */
+ new_page = old_page;
+ ret |= VM_FAULT_WRITE;
+@@ -2841,6 +3044,11 @@ static int do_swap_page(struct mm_struct
+ swap_free(entry);
+ if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
+ try_to_free_swap(page);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((flags & FAULT_FLAG_WRITE) || !pax_find_mirror_vma(vma))
++#endif
++
+ unlock_page(page);
+ if (swapcache) {
+ /*
+@@ -2864,6 +3072,11 @@ static int do_swap_page(struct mm_struct
+
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, address, page_table);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ pax_mirror_anon_pte(vma, address, page, ptl);
++#endif
++
+ unlock:
+ pte_unmap_unlock(page_table, ptl);
+ out:
+@@ -2883,40 +3096,6 @@ out_release:
+ }
+
+ /*
+- * This is like a special single-page "expand_{down|up}wards()",
+- * except we must first make sure that 'address{-|+}PAGE_SIZE'
+- * doesn't hit another vma.
+- */
+-static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
+-{
+- address &= PAGE_MASK;
+- if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) {
+- struct vm_area_struct *prev = vma->vm_prev;
+-
+- /*
+- * Is there a mapping abutting this one below?
+- *
+- * That's only ok if it's the same stack mapping
+- * that has gotten split..
+- */
+- if (prev && prev->vm_end == address)
+- return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
+-
+- expand_stack(vma, address - PAGE_SIZE);
+- }
+- if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
+- struct vm_area_struct *next = vma->vm_next;
+-
+- /* As VM_GROWSDOWN but s/below/above/ */
+- if (next && next->vm_start == address + PAGE_SIZE)
+- return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
+-
+- expand_upwards(vma, address + PAGE_SIZE);
+- }
+- return 0;
+-}
+-
+-/*
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
+@@ -2925,27 +3104,23 @@ static int do_anonymous_page(struct mm_s
+ unsigned long address, pte_t *page_table, pmd_t *pmd,
+ unsigned int flags)
+ {
+- struct page *page;
++ struct page *page = NULL;
+ spinlock_t *ptl;
+ pte_t entry;
+
+- pte_unmap(page_table);
+-
+- /* Check if we need to add a guard page to the stack */
+- if (check_stack_guard_page(vma, address) < 0)
+- return VM_FAULT_SIGBUS;
+-
+- /* Use the zero-page for reads */
+ if (!(flags & FAULT_FLAG_WRITE)) {
+ entry = pte_mkspecial(pfn_pte(my_zero_pfn(address),
+ vma->vm_page_prot));
+- page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
++ ptl = pte_lockptr(mm, pmd);
++ spin_lock(ptl);
+ if (!pte_none(*page_table))
+ goto unlock;
+ goto setpte;
+ }
+
+ /* Allocate our own private page. */
++ pte_unmap(page_table);
++
+ if (unlikely(anon_vma_prepare(vma)))
+ goto oom;
+ page = alloc_zeroed_user_highpage_movable(vma, address);
+@@ -2964,6 +3139,11 @@ static int do_anonymous_page(struct mm_s
+ if (!pte_none(*page_table))
+ goto release;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (pax_find_mirror_vma(vma))
++ BUG_ON(!trylock_page(page));
++#endif
++
+ inc_mm_counter_fast(mm, MM_ANONPAGES);
+ page_add_new_anon_rmap(page, vma, address);
+ setpte:
+@@ -2971,6 +3151,12 @@ setpte:
+
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, address, page_table);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (page)
++ pax_mirror_anon_pte(vma, address, page, ptl);
++#endif
++
+ unlock:
+ pte_unmap_unlock(page_table, ptl);
+ return 0;
+@@ -3108,6 +3294,12 @@ static int __do_fault(struct mm_struct *
+ */
+ /* Only go through if we didn't race with anybody else... */
+ if (likely(pte_same(*page_table, orig_pte))) {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (anon && pax_find_mirror_vma(vma))
++ BUG_ON(!trylock_page(page));
++#endif
++
+ flush_icache_page(vma, page);
+ entry = mk_pte(page, vma->vm_page_prot);
+ if (flags & FAULT_FLAG_WRITE)
+@@ -3127,6 +3319,14 @@ static int __do_fault(struct mm_struct *
+
+ /* no need to invalidate: a not-present page won't be cached */
+ update_mmu_cache(vma, address, page_table);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (anon)
++ pax_mirror_anon_pte(vma, address, page, ptl);
++ else
++ pax_mirror_file_pte(vma, address, page, ptl);
++#endif
++
+ } else {
+ if (charged)
+ mem_cgroup_uncharge_page(page);
+@@ -3274,6 +3474,12 @@ int handle_pte_fault(struct mm_struct *m
+ if (flags & FAULT_FLAG_WRITE)
+ flush_tlb_fix_spurious_fault(vma, address);
+ }
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ pax_mirror_pte(vma, address, pte, pmd, ptl);
++ return 0;
++#endif
++
+ unlock:
+ pte_unmap_unlock(pte, ptl);
+ return 0;
+@@ -3290,6 +3496,10 @@ int handle_mm_fault(struct mm_struct *mm
+ pmd_t *pmd;
+ pte_t *pte;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m;
++#endif
++
+ __set_current_state(TASK_RUNNING);
+
+ count_vm_event(PGFAULT);
+@@ -3300,6 +3510,34 @@ int handle_mm_fault(struct mm_struct *mm
+ if (unlikely(is_vm_hugetlb_page(vma)))
+ return hugetlb_fault(mm, vma, address, flags);
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ vma_m = pax_find_mirror_vma(vma);
++ if (vma_m) {
++ unsigned long address_m;
++ pgd_t *pgd_m;
++ pud_t *pud_m;
++ pmd_t *pmd_m;
++
++ if (vma->vm_start > vma_m->vm_start) {
++ address_m = address;
++ address -= SEGMEXEC_TASK_SIZE;
++ vma = vma_m;
++ } else
++ address_m = address + SEGMEXEC_TASK_SIZE;
++
++ pgd_m = pgd_offset(mm, address_m);
++ pud_m = pud_alloc(mm, pgd_m, address_m);
++ if (!pud_m)
++ return VM_FAULT_OOM;
++ pmd_m = pmd_alloc(mm, pud_m, address_m);
++ if (!pmd_m)
++ return VM_FAULT_OOM;
++ if (!pmd_present(*pmd_m) && __pte_alloc(mm, vma_m, pmd_m, address_m))
++ return VM_FAULT_OOM;
++ pax_unmap_mirror_pte(vma_m, address_m, pmd_m);
++ }
++#endif
++
+ pgd = pgd_offset(mm, address);
+ pud = pud_alloc(mm, pgd, address);
+ if (!pud)
+@@ -3329,7 +3567,7 @@ int handle_mm_fault(struct mm_struct *mm
+ * run pte_offset_map on the pmd, if an huge pmd could
+ * materialize from under us from a different thread.
+ */
+- if (unlikely(pmd_none(*pmd)) && __pte_alloc(mm, vma, pmd, address))
++ if (unlikely(pmd_none(*pmd) && __pte_alloc(mm, vma, pmd, address)))
+ return VM_FAULT_OOM;
+ /* if an huge pmd materialized from under us just retry later */
+ if (unlikely(pmd_trans_huge(*pmd)))
+@@ -3433,7 +3671,7 @@ static int __init gate_vma_init(void)
+ gate_vma.vm_start = FIXADDR_USER_START;
+ gate_vma.vm_end = FIXADDR_USER_END;
+ gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+- gate_vma.vm_page_prot = __P101;
++ gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags);
+ /*
+ * Make sure the vDSO gets into every core dump.
+ * Dumping its contents makes post-mortem fully interpretable later
+diff -urNp linux-2.6.38.7/mm/memory-failure.c linux-2.6.38.7/mm/memory-failure.c
+--- linux-2.6.38.7/mm/memory-failure.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/memory-failure.c 2011-04-28 19:34:15.000000000 -0400
+@@ -58,7 +58,7 @@ int sysctl_memory_failure_early_kill __r
+
+ int sysctl_memory_failure_recovery __read_mostly = 1;
+
+-atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0);
++atomic_long_unchecked_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0);
+
+ #if defined(CONFIG_HWPOISON_INJECT) || defined(CONFIG_HWPOISON_INJECT_MODULE)
+
+@@ -1012,7 +1012,7 @@ int __memory_failure(unsigned long pfn,
+ }
+
+ nr_pages = 1 << compound_trans_order(hpage);
+- atomic_long_add(nr_pages, &mce_bad_pages);
++ atomic_long_add_unchecked(nr_pages, &mce_bad_pages);
+
+ /*
+ * We need/can do nothing about count=0 pages.
+@@ -1042,7 +1042,7 @@ int __memory_failure(unsigned long pfn,
+ if (!PageHWPoison(hpage)
+ || (hwpoison_filter(p) && TestClearPageHWPoison(p))
+ || (p != hpage && TestSetPageHWPoison(hpage))) {
+- atomic_long_sub(nr_pages, &mce_bad_pages);
++ atomic_long_sub_unchecked(nr_pages, &mce_bad_pages);
+ return 0;
+ }
+ set_page_hwpoison_huge_page(hpage);
+@@ -1100,7 +1100,7 @@ int __memory_failure(unsigned long pfn,
+ }
+ if (hwpoison_filter(p)) {
+ if (TestClearPageHWPoison(p))
+- atomic_long_sub(nr_pages, &mce_bad_pages);
++ atomic_long_sub_unchecked(nr_pages, &mce_bad_pages);
+ unlock_page(hpage);
+ put_page(hpage);
+ return 0;
+@@ -1226,7 +1226,7 @@ int unpoison_memory(unsigned long pfn)
+ return 0;
+ }
+ if (TestClearPageHWPoison(p))
+- atomic_long_sub(nr_pages, &mce_bad_pages);
++ atomic_long_sub_unchecked(nr_pages, &mce_bad_pages);
+ pr_info("MCE: Software-unpoisoned free page %#lx\n", pfn);
+ return 0;
+ }
+@@ -1240,7 +1240,7 @@ int unpoison_memory(unsigned long pfn)
+ */
+ if (TestClearPageHWPoison(page)) {
+ pr_info("MCE: Software-unpoisoned page %#lx\n", pfn);
+- atomic_long_sub(nr_pages, &mce_bad_pages);
++ atomic_long_sub_unchecked(nr_pages, &mce_bad_pages);
+ freeit = 1;
+ if (PageHuge(page))
+ clear_page_hwpoison_huge_page(page);
+@@ -1353,7 +1353,7 @@ static int soft_offline_huge_page(struct
+ }
+ done:
+ if (!PageHWPoison(hpage))
+- atomic_long_add(1 << compound_trans_order(hpage), &mce_bad_pages);
++ atomic_long_add_unchecked(1 << compound_trans_order(hpage), &mce_bad_pages);
+ set_page_hwpoison_huge_page(hpage);
+ dequeue_hwpoisoned_huge_page(hpage);
+ /* keep elevated page count for bad page */
+@@ -1482,7 +1482,7 @@ int soft_offline_page(struct page *page,
+ return ret;
+
+ done:
+- atomic_long_add(1, &mce_bad_pages);
++ atomic_long_add_unchecked(1, &mce_bad_pages);
+ SetPageHWPoison(page);
+ /* keep elevated page count for bad page */
+ return ret;
+diff -urNp linux-2.6.38.7/mm/mempolicy.c linux-2.6.38.7/mm/mempolicy.c
+--- linux-2.6.38.7/mm/mempolicy.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/mempolicy.c 2011-04-28 19:34:15.000000000 -0400
+@@ -643,6 +643,10 @@ static int mbind_range(struct mm_struct
+ unsigned long vmstart;
+ unsigned long vmend;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m;
++#endif
++
+ vma = find_vma_prev(mm, start, &prev);
+ if (!vma || vma->vm_start > start)
+ return -EFAULT;
+@@ -673,6 +677,16 @@ static int mbind_range(struct mm_struct
+ err = policy_vma(vma, new_pol);
+ if (err)
+ goto out;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ vma_m = pax_find_mirror_vma(vma);
++ if (vma_m) {
++ err = policy_vma(vma_m, new_pol);
++ if (err)
++ goto out;
++ }
++#endif
++
+ }
+
+ out:
+@@ -1106,6 +1120,17 @@ static long do_mbind(unsigned long start
+
+ if (end < start)
+ return -EINVAL;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) {
++ if (end > SEGMEXEC_TASK_SIZE)
++ return -EINVAL;
++ } else
++#endif
++
++ if (end > TASK_SIZE)
++ return -EINVAL;
++
+ if (end == start)
+ return 0;
+
+@@ -1324,6 +1349,14 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pi
+ if (!mm)
+ goto out;
+
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ if (mm != current->mm &&
++ (mm->pax_flags & MF_PAX_RANDMMAP || mm->pax_flags & MF_PAX_SEGMEXEC)) {
++ err = -EPERM;
++ goto out;
++ }
++#endif
++
+ /*
+ * Check if this process has the right to modify the specified
+ * process. The right exists if the process has administrative
+@@ -1333,8 +1366,7 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pi
+ rcu_read_lock();
+ tcred = __task_cred(task);
+ if (cred->euid != tcred->suid && cred->euid != tcred->uid &&
+- cred->uid != tcred->suid && cred->uid != tcred->uid &&
+- !capable(CAP_SYS_NICE)) {
++ cred->uid != tcred->suid && !capable(CAP_SYS_NICE)) {
+ rcu_read_unlock();
+ err = -EPERM;
+ goto out;
+@@ -2635,7 +2667,7 @@ int show_numa_map(struct seq_file *m, vo
+
+ if (file) {
+ seq_printf(m, " file=");
+- seq_path(m, &file->f_path, "\n\t= ");
++ seq_path(m, &file->f_path, "\n\t\\= ");
+ } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
+ seq_printf(m, " heap");
+ } else if (vma->vm_start <= mm->start_stack &&
+diff -urNp linux-2.6.38.7/mm/migrate.c linux-2.6.38.7/mm/migrate.c
+--- linux-2.6.38.7/mm/migrate.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/migrate.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1115,6 +1115,8 @@ static int do_pages_move(struct mm_struc
+ unsigned long chunk_start;
+ int err;
+
++ pax_track_stack();
++
+ task_nodes = cpuset_mems_allowed(task);
+
+ err = -ENOMEM;
+@@ -1299,6 +1301,14 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid,
+ if (!mm)
+ return -EINVAL;
+
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
++ if (mm != current->mm &&
++ (mm->pax_flags & MF_PAX_RANDMMAP || mm->pax_flags & MF_PAX_SEGMEXEC)) {
++ err = -EPERM;
++ goto out;
++ }
++#endif
++
+ /*
+ * Check if this process has the right to modify the specified
+ * process. The right exists if the process has administrative
+@@ -1308,8 +1318,7 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid,
+ rcu_read_lock();
+ tcred = __task_cred(task);
+ if (cred->euid != tcred->suid && cred->euid != tcred->uid &&
+- cred->uid != tcred->suid && cred->uid != tcred->uid &&
+- !capable(CAP_SYS_NICE)) {
++ cred->uid != tcred->suid && !capable(CAP_SYS_NICE)) {
+ rcu_read_unlock();
+ err = -EPERM;
+ goto out;
+diff -urNp linux-2.6.38.7/mm/mlock.c linux-2.6.38.7/mm/mlock.c
+--- linux-2.6.38.7/mm/mlock.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/mm/mlock.c 2011-05-10 22:09:01.000000000 -0400
+@@ -13,6 +13,7 @@
+ #include <linux/pagemap.h>
+ #include <linux/mempolicy.h>
+ #include <linux/syscalls.h>
++#include <linux/security.h>
+ #include <linux/sched.h>
+ #include <linux/module.h>
+ #include <linux/rmap.h>
+@@ -377,6 +378,9 @@ static int do_mlock(unsigned long start,
+ return -EINVAL;
+ if (end == start)
+ return 0;
++ if (end > TASK_SIZE)
++ return -EINVAL;
++
+ vma = find_vma_prev(current->mm, start, &prev);
+ if (!vma || vma->vm_start > start)
+ return -ENOMEM;
+@@ -387,6 +391,11 @@ static int do_mlock(unsigned long start,
+ for (nstart = start ; ; ) {
+ unsigned int newflags;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_start >= SEGMEXEC_TASK_SIZE))
++ break;
++#endif
++
+ /* Here we know that vma->vm_start <= nstart < vma->vm_end. */
+
+ newflags = vma->vm_flags | VM_LOCKED;
+@@ -492,6 +501,7 @@ SYSCALL_DEFINE2(mlock, unsigned long, st
+ lock_limit >>= PAGE_SHIFT;
+
+ /* check against resource limits */
++ gr_learn_resource(current, RLIMIT_MEMLOCK, (current->mm->locked_vm << PAGE_SHIFT) + len, 1);
+ if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
+ error = do_mlock(start, len, 1);
+ up_write(&current->mm->mmap_sem);
+@@ -515,17 +525,23 @@ SYSCALL_DEFINE2(munlock, unsigned long,
+ static int do_mlockall(int flags)
+ {
+ struct vm_area_struct * vma, * prev = NULL;
+- unsigned int def_flags = 0;
+
+ if (flags & MCL_FUTURE)
+- def_flags = VM_LOCKED;
+- current->mm->def_flags = def_flags;
++ current->mm->def_flags |= VM_LOCKED;
++ else
++ current->mm->def_flags &= ~VM_LOCKED;
+ if (flags == MCL_FUTURE)
+ goto out;
+
+ for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
+- unsigned int newflags;
++ unsigned long newflags;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_start >= SEGMEXEC_TASK_SIZE))
++ break;
++#endif
+
++ BUG_ON(vma->vm_end > TASK_SIZE);
+ newflags = vma->vm_flags | VM_LOCKED;
+ if (!(flags & MCL_CURRENT))
+ newflags &= ~VM_LOCKED;
+@@ -557,6 +573,7 @@ SYSCALL_DEFINE1(mlockall, int, flags)
+ lock_limit >>= PAGE_SHIFT;
+
+ ret = -ENOMEM;
++ gr_learn_resource(current, RLIMIT_MEMLOCK, current->mm->total_vm << PAGE_SHIFT, 1);
+ if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
+ capable(CAP_IPC_LOCK))
+ ret = do_mlockall(flags);
+diff -urNp linux-2.6.38.7/mm/mmap.c linux-2.6.38.7/mm/mmap.c
+--- linux-2.6.38.7/mm/mmap.c 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/mm/mmap.c 2011-05-22 23:06:04.000000000 -0400
+@@ -46,6 +46,16 @@
+ #define arch_rebalance_pgtables(addr, len) (addr)
+ #endif
+
++static inline void verify_mm_writelocked(struct mm_struct *mm)
++{
++#if defined(CONFIG_DEBUG_VM) || defined(CONFIG_PAX)
++ if (unlikely(down_read_trylock(&mm->mmap_sem))) {
++ up_read(&mm->mmap_sem);
++ BUG();
++ }
++#endif
++}
++
+ static void unmap_region(struct mm_struct *mm,
+ struct vm_area_struct *vma, struct vm_area_struct *prev,
+ unsigned long start, unsigned long end);
+@@ -71,22 +81,32 @@ static void unmap_region(struct mm_struc
+ * x: (no) no x: (no) yes x: (no) yes x: (yes) yes
+ *
+ */
+-pgprot_t protection_map[16] = {
++pgprot_t protection_map[16] __read_only = {
+ __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111,
+ __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
+ };
+
+ pgprot_t vm_get_page_prot(unsigned long vm_flags)
+ {
+- return __pgprot(pgprot_val(protection_map[vm_flags &
++ pgprot_t prot = __pgprot(pgprot_val(protection_map[vm_flags &
+ (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]) |
+ pgprot_val(arch_vm_get_page_prot(vm_flags)));
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
++ if (!(__supported_pte_mask & _PAGE_NX) &&
++ (vm_flags & (VM_PAGEEXEC | VM_EXEC)) == VM_PAGEEXEC &&
++ (vm_flags & (VM_READ | VM_WRITE)))
++ prot = __pgprot(pte_val(pte_exprotect(__pte(pgprot_val(prot)))));
++#endif
++
++ return prot;
+ }
+ EXPORT_SYMBOL(vm_get_page_prot);
+
+ int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
+ int sysctl_overcommit_ratio = 50; /* default is 50% */
+ int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
++unsigned long sysctl_heap_stack_gap __read_mostly = 64*1024;
+ struct percpu_counter vm_committed_as;
+
+ /*
+@@ -232,6 +252,7 @@ static struct vm_area_struct *remove_vma
+ struct vm_area_struct *next = vma->vm_next;
+
+ might_sleep();
++ BUG_ON(vma->vm_mirror);
+ if (vma->vm_ops && vma->vm_ops->close)
+ vma->vm_ops->close(vma);
+ if (vma->vm_file) {
+@@ -276,6 +297,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
+ * not page aligned -Ram Gupta
+ */
+ rlim = rlimit(RLIMIT_DATA);
++ gr_learn_resource(current, RLIMIT_DATA, (brk - mm->start_brk) + (mm->end_data - mm->start_data), 1);
+ if (rlim < RLIM_INFINITY && (brk - mm->start_brk) +
+ (mm->end_data - mm->start_data) > rlim)
+ goto out;
+@@ -719,6 +741,12 @@ static int
+ can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags,
+ struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff)
+ {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_start == SEGMEXEC_TASK_SIZE)
++ return 0;
++#endif
++
+ if (is_mergeable_vma(vma, file, vm_flags) &&
+ is_mergeable_anon_vma(anon_vma, vma->anon_vma)) {
+ if (vma->vm_pgoff == vm_pgoff)
+@@ -738,6 +766,12 @@ static int
+ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
+ struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff)
+ {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_end == SEGMEXEC_TASK_SIZE)
++ return 0;
++#endif
++
+ if (is_mergeable_vma(vma, file, vm_flags) &&
+ is_mergeable_anon_vma(anon_vma, vma->anon_vma)) {
+ pgoff_t vm_pglen;
+@@ -780,13 +814,20 @@ can_vma_merge_after(struct vm_area_struc
+ struct vm_area_struct *vma_merge(struct mm_struct *mm,
+ struct vm_area_struct *prev, unsigned long addr,
+ unsigned long end, unsigned long vm_flags,
+- struct anon_vma *anon_vma, struct file *file,
++ struct anon_vma *anon_vma, struct file *file,
+ pgoff_t pgoff, struct mempolicy *policy)
+ {
+ pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
+ struct vm_area_struct *area, *next;
+ int err;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ unsigned long addr_m = addr + SEGMEXEC_TASK_SIZE, end_m = end + SEGMEXEC_TASK_SIZE;
++ struct vm_area_struct *area_m = NULL, *next_m = NULL, *prev_m = NULL;
++
++ BUG_ON((mm->pax_flags & MF_PAX_SEGMEXEC) && SEGMEXEC_TASK_SIZE < end);
++#endif
++
+ /*
+ * We later require that vma->vm_flags == vm_flags,
+ * so this tests vma->vm_flags & VM_SPECIAL, too.
+@@ -802,6 +843,15 @@ struct vm_area_struct *vma_merge(struct
+ if (next && next->vm_end == end) /* cases 6, 7, 8 */
+ next = next->vm_next;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (prev)
++ prev_m = pax_find_mirror_vma(prev);
++ if (area)
++ area_m = pax_find_mirror_vma(area);
++ if (next)
++ next_m = pax_find_mirror_vma(next);
++#endif
++
+ /*
+ * Can it merge with the predecessor?
+ */
+@@ -821,9 +871,24 @@ struct vm_area_struct *vma_merge(struct
+ /* cases 1, 6 */
+ err = vma_adjust(prev, prev->vm_start,
+ next->vm_end, prev->vm_pgoff, NULL);
+- } else /* cases 2, 5, 7 */
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (!err && prev_m)
++ err = vma_adjust(prev_m, prev_m->vm_start,
++ next_m->vm_end, prev_m->vm_pgoff, NULL);
++#endif
++
++ } else { /* cases 2, 5, 7 */
+ err = vma_adjust(prev, prev->vm_start,
+ end, prev->vm_pgoff, NULL);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (!err && prev_m)
++ err = vma_adjust(prev_m, prev_m->vm_start,
++ end_m, prev_m->vm_pgoff, NULL);
++#endif
++
++ }
+ if (err)
+ return NULL;
+ khugepaged_enter_vma_merge(prev);
+@@ -837,12 +902,27 @@ struct vm_area_struct *vma_merge(struct
+ mpol_equal(policy, vma_policy(next)) &&
+ can_vma_merge_before(next, vm_flags,
+ anon_vma, file, pgoff+pglen)) {
+- if (prev && addr < prev->vm_end) /* case 4 */
++ if (prev && addr < prev->vm_end) { /* case 4 */
+ err = vma_adjust(prev, prev->vm_start,
+ addr, prev->vm_pgoff, NULL);
+- else /* cases 3, 8 */
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (!err && prev_m)
++ err = vma_adjust(prev_m, prev_m->vm_start,
++ addr_m, prev_m->vm_pgoff, NULL);
++#endif
++
++ } else { /* cases 3, 8 */
+ err = vma_adjust(area, addr, next->vm_end,
+ next->vm_pgoff - pglen, NULL);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (!err && area_m)
++ err = vma_adjust(area_m, addr_m, next_m->vm_end,
++ next_m->vm_pgoff - pglen, NULL);
++#endif
++
++ }
+ if (err)
+ return NULL;
+ khugepaged_enter_vma_merge(area);
+@@ -958,14 +1038,11 @@ none:
+ void vm_stat_account(struct mm_struct *mm, unsigned long flags,
+ struct file *file, long pages)
+ {
+- const unsigned long stack_flags
+- = VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN);
+-
+ if (file) {
+ mm->shared_vm += pages;
+ if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC)
+ mm->exec_vm += pages;
+- } else if (flags & stack_flags)
++ } else if (flags & (VM_GROWSUP|VM_GROWSDOWN))
+ mm->stack_vm += pages;
+ if (flags & (VM_RESERVED|VM_IO))
+ mm->reserved_vm += pages;
+@@ -992,7 +1069,7 @@ unsigned long do_mmap_pgoff(struct file
+ * (the exception is when the underlying filesystem is noexec
+ * mounted, in which case we dont add PROT_EXEC.)
+ */
+- if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
++ if ((prot & (PROT_READ | PROT_WRITE)) && (current->personality & READ_IMPLIES_EXEC))
+ if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC)))
+ prot |= PROT_EXEC;
+
+@@ -1018,7 +1095,7 @@ unsigned long do_mmap_pgoff(struct file
+ /* Obtain the address to map to. we verify (or select) it and ensure
+ * that it represents a valid section of the address space.
+ */
+- addr = get_unmapped_area(file, addr, len, pgoff, flags);
++ addr = get_unmapped_area(file, addr, len, pgoff, flags | ((prot & PROT_EXEC) ? MAP_EXECUTABLE : 0));
+ if (addr & ~PAGE_MASK)
+ return addr;
+
+@@ -1029,6 +1106,36 @@ unsigned long do_mmap_pgoff(struct file
+ vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
+ mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+
++#ifdef CONFIG_PAX_MPROTECT
++ if (mm->pax_flags & MF_PAX_MPROTECT) {
++#ifndef CONFIG_PAX_MPROTECT_COMPAT
++ if ((vm_flags & (VM_WRITE | VM_EXEC)) == (VM_WRITE | VM_EXEC)) {
++ gr_log_rwxmmap(file);
++
++#ifdef CONFIG_PAX_EMUPLT
++ vm_flags &= ~VM_EXEC;
++#else
++ return -EPERM;
++#endif
++
++ }
++
++ if (!(vm_flags & VM_EXEC))
++ vm_flags &= ~VM_MAYEXEC;
++#else
++ if ((vm_flags & (VM_WRITE | VM_EXEC)) != VM_EXEC)
++ vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
++#endif
++ else
++ vm_flags &= ~VM_MAYWRITE;
++ }
++#endif
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && file)
++ vm_flags &= ~VM_PAGEEXEC;
++#endif
++
+ if (flags & MAP_LOCKED)
+ if (!can_do_mlock())
+ return -EPERM;
+@@ -1040,6 +1147,7 @@ unsigned long do_mmap_pgoff(struct file
+ locked += mm->locked_vm;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
+ lock_limit >>= PAGE_SHIFT;
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
+ if (locked > lock_limit && !capable(CAP_IPC_LOCK))
+ return -EAGAIN;
+ }
+@@ -1110,6 +1218,9 @@ unsigned long do_mmap_pgoff(struct file
+ if (error)
+ return error;
+
++ if (!gr_acl_handle_mmap(file, prot))
++ return -EACCES;
++
+ return mmap_region(file, addr, len, flags, vm_flags, pgoff);
+ }
+ EXPORT_SYMBOL(do_mmap_pgoff);
+@@ -1187,10 +1298,10 @@ SYSCALL_DEFINE1(old_mmap, struct mmap_ar
+ */
+ int vma_wants_writenotify(struct vm_area_struct *vma)
+ {
+- unsigned int vm_flags = vma->vm_flags;
++ unsigned long vm_flags = vma->vm_flags;
+
+ /* If it was private or non-writable, the write bit is already clear */
+- if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED)))
++ if ((vm_flags & (VM_WRITE|VM_SHARED)) != (VM_WRITE|VM_SHARED))
+ return 0;
+
+ /* The backer wishes to know when pages are first written to? */
+@@ -1239,14 +1350,24 @@ unsigned long mmap_region(struct file *f
+ unsigned long charged = 0;
+ struct inode *inode = file ? file->f_path.dentry->d_inode : NULL;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m = NULL;
++#endif
++
++ /*
++ * mm->mmap_sem is required to protect against another thread
++ * changing the mappings in case we sleep.
++ */
++ verify_mm_writelocked(mm);
++
+ /* Clear old maps */
+ error = -ENOMEM;
+-munmap_back:
+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
+ if (vma && vma->vm_start < addr + len) {
+ if (do_munmap(mm, addr, len))
+ return -ENOMEM;
+- goto munmap_back;
++ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
++ BUG_ON(vma && vma->vm_start < addr + len);
+ }
+
+ /* Check against address space limit. */
+@@ -1295,6 +1416,16 @@ munmap_back:
+ goto unacct_error;
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (vm_flags & VM_EXEC)) {
++ vma_m = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
++ if (!vma_m) {
++ error = -ENOMEM;
++ goto free_vma;
++ }
++ }
++#endif
++
+ vma->vm_mm = mm;
+ vma->vm_start = addr;
+ vma->vm_end = addr + len;
+@@ -1318,6 +1449,19 @@ munmap_back:
+ error = file->f_op->mmap(file, vma);
+ if (error)
+ goto unmap_and_free_vma;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma_m && (vm_flags & VM_EXECUTABLE))
++ added_exe_file_vma(mm);
++#endif
++
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_SPECIAL)) {
++ vma->vm_flags |= VM_PAGEEXEC;
++ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
++ }
++#endif
++
+ if (vm_flags & VM_EXECUTABLE)
+ added_exe_file_vma(mm);
+
+@@ -1353,6 +1497,11 @@ munmap_back:
+ vma_link(mm, vma, prev, rb_link, rb_parent);
+ file = vma->vm_file;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma_m)
++ BUG_ON(pax_mirror_vma(vma_m, vma));
++#endif
++
+ /* Once vma denies write, undo our temporary denial count */
+ if (correct_wcount)
+ atomic_inc(&inode->i_writecount);
+@@ -1361,6 +1510,7 @@ out:
+
+ mm->total_vm += len >> PAGE_SHIFT;
+ vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
++ track_exec_limit(mm, addr, addr + len, vm_flags);
+ if (vm_flags & VM_LOCKED) {
+ if (!mlock_vma_pages_range(vma, addr, addr + len))
+ mm->locked_vm += (len >> PAGE_SHIFT);
+@@ -1378,6 +1528,12 @@ unmap_and_free_vma:
+ unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
+ charged = 0;
+ free_vma:
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma_m)
++ kmem_cache_free(vm_area_cachep, vma_m);
++#endif
++
+ kmem_cache_free(vm_area_cachep, vma);
+ unacct_error:
+ if (charged)
+@@ -1385,6 +1541,44 @@ unacct_error:
+ return error;
+ }
+
++bool check_heap_stack_gap(const struct vm_area_struct *vma, unsigned long addr, unsigned long len)
++{
++ if (!vma) {
++#ifdef CONFIG_STACK_GROWSUP
++ if (addr > sysctl_heap_stack_gap)
++ vma = find_vma(current->mm, addr - sysctl_heap_stack_gap);
++ else
++ vma = find_vma(current->mm, 0);
++ if (vma && (vma->vm_flags & VM_GROWSUP))
++ return false;
++#endif
++ return true;
++ }
++
++ if (addr + len > vma->vm_start)
++ return false;
++
++ if (vma->vm_flags & VM_GROWSDOWN)
++ return sysctl_heap_stack_gap <= vma->vm_start - addr - len;
++#ifdef CONFIG_STACK_GROWSUP
++ else if (vma->vm_prev && (vma->vm_prev->vm_flags & VM_GROWSUP))
++ return addr - vma->vm_prev->vm_end <= sysctl_heap_stack_gap;
++#endif
++
++ return true;
++}
++
++unsigned long skip_heap_stack_gap(const struct vm_area_struct *vma, unsigned long len)
++{
++ if (vma->vm_start < len)
++ return -ENOMEM;
++ if (!(vma->vm_flags & VM_GROWSDOWN))
++ return vma->vm_start - len;
++ if (sysctl_heap_stack_gap <= vma->vm_start - len)
++ return vma->vm_start - len - sysctl_heap_stack_gap;
++ return -ENOMEM;
++}
++
+ /* Get an address range which is currently unmapped.
+ * For shmat() with addr=0.
+ *
+@@ -1411,18 +1605,23 @@ arch_get_unmapped_area(struct file *filp
+ if (flags & MAP_FIXED)
+ return addr;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ if (addr) {
+ addr = PAGE_ALIGN(addr);
+- vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
+- return addr;
++ if (TASK_SIZE - len >= addr) {
++ vma = find_vma(mm, addr);
++ if (check_heap_stack_gap(vma, addr, len))
++ return addr;
++ }
+ }
+ if (len > mm->cached_hole_size) {
+- start_addr = addr = mm->free_area_cache;
++ start_addr = addr = mm->free_area_cache;
+ } else {
+- start_addr = addr = TASK_UNMAPPED_BASE;
+- mm->cached_hole_size = 0;
++ start_addr = addr = mm->mmap_base;
++ mm->cached_hole_size = 0;
+ }
+
+ full_search:
+@@ -1433,34 +1632,40 @@ full_search:
+ * Start a new search - just in case we missed
+ * some holes.
+ */
+- if (start_addr != TASK_UNMAPPED_BASE) {
+- addr = TASK_UNMAPPED_BASE;
+- start_addr = addr;
++ if (start_addr != mm->mmap_base) {
++ start_addr = addr = mm->mmap_base;
+ mm->cached_hole_size = 0;
+ goto full_search;
+ }
+ return -ENOMEM;
+ }
+- if (!vma || addr + len <= vma->vm_start) {
+- /*
+- * Remember the place where we stopped the search:
+- */
+- mm->free_area_cache = addr + len;
+- return addr;
+- }
++ if (check_heap_stack_gap(vma, addr, len))
++ break;
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
+ addr = vma->vm_end;
+ }
++
++ /*
++ * Remember the place where we stopped the search:
++ */
++ mm->free_area_cache = addr + len;
++ return addr;
+ }
+ #endif
+
+ void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
+ {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && SEGMEXEC_TASK_SIZE <= addr)
++ return;
++#endif
++
+ /*
+ * Is this a new hole at the lowest possible address?
+ */
+- if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) {
++ if (addr >= mm->mmap_base && addr < mm->free_area_cache) {
+ mm->free_area_cache = addr;
+ mm->cached_hole_size = ~0UL;
+ }
+@@ -1478,7 +1683,7 @@ arch_get_unmapped_area_topdown(struct fi
+ {
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+- unsigned long addr = addr0;
++ unsigned long base = mm->mmap_base, addr = addr0;
+
+ /* requested length too big for entire address space */
+ if (len > TASK_SIZE)
+@@ -1487,13 +1692,18 @@ arch_get_unmapped_area_topdown(struct fi
+ if (flags & MAP_FIXED)
+ return addr;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ /* requesting a specific address */
+ if (addr) {
+ addr = PAGE_ALIGN(addr);
+- vma = find_vma(mm, addr);
+- if (TASK_SIZE - len >= addr &&
+- (!vma || addr + len <= vma->vm_start))
+- return addr;
++ if (TASK_SIZE - len >= addr) {
++ vma = find_vma(mm, addr);
++ if (check_heap_stack_gap(vma, addr, len))
++ return addr;
++ }
+ }
+
+ /* check if free_area_cache is useful for us */
+@@ -1508,7 +1718,7 @@ arch_get_unmapped_area_topdown(struct fi
+ /* make sure it can fit in the remaining address space */
+ if (addr > len) {
+ vma = find_vma(mm, addr-len);
+- if (!vma || addr <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr - len, len))
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr-len);
+ }
+@@ -1525,7 +1735,7 @@ arch_get_unmapped_area_topdown(struct fi
+ * return with success:
+ */
+ vma = find_vma(mm, addr);
+- if (!vma || addr+len <= vma->vm_start)
++ if (check_heap_stack_gap(vma, addr, len))
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr);
+
+@@ -1534,8 +1744,8 @@ arch_get_unmapped_area_topdown(struct fi
+ mm->cached_hole_size = vma->vm_start - addr;
+
+ /* try just below the current vma->vm_start */
+- addr = vma->vm_start-len;
+- } while (len < vma->vm_start);
++ addr = skip_heap_stack_gap(vma, len);
++ } while (!IS_ERR_VALUE(addr));
+
+ bottomup:
+ /*
+@@ -1544,13 +1754,21 @@ bottomup:
+ * can happen with large stack limits and large mmap()
+ * allocations.
+ */
++ mm->mmap_base = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
++ mm->free_area_cache = mm->mmap_base;
+ mm->cached_hole_size = ~0UL;
+- mm->free_area_cache = TASK_UNMAPPED_BASE;
+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+ /*
+ * Restore the topdown base:
+ */
+- mm->free_area_cache = mm->mmap_base;
++ mm->mmap_base = base;
++ mm->free_area_cache = base;
+ mm->cached_hole_size = ~0UL;
+
+ return addr;
+@@ -1559,6 +1777,12 @@ bottomup:
+
+ void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr)
+ {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && SEGMEXEC_TASK_SIZE <= addr)
++ return;
++#endif
++
+ /*
+ * Is this a new hole at the highest possible address?
+ */
+@@ -1566,8 +1790,10 @@ void arch_unmap_area_topdown(struct mm_s
+ mm->free_area_cache = addr;
+
+ /* dont allow allocations above current base */
+- if (mm->free_area_cache > mm->mmap_base)
++ if (mm->free_area_cache > mm->mmap_base) {
+ mm->free_area_cache = mm->mmap_base;
++ mm->cached_hole_size = ~0UL;
++ }
+ }
+
+ unsigned long
+@@ -1675,6 +1901,28 @@ out:
+ return prev ? prev->vm_next : vma;
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++struct vm_area_struct *pax_find_mirror_vma(struct vm_area_struct *vma)
++{
++ struct vm_area_struct *vma_m;
++
++ BUG_ON(!vma || vma->vm_start >= vma->vm_end);
++ if (!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) || !(vma->vm_flags & VM_EXEC)) {
++ BUG_ON(vma->vm_mirror);
++ return NULL;
++ }
++ BUG_ON(vma->vm_start < SEGMEXEC_TASK_SIZE && SEGMEXEC_TASK_SIZE < vma->vm_end);
++ vma_m = vma->vm_mirror;
++ BUG_ON(!vma_m || vma_m->vm_mirror != vma);
++ BUG_ON(vma->vm_file != vma_m->vm_file);
++ BUG_ON(vma->vm_end - vma->vm_start != vma_m->vm_end - vma_m->vm_start);
++ BUG_ON(vma->vm_pgoff != vma_m->vm_pgoff);
++ BUG_ON(vma->anon_vma != vma_m->anon_vma && vma->anon_vma->root != vma_m->anon_vma->root);
++ BUG_ON((vma->vm_flags ^ vma_m->vm_flags) & ~(VM_WRITE | VM_MAYWRITE | VM_ACCOUNT | VM_LOCKED | VM_RESERVED));
++ return vma_m;
++}
++#endif
++
+ /*
+ * Verify that the stack growth is acceptable and
+ * update accounting. This is shared with both the
+@@ -1691,6 +1939,7 @@ static int acct_stack_growth(struct vm_a
+ return -ENOMEM;
+
+ /* Stack limit test */
++ gr_learn_resource(current, RLIMIT_STACK, size, 1);
+ if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur))
+ return -ENOMEM;
+
+@@ -1701,6 +1950,7 @@ static int acct_stack_growth(struct vm_a
+ locked = mm->locked_vm + grow;
+ limit = ACCESS_ONCE(rlim[RLIMIT_MEMLOCK].rlim_cur);
+ limit >>= PAGE_SHIFT;
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
+ if (locked > limit && !capable(CAP_IPC_LOCK))
+ return -ENOMEM;
+ }
+@@ -1731,37 +1981,48 @@ static int acct_stack_growth(struct vm_a
+ * PA-RISC uses this for its stack; IA64 for its Register Backing Store.
+ * vma is the last one with address > vma->vm_end. Have to extend vma.
+ */
++#ifndef CONFIG_IA64
++static
++#endif
+ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
+ {
+ int error;
++ bool locknext;
+
+ if (!(vma->vm_flags & VM_GROWSUP))
+ return -EFAULT;
+
++ /* Also guard against wrapping around to address 0. */
++ if (address < PAGE_ALIGN(address+1))
++ address = PAGE_ALIGN(address+1);
++ else
++ return -ENOMEM;
++
+ /*
+ * We must make sure the anon_vma is allocated
+ * so that the anon_vma locking is not a noop.
+ */
+ if (unlikely(anon_vma_prepare(vma)))
+ return -ENOMEM;
++ locknext = vma->vm_next && (vma->vm_next->vm_flags & VM_GROWSDOWN);
++ if (locknext && anon_vma_prepare(vma->vm_next))
++ return -ENOMEM;
+ vma_lock_anon_vma(vma);
++ if (locknext)
++ vma_lock_anon_vma(vma->vm_next);
+
+ /*
+ * vma->vm_start/vm_end cannot change under us because the caller
+ * is required to hold the mmap_sem in read mode. We need the
+- * anon_vma lock to serialize against concurrent expand_stacks.
+- * Also guard against wrapping around to address 0.
++ * anon_vma locks to serialize against concurrent expand_stacks
++ * and expand_upwards.
+ */
+- if (address < PAGE_ALIGN(address+4))
+- address = PAGE_ALIGN(address+4);
+- else {
+- vma_unlock_anon_vma(vma);
+- return -ENOMEM;
+- }
+ error = 0;
+
+ /* Somebody else might have raced and expanded it already */
+- if (address > vma->vm_end) {
++ if (vma->vm_next && (vma->vm_next->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)) && vma->vm_next->vm_start - address < sysctl_heap_stack_gap)
++ error = -ENOMEM;
++ else if (address > vma->vm_end && (!locknext || vma->vm_next->vm_start >= address)) {
+ unsigned long size, grow;
+
+ size = address - vma->vm_start;
+@@ -1776,6 +2037,8 @@ int expand_upwards(struct vm_area_struct
+ }
+ }
+ }
++ if (locknext)
++ vma_unlock_anon_vma(vma->vm_next);
+ vma_unlock_anon_vma(vma);
+ khugepaged_enter_vma_merge(vma);
+ return error;
+@@ -1789,6 +2052,8 @@ static int expand_downwards(struct vm_ar
+ unsigned long address)
+ {
+ int error;
++ bool lockprev = false;
++ struct vm_area_struct *prev;
+
+ /*
+ * We must make sure the anon_vma is allocated
+@@ -1802,6 +2067,15 @@ static int expand_downwards(struct vm_ar
+ if (error)
+ return error;
+
++ prev = vma->vm_prev;
++#if defined(CONFIG_STACK_GROWSUP) || defined(CONFIG_IA64)
++ lockprev = prev && (prev->vm_flags & VM_GROWSUP);
++#endif
++ if (lockprev && anon_vma_prepare(prev))
++ return -ENOMEM;
++ if (lockprev)
++ vma_lock_anon_vma(prev);
++
+ vma_lock_anon_vma(vma);
+
+ /*
+@@ -1811,9 +2085,17 @@ static int expand_downwards(struct vm_ar
+ */
+
+ /* Somebody else might have raced and expanded it already */
+- if (address < vma->vm_start) {
++ if (prev && (prev->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)) && address - prev->vm_end < sysctl_heap_stack_gap)
++ error = -ENOMEM;
++ else if (address < vma->vm_start && (!lockprev || prev->vm_end <= address)) {
+ unsigned long size, grow;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m;
++
++ vma_m = pax_find_mirror_vma(vma);
++#endif
++
+ size = vma->vm_end - address;
+ grow = (vma->vm_start - address) >> PAGE_SHIFT;
+
+@@ -1823,11 +2105,22 @@ static int expand_downwards(struct vm_ar
+ if (!error) {
+ vma->vm_start = address;
+ vma->vm_pgoff -= grow;
++ track_exec_limit(vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_flags);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma_m) {
++ vma_m->vm_start -= grow << PAGE_SHIFT;
++ vma_m->vm_pgoff -= grow;
++ }
++#endif
++
+ perf_event_mmap(vma);
+ }
+ }
+ }
+ vma_unlock_anon_vma(vma);
++ if (lockprev)
++ vma_unlock_anon_vma(prev);
+ khugepaged_enter_vma_merge(vma);
+ return error;
+ }
+@@ -1902,6 +2195,13 @@ static void remove_vma_list(struct mm_st
+ do {
+ long nrpages = vma_pages(vma);
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_start >= SEGMEXEC_TASK_SIZE)) {
++ vma = remove_vma(vma);
++ continue;
++ }
++#endif
++
+ mm->total_vm -= nrpages;
+ vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages);
+ vma = remove_vma(vma);
+@@ -1947,6 +2247,16 @@ detach_vmas_to_be_unmapped(struct mm_str
+ insertion_point = (prev ? &prev->vm_next : &mm->mmap);
+ vma->vm_prev = NULL;
+ do {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma->vm_mirror) {
++ BUG_ON(!vma->vm_mirror->vm_mirror || vma->vm_mirror->vm_mirror != vma);
++ vma->vm_mirror->vm_mirror = NULL;
++ vma->vm_mirror->vm_flags &= ~VM_EXEC;
++ vma->vm_mirror = NULL;
++ }
++#endif
++
+ rb_erase(&vma->vm_rb, &mm->mm_rb);
+ mm->map_count--;
+ tail_vma = vma;
+@@ -1975,14 +2285,33 @@ static int __split_vma(struct mm_struct
+ struct vm_area_struct *new;
+ int err = -ENOMEM;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m, *new_m = NULL;
++ unsigned long addr_m = addr + SEGMEXEC_TASK_SIZE;
++#endif
++
+ if (is_vm_hugetlb_page(vma) && (addr &
+ ~(huge_page_mask(hstate_vma(vma)))))
+ return -EINVAL;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ vma_m = pax_find_mirror_vma(vma);
++#endif
++
+ new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
+ if (!new)
+ goto out_err;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma_m) {
++ new_m = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
++ if (!new_m) {
++ kmem_cache_free(vm_area_cachep, new);
++ goto out_err;
++ }
++ }
++#endif
++
+ /* most fields are the same, copy all, and then fixup */
+ *new = *vma;
+
+@@ -1995,6 +2324,22 @@ static int __split_vma(struct mm_struct
+ new->vm_pgoff += ((addr - vma->vm_start) >> PAGE_SHIFT);
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma_m) {
++ *new_m = *vma_m;
++ INIT_LIST_HEAD(&new_m->anon_vma_chain);
++ new_m->vm_mirror = new;
++ new->vm_mirror = new_m;
++
++ if (new_below)
++ new_m->vm_end = addr_m;
++ else {
++ new_m->vm_start = addr_m;
++ new_m->vm_pgoff += ((addr_m - vma_m->vm_start) >> PAGE_SHIFT);
++ }
++ }
++#endif
++
+ pol = mpol_dup(vma_policy(vma));
+ if (IS_ERR(pol)) {
+ err = PTR_ERR(pol);
+@@ -2020,6 +2365,42 @@ static int __split_vma(struct mm_struct
+ else
+ err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (!err && vma_m) {
++ if (anon_vma_clone(new_m, vma_m))
++ goto out_free_mpol;
++
++ mpol_get(pol);
++ vma_set_policy(new_m, pol);
++
++ if (new_m->vm_file) {
++ get_file(new_m->vm_file);
++ if (vma_m->vm_flags & VM_EXECUTABLE)
++ added_exe_file_vma(mm);
++ }
++
++ if (new_m->vm_ops && new_m->vm_ops->open)
++ new_m->vm_ops->open(new_m);
++
++ if (new_below)
++ err = vma_adjust(vma_m, addr_m, vma_m->vm_end, vma_m->vm_pgoff +
++ ((addr_m - new_m->vm_start) >> PAGE_SHIFT), new_m);
++ else
++ err = vma_adjust(vma_m, vma_m->vm_start, addr_m, vma_m->vm_pgoff, new_m);
++
++ if (err) {
++ if (new_m->vm_ops && new_m->vm_ops->close)
++ new_m->vm_ops->close(new_m);
++ if (new_m->vm_file) {
++ if (vma_m->vm_flags & VM_EXECUTABLE)
++ removed_exe_file_vma(mm);
++ fput(new_m->vm_file);
++ }
++ mpol_put(pol);
++ }
++ }
++#endif
++
+ /* Success. */
+ if (!err)
+ return 0;
+@@ -2032,10 +2413,18 @@ static int __split_vma(struct mm_struct
+ removed_exe_file_vma(mm);
+ fput(new->vm_file);
+ }
+- unlink_anon_vmas(new);
+ out_free_mpol:
+ mpol_put(pol);
+ out_free_vma:
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (new_m) {
++ unlink_anon_vmas(new_m);
++ kmem_cache_free(vm_area_cachep, new_m);
++ }
++#endif
++
++ unlink_anon_vmas(new);
+ kmem_cache_free(vm_area_cachep, new);
+ out_err:
+ return err;
+@@ -2048,6 +2437,15 @@ static int __split_vma(struct mm_struct
+ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long addr, int new_below)
+ {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) {
++ BUG_ON(vma->vm_end > SEGMEXEC_TASK_SIZE);
++ if (mm->map_count >= sysctl_max_map_count-1)
++ return -ENOMEM;
++ } else
++#endif
++
+ if (mm->map_count >= sysctl_max_map_count)
+ return -ENOMEM;
+
+@@ -2059,11 +2457,30 @@ int split_vma(struct mm_struct *mm, stru
+ * work. This now handles partial unmappings.
+ * Jeremy Fitzhardinge <jeremy@goop.org>
+ */
++#ifdef CONFIG_PAX_SEGMEXEC
++int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
++{
++ int ret = __do_munmap(mm, start, len);
++ if (ret || !(mm->pax_flags & MF_PAX_SEGMEXEC))
++ return ret;
++
++ return __do_munmap(mm, start + SEGMEXEC_TASK_SIZE, len);
++}
++
++int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
++#else
+ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
++#endif
+ {
+ unsigned long end;
+ struct vm_area_struct *vma, *prev, *last;
+
++ /*
++ * mm->mmap_sem is required to protect against another thread
++ * changing the mappings in case we sleep.
++ */
++ verify_mm_writelocked(mm);
++
+ if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE-start)
+ return -EINVAL;
+
+@@ -2137,6 +2554,8 @@ int do_munmap(struct mm_struct *mm, unsi
+ /* Fix up all other VM information */
+ remove_vma_list(mm, vma);
+
++ track_exec_limit(mm, start, end, 0UL);
++
+ return 0;
+ }
+
+@@ -2149,22 +2568,18 @@ SYSCALL_DEFINE2(munmap, unsigned long, a
+
+ profile_munmap(addr);
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) &&
++ (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len))
++ return -EINVAL;
++#endif
++
+ down_write(&mm->mmap_sem);
+ ret = do_munmap(mm, addr, len);
+ up_write(&mm->mmap_sem);
+ return ret;
+ }
+
+-static inline void verify_mm_writelocked(struct mm_struct *mm)
+-{
+-#ifdef CONFIG_DEBUG_VM
+- if (unlikely(down_read_trylock(&mm->mmap_sem))) {
+- WARN_ON(1);
+- up_read(&mm->mmap_sem);
+- }
+-#endif
+-}
+-
+ /*
+ * this is really a simplified "do_mmap". it only handles
+ * anonymous maps. eventually we may be able to do some
+@@ -2178,6 +2593,7 @@ unsigned long do_brk(unsigned long addr,
+ struct rb_node ** rb_link, * rb_parent;
+ pgoff_t pgoff = addr >> PAGE_SHIFT;
+ int error;
++ unsigned long charged;
+
+ len = PAGE_ALIGN(len);
+ if (!len)
+@@ -2189,16 +2605,30 @@ unsigned long do_brk(unsigned long addr,
+
+ flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
+
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
++ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
++ flags &= ~VM_EXEC;
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (mm->pax_flags & MF_PAX_MPROTECT)
++ flags &= ~VM_MAYEXEC;
++#endif
++
++ }
++#endif
++
+ error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED);
+ if (error & ~PAGE_MASK)
+ return error;
+
++ charged = len >> PAGE_SHIFT;
++
+ /*
+ * mlock MCL_FUTURE?
+ */
+ if (mm->def_flags & VM_LOCKED) {
+ unsigned long locked, lock_limit;
+- locked = len >> PAGE_SHIFT;
++ locked = charged;
+ locked += mm->locked_vm;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
+ lock_limit >>= PAGE_SHIFT;
+@@ -2215,22 +2645,22 @@ unsigned long do_brk(unsigned long addr,
+ /*
+ * Clear old maps. this also does some error checking for us
+ */
+- munmap_back:
+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
+ if (vma && vma->vm_start < addr + len) {
+ if (do_munmap(mm, addr, len))
+ return -ENOMEM;
+- goto munmap_back;
++ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
++ BUG_ON(vma && vma->vm_start < addr + len);
+ }
+
+ /* Check against address space limits *after* clearing old maps... */
+- if (!may_expand_vm(mm, len >> PAGE_SHIFT))
++ if (!may_expand_vm(mm, charged))
+ return -ENOMEM;
+
+ if (mm->map_count > sysctl_max_map_count)
+ return -ENOMEM;
+
+- if (security_vm_enough_memory(len >> PAGE_SHIFT))
++ if (security_vm_enough_memory(charged))
+ return -ENOMEM;
+
+ /* Can we just expand an old private anonymous mapping? */
+@@ -2244,7 +2674,7 @@ unsigned long do_brk(unsigned long addr,
+ */
+ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
+ if (!vma) {
+- vm_unacct_memory(len >> PAGE_SHIFT);
++ vm_unacct_memory(charged);
+ return -ENOMEM;
+ }
+
+@@ -2258,11 +2688,12 @@ unsigned long do_brk(unsigned long addr,
+ vma_link(mm, vma, prev, rb_link, rb_parent);
+ out:
+ perf_event_mmap(vma);
+- mm->total_vm += len >> PAGE_SHIFT;
++ mm->total_vm += charged;
+ if (flags & VM_LOCKED) {
+ if (!mlock_vma_pages_range(vma, addr, addr + len))
+- mm->locked_vm += (len >> PAGE_SHIFT);
++ mm->locked_vm += charged;
+ }
++ track_exec_limit(mm, addr, addr + len, flags);
+ return addr;
+ }
+
+@@ -2309,8 +2740,10 @@ void exit_mmap(struct mm_struct *mm)
+ * Walk the list again, actually closing and freeing it,
+ * with preemption enabled, without holding any MM locks.
+ */
+- while (vma)
++ while (vma) {
++ vma->vm_mirror = NULL;
+ vma = remove_vma(vma);
++ }
+
+ BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT);
+ }
+@@ -2324,6 +2757,13 @@ int insert_vm_struct(struct mm_struct *
+ struct vm_area_struct * __vma, * prev;
+ struct rb_node ** rb_link, * rb_parent;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m = NULL;
++#endif
++
++ if (security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1))
++ return -EPERM;
++
+ /*
+ * The vm_pgoff of a purely anonymous vma should be irrelevant
+ * until its first write fault, when page's anon_vma and index
+@@ -2346,7 +2786,22 @@ int insert_vm_struct(struct mm_struct *
+ if ((vma->vm_flags & VM_ACCOUNT) &&
+ security_vm_enough_memory_mm(mm, vma_pages(vma)))
+ return -ENOMEM;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_flags & VM_EXEC)) {
++ vma_m = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
++ if (!vma_m)
++ return -ENOMEM;
++ }
++#endif
++
+ vma_link(mm, vma, prev, rb_link, rb_parent);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (vma_m)
++ BUG_ON(pax_mirror_vma(vma_m, vma));
++#endif
++
+ return 0;
+ }
+
+@@ -2364,6 +2819,8 @@ struct vm_area_struct *copy_vma(struct v
+ struct rb_node **rb_link, *rb_parent;
+ struct mempolicy *pol;
+
++ BUG_ON(vma->vm_mirror);
++
+ /*
+ * If anonymous vma has not yet been faulted, update new pgoff
+ * to match new location, to increase its chance of merging.
+@@ -2413,6 +2870,39 @@ struct vm_area_struct *copy_vma(struct v
+ kmem_cache_free(vm_area_cachep, new_vma);
+ return NULL;
+ }
++
++#ifdef CONFIG_PAX_SEGMEXEC
++long pax_mirror_vma(struct vm_area_struct *vma_m, struct vm_area_struct *vma)
++{
++ struct vm_area_struct *prev_m;
++ struct rb_node **rb_link_m, *rb_parent_m;
++ struct mempolicy *pol_m;
++
++ BUG_ON(!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) || !(vma->vm_flags & VM_EXEC));
++ BUG_ON(vma->vm_mirror || vma_m->vm_mirror);
++ BUG_ON(!mpol_equal(vma_policy(vma), vma_policy(vma_m)));
++ *vma_m = *vma;
++ INIT_LIST_HEAD(&vma_m->anon_vma_chain);
++ if (anon_vma_clone(vma_m, vma))
++ return -ENOMEM;
++ pol_m = vma_policy(vma_m);
++ mpol_get(pol_m);
++ vma_set_policy(vma_m, pol_m);
++ vma_m->vm_start += SEGMEXEC_TASK_SIZE;
++ vma_m->vm_end += SEGMEXEC_TASK_SIZE;
++ vma_m->vm_flags &= ~(VM_WRITE | VM_MAYWRITE | VM_ACCOUNT | VM_LOCKED);
++ vma_m->vm_page_prot = vm_get_page_prot(vma_m->vm_flags);
++ if (vma_m->vm_file)
++ get_file(vma_m->vm_file);
++ if (vma_m->vm_ops && vma_m->vm_ops->open)
++ vma_m->vm_ops->open(vma_m);
++ find_vma_prepare(vma->vm_mm, vma_m->vm_start, &prev_m, &rb_link_m, &rb_parent_m);
++ vma_link(vma->vm_mm, vma_m, prev_m, rb_link_m, rb_parent_m);
++ vma_m->vm_mirror = vma;
++ vma->vm_mirror = vma_m;
++ return 0;
++}
++#endif
+
+ /*
+ * Return true if the calling process may expand its vm space by the passed
+@@ -2424,7 +2914,7 @@ int may_expand_vm(struct mm_struct *mm,
+ unsigned long lim;
+
+ lim = rlimit(RLIMIT_AS) >> PAGE_SHIFT;
+-
++ gr_learn_resource(current, RLIMIT_AS, (cur + npages) << PAGE_SHIFT, 1);
+ if (cur + npages > lim)
+ return 0;
+ return 1;
+@@ -2495,6 +2985,22 @@ int install_special_mapping(struct mm_st
+ vma->vm_start = addr;
+ vma->vm_end = addr + len;
+
++#ifdef CONFIG_PAX_MPROTECT
++ if (mm->pax_flags & MF_PAX_MPROTECT) {
++#ifndef CONFIG_PAX_MPROTECT_COMPAT
++ if ((vm_flags & (VM_WRITE | VM_EXEC)) == (VM_WRITE | VM_EXEC))
++ return -EPERM;
++ if (!(vm_flags & VM_EXEC))
++ vm_flags &= ~VM_MAYEXEC;
++#else
++ if ((vm_flags & (VM_WRITE | VM_EXEC)) != VM_EXEC)
++ vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
++#endif
++ else
++ vm_flags &= ~VM_MAYWRITE;
++ }
++#endif
++
+ vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND;
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+
+diff -urNp linux-2.6.38.7/mm/mprotect.c linux-2.6.38.7/mm/mprotect.c
+--- linux-2.6.38.7/mm/mprotect.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/mprotect.c 2011-04-28 19:34:15.000000000 -0400
+@@ -23,10 +23,16 @@
+ #include <linux/mmu_notifier.h>
+ #include <linux/migrate.h>
+ #include <linux/perf_event.h>
++
++#ifdef CONFIG_PAX_MPROTECT
++#include <linux/elf.h>
++#endif
++
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/cacheflush.h>
+ #include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
+
+ #ifndef pgprot_modify
+ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
+@@ -141,6 +147,48 @@ static void change_protection(struct vm_
+ flush_tlb_range(vma, start, end);
+ }
+
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
++/* called while holding the mmap semaphor for writing except stack expansion */
++void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot)
++{
++ unsigned long oldlimit, newlimit = 0UL;
++
++ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || (__supported_pte_mask & _PAGE_NX))
++ return;
++
++ spin_lock(&mm->page_table_lock);
++ oldlimit = mm->context.user_cs_limit;
++ if ((prot & VM_EXEC) && oldlimit < end)
++ /* USER_CS limit moved up */
++ newlimit = end;
++ else if (!(prot & VM_EXEC) && start < oldlimit && oldlimit <= end)
++ /* USER_CS limit moved down */
++ newlimit = start;
++
++ if (newlimit) {
++ mm->context.user_cs_limit = newlimit;
++
++#ifdef CONFIG_SMP
++ wmb();
++ cpus_clear(mm->context.cpu_user_cs_mask);
++ cpu_set(smp_processor_id(), mm->context.cpu_user_cs_mask);
++#endif
++
++ set_user_cs(mm->context.user_cs_base, mm->context.user_cs_limit, smp_processor_id());
++ }
++ spin_unlock(&mm->page_table_lock);
++ if (newlimit == end) {
++ struct vm_area_struct *vma = find_vma(mm, oldlimit);
++
++ for (; vma && vma->vm_start < end; vma = vma->vm_next)
++ if (is_vm_hugetlb_page(vma))
++ hugetlb_change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot);
++ else
++ change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot, vma_wants_writenotify(vma));
++ }
++}
++#endif
++
+ int
+ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
+ unsigned long start, unsigned long end, unsigned long newflags)
+@@ -153,11 +201,29 @@ mprotect_fixup(struct vm_area_struct *vm
+ int error;
+ int dirty_accountable = 0;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m = NULL;
++ unsigned long start_m, end_m;
++
++ start_m = start + SEGMEXEC_TASK_SIZE;
++ end_m = end + SEGMEXEC_TASK_SIZE;
++#endif
++
+ if (newflags == oldflags) {
+ *pprev = vma;
+ return 0;
+ }
+
++ if (newflags & (VM_READ | VM_WRITE | VM_EXEC)) {
++ struct vm_area_struct *prev = vma->vm_prev, *next = vma->vm_next;
++
++ if (next && (next->vm_flags & VM_GROWSDOWN) && sysctl_heap_stack_gap > next->vm_start - end)
++ return -ENOMEM;
++
++ if (prev && (prev->vm_flags & VM_GROWSUP) && sysctl_heap_stack_gap > start - prev->vm_end)
++ return -ENOMEM;
++ }
++
+ /*
+ * If we make a private mapping writable we increase our commit;
+ * but (without finer accounting) cannot reduce our commit if we
+@@ -174,6 +240,42 @@ mprotect_fixup(struct vm_area_struct *vm
+ }
+ }
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && ((oldflags ^ newflags) & VM_EXEC)) {
++ if (start != vma->vm_start) {
++ error = split_vma(mm, vma, start, 1);
++ if (error)
++ goto fail;
++ BUG_ON(!*pprev || (*pprev)->vm_next == vma);
++ *pprev = (*pprev)->vm_next;
++ }
++
++ if (end != vma->vm_end) {
++ error = split_vma(mm, vma, end, 0);
++ if (error)
++ goto fail;
++ }
++
++ if (pax_find_mirror_vma(vma)) {
++ error = __do_munmap(mm, start_m, end_m - start_m);
++ if (error)
++ goto fail;
++ } else {
++ vma_m = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
++ if (!vma_m) {
++ error = -ENOMEM;
++ goto fail;
++ }
++ vma->vm_flags = newflags;
++ error = pax_mirror_vma(vma_m, vma);
++ if (error) {
++ vma->vm_flags = oldflags;
++ goto fail;
++ }
++ }
++ }
++#endif
++
+ /*
+ * First try to merge with previous and/or next vma.
+ */
+@@ -204,9 +306,21 @@ success:
+ * vm_flags and vm_page_prot are protected by the mmap_sem
+ * held in write mode.
+ */
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (newflags & VM_EXEC) && ((vma->vm_flags ^ newflags) & VM_READ))
++ pax_find_mirror_vma(vma)->vm_flags ^= VM_READ;
++#endif
++
+ vma->vm_flags = newflags;
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (mm->binfmt && mm->binfmt->handle_mprotect)
++ mm->binfmt->handle_mprotect(vma, newflags);
++#endif
++
+ vma->vm_page_prot = pgprot_modify(vma->vm_page_prot,
+- vm_get_page_prot(newflags));
++ vm_get_page_prot(vma->vm_flags));
+
+ if (vma_wants_writenotify(vma)) {
+ vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED);
+@@ -248,6 +362,17 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+ end = start + len;
+ if (end <= start)
+ return -ENOMEM;
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
++ if (end > SEGMEXEC_TASK_SIZE)
++ return -EINVAL;
++ } else
++#endif
++
++ if (end > TASK_SIZE)
++ return -EINVAL;
++
+ if (!arch_validate_prot(prot))
+ return -EINVAL;
+
+@@ -255,7 +380,7 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+ /*
+ * Does the application expect PROT_READ to imply PROT_EXEC:
+ */
+- if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
++ if ((prot & (PROT_READ | PROT_WRITE)) && (current->personality & READ_IMPLIES_EXEC))
+ prot |= PROT_EXEC;
+
+ vm_flags = calc_vm_prot_bits(prot);
+@@ -287,6 +412,11 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+ if (start > vma->vm_start)
+ prev = vma;
+
++#ifdef CONFIG_PAX_MPROTECT
++ if (current->mm->binfmt && current->mm->binfmt->handle_mprotect)
++ current->mm->binfmt->handle_mprotect(vma, vm_flags);
++#endif
++
+ for (nstart = start ; ; ) {
+ unsigned long newflags;
+
+@@ -296,6 +426,14 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+
+ /* newflags >> 4 shift VM_MAY% in place of VM_% */
+ if ((newflags & ~(newflags >> 4)) & (VM_READ | VM_WRITE | VM_EXEC)) {
++ if (prot & (PROT_WRITE | PROT_EXEC))
++ gr_log_rwxmprotect(vma->vm_file);
++
++ error = -EACCES;
++ goto out;
++ }
++
++ if (!gr_acl_handle_mprotect(vma->vm_file, prot)) {
+ error = -EACCES;
+ goto out;
+ }
+@@ -310,6 +448,9 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+ error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
+ if (error)
+ goto out;
++
++ track_exec_limit(current->mm, nstart, tmp, vm_flags);
++
+ nstart = tmp;
+
+ if (nstart < prev->vm_end)
+diff -urNp linux-2.6.38.7/mm/mremap.c linux-2.6.38.7/mm/mremap.c
+--- linux-2.6.38.7/mm/mremap.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/mm/mremap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -114,6 +114,12 @@ static void move_ptes(struct vm_area_str
+ continue;
+ pte = ptep_clear_flush(vma, old_addr, old_pte);
+ pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
++
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
++ if (!(__supported_pte_mask & _PAGE_NX) && (new_vma->vm_flags & (VM_PAGEEXEC | VM_EXEC)) == VM_PAGEEXEC)
++ pte = pte_exprotect(pte);
++#endif
++
+ set_pte_at(mm, new_addr, new_pte, pte);
+ }
+
+@@ -273,6 +279,11 @@ static struct vm_area_struct *vma_to_res
+ if (is_vm_hugetlb_page(vma))
+ goto Einval;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (pax_find_mirror_vma(vma))
++ goto Einval;
++#endif
++
+ /* We can't remap across vm area boundaries */
+ if (old_len > vma->vm_end - addr)
+ goto Efault;
+@@ -329,20 +340,25 @@ static unsigned long mremap_to(unsigned
+ unsigned long ret = -EINVAL;
+ unsigned long charged = 0;
+ unsigned long map_flags;
++ unsigned long pax_task_size = TASK_SIZE;
+
+ if (new_addr & ~PAGE_MASK)
+ goto out;
+
+- if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
++ pax_task_size -= PAGE_SIZE;
++
++ if (new_len > TASK_SIZE || new_addr > pax_task_size - new_len)
+ goto out;
+
+ /* Check if the location we're moving into overlaps the
+ * old location at all, and fail if it does.
+ */
+- if ((new_addr <= addr) && (new_addr+new_len) > addr)
+- goto out;
+-
+- if ((addr <= new_addr) && (addr+old_len) > new_addr)
++ if (addr + old_len > new_addr && new_addr + new_len > addr)
+ goto out;
+
+ ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
+@@ -414,6 +430,7 @@ unsigned long do_mremap(unsigned long ad
+ struct vm_area_struct *vma;
+ unsigned long ret = -EINVAL;
+ unsigned long charged = 0;
++ unsigned long pax_task_size = TASK_SIZE;
+
+ if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
+ goto out;
+@@ -432,6 +449,17 @@ unsigned long do_mremap(unsigned long ad
+ if (!new_len)
+ goto out;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (mm->pax_flags & MF_PAX_SEGMEXEC)
++ pax_task_size = SEGMEXEC_TASK_SIZE;
++#endif
++
++ pax_task_size -= PAGE_SIZE;
++
++ if (new_len > pax_task_size || addr > pax_task_size-new_len ||
++ old_len > pax_task_size || addr > pax_task_size-old_len)
++ goto out;
++
+ if (flags & MREMAP_FIXED) {
+ if (flags & MREMAP_MAYMOVE)
+ ret = mremap_to(addr, old_len, new_addr, new_len);
+@@ -481,6 +509,7 @@ unsigned long do_mremap(unsigned long ad
+ addr + new_len);
+ }
+ ret = addr;
++ track_exec_limit(vma->vm_mm, vma->vm_start, addr + new_len, vma->vm_flags);
+ goto out;
+ }
+ }
+@@ -507,7 +536,13 @@ unsigned long do_mremap(unsigned long ad
+ ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
+ if (ret)
+ goto out;
++
++ map_flags = vma->vm_flags;
+ ret = move_vma(vma, addr, old_len, new_len, new_addr);
++ if (!(ret & ~PAGE_MASK)) {
++ track_exec_limit(current->mm, addr, addr + old_len, 0UL);
++ track_exec_limit(current->mm, new_addr, new_addr + new_len, map_flags);
++ }
+ }
+ out:
+ if (ret & ~PAGE_MASK)
+diff -urNp linux-2.6.38.7/mm/nommu.c linux-2.6.38.7/mm/nommu.c
+--- linux-2.6.38.7/mm/nommu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/nommu.c 2011-04-28 19:34:15.000000000 -0400
+@@ -63,7 +63,6 @@ int sysctl_overcommit_memory = OVERCOMMI
+ int sysctl_overcommit_ratio = 50; /* default is 50% */
+ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
+ int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS;
+-int heap_stack_gap = 0;
+
+ atomic_long_t mmap_pages_allocated;
+
+@@ -833,15 +832,6 @@ struct vm_area_struct *find_vma(struct m
+ EXPORT_SYMBOL(find_vma);
+
+ /*
+- * find a VMA
+- * - we don't extend stack VMAs under NOMMU conditions
+- */
+-struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
+-{
+- return find_vma(mm, addr);
+-}
+-
+-/*
+ * expand a stack to a given address
+ * - not supported under NOMMU conditions
+ */
+@@ -1563,6 +1553,7 @@ int split_vma(struct mm_struct *mm, stru
+
+ /* most fields are the same, copy all, and then fixup */
+ *new = *vma;
++ INIT_LIST_HEAD(&new->anon_vma_chain);
+ *region = *vma->vm_region;
+ new->vm_region = region;
+
+diff -urNp linux-2.6.38.7/mm/page_alloc.c linux-2.6.38.7/mm/page_alloc.c
+--- linux-2.6.38.7/mm/page_alloc.c 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/mm/page_alloc.c 2011-05-22 23:06:04.000000000 -0400
+@@ -644,6 +644,10 @@ static bool free_pages_prepare(struct pa
+ int i;
+ int bad = 0;
+
++#ifdef CONFIG_PAX_MEMORY_SANITIZE
++ unsigned long index = 1UL << order;
++#endif
++
+ trace_mm_page_free_direct(page, order);
+ kmemcheck_free_shadow(page, order);
+
+@@ -659,6 +663,12 @@ static bool free_pages_prepare(struct pa
+ debug_check_no_obj_freed(page_address(page),
+ PAGE_SIZE << order);
+ }
++
++#ifdef CONFIG_PAX_MEMORY_SANITIZE
++ for (; index; --index)
++ sanitize_highpage(page + index - 1);
++#endif
++
+ arch_free_page(page, order);
+ kernel_map_pages(page, 1 << order, 0);
+
+@@ -773,8 +783,10 @@ static int prep_new_page(struct page *pa
+ arch_alloc_page(page, order);
+ kernel_map_pages(page, 1 << order, 1);
+
++#ifndef CONFIG_PAX_MEMORY_SANITIZE
+ if (gfp_flags & __GFP_ZERO)
+ prep_zero_page(page, order, gfp_flags);
++#endif
+
+ if (order && (gfp_flags & __GFP_COMP))
+ prep_compound_page(page, order);
+@@ -2423,6 +2435,8 @@ void show_free_areas(void)
+ int cpu;
+ struct zone *zone;
+
++ pax_track_stack();
++
+ for_each_populated_zone(zone) {
+ show_node(zone);
+ printk("%s per-cpu:\n", zone->name);
+diff -urNp linux-2.6.38.7/mm/percpu.c linux-2.6.38.7/mm/percpu.c
+--- linux-2.6.38.7/mm/percpu.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/percpu.c 2011-04-28 19:34:15.000000000 -0400
+@@ -121,7 +121,7 @@ static unsigned int pcpu_first_unit_cpu
+ static unsigned int pcpu_last_unit_cpu __read_mostly;
+
+ /* the address of the first chunk which starts with the kernel static area */
+-void *pcpu_base_addr __read_mostly;
++void *pcpu_base_addr __read_only;
+ EXPORT_SYMBOL_GPL(pcpu_base_addr);
+
+ static const int *pcpu_unit_map __read_mostly; /* cpu -> unit */
+diff -urNp linux-2.6.38.7/mm/rmap.c linux-2.6.38.7/mm/rmap.c
+--- linux-2.6.38.7/mm/rmap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/rmap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -117,6 +117,10 @@ int anon_vma_prepare(struct vm_area_stru
+ struct anon_vma *anon_vma = vma->anon_vma;
+ struct anon_vma_chain *avc;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct anon_vma_chain *avc_m = NULL;
++#endif
++
+ might_sleep();
+ if (unlikely(!anon_vma)) {
+ struct mm_struct *mm = vma->vm_mm;
+@@ -126,6 +130,12 @@ int anon_vma_prepare(struct vm_area_stru
+ if (!avc)
+ goto out_enomem;
+
++#ifdef CONFIG_PAX_SEGMEXEC
++ avc_m = anon_vma_chain_alloc();
++ if (!avc_m)
++ goto out_enomem_free_avc;
++#endif
++
+ anon_vma = find_mergeable_anon_vma(vma);
+ allocated = NULL;
+ if (!anon_vma) {
+@@ -144,6 +154,21 @@ int anon_vma_prepare(struct vm_area_stru
+ /* page_table_lock to protect against threads */
+ spin_lock(&mm->page_table_lock);
+ if (likely(!vma->anon_vma)) {
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ struct vm_area_struct *vma_m = pax_find_mirror_vma(vma);
++
++ if (vma_m) {
++ BUG_ON(vma_m->anon_vma);
++ vma_m->anon_vma = anon_vma;
++ avc_m->anon_vma = anon_vma;
++ avc_m->vma = vma;
++ list_add(&avc_m->same_vma, &vma_m->anon_vma_chain);
++ list_add(&avc_m->same_anon_vma, &anon_vma->head);
++ avc_m = NULL;
++ }
++#endif
++
+ vma->anon_vma = anon_vma;
+ avc->anon_vma = anon_vma;
+ avc->vma = vma;
+@@ -157,12 +182,24 @@ int anon_vma_prepare(struct vm_area_stru
+
+ if (unlikely(allocated))
+ anon_vma_free(allocated);
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (unlikely(avc_m))
++ anon_vma_chain_free(avc_m);
++#endif
++
+ if (unlikely(avc))
+ anon_vma_chain_free(avc);
+ }
+ return 0;
+
+ out_enomem_free_avc:
++
++#ifdef CONFIG_PAX_SEGMEXEC
++ if (avc_m)
++ anon_vma_chain_free(avc_m);
++#endif
++
+ anon_vma_chain_free(avc);
+ out_enomem:
+ return -ENOMEM;
+@@ -189,7 +226,7 @@ static void anon_vma_chain_link(struct v
+ * Attach the anon_vmas from src to dst.
+ * Returns 0 on success, -ENOMEM on failure.
+ */
+-int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
++int anon_vma_clone(struct vm_area_struct *dst, const struct vm_area_struct *src)
+ {
+ struct anon_vma_chain *avc, *pavc;
+
+@@ -211,7 +248,7 @@ int anon_vma_clone(struct vm_area_struct
+ * the corresponding VMA in the parent process is attached to.
+ * Returns 0 on success, non-zero on failure.
+ */
+-int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
++int anon_vma_fork(struct vm_area_struct *vma, const struct vm_area_struct *pvma)
+ {
+ struct anon_vma_chain *avc;
+ struct anon_vma *anon_vma;
+diff -urNp linux-2.6.38.7/mm/shmem.c linux-2.6.38.7/mm/shmem.c
+--- linux-2.6.38.7/mm/shmem.c 2011-05-22 23:05:20.000000000 -0400
++++ linux-2.6.38.7/mm/shmem.c 2011-05-22 23:06:04.000000000 -0400
+@@ -31,7 +31,7 @@
+ #include <linux/percpu_counter.h>
+ #include <linux/swap.h>
+
+-static struct vfsmount *shm_mnt;
++struct vfsmount *shm_mnt;
+
+ #ifdef CONFIG_SHMEM
+ /*
+@@ -1088,6 +1088,8 @@ static int shmem_writepage(struct page *
+ goto unlock;
+ }
+ entry = shmem_swp_entry(info, index, NULL);
++ if (!entry)
++ goto unlock;
+ if (entry->val) {
+ /*
+ * The more uptodate page coming down from a stacked
+@@ -1160,6 +1162,8 @@ static struct page *shmem_swapin(swp_ent
+ struct vm_area_struct pvma;
+ struct page *page;
+
++ pax_track_stack();
++
+ spol = mpol_cond_copy(&mpol,
+ mpol_shared_policy_lookup(&info->policy, idx));
+
+@@ -2015,7 +2019,7 @@ static int shmem_symlink(struct inode *d
+
+ info = SHMEM_I(inode);
+ inode->i_size = len-1;
+- if (len <= (char *)inode - (char *)info) {
++ if (len <= (char *)inode - (char *)info && len <= 64) {
+ /* do it inline */
+ memcpy(info, symname, len);
+ inode->i_op = &shmem_symlink_inline_operations;
+@@ -2361,8 +2365,7 @@ int shmem_fill_super(struct super_block
+ int err = -ENOMEM;
+
+ /* Round up to L1_CACHE_BYTES to resist false sharing */
+- sbinfo = kzalloc(max((int)sizeof(struct shmem_sb_info),
+- L1_CACHE_BYTES), GFP_KERNEL);
++ sbinfo = kzalloc(max(sizeof(struct shmem_sb_info), L1_CACHE_BYTES), GFP_KERNEL);
+ if (!sbinfo)
+ return -ENOMEM;
+
+diff -urNp linux-2.6.38.7/mm/slab.c linux-2.6.38.7/mm/slab.c
+--- linux-2.6.38.7/mm/slab.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/mm/slab.c 2011-04-28 19:57:25.000000000 -0400
+@@ -150,7 +150,7 @@
+
+ /* Legal flag mask for kmem_cache_create(). */
+ #if DEBUG
+-# define CREATE_MASK (SLAB_RED_ZONE | \
++# define CREATE_MASK (SLAB_USERCOPY | SLAB_RED_ZONE | \
+ SLAB_POISON | SLAB_HWCACHE_ALIGN | \
+ SLAB_CACHE_DMA | \
+ SLAB_STORE_USER | \
+@@ -158,7 +158,7 @@
+ SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
+ SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK)
+ #else
+-# define CREATE_MASK (SLAB_HWCACHE_ALIGN | \
++# define CREATE_MASK (SLAB_USERCOPY | SLAB_HWCACHE_ALIGN | \
+ SLAB_CACHE_DMA | \
+ SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
+ SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
+@@ -284,7 +284,7 @@ struct kmem_list3 {
+ * Need this for bootstrapping a per node allocator.
+ */
+ #define NUM_INIT_LISTS (3 * MAX_NUMNODES)
+-static struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
++static struct kmem_list3 initkmem_list3[NUM_INIT_LISTS];
+ #define CACHE_CACHE 0
+ #define SIZE_AC MAX_NUMNODES
+ #define SIZE_L3 (2 * MAX_NUMNODES)
+@@ -385,10 +385,10 @@ static void kmem_list3_init(struct kmem_
+ if ((x)->max_freeable < i) \
+ (x)->max_freeable = i; \
+ } while (0)
+-#define STATS_INC_ALLOCHIT(x) atomic_inc(&(x)->allochit)
+-#define STATS_INC_ALLOCMISS(x) atomic_inc(&(x)->allocmiss)
+-#define STATS_INC_FREEHIT(x) atomic_inc(&(x)->freehit)
+-#define STATS_INC_FREEMISS(x) atomic_inc(&(x)->freemiss)
++#define STATS_INC_ALLOCHIT(x) atomic_inc_unchecked(&(x)->allochit)
++#define STATS_INC_ALLOCMISS(x) atomic_inc_unchecked(&(x)->allocmiss)
++#define STATS_INC_FREEHIT(x) atomic_inc_unchecked(&(x)->freehit)
++#define STATS_INC_FREEMISS(x) atomic_inc_unchecked(&(x)->freemiss)
+ #else
+ #define STATS_INC_ACTIVE(x) do { } while (0)
+ #define STATS_DEC_ACTIVE(x) do { } while (0)
+@@ -534,7 +534,7 @@ static inline void *index_to_obj(struct
+ * reciprocal_divide(offset, cache->reciprocal_buffer_size)
+ */
+ static inline unsigned int obj_to_index(const struct kmem_cache *cache,
+- const struct slab *slab, void *obj)
++ const struct slab *slab, const void *obj)
+ {
+ u32 offset = (obj - slab->s_mem);
+ return reciprocal_divide(offset, cache->reciprocal_buffer_size);
+@@ -560,7 +560,7 @@ struct cache_names {
+ static struct cache_names __initdata cache_names[] = {
+ #define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" },
+ #include <linux/kmalloc_sizes.h>
+- {NULL,}
++ {NULL}
+ #undef CACHE
+ };
+
+@@ -1526,7 +1526,7 @@ void __init kmem_cache_init(void)
+ sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name,
+ sizes[INDEX_AC].cs_size,
+ ARCH_KMALLOC_MINALIGN,
+- ARCH_KMALLOC_FLAGS|SLAB_PANIC,
++ ARCH_KMALLOC_FLAGS|SLAB_PANIC|SLAB_USERCOPY,
+ NULL);
+
+ if (INDEX_AC != INDEX_L3) {
+@@ -1534,7 +1534,7 @@ void __init kmem_cache_init(void)
+ kmem_cache_create(names[INDEX_L3].name,
+ sizes[INDEX_L3].cs_size,
+ ARCH_KMALLOC_MINALIGN,
+- ARCH_KMALLOC_FLAGS|SLAB_PANIC,
++ ARCH_KMALLOC_FLAGS|SLAB_PANIC|SLAB_USERCOPY,
+ NULL);
+ }
+
+@@ -1552,7 +1552,7 @@ void __init kmem_cache_init(void)
+ sizes->cs_cachep = kmem_cache_create(names->name,
+ sizes->cs_size,
+ ARCH_KMALLOC_MINALIGN,
+- ARCH_KMALLOC_FLAGS|SLAB_PANIC,
++ ARCH_KMALLOC_FLAGS|SLAB_PANIC|SLAB_USERCOPY,
+ NULL);
+ }
+ #ifdef CONFIG_ZONE_DMA
+@@ -4275,10 +4275,10 @@ static int s_show(struct seq_file *m, vo
+ }
+ /* cpu stats */
+ {
+- unsigned long allochit = atomic_read(&cachep->allochit);
+- unsigned long allocmiss = atomic_read(&cachep->allocmiss);
+- unsigned long freehit = atomic_read(&cachep->freehit);
+- unsigned long freemiss = atomic_read(&cachep->freemiss);
++ unsigned long allochit = atomic_read_unchecked(&cachep->allochit);
++ unsigned long allocmiss = atomic_read_unchecked(&cachep->allocmiss);
++ unsigned long freehit = atomic_read_unchecked(&cachep->freehit);
++ unsigned long freemiss = atomic_read_unchecked(&cachep->freemiss);
+
+ seq_printf(m, " : cpustat %6lu %6lu %6lu %6lu",
+ allochit, allocmiss, freehit, freemiss);
+@@ -4535,15 +4535,66 @@ static const struct file_operations proc
+
+ static int __init slab_proc_init(void)
+ {
+- proc_create("slabinfo",S_IWUSR|S_IRUGO,NULL,&proc_slabinfo_operations);
++ mode_t gr_mode = S_IRUGO;
++
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ gr_mode = S_IRUSR;
++#endif
++
++ proc_create("slabinfo",S_IWUSR|gr_mode,NULL,&proc_slabinfo_operations);
+ #ifdef CONFIG_DEBUG_SLAB_LEAK
+- proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
++ proc_create("slab_allocators", gr_mode, NULL, &proc_slabstats_operations);
+ #endif
+ return 0;
+ }
+ module_init(slab_proc_init);
+ #endif
+
++void check_object_size(const void *ptr, unsigned long n, bool to)
++{
++
++#ifdef CONFIG_PAX_USERCOPY
++ struct page *page;
++ struct kmem_cache *cachep = NULL;
++ struct slab *slabp;
++ unsigned int objnr;
++ unsigned long offset;
++
++ if (!n)
++ return;
++
++ if (ZERO_OR_NULL_PTR(ptr))
++ goto report;
++
++ if (!virt_addr_valid(ptr))
++ return;
++
++ page = virt_to_head_page(ptr);
++
++ if (!PageSlab(page)) {
++ if (object_is_on_stack(ptr, n) == -1)
++ goto report;
++ return;
++ }
++
++ cachep = page_get_cache(page);
++ if (!(cachep->flags & SLAB_USERCOPY))
++ goto report;
++
++ slabp = page_get_slab(page);
++ objnr = obj_to_index(cachep, slabp, ptr);
++ BUG_ON(objnr >= cachep->num);
++ offset = ptr - index_to_obj(cachep, slabp, objnr) - obj_offset(cachep);
++ if (offset <= obj_size(cachep) && n <= obj_size(cachep) - offset)
++ return;
++
++report:
++ pax_report_usercopy(ptr, n, to, cachep ? cachep->name : NULL);
++#endif
++
++}
++EXPORT_SYMBOL(check_object_size);
++
+ /**
+ * ksize - get the actual amount of memory allocated for a given object
+ * @objp: Pointer to the object
+diff -urNp linux-2.6.38.7/mm/slob.c linux-2.6.38.7/mm/slob.c
+--- linux-2.6.38.7/mm/slob.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/slob.c 2011-04-28 19:34:15.000000000 -0400
+@@ -29,7 +29,7 @@
+ * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
+ * alloc_pages() directly, allocating compound pages so the page order
+ * does not have to be separately tracked, and also stores the exact
+- * allocation size in page->private so that it can be used to accurately
++ * allocation size in slob_page->size so that it can be used to accurately
+ * provide ksize(). These objects are detected in kfree() because slob_page()
+ * is false for them.
+ *
+@@ -58,6 +58,7 @@
+ */
+
+ #include <linux/kernel.h>
++#include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/mm.h>
+ #include <linux/swap.h> /* struct reclaim_state */
+@@ -102,7 +103,8 @@ struct slob_page {
+ unsigned long flags; /* mandatory */
+ atomic_t _count; /* mandatory */
+ slobidx_t units; /* free units left in page */
+- unsigned long pad[2];
++ unsigned long pad[1];
++ unsigned long size; /* size when >=PAGE_SIZE */
+ slob_t *free; /* first free slob_t in page */
+ struct list_head list; /* linked list of free pages */
+ };
+@@ -135,7 +137,7 @@ static LIST_HEAD(free_slob_large);
+ */
+ static inline int is_slob_page(struct slob_page *sp)
+ {
+- return PageSlab((struct page *)sp);
++ return PageSlab((struct page *)sp) && !sp->size;
+ }
+
+ static inline void set_slob_page(struct slob_page *sp)
+@@ -150,7 +152,7 @@ static inline void clear_slob_page(struc
+
+ static inline struct slob_page *slob_page(const void *addr)
+ {
+- return (struct slob_page *)virt_to_page(addr);
++ return (struct slob_page *)virt_to_head_page(addr);
+ }
+
+ /*
+@@ -210,7 +212,7 @@ static void set_slob(slob_t *s, slobidx_
+ /*
+ * Return the size of a slob block.
+ */
+-static slobidx_t slob_units(slob_t *s)
++static slobidx_t slob_units(const slob_t *s)
+ {
+ if (s->units > 0)
+ return s->units;
+@@ -220,7 +222,7 @@ static slobidx_t slob_units(slob_t *s)
+ /*
+ * Return the next free slob block pointer after this one.
+ */
+-static slob_t *slob_next(slob_t *s)
++static slob_t *slob_next(const slob_t *s)
+ {
+ slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
+ slobidx_t next;
+@@ -235,7 +237,7 @@ static slob_t *slob_next(slob_t *s)
+ /*
+ * Returns true if s is the last free block in its page.
+ */
+-static int slob_last(slob_t *s)
++static int slob_last(const slob_t *s)
+ {
+ return !((unsigned long)slob_next(s) & ~PAGE_MASK);
+ }
+@@ -254,6 +256,7 @@ static void *slob_new_pages(gfp_t gfp, i
+ if (!page)
+ return NULL;
+
++ set_slob_page(page);
+ return page_address(page);
+ }
+
+@@ -370,11 +373,11 @@ static void *slob_alloc(size_t size, gfp
+ if (!b)
+ return NULL;
+ sp = slob_page(b);
+- set_slob_page(sp);
+
+ spin_lock_irqsave(&slob_lock, flags);
+ sp->units = SLOB_UNITS(PAGE_SIZE);
+ sp->free = b;
++ sp->size = 0;
+ INIT_LIST_HEAD(&sp->list);
+ set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
+ set_slob_page_free(sp, slob_list);
+@@ -476,10 +479,9 @@ out:
+ * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend.
+ */
+
+-void *__kmalloc_node(size_t size, gfp_t gfp, int node)
++static void *__kmalloc_node_align(size_t size, gfp_t gfp, int node, int align)
+ {
+- unsigned int *m;
+- int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
++ slob_t *m;
+ void *ret;
+
+ lockdep_trace_alloc(gfp);
+@@ -492,7 +494,10 @@ void *__kmalloc_node(size_t size, gfp_t
+
+ if (!m)
+ return NULL;
+- *m = size;
++ BUILD_BUG_ON(ARCH_KMALLOC_MINALIGN < 2 * SLOB_UNIT);
++ BUILD_BUG_ON(ARCH_SLAB_MINALIGN < 2 * SLOB_UNIT);
++ m[0].units = size;
++ m[1].units = align;
+ ret = (void *)m + align;
+
+ trace_kmalloc_node(_RET_IP_, ret,
+@@ -504,9 +509,9 @@ void *__kmalloc_node(size_t size, gfp_t
+ gfp |= __GFP_COMP;
+ ret = slob_new_pages(gfp, order, node);
+ if (ret) {
+- struct page *page;
+- page = virt_to_page(ret);
+- page->private = size;
++ struct slob_page *sp;
++ sp = slob_page(ret);
++ sp->size = size;
+ }
+
+ trace_kmalloc_node(_RET_IP_, ret,
+@@ -516,6 +521,13 @@ void *__kmalloc_node(size_t size, gfp_t
+ kmemleak_alloc(ret, size, 1, gfp);
+ return ret;
+ }
++
++void *__kmalloc_node(size_t size, gfp_t gfp, int node)
++{
++ int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
++
++ return __kmalloc_node_align(size, gfp, node, align);
++}
+ EXPORT_SYMBOL(__kmalloc_node);
+
+ void kfree(const void *block)
+@@ -531,13 +543,81 @@ void kfree(const void *block)
+ sp = slob_page(block);
+ if (is_slob_page(sp)) {
+ int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+- unsigned int *m = (unsigned int *)(block - align);
+- slob_free(m, *m + align);
+- } else
++ slob_t *m = (slob_t *)(block - align);
++ slob_free(m, m[0].units + align);
++ } else {
++ clear_slob_page(sp);
++ free_slob_page(sp);
++ sp->size = 0;
+ put_page(&sp->page);
++ }
+ }
+ EXPORT_SYMBOL(kfree);
+
++void check_object_size(const void *ptr, unsigned long n, bool to)
++{
++
++#ifdef CONFIG_PAX_USERCOPY
++ struct slob_page *sp;
++ const slob_t *free;
++ const void *base;
++
++ if (!n)
++ return;
++
++ if (ZERO_OR_NULL_PTR(ptr))
++ goto report;
++
++ if (!virt_addr_valid(ptr))
++ return;
++
++ sp = slob_page(ptr);
++ if (!PageSlab((struct page*)sp)) {
++ if (object_is_on_stack(ptr, n) == -1)
++ goto report;
++ return;
++ }
++
++ if (sp->size) {
++ base = page_address(&sp->page);
++ if (base <= ptr && n <= sp->size - (ptr - base))
++ return;
++ goto report;
++ }
++
++ /* some tricky double walking to find the chunk */
++ base = (void *)((unsigned long)ptr & PAGE_MASK);
++ free = sp->free;
++
++ while (!slob_last(free) && (void *)free <= ptr) {
++ base = free + slob_units(free);
++ free = slob_next(free);
++ }
++
++ while (base < (void *)free) {
++ slobidx_t m = ((slob_t *)base)[0].units, align = ((slob_t *)base)[1].units;
++ int size = SLOB_UNIT * SLOB_UNITS(m + align);
++ int offset;
++
++ if (ptr < base + align)
++ goto report;
++
++ offset = ptr - base - align;
++ if (offset < m) {
++ if (n <= m - offset)
++ return;
++ goto report;
++ }
++ base += size;
++ }
++
++report:
++ pax_report_usercopy(ptr, n, to, NULL);
++#endif
++
++}
++EXPORT_SYMBOL(check_object_size);
++
+ /* can't use ksize for kmem_cache_alloc memory, only kmalloc */
+ size_t ksize(const void *block)
+ {
+@@ -550,10 +630,10 @@ size_t ksize(const void *block)
+ sp = slob_page(block);
+ if (is_slob_page(sp)) {
+ int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+- unsigned int *m = (unsigned int *)(block - align);
+- return SLOB_UNITS(*m) * SLOB_UNIT;
++ slob_t *m = (slob_t *)(block - align);
++ return SLOB_UNITS(m[0].units) * SLOB_UNIT;
+ } else
+- return sp->page.private;
++ return sp->size;
+ }
+ EXPORT_SYMBOL(ksize);
+
+@@ -608,17 +688,25 @@ void *kmem_cache_alloc_node(struct kmem_
+ {
+ void *b;
+
++#ifdef CONFIG_PAX_USERCOPY
++ b = __kmalloc_node_align(c->size, flags, node, c->align);
++#else
+ if (c->size < PAGE_SIZE) {
+ b = slob_alloc(c->size, flags, c->align, node);
+ trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
+ SLOB_UNITS(c->size) * SLOB_UNIT,
+ flags, node);
+ } else {
++ struct slob_page *sp;
++
+ b = slob_new_pages(flags, get_order(c->size), node);
++ sp = slob_page(b);
++ sp->size = c->size;
+ trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
+ PAGE_SIZE << get_order(c->size),
+ flags, node);
+ }
++#endif
+
+ if (c->ctor)
+ c->ctor(b);
+@@ -630,10 +718,16 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
+
+ static void __kmem_cache_free(void *b, int size)
+ {
+- if (size < PAGE_SIZE)
++ struct slob_page *sp = slob_page(b);
++
++ if (is_slob_page(sp))
+ slob_free(b, size);
+- else
++ else {
++ clear_slob_page(sp);
++ free_slob_page(sp);
++ sp->size = 0;
+ slob_free_pages(b, get_order(size));
++ }
+ }
+
+ static void kmem_rcu_free(struct rcu_head *head)
+@@ -646,14 +740,23 @@ static void kmem_rcu_free(struct rcu_hea
+
+ void kmem_cache_free(struct kmem_cache *c, void *b)
+ {
++ int size = c->size;
++
++#ifdef CONFIG_PAX_USERCOPY
++ if (size + c->align < PAGE_SIZE) {
++ size += c->align;
++ b -= c->align;
++ }
++#endif
++
+ kmemleak_free_recursive(b, c->flags);
+ if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
+ struct slob_rcu *slob_rcu;
+- slob_rcu = b + (c->size - sizeof(struct slob_rcu));
+- slob_rcu->size = c->size;
++ slob_rcu = b + (size - sizeof(struct slob_rcu));
++ slob_rcu->size = size;
+ call_rcu(&slob_rcu->head, kmem_rcu_free);
+ } else {
+- __kmem_cache_free(b, c->size);
++ __kmem_cache_free(b, size);
+ }
+
+ trace_kmem_cache_free(_RET_IP_, b);
+diff -urNp linux-2.6.38.7/mm/slub.c linux-2.6.38.7/mm/slub.c
+--- linux-2.6.38.7/mm/slub.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/slub.c 2011-04-28 19:34:15.000000000 -0400
+@@ -390,7 +390,7 @@ static void print_track(const char *s, s
+ if (!t->addr)
+ return;
+
+- printk(KERN_ERR "INFO: %s in %pS age=%lu cpu=%u pid=%d\n",
++ printk(KERN_ERR "INFO: %s in %pA age=%lu cpu=%u pid=%d\n",
+ s, (void *)t->addr, jiffies - t->when, t->cpu, t->pid);
+ }
+
+@@ -1927,6 +1927,8 @@ void kmem_cache_free(struct kmem_cache *
+
+ page = virt_to_head_page(x);
+
++ BUG_ON(!PageSlab(page));
++
+ slab_free(s, page, x, _RET_IP_);
+
+ trace_kmem_cache_free(_RET_IP_, x);
+@@ -1960,7 +1962,7 @@ static int slub_min_objects;
+ * Merge control. If this is set then no merging of slab caches will occur.
+ * (Could be removed. This was introduced to pacify the merge skeptics.)
+ */
+-static int slub_nomerge;
++static int slub_nomerge = 1;
+
+ /*
+ * Calculate the order of allocation given an slab object size.
+@@ -2370,7 +2372,7 @@ static int kmem_cache_open(struct kmem_c
+ * list to avoid pounding the page allocator excessively.
+ */
+ set_min_partial(s, ilog2(s->size));
+- s->refcount = 1;
++ atomic_set(&s->refcount, 1);
+ #ifdef CONFIG_NUMA
+ s->remote_node_defrag_ratio = 1000;
+ #endif
+@@ -2482,8 +2484,7 @@ static inline int kmem_cache_close(struc
+ void kmem_cache_destroy(struct kmem_cache *s)
+ {
+ down_write(&slub_lock);
+- s->refcount--;
+- if (!s->refcount) {
++ if (atomic_dec_and_test(&s->refcount)) {
+ list_del(&s->list);
+ if (kmem_cache_close(s)) {
+ printk(KERN_ERR "SLUB %s: %s called for cache that "
+@@ -2693,6 +2694,46 @@ void *__kmalloc_node(size_t size, gfp_t
+ EXPORT_SYMBOL(__kmalloc_node);
+ #endif
+
++void check_object_size(const void *ptr, unsigned long n, bool to)
++{
++
++#ifdef CONFIG_PAX_USERCOPY
++ struct page *page;
++ struct kmem_cache *s = NULL;
++ unsigned long offset;
++
++ if (!n)
++ return;
++
++ if (ZERO_OR_NULL_PTR(ptr))
++ goto report;
++
++ if (!virt_addr_valid(ptr))
++ return;
++
++ page = virt_to_head_page(ptr);
++
++ if (!PageSlab(page)) {
++ if (object_is_on_stack(ptr, n) == -1)
++ goto report;
++ return;
++ }
++
++ s = page->slab;
++ if (!(s->flags & SLAB_USERCOPY))
++ goto report;
++
++ offset = (ptr - page_address(page)) % s->size;
++ if (offset <= s->objsize && n <= s->objsize - offset)
++ return;
++
++report:
++ pax_report_usercopy(ptr, n, to, s ? s->name : NULL);
++#endif
++
++}
++EXPORT_SYMBOL(check_object_size);
++
+ size_t ksize(const void *object)
+ {
+ struct page *page;
+@@ -2958,7 +2999,7 @@ static void __init kmem_cache_bootstrap_
+ int node;
+
+ list_add(&s->list, &slab_caches);
+- s->refcount = -1;
++ atomic_set(&s->refcount, -1);
+
+ for_each_node_state(node, N_NORMAL_MEMORY) {
+ struct kmem_cache_node *n = get_node(s, node);
+@@ -3075,17 +3116,17 @@ void __init kmem_cache_init(void)
+
+ /* Caches that are not of the two-to-the-power-of size */
+ if (KMALLOC_MIN_SIZE <= 32) {
+- kmalloc_caches[1] = create_kmalloc_cache("kmalloc-96", 96, 0);
++ kmalloc_caches[1] = create_kmalloc_cache("kmalloc-96", 96, SLAB_USERCOPY);
+ caches++;
+ }
+
+ if (KMALLOC_MIN_SIZE <= 64) {
+- kmalloc_caches[2] = create_kmalloc_cache("kmalloc-192", 192, 0);
++ kmalloc_caches[2] = create_kmalloc_cache("kmalloc-192", 192, SLAB_USERCOPY);
+ caches++;
+ }
+
+ for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) {
+- kmalloc_caches[i] = create_kmalloc_cache("kmalloc", 1 << i, 0);
++ kmalloc_caches[i] = create_kmalloc_cache("kmalloc", 1 << i, SLAB_USERCOPY);
+ caches++;
+ }
+
+@@ -3153,7 +3194,7 @@ static int slab_unmergeable(struct kmem_
+ /*
+ * We may have set a slab to be unmergeable during bootstrap.
+ */
+- if (s->refcount < 0)
++ if (atomic_read(&s->refcount) < 0)
+ return 1;
+
+ return 0;
+@@ -3212,7 +3253,7 @@ struct kmem_cache *kmem_cache_create(con
+ down_write(&slub_lock);
+ s = find_mergeable(size, align, flags, name, ctor);
+ if (s) {
+- s->refcount++;
++ atomic_inc(&s->refcount);
+ /*
+ * Adjust the object sizes so that we clear
+ * the complete object on kzalloc.
+@@ -3221,7 +3262,7 @@ struct kmem_cache *kmem_cache_create(con
+ s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
+
+ if (sysfs_slab_alias(s, name)) {
+- s->refcount--;
++ atomic_dec(&s->refcount);
+ goto err;
+ }
+ up_write(&slub_lock);
+@@ -3954,7 +3995,7 @@ SLAB_ATTR_RO(ctor);
+
+ static ssize_t aliases_show(struct kmem_cache *s, char *buf)
+ {
+- return sprintf(buf, "%d\n", s->refcount - 1);
++ return sprintf(buf, "%d\n", atomic_read(&s->refcount) - 1);
+ }
+ SLAB_ATTR_RO(aliases);
+
+@@ -4691,7 +4732,13 @@ static const struct file_operations proc
+
+ static int __init slab_proc_init(void)
+ {
+- proc_create("slabinfo", S_IRUGO, NULL, &proc_slabinfo_operations);
++ mode_t gr_mode = S_IRUGO;
++
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ gr_mode = S_IRUSR;
++#endif
++
++ proc_create("slabinfo", gr_mode, NULL, &proc_slabinfo_operations);
+ return 0;
+ }
+ module_init(slab_proc_init);
+diff -urNp linux-2.6.38.7/mm/swapfile.c linux-2.6.38.7/mm/swapfile.c
+--- linux-2.6.38.7/mm/swapfile.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/mm/swapfile.c 2011-04-28 19:57:25.000000000 -0400
+@@ -61,7 +61,7 @@ static DEFINE_MUTEX(swapon_mutex);
+
+ static DECLARE_WAIT_QUEUE_HEAD(proc_poll_wait);
+ /* Activity counter to indicate that a swapon or swapoff has occurred */
+-static atomic_t proc_poll_event = ATOMIC_INIT(0);
++static atomic_unchecked_t proc_poll_event = ATOMIC_INIT(0);
+
+ static inline unsigned char swap_count(unsigned char ent)
+ {
+@@ -1687,7 +1687,7 @@ SYSCALL_DEFINE1(swapoff, const char __us
+ }
+ filp_close(swap_file, NULL);
+ err = 0;
+- atomic_inc(&proc_poll_event);
++ atomic_inc_unchecked(&proc_poll_event);
+ wake_up_interruptible(&proc_poll_wait);
+
+ out_dput:
+@@ -1708,8 +1708,8 @@ static unsigned swaps_poll(struct file *
+
+ poll_wait(file, &proc_poll_wait, wait);
+
+- if (s->event != atomic_read(&proc_poll_event)) {
+- s->event = atomic_read(&proc_poll_event);
++ if (s->event != atomic_read_unchecked(&proc_poll_event)) {
++ s->event = atomic_read_unchecked(&proc_poll_event);
+ return POLLIN | POLLRDNORM | POLLERR | POLLPRI;
+ }
+
+@@ -1815,7 +1815,7 @@ static int swaps_open(struct inode *inod
+ }
+
+ s->seq.private = s;
+- s->event = atomic_read(&proc_poll_event);
++ s->event = atomic_read_unchecked(&proc_poll_event);
+ return ret;
+ }
+
+@@ -2131,7 +2131,7 @@ SYSCALL_DEFINE2(swapon, const char __use
+ swap_info[prev]->next = type;
+ spin_unlock(&swap_lock);
+ mutex_unlock(&swapon_mutex);
+- atomic_inc(&proc_poll_event);
++ atomic_inc_unchecked(&proc_poll_event);
+ wake_up_interruptible(&proc_poll_wait);
+
+ error = 0;
+diff -urNp linux-2.6.38.7/mm/util.c linux-2.6.38.7/mm/util.c
+--- linux-2.6.38.7/mm/util.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/util.c 2011-04-28 19:34:15.000000000 -0400
+@@ -219,6 +219,12 @@ EXPORT_SYMBOL(strndup_user);
+ void arch_pick_mmap_layout(struct mm_struct *mm)
+ {
+ mm->mmap_base = TASK_UNMAPPED_BASE;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ }
+diff -urNp linux-2.6.38.7/mm/vmalloc.c linux-2.6.38.7/mm/vmalloc.c
+--- linux-2.6.38.7/mm/vmalloc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/vmalloc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -39,8 +39,19 @@ static void vunmap_pte_range(pmd_t *pmd,
+
+ pte = pte_offset_kernel(pmd, addr);
+ do {
+- pte_t ptent = ptep_get_and_clear(&init_mm, addr, pte);
+- WARN_ON(!pte_none(ptent) && !pte_present(ptent));
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ if ((unsigned long)MODULES_EXEC_VADDR <= addr && addr < (unsigned long)MODULES_EXEC_END) {
++ BUG_ON(!pte_exec(*pte));
++ set_pte_at(&init_mm, addr, pte, pfn_pte(__pa(addr) >> PAGE_SHIFT, PAGE_KERNEL_EXEC));
++ continue;
++ }
++#endif
++
++ {
++ pte_t ptent = ptep_get_and_clear(&init_mm, addr, pte);
++ WARN_ON(!pte_none(ptent) && !pte_present(ptent));
++ }
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ }
+
+@@ -91,6 +102,7 @@ static int vmap_pte_range(pmd_t *pmd, un
+ unsigned long end, pgprot_t prot, struct page **pages, int *nr)
+ {
+ pte_t *pte;
++ int ret = -ENOMEM;
+
+ /*
+ * nr is a running index into the array which helps higher level
+@@ -100,17 +112,30 @@ static int vmap_pte_range(pmd_t *pmd, un
+ pte = pte_alloc_kernel(pmd, addr);
+ if (!pte)
+ return -ENOMEM;
++
++ pax_open_kernel();
+ do {
+ struct page *page = pages[*nr];
+
+- if (WARN_ON(!pte_none(*pte)))
+- return -EBUSY;
+- if (WARN_ON(!page))
+- return -ENOMEM;
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ if (pgprot_val(prot) & _PAGE_NX)
++#endif
++
++ if (WARN_ON(!pte_none(*pte))) {
++ ret = -EBUSY;
++ goto out;
++ }
++ if (WARN_ON(!page)) {
++ ret = -ENOMEM;
++ goto out;
++ }
+ set_pte_at(&init_mm, addr, pte, mk_pte(page, prot));
+ (*nr)++;
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+- return 0;
++ ret = 0;
++out:
++ pax_close_kernel();
++ return ret;
+ }
+
+ static int vmap_pmd_range(pud_t *pud, unsigned long addr,
+@@ -191,11 +216,20 @@ int is_vmalloc_or_module_addr(const void
+ * and fall back on vmalloc() if that fails. Others
+ * just put it in the vmalloc space.
+ */
+-#if defined(CONFIG_MODULES) && defined(MODULES_VADDR)
++#ifdef CONFIG_MODULES
++#ifdef MODULES_VADDR
+ unsigned long addr = (unsigned long)x;
+ if (addr >= MODULES_VADDR && addr < MODULES_END)
+ return 1;
+ #endif
++
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC)
++ if (x >= (const void *)MODULES_EXEC_VADDR && x < (const void *)MODULES_EXEC_END)
++ return 1;
++#endif
++
++#endif
++
+ return is_vmalloc_addr(x);
+ }
+
+@@ -216,8 +250,14 @@ struct page *vmalloc_to_page(const void
+
+ if (!pgd_none(*pgd)) {
+ pud_t *pud = pud_offset(pgd, addr);
++#ifdef CONFIG_X86
++ if (!pud_large(*pud))
++#endif
+ if (!pud_none(*pud)) {
+ pmd_t *pmd = pmd_offset(pud, addr);
++#ifdef CONFIG_X86
++ if (!pmd_large(*pmd))
++#endif
+ if (!pmd_none(*pmd)) {
+ pte_t *ptep, pte;
+
+@@ -1244,6 +1284,16 @@ static struct vm_struct *__get_vm_area_n
+ struct vm_struct *area;
+
+ BUG_ON(in_interrupt());
++
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86) && defined(CONFIG_PAX_KERNEXEC)
++ if (flags & VM_KERNEXEC) {
++ if (start != VMALLOC_START || end != VMALLOC_END)
++ return NULL;
++ start = (unsigned long)MODULES_EXEC_VADDR;
++ end = (unsigned long)MODULES_EXEC_END;
++ }
++#endif
++
+ if (flags & VM_IOREMAP) {
+ int bit = fls(size);
+
+@@ -1462,6 +1512,11 @@ void *vmap(struct page **pages, unsigned
+ if (count > totalram_pages)
+ return NULL;
+
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86) && defined(CONFIG_PAX_KERNEXEC)
++ if (!(pgprot_val(prot) & _PAGE_NX))
++ flags |= VM_KERNEXEC;
++#endif
++
+ area = get_vm_area_caller((count << PAGE_SHIFT), flags,
+ __builtin_return_address(0));
+ if (!area)
+@@ -1558,6 +1613,13 @@ void *__vmalloc_node_range(unsigned long
+ if (!size || (size >> PAGE_SHIFT) > totalram_pages)
+ return NULL;
+
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86) && defined(CONFIG_PAX_KERNEXEC)
++ if (!(pgprot_val(prot) & _PAGE_NX))
++ area = __get_vm_area_node(size, align, VM_ALLOC | VM_KERNEXEC, VMALLOC_START, VMALLOC_END,
++ node, gfp_mask, caller);
++ else
++#endif
++
+ area = __get_vm_area_node(size, align, VM_ALLOC, start, end, node,
+ gfp_mask, caller);
+
+@@ -1597,6 +1659,7 @@ static void *__vmalloc_node(unsigned lon
+ gfp_mask, prot, node, caller);
+ }
+
++#undef __vmalloc
+ void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+ {
+ return __vmalloc_node(size, 1, gfp_mask, prot, -1,
+@@ -1620,6 +1683,7 @@ static inline void *__vmalloc_node_flags
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
++#undef vmalloc
+ void *vmalloc(unsigned long size)
+ {
+ return __vmalloc_node_flags(size, -1, GFP_KERNEL | __GFP_HIGHMEM);
+@@ -1636,6 +1700,7 @@ EXPORT_SYMBOL(vmalloc);
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
++#undef vzalloc
+ void *vzalloc(unsigned long size)
+ {
+ return __vmalloc_node_flags(size, -1,
+@@ -1650,6 +1715,7 @@ EXPORT_SYMBOL(vzalloc);
+ * The resulting memory area is zeroed so it can be mapped to userspace
+ * without leaking data.
+ */
++#undef vmalloc_user
+ void *vmalloc_user(unsigned long size)
+ {
+ struct vm_struct *area;
+@@ -1677,6 +1743,7 @@ EXPORT_SYMBOL(vmalloc_user);
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
++#undef vmalloc_node
+ void *vmalloc_node(unsigned long size, int node)
+ {
+ return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
+@@ -1696,6 +1763,7 @@ EXPORT_SYMBOL(vmalloc_node);
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc_node() instead.
+ */
++#undef vzalloc_node
+ void *vzalloc_node(unsigned long size, int node)
+ {
+ return __vmalloc_node_flags(size, node,
+@@ -1718,10 +1786,10 @@ EXPORT_SYMBOL(vzalloc_node);
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
+-
++#undef vmalloc_exec
+ void *vmalloc_exec(unsigned long size)
+ {
+- return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
++ return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL_EXEC,
+ -1, __builtin_return_address(0));
+ }
+
+@@ -1740,6 +1808,7 @@ void *vmalloc_exec(unsigned long size)
+ * Allocate enough 32bit PA addressable pages to cover @size from the
+ * page level allocator and map them into contiguous kernel virtual space.
+ */
++#undef vmalloc_32
+ void *vmalloc_32(unsigned long size)
+ {
+ return __vmalloc_node(size, 1, GFP_VMALLOC32, PAGE_KERNEL,
+@@ -1754,6 +1823,7 @@ EXPORT_SYMBOL(vmalloc_32);
+ * The resulting memory area is 32bit addressable and zeroed so it can be
+ * mapped to userspace without leaking data.
+ */
++#undef vmalloc_32_user
+ void *vmalloc_32_user(unsigned long size)
+ {
+ struct vm_struct *area;
+@@ -2018,6 +2088,8 @@ int remap_vmalloc_range(struct vm_area_s
+ unsigned long uaddr = vma->vm_start;
+ unsigned long usize = vma->vm_end - vma->vm_start;
+
++ BUG_ON(vma->vm_mirror);
++
+ if ((PAGE_SIZE-1) & (unsigned long)addr)
+ return -EINVAL;
+
+diff -urNp linux-2.6.38.7/mm/vmstat.c linux-2.6.38.7/mm/vmstat.c
+--- linux-2.6.38.7/mm/vmstat.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/mm/vmstat.c 2011-04-28 19:34:15.000000000 -0400
+@@ -78,7 +78,7 @@ void vm_events_fold_cpu(int cpu)
+ *
+ * vm_stat contains the global counters
+ */
+-atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
++atomic_long_unchecked_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+ EXPORT_SYMBOL(vm_stat);
+
+ #ifdef CONFIG_SMP
+@@ -451,7 +451,7 @@ void refresh_cpu_vm_stats(int cpu)
+ v = p->vm_stat_diff[i];
+ p->vm_stat_diff[i] = 0;
+ local_irq_restore(flags);
+- atomic_long_add(v, &zone->vm_stat[i]);
++ atomic_long_add_unchecked(v, &zone->vm_stat[i]);
+ global_diff[i] += v;
+ #ifdef CONFIG_NUMA
+ /* 3 seconds idle till flush */
+@@ -489,7 +489,7 @@ void refresh_cpu_vm_stats(int cpu)
+
+ for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+ if (global_diff[i])
+- atomic_long_add(global_diff[i], &vm_stat[i]);
++ atomic_long_add_unchecked(global_diff[i], &vm_stat[i]);
+ }
+
+ #endif
+@@ -1188,10 +1188,20 @@ static int __init setup_vmstat(void)
+ start_cpu_timer(cpu);
+ #endif
+ #ifdef CONFIG_PROC_FS
+- proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
+- proc_create("pagetypeinfo", S_IRUGO, NULL, &pagetypeinfo_file_ops);
+- proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
+- proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
++ {
++ mode_t gr_mode = S_IRUGO;
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ gr_mode = S_IRUSR;
++#endif
++ proc_create("buddyinfo", gr_mode, NULL, &fragmentation_file_operations);
++ proc_create("pagetypeinfo", gr_mode, NULL, &pagetypeinfo_file_ops);
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
++ proc_create("vmstat", gr_mode | S_IRGRP, NULL, &proc_vmstat_file_operations);
++#else
++ proc_create("vmstat", gr_mode, NULL, &proc_vmstat_file_operations);
++#endif
++ proc_create("zoneinfo", gr_mode, NULL, &proc_zoneinfo_file_operations);
++ }
+ #endif
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/net/8021q/vlan.c linux-2.6.38.7/net/8021q/vlan.c
+--- linux-2.6.38.7/net/8021q/vlan.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/8021q/vlan.c 2011-04-28 19:34:15.000000000 -0400
+@@ -589,8 +589,7 @@ static int vlan_ioctl_handler(struct net
+ err = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ break;
+- if ((args.u.name_type >= 0) &&
+- (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
++ if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) {
+ struct vlan_net *vn;
+
+ vn = net_generic(net, vlan_net_id);
+diff -urNp linux-2.6.38.7/net/atm/atm_misc.c linux-2.6.38.7/net/atm/atm_misc.c
+--- linux-2.6.38.7/net/atm/atm_misc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/atm/atm_misc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -17,7 +17,7 @@ int atm_charge(struct atm_vcc *vcc, int
+ if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
+ return 1;
+ atm_return(vcc, truesize);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ return 0;
+ }
+ EXPORT_SYMBOL(atm_charge);
+@@ -39,7 +39,7 @@ struct sk_buff *atm_alloc_charge(struct
+ }
+ }
+ atm_return(vcc, guess);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ return NULL;
+ }
+ EXPORT_SYMBOL(atm_alloc_charge);
+@@ -86,7 +86,7 @@ EXPORT_SYMBOL(atm_pcr_goal);
+
+ void sonet_copy_stats(struct k_sonet_stats *from, struct sonet_stats *to)
+ {
+-#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
++#define __HANDLE_ITEM(i) to->i = atomic_read_unchecked(&from->i)
+ __SONET_ITEMS
+ #undef __HANDLE_ITEM
+ }
+@@ -94,7 +94,7 @@ EXPORT_SYMBOL(sonet_copy_stats);
+
+ void sonet_subtract_stats(struct k_sonet_stats *from, struct sonet_stats *to)
+ {
+-#define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
++#define __HANDLE_ITEM(i) atomic_sub_unchecked(to->i,&from->i)
+ __SONET_ITEMS
+ #undef __HANDLE_ITEM
+ }
+diff -urNp linux-2.6.38.7/net/atm/mpoa_caches.c linux-2.6.38.7/net/atm/mpoa_caches.c
+--- linux-2.6.38.7/net/atm/mpoa_caches.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/atm/mpoa_caches.c 2011-05-16 21:47:09.000000000 -0400
+@@ -255,6 +255,8 @@ static void check_resolving_entries(stru
+ struct timeval now;
+ struct k_message msg;
+
++ pax_track_stack();
++
+ do_gettimeofday(&now);
+
+ read_lock_bh(&client->ingress_lock);
+diff -urNp linux-2.6.38.7/net/atm/proc.c linux-2.6.38.7/net/atm/proc.c
+--- linux-2.6.38.7/net/atm/proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/atm/proc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -45,9 +45,9 @@ static void add_stats(struct seq_file *s
+ const struct k_atm_aal_stats *stats)
+ {
+ seq_printf(seq, "%s ( %d %d %d %d %d )", aal,
+- atomic_read(&stats->tx), atomic_read(&stats->tx_err),
+- atomic_read(&stats->rx), atomic_read(&stats->rx_err),
+- atomic_read(&stats->rx_drop));
++ atomic_read_unchecked(&stats->tx),atomic_read_unchecked(&stats->tx_err),
++ atomic_read_unchecked(&stats->rx),atomic_read_unchecked(&stats->rx_err),
++ atomic_read_unchecked(&stats->rx_drop));
+ }
+
+ static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev)
+@@ -191,7 +191,12 @@ static void vcc_info(struct seq_file *se
+ {
+ struct sock *sk = sk_atm(vcc);
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ seq_printf(seq, "%p ", NULL);
++#else
+ seq_printf(seq, "%p ", vcc);
++#endif
++
+ if (!vcc->dev)
+ seq_printf(seq, "Unassigned ");
+ else
+@@ -218,7 +223,11 @@ static void svc_info(struct seq_file *se
+ {
+ if (!vcc->dev)
+ seq_printf(seq, sizeof(void *) == 4 ?
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ "N/A@%p%10s" : "N/A@%p%2s", NULL, "");
++#else
+ "N/A@%p%10s" : "N/A@%p%2s", vcc, "");
++#endif
+ else
+ seq_printf(seq, "%3d %3d %5d ",
+ vcc->dev->number, vcc->vpi, vcc->vci);
+diff -urNp linux-2.6.38.7/net/atm/resources.c linux-2.6.38.7/net/atm/resources.c
+--- linux-2.6.38.7/net/atm/resources.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/atm/resources.c 2011-04-28 19:34:15.000000000 -0400
+@@ -160,7 +160,7 @@ EXPORT_SYMBOL(atm_dev_deregister);
+ static void copy_aal_stats(struct k_atm_aal_stats *from,
+ struct atm_aal_stats *to)
+ {
+-#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
++#define __HANDLE_ITEM(i) to->i = atomic_read_unchecked(&from->i)
+ __AAL_STAT_ITEMS
+ #undef __HANDLE_ITEM
+ }
+@@ -168,7 +168,7 @@ static void copy_aal_stats(struct k_atm_
+ static void subtract_aal_stats(struct k_atm_aal_stats *from,
+ struct atm_aal_stats *to)
+ {
+-#define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
++#define __HANDLE_ITEM(i) atomic_sub_unchecked(to->i, &from->i)
+ __AAL_STAT_ITEMS
+ #undef __HANDLE_ITEM
+ }
+diff -urNp linux-2.6.38.7/net/batman-adv/hard-interface.c linux-2.6.38.7/net/batman-adv/hard-interface.c
+--- linux-2.6.38.7/net/batman-adv/hard-interface.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/batman-adv/hard-interface.c 2011-04-28 19:57:25.000000000 -0400
+@@ -325,8 +325,8 @@ int hardif_enable_interface(struct batma
+ kref_get(&batman_if->refcount);
+ dev_add_pack(&batman_if->batman_adv_ptype);
+
+- atomic_set(&batman_if->seqno, 1);
+- atomic_set(&batman_if->frag_seqno, 1);
++ atomic_set_unchecked(&batman_if->seqno, 1);
++ atomic_set_unchecked(&batman_if->frag_seqno, 1);
+ bat_info(batman_if->soft_iface, "Adding interface: %s\n",
+ batman_if->net_dev->name);
+
+diff -urNp linux-2.6.38.7/net/batman-adv/routing.c linux-2.6.38.7/net/batman-adv/routing.c
+--- linux-2.6.38.7/net/batman-adv/routing.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/batman-adv/routing.c 2011-04-28 19:57:25.000000000 -0400
+@@ -569,7 +569,7 @@ void receive_bat_packet(struct ethhdr *e
+ return;
+
+ /* could be changed by schedule_own_packet() */
+- if_incoming_seqno = atomic_read(&if_incoming->seqno);
++ if_incoming_seqno = atomic_read_unchecked(&if_incoming->seqno);
+
+ has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
+
+diff -urNp linux-2.6.38.7/net/batman-adv/send.c linux-2.6.38.7/net/batman-adv/send.c
+--- linux-2.6.38.7/net/batman-adv/send.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/batman-adv/send.c 2011-04-28 19:57:25.000000000 -0400
+@@ -277,7 +277,7 @@ void schedule_own_packet(struct batman_i
+
+ /* change sequence number to network order */
+ batman_packet->seqno =
+- htonl((uint32_t)atomic_read(&batman_if->seqno));
++ htonl((uint32_t)atomic_read_unchecked(&batman_if->seqno));
+
+ if (vis_server == VIS_TYPE_SERVER_SYNC)
+ batman_packet->flags |= VIS_SERVER;
+@@ -291,7 +291,7 @@ void schedule_own_packet(struct batman_i
+ else
+ batman_packet->gw_flags = 0;
+
+- atomic_inc(&batman_if->seqno);
++ atomic_inc_unchecked(&batman_if->seqno);
+
+ slide_own_bcast_window(batman_if);
+ send_time = own_send_time(bat_priv);
+diff -urNp linux-2.6.38.7/net/batman-adv/soft-interface.c linux-2.6.38.7/net/batman-adv/soft-interface.c
+--- linux-2.6.38.7/net/batman-adv/soft-interface.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/batman-adv/soft-interface.c 2011-04-28 19:57:25.000000000 -0400
+@@ -410,7 +410,7 @@ int interface_tx(struct sk_buff *skb, st
+
+ /* set broadcast sequence number */
+ bcast_packet->seqno =
+- htonl(atomic_inc_return(&bat_priv->bcast_seqno));
++ htonl(atomic_inc_return_unchecked(&bat_priv->bcast_seqno));
+
+ add_bcast_packet_to_list(bat_priv, skb);
+
+@@ -603,7 +603,7 @@ struct net_device *softif_create(char *n
+ atomic_set(&bat_priv->batman_queue_left, BATMAN_QUEUE_LEN);
+
+ atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
+- atomic_set(&bat_priv->bcast_seqno, 1);
++ atomic_set_unchecked(&bat_priv->bcast_seqno, 1);
+ atomic_set(&bat_priv->hna_local_changed, 0);
+
+ bat_priv->primary_if = NULL;
+diff -urNp linux-2.6.38.7/net/batman-adv/types.h linux-2.6.38.7/net/batman-adv/types.h
+--- linux-2.6.38.7/net/batman-adv/types.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/batman-adv/types.h 2011-04-28 19:57:25.000000000 -0400
+@@ -38,8 +38,8 @@ struct batman_if {
+ int16_t if_num;
+ char if_status;
+ struct net_device *net_dev;
+- atomic_t seqno;
+- atomic_t frag_seqno;
++ atomic_unchecked_t seqno;
++ atomic_unchecked_t frag_seqno;
+ unsigned char *packet_buff;
+ int packet_len;
+ struct kobject *hardif_obj;
+@@ -133,7 +133,7 @@ struct bat_priv {
+ atomic_t orig_interval; /* uint */
+ atomic_t hop_penalty; /* uint */
+ atomic_t log_level; /* uint */
+- atomic_t bcast_seqno;
++ atomic_unchecked_t bcast_seqno;
+ atomic_t bcast_queue_left;
+ atomic_t batman_queue_left;
+ char num_ifaces;
+diff -urNp linux-2.6.38.7/net/batman-adv/unicast.c linux-2.6.38.7/net/batman-adv/unicast.c
+--- linux-2.6.38.7/net/batman-adv/unicast.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/batman-adv/unicast.c 2011-04-28 19:57:25.000000000 -0400
+@@ -261,9 +261,9 @@ int frag_send_skb(struct sk_buff *skb, s
+ frag1->flags |= UNI_FRAG_HEAD;
+ frag2->flags &= ~UNI_FRAG_HEAD;
+
+- frag1->seqno = htons((uint16_t)atomic_inc_return(
++ frag1->seqno = htons((uint16_t)atomic_inc_return_unchecked(
+ &batman_if->frag_seqno));
+- frag2->seqno = htons((uint16_t)atomic_inc_return(
++ frag2->seqno = htons((uint16_t)atomic_inc_return_unchecked(
+ &batman_if->frag_seqno));
+
+ send_skb_packet(skb, batman_if, dstaddr);
+diff -urNp linux-2.6.38.7/net/bridge/br_multicast.c linux-2.6.38.7/net/bridge/br_multicast.c
+--- linux-2.6.38.7/net/bridge/br_multicast.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/net/bridge/br_multicast.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1482,7 +1482,7 @@ static int br_multicast_ipv6_rcv(struct
+ nexthdr = ip6h->nexthdr;
+ offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr);
+
+- if (offset < 0 || nexthdr != IPPROTO_ICMPV6)
++ if (nexthdr != IPPROTO_ICMPV6)
+ return 0;
+
+ /* Okay, we found ICMPv6 header */
+diff -urNp linux-2.6.38.7/net/bridge/netfilter/ebtables.c linux-2.6.38.7/net/bridge/netfilter/ebtables.c
+--- linux-2.6.38.7/net/bridge/netfilter/ebtables.c 2011-04-18 17:27:18.000000000 -0400
++++ linux-2.6.38.7/net/bridge/netfilter/ebtables.c 2011-05-16 21:47:08.000000000 -0400
+@@ -1512,7 +1512,7 @@ static int do_ebt_get_ctl(struct sock *s
+ tmp.valid_hooks = t->table->valid_hooks;
+ }
+ mutex_unlock(&ebt_mutex);
+- if (copy_to_user(user, &tmp, *len) != 0){
++ if (*len > sizeof(tmp) || copy_to_user(user, &tmp, *len) != 0){
+ BUGPRINT("c2u Didn't work\n");
+ ret = -EFAULT;
+ break;
+@@ -1779,6 +1779,8 @@ static int compat_copy_everything_to_use
+ int ret;
+ void __user *pos;
+
++ pax_track_stack();
++
+ memset(&tinfo, 0, sizeof(tinfo));
+
+ if (cmd == EBT_SO_GET_ENTRIES) {
+diff -urNp linux-2.6.38.7/net/caif/caif_socket.c linux-2.6.38.7/net/caif/caif_socket.c
+--- linux-2.6.38.7/net/caif/caif_socket.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/caif/caif_socket.c 2011-04-28 19:57:25.000000000 -0400
+@@ -48,18 +48,19 @@ static struct dentry *debugfsdir;
+ #ifdef CONFIG_DEBUG_FS
+ struct debug_fs_counter {
+ atomic_t caif_nr_socks;
+- atomic_t num_connect_req;
+- atomic_t num_connect_resp;
+- atomic_t num_connect_fail_resp;
+- atomic_t num_disconnect;
+- atomic_t num_remote_shutdown_ind;
+- atomic_t num_tx_flow_off_ind;
+- atomic_t num_tx_flow_on_ind;
+- atomic_t num_rx_flow_off;
+- atomic_t num_rx_flow_on;
++ atomic_unchecked_t num_connect_req;
++ atomic_unchecked_t num_connect_resp;
++ atomic_unchecked_t num_connect_fail_resp;
++ atomic_unchecked_t num_disconnect;
++ atomic_unchecked_t num_remote_shutdown_ind;
++ atomic_unchecked_t num_tx_flow_off_ind;
++ atomic_unchecked_t num_tx_flow_on_ind;
++ atomic_unchecked_t num_rx_flow_off;
++ atomic_unchecked_t num_rx_flow_on;
+ };
+ static struct debug_fs_counter cnt;
+ #define dbfs_atomic_inc(v) atomic_inc(v)
++#define dbfs_atomic_inc_unchecked(v) atomic_inc_unchecked(v)
+ #define dbfs_atomic_dec(v) atomic_dec(v)
+ #else
+ #define dbfs_atomic_inc(v)
+@@ -159,7 +160,7 @@ static int caif_queue_rcv_skb(struct soc
+ atomic_read(&cf_sk->sk.sk_rmem_alloc),
+ sk_rcvbuf_lowwater(cf_sk));
+ set_rx_flow_off(cf_sk);
+- dbfs_atomic_inc(&cnt.num_rx_flow_off);
++ dbfs_atomic_inc_unchecked(&cnt.num_rx_flow_off);
+ caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
+ }
+
+@@ -169,7 +170,7 @@ static int caif_queue_rcv_skb(struct soc
+ if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) {
+ set_rx_flow_off(cf_sk);
+ pr_debug("sending flow OFF due to rmem_schedule\n");
+- dbfs_atomic_inc(&cnt.num_rx_flow_off);
++ dbfs_atomic_inc_unchecked(&cnt.num_rx_flow_off);
+ caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
+ }
+ skb->dev = NULL;
+@@ -218,21 +219,21 @@ static void caif_ctrl_cb(struct cflayer
+ switch (flow) {
+ case CAIF_CTRLCMD_FLOW_ON_IND:
+ /* OK from modem to start sending again */
+- dbfs_atomic_inc(&cnt.num_tx_flow_on_ind);
++ dbfs_atomic_inc_unchecked(&cnt.num_tx_flow_on_ind);
+ set_tx_flow_on(cf_sk);
+ cf_sk->sk.sk_state_change(&cf_sk->sk);
+ break;
+
+ case CAIF_CTRLCMD_FLOW_OFF_IND:
+ /* Modem asks us to shut up */
+- dbfs_atomic_inc(&cnt.num_tx_flow_off_ind);
++ dbfs_atomic_inc_unchecked(&cnt.num_tx_flow_off_ind);
+ set_tx_flow_off(cf_sk);
+ cf_sk->sk.sk_state_change(&cf_sk->sk);
+ break;
+
+ case CAIF_CTRLCMD_INIT_RSP:
+ /* We're now connected */
+- dbfs_atomic_inc(&cnt.num_connect_resp);
++ dbfs_atomic_inc_unchecked(&cnt.num_connect_resp);
+ cf_sk->sk.sk_state = CAIF_CONNECTED;
+ set_tx_flow_on(cf_sk);
+ cf_sk->sk.sk_state_change(&cf_sk->sk);
+@@ -247,7 +248,7 @@ static void caif_ctrl_cb(struct cflayer
+
+ case CAIF_CTRLCMD_INIT_FAIL_RSP:
+ /* Connect request failed */
+- dbfs_atomic_inc(&cnt.num_connect_fail_resp);
++ dbfs_atomic_inc_unchecked(&cnt.num_connect_fail_resp);
+ cf_sk->sk.sk_err = ECONNREFUSED;
+ cf_sk->sk.sk_state = CAIF_DISCONNECTED;
+ cf_sk->sk.sk_shutdown = SHUTDOWN_MASK;
+@@ -261,7 +262,7 @@ static void caif_ctrl_cb(struct cflayer
+
+ case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
+ /* Modem has closed this connection, or device is down. */
+- dbfs_atomic_inc(&cnt.num_remote_shutdown_ind);
++ dbfs_atomic_inc_unchecked(&cnt.num_remote_shutdown_ind);
+ cf_sk->sk.sk_shutdown = SHUTDOWN_MASK;
+ cf_sk->sk.sk_err = ECONNRESET;
+ set_rx_flow_on(cf_sk);
+@@ -281,7 +282,7 @@ static void caif_check_flow_release(stru
+ return;
+
+ if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) {
+- dbfs_atomic_inc(&cnt.num_rx_flow_on);
++ dbfs_atomic_inc_unchecked(&cnt.num_rx_flow_on);
+ set_rx_flow_on(cf_sk);
+ caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_ON_REQ);
+ }
+@@ -864,7 +865,7 @@ static int caif_connect(struct socket *s
+ /*ifindex = id of the interface.*/
+ cf_sk->conn_req.ifindex = cf_sk->sk.sk_bound_dev_if;
+
+- dbfs_atomic_inc(&cnt.num_connect_req);
++ dbfs_atomic_inc_unchecked(&cnt.num_connect_req);
+ cf_sk->layer.receive = caif_sktrecv_cb;
+ err = caif_connect_client(&cf_sk->conn_req,
+ &cf_sk->layer, &ifindex, &headroom, &tailroom);
+@@ -952,7 +953,7 @@ static int caif_release(struct socket *s
+ spin_unlock(&sk->sk_receive_queue.lock);
+ sock->sk = NULL;
+
+- dbfs_atomic_inc(&cnt.num_disconnect);
++ dbfs_atomic_inc_unchecked(&cnt.num_disconnect);
+
+ if (cf_sk->debugfs_socket_dir != NULL)
+ debugfs_remove_recursive(cf_sk->debugfs_socket_dir);
+diff -urNp linux-2.6.38.7/net/caif/cfctrl.c linux-2.6.38.7/net/caif/cfctrl.c
+--- linux-2.6.38.7/net/caif/cfctrl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/caif/cfctrl.c 2011-05-16 21:47:08.000000000 -0400
+@@ -9,6 +9,7 @@
+ #include <linux/stddef.h>
+ #include <linux/spinlock.h>
+ #include <linux/slab.h>
++#include <linux/sched.h>
+ #include <net/caif/caif_layer.h>
+ #include <net/caif/cfpkt.h>
+ #include <net/caif/cfctrl.h>
+@@ -46,8 +47,8 @@ struct cflayer *cfctrl_create(void)
+ dev_info.id = 0xff;
+ memset(this, 0, sizeof(*this));
+ cfsrvl_init(&this->serv, 0, &dev_info, false);
+- atomic_set(&this->req_seq_no, 1);
+- atomic_set(&this->rsp_seq_no, 1);
++ atomic_set_unchecked(&this->req_seq_no, 1);
++ atomic_set_unchecked(&this->rsp_seq_no, 1);
+ this->serv.layer.receive = cfctrl_recv;
+ sprintf(this->serv.layer.name, "ctrl");
+ this->serv.layer.ctrlcmd = cfctrl_ctrlcmd;
+@@ -116,8 +117,8 @@ void cfctrl_insert_req(struct cfctrl *ct
+ struct cfctrl_request_info *req)
+ {
+ spin_lock(&ctrl->info_list_lock);
+- atomic_inc(&ctrl->req_seq_no);
+- req->sequence_no = atomic_read(&ctrl->req_seq_no);
++ atomic_inc_unchecked(&ctrl->req_seq_no);
++ req->sequence_no = atomic_read_unchecked(&ctrl->req_seq_no);
+ list_add_tail(&req->list, &ctrl->list);
+ spin_unlock(&ctrl->info_list_lock);
+ }
+@@ -136,7 +137,7 @@ struct cfctrl_request_info *cfctrl_remov
+ if (p != first)
+ pr_warn("Requests are not received in order\n");
+
+- atomic_set(&ctrl->rsp_seq_no,
++ atomic_set_unchecked(&ctrl->rsp_seq_no,
+ p->sequence_no);
+ list_del(&p->list);
+ goto out;
+@@ -385,6 +386,7 @@ static int cfctrl_recv(struct cflayer *l
+ struct cfctrl *cfctrl = container_obj(layer);
+ struct cfctrl_request_info rsp, *req;
+
++ pax_track_stack();
+
+ cfpkt_extr_head(pkt, &cmdrsp, 1);
+ cmd = cmdrsp & CFCTRL_CMD_MASK;
+diff -urNp linux-2.6.38.7/net/can/bcm.c linux-2.6.38.7/net/can/bcm.c
+--- linux-2.6.38.7/net/can/bcm.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/net/can/bcm.c 2011-05-10 22:09:01.000000000 -0400
+@@ -165,9 +165,15 @@ static int bcm_proc_show(struct seq_file
+ struct bcm_sock *bo = bcm_sk(sk);
+ struct bcm_op *op;
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ seq_printf(m, ">>> socket %p", NULL);
++ seq_printf(m, " / sk %p", NULL);
++ seq_printf(m, " / bo %p", NULL);
++#else
+ seq_printf(m, ">>> socket %p", sk->sk_socket);
+ seq_printf(m, " / sk %p", sk);
+ seq_printf(m, " / bo %p", bo);
++#endif
+ seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
+ seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex));
+ seq_printf(m, " <<<\n");
+diff -urNp linux-2.6.38.7/net/core/datagram.c linux-2.6.38.7/net/core/datagram.c
+--- linux-2.6.38.7/net/core/datagram.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/core/datagram.c 2011-04-28 19:57:25.000000000 -0400
+@@ -285,7 +285,7 @@ int skb_kill_datagram(struct sock *sk, s
+ }
+
+ kfree_skb(skb);
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ sk_mem_reclaim_partial(sk);
+
+ return err;
+diff -urNp linux-2.6.38.7/net/core/dev.c linux-2.6.38.7/net/core/dev.c
+--- linux-2.6.38.7/net/core/dev.c 2011-05-22 23:05:21.000000000 -0400
++++ linux-2.6.38.7/net/core/dev.c 2011-05-22 23:06:04.000000000 -0400
+@@ -1124,10 +1124,14 @@ void dev_load(struct net *net, const cha
+ if (no_module && capable(CAP_NET_ADMIN))
+ no_module = request_module("netdev-%s", name);
+ if (no_module && capable(CAP_SYS_MODULE)) {
++#ifdef CONFIG_GRKERNSEC_MODHARDEN
++ ___request_module(true, "grsec_modharden_netdev", "%s", name);
++#else
+ if (!request_module("%s", name))
+ pr_err("Loading kernel module for a network device "
+ "with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%s "
+ "instead\n", name);
++#endif
+ }
+ }
+ EXPORT_SYMBOL(dev_load);
+@@ -2789,7 +2793,7 @@ int netif_rx_ni(struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL(netif_rx_ni);
+
+-static void net_tx_action(struct softirq_action *h)
++static void net_tx_action(void)
+ {
+ struct softnet_data *sd = &__get_cpu_var(softnet_data);
+
+@@ -3699,7 +3703,7 @@ void netif_napi_del(struct napi_struct *
+ }
+ EXPORT_SYMBOL(netif_napi_del);
+
+-static void net_rx_action(struct softirq_action *h)
++static void net_rx_action(void)
+ {
+ struct softnet_data *sd = &__get_cpu_var(softnet_data);
+ unsigned long time_limit = jiffies + 2;
+diff -urNp linux-2.6.38.7/net/core/flow.c linux-2.6.38.7/net/core/flow.c
+--- linux-2.6.38.7/net/core/flow.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/core/flow.c 2011-04-28 19:57:25.000000000 -0400
+@@ -60,7 +60,7 @@ struct flow_cache {
+ struct timer_list rnd_timer;
+ };
+
+-atomic_t flow_cache_genid = ATOMIC_INIT(0);
++atomic_unchecked_t flow_cache_genid = ATOMIC_INIT(0);
+ EXPORT_SYMBOL(flow_cache_genid);
+ static struct flow_cache flow_cache_global;
+ static struct kmem_cache *flow_cachep __read_mostly;
+@@ -85,7 +85,7 @@ static void flow_cache_new_hashrnd(unsig
+
+ static int flow_entry_valid(struct flow_cache_entry *fle)
+ {
+- if (atomic_read(&flow_cache_genid) != fle->genid)
++ if (atomic_read_unchecked(&flow_cache_genid) != fle->genid)
+ return 0;
+ if (fle->object && !fle->object->ops->check(fle->object))
+ return 0;
+@@ -253,7 +253,7 @@ flow_cache_lookup(struct net *net, struc
+ hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]);
+ fcp->hash_count++;
+ }
+- } else if (likely(fle->genid == atomic_read(&flow_cache_genid))) {
++ } else if (likely(fle->genid == atomic_read_unchecked(&flow_cache_genid))) {
+ flo = fle->object;
+ if (!flo)
+ goto ret_object;
+@@ -274,7 +274,7 @@ nocache:
+ }
+ flo = resolver(net, key, family, dir, flo, ctx);
+ if (fle) {
+- fle->genid = atomic_read(&flow_cache_genid);
++ fle->genid = atomic_read_unchecked(&flow_cache_genid);
+ if (!IS_ERR(flo))
+ fle->object = flo;
+ else
+diff -urNp linux-2.6.38.7/net/core/skbuff.c linux-2.6.38.7/net/core/skbuff.c
+--- linux-2.6.38.7/net/core/skbuff.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/core/skbuff.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1543,6 +1543,8 @@ int skb_splice_bits(struct sk_buff *skb,
+ struct sock *sk = skb->sk;
+ int ret = 0;
+
++ pax_track_stack();
++
+ if (splice_grow_spd(pipe, &spd))
+ return -ENOMEM;
+
+diff -urNp linux-2.6.38.7/net/core/sock.c linux-2.6.38.7/net/core/sock.c
+--- linux-2.6.38.7/net/core/sock.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/core/sock.c 2011-04-28 19:57:25.000000000 -0400
+@@ -291,7 +291,7 @@ int sock_queue_rcv_skb(struct sock *sk,
+ */
+ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+ (unsigned)sk->sk_rcvbuf) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ return -ENOMEM;
+ }
+
+@@ -300,7 +300,7 @@ int sock_queue_rcv_skb(struct sock *sk,
+ return err;
+
+ if (!sk_rmem_schedule(sk, skb->truesize)) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ return -ENOBUFS;
+ }
+
+@@ -320,7 +320,7 @@ int sock_queue_rcv_skb(struct sock *sk,
+ skb_dst_force(skb);
+
+ spin_lock_irqsave(&list->lock, flags);
+- skb->dropcount = atomic_read(&sk->sk_drops);
++ skb->dropcount = atomic_read_unchecked(&sk->sk_drops);
+ __skb_queue_tail(list, skb);
+ spin_unlock_irqrestore(&list->lock, flags);
+
+@@ -340,7 +340,7 @@ int sk_receive_skb(struct sock *sk, stru
+ skb->dev = NULL;
+
+ if (sk_rcvqueues_full(sk, skb)) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ goto discard_and_relse;
+ }
+ if (nested)
+@@ -358,7 +358,7 @@ int sk_receive_skb(struct sock *sk, stru
+ mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_);
+ } else if (sk_add_backlog(sk, skb)) {
+ bh_unlock_sock(sk);
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ goto discard_and_relse;
+ }
+
+@@ -934,7 +934,7 @@ int sock_getsockopt(struct socket *sock,
+ return -ENOTCONN;
+ if (lv < len)
+ return -EINVAL;
+- if (copy_to_user(optval, address, len))
++ if (len > sizeof(address) || copy_to_user(optval, address, len))
+ return -EFAULT;
+ goto lenout;
+ }
+@@ -967,7 +967,7 @@ int sock_getsockopt(struct socket *sock,
+
+ if (len > lv)
+ len = lv;
+- if (copy_to_user(optval, &v, len))
++ if (len > sizeof(v) || copy_to_user(optval, &v, len))
+ return -EFAULT;
+ lenout:
+ if (put_user(len, optlen))
+@@ -2023,7 +2023,7 @@ void sock_init_data(struct socket *sock,
+ */
+ smp_wmb();
+ atomic_set(&sk->sk_refcnt, 1);
+- atomic_set(&sk->sk_drops, 0);
++ atomic_set_unchecked(&sk->sk_drops, 0);
+ }
+ EXPORT_SYMBOL(sock_init_data);
+
+diff -urNp linux-2.6.38.7/net/decnet/sysctl_net_decnet.c linux-2.6.38.7/net/decnet/sysctl_net_decnet.c
+--- linux-2.6.38.7/net/decnet/sysctl_net_decnet.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/decnet/sysctl_net_decnet.c 2011-04-28 19:34:15.000000000 -0400
+@@ -173,7 +173,7 @@ static int dn_node_address_handler(ctl_t
+
+ if (len > *lenp) len = *lenp;
+
+- if (copy_to_user(buffer, addr, len))
++ if (len > sizeof addr || copy_to_user(buffer, addr, len))
+ return -EFAULT;
+
+ *lenp = len;
+@@ -236,7 +236,7 @@ static int dn_def_dev_handler(ctl_table
+
+ if (len > *lenp) len = *lenp;
+
+- if (copy_to_user(buffer, devname, len))
++ if (len > sizeof devname || copy_to_user(buffer, devname, len))
+ return -EFAULT;
+
+ *lenp = len;
+diff -urNp linux-2.6.38.7/net/econet/Kconfig linux-2.6.38.7/net/econet/Kconfig
+--- linux-2.6.38.7/net/econet/Kconfig 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/econet/Kconfig 2011-04-28 19:34:15.000000000 -0400
+@@ -4,7 +4,7 @@
+
+ config ECONET
+ tristate "Acorn Econet/AUN protocols (EXPERIMENTAL)"
+- depends on EXPERIMENTAL && INET
++ depends on EXPERIMENTAL && INET && BROKEN
+ ---help---
+ Econet is a fairly old and slow networking protocol mainly used by
+ Acorn computers to access file and print servers. It uses native
+diff -urNp linux-2.6.38.7/net/ipv4/inet_diag.c linux-2.6.38.7/net/ipv4/inet_diag.c
+--- linux-2.6.38.7/net/ipv4/inet_diag.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/inet_diag.c 2011-04-28 19:34:15.000000000 -0400
+@@ -114,8 +114,14 @@ static int inet_csk_diag_fill(struct soc
+ r->idiag_retrans = 0;
+
+ r->id.idiag_if = sk->sk_bound_dev_if;
++
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ r->id.idiag_cookie[0] = 0;
++ r->id.idiag_cookie[1] = 0;
++#else
+ r->id.idiag_cookie[0] = (u32)(unsigned long)sk;
+ r->id.idiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1);
++#endif
+
+ r->id.idiag_sport = inet->inet_sport;
+ r->id.idiag_dport = inet->inet_dport;
+@@ -201,8 +207,15 @@ static int inet_twsk_diag_fill(struct in
+ r->idiag_family = tw->tw_family;
+ r->idiag_retrans = 0;
+ r->id.idiag_if = tw->tw_bound_dev_if;
++
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ r->id.idiag_cookie[0] = 0;
++ r->id.idiag_cookie[1] = 0;
++#else
+ r->id.idiag_cookie[0] = (u32)(unsigned long)tw;
+ r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1);
++#endif
++
+ r->id.idiag_sport = tw->tw_sport;
+ r->id.idiag_dport = tw->tw_dport;
+ r->id.idiag_src[0] = tw->tw_rcv_saddr;
+@@ -285,12 +298,14 @@ static int inet_diag_get_exact(struct sk
+ if (sk == NULL)
+ goto unlock;
+
++#ifndef CONFIG_GRKERNSEC_HIDESYM
+ err = -ESTALE;
+ if ((req->id.idiag_cookie[0] != INET_DIAG_NOCOOKIE ||
+ req->id.idiag_cookie[1] != INET_DIAG_NOCOOKIE) &&
+ ((u32)(unsigned long)sk != req->id.idiag_cookie[0] ||
+ (u32)((((unsigned long)sk) >> 31) >> 1) != req->id.idiag_cookie[1]))
+ goto out;
++#endif
+
+ err = -ENOMEM;
+ rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) +
+@@ -582,8 +597,14 @@ static int inet_diag_fill_req(struct sk_
+ r->idiag_retrans = req->retrans;
+
+ r->id.idiag_if = sk->sk_bound_dev_if;
++
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ r->id.idiag_cookie[0] = 0;
++ r->id.idiag_cookie[1] = 0;
++#else
+ r->id.idiag_cookie[0] = (u32)(unsigned long)req;
+ r->id.idiag_cookie[1] = (u32)(((unsigned long)req >> 31) >> 1);
++#endif
+
+ tmo = req->expires - jiffies;
+ if (tmo < 0)
+diff -urNp linux-2.6.38.7/net/ipv4/inet_hashtables.c linux-2.6.38.7/net/ipv4/inet_hashtables.c
+--- linux-2.6.38.7/net/ipv4/inet_hashtables.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/inet_hashtables.c 2011-04-28 19:34:15.000000000 -0400
+@@ -18,11 +18,14 @@
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/wait.h>
++#include <linux/security.h>
+
+ #include <net/inet_connection_sock.h>
+ #include <net/inet_hashtables.h>
+ #include <net/ip.h>
+
++extern void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet);
++
+ /*
+ * Allocate and initialize a new local port bind bucket.
+ * The bindhash mutex for snum's hash chain must be held here.
+@@ -529,6 +532,8 @@ ok:
+ twrefcnt += inet_twsk_bind_unhash(tw, hinfo);
+ spin_unlock(&head->lock);
+
++ gr_update_task_in_ip_table(current, inet_sk(sk));
++
+ if (tw) {
+ inet_twsk_deschedule(tw, death_row);
+ while (twrefcnt) {
+diff -urNp linux-2.6.38.7/net/ipv4/inetpeer.c linux-2.6.38.7/net/ipv4/inetpeer.c
+--- linux-2.6.38.7/net/ipv4/inetpeer.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/inetpeer.c 2011-05-16 21:47:08.000000000 -0400
+@@ -478,6 +478,8 @@ struct inet_peer *inet_getpeer(struct in
+ struct inet_peer_base *base = family_to_base(daddr->family);
+ struct inet_peer *p;
+
++ pax_track_stack();
++
+ /* Look up for the address quickly, lockless.
+ * Because of a concurrent writer, we might not find an existing entry.
+ */
+@@ -509,8 +511,8 @@ struct inet_peer *inet_getpeer(struct in
+ if (p) {
+ p->daddr = *daddr;
+ atomic_set(&p->refcnt, 1);
+- atomic_set(&p->rid, 0);
+- atomic_set(&p->ip_id_count, secure_ip_id(daddr->a4));
++ atomic_set_unchecked(&p->rid, 0);
++ atomic_set_unchecked(&p->ip_id_count, secure_ip_id(daddr->a4));
+ p->tcp_ts_stamp = 0;
+ INIT_LIST_HEAD(&p->unused);
+
+diff -urNp linux-2.6.38.7/net/ipv4/ip_fragment.c linux-2.6.38.7/net/ipv4/ip_fragment.c
+--- linux-2.6.38.7/net/ipv4/ip_fragment.c 2011-05-22 23:05:21.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/ip_fragment.c 2011-05-22 23:06:04.000000000 -0400
+@@ -297,7 +297,7 @@ static inline int ip_frag_too_far(struct
+ return 0;
+
+ start = qp->rid;
+- end = atomic_inc_return(&peer->rid);
++ end = atomic_inc_return_unchecked(&peer->rid);
+ qp->rid = end;
+
+ rc = qp->q.fragments && (end - start) > max;
+diff -urNp linux-2.6.38.7/net/ipv4/ip_sockglue.c linux-2.6.38.7/net/ipv4/ip_sockglue.c
+--- linux-2.6.38.7/net/ipv4/ip_sockglue.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/ip_sockglue.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1064,6 +1064,8 @@ static int do_ip_getsockopt(struct sock
+ int val;
+ int len;
+
++ pax_track_stack();
++
+ if (level != SOL_IP)
+ return -EOPNOTSUPP;
+
+diff -urNp linux-2.6.38.7/net/ipv4/netfilter/nf_nat_snmp_basic.c linux-2.6.38.7/net/ipv4/netfilter/nf_nat_snmp_basic.c
+--- linux-2.6.38.7/net/ipv4/netfilter/nf_nat_snmp_basic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/netfilter/nf_nat_snmp_basic.c 2011-04-28 19:34:15.000000000 -0400
+@@ -398,7 +398,7 @@ static unsigned char asn1_octets_decode(
+
+ *len = 0;
+
+- *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
++ *octets = kmalloc((eoc - ctx->pointer), GFP_ATOMIC);
+ if (*octets == NULL) {
+ if (net_ratelimit())
+ pr_notice("OOM in bsalg (%d)\n", __LINE__);
+diff -urNp linux-2.6.38.7/net/ipv4/raw.c linux-2.6.38.7/net/ipv4/raw.c
+--- linux-2.6.38.7/net/ipv4/raw.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/raw.c 2011-05-04 18:00:09.000000000 -0400
+@@ -302,7 +302,7 @@ static int raw_rcv_skb(struct sock * sk,
+ int raw_rcv(struct sock *sk, struct sk_buff *skb)
+ {
+ if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ }
+@@ -724,15 +724,19 @@ static int raw_init(struct sock *sk)
+
+ static int raw_seticmpfilter(struct sock *sk, char __user *optval, int optlen)
+ {
++ struct icmp_filter filter;
++
+ if (optlen > sizeof(struct icmp_filter))
+ optlen = sizeof(struct icmp_filter);
+- if (copy_from_user(&raw_sk(sk)->filter, optval, optlen))
++ if (copy_from_user(&filter, optval, optlen))
+ return -EFAULT;
++ memcpy(&raw_sk(sk)->filter, &filter, sizeof(filter));
+ return 0;
+ }
+
+ static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *optlen)
+ {
++ struct icmp_filter filter;
+ int len, ret = -EFAULT;
+
+ if (get_user(len, optlen))
+@@ -743,8 +747,9 @@ static int raw_geticmpfilter(struct sock
+ if (len > sizeof(struct icmp_filter))
+ len = sizeof(struct icmp_filter);
+ ret = -EFAULT;
++ memcpy(&filter, &raw_sk(sk)->filter, len);
+ if (put_user(len, optlen) ||
+- copy_to_user(optval, &raw_sk(sk)->filter, len))
++ copy_to_user(optval, &filter, len))
+ goto out;
+ ret = 0;
+ out: return ret;
+@@ -972,7 +977,13 @@ static void raw_sock_seq_show(struct seq
+ sk_wmem_alloc_get(sp),
+ sk_rmem_alloc_get(sp),
+ 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
+- atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
++ atomic_read(&sp->sk_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
++ sp,
++#endif
++ atomic_read_unchecked(&sp->sk_drops));
+ }
+
+ static int raw_seq_show(struct seq_file *seq, void *v)
+diff -urNp linux-2.6.38.7/net/ipv4/route.c linux-2.6.38.7/net/ipv4/route.c
+--- linux-2.6.38.7/net/ipv4/route.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/route.c 2011-04-28 19:57:25.000000000 -0400
+@@ -270,7 +270,7 @@ static inline unsigned int rt_hash(__be3
+
+ static inline int rt_genid(struct net *net)
+ {
+- return atomic_read(&net->ipv4.rt_genid);
++ return atomic_read_unchecked(&net->ipv4.rt_genid);
+ }
+
+ #ifdef CONFIG_PROC_FS
+@@ -895,7 +895,7 @@ static void rt_cache_invalidate(struct n
+ unsigned char shuffle;
+
+ get_random_bytes(&shuffle, sizeof(shuffle));
+- atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
++ atomic_add_unchecked(shuffle + 1U, &net->ipv4.rt_genid);
+ }
+
+ /*
+@@ -2857,7 +2857,7 @@ static int rt_fill_info(struct net *net,
+ expires = rt->dst.expires ? rt->dst.expires - jiffies : 0;
+ if (rt->peer) {
+ inet_peer_refcheck(rt->peer);
+- id = atomic_read(&rt->peer->ip_id_count) & 0xffff;
++ id = atomic_read_unchecked(&rt->peer->ip_id_count) & 0xffff;
+ if (rt->peer->tcp_ts_stamp) {
+ ts = rt->peer->tcp_ts;
+ tsage = get_seconds() - rt->peer->tcp_ts_stamp;
+diff -urNp linux-2.6.38.7/net/ipv4/tcp.c linux-2.6.38.7/net/ipv4/tcp.c
+--- linux-2.6.38.7/net/ipv4/tcp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/tcp.c 2011-05-16 21:47:09.000000000 -0400
+@@ -2121,6 +2121,8 @@ static int do_tcp_setsockopt(struct sock
+ int val;
+ int err = 0;
+
++ pax_track_stack();
++
+ /* These are data/string values, all the others are ints */
+ switch (optname) {
+ case TCP_CONGESTION: {
+@@ -2500,6 +2502,8 @@ static int do_tcp_getsockopt(struct sock
+ struct tcp_sock *tp = tcp_sk(sk);
+ int val, len;
+
++ pax_track_stack();
++
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+diff -urNp linux-2.6.38.7/net/ipv4/tcp_ipv4.c linux-2.6.38.7/net/ipv4/tcp_ipv4.c
+--- linux-2.6.38.7/net/ipv4/tcp_ipv4.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/tcp_ipv4.c 2011-04-28 19:34:15.000000000 -0400
+@@ -86,6 +86,9 @@ int sysctl_tcp_tw_reuse __read_mostly;
+ int sysctl_tcp_low_latency __read_mostly;
+ EXPORT_SYMBOL(sysctl_tcp_low_latency);
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++extern int grsec_enable_blackhole;
++#endif
+
+ #ifdef CONFIG_TCP_MD5SIG
+ static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
+@@ -1593,6 +1596,9 @@ int tcp_v4_do_rcv(struct sock *sk, struc
+ return 0;
+
+ reset:
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!grsec_enable_blackhole)
++#endif
+ tcp_v4_send_reset(rsk, skb);
+ discard:
+ kfree_skb(skb);
+@@ -1655,12 +1661,19 @@ int tcp_v4_rcv(struct sk_buff *skb)
+ TCP_SKB_CB(skb)->sacked = 0;
+
+ sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
+- if (!sk)
++ if (!sk) {
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ ret = 1;
++#endif
+ goto no_tcp_socket;
+-
++ }
+ process:
+- if (sk->sk_state == TCP_TIME_WAIT)
++ if (sk->sk_state == TCP_TIME_WAIT) {
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ ret = 2;
++#endif
+ goto do_time_wait;
++ }
+
+ if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
+ NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
+@@ -1710,6 +1723,10 @@ no_tcp_socket:
+ bad_packet:
+ TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
+ } else {
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!grsec_enable_blackhole || (ret == 1 &&
++ (skb->dev->flags & IFF_LOOPBACK)))
++#endif
+ tcp_v4_send_reset(NULL, skb);
+ }
+
+@@ -2373,7 +2390,11 @@ static void get_openreq4(struct sock *sk
+ 0, /* non standard timer */
+ 0, /* open_requests have no inode */
+ atomic_read(&sk->sk_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
+ req,
++#endif
+ len);
+ }
+
+@@ -2423,7 +2444,12 @@ static void get_tcp4_sock(struct sock *s
+ sock_i_uid(sk),
+ icsk->icsk_probes_out,
+ sock_i_ino(sk),
+- atomic_read(&sk->sk_refcnt), sk,
++ atomic_read(&sk->sk_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
++ sk,
++#endif
+ jiffies_to_clock_t(icsk->icsk_rto),
+ jiffies_to_clock_t(icsk->icsk_ack.ato),
+ (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
+@@ -2451,7 +2477,13 @@ static void get_timewait4_sock(struct in
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p%n",
+ i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
+ 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
+- atomic_read(&tw->tw_refcnt), tw, len);
++ atomic_read(&tw->tw_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
++ tw,
++#endif
++ len);
+ }
+
+ #define TMPSZ 150
+diff -urNp linux-2.6.38.7/net/ipv4/tcp_minisocks.c linux-2.6.38.7/net/ipv4/tcp_minisocks.c
+--- linux-2.6.38.7/net/ipv4/tcp_minisocks.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/tcp_minisocks.c 2011-04-28 19:34:15.000000000 -0400
+@@ -27,6 +27,10 @@
+ #include <net/inet_common.h>
+ #include <net/xfrm.h>
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++extern int grsec_enable_blackhole;
++#endif
++
+ int sysctl_tcp_syncookies __read_mostly = 1;
+ EXPORT_SYMBOL(sysctl_tcp_syncookies);
+
+@@ -745,6 +749,10 @@ listen_overflow:
+
+ embryonic_reset:
+ NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
++
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!grsec_enable_blackhole)
++#endif
+ if (!(flg & TCP_FLAG_RST))
+ req->rsk_ops->send_reset(sk, skb);
+
+diff -urNp linux-2.6.38.7/net/ipv4/tcp_output.c linux-2.6.38.7/net/ipv4/tcp_output.c
+--- linux-2.6.38.7/net/ipv4/tcp_output.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/tcp_output.c 2011-05-16 21:47:09.000000000 -0400
+@@ -2420,6 +2420,8 @@ struct sk_buff *tcp_make_synack(struct s
+ int mss;
+ int s_data_desired = 0;
+
++ pax_track_stack();
++
+ if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
+ s_data_desired = cvp->s_data_desired;
+ skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15 + s_data_desired, 1, GFP_ATOMIC);
+diff -urNp linux-2.6.38.7/net/ipv4/tcp_probe.c linux-2.6.38.7/net/ipv4/tcp_probe.c
+--- linux-2.6.38.7/net/ipv4/tcp_probe.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/tcp_probe.c 2011-04-28 19:34:15.000000000 -0400
+@@ -202,7 +202,7 @@ static ssize_t tcpprobe_read(struct file
+ if (cnt + width >= len)
+ break;
+
+- if (copy_to_user(buf + cnt, tbuf, width))
++ if (width > sizeof tbuf || copy_to_user(buf + cnt, tbuf, width))
+ return -EFAULT;
+ cnt += width;
+ }
+diff -urNp linux-2.6.38.7/net/ipv4/tcp_timer.c linux-2.6.38.7/net/ipv4/tcp_timer.c
+--- linux-2.6.38.7/net/ipv4/tcp_timer.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/tcp_timer.c 2011-04-28 19:34:15.000000000 -0400
+@@ -22,6 +22,10 @@
+ #include <linux/gfp.h>
+ #include <net/tcp.h>
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++extern int grsec_lastack_retries;
++#endif
++
+ int sysctl_tcp_syn_retries __read_mostly = TCP_SYN_RETRIES;
+ int sysctl_tcp_synack_retries __read_mostly = TCP_SYNACK_RETRIES;
+ int sysctl_tcp_keepalive_time __read_mostly = TCP_KEEPALIVE_TIME;
+@@ -199,6 +203,13 @@ static int tcp_write_timeout(struct sock
+ }
+ }
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if ((sk->sk_state == TCP_LAST_ACK) &&
++ (grsec_lastack_retries > 0) &&
++ (grsec_lastack_retries < retry_until))
++ retry_until = grsec_lastack_retries;
++#endif
++
+ if (retransmits_timed_out(sk, retry_until,
+ syn_set ? 0 : icsk->icsk_user_timeout, syn_set)) {
+ /* Has it gone just too far? */
+diff -urNp linux-2.6.38.7/net/ipv4/udp.c linux-2.6.38.7/net/ipv4/udp.c
+--- linux-2.6.38.7/net/ipv4/udp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv4/udp.c 2011-04-28 20:09:30.000000000 -0400
+@@ -86,6 +86,7 @@
+ #include <linux/types.h>
+ #include <linux/fcntl.h>
+ #include <linux/module.h>
++#include <linux/security.h>
+ #include <linux/socket.h>
+ #include <linux/sockios.h>
+ #include <linux/igmp.h>
+@@ -107,6 +108,10 @@
+ #include <net/xfrm.h>
+ #include "udp_impl.h"
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++extern int grsec_enable_blackhole;
++#endif
++
+ struct udp_table udp_table __read_mostly;
+ EXPORT_SYMBOL(udp_table);
+
+@@ -564,6 +569,9 @@ found:
+ return s;
+ }
+
++extern int gr_search_udp_recvmsg(struct sock *sk, const struct sk_buff *skb);
++extern int gr_search_udp_sendmsg(struct sock *sk, struct sockaddr_in *addr);
++
+ /*
+ * This routine is called by the ICMP module when it gets some
+ * sort of error condition. If err < 0 then the socket should
+@@ -832,9 +840,18 @@ int udp_sendmsg(struct kiocb *iocb, stru
+ dport = usin->sin_port;
+ if (dport == 0)
+ return -EINVAL;
++
++ err = gr_search_udp_sendmsg(sk, usin);
++ if (err)
++ return err;
+ } else {
+ if (sk->sk_state != TCP_ESTABLISHED)
+ return -EDESTADDRREQ;
++
++ err = gr_search_udp_sendmsg(sk, NULL);
++ if (err)
++ return err;
++
+ daddr = inet->inet_daddr;
+ dport = inet->inet_dport;
+ /* Open fast path for connected socket.
+@@ -1053,7 +1070,7 @@ static unsigned int first_packet_length(
+ udp_lib_checksum_complete(skb)) {
+ UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS,
+ IS_UDPLITE(sk));
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ __skb_unlink(skb, rcvq);
+ __skb_queue_tail(&list_kill, skb);
+ }
+@@ -1139,6 +1156,10 @@ try_again:
+ if (!skb)
+ goto out;
+
++ err = gr_search_udp_recvmsg(sk, skb);
++ if (err)
++ goto out_free;
++
+ ulen = skb->len - sizeof(struct udphdr);
+ if (len > ulen)
+ len = ulen;
+@@ -1435,7 +1456,7 @@ int udp_queue_rcv_skb(struct sock *sk, s
+
+ drop:
+ UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ kfree_skb(skb);
+ return -1;
+ }
+@@ -1454,7 +1475,7 @@ static void flush_stack(struct sock **st
+ skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC);
+
+ if (!skb1) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS,
+ IS_UDPLITE(sk));
+ UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS,
+@@ -1623,6 +1644,9 @@ int __udp4_lib_rcv(struct sk_buff *skb,
+ goto csum_error;
+
+ UDP_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!grsec_enable_blackhole || (skb->dev->flags & IFF_LOOPBACK))
++#endif
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+ /*
+@@ -2050,8 +2074,13 @@ static void udp4_format_sock(struct sock
+ sk_wmem_alloc_get(sp),
+ sk_rmem_alloc_get(sp),
+ 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
+- atomic_read(&sp->sk_refcnt), sp,
+- atomic_read(&sp->sk_drops), len);
++ atomic_read(&sp->sk_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
++ sp,
++#endif
++ atomic_read_unchecked(&sp->sk_drops), len);
+ }
+
+ int udp4_seq_show(struct seq_file *seq, void *v)
+diff -urNp linux-2.6.38.7/net/ipv6/inet6_connection_sock.c linux-2.6.38.7/net/ipv6/inet6_connection_sock.c
+--- linux-2.6.38.7/net/ipv6/inet6_connection_sock.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv6/inet6_connection_sock.c 2011-04-28 19:57:25.000000000 -0400
+@@ -183,7 +183,7 @@ void __inet6_csk_dst_store(struct sock *
+ #ifdef CONFIG_XFRM
+ {
+ struct rt6_info *rt = (struct rt6_info *)dst;
+- rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
++ rt->rt6i_flow_cache_genid = atomic_read_unchecked(&flow_cache_genid);
+ }
+ #endif
+ }
+@@ -198,7 +198,7 @@ struct dst_entry *__inet6_csk_dst_check(
+ #ifdef CONFIG_XFRM
+ if (dst) {
+ struct rt6_info *rt = (struct rt6_info *)dst;
+- if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) {
++ if (rt->rt6i_flow_cache_genid != atomic_read_unchecked(&flow_cache_genid)) {
+ __sk_dst_reset(sk);
+ dst = NULL;
+ }
+diff -urNp linux-2.6.38.7/net/ipv6/inet6_hashtables.c linux-2.6.38.7/net/ipv6/inet6_hashtables.c
+--- linux-2.6.38.7/net/ipv6/inet6_hashtables.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv6/inet6_hashtables.c 2011-05-11 18:35:16.000000000 -0400
+@@ -124,7 +124,7 @@ out:
+ }
+ EXPORT_SYMBOL(__inet6_lookup_established);
+
+-static int inline compute_score(struct sock *sk, struct net *net,
++static inline int compute_score(struct sock *sk, struct net *net,
+ const unsigned short hnum,
+ const struct in6_addr *daddr,
+ const int dif)
+diff -urNp linux-2.6.38.7/net/ipv6/ipv6_sockglue.c linux-2.6.38.7/net/ipv6/ipv6_sockglue.c
+--- linux-2.6.38.7/net/ipv6/ipv6_sockglue.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv6/ipv6_sockglue.c 2011-05-16 21:47:09.000000000 -0400
+@@ -129,6 +129,8 @@ static int do_ipv6_setsockopt(struct soc
+ int val, valbool;
+ int retv = -ENOPROTOOPT;
+
++ pax_track_stack();
++
+ if (optval == NULL)
+ val=0;
+ else {
+@@ -919,6 +921,8 @@ static int do_ipv6_getsockopt(struct soc
+ int len;
+ int val;
+
++ pax_track_stack();
++
+ if (ip6_mroute_opt(optname))
+ return ip6_mroute_getsockopt(sk, optname, optval, optlen);
+
+diff -urNp linux-2.6.38.7/net/ipv6/raw.c linux-2.6.38.7/net/ipv6/raw.c
+--- linux-2.6.38.7/net/ipv6/raw.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv6/raw.c 2011-05-16 21:47:08.000000000 -0400
+@@ -376,7 +376,7 @@ static inline int rawv6_rcv_skb(struct s
+ {
+ if ((raw6_sk(sk)->checksum || rcu_dereference_raw(sk->sk_filter)) &&
+ skb_checksum_complete(skb)) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ }
+@@ -403,7 +403,7 @@ int rawv6_rcv(struct sock *sk, struct sk
+ struct raw6_sock *rp = raw6_sk(sk);
+
+ if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ }
+@@ -427,7 +427,7 @@ int rawv6_rcv(struct sock *sk, struct sk
+
+ if (inet->hdrincl) {
+ if (skb_checksum_complete(skb)) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ }
+@@ -602,7 +602,7 @@ out:
+ return err;
+ }
+
+-static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
++static int rawv6_send_hdrinc(struct sock *sk, void *from, unsigned int length,
+ struct flowi *fl, struct dst_entry **dstp,
+ unsigned int flags)
+ {
+@@ -743,6 +743,8 @@ static int rawv6_sendmsg(struct kiocb *i
+ u16 proto;
+ int err;
+
++ pax_track_stack();
++
+ /* Rough check on arithmetic overflow,
+ better check is made in ip6_append_data().
+ */
+@@ -919,12 +921,15 @@ do_confirm:
+ static int rawv6_seticmpfilter(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
+ {
++ struct icmp6_filter filter;
++
+ switch (optname) {
+ case ICMPV6_FILTER:
+ if (optlen > sizeof(struct icmp6_filter))
+ optlen = sizeof(struct icmp6_filter);
+- if (copy_from_user(&raw6_sk(sk)->filter, optval, optlen))
++ if (copy_from_user(&filter, optval, optlen))
+ return -EFAULT;
++ memcpy(&raw6_sk(sk)->filter, &filter, optlen);
+ return 0;
+ default:
+ return -ENOPROTOOPT;
+@@ -936,6 +941,7 @@ static int rawv6_seticmpfilter(struct so
+ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+ {
++ struct icmp6_filter filter;
+ int len;
+
+ switch (optname) {
+@@ -948,7 +954,8 @@ static int rawv6_geticmpfilter(struct so
+ len = sizeof(struct icmp6_filter);
+ if (put_user(len, optlen))
+ return -EFAULT;
+- if (copy_to_user(optval, &raw6_sk(sk)->filter, len))
++ memcpy(&filter, &raw6_sk(sk)->filter, len);
++ if (copy_to_user(optval, &filter, len))
+ return -EFAULT;
+ return 0;
+ default:
+@@ -1262,7 +1269,13 @@ static void raw6_sock_seq_show(struct se
+ 0, 0L, 0,
+ sock_i_uid(sp), 0,
+ sock_i_ino(sp),
+- atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
++ atomic_read(&sp->sk_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
++ sp,
++#endif
++ atomic_read_unchecked(&sp->sk_drops));
+ }
+
+ static int raw6_seq_show(struct seq_file *seq, void *v)
+diff -urNp linux-2.6.38.7/net/ipv6/tcp_ipv6.c linux-2.6.38.7/net/ipv6/tcp_ipv6.c
+--- linux-2.6.38.7/net/ipv6/tcp_ipv6.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv6/tcp_ipv6.c 2011-04-28 19:34:15.000000000 -0400
+@@ -92,6 +92,10 @@ static struct tcp_md5sig_key *tcp_v6_md5
+ }
+ #endif
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++extern int grsec_enable_blackhole;
++#endif
++
+ static void tcp_v6_hash(struct sock *sk)
+ {
+ if (sk->sk_state != TCP_CLOSE) {
+@@ -1676,6 +1680,9 @@ static int tcp_v6_do_rcv(struct sock *sk
+ return 0;
+
+ reset:
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!grsec_enable_blackhole)
++#endif
+ tcp_v6_send_reset(sk, skb);
+ discard:
+ if (opt_skb)
+@@ -1755,12 +1762,20 @@ static int tcp_v6_rcv(struct sk_buff *sk
+ TCP_SKB_CB(skb)->sacked = 0;
+
+ sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
+- if (!sk)
++ if (!sk) {
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ ret = 1;
++#endif
+ goto no_tcp_socket;
++ }
+
+ process:
+- if (sk->sk_state == TCP_TIME_WAIT)
++ if (sk->sk_state == TCP_TIME_WAIT) {
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ ret = 2;
++#endif
+ goto do_time_wait;
++ }
+
+ if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) {
+ NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
+@@ -1808,6 +1823,10 @@ no_tcp_socket:
+ bad_packet:
+ TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
+ } else {
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!grsec_enable_blackhole || (ret == 1 &&
++ (skb->dev->flags & IFF_LOOPBACK)))
++#endif
+ tcp_v6_send_reset(NULL, skb);
+ }
+
+@@ -2068,7 +2087,13 @@ static void get_openreq6(struct seq_file
+ uid,
+ 0, /* non standard timer */
+ 0, /* open_requests have no inode */
+- 0, req);
++ 0,
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL
++#else
++ req
++#endif
++ );
+ }
+
+ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
+@@ -2118,7 +2143,12 @@ static void get_tcp6_sock(struct seq_fil
+ sock_i_uid(sp),
+ icsk->icsk_probes_out,
+ sock_i_ino(sp),
+- atomic_read(&sp->sk_refcnt), sp,
++ atomic_read(&sp->sk_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
++ sp,
++#endif
+ jiffies_to_clock_t(icsk->icsk_rto),
+ jiffies_to_clock_t(icsk->icsk_ack.ato),
+ (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
+@@ -2153,7 +2183,13 @@ static void get_timewait6_sock(struct se
+ dest->s6_addr32[2], dest->s6_addr32[3], destp,
+ tw->tw_substate, 0, 0,
+ 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
+- atomic_read(&tw->tw_refcnt), tw);
++ atomic_read(&tw->tw_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL
++#else
++ tw
++#endif
++ );
+ }
+
+ static int tcp6_seq_show(struct seq_file *seq, void *v)
+diff -urNp linux-2.6.38.7/net/ipv6/udp.c linux-2.6.38.7/net/ipv6/udp.c
+--- linux-2.6.38.7/net/ipv6/udp.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/ipv6/udp.c 2011-04-28 20:09:04.000000000 -0400
+@@ -50,6 +50,10 @@
+ #include <linux/seq_file.h>
+ #include "udp_impl.h"
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++extern int grsec_enable_blackhole;
++#endif
++
+ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
+ {
+ const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;
+@@ -542,7 +546,7 @@ int udpv6_queue_rcv_skb(struct sock * sk
+
+ return 0;
+ drop:
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ drop_no_sk_drops_inc:
+ UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
+ kfree_skb(skb);
+@@ -618,7 +622,7 @@ static void flush_stack(struct sock **st
+ continue;
+ }
+ drop:
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ UDP6_INC_STATS_BH(sock_net(sk),
+ UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk));
+ UDP6_INC_STATS_BH(sock_net(sk),
+@@ -773,6 +777,9 @@ int __udp6_lib_rcv(struct sk_buff *skb,
+ UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS,
+ proto == IPPROTO_UDPLITE);
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!grsec_enable_blackhole || (skb->dev->flags & IFF_LOOPBACK))
++#endif
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
+
+ kfree_skb(skb);
+@@ -789,7 +796,7 @@ int __udp6_lib_rcv(struct sk_buff *skb,
+ if (!sock_owned_by_user(sk))
+ udpv6_queue_rcv_skb(sk, skb);
+ else if (sk_add_backlog(sk, skb)) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ bh_unlock_sock(sk);
+ sock_put(sk);
+ goto discard;
+@@ -1407,8 +1414,13 @@ static void udp6_sock_seq_show(struct se
+ 0, 0L, 0,
+ sock_i_uid(sp), 0,
+ sock_i_ino(sp),
+- atomic_read(&sp->sk_refcnt), sp,
+- atomic_read(&sp->sk_drops));
++ atomic_read(&sp->sk_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
++ sp,
++#endif
++ atomic_read_unchecked(&sp->sk_drops));
+ }
+
+ int udp6_seq_show(struct seq_file *seq, void *v)
+diff -urNp linux-2.6.38.7/net/irda/ircomm/ircomm_tty.c linux-2.6.38.7/net/irda/ircomm/ircomm_tty.c
+--- linux-2.6.38.7/net/irda/ircomm/ircomm_tty.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/irda/ircomm/ircomm_tty.c 2011-04-28 19:34:15.000000000 -0400
+@@ -281,16 +281,16 @@ static int ircomm_tty_block_til_ready(st
+ add_wait_queue(&self->open_wait, &wait);
+
+ IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
+- __FILE__,__LINE__, tty->driver->name, self->open_count );
++ __FILE__,__LINE__, tty->driver->name, local_read(&self->open_count) );
+
+ /* As far as I can see, we protect open_count - Jean II */
+ spin_lock_irqsave(&self->spinlock, flags);
+ if (!tty_hung_up_p(filp)) {
+ extra_count = 1;
+- self->open_count--;
++ local_dec(&self->open_count);
+ }
+ spin_unlock_irqrestore(&self->spinlock, flags);
+- self->blocked_open++;
++ local_inc(&self->blocked_open);
+
+ while (1) {
+ if (tty->termios->c_cflag & CBAUD) {
+@@ -330,7 +330,7 @@ static int ircomm_tty_block_til_ready(st
+ }
+
+ IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
+- __FILE__,__LINE__, tty->driver->name, self->open_count );
++ __FILE__,__LINE__, tty->driver->name, local_read(&self->open_count) );
+
+ schedule();
+ }
+@@ -341,13 +341,13 @@ static int ircomm_tty_block_til_ready(st
+ if (extra_count) {
+ /* ++ is not atomic, so this should be protected - Jean II */
+ spin_lock_irqsave(&self->spinlock, flags);
+- self->open_count++;
++ local_inc(&self->open_count);
+ spin_unlock_irqrestore(&self->spinlock, flags);
+ }
+- self->blocked_open--;
++ local_dec(&self->blocked_open);
+
+ IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
+- __FILE__,__LINE__, tty->driver->name, self->open_count);
++ __FILE__,__LINE__, tty->driver->name, local_read(&self->open_count));
+
+ if (!retval)
+ self->flags |= ASYNC_NORMAL_ACTIVE;
+@@ -416,14 +416,14 @@ static int ircomm_tty_open(struct tty_st
+ }
+ /* ++ is not atomic, so this should be protected - Jean II */
+ spin_lock_irqsave(&self->spinlock, flags);
+- self->open_count++;
++ local_inc(&self->open_count);
+
+ tty->driver_data = self;
+ self->tty = tty;
+ spin_unlock_irqrestore(&self->spinlock, flags);
+
+ IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name,
+- self->line, self->open_count);
++ self->line, local_read(&self->open_count));
+
+ /* Not really used by us, but lets do it anyway */
+ self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+@@ -509,7 +509,7 @@ static void ircomm_tty_close(struct tty_
+ return;
+ }
+
+- if ((tty->count == 1) && (self->open_count != 1)) {
++ if ((tty->count == 1) && (local_read(&self->open_count) != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. state->count should always
+@@ -519,16 +519,16 @@ static void ircomm_tty_close(struct tty_
+ */
+ IRDA_DEBUG(0, "%s(), bad serial port count; "
+ "tty->count is 1, state->count is %d\n", __func__ ,
+- self->open_count);
+- self->open_count = 1;
++ local_read(&self->open_count));
++ local_set(&self->open_count, 1);
+ }
+
+- if (--self->open_count < 0) {
++ if (local_dec_return(&self->open_count) < 0) {
+ IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
+- __func__, self->line, self->open_count);
+- self->open_count = 0;
++ __func__, self->line, local_read(&self->open_count));
++ local_set(&self->open_count, 0);
+ }
+- if (self->open_count) {
++ if (local_read(&self->open_count)) {
+ spin_unlock_irqrestore(&self->spinlock, flags);
+
+ IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
+@@ -560,7 +560,7 @@ static void ircomm_tty_close(struct tty_
+ tty->closing = 0;
+ self->tty = NULL;
+
+- if (self->blocked_open) {
++ if (local_read(&self->blocked_open)) {
+ if (self->close_delay)
+ schedule_timeout_interruptible(self->close_delay);
+ wake_up_interruptible(&self->open_wait);
+@@ -1012,7 +1012,7 @@ static void ircomm_tty_hangup(struct tty
+ spin_lock_irqsave(&self->spinlock, flags);
+ self->flags &= ~ASYNC_NORMAL_ACTIVE;
+ self->tty = NULL;
+- self->open_count = 0;
++ local_set(&self->open_count, 0);
+ spin_unlock_irqrestore(&self->spinlock, flags);
+
+ wake_up_interruptible(&self->open_wait);
+@@ -1364,7 +1364,7 @@ static void ircomm_tty_line_info(struct
+ seq_putc(m, '\n');
+
+ seq_printf(m, "Role: %s\n", self->client ? "client" : "server");
+- seq_printf(m, "Open count: %d\n", self->open_count);
++ seq_printf(m, "Open count: %d\n", local_read(&self->open_count));
+ seq_printf(m, "Max data size: %d\n", self->max_data_size);
+ seq_printf(m, "Max header size: %d\n", self->max_header_size);
+
+diff -urNp linux-2.6.38.7/net/iucv/af_iucv.c linux-2.6.38.7/net/iucv/af_iucv.c
+--- linux-2.6.38.7/net/iucv/af_iucv.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/iucv/af_iucv.c 2011-04-28 19:57:25.000000000 -0400
+@@ -653,10 +653,10 @@ static int iucv_sock_autobind(struct soc
+
+ write_lock_bh(&iucv_sk_list.lock);
+
+- sprintf(name, "%08x", atomic_inc_return(&iucv_sk_list.autobind_name));
++ sprintf(name, "%08x", atomic_inc_return_unchecked(&iucv_sk_list.autobind_name));
+ while (__iucv_get_sock_by_name(name)) {
+ sprintf(name, "%08x",
+- atomic_inc_return(&iucv_sk_list.autobind_name));
++ atomic_inc_return_unchecked(&iucv_sk_list.autobind_name));
+ }
+
+ write_unlock_bh(&iucv_sk_list.lock);
+diff -urNp linux-2.6.38.7/net/key/af_key.c linux-2.6.38.7/net/key/af_key.c
+--- linux-2.6.38.7/net/key/af_key.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/key/af_key.c 2011-05-16 21:47:08.000000000 -0400
+@@ -2470,6 +2470,8 @@ static int pfkey_migrate(struct sock *sk
+ struct xfrm_migrate m[XFRM_MAX_DEPTH];
+ struct xfrm_kmaddress k;
+
++ pax_track_stack();
++
+ if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1],
+ ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) ||
+ !ext_hdrs[SADB_X_EXT_POLICY - 1]) {
+@@ -3003,10 +3005,10 @@ static int pfkey_send_policy_notify(stru
+ static u32 get_acqseq(void)
+ {
+ u32 res;
+- static atomic_t acqseq;
++ static atomic_unchecked_t acqseq;
+
+ do {
+- res = atomic_inc_return(&acqseq);
++ res = atomic_inc_return_unchecked(&acqseq);
+ } while (!res);
+ return res;
+ }
+@@ -3644,7 +3646,11 @@ static int pfkey_seq_show(struct seq_fil
+ seq_printf(f ,"sk RefCnt Rmem Wmem User Inode\n");
+ else
+ seq_printf(f ,"%p %-6d %-6u %-6u %-6u %-6lu\n",
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
+ s,
++#endif
+ atomic_read(&s->sk_refcnt),
+ sk_rmem_alloc_get(s),
+ sk_wmem_alloc_get(s),
+diff -urNp linux-2.6.38.7/net/mac80211/cfg.c linux-2.6.38.7/net/mac80211/cfg.c
+--- linux-2.6.38.7/net/mac80211/cfg.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/cfg.c 2011-05-10 22:09:03.000000000 -0400
+@@ -1941,7 +1941,7 @@ static int ieee80211_get_antenna(struct
+ return drv_get_antenna(local, tx_ant, rx_ant);
+ }
+
+-struct cfg80211_ops mac80211_config_ops = {
++const struct cfg80211_ops mac80211_config_ops = {
+ .add_virtual_intf = ieee80211_add_iface,
+ .del_virtual_intf = ieee80211_del_iface,
+ .change_virtual_intf = ieee80211_change_iface,
+diff -urNp linux-2.6.38.7/net/mac80211/cfg.h linux-2.6.38.7/net/mac80211/cfg.h
+--- linux-2.6.38.7/net/mac80211/cfg.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/cfg.h 2011-04-28 19:34:15.000000000 -0400
+@@ -4,6 +4,6 @@
+ #ifndef __CFG_H
+ #define __CFG_H
+
+-extern struct cfg80211_ops mac80211_config_ops;
++extern const struct cfg80211_ops mac80211_config_ops;
+
+ #endif /* __CFG_H */
+diff -urNp linux-2.6.38.7/net/mac80211/debugfs_sta.c linux-2.6.38.7/net/mac80211/debugfs_sta.c
+--- linux-2.6.38.7/net/mac80211/debugfs_sta.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/debugfs_sta.c 2011-05-16 21:47:09.000000000 -0400
+@@ -115,6 +115,8 @@ static ssize_t sta_agg_status_read(struc
+ struct tid_ampdu_rx *tid_rx;
+ struct tid_ampdu_tx *tid_tx;
+
++ pax_track_stack();
++
+ rcu_read_lock();
+
+ p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
+@@ -215,6 +217,8 @@ static ssize_t sta_ht_capa_read(struct f
+ struct sta_info *sta = file->private_data;
+ struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap;
+
++ pax_track_stack();
++
+ p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n",
+ htc->ht_supported ? "" : "not ");
+ if (htc->ht_supported) {
+diff -urNp linux-2.6.38.7/net/mac80211/ieee80211_i.h linux-2.6.38.7/net/mac80211/ieee80211_i.h
+--- linux-2.6.38.7/net/mac80211/ieee80211_i.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/ieee80211_i.h 2011-04-28 19:34:15.000000000 -0400
+@@ -27,6 +27,7 @@
+ #include <net/ieee80211_radiotap.h>
+ #include <net/cfg80211.h>
+ #include <net/mac80211.h>
++#include <asm/local.h>
+ #include "key.h"
+ #include "sta_info.h"
+
+@@ -716,7 +717,7 @@ struct ieee80211_local {
+ /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
+ spinlock_t queue_stop_reason_lock;
+
+- int open_count;
++ local_t open_count;
+ int monitors, cooked_mntrs;
+ /* number of interfaces with corresponding FIF_ flags */
+ int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
+diff -urNp linux-2.6.38.7/net/mac80211/iface.c linux-2.6.38.7/net/mac80211/iface.c
+--- linux-2.6.38.7/net/mac80211/iface.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/iface.c 2011-04-28 19:34:15.000000000 -0400
+@@ -211,7 +211,7 @@ static int ieee80211_do_open(struct net_
+ break;
+ }
+
+- if (local->open_count == 0) {
++ if (local_read(&local->open_count) == 0) {
+ res = drv_start(local);
+ if (res)
+ goto err_del_bss;
+@@ -235,7 +235,7 @@ static int ieee80211_do_open(struct net_
+ memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
+
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+- if (!local->open_count)
++ if (!local_read(&local->open_count))
+ drv_stop(local);
+ return -EADDRNOTAVAIL;
+ }
+@@ -327,7 +327,7 @@ static int ieee80211_do_open(struct net_
+ mutex_unlock(&local->mtx);
+
+ if (coming_up)
+- local->open_count++;
++ local_inc(&local->open_count);
+
+ if (hw_reconf_flags) {
+ ieee80211_hw_config(local, hw_reconf_flags);
+@@ -347,7 +347,7 @@ static int ieee80211_do_open(struct net_
+ err_del_interface:
+ drv_remove_interface(local, &sdata->vif);
+ err_stop:
+- if (!local->open_count)
++ if (!local_read(&local->open_count))
+ drv_stop(local);
+ err_del_bss:
+ sdata->bss = NULL;
+@@ -473,7 +473,7 @@ static void ieee80211_do_stop(struct iee
+ }
+
+ if (going_down)
+- local->open_count--;
++ local_dec(&local->open_count);
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP_VLAN:
+@@ -532,7 +532,7 @@ static void ieee80211_do_stop(struct iee
+
+ ieee80211_recalc_ps(local, -1);
+
+- if (local->open_count == 0) {
++ if (local_read(&local->open_count) == 0) {
+ if (local->ops->napi_poll)
+ napi_disable(&local->napi);
+ ieee80211_clear_tx_pending(local);
+diff -urNp linux-2.6.38.7/net/mac80211/main.c linux-2.6.38.7/net/mac80211/main.c
+--- linux-2.6.38.7/net/mac80211/main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/main.c 2011-04-28 19:34:15.000000000 -0400
+@@ -161,7 +161,7 @@ int ieee80211_hw_config(struct ieee80211
+ local->hw.conf.power_level = power;
+ }
+
+- if (changed && local->open_count) {
++ if (changed && local_read(&local->open_count)) {
+ ret = drv_config(local, changed);
+ /*
+ * Goal:
+diff -urNp linux-2.6.38.7/net/mac80211/mlme.c linux-2.6.38.7/net/mac80211/mlme.c
+--- linux-2.6.38.7/net/mac80211/mlme.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/mlme.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1356,6 +1356,8 @@ static bool ieee80211_assoc_success(stru
+ bool have_higher_than_11mbit = false;
+ u16 ap_ht_cap_flags;
+
++ pax_track_stack();
++
+ /* AssocResp and ReassocResp have identical structure */
+
+ aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
+diff -urNp linux-2.6.38.7/net/mac80211/pm.c linux-2.6.38.7/net/mac80211/pm.c
+--- linux-2.6.38.7/net/mac80211/pm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/pm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -95,7 +95,7 @@ int __ieee80211_suspend(struct ieee80211
+ }
+
+ /* stop hardware - this must stop RX */
+- if (local->open_count)
++ if (local_read(&local->open_count))
+ ieee80211_stop_device(local);
+
+ local->suspended = true;
+diff -urNp linux-2.6.38.7/net/mac80211/rate.c linux-2.6.38.7/net/mac80211/rate.c
+--- linux-2.6.38.7/net/mac80211/rate.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/rate.c 2011-04-28 19:34:15.000000000 -0400
+@@ -371,7 +371,7 @@ int ieee80211_init_rate_ctrl_alg(struct
+
+ ASSERT_RTNL();
+
+- if (local->open_count)
++ if (local_read(&local->open_count))
+ return -EBUSY;
+
+ if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) {
+diff -urNp linux-2.6.38.7/net/mac80211/rc80211_pid_debugfs.c linux-2.6.38.7/net/mac80211/rc80211_pid_debugfs.c
+--- linux-2.6.38.7/net/mac80211/rc80211_pid_debugfs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/rc80211_pid_debugfs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -192,7 +192,7 @@ static ssize_t rate_control_pid_events_r
+
+ spin_unlock_irqrestore(&events->lock, status);
+
+- if (copy_to_user(buf, pb, p))
++ if (p > sizeof(pb) || copy_to_user(buf, pb, p))
+ return -EFAULT;
+
+ return p;
+diff -urNp linux-2.6.38.7/net/mac80211/tx.c linux-2.6.38.7/net/mac80211/tx.c
+--- linux-2.6.38.7/net/mac80211/tx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/tx.c 2011-04-28 19:34:15.000000000 -0400
+@@ -173,7 +173,7 @@ static __le16 ieee80211_duration(struct
+ return cpu_to_le16(dur);
+ }
+
+-static int inline is_ieee80211_device(struct ieee80211_local *local,
++static inline int is_ieee80211_device(struct ieee80211_local *local,
+ struct net_device *dev)
+ {
+ return local == wdev_priv(dev->ieee80211_ptr);
+diff -urNp linux-2.6.38.7/net/mac80211/util.c linux-2.6.38.7/net/mac80211/util.c
+--- linux-2.6.38.7/net/mac80211/util.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/mac80211/util.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1135,7 +1135,7 @@ int ieee80211_reconfig(struct ieee80211_
+ local->resuming = true;
+
+ /* restart hardware */
+- if (local->open_count) {
++ if (local_read(&local->open_count)) {
+ /*
+ * Upon resume hardware can sometimes be goofy due to
+ * various platform / driver / bus issues, so restarting
+diff -urNp linux-2.6.38.7/net/netfilter/ipvs/ip_vs_app.c linux-2.6.38.7/net/netfilter/ipvs/ip_vs_app.c
+--- linux-2.6.38.7/net/netfilter/ipvs/ip_vs_app.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/ipvs/ip_vs_app.c 2011-05-17 19:31:43.000000000 -0400
+@@ -565,7 +565,7 @@ static const struct file_operations ip_v
+ .open = ip_vs_app_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release,
++ .release = seq_release_net,
+ };
+ #endif
+
+diff -urNp linux-2.6.38.7/net/netfilter/ipvs/ip_vs_conn.c linux-2.6.38.7/net/netfilter/ipvs/ip_vs_conn.c
+--- linux-2.6.38.7/net/netfilter/ipvs/ip_vs_conn.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/ipvs/ip_vs_conn.c 2011-05-17 19:31:43.000000000 -0400
+@@ -553,7 +553,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, s
+ /* Increase the refcnt counter of the dest */
+ atomic_inc(&dest->refcnt);
+
+- conn_flags = atomic_read(&dest->conn_flags);
++ conn_flags = atomic_read_unchecked(&dest->conn_flags);
+ if (cp->protocol != IPPROTO_UDP)
+ conn_flags &= ~IP_VS_CONN_F_ONE_PACKET;
+ /* Bind with the destination and its corresponding transmitter */
+@@ -840,7 +840,7 @@ ip_vs_conn_new(const struct ip_vs_conn_p
+ atomic_set(&cp->refcnt, 1);
+
+ atomic_set(&cp->n_control, 0);
+- atomic_set(&cp->in_pkts, 0);
++ atomic_set_unchecked(&cp->in_pkts, 0);
+
+ atomic_inc(&ip_vs_conn_count);
+ if (flags & IP_VS_CONN_F_NO_CPORT)
+@@ -1012,7 +1012,7 @@ static const struct file_operations ip_v
+ .open = ip_vs_conn_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release,
++ .release = seq_release_net,
+ };
+
+ static const char *ip_vs_origin_name(unsigned flags)
+@@ -1075,7 +1075,7 @@ static const struct file_operations ip_v
+ .open = ip_vs_conn_sync_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release,
++ .release = seq_release_net,
+ };
+
+ #endif
+@@ -1102,7 +1102,7 @@ static inline int todrop_entry(struct ip
+
+ /* Don't drop the entry if its number of incoming packets is not
+ located in [0, 8] */
+- i = atomic_read(&cp->in_pkts);
++ i = atomic_read_unchecked(&cp->in_pkts);
+ if (i > 8 || i < 0) return 0;
+
+ if (!todrop_rate[i]) return 0;
+diff -urNp linux-2.6.38.7/net/netfilter/ipvs/ip_vs_core.c linux-2.6.38.7/net/netfilter/ipvs/ip_vs_core.c
+--- linux-2.6.38.7/net/netfilter/ipvs/ip_vs_core.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/ipvs/ip_vs_core.c 2011-04-28 19:57:25.000000000 -0400
+@@ -504,7 +504,7 @@ int ip_vs_leave(struct ip_vs_service *sv
+ ret = cp->packet_xmit(skb, cp, pp);
+ /* do not touch skb anymore */
+
+- atomic_inc(&cp->in_pkts);
++ atomic_inc_unchecked(&cp->in_pkts);
+ ip_vs_conn_put(cp);
+ return ret;
+ }
+@@ -1536,7 +1536,7 @@ ip_vs_in(unsigned int hooknum, struct sk
+ * Sync connection if it is about to close to
+ * encorage the standby servers to update the connections timeout
+ */
+- pkts = atomic_add_return(1, &cp->in_pkts);
++ pkts = atomic_add_return_unchecked(1, &cp->in_pkts);
+ if (af == AF_INET && (ip_vs_sync_state & IP_VS_STATE_MASTER) &&
+ cp->protocol == IPPROTO_SCTP) {
+ if ((cp->state == IP_VS_SCTP_S_ESTABLISHED &&
+diff -urNp linux-2.6.38.7/net/netfilter/ipvs/ip_vs_ctl.c linux-2.6.38.7/net/netfilter/ipvs/ip_vs_ctl.c
+--- linux-2.6.38.7/net/netfilter/ipvs/ip_vs_ctl.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/ipvs/ip_vs_ctl.c 2011-05-17 19:31:43.000000000 -0400
+@@ -787,7 +787,7 @@ __ip_vs_update_dest(struct ip_vs_service
+ ip_vs_rs_hash(dest);
+ write_unlock_bh(&__ip_vs_rs_lock);
+ }
+- atomic_set(&dest->conn_flags, conn_flags);
++ atomic_set_unchecked(&dest->conn_flags, conn_flags);
+
+ /* bind the service */
+ if (!dest->svc) {
+@@ -1905,7 +1905,7 @@ static int ip_vs_info_seq_show(struct se
+ " %-7s %-6d %-10d %-10d\n",
+ &dest->addr.in6,
+ ntohs(dest->port),
+- ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
++ ip_vs_fwd_name(atomic_read_unchecked(&dest->conn_flags)),
+ atomic_read(&dest->weight),
+ atomic_read(&dest->activeconns),
+ atomic_read(&dest->inactconns));
+@@ -1916,7 +1916,7 @@ static int ip_vs_info_seq_show(struct se
+ "%-7s %-6d %-10d %-10d\n",
+ ntohl(dest->addr.ip),
+ ntohs(dest->port),
+- ip_vs_fwd_name(atomic_read(&dest->conn_flags)),
++ ip_vs_fwd_name(atomic_read_unchecked(&dest->conn_flags)),
+ atomic_read(&dest->weight),
+ atomic_read(&dest->activeconns),
+ atomic_read(&dest->inactconns));
+@@ -1944,7 +1944,7 @@ static const struct file_operations ip_v
+ .open = ip_vs_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release_net,
+ };
+
+ #endif
+@@ -1993,7 +1993,7 @@ static const struct file_operations ip_v
+ .open = ip_vs_stats_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = single_release,
++ .release = single_release_net,
+ };
+
+ #endif
+@@ -2315,7 +2315,7 @@ __ip_vs_get_dest_entries(const struct ip
+
+ entry.addr = dest->addr.ip;
+ entry.port = dest->port;
+- entry.conn_flags = atomic_read(&dest->conn_flags);
++ entry.conn_flags = atomic_read_unchecked(&dest->conn_flags);
+ entry.weight = atomic_read(&dest->weight);
+ entry.u_threshold = dest->u_threshold;
+ entry.l_threshold = dest->l_threshold;
+@@ -2376,6 +2376,8 @@ do_ip_vs_get_ctl(struct sock *sk, int cm
+ int ret = 0;
+ unsigned int copylen;
+
++ pax_track_stack();
++
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+@@ -2831,7 +2833,7 @@ static int ip_vs_genl_fill_dest(struct s
+ NLA_PUT_U16(skb, IPVS_DEST_ATTR_PORT, dest->port);
+
+ NLA_PUT_U32(skb, IPVS_DEST_ATTR_FWD_METHOD,
+- atomic_read(&dest->conn_flags) & IP_VS_CONN_F_FWD_MASK);
++ atomic_read_unchecked(&dest->conn_flags) & IP_VS_CONN_F_FWD_MASK);
+ NLA_PUT_U32(skb, IPVS_DEST_ATTR_WEIGHT, atomic_read(&dest->weight));
+ NLA_PUT_U32(skb, IPVS_DEST_ATTR_U_THRESH, dest->u_threshold);
+ NLA_PUT_U32(skb, IPVS_DEST_ATTR_L_THRESH, dest->l_threshold);
+diff -urNp linux-2.6.38.7/net/netfilter/ipvs/ip_vs_sync.c linux-2.6.38.7/net/netfilter/ipvs/ip_vs_sync.c
+--- linux-2.6.38.7/net/netfilter/ipvs/ip_vs_sync.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/ipvs/ip_vs_sync.c 2011-04-28 19:57:25.000000000 -0400
+@@ -460,7 +460,7 @@ static void ip_vs_process_message(const
+
+ if (opt)
+ memcpy(&cp->in_seq, opt, sizeof(*opt));
+- atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]);
++ atomic_set_unchecked(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]);
+ cp->state = state;
+ cp->old_state = cp->state;
+ /*
+diff -urNp linux-2.6.38.7/net/netfilter/ipvs/ip_vs_xmit.c linux-2.6.38.7/net/netfilter/ipvs/ip_vs_xmit.c
+--- linux-2.6.38.7/net/netfilter/ipvs/ip_vs_xmit.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/ipvs/ip_vs_xmit.c 2011-04-28 19:57:25.000000000 -0400
+@@ -1116,7 +1116,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, str
+ else
+ rc = NF_ACCEPT;
+ /* do not touch skb anymore */
+- atomic_inc(&cp->in_pkts);
++ atomic_inc_unchecked(&cp->in_pkts);
+ goto out;
+ }
+
+@@ -1230,7 +1230,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb,
+ else
+ rc = NF_ACCEPT;
+ /* do not touch skb anymore */
+- atomic_inc(&cp->in_pkts);
++ atomic_inc_unchecked(&cp->in_pkts);
+ goto out;
+ }
+
+diff -urNp linux-2.6.38.7/net/netfilter/Kconfig linux-2.6.38.7/net/netfilter/Kconfig
+--- linux-2.6.38.7/net/netfilter/Kconfig 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/Kconfig 2011-04-28 19:34:15.000000000 -0400
+@@ -709,6 +709,16 @@ config NETFILTER_XT_MATCH_ESP
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config NETFILTER_XT_MATCH_GRADM
++ tristate '"gradm" match support'
++ depends on NETFILTER_XTABLES && NETFILTER_ADVANCED
++ depends on GRKERNSEC && !GRKERNSEC_NO_RBAC
++ ---help---
++ The gradm match allows to match on grsecurity RBAC being enabled.
++ It is useful when iptables rules are applied early on bootup to
++ prevent connections to the machine (except from a trusted host)
++ while the RBAC system is disabled.
++
+ config NETFILTER_XT_MATCH_HASHLIMIT
+ tristate '"hashlimit" match support'
+ depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
+diff -urNp linux-2.6.38.7/net/netfilter/Makefile linux-2.6.38.7/net/netfilter/Makefile
+--- linux-2.6.38.7/net/netfilter/Makefile 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/Makefile 2011-04-28 19:34:15.000000000 -0400
+@@ -74,6 +74,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CPU) +=
+ obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
+ obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o
+ obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
++obj-$(CONFIG_NETFILTER_XT_MATCH_GRADM) += xt_gradm.o
+ obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
+ obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
+ obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o
+diff -urNp linux-2.6.38.7/net/netfilter/nf_conntrack_netlink.c linux-2.6.38.7/net/netfilter/nf_conntrack_netlink.c
+--- linux-2.6.38.7/net/netfilter/nf_conntrack_netlink.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/nf_conntrack_netlink.c 2011-04-28 19:34:15.000000000 -0400
+@@ -761,7 +761,7 @@ static const struct nla_policy tuple_nla
+ static int
+ ctnetlink_parse_tuple(const struct nlattr * const cda[],
+ struct nf_conntrack_tuple *tuple,
+- enum ctattr_tuple type, u_int8_t l3num)
++ enum ctattr_type type, u_int8_t l3num)
+ {
+ struct nlattr *tb[CTA_TUPLE_MAX+1];
+ int err;
+diff -urNp linux-2.6.38.7/net/netfilter/nfnetlink_log.c linux-2.6.38.7/net/netfilter/nfnetlink_log.c
+--- linux-2.6.38.7/net/netfilter/nfnetlink_log.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/nfnetlink_log.c 2011-04-28 19:57:25.000000000 -0400
+@@ -70,7 +70,7 @@ struct nfulnl_instance {
+ };
+
+ static DEFINE_SPINLOCK(instances_lock);
+-static atomic_t global_seq;
++static atomic_unchecked_t global_seq;
+
+ #define INSTANCE_BUCKETS 16
+ static struct hlist_head instance_table[INSTANCE_BUCKETS];
+@@ -507,7 +507,7 @@ __build_packet_message(struct nfulnl_ins
+ /* global sequence number */
+ if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
+ NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL,
+- htonl(atomic_inc_return(&global_seq)));
++ htonl(atomic_inc_return_unchecked(&global_seq)));
+
+ if (data_len) {
+ struct nlattr *nla;
+diff -urNp linux-2.6.38.7/net/netfilter/nfnetlink_queue.c linux-2.6.38.7/net/netfilter/nfnetlink_queue.c
+--- linux-2.6.38.7/net/netfilter/nfnetlink_queue.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/nfnetlink_queue.c 2011-04-28 19:57:25.000000000 -0400
+@@ -58,7 +58,7 @@ struct nfqnl_instance {
+ */
+ spinlock_t lock;
+ unsigned int queue_total;
+- atomic_t id_sequence; /* 'sequence' of pkt ids */
++ atomic_unchecked_t id_sequence; /* 'sequence' of pkt ids */
+ struct list_head queue_list; /* packets in queue */
+ };
+
+@@ -272,7 +272,7 @@ nfqnl_build_packet_message(struct nfqnl_
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = htons(queue->queue_num);
+
+- entry->id = atomic_inc_return(&queue->id_sequence);
++ entry->id = atomic_inc_return_unchecked(&queue->id_sequence);
+ pmsg.packet_id = htonl(entry->id);
+ pmsg.hw_protocol = entskb->protocol;
+ pmsg.hook = entry->hook;
+@@ -863,7 +863,7 @@ static int seq_show(struct seq_file *s,
+ inst->peer_pid, inst->queue_total,
+ inst->copy_mode, inst->copy_range,
+ inst->queue_dropped, inst->queue_user_dropped,
+- atomic_read(&inst->id_sequence), 1);
++ atomic_read_unchecked(&inst->id_sequence), 1);
+ }
+
+ static const struct seq_operations nfqnl_seq_ops = {
+diff -urNp linux-2.6.38.7/net/netfilter/xt_gradm.c linux-2.6.38.7/net/netfilter/xt_gradm.c
+--- linux-2.6.38.7/net/netfilter/xt_gradm.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.38.7/net/netfilter/xt_gradm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -0,0 +1,51 @@
++/*
++ * gradm match for netfilter
++ * Copyright © Zbigniew Krzystolik, 2010
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License; either version
++ * 2 or 3 as published by the Free Software Foundation.
++ */
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter/x_tables.h>
++#include <linux/grsecurity.h>
++#include <linux/netfilter/xt_gradm.h>
++
++static bool
++gradm_mt(const struct sk_buff *skb, struct xt_action_param *par)
++{
++ const struct xt_gradm_mtinfo *info = par->matchinfo;
++ bool retval = false;
++ if (gr_acl_is_enabled())
++ retval = true;
++ return retval ^ info->invflags;
++}
++
++static struct xt_match gradm_mt_reg __read_mostly = {
++ .name = "gradm",
++ .revision = 0,
++ .family = NFPROTO_UNSPEC,
++ .match = gradm_mt,
++ .matchsize = XT_ALIGN(sizeof(struct xt_gradm_mtinfo)),
++ .me = THIS_MODULE,
++};
++
++static int __init gradm_mt_init(void)
++{
++ return xt_register_match(&gradm_mt_reg);
++}
++
++static void __exit gradm_mt_exit(void)
++{
++ xt_unregister_match(&gradm_mt_reg);
++}
++
++module_init(gradm_mt_init);
++module_exit(gradm_mt_exit);
++MODULE_AUTHOR("Zbigniew Krzystolik <zbyniu@destrukcja.pl>");
++MODULE_DESCRIPTION("Xtables: Grsecurity RBAC match");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("ipt_gradm");
++MODULE_ALIAS("ip6t_gradm");
+diff -urNp linux-2.6.38.7/net/netfilter/xt_statistic.c linux-2.6.38.7/net/netfilter/xt_statistic.c
+--- linux-2.6.38.7/net/netfilter/xt_statistic.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netfilter/xt_statistic.c 2011-04-28 19:57:25.000000000 -0400
+@@ -18,7 +18,7 @@
+ #include <linux/netfilter/x_tables.h>
+
+ struct xt_statistic_priv {
+- atomic_t count;
++ atomic_unchecked_t count;
+ } ____cacheline_aligned_in_smp;
+
+ MODULE_LICENSE("GPL");
+@@ -41,9 +41,9 @@ statistic_mt(const struct sk_buff *skb,
+ break;
+ case XT_STATISTIC_MODE_NTH:
+ do {
+- oval = atomic_read(&info->master->count);
++ oval = atomic_read_unchecked(&info->master->count);
+ nval = (oval == info->u.nth.every) ? 0 : oval + 1;
+- } while (atomic_cmpxchg(&info->master->count, oval, nval) != oval);
++ } while (atomic_cmpxchg_unchecked(&info->master->count, oval, nval) != oval);
+ if (nval == 0)
+ ret = !ret;
+ break;
+@@ -63,7 +63,7 @@ static int statistic_mt_check(const stru
+ info->master = kzalloc(sizeof(*info->master), GFP_KERNEL);
+ if (info->master == NULL)
+ return -ENOMEM;
+- atomic_set(&info->master->count, info->u.nth.count);
++ atomic_set_unchecked(&info->master->count, info->u.nth.count);
+
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/net/netlink/af_netlink.c linux-2.6.38.7/net/netlink/af_netlink.c
+--- linux-2.6.38.7/net/netlink/af_netlink.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netlink/af_netlink.c 2011-04-28 19:57:25.000000000 -0400
+@@ -742,7 +742,7 @@ static void netlink_overrun(struct sock
+ sk->sk_error_report(sk);
+ }
+ }
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ }
+
+ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
+@@ -2001,15 +2001,23 @@ static int netlink_seq_show(struct seq_f
+ struct netlink_sock *nlk = nlk_sk(s);
+
+ seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d %-8lu\n",
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
+ s,
++#endif
+ s->sk_protocol,
+ nlk->pid,
+ nlk->groups ? (u32)nlk->groups[0] : 0,
+ sk_rmem_alloc_get(s),
+ sk_wmem_alloc_get(s),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
+ nlk->cb,
++#endif
+ atomic_read(&s->sk_refcnt),
+- atomic_read(&s->sk_drops),
++ atomic_read_unchecked(&s->sk_drops),
+ sock_i_ino(s)
+ );
+
+diff -urNp linux-2.6.38.7/net/netrom/af_netrom.c linux-2.6.38.7/net/netrom/af_netrom.c
+--- linux-2.6.38.7/net/netrom/af_netrom.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/netrom/af_netrom.c 2011-04-28 19:34:15.000000000 -0400
+@@ -840,6 +840,7 @@ static int nr_getname(struct socket *soc
+ struct sock *sk = sock->sk;
+ struct nr_sock *nr = nr_sk(sk);
+
++ memset(sax, 0, sizeof(*sax));
+ lock_sock(sk);
+ if (peer != 0) {
+ if (sk->sk_state != TCP_ESTABLISHED) {
+@@ -854,7 +855,6 @@ static int nr_getname(struct socket *soc
+ *uaddr_len = sizeof(struct full_sockaddr_ax25);
+ } else {
+ sax->fsa_ax25.sax25_family = AF_NETROM;
+- sax->fsa_ax25.sax25_ndigis = 0;
+ sax->fsa_ax25.sax25_call = nr->source_addr;
+ *uaddr_len = sizeof(struct sockaddr_ax25);
+ }
+diff -urNp linux-2.6.38.7/net/packet/af_packet.c linux-2.6.38.7/net/packet/af_packet.c
+--- linux-2.6.38.7/net/packet/af_packet.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/packet/af_packet.c 2011-04-28 19:57:25.000000000 -0400
+@@ -635,14 +635,14 @@ static int packet_rcv(struct sk_buff *sk
+
+ spin_lock(&sk->sk_receive_queue.lock);
+ po->stats.tp_packets++;
+- skb->dropcount = atomic_read(&sk->sk_drops);
++ skb->dropcount = atomic_read_unchecked(&sk->sk_drops);
+ __skb_queue_tail(&sk->sk_receive_queue, skb);
+ spin_unlock(&sk->sk_receive_queue.lock);
+ sk->sk_data_ready(sk, skb->len);
+ return 0;
+
+ drop_n_acct:
+- po->stats.tp_drops = atomic_inc_return(&sk->sk_drops);
++ po->stats.tp_drops = atomic_inc_return_unchecked(&sk->sk_drops);
+
+ drop_n_restore:
+ if (skb_head != skb->data && skb_shared(skb)) {
+@@ -2134,7 +2134,7 @@ static int packet_getsockopt(struct sock
+ case PACKET_HDRLEN:
+ if (len > sizeof(int))
+ len = sizeof(int);
+- if (copy_from_user(&val, optval, len))
++ if (len > sizeof(val) || copy_from_user(&val, optval, len))
+ return -EFAULT;
+ switch (val) {
+ case TPACKET_V1:
+@@ -2172,7 +2172,7 @@ static int packet_getsockopt(struct sock
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+- if (copy_to_user(optval, data, len))
++ if (len > sizeof(st) || copy_to_user(optval, data, len))
+ return -EFAULT;
+ return 0;
+ }
+@@ -2684,7 +2684,11 @@ static int packet_seq_show(struct seq_fi
+
+ seq_printf(seq,
+ "%p %-6d %-4d %04x %-5d %1d %-6u %-6u %-6lu\n",
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
+ s,
++#endif
+ atomic_read(&s->sk_refcnt),
+ s->sk_type,
+ ntohs(po->num),
+diff -urNp linux-2.6.38.7/net/phonet/af_phonet.c linux-2.6.38.7/net/phonet/af_phonet.c
+--- linux-2.6.38.7/net/phonet/af_phonet.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/phonet/af_phonet.c 2011-04-28 19:34:15.000000000 -0400
+@@ -41,7 +41,7 @@ static struct phonet_protocol *phonet_pr
+ {
+ struct phonet_protocol *pp;
+
+- if (protocol >= PHONET_NPROTO)
++ if (protocol < 0 || protocol >= PHONET_NPROTO)
+ return NULL;
+
+ rcu_read_lock();
+@@ -463,7 +463,7 @@ int __init_or_module phonet_proto_regist
+ {
+ int err = 0;
+
+- if (protocol >= PHONET_NPROTO)
++ if (protocol < 0 || protocol >= PHONET_NPROTO)
+ return -EINVAL;
+
+ err = proto_register(pp->prot, 1);
+diff -urNp linux-2.6.38.7/net/phonet/pep.c linux-2.6.38.7/net/phonet/pep.c
+--- linux-2.6.38.7/net/phonet/pep.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/phonet/pep.c 2011-04-28 19:57:25.000000000 -0400
+@@ -592,7 +592,7 @@ static int pipe_do_rcv(struct sock *sk,
+
+ case PNS_PEP_CTRL_REQ:
+ if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ break;
+ }
+ __skb_pull(skb, 4);
+@@ -612,7 +612,7 @@ static int pipe_do_rcv(struct sock *sk,
+ }
+
+ if (pn->rx_credits == 0) {
+- atomic_inc(&sk->sk_drops);
++ atomic_inc_unchecked(&sk->sk_drops);
+ err = -ENOBUFS;
+ break;
+ }
+diff -urNp linux-2.6.38.7/net/phonet/socket.c linux-2.6.38.7/net/phonet/socket.c
+--- linux-2.6.38.7/net/phonet/socket.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/phonet/socket.c 2011-04-28 20:09:57.000000000 -0400
+@@ -637,8 +637,13 @@ static int pn_sock_seq_show(struct seq_f
+ sk->sk_state,
+ sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
+ sock_i_uid(sk), sock_i_ino(sk),
+- atomic_read(&sk->sk_refcnt), sk,
+- atomic_read(&sk->sk_drops), &len);
++ atomic_read(&sk->sk_refcnt),
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
++ sk,
++#endif
++ atomic_read_unchecked(&sk->sk_drops), &len);
+ }
+ seq_printf(seq, "%*s\n", 127 - len, "");
+ return 0;
+diff -urNp linux-2.6.38.7/net/rds/cong.c linux-2.6.38.7/net/rds/cong.c
+--- linux-2.6.38.7/net/rds/cong.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rds/cong.c 2011-04-28 19:57:25.000000000 -0400
+@@ -78,7 +78,7 @@
+ * finds that the saved generation number is smaller than the global generation
+ * number, it wakes up the process.
+ */
+-static atomic_t rds_cong_generation = ATOMIC_INIT(0);
++static atomic_unchecked_t rds_cong_generation = ATOMIC_INIT(0);
+
+ /*
+ * Congestion monitoring
+@@ -233,7 +233,7 @@ void rds_cong_map_updated(struct rds_con
+ rdsdebug("waking map %p for %pI4\n",
+ map, &map->m_addr);
+ rds_stats_inc(s_cong_update_received);
+- atomic_inc(&rds_cong_generation);
++ atomic_inc_unchecked(&rds_cong_generation);
+ if (waitqueue_active(&map->m_waitq))
+ wake_up(&map->m_waitq);
+ if (waitqueue_active(&rds_poll_waitq))
+@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(rds_cong_map_updated);
+
+ int rds_cong_updated_since(unsigned long *recent)
+ {
+- unsigned long gen = atomic_read(&rds_cong_generation);
++ unsigned long gen = atomic_read_unchecked(&rds_cong_generation);
+
+ if (likely(*recent == gen))
+ return 0;
+diff -urNp linux-2.6.38.7/net/rds/ib_cm.c linux-2.6.38.7/net/rds/ib_cm.c
+--- linux-2.6.38.7/net/rds/ib_cm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rds/ib_cm.c 2011-05-11 18:35:16.000000000 -0400
+@@ -720,7 +720,7 @@ void rds_ib_conn_shutdown(struct rds_con
+ /* Clear the ACK state */
+ clear_bit(IB_ACK_IN_FLIGHT, &ic->i_ack_flags);
+ #ifdef KERNEL_HAS_ATOMIC64
+- atomic64_set(&ic->i_ack_next, 0);
++ atomic64_set_unchecked(&ic->i_ack_next, 0);
+ #else
+ ic->i_ack_next = 0;
+ #endif
+diff -urNp linux-2.6.38.7/net/rds/ib.h linux-2.6.38.7/net/rds/ib.h
+--- linux-2.6.38.7/net/rds/ib.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rds/ib.h 2011-05-11 18:35:16.000000000 -0400
+@@ -127,7 +127,7 @@ struct rds_ib_connection {
+ /* sending acks */
+ unsigned long i_ack_flags;
+ #ifdef KERNEL_HAS_ATOMIC64
+- atomic64_t i_ack_next; /* next ACK to send */
++ atomic64_unchecked_t i_ack_next; /* next ACK to send */
+ #else
+ spinlock_t i_ack_lock; /* protect i_ack_next */
+ u64 i_ack_next; /* next ACK to send */
+diff -urNp linux-2.6.38.7/net/rds/ib_recv.c linux-2.6.38.7/net/rds/ib_recv.c
+--- linux-2.6.38.7/net/rds/ib_recv.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rds/ib_recv.c 2011-05-11 18:35:16.000000000 -0400
+@@ -592,7 +592,7 @@ static u64 rds_ib_get_ack(struct rds_ib_
+ static void rds_ib_set_ack(struct rds_ib_connection *ic, u64 seq,
+ int ack_required)
+ {
+- atomic64_set(&ic->i_ack_next, seq);
++ atomic64_set_unchecked(&ic->i_ack_next, seq);
+ if (ack_required) {
+ smp_mb__before_clear_bit();
+ set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags);
+@@ -604,7 +604,7 @@ static u64 rds_ib_get_ack(struct rds_ib_
+ clear_bit(IB_ACK_REQUESTED, &ic->i_ack_flags);
+ smp_mb__after_clear_bit();
+
+- return atomic64_read(&ic->i_ack_next);
++ return atomic64_read_unchecked(&ic->i_ack_next);
+ }
+ #endif
+
+diff -urNp linux-2.6.38.7/net/rds/iw_cm.c linux-2.6.38.7/net/rds/iw_cm.c
+--- linux-2.6.38.7/net/rds/iw_cm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rds/iw_cm.c 2011-05-11 18:35:16.000000000 -0400
+@@ -664,7 +664,7 @@ void rds_iw_conn_shutdown(struct rds_con
+ /* Clear the ACK state */
+ clear_bit(IB_ACK_IN_FLIGHT, &ic->i_ack_flags);
+ #ifdef KERNEL_HAS_ATOMIC64
+- atomic64_set(&ic->i_ack_next, 0);
++ atomic64_set_unchecked(&ic->i_ack_next, 0);
+ #else
+ ic->i_ack_next = 0;
+ #endif
+diff -urNp linux-2.6.38.7/net/rds/iw.h linux-2.6.38.7/net/rds/iw.h
+--- linux-2.6.38.7/net/rds/iw.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rds/iw.h 2011-05-11 18:35:16.000000000 -0400
+@@ -133,7 +133,7 @@ struct rds_iw_connection {
+ /* sending acks */
+ unsigned long i_ack_flags;
+ #ifdef KERNEL_HAS_ATOMIC64
+- atomic64_t i_ack_next; /* next ACK to send */
++ atomic64_unchecked_t i_ack_next; /* next ACK to send */
+ #else
+ spinlock_t i_ack_lock; /* protect i_ack_next */
+ u64 i_ack_next; /* next ACK to send */
+diff -urNp linux-2.6.38.7/net/rds/iw_rdma.c linux-2.6.38.7/net/rds/iw_rdma.c
+--- linux-2.6.38.7/net/rds/iw_rdma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rds/iw_rdma.c 2011-05-16 21:47:09.000000000 -0400
+@@ -182,6 +182,8 @@ int rds_iw_update_cm_id(struct rds_iw_de
+ struct rdma_cm_id *pcm_id;
+ int rc;
+
++ pax_track_stack();
++
+ src_addr = (struct sockaddr_in *)&cm_id->route.addr.src_addr;
+ dst_addr = (struct sockaddr_in *)&cm_id->route.addr.dst_addr;
+
+diff -urNp linux-2.6.38.7/net/rds/iw_recv.c linux-2.6.38.7/net/rds/iw_recv.c
+--- linux-2.6.38.7/net/rds/iw_recv.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rds/iw_recv.c 2011-05-11 18:35:16.000000000 -0400
+@@ -427,7 +427,7 @@ static u64 rds_iw_get_ack(struct rds_iw_
+ static void rds_iw_set_ack(struct rds_iw_connection *ic, u64 seq,
+ int ack_required)
+ {
+- atomic64_set(&ic->i_ack_next, seq);
++ atomic64_set_unchecked(&ic->i_ack_next, seq);
+ if (ack_required) {
+ smp_mb__before_clear_bit();
+ set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags);
+@@ -439,7 +439,7 @@ static u64 rds_iw_get_ack(struct rds_iw_
+ clear_bit(IB_ACK_REQUESTED, &ic->i_ack_flags);
+ smp_mb__after_clear_bit();
+
+- return atomic64_read(&ic->i_ack_next);
++ return atomic64_read_unchecked(&ic->i_ack_next);
+ }
+ #endif
+
+diff -urNp linux-2.6.38.7/net/rxrpc/af_rxrpc.c linux-2.6.38.7/net/rxrpc/af_rxrpc.c
+--- linux-2.6.38.7/net/rxrpc/af_rxrpc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/af_rxrpc.c 2011-04-28 19:57:25.000000000 -0400
+@@ -39,7 +39,7 @@ static const struct proto_ops rxrpc_rpc_
+ __be32 rxrpc_epoch;
+
+ /* current debugging ID */
+-atomic_t rxrpc_debug_id;
++atomic_unchecked_t rxrpc_debug_id;
+
+ /* count of skbs currently in use */
+ atomic_t rxrpc_n_skbs;
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-ack.c linux-2.6.38.7/net/rxrpc/ar-ack.c
+--- linux-2.6.38.7/net/rxrpc/ar-ack.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-ack.c 2011-05-16 21:47:08.000000000 -0400
+@@ -175,7 +175,7 @@ static void rxrpc_resend(struct rxrpc_ca
+
+ _enter("{%d,%d,%d,%d},",
+ call->acks_hard, call->acks_unacked,
+- atomic_read(&call->sequence),
++ atomic_read_unchecked(&call->sequence),
+ CIRC_CNT(call->acks_head, call->acks_tail, call->acks_winsz));
+
+ stop = 0;
+@@ -199,7 +199,7 @@ static void rxrpc_resend(struct rxrpc_ca
+
+ /* each Tx packet has a new serial number */
+ sp->hdr.serial =
+- htonl(atomic_inc_return(&call->conn->serial));
++ htonl(atomic_inc_return_unchecked(&call->conn->serial));
+
+ hdr = (struct rxrpc_header *) txb->head;
+ hdr->serial = sp->hdr.serial;
+@@ -405,7 +405,7 @@ static void rxrpc_rotate_tx_window(struc
+ */
+ static void rxrpc_clear_tx_window(struct rxrpc_call *call)
+ {
+- rxrpc_rotate_tx_window(call, atomic_read(&call->sequence));
++ rxrpc_rotate_tx_window(call, atomic_read_unchecked(&call->sequence));
+ }
+
+ /*
+@@ -631,7 +631,7 @@ process_further:
+
+ latest = ntohl(sp->hdr.serial);
+ hard = ntohl(ack.firstPacket);
+- tx = atomic_read(&call->sequence);
++ tx = atomic_read_unchecked(&call->sequence);
+
+ _proto("Rx ACK %%%u { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }",
+ latest,
+@@ -844,6 +844,8 @@ void rxrpc_process_call(struct work_stru
+ u32 abort_code = RX_PROTOCOL_ERROR;
+ u8 *acks = NULL;
+
++ pax_track_stack();
++
+ //printk("\n--------------------\n");
+ _enter("{%d,%s,%lx} [%lu]",
+ call->debug_id, rxrpc_call_states[call->state], call->events,
+@@ -1163,7 +1165,7 @@ void rxrpc_process_call(struct work_stru
+ goto maybe_reschedule;
+
+ send_ACK_with_skew:
+- ack.maxSkew = htons(atomic_read(&call->conn->hi_serial) -
++ ack.maxSkew = htons(atomic_read_unchecked(&call->conn->hi_serial) -
+ ntohl(ack.serial));
+ send_ACK:
+ mtu = call->conn->trans->peer->if_mtu;
+@@ -1175,7 +1177,7 @@ send_ACK:
+ ackinfo.rxMTU = htonl(5692);
+ ackinfo.jumbo_max = htonl(4);
+
+- hdr.serial = htonl(atomic_inc_return(&call->conn->serial));
++ hdr.serial = htonl(atomic_inc_return_unchecked(&call->conn->serial));
+ _proto("Tx ACK %%%u { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }",
+ ntohl(hdr.serial),
+ ntohs(ack.maxSkew),
+@@ -1193,7 +1195,7 @@ send_ACK:
+ send_message:
+ _debug("send message");
+
+- hdr.serial = htonl(atomic_inc_return(&call->conn->serial));
++ hdr.serial = htonl(atomic_inc_return_unchecked(&call->conn->serial));
+ _proto("Tx %s %%%u", rxrpc_pkts[hdr.type], ntohl(hdr.serial));
+ send_message_2:
+
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-call.c linux-2.6.38.7/net/rxrpc/ar-call.c
+--- linux-2.6.38.7/net/rxrpc/ar-call.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-call.c 2011-04-28 19:57:25.000000000 -0400
+@@ -83,7 +83,7 @@ static struct rxrpc_call *rxrpc_alloc_ca
+ spin_lock_init(&call->lock);
+ rwlock_init(&call->state_lock);
+ atomic_set(&call->usage, 1);
+- call->debug_id = atomic_inc_return(&rxrpc_debug_id);
++ call->debug_id = atomic_inc_return_unchecked(&rxrpc_debug_id);
+ call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
+
+ memset(&call->sock_node, 0xed, sizeof(call->sock_node));
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-connection.c linux-2.6.38.7/net/rxrpc/ar-connection.c
+--- linux-2.6.38.7/net/rxrpc/ar-connection.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-connection.c 2011-04-28 19:57:25.000000000 -0400
+@@ -206,7 +206,7 @@ static struct rxrpc_connection *rxrpc_al
+ rwlock_init(&conn->lock);
+ spin_lock_init(&conn->state_lock);
+ atomic_set(&conn->usage, 1);
+- conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
++ conn->debug_id = atomic_inc_return_unchecked(&rxrpc_debug_id);
+ conn->avail_calls = RXRPC_MAXCALLS;
+ conn->size_align = 4;
+ conn->header_size = sizeof(struct rxrpc_header);
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-connevent.c linux-2.6.38.7/net/rxrpc/ar-connevent.c
+--- linux-2.6.38.7/net/rxrpc/ar-connevent.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-connevent.c 2011-04-28 19:57:25.000000000 -0400
+@@ -109,7 +109,7 @@ static int rxrpc_abort_connection(struct
+
+ len = iov[0].iov_len + iov[1].iov_len;
+
+- hdr.serial = htonl(atomic_inc_return(&conn->serial));
++ hdr.serial = htonl(atomic_inc_return_unchecked(&conn->serial));
+ _proto("Tx CONN ABORT %%%u { %d }", ntohl(hdr.serial), abort_code);
+
+ ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 2, len);
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-input.c linux-2.6.38.7/net/rxrpc/ar-input.c
+--- linux-2.6.38.7/net/rxrpc/ar-input.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-input.c 2011-04-28 19:57:25.000000000 -0400
+@@ -340,9 +340,9 @@ void rxrpc_fast_process_packet(struct rx
+ /* track the latest serial number on this connection for ACK packet
+ * information */
+ serial = ntohl(sp->hdr.serial);
+- hi_serial = atomic_read(&call->conn->hi_serial);
++ hi_serial = atomic_read_unchecked(&call->conn->hi_serial);
+ while (serial > hi_serial)
+- hi_serial = atomic_cmpxchg(&call->conn->hi_serial, hi_serial,
++ hi_serial = atomic_cmpxchg_unchecked(&call->conn->hi_serial, hi_serial,
+ serial);
+
+ /* request ACK generation for any ACK or DATA packet that requests
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-internal.h linux-2.6.38.7/net/rxrpc/ar-internal.h
+--- linux-2.6.38.7/net/rxrpc/ar-internal.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-internal.h 2011-04-28 19:57:25.000000000 -0400
+@@ -272,8 +272,8 @@ struct rxrpc_connection {
+ int error; /* error code for local abort */
+ int debug_id; /* debug ID for printks */
+ unsigned call_counter; /* call ID counter */
+- atomic_t serial; /* packet serial number counter */
+- atomic_t hi_serial; /* highest serial number received */
++ atomic_unchecked_t serial; /* packet serial number counter */
++ atomic_unchecked_t hi_serial; /* highest serial number received */
+ u8 avail_calls; /* number of calls available */
+ u8 size_align; /* data size alignment (for security) */
+ u8 header_size; /* rxrpc + security header size */
+@@ -346,7 +346,7 @@ struct rxrpc_call {
+ spinlock_t lock;
+ rwlock_t state_lock; /* lock for state transition */
+ atomic_t usage;
+- atomic_t sequence; /* Tx data packet sequence counter */
++ atomic_unchecked_t sequence; /* Tx data packet sequence counter */
+ u32 abort_code; /* local/remote abort code */
+ enum { /* current state of call */
+ RXRPC_CALL_CLIENT_SEND_REQUEST, /* - client sending request phase */
+@@ -420,7 +420,7 @@ static inline void rxrpc_abort_call(stru
+ */
+ extern atomic_t rxrpc_n_skbs;
+ extern __be32 rxrpc_epoch;
+-extern atomic_t rxrpc_debug_id;
++extern atomic_unchecked_t rxrpc_debug_id;
+ extern struct workqueue_struct *rxrpc_workqueue;
+
+ /*
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-local.c linux-2.6.38.7/net/rxrpc/ar-local.c
+--- linux-2.6.38.7/net/rxrpc/ar-local.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-local.c 2011-04-28 19:57:25.000000000 -0400
+@@ -45,7 +45,7 @@ struct rxrpc_local *rxrpc_alloc_local(st
+ spin_lock_init(&local->lock);
+ rwlock_init(&local->services_lock);
+ atomic_set(&local->usage, 1);
+- local->debug_id = atomic_inc_return(&rxrpc_debug_id);
++ local->debug_id = atomic_inc_return_unchecked(&rxrpc_debug_id);
+ memcpy(&local->srx, srx, sizeof(*srx));
+ }
+
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-output.c linux-2.6.38.7/net/rxrpc/ar-output.c
+--- linux-2.6.38.7/net/rxrpc/ar-output.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-output.c 2011-04-28 19:57:25.000000000 -0400
+@@ -681,9 +681,9 @@ static int rxrpc_send_data(struct kiocb
+ sp->hdr.cid = call->cid;
+ sp->hdr.callNumber = call->call_id;
+ sp->hdr.seq =
+- htonl(atomic_inc_return(&call->sequence));
++ htonl(atomic_inc_return_unchecked(&call->sequence));
+ sp->hdr.serial =
+- htonl(atomic_inc_return(&conn->serial));
++ htonl(atomic_inc_return_unchecked(&conn->serial));
+ sp->hdr.type = RXRPC_PACKET_TYPE_DATA;
+ sp->hdr.userStatus = 0;
+ sp->hdr.securityIndex = conn->security_ix;
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-peer.c linux-2.6.38.7/net/rxrpc/ar-peer.c
+--- linux-2.6.38.7/net/rxrpc/ar-peer.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-peer.c 2011-04-28 19:57:25.000000000 -0400
+@@ -87,7 +87,7 @@ static struct rxrpc_peer *rxrpc_alloc_pe
+ INIT_LIST_HEAD(&peer->error_targets);
+ spin_lock_init(&peer->lock);
+ atomic_set(&peer->usage, 1);
+- peer->debug_id = atomic_inc_return(&rxrpc_debug_id);
++ peer->debug_id = atomic_inc_return_unchecked(&rxrpc_debug_id);
+ memcpy(&peer->srx, srx, sizeof(*srx));
+
+ rxrpc_assess_MTU_size(peer);
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-proc.c linux-2.6.38.7/net/rxrpc/ar-proc.c
+--- linux-2.6.38.7/net/rxrpc/ar-proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-proc.c 2011-04-28 19:57:25.000000000 -0400
+@@ -164,8 +164,8 @@ static int rxrpc_connection_seq_show(str
+ atomic_read(&conn->usage),
+ rxrpc_conn_states[conn->state],
+ key_serial(conn->key),
+- atomic_read(&conn->serial),
+- atomic_read(&conn->hi_serial));
++ atomic_read_unchecked(&conn->serial),
++ atomic_read_unchecked(&conn->hi_serial));
+
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/net/rxrpc/ar-transport.c linux-2.6.38.7/net/rxrpc/ar-transport.c
+--- linux-2.6.38.7/net/rxrpc/ar-transport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/ar-transport.c 2011-04-28 19:57:25.000000000 -0400
+@@ -47,7 +47,7 @@ static struct rxrpc_transport *rxrpc_all
+ spin_lock_init(&trans->client_lock);
+ rwlock_init(&trans->conn_lock);
+ atomic_set(&trans->usage, 1);
+- trans->debug_id = atomic_inc_return(&rxrpc_debug_id);
++ trans->debug_id = atomic_inc_return_unchecked(&rxrpc_debug_id);
+
+ if (peer->srx.transport.family == AF_INET) {
+ switch (peer->srx.transport_type) {
+diff -urNp linux-2.6.38.7/net/rxrpc/rxkad.c linux-2.6.38.7/net/rxrpc/rxkad.c
+--- linux-2.6.38.7/net/rxrpc/rxkad.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/rxrpc/rxkad.c 2011-05-16 21:47:08.000000000 -0400
+@@ -211,6 +211,8 @@ static int rxkad_secure_packet_encrypt(c
+ u16 check;
+ int nsg;
+
++ pax_track_stack();
++
+ sp = rxrpc_skb(skb);
+
+ _enter("");
+@@ -338,6 +340,8 @@ static int rxkad_verify_packet_auth(cons
+ u16 check;
+ int nsg;
+
++ pax_track_stack();
++
+ _enter("");
+
+ sp = rxrpc_skb(skb);
+@@ -610,7 +614,7 @@ static int rxkad_issue_challenge(struct
+
+ len = iov[0].iov_len + iov[1].iov_len;
+
+- hdr.serial = htonl(atomic_inc_return(&conn->serial));
++ hdr.serial = htonl(atomic_inc_return_unchecked(&conn->serial));
+ _proto("Tx CHALLENGE %%%u", ntohl(hdr.serial));
+
+ ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 2, len);
+@@ -660,7 +664,7 @@ static int rxkad_send_response(struct rx
+
+ len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
+
+- hdr->serial = htonl(atomic_inc_return(&conn->serial));
++ hdr->serial = htonl(atomic_inc_return_unchecked(&conn->serial));
+ _proto("Tx RESPONSE %%%u", ntohl(hdr->serial));
+
+ ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 3, len);
+diff -urNp linux-2.6.38.7/net/sctp/proc.c linux-2.6.38.7/net/sctp/proc.c
+--- linux-2.6.38.7/net/sctp/proc.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/sctp/proc.c 2011-04-28 19:34:15.000000000 -0400
+@@ -212,7 +212,12 @@ static int sctp_eps_seq_show(struct seq_
+ sctp_for_each_hentry(epb, node, &head->chain) {
+ ep = sctp_ep(epb);
+ sk = epb->sk;
+- seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
++ seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ",
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL, NULL,
++#else
++ ep, sk,
++#endif
+ sctp_sk(sk)->type, sk->sk_state, hash,
+ epb->bind_addr.port,
+ sock_i_uid(sk), sock_i_ino(sk));
+@@ -318,7 +323,12 @@ static int sctp_assocs_seq_show(struct s
+ seq_printf(seq,
+ "%8p %8p %-3d %-3d %-2d %-4d "
+ "%4d %8d %8d %7d %5lu %-5d %5d ",
+- assoc, sk, sctp_sk(sk)->type, sk->sk_state,
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL, NULL,
++#else
++ assoc, sk,
++#endif
++ sctp_sk(sk)->type, sk->sk_state,
+ assoc->state, hash,
+ assoc->assoc_id,
+ assoc->sndbuf_used,
+diff -urNp linux-2.6.38.7/net/sctp/socket.c linux-2.6.38.7/net/sctp/socket.c
+--- linux-2.6.38.7/net/sctp/socket.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/sctp/socket.c 2011-04-28 19:34:15.000000000 -0400
+@@ -4435,7 +4435,7 @@ static int sctp_getsockopt_peer_addrs(st
+ addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
+ if (space_left < addrlen)
+ return -ENOMEM;
+- if (copy_to_user(to, &temp, addrlen))
++ if (addrlen > sizeof(temp) || copy_to_user(to, &temp, addrlen))
+ return -EFAULT;
+ to += addrlen;
+ cnt++;
+diff -urNp linux-2.6.38.7/net/socket.c linux-2.6.38.7/net/socket.c
+--- linux-2.6.38.7/net/socket.c 2011-04-18 17:27:16.000000000 -0400
++++ linux-2.6.38.7/net/socket.c 2011-05-16 21:47:09.000000000 -0400
+@@ -88,6 +88,7 @@
+ #include <linux/nsproxy.h>
+ #include <linux/magic.h>
+ #include <linux/slab.h>
++#include <linux/in.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+@@ -105,6 +106,8 @@
+ #include <linux/sockios.h>
+ #include <linux/atalk.h>
+
++#include <linux/grsock.h>
++
+ static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
+ static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
+@@ -326,7 +329,7 @@ static struct dentry *sockfs_mount(struc
+ &sockfs_dentry_operations, SOCKFS_MAGIC);
+ }
+
+-static struct vfsmount *sock_mnt __read_mostly;
++struct vfsmount *sock_mnt __read_mostly;
+
+ static struct file_system_type sock_fs_type = {
+ .name = "sockfs",
+@@ -1174,6 +1177,8 @@ int __sock_create(struct net *net, int f
+ return -EAFNOSUPPORT;
+ if (type < 0 || type >= SOCK_MAX)
+ return -EINVAL;
++ if (protocol < 0)
++ return -EINVAL;
+
+ /* Compatibility.
+
+@@ -1306,6 +1311,16 @@ SYSCALL_DEFINE3(socket, int, family, int
+ if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+ flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
+
++ if(!gr_search_socket(family, type, protocol)) {
++ retval = -EACCES;
++ goto out;
++ }
++
++ if (gr_handle_sock_all(family, type, protocol)) {
++ retval = -EACCES;
++ goto out;
++ }
++
+ retval = sock_create(family, type, protocol, &sock);
+ if (retval < 0)
+ goto out;
+@@ -1418,6 +1433,14 @@ SYSCALL_DEFINE3(bind, int, fd, struct so
+ if (sock) {
+ err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
+ if (err >= 0) {
++ if (gr_handle_sock_server((struct sockaddr *)&address)) {
++ err = -EACCES;
++ goto error;
++ }
++ err = gr_search_bind(sock, (struct sockaddr_in *)&address);
++ if (err)
++ goto error;
++
+ err = security_socket_bind(sock,
+ (struct sockaddr *)&address,
+ addrlen);
+@@ -1426,6 +1449,7 @@ SYSCALL_DEFINE3(bind, int, fd, struct so
+ (struct sockaddr *)
+ &address, addrlen);
+ }
++error:
+ fput_light(sock->file, fput_needed);
+ }
+ return err;
+@@ -1449,10 +1473,20 @@ SYSCALL_DEFINE2(listen, int, fd, int, ba
+ if ((unsigned)backlog > somaxconn)
+ backlog = somaxconn;
+
++ if (gr_handle_sock_server_other(sock->sk)) {
++ err = -EPERM;
++ goto error;
++ }
++
++ err = gr_search_listen(sock);
++ if (err)
++ goto error;
++
+ err = security_socket_listen(sock, backlog);
+ if (!err)
+ err = sock->ops->listen(sock, backlog);
+
++error:
+ fput_light(sock->file, fput_needed);
+ }
+ return err;
+@@ -1496,6 +1530,18 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
+ newsock->type = sock->type;
+ newsock->ops = sock->ops;
+
++ if (gr_handle_sock_server_other(sock->sk)) {
++ err = -EPERM;
++ sock_release(newsock);
++ goto out_put;
++ }
++
++ err = gr_search_accept(sock);
++ if (err) {
++ sock_release(newsock);
++ goto out_put;
++ }
++
+ /*
+ * We don't need try_module_get here, as the listening socket (sock)
+ * has the protocol module (sock->ops->owner) held.
+@@ -1534,6 +1580,8 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
+ fd_install(newfd, newfile);
+ err = newfd;
+
++ gr_attach_curr_ip(newsock->sk);
++
+ out_put:
+ fput_light(sock->file, fput_needed);
+ out:
+@@ -1566,6 +1614,7 @@ SYSCALL_DEFINE3(connect, int, fd, struct
+ int, addrlen)
+ {
+ struct socket *sock;
++ struct sockaddr *sck;
+ struct sockaddr_storage address;
+ int err, fput_needed;
+
+@@ -1576,6 +1625,17 @@ SYSCALL_DEFINE3(connect, int, fd, struct
+ if (err < 0)
+ goto out_put;
+
++ sck = (struct sockaddr *)&address;
++
++ if (gr_handle_sock_client(sck)) {
++ err = -EACCES;
++ goto out_put;
++ }
++
++ err = gr_search_connect(sock, (struct sockaddr_in *)sck);
++ if (err)
++ goto out_put;
++
+ err =
+ security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
+ if (err)
+@@ -1877,6 +1937,8 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct
+ int err, ctl_len, iov_size, total_len;
+ int fput_needed;
+
++ pax_track_stack();
++
+ err = -EFAULT;
+ if (MSG_CMSG_COMPAT & flags) {
+ if (get_compat_msghdr(&msg_sys, msg_compat))
+diff -urNp linux-2.6.38.7/net/sunrpc/sched.c linux-2.6.38.7/net/sunrpc/sched.c
+--- linux-2.6.38.7/net/sunrpc/sched.c 2011-04-18 17:27:14.000000000 -0400
++++ linux-2.6.38.7/net/sunrpc/sched.c 2011-04-28 19:34:15.000000000 -0400
+@@ -234,9 +234,9 @@ static int rpc_wait_bit_killable(void *w
+ #ifdef RPC_DEBUG
+ static void rpc_task_set_debuginfo(struct rpc_task *task)
+ {
+- static atomic_t rpc_pid;
++ static atomic_unchecked_t rpc_pid;
+
+- task->tk_pid = atomic_inc_return(&rpc_pid);
++ task->tk_pid = atomic_inc_return_unchecked(&rpc_pid);
+ }
+ #else
+ static inline void rpc_task_set_debuginfo(struct rpc_task *task)
+diff -urNp linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma.c linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma.c
+--- linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma.c 2011-04-28 19:57:25.000000000 -0400
+@@ -61,15 +61,15 @@ unsigned int svcrdma_max_req_size = RPCR
+ static unsigned int min_max_inline = 4096;
+ static unsigned int max_max_inline = 65536;
+
+-atomic_t rdma_stat_recv;
+-atomic_t rdma_stat_read;
+-atomic_t rdma_stat_write;
+-atomic_t rdma_stat_sq_starve;
+-atomic_t rdma_stat_rq_starve;
+-atomic_t rdma_stat_rq_poll;
+-atomic_t rdma_stat_rq_prod;
+-atomic_t rdma_stat_sq_poll;
+-atomic_t rdma_stat_sq_prod;
++atomic_unchecked_t rdma_stat_recv;
++atomic_unchecked_t rdma_stat_read;
++atomic_unchecked_t rdma_stat_write;
++atomic_unchecked_t rdma_stat_sq_starve;
++atomic_unchecked_t rdma_stat_rq_starve;
++atomic_unchecked_t rdma_stat_rq_poll;
++atomic_unchecked_t rdma_stat_rq_prod;
++atomic_unchecked_t rdma_stat_sq_poll;
++atomic_unchecked_t rdma_stat_sq_prod;
+
+ /* Temporary NFS request map and context caches */
+ struct kmem_cache *svc_rdma_map_cachep;
+@@ -109,7 +109,7 @@ static int read_reset_stat(ctl_table *ta
+ len -= *ppos;
+ if (len > *lenp)
+ len = *lenp;
+- if (len && copy_to_user(buffer, str_buf, len))
++ if (len > sizeof str_buf || (len && copy_to_user(buffer, str_buf, len)))
+ return -EFAULT;
+ *lenp = len;
+ *ppos += len;
+@@ -150,63 +150,63 @@ static ctl_table svcrdma_parm_table[] =
+ {
+ .procname = "rdma_stat_read",
+ .data = &rdma_stat_read,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+ {
+ .procname = "rdma_stat_recv",
+ .data = &rdma_stat_recv,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+ {
+ .procname = "rdma_stat_write",
+ .data = &rdma_stat_write,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+ {
+ .procname = "rdma_stat_sq_starve",
+ .data = &rdma_stat_sq_starve,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+ {
+ .procname = "rdma_stat_rq_starve",
+ .data = &rdma_stat_rq_starve,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+ {
+ .procname = "rdma_stat_rq_poll",
+ .data = &rdma_stat_rq_poll,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+ {
+ .procname = "rdma_stat_rq_prod",
+ .data = &rdma_stat_rq_prod,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+ {
+ .procname = "rdma_stat_sq_poll",
+ .data = &rdma_stat_sq_poll,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+ {
+ .procname = "rdma_stat_sq_prod",
+ .data = &rdma_stat_sq_prod,
+- .maxlen = sizeof(atomic_t),
++ .maxlen = sizeof(atomic_unchecked_t),
+ .mode = 0644,
+ .proc_handler = read_reset_stat,
+ },
+diff -urNp linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+--- linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c 2011-04-28 19:57:25.000000000 -0400
+@@ -499,7 +499,7 @@ next_sge:
+ svc_rdma_put_context(ctxt, 0);
+ goto out;
+ }
+- atomic_inc(&rdma_stat_read);
++ atomic_inc_unchecked(&rdma_stat_read);
+
+ if (read_wr.num_sge < chl_map->ch[ch_no].count) {
+ chl_map->ch[ch_no].count -= read_wr.num_sge;
+@@ -609,7 +609,7 @@ int svc_rdma_recvfrom(struct svc_rqst *r
+ dto_q);
+ list_del_init(&ctxt->dto_q);
+ } else {
+- atomic_inc(&rdma_stat_rq_starve);
++ atomic_inc_unchecked(&rdma_stat_rq_starve);
+ clear_bit(XPT_DATA, &xprt->xpt_flags);
+ ctxt = NULL;
+ }
+@@ -629,7 +629,7 @@ int svc_rdma_recvfrom(struct svc_rqst *r
+ dprintk("svcrdma: processing ctxt=%p on xprt=%p, rqstp=%p, status=%d\n",
+ ctxt, rdma_xprt, rqstp, ctxt->wc_status);
+ BUG_ON(ctxt->wc_status != IB_WC_SUCCESS);
+- atomic_inc(&rdma_stat_recv);
++ atomic_inc_unchecked(&rdma_stat_recv);
+
+ /* Build up the XDR from the receive buffers. */
+ rdma_build_arg_xdr(rqstp, ctxt, ctxt->byte_len);
+diff -urNp linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_sendto.c linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+--- linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_sendto.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_sendto.c 2011-04-28 19:57:25.000000000 -0400
+@@ -362,7 +362,7 @@ static int send_write(struct svcxprt_rdm
+ write_wr.wr.rdma.remote_addr = to;
+
+ /* Post It */
+- atomic_inc(&rdma_stat_write);
++ atomic_inc_unchecked(&rdma_stat_write);
+ if (svc_rdma_send(xprt, &write_wr))
+ goto err;
+ return 0;
+diff -urNp linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_transport.c linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_transport.c
+--- linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_transport.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/sunrpc/xprtrdma/svc_rdma_transport.c 2011-04-28 19:57:25.000000000 -0400
+@@ -298,7 +298,7 @@ static void rq_cq_reap(struct svcxprt_rd
+ return;
+
+ ib_req_notify_cq(xprt->sc_rq_cq, IB_CQ_NEXT_COMP);
+- atomic_inc(&rdma_stat_rq_poll);
++ atomic_inc_unchecked(&rdma_stat_rq_poll);
+
+ while ((ret = ib_poll_cq(xprt->sc_rq_cq, 1, &wc)) > 0) {
+ ctxt = (struct svc_rdma_op_ctxt *)(unsigned long)wc.wr_id;
+@@ -320,7 +320,7 @@ static void rq_cq_reap(struct svcxprt_rd
+ }
+
+ if (ctxt)
+- atomic_inc(&rdma_stat_rq_prod);
++ atomic_inc_unchecked(&rdma_stat_rq_prod);
+
+ set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags);
+ /*
+@@ -392,7 +392,7 @@ static void sq_cq_reap(struct svcxprt_rd
+ return;
+
+ ib_req_notify_cq(xprt->sc_sq_cq, IB_CQ_NEXT_COMP);
+- atomic_inc(&rdma_stat_sq_poll);
++ atomic_inc_unchecked(&rdma_stat_sq_poll);
+ while ((ret = ib_poll_cq(cq, 1, &wc)) > 0) {
+ if (wc.status != IB_WC_SUCCESS)
+ /* Close the transport */
+@@ -410,7 +410,7 @@ static void sq_cq_reap(struct svcxprt_rd
+ }
+
+ if (ctxt)
+- atomic_inc(&rdma_stat_sq_prod);
++ atomic_inc_unchecked(&rdma_stat_sq_prod);
+ }
+
+ static void sq_comp_handler(struct ib_cq *cq, void *cq_context)
+@@ -1271,7 +1271,7 @@ int svc_rdma_send(struct svcxprt_rdma *x
+ spin_lock_bh(&xprt->sc_lock);
+ if (xprt->sc_sq_depth < atomic_read(&xprt->sc_sq_count) + wr_count) {
+ spin_unlock_bh(&xprt->sc_lock);
+- atomic_inc(&rdma_stat_sq_starve);
++ atomic_inc_unchecked(&rdma_stat_sq_starve);
+
+ /* See if we can opportunistically reap SQ WR to make room */
+ sq_cq_reap(xprt);
+diff -urNp linux-2.6.38.7/net/sysctl_net.c linux-2.6.38.7/net/sysctl_net.c
+--- linux-2.6.38.7/net/sysctl_net.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/sysctl_net.c 2011-04-28 19:34:15.000000000 -0400
+@@ -46,7 +46,7 @@ static int net_ctl_permissions(struct ct
+ struct ctl_table *table)
+ {
+ /* Allow network administrator to have same access as root. */
+- if (capable(CAP_NET_ADMIN)) {
++ if (capable_nolog(CAP_NET_ADMIN)) {
+ int mode = (table->mode >> 6) & 7;
+ return (mode << 6) | (mode << 3) | mode;
+ }
+diff -urNp linux-2.6.38.7/net/unix/af_unix.c linux-2.6.38.7/net/unix/af_unix.c
+--- linux-2.6.38.7/net/unix/af_unix.c 2011-05-10 22:06:29.000000000 -0400
++++ linux-2.6.38.7/net/unix/af_unix.c 2011-05-10 22:09:03.000000000 -0400
+@@ -767,6 +767,12 @@ static struct sock *unix_find_other(stru
+ err = -ECONNREFUSED;
+ if (!S_ISSOCK(inode->i_mode))
+ goto put_fail;
++
++ if (!gr_acl_handle_unix(path.dentry, path.mnt)) {
++ err = -EACCES;
++ goto put_fail;
++ }
++
+ u = unix_find_socket_byinode(inode);
+ if (!u)
+ goto put_fail;
+@@ -787,6 +793,13 @@ static struct sock *unix_find_other(stru
+ if (u) {
+ struct dentry *dentry;
+ dentry = unix_sk(u)->dentry;
++
++ if (!gr_handle_chroot_unix(u->sk_peer_pid)) {
++ err = -EPERM;
++ sock_put(u);
++ goto fail;
++ }
++
+ if (dentry)
+ touch_atime(unix_sk(u)->mnt, dentry);
+ } else
+@@ -872,11 +885,18 @@ static int unix_bind(struct socket *sock
+ err = security_path_mknod(&nd.path, dentry, mode, 0);
+ if (err)
+ goto out_mknod_drop_write;
++ if (!gr_acl_handle_mknod(dentry, nd.path.dentry, nd.path.mnt, mode)) {
++ err = -EACCES;
++ goto out_mknod_drop_write;
++ }
+ err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
+ out_mknod_drop_write:
+ mnt_drop_write(nd.path.mnt);
+ if (err)
+ goto out_mknod_dput;
++
++ gr_handle_create(dentry, nd.path.mnt);
++
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+ dput(nd.path.dentry);
+ nd.path.dentry = dentry;
+@@ -894,6 +914,11 @@ out_mknod_drop_write:
+ goto out_unlock;
+ }
+
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
++ put_pid(sk->sk_peer_pid);
++ sk->sk_peer_pid = get_pid(task_tgid(current));
++#endif
++
+ list = &unix_socket_table[addr->hash];
+ } else {
+ list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
+@@ -2249,7 +2274,11 @@ static int unix_seq_show(struct seq_file
+ unix_state_lock(s);
+
+ seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu",
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ NULL,
++#else
+ s,
++#endif
+ atomic_read(&s->sk_refcnt),
+ 0,
+ s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
+diff -urNp linux-2.6.38.7/net/wireless/wext-core.c linux-2.6.38.7/net/wireless/wext-core.c
+--- linux-2.6.38.7/net/wireless/wext-core.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/wireless/wext-core.c 2011-04-28 19:34:15.000000000 -0400
+@@ -746,8 +746,7 @@ static int ioctl_standard_iw_point(struc
+ */
+
+ /* Support for very large requests */
+- if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
+- (user_length > descr->max_tokens)) {
++ if (user_length > descr->max_tokens) {
+ /* Allow userspace to GET more than max so
+ * we can support any size GET requests.
+ * There is still a limit : -ENOMEM.
+@@ -784,22 +783,6 @@ static int ioctl_standard_iw_point(struc
+ }
+ }
+
+- if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) {
+- /*
+- * If this is a GET, but not NOMAX, it means that the extra
+- * data is not bounded by userspace, but by max_tokens. Thus
+- * set the length to max_tokens. This matches the extra data
+- * allocation.
+- * The driver should fill it with the number of tokens it
+- * provided, and it may check iwp->length rather than having
+- * knowledge of max_tokens. If the driver doesn't change the
+- * iwp->length, this ioctl just copies back max_token tokens
+- * filled with zeroes. Hopefully the driver isn't claiming
+- * them to be valid data.
+- */
+- iwp->length = descr->max_tokens;
+- }
+-
+ err = handler(dev, info, (union iwreq_data *) iwp, extra);
+
+ iwp->length += essid_compat;
+diff -urNp linux-2.6.38.7/net/xfrm/xfrm_policy.c linux-2.6.38.7/net/xfrm/xfrm_policy.c
+--- linux-2.6.38.7/net/xfrm/xfrm_policy.c 2011-04-22 19:20:59.000000000 -0400
++++ linux-2.6.38.7/net/xfrm/xfrm_policy.c 2011-04-28 19:57:25.000000000 -0400
+@@ -296,7 +296,7 @@ static void xfrm_policy_kill(struct xfrm
+ {
+ policy->walk.dead = 1;
+
+- atomic_inc(&policy->genid);
++ atomic_inc_unchecked(&policy->genid);
+
+ if (del_timer(&policy->timer))
+ xfrm_pol_put(policy);
+@@ -575,7 +575,7 @@ int xfrm_policy_insert(int dir, struct x
+ hlist_add_head(&policy->bydst, chain);
+ xfrm_pol_hold(policy);
+ net->xfrm.policy_count[dir]++;
+- atomic_inc(&flow_cache_genid);
++ atomic_inc_unchecked(&flow_cache_genid);
+ if (delpol)
+ __xfrm_policy_unlink(delpol, dir);
+ policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir);
+@@ -1507,7 +1507,7 @@ free_dst:
+ goto out;
+ }
+
+-static int inline
++static inline int
+ xfrm_dst_alloc_copy(void **target, void *src, int size)
+ {
+ if (!*target) {
+@@ -1519,7 +1519,7 @@ xfrm_dst_alloc_copy(void **target, void
+ return 0;
+ }
+
+-static int inline
++static inline int
+ xfrm_dst_update_parent(struct dst_entry *dst, struct xfrm_selector *sel)
+ {
+ #ifdef CONFIG_XFRM_SUB_POLICY
+@@ -1531,7 +1531,7 @@ xfrm_dst_update_parent(struct dst_entry
+ #endif
+ }
+
+-static int inline
++static inline int
+ xfrm_dst_update_origin(struct dst_entry *dst, struct flowi *fl)
+ {
+ #ifdef CONFIG_XFRM_SUB_POLICY
+@@ -1625,7 +1625,7 @@ xfrm_resolve_and_create_bundle(struct xf
+
+ xdst->num_pols = num_pols;
+ memcpy(xdst->pols, pols, sizeof(struct xfrm_policy*) * num_pols);
+- xdst->policy_genid = atomic_read(&pols[0]->genid);
++ xdst->policy_genid = atomic_read_unchecked(&pols[0]->genid);
+
+ return xdst;
+ }
+@@ -2319,7 +2319,7 @@ static int xfrm_bundle_ok(struct xfrm_po
+ if (xdst->xfrm_genid != dst->xfrm->genid)
+ return 0;
+ if (xdst->num_pols > 0 &&
+- xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
++ xdst->policy_genid != atomic_read_unchecked(&xdst->pols[0]->genid))
+ return 0;
+
+ if (strict && fl &&
+@@ -2852,7 +2852,7 @@ static int xfrm_policy_migrate(struct xf
+ sizeof(pol->xfrm_vec[i].saddr));
+ pol->xfrm_vec[i].encap_family = mp->new_family;
+ /* flush bundles */
+- atomic_inc(&pol->genid);
++ atomic_inc_unchecked(&pol->genid);
+ }
+ }
+
+diff -urNp linux-2.6.38.7/net/xfrm/xfrm_user.c linux-2.6.38.7/net/xfrm/xfrm_user.c
+--- linux-2.6.38.7/net/xfrm/xfrm_user.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/net/xfrm/xfrm_user.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1309,6 +1309,8 @@ static int copy_to_user_tmpl(struct xfrm
+ struct xfrm_user_tmpl vec[XFRM_MAX_DEPTH];
+ int i;
+
++ pax_track_stack();
++
+ if (xp->xfrm_nr == 0)
+ return 0;
+
+@@ -1957,6 +1959,8 @@ static int xfrm_do_migrate(struct sk_buf
+ int err;
+ int n = 0;
+
++ pax_track_stack();
++
+ if (attrs[XFRMA_MIGRATE] == NULL)
+ return -EINVAL;
+
+diff -urNp linux-2.6.38.7/scripts/basic/fixdep.c linux-2.6.38.7/scripts/basic/fixdep.c
+--- linux-2.6.38.7/scripts/basic/fixdep.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/scripts/basic/fixdep.c 2011-04-28 19:34:15.000000000 -0400
+@@ -235,9 +235,9 @@ static void use_config(const char *m, in
+
+ static void parse_config_file(const char *map, size_t len)
+ {
+- const int *end = (const int *) (map + len);
++ const unsigned int *end = (const unsigned int *) (map + len);
+ /* start at +1, so that p can never be < map */
+- const int *m = (const int *) map + 1;
++ const unsigned int *m = (const unsigned int *) map + 1;
+ const char *p, *q;
+
+ for (; m < end; m++) {
+@@ -405,7 +405,7 @@ static void print_deps(void)
+ static void traps(void)
+ {
+ static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
+- int *p = (int *)test;
++ unsigned int *p = (unsigned int *)test;
+
+ if (*p != INT_CONF) {
+ fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n",
+diff -urNp linux-2.6.38.7/scripts/mod/file2alias.c linux-2.6.38.7/scripts/mod/file2alias.c
+--- linux-2.6.38.7/scripts/mod/file2alias.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/scripts/mod/file2alias.c 2011-04-28 19:34:15.000000000 -0400
+@@ -72,7 +72,7 @@ static void device_id_check(const char *
+ unsigned long size, unsigned long id_size,
+ void *symval)
+ {
+- int i;
++ unsigned int i;
+
+ if (size % id_size || size < id_size) {
+ if (cross_build != 0)
+@@ -102,7 +102,7 @@ static void device_id_check(const char *
+ /* USB is special because the bcdDevice can be matched against a numeric range */
+ /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
+ static void do_usb_entry(struct usb_device_id *id,
+- unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
++ unsigned int bcdDevice_initial, unsigned int bcdDevice_initial_digits,
+ unsigned char range_lo, unsigned char range_hi,
+ unsigned char max, struct module *mod)
+ {
+@@ -437,7 +437,7 @@ static void do_pnp_device_entry(void *sy
+ for (i = 0; i < count; i++) {
+ const char *id = (char *)devs[i].id;
+ char acpi_id[sizeof(devs[0].id)];
+- int j;
++ unsigned int j;
+
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+@@ -467,7 +467,7 @@ static void do_pnp_card_entries(void *sy
+
+ for (j = 0; j < PNP_MAX_DEVICES; j++) {
+ const char *id = (char *)card->devs[j].id;
+- int i2, j2;
++ unsigned int i2, j2;
+ int dup = 0;
+
+ if (!id[0])
+@@ -493,7 +493,7 @@ static void do_pnp_card_entries(void *sy
+ /* add an individual alias for every device entry */
+ if (!dup) {
+ char acpi_id[sizeof(card->devs[0].id)];
+- int k;
++ unsigned int k;
+
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+@@ -768,7 +768,7 @@ static void dmi_ascii_filter(char *d, co
+ static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
+ char *alias)
+ {
+- int i, j;
++ unsigned int i, j;
+
+ sprintf(alias, "dmi*");
+
+diff -urNp linux-2.6.38.7/scripts/mod/modpost.c linux-2.6.38.7/scripts/mod/modpost.c
+--- linux-2.6.38.7/scripts/mod/modpost.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/scripts/mod/modpost.c 2011-04-28 19:34:15.000000000 -0400
+@@ -896,6 +896,7 @@ enum mismatch {
+ ANY_INIT_TO_ANY_EXIT,
+ ANY_EXIT_TO_ANY_INIT,
+ EXPORT_TO_INIT_EXIT,
++ DATA_TO_TEXT
+ };
+
+ struct sectioncheck {
+@@ -1004,6 +1005,12 @@ const struct sectioncheck sectioncheck[]
+ .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
+ .mismatch = EXPORT_TO_INIT_EXIT,
+ .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
++},
++/* Do not reference code from writable data */
++{
++ .fromsec = { DATA_SECTIONS, NULL },
++ .tosec = { TEXT_SECTIONS, NULL },
++ .mismatch = DATA_TO_TEXT
+ }
+ };
+
+@@ -1126,10 +1133,10 @@ static Elf_Sym *find_elf_symbol(struct e
+ continue;
+ if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
+ continue;
+- if (sym->st_value == addr)
+- return sym;
+ /* Find a symbol nearby - addr are maybe negative */
+ d = sym->st_value - addr;
++ if (d == 0)
++ return sym;
+ if (d < 0)
+ d = addr - sym->st_value;
+ if (d < distance) {
+@@ -1401,6 +1408,14 @@ static void report_sec_mismatch(const ch
+ tosym, prl_to, prl_to, tosym);
+ free(prl_to);
+ break;
++ case DATA_TO_TEXT:
++/*
++ fprintf(stderr,
++ "The variable %s references\n"
++ "the %s %s%s%s\n",
++ fromsym, to, sec2annotation(tosec), tosym, to_p);
++*/
++ break;
+ }
+ fprintf(stderr, "\n");
+ }
+@@ -1724,7 +1739,7 @@ void __attribute__((format(printf, 2, 3)
+ va_end(ap);
+ }
+
+-void buf_write(struct buffer *buf, const char *s, int len)
++void buf_write(struct buffer *buf, const char *s, unsigned int len)
+ {
+ if (buf->size - buf->pos < len) {
+ buf->size += len + SZ;
+@@ -1936,7 +1951,7 @@ static void write_if_changed(struct buff
+ if (fstat(fileno(file), &st) < 0)
+ goto close_write;
+
+- if (st.st_size != b->pos)
++ if (st.st_size != (off_t)b->pos)
+ goto close_write;
+
+ tmp = NOFAIL(malloc(b->pos));
+diff -urNp linux-2.6.38.7/scripts/mod/modpost.h linux-2.6.38.7/scripts/mod/modpost.h
+--- linux-2.6.38.7/scripts/mod/modpost.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/scripts/mod/modpost.h 2011-04-28 19:34:15.000000000 -0400
+@@ -92,15 +92,15 @@ void *do_nofail(void *ptr, const char *e
+
+ struct buffer {
+ char *p;
+- int pos;
+- int size;
++ unsigned int pos;
++ unsigned int size;
+ };
+
+ void __attribute__((format(printf, 2, 3)))
+ buf_printf(struct buffer *buf, const char *fmt, ...);
+
+ void
+-buf_write(struct buffer *buf, const char *s, int len);
++buf_write(struct buffer *buf, const char *s, unsigned int len);
+
+ struct module {
+ struct module *next;
+diff -urNp linux-2.6.38.7/scripts/mod/sumversion.c linux-2.6.38.7/scripts/mod/sumversion.c
+--- linux-2.6.38.7/scripts/mod/sumversion.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/scripts/mod/sumversion.c 2011-04-28 19:34:15.000000000 -0400
+@@ -470,7 +470,7 @@ static void write_version(const char *fi
+ goto out;
+ }
+
+- if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
++ if (write(fd, sum, strlen(sum)+1) != (ssize_t)strlen(sum)+1) {
+ warn("writing sum in %s failed: %s\n",
+ filename, strerror(errno));
+ goto out;
+diff -urNp linux-2.6.38.7/scripts/pnmtologo.c linux-2.6.38.7/scripts/pnmtologo.c
+--- linux-2.6.38.7/scripts/pnmtologo.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/scripts/pnmtologo.c 2011-04-28 19:34:15.000000000 -0400
+@@ -237,14 +237,14 @@ static void write_header(void)
+ fprintf(out, " * Linux logo %s\n", logoname);
+ fputs(" */\n\n", out);
+ fputs("#include <linux/linux_logo.h>\n\n", out);
+- fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
++ fprintf(out, "static unsigned char %s_data[] = {\n",
+ logoname);
+ }
+
+ static void write_footer(void)
+ {
+ fputs("\n};\n\n", out);
+- fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
++ fprintf(out, "const struct linux_logo %s = {\n", logoname);
+ fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
+ fprintf(out, "\t.width\t\t= %d,\n", logo_width);
+ fprintf(out, "\t.height\t\t= %d,\n", logo_height);
+@@ -374,7 +374,7 @@ static void write_logo_clut224(void)
+ fputs("\n};\n\n", out);
+
+ /* write logo clut */
+- fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
++ fprintf(out, "static unsigned char %s_clut[] = {\n",
+ logoname);
+ write_hex_cnt = 0;
+ for (i = 0; i < logo_clutsize; i++) {
+diff -urNp linux-2.6.38.7/security/apparmor/lsm.c linux-2.6.38.7/security/apparmor/lsm.c
+--- linux-2.6.38.7/security/apparmor/lsm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/apparmor/lsm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -619,7 +619,7 @@ static int apparmor_task_setrlimit(struc
+ return error;
+ }
+
+-static struct security_operations apparmor_ops = {
++static struct security_operations apparmor_ops __read_only = {
+ .name = "apparmor",
+
+ .ptrace_access_check = apparmor_ptrace_access_check,
+diff -urNp linux-2.6.38.7/security/commoncap.c linux-2.6.38.7/security/commoncap.c
+--- linux-2.6.38.7/security/commoncap.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/commoncap.c 2011-04-28 19:34:15.000000000 -0400
+@@ -27,6 +27,7 @@
+ #include <linux/sched.h>
+ #include <linux/prctl.h>
+ #include <linux/securebits.h>
++#include <net/sock.h>
+
+ /*
+ * If a non-root user executes a setuid-root binary in
+@@ -50,9 +51,11 @@ static void warn_setuid_and_fcaps_mixed(
+ }
+ }
+
++extern kernel_cap_t gr_cap_rtnetlink(struct sock *sk);
++
+ int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
+ {
+- NETLINK_CB(skb).eff_cap = current_cap();
++ NETLINK_CB(skb).eff_cap = gr_cap_rtnetlink(sk);
+ return 0;
+ }
+
+@@ -534,6 +537,9 @@ int cap_bprm_secureexec(struct linux_bin
+ {
+ const struct cred *cred = current_cred();
+
++ if (gr_acl_enable_at_secure())
++ return 1;
++
+ if (cred->uid != 0) {
+ if (bprm->cap_effective)
+ return 1;
+diff -urNp linux-2.6.38.7/security/integrity/ima/ima_api.c linux-2.6.38.7/security/integrity/ima/ima_api.c
+--- linux-2.6.38.7/security/integrity/ima/ima_api.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/integrity/ima/ima_api.c 2011-04-28 19:34:15.000000000 -0400
+@@ -75,7 +75,7 @@ void ima_add_violation(struct inode *ino
+ int result;
+
+ /* can overflow, only indicator */
+- atomic_long_inc(&ima_htable.violations);
++ atomic_long_inc_unchecked(&ima_htable.violations);
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+diff -urNp linux-2.6.38.7/security/integrity/ima/ima_fs.c linux-2.6.38.7/security/integrity/ima/ima_fs.c
+--- linux-2.6.38.7/security/integrity/ima/ima_fs.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/integrity/ima/ima_fs.c 2011-04-28 19:34:15.000000000 -0400
+@@ -28,12 +28,12 @@
+ static int valid_policy = 1;
+ #define TMPBUFLEN 12
+ static ssize_t ima_show_htable_value(char __user *buf, size_t count,
+- loff_t *ppos, atomic_long_t *val)
++ loff_t *ppos, atomic_long_unchecked_t *val)
+ {
+ char tmpbuf[TMPBUFLEN];
+ ssize_t len;
+
+- len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
++ len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read_unchecked(val));
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
+ }
+
+diff -urNp linux-2.6.38.7/security/integrity/ima/ima.h linux-2.6.38.7/security/integrity/ima/ima.h
+--- linux-2.6.38.7/security/integrity/ima/ima.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/integrity/ima/ima.h 2011-04-28 19:34:15.000000000 -0400
+@@ -85,8 +85,8 @@ void ima_add_violation(struct inode *ino
+ extern spinlock_t ima_queue_lock;
+
+ struct ima_h_table {
+- atomic_long_t len; /* number of stored measurements in the list */
+- atomic_long_t violations;
++ atomic_long_unchecked_t len; /* number of stored measurements in the list */
++ atomic_long_unchecked_t violations;
+ struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
+ };
+ extern struct ima_h_table ima_htable;
+diff -urNp linux-2.6.38.7/security/integrity/ima/ima_queue.c linux-2.6.38.7/security/integrity/ima/ima_queue.c
+--- linux-2.6.38.7/security/integrity/ima/ima_queue.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/integrity/ima/ima_queue.c 2011-04-28 19:34:15.000000000 -0400
+@@ -79,7 +79,7 @@ static int ima_add_digest_entry(struct i
+ INIT_LIST_HEAD(&qe->later);
+ list_add_tail_rcu(&qe->later, &ima_measurements);
+
+- atomic_long_inc(&ima_htable.len);
++ atomic_long_inc_unchecked(&ima_htable.len);
+ key = ima_hash_key(entry->digest);
+ hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
+ return 0;
+diff -urNp linux-2.6.38.7/security/Kconfig linux-2.6.38.7/security/Kconfig
+--- linux-2.6.38.7/security/Kconfig 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/Kconfig 2011-04-30 19:58:48.000000000 -0400
+@@ -4,6 +4,548 @@
+
+ menu "Security options"
+
++source grsecurity/Kconfig
++
++menu "PaX"
++
++ config ARCH_TRACK_EXEC_LIMIT
++ bool
++
++ config PAX_PER_CPU_PGD
++ bool
++
++ config TASK_SIZE_MAX_SHIFT
++ int
++ depends on X86_64
++ default 47 if !PAX_PER_CPU_PGD
++ default 42 if PAX_PER_CPU_PGD
++
++ config PAX_ENABLE_PAE
++ bool
++ default y if (X86_32 && (MPENTIUM4 || MK8 || MPSC || MCORE2 || MATOM))
++
++config PAX
++ bool "Enable various PaX features"
++ depends on GRKERNSEC && (ALPHA || ARM || AVR32 || IA64 || MIPS || PARISC || PPC || SPARC || X86)
++ help
++ This allows you to enable various PaX features. PaX adds
++ intrusion prevention mechanisms to the kernel that reduce
++ the risks posed by exploitable memory corruption bugs.
++
++menu "PaX Control"
++ depends on PAX
++
++config PAX_SOFTMODE
++ bool 'Support soft mode'
++ select PAX_PT_PAX_FLAGS
++ help
++ Enabling this option will allow you to run PaX in soft mode, that
++ is, PaX features will not be enforced by default, only on executables
++ marked explicitly. You must also enable PT_PAX_FLAGS support as it
++ is the only way to mark executables for soft mode use.
++
++ Soft mode can be activated by using the "pax_softmode=1" kernel command
++ line option on boot. Furthermore you can control various PaX features
++ at runtime via the entries in /proc/sys/kernel/pax.
++
++config PAX_EI_PAX
++ bool 'Use legacy ELF header marking'
++ help
++ Enabling this option will allow you to control PaX features on
++ a per executable basis via the 'chpax' utility available at
++ http://pax.grsecurity.net/. The control flags will be read from
++ an otherwise reserved part of the ELF header. This marking has
++ numerous drawbacks (no support for soft-mode, toolchain does not
++ know about the non-standard use of the ELF header) therefore it
++ has been deprecated in favour of PT_PAX_FLAGS support.
++
++ Note that if you enable PT_PAX_FLAGS marking support as well,
++ the PT_PAX_FLAG marks will override the legacy EI_PAX marks.
++
++config PAX_PT_PAX_FLAGS
++ bool 'Use ELF program header marking'
++ help
++ Enabling this option will allow you to control PaX features on
++ a per executable basis via the 'paxctl' utility available at
++ http://pax.grsecurity.net/. The control flags will be read from
++ a PaX specific ELF program header (PT_PAX_FLAGS). This marking
++ has the benefits of supporting both soft mode and being fully
++ integrated into the toolchain (the binutils patch is available
++ from http://pax.grsecurity.net).
++
++ If your toolchain does not support PT_PAX_FLAGS markings,
++ you can create one in most cases with 'paxctl -C'.
++
++ Note that if you enable the legacy EI_PAX marking support as well,
++ the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks.
++
++choice
++ prompt 'MAC system integration'
++ default PAX_HAVE_ACL_FLAGS
++ help
++ Mandatory Access Control systems have the option of controlling
++ PaX flags on a per executable basis, choose the method supported
++ by your particular system.
++
++ - "none": if your MAC system does not interact with PaX,
++ - "direct": if your MAC system defines pax_set_initial_flags() itself,
++ - "hook": if your MAC system uses the pax_set_initial_flags_func callback.
++
++ NOTE: this option is for developers/integrators only.
++
++ config PAX_NO_ACL_FLAGS
++ bool 'none'
++
++ config PAX_HAVE_ACL_FLAGS
++ bool 'direct'
++
++ config PAX_HOOK_ACL_FLAGS
++ bool 'hook'
++endchoice
++
++endmenu
++
++menu "Non-executable pages"
++ depends on PAX
++
++config PAX_NOEXEC
++ bool "Enforce non-executable pages"
++ depends on (PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS) && (ALPHA || (ARM && (CPU_V6 || CPU_V7)) || IA64 || MIPS || PARISC || PPC || S390 || SPARC || X86)
++ help
++ By design some architectures do not allow for protecting memory
++ pages against execution or even if they do, Linux does not make
++ use of this feature. In practice this means that if a page is
++ readable (such as the stack or heap) it is also executable.
++
++ There is a well known exploit technique that makes use of this
++ fact and a common programming mistake where an attacker can
++ introduce code of his choice somewhere in the attacked program's
++ memory (typically the stack or the heap) and then execute it.
++
++ If the attacked program was running with different (typically
++ higher) privileges than that of the attacker, then he can elevate
++ his own privilege level (e.g. get a root shell, write to files for
++ which he does not have write access to, etc).
++
++ Enabling this option will let you choose from various features
++ that prevent the injection and execution of 'foreign' code in
++ a program.
++
++ This will also break programs that rely on the old behaviour and
++ expect that dynamically allocated memory via the malloc() family
++ of functions is executable (which it is not). Notable examples
++ are the XFree86 4.x server, the java runtime and wine.
++
++config PAX_PAGEEXEC
++ bool "Paging based non-executable pages"
++ depends on PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MATOM || MPENTIUM4 || MPSC || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2 || MVIAC7)
++ select S390_SWITCH_AMODE if S390
++ select S390_EXEC_PROTECT if S390
++ select ARCH_TRACK_EXEC_LIMIT if X86_32
++ help
++ This implementation is based on the paging feature of the CPU.
++ On i386 without hardware non-executable bit support there is a
++ variable but usually low performance impact, however on Intel's
++ P4 core based CPUs it is very high so you should not enable this
++ for kernels meant to be used on such CPUs.
++
++ On alpha, avr32, ia64, parisc, sparc, sparc64, x86_64 and i386
++ with hardware non-executable bit support there is no performance
++ impact, on ppc the impact is negligible.
++
++ Note that several architectures require various emulations due to
++ badly designed userland ABIs, this will cause a performance impact
++ but will disappear as soon as userland is fixed. For example, ppc
++ userland MUST have been built with secure-plt by a recent toolchain.
++
++config PAX_SEGMEXEC
++ bool "Segmentation based non-executable pages"
++ depends on PAX_NOEXEC && X86_32
++ help
++ This implementation is based on the segmentation feature of the
++ CPU and has a very small performance impact, however applications
++ will be limited to a 1.5 GB address space instead of the normal
++ 3 GB.
++
++config PAX_EMUTRAMP
++ bool "Emulate trampolines" if (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || X86)
++ default y if PARISC
++ help
++ There are some programs and libraries that for one reason or
++ another attempt to execute special small code snippets from
++ non-executable memory pages. Most notable examples are the
++ signal handler return code generated by the kernel itself and
++ the GCC trampolines.
++
++ If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then
++ such programs will no longer work under your kernel.
++
++ As a remedy you can say Y here and use the 'chpax' or 'paxctl'
++ utilities to enable trampoline emulation for the affected programs
++ yet still have the protection provided by the non-executable pages.
++
++ On parisc you MUST enable this option and EMUSIGRT as well, otherwise
++ your system will not even boot.
++
++ Alternatively you can say N here and use the 'chpax' or 'paxctl'
++ utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC
++ for the affected files.
++
++ NOTE: enabling this feature *may* open up a loophole in the
++ protection provided by non-executable pages that an attacker
++ could abuse. Therefore the best solution is to not have any
++ files on your system that would require this option. This can
++ be achieved by not using libc5 (which relies on the kernel
++ signal handler return code) and not using or rewriting programs
++ that make use of the nested function implementation of GCC.
++ Skilled users can just fix GCC itself so that it implements
++ nested function calls in a way that does not interfere with PaX.
++
++config PAX_EMUSIGRT
++ bool "Automatically emulate sigreturn trampolines"
++ depends on PAX_EMUTRAMP && PARISC
++ default y
++ help
++ Enabling this option will have the kernel automatically detect
++ and emulate signal return trampolines executing on the stack
++ that would otherwise lead to task termination.
++
++ This solution is intended as a temporary one for users with
++ legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17,
++ Modula-3 runtime, etc) or executables linked to such, basically
++ everything that does not specify its own SA_RESTORER function in
++ normal executable memory like glibc 2.1+ does.
++
++ On parisc you MUST enable this option, otherwise your system will
++ not even boot.
++
++ NOTE: this feature cannot be disabled on a per executable basis
++ and since it *does* open up a loophole in the protection provided
++ by non-executable pages, the best solution is to not have any
++ files on your system that would require this option.
++
++config PAX_MPROTECT
++ bool "Restrict mprotect()"
++ depends on (PAX_PAGEEXEC || PAX_SEGMEXEC)
++ help
++ Enabling this option will prevent programs from
++ - changing the executable status of memory pages that were
++ not originally created as executable,
++ - making read-only executable pages writable again,
++ - creating executable pages from anonymous memory,
++ - making read-only-after-relocations (RELRO) data pages writable again.
++
++ You should say Y here to complete the protection provided by
++ the enforcement of non-executable pages.
++
++ NOTE: you can use the 'chpax' or 'paxctl' utilities to control
++ this feature on a per file basis.
++
++config PAX_MPROTECT_COMPAT
++ bool "Use legacy/compat protection demoting (read help)"
++ depends on PAX_MPROTECT
++ default n
++ help
++ The current implementation of PAX_MPROTECT denies RWX allocations/mprotects
++ by sending the proper error code to the application. For some broken
++ userland, this can cause problems with Python or other applications. The
++ current implementation however allows for applications like clamav to
++ detect if JIT compilation/execution is allowed and to fall back gracefully
++ to an interpreter-based mode if it does not. While we encourage everyone
++ to use the current implementation as-is and push upstream to fix broken
++ userland (note that the RWX logging option can assist with this), in some
++ environments this may not be possible. Having to disable MPROTECT
++ completely on certain binaries reduces the security benefit of PaX,
++ so this option is provided for those environments to revert to the old
++ behavior.
++
++config PAX_ELFRELOCS
++ bool "Allow ELF text relocations (read help)"
++ depends on PAX_MPROTECT
++ default n
++ help
++ Non-executable pages and mprotect() restrictions are effective
++ in preventing the introduction of new executable code into an
++ attacked task's address space. There remain only two venues
++ for this kind of attack: if the attacker can execute already
++ existing code in the attacked task then he can either have it
++ create and mmap() a file containing his code or have it mmap()
++ an already existing ELF library that does not have position
++ independent code in it and use mprotect() on it to make it
++ writable and copy his code there. While protecting against
++ the former approach is beyond PaX, the latter can be prevented
++ by having only PIC ELF libraries on one's system (which do not
++ need to relocate their code). If you are sure this is your case,
++ as is the case with all modern Linux distributions, then leave
++ this option disabled. You should say 'n' here.
++
++config PAX_ETEXECRELOCS
++ bool "Allow ELF ET_EXEC text relocations"
++ depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC)
++ select PAX_ELFRELOCS
++ default y
++ help
++ On some architectures there are incorrectly created applications
++ that require text relocations and would not work without enabling
++ this option. If you are an alpha, ia64 or parisc user, you should
++ enable this option and disable it once you have made sure that
++ none of your applications need it.
++
++config PAX_EMUPLT
++ bool "Automatically emulate ELF PLT"
++ depends on PAX_MPROTECT && (ALPHA || PARISC || SPARC)
++ default y
++ help
++ Enabling this option will have the kernel automatically detect
++ and emulate the Procedure Linkage Table entries in ELF files.
++ On some architectures such entries are in writable memory, and
++ become non-executable leading to task termination. Therefore
++ it is mandatory that you enable this option on alpha, parisc,
++ sparc and sparc64, otherwise your system would not even boot.
++
++ NOTE: this feature *does* open up a loophole in the protection
++ provided by the non-executable pages, therefore the proper
++ solution is to modify the toolchain to produce a PLT that does
++ not need to be writable.
++
++config PAX_DLRESOLVE
++ bool 'Emulate old glibc resolver stub'
++ depends on PAX_EMUPLT && SPARC
++ default n
++ help
++ This option is needed if userland has an old glibc (before 2.4)
++ that puts a 'save' instruction into the runtime generated resolver
++ stub that needs special emulation.
++
++config PAX_KERNEXEC
++ bool "Enforce non-executable kernel pages"
++ depends on PAX_NOEXEC && (PPC || X86) && (!X86_32 || X86_WP_WORKS_OK) && !XEN
++ select PAX_PER_CPU_PGD if X86_64 || (X86_32 && X86_PAE)
++ help
++ This is the kernel land equivalent of PAGEEXEC and MPROTECT,
++ that is, enabling this option will make it harder to inject
++ and execute 'foreign' code in kernel memory itself.
++
++ Note that on x86_64 kernels there is a known regression when
++ this feature and KVM/VMX are both enabled in the host kernel.
++
++config PAX_KERNEXEC_MODULE_TEXT
++ int "Minimum amount of memory reserved for module code"
++ default "4"
++ depends on PAX_KERNEXEC && X86_32 && MODULES
++ help
++ Due to implementation details the kernel must reserve a fixed
++ amount of memory for module code at compile time that cannot be
++ changed at runtime. Here you can specify the minimum amount
++ in MB that will be reserved. Due to the same implementation
++ details this size will always be rounded up to the next 2/4 MB
++ boundary (depends on PAE) so the actually available memory for
++ module code will usually be more than this minimum.
++
++ The default 4 MB should be enough for most users but if you have
++ an excessive number of modules (e.g., most distribution configs
++ compile many drivers as modules) or use huge modules such as
++ nvidia's kernel driver, you will need to adjust this amount.
++ A good rule of thumb is to look at your currently loaded kernel
++ modules and add up their sizes.
++
++endmenu
++
++menu "Address Space Layout Randomization"
++ depends on PAX
++
++config PAX_ASLR
++ bool "Address Space Layout Randomization"
++ depends on PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS
++ help
++ Many if not most exploit techniques rely on the knowledge of
++ certain addresses in the attacked program. The following options
++ will allow the kernel to apply a certain amount of randomization
++ to specific parts of the program thereby forcing an attacker to
++ guess them in most cases. Any failed guess will most likely crash
++ the attacked program which allows the kernel to detect such attempts
++ and react on them. PaX itself provides no reaction mechanisms,
++ instead it is strongly encouraged that you make use of Nergal's
++ segvguard (ftp://ftp.pl.openwall.com/misc/segvguard/) or grsecurity's
++ (http://www.grsecurity.net/) built-in crash detection features or
++ develop one yourself.
++
++ By saying Y here you can choose to randomize the following areas:
++ - top of the task's kernel stack
++ - top of the task's userland stack
++ - base address for mmap() requests that do not specify one
++ (this includes all libraries)
++ - base address of the main executable
++
++ It is strongly recommended to say Y here as address space layout
++ randomization has negligible impact on performance yet it provides
++ a very effective protection.
++
++ NOTE: you can use the 'chpax' or 'paxctl' utilities to control
++ this feature on a per file basis.
++
++config PAX_RANDKSTACK
++ bool "Randomize kernel stack base"
++ depends on PAX_ASLR && X86_TSC && X86
++ help
++ By saying Y here the kernel will randomize every task's kernel
++ stack on every system call. This will not only force an attacker
++ to guess it but also prevent him from making use of possible
++ leaked information about it.
++
++ Since the kernel stack is a rather scarce resource, randomization
++ may cause unexpected stack overflows, therefore you should very
++ carefully test your system. Note that once enabled in the kernel
++ configuration, this feature cannot be disabled on a per file basis.
++
++config PAX_RANDUSTACK
++ bool "Randomize user stack base"
++ depends on PAX_ASLR
++ help
++ By saying Y here the kernel will randomize every task's userland
++ stack. The randomization is done in two steps where the second
++ one may apply a big amount of shift to the top of the stack and
++ cause problems for programs that want to use lots of memory (more
++ than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is).
++ For this reason the second step can be controlled by 'chpax' or
++ 'paxctl' on a per file basis.
++
++config PAX_RANDMMAP
++ bool "Randomize mmap() base"
++ depends on PAX_ASLR
++ help
++ By saying Y here the kernel will use a randomized base address for
++ mmap() requests that do not specify one themselves. As a result
++ all dynamically loaded libraries will appear at random addresses
++ and therefore be harder to exploit by a technique where an attacker
++ attempts to execute library code for his purposes (e.g. spawn a
++ shell from an exploited program that is running at an elevated
++ privilege level).
++
++ Furthermore, if a program is relinked as a dynamic ELF file, its
++ base address will be randomized as well, completing the full
++ randomization of the address space layout. Attacking such programs
++ becomes a guess game. You can find an example of doing this at
++ http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at
++ http://www.grsecurity.net/grsec-gcc-specs.tar.gz .
++
++ NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
++ feature on a per file basis.
++
++endmenu
++
++menu "Miscellaneous hardening features"
++
++config PAX_MEMORY_SANITIZE
++ bool "Sanitize all freed memory"
++ help
++ By saying Y here the kernel will erase memory pages as soon as they
++ are freed. This in turn reduces the lifetime of data stored in the
++ pages, making it less likely that sensitive information such as
++ passwords, cryptographic secrets, etc stay in memory for too long.
++
++ This is especially useful for programs whose runtime is short, long
++ lived processes and the kernel itself benefit from this as long as
++ they operate on whole memory pages and ensure timely freeing of pages
++ that may hold sensitive information.
++
++ The tradeoff is performance impact, on a single CPU system kernel
++ compilation sees a 3% slowdown, other systems and workloads may vary
++ and you are advised to test this feature on your expected workload
++ before deploying it.
++
++ Note that this feature does not protect data stored in live pages,
++ e.g., process memory swapped to disk may stay there for a long time.
++
++config PAX_MEMORY_STACKLEAK
++ bool "Sanitize kernel stack"
++ depends on X86
++ help
++ By saying Y here the kernel will erase the kernel stack before it
++ returns from a system call. This in turn reduces the information
++ that a kernel stack leak bug can reveal.
++
++ Note that such a bug can still leak information that was put on
++ the stack by the current system call (the one eventually triggering
++ the bug) but traces of earlier system calls on the kernel stack
++ cannot leak anymore.
++
++ The tradeoff is performance impact: on a single CPU system kernel
++ compilation sees a 1% slowdown, other systems and workloads may vary
++ and you are advised to test this feature on your expected workload
++ before deploying it.
++
++config PAX_MEMORY_UDEREF
++ bool "Prevent invalid userland pointer dereference"
++ depends on X86 && !UML_X86 && !XEN
++ select PAX_PER_CPU_PGD if X86_64
++ help
++ By saying Y here the kernel will be prevented from dereferencing
++ userland pointers in contexts where the kernel expects only kernel
++ pointers. This is both a useful runtime debugging feature and a
++ security measure that prevents exploiting a class of kernel bugs.
++
++ The tradeoff is that some virtualization solutions may experience
++ a huge slowdown and therefore you should not enable this feature
++ for kernels meant to run in such environments. Whether a given VM
++ solution is affected or not is best determined by simply trying it
++ out, the performance impact will be obvious right on boot as this
++ mechanism engages from very early on. A good rule of thumb is that
++ VMs running on CPUs without hardware virtualization support (i.e.,
++ the majority of IA-32 CPUs) will likely experience the slowdown.
++
++config PAX_REFCOUNT
++ bool "Prevent various kernel object reference counter overflows"
++ depends on GRKERNSEC && (X86 || SPARC64)
++ help
++ By saying Y here the kernel will detect and prevent overflowing
++ various (but not all) kinds of object reference counters. Such
++ overflows can normally occur due to bugs only and are often, if
++ not always, exploitable.
++
++ The tradeoff is that data structures protected by an overflowed
++ refcount will never be freed and therefore will leak memory. Note
++ that this leak also happens even without this protection but in
++ that case the overflow can eventually trigger the freeing of the
++ data structure while it is still being used elsewhere, resulting
++ in the exploitable situation that this feature prevents.
++
++ Since this has a negligible performance impact, you should enable
++ this feature.
++
++config PAX_USERCOPY
++ bool "Harden heap object copies between kernel and userland"
++ depends on X86 || PPC || SPARC
++ depends on GRKERNSEC && (SLAB || SLUB)
++ help
++ By saying Y here the kernel will enforce the size of heap objects
++ when they are copied in either direction between the kernel and
++ userland, even if only a part of the heap object is copied.
++
++ Specifically, this checking prevents information leaking from the
++ kernel heap during kernel to userland copies (if the kernel heap
++ object is otherwise fully initialized) and prevents kernel heap
++ overflows during userland to kernel copies.
++
++ Note that the current implementation provides the strictest bounds
++ checks for the SLUB allocator.
++
++ Enabling this option also enables per-slab cache protection against
++ data in a given cache being copied into/out of via userland
++ accessors. Though the whitelist of regions will be reduced over
++ time, it notably protects important data structures like task structs.
++
++ If frame pointers are enabled on x86, this option will also restrict
++ copies into and out of the kernel stack to local variables within a
++ single frame.
++
++ Since this has a negligible performance impact, you should enable
++ this feature.
++
++endmenu
++
++endmenu
++
+ config KEYS
+ bool "Enable access key retention support"
+ help
+@@ -167,7 +709,7 @@ config INTEL_TXT
+ config LSM_MMAP_MIN_ADDR
+ int "Low address space for LSM to protect from user allocation"
+ depends on SECURITY && SECURITY_SELINUX
+- default 65536
++ default 32768
+ help
+ This is the portion of low virtual memory which should be protected
+ from userspace allocation. Keeping a user from writing to low pages
+diff -urNp linux-2.6.38.7/security/keys/keyring.c linux-2.6.38.7/security/keys/keyring.c
+--- linux-2.6.38.7/security/keys/keyring.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/keys/keyring.c 2011-04-28 19:34:15.000000000 -0400
+@@ -213,15 +213,15 @@ static long keyring_read(const struct ke
+ ret = -EFAULT;
+
+ for (loop = 0; loop < klist->nkeys; loop++) {
++ key_serial_t serial;
+ key = klist->keys[loop];
++ serial = key->serial;
+
+ tmp = sizeof(key_serial_t);
+ if (tmp > buflen)
+ tmp = buflen;
+
+- if (copy_to_user(buffer,
+- &key->serial,
+- tmp) != 0)
++ if (copy_to_user(buffer, &serial, tmp))
+ goto error;
+
+ buflen -= tmp;
+diff -urNp linux-2.6.38.7/security/min_addr.c linux-2.6.38.7/security/min_addr.c
+--- linux-2.6.38.7/security/min_addr.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/min_addr.c 2011-04-28 19:34:15.000000000 -0400
+@@ -14,6 +14,7 @@ unsigned long dac_mmap_min_addr = CONFIG
+ */
+ static void update_mmap_min_addr(void)
+ {
++#ifndef SPARC
+ #ifdef CONFIG_LSM_MMAP_MIN_ADDR
+ if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
+ mmap_min_addr = dac_mmap_min_addr;
+@@ -22,6 +23,7 @@ static void update_mmap_min_addr(void)
+ #else
+ mmap_min_addr = dac_mmap_min_addr;
+ #endif
++#endif
+ }
+
+ /*
+diff -urNp linux-2.6.38.7/security/security.c linux-2.6.38.7/security/security.c
+--- linux-2.6.38.7/security/security.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/security.c 2011-04-28 19:34:15.000000000 -0400
+@@ -25,8 +25,8 @@ static __initdata char chosen_lsm[SECURI
+ /* things that live in capability.c */
+ extern void __init security_fixup_ops(struct security_operations *ops);
+
+-static struct security_operations *security_ops;
+-static struct security_operations default_security_ops = {
++static struct security_operations *security_ops __read_only;
++static struct security_operations default_security_ops __read_only = {
+ .name = "default",
+ };
+
+@@ -67,7 +67,9 @@ int __init security_init(void)
+
+ void reset_security_ops(void)
+ {
++ pax_open_kernel();
+ security_ops = &default_security_ops;
++ pax_close_kernel();
+ }
+
+ /* Save user chosen LSM */
+diff -urNp linux-2.6.38.7/security/selinux/hooks.c linux-2.6.38.7/security/selinux/hooks.c
+--- linux-2.6.38.7/security/selinux/hooks.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/selinux/hooks.c 2011-04-28 19:34:15.000000000 -0400
+@@ -90,7 +90,6 @@
+ #define NUM_SEL_MNT_OPTS 5
+
+ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
+-extern struct security_operations *security_ops;
+
+ /* SECMARK reference count */
+ atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
+@@ -5395,7 +5394,7 @@ static int selinux_key_getsecurity(struc
+
+ #endif
+
+-static struct security_operations selinux_ops = {
++static struct security_operations selinux_ops __read_only = {
+ .name = "selinux",
+
+ .ptrace_access_check = selinux_ptrace_access_check,
+diff -urNp linux-2.6.38.7/security/selinux/include/xfrm.h linux-2.6.38.7/security/selinux/include/xfrm.h
+--- linux-2.6.38.7/security/selinux/include/xfrm.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/selinux/include/xfrm.h 2011-05-18 20:23:44.000000000 -0400
+@@ -48,7 +48,7 @@ int selinux_xfrm_decode_session(struct s
+
+ static inline void selinux_xfrm_notify_policyload(void)
+ {
+- atomic_inc(&flow_cache_genid);
++ atomic_inc_unchecked(&flow_cache_genid);
+ }
+ #else
+ static inline int selinux_xfrm_enabled(void)
+diff -urNp linux-2.6.38.7/security/selinux/ss/services.c linux-2.6.38.7/security/selinux/ss/services.c
+--- linux-2.6.38.7/security/selinux/ss/services.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/selinux/ss/services.c 2011-05-16 21:47:09.000000000 -0400
+@@ -1769,6 +1769,8 @@ int security_load_policy(void *data, siz
+ int rc = 0;
+ struct policy_file file = { data, len }, *fp = &file;
+
++ pax_track_stack();
++
+ if (!ss_initialized) {
+ avtab_cache_init();
+ rc = policydb_read(&policydb, fp);
+diff -urNp linux-2.6.38.7/security/smack/smack_lsm.c linux-2.6.38.7/security/smack/smack_lsm.c
+--- linux-2.6.38.7/security/smack/smack_lsm.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/smack/smack_lsm.c 2011-04-28 19:34:15.000000000 -0400
+@@ -3179,7 +3179,7 @@ static int smack_inode_getsecctx(struct
+ return 0;
+ }
+
+-struct security_operations smack_ops = {
++struct security_operations smack_ops __read_only = {
+ .name = "smack",
+
+ .ptrace_access_check = smack_ptrace_access_check,
+diff -urNp linux-2.6.38.7/security/tomoyo/tomoyo.c linux-2.6.38.7/security/tomoyo/tomoyo.c
+--- linux-2.6.38.7/security/tomoyo/tomoyo.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/security/tomoyo/tomoyo.c 2011-04-28 19:34:15.000000000 -0400
+@@ -240,7 +240,7 @@ static int tomoyo_sb_pivotroot(struct pa
+ * tomoyo_security_ops is a "struct security_operations" which is used for
+ * registering TOMOYO.
+ */
+-static struct security_operations tomoyo_security_ops = {
++static struct security_operations tomoyo_security_ops __read_only = {
+ .name = "tomoyo",
+ .cred_alloc_blank = tomoyo_cred_alloc_blank,
+ .cred_prepare = tomoyo_cred_prepare,
+diff -urNp linux-2.6.38.7/sound/aoa/codecs/onyx.c linux-2.6.38.7/sound/aoa/codecs/onyx.c
+--- linux-2.6.38.7/sound/aoa/codecs/onyx.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/sound/aoa/codecs/onyx.c 2011-04-28 19:34:15.000000000 -0400
+@@ -54,7 +54,7 @@ struct onyx {
+ spdif_locked:1,
+ analog_locked:1,
+ original_mute:2;
+- int open_count;
++ local_t open_count;
+ struct codec_info *codec_info;
+
+ /* mutex serializes concurrent access to the device
+@@ -753,7 +753,7 @@ static int onyx_open(struct codec_info_i
+ struct onyx *onyx = cii->codec_data;
+
+ mutex_lock(&onyx->mutex);
+- onyx->open_count++;
++ local_inc(&onyx->open_count);
+ mutex_unlock(&onyx->mutex);
+
+ return 0;
+@@ -765,8 +765,7 @@ static int onyx_close(struct codec_info_
+ struct onyx *onyx = cii->codec_data;
+
+ mutex_lock(&onyx->mutex);
+- onyx->open_count--;
+- if (!onyx->open_count)
++ if (local_dec_and_test(&onyx->open_count))
+ onyx->spdif_locked = onyx->analog_locked = 0;
+ mutex_unlock(&onyx->mutex);
+
+diff -urNp linux-2.6.38.7/sound/aoa/codecs/onyx.h linux-2.6.38.7/sound/aoa/codecs/onyx.h
+--- linux-2.6.38.7/sound/aoa/codecs/onyx.h 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/sound/aoa/codecs/onyx.h 2011-04-28 19:34:15.000000000 -0400
+@@ -11,6 +11,7 @@
+ #include <linux/i2c.h>
+ #include <asm/pmac_low_i2c.h>
+ #include <asm/prom.h>
++#include <asm/local.h>
+
+ /* PCM3052 register definitions */
+
+diff -urNp linux-2.6.38.7/sound/drivers/mts64.c linux-2.6.38.7/sound/drivers/mts64.c
+--- linux-2.6.38.7/sound/drivers/mts64.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/sound/drivers/mts64.c 2011-04-28 19:34:15.000000000 -0400
+@@ -28,6 +28,7 @@
+ #include <sound/initval.h>
+ #include <sound/rawmidi.h>
+ #include <sound/control.h>
++#include <asm/local.h>
+
+ #define CARD_NAME "Miditerminal 4140"
+ #define DRIVER_NAME "MTS64"
+@@ -66,7 +67,7 @@ struct mts64 {
+ struct pardevice *pardev;
+ int pardev_claimed;
+
+- int open_count;
++ local_t open_count;
+ int current_midi_output_port;
+ int current_midi_input_port;
+ u8 mode[MTS64_NUM_INPUT_PORTS];
+@@ -696,7 +697,7 @@ static int snd_mts64_rawmidi_open(struct
+ {
+ struct mts64 *mts = substream->rmidi->private_data;
+
+- if (mts->open_count == 0) {
++ if (local_read(&mts->open_count) == 0) {
+ /* We don't need a spinlock here, because this is just called
+ if the device has not been opened before.
+ So there aren't any IRQs from the device */
+@@ -704,7 +705,7 @@ static int snd_mts64_rawmidi_open(struct
+
+ msleep(50);
+ }
+- ++(mts->open_count);
++ local_inc(&mts->open_count);
+
+ return 0;
+ }
+@@ -714,8 +715,7 @@ static int snd_mts64_rawmidi_close(struc
+ struct mts64 *mts = substream->rmidi->private_data;
+ unsigned long flags;
+
+- --(mts->open_count);
+- if (mts->open_count == 0) {
++ if (local_dec_return(&mts->open_count) == 0) {
+ /* We need the spinlock_irqsave here because we can still
+ have IRQs at this point */
+ spin_lock_irqsave(&mts->lock, flags);
+@@ -724,8 +724,8 @@ static int snd_mts64_rawmidi_close(struc
+
+ msleep(500);
+
+- } else if (mts->open_count < 0)
+- mts->open_count = 0;
++ } else if (local_read(&mts->open_count) < 0)
++ local_set(&mts->open_count, 0);
+
+ return 0;
+ }
+diff -urNp linux-2.6.38.7/sound/drivers/portman2x4.c linux-2.6.38.7/sound/drivers/portman2x4.c
+--- linux-2.6.38.7/sound/drivers/portman2x4.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/sound/drivers/portman2x4.c 2011-04-28 19:34:15.000000000 -0400
+@@ -47,6 +47,7 @@
+ #include <sound/initval.h>
+ #include <sound/rawmidi.h>
+ #include <sound/control.h>
++#include <asm/local.h>
+
+ #define CARD_NAME "Portman 2x4"
+ #define DRIVER_NAME "portman"
+@@ -84,7 +85,7 @@ struct portman {
+ struct pardevice *pardev;
+ int pardev_claimed;
+
+- int open_count;
++ local_t open_count;
+ int mode[PORTMAN_NUM_INPUT_PORTS];
+ struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS];
+ };
+diff -urNp linux-2.6.38.7/sound/oss/sb_audio.c linux-2.6.38.7/sound/oss/sb_audio.c
+--- linux-2.6.38.7/sound/oss/sb_audio.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/sound/oss/sb_audio.c 2011-04-28 19:34:15.000000000 -0400
+@@ -901,7 +901,7 @@ sb16_copy_from_user(int dev,
+ buf16 = (signed short *)(localbuf + localoffs);
+ while (c)
+ {
+- locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
++ locallen = ((unsigned)c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
+ if (copy_from_user(lbuf8,
+ userbuf+useroffs + p,
+ locallen))
+diff -urNp linux-2.6.38.7/sound/oss/swarm_cs4297a.c linux-2.6.38.7/sound/oss/swarm_cs4297a.c
+--- linux-2.6.38.7/sound/oss/swarm_cs4297a.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/sound/oss/swarm_cs4297a.c 2011-04-28 19:34:15.000000000 -0400
+@@ -2606,7 +2606,6 @@ static int __init cs4297a_init(void)
+ {
+ struct cs4297a_state *s;
+ u32 pwr, id;
+- mm_segment_t fs;
+ int rval;
+ #ifndef CONFIG_BCM_CS4297A_CSWARM
+ u64 cfg;
+@@ -2696,22 +2695,23 @@ static int __init cs4297a_init(void)
+ if (!rval) {
+ char *sb1250_duart_present;
+
++#if 0
++ mm_segment_t fs;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+-#if 0
+ val = SOUND_MASK_LINE;
+ mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val);
+ for (i = 0; i < ARRAY_SIZE(initvol); i++) {
+ val = initvol[i].vol;
+ mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val);
+ }
++ set_fs(fs);
+ // cs4297a_write_ac97(s, 0x18, 0x0808);
+ #else
+ // cs4297a_write_ac97(s, 0x5e, 0x180);
+ cs4297a_write_ac97(s, 0x02, 0x0808);
+ cs4297a_write_ac97(s, 0x18, 0x0808);
+ #endif
+- set_fs(fs);
+
+ list_add(&s->list, &cs4297a_devs);
+
+diff -urNp linux-2.6.38.7/sound/pci/intel8x0m.c linux-2.6.38.7/sound/pci/intel8x0m.c
+--- linux-2.6.38.7/sound/pci/intel8x0m.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/sound/pci/intel8x0m.c 2011-04-28 19:34:15.000000000 -0400
+@@ -1264,7 +1264,7 @@ static struct shortname_table {
+ { 0x5455, "ALi M5455" },
+ { 0x746d, "AMD AMD8111" },
+ #endif
+- { 0 },
++ { 0, },
+ };
+
+ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
+diff -urNp linux-2.6.38.7/sound/pci/ymfpci/ymfpci_main.c linux-2.6.38.7/sound/pci/ymfpci/ymfpci_main.c
+--- linux-2.6.38.7/sound/pci/ymfpci/ymfpci_main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/sound/pci/ymfpci/ymfpci_main.c 2011-04-28 19:57:25.000000000 -0400
+@@ -202,8 +202,8 @@ static void snd_ymfpci_hw_stop(struct sn
+ if ((snd_ymfpci_readl(chip, YDSXGR_STATUS) & 2) == 0)
+ break;
+ }
+- if (atomic_read(&chip->interrupt_sleep_count)) {
+- atomic_set(&chip->interrupt_sleep_count, 0);
++ if (atomic_read_unchecked(&chip->interrupt_sleep_count)) {
++ atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
+ wake_up(&chip->interrupt_sleep);
+ }
+ __end:
+@@ -787,7 +787,7 @@ static void snd_ymfpci_irq_wait(struct s
+ continue;
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&chip->interrupt_sleep, &wait);
+- atomic_inc(&chip->interrupt_sleep_count);
++ atomic_inc_unchecked(&chip->interrupt_sleep_count);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(50));
+ remove_wait_queue(&chip->interrupt_sleep, &wait);
+ }
+@@ -825,8 +825,8 @@ static irqreturn_t snd_ymfpci_interrupt(
+ snd_ymfpci_writel(chip, YDSXGR_MODE, mode);
+ spin_unlock(&chip->reg_lock);
+
+- if (atomic_read(&chip->interrupt_sleep_count)) {
+- atomic_set(&chip->interrupt_sleep_count, 0);
++ if (atomic_read_unchecked(&chip->interrupt_sleep_count)) {
++ atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
+ wake_up(&chip->interrupt_sleep);
+ }
+ }
+@@ -2363,7 +2363,7 @@ int __devinit snd_ymfpci_create(struct s
+ spin_lock_init(&chip->reg_lock);
+ spin_lock_init(&chip->voice_lock);
+ init_waitqueue_head(&chip->interrupt_sleep);
+- atomic_set(&chip->interrupt_sleep_count, 0);
++ atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+diff -urNp linux-2.6.38.7/usr/gen_init_cpio.c linux-2.6.38.7/usr/gen_init_cpio.c
+--- linux-2.6.38.7/usr/gen_init_cpio.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/usr/gen_init_cpio.c 2011-04-28 19:34:15.000000000 -0400
+@@ -305,7 +305,7 @@ static int cpio_mkfile(const char *name,
+ int retval;
+ int rc = -1;
+ int namesize;
+- int i;
++ unsigned int i;
+
+ mode |= S_IFREG;
+
+@@ -394,9 +394,10 @@ static char *cpio_replace_env(char *new_
+ *env_var = *expanded = '\0';
+ strncat(env_var, start + 2, end - start - 2);
+ strncat(expanded, new_location, start - new_location);
+- strncat(expanded, getenv(env_var), PATH_MAX);
+- strncat(expanded, end + 1, PATH_MAX);
++ strncat(expanded, getenv(env_var), PATH_MAX - strlen(expanded));
++ strncat(expanded, end + 1, PATH_MAX - strlen(expanded));
+ strncpy(new_location, expanded, PATH_MAX);
++ new_location[PATH_MAX] = 0;
+ } else
+ break;
+ }
+diff -urNp linux-2.6.38.7/virt/kvm/kvm_main.c linux-2.6.38.7/virt/kvm/kvm_main.c
+--- linux-2.6.38.7/virt/kvm/kvm_main.c 2011-03-14 21:20:32.000000000 -0400
++++ linux-2.6.38.7/virt/kvm/kvm_main.c 2011-04-28 19:57:25.000000000 -0400
+@@ -74,7 +74,7 @@ LIST_HEAD(vm_list);
+
+ static cpumask_var_t cpus_hardware_enabled;
+ static int kvm_usage_count = 0;
+-static atomic_t hardware_enable_failed;
++static atomic_unchecked_t hardware_enable_failed;
+
+ struct kmem_cache *kvm_vcpu_cache;
+ EXPORT_SYMBOL_GPL(kvm_vcpu_cache);
+@@ -1521,7 +1521,7 @@ static int kvm_vcpu_release(struct inode
+ return 0;
+ }
+
+-static struct file_operations kvm_vcpu_fops = {
++static struct file_operations kvm_vcpu_fops = { /* cannot be const */
+ .release = kvm_vcpu_release,
+ .unlocked_ioctl = kvm_vcpu_ioctl,
+ .compat_ioctl = kvm_vcpu_ioctl,
+@@ -1990,7 +1990,7 @@ static int kvm_vm_mmap(struct file *file
+ return 0;
+ }
+
+-static struct file_operations kvm_vm_fops = {
++static struct file_operations kvm_vm_fops = { /* cannot be const */
+ .release = kvm_vm_release,
+ .unlocked_ioctl = kvm_vm_ioctl,
+ #ifdef CONFIG_COMPAT
+@@ -2088,7 +2088,7 @@ out:
+ return r;
+ }
+
+-static struct file_operations kvm_chardev_ops = {
++static struct file_operations kvm_chardev_ops = { /* cannot be const */
+ .unlocked_ioctl = kvm_dev_ioctl,
+ .compat_ioctl = kvm_dev_ioctl,
+ .llseek = noop_llseek,
+@@ -2114,7 +2114,7 @@ static void hardware_enable_nolock(void
+
+ if (r) {
+ cpumask_clear_cpu(cpu, cpus_hardware_enabled);
+- atomic_inc(&hardware_enable_failed);
++ atomic_inc_unchecked(&hardware_enable_failed);
+ printk(KERN_INFO "kvm: enabling virtualization on "
+ "CPU%d failed\n", cpu);
+ }
+@@ -2168,10 +2168,10 @@ static int hardware_enable_all(void)
+
+ kvm_usage_count++;
+ if (kvm_usage_count == 1) {
+- atomic_set(&hardware_enable_failed, 0);
++ atomic_set_unchecked(&hardware_enable_failed, 0);
+ on_each_cpu(hardware_enable_nolock, NULL, 1);
+
+- if (atomic_read(&hardware_enable_failed)) {
++ if (atomic_read_unchecked(&hardware_enable_failed)) {
+ hardware_disable_all_nolock();
+ r = -EBUSY;
+ }
+@@ -2443,7 +2443,7 @@ static void kvm_sched_out(struct preempt
+ kvm_arch_vcpu_put(vcpu);
+ }
+
+-int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
++int kvm_init(const void *opaque, unsigned vcpu_size, unsigned vcpu_align,
+ struct module *module)
+ {
+ int r;
+@@ -2514,7 +2514,7 @@ int kvm_init(void *opaque, unsigned vcpu
+ if (!vcpu_align)
+ vcpu_align = __alignof__(struct kvm_vcpu);
+ kvm_vcpu_cache = kmem_cache_create("kvm_vcpu", vcpu_size, vcpu_align,
+- 0, NULL);
++ SLAB_USERCOPY, NULL);
+ if (!kvm_vcpu_cache) {
+ r = -ENOMEM;
+ goto out_free_5;
diff --git a/main/linux-grsec/kernelconfig.x86 b/main/linux-grsec/kernelconfig.x86
new file mode 100644
index 0000000000..f21ca50e0e
--- /dev/null
+++ b/main/linux-grsec/kernelconfig.x86
@@ -0,0 +1,5157 @@
+#
+# Automatically generated make config: don't edit
+# Linux/i386 2.6.38.6 Kernel Configuration
+# Thu May 19 13:36:21 2011
+#
+# CONFIG_64BIT is not set
+CONFIG_X86_32=y
+# CONFIG_X86_64 is not set
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf32-i386"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+# CONFIG_NEED_DMA_MAP_STATE is not set
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME_VSYSCALL is not set
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ZONE_DMA32 is not set
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+# CONFIG_AUDIT_ARCH is not set
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_X86_32_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_32_LAZY_GS=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
+CONFIG_KTIME_SCALAR=y
+CONFIG_ARCH_CPU_PROBE_RELEASE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+# CONFIG_AUTO_IRQ_AFFINITY is not set
+# CONFIG_IRQ_PER_CPU is not set
+# CONFIG_HARDIRQS_SW_RESEND is not set
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+CONFIG_RCU_FAST_NO_HZ=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=m
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+# CONFIG_CPUSETS is not set
+CONFIG_CGROUP_CPUACCT=y
+# CONFIG_RESOURCE_COUNTERS is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+# CONFIG_JUMP_LABEL is not set
+CONFIG_OPTPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_KRETPROBES=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_DEV_THROTTLING is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_PADATA=y
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_X86_MPPARSE=y
+# CONFIG_X86_BIGSMP is not set
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_MRST is not set
+# CONFIG_X86_RDC321X is not set
+# CONFIG_X86_32_NON_STANDARD is not set
+# CONFIG_X86_32_IRIS is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_PARAVIRT_GUEST=y
+# CONFIG_XEN_PRIVILEGED_GUEST is not set
+CONFIG_KVM_CLOCK=y
+CONFIG_KVM_GUEST=y
+# CONFIG_LGUEST_GUEST is not set
+CONFIG_PARAVIRT=y
+# CONFIG_PARAVIRT_SPINLOCKS is not set
+CONFIG_PARAVIRT_CLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_MEMTEST is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+CONFIG_M586=y
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CPU=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_CMPXCHG=y
+CONFIG_CMPXCHG_LOCAL=y
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_XADD=y
+# CONFIG_X86_PPRO_FENCE is not set
+CONFIG_X86_F00F_BUG=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_ALIGNMENT_16=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=4
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_CYRIX_32=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_TRANSMETA_32=y
+CONFIG_CPU_SUP_UMC_32=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_IOMMU_API is not set
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+# CONFIG_X86_MCE is not set
+CONFIG_VM86=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+CONFIG_X86_REBOOTFIXUPS=y
+CONFIG_MICROCODE=m
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_2G_OPT is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ILLEGAL_POINTER_VALUE=0
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
+# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
+# CONFIG_HIGHPTE is not set
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW=64
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+# CONFIG_EFI is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_300=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=300
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM_OPS=y
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+# CONFIG_ACPI_POWER_METER is not set
+CONFIG_ACPI_EC_DEBUGFS=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_IPMI=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=m
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+CONFIG_ACPI_HED=m
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=m
+CONFIG_ACPI_APEI_EINJ=m
+CONFIG_ACPI_APEI_ERST_DEBUG=y
+# CONFIG_SFI is not set
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_PCC_CPUFREQ=m
+CONFIG_X86_ACPI_CPUFREQ=m
+# CONFIG_X86_POWERNOW_K6 is not set
+# CONFIG_X86_POWERNOW_K7 is not set
+CONFIG_X86_POWERNOW_K8=m
+# CONFIG_X86_GX_SUSPMOD is not set
+CONFIG_X86_SPEEDSTEP_CENTRINO=m
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
+# CONFIG_X86_SPEEDSTEP_ICH is not set
+# CONFIG_X86_SPEEDSTEP_SMI is not set
+CONFIG_X86_P4_CLOCKMOD=m
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+# CONFIG_X86_LONGRUN is not set
+# CONFIG_X86_LONGHAUL is not set
+# CONFIG_X86_E_POWERSAVER is not set
+
+#
+# shared options
+#
+CONFIG_X86_SPEEDSTEP_LIB=m
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_INTEL_IDLE=y
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_CNB20LE_QUIRK=y
+# CONFIG_DMAR is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_PCIEAER is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_STUB=m
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+CONFIG_PCI_IOAPIC=y
+CONFIG_ISA_DMA_API=y
+# CONFIG_ISA is not set
+# CONFIG_MCA is not set
+CONFIG_SCx200=m
+CONFIG_SCx200HR_TIMER=m
+# CONFIG_OLPC is not set
+# CONFIG_OLPC_OPENFIRMWARE is not set
+CONFIG_AMD_NB=y
+CONFIG_PCCARD=m
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+CONFIG_HOTPLUG_PCI=m
+CONFIG_HOTPLUG_PCI_FAKE=m
+# CONFIG_HOTPLUG_PCI_COMPAQ is not set
+# CONFIG_HOTPLUG_PCI_IBM is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_SHPC=m
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_MISC=m
+CONFIG_HAVE_ATOMIC_IOMAP=y
+CONFIG_HAVE_TEXT_POKE_SMP=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+# CONFIG_IP_PIMSM_V1 is not set
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETLABEL=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_GRADM=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_NFCT=y
+CONFIG_IP_VS_PE_SIP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_SCTP=m
+CONFIG_NET_SCTPPROBE=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+CONFIG_RDS=m
+# CONFIG_RDS_RDMA is not set
+# CONFIG_RDS_TCP is not set
+# CONFIG_RDS_DEBUG is not set
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+CONFIG_WAN_ROUTER=m
+CONFIG_PHONET=m
+# CONFIG_PHONET_PIPECTRLR is not set
+CONFIG_IEEE802154=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_CLS_CGROUP is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+CONFIG_RPS=y
+CONFIG_XPS=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_DEV=m
+# CONFIG_CAN_CALC_BITTIMING is not set
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_JANZ_ICAN3=m
+# CONFIG_PCH_CAN is not set
+CONFIG_CAN_SJA1000=m
+CONFIG_CAN_SJA1000_PLATFORM=m
+CONFIG_CAN_EMS_PCI=m
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PLX_PCI=m
+
+#
+# CAN USB interfaces
+#
+# CONFIG_CAN_EMS_USB is not set
+# CONFIG_CAN_ESD_USB2 is not set
+CONFIG_CAN_SOFTING=m
+CONFIG_CAN_SOFTING_CS=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+# CONFIG_TOSHIBA_FIR is not set
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_RXKAD=m
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+# CONFIG_RFKILL_INPUT is not set
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NET_9P_RDMA=m
+# CONFIG_NET_9P_DEBUG is not set
+CONFIG_CAIF=m
+# CONFIG_CAIF_DEBUG is not set
+CONFIG_CAIF_NETDEV=m
+CONFIG_CEPH_LIB=m
+# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=m
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_AR7_PARTS=m
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_HAVE_MTD_OTP=y
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+CONFIG_SSFDC=m
+CONFIG_SM_FTL=m
+CONFIG_MTD_OOPS=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+CONFIG_MTD_SBC_GXX=m
+# CONFIG_MTD_SCx200_DOCFLASH is not set
+CONFIG_MTD_AMD76XROM=m
+CONFIG_MTD_ICHXROM=m
+CONFIG_MTD_ESB2ROM=m
+CONFIG_MTD_CK804XROM=m
+CONFIG_MTD_SCB2_FLASH=m
+CONFIG_MTD_NETtel=m
+CONFIG_MTD_L440GX=m
+CONFIG_MTD_PCI=m
+CONFIG_MTD_PCMCIA=m
+# CONFIG_MTD_PCMCIA_ANONYMOUS is not set
+# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_INTEL_VR_NOR=m
+CONFIG_MTD_PLATRAM=m
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+CONFIG_MTD_PMC551_BUGFIX=y
+# CONFIG_MTD_PMC551_DEBUG is not set
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DATAFLASH_OTP is not set
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_MTD_SST25L is not set
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+# CONFIG_MTD_DOCPROBE_HIGH is not set
+# CONFIG_MTD_DOCPROBE_55AA is not set
+CONFIG_MTD_NAND_ECC=m
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_SM_COMMON=m
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_DENALI=m
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_RICOH=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CAFE=m
+# CONFIG_MTD_NAND_CS553X is not set
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_ALAUDA=m
+CONFIG_MTD_ONENAND=m
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OTP=y
+CONFIG_MTD_ONENAND_2X_PROGRAM=y
+CONFIG_MTD_ONENAND_SIM=m
+
+#
+# LPDDR flash memory drivers
+#
+CONFIG_MTD_LPDDR=m
+CONFIG_MTD_QINFO_PROBE=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_AX88796=m
+# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=m
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_AD525X_DPOT_SPI=m
+CONFIG_IBM_ASM=m
+CONFIG_PHANTOM=m
+CONFIG_SGI_IOC4=m
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
+CONFIG_ICS932S401=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_CS5535_MFGPT=m
+CONFIG_CS5535_MFGPT_DEFAULT_IRQ=7
+CONFIG_CS5535_CLOCK_EVENT_SRC=m
+CONFIG_HP_ILO=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1780=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_TI_DAC7512=m
+CONFIG_VMWARE_BALLOON=m
+CONFIG_BMP085=m
+CONFIG_PCH_PHUB=m
+CONFIG_C2PORT=m
+CONFIG_C2PORT_DURAMAR_2150=m
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_AT25=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93CX6=m
+CONFIG_CB710_CORE=m
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
+CONFIG_IWMC3200TOP=m
+# CONFIG_IWMC3200TOP_DEBUG is not set
+# CONFIG_IWMC3200TOP_DEBUGFS is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_FC_TGT_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_HOST_SMP=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+# CONFIG_BE2ISCSI is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_HPSA=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_3W_SAS=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
+CONFIG_SCSI_MVSAS=m
+CONFIG_SCSI_MVSAS_DEBUG=y
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_ARCMSR=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_MPT2SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
+# CONFIG_SCSI_MPT2SAS_LOGGING is not set
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_FLASHPOINT is not set
+CONFIG_VMWARE_PVSCSI=m
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+CONFIG_FCOE=m
+CONFIG_FCOE_FNIC=m
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_EATA=m
+# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set
+# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+CONFIG_SCSI_IPR_TRACE=y
+# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_NSP32 is not set
+CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_PMCRAID is not set
+CONFIG_SCSI_PM8001=m
+CONFIG_SCSI_SRP=m
+# CONFIG_SCSI_BFA_FC is not set
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_SCSI_OSD_DPRINT_SENSE=1
+# CONFIG_SCSI_OSD_DEBUG is not set
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_SATA_INIC162X=m
+CONFIG_SATA_ACARD_AHCI=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SX4=m
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+CONFIG_ATA_PIIX=m
+CONFIG_SATA_MV=m
+CONFIG_SATA_NV=m
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+
+#
+# PATA SFF controllers with BMDMA
+#
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+CONFIG_PATA_ATP867X=m
+CONFIG_PATA_CMD64X=m
+CONFIG_PATA_CS5520=m
+CONFIG_PATA_CS5530=m
+# CONFIG_PATA_CS5535 is not set
+CONFIG_PATA_CS5536=m
+CONFIG_PATA_CYPRESS=m
+CONFIG_PATA_EFAR=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+CONFIG_PATA_HPT3X2N=m
+CONFIG_PATA_HPT3X3=m
+CONFIG_PATA_HPT3X3_DMA=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87415=m
+CONFIG_PATA_OLDPIIX=m
+CONFIG_PATA_OPTIDMA=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_PDC_OLD=m
+CONFIG_PATA_RADISYS=m
+CONFIG_PATA_RDC=m
+CONFIG_PATA_SC1200=m
+CONFIG_PATA_SCH=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_TOSHIBA=m
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+
+#
+# PIO-only SFF controllers
+#
+CONFIG_PATA_CMD640_PCI=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_OPTI=m
+CONFIG_PATA_PCMCIA=m
+CONFIG_PATA_PLATFORM=m
+CONFIG_PATA_RZ1000=m
+
+#
+# Generic fallback / legacy drivers
+#
+CONFIG_PATA_ACPI=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_LEGACY=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_AUTODETECT is not set
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MULTICORE_RAID456 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_OHCI_DEBUG=y
+CONFIG_FIREWIRE_SBP2=m
+CONFIG_FIREWIRE_NET=m
+CONFIG_FIREWIRE_NOSY=m
+CONFIG_I2O=m
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+CONFIG_ARCNET=m
+CONFIG_ARCNET_1201=m
+CONFIG_ARCNET_1051=m
+CONFIG_ARCNET_RAW=m
+CONFIG_ARCNET_CAP=m
+CONFIG_ARCNET_COM90xx=m
+CONFIG_ARCNET_COM90xxIO=m
+CONFIG_ARCNET_RIM_I=m
+CONFIG_ARCNET_COM20020=m
+CONFIG_ARCNET_COM20020_PCI=m
+CONFIG_MII=m
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_BCM63XX_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MICREL_PHY=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_MDIO_GPIO=m
+CONFIG_NET_ETHERNET=y
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ETHOC=m
+CONFIG_DNET=m
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_DE2104X_DSL=0
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_HP100=m
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_KSZ884X_PCI=m
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SMSC9420=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_KS8842=m
+CONFIG_KS8851=m
+CONFIG_KS8851_MLL=m
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_ATL2=m
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_IP1000=m
+CONFIG_IGB=m
+CONFIG_IGB_DCA=y
+CONFIG_IGBVF=m
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_CNIC=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_ATL1C=m
+CONFIG_JME=m
+CONFIG_STMMAC_ETH=m
+# CONFIG_STMMAC_DA is not set
+# CONFIG_STMMAC_DUAL_MAC is not set
+CONFIG_PCH_GBE=m
+CONFIG_NETDEV_10000=y
+CONFIG_MDIO=m
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3_DEPENDS=y
+CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4_DEPENDS=y
+CONFIG_CHELSIO_T4=m
+CONFIG_CHELSIO_T4VF_DEPENDS=y
+CONFIG_CHELSIO_T4VF=m
+CONFIG_ENIC=m
+CONFIG_IXGBE=m
+CONFIG_IXGBE_DCA=y
+# CONFIG_IXGBEVF is not set
+CONFIG_IXGB=m
+CONFIG_S2IO=m
+CONFIG_VXGE=m
+# CONFIG_VXGE_DEBUG_TRACE_ALL is not set
+CONFIG_MYRI10GE=m
+CONFIG_MYRI10GE_DCA=y
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_QLCNIC=m
+CONFIG_QLGE=m
+CONFIG_BNA=m
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_BE2NET=m
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AIRO=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_AT76C50X_USB=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+CONFIG_ADM8211=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_MWL8K=m
+CONFIG_ATH_COMMON=m
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH5K_PCI=y
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K=m
+# CONFIG_ATH9K_DEBUGFS is not set
+CONFIG_ATH9K_RATE_CONTROL=y
+CONFIG_ATH9K_HTC=m
+# CONFIG_ATH9K_HTC_DEBUGFS is not set
+CONFIG_AR9170_USB=m
+CONFIG_AR9170_LEDS=y
+CONFIG_CARL9170=m
+CONFIG_CARL9170_LEDS=y
+CONFIG_CARL9170_WPC=y
+CONFIG_B43=m
+CONFIG_B43_PCI_AUTOSELECT=y
+CONFIG_B43_PCICORE_AUTOSELECT=y
+CONFIG_B43_PCMCIA=y
+CONFIG_B43_SDIO=y
+CONFIG_B43_PIO=y
+CONFIG_B43_PHY_N=y
+CONFIG_B43_PHY_LP=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_PCI_AUTOSELECT=y
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_HWRNG=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
+CONFIG_IWLWIFI=m
+
+#
+# Debugging Options
+#
+# CONFIG_IWLWIFI_DEBUG is not set
+CONFIG_IWLAGN=m
+CONFIG_IWL4965=y
+CONFIG_IWL5000=y
+CONFIG_IWL3945=m
+CONFIG_IWM=m
+# CONFIG_IWM_DEBUG is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_CS=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_LIBERTAS_MESH=y
+CONFIG_HERMES=m
+# CONFIG_HERMES_PRISM is not set
+CONFIG_HERMES_CACHE_FW_ON_INIT=y
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ORINOCO_USB=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_P54_PCI=m
+CONFIG_P54_SPI=m
+# CONFIG_P54_SPI_DEFAULT_EEPROM is not set
+CONFIG_P54_LEDS=y
+CONFIG_RT2X00=m
+CONFIG_RT2400PCI=m
+CONFIG_RT2500PCI=m
+CONFIG_RT61PCI=m
+CONFIG_RT2800PCI=m
+CONFIG_RT2800PCI_RT33XX=y
+# CONFIG_RT2800PCI_RT35XX is not set
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT33XX=y
+# CONFIG_RT2800USB_RT35XX is not set
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RT2800_LIB=m
+CONFIG_RT2X00_LIB_PCI=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_HT=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_RTL8192CE=m
+CONFIG_RTLWIFI=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SPI=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_HT=y
+CONFIG_WL12XX_SPI=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_WL12XX_SDIO_TEST=m
+CONFIG_WL12XX_PLATFORM_DATA=y
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+CONFIG_WIMAX_I2400M=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_WIMAX_I2400M_SDIO=m
+CONFIG_WIMAX_IWMC3200_SDIO=y
+CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_CDC_PHONET=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_ARCNET_COM20020_CS=m
+CONFIG_WAN=y
+CONFIG_LANMEDIA=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=m
+CONFIG_HDLC_RAW_ETH=m
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_X25=m
+CONFIG_PCI200SYN=m
+CONFIG_WANXL=m
+# CONFIG_WANXL_BUILD_FIRMWARE is not set
+CONFIG_PC300TOO=m
+CONFIG_FARSYNC=m
+CONFIG_DSCC4=m
+CONFIG_DSCC4_PCISYNC=y
+CONFIG_DSCC4_PCI_RST=y
+CONFIG_DLCI=m
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=m
+CONFIG_CYCLADES_SYNC=m
+CONFIG_CYCLOMX_X25=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+CONFIG_SBNI=m
+CONFIG_SBNI_MULTILINE=y
+CONFIG_ATM_DRIVERS=y
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_USE_TASKLET=y
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_ATM_SOLOS=m
+CONFIG_IEEE802154_DRIVERS=m
+CONFIG_IEEE802154_FAKEHARD=m
+
+#
+# CAIF transport drivers
+#
+CONFIG_CAIF_TTY=m
+CONFIG_CAIF_SPI_SLAVE=m
+# CONFIG_CAIF_SPI_SYNC is not set
+CONFIG_FDDI=y
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_SKFP=m
+CONFIG_HIPPI=y
+CONFIG_ROADRUNNER=m
+# CONFIG_ROADRUNNER_LARGE_RINGS is not set
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOATM=m
+CONFIG_PPPOL2TP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+CONFIG_VMXNET3=m
+CONFIG_ISDN=y
+# CONFIG_ISDN_I4L is not set
+CONFIG_ISDN_CAPI=m
+# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set
+# CONFIG_CAPI_TRACE is not set
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_CAPI=y
+# CONFIG_GIGASET_DUMMYLL is not set
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+CONFIG_GIGASET_M101=m
+# CONFIG_GIGASET_DEBUG is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+CONFIG_MISDN=m
+CONFIG_MISDN_DSP=m
+CONFIG_MISDN_L1OIP=m
+
+#
+# mISDN hardware drivers
+#
+CONFIG_MISDN_HFCPCI=m
+CONFIG_MISDN_HFCMULTI=m
+CONFIG_MISDN_HFCUSB=m
+CONFIG_MISDN_AVMFRITZ=m
+# CONFIG_MISDN_SPEEDFAX is not set
+# CONFIG_MISDN_INFINEON is not set
+# CONFIG_MISDN_W6692 is not set
+# CONFIG_MISDN_NETJET is not set
+CONFIG_MISDN_IPAC=m
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_POLLDEV=m
+CONFIG_INPUT_SPARSEKMAP=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT2160 is not set
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_GPIO_POLLED=m
+CONFIG_KEYBOARD_TCA6416=m
+CONFIG_KEYBOARD_MATRIX=m
+CONFIG_KEYBOARD_LM8323=m
+# CONFIG_KEYBOARD_MAX7359 is not set
+CONFIG_KEYBOARD_MCS=m
+CONFIG_KEYBOARD_NEWTON=m
+# CONFIG_KEYBOARD_OPENCORES is not set
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_GPIO=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_AD7877=m
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_AD7879_SPI=m
+CONFIG_TOUCHSCREEN_BU21013=m
+CONFIG_TOUCHSCREEN_CY8CTMG110=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_QT602240=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_UCB1400=m
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+# CONFIG_TOUCHSCREEN_MC13783 is not set
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
+CONFIG_TOUCHSCREEN_USB_NEXIO=y
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_ST1232=m
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_AD714X_I2C=m
+CONFIG_INPUT_AD714X_SPI=m
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_APANEL=m
+# CONFIG_INPUT_WISTRON_BTNS is not set
+CONFIG_INPUT_ATLAS_BTNS=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_PCF50633_PMU=m
+CONFIG_INPUT_PCF8574=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_ADXL34X_I2C=m
+CONFIG_INPUT_ADXL34X_SPI=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_INPUT_CMA3000_I2C=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_ALTERA_PS2=m
+CONFIG_SERIO_PS2MULT=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_COMPUTONE=m
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+CONFIG_ISI=m
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_N_GSM is not set
+CONFIG_RISCOM8=m
+CONFIG_SPECIALIX=m
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MAX3100=m
+CONFIG_SERIAL_MAX3107=m
+CONFIG_SERIAL_MRST_MAX3110=m
+CONFIG_SERIAL_MFD_HSU=m
+CONFIG_SERIAL_UARTLITE=m
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_SERIAL_TIMBERDALE=m
+CONFIG_SERIAL_ALTERA_JTAGUART=m
+CONFIG_SERIAL_ALTERA_UART=m
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
+CONFIG_SERIAL_IFX6X60=m
+CONFIG_SERIAL_PCH_UART=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_HVC_DRIVER=y
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=m
+CONFIG_R3964=m
+CONFIG_APPLICOM=m
+# CONFIG_SONYPI is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+CONFIG_MWAVE=m
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+CONFIG_TELCLOCK=m
+CONFIG_RAMOOPS=m
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_MUX=m
+
+#
+# Multiplexer I2C Chip support
+#
+CONFIG_I2C_MUX_GPIO=m
+CONFIG_I2C_MUX_PCA9541=m
+CONFIG_I2C_MUX_PCA954x=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_SMBUS=m
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+
+#
+# ACPI drivers
+#
+CONFIG_I2C_SCMI=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=m
+CONFIG_I2C_INTEL_MID=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_XILINX=m
+CONFIG_I2C_EG20T=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_STUB=m
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+CONFIG_SPI_BUTTERFLY=m
+CONFIG_SPI_GPIO=m
+CONFIG_SPI_LM70_LLP=m
+CONFIG_SPI_PXA2XX=m
+CONFIG_SPI_PXA2XX_PCI=y
+CONFIG_SPI_TOPCLIFF_PCH=m
+# CONFIG_SPI_XILINX is not set
+CONFIG_SPI_DESIGNWARE=m
+CONFIG_SPI_DW_PCI=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+CONFIG_GPIO_MAX730X=m
+
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_BASIC_MMIO=m
+CONFIG_GPIO_IT8761E=m
+CONFIG_GPIO_SCH=m
+CONFIG_GPIO_VX855=m
+
+#
+# I2C GPIO expanders:
+#
+CONFIG_GPIO_MAX7300=m
+CONFIG_GPIO_MAX732X=m
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_ADP5588=m
+
+#
+# PCI GPIO expanders:
+#
+CONFIG_GPIO_CS5535=m
+# CONFIG_GPIO_LANGWELL is not set
+CONFIG_GPIO_PCH=m
+CONFIG_GPIO_ML_IOH=m
+CONFIG_GPIO_TIMBERDALE=y
+CONFIG_GPIO_RDC321X=m
+
+#
+# SPI GPIO expanders:
+#
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MCP23S08=m
+# CONFIG_GPIO_MC33880 is not set
+CONFIG_GPIO_74X164=m
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_GPIO_UCB1400 is not set
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_GPIO_JANZ_TTL=m
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_GPIO=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PDA_POWER=m
+CONFIG_TEST_POWER=m
+CONFIG_BATTERY_DS2760=m
+CONFIG_BATTERY_DS2782=m
+CONFIG_BATTERY_BQ20Z75=m
+CONFIG_BATTERY_BQ27x00=m
+CONFIG_BATTERY_MAX17040=m
+CONFIG_BATTERY_MAX17042=m
+CONFIG_CHARGER_PCF50633=m
+CONFIG_CHARGER_ISP1704=m
+CONFIG_CHARGER_GPIO=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7411=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7475=m
+CONFIG_SENSORS_ASC7621=m
+CONFIG_SENSORS_K8TEMP=m
+CONFIG_SENSORS_K10TEMP=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS620=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_G760A=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_GPIO_FAN=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_PKGTEMP=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_JC42=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LTC4215=m
+CONFIG_SENSORS_LTC4245=m
+CONFIG_SENSORS_LTC4261=m
+CONFIG_SENSORS_LM95241=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SHT21=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMM665=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
+CONFIG_SENSORS_EMC2103=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_ADS7871=m
+CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=m
+CONFIG_SENSORS_TMP401=m
+CONFIG_SENSORS_TMP421=m
+CONFIG_SENSORS_VIA_CPUTEMP=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83795=m
+CONFIG_SENSORS_W83795_FANCTRL=y
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_LIS3_I2C=m
+CONFIG_SENSORS_APPLESMC=m
+# CONFIG_SENSORS_MC13783_ADC is not set
+
+#
+# ACPI drivers
+#
+CONFIG_SENSORS_ATK0110=m
+CONFIG_SENSORS_LIS3LV02D=m
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_F71808E_WDT=m
+CONFIG_SP5100_TCO=m
+CONFIG_GEODE_WDT=m
+CONFIG_SC520_WDT=m
+# CONFIG_SBC_FITPC2_WATCHDOG is not set
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_WAFER_WDT=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_ITCO_WDT=m
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_IT8712F_WDT=m
+CONFIG_IT87_WDT=m
+# CONFIG_HP_WATCHDOG is not set
+CONFIG_SC1200_WDT=m
+# CONFIG_SCx200_WDT is not set
+CONFIG_PC87413_WDT=m
+CONFIG_NV_TCO=m
+CONFIG_60XX_WDT=m
+CONFIG_SBC8360_WDT=m
+# CONFIG_SBC7240_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_SMSC_SCH311X_WDT=m
+CONFIG_SMSC37B787_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83697HF_WDT=m
+CONFIG_W83697UG_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+CONFIG_SSB_SDIOHOST=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_MFD_SUPPORT=y
+CONFIG_MFD_CORE=m
+CONFIG_MFD_SM501=m
+# CONFIG_MFD_SM501_GPIO is not set
+CONFIG_HTC_PASIC3=m
+CONFIG_UCB1400_CORE=m
+CONFIG_TPS65010=m
+CONFIG_TPS6507X=m
+# CONFIG_MFD_TMIO is not set
+CONFIG_MFD_WM8400=m
+# CONFIG_MFD_WM831X_SPI is not set
+CONFIG_MFD_PCF50633=m
+CONFIG_MFD_MC13783=m
+CONFIG_MFD_MC13XXX=m
+CONFIG_PCF50633_ADC=m
+CONFIG_PCF50633_GPIO=m
+CONFIG_ABX500_CORE=y
+# CONFIG_EZX_PCAP is not set
+# CONFIG_AB8500_CORE is not set
+CONFIG_MFD_CS5535=m
+CONFIG_MFD_TIMBERDALE=m
+CONFIG_LPC_SCH=m
+CONFIG_MFD_RDC321X=m
+CONFIG_MFD_JANZ_CMODIO=m
+CONFIG_MFD_VX855=m
+CONFIG_MFD_WL1273_CORE=m
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_REGULATOR_BQ24022=m
+CONFIG_REGULATOR_MAX1586=m
+CONFIG_REGULATOR_MAX8649=m
+CONFIG_REGULATOR_MAX8660=m
+CONFIG_REGULATOR_MAX8952=m
+CONFIG_REGULATOR_WM8400=m
+CONFIG_REGULATOR_PCF50633=m
+CONFIG_REGULATOR_LP3971=m
+CONFIG_REGULATOR_LP3972=m
+CONFIG_REGULATOR_MC13XXX_CORE=m
+CONFIG_REGULATOR_MC13783=m
+CONFIG_REGULATOR_MC13892=m
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_ISL6271A=m
+# CONFIG_REGULATOR_AD5398 is not set
+CONFIG_REGULATOR_TPS6524X=m
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_RC_CORE=m
+CONFIG_LIRC=m
+CONFIG_RC_MAP=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_RC5_SZ_DECODER=m
+CONFIG_IR_LIRC_CODEC=m
+# CONFIG_IR_ENE is not set
+CONFIG_IR_IMON=m
+# CONFIG_IR_MCEUSB is not set
+# CONFIG_IR_NUVOTON is not set
+# CONFIG_IR_STREAMZAP is not set
+CONFIG_IR_WINBOND_CIR=m
+CONFIG_RC_LOOPBACK=m
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_MEDIA_TUNER_TDA18218=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_V4L2_MEM2MEM_DEV=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+
+#
+# RDS decoders
+#
+CONFIG_VIDEO_SAA6588=m
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_ADV7180=m
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_BT866=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_MT9V011=m
+CONFIG_VIDEO_TCM825X=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_SAA7191=m
+CONFIG_VIDEO_TVP514X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_TVP7002=m
+CONFIG_VIDEO_VPX3220=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_THS7303=m
+CONFIG_VIDEO_ADV7343=m
+CONFIG_VIDEO_AK881X=m
+
+#
+# Video improvement chips
+#
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+# CONFIG_VIDEO_CPIA2 is not set
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_ZR36060=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_RC=y
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_TIMBERDALE=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_MPEG=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CX18_ALSA=m
+CONFIG_VIDEO_SAA7164=m
+CONFIG_VIDEO_CAFE_CCIC=m
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_VIA_CAMERA is not set
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_IMX074 is not set
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9T031=m
+CONFIG_SOC_CAMERA_MT9T112=m
+CONFIG_SOC_CAMERA_MT9V022=m
+CONFIG_SOC_CAMERA_RJ54N1=m
+CONFIG_SOC_CAMERA_TW9910=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_SOC_CAMERA_OV2640=m
+# CONFIG_SOC_CAMERA_OV6650 is not set
+CONFIG_SOC_CAMERA_OV772X=m
+CONFIG_SOC_CAMERA_OV9640=m
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+# CONFIG_USB_GSPCA_KONICA is not set
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+# CONFIG_USB_GSPCA_SQ930X is not set
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_RC=y
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_USB_ET61X251=m
+CONFIG_USB_SN9C102=m
+# CONFIG_USB_PWC is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MEM2MEM_TESTDEV=m
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_I2C_SI4713 is not set
+# CONFIG_RADIO_SI4713 is not set
+CONFIG_USB_DSBR=m
+# CONFIG_RADIO_SI470X is not set
+CONFIG_USB_MR800=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_TIMBERDALE=m
+CONFIG_RADIO_WL1273=m
+CONFIG_DVB_MAX_ADAPTERS=8
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_CE6230=m
+# CONFIG_DVB_USB_FRIIO is not set
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_AZ6027=m
+# CONFIG_DVB_USB_LME2510 is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_SMS_SIANO_MDTV=m
+
+#
+# Siano module components
+#
+CONFIG_SMS_USB_DRV=m
+CONFIG_SMS_SDIO_DRV=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported SDMC DM1105 Adapters
+#
+CONFIG_DVB_DM1105=m
+CONFIG_DVB_FIREDTV=m
+CONFIG_DVB_FIREDTV_FIREWIRE=y
+# CONFIG_DVB_FIREDTV_IEEE1394 is not set
+CONFIG_DVB_FIREDTV_INPUT=y
+
+#
+# Supported Earthsoft PT1 Adapters
+#
+# CONFIG_DVB_PT1 is not set
+
+#
+# Supported Mantis Adapters
+#
+CONFIG_MANTIS_CORE=m
+CONFIG_DVB_MANTIS=m
+CONFIG_DVB_HOPPER=m
+
+#
+# Supported nGene Adapters
+#
+CONFIG_DVB_NGENE=m
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+CONFIG_DVB_STV090x=m
+CONFIG_DVB_STV6110x=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10036=m
+CONFIG_DVB_ZL10039=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_STV6110=m
+CONFIG_DVB_STV0900=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_MB86A16=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+CONFIG_DVB_DIB8000=m
+CONFIG_DVB_MB86A20S=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_TDA665x=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+CONFIG_AGP=m
+# CONFIG_AGP_ALI is not set
+# CONFIG_AGP_ATI is not set
+# CONFIG_AGP_AMD is not set
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_INTEL=m
+# CONFIG_AGP_NVIDIA is not set
+CONFIG_AGP_SIS=m
+# CONFIG_AGP_SWORKS is not set
+CONFIG_AGP_VIA=m
+# CONFIG_AGP_EFFICEON is not set
+# CONFIG_VGA_ARB is not set
+CONFIG_VGA_SWITCHEROO=y
+CONFIG_DRM=m
+CONFIG_DRM_KMS_HELPER=m
+CONFIG_DRM_TTM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+# CONFIG_DRM_RADEON_KMS is not set
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+# CONFIG_DRM_I915_KMS is not set
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+# CONFIG_STUB_POULSBO is not set
+CONFIG_VGASTATE=m
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=m
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=m
+# CONFIG_FB_WMT_GE_ROPS is not set
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_HECUBA=m
+CONFIG_FB_SVGALIB=m
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+CONFIG_FB_PM2=m
+CONFIG_FB_PM2_FIFO_DISCONNECT=y
+CONFIG_FB_CYBER2000=m
+CONFIG_FB_ARC=m
+CONFIG_FB_VGA16=m
+CONFIG_FB_UVESA=m
+CONFIG_FB_N411=m
+CONFIG_FB_HGA=m
+CONFIG_FB_S1D13XXX=m
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+# CONFIG_FB_I810 is not set
+CONFIG_FB_LE80578=m
+CONFIG_FB_CARILLO_RANCH=m
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_INTEL_I2C=y
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_S3=m
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+CONFIG_FB_SIS=m
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+CONFIG_FB_VIA=m
+# CONFIG_FB_VIA_DIRECT_PROCFS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_3DFX_I2C=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_VT8623=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_ARK=m
+CONFIG_FB_PM3=m
+CONFIG_FB_CARMINE=m
+CONFIG_FB_CARMINE_DRAM_EVAL=y
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
+CONFIG_FB_GEODE=y
+CONFIG_FB_GEODE_LX=m
+CONFIG_FB_GEODE_GX=m
+CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_TMIO=m
+CONFIG_FB_TMIO_ACCELL=y
+CONFIG_FB_SM501=m
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_METRONOME=m
+CONFIG_FB_MB862XX=m
+# CONFIG_FB_MB862XX_PCI_GDC is not set
+CONFIG_FB_BROADSHEET=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_L4F00242T03=m
+CONFIG_LCD_LMS283GF05=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_ILI9320=m
+CONFIG_LCD_TDO24M=m
+CONFIG_LCD_VGG2432A4=m
+CONFIG_LCD_PLATFORM=m
+CONFIG_LCD_S6E63M0=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_PROGEAR=m
+CONFIG_BACKLIGHT_CARILLO_RANCH=m
+CONFIG_BACKLIGHT_MBP_NVIDIA=m
+CONFIG_BACKLIGHT_SAHARA=m
+CONFIG_BACKLIGHT_ADP8860=m
+CONFIG_BACKLIGHT_PCF50633=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_RAWMIDI_SEQ=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_PCSP=m
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_ALOOP is not set
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ASIHPI=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_CTXFI=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_INDIGOIOX=m
+CONFIG_SND_INDIGODJX=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_ES1968_INPUT=y
+CONFIG_SND_FM801=m
+# CONFIG_SND_FM801_TEA575X_BOOL is not set
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDA_HWDEP=y
+# CONFIG_SND_HDA_RECONFIG is not set
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_INPUT_BEEP_MODE=0
+CONFIG_SND_HDA_INPUT_JACK=y
+# CONFIG_SND_HDA_PATCH_LOADER is not set
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_CODEC_HDMI=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_GENERIC=y
+# CONFIG_SND_HDA_POWER_SAVE is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_LX6464ES=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MAESTRO3_INPUT=y
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+# CONFIG_SND_SIS7019 is not set
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+# CONFIG_SND_USB_CAIAQ_INPUT is not set
+CONFIG_SND_USB_US122L=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_PDAUDIOCF=m
+CONFIG_SND_SOC=m
+# CONFIG_SND_SOC_CACHE_LZO is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+CONFIG_SND_SOC_ALL_CODECS=m
+CONFIG_SND_SOC_WM_HUBS=m
+CONFIG_SND_SOC_AD1836=m
+CONFIG_SND_SOC_AD193X=m
+CONFIG_SND_SOC_AD73311=m
+CONFIG_SND_SOC_ADS117X=m
+CONFIG_SND_SOC_AK4104=m
+CONFIG_SND_SOC_AK4535=m
+CONFIG_SND_SOC_AK4642=m
+CONFIG_SND_SOC_AK4671=m
+CONFIG_SND_SOC_ALC5623=m
+CONFIG_SND_SOC_CS42L51=m
+CONFIG_SND_SOC_CS4270=m
+CONFIG_SND_SOC_CX20442=m
+CONFIG_SND_SOC_L3=m
+CONFIG_SND_SOC_DA7210=m
+CONFIG_SND_SOC_MAX98088=m
+CONFIG_SND_SOC_PCM3008=m
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_SSM2602=m
+CONFIG_SND_SOC_TLV320AIC23=m
+CONFIG_SND_SOC_TLV320AIC26=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_TLV320DAC33=m
+CONFIG_SND_SOC_UDA134X=m
+CONFIG_SND_SOC_UDA1380=m
+CONFIG_SND_SOC_WL1273=m
+CONFIG_SND_SOC_WM8400=m
+CONFIG_SND_SOC_WM8510=m
+CONFIG_SND_SOC_WM8523=m
+CONFIG_SND_SOC_WM8580=m
+CONFIG_SND_SOC_WM8711=m
+CONFIG_SND_SOC_WM8727=m
+CONFIG_SND_SOC_WM8728=m
+CONFIG_SND_SOC_WM8731=m
+CONFIG_SND_SOC_WM8737=m
+CONFIG_SND_SOC_WM8741=m
+CONFIG_SND_SOC_WM8750=m
+CONFIG_SND_SOC_WM8753=m
+CONFIG_SND_SOC_WM8770=m
+CONFIG_SND_SOC_WM8776=m
+CONFIG_SND_SOC_WM8804=m
+CONFIG_SND_SOC_WM8900=m
+CONFIG_SND_SOC_WM8903=m
+CONFIG_SND_SOC_WM8904=m
+CONFIG_SND_SOC_WM8940=m
+CONFIG_SND_SOC_WM8955=m
+CONFIG_SND_SOC_WM8960=m
+CONFIG_SND_SOC_WM8961=m
+CONFIG_SND_SOC_WM8962=m
+CONFIG_SND_SOC_WM8971=m
+CONFIG_SND_SOC_WM8974=m
+CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_WM8985=m
+CONFIG_SND_SOC_WM8988=m
+CONFIG_SND_SOC_WM8990=m
+CONFIG_SND_SOC_WM8993=m
+CONFIG_SND_SOC_WM8995=m
+CONFIG_SND_SOC_WM9081=m
+CONFIG_SND_SOC_MAX9877=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SOC_WM2000=m
+CONFIG_SND_SOC_WM9090=m
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_3M_PCT=m
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+CONFIG_HID_CANDO=m
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_PRODIKEYS=m
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+CONFIG_HID_EGALAX=m
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+CONFIG_HID_MAGICMOUSE=m
+# CONFIG_HID_MICROSOFT is not set
+CONFIG_HID_MOSART=m
+# CONFIG_HID_MONTEREY is not set
+CONFIG_HID_MULTITOUCH=m
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_ORTEK=m
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_ROCCAT_KONE=m
+CONFIG_HID_ROCCAT_KONEPLUS=m
+# CONFIG_HID_ROCCAT_PYRA is not set
+# CONFIG_HID_SAMSUNG is not set
+CONFIG_HID_SONY=m
+CONFIG_HID_STANTUM=m
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_HID_ZYDACRON=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+CONFIG_USB_WUSB=m
+CONFIG_USB_WUSB_CBAF=m
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_XHCI_HCD=m
+# CONFIG_USB_XHCI_HCD_DEBUGGING is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OXU210HP_HCD=m
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_ISP1760_HCD=m
+CONFIG_USB_ISP1362_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_SSB=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_WHCI_HCD=m
+CONFIG_USB_HWA_HCD=m
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_UAS=m
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7715_PARPORT=y
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_SAMBA is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+# CONFIG_USB_SERIAL_SSU100 is not set
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+# CONFIG_USB_LEGOTOWER is not set
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+# CONFIG_USB_TRANCEVIBRATOR is not set
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=m
+CONFIG_NOP_USB_XCEIV=m
+CONFIG_UWB=m
+CONFIG_UWB_HWA=m
+CONFIG_UWB_WHCI=m
+CONFIG_UWB_I1480U=m
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+CONFIG_MMC_TEST=m
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_SDHCI_PCI=m
+CONFIG_MMC_RICOH_MMC=y
+CONFIG_MMC_SDHCI_PLTFM=m
+CONFIG_MMC_WBSD=m
+CONFIG_MMC_TIFM_SD=m
+CONFIG_MMC_SDRICOH_CS=m
+CONFIG_MMC_CB710=m
+CONFIG_MMC_VIA_SDMMC=m
+# CONFIG_MMC_USHC is not set
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_NET5501=m
+CONFIG_LEDS_ALIX2=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+CONFIG_LEDS_LP3944=m
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+CONFIG_LEDS_CLEVO_MAIL=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_REGULATOR=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_INTEL_SS4200=m
+CONFIG_LEDS_LT3593=m
+CONFIG_LEDS_DELL_NETBOOKS=m
+# CONFIG_LEDS_MC13783 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_NFC_DEVICES is not set
+CONFIG_ACCESSIBILITY=y
+# CONFIG_A11Y_BRAILLE_CONSOLE is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_AMSO1100=m
+# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_INFINIBAND_CXGB4=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_INFINIBAND_NES=m
+# CONFIG_INFINIBAND_NES_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_TEST=m
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+# CONFIG_RTC_DRV_DS3232 is not set
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+# CONFIG_RTC_DRV_ISL12022 is not set
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=m
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8581=m
+CONFIG_RTC_DRV_RX8025=m
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_DS3234=m
+CONFIG_RTC_DRV_PCF2123=m
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=m
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_PCF50633=m
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_MC13XXX is not set
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_INTEL_MID_DMAC is not set
+CONFIG_INTEL_IOATDMA=m
+CONFIG_TIMB_DMA=m
+CONFIG_PCH_DMA=m
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+# CONFIG_ASYNC_TX_DMA is not set
+CONFIG_DMATEST=m
+CONFIG_DCA=m
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+CONFIG_CFAG12864B=m
+CONFIG_CFAG12864B_RATE=20
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+CONFIG_UIO_PCI_GENERIC=m
+CONFIG_UIO_NETX=m
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_ET131X is not set
+# CONFIG_SLICOSS is not set
+# CONFIG_VIDEO_GO7007 is not set
+# CONFIG_VIDEO_CX25821 is not set
+# CONFIG_VIDEO_TM6000 is not set
+CONFIG_USB_DABUSB=m
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_W35UND is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+CONFIG_BRCM80211=m
+CONFIG_BRCM80211_PCI=y
+# CONFIG_BRCMFMAC is not set
+# CONFIG_RT2860 is not set
+# CONFIG_RT2870 is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_PANEL is not set
+# CONFIG_R8187SE is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTL8192E is not set
+# CONFIG_R8712U is not set
+# CONFIG_TRANZPORT is not set
+# CONFIG_POHMELFS is not set
+CONFIG_AUTOFS_FS=m
+# CONFIG_IDE_PHISON is not set
+# CONFIG_LINE6_USB is not set
+CONFIG_DRM_VMWGFX=m
+CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_NOUVEAU_BACKLIGHT=y
+CONFIG_DRM_NOUVEAU_DEBUG=y
+
+#
+# I2C encoder or helper chips
+#
+# CONFIG_DRM_I2C_CH7006 is not set
+CONFIG_DRM_I2C_SIL164=m
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+CONFIG_HYPERV=m
+CONFIG_HYPERV_STORAGE=m
+CONFIG_HYPERV_BLOCK=m
+CONFIG_HYPERV_NET=m
+CONFIG_HYPERV_UTILS=m
+# CONFIG_VME_BUS is not set
+# CONFIG_DX_SEP is not set
+# CONFIG_IIO is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_ZRAM is not set
+# CONFIG_WLAGS49_H2 is not set
+# CONFIG_WLAGS49_H25 is not set
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_VIDEO_DT3155 is not set
+# CONFIG_CRYSTALHD is not set
+# CONFIG_CXT1E1 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_ST_BT is not set
+# CONFIG_FB_XGI is not set
+# CONFIG_LIRC_STAGING is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_EASYCAP is not set
+# CONFIG_SOLO6X10 is not set
+# CONFIG_ACPI_QUICKSTART is not set
+CONFIG_MACH_NO_WESTBRIDGE=y
+# CONFIG_SBE_2T3E3 is not set
+# CONFIG_ATH6K_LEGACY is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_ACER_WMI=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_DELL_LAPTOP=m
+CONFIG_DELL_WMI=m
+CONFIG_FUJITSU_LAPTOP=m
+# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
+# CONFIG_TC1100_WMI is not set
+CONFIG_HP_WMI=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+# CONFIG_SONYPI_COMPAT is not set
+CONFIG_IDEAPAD_LAPTOP=m
+CONFIG_THINKPAD_ACPI=m
+CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y
+# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_SENSORS_HDAPS=m
+CONFIG_INTEL_MENLOW=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_EEEPC_WMI=m
+CONFIG_ACPI_WMI=m
+CONFIG_MSI_WMI=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_TOPSTAR_LAPTOP is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_TOSHIBA_BT_RFKILL=m
+CONFIG_ACPI_CMPC=m
+CONFIG_INTEL_IPS=m
+# CONFIG_IBM_RTL is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+# CONFIG_EDD_OFF is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+CONFIG_DMIID=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=m
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_HISTOGRAM=y
+# CONFIG_FSCACHE_DEBUG is not set
+# CONFIG_FSCACHE_OBJECT_LIST is not set
+CONFIG_CACHEFILES=m
+# CONFIG_CACHEFILES_DEBUG is not set
+# CONFIG_CACHEFILES_HISTOGRAM is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=m
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_LOGFS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_LZO is not set
+CONFIG_SQUASHFS_XZ=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_EXOFS_FS=m
+# CONFIG_EXOFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+# CONFIG_NFS_FSCACHE is not set
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_DEPRECATED=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_XPRT_RDMA=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_CEPH_FS=m
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_DFS_UPCALL=y
+# CONFIG_CIFS_FSCACHE is not set
+# CONFIG_CIFS_ACL is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_BKL=y
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LKDTM is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_RING_BUFFER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_TEST_KSTRTOX=m
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_DOUBLEFAULT=y
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_OPTIMIZE_INLINING is not set
+
+#
+# Security options
+#
+
+#
+# Grsecurity
+#
+CONFIG_GRKERNSEC=y
+# CONFIG_GRKERNSEC_LOW is not set
+# CONFIG_GRKERNSEC_MEDIUM is not set
+# CONFIG_GRKERNSEC_HIGH is not set
+CONFIG_GRKERNSEC_CUSTOM=y
+
+#
+# Address Space Protection
+#
+CONFIG_GRKERNSEC_KMEM=y
+# CONFIG_GRKERNSEC_VM86 is not set
+# CONFIG_GRKERNSEC_IO is not set
+CONFIG_GRKERNSEC_PROC_MEMMAP=y
+# CONFIG_GRKERNSEC_BRUTE is not set
+# CONFIG_GRKERNSEC_MODHARDEN is not set
+# CONFIG_GRKERNSEC_HIDESYM is not set
+# CONFIG_GRKERNSEC_KERN_LOCKOUT is not set
+
+#
+# Role Based Access Control Options
+#
+# CONFIG_GRKERNSEC_NO_RBAC is not set
+CONFIG_GRKERNSEC_ACL_HIDEKERN=y
+CONFIG_GRKERNSEC_ACL_MAXTRIES=3
+CONFIG_GRKERNSEC_ACL_TIMEOUT=30
+
+#
+# Filesystem Protections
+#
+CONFIG_GRKERNSEC_PROC=y
+# CONFIG_GRKERNSEC_PROC_USER is not set
+CONFIG_GRKERNSEC_PROC_USERGROUP=y
+CONFIG_GRKERNSEC_PROC_GID=30
+CONFIG_GRKERNSEC_PROC_ADD=y
+CONFIG_GRKERNSEC_LINK=y
+CONFIG_GRKERNSEC_FIFO=y
+CONFIG_GRKERNSEC_SYSFS_RESTRICT=y
+# CONFIG_GRKERNSEC_ROFS is not set
+CONFIG_GRKERNSEC_CHROOT=y
+CONFIG_GRKERNSEC_CHROOT_MOUNT=y
+CONFIG_GRKERNSEC_CHROOT_DOUBLE=y
+CONFIG_GRKERNSEC_CHROOT_PIVOT=y
+CONFIG_GRKERNSEC_CHROOT_CHDIR=y
+CONFIG_GRKERNSEC_CHROOT_CHMOD=y
+CONFIG_GRKERNSEC_CHROOT_FCHDIR=y
+CONFIG_GRKERNSEC_CHROOT_MKNOD=y
+CONFIG_GRKERNSEC_CHROOT_SHMAT=y
+CONFIG_GRKERNSEC_CHROOT_UNIX=y
+CONFIG_GRKERNSEC_CHROOT_FINDTASK=y
+CONFIG_GRKERNSEC_CHROOT_NICE=y
+CONFIG_GRKERNSEC_CHROOT_SYSCTL=y
+CONFIG_GRKERNSEC_CHROOT_CAPS=y
+
+#
+# Kernel Auditing
+#
+# CONFIG_GRKERNSEC_AUDIT_GROUP is not set
+# CONFIG_GRKERNSEC_EXECLOG is not set
+CONFIG_GRKERNSEC_RESLOG=y
+# CONFIG_GRKERNSEC_CHROOT_EXECLOG is not set
+# CONFIG_GRKERNSEC_AUDIT_PTRACE is not set
+# CONFIG_GRKERNSEC_AUDIT_CHDIR is not set
+# CONFIG_GRKERNSEC_AUDIT_MOUNT is not set
+CONFIG_GRKERNSEC_SIGNAL=y
+CONFIG_GRKERNSEC_FORKFAIL=y
+CONFIG_GRKERNSEC_TIME=y
+CONFIG_GRKERNSEC_PROC_IPADDR=y
+# CONFIG_GRKERNSEC_RWXMAP_LOG is not set
+# CONFIG_GRKERNSEC_AUDIT_TEXTREL is not set
+
+#
+# Executable Protections
+#
+CONFIG_GRKERNSEC_EXECVE=y
+# CONFIG_GRKERNSEC_DMESG is not set
+CONFIG_GRKERNSEC_HARDEN_PTRACE=y
+# CONFIG_GRKERNSEC_TPE is not set
+
+#
+# Network Protections
+#
+CONFIG_GRKERNSEC_RANDNET=y
+# CONFIG_GRKERNSEC_BLACKHOLE is not set
+# CONFIG_GRKERNSEC_SOCKET is not set
+
+#
+# Sysctl support
+#
+CONFIG_GRKERNSEC_SYSCTL=y
+CONFIG_GRKERNSEC_SYSCTL_ON=y
+
+#
+# Logging Options
+#
+CONFIG_GRKERNSEC_FLOODTIME=10
+CONFIG_GRKERNSEC_FLOODBURST=4
+
+#
+# PaX
+#
+CONFIG_ARCH_TRACK_EXEC_LIMIT=y
+CONFIG_PAX=y
+
+#
+# PaX Control
+#
+CONFIG_PAX_SOFTMODE=y
+# CONFIG_PAX_EI_PAX is not set
+CONFIG_PAX_PT_PAX_FLAGS=y
+# CONFIG_PAX_NO_ACL_FLAGS is not set
+CONFIG_PAX_HAVE_ACL_FLAGS=y
+# CONFIG_PAX_HOOK_ACL_FLAGS is not set
+
+#
+# Non-executable pages
+#
+CONFIG_PAX_NOEXEC=y
+CONFIG_PAX_PAGEEXEC=y
+CONFIG_PAX_SEGMEXEC=y
+CONFIG_PAX_EMUTRAMP=y
+CONFIG_PAX_MPROTECT=y
+# CONFIG_PAX_MPROTECT_COMPAT is not set
+# CONFIG_PAX_ELFRELOCS is not set
+# CONFIG_PAX_KERNEXEC is not set
+
+#
+# Address Space Layout Randomization
+#
+CONFIG_PAX_ASLR=y
+CONFIG_PAX_RANDUSTACK=y
+CONFIG_PAX_RANDMMAP=y
+
+#
+# Miscellaneous hardening features
+#
+# CONFIG_PAX_MEMORY_SANITIZE is not set
+# CONFIG_PAX_MEMORY_STACKLEAK is not set
+# CONFIG_PAX_MEMORY_UDEREF is not set
+CONFIG_PAX_REFCOUNT=y
+# CONFIG_PAX_USERCOPY is not set
+CONFIG_KEYS=y
+CONFIG_TRUSTED_KEYS=m
+CONFIG_ENCRYPTED_KEYS=m
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_IMA is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y
+CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_FPU=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C_INTEL=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_AES_NI_INTEL=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SALSA20_586=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_TWOFISH_586=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_USER_API=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+# CONFIG_CRYPTO_DEV_GEODE is not set
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_APIC_ARCHITECTURE=y
+CONFIG_KVM_MMIO=y
+CONFIG_KVM_ASYNC_PF=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_KVM_AMD=m
+CONFIG_VHOST_NET=m
+# CONFIG_LGUEST is not set
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_BTREE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_NLATTR=y
+CONFIG_AVERAGE=y
diff --git a/main/linux-grsec/kernelconfig.x86_64 b/main/linux-grsec/kernelconfig.x86_64
new file mode 100644
index 0000000000..c035fc93bf
--- /dev/null
+++ b/main/linux-grsec/kernelconfig.x86_64
@@ -0,0 +1,5111 @@
+#
+# Automatically generated make config: don't edit
+# Linux/x86_64 2.6.38.3 Kernel Configuration
+# Mon Apr 18 10:45:51 2011
+#
+CONFIG_64BIT=y
+# CONFIG_X86_32 is not set
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_X86_64_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
+# CONFIG_KTIME_SCALAR is not set
+CONFIG_ARCH_CPU_PROBE_RELEASE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+# CONFIG_AUTO_IRQ_AFFINITY is not set
+# CONFIG_IRQ_PER_CPU is not set
+# CONFIG_HARDIRQS_SW_RESEND is not set
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+CONFIG_RCU_FAST_NO_HZ=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=m
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+# CONFIG_PROC_PID_CPUSET is not set
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+# CONFIG_CGROUP_MEM_RES_CTLR is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+# CONFIG_JUMP_LABEL is not set
+CONFIG_OPTPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_KRETPROBES=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_DEV_THROTTLING is not set
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CFQ_GROUP_IOSCHED is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_PADATA=y
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_VSMP is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_PARAVIRT_GUEST=y
+CONFIG_XEN=y
+CONFIG_XEN_DOM0=y
+CONFIG_XEN_PRIVILEGED_GUEST=y
+CONFIG_XEN_PVHVM=y
+CONFIG_XEN_MAX_DOMAIN_MEMORY=128
+CONFIG_XEN_SAVE_RESTORE=y
+# CONFIG_XEN_DEBUG_FS is not set
+CONFIG_KVM_CLOCK=y
+CONFIG_KVM_GUEST=y
+CONFIG_PARAVIRT=y
+# CONFIG_PARAVIRT_SPINLOCKS is not set
+CONFIG_PARAVIRT_CLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_MEMTEST is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_CPU=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_CMPXCHG=y
+CONFIG_CMPXCHG_LOCAL=y
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_XADD=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+CONFIG_GART_IOMMU=y
+# CONFIG_CALGARY_IOMMU is not set
+# CONFIG_AMD_IOMMU is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_IOMMU_API is not set
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+# CONFIG_X86_MCE is not set
+CONFIG_I8K=m
+CONFIG_MICROCODE=m
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_DIRECT_GBPAGES=y
+# CONFIG_NUMA is not set
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
+# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW=64
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+# CONFIG_EFI is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_300=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=300
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM_OPS=y
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+# CONFIG_ACPI_POWER_METER is not set
+CONFIG_ACPI_EC_DEBUGFS=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_IPMI=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=m
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+CONFIG_ACPI_HED=m
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=m
+CONFIG_ACPI_APEI_EINJ=m
+CONFIG_ACPI_APEI_ERST_DEBUG=y
+# CONFIG_SFI is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_PCC_CPUFREQ=m
+CONFIG_X86_ACPI_CPUFREQ=m
+CONFIG_X86_POWERNOW_K8=m
+CONFIG_X86_SPEEDSTEP_CENTRINO=m
+CONFIG_X86_P4_CLOCKMOD=m
+
+#
+# shared options
+#
+CONFIG_X86_SPEEDSTEP_LIB=m
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_INTEL_IDLE=y
+
+#
+# Memory power savings
+#
+# CONFIG_I7300_IDLE is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_XEN=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_CNB20LE_QUIRK=y
+# CONFIG_DMAR is not set
+# CONFIG_INTR_REMAP is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_PCIEAER is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_STUB=m
+CONFIG_XEN_PCIDEV_FRONTEND=y
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+CONFIG_PCI_IOAPIC=y
+CONFIG_ISA_DMA_API=y
+CONFIG_AMD_NB=y
+CONFIG_PCCARD=m
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+CONFIG_HOTPLUG_PCI=m
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_SHPC=m
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_HAVE_TEXT_POKE_SMP=y
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+# CONFIG_IP_PIMSM_V1 is not set
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETLABEL=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_GRADM=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_NFCT=y
+CONFIG_IP_VS_PE_SIP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_SCTP=m
+CONFIG_NET_SCTPPROBE=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+CONFIG_RDS=m
+# CONFIG_RDS_RDMA is not set
+# CONFIG_RDS_TCP is not set
+# CONFIG_RDS_DEBUG is not set
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+CONFIG_WAN_ROUTER=m
+CONFIG_PHONET=m
+# CONFIG_PHONET_PIPECTRLR is not set
+CONFIG_IEEE802154=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_CLS_CGROUP is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+CONFIG_RPS=y
+CONFIG_XPS=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_DEV=m
+# CONFIG_CAN_CALC_BITTIMING is not set
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_JANZ_ICAN3=m
+# CONFIG_PCH_CAN is not set
+CONFIG_CAN_SJA1000=m
+CONFIG_CAN_SJA1000_PLATFORM=m
+CONFIG_CAN_EMS_PCI=m
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PLX_PCI=m
+
+#
+# CAN USB interfaces
+#
+# CONFIG_CAN_EMS_USB is not set
+# CONFIG_CAN_ESD_USB2 is not set
+CONFIG_CAN_SOFTING=m
+CONFIG_CAN_SOFTING_CS=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_RXKAD=m
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+# CONFIG_RFKILL_INPUT is not set
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NET_9P_RDMA=m
+# CONFIG_NET_9P_DEBUG is not set
+CONFIG_CAIF=m
+# CONFIG_CAIF_DEBUG is not set
+CONFIG_CAIF_NETDEV=m
+CONFIG_CEPH_LIB=m
+# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=m
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+CONFIG_SYS_HYPERVISOR=y
+CONFIG_CONNECTOR=m
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_AR7_PARTS=m
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_HAVE_MTD_OTP=y
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+CONFIG_SSFDC=m
+CONFIG_SM_FTL=m
+CONFIG_MTD_OOPS=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_AMD76XROM=m
+CONFIG_MTD_ICHXROM=m
+CONFIG_MTD_ESB2ROM=m
+CONFIG_MTD_CK804XROM=m
+CONFIG_MTD_SCB2_FLASH=m
+CONFIG_MTD_NETtel=m
+CONFIG_MTD_L440GX=m
+CONFIG_MTD_PCI=m
+CONFIG_MTD_PCMCIA=m
+# CONFIG_MTD_PCMCIA_ANONYMOUS is not set
+# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_INTEL_VR_NOR=m
+CONFIG_MTD_PLATRAM=m
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+CONFIG_MTD_PMC551_BUGFIX=y
+# CONFIG_MTD_PMC551_DEBUG is not set
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DATAFLASH_OTP is not set
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_MTD_SST25L is not set
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+# CONFIG_MTD_DOCPROBE_HIGH is not set
+# CONFIG_MTD_DOCPROBE_55AA is not set
+CONFIG_MTD_NAND_ECC=m
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_SM_COMMON=m
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_DENALI=m
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_RICOH=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CAFE=m
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_ALAUDA=m
+CONFIG_MTD_ONENAND=m
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OTP=y
+CONFIG_MTD_ONENAND_2X_PROGRAM=y
+CONFIG_MTD_ONENAND_SIM=m
+
+#
+# LPDDR flash memory drivers
+#
+CONFIG_MTD_LPDDR=m
+CONFIG_MTD_QINFO_PROBE=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_AX88796=m
+# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=m
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_AD525X_DPOT_SPI=m
+CONFIG_IBM_ASM=m
+CONFIG_PHANTOM=m
+CONFIG_SGI_IOC4=m
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
+CONFIG_ICS932S401=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_CS5535_MFGPT=m
+CONFIG_CS5535_MFGPT_DEFAULT_IRQ=7
+CONFIG_CS5535_CLOCK_EVENT_SRC=m
+CONFIG_HP_ILO=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1780=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_TI_DAC7512=m
+CONFIG_VMWARE_BALLOON=m
+CONFIG_BMP085=m
+CONFIG_PCH_PHUB=m
+CONFIG_C2PORT=m
+CONFIG_C2PORT_DURAMAR_2150=m
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_AT25=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93CX6=m
+CONFIG_CB710_CORE=m
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
+CONFIG_IWMC3200TOP=m
+# CONFIG_IWMC3200TOP_DEBUG is not set
+# CONFIG_IWMC3200TOP_DEBUGFS is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_FC_TGT_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_HOST_SMP=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+# CONFIG_BE2ISCSI is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_HPSA=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_3W_SAS=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
+CONFIG_SCSI_MVSAS=m
+CONFIG_SCSI_MVSAS_DEBUG=y
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_ARCMSR=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_MPT2SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
+# CONFIG_SCSI_MPT2SAS_LOGGING is not set
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_BUSLOGIC=m
+CONFIG_VMWARE_PVSCSI=m
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+CONFIG_FCOE=m
+CONFIG_FCOE_FNIC=m
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_EATA=m
+# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set
+# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+CONFIG_SCSI_IPR_TRACE=y
+# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_PMCRAID is not set
+CONFIG_SCSI_PM8001=m
+CONFIG_SCSI_SRP=m
+# CONFIG_SCSI_BFA_FC is not set
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_SCSI_OSD_DPRINT_SENSE=1
+# CONFIG_SCSI_OSD_DEBUG is not set
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_SATA_INIC162X=m
+CONFIG_SATA_ACARD_AHCI=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SX4=m
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+CONFIG_ATA_PIIX=m
+CONFIG_SATA_MV=m
+CONFIG_SATA_NV=m
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+
+#
+# PATA SFF controllers with BMDMA
+#
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+CONFIG_PATA_ATP867X=m
+CONFIG_PATA_CMD64X=m
+CONFIG_PATA_CS5520=m
+CONFIG_PATA_CS5530=m
+CONFIG_PATA_CS5536=m
+CONFIG_PATA_CYPRESS=m
+CONFIG_PATA_EFAR=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+CONFIG_PATA_HPT3X2N=m
+CONFIG_PATA_HPT3X3=m
+CONFIG_PATA_HPT3X3_DMA=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87415=m
+CONFIG_PATA_OLDPIIX=m
+CONFIG_PATA_OPTIDMA=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_PDC_OLD=m
+CONFIG_PATA_RADISYS=m
+CONFIG_PATA_RDC=m
+CONFIG_PATA_SC1200=m
+CONFIG_PATA_SCH=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_TOSHIBA=m
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+
+#
+# PIO-only SFF controllers
+#
+CONFIG_PATA_CMD640_PCI=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_OPTI=m
+CONFIG_PATA_PCMCIA=m
+CONFIG_PATA_PLATFORM=m
+CONFIG_PATA_RZ1000=m
+
+#
+# Generic fallback / legacy drivers
+#
+CONFIG_PATA_ACPI=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_LEGACY=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_AUTODETECT is not set
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MULTICORE_RAID456 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_OHCI_DEBUG=y
+CONFIG_FIREWIRE_SBP2=m
+CONFIG_FIREWIRE_NET=m
+CONFIG_FIREWIRE_NOSY=m
+CONFIG_I2O=m
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+CONFIG_ARCNET=m
+CONFIG_ARCNET_1201=m
+CONFIG_ARCNET_1051=m
+CONFIG_ARCNET_RAW=m
+CONFIG_ARCNET_CAP=m
+CONFIG_ARCNET_COM90xx=m
+CONFIG_ARCNET_COM90xxIO=m
+CONFIG_ARCNET_RIM_I=m
+CONFIG_ARCNET_COM20020=m
+CONFIG_ARCNET_COM20020_PCI=m
+CONFIG_MII=m
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_BCM63XX_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MICREL_PHY=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_MDIO_GPIO=m
+CONFIG_NET_ETHERNET=y
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ETHOC=m
+CONFIG_DNET=m
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_DE2104X_DSL=0
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_HP100=m
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_KSZ884X_PCI=m
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SMSC9420=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_KS8842=m
+CONFIG_KS8851=m
+CONFIG_KS8851_MLL=m
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_ATL2=m
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_IP1000=m
+CONFIG_IGB=m
+CONFIG_IGB_DCA=y
+CONFIG_IGBVF=m
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_CNIC=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_ATL1C=m
+CONFIG_JME=m
+CONFIG_STMMAC_ETH=m
+# CONFIG_STMMAC_DA is not set
+# CONFIG_STMMAC_DUAL_MAC is not set
+CONFIG_PCH_GBE=m
+CONFIG_NETDEV_10000=y
+CONFIG_MDIO=m
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3_DEPENDS=y
+CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4_DEPENDS=y
+CONFIG_CHELSIO_T4=m
+CONFIG_CHELSIO_T4VF_DEPENDS=y
+CONFIG_CHELSIO_T4VF=m
+CONFIG_ENIC=m
+CONFIG_IXGBE=m
+CONFIG_IXGBE_DCA=y
+# CONFIG_IXGBEVF is not set
+CONFIG_IXGB=m
+CONFIG_S2IO=m
+CONFIG_VXGE=m
+# CONFIG_VXGE_DEBUG_TRACE_ALL is not set
+CONFIG_MYRI10GE=m
+CONFIG_MYRI10GE_DCA=y
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_QLCNIC=m
+CONFIG_QLGE=m
+CONFIG_BNA=m
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_BE2NET=m
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AIRO=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_AT76C50X_USB=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+CONFIG_ADM8211=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_MWL8K=m
+CONFIG_ATH_COMMON=m
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH5K_PCI=y
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K=m
+# CONFIG_ATH9K_DEBUGFS is not set
+CONFIG_ATH9K_RATE_CONTROL=y
+CONFIG_ATH9K_HTC=m
+# CONFIG_ATH9K_HTC_DEBUGFS is not set
+CONFIG_AR9170_USB=m
+CONFIG_AR9170_LEDS=y
+CONFIG_CARL9170=m
+CONFIG_CARL9170_LEDS=y
+CONFIG_CARL9170_WPC=y
+CONFIG_B43=m
+CONFIG_B43_PCI_AUTOSELECT=y
+CONFIG_B43_PCICORE_AUTOSELECT=y
+CONFIG_B43_PCMCIA=y
+CONFIG_B43_SDIO=y
+CONFIG_B43_PIO=y
+CONFIG_B43_PHY_N=y
+CONFIG_B43_PHY_LP=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_PCI_AUTOSELECT=y
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_HWRNG=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
+CONFIG_IWLWIFI=m
+
+#
+# Debugging Options
+#
+# CONFIG_IWLWIFI_DEBUG is not set
+CONFIG_IWLAGN=m
+CONFIG_IWL4965=y
+CONFIG_IWL5000=y
+CONFIG_IWL3945=m
+CONFIG_IWM=m
+# CONFIG_IWM_DEBUG is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_CS=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_LIBERTAS_MESH=y
+CONFIG_HERMES=m
+# CONFIG_HERMES_PRISM is not set
+CONFIG_HERMES_CACHE_FW_ON_INIT=y
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ORINOCO_USB=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_P54_PCI=m
+CONFIG_P54_SPI=m
+# CONFIG_P54_SPI_DEFAULT_EEPROM is not set
+CONFIG_P54_LEDS=y
+CONFIG_RT2X00=m
+CONFIG_RT2400PCI=m
+CONFIG_RT2500PCI=m
+CONFIG_RT61PCI=m
+CONFIG_RT2800PCI=m
+CONFIG_RT2800PCI_RT33XX=y
+# CONFIG_RT2800PCI_RT35XX is not set
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT33XX=y
+# CONFIG_RT2800USB_RT35XX is not set
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RT2800_LIB=m
+CONFIG_RT2X00_LIB_PCI=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_HT=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_RTL8192CE=m
+CONFIG_RTLWIFI=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SPI=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_HT=y
+CONFIG_WL12XX_SPI=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_WL12XX_SDIO_TEST=m
+CONFIG_WL12XX_PLATFORM_DATA=y
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+CONFIG_WIMAX_I2400M=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_WIMAX_I2400M_SDIO=m
+CONFIG_WIMAX_IWMC3200_SDIO=y
+CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_CDC_PHONET=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_ARCNET_COM20020_CS=m
+CONFIG_WAN=y
+CONFIG_LANMEDIA=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=m
+CONFIG_HDLC_RAW_ETH=m
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_X25=m
+CONFIG_PCI200SYN=m
+CONFIG_WANXL=m
+# CONFIG_WANXL_BUILD_FIRMWARE is not set
+CONFIG_PC300TOO=m
+CONFIG_FARSYNC=m
+CONFIG_DSCC4=m
+CONFIG_DSCC4_PCISYNC=y
+CONFIG_DSCC4_PCI_RST=y
+CONFIG_DLCI=m
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=m
+CONFIG_CYCLADES_SYNC=m
+CONFIG_CYCLOMX_X25=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+CONFIG_SBNI=m
+CONFIG_SBNI_MULTILINE=y
+CONFIG_ATM_DRIVERS=y
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_USE_TASKLET=y
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_ATM_SOLOS=m
+CONFIG_IEEE802154_DRIVERS=m
+CONFIG_IEEE802154_FAKEHARD=m
+
+#
+# CAIF transport drivers
+#
+CONFIG_CAIF_TTY=m
+CONFIG_CAIF_SPI_SLAVE=m
+# CONFIG_CAIF_SPI_SYNC is not set
+CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_FDDI=y
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_SKFP=m
+CONFIG_HIPPI=y
+CONFIG_ROADRUNNER=m
+# CONFIG_ROADRUNNER_LARGE_RINGS is not set
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOATM=m
+CONFIG_PPPOL2TP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+CONFIG_VMXNET3=m
+CONFIG_ISDN=y
+# CONFIG_ISDN_I4L is not set
+CONFIG_ISDN_CAPI=m
+# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set
+# CONFIG_CAPI_TRACE is not set
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_CAPI=y
+# CONFIG_GIGASET_DUMMYLL is not set
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+CONFIG_GIGASET_M101=m
+# CONFIG_GIGASET_DEBUG is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+CONFIG_MISDN=m
+CONFIG_MISDN_DSP=m
+CONFIG_MISDN_L1OIP=m
+
+#
+# mISDN hardware drivers
+#
+CONFIG_MISDN_HFCPCI=m
+CONFIG_MISDN_HFCMULTI=m
+CONFIG_MISDN_HFCUSB=m
+CONFIG_MISDN_AVMFRITZ=m
+# CONFIG_MISDN_SPEEDFAX is not set
+# CONFIG_MISDN_INFINEON is not set
+# CONFIG_MISDN_W6692 is not set
+# CONFIG_MISDN_NETJET is not set
+CONFIG_MISDN_IPAC=m
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_POLLDEV=m
+CONFIG_INPUT_SPARSEKMAP=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+CONFIG_XEN_KBDDEV_FRONTEND=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT2160 is not set
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_GPIO_POLLED=m
+CONFIG_KEYBOARD_TCA6416=m
+CONFIG_KEYBOARD_MATRIX=m
+CONFIG_KEYBOARD_LM8323=m
+# CONFIG_KEYBOARD_MAX7359 is not set
+CONFIG_KEYBOARD_MCS=m
+CONFIG_KEYBOARD_NEWTON=m
+# CONFIG_KEYBOARD_OPENCORES is not set
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_GPIO=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_AD7877=m
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_AD7879_SPI=m
+CONFIG_TOUCHSCREEN_BU21013=m
+CONFIG_TOUCHSCREEN_CY8CTMG110=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_QT602240=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_UCB1400=m
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+# CONFIG_TOUCHSCREEN_MC13783 is not set
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
+CONFIG_TOUCHSCREEN_USB_NEXIO=y
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_ST1232=m
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_AD714X_I2C=m
+CONFIG_INPUT_AD714X_SPI=m
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_APANEL=m
+CONFIG_INPUT_ATLAS_BTNS=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_PCF50633_PMU=m
+CONFIG_INPUT_PCF8574=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_ADXL34X_I2C=m
+CONFIG_INPUT_ADXL34X_SPI=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_INPUT_CMA3000_I2C=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_ALTERA_PS2=m
+CONFIG_SERIO_PS2MULT=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_COMPUTONE=m
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+CONFIG_ISI=m
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_N_GSM is not set
+CONFIG_RISCOM8=m
+CONFIG_SPECIALIX=m
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MAX3100=m
+CONFIG_SERIAL_MAX3107=m
+CONFIG_SERIAL_MRST_MAX3110=m
+CONFIG_SERIAL_MFD_HSU=m
+CONFIG_SERIAL_UARTLITE=m
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_SERIAL_TIMBERDALE=m
+CONFIG_SERIAL_ALTERA_JTAGUART=m
+CONFIG_SERIAL_ALTERA_UART=m
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
+CONFIG_SERIAL_IFX6X60=m
+CONFIG_SERIAL_PCH_UART=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_XEN=y
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=m
+CONFIG_R3964=m
+CONFIG_APPLICOM=m
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+CONFIG_MWAVE=m
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+CONFIG_TELCLOCK=m
+CONFIG_RAMOOPS=m
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_MUX=m
+
+#
+# Multiplexer I2C Chip support
+#
+CONFIG_I2C_MUX_GPIO=m
+CONFIG_I2C_MUX_PCA9541=m
+CONFIG_I2C_MUX_PCA954x=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_SMBUS=m
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+
+#
+# ACPI drivers
+#
+CONFIG_I2C_SCMI=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=m
+CONFIG_I2C_INTEL_MID=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_XILINX=m
+CONFIG_I2C_EG20T=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+CONFIG_SPI_BUTTERFLY=m
+CONFIG_SPI_GPIO=m
+CONFIG_SPI_LM70_LLP=m
+# CONFIG_SPI_PXA2XX_PCI is not set
+CONFIG_SPI_TOPCLIFF_PCH=m
+# CONFIG_SPI_XILINX is not set
+CONFIG_SPI_DESIGNWARE=m
+CONFIG_SPI_DW_PCI=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+CONFIG_GPIO_MAX730X=m
+
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_BASIC_MMIO=m
+CONFIG_GPIO_IT8761E=m
+CONFIG_GPIO_SCH=m
+CONFIG_GPIO_VX855=m
+
+#
+# I2C GPIO expanders:
+#
+CONFIG_GPIO_MAX7300=m
+CONFIG_GPIO_MAX732X=m
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_ADP5588=m
+
+#
+# PCI GPIO expanders:
+#
+CONFIG_GPIO_CS5535=m
+# CONFIG_GPIO_LANGWELL is not set
+CONFIG_GPIO_PCH=m
+CONFIG_GPIO_ML_IOH=m
+CONFIG_GPIO_TIMBERDALE=y
+CONFIG_GPIO_RDC321X=m
+
+#
+# SPI GPIO expanders:
+#
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MCP23S08=m
+# CONFIG_GPIO_MC33880 is not set
+CONFIG_GPIO_74X164=m
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_GPIO_UCB1400 is not set
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_GPIO_JANZ_TTL=m
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_GPIO=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PDA_POWER=m
+CONFIG_TEST_POWER=m
+CONFIG_BATTERY_DS2760=m
+CONFIG_BATTERY_DS2782=m
+CONFIG_BATTERY_BQ20Z75=m
+CONFIG_BATTERY_BQ27x00=m
+CONFIG_BATTERY_MAX17040=m
+CONFIG_BATTERY_MAX17042=m
+CONFIG_CHARGER_PCF50633=m
+CONFIG_CHARGER_ISP1704=m
+CONFIG_CHARGER_GPIO=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7411=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7475=m
+CONFIG_SENSORS_ASC7621=m
+CONFIG_SENSORS_K8TEMP=m
+CONFIG_SENSORS_K10TEMP=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS620=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_G760A=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_GPIO_FAN=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_PKGTEMP=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_JC42=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LTC4215=m
+CONFIG_SENSORS_LTC4245=m
+CONFIG_SENSORS_LTC4261=m
+CONFIG_SENSORS_LM95241=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SHT21=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMM665=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
+CONFIG_SENSORS_EMC2103=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_ADS7871=m
+CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=m
+CONFIG_SENSORS_TMP401=m
+CONFIG_SENSORS_TMP421=m
+CONFIG_SENSORS_VIA_CPUTEMP=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83795=m
+CONFIG_SENSORS_W83795_FANCTRL=y
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_LIS3_I2C=m
+CONFIG_SENSORS_APPLESMC=m
+# CONFIG_SENSORS_MC13783_ADC is not set
+
+#
+# ACPI drivers
+#
+CONFIG_SENSORS_ATK0110=m
+CONFIG_SENSORS_LIS3LV02D=m
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_F71808E_WDT=m
+CONFIG_SP5100_TCO=m
+CONFIG_GEODE_WDT=m
+CONFIG_SC520_WDT=m
+# CONFIG_SBC_FITPC2_WATCHDOG is not set
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_WAFER_WDT=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_ITCO_WDT=m
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_IT8712F_WDT=m
+CONFIG_IT87_WDT=m
+# CONFIG_HP_WATCHDOG is not set
+CONFIG_SC1200_WDT=m
+CONFIG_PC87413_WDT=m
+CONFIG_NV_TCO=m
+CONFIG_60XX_WDT=m
+CONFIG_SBC8360_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_SMSC_SCH311X_WDT=m
+CONFIG_SMSC37B787_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83697HF_WDT=m
+CONFIG_W83697UG_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+CONFIG_SSB_SDIOHOST=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_MFD_SUPPORT=y
+CONFIG_MFD_CORE=m
+CONFIG_MFD_SM501=m
+# CONFIG_MFD_SM501_GPIO is not set
+CONFIG_HTC_PASIC3=m
+CONFIG_UCB1400_CORE=m
+CONFIG_TPS65010=m
+CONFIG_TPS6507X=m
+# CONFIG_MFD_TMIO is not set
+CONFIG_MFD_WM8400=m
+# CONFIG_MFD_WM831X_SPI is not set
+CONFIG_MFD_PCF50633=m
+CONFIG_MFD_MC13783=m
+CONFIG_MFD_MC13XXX=m
+CONFIG_PCF50633_ADC=m
+CONFIG_PCF50633_GPIO=m
+CONFIG_ABX500_CORE=y
+# CONFIG_EZX_PCAP is not set
+# CONFIG_AB8500_CORE is not set
+CONFIG_MFD_CS5535=m
+CONFIG_MFD_TIMBERDALE=m
+CONFIG_LPC_SCH=m
+CONFIG_MFD_RDC321X=m
+CONFIG_MFD_JANZ_CMODIO=m
+CONFIG_MFD_VX855=m
+CONFIG_MFD_WL1273_CORE=m
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_REGULATOR_BQ24022=m
+CONFIG_REGULATOR_MAX1586=m
+CONFIG_REGULATOR_MAX8649=m
+CONFIG_REGULATOR_MAX8660=m
+CONFIG_REGULATOR_MAX8952=m
+CONFIG_REGULATOR_WM8400=m
+CONFIG_REGULATOR_PCF50633=m
+CONFIG_REGULATOR_LP3971=m
+CONFIG_REGULATOR_LP3972=m
+CONFIG_REGULATOR_MC13XXX_CORE=m
+CONFIG_REGULATOR_MC13783=m
+CONFIG_REGULATOR_MC13892=m
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_ISL6271A=m
+# CONFIG_REGULATOR_AD5398 is not set
+CONFIG_REGULATOR_TPS6524X=m
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_RC_CORE=m
+CONFIG_LIRC=m
+CONFIG_RC_MAP=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_RC5_SZ_DECODER=m
+CONFIG_IR_LIRC_CODEC=m
+# CONFIG_IR_ENE is not set
+CONFIG_IR_IMON=m
+# CONFIG_IR_MCEUSB is not set
+# CONFIG_IR_NUVOTON is not set
+# CONFIG_IR_STREAMZAP is not set
+CONFIG_IR_WINBOND_CIR=m
+CONFIG_RC_LOOPBACK=m
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_MEDIA_TUNER_TDA18218=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_V4L2_MEM2MEM_DEV=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+
+#
+# RDS decoders
+#
+CONFIG_VIDEO_SAA6588=m
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_ADV7180=m
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_BT866=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_MT9V011=m
+CONFIG_VIDEO_TCM825X=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_SAA7191=m
+CONFIG_VIDEO_TVP514X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_TVP7002=m
+CONFIG_VIDEO_VPX3220=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_THS7303=m
+CONFIG_VIDEO_ADV7343=m
+CONFIG_VIDEO_AK881X=m
+
+#
+# Video improvement chips
+#
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+# CONFIG_VIDEO_CPIA2 is not set
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_ZR36060=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_RC=y
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_TIMBERDALE=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_MPEG=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CX18_ALSA=m
+CONFIG_VIDEO_SAA7164=m
+CONFIG_VIDEO_CAFE_CCIC=m
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_VIA_CAMERA is not set
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_IMX074 is not set
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9T031=m
+CONFIG_SOC_CAMERA_MT9T112=m
+CONFIG_SOC_CAMERA_MT9V022=m
+CONFIG_SOC_CAMERA_RJ54N1=m
+CONFIG_SOC_CAMERA_TW9910=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_SOC_CAMERA_OV2640=m
+# CONFIG_SOC_CAMERA_OV6650 is not set
+CONFIG_SOC_CAMERA_OV772X=m
+CONFIG_SOC_CAMERA_OV9640=m
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+# CONFIG_USB_GSPCA_KONICA is not set
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+# CONFIG_USB_GSPCA_SQ930X is not set
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_RC=y
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_USB_ET61X251=m
+CONFIG_USB_SN9C102=m
+# CONFIG_USB_PWC is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MEM2MEM_TESTDEV=m
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_I2C_SI4713 is not set
+# CONFIG_RADIO_SI4713 is not set
+CONFIG_USB_DSBR=m
+# CONFIG_RADIO_SI470X is not set
+CONFIG_USB_MR800=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_TIMBERDALE=m
+CONFIG_RADIO_WL1273=m
+CONFIG_DVB_MAX_ADAPTERS=8
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_CE6230=m
+# CONFIG_DVB_USB_FRIIO is not set
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_AZ6027=m
+# CONFIG_DVB_USB_LME2510 is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_SMS_SIANO_MDTV=m
+
+#
+# Siano module components
+#
+CONFIG_SMS_USB_DRV=m
+CONFIG_SMS_SDIO_DRV=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported SDMC DM1105 Adapters
+#
+CONFIG_DVB_DM1105=m
+CONFIG_DVB_FIREDTV=m
+CONFIG_DVB_FIREDTV_FIREWIRE=y
+# CONFIG_DVB_FIREDTV_IEEE1394 is not set
+CONFIG_DVB_FIREDTV_INPUT=y
+
+#
+# Supported Earthsoft PT1 Adapters
+#
+# CONFIG_DVB_PT1 is not set
+
+#
+# Supported Mantis Adapters
+#
+CONFIG_MANTIS_CORE=m
+CONFIG_DVB_MANTIS=m
+CONFIG_DVB_HOPPER=m
+
+#
+# Supported nGene Adapters
+#
+CONFIG_DVB_NGENE=m
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+CONFIG_DVB_STV090x=m
+CONFIG_DVB_STV6110x=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10036=m
+CONFIG_DVB_ZL10039=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_STV6110=m
+CONFIG_DVB_STV0900=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_MB86A16=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+CONFIG_DVB_DIB8000=m
+CONFIG_DVB_MB86A20S=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_TDA665x=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+CONFIG_AGP=m
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_INTEL=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_VIA=m
+# CONFIG_VGA_ARB is not set
+CONFIG_VGA_SWITCHEROO=y
+CONFIG_DRM=m
+CONFIG_DRM_KMS_HELPER=m
+CONFIG_DRM_TTM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+# CONFIG_DRM_RADEON_KMS is not set
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+# CONFIG_DRM_I915_KMS is not set
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+# CONFIG_STUB_POULSBO is not set
+CONFIG_VGASTATE=m
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=m
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=m
+# CONFIG_FB_WMT_GE_ROPS is not set
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_HECUBA=m
+CONFIG_FB_SVGALIB=m
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+CONFIG_FB_PM2=m
+CONFIG_FB_PM2_FIFO_DISCONNECT=y
+CONFIG_FB_CYBER2000=m
+CONFIG_FB_ARC=m
+CONFIG_FB_VGA16=m
+CONFIG_FB_UVESA=m
+CONFIG_FB_N411=m
+CONFIG_FB_HGA=m
+CONFIG_FB_S1D13XXX=m
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_LE80578=m
+CONFIG_FB_CARILLO_RANCH=m
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_INTEL_I2C=y
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_S3=m
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+CONFIG_FB_SIS=m
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+CONFIG_FB_VIA=m
+# CONFIG_FB_VIA_DIRECT_PROCFS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_3DFX_I2C=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_VT8623=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_ARK=m
+CONFIG_FB_PM3=m
+CONFIG_FB_CARMINE=m
+CONFIG_FB_CARMINE_DRAM_EVAL=y
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
+CONFIG_FB_GEODE=y
+CONFIG_FB_GEODE_LX=m
+CONFIG_FB_GEODE_GX=m
+CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_TMIO=m
+CONFIG_FB_TMIO_ACCELL=y
+CONFIG_FB_SM501=m
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_XEN_FBDEV_FRONTEND=m
+CONFIG_FB_METRONOME=m
+CONFIG_FB_MB862XX=m
+# CONFIG_FB_MB862XX_PCI_GDC is not set
+CONFIG_FB_BROADSHEET=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_L4F00242T03=m
+CONFIG_LCD_LMS283GF05=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_ILI9320=m
+CONFIG_LCD_TDO24M=m
+CONFIG_LCD_VGG2432A4=m
+CONFIG_LCD_PLATFORM=m
+CONFIG_LCD_S6E63M0=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_PROGEAR=m
+CONFIG_BACKLIGHT_CARILLO_RANCH=m
+CONFIG_BACKLIGHT_MBP_NVIDIA=m
+CONFIG_BACKLIGHT_SAHARA=m
+CONFIG_BACKLIGHT_ADP8860=m
+CONFIG_BACKLIGHT_PCF50633=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_RAWMIDI_SEQ=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_PCSP=m
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_ALOOP is not set
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ASIHPI=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_CTXFI=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_INDIGOIOX=m
+CONFIG_SND_INDIGODJX=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_ES1968_INPUT=y
+CONFIG_SND_FM801=m
+# CONFIG_SND_FM801_TEA575X_BOOL is not set
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDA_HWDEP=y
+# CONFIG_SND_HDA_RECONFIG is not set
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_INPUT_BEEP_MODE=0
+CONFIG_SND_HDA_INPUT_JACK=y
+# CONFIG_SND_HDA_PATCH_LOADER is not set
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_CODEC_HDMI=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_GENERIC=y
+# CONFIG_SND_HDA_POWER_SAVE is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_LX6464ES=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MAESTRO3_INPUT=y
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+# CONFIG_SND_USB_CAIAQ_INPUT is not set
+CONFIG_SND_USB_US122L=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_PDAUDIOCF=m
+CONFIG_SND_SOC=m
+# CONFIG_SND_SOC_CACHE_LZO is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+CONFIG_SND_SOC_ALL_CODECS=m
+CONFIG_SND_SOC_WM_HUBS=m
+CONFIG_SND_SOC_AD1836=m
+CONFIG_SND_SOC_AD193X=m
+CONFIG_SND_SOC_AD73311=m
+CONFIG_SND_SOC_ADS117X=m
+CONFIG_SND_SOC_AK4104=m
+CONFIG_SND_SOC_AK4535=m
+CONFIG_SND_SOC_AK4642=m
+CONFIG_SND_SOC_AK4671=m
+CONFIG_SND_SOC_ALC5623=m
+CONFIG_SND_SOC_CS42L51=m
+CONFIG_SND_SOC_CS4270=m
+CONFIG_SND_SOC_CX20442=m
+CONFIG_SND_SOC_L3=m
+CONFIG_SND_SOC_DA7210=m
+CONFIG_SND_SOC_MAX98088=m
+CONFIG_SND_SOC_PCM3008=m
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_SSM2602=m
+CONFIG_SND_SOC_TLV320AIC23=m
+CONFIG_SND_SOC_TLV320AIC26=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_TLV320DAC33=m
+CONFIG_SND_SOC_UDA134X=m
+CONFIG_SND_SOC_UDA1380=m
+CONFIG_SND_SOC_WL1273=m
+CONFIG_SND_SOC_WM8400=m
+CONFIG_SND_SOC_WM8510=m
+CONFIG_SND_SOC_WM8523=m
+CONFIG_SND_SOC_WM8580=m
+CONFIG_SND_SOC_WM8711=m
+CONFIG_SND_SOC_WM8727=m
+CONFIG_SND_SOC_WM8728=m
+CONFIG_SND_SOC_WM8731=m
+CONFIG_SND_SOC_WM8737=m
+CONFIG_SND_SOC_WM8741=m
+CONFIG_SND_SOC_WM8750=m
+CONFIG_SND_SOC_WM8753=m
+CONFIG_SND_SOC_WM8770=m
+CONFIG_SND_SOC_WM8776=m
+CONFIG_SND_SOC_WM8804=m
+CONFIG_SND_SOC_WM8900=m
+CONFIG_SND_SOC_WM8903=m
+CONFIG_SND_SOC_WM8904=m
+CONFIG_SND_SOC_WM8940=m
+CONFIG_SND_SOC_WM8955=m
+CONFIG_SND_SOC_WM8960=m
+CONFIG_SND_SOC_WM8961=m
+CONFIG_SND_SOC_WM8962=m
+CONFIG_SND_SOC_WM8971=m
+CONFIG_SND_SOC_WM8974=m
+CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_WM8985=m
+CONFIG_SND_SOC_WM8988=m
+CONFIG_SND_SOC_WM8990=m
+CONFIG_SND_SOC_WM8993=m
+CONFIG_SND_SOC_WM8995=m
+CONFIG_SND_SOC_WM9081=m
+CONFIG_SND_SOC_MAX9877=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SOC_WM2000=m
+CONFIG_SND_SOC_WM9090=m
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_3M_PCT=m
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+CONFIG_HID_CANDO=m
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_PRODIKEYS=m
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+CONFIG_HID_EGALAX=m
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+CONFIG_HID_MAGICMOUSE=m
+# CONFIG_HID_MICROSOFT is not set
+CONFIG_HID_MOSART=m
+# CONFIG_HID_MONTEREY is not set
+CONFIG_HID_MULTITOUCH=m
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_ORTEK=m
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_ROCCAT_KONE=m
+CONFIG_HID_ROCCAT_KONEPLUS=m
+# CONFIG_HID_ROCCAT_PYRA is not set
+# CONFIG_HID_SAMSUNG is not set
+CONFIG_HID_SONY=m
+CONFIG_HID_STANTUM=m
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_HID_ZYDACRON=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+CONFIG_USB_WUSB=m
+CONFIG_USB_WUSB_CBAF=m
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_XHCI_HCD=m
+# CONFIG_USB_XHCI_HCD_DEBUGGING is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OXU210HP_HCD=m
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_ISP1760_HCD=m
+CONFIG_USB_ISP1362_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_SSB=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_WHCI_HCD=m
+CONFIG_USB_HWA_HCD=m
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+# CONFIG_USB_UAS is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7715_PARPORT=y
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_SAMBA is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+# CONFIG_USB_SERIAL_SSU100 is not set
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+# CONFIG_USB_LEGOTOWER is not set
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+# CONFIG_USB_TRANCEVIBRATOR is not set
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=m
+CONFIG_NOP_USB_XCEIV=m
+CONFIG_UWB=m
+CONFIG_UWB_HWA=m
+CONFIG_UWB_WHCI=m
+CONFIG_UWB_I1480U=m
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+CONFIG_MMC_TEST=m
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_SDHCI_PCI=m
+CONFIG_MMC_RICOH_MMC=y
+CONFIG_MMC_SDHCI_PLTFM=m
+CONFIG_MMC_WBSD=m
+CONFIG_MMC_TIFM_SD=m
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_SDRICOH_CS=m
+CONFIG_MMC_CB710=m
+CONFIG_MMC_VIA_SDMMC=m
+# CONFIG_MMC_USHC is not set
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_NET5501=m
+CONFIG_LEDS_ALIX2=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+CONFIG_LEDS_LP3944=m
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+CONFIG_LEDS_CLEVO_MAIL=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_REGULATOR=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_INTEL_SS4200=m
+CONFIG_LEDS_LT3593=m
+CONFIG_LEDS_DELL_NETBOOKS=m
+# CONFIG_LEDS_MC13783 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_NFC_DEVICES is not set
+CONFIG_ACCESSIBILITY=y
+# CONFIG_A11Y_BRAILLE_CONSOLE is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+# CONFIG_INFINIBAND_IPATH is not set
+# CONFIG_INFINIBAND_QIB is not set
+CONFIG_INFINIBAND_AMSO1100=m
+# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_INFINIBAND_CXGB4=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_INFINIBAND_NES=m
+# CONFIG_INFINIBAND_NES_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_TEST=m
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+# CONFIG_RTC_DRV_DS3232 is not set
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+# CONFIG_RTC_DRV_ISL12022 is not set
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=m
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8581=m
+CONFIG_RTC_DRV_RX8025=m
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_DS3234=m
+CONFIG_RTC_DRV_PCF2123=m
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=m
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_PCF50633=m
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_MC13XXX is not set
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_INTEL_MID_DMAC is not set
+CONFIG_INTEL_IOATDMA=m
+CONFIG_TIMB_DMA=m
+CONFIG_PCH_DMA=m
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+# CONFIG_ASYNC_TX_DMA is not set
+CONFIG_DMATEST=m
+CONFIG_DCA=m
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+CONFIG_CFAG12864B=m
+CONFIG_CFAG12864B_RATE=20
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+# CONFIG_UIO_PCI_GENERIC is not set
+CONFIG_UIO_NETX=m
+
+#
+# Xen driver support
+#
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DEV_EVTCHN=y
+CONFIG_XEN_BACKEND=y
+CONFIG_XENFS=y
+CONFIG_XEN_COMPAT_XENFS=y
+CONFIG_XEN_SYS_HYPERVISOR=y
+CONFIG_XEN_XENBUS_FRONTEND=y
+CONFIG_XEN_GNTDEV=m
+CONFIG_XEN_PLATFORM_PCI=m
+CONFIG_SWIOTLB_XEN=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_ET131X is not set
+# CONFIG_SLICOSS is not set
+# CONFIG_VIDEO_GO7007 is not set
+# CONFIG_VIDEO_CX25821 is not set
+# CONFIG_VIDEO_TM6000 is not set
+CONFIG_USB_DABUSB=m
+CONFIG_USB_SE401=m
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_W35UND is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+CONFIG_BRCM80211=m
+CONFIG_BRCM80211_PCI=y
+# CONFIG_BRCMFMAC is not set
+# CONFIG_RT2860 is not set
+# CONFIG_RT2870 is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_PANEL is not set
+# CONFIG_R8187SE is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTL8192E is not set
+# CONFIG_R8712U is not set
+# CONFIG_TRANZPORT is not set
+# CONFIG_POHMELFS is not set
+CONFIG_AUTOFS_FS=m
+# CONFIG_IDE_PHISON is not set
+# CONFIG_LINE6_USB is not set
+CONFIG_DRM_VMWGFX=m
+CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_NOUVEAU_BACKLIGHT=y
+CONFIG_DRM_NOUVEAU_DEBUG=y
+
+#
+# I2C encoder or helper chips
+#
+# CONFIG_DRM_I2C_CH7006 is not set
+CONFIG_DRM_I2C_SIL164=m
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+CONFIG_HYPERV=m
+CONFIG_HYPERV_STORAGE=m
+CONFIG_HYPERV_BLOCK=m
+CONFIG_HYPERV_NET=m
+CONFIG_HYPERV_UTILS=m
+# CONFIG_VME_BUS is not set
+# CONFIG_DX_SEP is not set
+# CONFIG_IIO is not set
+# CONFIG_ZRAM is not set
+# CONFIG_WLAGS49_H2 is not set
+# CONFIG_WLAGS49_H25 is not set
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_VIDEO_DT3155 is not set
+# CONFIG_CRYSTALHD is not set
+# CONFIG_CXT1E1 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_ST_BT is not set
+# CONFIG_FB_XGI is not set
+# CONFIG_LIRC_STAGING is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_EASYCAP is not set
+# CONFIG_SOLO6X10 is not set
+# CONFIG_ACPI_QUICKSTART is not set
+CONFIG_MACH_NO_WESTBRIDGE=y
+# CONFIG_SBE_2T3E3 is not set
+# CONFIG_ATH6K_LEGACY is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_ACER_WMI=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_DELL_LAPTOP=m
+CONFIG_DELL_WMI=m
+CONFIG_FUJITSU_LAPTOP=m
+# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
+CONFIG_HP_WMI=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+# CONFIG_SONYPI_COMPAT is not set
+# CONFIG_IDEAPAD_LAPTOP is not set
+CONFIG_THINKPAD_ACPI=m
+CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y
+# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_SENSORS_HDAPS=m
+CONFIG_INTEL_MENLOW=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_EEEPC_WMI=m
+CONFIG_ACPI_WMI=m
+CONFIG_MSI_WMI=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_TOPSTAR_LAPTOP is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_TOSHIBA_BT_RFKILL=m
+CONFIG_ACPI_CMPC=m
+# CONFIG_INTEL_IPS is not set
+# CONFIG_IBM_RTL is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+# CONFIG_EDD_OFF is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+CONFIG_DMIID=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=m
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_QUOTACTL_COMPAT=y
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_HISTOGRAM=y
+# CONFIG_FSCACHE_DEBUG is not set
+# CONFIG_FSCACHE_OBJECT_LIST is not set
+CONFIG_CACHEFILES=m
+# CONFIG_CACHEFILES_DEBUG is not set
+# CONFIG_CACHEFILES_HISTOGRAM is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=m
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_LOGFS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_LZO is not set
+CONFIG_SQUASHFS_XZ=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_EXOFS_FS=m
+# CONFIG_EXOFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+# CONFIG_NFS_FSCACHE is not set
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_DEPRECATED=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_XPRT_RDMA=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_CEPH_FS=m
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_DFS_UPCALL=y
+# CONFIG_CIFS_FSCACHE is not set
+# CONFIG_CIFS_ACL is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_BKL=y
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LKDTM is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_RING_BUFFER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_TEST_KSTRTOX=m
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_OPTIMIZE_INLINING is not set
+
+#
+# Security options
+#
+
+#
+# Grsecurity
+#
+CONFIG_GRKERNSEC=y
+# CONFIG_GRKERNSEC_LOW is not set
+# CONFIG_GRKERNSEC_MEDIUM is not set
+# CONFIG_GRKERNSEC_HIGH is not set
+CONFIG_GRKERNSEC_CUSTOM=y
+
+#
+# Address Space Protection
+#
+CONFIG_GRKERNSEC_KMEM=y
+# CONFIG_GRKERNSEC_IO is not set
+CONFIG_GRKERNSEC_PROC_MEMMAP=y
+# CONFIG_GRKERNSEC_BRUTE is not set
+# CONFIG_GRKERNSEC_MODHARDEN is not set
+# CONFIG_GRKERNSEC_HIDESYM is not set
+# CONFIG_GRKERNSEC_KERN_LOCKOUT is not set
+
+#
+# Role Based Access Control Options
+#
+# CONFIG_GRKERNSEC_NO_RBAC is not set
+CONFIG_GRKERNSEC_ACL_HIDEKERN=y
+CONFIG_GRKERNSEC_ACL_MAXTRIES=3
+CONFIG_GRKERNSEC_ACL_TIMEOUT=30
+
+#
+# Filesystem Protections
+#
+CONFIG_GRKERNSEC_PROC=y
+# CONFIG_GRKERNSEC_PROC_USER is not set
+CONFIG_GRKERNSEC_PROC_USERGROUP=y
+CONFIG_GRKERNSEC_PROC_GID=30
+CONFIG_GRKERNSEC_PROC_ADD=y
+CONFIG_GRKERNSEC_LINK=y
+CONFIG_GRKERNSEC_FIFO=y
+CONFIG_GRKERNSEC_SYSFS_RESTRICT=y
+# CONFIG_GRKERNSEC_ROFS is not set
+CONFIG_GRKERNSEC_CHROOT=y
+CONFIG_GRKERNSEC_CHROOT_MOUNT=y
+CONFIG_GRKERNSEC_CHROOT_DOUBLE=y
+CONFIG_GRKERNSEC_CHROOT_PIVOT=y
+CONFIG_GRKERNSEC_CHROOT_CHDIR=y
+CONFIG_GRKERNSEC_CHROOT_CHMOD=y
+CONFIG_GRKERNSEC_CHROOT_FCHDIR=y
+CONFIG_GRKERNSEC_CHROOT_MKNOD=y
+CONFIG_GRKERNSEC_CHROOT_SHMAT=y
+CONFIG_GRKERNSEC_CHROOT_UNIX=y
+CONFIG_GRKERNSEC_CHROOT_FINDTASK=y
+CONFIG_GRKERNSEC_CHROOT_NICE=y
+CONFIG_GRKERNSEC_CHROOT_SYSCTL=y
+CONFIG_GRKERNSEC_CHROOT_CAPS=y
+
+#
+# Kernel Auditing
+#
+# CONFIG_GRKERNSEC_AUDIT_GROUP is not set
+# CONFIG_GRKERNSEC_EXECLOG is not set
+CONFIG_GRKERNSEC_RESLOG=y
+# CONFIG_GRKERNSEC_CHROOT_EXECLOG is not set
+# CONFIG_GRKERNSEC_AUDIT_PTRACE is not set
+# CONFIG_GRKERNSEC_AUDIT_CHDIR is not set
+# CONFIG_GRKERNSEC_AUDIT_MOUNT is not set
+CONFIG_GRKERNSEC_SIGNAL=y
+CONFIG_GRKERNSEC_FORKFAIL=y
+CONFIG_GRKERNSEC_TIME=y
+CONFIG_GRKERNSEC_PROC_IPADDR=y
+# CONFIG_GRKERNSEC_RWXMAP_LOG is not set
+# CONFIG_GRKERNSEC_AUDIT_TEXTREL is not set
+
+#
+# Executable Protections
+#
+CONFIG_GRKERNSEC_EXECVE=y
+# CONFIG_GRKERNSEC_DMESG is not set
+CONFIG_GRKERNSEC_HARDEN_PTRACE=y
+# CONFIG_GRKERNSEC_TPE is not set
+
+#
+# Network Protections
+#
+CONFIG_GRKERNSEC_RANDNET=y
+# CONFIG_GRKERNSEC_BLACKHOLE is not set
+# CONFIG_GRKERNSEC_SOCKET is not set
+
+#
+# Sysctl support
+#
+CONFIG_GRKERNSEC_SYSCTL=y
+CONFIG_GRKERNSEC_SYSCTL_ON=y
+
+#
+# Logging Options
+#
+CONFIG_GRKERNSEC_FLOODTIME=10
+CONFIG_GRKERNSEC_FLOODBURST=4
+
+#
+# PaX
+#
+CONFIG_TASK_SIZE_MAX_SHIFT=47
+CONFIG_PAX=y
+
+#
+# PaX Control
+#
+CONFIG_PAX_SOFTMODE=y
+# CONFIG_PAX_EI_PAX is not set
+CONFIG_PAX_PT_PAX_FLAGS=y
+# CONFIG_PAX_NO_ACL_FLAGS is not set
+CONFIG_PAX_HAVE_ACL_FLAGS=y
+# CONFIG_PAX_HOOK_ACL_FLAGS is not set
+
+#
+# Non-executable pages
+#
+CONFIG_PAX_NOEXEC=y
+CONFIG_PAX_PAGEEXEC=y
+CONFIG_PAX_EMUTRAMP=y
+CONFIG_PAX_MPROTECT=y
+# CONFIG_PAX_MPROTECT_COMPAT is not set
+# CONFIG_PAX_ELFRELOCS is not set
+
+#
+# Address Space Layout Randomization
+#
+CONFIG_PAX_ASLR=y
+# CONFIG_PAX_RANDKSTACK is not set
+CONFIG_PAX_RANDUSTACK=y
+CONFIG_PAX_RANDMMAP=y
+
+#
+# Miscellaneous hardening features
+#
+# CONFIG_PAX_MEMORY_SANITIZE is not set
+# CONFIG_PAX_MEMORY_STACKLEAK is not set
+CONFIG_PAX_REFCOUNT=y
+# CONFIG_PAX_USERCOPY is not set
+CONFIG_KEYS=y
+CONFIG_TRUSTED_KEYS=m
+CONFIG_ENCRYPTED_KEYS=m
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_IMA is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y
+CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_FPU=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C_INTEL=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_AES_NI_INTEL=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SALSA20_X86_64=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_TWOFISH_X86_64=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_USER_API=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_APIC_ARCHITECTURE=y
+CONFIG_KVM_MMIO=y
+CONFIG_KVM_ASYNC_PF=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_KVM_AMD=m
+CONFIG_VHOST_NET=m
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_BTREE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_NLATTR=y
+CONFIG_AVERAGE=y
diff --git a/main/linux-grsec/net-gre-provide-multicast-mappings-for-ipv4-and-ipv6.patch b/main/linux-grsec/net-gre-provide-multicast-mappings-for-ipv4-and-ipv6.patch
new file mode 100644
index 0000000000..a9bff5dcfd
--- /dev/null
+++ b/main/linux-grsec/net-gre-provide-multicast-mappings-for-ipv4-and-ipv6.patch
@@ -0,0 +1,98 @@
+From: Timo Teräs <timo.teras@iki.fi>
+Date: Mon, 28 Mar 2011 22:40:53 +0000 (+0000)
+Subject: net: gre: provide multicast mappings for ipv4 and ipv6
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fdavem%2Fnet-2.6.git;a=commitdiff_plain;h=93ca3bb5df9bc8b2c60485e1cc6507c3d7c8e1fa
+
+net: gre: provide multicast mappings for ipv4 and ipv6
+
+My commit 6d55cb91a0020ac0 (gre: fix hard header destination
+address checking) broke multicast.
+
+The reason is that ip_gre used to get ipgre_header() calls with
+zero destination if we have NOARP or multicast destination. Instead
+the actual target was decided at ipgre_tunnel_xmit() time based on
+per-protocol dissection.
+
+Instead of allowing the "abuse" of ->header() calls with invalid
+destination, this creates multicast mappings for ip_gre. This also
+fixes "ip neigh show nud noarp" to display the proper multicast
+mappings used by the gre device.
+
+Reported-by: Doug Kehn <rdkehn@yahoo.com>
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+Acked-by: Doug Kehn <rdkehn@yahoo.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
+index 04977ee..fccc218 100644
+--- a/include/net/if_inet6.h
++++ b/include/net/if_inet6.h
+@@ -286,5 +286,21 @@ static inline void ipv6_ib_mc_map(const struct in6_addr *addr,
+ buf[9] = broadcast[9];
+ memcpy(buf + 10, addr->s6_addr + 6, 10);
+ }
++
++static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr,
++ const unsigned char *broadcast, char *buf)
++{
++ if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) {
++ memcpy(buf, broadcast, 4);
++ } else {
++ /* v4mapped? */
++ if ((addr->s6_addr32[0] | addr->s6_addr32[1] |
++ (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0)
++ return -EINVAL;
++ memcpy(buf, &addr->s6_addr32[3], 4);
++ }
++ return 0;
++}
++
+ #endif
+ #endif
+diff --git a/include/net/ip.h b/include/net/ip.h
+index a4f6311..7c41658 100644
+--- a/include/net/ip.h
++++ b/include/net/ip.h
+@@ -339,6 +339,14 @@ static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, ch
+ buf[16] = addr & 0x0f;
+ }
+
++static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
++{
++ if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0)
++ memcpy(buf, broadcast, 4);
++ else
++ memcpy(buf, &naddr, sizeof(naddr));
++}
++
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ #include <linux/ipv6.h>
+ #endif
+diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
+index 090d273..1b74d3b 100644
+--- a/net/ipv4/arp.c
++++ b/net/ipv4/arp.c
+@@ -215,6 +215,9 @@ int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
+ case ARPHRD_INFINIBAND:
+ ip_ib_mc_map(addr, dev->broadcast, haddr);
+ return 0;
++ case ARPHRD_IPGRE:
++ ip_ipgre_mc_map(addr, dev->broadcast, haddr);
++ return 0;
+ default:
+ if (dir) {
+ memcpy(haddr, dev->broadcast, dev->addr_len);
+diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
+index 0e49c9d..92f952d 100644
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -341,6 +341,8 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d
+ case ARPHRD_INFINIBAND:
+ ipv6_ib_mc_map(addr, dev->broadcast, buf);
+ return 0;
++ case ARPHRD_IPGRE:
++ return ipv6_ipgre_mc_map(addr, dev->broadcast, buf);
+ default:
+ if (dir) {
+ memcpy(buf, dev->broadcast, dev->addr_len);
diff --git a/main/linux-headers/APKBUILD b/main/linux-headers/APKBUILD
new file mode 100644
index 0000000000..536fb7827f
--- /dev/null
+++ b/main/linux-headers/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=linux-headers
+pkgver=2.6.38.2
+_kernver=2.6.38
+pkgrel=0
+pkgdesc="Linux system headers"
+url="http://kernel.org"
+arch="noarch"
+license='GPL-2'
+makedepends="perl"
+if [ "$ALPINE_LIBC" = "eglibc" ]; then
+ replaces="eglibc-dev"
+else
+ replaces="uclibc-dev"
+fi
+options="!strip !tracedeps"
+source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
+ "
+
+prepare() {
+ cd "$srcdir"/linux-$_kernver
+ if [ "$_kernver" != "$pkgver" ]; then
+ bunzip2 -c < "$srcdir"/patch-$pkgver.bz2 | patch -p1 || return 1
+ fi
+}
+
+build() {
+ return 0
+}
+
+
+package() {
+ cd "$srcdir"/linux-$_kernver
+ mkdir -p "$pkgdir/usr"
+ make headers_install INSTALL_HDR_PATH="$pkgdir/usr" || return 1
+
+ find "$pkgdir/usr" \( -name .install -o -name ..install.cmd \) -exec \
+ rm -f {} \;
+
+ # provided by libdrm
+ rm -rf "$pkgdir"/usr/include/drm
+}
+
+md5sums="7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2
+599badab31c4920d4122133208c810d7 patch-2.6.38.2.bz2"
diff --git a/main/linux-scst/0004-arp-flush-arp-cache-on-device-change.patch b/main/linux-scst/0004-arp-flush-arp-cache-on-device-change.patch
new file mode 100644
index 0000000000..85161ea3a3
--- /dev/null
+++ b/main/linux-scst/0004-arp-flush-arp-cache-on-device-change.patch
@@ -0,0 +1,29 @@
+From 8a0e3ea4924059a7268446177d6869e3399adbb2 Mon Sep 17 00:00:00 2001
+From: Timo Teras <timo.teras@iki.fi>
+Date: Mon, 12 Apr 2010 13:46:45 +0000
+Subject: [PATCH 04/18] arp: flush arp cache on device change
+
+If IFF_NOARP is changed, we must flush the arp cache.
+
+Signed-off-by: Timo Teras <timo.teras@iki.fi>
+---
+ net/ipv4/arp.c | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
+index 4e80f33..580bfc3 100644
+--- a/net/ipv4/arp.c
++++ b/net/ipv4/arp.c
+@@ -1200,6 +1200,9 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
+ neigh_changeaddr(&arp_tbl, dev);
+ rt_cache_flush(dev_net(dev), 0);
+ break;
++ case NETDEV_CHANGE:
++ neigh_changeaddr(&arp_tbl, dev);
++ break;
+ default:
+ break;
+ }
+--
+1.7.0.2
+
diff --git a/main/linux-scst/APKBUILD b/main/linux-scst/APKBUILD
new file mode 100644
index 0000000000..6caf4f285e
--- /dev/null
+++ b/main/linux-scst/APKBUILD
@@ -0,0 +1,148 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+_flavor=scst
+pkgname=linux-${_flavor}
+pkgver=2.6.36.3
+_kernver=2.6.36
+pkgrel=0
+pkgdesc="Linux kernel optimised for scst"
+url="http://scst.sourceforge.net"
+depends="mkinitfs linux-firmware"
+makedepends="perl installkernel bash"
+options="!strip"
+_config=${config:-kernelconfig.${CARCH}}
+install=
+source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
+ kernelconfig.x86_64
+ scst-2.0.0.1-2.6.36.patch
+ unionfs-2.5.7_for_$_kernver.diff
+ 0004-arp-flush-arp-cache-on-device-change.patch
+ "
+subpackages="$pkgname-dev linux-firmware:firmware"
+arch="x86_64"
+license="GPL-2"
+
+_abi_release=${pkgver}-${_flavor}
+
+prepare() {
+ local _patch_failed=
+ cd "$srcdir"/linux-$_kernver
+ if [ "$_kernver" != "$pkgver" ]; then
+ bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 -N || return 1
+ fi
+
+ # first apply patches in specified order
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i..."
+ if ! patch -s -p1 -N -i "$srcdir"/$i; then
+ echo $i >>failed
+ _patch_failed=1
+ fi
+ ;;
+ esac
+ done
+
+ if ! [ -z "$_patch_failed" ]; then
+ error "The following patches failed:"
+ cat failed
+ return 1
+ fi
+
+ echo "-scst" > "$srcdir"/linux-$_kernver/localversion-scst
+
+ mkdir -p "$srcdir"/build
+ cp "$srcdir"/$_config "$srcdir"/build/.config || return 1
+ make -C "$srcdir"/linux-$_kernver O="$srcdir"/build HOSTCC="${CC:-gcc}" \
+ silentoldconfig
+}
+
+# this is so we can do: 'abuild menuconfig' to reconfigure kernel
+menuconfig() {
+ cd "$srcdir"/build || return 1
+ make menuconfig
+ cp .config "$startdir"/$_config
+}
+
+build() {
+ cd "$srcdir"/build
+ make CC="${CC:-gcc}" \
+ KBUILD_BUILD_VERSION="$((pkgrel + 1 ))-Alpine" \
+ || return 1
+}
+
+package() {
+ cd "$srcdir"/build
+ mkdir -p "$pkgdir"/boot "$pkgdir"/lib/modules
+ make -j1 modules_install firmware_install install \
+ INSTALL_MOD_PATH="$pkgdir" \
+ INSTALL_PATH="$pkgdir"/boot \
+ || return 1
+
+ rm -f "$pkgdir"/lib/modules/${_abi_release}/build \
+ "$pkgdir"/lib/modules/${_abi_release}/source
+ install -D include/config/kernel.release \
+ "$pkgdir"/usr/share/kernel/$_flavor/kernel.release
+}
+
+dev() {
+ # copy the only the parts that we really need for build 3rd party
+ # kernel modules and install those as /usr/src/linux-headers,
+ # simlar to what ubuntu does
+ #
+ # this way you dont need to install the 300-400 kernel sources to
+ # build a tiny kernel module
+ #
+ pkgdesc="Headers and script for third party modules for grsec kernel"
+ local dir="$subpkgdir"/usr/src/linux-headers-${_abi_release}
+
+ # first we import config, run prepare to set up for building
+ # external modules, and create the scripts
+ mkdir -p "$dir"
+ cp "$srcdir"/$_config "$dir"/.config
+ make -j1 -C "$srcdir"/linux-$_kernver O="$dir" HOSTCC="${CC:-gcc}" \
+ silentoldconfig prepare scripts
+
+ # remove the stuff that poits to real sources. we want 3rd party
+ # modules to believe this is the soruces
+ rm "$dir"/Makefile "$dir"/source
+
+ # copy the needed stuff from real sources
+ #
+ # this is taken from ubuntu kernel build script
+ # http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-jaunty.git;a=blob;f=debian/rules.d/3-binary-indep.mk;hb=HEAD
+ cd "$srcdir"/linux-$_kernver
+ find . -path './include/*' -prune -o -path './scripts/*' -prune \
+ -o -type f \( -name 'Makefile*' -o -name 'Kconfig*' \
+ -o -name 'Kbuild*' -o -name '*.sh' -o -name '*.pl' \
+ -o -name '*.lds' \) | cpio -pdm "$dir"
+ cp -a drivers/media/dvb/dvb-core/*.h "$dir"/drivers/media/dvb/dvb-core
+ cp -a drivers/media/video/*.h "$dir"/drivers/media/video
+ cp -a drivers/media/dvb/frontends/*.h "$dir"/drivers/media/dvb/frontends
+ cp -a scripts include "$dir"
+ find $(find arch -name include -type d -print) -type f \
+ | cpio -pdm "$dir"
+
+ install -Dm644 "$srcdir"/build/Module.symvers \
+ "$dir"/Module.symvers
+
+ mkdir -p "$subpkgdir"/lib/modules/${_abi_release}
+ ln -sf /usr/src/linux-headers-${_abi_release} \
+ "$subpkgdir"/lib/modules/${_abi_release}/build
+}
+
+firmware() {
+ pkgdesc="Firmware for linux kernel"
+ replaces="linux-grsec linux-vserver"
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/firmware "$subpkgdir"/lib/
+}
+
+md5sums="61f3739a73afb6914cb007f37fb09b62 linux-2.6.36.tar.bz2
+33f51375d4baa343502b39acf94d5a6c patch-2.6.36.3.bz2
+68d4cbd30411aca485293117bd98ec38 kernelconfig.x86_64
+e62cd51e9452633821e4457564a094f3 scst-2.0.0.1-2.6.36.patch
+fec281a4e03fed560ce309ad8fc5a592 unionfs-2.5.7_for_2.6.36.diff
+776adeeb5272093574f8836c5037dd7d 0004-arp-flush-arp-cache-on-device-change.patch"
diff --git a/main/linux-scst/kernelconfig.x86_64 b/main/linux-scst/kernelconfig.x86_64
new file mode 100644
index 0000000000..d98eb305a1
--- /dev/null
+++ b/main/linux-scst/kernelconfig.x86_64
@@ -0,0 +1,4729 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.36.2
+# Thu Dec 23 12:32:35 2010
+#
+CONFIG_64BIT=y
+# CONFIG_X86_32 is not set
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_HAVE_EARLY_RES=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_X86_64_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
+# CONFIG_KTIME_SCALAR is not set
+CONFIG_ARCH_CPU_PROBE_RELEASE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+CONFIG_RCU_FAST_NO_HZ=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=m
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_PADATA=y
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+# CONFIG_SPARSE_IRQ is not set
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_VSMP is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_PARAVIRT_GUEST=y
+# CONFIG_XEN is not set
+CONFIG_KVM_CLOCK=y
+CONFIG_KVM_GUEST=y
+CONFIG_PARAVIRT=y
+# CONFIG_PARAVIRT_SPINLOCKS is not set
+CONFIG_PARAVIRT_CLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_MEMTEST is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_CPU=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_XADD=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+CONFIG_GART_IOMMU=y
+CONFIG_CALGARY_IOMMU=y
+CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y
+CONFIG_AMD_IOMMU=y
+# CONFIG_AMD_IOMMU_STATS is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+CONFIG_IOMMU_API=y
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+# CONFIG_X86_MCE is not set
+CONFIG_I8K=m
+CONFIG_MICROCODE=m
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_DIRECT_GBPAGES=y
+# CONFIG_NUMA is not set
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW_64K=y
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+# CONFIG_EFI is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_300=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=300
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_NVS=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM_OPS=y
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+# CONFIG_ACPI_POWER_METER is not set
+CONFIG_ACPI_SYSFS_POWER=y
+CONFIG_ACPI_EC_DEBUGFS=m
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=m
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+CONFIG_ACPI_HED=m
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=m
+CONFIG_ACPI_APEI_EINJ=m
+CONFIG_ACPI_APEI_ERST_DEBUG=m
+# CONFIG_SFI is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_PCC_CPUFREQ=m
+CONFIG_X86_ACPI_CPUFREQ=m
+CONFIG_X86_POWERNOW_K8=m
+CONFIG_X86_SPEEDSTEP_CENTRINO=m
+CONFIG_X86_P4_CLOCKMOD=m
+
+#
+# shared options
+#
+CONFIG_X86_SPEEDSTEP_LIB=m
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_INTEL_IDLE is not set
+
+#
+# Memory power savings
+#
+CONFIG_I7300_IDLE_IOAT_CHANNEL=y
+CONFIG_I7300_IDLE=m
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_CNB20LE_QUIRK=y
+# CONFIG_DMAR is not set
+# CONFIG_INTR_REMAP is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_PCIEAER is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_STUB=m
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+CONFIG_PCI_IOAPIC=y
+CONFIG_ISA_DMA_API=y
+CONFIG_K8_NB=y
+CONFIG_PCCARD=m
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+CONFIG_HOTPLUG_PCI=m
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_SHPC=m
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+# CONFIG_IA32_EMULATION is not set
+# CONFIG_COMPAT_FOR_U64_ALIGNMENT is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+# CONFIG_IP_PIMSM_V1 is not set
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETLABEL=y
+CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+CONFIG_RDS=m
+# CONFIG_RDS_RDMA is not set
+# CONFIG_RDS_TCP is not set
+# CONFIG_RDS_DEBUG is not set
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+CONFIG_ECONET=m
+CONFIG_ECONET_AUNUDP=y
+CONFIG_ECONET_NATIVE=y
+CONFIG_WAN_ROUTER=m
+CONFIG_PHONET=m
+CONFIG_IEEE802154=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+CONFIG_RPS=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_DEV=m
+# CONFIG_CAN_CALC_BITTIMING is not set
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_JANZ_ICAN3=m
+CONFIG_CAN_SJA1000=m
+CONFIG_CAN_SJA1000_PLATFORM=m
+CONFIG_CAN_EMS_PCI=m
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PLX_PCI=m
+
+#
+# CAN USB interfaces
+#
+# CONFIG_CAN_EMS_USB is not set
+CONFIG_CAN_ESD_USB2=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIUART_ATH3K is not set
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_RXKAD=m
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+# CONFIG_RFKILL_INPUT is not set
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NET_9P_RDMA=m
+# CONFIG_NET_9P_DEBUG is not set
+CONFIG_CAIF=m
+# CONFIG_CAIF_DEBUG is not set
+CONFIG_CAIF_NETDEV=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=m
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_AR7_PARTS=m
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_HAVE_MTD_OTP=y
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+CONFIG_SSFDC=m
+CONFIG_SM_FTL=m
+CONFIG_MTD_OOPS=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_AMD76XROM=m
+CONFIG_MTD_ICHXROM=m
+CONFIG_MTD_ESB2ROM=m
+CONFIG_MTD_CK804XROM=m
+CONFIG_MTD_SCB2_FLASH=m
+CONFIG_MTD_NETtel=m
+CONFIG_MTD_L440GX=m
+CONFIG_MTD_PCI=m
+CONFIG_MTD_PCMCIA=m
+# CONFIG_MTD_PCMCIA_ANONYMOUS is not set
+# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_INTEL_VR_NOR=m
+CONFIG_MTD_PLATRAM=m
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+CONFIG_MTD_PMC551_BUGFIX=y
+# CONFIG_MTD_PMC551_DEBUG is not set
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DATAFLASH_OTP is not set
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_MTD_SST25L is not set
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+# CONFIG_MTD_DOCPROBE_HIGH is not set
+# CONFIG_MTD_DOCPROBE_55AA is not set
+CONFIG_MTD_NAND_ECC=m
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_SM_COMMON=m
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_DENALI=m
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_RICOH=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CAFE=m
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_ALAUDA=m
+CONFIG_MTD_ONENAND=m
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OTP=y
+CONFIG_MTD_ONENAND_2X_PROGRAM=y
+CONFIG_MTD_ONENAND_SIM=m
+
+#
+# LPDDR flash memory drivers
+#
+CONFIG_MTD_LPDDR=m
+CONFIG_MTD_QINFO_PROBE=m
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_AX88796=m
+# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=m
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_AD525X_DPOT_SPI=m
+CONFIG_IBM_ASM=m
+CONFIG_PHANTOM=m
+CONFIG_SGI_IOC4=m
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
+CONFIG_ICS932S401=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_CS5535_MFGPT=m
+CONFIG_CS5535_MFGPT_DEFAULT_IRQ=7
+CONFIG_CS5535_CLOCK_EVENT_SRC=m
+CONFIG_HP_ILO=m
+CONFIG_ISL29003=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1780=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_TI_DAC7512=m
+CONFIG_VMWARE_BALLOON=m
+CONFIG_BMP085=m
+CONFIG_C2PORT=m
+CONFIG_C2PORT_DURAMAR_2150=m
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_AT25=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93CX6=m
+CONFIG_CB710_CORE=m
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
+CONFIG_IWMC3200TOP=m
+# CONFIG_IWMC3200TOP_DEBUG is not set
+# CONFIG_IWMC3200TOP_DEBUGFS is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_FC_TGT_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_HOST_SMP=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+# CONFIG_BE2ISCSI is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_HPSA=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_3W_SAS=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
+CONFIG_SCSI_MVSAS=m
+CONFIG_SCSI_MVSAS_DEBUG=y
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_ARCMSR=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_MPT2SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
+# CONFIG_SCSI_MPT2SAS_LOGGING is not set
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_BUSLOGIC=m
+CONFIG_VMWARE_PVSCSI=m
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+CONFIG_FCOE=m
+CONFIG_FCOE_FNIC=m
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_EATA=m
+# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set
+# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+CONFIG_SCSI_IPR_TRACE=y
+# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_PMCRAID is not set
+CONFIG_SCSI_PM8001=m
+CONFIG_SCSI_SRP=m
+# CONFIG_SCSI_BFA_FC is not set
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_SCSI_OSD_DPRINT_SENSE=1
+# CONFIG_SCSI_OSD_DEBUG is not set
+
+#
+# SCSI target (SCST) support
+#
+CONFIG_SCST=m
+CONFIG_SCST_DISK=m
+CONFIG_SCST_TAPE=m
+CONFIG_SCST_CDROM=m
+CONFIG_SCST_MODISK=m
+CONFIG_SCST_CHANGER=m
+CONFIG_SCST_PROCESSOR=m
+CONFIG_SCST_RAID=m
+CONFIG_SCST_VDISK=m
+CONFIG_SCST_USER=m
+# CONFIG_SCST_STRICT_SERIALIZING is not set
+# CONFIG_SCST_STRICT_SECURITY is not set
+# CONFIG_SCST_TEST_IO_IN_SIRQ is not set
+# CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING is not set
+# CONFIG_SCST_USE_EXPECTED_VALUES is not set
+# CONFIG_SCST_EXTRACHECKS is not set
+CONFIG_SCST_TRACING=y
+# CONFIG_SCST_DEBUG is not set
+# CONFIG_SCST_DEBUG_OOM is not set
+# CONFIG_SCST_DEBUG_RETRY is not set
+# CONFIG_SCST_DEBUG_SN is not set
+# CONFIG_SCST_MEASURE_LATENCY is not set
+CONFIG_SCST_ISCSI=m
+# CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES is not set
+CONFIG_SCST_SRPT=m
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_SATA_INIC162X=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SX4=m
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+CONFIG_ATA_PIIX=m
+CONFIG_SATA_MV=m
+CONFIG_SATA_NV=m
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+
+#
+# PATA SFF controllers with BMDMA
+#
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+CONFIG_PATA_ATP867X=m
+CONFIG_PATA_CMD64X=m
+CONFIG_PATA_CS5520=m
+CONFIG_PATA_CS5530=m
+CONFIG_PATA_CYPRESS=m
+CONFIG_PATA_EFAR=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+CONFIG_PATA_HPT3X2N=m
+CONFIG_PATA_HPT3X3=m
+CONFIG_PATA_HPT3X3_DMA=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87415=m
+CONFIG_PATA_OLDPIIX=m
+CONFIG_PATA_OPTIDMA=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_PDC_OLD=m
+CONFIG_PATA_RADISYS=m
+CONFIG_PATA_RDC=m
+CONFIG_PATA_SC1200=m
+CONFIG_PATA_SCH=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_TOSHIBA=m
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+
+#
+# PIO-only SFF controllers
+#
+CONFIG_PATA_CMD640_PCI=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_OPTI=m
+CONFIG_PATA_PCMCIA=m
+CONFIG_PATA_PLATFORM=m
+CONFIG_PATA_RZ1000=m
+
+#
+# Generic fallback / legacy drivers
+#
+CONFIG_PATA_ACPI=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_LEGACY=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_AUTODETECT is not set
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MULTICORE_RAID456 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# The newer stack is recommended.
+#
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_OHCI_DEBUG=y
+CONFIG_FIREWIRE_SBP2=m
+CONFIG_FIREWIRE_NET=m
+CONFIG_IEEE1394=m
+CONFIG_IEEE1394_OHCI1394=m
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_DV1394=m
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_FIREWIRE_NOSY=m
+CONFIG_I2O=m
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+CONFIG_ARCNET=m
+CONFIG_ARCNET_1201=m
+CONFIG_ARCNET_1051=m
+CONFIG_ARCNET_RAW=m
+CONFIG_ARCNET_CAP=m
+CONFIG_ARCNET_COM90xx=m
+CONFIG_ARCNET_COM90xxIO=m
+CONFIG_ARCNET_RIM_I=m
+CONFIG_ARCNET_COM20020=m
+CONFIG_ARCNET_COM20020_PCI=m
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MICREL_PHY=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_MDIO_GPIO=m
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ETHOC=m
+CONFIG_DNET=m
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_DE2104X_DSL=0
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_HP100=m
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_KSZ884X_PCI=m
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SMSC9420=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_KS8842=m
+CONFIG_KS8851=m
+CONFIG_KS8851_MLL=m
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_ATL2=m
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_IP1000=m
+CONFIG_IGB=m
+CONFIG_IGB_DCA=y
+CONFIG_IGBVF=m
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_CNIC=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_ATL1C=m
+CONFIG_JME=m
+CONFIG_NETDEV_10000=y
+CONFIG_MDIO=m
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3_DEPENDS=y
+CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4_DEPENDS=y
+CONFIG_CHELSIO_T4=m
+CONFIG_CHELSIO_T4VF_DEPENDS=y
+CONFIG_CHELSIO_T4VF=m
+CONFIG_ENIC=m
+CONFIG_IXGBE=m
+CONFIG_IXGBE_DCA=y
+# CONFIG_IXGBEVF is not set
+CONFIG_IXGB=m
+CONFIG_S2IO=m
+CONFIG_VXGE=m
+# CONFIG_VXGE_DEBUG_TRACE_ALL is not set
+CONFIG_MYRI10GE=m
+CONFIG_MYRI10GE_DCA=y
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_QLCNIC=m
+CONFIG_QLGE=m
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_BE2NET=m
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AIRO=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_AT76C50X_USB=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+CONFIG_ADM8211=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_MWL8K=m
+CONFIG_ATH_COMMON=m
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K=m
+# CONFIG_ATH9K_DEBUGFS is not set
+CONFIG_ATH9K_HTC=m
+# CONFIG_ATH9K_HTC_DEBUGFS is not set
+CONFIG_AR9170_USB=m
+CONFIG_AR9170_LEDS=y
+CONFIG_B43=m
+CONFIG_B43_PCI_AUTOSELECT=y
+CONFIG_B43_PCICORE_AUTOSELECT=y
+CONFIG_B43_PCMCIA=y
+CONFIG_B43_SDIO=y
+CONFIG_B43_PIO=y
+CONFIG_B43_PHY_LP=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_PCI_AUTOSELECT=y
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_HWRNG=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
+CONFIG_IWLWIFI=m
+# CONFIG_IWLWIFI_DEBUG is not set
+CONFIG_IWLAGN=m
+CONFIG_IWL4965=y
+CONFIG_IWL5000=y
+CONFIG_IWL3945=m
+CONFIG_IWM=m
+# CONFIG_IWM_DEBUG is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_CS=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_LIBERTAS_MESH=y
+CONFIG_HERMES=m
+# CONFIG_HERMES_PRISM is not set
+CONFIG_HERMES_CACHE_FW_ON_INIT=y
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ORINOCO_USB=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_P54_PCI=m
+CONFIG_P54_SPI=m
+CONFIG_P54_LEDS=y
+CONFIG_RT2X00=m
+CONFIG_RT2400PCI=m
+CONFIG_RT2500PCI=m
+CONFIG_RT61PCI=m
+CONFIG_RT2800PCI_PCI=y
+CONFIG_RT2800PCI=m
+CONFIG_RT2800PCI_RT30XX=y
+# CONFIG_RT2800PCI_RT35XX is not set
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT30XX=y
+# CONFIG_RT2800USB_RT35XX is not set
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RT2800_LIB=m
+CONFIG_RT2X00_LIB_PCI=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_HT=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_WL12XX=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SPI=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL1271=m
+CONFIG_WL1271_SPI=m
+CONFIG_WL1271_SDIO=m
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+CONFIG_WIMAX_I2400M=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_WIMAX_I2400M_SDIO=m
+CONFIG_WIMAX_IWMC3200_SDIO=y
+CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_CDC_PHONET=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_ARCNET_COM20020_CS=m
+CONFIG_WAN=y
+CONFIG_LANMEDIA=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=m
+CONFIG_HDLC_RAW_ETH=m
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_X25=m
+CONFIG_PCI200SYN=m
+CONFIG_WANXL=m
+# CONFIG_WANXL_BUILD_FIRMWARE is not set
+CONFIG_PC300TOO=m
+CONFIG_FARSYNC=m
+CONFIG_DSCC4=m
+CONFIG_DSCC4_PCISYNC=y
+CONFIG_DSCC4_PCI_RST=y
+CONFIG_DLCI=m
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=m
+CONFIG_CYCLADES_SYNC=m
+CONFIG_CYCLOMX_X25=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+CONFIG_SBNI=m
+CONFIG_SBNI_MULTILINE=y
+CONFIG_ATM_DRIVERS=y
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_USE_TASKLET=y
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_ATM_SOLOS=m
+CONFIG_IEEE802154_DRIVERS=m
+CONFIG_IEEE802154_FAKEHARD=m
+
+#
+# CAIF transport drivers
+#
+CONFIG_CAIF_TTY=m
+CONFIG_CAIF_SPI_SLAVE=m
+# CONFIG_CAIF_SPI_SYNC is not set
+CONFIG_FDDI=y
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_SKFP=m
+CONFIG_HIPPI=y
+CONFIG_ROADRUNNER=m
+# CONFIG_ROADRUNNER_LARGE_RINGS is not set
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_PPPOL2TP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+CONFIG_VMXNET3=m
+CONFIG_ISDN=y
+# CONFIG_ISDN_I4L is not set
+CONFIG_ISDN_CAPI=m
+# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set
+# CONFIG_CAPI_TRACE is not set
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_CAPI=y
+# CONFIG_GIGASET_DUMMYLL is not set
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+CONFIG_GIGASET_M101=m
+# CONFIG_GIGASET_DEBUG is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+CONFIG_MISDN=m
+CONFIG_MISDN_DSP=m
+CONFIG_MISDN_L1OIP=m
+
+#
+# mISDN hardware drivers
+#
+CONFIG_MISDN_HFCPCI=m
+CONFIG_MISDN_HFCMULTI=m
+CONFIG_MISDN_HFCUSB=m
+CONFIG_MISDN_AVMFRITZ=m
+# CONFIG_MISDN_SPEEDFAX is not set
+# CONFIG_MISDN_INFINEON is not set
+# CONFIG_MISDN_W6692 is not set
+# CONFIG_MISDN_NETJET is not set
+CONFIG_MISDN_IPAC=m
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_POLLDEV=m
+CONFIG_INPUT_SPARSEKMAP=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT2160 is not set
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_TCA6416=m
+CONFIG_KEYBOARD_MATRIX=m
+CONFIG_KEYBOARD_LM8323=m
+# CONFIG_KEYBOARD_MAX7359 is not set
+CONFIG_KEYBOARD_MCS=m
+CONFIG_KEYBOARD_NEWTON=m
+# CONFIG_KEYBOARD_OPENCORES is not set
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_GPIO=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_AD7877=m
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_AD7879_SPI=m
+CONFIG_TOUCHSCREEN_CY8CTMG110=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_QT602240=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_UCB1400=m
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
+CONFIG_TOUCHSCREEN_USB_NEXIO=y
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_AD714X_I2C=m
+CONFIG_INPUT_AD714X_SPI=m
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_APANEL=m
+CONFIG_INPUT_ATLAS_BTNS=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_WINBOND_CIR=m
+CONFIG_INPUT_PCF50633_PMU=m
+CONFIG_INPUT_PCF8574=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_ADXL34X_I2C=m
+CONFIG_INPUT_ADXL34X_SPI=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_ALTERA_PS2=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_COMPUTONE=m
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+CONFIG_ISI=m
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_N_GSM is not set
+CONFIG_RISCOM8=m
+CONFIG_SPECIALIX=m
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MAX3100=m
+CONFIG_SERIAL_MAX3107=m
+CONFIG_SERIAL_MRST_MAX3110=m
+CONFIG_SERIAL_MFD_HSU=m
+CONFIG_SERIAL_UARTLITE=m
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_SERIAL_TIMBERDALE=m
+CONFIG_SERIAL_ALTERA_JTAGUART=m
+CONFIG_SERIAL_ALTERA_UART=m
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_HVC_DRIVER=y
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=m
+CONFIG_R3964=m
+CONFIG_APPLICOM=m
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+CONFIG_MWAVE=m
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+CONFIG_TELCLOCK=m
+CONFIG_DEVPORT=y
+CONFIG_RAMOOPS=m
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_MUX=m
+
+#
+# Multiplexer I2C Chip support
+#
+CONFIG_I2C_MUX_PCA954x=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_SMBUS=m
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+
+#
+# ACPI drivers
+#
+CONFIG_I2C_SCMI=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_XILINX=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+CONFIG_SPI_BUTTERFLY=m
+CONFIG_SPI_GPIO=m
+CONFIG_SPI_LM70_LLP=m
+# CONFIG_SPI_XILINX is not set
+CONFIG_SPI_DESIGNWARE=m
+CONFIG_SPI_DW_PCI=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+CONFIG_GPIO_MAX730X=m
+
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_IT8761E=m
+CONFIG_GPIO_SCH=m
+
+#
+# I2C GPIO expanders:
+#
+CONFIG_GPIO_MAX7300=m
+CONFIG_GPIO_MAX732X=m
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_ADP5588=m
+
+#
+# PCI GPIO expanders:
+#
+CONFIG_GPIO_CS5535=m
+# CONFIG_GPIO_LANGWELL is not set
+CONFIG_GPIO_TIMBERDALE=y
+CONFIG_GPIO_RDC321X=m
+
+#
+# SPI GPIO expanders:
+#
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MCP23S08=m
+# CONFIG_GPIO_MC33880 is not set
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_GPIO_UCB1400 is not set
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_GPIO_JANZ_TTL=m
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_GPIO=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PDA_POWER=m
+CONFIG_TEST_POWER=m
+CONFIG_BATTERY_DS2760=m
+CONFIG_BATTERY_DS2782=m
+CONFIG_BATTERY_BQ27x00=m
+CONFIG_BATTERY_MAX17040=m
+CONFIG_CHARGER_PCF50633=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7411=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7475=m
+CONFIG_SENSORS_ASC7621=m
+CONFIG_SENSORS_K8TEMP=m
+CONFIG_SENSORS_K10TEMP=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_G760A=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_PKGTEMP=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_JC42=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LTC4215=m
+CONFIG_SENSORS_LTC4245=m
+CONFIG_SENSORS_LM95241=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMM665=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
+CONFIG_SENSORS_EMC2103=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_ADS7871=m
+CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=m
+CONFIG_SENSORS_TMP401=m
+CONFIG_SENSORS_TMP421=m
+CONFIG_SENSORS_VIA_CPUTEMP=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+CONFIG_SENSORS_LIS3_I2C=m
+CONFIG_SENSORS_APPLESMC=m
+
+#
+# ACPI drivers
+#
+CONFIG_SENSORS_ATK0110=m
+CONFIG_SENSORS_LIS3LV02D=m
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_F71808E_WDT=m
+CONFIG_GEODE_WDT=m
+CONFIG_SC520_WDT=m
+# CONFIG_SBC_FITPC2_WATCHDOG is not set
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_WAFER_WDT=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_ITCO_WDT=m
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_IT8712F_WDT=m
+CONFIG_IT87_WDT=m
+# CONFIG_HP_WATCHDOG is not set
+CONFIG_SC1200_WDT=m
+CONFIG_PC87413_WDT=m
+CONFIG_60XX_WDT=m
+CONFIG_SBC8360_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_SMSC_SCH311X_WDT=m
+CONFIG_SMSC37B787_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83697HF_WDT=m
+CONFIG_W83697UG_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+CONFIG_SSB_SDIOHOST=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_MFD_SUPPORT=y
+CONFIG_MFD_CORE=y
+CONFIG_MFD_SM501=m
+# CONFIG_MFD_SM501_GPIO is not set
+CONFIG_HTC_PASIC3=m
+CONFIG_UCB1400_CORE=m
+CONFIG_TPS65010=m
+CONFIG_TPS6507X=m
+# CONFIG_MFD_TMIO is not set
+CONFIG_MFD_WM8400=m
+CONFIG_MFD_PCF50633=m
+# CONFIG_MFD_MC13783 is not set
+CONFIG_PCF50633_ADC=m
+CONFIG_PCF50633_GPIO=m
+CONFIG_ABX500_CORE=y
+# CONFIG_EZX_PCAP is not set
+CONFIG_AB8500_CORE=y
+CONFIG_MFD_TIMBERDALE=m
+CONFIG_LPC_SCH=m
+CONFIG_MFD_RDC321X=m
+CONFIG_MFD_JANZ_CMODIO=m
+CONFIG_MFD_TPS6586X=m
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_REGULATOR_BQ24022=m
+CONFIG_REGULATOR_MAX1586=m
+CONFIG_REGULATOR_MAX8649=m
+CONFIG_REGULATOR_MAX8660=m
+CONFIG_REGULATOR_WM8400=m
+CONFIG_REGULATOR_PCF50633=m
+CONFIG_REGULATOR_LP3971=m
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_ISL6271A=m
+CONFIG_REGULATOR_AD5398=m
+# CONFIG_REGULATOR_AB8500 is not set
+CONFIG_REGULATOR_TPS6586X=m
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_IR_CORE=m
+CONFIG_VIDEO_IR=m
+CONFIG_LIRC=m
+CONFIG_RC_MAP=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_LIRC_CODEC=m
+CONFIG_IR_IMON=m
+CONFIG_IR_MCEUSB=m
+CONFIG_IR_ENE=m
+CONFIG_IR_STREAMZAP=m
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_V4L2_MEM2MEM_DEV=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TDA9875=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+
+#
+# RDS decoders
+#
+CONFIG_VIDEO_SAA6588=m
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_ADV7180 is not set
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_BT866=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_MT9V011=m
+CONFIG_VIDEO_TCM825X=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_SAA7191=m
+CONFIG_VIDEO_TVP514X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_TVP7002=m
+CONFIG_VIDEO_VPX3220=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_THS7303=m
+CONFIG_VIDEO_ADV7343=m
+CONFIG_VIDEO_AK881X=m
+
+#
+# Video improvement chips
+#
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_ZR36060=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_MPEG=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CX18_ALSA=m
+CONFIG_VIDEO_SAA7164=m
+CONFIG_VIDEO_CAFE_CCIC=m
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9T031=m
+CONFIG_SOC_CAMERA_MT9T112=m
+CONFIG_SOC_CAMERA_MT9V022=m
+CONFIG_SOC_CAMERA_RJ54N1=m
+CONFIG_SOC_CAMERA_TW9910=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_SOC_CAMERA_OV772X=m
+CONFIG_SOC_CAMERA_OV9640=m
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SPCA1528=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_USB_ET61X251=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MEM2MEM_TESTDEV=m
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_I2C_SI4713 is not set
+# CONFIG_RADIO_SI4713 is not set
+CONFIG_USB_DSBR=m
+# CONFIG_RADIO_SI470X is not set
+CONFIG_USB_MR800=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_TIMBERDALE=m
+CONFIG_DVB_MAX_ADAPTERS=8
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_CE6230=m
+# CONFIG_DVB_USB_FRIIO is not set
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_AZ6027=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_SMS_SIANO_MDTV=m
+
+#
+# Siano module components
+#
+CONFIG_SMS_USB_DRV=m
+CONFIG_SMS_SDIO_DRV=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported SDMC DM1105 Adapters
+#
+CONFIG_DVB_DM1105=m
+
+#
+# Supported FireWire (IEEE 1394) Adapters
+#
+CONFIG_DVB_FIREDTV=m
+CONFIG_DVB_FIREDTV_FIREWIRE=y
+CONFIG_DVB_FIREDTV_IEEE1394=y
+CONFIG_DVB_FIREDTV_INPUT=y
+
+#
+# Supported Earthsoft PT1 Adapters
+#
+# CONFIG_DVB_PT1 is not set
+
+#
+# Supported Mantis Adapters
+#
+CONFIG_MANTIS_CORE=m
+CONFIG_DVB_MANTIS=m
+CONFIG_DVB_HOPPER=m
+
+#
+# Supported nGene Adapters
+#
+CONFIG_DVB_NGENE=m
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+CONFIG_DVB_STV090x=m
+CONFIG_DVB_STV6110x=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10036=m
+CONFIG_DVB_ZL10039=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_STV6110=m
+CONFIG_DVB_STV0900=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_MB86A16=m
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+CONFIG_DVB_DIB8000=m
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_TDA665x=m
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_AGP=m
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_INTEL=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_VIA=m
+# CONFIG_VGA_ARB is not set
+CONFIG_VGA_SWITCHEROO=y
+CONFIG_DRM=m
+CONFIG_DRM_KMS_HELPER=m
+CONFIG_DRM_TTM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+# CONFIG_DRM_RADEON_KMS is not set
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+# CONFIG_DRM_I915_KMS is not set
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+CONFIG_VGASTATE=m
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=m
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_HECUBA=m
+CONFIG_FB_SVGALIB=m
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+CONFIG_FB_PM2=m
+CONFIG_FB_PM2_FIFO_DISCONNECT=y
+CONFIG_FB_CYBER2000=m
+CONFIG_FB_ARC=m
+CONFIG_FB_VGA16=m
+CONFIG_FB_UVESA=m
+CONFIG_FB_N411=m
+CONFIG_FB_HGA=m
+# CONFIG_FB_HGA_ACCEL is not set
+CONFIG_FB_S1D13XXX=m
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_LE80578=m
+CONFIG_FB_CARILLO_RANCH=m
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_INTEL_I2C=y
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_S3=m
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+CONFIG_FB_SIS=m
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+CONFIG_FB_VIA=m
+# CONFIG_FB_VIA_DIRECT_PROCFS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_3DFX_I2C=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_VT8623=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_ARK=m
+CONFIG_FB_PM3=m
+CONFIG_FB_CARMINE=m
+CONFIG_FB_CARMINE_DRAM_EVAL=y
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
+CONFIG_FB_GEODE=y
+CONFIG_FB_GEODE_LX=m
+CONFIG_FB_GEODE_GX=m
+CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_TMIO=m
+CONFIG_FB_TMIO_ACCELL=y
+CONFIG_FB_SM501=m
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_METRONOME=m
+CONFIG_FB_MB862XX=m
+# CONFIG_FB_MB862XX_PCI_GDC is not set
+CONFIG_FB_BROADSHEET=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_L4F00242T03=m
+CONFIG_LCD_LMS283GF05=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_ILI9320=m
+CONFIG_LCD_TDO24M=m
+CONFIG_LCD_VGG2432A4=m
+CONFIG_LCD_PLATFORM=m
+CONFIG_LCD_S6E63M0=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_PROGEAR=m
+CONFIG_BACKLIGHT_CARILLO_RANCH=m
+CONFIG_BACKLIGHT_MBP_NVIDIA=m
+CONFIG_BACKLIGHT_SAHARA=m
+CONFIG_BACKLIGHT_ADP8860=m
+CONFIG_BACKLIGHT_PCF50633=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_RAWMIDI_SEQ=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_PCSP=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ASIHPI=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_CTXFI=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_INDIGOIOX=m
+CONFIG_SND_INDIGODJX=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_ES1968_INPUT=y
+CONFIG_SND_FM801=m
+# CONFIG_SND_FM801_TEA575X_BOOL is not set
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDA_HWDEP=y
+# CONFIG_SND_HDA_RECONFIG is not set
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_INPUT_BEEP_MODE=0
+CONFIG_SND_HDA_INPUT_JACK=y
+# CONFIG_SND_HDA_PATCH_LOADER is not set
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_CODEC_ATIHDMI=y
+CONFIG_SND_HDA_CODEC_NVHDMI=y
+CONFIG_SND_HDA_CODEC_INTELHDMI=y
+CONFIG_SND_HDA_ELD=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_GENERIC=y
+# CONFIG_SND_HDA_POWER_SAVE is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_HIFIER=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_LX6464ES=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MAESTRO3_INPUT=y
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+# CONFIG_SND_USB_CAIAQ_INPUT is not set
+CONFIG_SND_USB_US122L=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_PDAUDIOCF=m
+CONFIG_SND_SOC=m
+CONFIG_SND_SOC_I2C_AND_SPI=m
+CONFIG_SND_SOC_ALL_CODECS=m
+CONFIG_SND_SOC_WM_HUBS=m
+CONFIG_SND_SOC_AD1836=m
+CONFIG_SND_SOC_AD193X=m
+CONFIG_SND_SOC_AD73311=m
+CONFIG_SND_SOC_ADS117X=m
+CONFIG_SND_SOC_AK4104=m
+CONFIG_SND_SOC_AK4535=m
+CONFIG_SND_SOC_AK4642=m
+CONFIG_SND_SOC_AK4671=m
+CONFIG_SND_SOC_CS42L51=m
+CONFIG_SND_SOC_CS4270=m
+CONFIG_SND_SOC_L3=m
+CONFIG_SND_SOC_DA7210=m
+CONFIG_SND_SOC_PCM3008=m
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_SSM2602=m
+CONFIG_SND_SOC_TLV320AIC23=m
+CONFIG_SND_SOC_TLV320AIC26=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_TLV320DAC33=m
+CONFIG_SND_SOC_UDA134X=m
+CONFIG_SND_SOC_UDA1380=m
+CONFIG_SND_SOC_WM8400=m
+CONFIG_SND_SOC_WM8510=m
+CONFIG_SND_SOC_WM8523=m
+CONFIG_SND_SOC_WM8580=m
+CONFIG_SND_SOC_WM8711=m
+CONFIG_SND_SOC_WM8727=m
+CONFIG_SND_SOC_WM8728=m
+CONFIG_SND_SOC_WM8731=m
+CONFIG_SND_SOC_WM8741=m
+CONFIG_SND_SOC_WM8750=m
+CONFIG_SND_SOC_WM8753=m
+CONFIG_SND_SOC_WM8776=m
+CONFIG_SND_SOC_WM8900=m
+CONFIG_SND_SOC_WM8903=m
+CONFIG_SND_SOC_WM8904=m
+CONFIG_SND_SOC_WM8940=m
+CONFIG_SND_SOC_WM8955=m
+CONFIG_SND_SOC_WM8960=m
+CONFIG_SND_SOC_WM8961=m
+CONFIG_SND_SOC_WM8971=m
+CONFIG_SND_SOC_WM8974=m
+CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_WM8988=m
+CONFIG_SND_SOC_WM8990=m
+CONFIG_SND_SOC_WM8993=m
+CONFIG_SND_SOC_WM9081=m
+CONFIG_SND_SOC_MAX9877=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SOC_WM2000=m
+CONFIG_SND_SOC_WM9090=m
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_3M_PCT=m
+# CONFIG_HID_A4TECH is not set
+CONFIG_HID_ACRUX_FF=m
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+CONFIG_HID_CANDO=m
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_PRODIKEYS=m
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+CONFIG_HID_EGALAX=m
+CONFIG_HID_ELECOM=m
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+CONFIG_HID_MAGICMOUSE=m
+# CONFIG_HID_MICROSOFT is not set
+CONFIG_HID_MOSART=m
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_ORTEK=m
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_ROCCAT_KONE=m
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+CONFIG_HID_STANTUM=m
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_HID_ZYDACRON=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+CONFIG_USB_WUSB=m
+CONFIG_USB_WUSB_CBAF=m
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_XHCI_HCD=m
+# CONFIG_USB_XHCI_HCD_DEBUGGING is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OXU210HP_HCD=m
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_ISP1760_HCD=m
+CONFIG_USB_ISP1362_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_SSB=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_WHCI_HCD=m
+CONFIG_USB_HWA_HCD=m
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7715_PARPORT=y
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+# CONFIG_USB_LEGOTOWER is not set
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+# CONFIG_USB_TRANCEVIBRATOR is not set
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=m
+CONFIG_NOP_USB_XCEIV=m
+CONFIG_UWB=m
+CONFIG_UWB_HWA=m
+CONFIG_UWB_WHCI=m
+CONFIG_UWB_WLP=m
+CONFIG_UWB_I1480U=m
+CONFIG_UWB_I1480U_WLP=m
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+CONFIG_MMC_TEST=m
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_SDHCI_PCI=m
+CONFIG_MMC_RICOH_MMC=y
+CONFIG_MMC_SDHCI_PLTFM=m
+CONFIG_MMC_WBSD=m
+CONFIG_MMC_TIFM_SD=m
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_SDRICOH_CS=m
+CONFIG_MMC_CB710=m
+CONFIG_MMC_VIA_SDMMC=m
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+CONFIG_LEDS_NET5501=m
+CONFIG_LEDS_ALIX2=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+CONFIG_LEDS_LP3944=m
+CONFIG_LEDS_CLEVO_MAIL=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_REGULATOR=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_INTEL_SS4200=m
+CONFIG_LEDS_LT3593=m
+CONFIG_LEDS_DELL_NETBOOKS=m
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_ACCESSIBILITY=y
+# CONFIG_A11Y_BRAILLE_CONSOLE is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+# CONFIG_INFINIBAND_IPATH is not set
+# CONFIG_INFINIBAND_QIB is not set
+CONFIG_INFINIBAND_AMSO1100=m
+# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_INFINIBAND_CXGB4=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_INFINIBAND_NES=m
+# CONFIG_INFINIBAND_NES_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_TEST=m
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS3232=m
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_ISL12022=m
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=m
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8581=m
+CONFIG_RTC_DRV_RX8025=m
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_DS3234=m
+CONFIG_RTC_DRV_PCF2123=m
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=m
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_PCF50633=m
+CONFIG_RTC_DRV_AB8500=m
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_MID_DMAC=m
+CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y
+CONFIG_INTEL_IOATDMA=m
+CONFIG_TIMB_DMA=m
+CONFIG_PCH_DMA=m
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+# CONFIG_ASYNC_TX_DMA is not set
+CONFIG_DMATEST=m
+CONFIG_DCA=m
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+CONFIG_CFAG12864B=m
+CONFIG_CFAG12864B_RATE=20
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+# CONFIG_UIO_PCI_GENERIC is not set
+CONFIG_UIO_NETX=m
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_ET131X is not set
+# CONFIG_SLICOSS is not set
+# CONFIG_VIDEO_GO7007 is not set
+# CONFIG_VIDEO_CX25821 is not set
+# CONFIG_VIDEO_TM6000 is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_W35UND is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+# CONFIG_OTUS is not set
+# CONFIG_RT2860 is not set
+# CONFIG_RT2870 is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_PANEL is not set
+# CONFIG_R8187SE is not set
+# CONFIG_RTL8192SU is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTL8192E is not set
+# CONFIG_TRANZPORT is not set
+# CONFIG_POHMELFS is not set
+# CONFIG_IDE_PHISON is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_DRM_VMWGFX is not set
+# CONFIG_DRM_NOUVEAU is not set
+
+#
+# I2C encoder or helper chips
+#
+# CONFIG_DRM_I2C_CH7006 is not set
+CONFIG_DRM_I2C_SIL164=m
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+# CONFIG_FB_UDL is not set
+CONFIG_HYPERV=m
+CONFIG_HYPERV_STORAGE=m
+CONFIG_HYPERV_BLOCK=m
+CONFIG_HYPERV_NET=m
+CONFIG_HYPERV_UTILS=m
+# CONFIG_VME_BUS is not set
+# CONFIG_IIO is not set
+CONFIG_ZRAM=m
+CONFIG_ZRAM_STATS=y
+# CONFIG_WLAGS49_H2 is not set
+# CONFIG_WLAGS49_H25 is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_VIDEO_DT3155 is not set
+# CONFIG_CRYSTALHD is not set
+# CONFIG_CXT1E1 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_ST_BT is not set
+# CONFIG_ADIS16255 is not set
+# CONFIG_FB_XGI is not set
+# CONFIG_LIRC_STAGING is not set
+CONFIG_EASYCAP=m
+CONFIG_SOLO6X10=m
+CONFIG_ACPI_QUICKSTART=m
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_ACER_WMI=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_DELL_LAPTOP=m
+CONFIG_DELL_WMI=m
+CONFIG_FUJITSU_LAPTOP=m
+# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
+CONFIG_HP_WMI=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+# CONFIG_SONYPI_COMPAT is not set
+CONFIG_IDEAPAD_ACPI=m
+CONFIG_THINKPAD_ACPI=m
+CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y
+# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_INTEL_MENLOW=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_EEEPC_WMI=m
+CONFIG_ACPI_WMI=m
+CONFIG_MSI_WMI=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_TOPSTAR_LAPTOP is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_TOSHIBA_BT_RFKILL=m
+CONFIG_ACPI_CMPC=m
+CONFIG_INTEL_IPS=m
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+# CONFIG_EDD_OFF is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+CONFIG_DMIID=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=m
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_HISTOGRAM=y
+# CONFIG_FSCACHE_DEBUG is not set
+# CONFIG_FSCACHE_OBJECT_LIST is not set
+CONFIG_CACHEFILES=m
+# CONFIG_CACHEFILES_DEBUG is not set
+# CONFIG_CACHEFILES_HISTOGRAM is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=m
+CONFIG_UNION_FS=m
+# CONFIG_UNION_FS_XATTR is not set
+# CONFIG_UNION_FS_DEBUG is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=m
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_LOGFS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_LZO is not set
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_EXOFS_FS=m
+# CONFIG_EXOFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+# CONFIG_NFS_FSCACHE is not set
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_XPRT_RDMA=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CEPH_FS=m
+# CONFIG_CEPH_FS_PRETTYDEBUG is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_DFS_UPCALL=y
+# CONFIG_CIFS_FSCACHE is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LKDTM is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_RING_BUFFER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_OPTIMIZE_INLINING is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_IMA is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+# CONFIG_ASYNC_RAID6_TEST is not set
+CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y
+CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C_INTEL=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_AES_X86_64 is not set
+# CONFIG_CRYPTO_AES_NI_INTEL is not set
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+# CONFIG_CRYPTO_SALSA20_X86_64 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+# CONFIG_CRYPTO_TWOFISH_X86_64 is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_APIC_ARCHITECTURE=y
+CONFIG_KVM_MMIO=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_KVM_AMD=m
+CONFIG_VHOST_NET=m
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_BTREE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_NLATTR=y
diff --git a/main/linux-scst/scst-2.0.0.1-2.6.36.patch b/main/linux-scst/scst-2.0.0.1-2.6.36.patch
new file mode 100644
index 0000000000..c8699d8268
--- /dev/null
+++ b/main/linux-scst/scst-2.0.0.1-2.6.36.patch
@@ -0,0 +1,76096 @@
+Signed-off-by:
+
+diff -upkr linux-2.6.36/block/blk-map.c linux-2.6.36/block/blk-map.c
+--- linux-2.6.36/block/blk-map.c 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/block/blk-map.c 2010-11-26 17:52:19.467689539 +0300
+@@ -5,6 +5,8 @@
+ #include <linux/module.h>
+ #include <linux/bio.h>
+ #include <linux/blkdev.h>
++#include <linux/scatterlist.h>
++#include <linux/slab.h>
+ #include <scsi/sg.h> /* for struct sg_iovec */
+
+ #include "blk.h"
+@@ -271,6 +273,337 @@ int blk_rq_unmap_user(struct bio *bio)
+ }
+ EXPORT_SYMBOL(blk_rq_unmap_user);
+
++struct blk_kern_sg_work {
++ atomic_t bios_inflight;
++ struct sg_table sg_table;
++ struct scatterlist *src_sgl;
++};
++
++static void blk_free_kern_sg_work(struct blk_kern_sg_work *bw)
++{
++ sg_free_table(&bw->sg_table);
++ kfree(bw);
++ return;
++}
++
++static void blk_bio_map_kern_endio(struct bio *bio, int err)
++{
++ struct blk_kern_sg_work *bw = bio->bi_private;
++
++ if (bw != NULL) {
++ /* Decrement the bios in processing and, if zero, free */
++ BUG_ON(atomic_read(&bw->bios_inflight) <= 0);
++ if (atomic_dec_and_test(&bw->bios_inflight)) {
++ if ((bio_data_dir(bio) == READ) && (err == 0)) {
++ unsigned long flags;
++
++ local_irq_save(flags); /* to protect KMs */
++ sg_copy(bw->src_sgl, bw->sg_table.sgl, 0, 0,
++ KM_BIO_DST_IRQ, KM_BIO_SRC_IRQ);
++ local_irq_restore(flags);
++ }
++ blk_free_kern_sg_work(bw);
++ }
++ }
++
++ bio_put(bio);
++ return;
++}
++
++static int blk_rq_copy_kern_sg(struct request *rq, struct scatterlist *sgl,
++ int nents, struct blk_kern_sg_work **pbw,
++ gfp_t gfp, gfp_t page_gfp)
++{
++ int res = 0, i;
++ struct scatterlist *sg;
++ struct scatterlist *new_sgl;
++ int new_sgl_nents;
++ size_t len = 0, to_copy;
++ struct blk_kern_sg_work *bw;
++
++ bw = kzalloc(sizeof(*bw), gfp);
++ if (bw == NULL)
++ goto out;
++
++ bw->src_sgl = sgl;
++
++ for_each_sg(sgl, sg, nents, i)
++ len += sg->length;
++ to_copy = len;
++
++ new_sgl_nents = PFN_UP(len);
++
++ res = sg_alloc_table(&bw->sg_table, new_sgl_nents, gfp);
++ if (res != 0)
++ goto out_free_bw;
++
++ new_sgl = bw->sg_table.sgl;
++
++ for_each_sg(new_sgl, sg, new_sgl_nents, i) {
++ struct page *pg;
++
++ pg = alloc_page(page_gfp);
++ if (pg == NULL)
++ goto err_free_new_sgl;
++
++ sg_assign_page(sg, pg);
++ sg->length = min_t(size_t, PAGE_SIZE, len);
++
++ len -= PAGE_SIZE;
++ }
++
++ if (rq_data_dir(rq) == WRITE) {
++ /*
++ * We need to limit amount of copied data to to_copy, because
++ * sgl might have the last element in sgl not marked as last in
++ * SG chaining.
++ */
++ sg_copy(new_sgl, sgl, 0, to_copy,
++ KM_USER0, KM_USER1);
++ }
++
++ *pbw = bw;
++ /*
++ * REQ_COPY_USER name is misleading. It should be something like
++ * REQ_HAS_TAIL_SPACE_FOR_PADDING.
++ */
++ rq->cmd_flags |= REQ_COPY_USER;
++
++out:
++ return res;
++
++err_free_new_sgl:
++ for_each_sg(new_sgl, sg, new_sgl_nents, i) {
++ struct page *pg = sg_page(sg);
++ if (pg == NULL)
++ break;
++ __free_page(pg);
++ }
++ sg_free_table(&bw->sg_table);
++
++out_free_bw:
++ kfree(bw);
++ res = -ENOMEM;
++ goto out;
++}
++
++static int __blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
++ int nents, struct blk_kern_sg_work *bw, gfp_t gfp)
++{
++ int res;
++ struct request_queue *q = rq->q;
++ int rw = rq_data_dir(rq);
++ int max_nr_vecs, i;
++ size_t tot_len;
++ bool need_new_bio;
++ struct scatterlist *sg, *prev_sg = NULL;
++ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
++ int bios;
++
++ if (unlikely((sgl == NULL) || (sgl->length == 0) || (nents <= 0))) {
++ WARN_ON(1);
++ res = -EINVAL;
++ goto out;
++ }
++
++ /*
++ * Let's keep each bio allocation inside a single page to decrease
++ * probability of failure.
++ */
++ max_nr_vecs = min_t(size_t,
++ ((PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec)),
++ BIO_MAX_PAGES);
++
++ need_new_bio = true;
++ tot_len = 0;
++ bios = 0;
++ for_each_sg(sgl, sg, nents, i) {
++ struct page *page = sg_page(sg);
++ void *page_addr = page_address(page);
++ size_t len = sg->length, l;
++ size_t offset = sg->offset;
++
++ tot_len += len;
++ prev_sg = sg;
++
++ /*
++ * Each segment must be aligned on DMA boundary and
++ * not on stack. The last one may have unaligned
++ * length as long as the total length is aligned to
++ * DMA padding alignment.
++ */
++ if (i == nents - 1)
++ l = 0;
++ else
++ l = len;
++ if (((sg->offset | l) & queue_dma_alignment(q)) ||
++ (page_addr && object_is_on_stack(page_addr + sg->offset))) {
++ res = -EINVAL;
++ goto out_free_bios;
++ }
++
++ while (len > 0) {
++ size_t bytes;
++ int rc;
++
++ if (need_new_bio) {
++ bio = bio_kmalloc(gfp, max_nr_vecs);
++ if (bio == NULL) {
++ res = -ENOMEM;
++ goto out_free_bios;
++ }
++
++ if (rw == WRITE)
++ bio->bi_rw |= REQ_WRITE;
++
++ bios++;
++ bio->bi_private = bw;
++ bio->bi_end_io = blk_bio_map_kern_endio;
++
++ if (hbio == NULL)
++ hbio = tbio = bio;
++ else
++ tbio = tbio->bi_next = bio;
++ }
++
++ bytes = min_t(size_t, len, PAGE_SIZE - offset);
++
++ rc = bio_add_pc_page(q, bio, page, bytes, offset);
++ if (rc < bytes) {
++ if (unlikely(need_new_bio || (rc < 0))) {
++ if (rc < 0)
++ res = rc;
++ else
++ res = -EIO;
++ goto out_free_bios;
++ } else {
++ need_new_bio = true;
++ len -= rc;
++ offset += rc;
++ continue;
++ }
++ }
++
++ need_new_bio = false;
++ offset = 0;
++ len -= bytes;
++ page = nth_page(page, 1);
++ }
++ }
++
++ if (hbio == NULL) {
++ res = -EINVAL;
++ goto out_free_bios;
++ }
++
++ /* Total length must be aligned on DMA padding alignment */
++ if ((tot_len & q->dma_pad_mask) &&
++ !(rq->cmd_flags & REQ_COPY_USER)) {
++ res = -EINVAL;
++ goto out_free_bios;
++ }
++
++ if (bw != NULL)
++ atomic_set(&bw->bios_inflight, bios);
++
++ while (hbio != NULL) {
++ bio = hbio;
++ hbio = hbio->bi_next;
++ bio->bi_next = NULL;
++
++ blk_queue_bounce(q, &bio);
++
++ res = blk_rq_append_bio(q, rq, bio);
++ if (unlikely(res != 0)) {
++ bio->bi_next = hbio;
++ hbio = bio;
++ /* We can have one or more bios bounced */
++ goto out_unmap_bios;
++ }
++ }
++
++ res = 0;
++
++ rq->buffer = NULL;
++out:
++ return res;
++
++out_unmap_bios:
++ blk_rq_unmap_kern_sg(rq, res);
++
++out_free_bios:
++ while (hbio != NULL) {
++ bio = hbio;
++ hbio = hbio->bi_next;
++ bio_put(bio);
++ }
++ goto out;
++}
++
++/**
++ * blk_rq_map_kern_sg - map kernel data to a request, for REQ_TYPE_BLOCK_PC
++ * @rq: request to fill
++ * @sgl: area to map
++ * @nents: number of elements in @sgl
++ * @gfp: memory allocation flags
++ *
++ * Description:
++ * Data will be mapped directly if possible. Otherwise a bounce
++ * buffer will be used.
++ */
++int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
++ int nents, gfp_t gfp)
++{
++ int res;
++
++ res = __blk_rq_map_kern_sg(rq, sgl, nents, NULL, gfp);
++ if (unlikely(res != 0)) {
++ struct blk_kern_sg_work *bw = NULL;
++
++ res = blk_rq_copy_kern_sg(rq, sgl, nents, &bw,
++ gfp, rq->q->bounce_gfp | gfp);
++ if (unlikely(res != 0))
++ goto out;
++
++ res = __blk_rq_map_kern_sg(rq, bw->sg_table.sgl,
++ bw->sg_table.nents, bw, gfp);
++ if (res != 0) {
++ blk_free_kern_sg_work(bw);
++ goto out;
++ }
++ }
++
++ rq->buffer = NULL;
++
++out:
++ return res;
++}
++EXPORT_SYMBOL(blk_rq_map_kern_sg);
++
++/**
++ * blk_rq_unmap_kern_sg - unmap a request with kernel sg
++ * @rq: request to unmap
++ * @err: non-zero error code
++ *
++ * Description:
++ * Unmap a rq previously mapped by blk_rq_map_kern_sg(). Must be called
++ * only in case of an error!
++ */
++void blk_rq_unmap_kern_sg(struct request *rq, int err)
++{
++ struct bio *bio = rq->bio;
++
++ while (bio) {
++ struct bio *b = bio;
++ bio = bio->bi_next;
++ b->bi_end_io(b, err);
++ }
++ rq->bio = NULL;
++
++ return;
++}
++EXPORT_SYMBOL(blk_rq_unmap_kern_sg);
++
+ /**
+ * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage
+ * @q: request queue where request should be inserted
+diff -upkr linux-2.6.36/include/linux/blkdev.h linux-2.6.36/include/linux/blkdev.h
+--- linux-2.6.36/include/linux/blkdev.h 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/include/linux/blkdev.h 2010-10-26 12:00:15.899759399 +0400
+@@ -746,6 +748,9 @@ extern int blk_rq_map_kern(struct reques
+ extern int blk_rq_map_user_iov(struct request_queue *, struct request *,
+ struct rq_map_data *, struct sg_iovec *, int,
+ unsigned int, gfp_t);
++extern int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
++ int nents, gfp_t gfp);
++extern void blk_rq_unmap_kern_sg(struct request *rq, int err);
+ extern int blk_execute_rq(struct request_queue *, struct gendisk *,
+ struct request *, int);
+ extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
+diff -upkr linux-2.6.36/include/linux/scatterlist.h linux-2.6.36/include/linux/scatterlist.h
+--- linux-2.6.36/include/linux/scatterlist.h 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/include/linux/scatterlist.h 2010-10-26 12:00:15.899759399 +0400
+@@ -3,6 +3,7 @@
+
+ #include <asm/types.h>
+ #include <asm/scatterlist.h>
++#include <asm/kmap_types.h>
+ #include <linux/mm.h>
+ #include <linux/string.h>
+ #include <asm/io.h>
+@@ -218,6 +219,10 @@ size_t sg_copy_from_buffer(struct scatte
+ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
+ void *buf, size_t buflen);
+
++int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
++ int nents_to_copy, size_t copy_len,
++ enum km_type d_km_type, enum km_type s_km_type);
++
+ /*
+ * Maximum number of entries that will be allocated in one piece, if
+ * a list larger than this is required then chaining will be utilized.
+diff -upkr linux-2.6.36/lib/scatterlist.c linux-2.6.36/lib/scatterlist.c
+--- linux-2.6.36/lib/scatterlist.c 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/lib/scatterlist.c 2010-10-26 12:00:15.899759399 +0400
+@@ -517,3 +517,132 @@ size_t sg_copy_to_buffer(struct scatterl
+ return sg_copy_buffer(sgl, nents, buf, buflen, 1);
+ }
+ EXPORT_SYMBOL(sg_copy_to_buffer);
++
++/*
++ * Can switch to the next dst_sg element, so, to copy to strictly only
++ * one dst_sg element, it must be either last in the chain, or
++ * copy_len == dst_sg->length.
++ */
++static int sg_copy_elem(struct scatterlist **pdst_sg, size_t *pdst_len,
++ size_t *pdst_offs, struct scatterlist *src_sg,
++ size_t copy_len,
++ enum km_type d_km_type, enum km_type s_km_type)
++{
++ int res = 0;
++ struct scatterlist *dst_sg;
++ size_t src_len, dst_len, src_offs, dst_offs;
++ struct page *src_page, *dst_page;
++
++ dst_sg = *pdst_sg;
++ dst_len = *pdst_len;
++ dst_offs = *pdst_offs;
++ dst_page = sg_page(dst_sg);
++
++ src_page = sg_page(src_sg);
++ src_len = src_sg->length;
++ src_offs = src_sg->offset;
++
++ do {
++ void *saddr, *daddr;
++ size_t n;
++
++ saddr = kmap_atomic(src_page +
++ (src_offs >> PAGE_SHIFT), s_km_type) +
++ (src_offs & ~PAGE_MASK);
++ daddr = kmap_atomic(dst_page +
++ (dst_offs >> PAGE_SHIFT), d_km_type) +
++ (dst_offs & ~PAGE_MASK);
++
++ if (((src_offs & ~PAGE_MASK) == 0) &&
++ ((dst_offs & ~PAGE_MASK) == 0) &&
++ (src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) &&
++ (copy_len >= PAGE_SIZE)) {
++ copy_page(daddr, saddr);
++ n = PAGE_SIZE;
++ } else {
++ n = min_t(size_t, PAGE_SIZE - (dst_offs & ~PAGE_MASK),
++ PAGE_SIZE - (src_offs & ~PAGE_MASK));
++ n = min(n, src_len);
++ n = min(n, dst_len);
++ n = min_t(size_t, n, copy_len);
++ memcpy(daddr, saddr, n);
++ }
++ dst_offs += n;
++ src_offs += n;
++
++ kunmap_atomic(saddr, s_km_type);
++ kunmap_atomic(daddr, d_km_type);
++
++ res += n;
++ copy_len -= n;
++ if (copy_len == 0)
++ goto out;
++
++ src_len -= n;
++ dst_len -= n;
++ if (dst_len == 0) {
++ dst_sg = sg_next(dst_sg);
++ if (dst_sg == NULL)
++ goto out;
++ dst_page = sg_page(dst_sg);
++ dst_len = dst_sg->length;
++ dst_offs = dst_sg->offset;
++ }
++ } while (src_len > 0);
++
++out:
++ *pdst_sg = dst_sg;
++ *pdst_len = dst_len;
++ *pdst_offs = dst_offs;
++ return res;
++}
++
++/**
++ * sg_copy - copy one SG vector to another
++ * @dst_sg: destination SG
++ * @src_sg: source SG
++ * @nents_to_copy: maximum number of entries to copy
++ * @copy_len: maximum amount of data to copy. If 0, then copy all.
++ * @d_km_type: kmap_atomic type for the destination SG
++ * @s_km_type: kmap_atomic type for the source SG
++ *
++ * Description:
++ * Data from the source SG vector will be copied to the destination SG
++ * vector. End of the vectors will be determined by sg_next() returning
++ * NULL. Returns number of bytes copied.
++ */
++int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
++ int nents_to_copy, size_t copy_len,
++ enum km_type d_km_type, enum km_type s_km_type)
++{
++ int res = 0;
++ size_t dst_len, dst_offs;
++
++ if (copy_len == 0)
++ copy_len = 0x7FFFFFFF; /* copy all */
++
++ if (nents_to_copy == 0)
++ nents_to_copy = 0x7FFFFFFF; /* copy all */
++
++ dst_len = dst_sg->length;
++ dst_offs = dst_sg->offset;
++
++ do {
++ int copied = sg_copy_elem(&dst_sg, &dst_len, &dst_offs,
++ src_sg, copy_len, d_km_type, s_km_type);
++ copy_len -= copied;
++ res += copied;
++ if ((copy_len == 0) || (dst_sg == NULL))
++ goto out;
++
++ nents_to_copy--;
++ if (nents_to_copy == 0)
++ goto out;
++
++ src_sg = sg_next(src_sg);
++ } while (src_sg != NULL);
++
++out:
++ return res;
++}
++EXPORT_SYMBOL(sg_copy);
+
+diff -upkr linux-2.6.36/include/linux/mm_types.h linux-2.6.36/include/linux/mm_types.h
+--- linux-2.6.36/include/linux/mm_types.h 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/include/linux/mm_types.h 2010-10-26 12:01:40.651752329 +0400
+@@ -100,6 +100,18 @@ struct page {
+ */
+ void *shadow;
+ #endif
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ /*
++ * Used to implement support for notification on zero-copy TCP transfer
++ * completion. It might look as not good to have this field here and
++ * it's better to have it in struct sk_buff, but it would make the code
++ * much more complicated and fragile, since all skb then would have to
++ * contain only pages with the same value in this field.
++ */
++ void *net_priv;
++#endif
++
+ };
+
+ /*
+diff -upkr linux-2.6.36/include/linux/net.h linux-2.6.36/include/linux/net.h
+--- linux-2.6.36/include/linux/net.h 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/include/linux/net.h 2010-10-26 12:01:40.651752329 +0400
+@@ -20,6 +20,7 @@
+
+ #include <linux/socket.h>
+ #include <asm/socket.h>
++#include <linux/mm.h>
+
+ #define NPROTO AF_MAX
+
+@@ -291,5 +292,44 @@ extern int kernel_sock_shutdown(struct s
+ extern struct ratelimit_state net_ratelimit_state;
+ #endif
+
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++/* Support for notification on zero-copy TCP transfer completion */
++typedef void (*net_get_page_callback_t)(struct page *page);
++typedef void (*net_put_page_callback_t)(struct page *page);
++
++extern net_get_page_callback_t net_get_page_callback;
++extern net_put_page_callback_t net_put_page_callback;
++
++extern int net_set_get_put_page_callbacks(
++ net_get_page_callback_t get_callback,
++ net_put_page_callback_t put_callback);
++
++/*
++ * See comment for net_set_get_put_page_callbacks() why those functions
++ * don't need any protection.
++ */
++static inline void net_get_page(struct page *page)
++{
++ if (page->net_priv != 0)
++ net_get_page_callback(page);
++ get_page(page);
++}
++static inline void net_put_page(struct page *page)
++{
++ if (page->net_priv != 0)
++ net_put_page_callback(page);
++ put_page(page);
++}
++#else
++static inline void net_get_page(struct page *page)
++{
++ get_page(page);
++}
++static inline void net_put_page(struct page *page)
++{
++ put_page(page);
++}
++#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */
++
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_NET_H */
+diff -upkr linux-2.6.36/net/core/dev.c linux-2.6.36/net/core/dev.c
+--- linux-2.6.36/net/core/dev.c 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/net/core/dev.c 2010-10-26 12:01:40.651752329 +0400
+@@ -3140,7 +3140,7 @@ pull:
+ skb_shinfo(skb)->frags[0].size -= grow;
+
+ if (unlikely(!skb_shinfo(skb)->frags[0].size)) {
+- put_page(skb_shinfo(skb)->frags[0].page);
++ net_put_page(skb_shinfo(skb)->frags[0].page);
+ memmove(skb_shinfo(skb)->frags,
+ skb_shinfo(skb)->frags + 1,
+ --skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
+diff -upkr linux-2.6.36/net/core/skbuff.c linux-2.6.36/net/core/skbuff.c
+--- linux-2.6.36/net/core/skbuff.c 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/net/core/skbuff.c 2010-10-26 12:01:40.655752708 +0400
+@@ -76,13 +76,13 @@ static struct kmem_cache *skbuff_fclone_
+ static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+ {
+- put_page(buf->page);
++ net_put_page(buf->page);
+ }
+
+ static void sock_pipe_buf_get(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+ {
+- get_page(buf->page);
++ net_get_page(buf->page);
+ }
+
+ static int sock_pipe_buf_steal(struct pipe_inode_info *pipe,
+@@ -337,7 +337,7 @@ static void skb_release_data(struct sk_b
+ if (skb_shinfo(skb)->nr_frags) {
+ int i;
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+- put_page(skb_shinfo(skb)->frags[i].page);
++ net_put_page(skb_shinfo(skb)->frags[i].page);
+ }
+
+ if (skb_has_frags(skb))
+@@ -754,7 +754,7 @@ struct sk_buff *pskb_copy(struct sk_buff
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
+- get_page(skb_shinfo(n)->frags[i].page);
++ net_get_page(skb_shinfo(n)->frags[i].page);
+ }
+ skb_shinfo(n)->nr_frags = i;
+ }
+@@ -820,7 +820,7 @@ int pskb_expand_head(struct sk_buff *skb
+ offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+- get_page(skb_shinfo(skb)->frags[i].page);
++ net_get_page(skb_shinfo(skb)->frags[i].page);
+
+ if (skb_has_frags(skb))
+ skb_clone_fraglist(skb);
+@@ -1097,7 +1097,7 @@ drop_pages:
+ skb_shinfo(skb)->nr_frags = i;
+
+ for (; i < nfrags; i++)
+- put_page(skb_shinfo(skb)->frags[i].page);
++ net_put_page(skb_shinfo(skb)->frags[i].page);
+
+ if (skb_has_frags(skb))
+ skb_drop_fraglist(skb);
+@@ -1266,7 +1266,7 @@ pull_pages:
+ k = 0;
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ if (skb_shinfo(skb)->frags[i].size <= eat) {
+- put_page(skb_shinfo(skb)->frags[i].page);
++ net_put_page(skb_shinfo(skb)->frags[i].page);
+ eat -= skb_shinfo(skb)->frags[i].size;
+ } else {
+ skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
+@@ -1367,7 +1367,7 @@ EXPORT_SYMBOL(skb_copy_bits);
+ */
+ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
+ {
+- put_page(spd->pages[i]);
++ net_put_page(spd->pages[i]);
+ }
+
+ static inline struct page *linear_to_page(struct page *page, unsigned int *len,
+@@ -1391,7 +1391,7 @@ new_page:
+ off = sk->sk_sndmsg_off;
+ mlen = PAGE_SIZE - off;
+ if (mlen < 64 && mlen < *len) {
+- put_page(p);
++ net_put_page(p);
+ goto new_page;
+ }
+
+@@ -1401,7 +1401,7 @@ new_page:
+ memcpy(page_address(p) + off, page_address(page) + *offset, *len);
+ sk->sk_sndmsg_off += *len;
+ *offset = off;
+- get_page(p);
++ net_get_page(p);
+
+ return p;
+ }
+@@ -1423,7 +1423,7 @@ static inline int spd_fill_page(struct s
+ if (!page)
+ return 1;
+ } else
+- get_page(page);
++ net_get_page(page);
+
+ spd->pages[spd->nr_pages] = page;
+ spd->partial[spd->nr_pages].len = *len;
+@@ -2056,7 +2056,7 @@ static inline void skb_split_no_header(s
+ * where splitting is expensive.
+ * 2. Split is accurately. We make this.
+ */
+- get_page(skb_shinfo(skb)->frags[i].page);
++ net_get_page(skb_shinfo(skb)->frags[i].page);
+ skb_shinfo(skb1)->frags[0].page_offset += len - pos;
+ skb_shinfo(skb1)->frags[0].size -= len - pos;
+ skb_shinfo(skb)->frags[i].size = len - pos;
+@@ -2178,7 +2178,7 @@ int skb_shift(struct sk_buff *tgt, struc
+ to++;
+
+ } else {
+- get_page(fragfrom->page);
++ net_get_page(fragfrom->page);
+ fragto->page = fragfrom->page;
+ fragto->page_offset = fragfrom->page_offset;
+ fragto->size = todo;
+@@ -2200,7 +2200,7 @@ int skb_shift(struct sk_buff *tgt, struc
+ fragto = &skb_shinfo(tgt)->frags[merge];
+
+ fragto->size += fragfrom->size;
+- put_page(fragfrom->page);
++ net_put_page(fragfrom->page);
+ }
+
+ /* Reposition in the original skb */
+@@ -2601,7 +2601,7 @@ struct sk_buff *skb_segment(struct sk_bu
+
+ while (pos < offset + len && i < nfrags) {
+ *frag = skb_shinfo(skb)->frags[i];
+- get_page(frag->page);
++ net_get_page(frag->page);
+ size = frag->size;
+
+ if (pos < offset) {
+diff -upkr linux-2.6.36/net/ipv4/ip_output.c linux-2.6.36/net/ipv4/ip_output.c
+--- linux-2.6.36/net/ipv4/ip_output.c 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/net/ipv4/ip_output.c 2010-10-26 12:01:40.655752708 +0400
+@@ -1040,7 +1040,7 @@ alloc_new_skb:
+ err = -EMSGSIZE;
+ goto error;
+ }
+- get_page(page);
++ net_get_page(page);
+ skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
+ frag = &skb_shinfo(skb)->frags[i];
+ }
+@@ -1199,7 +1199,7 @@ ssize_t ip_append_page(struct sock *sk,
+ if (skb_can_coalesce(skb, i, page, offset)) {
+ skb_shinfo(skb)->frags[i-1].size += len;
+ } else if (i < MAX_SKB_FRAGS) {
+- get_page(page);
++ net_get_page(page);
+ skb_fill_page_desc(skb, i, page, offset, len);
+ } else {
+ err = -EMSGSIZE;
+diff -upkr linux-2.6.36/net/ipv4/Makefile linux-2.6.36/net/ipv4/Makefile
+--- linux-2.6.36/net/ipv4/Makefile 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/net/ipv4/Makefile 2010-10-26 12:01:40.655752708 +0400
+@@ -49,6 +49,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
+ obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
+ obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
+ obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
++obj-$(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) += tcp_zero_copy.o
+
+ obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
+ xfrm4_output.o
+diff -upkr linux-2.6.36/net/ipv4/tcp.c linux-2.6.36/net/ipv4/tcp.c
+--- linux-2.6.36/net/ipv4/tcp.c 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/net/ipv4/tcp.c 2010-10-26 12:01:40.659752056 +0400
+@@ -806,7 +806,7 @@ new_segment:
+ if (can_coalesce) {
+ skb_shinfo(skb)->frags[i - 1].size += copy;
+ } else {
+- get_page(page);
++ net_get_page(page);
+ skb_fill_page_desc(skb, i, page, offset, copy);
+ }
+
+@@ -1015,7 +1015,7 @@ new_segment:
+ goto new_segment;
+ } else if (page) {
+ if (off == PAGE_SIZE) {
+- put_page(page);
++ net_put_page(page);
+ TCP_PAGE(sk) = page = NULL;
+ off = 0;
+ }
+@@ -1056,9 +1056,9 @@ new_segment:
+ } else {
+ skb_fill_page_desc(skb, i, page, off, copy);
+ if (TCP_PAGE(sk)) {
+- get_page(page);
++ net_get_page(page);
+ } else if (off + copy < PAGE_SIZE) {
+- get_page(page);
++ net_get_page(page);
+ TCP_PAGE(sk) = page;
+ }
+ }
+diff -upkr linux-2.6.36/net/ipv4/tcp_output.c linux-2.6.36/net/ipv4/tcp_output.c
+--- linux-2.6.36/net/ipv4/tcp_output.c 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/net/ipv4/tcp_output.c 2010-10-26 12:01:40.659752056 +0400
+@@ -1086,7 +1086,7 @@ static void __pskb_trim_head(struct sk_b
+ k = 0;
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ if (skb_shinfo(skb)->frags[i].size <= eat) {
+- put_page(skb_shinfo(skb)->frags[i].page);
++ net_put_page(skb_shinfo(skb)->frags[i].page);
+ eat -= skb_shinfo(skb)->frags[i].size;
+ } else {
+ skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
+diff -upkr linux-2.6.36/net/ipv4/tcp_zero_copy.c linux-2.6.36/net/ipv4/tcp_zero_copy.c
+--- linux-2.6.36/net/ipv4/tcp_zero_copy.c 2010-10-26 12:02:24.519252006 +0400
++++ linux-2.6.36/net/ipv4/tcp_zero_copy.c 2010-10-26 12:01:40.659752056 +0400
+@@ -0,0 +1,49 @@
++/*
++ * Support routines for TCP zero copy transmit
++ *
++ * Created by Vladislav Bolkhovitin
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ */
++
++#include <linux/skbuff.h>
++
++net_get_page_callback_t net_get_page_callback __read_mostly;
++EXPORT_SYMBOL(net_get_page_callback);
++
++net_put_page_callback_t net_put_page_callback __read_mostly;
++EXPORT_SYMBOL(net_put_page_callback);
++
++/*
++ * Caller of this function must ensure that at the moment when it's called
++ * there are no pages in the system with net_priv field set to non-zero
++ * value. Hence, this function, as well as net_get_page() and net_put_page(),
++ * don't need any protection.
++ */
++int net_set_get_put_page_callbacks(
++ net_get_page_callback_t get_callback,
++ net_put_page_callback_t put_callback)
++{
++ int res = 0;
++
++ if ((net_get_page_callback != NULL) && (get_callback != NULL) &&
++ (net_get_page_callback != get_callback)) {
++ res = -EBUSY;
++ goto out;
++ }
++
++ if ((net_put_page_callback != NULL) && (put_callback != NULL) &&
++ (net_put_page_callback != put_callback)) {
++ res = -EBUSY;
++ goto out;
++ }
++
++ net_get_page_callback = get_callback;
++ net_put_page_callback = put_callback;
++
++out:
++ return res;
++}
++EXPORT_SYMBOL(net_set_get_put_page_callbacks);
+diff -upkr linux-2.6.36/net/ipv6/ip6_output.c linux-2.6.36/net/ipv6/ip6_output.c
+--- linux-2.6.36/net/ipv6/ip6_output.c 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/net/ipv6/ip6_output.c 2010-10-26 12:01:40.659752056 +0400
+@@ -1391,7 +1391,7 @@ alloc_new_skb:
+ err = -EMSGSIZE;
+ goto error;
+ }
+- get_page(page);
++ net_get_page(page);
+ skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
+ frag = &skb_shinfo(skb)->frags[i];
+ }
+diff -upkr linux-2.6.36/net/Kconfig linux-2.6.36/net/Kconfig
+--- linux-2.6.36/net/Kconfig 2010-10-21 00:30:22.000000000 +0400
++++ linux-2.6.36/net/Kconfig 2010-10-26 12:01:40.659752056 +0400
+@@ -72,6 +72,18 @@ config INET
+
+ Short answer: say Y.
+
++config TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION
++ bool "TCP/IP zero-copy transfer completion notification"
++ depends on INET
++ default SCST_ISCSI
++ ---help---
++ Adds support for sending a notification upon completion of a
++ zero-copy TCP/IP transfer. This can speed up certain TCP/IP
++ software. Currently this is only used by the iSCSI target driver
++ iSCSI-SCST.
++
++ If unsure, say N.
++
+ if INET
+ source "net/ipv4/Kconfig"
+ source "net/ipv6/Kconfig"
+diff -uprN orig/linux-2.6.36/include/scst/scst_const.h linux-2.6.36/include/scst/scst_const.h
+--- orig/linux-2.6.36/include/scst/scst_const.h
++++ linux-2.6.36/include/scst/scst_const.h
+@@ -0,0 +1,413 @@
++/*
++ * include/scst_const.h
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * Contains common SCST constants.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef __SCST_CONST_H
++#define __SCST_CONST_H
++
++#ifndef GENERATING_UPSTREAM_PATCH
++/*
++ * Include <linux/version.h> only when not converting this header file into
++ * a patch for upstream review because only then the symbol LINUX_VERSION_CODE
++ * is needed.
++ */
++#include <linux/version.h>
++#endif
++#include <scsi/scsi.h>
++
++#define SCST_CONST_VERSION "$Revision: 2605 $"
++
++/*** Shared constants between user and kernel spaces ***/
++
++/* Max size of CDB */
++#define SCST_MAX_CDB_SIZE 16
++
++/* Max size of various names */
++#define SCST_MAX_NAME 50
++
++/* Max size of external names, like initiator name */
++#define SCST_MAX_EXTERNAL_NAME 256
++
++/*
++ * Size of sense sufficient to carry standard sense data.
++ * Warning! It's allocated on stack!
++ */
++#define SCST_STANDARD_SENSE_LEN 18
++
++/* Max size of sense */
++#define SCST_SENSE_BUFFERSIZE 96
++
++/*************************************************************
++ ** Allowed delivery statuses for cmd's delivery_status
++ *************************************************************/
++
++#define SCST_CMD_DELIVERY_SUCCESS 0
++#define SCST_CMD_DELIVERY_FAILED -1
++#define SCST_CMD_DELIVERY_ABORTED -2
++
++/*************************************************************
++ ** Values for task management functions
++ *************************************************************/
++#define SCST_ABORT_TASK 0
++#define SCST_ABORT_TASK_SET 1
++#define SCST_CLEAR_ACA 2
++#define SCST_CLEAR_TASK_SET 3
++#define SCST_LUN_RESET 4
++#define SCST_TARGET_RESET 5
++
++/** SCST extensions **/
++
++/*
++ * Notifies about I_T nexus loss event in the corresponding session.
++ * Aborts all tasks there, resets the reservation, if any, and sets
++ * up the I_T Nexus loss UA.
++ */
++#define SCST_NEXUS_LOSS_SESS 6
++
++/* Aborts all tasks in the corresponding session */
++#define SCST_ABORT_ALL_TASKS_SESS 7
++
++/*
++ * Notifies about I_T nexus loss event. Aborts all tasks in all sessions
++ * of the tgt, resets the reservations, if any, and sets up the I_T Nexus
++ * loss UA.
++ */
++#define SCST_NEXUS_LOSS 8
++
++/* Aborts all tasks in all sessions of the tgt */
++#define SCST_ABORT_ALL_TASKS 9
++
++/*
++ * Internal TM command issued by SCST in scst_unregister_session(). It is the
++ * same as SCST_NEXUS_LOSS_SESS, except:
++ * - it doesn't call task_mgmt_affected_cmds_done()
++ * - it doesn't call task_mgmt_fn_done()
++ * - it doesn't queue NEXUS LOSS UA.
++ *
++ * Target drivers must NEVER use it!!
++ */
++#define SCST_UNREG_SESS_TM 10
++
++/*
++ * Internal TM command issued by SCST in scst_pr_abort_reg(). It aborts all
++ * tasks from mcmd->origin_pr_cmd->tgt_dev, except mcmd->origin_pr_cmd.
++ * Additionally:
++ * - it signals pr_aborting_cmpl completion when all affected
++ * commands marked as aborted.
++ * - it doesn't call task_mgmt_affected_cmds_done()
++ * - it doesn't call task_mgmt_fn_done()
++ * - it calls mcmd->origin_pr_cmd->scst_cmd_done() when all affected
++ * commands aborted.
++ *
++ * Target drivers must NEVER use it!!
++ */
++#define SCST_PR_ABORT_ALL 11
++
++/*************************************************************
++ ** Values for mgmt cmd's status field. Codes taken from iSCSI
++ *************************************************************/
++#define SCST_MGMT_STATUS_SUCCESS 0
++#define SCST_MGMT_STATUS_TASK_NOT_EXIST -1
++#define SCST_MGMT_STATUS_LUN_NOT_EXIST -2
++#define SCST_MGMT_STATUS_FN_NOT_SUPPORTED -5
++#define SCST_MGMT_STATUS_REJECTED -255
++#define SCST_MGMT_STATUS_FAILED -129
++
++/*************************************************************
++ ** SCSI task attribute queue types
++ *************************************************************/
++enum scst_cmd_queue_type {
++ SCST_CMD_QUEUE_UNTAGGED = 0,
++ SCST_CMD_QUEUE_SIMPLE,
++ SCST_CMD_QUEUE_ORDERED,
++ SCST_CMD_QUEUE_HEAD_OF_QUEUE,
++ SCST_CMD_QUEUE_ACA
++};
++
++/*************************************************************
++ ** CDB flags
++ **
++ ** Implicit ordered used for commands which need calm environment
++ ** without any simultaneous activities. For instance, for MODE
++ ** SELECT it is needed to correctly generate its UA.
++ *************************************************************/
++enum scst_cdb_flags {
++ SCST_TRANSFER_LEN_TYPE_FIXED = 0x0001,
++ SCST_SMALL_TIMEOUT = 0x0002,
++ SCST_LONG_TIMEOUT = 0x0004,
++ SCST_UNKNOWN_LENGTH = 0x0008,
++ SCST_INFO_VALID = 0x0010, /* must be single bit */
++ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x0020,
++ SCST_IMPLICIT_HQ = 0x0040,
++ SCST_IMPLICIT_ORDERED = 0x0080, /* ToDo: remove it's nonsense */
++ SCST_SKIP_UA = 0x0100,
++ SCST_WRITE_MEDIUM = 0x0200,
++ SCST_LOCAL_CMD = 0x0400,
++ SCST_FULLY_LOCAL_CMD = 0x0800,
++ SCST_REG_RESERVE_ALLOWED = 0x1000,
++ SCST_WRITE_EXCL_ALLOWED = 0x2000,
++ SCST_EXCL_ACCESS_ALLOWED = 0x4000,
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED = 0x8000,
++#endif
++};
++
++/*************************************************************
++ ** Data direction aliases. Changing it don't forget to change
++ ** scst_to_tgt_dma_dir as well!!
++ *************************************************************/
++#define SCST_DATA_UNKNOWN 0
++#define SCST_DATA_WRITE 1
++#define SCST_DATA_READ 2
++#define SCST_DATA_BIDI (SCST_DATA_WRITE | SCST_DATA_READ)
++#define SCST_DATA_NONE 4
++
++/*************************************************************
++ ** Default suffix for targets with NULL names
++ *************************************************************/
++#define SCST_DEFAULT_TGT_NAME_SUFFIX "_target_"
++
++/*************************************************************
++ ** Sense manipulation and examination
++ *************************************************************/
++#define SCST_LOAD_SENSE(key_asc_ascq) key_asc_ascq
++
++#define SCST_SENSE_VALID(sense) ((sense != NULL) && \
++ ((((const uint8_t *)(sense))[0] & 0x70) == 0x70))
++
++#define SCST_NO_SENSE(sense) ((sense != NULL) && \
++ (((const uint8_t *)(sense))[2] == 0))
++
++/*************************************************************
++ ** Sense data for the appropriate errors. Can be used with
++ ** scst_set_cmd_error()
++ *************************************************************/
++#define scst_sense_no_sense NO_SENSE, 0x00, 0
++#define scst_sense_hardw_error HARDWARE_ERROR, 0x44, 0
++#define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0
++#define scst_sense_invalid_opcode ILLEGAL_REQUEST, 0x20, 0
++#define scst_sense_invalid_field_in_cdb ILLEGAL_REQUEST, 0x24, 0
++#define scst_sense_invalid_field_in_parm_list ILLEGAL_REQUEST, 0x26, 0
++#define scst_sense_parameter_value_invalid ILLEGAL_REQUEST, 0x26, 2
++#define scst_sense_invalid_release ILLEGAL_REQUEST, 0x26, 4
++#define scst_sense_parameter_list_length_invalid \
++ ILLEGAL_REQUEST, 0x1A, 0
++#define scst_sense_reset_UA UNIT_ATTENTION, 0x29, 0
++#define scst_sense_nexus_loss_UA UNIT_ATTENTION, 0x29, 0x7
++#define scst_sense_saving_params_unsup ILLEGAL_REQUEST, 0x39, 0
++#define scst_sense_lun_not_supported ILLEGAL_REQUEST, 0x25, 0
++#define scst_sense_data_protect DATA_PROTECT, 0x00, 0
++#define scst_sense_miscompare_error MISCOMPARE, 0x1D, 0
++#define scst_sense_block_out_range_error ILLEGAL_REQUEST, 0x21, 0
++#define scst_sense_medium_changed_UA UNIT_ATTENTION, 0x28, 0
++#define scst_sense_read_error MEDIUM_ERROR, 0x11, 0
++#define scst_sense_write_error MEDIUM_ERROR, 0x03, 0
++#define scst_sense_not_ready NOT_READY, 0x04, 0x10
++#define scst_sense_invalid_message ILLEGAL_REQUEST, 0x49, 0
++#define scst_sense_cleared_by_another_ini_UA UNIT_ATTENTION, 0x2F, 0
++#define scst_sense_capacity_data_changed UNIT_ATTENTION, 0x2A, 0x9
++#define scst_sense_reservation_preempted UNIT_ATTENTION, 0x2A, 0x03
++#define scst_sense_reservation_released UNIT_ATTENTION, 0x2A, 0x04
++#define scst_sense_registrations_preempted UNIT_ATTENTION, 0x2A, 0x05
++#define scst_sense_reported_luns_data_changed UNIT_ATTENTION, 0x3F, 0xE
++#define scst_sense_inquery_data_changed UNIT_ATTENTION, 0x3F, 0x3
++
++/*************************************************************
++ * SCSI opcodes not listed anywhere else
++ *************************************************************/
++#define REPORT_DEVICE_IDENTIFIER 0xA3
++#define INIT_ELEMENT_STATUS 0x07
++#define INIT_ELEMENT_STATUS_RANGE 0x37
++#define PREVENT_ALLOW_MEDIUM 0x1E
++#define READ_ATTRIBUTE 0x8C
++#define REQUEST_VOLUME_ADDRESS 0xB5
++#define WRITE_ATTRIBUTE 0x8D
++#define WRITE_VERIFY_16 0x8E
++#define VERIFY_6 0x13
++#ifndef VERIFY_12
++#define VERIFY_12 0xAF
++#endif
++#ifndef GENERATING_UPSTREAM_PATCH
++/*
++ * The constants below have been defined in the kernel header <scsi/scsi.h>
++ * and hence are not needed when this header file is included in kernel code.
++ * The definitions below are only used when this header file is included during
++ * compilation of SCST's user space components.
++ */
++#ifndef READ_16
++#define READ_16 0x88
++#endif
++#ifndef WRITE_16
++#define WRITE_16 0x8a
++#endif
++#ifndef VERIFY_16
++#define VERIFY_16 0x8f
++#endif
++#ifndef SERVICE_ACTION_IN
++#define SERVICE_ACTION_IN 0x9e
++#endif
++#ifndef SAI_READ_CAPACITY_16
++/* values for service action in */
++#define SAI_READ_CAPACITY_16 0x10
++#endif
++#endif
++#ifndef GENERATING_UPSTREAM_PATCH
++#ifndef REPORT_LUNS
++#define REPORT_LUNS 0xa0
++#endif
++#endif
++
++/*************************************************************
++ ** SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
++ ** T10/1561-D Revision 4 Draft dated 7th November 2002.
++ *************************************************************/
++#define SAM_STAT_GOOD 0x00
++#define SAM_STAT_CHECK_CONDITION 0x02
++#define SAM_STAT_CONDITION_MET 0x04
++#define SAM_STAT_BUSY 0x08
++#define SAM_STAT_INTERMEDIATE 0x10
++#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14
++#define SAM_STAT_RESERVATION_CONFLICT 0x18
++#define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */
++#define SAM_STAT_TASK_SET_FULL 0x28
++#define SAM_STAT_ACA_ACTIVE 0x30
++#define SAM_STAT_TASK_ABORTED 0x40
++
++/*************************************************************
++ ** Control byte field in CDB
++ *************************************************************/
++#define CONTROL_BYTE_LINK_BIT 0x01
++#define CONTROL_BYTE_NACA_BIT 0x04
++
++/*************************************************************
++ ** Byte 1 in INQUIRY CDB
++ *************************************************************/
++#define SCST_INQ_EVPD 0x01
++
++/*************************************************************
++ ** Byte 3 in Standard INQUIRY data
++ *************************************************************/
++#define SCST_INQ_BYTE3 3
++
++#define SCST_INQ_NORMACA_BIT 0x20
++
++/*************************************************************
++ ** Byte 2 in RESERVE_10 CDB
++ *************************************************************/
++#define SCST_RES_3RDPTY 0x10
++#define SCST_RES_LONGID 0x02
++
++/*************************************************************
++ ** Values for the control mode page TST field
++ *************************************************************/
++#define SCST_CONTR_MODE_ONE_TASK_SET 0
++#define SCST_CONTR_MODE_SEP_TASK_SETS 1
++
++/*******************************************************************
++ ** Values for the control mode page QUEUE ALGORITHM MODIFIER field
++ *******************************************************************/
++#define SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER 0
++#define SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER 1
++
++/*************************************************************
++ ** Values for the control mode page D_SENSE field
++ *************************************************************/
++#define SCST_CONTR_MODE_FIXED_SENSE 0
++#define SCST_CONTR_MODE_DESCR_SENSE 1
++
++/*************************************************************
++ ** TransportID protocol identifiers
++ *************************************************************/
++
++#define SCSI_TRANSPORTID_PROTOCOLID_FCP2 0
++#define SCSI_TRANSPORTID_PROTOCOLID_SPI5 1
++#define SCSI_TRANSPORTID_PROTOCOLID_SRP 4
++#define SCSI_TRANSPORTID_PROTOCOLID_ISCSI 5
++#define SCSI_TRANSPORTID_PROTOCOLID_SAS 6
++
++/*************************************************************
++ ** Misc SCSI constants
++ *************************************************************/
++#define SCST_SENSE_ASC_UA_RESET 0x29
++#define BYTCHK 0x02
++#define POSITION_LEN_SHORT 20
++#define POSITION_LEN_LONG 32
++
++/*************************************************************
++ ** Various timeouts
++ *************************************************************/
++#define SCST_DEFAULT_TIMEOUT (60 * HZ)
++
++#define SCST_GENERIC_CHANGER_TIMEOUT (3 * HZ)
++#define SCST_GENERIC_CHANGER_LONG_TIMEOUT (14000 * HZ)
++
++#define SCST_GENERIC_PROCESSOR_TIMEOUT (3 * HZ)
++#define SCST_GENERIC_PROCESSOR_LONG_TIMEOUT (14000 * HZ)
++
++#define SCST_GENERIC_TAPE_SMALL_TIMEOUT (3 * HZ)
++#define SCST_GENERIC_TAPE_REG_TIMEOUT (900 * HZ)
++#define SCST_GENERIC_TAPE_LONG_TIMEOUT (14000 * HZ)
++
++#define SCST_GENERIC_MODISK_SMALL_TIMEOUT (3 * HZ)
++#define SCST_GENERIC_MODISK_REG_TIMEOUT (900 * HZ)
++#define SCST_GENERIC_MODISK_LONG_TIMEOUT (14000 * HZ)
++
++#define SCST_GENERIC_DISK_SMALL_TIMEOUT (3 * HZ)
++#define SCST_GENERIC_DISK_REG_TIMEOUT (60 * HZ)
++#define SCST_GENERIC_DISK_LONG_TIMEOUT (3600 * HZ)
++
++#define SCST_GENERIC_RAID_TIMEOUT (3 * HZ)
++#define SCST_GENERIC_RAID_LONG_TIMEOUT (14000 * HZ)
++
++#define SCST_GENERIC_CDROM_SMALL_TIMEOUT (3 * HZ)
++#define SCST_GENERIC_CDROM_REG_TIMEOUT (900 * HZ)
++#define SCST_GENERIC_CDROM_LONG_TIMEOUT (14000 * HZ)
++
++#define SCST_MAX_OTHER_TIMEOUT (14000 * HZ)
++
++/*************************************************************
++ ** I/O grouping attribute string values. Must match constants
++ ** w/o '_STR' suffix!
++ *************************************************************/
++#define SCST_IO_GROUPING_AUTO_STR "auto"
++#define SCST_IO_GROUPING_THIS_GROUP_ONLY_STR "this_group_only"
++#define SCST_IO_GROUPING_NEVER_STR "never"
++
++/*************************************************************
++ ** Threads pool type attribute string values.
++ ** Must match scst_dev_type_threads_pool_type!
++ *************************************************************/
++#define SCST_THREADS_POOL_PER_INITIATOR_STR "per_initiator"
++#define SCST_THREADS_POOL_SHARED_STR "shared"
++
++/*************************************************************
++ ** Misc constants
++ *************************************************************/
++#define SCST_SYSFS_BLOCK_SIZE PAGE_SIZE
++
++#define SCST_PR_DIR "/var/lib/scst/pr"
++
++#define TID_COMMON_SIZE 24
++
++#define SCST_SYSFS_KEY_MARK "[key]"
++
++#define SCST_MIN_REL_TGT_ID 1
++#define SCST_MAX_REL_TGT_ID 65535
++
++#endif /* __SCST_CONST_H */
+diff -uprN orig/linux-2.6.36/include/scst/scst.h linux-2.6.36/include/scst/scst.h
+--- orig/linux-2.6.36/include/scst/scst.h
++++ linux-2.6.36/include/scst/scst.h
+@@ -0,0 +1,3524 @@
++/*
++ * include/scst.h
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * Main SCSI target mid-level include file.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef __SCST_H
++#define __SCST_H
++
++#include <linux/types.h>
++#include <linux/version.h>
++#include <linux/blkdev.h>
++#include <linux/interrupt.h>
++#include <linux/wait.h>
++
++/* #define CONFIG_SCST_PROC */
++
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_eh.h>
++#include <scsi/scsi.h>
++
++#include <scst/scst_const.h>
++
++#include <scst/scst_sgv.h>
++
++/*
++ * Version numbers, the same as for the kernel.
++ *
++ * Changing it don't forget to change SCST_FIO_REV in scst_vdisk.c
++ * and FIO_REV in usr/fileio/common.h as well.
++ */
++#define SCST_VERSION(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + d)
++#define SCST_VERSION_CODE SCST_VERSION(2, 0, 0, 1)
++#define SCST_VERSION_STRING_SUFFIX
++#define SCST_VERSION_STRING "2.0.0.1" SCST_VERSION_STRING_SUFFIX
++#define SCST_INTERFACE_VERSION \
++ SCST_VERSION_STRING "$Revision: 3165 $" SCST_CONST_VERSION
++
++#define SCST_LOCAL_NAME "scst_local"
++
++/*************************************************************
++ ** States of command processing state machine. At first,
++ ** "active" states, then - "passive" ones. This is to have
++ ** more efficient generated code of the corresponding
++ ** "switch" statements.
++ *************************************************************/
++
++/* Dev handler's parse() is going to be called */
++#define SCST_CMD_STATE_PARSE 0
++
++/* Allocation of the cmd's data buffer */
++#define SCST_CMD_STATE_PREPARE_SPACE 1
++
++/* Calling preprocessing_done() */
++#define SCST_CMD_STATE_PREPROCESSING_DONE 2
++
++/* Target driver's rdy_to_xfer() is going to be called */
++#define SCST_CMD_STATE_RDY_TO_XFER 3
++
++/* Target driver's pre_exec() is going to be called */
++#define SCST_CMD_STATE_TGT_PRE_EXEC 4
++
++/* Cmd is going to be sent for execution */
++#define SCST_CMD_STATE_SEND_FOR_EXEC 5
++
++/* Cmd is being checked if it should be executed locally */
++#define SCST_CMD_STATE_LOCAL_EXEC 6
++
++/* Cmd is ready for execution */
++#define SCST_CMD_STATE_REAL_EXEC 7
++
++/* Internal post-exec checks */
++#define SCST_CMD_STATE_PRE_DEV_DONE 8
++
++/* Internal MODE SELECT pages related checks */
++#define SCST_CMD_STATE_MODE_SELECT_CHECKS 9
++
++/* Dev handler's dev_done() is going to be called */
++#define SCST_CMD_STATE_DEV_DONE 10
++
++/* Target driver's xmit_response() is going to be called */
++#define SCST_CMD_STATE_PRE_XMIT_RESP 11
++
++/* Target driver's xmit_response() is going to be called */
++#define SCST_CMD_STATE_XMIT_RESP 12
++
++/* Cmd finished */
++#define SCST_CMD_STATE_FINISHED 13
++
++/* Internal cmd finished */
++#define SCST_CMD_STATE_FINISHED_INTERNAL 14
++
++#define SCST_CMD_STATE_LAST_ACTIVE (SCST_CMD_STATE_FINISHED_INTERNAL+100)
++
++/* A cmd is created, but scst_cmd_init_done() not called */
++#define SCST_CMD_STATE_INIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+1)
++
++/* LUN translation (cmd->tgt_dev assignment) */
++#define SCST_CMD_STATE_INIT (SCST_CMD_STATE_LAST_ACTIVE+2)
++
++/* Waiting for scst_restart_cmd() */
++#define SCST_CMD_STATE_PREPROCESSING_DONE_CALLED (SCST_CMD_STATE_LAST_ACTIVE+3)
++
++/* Waiting for data from the initiator (until scst_rx_data() called) */
++#define SCST_CMD_STATE_DATA_WAIT (SCST_CMD_STATE_LAST_ACTIVE+4)
++
++/* Waiting for CDB's execution finish */
++#define SCST_CMD_STATE_REAL_EXECUTING (SCST_CMD_STATE_LAST_ACTIVE+5)
++
++/* Waiting for response's transmission finish */
++#define SCST_CMD_STATE_XMIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+6)
++
++/*************************************************************
++ * Can be retuned instead of cmd's state by dev handlers'
++ * functions, if the command's state should be set by default
++ *************************************************************/
++#define SCST_CMD_STATE_DEFAULT 500
++
++/*************************************************************
++ * Can be retuned instead of cmd's state by dev handlers'
++ * functions, if it is impossible to complete requested
++ * task in atomic context. The cmd will be restarted in thread
++ * context.
++ *************************************************************/
++#define SCST_CMD_STATE_NEED_THREAD_CTX 1000
++
++/*************************************************************
++ * Can be retuned instead of cmd's state by dev handlers'
++ * parse function, if the cmd processing should be stopped
++ * for now. The cmd will be restarted by dev handlers itself.
++ *************************************************************/
++#define SCST_CMD_STATE_STOP 1001
++
++/*************************************************************
++ ** States of mgmt command processing state machine
++ *************************************************************/
++
++/* LUN translation (mcmd->tgt_dev assignment) */
++#define SCST_MCMD_STATE_INIT 0
++
++/* Mgmt cmd is being processed */
++#define SCST_MCMD_STATE_EXEC 1
++
++/* Waiting for affected commands done */
++#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE 2
++
++/* Post actions when affected commands done */
++#define SCST_MCMD_STATE_AFFECTED_CMDS_DONE 3
++
++/* Waiting for affected local commands finished */
++#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED 4
++
++/* Target driver's task_mgmt_fn_done() is going to be called */
++#define SCST_MCMD_STATE_DONE 5
++
++/* The mcmd finished */
++#define SCST_MCMD_STATE_FINISHED 6
++
++/*************************************************************
++ ** Constants for "atomic" parameter of SCST's functions
++ *************************************************************/
++#define SCST_NON_ATOMIC 0
++#define SCST_ATOMIC 1
++
++/*************************************************************
++ ** Values for pref_context parameter of scst_cmd_init_done(),
++ ** scst_rx_data(), scst_restart_cmd(), scst_tgt_cmd_done()
++ ** and scst_cmd_done()
++ *************************************************************/
++
++enum scst_exec_context {
++ /*
++ * Direct cmd's processing (i.e. regular function calls in the current
++ * context) sleeping is not allowed
++ */
++ SCST_CONTEXT_DIRECT_ATOMIC,
++
++ /*
++ * Direct cmd's processing (i.e. regular function calls in the current
++ * context), sleeping is allowed, no restrictions
++ */
++ SCST_CONTEXT_DIRECT,
++
++ /* Tasklet or thread context required for cmd's processing */
++ SCST_CONTEXT_TASKLET,
++
++ /* Thread context required for cmd's processing */
++ SCST_CONTEXT_THREAD,
++
++ /*
++ * Context is the same as it was in previous call of the corresponding
++ * callback. For example, if dev handler's exec() does sync. data
++ * reading this value should be used for scst_cmd_done(). The same is
++ * true if scst_tgt_cmd_done() called directly from target driver's
++ * xmit_response(). Not allowed in scst_cmd_init_done() and
++ * scst_cmd_init_stage1_done().
++ */
++ SCST_CONTEXT_SAME
++};
++
++/*************************************************************
++ ** Values for status parameter of scst_rx_data()
++ *************************************************************/
++
++/* Success */
++#define SCST_RX_STATUS_SUCCESS 0
++
++/*
++ * Data receiving finished with error, so set the sense and
++ * finish the command, including xmit_response() call
++ */
++#define SCST_RX_STATUS_ERROR 1
++
++/*
++ * Data receiving finished with error and the sense is set,
++ * so finish the command, including xmit_response() call
++ */
++#define SCST_RX_STATUS_ERROR_SENSE_SET 2
++
++/*
++ * Data receiving finished with fatal error, so finish the command,
++ * but don't call xmit_response()
++ */
++#define SCST_RX_STATUS_ERROR_FATAL 3
++
++/*************************************************************
++ ** Values for status parameter of scst_restart_cmd()
++ *************************************************************/
++
++/* Success */
++#define SCST_PREPROCESS_STATUS_SUCCESS 0
++
++/*
++ * Command's processing finished with error, so set the sense and
++ * finish the command, including xmit_response() call
++ */
++#define SCST_PREPROCESS_STATUS_ERROR 1
++
++/*
++ * Command's processing finished with error and the sense is set,
++ * so finish the command, including xmit_response() call
++ */
++#define SCST_PREPROCESS_STATUS_ERROR_SENSE_SET 2
++
++/*
++ * Command's processing finished with fatal error, so finish the command,
++ * but don't call xmit_response()
++ */
++#define SCST_PREPROCESS_STATUS_ERROR_FATAL 3
++
++/*************************************************************
++ ** Values for AEN functions
++ *************************************************************/
++
++/*
++ * SCSI Asynchronous Event. Parameter contains SCSI sense
++ * (Unit Attention). AENs generated only for 2 the following UAs:
++ * CAPACITY DATA HAS CHANGED and REPORTED LUNS DATA HAS CHANGED.
++ * Other UAs reported regularly as CHECK CONDITION status,
++ * because it doesn't look safe to report them using AENs, since
++ * reporting using AENs opens delivery race windows even in case of
++ * untagged commands.
++ */
++#define SCST_AEN_SCSI 0
++
++/*************************************************************
++ ** Allowed return/status codes for report_aen() callback and
++ ** scst_set_aen_delivery_status() function
++ *************************************************************/
++
++/* Success */
++#define SCST_AEN_RES_SUCCESS 0
++
++/* Not supported */
++#define SCST_AEN_RES_NOT_SUPPORTED -1
++
++/* Failure */
++#define SCST_AEN_RES_FAILED -2
++
++/*************************************************************
++ ** Allowed return codes for xmit_response(), rdy_to_xfer()
++ *************************************************************/
++
++/* Success */
++#define SCST_TGT_RES_SUCCESS 0
++
++/* Internal device queue is full, retry again later */
++#define SCST_TGT_RES_QUEUE_FULL -1
++
++/*
++ * It is impossible to complete requested task in atomic context.
++ * The cmd will be restarted in thread context.
++ */
++#define SCST_TGT_RES_NEED_THREAD_CTX -2
++
++/*
++ * Fatal error, if returned by xmit_response() the cmd will
++ * be destroyed, if by any other function, xmit_response()
++ * will be called with HARDWARE ERROR sense data
++ */
++#define SCST_TGT_RES_FATAL_ERROR -3
++
++/*************************************************************
++ ** Allowed return codes for dev handler's exec()
++ *************************************************************/
++
++/* The cmd is done, go to other ones */
++#define SCST_EXEC_COMPLETED 0
++
++/* The cmd should be sent to SCSI mid-level */
++#define SCST_EXEC_NOT_COMPLETED 1
++
++/*
++ * Set if cmd is finished and there is status/sense to be sent.
++ * The status should be not sent (i.e. the flag not set) if the
++ * possibility to perform a command in "chunks" (i.e. with multiple
++ * xmit_response()/rdy_to_xfer()) is used (not implemented yet).
++ * Obsolete, use scst_cmd_get_is_send_status() instead.
++ */
++#define SCST_TSC_FLAG_STATUS 0x2
++
++/*************************************************************
++ ** Additional return code for dev handler's task_mgmt_fn()
++ *************************************************************/
++
++/* Regular standard actions for the command should be done */
++#define SCST_DEV_TM_NOT_COMPLETED 1
++
++/*************************************************************
++ ** Session initialization phases
++ *************************************************************/
++
++/* Set if session is being initialized */
++#define SCST_SESS_IPH_INITING 0
++
++/* Set if the session is successfully initialized */
++#define SCST_SESS_IPH_SUCCESS 1
++
++/* Set if the session initialization failed */
++#define SCST_SESS_IPH_FAILED 2
++
++/* Set if session is initialized and ready */
++#define SCST_SESS_IPH_READY 3
++
++/*************************************************************
++ ** Session shutdown phases
++ *************************************************************/
++
++/* Set if session is initialized and ready */
++#define SCST_SESS_SPH_READY 0
++
++/* Set if session is shutting down */
++#define SCST_SESS_SPH_SHUTDOWN 1
++
++/* Set if session is shutting down */
++#define SCST_SESS_SPH_UNREG_DONE_CALLING 2
++
++/*************************************************************
++ ** Session's async (atomic) flags
++ *************************************************************/
++
++/* Set if the sess's hw pending work is scheduled */
++#define SCST_SESS_HW_PENDING_WORK_SCHEDULED 0
++
++/*************************************************************
++ ** Cmd's async (atomic) flags
++ *************************************************************/
++
++/* Set if the cmd is aborted and ABORTED sense will be sent as the result */
++#define SCST_CMD_ABORTED 0
++
++/* Set if the cmd is aborted by other initiator */
++#define SCST_CMD_ABORTED_OTHER 1
++
++/* Set if no response should be sent to the target about this cmd */
++#define SCST_CMD_NO_RESP 2
++
++/* Set if the cmd is dead and can be destroyed at any time */
++#define SCST_CMD_CAN_BE_DESTROYED 3
++
++/*
++ * Set if the cmd's device has TAS flag set. Used only when aborted by
++ * other initiator.
++ */
++#define SCST_CMD_DEVICE_TAS 4
++
++/*************************************************************
++ ** Tgt_dev's async. flags (tgt_dev_flags)
++ *************************************************************/
++
++/* Set if tgt_dev has Unit Attention sense */
++#define SCST_TGT_DEV_UA_PENDING 0
++
++/* Set if tgt_dev is RESERVED by another session */
++#define SCST_TGT_DEV_RESERVED 1
++
++/* Set if the corresponding context is atomic */
++#define SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC 5
++#define SCST_TGT_DEV_AFTER_EXEC_ATOMIC 6
++
++#define SCST_TGT_DEV_CLUST_POOL 11
++
++/*************************************************************
++ ** I/O groupping types. Changing them don't forget to change
++ ** the corresponding *_STR values in scst_const.h!
++ *************************************************************/
++
++/*
++ * All initiators with the same name connected to this group will have
++ * shared IO context, for each name own context. All initiators with
++ * different names will have own IO context.
++ */
++#define SCST_IO_GROUPING_AUTO 0
++
++/* All initiators connected to this group will have shared IO context */
++#define SCST_IO_GROUPING_THIS_GROUP_ONLY -1
++
++/* Each initiator connected to this group will have own IO context */
++#define SCST_IO_GROUPING_NEVER -2
++
++/*************************************************************
++ ** Kernel cache creation helper
++ *************************************************************/
++#ifndef KMEM_CACHE
++#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
++ sizeof(struct __struct), __alignof__(struct __struct),\
++ (__flags), NULL, NULL)
++#endif
++
++/*************************************************************
++ ** Vlaid_mask constants for scst_analyze_sense()
++ *************************************************************/
++
++#define SCST_SENSE_KEY_VALID 1
++#define SCST_SENSE_ASC_VALID 2
++#define SCST_SENSE_ASCQ_VALID 4
++
++#define SCST_SENSE_ASCx_VALID (SCST_SENSE_ASC_VALID | \
++ SCST_SENSE_ASCQ_VALID)
++
++#define SCST_SENSE_ALL_VALID (SCST_SENSE_KEY_VALID | \
++ SCST_SENSE_ASC_VALID | \
++ SCST_SENSE_ASCQ_VALID)
++
++/*************************************************************
++ * TYPES
++ *************************************************************/
++
++struct scst_tgt;
++struct scst_session;
++struct scst_cmd;
++struct scst_mgmt_cmd;
++struct scst_device;
++struct scst_tgt_dev;
++struct scst_dev_type;
++struct scst_acg;
++struct scst_acg_dev;
++struct scst_acn;
++struct scst_aen;
++
++/*
++ * SCST uses 64-bit numbers to represent LUN's internally. The value
++ * NO_SUCH_LUN is guaranteed to be different of every valid LUN.
++ */
++#define NO_SUCH_LUN ((uint64_t)-1)
++
++typedef enum dma_data_direction scst_data_direction;
++
++/*
++ * SCST target template: defines target driver's parameters and callback
++ * functions.
++ *
++ * MUST HAVEs define functions that are expected to be defined in order to
++ * work. OPTIONAL says that there is a choice.
++ */
++struct scst_tgt_template {
++ /* public: */
++
++ /*
++ * SG tablesize allows to check whether scatter/gather can be used
++ * or not.
++ */
++ int sg_tablesize;
++
++ /*
++ * True, if this target adapter uses unchecked DMA onto an ISA bus.
++ */
++ unsigned unchecked_isa_dma:1;
++
++ /*
++ * True, if this target adapter can benefit from using SG-vector
++ * clustering (i.e. smaller number of segments).
++ */
++ unsigned use_clustering:1;
++
++ /*
++ * True, if this target adapter doesn't support SG-vector clustering
++ */
++ unsigned no_clustering:1;
++
++ /*
++ * True, if corresponding function supports execution in
++ * the atomic (non-sleeping) context
++ */
++ unsigned xmit_response_atomic:1;
++ unsigned rdy_to_xfer_atomic:1;
++
++ /* True, if this target doesn't need "enabled" attribute */
++ unsigned enabled_attr_not_needed:1;
++
++ /*
++ * The maximum time in seconds cmd can stay inside the target
++ * hardware, i.e. after rdy_to_xfer() and xmit_response(), before
++ * on_hw_pending_cmd_timeout() will be called, if defined.
++ *
++ * In the current implementation a cmd will be aborted in time t
++ * max_hw_pending_time <= t < 2*max_hw_pending_time.
++ */
++ int max_hw_pending_time;
++
++ /*
++ * This function is equivalent to the SCSI
++ * queuecommand. The target should transmit the response
++ * buffer and the status in the scst_cmd struct.
++ * The expectation is that this executing this command is NON-BLOCKING.
++ * If it is blocking, consider to set threads_num to some none 0 number.
++ *
++ * After the response is actually transmitted, the target
++ * should call the scst_tgt_cmd_done() function of the
++ * mid-level, which will allow it to free up the command.
++ * Returns one of the SCST_TGT_RES_* constants.
++ *
++ * Pay attention to "atomic" attribute of the cmd, which can be get
++ * by scst_cmd_atomic(): it is true if the function called in the
++ * atomic (non-sleeping) context.
++ *
++ * MUST HAVE
++ */
++ int (*xmit_response) (struct scst_cmd *cmd);
++
++ /*
++ * This function informs the driver that data
++ * buffer corresponding to the said command have now been
++ * allocated and it is OK to receive data for this command.
++ * This function is necessary because a SCSI target does not
++ * have any control over the commands it receives. Most lower
++ * level protocols have a corresponding function which informs
++ * the initiator that buffers have been allocated e.g., XFER_
++ * RDY in Fibre Channel. After the data is actually received
++ * the low-level driver needs to call scst_rx_data() in order to
++ * continue processing this command.
++ * Returns one of the SCST_TGT_RES_* constants.
++ *
++ * This command is expected to be NON-BLOCKING.
++ * If it is blocking, consider to set threads_num to some none 0 number.
++ *
++ * Pay attention to "atomic" attribute of the cmd, which can be get
++ * by scst_cmd_atomic(): it is true if the function called in the
++ * atomic (non-sleeping) context.
++ *
++ * OPTIONAL
++ */
++ int (*rdy_to_xfer) (struct scst_cmd *cmd);
++
++ /*
++ * Called if cmd stays inside the target hardware, i.e. after
++ * rdy_to_xfer() and xmit_response(), more than max_hw_pending_time
++ * time. The target driver supposed to cleanup this command and
++ * resume cmd's processing.
++ *
++ * OPTIONAL
++ */
++ void (*on_hw_pending_cmd_timeout) (struct scst_cmd *cmd);
++
++ /*
++ * Called to notify the driver that the command is about to be freed.
++ * Necessary, because for aborted commands xmit_response() could not
++ * be called. Could be called on IRQ context.
++ *
++ * OPTIONAL
++ */
++ void (*on_free_cmd) (struct scst_cmd *cmd);
++
++ /*
++ * This function allows target driver to handle data buffer
++ * allocations on its own.
++ *
++ * Target driver doesn't have to always allocate buffer in this
++ * function, but if it decide to do it, it must check that
++ * scst_cmd_get_data_buff_alloced() returns 0, otherwise to avoid
++ * double buffer allocation and memory leaks alloc_data_buf() shall
++ * fail.
++ *
++ * Shall return 0 in case of success or < 0 (preferrably -ENOMEM)
++ * in case of error, or > 0 if the regular SCST allocation should be
++ * done. In case of returning successfully,
++ * scst_cmd->tgt_data_buf_alloced will be set by SCST.
++ *
++ * It is possible that both target driver and dev handler request own
++ * memory allocation. In this case, data will be memcpy() between
++ * buffers, where necessary.
++ *
++ * If allocation in atomic context - cf. scst_cmd_atomic() - is not
++ * desired or fails and consequently < 0 is returned, this function
++ * will be re-called in thread context.
++ *
++ * Please note that the driver will have to handle itself all relevant
++ * details such as scatterlist setup, highmem, freeing the allocated
++ * memory, etc.
++ *
++ * OPTIONAL.
++ */
++ int (*alloc_data_buf) (struct scst_cmd *cmd);
++
++ /*
++ * This function informs the driver that data
++ * buffer corresponding to the said command have now been
++ * allocated and other preprocessing tasks have been done.
++ * A target driver could need to do some actions at this stage.
++ * After the target driver done the needed actions, it shall call
++ * scst_restart_cmd() in order to continue processing this command.
++ * In case of preliminary the command completion, this function will
++ * also be called before xmit_response().
++ *
++ * Called only if the cmd is queued using scst_cmd_init_stage1_done()
++ * instead of scst_cmd_init_done().
++ *
++ * Returns void, the result is expected to be returned using
++ * scst_restart_cmd().
++ *
++ * This command is expected to be NON-BLOCKING.
++ * If it is blocking, consider to set threads_num to some none 0 number.
++ *
++ * Pay attention to "atomic" attribute of the cmd, which can be get
++ * by scst_cmd_atomic(): it is true if the function called in the
++ * atomic (non-sleeping) context.
++ *
++ * OPTIONAL.
++ */
++ void (*preprocessing_done) (struct scst_cmd *cmd);
++
++ /*
++ * This function informs the driver that the said command is about
++ * to be executed.
++ *
++ * Returns one of the SCST_PREPROCESS_* constants.
++ *
++ * This command is expected to be NON-BLOCKING.
++ * If it is blocking, consider to set threads_num to some none 0 number.
++ *
++ * OPTIONAL
++ */
++ int (*pre_exec) (struct scst_cmd *cmd);
++
++ /*
++ * This function informs the driver that all affected by the
++ * corresponding task management function commands have beed completed.
++ * No return value expected.
++ *
++ * This function is expected to be NON-BLOCKING.
++ *
++ * Called without any locks held from a thread context.
++ *
++ * OPTIONAL
++ */
++ void (*task_mgmt_affected_cmds_done) (struct scst_mgmt_cmd *mgmt_cmd);
++
++ /*
++ * This function informs the driver that the corresponding task
++ * management function has been completed, i.e. all the corresponding
++ * commands completed and freed. No return value expected.
++ *
++ * This function is expected to be NON-BLOCKING.
++ *
++ * Called without any locks held from a thread context.
++ *
++ * MUST HAVE if the target supports task management.
++ */
++ void (*task_mgmt_fn_done) (struct scst_mgmt_cmd *mgmt_cmd);
++
++ /*
++ * This function should detect the target adapters that
++ * are present in the system. The function should return a value
++ * >= 0 to signify the number of detected target adapters.
++ * A negative value should be returned whenever there is
++ * an error.
++ *
++ * MUST HAVE
++ */
++ int (*detect) (struct scst_tgt_template *tgt_template);
++
++ /*
++ * This function should free up the resources allocated to the device.
++ * The function should return 0 to indicate successful release
++ * or a negative value if there are some issues with the release.
++ * In the current version the return value is ignored.
++ *
++ * MUST HAVE
++ */
++ int (*release) (struct scst_tgt *tgt);
++
++ /*
++ * This function is used for Asynchronous Event Notifications.
++ *
++ * Returns one of the SCST_AEN_RES_* constants.
++ * After AEN is sent, target driver must call scst_aen_done() and,
++ * optionally, scst_set_aen_delivery_status().
++ *
++ * This function is expected to be NON-BLOCKING, but can sleep.
++ *
++ * This function must be prepared to handle AENs between calls for the
++ * corresponding session of scst_unregister_session() and
++ * unreg_done_fn() callback called or before scst_unregister_session()
++ * returned, if its called in the blocking mode. AENs for such sessions
++ * should be ignored.
++ *
++ * MUST HAVE, if low-level protocol supports AENs.
++ */
++ int (*report_aen) (struct scst_aen *aen);
++
++ /*
++ * This function returns in tr_id the corresponding to sess initiator
++ * port TransporID in the form as it's used by PR commands, see
++ * "Transport Identifiers" in SPC. Space for the initiator port
++ * TransporID must be allocated via kmalloc(). Caller supposed to
++ * kfree() it, when it isn't needed anymore.
++ *
++ * If sess is NULL, this function must return TransportID PROTOCOL
++ * IDENTIFIER of this transport.
++ *
++ * Returns 0 on success or negative error code otherwise.
++ *
++ * SHOULD HAVE, because it's required for Persistent Reservations.
++ */
++ int (*get_initiator_port_transport_id) (struct scst_session *sess,
++ uint8_t **transport_id);
++
++ /*
++ * This function allows to enable or disable particular target.
++ * A disabled target doesn't receive and process any SCSI commands.
++ *
++ * SHOULD HAVE to avoid race when there are connected initiators,
++ * while target not yet completed the initial configuration. In this
++ * case the too early connected initiators would see not those devices,
++ * which they intended to see.
++ *
++ * If you are sure your target driver doesn't need enabling target,
++ * you should set enabled_attr_not_needed in 1.
++ */
++ int (*enable_target) (struct scst_tgt *tgt, bool enable);
++
++ /*
++ * This function shows if particular target is enabled or not.
++ *
++ * SHOULD HAVE, see above why.
++ */
++ bool (*is_target_enabled) (struct scst_tgt *tgt);
++
++ /*
++ * This function adds a virtual target.
++ *
++ * If both add_target and del_target callbacks defined, then this
++ * target driver supposed to support virtual targets. In this case
++ * an "mgmt" entry will be created in the sysfs root for this driver.
++ * The "mgmt" entry will support 2 commands: "add_target" and
++ * "del_target", for which the corresponding callbacks will be called.
++ * Also target driver can define own commands for the "mgmt" entry, see
++ * mgmt_cmd and mgmt_cmd_help below.
++ *
++ * This approach allows uniform targets management to simplify external
++ * management tools like scstadmin. See README for more details.
++ *
++ * Either both add_target and del_target must be defined, or none.
++ *
++ * MUST HAVE if virtual targets are supported.
++ */
++ ssize_t (*add_target) (const char *target_name, char *params);
++
++ /*
++ * This function deletes a virtual target. See comment for add_target
++ * above.
++ *
++ * MUST HAVE if virtual targets are supported.
++ */
++ ssize_t (*del_target) (const char *target_name);
++
++ /*
++ * This function called if not "add_target" or "del_target" command is
++ * sent to the mgmt entry (see comment for add_target above). In this
++ * case the command passed to this function as is in a string form.
++ *
++ * OPTIONAL.
++ */
++ ssize_t (*mgmt_cmd) (char *cmd);
++
++ /*
++ * Should return physical transport version. Used in the corresponding
++ * INQUIRY version descriptor. See SPC for the list of available codes.
++ *
++ * OPTIONAL
++ */
++ uint16_t (*get_phys_transport_version) (struct scst_tgt *tgt);
++
++ /*
++ * Should return SCSI transport version. Used in the corresponding
++ * INQUIRY version descriptor. See SPC for the list of available codes.
++ *
++ * OPTIONAL
++ */
++ uint16_t (*get_scsi_transport_version) (struct scst_tgt *tgt);
++
++ /*
++ * Name of the template. Must be unique to identify
++ * the template. MUST HAVE
++ */
++ const char name[SCST_MAX_NAME];
++
++ /*
++ * Number of additional threads to the pool of dedicated threads.
++ * Used if xmit_response() or rdy_to_xfer() is blocking.
++ * It is the target driver's duty to ensure that not more, than that
++ * number of threads, are blocked in those functions at any time.
++ */
++ int threads_num;
++
++ /* Optional default log flags */
++ const unsigned long default_trace_flags;
++
++ /* Optional pointer to trace flags */
++ unsigned long *trace_flags;
++
++ /* Optional local trace table */
++ struct scst_trace_log *trace_tbl;
++
++ /* Optional local trace table help string */
++ const char *trace_tbl_help;
++
++ /* sysfs attributes, if any */
++ const struct attribute **tgtt_attrs;
++
++ /* sysfs target attributes, if any */
++ const struct attribute **tgt_attrs;
++
++ /* sysfs session attributes, if any */
++ const struct attribute **sess_attrs;
++
++ /* Optional help string for mgmt_cmd commands */
++ const char *mgmt_cmd_help;
++
++ /* List of parameters for add_target command, if any */
++ const char *add_target_parameters;
++
++ /*
++ * List of optional, i.e. which could be added by add_attribute command
++ * and deleted by del_attribute command, sysfs attributes, if any.
++ * Helpful for scstadmin to work correctly.
++ */
++ const char *tgtt_optional_attributes;
++
++ /*
++ * List of optional, i.e. which could be added by add_target_attribute
++ * command and deleted by del_target_attribute command, sysfs
++ * attributes, if any. Helpful for scstadmin to work correctly.
++ */
++ const char *tgt_optional_attributes;
++
++ /** Private, must be inited to 0 by memset() **/
++
++ /* List of targets per template, protected by scst_mutex */
++ struct list_head tgt_list;
++
++ /* List entry of global templates list */
++ struct list_head scst_template_list_entry;
++
++ struct kobject tgtt_kobj; /* kobject for this struct */
++
++ /* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */
++ int tgtt_active_sysfs_works_count;
++
++ /* sysfs release completion */
++ struct completion tgtt_kobj_release_cmpl;
++
++};
++
++/*
++ * Threads pool types. Changing them don't forget to change
++ * the corresponding *_STR values in scst_const.h!
++ */
++enum scst_dev_type_threads_pool_type {
++ /* Each initiator will have dedicated threads pool. */
++ SCST_THREADS_POOL_PER_INITIATOR = 0,
++
++ /* All connected initiators will use shared threads pool */
++ SCST_THREADS_POOL_SHARED,
++
++ /* Invalid value for scst_parse_threads_pool_type() */
++ SCST_THREADS_POOL_TYPE_INVALID,
++};
++
++/*
++ * SCST dev handler template: defines dev handler's parameters and callback
++ * functions.
++ *
++ * MUST HAVEs define functions that are expected to be defined in order to
++ * work. OPTIONAL says that there is a choice.
++ */
++struct scst_dev_type {
++ /* SCSI type of the supported device. MUST HAVE */
++ int type;
++
++ /*
++ * True, if corresponding function supports execution in
++ * the atomic (non-sleeping) context
++ */
++ unsigned parse_atomic:1;
++ unsigned alloc_data_buf_atomic:1;
++ unsigned dev_done_atomic:1;
++
++ /*
++ * Should be true, if exec() is synchronous. This is a hint to SCST core
++ * to optimize commands order management.
++ */
++ unsigned exec_sync:1;
++
++ /*
++ * Should be set if the device wants to receive notification of
++ * Persistent Reservation commands (PR OUT only)
++ * Note: The notification will not be send if the command failed
++ */
++ unsigned pr_cmds_notifications:1;
++
++ /*
++ * Called to parse CDB from the cmd and initialize
++ * cmd->bufflen and cmd->data_direction (both - REQUIRED).
++ *
++ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
++ * if the next default state should be used, or
++ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
++ * context, but requires sleeping, or SCST_CMD_STATE_STOP if the
++ * command should not be further processed for now. In the
++ * SCST_CMD_STATE_NEED_THREAD_CTX case the function
++ * will be recalled in the thread context, where sleeping is allowed.
++ *
++ * Pay attention to "atomic" attribute of the cmd, which can be get
++ * by scst_cmd_atomic(): it is true if the function called in the
++ * atomic (non-sleeping) context.
++ *
++ * MUST HAVE
++ */
++ int (*parse) (struct scst_cmd *cmd);
++
++ /*
++ * This function allows dev handler to handle data buffer
++ * allocations on its own.
++ *
++ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
++ * if the next default state should be used, or
++ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
++ * context, but requires sleeping, or SCST_CMD_STATE_STOP if the
++ * command should not be further processed for now. In the
++ * SCST_CMD_STATE_NEED_THREAD_CTX case the function
++ * will be recalled in the thread context, where sleeping is allowed.
++ *
++ * Pay attention to "atomic" attribute of the cmd, which can be get
++ * by scst_cmd_atomic(): it is true if the function called in the
++ * atomic (non-sleeping) context.
++ *
++ * OPTIONAL
++ */
++ int (*alloc_data_buf) (struct scst_cmd *cmd);
++
++ /*
++ * Called to execute CDB. Useful, for instance, to implement
++ * data caching. The result of CDB execution is reported via
++ * cmd->scst_cmd_done() callback.
++ * Returns:
++ * - SCST_EXEC_COMPLETED - the cmd is done, go to other ones
++ * - SCST_EXEC_NOT_COMPLETED - the cmd should be sent to SCSI
++ * mid-level.
++ *
++ * If this function provides sync execution, you should set
++ * exec_sync flag and consider to setup dedicated threads by
++ * setting threads_num > 0.
++ *
++ * !! If this function is implemented, scst_check_local_events() !!
++ * !! shall be called inside it just before the actual command's !!
++ * !! execution. !!
++ *
++ * OPTIONAL, if not set, the commands will be sent directly to SCSI
++ * device.
++ */
++ int (*exec) (struct scst_cmd *cmd);
++
++ /*
++ * Called to notify dev handler about the result of cmd execution
++ * and perform some post processing. Cmd's fields is_send_status and
++ * resp_data_len should be set by this function, but SCST offers good
++ * defaults.
++ * Returns the command's next state or SCST_CMD_STATE_DEFAULT,
++ * if the next default state should be used, or
++ * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic
++ * context, but requires sleeping. In the last case, the function
++ * will be recalled in the thread context, where sleeping is allowed.
++ *
++ * Pay attention to "atomic" attribute of the cmd, which can be get
++ * by scst_cmd_atomic(): it is true if the function called in the
++ * atomic (non-sleeping) context.
++ */
++ int (*dev_done) (struct scst_cmd *cmd);
++
++ /*
++ * Called to notify dev hander that the command is about to be freed.
++ * Could be called on IRQ context.
++ */
++ void (*on_free_cmd) (struct scst_cmd *cmd);
++
++ /*
++ * Called to execute a task management command.
++ * Returns:
++ * - SCST_MGMT_STATUS_SUCCESS - the command is done with success,
++ * no firther actions required
++ * - The SCST_MGMT_STATUS_* error code if the command is failed and
++ * no further actions required
++ * - SCST_DEV_TM_NOT_COMPLETED - regular standard actions for the
++ * command should be done
++ *
++ * Called without any locks held from a thread context.
++ */
++ int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd,
++ struct scst_tgt_dev *tgt_dev);
++
++ /*
++ * Called when new device is attaching to the dev handler
++ * Returns 0 on success, error code otherwise.
++ */
++ int (*attach) (struct scst_device *dev);
++
++ /* Called when a device is detaching from the dev handler */
++ void (*detach) (struct scst_device *dev);
++
++ /*
++ * Called when new tgt_dev (session) is attaching to the dev handler.
++ * Returns 0 on success, error code otherwise.
++ */
++ int (*attach_tgt) (struct scst_tgt_dev *tgt_dev);
++
++ /* Called when tgt_dev (session) is detaching from the dev handler */
++ void (*detach_tgt) (struct scst_tgt_dev *tgt_dev);
++
++ /*
++ * This function adds a virtual device.
++ *
++ * If both add_device and del_device callbacks defined, then this
++ * dev handler supposed to support adding/deleting virtual devices.
++ * In this case an "mgmt" entry will be created in the sysfs root for
++ * this handler. The "mgmt" entry will support 2 commands: "add_device"
++ * and "del_device", for which the corresponding callbacks will be called.
++ * Also dev handler can define own commands for the "mgmt" entry, see
++ * mgmt_cmd and mgmt_cmd_help below.
++ *
++ * This approach allows uniform devices management to simplify external
++ * management tools like scstadmin. See README for more details.
++ *
++ * Either both add_device and del_device must be defined, or none.
++ *
++ * MUST HAVE if virtual devices are supported.
++ */
++ ssize_t (*add_device) (const char *device_name, char *params);
++
++ /*
++ * This function deletes a virtual device. See comment for add_device
++ * above.
++ *
++ * MUST HAVE if virtual devices are supported.
++ */
++ ssize_t (*del_device) (const char *device_name);
++
++ /*
++ * This function called if not "add_device" or "del_device" command is
++ * sent to the mgmt entry (see comment for add_device above). In this
++ * case the command passed to this function as is in a string form.
++ *
++ * OPTIONAL.
++ */
++ ssize_t (*mgmt_cmd) (char *cmd);
++
++ /*
++ * Name of the dev handler. Must be unique. MUST HAVE.
++ *
++ * It's SCST_MAX_NAME + few more bytes to match scst_user expectations.
++ */
++ char name[SCST_MAX_NAME + 10];
++
++ /*
++ * Number of threads in this handler's devices' threads pools.
++ * If 0 - no threads will be created, if <0 - creation of the threads
++ * pools is prohibited. Also pay attention to threads_pool_type below.
++ */
++ int threads_num;
++
++ /* Threads pool type. Valid only if threads_num > 0. */
++ enum scst_dev_type_threads_pool_type threads_pool_type;
++
++ /* Optional default log flags */
++ const unsigned long default_trace_flags;
++
++ /* Optional pointer to trace flags */
++ unsigned long *trace_flags;
++
++ /* Optional local trace table */
++ struct scst_trace_log *trace_tbl;
++
++ /* Optional local trace table help string */
++ const char *trace_tbl_help;
++
++ /* Optional help string for mgmt_cmd commands */
++ const char *mgmt_cmd_help;
++
++ /* List of parameters for add_device command, if any */
++ const char *add_device_parameters;
++
++ /*
++ * List of optional, i.e. which could be added by add_attribute command
++ * and deleted by del_attribute command, sysfs attributes, if any.
++ * Helpful for scstadmin to work correctly.
++ */
++ const char *devt_optional_attributes;
++
++ /*
++ * List of optional, i.e. which could be added by add_device_attribute
++ * command and deleted by del_device_attribute command, sysfs
++ * attributes, if any. Helpful for scstadmin to work correctly.
++ */
++ const char *dev_optional_attributes;
++
++ /* sysfs attributes, if any */
++ const struct attribute **devt_attrs;
++
++ /* sysfs device attributes, if any */
++ const struct attribute **dev_attrs;
++
++ /* Pointer to dev handler's private data */
++ void *devt_priv;
++
++ /* Pointer to parent dev type in the sysfs hierarchy */
++ struct scst_dev_type *parent;
++
++ struct module *module;
++
++ /** Private, must be inited to 0 by memset() **/
++
++ /* list entry in scst_(virtual_)dev_type_list */
++ struct list_head dev_type_list_entry;
++
++ struct kobject devt_kobj; /* main handlers/driver */
++
++ /* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */
++ int devt_active_sysfs_works_count;
++
++ /* To wait until devt_kobj released */
++ struct completion devt_kobj_release_compl;
++};
++
++/*
++ * An SCST target, analog of SCSI target port.
++ */
++struct scst_tgt {
++ /* List of remote sessions per target, protected by scst_mutex */
++ struct list_head sess_list;
++
++ /* List entry of targets per template (tgts_list) */
++ struct list_head tgt_list_entry;
++
++ struct scst_tgt_template *tgtt; /* corresponding target template */
++
++ struct scst_acg *default_acg; /* default acg for this target */
++
++ struct list_head tgt_acg_list; /* target ACG groups */
++
++ /*
++ * Maximum SG table size. Needed here, since different cards on the
++ * same target template can have different SG table limitations.
++ */
++ int sg_tablesize;
++
++ /* Used for storage of target driver private stuff */
++ void *tgt_priv;
++
++ /*
++ * The following fields used to store and retry cmds if target's
++ * internal queue is full, so the target is unable to accept
++ * the cmd returning QUEUE FULL.
++ * They protected by tgt_lock, where necessary.
++ */
++ bool retry_timer_active;
++ struct timer_list retry_timer;
++ atomic_t finished_cmds;
++ int retry_cmds;
++ spinlock_t tgt_lock;
++ struct list_head retry_cmd_list;
++
++ /* Used to wait until session finished to unregister */
++ wait_queue_head_t unreg_waitQ;
++
++ /* Name of the target */
++ char *tgt_name;
++
++ uint16_t rel_tgt_id;
++
++ /* sysfs release completion */
++ struct completion tgt_kobj_release_cmpl;
++
++ struct kobject tgt_kobj; /* main targets/target kobject */
++ struct kobject *tgt_sess_kobj; /* target/sessions/ */
++ struct kobject *tgt_luns_kobj; /* target/luns/ */
++ struct kobject *tgt_ini_grp_kobj; /* target/ini_groups/ */
++};
++
++/* Hash size and hash fn for hash based lun translation */
++#define TGT_DEV_HASH_SHIFT 5
++#define TGT_DEV_HASH_SIZE (1 << TGT_DEV_HASH_SHIFT)
++#define HASH_VAL(_val) (_val & (TGT_DEV_HASH_SIZE - 1))
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++
++/* Defines extended latency statistics */
++struct scst_ext_latency_stat {
++ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
++ unsigned int processed_cmds_rd;
++ uint64_t min_scst_time_rd, min_tgt_time_rd, min_dev_time_rd;
++ uint64_t max_scst_time_rd, max_tgt_time_rd, max_dev_time_rd;
++
++ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
++ unsigned int processed_cmds_wr;
++ uint64_t min_scst_time_wr, min_tgt_time_wr, min_dev_time_wr;
++ uint64_t max_scst_time_wr, max_tgt_time_wr, max_dev_time_wr;
++};
++
++#define SCST_IO_SIZE_THRESHOLD_SMALL (8*1024)
++#define SCST_IO_SIZE_THRESHOLD_MEDIUM (32*1024)
++#define SCST_IO_SIZE_THRESHOLD_LARGE (128*1024)
++#define SCST_IO_SIZE_THRESHOLD_VERY_LARGE (512*1024)
++
++#define SCST_LATENCY_STAT_INDEX_SMALL 0
++#define SCST_LATENCY_STAT_INDEX_MEDIUM 1
++#define SCST_LATENCY_STAT_INDEX_LARGE 2
++#define SCST_LATENCY_STAT_INDEX_VERY_LARGE 3
++#define SCST_LATENCY_STAT_INDEX_OTHER 4
++#define SCST_LATENCY_STATS_NUM (SCST_LATENCY_STAT_INDEX_OTHER + 1)
++
++#endif /* CONFIG_SCST_MEASURE_LATENCY */
++
++/*
++ * SCST session, analog of SCSI I_T nexus
++ */
++struct scst_session {
++ /*
++ * Initialization phase, one of SCST_SESS_IPH_* constants, protected by
++ * sess_list_lock
++ */
++ int init_phase;
++
++ struct scst_tgt *tgt; /* corresponding target */
++
++ /* Used for storage of target driver private stuff */
++ void *tgt_priv;
++
++ /* session's async flags */
++ unsigned long sess_aflags;
++
++ /*
++ * Hash list of tgt_dev's for this session, protected by scst_mutex
++ * and suspended activity
++ */
++ struct list_head sess_tgt_dev_list_hash[TGT_DEV_HASH_SIZE];
++
++ /*
++ * List of cmds in this session. Protected by sess_list_lock.
++ *
++ * We must always keep commands in the sess list from the
++ * very beginning, because otherwise they can be missed during
++ * TM processing.
++ */
++ struct list_head sess_cmd_list;
++
++ spinlock_t sess_list_lock; /* protects sess_cmd_list, etc */
++
++ atomic_t refcnt; /* get/put counter */
++
++ /*
++ * Alive commands for this session. ToDo: make it part of the common
++ * IO flow control.
++ */
++ atomic_t sess_cmd_count;
++
++ /* Access control for this session and list entry there */
++ struct scst_acg *acg;
++
++ /* Initiator port transport id */
++ uint8_t *transport_id;
++
++ /* List entry for the sessions list inside ACG */
++ struct list_head acg_sess_list_entry;
++
++ struct delayed_work hw_pending_work;
++
++ /* Name of attached initiator */
++ const char *initiator_name;
++
++ /* List entry of sessions per target */
++ struct list_head sess_list_entry;
++
++ /* List entry for the list that keeps session, waiting for the init */
++ struct list_head sess_init_list_entry;
++
++ /*
++ * List entry for the list that keeps session, waiting for the shutdown
++ */
++ struct list_head sess_shut_list_entry;
++
++ /*
++ * Lists of deferred during session initialization commands.
++ * Protected by sess_list_lock.
++ */
++ struct list_head init_deferred_cmd_list;
++ struct list_head init_deferred_mcmd_list;
++
++ /*
++ * Shutdown phase, one of SCST_SESS_SPH_* constants, unprotected.
++ * Async. relating to init_phase, must be a separate variable, because
++ * session could be unregistered before async. registration is finished.
++ */
++ unsigned long shut_phase;
++
++ /* Used if scst_unregister_session() called in wait mode */
++ struct completion *shutdown_compl;
++
++ /* sysfs release completion */
++ struct completion sess_kobj_release_cmpl;
++
++ unsigned int sess_kobj_ready:1;
++
++ struct kobject sess_kobj; /* kobject for this struct */
++
++ /*
++ * Functions and data for user callbacks from scst_register_session()
++ * and scst_unregister_session()
++ */
++ void *reg_sess_data;
++ void (*init_result_fn) (struct scst_session *sess, void *data,
++ int result);
++ void (*unreg_done_fn) (struct scst_session *sess);
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++ /*
++ * Must be the last to allow to work with drivers who don't know
++ * about this config time option.
++ */
++ spinlock_t lat_lock;
++ uint64_t scst_time, tgt_time, dev_time;
++ unsigned int processed_cmds;
++ uint64_t min_scst_time, min_tgt_time, min_dev_time;
++ uint64_t max_scst_time, max_tgt_time, max_dev_time;
++ struct scst_ext_latency_stat sess_latency_stat[SCST_LATENCY_STATS_NUM];
++#endif
++};
++
++/*
++ * SCST_PR_ABORT_ALL TM function helper structure
++ */
++struct scst_pr_abort_all_pending_mgmt_cmds_counter {
++ /*
++ * How many there are pending for this cmd SCST_PR_ABORT_ALL TM
++ * commands.
++ */
++ atomic_t pr_abort_pending_cnt;
++
++ /* Saved completition routine */
++ void (*saved_cmd_done) (struct scst_cmd *cmd, int next_state,
++ enum scst_exec_context pref_context);
++
++ /*
++ * How many there are pending for this cmd SCST_PR_ABORT_ALL TM
++ * commands, which not yet aborted all affected commands and
++ * a completion to signal, when it's done.
++ */
++ atomic_t pr_aborting_cnt;
++ struct completion pr_aborting_cmpl;
++};
++
++/*
++ * Structure to control commands' queuing and threads pool processing the queue
++ */
++struct scst_cmd_threads {
++ spinlock_t cmd_list_lock;
++ struct list_head active_cmd_list; /* commands queue */
++ wait_queue_head_t cmd_list_waitQ;
++
++ struct io_context *io_context; /* IO context of the threads pool */
++ int io_context_refcnt;
++
++ bool io_context_ready;
++
++ /* io_context_mutex protects io_context and io_context_refcnt. */
++ struct mutex io_context_mutex;
++
++ int nr_threads; /* number of processing threads */
++ struct list_head threads_list; /* processing threads */
++
++ struct list_head lists_list_entry;
++};
++
++/*
++ * SCST command, analog of I_T_L_Q nexus or task
++ */
++struct scst_cmd {
++ /* List entry for below *_cmd_threads */
++ struct list_head cmd_list_entry;
++
++ /* Pointer to lists of commands with the lock */
++ struct scst_cmd_threads *cmd_threads;
++
++ atomic_t cmd_ref;
++
++ struct scst_session *sess; /* corresponding session */
++
++ /* Cmd state, one of SCST_CMD_STATE_* constants */
++ int state;
++
++ /*************************************************************
++ ** Cmd's flags
++ *************************************************************/
++
++ /*
++ * Set if expected_sn should be incremented, i.e. cmd was sent
++ * for execution
++ */
++ unsigned int sent_for_exec:1;
++
++ /* Set if the cmd's action is completed */
++ unsigned int completed:1;
++
++ /* Set if we should ignore Unit Attention in scst_check_sense() */
++ unsigned int ua_ignore:1;
++
++ /* Set if cmd is being processed in atomic context */
++ unsigned int atomic:1;
++
++ /* Set if this command was sent in double UA possible state */
++ unsigned int double_ua_possible:1;
++
++ /* Set if this command contains status */
++ unsigned int is_send_status:1;
++
++ /* Set if cmd is being retried */
++ unsigned int retry:1;
++
++ /* Set if cmd is internally generated */
++ unsigned int internal:1;
++
++ /* Set if the device was blocked by scst_check_blocked_dev() */
++ unsigned int unblock_dev:1;
++
++ /* Set if cmd is queued as hw pending */
++ unsigned int cmd_hw_pending:1;
++
++ /*
++ * Set if the target driver wants to alloc data buffers on its own.
++ * In this case alloc_data_buf() must be provided in the target driver
++ * template.
++ */
++ unsigned int tgt_need_alloc_data_buf:1;
++
++ /*
++ * Set by SCST if the custom data buffer allocation by the target driver
++ * succeeded.
++ */
++ unsigned int tgt_data_buf_alloced:1;
++
++ /* Set if custom data buffer allocated by dev handler */
++ unsigned int dh_data_buf_alloced:1;
++
++ /* Set if the target driver called scst_set_expected() */
++ unsigned int expected_values_set:1;
++
++ /*
++ * Set if the SG buffer was modified by scst_adjust_sg()
++ */
++ unsigned int sg_buff_modified:1;
++
++ /*
++ * Set if cmd buffer was vmallocated and copied from more
++ * then one sg chunk
++ */
++ unsigned int sg_buff_vmallocated:1;
++
++ /*
++ * Set if scst_cmd_init_stage1_done() called and the target
++ * want that preprocessing_done() will be called
++ */
++ unsigned int preprocessing_only:1;
++
++ /* Set if cmd's SN was set */
++ unsigned int sn_set:1;
++
++ /* Set if hq_cmd_count was incremented */
++ unsigned int hq_cmd_inced:1;
++
++ /*
++ * Set if scst_cmd_init_stage1_done() called and the target wants
++ * that the SN for the cmd won't be assigned until scst_restart_cmd()
++ */
++ unsigned int set_sn_on_restart_cmd:1;
++
++ /* Set if the cmd's must not use sgv cache for data buffer */
++ unsigned int no_sgv:1;
++
++ /*
++ * Set if target driver may need to call dma_sync_sg() or similar
++ * function before transferring cmd' data to the target device
++ * via DMA.
++ */
++ unsigned int may_need_dma_sync:1;
++
++ /* Set if the cmd was done or aborted out of its SN */
++ unsigned int out_of_sn:1;
++
++ /* Set if increment expected_sn in cmd->scst_cmd_done() */
++ unsigned int inc_expected_sn_on_done:1;
++
++ /* Set if tgt_sn field is valid */
++ unsigned int tgt_sn_set:1;
++
++ /* Set if any direction residual is possible */
++ unsigned int resid_possible:1;
++
++ /* Set if cmd is done */
++ unsigned int done:1;
++
++ /* Set if cmd is finished */
++ unsigned int finished:1;
++
++#ifdef CONFIG_SCST_DEBUG_TM
++ /* Set if the cmd was delayed by task management debugging code */
++ unsigned int tm_dbg_delayed:1;
++
++ /* Set if the cmd must be ignored by task management debugging code */
++ unsigned int tm_dbg_immut:1;
++#endif
++
++ /**************************************************************/
++
++ /* cmd's async flags */
++ unsigned long cmd_flags;
++
++ /* Keeps status of cmd's status/data delivery to remote initiator */
++ int delivery_status;
++
++ struct scst_tgt_template *tgtt; /* to save extra dereferences */
++ struct scst_tgt *tgt; /* to save extra dereferences */
++ struct scst_device *dev; /* to save extra dereferences */
++
++ struct scst_tgt_dev *tgt_dev; /* corresponding device for this cmd */
++
++ uint64_t lun; /* LUN for this cmd */
++
++ unsigned long start_time;
++
++ /* List entry for tgt_dev's SN related lists */
++ struct list_head sn_cmd_list_entry;
++
++ /* Cmd's serial number, used to execute cmd's in order of arrival */
++ unsigned int sn;
++
++ /* The corresponding sn_slot in tgt_dev->sn_slots */
++ atomic_t *sn_slot;
++
++ /* List entry for sess's sess_cmd_list */
++ struct list_head sess_cmd_list_entry;
++
++ /*
++ * Used to found the cmd by scst_find_cmd_by_tag(). Set by the
++ * target driver on the cmd's initialization time
++ */
++ uint64_t tag;
++
++ uint32_t tgt_sn; /* SN set by target driver (for TM purposes) */
++
++ /* CDB and its len */
++ uint8_t cdb[SCST_MAX_CDB_SIZE];
++ unsigned short cdb_len;
++ unsigned short ext_cdb_len;
++ uint8_t *ext_cdb;
++
++ enum scst_cdb_flags op_flags;
++ const char *op_name;
++
++ enum scst_cmd_queue_type queue_type;
++
++ int timeout; /* CDB execution timeout in seconds */
++ int retries; /* Amount of retries that will be done by SCSI mid-level */
++
++ /* SCSI data direction, one of SCST_DATA_* constants */
++ scst_data_direction data_direction;
++
++ /* Remote initiator supplied values, if any */
++ scst_data_direction expected_data_direction;
++ int expected_transfer_len;
++ int expected_out_transfer_len; /* for bidi writes */
++
++ /*
++ * Cmd data length. Could be different from bufflen for commands like
++ * VERIFY, which transfer different amount of data (if any), than
++ * processed.
++ */
++ int data_len;
++
++ /* Completition routine */
++ void (*scst_cmd_done) (struct scst_cmd *cmd, int next_state,
++ enum scst_exec_context pref_context);
++
++ struct sgv_pool_obj *sgv; /* sgv object */
++ int bufflen; /* cmd buffer length */
++ struct scatterlist *sg; /* cmd data buffer SG vector */
++ int sg_cnt; /* SG segments count */
++
++ /*
++ * Response data length in data buffer. Must not be set
++ * directly, use scst_set_resp_data_len() for that.
++ */
++ int resp_data_len;
++
++ /*
++ * Response data length adjusted on residual, i.e.
++ * min(expected_len, resp_len), if expected len set.
++ */
++ int adjusted_resp_data_len;
++
++ /*
++ * Data length to write, i.e. transfer from the initiator. Might be
++ * different from (out_)bufflen, if the initiator asked too big or too
++ * small expected(_out_)transfer_len.
++ */
++ int write_len;
++
++ /*
++ * Write sg and sg_cnt to point out either on sg/sg_cnt, or on
++ * out_sg/out_sg_cnt.
++ */
++ struct scatterlist **write_sg;
++ int *write_sg_cnt;
++
++ /* scst_get_sg_buf_[first,next]() support */
++ int get_sg_buf_entry_num;
++
++ /* Bidirectional transfers support */
++ int out_bufflen; /* WRITE buffer length */
++ struct sgv_pool_obj *out_sgv; /* WRITE sgv object */
++ struct scatterlist *out_sg; /* WRITE data buffer SG vector */
++ int out_sg_cnt; /* WRITE SG segments count */
++
++ /*
++ * Used if both target driver and dev handler request own memory
++ * allocation. In other cases, both are equal to sg and sg_cnt
++ * correspondingly.
++ *
++ * If target driver requests own memory allocations, it MUST use
++ * functions scst_cmd_get_tgt_sg*() to get sg and sg_cnt! Otherwise,
++ * it may use functions scst_cmd_get_sg*().
++ */
++ struct scatterlist *tgt_sg;
++ int tgt_sg_cnt;
++ struct scatterlist *tgt_out_sg; /* bidirectional */
++ int tgt_out_sg_cnt; /* bidirectional */
++
++ /*
++ * The status fields in case of errors must be set using
++ * scst_set_cmd_error_status()!
++ */
++ uint8_t status; /* status byte from target device */
++ uint8_t msg_status; /* return status from host adapter itself */
++ uint8_t host_status; /* set by low-level driver to indicate status */
++ uint8_t driver_status; /* set by mid-level */
++
++ uint8_t *sense; /* pointer to sense buffer */
++ unsigned short sense_valid_len; /* length of valid sense data */
++ unsigned short sense_buflen; /* length of the sense buffer, if any */
++
++ /* Start time when cmd was sent to rdy_to_xfer() or xmit_response() */
++ unsigned long hw_pending_start;
++
++ /* Used for storage of target driver private stuff */
++ void *tgt_priv;
++
++ /* Used for storage of dev handler private stuff */
++ void *dh_priv;
++
++ /* Used to restore sg if it was modified by scst_adjust_sg() */
++ struct scatterlist *orig_sg;
++ int *p_orig_sg_cnt;
++ int orig_sg_cnt, orig_sg_entry, orig_entry_len;
++
++ /* Used to retry commands in case of double UA */
++ int dbl_ua_orig_resp_data_len, dbl_ua_orig_data_direction;
++
++ /*
++ * List of the corresponding mgmt cmds, if any. Protected by
++ * sess_list_lock.
++ */
++ struct list_head mgmt_cmd_list;
++
++ /* List entry for dev's blocked_cmd_list */
++ struct list_head blocked_cmd_list_entry;
++
++ /* Counter of the corresponding SCST_PR_ABORT_ALL TM commands */
++ struct scst_pr_abort_all_pending_mgmt_cmds_counter *pr_abort_counter;
++
++ struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++ /*
++ * Must be the last to allow to work with drivers who don't know
++ * about this config time option.
++ */
++ uint64_t start, curr_start, parse_time, alloc_buf_time;
++ uint64_t restart_waiting_time, rdy_to_xfer_time;
++ uint64_t pre_exec_time, exec_time, dev_done_time;
++ uint64_t xmit_time, tgt_on_free_time, dev_on_free_time;
++#endif
++};
++
++/*
++ * Parameters for SCST management commands
++ */
++struct scst_rx_mgmt_params {
++ int fn;
++ uint64_t tag;
++ const uint8_t *lun;
++ int lun_len;
++ uint32_t cmd_sn;
++ int atomic;
++ void *tgt_priv;
++ unsigned char tag_set;
++ unsigned char lun_set;
++ unsigned char cmd_sn_set;
++};
++
++/*
++ * A stub structure to link an management command and affected regular commands
++ */
++struct scst_mgmt_cmd_stub {
++ struct scst_mgmt_cmd *mcmd;
++
++ /* List entry in cmd->mgmt_cmd_list */
++ struct list_head cmd_mgmt_cmd_list_entry;
++
++ /* Set if the cmd was counted in mcmd->cmd_done_wait_count */
++ unsigned int done_counted:1;
++
++ /* Set if the cmd was counted in mcmd->cmd_finish_wait_count */
++ unsigned int finish_counted:1;
++};
++
++/*
++ * SCST task management structure
++ */
++struct scst_mgmt_cmd {
++ /* List entry for *_mgmt_cmd_list */
++ struct list_head mgmt_cmd_list_entry;
++
++ struct scst_session *sess;
++
++ /* Mgmt cmd state, one of SCST_MCMD_STATE_* constants */
++ int state;
++
++ int fn; /* task management function */
++
++ /* Set if device(s) should be unblocked after mcmd's finish */
++ unsigned int needs_unblocking:1;
++ unsigned int lun_set:1; /* set, if lun field is valid */
++ unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */
++
++ /*
++ * Number of commands to finish before sending response,
++ * protected by scst_mcmd_lock
++ */
++ int cmd_finish_wait_count;
++
++ /*
++ * Number of commands to complete (done) before resetting reservation,
++ * protected by scst_mcmd_lock
++ */
++ int cmd_done_wait_count;
++
++ /* Number of completed commands, protected by scst_mcmd_lock */
++ int completed_cmd_count;
++
++ uint64_t lun; /* LUN for this mgmt cmd */
++ /* or (and for iSCSI) */
++ uint64_t tag; /* tag of the corresponding cmd */
++
++ uint32_t cmd_sn; /* affected command's highest SN */
++
++ /* corresponding cmd (to be aborted, found by tag) */
++ struct scst_cmd *cmd_to_abort;
++
++ /* corresponding device for this mgmt cmd (found by lun) */
++ struct scst_tgt_dev *mcmd_tgt_dev;
++
++ /* completition status, one of the SCST_MGMT_STATUS_* constants */
++ int status;
++
++ /* Used for storage of target driver private stuff or origin PR cmd */
++ union {
++ void *tgt_priv;
++ struct scst_cmd *origin_pr_cmd;
++ };
++};
++
++/*
++ * Persistent reservations registrant
++ */
++struct scst_dev_registrant {
++ uint8_t *transport_id;
++ uint16_t rel_tgt_id;
++ __be64 key;
++
++ /* tgt_dev (I_T nexus) for this registrant, if any */
++ struct scst_tgt_dev *tgt_dev;
++
++ /* List entry for dev_registrants_list */
++ struct list_head dev_registrants_list_entry;
++
++ /* 2 auxiliary fields used to rollback changes for errors, etc. */
++ struct list_head aux_list_entry;
++ __be64 rollback_key;
++};
++
++/*
++ * SCST device
++ */
++struct scst_device {
++ unsigned short type; /* SCSI type of the device */
++
++ /*************************************************************
++ ** Dev's flags. Updates serialized by dev_lock or suspended
++ ** activity
++ *************************************************************/
++
++ /* Set if dev is RESERVED */
++ unsigned short dev_reserved:1;
++
++ /* Set if double reset UA is possible */
++ unsigned short dev_double_ua_possible:1;
++
++ /* If set, dev is read only */
++ unsigned short rd_only:1;
++
++ /**************************************************************/
++
++ /*************************************************************
++ ** Dev's control mode page related values. Updates serialized
++ ** by scst_block_dev(). Modified independently to the above and
++ ** below fields, hence the alignment.
++ *************************************************************/
++
++ unsigned int queue_alg:4 __attribute__((aligned(sizeof(long))));
++ unsigned int tst:3;
++ unsigned int tas:1;
++ unsigned int swp:1;
++ unsigned int d_sense:1;
++
++ /*
++ * Set if device implements own ordered commands management. If not set
++ * and queue_alg is SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER,
++ * expected_sn will be incremented only after commands finished.
++ */
++ unsigned int has_own_order_mgmt:1;
++
++ /**************************************************************/
++
++ /*
++ * How many times device was blocked for new cmds execution.
++ * Protected by dev_lock
++ */
++ int block_count;
++
++ /* How many cmds alive on this dev */
++ atomic_t dev_cmd_count;
++
++ /*
++ * Set if dev is persistently reserved. Protected by dev_pr_mutex.
++ * Modified independently to the above field, hence the alignment.
++ */
++ unsigned int pr_is_set:1 __attribute__((aligned(sizeof(long))));
++
++ /*
++ * Set if there is a thread changing or going to change PR state(s).
++ * Protected by dev_pr_mutex.
++ */
++ unsigned int pr_writer_active:1;
++
++ /*
++ * How many threads are checking commands for PR allowance. Used to
++ * implement lockless read-only fast path.
++ */
++ atomic_t pr_readers_count;
++
++ struct scst_dev_type *handler; /* corresponding dev handler */
++
++ /* Used for storage of dev handler private stuff */
++ void *dh_priv;
++
++ /* Corresponding real SCSI device, could be NULL for virtual devices */
++ struct scsi_device *scsi_dev;
++
++ /* List of commands with lock, if dedicated threads are used */
++ struct scst_cmd_threads dev_cmd_threads;
++
++ /* Memory limits for this device */
++ struct scst_mem_lim dev_mem_lim;
++
++ /* How many write cmds alive on this dev. Temporary, ToDo */
++ atomic_t write_cmd_count;
++
++ /*************************************************************
++ ** Persistent reservation fields. Protected by dev_pr_mutex.
++ *************************************************************/
++
++ /*
++ * True if persist through power loss is activated. Modified
++ * independently to the above field, hence the alignment.
++ */
++ unsigned short pr_aptpl:1 __attribute__((aligned(sizeof(long))));
++
++ /* Persistent reservation type */
++ uint8_t pr_type;
++
++ /* Persistent reservation scope */
++ uint8_t pr_scope;
++
++ /* Mutex to protect PR operations */
++ struct mutex dev_pr_mutex;
++
++ /* Persistent reservation generation value */
++ uint32_t pr_generation;
++
++ /* Reference to registrant - persistent reservation holder */
++ struct scst_dev_registrant *pr_holder;
++
++ /* List of dev's registrants */
++ struct list_head dev_registrants_list;
++
++ /*
++ * Count of connected tgt_devs from transports, which don't support
++ * PRs, i.e. don't have get_initiator_port_transport_id(). Protected
++ * by scst_mutex.
++ */
++ int not_pr_supporting_tgt_devs_num;
++
++ /* Persist through power loss files */
++ char *pr_file_name;
++ char *pr_file_name1;
++
++ /**************************************************************/
++
++ spinlock_t dev_lock; /* device lock */
++
++ struct list_head blocked_cmd_list; /* protected by dev_lock */
++
++ /* A list entry used during TM, protected by scst_mutex */
++ struct list_head tm_dev_list_entry;
++
++ /* Virtual device internal ID */
++ int virt_id;
++
++ /* Pointer to virtual device name, for convenience only */
++ char *virt_name;
++
++ /* List entry in global devices list */
++ struct list_head dev_list_entry;
++
++ /*
++ * List of tgt_dev's, one per session, protected by scst_mutex or
++ * dev_lock for reads and both for writes
++ */
++ struct list_head dev_tgt_dev_list;
++
++ /* List of acg_dev's, one per acg, protected by scst_mutex */
++ struct list_head dev_acg_dev_list;
++
++ /* Number of threads in the device's threads pools */
++ int threads_num;
++
++ /* Threads pool type of the device. Valid only if threads_num > 0. */
++ enum scst_dev_type_threads_pool_type threads_pool_type;
++
++ /* sysfs release completion */
++ struct completion dev_kobj_release_cmpl;
++
++ struct kobject dev_kobj; /* kobject for this struct */
++ struct kobject *dev_exp_kobj; /* exported groups */
++
++ /* Export number in the dev's sysfs list. Protected by scst_mutex */
++ int dev_exported_lun_num;
++};
++
++/*
++ * Used to store threads local tgt_dev specific data
++ */
++struct scst_thr_data_hdr {
++ /* List entry in tgt_dev->thr_data_list */
++ struct list_head thr_data_list_entry;
++ struct task_struct *owner_thr; /* the owner thread */
++ atomic_t ref;
++ /* Function that will be called on the tgt_dev destruction */
++ void (*free_fn) (struct scst_thr_data_hdr *data);
++};
++
++/*
++ * Used to clearly dispose async io_context
++ */
++struct scst_async_io_context_keeper {
++ struct kref aic_keeper_kref;
++ bool aic_ready;
++ struct io_context *aic;
++ struct task_struct *aic_keeper_thr;
++ wait_queue_head_t aic_keeper_waitQ;
++};
++
++/*
++ * Used to store per-session specific device information, analog of
++ * SCSI I_T_L nexus.
++ */
++struct scst_tgt_dev {
++ /* List entry in sess->sess_tgt_dev_list_hash */
++ struct list_head sess_tgt_dev_list_entry;
++
++ struct scst_device *dev; /* to save extra dereferences */
++ uint64_t lun; /* to save extra dereferences */
++
++ gfp_t gfp_mask;
++ struct sgv_pool *pool;
++ int max_sg_cnt;
++
++ /*
++ * Tgt_dev's async flags. Modified independently to the neighbour
++ * fields.
++ */
++ unsigned long tgt_dev_flags;
++
++ /* Used for storage of dev handler private stuff */
++ void *dh_priv;
++
++ /* How many cmds alive on this dev in this session */
++ atomic_t tgt_dev_cmd_count;
++
++ /*
++ * Used to execute cmd's in order of arrival, honoring SCSI task
++ * attributes.
++ *
++ * Protected by sn_lock, except expected_sn, which is protected by
++ * itself. Curr_sn must have the same size as expected_sn to
++ * overflow simultaneously.
++ */
++ int def_cmd_count;
++ spinlock_t sn_lock;
++ unsigned int expected_sn;
++ unsigned int curr_sn;
++ int hq_cmd_count;
++ struct list_head deferred_cmd_list;
++ struct list_head skipped_sn_list;
++
++ /*
++ * Set if the prev cmd was ORDERED. Size and, hence, alignment must
++ * allow unprotected modifications independently to the neighbour fields.
++ */
++ unsigned long prev_cmd_ordered;
++
++ int num_free_sn_slots; /* if it's <0, then all slots are busy */
++ atomic_t *cur_sn_slot;
++ atomic_t sn_slots[15];
++
++ /* List of scst_thr_data_hdr and lock */
++ spinlock_t thr_data_lock;
++ struct list_head thr_data_list;
++
++ /* Pointer to lists of commands with the lock */
++ struct scst_cmd_threads *active_cmd_threads;
++
++ /* Union to save some CPU cache footprint */
++ union {
++ struct {
++ /* Copy to save fast path dereference */
++ struct io_context *async_io_context;
++
++ struct scst_async_io_context_keeper *aic_keeper;
++ };
++
++ /* Lists of commands with lock, if dedicated threads are used */
++ struct scst_cmd_threads tgt_dev_cmd_threads;
++ };
++
++ spinlock_t tgt_dev_lock; /* per-session device lock */
++
++ /* List of UA's for this device, protected by tgt_dev_lock */
++ struct list_head UA_list;
++
++ struct scst_session *sess; /* corresponding session */
++ struct scst_acg_dev *acg_dev; /* corresponding acg_dev */
++
++ /* Reference to registrant to find quicker */
++ struct scst_dev_registrant *registrant;
++
++ /* List entry in dev->dev_tgt_dev_list */
++ struct list_head dev_tgt_dev_list_entry;
++
++ /* Internal tmp list entry */
++ struct list_head extra_tgt_dev_list_entry;
++
++ /* Set if INQUIRY DATA HAS CHANGED UA is needed */
++ unsigned int inq_changed_ua_needed:1;
++
++ /*
++ * Stored Unit Attention sense and its length for possible
++ * subsequent REQUEST SENSE. Both protected by tgt_dev_lock.
++ */
++ unsigned short tgt_dev_valid_sense_len;
++ uint8_t tgt_dev_sense[SCST_SENSE_BUFFERSIZE];
++
++ /* sysfs release completion */
++ struct completion tgt_dev_kobj_release_cmpl;
++
++ struct kobject tgt_dev_kobj; /* kobject for this struct */
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++ /*
++ * Must be the last to allow to work with drivers who don't know
++ * about this config time option.
++ *
++ * Protected by sess->lat_lock.
++ */
++ uint64_t scst_time, tgt_time, dev_time;
++ unsigned int processed_cmds;
++ struct scst_ext_latency_stat dev_latency_stat[SCST_LATENCY_STATS_NUM];
++#endif
++};
++
++/*
++ * Used to store ACG-specific device information, like LUN
++ */
++struct scst_acg_dev {
++ struct scst_device *dev; /* corresponding device */
++
++ uint64_t lun; /* device's LUN in this acg */
++
++ /* If set, the corresponding LU is read only */
++ unsigned int rd_only:1;
++
++ struct scst_acg *acg; /* parent acg */
++
++ /* List entry in dev->dev_acg_dev_list */
++ struct list_head dev_acg_dev_list_entry;
++
++ /* List entry in acg->acg_dev_list */
++ struct list_head acg_dev_list_entry;
++
++ /* kobject for this structure */
++ struct kobject acg_dev_kobj;
++
++ /* sysfs release completion */
++ struct completion acg_dev_kobj_release_cmpl;
++
++ /* Name of the link to the corresponding LUN */
++ char acg_dev_link_name[20];
++};
++
++/*
++ * ACG - access control group. Used to store group related
++ * control information.
++ */
++struct scst_acg {
++ /* Owner target */
++ struct scst_tgt *tgt;
++
++ /* List of acg_dev's in this acg, protected by scst_mutex */
++ struct list_head acg_dev_list;
++
++ /* List of attached sessions, protected by scst_mutex */
++ struct list_head acg_sess_list;
++
++ /* List of attached acn's, protected by scst_mutex */
++ struct list_head acn_list;
++
++ /* List entry in acg_lists */
++ struct list_head acg_list_entry;
++
++ /* Name of this acg */
++ const char *acg_name;
++
++ /* Type of I/O initiators groupping */
++ int acg_io_grouping_type;
++
++ unsigned int tgt_acg:1;
++
++ /* sysfs release completion */
++ struct completion acg_kobj_release_cmpl;
++
++ /* kobject for this structure */
++ struct kobject acg_kobj;
++
++ struct kobject *luns_kobj;
++ struct kobject *initiators_kobj;
++
++ unsigned int addr_method;
++};
++
++/*
++ * ACN - access control name. Used to store names, by which
++ * incoming sessions will be assigned to appropriate ACG.
++ */
++struct scst_acn {
++ struct scst_acg *acg; /* owner ACG */
++
++ const char *name; /* initiator's name */
++
++ /* List entry in acg->acn_list */
++ struct list_head acn_list_entry;
++
++ /* sysfs file attributes */
++ struct kobj_attribute *acn_attr;
++};
++
++/*
++ * Used to store per-session UNIT ATTENTIONs
++ */
++struct scst_tgt_dev_UA {
++ /* List entry in tgt_dev->UA_list */
++ struct list_head UA_list_entry;
++
++ /* Set if UA is global for session */
++ unsigned short global_UA:1;
++
++ /* Unit Attention valid sense len */
++ unsigned short UA_valid_sense_len;
++ /* Unit Attention sense buf */
++ uint8_t UA_sense_buffer[SCST_SENSE_BUFFERSIZE];
++};
++
++/* Used to deliver AENs */
++struct scst_aen {
++ int event_fn; /* AEN fn */
++
++ struct scst_session *sess; /* corresponding session */
++ __be64 lun; /* corresponding LUN in SCSI form */
++
++ union {
++ /* SCSI AEN data */
++ struct {
++ int aen_sense_len;
++ uint8_t aen_sense[SCST_STANDARD_SENSE_LEN];
++ };
++ };
++
++ /* Keeps status of AEN's delivery to remote initiator */
++ int delivery_status;
++};
++
++#ifndef smp_mb__after_set_bit
++/* There is no smp_mb__after_set_bit() in the kernel */
++#define smp_mb__after_set_bit() smp_mb()
++#endif
++
++/*
++ * Registers target template.
++ * Returns 0 on success or appropriate error code otherwise.
++ */
++int __scst_register_target_template(struct scst_tgt_template *vtt,
++ const char *version);
++static inline int scst_register_target_template(struct scst_tgt_template *vtt)
++{
++ return __scst_register_target_template(vtt, SCST_INTERFACE_VERSION);
++}
++
++/*
++ * Registers target template, non-GPL version.
++ * Returns 0 on success or appropriate error code otherwise.
++ *
++ * Note: *vtt must be static!
++ */
++int __scst_register_target_template_non_gpl(struct scst_tgt_template *vtt,
++ const char *version);
++static inline int scst_register_target_template_non_gpl(
++ struct scst_tgt_template *vtt)
++{
++ return __scst_register_target_template_non_gpl(vtt,
++ SCST_INTERFACE_VERSION);
++}
++
++void scst_unregister_target_template(struct scst_tgt_template *vtt);
++
++struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
++ const char *target_name);
++void scst_unregister_target(struct scst_tgt *tgt);
++
++struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
++ const char *initiator_name, void *tgt_priv, void *result_fn_data,
++ void (*result_fn) (struct scst_session *sess, void *data, int result));
++struct scst_session *scst_register_session_non_gpl(struct scst_tgt *tgt,
++ const char *initiator_name, void *tgt_priv);
++void scst_unregister_session(struct scst_session *sess, int wait,
++ void (*unreg_done_fn) (struct scst_session *sess));
++void scst_unregister_session_non_gpl(struct scst_session *sess);
++
++int __scst_register_dev_driver(struct scst_dev_type *dev_type,
++ const char *version);
++static inline int scst_register_dev_driver(struct scst_dev_type *dev_type)
++{
++ return __scst_register_dev_driver(dev_type, SCST_INTERFACE_VERSION);
++}
++void scst_unregister_dev_driver(struct scst_dev_type *dev_type);
++
++int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
++ const char *version);
++/*
++ * Registers dev handler driver for virtual devices (eg VDISK).
++ * Returns 0 on success or appropriate error code otherwise.
++ */
++static inline int scst_register_virtual_dev_driver(
++ struct scst_dev_type *dev_type)
++{
++ return __scst_register_virtual_dev_driver(dev_type,
++ SCST_INTERFACE_VERSION);
++}
++
++void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type);
++
++bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name);
++
++struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
++ const uint8_t *lun, int lun_len, const uint8_t *cdb,
++ unsigned int cdb_len, int atomic);
++void scst_cmd_init_done(struct scst_cmd *cmd,
++ enum scst_exec_context pref_context);
++
++/*
++ * Notifies SCST that the driver finished the first stage of the command
++ * initialization, and the command is ready for execution, but after
++ * SCST done the command's preprocessing preprocessing_done() function
++ * should be called. The second argument sets preferred command execition
++ * context. See SCST_CONTEXT_* constants for details.
++ *
++ * See comment for scst_cmd_init_done() for the serialization requirements.
++ */
++static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd,
++ enum scst_exec_context pref_context, int set_sn)
++{
++ cmd->preprocessing_only = 1;
++ cmd->set_sn_on_restart_cmd = !set_sn;
++ scst_cmd_init_done(cmd, pref_context);
++}
++
++void scst_restart_cmd(struct scst_cmd *cmd, int status,
++ enum scst_exec_context pref_context);
++
++void scst_rx_data(struct scst_cmd *cmd, int status,
++ enum scst_exec_context pref_context);
++
++void scst_tgt_cmd_done(struct scst_cmd *cmd,
++ enum scst_exec_context pref_context);
++
++int scst_rx_mgmt_fn(struct scst_session *sess,
++ const struct scst_rx_mgmt_params *params);
++
++/*
++ * Creates new management command using tag and sends it for execution.
++ * Can be used for SCST_ABORT_TASK only.
++ * Must not be called in parallel with scst_unregister_session() for the
++ * same sess. Returns 0 for success, error code otherwise.
++ *
++ * Obsolete in favor of scst_rx_mgmt_fn()
++ */
++static inline int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn,
++ uint64_t tag, int atomic, void *tgt_priv)
++{
++ struct scst_rx_mgmt_params params;
++
++ BUG_ON(fn != SCST_ABORT_TASK);
++
++ memset(&params, 0, sizeof(params));
++ params.fn = fn;
++ params.tag = tag;
++ params.tag_set = 1;
++ params.atomic = atomic;
++ params.tgt_priv = tgt_priv;
++ return scst_rx_mgmt_fn(sess, &params);
++}
++
++/*
++ * Creates new management command using LUN and sends it for execution.
++ * Currently can be used for any fn, except SCST_ABORT_TASK.
++ * Must not be called in parallel with scst_unregister_session() for the
++ * same sess. Returns 0 for success, error code otherwise.
++ *
++ * Obsolete in favor of scst_rx_mgmt_fn()
++ */
++static inline int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn,
++ const uint8_t *lun, int lun_len, int atomic, void *tgt_priv)
++{
++ struct scst_rx_mgmt_params params;
++
++ BUG_ON(fn == SCST_ABORT_TASK);
++
++ memset(&params, 0, sizeof(params));
++ params.fn = fn;
++ params.lun = lun;
++ params.lun_len = lun_len;
++ params.lun_set = 1;
++ params.atomic = atomic;
++ params.tgt_priv = tgt_priv;
++ return scst_rx_mgmt_fn(sess, &params);
++}
++
++int scst_get_cdb_info(struct scst_cmd *cmd);
++
++int scst_set_cmd_error_status(struct scst_cmd *cmd, int status);
++int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq);
++void scst_set_busy(struct scst_cmd *cmd);
++
++void scst_check_convert_sense(struct scst_cmd *cmd);
++
++void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq);
++
++void scst_capacity_data_changed(struct scst_device *dev);
++
++struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag);
++struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data,
++ int (*cmp_fn) (struct scst_cmd *cmd,
++ void *data));
++
++enum dma_data_direction scst_to_dma_dir(int scst_dir);
++enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir);
++
++/*
++ * Returns true, if cmd's CDB is fully locally handled by SCST and false
++ * otherwise. Dev handlers parse() and dev_done() not called for such commands.
++ */
++static inline bool scst_is_cmd_fully_local(struct scst_cmd *cmd)
++{
++ return (cmd->op_flags & SCST_FULLY_LOCAL_CMD) != 0;
++}
++
++/*
++ * Returns true, if cmd's CDB is locally handled by SCST and
++ * false otherwise.
++ */
++static inline bool scst_is_cmd_local(struct scst_cmd *cmd)
++{
++ return (cmd->op_flags & SCST_LOCAL_CMD) != 0;
++}
++
++/* Returns true, if cmd can deliver UA */
++static inline bool scst_is_ua_command(struct scst_cmd *cmd)
++{
++ return (cmd->op_flags & SCST_SKIP_UA) == 0;
++}
++
++int scst_register_virtual_device(struct scst_dev_type *dev_handler,
++ const char *dev_name);
++void scst_unregister_virtual_device(int id);
++
++/*
++ * Get/Set functions for tgt's sg_tablesize
++ */
++static inline int scst_tgt_get_sg_tablesize(struct scst_tgt *tgt)
++{
++ return tgt->sg_tablesize;
++}
++
++static inline void scst_tgt_set_sg_tablesize(struct scst_tgt *tgt, int val)
++{
++ tgt->sg_tablesize = val;
++}
++
++/*
++ * Get/Set functions for tgt's target private data
++ */
++static inline void *scst_tgt_get_tgt_priv(struct scst_tgt *tgt)
++{
++ return tgt->tgt_priv;
++}
++
++static inline void scst_tgt_set_tgt_priv(struct scst_tgt *tgt, void *val)
++{
++ tgt->tgt_priv = val;
++}
++
++void scst_update_hw_pending_start(struct scst_cmd *cmd);
++
++/*
++ * Get/Set functions for session's target private data
++ */
++static inline void *scst_sess_get_tgt_priv(struct scst_session *sess)
++{
++ return sess->tgt_priv;
++}
++
++static inline void scst_sess_set_tgt_priv(struct scst_session *sess,
++ void *val)
++{
++ sess->tgt_priv = val;
++}
++
++/**
++ * Returns TRUE if cmd is being executed in atomic context.
++ *
++ * Note: checkpatch will complain on the use of in_atomic() below. You can
++ * safely ignore this warning since in_atomic() is used here only for debugging
++ * purposes.
++ */
++static inline bool scst_cmd_atomic(struct scst_cmd *cmd)
++{
++ int res = cmd->atomic;
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (unlikely((in_atomic() || in_interrupt() || irqs_disabled()) &&
++ !res)) {
++ printk(KERN_ERR "ERROR: atomic context and non-atomic cmd\n");
++ dump_stack();
++ cmd->atomic = 1;
++ res = 1;
++ }
++#endif
++ return res;
++}
++
++/*
++ * Returns TRUE if cmd has been preliminary completed, i.e. completed or
++ * aborted.
++ */
++static inline bool scst_cmd_prelim_completed(struct scst_cmd *cmd)
++{
++ return cmd->completed || test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
++}
++
++static inline enum scst_exec_context __scst_estimate_context(bool atomic)
++{
++ if (in_irq())
++ return SCST_CONTEXT_TASKLET;
++/*
++ * We come here from many non reliable places, like the block layer, and don't
++ * have any reliable way to detect if we called under atomic context or not
++ * (in_atomic() isn't reliable), so let's be safe and disable this section
++ * for now to unconditionally return thread context.
++ */
++#if 0
++ else if (irqs_disabled())
++ return SCST_CONTEXT_THREAD;
++ else if (in_atomic())
++ return SCST_CONTEXT_DIRECT_ATOMIC;
++ else
++ return atomic ? SCST_CONTEXT_DIRECT :
++ SCST_CONTEXT_DIRECT_ATOMIC;
++#else
++ return SCST_CONTEXT_THREAD;
++#endif
++}
++
++static inline enum scst_exec_context scst_estimate_context(void)
++{
++ return __scst_estimate_context(false);
++}
++
++static inline enum scst_exec_context scst_estimate_context_atomic(void)
++{
++ return __scst_estimate_context(true);
++}
++
++/* Returns cmd's CDB */
++static inline const uint8_t *scst_cmd_get_cdb(struct scst_cmd *cmd)
++{
++ return cmd->cdb;
++}
++
++/* Returns cmd's CDB length */
++static inline unsigned int scst_cmd_get_cdb_len(struct scst_cmd *cmd)
++{
++ return cmd->cdb_len;
++}
++
++/* Returns cmd's extended CDB */
++static inline const uint8_t *scst_cmd_get_ext_cdb(struct scst_cmd *cmd)
++{
++ return cmd->ext_cdb;
++}
++
++/* Returns cmd's extended CDB length */
++static inline unsigned int scst_cmd_get_ext_cdb_len(struct scst_cmd *cmd)
++{
++ return cmd->ext_cdb_len;
++}
++
++/* Sets cmd's extended CDB and its length */
++static inline void scst_cmd_set_ext_cdb(struct scst_cmd *cmd,
++ uint8_t *ext_cdb, unsigned int ext_cdb_len)
++{
++ cmd->ext_cdb = ext_cdb;
++ cmd->ext_cdb_len = ext_cdb_len;
++}
++
++/* Returns cmd's session */
++static inline struct scst_session *scst_cmd_get_session(struct scst_cmd *cmd)
++{
++ return cmd->sess;
++}
++
++/* Returns cmd's response data length */
++static inline int scst_cmd_get_resp_data_len(struct scst_cmd *cmd)
++{
++ return cmd->resp_data_len;
++}
++
++/* Returns cmd's adjusted response data length */
++static inline int scst_cmd_get_adjusted_resp_data_len(struct scst_cmd *cmd)
++{
++ return cmd->adjusted_resp_data_len;
++}
++
++/* Returns if status should be sent for cmd */
++static inline int scst_cmd_get_is_send_status(struct scst_cmd *cmd)
++{
++ return cmd->is_send_status;
++}
++
++/*
++ * Returns pointer to cmd's SG data buffer.
++ *
++ * Usage of this function is not recommended, use scst_get_buf_*()
++ * family of functions instead.
++ */
++static inline struct scatterlist *scst_cmd_get_sg(struct scst_cmd *cmd)
++{
++ return cmd->sg;
++}
++
++/*
++ * Returns cmd's sg_cnt.
++ *
++ * Usage of this function is not recommended, use scst_get_buf_*()
++ * family of functions instead.
++ */
++static inline int scst_cmd_get_sg_cnt(struct scst_cmd *cmd)
++{
++ return cmd->sg_cnt;
++}
++
++/*
++ * Returns cmd's data buffer length.
++ *
++ * In case if you need to iterate over data in the buffer, usage of
++ * this function is not recommended, use scst_get_buf_*()
++ * family of functions instead.
++ */
++static inline unsigned int scst_cmd_get_bufflen(struct scst_cmd *cmd)
++{
++ return cmd->bufflen;
++}
++
++/*
++ * Returns pointer to cmd's bidirectional in (WRITE) SG data buffer.
++ *
++ * Usage of this function is not recommended, use scst_get_out_buf_*()
++ * family of functions instead.
++ */
++static inline struct scatterlist *scst_cmd_get_out_sg(struct scst_cmd *cmd)
++{
++ return cmd->out_sg;
++}
++
++/*
++ * Returns cmd's bidirectional in (WRITE) sg_cnt.
++ *
++ * Usage of this function is not recommended, use scst_get_out_buf_*()
++ * family of functions instead.
++ */
++static inline int scst_cmd_get_out_sg_cnt(struct scst_cmd *cmd)
++{
++ return cmd->out_sg_cnt;
++}
++
++void scst_restore_sg_buff(struct scst_cmd *cmd);
++
++/* Restores modified sg buffer in the original state, if necessary */
++static inline void scst_check_restore_sg_buff(struct scst_cmd *cmd)
++{
++ if (unlikely(cmd->sg_buff_modified))
++ scst_restore_sg_buff(cmd);
++}
++
++/*
++ * Returns cmd's bidirectional in (WRITE) data buffer length.
++ *
++ * In case if you need to iterate over data in the buffer, usage of
++ * this function is not recommended, use scst_get_out_buf_*()
++ * family of functions instead.
++ */
++static inline unsigned int scst_cmd_get_out_bufflen(struct scst_cmd *cmd)
++{
++ return cmd->out_bufflen;
++}
++
++/* Returns pointer to cmd's target's SG data buffer */
++static inline struct scatterlist *scst_cmd_get_tgt_sg(struct scst_cmd *cmd)
++{
++ return cmd->tgt_sg;
++}
++
++/* Returns cmd's target's sg_cnt */
++static inline int scst_cmd_get_tgt_sg_cnt(struct scst_cmd *cmd)
++{
++ return cmd->tgt_sg_cnt;
++}
++
++/* Sets cmd's target's SG data buffer */
++static inline void scst_cmd_set_tgt_sg(struct scst_cmd *cmd,
++ struct scatterlist *sg, int sg_cnt)
++{
++ cmd->tgt_sg = sg;
++ cmd->tgt_sg_cnt = sg_cnt;
++ cmd->tgt_data_buf_alloced = 1;
++}
++
++/* Returns pointer to cmd's target's OUT SG data buffer */
++static inline struct scatterlist *scst_cmd_get_out_tgt_sg(struct scst_cmd *cmd)
++{
++ return cmd->tgt_out_sg;
++}
++
++/* Returns cmd's target's OUT sg_cnt */
++static inline int scst_cmd_get_tgt_out_sg_cnt(struct scst_cmd *cmd)
++{
++ return cmd->tgt_out_sg_cnt;
++}
++
++/* Sets cmd's target's OUT SG data buffer */
++static inline void scst_cmd_set_tgt_out_sg(struct scst_cmd *cmd,
++ struct scatterlist *sg, int sg_cnt)
++{
++ WARN_ON(!cmd->tgt_data_buf_alloced);
++
++ cmd->tgt_out_sg = sg;
++ cmd->tgt_out_sg_cnt = sg_cnt;
++}
++
++/* Returns cmd's data direction */
++static inline scst_data_direction scst_cmd_get_data_direction(
++ struct scst_cmd *cmd)
++{
++ return cmd->data_direction;
++}
++
++/* Returns cmd's write len as well as write SG and sg_cnt */
++static inline int scst_cmd_get_write_fields(struct scst_cmd *cmd,
++ struct scatterlist **sg, int *sg_cnt)
++{
++ *sg = *cmd->write_sg;
++ *sg_cnt = *cmd->write_sg_cnt;
++ return cmd->write_len;
++}
++
++void scst_cmd_set_write_not_received_data_len(struct scst_cmd *cmd,
++ int not_received);
++
++bool __scst_get_resid(struct scst_cmd *cmd, int *resid, int *bidi_out_resid);
++
++/*
++ * Returns true if cmd has residual(s) and returns them in the corresponding
++ * parameters(s).
++ */
++static inline bool scst_get_resid(struct scst_cmd *cmd,
++ int *resid, int *bidi_out_resid)
++{
++ if (likely(!cmd->resid_possible))
++ return false;
++ return __scst_get_resid(cmd, resid, bidi_out_resid);
++}
++
++/* Returns cmd's status byte from host device */
++static inline uint8_t scst_cmd_get_status(struct scst_cmd *cmd)
++{
++ return cmd->status;
++}
++
++/* Returns cmd's status from host adapter itself */
++static inline uint8_t scst_cmd_get_msg_status(struct scst_cmd *cmd)
++{
++ return cmd->msg_status;
++}
++
++/* Returns cmd's status set by low-level driver to indicate its status */
++static inline uint8_t scst_cmd_get_host_status(struct scst_cmd *cmd)
++{
++ return cmd->host_status;
++}
++
++/* Returns cmd's status set by SCSI mid-level */
++static inline uint8_t scst_cmd_get_driver_status(struct scst_cmd *cmd)
++{
++ return cmd->driver_status;
++}
++
++/* Returns pointer to cmd's sense buffer */
++static inline uint8_t *scst_cmd_get_sense_buffer(struct scst_cmd *cmd)
++{
++ return cmd->sense;
++}
++
++/* Returns cmd's valid sense length */
++static inline int scst_cmd_get_sense_buffer_len(struct scst_cmd *cmd)
++{
++ return cmd->sense_valid_len;
++}
++
++/*
++ * Get/Set functions for cmd's queue_type
++ */
++static inline enum scst_cmd_queue_type scst_cmd_get_queue_type(
++ struct scst_cmd *cmd)
++{
++ return cmd->queue_type;
++}
++
++static inline void scst_cmd_set_queue_type(struct scst_cmd *cmd,
++ enum scst_cmd_queue_type queue_type)
++{
++ cmd->queue_type = queue_type;
++}
++
++/*
++ * Get/Set functions for cmd's target SN
++ */
++static inline uint64_t scst_cmd_get_tag(struct scst_cmd *cmd)
++{
++ return cmd->tag;
++}
++
++static inline void scst_cmd_set_tag(struct scst_cmd *cmd, uint64_t tag)
++{
++ cmd->tag = tag;
++}
++
++/*
++ * Get/Set functions for cmd's target private data.
++ * Variant with *_lock must be used if target driver uses
++ * scst_find_cmd() to avoid race with it, except inside scst_find_cmd()'s
++ * callback, where lock is already taken.
++ */
++static inline void *scst_cmd_get_tgt_priv(struct scst_cmd *cmd)
++{
++ return cmd->tgt_priv;
++}
++
++static inline void scst_cmd_set_tgt_priv(struct scst_cmd *cmd, void *val)
++{
++ cmd->tgt_priv = val;
++}
++
++/*
++ * Get/Set functions for tgt_need_alloc_data_buf flag
++ */
++static inline int scst_cmd_get_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
++{
++ return cmd->tgt_need_alloc_data_buf;
++}
++
++static inline void scst_cmd_set_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
++{
++ cmd->tgt_need_alloc_data_buf = 1;
++}
++
++/*
++ * Get/Set functions for tgt_data_buf_alloced flag
++ */
++static inline int scst_cmd_get_tgt_data_buff_alloced(struct scst_cmd *cmd)
++{
++ return cmd->tgt_data_buf_alloced;
++}
++
++static inline void scst_cmd_set_tgt_data_buff_alloced(struct scst_cmd *cmd)
++{
++ cmd->tgt_data_buf_alloced = 1;
++}
++
++/*
++ * Get/Set functions for dh_data_buf_alloced flag
++ */
++static inline int scst_cmd_get_dh_data_buff_alloced(struct scst_cmd *cmd)
++{
++ return cmd->dh_data_buf_alloced;
++}
++
++static inline void scst_cmd_set_dh_data_buff_alloced(struct scst_cmd *cmd)
++{
++ cmd->dh_data_buf_alloced = 1;
++}
++
++/*
++ * Get/Set functions for no_sgv flag
++ */
++static inline int scst_cmd_get_no_sgv(struct scst_cmd *cmd)
++{
++ return cmd->no_sgv;
++}
++
++static inline void scst_cmd_set_no_sgv(struct scst_cmd *cmd)
++{
++ cmd->no_sgv = 1;
++}
++
++/*
++ * Get/Set functions for tgt_sn
++ */
++static inline int scst_cmd_get_tgt_sn(struct scst_cmd *cmd)
++{
++ BUG_ON(!cmd->tgt_sn_set);
++ return cmd->tgt_sn;
++}
++
++static inline void scst_cmd_set_tgt_sn(struct scst_cmd *cmd, uint32_t tgt_sn)
++{
++ cmd->tgt_sn_set = 1;
++ cmd->tgt_sn = tgt_sn;
++}
++
++/*
++ * Returns 1 if the cmd was aborted, so its status is invalid and no
++ * reply shall be sent to the remote initiator. A target driver should
++ * only clear internal resources, associated with cmd.
++ */
++static inline int scst_cmd_aborted(struct scst_cmd *cmd)
++{
++ return test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags) &&
++ !test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
++}
++
++/* Returns sense data format for cmd's dev */
++static inline bool scst_get_cmd_dev_d_sense(struct scst_cmd *cmd)
++{
++ return (cmd->dev != NULL) ? cmd->dev->d_sense : 0;
++}
++
++/*
++ * Get/Set functions for expected data direction, transfer length
++ * and its validity flag
++ */
++static inline int scst_cmd_is_expected_set(struct scst_cmd *cmd)
++{
++ return cmd->expected_values_set;
++}
++
++static inline scst_data_direction scst_cmd_get_expected_data_direction(
++ struct scst_cmd *cmd)
++{
++ return cmd->expected_data_direction;
++}
++
++static inline int scst_cmd_get_expected_transfer_len(
++ struct scst_cmd *cmd)
++{
++ return cmd->expected_transfer_len;
++}
++
++static inline int scst_cmd_get_expected_out_transfer_len(
++ struct scst_cmd *cmd)
++{
++ return cmd->expected_out_transfer_len;
++}
++
++static inline void scst_cmd_set_expected(struct scst_cmd *cmd,
++ scst_data_direction expected_data_direction,
++ int expected_transfer_len)
++{
++ cmd->expected_data_direction = expected_data_direction;
++ cmd->expected_transfer_len = expected_transfer_len;
++ cmd->expected_values_set = 1;
++}
++
++static inline void scst_cmd_set_expected_out_transfer_len(struct scst_cmd *cmd,
++ int expected_out_transfer_len)
++{
++ WARN_ON(!cmd->expected_values_set);
++ cmd->expected_out_transfer_len = expected_out_transfer_len;
++}
++
++/*
++ * Get/clear functions for cmd's may_need_dma_sync
++ */
++static inline int scst_get_may_need_dma_sync(struct scst_cmd *cmd)
++{
++ return cmd->may_need_dma_sync;
++}
++
++static inline void scst_clear_may_need_dma_sync(struct scst_cmd *cmd)
++{
++ cmd->may_need_dma_sync = 0;
++}
++
++/*
++ * Get/set functions for cmd's delivery_status. It is one of
++ * SCST_CMD_DELIVERY_* constants. It specifies the status of the
++ * command's delivery to initiator.
++ */
++static inline int scst_get_delivery_status(struct scst_cmd *cmd)
++{
++ return cmd->delivery_status;
++}
++
++static inline void scst_set_delivery_status(struct scst_cmd *cmd,
++ int delivery_status)
++{
++ cmd->delivery_status = delivery_status;
++}
++
++static inline unsigned int scst_get_active_cmd_count(struct scst_cmd *cmd)
++{
++ if (likely(cmd->tgt_dev != NULL))
++ return atomic_read(&cmd->tgt_dev->tgt_dev_cmd_count);
++ else
++ return (unsigned int)-1;
++}
++
++/*
++ * Get/Set function for mgmt cmd's target private data
++ */
++static inline void *scst_mgmt_cmd_get_tgt_priv(struct scst_mgmt_cmd *mcmd)
++{
++ return mcmd->tgt_priv;
++}
++
++static inline void scst_mgmt_cmd_set_tgt_priv(struct scst_mgmt_cmd *mcmd,
++ void *val)
++{
++ mcmd->tgt_priv = val;
++}
++
++/* Returns mgmt cmd's completition status (SCST_MGMT_STATUS_* constants) */
++static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd)
++{
++ return mcmd->status;
++}
++
++/* Returns mgmt cmd's TM fn */
++static inline int scst_mgmt_cmd_get_fn(struct scst_mgmt_cmd *mcmd)
++{
++ return mcmd->fn;
++}
++
++/*
++ * Called by dev handler's task_mgmt_fn() to notify SCST core that mcmd
++ * is going to complete asynchronously.
++ */
++void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd);
++
++/*
++ * Called by dev handler to notify SCST core that async. mcmd is completed
++ * with status "status".
++ */
++void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status);
++
++/* Returns AEN's fn */
++static inline int scst_aen_get_event_fn(struct scst_aen *aen)
++{
++ return aen->event_fn;
++}
++
++/* Returns AEN's session */
++static inline struct scst_session *scst_aen_get_sess(struct scst_aen *aen)
++{
++ return aen->sess;
++}
++
++/* Returns AEN's LUN */
++static inline __be64 scst_aen_get_lun(struct scst_aen *aen)
++{
++ return aen->lun;
++}
++
++/* Returns SCSI AEN's sense */
++static inline const uint8_t *scst_aen_get_sense(struct scst_aen *aen)
++{
++ return aen->aen_sense;
++}
++
++/* Returns SCSI AEN's sense length */
++static inline int scst_aen_get_sense_len(struct scst_aen *aen)
++{
++ return aen->aen_sense_len;
++}
++
++/*
++ * Get/set functions for AEN's delivery_status. It is one of
++ * SCST_AEN_RES_* constants. It specifies the status of the
++ * command's delivery to initiator.
++ */
++static inline int scst_get_aen_delivery_status(struct scst_aen *aen)
++{
++ return aen->delivery_status;
++}
++
++static inline void scst_set_aen_delivery_status(struct scst_aen *aen,
++ int status)
++{
++ aen->delivery_status = status;
++}
++
++void scst_aen_done(struct scst_aen *aen);
++
++static inline void sg_clear(struct scatterlist *sg)
++{
++ memset(sg, 0, sizeof(*sg));
++#ifdef CONFIG_DEBUG_SG
++ sg->sg_magic = SG_MAGIC;
++#endif
++}
++
++enum scst_sg_copy_dir {
++ SCST_SG_COPY_FROM_TARGET,
++ SCST_SG_COPY_TO_TARGET
++};
++
++void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir);
++
++/*
++ * Functions for access to the commands data (SG) buffer,
++ * including HIGHMEM environment. Should be used instead of direct
++ * access. Returns the mapped buffer length for success, 0 for EOD,
++ * negative error code otherwise.
++ *
++ * "Buf" argument returns the mapped buffer
++ *
++ * The "put" function unmaps the buffer.
++ */
++static inline int __scst_get_buf(struct scst_cmd *cmd, struct scatterlist *sg,
++ int sg_cnt, uint8_t **buf)
++{
++ int res = 0;
++ int i = cmd->get_sg_buf_entry_num;
++
++ *buf = NULL;
++
++ if ((i >= sg_cnt) || unlikely(sg == NULL))
++ goto out;
++
++ *buf = page_address(sg_page(&sg[i]));
++ *buf += sg[i].offset;
++
++ res = sg[i].length;
++ cmd->get_sg_buf_entry_num++;
++
++out:
++ return res;
++}
++
++static inline int scst_get_buf_first(struct scst_cmd *cmd, uint8_t **buf)
++{
++ cmd->get_sg_buf_entry_num = 0;
++ cmd->may_need_dma_sync = 1;
++ return __scst_get_buf(cmd, cmd->sg, cmd->sg_cnt, buf);
++}
++
++static inline int scst_get_buf_next(struct scst_cmd *cmd, uint8_t **buf)
++{
++ return __scst_get_buf(cmd, cmd->sg, cmd->sg_cnt, buf);
++}
++
++static inline void scst_put_buf(struct scst_cmd *cmd, void *buf)
++{
++ /* Nothing to do */
++}
++
++static inline int scst_get_out_buf_first(struct scst_cmd *cmd, uint8_t **buf)
++{
++ cmd->get_sg_buf_entry_num = 0;
++ cmd->may_need_dma_sync = 1;
++ return __scst_get_buf(cmd, cmd->out_sg, cmd->out_sg_cnt, buf);
++}
++
++static inline int scst_get_out_buf_next(struct scst_cmd *cmd, uint8_t **buf)
++{
++ return __scst_get_buf(cmd, cmd->out_sg, cmd->out_sg_cnt, buf);
++}
++
++static inline void scst_put_out_buf(struct scst_cmd *cmd, void *buf)
++{
++ /* Nothing to do */
++}
++
++static inline int scst_get_sg_buf_first(struct scst_cmd *cmd, uint8_t **buf,
++ struct scatterlist *sg, int sg_cnt)
++{
++ cmd->get_sg_buf_entry_num = 0;
++ cmd->may_need_dma_sync = 1;
++ return __scst_get_buf(cmd, sg, sg_cnt, buf);
++}
++
++static inline int scst_get_sg_buf_next(struct scst_cmd *cmd, uint8_t **buf,
++ struct scatterlist *sg, int sg_cnt)
++{
++ return __scst_get_buf(cmd, sg, sg_cnt, buf);
++}
++
++static inline void scst_put_sg_buf(struct scst_cmd *cmd, void *buf,
++ struct scatterlist *sg, int sg_cnt)
++{
++ /* Nothing to do */
++}
++
++/*
++ * Returns approximate higher rounded buffers count that
++ * scst_get_buf_[first|next]() return.
++ */
++static inline int scst_get_buf_count(struct scst_cmd *cmd)
++{
++ return (cmd->sg_cnt == 0) ? 1 : cmd->sg_cnt;
++}
++
++/*
++ * Returns approximate higher rounded buffers count that
++ * scst_get_out_buf_[first|next]() return.
++ */
++static inline int scst_get_out_buf_count(struct scst_cmd *cmd)
++{
++ return (cmd->out_sg_cnt == 0) ? 1 : cmd->out_sg_cnt;
++}
++
++int scst_suspend_activity(bool interruptible);
++void scst_resume_activity(void);
++
++void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic);
++
++void scst_post_parse(struct scst_cmd *cmd);
++void scst_post_alloc_data_buf(struct scst_cmd *cmd);
++
++int scst_check_local_events(struct scst_cmd *cmd);
++
++int scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd);
++
++struct scst_trace_log {
++ unsigned int val;
++ const char *token;
++};
++
++extern struct mutex scst_mutex;
++
++const struct sysfs_ops *scst_sysfs_get_sysfs_ops(void);
++
++/*
++ * Returns target driver's root sysfs kobject.
++ * The driver can create own files/directories/links here.
++ */
++static inline struct kobject *scst_sysfs_get_tgtt_kobj(
++ struct scst_tgt_template *tgtt)
++{
++ return &tgtt->tgtt_kobj;
++}
++
++/*
++ * Returns target's root sysfs kobject.
++ * The driver can create own files/directories/links here.
++ */
++static inline struct kobject *scst_sysfs_get_tgt_kobj(
++ struct scst_tgt *tgt)
++{
++ return &tgt->tgt_kobj;
++}
++
++/*
++ * Returns device handler's root sysfs kobject.
++ * The driver can create own files/directories/links here.
++ */
++static inline struct kobject *scst_sysfs_get_devt_kobj(
++ struct scst_dev_type *devt)
++{
++ return &devt->devt_kobj;
++}
++
++/*
++ * Returns device's root sysfs kobject.
++ * The driver can create own files/directories/links here.
++ */
++static inline struct kobject *scst_sysfs_get_dev_kobj(
++ struct scst_device *dev)
++{
++ return &dev->dev_kobj;
++}
++
++/*
++ * Returns session's root sysfs kobject.
++ * The driver can create own files/directories/links here.
++ */
++static inline struct kobject *scst_sysfs_get_sess_kobj(
++ struct scst_session *sess)
++{
++ return &sess->sess_kobj;
++}
++
++/* Returns target name */
++static inline const char *scst_get_tgt_name(const struct scst_tgt *tgt)
++{
++ return tgt->tgt_name;
++}
++
++int scst_alloc_sense(struct scst_cmd *cmd, int atomic);
++int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
++ const uint8_t *sense, unsigned int len);
++
++int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
++ int key, int asc, int ascq);
++
++bool scst_is_ua_sense(const uint8_t *sense, int len);
++
++bool scst_analyze_sense(const uint8_t *sense, int len,
++ unsigned int valid_mask, int key, int asc, int ascq);
++
++unsigned long scst_random(void);
++
++void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len);
++
++void scst_get(void);
++void scst_put(void);
++
++void scst_cmd_get(struct scst_cmd *cmd);
++void scst_cmd_put(struct scst_cmd *cmd);
++
++struct scatterlist *scst_alloc(int size, gfp_t gfp_mask, int *count);
++void scst_free(struct scatterlist *sg, int count);
++
++void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
++ struct scst_thr_data_hdr *data,
++ void (*free_fn) (struct scst_thr_data_hdr *data));
++void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev);
++void scst_dev_del_all_thr_data(struct scst_device *dev);
++struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
++ struct task_struct *tsk);
++
++/* Finds local to the current thread data. Returns NULL, if they not found. */
++static inline struct scst_thr_data_hdr *scst_find_thr_data(
++ struct scst_tgt_dev *tgt_dev)
++{
++ return __scst_find_thr_data(tgt_dev, current);
++}
++
++/* Increase ref counter for the thread data */
++static inline void scst_thr_data_get(struct scst_thr_data_hdr *data)
++{
++ atomic_inc(&data->ref);
++}
++
++/* Decrease ref counter for the thread data */
++static inline void scst_thr_data_put(struct scst_thr_data_hdr *data)
++{
++ if (atomic_dec_and_test(&data->ref))
++ data->free_fn(data);
++}
++
++int scst_calc_block_shift(int sector_size);
++int scst_sbc_generic_parse(struct scst_cmd *cmd,
++ int (*get_block_shift)(struct scst_cmd *cmd));
++int scst_cdrom_generic_parse(struct scst_cmd *cmd,
++ int (*get_block_shift)(struct scst_cmd *cmd));
++int scst_modisk_generic_parse(struct scst_cmd *cmd,
++ int (*get_block_shift)(struct scst_cmd *cmd));
++int scst_tape_generic_parse(struct scst_cmd *cmd,
++ int (*get_block_size)(struct scst_cmd *cmd));
++int scst_changer_generic_parse(struct scst_cmd *cmd,
++ int (*nothing)(struct scst_cmd *cmd));
++int scst_processor_generic_parse(struct scst_cmd *cmd,
++ int (*nothing)(struct scst_cmd *cmd));
++int scst_raid_generic_parse(struct scst_cmd *cmd,
++ int (*nothing)(struct scst_cmd *cmd));
++
++int scst_block_generic_dev_done(struct scst_cmd *cmd,
++ void (*set_block_shift)(struct scst_cmd *cmd, int block_shift));
++int scst_tape_generic_dev_done(struct scst_cmd *cmd,
++ void (*set_block_size)(struct scst_cmd *cmd, int block_size));
++
++int scst_obtain_device_parameters(struct scst_device *dev);
++
++void scst_reassign_persistent_sess_states(struct scst_session *new_sess,
++ struct scst_session *old_sess);
++
++int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun);
++
++/*
++ * Has to be put here open coded, because Linux doesn't have equivalent, which
++ * allows exclusive wake ups of threads in LIFO order. We need it to let (yet)
++ * unneeded threads sleep and not pollute CPU cache by their stacks.
++ */
++static inline void add_wait_queue_exclusive_head(wait_queue_head_t *q,
++ wait_queue_t *wait)
++{
++ unsigned long flags;
++
++ wait->flags |= WQ_FLAG_EXCLUSIVE;
++ spin_lock_irqsave(&q->lock, flags);
++ __add_wait_queue(q, wait);
++ spin_unlock_irqrestore(&q->lock, flags);
++}
++
++/*
++ * Structure to match events to user space and replies on them
++ */
++struct scst_sysfs_user_info {
++ /* Unique cookie to identify request */
++ uint32_t info_cookie;
++
++ /* Entry in the global list */
++ struct list_head info_list_entry;
++
++ /* Set if reply from the user space is being executed */
++ unsigned int info_being_executed:1;
++
++ /* Set if this info is in the info_list */
++ unsigned int info_in_list:1;
++
++ /* Completion to wait on for the request completion */
++ struct completion info_completion;
++
++ /* Request completion status and optional data */
++ int info_status;
++ void *data;
++};
++
++int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info);
++void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info);
++struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie);
++int scst_wait_info_completion(struct scst_sysfs_user_info *info,
++ unsigned long timeout);
++
++unsigned int scst_get_setup_id(void);
++
++/*
++ * Needed to avoid potential circular locking dependency between scst_mutex
++ * and internal sysfs locking (s_active). It could be since most sysfs entries
++ * are created and deleted under scst_mutex AND scst_mutex is taken inside
++ * sysfs functions. So, we push from the sysfs functions all the processing
++ * taking scst_mutex. To avoid deadlock, we return from them with EAGAIN
++ * if processing is taking too long. User space then should poll
++ * last_sysfs_mgmt_res until it returns the result of the processing
++ * (something other than EAGAIN).
++ */
++struct scst_sysfs_work_item {
++ /*
++ * If true, then last_sysfs_mgmt_res will not be updated. This is
++ * needed to allow read only sysfs monitoring during management actions.
++ * All management actions are supposed to be externally serialized,
++ * so then last_sysfs_mgmt_res automatically serialized too.
++ * Othewrwise a monitoring action can overwrite value of simultaneous
++ * management action's last_sysfs_mgmt_res.
++ */
++ bool read_only_action;
++
++ struct list_head sysfs_work_list_entry;
++ struct kref sysfs_work_kref;
++ int (*sysfs_work_fn)(struct scst_sysfs_work_item *work);
++ struct completion sysfs_work_done;
++ char *buf;
++
++ union {
++ struct scst_dev_type *devt;
++ struct scst_tgt_template *tgtt;
++ struct {
++ struct scst_tgt *tgt;
++ struct scst_acg *acg;
++ union {
++ bool is_tgt_kobj;
++ int io_grouping_type;
++ bool enable;
++ };
++ };
++ struct {
++ struct scst_device *dev;
++ int new_threads_num;
++ enum scst_dev_type_threads_pool_type new_threads_pool_type;
++ };
++ struct scst_session *sess;
++ struct {
++ struct scst_tgt *tgt;
++ unsigned long l;
++ };
++ };
++ int work_res;
++ char *res_buf;
++};
++
++int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
++ bool read_only_action, struct scst_sysfs_work_item **res_work);
++int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work);
++void scst_sysfs_work_get(struct scst_sysfs_work_item *work);
++void scst_sysfs_work_put(struct scst_sysfs_work_item *work);
++
++char *scst_get_next_lexem(char **token_str);
++void scst_restore_token_str(char *prev_lexem, char *token_str);
++char *scst_get_next_token_str(char **input_str);
++
++void scst_init_threads(struct scst_cmd_threads *cmd_threads);
++void scst_deinit_threads(struct scst_cmd_threads *cmd_threads);
++
++#endif /* __SCST_H */
+diff -upkr -X linux-2.6.36/Documentation/dontdiff linux-2.6.36/drivers/Kconfig linux-2.6.36/drivers/Kconfig
+--- orig/linux-2.6.36/drivers/Kconfig 01:51:29.000000000 +0400
++++ linux-2.6.36/drivers/Kconfig 14:14:46.000000000 +0400
+@@ -22,6 +22,8 @@ source "drivers/ide/Kconfig"
+
+ source "drivers/scsi/Kconfig"
+
++source "drivers/scst/Kconfig"
++
+ source "drivers/ata/Kconfig"
+
+ source "drivers/md/Kconfig"
+diff -upkr -X linux-2.6.36/Documentation/dontdiff linux-2.6.36/drivers/Makefile linux-2.6.36/drivers/Makefile
+--- orig/linux-2.6.36/drivers/Makefile 15:40:04.000000000 +0200
++++ linux-2.6.36/drivers/Makefile 15:40:20.000000000 +0200
+@@ -113,3 +113,4 @@ obj-$(CONFIG_VLYNQ) += vlynq/
+ obj-$(CONFIG_STAGING) += staging/
+ obj-y += platform/
+ obj-y += ieee802154/
++obj-$(CONFIG_SCST) += scst/
+diff -uprN orig/linux-2.6.36/drivers/scst/Kconfig linux-2.6.36/drivers/scst/Kconfig
+--- orig/linux-2.6.36/drivers/scst/Kconfig
++++ linux-2.6.36/drivers/scst/Kconfig
+@@ -0,0 +1,254 @@
++menu "SCSI target (SCST) support"
++
++config SCST
++ tristate "SCSI target (SCST) support"
++ depends on SCSI
++ help
++ SCSI target (SCST) is designed to provide unified, consistent
++ interface between SCSI target drivers and Linux kernel and
++ simplify target drivers development as much as possible. Visit
++ http://scst.sourceforge.net for more info about it.
++
++config SCST_DISK
++ tristate "SCSI target disk support"
++ default SCST
++ depends on SCSI && SCST
++ help
++ SCST pass-through device handler for disk device.
++
++config SCST_TAPE
++ tristate "SCSI target tape support"
++ default SCST
++ depends on SCSI && SCST
++ help
++ SCST pass-through device handler for tape device.
++
++config SCST_CDROM
++ tristate "SCSI target CDROM support"
++ default SCST
++ depends on SCSI && SCST
++ help
++ SCST pass-through device handler for CDROM device.
++
++config SCST_MODISK
++ tristate "SCSI target MO disk support"
++ default SCST
++ depends on SCSI && SCST
++ help
++ SCST pass-through device handler for MO disk device.
++
++config SCST_CHANGER
++ tristate "SCSI target changer support"
++ default SCST
++ depends on SCSI && SCST
++ help
++ SCST pass-through device handler for changer device.
++
++config SCST_PROCESSOR
++ tristate "SCSI target processor support"
++ default SCST
++ depends on SCSI && SCST
++ help
++ SCST pass-through device handler for processor device.
++
++config SCST_RAID
++ tristate "SCSI target storage array controller (RAID) support"
++ default SCST
++ depends on SCSI && SCST
++ help
++ SCST pass-through device handler for raid storage array controller (RAID) device.
++
++config SCST_VDISK
++ tristate "SCSI target virtual disk and/or CDROM support"
++ default SCST
++ depends on SCSI && SCST
++ help
++ SCST device handler for virtual disk and/or CDROM device.
++
++config SCST_USER
++ tristate "User-space SCSI target driver support"
++ default SCST
++ depends on SCSI && SCST && !HIGHMEM4G && !HIGHMEM64G
++ help
++ The SCST device handler scst_user allows to implement full-feature
++ SCSI target devices in user space.
++
++ If unsure, say "N".
++
++config SCST_STRICT_SERIALIZING
++ bool "Strict serialization"
++ depends on SCST
++ help
++ Enable strict SCSI command serialization. When enabled, SCST sends
++ all SCSI commands to the underlying SCSI device synchronously, one
++ after one. This makes task management more reliable, at the cost of
++ a performance penalty. This is most useful for stateful SCSI devices
++ like tapes, where the result of the execution of a command
++ depends on the device settings configured by previous commands. Disk
++ and RAID devices are stateless in most cases. The current SCSI core
++ in Linux doesn't allow to abort all commands reliably if they have
++ been sent asynchronously to a stateful device.
++ Enable this option if you use stateful device(s) and need as much
++ error recovery reliability as possible.
++
++ If unsure, say "N".
++
++config SCST_STRICT_SECURITY
++ bool "Strict security"
++ depends on SCST
++ help
++ Makes SCST clear (zero-fill) allocated data buffers. Note: this has a
++ significant performance penalty.
++
++ If unsure, say "N".
++
++config SCST_TEST_IO_IN_SIRQ
++ bool "Allow test I/O from soft-IRQ context"
++ depends on SCST
++ help
++ Allows SCST to submit selected SCSI commands (TUR and
++ READ/WRITE) from soft-IRQ context (tasklets). Enabling it will
++ decrease amount of context switches and slightly improve
++ performance. The goal of this option is to be able to measure
++ overhead of the context switches. See more info about it in
++ README.scst.
++
++ WARNING! Improperly used, this option can lead you to a kernel crash!
++
++ If unsure, say "N".
++
++config SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING
++ bool "Send back UNKNOWN TASK when an already finished task is aborted"
++ depends on SCST
++ help
++ Controls which response is sent by SCST to the initiator in case
++ the initiator attempts to abort (ABORT TASK) an already finished
++ request. If this option is enabled, the response UNKNOWN TASK is
++ sent back to the initiator. However, some initiators, particularly
++ the VMware iSCSI initiator, interpret the UNKNOWN TASK response as
++ if the target got crazy and try to RESET it. Then sometimes the
++ initiator gets crazy itself.
++
++ If unsure, say "N".
++
++config SCST_USE_EXPECTED_VALUES
++ bool "Prefer initiator-supplied SCSI command attributes"
++ depends on SCST
++ help
++ When SCST receives a SCSI command from an initiator, such a SCSI
++ command has both data transfer length and direction attributes.
++ There are two possible sources for these attributes: either the
++ values computed by SCST from its internal command translation table
++ or the values supplied by the initiator. The former are used by
++ default because of security reasons. Invalid initiator-supplied
++ attributes can crash the target, especially in pass-through mode.
++ Only consider enabling this option when SCST logs the following
++ message: "Unknown opcode XX for YY. Should you update
++ scst_scsi_op_table?" and when the initiator complains. Please
++ report any unrecognized commands to scst-devel@lists.sourceforge.net.
++
++ If unsure, say "N".
++
++config SCST_EXTRACHECKS
++ bool "Extra consistency checks"
++ depends on SCST
++ help
++ Enable additional consistency checks in the SCSI middle level target
++ code. This may be helpful for SCST developers. Enable it if you have
++ any problems.
++
++ If unsure, say "N".
++
++config SCST_TRACING
++ bool "Tracing support"
++ depends on SCST
++ default y
++ help
++ Enable SCSI middle level tracing support. Tracing can be controlled
++ dynamically via sysfs interface. The traced information
++ is sent to the kernel log and may be very helpful when analyzing
++ the cause of a communication problem between initiator and target.
++
++ If unsure, say "Y".
++
++config SCST_DEBUG
++ bool "Debugging support"
++ depends on SCST
++ select DEBUG_BUGVERBOSE
++ help
++ Enables support for debugging SCST. This may be helpful for SCST
++ developers.
++
++ If unsure, say "N".
++
++config SCST_DEBUG_OOM
++ bool "Out-of-memory debugging support"
++ depends on SCST
++ help
++ Let SCST's internal memory allocation function
++ (scst_alloc_sg_entries()) fail about once in every 10000 calls, at
++ least if the flag __GFP_NOFAIL has not been set. This allows SCST
++ developers to test the behavior of SCST in out-of-memory conditions.
++ This may be helpful for SCST developers.
++
++ If unsure, say "N".
++
++config SCST_DEBUG_RETRY
++ bool "SCSI command retry debugging support"
++ depends on SCST
++ help
++ Let SCST's internal SCSI command transfer function
++ (scst_rdy_to_xfer()) fail about once in every 100 calls. This allows
++ SCST developers to test the behavior of SCST when SCSI queues fill
++ up. This may be helpful for SCST developers.
++
++ If unsure, say "N".
++
++config SCST_DEBUG_SN
++ bool "SCSI sequence number debugging support"
++ depends on SCST
++ help
++ Allows to test SCSI command ordering via sequence numbers by
++ randomly changing the type of SCSI commands into
++ SCST_CMD_QUEUE_ORDERED, SCST_CMD_QUEUE_HEAD_OF_QUEUE or
++ SCST_CMD_QUEUE_SIMPLE for about one in 300 SCSI commands.
++ This may be helpful for SCST developers.
++
++ If unsure, say "N".
++
++config SCST_DEBUG_TM
++ bool "Task management debugging support"
++ depends on SCST_DEBUG
++ help
++ Enables support for debugging of SCST's task management functions.
++ When enabled, some of the commands on LUN 0 in the default access
++ control group will be delayed for about 60 seconds. This will
++ cause the remote initiator send SCSI task management functions,
++ e.g. ABORT TASK and TARGET RESET.
++
++ If unsure, say "N".
++
++config SCST_TM_DBG_GO_OFFLINE
++ bool "Let devices become completely unresponsive"
++ depends on SCST_DEBUG_TM
++ help
++ Enable this option if you want that the device eventually becomes
++ completely unresponsive. When disabled, the device will receive
++ ABORT and RESET commands.
++
++config SCST_MEASURE_LATENCY
++ bool "Commands processing latency measurement facility"
++ depends on SCST
++ help
++ This option enables commands processing latency measurement
++ facility in SCST. It will provide in the sysfs interface
++ average commands processing latency statistics. You can clear
++ already measured results by writing 0 in the corresponding sysfs file.
++ Note, you need a non-preemtible kernel to have correct results.
++
++ If unsure, say "N".
++
++source "drivers/scst/iscsi-scst/Kconfig"
++source "drivers/scst/srpt/Kconfig"
++
++endmenu
+diff -uprN orig/linux-2.6.36/drivers/scst/Makefile linux-2.6.36/drivers/scst/Makefile
+--- orig/linux-2.6.36/drivers/scst/Makefile
++++ linux-2.6.36/drivers/scst/Makefile
+@@ -0,0 +1,12 @@
++ccflags-y += -Wno-unused-parameter
++
++scst-y += scst_main.o
++scst-y += scst_pres.o
++scst-y += scst_targ.o
++scst-y += scst_lib.o
++scst-y += scst_sysfs.o
++scst-y += scst_mem.o
++scst-y += scst_debug.o
++
++obj-$(CONFIG_SCST) += scst.o dev_handlers/ iscsi-scst/ qla2xxx-target/ \
++ srpt/ scst_local/
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_lib.c linux-2.6.36/drivers/scst/scst_lib.c
+--- orig/linux-2.6.36/drivers/scst/scst_lib.c
++++ linux-2.6.36/drivers/scst/scst_lib.c
+@@ -0,0 +1,7362 @@
++/*
++ * scst_lib.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/kthread.h>
++#include <linux/cdrom.h>
++#include <linux/unistd.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/delay.h>
++#include <linux/vmalloc.h>
++#include <asm/kmap_types.h>
++#include <asm/unaligned.h>
++
++#include <scst/scst.h>
++#include "scst_priv.h"
++#include "scst_mem.h"
++#include "scst_pres.h"
++
++struct scsi_io_context {
++ unsigned int full_cdb_used:1;
++ void *data;
++ void (*done)(void *data, char *sense, int result, int resid);
++ char sense[SCST_SENSE_BUFFERSIZE];
++ unsigned char full_cdb[0];
++};
++static struct kmem_cache *scsi_io_context_cache;
++
++/* get_trans_len_x extract x bytes from cdb as length starting from off */
++static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_1_256(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_2(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_3(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off);
++
++static int get_bidi_trans_len_2(struct scst_cmd *cmd, uint8_t off);
++
++/* for special commands */
++static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_serv_act_in(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_cdb_len_10(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_prevent_allow_medium_removal(struct scst_cmd *cmd,
++ uint8_t off);
++static int get_trans_len_3_read_elem_stat(struct scst_cmd *cmd, uint8_t off);
++static int get_trans_len_start_stop(struct scst_cmd *cmd, uint8_t off);
++
++/*
+++=====================================-============-======-
++| Command name | Operation | Type |
++| | code | |
++|-------------------------------------+------------+------+
++
+++=========================================================+
++|Key: M = command implementation is mandatory. |
++| O = command implementation is optional. |
++| V = Vendor-specific |
++| R = Reserved |
++| ' '= DON'T use for this device |
+++=========================================================+
++*/
++
++#define SCST_CDB_MANDATORY 'M' /* mandatory */
++#define SCST_CDB_OPTIONAL 'O' /* optional */
++#define SCST_CDB_VENDOR 'V' /* vendor */
++#define SCST_CDB_RESERVED 'R' /* reserved */
++#define SCST_CDB_NOTSUPP ' ' /* don't use */
++
++struct scst_sdbops {
++ uint8_t ops; /* SCSI-2 op codes */
++ uint8_t devkey[16]; /* Key for every device type M,O,V,R
++ * type_disk devkey[0]
++ * type_tape devkey[1]
++ * type_printer devkey[2]
++ * type_proseccor devkey[3]
++ * type_worm devkey[4]
++ * type_cdrom devkey[5]
++ * type_scanner devkey[6]
++ * type_mod devkey[7]
++ * type_changer devkey[8]
++ * type_commdev devkey[9]
++ * type_reserv devkey[A]
++ * type_reserv devkey[B]
++ * type_raid devkey[C]
++ * type_enclosure devkey[D]
++ * type_reserv devkey[E]
++ * type_reserv devkey[F]
++ */
++ const char *op_name; /* SCSI-2 op codes full name */
++ uint8_t direction; /* init --> target: SCST_DATA_WRITE
++ * target --> init: SCST_DATA_READ
++ */
++ uint16_t flags; /* opcode -- various flags */
++ uint8_t off; /* length offset in cdb */
++ int (*get_trans_len)(struct scst_cmd *cmd, uint8_t off);
++};
++
++static int scst_scsi_op_list[256];
++
++#define FLAG_NONE 0
++
++static const struct scst_sdbops scst_scsi_op_table[] = {
++ /*
++ * +-------------------> TYPE_IS_DISK (0)
++ * |
++ * |+------------------> TYPE_IS_TAPE (1)
++ * ||
++ * || +----------------> TYPE_IS_PROCESSOR (3)
++ * || |
++ * || | +--------------> TYPE_IS_CDROM (5)
++ * || | |
++ * || | | +------------> TYPE_IS_MOD (7)
++ * || | | |
++ * || | | |+-----------> TYPE_IS_CHANGER (8)
++ * || | | ||
++ * || | | || +-------> TYPE_IS_RAID (C)
++ * || | | || |
++ * || | | || |
++ * 0123456789ABCDEF ---> TYPE_IS_???? */
++
++ /* 6-bytes length CDB */
++ {0x00, "MMMMMMMMMMMMMMMM", "TEST UNIT READY",
++ /* let's be HQ to don't look dead under high load */
++ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|
++ SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_EXCL_ACCESS_ALLOWED,
++ 0, get_trans_len_none},
++ {0x01, " M ", "REWIND",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x01, "O V OO OO ", "REZERO UNIT",
++ SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x02, "VVVVVV V ", "REQUEST BLOCK ADDR",
++ SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
++ {0x03, "MMMMMMMMMMMMMMMM", "REQUEST SENSE",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_SKIP_UA|SCST_LOCAL_CMD|
++ SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 4, get_trans_len_1},
++ {0x04, "M O O ", "FORMAT UNIT",
++ SCST_DATA_WRITE, SCST_LONG_TIMEOUT|SCST_UNKNOWN_LENGTH|SCST_WRITE_MEDIUM,
++ 0, get_trans_len_none},
++ {0x04, " O ", "FORMAT",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0x05, "VMVVVV V ", "READ BLOCK LIMITS",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT|
++ SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 0, get_trans_len_block_limit},
++ {0x07, " O ", "INITIALIZE ELEMENT STATUS",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0x07, "OVV O OV ", "REASSIGN BLOCKS",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0x08, "O ", "READ(6)",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_WRITE_EXCL_ALLOWED,
++ 4, get_trans_len_1_256},
++ {0x08, " MV OO OV ", "READ(6)",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
++ SCST_WRITE_EXCL_ALLOWED,
++ 2, get_trans_len_3},
++ {0x08, " M ", "GET MESSAGE(6)",
++ SCST_DATA_READ, FLAG_NONE, 2, get_trans_len_3},
++ {0x08, " O ", "RECEIVE",
++ SCST_DATA_READ, FLAG_NONE, 2, get_trans_len_3},
++ {0x0A, "O ", "WRITE(6)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_WRITE_MEDIUM,
++ 4, get_trans_len_1_256},
++ {0x0A, " M O OV ", "WRITE(6)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
++ 2, get_trans_len_3},
++ {0x0A, " M ", "PRINT",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x0A, " M ", "SEND MESSAGE(6)",
++ SCST_DATA_WRITE, FLAG_NONE, 2, get_trans_len_3},
++ {0x0A, " M ", "SEND(6)",
++ SCST_DATA_WRITE, FLAG_NONE, 2, get_trans_len_3},
++ {0x0B, "O OO OV ", "SEEK(6)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x0B, " ", "TRACK SELECT",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x0B, " O ", "SLEW AND PRINT",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x0C, "VVVVVV V ", "SEEK BLOCK",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0x0D, "VVVVVV V ", "PARTITION",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
++ 0, get_trans_len_none},
++ {0x0F, "VOVVVV V ", "READ REVERSE",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
++ SCST_WRITE_EXCL_ALLOWED,
++ 2, get_trans_len_3},
++ {0x10, "VM V V ", "WRITE FILEMARKS",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0x10, " O O ", "SYNCHRONIZE BUFFER",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x11, "VMVVVV ", "SPACE",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|
++ SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x12, "MMMMMMMMMMMMMMMM", "INQUIRY",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA|
++ SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
++ 4, get_trans_len_1},
++ {0x13, "VOVVVV ", "VERIFY(6)",
++ SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
++ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED,
++ 2, get_trans_len_3},
++ {0x14, "VOOVVV ", "RECOVER BUFFERED DATA",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
++ SCST_WRITE_EXCL_ALLOWED,
++ 2, get_trans_len_3},
++ {0x15, "OMOOOOOOOOOOOOOO", "MODE SELECT(6)",
++ SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 4, get_trans_len_1},
++ {0x16, "MMMMMMMMMMMMMMMM", "RESERVE",
++ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
++ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
++ 0, get_trans_len_none},
++ {0x17, "MMMMMMMMMMMMMMMM", "RELEASE",
++ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
++ SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
++ 0, get_trans_len_none},
++ {0x18, "OOOOOOOO ", "COPY",
++ SCST_DATA_WRITE, SCST_LONG_TIMEOUT, 2, get_trans_len_3},
++ {0x19, "VMVVVV ", "ERASE",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
++ 0, get_trans_len_none},
++ {0x1A, "OMOOOOOOOOOOOOOO", "MODE SENSE(6)",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT, 4, get_trans_len_1},
++ {0x1B, " O ", "SCAN",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x1B, " O ", "LOAD UNLOAD",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0x1B, " O ", "STOP PRINT",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x1B, "O OO O O ", "START STOP UNIT",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_start_stop},
++ {0x1C, "OOOOOOOOOOOOOOOO", "RECEIVE DIAGNOSTIC RESULTS",
++ SCST_DATA_READ, FLAG_NONE, 3, get_trans_len_2},
++ {0x1D, "MMMMMMMMMMMMMMMM", "SEND DIAGNOSTIC",
++ SCST_DATA_WRITE, FLAG_NONE, 4, get_trans_len_1},
++ {0x1E, "OOOOOOOOOOOOOOOO", "PREVENT ALLOW MEDIUM REMOVAL",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0,
++ get_trans_len_prevent_allow_medium_removal},
++ {0x1F, " O ", "PORT STATUS",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++
++ /* 10-bytes length CDB */
++ {0x23, "V VV V ", "READ FORMAT CAPACITY",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x24, "V VVM ", "SET WINDOW",
++ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3},
++ {0x25, "M MM M ", "READ CAPACITY",
++ SCST_DATA_READ, SCST_IMPLICIT_HQ|
++ SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 0, get_trans_len_read_capacity},
++ {0x25, " O ", "GET WINDOW",
++ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_3},
++ {0x28, "M MMMM ", "READ(10)",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_WRITE_EXCL_ALLOWED,
++ 7, get_trans_len_2},
++ {0x28, " O ", "GET MESSAGE(10)",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x29, "V VV O ", "READ GENERATION",
++ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_1},
++ {0x2A, "O MO M ", "WRITE(10)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_WRITE_MEDIUM,
++ 7, get_trans_len_2},
++ {0x2A, " O ", "SEND MESSAGE(10)",
++ SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
++ {0x2A, " O ", "SEND(10)",
++ SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
++ {0x2B, " O ", "LOCATE",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|
++ SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x2B, " O ", "POSITION TO ELEMENT",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0x2B, "O OO O ", "SEEK(10)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x2C, "V O O ", "ERASE(10)",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
++ 0, get_trans_len_none},
++ {0x2D, "V O O ", "READ UPDATED BLOCK",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 0, get_trans_len_single},
++ {0x2E, "O OO O ", "WRITE AND VERIFY(10)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
++ 7, get_trans_len_2},
++ {0x2F, "O OO O ", "VERIFY(10)",
++ SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
++ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED,
++ 7, get_trans_len_2},
++ {0x33, "O OO O ", "SET LIMITS(10)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x34, " O ", "READ POSITION",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT|
++ SCST_WRITE_EXCL_ALLOWED,
++ 7, get_trans_len_read_pos},
++ {0x34, " O ", "GET DATA BUFFER STATUS",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x34, "O OO O ", "PRE-FETCH",
++ SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x35, "O OO O ", "SYNCHRONIZE CACHE",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x36, "O OO O ", "LOCK UNLOCK CACHE",
++ SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x37, "O O ", "READ DEFECT DATA(10)",
++ SCST_DATA_READ, SCST_WRITE_EXCL_ALLOWED,
++ 8, get_trans_len_1},
++ {0x37, " O ", "INIT ELEMENT STATUS WRANGE",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0x38, " O O ", "MEDIUM SCAN",
++ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_1},
++ {0x39, "OOOOOOOO ", "COMPARE",
++ SCST_DATA_WRITE, FLAG_NONE, 3, get_trans_len_3},
++ {0x3A, "OOOOOOOO ", "COPY AND VERIFY",
++ SCST_DATA_WRITE, FLAG_NONE, 3, get_trans_len_3},
++ {0x3B, "OOOOOOOOOOOOOOOO", "WRITE BUFFER",
++ SCST_DATA_WRITE, SCST_SMALL_TIMEOUT, 6, get_trans_len_3},
++ {0x3C, "OOOOOOOOOOOOOOOO", "READ BUFFER",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT, 6, get_trans_len_3},
++ {0x3D, " O O ", "UPDATE BLOCK",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED,
++ 0, get_trans_len_single},
++ {0x3E, "O OO O ", "READ LONG",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x3F, "O O O ", "WRITE LONG",
++ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 7, get_trans_len_2},
++ {0x40, "OOOOOOOOOO ", "CHANGE DEFINITION",
++ SCST_DATA_WRITE, SCST_SMALL_TIMEOUT, 8, get_trans_len_1},
++ {0x41, "O O ", "WRITE SAME",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
++ 0, get_trans_len_single},
++ {0x42, " O ", "READ SUB-CHANNEL",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x43, " O ", "READ TOC/PMA/ATIP",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x44, " M ", "REPORT DENSITY SUPPORT",
++ SCST_DATA_READ, SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 7, get_trans_len_2},
++ {0x44, " O ", "READ HEADER",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x45, " O ", "PLAY AUDIO(10)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x46, " O ", "GET CONFIGURATION",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x47, " O ", "PLAY AUDIO MSF",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x48, " O ", "PLAY AUDIO TRACK INDEX",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x49, " O ", "PLAY TRACK RELATIVE(10)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x4A, " O ", "GET EVENT STATUS NOTIFICATION",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x4B, " O ", "PAUSE/RESUME",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x4C, "OOOOOOOOOOOOOOOO", "LOG SELECT",
++ SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 7, get_trans_len_2},
++ {0x4D, "OOOOOOOOOOOOOOOO", "LOG SENSE",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT|
++ SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 7, get_trans_len_2},
++ {0x4E, " O ", "STOP PLAY/SCAN",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x50, " ", "XDWRITE",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0x51, " O ", "READ DISC INFORMATION",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x51, " ", "XPWRITE",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0x52, " O ", "READ TRACK INFORMATION",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x53, "O ", "XDWRITEREAD(10)",
++ SCST_DATA_READ|SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
++ SCST_WRITE_MEDIUM,
++ 7, get_bidi_trans_len_2},
++ {0x53, " O ", "RESERVE TRACK",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x54, " O ", "SEND OPC INFORMATION",
++ SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
++ {0x55, "OOOOOOOOOOOOOOOO", "MODE SELECT(10)",
++ SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 7, get_trans_len_2},
++ {0x56, "OOOOOOOOOOOOOOOO", "RESERVE(10)",
++ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD,
++ 0, get_trans_len_none},
++ {0x57, "OOOOOOOOOOOOOOOO", "RELEASE(10)",
++ SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
++ SCST_REG_RESERVE_ALLOWED,
++ 0, get_trans_len_none},
++ {0x58, " O ", "REPAIR TRACK",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0x5A, "OOOOOOOOOOOOOOOO", "MODE SENSE(10)",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT, 7, get_trans_len_2},
++ {0x5B, " O ", "CLOSE TRACK/SESSION",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x5C, " O ", "READ BUFFER CAPACITY",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
++ {0x5D, " O ", "SEND CUE SHEET",
++ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3},
++ {0x5E, "OOOOO OOOO ", "PERSISTENT RESERV IN",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT|
++ SCST_LOCAL_CMD|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 5, get_trans_len_4},
++ {0x5F, "OOOOO OOOO ", "PERSISTENT RESERV OUT",
++ SCST_DATA_WRITE, SCST_SMALL_TIMEOUT|
++ SCST_LOCAL_CMD|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 5, get_trans_len_4},
++
++ /* 16-bytes length CDB */
++ {0x80, "O OO O ", "XDWRITE EXTENDED",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0x80, " M ", "WRITE FILEMARKS",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0x81, "O OO O ", "REBUILD",
++ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
++ {0x82, "O OO O ", "REGENERATE",
++ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
++ {0x83, "OOOOOOOOOOOOOOOO", "EXTENDED COPY",
++ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
++ {0x84, "OOOOOOOOOOOOOOOO", "RECEIVE COPY RESULT",
++ SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4},
++ {0x86, "OOOOOOOOOO ", "ACCESS CONTROL IN",
++ SCST_DATA_NONE, SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 0, get_trans_len_none},
++ {0x87, "OOOOOOOOOO ", "ACCESS CONTROL OUT",
++ SCST_DATA_NONE, SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|
++ SCST_EXCL_ACCESS_ALLOWED,
++ 0, get_trans_len_none},
++ {0x88, "M MMMM ", "READ(16)",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_WRITE_EXCL_ALLOWED,
++ 10, get_trans_len_4},
++ {0x8A, "O OO O ", "WRITE(16)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_WRITE_MEDIUM,
++ 10, get_trans_len_4},
++ {0x8C, "OOOOOOOOOO ", "READ ATTRIBUTE",
++ SCST_DATA_READ, FLAG_NONE, 10, get_trans_len_4},
++ {0x8D, "OOOOOOOOOO ", "WRITE ATTRIBUTE",
++ SCST_DATA_WRITE, SCST_WRITE_MEDIUM, 10, get_trans_len_4},
++ {0x8E, "O OO O ", "WRITE AND VERIFY(16)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
++ 10, get_trans_len_4},
++ {0x8F, "O OO O ", "VERIFY(16)",
++ SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
++ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED,
++ 10, get_trans_len_4},
++ {0x90, "O OO O ", "PRE-FETCH(16)",
++ SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x91, "O OO O ", "SYNCHRONIZE CACHE(16)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x91, " M ", "SPACE(16)",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|
++ SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x92, "O OO O ", "LOCK UNLOCK CACHE(16)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0x92, " O ", "LOCATE(16)",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|
++ SCST_WRITE_EXCL_ALLOWED,
++ 0, get_trans_len_none},
++ {0x93, "O O ", "WRITE SAME(16)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
++ 10, get_trans_len_4},
++ {0x93, " M ", "ERASE(16)",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
++ 0, get_trans_len_none},
++ {0x9E, "O ", "SERVICE ACTION IN",
++ SCST_DATA_READ, FLAG_NONE, 0, get_trans_len_serv_act_in},
++
++ /* 12-bytes length CDB */
++ {0xA0, "VVVVVVVVVV M ", "REPORT LUNS",
++ SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA|
++ SCST_FULLY_LOCAL_CMD|SCST_LOCAL_CMD|
++ SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
++ 6, get_trans_len_4},
++ {0xA1, " O ", "BLANK",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0xA3, " O ", "SEND KEY",
++ SCST_DATA_WRITE, FLAG_NONE, 8, get_trans_len_2},
++ {0xA3, "OOOOO OOOO ", "REPORT DEVICE IDENTIDIER",
++ SCST_DATA_READ, SCST_REG_RESERVE_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
++ 6, get_trans_len_4},
++ {0xA3, " M ", "MAINTENANCE(IN)",
++ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
++ {0xA4, " O ", "REPORT KEY",
++ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2},
++ {0xA4, " O ", "MAINTENANCE(OUT)",
++ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
++ {0xA5, " M ", "MOVE MEDIUM",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0xA5, " O ", "PLAY AUDIO(12)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0xA6, " O O ", "EXCHANGE/LOAD/UNLOAD MEDIUM",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0xA7, " O ", "SET READ AHEAD",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0xA8, " O ", "GET MESSAGE(12)",
++ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
++ {0xA8, "O OO O ", "READ(12)",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_WRITE_EXCL_ALLOWED,
++ 6, get_trans_len_4},
++ {0xA9, " O ", "PLAY TRACK RELATIVE(12)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0xAA, "O OO O ", "WRITE(12)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ SCST_TEST_IO_IN_SIRQ_ALLOWED|
++#endif
++ SCST_WRITE_MEDIUM,
++ 6, get_trans_len_4},
++ {0xAA, " O ", "SEND MESSAGE(12)",
++ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
++ {0xAC, " O ", "ERASE(12)",
++ SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
++ {0xAC, " M ", "GET PERFORMANCE",
++ SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none},
++ {0xAD, " O ", "READ DVD STRUCTURE",
++ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2},
++ {0xAE, "O OO O ", "WRITE AND VERIFY(12)",
++ SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
++ 6, get_trans_len_4},
++ {0xAF, "O OO O ", "VERIFY(12)",
++ SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
++ SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
++ SCST_WRITE_EXCL_ALLOWED,
++ 6, get_trans_len_4},
++#if 0 /* No need to support at all */
++ {0xB0, " OO O ", "SEARCH DATA HIGH(12)",
++ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1},
++ {0xB1, " OO O ", "SEARCH DATA EQUAL(12)",
++ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1},
++ {0xB2, " OO O ", "SEARCH DATA LOW(12)",
++ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1},
++#endif
++ {0xB3, " OO O ", "SET LIMITS(12)",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0xB5, " O ", "REQUEST VOLUME ELEMENT ADDRESS",
++ SCST_DATA_READ, FLAG_NONE, 9, get_trans_len_1},
++ {0xB6, " O ", "SEND VOLUME TAG",
++ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1},
++ {0xB6, " M ", "SET STREAMING",
++ SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_2},
++ {0xB7, " O ", "READ DEFECT DATA(12)",
++ SCST_DATA_READ, SCST_WRITE_EXCL_ALLOWED,
++ 9, get_trans_len_1},
++ {0xB8, " O ", "READ ELEMENT STATUS",
++ SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_3_read_elem_stat},
++ {0xB9, " O ", "READ CD MSF",
++ SCST_DATA_READ, SCST_UNKNOWN_LENGTH, 0, get_trans_len_none},
++ {0xBA, " O ", "SCAN",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
++ {0xBA, " O ", "REDUNDANCY GROUP(IN)",
++ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
++ {0xBB, " O ", "SET SPEED",
++ SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
++ {0xBB, " O ", "REDUNDANCY GROUP(OUT)",
++ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
++ {0xBC, " O ", "SPARE(IN)",
++ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
++ {0xBD, " O ", "MECHANISM STATUS",
++ SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_2},
++ {0xBD, " O ", "SPARE(OUT)",
++ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
++ {0xBE, " O ", "READ CD",
++ SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 6, get_trans_len_3},
++ {0xBE, " O ", "VOLUME SET(IN)",
++ SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
++ {0xBF, " O ", "SEND DVD STRUCTUE",
++ SCST_DATA_WRITE, FLAG_NONE, 8, get_trans_len_2},
++ {0xBF, " O ", "VOLUME SET(OUT)",
++ SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
++ {0xE7, " V ", "INIT ELEMENT STATUS WRANGE",
++ SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_cdb_len_10}
++};
++
++#define SCST_CDB_TBL_SIZE ((int)ARRAY_SIZE(scst_scsi_op_table))
++
++static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev);
++static void scst_check_internal_sense(struct scst_device *dev, int result,
++ uint8_t *sense, int sense_len);
++static void scst_queue_report_luns_changed_UA(struct scst_session *sess,
++ int flags);
++static void __scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
++ const uint8_t *sense, int sense_len, int flags);
++static void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev,
++ const uint8_t *sense, int sense_len, int flags);
++static void scst_free_all_UA(struct scst_tgt_dev *tgt_dev);
++static void scst_release_space(struct scst_cmd *cmd);
++static void scst_unblock_cmds(struct scst_device *dev);
++static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev);
++static int scst_alloc_add_tgt_dev(struct scst_session *sess,
++ struct scst_acg_dev *acg_dev, struct scst_tgt_dev **out_tgt_dev);
++static void scst_tgt_retry_timer_fn(unsigned long arg);
++
++#ifdef CONFIG_SCST_DEBUG_TM
++static void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev);
++static void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev);
++#else
++static inline void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev) {}
++static inline void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev) {}
++#endif /* CONFIG_SCST_DEBUG_TM */
++
++/**
++ * scst_alloc_sense() - allocate sense buffer for command
++ *
++ * Allocates, if necessary, sense buffer for command. Returns 0 on success
++ * and error code othrwise. Parameter "atomic" should be non-0 if the
++ * function called in atomic context.
++ */
++int scst_alloc_sense(struct scst_cmd *cmd, int atomic)
++{
++ int res = 0;
++ gfp_t gfp_mask = atomic ? GFP_ATOMIC : (GFP_KERNEL|__GFP_NOFAIL);
++
++ TRACE_ENTRY();
++
++ if (cmd->sense != NULL)
++ goto memzero;
++
++ cmd->sense = mempool_alloc(scst_sense_mempool, gfp_mask);
++ if (cmd->sense == NULL) {
++ PRINT_CRIT_ERROR("Sense memory allocation failed (op %x). "
++ "The sense data will be lost!!", cmd->cdb[0]);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ cmd->sense_buflen = SCST_SENSE_BUFFERSIZE;
++
++memzero:
++ cmd->sense_valid_len = 0;
++ memset(cmd->sense, 0, cmd->sense_buflen);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL(scst_alloc_sense);
++
++/**
++ * scst_alloc_set_sense() - allocate and fill sense buffer for command
++ *
++ * Allocates, if necessary, sense buffer for command and copies in
++ * it data from the supplied sense buffer. Returns 0 on success
++ * and error code othrwise.
++ */
++int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
++ const uint8_t *sense, unsigned int len)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ /*
++ * We don't check here if the existing sense is valid or not, because
++ * we suppose the caller did it based on cmd->status.
++ */
++
++ res = scst_alloc_sense(cmd, atomic);
++ if (res != 0) {
++ PRINT_BUFFER("Lost sense", sense, len);
++ goto out;
++ }
++
++ cmd->sense_valid_len = len;
++ if (cmd->sense_buflen < len) {
++ PRINT_WARNING("Sense truncated (needed %d), shall you increase "
++ "SCST_SENSE_BUFFERSIZE? Op: %x", len, cmd->cdb[0]);
++ cmd->sense_valid_len = cmd->sense_buflen;
++ }
++
++ memcpy(cmd->sense, sense, cmd->sense_valid_len);
++ TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_valid_len);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL(scst_alloc_set_sense);
++
++/**
++ * scst_set_cmd_error_status() - set error SCSI status
++ * @cmd: SCST command
++ * @status: SCSI status to set
++ *
++ * Description:
++ * Sets error SCSI status in the command and prepares it for returning it.
++ * Returns 0 on success, error code otherwise.
++ */
++int scst_set_cmd_error_status(struct scst_cmd *cmd, int status)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (cmd->status != 0) {
++ TRACE_MGMT_DBG("cmd %p already has status %x set", cmd,
++ cmd->status);
++ res = -EEXIST;
++ goto out;
++ }
++
++ cmd->status = status;
++ cmd->host_status = DID_OK;
++
++ cmd->dbl_ua_orig_resp_data_len = cmd->resp_data_len;
++ cmd->dbl_ua_orig_data_direction = cmd->data_direction;
++
++ cmd->data_direction = SCST_DATA_NONE;
++ cmd->resp_data_len = 0;
++ cmd->resid_possible = 1;
++ cmd->is_send_status = 1;
++
++ cmd->completed = 1;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL(scst_set_cmd_error_status);
++
++static int scst_set_lun_not_supported_request_sense(struct scst_cmd *cmd,
++ int key, int asc, int ascq)
++{
++ int res;
++ int sense_len, len;
++ struct scatterlist *sg;
++
++ TRACE_ENTRY();
++
++ if (cmd->status != 0) {
++ TRACE_MGMT_DBG("cmd %p already has status %x set", cmd,
++ cmd->status);
++ res = -EEXIST;
++ goto out;
++ }
++
++ if ((cmd->sg != NULL) && SCST_SENSE_VALID(sg_virt(cmd->sg))) {
++ TRACE_MGMT_DBG("cmd %p already has sense set", cmd);
++ res = -EEXIST;
++ goto out;
++ }
++
++ if (cmd->sg == NULL) {
++ /*
++ * If target driver preparing data buffer using alloc_data_buf()
++ * callback, it is responsible to copy the sense to its buffer
++ * in xmit_response().
++ */
++ if (cmd->tgt_data_buf_alloced && (cmd->tgt_sg != NULL)) {
++ cmd->sg = cmd->tgt_sg;
++ cmd->sg_cnt = cmd->tgt_sg_cnt;
++ TRACE_MEM("Tgt sg used for sense for cmd %p", cmd);
++ goto go;
++ }
++
++ if (cmd->bufflen == 0)
++ cmd->bufflen = cmd->cdb[4];
++
++ cmd->sg = scst_alloc(cmd->bufflen, GFP_ATOMIC, &cmd->sg_cnt);
++ if (cmd->sg == NULL) {
++ PRINT_ERROR("Unable to alloc sg for REQUEST SENSE"
++ "(sense %x/%x/%x)", key, asc, ascq);
++ res = 1;
++ goto out;
++ }
++
++ TRACE_MEM("sg %p alloced for sense for cmd %p (cnt %d, "
++ "len %d)", cmd->sg, cmd, cmd->sg_cnt, cmd->bufflen);
++ }
++
++go:
++ sg = cmd->sg;
++ len = sg->length;
++
++ TRACE_MEM("sg %p (len %d) for sense for cmd %p", sg, len, cmd);
++
++ sense_len = scst_set_sense(sg_virt(sg), len, cmd->cdb[1] & 1,
++ key, asc, ascq);
++
++ TRACE_BUFFER("Sense set", sg_virt(sg), sense_len);
++
++ cmd->data_direction = SCST_DATA_READ;
++ scst_set_resp_data_len(cmd, sense_len);
++
++ res = 0;
++ cmd->completed = 1;
++ cmd->resid_possible = 1;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_set_lun_not_supported_inquiry(struct scst_cmd *cmd)
++{
++ int res;
++ uint8_t *buf;
++ struct scatterlist *sg;
++ int len;
++
++ TRACE_ENTRY();
++
++ if (cmd->status != 0) {
++ TRACE_MGMT_DBG("cmd %p already has status %x set", cmd,
++ cmd->status);
++ res = -EEXIST;
++ goto out;
++ }
++
++ if (cmd->sg == NULL) {
++ /*
++ * If target driver preparing data buffer using alloc_data_buf()
++ * callback, it is responsible to copy the sense to its buffer
++ * in xmit_response().
++ */
++ if (cmd->tgt_data_buf_alloced && (cmd->tgt_sg != NULL)) {
++ cmd->sg = cmd->tgt_sg;
++ cmd->sg_cnt = cmd->tgt_sg_cnt;
++ TRACE_MEM("Tgt used for INQUIRY for not supported "
++ "LUN for cmd %p", cmd);
++ goto go;
++ }
++
++ if (cmd->bufflen == 0)
++ cmd->bufflen = min_t(int, 36, (cmd->cdb[3] << 8) | cmd->cdb[4]);
++
++ cmd->sg = scst_alloc(cmd->bufflen, GFP_ATOMIC, &cmd->sg_cnt);
++ if (cmd->sg == NULL) {
++ PRINT_ERROR("%s", "Unable to alloc sg for INQUIRY "
++ "for not supported LUN");
++ res = 1;
++ goto out;
++ }
++
++ TRACE_MEM("sg %p alloced for INQUIRY for not supported LUN for "
++ "cmd %p (cnt %d, len %d)", cmd->sg, cmd, cmd->sg_cnt,
++ cmd->bufflen);
++ }
++
++go:
++ sg = cmd->sg;
++ len = sg->length;
++
++ TRACE_MEM("sg %p (len %d) for INQUIRY for cmd %p", sg, len, cmd);
++
++ buf = sg_virt(sg);
++ len = min_t(int, 36, len);
++
++ memset(buf, 0, len);
++ buf[0] = 0x7F; /* Peripheral qualifier 011b, Peripheral device type 1Fh */
++ buf[4] = len - 4;
++
++ TRACE_BUFFER("INQUIRY for not supported LUN set", buf, len);
++
++ cmd->data_direction = SCST_DATA_READ;
++ scst_set_resp_data_len(cmd, len);
++
++ res = 0;
++ cmd->completed = 1;
++ cmd->resid_possible = 1;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * scst_set_cmd_error() - set error in the command and fill the sense buffer.
++ *
++ * Sets error in the command and fill the sense buffer. Returns 0 on success,
++ * error code otherwise.
++ */
++int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ /*
++ * We need for LOGICAL UNIT NOT SUPPORTED special handling for
++ * REQUEST SENSE and INQUIRY.
++ */
++ if ((key == ILLEGAL_REQUEST) && (asc == 0x25) && (ascq == 0)) {
++ if (cmd->cdb[0] == REQUEST_SENSE)
++ res = scst_set_lun_not_supported_request_sense(cmd,
++ key, asc, ascq);
++ else if (cmd->cdb[0] == INQUIRY)
++ res = scst_set_lun_not_supported_inquiry(cmd);
++ else
++ goto do_sense;
++
++ if (res > 0)
++ goto do_sense;
++ else
++ goto out;
++ }
++
++do_sense:
++ res = scst_set_cmd_error_status(cmd, SAM_STAT_CHECK_CONDITION);
++ if (res != 0)
++ goto out;
++
++ res = scst_alloc_sense(cmd, 1);
++ if (res != 0) {
++ PRINT_ERROR("Lost sense data (key %x, asc %x, ascq %x)",
++ key, asc, ascq);
++ goto out;
++ }
++
++ cmd->sense_valid_len = scst_set_sense(cmd->sense, cmd->sense_buflen,
++ scst_get_cmd_dev_d_sense(cmd), key, asc, ascq);
++ TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_valid_len);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL(scst_set_cmd_error);
++
++/**
++ * scst_set_sense() - set sense from KEY/ASC/ASCQ numbers
++ *
++ * Sets the corresponding fields in the sense buffer taking sense type
++ * into account. Returns resulting sense length.
++ */
++int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
++ int key, int asc, int ascq)
++{
++ int res;
++
++ BUG_ON(len == 0);
++
++ memset(buffer, 0, len);
++
++ if (d_sense) {
++ /* Descriptor format */
++ if (len < 8) {
++ PRINT_ERROR("Length %d of sense buffer too small to "
++ "fit sense %x:%x:%x", len, key, asc, ascq);
++ }
++
++ buffer[0] = 0x72; /* Response Code */
++ if (len > 1)
++ buffer[1] = key; /* Sense Key */
++ if (len > 2)
++ buffer[2] = asc; /* ASC */
++ if (len > 3)
++ buffer[3] = ascq; /* ASCQ */
++ res = 8;
++ } else {
++ /* Fixed format */
++ if (len < 18) {
++ PRINT_ERROR("Length %d of sense buffer too small to "
++ "fit sense %x:%x:%x", len, key, asc, ascq);
++ }
++
++ buffer[0] = 0x70; /* Response Code */
++ if (len > 2)
++ buffer[2] = key; /* Sense Key */
++ if (len > 7)
++ buffer[7] = 0x0a; /* Additional Sense Length */
++ if (len > 12)
++ buffer[12] = asc; /* ASC */
++ if (len > 13)
++ buffer[13] = ascq; /* ASCQ */
++ res = 18;
++ }
++
++ TRACE_BUFFER("Sense set", buffer, res);
++ return res;
++}
++EXPORT_SYMBOL(scst_set_sense);
++
++/**
++ * scst_analyze_sense() - analyze sense
++ *
++ * Returns true if sense matches to (key, asc, ascq) and false otherwise.
++ * Valid_mask is one or several SCST_SENSE_*_VALID constants setting valid
++ * (key, asc, ascq) values.
++ */
++bool scst_analyze_sense(const uint8_t *sense, int len, unsigned int valid_mask,
++ int key, int asc, int ascq)
++{
++ bool res = false;
++
++ /* Response Code */
++ if ((sense[0] == 0x70) || (sense[0] == 0x71)) {
++ /* Fixed format */
++
++ /* Sense Key */
++ if (valid_mask & SCST_SENSE_KEY_VALID) {
++ if (len < 3)
++ goto out;
++ if (sense[2] != key)
++ goto out;
++ }
++
++ /* ASC */
++ if (valid_mask & SCST_SENSE_ASC_VALID) {
++ if (len < 13)
++ goto out;
++ if (sense[12] != asc)
++ goto out;
++ }
++
++ /* ASCQ */
++ if (valid_mask & SCST_SENSE_ASCQ_VALID) {
++ if (len < 14)
++ goto out;
++ if (sense[13] != ascq)
++ goto out;
++ }
++ } else if ((sense[0] == 0x72) || (sense[0] == 0x73)) {
++ /* Descriptor format */
++
++ /* Sense Key */
++ if (valid_mask & SCST_SENSE_KEY_VALID) {
++ if (len < 2)
++ goto out;
++ if (sense[1] != key)
++ goto out;
++ }
++
++ /* ASC */
++ if (valid_mask & SCST_SENSE_ASC_VALID) {
++ if (len < 3)
++ goto out;
++ if (sense[2] != asc)
++ goto out;
++ }
++
++ /* ASCQ */
++ if (valid_mask & SCST_SENSE_ASCQ_VALID) {
++ if (len < 4)
++ goto out;
++ if (sense[3] != ascq)
++ goto out;
++ }
++ } else
++ goto out;
++
++ res = true;
++
++out:
++ TRACE_EXIT_RES((int)res);
++ return res;
++}
++EXPORT_SYMBOL(scst_analyze_sense);
++
++/**
++ * scst_is_ua_sense() - determine if the sense is UA sense
++ *
++ * Returns true if the sense is valid and carrying a Unit
++ * Attention or false otherwise.
++ */
++bool scst_is_ua_sense(const uint8_t *sense, int len)
++{
++ if (SCST_SENSE_VALID(sense))
++ return scst_analyze_sense(sense, len,
++ SCST_SENSE_KEY_VALID, UNIT_ATTENTION, 0, 0);
++ else
++ return false;
++}
++EXPORT_SYMBOL(scst_is_ua_sense);
++
++bool scst_is_ua_global(const uint8_t *sense, int len)
++{
++ bool res;
++
++ /* Changing it don't forget to change scst_requeue_ua() as well!! */
++
++ if (scst_analyze_sense(sense, len, SCST_SENSE_ALL_VALID,
++ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed)))
++ res = true;
++ else
++ res = false;
++
++ return res;
++}
++
++/**
++ * scst_check_convert_sense() - check sense type and convert it if needed
++ *
++ * Checks if sense in the sense buffer, if any, is in the correct format.
++ * If not, converts it in the correct format.
++ */
++void scst_check_convert_sense(struct scst_cmd *cmd)
++{
++ bool d_sense;
++
++ TRACE_ENTRY();
++
++ if ((cmd->sense == NULL) || (cmd->status != SAM_STAT_CHECK_CONDITION))
++ goto out;
++
++ d_sense = scst_get_cmd_dev_d_sense(cmd);
++ if (d_sense && ((cmd->sense[0] == 0x70) || (cmd->sense[0] == 0x71))) {
++ TRACE_MGMT_DBG("Converting fixed sense to descriptor (cmd %p)",
++ cmd);
++ if ((cmd->sense_valid_len < 18)) {
++ PRINT_ERROR("Sense too small to convert (%d, "
++ "type: fixed)", cmd->sense_buflen);
++ goto out;
++ }
++ cmd->sense_valid_len = scst_set_sense(cmd->sense, cmd->sense_buflen,
++ d_sense, cmd->sense[2], cmd->sense[12], cmd->sense[13]);
++ } else if (!d_sense && ((cmd->sense[0] == 0x72) ||
++ (cmd->sense[0] == 0x73))) {
++ TRACE_MGMT_DBG("Converting descriptor sense to fixed (cmd %p)",
++ cmd);
++ if ((cmd->sense_buflen < 18) || (cmd->sense_valid_len < 8)) {
++ PRINT_ERROR("Sense too small to convert (%d, "
++ "type: descryptor, valid %d)",
++ cmd->sense_buflen, cmd->sense_valid_len);
++ goto out;
++ }
++ cmd->sense_valid_len = scst_set_sense(cmd->sense,
++ cmd->sense_buflen, d_sense,
++ cmd->sense[1], cmd->sense[2], cmd->sense[3]);
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_check_convert_sense);
++
++static int scst_set_cmd_error_sense(struct scst_cmd *cmd, uint8_t *sense,
++ unsigned int len)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ res = scst_set_cmd_error_status(cmd, SAM_STAT_CHECK_CONDITION);
++ if (res != 0)
++ goto out;
++
++ res = scst_alloc_set_sense(cmd, 1, sense, len);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * scst_set_busy() - set BUSY or TASK QUEUE FULL status
++ *
++ * Sets BUSY or TASK QUEUE FULL status depending on if this session has other
++ * outstanding commands or not.
++ */
++void scst_set_busy(struct scst_cmd *cmd)
++{
++ int c = atomic_read(&cmd->sess->sess_cmd_count);
++
++ TRACE_ENTRY();
++
++ if ((c <= 1) || (cmd->sess->init_phase != SCST_SESS_IPH_READY)) {
++ scst_set_cmd_error_status(cmd, SAM_STAT_BUSY);
++ TRACE(TRACE_FLOW_CONTROL, "Sending BUSY status to initiator %s "
++ "(cmds count %d, queue_type %x, sess->init_phase %d)",
++ cmd->sess->initiator_name, c,
++ cmd->queue_type, cmd->sess->init_phase);
++ } else {
++ scst_set_cmd_error_status(cmd, SAM_STAT_TASK_SET_FULL);
++ TRACE(TRACE_FLOW_CONTROL, "Sending QUEUE_FULL status to "
++ "initiator %s (cmds count %d, queue_type %x, "
++ "sess->init_phase %d)", cmd->sess->initiator_name, c,
++ cmd->queue_type, cmd->sess->init_phase);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_set_busy);
++
++/**
++ * scst_set_initial_UA() - set initial Unit Attention
++ *
++ * Sets initial Unit Attention on all devices of the session,
++ * replacing default scst_sense_reset_UA
++ */
++void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq)
++{
++ int i;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Setting for sess %p initial UA %x/%x/%x", sess, key,
++ asc, ascq);
++
++ /* Protect sess_tgt_dev_list_hash */
++ mutex_lock(&scst_mutex);
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ struct scst_tgt_dev *tgt_dev;
++
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ spin_lock_bh(&tgt_dev->tgt_dev_lock);
++ if (!list_empty(&tgt_dev->UA_list)) {
++ struct scst_tgt_dev_UA *ua;
++
++ ua = list_entry(tgt_dev->UA_list.next,
++ typeof(*ua), UA_list_entry);
++ if (scst_analyze_sense(ua->UA_sense_buffer,
++ ua->UA_valid_sense_len,
++ SCST_SENSE_ALL_VALID,
++ SCST_LOAD_SENSE(scst_sense_reset_UA))) {
++ ua->UA_valid_sense_len = scst_set_sense(
++ ua->UA_sense_buffer,
++ sizeof(ua->UA_sense_buffer),
++ tgt_dev->dev->d_sense,
++ key, asc, ascq);
++ } else
++ PRINT_ERROR("%s",
++ "The first UA isn't RESET UA");
++ } else
++ PRINT_ERROR("%s", "There's no RESET UA to "
++ "replace");
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++ }
++ }
++
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_set_initial_UA);
++
++static struct scst_aen *scst_alloc_aen(struct scst_session *sess,
++ uint64_t unpacked_lun)
++{
++ struct scst_aen *aen;
++
++ TRACE_ENTRY();
++
++ aen = mempool_alloc(scst_aen_mempool, GFP_KERNEL);
++ if (aen == NULL) {
++ PRINT_ERROR("AEN memory allocation failed. Corresponding "
++ "event notification will not be performed (initiator "
++ "%s)", sess->initiator_name);
++ goto out;
++ }
++ memset(aen, 0, sizeof(*aen));
++
++ aen->sess = sess;
++ scst_sess_get(sess);
++
++ aen->lun = scst_pack_lun(unpacked_lun, sess->acg->addr_method);
++
++out:
++ TRACE_EXIT_HRES((unsigned long)aen);
++ return aen;
++};
++
++static void scst_free_aen(struct scst_aen *aen)
++{
++ TRACE_ENTRY();
++
++ scst_sess_put(aen->sess);
++ mempool_free(aen, scst_aen_mempool);
++
++ TRACE_EXIT();
++ return;
++};
++
++/* Must be called under scst_mutex */
++void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
++ int key, int asc, int ascq)
++{
++ struct scst_tgt_template *tgtt = tgt_dev->sess->tgt->tgtt;
++ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
++ int sl;
++
++ TRACE_ENTRY();
++
++ if ((tgt_dev->sess->init_phase != SCST_SESS_IPH_READY) ||
++ (tgt_dev->sess->shut_phase != SCST_SESS_SPH_READY))
++ goto out;
++
++ if (tgtt->report_aen != NULL) {
++ struct scst_aen *aen;
++ int rc;
++
++ aen = scst_alloc_aen(tgt_dev->sess, tgt_dev->lun);
++ if (aen == NULL)
++ goto queue_ua;
++
++ aen->event_fn = SCST_AEN_SCSI;
++ aen->aen_sense_len = scst_set_sense(aen->aen_sense,
++ sizeof(aen->aen_sense), tgt_dev->dev->d_sense,
++ key, asc, ascq);
++
++ TRACE_DBG("Calling target's %s report_aen(%p)",
++ tgtt->name, aen);
++ rc = tgtt->report_aen(aen);
++ TRACE_DBG("Target's %s report_aen(%p) returned %d",
++ tgtt->name, aen, rc);
++ if (rc == SCST_AEN_RES_SUCCESS)
++ goto out;
++
++ scst_free_aen(aen);
++ }
++
++queue_ua:
++ TRACE_MGMT_DBG("AEN not supported, queuing plain UA (tgt_dev %p)",
++ tgt_dev);
++ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
++ tgt_dev->dev->d_sense, key, asc, ascq);
++ scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_capacity_data_changed() - notify SCST about device capacity change
++ *
++ * Notifies SCST core that dev has changed its capacity. Called under no locks.
++ */
++void scst_capacity_data_changed(struct scst_device *dev)
++{
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ if (dev->type != TYPE_DISK) {
++ TRACE_MGMT_DBG("Device type %d isn't for CAPACITY DATA "
++ "CHANGED UA", dev->type);
++ goto out;
++ }
++
++ TRACE_MGMT_DBG("CAPACITY DATA CHANGED (dev %p)", dev);
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ scst_gen_aen_or_ua(tgt_dev,
++ SCST_LOAD_SENSE(scst_sense_capacity_data_changed));
++ }
++
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_capacity_data_changed);
++
++static inline bool scst_is_report_luns_changed_type(int type)
++{
++ switch (type) {
++ case TYPE_DISK:
++ case TYPE_TAPE:
++ case TYPE_PRINTER:
++ case TYPE_PROCESSOR:
++ case TYPE_WORM:
++ case TYPE_ROM:
++ case TYPE_SCANNER:
++ case TYPE_MOD:
++ case TYPE_MEDIUM_CHANGER:
++ case TYPE_RAID:
++ case TYPE_ENCLOSURE:
++ return true;
++ default:
++ return false;
++ }
++}
++
++/* scst_mutex supposed to be held */
++static void scst_queue_report_luns_changed_UA(struct scst_session *sess,
++ int flags)
++{
++ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
++ struct list_head *shead;
++ struct scst_tgt_dev *tgt_dev;
++ int i;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Queuing REPORTED LUNS DATA CHANGED UA "
++ "(sess %p)", sess);
++
++ local_bh_disable();
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ shead = &sess->sess_tgt_dev_list_hash[i];
++
++ list_for_each_entry(tgt_dev, shead,
++ sess_tgt_dev_list_entry) {
++ /* Lockdep triggers here a false positive.. */
++ spin_lock(&tgt_dev->tgt_dev_lock);
++ }
++ }
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ shead = &sess->sess_tgt_dev_list_hash[i];
++
++ list_for_each_entry(tgt_dev, shead,
++ sess_tgt_dev_list_entry) {
++ int sl;
++
++ if (!scst_is_report_luns_changed_type(
++ tgt_dev->dev->type))
++ continue;
++
++ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
++ tgt_dev->dev->d_sense,
++ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed));
++
++ __scst_check_set_UA(tgt_dev, sense_buffer,
++ sl, flags | SCST_SET_UA_FLAG_GLOBAL);
++ }
++ }
++
++ for (i = TGT_DEV_HASH_SIZE-1; i >= 0; i--) {
++ shead = &sess->sess_tgt_dev_list_hash[i];
++
++ list_for_each_entry_reverse(tgt_dev,
++ shead, sess_tgt_dev_list_entry) {
++ spin_unlock(&tgt_dev->tgt_dev_lock);
++ }
++ }
++
++ local_bh_enable();
++
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++static void scst_report_luns_changed_sess(struct scst_session *sess)
++{
++ int i;
++ struct scst_tgt_template *tgtt = sess->tgt->tgtt;
++ int d_sense = 0;
++ uint64_t lun = 0;
++
++ TRACE_ENTRY();
++
++ if ((sess->init_phase != SCST_SESS_IPH_READY) ||
++ (sess->shut_phase != SCST_SESS_SPH_READY))
++ goto out;
++
++ TRACE_DBG("REPORTED LUNS DATA CHANGED (sess %p)", sess);
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *shead;
++ struct scst_tgt_dev *tgt_dev;
++
++ shead = &sess->sess_tgt_dev_list_hash[i];
++
++ list_for_each_entry(tgt_dev, shead,
++ sess_tgt_dev_list_entry) {
++ if (scst_is_report_luns_changed_type(
++ tgt_dev->dev->type)) {
++ lun = tgt_dev->lun;
++ d_sense = tgt_dev->dev->d_sense;
++ goto found;
++ }
++ }
++ }
++
++found:
++ if (tgtt->report_aen != NULL) {
++ struct scst_aen *aen;
++ int rc;
++
++ aen = scst_alloc_aen(sess, lun);
++ if (aen == NULL)
++ goto queue_ua;
++
++ aen->event_fn = SCST_AEN_SCSI;
++ aen->aen_sense_len = scst_set_sense(aen->aen_sense,
++ sizeof(aen->aen_sense), d_sense,
++ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed));
++
++ TRACE_DBG("Calling target's %s report_aen(%p)",
++ tgtt->name, aen);
++ rc = tgtt->report_aen(aen);
++ TRACE_DBG("Target's %s report_aen(%p) returned %d",
++ tgtt->name, aen, rc);
++ if (rc == SCST_AEN_RES_SUCCESS)
++ goto out;
++
++ scst_free_aen(aen);
++ }
++
++queue_ua:
++ scst_queue_report_luns_changed_UA(sess, 0);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++void scst_report_luns_changed(struct scst_acg *acg)
++{
++ struct scst_session *sess;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("REPORTED LUNS DATA CHANGED (acg %s)", acg->acg_name);
++
++ list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
++ scst_report_luns_changed_sess(sess);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_aen_done() - AEN processing done
++ *
++ * Notifies SCST that the driver has sent the AEN and it
++ * can be freed now. Don't forget to set the delivery status, if it
++ * isn't success, using scst_set_aen_delivery_status() before calling
++ * this function.
++ */
++void scst_aen_done(struct scst_aen *aen)
++{
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("AEN %p (fn %d) done (initiator %s)", aen,
++ aen->event_fn, aen->sess->initiator_name);
++
++ if (aen->delivery_status == SCST_AEN_RES_SUCCESS)
++ goto out_free;
++
++ if (aen->event_fn != SCST_AEN_SCSI)
++ goto out_free;
++
++ TRACE_MGMT_DBG("Delivery of SCSI AEN failed (initiator %s)",
++ aen->sess->initiator_name);
++
++ if (scst_analyze_sense(aen->aen_sense, aen->aen_sense_len,
++ SCST_SENSE_ALL_VALID, SCST_LOAD_SENSE(
++ scst_sense_reported_luns_data_changed))) {
++ mutex_lock(&scst_mutex);
++ scst_queue_report_luns_changed_UA(aen->sess,
++ SCST_SET_UA_FLAG_AT_HEAD);
++ mutex_unlock(&scst_mutex);
++ } else {
++ struct list_head *shead;
++ struct scst_tgt_dev *tgt_dev;
++ uint64_t lun;
++
++ lun = scst_unpack_lun((uint8_t *)&aen->lun, sizeof(aen->lun));
++
++ mutex_lock(&scst_mutex);
++
++ /* tgt_dev might get dead, so we need to reseek it */
++ shead = &aen->sess->sess_tgt_dev_list_hash[HASH_VAL(lun)];
++ list_for_each_entry(tgt_dev, shead,
++ sess_tgt_dev_list_entry) {
++ if (tgt_dev->lun == lun) {
++ TRACE_MGMT_DBG("Requeuing failed AEN UA for "
++ "tgt_dev %p", tgt_dev);
++ scst_check_set_UA(tgt_dev, aen->aen_sense,
++ aen->aen_sense_len,
++ SCST_SET_UA_FLAG_AT_HEAD);
++ break;
++ }
++ }
++
++ mutex_unlock(&scst_mutex);
++ }
++
++out_free:
++ scst_free_aen(aen);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_aen_done);
++
++void scst_requeue_ua(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++ if (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
++ SCST_SENSE_ALL_VALID,
++ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) {
++ TRACE_MGMT_DBG("Requeuing REPORTED LUNS DATA CHANGED UA "
++ "for delivery failed cmd %p", cmd);
++ mutex_lock(&scst_mutex);
++ scst_queue_report_luns_changed_UA(cmd->sess,
++ SCST_SET_UA_FLAG_AT_HEAD);
++ mutex_unlock(&scst_mutex);
++ } else {
++ TRACE_MGMT_DBG("Requeuing UA for delivery failed cmd %p", cmd);
++ scst_check_set_UA(cmd->tgt_dev, cmd->sense,
++ cmd->sense_valid_len, SCST_SET_UA_FLAG_AT_HEAD);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++static void scst_check_reassign_sess(struct scst_session *sess)
++{
++ struct scst_acg *acg, *old_acg;
++ struct scst_acg_dev *acg_dev;
++ int i, rc;
++ struct list_head *shead;
++ struct scst_tgt_dev *tgt_dev;
++ bool luns_changed = false;
++ bool add_failed, something_freed, not_needed_freed = false;
++
++ TRACE_ENTRY();
++
++ if (sess->shut_phase != SCST_SESS_SPH_READY)
++ goto out;
++
++ TRACE_MGMT_DBG("Checking reassignment for sess %p (initiator %s)",
++ sess, sess->initiator_name);
++
++ acg = scst_find_acg(sess);
++ if (acg == sess->acg) {
++ TRACE_MGMT_DBG("No reassignment for sess %p", sess);
++ goto out;
++ }
++
++ TRACE_MGMT_DBG("sess %p will be reassigned from acg %s to acg %s",
++ sess, sess->acg->acg_name, acg->acg_name);
++
++ old_acg = sess->acg;
++ sess->acg = NULL; /* to catch implicit dependencies earlier */
++
++retry_add:
++ add_failed = false;
++ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
++ unsigned int inq_changed_ua_needed = 0;
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ shead = &sess->sess_tgt_dev_list_hash[i];
++
++ list_for_each_entry(tgt_dev, shead,
++ sess_tgt_dev_list_entry) {
++ if ((tgt_dev->dev == acg_dev->dev) &&
++ (tgt_dev->lun == acg_dev->lun) &&
++ (tgt_dev->acg_dev->rd_only == acg_dev->rd_only)) {
++ TRACE_MGMT_DBG("sess %p: tgt_dev %p for "
++ "LUN %lld stays the same",
++ sess, tgt_dev,
++ (unsigned long long)tgt_dev->lun);
++ tgt_dev->acg_dev = acg_dev;
++ goto next;
++ } else if (tgt_dev->lun == acg_dev->lun)
++ inq_changed_ua_needed = 1;
++ }
++ }
++
++ luns_changed = true;
++
++ TRACE_MGMT_DBG("sess %p: Allocing new tgt_dev for LUN %lld",
++ sess, (unsigned long long)acg_dev->lun);
++
++ rc = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
++ if (rc == -EPERM)
++ continue;
++ else if (rc != 0) {
++ add_failed = true;
++ break;
++ }
++
++ tgt_dev->inq_changed_ua_needed = inq_changed_ua_needed ||
++ not_needed_freed;
++next:
++ continue;
++ }
++
++ something_freed = false;
++ not_needed_freed = true;
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct scst_tgt_dev *t;
++ shead = &sess->sess_tgt_dev_list_hash[i];
++
++ list_for_each_entry_safe(tgt_dev, t, shead,
++ sess_tgt_dev_list_entry) {
++ if (tgt_dev->acg_dev->acg != acg) {
++ TRACE_MGMT_DBG("sess %p: Deleting not used "
++ "tgt_dev %p for LUN %lld",
++ sess, tgt_dev,
++ (unsigned long long)tgt_dev->lun);
++ luns_changed = true;
++ something_freed = true;
++ scst_free_tgt_dev(tgt_dev);
++ }
++ }
++ }
++
++ if (add_failed && something_freed) {
++ TRACE_MGMT_DBG("sess %p: Retrying adding new tgt_devs", sess);
++ goto retry_add;
++ }
++
++ sess->acg = acg;
++
++ TRACE_DBG("Moving sess %p from acg %s to acg %s", sess,
++ old_acg->acg_name, acg->acg_name);
++ list_move_tail(&sess->acg_sess_list_entry, &acg->acg_sess_list);
++
++ scst_recreate_sess_luns_link(sess);
++ /* Ignore possible error, since we can't do anything on it */
++
++ if (luns_changed) {
++ scst_report_luns_changed_sess(sess);
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ shead = &sess->sess_tgt_dev_list_hash[i];
++
++ list_for_each_entry(tgt_dev, shead,
++ sess_tgt_dev_list_entry) {
++ if (tgt_dev->inq_changed_ua_needed) {
++ TRACE_MGMT_DBG("sess %p: Setting "
++ "INQUIRY DATA HAS CHANGED UA "
++ "(tgt_dev %p)", sess, tgt_dev);
++
++ tgt_dev->inq_changed_ua_needed = 0;
++
++ scst_gen_aen_or_ua(tgt_dev,
++ SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
++ }
++ }
++ }
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++void scst_check_reassign_sessions(void)
++{
++ struct scst_tgt_template *tgtt;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
++ struct scst_tgt *tgt;
++ list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
++ struct scst_session *sess;
++ list_for_each_entry(sess, &tgt->sess_list,
++ sess_list_entry) {
++ scst_check_reassign_sess(sess);
++ }
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ switch (cmd->state) {
++ case SCST_CMD_STATE_INIT_WAIT:
++ case SCST_CMD_STATE_INIT:
++ case SCST_CMD_STATE_PARSE:
++ if (cmd->preprocessing_only) {
++ res = SCST_CMD_STATE_PREPROCESSING_DONE;
++ break;
++ } /* else go through */
++ case SCST_CMD_STATE_DEV_DONE:
++ if (cmd->internal)
++ res = SCST_CMD_STATE_FINISHED_INTERNAL;
++ else
++ res = SCST_CMD_STATE_PRE_XMIT_RESP;
++ break;
++
++ case SCST_CMD_STATE_PRE_DEV_DONE:
++ case SCST_CMD_STATE_MODE_SELECT_CHECKS:
++ res = SCST_CMD_STATE_DEV_DONE;
++ break;
++
++ case SCST_CMD_STATE_PRE_XMIT_RESP:
++ res = SCST_CMD_STATE_XMIT_RESP;
++ break;
++
++ case SCST_CMD_STATE_PREPROCESSING_DONE:
++ case SCST_CMD_STATE_PREPROCESSING_DONE_CALLED:
++ if (cmd->tgt_dev == NULL)
++ res = SCST_CMD_STATE_PRE_XMIT_RESP;
++ else
++ res = SCST_CMD_STATE_PRE_DEV_DONE;
++ break;
++
++ case SCST_CMD_STATE_PREPARE_SPACE:
++ if (cmd->preprocessing_only) {
++ res = SCST_CMD_STATE_PREPROCESSING_DONE;
++ break;
++ } /* else go through */
++ case SCST_CMD_STATE_RDY_TO_XFER:
++ case SCST_CMD_STATE_DATA_WAIT:
++ case SCST_CMD_STATE_TGT_PRE_EXEC:
++ case SCST_CMD_STATE_SEND_FOR_EXEC:
++ case SCST_CMD_STATE_LOCAL_EXEC:
++ case SCST_CMD_STATE_REAL_EXEC:
++ case SCST_CMD_STATE_REAL_EXECUTING:
++ res = SCST_CMD_STATE_PRE_DEV_DONE;
++ break;
++
++ default:
++ PRINT_CRIT_ERROR("Wrong cmd state %d (cmd %p, op %x)",
++ cmd->state, cmd, cmd->cdb[0]);
++ BUG();
++ /* Invalid state to supress compiler's warning */
++ res = SCST_CMD_STATE_LAST_ACTIVE;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * scst_set_cmd_abnormal_done_state() - set command's next abnormal done state
++ *
++ * Sets state of the SCSI target state machine to abnormally complete command
++ * ASAP.
++ *
++ * Returns the new state.
++ */
++int scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ switch (cmd->state) {
++ case SCST_CMD_STATE_XMIT_RESP:
++ case SCST_CMD_STATE_FINISHED:
++ case SCST_CMD_STATE_FINISHED_INTERNAL:
++ case SCST_CMD_STATE_XMIT_WAIT:
++ PRINT_CRIT_ERROR("Wrong cmd state %d (cmd %p, op %x)",
++ cmd->state, cmd, cmd->cdb[0]);
++ BUG();
++ }
++#endif
++
++ cmd->state = scst_get_cmd_abnormal_done_state(cmd);
++
++ switch (cmd->state) {
++ case SCST_CMD_STATE_INIT_WAIT:
++ case SCST_CMD_STATE_INIT:
++ case SCST_CMD_STATE_PARSE:
++ case SCST_CMD_STATE_PREPROCESSING_DONE:
++ case SCST_CMD_STATE_PREPROCESSING_DONE_CALLED:
++ case SCST_CMD_STATE_PREPARE_SPACE:
++ case SCST_CMD_STATE_RDY_TO_XFER:
++ case SCST_CMD_STATE_DATA_WAIT:
++ cmd->write_len = 0;
++ cmd->resid_possible = 1;
++ break;
++ case SCST_CMD_STATE_TGT_PRE_EXEC:
++ case SCST_CMD_STATE_SEND_FOR_EXEC:
++ case SCST_CMD_STATE_LOCAL_EXEC:
++ case SCST_CMD_STATE_REAL_EXEC:
++ case SCST_CMD_STATE_REAL_EXECUTING:
++ case SCST_CMD_STATE_DEV_DONE:
++ case SCST_CMD_STATE_PRE_DEV_DONE:
++ case SCST_CMD_STATE_MODE_SELECT_CHECKS:
++ case SCST_CMD_STATE_PRE_XMIT_RESP:
++ break;
++ default:
++ PRINT_CRIT_ERROR("Wrong cmd state %d (cmd %p, op %x)",
++ cmd->state, cmd, cmd->cdb[0]);
++ BUG();
++ break;
++ }
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (((cmd->state != SCST_CMD_STATE_PRE_XMIT_RESP) &&
++ (cmd->state != SCST_CMD_STATE_PREPROCESSING_DONE)) &&
++ (cmd->tgt_dev == NULL) && !cmd->internal) {
++ PRINT_CRIT_ERROR("Wrong not inited cmd state %d (cmd %p, "
++ "op %x)", cmd->state, cmd, cmd->cdb[0]);
++ BUG();
++ }
++#endif
++
++ TRACE_EXIT_RES(cmd->state);
++ return cmd->state;
++}
++EXPORT_SYMBOL_GPL(scst_set_cmd_abnormal_done_state);
++
++void scst_zero_write_rest(struct scst_cmd *cmd)
++{
++ int len, offs = 0;
++ uint8_t *buf;
++
++ TRACE_ENTRY();
++
++ len = scst_get_sg_buf_first(cmd, &buf, *cmd->write_sg,
++ *cmd->write_sg_cnt);
++ while (len > 0) {
++ int cur_offs;
++
++ if (offs + len <= cmd->write_len)
++ goto next;
++ else if (offs >= cmd->write_len)
++ cur_offs = 0;
++ else
++ cur_offs = cmd->write_len - offs;
++
++ memset(&buf[cur_offs], 0, len - cur_offs);
++
++next:
++ offs += len;
++ scst_put_sg_buf(cmd, buf, *cmd->write_sg, *cmd->write_sg_cnt);
++ len = scst_get_sg_buf_next(cmd, &buf, *cmd->write_sg,
++ *cmd->write_sg_cnt);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static void scst_adjust_sg(struct scst_cmd *cmd, struct scatterlist *sg,
++ int *sg_cnt, int adjust_len)
++{
++ int i, l;
++
++ TRACE_ENTRY();
++
++ l = 0;
++ for (i = 0; i < *sg_cnt; i++) {
++ l += sg[i].length;
++ if (l >= adjust_len) {
++ int left = adjust_len - (l - sg[i].length);
++#ifdef CONFIG_SCST_DEBUG
++ TRACE(TRACE_SG_OP|TRACE_MEMORY, "cmd %p (tag %llu), "
++ "sg %p, sg_cnt %d, adjust_len %d, i %d, "
++ "sg[i].length %d, left %d",
++ cmd, (long long unsigned int)cmd->tag,
++ sg, *sg_cnt, adjust_len, i,
++ sg[i].length, left);
++#endif
++ cmd->orig_sg = sg;
++ cmd->p_orig_sg_cnt = sg_cnt;
++ cmd->orig_sg_cnt = *sg_cnt;
++ cmd->orig_sg_entry = i;
++ cmd->orig_entry_len = sg[i].length;
++ *sg_cnt = (left > 0) ? i+1 : i;
++ sg[i].length = left;
++ cmd->sg_buff_modified = 1;
++ break;
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_restore_sg_buff() - restores modified sg buffer
++ *
++ * Restores modified sg buffer in the original state.
++ */
++void scst_restore_sg_buff(struct scst_cmd *cmd)
++{
++ TRACE_MEM("cmd %p, sg %p, orig_sg_entry %d, "
++ "orig_entry_len %d, orig_sg_cnt %d", cmd, cmd->orig_sg,
++ cmd->orig_sg_entry, cmd->orig_entry_len,
++ cmd->orig_sg_cnt);
++ cmd->orig_sg[cmd->orig_sg_entry].length = cmd->orig_entry_len;
++ *cmd->p_orig_sg_cnt = cmd->orig_sg_cnt;
++ cmd->sg_buff_modified = 0;
++}
++EXPORT_SYMBOL(scst_restore_sg_buff);
++
++/**
++ * scst_set_resp_data_len() - set response data length
++ *
++ * Sets response data length for cmd and truncates its SG vector accordingly.
++ *
++ * The cmd->resp_data_len must not be set directly, it must be set only
++ * using this function. Value of resp_data_len must be <= cmd->bufflen.
++ */
++void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len)
++{
++ TRACE_ENTRY();
++
++ scst_check_restore_sg_buff(cmd);
++ cmd->resp_data_len = resp_data_len;
++
++ if (resp_data_len == cmd->bufflen)
++ goto out;
++
++ scst_adjust_sg(cmd, cmd->sg, &cmd->sg_cnt, resp_data_len);
++
++ cmd->resid_possible = 1;
++
++out:
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_set_resp_data_len);
++
++void scst_limit_sg_write_len(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++ TRACE_MEM("Limiting sg write len to %d (cmd %p, sg %p, sg_cnt %d)",
++ cmd->write_len, cmd, *cmd->write_sg, *cmd->write_sg_cnt);
++
++ scst_check_restore_sg_buff(cmd);
++ scst_adjust_sg(cmd, *cmd->write_sg, cmd->write_sg_cnt, cmd->write_len);
++
++ TRACE_EXIT();
++ return;
++}
++
++void scst_adjust_resp_data_len(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++ if (!cmd->expected_values_set) {
++ cmd->adjusted_resp_data_len = cmd->resp_data_len;
++ goto out;
++ }
++
++ cmd->adjusted_resp_data_len = min(cmd->resp_data_len,
++ cmd->expected_transfer_len);
++
++ if (cmd->adjusted_resp_data_len != cmd->resp_data_len) {
++ TRACE_MEM("Abjusting resp_data_len to %d (cmd %p, sg %p, "
++ "sg_cnt %d)", cmd->adjusted_resp_data_len, cmd, cmd->sg,
++ cmd->sg_cnt);
++ scst_check_restore_sg_buff(cmd);
++ scst_adjust_sg(cmd, cmd->sg, &cmd->sg_cnt,
++ cmd->adjusted_resp_data_len);
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_cmd_set_write_not_received_data_len() - sets cmd's not received len
++ *
++ * Sets cmd's not received data length. Also automatically sets resid_possible.
++ */
++void scst_cmd_set_write_not_received_data_len(struct scst_cmd *cmd,
++ int not_received)
++{
++ TRACE_ENTRY();
++
++ BUG_ON(!cmd->expected_values_set);
++
++ cmd->resid_possible = 1;
++
++ if ((cmd->expected_data_direction & SCST_DATA_READ) &&
++ (cmd->expected_data_direction & SCST_DATA_WRITE)) {
++ cmd->write_len = cmd->expected_out_transfer_len - not_received;
++ if (cmd->write_len == cmd->out_bufflen)
++ goto out;
++ } else if (cmd->expected_data_direction & SCST_DATA_WRITE) {
++ cmd->write_len = cmd->expected_transfer_len - not_received;
++ if (cmd->write_len == cmd->bufflen)
++ goto out;
++ }
++
++ /*
++ * Write len now can be bigger cmd->(out_)bufflen, but that's OK,
++ * because it will be used to only calculate write residuals.
++ */
++
++ TRACE_DBG("cmd %p, not_received %d, write_len %d", cmd, not_received,
++ cmd->write_len);
++
++ if (cmd->data_direction & SCST_DATA_WRITE)
++ scst_limit_sg_write_len(cmd);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_cmd_set_write_not_received_data_len);
++
++/**
++ * __scst_get_resid() - returns residuals for cmd
++ *
++ * Returns residuals for command. Must not be called directly, use
++ * scst_get_resid() instead.
++ */
++bool __scst_get_resid(struct scst_cmd *cmd, int *resid, int *bidi_out_resid)
++{
++ TRACE_ENTRY();
++
++ *resid = 0;
++ if (bidi_out_resid != NULL)
++ *bidi_out_resid = 0;
++
++ BUG_ON(!cmd->expected_values_set);
++
++ if (cmd->expected_data_direction & SCST_DATA_READ) {
++ *resid = cmd->expected_transfer_len - cmd->resp_data_len;
++ if ((cmd->expected_data_direction & SCST_DATA_WRITE) && bidi_out_resid) {
++ if (cmd->write_len < cmd->expected_out_transfer_len)
++ *bidi_out_resid = cmd->expected_out_transfer_len -
++ cmd->write_len;
++ else
++ *bidi_out_resid = cmd->write_len - cmd->out_bufflen;
++ }
++ } else if (cmd->expected_data_direction & SCST_DATA_WRITE) {
++ if (cmd->write_len < cmd->expected_transfer_len)
++ *resid = cmd->expected_transfer_len - cmd->write_len;
++ else
++ *resid = cmd->write_len - cmd->bufflen;
++ }
++
++ TRACE_DBG("cmd %p, resid %d, bidi_out_resid %d (resp_data_len %d, "
++ "expected_data_direction %d, write_len %d, bufflen %d)", cmd,
++ *resid, bidi_out_resid ? *bidi_out_resid : 0, cmd->resp_data_len,
++ cmd->expected_data_direction, cmd->write_len, cmd->bufflen);
++
++ TRACE_EXIT_RES(1);
++ return true;
++}
++EXPORT_SYMBOL(__scst_get_resid);
++
++/* No locks */
++int scst_queue_retry_cmd(struct scst_cmd *cmd, int finished_cmds)
++{
++ struct scst_tgt *tgt = cmd->tgt;
++ int res = 0;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ spin_lock_irqsave(&tgt->tgt_lock, flags);
++ tgt->retry_cmds++;
++ /*
++ * Memory barrier is needed here, because we need the exact order
++ * between the read and write between retry_cmds and finished_cmds to
++ * not miss the case when a command finished while we queuing it for
++ * retry after the finished_cmds check.
++ */
++ smp_mb();
++ TRACE_RETRY("TGT QUEUE FULL: incrementing retry_cmds %d",
++ tgt->retry_cmds);
++ if (finished_cmds != atomic_read(&tgt->finished_cmds)) {
++ /* At least one cmd finished, so try again */
++ tgt->retry_cmds--;
++ TRACE_RETRY("Some command(s) finished, direct retry "
++ "(finished_cmds=%d, tgt->finished_cmds=%d, "
++ "retry_cmds=%d)", finished_cmds,
++ atomic_read(&tgt->finished_cmds), tgt->retry_cmds);
++ res = -1;
++ goto out_unlock_tgt;
++ }
++
++ TRACE_RETRY("Adding cmd %p to retry cmd list", cmd);
++ list_add_tail(&cmd->cmd_list_entry, &tgt->retry_cmd_list);
++
++ if (!tgt->retry_timer_active) {
++ tgt->retry_timer.expires = jiffies + SCST_TGT_RETRY_TIMEOUT;
++ add_timer(&tgt->retry_timer);
++ tgt->retry_timer_active = 1;
++ }
++
++out_unlock_tgt:
++ spin_unlock_irqrestore(&tgt->tgt_lock, flags);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * scst_update_hw_pending_start() - update commands pending start
++ *
++ * Updates the command's hw_pending_start as if it's just started hw pending.
++ * Target drivers should call it if they received reply from this pending
++ * command, but SCST core won't see it.
++ */
++void scst_update_hw_pending_start(struct scst_cmd *cmd)
++{
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ /* To sync with scst_check_hw_pending_cmd() */
++ spin_lock_irqsave(&cmd->sess->sess_list_lock, flags);
++ cmd->hw_pending_start = jiffies;
++ TRACE_MGMT_DBG("Updated hw_pending_start to %ld (cmd %p)",
++ cmd->hw_pending_start, cmd);
++ spin_unlock_irqrestore(&cmd->sess->sess_list_lock, flags);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_update_hw_pending_start);
++
++/*
++ * Supposed to be called under sess_list_lock, but can release/reaquire it.
++ * Returns 0 to continue, >0 to restart, <0 to break.
++ */
++static int scst_check_hw_pending_cmd(struct scst_cmd *cmd,
++ unsigned long cur_time, unsigned long max_time,
++ struct scst_session *sess, unsigned long *flags,
++ struct scst_tgt_template *tgtt)
++{
++ int res = -1; /* break */
++
++ TRACE_DBG("cmd %p, hw_pending %d, proc time %ld, "
++ "pending time %ld", cmd, cmd->cmd_hw_pending,
++ (long)(cur_time - cmd->start_time) / HZ,
++ (long)(cur_time - cmd->hw_pending_start) / HZ);
++
++ if (time_before(cur_time, cmd->start_time + max_time)) {
++ /* Cmds are ordered, so no need to check more */
++ goto out;
++ }
++
++ if (!cmd->cmd_hw_pending) {
++ res = 0; /* continue */
++ goto out;
++ }
++
++ if (time_before(cur_time, cmd->hw_pending_start + max_time)) {
++ res = 0; /* continue */
++ goto out;
++ }
++
++ TRACE_MGMT_DBG("Cmd %p HW pending for too long %ld (state %x)",
++ cmd, (cur_time - cmd->hw_pending_start) / HZ,
++ cmd->state);
++
++ cmd->cmd_hw_pending = 0;
++
++ spin_unlock_irqrestore(&sess->sess_list_lock, *flags);
++ tgtt->on_hw_pending_cmd_timeout(cmd);
++ spin_lock_irqsave(&sess->sess_list_lock, *flags);
++
++ res = 1; /* restart */
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void scst_hw_pending_work_fn(struct delayed_work *work)
++{
++ struct scst_session *sess = container_of(work, struct scst_session,
++ hw_pending_work);
++ struct scst_tgt_template *tgtt = sess->tgt->tgtt;
++ struct scst_cmd *cmd;
++ unsigned long cur_time = jiffies;
++ unsigned long flags;
++ unsigned long max_time = tgtt->max_hw_pending_time * HZ;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("HW pending work (sess %p, max time %ld)", sess, max_time/HZ);
++
++ clear_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags);
++
++ spin_lock_irqsave(&sess->sess_list_lock, flags);
++
++restart:
++ list_for_each_entry(cmd, &sess->sess_cmd_list, sess_cmd_list_entry) {
++ int rc;
++
++ rc = scst_check_hw_pending_cmd(cmd, cur_time, max_time, sess,
++ &flags, tgtt);
++ if (rc < 0)
++ break;
++ else if (rc == 0)
++ continue;
++ else
++ goto restart;
++ }
++
++ if (!list_empty(&sess->sess_cmd_list)) {
++ /*
++ * For stuck cmds if there is no activity we might need to have
++ * one more run to release them, so reschedule once again.
++ */
++ TRACE_DBG("Sched HW pending work for sess %p (max time %d)",
++ sess, tgtt->max_hw_pending_time);
++ set_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags);
++ schedule_delayed_work(&sess->hw_pending_work,
++ tgtt->max_hw_pending_time * HZ);
++ }
++
++ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
++
++ TRACE_EXIT();
++ return;
++}
++
++static bool __scst_is_relative_target_port_id_unique(uint16_t id,
++ const struct scst_tgt *t)
++{
++ bool res = true;
++ struct scst_tgt_template *tgtt;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(tgtt, &scst_template_list,
++ scst_template_list_entry) {
++ struct scst_tgt *tgt;
++ list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
++ if (tgt == t)
++ continue;
++ if ((tgt->tgtt->is_target_enabled != NULL) &&
++ !tgt->tgtt->is_target_enabled(tgt))
++ continue;
++ if (id == tgt->rel_tgt_id) {
++ res = false;
++ break;
++ }
++ }
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* scst_mutex supposed to be locked */
++bool scst_is_relative_target_port_id_unique(uint16_t id,
++ const struct scst_tgt *t)
++{
++ bool res;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++ res = __scst_is_relative_target_port_id_unique(id, t);
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++int gen_relative_target_port_id(uint16_t *id)
++{
++ int res = -EOVERFLOW;
++ static unsigned long rti = SCST_MIN_REL_TGT_ID, rti_prev;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ rti_prev = rti;
++ do {
++ if (__scst_is_relative_target_port_id_unique(rti, NULL)) {
++ *id = (uint16_t)rti++;
++ res = 0;
++ goto out_unlock;
++ }
++ rti++;
++ if (rti > SCST_MAX_REL_TGT_ID)
++ rti = SCST_MIN_REL_TGT_ID;
++ } while (rti != rti_prev);
++
++ PRINT_ERROR("%s", "Unable to create unique relative target port id");
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* No locks */
++int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt)
++{
++ struct scst_tgt *t;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ t = kzalloc(sizeof(*t), GFP_KERNEL);
++ if (t == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of tgt failed");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ INIT_LIST_HEAD(&t->sess_list);
++ init_waitqueue_head(&t->unreg_waitQ);
++ t->tgtt = tgtt;
++ t->sg_tablesize = tgtt->sg_tablesize;
++ spin_lock_init(&t->tgt_lock);
++ INIT_LIST_HEAD(&t->retry_cmd_list);
++ atomic_set(&t->finished_cmds, 0);
++ init_timer(&t->retry_timer);
++ t->retry_timer.data = (unsigned long)t;
++ t->retry_timer.function = scst_tgt_retry_timer_fn;
++
++ INIT_LIST_HEAD(&t->tgt_acg_list);
++
++ *tgt = t;
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/* No locks */
++void scst_free_tgt(struct scst_tgt *tgt)
++{
++ TRACE_ENTRY();
++
++ kfree(tgt->tgt_name);
++
++ kfree(tgt);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called under scst_mutex and suspended activity */
++int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev)
++{
++ struct scst_device *dev;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ dev = kzalloc(sizeof(*dev), gfp_mask);
++ if (dev == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s",
++ "Allocation of scst_device failed");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ dev->handler = &scst_null_devtype;
++ atomic_set(&dev->dev_cmd_count, 0);
++ atomic_set(&dev->write_cmd_count, 0);
++ scst_init_mem_lim(&dev->dev_mem_lim);
++ spin_lock_init(&dev->dev_lock);
++ INIT_LIST_HEAD(&dev->blocked_cmd_list);
++ INIT_LIST_HEAD(&dev->dev_tgt_dev_list);
++ INIT_LIST_HEAD(&dev->dev_acg_dev_list);
++ dev->dev_double_ua_possible = 1;
++ dev->queue_alg = SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER;
++
++ mutex_init(&dev->dev_pr_mutex);
++ atomic_set(&dev->pr_readers_count, 0);
++ dev->pr_generation = 0;
++ dev->pr_is_set = 0;
++ dev->pr_holder = NULL;
++ dev->pr_scope = SCOPE_LU;
++ dev->pr_type = TYPE_UNSPECIFIED;
++ INIT_LIST_HEAD(&dev->dev_registrants_list);
++
++ scst_init_threads(&dev->dev_cmd_threads);
++
++ *out_dev = dev;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++void scst_free_device(struct scst_device *dev)
++{
++ TRACE_ENTRY();
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (!list_empty(&dev->dev_tgt_dev_list) ||
++ !list_empty(&dev->dev_acg_dev_list)) {
++ PRINT_CRIT_ERROR("%s: dev_tgt_dev_list or dev_acg_dev_list "
++ "is not empty!", __func__);
++ BUG();
++ }
++#endif
++
++ scst_deinit_threads(&dev->dev_cmd_threads);
++
++ kfree(dev->virt_name);
++ kfree(dev);
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_init_mem_lim - initialize memory limits structure
++ *
++ * Initializes memory limits structure mem_lim according to
++ * the current system configuration. This structure should be latter used
++ * to track and limit allocated by one or more SGV pools memory.
++ */
++void scst_init_mem_lim(struct scst_mem_lim *mem_lim)
++{
++ atomic_set(&mem_lim->alloced_pages, 0);
++ mem_lim->max_allowed_pages =
++ ((uint64_t)scst_max_dev_cmd_mem << 10) >> (PAGE_SHIFT - 10);
++}
++EXPORT_SYMBOL_GPL(scst_init_mem_lim);
++
++static struct scst_acg_dev *scst_alloc_acg_dev(struct scst_acg *acg,
++ struct scst_device *dev, uint64_t lun)
++{
++ struct scst_acg_dev *res;
++
++ TRACE_ENTRY();
++
++ res = kmem_cache_zalloc(scst_acgd_cachep, GFP_KERNEL);
++ if (res == NULL) {
++ TRACE(TRACE_OUT_OF_MEM,
++ "%s", "Allocation of scst_acg_dev failed");
++ goto out;
++ }
++
++ res->dev = dev;
++ res->acg = acg;
++ res->lun = lun;
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/*
++ * The activity supposed to be suspended and scst_mutex held or the
++ * corresponding target supposed to be stopped.
++ */
++static void scst_del_free_acg_dev(struct scst_acg_dev *acg_dev, bool del_sysfs)
++{
++ TRACE_ENTRY();
++
++ TRACE_DBG("Removing acg_dev %p from acg_dev_list and dev_acg_dev_list",
++ acg_dev);
++ list_del(&acg_dev->acg_dev_list_entry);
++ list_del(&acg_dev->dev_acg_dev_list_entry);
++
++ if (del_sysfs)
++ scst_acg_dev_sysfs_del(acg_dev);
++
++ kmem_cache_free(scst_acgd_cachep, acg_dev);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
++ struct scst_device *dev, uint64_t lun, int read_only,
++ bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev)
++{
++ int res = 0;
++ struct scst_acg_dev *acg_dev;
++ struct scst_tgt_dev *tgt_dev;
++ struct scst_session *sess;
++ LIST_HEAD(tmp_tgt_dev_list);
++ bool del_sysfs = true;
++
++ TRACE_ENTRY();
++
++ INIT_LIST_HEAD(&tmp_tgt_dev_list);
++
++ acg_dev = scst_alloc_acg_dev(acg, dev, lun);
++ if (acg_dev == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++ acg_dev->rd_only = read_only;
++
++ TRACE_DBG("Adding acg_dev %p to acg_dev_list and dev_acg_dev_list",
++ acg_dev);
++ list_add_tail(&acg_dev->acg_dev_list_entry, &acg->acg_dev_list);
++ list_add_tail(&acg_dev->dev_acg_dev_list_entry, &dev->dev_acg_dev_list);
++
++ list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
++ res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
++ if (res == -EPERM)
++ continue;
++ else if (res != 0)
++ goto out_free;
++
++ list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
++ &tmp_tgt_dev_list);
++ }
++
++ res = scst_acg_dev_sysfs_create(acg_dev, parent);
++ if (res != 0) {
++ del_sysfs = false;
++ goto out_free;
++ }
++
++ if (gen_scst_report_luns_changed)
++ scst_report_luns_changed(acg);
++
++ PRINT_INFO("Added device %s to group %s (LUN %lld, "
++ "rd_only %d)", dev->virt_name, acg->acg_name,
++ (long long unsigned int)lun, read_only);
++
++ if (out_acg_dev != NULL)
++ *out_acg_dev = acg_dev;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ list_for_each_entry(tgt_dev, &tmp_tgt_dev_list,
++ extra_tgt_dev_list_entry) {
++ scst_free_tgt_dev(tgt_dev);
++ }
++ scst_del_free_acg_dev(acg_dev, del_sysfs);
++ goto out;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
++ bool gen_scst_report_luns_changed)
++{
++ int res = 0;
++ struct scst_acg_dev *acg_dev = NULL, *a;
++ struct scst_tgt_dev *tgt_dev, *tt;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(a, &acg->acg_dev_list, acg_dev_list_entry) {
++ if (a->lun == lun) {
++ acg_dev = a;
++ break;
++ }
++ }
++ if (acg_dev == NULL) {
++ PRINT_ERROR("Device is not found in group %s", acg->acg_name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ list_for_each_entry_safe(tgt_dev, tt, &acg_dev->dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if (tgt_dev->acg_dev == acg_dev)
++ scst_free_tgt_dev(tgt_dev);
++ }
++
++ scst_del_free_acg_dev(acg_dev, true);
++
++ if (gen_scst_report_luns_changed)
++ scst_report_luns_changed(acg);
++
++ PRINT_INFO("Removed LUN %lld from group %s", (unsigned long long)lun,
++ acg->acg_name);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
++ const char *acg_name, bool tgt_acg)
++{
++ struct scst_acg *acg;
++
++ TRACE_ENTRY();
++
++ acg = kzalloc(sizeof(*acg), GFP_KERNEL);
++ if (acg == NULL) {
++ PRINT_ERROR("%s", "Allocation of acg failed");
++ goto out;
++ }
++
++ acg->tgt = tgt;
++ INIT_LIST_HEAD(&acg->acg_dev_list);
++ INIT_LIST_HEAD(&acg->acg_sess_list);
++ INIT_LIST_HEAD(&acg->acn_list);
++ acg->acg_name = kstrdup(acg_name, GFP_KERNEL);
++ if (acg->acg_name == NULL) {
++ PRINT_ERROR("%s", "Allocation of acg_name failed");
++ goto out_free;
++ }
++
++ acg->addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
++
++ if (tgt_acg) {
++ int rc;
++
++ TRACE_DBG("Adding acg '%s' to device '%s' acg_list", acg_name,
++ tgt->tgt_name);
++ list_add_tail(&acg->acg_list_entry, &tgt->tgt_acg_list);
++ acg->tgt_acg = 1;
++
++ rc = scst_acg_sysfs_create(tgt, acg);
++ if (rc != 0)
++ goto out_del;
++ }
++
++out:
++ TRACE_EXIT_HRES(acg);
++ return acg;
++
++out_del:
++ list_del(&acg->acg_list_entry);
++
++out_free:
++ kfree(acg);
++ acg = NULL;
++ goto out;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++void scst_del_free_acg(struct scst_acg *acg)
++{
++ struct scst_acn *acn, *acnt;
++ struct scst_acg_dev *acg_dev, *acg_dev_tmp;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Clearing acg %s from list", acg->acg_name);
++
++ BUG_ON(!list_empty(&acg->acg_sess_list));
++
++ /* Freeing acg_devs */
++ list_for_each_entry_safe(acg_dev, acg_dev_tmp, &acg->acg_dev_list,
++ acg_dev_list_entry) {
++ struct scst_tgt_dev *tgt_dev, *tt;
++ list_for_each_entry_safe(tgt_dev, tt,
++ &acg_dev->dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if (tgt_dev->acg_dev == acg_dev)
++ scst_free_tgt_dev(tgt_dev);
++ }
++ scst_del_free_acg_dev(acg_dev, true);
++ }
++
++ /* Freeing names */
++ list_for_each_entry_safe(acn, acnt, &acg->acn_list, acn_list_entry) {
++ scst_del_free_acn(acn,
++ list_is_last(&acn->acn_list_entry, &acg->acn_list));
++ }
++ INIT_LIST_HEAD(&acg->acn_list);
++
++ if (acg->tgt_acg) {
++ TRACE_DBG("Removing acg %s from list", acg->acg_name);
++ list_del(&acg->acg_list_entry);
++
++ scst_acg_sysfs_del(acg);
++ } else
++ acg->tgt->default_acg = NULL;
++
++ BUG_ON(!list_empty(&acg->acg_sess_list));
++ BUG_ON(!list_empty(&acg->acg_dev_list));
++ BUG_ON(!list_empty(&acg->acn_list));
++
++ kfree(acg->acg_name);
++ kfree(acg);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name)
++{
++ struct scst_acg *acg, *acg_ret = NULL;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(acg, &tgt->tgt_acg_list, acg_list_entry) {
++ if (strcmp(acg->acg_name, name) == 0) {
++ acg_ret = acg;
++ break;
++ }
++ }
++
++ TRACE_EXIT();
++ return acg_ret;
++}
++
++/* scst_mutex supposed to be held */
++static struct scst_tgt_dev *scst_find_shared_io_tgt_dev(
++ struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_tgt_dev *res = NULL;
++ struct scst_acg *acg = tgt_dev->acg_dev->acg;
++ struct scst_tgt_dev *t;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("tgt_dev %s (acg %p, io_grouping_type %d)",
++ tgt_dev->sess->initiator_name, acg, acg->acg_io_grouping_type);
++
++ switch (acg->acg_io_grouping_type) {
++ case SCST_IO_GROUPING_AUTO:
++ if (tgt_dev->sess->initiator_name == NULL)
++ goto out;
++
++ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if ((t == tgt_dev) ||
++ (t->sess->initiator_name == NULL) ||
++ (t->active_cmd_threads == NULL))
++ continue;
++
++ TRACE_DBG("t %s", t->sess->initiator_name);
++
++ /* We check other ACG's as well */
++
++ if (strcmp(t->sess->initiator_name,
++ tgt_dev->sess->initiator_name) == 0)
++ goto found;
++ }
++ break;
++
++ case SCST_IO_GROUPING_THIS_GROUP_ONLY:
++ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if ((t == tgt_dev) || (t->active_cmd_threads == NULL))
++ continue;
++
++ TRACE_DBG("t %s (acg %p)", t->sess->initiator_name,
++ t->acg_dev->acg);
++
++ if (t->acg_dev->acg == acg)
++ goto found;
++ }
++ break;
++
++ case SCST_IO_GROUPING_NEVER:
++ goto out;
++
++ default:
++ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if ((t == tgt_dev) || (t->active_cmd_threads == NULL))
++ continue;
++
++ TRACE_DBG("t %s (acg %p, io_grouping_type %d)",
++ t->sess->initiator_name, t->acg_dev->acg,
++ t->acg_dev->acg->acg_io_grouping_type);
++
++ if (t->acg_dev->acg->acg_io_grouping_type ==
++ acg->acg_io_grouping_type)
++ goto found;
++ }
++ break;
++ }
++
++out:
++ TRACE_EXIT_HRES((unsigned long)res);
++ return res;
++
++found:
++ if (t->active_cmd_threads == &scst_main_cmd_threads) {
++ res = t;
++ TRACE_MGMT_DBG("Going to share async IO context %p (res %p, "
++ "ini %s, dev %s, grouping type %d)",
++ t->aic_keeper->aic, res, t->sess->initiator_name,
++ t->dev->virt_name,
++ t->acg_dev->acg->acg_io_grouping_type);
++ } else {
++ res = t;
++ if (!*(volatile bool*)&res->active_cmd_threads->io_context_ready) {
++ TRACE_MGMT_DBG("IO context for t %p not yet "
++ "initialized, waiting...", t);
++ msleep(100);
++ barrier();
++ goto found;
++ }
++ TRACE_MGMT_DBG("Going to share IO context %p (res %p, ini %s, "
++ "dev %s, cmd_threads %p, grouping type %d)",
++ res->active_cmd_threads->io_context, res,
++ t->sess->initiator_name, t->dev->virt_name,
++ t->active_cmd_threads,
++ t->acg_dev->acg->acg_io_grouping_type);
++ }
++ goto out;
++}
++
++enum scst_dev_type_threads_pool_type scst_parse_threads_pool_type(const char *p,
++ int len)
++{
++ enum scst_dev_type_threads_pool_type res;
++
++ if (strncasecmp(p, SCST_THREADS_POOL_PER_INITIATOR_STR,
++ min_t(int, strlen(SCST_THREADS_POOL_PER_INITIATOR_STR),
++ len)) == 0)
++ res = SCST_THREADS_POOL_PER_INITIATOR;
++ else if (strncasecmp(p, SCST_THREADS_POOL_SHARED_STR,
++ min_t(int, strlen(SCST_THREADS_POOL_SHARED_STR),
++ len)) == 0)
++ res = SCST_THREADS_POOL_SHARED;
++ else {
++ PRINT_ERROR("Unknown threads pool type %s", p);
++ res = SCST_THREADS_POOL_TYPE_INVALID;
++ }
++
++ return res;
++}
++
++static int scst_ioc_keeper_thread(void *arg)
++{
++ struct scst_async_io_context_keeper *aic_keeper =
++ (struct scst_async_io_context_keeper *)arg;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("AIC %p keeper thread %s (PID %d) started", aic_keeper,
++ current->comm, current->pid);
++
++ current->flags |= PF_NOFREEZE;
++
++ BUG_ON(aic_keeper->aic != NULL);
++
++ aic_keeper->aic = get_io_context(GFP_KERNEL, -1);
++ TRACE_MGMT_DBG("Alloced new async IO context %p (aic %p)",
++ aic_keeper->aic, aic_keeper);
++
++ /* We have our own ref counting */
++ put_io_context(aic_keeper->aic);
++
++ /* We are ready */
++ aic_keeper->aic_ready = true;
++ wake_up_all(&aic_keeper->aic_keeper_waitQ);
++
++ wait_event_interruptible(aic_keeper->aic_keeper_waitQ,
++ kthread_should_stop());
++
++ TRACE_MGMT_DBG("AIC %p keeper thread %s (PID %d) finished", aic_keeper,
++ current->comm, current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++/* scst_mutex supposed to be held */
++int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
++{
++ int res = 0;
++ struct scst_device *dev = tgt_dev->dev;
++ struct scst_async_io_context_keeper *aic_keeper;
++
++ TRACE_ENTRY();
++
++ if (dev->threads_num < 0)
++ goto out;
++
++ if (dev->threads_num == 0) {
++ struct scst_tgt_dev *shared_io_tgt_dev;
++ tgt_dev->active_cmd_threads = &scst_main_cmd_threads;
++
++ shared_io_tgt_dev = scst_find_shared_io_tgt_dev(tgt_dev);
++ if (shared_io_tgt_dev != NULL) {
++ aic_keeper = shared_io_tgt_dev->aic_keeper;
++ kref_get(&aic_keeper->aic_keeper_kref);
++
++ TRACE_MGMT_DBG("Linking async io context %p "
++ "for shared tgt_dev %p (dev %s)",
++ aic_keeper->aic, tgt_dev,
++ tgt_dev->dev->virt_name);
++ } else {
++ /* Create new context */
++ aic_keeper = kzalloc(sizeof(*aic_keeper), GFP_KERNEL);
++ if (aic_keeper == NULL) {
++ PRINT_ERROR("Unable to alloc aic_keeper "
++ "(size %zd)", sizeof(*aic_keeper));
++ res = -ENOMEM;
++ goto out;
++ }
++
++ kref_init(&aic_keeper->aic_keeper_kref);
++ init_waitqueue_head(&aic_keeper->aic_keeper_waitQ);
++
++ aic_keeper->aic_keeper_thr =
++ kthread_run(scst_ioc_keeper_thread,
++ aic_keeper, "aic_keeper");
++ if (IS_ERR(aic_keeper->aic_keeper_thr)) {
++ PRINT_ERROR("Error running ioc_keeper "
++ "thread (tgt_dev %p)", tgt_dev);
++ res = PTR_ERR(aic_keeper->aic_keeper_thr);
++ goto out_free_keeper;
++ }
++
++ wait_event(aic_keeper->aic_keeper_waitQ,
++ aic_keeper->aic_ready);
++
++ TRACE_MGMT_DBG("Created async io context %p "
++ "for not shared tgt_dev %p (dev %s)",
++ aic_keeper->aic, tgt_dev,
++ tgt_dev->dev->virt_name);
++ }
++
++ tgt_dev->async_io_context = aic_keeper->aic;
++ tgt_dev->aic_keeper = aic_keeper;
++
++ res = scst_add_threads(tgt_dev->active_cmd_threads, NULL, NULL,
++ tgt_dev->sess->tgt->tgtt->threads_num);
++ goto out;
++ }
++
++ switch (dev->threads_pool_type) {
++ case SCST_THREADS_POOL_PER_INITIATOR:
++ {
++ struct scst_tgt_dev *shared_io_tgt_dev;
++
++ scst_init_threads(&tgt_dev->tgt_dev_cmd_threads);
++
++ tgt_dev->active_cmd_threads = &tgt_dev->tgt_dev_cmd_threads;
++
++ shared_io_tgt_dev = scst_find_shared_io_tgt_dev(tgt_dev);
++ if (shared_io_tgt_dev != NULL) {
++ TRACE_MGMT_DBG("Linking io context %p for "
++ "shared tgt_dev %p (cmd_threads %p)",
++ shared_io_tgt_dev->active_cmd_threads->io_context,
++ tgt_dev, tgt_dev->active_cmd_threads);
++ /* It's ref counted via threads */
++ tgt_dev->active_cmd_threads->io_context =
++ shared_io_tgt_dev->active_cmd_threads->io_context;
++ }
++
++ res = scst_add_threads(tgt_dev->active_cmd_threads, NULL,
++ tgt_dev,
++ dev->threads_num + tgt_dev->sess->tgt->tgtt->threads_num);
++ if (res != 0) {
++ /* Let's clear here, because no threads could be run */
++ tgt_dev->active_cmd_threads->io_context = NULL;
++ }
++ break;
++ }
++ case SCST_THREADS_POOL_SHARED:
++ {
++ tgt_dev->active_cmd_threads = &dev->dev_cmd_threads;
++
++ res = scst_add_threads(tgt_dev->active_cmd_threads, dev, NULL,
++ tgt_dev->sess->tgt->tgtt->threads_num);
++ break;
++ }
++ default:
++ PRINT_CRIT_ERROR("Unknown threads pool type %d (dev %s)",
++ dev->threads_pool_type, dev->virt_name);
++ BUG();
++ break;
++ }
++
++out:
++ if (res == 0)
++ tm_dbg_init_tgt_dev(tgt_dev);
++
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free_keeper:
++ kfree(aic_keeper);
++ goto out;
++}
++
++static void scst_aic_keeper_release(struct kref *kref)
++{
++ struct scst_async_io_context_keeper *aic_keeper;
++
++ TRACE_ENTRY();
++
++ aic_keeper = container_of(kref, struct scst_async_io_context_keeper,
++ aic_keeper_kref);
++
++ kthread_stop(aic_keeper->aic_keeper_thr);
++
++ kfree(aic_keeper);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* scst_mutex supposed to be held */
++void scst_tgt_dev_stop_threads(struct scst_tgt_dev *tgt_dev)
++{
++ TRACE_ENTRY();
++
++ if (tgt_dev->dev->threads_num < 0)
++ goto out_deinit;
++
++ if (tgt_dev->active_cmd_threads == &scst_main_cmd_threads) {
++ /* Global async threads */
++ kref_put(&tgt_dev->aic_keeper->aic_keeper_kref,
++ scst_aic_keeper_release);
++ tgt_dev->async_io_context = NULL;
++ tgt_dev->aic_keeper = NULL;
++ } else if (tgt_dev->active_cmd_threads == &tgt_dev->dev->dev_cmd_threads) {
++ /* Per device shared threads */
++ scst_del_threads(tgt_dev->active_cmd_threads,
++ tgt_dev->sess->tgt->tgtt->threads_num);
++ } else if (tgt_dev->active_cmd_threads == &tgt_dev->tgt_dev_cmd_threads) {
++ /* Per tgt_dev threads */
++ scst_del_threads(tgt_dev->active_cmd_threads, -1);
++ scst_deinit_threads(&tgt_dev->tgt_dev_cmd_threads);
++ } /* else no threads (not yet initialized, e.g.) */
++
++out_deinit:
++ tm_dbg_deinit_tgt_dev(tgt_dev);
++ tgt_dev->active_cmd_threads = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * scst_mutex supposed to be held, there must not be parallel activity in this
++ * session.
++ */
++static int scst_alloc_add_tgt_dev(struct scst_session *sess,
++ struct scst_acg_dev *acg_dev, struct scst_tgt_dev **out_tgt_dev)
++{
++ int res = 0;
++ int ini_sg, ini_unchecked_isa_dma, ini_use_clustering;
++ struct scst_tgt_dev *tgt_dev;
++ struct scst_device *dev = acg_dev->dev;
++ struct list_head *sess_tgt_dev_list_head;
++ int i, sl;
++ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
++
++ TRACE_ENTRY();
++
++ tgt_dev = kmem_cache_zalloc(scst_tgtd_cachep, GFP_KERNEL);
++ if (tgt_dev == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of scst_tgt_dev "
++ "failed");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ tgt_dev->dev = dev;
++ tgt_dev->lun = acg_dev->lun;
++ tgt_dev->acg_dev = acg_dev;
++ tgt_dev->sess = sess;
++ atomic_set(&tgt_dev->tgt_dev_cmd_count, 0);
++
++ scst_sgv_pool_use_norm(tgt_dev);
++
++ if (dev->scsi_dev != NULL) {
++ ini_sg = dev->scsi_dev->host->sg_tablesize;
++ ini_unchecked_isa_dma = dev->scsi_dev->host->unchecked_isa_dma;
++ ini_use_clustering = (dev->scsi_dev->host->use_clustering ==
++ ENABLE_CLUSTERING);
++ } else {
++ ini_sg = (1 << 15) /* infinite */;
++ ini_unchecked_isa_dma = 0;
++ ini_use_clustering = 0;
++ }
++ tgt_dev->max_sg_cnt = min(ini_sg, sess->tgt->sg_tablesize);
++
++ if ((sess->tgt->tgtt->use_clustering || ini_use_clustering) &&
++ !sess->tgt->tgtt->no_clustering)
++ scst_sgv_pool_use_norm_clust(tgt_dev);
++
++ if (sess->tgt->tgtt->unchecked_isa_dma || ini_unchecked_isa_dma)
++ scst_sgv_pool_use_dma(tgt_dev);
++
++ TRACE_MGMT_DBG("Device %s on SCST lun=%lld",
++ dev->virt_name, (long long unsigned int)tgt_dev->lun);
++
++ spin_lock_init(&tgt_dev->tgt_dev_lock);
++ INIT_LIST_HEAD(&tgt_dev->UA_list);
++ spin_lock_init(&tgt_dev->thr_data_lock);
++ INIT_LIST_HEAD(&tgt_dev->thr_data_list);
++ spin_lock_init(&tgt_dev->sn_lock);
++ INIT_LIST_HEAD(&tgt_dev->deferred_cmd_list);
++ INIT_LIST_HEAD(&tgt_dev->skipped_sn_list);
++ tgt_dev->curr_sn = (typeof(tgt_dev->curr_sn))(-300);
++ tgt_dev->expected_sn = tgt_dev->curr_sn + 1;
++ tgt_dev->num_free_sn_slots = ARRAY_SIZE(tgt_dev->sn_slots)-1;
++ tgt_dev->cur_sn_slot = &tgt_dev->sn_slots[0];
++ for (i = 0; i < (int)ARRAY_SIZE(tgt_dev->sn_slots); i++)
++ atomic_set(&tgt_dev->sn_slots[i], 0);
++
++ if (dev->handler->parse_atomic &&
++ dev->handler->alloc_data_buf_atomic &&
++ (sess->tgt->tgtt->preprocessing_done == NULL)) {
++ if (sess->tgt->tgtt->rdy_to_xfer_atomic)
++ __set_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC,
++ &tgt_dev->tgt_dev_flags);
++ }
++ if (dev->handler->dev_done_atomic &&
++ sess->tgt->tgtt->xmit_response_atomic) {
++ __set_bit(SCST_TGT_DEV_AFTER_EXEC_ATOMIC,
++ &tgt_dev->tgt_dev_flags);
++ }
++
++ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
++ dev->d_sense, SCST_LOAD_SENSE(scst_sense_reset_UA));
++ scst_alloc_set_UA(tgt_dev, sense_buffer, sl, 0);
++
++ if (sess->tgt->tgtt->get_initiator_port_transport_id == NULL) {
++ if (!list_empty(&dev->dev_registrants_list)) {
++ PRINT_WARNING("Initiators from target %s can't connect "
++ "to device %s, because the device has PR "
++ "registrants and the target doesn't support "
++ "Persistent Reservations", sess->tgt->tgtt->name,
++ dev->virt_name);
++ res = -EPERM;
++ goto out_free;
++ }
++ dev->not_pr_supporting_tgt_devs_num++;
++ }
++
++ res = scst_pr_init_tgt_dev(tgt_dev);
++ if (res != 0)
++ goto out_dec_free;
++
++ res = scst_tgt_dev_setup_threads(tgt_dev);
++ if (res != 0)
++ goto out_pr_clear;
++
++ if (dev->handler && dev->handler->attach_tgt) {
++ TRACE_DBG("Calling dev handler's attach_tgt(%p)", tgt_dev);
++ res = dev->handler->attach_tgt(tgt_dev);
++ TRACE_DBG("%s", "Dev handler's attach_tgt() returned");
++ if (res != 0) {
++ PRINT_ERROR("Device handler's %s attach_tgt() "
++ "failed: %d", dev->handler->name, res);
++ goto out_stop_threads;
++ }
++ }
++
++ res = scst_tgt_dev_sysfs_create(tgt_dev);
++ if (res != 0)
++ goto out_detach;
++
++ spin_lock_bh(&dev->dev_lock);
++ list_add_tail(&tgt_dev->dev_tgt_dev_list_entry, &dev->dev_tgt_dev_list);
++ if (dev->dev_reserved)
++ __set_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags);
++ spin_unlock_bh(&dev->dev_lock);
++
++ sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[HASH_VAL(tgt_dev->lun)];
++ list_add_tail(&tgt_dev->sess_tgt_dev_list_entry,
++ sess_tgt_dev_list_head);
++
++ *out_tgt_dev = tgt_dev;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_detach:
++ if (dev->handler && dev->handler->detach_tgt) {
++ TRACE_DBG("Calling dev handler's detach_tgt(%p)",
++ tgt_dev);
++ dev->handler->detach_tgt(tgt_dev);
++ TRACE_DBG("%s", "Dev handler's detach_tgt() returned");
++ }
++
++out_stop_threads:
++ scst_tgt_dev_stop_threads(tgt_dev);
++
++out_pr_clear:
++ scst_pr_clear_tgt_dev(tgt_dev);
++
++out_dec_free:
++ if (tgt_dev->sess->tgt->tgtt->get_initiator_port_transport_id == NULL)
++ dev->not_pr_supporting_tgt_devs_num--;
++
++out_free:
++ scst_free_all_UA(tgt_dev);
++ kmem_cache_free(scst_tgtd_cachep, tgt_dev);
++ goto out;
++}
++
++/* No locks supposed to be held, scst_mutex - held */
++void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA)
++{
++ TRACE_ENTRY();
++
++ scst_clear_reservation(tgt_dev);
++
++ /* With activity suspended the lock isn't needed, but let's be safe */
++ spin_lock_bh(&tgt_dev->tgt_dev_lock);
++ scst_free_all_UA(tgt_dev);
++ memset(tgt_dev->tgt_dev_sense, 0, sizeof(tgt_dev->tgt_dev_sense));
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++
++ if (queue_UA) {
++ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
++ int sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
++ tgt_dev->dev->d_sense,
++ SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
++ scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * scst_mutex supposed to be held, there must not be parallel activity in this
++ * session.
++ */
++static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_device *dev = tgt_dev->dev;
++
++ TRACE_ENTRY();
++
++ spin_lock_bh(&dev->dev_lock);
++ list_del(&tgt_dev->dev_tgt_dev_list_entry);
++ spin_unlock_bh(&dev->dev_lock);
++
++ list_del(&tgt_dev->sess_tgt_dev_list_entry);
++
++ scst_tgt_dev_sysfs_del(tgt_dev);
++
++ if (tgt_dev->sess->tgt->tgtt->get_initiator_port_transport_id == NULL)
++ dev->not_pr_supporting_tgt_devs_num--;
++
++ scst_clear_reservation(tgt_dev);
++ scst_pr_clear_tgt_dev(tgt_dev);
++ scst_free_all_UA(tgt_dev);
++
++ if (dev->handler && dev->handler->detach_tgt) {
++ TRACE_DBG("Calling dev handler's detach_tgt(%p)",
++ tgt_dev);
++ dev->handler->detach_tgt(tgt_dev);
++ TRACE_DBG("%s", "Dev handler's detach_tgt() returned");
++ }
++
++ scst_tgt_dev_stop_threads(tgt_dev);
++
++ BUG_ON(!list_empty(&tgt_dev->thr_data_list));
++
++ kmem_cache_free(scst_tgtd_cachep, tgt_dev);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* scst_mutex supposed to be held */
++int scst_sess_alloc_tgt_devs(struct scst_session *sess)
++{
++ int res = 0;
++ struct scst_acg_dev *acg_dev;
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(acg_dev, &sess->acg->acg_dev_list,
++ acg_dev_list_entry) {
++ res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
++ if (res == -EPERM)
++ continue;
++ else if (res != 0)
++ goto out_free;
++ }
++
++out:
++ TRACE_EXIT();
++ return res;
++
++out_free:
++ scst_sess_free_tgt_devs(sess);
++ goto out;
++}
++
++/*
++ * scst_mutex supposed to be held, there must not be parallel activity in this
++ * session.
++ */
++void scst_sess_free_tgt_devs(struct scst_session *sess)
++{
++ int i;
++ struct scst_tgt_dev *tgt_dev, *t;
++
++ TRACE_ENTRY();
++
++ /* The session is going down, no users, so no locks */
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ list_for_each_entry_safe(tgt_dev, t, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ scst_free_tgt_dev(tgt_dev);
++ }
++ INIT_LIST_HEAD(sess_tgt_dev_list_head);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++int scst_acg_add_acn(struct scst_acg *acg, const char *name)
++{
++ int res = 0;
++ struct scst_acn *acn;
++ int len;
++ char *nm;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(acn, &acg->acn_list, acn_list_entry) {
++ if (strcmp(acn->name, name) == 0) {
++ PRINT_ERROR("Name %s already exists in group %s",
++ name, acg->acg_name);
++ res = -EEXIST;
++ goto out;
++ }
++ }
++
++ acn = kzalloc(sizeof(*acn), GFP_KERNEL);
++ if (acn == NULL) {
++ PRINT_ERROR("%s", "Unable to allocate scst_acn");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ acn->acg = acg;
++
++ len = strlen(name);
++ nm = kmalloc(len + 1, GFP_KERNEL);
++ if (nm == NULL) {
++ PRINT_ERROR("%s", "Unable to allocate scst_acn->name");
++ res = -ENOMEM;
++ goto out_free;
++ }
++
++ strcpy(nm, name);
++ acn->name = nm;
++
++ res = scst_acn_sysfs_create(acn);
++ if (res != 0)
++ goto out_free_nm;
++
++ list_add_tail(&acn->acn_list_entry, &acg->acn_list);
++
++out:
++ if (res == 0) {
++ PRINT_INFO("Added name %s to group %s", name, acg->acg_name);
++ scst_check_reassign_sessions();
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free_nm:
++ kfree(nm);
++
++out_free:
++ kfree(acn);
++ goto out;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++void scst_del_free_acn(struct scst_acn *acn, bool reassign)
++{
++ TRACE_ENTRY();
++
++ list_del(&acn->acn_list_entry);
++
++ scst_acn_sysfs_del(acn);
++
++ kfree(acn->name);
++ kfree(acn);
++
++ if (reassign)
++ scst_check_reassign_sessions();
++
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++struct scst_acn *scst_find_acn(struct scst_acg *acg, const char *name)
++{
++ struct scst_acn *acn;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Trying to find name '%s'", name);
++
++ list_for_each_entry(acn, &acg->acn_list, acn_list_entry) {
++ if (strcmp(acn->name, name) == 0) {
++ TRACE_DBG("%s", "Found");
++ goto out;
++ }
++ }
++ acn = NULL;
++out:
++ TRACE_EXIT();
++ return acn;
++}
++
++static struct scst_cmd *scst_create_prepare_internal_cmd(
++ struct scst_cmd *orig_cmd, int bufsize)
++{
++ struct scst_cmd *res;
++ gfp_t gfp_mask = scst_cmd_atomic(orig_cmd) ? GFP_ATOMIC : GFP_KERNEL;
++
++ TRACE_ENTRY();
++
++ res = scst_alloc_cmd(gfp_mask);
++ if (res == NULL)
++ goto out;
++
++ res->cmd_threads = orig_cmd->cmd_threads;
++ res->sess = orig_cmd->sess;
++ res->atomic = scst_cmd_atomic(orig_cmd);
++ res->internal = 1;
++ res->tgtt = orig_cmd->tgtt;
++ res->tgt = orig_cmd->tgt;
++ res->dev = orig_cmd->dev;
++ res->tgt_dev = orig_cmd->tgt_dev;
++ res->lun = orig_cmd->lun;
++ res->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
++ res->data_direction = SCST_DATA_UNKNOWN;
++ res->orig_cmd = orig_cmd;
++ res->bufflen = bufsize;
++
++ scst_sess_get(res->sess);
++ if (res->tgt_dev != NULL)
++ __scst_get();
++
++ res->state = SCST_CMD_STATE_PARSE;
++
++out:
++ TRACE_EXIT_HRES((unsigned long)res);
++ return res;
++}
++
++int scst_prepare_request_sense(struct scst_cmd *orig_cmd)
++{
++ int res = 0;
++ static const uint8_t request_sense[6] = {
++ REQUEST_SENSE, 0, 0, 0, SCST_SENSE_BUFFERSIZE, 0
++ };
++ struct scst_cmd *rs_cmd;
++
++ TRACE_ENTRY();
++
++ if (orig_cmd->sense != NULL) {
++ TRACE_MEM("Releasing sense %p (orig_cmd %p)",
++ orig_cmd->sense, orig_cmd);
++ mempool_free(orig_cmd->sense, scst_sense_mempool);
++ orig_cmd->sense = NULL;
++ }
++
++ rs_cmd = scst_create_prepare_internal_cmd(orig_cmd,
++ SCST_SENSE_BUFFERSIZE);
++ if (rs_cmd == NULL)
++ goto out_error;
++
++ memcpy(rs_cmd->cdb, request_sense, sizeof(request_sense));
++ rs_cmd->cdb[1] |= scst_get_cmd_dev_d_sense(orig_cmd);
++ rs_cmd->cdb_len = sizeof(request_sense);
++ rs_cmd->data_direction = SCST_DATA_READ;
++ rs_cmd->expected_data_direction = rs_cmd->data_direction;
++ rs_cmd->expected_transfer_len = SCST_SENSE_BUFFERSIZE;
++ rs_cmd->expected_values_set = 1;
++
++ TRACE_MGMT_DBG("Adding REQUEST SENSE cmd %p to head of active "
++ "cmd list", rs_cmd);
++ spin_lock_irq(&rs_cmd->cmd_threads->cmd_list_lock);
++ list_add(&rs_cmd->cmd_list_entry, &rs_cmd->cmd_threads->active_cmd_list);
++ wake_up(&rs_cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock_irq(&rs_cmd->cmd_threads->cmd_list_lock);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_error:
++ res = -1;
++ goto out;
++}
++
++static void scst_complete_request_sense(struct scst_cmd *req_cmd)
++{
++ struct scst_cmd *orig_cmd = req_cmd->orig_cmd;
++ uint8_t *buf;
++ int len;
++
++ TRACE_ENTRY();
++
++ BUG_ON(orig_cmd == NULL);
++
++ len = scst_get_buf_first(req_cmd, &buf);
++
++ if (scsi_status_is_good(req_cmd->status) && (len > 0) &&
++ SCST_SENSE_VALID(buf) && (!SCST_NO_SENSE(buf))) {
++ PRINT_BUFF_FLAG(TRACE_SCSI, "REQUEST SENSE returned",
++ buf, len);
++ scst_alloc_set_sense(orig_cmd, scst_cmd_atomic(req_cmd), buf,
++ len);
++ } else {
++ PRINT_ERROR("%s", "Unable to get the sense via "
++ "REQUEST SENSE, returning HARDWARE ERROR");
++ scst_set_cmd_error(orig_cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++
++ if (len > 0)
++ scst_put_buf(req_cmd, buf);
++
++ TRACE_MGMT_DBG("Adding orig cmd %p to head of active "
++ "cmd list", orig_cmd);
++ spin_lock_irq(&orig_cmd->cmd_threads->cmd_list_lock);
++ list_add(&orig_cmd->cmd_list_entry, &orig_cmd->cmd_threads->active_cmd_list);
++ wake_up(&orig_cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock_irq(&orig_cmd->cmd_threads->cmd_list_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++int scst_finish_internal_cmd(struct scst_cmd *cmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ BUG_ON(!cmd->internal);
++
++ if (cmd->cdb[0] == REQUEST_SENSE)
++ scst_complete_request_sense(cmd);
++
++ __scst_cmd_put(cmd);
++
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++static void scst_send_release(struct scst_device *dev)
++{
++ struct scsi_device *scsi_dev;
++ unsigned char cdb[6];
++ uint8_t sense[SCSI_SENSE_BUFFERSIZE];
++ int rc, i;
++
++ TRACE_ENTRY();
++
++ if (dev->scsi_dev == NULL)
++ goto out;
++
++ scsi_dev = dev->scsi_dev;
++
++ for (i = 0; i < 5; i++) {
++ memset(cdb, 0, sizeof(cdb));
++ cdb[0] = RELEASE;
++ cdb[1] = (scsi_dev->scsi_level <= SCSI_2) ?
++ ((scsi_dev->lun << 5) & 0xe0) : 0;
++
++ memset(sense, 0, sizeof(sense));
++
++ TRACE(TRACE_DEBUG | TRACE_SCSI, "%s", "Sending RELEASE req to "
++ "SCSI mid-level");
++ rc = scsi_execute(scsi_dev, cdb, SCST_DATA_NONE, NULL, 0,
++ sense, 15, 0, 0
++ , NULL
++ );
++ TRACE_DBG("MODE_SENSE done: %x", rc);
++
++ if (scsi_status_is_good(rc)) {
++ break;
++ } else {
++ PRINT_ERROR("RELEASE failed: %d", rc);
++ PRINT_BUFFER("RELEASE sense", sense, sizeof(sense));
++ scst_check_internal_sense(dev, rc, sense,
++ sizeof(sense));
++ }
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* scst_mutex supposed to be held */
++static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_device *dev = tgt_dev->dev;
++ int release = 0;
++
++ TRACE_ENTRY();
++
++ spin_lock_bh(&dev->dev_lock);
++ if (dev->dev_reserved &&
++ !test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags)) {
++ /* This is one who holds the reservation */
++ struct scst_tgt_dev *tgt_dev_tmp;
++ list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ clear_bit(SCST_TGT_DEV_RESERVED,
++ &tgt_dev_tmp->tgt_dev_flags);
++ }
++ dev->dev_reserved = 0;
++ release = 1;
++ }
++ spin_unlock_bh(&dev->dev_lock);
++
++ if (release)
++ scst_send_release(dev);
++
++ TRACE_EXIT();
++ return;
++}
++
++struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
++ const char *initiator_name)
++{
++ struct scst_session *sess;
++ int i;
++
++ TRACE_ENTRY();
++
++ sess = kmem_cache_zalloc(scst_sess_cachep, gfp_mask);
++ if (sess == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s",
++ "Allocation of scst_session failed");
++ goto out;
++ }
++
++ sess->init_phase = SCST_SESS_IPH_INITING;
++ sess->shut_phase = SCST_SESS_SPH_READY;
++ atomic_set(&sess->refcnt, 0);
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ INIT_LIST_HEAD(sess_tgt_dev_list_head);
++ }
++ spin_lock_init(&sess->sess_list_lock);
++ INIT_LIST_HEAD(&sess->sess_cmd_list);
++ sess->tgt = tgt;
++ INIT_LIST_HEAD(&sess->init_deferred_cmd_list);
++ INIT_LIST_HEAD(&sess->init_deferred_mcmd_list);
++ INIT_DELAYED_WORK(&sess->hw_pending_work,
++ (void (*)(struct work_struct *))scst_hw_pending_work_fn);
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++ spin_lock_init(&sess->lat_lock);
++#endif
++
++ sess->initiator_name = kstrdup(initiator_name, gfp_mask);
++ if (sess->initiator_name == NULL) {
++ PRINT_ERROR("%s", "Unable to dup sess->initiator_name");
++ goto out_free;
++ }
++
++out:
++ TRACE_EXIT();
++ return sess;
++
++out_free:
++ kmem_cache_free(scst_sess_cachep, sess);
++ sess = NULL;
++ goto out;
++}
++
++void scst_free_session(struct scst_session *sess)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ scst_sess_free_tgt_devs(sess);
++
++ /* tgt will stay alive at least until its sysfs alive */
++ kobject_get(&sess->tgt->tgt_kobj);
++
++ mutex_unlock(&scst_mutex);
++ scst_sess_sysfs_del(sess);
++ mutex_lock(&scst_mutex);
++
++ /*
++ * The lists delete must be after sysfs del. Otherwise it would break
++ * logic in scst_sess_sysfs_create() to avoid duplicate sysfs names.
++ */
++
++ TRACE_DBG("Removing sess %p from the list", sess);
++ list_del(&sess->sess_list_entry);
++ TRACE_DBG("Removing session %p from acg %s", sess, sess->acg->acg_name);
++ list_del(&sess->acg_sess_list_entry);
++
++ mutex_unlock(&scst_mutex);
++
++ wake_up_all(&sess->tgt->unreg_waitQ);
++
++ kobject_put(&sess->tgt->tgt_kobj);
++
++ kfree(sess->transport_id);
++ kfree(sess->initiator_name);
++
++ kmem_cache_free(scst_sess_cachep, sess);
++
++ TRACE_EXIT();
++ return;
++}
++
++void scst_free_session_callback(struct scst_session *sess)
++{
++ struct completion *c;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Freeing session %p", sess);
++
++ cancel_delayed_work_sync(&sess->hw_pending_work);
++
++ c = sess->shutdown_compl;
++
++ mutex_lock(&scst_mutex);
++ /*
++ * Necessary to sync with other threads trying to queue AEN, which
++ * the target driver will not be able to serve and crash, because after
++ * unreg_done_fn() called its internal session data will be destroyed.
++ */
++ sess->shut_phase = SCST_SESS_SPH_UNREG_DONE_CALLING;
++ mutex_unlock(&scst_mutex);
++
++ if (sess->unreg_done_fn) {
++ TRACE_DBG("Calling unreg_done_fn(%p)", sess);
++ sess->unreg_done_fn(sess);
++ TRACE_DBG("%s", "unreg_done_fn() returned");
++ }
++ scst_free_session(sess);
++
++ if (c)
++ complete_all(c);
++
++ TRACE_EXIT();
++ return;
++}
++
++void scst_sched_session_free(struct scst_session *sess)
++{
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ if (sess->shut_phase != SCST_SESS_SPH_SHUTDOWN) {
++ PRINT_CRIT_ERROR("session %p is going to shutdown with unknown "
++ "shut phase %lx", sess, sess->shut_phase);
++ BUG();
++ }
++
++ spin_lock_irqsave(&scst_mgmt_lock, flags);
++ TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess);
++ list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list);
++ spin_unlock_irqrestore(&scst_mgmt_lock, flags);
++
++ wake_up(&scst_mgmt_waitQ);
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_cmd_get() - increase command's reference counter
++ */
++void scst_cmd_get(struct scst_cmd *cmd)
++{
++ __scst_cmd_get(cmd);
++}
++EXPORT_SYMBOL(scst_cmd_get);
++
++/**
++ * scst_cmd_put() - decrease command's reference counter
++ */
++void scst_cmd_put(struct scst_cmd *cmd)
++{
++ __scst_cmd_put(cmd);
++}
++EXPORT_SYMBOL(scst_cmd_put);
++
++struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask)
++{
++ struct scst_cmd *cmd;
++
++ TRACE_ENTRY();
++
++ cmd = kmem_cache_zalloc(scst_cmd_cachep, gfp_mask);
++ if (cmd == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of scst_cmd failed");
++ goto out;
++ }
++
++ cmd->state = SCST_CMD_STATE_INIT_WAIT;
++ cmd->start_time = jiffies;
++ atomic_set(&cmd->cmd_ref, 1);
++ cmd->cmd_threads = &scst_main_cmd_threads;
++ INIT_LIST_HEAD(&cmd->mgmt_cmd_list);
++ cmd->queue_type = SCST_CMD_QUEUE_SIMPLE;
++ cmd->timeout = SCST_DEFAULT_TIMEOUT;
++ cmd->retries = 0;
++ cmd->data_len = -1;
++ cmd->is_send_status = 1;
++ cmd->resp_data_len = -1;
++ cmd->write_sg = &cmd->sg;
++ cmd->write_sg_cnt = &cmd->sg_cnt;
++
++ cmd->dbl_ua_orig_data_direction = SCST_DATA_UNKNOWN;
++ cmd->dbl_ua_orig_resp_data_len = -1;
++
++out:
++ TRACE_EXIT();
++ return cmd;
++}
++
++static void scst_destroy_put_cmd(struct scst_cmd *cmd)
++{
++ scst_sess_put(cmd->sess);
++
++ /*
++ * At this point tgt_dev can be dead, but the pointer remains non-NULL
++ */
++ if (likely(cmd->tgt_dev != NULL))
++ __scst_put();
++
++ scst_destroy_cmd(cmd);
++ return;
++}
++
++/* No locks supposed to be held */
++void scst_free_cmd(struct scst_cmd *cmd)
++{
++ int destroy = 1;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Freeing cmd %p (tag %llu)",
++ cmd, (long long unsigned int)cmd->tag);
++
++ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
++ TRACE_MGMT_DBG("Freeing aborted cmd %p (scst_cmd_count %d)",
++ cmd, atomic_read(&scst_cmd_count));
++ }
++
++ BUG_ON(cmd->unblock_dev);
++
++ /*
++ * Target driver can already free sg buffer before calling
++ * scst_tgt_cmd_done(). E.g., scst_local has to do that.
++ */
++ if (!cmd->tgt_data_buf_alloced)
++ scst_check_restore_sg_buff(cmd);
++
++ if ((cmd->tgtt->on_free_cmd != NULL) && likely(!cmd->internal)) {
++ TRACE_DBG("Calling target's on_free_cmd(%p)", cmd);
++ scst_set_cur_start(cmd);
++ cmd->tgtt->on_free_cmd(cmd);
++ scst_set_tgt_on_free_time(cmd);
++ TRACE_DBG("%s", "Target's on_free_cmd() returned");
++ }
++
++ if (likely(cmd->dev != NULL)) {
++ struct scst_dev_type *handler = cmd->dev->handler;
++ if (handler->on_free_cmd != NULL) {
++ TRACE_DBG("Calling dev handler %s on_free_cmd(%p)",
++ handler->name, cmd);
++ scst_set_cur_start(cmd);
++ handler->on_free_cmd(cmd);
++ scst_set_dev_on_free_time(cmd);
++ TRACE_DBG("Dev handler %s on_free_cmd() returned",
++ handler->name);
++ }
++ }
++
++ scst_release_space(cmd);
++
++ if (unlikely(cmd->sense != NULL)) {
++ TRACE_MEM("Releasing sense %p (cmd %p)", cmd->sense, cmd);
++ mempool_free(cmd->sense, scst_sense_mempool);
++ cmd->sense = NULL;
++ }
++
++ if (likely(cmd->tgt_dev != NULL)) {
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (unlikely(!cmd->sent_for_exec) && !cmd->internal) {
++ PRINT_ERROR("Finishing not executed cmd %p (opcode "
++ "%d, target %s, LUN %lld, sn %d, expected_sn %d)",
++ cmd, cmd->cdb[0], cmd->tgtt->name,
++ (long long unsigned int)cmd->lun,
++ cmd->sn, cmd->tgt_dev->expected_sn);
++ scst_unblock_deferred(cmd->tgt_dev, cmd);
++ }
++#endif
++
++ if (unlikely(cmd->out_of_sn)) {
++ TRACE_SN("Out of SN cmd %p (tag %llu, sn %d), "
++ "destroy=%d", cmd,
++ (long long unsigned int)cmd->tag,
++ cmd->sn, destroy);
++ destroy = test_and_set_bit(SCST_CMD_CAN_BE_DESTROYED,
++ &cmd->cmd_flags);
++ }
++ }
++
++ if (likely(destroy))
++ scst_destroy_put_cmd(cmd);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* No locks supposed to be held. */
++void scst_check_retries(struct scst_tgt *tgt)
++{
++ int need_wake_up = 0;
++
++ TRACE_ENTRY();
++
++ /*
++ * We don't worry about overflow of finished_cmds, because we check
++ * only for its change.
++ */
++ atomic_inc(&tgt->finished_cmds);
++ /* See comment in scst_queue_retry_cmd() */
++ smp_mb__after_atomic_inc();
++ if (unlikely(tgt->retry_cmds > 0)) {
++ struct scst_cmd *c, *tc;
++ unsigned long flags;
++
++ TRACE_RETRY("Checking retry cmd list (retry_cmds %d)",
++ tgt->retry_cmds);
++
++ spin_lock_irqsave(&tgt->tgt_lock, flags);
++ list_for_each_entry_safe(c, tc, &tgt->retry_cmd_list,
++ cmd_list_entry) {
++ tgt->retry_cmds--;
++
++ TRACE_RETRY("Moving retry cmd %p to head of active "
++ "cmd list (retry_cmds left %d)",
++ c, tgt->retry_cmds);
++ spin_lock(&c->cmd_threads->cmd_list_lock);
++ list_move(&c->cmd_list_entry,
++ &c->cmd_threads->active_cmd_list);
++ wake_up(&c->cmd_threads->cmd_list_waitQ);
++ spin_unlock(&c->cmd_threads->cmd_list_lock);
++
++ need_wake_up++;
++ if (need_wake_up >= 2) /* "slow start" */
++ break;
++ }
++ spin_unlock_irqrestore(&tgt->tgt_lock, flags);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static void scst_tgt_retry_timer_fn(unsigned long arg)
++{
++ struct scst_tgt *tgt = (struct scst_tgt *)arg;
++ unsigned long flags;
++
++ TRACE_RETRY("Retry timer expired (retry_cmds %d)", tgt->retry_cmds);
++
++ spin_lock_irqsave(&tgt->tgt_lock, flags);
++ tgt->retry_timer_active = 0;
++ spin_unlock_irqrestore(&tgt->tgt_lock, flags);
++
++ scst_check_retries(tgt);
++
++ TRACE_EXIT();
++ return;
++}
++
++struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask)
++{
++ struct scst_mgmt_cmd *mcmd;
++
++ TRACE_ENTRY();
++
++ mcmd = mempool_alloc(scst_mgmt_mempool, gfp_mask);
++ if (mcmd == NULL) {
++ PRINT_CRIT_ERROR("%s", "Allocation of management command "
++ "failed, some commands and their data could leak");
++ goto out;
++ }
++ memset(mcmd, 0, sizeof(*mcmd));
++
++out:
++ TRACE_EXIT();
++ return mcmd;
++}
++
++void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
++{
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ spin_lock_irqsave(&mcmd->sess->sess_list_lock, flags);
++ atomic_dec(&mcmd->sess->sess_cmd_count);
++ spin_unlock_irqrestore(&mcmd->sess->sess_list_lock, flags);
++
++ scst_sess_put(mcmd->sess);
++
++ if (mcmd->mcmd_tgt_dev != NULL)
++ __scst_put();
++
++ mempool_free(mcmd, scst_mgmt_mempool);
++
++ TRACE_EXIT();
++ return;
++}
++
++int scst_alloc_space(struct scst_cmd *cmd)
++{
++ gfp_t gfp_mask;
++ int res = -ENOMEM;
++ int atomic = scst_cmd_atomic(cmd);
++ int flags;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ static int ll;
++
++ TRACE_ENTRY();
++
++ gfp_mask = tgt_dev->gfp_mask | (atomic ? GFP_ATOMIC : GFP_KERNEL);
++
++ flags = atomic ? SGV_POOL_NO_ALLOC_ON_CACHE_MISS : 0;
++ if (cmd->no_sgv)
++ flags |= SGV_POOL_ALLOC_NO_CACHED;
++
++ cmd->sg = sgv_pool_alloc(tgt_dev->pool, cmd->bufflen, gfp_mask, flags,
++ &cmd->sg_cnt, &cmd->sgv, &cmd->dev->dev_mem_lim, NULL);
++ if (cmd->sg == NULL)
++ goto out;
++
++ if (unlikely(cmd->sg_cnt > tgt_dev->max_sg_cnt)) {
++ if ((ll < 10) || TRACING_MINOR()) {
++ PRINT_INFO("Unable to complete command due to "
++ "SG IO count limitation (requested %d, "
++ "available %d, tgt lim %d)", cmd->sg_cnt,
++ tgt_dev->max_sg_cnt, cmd->tgt->sg_tablesize);
++ ll++;
++ }
++ goto out_sg_free;
++ }
++
++ if (cmd->data_direction != SCST_DATA_BIDI)
++ goto success;
++
++ cmd->out_sg = sgv_pool_alloc(tgt_dev->pool, cmd->out_bufflen, gfp_mask,
++ flags, &cmd->out_sg_cnt, &cmd->out_sgv,
++ &cmd->dev->dev_mem_lim, NULL);
++ if (cmd->out_sg == NULL)
++ goto out_sg_free;
++
++ if (unlikely(cmd->out_sg_cnt > tgt_dev->max_sg_cnt)) {
++ if ((ll < 10) || TRACING_MINOR()) {
++ PRINT_INFO("Unable to complete command due to "
++ "SG IO count limitation (OUT buffer, requested "
++ "%d, available %d, tgt lim %d)", cmd->out_sg_cnt,
++ tgt_dev->max_sg_cnt, cmd->tgt->sg_tablesize);
++ ll++;
++ }
++ goto out_out_sg_free;
++ }
++
++success:
++ res = 0;
++
++out:
++ TRACE_EXIT();
++ return res;
++
++out_out_sg_free:
++ sgv_pool_free(cmd->out_sgv, &cmd->dev->dev_mem_lim);
++ cmd->out_sgv = NULL;
++ cmd->out_sg = NULL;
++ cmd->out_sg_cnt = 0;
++
++out_sg_free:
++ sgv_pool_free(cmd->sgv, &cmd->dev->dev_mem_lim);
++ cmd->sgv = NULL;
++ cmd->sg = NULL;
++ cmd->sg_cnt = 0;
++ goto out;
++}
++
++static void scst_release_space(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++ if (cmd->sgv == NULL) {
++ if ((cmd->sg != NULL) &&
++ !(cmd->tgt_data_buf_alloced || cmd->dh_data_buf_alloced)) {
++ TRACE_MEM("Freeing sg %p for cmd %p (cnt %d)", cmd->sg,
++ cmd, cmd->sg_cnt);
++ scst_free(cmd->sg, cmd->sg_cnt);
++ goto out_zero;
++ } else
++ goto out;
++ }
++
++ if (cmd->tgt_data_buf_alloced || cmd->dh_data_buf_alloced) {
++ TRACE_MEM("%s", "*data_buf_alloced set, returning");
++ goto out;
++ }
++
++ if (cmd->out_sgv != NULL) {
++ sgv_pool_free(cmd->out_sgv, &cmd->dev->dev_mem_lim);
++ cmd->out_sgv = NULL;
++ cmd->out_sg_cnt = 0;
++ cmd->out_sg = NULL;
++ cmd->out_bufflen = 0;
++ }
++
++ sgv_pool_free(cmd->sgv, &cmd->dev->dev_mem_lim);
++
++out_zero:
++ cmd->sgv = NULL;
++ cmd->sg_cnt = 0;
++ cmd->sg = NULL;
++ cmd->bufflen = 0;
++ cmd->data_len = 0;
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void scsi_end_async(struct request *req, int error)
++{
++ struct scsi_io_context *sioc = req->end_io_data;
++
++ TRACE_DBG("sioc %p, cmd %p", sioc, sioc->data);
++
++ if (sioc->done)
++ sioc->done(sioc->data, sioc->sense, req->errors, req->resid_len);
++
++ if (!sioc->full_cdb_used)
++ kmem_cache_free(scsi_io_context_cache, sioc);
++ else
++ kfree(sioc);
++
++ __blk_put_request(req->q, req);
++ return;
++}
++
++/**
++ * scst_scsi_exec_async - executes a SCSI command in pass-through mode
++ * @cmd: scst command
++ * @done: callback function when done
++ */
++int scst_scsi_exec_async(struct scst_cmd *cmd,
++ void (*done)(void *, char *, int, int))
++{
++ int res = 0;
++ struct request_queue *q = cmd->dev->scsi_dev->request_queue;
++ struct request *rq;
++ struct scsi_io_context *sioc;
++ int write = (cmd->data_direction & SCST_DATA_WRITE) ? WRITE : READ;
++ gfp_t gfp = GFP_KERNEL;
++ int cmd_len = cmd->cdb_len;
++
++ if (cmd->ext_cdb_len == 0) {
++ TRACE_DBG("Simple CDB (cmd_len %d)", cmd_len);
++ sioc = kmem_cache_zalloc(scsi_io_context_cache, gfp);
++ if (sioc == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++ } else {
++ cmd_len += cmd->ext_cdb_len;
++
++ TRACE_DBG("Extended CDB (cmd_len %d)", cmd_len);
++
++ sioc = kzalloc(sizeof(*sioc) + cmd_len, gfp);
++ if (sioc == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++
++ sioc->full_cdb_used = 1;
++
++ memcpy(sioc->full_cdb, cmd->cdb, cmd->cdb_len);
++ memcpy(&sioc->full_cdb[cmd->cdb_len], cmd->ext_cdb,
++ cmd->ext_cdb_len);
++ }
++
++ rq = blk_get_request(q, write, gfp);
++ if (rq == NULL) {
++ res = -ENOMEM;
++ goto out_free_sioc;
++ }
++
++ rq->cmd_type = REQ_TYPE_BLOCK_PC;
++ rq->cmd_flags |= REQ_QUIET;
++
++ if (cmd->sg == NULL)
++ goto done;
++
++ if (cmd->data_direction == SCST_DATA_BIDI) {
++ struct request *next_rq;
++
++ if (!test_bit(QUEUE_FLAG_BIDI, &q->queue_flags)) {
++ res = -EOPNOTSUPP;
++ goto out_free_rq;
++ }
++
++ res = blk_rq_map_kern_sg(rq, cmd->out_sg, cmd->out_sg_cnt, gfp);
++ if (res != 0) {
++ TRACE_DBG("blk_rq_map_kern_sg() failed: %d", res);
++ goto out_free_rq;
++ }
++
++ next_rq = blk_get_request(q, READ, gfp);
++ if (next_rq == NULL) {
++ res = -ENOMEM;
++ goto out_free_unmap;
++ }
++ rq->next_rq = next_rq;
++ next_rq->cmd_type = rq->cmd_type;
++
++ res = blk_rq_map_kern_sg(next_rq, cmd->sg, cmd->sg_cnt, gfp);
++ if (res != 0) {
++ TRACE_DBG("blk_rq_map_kern_sg() failed: %d", res);
++ goto out_free_unmap;
++ }
++ } else {
++ res = blk_rq_map_kern_sg(rq, cmd->sg, cmd->sg_cnt, gfp);
++ if (res != 0) {
++ TRACE_DBG("blk_rq_map_kern_sg() failed: %d", res);
++ goto out_free_rq;
++ }
++ }
++
++done:
++ TRACE_DBG("sioc %p, cmd %p", sioc, cmd);
++
++ sioc->data = cmd;
++ sioc->done = done;
++
++ rq->cmd_len = cmd_len;
++ if (cmd->ext_cdb_len == 0) {
++ memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
++ memcpy(rq->cmd, cmd->cdb, cmd->cdb_len);
++ } else
++ rq->cmd = sioc->full_cdb;
++
++ rq->sense = sioc->sense;
++ rq->sense_len = sizeof(sioc->sense);
++ rq->timeout = cmd->timeout;
++ rq->retries = cmd->retries;
++ rq->end_io_data = sioc;
++
++ blk_execute_rq_nowait(rq->q, NULL, rq,
++ (cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE), scsi_end_async);
++out:
++ return res;
++
++out_free_unmap:
++ if (rq->next_rq != NULL) {
++ blk_put_request(rq->next_rq);
++ rq->next_rq = NULL;
++ }
++ blk_rq_unmap_kern_sg(rq, res);
++
++out_free_rq:
++ blk_put_request(rq);
++
++out_free_sioc:
++ if (!sioc->full_cdb_used)
++ kmem_cache_free(scsi_io_context_cache, sioc);
++ else
++ kfree(sioc);
++ goto out;
++}
++
++/**
++ * scst_copy_sg() - copy data between the command's SGs
++ *
++ * Copies data between cmd->tgt_sg and cmd->sg in direction defined by
++ * copy_dir parameter.
++ */
++void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir)
++{
++ struct scatterlist *src_sg, *dst_sg;
++ unsigned int to_copy;
++ int atomic = scst_cmd_atomic(cmd);
++
++ TRACE_ENTRY();
++
++ if (copy_dir == SCST_SG_COPY_FROM_TARGET) {
++ if (cmd->data_direction != SCST_DATA_BIDI) {
++ src_sg = cmd->tgt_sg;
++ dst_sg = cmd->sg;
++ to_copy = cmd->bufflen;
++ } else {
++ TRACE_MEM("BIDI cmd %p", cmd);
++ src_sg = cmd->tgt_out_sg;
++ dst_sg = cmd->out_sg;
++ to_copy = cmd->out_bufflen;
++ }
++ } else {
++ src_sg = cmd->sg;
++ dst_sg = cmd->tgt_sg;
++ to_copy = cmd->resp_data_len;
++ }
++
++ TRACE_MEM("cmd %p, copy_dir %d, src_sg %p, dst_sg %p, to_copy %lld",
++ cmd, copy_dir, src_sg, dst_sg, (long long)to_copy);
++
++ if (unlikely(src_sg == NULL) || unlikely(dst_sg == NULL)) {
++ /*
++ * It can happened, e.g., with scst_user for cmd with delay
++ * alloc, which failed with Check Condition.
++ */
++ goto out;
++ }
++
++ sg_copy(dst_sg, src_sg, 0, to_copy,
++ atomic ? KM_SOFTIRQ0 : KM_USER0,
++ atomic ? KM_SOFTIRQ1 : KM_USER1);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_copy_sg);
++
++int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(cmd->sg_buff_vmallocated);
++
++ if (scst_get_buf_count(cmd) > 1) {
++ int len;
++ uint8_t *tmp_buf;
++ int full_size;
++
++ full_size = 0;
++ len = scst_get_buf_first(cmd, &tmp_buf);
++ while (len > 0) {
++ full_size += len;
++ scst_put_buf(cmd, tmp_buf);
++ len = scst_get_buf_next(cmd, &tmp_buf);
++ }
++
++ *buf = vmalloc(full_size);
++ if (*buf == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "vmalloc() failed for opcode "
++ "%x", cmd->cdb[0]);
++ res = -ENOMEM;
++ goto out;
++ }
++ cmd->sg_buff_vmallocated = 1;
++
++ if (scst_cmd_get_data_direction(cmd) == SCST_DATA_WRITE) {
++ uint8_t *buf_ptr;
++
++ buf_ptr = *buf;
++
++ len = scst_get_buf_first(cmd, &tmp_buf);
++ while (len > 0) {
++ memcpy(buf_ptr, tmp_buf, len);
++ buf_ptr += len;
++
++ scst_put_buf(cmd, tmp_buf);
++ len = scst_get_buf_next(cmd, &tmp_buf);
++ }
++ }
++ res = full_size;
++ } else
++ res = scst_get_buf_first(cmd, buf);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf)
++{
++ TRACE_ENTRY();
++
++ if (buf == NULL)
++ goto out;
++
++ if (cmd->sg_buff_vmallocated) {
++ if (scst_cmd_get_data_direction(cmd) == SCST_DATA_READ) {
++ int len;
++ uint8_t *tmp_buf, *buf_p;
++
++ buf_p = buf;
++
++ len = scst_get_buf_first(cmd, &tmp_buf);
++ while (len > 0) {
++ memcpy(tmp_buf, buf_p, len);
++ buf_p += len;
++
++ scst_put_buf(cmd, tmp_buf);
++ len = scst_get_buf_next(cmd, &tmp_buf);
++ }
++
++ }
++
++ cmd->sg_buff_vmallocated = 0;
++
++ vfree(buf);
++ } else
++ scst_put_buf(cmd, buf);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static const int SCST_CDB_LENGTH[8] = { 6, 10, 10, 0, 16, 12, 0, 0 };
++
++#define SCST_CDB_GROUP(opcode) ((opcode >> 5) & 0x7)
++#define SCST_GET_CDB_LEN(opcode) SCST_CDB_LENGTH[SCST_CDB_GROUP(opcode)]
++
++/* get_trans_len_x extract x bytes from cdb as length starting from off */
++
++static int get_trans_cdb_len_10(struct scst_cmd *cmd, uint8_t off)
++{
++ cmd->cdb_len = 10;
++ cmd->bufflen = 0;
++ return 0;
++}
++
++static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off)
++{
++ cmd->bufflen = 6;
++ return 0;
++}
++
++static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off)
++{
++ cmd->bufflen = 8;
++ return 0;
++}
++
++static int get_trans_len_serv_act_in(struct scst_cmd *cmd, uint8_t off)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
++ cmd->op_name = "READ CAPACITY(16)";
++ cmd->bufflen = be32_to_cpu(get_unaligned((__be32 *)&cmd->cdb[10]));
++ cmd->op_flags |= SCST_IMPLICIT_HQ | SCST_REG_RESERVE_ALLOWED |
++ SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
++ } else
++ cmd->op_flags |= SCST_UNKNOWN_LENGTH;
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int get_trans_len_single(struct scst_cmd *cmd, uint8_t off)
++{
++ cmd->bufflen = 1;
++ return 0;
++}
++
++static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off)
++{
++ uint8_t *p = (uint8_t *)cmd->cdb + off;
++ int res = 0;
++
++ cmd->bufflen = 0;
++ cmd->bufflen |= ((u32)p[0]) << 8;
++ cmd->bufflen |= ((u32)p[1]);
++
++ switch (cmd->cdb[1] & 0x1f) {
++ case 0:
++ case 1:
++ case 6:
++ if (cmd->bufflen != 0) {
++ PRINT_ERROR("READ POSITION: Invalid non-zero (%d) "
++ "allocation length for service action %x",
++ cmd->bufflen, cmd->cdb[1] & 0x1f);
++ goto out_inval;
++ }
++ break;
++ }
++
++ switch (cmd->cdb[1] & 0x1f) {
++ case 0:
++ case 1:
++ cmd->bufflen = 20;
++ break;
++ case 6:
++ cmd->bufflen = 32;
++ break;
++ case 8:
++ cmd->bufflen = max(28, cmd->bufflen);
++ break;
++ default:
++ PRINT_ERROR("READ POSITION: Invalid service action %x",
++ cmd->cdb[1] & 0x1f);
++ goto out_inval;
++ }
++
++out:
++ return res;
++
++out_inval:
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ res = 1;
++ goto out;
++}
++
++static int get_trans_len_prevent_allow_medium_removal(struct scst_cmd *cmd,
++ uint8_t off)
++{
++ if ((cmd->cdb[4] & 3) == 0)
++ cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
++ SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
++ return 0;
++}
++
++static int get_trans_len_start_stop(struct scst_cmd *cmd, uint8_t off)
++{
++ if ((cmd->cdb[4] & 0xF1) == 0x1)
++ cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
++ SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
++ return 0;
++}
++
++static int get_trans_len_3_read_elem_stat(struct scst_cmd *cmd, uint8_t off)
++{
++ const uint8_t *p = cmd->cdb + off;
++
++ cmd->bufflen = 0;
++ cmd->bufflen |= ((u32)p[0]) << 16;
++ cmd->bufflen |= ((u32)p[1]) << 8;
++ cmd->bufflen |= ((u32)p[2]);
++
++ if ((cmd->cdb[6] & 0x2) == 0x2)
++ cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
++ SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
++ return 0;
++}
++
++static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off)
++{
++ cmd->bufflen = (u32)cmd->cdb[off];
++ return 0;
++}
++
++static int get_trans_len_1_256(struct scst_cmd *cmd, uint8_t off)
++{
++ cmd->bufflen = (u32)cmd->cdb[off];
++ if (cmd->bufflen == 0)
++ cmd->bufflen = 256;
++ return 0;
++}
++
++static int get_trans_len_2(struct scst_cmd *cmd, uint8_t off)
++{
++ const uint8_t *p = cmd->cdb + off;
++
++ cmd->bufflen = 0;
++ cmd->bufflen |= ((u32)p[0]) << 8;
++ cmd->bufflen |= ((u32)p[1]);
++
++ return 0;
++}
++
++static int get_trans_len_3(struct scst_cmd *cmd, uint8_t off)
++{
++ const uint8_t *p = cmd->cdb + off;
++
++ cmd->bufflen = 0;
++ cmd->bufflen |= ((u32)p[0]) << 16;
++ cmd->bufflen |= ((u32)p[1]) << 8;
++ cmd->bufflen |= ((u32)p[2]);
++
++ return 0;
++}
++
++static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off)
++{
++ const uint8_t *p = cmd->cdb + off;
++
++ cmd->bufflen = 0;
++ cmd->bufflen |= ((u32)p[0]) << 24;
++ cmd->bufflen |= ((u32)p[1]) << 16;
++ cmd->bufflen |= ((u32)p[2]) << 8;
++ cmd->bufflen |= ((u32)p[3]);
++
++ return 0;
++}
++
++static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off)
++{
++ cmd->bufflen = 0;
++ return 0;
++}
++
++static int get_bidi_trans_len_2(struct scst_cmd *cmd, uint8_t off)
++{
++ const uint8_t *p = cmd->cdb + off;
++
++ cmd->bufflen = 0;
++ cmd->bufflen |= ((u32)p[0]) << 8;
++ cmd->bufflen |= ((u32)p[1]);
++
++ cmd->out_bufflen = cmd->bufflen;
++
++ return 0;
++}
++
++/**
++ * scst_get_cdb_info() - fill various info about the command's CDB
++ *
++ * Description:
++ * Fills various info about the command's CDB in the corresponding fields
++ * in the command.
++ *
++ * Returns: 0 on success, <0 if command is unknown, >0 if command
++ * is invalid.
++ */
++int scst_get_cdb_info(struct scst_cmd *cmd)
++{
++ int dev_type = cmd->dev->type;
++ int i, res = 0;
++ uint8_t op;
++ const struct scst_sdbops *ptr = NULL;
++
++ TRACE_ENTRY();
++
++ op = cmd->cdb[0]; /* get clear opcode */
++
++ TRACE_DBG("opcode=%02x, cdblen=%d bytes, tblsize=%d, "
++ "dev_type=%d", op, SCST_GET_CDB_LEN(op), SCST_CDB_TBL_SIZE,
++ dev_type);
++
++ i = scst_scsi_op_list[op];
++ while (i < SCST_CDB_TBL_SIZE && scst_scsi_op_table[i].ops == op) {
++ if (scst_scsi_op_table[i].devkey[dev_type] != SCST_CDB_NOTSUPP) {
++ ptr = &scst_scsi_op_table[i];
++ TRACE_DBG("op = 0x%02x+'%c%c%c%c%c%c%c%c%c%c'+<%s>",
++ ptr->ops, ptr->devkey[0], /* disk */
++ ptr->devkey[1], /* tape */
++ ptr->devkey[2], /* printer */
++ ptr->devkey[3], /* cpu */
++ ptr->devkey[4], /* cdr */
++ ptr->devkey[5], /* cdrom */
++ ptr->devkey[6], /* scanner */
++ ptr->devkey[7], /* worm */
++ ptr->devkey[8], /* changer */
++ ptr->devkey[9], /* commdev */
++ ptr->op_name);
++ TRACE_DBG("direction=%d flags=%d off=%d",
++ ptr->direction,
++ ptr->flags,
++ ptr->off);
++ break;
++ }
++ i++;
++ }
++
++ if (unlikely(ptr == NULL)) {
++ /* opcode not found or now not used */
++ TRACE(TRACE_MINOR, "Unknown opcode 0x%x for type %d", op,
++ dev_type);
++ res = -1;
++ goto out;
++ }
++
++ cmd->cdb_len = SCST_GET_CDB_LEN(op);
++ cmd->op_name = ptr->op_name;
++ cmd->data_direction = ptr->direction;
++ cmd->op_flags = ptr->flags | SCST_INFO_VALID;
++ res = (*ptr->get_trans_len)(cmd, ptr->off);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_get_cdb_info);
++
++/* Packs SCST LUN back to SCSI form */
++__be64 scst_pack_lun(const uint64_t lun, unsigned int addr_method)
++{
++ uint64_t res;
++ uint16_t *p = (uint16_t *)&res;
++
++ res = lun;
++
++ if ((addr_method == SCST_LUN_ADDR_METHOD_FLAT) && (lun != 0)) {
++ /*
++ * Flat space: luns other than 0 should use flat space
++ * addressing method.
++ */
++ *p = 0x7fff & *p;
++ *p = 0x4000 | *p;
++ }
++ /* Default is to use peripheral device addressing mode */
++
++ *p = (__force u16)cpu_to_be16(*p);
++
++ TRACE_EXIT_HRES((unsigned long)res);
++ return (__force __be64)res;
++}
++
++/*
++ * Routine to extract a lun number from an 8-byte LUN structure
++ * in network byte order (BE).
++ * (see SAM-2, Section 4.12.3 page 40)
++ * Supports 2 types of lun unpacking: peripheral and logical unit.
++ */
++uint64_t scst_unpack_lun(const uint8_t *lun, int len)
++{
++ uint64_t res = NO_SUCH_LUN;
++ int address_method;
++
++ TRACE_ENTRY();
++
++ TRACE_BUFF_FLAG(TRACE_DEBUG, "Raw LUN", lun, len);
++
++ if (unlikely(len < 2)) {
++ PRINT_ERROR("Illegal lun length %d, expected 2 bytes or "
++ "more", len);
++ goto out;
++ }
++
++ if (len > 2) {
++ switch (len) {
++ case 8:
++ if ((*((__be64 *)lun) &
++ __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0)
++ goto out_err;
++ break;
++ case 4:
++ if (*((__be16 *)&lun[2]) != 0)
++ goto out_err;
++ break;
++ case 6:
++ if (*((__be32 *)&lun[2]) != 0)
++ goto out_err;
++ break;
++ default:
++ goto out_err;
++ }
++ }
++
++ address_method = (*lun) >> 6; /* high 2 bits of byte 0 */
++ switch (address_method) {
++ case 0: /* peripheral device addressing method */
++#if 0
++ if (*lun) {
++ PRINT_ERROR("Illegal BUS INDENTIFIER in LUN "
++ "peripheral device addressing method 0x%02x, "
++ "expected 0", *lun);
++ break;
++ }
++ res = *(lun + 1);
++ break;
++#else
++ /*
++ * Looks like it's legal to use it as flat space addressing
++ * method as well
++ */
++
++ /* go through */
++#endif
++
++ case 1: /* flat space addressing method */
++ res = *(lun + 1) | (((*lun) & 0x3f) << 8);
++ break;
++
++ case 2: /* logical unit addressing method */
++ if (*lun & 0x3f) {
++ PRINT_ERROR("Illegal BUS NUMBER in LUN logical unit "
++ "addressing method 0x%02x, expected 0",
++ *lun & 0x3f);
++ break;
++ }
++ if (*(lun + 1) & 0xe0) {
++ PRINT_ERROR("Illegal TARGET in LUN logical unit "
++ "addressing method 0x%02x, expected 0",
++ (*(lun + 1) & 0xf8) >> 5);
++ break;
++ }
++ res = *(lun + 1) & 0x1f;
++ break;
++
++ case 3: /* extended logical unit addressing method */
++ default:
++ PRINT_ERROR("Unimplemented LUN addressing method %u",
++ address_method);
++ break;
++ }
++
++out:
++ TRACE_EXIT_RES((int)res);
++ return res;
++
++out_err:
++ PRINT_ERROR("%s", "Multi-level LUN unimplemented");
++ goto out;
++}
++
++/**
++ ** Generic parse() support routines.
++ ** Done via pointer on functions to avoid unneeded dereferences on
++ ** the fast path.
++ **/
++
++/**
++ * scst_calc_block_shift() - calculate block shift
++ *
++ * Calculates and returns block shift for the given sector size
++ */
++int scst_calc_block_shift(int sector_size)
++{
++ int block_shift = 0;
++ int t;
++
++ if (sector_size == 0)
++ sector_size = 512;
++
++ t = sector_size;
++ while (1) {
++ if ((t & 1) != 0)
++ break;
++ t >>= 1;
++ block_shift++;
++ }
++ if (block_shift < 9) {
++ PRINT_ERROR("Wrong sector size %d", sector_size);
++ block_shift = -1;
++ }
++
++ TRACE_EXIT_RES(block_shift);
++ return block_shift;
++}
++EXPORT_SYMBOL_GPL(scst_calc_block_shift);
++
++/**
++ * scst_sbc_generic_parse() - generic SBC parsing
++ *
++ * Generic parse() for SBC (disk) devices
++ */
++int scst_sbc_generic_parse(struct scst_cmd *cmd,
++ int (*get_block_shift)(struct scst_cmd *cmd))
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
++ * therefore change them only if necessary
++ */
++
++ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
++ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
++
++ switch (cmd->cdb[0]) {
++ case VERIFY_6:
++ case VERIFY:
++ case VERIFY_12:
++ case VERIFY_16:
++ if ((cmd->cdb[1] & BYTCHK) == 0) {
++ cmd->data_len = cmd->bufflen << get_block_shift(cmd);
++ cmd->bufflen = 0;
++ goto set_timeout;
++ } else
++ cmd->data_len = 0;
++ break;
++ default:
++ /* It's all good */
++ break;
++ }
++
++ if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED) {
++ int block_shift = get_block_shift(cmd);
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ cmd->bufflen = cmd->bufflen << block_shift;
++ cmd->out_bufflen = cmd->out_bufflen << block_shift;
++ }
++
++set_timeout:
++ if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
++ cmd->timeout = SCST_GENERIC_DISK_REG_TIMEOUT;
++ else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_DISK_SMALL_TIMEOUT;
++ else if (cmd->op_flags & SCST_LONG_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_DISK_LONG_TIMEOUT;
++
++ TRACE_DBG("res %d, bufflen %d, data_len %d, direct %d",
++ res, cmd->bufflen, cmd->data_len, cmd->data_direction);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_sbc_generic_parse);
++
++/**
++ * scst_cdrom_generic_parse() - generic MMC parse
++ *
++ * Generic parse() for MMC (cdrom) devices
++ */
++int scst_cdrom_generic_parse(struct scst_cmd *cmd,
++ int (*get_block_shift)(struct scst_cmd *cmd))
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
++ * therefore change them only if necessary
++ */
++
++ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
++ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
++
++ cmd->cdb[1] &= 0x1f;
++
++ switch (cmd->cdb[0]) {
++ case VERIFY_6:
++ case VERIFY:
++ case VERIFY_12:
++ case VERIFY_16:
++ if ((cmd->cdb[1] & BYTCHK) == 0) {
++ cmd->data_len = cmd->bufflen << get_block_shift(cmd);
++ cmd->bufflen = 0;
++ goto set_timeout;
++ }
++ break;
++ default:
++ /* It's all good */
++ break;
++ }
++
++ if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED) {
++ int block_shift = get_block_shift(cmd);
++ cmd->bufflen = cmd->bufflen << block_shift;
++ cmd->out_bufflen = cmd->out_bufflen << block_shift;
++ }
++
++set_timeout:
++ if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
++ cmd->timeout = SCST_GENERIC_CDROM_REG_TIMEOUT;
++ else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_CDROM_SMALL_TIMEOUT;
++ else if (cmd->op_flags & SCST_LONG_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_CDROM_LONG_TIMEOUT;
++
++ TRACE_DBG("res=%d, bufflen=%d, direct=%d", res, cmd->bufflen,
++ cmd->data_direction);
++
++ TRACE_EXIT();
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_cdrom_generic_parse);
++
++/**
++ * scst_modisk_generic_parse() - generic MO parse
++ *
++ * Generic parse() for MO disk devices
++ */
++int scst_modisk_generic_parse(struct scst_cmd *cmd,
++ int (*get_block_shift)(struct scst_cmd *cmd))
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
++ * therefore change them only if necessary
++ */
++
++ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
++ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
++
++ cmd->cdb[1] &= 0x1f;
++
++ switch (cmd->cdb[0]) {
++ case VERIFY_6:
++ case VERIFY:
++ case VERIFY_12:
++ case VERIFY_16:
++ if ((cmd->cdb[1] & BYTCHK) == 0) {
++ cmd->data_len = cmd->bufflen << get_block_shift(cmd);
++ cmd->bufflen = 0;
++ goto set_timeout;
++ }
++ break;
++ default:
++ /* It's all good */
++ break;
++ }
++
++ if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED) {
++ int block_shift = get_block_shift(cmd);
++ cmd->bufflen = cmd->bufflen << block_shift;
++ cmd->out_bufflen = cmd->out_bufflen << block_shift;
++ }
++
++set_timeout:
++ if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
++ cmd->timeout = SCST_GENERIC_MODISK_REG_TIMEOUT;
++ else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_MODISK_SMALL_TIMEOUT;
++ else if (cmd->op_flags & SCST_LONG_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_MODISK_LONG_TIMEOUT;
++
++ TRACE_DBG("res=%d, bufflen=%d, direct=%d", res, cmd->bufflen,
++ cmd->data_direction);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_modisk_generic_parse);
++
++/**
++ * scst_tape_generic_parse() - generic tape parse
++ *
++ * Generic parse() for tape devices
++ */
++int scst_tape_generic_parse(struct scst_cmd *cmd,
++ int (*get_block_size)(struct scst_cmd *cmd))
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
++ * therefore change them only if necessary
++ */
++
++ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
++ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
++
++ if (cmd->cdb[0] == READ_POSITION) {
++ int tclp = cmd->cdb[1] & 4;
++ int long_bit = cmd->cdb[1] & 2;
++ int bt = cmd->cdb[1] & 1;
++
++ if ((tclp == long_bit) && (!bt || !long_bit)) {
++ cmd->bufflen =
++ tclp ? POSITION_LEN_LONG : POSITION_LEN_SHORT;
++ cmd->data_direction = SCST_DATA_READ;
++ } else {
++ cmd->bufflen = 0;
++ cmd->data_direction = SCST_DATA_NONE;
++ }
++ }
++
++ if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED & cmd->cdb[1]) {
++ int block_size = get_block_size(cmd);
++ cmd->bufflen = cmd->bufflen * block_size;
++ cmd->out_bufflen = cmd->out_bufflen * block_size;
++ }
++
++ if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
++ cmd->timeout = SCST_GENERIC_TAPE_REG_TIMEOUT;
++ else if (cmd->op_flags & SCST_SMALL_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_TAPE_SMALL_TIMEOUT;
++ else if (cmd->op_flags & SCST_LONG_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_TAPE_LONG_TIMEOUT;
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_tape_generic_parse);
++
++static int scst_null_parse(struct scst_cmd *cmd)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->data_direction and cmd->bufflen,
++ * therefore change them only if necessary
++ */
++
++ TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
++ cmd->op_name, cmd->data_direction, cmd->op_flags, cmd->bufflen);
++#if 0
++ switch (cmd->cdb[0]) {
++ default:
++ /* It's all good */
++ break;
++ }
++#endif
++ TRACE_DBG("res %d bufflen %d direct %d",
++ res, cmd->bufflen, cmd->data_direction);
++
++ TRACE_EXIT();
++ return res;
++}
++
++/**
++ * scst_changer_generic_parse() - generic changer parse
++ *
++ * Generic parse() for changer devices
++ */
++int scst_changer_generic_parse(struct scst_cmd *cmd,
++ int (*nothing)(struct scst_cmd *cmd))
++{
++ int res = scst_null_parse(cmd);
++
++ if (cmd->op_flags & SCST_LONG_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_CHANGER_LONG_TIMEOUT;
++ else
++ cmd->timeout = SCST_GENERIC_CHANGER_TIMEOUT;
++
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_changer_generic_parse);
++
++/**
++ * scst_processor_generic_parse - generic SCSI processor parse
++ *
++ * Generic parse() for SCSI processor devices
++ */
++int scst_processor_generic_parse(struct scst_cmd *cmd,
++ int (*nothing)(struct scst_cmd *cmd))
++{
++ int res = scst_null_parse(cmd);
++
++ if (cmd->op_flags & SCST_LONG_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_PROCESSOR_LONG_TIMEOUT;
++ else
++ cmd->timeout = SCST_GENERIC_PROCESSOR_TIMEOUT;
++
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_processor_generic_parse);
++
++/**
++ * scst_raid_generic_parse() - generic RAID parse
++ *
++ * Generic parse() for RAID devices
++ */
++int scst_raid_generic_parse(struct scst_cmd *cmd,
++ int (*nothing)(struct scst_cmd *cmd))
++{
++ int res = scst_null_parse(cmd);
++
++ if (cmd->op_flags & SCST_LONG_TIMEOUT)
++ cmd->timeout = SCST_GENERIC_RAID_LONG_TIMEOUT;
++ else
++ cmd->timeout = SCST_GENERIC_RAID_TIMEOUT;
++
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_raid_generic_parse);
++
++/**
++ ** Generic dev_done() support routines.
++ ** Done via pointer on functions to avoid unneeded dereferences on
++ ** the fast path.
++ **/
++
++/**
++ * scst_block_generic_dev_done() - generic SBC dev_done
++ *
++ * Generic dev_done() for block (SBC) devices
++ */
++int scst_block_generic_dev_done(struct scst_cmd *cmd,
++ void (*set_block_shift)(struct scst_cmd *cmd, int block_shift))
++{
++ int opcode = cmd->cdb[0];
++ int status = cmd->status;
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->is_send_status and
++ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
++ * therefore change them only if necessary
++ */
++
++ if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) {
++ switch (opcode) {
++ case READ_CAPACITY:
++ {
++ /* Always keep track of disk capacity */
++ int buffer_size, sector_size, sh;
++ uint8_t *buffer;
++
++ buffer_size = scst_get_buf_first(cmd, &buffer);
++ if (unlikely(buffer_size <= 0)) {
++ if (buffer_size < 0) {
++ PRINT_ERROR("%s: Unable to get the"
++ " buffer (%d)", __func__, buffer_size);
++ }
++ goto out;
++ }
++
++ sector_size =
++ ((buffer[4] << 24) | (buffer[5] << 16) |
++ (buffer[6] << 8) | (buffer[7] << 0));
++ scst_put_buf(cmd, buffer);
++ if (sector_size != 0)
++ sh = scst_calc_block_shift(sector_size);
++ else
++ sh = 0;
++ set_block_shift(cmd, sh);
++ TRACE_DBG("block_shift %d", sh);
++ break;
++ }
++ default:
++ /* It's all good */
++ break;
++ }
++ }
++
++ TRACE_DBG("cmd->is_send_status=%x, cmd->resp_data_len=%d, "
++ "res=%d", cmd->is_send_status, cmd->resp_data_len, res);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_block_generic_dev_done);
++
++/**
++ * scst_tape_generic_dev_done() - generic tape dev done
++ *
++ * Generic dev_done() for tape devices
++ */
++int scst_tape_generic_dev_done(struct scst_cmd *cmd,
++ void (*set_block_size)(struct scst_cmd *cmd, int block_shift))
++{
++ int opcode = cmd->cdb[0];
++ int res = SCST_CMD_STATE_DEFAULT;
++ int buffer_size, bs;
++ uint8_t *buffer = NULL;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->is_send_status and
++ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
++ * therefore change them only if necessary
++ */
++
++ if (cmd->status != SAM_STAT_GOOD)
++ goto out;
++
++ switch (opcode) {
++ case MODE_SENSE:
++ case MODE_SELECT:
++ buffer_size = scst_get_buf_first(cmd, &buffer);
++ if (unlikely(buffer_size <= 0)) {
++ if (buffer_size < 0) {
++ PRINT_ERROR("%s: Unable to get the buffer (%d)",
++ __func__, buffer_size);
++ }
++ goto out;
++ }
++ break;
++ }
++
++ switch (opcode) {
++ case MODE_SENSE:
++ TRACE_DBG("%s", "MODE_SENSE");
++ if ((cmd->cdb[2] & 0xC0) == 0) {
++ if (buffer[3] == 8) {
++ bs = (buffer[9] << 16) |
++ (buffer[10] << 8) | buffer[11];
++ set_block_size(cmd, bs);
++ }
++ }
++ break;
++ case MODE_SELECT:
++ TRACE_DBG("%s", "MODE_SELECT");
++ if (buffer[3] == 8) {
++ bs = (buffer[9] << 16) | (buffer[10] << 8) |
++ (buffer[11]);
++ set_block_size(cmd, bs);
++ }
++ break;
++ default:
++ /* It's all good */
++ break;
++ }
++
++ switch (opcode) {
++ case MODE_SENSE:
++ case MODE_SELECT:
++ scst_put_buf(cmd, buffer);
++ break;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_tape_generic_dev_done);
++
++static void scst_check_internal_sense(struct scst_device *dev, int result,
++ uint8_t *sense, int sense_len)
++{
++ TRACE_ENTRY();
++
++ if (host_byte(result) == DID_RESET) {
++ int sl;
++ TRACE(TRACE_MGMT, "DID_RESET received for device %s, "
++ "triggering reset UA", dev->virt_name);
++ sl = scst_set_sense(sense, sense_len, dev->d_sense,
++ SCST_LOAD_SENSE(scst_sense_reset_UA));
++ scst_dev_check_set_UA(dev, NULL, sense, sl);
++ } else if ((status_byte(result) == CHECK_CONDITION) &&
++ scst_is_ua_sense(sense, sense_len))
++ scst_dev_check_set_UA(dev, NULL, sense, sense_len);
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_to_dma_dir() - translate SCST's data direction to DMA direction
++ *
++ * Translates SCST's data direction to DMA one from backend storage
++ * perspective.
++ */
++enum dma_data_direction scst_to_dma_dir(int scst_dir)
++{
++ static const enum dma_data_direction tr_tbl[] = { DMA_NONE,
++ DMA_TO_DEVICE, DMA_FROM_DEVICE, DMA_BIDIRECTIONAL, DMA_NONE };
++
++ return tr_tbl[scst_dir];
++}
++EXPORT_SYMBOL(scst_to_dma_dir);
++
++/*
++ * scst_to_tgt_dma_dir() - translate SCST data direction to DMA direction
++ *
++ * Translates SCST data direction to DMA data direction from the perspective
++ * of a target.
++ */
++enum dma_data_direction scst_to_tgt_dma_dir(int scst_dir)
++{
++ static const enum dma_data_direction tr_tbl[] = { DMA_NONE,
++ DMA_FROM_DEVICE, DMA_TO_DEVICE, DMA_BIDIRECTIONAL, DMA_NONE };
++
++ return tr_tbl[scst_dir];
++}
++EXPORT_SYMBOL(scst_to_tgt_dma_dir);
++
++/**
++ * scst_obtain_device_parameters() - obtain device control parameters
++ *
++ * Issues a MODE SENSE for control mode page data and sets the corresponding
++ * dev's parameter from it. Returns 0 on success and not 0 otherwise.
++ */
++int scst_obtain_device_parameters(struct scst_device *dev)
++{
++ int rc, i;
++ uint8_t cmd[16];
++ uint8_t buffer[4+0x0A];
++ uint8_t sense_buffer[SCSI_SENSE_BUFFERSIZE];
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(dev->scsi_dev == NULL);
++
++ for (i = 0; i < 5; i++) {
++ /* Get control mode page */
++ memset(cmd, 0, sizeof(cmd));
++#if 0
++ cmd[0] = MODE_SENSE_10;
++ cmd[1] = 0;
++ cmd[2] = 0x0A;
++ cmd[8] = sizeof(buffer); /* it's < 256 */
++#else
++ cmd[0] = MODE_SENSE;
++ cmd[1] = 8; /* DBD */
++ cmd[2] = 0x0A;
++ cmd[4] = sizeof(buffer);
++#endif
++
++ memset(buffer, 0, sizeof(buffer));
++ memset(sense_buffer, 0, sizeof(sense_buffer));
++
++ TRACE(TRACE_SCSI, "%s", "Doing internal MODE_SENSE");
++ rc = scsi_execute(dev->scsi_dev, cmd, SCST_DATA_READ, buffer,
++ sizeof(buffer), sense_buffer, 15, 0, 0
++ , NULL
++ );
++
++ TRACE_DBG("MODE_SENSE done: %x", rc);
++
++ if (scsi_status_is_good(rc)) {
++ int q;
++
++ PRINT_BUFF_FLAG(TRACE_SCSI, "Returned control mode "
++ "page data", buffer, sizeof(buffer));
++
++ dev->tst = buffer[4+2] >> 5;
++ q = buffer[4+3] >> 4;
++ if (q > SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER) {
++ PRINT_ERROR("Too big QUEUE ALG %x, dev %s",
++ dev->queue_alg, dev->virt_name);
++ }
++ dev->queue_alg = q;
++ dev->swp = (buffer[4+4] & 0x8) >> 3;
++ dev->tas = (buffer[4+5] & 0x40) >> 6;
++ dev->d_sense = (buffer[4+2] & 0x4) >> 2;
++
++ /*
++ * Unfortunately, SCSI ML doesn't provide a way to
++ * specify commands task attribute, so we can rely on
++ * device's restricted reordering only. Linux I/O
++ * subsystem doesn't reorder pass-through (PC) requests.
++ */
++ dev->has_own_order_mgmt = !dev->queue_alg;
++
++ PRINT_INFO("Device %s: TST %x, QUEUE ALG %x, SWP %x, "
++ "TAS %x, D_SENSE %d, has_own_order_mgmt %d",
++ dev->virt_name, dev->tst, dev->queue_alg,
++ dev->swp, dev->tas, dev->d_sense,
++ dev->has_own_order_mgmt);
++
++ goto out;
++ } else {
++ scst_check_internal_sense(dev, rc, sense_buffer,
++ sizeof(sense_buffer));
++#if 0
++ if ((status_byte(rc) == CHECK_CONDITION) &&
++ SCST_SENSE_VALID(sense_buffer)) {
++#else
++ /*
++ * 3ware controller is buggy and returns CONDITION_GOOD
++ * instead of CHECK_CONDITION
++ */
++ if (SCST_SENSE_VALID(sense_buffer)) {
++#endif
++ PRINT_BUFF_FLAG(TRACE_SCSI, "Returned sense "
++ "data", sense_buffer,
++ sizeof(sense_buffer));
++ if (scst_analyze_sense(sense_buffer,
++ sizeof(sense_buffer),
++ SCST_SENSE_KEY_VALID,
++ ILLEGAL_REQUEST, 0, 0)) {
++ PRINT_INFO("Device %s doesn't support "
++ "MODE SENSE", dev->virt_name);
++ break;
++ } else if (scst_analyze_sense(sense_buffer,
++ sizeof(sense_buffer),
++ SCST_SENSE_KEY_VALID,
++ NOT_READY, 0, 0)) {
++ PRINT_ERROR("Device %s not ready",
++ dev->virt_name);
++ break;
++ }
++ } else {
++ PRINT_INFO("Internal MODE SENSE to "
++ "device %s failed: %x",
++ dev->virt_name, rc);
++ PRINT_BUFF_FLAG(TRACE_SCSI, "MODE SENSE sense",
++ sense_buffer, sizeof(sense_buffer));
++ switch (host_byte(rc)) {
++ case DID_RESET:
++ case DID_ABORT:
++ case DID_SOFT_ERROR:
++ break;
++ default:
++ goto brk;
++ }
++ switch (driver_byte(rc)) {
++ case DRIVER_BUSY:
++ case DRIVER_SOFT:
++ break;
++ default:
++ goto brk;
++ }
++ }
++ }
++ }
++brk:
++ PRINT_WARNING("Unable to get device's %s control mode page, using "
++ "existing values/defaults: TST %x, QUEUE ALG %x, SWP %x, "
++ "TAS %x, D_SENSE %d, has_own_order_mgmt %d", dev->virt_name,
++ dev->tst, dev->queue_alg, dev->swp, dev->tas, dev->d_sense,
++ dev->has_own_order_mgmt);
++
++out:
++ TRACE_EXIT();
++ return 0;
++}
++EXPORT_SYMBOL_GPL(scst_obtain_device_parameters);
++
++/* Called under dev_lock and BH off */
++void scst_process_reset(struct scst_device *dev,
++ struct scst_session *originator, struct scst_cmd *exclude_cmd,
++ struct scst_mgmt_cmd *mcmd, bool setUA)
++{
++ struct scst_tgt_dev *tgt_dev;
++ struct scst_cmd *cmd, *tcmd;
++
++ TRACE_ENTRY();
++
++ /* Clear RESERVE'ation, if necessary */
++ if (dev->dev_reserved) {
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ TRACE_MGMT_DBG("Clearing RESERVE'ation for "
++ "tgt_dev LUN %lld",
++ (long long unsigned int)tgt_dev->lun);
++ clear_bit(SCST_TGT_DEV_RESERVED,
++ &tgt_dev->tgt_dev_flags);
++ }
++ dev->dev_reserved = 0;
++ /*
++ * There is no need to send RELEASE, since the device is going
++ * to be resetted. Actually, since we can be in RESET TM
++ * function, it might be dangerous.
++ */
++ }
++
++ dev->dev_double_ua_possible = 1;
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ struct scst_session *sess = tgt_dev->sess;
++
++ spin_lock_bh(&tgt_dev->tgt_dev_lock);
++
++ scst_free_all_UA(tgt_dev);
++
++ memset(tgt_dev->tgt_dev_sense, 0,
++ sizeof(tgt_dev->tgt_dev_sense));
++
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++
++ spin_lock_irq(&sess->sess_list_lock);
++
++ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess);
++ list_for_each_entry(cmd, &sess->sess_cmd_list,
++ sess_cmd_list_entry) {
++ if (cmd == exclude_cmd)
++ continue;
++ if ((cmd->tgt_dev == tgt_dev) ||
++ ((cmd->tgt_dev == NULL) &&
++ (cmd->lun == tgt_dev->lun))) {
++ scst_abort_cmd(cmd, mcmd,
++ (tgt_dev->sess != originator), 0);
++ }
++ }
++ spin_unlock_irq(&sess->sess_list_lock);
++ }
++
++ list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list,
++ blocked_cmd_list_entry) {
++ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
++ list_del(&cmd->blocked_cmd_list_entry);
++ TRACE_MGMT_DBG("Adding aborted blocked cmd %p "
++ "to active cmd list", cmd);
++ spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
++ list_add_tail(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
++ }
++ }
++
++ if (setUA) {
++ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
++ int sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
++ dev->d_sense, SCST_LOAD_SENSE(scst_sense_reset_UA));
++ scst_dev_check_set_local_UA(dev, exclude_cmd, sense_buffer, sl);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* No locks, no IRQ or IRQ-disabled context allowed */
++int scst_set_pending_UA(struct scst_cmd *cmd)
++{
++ int res = 0, i;
++ struct scst_tgt_dev_UA *UA_entry;
++ bool first = true, global_unlock = false;
++ struct scst_session *sess = cmd->sess;
++
++ TRACE_ENTRY();
++
++ /*
++ * RMB and recheck to sync with setting SCST_CMD_ABORTED in
++ * scst_abort_cmd() to not set UA for the being aborted cmd, hence
++ * possibly miss its delivery by a legitimate command while the UA is
++ * being requeued.
++ */
++ smp_rmb();
++ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
++ TRACE_MGMT_DBG("Not set pending UA for aborted cmd %p", cmd);
++ res = -1;
++ goto out;
++ }
++
++ TRACE_MGMT_DBG("Setting pending UA cmd %p", cmd);
++
++ spin_lock_bh(&cmd->tgt_dev->tgt_dev_lock);
++
++again:
++ /* UA list could be cleared behind us, so retest */
++ if (list_empty(&cmd->tgt_dev->UA_list)) {
++ TRACE_DBG("%s",
++ "SCST_TGT_DEV_UA_PENDING set, but UA_list empty");
++ res = -1;
++ goto out_unlock;
++ }
++
++ UA_entry = list_entry(cmd->tgt_dev->UA_list.next, typeof(*UA_entry),
++ UA_list_entry);
++
++ TRACE_DBG("next %p UA_entry %p",
++ cmd->tgt_dev->UA_list.next, UA_entry);
++
++ if (UA_entry->global_UA && first) {
++ TRACE_MGMT_DBG("Global UA %p detected", UA_entry);
++
++ spin_unlock_bh(&cmd->tgt_dev->tgt_dev_lock);
++
++ /*
++ * cmd won't allow to suspend activities, so we can access
++ * sess->sess_tgt_dev_list_hash without any additional
++ * protection.
++ */
++
++ local_bh_disable();
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ /* Lockdep triggers here a false positive.. */
++ spin_lock(&tgt_dev->tgt_dev_lock);
++ }
++ }
++
++ first = false;
++ global_unlock = true;
++ goto again;
++ }
++
++ if (scst_set_cmd_error_sense(cmd, UA_entry->UA_sense_buffer,
++ UA_entry->UA_valid_sense_len) != 0)
++ goto out_unlock;
++
++ cmd->ua_ignore = 1;
++
++ list_del(&UA_entry->UA_list_entry);
++
++ if (UA_entry->global_UA) {
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ struct scst_tgt_dev *tgt_dev;
++
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ struct scst_tgt_dev_UA *ua;
++ list_for_each_entry(ua, &tgt_dev->UA_list,
++ UA_list_entry) {
++ if (ua->global_UA &&
++ memcmp(ua->UA_sense_buffer,
++ UA_entry->UA_sense_buffer,
++ sizeof(ua->UA_sense_buffer)) == 0) {
++ TRACE_MGMT_DBG("Freeing not "
++ "needed global UA %p",
++ ua);
++ list_del(&ua->UA_list_entry);
++ mempool_free(ua, scst_ua_mempool);
++ break;
++ }
++ }
++ }
++ }
++ }
++
++ mempool_free(UA_entry, scst_ua_mempool);
++
++ if (list_empty(&cmd->tgt_dev->UA_list)) {
++ clear_bit(SCST_TGT_DEV_UA_PENDING,
++ &cmd->tgt_dev->tgt_dev_flags);
++ }
++
++out_unlock:
++ if (global_unlock) {
++ for (i = TGT_DEV_HASH_SIZE-1; i >= 0; i--) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry_reverse(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ spin_unlock(&tgt_dev->tgt_dev_lock);
++ }
++ }
++
++ local_bh_enable();
++ spin_lock_bh(&cmd->tgt_dev->tgt_dev_lock);
++ }
++
++ spin_unlock_bh(&cmd->tgt_dev->tgt_dev_lock);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Called under tgt_dev_lock and BH off */
++static void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev,
++ const uint8_t *sense, int sense_len, int flags)
++{
++ struct scst_tgt_dev_UA *UA_entry = NULL;
++
++ TRACE_ENTRY();
++
++ UA_entry = mempool_alloc(scst_ua_mempool, GFP_ATOMIC);
++ if (UA_entry == NULL) {
++ PRINT_CRIT_ERROR("%s", "UNIT ATTENTION memory "
++ "allocation failed. The UNIT ATTENTION "
++ "on some sessions will be missed");
++ PRINT_BUFFER("Lost UA", sense, sense_len);
++ goto out;
++ }
++ memset(UA_entry, 0, sizeof(*UA_entry));
++
++ UA_entry->global_UA = (flags & SCST_SET_UA_FLAG_GLOBAL) != 0;
++ if (UA_entry->global_UA)
++ TRACE_MGMT_DBG("Queuing global UA %p", UA_entry);
++
++ if (sense_len > (int)sizeof(UA_entry->UA_sense_buffer)) {
++ PRINT_WARNING("Sense truncated (needed %d), shall you increase "
++ "SCST_SENSE_BUFFERSIZE?", sense_len);
++ sense_len = sizeof(UA_entry->UA_sense_buffer);
++ }
++ memcpy(UA_entry->UA_sense_buffer, sense, sense_len);
++ UA_entry->UA_valid_sense_len = sense_len;
++
++ set_bit(SCST_TGT_DEV_UA_PENDING, &tgt_dev->tgt_dev_flags);
++
++ TRACE_MGMT_DBG("Adding new UA to tgt_dev %p", tgt_dev);
++
++ if (flags & SCST_SET_UA_FLAG_AT_HEAD)
++ list_add(&UA_entry->UA_list_entry, &tgt_dev->UA_list);
++ else
++ list_add_tail(&UA_entry->UA_list_entry, &tgt_dev->UA_list);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* tgt_dev_lock supposed to be held and BH off */
++static void __scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
++ const uint8_t *sense, int sense_len, int flags)
++{
++ int skip_UA = 0;
++ struct scst_tgt_dev_UA *UA_entry_tmp;
++ int len = min((int)sizeof(UA_entry_tmp->UA_sense_buffer), sense_len);
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(UA_entry_tmp, &tgt_dev->UA_list,
++ UA_list_entry) {
++ if (memcmp(sense, UA_entry_tmp->UA_sense_buffer, len) == 0) {
++ TRACE_MGMT_DBG("%s", "UA already exists");
++ skip_UA = 1;
++ break;
++ }
++ }
++
++ if (skip_UA == 0)
++ scst_alloc_set_UA(tgt_dev, sense, len, flags);
++
++ TRACE_EXIT();
++ return;
++}
++
++void scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
++ const uint8_t *sense, int sense_len, int flags)
++{
++ TRACE_ENTRY();
++
++ spin_lock_bh(&tgt_dev->tgt_dev_lock);
++ __scst_check_set_UA(tgt_dev, sense, sense_len, flags);
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called under dev_lock and BH off */
++void scst_dev_check_set_local_UA(struct scst_device *dev,
++ struct scst_cmd *exclude, const uint8_t *sense, int sense_len)
++{
++ struct scst_tgt_dev *tgt_dev, *exclude_tgt_dev = NULL;
++
++ TRACE_ENTRY();
++
++ if (exclude != NULL)
++ exclude_tgt_dev = exclude->tgt_dev;
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if (tgt_dev != exclude_tgt_dev)
++ scst_check_set_UA(tgt_dev, sense, sense_len, 0);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called under dev_lock and BH off */
++void __scst_dev_check_set_UA(struct scst_device *dev,
++ struct scst_cmd *exclude, const uint8_t *sense, int sense_len)
++{
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Processing UA dev %p", dev);
++
++ /* Check for reset UA */
++ if (scst_analyze_sense(sense, sense_len, SCST_SENSE_ASC_VALID,
++ 0, SCST_SENSE_ASC_UA_RESET, 0))
++ scst_process_reset(dev,
++ (exclude != NULL) ? exclude->sess : NULL,
++ exclude, NULL, false);
++
++ scst_dev_check_set_local_UA(dev, exclude, sense, sense_len);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called under tgt_dev_lock or when tgt_dev is unused */
++static void scst_free_all_UA(struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_tgt_dev_UA *UA_entry, *t;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry_safe(UA_entry, t,
++ &tgt_dev->UA_list, UA_list_entry) {
++ TRACE_MGMT_DBG("Clearing UA for tgt_dev LUN %lld",
++ (long long unsigned int)tgt_dev->lun);
++ list_del(&UA_entry->UA_list_entry);
++ mempool_free(UA_entry, scst_ua_mempool);
++ }
++ INIT_LIST_HEAD(&tgt_dev->UA_list);
++ clear_bit(SCST_TGT_DEV_UA_PENDING, &tgt_dev->tgt_dev_flags);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* No locks */
++struct scst_cmd *__scst_check_deferred_commands(struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_cmd *res = NULL, *cmd, *t;
++ typeof(tgt_dev->expected_sn) expected_sn = tgt_dev->expected_sn;
++
++ spin_lock_irq(&tgt_dev->sn_lock);
++
++ if (unlikely(tgt_dev->hq_cmd_count != 0))
++ goto out_unlock;
++
++restart:
++ list_for_each_entry_safe(cmd, t, &tgt_dev->deferred_cmd_list,
++ sn_cmd_list_entry) {
++ EXTRACHECKS_BUG_ON(cmd->queue_type ==
++ SCST_CMD_QUEUE_HEAD_OF_QUEUE);
++ if (cmd->sn == expected_sn) {
++ TRACE_SN("Deferred command %p (sn %d, set %d) found",
++ cmd, cmd->sn, cmd->sn_set);
++ tgt_dev->def_cmd_count--;
++ list_del(&cmd->sn_cmd_list_entry);
++ if (res == NULL)
++ res = cmd;
++ else {
++ spin_lock(&cmd->cmd_threads->cmd_list_lock);
++ TRACE_SN("Adding cmd %p to active cmd list",
++ cmd);
++ list_add_tail(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
++ }
++ }
++ }
++ if (res != NULL)
++ goto out_unlock;
++
++ list_for_each_entry(cmd, &tgt_dev->skipped_sn_list,
++ sn_cmd_list_entry) {
++ EXTRACHECKS_BUG_ON(cmd->queue_type ==
++ SCST_CMD_QUEUE_HEAD_OF_QUEUE);
++ if (cmd->sn == expected_sn) {
++ atomic_t *slot = cmd->sn_slot;
++ /*
++ * !! At this point any pointer in cmd, except !!
++ * !! sn_slot and sn_cmd_list_entry, could be !!
++ * !! already destroyed !!
++ */
++ TRACE_SN("cmd %p (tag %llu) with skipped sn %d found",
++ cmd,
++ (long long unsigned int)cmd->tag,
++ cmd->sn);
++ tgt_dev->def_cmd_count--;
++ list_del(&cmd->sn_cmd_list_entry);
++ spin_unlock_irq(&tgt_dev->sn_lock);
++ if (test_and_set_bit(SCST_CMD_CAN_BE_DESTROYED,
++ &cmd->cmd_flags))
++ scst_destroy_put_cmd(cmd);
++ scst_inc_expected_sn(tgt_dev, slot);
++ expected_sn = tgt_dev->expected_sn;
++ spin_lock_irq(&tgt_dev->sn_lock);
++ goto restart;
++ }
++ }
++
++out_unlock:
++ spin_unlock_irq(&tgt_dev->sn_lock);
++ return res;
++}
++
++/*****************************************************************
++ ** The following thr_data functions are necessary, because the
++ ** kernel doesn't provide a better way to have threads local
++ ** storage
++ *****************************************************************/
++
++/**
++ * scst_add_thr_data() - add the current thread's local data
++ *
++ * Adds local to the current thread data to tgt_dev
++ * (they will be local for the tgt_dev and current thread).
++ */
++void scst_add_thr_data(struct scst_tgt_dev *tgt_dev,
++ struct scst_thr_data_hdr *data,
++ void (*free_fn) (struct scst_thr_data_hdr *data))
++{
++ data->owner_thr = current;
++ atomic_set(&data->ref, 1);
++ EXTRACHECKS_BUG_ON(free_fn == NULL);
++ data->free_fn = free_fn;
++ spin_lock(&tgt_dev->thr_data_lock);
++ list_add_tail(&data->thr_data_list_entry, &tgt_dev->thr_data_list);
++ spin_unlock(&tgt_dev->thr_data_lock);
++}
++EXPORT_SYMBOL_GPL(scst_add_thr_data);
++
++/**
++ * scst_del_all_thr_data() - delete all thread's local data
++ *
++ * Deletes all local to threads data from tgt_dev
++ */
++void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev)
++{
++ spin_lock(&tgt_dev->thr_data_lock);
++ while (!list_empty(&tgt_dev->thr_data_list)) {
++ struct scst_thr_data_hdr *d = list_entry(
++ tgt_dev->thr_data_list.next, typeof(*d),
++ thr_data_list_entry);
++ list_del(&d->thr_data_list_entry);
++ spin_unlock(&tgt_dev->thr_data_lock);
++ scst_thr_data_put(d);
++ spin_lock(&tgt_dev->thr_data_lock);
++ }
++ spin_unlock(&tgt_dev->thr_data_lock);
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_del_all_thr_data);
++
++/**
++ * scst_dev_del_all_thr_data() - delete all thread's local data from device
++ *
++ * Deletes all local to threads data from all tgt_dev's of the device
++ */
++void scst_dev_del_all_thr_data(struct scst_device *dev)
++{
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ scst_del_all_thr_data(tgt_dev);
++ }
++
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_dev_del_all_thr_data);
++
++/* thr_data_lock supposed to be held */
++static struct scst_thr_data_hdr *__scst_find_thr_data_locked(
++ struct scst_tgt_dev *tgt_dev, struct task_struct *tsk)
++{
++ struct scst_thr_data_hdr *res = NULL, *d;
++
++ list_for_each_entry(d, &tgt_dev->thr_data_list, thr_data_list_entry) {
++ if (d->owner_thr == tsk) {
++ res = d;
++ scst_thr_data_get(res);
++ break;
++ }
++ }
++ return res;
++}
++
++/**
++ * __scst_find_thr_data() - find local to the thread data
++ *
++ * Finds local to the thread data. Returns NULL, if they not found.
++ */
++struct scst_thr_data_hdr *__scst_find_thr_data(struct scst_tgt_dev *tgt_dev,
++ struct task_struct *tsk)
++{
++ struct scst_thr_data_hdr *res;
++
++ spin_lock(&tgt_dev->thr_data_lock);
++ res = __scst_find_thr_data_locked(tgt_dev, tsk);
++ spin_unlock(&tgt_dev->thr_data_lock);
++
++ return res;
++}
++EXPORT_SYMBOL_GPL(__scst_find_thr_data);
++
++bool scst_del_thr_data(struct scst_tgt_dev *tgt_dev, struct task_struct *tsk)
++{
++ bool res;
++ struct scst_thr_data_hdr *td;
++
++ spin_lock(&tgt_dev->thr_data_lock);
++
++ td = __scst_find_thr_data_locked(tgt_dev, tsk);
++ if (td != NULL) {
++ list_del(&td->thr_data_list_entry);
++ res = true;
++ } else
++ res = false;
++
++ spin_unlock(&tgt_dev->thr_data_lock);
++
++ if (td != NULL) {
++ /* the find() fn also gets it */
++ scst_thr_data_put(td);
++ scst_thr_data_put(td);
++ }
++
++ return res;
++}
++
++/* dev_lock supposed to be held and BH disabled */
++void scst_block_dev(struct scst_device *dev)
++{
++ dev->block_count++;
++ TRACE_MGMT_DBG("Device BLOCK(new %d), dev %p", dev->block_count, dev);
++}
++
++/* No locks */
++void scst_unblock_dev(struct scst_device *dev)
++{
++ spin_lock_bh(&dev->dev_lock);
++ TRACE_MGMT_DBG("Device UNBLOCK(new %d), dev %p",
++ dev->block_count-1, dev);
++ if (--dev->block_count == 0)
++ scst_unblock_cmds(dev);
++ spin_unlock_bh(&dev->dev_lock);
++ BUG_ON(dev->block_count < 0);
++}
++
++/* No locks */
++bool __scst_check_blocked_dev(struct scst_cmd *cmd)
++{
++ int res = false;
++ struct scst_device *dev = cmd->dev;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(cmd->unblock_dev);
++
++ if (unlikely(cmd->internal) && (cmd->cdb[0] == REQUEST_SENSE)) {
++ /*
++ * The original command can already block the device, so
++ * REQUEST SENSE command should always pass.
++ */
++ goto out;
++ }
++
++repeat:
++ if (dev->block_count > 0) {
++ spin_lock_bh(&dev->dev_lock);
++ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
++ goto out_unlock;
++ if (dev->block_count > 0) {
++ TRACE_MGMT_DBG("Delaying cmd %p due to blocking "
++ "(tag %llu, dev %p)", cmd,
++ (long long unsigned int)cmd->tag, dev);
++ list_add_tail(&cmd->blocked_cmd_list_entry,
++ &dev->blocked_cmd_list);
++ res = true;
++ spin_unlock_bh(&dev->dev_lock);
++ goto out;
++ } else {
++ TRACE_MGMT_DBG("%s", "Somebody unblocked the device, "
++ "continuing");
++ }
++ spin_unlock_bh(&dev->dev_lock);
++ }
++
++ if (dev->dev_double_ua_possible) {
++ spin_lock_bh(&dev->dev_lock);
++ if (dev->block_count == 0) {
++ TRACE_MGMT_DBG("cmd %p (tag %llu), blocking further "
++ "cmds due to possible double reset UA (dev %p)",
++ cmd, (long long unsigned int)cmd->tag, dev);
++ scst_block_dev(dev);
++ cmd->unblock_dev = 1;
++ } else {
++ spin_unlock_bh(&dev->dev_lock);
++ TRACE_MGMT_DBG("Somebody blocked the device, "
++ "repeating (count %d)", dev->block_count);
++ goto repeat;
++ }
++ spin_unlock_bh(&dev->dev_lock);
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unlock:
++ spin_unlock_bh(&dev->dev_lock);
++ goto out;
++}
++
++/* Called under dev_lock */
++static void scst_unblock_cmds(struct scst_device *dev)
++{
++ struct scst_cmd *cmd, *tcmd;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ local_irq_save(flags);
++ list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list,
++ blocked_cmd_list_entry) {
++ list_del(&cmd->blocked_cmd_list_entry);
++ TRACE_MGMT_DBG("Adding blocked cmd %p to active cmd list", cmd);
++ spin_lock(&cmd->cmd_threads->cmd_list_lock);
++ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
++ list_add(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ else
++ list_add_tail(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
++ }
++ local_irq_restore(flags);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void __scst_unblock_deferred(struct scst_tgt_dev *tgt_dev,
++ struct scst_cmd *out_of_sn_cmd)
++{
++ EXTRACHECKS_BUG_ON(!out_of_sn_cmd->sn_set);
++
++ if (out_of_sn_cmd->sn == tgt_dev->expected_sn) {
++ scst_inc_expected_sn(tgt_dev, out_of_sn_cmd->sn_slot);
++ scst_make_deferred_commands_active(tgt_dev);
++ } else {
++ out_of_sn_cmd->out_of_sn = 1;
++ spin_lock_irq(&tgt_dev->sn_lock);
++ tgt_dev->def_cmd_count++;
++ list_add_tail(&out_of_sn_cmd->sn_cmd_list_entry,
++ &tgt_dev->skipped_sn_list);
++ TRACE_SN("out_of_sn_cmd %p with sn %d added to skipped_sn_list"
++ " (expected_sn %d)", out_of_sn_cmd, out_of_sn_cmd->sn,
++ tgt_dev->expected_sn);
++ spin_unlock_irq(&tgt_dev->sn_lock);
++ }
++
++ return;
++}
++
++void scst_unblock_deferred(struct scst_tgt_dev *tgt_dev,
++ struct scst_cmd *out_of_sn_cmd)
++{
++ TRACE_ENTRY();
++
++ if (!out_of_sn_cmd->sn_set) {
++ TRACE_SN("cmd %p without sn", out_of_sn_cmd);
++ goto out;
++ }
++
++ __scst_unblock_deferred(tgt_dev, out_of_sn_cmd);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++void scst_on_hq_cmd_response(struct scst_cmd *cmd)
++{
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++
++ TRACE_ENTRY();
++
++ if (!cmd->hq_cmd_inced)
++ goto out;
++
++ spin_lock_irq(&tgt_dev->sn_lock);
++ tgt_dev->hq_cmd_count--;
++ spin_unlock_irq(&tgt_dev->sn_lock);
++
++ EXTRACHECKS_BUG_ON(tgt_dev->hq_cmd_count < 0);
++
++ /*
++ * There is no problem in checking hq_cmd_count in the
++ * non-locked state. In the worst case we will only have
++ * unneeded run of the deferred commands.
++ */
++ if (tgt_dev->hq_cmd_count == 0)
++ scst_make_deferred_commands_active(tgt_dev);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++void scst_store_sense(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++ if (SCST_SENSE_VALID(cmd->sense) &&
++ !test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags) &&
++ (cmd->tgt_dev != NULL)) {
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++
++ TRACE_DBG("Storing sense (cmd %p)", cmd);
++
++ spin_lock_bh(&tgt_dev->tgt_dev_lock);
++
++ if (cmd->sense_valid_len <= sizeof(tgt_dev->tgt_dev_sense))
++ tgt_dev->tgt_dev_valid_sense_len = cmd->sense_valid_len;
++ else {
++ tgt_dev->tgt_dev_valid_sense_len = sizeof(tgt_dev->tgt_dev_sense);
++ PRINT_ERROR("Stored sense truncated to size %d "
++ "(needed %d)", tgt_dev->tgt_dev_valid_sense_len,
++ cmd->sense_valid_len);
++ }
++ memcpy(tgt_dev->tgt_dev_sense, cmd->sense,
++ tgt_dev->tgt_dev_valid_sense_len);
++
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++void scst_xmit_process_aborted_cmd(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Aborted cmd %p done (cmd_ref %d, "
++ "scst_cmd_count %d)", cmd, atomic_read(&cmd->cmd_ref),
++ atomic_read(&scst_cmd_count));
++
++ scst_done_cmd_mgmt(cmd);
++
++ if (test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags)) {
++ if (cmd->completed) {
++ /* It's completed and it's OK to return its result */
++ goto out;
++ }
++
++ /* For not yet inited commands cmd->dev can be NULL here */
++ if (test_bit(SCST_CMD_DEVICE_TAS, &cmd->cmd_flags)) {
++ TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd %p "
++ "(tag %llu), returning TASK ABORTED ", cmd,
++ (long long unsigned int)cmd->tag);
++ scst_set_cmd_error_status(cmd, SAM_STAT_TASK_ABORTED);
++ } else {
++ TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd %p "
++ "(tag %llu), aborting without delivery or "
++ "notification",
++ cmd, (long long unsigned int)cmd->tag);
++ /*
++ * There is no need to check/requeue possible UA,
++ * because, if it exists, it will be delivered
++ * by the "completed" branch above.
++ */
++ clear_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
++ }
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_get_max_lun_commands() - return maximum supported commands count
++ *
++ * Returns maximum commands count which can be queued to this LUN in this
++ * session.
++ *
++ * If lun is NO_SUCH_LUN, returns minimum of maximum commands count which
++ * can be queued to any LUN in this session.
++ *
++ * If sess is NULL, returns minimum of maximum commands count which can be
++ * queued to any SCST device.
++ */
++int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun)
++{
++ return SCST_MAX_TGT_DEV_COMMANDS;
++}
++EXPORT_SYMBOL(scst_get_max_lun_commands);
++
++/**
++ * scst_reassign_persistent_sess_states() - reassigns persistent states
++ *
++ * Reassigns persistent states from old_sess to new_sess.
++ */
++void scst_reassign_persistent_sess_states(struct scst_session *new_sess,
++ struct scst_session *old_sess)
++{
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ TRACE_PR("Reassigning persistent states from old_sess %p to "
++ "new_sess %p", old_sess, new_sess);
++
++ if ((new_sess == NULL) || (old_sess == NULL)) {
++ TRACE_DBG("%s", "new_sess or old_sess is NULL");
++ goto out;
++ }
++
++ if (new_sess == old_sess) {
++ TRACE_DBG("%s", "new_sess or old_sess are the same");
++ goto out;
++ }
++
++ if ((new_sess->transport_id == NULL) ||
++ (old_sess->transport_id == NULL)) {
++ TRACE_DBG("%s", "new_sess or old_sess doesn't support PRs");
++ goto out;
++ }
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
++ struct scst_tgt_dev *tgt_dev;
++ struct scst_tgt_dev *new_tgt_dev = NULL, *old_tgt_dev = NULL;
++
++ TRACE_DBG("Processing dev %s", dev->virt_name);
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if (tgt_dev->sess == new_sess) {
++ new_tgt_dev = tgt_dev;
++ if (old_tgt_dev != NULL)
++ break;
++ }
++ if (tgt_dev->sess == old_sess) {
++ old_tgt_dev = tgt_dev;
++ if (new_tgt_dev != NULL)
++ break;
++ }
++ }
++
++ if ((new_tgt_dev == NULL) || (old_tgt_dev == NULL)) {
++ TRACE_DBG("new_tgt_dev %p or old_sess %p is NULL, "
++ "skipping (dev %s)", new_tgt_dev, old_tgt_dev,
++ dev->virt_name);
++ continue;
++ }
++
++ scst_pr_write_lock(dev);
++
++ if (old_tgt_dev->registrant != NULL) {
++ TRACE_PR("Reassigning reg %p from tgt_dev %p to %p",
++ old_tgt_dev->registrant, old_tgt_dev,
++ new_tgt_dev);
++
++ if (new_tgt_dev->registrant != NULL)
++ new_tgt_dev->registrant->tgt_dev = NULL;
++
++ new_tgt_dev->registrant = old_tgt_dev->registrant;
++ new_tgt_dev->registrant->tgt_dev = new_tgt_dev;
++
++ old_tgt_dev->registrant = NULL;
++ }
++
++ scst_pr_write_unlock(dev);
++ }
++
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_reassign_persistent_sess_states);
++
++/**
++ * scst_get_next_lexem() - parse and return next lexem in the string
++ *
++ * Returns pointer to the next lexem from token_str skipping
++ * spaces and '=' character and using them then as a delimeter. Content
++ * of token_str is modified by setting '\0' at the delimeter's position.
++ */
++char *scst_get_next_lexem(char **token_str)
++{
++ char *p = *token_str;
++ char *q;
++ static const char blank = '\0';
++
++ if ((token_str == NULL) || (*token_str == NULL))
++ return (char *)&blank;
++
++ for (p = *token_str; (*p != '\0') && (isspace(*p) || (*p == '=')); p++)
++ ;
++
++ for (q = p; (*q != '\0') && !isspace(*q) && (*q != '='); q++)
++ ;
++
++ if (*q != '\0')
++ *q++ = '\0';
++
++ *token_str = q;
++ return p;
++}
++EXPORT_SYMBOL_GPL(scst_get_next_lexem);
++
++/**
++ * scst_restore_token_str() - restore string modified by scst_get_next_lexem()
++ *
++ * Restores token_str modified by scst_get_next_lexem() to the
++ * previous value before scst_get_next_lexem() was called. Prev_lexem is
++ * a pointer to lexem returned by scst_get_next_lexem().
++ */
++void scst_restore_token_str(char *prev_lexem, char *token_str)
++{
++ if (&prev_lexem[strlen(prev_lexem)] != token_str)
++ prev_lexem[strlen(prev_lexem)] = ' ';
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_restore_token_str);
++
++/**
++ * scst_get_next_token_str() - parse and return next token
++ *
++ * This function returns pointer to the next token strings from input_str
++ * using '\n', ';' and '\0' as a delimeter. Content of input_str is
++ * modified by setting '\0' at the delimeter's position.
++ */
++char *scst_get_next_token_str(char **input_str)
++{
++ char *p = *input_str;
++ int i = 0;
++
++ while ((p[i] != '\n') && (p[i] != ';') && (p[i] != '\0'))
++ i++;
++
++ if (i == 0)
++ return NULL;
++
++ if (p[i] == '\0')
++ *input_str = &p[i];
++ else
++ *input_str = &p[i+1];
++
++ p[i] = '\0';
++
++ return p;
++}
++EXPORT_SYMBOL_GPL(scst_get_next_token_str);
++
++static void __init scst_scsi_op_list_init(void)
++{
++ int i;
++ uint8_t op = 0xff;
++
++ TRACE_ENTRY();
++
++ for (i = 0; i < 256; i++)
++ scst_scsi_op_list[i] = SCST_CDB_TBL_SIZE;
++
++ for (i = 0; i < SCST_CDB_TBL_SIZE; i++) {
++ if (scst_scsi_op_table[i].ops != op) {
++ op = scst_scsi_op_table[i].ops;
++ scst_scsi_op_list[op] = i;
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++int __init scst_lib_init(void)
++{
++ int res = 0;
++
++ scst_scsi_op_list_init();
++
++ scsi_io_context_cache = kmem_cache_create("scst_scsi_io_context",
++ sizeof(struct scsi_io_context),
++ 0, 0, NULL);
++ if (!scsi_io_context_cache) {
++ PRINT_ERROR("%s", "Can't init scsi io context cache");
++ res = -ENOMEM;
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++void scst_lib_exit(void)
++{
++ BUILD_BUG_ON(SCST_MAX_CDB_SIZE != BLK_MAX_CDB);
++ BUILD_BUG_ON(SCST_SENSE_BUFFERSIZE < SCSI_SENSE_BUFFERSIZE);
++
++ kmem_cache_destroy(scsi_io_context_cache);
++}
++
++#ifdef CONFIG_SCST_DEBUG
++
++/**
++ * scst_random() - return a pseudo-random number for debugging purposes.
++ *
++ * Returns a pseudo-random number for debugging purposes. Available only in
++ * the DEBUG build.
++ *
++ * Original taken from the XFS code
++ */
++unsigned long scst_random(void)
++{
++ static int Inited;
++ static unsigned long RandomValue;
++ static DEFINE_SPINLOCK(lock);
++ /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */
++ register long rv;
++ register long lo;
++ register long hi;
++ unsigned long flags;
++
++ spin_lock_irqsave(&lock, flags);
++ if (!Inited) {
++ RandomValue = jiffies;
++ Inited = 1;
++ }
++ rv = RandomValue;
++ hi = rv / 127773;
++ lo = rv % 127773;
++ rv = 16807 * lo - 2836 * hi;
++ if (rv <= 0)
++ rv += 2147483647;
++ RandomValue = rv;
++ spin_unlock_irqrestore(&lock, flags);
++ return rv;
++}
++EXPORT_SYMBOL_GPL(scst_random);
++#endif /* CONFIG_SCST_DEBUG */
++
++#ifdef CONFIG_SCST_DEBUG_TM
++
++#define TM_DBG_STATE_ABORT 0
++#define TM_DBG_STATE_RESET 1
++#define TM_DBG_STATE_OFFLINE 2
++
++#define INIT_TM_DBG_STATE TM_DBG_STATE_ABORT
++
++static void tm_dbg_timer_fn(unsigned long arg);
++
++static DEFINE_SPINLOCK(scst_tm_dbg_lock);
++/* All serialized by scst_tm_dbg_lock */
++static struct {
++ unsigned int tm_dbg_release:1;
++ unsigned int tm_dbg_blocked:1;
++} tm_dbg_flags;
++static LIST_HEAD(tm_dbg_delayed_cmd_list);
++static int tm_dbg_delayed_cmds_count;
++static int tm_dbg_passed_cmds_count;
++static int tm_dbg_state;
++static int tm_dbg_on_state_passes;
++static DEFINE_TIMER(tm_dbg_timer, tm_dbg_timer_fn, 0, 0);
++static struct scst_tgt_dev *tm_dbg_tgt_dev;
++
++static const int tm_dbg_on_state_num_passes[] = { 5, 1, 0x7ffffff };
++
++static void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev)
++{
++ if (tgt_dev->lun == 6) {
++ unsigned long flags;
++
++ if (tm_dbg_tgt_dev != NULL)
++ tm_dbg_deinit_tgt_dev(tm_dbg_tgt_dev);
++
++ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
++ tm_dbg_state = INIT_TM_DBG_STATE;
++ tm_dbg_on_state_passes =
++ tm_dbg_on_state_num_passes[tm_dbg_state];
++ tm_dbg_tgt_dev = tgt_dev;
++ PRINT_INFO("LUN %lld connected from initiator %s is under "
++ "TM debugging (tgt_dev %p)",
++ (unsigned long long)tgt_dev->lun,
++ tgt_dev->sess->initiator_name, tgt_dev);
++ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
++ }
++ return;
++}
++
++static void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev)
++{
++ if (tm_dbg_tgt_dev == tgt_dev) {
++ unsigned long flags;
++ TRACE_MGMT_DBG("Deinit TM debugging tgt_dev %p", tgt_dev);
++ del_timer_sync(&tm_dbg_timer);
++ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
++ tm_dbg_tgt_dev = NULL;
++ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
++ }
++ return;
++}
++
++static void tm_dbg_timer_fn(unsigned long arg)
++{
++ TRACE_MGMT_DBG("%s", "delayed cmd timer expired");
++ tm_dbg_flags.tm_dbg_release = 1;
++ /* Used to make sure that all woken up threads see the new value */
++ smp_wmb();
++ wake_up_all(&tm_dbg_tgt_dev->active_cmd_threads->cmd_list_waitQ);
++ return;
++}
++
++/* Called under scst_tm_dbg_lock and IRQs off */
++static void tm_dbg_delay_cmd(struct scst_cmd *cmd)
++{
++ switch (tm_dbg_state) {
++ case TM_DBG_STATE_ABORT:
++ if (tm_dbg_delayed_cmds_count == 0) {
++ unsigned long d = 58*HZ + (scst_random() % (4*HZ));
++ TRACE_MGMT_DBG("STATE ABORT: delaying cmd %p (tag %llu)"
++ " for %ld.%ld seconds (%ld HZ), "
++ "tm_dbg_on_state_passes=%d", cmd, cmd->tag,
++ d/HZ, (d%HZ)*100/HZ, d, tm_dbg_on_state_passes);
++ mod_timer(&tm_dbg_timer, jiffies + d);
++#if 0
++ tm_dbg_flags.tm_dbg_blocked = 1;
++#endif
++ } else {
++ TRACE_MGMT_DBG("Delaying another timed cmd %p "
++ "(tag %llu), delayed_cmds_count=%d, "
++ "tm_dbg_on_state_passes=%d", cmd, cmd->tag,
++ tm_dbg_delayed_cmds_count,
++ tm_dbg_on_state_passes);
++ if (tm_dbg_delayed_cmds_count == 2)
++ tm_dbg_flags.tm_dbg_blocked = 0;
++ }
++ break;
++
++ case TM_DBG_STATE_RESET:
++ case TM_DBG_STATE_OFFLINE:
++ TRACE_MGMT_DBG("STATE RESET/OFFLINE: delaying cmd %p "
++ "(tag %llu), delayed_cmds_count=%d, "
++ "tm_dbg_on_state_passes=%d", cmd, cmd->tag,
++ tm_dbg_delayed_cmds_count, tm_dbg_on_state_passes);
++ tm_dbg_flags.tm_dbg_blocked = 1;
++ break;
++
++ default:
++ BUG();
++ }
++ /* IRQs already off */
++ spin_lock(&cmd->cmd_threads->cmd_list_lock);
++ list_add_tail(&cmd->cmd_list_entry, &tm_dbg_delayed_cmd_list);
++ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
++ cmd->tm_dbg_delayed = 1;
++ tm_dbg_delayed_cmds_count++;
++ return;
++}
++
++/* No locks */
++void tm_dbg_check_released_cmds(void)
++{
++ if (tm_dbg_flags.tm_dbg_release) {
++ struct scst_cmd *cmd, *tc;
++ spin_lock_irq(&scst_tm_dbg_lock);
++ list_for_each_entry_safe_reverse(cmd, tc,
++ &tm_dbg_delayed_cmd_list, cmd_list_entry) {
++ TRACE_MGMT_DBG("Releasing timed cmd %p (tag %llu), "
++ "delayed_cmds_count=%d", cmd, cmd->tag,
++ tm_dbg_delayed_cmds_count);
++ spin_lock(&cmd->cmd_threads->cmd_list_lock);
++ list_move(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
++ }
++ tm_dbg_flags.tm_dbg_release = 0;
++ spin_unlock_irq(&scst_tm_dbg_lock);
++ }
++}
++
++/* Called under scst_tm_dbg_lock */
++static void tm_dbg_change_state(void)
++{
++ tm_dbg_flags.tm_dbg_blocked = 0;
++ if (--tm_dbg_on_state_passes == 0) {
++ switch (tm_dbg_state) {
++ case TM_DBG_STATE_ABORT:
++ TRACE_MGMT_DBG("%s", "Changing "
++ "tm_dbg_state to RESET");
++ tm_dbg_state = TM_DBG_STATE_RESET;
++ tm_dbg_flags.tm_dbg_blocked = 0;
++ break;
++ case TM_DBG_STATE_RESET:
++ case TM_DBG_STATE_OFFLINE:
++#ifdef CONFIG_SCST_TM_DBG_GO_OFFLINE
++ TRACE_MGMT_DBG("%s", "Changing "
++ "tm_dbg_state to OFFLINE");
++ tm_dbg_state = TM_DBG_STATE_OFFLINE;
++#else
++ TRACE_MGMT_DBG("%s", "Changing "
++ "tm_dbg_state to ABORT");
++ tm_dbg_state = TM_DBG_STATE_ABORT;
++#endif
++ break;
++ default:
++ BUG();
++ }
++ tm_dbg_on_state_passes =
++ tm_dbg_on_state_num_passes[tm_dbg_state];
++ }
++
++ TRACE_MGMT_DBG("%s", "Deleting timer");
++ del_timer_sync(&tm_dbg_timer);
++ return;
++}
++
++/* No locks */
++int tm_dbg_check_cmd(struct scst_cmd *cmd)
++{
++ int res = 0;
++ unsigned long flags;
++
++ if (cmd->tm_dbg_immut)
++ goto out;
++
++ if (cmd->tm_dbg_delayed) {
++ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
++ TRACE_MGMT_DBG("Processing delayed cmd %p (tag %llu), "
++ "delayed_cmds_count=%d", cmd, cmd->tag,
++ tm_dbg_delayed_cmds_count);
++
++ cmd->tm_dbg_immut = 1;
++ tm_dbg_delayed_cmds_count--;
++ if ((tm_dbg_delayed_cmds_count == 0) &&
++ (tm_dbg_state == TM_DBG_STATE_ABORT))
++ tm_dbg_change_state();
++ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
++ } else if (cmd->tgt_dev && (tm_dbg_tgt_dev == cmd->tgt_dev)) {
++ /* Delay 50th command */
++ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
++ if (tm_dbg_flags.tm_dbg_blocked ||
++ (++tm_dbg_passed_cmds_count % 50) == 0) {
++ tm_dbg_delay_cmd(cmd);
++ res = 1;
++ } else
++ cmd->tm_dbg_immut = 1;
++ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
++ }
++
++out:
++ return res;
++}
++
++/* No locks */
++void tm_dbg_release_cmd(struct scst_cmd *cmd)
++{
++ struct scst_cmd *c;
++ unsigned long flags;
++
++ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
++ list_for_each_entry(c, &tm_dbg_delayed_cmd_list,
++ cmd_list_entry) {
++ if (c == cmd) {
++ TRACE_MGMT_DBG("Abort request for "
++ "delayed cmd %p (tag=%llu), moving it to "
++ "active cmd list (delayed_cmds_count=%d)",
++ c, c->tag, tm_dbg_delayed_cmds_count);
++
++ if (!test_bit(SCST_CMD_ABORTED_OTHER,
++ &cmd->cmd_flags)) {
++ /* Test how completed commands handled */
++ if (((scst_random() % 10) == 5)) {
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(
++ scst_sense_hardw_error));
++ /* It's completed now */
++ }
++ }
++
++ spin_lock(&cmd->cmd_threads->cmd_list_lock);
++ list_move(&c->cmd_list_entry,
++ &c->cmd_threads->active_cmd_list);
++ wake_up(&c->cmd_threads->cmd_list_waitQ);
++ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
++ return;
++}
++
++/* Might be called under scst_mutex */
++void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn, int force)
++{
++ unsigned long flags;
++
++ if (dev != NULL) {
++ if (tm_dbg_tgt_dev == NULL)
++ goto out;
++
++ if (tm_dbg_tgt_dev->dev != dev)
++ goto out;
++ }
++
++ spin_lock_irqsave(&scst_tm_dbg_lock, flags);
++ if ((tm_dbg_state != TM_DBG_STATE_OFFLINE) || force) {
++ TRACE_MGMT_DBG("%s: freeing %d delayed cmds", fn,
++ tm_dbg_delayed_cmds_count);
++ tm_dbg_change_state();
++ tm_dbg_flags.tm_dbg_release = 1;
++ /*
++ * Used to make sure that all woken up threads see the new
++ * value.
++ */
++ smp_wmb();
++ if (tm_dbg_tgt_dev != NULL)
++ wake_up_all(&tm_dbg_tgt_dev->active_cmd_threads->cmd_list_waitQ);
++ } else {
++ TRACE_MGMT_DBG("%s: while OFFLINE state, doing nothing", fn);
++ }
++ spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
++
++out:
++ return;
++}
++
++int tm_dbg_is_release(void)
++{
++ return tm_dbg_flags.tm_dbg_release;
++}
++#endif /* CONFIG_SCST_DEBUG_TM */
++
++#ifdef CONFIG_SCST_DEBUG_SN
++void scst_check_debug_sn(struct scst_cmd *cmd)
++{
++ static DEFINE_SPINLOCK(lock);
++ static int type;
++ static int cnt;
++ unsigned long flags;
++ int old = cmd->queue_type;
++
++ spin_lock_irqsave(&lock, flags);
++
++ if (cnt == 0) {
++ if ((scst_random() % 1000) == 500) {
++ if ((scst_random() % 3) == 1)
++ type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
++ else
++ type = SCST_CMD_QUEUE_ORDERED;
++ do {
++ cnt = scst_random() % 10;
++ } while (cnt == 0);
++ } else
++ goto out_unlock;
++ }
++
++ cmd->queue_type = type;
++ cnt--;
++
++ if (((scst_random() % 1000) == 750))
++ cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
++ else if (((scst_random() % 1000) == 751))
++ cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
++ else if (((scst_random() % 1000) == 752))
++ cmd->queue_type = SCST_CMD_QUEUE_SIMPLE;
++
++ TRACE_SN("DbgSN changed cmd %p: %d/%d (cnt %d)", cmd, old,
++ cmd->queue_type, cnt);
++
++out_unlock:
++ spin_unlock_irqrestore(&lock, flags);
++ return;
++}
++#endif /* CONFIG_SCST_DEBUG_SN */
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++
++static uint64_t scst_get_nsec(void)
++{
++ struct timespec ts;
++ ktime_get_ts(&ts);
++ return (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
++}
++
++void scst_set_start_time(struct scst_cmd *cmd)
++{
++ cmd->start = scst_get_nsec();
++ TRACE_DBG("cmd %p: start %lld", cmd, cmd->start);
++}
++
++void scst_set_cur_start(struct scst_cmd *cmd)
++{
++ cmd->curr_start = scst_get_nsec();
++ TRACE_DBG("cmd %p: cur_start %lld", cmd, cmd->curr_start);
++}
++
++void scst_set_parse_time(struct scst_cmd *cmd)
++{
++ cmd->parse_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: parse_time %lld", cmd, cmd->parse_time);
++}
++
++void scst_set_alloc_buf_time(struct scst_cmd *cmd)
++{
++ cmd->alloc_buf_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: alloc_buf_time %lld", cmd, cmd->alloc_buf_time);
++}
++
++void scst_set_restart_waiting_time(struct scst_cmd *cmd)
++{
++ cmd->restart_waiting_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: restart_waiting_time %lld", cmd,
++ cmd->restart_waiting_time);
++}
++
++void scst_set_rdy_to_xfer_time(struct scst_cmd *cmd)
++{
++ cmd->rdy_to_xfer_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: rdy_to_xfer_time %lld", cmd, cmd->rdy_to_xfer_time);
++}
++
++void scst_set_pre_exec_time(struct scst_cmd *cmd)
++{
++ cmd->pre_exec_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: pre_exec_time %lld", cmd, cmd->pre_exec_time);
++}
++
++void scst_set_exec_time(struct scst_cmd *cmd)
++{
++ cmd->exec_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: exec_time %lld", cmd, cmd->exec_time);
++}
++
++void scst_set_dev_done_time(struct scst_cmd *cmd)
++{
++ cmd->dev_done_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: dev_done_time %lld", cmd, cmd->dev_done_time);
++}
++
++void scst_set_xmit_time(struct scst_cmd *cmd)
++{
++ cmd->xmit_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: xmit_time %lld", cmd, cmd->xmit_time);
++}
++
++void scst_set_tgt_on_free_time(struct scst_cmd *cmd)
++{
++ cmd->tgt_on_free_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: tgt_on_free_time %lld", cmd, cmd->tgt_on_free_time);
++}
++
++void scst_set_dev_on_free_time(struct scst_cmd *cmd)
++{
++ cmd->dev_on_free_time += scst_get_nsec() - cmd->curr_start;
++ TRACE_DBG("cmd %p: dev_on_free_time %lld", cmd, cmd->dev_on_free_time);
++}
++
++void scst_update_lat_stats(struct scst_cmd *cmd)
++{
++ uint64_t finish, scst_time, tgt_time, dev_time;
++ struct scst_session *sess = cmd->sess;
++ int data_len;
++ int i;
++ struct scst_ext_latency_stat *latency_stat, *dev_latency_stat;
++
++ finish = scst_get_nsec();
++
++ /* Determine the IO size for extended latency statistics */
++ data_len = cmd->bufflen;
++ i = SCST_LATENCY_STAT_INDEX_OTHER;
++ if (data_len <= SCST_IO_SIZE_THRESHOLD_SMALL)
++ i = SCST_LATENCY_STAT_INDEX_SMALL;
++ else if (data_len <= SCST_IO_SIZE_THRESHOLD_MEDIUM)
++ i = SCST_LATENCY_STAT_INDEX_MEDIUM;
++ else if (data_len <= SCST_IO_SIZE_THRESHOLD_LARGE)
++ i = SCST_LATENCY_STAT_INDEX_LARGE;
++ else if (data_len <= SCST_IO_SIZE_THRESHOLD_VERY_LARGE)
++ i = SCST_LATENCY_STAT_INDEX_VERY_LARGE;
++ latency_stat = &sess->sess_latency_stat[i];
++ if (cmd->tgt_dev != NULL)
++ dev_latency_stat = &cmd->tgt_dev->dev_latency_stat[i];
++ else
++ dev_latency_stat = NULL;
++
++ /* Calculate the latencies */
++ scst_time = finish - cmd->start - (cmd->parse_time +
++ cmd->alloc_buf_time + cmd->restart_waiting_time +
++ cmd->rdy_to_xfer_time + cmd->pre_exec_time +
++ cmd->exec_time + cmd->dev_done_time + cmd->xmit_time +
++ cmd->tgt_on_free_time + cmd->dev_on_free_time);
++ tgt_time = cmd->alloc_buf_time + cmd->restart_waiting_time +
++ cmd->rdy_to_xfer_time + cmd->pre_exec_time +
++ cmd->xmit_time + cmd->tgt_on_free_time;
++ dev_time = cmd->parse_time + cmd->exec_time + cmd->dev_done_time +
++ cmd->dev_on_free_time;
++
++ spin_lock_bh(&sess->lat_lock);
++
++ /* Save the basic latency information */
++ sess->scst_time += scst_time;
++ sess->tgt_time += tgt_time;
++ sess->dev_time += dev_time;
++ sess->processed_cmds++;
++
++ if ((sess->min_scst_time == 0) ||
++ (sess->min_scst_time > scst_time))
++ sess->min_scst_time = scst_time;
++ if ((sess->min_tgt_time == 0) ||
++ (sess->min_tgt_time > tgt_time))
++ sess->min_tgt_time = tgt_time;
++ if ((sess->min_dev_time == 0) ||
++ (sess->min_dev_time > dev_time))
++ sess->min_dev_time = dev_time;
++
++ if (sess->max_scst_time < scst_time)
++ sess->max_scst_time = scst_time;
++ if (sess->max_tgt_time < tgt_time)
++ sess->max_tgt_time = tgt_time;
++ if (sess->max_dev_time < dev_time)
++ sess->max_dev_time = dev_time;
++
++ /* Save the extended latency information */
++ if (cmd->data_direction & SCST_DATA_READ) {
++ latency_stat->scst_time_rd += scst_time;
++ latency_stat->tgt_time_rd += tgt_time;
++ latency_stat->dev_time_rd += dev_time;
++ latency_stat->processed_cmds_rd++;
++
++ if ((latency_stat->min_scst_time_rd == 0) ||
++ (latency_stat->min_scst_time_rd > scst_time))
++ latency_stat->min_scst_time_rd = scst_time;
++ if ((latency_stat->min_tgt_time_rd == 0) ||
++ (latency_stat->min_tgt_time_rd > tgt_time))
++ latency_stat->min_tgt_time_rd = tgt_time;
++ if ((latency_stat->min_dev_time_rd == 0) ||
++ (latency_stat->min_dev_time_rd > dev_time))
++ latency_stat->min_dev_time_rd = dev_time;
++
++ if (latency_stat->max_scst_time_rd < scst_time)
++ latency_stat->max_scst_time_rd = scst_time;
++ if (latency_stat->max_tgt_time_rd < tgt_time)
++ latency_stat->max_tgt_time_rd = tgt_time;
++ if (latency_stat->max_dev_time_rd < dev_time)
++ latency_stat->max_dev_time_rd = dev_time;
++
++ if (dev_latency_stat != NULL) {
++ dev_latency_stat->scst_time_rd += scst_time;
++ dev_latency_stat->tgt_time_rd += tgt_time;
++ dev_latency_stat->dev_time_rd += dev_time;
++ dev_latency_stat->processed_cmds_rd++;
++
++ if ((dev_latency_stat->min_scst_time_rd == 0) ||
++ (dev_latency_stat->min_scst_time_rd > scst_time))
++ dev_latency_stat->min_scst_time_rd = scst_time;
++ if ((dev_latency_stat->min_tgt_time_rd == 0) ||
++ (dev_latency_stat->min_tgt_time_rd > tgt_time))
++ dev_latency_stat->min_tgt_time_rd = tgt_time;
++ if ((dev_latency_stat->min_dev_time_rd == 0) ||
++ (dev_latency_stat->min_dev_time_rd > dev_time))
++ dev_latency_stat->min_dev_time_rd = dev_time;
++
++ if (dev_latency_stat->max_scst_time_rd < scst_time)
++ dev_latency_stat->max_scst_time_rd = scst_time;
++ if (dev_latency_stat->max_tgt_time_rd < tgt_time)
++ dev_latency_stat->max_tgt_time_rd = tgt_time;
++ if (dev_latency_stat->max_dev_time_rd < dev_time)
++ dev_latency_stat->max_dev_time_rd = dev_time;
++ }
++ } else if (cmd->data_direction & SCST_DATA_WRITE) {
++ latency_stat->scst_time_wr += scst_time;
++ latency_stat->tgt_time_wr += tgt_time;
++ latency_stat->dev_time_wr += dev_time;
++ latency_stat->processed_cmds_wr++;
++
++ if ((latency_stat->min_scst_time_wr == 0) ||
++ (latency_stat->min_scst_time_wr > scst_time))
++ latency_stat->min_scst_time_wr = scst_time;
++ if ((latency_stat->min_tgt_time_wr == 0) ||
++ (latency_stat->min_tgt_time_wr > tgt_time))
++ latency_stat->min_tgt_time_wr = tgt_time;
++ if ((latency_stat->min_dev_time_wr == 0) ||
++ (latency_stat->min_dev_time_wr > dev_time))
++ latency_stat->min_dev_time_wr = dev_time;
++
++ if (latency_stat->max_scst_time_wr < scst_time)
++ latency_stat->max_scst_time_wr = scst_time;
++ if (latency_stat->max_tgt_time_wr < tgt_time)
++ latency_stat->max_tgt_time_wr = tgt_time;
++ if (latency_stat->max_dev_time_wr < dev_time)
++ latency_stat->max_dev_time_wr = dev_time;
++
++ if (dev_latency_stat != NULL) {
++ dev_latency_stat->scst_time_wr += scst_time;
++ dev_latency_stat->tgt_time_wr += tgt_time;
++ dev_latency_stat->dev_time_wr += dev_time;
++ dev_latency_stat->processed_cmds_wr++;
++
++ if ((dev_latency_stat->min_scst_time_wr == 0) ||
++ (dev_latency_stat->min_scst_time_wr > scst_time))
++ dev_latency_stat->min_scst_time_wr = scst_time;
++ if ((dev_latency_stat->min_tgt_time_wr == 0) ||
++ (dev_latency_stat->min_tgt_time_wr > tgt_time))
++ dev_latency_stat->min_tgt_time_wr = tgt_time;
++ if ((dev_latency_stat->min_dev_time_wr == 0) ||
++ (dev_latency_stat->min_dev_time_wr > dev_time))
++ dev_latency_stat->min_dev_time_wr = dev_time;
++
++ if (dev_latency_stat->max_scst_time_wr < scst_time)
++ dev_latency_stat->max_scst_time_wr = scst_time;
++ if (dev_latency_stat->max_tgt_time_wr < tgt_time)
++ dev_latency_stat->max_tgt_time_wr = tgt_time;
++ if (dev_latency_stat->max_dev_time_wr < dev_time)
++ dev_latency_stat->max_dev_time_wr = dev_time;
++ }
++ }
++
++ spin_unlock_bh(&sess->lat_lock);
++
++ TRACE_DBG("cmd %p: finish %lld, scst_time %lld, "
++ "tgt_time %lld, dev_time %lld", cmd, finish, scst_time,
++ tgt_time, dev_time);
++ return;
++}
++
++#endif /* CONFIG_SCST_MEASURE_LATENCY */
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_main.c linux-2.6.36/drivers/scst/scst_main.c
+--- orig/linux-2.6.36/drivers/scst/scst_main.c
++++ linux-2.6.36/drivers/scst/scst_main.c
+@@ -0,0 +1,2198 @@
++/*
++ * scst_main.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/unistd.h>
++#include <linux/string.h>
++#include <linux/kthread.h>
++#include <linux/delay.h>
++
++#include <scst/scst.h>
++#include "scst_priv.h"
++#include "scst_mem.h"
++#include "scst_pres.h"
++
++#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G)
++#warning "HIGHMEM kernel configurations are fully supported, but not\
++ recommended for performance reasons. Consider changing VMSPLIT\
++ option or use a 64-bit configuration instead. See README file for\
++ details."
++#endif
++
++/**
++ ** SCST global variables. They are all uninitialized to have their layout in
++ ** memory be exactly as specified. Otherwise compiler puts zero-initialized
++ ** variable separately from nonzero-initialized ones.
++ **/
++
++/*
++ * Main SCST mutex. All targets, devices and dev_types management is done
++ * under this mutex.
++ *
++ * It must NOT be used in any works (schedule_work(), etc.), because
++ * otherwise a deadlock (double lock, actually) is possible, e.g., with
++ * scst_user detach_tgt(), which is called under scst_mutex and calls
++ * flush_scheduled_work().
++ */
++struct mutex scst_mutex;
++EXPORT_SYMBOL_GPL(scst_mutex);
++
++/*
++ * Secondary level main mutex, inner for scst_mutex. Needed for
++ * __scst_pr_register_all_tg_pt(), since we can't use scst_mutex there,
++ * because of the circular locking dependency with dev_pr_mutex.
++ */
++struct mutex scst_mutex2;
++
++/* Both protected by scst_mutex or scst_mutex2 on read and both on write */
++struct list_head scst_template_list;
++struct list_head scst_dev_list;
++
++/* Protected by scst_mutex */
++struct list_head scst_dev_type_list;
++struct list_head scst_virtual_dev_type_list;
++
++spinlock_t scst_main_lock;
++
++static struct kmem_cache *scst_mgmt_cachep;
++mempool_t *scst_mgmt_mempool;
++static struct kmem_cache *scst_mgmt_stub_cachep;
++mempool_t *scst_mgmt_stub_mempool;
++static struct kmem_cache *scst_ua_cachep;
++mempool_t *scst_ua_mempool;
++static struct kmem_cache *scst_sense_cachep;
++mempool_t *scst_sense_mempool;
++static struct kmem_cache *scst_aen_cachep;
++mempool_t *scst_aen_mempool;
++struct kmem_cache *scst_tgtd_cachep;
++struct kmem_cache *scst_sess_cachep;
++struct kmem_cache *scst_acgd_cachep;
++
++unsigned int scst_setup_id;
++
++spinlock_t scst_init_lock;
++wait_queue_head_t scst_init_cmd_list_waitQ;
++struct list_head scst_init_cmd_list;
++unsigned int scst_init_poll_cnt;
++
++struct kmem_cache *scst_cmd_cachep;
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++unsigned long scst_trace_flag;
++#endif
++
++int scst_max_tasklet_cmd = SCST_DEF_MAX_TASKLET_CMD;
++
++unsigned long scst_flags;
++atomic_t scst_cmd_count;
++
++struct scst_cmd_threads scst_main_cmd_threads;
++
++struct scst_tasklet scst_tasklets[NR_CPUS];
++
++spinlock_t scst_mcmd_lock;
++struct list_head scst_active_mgmt_cmd_list;
++struct list_head scst_delayed_mgmt_cmd_list;
++wait_queue_head_t scst_mgmt_cmd_list_waitQ;
++
++wait_queue_head_t scst_mgmt_waitQ;
++spinlock_t scst_mgmt_lock;
++struct list_head scst_sess_init_list;
++struct list_head scst_sess_shut_list;
++
++wait_queue_head_t scst_dev_cmd_waitQ;
++
++static struct mutex scst_suspend_mutex;
++/* protected by scst_suspend_mutex */
++static struct list_head scst_cmd_threads_list;
++
++int scst_threads;
++static struct task_struct *scst_init_cmd_thread;
++static struct task_struct *scst_mgmt_thread;
++static struct task_struct *scst_mgmt_cmd_thread;
++
++static int suspend_count;
++
++static int scst_virt_dev_last_id; /* protected by scst_mutex */
++
++static unsigned int scst_max_cmd_mem;
++unsigned int scst_max_dev_cmd_mem;
++
++module_param_named(scst_threads, scst_threads, int, 0);
++MODULE_PARM_DESC(scst_threads, "SCSI target threads count");
++
++module_param_named(scst_max_cmd_mem, scst_max_cmd_mem, int, S_IRUGO);
++MODULE_PARM_DESC(scst_max_cmd_mem, "Maximum memory allowed to be consumed by "
++ "all SCSI commands of all devices at any given time in MB");
++
++module_param_named(scst_max_dev_cmd_mem, scst_max_dev_cmd_mem, int, S_IRUGO);
++MODULE_PARM_DESC(scst_max_dev_cmd_mem, "Maximum memory allowed to be consumed "
++ "by all SCSI commands of a device at any given time in MB");
++
++struct scst_dev_type scst_null_devtype = {
++ .name = "none",
++ .threads_num = -1,
++};
++
++static void __scst_resume_activity(void);
++
++/**
++ * __scst_register_target_template() - register target template.
++ * @vtt: target template
++ * @version: SCST_INTERFACE_VERSION version string to ensure that
++ * SCST core and the target driver use the same version of
++ * the SCST interface
++ *
++ * Description:
++ * Registers a target template and returns 0 on success or appropriate
++ * error code otherwise.
++ *
++ * Target drivers supposed to behave sanely and not call register()
++ * and unregister() randomly sinultaneously.
++ */
++int __scst_register_target_template(struct scst_tgt_template *vtt,
++ const char *version)
++{
++ int res = 0;
++ struct scst_tgt_template *t;
++
++ TRACE_ENTRY();
++
++ INIT_LIST_HEAD(&vtt->tgt_list);
++
++ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) {
++ PRINT_ERROR("Incorrect version of target %s", vtt->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (!vtt->detect) {
++ PRINT_ERROR("Target driver %s must have "
++ "detect() method.", vtt->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (!vtt->release) {
++ PRINT_ERROR("Target driver %s must have "
++ "release() method.", vtt->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (!vtt->xmit_response) {
++ PRINT_ERROR("Target driver %s must have "
++ "xmit_response() method.", vtt->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (vtt->get_initiator_port_transport_id == NULL)
++ PRINT_WARNING("Target driver %s doesn't support Persistent "
++ "Reservations", vtt->name);
++
++ if (vtt->threads_num < 0) {
++ PRINT_ERROR("Wrong threads_num value %d for "
++ "target \"%s\"", vtt->threads_num,
++ vtt->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if ((!vtt->enable_target || !vtt->is_target_enabled) &&
++ !vtt->enabled_attr_not_needed)
++ PRINT_WARNING("Target driver %s doesn't have enable_target() "
++ "and/or is_target_enabled() method(s). This is unsafe "
++ "and can lead that initiators connected on the "
++ "initialization time can see an unexpected set of "
++ "devices or no devices at all!", vtt->name);
++
++ if (((vtt->add_target != NULL) && (vtt->del_target == NULL)) ||
++ ((vtt->add_target == NULL) && (vtt->del_target != NULL))) {
++ PRINT_ERROR("Target driver %s must either define both "
++ "add_target() and del_target(), or none.", vtt->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (vtt->rdy_to_xfer == NULL)
++ vtt->rdy_to_xfer_atomic = 1;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0)
++ goto out;
++ list_for_each_entry(t, &scst_template_list, scst_template_list_entry) {
++ if (strcmp(t->name, vtt->name) == 0) {
++ PRINT_ERROR("Target driver %s already registered",
++ vtt->name);
++ mutex_unlock(&scst_mutex);
++ goto out_unlock;
++ }
++ }
++ mutex_unlock(&scst_mutex);
++
++ res = scst_tgtt_sysfs_create(vtt);
++ if (res)
++ goto out;
++
++ mutex_lock(&scst_mutex);
++ mutex_lock(&scst_mutex2);
++ list_add_tail(&vtt->scst_template_list_entry, &scst_template_list);
++ mutex_unlock(&scst_mutex2);
++ mutex_unlock(&scst_mutex);
++
++ TRACE_DBG("%s", "Calling target driver's detect()");
++ res = vtt->detect(vtt);
++ TRACE_DBG("Target driver's detect() returned %d", res);
++ if (res < 0) {
++ PRINT_ERROR("%s", "The detect() routine failed");
++ res = -EINVAL;
++ goto out_del;
++ }
++
++ PRINT_INFO("Target template %s registered successfully", vtt->name);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ scst_tgtt_sysfs_del(vtt);
++
++ mutex_lock(&scst_mutex);
++
++ mutex_lock(&scst_mutex2);
++ list_del(&vtt->scst_template_list_entry);
++ mutex_unlock(&scst_mutex2);
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++ goto out;
++}
++EXPORT_SYMBOL_GPL(__scst_register_target_template);
++
++static int scst_check_non_gpl_target_template(struct scst_tgt_template *vtt)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (vtt->task_mgmt_affected_cmds_done || vtt->threads_num ||
++ vtt->on_hw_pending_cmd_timeout) {
++ PRINT_ERROR("Not allowed functionality in non-GPL version for "
++ "target template %s", vtt->name);
++ res = -EPERM;
++ goto out;
++ }
++
++ res = 0;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * __scst_register_target_template_non_gpl() - register target template,
++ * non-GPL version
++ * @vtt: target template
++ * @version: SCST_INTERFACE_VERSION version string to ensure that
++ * SCST core and the target driver use the same version of
++ * the SCST interface
++ *
++ * Description:
++ * Registers a target template and returns 0 on success or appropriate
++ * error code otherwise.
++ *
++ * Note: *vtt must be static!
++ */
++int __scst_register_target_template_non_gpl(struct scst_tgt_template *vtt,
++ const char *version)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ res = scst_check_non_gpl_target_template(vtt);
++ if (res != 0)
++ goto out;
++
++ res = __scst_register_target_template(vtt, version);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL(__scst_register_target_template_non_gpl);
++
++/**
++ * scst_unregister_target_template() - unregister target template
++ *
++ * Target drivers supposed to behave sanely and not call register()
++ * and unregister() randomly sinultaneously. Also it is supposed that
++ * no attepts to create new targets for this vtt will be done in a race
++ * with this function.
++ */
++void scst_unregister_target_template(struct scst_tgt_template *vtt)
++{
++ struct scst_tgt *tgt;
++ struct scst_tgt_template *t;
++ int found = 0;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(t, &scst_template_list, scst_template_list_entry) {
++ if (strcmp(t->name, vtt->name) == 0) {
++ found = 1;
++ break;
++ }
++ }
++ if (!found) {
++ PRINT_ERROR("Target driver %s isn't registered", vtt->name);
++ goto out_err_up;
++ }
++
++ mutex_lock(&scst_mutex2);
++ list_del(&vtt->scst_template_list_entry);
++ mutex_unlock(&scst_mutex2);
++
++ /* Wait for outstanding sysfs mgmt calls completed */
++ while (vtt->tgtt_active_sysfs_works_count > 0) {
++ mutex_unlock(&scst_mutex);
++ msleep(100);
++ mutex_lock(&scst_mutex);
++ }
++
++restart:
++ list_for_each_entry(tgt, &vtt->tgt_list, tgt_list_entry) {
++ mutex_unlock(&scst_mutex);
++ scst_unregister_target(tgt);
++ mutex_lock(&scst_mutex);
++ goto restart;
++ }
++
++ mutex_unlock(&scst_mutex);
++
++ scst_tgtt_sysfs_del(vtt);
++
++ PRINT_INFO("Target template %s unregistered successfully", vtt->name);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_err_up:
++ mutex_unlock(&scst_mutex);
++ goto out;
++}
++EXPORT_SYMBOL(scst_unregister_target_template);
++
++/**
++ * scst_register_target() - register target
++ *
++ * Registers a target for template vtt and returns new target structure on
++ * success or NULL otherwise.
++ */
++struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
++ const char *target_name)
++{
++ struct scst_tgt *tgt;
++ int rc = 0;
++
++ TRACE_ENTRY();
++
++ rc = scst_alloc_tgt(vtt, &tgt);
++ if (rc != 0)
++ goto out;
++
++ if (target_name != NULL) {
++
++ tgt->tgt_name = kmalloc(strlen(target_name) + 1, GFP_KERNEL);
++ if (tgt->tgt_name == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "Allocation of tgt name %s failed",
++ target_name);
++ rc = -ENOMEM;
++ goto out_free_tgt;
++ }
++ strcpy(tgt->tgt_name, target_name);
++ } else {
++ static int tgt_num; /* protected by scst_mutex */
++ int len = strlen(vtt->name) +
++ strlen(SCST_DEFAULT_TGT_NAME_SUFFIX) + 11 + 1;
++
++ tgt->tgt_name = kmalloc(len, GFP_KERNEL);
++ if (tgt->tgt_name == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "Allocation of tgt name failed "
++ "(template name %s)", vtt->name);
++ rc = -ENOMEM;
++ goto out_free_tgt;
++ }
++ sprintf(tgt->tgt_name, "%s%s%d", vtt->name,
++ SCST_DEFAULT_TGT_NAME_SUFFIX, tgt_num++);
++ }
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ rc = -EINTR;
++ goto out_free_tgt;
++ }
++
++ rc = scst_tgt_sysfs_create(tgt);
++ if (rc < 0)
++ goto out_unlock;
++
++ tgt->default_acg = scst_alloc_add_acg(tgt, tgt->tgt_name, false);
++ if (tgt->default_acg == NULL)
++ goto out_sysfs_del;
++
++ mutex_lock(&scst_mutex2);
++ list_add_tail(&tgt->tgt_list_entry, &vtt->tgt_list);
++ mutex_unlock(&scst_mutex2);
++
++ mutex_unlock(&scst_mutex);
++
++ PRINT_INFO("Target %s for template %s registered successfully",
++ tgt->tgt_name, vtt->name);
++
++ TRACE_DBG("tgt %p", tgt);
++
++out:
++ TRACE_EXIT();
++ return tgt;
++
++out_sysfs_del:
++ mutex_unlock(&scst_mutex);
++ scst_tgt_sysfs_del(tgt);
++ goto out_free_tgt;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out_free_tgt:
++ /* In case of error tgt_name will be freed in scst_free_tgt() */
++ scst_free_tgt(tgt);
++ tgt = NULL;
++ goto out;
++}
++EXPORT_SYMBOL(scst_register_target);
++
++static inline int test_sess_list(struct scst_tgt *tgt)
++{
++ int res;
++ mutex_lock(&scst_mutex);
++ res = list_empty(&tgt->sess_list);
++ mutex_unlock(&scst_mutex);
++ return res;
++}
++
++/**
++ * scst_unregister_target() - unregister target.
++ *
++ * It is supposed that no attepts to create new sessions for this
++ * target will be done in a race with this function.
++ */
++void scst_unregister_target(struct scst_tgt *tgt)
++{
++ struct scst_session *sess;
++ struct scst_tgt_template *vtt = tgt->tgtt;
++ struct scst_acg *acg, *acg_tmp;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("%s", "Calling target driver's release()");
++ tgt->tgtt->release(tgt);
++ TRACE_DBG("%s", "Target driver's release() returned");
++
++ mutex_lock(&scst_mutex);
++again:
++ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
++ if (sess->shut_phase == SCST_SESS_SPH_READY) {
++ /*
++ * Sometimes it's hard for target driver to track all
++ * its sessions (see scst_local, eg), so let's help it.
++ */
++ mutex_unlock(&scst_mutex);
++ scst_unregister_session(sess, 0, NULL);
++ mutex_lock(&scst_mutex);
++ goto again;
++ }
++ }
++ mutex_unlock(&scst_mutex);
++
++ TRACE_DBG("%s", "Waiting for sessions shutdown");
++ wait_event(tgt->unreg_waitQ, test_sess_list(tgt));
++ TRACE_DBG("%s", "wait_event() returned");
++
++ scst_suspend_activity(false);
++ mutex_lock(&scst_mutex);
++
++ mutex_lock(&scst_mutex2);
++ list_del(&tgt->tgt_list_entry);
++ mutex_unlock(&scst_mutex2);
++
++ del_timer_sync(&tgt->retry_timer);
++
++ scst_del_free_acg(tgt->default_acg);
++
++ list_for_each_entry_safe(acg, acg_tmp, &tgt->tgt_acg_list,
++ acg_list_entry) {
++ scst_del_free_acg(acg);
++ }
++
++ mutex_unlock(&scst_mutex);
++ scst_resume_activity();
++
++ scst_tgt_sysfs_del(tgt);
++
++ PRINT_INFO("Target %s for template %s unregistered successfully",
++ tgt->tgt_name, vtt->name);
++
++ scst_free_tgt(tgt);
++
++ TRACE_DBG("Unregistering tgt %p finished", tgt);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_unregister_target);
++
++static int scst_susp_wait(bool interruptible)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (interruptible) {
++ res = wait_event_interruptible_timeout(scst_dev_cmd_waitQ,
++ (atomic_read(&scst_cmd_count) == 0),
++ SCST_SUSPENDING_TIMEOUT);
++ if (res <= 0) {
++ __scst_resume_activity();
++ if (res == 0)
++ res = -EBUSY;
++ } else
++ res = 0;
++ } else
++ wait_event(scst_dev_cmd_waitQ,
++ atomic_read(&scst_cmd_count) == 0);
++
++ TRACE_MGMT_DBG("wait_event() returned %d", res);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * scst_suspend_activity() - globally suspend any activity
++ *
++ * Description:
++ * Globally suspends any activity and doesn't return, until there are any
++ * active commands (state after SCST_CMD_STATE_INIT). If "interruptible"
++ * is true, it returns after SCST_SUSPENDING_TIMEOUT or if it was interrupted
++ * by a signal with the corresponding error status < 0. If "interruptible"
++ * is false, it will wait virtually forever. On success returns 0.
++ *
++ * New arriving commands stay in the suspended state until
++ * scst_resume_activity() is called.
++ */
++int scst_suspend_activity(bool interruptible)
++{
++ int res = 0;
++ bool rep = false;
++
++ TRACE_ENTRY();
++
++ if (interruptible) {
++ if (mutex_lock_interruptible(&scst_suspend_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++ } else
++ mutex_lock(&scst_suspend_mutex);
++
++ TRACE_MGMT_DBG("suspend_count %d", suspend_count);
++ suspend_count++;
++ if (suspend_count > 1)
++ goto out_up;
++
++ set_bit(SCST_FLAG_SUSPENDING, &scst_flags);
++ set_bit(SCST_FLAG_SUSPENDED, &scst_flags);
++ /*
++ * Assignment of SCST_FLAG_SUSPENDING and SCST_FLAG_SUSPENDED must be
++ * ordered with scst_cmd_count. Otherwise lockless logic in
++ * scst_translate_lun() and scst_mgmt_translate_lun() won't work.
++ */
++ smp_mb__after_set_bit();
++
++ /*
++ * See comment in scst_user.c::dev_user_task_mgmt_fn() for more
++ * information about scst_user behavior.
++ *
++ * ToDo: make the global suspending unneeded (switch to per-device
++ * reference counting? That would mean to switch off from lockless
++ * implementation of scst_translate_lun().. )
++ */
++
++ if (atomic_read(&scst_cmd_count) != 0) {
++ PRINT_INFO("Waiting for %d active commands to complete... This "
++ "might take few minutes for disks or few hours for "
++ "tapes, if you use long executed commands, like "
++ "REWIND or FORMAT. In case, if you have a hung user "
++ "space device (i.e. made using scst_user module) not "
++ "responding to any commands, if might take virtually "
++ "forever until the corresponding user space "
++ "program recovers and starts responding or gets "
++ "killed.", atomic_read(&scst_cmd_count));
++ rep = true;
++ }
++
++ res = scst_susp_wait(interruptible);
++ if (res != 0)
++ goto out_clear;
++
++ clear_bit(SCST_FLAG_SUSPENDING, &scst_flags);
++ /* See comment about smp_mb() above */
++ smp_mb__after_clear_bit();
++
++ TRACE_MGMT_DBG("Waiting for %d active commands finally to complete",
++ atomic_read(&scst_cmd_count));
++
++ res = scst_susp_wait(interruptible);
++ if (res != 0)
++ goto out_clear;
++
++ if (rep)
++ PRINT_INFO("%s", "All active commands completed");
++
++out_up:
++ mutex_unlock(&scst_suspend_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_clear:
++ clear_bit(SCST_FLAG_SUSPENDING, &scst_flags);
++ /* See comment about smp_mb() above */
++ smp_mb__after_clear_bit();
++ goto out_up;
++}
++EXPORT_SYMBOL_GPL(scst_suspend_activity);
++
++static void __scst_resume_activity(void)
++{
++ struct scst_cmd_threads *l;
++
++ TRACE_ENTRY();
++
++ suspend_count--;
++ TRACE_MGMT_DBG("suspend_count %d left", suspend_count);
++ if (suspend_count > 0)
++ goto out;
++
++ clear_bit(SCST_FLAG_SUSPENDED, &scst_flags);
++ /*
++ * The barrier is needed to make sure all woken up threads see the
++ * cleared flag. Not sure if it's really needed, but let's be safe.
++ */
++ smp_mb__after_clear_bit();
++
++ list_for_each_entry(l, &scst_cmd_threads_list, lists_list_entry) {
++ wake_up_all(&l->cmd_list_waitQ);
++ }
++ wake_up_all(&scst_init_cmd_list_waitQ);
++
++ spin_lock_irq(&scst_mcmd_lock);
++ if (!list_empty(&scst_delayed_mgmt_cmd_list)) {
++ struct scst_mgmt_cmd *m;
++ m = list_entry(scst_delayed_mgmt_cmd_list.next, typeof(*m),
++ mgmt_cmd_list_entry);
++ TRACE_MGMT_DBG("Moving delayed mgmt cmd %p to head of active "
++ "mgmt cmd list", m);
++ list_move(&m->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list);
++ }
++ spin_unlock_irq(&scst_mcmd_lock);
++ wake_up_all(&scst_mgmt_cmd_list_waitQ);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_resume_activity() - globally resume all activities
++ *
++ * Resumes suspended by scst_suspend_activity() activities.
++ */
++void scst_resume_activity(void)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_suspend_mutex);
++ __scst_resume_activity();
++ mutex_unlock(&scst_suspend_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_resume_activity);
++
++static int scst_register_device(struct scsi_device *scsidp)
++{
++ int res = 0;
++ struct scst_device *dev, *d;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = scst_alloc_device(GFP_KERNEL, &dev);
++ if (res != 0)
++ goto out_unlock;
++
++ dev->type = scsidp->type;
++
++ dev->virt_name = kmalloc(50, GFP_KERNEL);
++ if (dev->virt_name == NULL) {
++ PRINT_ERROR("%s", "Unable to alloc device name");
++ res = -ENOMEM;
++ goto out_free_dev;
++ }
++ snprintf(dev->virt_name, 50, "%d:%d:%d:%d", scsidp->host->host_no,
++ scsidp->channel, scsidp->id, scsidp->lun);
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if (strcmp(d->virt_name, dev->virt_name) == 0) {
++ PRINT_ERROR("Device %s already exists", dev->virt_name);
++ res = -EEXIST;
++ goto out_free_dev;
++ }
++ }
++
++ dev->scsi_dev = scsidp;
++
++ list_add_tail(&dev->dev_list_entry, &scst_dev_list);
++
++ mutex_unlock(&scst_mutex);
++
++ res = scst_dev_sysfs_create(dev);
++ if (res != 0)
++ goto out_del;
++
++ PRINT_INFO("Attached to scsi%d, channel %d, id %d, lun %d, "
++ "type %d", scsidp->host->host_no, scsidp->channel,
++ scsidp->id, scsidp->lun, scsidp->type);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ list_del(&dev->dev_list_entry);
++
++out_free_dev:
++ scst_free_device(dev);
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++ goto out;
++}
++
++static void scst_unregister_device(struct scsi_device *scsidp)
++{
++ struct scst_device *d, *dev = NULL;
++ struct scst_acg_dev *acg_dev, *aa;
++
++ TRACE_ENTRY();
++
++ scst_suspend_activity(false);
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if (d->scsi_dev == scsidp) {
++ dev = d;
++ TRACE_DBG("Device %p found", dev);
++ break;
++ }
++ }
++ if (dev == NULL) {
++ PRINT_ERROR("SCST device for SCSI device %d:%d:%d:%d not found",
++ scsidp->host->host_no, scsidp->channel, scsidp->id,
++ scsidp->lun);
++ goto out_unlock;
++ }
++
++ list_del(&dev->dev_list_entry);
++
++ scst_assign_dev_handler(dev, &scst_null_devtype);
++
++ list_for_each_entry_safe(acg_dev, aa, &dev->dev_acg_dev_list,
++ dev_acg_dev_list_entry) {
++ scst_acg_del_lun(acg_dev->acg, acg_dev->lun, true);
++ }
++
++ mutex_unlock(&scst_mutex);
++
++ scst_resume_activity();
++
++ scst_dev_sysfs_del(dev);
++
++ PRINT_INFO("Detached from scsi%d, channel %d, id %d, lun %d, type %d",
++ scsidp->host->host_no, scsidp->channel, scsidp->id,
++ scsidp->lun, scsidp->type);
++
++ scst_free_device(dev);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++ scst_resume_activity();
++ goto out;
++}
++
++static int scst_dev_handler_check(struct scst_dev_type *dev_handler)
++{
++ int res = 0;
++
++ if (dev_handler->parse == NULL) {
++ PRINT_ERROR("scst dev handler %s must have "
++ "parse() method.", dev_handler->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (((dev_handler->add_device != NULL) &&
++ (dev_handler->del_device == NULL)) ||
++ ((dev_handler->add_device == NULL) &&
++ (dev_handler->del_device != NULL))) {
++ PRINT_ERROR("Dev handler %s must either define both "
++ "add_device() and del_device(), or none.",
++ dev_handler->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (dev_handler->alloc_data_buf == NULL)
++ dev_handler->alloc_data_buf_atomic = 1;
++
++ if (dev_handler->dev_done == NULL)
++ dev_handler->dev_done_atomic = 1;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_check_device_name(const char *dev_name)
++{
++ int res = 0;
++
++ if (strchr(dev_name, '/') != NULL) {
++ PRINT_ERROR("Dev name %s contains illegal character '/'",
++ dev_name);
++ res = -EINVAL;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * scst_register_virtual_device() - register a virtual device.
++ * @dev_handler: the device's device handler
++ * @dev_name: the new device name, NULL-terminated string. Must be uniq
++ * among all virtual devices in the system.
++ *
++ * Registers a virtual device and returns assinged to the device ID on
++ * success, or negative value otherwise
++ */
++int scst_register_virtual_device(struct scst_dev_type *dev_handler,
++ const char *dev_name)
++{
++ int res, rc;
++ struct scst_device *dev, *d;
++ bool sysfs_del = false;
++
++ TRACE_ENTRY();
++
++ if (dev_handler == NULL) {
++ PRINT_ERROR("%s: valid device handler must be supplied",
++ __func__);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (dev_name == NULL) {
++ PRINT_ERROR("%s: device name must be non-NULL", __func__);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_check_device_name(dev_name);
++ if (res != 0)
++ goto out;
++
++ res = scst_dev_handler_check(dev_handler);
++ if (res != 0)
++ goto out;
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_resume;
++ }
++
++ res = scst_alloc_device(GFP_KERNEL, &dev);
++ if (res != 0)
++ goto out_unlock;
++
++ dev->type = dev_handler->type;
++ dev->scsi_dev = NULL;
++ dev->virt_name = kstrdup(dev_name, GFP_KERNEL);
++ if (dev->virt_name == NULL) {
++ PRINT_ERROR("Unable to allocate virt_name for dev %s",
++ dev_name);
++ res = -ENOMEM;
++ goto out_free_dev;
++ }
++
++ while (1) {
++ dev->virt_id = scst_virt_dev_last_id++;
++ if (dev->virt_id > 0)
++ break;
++ scst_virt_dev_last_id = 1;
++ }
++
++ res = dev->virt_id;
++
++ rc = scst_pr_init_dev(dev);
++ if (rc != 0) {
++ res = rc;
++ goto out_free_dev;
++ }
++
++ /*
++ * We can drop scst_mutex, because we have not yet added the dev in
++ * scst_dev_list, so it "doesn't exist" yet.
++ */
++ mutex_unlock(&scst_mutex);
++
++ res = scst_dev_sysfs_create(dev);
++ if (res != 0)
++ goto out_lock_pr_clear_dev;
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if (strcmp(d->virt_name, dev_name) == 0) {
++ PRINT_ERROR("Device %s already exists", dev_name);
++ res = -EEXIST;
++ sysfs_del = true;
++ goto out_pr_clear_dev;
++ }
++ }
++
++ rc = scst_assign_dev_handler(dev, dev_handler);
++ if (rc != 0) {
++ res = rc;
++ sysfs_del = true;
++ goto out_pr_clear_dev;
++ }
++
++ list_add_tail(&dev->dev_list_entry, &scst_dev_list);
++
++ mutex_unlock(&scst_mutex);
++ scst_resume_activity();
++
++ res = dev->virt_id;
++
++ PRINT_INFO("Attached to virtual device %s (id %d)",
++ dev_name, res);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_lock_pr_clear_dev:
++ mutex_lock(&scst_mutex);
++
++out_pr_clear_dev:
++ scst_pr_clear_dev(dev);
++
++out_free_dev:
++ mutex_unlock(&scst_mutex);
++ if (sysfs_del)
++ scst_dev_sysfs_del(dev);
++ scst_free_device(dev);
++ goto out_resume;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out_resume:
++ scst_resume_activity();
++ goto out;
++}
++EXPORT_SYMBOL_GPL(scst_register_virtual_device);
++
++/**
++ * scst_unregister_virtual_device() - unegister a virtual device.
++ * @id: the device's ID, returned by the registration function
++ */
++void scst_unregister_virtual_device(int id)
++{
++ struct scst_device *d, *dev = NULL;
++ struct scst_acg_dev *acg_dev, *aa;
++
++ TRACE_ENTRY();
++
++ scst_suspend_activity(false);
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if (d->virt_id == id) {
++ dev = d;
++ TRACE_DBG("Virtual device %p (id %d) found", dev, id);
++ break;
++ }
++ }
++ if (dev == NULL) {
++ PRINT_ERROR("Virtual device (id %d) not found", id);
++ goto out_unlock;
++ }
++
++ list_del(&dev->dev_list_entry);
++
++ scst_pr_clear_dev(dev);
++
++ scst_assign_dev_handler(dev, &scst_null_devtype);
++
++ list_for_each_entry_safe(acg_dev, aa, &dev->dev_acg_dev_list,
++ dev_acg_dev_list_entry) {
++ scst_acg_del_lun(acg_dev->acg, acg_dev->lun, true);
++ }
++
++ mutex_unlock(&scst_mutex);
++ scst_resume_activity();
++
++ scst_dev_sysfs_del(dev);
++
++ PRINT_INFO("Detached from virtual device %s (id %d)",
++ dev->virt_name, dev->virt_id);
++
++ scst_free_device(dev);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++ scst_resume_activity();
++ goto out;
++}
++EXPORT_SYMBOL_GPL(scst_unregister_virtual_device);
++
++/**
++ * __scst_register_dev_driver() - register pass-through dev handler driver
++ * @dev_type: dev handler template
++ * @version: SCST_INTERFACE_VERSION version string to ensure that
++ * SCST core and the dev handler use the same version of
++ * the SCST interface
++ *
++ * Description:
++ * Registers a pass-through dev handler driver. Returns 0 on success
++ * or appropriate error code otherwise.
++ */
++int __scst_register_dev_driver(struct scst_dev_type *dev_type,
++ const char *version)
++{
++ int res, exist;
++ struct scst_dev_type *dt;
++
++ TRACE_ENTRY();
++
++ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) {
++ PRINT_ERROR("Incorrect version of dev handler %s",
++ dev_type->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_dev_handler_check(dev_type);
++ if (res != 0)
++ goto out;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ exist = 0;
++ list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) {
++ if (strcmp(dt->name, dev_type->name) == 0) {
++ PRINT_ERROR("Device type handler \"%s\" already "
++ "exist", dt->name);
++ exist = 1;
++ break;
++ }
++ }
++ if (exist)
++ goto out_unlock;
++
++ list_add_tail(&dev_type->dev_type_list_entry, &scst_dev_type_list);
++
++ mutex_unlock(&scst_mutex);
++
++ res = scst_devt_sysfs_create(dev_type);
++ if (res < 0)
++ goto out;
++
++ PRINT_INFO("Device handler \"%s\" for type %d registered "
++ "successfully", dev_type->name, dev_type->type);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++ goto out;
++}
++EXPORT_SYMBOL_GPL(__scst_register_dev_driver);
++
++/**
++ * scst_unregister_dev_driver() - unregister pass-through dev handler driver
++ */
++void scst_unregister_dev_driver(struct scst_dev_type *dev_type)
++{
++ struct scst_device *dev;
++ struct scst_dev_type *dt;
++ int found = 0;
++
++ TRACE_ENTRY();
++
++ scst_suspend_activity(false);
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) {
++ if (strcmp(dt->name, dev_type->name) == 0) {
++ found = 1;
++ break;
++ }
++ }
++ if (!found) {
++ PRINT_ERROR("Dev handler \"%s\" isn't registered",
++ dev_type->name);
++ goto out_up;
++ }
++
++ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
++ if (dev->handler == dev_type) {
++ scst_assign_dev_handler(dev, &scst_null_devtype);
++ TRACE_DBG("Dev handler removed from device %p", dev);
++ }
++ }
++
++ list_del(&dev_type->dev_type_list_entry);
++
++ mutex_unlock(&scst_mutex);
++ scst_resume_activity();
++
++ scst_devt_sysfs_del(dev_type);
++
++ PRINT_INFO("Device handler \"%s\" for type %d unloaded",
++ dev_type->name, dev_type->type);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_up:
++ mutex_unlock(&scst_mutex);
++ scst_resume_activity();
++ goto out;
++}
++EXPORT_SYMBOL_GPL(scst_unregister_dev_driver);
++
++/**
++ * __scst_register_virtual_dev_driver() - register virtual dev handler driver
++ * @dev_type: dev handler template
++ * @version: SCST_INTERFACE_VERSION version string to ensure that
++ * SCST core and the dev handler use the same version of
++ * the SCST interface
++ *
++ * Description:
++ * Registers a virtual dev handler driver. Returns 0 on success or
++ * appropriate error code otherwise.
++ */
++int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
++ const char *version)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (strcmp(version, SCST_INTERFACE_VERSION) != 0) {
++ PRINT_ERROR("Incorrect version of virtual dev handler %s",
++ dev_type->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_dev_handler_check(dev_type);
++ if (res != 0)
++ goto out;
++
++ mutex_lock(&scst_mutex);
++ list_add_tail(&dev_type->dev_type_list_entry, &scst_virtual_dev_type_list);
++ mutex_unlock(&scst_mutex);
++
++ res = scst_devt_sysfs_create(dev_type);
++ if (res < 0)
++ goto out;
++
++ if (dev_type->type != -1) {
++ PRINT_INFO("Virtual device handler %s for type %d "
++ "registered successfully", dev_type->name,
++ dev_type->type);
++ } else {
++ PRINT_INFO("Virtual device handler \"%s\" registered "
++ "successfully", dev_type->name);
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(__scst_register_virtual_dev_driver);
++
++/**
++ * scst_unregister_virtual_dev_driver() - unregister virtual dev driver
++ */
++void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ /* Disable sysfs mgmt calls (e.g. addition of new devices) */
++ list_del(&dev_type->dev_type_list_entry);
++
++ /* Wait for outstanding sysfs mgmt calls completed */
++ while (dev_type->devt_active_sysfs_works_count > 0) {
++ mutex_unlock(&scst_mutex);
++ msleep(100);
++ mutex_lock(&scst_mutex);
++ }
++
++ mutex_unlock(&scst_mutex);
++
++ scst_devt_sysfs_del(dev_type);
++
++ PRINT_INFO("Device handler \"%s\" unloaded", dev_type->name);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_unregister_virtual_dev_driver);
++
++/* scst_mutex supposed to be held */
++int scst_add_threads(struct scst_cmd_threads *cmd_threads,
++ struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num)
++{
++ int res = 0, i;
++ struct scst_cmd_thread_t *thr;
++ int n = 0, tgt_dev_num = 0;
++
++ TRACE_ENTRY();
++
++ if (num == 0) {
++ res = 0;
++ goto out;
++ }
++
++ list_for_each_entry(thr, &cmd_threads->threads_list, thread_list_entry) {
++ n++;
++ }
++
++ TRACE_DBG("cmd_threads %p, dev %p, tgt_dev %p, num %d, n %d",
++ cmd_threads, dev, tgt_dev, num, n);
++
++ if (tgt_dev != NULL) {
++ struct scst_tgt_dev *t;
++ list_for_each_entry(t, &tgt_dev->dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if (t == tgt_dev)
++ break;
++ tgt_dev_num++;
++ }
++ }
++
++ for (i = 0; i < num; i++) {
++ thr = kmalloc(sizeof(*thr), GFP_KERNEL);
++ if (!thr) {
++ res = -ENOMEM;
++ PRINT_ERROR("Fail to allocate thr %d", res);
++ goto out_wait;
++ }
++
++ if (dev != NULL) {
++ char nm[14]; /* to limit the name's len */
++ strlcpy(nm, dev->virt_name, ARRAY_SIZE(nm));
++ thr->cmd_thread = kthread_create(scst_cmd_thread,
++ cmd_threads, "%s%d", nm, n++);
++ } else if (tgt_dev != NULL) {
++ char nm[11]; /* to limit the name's len */
++ strlcpy(nm, tgt_dev->dev->virt_name, ARRAY_SIZE(nm));
++ thr->cmd_thread = kthread_create(scst_cmd_thread,
++ cmd_threads, "%s%d_%d", nm, tgt_dev_num, n++);
++ } else
++ thr->cmd_thread = kthread_create(scst_cmd_thread,
++ cmd_threads, "scstd%d", n++);
++
++ if (IS_ERR(thr->cmd_thread)) {
++ res = PTR_ERR(thr->cmd_thread);
++ PRINT_ERROR("kthread_create() failed: %d", res);
++ kfree(thr);
++ goto out_wait;
++ }
++
++ list_add(&thr->thread_list_entry, &cmd_threads->threads_list);
++ cmd_threads->nr_threads++;
++
++ TRACE_DBG("Added thr %p to threads list (nr_threads %d, n %d)",
++ thr, cmd_threads->nr_threads, n);
++
++ wake_up_process(thr->cmd_thread);
++ }
++
++out_wait:
++ if (i > 0 && cmd_threads != &scst_main_cmd_threads) {
++ /*
++ * Wait for io_context gets initialized to avoid possible races
++ * for it from the sharing it tgt_devs.
++ */
++ while (!*(volatile bool*)&cmd_threads->io_context_ready) {
++ TRACE_DBG("Waiting for io_context for cmd_threads %p "
++ "initialized", cmd_threads);
++ msleep(50);
++ }
++ }
++
++ if (res != 0)
++ scst_del_threads(cmd_threads, i);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* scst_mutex supposed to be held */
++void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num)
++{
++ struct scst_cmd_thread_t *ct, *tmp;
++
++ TRACE_ENTRY();
++
++ if (num == 0)
++ goto out;
++
++ list_for_each_entry_safe_reverse(ct, tmp, &cmd_threads->threads_list,
++ thread_list_entry) {
++ int rc;
++ struct scst_device *dev;
++
++ rc = kthread_stop(ct->cmd_thread);
++ if (rc != 0 && rc != -EINTR)
++ TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
++
++ list_del(&ct->thread_list_entry);
++
++ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ scst_del_thr_data(tgt_dev, ct->cmd_thread);
++ }
++ }
++
++ kfree(ct);
++
++ cmd_threads->nr_threads--;
++
++ --num;
++ if (num == 0)
++ break;
++ }
++
++ EXTRACHECKS_BUG_ON((cmd_threads->nr_threads == 0) &&
++ (cmd_threads->io_context != NULL));
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++void scst_stop_dev_threads(struct scst_device *dev)
++{
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ scst_tgt_dev_stop_threads(tgt_dev);
++ }
++
++ if ((dev->threads_num > 0) &&
++ (dev->threads_pool_type == SCST_THREADS_POOL_SHARED))
++ scst_del_threads(&dev->dev_cmd_threads, -1);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++int scst_create_dev_threads(struct scst_device *dev)
++{
++ int res = 0;
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ res = scst_tgt_dev_setup_threads(tgt_dev);
++ if (res != 0)
++ goto out_err;
++ }
++
++ if ((dev->threads_num > 0) &&
++ (dev->threads_pool_type == SCST_THREADS_POOL_SHARED)) {
++ res = scst_add_threads(&dev->dev_cmd_threads, dev, NULL,
++ dev->threads_num);
++ if (res != 0)
++ goto out_err;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_err:
++ scst_stop_dev_threads(dev);
++ goto out;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++int scst_assign_dev_handler(struct scst_device *dev,
++ struct scst_dev_type *handler)
++{
++ int res = 0;
++ struct scst_tgt_dev *tgt_dev;
++ LIST_HEAD(attached_tgt_devs);
++
++ TRACE_ENTRY();
++
++ BUG_ON(handler == NULL);
++
++ if (dev->handler == handler)
++ goto out;
++
++ if (dev->handler == NULL)
++ goto assign;
++
++ if (dev->handler->detach_tgt) {
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ TRACE_DBG("Calling dev handler's detach_tgt(%p)",
++ tgt_dev);
++ dev->handler->detach_tgt(tgt_dev);
++ TRACE_DBG("%s", "Dev handler's detach_tgt() returned");
++ }
++ }
++
++ /*
++ * devt_dev sysfs must be created AFTER attach() and deleted BEFORE
++ * detach() to avoid calls from sysfs for not yet ready or already dead
++ * objects.
++ */
++ scst_devt_dev_sysfs_del(dev);
++
++ if (dev->handler->detach) {
++ TRACE_DBG("%s", "Calling dev handler's detach()");
++ dev->handler->detach(dev);
++ TRACE_DBG("%s", "Old handler's detach() returned");
++ }
++
++ scst_stop_dev_threads(dev);
++
++assign:
++ dev->handler = handler;
++
++ if (handler == NULL)
++ goto out;
++
++ dev->threads_num = handler->threads_num;
++ dev->threads_pool_type = handler->threads_pool_type;
++
++ if (handler->attach) {
++ TRACE_DBG("Calling new dev handler's attach(%p)", dev);
++ res = handler->attach(dev);
++ TRACE_DBG("New dev handler's attach() returned %d", res);
++ if (res != 0) {
++ PRINT_ERROR("New device handler's %s attach() "
++ "failed: %d", handler->name, res);
++ goto out;
++ }
++ }
++
++ res = scst_devt_dev_sysfs_create(dev);
++ if (res != 0)
++ goto out_detach;
++
++ if (handler->attach_tgt) {
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ TRACE_DBG("Calling dev handler's attach_tgt(%p)",
++ tgt_dev);
++ res = handler->attach_tgt(tgt_dev);
++ TRACE_DBG("%s", "Dev handler's attach_tgt() returned");
++ if (res != 0) {
++ PRINT_ERROR("Device handler's %s attach_tgt() "
++ "failed: %d", handler->name, res);
++ goto out_err_remove_sysfs;
++ }
++ list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
++ &attached_tgt_devs);
++ }
++ }
++
++ res = scst_create_dev_threads(dev);
++ if (res != 0)
++ goto out_err_detach_tgt;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_err_detach_tgt:
++ if (handler && handler->detach_tgt) {
++ list_for_each_entry(tgt_dev, &attached_tgt_devs,
++ extra_tgt_dev_list_entry) {
++ TRACE_DBG("Calling handler's detach_tgt(%p)",
++ tgt_dev);
++ handler->detach_tgt(tgt_dev);
++ TRACE_DBG("%s", "Handler's detach_tgt() returned");
++ }
++ }
++
++out_err_remove_sysfs:
++ scst_devt_dev_sysfs_del(dev);
++
++out_detach:
++ if (handler && handler->detach) {
++ TRACE_DBG("%s", "Calling handler's detach()");
++ handler->detach(dev);
++ TRACE_DBG("%s", "Handler's detach() returned");
++ }
++
++ dev->handler = &scst_null_devtype;
++ dev->threads_num = scst_null_devtype.threads_num;
++ dev->threads_pool_type = scst_null_devtype.threads_pool_type;
++ goto out;
++}
++
++/**
++ * scst_init_threads() - initialize SCST processing threads pool
++ *
++ * Initializes scst_cmd_threads structure
++ */
++void scst_init_threads(struct scst_cmd_threads *cmd_threads)
++{
++ TRACE_ENTRY();
++
++ spin_lock_init(&cmd_threads->cmd_list_lock);
++ INIT_LIST_HEAD(&cmd_threads->active_cmd_list);
++ init_waitqueue_head(&cmd_threads->cmd_list_waitQ);
++ INIT_LIST_HEAD(&cmd_threads->threads_list);
++ mutex_init(&cmd_threads->io_context_mutex);
++
++ mutex_lock(&scst_suspend_mutex);
++ list_add_tail(&cmd_threads->lists_list_entry,
++ &scst_cmd_threads_list);
++ mutex_unlock(&scst_suspend_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_init_threads);
++
++/**
++ * scst_deinit_threads() - deinitialize SCST processing threads pool
++ *
++ * Deinitializes scst_cmd_threads structure
++ */
++void scst_deinit_threads(struct scst_cmd_threads *cmd_threads)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_suspend_mutex);
++ list_del(&cmd_threads->lists_list_entry);
++ mutex_unlock(&scst_suspend_mutex);
++
++ BUG_ON(cmd_threads->io_context);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_deinit_threads);
++
++static void scst_stop_global_threads(void)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ scst_del_threads(&scst_main_cmd_threads, -1);
++
++ if (scst_mgmt_cmd_thread)
++ kthread_stop(scst_mgmt_cmd_thread);
++ if (scst_mgmt_thread)
++ kthread_stop(scst_mgmt_thread);
++ if (scst_init_cmd_thread)
++ kthread_stop(scst_init_cmd_thread);
++
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* It does NOT stop ran threads on error! */
++static int scst_start_global_threads(int num)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ res = scst_add_threads(&scst_main_cmd_threads, NULL, NULL, num);
++ if (res < 0)
++ goto out_unlock;
++
++ scst_init_cmd_thread = kthread_run(scst_init_thread,
++ NULL, "scst_initd");
++ if (IS_ERR(scst_init_cmd_thread)) {
++ res = PTR_ERR(scst_init_cmd_thread);
++ PRINT_ERROR("kthread_create() for init cmd failed: %d", res);
++ scst_init_cmd_thread = NULL;
++ goto out_unlock;
++ }
++
++ scst_mgmt_cmd_thread = kthread_run(scst_tm_thread,
++ NULL, "scsi_tm");
++ if (IS_ERR(scst_mgmt_cmd_thread)) {
++ res = PTR_ERR(scst_mgmt_cmd_thread);
++ PRINT_ERROR("kthread_create() for TM failed: %d", res);
++ scst_mgmt_cmd_thread = NULL;
++ goto out_unlock;
++ }
++
++ scst_mgmt_thread = kthread_run(scst_global_mgmt_thread,
++ NULL, "scst_mgmtd");
++ if (IS_ERR(scst_mgmt_thread)) {
++ res = PTR_ERR(scst_mgmt_thread);
++ PRINT_ERROR("kthread_create() for mgmt failed: %d", res);
++ scst_mgmt_thread = NULL;
++ goto out_unlock;
++ }
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * scst_get() - increase global SCST ref counter
++ *
++ * Increases global SCST ref counter that prevents from entering into suspended
++ * activities stage, so protects from any global management operations.
++ */
++void scst_get(void)
++{
++ __scst_get();
++}
++EXPORT_SYMBOL(scst_get);
++
++/**
++ * scst_put() - decrease global SCST ref counter
++ *
++ * Decreses global SCST ref counter that prevents from entering into suspended
++ * activities stage, so protects from any global management operations. On
++ * zero, if suspending activities is waiting, they will be suspended.
++ */
++void scst_put(void)
++{
++ __scst_put();
++}
++EXPORT_SYMBOL(scst_put);
++
++/**
++ * scst_get_setup_id() - return SCST setup ID
++ *
++ * Returns SCST setup ID. This ID can be used for multiple
++ * setups with the same configuration.
++ */
++unsigned int scst_get_setup_id(void)
++{
++ return scst_setup_id;
++}
++EXPORT_SYMBOL_GPL(scst_get_setup_id);
++
++static int scst_add(struct device *cdev, struct class_interface *intf)
++{
++ struct scsi_device *scsidp;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ scsidp = to_scsi_device(cdev->parent);
++
++ if ((scsidp->host->hostt->name == NULL) ||
++ (strcmp(scsidp->host->hostt->name, SCST_LOCAL_NAME) != 0))
++ res = scst_register_device(scsidp);
++
++ TRACE_EXIT();
++ return res;
++}
++
++static void scst_remove(struct device *cdev, struct class_interface *intf)
++{
++ struct scsi_device *scsidp;
++
++ TRACE_ENTRY();
++
++ scsidp = to_scsi_device(cdev->parent);
++
++ if ((scsidp->host->hostt->name == NULL) ||
++ (strcmp(scsidp->host->hostt->name, SCST_LOCAL_NAME) != 0))
++ scst_unregister_device(scsidp);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct class_interface scst_interface = {
++ .add_dev = scst_add,
++ .remove_dev = scst_remove,
++};
++
++static void __init scst_print_config(void)
++{
++ char buf[128];
++ int i, j;
++
++ i = snprintf(buf, sizeof(buf), "Enabled features: ");
++ j = i;
++
++#ifdef CONFIG_SCST_STRICT_SERIALIZING
++ i += snprintf(&buf[i], sizeof(buf) - i, "STRICT_SERIALIZING");
++#endif
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sEXTRACHECKS",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_TRACING
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sTRACING",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_TM
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_TM",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_RETRY
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_RETRY",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_OOM
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_OOM",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_SN
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sDEBUG_SN",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sUSE_EXPECTED_VALUES",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ i += snprintf(&buf[i], sizeof(buf) - i,
++ "%sTEST_IO_IN_SIRQ",
++ (j == i) ? "" : ", ");
++#endif
++
++#ifdef CONFIG_SCST_STRICT_SECURITY
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sSTRICT_SECURITY",
++ (j == i) ? "" : ", ");
++#endif
++
++ if (j != i)
++ PRINT_INFO("%s", buf);
++}
++
++static int __init init_scst(void)
++{
++ int res, i;
++ int scst_num_cpus;
++
++ TRACE_ENTRY();
++
++ {
++ struct scsi_sense_hdr *shdr;
++ BUILD_BUG_ON(SCST_SENSE_BUFFERSIZE < sizeof(*shdr));
++ }
++ {
++ struct scst_tgt_dev *t;
++ struct scst_cmd *c;
++ BUILD_BUG_ON(sizeof(t->curr_sn) != sizeof(t->expected_sn));
++ BUILD_BUG_ON(sizeof(c->sn) != sizeof(t->expected_sn));
++ }
++
++ mutex_init(&scst_mutex);
++ mutex_init(&scst_mutex2);
++ INIT_LIST_HEAD(&scst_template_list);
++ INIT_LIST_HEAD(&scst_dev_list);
++ INIT_LIST_HEAD(&scst_dev_type_list);
++ INIT_LIST_HEAD(&scst_virtual_dev_type_list);
++ spin_lock_init(&scst_main_lock);
++ spin_lock_init(&scst_init_lock);
++ init_waitqueue_head(&scst_init_cmd_list_waitQ);
++ INIT_LIST_HEAD(&scst_init_cmd_list);
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ scst_trace_flag = SCST_DEFAULT_LOG_FLAGS;
++#endif
++ atomic_set(&scst_cmd_count, 0);
++ spin_lock_init(&scst_mcmd_lock);
++ INIT_LIST_HEAD(&scst_active_mgmt_cmd_list);
++ INIT_LIST_HEAD(&scst_delayed_mgmt_cmd_list);
++ init_waitqueue_head(&scst_mgmt_cmd_list_waitQ);
++ init_waitqueue_head(&scst_mgmt_waitQ);
++ spin_lock_init(&scst_mgmt_lock);
++ INIT_LIST_HEAD(&scst_sess_init_list);
++ INIT_LIST_HEAD(&scst_sess_shut_list);
++ init_waitqueue_head(&scst_dev_cmd_waitQ);
++ mutex_init(&scst_suspend_mutex);
++ INIT_LIST_HEAD(&scst_cmd_threads_list);
++
++ scst_init_threads(&scst_main_cmd_threads);
++
++ res = scst_lib_init();
++ if (res != 0)
++ goto out_deinit_threads;
++
++ scst_num_cpus = num_online_cpus();
++
++ /* ToDo: register_cpu_notifier() */
++
++ if (scst_threads == 0)
++ scst_threads = scst_num_cpus;
++
++ if (scst_threads < 1) {
++ PRINT_ERROR("%s", "scst_threads can not be less than 1");
++ scst_threads = scst_num_cpus;
++ }
++
++#define INIT_CACHEP(p, s, o) do { \
++ p = KMEM_CACHE(s, SCST_SLAB_FLAGS); \
++ TRACE_MEM("Slab create: %s at %p size %zd", #s, p, \
++ sizeof(struct s)); \
++ if (p == NULL) { \
++ res = -ENOMEM; \
++ goto o; \
++ } \
++ } while (0)
++
++ INIT_CACHEP(scst_mgmt_cachep, scst_mgmt_cmd, out_lib_exit);
++ INIT_CACHEP(scst_mgmt_stub_cachep, scst_mgmt_cmd_stub,
++ out_destroy_mgmt_cache);
++ INIT_CACHEP(scst_ua_cachep, scst_tgt_dev_UA,
++ out_destroy_mgmt_stub_cache);
++ {
++ struct scst_sense { uint8_t s[SCST_SENSE_BUFFERSIZE]; };
++ INIT_CACHEP(scst_sense_cachep, scst_sense,
++ out_destroy_ua_cache);
++ }
++ INIT_CACHEP(scst_aen_cachep, scst_aen, out_destroy_sense_cache);
++ INIT_CACHEP(scst_cmd_cachep, scst_cmd, out_destroy_aen_cache);
++ INIT_CACHEP(scst_sess_cachep, scst_session, out_destroy_cmd_cache);
++ INIT_CACHEP(scst_tgtd_cachep, scst_tgt_dev, out_destroy_sess_cache);
++ INIT_CACHEP(scst_acgd_cachep, scst_acg_dev, out_destroy_tgt_cache);
++
++ scst_mgmt_mempool = mempool_create(64, mempool_alloc_slab,
++ mempool_free_slab, scst_mgmt_cachep);
++ if (scst_mgmt_mempool == NULL) {
++ res = -ENOMEM;
++ goto out_destroy_acg_cache;
++ }
++
++ /*
++ * All mgmt stubs, UAs and sense buffers are bursty and loosing them
++ * may have fatal consequences, so let's have big pools for them.
++ */
++
++ scst_mgmt_stub_mempool = mempool_create(1024, mempool_alloc_slab,
++ mempool_free_slab, scst_mgmt_stub_cachep);
++ if (scst_mgmt_stub_mempool == NULL) {
++ res = -ENOMEM;
++ goto out_destroy_mgmt_mempool;
++ }
++
++ scst_ua_mempool = mempool_create(512, mempool_alloc_slab,
++ mempool_free_slab, scst_ua_cachep);
++ if (scst_ua_mempool == NULL) {
++ res = -ENOMEM;
++ goto out_destroy_mgmt_stub_mempool;
++ }
++
++ scst_sense_mempool = mempool_create(1024, mempool_alloc_slab,
++ mempool_free_slab, scst_sense_cachep);
++ if (scst_sense_mempool == NULL) {
++ res = -ENOMEM;
++ goto out_destroy_ua_mempool;
++ }
++
++ scst_aen_mempool = mempool_create(100, mempool_alloc_slab,
++ mempool_free_slab, scst_aen_cachep);
++ if (scst_aen_mempool == NULL) {
++ res = -ENOMEM;
++ goto out_destroy_sense_mempool;
++ }
++
++ res = scst_sysfs_init();
++ if (res != 0)
++ goto out_destroy_aen_mempool;
++
++ if (scst_max_cmd_mem == 0) {
++ struct sysinfo si;
++ si_meminfo(&si);
++#if BITS_PER_LONG == 32
++ scst_max_cmd_mem = min(
++ (((uint64_t)(si.totalram - si.totalhigh) << PAGE_SHIFT)
++ >> 20) >> 2, (uint64_t)1 << 30);
++#else
++ scst_max_cmd_mem = (((si.totalram - si.totalhigh) << PAGE_SHIFT)
++ >> 20) >> 2;
++#endif
++ }
++
++ if (scst_max_dev_cmd_mem != 0) {
++ if (scst_max_dev_cmd_mem > scst_max_cmd_mem) {
++ PRINT_ERROR("scst_max_dev_cmd_mem (%d) > "
++ "scst_max_cmd_mem (%d)",
++ scst_max_dev_cmd_mem,
++ scst_max_cmd_mem);
++ scst_max_dev_cmd_mem = scst_max_cmd_mem;
++ }
++ } else
++ scst_max_dev_cmd_mem = scst_max_cmd_mem * 2 / 5;
++
++ res = scst_sgv_pools_init(
++ ((uint64_t)scst_max_cmd_mem << 10) >> (PAGE_SHIFT - 10), 0);
++ if (res != 0)
++ goto out_sysfs_cleanup;
++
++ res = scsi_register_interface(&scst_interface);
++ if (res != 0)
++ goto out_destroy_sgv_pool;
++
++ for (i = 0; i < (int)ARRAY_SIZE(scst_tasklets); i++) {
++ spin_lock_init(&scst_tasklets[i].tasklet_lock);
++ INIT_LIST_HEAD(&scst_tasklets[i].tasklet_cmd_list);
++ tasklet_init(&scst_tasklets[i].tasklet,
++ (void *)scst_cmd_tasklet,
++ (unsigned long)&scst_tasklets[i]);
++ }
++
++ TRACE_DBG("%d CPUs found, starting %d threads", scst_num_cpus,
++ scst_threads);
++
++ res = scst_start_global_threads(scst_threads);
++ if (res < 0)
++ goto out_thread_free;
++
++ PRINT_INFO("SCST version %s loaded successfully (max mem for "
++ "commands %dMB, per device %dMB)", SCST_VERSION_STRING,
++ scst_max_cmd_mem, scst_max_dev_cmd_mem);
++
++ scst_print_config();
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_thread_free:
++ scst_stop_global_threads();
++
++ scsi_unregister_interface(&scst_interface);
++
++out_destroy_sgv_pool:
++ scst_sgv_pools_deinit();
++
++out_sysfs_cleanup:
++ scst_sysfs_cleanup();
++
++out_destroy_aen_mempool:
++ mempool_destroy(scst_aen_mempool);
++
++out_destroy_sense_mempool:
++ mempool_destroy(scst_sense_mempool);
++
++out_destroy_ua_mempool:
++ mempool_destroy(scst_ua_mempool);
++
++out_destroy_mgmt_stub_mempool:
++ mempool_destroy(scst_mgmt_stub_mempool);
++
++out_destroy_mgmt_mempool:
++ mempool_destroy(scst_mgmt_mempool);
++
++out_destroy_acg_cache:
++ kmem_cache_destroy(scst_acgd_cachep);
++
++out_destroy_tgt_cache:
++ kmem_cache_destroy(scst_tgtd_cachep);
++
++out_destroy_sess_cache:
++ kmem_cache_destroy(scst_sess_cachep);
++
++out_destroy_cmd_cache:
++ kmem_cache_destroy(scst_cmd_cachep);
++
++out_destroy_aen_cache:
++ kmem_cache_destroy(scst_aen_cachep);
++
++out_destroy_sense_cache:
++ kmem_cache_destroy(scst_sense_cachep);
++
++out_destroy_ua_cache:
++ kmem_cache_destroy(scst_ua_cachep);
++
++out_destroy_mgmt_stub_cache:
++ kmem_cache_destroy(scst_mgmt_stub_cachep);
++
++out_destroy_mgmt_cache:
++ kmem_cache_destroy(scst_mgmt_cachep);
++
++out_lib_exit:
++ scst_lib_exit();
++
++out_deinit_threads:
++ scst_deinit_threads(&scst_main_cmd_threads);
++ goto out;
++}
++
++static void __exit exit_scst(void)
++{
++ TRACE_ENTRY();
++
++ /* ToDo: unregister_cpu_notifier() */
++
++ scst_stop_global_threads();
++
++ scst_deinit_threads(&scst_main_cmd_threads);
++
++ scsi_unregister_interface(&scst_interface);
++
++ scst_sgv_pools_deinit();
++
++ scst_sysfs_cleanup();
++
++#define DEINIT_CACHEP(p) do { \
++ kmem_cache_destroy(p); \
++ p = NULL; \
++ } while (0)
++
++ mempool_destroy(scst_mgmt_mempool);
++ mempool_destroy(scst_mgmt_stub_mempool);
++ mempool_destroy(scst_ua_mempool);
++ mempool_destroy(scst_sense_mempool);
++ mempool_destroy(scst_aen_mempool);
++
++ DEINIT_CACHEP(scst_mgmt_cachep);
++ DEINIT_CACHEP(scst_mgmt_stub_cachep);
++ DEINIT_CACHEP(scst_ua_cachep);
++ DEINIT_CACHEP(scst_sense_cachep);
++ DEINIT_CACHEP(scst_aen_cachep);
++ DEINIT_CACHEP(scst_cmd_cachep);
++ DEINIT_CACHEP(scst_sess_cachep);
++ DEINIT_CACHEP(scst_tgtd_cachep);
++ DEINIT_CACHEP(scst_acgd_cachep);
++
++ scst_lib_exit();
++
++ PRINT_INFO("%s", "SCST unloaded");
++
++ TRACE_EXIT();
++ return;
++}
++
++module_init(init_scst);
++module_exit(exit_scst);
++
++MODULE_AUTHOR("Vladislav Bolkhovitin");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCSI target core");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_module.c linux-2.6.36/drivers/scst/scst_module.c
+--- orig/linux-2.6.36/drivers/scst/scst_module.c
++++ linux-2.6.36/drivers/scst/scst_module.c
+@@ -0,0 +1,70 @@
++/*
++ * scst_module.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * Support for loading target modules. The usage is similar to scsi_module.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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <scst.h>
++
++static int __init init_this_scst_driver(void)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ res = scst_register_target_template(&driver_target_template);
++ TRACE_DBG("scst_register_target_template() returned %d", res);
++ if (res < 0)
++ goto out;
++
++#ifdef SCST_REGISTER_INITIATOR_DRIVER
++ driver_template.module = THIS_MODULE;
++ scsi_register_module(MODULE_SCSI_HA, &driver_template);
++ TRACE_DBG("driver_template.present=%d",
++ driver_template.present);
++ if (driver_template.present == 0) {
++ res = -ENODEV;
++ MOD_DEC_USE_COUNT;
++ goto out;
++ }
++#endif
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void __exit exit_this_scst_driver(void)
++{
++ TRACE_ENTRY();
++
++#ifdef SCST_REGISTER_INITIATOR_DRIVER
++ scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
++#endif
++
++ scst_unregister_target_template(&driver_target_template);
++
++ TRACE_EXIT();
++ return;
++}
++
++module_init(init_this_scst_driver);
++module_exit(exit_this_scst_driver);
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_pres.c linux-2.6.36/drivers/scst/scst_pres.c
+--- orig/linux-2.6.36/drivers/scst/scst_pres.c
++++ linux-2.6.36/drivers/scst/scst_pres.c
+@@ -0,0 +1,2648 @@
++/*
++ * scst_pres.c
++ *
++ * Copyright (C) 2009 - 2010 Alexey Obitotskiy <alexeyo1@open-e.com>
++ * Copyright (C) 2009 - 2010 Open-E, Inc.
++ * Copyright (C) 2009 - 2011 Vladislav Bolkhovitin <vst@vlnb.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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/smp_lock.h>
++#include <linux/unistd.h>
++#include <linux/string.h>
++#include <linux/kthread.h>
++#include <linux/delay.h>
++#include <linux/time.h>
++#include <linux/ctype.h>
++#include <asm/byteorder.h>
++#include <linux/syscalls.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/fcntl.h>
++#include <linux/uaccess.h>
++#include <linux/namei.h>
++#include <linux/version.h>
++#include <linux/vmalloc.h>
++#include <asm/unaligned.h>
++
++#include <scst/scst.h>
++#include <scst/scst_const.h>
++#include "scst_priv.h"
++#include "scst_pres.h"
++
++#define SCST_PR_ROOT_ENTRY "pr"
++#define SCST_PR_FILE_SIGN 0xBBEEEEAAEEBBDD77LLU
++#define SCST_PR_FILE_VERSION 1LLU
++
++#define FILE_BUFFER_SIZE 512
++
++#ifndef isblank
++#define isblank(c) ((c) == ' ' || (c) == '\t')
++#endif
++
++static inline int tid_size(const uint8_t *tid)
++{
++ BUG_ON(tid == NULL);
++
++ if ((tid[0] & 0x0f) == SCSI_TRANSPORTID_PROTOCOLID_ISCSI)
++ return be16_to_cpu(get_unaligned((__be16 *)&tid[2])) + 4;
++ else
++ return TID_COMMON_SIZE;
++}
++
++/* Secures tid by setting 0 in the last byte of NULL-terminated tid's */
++static inline void tid_secure(uint8_t *tid)
++{
++ if ((tid[0] & 0x0f) == SCSI_TRANSPORTID_PROTOCOLID_ISCSI) {
++ int size = tid_size(tid);
++ tid[size - 1] = '\0';
++ }
++
++ return;
++}
++
++/* Returns false if tid's are not equal, true otherwise */
++static bool tid_equal(const uint8_t *tid_a, const uint8_t *tid_b)
++{
++ int len;
++
++ if (tid_a == NULL || tid_b == NULL)
++ return false;
++
++ if ((tid_a[0] & 0x0f) != (tid_b[0] & 0x0f)) {
++ TRACE_DBG("%s", "Different protocol IDs");
++ return false;
++ }
++
++ if ((tid_a[0] & 0x0f) == SCSI_TRANSPORTID_PROTOCOLID_ISCSI) {
++ const uint8_t tid_a_fmt = tid_a[0] & 0xc0;
++ const uint8_t tid_b_fmt = tid_b[0] & 0xc0;
++ int tid_a_len, tid_a_max = tid_size(tid_a) - 4;
++ int tid_b_len, tid_b_max = tid_size(tid_b) - 4;
++ int i;
++
++ tid_a += 4;
++ tid_b += 4;
++
++ if (tid_a_fmt == 0x00)
++ tid_a_len = strnlen(tid_a, tid_a_max);
++ else if (tid_a_fmt == 0x40) {
++ if (tid_a_fmt != tid_b_fmt) {
++ uint8_t *p = strnchr(tid_a, tid_a_max, ',');
++ if (p == NULL)
++ goto out_error;
++ tid_a_len = p - tid_a;
++
++ BUG_ON(tid_a_len > tid_a_max);
++ BUG_ON(tid_a_len < 0);
++ } else
++ tid_a_len = strnlen(tid_a, tid_a_max);
++ } else
++ goto out_error;
++
++ if (tid_b_fmt == 0x00)
++ tid_b_len = strnlen(tid_b, tid_b_max);
++ else if (tid_b_fmt == 0x40) {
++ if (tid_a_fmt != tid_b_fmt) {
++ uint8_t *p = strnchr(tid_b, tid_b_max, ',');
++ if (p == NULL)
++ goto out_error;
++ tid_b_len = p - tid_b;
++
++ BUG_ON(tid_b_len > tid_b_max);
++ BUG_ON(tid_b_len < 0);
++ } else
++ tid_b_len = strnlen(tid_b, tid_b_max);
++ } else
++ goto out_error;
++
++ if (tid_a_len != tid_b_len)
++ return false;
++
++ len = tid_a_len;
++
++ /* ISCSI names are case insensitive */
++ for (i = 0; i < len; i++)
++ if (tolower(tid_a[i]) != tolower(tid_b[i]))
++ return false;
++ return true;
++ } else
++ len = TID_COMMON_SIZE;
++
++ return (memcmp(tid_a, tid_b, len) == 0);
++
++out_error:
++ PRINT_ERROR("%s", "Invalid initiator port transport id");
++ return false;
++}
++
++/* Must be called under dev_pr_mutex */
++static inline void scst_pr_set_holder(struct scst_device *dev,
++ struct scst_dev_registrant *holder, uint8_t scope, uint8_t type)
++{
++ dev->pr_is_set = 1;
++ dev->pr_scope = scope;
++ dev->pr_type = type;
++ if (dev->pr_type != TYPE_EXCLUSIVE_ACCESS_ALL_REG &&
++ dev->pr_type != TYPE_WRITE_EXCLUSIVE_ALL_REG)
++ dev->pr_holder = holder;
++}
++
++/* Must be called under dev_pr_mutex */
++static bool scst_pr_is_holder(struct scst_device *dev,
++ struct scst_dev_registrant *reg)
++{
++ bool res = false;
++
++ TRACE_ENTRY();
++
++ if (!dev->pr_is_set)
++ goto out;
++
++ if (dev->pr_type == TYPE_EXCLUSIVE_ACCESS_ALL_REG ||
++ dev->pr_type == TYPE_WRITE_EXCLUSIVE_ALL_REG) {
++ res = (reg != NULL);
++ } else
++ res = (dev->pr_holder == reg);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++/* Must be called under dev_pr_mutex */
++void scst_pr_dump_prs(struct scst_device *dev, bool force)
++{
++ if (!force) {
++#if defined(CONFIG_SCST_DEBUG)
++ if ((trace_flag & TRACE_PRES) == 0)
++#endif
++ goto out;
++ }
++
++ PRINT_INFO("Persistent reservations for device %s:", dev->virt_name);
++
++ if (list_empty(&dev->dev_registrants_list))
++ PRINT_INFO("%s", " No registrants");
++ else {
++ struct scst_dev_registrant *reg;
++ int i = 0;
++ list_for_each_entry(reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ PRINT_INFO(" [%d] registrant %s/%d, key %016llx "
++ "(reg %p, tgt_dev %p)", i++,
++ debug_transport_id_to_initiator_name(
++ reg->transport_id),
++ reg->rel_tgt_id, reg->key, reg, reg->tgt_dev);
++ }
++ }
++
++ if (dev->pr_is_set) {
++ struct scst_dev_registrant *holder = dev->pr_holder;
++ if (holder != NULL)
++ PRINT_INFO("Reservation holder is %s/%d (key %016llx, "
++ "scope %x, type %x, reg %p, tgt_dev %p)",
++ debug_transport_id_to_initiator_name(
++ holder->transport_id),
++ holder->rel_tgt_id, holder->key, dev->pr_scope,
++ dev->pr_type, holder, holder->tgt_dev);
++ else
++ PRINT_INFO("All registrants are reservation holders "
++ "(scope %x, type %x)", dev->pr_scope,
++ dev->pr_type);
++ } else
++ PRINT_INFO("%s", "Not reserved");
++
++out:
++ return;
++}
++
++#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
++
++/* dev_pr_mutex must be locked */
++static void scst_pr_find_registrants_list_all(struct scst_device *dev,
++ struct scst_dev_registrant *exclude_reg, struct list_head *list)
++{
++ struct scst_dev_registrant *reg;
++
++ TRACE_ENTRY();
++
++ TRACE_PR("Finding all registered records for device '%s' "
++ "with exclude reg key %016llx",
++ dev->virt_name, exclude_reg->key);
++
++ list_for_each_entry(reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ if (reg == exclude_reg)
++ continue;
++ TRACE_PR("Adding registrant %s/%d (%p) to find list (key %016llx)",
++ debug_transport_id_to_initiator_name(reg->transport_id),
++ reg->rel_tgt_id, reg, reg->key);
++ list_add_tail(&reg->aux_list_entry, list);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* dev_pr_mutex must be locked */
++static void scst_pr_find_registrants_list_key(struct scst_device *dev,
++ __be64 key, struct list_head *list)
++{
++ struct scst_dev_registrant *reg;
++
++ TRACE_ENTRY();
++
++ TRACE_PR("Finding registrants for device '%s' with key %016llx",
++ dev->virt_name, key);
++
++ list_for_each_entry(reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ if (reg->key == key) {
++ TRACE_PR("Adding registrant %s/%d (%p) to the find "
++ "list (key %016llx)",
++ debug_transport_id_to_initiator_name(
++ reg->transport_id),
++ reg->rel_tgt_id, reg->tgt_dev, key);
++ list_add_tail(&reg->aux_list_entry, list);
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* dev_pr_mutex must be locked */
++static struct scst_dev_registrant *scst_pr_find_reg(
++ struct scst_device *dev, const uint8_t *transport_id,
++ const uint16_t rel_tgt_id)
++{
++ struct scst_dev_registrant *reg, *res = NULL;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ if ((reg->rel_tgt_id == rel_tgt_id) &&
++ tid_equal(reg->transport_id, transport_id)) {
++ res = reg;
++ break;
++ }
++ }
++
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/* Must be called under dev_pr_mutex */
++static void scst_pr_clear_reservation(struct scst_device *dev)
++{
++ TRACE_ENTRY();
++
++ WARN_ON(!dev->pr_is_set);
++
++ dev->pr_is_set = 0;
++ dev->pr_scope = SCOPE_LU;
++ dev->pr_type = TYPE_UNSPECIFIED;
++
++ dev->pr_holder = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called under dev_pr_mutex */
++static void scst_pr_clear_holder(struct scst_device *dev)
++{
++ TRACE_ENTRY();
++
++ WARN_ON(!dev->pr_is_set);
++
++ if (dev->pr_type == TYPE_WRITE_EXCLUSIVE_ALL_REG ||
++ dev->pr_type == TYPE_EXCLUSIVE_ACCESS_ALL_REG) {
++ if (list_empty(&dev->dev_registrants_list))
++ scst_pr_clear_reservation(dev);
++ } else
++ scst_pr_clear_reservation(dev);
++
++ dev->pr_holder = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called under dev_pr_mutex */
++static struct scst_dev_registrant *scst_pr_add_registrant(
++ struct scst_device *dev, const uint8_t *transport_id,
++ const uint16_t rel_tgt_id, __be64 key,
++ bool dev_lock_locked)
++{
++ struct scst_dev_registrant *reg;
++ struct scst_tgt_dev *t;
++ gfp_t gfp_flags = dev_lock_locked ? GFP_ATOMIC : GFP_KERNEL;
++
++ TRACE_ENTRY();
++
++ BUG_ON(dev == NULL);
++ BUG_ON(transport_id == NULL);
++
++ TRACE_PR("Registering %s/%d (dev %s)",
++ debug_transport_id_to_initiator_name(transport_id),
++ rel_tgt_id, dev->virt_name);
++
++ reg = scst_pr_find_reg(dev, transport_id, rel_tgt_id);
++ if (reg != NULL) {
++ /*
++ * It might happen when a target driver would make >1 session
++ * from the same initiator to the same target.
++ */
++ PRINT_ERROR("Registrant %p/%d (dev %s) already exists!", reg,
++ rel_tgt_id, dev->virt_name);
++ PRINT_BUFFER("TransportID", transport_id, 24);
++ WARN_ON(1);
++ reg = NULL;
++ goto out;
++ }
++
++ reg = kzalloc(sizeof(*reg), gfp_flags);
++ if (reg == NULL) {
++ PRINT_ERROR("%s", "Unable to allocate registration record");
++ goto out;
++ }
++
++ reg->transport_id = kmalloc(tid_size(transport_id), gfp_flags);
++ if (reg->transport_id == NULL) {
++ PRINT_ERROR("%s", "Unable to allocate initiator port "
++ "transport id");
++ goto out_free;
++ }
++ memcpy(reg->transport_id, transport_id, tid_size(transport_id));
++
++ reg->rel_tgt_id = rel_tgt_id;
++ reg->key = key;
++
++ /*
++ * We can't use scst_mutex here, because of the circular
++ * locking dependency with dev_pr_mutex.
++ */
++ if (!dev_lock_locked)
++ spin_lock_bh(&dev->dev_lock);
++ list_for_each_entry(t, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) {
++ if (tid_equal(t->sess->transport_id, transport_id) &&
++ (t->sess->tgt->rel_tgt_id == rel_tgt_id) &&
++ (t->registrant == NULL)) {
++ /*
++ * We must assign here, because t can die
++ * immediately after we release dev_lock.
++ */
++ TRACE_PR("Found tgt_dev %p", t);
++ reg->tgt_dev = t;
++ t->registrant = reg;
++ break;
++ }
++ }
++ if (!dev_lock_locked)
++ spin_unlock_bh(&dev->dev_lock);
++
++ list_add_tail(&reg->dev_registrants_list_entry,
++ &dev->dev_registrants_list);
++
++ TRACE_PR("Reg %p registered (dev %s, tgt_dev %p)", reg,
++ dev->virt_name, reg->tgt_dev);
++
++out:
++ TRACE_EXIT_HRES((unsigned long)reg);
++ return reg;
++
++out_free:
++ kfree(reg);
++ reg = NULL;
++ goto out;
++}
++
++/* Must be called under dev_pr_mutex */
++static void scst_pr_remove_registrant(struct scst_device *dev,
++ struct scst_dev_registrant *reg)
++{
++ TRACE_ENTRY();
++
++ TRACE_PR("Removing registrant %s/%d (reg %p, tgt_dev %p, key %016llx, "
++ "dev %s)", debug_transport_id_to_initiator_name(reg->transport_id),
++ reg->rel_tgt_id, reg, reg->tgt_dev, reg->key, dev->virt_name);
++
++ list_del(&reg->dev_registrants_list_entry);
++
++ if (scst_pr_is_holder(dev, reg))
++ scst_pr_clear_holder(dev);
++
++ if (reg->tgt_dev)
++ reg->tgt_dev->registrant = NULL;
++
++ kfree(reg->transport_id);
++ kfree(reg);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called under dev_pr_mutex */
++static void scst_pr_send_ua_reg(struct scst_device *dev,
++ struct scst_dev_registrant *reg,
++ int key, int asc, int ascq)
++{
++ static uint8_t ua[SCST_STANDARD_SENSE_LEN];
++
++ TRACE_ENTRY();
++
++ scst_set_sense(ua, sizeof(ua), dev->d_sense, key, asc, ascq);
++
++ TRACE_PR("Queuing UA [%x %x %x]: registrant %s/%d (%p), tgt_dev %p, "
++ "key %016llx", ua[2], ua[12], ua[13],
++ debug_transport_id_to_initiator_name(reg->transport_id),
++ reg->rel_tgt_id, reg, reg->tgt_dev, reg->key);
++
++ if (reg->tgt_dev)
++ scst_check_set_UA(reg->tgt_dev, ua, sizeof(ua), 0);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called under dev_pr_mutex */
++static void scst_pr_send_ua_all(struct scst_device *dev,
++ struct scst_dev_registrant *exclude_reg,
++ int key, int asc, int ascq)
++{
++ struct scst_dev_registrant *reg;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ if (reg != exclude_reg)
++ scst_pr_send_ua_reg(dev, reg, key, asc, ascq);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called under dev_pr_mutex */
++static void scst_pr_abort_reg(struct scst_device *dev,
++ struct scst_cmd *pr_cmd, struct scst_dev_registrant *reg)
++{
++ struct scst_session *sess;
++ __be64 packed_lun;
++ int rc;
++
++ TRACE_ENTRY();
++
++ if (reg->tgt_dev == NULL) {
++ TRACE_PR("Registrant %s/%d (%p, key 0x%016llx) has no session",
++ debug_transport_id_to_initiator_name(reg->transport_id),
++ reg->rel_tgt_id, reg, reg->key);
++ goto out;
++ }
++
++ sess = reg->tgt_dev->sess;
++
++ TRACE_PR("Aborting %d commands for %s/%d (reg %p, key 0x%016llx, "
++ "tgt_dev %p, sess %p)",
++ atomic_read(&reg->tgt_dev->tgt_dev_cmd_count),
++ debug_transport_id_to_initiator_name(reg->transport_id),
++ reg->rel_tgt_id, reg, reg->key, reg->tgt_dev, sess);
++
++ packed_lun = scst_pack_lun(reg->tgt_dev->lun, sess->acg->addr_method);
++
++ rc = scst_rx_mgmt_fn_lun(sess, SCST_PR_ABORT_ALL,
++ (uint8_t *)&packed_lun, sizeof(packed_lun), SCST_NON_ATOMIC,
++ pr_cmd);
++ if (rc != 0) {
++ /*
++ * There's nothing more we can do here... Hopefully, it would
++ * never happen.
++ */
++ PRINT_ERROR("SCST_PR_ABORT_ALL failed %d (sess %p)",
++ rc, sess);
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Abstract vfs_unlink & path_put for different kernel versions */
++static inline void scst_pr_vfs_unlink_and_put(struct nameidata *nd)
++{
++ vfs_unlink(nd->path.dentry->d_parent->d_inode,
++ nd->path.dentry);
++ path_put(&nd->path);
++}
++
++static inline void scst_pr_path_put(struct nameidata *nd)
++{
++ path_put(&nd->path);
++}
++
++/* Called under scst_mutex */
++static int scst_pr_do_load_device_file(struct scst_device *dev,
++ const char *file_name)
++{
++ int res = 0, rc;
++ struct file *file = NULL;
++ struct inode *inode;
++ char *buf = NULL;
++ loff_t file_size, pos, data_size;
++ uint64_t sign, version;
++ mm_segment_t old_fs;
++ uint8_t pr_is_set, aptpl;
++ __be64 key;
++ uint16_t rel_tgt_id;
++
++ TRACE_ENTRY();
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++
++ TRACE_PR("Loading persistent file '%s'", file_name);
++
++ file = filp_open(file_name, O_RDONLY, 0);
++ if (IS_ERR(file)) {
++ res = PTR_ERR(file);
++ TRACE_PR("Unable to open file '%s' - error %d", file_name, res);
++ goto out;
++ }
++
++ inode = file->f_dentry->d_inode;
++
++ if (S_ISREG(inode->i_mode))
++ /* Nothing to do */;
++ else if (S_ISBLK(inode->i_mode))
++ inode = inode->i_bdev->bd_inode;
++ else {
++ PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
++ goto out_close;
++ }
++
++ file_size = inode->i_size;
++
++ /* Let's limit the file size by some reasonable number */
++ if ((file_size == 0) || (file_size >= 15*1024*1024)) {
++ PRINT_ERROR("Invalid PR file size %d", (int)file_size);
++ res = -EINVAL;
++ goto out_close;
++ }
++
++ buf = vmalloc(file_size);
++ if (buf == NULL) {
++ res = -ENOMEM;
++ PRINT_ERROR("%s", "Unable to allocate buffer");
++ goto out_close;
++ }
++
++ pos = 0;
++ rc = vfs_read(file, (void __force __user *)buf, file_size, &pos);
++ if (rc != file_size) {
++ PRINT_ERROR("Unable to read file '%s' - error %d", file_name,
++ rc);
++ res = rc;
++ goto out_close;
++ }
++
++ data_size = 0;
++ data_size += sizeof(sign);
++ data_size += sizeof(version);
++ data_size += sizeof(aptpl);
++ data_size += sizeof(pr_is_set);
++ data_size += sizeof(dev->pr_type);
++ data_size += sizeof(dev->pr_scope);
++
++ if (file_size < data_size) {
++ res = -EINVAL;
++ PRINT_ERROR("Invalid file '%s' - size too small", file_name);
++ goto out_close;
++ }
++
++ pos = 0;
++
++ sign = get_unaligned((uint64_t *)&buf[pos]);
++ if (sign != SCST_PR_FILE_SIGN) {
++ res = -EINVAL;
++ PRINT_ERROR("Invalid persistent file signature %016llx "
++ "(expected %016llx)", sign, SCST_PR_FILE_SIGN);
++ goto out_close;
++ }
++ pos += sizeof(sign);
++
++ version = get_unaligned((uint64_t *)&buf[pos]);
++ if (version != SCST_PR_FILE_VERSION) {
++ res = -EINVAL;
++ PRINT_ERROR("Invalid persistent file version %016llx "
++ "(expected %016llx)", version, SCST_PR_FILE_VERSION);
++ goto out_close;
++ }
++ pos += sizeof(version);
++
++ while (data_size < file_size) {
++ uint8_t *tid;
++
++ data_size++;
++ tid = &buf[data_size];
++ data_size += tid_size(tid);
++ data_size += sizeof(key);
++ data_size += sizeof(rel_tgt_id);
++
++ if (data_size > file_size) {
++ res = -EINVAL;
++ PRINT_ERROR("Invalid file '%s' - size mismatch have "
++ "%lld expected %lld", file_name, file_size,
++ data_size);
++ goto out_close;
++ }
++ }
++
++ aptpl = buf[pos];
++ dev->pr_aptpl = aptpl ? 1 : 0;
++ pos += sizeof(aptpl);
++
++ pr_is_set = buf[pos];
++ dev->pr_is_set = pr_is_set ? 1 : 0;
++ pos += sizeof(pr_is_set);
++
++ dev->pr_type = buf[pos];
++ pos += sizeof(dev->pr_type);
++
++ dev->pr_scope = buf[pos];
++ pos += sizeof(dev->pr_scope);
++
++ while (pos < file_size) {
++ uint8_t is_holder;
++ uint8_t *tid;
++ struct scst_dev_registrant *reg = NULL;
++
++ is_holder = buf[pos++];
++
++ tid = &buf[pos];
++ pos += tid_size(tid);
++
++ key = get_unaligned((__be64 *)&buf[pos]);
++ pos += sizeof(key);
++
++ rel_tgt_id = get_unaligned((uint16_t *)&buf[pos]);
++ pos += sizeof(rel_tgt_id);
++
++ reg = scst_pr_add_registrant(dev, tid, rel_tgt_id, key, false);
++ if (reg == NULL) {
++ res = -ENOMEM;
++ goto out_close;
++ }
++
++ if (is_holder)
++ dev->pr_holder = reg;
++ }
++
++out_close:
++ filp_close(file, NULL);
++
++out:
++ if (buf != NULL)
++ vfree(buf);
++
++ set_fs(old_fs);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_pr_load_device_file(struct scst_device *dev)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (dev->pr_file_name == NULL || dev->pr_file_name1 == NULL) {
++ PRINT_ERROR("Invalid file paths for '%s'", dev->virt_name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_pr_do_load_device_file(dev, dev->pr_file_name);
++ if (res == 0)
++ goto out;
++ else if (res == -ENOMEM)
++ goto out;
++
++ res = scst_pr_do_load_device_file(dev, dev->pr_file_name1);
++
++ scst_pr_dump_prs(dev, false);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_pr_copy_file(const char *src, const char *dest)
++{
++ int res = 0;
++ struct inode *inode;
++ loff_t file_size, pos;
++ uint8_t *buf = NULL;
++ struct file *file_src = NULL, *file_dest = NULL;
++ mm_segment_t old_fs = get_fs();
++
++ TRACE_ENTRY();
++
++ if (src == NULL || dest == NULL) {
++ res = -EINVAL;
++ PRINT_ERROR("%s", "Invalid persistent files path - backup "
++ "skipped");
++ goto out;
++ }
++
++ TRACE_PR("Copying '%s' into '%s'", src, dest);
++
++ set_fs(KERNEL_DS);
++
++ file_src = filp_open(src, O_RDONLY, 0);
++ if (IS_ERR(file_src)) {
++ res = PTR_ERR(file_src);
++ TRACE_PR("Unable to open file '%s' - error %d", src,
++ res);
++ goto out_free;
++ }
++
++ file_dest = filp_open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0644);
++ if (IS_ERR(file_dest)) {
++ res = PTR_ERR(file_dest);
++ TRACE_PR("Unable to open backup file '%s' - error %d", dest,
++ res);
++ goto out_close;
++ }
++
++ inode = file_src->f_dentry->d_inode;
++
++ if (S_ISREG(inode->i_mode))
++ /* Nothing to do */;
++ else if (S_ISBLK(inode->i_mode))
++ inode = inode->i_bdev->bd_inode;
++ else {
++ PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode);
++ res = -EINVAL;
++ set_fs(old_fs);
++ goto out_skip;
++ }
++
++ file_size = inode->i_size;
++
++ buf = vmalloc(file_size);
++ if (buf == NULL) {
++ res = -ENOMEM;
++ PRINT_ERROR("%s", "Unable to allocate temporary buffer");
++ goto out_skip;
++ }
++
++ pos = 0;
++ res = vfs_read(file_src, (void __force __user *)buf, file_size, &pos);
++ if (res != file_size) {
++ PRINT_ERROR("Unable to read file '%s' - error %d", src, res);
++ goto out_skip;
++ }
++
++ pos = 0;
++ res = vfs_write(file_dest, (void __force __user *)buf, file_size, &pos);
++ if (res != file_size) {
++ PRINT_ERROR("Unable to write to '%s' - error %d", dest, res);
++ goto out_skip;
++ }
++
++ res = vfs_fsync(file_dest, 0);
++ if (res != 0) {
++ PRINT_ERROR("fsync() of the backup PR file failed: %d", res);
++ goto out_skip;
++ }
++
++out_skip:
++ filp_close(file_dest, NULL);
++
++out_close:
++ filp_close(file_src, NULL);
++
++out_free:
++ if (buf != NULL)
++ vfree(buf);
++
++ set_fs(old_fs);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void scst_pr_remove_device_files(struct scst_tgt_dev *tgt_dev)
++{
++ int res = 0;
++ struct scst_device *dev = tgt_dev->dev;
++ struct nameidata nd;
++ mm_segment_t old_fs = get_fs();
++
++ TRACE_ENTRY();
++
++ set_fs(KERNEL_DS);
++
++ res = path_lookup(dev->pr_file_name, 0, &nd);
++ if (!res)
++ scst_pr_vfs_unlink_and_put(&nd);
++ else
++ TRACE_DBG("Unable to lookup file '%s' - error %d",
++ dev->pr_file_name, res);
++
++ res = path_lookup(dev->pr_file_name1, 0, &nd);
++ if (!res)
++ scst_pr_vfs_unlink_and_put(&nd);
++ else
++ TRACE_DBG("Unable to lookup file '%s' - error %d",
++ dev->pr_file_name1, res);
++
++ set_fs(old_fs);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called under dev_pr_mutex */
++void scst_pr_sync_device_file(struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd)
++{
++ int res = 0;
++ struct scst_device *dev = tgt_dev->dev;
++ struct file *file;
++ mm_segment_t old_fs = get_fs();
++ loff_t pos = 0;
++ uint64_t sign;
++ uint64_t version;
++ uint8_t pr_is_set, aptpl;
++
++ TRACE_ENTRY();
++
++ if ((dev->pr_aptpl == 0) || list_empty(&dev->dev_registrants_list)) {
++ scst_pr_remove_device_files(tgt_dev);
++ goto out;
++ }
++
++ scst_pr_copy_file(dev->pr_file_name, dev->pr_file_name1);
++
++ set_fs(KERNEL_DS);
++
++ file = filp_open(dev->pr_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
++ if (IS_ERR(file)) {
++ res = PTR_ERR(file);
++ PRINT_ERROR("Unable to (re)create PR file '%s' - error %d",
++ dev->pr_file_name, res);
++ goto out_set_fs;
++ }
++
++ TRACE_PR("Updating pr file '%s'", dev->pr_file_name);
++
++ /*
++ * signature
++ */
++ sign = 0;
++ pos = 0;
++ res = vfs_write(file, (void __force __user *)&sign, sizeof(sign), &pos);
++ if (res != sizeof(sign))
++ goto write_error;
++
++ /*
++ * version
++ */
++ version = SCST_PR_FILE_VERSION;
++ res = vfs_write(file, (void __force __user *)&version, sizeof(version), &pos);
++ if (res != sizeof(version))
++ goto write_error;
++
++ /*
++ * APTPL
++ */
++ aptpl = dev->pr_aptpl;
++ res = vfs_write(file, (void __force __user *)&aptpl, sizeof(aptpl), &pos);
++ if (res != sizeof(aptpl))
++ goto write_error;
++
++ /*
++ * reservation
++ */
++ pr_is_set = dev->pr_is_set;
++ res = vfs_write(file, (void __force __user *)&pr_is_set, sizeof(pr_is_set), &pos);
++ if (res != sizeof(pr_is_set))
++ goto write_error;
++
++ res = vfs_write(file, (void __force __user *)&dev->pr_type, sizeof(dev->pr_type), &pos);
++ if (res != sizeof(dev->pr_type))
++ goto write_error;
++
++ res = vfs_write(file, (void __force __user *)&dev->pr_scope, sizeof(dev->pr_scope), &pos);
++ if (res != sizeof(dev->pr_scope))
++ goto write_error;
++
++ /*
++ * registration records
++ */
++ if (!list_empty(&dev->dev_registrants_list)) {
++ struct scst_dev_registrant *reg;
++
++ list_for_each_entry(reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ uint8_t is_holder = 0;
++ int size;
++
++ is_holder = (dev->pr_holder == reg);
++
++ res = vfs_write(file, (void __force __user *)&is_holder, sizeof(is_holder),
++ &pos);
++ if (res != sizeof(is_holder))
++ goto write_error;
++
++ size = tid_size(reg->transport_id);
++ res = vfs_write(file, (void __force __user *)reg->transport_id, size, &pos);
++ if (res != size)
++ goto write_error;
++
++ res = vfs_write(file, (void __force __user *)&reg->key,
++ sizeof(reg->key), &pos);
++ if (res != sizeof(reg->key))
++ goto write_error;
++
++ res = vfs_write(file, (void __force __user *)&reg->rel_tgt_id,
++ sizeof(reg->rel_tgt_id), &pos);
++ if (res != sizeof(reg->rel_tgt_id))
++ goto write_error;
++ }
++ }
++
++ res = vfs_fsync(file, 0);
++ if (res != 0) {
++ PRINT_ERROR("fsync() of the PR file failed: %d", res);
++ goto write_error_close;
++ }
++
++ sign = SCST_PR_FILE_SIGN;
++ pos = 0;
++ res = vfs_write(file, (void __force __user *)&sign, sizeof(sign), &pos);
++ if (res != sizeof(sign))
++ goto write_error;
++
++ res = vfs_fsync(file, 0);
++ if (res != 0) {
++ PRINT_ERROR("fsync() of the PR file failed: %d", res);
++ goto write_error_close;
++ }
++
++ res = 0;
++
++ filp_close(file, NULL);
++
++out_set_fs:
++ set_fs(old_fs);
++
++out:
++ if (res != 0) {
++ PRINT_CRIT_ERROR("Unable to save persistent information "
++ "(target %s, initiator %s, device %s)",
++ tgt_dev->sess->tgt->tgt_name,
++ tgt_dev->sess->initiator_name, dev->virt_name);
++#if 0 /*
++ * Looks like it's safer to return SUCCESS and expect operator's
++ * intervention to be able to save the PR's state next time, than
++ * to return HARDWARE ERROR and screw up all the interaction with
++ * the affected initiator.
++ */
++ if (cmd != NULL)
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++#endif
++ }
++
++ TRACE_EXIT_RES(res);
++ return;
++
++write_error:
++ PRINT_ERROR("Error writing to '%s' - error %d", dev->pr_file_name, res);
++
++write_error_close:
++ filp_close(file, NULL);
++ {
++ struct nameidata nd;
++ int rc;
++
++ rc = path_lookup(dev->pr_file_name, 0, &nd);
++ if (!rc)
++ scst_pr_vfs_unlink_and_put(&nd);
++ else
++ TRACE_PR("Unable to lookup '%s' - error %d",
++ dev->pr_file_name, rc);
++ }
++ goto out_set_fs;
++}
++
++static int scst_pr_check_pr_path(void)
++{
++ int res;
++ struct nameidata nd;
++ mm_segment_t old_fs = get_fs();
++
++ TRACE_ENTRY();
++
++ set_fs(KERNEL_DS);
++
++ res = path_lookup(SCST_PR_DIR, 0, &nd);
++ if (res != 0) {
++ PRINT_ERROR("Unable to find %s (err %d), you should create "
++ "this directory manually or reinstall SCST",
++ SCST_PR_DIR, res);
++ goto out_setfs;
++ }
++
++ scst_pr_path_put(&nd);
++
++out_setfs:
++ set_fs(old_fs);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Called under scst_mutex */
++int scst_pr_init_dev(struct scst_device *dev)
++{
++ int res = 0;
++ uint8_t q;
++ int name_len;
++
++ TRACE_ENTRY();
++
++ name_len = snprintf(&q, sizeof(q), "%s/%s", SCST_PR_DIR, dev->virt_name) + 1;
++ dev->pr_file_name = kmalloc(name_len, GFP_KERNEL);
++ if (dev->pr_file_name == NULL) {
++ PRINT_ERROR("Allocation of device '%s' file path failed",
++ dev->virt_name);
++ res = -ENOMEM;
++ goto out;
++ } else
++ snprintf(dev->pr_file_name, name_len, "%s/%s", SCST_PR_DIR,
++ dev->virt_name);
++
++ name_len = snprintf(&q, sizeof(q), "%s/%s.1", SCST_PR_DIR, dev->virt_name) + 1;
++ dev->pr_file_name1 = kmalloc(name_len, GFP_KERNEL);
++ if (dev->pr_file_name1 == NULL) {
++ PRINT_ERROR("Allocation of device '%s' backup file path failed",
++ dev->virt_name);
++ res = -ENOMEM;
++ goto out_free_name;
++ } else
++ snprintf(dev->pr_file_name1, name_len, "%s/%s.1", SCST_PR_DIR,
++ dev->virt_name);
++
++ res = scst_pr_check_pr_path();
++ if (res == 0) {
++ res = scst_pr_load_device_file(dev);
++ if (res == -ENOENT)
++ res = 0;
++ }
++
++ if (res != 0)
++ goto out_free_name1;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free_name1:
++ kfree(dev->pr_file_name1);
++ dev->pr_file_name1 = NULL;
++
++out_free_name:
++ kfree(dev->pr_file_name);
++ dev->pr_file_name = NULL;
++ goto out;
++}
++
++/* Called under scst_mutex */
++void scst_pr_clear_dev(struct scst_device *dev)
++{
++ struct scst_dev_registrant *reg, *tmp_reg;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry_safe(reg, tmp_reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ scst_pr_remove_registrant(dev, reg);
++ }
++
++ kfree(dev->pr_file_name);
++ kfree(dev->pr_file_name1);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called under scst_mutex */
++int scst_pr_init_tgt_dev(struct scst_tgt_dev *tgt_dev)
++{
++ int res = 0;
++ struct scst_dev_registrant *reg;
++ struct scst_device *dev = tgt_dev->dev;
++ const uint8_t *transport_id = tgt_dev->sess->transport_id;
++ const uint16_t rel_tgt_id = tgt_dev->sess->tgt->rel_tgt_id;
++
++ TRACE_ENTRY();
++
++ if (tgt_dev->sess->transport_id == NULL)
++ goto out;
++
++ scst_pr_write_lock(dev);
++
++ reg = scst_pr_find_reg(dev, transport_id, rel_tgt_id);
++ if ((reg != NULL) && (reg->tgt_dev == NULL)) {
++ TRACE_PR("Assigning reg %s/%d (%p) to tgt_dev %p (dev %s)",
++ debug_transport_id_to_initiator_name(transport_id),
++ rel_tgt_id, reg, tgt_dev, dev->virt_name);
++ tgt_dev->registrant = reg;
++ reg->tgt_dev = tgt_dev;
++ }
++
++ scst_pr_write_unlock(dev);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Called under scst_mutex */
++void scst_pr_clear_tgt_dev(struct scst_tgt_dev *tgt_dev)
++{
++ TRACE_ENTRY();
++
++ if (tgt_dev->registrant != NULL) {
++ struct scst_dev_registrant *reg = tgt_dev->registrant;
++ struct scst_device *dev = tgt_dev->dev;
++ struct scst_tgt_dev *t;
++
++ scst_pr_write_lock(dev);
++
++ tgt_dev->registrant = NULL;
++ reg->tgt_dev = NULL;
++
++ /* Just in case, actually. It should never happen. */
++ list_for_each_entry(t, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if (t == tgt_dev)
++ continue;
++ if ((t->sess->tgt->rel_tgt_id == reg->rel_tgt_id) &&
++ tid_equal(t->sess->transport_id, reg->transport_id)) {
++ TRACE_PR("Reassigning reg %s/%d (%p) to tgt_dev "
++ "%p (being cleared tgt_dev %p)",
++ debug_transport_id_to_initiator_name(
++ reg->transport_id),
++ reg->rel_tgt_id, reg, t, tgt_dev);
++ t->registrant = reg;
++ reg->tgt_dev = t;
++ break;
++ }
++ }
++
++ scst_pr_write_unlock(dev);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked. Might also be called under scst_mutex2. */
++static int scst_pr_register_with_spec_i_pt(struct scst_cmd *cmd,
++ const uint16_t rel_tgt_id, uint8_t *buffer, int buffer_size,
++ struct list_head *rollback_list)
++{
++ int res = 0;
++ int offset, ext_size;
++ __be64 action_key;
++ struct scst_device *dev = cmd->dev;
++ struct scst_dev_registrant *reg;
++ uint8_t *transport_id;
++
++ action_key = get_unaligned((__be64 *)&buffer[8]);
++
++ ext_size = be32_to_cpu(get_unaligned((__be32 *)&buffer[24]));
++ if ((ext_size + 28) > buffer_size) {
++ TRACE_PR("Invalid buffer size %d (max %d)", buffer_size,
++ ext_size + 28);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
++ res = -EINVAL;
++ goto out;
++ }
++
++ offset = 0;
++ while (offset < ext_size) {
++ transport_id = &buffer[28 + offset];
++
++ if ((offset + tid_size(transport_id)) > ext_size) {
++ TRACE_PR("Invalid transport_id size %d (max %d)",
++ tid_size(transport_id), ext_size - offset);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
++ res = -EINVAL;
++ goto out;
++ }
++ tid_secure(transport_id);
++ offset += tid_size(transport_id);
++ }
++
++ offset = 0;
++ while (offset < ext_size) {
++ struct scst_tgt_dev *t;
++
++ transport_id = &buffer[28 + offset];
++
++ TRACE_PR("rel_tgt_id %d, transport_id %s", rel_tgt_id,
++ debug_transport_id_to_initiator_name(transport_id));
++
++ if ((transport_id[0] & 0x0f) == SCSI_TRANSPORTID_PROTOCOLID_ISCSI &&
++ (transport_id[0] & 0xc0) == 0) {
++ TRACE_PR("Wildcard iSCSI TransportID %s",
++ &transport_id[4]);
++ /*
++ * We can't use scst_mutex here, because of the
++ * circular locking dependency with dev_pr_mutex.
++ */
++ spin_lock_bh(&dev->dev_lock);
++ list_for_each_entry(t, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ /*
++ * We must go over all matching tgt_devs and
++ * register them on the requested rel_tgt_id
++ */
++ if (!tid_equal(t->sess->transport_id,
++ transport_id))
++ continue;
++
++ reg = scst_pr_find_reg(dev,
++ t->sess->transport_id, rel_tgt_id);
++ if (reg == NULL) {
++ reg = scst_pr_add_registrant(dev,
++ t->sess->transport_id,
++ rel_tgt_id, action_key, true);
++ if (reg == NULL) {
++ spin_unlock_bh(&dev->dev_lock);
++ scst_set_busy(cmd);
++ res = -ENOMEM;
++ goto out;
++ }
++ } else if (reg->key != action_key) {
++ TRACE_PR("Changing key of reg %p "
++ "(tgt_dev %p)", reg, t);
++ reg->rollback_key = reg->key;
++ reg->key = action_key;
++ } else
++ continue;
++
++ list_add_tail(&reg->aux_list_entry,
++ rollback_list);
++ }
++ spin_unlock_bh(&dev->dev_lock);
++ } else {
++ reg = scst_pr_find_reg(dev, transport_id, rel_tgt_id);
++ if (reg != NULL) {
++ if (reg->key == action_key)
++ goto next;
++ TRACE_PR("Changing key of reg %p (tgt_dev %p)",
++ reg, reg->tgt_dev);
++ reg->rollback_key = reg->key;
++ reg->key = action_key;
++ } else {
++ reg = scst_pr_add_registrant(dev, transport_id,
++ rel_tgt_id, action_key, false);
++ if (reg == NULL) {
++ scst_set_busy(cmd);
++ res = -ENOMEM;
++ goto out;
++ }
++ }
++
++ list_add_tail(&reg->aux_list_entry,
++ rollback_list);
++ }
++next:
++ offset += tid_size(transport_id);
++ }
++out:
++ return res;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++static void scst_pr_unregister(struct scst_device *dev,
++ struct scst_dev_registrant *reg)
++{
++ bool is_holder;
++ uint8_t pr_type;
++
++ TRACE_ENTRY();
++
++ TRACE_PR("Unregistering key %0llx", reg->key);
++
++ is_holder = scst_pr_is_holder(dev, reg);
++ pr_type = dev->pr_type;
++
++ scst_pr_remove_registrant(dev, reg);
++
++ if (is_holder && !dev->pr_is_set) {
++ /* A registration just released */
++ switch (pr_type) {
++ case TYPE_WRITE_EXCLUSIVE_REGONLY:
++ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
++ scst_pr_send_ua_all(dev, NULL,
++ SCST_LOAD_SENSE(scst_sense_reservation_released));
++ break;
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++static void scst_pr_unregister_all_tg_pt(struct scst_device *dev,
++ const uint8_t *transport_id)
++{
++ struct scst_tgt_template *tgtt;
++ uint8_t proto_id = transport_id[0] & 0x0f;
++
++ TRACE_ENTRY();
++
++ /*
++ * We can't use scst_mutex here, because of the circular locking
++ * dependency with dev_pr_mutex.
++ */
++ mutex_lock(&scst_mutex2);
++
++ list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
++ struct scst_tgt *tgt;
++
++ if (tgtt->get_initiator_port_transport_id == NULL)
++ continue;
++
++ if (tgtt->get_initiator_port_transport_id(NULL, NULL) != proto_id)
++ continue;
++
++ list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
++ struct scst_dev_registrant *reg;
++
++ reg = scst_pr_find_reg(dev, transport_id,
++ tgt->rel_tgt_id);
++ if (reg == NULL)
++ continue;
++
++ scst_pr_unregister(dev, reg);
++ }
++ }
++
++ mutex_unlock(&scst_mutex2);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked. Might also be called under scst_mutex2. */
++static int scst_pr_register_on_tgt_id(struct scst_cmd *cmd,
++ const uint16_t rel_tgt_id, uint8_t *buffer, int buffer_size,
++ bool spec_i_pt, struct list_head *rollback_list)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ TRACE_PR("rel_tgt_id %d, spec_i_pt %d", rel_tgt_id, spec_i_pt);
++
++ if (spec_i_pt) {
++ res = scst_pr_register_with_spec_i_pt(cmd, rel_tgt_id, buffer,
++ buffer_size, rollback_list);
++ if (res != 0)
++ goto out;
++ }
++
++ /* tgt_dev can be among TIDs for scst_pr_register_with_spec_i_pt() */
++
++ if (scst_pr_find_reg(cmd->dev, cmd->sess->transport_id, rel_tgt_id) == NULL) {
++ __be64 action_key;
++ struct scst_dev_registrant *reg;
++
++ action_key = get_unaligned((__be64 *)&buffer[8]);
++
++ reg = scst_pr_add_registrant(cmd->dev, cmd->sess->transport_id,
++ rel_tgt_id, action_key, false);
++ if (reg == NULL) {
++ res = -ENOMEM;
++ scst_set_busy(cmd);
++ goto out;
++ }
++
++ list_add_tail(&reg->aux_list_entry, rollback_list);
++ }
++
++ res = 0;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++static int scst_pr_register_all_tg_pt(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size, bool spec_i_pt, struct list_head *rollback_list)
++{
++ int res = 0;
++ struct scst_tgt_template *tgtt;
++ uint8_t proto_id = cmd->sess->transport_id[0] & 0x0f;
++
++ TRACE_ENTRY();
++
++ /*
++ * We can't use scst_mutex here, because of the circular locking
++ * dependency with dev_pr_mutex.
++ */
++ mutex_lock(&scst_mutex2);
++
++ list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
++ struct scst_tgt *tgt;
++
++ if (tgtt->get_initiator_port_transport_id == NULL)
++ continue;
++
++ if (tgtt->get_initiator_port_transport_id(NULL, NULL) != proto_id)
++ continue;
++
++ TRACE_PR("tgtt %s, spec_i_pt %d", tgtt->name, spec_i_pt);
++
++ list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
++ if (tgt->rel_tgt_id == 0)
++ continue;
++ TRACE_PR("tgt %s, rel_tgt_id %d", tgt->tgt_name,
++ tgt->rel_tgt_id);
++ res = scst_pr_register_on_tgt_id(cmd, tgt->rel_tgt_id,
++ buffer, buffer_size, spec_i_pt, rollback_list);
++ if (res != 0)
++ goto out_unlock;
++ }
++ }
++
++out_unlock:
++ mutex_unlock(&scst_mutex2);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++static int __scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size, bool spec_i_pt, bool all_tg_pt)
++{
++ int res;
++ struct scst_dev_registrant *reg, *treg;
++ LIST_HEAD(rollback_list);
++
++ TRACE_ENTRY();
++
++ if (all_tg_pt) {
++ res = scst_pr_register_all_tg_pt(cmd, buffer, buffer_size,
++ spec_i_pt, &rollback_list);
++ if (res != 0)
++ goto out_rollback;
++ } else {
++ res = scst_pr_register_on_tgt_id(cmd,
++ cmd->sess->tgt->rel_tgt_id, buffer, buffer_size,
++ spec_i_pt, &rollback_list);
++ if (res != 0)
++ goto out_rollback;
++ }
++
++ list_for_each_entry(reg, &rollback_list, aux_list_entry) {
++ reg->rollback_key = 0;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_rollback:
++ list_for_each_entry_safe(reg, treg, &rollback_list, aux_list_entry) {
++ list_del(&reg->aux_list_entry);
++ if (reg->rollback_key == 0)
++ scst_pr_remove_registrant(cmd->dev, reg);
++ else {
++ reg->key = reg->rollback_key;
++ reg->rollback_key = 0;
++ }
++ }
++ goto out;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
++{
++ int aptpl, spec_i_pt, all_tg_pt;
++ __be64 key, action_key;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_session *sess = cmd->sess;
++ struct scst_dev_registrant *reg;
++
++ TRACE_ENTRY();
++
++ aptpl = buffer[20] & 0x01;
++ spec_i_pt = (buffer[20] >> 3) & 0x01;
++ all_tg_pt = (buffer[20] >> 2) & 0x01;
++ key = get_unaligned((__be64 *)&buffer[0]);
++ action_key = get_unaligned((__be64 *)&buffer[8]);
++
++ if (spec_i_pt == 0 && buffer_size != 24) {
++ TRACE_PR("Invalid buffer size %d", buffer_size);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
++ goto out;
++ }
++
++ reg = tgt_dev->registrant;
++
++ TRACE_PR("Register: initiator %s/%d (%p), key %0llx, action_key %0llx "
++ "(tgt_dev %p)",
++ debug_transport_id_to_initiator_name(sess->transport_id),
++ sess->tgt->rel_tgt_id, reg, key, action_key, tgt_dev);
++
++ if (reg == NULL) {
++ TRACE_PR("tgt_dev %p is not registered yet - registering",
++ tgt_dev);
++ if (key) {
++ TRACE_PR("%s", "Key must be zero on new registration");
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++ if (action_key) {
++ int rc = __scst_pr_register(cmd, buffer, buffer_size,
++ spec_i_pt, all_tg_pt);
++ if (rc != 0)
++ goto out;
++ } else
++ TRACE_PR("%s", "Doing nothing - action_key is zero");
++ } else {
++ if (reg->key != key) {
++ TRACE_PR("tgt_dev %p already registered - reservation "
++ "key %0llx mismatch", tgt_dev, reg->key);
++ scst_set_cmd_error_status(cmd,
++ SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++ if (spec_i_pt) {
++ TRACE_PR("%s", "spec_i_pt must be zero in this case");
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++ if (action_key == 0) {
++ if (all_tg_pt)
++ scst_pr_unregister_all_tg_pt(dev,
++ sess->transport_id);
++ else
++ scst_pr_unregister(dev, reg);
++ } else
++ reg->key = action_key;
++ }
++
++ dev->pr_generation++;
++
++ dev->pr_aptpl = aptpl;
++
++ scst_pr_dump_prs(dev, false);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_register_and_ignore(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size)
++{
++ int aptpl, all_tg_pt;
++ __be64 action_key;
++ struct scst_dev_registrant *reg = NULL;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_session *sess = cmd->sess;
++
++ TRACE_ENTRY();
++
++ aptpl = buffer[20] & 0x01;
++ all_tg_pt = (buffer[20] >> 2) & 0x01;
++ action_key = get_unaligned((__be64 *)&buffer[8]);
++
++ if (buffer_size != 24) {
++ TRACE_PR("Invalid buffer size %d", buffer_size);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
++ goto out;
++ }
++
++ reg = tgt_dev->registrant;
++
++ TRACE_PR("Register and ignore: initiator %s/%d (%p), action_key "
++ "%016llx (tgt_dev %p)",
++ debug_transport_id_to_initiator_name(sess->transport_id),
++ sess->tgt->rel_tgt_id, reg, action_key, tgt_dev);
++
++ if (reg == NULL) {
++ TRACE_PR("Tgt_dev %p is not registered yet - trying to "
++ "register", tgt_dev);
++ if (action_key) {
++ int rc = __scst_pr_register(cmd, buffer, buffer_size,
++ false, all_tg_pt);
++ if (rc != 0)
++ goto out;
++ } else
++ TRACE_PR("%s", "Doing nothing, action_key is zero");
++ } else {
++ if (action_key == 0) {
++ if (all_tg_pt)
++ scst_pr_unregister_all_tg_pt(dev,
++ sess->transport_id);
++ else
++ scst_pr_unregister(dev, reg);
++ } else
++ reg->key = action_key;
++ }
++
++ dev->pr_generation++;
++
++ dev->pr_aptpl = aptpl;
++
++ scst_pr_dump_prs(dev, false);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size)
++{
++ int aptpl;
++ int unreg;
++ int tid_buffer_size;
++ __be64 key, action_key;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_session *sess = cmd->sess;
++ struct scst_dev_registrant *reg, *reg_move;
++ const uint8_t *transport_id = NULL;
++ uint8_t *transport_id_move = NULL;
++ uint16_t rel_tgt_id_move;
++
++ TRACE_ENTRY();
++
++ aptpl = buffer[17] & 0x01;
++ key = get_unaligned((__be64 *)&buffer[0]);
++ action_key = get_unaligned((__be64 *)&buffer[8]);
++ unreg = (buffer[17] >> 1) & 0x01;
++ tid_buffer_size = be32_to_cpu(get_unaligned((__be32 *)&buffer[20]));
++
++ if ((tid_buffer_size + 24) > buffer_size) {
++ TRACE_PR("Invalid buffer size %d (%d)",
++ buffer_size, tid_buffer_size + 24);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
++ goto out;
++ }
++
++ if (tid_buffer_size < 24) {
++ TRACE_PR("%s", "Transport id buffer too small");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
++ goto out;
++ }
++
++ reg = tgt_dev->registrant;
++ /* We already checked reg is not NULL */
++ if (reg->key != key) {
++ TRACE_PR("Registrant's %s/%d (%p) key %016llx mismatch with "
++ "%016llx (tgt_dev %p)",
++ debug_transport_id_to_initiator_name(reg->transport_id),
++ reg->rel_tgt_id, reg, reg->key, key, tgt_dev);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++
++ if (!dev->pr_is_set) {
++ TRACE_PR("%s", "There must be a PR");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++
++ /*
++ * This check also required by table "PERSISTENT RESERVE OUT service
++ * actions that are allowed in the presence of various reservations".
++ */
++ if (!scst_pr_is_holder(dev, reg)) {
++ TRACE_PR("Registrant %s/%d (%p) is not a holder (tgt_dev %p)",
++ debug_transport_id_to_initiator_name(
++ reg->transport_id), reg->rel_tgt_id,
++ reg, tgt_dev);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++
++ if (action_key == 0) {
++ TRACE_PR("%s", "Action key must be non-zero");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++
++ transport_id = sess->transport_id;
++ transport_id_move = (uint8_t *)&buffer[24];
++ rel_tgt_id_move = be16_to_cpu(get_unaligned((__be16 *)&buffer[18]));
++
++ if ((tid_size(transport_id_move) + 24) > buffer_size) {
++ TRACE_PR("Invalid buffer size %d (%d)",
++ buffer_size, tid_size(transport_id_move) + 24);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
++ goto out;
++ }
++
++ tid_secure(transport_id_move);
++
++ if (dev->pr_type == TYPE_WRITE_EXCLUSIVE_ALL_REG ||
++ dev->pr_type == TYPE_EXCLUSIVE_ACCESS_ALL_REG) {
++ TRACE_PR("Unable to finish operation due to wrong reservation "
++ "type %02x", dev->pr_type);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++
++ if (tid_equal(transport_id, transport_id_move)) {
++ TRACE_PR("%s", "Equal transport id's");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
++ goto out;
++ }
++
++ reg_move = scst_pr_find_reg(dev, transport_id_move, rel_tgt_id_move);
++ if (reg_move == NULL) {
++ reg_move = scst_pr_add_registrant(dev, transport_id_move,
++ rel_tgt_id_move, action_key, false);
++ if (reg_move == NULL) {
++ scst_set_busy(cmd);
++ goto out;
++ }
++ } else if (reg_move->key != action_key) {
++ TRACE_PR("Changing key for reg %p", reg);
++ reg_move->key = action_key;
++ }
++
++ TRACE_PR("Register and move: from initiator %s/%d (%p, tgt_dev %p) to "
++ "initiator %s/%d (%p, tgt_dev %p), key %016llx (unreg %d)",
++ debug_transport_id_to_initiator_name(reg->transport_id),
++ reg->rel_tgt_id, reg, reg->tgt_dev,
++ debug_transport_id_to_initiator_name(transport_id_move),
++ rel_tgt_id_move, reg_move, reg_move->tgt_dev, action_key,
++ unreg);
++
++ /* Move the holder */
++ scst_pr_set_holder(dev, reg_move, dev->pr_scope, dev->pr_type);
++
++ if (unreg)
++ scst_pr_remove_registrant(dev, reg);
++
++ dev->pr_generation++;
++
++ dev->pr_aptpl = aptpl;
++
++ scst_pr_dump_prs(dev, false);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_reserve(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
++{
++ uint8_t scope, type;
++ __be64 key;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_dev_registrant *reg;
++
++ TRACE_ENTRY();
++
++ key = get_unaligned((__be64 *)&buffer[0]);
++ scope = (cmd->cdb[2] & 0x0f) >> 4;
++ type = cmd->cdb[2] & 0x0f;
++
++ if (buffer_size != 24) {
++ TRACE_PR("Invalid buffer size %d", buffer_size);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
++ goto out;
++ }
++
++ if (!scst_pr_type_valid(type)) {
++ TRACE_PR("Invalid reservation type %d", type);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++
++ if (((cmd->cdb[2] & 0x0f) >> 4) != SCOPE_LU) {
++ TRACE_PR("Invalid reservation scope %d", scope);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++
++ reg = tgt_dev->registrant;
++
++ TRACE_PR("Reserve: initiator %s/%d (%p), key %016llx, scope %d, "
++ "type %d (tgt_dev %p)",
++ debug_transport_id_to_initiator_name(cmd->sess->transport_id),
++ cmd->sess->tgt->rel_tgt_id, reg, key, scope, type, tgt_dev);
++
++ /* We already checked reg is not NULL */
++ if (reg->key != key) {
++ TRACE_PR("Registrant's %p key %016llx mismatch with %016llx",
++ reg, reg->key, key);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++
++ if (!dev->pr_is_set)
++ scst_pr_set_holder(dev, reg, scope, type);
++ else {
++ if (!scst_pr_is_holder(dev, reg)) {
++ /*
++ * This check also required by table "PERSISTENT
++ * RESERVE OUT service actions that are allowed in the
++ * presence of various reservations".
++ */
++ TRACE_PR("Only holder can override - reg %p is not a "
++ "holder", reg);
++ scst_set_cmd_error_status(cmd,
++ SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ } else {
++ if (dev->pr_scope != scope || dev->pr_type != type) {
++ TRACE_PR("Error overriding scope or type for "
++ "reg %p", reg);
++ scst_set_cmd_error_status(cmd,
++ SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ } else
++ TRACE_PR("Do nothing: reservation of reg %p "
++ "is the same", reg);
++ }
++ }
++
++ scst_pr_dump_prs(dev, false);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_release(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
++{
++ int scope, type;
++ __be64 key;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_dev_registrant *reg;
++ uint8_t cur_pr_type;
++
++ TRACE_ENTRY();
++
++ key = get_unaligned((__be64 *)&buffer[0]);
++ scope = (cmd->cdb[2] & 0x0f) >> 4;
++ type = cmd->cdb[2] & 0x0f;
++
++ if (buffer_size != 24) {
++ TRACE_PR("Invalid buffer size %d", buffer_size);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
++ goto out;
++ }
++
++ if (!dev->pr_is_set) {
++ TRACE_PR("%s", "There is no PR - do nothing");
++ goto out;
++ }
++
++ reg = tgt_dev->registrant;
++
++ TRACE_PR("Release: initiator %s/%d (%p), key %016llx, scope %d, type "
++ "%d (tgt_dev %p)", debug_transport_id_to_initiator_name(
++ cmd->sess->transport_id),
++ cmd->sess->tgt->rel_tgt_id, reg, key, scope, type, tgt_dev);
++
++ /* We already checked reg is not NULL */
++ if (reg->key != key) {
++ TRACE_PR("Registrant's %p key %016llx mismatch with %016llx",
++ reg, reg->key, key);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++
++ if (!scst_pr_is_holder(dev, reg)) {
++ TRACE_PR("Registrant %p is not a holder - do nothing", reg);
++ goto out;
++ }
++
++ if (dev->pr_scope != scope || dev->pr_type != type) {
++ TRACE_PR("%s", "Released scope or type do not match with "
++ "holder");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_release));
++ goto out;
++ }
++
++ cur_pr_type = dev->pr_type; /* it will be cleared */
++
++ scst_pr_clear_reservation(dev);
++
++ switch (cur_pr_type) {
++ case TYPE_WRITE_EXCLUSIVE_REGONLY:
++ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
++ case TYPE_WRITE_EXCLUSIVE_ALL_REG:
++ case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
++ scst_pr_send_ua_all(dev, reg,
++ SCST_LOAD_SENSE(scst_sense_reservation_released));
++ }
++
++ scst_pr_dump_prs(dev, false);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_clear(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
++{
++ int scope, type;
++ __be64 key;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_dev_registrant *reg, *r, *t;
++
++ TRACE_ENTRY();
++
++ key = get_unaligned((__be64 *)&buffer[0]);
++ scope = (cmd->cdb[2] & 0x0f) >> 4;
++ type = cmd->cdb[2] & 0x0f;
++
++ if (buffer_size != 24) {
++ TRACE_PR("Invalid buffer size %d", buffer_size);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
++ goto out;
++ }
++
++ reg = tgt_dev->registrant;
++
++ TRACE_PR("Clear: initiator %s/%d (%p), key %016llx (tgt_dev %p)",
++ debug_transport_id_to_initiator_name(cmd->sess->transport_id),
++ cmd->sess->tgt->rel_tgt_id, reg, key, tgt_dev);
++
++ /* We already checked reg is not NULL */
++ if (reg->key != key) {
++ TRACE_PR("Registrant's %p key %016llx mismatch with %016llx",
++ reg, reg->key, key);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++
++ scst_pr_send_ua_all(dev, reg,
++ SCST_LOAD_SENSE(scst_sense_reservation_preempted));
++
++ list_for_each_entry_safe(r, t, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ scst_pr_remove_registrant(dev, r);
++ }
++
++ dev->pr_generation++;
++
++ scst_pr_dump_prs(dev, false);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void scst_pr_do_preempt(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size, bool abort)
++{
++ __be64 key, action_key;
++ int scope, type;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_dev_registrant *reg, *r, *rt;
++ int existing_pr_type = dev->pr_type;
++ int existing_pr_scope = dev->pr_scope;
++ LIST_HEAD(preempt_list);
++
++ TRACE_ENTRY();
++
++ key = get_unaligned((__be64 *)&buffer[0]);
++ action_key = get_unaligned((__be64 *)&buffer[8]);
++ scope = (cmd->cdb[2] & 0x0f) >> 4;
++ type = cmd->cdb[2] & 0x0f;
++
++ if (buffer_size != 24) {
++ TRACE_PR("Invalid buffer size %d", buffer_size);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_parameter_list_length_invalid));
++ goto out;
++ }
++
++ if (!scst_pr_type_valid(type)) {
++ TRACE_PR("Invalid reservation type %d", type);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++
++ reg = tgt_dev->registrant;
++
++ TRACE_PR("Preempt%s: initiator %s/%d (%p), key %016llx, action_key "
++ "%016llx, scope %x type %x (tgt_dev %p)",
++ abort ? " and abort" : "",
++ debug_transport_id_to_initiator_name(cmd->sess->transport_id),
++ cmd->sess->tgt->rel_tgt_id, reg, key, action_key, scope, type,
++ tgt_dev);
++
++ /* We already checked reg is not NULL */
++ if (reg->key != key) {
++ TRACE_PR("Registrant's %p key %016llx mismatch with %016llx",
++ reg, reg->key, key);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++ }
++
++ if (!dev->pr_is_set) {
++ scst_pr_find_registrants_list_key(dev, action_key,
++ &preempt_list);
++ if (list_empty(&preempt_list))
++ goto out_error;
++ list_for_each_entry_safe(r, rt, &preempt_list, aux_list_entry) {
++ if (abort)
++ scst_pr_abort_reg(dev, cmd, r);
++ if (r != reg) {
++ scst_pr_send_ua_reg(dev, r, SCST_LOAD_SENSE(
++ scst_sense_registrations_preempted));
++ scst_pr_remove_registrant(dev, r);
++ }
++ }
++ goto done;
++ }
++
++ if (dev->pr_type == TYPE_WRITE_EXCLUSIVE_ALL_REG ||
++ dev->pr_type == TYPE_EXCLUSIVE_ACCESS_ALL_REG) {
++ if (action_key == 0) {
++ scst_pr_find_registrants_list_all(dev, reg,
++ &preempt_list);
++ list_for_each_entry_safe(r, rt, &preempt_list,
++ aux_list_entry) {
++ BUG_ON(r == reg);
++ if (abort)
++ scst_pr_abort_reg(dev, cmd, r);
++ scst_pr_send_ua_reg(dev, r,
++ SCST_LOAD_SENSE(
++ scst_sense_registrations_preempted));
++ scst_pr_remove_registrant(dev, r);
++ }
++ scst_pr_set_holder(dev, reg, scope, type);
++ } else {
++ scst_pr_find_registrants_list_key(dev, action_key,
++ &preempt_list);
++ if (list_empty(&preempt_list))
++ goto out_error;
++ list_for_each_entry_safe(r, rt, &preempt_list,
++ aux_list_entry) {
++ if (abort)
++ scst_pr_abort_reg(dev, cmd, r);
++ if (r != reg) {
++ scst_pr_send_ua_reg(dev, r,
++ SCST_LOAD_SENSE(
++ scst_sense_registrations_preempted));
++ scst_pr_remove_registrant(dev, r);
++ }
++ }
++ }
++ goto done;
++ }
++
++ if (dev->pr_holder->key != action_key) {
++ if (action_key == 0) {
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_invalid_field_in_parm_list));
++ goto out;
++ } else {
++ scst_pr_find_registrants_list_key(dev, action_key,
++ &preempt_list);
++ if (list_empty(&preempt_list))
++ goto out_error;
++ list_for_each_entry_safe(r, rt, &preempt_list,
++ aux_list_entry) {
++ if (abort)
++ scst_pr_abort_reg(dev, cmd, r);
++ if (r != reg)
++ scst_pr_send_ua_reg(dev, r,
++ SCST_LOAD_SENSE(
++ scst_sense_registrations_preempted));
++ scst_pr_remove_registrant(dev, r);
++ }
++ goto done;
++ }
++ }
++
++ scst_pr_find_registrants_list_key(dev, action_key,
++ &preempt_list);
++
++ list_for_each_entry_safe(r, rt, &preempt_list, aux_list_entry) {
++ if (abort)
++ scst_pr_abort_reg(dev, cmd, r);
++ if (r != reg) {
++ scst_pr_send_ua_reg(dev, r, SCST_LOAD_SENSE(
++ scst_sense_registrations_preempted));
++ scst_pr_remove_registrant(dev, r);
++ }
++ }
++
++ scst_pr_set_holder(dev, reg, scope, type);
++
++ if (existing_pr_type != type || existing_pr_scope != scope) {
++ list_for_each_entry(r, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ if (r != reg)
++ scst_pr_send_ua_reg(dev, r, SCST_LOAD_SENSE(
++ scst_sense_reservation_released));
++ }
++ }
++
++done:
++ dev->pr_generation++;
++
++ scst_pr_dump_prs(dev, false);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_error:
++ TRACE_PR("Invalid key %016llx", action_key);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_preempt(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
++{
++ TRACE_ENTRY();
++
++ scst_pr_do_preempt(cmd, buffer, buffer_size, false);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void scst_cmd_done_pr_preempt(struct scst_cmd *cmd, int next_state,
++ enum scst_exec_context pref_context)
++{
++ void (*saved_cmd_done) (struct scst_cmd *cmd, int next_state,
++ enum scst_exec_context pref_context);
++
++ TRACE_ENTRY();
++
++ saved_cmd_done = NULL; /* to remove warning that it's used not inited */
++
++ if (cmd->pr_abort_counter != NULL) {
++ if (!atomic_dec_and_test(&cmd->pr_abort_counter->pr_abort_pending_cnt))
++ goto out;
++ saved_cmd_done = cmd->pr_abort_counter->saved_cmd_done;
++ kfree(cmd->pr_abort_counter);
++ cmd->pr_abort_counter = NULL;
++ }
++
++ saved_cmd_done(cmd, next_state, pref_context);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * Called with dev_pr_mutex locked, no IRQ. Expects session_list_lock
++ * not locked
++ */
++void scst_pr_preempt_and_abort(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size)
++{
++ TRACE_ENTRY();
++
++ cmd->pr_abort_counter = kzalloc(sizeof(*cmd->pr_abort_counter),
++ GFP_KERNEL);
++ if (cmd->pr_abort_counter == NULL) {
++ PRINT_ERROR("Unable to allocate PR abort counter (size %zd)",
++ sizeof(*cmd->pr_abort_counter));
++ scst_set_busy(cmd);
++ goto out;
++ }
++
++ /* 1 to protect cmd from be done by the TM thread too early */
++ atomic_set(&cmd->pr_abort_counter->pr_abort_pending_cnt, 1);
++ atomic_set(&cmd->pr_abort_counter->pr_aborting_cnt, 1);
++ init_completion(&cmd->pr_abort_counter->pr_aborting_cmpl);
++
++ cmd->pr_abort_counter->saved_cmd_done = cmd->scst_cmd_done;
++ cmd->scst_cmd_done = scst_cmd_done_pr_preempt;
++
++ scst_pr_do_preempt(cmd, buffer, buffer_size, true);
++
++ if (!atomic_dec_and_test(&cmd->pr_abort_counter->pr_aborting_cnt))
++ wait_for_completion(&cmd->pr_abort_counter->pr_aborting_cmpl);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Checks if this is a Compatible Reservation Handling (CRH) case */
++bool scst_pr_crh_case(struct scst_cmd *cmd)
++{
++ bool allowed;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_dev_registrant *reg;
++ uint8_t type;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Test if there is a CRH case for command %s (0x%x) from "
++ "%s", cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
++
++ if (!dev->pr_is_set) {
++ TRACE_PR("%s", "PR not set");
++ allowed = false;
++ goto out;
++ }
++
++ reg = tgt_dev->registrant;
++ type = dev->pr_type;
++
++ switch (type) {
++ case TYPE_WRITE_EXCLUSIVE:
++ case TYPE_EXCLUSIVE_ACCESS:
++ WARN_ON(dev->pr_holder == NULL);
++ if (reg == dev->pr_holder)
++ allowed = true;
++ else
++ allowed = false;
++ break;
++
++ case TYPE_WRITE_EXCLUSIVE_REGONLY:
++ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
++ case TYPE_WRITE_EXCLUSIVE_ALL_REG:
++ case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
++ allowed = (reg != NULL);
++ break;
++
++ default:
++ PRINT_ERROR("Invalid PR type %x", type);
++ allowed = false;
++ break;
++ }
++
++ if (!allowed)
++ TRACE_PR("Command %s (0x%x) from %s rejected due to not CRH "
++ "reservation", cmd->op_name, cmd->cdb[0],
++ cmd->sess->initiator_name);
++ else
++ TRACE_DBG("Command %s (0x%x) from %s is allowed to execute "
++ "due to CRH", cmd->op_name, cmd->cdb[0],
++ cmd->sess->initiator_name);
++
++out:
++ TRACE_EXIT_RES(allowed);
++ return allowed;
++
++}
++
++/* Check if command allowed in presence of reservation */
++bool scst_pr_is_cmd_allowed(struct scst_cmd *cmd)
++{
++ bool allowed;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_dev_registrant *reg;
++ uint8_t type;
++ bool unlock;
++
++ TRACE_ENTRY();
++
++ unlock = scst_pr_read_lock(dev);
++
++ TRACE_DBG("Testing if command %s (0x%x) from %s allowed to execute",
++ cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
++
++ /* Recheck, because it can change while we were waiting for the lock */
++ if (unlikely(!dev->pr_is_set)) {
++ allowed = true;
++ goto out_unlock;
++ }
++
++ reg = tgt_dev->registrant;
++ type = dev->pr_type;
++
++ switch (type) {
++ case TYPE_WRITE_EXCLUSIVE:
++ if (reg && reg == dev->pr_holder)
++ allowed = true;
++ else
++ allowed = (cmd->op_flags & SCST_WRITE_EXCL_ALLOWED) != 0;
++ break;
++
++ case TYPE_EXCLUSIVE_ACCESS:
++ if (reg && reg == dev->pr_holder)
++ allowed = true;
++ else
++ allowed = (cmd->op_flags & SCST_EXCL_ACCESS_ALLOWED) != 0;
++ break;
++
++ case TYPE_WRITE_EXCLUSIVE_REGONLY:
++ case TYPE_WRITE_EXCLUSIVE_ALL_REG:
++ if (reg)
++ allowed = true;
++ else
++ allowed = (cmd->op_flags & SCST_WRITE_EXCL_ALLOWED) != 0;
++ break;
++
++ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
++ case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
++ if (reg)
++ allowed = true;
++ else
++ allowed = (cmd->op_flags & SCST_EXCL_ACCESS_ALLOWED) != 0;
++ break;
++
++ default:
++ PRINT_ERROR("Invalid PR type %x", type);
++ allowed = false;
++ break;
++ }
++
++ if (!allowed)
++ TRACE_PR("Command %s (0x%x) from %s rejected due "
++ "to PR", cmd->op_name, cmd->cdb[0],
++ cmd->sess->initiator_name);
++ else
++ TRACE_DBG("Command %s (0x%x) from %s is allowed to execute",
++ cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
++
++out_unlock:
++ scst_pr_read_unlock(dev, unlock);
++
++ TRACE_EXIT_RES(allowed);
++ return allowed;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_read_keys(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
++{
++ int i, offset = 0, size, size_max;
++ struct scst_device *dev = cmd->dev;
++ struct scst_dev_registrant *reg;
++
++ TRACE_ENTRY();
++
++ if (buffer_size < 8) {
++ TRACE_PR("buffer_size too small: %d. expected >= 8 "
++ "(buffer %p)", buffer_size, buffer);
++ goto skip;
++ }
++
++ TRACE_PR("Read Keys (dev %s): PRGen %d", dev->virt_name,
++ dev->pr_generation);
++
++ put_unaligned(cpu_to_be32(dev->pr_generation), (__be32 *)&buffer[0]);
++
++ offset = 8;
++ size = 0;
++ size_max = buffer_size - 8;
++
++ i = 0;
++ list_for_each_entry(reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ if (size_max - size >= 8) {
++ TRACE_PR("Read Keys (dev %s): key 0x%llx",
++ dev->virt_name, reg->key);
++
++ WARN_ON(reg->key == 0);
++
++ put_unaligned(reg->key,
++ (__be64 *)&buffer[offset + 8 * i]);
++
++ offset += 8;
++ }
++ size += 8;
++ }
++
++ put_unaligned(cpu_to_be32(size), (__be32 *)&buffer[4]);
++
++skip:
++ scst_set_resp_data_len(cmd, offset);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_read_reservation(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size)
++{
++ struct scst_device *dev = cmd->dev;
++ uint8_t b[24];
++ int size = 0;
++
++ TRACE_ENTRY();
++
++ if (buffer_size < 8) {
++ TRACE_PR("buffer_size too small: %d. expected >= 8 "
++ "(buffer %p)", buffer_size, buffer);
++ goto skip;
++ }
++
++ memset(b, 0, sizeof(b));
++
++ put_unaligned(cpu_to_be32(dev->pr_generation), (__be32 *)&b[0]);
++
++ if (!dev->pr_is_set) {
++ TRACE_PR("Read Reservation: no reservations for dev %s",
++ dev->virt_name);
++ b[4] =
++ b[5] =
++ b[6] =
++ b[7] = 0;
++
++ size = 8;
++ } else {
++ __be64 key = dev->pr_holder ? dev->pr_holder->key : 0;
++
++ TRACE_PR("Read Reservation: dev %s, holder %p, key 0x%llx, "
++ "scope %d, type %d", dev->virt_name, dev->pr_holder,
++ key, dev->pr_scope, dev->pr_type);
++
++ b[4] =
++ b[5] =
++ b[6] = 0;
++ b[7] = 0x10;
++
++ put_unaligned(key, (__be64 *)&b[8]);
++ b[21] = dev->pr_scope << 4 | dev->pr_type;
++
++ size = 24;
++ }
++
++ memset(buffer, 0, buffer_size);
++ memcpy(buffer, b, min(size, buffer_size));
++
++skip:
++ scst_set_resp_data_len(cmd, size);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_report_caps(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
++{
++ int offset = 0;
++ unsigned int crh = 1;
++ unsigned int atp_c = 1;
++ unsigned int sip_c = 1;
++ unsigned int ptpl_c = 1;
++ struct scst_device *dev = cmd->dev;
++
++ TRACE_ENTRY();
++
++ if (buffer_size < 8) {
++ TRACE_PR("buffer_size too small: %d. expected >= 8 "
++ "(buffer %p)", buffer_size, buffer);
++ goto skip;
++ }
++
++ TRACE_PR("Reporting capabilities (dev %s): crh %x, sip_c %x, "
++ "atp_c %x, ptpl_c %x, pr_aptpl %x", dev->virt_name,
++ crh, sip_c, atp_c, ptpl_c, dev->pr_aptpl);
++
++ buffer[0] = 0;
++ buffer[1] = 8;
++
++ buffer[2] = crh << 4 | sip_c << 3 | atp_c << 2 | ptpl_c;
++ buffer[3] = (1 << 7) | (dev->pr_aptpl > 0 ? 1 : 0);
++
++ /* All commands supported */
++ buffer[4] = 0xEA;
++ buffer[5] = 0x1;
++
++ offset += 8;
++
++skip:
++ scst_set_resp_data_len(cmd, offset);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called with dev_pr_mutex locked, no IRQ */
++void scst_pr_read_full_status(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size)
++{
++ int offset = 0, size, size_max;
++ struct scst_device *dev = cmd->dev;
++ struct scst_dev_registrant *reg;
++
++ TRACE_ENTRY();
++
++ if (buffer_size < 8)
++ goto skip;
++
++ put_unaligned(cpu_to_be32(dev->pr_generation), (__be32 *)&buffer[0]);
++ offset += 8;
++
++ size = 0;
++ size_max = buffer_size - 8;
++
++ list_for_each_entry(reg, &dev->dev_registrants_list,
++ dev_registrants_list_entry) {
++ int ts;
++ int rec_len;
++
++ ts = tid_size(reg->transport_id);
++ rec_len = 24 + ts;
++
++ if (size_max - size > rec_len) {
++ memset(&buffer[offset], 0, rec_len);
++
++ put_unaligned(reg->key, (__be64 *)(&buffer[offset]));
++
++ if (dev->pr_is_set && scst_pr_is_holder(dev, reg)) {
++ buffer[offset + 12] = 1;
++ buffer[offset + 13] = (dev->pr_scope << 8) | dev->pr_type;
++ }
++
++ put_unaligned(cpu_to_be16(reg->rel_tgt_id),
++ (__be16 *)&buffer[offset + 18]);
++ put_unaligned(cpu_to_be32(ts),
++ (__be32 *)&buffer[offset + 20]);
++
++ memcpy(&buffer[offset + 24], reg->transport_id, ts);
++
++ offset += rec_len;
++ }
++ size += rec_len;
++ }
++
++ put_unaligned(cpu_to_be32(size), (__be32 *)&buffer[4]);
++
++skip:
++ scst_set_resp_data_len(cmd, offset);
++
++ TRACE_EXIT();
++ return;
++}
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_pres.h linux-2.6.36/drivers/scst/scst_pres.h
+--- orig/linux-2.6.36/drivers/scst/scst_pres.h
++++ linux-2.6.36/drivers/scst/scst_pres.h
+@@ -0,0 +1,170 @@
++/*
++ * scst_pres.c
++ *
++ * Copyright (C) 2009 - 2010 Alexey Obitotskiy <alexeyo1@open-e.com>
++ * Copyright (C) 2009 - 2010 Open-E, Inc.
++ * Copyright (C) 2009 - 2011 Vladislav Bolkhovitin <vst@vlnb.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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef SCST_PRES_H_
++#define SCST_PRES_H_
++
++#include <linux/delay.h>
++
++#define PR_REGISTER 0x00
++#define PR_RESERVE 0x01
++#define PR_RELEASE 0x02
++#define PR_CLEAR 0x03
++#define PR_PREEMPT 0x04
++#define PR_PREEMPT_AND_ABORT 0x05
++#define PR_REGISTER_AND_IGNORE 0x06
++#define PR_REGISTER_AND_MOVE 0x07
++
++#define PR_READ_KEYS 0x00
++#define PR_READ_RESERVATION 0x01
++#define PR_REPORT_CAPS 0x02
++#define PR_READ_FULL_STATUS 0x03
++
++#define TYPE_UNSPECIFIED (-1)
++#define TYPE_WRITE_EXCLUSIVE 0x01
++#define TYPE_EXCLUSIVE_ACCESS 0x03
++#define TYPE_WRITE_EXCLUSIVE_REGONLY 0x05
++#define TYPE_EXCLUSIVE_ACCESS_REGONLY 0x06
++#define TYPE_WRITE_EXCLUSIVE_ALL_REG 0x07
++#define TYPE_EXCLUSIVE_ACCESS_ALL_REG 0x08
++
++#define SCOPE_LU 0x00
++
++static inline bool scst_pr_type_valid(uint8_t type)
++{
++ switch (type) {
++ case TYPE_WRITE_EXCLUSIVE:
++ case TYPE_EXCLUSIVE_ACCESS:
++ case TYPE_WRITE_EXCLUSIVE_REGONLY:
++ case TYPE_EXCLUSIVE_ACCESS_REGONLY:
++ case TYPE_WRITE_EXCLUSIVE_ALL_REG:
++ case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
++ return true;
++ default:
++ return false;
++ }
++}
++
++static inline bool scst_pr_read_lock(struct scst_device *dev)
++{
++ bool unlock = false;
++
++ TRACE_ENTRY();
++
++ atomic_inc(&dev->pr_readers_count);
++ smp_mb__after_atomic_inc(); /* to sync with scst_pr_write_lock() */
++
++ if (unlikely(dev->pr_writer_active)) {
++ unlock = true;
++ atomic_dec(&dev->pr_readers_count);
++ mutex_lock(&dev->dev_pr_mutex);
++ }
++
++ TRACE_EXIT_RES(unlock);
++ return unlock;
++}
++
++static inline void scst_pr_read_unlock(struct scst_device *dev, bool unlock)
++{
++ TRACE_ENTRY();
++
++ if (unlikely(unlock))
++ mutex_unlock(&dev->dev_pr_mutex);
++ else {
++ /*
++ * To sync with scst_pr_write_lock(). We need it to ensure
++ * order of our reads with the writer's writes.
++ */
++ smp_mb__before_atomic_dec();
++ atomic_dec(&dev->pr_readers_count);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline void scst_pr_write_lock(struct scst_device *dev)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&dev->dev_pr_mutex);
++
++ dev->pr_writer_active = 1;
++
++ /* to sync with scst_pr_read_lock() and unlock() */
++ smp_mb();
++
++ while (atomic_read(&dev->pr_readers_count) != 0) {
++ TRACE_DBG("Waiting for %d readers (dev %p)",
++ atomic_read(&dev->pr_readers_count), dev);
++ msleep(1);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline void scst_pr_write_unlock(struct scst_device *dev)
++{
++ TRACE_ENTRY();
++
++ dev->pr_writer_active = 0;
++
++ mutex_unlock(&dev->dev_pr_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++
++int scst_pr_init_dev(struct scst_device *dev);
++void scst_pr_clear_dev(struct scst_device *dev);
++
++int scst_pr_init_tgt_dev(struct scst_tgt_dev *tgt_dev);
++void scst_pr_clear_tgt_dev(struct scst_tgt_dev *tgt_dev);
++
++bool scst_pr_crh_case(struct scst_cmd *cmd);
++bool scst_pr_is_cmd_allowed(struct scst_cmd *cmd);
++
++void scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
++void scst_pr_register_and_ignore(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size);
++void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size);
++void scst_pr_reserve(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
++void scst_pr_release(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
++void scst_pr_clear(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
++void scst_pr_preempt(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
++void scst_pr_preempt_and_abort(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size);
++
++void scst_pr_read_keys(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
++void scst_pr_read_reservation(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size);
++void scst_pr_report_caps(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
++void scst_pr_read_full_status(struct scst_cmd *cmd, uint8_t *buffer,
++ int buffer_size);
++
++void scst_pr_sync_device_file(struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd);
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++void scst_pr_dump_prs(struct scst_device *dev, bool force);
++#else
++static inline void scst_pr_dump_prs(struct scst_device *dev, bool force) {}
++#endif
++
++#endif /* SCST_PRES_H_ */
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_priv.h linux-2.6.36/drivers/scst/scst_priv.h
+--- orig/linux-2.6.36/drivers/scst/scst_priv.h
++++ linux-2.6.36/drivers/scst/scst_priv.h
+@@ -0,0 +1,603 @@
++/*
++ * scst_priv.h
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef __SCST_PRIV_H
++#define __SCST_PRIV_H
++
++#include <linux/types.h>
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_driver.h>
++#include <scsi/scsi_device.h>
++#include <scsi/scsi_host.h>
++
++#define LOG_PREFIX "scst"
++
++#include <scst/scst_debug.h>
++
++#define TRACE_RTRY 0x80000000
++#define TRACE_SCSI_SERIALIZING 0x40000000
++/** top being the edge away from the interupt */
++#define TRACE_SND_TOP 0x20000000
++#define TRACE_RCV_TOP 0x01000000
++/** bottom being the edge toward the interupt */
++#define TRACE_SND_BOT 0x08000000
++#define TRACE_RCV_BOT 0x04000000
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++#define trace_flag scst_trace_flag
++extern unsigned long scst_trace_flag;
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++
++#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR | TRACE_PID | \
++ TRACE_LINE | TRACE_FUNCTION | TRACE_SPECIAL | TRACE_MGMT | \
++ TRACE_MGMT_DEBUG | TRACE_RTRY)
++
++#define TRACE_RETRY(args...) TRACE_DBG_FLAG(TRACE_RTRY, args)
++#define TRACE_SN(args...) TRACE_DBG_FLAG(TRACE_SCSI_SERIALIZING, args)
++#define TRACE_SEND_TOP(args...) TRACE_DBG_FLAG(TRACE_SND_TOP, args)
++#define TRACE_RECV_TOP(args...) TRACE_DBG_FLAG(TRACE_RCV_TOP, args)
++#define TRACE_SEND_BOT(args...) TRACE_DBG_FLAG(TRACE_SND_BOT, args)
++#define TRACE_RECV_BOT(args...) TRACE_DBG_FLAG(TRACE_RCV_BOT, args)
++
++#else /* CONFIG_SCST_DEBUG */
++
++# ifdef CONFIG_SCST_TRACING
++#define SCST_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
++ TRACE_SPECIAL)
++# else
++#define SCST_DEFAULT_LOG_FLAGS 0
++# endif
++
++#define TRACE_RETRY(args...)
++#define TRACE_SN(args...)
++#define TRACE_SEND_TOP(args...)
++#define TRACE_RECV_TOP(args...)
++#define TRACE_SEND_BOT(args...)
++#define TRACE_RECV_BOT(args...)
++
++#endif
++
++/**
++ ** Bits for scst_flags
++ **/
++
++/*
++ * Set if new commands initialization is being suspended for a while.
++ * Used to let TM commands execute while preparing the suspend, since
++ * RESET or ABORT could be necessary to free SCSI commands.
++ */
++#define SCST_FLAG_SUSPENDING 0
++
++/* Set if new commands initialization is suspended for a while */
++#define SCST_FLAG_SUSPENDED 1
++
++/**
++ ** Return codes for cmd state process functions. Codes are the same as
++ ** for SCST_EXEC_* to avoid translation to them and, hence, have better code.
++ **/
++#define SCST_CMD_STATE_RES_CONT_NEXT SCST_EXEC_COMPLETED
++#define SCST_CMD_STATE_RES_CONT_SAME SCST_EXEC_NOT_COMPLETED
++#define SCST_CMD_STATE_RES_NEED_THREAD (SCST_EXEC_NOT_COMPLETED+1)
++
++/**
++ ** Maximum count of uncompleted commands that an initiator could
++ ** queue on any device. Then it will start getting TASK QUEUE FULL status.
++ **/
++#define SCST_MAX_TGT_DEV_COMMANDS 48
++
++/**
++ ** Maximum count of uncompleted commands that could be queued on any device.
++ ** Then initiators sending commands to this device will start getting
++ ** TASK QUEUE FULL status.
++ **/
++#define SCST_MAX_DEV_COMMANDS 256
++
++#define SCST_TGT_RETRY_TIMEOUT (3/2*HZ)
++
++/* Definitions of symbolic constants for LUN addressing method */
++#define SCST_LUN_ADDR_METHOD_PERIPHERAL 0
++#define SCST_LUN_ADDR_METHOD_FLAT 1
++
++/* Activities suspending timeout */
++#define SCST_SUSPENDING_TIMEOUT (90 * HZ)
++
++extern struct mutex scst_mutex2;
++
++extern int scst_threads;
++
++extern unsigned int scst_max_dev_cmd_mem;
++
++extern mempool_t *scst_mgmt_mempool;
++extern mempool_t *scst_mgmt_stub_mempool;
++extern mempool_t *scst_ua_mempool;
++extern mempool_t *scst_sense_mempool;
++extern mempool_t *scst_aen_mempool;
++
++extern struct kmem_cache *scst_cmd_cachep;
++extern struct kmem_cache *scst_sess_cachep;
++extern struct kmem_cache *scst_tgtd_cachep;
++extern struct kmem_cache *scst_acgd_cachep;
++
++extern spinlock_t scst_main_lock;
++
++extern struct scst_sgv_pools scst_sgv;
++
++extern unsigned long scst_flags;
++extern atomic_t scst_cmd_count;
++extern struct list_head scst_template_list;
++extern struct list_head scst_dev_list;
++extern struct list_head scst_dev_type_list;
++extern struct list_head scst_virtual_dev_type_list;
++extern wait_queue_head_t scst_dev_cmd_waitQ;
++
++extern unsigned int scst_setup_id;
++
++#define SCST_DEF_MAX_TASKLET_CMD 20
++extern int scst_max_tasklet_cmd;
++
++extern spinlock_t scst_init_lock;
++extern struct list_head scst_init_cmd_list;
++extern wait_queue_head_t scst_init_cmd_list_waitQ;
++extern unsigned int scst_init_poll_cnt;
++
++extern struct scst_cmd_threads scst_main_cmd_threads;
++
++extern spinlock_t scst_mcmd_lock;
++/* The following lists protected by scst_mcmd_lock */
++extern struct list_head scst_active_mgmt_cmd_list;
++extern struct list_head scst_delayed_mgmt_cmd_list;
++extern wait_queue_head_t scst_mgmt_cmd_list_waitQ;
++
++struct scst_tasklet {
++ spinlock_t tasklet_lock;
++ struct list_head tasklet_cmd_list;
++ struct tasklet_struct tasklet;
++};
++extern struct scst_tasklet scst_tasklets[NR_CPUS];
++
++extern wait_queue_head_t scst_mgmt_waitQ;
++extern spinlock_t scst_mgmt_lock;
++extern struct list_head scst_sess_init_list;
++extern struct list_head scst_sess_shut_list;
++
++struct scst_cmd_thread_t {
++ struct task_struct *cmd_thread;
++ struct list_head thread_list_entry;
++};
++
++static inline bool scst_set_io_context(struct scst_cmd *cmd,
++ struct io_context **old)
++{
++ bool res;
++
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ return false;
++#endif
++
++ if (cmd->cmd_threads == &scst_main_cmd_threads) {
++ EXTRACHECKS_BUG_ON(in_interrupt());
++ /*
++ * No need for any ref counting action, because io_context
++ * supposed to be cleared in the end of the caller function.
++ */
++ current->io_context = cmd->tgt_dev->async_io_context;
++ res = true;
++ TRACE_DBG("io_context %p (tgt_dev %p)", current->io_context,
++ cmd->tgt_dev);
++ EXTRACHECKS_BUG_ON(current->io_context == NULL);
++ } else
++ res = false;
++
++ return res;
++}
++
++static inline void scst_reset_io_context(struct scst_tgt_dev *tgt_dev,
++ struct io_context *old)
++{
++ current->io_context = old;
++ TRACE_DBG("io_context %p reset", current->io_context);
++ return;
++}
++
++/*
++ * Converts string presentation of threads pool type to enum.
++ * Returns SCST_THREADS_POOL_TYPE_INVALID if the string is invalid.
++ */
++extern enum scst_dev_type_threads_pool_type scst_parse_threads_pool_type(
++ const char *p, int len);
++
++extern int scst_add_threads(struct scst_cmd_threads *cmd_threads,
++ struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num);
++extern void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num);
++
++extern int scst_create_dev_threads(struct scst_device *dev);
++extern void scst_stop_dev_threads(struct scst_device *dev);
++
++extern int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev);
++extern void scst_tgt_dev_stop_threads(struct scst_tgt_dev *tgt_dev);
++
++extern bool scst_del_thr_data(struct scst_tgt_dev *tgt_dev,
++ struct task_struct *tsk);
++
++extern struct scst_dev_type scst_null_devtype;
++
++extern struct scst_cmd *__scst_check_deferred_commands(
++ struct scst_tgt_dev *tgt_dev);
++
++/* Used to save the function call on the fast path */
++static inline struct scst_cmd *scst_check_deferred_commands(
++ struct scst_tgt_dev *tgt_dev)
++{
++ if (tgt_dev->def_cmd_count == 0)
++ return NULL;
++ else
++ return __scst_check_deferred_commands(tgt_dev);
++}
++
++static inline void scst_make_deferred_commands_active(
++ struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_cmd *c;
++
++ c = __scst_check_deferred_commands(tgt_dev);
++ if (c != NULL) {
++ TRACE_SN("Adding cmd %p to active cmd list", c);
++ spin_lock_irq(&c->cmd_threads->cmd_list_lock);
++ list_add_tail(&c->cmd_list_entry,
++ &c->cmd_threads->active_cmd_list);
++ wake_up(&c->cmd_threads->cmd_list_waitQ);
++ spin_unlock_irq(&c->cmd_threads->cmd_list_lock);
++ }
++
++ return;
++}
++
++void scst_inc_expected_sn(struct scst_tgt_dev *tgt_dev, atomic_t *slot);
++int scst_check_hq_cmd(struct scst_cmd *cmd);
++
++void scst_unblock_deferred(struct scst_tgt_dev *tgt_dev,
++ struct scst_cmd *cmd_sn);
++
++void scst_on_hq_cmd_response(struct scst_cmd *cmd);
++void scst_xmit_process_aborted_cmd(struct scst_cmd *cmd);
++
++int scst_cmd_thread(void *arg);
++void scst_cmd_tasklet(long p);
++int scst_init_thread(void *arg);
++int scst_tm_thread(void *arg);
++int scst_global_mgmt_thread(void *arg);
++
++void scst_zero_write_rest(struct scst_cmd *cmd);
++void scst_limit_sg_write_len(struct scst_cmd *cmd);
++void scst_adjust_resp_data_len(struct scst_cmd *cmd);
++
++int scst_queue_retry_cmd(struct scst_cmd *cmd, int finished_cmds);
++
++int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt);
++void scst_free_tgt(struct scst_tgt *tgt);
++
++int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev);
++void scst_free_device(struct scst_device *dev);
++
++struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
++ const char *acg_name, bool tgt_acg);
++void scst_del_free_acg(struct scst_acg *acg);
++
++struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name);
++struct scst_acg *scst_find_acg(const struct scst_session *sess);
++
++void scst_check_reassign_sessions(void);
++
++int scst_sess_alloc_tgt_devs(struct scst_session *sess);
++void scst_sess_free_tgt_devs(struct scst_session *sess);
++void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA);
++
++int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
++ struct scst_device *dev, uint64_t lun, int read_only,
++ bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev);
++int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
++ bool gen_scst_report_luns_changed);
++
++int scst_acg_add_acn(struct scst_acg *acg, const char *name);
++void scst_del_free_acn(struct scst_acn *acn, bool reassign);
++struct scst_acn *scst_find_acn(struct scst_acg *acg, const char *name);
++
++/* The activity supposed to be suspended and scst_mutex held */
++static inline bool scst_acg_sess_is_empty(struct scst_acg *acg)
++{
++ return list_empty(&acg->acg_sess_list);
++}
++
++int scst_prepare_request_sense(struct scst_cmd *orig_cmd);
++int scst_finish_internal_cmd(struct scst_cmd *cmd);
++
++void scst_store_sense(struct scst_cmd *cmd);
++
++int scst_assign_dev_handler(struct scst_device *dev,
++ struct scst_dev_type *handler);
++
++struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
++ const char *initiator_name);
++void scst_free_session(struct scst_session *sess);
++void scst_free_session_callback(struct scst_session *sess);
++
++struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask);
++void scst_free_cmd(struct scst_cmd *cmd);
++static inline void scst_destroy_cmd(struct scst_cmd *cmd)
++{
++ kmem_cache_free(scst_cmd_cachep, cmd);
++ return;
++}
++
++void scst_check_retries(struct scst_tgt *tgt);
++
++int scst_scsi_exec_async(struct scst_cmd *cmd,
++ void (*done)(void *, char *, int, int));
++
++int scst_alloc_space(struct scst_cmd *cmd);
++
++int scst_lib_init(void);
++void scst_lib_exit(void);
++
++int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf);
++void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf);
++
++__be64 scst_pack_lun(const uint64_t lun, unsigned int addr_method);
++uint64_t scst_unpack_lun(const uint8_t *lun, int len);
++
++struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask);
++void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd);
++void scst_done_cmd_mgmt(struct scst_cmd *cmd);
++
++static inline void scst_devt_cleanup(struct scst_dev_type *devt) { }
++
++int scst_sysfs_init(void);
++void scst_sysfs_cleanup(void);
++int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt);
++void scst_tgtt_sysfs_del(struct scst_tgt_template *tgtt);
++int scst_tgt_sysfs_create(struct scst_tgt *tgt);
++void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt);
++void scst_tgt_sysfs_del(struct scst_tgt *tgt);
++int scst_sess_sysfs_create(struct scst_session *sess);
++void scst_sess_sysfs_del(struct scst_session *sess);
++int scst_recreate_sess_luns_link(struct scst_session *sess);
++int scst_sgv_sysfs_create(struct sgv_pool *pool);
++void scst_sgv_sysfs_del(struct sgv_pool *pool);
++int scst_devt_sysfs_create(struct scst_dev_type *devt);
++void scst_devt_sysfs_del(struct scst_dev_type *devt);
++int scst_dev_sysfs_create(struct scst_device *dev);
++void scst_dev_sysfs_del(struct scst_device *dev);
++int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev);
++void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev);
++int scst_devt_dev_sysfs_create(struct scst_device *dev);
++void scst_devt_dev_sysfs_del(struct scst_device *dev);
++int scst_acg_sysfs_create(struct scst_tgt *tgt,
++ struct scst_acg *acg);
++void scst_acg_sysfs_del(struct scst_acg *acg);
++int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
++ struct kobject *parent);
++void scst_acg_dev_sysfs_del(struct scst_acg_dev *acg_dev);
++int scst_acn_sysfs_create(struct scst_acn *acn);
++void scst_acn_sysfs_del(struct scst_acn *acn);
++
++void __scst_dev_check_set_UA(struct scst_device *dev, struct scst_cmd *exclude,
++ const uint8_t *sense, int sense_len);
++static inline void scst_dev_check_set_UA(struct scst_device *dev,
++ struct scst_cmd *exclude, const uint8_t *sense, int sense_len)
++{
++ spin_lock_bh(&dev->dev_lock);
++ __scst_dev_check_set_UA(dev, exclude, sense, sense_len);
++ spin_unlock_bh(&dev->dev_lock);
++ return;
++}
++void scst_dev_check_set_local_UA(struct scst_device *dev,
++ struct scst_cmd *exclude, const uint8_t *sense, int sense_len);
++
++#define SCST_SET_UA_FLAG_AT_HEAD 1
++#define SCST_SET_UA_FLAG_GLOBAL 2
++
++void scst_check_set_UA(struct scst_tgt_dev *tgt_dev,
++ const uint8_t *sense, int sense_len, int flags);
++int scst_set_pending_UA(struct scst_cmd *cmd);
++
++void scst_report_luns_changed(struct scst_acg *acg);
++
++void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
++ bool other_ini, bool call_dev_task_mgmt_fn);
++void scst_process_reset(struct scst_device *dev,
++ struct scst_session *originator, struct scst_cmd *exclude_cmd,
++ struct scst_mgmt_cmd *mcmd, bool setUA);
++
++bool scst_is_ua_global(const uint8_t *sense, int len);
++void scst_requeue_ua(struct scst_cmd *cmd);
++
++void scst_gen_aen_or_ua(struct scst_tgt_dev *tgt_dev,
++ int key, int asc, int ascq);
++
++static inline bool scst_is_implicit_hq(struct scst_cmd *cmd)
++{
++ return (cmd->op_flags & SCST_IMPLICIT_HQ) != 0;
++}
++
++/*
++ * Some notes on devices "blocking". Blocking means that no
++ * commands will go from SCST to underlying SCSI device until it
++ * is unblocked. But we don't care about all commands that
++ * already on the device.
++ */
++
++extern void scst_block_dev(struct scst_device *dev);
++extern void scst_unblock_dev(struct scst_device *dev);
++
++extern bool __scst_check_blocked_dev(struct scst_cmd *cmd);
++
++static inline bool scst_check_blocked_dev(struct scst_cmd *cmd)
++{
++ if (unlikely(cmd->dev->block_count > 0) ||
++ unlikely(cmd->dev->dev_double_ua_possible))
++ return __scst_check_blocked_dev(cmd);
++ else
++ return false;
++}
++
++/* No locks */
++static inline void scst_check_unblock_dev(struct scst_cmd *cmd)
++{
++ if (unlikely(cmd->unblock_dev)) {
++ TRACE_MGMT_DBG("cmd %p (tag %llu): unblocking dev %p", cmd,
++ (long long unsigned int)cmd->tag, cmd->dev);
++ cmd->unblock_dev = 0;
++ scst_unblock_dev(cmd->dev);
++ }
++ return;
++}
++
++static inline void __scst_get(void)
++{
++ atomic_inc(&scst_cmd_count);
++ TRACE_DBG("Incrementing scst_cmd_count(new value %d)",
++ atomic_read(&scst_cmd_count));
++ /* See comment about smp_mb() in scst_suspend_activity() */
++ smp_mb__after_atomic_inc();
++}
++
++static inline void __scst_put(void)
++{
++ int f;
++ f = atomic_dec_and_test(&scst_cmd_count);
++ /* See comment about smp_mb() in scst_suspend_activity() */
++ if (f && unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags))) {
++ TRACE_MGMT_DBG("%s", "Waking up scst_dev_cmd_waitQ");
++ wake_up_all(&scst_dev_cmd_waitQ);
++ }
++ TRACE_DBG("Decrementing scst_cmd_count(new value %d)",
++ atomic_read(&scst_cmd_count));
++}
++
++void scst_sched_session_free(struct scst_session *sess);
++
++static inline void scst_sess_get(struct scst_session *sess)
++{
++ atomic_inc(&sess->refcnt);
++ TRACE_DBG("Incrementing sess %p refcnt (new value %d)",
++ sess, atomic_read(&sess->refcnt));
++}
++
++static inline void scst_sess_put(struct scst_session *sess)
++{
++ TRACE_DBG("Decrementing sess %p refcnt (new value %d)",
++ sess, atomic_read(&sess->refcnt)-1);
++ if (atomic_dec_and_test(&sess->refcnt))
++ scst_sched_session_free(sess);
++}
++
++static inline void __scst_cmd_get(struct scst_cmd *cmd)
++{
++ atomic_inc(&cmd->cmd_ref);
++ TRACE_DBG("Incrementing cmd %p ref (new value %d)",
++ cmd, atomic_read(&cmd->cmd_ref));
++}
++
++static inline void __scst_cmd_put(struct scst_cmd *cmd)
++{
++ TRACE_DBG("Decrementing cmd %p ref (new value %d)",
++ cmd, atomic_read(&cmd->cmd_ref)-1);
++ if (atomic_dec_and_test(&cmd->cmd_ref))
++ scst_free_cmd(cmd);
++}
++
++extern void scst_throttle_cmd(struct scst_cmd *cmd);
++extern void scst_unthrottle_cmd(struct scst_cmd *cmd);
++
++#ifdef CONFIG_SCST_DEBUG_TM
++extern void tm_dbg_check_released_cmds(void);
++extern int tm_dbg_check_cmd(struct scst_cmd *cmd);
++extern void tm_dbg_release_cmd(struct scst_cmd *cmd);
++extern void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn,
++ int force);
++extern int tm_dbg_is_release(void);
++#else
++static inline void tm_dbg_check_released_cmds(void) {}
++static inline int tm_dbg_check_cmd(struct scst_cmd *cmd)
++{
++ return 0;
++}
++static inline void tm_dbg_release_cmd(struct scst_cmd *cmd) {}
++static inline void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn,
++ int force) {}
++static inline int tm_dbg_is_release(void)
++{
++ return 0;
++}
++#endif /* CONFIG_SCST_DEBUG_TM */
++
++#ifdef CONFIG_SCST_DEBUG_SN
++void scst_check_debug_sn(struct scst_cmd *cmd);
++#else
++static inline void scst_check_debug_sn(struct scst_cmd *cmd) {}
++#endif
++
++static inline int scst_sn_before(uint32_t seq1, uint32_t seq2)
++{
++ return (int32_t)(seq1-seq2) < 0;
++}
++
++int gen_relative_target_port_id(uint16_t *id);
++bool scst_is_relative_target_port_id_unique(uint16_t id,
++ const struct scst_tgt *t);
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++
++void scst_set_start_time(struct scst_cmd *cmd);
++void scst_set_cur_start(struct scst_cmd *cmd);
++void scst_set_parse_time(struct scst_cmd *cmd);
++void scst_set_alloc_buf_time(struct scst_cmd *cmd);
++void scst_set_restart_waiting_time(struct scst_cmd *cmd);
++void scst_set_rdy_to_xfer_time(struct scst_cmd *cmd);
++void scst_set_pre_exec_time(struct scst_cmd *cmd);
++void scst_set_exec_time(struct scst_cmd *cmd);
++void scst_set_dev_done_time(struct scst_cmd *cmd);
++void scst_set_xmit_time(struct scst_cmd *cmd);
++void scst_set_tgt_on_free_time(struct scst_cmd *cmd);
++void scst_set_dev_on_free_time(struct scst_cmd *cmd);
++void scst_update_lat_stats(struct scst_cmd *cmd);
++
++#else
++
++static inline void scst_set_start_time(struct scst_cmd *cmd) {}
++static inline void scst_set_cur_start(struct scst_cmd *cmd) {}
++static inline void scst_set_parse_time(struct scst_cmd *cmd) {}
++static inline void scst_set_alloc_buf_time(struct scst_cmd *cmd) {}
++static inline void scst_set_restart_waiting_time(struct scst_cmd *cmd) {}
++static inline void scst_set_rdy_to_xfer_time(struct scst_cmd *cmd) {}
++static inline void scst_set_pre_exec_time(struct scst_cmd *cmd) {}
++static inline void scst_set_exec_time(struct scst_cmd *cmd) {}
++static inline void scst_set_dev_done_time(struct scst_cmd *cmd) {}
++static inline void scst_set_xmit_time(struct scst_cmd *cmd) {}
++static inline void scst_set_tgt_on_free_time(struct scst_cmd *cmd) {}
++static inline void scst_set_dev_on_free_time(struct scst_cmd *cmd) {}
++static inline void scst_update_lat_stats(struct scst_cmd *cmd) {}
++
++#endif /* CONFIG_SCST_MEASURE_LATENCY */
++
++#endif /* __SCST_PRIV_H */
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_sysfs.c linux-2.6.36/drivers/scst/scst_sysfs.c
+--- orig/linux-2.6.36/drivers/scst/scst_sysfs.c
++++ linux-2.6.36/drivers/scst/scst_sysfs.c
+@@ -0,0 +1,5336 @@
++/*
++ * scst_sysfs.c
++ *
++ * Copyright (C) 2009 Daniel Henrique Debonzi <debonzi@linux.vnet.ibm.com>
++ * Copyright (C) 2009 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2009 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/kobject.h>
++#include <linux/string.h>
++#include <linux/sysfs.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/ctype.h>
++#include <linux/slab.h>
++#include <linux/kthread.h>
++
++#include <scst/scst.h>
++#include "scst_priv.h"
++#include "scst_mem.h"
++#include "scst_pres.h"
++
++static DECLARE_COMPLETION(scst_sysfs_root_release_completion);
++
++static struct kobject scst_sysfs_root_kobj;
++static struct kobject *scst_targets_kobj;
++static struct kobject *scst_devices_kobj;
++static struct kobject *scst_sgv_kobj;
++static struct kobject *scst_handlers_kobj;
++
++static const char *scst_dev_handler_types[] = {
++ "Direct-access device (e.g., magnetic disk)",
++ "Sequential-access device (e.g., magnetic tape)",
++ "Printer device",
++ "Processor device",
++ "Write-once device (e.g., some optical disks)",
++ "CD-ROM device",
++ "Scanner device (obsolete)",
++ "Optical memory device (e.g., some optical disks)",
++ "Medium changer device (e.g., jukeboxes)",
++ "Communications device (obsolete)",
++ "Defined by ASC IT8 (Graphic arts pre-press devices)",
++ "Defined by ASC IT8 (Graphic arts pre-press devices)",
++ "Storage array controller device (e.g., RAID)",
++ "Enclosure services device",
++ "Simplified direct-access device (e.g., magnetic disk)",
++ "Optical card reader/writer device"
++};
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++static DEFINE_MUTEX(scst_log_mutex);
++
++static struct scst_trace_log scst_trace_tbl[] = {
++ { TRACE_OUT_OF_MEM, "out_of_mem" },
++ { TRACE_MINOR, "minor" },
++ { TRACE_SG_OP, "sg" },
++ { TRACE_MEMORY, "mem" },
++ { TRACE_BUFF, "buff" },
++#ifndef GENERATING_UPSTREAM_PATCH
++ { TRACE_ENTRYEXIT, "entryexit" },
++#endif
++ { TRACE_PID, "pid" },
++ { TRACE_LINE, "line" },
++ { TRACE_FUNCTION, "function" },
++ { TRACE_DEBUG, "debug" },
++ { TRACE_SPECIAL, "special" },
++ { TRACE_SCSI, "scsi" },
++ { TRACE_MGMT, "mgmt" },
++ { TRACE_MGMT_DEBUG, "mgmt_dbg" },
++ { TRACE_FLOW_CONTROL, "flow_control" },
++ { TRACE_PRES, "pr" },
++ { 0, NULL }
++};
++
++static struct scst_trace_log scst_local_trace_tbl[] = {
++ { TRACE_RTRY, "retry" },
++ { TRACE_SCSI_SERIALIZING, "scsi_serializing" },
++ { TRACE_RCV_BOT, "recv_bot" },
++ { TRACE_SND_BOT, "send_bot" },
++ { TRACE_RCV_TOP, "recv_top" },
++ { TRACE_SND_TOP, "send_top" },
++ { 0, NULL }
++};
++
++static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
++ unsigned long log_level, char *buf, const char *help);
++static int scst_write_trace(const char *buf, size_t length,
++ unsigned long *log_level, unsigned long default_level,
++ const char *name, const struct scst_trace_log *tbl);
++
++#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
++
++static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf);
++static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_tgt_addr_method_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf);
++static ssize_t scst_tgt_addr_method_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_tgt_io_grouping_type_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf);
++static ssize_t scst_tgt_io_grouping_type_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf);
++static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf);
++static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_acg_luns_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_acg_ini_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf);
++static ssize_t scst_acg_ini_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_acg_addr_method_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf);
++static ssize_t scst_acg_addr_method_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_acg_io_grouping_type_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf);
++static ssize_t scst_acg_io_grouping_type_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count);
++static ssize_t scst_acn_file_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++
++/**
++ ** Sysfs work
++ **/
++
++static DEFINE_SPINLOCK(sysfs_work_lock);
++static LIST_HEAD(sysfs_work_list);
++static DECLARE_WAIT_QUEUE_HEAD(sysfs_work_waitQ);
++static int active_sysfs_works;
++static int last_sysfs_work_res;
++static struct task_struct *sysfs_work_thread;
++
++/**
++ * scst_alloc_sysfs_work() - allocates a sysfs work
++ */
++int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
++ bool read_only_action, struct scst_sysfs_work_item **res_work)
++{
++ int res = 0;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ if (sysfs_work_fn == NULL) {
++ PRINT_ERROR("%s", "sysfs_work_fn is NULL");
++ res = -EINVAL;
++ goto out;
++ }
++
++ *res_work = NULL;
++
++ work = kzalloc(sizeof(*work), GFP_KERNEL);
++ if (work == NULL) {
++ PRINT_ERROR("Unable to alloc sysfs work (size %zd)",
++ sizeof(*work));
++ res = -ENOMEM;
++ goto out;
++ }
++
++ work->read_only_action = read_only_action;
++ kref_init(&work->sysfs_work_kref);
++ init_completion(&work->sysfs_work_done);
++ work->sysfs_work_fn = sysfs_work_fn;
++
++ *res_work = work;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL(scst_alloc_sysfs_work);
++
++static void scst_sysfs_work_release(struct kref *kref)
++{
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ work = container_of(kref, struct scst_sysfs_work_item,
++ sysfs_work_kref);
++
++ TRACE_DBG("Freeing sysfs work %p (buf %p)", work, work->buf);
++
++ kfree(work->buf);
++ kfree(work->res_buf);
++ kfree(work);
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_sysfs_work_get() - increases ref counter of the sysfs work
++ */
++void scst_sysfs_work_get(struct scst_sysfs_work_item *work)
++{
++ kref_get(&work->sysfs_work_kref);
++}
++EXPORT_SYMBOL(scst_sysfs_work_get);
++
++/**
++ * scst_sysfs_work_put() - decreases ref counter of the sysfs work
++ */
++void scst_sysfs_work_put(struct scst_sysfs_work_item *work)
++{
++ kref_put(&work->sysfs_work_kref, scst_sysfs_work_release);
++}
++EXPORT_SYMBOL(scst_sysfs_work_put);
++
++/**
++ * scst_sysfs_queue_wait_work() - waits for the work to complete
++ *
++ * Returnes status of the completed work or -EAGAIN if the work not
++ * completed before timeout. In the latter case a user should poll
++ * last_sysfs_mgmt_res until it returns the result of the processing.
++ */
++int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work)
++{
++ int res = 0, rc;
++ unsigned long timeout = 15*HZ;
++
++ TRACE_ENTRY();
++
++ spin_lock(&sysfs_work_lock);
++
++ TRACE_DBG("Adding sysfs work %p to the list", work);
++ list_add_tail(&work->sysfs_work_list_entry, &sysfs_work_list);
++
++ active_sysfs_works++;
++
++ spin_unlock(&sysfs_work_lock);
++
++ kref_get(&work->sysfs_work_kref);
++
++ wake_up(&sysfs_work_waitQ);
++
++ while (1) {
++ rc = wait_for_completion_interruptible_timeout(
++ &work->sysfs_work_done, timeout);
++ if (rc == 0) {
++ if (!mutex_is_locked(&scst_mutex)) {
++ TRACE_DBG("scst_mutex not locked, continue "
++ "waiting (work %p)", work);
++ timeout = 5*HZ;
++ continue;
++ }
++ TRACE_MGMT_DBG("Time out waiting for work %p",
++ work);
++ res = -EAGAIN;
++ goto out_put;
++ } else if (rc < 0) {
++ res = rc;
++ goto out_put;
++ }
++ break;
++ }
++
++ res = work->work_res;
++
++out_put:
++ kref_put(&work->sysfs_work_kref, scst_sysfs_work_release);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL(scst_sysfs_queue_wait_work);
++
++/* Called under sysfs_work_lock and drops/reaquire it inside */
++static void scst_process_sysfs_works(void)
++{
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ while (!list_empty(&sysfs_work_list)) {
++ work = list_entry(sysfs_work_list.next,
++ struct scst_sysfs_work_item, sysfs_work_list_entry);
++ list_del(&work->sysfs_work_list_entry);
++ spin_unlock(&sysfs_work_lock);
++
++ TRACE_DBG("Sysfs work %p", work);
++
++ work->work_res = work->sysfs_work_fn(work);
++
++ spin_lock(&sysfs_work_lock);
++ if (!work->read_only_action)
++ last_sysfs_work_res = work->work_res;
++ active_sysfs_works--;
++ spin_unlock(&sysfs_work_lock);
++
++ complete_all(&work->sysfs_work_done);
++ kref_put(&work->sysfs_work_kref, scst_sysfs_work_release);
++
++ spin_lock(&sysfs_work_lock);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline int test_sysfs_work_list(void)
++{
++ int res = !list_empty(&sysfs_work_list) ||
++ unlikely(kthread_should_stop());
++ return res;
++}
++
++static int sysfs_work_thread_fn(void *arg)
++{
++ TRACE_ENTRY();
++
++ PRINT_INFO("User interface thread started, PID %d", current->pid);
++
++ current->flags |= PF_NOFREEZE;
++
++ set_user_nice(current, -10);
++
++ spin_lock(&sysfs_work_lock);
++ while (!kthread_should_stop()) {
++ wait_queue_t wait;
++ init_waitqueue_entry(&wait, current);
++
++ if (!test_sysfs_work_list()) {
++ add_wait_queue_exclusive(&sysfs_work_waitQ, &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_sysfs_work_list())
++ break;
++ spin_unlock(&sysfs_work_lock);
++ schedule();
++ spin_lock(&sysfs_work_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&sysfs_work_waitQ, &wait);
++ }
++
++ scst_process_sysfs_works();
++ }
++ spin_unlock(&sysfs_work_lock);
++
++ /*
++ * If kthread_should_stop() is true, we are guaranteed to be
++ * on the module unload, so both lists must be empty.
++ */
++ BUG_ON(!list_empty(&sysfs_work_list));
++
++ PRINT_INFO("User interface thread PID %d finished", current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++/* No locks */
++static int scst_check_grab_tgtt_ptr(struct scst_tgt_template *tgtt)
++{
++ int res = 0;
++ struct scst_tgt_template *tt;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(tt, &scst_template_list, scst_template_list_entry) {
++ if (tt == tgtt) {
++ tgtt->tgtt_active_sysfs_works_count++;
++ goto out_unlock;
++ }
++ }
++
++ TRACE_DBG("Tgtt %p not found", tgtt);
++ res = -ENOENT;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* No locks */
++static void scst_ungrab_tgtt_ptr(struct scst_tgt_template *tgtt)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++ tgtt->tgtt_active_sysfs_works_count--;
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* scst_mutex supposed to be locked */
++static int scst_check_tgt_acg_ptrs(struct scst_tgt *tgt, struct scst_acg *acg)
++{
++ int res = 0;
++ struct scst_tgt_template *tgtt;
++
++ list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
++ struct scst_tgt *t;
++ list_for_each_entry(t, &tgtt->tgt_list, tgt_list_entry) {
++ if (t == tgt) {
++ struct scst_acg *a;
++ if (acg == NULL)
++ goto out;
++ if (acg == tgt->default_acg)
++ goto out;
++ list_for_each_entry(a, &tgt->tgt_acg_list,
++ acg_list_entry) {
++ if (a == acg)
++ goto out;
++ }
++ }
++ }
++ }
++
++ TRACE_DBG("Tgt %p/ACG %p not found", tgt, acg);
++ res = -ENOENT;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* scst_mutex supposed to be locked */
++static int scst_check_devt_ptr(struct scst_dev_type *devt,
++ struct list_head *list)
++{
++ int res = 0;
++ struct scst_dev_type *dt;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(dt, list, dev_type_list_entry) {
++ if (dt == devt)
++ goto out;
++ }
++
++ TRACE_DBG("Devt %p not found", devt);
++ res = -ENOENT;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* scst_mutex supposed to be locked */
++static int scst_check_dev_ptr(struct scst_device *dev)
++{
++ int res = 0;
++ struct scst_device *d;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if (d == dev)
++ goto out;
++ }
++
++ TRACE_DBG("Dev %p not found", dev);
++ res = -ENOENT;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* No locks */
++static int scst_check_grab_devt_ptr(struct scst_dev_type *devt,
++ struct list_head *list)
++{
++ int res = 0;
++ struct scst_dev_type *dt;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(dt, list, dev_type_list_entry) {
++ if (dt == devt) {
++ devt->devt_active_sysfs_works_count++;
++ goto out_unlock;
++ }
++ }
++
++ TRACE_DBG("Devt %p not found", devt);
++ res = -ENOENT;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* No locks */
++static void scst_ungrab_devt_ptr(struct scst_dev_type *devt)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++ devt->devt_active_sysfs_works_count--;
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ ** Regilar SCST sysfs ops
++ **/
++static ssize_t scst_show(struct kobject *kobj, struct attribute *attr,
++ char *buf)
++{
++ struct kobj_attribute *kobj_attr;
++ kobj_attr = container_of(attr, struct kobj_attribute, attr);
++
++ return kobj_attr->show(kobj, kobj_attr, buf);
++}
++
++static ssize_t scst_store(struct kobject *kobj, struct attribute *attr,
++ const char *buf, size_t count)
++{
++ struct kobj_attribute *kobj_attr;
++ kobj_attr = container_of(attr, struct kobj_attribute, attr);
++
++ if (kobj_attr->store)
++ return kobj_attr->store(kobj, kobj_attr, buf, count);
++ else
++ return -EIO;
++}
++
++static const struct sysfs_ops scst_sysfs_ops = {
++ .show = scst_show,
++ .store = scst_store,
++};
++
++const struct sysfs_ops *scst_sysfs_get_sysfs_ops(void)
++{
++ return &scst_sysfs_ops;
++}
++EXPORT_SYMBOL_GPL(scst_sysfs_get_sysfs_ops);
++
++/**
++ ** Target Template
++ **/
++
++static void scst_tgtt_release(struct kobject *kobj)
++{
++ struct scst_tgt_template *tgtt;
++
++ TRACE_ENTRY();
++
++ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
++ complete_all(&tgtt->tgtt_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct kobj_type tgtt_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_tgtt_release,
++};
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++static ssize_t scst_tgtt_trace_level_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_tgt_template *tgtt;
++
++ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
++
++ return scst_trace_level_show(tgtt->trace_tbl,
++ tgtt->trace_flags ? *tgtt->trace_flags : 0, buf,
++ tgtt->trace_tbl_help);
++}
++
++static ssize_t scst_tgtt_trace_level_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_tgt_template *tgtt;
++
++ TRACE_ENTRY();
++
++ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
++
++ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = scst_write_trace(buf, count, tgtt->trace_flags,
++ tgtt->default_trace_flags, tgtt->name, tgtt->trace_tbl);
++
++ mutex_unlock(&scst_log_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute tgtt_trace_attr =
++ __ATTR(trace_level, S_IRUGO | S_IWUSR,
++ scst_tgtt_trace_level_show, scst_tgtt_trace_level_store);
++
++#endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
++
++static ssize_t scst_tgtt_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++char *help = "Usage: echo \"add_target target_name [parameters]\" "
++ ">mgmt\n"
++ " echo \"del_target target_name\" >mgmt\n"
++ "%s%s"
++ "%s"
++ "\n"
++ "where parameters are one or more "
++ "param_name=value pairs separated by ';'\n\n"
++ "%s%s%s%s%s%s%s%s\n";
++ struct scst_tgt_template *tgtt;
++
++ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
++
++ return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, help,
++ (tgtt->tgtt_optional_attributes != NULL) ?
++ " echo \"add_attribute <attribute> <value>\" >mgmt\n"
++ " echo \"del_attribute <attribute> <value>\" >mgmt\n" : "",
++ (tgtt->tgt_optional_attributes != NULL) ?
++ " echo \"add_target_attribute target_name <attribute> <value>\" >mgmt\n"
++ " echo \"del_target_attribute target_name <attribute> <value>\" >mgmt\n" : "",
++ (tgtt->mgmt_cmd_help) ? tgtt->mgmt_cmd_help : "",
++ (tgtt->add_target_parameters != NULL) ?
++ "The following parameters available: " : "",
++ (tgtt->add_target_parameters != NULL) ?
++ tgtt->add_target_parameters : "",
++ (tgtt->tgtt_optional_attributes != NULL) ?
++ "The following target driver attributes available: " : "",
++ (tgtt->tgtt_optional_attributes != NULL) ?
++ tgtt->tgtt_optional_attributes : "",
++ (tgtt->tgtt_optional_attributes != NULL) ? "\n" : "",
++ (tgtt->tgt_optional_attributes != NULL) ?
++ "The following target attributes available: " : "",
++ (tgtt->tgt_optional_attributes != NULL) ?
++ tgtt->tgt_optional_attributes : "",
++ (tgtt->tgt_optional_attributes != NULL) ? "\n" : "");
++}
++
++static int scst_process_tgtt_mgmt_store(char *buffer,
++ struct scst_tgt_template *tgtt)
++{
++ int res = 0;
++ char *p, *pp, *target_name;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("buffer %s", buffer);
++
++ /* Check if our pointer is still alive and, if yes, grab it */
++ if (scst_check_grab_tgtt_ptr(tgtt) != 0)
++ goto out;
++
++ pp = buffer;
++ if (pp[strlen(pp) - 1] == '\n')
++ pp[strlen(pp) - 1] = '\0';
++
++ p = scst_get_next_lexem(&pp);
++
++ if (strcasecmp("add_target", p) == 0) {
++ target_name = scst_get_next_lexem(&pp);
++ if (*target_name == '\0') {
++ PRINT_ERROR("%s", "Target name required");
++ res = -EINVAL;
++ goto out_ungrab;
++ }
++ res = tgtt->add_target(target_name, pp);
++ } else if (strcasecmp("del_target", p) == 0) {
++ target_name = scst_get_next_lexem(&pp);
++ if (*target_name == '\0') {
++ PRINT_ERROR("%s", "Target name required");
++ res = -EINVAL;
++ goto out_ungrab;
++ }
++
++ p = scst_get_next_lexem(&pp);
++ if (*p != '\0')
++ goto out_syntax_err;
++
++ res = tgtt->del_target(target_name);
++ } else if (tgtt->mgmt_cmd != NULL) {
++ scst_restore_token_str(p, pp);
++ res = tgtt->mgmt_cmd(buffer);
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out_ungrab;
++ }
++
++out_ungrab:
++ scst_ungrab_tgtt_ptr(tgtt);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_syntax_err:
++ PRINT_ERROR("Syntax error on \"%s\"", p);
++ res = -EINVAL;
++ goto out_ungrab;
++}
++
++static int scst_tgtt_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
++{
++ return scst_process_tgtt_mgmt_store(work->buf, work->tgtt);
++}
++
++static ssize_t scst_tgtt_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ char *buffer;
++ struct scst_sysfs_work_item *work;
++ struct scst_tgt_template *tgtt;
++
++ TRACE_ENTRY();
++
++ tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
++
++ buffer = kzalloc(count+1, GFP_KERNEL);
++ if (buffer == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++ memcpy(buffer, buf, count);
++ buffer[count] = '\0';
++
++ res = scst_alloc_sysfs_work(scst_tgtt_mgmt_store_work_fn, false, &work);
++ if (res != 0)
++ goto out_free;
++
++ work->buf = buffer;
++ work->tgtt = tgtt;
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(buffer);
++ goto out;
++}
++
++static struct kobj_attribute scst_tgtt_mgmt =
++ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_tgtt_mgmt_show,
++ scst_tgtt_mgmt_store);
++
++int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt)
++{
++ int res = 0;
++ const struct attribute **pattr;
++
++ TRACE_ENTRY();
++
++ init_completion(&tgtt->tgtt_kobj_release_cmpl);
++
++ res = kobject_init_and_add(&tgtt->tgtt_kobj, &tgtt_ktype,
++ scst_targets_kobj, tgtt->name);
++ if (res != 0) {
++ PRINT_ERROR("Can't add tgtt %s to sysfs", tgtt->name);
++ goto out;
++ }
++
++ if (tgtt->add_target != NULL) {
++ res = sysfs_create_file(&tgtt->tgtt_kobj,
++ &scst_tgtt_mgmt.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add mgmt attr for target driver %s",
++ tgtt->name);
++ goto out_del;
++ }
++ }
++
++ pattr = tgtt->tgtt_attrs;
++ if (pattr != NULL) {
++ while (*pattr != NULL) {
++ TRACE_DBG("Creating attr %s for target driver %s",
++ (*pattr)->name, tgtt->name);
++ res = sysfs_create_file(&tgtt->tgtt_kobj, *pattr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add attr %s for target "
++ "driver %s", (*pattr)->name,
++ tgtt->name);
++ goto out_del;
++ }
++ pattr++;
++ }
++ }
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ if (tgtt->trace_flags != NULL) {
++ res = sysfs_create_file(&tgtt->tgtt_kobj,
++ &tgtt_trace_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add trace_flag for target "
++ "driver %s", tgtt->name);
++ goto out_del;
++ }
++ }
++#endif
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ scst_tgtt_sysfs_del(tgtt);
++ goto out;
++}
++
++/*
++ * Must not be called under scst_mutex, due to possible deadlock with
++ * sysfs ref counting in sysfs works (it is waiting for the last put, but
++ * the last ref counter holder is waiting for scst_mutex)
++ */
++void scst_tgtt_sysfs_del(struct scst_tgt_template *tgtt)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ kobject_del(&tgtt->tgtt_kobj);
++ kobject_put(&tgtt->tgtt_kobj);
++
++ rc = wait_for_completion_timeout(&tgtt->tgtt_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for target template %s (%d refs)...", tgtt->name,
++ atomic_read(&tgtt->tgtt_kobj.kref.refcount));
++ wait_for_completion(&tgtt->tgtt_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs "
++ "entry for target template %s", tgtt->name);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ ** Target directory implementation
++ **/
++
++static void scst_tgt_release(struct kobject *kobj)
++{
++ struct scst_tgt *tgt;
++
++ TRACE_ENTRY();
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ complete_all(&tgt->tgt_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct kobj_type tgt_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_tgt_release,
++};
++
++static void scst_acg_release(struct kobject *kobj)
++{
++ struct scst_acg *acg;
++
++ TRACE_ENTRY();
++
++ acg = container_of(kobj, struct scst_acg, acg_kobj);
++ complete_all(&acg->acg_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct kobj_type acg_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_acg_release,
++};
++
++static struct kobj_attribute scst_luns_mgmt =
++ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
++ scst_luns_mgmt_store);
++
++static struct kobj_attribute scst_acg_luns_mgmt =
++ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_luns_mgmt_show,
++ scst_acg_luns_mgmt_store);
++
++static struct kobj_attribute scst_acg_ini_mgmt =
++ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_acg_ini_mgmt_show,
++ scst_acg_ini_mgmt_store);
++
++static struct kobj_attribute scst_ini_group_mgmt =
++ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_ini_group_mgmt_show,
++ scst_ini_group_mgmt_store);
++
++static struct kobj_attribute scst_tgt_addr_method =
++ __ATTR(addr_method, S_IRUGO | S_IWUSR, scst_tgt_addr_method_show,
++ scst_tgt_addr_method_store);
++
++static struct kobj_attribute scst_tgt_io_grouping_type =
++ __ATTR(io_grouping_type, S_IRUGO | S_IWUSR,
++ scst_tgt_io_grouping_type_show,
++ scst_tgt_io_grouping_type_store);
++
++static struct kobj_attribute scst_rel_tgt_id =
++ __ATTR(rel_tgt_id, S_IRUGO | S_IWUSR, scst_rel_tgt_id_show,
++ scst_rel_tgt_id_store);
++
++static struct kobj_attribute scst_acg_addr_method =
++ __ATTR(addr_method, S_IRUGO | S_IWUSR, scst_acg_addr_method_show,
++ scst_acg_addr_method_store);
++
++static struct kobj_attribute scst_acg_io_grouping_type =
++ __ATTR(io_grouping_type, S_IRUGO | S_IWUSR,
++ scst_acg_io_grouping_type_show,
++ scst_acg_io_grouping_type_store);
++
++static ssize_t scst_tgt_enable_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_tgt *tgt;
++ int res;
++ bool enabled;
++
++ TRACE_ENTRY();
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++
++ enabled = tgt->tgtt->is_target_enabled(tgt);
++
++ res = sprintf(buf, "%d\n", enabled ? 1 : 0);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_process_tgt_enable_store(struct scst_tgt *tgt, bool enable)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ /* Tgt protected by kobject reference */
++
++ TRACE_DBG("tgt %s, enable %d", tgt->tgt_name, enable);
++
++ if (enable) {
++ if (tgt->rel_tgt_id == 0) {
++ res = gen_relative_target_port_id(&tgt->rel_tgt_id);
++ if (res != 0)
++ goto out_put;
++ PRINT_INFO("Using autogenerated rel ID %d for target "
++ "%s", tgt->rel_tgt_id, tgt->tgt_name);
++ } else {
++ if (!scst_is_relative_target_port_id_unique(
++ tgt->rel_tgt_id, tgt)) {
++ PRINT_ERROR("Relative port id %d is not unique",
++ tgt->rel_tgt_id);
++ res = -EBADSLT;
++ goto out_put;
++ }
++ }
++ }
++
++ res = tgt->tgtt->enable_target(tgt, enable);
++
++out_put:
++ kobject_put(&tgt->tgt_kobj);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_tgt_enable_store_work_fn(struct scst_sysfs_work_item *work)
++{
++ return scst_process_tgt_enable_store(work->tgt, work->enable);
++}
++
++static ssize_t scst_tgt_enable_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_tgt *tgt;
++ bool enable;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ if (buf == NULL) {
++ PRINT_ERROR("%s: NULL buffer?", __func__);
++ res = -EINVAL;
++ goto out;
++ }
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++
++ switch (buf[0]) {
++ case '0':
++ enable = false;
++ break;
++ case '1':
++ enable = true;
++ break;
++ default:
++ PRINT_ERROR("%s: Requested action not understood: %s",
++ __func__, buf);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_alloc_sysfs_work(scst_tgt_enable_store_work_fn, false,
++ &work);
++ if (res != 0)
++ goto out;
++
++ work->tgt = tgt;
++ work->enable = enable;
++
++ kobject_get(&tgt->tgt_kobj);
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute tgt_enable_attr =
++ __ATTR(enabled, S_IRUGO | S_IWUSR,
++ scst_tgt_enable_show, scst_tgt_enable_store);
++
++/*
++ * Supposed to be called under scst_mutex. In case of error will drop,
++ * then reacquire it.
++ */
++int scst_tgt_sysfs_create(struct scst_tgt *tgt)
++{
++ int res;
++ const struct attribute **pattr;
++
++ TRACE_ENTRY();
++
++ init_completion(&tgt->tgt_kobj_release_cmpl);
++
++ res = kobject_init_and_add(&tgt->tgt_kobj, &tgt_ktype,
++ &tgt->tgtt->tgtt_kobj, tgt->tgt_name);
++ if (res != 0) {
++ PRINT_ERROR("Can't add tgt %s to sysfs", tgt->tgt_name);
++ goto out;
++ }
++
++ if ((tgt->tgtt->enable_target != NULL) &&
++ (tgt->tgtt->is_target_enabled != NULL)) {
++ res = sysfs_create_file(&tgt->tgt_kobj,
++ &tgt_enable_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add attr %s to sysfs",
++ tgt_enable_attr.attr.name);
++ goto out_err;
++ }
++ }
++
++ tgt->tgt_sess_kobj = kobject_create_and_add("sessions", &tgt->tgt_kobj);
++ if (tgt->tgt_sess_kobj == NULL) {
++ PRINT_ERROR("Can't create sess kobj for tgt %s", tgt->tgt_name);
++ goto out_nomem;
++ }
++
++ tgt->tgt_luns_kobj = kobject_create_and_add("luns", &tgt->tgt_kobj);
++ if (tgt->tgt_luns_kobj == NULL) {
++ PRINT_ERROR("Can't create luns kobj for tgt %s", tgt->tgt_name);
++ goto out_nomem;
++ }
++
++ res = sysfs_create_file(tgt->tgt_luns_kobj, &scst_luns_mgmt.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add attribute %s for tgt %s",
++ scst_luns_mgmt.attr.name, tgt->tgt_name);
++ goto out_err;
++ }
++
++ tgt->tgt_ini_grp_kobj = kobject_create_and_add("ini_groups",
++ &tgt->tgt_kobj);
++ if (tgt->tgt_ini_grp_kobj == NULL) {
++ PRINT_ERROR("Can't create ini_grp kobj for tgt %s",
++ tgt->tgt_name);
++ goto out_nomem;
++ }
++
++ res = sysfs_create_file(tgt->tgt_ini_grp_kobj,
++ &scst_ini_group_mgmt.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add attribute %s for tgt %s",
++ scst_ini_group_mgmt.attr.name, tgt->tgt_name);
++ goto out_err;
++ }
++
++ res = sysfs_create_file(&tgt->tgt_kobj,
++ &scst_rel_tgt_id.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add attribute %s for tgt %s",
++ scst_rel_tgt_id.attr.name, tgt->tgt_name);
++ goto out_err;
++ }
++
++ res = sysfs_create_file(&tgt->tgt_kobj,
++ &scst_tgt_addr_method.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add attribute %s for tgt %s",
++ scst_tgt_addr_method.attr.name, tgt->tgt_name);
++ goto out_err;
++ }
++
++ res = sysfs_create_file(&tgt->tgt_kobj,
++ &scst_tgt_io_grouping_type.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add attribute %s for tgt %s",
++ scst_tgt_io_grouping_type.attr.name, tgt->tgt_name);
++ goto out_err;
++ }
++
++ pattr = tgt->tgtt->tgt_attrs;
++ if (pattr != NULL) {
++ while (*pattr != NULL) {
++ TRACE_DBG("Creating attr %s for tgt %s", (*pattr)->name,
++ tgt->tgt_name);
++ res = sysfs_create_file(&tgt->tgt_kobj, *pattr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
++ (*pattr)->name, tgt->tgt_name);
++ goto out_err;
++ }
++ pattr++;
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_nomem:
++ res = -ENOMEM;
++
++out_err:
++ mutex_unlock(&scst_mutex);
++ scst_tgt_sysfs_del(tgt);
++ mutex_lock(&scst_mutex);
++ goto out;
++}
++
++/*
++ * Must not be called under scst_mutex, due to possible deadlock with
++ * sysfs ref counting in sysfs works (it is waiting for the last put, but
++ * the last ref counter holder is waiting for scst_mutex)
++ */
++void scst_tgt_sysfs_del(struct scst_tgt *tgt)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ kobject_del(tgt->tgt_sess_kobj);
++ kobject_del(tgt->tgt_luns_kobj);
++ kobject_del(tgt->tgt_ini_grp_kobj);
++ kobject_del(&tgt->tgt_kobj);
++
++ kobject_put(tgt->tgt_sess_kobj);
++ kobject_put(tgt->tgt_luns_kobj);
++ kobject_put(tgt->tgt_ini_grp_kobj);
++ kobject_put(&tgt->tgt_kobj);
++
++ rc = wait_for_completion_timeout(&tgt->tgt_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for target %s (%d refs)...", tgt->tgt_name,
++ atomic_read(&tgt->tgt_kobj.kref.refcount));
++ wait_for_completion(&tgt->tgt_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs "
++ "entry for target %s", tgt->tgt_name);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ ** Devices directory implementation
++ **/
++
++static ssize_t scst_dev_sysfs_type_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++
++ struct scst_device *dev;
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ pos = sprintf(buf, "%d - %s\n", dev->type,
++ (unsigned)dev->type > ARRAY_SIZE(scst_dev_handler_types) ?
++ "unknown" : scst_dev_handler_types[dev->type]);
++
++ return pos;
++}
++
++static struct kobj_attribute dev_type_attr =
++ __ATTR(type, S_IRUGO, scst_dev_sysfs_type_show, NULL);
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++static ssize_t scst_dev_sysfs_dump_prs(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ scst_pr_dump_prs(dev, true);
++
++ TRACE_EXIT_RES(count);
++ return count;
++}
++
++static struct kobj_attribute dev_dump_prs_attr =
++ __ATTR(dump_prs, S_IWUSR, NULL, scst_dev_sysfs_dump_prs);
++
++#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
++
++static int scst_process_dev_sysfs_threads_data_store(
++ struct scst_device *dev, int threads_num,
++ enum scst_dev_type_threads_pool_type threads_pool_type)
++{
++ int res = 0;
++ int oldtn = dev->threads_num;
++ enum scst_dev_type_threads_pool_type oldtt = dev->threads_pool_type;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("dev %p, threads_num %d, threads_pool_type %d", dev,
++ threads_num, threads_pool_type);
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_resume;
++ }
++
++ /* Check if our pointer is still alive */
++ if (scst_check_dev_ptr(dev) != 0)
++ goto out_unlock;
++
++ scst_stop_dev_threads(dev);
++
++ dev->threads_num = threads_num;
++ dev->threads_pool_type = threads_pool_type;
++
++ res = scst_create_dev_threads(dev);
++ if (res != 0)
++ goto out_unlock;
++
++ if (oldtn != dev->threads_num)
++ PRINT_INFO("Changed cmd threads num to %d", dev->threads_num);
++ else if (oldtt != dev->threads_pool_type)
++ PRINT_INFO("Changed cmd threads pool type to %d",
++ dev->threads_pool_type);
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out_resume:
++ scst_resume_activity();
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_dev_sysfs_threads_data_store_work_fn(
++ struct scst_sysfs_work_item *work)
++{
++ return scst_process_dev_sysfs_threads_data_store(work->dev,
++ work->new_threads_num, work->new_threads_pool_type);
++}
++
++static ssize_t scst_dev_sysfs_check_threads_data(
++ struct scst_device *dev, int threads_num,
++ enum scst_dev_type_threads_pool_type threads_pool_type, bool *stop)
++{
++ int res = 0;
++
++ *stop = false;
++
++ if (dev->threads_num < 0) {
++ PRINT_ERROR("Threads pool disabled for device %s",
++ dev->virt_name);
++ res = -EPERM;
++ goto out;
++ }
++
++ if ((threads_num == dev->threads_num) &&
++ (threads_pool_type == dev->threads_pool_type)) {
++ *stop = true;
++ goto out;
++ }
++
++out:
++ return res;
++}
++
++static ssize_t scst_dev_sysfs_threads_num_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ pos = sprintf(buf, "%d\n%s", dev->threads_num,
++ (dev->threads_num != dev->handler->threads_num) ?
++ SCST_SYSFS_KEY_MARK "\n" : "");
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t scst_dev_sysfs_threads_num_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_device *dev;
++ long newtn;
++ bool stop;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ res = strict_strtol(buf, 0, &newtn);
++ if (res != 0) {
++ PRINT_ERROR("strict_strtol() for %s failed: %d ", buf, res);
++ goto out;
++ }
++ if (newtn < 0) {
++ PRINT_ERROR("Illegal threads num value %ld", newtn);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_dev_sysfs_check_threads_data(dev, newtn,
++ dev->threads_pool_type, &stop);
++ if ((res != 0) || stop)
++ goto out;
++
++ res = scst_alloc_sysfs_work(scst_dev_sysfs_threads_data_store_work_fn,
++ false, &work);
++ if (res != 0)
++ goto out;
++
++ work->dev = dev;
++ work->new_threads_num = newtn;
++ work->new_threads_pool_type = dev->threads_pool_type;
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute dev_threads_num_attr =
++ __ATTR(threads_num, S_IRUGO | S_IWUSR,
++ scst_dev_sysfs_threads_num_show,
++ scst_dev_sysfs_threads_num_store);
++
++static ssize_t scst_dev_sysfs_threads_pool_type_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ if (dev->threads_num == 0) {
++ pos = sprintf(buf, "Async\n");
++ goto out;
++ } else if (dev->threads_num < 0) {
++ pos = sprintf(buf, "Not valid\n");
++ goto out;
++ }
++
++ switch (dev->threads_pool_type) {
++ case SCST_THREADS_POOL_PER_INITIATOR:
++ pos = sprintf(buf, "%s\n%s", SCST_THREADS_POOL_PER_INITIATOR_STR,
++ (dev->threads_pool_type != dev->handler->threads_pool_type) ?
++ SCST_SYSFS_KEY_MARK "\n" : "");
++ break;
++ case SCST_THREADS_POOL_SHARED:
++ pos = sprintf(buf, "%s\n%s", SCST_THREADS_POOL_SHARED_STR,
++ (dev->threads_pool_type != dev->handler->threads_pool_type) ?
++ SCST_SYSFS_KEY_MARK "\n" : "");
++ break;
++ default:
++ pos = sprintf(buf, "Unknown\n");
++ break;
++ }
++
++out:
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t scst_dev_sysfs_threads_pool_type_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_device *dev;
++ enum scst_dev_type_threads_pool_type newtpt;
++ struct scst_sysfs_work_item *work;
++ bool stop;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ newtpt = scst_parse_threads_pool_type(buf, count);
++ if (newtpt == SCST_THREADS_POOL_TYPE_INVALID) {
++ PRINT_ERROR("Illegal threads pool type %s", buf);
++ res = -EINVAL;
++ goto out;
++ }
++
++ TRACE_DBG("buf %s, count %zd, newtpt %d", buf, count, newtpt);
++
++ res = scst_dev_sysfs_check_threads_data(dev, dev->threads_num,
++ newtpt, &stop);
++ if ((res != 0) || stop)
++ goto out;
++
++ res = scst_alloc_sysfs_work(scst_dev_sysfs_threads_data_store_work_fn,
++ false, &work);
++ if (res != 0)
++ goto out;
++
++ work->dev = dev;
++ work->new_threads_num = dev->threads_num;
++ work->new_threads_pool_type = newtpt;
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute dev_threads_pool_type_attr =
++ __ATTR(threads_pool_type, S_IRUGO | S_IWUSR,
++ scst_dev_sysfs_threads_pool_type_show,
++ scst_dev_sysfs_threads_pool_type_store);
++
++static struct attribute *scst_dev_attrs[] = {
++ &dev_type_attr.attr,
++ NULL,
++};
++
++static void scst_sysfs_dev_release(struct kobject *kobj)
++{
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ complete_all(&dev->dev_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++int scst_devt_dev_sysfs_create(struct scst_device *dev)
++{
++ int res = 0;
++ const struct attribute **pattr;
++
++ TRACE_ENTRY();
++
++ if (dev->handler == &scst_null_devtype)
++ goto out;
++
++ res = sysfs_create_link(&dev->dev_kobj,
++ &dev->handler->devt_kobj, "handler");
++ if (res != 0) {
++ PRINT_ERROR("Can't create handler link for dev %s",
++ dev->virt_name);
++ goto out;
++ }
++
++ res = sysfs_create_link(&dev->handler->devt_kobj,
++ &dev->dev_kobj, dev->virt_name);
++ if (res != 0) {
++ PRINT_ERROR("Can't create handler link for dev %s",
++ dev->virt_name);
++ goto out_err;
++ }
++
++ if (dev->handler->threads_num >= 0) {
++ res = sysfs_create_file(&dev->dev_kobj,
++ &dev_threads_num_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add dev attr %s for dev %s",
++ dev_threads_num_attr.attr.name,
++ dev->virt_name);
++ goto out_err;
++ }
++ res = sysfs_create_file(&dev->dev_kobj,
++ &dev_threads_pool_type_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add dev attr %s for dev %s",
++ dev_threads_pool_type_attr.attr.name,
++ dev->virt_name);
++ goto out_err;
++ }
++ }
++
++ pattr = dev->handler->dev_attrs;
++ if (pattr != NULL) {
++ while (*pattr != NULL) {
++ res = sysfs_create_file(&dev->dev_kobj, *pattr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add dev attr %s for dev %s",
++ (*pattr)->name, dev->virt_name);
++ goto out_err;
++ }
++ pattr++;
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_err:
++ scst_devt_dev_sysfs_del(dev);
++ goto out;
++}
++
++void scst_devt_dev_sysfs_del(struct scst_device *dev)
++{
++ const struct attribute **pattr;
++
++ TRACE_ENTRY();
++
++ if (dev->handler == &scst_null_devtype)
++ goto out;
++
++ pattr = dev->handler->dev_attrs;
++ if (pattr != NULL) {
++ while (*pattr != NULL) {
++ sysfs_remove_file(&dev->dev_kobj, *pattr);
++ pattr++;
++ }
++ }
++
++ sysfs_remove_link(&dev->dev_kobj, "handler");
++ sysfs_remove_link(&dev->handler->devt_kobj, dev->virt_name);
++
++ if (dev->handler->threads_num >= 0) {
++ sysfs_remove_file(&dev->dev_kobj,
++ &dev_threads_num_attr.attr);
++ sysfs_remove_file(&dev->dev_kobj,
++ &dev_threads_pool_type_attr.attr);
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static struct kobj_type scst_dev_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_sysfs_dev_release,
++ .default_attrs = scst_dev_attrs,
++};
++
++/*
++ * Must not be called under scst_mutex, because it can call
++ * scst_dev_sysfs_del()
++ */
++int scst_dev_sysfs_create(struct scst_device *dev)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ init_completion(&dev->dev_kobj_release_cmpl);
++
++ res = kobject_init_and_add(&dev->dev_kobj, &scst_dev_ktype,
++ scst_devices_kobj, dev->virt_name);
++ if (res != 0) {
++ PRINT_ERROR("Can't add device %s to sysfs", dev->virt_name);
++ goto out;
++ }
++
++ dev->dev_exp_kobj = kobject_create_and_add("exported",
++ &dev->dev_kobj);
++ if (dev->dev_exp_kobj == NULL) {
++ PRINT_ERROR("Can't create exported link for device %s",
++ dev->virt_name);
++ res = -ENOMEM;
++ goto out_del;
++ }
++
++ if (dev->scsi_dev != NULL) {
++ res = sysfs_create_link(&dev->dev_kobj,
++ &dev->scsi_dev->sdev_dev.kobj, "scsi_device");
++ if (res != 0) {
++ PRINT_ERROR("Can't create scsi_device link for dev %s",
++ dev->virt_name);
++ goto out_del;
++ }
++ }
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ if (dev->scsi_dev == NULL) {
++ res = sysfs_create_file(&dev->dev_kobj,
++ &dev_dump_prs_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't create attr %s for dev %s",
++ dev_dump_prs_attr.attr.name, dev->virt_name);
++ goto out_del;
++ }
++ }
++#endif
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ scst_dev_sysfs_del(dev);
++ goto out;
++}
++
++/*
++ * Must not be called under scst_mutex, due to possible deadlock with
++ * sysfs ref counting in sysfs works (it is waiting for the last put, but
++ * the last ref counter holder is waiting for scst_mutex)
++ */
++void scst_dev_sysfs_del(struct scst_device *dev)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ kobject_del(dev->dev_exp_kobj);
++ kobject_del(&dev->dev_kobj);
++
++ kobject_put(dev->dev_exp_kobj);
++ kobject_put(&dev->dev_kobj);
++
++ rc = wait_for_completion_timeout(&dev->dev_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for device %s (%d refs)...", dev->virt_name,
++ atomic_read(&dev->dev_kobj.kref.refcount));
++ wait_for_completion(&dev->dev_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs "
++ "entry for device %s", dev->virt_name);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ ** Tgt_dev's directory implementation
++ **/
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++
++static char *scst_io_size_names[] = {
++ "<=8K ",
++ "<=32K ",
++ "<=128K",
++ "<=512K",
++ ">512K "
++};
++
++static ssize_t scst_tgt_dev_latency_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buffer)
++{
++ int res = 0, i;
++ char buf[50];
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
++
++ for (i = 0; i < SCST_LATENCY_STATS_NUM; i++) {
++ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
++ unsigned int processed_cmds_wr;
++ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
++ unsigned int processed_cmds_rd;
++ struct scst_ext_latency_stat *latency_stat;
++
++ latency_stat = &tgt_dev->dev_latency_stat[i];
++ scst_time_wr = latency_stat->scst_time_wr;
++ scst_time_rd = latency_stat->scst_time_rd;
++ tgt_time_wr = latency_stat->tgt_time_wr;
++ tgt_time_rd = latency_stat->tgt_time_rd;
++ dev_time_wr = latency_stat->dev_time_wr;
++ dev_time_rd = latency_stat->dev_time_rd;
++ processed_cmds_wr = latency_stat->processed_cmds_wr;
++ processed_cmds_rd = latency_stat->processed_cmds_rd;
++
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-5s %-9s %-15lu ", "Write", scst_io_size_names[i],
++ (unsigned long)processed_cmds_wr);
++ if (processed_cmds_wr == 0)
++ processed_cmds_wr = 1;
++
++ do_div(scst_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_scst_time_wr,
++ (unsigned long)scst_time_wr,
++ (unsigned long)latency_stat->max_scst_time_wr,
++ (unsigned long)latency_stat->scst_time_wr);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(tgt_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_tgt_time_wr,
++ (unsigned long)tgt_time_wr,
++ (unsigned long)latency_stat->max_tgt_time_wr,
++ (unsigned long)latency_stat->tgt_time_wr);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(dev_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_dev_time_wr,
++ (unsigned long)dev_time_wr,
++ (unsigned long)latency_stat->max_dev_time_wr,
++ (unsigned long)latency_stat->dev_time_wr);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s\n", buf);
++
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-5s %-9s %-15lu ", "Read", scst_io_size_names[i],
++ (unsigned long)processed_cmds_rd);
++ if (processed_cmds_rd == 0)
++ processed_cmds_rd = 1;
++
++ do_div(scst_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_scst_time_rd,
++ (unsigned long)scst_time_rd,
++ (unsigned long)latency_stat->max_scst_time_rd,
++ (unsigned long)latency_stat->scst_time_rd);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(tgt_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_tgt_time_rd,
++ (unsigned long)tgt_time_rd,
++ (unsigned long)latency_stat->max_tgt_time_rd,
++ (unsigned long)latency_stat->tgt_time_rd);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(dev_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_dev_time_rd,
++ (unsigned long)dev_time_rd,
++ (unsigned long)latency_stat->max_dev_time_rd,
++ (unsigned long)latency_stat->dev_time_rd);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s\n", buf);
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute tgt_dev_latency_attr =
++ __ATTR(latency, S_IRUGO,
++ scst_tgt_dev_latency_show, NULL);
++
++#endif /* CONFIG_SCST_MEASURE_LATENCY */
++
++static ssize_t scst_tgt_dev_active_commands_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_tgt_dev *tgt_dev;
++
++ tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
++
++ pos = sprintf(buf, "%d\n", atomic_read(&tgt_dev->tgt_dev_cmd_count));
++
++ return pos;
++}
++
++static struct kobj_attribute tgt_dev_active_commands_attr =
++ __ATTR(active_commands, S_IRUGO,
++ scst_tgt_dev_active_commands_show, NULL);
++
++static struct attribute *scst_tgt_dev_attrs[] = {
++ &tgt_dev_active_commands_attr.attr,
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++ &tgt_dev_latency_attr.attr,
++#endif
++ NULL,
++};
++
++static void scst_sysfs_tgt_dev_release(struct kobject *kobj)
++{
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
++ complete_all(&tgt_dev->tgt_dev_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct kobj_type scst_tgt_dev_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_sysfs_tgt_dev_release,
++ .default_attrs = scst_tgt_dev_attrs,
++};
++
++int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ init_completion(&tgt_dev->tgt_dev_kobj_release_cmpl);
++
++ res = kobject_init_and_add(&tgt_dev->tgt_dev_kobj, &scst_tgt_dev_ktype,
++ &tgt_dev->sess->sess_kobj, "lun%lld",
++ (unsigned long long)tgt_dev->lun);
++ if (res != 0) {
++ PRINT_ERROR("Can't add tgt_dev %lld to sysfs",
++ (unsigned long long)tgt_dev->lun);
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * Called with scst_mutex held.
++ *
++ * !! No sysfs works must use kobject_get() to protect tgt_dev, due to possible
++ * !! deadlock with scst_mutex (it is waiting for the last put, but
++ * !! the last ref counter holder is waiting for scst_mutex)
++ */
++void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ kobject_del(&tgt_dev->tgt_dev_kobj);
++ kobject_put(&tgt_dev->tgt_dev_kobj);
++
++ rc = wait_for_completion_timeout(
++ &tgt_dev->tgt_dev_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for tgt_dev %lld (%d refs)...",
++ (unsigned long long)tgt_dev->lun,
++ atomic_read(&tgt_dev->tgt_dev_kobj.kref.refcount));
++ wait_for_completion(&tgt_dev->tgt_dev_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs entry for "
++ "tgt_dev %lld", (unsigned long long)tgt_dev->lun);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ ** Sessions subdirectory implementation
++ **/
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++
++static ssize_t scst_sess_latency_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buffer)
++{
++ ssize_t res = 0;
++ struct scst_session *sess;
++ int i;
++ char buf[50];
++ uint64_t scst_time, tgt_time, dev_time;
++ unsigned int processed_cmds;
++
++ TRACE_ENTRY();
++
++ sess = container_of(kobj, struct scst_session, sess_kobj);
++
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-15s %-15s %-46s %-46s %-46s\n",
++ "T-L names", "Total commands", "SCST latency",
++ "Target latency", "Dev latency (min/avg/max/all ns)");
++
++ spin_lock_bh(&sess->lat_lock);
++
++ for (i = 0; i < SCST_LATENCY_STATS_NUM ; i++) {
++ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
++ unsigned int processed_cmds_wr;
++ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
++ unsigned int processed_cmds_rd;
++ struct scst_ext_latency_stat *latency_stat;
++
++ latency_stat = &sess->sess_latency_stat[i];
++ scst_time_wr = latency_stat->scst_time_wr;
++ scst_time_rd = latency_stat->scst_time_rd;
++ tgt_time_wr = latency_stat->tgt_time_wr;
++ tgt_time_rd = latency_stat->tgt_time_rd;
++ dev_time_wr = latency_stat->dev_time_wr;
++ dev_time_rd = latency_stat->dev_time_rd;
++ processed_cmds_wr = latency_stat->processed_cmds_wr;
++ processed_cmds_rd = latency_stat->processed_cmds_rd;
++
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-5s %-9s %-15lu ",
++ "Write", scst_io_size_names[i],
++ (unsigned long)processed_cmds_wr);
++ if (processed_cmds_wr == 0)
++ processed_cmds_wr = 1;
++
++ do_div(scst_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_scst_time_wr,
++ (unsigned long)scst_time_wr,
++ (unsigned long)latency_stat->max_scst_time_wr,
++ (unsigned long)latency_stat->scst_time_wr);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(tgt_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_tgt_time_wr,
++ (unsigned long)tgt_time_wr,
++ (unsigned long)latency_stat->max_tgt_time_wr,
++ (unsigned long)latency_stat->tgt_time_wr);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(dev_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_dev_time_wr,
++ (unsigned long)dev_time_wr,
++ (unsigned long)latency_stat->max_dev_time_wr,
++ (unsigned long)latency_stat->dev_time_wr);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s\n", buf);
++
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-5s %-9s %-15lu ",
++ "Read", scst_io_size_names[i],
++ (unsigned long)processed_cmds_rd);
++ if (processed_cmds_rd == 0)
++ processed_cmds_rd = 1;
++
++ do_div(scst_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_scst_time_rd,
++ (unsigned long)scst_time_rd,
++ (unsigned long)latency_stat->max_scst_time_rd,
++ (unsigned long)latency_stat->scst_time_rd);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(tgt_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_tgt_time_rd,
++ (unsigned long)tgt_time_rd,
++ (unsigned long)latency_stat->max_tgt_time_rd,
++ (unsigned long)latency_stat->tgt_time_rd);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(dev_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_dev_time_rd,
++ (unsigned long)dev_time_rd,
++ (unsigned long)latency_stat->max_dev_time_rd,
++ (unsigned long)latency_stat->dev_time_rd);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s\n", buf);
++ }
++
++ scst_time = sess->scst_time;
++ tgt_time = sess->tgt_time;
++ dev_time = sess->dev_time;
++ processed_cmds = sess->processed_cmds;
++
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "\n%-15s %-16d", "Overall ", processed_cmds);
++
++ if (processed_cmds == 0)
++ processed_cmds = 1;
++
++ do_div(scst_time, processed_cmds);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)sess->min_scst_time,
++ (unsigned long)scst_time,
++ (unsigned long)sess->max_scst_time,
++ (unsigned long)sess->scst_time);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(tgt_time, processed_cmds);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)sess->min_tgt_time,
++ (unsigned long)tgt_time,
++ (unsigned long)sess->max_tgt_time,
++ (unsigned long)sess->tgt_time);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s", buf);
++
++ do_div(dev_time, processed_cmds);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)sess->min_dev_time,
++ (unsigned long)dev_time,
++ (unsigned long)sess->max_dev_time,
++ (unsigned long)sess->dev_time);
++ res += scnprintf(&buffer[res], SCST_SYSFS_BLOCK_SIZE - res,
++ "%-47s\n\n", buf);
++
++ spin_unlock_bh(&sess->lat_lock);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_sess_zero_latency(struct scst_sysfs_work_item *work)
++{
++ int res = 0, t;
++ struct scst_session *sess = work->sess;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_put;
++ }
++
++ PRINT_INFO("Zeroing latency statistics for initiator "
++ "%s", sess->initiator_name);
++
++ spin_lock_bh(&sess->lat_lock);
++
++ sess->scst_time = 0;
++ sess->tgt_time = 0;
++ sess->dev_time = 0;
++ sess->min_scst_time = 0;
++ sess->min_tgt_time = 0;
++ sess->min_dev_time = 0;
++ sess->max_scst_time = 0;
++ sess->max_tgt_time = 0;
++ sess->max_dev_time = 0;
++ sess->processed_cmds = 0;
++ memset(sess->sess_latency_stat, 0,
++ sizeof(sess->sess_latency_stat));
++
++ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[t];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ tgt_dev->scst_time = 0;
++ tgt_dev->tgt_time = 0;
++ tgt_dev->dev_time = 0;
++ tgt_dev->processed_cmds = 0;
++ memset(tgt_dev->dev_latency_stat, 0,
++ sizeof(tgt_dev->dev_latency_stat));
++ }
++ }
++
++ spin_unlock_bh(&sess->lat_lock);
++
++ mutex_unlock(&scst_mutex);
++
++out_put:
++ kobject_put(&sess->sess_kobj);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_sess_latency_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_session *sess;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ sess = container_of(kobj, struct scst_session, sess_kobj);
++
++ res = scst_alloc_sysfs_work(scst_sess_zero_latency, false, &work);
++ if (res != 0)
++ goto out;
++
++ work->sess = sess;
++
++ kobject_get(&sess->sess_kobj);
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute session_latency_attr =
++ __ATTR(latency, S_IRUGO | S_IWUSR, scst_sess_latency_show,
++ scst_sess_latency_store);
++
++#endif /* CONFIG_SCST_MEASURE_LATENCY */
++
++static ssize_t scst_sess_sysfs_commands_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_session *sess;
++
++ sess = container_of(kobj, struct scst_session, sess_kobj);
++
++ return sprintf(buf, "%i\n", atomic_read(&sess->sess_cmd_count));
++}
++
++static struct kobj_attribute session_commands_attr =
++ __ATTR(commands, S_IRUGO, scst_sess_sysfs_commands_show, NULL);
++
++static int scst_sysfs_sess_get_active_commands(struct scst_session *sess)
++{
++ int res;
++ int active_cmds = 0, t;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_put;
++ }
++
++ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[t];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ active_cmds += atomic_read(&tgt_dev->tgt_dev_cmd_count);
++ }
++ }
++
++ mutex_unlock(&scst_mutex);
++
++ res = active_cmds;
++
++out_put:
++ kobject_put(&sess->sess_kobj);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_sysfs_sess_get_active_commands_work_fn(struct scst_sysfs_work_item *work)
++{
++ return scst_sysfs_sess_get_active_commands(work->sess);
++}
++
++static ssize_t scst_sess_sysfs_active_commands_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int res;
++ struct scst_session *sess;
++ struct scst_sysfs_work_item *work;
++
++ sess = container_of(kobj, struct scst_session, sess_kobj);
++
++ res = scst_alloc_sysfs_work(scst_sysfs_sess_get_active_commands_work_fn,
++ true, &work);
++ if (res != 0)
++ goto out;
++
++ work->sess = sess;
++
++ kobject_get(&sess->sess_kobj);
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res != -EAGAIN)
++ res = sprintf(buf, "%i\n", res);
++
++out:
++ return res;
++}
++
++static struct kobj_attribute session_active_commands_attr =
++ __ATTR(active_commands, S_IRUGO, scst_sess_sysfs_active_commands_show,
++ NULL);
++
++static ssize_t scst_sess_sysfs_initiator_name_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_session *sess;
++
++ sess = container_of(kobj, struct scst_session, sess_kobj);
++
++ return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
++ sess->initiator_name);
++}
++
++static struct kobj_attribute session_initiator_name_attr =
++ __ATTR(initiator_name, S_IRUGO, scst_sess_sysfs_initiator_name_show, NULL);
++
++static struct attribute *scst_session_attrs[] = {
++ &session_commands_attr.attr,
++ &session_active_commands_attr.attr,
++ &session_initiator_name_attr.attr,
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++ &session_latency_attr.attr,
++#endif /* CONFIG_SCST_MEASURE_LATENCY */
++ NULL,
++};
++
++static void scst_sysfs_session_release(struct kobject *kobj)
++{
++ struct scst_session *sess;
++
++ TRACE_ENTRY();
++
++ sess = container_of(kobj, struct scst_session, sess_kobj);
++ complete_all(&sess->sess_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct kobj_type scst_session_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_sysfs_session_release,
++ .default_attrs = scst_session_attrs,
++};
++
++static int scst_create_sess_luns_link(struct scst_session *sess)
++{
++ int res;
++
++ /*
++ * No locks are needed, because sess supposed to be in acg->acg_sess_list
++ * and tgt->sess_list, so blocking them from disappearing.
++ */
++
++ if (sess->acg == sess->tgt->default_acg)
++ res = sysfs_create_link(&sess->sess_kobj,
++ sess->tgt->tgt_luns_kobj, "luns");
++ else
++ res = sysfs_create_link(&sess->sess_kobj,
++ sess->acg->luns_kobj, "luns");
++
++ if (res != 0)
++ PRINT_ERROR("Can't create luns link for initiator %s",
++ sess->initiator_name);
++
++ return res;
++}
++
++int scst_recreate_sess_luns_link(struct scst_session *sess)
++{
++ sysfs_remove_link(&sess->sess_kobj, "luns");
++ return scst_create_sess_luns_link(sess);
++}
++
++/* Supposed to be called under scst_mutex */
++int scst_sess_sysfs_create(struct scst_session *sess)
++{
++ int res = 0;
++ struct scst_session *s;
++ const struct attribute **pattr;
++ char *name = (char *)sess->initiator_name;
++ int len = strlen(name) + 1, n = 1;
++
++ TRACE_ENTRY();
++
++restart:
++ list_for_each_entry(s, &sess->tgt->sess_list, sess_list_entry) {
++ if (!s->sess_kobj_ready)
++ continue;
++
++ if (strcmp(name, kobject_name(&s->sess_kobj)) == 0) {
++ if (s == sess)
++ continue;
++
++ TRACE_DBG("Dublicated session from the same initiator "
++ "%s found", name);
++
++ if (name == sess->initiator_name) {
++ len = strlen(sess->initiator_name);
++ len += 20;
++ name = kmalloc(len, GFP_KERNEL);
++ if (name == NULL) {
++ PRINT_ERROR("Unable to allocate a "
++ "replacement name (size %d)",
++ len);
++ }
++ }
++
++ snprintf(name, len, "%s_%d", sess->initiator_name, n);
++ n++;
++ goto restart;
++ }
++ }
++
++ init_completion(&sess->sess_kobj_release_cmpl);
++
++ TRACE_DBG("Adding session %s to sysfs", name);
++
++ res = kobject_init_and_add(&sess->sess_kobj, &scst_session_ktype,
++ sess->tgt->tgt_sess_kobj, name);
++ if (res != 0) {
++ PRINT_ERROR("Can't add session %s to sysfs", name);
++ goto out_free;
++ }
++
++ sess->sess_kobj_ready = 1;
++
++ pattr = sess->tgt->tgtt->sess_attrs;
++ if (pattr != NULL) {
++ while (*pattr != NULL) {
++ res = sysfs_create_file(&sess->sess_kobj, *pattr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add sess attr %s for sess "
++ "for initiator %s", (*pattr)->name,
++ name);
++ goto out_free;
++ }
++ pattr++;
++ }
++ }
++
++ res = scst_create_sess_luns_link(sess);
++
++out_free:
++ if (name != sess->initiator_name)
++ kfree(name);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * Must not be called under scst_mutex, due to possible deadlock with
++ * sysfs ref counting in sysfs works (it is waiting for the last put, but
++ * the last ref counter holder is waiting for scst_mutex)
++ */
++void scst_sess_sysfs_del(struct scst_session *sess)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ if (!sess->sess_kobj_ready)
++ goto out;
++
++ TRACE_DBG("Deleting session %s from sysfs",
++ kobject_name(&sess->sess_kobj));
++
++ kobject_del(&sess->sess_kobj);
++ kobject_put(&sess->sess_kobj);
++
++ rc = wait_for_completion_timeout(&sess->sess_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for session from %s (%d refs)...", sess->initiator_name,
++ atomic_read(&sess->sess_kobj.kref.refcount));
++ wait_for_completion(&sess->sess_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs "
++ "entry for session %s", sess->initiator_name);
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ ** Target luns directory implementation
++ **/
++
++static void scst_acg_dev_release(struct kobject *kobj)
++{
++ struct scst_acg_dev *acg_dev;
++
++ TRACE_ENTRY();
++
++ acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
++ complete_all(&acg_dev->acg_dev_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++static ssize_t scst_lun_rd_only_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ struct scst_acg_dev *acg_dev;
++
++ acg_dev = container_of(kobj, struct scst_acg_dev, acg_dev_kobj);
++
++ if (acg_dev->rd_only || acg_dev->dev->rd_only)
++ return sprintf(buf, "%d\n%s\n", 1, SCST_SYSFS_KEY_MARK);
++ else
++ return sprintf(buf, "%d\n", 0);
++}
++
++static struct kobj_attribute lun_options_attr =
++ __ATTR(read_only, S_IRUGO, scst_lun_rd_only_show, NULL);
++
++static struct attribute *lun_attrs[] = {
++ &lun_options_attr.attr,
++ NULL,
++};
++
++static struct kobj_type acg_dev_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_acg_dev_release,
++ .default_attrs = lun_attrs,
++};
++
++/*
++ * Called with scst_mutex held.
++ *
++ * !! No sysfs works must use kobject_get() to protect acg_dev, due to possible
++ * !! deadlock with scst_mutex (it is waiting for the last put, but
++ * !! the last ref counter holder is waiting for scst_mutex)
++ */
++void scst_acg_dev_sysfs_del(struct scst_acg_dev *acg_dev)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ if (acg_dev->dev != NULL) {
++ sysfs_remove_link(acg_dev->dev->dev_exp_kobj,
++ acg_dev->acg_dev_link_name);
++ kobject_put(&acg_dev->dev->dev_kobj);
++ }
++
++ kobject_del(&acg_dev->acg_dev_kobj);
++ kobject_put(&acg_dev->acg_dev_kobj);
++
++ rc = wait_for_completion_timeout(&acg_dev->acg_dev_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for acg_dev %p (%d refs)...", acg_dev,
++ atomic_read(&acg_dev->acg_dev_kobj.kref.refcount));
++ wait_for_completion(&acg_dev->acg_dev_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs "
++ "entry for acg_dev %p", acg_dev);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++int scst_acg_dev_sysfs_create(struct scst_acg_dev *acg_dev,
++ struct kobject *parent)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ init_completion(&acg_dev->acg_dev_kobj_release_cmpl);
++
++ res = kobject_init_and_add(&acg_dev->acg_dev_kobj, &acg_dev_ktype,
++ parent, "%u", acg_dev->lun);
++ if (res != 0) {
++ PRINT_ERROR("Can't add acg_dev %p to sysfs", acg_dev);
++ goto out;
++ }
++
++ kobject_get(&acg_dev->dev->dev_kobj);
++
++ snprintf(acg_dev->acg_dev_link_name, sizeof(acg_dev->acg_dev_link_name),
++ "export%u", acg_dev->dev->dev_exported_lun_num++);
++
++ res = sysfs_create_link(acg_dev->dev->dev_exp_kobj,
++ &acg_dev->acg_dev_kobj, acg_dev->acg_dev_link_name);
++ if (res != 0) {
++ PRINT_ERROR("Can't create acg %s LUN link",
++ acg_dev->acg->acg_name);
++ goto out_del;
++ }
++
++ res = sysfs_create_link(&acg_dev->acg_dev_kobj,
++ &acg_dev->dev->dev_kobj, "device");
++ if (res != 0) {
++ PRINT_ERROR("Can't create acg %s device link",
++ acg_dev->acg->acg_name);
++ goto out_del;
++ }
++
++out:
++ return res;
++
++out_del:
++ scst_acg_dev_sysfs_del(acg_dev);
++ goto out;
++}
++
++static int __scst_process_luns_mgmt_store(char *buffer,
++ struct scst_tgt *tgt, struct scst_acg *acg, bool tgt_kobj)
++{
++ int res, read_only = 0, action;
++ char *p, *e = NULL;
++ unsigned int virt_lun;
++ struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
++ struct scst_device *d, *dev = NULL;
++
++#define SCST_LUN_ACTION_ADD 1
++#define SCST_LUN_ACTION_DEL 2
++#define SCST_LUN_ACTION_REPLACE 3
++#define SCST_LUN_ACTION_CLEAR 4
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("buffer %s", buffer);
++
++ p = buffer;
++ if (p[strlen(p) - 1] == '\n')
++ p[strlen(p) - 1] = '\0';
++ if (strncasecmp("add", p, 3) == 0) {
++ p += 3;
++ action = SCST_LUN_ACTION_ADD;
++ } else if (strncasecmp("del", p, 3) == 0) {
++ p += 3;
++ action = SCST_LUN_ACTION_DEL;
++ } else if (!strncasecmp("replace", p, 7)) {
++ p += 7;
++ action = SCST_LUN_ACTION_REPLACE;
++ } else if (!strncasecmp("clear", p, 5)) {
++ p += 5;
++ action = SCST_LUN_ACTION_CLEAR;
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_resume;
++ }
++
++ /* Check if tgt and acg not already freed while we were coming here */
++ if (scst_check_tgt_acg_ptrs(tgt, acg) != 0)
++ goto out_unlock;
++
++ if ((action != SCST_LUN_ACTION_CLEAR) &&
++ (action != SCST_LUN_ACTION_DEL)) {
++ if (!isspace(*p)) {
++ PRINT_ERROR("%s", "Syntax error");
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ while (isspace(*p) && *p != '\0')
++ p++;
++ e = p; /* save p */
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = '\0';
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if (!strcmp(d->virt_name, p)) {
++ dev = d;
++ TRACE_DBG("Device %p (%s) found", dev, p);
++ break;
++ }
++ }
++ if (dev == NULL) {
++ PRINT_ERROR("Device '%s' not found", p);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ }
++
++ switch (action) {
++ case SCST_LUN_ACTION_ADD:
++ case SCST_LUN_ACTION_REPLACE:
++ {
++ bool dev_replaced = false;
++
++ e++;
++ while (isspace(*e) && *e != '\0')
++ e++;
++ virt_lun = simple_strtoul(e, &e, 0);
++
++ while (isspace(*e) && *e != '\0')
++ e++;
++
++ while (1) {
++ char *pp;
++ unsigned long val;
++ char *param = scst_get_next_token_str(&e);
++ if (param == NULL)
++ break;
++
++ p = scst_get_next_lexem(&param);
++ if (*p == '\0') {
++ PRINT_ERROR("Syntax error at %s (device %s)",
++ param, dev->virt_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ pp = scst_get_next_lexem(&param);
++ if (*pp == '\0') {
++ PRINT_ERROR("Parameter %s value missed for device %s",
++ p, dev->virt_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ if (scst_get_next_lexem(&param)[0] != '\0') {
++ PRINT_ERROR("Too many parameter's %s values (device %s)",
++ p, dev->virt_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ res = strict_strtoul(pp, 0, &val);
++ if (res != 0) {
++ PRINT_ERROR("strict_strtoul() for %s failed: %d "
++ "(device %s)", pp, res, dev->virt_name);
++ goto out_unlock;
++ }
++
++ if (!strcasecmp("read_only", p)) {
++ read_only = val;
++ TRACE_DBG("READ ONLY %d", read_only);
++ } else {
++ PRINT_ERROR("Unknown parameter %s (device %s)",
++ p, dev->virt_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ }
++
++ acg_dev = NULL;
++ list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
++ acg_dev_list_entry) {
++ if (acg_dev_tmp->lun == virt_lun) {
++ acg_dev = acg_dev_tmp;
++ break;
++ }
++ }
++
++ if (acg_dev != NULL) {
++ if (action == SCST_LUN_ACTION_ADD) {
++ PRINT_ERROR("virt lun %d already exists in "
++ "group %s", virt_lun, acg->acg_name);
++ res = -EEXIST;
++ goto out_unlock;
++ } else {
++ /* Replace */
++ res = scst_acg_del_lun(acg, acg_dev->lun,
++ false);
++ if (res != 0)
++ goto out_unlock;
++
++ dev_replaced = true;
++ }
++ }
++
++ res = scst_acg_add_lun(acg,
++ tgt_kobj ? tgt->tgt_luns_kobj : acg->luns_kobj,
++ dev, virt_lun, read_only, !dev_replaced, NULL);
++ if (res != 0)
++ goto out_unlock;
++
++ if (dev_replaced) {
++ struct scst_tgt_dev *tgt_dev;
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if ((tgt_dev->acg_dev->acg == acg) &&
++ (tgt_dev->lun == virt_lun)) {
++ TRACE_MGMT_DBG("INQUIRY DATA HAS CHANGED"
++ " on tgt_dev %p", tgt_dev);
++ scst_gen_aen_or_ua(tgt_dev,
++ SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
++ }
++ }
++ }
++
++ break;
++ }
++ case SCST_LUN_ACTION_DEL:
++ while (isspace(*p) && *p != '\0')
++ p++;
++ virt_lun = simple_strtoul(p, &p, 0);
++
++ res = scst_acg_del_lun(acg, virt_lun, true);
++ if (res != 0)
++ goto out_unlock;
++ break;
++ case SCST_LUN_ACTION_CLEAR:
++ PRINT_INFO("Removed all devices from group %s",
++ acg->acg_name);
++ list_for_each_entry_safe(acg_dev, acg_dev_tmp,
++ &acg->acg_dev_list,
++ acg_dev_list_entry) {
++ res = scst_acg_del_lun(acg, acg_dev->lun,
++ list_is_last(&acg_dev->acg_dev_list_entry,
++ &acg->acg_dev_list));
++ if (res)
++ goto out_unlock;
++ }
++ break;
++ }
++
++ res = 0;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out_resume:
++ scst_resume_activity();
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++#undef SCST_LUN_ACTION_ADD
++#undef SCST_LUN_ACTION_DEL
++#undef SCST_LUN_ACTION_REPLACE
++#undef SCST_LUN_ACTION_CLEAR
++}
++
++static int scst_luns_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
++{
++ return __scst_process_luns_mgmt_store(work->buf, work->tgt, work->acg,
++ work->is_tgt_kobj);
++}
++
++static ssize_t __scst_acg_mgmt_store(struct scst_acg *acg,
++ const char *buf, size_t count, bool is_tgt_kobj,
++ int (*sysfs_work_fn)(struct scst_sysfs_work_item *))
++{
++ int res;
++ char *buffer;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ buffer = kzalloc(count+1, GFP_KERNEL);
++ if (buffer == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++ memcpy(buffer, buf, count);
++ buffer[count] = '\0';
++
++ res = scst_alloc_sysfs_work(sysfs_work_fn, false, &work);
++ if (res != 0)
++ goto out_free;
++
++ work->buf = buffer;
++ work->tgt = acg->tgt;
++ work->acg = acg;
++ work->is_tgt_kobj = is_tgt_kobj;
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(buffer);
++ goto out;
++}
++
++static ssize_t __scst_luns_mgmt_store(struct scst_acg *acg,
++ bool tgt_kobj, const char *buf, size_t count)
++{
++ return __scst_acg_mgmt_store(acg, buf, count, tgt_kobj,
++ scst_luns_mgmt_store_work_fn);
++}
++
++static ssize_t scst_luns_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ static char *help = "Usage: echo \"add|del H:C:I:L lun [parameters]\" >mgmt\n"
++ " echo \"add VNAME lun [parameters]\" >mgmt\n"
++ " echo \"del lun\" >mgmt\n"
++ " echo \"replace H:C:I:L lun [parameters]\" >mgmt\n"
++ " echo \"replace VNAME lun [parameters]\" >mgmt\n"
++ " echo \"clear\" >mgmt\n"
++ "\n"
++ "where parameters are one or more "
++ "param_name=value pairs separated by ';'\n"
++ "\nThe following parameters available: read_only.";
++
++ return sprintf(buf, "%s", help);
++}
++
++static ssize_t scst_luns_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count)
++{
++ int res;
++ struct scst_acg *acg;
++ struct scst_tgt *tgt;
++
++ tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
++ acg = tgt->default_acg;
++
++ res = __scst_luns_mgmt_store(acg, true, buf, count);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t __scst_acg_addr_method_show(struct scst_acg *acg, char *buf)
++{
++ int res;
++
++ switch (acg->addr_method) {
++ case SCST_LUN_ADDR_METHOD_FLAT:
++ res = sprintf(buf, "FLAT\n%s\n", SCST_SYSFS_KEY_MARK);
++ break;
++ case SCST_LUN_ADDR_METHOD_PERIPHERAL:
++ res = sprintf(buf, "PERIPHERAL\n");
++ break;
++ default:
++ res = sprintf(buf, "UNKNOWN\n");
++ break;
++ }
++
++ return res;
++}
++
++static ssize_t __scst_acg_addr_method_store(struct scst_acg *acg,
++ const char *buf, size_t count)
++{
++ int res = count;
++
++ if (strncasecmp(buf, "FLAT", min_t(int, 4, count)) == 0)
++ acg->addr_method = SCST_LUN_ADDR_METHOD_FLAT;
++ else if (strncasecmp(buf, "PERIPHERAL", min_t(int, 10, count)) == 0)
++ acg->addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
++ else {
++ PRINT_ERROR("Unknown address method %s", buf);
++ res = -EINVAL;
++ }
++
++ TRACE_DBG("acg %p, addr_method %d", acg, acg->addr_method);
++
++ return res;
++}
++
++static ssize_t scst_tgt_addr_method_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_acg *acg;
++ struct scst_tgt *tgt;
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ acg = tgt->default_acg;
++
++ return __scst_acg_addr_method_show(acg, buf);
++}
++
++static ssize_t scst_tgt_addr_method_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_acg *acg;
++ struct scst_tgt *tgt;
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ acg = tgt->default_acg;
++
++ res = __scst_acg_addr_method_store(acg, buf, count);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t __scst_acg_io_grouping_type_show(struct scst_acg *acg, char *buf)
++{
++ int res;
++
++ switch (acg->acg_io_grouping_type) {
++ case SCST_IO_GROUPING_AUTO:
++ res = sprintf(buf, "%s\n", SCST_IO_GROUPING_AUTO_STR);
++ break;
++ case SCST_IO_GROUPING_THIS_GROUP_ONLY:
++ res = sprintf(buf, "%s\n%s\n",
++ SCST_IO_GROUPING_THIS_GROUP_ONLY_STR,
++ SCST_SYSFS_KEY_MARK);
++ break;
++ case SCST_IO_GROUPING_NEVER:
++ res = sprintf(buf, "%s\n%s\n", SCST_IO_GROUPING_NEVER_STR,
++ SCST_SYSFS_KEY_MARK);
++ break;
++ default:
++ res = sprintf(buf, "%d\n%s\n", acg->acg_io_grouping_type,
++ SCST_SYSFS_KEY_MARK);
++ break;
++ }
++
++ return res;
++}
++
++static int __scst_acg_process_io_grouping_type_store(struct scst_tgt *tgt,
++ struct scst_acg *acg, int io_grouping_type)
++{
++ int res = 0;
++ struct scst_acg_dev *acg_dev;
++
++ TRACE_DBG("tgt %p, acg %p, io_grouping_type %d", tgt, acg,
++ io_grouping_type);
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_resume;
++ }
++
++ /* Check if tgt and acg not already freed while we were coming here */
++ if (scst_check_tgt_acg_ptrs(tgt, acg) != 0)
++ goto out_unlock;
++
++ acg->acg_io_grouping_type = io_grouping_type;
++
++ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
++ int rc;
++
++ scst_stop_dev_threads(acg_dev->dev);
++
++ rc = scst_create_dev_threads(acg_dev->dev);
++ if (rc != 0)
++ res = rc;
++ }
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out_resume:
++ scst_resume_activity();
++
++out:
++ return res;
++}
++
++static int __scst_acg_io_grouping_type_store_work_fn(struct scst_sysfs_work_item *work)
++{
++ return __scst_acg_process_io_grouping_type_store(work->tgt, work->acg,
++ work->io_grouping_type);
++}
++
++static ssize_t __scst_acg_io_grouping_type_store(struct scst_acg *acg,
++ const char *buf, size_t count)
++{
++ int res = 0;
++ int prev = acg->acg_io_grouping_type;
++ long io_grouping_type;
++ struct scst_sysfs_work_item *work;
++
++ if (strncasecmp(buf, SCST_IO_GROUPING_AUTO_STR,
++ min_t(int, strlen(SCST_IO_GROUPING_AUTO_STR), count)) == 0)
++ io_grouping_type = SCST_IO_GROUPING_AUTO;
++ else if (strncasecmp(buf, SCST_IO_GROUPING_THIS_GROUP_ONLY_STR,
++ min_t(int, strlen(SCST_IO_GROUPING_THIS_GROUP_ONLY_STR), count)) == 0)
++ io_grouping_type = SCST_IO_GROUPING_THIS_GROUP_ONLY;
++ else if (strncasecmp(buf, SCST_IO_GROUPING_NEVER_STR,
++ min_t(int, strlen(SCST_IO_GROUPING_NEVER_STR), count)) == 0)
++ io_grouping_type = SCST_IO_GROUPING_NEVER;
++ else {
++ res = strict_strtol(buf, 0, &io_grouping_type);
++ if ((res != 0) || (io_grouping_type <= 0)) {
++ PRINT_ERROR("Unknown or not allowed I/O grouping type "
++ "%s", buf);
++ res = -EINVAL;
++ goto out;
++ }
++ }
++
++ if (prev == io_grouping_type)
++ goto out;
++
++ res = scst_alloc_sysfs_work(__scst_acg_io_grouping_type_store_work_fn,
++ false, &work);
++ if (res != 0)
++ goto out;
++
++ work->tgt = acg->tgt;
++ work->acg = acg;
++ work->io_grouping_type = io_grouping_type;
++
++ res = scst_sysfs_queue_wait_work(work);
++
++out:
++ return res;
++}
++
++static ssize_t scst_tgt_io_grouping_type_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_acg *acg;
++ struct scst_tgt *tgt;
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ acg = tgt->default_acg;
++
++ return __scst_acg_io_grouping_type_show(acg, buf);
++}
++
++static ssize_t scst_tgt_io_grouping_type_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_acg *acg;
++ struct scst_tgt *tgt;
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ acg = tgt->default_acg;
++
++ res = __scst_acg_io_grouping_type_store(acg, buf, count);
++ if (res != 0)
++ goto out;
++
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * Called with scst_mutex held.
++ *
++ * !! No sysfs works must use kobject_get() to protect acg, due to possible
++ * !! deadlock with scst_mutex (it is waiting for the last put, but
++ * !! the last ref counter holder is waiting for scst_mutex)
++ */
++void scst_acg_sysfs_del(struct scst_acg *acg)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ kobject_del(acg->luns_kobj);
++ kobject_del(acg->initiators_kobj);
++ kobject_del(&acg->acg_kobj);
++
++ kobject_put(acg->luns_kobj);
++ kobject_put(acg->initiators_kobj);
++ kobject_put(&acg->acg_kobj);
++
++ rc = wait_for_completion_timeout(&acg->acg_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for acg %s (%d refs)...", acg->acg_name,
++ atomic_read(&acg->acg_kobj.kref.refcount));
++ wait_for_completion(&acg->acg_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs "
++ "entry for acg %s", acg->acg_name);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++int scst_acg_sysfs_create(struct scst_tgt *tgt,
++ struct scst_acg *acg)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ init_completion(&acg->acg_kobj_release_cmpl);
++
++ res = kobject_init_and_add(&acg->acg_kobj, &acg_ktype,
++ tgt->tgt_ini_grp_kobj, acg->acg_name);
++ if (res != 0) {
++ PRINT_ERROR("Can't add acg '%s' to sysfs", acg->acg_name);
++ goto out;
++ }
++
++ acg->luns_kobj = kobject_create_and_add("luns", &acg->acg_kobj);
++ if (acg->luns_kobj == NULL) {
++ PRINT_ERROR("Can't create luns kobj for tgt %s",
++ tgt->tgt_name);
++ res = -ENOMEM;
++ goto out_del;
++ }
++
++ res = sysfs_create_file(acg->luns_kobj, &scst_acg_luns_mgmt.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
++ scst_acg_luns_mgmt.attr.name, tgt->tgt_name);
++ goto out_del;
++ }
++
++ acg->initiators_kobj = kobject_create_and_add("initiators",
++ &acg->acg_kobj);
++ if (acg->initiators_kobj == NULL) {
++ PRINT_ERROR("Can't create initiators kobj for tgt %s",
++ tgt->tgt_name);
++ res = -ENOMEM;
++ goto out_del;
++ }
++
++ res = sysfs_create_file(acg->initiators_kobj,
++ &scst_acg_ini_mgmt.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
++ scst_acg_ini_mgmt.attr.name, tgt->tgt_name);
++ goto out_del;
++ }
++
++ res = sysfs_create_file(&acg->acg_kobj, &scst_acg_addr_method.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
++ scst_acg_addr_method.attr.name, tgt->tgt_name);
++ goto out_del;
++ }
++
++ res = sysfs_create_file(&acg->acg_kobj, &scst_acg_io_grouping_type.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add tgt attr %s for tgt %s",
++ scst_acg_io_grouping_type.attr.name, tgt->tgt_name);
++ goto out_del;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ scst_acg_sysfs_del(acg);
++ goto out;
++}
++
++static ssize_t scst_acg_addr_method_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_acg *acg;
++
++ acg = container_of(kobj, struct scst_acg, acg_kobj);
++
++ return __scst_acg_addr_method_show(acg, buf);
++}
++
++static ssize_t scst_acg_addr_method_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_acg *acg;
++
++ acg = container_of(kobj, struct scst_acg, acg_kobj);
++
++ res = __scst_acg_addr_method_store(acg, buf, count);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_acg_io_grouping_type_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_acg *acg;
++
++ acg = container_of(kobj, struct scst_acg, acg_kobj);
++
++ return __scst_acg_io_grouping_type_show(acg, buf);
++}
++
++static ssize_t scst_acg_io_grouping_type_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_acg *acg;
++
++ acg = container_of(kobj, struct scst_acg, acg_kobj);
++
++ res = __scst_acg_io_grouping_type_store(acg, buf, count);
++ if (res != 0)
++ goto out;
++
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_ini_group_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ static char *help = "Usage: echo \"create GROUP_NAME\" >mgmt\n"
++ " echo \"del GROUP_NAME\" >mgmt\n";
++
++ return sprintf(buf, "%s", help);
++}
++
++static int scst_process_ini_group_mgmt_store(char *buffer,
++ struct scst_tgt *tgt)
++{
++ int res, action;
++ int len;
++ char *name;
++ char *p, *e = NULL;
++ struct scst_acg *a, *acg = NULL;
++
++#define SCST_INI_GROUP_ACTION_CREATE 1
++#define SCST_INI_GROUP_ACTION_DEL 2
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("tgt %p, buffer %s", tgt, buffer);
++
++ p = buffer;
++ if (p[strlen(p) - 1] == '\n')
++ p[strlen(p) - 1] = '\0';
++ if (strncasecmp("create ", p, 7) == 0) {
++ p += 7;
++ action = SCST_INI_GROUP_ACTION_CREATE;
++ } else if (strncasecmp("del ", p, 4) == 0) {
++ p += 4;
++ action = SCST_INI_GROUP_ACTION_DEL;
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_resume;
++ }
++
++ /* Check if our pointer is still alive */
++ if (scst_check_tgt_acg_ptrs(tgt, NULL) != 0)
++ goto out_unlock;
++
++ while (isspace(*p) && *p != '\0')
++ p++;
++ e = p;
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = '\0';
++
++ if (p[0] == '\0') {
++ PRINT_ERROR("%s", "Group name required");
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ list_for_each_entry(a, &tgt->tgt_acg_list, acg_list_entry) {
++ if (strcmp(a->acg_name, p) == 0) {
++ TRACE_DBG("group (acg) %p %s found",
++ a, a->acg_name);
++ acg = a;
++ break;
++ }
++ }
++
++ switch (action) {
++ case SCST_INI_GROUP_ACTION_CREATE:
++ TRACE_DBG("Creating group '%s'", p);
++ if (acg != NULL) {
++ PRINT_ERROR("acg name %s exist", p);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ len = strlen(p) + 1;
++ name = kmalloc(len, GFP_KERNEL);
++ if (name == NULL) {
++ PRINT_ERROR("%s", "Allocation of name failed");
++ res = -ENOMEM;
++ goto out_unlock;
++ }
++ strlcpy(name, p, len);
++
++ acg = scst_alloc_add_acg(tgt, name, true);
++ kfree(name);
++ if (acg == NULL)
++ goto out_unlock;
++ break;
++ case SCST_INI_GROUP_ACTION_DEL:
++ TRACE_DBG("Deleting group '%s'", p);
++ if (acg == NULL) {
++ PRINT_ERROR("Group %s not found", p);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ if (!scst_acg_sess_is_empty(acg)) {
++ PRINT_ERROR("Group %s is not empty", acg->acg_name);
++ res = -EBUSY;
++ goto out_unlock;
++ }
++ scst_del_free_acg(acg);
++ break;
++ }
++
++ res = 0;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out_resume:
++ scst_resume_activity();
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++#undef SCST_LUN_ACTION_CREATE
++#undef SCST_LUN_ACTION_DEL
++}
++
++static int scst_ini_group_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
++{
++ return scst_process_ini_group_mgmt_store(work->buf, work->tgt);
++}
++
++static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ char *buffer;
++ struct scst_tgt *tgt;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ tgt = container_of(kobj->parent, struct scst_tgt, tgt_kobj);
++
++ buffer = kzalloc(count+1, GFP_KERNEL);
++ if (buffer == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++ memcpy(buffer, buf, count);
++ buffer[count] = '\0';
++
++ res = scst_alloc_sysfs_work(scst_ini_group_mgmt_store_work_fn, false,
++ &work);
++ if (res != 0)
++ goto out_free;
++
++ work->buf = buffer;
++ work->tgt = tgt;
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(buffer);
++ goto out;
++}
++
++static ssize_t scst_rel_tgt_id_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_tgt *tgt;
++ int res;
++
++ TRACE_ENTRY();
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++
++ res = sprintf(buf, "%d\n%s", tgt->rel_tgt_id,
++ (tgt->rel_tgt_id != 0) ? SCST_SYSFS_KEY_MARK "\n" : "");
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_process_rel_tgt_id_store(struct scst_sysfs_work_item *work)
++{
++ int res = 0;
++ struct scst_tgt *tgt = work->tgt;
++ unsigned long rel_tgt_id = work->l;
++
++ TRACE_ENTRY();
++
++ /* tgt protected by kobject_get() */
++
++ TRACE_DBG("Trying to set relative target port id %d",
++ (uint16_t)rel_tgt_id);
++
++ if (tgt->tgtt->is_target_enabled(tgt) &&
++ rel_tgt_id != tgt->rel_tgt_id) {
++ if (!scst_is_relative_target_port_id_unique(rel_tgt_id, tgt)) {
++ PRINT_ERROR("Relative port id %d is not unique",
++ (uint16_t)rel_tgt_id);
++ res = -EBADSLT;
++ goto out_put;
++ }
++ }
++
++ if (rel_tgt_id < SCST_MIN_REL_TGT_ID ||
++ rel_tgt_id > SCST_MAX_REL_TGT_ID) {
++ if ((rel_tgt_id == 0) && !tgt->tgtt->is_target_enabled(tgt))
++ goto set;
++
++ PRINT_ERROR("Invalid relative port id %d",
++ (uint16_t)rel_tgt_id);
++ res = -EINVAL;
++ goto out_put;
++ }
++
++set:
++ tgt->rel_tgt_id = (uint16_t)rel_tgt_id;
++
++out_put:
++ kobject_put(&tgt->tgt_kobj);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res = 0;
++ struct scst_tgt *tgt;
++ unsigned long rel_tgt_id;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ if (buf == NULL)
++ goto out;
++
++ tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++
++ res = strict_strtoul(buf, 0, &rel_tgt_id);
++ if (res != 0) {
++ PRINT_ERROR("%s", "Wrong rel_tgt_id");
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_alloc_sysfs_work(scst_process_rel_tgt_id_store, false,
++ &work);
++ if (res != 0)
++ goto out;
++
++ work->tgt = tgt;
++ work->l = rel_tgt_id;
++
++ kobject_get(&tgt->tgt_kobj);
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++int scst_acn_sysfs_create(struct scst_acn *acn)
++{
++ int res = 0;
++ int len;
++ struct scst_acg *acg = acn->acg;
++ struct kobj_attribute *attr = NULL;
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++ static struct lock_class_key __key;
++#endif
++
++ TRACE_ENTRY();
++
++ acn->acn_attr = NULL;
++
++ attr = kzalloc(sizeof(struct kobj_attribute), GFP_KERNEL);
++ if (attr == NULL) {
++ PRINT_ERROR("Unable to allocate attributes for initiator '%s'",
++ acn->name);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ len = strlen(acn->name) + 1;
++ attr->attr.name = kzalloc(len, GFP_KERNEL);
++ if (attr->attr.name == NULL) {
++ PRINT_ERROR("Unable to allocate attributes for initiator '%s'",
++ acn->name);
++ res = -ENOMEM;
++ goto out_free;
++ }
++ strlcpy((char *)attr->attr.name, acn->name, len);
++
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++ attr->attr.key = &__key;
++#endif
++
++ attr->attr.mode = S_IRUGO;
++ attr->show = scst_acn_file_show;
++ attr->store = NULL;
++
++ res = sysfs_create_file(acg->initiators_kobj, &attr->attr);
++ if (res != 0) {
++ PRINT_ERROR("Unable to create acn '%s' for group '%s'",
++ acn->name, acg->acg_name);
++ kfree(attr->attr.name);
++ goto out_free;
++ }
++
++ acn->acn_attr = attr;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(attr);
++ goto out;
++}
++
++void scst_acn_sysfs_del(struct scst_acn *acn)
++{
++ struct scst_acg *acg = acn->acg;
++
++ TRACE_ENTRY();
++
++ if (acn->acn_attr != NULL) {
++ sysfs_remove_file(acg->initiators_kobj,
++ &acn->acn_attr->attr);
++ kfree(acn->acn_attr->attr.name);
++ kfree(acn->acn_attr);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static ssize_t scst_acn_file_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n",
++ attr->attr.name);
++}
++
++static ssize_t scst_acg_luns_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count)
++{
++ int res;
++ struct scst_acg *acg;
++
++ acg = container_of(kobj->parent, struct scst_acg, acg_kobj);
++ res = __scst_luns_mgmt_store(acg, false, buf, count);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_acg_ini_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ static char *help = "Usage: echo \"add INITIATOR_NAME\" "
++ ">mgmt\n"
++ " echo \"del INITIATOR_NAME\" "
++ ">mgmt\n"
++ " echo \"move INITIATOR_NAME DEST_GROUP_NAME\" "
++ ">mgmt\n"
++ " echo \"clear\" "
++ ">mgmt\n";
++
++ return sprintf(buf, "%s", help);
++}
++
++static int scst_process_acg_ini_mgmt_store(char *buffer,
++ struct scst_tgt *tgt, struct scst_acg *acg)
++{
++ int res, action;
++ char *p, *e = NULL;
++ char *name = NULL, *group = NULL;
++ struct scst_acg *acg_dest = NULL;
++ struct scst_acn *acn = NULL, *acn_tmp;
++
++#define SCST_ACG_ACTION_INI_ADD 1
++#define SCST_ACG_ACTION_INI_DEL 2
++#define SCST_ACG_ACTION_INI_CLEAR 3
++#define SCST_ACG_ACTION_INI_MOVE 4
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("tgt %p, acg %p, buffer %s", tgt, acg, buffer);
++
++ p = buffer;
++ if (p[strlen(p) - 1] == '\n')
++ p[strlen(p) - 1] = '\0';
++
++ if (strncasecmp("add", p, 3) == 0) {
++ p += 3;
++ action = SCST_ACG_ACTION_INI_ADD;
++ } else if (strncasecmp("del", p, 3) == 0) {
++ p += 3;
++ action = SCST_ACG_ACTION_INI_DEL;
++ } else if (strncasecmp("clear", p, 5) == 0) {
++ p += 5;
++ action = SCST_ACG_ACTION_INI_CLEAR;
++ } else if (strncasecmp("move", p, 4) == 0) {
++ p += 4;
++ action = SCST_ACG_ACTION_INI_MOVE;
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (action != SCST_ACG_ACTION_INI_CLEAR)
++ if (!isspace(*p)) {
++ PRINT_ERROR("%s", "Syntax error");
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_resume;
++ }
++
++ /* Check if tgt and acg not already freed while we were coming here */
++ if (scst_check_tgt_acg_ptrs(tgt, acg) != 0)
++ goto out_unlock;
++
++ if (action != SCST_ACG_ACTION_INI_CLEAR)
++ while (isspace(*p) && *p != '\0')
++ p++;
++
++ switch (action) {
++ case SCST_ACG_ACTION_INI_ADD:
++ e = p;
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = '\0';
++ name = p;
++
++ if (name[0] == '\0') {
++ PRINT_ERROR("%s", "Invalid initiator name");
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ res = scst_acg_add_acn(acg, name);
++ if (res != 0)
++ goto out_unlock;
++ break;
++ case SCST_ACG_ACTION_INI_DEL:
++ e = p;
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = '\0';
++ name = p;
++
++ if (name[0] == '\0') {
++ PRINT_ERROR("%s", "Invalid initiator name");
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ acn = scst_find_acn(acg, name);
++ if (acn == NULL) {
++ PRINT_ERROR("Unable to find "
++ "initiator '%s' in group '%s'",
++ name, acg->acg_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ scst_del_free_acn(acn, true);
++ break;
++ case SCST_ACG_ACTION_INI_CLEAR:
++ list_for_each_entry_safe(acn, acn_tmp, &acg->acn_list,
++ acn_list_entry) {
++ scst_del_free_acn(acn, false);
++ }
++ scst_check_reassign_sessions();
++ break;
++ case SCST_ACG_ACTION_INI_MOVE:
++ e = p;
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ if (*e == '\0') {
++ PRINT_ERROR("%s", "Too few parameters");
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ *e = '\0';
++ name = p;
++
++ if (name[0] == '\0') {
++ PRINT_ERROR("%s", "Invalid initiator name");
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ e++;
++ p = e;
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = '\0';
++ group = p;
++
++ if (group[0] == '\0') {
++ PRINT_ERROR("%s", "Invalid group name");
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ TRACE_DBG("Move initiator '%s' to group '%s'",
++ name, group);
++
++ acn = scst_find_acn(acg, name);
++ if (acn == NULL) {
++ PRINT_ERROR("Unable to find "
++ "initiator '%s' in group '%s'",
++ name, acg->acg_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ acg_dest = scst_tgt_find_acg(tgt, group);
++ if (acg_dest == NULL) {
++ PRINT_ERROR("Unable to find group '%s' in target '%s'",
++ group, tgt->tgt_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ if (scst_find_acn(acg_dest, name) != NULL) {
++ PRINT_ERROR("Initiator '%s' already exists in group '%s'",
++ name, acg_dest->acg_name);
++ res = -EEXIST;
++ goto out_unlock;
++ }
++ scst_del_free_acn(acn, false);
++
++ res = scst_acg_add_acn(acg_dest, name);
++ if (res != 0)
++ goto out_unlock;
++ break;
++ }
++
++ res = 0;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out_resume:
++ scst_resume_activity();
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++#undef SCST_ACG_ACTION_INI_ADD
++#undef SCST_ACG_ACTION_INI_DEL
++#undef SCST_ACG_ACTION_INI_CLEAR
++#undef SCST_ACG_ACTION_INI_MOVE
++}
++
++static int scst_acg_ini_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
++{
++ return scst_process_acg_ini_mgmt_store(work->buf, work->tgt, work->acg);
++}
++
++static ssize_t scst_acg_ini_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ struct scst_acg *acg;
++
++ acg = container_of(kobj->parent, struct scst_acg, acg_kobj);
++
++ return __scst_acg_mgmt_store(acg, buf, count, false,
++ scst_acg_ini_mgmt_store_work_fn);
++}
++
++/**
++ ** SGV directory implementation
++ **/
++
++static struct kobj_attribute sgv_stat_attr =
++ __ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show,
++ sgv_sysfs_stat_reset);
++
++static struct attribute *sgv_attrs[] = {
++ &sgv_stat_attr.attr,
++ NULL,
++};
++
++static void sgv_kobj_release(struct kobject *kobj)
++{
++ struct sgv_pool *pool;
++
++ TRACE_ENTRY();
++
++ pool = container_of(kobj, struct sgv_pool, sgv_kobj);
++ complete_all(&pool->sgv_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct kobj_type sgv_pool_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = sgv_kobj_release,
++ .default_attrs = sgv_attrs,
++};
++
++int scst_sgv_sysfs_create(struct sgv_pool *pool)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ init_completion(&pool->sgv_kobj_release_cmpl);
++
++ res = kobject_init_and_add(&pool->sgv_kobj, &sgv_pool_ktype,
++ scst_sgv_kobj, pool->name);
++ if (res != 0) {
++ PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name);
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++void scst_sgv_sysfs_del(struct sgv_pool *pool)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ kobject_del(&pool->sgv_kobj);
++ kobject_put(&pool->sgv_kobj);
++
++ rc = wait_for_completion_timeout(&pool->sgv_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for SGV pool %s (%d refs)...", pool->name,
++ atomic_read(&pool->sgv_kobj.kref.refcount));
++ wait_for_completion(&pool->sgv_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs "
++ "entry for SGV pool %s", pool->name);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct kobj_attribute sgv_global_stat_attr =
++ __ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show,
++ sgv_sysfs_global_stat_reset);
++
++static struct attribute *sgv_default_attrs[] = {
++ &sgv_global_stat_attr.attr,
++ NULL,
++};
++
++static void scst_sysfs_release(struct kobject *kobj)
++{
++ kfree(kobj);
++}
++
++static struct kobj_type sgv_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_sysfs_release,
++ .default_attrs = sgv_default_attrs,
++};
++
++/**
++ ** SCST sysfs root directory implementation
++ **/
++
++static ssize_t scst_threads_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int count;
++
++ TRACE_ENTRY();
++
++ count = sprintf(buf, "%d\n%s", scst_main_cmd_threads.nr_threads,
++ (scst_main_cmd_threads.nr_threads != scst_threads) ?
++ SCST_SYSFS_KEY_MARK "\n" : "");
++
++ TRACE_EXIT();
++ return count;
++}
++
++static int scst_process_threads_store(int newtn)
++{
++ int res;
++ long oldtn, delta;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("newtn %d", newtn);
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ oldtn = scst_main_cmd_threads.nr_threads;
++
++ delta = newtn - oldtn;
++ if (delta < 0)
++ scst_del_threads(&scst_main_cmd_threads, -delta);
++ else {
++ res = scst_add_threads(&scst_main_cmd_threads, NULL, NULL, delta);
++ if (res != 0)
++ goto out_up;
++ }
++
++ PRINT_INFO("Changed cmd threads num: old %ld, new %d", oldtn, newtn);
++
++out_up:
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_threads_store_work_fn(struct scst_sysfs_work_item *work)
++{
++ return scst_process_threads_store(work->new_threads_num);
++}
++
++static ssize_t scst_threads_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ long newtn;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ res = strict_strtol(buf, 0, &newtn);
++ if (res != 0) {
++ PRINT_ERROR("strict_strtol() for %s failed: %d ", buf, res);
++ goto out;
++ }
++ if (newtn <= 0) {
++ PRINT_ERROR("Illegal threads num value %ld", newtn);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_alloc_sysfs_work(scst_threads_store_work_fn, false, &work);
++ if (res != 0)
++ goto out;
++
++ work->new_threads_num = newtn;
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_setup_id_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int count;
++
++ TRACE_ENTRY();
++
++ count = sprintf(buf, "0x%x\n%s\n", scst_setup_id,
++ (scst_setup_id == 0) ? "" : SCST_SYSFS_KEY_MARK);
++
++ TRACE_EXIT();
++ return count;
++}
++
++static ssize_t scst_setup_id_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ unsigned long val;
++
++ TRACE_ENTRY();
++
++ res = strict_strtoul(buf, 0, &val);
++ if (res != 0) {
++ PRINT_ERROR("strict_strtoul() for %s failed: %d ", buf, res);
++ goto out;
++ }
++
++ scst_setup_id = val;
++ PRINT_INFO("Changed scst_setup_id to %x", scst_setup_id);
++
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++static void scst_read_trace_tlb(const struct scst_trace_log *tbl, char *buf,
++ unsigned long log_level, int *pos)
++{
++ const struct scst_trace_log *t = tbl;
++
++ if (t == NULL)
++ goto out;
++
++ while (t->token) {
++ if (log_level & t->val) {
++ *pos += sprintf(&buf[*pos], "%s%s",
++ (*pos == 0) ? "" : " | ",
++ t->token);
++ }
++ t++;
++ }
++out:
++ return;
++}
++
++static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
++ unsigned long log_level, char *buf, const char *help)
++{
++ int pos = 0;
++
++ scst_read_trace_tlb(scst_trace_tbl, buf, log_level, &pos);
++ scst_read_trace_tlb(local_tbl, buf, log_level, &pos);
++
++ pos += sprintf(&buf[pos], "\n\n\nUsage:\n"
++ " echo \"all|none|default\" >trace_level\n"
++ " echo \"value DEC|0xHEX|0OCT\" >trace_level\n"
++ " echo \"add|del TOKEN\" >trace_level\n"
++ "\nwhere TOKEN is one of [debug, function, line, pid,\n"
++#ifndef GENERATING_UPSTREAM_PATCH
++ " entryexit, buff, mem, sg, out_of_mem,\n"
++#else
++ " buff, mem, sg, out_of_mem,\n"
++#endif
++ " special, scsi, mgmt, minor,\n"
++ " mgmt_dbg, scsi_serializing,\n"
++ " retry, recv_bot, send_bot, recv_top, pr,\n"
++ " send_top%s]", help != NULL ? help : "");
++
++ return pos;
++}
++
++static ssize_t scst_main_trace_level_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ return scst_trace_level_show(scst_local_trace_tbl, trace_flag,
++ buf, NULL);
++}
++
++static int scst_write_trace(const char *buf, size_t length,
++ unsigned long *log_level, unsigned long default_level,
++ const char *name, const struct scst_trace_log *tbl)
++{
++ int res = length;
++ int action;
++ unsigned long level = 0, oldlevel;
++ char *buffer, *p, *e;
++ const struct scst_trace_log *t;
++
++#define SCST_TRACE_ACTION_ALL 1
++#define SCST_TRACE_ACTION_NONE 2
++#define SCST_TRACE_ACTION_DEFAULT 3
++#define SCST_TRACE_ACTION_ADD 4
++#define SCST_TRACE_ACTION_DEL 5
++#define SCST_TRACE_ACTION_VALUE 6
++
++ TRACE_ENTRY();
++
++ if ((buf == NULL) || (length == 0)) {
++ res = -EINVAL;
++ goto out;
++ }
++
++ buffer = kmalloc(length+1, GFP_KERNEL);
++ if (buffer == NULL) {
++ PRINT_ERROR("Unable to alloc intermediate buffer (size %zd)",
++ length+1);
++ res = -ENOMEM;
++ goto out;
++ }
++ memcpy(buffer, buf, length);
++ buffer[length] = '\0';
++
++ TRACE_DBG("buffer %s", buffer);
++
++ p = buffer;
++ if (!strncasecmp("all", p, 3)) {
++ action = SCST_TRACE_ACTION_ALL;
++ } else if (!strncasecmp("none", p, 4) || !strncasecmp("null", p, 4)) {
++ action = SCST_TRACE_ACTION_NONE;
++ } else if (!strncasecmp("default", p, 7)) {
++ action = SCST_TRACE_ACTION_DEFAULT;
++ } else if (!strncasecmp("add", p, 3)) {
++ p += 3;
++ action = SCST_TRACE_ACTION_ADD;
++ } else if (!strncasecmp("del", p, 3)) {
++ p += 3;
++ action = SCST_TRACE_ACTION_DEL;
++ } else if (!strncasecmp("value", p, 5)) {
++ p += 5;
++ action = SCST_TRACE_ACTION_VALUE;
++ } else {
++ if (p[strlen(p) - 1] == '\n')
++ p[strlen(p) - 1] = '\0';
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ switch (action) {
++ case SCST_TRACE_ACTION_ADD:
++ case SCST_TRACE_ACTION_DEL:
++ case SCST_TRACE_ACTION_VALUE:
++ if (!isspace(*p)) {
++ PRINT_ERROR("%s", "Syntax error");
++ res = -EINVAL;
++ goto out_free;
++ }
++ }
++
++ switch (action) {
++ case SCST_TRACE_ACTION_ALL:
++ level = TRACE_ALL;
++ break;
++ case SCST_TRACE_ACTION_DEFAULT:
++ level = default_level;
++ break;
++ case SCST_TRACE_ACTION_NONE:
++ level = TRACE_NULL;
++ break;
++ case SCST_TRACE_ACTION_ADD:
++ case SCST_TRACE_ACTION_DEL:
++ while (isspace(*p) && *p != '\0')
++ p++;
++ e = p;
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = 0;
++ if (tbl) {
++ t = tbl;
++ while (t->token) {
++ if (!strcasecmp(p, t->token)) {
++ level = t->val;
++ break;
++ }
++ t++;
++ }
++ }
++ if (level == 0) {
++ t = scst_trace_tbl;
++ while (t->token) {
++ if (!strcasecmp(p, t->token)) {
++ level = t->val;
++ break;
++ }
++ t++;
++ }
++ }
++ if (level == 0) {
++ PRINT_ERROR("Unknown token \"%s\"", p);
++ res = -EINVAL;
++ goto out_free;
++ }
++ break;
++ case SCST_TRACE_ACTION_VALUE:
++ while (isspace(*p) && *p != '\0')
++ p++;
++ res = strict_strtoul(p, 0, &level);
++ if (res != 0) {
++ PRINT_ERROR("Invalid trace value \"%s\"", p);
++ res = -EINVAL;
++ goto out_free;
++ }
++ break;
++ }
++
++ oldlevel = *log_level;
++
++ switch (action) {
++ case SCST_TRACE_ACTION_ADD:
++ *log_level |= level;
++ break;
++ case SCST_TRACE_ACTION_DEL:
++ *log_level &= ~level;
++ break;
++ default:
++ *log_level = level;
++ break;
++ }
++
++ PRINT_INFO("Changed trace level for \"%s\": old 0x%08lx, new 0x%08lx",
++ name, oldlevel, *log_level);
++
++out_free:
++ kfree(buffer);
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++#undef SCST_TRACE_ACTION_ALL
++#undef SCST_TRACE_ACTION_NONE
++#undef SCST_TRACE_ACTION_DEFAULT
++#undef SCST_TRACE_ACTION_ADD
++#undef SCST_TRACE_ACTION_DEL
++#undef SCST_TRACE_ACTION_VALUE
++}
++
++static ssize_t scst_main_trace_level_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = scst_write_trace(buf, count, &trace_flag,
++ SCST_DEFAULT_LOG_FLAGS, "scst", scst_local_trace_tbl);
++
++ mutex_unlock(&scst_log_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
++
++static ssize_t scst_version_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ TRACE_ENTRY();
++
++ sprintf(buf, "%s\n", SCST_VERSION_STRING);
++
++#ifdef CONFIG_SCST_STRICT_SERIALIZING
++ strcat(buf, "STRICT_SERIALIZING\n");
++#endif
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ strcat(buf, "EXTRACHECKS\n");
++#endif
++
++#ifdef CONFIG_SCST_TRACING
++ strcat(buf, "TRACING\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++ strcat(buf, "DEBUG\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_TM
++ strcat(buf, "DEBUG_TM\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_RETRY
++ strcat(buf, "DEBUG_RETRY\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_OOM
++ strcat(buf, "DEBUG_OOM\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_SN
++ strcat(buf, "DEBUG_SN\n");
++#endif
++
++#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
++ strcat(buf, "USE_EXPECTED_VALUES\n");
++#endif
++
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ strcat(buf, "TEST_IO_IN_SIRQ\n");
++#endif
++
++#ifdef CONFIG_SCST_STRICT_SECURITY
++ strcat(buf, "STRICT_SECURITY\n");
++#endif
++
++ TRACE_EXIT();
++ return strlen(buf);
++}
++
++static ssize_t scst_last_sysfs_mgmt_res_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ spin_lock(&sysfs_work_lock);
++ TRACE_DBG("active_sysfs_works %d", active_sysfs_works);
++ if (active_sysfs_works > 0)
++ res = -EAGAIN;
++ else
++ res = sprintf(buf, "%d\n", last_sysfs_work_res);
++ spin_unlock(&sysfs_work_lock);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute scst_threads_attr =
++ __ATTR(threads, S_IRUGO | S_IWUSR, scst_threads_show,
++ scst_threads_store);
++
++static struct kobj_attribute scst_setup_id_attr =
++ __ATTR(setup_id, S_IRUGO | S_IWUSR, scst_setup_id_show,
++ scst_setup_id_store);
++
++static ssize_t scst_max_tasklet_cmd_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int count;
++
++ TRACE_ENTRY();
++
++ count = sprintf(buf, "%d\n%s\n", scst_max_tasklet_cmd,
++ (scst_max_tasklet_cmd == SCST_DEF_MAX_TASKLET_CMD)
++ ? "" : SCST_SYSFS_KEY_MARK);
++
++ TRACE_EXIT();
++ return count;
++}
++
++static ssize_t scst_max_tasklet_cmd_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ unsigned long val;
++
++ TRACE_ENTRY();
++
++ res = strict_strtoul(buf, 0, &val);
++ if (res != 0) {
++ PRINT_ERROR("strict_strtoul() for %s failed: %d ", buf, res);
++ goto out;
++ }
++
++ scst_max_tasklet_cmd = val;
++ PRINT_INFO("Changed scst_max_tasklet_cmd to %d", scst_max_tasklet_cmd);
++
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute scst_max_tasklet_cmd_attr =
++ __ATTR(max_tasklet_cmd, S_IRUGO | S_IWUSR, scst_max_tasklet_cmd_show,
++ scst_max_tasklet_cmd_store);
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++static struct kobj_attribute scst_trace_level_attr =
++ __ATTR(trace_level, S_IRUGO | S_IWUSR, scst_main_trace_level_show,
++ scst_main_trace_level_store);
++#endif
++
++static struct kobj_attribute scst_version_attr =
++ __ATTR(version, S_IRUGO, scst_version_show, NULL);
++
++static struct kobj_attribute scst_last_sysfs_mgmt_res_attr =
++ __ATTR(last_sysfs_mgmt_res, S_IRUGO,
++ scst_last_sysfs_mgmt_res_show, NULL);
++
++static struct attribute *scst_sysfs_root_default_attrs[] = {
++ &scst_threads_attr.attr,
++ &scst_setup_id_attr.attr,
++ &scst_max_tasklet_cmd_attr.attr,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ &scst_trace_level_attr.attr,
++#endif
++ &scst_version_attr.attr,
++ &scst_last_sysfs_mgmt_res_attr.attr,
++ NULL,
++};
++
++static void scst_sysfs_root_release(struct kobject *kobj)
++{
++ complete_all(&scst_sysfs_root_release_completion);
++}
++
++static struct kobj_type scst_sysfs_root_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_sysfs_root_release,
++ .default_attrs = scst_sysfs_root_default_attrs,
++};
++
++/**
++ ** Dev handlers
++ **/
++
++static void scst_devt_release(struct kobject *kobj)
++{
++ struct scst_dev_type *devt;
++
++ TRACE_ENTRY();
++
++ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
++ complete_all(&devt->devt_kobj_release_compl);
++
++ TRACE_EXIT();
++ return;
++}
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++static ssize_t scst_devt_trace_level_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_dev_type *devt;
++
++ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
++
++ return scst_trace_level_show(devt->trace_tbl,
++ devt->trace_flags ? *devt->trace_flags : 0, buf,
++ devt->trace_tbl_help);
++}
++
++static ssize_t scst_devt_trace_level_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_dev_type *devt;
++
++ TRACE_ENTRY();
++
++ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
++
++ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = scst_write_trace(buf, count, devt->trace_flags,
++ devt->default_trace_flags, devt->name, devt->trace_tbl);
++
++ mutex_unlock(&scst_log_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute devt_trace_attr =
++ __ATTR(trace_level, S_IRUGO | S_IWUSR,
++ scst_devt_trace_level_show, scst_devt_trace_level_store);
++
++#endif /* #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
++
++static ssize_t scst_devt_type_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos;
++ struct scst_dev_type *devt;
++
++ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
++
++ pos = sprintf(buf, "%d - %s\n", devt->type,
++ (unsigned)devt->type > ARRAY_SIZE(scst_dev_handler_types) ?
++ "unknown" : scst_dev_handler_types[devt->type]);
++
++ return pos;
++}
++
++static struct kobj_attribute scst_devt_type_attr =
++ __ATTR(type, S_IRUGO, scst_devt_type_show, NULL);
++
++static struct attribute *scst_devt_default_attrs[] = {
++ &scst_devt_type_attr.attr,
++ NULL,
++};
++
++static struct kobj_type scst_devt_ktype = {
++ .sysfs_ops = &scst_sysfs_ops,
++ .release = scst_devt_release,
++ .default_attrs = scst_devt_default_attrs,
++};
++
++static ssize_t scst_devt_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ char *help = "Usage: echo \"add_device device_name [parameters]\" "
++ ">mgmt\n"
++ " echo \"del_device device_name\" >mgmt\n"
++ "%s%s"
++ "%s"
++ "\n"
++ "where parameters are one or more "
++ "param_name=value pairs separated by ';'\n\n"
++ "%s%s%s%s%s%s%s%s\n";
++ struct scst_dev_type *devt;
++
++ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
++
++ return scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, help,
++ (devt->devt_optional_attributes != NULL) ?
++ " echo \"add_attribute <attribute> <value>\" >mgmt\n"
++ " echo \"del_attribute <attribute> <value>\" >mgmt\n" : "",
++ (devt->dev_optional_attributes != NULL) ?
++ " echo \"add_device_attribute device_name <attribute> <value>\" >mgmt"
++ " echo \"del_device_attribute device_name <attribute> <value>\" >mgmt\n" : "",
++ (devt->mgmt_cmd_help) ? devt->mgmt_cmd_help : "",
++ (devt->add_device_parameters != NULL) ?
++ "The following parameters available: " : "",
++ (devt->add_device_parameters != NULL) ?
++ devt->add_device_parameters : "",
++ (devt->devt_optional_attributes != NULL) ?
++ "The following dev handler attributes available: " : "",
++ (devt->devt_optional_attributes != NULL) ?
++ devt->devt_optional_attributes : "",
++ (devt->devt_optional_attributes != NULL) ? "\n" : "",
++ (devt->dev_optional_attributes != NULL) ?
++ "The following device attributes available: " : "",
++ (devt->dev_optional_attributes != NULL) ?
++ devt->dev_optional_attributes : "",
++ (devt->dev_optional_attributes != NULL) ? "\n" : "");
++}
++
++static int scst_process_devt_mgmt_store(char *buffer,
++ struct scst_dev_type *devt)
++{
++ int res = 0;
++ char *p, *pp, *dev_name;
++
++ TRACE_ENTRY();
++
++ /* Check if our pointer is still alive and, if yes, grab it */
++ if (scst_check_grab_devt_ptr(devt, &scst_virtual_dev_type_list) != 0)
++ goto out;
++
++ TRACE_DBG("devt %p, buffer %s", devt, buffer);
++
++ pp = buffer;
++ if (pp[strlen(pp) - 1] == '\n')
++ pp[strlen(pp) - 1] = '\0';
++
++ p = scst_get_next_lexem(&pp);
++
++ if (strcasecmp("add_device", p) == 0) {
++ dev_name = scst_get_next_lexem(&pp);
++ if (*dev_name == '\0') {
++ PRINT_ERROR("%s", "Device name required");
++ res = -EINVAL;
++ goto out_ungrab;
++ }
++ res = devt->add_device(dev_name, pp);
++ } else if (strcasecmp("del_device", p) == 0) {
++ dev_name = scst_get_next_lexem(&pp);
++ if (*dev_name == '\0') {
++ PRINT_ERROR("%s", "Device name required");
++ res = -EINVAL;
++ goto out_ungrab;
++ }
++
++ p = scst_get_next_lexem(&pp);
++ if (*p != '\0')
++ goto out_syntax_err;
++
++ res = devt->del_device(dev_name);
++ } else if (devt->mgmt_cmd != NULL) {
++ scst_restore_token_str(p, pp);
++ res = devt->mgmt_cmd(buffer);
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out_ungrab;
++ }
++
++out_ungrab:
++ scst_ungrab_devt_ptr(devt);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_syntax_err:
++ PRINT_ERROR("Syntax error on \"%s\"", p);
++ res = -EINVAL;
++ goto out_ungrab;
++}
++
++static int scst_devt_mgmt_store_work_fn(struct scst_sysfs_work_item *work)
++{
++ return scst_process_devt_mgmt_store(work->buf, work->devt);
++}
++
++static ssize_t __scst_devt_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count,
++ int (*sysfs_work_fn)(struct scst_sysfs_work_item *work))
++{
++ int res;
++ char *buffer;
++ struct scst_dev_type *devt;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ devt = container_of(kobj, struct scst_dev_type, devt_kobj);
++
++ buffer = kzalloc(count+1, GFP_KERNEL);
++ if (buffer == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++ memcpy(buffer, buf, count);
++ buffer[count] = '\0';
++
++ res = scst_alloc_sysfs_work(sysfs_work_fn, false, &work);
++ if (res != 0)
++ goto out_free;
++
++ work->buf = buffer;
++ work->devt = devt;
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(buffer);
++ goto out;
++}
++
++static ssize_t scst_devt_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ return __scst_devt_mgmt_store(kobj, attr, buf, count,
++ scst_devt_mgmt_store_work_fn);
++}
++
++static struct kobj_attribute scst_devt_mgmt =
++ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_devt_mgmt_show,
++ scst_devt_mgmt_store);
++
++static ssize_t scst_devt_pass_through_mgmt_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ char *help = "Usage: echo \"add_device H:C:I:L\" >mgmt\n"
++ " echo \"del_device H:C:I:L\" >mgmt\n";
++ return sprintf(buf, "%s", help);
++}
++
++static int scst_process_devt_pass_through_mgmt_store(char *buffer,
++ struct scst_dev_type *devt)
++{
++ int res = 0;
++ char *p, *pp, *action;
++ unsigned long host, channel, id, lun;
++ struct scst_device *d, *dev = NULL;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("devt %p, buffer %s", devt, buffer);
++
++ pp = buffer;
++ if (pp[strlen(pp) - 1] == '\n')
++ pp[strlen(pp) - 1] = '\0';
++
++ action = scst_get_next_lexem(&pp);
++ p = scst_get_next_lexem(&pp);
++ if (*p == '\0') {
++ PRINT_ERROR("%s", "Device required");
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (*scst_get_next_lexem(&pp) != '\0') {
++ PRINT_ERROR("%s", "Too many parameters");
++ res = -EINVAL;
++ goto out_syntax_err;
++ }
++
++ host = simple_strtoul(p, &p, 0);
++ if ((host == ULONG_MAX) || (*p != ':'))
++ goto out_syntax_err;
++ p++;
++ channel = simple_strtoul(p, &p, 0);
++ if ((channel == ULONG_MAX) || (*p != ':'))
++ goto out_syntax_err;
++ p++;
++ id = simple_strtoul(p, &p, 0);
++ if ((channel == ULONG_MAX) || (*p != ':'))
++ goto out_syntax_err;
++ p++;
++ lun = simple_strtoul(p, &p, 0);
++ if (lun == ULONG_MAX)
++ goto out_syntax_err;
++
++ TRACE_DBG("Dev %ld:%ld:%ld:%ld", host, channel, id, lun);
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ /* Check if devt not be already freed while we were coming here */
++ if (scst_check_devt_ptr(devt, &scst_dev_type_list) != 0)
++ goto out_unlock;
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if ((d->virt_id == 0) &&
++ d->scsi_dev->host->host_no == host &&
++ d->scsi_dev->channel == channel &&
++ d->scsi_dev->id == id &&
++ d->scsi_dev->lun == lun) {
++ dev = d;
++ TRACE_DBG("Dev %p (%ld:%ld:%ld:%ld) found",
++ dev, host, channel, id, lun);
++ break;
++ }
++ }
++ if (dev == NULL) {
++ PRINT_ERROR("Device %ld:%ld:%ld:%ld not found",
++ host, channel, id, lun);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ if (dev->scsi_dev->type != devt->type) {
++ PRINT_ERROR("Type %d of device %s differs from type "
++ "%d of dev handler %s", dev->type,
++ dev->virt_name, devt->type, devt->name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ if (strcasecmp("add_device", action) == 0) {
++ res = scst_assign_dev_handler(dev, devt);
++ if (res == 0)
++ PRINT_INFO("Device %s assigned to dev handler %s",
++ dev->virt_name, devt->name);
++ } else if (strcasecmp("del_device", action) == 0) {
++ if (dev->handler != devt) {
++ PRINT_ERROR("Device %s is not assigned to handler %s",
++ dev->virt_name, devt->name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ res = scst_assign_dev_handler(dev, &scst_null_devtype);
++ if (res == 0)
++ PRINT_INFO("Device %s unassigned from dev handler %s",
++ dev->virt_name, devt->name);
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", action);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_syntax_err:
++ PRINT_ERROR("Syntax error on \"%s\"", p);
++ res = -EINVAL;
++ goto out;
++}
++
++static int scst_devt_pass_through_mgmt_store_work_fn(
++ struct scst_sysfs_work_item *work)
++{
++ return scst_process_devt_pass_through_mgmt_store(work->buf, work->devt);
++}
++
++static ssize_t scst_devt_pass_through_mgmt_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ return __scst_devt_mgmt_store(kobj, attr, buf, count,
++ scst_devt_pass_through_mgmt_store_work_fn);
++}
++
++static struct kobj_attribute scst_devt_pass_through_mgmt =
++ __ATTR(mgmt, S_IRUGO | S_IWUSR, scst_devt_pass_through_mgmt_show,
++ scst_devt_pass_through_mgmt_store);
++
++int scst_devt_sysfs_create(struct scst_dev_type *devt)
++{
++ int res;
++ struct kobject *parent;
++ const struct attribute **pattr;
++
++ TRACE_ENTRY();
++
++ init_completion(&devt->devt_kobj_release_compl);
++
++ if (devt->parent != NULL)
++ parent = &devt->parent->devt_kobj;
++ else
++ parent = scst_handlers_kobj;
++
++ res = kobject_init_and_add(&devt->devt_kobj, &scst_devt_ktype,
++ parent, devt->name);
++ if (res != 0) {
++ PRINT_ERROR("Can't add devt %s to sysfs", devt->name);
++ goto out;
++ }
++
++ if (devt->add_device != NULL) {
++ res = sysfs_create_file(&devt->devt_kobj,
++ &scst_devt_mgmt.attr);
++ } else {
++ res = sysfs_create_file(&devt->devt_kobj,
++ &scst_devt_pass_through_mgmt.attr);
++ }
++ if (res != 0) {
++ PRINT_ERROR("Can't add mgmt attr for dev handler %s",
++ devt->name);
++ goto out_err;
++ }
++
++ pattr = devt->devt_attrs;
++ if (pattr != NULL) {
++ while (*pattr != NULL) {
++ res = sysfs_create_file(&devt->devt_kobj, *pattr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add devt attr %s for dev "
++ "handler %s", (*pattr)->name,
++ devt->name);
++ goto out_err;
++ }
++ pattr++;
++ }
++ }
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ if (devt->trace_flags != NULL) {
++ res = sysfs_create_file(&devt->devt_kobj,
++ &devt_trace_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Can't add devt trace_flag for dev "
++ "handler %s", devt->name);
++ goto out_err;
++ }
++ }
++#endif
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_err:
++ scst_devt_sysfs_del(devt);
++ goto out;
++}
++
++void scst_devt_sysfs_del(struct scst_dev_type *devt)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ kobject_del(&devt->devt_kobj);
++ kobject_put(&devt->devt_kobj);
++
++ rc = wait_for_completion_timeout(&devt->devt_kobj_release_compl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing of sysfs entry "
++ "for dev handler template %s (%d refs)...", devt->name,
++ atomic_read(&devt->devt_kobj.kref.refcount));
++ wait_for_completion(&devt->devt_kobj_release_compl);
++ PRINT_INFO("Done waiting for releasing sysfs entry "
++ "for dev handler template %s", devt->name);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ ** Sysfs user info
++ **/
++
++static DEFINE_MUTEX(scst_sysfs_user_info_mutex);
++
++/* All protected by scst_sysfs_user_info_mutex */
++static LIST_HEAD(scst_sysfs_user_info_list);
++static uint32_t scst_sysfs_info_cur_cookie;
++
++/* scst_sysfs_user_info_mutex supposed to be held */
++static struct scst_sysfs_user_info *scst_sysfs_user_find_info(uint32_t cookie)
++{
++ struct scst_sysfs_user_info *info, *res = NULL;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(info, &scst_sysfs_user_info_list,
++ info_list_entry) {
++ if (info->info_cookie == cookie) {
++ res = info;
++ break;
++ }
++ }
++
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/**
++ * scst_sysfs_user_get_info() - get user_info
++ *
++ * Finds the user_info based on cookie and mark it as received the reply by
++ * setting for it flag info_being_executed.
++ *
++ * Returns found entry or NULL.
++ */
++struct scst_sysfs_user_info *scst_sysfs_user_get_info(uint32_t cookie)
++{
++ struct scst_sysfs_user_info *res = NULL;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_sysfs_user_info_mutex);
++
++ res = scst_sysfs_user_find_info(cookie);
++ if (res != NULL) {
++ if (!res->info_being_executed)
++ res->info_being_executed = 1;
++ }
++
++ mutex_unlock(&scst_sysfs_user_info_mutex);
++
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_sysfs_user_get_info);
++
++/**
++ ** Helper functionality to help target drivers and dev handlers support
++ ** sending events to user space and wait for their completion in a safe
++ ** manner. See samples how to use it in iscsi-scst or scst_user.
++ **/
++
++/**
++ * scst_sysfs_user_add_info() - create and add user_info in the global list
++ *
++ * Creates an info structure and adds it in the info_list.
++ * Returns 0 and out_info on success, error code otherwise.
++ */
++int scst_sysfs_user_add_info(struct scst_sysfs_user_info **out_info)
++{
++ int res = 0;
++ struct scst_sysfs_user_info *info;
++
++ TRACE_ENTRY();
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ PRINT_ERROR("Unable to allocate sysfs user info (size %zd)",
++ sizeof(*info));
++ res = -ENOMEM;
++ goto out;
++ }
++
++ mutex_lock(&scst_sysfs_user_info_mutex);
++
++ while ((info->info_cookie == 0) ||
++ (scst_sysfs_user_find_info(info->info_cookie) != NULL))
++ info->info_cookie = scst_sysfs_info_cur_cookie++;
++
++ init_completion(&info->info_completion);
++
++ list_add_tail(&info->info_list_entry, &scst_sysfs_user_info_list);
++ info->info_in_list = 1;
++
++ *out_info = info;
++
++ mutex_unlock(&scst_sysfs_user_info_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_sysfs_user_add_info);
++
++/**
++ * scst_sysfs_user_del_info - delete and frees user_info
++ */
++void scst_sysfs_user_del_info(struct scst_sysfs_user_info *info)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_sysfs_user_info_mutex);
++
++ if (info->info_in_list)
++ list_del(&info->info_list_entry);
++
++ mutex_unlock(&scst_sysfs_user_info_mutex);
++
++ kfree(info);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_sysfs_user_del_info);
++
++/*
++ * Returns true if the reply received and being processed by another part of
++ * the kernel, false otherwise. Also removes the user_info from the list to
++ * fix for the user space that it missed the timeout.
++ */
++static bool scst_sysfs_user_info_executing(struct scst_sysfs_user_info *info)
++{
++ bool res;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_sysfs_user_info_mutex);
++
++ res = info->info_being_executed;
++
++ if (info->info_in_list) {
++ list_del(&info->info_list_entry);
++ info->info_in_list = 0;
++ }
++
++ mutex_unlock(&scst_sysfs_user_info_mutex);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * scst_wait_info_completion() - wait an user space event's completion
++ *
++ * Waits for the info request been completed by user space at most timeout
++ * jiffies. If the reply received before timeout and being processed by
++ * another part of the kernel, i.e. scst_sysfs_user_info_executing()
++ * returned true, waits for it to complete indefinitely.
++ *
++ * Returns status of the request completion.
++ */
++int scst_wait_info_completion(struct scst_sysfs_user_info *info,
++ unsigned long timeout)
++{
++ int res, rc;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Waiting for info %p completion", info);
++
++ while (1) {
++ rc = wait_for_completion_interruptible_timeout(
++ &info->info_completion, timeout);
++ if (rc > 0) {
++ TRACE_DBG("Waiting for info %p finished with %d",
++ info, rc);
++ break;
++ } else if (rc == 0) {
++ if (!scst_sysfs_user_info_executing(info)) {
++ PRINT_ERROR("Timeout waiting for user "
++ "space event %p", info);
++ res = -EBUSY;
++ goto out;
++ } else {
++ /* Req is being executed in the kernel */
++ TRACE_DBG("Keep waiting for info %p completion",
++ info);
++ wait_for_completion(&info->info_completion);
++ break;
++ }
++ } else if (rc != -ERESTARTSYS) {
++ res = rc;
++ PRINT_ERROR("wait_for_completion() failed: %d",
++ res);
++ goto out;
++ } else {
++ TRACE_DBG("Waiting for info %p finished with %d, "
++ "retrying", info, rc);
++ }
++ }
++
++ TRACE_DBG("info %p, status %d", info, info->info_status);
++ res = info->info_status;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_wait_info_completion);
++
++int __init scst_sysfs_init(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ sysfs_work_thread = kthread_run(sysfs_work_thread_fn,
++ NULL, "scst_uid");
++ if (IS_ERR(sysfs_work_thread)) {
++ res = PTR_ERR(sysfs_work_thread);
++ PRINT_ERROR("kthread_create() for user interface thread "
++ "failed: %d", res);
++ sysfs_work_thread = NULL;
++ goto out;
++ }
++
++ res = kobject_init_and_add(&scst_sysfs_root_kobj,
++ &scst_sysfs_root_ktype, kernel_kobj, "%s", "scst_tgt");
++ if (res != 0)
++ goto sysfs_root_add_error;
++
++ scst_targets_kobj = kobject_create_and_add("targets",
++ &scst_sysfs_root_kobj);
++ if (scst_targets_kobj == NULL)
++ goto targets_kobj_error;
++
++ scst_devices_kobj = kobject_create_and_add("devices",
++ &scst_sysfs_root_kobj);
++ if (scst_devices_kobj == NULL)
++ goto devices_kobj_error;
++
++ scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL);
++ if (scst_sgv_kobj == NULL)
++ goto sgv_kobj_error;
++
++ res = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype,
++ &scst_sysfs_root_kobj, "%s", "sgv");
++ if (res != 0)
++ goto sgv_kobj_add_error;
++
++ scst_handlers_kobj = kobject_create_and_add("handlers",
++ &scst_sysfs_root_kobj);
++ if (scst_handlers_kobj == NULL)
++ goto handlers_kobj_error;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++handlers_kobj_error:
++ kobject_del(scst_sgv_kobj);
++
++sgv_kobj_add_error:
++ kobject_put(scst_sgv_kobj);
++
++sgv_kobj_error:
++ kobject_del(scst_devices_kobj);
++ kobject_put(scst_devices_kobj);
++
++devices_kobj_error:
++ kobject_del(scst_targets_kobj);
++ kobject_put(scst_targets_kobj);
++
++targets_kobj_error:
++ kobject_del(&scst_sysfs_root_kobj);
++
++sysfs_root_add_error:
++ kobject_put(&scst_sysfs_root_kobj);
++
++ kthread_stop(sysfs_work_thread);
++
++ if (res == 0)
++ res = -EINVAL;
++
++ goto out;
++}
++
++void scst_sysfs_cleanup(void)
++{
++ TRACE_ENTRY();
++
++ PRINT_INFO("%s", "Exiting SCST sysfs hierarchy...");
++
++ kobject_del(scst_sgv_kobj);
++ kobject_put(scst_sgv_kobj);
++
++ kobject_del(scst_devices_kobj);
++ kobject_put(scst_devices_kobj);
++
++ kobject_del(scst_targets_kobj);
++ kobject_put(scst_targets_kobj);
++
++ kobject_del(scst_handlers_kobj);
++ kobject_put(scst_handlers_kobj);
++
++ kobject_del(&scst_sysfs_root_kobj);
++ kobject_put(&scst_sysfs_root_kobj);
++
++ wait_for_completion(&scst_sysfs_root_release_completion);
++ /*
++ * There is a race, when in the release() schedule happens just after
++ * calling complete(), so if we exit and unload scst module immediately,
++ * there will be oops there. So let's give it a chance to quit
++ * gracefully. Unfortunately, current kobjects implementation
++ * doesn't allow better ways to handle it.
++ */
++ msleep(3000);
++
++ if (sysfs_work_thread)
++ kthread_stop(sysfs_work_thread);
++
++ PRINT_INFO("%s", "Exiting SCST sysfs hierarchy done");
++
++ TRACE_EXIT();
++ return;
++}
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_targ.c linux-2.6.36/drivers/scst/scst_targ.c
+--- orig/linux-2.6.36/drivers/scst/scst_targ.c
++++ linux-2.6.36/drivers/scst/scst_targ.c
+@@ -0,0 +1,6654 @@
++/*
++ * scst_targ.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/smp_lock.h>
++#include <linux/unistd.h>
++#include <linux/string.h>
++#include <linux/kthread.h>
++#include <linux/delay.h>
++#include <linux/ktime.h>
++
++#include <scst/scst.h>
++#include "scst_priv.h"
++#include "scst_pres.h"
++
++#if 0 /* Temporary left for future performance investigations */
++/* Deleting it don't forget to delete write_cmd_count */
++#define CONFIG_SCST_ORDERED_READS
++#endif
++
++#if 0 /* Let's disable it for now to see if users will complain about it */
++/* Deleting it don't forget to delete write_cmd_count */
++#define CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
++#endif
++
++static void scst_cmd_set_sn(struct scst_cmd *cmd);
++static int __scst_init_cmd(struct scst_cmd *cmd);
++static void scst_finish_cmd_mgmt(struct scst_cmd *cmd);
++static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess,
++ uint64_t tag, bool to_abort);
++static void scst_process_redirect_cmd(struct scst_cmd *cmd,
++ enum scst_exec_context context, int check_retries);
++
++/**
++ * scst_post_parse() - do post parse actions
++ *
++ * This function must be called by dev handler after its parse() callback
++ * returned SCST_CMD_STATE_STOP before calling scst_process_active_cmd().
++ */
++void scst_post_parse(struct scst_cmd *cmd)
++{
++ scst_set_parse_time(cmd);
++}
++EXPORT_SYMBOL_GPL(scst_post_parse);
++
++/**
++ * scst_post_alloc_data_buf() - do post alloc_data_buf actions
++ *
++ * This function must be called by dev handler after its alloc_data_buf()
++ * callback returned SCST_CMD_STATE_STOP before calling
++ * scst_process_active_cmd().
++ */
++void scst_post_alloc_data_buf(struct scst_cmd *cmd)
++{
++ scst_set_alloc_buf_time(cmd);
++}
++EXPORT_SYMBOL_GPL(scst_post_alloc_data_buf);
++
++static inline void scst_schedule_tasklet(struct scst_cmd *cmd)
++{
++ struct scst_tasklet *t = &scst_tasklets[smp_processor_id()];
++ unsigned long flags;
++
++ if (atomic_read(&scst_cmd_count) <= scst_max_tasklet_cmd) {
++ spin_lock_irqsave(&t->tasklet_lock, flags);
++ TRACE_DBG("Adding cmd %p to tasklet %d cmd list", cmd,
++ smp_processor_id());
++ list_add_tail(&cmd->cmd_list_entry, &t->tasklet_cmd_list);
++ spin_unlock_irqrestore(&t->tasklet_lock, flags);
++
++ tasklet_schedule(&t->tasklet);
++ } else {
++ spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags);
++ TRACE_DBG("Too many tasklet commands (%d), adding cmd %p to "
++ "active cmd list", atomic_read(&scst_cmd_count), cmd);
++ list_add_tail(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock_irqrestore(&cmd->cmd_threads->cmd_list_lock, flags);
++ }
++ return;
++}
++
++/**
++ * scst_rx_cmd() - create new command
++ * @sess: SCST session
++ * @lun: LUN for the command
++ * @lun_len: length of the LUN in bytes
++ * @cdb: CDB of the command
++ * @cdb_len: length of the CDB in bytes
++ * @atomic: true, if current context is atomic
++ *
++ * Description:
++ * Creates new SCST command. Returns new command on success or
++ * NULL otherwise.
++ *
++ * Must not be called in parallel with scst_unregister_session() for the
++ * same session.
++ */
++struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
++ const uint8_t *lun, int lun_len, const uint8_t *cdb,
++ unsigned int cdb_len, int atomic)
++{
++ struct scst_cmd *cmd;
++
++ TRACE_ENTRY();
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) {
++ PRINT_CRIT_ERROR("%s",
++ "New cmd while shutting down the session");
++ BUG();
++ }
++#endif
++
++ cmd = scst_alloc_cmd(atomic ? GFP_ATOMIC : GFP_KERNEL);
++ if (cmd == NULL)
++ goto out;
++
++ cmd->sess = sess;
++ cmd->tgt = sess->tgt;
++ cmd->tgtt = sess->tgt->tgtt;
++
++ cmd->lun = scst_unpack_lun(lun, lun_len);
++ if (unlikely(cmd->lun == NO_SUCH_LUN)) {
++ PRINT_ERROR("Wrong LUN %d, finishing cmd", -1);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_lun_not_supported));
++ }
++
++ /*
++ * For cdb_len 0 defer the error reporting until scst_cmd_init_done(),
++ * scst_set_cmd_error() supports nested calls.
++ */
++ if (unlikely(cdb_len > SCST_MAX_CDB_SIZE)) {
++ PRINT_ERROR("Too big CDB len %d, finishing cmd", cdb_len);
++ cdb_len = SCST_MAX_CDB_SIZE;
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_message));
++ }
++
++ memcpy(cmd->cdb, cdb, cdb_len);
++ cmd->cdb_len = cdb_len;
++
++ TRACE_DBG("cmd %p, sess %p", cmd, sess);
++ scst_sess_get(sess);
++
++out:
++ TRACE_EXIT();
++ return cmd;
++}
++EXPORT_SYMBOL(scst_rx_cmd);
++
++/*
++ * No locks, but might be on IRQ. Returns 0 on success, <0 if processing of
++ * this command should be stopped.
++ */
++static int scst_init_cmd(struct scst_cmd *cmd, enum scst_exec_context *context)
++{
++ int rc, res = 0;
++
++ TRACE_ENTRY();
++
++ /* See the comment in scst_do_job_init() */
++ if (unlikely(!list_empty(&scst_init_cmd_list))) {
++ TRACE_MGMT_DBG("%s", "init cmd list busy");
++ goto out_redirect;
++ }
++ /*
++ * Memory barrier isn't necessary here, because CPU appears to
++ * be self-consistent and we don't care about the race, described
++ * in comment in scst_do_job_init().
++ */
++
++ rc = __scst_init_cmd(cmd);
++ if (unlikely(rc > 0))
++ goto out_redirect;
++ else if (unlikely(rc != 0)) {
++ res = 1;
++ goto out;
++ }
++
++ EXTRACHECKS_BUG_ON(*context == SCST_CONTEXT_SAME);
++
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ scst_get_cdb_info(cmd);
++ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED)
++ goto out;
++#endif
++
++ /* Small context optimization */
++ if ((*context == SCST_CONTEXT_TASKLET) ||
++ (*context == SCST_CONTEXT_DIRECT_ATOMIC)) {
++ /*
++ * If any data_direction not set, it's SCST_DATA_UNKNOWN,
++ * which is 0, so we can safely | them
++ */
++ BUILD_BUG_ON(SCST_DATA_UNKNOWN != 0);
++ if ((cmd->data_direction | cmd->expected_data_direction) & SCST_DATA_WRITE) {
++ if (!test_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC,
++ &cmd->tgt_dev->tgt_dev_flags))
++ *context = SCST_CONTEXT_THREAD;
++ } else
++ *context = SCST_CONTEXT_THREAD;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_redirect:
++ if (cmd->preprocessing_only) {
++ /*
++ * Poor man solution for single threaded targets, where
++ * blocking receiver at least sometimes means blocking all.
++ * For instance, iSCSI target won't be able to receive
++ * Data-Out PDUs.
++ */
++ BUG_ON(*context != SCST_CONTEXT_DIRECT);
++ scst_set_busy(cmd);
++ scst_set_cmd_abnormal_done_state(cmd);
++ res = 1;
++ /* Keep initiator away from too many BUSY commands */
++ msleep(50);
++ } else {
++ unsigned long flags;
++ spin_lock_irqsave(&scst_init_lock, flags);
++ TRACE_MGMT_DBG("Adding cmd %p to init cmd list (scst_cmd_count "
++ "%d)", cmd, atomic_read(&scst_cmd_count));
++ list_add_tail(&cmd->cmd_list_entry, &scst_init_cmd_list);
++ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))
++ scst_init_poll_cnt++;
++ spin_unlock_irqrestore(&scst_init_lock, flags);
++ wake_up(&scst_init_cmd_list_waitQ);
++ res = -1;
++ }
++ goto out;
++}
++
++/**
++ * scst_cmd_init_done() - the command's initialization done
++ * @cmd: SCST command
++ * @pref_context: preferred command execution context
++ *
++ * Description:
++ * Notifies SCST that the driver finished its part of the command
++ * initialization, and the command is ready for execution.
++ * The second argument sets preferred command execition context.
++ * See SCST_CONTEXT_* constants for details.
++ *
++ * !!IMPORTANT!!
++ *
++ * If cmd->set_sn_on_restart_cmd not set, this function, as well as
++ * scst_cmd_init_stage1_done() and scst_restart_cmd(), must not be
++ * called simultaneously for the same session (more precisely,
++ * for the same session/LUN, i.e. tgt_dev), i.e. they must be
++ * somehow externally serialized. This is needed to have lock free fast
++ * path in scst_cmd_set_sn(). For majority of targets those functions are
++ * naturally serialized by the single source of commands. Only iSCSI
++ * immediate commands with multiple connections per session seems to be an
++ * exception. For it, some mutex/lock shall be used for the serialization.
++ */
++void scst_cmd_init_done(struct scst_cmd *cmd,
++ enum scst_exec_context pref_context)
++{
++ unsigned long flags;
++ struct scst_session *sess = cmd->sess;
++ int rc;
++
++ TRACE_ENTRY();
++
++ scst_set_start_time(cmd);
++
++ TRACE_DBG("Preferred context: %d (cmd %p)", pref_context, cmd);
++ TRACE(TRACE_SCSI, "tag=%llu, lun=%lld, CDB len=%d, queue_type=%x "
++ "(cmd %p)", (long long unsigned int)cmd->tag,
++ (long long unsigned int)cmd->lun, cmd->cdb_len,
++ cmd->queue_type, cmd);
++ PRINT_BUFF_FLAG(TRACE_SCSI|TRACE_RCV_BOT, "Recieving CDB",
++ cmd->cdb, cmd->cdb_len);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (unlikely((in_irq() || irqs_disabled())) &&
++ ((pref_context == SCST_CONTEXT_DIRECT) ||
++ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) {
++ PRINT_ERROR("Wrong context %d in IRQ from target %s, use "
++ "SCST_CONTEXT_THREAD instead", pref_context,
++ cmd->tgtt->name);
++ dump_stack();
++ pref_context = SCST_CONTEXT_THREAD;
++ }
++#endif
++
++ atomic_inc(&sess->sess_cmd_count);
++
++ spin_lock_irqsave(&sess->sess_list_lock, flags);
++
++ if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) {
++ /*
++ * We must always keep commands in the sess list from the
++ * very beginning, because otherwise they can be missed during
++ * TM processing. This check is needed because there might be
++ * old, i.e. deferred, commands and new, i.e. just coming, ones.
++ */
++ if (cmd->sess_cmd_list_entry.next == NULL)
++ list_add_tail(&cmd->sess_cmd_list_entry,
++ &sess->sess_cmd_list);
++ switch (sess->init_phase) {
++ case SCST_SESS_IPH_SUCCESS:
++ break;
++ case SCST_SESS_IPH_INITING:
++ TRACE_DBG("Adding cmd %p to init deferred cmd list",
++ cmd);
++ list_add_tail(&cmd->cmd_list_entry,
++ &sess->init_deferred_cmd_list);
++ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
++ goto out;
++ case SCST_SESS_IPH_FAILED:
++ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
++ scst_set_busy(cmd);
++ scst_set_cmd_abnormal_done_state(cmd);
++ goto active;
++ default:
++ BUG();
++ }
++ } else
++ list_add_tail(&cmd->sess_cmd_list_entry,
++ &sess->sess_cmd_list);
++
++ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
++
++ if (unlikely(cmd->cdb_len == 0)) {
++ PRINT_ERROR("%s", "Wrong CDB len 0, finishing cmd");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ scst_set_cmd_abnormal_done_state(cmd);
++ goto active;
++ }
++
++ if (unlikely(cmd->queue_type >= SCST_CMD_QUEUE_ACA)) {
++ PRINT_ERROR("Unsupported queue type %d", cmd->queue_type);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_message));
++ goto active;
++ }
++
++ /*
++ * Cmd must be inited here to preserve the order. In case if cmd
++ * already preliminary completed by target driver we need to init
++ * cmd anyway to find out in which format we should return sense.
++ */
++ cmd->state = SCST_CMD_STATE_INIT;
++ rc = scst_init_cmd(cmd, &pref_context);
++ if (unlikely(rc < 0))
++ goto out;
++
++active:
++ /* Here cmd must not be in any cmd list, no locks */
++ switch (pref_context) {
++ case SCST_CONTEXT_TASKLET:
++ scst_schedule_tasklet(cmd);
++ break;
++
++ default:
++ PRINT_ERROR("Context %x is undefined, using the thread one",
++ pref_context);
++ /* go through */
++ case SCST_CONTEXT_THREAD:
++ spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags);
++ TRACE_DBG("Adding cmd %p to active cmd list", cmd);
++ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
++ list_add(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ else
++ list_add_tail(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock_irqrestore(&cmd->cmd_threads->cmd_list_lock, flags);
++ break;
++
++ case SCST_CONTEXT_DIRECT:
++ scst_process_active_cmd(cmd, false);
++ break;
++
++ case SCST_CONTEXT_DIRECT_ATOMIC:
++ scst_process_active_cmd(cmd, true);
++ break;
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_cmd_init_done);
++
++static int scst_pre_parse(struct scst_cmd *cmd)
++{
++ int res;
++ struct scst_device *dev = cmd->dev;
++ int rc;
++
++ TRACE_ENTRY();
++
++ /*
++ * Expected transfer data supplied by the SCSI transport via the
++ * target driver are untrusted, so we prefer to fetch them from CDB.
++ * Additionally, not all transports support supplying the expected
++ * transfer data.
++ */
++
++ rc = scst_get_cdb_info(cmd);
++ if (unlikely(rc != 0)) {
++ if (rc > 0) {
++ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
++ goto out_err;
++ }
++
++ EXTRACHECKS_BUG_ON(cmd->op_flags & SCST_INFO_VALID);
++
++ TRACE(TRACE_MINOR, "Unknown opcode 0x%02x for %s. "
++ "Should you update scst_scsi_op_table?",
++ cmd->cdb[0], dev->handler->name);
++ PRINT_BUFF_FLAG(TRACE_MINOR, "Failed CDB", cmd->cdb,
++ cmd->cdb_len);
++ } else
++ EXTRACHECKS_BUG_ON(!(cmd->op_flags & SCST_INFO_VALID));
++
++#ifdef CONFIG_SCST_STRICT_SERIALIZING
++ cmd->inc_expected_sn_on_done = 1;
++#else
++ cmd->inc_expected_sn_on_done = dev->handler->exec_sync ||
++ (!dev->has_own_order_mgmt &&
++ (dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER ||
++ cmd->queue_type == SCST_CMD_QUEUE_ORDERED));
++#endif
++
++ TRACE_DBG("op_name <%s> (cmd %p), direction=%d "
++ "(expected %d, set %s), bufflen=%d, out_bufflen=%d (expected "
++ "len %d, out expected len %d), flags=%d", cmd->op_name, cmd,
++ cmd->data_direction, cmd->expected_data_direction,
++ scst_cmd_is_expected_set(cmd) ? "yes" : "no",
++ cmd->bufflen, cmd->out_bufflen, cmd->expected_transfer_len,
++ cmd->expected_out_transfer_len, cmd->op_flags);
++
++ res = 0;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_err:
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ scst_set_cmd_abnormal_done_state(cmd);
++ res = -1;
++ goto out;
++}
++
++#ifndef CONFIG_SCST_USE_EXPECTED_VALUES
++static bool scst_is_allowed_to_mismatch_cmd(struct scst_cmd *cmd)
++{
++ bool res = false;
++
++ /* VERIFY commands with BYTCHK unset shouldn't fail here */
++ if ((cmd->op_flags & SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED) &&
++ (cmd->cdb[1] & BYTCHK) == 0) {
++ res = true;
++ goto out;
++ }
++
++ switch (cmd->cdb[0]) {
++ case TEST_UNIT_READY:
++ /* Crazy VMware people sometimes do TUR with READ direction */
++ if ((cmd->expected_data_direction == SCST_DATA_READ) ||
++ (cmd->expected_data_direction == SCST_DATA_NONE))
++ res = true;
++ break;
++ }
++
++out:
++ return res;
++}
++#endif
++
++static int scst_parse_cmd(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_RES_CONT_SAME;
++ int state;
++ struct scst_device *dev = cmd->dev;
++ int orig_bufflen = cmd->bufflen;
++
++ TRACE_ENTRY();
++
++ if (likely(!scst_is_cmd_fully_local(cmd))) {
++ if (unlikely(!dev->handler->parse_atomic &&
++ scst_cmd_atomic(cmd))) {
++ /*
++ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
++ * optimization.
++ */
++ TRACE_MGMT_DBG("Dev handler %s parse() needs thread "
++ "context, rescheduling", dev->handler->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++
++ TRACE_DBG("Calling dev handler %s parse(%p)",
++ dev->handler->name, cmd);
++ TRACE_BUFF_FLAG(TRACE_SND_BOT, "Parsing: ",
++ cmd->cdb, cmd->cdb_len);
++ scst_set_cur_start(cmd);
++ state = dev->handler->parse(cmd);
++ /* Caution: cmd can be already dead here */
++ TRACE_DBG("Dev handler %s parse() returned %d",
++ dev->handler->name, state);
++
++ switch (state) {
++ case SCST_CMD_STATE_NEED_THREAD_CTX:
++ scst_set_parse_time(cmd);
++ TRACE_DBG("Dev handler %s parse() requested thread "
++ "context, rescheduling", dev->handler->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++
++ case SCST_CMD_STATE_STOP:
++ TRACE_DBG("Dev handler %s parse() requested stop "
++ "processing", dev->handler->name);
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ goto out;
++ }
++
++ scst_set_parse_time(cmd);
++
++ if (state == SCST_CMD_STATE_DEFAULT)
++ state = SCST_CMD_STATE_PREPARE_SPACE;
++ } else
++ state = SCST_CMD_STATE_PREPARE_SPACE;
++
++ if (unlikely(state == SCST_CMD_STATE_PRE_XMIT_RESP))
++ goto set_res;
++
++ if (unlikely(!(cmd->op_flags & SCST_INFO_VALID))) {
++#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
++ if (scst_cmd_is_expected_set(cmd)) {
++ TRACE(TRACE_MINOR, "Using initiator supplied values: "
++ "direction %d, transfer_len %d/%d",
++ cmd->expected_data_direction,
++ cmd->expected_transfer_len,
++ cmd->expected_out_transfer_len);
++ cmd->data_direction = cmd->expected_data_direction;
++ cmd->bufflen = cmd->expected_transfer_len;
++ cmd->out_bufflen = cmd->expected_out_transfer_len;
++ } else {
++ PRINT_ERROR("Unknown opcode 0x%02x for %s and "
++ "target %s not supplied expected values",
++ cmd->cdb[0], dev->handler->name, cmd->tgtt->name);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ goto out_done;
++ }
++#else
++ /*
++ * Let's ignore reporting T10/04-262r7 16-byte and 12-byte ATA
++ * pass-thru commands to not pollute logs (udev(?) checks them
++ * for some reason). If somebody has their description, please,
++ * update scst_scsi_op_table.
++ */
++ if ((cmd->cdb[0] != 0x85) && (cmd->cdb[0] != 0xa1))
++ PRINT_ERROR("Refusing unknown opcode %x", cmd->cdb[0]);
++ else
++ TRACE(TRACE_MINOR, "Refusing unknown opcode %x",
++ cmd->cdb[0]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ goto out_done;
++#endif
++ }
++
++ if (unlikely(cmd->cdb_len == 0)) {
++ PRINT_ERROR("Unable to get CDB length for "
++ "opcode 0x%02x. Returning INVALID "
++ "OPCODE", cmd->cdb[0]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ goto out_done;
++ }
++
++ EXTRACHECKS_BUG_ON(cmd->cdb_len == 0);
++
++ TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
++ "(expected %d, set %s), bufflen=%d, out_bufflen=%d, (expected "
++ "len %d, out expected len %d), flags=%x", cmd->op_name, cmd,
++ cmd->data_direction, cmd->expected_data_direction,
++ scst_cmd_is_expected_set(cmd) ? "yes" : "no",
++ cmd->bufflen, cmd->out_bufflen, cmd->expected_transfer_len,
++ cmd->expected_out_transfer_len, cmd->op_flags);
++
++ if (unlikely((cmd->op_flags & SCST_UNKNOWN_LENGTH) != 0)) {
++ if (scst_cmd_is_expected_set(cmd)) {
++ /*
++ * Command data length can't be easily
++ * determined from the CDB. ToDo, all such
++ * commands processing should be fixed. Until
++ * it's done, get the length from the supplied
++ * expected value, but limit it to some
++ * reasonable value (15MB).
++ */
++ cmd->bufflen = min(cmd->expected_transfer_len,
++ 15*1024*1024);
++ if (cmd->data_direction == SCST_DATA_BIDI)
++ cmd->out_bufflen = min(cmd->expected_out_transfer_len,
++ 15*1024*1024);
++ cmd->op_flags &= ~SCST_UNKNOWN_LENGTH;
++ } else {
++ PRINT_ERROR("Unknown data transfer length for opcode "
++ "0x%x (handler %s, target %s)", cmd->cdb[0],
++ dev->handler->name, cmd->tgtt->name);
++ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_message));
++ goto out_done;
++ }
++ }
++
++ if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_NACA_BIT)) {
++ PRINT_ERROR("NACA bit in control byte CDB is not supported "
++ "(opcode 0x%02x)", cmd->cdb[0]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_done;
++ }
++
++ if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_LINK_BIT)) {
++ PRINT_ERROR("Linked commands are not supported "
++ "(opcode 0x%02x)", cmd->cdb[0]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_done;
++ }
++
++ if (cmd->dh_data_buf_alloced &&
++ unlikely((orig_bufflen > cmd->bufflen))) {
++ PRINT_ERROR("Dev handler supplied data buffer (size %d), "
++ "is less, than required (size %d)", cmd->bufflen,
++ orig_bufflen);
++ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
++ goto out_hw_error;
++ }
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if ((cmd->bufflen != 0) &&
++ ((cmd->data_direction == SCST_DATA_NONE) ||
++ ((cmd->sg == NULL) && (state > SCST_CMD_STATE_PREPARE_SPACE)))) {
++ PRINT_ERROR("Dev handler %s parse() returned "
++ "invalid cmd data_direction %d, bufflen %d, state %d "
++ "or sg %p (opcode 0x%x)", dev->handler->name,
++ cmd->data_direction, cmd->bufflen, state, cmd->sg,
++ cmd->cdb[0]);
++ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
++ goto out_hw_error;
++ }
++#endif
++
++ if (scst_cmd_is_expected_set(cmd)) {
++#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
++ if (unlikely((cmd->data_direction != cmd->expected_data_direction) ||
++ (cmd->bufflen != cmd->expected_transfer_len) ||
++ (cmd->out_bufflen != cmd->expected_out_transfer_len))) {
++ TRACE(TRACE_MINOR, "Expected values don't match "
++ "decoded ones: data_direction %d, "
++ "expected_data_direction %d, "
++ "bufflen %d, expected_transfer_len %d, "
++ "out_bufflen %d, expected_out_transfer_len %d",
++ cmd->data_direction,
++ cmd->expected_data_direction,
++ cmd->bufflen, cmd->expected_transfer_len,
++ cmd->out_bufflen, cmd->expected_out_transfer_len);
++ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
++ cmd->cdb, cmd->cdb_len);
++ cmd->data_direction = cmd->expected_data_direction;
++ cmd->bufflen = cmd->expected_transfer_len;
++ cmd->out_bufflen = cmd->expected_out_transfer_len;
++ cmd->resid_possible = 1;
++ }
++#else
++ if (unlikely(cmd->data_direction !=
++ cmd->expected_data_direction)) {
++ if (((cmd->expected_data_direction != SCST_DATA_NONE) ||
++ (cmd->bufflen != 0)) &&
++ !scst_is_allowed_to_mismatch_cmd(cmd)) {
++ PRINT_ERROR("Expected data direction %d for "
++ "opcode 0x%02x (handler %s, target %s) "
++ "doesn't match decoded value %d",
++ cmd->expected_data_direction,
++ cmd->cdb[0], dev->handler->name,
++ cmd->tgtt->name, cmd->data_direction);
++ PRINT_BUFFER("Failed CDB", cmd->cdb,
++ cmd->cdb_len);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_message));
++ goto out_done;
++ }
++ }
++ if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) {
++ TRACE(TRACE_MINOR, "Warning: expected "
++ "transfer length %d for opcode 0x%02x "
++ "(handler %s, target %s) doesn't match "
++ "decoded value %d",
++ cmd->expected_transfer_len, cmd->cdb[0],
++ dev->handler->name, cmd->tgtt->name,
++ cmd->bufflen);
++ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
++ cmd->cdb, cmd->cdb_len);
++ if ((cmd->data_direction & SCST_DATA_READ) ||
++ (cmd->data_direction & SCST_DATA_WRITE))
++ cmd->resid_possible = 1;
++ }
++ if (unlikely(cmd->out_bufflen != cmd->expected_out_transfer_len)) {
++ TRACE(TRACE_MINOR, "Warning: expected bidirectional OUT "
++ "transfer length %d for opcode 0x%02x "
++ "(handler %s, target %s) doesn't match "
++ "decoded value %d",
++ cmd->expected_out_transfer_len, cmd->cdb[0],
++ dev->handler->name, cmd->tgtt->name,
++ cmd->out_bufflen);
++ PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
++ cmd->cdb, cmd->cdb_len);
++ cmd->resid_possible = 1;
++ }
++#endif
++ }
++
++ if (unlikely(cmd->data_direction == SCST_DATA_UNKNOWN)) {
++ PRINT_ERROR("Unknown data direction. Opcode 0x%x, handler %s, "
++ "target %s", cmd->cdb[0], dev->handler->name,
++ cmd->tgtt->name);
++ PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
++ goto out_hw_error;
++ }
++
++set_res:
++ if (cmd->data_len == -1)
++ cmd->data_len = cmd->bufflen;
++
++ if (cmd->bufflen == 0) {
++ /*
++ * According to SPC bufflen 0 for data transfer commands isn't
++ * an error, so we need to fix the transfer direction.
++ */
++ cmd->data_direction = SCST_DATA_NONE;
++ }
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ switch (state) {
++ case SCST_CMD_STATE_PREPARE_SPACE:
++ case SCST_CMD_STATE_PARSE:
++ case SCST_CMD_STATE_RDY_TO_XFER:
++ case SCST_CMD_STATE_TGT_PRE_EXEC:
++ case SCST_CMD_STATE_SEND_FOR_EXEC:
++ case SCST_CMD_STATE_LOCAL_EXEC:
++ case SCST_CMD_STATE_REAL_EXEC:
++ case SCST_CMD_STATE_PRE_DEV_DONE:
++ case SCST_CMD_STATE_DEV_DONE:
++ case SCST_CMD_STATE_PRE_XMIT_RESP:
++ case SCST_CMD_STATE_XMIT_RESP:
++ case SCST_CMD_STATE_FINISHED:
++ case SCST_CMD_STATE_FINISHED_INTERNAL:
++#endif
++ cmd->state = state;
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++#ifdef CONFIG_SCST_EXTRACHECKS
++ break;
++
++ default:
++ if (state >= 0) {
++ PRINT_ERROR("Dev handler %s parse() returned "
++ "invalid cmd state %d (opcode %d)",
++ dev->handler->name, state, cmd->cdb[0]);
++ } else {
++ PRINT_ERROR("Dev handler %s parse() returned "
++ "error %d (opcode %d)", dev->handler->name,
++ state, cmd->cdb[0]);
++ }
++ goto out_hw_error;
++ }
++#endif
++
++ if (cmd->resp_data_len == -1) {
++ if (cmd->data_direction & SCST_DATA_READ)
++ cmd->resp_data_len = cmd->bufflen;
++ else
++ cmd->resp_data_len = 0;
++ }
++
++ /* We already completed (with an error) */
++ if (unlikely(cmd->completed))
++ goto out_done;
++
++#ifndef CONFIG_SCST_TEST_IO_IN_SIRQ
++ /*
++ * We can't allow atomic command on the exec stages. It shouldn't
++ * be because of the SCST_TGT_DEV_AFTER_* optimization, but during
++ * parsing data_direction can change, so we need to recheck.
++ */
++ if (unlikely(scst_cmd_atomic(cmd) &&
++ !(cmd->data_direction & SCST_DATA_WRITE))) {
++ TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_MINOR, "Atomic context and "
++ "non-WRITE data direction, rescheduling (cmd %p)", cmd);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++#endif
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++
++out_hw_error:
++ /* dev_done() will be called as part of the regular cmd's finish */
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++
++out_done:
++ scst_set_cmd_abnormal_done_state(cmd);
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++ goto out;
++}
++
++static void scst_set_write_len(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(!(cmd->data_direction & SCST_DATA_WRITE));
++
++ if (cmd->data_direction & SCST_DATA_READ) {
++ cmd->write_len = cmd->out_bufflen;
++ cmd->write_sg = &cmd->out_sg;
++ cmd->write_sg_cnt = &cmd->out_sg_cnt;
++ } else {
++ cmd->write_len = cmd->bufflen;
++ /* write_sg and write_sg_cnt already initialized correctly */
++ }
++
++ TRACE_MEM("cmd %p, write_len %d, write_sg %p, write_sg_cnt %d, "
++ "resid_possible %d", cmd, cmd->write_len, *cmd->write_sg,
++ *cmd->write_sg_cnt, cmd->resid_possible);
++
++ if (unlikely(cmd->resid_possible)) {
++ if (cmd->data_direction & SCST_DATA_READ) {
++ cmd->write_len = min(cmd->out_bufflen,
++ cmd->expected_out_transfer_len);
++ if (cmd->write_len == cmd->out_bufflen)
++ goto out;
++ } else {
++ cmd->write_len = min(cmd->bufflen,
++ cmd->expected_transfer_len);
++ if (cmd->write_len == cmd->bufflen)
++ goto out;
++ }
++ scst_limit_sg_write_len(cmd);
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int scst_prepare_space(struct scst_cmd *cmd)
++{
++ int r = 0, res = SCST_CMD_STATE_RES_CONT_SAME;
++ struct scst_device *dev = cmd->dev;
++
++ TRACE_ENTRY();
++
++ if (cmd->data_direction == SCST_DATA_NONE)
++ goto done;
++
++ if (likely(!scst_is_cmd_fully_local(cmd)) &&
++ (dev->handler->alloc_data_buf != NULL)) {
++ int state;
++
++ if (unlikely(!dev->handler->alloc_data_buf_atomic &&
++ scst_cmd_atomic(cmd))) {
++ /*
++ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
++ * optimization.
++ */
++ TRACE_MGMT_DBG("Dev handler %s alloc_data_buf() needs "
++ "thread context, rescheduling",
++ dev->handler->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++
++ TRACE_DBG("Calling dev handler %s alloc_data_buf(%p)",
++ dev->handler->name, cmd);
++ scst_set_cur_start(cmd);
++ state = dev->handler->alloc_data_buf(cmd);
++ /* Caution: cmd can be already dead here */
++ TRACE_DBG("Dev handler %s alloc_data_buf() returned %d",
++ dev->handler->name, state);
++
++ switch (state) {
++ case SCST_CMD_STATE_NEED_THREAD_CTX:
++ scst_set_alloc_buf_time(cmd);
++ TRACE_DBG("Dev handler %s alloc_data_buf() requested "
++ "thread context, rescheduling",
++ dev->handler->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++
++ case SCST_CMD_STATE_STOP:
++ TRACE_DBG("Dev handler %s alloc_data_buf() requested "
++ "stop processing", dev->handler->name);
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ goto out;
++ }
++
++ scst_set_alloc_buf_time(cmd);
++
++ if (unlikely(state != SCST_CMD_STATE_DEFAULT)) {
++ cmd->state = state;
++ goto out;
++ }
++ }
++
++ if (cmd->tgt_need_alloc_data_buf) {
++ int orig_bufflen = cmd->bufflen;
++
++ TRACE_MEM("Custom tgt data buf allocation requested (cmd %p)",
++ cmd);
++
++ scst_set_cur_start(cmd);
++ r = cmd->tgtt->alloc_data_buf(cmd);
++ scst_set_alloc_buf_time(cmd);
++
++ if (r > 0)
++ goto alloc;
++ else if (r == 0) {
++ if (unlikely(cmd->bufflen == 0)) {
++ /* See comment in scst_alloc_space() */
++ if (cmd->sg == NULL)
++ goto alloc;
++ }
++
++ cmd->tgt_data_buf_alloced = 1;
++
++ if (unlikely(orig_bufflen < cmd->bufflen)) {
++ PRINT_ERROR("Target driver allocated data "
++ "buffer (size %d), is less, than "
++ "required (size %d)", orig_bufflen,
++ cmd->bufflen);
++ goto out_error;
++ }
++ TRACE_MEM("tgt_data_buf_alloced (cmd %p)", cmd);
++ } else
++ goto check;
++ }
++
++alloc:
++ if (!cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) {
++ r = scst_alloc_space(cmd);
++ } else if (cmd->dh_data_buf_alloced && !cmd->tgt_data_buf_alloced) {
++ TRACE_MEM("dh_data_buf_alloced set (cmd %p)", cmd);
++ r = 0;
++ } else if (cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) {
++ TRACE_MEM("tgt_data_buf_alloced set (cmd %p)", cmd);
++ cmd->sg = cmd->tgt_sg;
++ cmd->sg_cnt = cmd->tgt_sg_cnt;
++ cmd->out_sg = cmd->tgt_out_sg;
++ cmd->out_sg_cnt = cmd->tgt_out_sg_cnt;
++ r = 0;
++ } else {
++ TRACE_MEM("Both *_data_buf_alloced set (cmd %p, sg %p, "
++ "sg_cnt %d, tgt_sg %p, tgt_sg_cnt %d)", cmd, cmd->sg,
++ cmd->sg_cnt, cmd->tgt_sg, cmd->tgt_sg_cnt);
++ r = 0;
++ }
++
++check:
++ if (r != 0) {
++ if (scst_cmd_atomic(cmd)) {
++ TRACE_MEM("%s", "Atomic memory allocation failed, "
++ "rescheduling to the thread");
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ } else
++ goto out_no_space;
++ }
++
++done:
++ if (cmd->preprocessing_only) {
++ cmd->state = SCST_CMD_STATE_PREPROCESSING_DONE;
++ if (cmd->data_direction & SCST_DATA_WRITE)
++ scst_set_write_len(cmd);
++ } else if (cmd->data_direction & SCST_DATA_WRITE) {
++ cmd->state = SCST_CMD_STATE_RDY_TO_XFER;
++ scst_set_write_len(cmd);
++ } else
++ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++
++out_no_space:
++ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate or build requested buffer "
++ "(size %d), sending BUSY or QUEUE FULL status", cmd->bufflen);
++ scst_set_busy(cmd);
++ scst_set_cmd_abnormal_done_state(cmd);
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++ goto out;
++
++out_error:
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++ scst_set_cmd_abnormal_done_state(cmd);
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++ goto out;
++}
++
++static int scst_preprocessing_done(struct scst_cmd *cmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(!cmd->preprocessing_only);
++
++ cmd->preprocessing_only = 0;
++
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ cmd->state = SCST_CMD_STATE_PREPROCESSING_DONE_CALLED;
++
++ TRACE_DBG("Calling preprocessing_done(cmd %p)", cmd);
++ scst_set_cur_start(cmd);
++ cmd->tgtt->preprocessing_done(cmd);
++ TRACE_DBG("%s", "preprocessing_done() returned");
++
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/**
++ * scst_restart_cmd() - restart execution of the command
++ * @cmd: SCST commands
++ * @status: completion status
++ * @pref_context: preferred command execition context
++ *
++ * Description:
++ * Notifies SCST that the driver finished its part of the command's
++ * preprocessing and it is ready for further processing.
++ *
++ * The second argument sets completion status
++ * (see SCST_PREPROCESS_STATUS_* constants for details)
++ *
++ * See also comment for scst_cmd_init_done() for the serialization
++ * requirements.
++ */
++void scst_restart_cmd(struct scst_cmd *cmd, int status,
++ enum scst_exec_context pref_context)
++{
++ TRACE_ENTRY();
++
++ scst_set_restart_waiting_time(cmd);
++
++ TRACE_DBG("Preferred context: %d", pref_context);
++ TRACE_DBG("tag=%llu, status=%#x",
++ (long long unsigned int)scst_cmd_get_tag(cmd),
++ status);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if ((in_irq() || irqs_disabled()) &&
++ ((pref_context == SCST_CONTEXT_DIRECT) ||
++ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) {
++ PRINT_ERROR("Wrong context %d in IRQ from target %s, use "
++ "SCST_CONTEXT_THREAD instead", pref_context,
++ cmd->tgtt->name);
++ dump_stack();
++ pref_context = SCST_CONTEXT_THREAD;
++ }
++#endif
++
++ switch (status) {
++ case SCST_PREPROCESS_STATUS_SUCCESS:
++ if (cmd->data_direction & SCST_DATA_WRITE)
++ cmd->state = SCST_CMD_STATE_RDY_TO_XFER;
++ else
++ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
++ if (cmd->set_sn_on_restart_cmd)
++ scst_cmd_set_sn(cmd);
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED)
++ break;
++#endif
++ /* Small context optimization */
++ if ((pref_context == SCST_CONTEXT_TASKLET) ||
++ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC) ||
++ ((pref_context == SCST_CONTEXT_SAME) &&
++ scst_cmd_atomic(cmd)))
++ pref_context = SCST_CONTEXT_THREAD;
++ break;
++
++ case SCST_PREPROCESS_STATUS_ERROR_SENSE_SET:
++ scst_set_cmd_abnormal_done_state(cmd);
++ pref_context = SCST_CONTEXT_THREAD;
++ break;
++
++ case SCST_PREPROCESS_STATUS_ERROR_FATAL:
++ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
++ /* go through */
++ case SCST_PREPROCESS_STATUS_ERROR:
++ if (cmd->sense != NULL)
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ scst_set_cmd_abnormal_done_state(cmd);
++ pref_context = SCST_CONTEXT_THREAD;
++ break;
++
++ default:
++ PRINT_ERROR("%s() received unknown status %x", __func__,
++ status);
++ scst_set_cmd_abnormal_done_state(cmd);
++ pref_context = SCST_CONTEXT_THREAD;
++ break;
++ }
++
++ scst_process_redirect_cmd(cmd, pref_context, 1);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_restart_cmd);
++
++static int scst_rdy_to_xfer(struct scst_cmd *cmd)
++{
++ int res, rc;
++ struct scst_tgt_template *tgtt = cmd->tgtt;
++
++ TRACE_ENTRY();
++
++ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
++ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd);
++ goto out_dev_done;
++ }
++
++ if ((tgtt->rdy_to_xfer == NULL) || unlikely(cmd->internal)) {
++ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
++#ifndef CONFIG_SCST_TEST_IO_IN_SIRQ
++ /* We can't allow atomic command on the exec stages */
++ if (scst_cmd_atomic(cmd)) {
++ TRACE_DBG("NULL rdy_to_xfer() and atomic context, "
++ "rescheduling (cmd %p)", cmd);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ } else
++#endif
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++ goto out;
++ }
++
++ if (unlikely(!tgtt->rdy_to_xfer_atomic && scst_cmd_atomic(cmd))) {
++ /*
++ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
++ * optimization.
++ */
++ TRACE_MGMT_DBG("Target driver %s rdy_to_xfer() needs thread "
++ "context, rescheduling", tgtt->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++
++ while (1) {
++ int finished_cmds = atomic_read(&cmd->tgt->finished_cmds);
++
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ cmd->state = SCST_CMD_STATE_DATA_WAIT;
++
++ if (tgtt->on_hw_pending_cmd_timeout != NULL) {
++ struct scst_session *sess = cmd->sess;
++ cmd->hw_pending_start = jiffies;
++ cmd->cmd_hw_pending = 1;
++ if (!test_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags)) {
++ TRACE_DBG("Sched HW pending work for sess %p "
++ "(max time %d)", sess,
++ tgtt->max_hw_pending_time);
++ set_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED,
++ &sess->sess_aflags);
++ schedule_delayed_work(&sess->hw_pending_work,
++ tgtt->max_hw_pending_time * HZ);
++ }
++ }
++
++ scst_set_cur_start(cmd);
++
++ TRACE_DBG("Calling rdy_to_xfer(%p)", cmd);
++#ifdef CONFIG_SCST_DEBUG_RETRY
++ if (((scst_random() % 100) == 75))
++ rc = SCST_TGT_RES_QUEUE_FULL;
++ else
++#endif
++ rc = tgtt->rdy_to_xfer(cmd);
++ TRACE_DBG("rdy_to_xfer() returned %d", rc);
++
++ if (likely(rc == SCST_TGT_RES_SUCCESS))
++ goto out;
++
++ scst_set_rdy_to_xfer_time(cmd);
++
++ cmd->cmd_hw_pending = 0;
++
++ /* Restore the previous state */
++ cmd->state = SCST_CMD_STATE_RDY_TO_XFER;
++
++ switch (rc) {
++ case SCST_TGT_RES_QUEUE_FULL:
++ if (scst_queue_retry_cmd(cmd, finished_cmds) == 0)
++ break;
++ else
++ continue;
++
++ case SCST_TGT_RES_NEED_THREAD_CTX:
++ TRACE_DBG("Target driver %s "
++ "rdy_to_xfer() requested thread "
++ "context, rescheduling", tgtt->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ break;
++
++ default:
++ goto out_error_rc;
++ }
++ break;
++ }
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++
++out_error_rc:
++ if (rc == SCST_TGT_RES_FATAL_ERROR) {
++ PRINT_ERROR("Target driver %s rdy_to_xfer() returned "
++ "fatal error", tgtt->name);
++ } else {
++ PRINT_ERROR("Target driver %s rdy_to_xfer() returned invalid "
++ "value %d", tgtt->name, rc);
++ }
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++
++out_dev_done:
++ scst_set_cmd_abnormal_done_state(cmd);
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++ goto out;
++}
++
++/* No locks, but might be in IRQ */
++static void scst_process_redirect_cmd(struct scst_cmd *cmd,
++ enum scst_exec_context context, int check_retries)
++{
++ struct scst_tgt *tgt = cmd->tgt;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Context: %x", context);
++
++ if (check_retries)
++ scst_check_retries(tgt);
++
++ if (context == SCST_CONTEXT_SAME)
++ context = scst_cmd_atomic(cmd) ? SCST_CONTEXT_DIRECT_ATOMIC :
++ SCST_CONTEXT_DIRECT;
++
++ switch (context) {
++ case SCST_CONTEXT_DIRECT_ATOMIC:
++ scst_process_active_cmd(cmd, true);
++ break;
++
++ case SCST_CONTEXT_DIRECT:
++ scst_process_active_cmd(cmd, false);
++ break;
++
++ case SCST_CONTEXT_TASKLET:
++ scst_schedule_tasklet(cmd);
++ break;
++
++ default:
++ PRINT_ERROR("Context %x is unknown, using the thread one",
++ context);
++ /* go through */
++ case SCST_CONTEXT_THREAD:
++ spin_lock_irqsave(&cmd->cmd_threads->cmd_list_lock, flags);
++ TRACE_DBG("Adding cmd %p to active cmd list", cmd);
++ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
++ list_add(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ else
++ list_add_tail(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock_irqrestore(&cmd->cmd_threads->cmd_list_lock, flags);
++ break;
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_rx_data() - the command's data received
++ * @cmd: SCST commands
++ * @status: data receiving completion status
++ * @pref_context: preferred command execution context
++ *
++ * Description:
++ * Notifies SCST that the driver received all the necessary data
++ * and the command is ready for further processing.
++ *
++ * The second argument sets data receiving completion status
++ * (see SCST_RX_STATUS_* constants for details)
++ */
++void scst_rx_data(struct scst_cmd *cmd, int status,
++ enum scst_exec_context pref_context)
++{
++ TRACE_ENTRY();
++
++ scst_set_rdy_to_xfer_time(cmd);
++
++ TRACE_DBG("Preferred context: %d", pref_context);
++ TRACE(TRACE_SCSI, "cmd %p, status %#x", cmd, status);
++
++ cmd->cmd_hw_pending = 0;
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if ((in_irq() || irqs_disabled()) &&
++ ((pref_context == SCST_CONTEXT_DIRECT) ||
++ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) {
++ PRINT_ERROR("Wrong context %d in IRQ from target %s, use "
++ "SCST_CONTEXT_THREAD instead", pref_context,
++ cmd->tgtt->name);
++ dump_stack();
++ pref_context = SCST_CONTEXT_THREAD;
++ }
++#endif
++
++ switch (status) {
++ case SCST_RX_STATUS_SUCCESS:
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ if (trace_flag & TRACE_RCV_BOT) {
++ int i;
++ struct scatterlist *sg;
++ if (cmd->out_sg != NULL)
++ sg = cmd->out_sg;
++ else if (cmd->tgt_out_sg != NULL)
++ sg = cmd->tgt_out_sg;
++ else if (cmd->tgt_sg != NULL)
++ sg = cmd->tgt_sg;
++ else
++ sg = cmd->sg;
++ if (sg != NULL) {
++ TRACE_RECV_BOT("RX data for cmd %p "
++ "(sg_cnt %d, sg %p, sg[0].page %p)",
++ cmd, cmd->tgt_sg_cnt, sg,
++ (void *)sg_page(&sg[0]));
++ for (i = 0; i < cmd->tgt_sg_cnt; ++i) {
++ PRINT_BUFF_FLAG(TRACE_RCV_BOT, "RX sg",
++ sg_virt(&sg[i]), sg[i].length);
++ }
++ }
++ }
++#endif
++ cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
++
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED)
++ break;
++#endif
++
++ /* Small context optimization */
++ if ((pref_context == SCST_CONTEXT_TASKLET) ||
++ (pref_context == SCST_CONTEXT_DIRECT_ATOMIC) ||
++ ((pref_context == SCST_CONTEXT_SAME) &&
++ scst_cmd_atomic(cmd)))
++ pref_context = SCST_CONTEXT_THREAD;
++ break;
++
++ case SCST_RX_STATUS_ERROR_SENSE_SET:
++ scst_set_cmd_abnormal_done_state(cmd);
++ pref_context = SCST_CONTEXT_THREAD;
++ break;
++
++ case SCST_RX_STATUS_ERROR_FATAL:
++ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
++ /* go through */
++ case SCST_RX_STATUS_ERROR:
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ scst_set_cmd_abnormal_done_state(cmd);
++ pref_context = SCST_CONTEXT_THREAD;
++ break;
++
++ default:
++ PRINT_ERROR("scst_rx_data() received unknown status %x",
++ status);
++ scst_set_cmd_abnormal_done_state(cmd);
++ pref_context = SCST_CONTEXT_THREAD;
++ break;
++ }
++
++ scst_process_redirect_cmd(cmd, pref_context, 1);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_rx_data);
++
++static int scst_tgt_pre_exec(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_RES_CONT_SAME, rc;
++
++ TRACE_ENTRY();
++
++ if (unlikely(cmd->resid_possible)) {
++ if (cmd->data_direction & SCST_DATA_WRITE) {
++ bool do_zero = false;
++ if (cmd->data_direction & SCST_DATA_READ) {
++ if (cmd->write_len != cmd->out_bufflen)
++ do_zero = true;
++ } else {
++ if (cmd->write_len != cmd->bufflen)
++ do_zero = true;
++ }
++ if (do_zero) {
++ scst_check_restore_sg_buff(cmd);
++ scst_zero_write_rest(cmd);
++ }
++ }
++ }
++
++ cmd->state = SCST_CMD_STATE_SEND_FOR_EXEC;
++
++ if ((cmd->tgtt->pre_exec == NULL) || unlikely(cmd->internal))
++ goto out;
++
++ TRACE_DBG("Calling pre_exec(%p)", cmd);
++ scst_set_cur_start(cmd);
++ rc = cmd->tgtt->pre_exec(cmd);
++ scst_set_pre_exec_time(cmd);
++ TRACE_DBG("pre_exec() returned %d", rc);
++
++ if (unlikely(rc != SCST_PREPROCESS_STATUS_SUCCESS)) {
++ switch (rc) {
++ case SCST_PREPROCESS_STATUS_ERROR_SENSE_SET:
++ scst_set_cmd_abnormal_done_state(cmd);
++ break;
++ case SCST_PREPROCESS_STATUS_ERROR_FATAL:
++ set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
++ /* go through */
++ case SCST_PREPROCESS_STATUS_ERROR:
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ scst_set_cmd_abnormal_done_state(cmd);
++ break;
++ default:
++ BUG();
++ break;
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
++ const uint8_t *rq_sense, int rq_sense_len, int resid)
++{
++ TRACE_ENTRY();
++
++ scst_set_exec_time(cmd);
++
++ cmd->status = result & 0xff;
++ cmd->msg_status = msg_byte(result);
++ cmd->host_status = host_byte(result);
++ cmd->driver_status = driver_byte(result);
++ if (unlikely(resid != 0)) {
++ if ((cmd->data_direction & SCST_DATA_READ) &&
++ (resid > 0) && (resid < cmd->resp_data_len))
++ scst_set_resp_data_len(cmd, cmd->resp_data_len - resid);
++ /*
++ * We ignore write direction residue, because from the
++ * initiator's POV we already transferred all the data.
++ */
++ }
++
++ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION)) {
++ /* We might have double reset UA here */
++ cmd->dbl_ua_orig_resp_data_len = cmd->resp_data_len;
++ cmd->dbl_ua_orig_data_direction = cmd->data_direction;
++
++ scst_alloc_set_sense(cmd, 1, rq_sense, rq_sense_len);
++ }
++
++ TRACE(TRACE_SCSI, "cmd %p, result %x, cmd->status %x, resid %d, "
++ "cmd->msg_status %x, cmd->host_status %x, "
++ "cmd->driver_status %x", cmd, result, cmd->status, resid,
++ cmd->msg_status, cmd->host_status, cmd->driver_status);
++
++ cmd->completed = 1;
++
++ TRACE_EXIT();
++ return;
++}
++
++/* For small context optimization */
++static inline enum scst_exec_context scst_optimize_post_exec_context(
++ struct scst_cmd *cmd, enum scst_exec_context context)
++{
++ if (((context == SCST_CONTEXT_SAME) && scst_cmd_atomic(cmd)) ||
++ (context == SCST_CONTEXT_TASKLET) ||
++ (context == SCST_CONTEXT_DIRECT_ATOMIC)) {
++ if (!test_bit(SCST_TGT_DEV_AFTER_EXEC_ATOMIC,
++ &cmd->tgt_dev->tgt_dev_flags))
++ context = SCST_CONTEXT_THREAD;
++ }
++ return context;
++}
++
++static void scst_cmd_done(void *data, char *sense, int result, int resid)
++{
++ struct scst_cmd *cmd;
++
++ TRACE_ENTRY();
++
++ cmd = (struct scst_cmd *)data;
++ if (cmd == NULL)
++ goto out;
++
++ scst_do_cmd_done(cmd, result, sense, SCSI_SENSE_BUFFERSIZE, resid);
++
++ cmd->state = SCST_CMD_STATE_PRE_DEV_DONE;
++
++ scst_process_redirect_cmd(cmd,
++ scst_optimize_post_exec_context(cmd, scst_estimate_context()), 0);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state,
++ enum scst_exec_context pref_context)
++{
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(cmd->pr_abort_counter != NULL);
++
++ scst_set_exec_time(cmd);
++
++ TRACE(TRACE_SCSI, "cmd %p, status %x, msg_status %x, host_status %x, "
++ "driver_status %x, resp_data_len %d", cmd, cmd->status,
++ cmd->msg_status, cmd->host_status, cmd->driver_status,
++ cmd->resp_data_len);
++
++ if (next_state == SCST_CMD_STATE_DEFAULT)
++ next_state = SCST_CMD_STATE_PRE_DEV_DONE;
++
++#if defined(CONFIG_SCST_DEBUG)
++ if (next_state == SCST_CMD_STATE_PRE_DEV_DONE) {
++ if ((trace_flag & TRACE_RCV_TOP) && (cmd->sg != NULL)) {
++ int i;
++ struct scatterlist *sg = cmd->sg;
++ TRACE_RECV_TOP("Exec'd %d S/G(s) at %p sg[0].page at "
++ "%p", cmd->sg_cnt, sg, (void *)sg_page(&sg[0]));
++ for (i = 0; i < cmd->sg_cnt; ++i) {
++ TRACE_BUFF_FLAG(TRACE_RCV_TOP,
++ "Exec'd sg", sg_virt(&sg[i]),
++ sg[i].length);
++ }
++ }
++ }
++#endif
++
++ cmd->state = next_state;
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if ((next_state != SCST_CMD_STATE_PRE_DEV_DONE) &&
++ (next_state != SCST_CMD_STATE_PRE_XMIT_RESP) &&
++ (next_state != SCST_CMD_STATE_FINISHED) &&
++ (next_state != SCST_CMD_STATE_FINISHED_INTERNAL)) {
++ PRINT_ERROR("%s() received invalid cmd state %d (opcode %d)",
++ __func__, next_state, cmd->cdb[0]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ scst_set_cmd_abnormal_done_state(cmd);
++ }
++#endif
++ pref_context = scst_optimize_post_exec_context(cmd, pref_context);
++ scst_process_redirect_cmd(cmd, pref_context, 0);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int scst_report_luns_local(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_COMPLETED, rc;
++ int dev_cnt = 0;
++ int buffer_size;
++ int i;
++ struct scst_tgt_dev *tgt_dev = NULL;
++ uint8_t *buffer;
++ int offs, overflow = 0;
++
++ TRACE_ENTRY();
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++
++ if ((cmd->cdb[2] != 0) && (cmd->cdb[2] != 2)) {
++ PRINT_ERROR("Unsupported SELECT REPORT value %x in REPORT "
++ "LUNS command", cmd->cdb[2]);
++ goto out_err;
++ }
++
++ buffer_size = scst_get_buf_first(cmd, &buffer);
++ if (unlikely(buffer_size == 0))
++ goto out_compl;
++ else if (unlikely(buffer_size < 0))
++ goto out_hw_err;
++
++ if (buffer_size < 16)
++ goto out_put_err;
++
++ memset(buffer, 0, buffer_size);
++ offs = 8;
++
++ /*
++ * cmd won't allow to suspend activities, so we can access
++ * sess->sess_tgt_dev_list_hash without any additional protection.
++ */
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &cmd->sess->sess_tgt_dev_list_hash[i];
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ if (!overflow) {
++ if (offs >= buffer_size) {
++ scst_put_buf(cmd, buffer);
++ buffer_size = scst_get_buf_next(cmd,
++ &buffer);
++ if (buffer_size > 0) {
++ memset(buffer, 0, buffer_size);
++ offs = 0;
++ } else {
++ overflow = 1;
++ goto inc_dev_cnt;
++ }
++ }
++ if ((buffer_size - offs) < 8) {
++ PRINT_ERROR("Buffer allocated for "
++ "REPORT LUNS command doesn't "
++ "allow to fit 8 byte entry "
++ "(buffer_size=%d)",
++ buffer_size);
++ goto out_put_hw_err;
++ }
++ if ((cmd->sess->acg->addr_method == SCST_LUN_ADDR_METHOD_FLAT) &&
++ (tgt_dev->lun != 0)) {
++ buffer[offs] = (tgt_dev->lun >> 8) & 0x3f;
++ buffer[offs] = buffer[offs] | 0x40;
++ buffer[offs+1] = tgt_dev->lun & 0xff;
++ } else {
++ buffer[offs] = (tgt_dev->lun >> 8) & 0xff;
++ buffer[offs+1] = tgt_dev->lun & 0xff;
++ }
++ offs += 8;
++ }
++inc_dev_cnt:
++ dev_cnt++;
++ }
++ }
++ if (!overflow)
++ scst_put_buf(cmd, buffer);
++
++ /* Set the response header */
++ buffer_size = scst_get_buf_first(cmd, &buffer);
++ if (unlikely(buffer_size == 0))
++ goto out_compl;
++ else if (unlikely(buffer_size < 0))
++ goto out_hw_err;
++
++ dev_cnt *= 8;
++ buffer[0] = (dev_cnt >> 24) & 0xff;
++ buffer[1] = (dev_cnt >> 16) & 0xff;
++ buffer[2] = (dev_cnt >> 8) & 0xff;
++ buffer[3] = dev_cnt & 0xff;
++
++ scst_put_buf(cmd, buffer);
++
++ dev_cnt += 8;
++ if (dev_cnt < cmd->resp_data_len)
++ scst_set_resp_data_len(cmd, dev_cnt);
++
++out_compl:
++ cmd->completed = 1;
++
++ /* Clear left sense_reported_luns_data_changed UA, if any. */
++
++ /*
++ * cmd won't allow to suspend activities, so we can access
++ * sess->sess_tgt_dev_list_hash without any additional protection.
++ */
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &cmd->sess->sess_tgt_dev_list_hash[i];
++
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ struct scst_tgt_dev_UA *ua;
++
++ spin_lock_bh(&tgt_dev->tgt_dev_lock);
++ list_for_each_entry(ua, &tgt_dev->UA_list,
++ UA_list_entry) {
++ if (scst_analyze_sense(ua->UA_sense_buffer,
++ ua->UA_valid_sense_len,
++ SCST_SENSE_ALL_VALID,
++ SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed))) {
++ TRACE_MGMT_DBG("Freeing not needed "
++ "REPORTED LUNS DATA CHANGED UA "
++ "%p", ua);
++ list_del(&ua->UA_list_entry);
++ mempool_free(ua, scst_ua_mempool);
++ break;
++ }
++ }
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++ }
++ }
++
++out_done:
++ /* Report the result */
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_put_err:
++ scst_put_buf(cmd, buffer);
++
++out_err:
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_compl;
++
++out_put_hw_err:
++ scst_put_buf(cmd, buffer);
++
++out_hw_err:
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_compl;
++}
++
++static int scst_request_sense_local(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_COMPLETED, rc;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ uint8_t *buffer;
++ int buffer_size = 0, sl = 0;
++
++ TRACE_ENTRY();
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++
++ spin_lock_bh(&tgt_dev->tgt_dev_lock);
++
++ if (tgt_dev->tgt_dev_valid_sense_len == 0)
++ goto out_unlock_not_completed;
++
++ TRACE(TRACE_SCSI, "%s: Returning stored sense", cmd->op_name);
++
++ buffer_size = scst_get_buf_first(cmd, &buffer);
++ if (unlikely(buffer_size == 0))
++ goto out_unlock_compl;
++ else if (unlikely(buffer_size < 0))
++ goto out_unlock_hw_err;
++
++ memset(buffer, 0, buffer_size);
++
++ if (((tgt_dev->tgt_dev_sense[0] == 0x70) ||
++ (tgt_dev->tgt_dev_sense[0] == 0x71)) && (cmd->cdb[1] & 1)) {
++ PRINT_WARNING("%s: Fixed format of the saved sense, but "
++ "descriptor format requested. Convertion will "
++ "truncated data", cmd->op_name);
++ PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense,
++ tgt_dev->tgt_dev_valid_sense_len);
++
++ buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size);
++ sl = scst_set_sense(buffer, buffer_size, true,
++ tgt_dev->tgt_dev_sense[2], tgt_dev->tgt_dev_sense[12],
++ tgt_dev->tgt_dev_sense[13]);
++ } else if (((tgt_dev->tgt_dev_sense[0] == 0x72) ||
++ (tgt_dev->tgt_dev_sense[0] == 0x73)) && !(cmd->cdb[1] & 1)) {
++ PRINT_WARNING("%s: Descriptor format of the "
++ "saved sense, but fixed format requested. Convertion "
++ "will truncated data", cmd->op_name);
++ PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense,
++ tgt_dev->tgt_dev_valid_sense_len);
++
++ buffer_size = min(SCST_STANDARD_SENSE_LEN, buffer_size);
++ sl = scst_set_sense(buffer, buffer_size, false,
++ tgt_dev->tgt_dev_sense[1], tgt_dev->tgt_dev_sense[2],
++ tgt_dev->tgt_dev_sense[3]);
++ } else {
++ if (buffer_size >= tgt_dev->tgt_dev_valid_sense_len)
++ sl = tgt_dev->tgt_dev_valid_sense_len;
++ else {
++ sl = buffer_size;
++ TRACE(TRACE_MINOR, "%s: Being returned sense truncated "
++ "to size %d (needed %d)", cmd->op_name,
++ buffer_size, tgt_dev->tgt_dev_valid_sense_len);
++ }
++ memcpy(buffer, tgt_dev->tgt_dev_sense, sl);
++ }
++
++ scst_put_buf(cmd, buffer);
++
++ tgt_dev->tgt_dev_valid_sense_len = 0;
++
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++
++ scst_set_resp_data_len(cmd, sl);
++
++out_compl:
++ cmd->completed = 1;
++
++out_done:
++ /* Report the result */
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unlock_hw_err:
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_compl;
++
++out_unlock_not_completed:
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++ res = SCST_EXEC_NOT_COMPLETED;
++ goto out;
++
++out_unlock_compl:
++ spin_unlock_bh(&tgt_dev->tgt_dev_lock);
++ goto out_compl;
++}
++
++static int scst_reserve_local(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_NOT_COMPLETED, rc;
++ struct scst_device *dev;
++ struct scst_tgt_dev *tgt_dev_tmp;
++
++ TRACE_ENTRY();
++
++ if ((cmd->cdb[0] == RESERVE_10) && (cmd->cdb[2] & SCST_RES_3RDPTY)) {
++ PRINT_ERROR("RESERVE_10: 3rdPty RESERVE not implemented "
++ "(lun=%lld)", (long long unsigned int)cmd->lun);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_done;
++ }
++
++ dev = cmd->dev;
++
++ /*
++ * There's no need to block this device, even for
++ * SCST_CONTR_MODE_ONE_TASK_SET, or anyhow else protect reservations
++ * changes, because:
++ *
++ * 1. The reservation changes are (rather) atomic, i.e., in contrast
++ * to persistent reservations, don't have any invalid intermediate
++ * states during being changed.
++ *
++ * 2. It's a duty of initiators to ensure order of regular commands
++ * around the reservation command either by ORDERED attribute, or by
++ * queue draining, or etc. For case of SCST_CONTR_MODE_ONE_TASK_SET
++ * there are no target drivers which can ensure even for ORDERED
++ * comamnds order of their delivery, so, because initiators know
++ * it, also there's no point to do any extra protection actions.
++ */
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ if (!list_empty(&dev->dev_registrants_list)) {
++ if (scst_pr_crh_case(cmd))
++ goto out_completed;
++ else {
++ scst_set_cmd_error_status(cmd,
++ SAM_STAT_RESERVATION_CONFLICT);
++ goto out_done;
++ }
++ }
++
++ spin_lock_bh(&dev->dev_lock);
++
++ if (test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) {
++ spin_unlock_bh(&dev->dev_lock);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out_done;
++ }
++
++ list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if (cmd->tgt_dev != tgt_dev_tmp)
++ set_bit(SCST_TGT_DEV_RESERVED,
++ &tgt_dev_tmp->tgt_dev_flags);
++ }
++ dev->dev_reserved = 1;
++
++ spin_unlock_bh(&dev->dev_lock);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_completed:
++ cmd->completed = 1;
++
++out_done:
++ /* Report the result */
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++ res = SCST_EXEC_COMPLETED;
++ goto out;
++}
++
++static int scst_release_local(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_NOT_COMPLETED, rc;
++ struct scst_tgt_dev *tgt_dev_tmp;
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ dev = cmd->dev;
++
++ /*
++ * See comment in scst_reserve_local() why no dev blocking or any
++ * other protection is needed here.
++ */
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ if (!list_empty(&dev->dev_registrants_list)) {
++ if (scst_pr_crh_case(cmd))
++ goto out_completed;
++ else {
++ scst_set_cmd_error_status(cmd,
++ SAM_STAT_RESERVATION_CONFLICT);
++ goto out_done;
++ }
++ }
++
++ spin_lock_bh(&dev->dev_lock);
++
++ /*
++ * The device could be RELEASED behind us, if RESERVING session
++ * is closed (see scst_free_tgt_dev()), but this actually doesn't
++ * matter, so use lock and no retest for DEV_RESERVED bits again
++ */
++ if (test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) {
++ res = SCST_EXEC_COMPLETED;
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++ cmd->completed = 1;
++ } else {
++ list_for_each_entry(tgt_dev_tmp,
++ &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ clear_bit(SCST_TGT_DEV_RESERVED,
++ &tgt_dev_tmp->tgt_dev_flags);
++ }
++ dev->dev_reserved = 0;
++ }
++
++ spin_unlock_bh(&dev->dev_lock);
++
++ if (res == SCST_EXEC_COMPLETED)
++ goto out_done;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_completed:
++ cmd->completed = 1;
++
++out_done:
++ res = SCST_EXEC_COMPLETED;
++ /* Report the result */
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++ goto out;
++}
++
++/**
++ * scst_check_local_events() - check if there are any local SCSI events
++ *
++ * Description:
++ * Checks if the command can be executed or there are local events,
++ * like reservatons, pending UAs, etc. Returns < 0 if command must be
++ * aborted, > 0 if there is an event and command should be immediately
++ * completed, or 0 otherwise.
++ *
++ * !! Dev handlers implementing exec() callback must call this function there
++ * !! just before the actual command's execution!
++ *
++ * On call no locks, no IRQ or IRQ-disabled context allowed.
++ */
++static int scst_persistent_reserve_in_local(struct scst_cmd *cmd)
++{
++ int rc;
++ struct scst_device *dev;
++ struct scst_tgt_dev *tgt_dev;
++ struct scst_session *session;
++ int action;
++ uint8_t *buffer;
++ int buffer_size;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(scst_cmd_atomic(cmd));
++
++ dev = cmd->dev;
++ tgt_dev = cmd->tgt_dev;
++ session = cmd->sess;
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ if (unlikely(dev->not_pr_supporting_tgt_devs_num != 0)) {
++ PRINT_WARNING("Persistent Reservation command %x refused for "
++ "device %s, because the device has not supporting PR "
++ "transports connected", cmd->cdb[0], dev->virt_name);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ goto out_done;
++ }
++
++ if (dev->dev_reserved) {
++ TRACE_PR("PR command rejected, because device %s holds regular "
++ "reservation", dev->virt_name);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out_done;
++ }
++
++ if (dev->scsi_dev != NULL) {
++ PRINT_WARNING("PR commands for pass-through devices not "
++ "supported (device %s)", dev->virt_name);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ goto out_done;
++ }
++
++ buffer_size = scst_get_full_buf(cmd, &buffer);
++ if (unlikely(buffer_size <= 0)) {
++ if (buffer_size < 0)
++ scst_set_busy(cmd);
++ goto out_done;
++ }
++
++ scst_pr_write_lock(dev);
++
++ /* We can be aborted by another PR command while waiting for the lock */
++ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
++ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd);
++ goto out_unlock;
++ }
++
++ action = cmd->cdb[1] & 0x1f;
++
++ TRACE(TRACE_SCSI, "PR action %x for '%s' (LUN %llx) from '%s'", action,
++ dev->virt_name, tgt_dev->lun, session->initiator_name);
++
++ switch (action) {
++ case PR_READ_KEYS:
++ scst_pr_read_keys(cmd, buffer, buffer_size);
++ break;
++ case PR_READ_RESERVATION:
++ scst_pr_read_reservation(cmd, buffer, buffer_size);
++ break;
++ case PR_REPORT_CAPS:
++ scst_pr_report_caps(cmd, buffer, buffer_size);
++ break;
++ case PR_READ_FULL_STATUS:
++ scst_pr_read_full_status(cmd, buffer, buffer_size);
++ break;
++ default:
++ PRINT_ERROR("Unsupported action %x", action);
++ scst_pr_write_unlock(dev);
++ goto out_err;
++ }
++
++out_complete:
++ cmd->completed = 1;
++
++out_unlock:
++ scst_pr_write_unlock(dev);
++
++ scst_put_full_buf(cmd, buffer);
++
++out_done:
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++
++ TRACE_EXIT_RES(SCST_EXEC_COMPLETED);
++ return SCST_EXEC_COMPLETED;
++
++out_err:
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_complete;
++}
++
++/* No locks, no IRQ or IRQ-disabled context allowed */
++static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_COMPLETED;
++ int rc;
++ struct scst_device *dev;
++ struct scst_tgt_dev *tgt_dev;
++ struct scst_session *session;
++ int action;
++ uint8_t *buffer;
++ int buffer_size;
++ bool aborted = false;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(scst_cmd_atomic(cmd));
++
++ dev = cmd->dev;
++ tgt_dev = cmd->tgt_dev;
++ session = cmd->sess;
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ if (unlikely(dev->not_pr_supporting_tgt_devs_num != 0)) {
++ PRINT_WARNING("Persistent Reservation command %x refused for "
++ "device %s, because the device has not supporting PR "
++ "transports connected", cmd->cdb[0], dev->virt_name);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ goto out_done;
++ }
++
++ action = cmd->cdb[1] & 0x1f;
++
++ TRACE(TRACE_SCSI, "PR action %x for '%s' (LUN %llx) from '%s'", action,
++ dev->virt_name, tgt_dev->lun, session->initiator_name);
++
++ if (dev->dev_reserved) {
++ TRACE_PR("PR command rejected, because device %s holds regular "
++ "reservation", dev->virt_name);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out_done;
++ }
++
++ /*
++ * Check if tgt_dev already registered. Also by this check we make
++ * sure that table "PERSISTENT RESERVE OUT service actions that are
++ * allowed in the presence of various reservations" is honored.
++ * REGISTER AND MOVE and RESERVE will be additionally checked for
++ * conflicts later.
++ */
++ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
++ (tgt_dev->registrant == NULL)) {
++ TRACE_PR("'%s' not registered", cmd->sess->initiator_name);
++ scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
++ goto out_done;
++ }
++
++ buffer_size = scst_get_full_buf(cmd, &buffer);
++ if (unlikely(buffer_size <= 0)) {
++ if (buffer_size < 0)
++ scst_set_busy(cmd);
++ goto out_done;
++ }
++
++ /* Check scope */
++ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
++ (action != PR_CLEAR) && ((cmd->cdb[2] & 0x0f) >> 4) != SCOPE_LU) {
++ TRACE_PR("Scope must be SCOPE_LU for action %x", action);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_put_full_buf;
++ }
++
++ /* Check SPEC_I_PT (PR_REGISTER_AND_MOVE has another format) */
++ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_MOVE) &&
++ ((buffer[20] >> 3) & 0x01)) {
++ TRACE_PR("SPEC_I_PT must be zero for action %x", action);
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_invalid_field_in_cdb));
++ goto out_put_full_buf;
++ }
++
++ /* Check ALL_TG_PT (PR_REGISTER_AND_MOVE has another format) */
++ if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
++ (action != PR_REGISTER_AND_MOVE) && ((buffer[20] >> 2) & 0x01)) {
++ TRACE_PR("ALL_TG_PT must be zero for action %x", action);
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_invalid_field_in_cdb));
++ goto out_put_full_buf;
++ }
++
++ scst_pr_write_lock(dev);
++
++ /* We can be aborted by another PR command while waiting for the lock */
++ aborted = test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
++ if (unlikely(aborted)) {
++ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd);
++ goto out_unlock;
++ }
++
++ switch (action) {
++ case PR_REGISTER:
++ scst_pr_register(cmd, buffer, buffer_size);
++ break;
++ case PR_RESERVE:
++ scst_pr_reserve(cmd, buffer, buffer_size);
++ break;
++ case PR_RELEASE:
++ scst_pr_release(cmd, buffer, buffer_size);
++ break;
++ case PR_CLEAR:
++ scst_pr_clear(cmd, buffer, buffer_size);
++ break;
++ case PR_PREEMPT:
++ scst_pr_preempt(cmd, buffer, buffer_size);
++ break;
++ case PR_PREEMPT_AND_ABORT:
++ scst_pr_preempt_and_abort(cmd, buffer, buffer_size);
++ break;
++ case PR_REGISTER_AND_IGNORE:
++ scst_pr_register_and_ignore(cmd, buffer, buffer_size);
++ break;
++ case PR_REGISTER_AND_MOVE:
++ scst_pr_register_and_move(cmd, buffer, buffer_size);
++ break;
++ default:
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_unlock;
++ }
++
++ if (cmd->status == SAM_STAT_GOOD)
++ scst_pr_sync_device_file(tgt_dev, cmd);
++
++ if ((dev->handler->pr_cmds_notifications) &&
++ (cmd->status == SAM_STAT_GOOD)) /* sync file may change status */
++ res = SCST_EXEC_NOT_COMPLETED;
++
++out_unlock:
++ scst_pr_write_unlock(dev);
++
++out_put_full_buf:
++ scst_put_full_buf(cmd, buffer);
++
++out_done:
++ if (SCST_EXEC_COMPLETED == res) {
++ if (!aborted)
++ cmd->completed = 1;
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT,
++ SCST_CONTEXT_SAME);
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* No locks, no IRQ or IRQ-disabled context allowed */
++int scst_check_local_events(struct scst_cmd *cmd)
++{
++ int res, rc;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_device *dev = cmd->dev;
++
++ TRACE_ENTRY();
++
++ /*
++ * There's no race here, because we need to trace commands sent
++ * *after* dev_double_ua_possible flag was set.
++ */
++ if (unlikely(dev->dev_double_ua_possible))
++ cmd->double_ua_possible = 1;
++
++ /* Reserve check before Unit Attention */
++ if (unlikely(test_bit(SCST_TGT_DEV_RESERVED,
++ &tgt_dev->tgt_dev_flags))) {
++ if ((cmd->op_flags & SCST_REG_RESERVE_ALLOWED) == 0) {
++ scst_set_cmd_error_status(cmd,
++ SAM_STAT_RESERVATION_CONFLICT);
++ goto out_complete;
++ }
++ }
++
++ if (dev->pr_is_set) {
++ if (unlikely(!scst_pr_is_cmd_allowed(cmd))) {
++ scst_set_cmd_error_status(cmd,
++ SAM_STAT_RESERVATION_CONFLICT);
++ goto out_complete;
++ }
++ }
++
++ /*
++ * Let's check for ABORTED after scst_pr_is_cmd_allowed(), because
++ * we might sleep for a while there.
++ */
++ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
++ TRACE_MGMT_DBG("ABORTED set, aborting cmd %p", cmd);
++ goto out_uncomplete;
++ }
++
++ /* If we had internal bus reset, set the command error unit attention */
++ if ((dev->scsi_dev != NULL) &&
++ unlikely(dev->scsi_dev->was_reset)) {
++ if (scst_is_ua_command(cmd)) {
++ int done = 0;
++ /*
++ * Prevent more than 1 cmd to be triggered by
++ * was_reset.
++ */
++ spin_lock_bh(&dev->dev_lock);
++ if (dev->scsi_dev->was_reset) {
++ TRACE(TRACE_MGMT, "was_reset is %d", 1);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_reset_UA));
++ /*
++ * It looks like it is safe to clear was_reset
++ * here.
++ */
++ dev->scsi_dev->was_reset = 0;
++ done = 1;
++ }
++ spin_unlock_bh(&dev->dev_lock);
++
++ if (done)
++ goto out_complete;
++ }
++ }
++
++ if (unlikely(test_bit(SCST_TGT_DEV_UA_PENDING,
++ &cmd->tgt_dev->tgt_dev_flags))) {
++ if (scst_is_ua_command(cmd)) {
++ rc = scst_set_pending_UA(cmd);
++ if (rc == 0)
++ goto out_complete;
++ }
++ }
++
++ res = 0;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_complete:
++ res = 1;
++ BUG_ON(!cmd->completed);
++ goto out;
++
++out_uncomplete:
++ res = -1;
++ goto out;
++}
++EXPORT_SYMBOL_GPL(scst_check_local_events);
++
++/* No locks */
++void scst_inc_expected_sn(struct scst_tgt_dev *tgt_dev, atomic_t *slot)
++{
++ if (slot == NULL)
++ goto inc;
++
++ /* Optimized for lockless fast path */
++
++ TRACE_SN("Slot %zd, *cur_sn_slot %d", slot - tgt_dev->sn_slots,
++ atomic_read(slot));
++
++ if (!atomic_dec_and_test(slot))
++ goto out;
++
++ TRACE_SN("Slot is 0 (num_free_sn_slots=%d)",
++ tgt_dev->num_free_sn_slots);
++ if (tgt_dev->num_free_sn_slots < (int)ARRAY_SIZE(tgt_dev->sn_slots)-1) {
++ spin_lock_irq(&tgt_dev->sn_lock);
++ if (likely(tgt_dev->num_free_sn_slots < (int)ARRAY_SIZE(tgt_dev->sn_slots)-1)) {
++ if (tgt_dev->num_free_sn_slots < 0)
++ tgt_dev->cur_sn_slot = slot;
++ /*
++ * To be in-sync with SIMPLE case in scst_cmd_set_sn()
++ */
++ smp_mb();
++ tgt_dev->num_free_sn_slots++;
++ TRACE_SN("Incremented num_free_sn_slots (%d)",
++ tgt_dev->num_free_sn_slots);
++
++ }
++ spin_unlock_irq(&tgt_dev->sn_lock);
++ }
++
++inc:
++ /*
++ * No protection of expected_sn is needed, because only one thread
++ * at time can be here (serialized by sn). Also it is supposed that
++ * there could not be half-incremented halves.
++ */
++ tgt_dev->expected_sn++;
++ /*
++ * Write must be before def_cmd_count read to be in sync. with
++ * scst_post_exec_sn(). See comment in scst_send_for_exec().
++ */
++ smp_mb();
++ TRACE_SN("Next expected_sn: %d", tgt_dev->expected_sn);
++
++out:
++ return;
++}
++
++/* No locks */
++static struct scst_cmd *scst_post_exec_sn(struct scst_cmd *cmd,
++ bool make_active)
++{
++ /* For HQ commands SN is not set */
++ bool inc_expected_sn = !cmd->inc_expected_sn_on_done &&
++ cmd->sn_set && !cmd->retry;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_cmd *res;
++
++ TRACE_ENTRY();
++
++ if (inc_expected_sn)
++ scst_inc_expected_sn(tgt_dev, cmd->sn_slot);
++
++ if (make_active) {
++ scst_make_deferred_commands_active(tgt_dev);
++ res = NULL;
++ } else
++ res = scst_check_deferred_commands(tgt_dev);
++
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/* cmd must be additionally referenced to not die inside */
++static int scst_do_real_exec(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_NOT_COMPLETED;
++ int rc;
++ struct scst_device *dev = cmd->dev;
++ struct scst_dev_type *handler = dev->handler;
++ struct io_context *old_ctx = NULL;
++ bool ctx_changed = false;
++
++ TRACE_ENTRY();
++
++ ctx_changed = scst_set_io_context(cmd, &old_ctx);
++
++ cmd->state = SCST_CMD_STATE_REAL_EXECUTING;
++
++ if (handler->exec) {
++ TRACE_DBG("Calling dev handler %s exec(%p)",
++ handler->name, cmd);
++ TRACE_BUFF_FLAG(TRACE_SND_TOP, "Execing: ", cmd->cdb,
++ cmd->cdb_len);
++ scst_set_cur_start(cmd);
++ res = handler->exec(cmd);
++ TRACE_DBG("Dev handler %s exec() returned %d",
++ handler->name, res);
++
++ if (res == SCST_EXEC_COMPLETED)
++ goto out_complete;
++
++ scst_set_exec_time(cmd);
++
++ BUG_ON(res != SCST_EXEC_NOT_COMPLETED);
++ }
++
++ TRACE_DBG("Sending cmd %p to SCSI mid-level", cmd);
++
++ if (unlikely(dev->scsi_dev == NULL)) {
++ PRINT_ERROR("Command for virtual device must be "
++ "processed by device handler (LUN %lld)!",
++ (long long unsigned int)cmd->lun);
++ goto out_error;
++ }
++
++ res = scst_check_local_events(cmd);
++ if (unlikely(res != 0))
++ goto out_done;
++
++ scst_set_cur_start(cmd);
++
++ rc = scst_scsi_exec_async(cmd, scst_cmd_done);
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("scst pass-through exec failed: %x", rc);
++ if ((int)rc == -EINVAL)
++ PRINT_ERROR("Do you have too low max_sectors on your "
++ "backend hardware? For success max_sectors must "
++ "be >= bufflen in sectors (max_sectors %d, "
++ "bufflen %db, CDB %x). See README for more "
++ "details.", dev->scsi_dev->host->max_sectors,
++ cmd->bufflen, cmd->cdb[0]);
++ goto out_error;
++ }
++
++out_complete:
++ res = SCST_EXEC_COMPLETED;
++
++ if (ctx_changed)
++ scst_reset_io_context(cmd->tgt_dev, old_ctx);
++
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_error:
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_done;
++
++out_done:
++ res = SCST_EXEC_COMPLETED;
++ /* Report the result */
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++ goto out_complete;
++}
++
++static inline int scst_real_exec(struct scst_cmd *cmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_SAME != SCST_EXEC_NOT_COMPLETED);
++ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_NEXT != SCST_EXEC_COMPLETED);
++
++ __scst_cmd_get(cmd);
++
++ res = scst_do_real_exec(cmd);
++ if (likely(res == SCST_EXEC_COMPLETED)) {
++ scst_post_exec_sn(cmd, true);
++ if (cmd->dev->scsi_dev != NULL)
++ generic_unplug_device(
++ cmd->dev->scsi_dev->request_queue);
++ } else
++ BUG();
++
++ __scst_cmd_put(cmd);
++
++ /* SCST_EXEC_* match SCST_CMD_STATE_RES_* */
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_do_local_exec(struct scst_cmd *cmd)
++{
++ int res;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++
++ TRACE_ENTRY();
++
++ /* Check READ_ONLY device status */
++ if ((cmd->op_flags & SCST_WRITE_MEDIUM) &&
++ (tgt_dev->acg_dev->rd_only || cmd->dev->swp ||
++ cmd->dev->rd_only)) {
++ PRINT_WARNING("Attempt of write access to read-only device: "
++ "initiator %s, LUN %lld, op %x",
++ cmd->sess->initiator_name, cmd->lun, cmd->cdb[0]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_data_protect));
++ goto out_done;
++ }
++
++ if (!scst_is_cmd_local(cmd)) {
++ res = SCST_EXEC_NOT_COMPLETED;
++ goto out;
++ }
++
++ switch (cmd->cdb[0]) {
++ case RESERVE:
++ case RESERVE_10:
++ res = scst_reserve_local(cmd);
++ break;
++ case RELEASE:
++ case RELEASE_10:
++ res = scst_release_local(cmd);
++ break;
++ case PERSISTENT_RESERVE_IN:
++ res = scst_persistent_reserve_in_local(cmd);
++ break;
++ case PERSISTENT_RESERVE_OUT:
++ res = scst_persistent_reserve_out_local(cmd);
++ break;
++ case REPORT_LUNS:
++ res = scst_report_luns_local(cmd);
++ break;
++ case REQUEST_SENSE:
++ res = scst_request_sense_local(cmd);
++ break;
++ default:
++ res = SCST_EXEC_NOT_COMPLETED;
++ break;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_done:
++ /* Report the result */
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++ res = SCST_EXEC_COMPLETED;
++ goto out;
++}
++
++static int scst_local_exec(struct scst_cmd *cmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_SAME != SCST_EXEC_NOT_COMPLETED);
++ BUILD_BUG_ON(SCST_CMD_STATE_RES_CONT_NEXT != SCST_EXEC_COMPLETED);
++
++ __scst_cmd_get(cmd);
++
++ res = scst_do_local_exec(cmd);
++ if (likely(res == SCST_EXEC_NOT_COMPLETED))
++ cmd->state = SCST_CMD_STATE_REAL_EXEC;
++ else if (res == SCST_EXEC_COMPLETED)
++ scst_post_exec_sn(cmd, true);
++ else
++ BUG();
++
++ __scst_cmd_put(cmd);
++
++ /* SCST_EXEC_* match SCST_CMD_STATE_RES_* */
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_exec(struct scst_cmd **active_cmd)
++{
++ struct scst_cmd *cmd = *active_cmd;
++ struct scst_cmd *ref_cmd;
++ struct scst_device *dev = cmd->dev;
++ int res = SCST_CMD_STATE_RES_CONT_NEXT, count;
++
++ TRACE_ENTRY();
++
++ if (unlikely(scst_check_blocked_dev(cmd)))
++ goto out;
++
++ /* To protect tgt_dev */
++ ref_cmd = cmd;
++ __scst_cmd_get(ref_cmd);
++
++ count = 0;
++ while (1) {
++ int rc;
++
++ cmd->sent_for_exec = 1;
++ /*
++ * To sync with scst_abort_cmd(). The above assignment must
++ * be before SCST_CMD_ABORTED test, done later in
++ * scst_check_local_events(). It's far from here, so the order
++ * is virtually guaranteed, but let's have it just in case.
++ */
++ smp_mb();
++
++ cmd->scst_cmd_done = scst_cmd_done_local;
++ cmd->state = SCST_CMD_STATE_LOCAL_EXEC;
++
++ rc = scst_do_local_exec(cmd);
++ if (likely(rc == SCST_EXEC_NOT_COMPLETED))
++ /* Nothing to do */;
++ else {
++ BUG_ON(rc != SCST_EXEC_COMPLETED);
++ goto done;
++ }
++
++ cmd->state = SCST_CMD_STATE_REAL_EXEC;
++
++ rc = scst_do_real_exec(cmd);
++ BUG_ON(rc != SCST_EXEC_COMPLETED);
++
++done:
++ count++;
++
++ cmd = scst_post_exec_sn(cmd, false);
++ if (cmd == NULL)
++ break;
++
++ if (unlikely(scst_check_blocked_dev(cmd)))
++ break;
++
++ __scst_cmd_put(ref_cmd);
++ ref_cmd = cmd;
++ __scst_cmd_get(ref_cmd);
++ }
++
++ *active_cmd = cmd;
++
++ if (count == 0)
++ goto out_put;
++
++ if (dev->scsi_dev != NULL)
++ generic_unplug_device(dev->scsi_dev->request_queue);
++
++out_put:
++ __scst_cmd_put(ref_cmd);
++ /* !! At this point sess, dev and tgt_dev can be already freed !! */
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_send_for_exec(struct scst_cmd **active_cmd)
++{
++ int res;
++ struct scst_cmd *cmd = *active_cmd;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ typeof(tgt_dev->expected_sn) expected_sn;
++
++ TRACE_ENTRY();
++
++ if (unlikely(cmd->internal))
++ goto exec;
++
++ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
++ goto exec;
++
++ BUG_ON(!cmd->sn_set);
++
++ expected_sn = tgt_dev->expected_sn;
++ /* Optimized for lockless fast path */
++ if ((cmd->sn != expected_sn) || (tgt_dev->hq_cmd_count > 0)) {
++ spin_lock_irq(&tgt_dev->sn_lock);
++
++ tgt_dev->def_cmd_count++;
++ /*
++ * Memory barrier is needed here to implement lockless fast
++ * path. We need the exact order of read and write between
++ * def_cmd_count and expected_sn. Otherwise, we can miss case,
++ * when expected_sn was changed to be equal to cmd->sn while
++ * we are queuing cmd the deferred list after the expected_sn
++ * below. It will lead to a forever stuck command. But with
++ * the barrier in such case __scst_check_deferred_commands()
++ * will be called and it will take sn_lock, so we will be
++ * synchronized.
++ */
++ smp_mb();
++
++ expected_sn = tgt_dev->expected_sn;
++ if ((cmd->sn != expected_sn) || (tgt_dev->hq_cmd_count > 0)) {
++ if (unlikely(test_bit(SCST_CMD_ABORTED,
++ &cmd->cmd_flags))) {
++ /* Necessary to allow aborting out of sn cmds */
++ TRACE_MGMT_DBG("Aborting out of sn cmd %p "
++ "(tag %llu, sn %u)", cmd,
++ (long long unsigned)cmd->tag, cmd->sn);
++ tgt_dev->def_cmd_count--;
++ scst_set_cmd_abnormal_done_state(cmd);
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++ } else {
++ TRACE_SN("Deferring cmd %p (sn=%d, set %d, "
++ "expected_sn=%d)", cmd, cmd->sn,
++ cmd->sn_set, expected_sn);
++ list_add_tail(&cmd->sn_cmd_list_entry,
++ &tgt_dev->deferred_cmd_list);
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ }
++ spin_unlock_irq(&tgt_dev->sn_lock);
++ goto out;
++ } else {
++ TRACE_SN("Somebody incremented expected_sn %d, "
++ "continuing", expected_sn);
++ tgt_dev->def_cmd_count--;
++ spin_unlock_irq(&tgt_dev->sn_lock);
++ }
++ }
++
++exec:
++ res = scst_exec(active_cmd);
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/* No locks supposed to be held */
++static int scst_check_sense(struct scst_cmd *cmd)
++{
++ int res = 0;
++ struct scst_device *dev = cmd->dev;
++
++ TRACE_ENTRY();
++
++ if (unlikely(cmd->ua_ignore))
++ goto out;
++
++ /* If we had internal bus reset behind us, set the command error UA */
++ if ((dev->scsi_dev != NULL) &&
++ unlikely(cmd->host_status == DID_RESET) &&
++ scst_is_ua_command(cmd)) {
++ TRACE(TRACE_MGMT, "DID_RESET: was_reset=%d host_status=%x",
++ dev->scsi_dev->was_reset, cmd->host_status);
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_reset_UA));
++ /* It looks like it is safe to clear was_reset here */
++ dev->scsi_dev->was_reset = 0;
++ }
++
++ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
++ SCST_SENSE_VALID(cmd->sense)) {
++ PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense,
++ cmd->sense_valid_len);
++
++ /* Check Unit Attention Sense Key */
++ if (scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) {
++ if (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
++ SCST_SENSE_ASC_VALID,
++ 0, SCST_SENSE_ASC_UA_RESET, 0)) {
++ if (cmd->double_ua_possible) {
++ TRACE_MGMT_DBG("Double UA "
++ "detected for device %p", dev);
++ TRACE_MGMT_DBG("Retrying cmd"
++ " %p (tag %llu)", cmd,
++ (long long unsigned)cmd->tag);
++
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++ cmd->completed = 0;
++
++ mempool_free(cmd->sense,
++ scst_sense_mempool);
++ cmd->sense = NULL;
++
++ scst_check_restore_sg_buff(cmd);
++
++ BUG_ON(cmd->dbl_ua_orig_resp_data_len < 0);
++ cmd->data_direction =
++ cmd->dbl_ua_orig_data_direction;
++ cmd->resp_data_len =
++ cmd->dbl_ua_orig_resp_data_len;
++
++ cmd->state = SCST_CMD_STATE_REAL_EXEC;
++ cmd->retry = 1;
++ res = 1;
++ goto out;
++ }
++ }
++ scst_dev_check_set_UA(dev, cmd, cmd->sense,
++ cmd->sense_valid_len);
++ }
++ }
++
++ if (unlikely(cmd->double_ua_possible)) {
++ if (scst_is_ua_command(cmd)) {
++ TRACE_MGMT_DBG("Clearing dbl_ua_possible flag (dev %p, "
++ "cmd %p)", dev, cmd);
++ /*
++ * Lock used to protect other flags in the bitfield
++ * (just in case, actually). Those flags can't be
++ * changed in parallel, because the device is
++ * serialized.
++ */
++ spin_lock_bh(&dev->dev_lock);
++ dev->dev_double_ua_possible = 0;
++ spin_unlock_bh(&dev->dev_lock);
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_check_auto_sense(struct scst_cmd *cmd)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
++ (!SCST_SENSE_VALID(cmd->sense) ||
++ SCST_NO_SENSE(cmd->sense))) {
++ TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "CHECK_CONDITION, "
++ "but no sense: cmd->status=%x, cmd->msg_status=%x, "
++ "cmd->host_status=%x, cmd->driver_status=%x (cmd %p)",
++ cmd->status, cmd->msg_status, cmd->host_status,
++ cmd->driver_status, cmd);
++ res = 1;
++ } else if (unlikely(cmd->host_status)) {
++ if ((cmd->host_status == DID_REQUEUE) ||
++ (cmd->host_status == DID_IMM_RETRY) ||
++ (cmd->host_status == DID_SOFT_ERROR) ||
++ (cmd->host_status == DID_ABORT)) {
++ scst_set_busy(cmd);
++ } else {
++ TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "Host "
++ "status %x received, returning HARDWARE ERROR "
++ "instead (cmd %p)", cmd->host_status, cmd);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_pre_dev_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_RES_CONT_SAME, rc;
++
++ TRACE_ENTRY();
++
++ if (unlikely(scst_check_auto_sense(cmd))) {
++ PRINT_INFO("Command finished with CHECK CONDITION, but "
++ "without sense data (opcode 0x%x), issuing "
++ "REQUEST SENSE", cmd->cdb[0]);
++ rc = scst_prepare_request_sense(cmd);
++ if (rc == 0)
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ else {
++ PRINT_ERROR("%s", "Unable to issue REQUEST SENSE, "
++ "returning HARDWARE ERROR");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ goto out;
++ } else if (unlikely(scst_check_sense(cmd))) {
++ /*
++ * We can't allow atomic command on the exec stages, so
++ * restart to the thread
++ */
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++
++ if (likely(scsi_status_is_good(cmd->status))) {
++ unsigned char type = cmd->dev->type;
++ if (unlikely((cmd->cdb[0] == MODE_SENSE ||
++ cmd->cdb[0] == MODE_SENSE_10)) &&
++ (cmd->tgt_dev->acg_dev->rd_only || cmd->dev->swp ||
++ cmd->dev->rd_only) &&
++ (type == TYPE_DISK ||
++ type == TYPE_WORM ||
++ type == TYPE_MOD ||
++ type == TYPE_TAPE)) {
++ int32_t length;
++ uint8_t *address;
++ bool err = false;
++
++ length = scst_get_buf_first(cmd, &address);
++ if (length < 0) {
++ PRINT_ERROR("%s", "Unable to get "
++ "MODE_SENSE buffer");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(
++ scst_sense_hardw_error));
++ err = true;
++ } else if (length > 2 && cmd->cdb[0] == MODE_SENSE)
++ address[2] |= 0x80; /* Write Protect*/
++ else if (length > 3 && cmd->cdb[0] == MODE_SENSE_10)
++ address[3] |= 0x80; /* Write Protect*/
++ scst_put_buf(cmd, address);
++
++ if (err)
++ goto out;
++ }
++
++ /*
++ * Check and clear NormACA option for the device, if necessary,
++ * since we don't support ACA
++ */
++ if (unlikely((cmd->cdb[0] == INQUIRY)) &&
++ /* Std INQUIRY data (no EVPD) */
++ !(cmd->cdb[1] & SCST_INQ_EVPD) &&
++ (cmd->resp_data_len > SCST_INQ_BYTE3)) {
++ uint8_t *buffer;
++ int buflen;
++ bool err = false;
++
++ /* ToDo: all pages ?? */
++ buflen = scst_get_buf_first(cmd, &buffer);
++ if (buflen > SCST_INQ_BYTE3) {
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (buffer[SCST_INQ_BYTE3] & SCST_INQ_NORMACA_BIT) {
++ PRINT_INFO("NormACA set for device: "
++ "lun=%lld, type 0x%02x. Clear it, "
++ "since it's unsupported.",
++ (long long unsigned int)cmd->lun,
++ buffer[0]);
++ }
++#endif
++ buffer[SCST_INQ_BYTE3] &= ~SCST_INQ_NORMACA_BIT;
++ } else if (buflen != 0) {
++ PRINT_ERROR("%s", "Unable to get INQUIRY "
++ "buffer");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ err = true;
++ }
++ if (buflen > 0)
++ scst_put_buf(cmd, buffer);
++
++ if (err)
++ goto out;
++ }
++
++ if (unlikely((cmd->cdb[0] == MODE_SELECT) ||
++ (cmd->cdb[0] == MODE_SELECT_10) ||
++ (cmd->cdb[0] == LOG_SELECT))) {
++ TRACE(TRACE_SCSI,
++ "MODE/LOG SELECT succeeded (LUN %lld)",
++ (long long unsigned int)cmd->lun);
++ cmd->state = SCST_CMD_STATE_MODE_SELECT_CHECKS;
++ goto out;
++ }
++ } else {
++ TRACE(TRACE_SCSI, "cmd %p not succeeded with status %x",
++ cmd, cmd->status);
++
++ if ((cmd->cdb[0] == RESERVE) || (cmd->cdb[0] == RESERVE_10)) {
++ if (!test_bit(SCST_TGT_DEV_RESERVED,
++ &cmd->tgt_dev->tgt_dev_flags)) {
++ struct scst_tgt_dev *tgt_dev_tmp;
++ struct scst_device *dev = cmd->dev;
++
++ TRACE(TRACE_SCSI, "RESERVE failed lun=%lld, "
++ "status=%x",
++ (long long unsigned int)cmd->lun,
++ cmd->status);
++ PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense,
++ cmd->sense_valid_len);
++
++ /* Clearing the reservation */
++ spin_lock_bh(&dev->dev_lock);
++ list_for_each_entry(tgt_dev_tmp,
++ &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ clear_bit(SCST_TGT_DEV_RESERVED,
++ &tgt_dev_tmp->tgt_dev_flags);
++ }
++ dev->dev_reserved = 0;
++ spin_unlock_bh(&dev->dev_lock);
++ }
++ }
++
++ /* Check for MODE PARAMETERS CHANGED UA */
++ if ((cmd->dev->scsi_dev != NULL) &&
++ (cmd->status == SAM_STAT_CHECK_CONDITION) &&
++ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) &&
++ scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
++ SCST_SENSE_ASCx_VALID,
++ 0, 0x2a, 0x01)) {
++ TRACE(TRACE_SCSI, "MODE PARAMETERS CHANGED UA (lun "
++ "%lld)", (long long unsigned int)cmd->lun);
++ cmd->state = SCST_CMD_STATE_MODE_SELECT_CHECKS;
++ goto out;
++ }
++ }
++
++ cmd->state = SCST_CMD_STATE_DEV_DONE;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_mode_select_checks(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_RES_CONT_SAME;
++
++ TRACE_ENTRY();
++
++ if (likely(scsi_status_is_good(cmd->status))) {
++ int atomic = scst_cmd_atomic(cmd);
++ if (unlikely((cmd->cdb[0] == MODE_SELECT) ||
++ (cmd->cdb[0] == MODE_SELECT_10) ||
++ (cmd->cdb[0] == LOG_SELECT))) {
++ struct scst_device *dev = cmd->dev;
++ int sl;
++ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
++
++ if (atomic && (dev->scsi_dev != NULL)) {
++ TRACE_DBG("%s", "MODE/LOG SELECT: thread "
++ "context required");
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++
++ TRACE(TRACE_SCSI, "MODE/LOG SELECT succeeded, "
++ "setting the SELECT UA (lun=%lld)",
++ (long long unsigned int)cmd->lun);
++
++ spin_lock_bh(&dev->dev_lock);
++ if (cmd->cdb[0] == LOG_SELECT) {
++ sl = scst_set_sense(sense_buffer,
++ sizeof(sense_buffer),
++ dev->d_sense,
++ UNIT_ATTENTION, 0x2a, 0x02);
++ } else {
++ sl = scst_set_sense(sense_buffer,
++ sizeof(sense_buffer),
++ dev->d_sense,
++ UNIT_ATTENTION, 0x2a, 0x01);
++ }
++ scst_dev_check_set_local_UA(dev, cmd, sense_buffer, sl);
++ spin_unlock_bh(&dev->dev_lock);
++
++ if (dev->scsi_dev != NULL)
++ scst_obtain_device_parameters(dev);
++ }
++ } else if ((cmd->status == SAM_STAT_CHECK_CONDITION) &&
++ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len) &&
++ /* mode parameters changed */
++ (scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
++ SCST_SENSE_ASCx_VALID,
++ 0, 0x2a, 0x01) ||
++ scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
++ SCST_SENSE_ASC_VALID,
++ 0, 0x29, 0) /* reset */ ||
++ scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
++ SCST_SENSE_ASC_VALID,
++ 0, 0x28, 0) /* medium changed */ ||
++ /* cleared by another ini (just in case) */
++ scst_analyze_sense(cmd->sense, cmd->sense_valid_len,
++ SCST_SENSE_ASC_VALID,
++ 0, 0x2F, 0))) {
++ int atomic = scst_cmd_atomic(cmd);
++ if (atomic) {
++ TRACE_DBG("Possible parameters changed UA %x: "
++ "thread context required", cmd->sense[12]);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++
++ TRACE(TRACE_SCSI, "Possible parameters changed UA %x "
++ "(LUN %lld): getting new parameters", cmd->sense[12],
++ (long long unsigned int)cmd->lun);
++
++ scst_obtain_device_parameters(cmd->dev);
++ } else
++ BUG();
++
++ cmd->state = SCST_CMD_STATE_DEV_DONE;
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++static void scst_inc_check_expected_sn(struct scst_cmd *cmd)
++{
++ if (likely(cmd->sn_set))
++ scst_inc_expected_sn(cmd->tgt_dev, cmd->sn_slot);
++
++ scst_make_deferred_commands_active(cmd->tgt_dev);
++}
++
++static int scst_dev_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_RES_CONT_SAME;
++ int state;
++ struct scst_device *dev = cmd->dev;
++
++ TRACE_ENTRY();
++
++ state = SCST_CMD_STATE_PRE_XMIT_RESP;
++
++ if (likely(!scst_is_cmd_fully_local(cmd)) &&
++ likely(dev->handler->dev_done != NULL)) {
++ int rc;
++
++ if (unlikely(!dev->handler->dev_done_atomic &&
++ scst_cmd_atomic(cmd))) {
++ /*
++ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
++ * optimization.
++ */
++ TRACE_MGMT_DBG("Dev handler %s dev_done() needs thread "
++ "context, rescheduling", dev->handler->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++
++ TRACE_DBG("Calling dev handler %s dev_done(%p)",
++ dev->handler->name, cmd);
++ scst_set_cur_start(cmd);
++ rc = dev->handler->dev_done(cmd);
++ scst_set_dev_done_time(cmd);
++ TRACE_DBG("Dev handler %s dev_done() returned %d",
++ dev->handler->name, rc);
++ if (rc != SCST_CMD_STATE_DEFAULT)
++ state = rc;
++ }
++
++ switch (state) {
++#ifdef CONFIG_SCST_EXTRACHECKS
++ case SCST_CMD_STATE_PRE_XMIT_RESP:
++ case SCST_CMD_STATE_PARSE:
++ case SCST_CMD_STATE_PREPARE_SPACE:
++ case SCST_CMD_STATE_RDY_TO_XFER:
++ case SCST_CMD_STATE_TGT_PRE_EXEC:
++ case SCST_CMD_STATE_SEND_FOR_EXEC:
++ case SCST_CMD_STATE_LOCAL_EXEC:
++ case SCST_CMD_STATE_REAL_EXEC:
++ case SCST_CMD_STATE_PRE_DEV_DONE:
++ case SCST_CMD_STATE_MODE_SELECT_CHECKS:
++ case SCST_CMD_STATE_DEV_DONE:
++ case SCST_CMD_STATE_XMIT_RESP:
++ case SCST_CMD_STATE_FINISHED:
++ case SCST_CMD_STATE_FINISHED_INTERNAL:
++#else
++ default:
++#endif
++ cmd->state = state;
++ break;
++ case SCST_CMD_STATE_NEED_THREAD_CTX:
++ TRACE_DBG("Dev handler %s dev_done() requested "
++ "thread context, rescheduling",
++ dev->handler->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ break;
++#ifdef CONFIG_SCST_EXTRACHECKS
++ default:
++ if (state >= 0) {
++ PRINT_ERROR("Dev handler %s dev_done() returned "
++ "invalid cmd state %d",
++ dev->handler->name, state);
++ } else {
++ PRINT_ERROR("Dev handler %s dev_done() returned "
++ "error %d", dev->handler->name,
++ state);
++ }
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ scst_set_cmd_abnormal_done_state(cmd);
++ break;
++#endif
++ }
++
++ scst_check_unblock_dev(cmd);
++
++ if (cmd->inc_expected_sn_on_done && cmd->sent_for_exec)
++ scst_inc_check_expected_sn(cmd);
++
++ if (unlikely(cmd->internal))
++ cmd->state = SCST_CMD_STATE_FINISHED_INTERNAL;
++
++#ifndef CONFIG_SCST_TEST_IO_IN_SIRQ
++ if (cmd->state != SCST_CMD_STATE_PRE_XMIT_RESP) {
++ /* We can't allow atomic command on the exec stages */
++ if (scst_cmd_atomic(cmd)) {
++ switch (state) {
++ case SCST_CMD_STATE_TGT_PRE_EXEC:
++ case SCST_CMD_STATE_SEND_FOR_EXEC:
++ case SCST_CMD_STATE_LOCAL_EXEC:
++ case SCST_CMD_STATE_REAL_EXEC:
++ TRACE_DBG("Atomic context and redirect, "
++ "rescheduling (cmd %p)", cmd);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ break;
++ }
++ }
++ }
++#endif
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++static int scst_pre_xmit_response(struct scst_cmd *cmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(cmd->internal);
++
++#ifdef CONFIG_SCST_DEBUG_TM
++ if (cmd->tm_dbg_delayed &&
++ !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
++ if (scst_cmd_atomic(cmd)) {
++ TRACE_MGMT_DBG("%s",
++ "DEBUG_TM delayed cmd needs a thread");
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ return res;
++ }
++ TRACE_MGMT_DBG("Delaying cmd %p (tag %llu) for 1 second",
++ cmd, cmd->tag);
++ schedule_timeout_uninterruptible(HZ);
++ }
++#endif
++
++ if (likely(cmd->tgt_dev != NULL)) {
++ /*
++ * Those counters protect from not getting too long processing
++ * latency, so we should decrement them after cmd completed.
++ */
++ atomic_dec(&cmd->tgt_dev->tgt_dev_cmd_count);
++#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
++ atomic_dec(&cmd->dev->dev_cmd_count);
++#endif
++#ifdef CONFIG_SCST_ORDERED_READS
++ /* If expected values not set, expected direction is UNKNOWN */
++ if (cmd->expected_data_direction & SCST_DATA_WRITE)
++ atomic_dec(&cmd->dev->write_cmd_count);
++#endif
++ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
++ scst_on_hq_cmd_response(cmd);
++
++ if (unlikely(!cmd->sent_for_exec)) {
++ TRACE_SN("cmd %p was not sent to mid-lev"
++ " (sn %d, set %d)",
++ cmd, cmd->sn, cmd->sn_set);
++ scst_unblock_deferred(cmd->tgt_dev, cmd);
++ cmd->sent_for_exec = 1;
++ }
++ }
++
++ cmd->done = 1;
++ smp_mb(); /* to sync with scst_abort_cmd() */
++
++ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
++ scst_xmit_process_aborted_cmd(cmd);
++ else if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION))
++ scst_store_sense(cmd);
++
++ if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) {
++ TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %llu), "
++ "skipping", cmd, (long long unsigned int)cmd->tag);
++ cmd->state = SCST_CMD_STATE_FINISHED;
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++ goto out;
++ }
++
++ if (unlikely(cmd->resid_possible))
++ scst_adjust_resp_data_len(cmd);
++ else
++ cmd->adjusted_resp_data_len = cmd->resp_data_len;
++
++ cmd->state = SCST_CMD_STATE_XMIT_RESP;
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++static int scst_xmit_response(struct scst_cmd *cmd)
++{
++ struct scst_tgt_template *tgtt = cmd->tgtt;
++ int res, rc;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(cmd->internal);
++
++ if (unlikely(!tgtt->xmit_response_atomic &&
++ scst_cmd_atomic(cmd))) {
++ /*
++ * It shouldn't be because of the SCST_TGT_DEV_AFTER_*
++ * optimization.
++ */
++ TRACE_MGMT_DBG("Target driver %s xmit_response() needs thread "
++ "context, rescheduling", tgtt->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++
++ while (1) {
++ int finished_cmds = atomic_read(&cmd->tgt->finished_cmds);
++
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ cmd->state = SCST_CMD_STATE_XMIT_WAIT;
++
++ TRACE_DBG("Calling xmit_response(%p)", cmd);
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ if (trace_flag & TRACE_SND_BOT) {
++ int i;
++ struct scatterlist *sg;
++ if (cmd->tgt_sg != NULL)
++ sg = cmd->tgt_sg;
++ else
++ sg = cmd->sg;
++ if (sg != NULL) {
++ TRACE(TRACE_SND_BOT, "Xmitting data for cmd %p "
++ "(sg_cnt %d, sg %p, sg[0].page %p)",
++ cmd, cmd->tgt_sg_cnt, sg,
++ (void *)sg_page(&sg[0]));
++ for (i = 0; i < cmd->tgt_sg_cnt; ++i) {
++ PRINT_BUFF_FLAG(TRACE_SND_BOT,
++ "Xmitting sg", sg_virt(&sg[i]),
++ sg[i].length);
++ }
++ }
++ }
++#endif
++
++ if (tgtt->on_hw_pending_cmd_timeout != NULL) {
++ struct scst_session *sess = cmd->sess;
++ cmd->hw_pending_start = jiffies;
++ cmd->cmd_hw_pending = 1;
++ if (!test_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED, &sess->sess_aflags)) {
++ TRACE_DBG("Sched HW pending work for sess %p "
++ "(max time %d)", sess,
++ tgtt->max_hw_pending_time);
++ set_bit(SCST_SESS_HW_PENDING_WORK_SCHEDULED,
++ &sess->sess_aflags);
++ schedule_delayed_work(&sess->hw_pending_work,
++ tgtt->max_hw_pending_time * HZ);
++ }
++ }
++
++ scst_set_cur_start(cmd);
++
++#ifdef CONFIG_SCST_DEBUG_RETRY
++ if (((scst_random() % 100) == 77))
++ rc = SCST_TGT_RES_QUEUE_FULL;
++ else
++#endif
++ rc = tgtt->xmit_response(cmd);
++ TRACE_DBG("xmit_response() returned %d", rc);
++
++ if (likely(rc == SCST_TGT_RES_SUCCESS))
++ goto out;
++
++ scst_set_xmit_time(cmd);
++
++ cmd->cmd_hw_pending = 0;
++
++ /* Restore the previous state */
++ cmd->state = SCST_CMD_STATE_XMIT_RESP;
++
++ switch (rc) {
++ case SCST_TGT_RES_QUEUE_FULL:
++ if (scst_queue_retry_cmd(cmd, finished_cmds) == 0)
++ break;
++ else
++ continue;
++
++ case SCST_TGT_RES_NEED_THREAD_CTX:
++ TRACE_DBG("Target driver %s xmit_response() "
++ "requested thread context, rescheduling",
++ tgtt->name);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ break;
++
++ default:
++ goto out_error;
++ }
++ break;
++ }
++
++out:
++ /* Caution: cmd can be already dead here */
++ TRACE_EXIT_HRES(res);
++ return res;
++
++out_error:
++ if (rc == SCST_TGT_RES_FATAL_ERROR) {
++ PRINT_ERROR("Target driver %s xmit_response() returned "
++ "fatal error", tgtt->name);
++ } else {
++ PRINT_ERROR("Target driver %s xmit_response() returned "
++ "invalid value %d", tgtt->name, rc);
++ }
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++ cmd->state = SCST_CMD_STATE_FINISHED;
++ res = SCST_CMD_STATE_RES_CONT_SAME;
++ goto out;
++}
++
++/**
++ * scst_tgt_cmd_done() - the command's processing done
++ * @cmd: SCST command
++ * @pref_context: preferred command execution context
++ *
++ * Description:
++ * Notifies SCST that the driver sent the response and the command
++ * can be freed now. Don't forget to set the delivery status, if it
++ * isn't success, using scst_set_delivery_status() before calling
++ * this function. The third argument sets preferred command execition
++ * context (see SCST_CONTEXT_* constants for details)
++ */
++void scst_tgt_cmd_done(struct scst_cmd *cmd,
++ enum scst_exec_context pref_context)
++{
++ TRACE_ENTRY();
++
++ BUG_ON(cmd->state != SCST_CMD_STATE_XMIT_WAIT);
++
++ scst_set_xmit_time(cmd);
++
++ cmd->cmd_hw_pending = 0;
++
++ if (unlikely(cmd->tgt_dev == NULL))
++ pref_context = SCST_CONTEXT_THREAD;
++
++ cmd->state = SCST_CMD_STATE_FINISHED;
++
++ scst_process_redirect_cmd(cmd, pref_context, 1);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_tgt_cmd_done);
++
++static int scst_finish_cmd(struct scst_cmd *cmd)
++{
++ int res;
++ struct scst_session *sess = cmd->sess;
++
++ TRACE_ENTRY();
++
++ scst_update_lat_stats(cmd);
++
++ if (unlikely(cmd->delivery_status != SCST_CMD_DELIVERY_SUCCESS)) {
++ if ((cmd->tgt_dev != NULL) &&
++ scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) {
++ /* This UA delivery failed, so we need to requeue it */
++ if (scst_cmd_atomic(cmd) &&
++ scst_is_ua_global(cmd->sense, cmd->sense_valid_len)) {
++ TRACE_MGMT_DBG("Requeuing of global UA for "
++ "failed cmd %p needs a thread", cmd);
++ res = SCST_CMD_STATE_RES_NEED_THREAD;
++ goto out;
++ }
++ scst_requeue_ua(cmd);
++ }
++ }
++
++ atomic_dec(&sess->sess_cmd_count);
++
++ spin_lock_irq(&sess->sess_list_lock);
++ list_del(&cmd->sess_cmd_list_entry);
++ spin_unlock_irq(&sess->sess_list_lock);
++
++ cmd->finished = 1;
++ smp_mb(); /* to sync with scst_abort_cmd() */
++
++ if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
++ TRACE_MGMT_DBG("Aborted cmd %p finished (cmd_ref %d, "
++ "scst_cmd_count %d)", cmd, atomic_read(&cmd->cmd_ref),
++ atomic_read(&scst_cmd_count));
++
++ scst_finish_cmd_mgmt(cmd);
++ }
++
++ __scst_cmd_put(cmd);
++
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/*
++ * No locks, but it must be externally serialized (see comment for
++ * scst_cmd_init_done() in scst.h)
++ */
++static void scst_cmd_set_sn(struct scst_cmd *cmd)
++{
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ if (scst_is_implicit_hq(cmd) &&
++ likely(cmd->queue_type == SCST_CMD_QUEUE_SIMPLE)) {
++ TRACE_SN("Implicit HQ cmd %p", cmd);
++ cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
++ }
++
++ EXTRACHECKS_BUG_ON(cmd->sn_set || cmd->hq_cmd_inced);
++
++ /* Optimized for lockless fast path */
++
++ scst_check_debug_sn(cmd);
++
++#ifdef CONFIG_SCST_STRICT_SERIALIZING
++ cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
++#endif
++
++ if (cmd->dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) {
++ /*
++ * Not the best way, but good enough until there is a
++ * possibility to specify queue type during pass-through
++ * commands submission.
++ */
++ cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
++ }
++
++ switch (cmd->queue_type) {
++ case SCST_CMD_QUEUE_SIMPLE:
++ case SCST_CMD_QUEUE_UNTAGGED:
++#ifdef CONFIG_SCST_ORDERED_READS
++ if (scst_cmd_is_expected_set(cmd)) {
++ if ((cmd->expected_data_direction == SCST_DATA_READ) &&
++ (atomic_read(&cmd->dev->write_cmd_count) == 0))
++ goto ordered;
++ } else
++ goto ordered;
++#endif
++ if (likely(tgt_dev->num_free_sn_slots >= 0)) {
++ /*
++ * atomic_inc_return() implies memory barrier to sync
++ * with scst_inc_expected_sn()
++ */
++ if (atomic_inc_return(tgt_dev->cur_sn_slot) == 1) {
++ tgt_dev->curr_sn++;
++ TRACE_SN("Incremented curr_sn %d",
++ tgt_dev->curr_sn);
++ }
++ cmd->sn_slot = tgt_dev->cur_sn_slot;
++ cmd->sn = tgt_dev->curr_sn;
++
++ tgt_dev->prev_cmd_ordered = 0;
++ } else {
++ TRACE(TRACE_MINOR, "***WARNING*** Not enough SN slots "
++ "%zd", ARRAY_SIZE(tgt_dev->sn_slots));
++ goto ordered;
++ }
++ break;
++
++ case SCST_CMD_QUEUE_ORDERED:
++ TRACE_SN("ORDERED cmd %p (op %x)", cmd, cmd->cdb[0]);
++ordered:
++ if (!tgt_dev->prev_cmd_ordered) {
++ spin_lock_irqsave(&tgt_dev->sn_lock, flags);
++ if (tgt_dev->num_free_sn_slots >= 0) {
++ tgt_dev->num_free_sn_slots--;
++ if (tgt_dev->num_free_sn_slots >= 0) {
++ int i = 0;
++ /* Commands can finish in any order, so
++ * we don't know which slot is empty.
++ */
++ while (1) {
++ tgt_dev->cur_sn_slot++;
++ if (tgt_dev->cur_sn_slot ==
++ tgt_dev->sn_slots + ARRAY_SIZE(tgt_dev->sn_slots))
++ tgt_dev->cur_sn_slot = tgt_dev->sn_slots;
++
++ if (atomic_read(tgt_dev->cur_sn_slot) == 0)
++ break;
++
++ i++;
++ BUG_ON(i == ARRAY_SIZE(tgt_dev->sn_slots));
++ }
++ TRACE_SN("New cur SN slot %zd",
++ tgt_dev->cur_sn_slot -
++ tgt_dev->sn_slots);
++ }
++ }
++ spin_unlock_irqrestore(&tgt_dev->sn_lock, flags);
++ }
++ tgt_dev->prev_cmd_ordered = 1;
++ tgt_dev->curr_sn++;
++ cmd->sn = tgt_dev->curr_sn;
++ break;
++
++ case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
++ TRACE_SN("HQ cmd %p (op %x)", cmd, cmd->cdb[0]);
++ spin_lock_irqsave(&tgt_dev->sn_lock, flags);
++ tgt_dev->hq_cmd_count++;
++ spin_unlock_irqrestore(&tgt_dev->sn_lock, flags);
++ cmd->hq_cmd_inced = 1;
++ goto out;
++
++ default:
++ BUG();
++ }
++
++ TRACE_SN("cmd(%p)->sn: %d (tgt_dev %p, *cur_sn_slot %d, "
++ "num_free_sn_slots %d, prev_cmd_ordered %ld, "
++ "cur_sn_slot %zd)", cmd, cmd->sn, tgt_dev,
++ atomic_read(tgt_dev->cur_sn_slot),
++ tgt_dev->num_free_sn_slots, tgt_dev->prev_cmd_ordered,
++ tgt_dev->cur_sn_slot-tgt_dev->sn_slots);
++
++ cmd->sn_set = 1;
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * Returns 0 on success, > 0 when we need to wait for unblock,
++ * < 0 if there is no device (lun) or device type handler.
++ *
++ * No locks, but might be on IRQ, protection is done by the
++ * suspended activity.
++ */
++static int scst_translate_lun(struct scst_cmd *cmd)
++{
++ struct scst_tgt_dev *tgt_dev = NULL;
++ int res;
++
++ TRACE_ENTRY();
++
++ /* See comment about smp_mb() in scst_suspend_activity() */
++ __scst_get();
++
++ if (likely(!test_bit(SCST_FLAG_SUSPENDED, &scst_flags))) {
++ struct list_head *sess_tgt_dev_list_head =
++ &cmd->sess->sess_tgt_dev_list_hash[HASH_VAL(cmd->lun)];
++ TRACE_DBG("Finding tgt_dev for cmd %p (lun %lld)", cmd,
++ (long long unsigned int)cmd->lun);
++ res = -1;
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ if (tgt_dev->lun == cmd->lun) {
++ TRACE_DBG("tgt_dev %p found", tgt_dev);
++
++ if (unlikely(tgt_dev->dev->handler ==
++ &scst_null_devtype)) {
++ PRINT_INFO("Dev handler for device "
++ "%lld is NULL, the device will not "
++ "be visible remotely",
++ (long long unsigned int)cmd->lun);
++ break;
++ }
++
++ cmd->cmd_threads = tgt_dev->active_cmd_threads;
++ cmd->tgt_dev = tgt_dev;
++ cmd->dev = tgt_dev->dev;
++
++ res = 0;
++ break;
++ }
++ }
++ if (res != 0) {
++ TRACE(TRACE_MINOR,
++ "tgt_dev for LUN %lld not found, command to "
++ "unexisting LU?",
++ (long long unsigned int)cmd->lun);
++ __scst_put();
++ }
++ } else {
++ TRACE_MGMT_DBG("%s", "FLAG SUSPENDED set, skipping");
++ __scst_put();
++ res = 1;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * No locks, but might be on IRQ.
++ *
++ * Returns 0 on success, > 0 when we need to wait for unblock,
++ * < 0 if there is no device (lun) or device type handler.
++ */
++static int __scst_init_cmd(struct scst_cmd *cmd)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ res = scst_translate_lun(cmd);
++ if (likely(res == 0)) {
++ int cnt;
++ bool failure = false;
++
++ cmd->state = SCST_CMD_STATE_PARSE;
++
++ cnt = atomic_inc_return(&cmd->tgt_dev->tgt_dev_cmd_count);
++ if (unlikely(cnt > SCST_MAX_TGT_DEV_COMMANDS)) {
++ TRACE(TRACE_FLOW_CONTROL,
++ "Too many pending commands (%d) in "
++ "session, returning BUSY to initiator \"%s\"",
++ cnt, (cmd->sess->initiator_name[0] == '\0') ?
++ "Anonymous" : cmd->sess->initiator_name);
++ failure = true;
++ }
++
++#ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT
++ cnt = atomic_inc_return(&cmd->dev->dev_cmd_count);
++ if (unlikely(cnt > SCST_MAX_DEV_COMMANDS)) {
++ if (!failure) {
++ TRACE(TRACE_FLOW_CONTROL,
++ "Too many pending device "
++ "commands (%d), returning BUSY to "
++ "initiator \"%s\"", cnt,
++ (cmd->sess->initiator_name[0] == '\0') ?
++ "Anonymous" :
++ cmd->sess->initiator_name);
++ failure = true;
++ }
++ }
++#endif
++
++#ifdef CONFIG_SCST_ORDERED_READS
++ /* If expected values not set, expected direction is UNKNOWN */
++ if (cmd->expected_data_direction & SCST_DATA_WRITE)
++ atomic_inc(&cmd->dev->write_cmd_count);
++#endif
++
++ if (unlikely(failure))
++ goto out_busy;
++
++ if (unlikely(scst_pre_parse(cmd) != 0))
++ goto out;
++
++ if (!cmd->set_sn_on_restart_cmd)
++ scst_cmd_set_sn(cmd);
++ } else if (res < 0) {
++ TRACE_DBG("Finishing cmd %p", cmd);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_lun_not_supported));
++ scst_set_cmd_abnormal_done_state(cmd);
++ } else
++ goto out;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_busy:
++ scst_set_busy(cmd);
++ scst_set_cmd_abnormal_done_state(cmd);
++ goto out;
++}
++
++/* Called under scst_init_lock and IRQs disabled */
++static void scst_do_job_init(void)
++ __releases(&scst_init_lock)
++ __acquires(&scst_init_lock)
++{
++ struct scst_cmd *cmd;
++ int susp;
++
++ TRACE_ENTRY();
++
++restart:
++ /*
++ * There is no need for read barrier here, because we don't care where
++ * this check will be done.
++ */
++ susp = test_bit(SCST_FLAG_SUSPENDED, &scst_flags);
++ if (scst_init_poll_cnt > 0)
++ scst_init_poll_cnt--;
++
++ list_for_each_entry(cmd, &scst_init_cmd_list, cmd_list_entry) {
++ int rc;
++ if (susp && !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))
++ continue;
++ if (!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
++ spin_unlock_irq(&scst_init_lock);
++ rc = __scst_init_cmd(cmd);
++ spin_lock_irq(&scst_init_lock);
++ if (rc > 0) {
++ TRACE_MGMT_DBG("%s",
++ "FLAG SUSPENDED set, restarting");
++ goto restart;
++ }
++ } else {
++ TRACE_MGMT_DBG("Aborting not inited cmd %p (tag %llu)",
++ cmd, (long long unsigned int)cmd->tag);
++ scst_set_cmd_abnormal_done_state(cmd);
++ }
++
++ /*
++ * Deleting cmd from init cmd list after __scst_init_cmd()
++ * is necessary to keep the check in scst_init_cmd() correct
++ * to preserve the commands order.
++ *
++ * We don't care about the race, when init cmd list is empty
++ * and one command detected that it just was not empty, so
++ * it's inserting to it, but another command at the same time
++ * seeing init cmd list empty and goes directly, because it
++ * could affect only commands from the same initiator to the
++ * same tgt_dev, but scst_cmd_init_done*() doesn't guarantee
++ * the order in case of simultaneous such calls anyway.
++ */
++ TRACE_MGMT_DBG("Deleting cmd %p from init cmd list", cmd);
++ smp_wmb(); /* enforce the required order */
++ list_del(&cmd->cmd_list_entry);
++ spin_unlock(&scst_init_lock);
++
++ spin_lock(&cmd->cmd_threads->cmd_list_lock);
++ TRACE_MGMT_DBG("Adding cmd %p to active cmd list", cmd);
++ if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
++ list_add(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ else
++ list_add_tail(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
++
++ spin_lock(&scst_init_lock);
++ goto restart;
++ }
++
++ /* It isn't really needed, but let's keep it */
++ if (susp != test_bit(SCST_FLAG_SUSPENDED, &scst_flags))
++ goto restart;
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline int test_init_cmd_list(void)
++{
++ int res = (!list_empty(&scst_init_cmd_list) &&
++ !test_bit(SCST_FLAG_SUSPENDED, &scst_flags)) ||
++ unlikely(kthread_should_stop()) ||
++ (scst_init_poll_cnt > 0);
++ return res;
++}
++
++int scst_init_thread(void *arg)
++{
++ TRACE_ENTRY();
++
++ PRINT_INFO("Init thread started, PID %d", current->pid);
++
++ current->flags |= PF_NOFREEZE;
++
++ set_user_nice(current, -10);
++
++ spin_lock_irq(&scst_init_lock);
++ while (!kthread_should_stop()) {
++ wait_queue_t wait;
++ init_waitqueue_entry(&wait, current);
++
++ if (!test_init_cmd_list()) {
++ add_wait_queue_exclusive(&scst_init_cmd_list_waitQ,
++ &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_init_cmd_list())
++ break;
++ spin_unlock_irq(&scst_init_lock);
++ schedule();
++ spin_lock_irq(&scst_init_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&scst_init_cmd_list_waitQ, &wait);
++ }
++ scst_do_job_init();
++ }
++ spin_unlock_irq(&scst_init_lock);
++
++ /*
++ * If kthread_should_stop() is true, we are guaranteed to be
++ * on the module unload, so scst_init_cmd_list must be empty.
++ */
++ BUG_ON(!list_empty(&scst_init_cmd_list));
++
++ PRINT_INFO("Init thread PID %d finished", current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++/**
++ * scst_process_active_cmd() - process active command
++ *
++ * Description:
++ * Main SCST commands processing routing. Must be used only by dev handlers.
++ *
++ * Argument atomic is true, if function called in atomic context.
++ *
++ * Must be called with no locks held.
++ */
++void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ /*
++ * Checkpatch will complain on the use of in_atomic() below. You
++ * can safely ignore this warning since in_atomic() is used here only
++ * for debugging purposes.
++ */
++ EXTRACHECKS_BUG_ON(in_irq() || irqs_disabled());
++ EXTRACHECKS_WARN_ON((in_atomic() || in_interrupt() || irqs_disabled()) &&
++ !atomic);
++
++ cmd->atomic = atomic;
++
++ TRACE_DBG("cmd %p, atomic %d", cmd, atomic);
++
++ do {
++ switch (cmd->state) {
++ case SCST_CMD_STATE_PARSE:
++ res = scst_parse_cmd(cmd);
++ break;
++
++ case SCST_CMD_STATE_PREPARE_SPACE:
++ res = scst_prepare_space(cmd);
++ break;
++
++ case SCST_CMD_STATE_PREPROCESSING_DONE:
++ res = scst_preprocessing_done(cmd);
++ break;
++
++ case SCST_CMD_STATE_RDY_TO_XFER:
++ res = scst_rdy_to_xfer(cmd);
++ break;
++
++ case SCST_CMD_STATE_TGT_PRE_EXEC:
++ res = scst_tgt_pre_exec(cmd);
++ break;
++
++ case SCST_CMD_STATE_SEND_FOR_EXEC:
++ if (tm_dbg_check_cmd(cmd) != 0) {
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ TRACE_MGMT_DBG("Skipping cmd %p (tag %llu), "
++ "because of TM DBG delay", cmd,
++ (long long unsigned int)cmd->tag);
++ break;
++ }
++ res = scst_send_for_exec(&cmd);
++ /*
++ * !! At this point cmd, sess & tgt_dev can already be
++ * freed !!
++ */
++ break;
++
++ case SCST_CMD_STATE_LOCAL_EXEC:
++ res = scst_local_exec(cmd);
++ /*
++ * !! At this point cmd, sess & tgt_dev can already be
++ * freed !!
++ */
++ break;
++
++ case SCST_CMD_STATE_REAL_EXEC:
++ res = scst_real_exec(cmd);
++ /*
++ * !! At this point cmd, sess & tgt_dev can already be
++ * freed !!
++ */
++ break;
++
++ case SCST_CMD_STATE_PRE_DEV_DONE:
++ res = scst_pre_dev_done(cmd);
++ EXTRACHECKS_BUG_ON((res == SCST_CMD_STATE_RES_NEED_THREAD) &&
++ (cmd->state == SCST_CMD_STATE_PRE_DEV_DONE));
++ break;
++
++ case SCST_CMD_STATE_MODE_SELECT_CHECKS:
++ res = scst_mode_select_checks(cmd);
++ break;
++
++ case SCST_CMD_STATE_DEV_DONE:
++ res = scst_dev_done(cmd);
++ break;
++
++ case SCST_CMD_STATE_PRE_XMIT_RESP:
++ res = scst_pre_xmit_response(cmd);
++ EXTRACHECKS_BUG_ON(res ==
++ SCST_CMD_STATE_RES_NEED_THREAD);
++ break;
++
++ case SCST_CMD_STATE_XMIT_RESP:
++ res = scst_xmit_response(cmd);
++ break;
++
++ case SCST_CMD_STATE_FINISHED:
++ res = scst_finish_cmd(cmd);
++ break;
++
++ case SCST_CMD_STATE_FINISHED_INTERNAL:
++ res = scst_finish_internal_cmd(cmd);
++ EXTRACHECKS_BUG_ON(res ==
++ SCST_CMD_STATE_RES_NEED_THREAD);
++ break;
++
++ default:
++ PRINT_CRIT_ERROR("cmd (%p) in state %d, but shouldn't "
++ "be", cmd, cmd->state);
++ BUG();
++ res = SCST_CMD_STATE_RES_CONT_NEXT;
++ break;
++ }
++ } while (res == SCST_CMD_STATE_RES_CONT_SAME);
++
++ if (res == SCST_CMD_STATE_RES_CONT_NEXT) {
++ /* None */
++ } else if (res == SCST_CMD_STATE_RES_NEED_THREAD) {
++ spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
++#ifdef CONFIG_SCST_EXTRACHECKS
++ switch (cmd->state) {
++ case SCST_CMD_STATE_PARSE:
++ case SCST_CMD_STATE_PREPARE_SPACE:
++ case SCST_CMD_STATE_RDY_TO_XFER:
++ case SCST_CMD_STATE_TGT_PRE_EXEC:
++ case SCST_CMD_STATE_SEND_FOR_EXEC:
++ case SCST_CMD_STATE_LOCAL_EXEC:
++ case SCST_CMD_STATE_REAL_EXEC:
++ case SCST_CMD_STATE_DEV_DONE:
++ case SCST_CMD_STATE_XMIT_RESP:
++#endif
++ TRACE_DBG("Adding cmd %p to head of active cmd list",
++ cmd);
++ list_add(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++#ifdef CONFIG_SCST_EXTRACHECKS
++ break;
++ default:
++ PRINT_CRIT_ERROR("cmd %p is in invalid state %d)", cmd,
++ cmd->state);
++ spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
++ BUG();
++ spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
++ break;
++ }
++#endif
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
++ } else
++ BUG();
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_process_active_cmd);
++
++/* Called under cmd_list_lock and IRQs disabled */
++static void scst_do_job_active(struct list_head *cmd_list,
++ spinlock_t *cmd_list_lock, bool atomic)
++ __releases(cmd_list_lock)
++ __acquires(cmd_list_lock)
++{
++ TRACE_ENTRY();
++
++ while (!list_empty(cmd_list)) {
++ struct scst_cmd *cmd = list_entry(cmd_list->next, typeof(*cmd),
++ cmd_list_entry);
++ TRACE_DBG("Deleting cmd %p from active cmd list", cmd);
++ list_del(&cmd->cmd_list_entry);
++ spin_unlock_irq(cmd_list_lock);
++ scst_process_active_cmd(cmd, atomic);
++ spin_lock_irq(cmd_list_lock);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline int test_cmd_threads(struct scst_cmd_threads *p_cmd_threads)
++{
++ int res = !list_empty(&p_cmd_threads->active_cmd_list) ||
++ unlikely(kthread_should_stop()) ||
++ tm_dbg_is_release();
++ return res;
++}
++
++int scst_cmd_thread(void *arg)
++{
++ struct scst_cmd_threads *p_cmd_threads = arg;
++
++ TRACE_ENTRY();
++
++ PRINT_INFO("Processing thread %s (PID %d) started", current->comm,
++ current->pid);
++
++#if 0
++ set_user_nice(current, 10);
++#endif
++ current->flags |= PF_NOFREEZE;
++
++ mutex_lock(&p_cmd_threads->io_context_mutex);
++
++ WARN_ON(current->io_context);
++
++ if (p_cmd_threads != &scst_main_cmd_threads) {
++ /*
++ * For linked IO contexts io_context might be not NULL while
++ * io_context 0.
++ */
++ if (p_cmd_threads->io_context == NULL) {
++ p_cmd_threads->io_context = get_io_context(GFP_KERNEL, -1);
++ TRACE_MGMT_DBG("Alloced new IO context %p "
++ "(p_cmd_threads %p)",
++ p_cmd_threads->io_context,
++ p_cmd_threads);
++ /*
++ * Put the extra reference created by get_io_context()
++ * because we don't need it.
++ */
++ put_io_context(p_cmd_threads->io_context);
++ } else {
++ current->io_context = ioc_task_link(p_cmd_threads->io_context);
++ TRACE_MGMT_DBG("Linked IO context %p "
++ "(p_cmd_threads %p)", p_cmd_threads->io_context,
++ p_cmd_threads);
++ }
++ p_cmd_threads->io_context_refcnt++;
++ }
++
++ mutex_unlock(&p_cmd_threads->io_context_mutex);
++
++ p_cmd_threads->io_context_ready = true;
++
++ spin_lock_irq(&p_cmd_threads->cmd_list_lock);
++ while (!kthread_should_stop()) {
++ wait_queue_t wait;
++ init_waitqueue_entry(&wait, current);
++
++ if (!test_cmd_threads(p_cmd_threads)) {
++ add_wait_queue_exclusive_head(
++ &p_cmd_threads->cmd_list_waitQ,
++ &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_cmd_threads(p_cmd_threads))
++ break;
++ spin_unlock_irq(&p_cmd_threads->cmd_list_lock);
++ schedule();
++ spin_lock_irq(&p_cmd_threads->cmd_list_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&p_cmd_threads->cmd_list_waitQ, &wait);
++ }
++
++ if (tm_dbg_is_release()) {
++ spin_unlock_irq(&p_cmd_threads->cmd_list_lock);
++ tm_dbg_check_released_cmds();
++ spin_lock_irq(&p_cmd_threads->cmd_list_lock);
++ }
++
++ scst_do_job_active(&p_cmd_threads->active_cmd_list,
++ &p_cmd_threads->cmd_list_lock, false);
++ }
++ spin_unlock_irq(&p_cmd_threads->cmd_list_lock);
++
++ if (p_cmd_threads != &scst_main_cmd_threads) {
++ mutex_lock(&p_cmd_threads->io_context_mutex);
++ if (--p_cmd_threads->io_context_refcnt == 0)
++ p_cmd_threads->io_context = NULL;
++ mutex_unlock(&p_cmd_threads->io_context_mutex);
++ }
++
++ PRINT_INFO("Processing thread %s (PID %d) finished", current->comm,
++ current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++void scst_cmd_tasklet(long p)
++{
++ struct scst_tasklet *t = (struct scst_tasklet *)p;
++
++ TRACE_ENTRY();
++
++ spin_lock_irq(&t->tasklet_lock);
++ scst_do_job_active(&t->tasklet_cmd_list, &t->tasklet_lock, true);
++ spin_unlock_irq(&t->tasklet_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * Returns 0 on success, < 0 if there is no device handler or
++ * > 0 if SCST_FLAG_SUSPENDED set and SCST_FLAG_SUSPENDING - not.
++ * No locks, protection is done by the suspended activity.
++ */
++static int scst_mgmt_translate_lun(struct scst_mgmt_cmd *mcmd)
++{
++ struct scst_tgt_dev *tgt_dev = NULL;
++ struct list_head *sess_tgt_dev_list_head;
++ int res = -1;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Finding tgt_dev for mgmt cmd %p (lun %lld)", mcmd,
++ (long long unsigned int)mcmd->lun);
++
++ /* See comment about smp_mb() in scst_suspend_activity() */
++ __scst_get();
++
++ if (unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags) &&
++ !test_bit(SCST_FLAG_SUSPENDING, &scst_flags))) {
++ TRACE_MGMT_DBG("%s", "FLAG SUSPENDED set, skipping");
++ __scst_put();
++ res = 1;
++ goto out;
++ }
++
++ sess_tgt_dev_list_head =
++ &mcmd->sess->sess_tgt_dev_list_hash[HASH_VAL(mcmd->lun)];
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ if (tgt_dev->lun == mcmd->lun) {
++ TRACE_DBG("tgt_dev %p found", tgt_dev);
++ mcmd->mcmd_tgt_dev = tgt_dev;
++ res = 0;
++ break;
++ }
++ }
++ if (mcmd->mcmd_tgt_dev == NULL)
++ __scst_put();
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/* No locks */
++void scst_done_cmd_mgmt(struct scst_cmd *cmd)
++{
++ struct scst_mgmt_cmd_stub *mstb, *t;
++ bool wake = 0;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("cmd %p done (tag %llu)",
++ cmd, (long long unsigned int)cmd->tag);
++
++ spin_lock_irqsave(&scst_mcmd_lock, flags);
++
++ list_for_each_entry_safe(mstb, t, &cmd->mgmt_cmd_list,
++ cmd_mgmt_cmd_list_entry) {
++ struct scst_mgmt_cmd *mcmd;
++
++ if (!mstb->done_counted)
++ continue;
++
++ mcmd = mstb->mcmd;
++ TRACE_MGMT_DBG("mcmd %p, mcmd->cmd_done_wait_count %d",
++ mcmd, mcmd->cmd_done_wait_count);
++
++ mcmd->cmd_done_wait_count--;
++
++ BUG_ON(mcmd->cmd_done_wait_count < 0);
++
++ if (mcmd->cmd_done_wait_count > 0) {
++ TRACE_MGMT_DBG("cmd_done_wait_count(%d) not 0, "
++ "skipping", mcmd->cmd_done_wait_count);
++ goto check_free;
++ }
++
++ if (mcmd->state == SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE) {
++ mcmd->state = SCST_MCMD_STATE_AFFECTED_CMDS_DONE;
++ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
++ "list", mcmd);
++ list_add_tail(&mcmd->mgmt_cmd_list_entry,
++ &scst_active_mgmt_cmd_list);
++ wake = 1;
++ }
++
++check_free:
++ if (!mstb->finish_counted) {
++ TRACE_DBG("Releasing mstb %p", mstb);
++ list_del(&mstb->cmd_mgmt_cmd_list_entry);
++ mempool_free(mstb, scst_mgmt_stub_mempool);
++ }
++ }
++
++ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
++
++ if (wake)
++ wake_up(&scst_mgmt_cmd_list_waitQ);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called under scst_mcmd_lock and IRQs disabled */
++static void __scst_dec_finish_wait_count(struct scst_mgmt_cmd *mcmd, bool *wake)
++{
++ TRACE_ENTRY();
++
++ mcmd->cmd_finish_wait_count--;
++
++ BUG_ON(mcmd->cmd_finish_wait_count < 0);
++
++ if (mcmd->cmd_finish_wait_count > 0) {
++ TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, "
++ "skipping", mcmd->cmd_finish_wait_count);
++ goto out;
++ }
++
++ if (mcmd->cmd_done_wait_count > 0) {
++ TRACE_MGMT_DBG("cmd_done_wait_count(%d) not 0, "
++ "skipping", mcmd->cmd_done_wait_count);
++ goto out;
++ }
++
++ if (mcmd->state == SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED) {
++ mcmd->state = SCST_MCMD_STATE_DONE;
++ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
++ "list", mcmd);
++ list_add_tail(&mcmd->mgmt_cmd_list_entry,
++ &scst_active_mgmt_cmd_list);
++ *wake = true;
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * scst_prepare_async_mcmd() - prepare async management command
++ *
++ * Notifies SCST that management command is going to be async, i.e.
++ * will be completed in another context.
++ *
++ * No SCST locks supposed to be held on entrance.
++ */
++void scst_prepare_async_mcmd(struct scst_mgmt_cmd *mcmd)
++{
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Preparing mcmd %p for async execution "
++ "(cmd_finish_wait_count %d)", mcmd,
++ mcmd->cmd_finish_wait_count);
++
++ spin_lock_irqsave(&scst_mcmd_lock, flags);
++ mcmd->cmd_finish_wait_count++;
++ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_prepare_async_mcmd);
++
++/**
++ * scst_async_mcmd_completed() - async management command completed
++ *
++ * Notifies SCST that async management command, prepared by
++ * scst_prepare_async_mcmd(), completed.
++ *
++ * No SCST locks supposed to be held on entrance.
++ */
++void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status)
++{
++ unsigned long flags;
++ bool wake = false;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Async mcmd %p completed (status %d)", mcmd, status);
++
++ spin_lock_irqsave(&scst_mcmd_lock, flags);
++
++ if (status != SCST_MGMT_STATUS_SUCCESS)
++ mcmd->status = status;
++
++ __scst_dec_finish_wait_count(mcmd, &wake);
++
++ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
++
++ if (wake)
++ wake_up(&scst_mgmt_cmd_list_waitQ);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_async_mcmd_completed);
++
++/* No locks */
++static void scst_finish_cmd_mgmt(struct scst_cmd *cmd)
++{
++ struct scst_mgmt_cmd_stub *mstb, *t;
++ bool wake = false;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("cmd %p finished (tag %llu)",
++ cmd, (long long unsigned int)cmd->tag);
++
++ spin_lock_irqsave(&scst_mcmd_lock, flags);
++
++ list_for_each_entry_safe(mstb, t, &cmd->mgmt_cmd_list,
++ cmd_mgmt_cmd_list_entry) {
++ struct scst_mgmt_cmd *mcmd = mstb->mcmd;
++
++ TRACE_MGMT_DBG("mcmd %p, mcmd->cmd_finish_wait_count %d", mcmd,
++ mcmd->cmd_finish_wait_count);
++
++ BUG_ON(!mstb->finish_counted);
++
++ if (cmd->completed)
++ mcmd->completed_cmd_count++;
++
++ __scst_dec_finish_wait_count(mcmd, &wake);
++
++ TRACE_DBG("Releasing mstb %p", mstb);
++ list_del(&mstb->cmd_mgmt_cmd_list_entry);
++ mempool_free(mstb, scst_mgmt_stub_mempool);
++ }
++
++ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
++
++ if (wake)
++ wake_up(&scst_mgmt_cmd_list_waitQ);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int scst_call_dev_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
++ struct scst_tgt_dev *tgt_dev, int set_status)
++{
++ int res = SCST_DEV_TM_NOT_COMPLETED;
++ struct scst_dev_type *h = tgt_dev->dev->handler;
++
++ if (h->task_mgmt_fn) {
++ TRACE_MGMT_DBG("Calling dev handler %s task_mgmt_fn(fn=%d)",
++ h->name, mcmd->fn);
++ EXTRACHECKS_BUG_ON(in_irq() || irqs_disabled());
++ res = h->task_mgmt_fn(mcmd, tgt_dev);
++ TRACE_MGMT_DBG("Dev handler %s task_mgmt_fn() returned %d",
++ h->name, res);
++ if (set_status && (res != SCST_DEV_TM_NOT_COMPLETED))
++ mcmd->status = res;
++ }
++ return res;
++}
++
++static inline int scst_is_strict_mgmt_fn(int mgmt_fn)
++{
++ switch (mgmt_fn) {
++#ifdef CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING
++ case SCST_ABORT_TASK:
++#endif
++#if 0
++ case SCST_ABORT_TASK_SET:
++ case SCST_CLEAR_TASK_SET:
++#endif
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++/* Might be called under sess_list_lock and IRQ off + BHs also off */
++void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
++ bool other_ini, bool call_dev_task_mgmt_fn)
++{
++ unsigned long flags;
++ static DEFINE_SPINLOCK(other_ini_lock);
++
++ TRACE_ENTRY();
++
++ TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, "Aborting cmd %p (tag %llu, op %x)",
++ cmd, (long long unsigned int)cmd->tag, cmd->cdb[0]);
++
++ /* To protect from concurrent aborts */
++ spin_lock_irqsave(&other_ini_lock, flags);
++
++ if (other_ini) {
++ struct scst_device *dev = NULL;
++
++ /* Might be necessary if command aborted several times */
++ if (!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))
++ set_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
++
++ /* Necessary for scst_xmit_process_aborted_cmd */
++ if (cmd->dev != NULL)
++ dev = cmd->dev;
++ else if ((mcmd != NULL) && (mcmd->mcmd_tgt_dev != NULL))
++ dev = mcmd->mcmd_tgt_dev->dev;
++
++ if (dev != NULL) {
++ if (dev->tas)
++ set_bit(SCST_CMD_DEVICE_TAS, &cmd->cmd_flags);
++ } else
++ PRINT_WARNING("Abort cmd %p from other initiator, but "
++ "neither cmd, nor mcmd %p have tgt_dev set, so "
++ "TAS information can be lost", cmd, mcmd);
++ } else {
++ /* Might be necessary if command aborted several times */
++ clear_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
++ }
++
++ set_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
++
++ spin_unlock_irqrestore(&other_ini_lock, flags);
++
++ /*
++ * To sync with cmd->finished/done set in
++ * scst_finish_cmd()/scst_pre_xmit_response() and with setting UA for
++ * aborted cmd in scst_set_pending_UA().
++ */
++ smp_mb__after_set_bit();
++
++ if (cmd->tgt_dev == NULL) {
++ spin_lock_irqsave(&scst_init_lock, flags);
++ scst_init_poll_cnt++;
++ spin_unlock_irqrestore(&scst_init_lock, flags);
++ wake_up(&scst_init_cmd_list_waitQ);
++ }
++
++ if (call_dev_task_mgmt_fn && (cmd->tgt_dev != NULL)) {
++ EXTRACHECKS_BUG_ON(irqs_disabled());
++ scst_call_dev_task_mgmt_fn(mcmd, cmd->tgt_dev, 1);
++ }
++
++ spin_lock_irqsave(&scst_mcmd_lock, flags);
++ if ((mcmd != NULL) && !cmd->finished) {
++ struct scst_mgmt_cmd_stub *mstb;
++
++ mstb = mempool_alloc(scst_mgmt_stub_mempool, GFP_ATOMIC);
++ if (mstb == NULL) {
++ PRINT_CRIT_ERROR("Allocation of management command "
++ "stub failed (mcmd %p, cmd %p)", mcmd, cmd);
++ goto unlock;
++ }
++ memset(mstb, 0, sizeof(*mstb));
++
++ TRACE_DBG("mstb %p, mcmd %p", mstb, mcmd);
++
++ mstb->mcmd = mcmd;
++
++ /*
++ * Delay the response until the command's finish in order to
++ * guarantee that "no further responses from the task are sent
++ * to the SCSI initiator port" after response from the TM
++ * function is sent (SAM). Plus, we must wait here to be sure
++ * that we won't receive double commands with the same tag.
++ * Moreover, if we don't wait here, we might have a possibility
++ * for data corruption, when aborted and reported as completed
++ * command actually gets executed *after* new commands sent
++ * after this TM command completed.
++ */
++
++ if (cmd->sent_for_exec && !cmd->done) {
++ TRACE_MGMT_DBG("cmd %p (tag %llu) is being executed",
++ cmd, (long long unsigned int)cmd->tag);
++ mstb->done_counted = 1;
++ mcmd->cmd_done_wait_count++;
++ }
++
++ /*
++ * We don't have to wait the command's status delivery finish
++ * to other initiators + it can affect MPIO failover.
++ */
++ if (!other_ini) {
++ mstb->finish_counted = 1;
++ mcmd->cmd_finish_wait_count++;
++ }
++
++ if (mstb->done_counted || mstb->finish_counted) {
++ TRACE_MGMT_DBG("cmd %p (tag %llu, sn %u) being "
++ "executed/xmitted (state %d, op %x, proc time "
++ "%ld sec., timeout %d sec.), deferring ABORT "
++ "(cmd_done_wait_count %d, cmd_finish_wait_count "
++ "%d)", cmd, (long long unsigned int)cmd->tag,
++ cmd->sn, cmd->state, cmd->cdb[0],
++ (long)(jiffies - cmd->start_time) / HZ,
++ cmd->timeout / HZ, mcmd->cmd_done_wait_count,
++ mcmd->cmd_finish_wait_count);
++ /*
++ * cmd can't die here or sess_list_lock already taken
++ * and cmd is in the sess list
++ */
++ list_add_tail(&mstb->cmd_mgmt_cmd_list_entry,
++ &cmd->mgmt_cmd_list);
++ } else {
++ /* We don't need to wait for this cmd */
++ mempool_free(mstb, scst_mgmt_stub_mempool);
++ }
++ }
++
++unlock:
++ spin_unlock_irqrestore(&scst_mcmd_lock, flags);
++
++ tm_dbg_release_cmd(cmd);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* No locks. Returns 0, if mcmd should be processed further. */
++static int scst_set_mcmd_next_state(struct scst_mgmt_cmd *mcmd)
++{
++ int res;
++
++ spin_lock_irq(&scst_mcmd_lock);
++
++ switch (mcmd->state) {
++ case SCST_MCMD_STATE_INIT:
++ case SCST_MCMD_STATE_EXEC:
++ if (mcmd->cmd_done_wait_count == 0) {
++ mcmd->state = SCST_MCMD_STATE_AFFECTED_CMDS_DONE;
++ res = 0;
++ } else {
++ TRACE_MGMT_DBG("cmd_done_wait_count(%d) not 0, "
++ "preparing to wait", mcmd->cmd_done_wait_count);
++ mcmd->state = SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE;
++ res = -1;
++ }
++ break;
++
++ case SCST_MCMD_STATE_AFFECTED_CMDS_DONE:
++ if (mcmd->cmd_finish_wait_count == 0) {
++ mcmd->state = SCST_MCMD_STATE_DONE;
++ res = 0;
++ } else {
++ TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, "
++ "preparing to wait",
++ mcmd->cmd_finish_wait_count);
++ mcmd->state = SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED;
++ res = -1;
++ }
++ break;
++
++ case SCST_MCMD_STATE_DONE:
++ mcmd->state = SCST_MCMD_STATE_FINISHED;
++ res = 0;
++ break;
++
++ default:
++ PRINT_CRIT_ERROR("Wrong mcmd %p state %d (fn %d, "
++ "cmd_finish_wait_count %d, cmd_done_wait_count %d)",
++ mcmd, mcmd->state, mcmd->fn,
++ mcmd->cmd_finish_wait_count, mcmd->cmd_done_wait_count);
++ spin_unlock_irq(&scst_mcmd_lock);
++ BUG();
++ goto out;
++ }
++
++ spin_unlock_irq(&scst_mcmd_lock);
++
++out:
++ return res;
++}
++
++/* IRQs supposed to be disabled */
++static bool __scst_check_unblock_aborted_cmd(struct scst_cmd *cmd,
++ struct list_head *list_entry)
++{
++ bool res;
++ if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
++ list_del(list_entry);
++ spin_lock(&cmd->cmd_threads->cmd_list_lock);
++ list_add_tail(&cmd->cmd_list_entry,
++ &cmd->cmd_threads->active_cmd_list);
++ wake_up(&cmd->cmd_threads->cmd_list_waitQ);
++ spin_unlock(&cmd->cmd_threads->cmd_list_lock);
++ res = 1;
++ } else
++ res = 0;
++ return res;
++}
++
++static void scst_unblock_aborted_cmds(int scst_mutex_held)
++{
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ if (!scst_mutex_held)
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
++ struct scst_cmd *cmd, *tcmd;
++ struct scst_tgt_dev *tgt_dev;
++ spin_lock_bh(&dev->dev_lock);
++ local_irq_disable();
++ list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list,
++ blocked_cmd_list_entry) {
++ if (__scst_check_unblock_aborted_cmd(cmd,
++ &cmd->blocked_cmd_list_entry)) {
++ TRACE_MGMT_DBG("Unblock aborted blocked cmd %p",
++ cmd);
++ }
++ }
++ local_irq_enable();
++ spin_unlock_bh(&dev->dev_lock);
++
++ local_irq_disable();
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ spin_lock(&tgt_dev->sn_lock);
++ list_for_each_entry_safe(cmd, tcmd,
++ &tgt_dev->deferred_cmd_list,
++ sn_cmd_list_entry) {
++ if (__scst_check_unblock_aborted_cmd(cmd,
++ &cmd->sn_cmd_list_entry)) {
++ TRACE_MGMT_DBG("Unblocked aborted SN "
++ "cmd %p (sn %u)",
++ cmd, cmd->sn);
++ tgt_dev->def_cmd_count--;
++ }
++ }
++ spin_unlock(&tgt_dev->sn_lock);
++ }
++ local_irq_enable();
++ }
++
++ if (!scst_mutex_held)
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void __scst_abort_task_set(struct scst_mgmt_cmd *mcmd,
++ struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_cmd *cmd;
++ struct scst_session *sess = tgt_dev->sess;
++ bool other_ini;
++
++ TRACE_ENTRY();
++
++ if ((mcmd->fn == SCST_PR_ABORT_ALL) &&
++ (mcmd->origin_pr_cmd->sess != sess))
++ other_ini = true;
++ else
++ other_ini = false;
++
++ spin_lock_irq(&sess->sess_list_lock);
++
++ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess);
++ list_for_each_entry(cmd, &sess->sess_cmd_list,
++ sess_cmd_list_entry) {
++ if ((mcmd->fn == SCST_PR_ABORT_ALL) &&
++ (mcmd->origin_pr_cmd == cmd))
++ continue;
++ if ((cmd->tgt_dev == tgt_dev) ||
++ ((cmd->tgt_dev == NULL) &&
++ (cmd->lun == tgt_dev->lun))) {
++ if (mcmd->cmd_sn_set) {
++ BUG_ON(!cmd->tgt_sn_set);
++ if (scst_sn_before(mcmd->cmd_sn, cmd->tgt_sn) ||
++ (mcmd->cmd_sn == cmd->tgt_sn))
++ continue;
++ }
++ scst_abort_cmd(cmd, mcmd, other_ini, 0);
++ }
++ }
++ spin_unlock_irq(&sess->sess_list_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Returns 0 if the command processing should be continued, <0 otherwise */
++static int scst_abort_task_set(struct scst_mgmt_cmd *mcmd)
++{
++ int res;
++ struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev;
++
++ TRACE(TRACE_MGMT, "Aborting task set (lun=%lld, mcmd=%p)",
++ (long long unsigned int)tgt_dev->lun, mcmd);
++
++ __scst_abort_task_set(mcmd, tgt_dev);
++
++ if (mcmd->fn == SCST_PR_ABORT_ALL) {
++ struct scst_pr_abort_all_pending_mgmt_cmds_counter *pr_cnt =
++ mcmd->origin_pr_cmd->pr_abort_counter;
++ if (atomic_dec_and_test(&pr_cnt->pr_aborting_cnt))
++ complete_all(&pr_cnt->pr_aborting_cmpl);
++ }
++
++ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "ABORT TASK SET/PR ABORT", 0);
++
++ scst_unblock_aborted_cmds(0);
++
++ scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0);
++
++ res = scst_set_mcmd_next_state(mcmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_is_cmd_belongs_to_dev(struct scst_cmd *cmd,
++ struct scst_device *dev)
++{
++ struct scst_tgt_dev *tgt_dev = NULL;
++ struct list_head *sess_tgt_dev_list_head;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Finding match for dev %p and cmd %p (lun %lld)", dev, cmd,
++ (long long unsigned int)cmd->lun);
++
++ sess_tgt_dev_list_head =
++ &cmd->sess->sess_tgt_dev_list_hash[HASH_VAL(cmd->lun)];
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ if (tgt_dev->lun == cmd->lun) {
++ TRACE_DBG("dev %p found", tgt_dev->dev);
++ res = (tgt_dev->dev == dev);
++ goto out;
++ }
++ }
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/* Returns 0 if the command processing should be continued, <0 otherwise */
++static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
++{
++ int res;
++ struct scst_device *dev = mcmd->mcmd_tgt_dev->dev;
++ struct scst_tgt_dev *tgt_dev;
++ LIST_HEAD(UA_tgt_devs);
++
++ TRACE_ENTRY();
++
++ TRACE(TRACE_MGMT, "Clearing task set (lun=%lld, mcmd=%p)",
++ (long long unsigned int)mcmd->lun, mcmd);
++
++#if 0 /* we are SAM-3 */
++ /*
++ * When a logical unit is aborting one or more tasks from a SCSI
++ * initiator port with the TASK ABORTED status it should complete all
++ * of those tasks before entering additional tasks from that SCSI
++ * initiator port into the task set - SAM2
++ */
++ mcmd->needs_unblocking = 1;
++ spin_lock_bh(&dev->dev_lock);
++ scst_block_dev(dev);
++ spin_unlock_bh(&dev->dev_lock);
++#endif
++
++ __scst_abort_task_set(mcmd, mcmd->mcmd_tgt_dev);
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ struct scst_session *sess = tgt_dev->sess;
++ struct scst_cmd *cmd;
++ int aborted = 0;
++
++ if (tgt_dev == mcmd->mcmd_tgt_dev)
++ continue;
++
++ spin_lock_irq(&sess->sess_list_lock);
++
++ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess);
++ list_for_each_entry(cmd, &sess->sess_cmd_list,
++ sess_cmd_list_entry) {
++ if ((cmd->dev == dev) ||
++ ((cmd->dev == NULL) &&
++ scst_is_cmd_belongs_to_dev(cmd, dev))) {
++ scst_abort_cmd(cmd, mcmd, 1, 0);
++ aborted = 1;
++ }
++ }
++ spin_unlock_irq(&sess->sess_list_lock);
++
++ if (aborted)
++ list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
++ &UA_tgt_devs);
++ }
++
++ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "CLEAR TASK SET", 0);
++
++ scst_unblock_aborted_cmds(1);
++
++ mutex_unlock(&scst_mutex);
++
++ if (!dev->tas) {
++ uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
++ int sl;
++
++ sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
++ dev->d_sense,
++ SCST_LOAD_SENSE(scst_sense_cleared_by_another_ini_UA));
++
++ list_for_each_entry(tgt_dev, &UA_tgt_devs,
++ extra_tgt_dev_list_entry) {
++ scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
++ }
++ }
++
++ scst_call_dev_task_mgmt_fn(mcmd, mcmd->mcmd_tgt_dev, 0);
++
++ res = scst_set_mcmd_next_state(mcmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Returns 0 if the command processing should be continued,
++ * >0, if it should be requeued, <0 otherwise */
++static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
++{
++ int res = 0, rc;
++
++ TRACE_ENTRY();
++
++ switch (mcmd->fn) {
++ case SCST_ABORT_TASK:
++ {
++ struct scst_session *sess = mcmd->sess;
++ struct scst_cmd *cmd;
++
++ spin_lock_irq(&sess->sess_list_lock);
++ cmd = __scst_find_cmd_by_tag(sess, mcmd->tag, true);
++ if (cmd == NULL) {
++ TRACE_MGMT_DBG("ABORT TASK: command "
++ "for tag %llu not found",
++ (long long unsigned int)mcmd->tag);
++ mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST;
++ spin_unlock_irq(&sess->sess_list_lock);
++ res = scst_set_mcmd_next_state(mcmd);
++ goto out;
++ }
++ __scst_cmd_get(cmd);
++ spin_unlock_irq(&sess->sess_list_lock);
++ TRACE_DBG("Cmd to abort %p for tag %llu found",
++ cmd, (long long unsigned int)mcmd->tag);
++ mcmd->cmd_to_abort = cmd;
++ mcmd->state = SCST_MCMD_STATE_EXEC;
++ break;
++ }
++
++ case SCST_TARGET_RESET:
++ case SCST_NEXUS_LOSS_SESS:
++ case SCST_ABORT_ALL_TASKS_SESS:
++ case SCST_NEXUS_LOSS:
++ case SCST_ABORT_ALL_TASKS:
++ case SCST_UNREG_SESS_TM:
++ mcmd->state = SCST_MCMD_STATE_EXEC;
++ break;
++
++ case SCST_ABORT_TASK_SET:
++ case SCST_CLEAR_ACA:
++ case SCST_CLEAR_TASK_SET:
++ case SCST_LUN_RESET:
++ case SCST_PR_ABORT_ALL:
++ rc = scst_mgmt_translate_lun(mcmd);
++ if (rc == 0)
++ mcmd->state = SCST_MCMD_STATE_EXEC;
++ else if (rc < 0) {
++ PRINT_ERROR("Corresponding device for LUN %lld not "
++ "found", (long long unsigned int)mcmd->lun);
++ mcmd->status = SCST_MGMT_STATUS_LUN_NOT_EXIST;
++ res = scst_set_mcmd_next_state(mcmd);
++ } else
++ res = rc;
++ break;
++
++ default:
++ BUG();
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Returns 0 if the command processing should be continued, <0 otherwise */
++static int scst_target_reset(struct scst_mgmt_cmd *mcmd)
++{
++ int res, rc;
++ struct scst_device *dev;
++ struct scst_acg *acg = mcmd->sess->acg;
++ struct scst_acg_dev *acg_dev;
++ int cont, c;
++ LIST_HEAD(host_devs);
++
++ TRACE_ENTRY();
++
++ TRACE(TRACE_MGMT, "Target reset (mcmd %p, cmd count %d)",
++ mcmd, atomic_read(&mcmd->sess->sess_cmd_count));
++
++ mcmd->needs_unblocking = 1;
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
++ struct scst_device *d;
++ struct scst_tgt_dev *tgt_dev;
++ int found = 0;
++
++ dev = acg_dev->dev;
++
++ spin_lock_bh(&dev->dev_lock);
++ scst_block_dev(dev);
++ scst_process_reset(dev, mcmd->sess, NULL, mcmd, true);
++ spin_unlock_bh(&dev->dev_lock);
++
++ cont = 0;
++ c = 0;
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ cont = 1;
++ if (mcmd->sess == tgt_dev->sess) {
++ rc = scst_call_dev_task_mgmt_fn(mcmd,
++ tgt_dev, 0);
++ if (rc == SCST_DEV_TM_NOT_COMPLETED)
++ c = 1;
++ else if ((rc < 0) &&
++ (mcmd->status == SCST_MGMT_STATUS_SUCCESS))
++ mcmd->status = rc;
++ break;
++ }
++ }
++ if (cont && !c)
++ continue;
++
++ if (dev->scsi_dev == NULL)
++ continue;
++
++ list_for_each_entry(d, &host_devs, tm_dev_list_entry) {
++ if (dev->scsi_dev->host->host_no ==
++ d->scsi_dev->host->host_no) {
++ found = 1;
++ break;
++ }
++ }
++ if (!found)
++ list_add_tail(&dev->tm_dev_list_entry, &host_devs);
++
++ tm_dbg_task_mgmt(dev, "TARGET RESET", 0);
++ }
++
++ scst_unblock_aborted_cmds(1);
++
++ /*
++ * We suppose here that for all commands that already on devices
++ * on/after scsi_reset_provider() completion callbacks will be called.
++ */
++
++ list_for_each_entry(dev, &host_devs, tm_dev_list_entry) {
++ /* dev->scsi_dev must be non-NULL here */
++ TRACE(TRACE_MGMT, "Resetting host %d bus ",
++ dev->scsi_dev->host->host_no);
++ rc = scsi_reset_provider(dev->scsi_dev, SCSI_TRY_RESET_TARGET);
++ TRACE(TRACE_MGMT, "Result of host %d target reset: %s",
++ dev->scsi_dev->host->host_no,
++ (rc == SUCCESS) ? "SUCCESS" : "FAILED");
++#if 0
++ if ((rc != SUCCESS) &&
++ (mcmd->status == SCST_MGMT_STATUS_SUCCESS)) {
++ /*
++ * SCSI_TRY_RESET_BUS is also done by
++ * scsi_reset_provider()
++ */
++ mcmd->status = SCST_MGMT_STATUS_FAILED;
++ }
++#else
++ /*
++ * scsi_reset_provider() returns very weird status, so let's
++ * always succeed
++ */
++#endif
++ }
++
++ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
++ dev = acg_dev->dev;
++ if (dev->scsi_dev != NULL)
++ dev->scsi_dev->was_reset = 0;
++ }
++
++ mutex_unlock(&scst_mutex);
++
++ res = scst_set_mcmd_next_state(mcmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Returns 0 if the command processing should be continued, <0 otherwise */
++static int scst_lun_reset(struct scst_mgmt_cmd *mcmd)
++{
++ int res, rc;
++ struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev;
++ struct scst_device *dev = tgt_dev->dev;
++
++ TRACE_ENTRY();
++
++ TRACE(TRACE_MGMT, "Resetting LUN %lld (mcmd %p)",
++ (long long unsigned int)tgt_dev->lun, mcmd);
++
++ mcmd->needs_unblocking = 1;
++
++ spin_lock_bh(&dev->dev_lock);
++ scst_block_dev(dev);
++ scst_process_reset(dev, mcmd->sess, NULL, mcmd, true);
++ spin_unlock_bh(&dev->dev_lock);
++
++ rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 1);
++ if (rc != SCST_DEV_TM_NOT_COMPLETED)
++ goto out_tm_dbg;
++
++ if (dev->scsi_dev != NULL) {
++ TRACE(TRACE_MGMT, "Resetting host %d bus ",
++ dev->scsi_dev->host->host_no);
++ rc = scsi_reset_provider(dev->scsi_dev, SCSI_TRY_RESET_DEVICE);
++#if 0
++ if (rc != SUCCESS && mcmd->status == SCST_MGMT_STATUS_SUCCESS)
++ mcmd->status = SCST_MGMT_STATUS_FAILED;
++#else
++ /*
++ * scsi_reset_provider() returns very weird status, so let's
++ * always succeed
++ */
++#endif
++ dev->scsi_dev->was_reset = 0;
++ }
++
++ scst_unblock_aborted_cmds(0);
++
++out_tm_dbg:
++ tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "LUN RESET", 0);
++
++ res = scst_set_mcmd_next_state(mcmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* scst_mutex supposed to be held */
++static void scst_do_nexus_loss_sess(struct scst_mgmt_cmd *mcmd)
++{
++ int i;
++ struct scst_session *sess = mcmd->sess;
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ scst_nexus_loss(tgt_dev,
++ (mcmd->fn != SCST_UNREG_SESS_TM));
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Returns 0 if the command processing should be continued, <0 otherwise */
++static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
++ int nexus_loss)
++{
++ int res;
++ int i;
++ struct scst_session *sess = mcmd->sess;
++ struct scst_tgt_dev *tgt_dev;
++
++ TRACE_ENTRY();
++
++ if (nexus_loss) {
++ TRACE_MGMT_DBG("Nexus loss for sess %p (mcmd %p)",
++ sess, mcmd);
++ } else {
++ TRACE_MGMT_DBG("Aborting all from sess %p (mcmd %p)",
++ sess, mcmd);
++ }
++
++ mutex_lock(&scst_mutex);
++
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ int rc;
++
++ __scst_abort_task_set(mcmd, tgt_dev);
++
++ rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0);
++ if (rc < 0 && mcmd->status == SCST_MGMT_STATUS_SUCCESS)
++ mcmd->status = rc;
++
++ tm_dbg_task_mgmt(tgt_dev->dev, "NEXUS LOSS SESS or "
++ "ABORT ALL SESS or UNREG SESS",
++ (mcmd->fn == SCST_UNREG_SESS_TM));
++ }
++ }
++
++ scst_unblock_aborted_cmds(1);
++
++ mutex_unlock(&scst_mutex);
++
++ res = scst_set_mcmd_next_state(mcmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* scst_mutex supposed to be held */
++static void scst_do_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd)
++{
++ int i;
++ struct scst_tgt *tgt = mcmd->sess->tgt;
++ struct scst_session *sess;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ scst_nexus_loss(tgt_dev, true);
++ }
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
++ int nexus_loss)
++{
++ int res;
++ int i;
++ struct scst_tgt *tgt = mcmd->sess->tgt;
++ struct scst_session *sess;
++
++ TRACE_ENTRY();
++
++ if (nexus_loss) {
++ TRACE_MGMT_DBG("I_T Nexus loss (tgt %p, mcmd %p)",
++ tgt, mcmd);
++ } else {
++ TRACE_MGMT_DBG("Aborting all from tgt %p (mcmd %p)",
++ tgt, mcmd);
++ }
++
++ mutex_lock(&scst_mutex);
++
++ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
++ for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[i];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ int rc;
++
++ __scst_abort_task_set(mcmd, tgt_dev);
++
++ if (nexus_loss)
++ scst_nexus_loss(tgt_dev, true);
++
++ if (mcmd->sess == tgt_dev->sess) {
++ rc = scst_call_dev_task_mgmt_fn(
++ mcmd, tgt_dev, 0);
++ if ((rc < 0) &&
++ (mcmd->status == SCST_MGMT_STATUS_SUCCESS))
++ mcmd->status = rc;
++ }
++
++ tm_dbg_task_mgmt(tgt_dev->dev, "NEXUS LOSS or "
++ "ABORT ALL", 0);
++ }
++ }
++ }
++
++ scst_unblock_aborted_cmds(1);
++
++ mutex_unlock(&scst_mutex);
++
++ res = scst_set_mcmd_next_state(mcmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_abort_task(struct scst_mgmt_cmd *mcmd)
++{
++ int res;
++ struct scst_cmd *cmd = mcmd->cmd_to_abort;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Abortind task (cmd %p, sn %d, set %d, tag %llu, "
++ "queue_type %x)", cmd, cmd->sn, cmd->sn_set,
++ (long long unsigned int)mcmd->tag, cmd->queue_type);
++
++ if (mcmd->lun_set && (mcmd->lun != cmd->lun)) {
++ PRINT_ERROR("ABORT TASK: LUN mismatch: mcmd LUN %llx, "
++ "cmd LUN %llx, cmd tag %llu",
++ (long long unsigned int)mcmd->lun,
++ (long long unsigned int)cmd->lun,
++ (long long unsigned int)mcmd->tag);
++ mcmd->status = SCST_MGMT_STATUS_REJECTED;
++ } else if (mcmd->cmd_sn_set &&
++ (scst_sn_before(mcmd->cmd_sn, cmd->tgt_sn) ||
++ (mcmd->cmd_sn == cmd->tgt_sn))) {
++ PRINT_ERROR("ABORT TASK: SN mismatch: mcmd SN %x, "
++ "cmd SN %x, cmd tag %llu", mcmd->cmd_sn,
++ cmd->tgt_sn, (long long unsigned int)mcmd->tag);
++ mcmd->status = SCST_MGMT_STATUS_REJECTED;
++ } else {
++ scst_abort_cmd(cmd, mcmd, 0, 1);
++ scst_unblock_aborted_cmds(0);
++ }
++
++ res = scst_set_mcmd_next_state(mcmd);
++
++ mcmd->cmd_to_abort = NULL; /* just in case */
++
++ __scst_cmd_put(cmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Returns 0 if the command processing should be continued, <0 otherwise */
++static int scst_mgmt_cmd_exec(struct scst_mgmt_cmd *mcmd)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ mcmd->status = SCST_MGMT_STATUS_SUCCESS;
++
++ switch (mcmd->fn) {
++ case SCST_ABORT_TASK:
++ res = scst_abort_task(mcmd);
++ break;
++
++ case SCST_ABORT_TASK_SET:
++ case SCST_PR_ABORT_ALL:
++ res = scst_abort_task_set(mcmd);
++ break;
++
++ case SCST_CLEAR_TASK_SET:
++ if (mcmd->mcmd_tgt_dev->dev->tst ==
++ SCST_CONTR_MODE_SEP_TASK_SETS)
++ res = scst_abort_task_set(mcmd);
++ else
++ res = scst_clear_task_set(mcmd);
++ break;
++
++ case SCST_LUN_RESET:
++ res = scst_lun_reset(mcmd);
++ break;
++
++ case SCST_TARGET_RESET:
++ res = scst_target_reset(mcmd);
++ break;
++
++ case SCST_ABORT_ALL_TASKS_SESS:
++ res = scst_abort_all_nexus_loss_sess(mcmd, 0);
++ break;
++
++ case SCST_NEXUS_LOSS_SESS:
++ case SCST_UNREG_SESS_TM:
++ res = scst_abort_all_nexus_loss_sess(mcmd, 1);
++ break;
++
++ case SCST_ABORT_ALL_TASKS:
++ res = scst_abort_all_nexus_loss_tgt(mcmd, 0);
++ break;
++
++ case SCST_NEXUS_LOSS:
++ res = scst_abort_all_nexus_loss_tgt(mcmd, 1);
++ break;
++
++ case SCST_CLEAR_ACA:
++ if (scst_call_dev_task_mgmt_fn(mcmd, mcmd->mcmd_tgt_dev, 1) ==
++ SCST_DEV_TM_NOT_COMPLETED) {
++ mcmd->status = SCST_MGMT_STATUS_FN_NOT_SUPPORTED;
++ /* Nothing to do (yet) */
++ }
++ goto out_done;
++
++ default:
++ PRINT_ERROR("Unknown task management function %d", mcmd->fn);
++ mcmd->status = SCST_MGMT_STATUS_REJECTED;
++ goto out_done;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_done:
++ res = scst_set_mcmd_next_state(mcmd);
++ goto out;
++}
++
++static void scst_call_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd)
++{
++ struct scst_session *sess = mcmd->sess;
++
++ if ((sess->tgt->tgtt->task_mgmt_affected_cmds_done != NULL) &&
++ (mcmd->fn != SCST_UNREG_SESS_TM) &&
++ (mcmd->fn != SCST_PR_ABORT_ALL)) {
++ TRACE_DBG("Calling target %s task_mgmt_affected_cmds_done(%p)",
++ sess->tgt->tgtt->name, sess);
++ sess->tgt->tgtt->task_mgmt_affected_cmds_done(mcmd);
++ TRACE_MGMT_DBG("Target's %s task_mgmt_affected_cmds_done() "
++ "returned", sess->tgt->tgtt->name);
++ }
++ return;
++}
++
++static int scst_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ switch (mcmd->fn) {
++ case SCST_NEXUS_LOSS_SESS:
++ case SCST_UNREG_SESS_TM:
++ scst_do_nexus_loss_sess(mcmd);
++ break;
++
++ case SCST_NEXUS_LOSS:
++ scst_do_nexus_loss_tgt(mcmd);
++ break;
++ }
++
++ mutex_unlock(&scst_mutex);
++
++ scst_call_task_mgmt_affected_cmds_done(mcmd);
++
++ res = scst_set_mcmd_next_state(mcmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
++{
++ struct scst_device *dev;
++ struct scst_session *sess = mcmd->sess;
++
++ TRACE_ENTRY();
++
++ mcmd->state = SCST_MCMD_STATE_FINISHED;
++ if (scst_is_strict_mgmt_fn(mcmd->fn) && (mcmd->completed_cmd_count > 0))
++ mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST;
++
++ if (mcmd->fn < SCST_UNREG_SESS_TM)
++ TRACE(TRACE_MGMT, "TM fn %d finished, "
++ "status %x", mcmd->fn, mcmd->status);
++ else
++ TRACE_MGMT_DBG("TM fn %d finished, "
++ "status %x", mcmd->fn, mcmd->status);
++
++ if (mcmd->fn == SCST_PR_ABORT_ALL) {
++ mcmd->origin_pr_cmd->scst_cmd_done(mcmd->origin_pr_cmd,
++ SCST_CMD_STATE_DEFAULT,
++ SCST_CONTEXT_THREAD);
++ } else if ((sess->tgt->tgtt->task_mgmt_fn_done != NULL) &&
++ (mcmd->fn != SCST_UNREG_SESS_TM)) {
++ TRACE_DBG("Calling target %s task_mgmt_fn_done(%p)",
++ sess->tgt->tgtt->name, sess);
++ sess->tgt->tgtt->task_mgmt_fn_done(mcmd);
++ TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() "
++ "returned", sess->tgt->tgtt->name);
++ }
++
++ if (mcmd->needs_unblocking) {
++ switch (mcmd->fn) {
++ case SCST_LUN_RESET:
++ case SCST_CLEAR_TASK_SET:
++ scst_unblock_dev(mcmd->mcmd_tgt_dev->dev);
++ break;
++
++ case SCST_TARGET_RESET:
++ {
++ struct scst_acg *acg = mcmd->sess->acg;
++ struct scst_acg_dev *acg_dev;
++
++ mutex_lock(&scst_mutex);
++ list_for_each_entry(acg_dev, &acg->acg_dev_list,
++ acg_dev_list_entry) {
++ dev = acg_dev->dev;
++ scst_unblock_dev(dev);
++ }
++ mutex_unlock(&scst_mutex);
++ break;
++ }
++
++ default:
++ BUG();
++ break;
++ }
++ }
++
++ mcmd->tgt_priv = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Returns >0, if cmd should be requeued */
++static int scst_process_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /*
++ * We are in the TM thread and mcmd->state guaranteed to not be
++ * changed behind us.
++ */
++
++ TRACE_DBG("mcmd %p, state %d", mcmd, mcmd->state);
++
++ while (1) {
++ switch (mcmd->state) {
++ case SCST_MCMD_STATE_INIT:
++ res = scst_mgmt_cmd_init(mcmd);
++ if (res)
++ goto out;
++ break;
++
++ case SCST_MCMD_STATE_EXEC:
++ if (scst_mgmt_cmd_exec(mcmd))
++ goto out;
++ break;
++
++ case SCST_MCMD_STATE_AFFECTED_CMDS_DONE:
++ if (scst_mgmt_affected_cmds_done(mcmd))
++ goto out;
++ break;
++
++ case SCST_MCMD_STATE_DONE:
++ scst_mgmt_cmd_send_done(mcmd);
++ break;
++
++ case SCST_MCMD_STATE_FINISHED:
++ scst_free_mgmt_cmd(mcmd);
++ /* mcmd is dead */
++ goto out;
++
++ default:
++ PRINT_CRIT_ERROR("Wrong mcmd %p state %d (fn %d, "
++ "cmd_finish_wait_count %d, cmd_done_wait_count "
++ "%d)", mcmd, mcmd->state, mcmd->fn,
++ mcmd->cmd_finish_wait_count,
++ mcmd->cmd_done_wait_count);
++ BUG();
++ res = -1;
++ goto out;
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static inline int test_mgmt_cmd_list(void)
++{
++ int res = !list_empty(&scst_active_mgmt_cmd_list) ||
++ unlikely(kthread_should_stop());
++ return res;
++}
++
++int scst_tm_thread(void *arg)
++{
++ TRACE_ENTRY();
++
++ PRINT_INFO("Task management thread started, PID %d", current->pid);
++
++ current->flags |= PF_NOFREEZE;
++
++ set_user_nice(current, -10);
++
++ spin_lock_irq(&scst_mcmd_lock);
++ while (!kthread_should_stop()) {
++ wait_queue_t wait;
++ init_waitqueue_entry(&wait, current);
++
++ if (!test_mgmt_cmd_list()) {
++ add_wait_queue_exclusive(&scst_mgmt_cmd_list_waitQ,
++ &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_mgmt_cmd_list())
++ break;
++ spin_unlock_irq(&scst_mcmd_lock);
++ schedule();
++ spin_lock_irq(&scst_mcmd_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&scst_mgmt_cmd_list_waitQ, &wait);
++ }
++
++ while (!list_empty(&scst_active_mgmt_cmd_list)) {
++ int rc;
++ struct scst_mgmt_cmd *mcmd;
++ mcmd = list_entry(scst_active_mgmt_cmd_list.next,
++ typeof(*mcmd), mgmt_cmd_list_entry);
++ TRACE_MGMT_DBG("Deleting mgmt cmd %p from active cmd "
++ "list", mcmd);
++ list_del(&mcmd->mgmt_cmd_list_entry);
++ spin_unlock_irq(&scst_mcmd_lock);
++ rc = scst_process_mgmt_cmd(mcmd);
++ spin_lock_irq(&scst_mcmd_lock);
++ if (rc > 0) {
++ if (test_bit(SCST_FLAG_SUSPENDED, &scst_flags) &&
++ !test_bit(SCST_FLAG_SUSPENDING,
++ &scst_flags)) {
++ TRACE_MGMT_DBG("Adding mgmt cmd %p to "
++ "head of delayed mgmt cmd list",
++ mcmd);
++ list_add(&mcmd->mgmt_cmd_list_entry,
++ &scst_delayed_mgmt_cmd_list);
++ } else {
++ TRACE_MGMT_DBG("Adding mgmt cmd %p to "
++ "head of active mgmt cmd list",
++ mcmd);
++ list_add(&mcmd->mgmt_cmd_list_entry,
++ &scst_active_mgmt_cmd_list);
++ }
++ }
++ }
++ }
++ spin_unlock_irq(&scst_mcmd_lock);
++
++ /*
++ * If kthread_should_stop() is true, we are guaranteed to be
++ * on the module unload, so scst_active_mgmt_cmd_list must be empty.
++ */
++ BUG_ON(!list_empty(&scst_active_mgmt_cmd_list));
++
++ PRINT_INFO("Task management thread PID %d finished", current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static struct scst_mgmt_cmd *scst_pre_rx_mgmt_cmd(struct scst_session
++ *sess, int fn, int atomic, void *tgt_priv)
++{
++ struct scst_mgmt_cmd *mcmd = NULL;
++
++ TRACE_ENTRY();
++
++ if (unlikely(sess->tgt->tgtt->task_mgmt_fn_done == NULL)) {
++ PRINT_ERROR("New mgmt cmd, but task_mgmt_fn_done() is NULL "
++ "(target %s)", sess->tgt->tgtt->name);
++ goto out;
++ }
++
++ mcmd = scst_alloc_mgmt_cmd(atomic ? GFP_ATOMIC : GFP_KERNEL);
++ if (mcmd == NULL) {
++ PRINT_CRIT_ERROR("Lost TM fn %d, initiator %s", fn,
++ sess->initiator_name);
++ goto out;
++ }
++
++ mcmd->sess = sess;
++ mcmd->fn = fn;
++ mcmd->state = SCST_MCMD_STATE_INIT;
++ mcmd->tgt_priv = tgt_priv;
++
++ if (fn == SCST_PR_ABORT_ALL) {
++ atomic_inc(&mcmd->origin_pr_cmd->pr_abort_counter->pr_abort_pending_cnt);
++ atomic_inc(&mcmd->origin_pr_cmd->pr_abort_counter->pr_aborting_cnt);
++ }
++
++out:
++ TRACE_EXIT();
++ return mcmd;
++}
++
++static int scst_post_rx_mgmt_cmd(struct scst_session *sess,
++ struct scst_mgmt_cmd *mcmd)
++{
++ unsigned long flags;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ scst_sess_get(sess);
++
++ if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) {
++ PRINT_CRIT_ERROR("New mgmt cmd while shutting down the "
++ "session %p shut_phase %ld", sess, sess->shut_phase);
++ BUG();
++ }
++
++ local_irq_save(flags);
++
++ spin_lock(&sess->sess_list_lock);
++ atomic_inc(&sess->sess_cmd_count);
++
++ if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) {
++ switch (sess->init_phase) {
++ case SCST_SESS_IPH_INITING:
++ TRACE_DBG("Adding mcmd %p to init deferred mcmd list",
++ mcmd);
++ list_add_tail(&mcmd->mgmt_cmd_list_entry,
++ &sess->init_deferred_mcmd_list);
++ goto out_unlock;
++ case SCST_SESS_IPH_SUCCESS:
++ break;
++ case SCST_SESS_IPH_FAILED:
++ res = -1;
++ goto out_unlock;
++ default:
++ BUG();
++ }
++ }
++
++ spin_unlock(&sess->sess_list_lock);
++
++ TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd list", mcmd);
++ spin_lock(&scst_mcmd_lock);
++ list_add_tail(&mcmd->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list);
++ spin_unlock(&scst_mcmd_lock);
++
++ local_irq_restore(flags);
++
++ wake_up(&scst_mgmt_cmd_list_waitQ);
++
++out:
++ TRACE_EXIT();
++ return res;
++
++out_unlock:
++ spin_unlock(&sess->sess_list_lock);
++ local_irq_restore(flags);
++ goto out;
++}
++
++/**
++ * scst_rx_mgmt_fn() - create new management command and send it for execution
++ *
++ * Description:
++ * Creates new management command and sends it for execution.
++ *
++ * Returns 0 for success, error code otherwise.
++ *
++ * Must not be called in parallel with scst_unregister_session() for the
++ * same sess.
++ */
++int scst_rx_mgmt_fn(struct scst_session *sess,
++ const struct scst_rx_mgmt_params *params)
++{
++ int res = -EFAULT;
++ struct scst_mgmt_cmd *mcmd = NULL;
++
++ TRACE_ENTRY();
++
++ switch (params->fn) {
++ case SCST_ABORT_TASK:
++ BUG_ON(!params->tag_set);
++ break;
++ case SCST_TARGET_RESET:
++ case SCST_ABORT_ALL_TASKS:
++ case SCST_NEXUS_LOSS:
++ break;
++ default:
++ BUG_ON(!params->lun_set);
++ }
++
++ mcmd = scst_pre_rx_mgmt_cmd(sess, params->fn, params->atomic,
++ params->tgt_priv);
++ if (mcmd == NULL)
++ goto out;
++
++ if (params->lun_set) {
++ mcmd->lun = scst_unpack_lun(params->lun, params->lun_len);
++ if (mcmd->lun == NO_SUCH_LUN)
++ goto out_free;
++ mcmd->lun_set = 1;
++ }
++
++ if (params->tag_set)
++ mcmd->tag = params->tag;
++
++ mcmd->cmd_sn_set = params->cmd_sn_set;
++ mcmd->cmd_sn = params->cmd_sn;
++
++ if (params->fn < SCST_UNREG_SESS_TM)
++ TRACE(TRACE_MGMT, "TM fn %d", params->fn);
++ else
++ TRACE_MGMT_DBG("TM fn %d", params->fn);
++
++ TRACE_MGMT_DBG("sess=%p, tag_set %d, tag %lld, lun_set %d, "
++ "lun=%lld, cmd_sn_set %d, cmd_sn %d, priv %p", sess,
++ params->tag_set,
++ (long long unsigned int)params->tag,
++ params->lun_set,
++ (long long unsigned int)mcmd->lun,
++ params->cmd_sn_set,
++ params->cmd_sn,
++ params->tgt_priv);
++
++ if (scst_post_rx_mgmt_cmd(sess, mcmd) != 0)
++ goto out_free;
++
++ res = 0;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ scst_free_mgmt_cmd(mcmd);
++ mcmd = NULL;
++ goto out;
++}
++EXPORT_SYMBOL(scst_rx_mgmt_fn);
++
++/*
++ * Written by Jack Handy - jakkhandy@hotmail.com
++ * Taken by Gennadiy Nerubayev <parakie@gmail.com> from
++ * http://www.codeproject.com/KB/string/wildcmp.aspx. No license attached
++ * to it, and it's posted on a free site; assumed to be free for use.
++ *
++ * Added the negative sign support - VLNB
++ *
++ * Also see comment for wildcmp().
++ *
++ * User space part of iSCSI-SCST also has a copy of this code, so fixing a bug
++ * here, don't forget to fix the copy too!
++ */
++static bool __wildcmp(const char *wild, const char *string, int recursion_level)
++{
++ const char *cp = NULL, *mp = NULL;
++
++ while ((*string) && (*wild != '*')) {
++ if ((*wild == '!') && (recursion_level == 0))
++ return !__wildcmp(++wild, string, ++recursion_level);
++
++ if ((*wild != *string) && (*wild != '?'))
++ return false;
++
++ wild++;
++ string++;
++ }
++
++ while (*string) {
++ if ((*wild == '!') && (recursion_level == 0))
++ return !__wildcmp(++wild, string, ++recursion_level);
++
++ if (*wild == '*') {
++ if (!*++wild)
++ return true;
++
++ mp = wild;
++ cp = string+1;
++ } else if ((*wild == *string) || (*wild == '?')) {
++ wild++;
++ string++;
++ } else {
++ wild = mp;
++ string = cp++;
++ }
++ }
++
++ while (*wild == '*')
++ wild++;
++
++ return !*wild;
++}
++
++/*
++ * Returns true if string "string" matches pattern "wild", false otherwise.
++ * Pattern is a regular DOS-type pattern, containing '*' and '?' symbols.
++ * '*' means match all any symbols, '?' means match only any single symbol.
++ *
++ * For instance:
++ * if (wildcmp("bl?h.*", "blah.jpg")) {
++ * // match
++ * } else {
++ * // no match
++ * }
++ *
++ * Also it supports boolean inversion sign '!', which does boolean inversion of
++ * the value of the rest of the string. Only one '!' allowed in the pattern,
++ * other '!' are treated as regular symbols. For instance:
++ * if (wildcmp("bl!?h.*", "blah.jpg")) {
++ * // no match
++ * } else {
++ * // match
++ * }
++ *
++ * Also see comment for __wildcmp().
++ */
++static bool wildcmp(const char *wild, const char *string)
++{
++ return __wildcmp(wild, string, 0);
++}
++
++/* scst_mutex supposed to be held */
++static struct scst_acg *scst_find_tgt_acg_by_name_wild(struct scst_tgt *tgt,
++ const char *initiator_name)
++{
++ struct scst_acg *acg, *res = NULL;
++ struct scst_acn *n;
++
++ TRACE_ENTRY();
++
++ if (initiator_name == NULL)
++ goto out;
++
++ list_for_each_entry(acg, &tgt->tgt_acg_list, acg_list_entry) {
++ list_for_each_entry(n, &acg->acn_list, acn_list_entry) {
++ if (wildcmp(n->name, initiator_name)) {
++ TRACE_DBG("Access control group %s found",
++ acg->acg_name);
++ res = acg;
++ goto out;
++ }
++ }
++ }
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/* Must be called under scst_mutex */
++static struct scst_acg *__scst_find_acg(struct scst_tgt *tgt,
++ const char *initiator_name)
++{
++ struct scst_acg *acg = NULL;
++
++ TRACE_ENTRY();
++
++ acg = scst_find_tgt_acg_by_name_wild(tgt, initiator_name);
++ if (acg == NULL)
++ acg = tgt->default_acg;
++
++ TRACE_EXIT_HRES((unsigned long)acg);
++ return acg;
++}
++
++/* Must be called under scst_mutex */
++struct scst_acg *scst_find_acg(const struct scst_session *sess)
++{
++ return __scst_find_acg(sess->tgt, sess->initiator_name);
++}
++
++/**
++ * scst_initiator_has_luns() - check if this initiator will see any LUNs
++ *
++ * Checks if this initiator will see any LUNs upon connect to this target.
++ * Returns true if yes and false otherwise.
++ */
++bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name)
++{
++ bool res;
++ struct scst_acg *acg;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ acg = __scst_find_acg(tgt, initiator_name);
++
++ res = !list_empty(&acg->acg_dev_list);
++
++ mutex_unlock(&scst_mutex);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_initiator_has_luns);
++
++static int scst_init_session(struct scst_session *sess)
++{
++ int res = 0;
++ struct scst_cmd *cmd;
++ struct scst_mgmt_cmd *mcmd, *tm;
++ int mwake = 0;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_mutex);
++
++ sess->acg = scst_find_acg(sess);
++
++ PRINT_INFO("Using security group \"%s\" for initiator \"%s\"",
++ sess->acg->acg_name, sess->initiator_name);
++
++ list_add_tail(&sess->acg_sess_list_entry, &sess->acg->acg_sess_list);
++
++ TRACE_DBG("Adding sess %p to tgt->sess_list", sess);
++ list_add_tail(&sess->sess_list_entry, &sess->tgt->sess_list);
++
++ if (sess->tgt->tgtt->get_initiator_port_transport_id != NULL) {
++ res = sess->tgt->tgtt->get_initiator_port_transport_id(sess,
++ &sess->transport_id);
++ if (res != 0) {
++ PRINT_ERROR("Unable to make initiator %s port "
++ "transport id", sess->initiator_name);
++ goto failed;
++ }
++ TRACE_PR("sess %p (ini %s), transport id %s/%d", sess,
++ sess->initiator_name,
++ debug_transport_id_to_initiator_name(
++ sess->transport_id), sess->tgt->rel_tgt_id);
++ }
++
++ res = scst_sess_sysfs_create(sess);
++ if (res != 0)
++ goto failed;
++
++ /*
++ * scst_sess_alloc_tgt_devs() must be called after session added in the
++ * sess_list to not race with scst_check_reassign_sess()!
++ */
++ res = scst_sess_alloc_tgt_devs(sess);
++
++failed:
++ mutex_unlock(&scst_mutex);
++
++ if (sess->init_result_fn) {
++ TRACE_DBG("Calling init_result_fn(%p)", sess);
++ sess->init_result_fn(sess, sess->reg_sess_data, res);
++ TRACE_DBG("%s", "init_result_fn() returned");
++ }
++
++ spin_lock_irq(&sess->sess_list_lock);
++
++ if (res == 0)
++ sess->init_phase = SCST_SESS_IPH_SUCCESS;
++ else
++ sess->init_phase = SCST_SESS_IPH_FAILED;
++
++restart:
++ list_for_each_entry(cmd, &sess->init_deferred_cmd_list,
++ cmd_list_entry) {
++ TRACE_DBG("Deleting cmd %p from init deferred cmd list", cmd);
++ list_del(&cmd->cmd_list_entry);
++ atomic_dec(&sess->sess_cmd_count);
++ spin_unlock_irq(&sess->sess_list_lock);
++ scst_cmd_init_done(cmd, SCST_CONTEXT_THREAD);
++ spin_lock_irq(&sess->sess_list_lock);
++ goto restart;
++ }
++
++ spin_lock(&scst_mcmd_lock);
++ list_for_each_entry_safe(mcmd, tm, &sess->init_deferred_mcmd_list,
++ mgmt_cmd_list_entry) {
++ TRACE_DBG("Moving mgmt command %p from init deferred mcmd list",
++ mcmd);
++ list_move_tail(&mcmd->mgmt_cmd_list_entry,
++ &scst_active_mgmt_cmd_list);
++ mwake = 1;
++ }
++
++ spin_unlock(&scst_mcmd_lock);
++ /*
++ * In case of an error at this point the caller target driver supposed
++ * to already call this sess's unregistration.
++ */
++ sess->init_phase = SCST_SESS_IPH_READY;
++ spin_unlock_irq(&sess->sess_list_lock);
++
++ if (mwake)
++ wake_up(&scst_mgmt_cmd_list_waitQ);
++
++ scst_sess_put(sess);
++
++ TRACE_EXIT();
++ return res;
++}
++
++/**
++ * scst_register_session() - register session
++ * @tgt: target
++ * @atomic: true, if the function called in the atomic context. If false,
++ * this function will block until the session registration is
++ * completed.
++ * @initiator_name: remote initiator's name, any NULL-terminated string,
++ * e.g. iSCSI name, which used as the key to found appropriate
++ * access control group. Could be NULL, then the default
++ * target's LUNs are used.
++ * @tgt_priv: pointer to target driver's private data
++ * @result_fn_data: any target driver supplied data
++ * @result_fn: pointer to the function that will be asynchronously called
++ * when session initialization finishes.
++ * Can be NULL. Parameters:
++ * - sess - session
++ * - data - target driver supplied to scst_register_session()
++ * data
++ * - result - session initialization result, 0 on success or
++ * appropriate error code otherwise
++ *
++ * Description:
++ * Registers new session. Returns new session on success or NULL otherwise.
++ *
++ * Note: A session creation and initialization is a complex task,
++ * which requires sleeping state, so it can't be fully done
++ * in interrupt context. Therefore the "bottom half" of it, if
++ * scst_register_session() is called from atomic context, will be
++ * done in SCST thread context. In this case scst_register_session()
++ * will return not completely initialized session, but the target
++ * driver can supply commands to this session via scst_rx_cmd().
++ * Those commands processing will be delayed inside SCST until
++ * the session initialization is finished, then their processing
++ * will be restarted. The target driver will be notified about
++ * finish of the session initialization by function result_fn().
++ * On success the target driver could do nothing, but if the
++ * initialization fails, the target driver must ensure that
++ * no more new commands being sent or will be sent to SCST after
++ * result_fn() returns. All already sent to SCST commands for
++ * failed session will be returned in xmit_response() with BUSY status.
++ * In case of failure the driver shall call scst_unregister_session()
++ * inside result_fn(), it will NOT be called automatically.
++ */
++struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
++ const char *initiator_name, void *tgt_priv, void *result_fn_data,
++ void (*result_fn) (struct scst_session *sess, void *data, int result))
++{
++ struct scst_session *sess;
++ int res;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ sess = scst_alloc_session(tgt, atomic ? GFP_ATOMIC : GFP_KERNEL,
++ initiator_name);
++ if (sess == NULL)
++ goto out;
++
++ scst_sess_set_tgt_priv(sess, tgt_priv);
++
++ scst_sess_get(sess); /* one for registered session */
++ scst_sess_get(sess); /* one held until sess is inited */
++
++ if (atomic) {
++ sess->reg_sess_data = result_fn_data;
++ sess->init_result_fn = result_fn;
++ spin_lock_irqsave(&scst_mgmt_lock, flags);
++ TRACE_DBG("Adding sess %p to scst_sess_init_list", sess);
++ list_add_tail(&sess->sess_init_list_entry,
++ &scst_sess_init_list);
++ spin_unlock_irqrestore(&scst_mgmt_lock, flags);
++ wake_up(&scst_mgmt_waitQ);
++ } else {
++ res = scst_init_session(sess);
++ if (res != 0)
++ goto out_free;
++ }
++
++out:
++ TRACE_EXIT();
++ return sess;
++
++out_free:
++ scst_free_session(sess);
++ sess = NULL;
++ goto out;
++}
++EXPORT_SYMBOL_GPL(scst_register_session);
++
++/**
++ * scst_register_session_non_gpl() - register session (non-GPL version)
++ * @tgt: target
++ * @initiator_name: remote initiator's name, any NULL-terminated string,
++ * e.g. iSCSI name, which used as the key to found appropriate
++ * access control group. Could be NULL, then the default
++ * target's LUNs are used.
++ * @tgt_priv: pointer to target driver's private data
++ *
++ * Description:
++ * Registers new session. Returns new session on success or NULL otherwise.
++ */
++struct scst_session *scst_register_session_non_gpl(struct scst_tgt *tgt,
++ const char *initiator_name, void *tgt_priv)
++{
++ return scst_register_session(tgt, 0, initiator_name, tgt_priv,
++ NULL, NULL);
++}
++EXPORT_SYMBOL(scst_register_session_non_gpl);
++
++/**
++ * scst_unregister_session() - unregister session
++ * @sess: session to be unregistered
++ * @wait: if true, instructs to wait until all commands, which
++ * currently is being executed and belonged to the session,
++ * finished. Otherwise, target driver should be prepared to
++ * receive xmit_response() for the session's command after
++ * scst_unregister_session() returns.
++ * @unreg_done_fn: pointer to the function that will be asynchronously called
++ * when the last session's command finishes and
++ * the session is about to be completely freed. Can be NULL.
++ * Parameter:
++ * - sess - session
++ *
++ * Unregisters session.
++ *
++ * Notes:
++ * - All outstanding commands will be finished regularly. After
++ * scst_unregister_session() returned, no new commands must be sent to
++ * SCST via scst_rx_cmd().
++ *
++ * - The caller must ensure that no scst_rx_cmd() or scst_rx_mgmt_fn_*() is
++ * called in paralell with scst_unregister_session().
++ *
++ * - Can be called before result_fn() of scst_register_session() called,
++ * i.e. during the session registration/initialization.
++ *
++ * - It is highly recommended to call scst_unregister_session() as soon as it
++ * gets clear that session will be unregistered and not to wait until all
++ * related commands finished. This function provides the wait functionality,
++ * but it also starts recovering stuck commands, if there are any.
++ * Otherwise, your target driver could wait for those commands forever.
++ */
++void scst_unregister_session(struct scst_session *sess, int wait,
++ void (*unreg_done_fn) (struct scst_session *sess))
++{
++ unsigned long flags;
++ DECLARE_COMPLETION_ONSTACK(c);
++ int rc, lun;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Unregistering session %p (wait %d)", sess, wait);
++
++ sess->unreg_done_fn = unreg_done_fn;
++
++ /* Abort all outstanding commands and clear reservation, if necessary */
++ lun = 0;
++ rc = scst_rx_mgmt_fn_lun(sess, SCST_UNREG_SESS_TM,
++ (uint8_t *)&lun, sizeof(lun), SCST_ATOMIC, NULL);
++ if (rc != 0) {
++ PRINT_ERROR("SCST_UNREG_SESS_TM failed %d (sess %p)",
++ rc, sess);
++ }
++
++ sess->shut_phase = SCST_SESS_SPH_SHUTDOWN;
++
++ spin_lock_irqsave(&scst_mgmt_lock, flags);
++
++ if (wait)
++ sess->shutdown_compl = &c;
++
++ spin_unlock_irqrestore(&scst_mgmt_lock, flags);
++
++ scst_sess_put(sess);
++
++ if (wait) {
++ TRACE_DBG("Waiting for session %p to complete", sess);
++ wait_for_completion(&c);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_unregister_session);
++
++/**
++ * scst_unregister_session_non_gpl() - unregister session, non-GPL version
++ * @sess: session to be unregistered
++ *
++ * Unregisters session.
++ *
++ * See notes for scst_unregister_session() above.
++ */
++void scst_unregister_session_non_gpl(struct scst_session *sess)
++{
++ TRACE_ENTRY();
++
++ scst_unregister_session(sess, 1, NULL);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL(scst_unregister_session_non_gpl);
++
++static inline int test_mgmt_list(void)
++{
++ int res = !list_empty(&scst_sess_init_list) ||
++ !list_empty(&scst_sess_shut_list) ||
++ unlikely(kthread_should_stop());
++ return res;
++}
++
++int scst_global_mgmt_thread(void *arg)
++{
++ struct scst_session *sess;
++
++ TRACE_ENTRY();
++
++ PRINT_INFO("Management thread started, PID %d", current->pid);
++
++ current->flags |= PF_NOFREEZE;
++
++ set_user_nice(current, -10);
++
++ spin_lock_irq(&scst_mgmt_lock);
++ while (!kthread_should_stop()) {
++ wait_queue_t wait;
++ init_waitqueue_entry(&wait, current);
++
++ if (!test_mgmt_list()) {
++ add_wait_queue_exclusive(&scst_mgmt_waitQ, &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_mgmt_list())
++ break;
++ spin_unlock_irq(&scst_mgmt_lock);
++ schedule();
++ spin_lock_irq(&scst_mgmt_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&scst_mgmt_waitQ, &wait);
++ }
++
++ while (!list_empty(&scst_sess_init_list)) {
++ sess = list_entry(scst_sess_init_list.next,
++ typeof(*sess), sess_init_list_entry);
++ TRACE_DBG("Removing sess %p from scst_sess_init_list",
++ sess);
++ list_del(&sess->sess_init_list_entry);
++ spin_unlock_irq(&scst_mgmt_lock);
++
++ if (sess->init_phase == SCST_SESS_IPH_INITING)
++ scst_init_session(sess);
++ else {
++ PRINT_CRIT_ERROR("session %p is in "
++ "scst_sess_init_list, but in unknown "
++ "init phase %x", sess,
++ sess->init_phase);
++ BUG();
++ }
++
++ spin_lock_irq(&scst_mgmt_lock);
++ }
++
++ while (!list_empty(&scst_sess_shut_list)) {
++ sess = list_entry(scst_sess_shut_list.next,
++ typeof(*sess), sess_shut_list_entry);
++ TRACE_DBG("Removing sess %p from scst_sess_shut_list",
++ sess);
++ list_del(&sess->sess_shut_list_entry);
++ spin_unlock_irq(&scst_mgmt_lock);
++
++ switch (sess->shut_phase) {
++ case SCST_SESS_SPH_SHUTDOWN:
++ BUG_ON(atomic_read(&sess->refcnt) != 0);
++ scst_free_session_callback(sess);
++ break;
++ default:
++ PRINT_CRIT_ERROR("session %p is in "
++ "scst_sess_shut_list, but in unknown "
++ "shut phase %lx", sess,
++ sess->shut_phase);
++ BUG();
++ break;
++ }
++
++ spin_lock_irq(&scst_mgmt_lock);
++ }
++ }
++ spin_unlock_irq(&scst_mgmt_lock);
++
++ /*
++ * If kthread_should_stop() is true, we are guaranteed to be
++ * on the module unload, so both lists must be empty.
++ */
++ BUG_ON(!list_empty(&scst_sess_init_list));
++ BUG_ON(!list_empty(&scst_sess_shut_list));
++
++ PRINT_INFO("Management thread PID %d finished", current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++/* Called under sess->sess_list_lock */
++static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess,
++ uint64_t tag, bool to_abort)
++{
++ struct scst_cmd *cmd, *res = NULL;
++
++ TRACE_ENTRY();
++
++ /* ToDo: hash list */
++
++ TRACE_DBG("%s (sess=%p, tag=%llu)", "Searching in sess cmd list",
++ sess, (long long unsigned int)tag);
++
++ list_for_each_entry(cmd, &sess->sess_cmd_list,
++ sess_cmd_list_entry) {
++ if (cmd->tag == tag) {
++ /*
++ * We must not count done commands, because
++ * they were submitted for transmittion.
++ * Otherwise we can have a race, when for
++ * some reason cmd's release delayed
++ * after transmittion and initiator sends
++ * cmd with the same tag => it can be possible
++ * that a wrong cmd will be returned.
++ */
++ if (cmd->done) {
++ if (to_abort) {
++ /*
++ * We should return the latest not
++ * aborted cmd with this tag.
++ */
++ if (res == NULL)
++ res = cmd;
++ else {
++ if (test_bit(SCST_CMD_ABORTED,
++ &res->cmd_flags)) {
++ res = cmd;
++ } else if (!test_bit(SCST_CMD_ABORTED,
++ &cmd->cmd_flags))
++ res = cmd;
++ }
++ }
++ continue;
++ } else {
++ res = cmd;
++ break;
++ }
++ }
++ }
++
++ TRACE_EXIT();
++ return res;
++}
++
++/**
++ * scst_find_cmd() - find command by custom comparison function
++ *
++ * Finds a command based on user supplied data and comparision
++ * callback function, that should return true, if the command is found.
++ * Returns the command on success or NULL otherwise.
++ */
++struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data,
++ int (*cmp_fn) (struct scst_cmd *cmd,
++ void *data))
++{
++ struct scst_cmd *cmd = NULL;
++ unsigned long flags = 0;
++
++ TRACE_ENTRY();
++
++ if (cmp_fn == NULL)
++ goto out;
++
++ spin_lock_irqsave(&sess->sess_list_lock, flags);
++
++ TRACE_DBG("Searching in sess cmd list (sess=%p)", sess);
++ list_for_each_entry(cmd, &sess->sess_cmd_list, sess_cmd_list_entry) {
++ /*
++ * We must not count done commands, because they were
++ * submitted for transmittion. Otherwise we can have a race,
++ * when for some reason cmd's release delayed after
++ * transmittion and initiator sends cmd with the same tag =>
++ * it can be possible that a wrong cmd will be returned.
++ */
++ if (cmd->done)
++ continue;
++ if (cmp_fn(cmd, data))
++ goto out_unlock;
++ }
++
++ cmd = NULL;
++
++out_unlock:
++ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
++
++out:
++ TRACE_EXIT();
++ return cmd;
++}
++EXPORT_SYMBOL(scst_find_cmd);
++
++/**
++ * scst_find_cmd_by_tag() - find command by tag
++ *
++ * Finds a command based on the supplied tag comparing it with one
++ * that previously set by scst_cmd_set_tag(). Returns the found command on
++ * success or NULL otherwise.
++ */
++struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess,
++ uint64_t tag)
++{
++ unsigned long flags;
++ struct scst_cmd *cmd;
++ spin_lock_irqsave(&sess->sess_list_lock, flags);
++ cmd = __scst_find_cmd_by_tag(sess, tag, false);
++ spin_unlock_irqrestore(&sess->sess_list_lock, flags);
++ return cmd;
++}
++EXPORT_SYMBOL(scst_find_cmd_by_tag);
+diff -uprN orig/linux-2.6.36/include/scst/scst_debug.h linux-2.6.36/include/scst/scst_debug.h
+--- orig/linux-2.6.36/include/scst/scst_debug.h
++++ linux-2.6.36/include/scst/scst_debug.h
+@@ -0,0 +1,351 @@
++/*
++ * include/scst_debug.h
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * Contains macroses for execution tracing and error reporting
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef __SCST_DEBUG_H
++#define __SCST_DEBUG_H
++
++#include <generated/autoconf.h> /* for CONFIG_* */
++
++#include <linux/bug.h> /* for WARN_ON_ONCE */
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++#define EXTRACHECKS_BUG_ON(a) BUG_ON(a)
++#define EXTRACHECKS_WARN_ON(a) WARN_ON(a)
++#define EXTRACHECKS_WARN_ON_ONCE(a) WARN_ON_ONCE(a)
++#else
++#define EXTRACHECKS_BUG_ON(a) do { } while (0)
++#define EXTRACHECKS_WARN_ON(a) do { } while (0)
++#define EXTRACHECKS_WARN_ON_ONCE(a) do { } while (0)
++#endif
++
++#define TRACE_NULL 0x00000000
++#define TRACE_DEBUG 0x00000001
++#define TRACE_FUNCTION 0x00000002
++#define TRACE_LINE 0x00000004
++#define TRACE_PID 0x00000008
++#ifndef GENERATING_UPSTREAM_PATCH
++#define TRACE_ENTRYEXIT 0x00000010
++#endif
++#define TRACE_BUFF 0x00000020
++#define TRACE_MEMORY 0x00000040
++#define TRACE_SG_OP 0x00000080
++#define TRACE_OUT_OF_MEM 0x00000100
++#define TRACE_MINOR 0x00000200 /* less important events */
++#define TRACE_MGMT 0x00000400
++#define TRACE_MGMT_DEBUG 0x00000800
++#define TRACE_SCSI 0x00001000
++#define TRACE_SPECIAL 0x00002000 /* filtering debug, etc */
++#define TRACE_FLOW_CONTROL 0x00004000 /* flow control in action */
++#define TRACE_PRES 0x00008000
++#define TRACE_ALL 0xffffffff
++/* Flags 0xXXXX0000 are local for users */
++
++#define TRACE_MINOR_AND_MGMT_DBG (TRACE_MINOR|TRACE_MGMT_DEBUG)
++
++#ifndef KERN_CONT
++#define KERN_CONT ""
++#endif
++
++/*
++ * Note: in the next two printk() statements the KERN_CONT macro is only
++ * present to suppress a checkpatch warning (KERN_CONT is defined as "").
++ */
++#define PRINT(log_flag, format, args...) \
++ printk(log_flag format "\n", ## args)
++#define PRINTN(log_flag, format, args...) \
++ printk(log_flag format, ## args)
++
++#ifdef LOG_PREFIX
++#define __LOG_PREFIX LOG_PREFIX
++#else
++#define __LOG_PREFIX NULL
++#endif
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++#ifndef CONFIG_SCST_DEBUG
++#define ___unlikely(a) (a)
++#else
++#define ___unlikely(a) unlikely(a)
++#endif
++
++/*
++ * We don't print prefix for debug traces to not put additional preasure
++ * on the logging system in case of a lot of logging.
++ */
++
++int debug_print_prefix(unsigned long trace_flag,
++ const char *prefix, const char *func, int line);
++void debug_print_buffer(const void *data, int len);
++const char *debug_transport_id_to_initiator_name(const uint8_t *transport_id);
++
++#define TRACING_MINOR() (trace_flag & TRACE_MINOR)
++
++#define TRACE(trace, format, args...) \
++do { \
++ if (___unlikely(trace_flag & (trace))) { \
++ debug_print_prefix(trace_flag, __LOG_PREFIX, \
++ __func__, __LINE__); \
++ PRINT(KERN_CONT, format, args); \
++ } \
++} while (0)
++
++#ifdef CONFIG_SCST_DEBUG
++
++#define PRINT_BUFFER(message, buff, len) \
++do { \
++ PRINT(KERN_INFO, "%s:%s:", __func__, message); \
++ debug_print_buffer(buff, len); \
++} while (0)
++
++#else
++
++#define PRINT_BUFFER(message, buff, len) \
++do { \
++ PRINT(KERN_INFO, "%s:", message); \
++ debug_print_buffer(buff, len); \
++} while (0)
++
++#endif
++
++#define PRINT_BUFF_FLAG(flag, message, buff, len) \
++do { \
++ if (___unlikely(trace_flag & (flag))) { \
++ debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\
++ PRINT(KERN_CONT, "%s:", message); \
++ debug_print_buffer(buff, len); \
++ } \
++} while (0)
++
++#else /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
++
++#define TRACING_MINOR() (false)
++
++#define TRACE(trace, args...) do {} while (0)
++#define PRINT_BUFFER(message, buff, len) do {} while (0)
++#define PRINT_BUFF_FLAG(flag, message, buff, len) do {} while (0)
++
++#endif /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
++
++#ifdef CONFIG_SCST_DEBUG
++
++#define TRACE_DBG_FLAG(trace, format, args...) \
++do { \
++ if (trace_flag & (trace)) { \
++ debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\
++ PRINT(KERN_CONT, format, args); \
++ } \
++} while (0)
++
++#define TRACE_MEM(args...) TRACE_DBG_FLAG(TRACE_MEMORY, args)
++#define TRACE_SG(args...) TRACE_DBG_FLAG(TRACE_SG_OP, args)
++#define TRACE_DBG(args...) TRACE_DBG_FLAG(TRACE_DEBUG, args)
++#define TRACE_DBG_SPECIAL(args...) TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_SPECIAL, args)
++#define TRACE_MGMT_DBG(args...) TRACE_DBG_FLAG(TRACE_MGMT_DEBUG, args)
++#define TRACE_MGMT_DBG_SPECIAL(args...) \
++ TRACE_DBG_FLAG(TRACE_MGMT_DEBUG|TRACE_SPECIAL, args)
++#define TRACE_PR(args...) TRACE_DBG_FLAG(TRACE_PRES, args)
++
++#define TRACE_BUFFER(message, buff, len) \
++do { \
++ if (trace_flag & TRACE_BUFF) { \
++ debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\
++ PRINT(KERN_CONT, "%s:", message); \
++ debug_print_buffer(buff, len); \
++ } \
++} while (0)
++
++#define TRACE_BUFF_FLAG(flag, message, buff, len) \
++do { \
++ if (trace_flag & (flag)) { \
++ debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\
++ PRINT(KERN_CONT, "%s:", message); \
++ debug_print_buffer(buff, len); \
++ } \
++} while (0)
++
++#define PRINT_LOG_FLAG(log_flag, format, args...) \
++do { \
++ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
++ PRINT(KERN_CONT, format, args); \
++} while (0)
++
++#define PRINT_WARNING(format, args...) \
++do { \
++ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
++ PRINT(KERN_CONT, "***WARNING***: " format, args); \
++} while (0)
++
++#define PRINT_ERROR(format, args...) \
++do { \
++ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
++ PRINT(KERN_CONT, "***ERROR***: " format, args); \
++} while (0)
++
++#define PRINT_CRIT_ERROR(format, args...) \
++do { \
++ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
++ PRINT(KERN_CONT, "***CRITICAL ERROR***: " format, args); \
++} while (0)
++
++#define PRINT_INFO(format, args...) \
++do { \
++ debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\
++ PRINT(KERN_CONT, format, args); \
++} while (0)
++
++#ifndef GENERATING_UPSTREAM_PATCH
++#define TRACE_ENTRY() \
++do { \
++ if (trace_flag & TRACE_ENTRYEXIT) { \
++ if (trace_flag & TRACE_PID) { \
++ PRINT(KERN_INFO, "[%d]: ENTRY %s", current->pid, \
++ __func__); \
++ } \
++ else { \
++ PRINT(KERN_INFO, "ENTRY %s", __func__); \
++ } \
++ } \
++} while (0)
++
++#define TRACE_EXIT() \
++do { \
++ if (trace_flag & TRACE_ENTRYEXIT) { \
++ if (trace_flag & TRACE_PID) { \
++ PRINT(KERN_INFO, "[%d]: EXIT %s", current->pid, \
++ __func__); \
++ } \
++ else { \
++ PRINT(KERN_INFO, "EXIT %s", __func__); \
++ } \
++ } \
++} while (0)
++
++#define TRACE_EXIT_RES(res) \
++do { \
++ if (trace_flag & TRACE_ENTRYEXIT) { \
++ if (trace_flag & TRACE_PID) { \
++ PRINT(KERN_INFO, "[%d]: EXIT %s: %ld", current->pid, \
++ __func__, (long)(res)); \
++ } \
++ else { \
++ PRINT(KERN_INFO, "EXIT %s: %ld", \
++ __func__, (long)(res)); \
++ } \
++ } \
++} while (0)
++
++#define TRACE_EXIT_HRES(res) \
++do { \
++ if (trace_flag & TRACE_ENTRYEXIT) { \
++ if (trace_flag & TRACE_PID) { \
++ PRINT(KERN_INFO, "[%d]: EXIT %s: 0x%lx", current->pid, \
++ __func__, (long)(res)); \
++ } \
++ else { \
++ PRINT(KERN_INFO, "EXIT %s: %lx", \
++ __func__, (long)(res)); \
++ } \
++ } \
++} while (0)
++#endif
++
++#else /* CONFIG_SCST_DEBUG */
++
++#define TRACE_MEM(format, args...) do {} while (0)
++#define TRACE_SG(format, args...) do {} while (0)
++#define TRACE_DBG(format, args...) do {} while (0)
++#define TRACE_DBG_FLAG(format, args...) do {} while (0)
++#define TRACE_DBG_SPECIAL(format, args...) do {} while (0)
++#define TRACE_MGMT_DBG(format, args...) do {} while (0)
++#define TRACE_MGMT_DBG_SPECIAL(format, args...) do {} while (0)
++#define TRACE_PR(format, args...) do {} while (0)
++#define TRACE_BUFFER(message, buff, len) do {} while (0)
++#define TRACE_BUFF_FLAG(flag, message, buff, len) do {} while (0)
++
++#ifndef GENERATING_UPSTREAM_PATCH
++#define TRACE_ENTRY() do {} while (0)
++#define TRACE_EXIT() do {} while (0)
++#define TRACE_EXIT_RES(res) do {} while (0)
++#define TRACE_EXIT_HRES(res) do {} while (0)
++#endif
++
++#ifdef LOG_PREFIX
++
++#define PRINT_INFO(format, args...) \
++do { \
++ PRINT(KERN_INFO, "%s: " format, LOG_PREFIX, args); \
++} while (0)
++
++#define PRINT_WARNING(format, args...) \
++do { \
++ PRINT(KERN_INFO, "%s: ***WARNING***: " \
++ format, LOG_PREFIX, args); \
++} while (0)
++
++#define PRINT_ERROR(format, args...) \
++do { \
++ PRINT(KERN_INFO, "%s: ***ERROR***: " \
++ format, LOG_PREFIX, args); \
++} while (0)
++
++#define PRINT_CRIT_ERROR(format, args...) \
++do { \
++ PRINT(KERN_INFO, "%s: ***CRITICAL ERROR***: " \
++ format, LOG_PREFIX, args); \
++} while (0)
++
++#else
++
++#define PRINT_INFO(format, args...) \
++do { \
++ PRINT(KERN_INFO, format, args); \
++} while (0)
++
++#define PRINT_WARNING(format, args...) \
++do { \
++ PRINT(KERN_INFO, "***WARNING***: " \
++ format, args); \
++} while (0)
++
++#define PRINT_ERROR(format, args...) \
++do { \
++ PRINT(KERN_ERR, "***ERROR***: " \
++ format, args); \
++} while (0)
++
++#define PRINT_CRIT_ERROR(format, args...) \
++do { \
++ PRINT(KERN_CRIT, "***CRITICAL ERROR***: " \
++ format, args); \
++} while (0)
++
++#endif /* LOG_PREFIX */
++
++#endif /* CONFIG_SCST_DEBUG */
++
++#if defined(CONFIG_SCST_DEBUG) && defined(CONFIG_DEBUG_SLAB)
++#define SCST_SLAB_FLAGS (SLAB_RED_ZONE | SLAB_POISON)
++#else
++#define SCST_SLAB_FLAGS 0L
++#endif
++
++#endif /* __SCST_DEBUG_H */
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_debug.c linux-2.6.36/drivers/scst/scst_debug.c
+--- orig/linux-2.6.36/drivers/scst/scst_debug.c
++++ linux-2.6.36/drivers/scst/scst_debug.c
+@@ -0,0 +1,224 @@
++/*
++ * scst_debug.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * Contains helper functions for execution tracing and error reporting.
++ * Intended to be included in main .c file.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <scst/scst.h>
++#include <scst/scst_debug.h>
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++#define TRACE_BUF_SIZE 512
++
++static char trace_buf[TRACE_BUF_SIZE];
++static DEFINE_SPINLOCK(trace_buf_lock);
++
++static inline int get_current_tid(void)
++{
++ /* Code should be the same as in sys_gettid() */
++ if (in_interrupt()) {
++ /*
++ * Unfortunately, task_pid_vnr() isn't IRQ-safe, so otherwise
++ * it can oops. ToDo.
++ */
++ return 0;
++ }
++ return task_pid_vnr(current);
++}
++
++/**
++ * debug_print_prefix() - print debug prefix for a log line
++ *
++ * Prints, if requested by trace_flag, debug prefix for each log line
++ */
++int debug_print_prefix(unsigned long trace_flag,
++ const char *prefix, const char *func, int line)
++{
++ int i = 0;
++ unsigned long flags;
++ int pid = get_current_tid();
++
++ spin_lock_irqsave(&trace_buf_lock, flags);
++
++ trace_buf[0] = '\0';
++
++ if (trace_flag & TRACE_PID)
++ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE, "[%d]: ", pid);
++ if (prefix != NULL)
++ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%s: ",
++ prefix);
++ if (trace_flag & TRACE_FUNCTION)
++ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%s:", func);
++ if (trace_flag & TRACE_LINE)
++ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%i:", line);
++
++ PRINTN(KERN_INFO, "%s", trace_buf);
++
++ spin_unlock_irqrestore(&trace_buf_lock, flags);
++
++ return i;
++}
++EXPORT_SYMBOL(debug_print_prefix);
++
++/**
++ * debug_print_buffer() - print a buffer
++ *
++ * Prints in the log data from the buffer
++ */
++void debug_print_buffer(const void *data, int len)
++{
++ int z, z1, i;
++ const unsigned char *buf = (const unsigned char *) data;
++ unsigned long flags;
++
++ if (buf == NULL)
++ return;
++
++ spin_lock_irqsave(&trace_buf_lock, flags);
++
++ PRINT(KERN_INFO, " (h)___0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F");
++ for (z = 0, z1 = 0, i = 0; z < len; z++) {
++ if (z % 16 == 0) {
++ if (z != 0) {
++ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i,
++ " ");
++ for (; (z1 < z) && (i < TRACE_BUF_SIZE - 1);
++ z1++) {
++ if ((buf[z1] >= 0x20) &&
++ (buf[z1] < 0x80))
++ trace_buf[i++] = buf[z1];
++ else
++ trace_buf[i++] = '.';
++ }
++ trace_buf[i] = '\0';
++ PRINT(KERN_INFO, "%s", trace_buf);
++ i = 0;
++ }
++ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i,
++ "%4x: ", z);
++ }
++ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, "%02x ",
++ buf[z]);
++ }
++
++ i += snprintf(&trace_buf[i], TRACE_BUF_SIZE - i, " ");
++ for (; (z1 < z) && (i < TRACE_BUF_SIZE - 1); z1++) {
++ if ((buf[z1] > 0x20) && (buf[z1] < 0x80))
++ trace_buf[i++] = buf[z1];
++ else
++ trace_buf[i++] = '.';
++ }
++ trace_buf[i] = '\0';
++
++ PRINT(KERN_INFO, "%s", trace_buf);
++
++ spin_unlock_irqrestore(&trace_buf_lock, flags);
++ return;
++}
++EXPORT_SYMBOL(debug_print_buffer);
++
++/*
++ * This function converts transport_id in a string form into internal per-CPU
++ * static buffer. This buffer isn't anyhow protected, because it's acceptable
++ * if the name corrupted in the debug logs because of the race for this buffer.
++ *
++ * Note! You can't call this function 2 or more times in a single logging
++ * (printk) statement, because then each new call of this functon will override
++ * data written in this buffer by the previous call. You should instead split
++ * that logging statement on smaller statements each calling
++ * debug_transport_id_to_initiator_name() only once.
++ */
++const char *debug_transport_id_to_initiator_name(const uint8_t *transport_id)
++{
++ /*
++ * No external protection, because it's acceptable if the name
++ * corrupted in the debug logs because of the race for this
++ * buffer.
++ */
++#define SIZEOF_NAME_BUF 256
++ static char name_bufs[NR_CPUS][SIZEOF_NAME_BUF];
++ char *name_buf;
++ unsigned long flags;
++
++ BUG_ON(transport_id == NULL); /* better to catch it not under lock */
++
++ spin_lock_irqsave(&trace_buf_lock, flags);
++
++ name_buf = name_bufs[smp_processor_id()];
++
++ /*
++ * To prevent external racing with us users from accidentally
++ * missing their NULL terminator.
++ */
++ memset(name_buf, 0, SIZEOF_NAME_BUF);
++ smp_mb();
++
++ switch (transport_id[0] & 0x0f) {
++ case SCSI_TRANSPORTID_PROTOCOLID_ISCSI:
++ scnprintf(name_buf, SIZEOF_NAME_BUF, "%s",
++ &transport_id[4]);
++ break;
++ case SCSI_TRANSPORTID_PROTOCOLID_FCP2:
++ scnprintf(name_buf, SIZEOF_NAME_BUF,
++ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
++ transport_id[8], transport_id[9],
++ transport_id[10], transport_id[11],
++ transport_id[12], transport_id[13],
++ transport_id[14], transport_id[15]);
++ break;
++ case SCSI_TRANSPORTID_PROTOCOLID_SPI5:
++ scnprintf(name_buf, SIZEOF_NAME_BUF,
++ "%x:%x", be16_to_cpu((__force __be16)transport_id[2]),
++ be16_to_cpu((__force __be16)transport_id[6]));
++ break;
++ case SCSI_TRANSPORTID_PROTOCOLID_SRP:
++ scnprintf(name_buf, SIZEOF_NAME_BUF,
++ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
++ ":%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
++ transport_id[8], transport_id[9],
++ transport_id[10], transport_id[11],
++ transport_id[12], transport_id[13],
++ transport_id[14], transport_id[15],
++ transport_id[16], transport_id[17],
++ transport_id[18], transport_id[19],
++ transport_id[20], transport_id[21],
++ transport_id[22], transport_id[23]);
++ break;
++ case SCSI_TRANSPORTID_PROTOCOLID_SAS:
++ scnprintf(name_buf, SIZEOF_NAME_BUF,
++ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
++ transport_id[4], transport_id[5],
++ transport_id[6], transport_id[7],
++ transport_id[8], transport_id[9],
++ transport_id[10], transport_id[11]);
++ break;
++ default:
++ scnprintf(name_buf, SIZEOF_NAME_BUF,
++ "(Not known protocol ID %x)", transport_id[0] & 0x0f);
++ break;
++ }
++
++ spin_unlock_irqrestore(&trace_buf_lock, flags);
++
++ return name_buf;
++#undef SIZEOF_NAME_BUF
++}
++
++#endif /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_proc.c linux-2.6.36/drivers/scst/scst_proc.c
+--- orig/linux-2.6.36/drivers/scst/scst_proc.c
++++ linux-2.6.36/drivers/scst/scst_proc.c
+@@ -0,0 +1,2704 @@
++/*
++ * scst_proc.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/unistd.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++
++#include <scst/scst.h>
++#include "scst_priv.h"
++#include "scst_mem.h"
++#include "scst_pres.h"
++
++static int scst_proc_init_groups(void);
++static void scst_proc_cleanup_groups(void);
++static int scst_proc_assign_handler(char *buf);
++static int scst_proc_group_add(const char *p, unsigned int addr_method);
++static int scst_proc_del_free_acg(struct scst_acg *acg, int remove_proc);
++
++static struct scst_proc_data scst_version_proc_data;
++static struct scst_proc_data scst_help_proc_data;
++static struct scst_proc_data scst_sgv_proc_data;
++static struct scst_proc_data scst_groups_names_proc_data;
++static struct scst_proc_data scst_groups_devices_proc_data;
++static struct scst_proc_data scst_groups_addr_method_proc_data;
++static struct scst_proc_data scst_sessions_proc_data;
++static struct scst_proc_data scst_dev_handler_type_proc_data;
++static struct scst_proc_data scst_tgt_proc_data;
++static struct scst_proc_data scst_threads_proc_data;
++static struct scst_proc_data scst_scsi_tgt_proc_data;
++static struct scst_proc_data scst_dev_handler_proc_data;
++
++/*
++ * Must be less than 4K page size, since our output routines
++ * use some slack for overruns
++ */
++#define SCST_PROC_BLOCK_SIZE (PAGE_SIZE - 512)
++
++#define SCST_PROC_LOG_ENTRY_NAME "trace_level"
++#define SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME "type"
++#define SCST_PROC_VERSION_NAME "version"
++#define SCST_PROC_SESSIONS_NAME "sessions"
++#define SCST_PROC_HELP_NAME "help"
++#define SCST_PROC_THREADS_NAME "threads"
++#define SCST_PROC_GROUPS_ENTRY_NAME "groups"
++#define SCST_PROC_GROUPS_DEVICES_ENTRY_NAME "devices"
++#define SCST_PROC_GROUPS_USERS_ENTRY_NAME "names"
++#define SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME "addr_method"
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++#define SCST_PROC_LAT_ENTRY_NAME "latency"
++#endif
++
++#define SCST_PROC_ACTION_ALL 1
++#define SCST_PROC_ACTION_NONE 2
++#define SCST_PROC_ACTION_DEFAULT 3
++#define SCST_PROC_ACTION_ADD 4
++#define SCST_PROC_ACTION_CLEAR 5
++#define SCST_PROC_ACTION_MOVE 6
++#define SCST_PROC_ACTION_DEL 7
++#define SCST_PROC_ACTION_REPLACE 8
++#define SCST_PROC_ACTION_VALUE 9
++#define SCST_PROC_ACTION_ASSIGN 10
++#define SCST_PROC_ACTION_ADD_GROUP 11
++#define SCST_PROC_ACTION_DEL_GROUP 12
++#define SCST_PROC_ACTION_RENAME_GROUP 13
++#define SCST_PROC_ACTION_DUMP_PRS 14
++
++static struct proc_dir_entry *scst_proc_scsi_tgt;
++static struct proc_dir_entry *scst_proc_groups_root;
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++static struct scst_proc_data scst_log_proc_data;
++
++static struct scst_trace_log scst_proc_trace_tbl[] = {
++ { TRACE_OUT_OF_MEM, "out_of_mem" },
++ { TRACE_MINOR, "minor" },
++ { TRACE_SG_OP, "sg" },
++ { TRACE_MEMORY, "mem" },
++ { TRACE_BUFF, "buff" },
++#ifndef GENERATING_UPSTREAM_PATCH
++ { TRACE_ENTRYEXIT, "entryexit" },
++#endif
++ { TRACE_PID, "pid" },
++ { TRACE_LINE, "line" },
++ { TRACE_FUNCTION, "function" },
++ { TRACE_DEBUG, "debug" },
++ { TRACE_SPECIAL, "special" },
++ { TRACE_SCSI, "scsi" },
++ { TRACE_MGMT, "mgmt" },
++ { TRACE_MGMT_DEBUG, "mgmt_dbg" },
++ { TRACE_FLOW_CONTROL, "flow_control" },
++ { TRACE_PRES, "pr" },
++ { 0, NULL }
++};
++
++static struct scst_trace_log scst_proc_local_trace_tbl[] = {
++ { TRACE_RTRY, "retry" },
++ { TRACE_SCSI_SERIALIZING, "scsi_serializing" },
++ { TRACE_RCV_BOT, "recv_bot" },
++ { TRACE_SND_BOT, "send_bot" },
++ { TRACE_RCV_TOP, "recv_top" },
++ { TRACE_SND_TOP, "send_top" },
++ { 0, NULL }
++};
++#endif
++
++static char *scst_proc_help_string =
++" echo \"assign H:C:I:L HANDLER_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
++"\n"
++" echo \"add_group GROUP_NAME [FLAT]\" >/proc/scsi_tgt/scsi_tgt\n"
++" echo \"del_group GROUP_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
++" echo \"rename_group OLD_NAME NEW_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
++"\n"
++" echo \"add|del H:C:I:L lun [READ_ONLY]\""
++" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
++" echo \"replace H:C:I:L lun [READ_ONLY]\""
++" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
++" echo \"add|del V_NAME lun [READ_ONLY]\""
++" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
++" echo \"replace V_NAME lun [READ_ONLY]\""
++" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
++" echo \"clear\" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
++"\n"
++" echo \"add|del NAME\" >/proc/scsi_tgt/groups/GROUP_NAME/names\n"
++" echo \"move NAME NEW_GROUP_NAME\" >/proc/scsi_tgt/groups/OLD_GROUP_NAME/names\n"
++" echo \"clear\" >/proc/scsi_tgt/groups/GROUP_NAME/names\n"
++"\n"
++" echo \"DEC|0xHEX|0OCT\" >/proc/scsi_tgt/threads\n"
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++"\n"
++" echo \"all|none|default\" >/proc/scsi_tgt/[DEV_HANDLER_NAME/]trace_level\n"
++" echo \"value DEC|0xHEX|0OCT\""
++" >/proc/scsi_tgt/[DEV_HANDLER_NAME/]trace_level\n"
++" echo \"set|add|del TOKEN\""
++" >/proc/scsi_tgt/[DEV_HANDLER_NAME/]trace_level\n"
++" where TOKEN is one of [debug, function, line, pid, entryexit,\n"
++" buff, mem, sg, out_of_mem, special, scsi,\n"
++" mgmt, minor, mgmt_dbg]\n"
++" Additionally for /proc/scsi_tgt/trace_level there are these TOKENs\n"
++" [scsi_serializing, retry, recv_bot, send_bot, recv_top, send_top]\n"
++" echo \"dump_prs dev_name\" >/proc/scsi_tgt/trace_level\n"
++#endif
++;
++
++static char *scst_proc_dev_handler_type[] = {
++ "Direct-access device (e.g., magnetic disk)",
++ "Sequential-access device (e.g., magnetic tape)",
++ "Printer device",
++ "Processor device",
++ "Write-once device (e.g., some optical disks)",
++ "CD-ROM device",
++ "Scanner device (obsolete)",
++ "Optical memory device (e.g., some optical disks)",
++ "Medium changer device (e.g., jukeboxes)",
++ "Communications device (obsolete)",
++ "Defined by ASC IT8 (Graphic arts pre-press devices)",
++ "Defined by ASC IT8 (Graphic arts pre-press devices)",
++ "Storage array controller device (e.g., RAID)",
++ "Enclosure services device",
++ "Simplified direct-access device (e.g., magnetic disk)",
++ "Optical card reader/writer device"
++};
++
++static DEFINE_MUTEX(scst_proc_mutex);
++
++#include <linux/ctype.h>
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++static DEFINE_MUTEX(scst_log_mutex);
++
++int scst_proc_log_entry_write(struct file *file, const char __user *buf,
++ unsigned long length, unsigned long *log_level,
++ unsigned long default_level, const struct scst_trace_log *tbl)
++{
++ int res = length;
++ int action;
++ unsigned long level = 0, oldlevel;
++ char *buffer, *p, *e;
++ const struct scst_trace_log *t;
++ char *data = (char *)PDE(file->f_dentry->d_inode)->data;
++
++ TRACE_ENTRY();
++
++ if (length > SCST_PROC_BLOCK_SIZE) {
++ res = -EOVERFLOW;
++ goto out;
++ }
++ if (!buf) {
++ res = -EINVAL;
++ goto out;
++ }
++ buffer = (char *)__get_free_page(GFP_KERNEL);
++ if (!buffer) {
++ res = -ENOMEM;
++ goto out;
++ }
++ if (copy_from_user(buffer, buf, length)) {
++ res = -EFAULT;
++ goto out_free;
++ }
++ if (length < PAGE_SIZE) {
++ buffer[length] = '\0';
++ } else if (buffer[PAGE_SIZE-1]) {
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ /*
++ * Usage:
++ * echo "all|none|default" >/proc/scsi_tgt/trace_level
++ * echo "value DEC|0xHEX|0OCT" >/proc/scsi_tgt/trace_level
++ * echo "add|del TOKEN" >/proc/scsi_tgt/trace_level
++ */
++ p = buffer;
++ if (!strncasecmp("all", p, 3)) {
++ action = SCST_PROC_ACTION_ALL;
++ } else if (!strncasecmp("none", p, 4) || !strncasecmp("null", p, 4)) {
++ action = SCST_PROC_ACTION_NONE;
++ } else if (!strncasecmp("default", p, 7)) {
++ action = SCST_PROC_ACTION_DEFAULT;
++ } else if (!strncasecmp("add ", p, 4)) {
++ p += 4;
++ action = SCST_PROC_ACTION_ADD;
++ } else if (!strncasecmp("del ", p, 4)) {
++ p += 4;
++ action = SCST_PROC_ACTION_DEL;
++ } else if (!strncasecmp("value ", p, 6)) {
++ p += 6;
++ action = SCST_PROC_ACTION_VALUE;
++ } else if (!strncasecmp("dump_prs ", p, 9)) {
++ p += 9;
++ action = SCST_PROC_ACTION_DUMP_PRS;
++ } else {
++ if (p[strlen(p) - 1] == '\n')
++ p[strlen(p) - 1] = '\0';
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ switch (action) {
++ case SCST_PROC_ACTION_ALL:
++ level = TRACE_ALL;
++ break;
++ case SCST_PROC_ACTION_DEFAULT:
++ level = default_level;
++ break;
++ case SCST_PROC_ACTION_NONE:
++ level = TRACE_NULL;
++ break;
++ case SCST_PROC_ACTION_ADD:
++ case SCST_PROC_ACTION_DEL:
++ while (isspace(*p) && *p != '\0')
++ p++;
++ e = p;
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = 0;
++ if (tbl) {
++ t = tbl;
++ while (t->token) {
++ if (!strcasecmp(p, t->token)) {
++ level = t->val;
++ break;
++ }
++ t++;
++ }
++ }
++ if (level == 0) {
++ t = scst_proc_trace_tbl;
++ while (t->token) {
++ if (!strcasecmp(p, t->token)) {
++ level = t->val;
++ break;
++ }
++ t++;
++ }
++ }
++ if (level == 0) {
++ PRINT_ERROR("Unknown token \"%s\"", p);
++ res = -EINVAL;
++ goto out_free;
++ }
++ break;
++ case SCST_PROC_ACTION_VALUE:
++ while (isspace(*p) && *p != '\0')
++ p++;
++ level = simple_strtoul(p, NULL, 0);
++ break;
++ case SCST_PROC_ACTION_DUMP_PRS:
++ {
++ struct scst_device *dev;
++
++ while (isspace(*p) && *p != '\0')
++ p++;
++ e = p;
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = '\0';
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_free;
++ }
++
++ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
++ if (strcmp(dev->virt_name, p) == 0) {
++ scst_pr_dump_prs(dev, true);
++ goto out_up;
++ }
++ }
++
++ PRINT_ERROR("Device %s not found", p);
++ res = -ENOENT;
++out_up:
++ mutex_unlock(&scst_mutex);
++ goto out_free;
++ }
++ }
++
++ oldlevel = *log_level;
++
++ switch (action) {
++ case SCST_PROC_ACTION_ADD:
++ *log_level |= level;
++ break;
++ case SCST_PROC_ACTION_DEL:
++ *log_level &= ~level;
++ break;
++ default:
++ *log_level = level;
++ break;
++ }
++
++ PRINT_INFO("Changed trace level for \"%s\": "
++ "old 0x%08lx, new 0x%08lx",
++ (char *)data, oldlevel, *log_level);
++
++out_free:
++ free_page((unsigned long)buffer);
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_proc_log_entry_write);
++
++static ssize_t scst_proc_scsi_tgt_gen_write_log(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *off)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = scst_proc_log_entry_write(file, buf, length,
++ &trace_flag, SCST_DEFAULT_LOG_FLAGS,
++ scst_proc_local_trace_tbl);
++
++ mutex_unlock(&scst_log_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++
++static char *scst_io_size_names[] = {
++ "<=8K ",
++ "<=32K ",
++ "<=128K",
++ "<=512K",
++ ">512K "
++};
++
++static int lat_info_show(struct seq_file *seq, void *v)
++{
++ int res = 0;
++ struct scst_acg *acg;
++ struct scst_session *sess;
++ char buf[50];
++
++ TRACE_ENTRY();
++
++ BUILD_BUG_ON(SCST_LATENCY_STATS_NUM != ARRAY_SIZE(scst_io_size_names));
++ BUILD_BUG_ON(SCST_LATENCY_STATS_NUM != ARRAY_SIZE(sess->sess_latency_stat));
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ list_for_each_entry(acg, &scst_acg_list, acg_list_entry) {
++ bool header_printed = false;
++
++ list_for_each_entry(sess, &acg->acg_sess_list,
++ acg_sess_list_entry) {
++ unsigned int i;
++ int t;
++ uint64_t scst_time, tgt_time, dev_time;
++ unsigned int processed_cmds;
++
++ if (!header_printed) {
++ seq_printf(seq, "%-15s %-15s %-46s %-46s %-46s\n",
++ "T-L names", "Total commands", "SCST latency",
++ "Target latency", "Dev latency (min/avg/max/all ns)");
++ header_printed = true;
++ }
++
++ seq_printf(seq, "Target name: %s\nInitiator name: %s\n",
++ sess->tgt->tgtt->name,
++ sess->initiator_name);
++
++ spin_lock_bh(&sess->lat_lock);
++
++ for (i = 0; i < SCST_LATENCY_STATS_NUM ; i++) {
++ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
++ unsigned int processed_cmds_wr;
++ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
++ unsigned int processed_cmds_rd;
++ struct scst_ext_latency_stat *latency_stat;
++
++ latency_stat = &sess->sess_latency_stat[i];
++ scst_time_wr = latency_stat->scst_time_wr;
++ scst_time_rd = latency_stat->scst_time_rd;
++ tgt_time_wr = latency_stat->tgt_time_wr;
++ tgt_time_rd = latency_stat->tgt_time_rd;
++ dev_time_wr = latency_stat->dev_time_wr;
++ dev_time_rd = latency_stat->dev_time_rd;
++ processed_cmds_wr = latency_stat->processed_cmds_wr;
++ processed_cmds_rd = latency_stat->processed_cmds_rd;
++
++ seq_printf(seq, "%-5s %-9s %-15lu ",
++ "Write", scst_io_size_names[i],
++ (unsigned long)processed_cmds_wr);
++ if (processed_cmds_wr == 0)
++ processed_cmds_wr = 1;
++
++ do_div(scst_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_scst_time_wr,
++ (unsigned long)scst_time_wr,
++ (unsigned long)latency_stat->max_scst_time_wr,
++ (unsigned long)latency_stat->scst_time_wr);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(tgt_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_tgt_time_wr,
++ (unsigned long)tgt_time_wr,
++ (unsigned long)latency_stat->max_tgt_time_wr,
++ (unsigned long)latency_stat->tgt_time_wr);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(dev_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_dev_time_wr,
++ (unsigned long)dev_time_wr,
++ (unsigned long)latency_stat->max_dev_time_wr,
++ (unsigned long)latency_stat->dev_time_wr);
++ seq_printf(seq, "%-47s\n", buf);
++
++ seq_printf(seq, "%-5s %-9s %-15lu ",
++ "Read", scst_io_size_names[i],
++ (unsigned long)processed_cmds_rd);
++ if (processed_cmds_rd == 0)
++ processed_cmds_rd = 1;
++
++ do_div(scst_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_scst_time_rd,
++ (unsigned long)scst_time_rd,
++ (unsigned long)latency_stat->max_scst_time_rd,
++ (unsigned long)latency_stat->scst_time_rd);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(tgt_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_tgt_time_rd,
++ (unsigned long)tgt_time_rd,
++ (unsigned long)latency_stat->max_tgt_time_rd,
++ (unsigned long)latency_stat->tgt_time_rd);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(dev_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_dev_time_rd,
++ (unsigned long)dev_time_rd,
++ (unsigned long)latency_stat->max_dev_time_rd,
++ (unsigned long)latency_stat->dev_time_rd);
++ seq_printf(seq, "%-47s\n", buf);
++ }
++
++ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[t];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++
++ seq_printf(seq, "\nLUN: %llu\n", tgt_dev->lun);
++
++ for (i = 0; i < SCST_LATENCY_STATS_NUM ; i++) {
++ uint64_t scst_time_wr, tgt_time_wr, dev_time_wr;
++ unsigned int processed_cmds_wr;
++ uint64_t scst_time_rd, tgt_time_rd, dev_time_rd;
++ unsigned int processed_cmds_rd;
++ struct scst_ext_latency_stat *latency_stat;
++
++ latency_stat = &tgt_dev->dev_latency_stat[i];
++ scst_time_wr = latency_stat->scst_time_wr;
++ scst_time_rd = latency_stat->scst_time_rd;
++ tgt_time_wr = latency_stat->tgt_time_wr;
++ tgt_time_rd = latency_stat->tgt_time_rd;
++ dev_time_wr = latency_stat->dev_time_wr;
++ dev_time_rd = latency_stat->dev_time_rd;
++ processed_cmds_wr = latency_stat->processed_cmds_wr;
++ processed_cmds_rd = latency_stat->processed_cmds_rd;
++
++ seq_printf(seq, "%-5s %-9s %-15lu ",
++ "Write", scst_io_size_names[i],
++ (unsigned long)processed_cmds_wr);
++ if (processed_cmds_wr == 0)
++ processed_cmds_wr = 1;
++
++ do_div(scst_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_scst_time_wr,
++ (unsigned long)scst_time_wr,
++ (unsigned long)latency_stat->max_scst_time_wr,
++ (unsigned long)latency_stat->scst_time_wr);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(tgt_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_tgt_time_wr,
++ (unsigned long)tgt_time_wr,
++ (unsigned long)latency_stat->max_tgt_time_wr,
++ (unsigned long)latency_stat->tgt_time_wr);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(dev_time_wr, processed_cmds_wr);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_dev_time_wr,
++ (unsigned long)dev_time_wr,
++ (unsigned long)latency_stat->max_dev_time_wr,
++ (unsigned long)latency_stat->dev_time_wr);
++ seq_printf(seq, "%-47s\n", buf);
++
++ seq_printf(seq, "%-5s %-9s %-15lu ",
++ "Read", scst_io_size_names[i],
++ (unsigned long)processed_cmds_rd);
++ if (processed_cmds_rd == 0)
++ processed_cmds_rd = 1;
++
++ do_div(scst_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_scst_time_rd,
++ (unsigned long)scst_time_rd,
++ (unsigned long)latency_stat->max_scst_time_rd,
++ (unsigned long)latency_stat->scst_time_rd);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(tgt_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_tgt_time_rd,
++ (unsigned long)tgt_time_rd,
++ (unsigned long)latency_stat->max_tgt_time_rd,
++ (unsigned long)latency_stat->tgt_time_rd);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(dev_time_rd, processed_cmds_rd);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)latency_stat->min_dev_time_rd,
++ (unsigned long)dev_time_rd,
++ (unsigned long)latency_stat->max_dev_time_rd,
++ (unsigned long)latency_stat->dev_time_rd);
++ seq_printf(seq, "%-47s\n", buf);
++ }
++ }
++ }
++
++ scst_time = sess->scst_time;
++ tgt_time = sess->tgt_time;
++ dev_time = sess->dev_time;
++ processed_cmds = sess->processed_cmds;
++
++ seq_printf(seq, "\n%-15s %-16d", "Overall ",
++ processed_cmds);
++
++ if (processed_cmds == 0)
++ processed_cmds = 1;
++
++ do_div(scst_time, processed_cmds);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)sess->min_scst_time,
++ (unsigned long)scst_time,
++ (unsigned long)sess->max_scst_time,
++ (unsigned long)sess->scst_time);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(tgt_time, processed_cmds);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)sess->min_tgt_time,
++ (unsigned long)tgt_time,
++ (unsigned long)sess->max_tgt_time,
++ (unsigned long)sess->tgt_time);
++ seq_printf(seq, "%-47s", buf);
++
++ do_div(dev_time, processed_cmds);
++ snprintf(buf, sizeof(buf), "%lu/%lu/%lu/%lu",
++ (unsigned long)sess->min_dev_time,
++ (unsigned long)dev_time,
++ (unsigned long)sess->max_dev_time,
++ (unsigned long)sess->dev_time);
++ seq_printf(seq, "%-47s\n\n", buf);
++
++ spin_unlock_bh(&sess->lat_lock);
++ }
++ }
++
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_proc_scsi_tgt_gen_write_lat(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *off)
++{
++ int res = length, t;
++ struct scst_acg *acg;
++ struct scst_session *sess;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ list_for_each_entry(acg, &scst_acg_list, acg_list_entry) {
++ list_for_each_entry(sess, &acg->acg_sess_list,
++ acg_sess_list_entry) {
++ PRINT_INFO("Zeroing latency statistics for initiator "
++ "%s", sess->initiator_name);
++ spin_lock_bh(&sess->lat_lock);
++
++ sess->scst_time = 0;
++ sess->tgt_time = 0;
++ sess->dev_time = 0;
++ sess->min_scst_time = 0;
++ sess->min_tgt_time = 0;
++ sess->min_dev_time = 0;
++ sess->max_scst_time = 0;
++ sess->max_tgt_time = 0;
++ sess->max_dev_time = 0;
++ sess->processed_cmds = 0;
++ memset(sess->sess_latency_stat, 0,
++ sizeof(sess->sess_latency_stat));
++
++ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[t];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ tgt_dev->scst_time = 0;
++ tgt_dev->tgt_time = 0;
++ tgt_dev->dev_time = 0;
++ tgt_dev->processed_cmds = 0;
++ memset(tgt_dev->dev_latency_stat, 0,
++ sizeof(tgt_dev->dev_latency_stat));
++ }
++ }
++
++ spin_unlock_bh(&sess->lat_lock);
++ }
++ }
++
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_proc_data scst_lat_proc_data = {
++ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_tgt_gen_write_lat)
++ .show = lat_info_show,
++ .data = "scsi_tgt",
++};
++
++#endif /* CONFIG_SCST_MEASURE_LATENCY */
++
++static int __init scst_proc_init_module_log(void)
++{
++ int res = 0;
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) || \
++ defined(CONFIG_SCST_MEASURE_LATENCY)
++ struct proc_dir_entry *generic;
++#endif
++
++ TRACE_ENTRY();
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
++ SCST_PROC_LOG_ENTRY_NAME,
++ &scst_log_proc_data);
++ if (!generic) {
++ PRINT_ERROR("cannot init /proc/%s/%s",
++ SCST_PROC_ENTRY_NAME, SCST_PROC_LOG_ENTRY_NAME);
++ res = -ENOMEM;
++ }
++#endif
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++ if (res == 0) {
++ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
++ SCST_PROC_LAT_ENTRY_NAME,
++ &scst_lat_proc_data);
++ if (!generic) {
++ PRINT_ERROR("cannot init /proc/%s/%s",
++ SCST_PROC_ENTRY_NAME,
++ SCST_PROC_LAT_ENTRY_NAME);
++ res = -ENOMEM;
++ }
++ }
++#endif
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void scst_proc_cleanup_module_log(void)
++{
++ TRACE_ENTRY();
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ remove_proc_entry(SCST_PROC_LOG_ENTRY_NAME, scst_proc_scsi_tgt);
++#endif
++
++#ifdef CONFIG_SCST_MEASURE_LATENCY
++ remove_proc_entry(SCST_PROC_LAT_ENTRY_NAME, scst_proc_scsi_tgt);
++#endif
++
++ TRACE_EXIT();
++ return;
++}
++
++static int scst_proc_group_add_tree(struct scst_acg *acg, const char *name)
++{
++ int res = 0;
++ struct proc_dir_entry *generic;
++
++ TRACE_ENTRY();
++
++ acg->acg_proc_root = proc_mkdir(name, scst_proc_groups_root);
++ if (acg->acg_proc_root == NULL) {
++ PRINT_ERROR("Not enough memory to register %s entry in "
++ "/proc/%s/%s", name, SCST_PROC_ENTRY_NAME,
++ SCST_PROC_GROUPS_ENTRY_NAME);
++ goto out;
++ }
++
++ scst_groups_addr_method_proc_data.data = acg;
++ generic = scst_create_proc_entry(acg->acg_proc_root,
++ SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME,
++ &scst_groups_addr_method_proc_data);
++ if (!generic) {
++ PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
++ SCST_PROC_ENTRY_NAME,
++ SCST_PROC_GROUPS_ENTRY_NAME,
++ name, SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME);
++ res = -ENOMEM;
++ goto out_remove;
++ }
++
++ scst_groups_devices_proc_data.data = acg;
++ generic = scst_create_proc_entry(acg->acg_proc_root,
++ SCST_PROC_GROUPS_DEVICES_ENTRY_NAME,
++ &scst_groups_devices_proc_data);
++ if (!generic) {
++ PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
++ SCST_PROC_ENTRY_NAME,
++ SCST_PROC_GROUPS_ENTRY_NAME,
++ name, SCST_PROC_GROUPS_DEVICES_ENTRY_NAME);
++ res = -ENOMEM;
++ goto out_remove0;
++ }
++
++ scst_groups_names_proc_data.data = acg;
++ generic = scst_create_proc_entry(acg->acg_proc_root,
++ SCST_PROC_GROUPS_USERS_ENTRY_NAME,
++ &scst_groups_names_proc_data);
++ if (!generic) {
++ PRINT_ERROR("Cannot init /proc/%s/%s/%s/%s",
++ SCST_PROC_ENTRY_NAME,
++ SCST_PROC_GROUPS_ENTRY_NAME,
++ name, SCST_PROC_GROUPS_USERS_ENTRY_NAME);
++ res = -ENOMEM;
++ goto out_remove1;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_remove1:
++ remove_proc_entry(SCST_PROC_GROUPS_DEVICES_ENTRY_NAME,
++ acg->acg_proc_root);
++
++out_remove0:
++ remove_proc_entry(SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME,
++ acg->acg_proc_root);
++out_remove:
++ remove_proc_entry(name, scst_proc_groups_root);
++ goto out;
++}
++
++static void scst_proc_del_acg_tree(struct proc_dir_entry *acg_proc_root,
++ const char *name)
++{
++ TRACE_ENTRY();
++
++ remove_proc_entry(SCST_PROC_GROUPS_ADDR_METHOD_ENTRY_NAME, acg_proc_root);
++ remove_proc_entry(SCST_PROC_GROUPS_USERS_ENTRY_NAME, acg_proc_root);
++ remove_proc_entry(SCST_PROC_GROUPS_DEVICES_ENTRY_NAME, acg_proc_root);
++ remove_proc_entry(name, scst_proc_groups_root);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++static int scst_proc_group_add(const char *p, unsigned int addr_method)
++{
++ int res = 0, len = strlen(p) + 1;
++ struct scst_acg *acg;
++ char *name = NULL;
++
++ TRACE_ENTRY();
++
++ name = kmalloc(len, GFP_KERNEL);
++ if (name == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of name failed");
++ goto out_nomem;
++ }
++ strlcpy(name, p, len);
++
++ acg = scst_alloc_add_acg(NULL, name, false);
++ if (acg == NULL) {
++ PRINT_ERROR("scst_alloc_add_acg() (name %s) failed", name);
++ goto out_free;
++ }
++
++ acg->addr_method = addr_method;
++
++ res = scst_proc_group_add_tree(acg, p);
++ if (res != 0)
++ goto out_free_acg;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free_acg:
++ scst_proc_del_free_acg(acg, 0);
++
++out_free:
++ kfree(name);
++
++out_nomem:
++ res = -ENOMEM;
++ goto out;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++static int scst_proc_del_free_acg(struct scst_acg *acg, int remove_proc)
++{
++ struct proc_dir_entry *acg_proc_root = acg->acg_proc_root;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (acg != scst_default_acg) {
++ if (!scst_acg_sess_is_empty(acg)) {
++ PRINT_ERROR("%s", "Session is not empty");
++ res = -EBUSY;
++ goto out;
++ }
++ if (remove_proc)
++ scst_proc_del_acg_tree(acg_proc_root, acg->acg_name);
++ scst_del_free_acg(acg);
++ }
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++static int scst_proc_rename_acg(struct scst_acg *acg, const char *new_name)
++{
++ int res = 0, len = strlen(new_name) + 1;
++ char *name;
++ struct proc_dir_entry *old_acg_proc_root = acg->acg_proc_root;
++
++ TRACE_ENTRY();
++
++ name = kmalloc(len, GFP_KERNEL);
++ if (name == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of new name failed");
++ goto out_nomem;
++ }
++ strlcpy(name, new_name, len);
++
++ res = scst_proc_group_add_tree(acg, new_name);
++ if (res != 0)
++ goto out_free;
++
++ scst_proc_del_acg_tree(old_acg_proc_root, acg->acg_name);
++
++ kfree(acg->acg_name);
++ acg->acg_name = name;
++
++ scst_check_reassign_sessions();
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(name);
++
++out_nomem:
++ res = -ENOMEM;
++ goto out;
++}
++
++static int __init scst_proc_init_groups(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /* create the proc directory entry for the device */
++ scst_proc_groups_root = proc_mkdir(SCST_PROC_GROUPS_ENTRY_NAME,
++ scst_proc_scsi_tgt);
++ if (scst_proc_groups_root == NULL) {
++ PRINT_ERROR("Not enough memory to register %s entry in "
++ "/proc/%s", SCST_PROC_GROUPS_ENTRY_NAME,
++ SCST_PROC_ENTRY_NAME);
++ goto out_nomem;
++ }
++
++ res = scst_proc_group_add_tree(scst_default_acg,
++ SCST_DEFAULT_ACG_NAME);
++ if (res != 0)
++ goto out_remove;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_remove:
++ remove_proc_entry(SCST_PROC_GROUPS_ENTRY_NAME, scst_proc_scsi_tgt);
++
++out_nomem:
++ res = -ENOMEM;
++ goto out;
++}
++
++static void scst_proc_cleanup_groups(void)
++{
++ struct scst_acg *acg_tmp, *acg;
++
++ TRACE_ENTRY();
++
++ /* remove all groups (dir & entries) */
++ list_for_each_entry_safe(acg, acg_tmp, &scst_acg_list,
++ acg_list_entry) {
++ scst_proc_del_free_acg(acg, 1);
++ }
++
++ scst_proc_del_acg_tree(scst_default_acg->acg_proc_root,
++ SCST_DEFAULT_ACG_NAME);
++ TRACE_DBG("remove_proc_entry(%s, %p)",
++ SCST_PROC_GROUPS_ENTRY_NAME, scst_proc_scsi_tgt);
++ remove_proc_entry(SCST_PROC_GROUPS_ENTRY_NAME, scst_proc_scsi_tgt);
++
++ TRACE_EXIT();
++}
++
++static int __init scst_proc_init_sgv(void)
++{
++ int res = 0;
++ struct proc_dir_entry *pr;
++
++ TRACE_ENTRY();
++
++ pr = scst_create_proc_entry(scst_proc_scsi_tgt, "sgv",
++ &scst_sgv_proc_data);
++ if (pr == NULL) {
++ PRINT_ERROR("%s", "cannot create sgv /proc entry");
++ res = -ENOMEM;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void __exit scst_proc_cleanup_sgv(void)
++{
++ TRACE_ENTRY();
++ remove_proc_entry("sgv", scst_proc_scsi_tgt);
++ TRACE_EXIT();
++}
++
++int __init scst_proc_init_module(void)
++{
++ int res = 0;
++ struct proc_dir_entry *generic;
++
++ TRACE_ENTRY();
++
++ scst_proc_scsi_tgt = proc_mkdir(SCST_PROC_ENTRY_NAME, NULL);
++ if (!scst_proc_scsi_tgt) {
++ PRINT_ERROR("cannot init /proc/%s", SCST_PROC_ENTRY_NAME);
++ goto out_nomem;
++ }
++
++ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
++ SCST_PROC_ENTRY_NAME,
++ &scst_tgt_proc_data);
++ if (!generic) {
++ PRINT_ERROR("cannot init /proc/%s/%s",
++ SCST_PROC_ENTRY_NAME, SCST_PROC_ENTRY_NAME);
++ goto out_remove;
++ }
++
++ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
++ SCST_PROC_VERSION_NAME,
++ &scst_version_proc_data);
++ if (!generic) {
++ PRINT_ERROR("cannot init /proc/%s/%s",
++ SCST_PROC_ENTRY_NAME, SCST_PROC_VERSION_NAME);
++ goto out_remove1;
++ }
++
++ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
++ SCST_PROC_SESSIONS_NAME,
++ &scst_sessions_proc_data);
++ if (!generic) {
++ PRINT_ERROR("cannot init /proc/%s/%s",
++ SCST_PROC_ENTRY_NAME, SCST_PROC_SESSIONS_NAME);
++ goto out_remove2;
++ }
++
++ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
++ SCST_PROC_HELP_NAME,
++ &scst_help_proc_data);
++ if (!generic) {
++ PRINT_ERROR("cannot init /proc/%s/%s",
++ SCST_PROC_ENTRY_NAME, SCST_PROC_HELP_NAME);
++ goto out_remove3;
++ }
++
++ generic = scst_create_proc_entry(scst_proc_scsi_tgt,
++ SCST_PROC_THREADS_NAME,
++ &scst_threads_proc_data);
++ if (!generic) {
++ PRINT_ERROR("cannot init /proc/%s/%s",
++ SCST_PROC_ENTRY_NAME, SCST_PROC_THREADS_NAME);
++ goto out_remove4;
++ }
++
++ if (scst_proc_init_module_log() < 0)
++ goto out_remove5;
++
++ if (scst_proc_init_groups() < 0)
++ goto out_remove6;
++
++ if (scst_proc_init_sgv() < 0)
++ goto out_remove7;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_remove7:
++ scst_proc_cleanup_groups();
++
++out_remove6:
++ scst_proc_cleanup_module_log();
++
++out_remove5:
++ remove_proc_entry(SCST_PROC_THREADS_NAME, scst_proc_scsi_tgt);
++
++out_remove4:
++ remove_proc_entry(SCST_PROC_HELP_NAME, scst_proc_scsi_tgt);
++
++out_remove3:
++ remove_proc_entry(SCST_PROC_SESSIONS_NAME, scst_proc_scsi_tgt);
++
++out_remove2:
++ remove_proc_entry(SCST_PROC_VERSION_NAME, scst_proc_scsi_tgt);
++
++out_remove1:
++ remove_proc_entry(SCST_PROC_ENTRY_NAME, scst_proc_scsi_tgt);
++
++out_remove:
++ remove_proc_entry(SCST_PROC_ENTRY_NAME, NULL);
++
++out_nomem:
++ res = -ENOMEM;
++ goto out;
++}
++
++void __exit scst_proc_cleanup_module(void)
++{
++ TRACE_ENTRY();
++
++ /* We may not bother about locks here */
++ scst_proc_cleanup_sgv();
++ scst_proc_cleanup_groups();
++ scst_proc_cleanup_module_log();
++ remove_proc_entry(SCST_PROC_THREADS_NAME, scst_proc_scsi_tgt);
++ remove_proc_entry(SCST_PROC_HELP_NAME, scst_proc_scsi_tgt);
++ remove_proc_entry(SCST_PROC_SESSIONS_NAME, scst_proc_scsi_tgt);
++ remove_proc_entry(SCST_PROC_VERSION_NAME, scst_proc_scsi_tgt);
++ remove_proc_entry(SCST_PROC_ENTRY_NAME, scst_proc_scsi_tgt);
++ remove_proc_entry(SCST_PROC_ENTRY_NAME, NULL);
++
++ TRACE_EXIT();
++}
++
++static ssize_t scst_proc_threads_write(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *off)
++{
++ int res = length;
++ int oldtn, newtn, delta;
++ char *buffer;
++
++ TRACE_ENTRY();
++
++ if (length > SCST_PROC_BLOCK_SIZE) {
++ res = -EOVERFLOW;
++ goto out;
++ }
++ if (!buf) {
++ res = -EINVAL;
++ goto out;
++ }
++ buffer = (char *)__get_free_page(GFP_KERNEL);
++ if (!buffer) {
++ res = -ENOMEM;
++ goto out;
++ }
++ if (copy_from_user(buffer, buf, length)) {
++ res = -EFAULT;
++ goto out_free;
++ }
++ if (length < PAGE_SIZE) {
++ buffer[length] = '\0';
++ } else if (buffer[PAGE_SIZE-1]) {
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
++ res = -EINTR;
++ goto out_free;
++ }
++
++ mutex_lock(&scst_mutex);
++
++ oldtn = scst_main_cmd_threads.nr_threads;
++ newtn = simple_strtoul(buffer, NULL, 0);
++ if (newtn <= 0) {
++ PRINT_ERROR("Illegal threads num value %d", newtn);
++ res = -EINVAL;
++ goto out_up_thr_free;
++ }
++ delta = newtn - oldtn;
++ if (delta < 0)
++ scst_del_threads(&scst_main_cmd_threads, -delta);
++ else {
++ int rc = scst_add_threads(&scst_main_cmd_threads, NULL, NULL,
++ delta);
++ if (rc != 0)
++ res = rc;
++ }
++
++ PRINT_INFO("Changed cmd threads num: old %d, new %d", oldtn, newtn);
++
++out_up_thr_free:
++ mutex_unlock(&scst_mutex);
++
++ mutex_unlock(&scst_proc_mutex);
++
++out_free:
++ free_page((unsigned long)buffer);
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++int scst_build_proc_target_dir_entries(struct scst_tgt_template *vtt)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /* create the proc directory entry for the device */
++ vtt->proc_tgt_root = proc_mkdir(vtt->name, scst_proc_scsi_tgt);
++ if (vtt->proc_tgt_root == NULL) {
++ PRINT_ERROR("Not enough memory to register SCSI target %s "
++ "in /proc/%s", vtt->name, SCST_PROC_ENTRY_NAME);
++ goto out_nomem;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_nomem:
++ res = -ENOMEM;
++ goto out;
++}
++
++void scst_cleanup_proc_target_dir_entries(struct scst_tgt_template *vtt)
++{
++ TRACE_ENTRY();
++
++ remove_proc_entry(vtt->name, scst_proc_scsi_tgt);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called under scst_mutex */
++int scst_build_proc_target_entries(struct scst_tgt *vtt)
++{
++ int res = 0;
++ struct proc_dir_entry *p;
++ char name[20];
++
++ TRACE_ENTRY();
++
++ if (vtt->tgtt->read_proc || vtt->tgtt->write_proc) {
++ /* create the proc file entry for the device */
++ scnprintf(name, sizeof(name), "%d", vtt->tgtt->proc_dev_num);
++ scst_scsi_tgt_proc_data.data = (void *)vtt;
++ p = scst_create_proc_entry(vtt->tgtt->proc_tgt_root,
++ name,
++ &scst_scsi_tgt_proc_data);
++ if (p == NULL) {
++ PRINT_ERROR("Not enough memory to register SCSI "
++ "target entry %s in /proc/%s/%s", name,
++ SCST_PROC_ENTRY_NAME, vtt->tgtt->name);
++ res = -ENOMEM;
++ goto out;
++ }
++ vtt->proc_num = vtt->tgtt->proc_dev_num;
++ vtt->tgtt->proc_dev_num++;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++void scst_cleanup_proc_target_entries(struct scst_tgt *vtt)
++{
++ char name[20];
++
++ TRACE_ENTRY();
++
++ if (vtt->tgtt->read_proc || vtt->tgtt->write_proc) {
++ scnprintf(name, sizeof(name), "%d", vtt->proc_num);
++ remove_proc_entry(name, vtt->tgtt->proc_tgt_root);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static ssize_t scst_proc_scsi_tgt_write(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *off)
++{
++ struct scst_tgt *vtt =
++ (struct scst_tgt *)PDE(file->f_dentry->d_inode)->data;
++ ssize_t res = 0;
++ char *buffer;
++ char *start;
++ int eof = 0;
++
++ TRACE_ENTRY();
++
++ if (vtt->tgtt->write_proc == NULL) {
++ res = -ENOSYS;
++ goto out;
++ }
++
++ if (length > SCST_PROC_BLOCK_SIZE) {
++ res = -EOVERFLOW;
++ goto out;
++ }
++ if (!buf) {
++ res = -EINVAL;
++ goto out;
++ }
++ buffer = (char *)__get_free_page(GFP_KERNEL);
++ if (!buffer) {
++ res = -ENOMEM;
++ goto out;
++ }
++ if (copy_from_user(buffer, buf, length)) {
++ res = -EFAULT;
++ goto out_free;
++ }
++ if (length < PAGE_SIZE) {
++ buffer[length] = '\0';
++ } else if (buffer[PAGE_SIZE-1]) {
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ TRACE_BUFFER("Buffer", buffer, length);
++
++ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
++ res = -EINTR;
++ goto out_free;
++ }
++
++ res = vtt->tgtt->write_proc(buffer, &start, 0, length, &eof, vtt);
++
++ mutex_unlock(&scst_proc_mutex);
++
++out_free:
++ free_page((unsigned long)buffer);
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++int scst_build_proc_dev_handler_dir_entries(struct scst_dev_type *dev_type)
++{
++ int res = 0;
++ struct proc_dir_entry *p;
++ const char *name; /* workaround to keep /proc ABI intact */
++
++ TRACE_ENTRY();
++
++ BUG_ON(dev_type->proc_dev_type_root);
++
++ if (strcmp(dev_type->name, "vdisk_fileio") == 0)
++ name = "vdisk";
++ else
++ name = dev_type->name;
++
++ /* create the proc directory entry for the dev type handler */
++ dev_type->proc_dev_type_root = proc_mkdir(name,
++ scst_proc_scsi_tgt);
++ if (dev_type->proc_dev_type_root == NULL) {
++ PRINT_ERROR("Not enough memory to register dev handler dir "
++ "%s in /proc/%s", name, SCST_PROC_ENTRY_NAME);
++ goto out_nomem;
++ }
++
++ scst_dev_handler_type_proc_data.data = dev_type;
++ if (dev_type->type >= 0) {
++ p = scst_create_proc_entry(dev_type->proc_dev_type_root,
++ SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME,
++ &scst_dev_handler_type_proc_data);
++ if (p == NULL) {
++ PRINT_ERROR("Not enough memory to register dev "
++ "handler entry %s in /proc/%s/%s",
++ SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME,
++ SCST_PROC_ENTRY_NAME, name);
++ goto out_remove;
++ }
++ }
++
++ if (dev_type->read_proc || dev_type->write_proc) {
++ /* create the proc file entry for the dev type handler */
++ scst_dev_handler_proc_data.data = (void *)dev_type;
++ p = scst_create_proc_entry(dev_type->proc_dev_type_root,
++ name,
++ &scst_dev_handler_proc_data);
++ if (p == NULL) {
++ PRINT_ERROR("Not enough memory to register dev "
++ "handler entry %s in /proc/%s/%s", name,
++ SCST_PROC_ENTRY_NAME, name);
++ goto out_remove1;
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_remove1:
++ if (dev_type->type >= 0)
++ remove_proc_entry(SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME,
++ dev_type->proc_dev_type_root);
++
++out_remove:
++ remove_proc_entry(name, scst_proc_scsi_tgt);
++
++out_nomem:
++ res = -ENOMEM;
++ goto out;
++}
++
++void scst_cleanup_proc_dev_handler_dir_entries(struct scst_dev_type *dev_type)
++{
++ /* Workaround to keep /proc ABI intact */
++ const char *name;
++
++ TRACE_ENTRY();
++
++ BUG_ON(dev_type->proc_dev_type_root == NULL);
++
++ if (strcmp(dev_type->name, "vdisk_fileio") == 0)
++ name = "vdisk";
++ else
++ name = dev_type->name;
++
++ if (dev_type->type >= 0) {
++ remove_proc_entry(SCST_PROC_DEV_HANDLER_TYPE_ENTRY_NAME,
++ dev_type->proc_dev_type_root);
++ }
++ if (dev_type->read_proc || dev_type->write_proc)
++ remove_proc_entry(name, dev_type->proc_dev_type_root);
++ remove_proc_entry(name, scst_proc_scsi_tgt);
++ dev_type->proc_dev_type_root = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++static ssize_t scst_proc_scsi_dev_handler_write(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *off)
++{
++ struct scst_dev_type *dev_type =
++ (struct scst_dev_type *)PDE(file->f_dentry->d_inode)->data;
++ ssize_t res = 0;
++ char *buffer;
++ char *start;
++ int eof = 0;
++
++ TRACE_ENTRY();
++
++ if (dev_type->write_proc == NULL) {
++ res = -ENOSYS;
++ goto out;
++ }
++
++ if (length > SCST_PROC_BLOCK_SIZE) {
++ res = -EOVERFLOW;
++ goto out;
++ }
++ if (!buf) {
++ res = -EINVAL;
++ goto out;
++ }
++
++ buffer = (char *)__get_free_page(GFP_KERNEL);
++ if (!buffer) {
++ res = -ENOMEM;
++ goto out;
++ }
++
++ if (copy_from_user(buffer, buf, length)) {
++ res = -EFAULT;
++ goto out_free;
++ }
++ if (length < PAGE_SIZE) {
++ buffer[length] = '\0';
++ } else if (buffer[PAGE_SIZE-1]) {
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ TRACE_BUFFER("Buffer", buffer, length);
++
++ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
++ res = -EINTR;
++ goto out_free;
++ }
++
++ res = dev_type->write_proc(buffer, &start, 0, length, &eof, dev_type);
++
++ mutex_unlock(&scst_proc_mutex);
++
++out_free:
++ free_page((unsigned long)buffer);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *off)
++{
++ int res, rc = 0, action;
++ char *buffer, *p, *pp, *ppp;
++ struct scst_acg *a, *acg = NULL;
++ unsigned int addr_method = SCST_LUN_ADDR_METHOD_PERIPHERAL;
++
++ TRACE_ENTRY();
++
++ if (length > SCST_PROC_BLOCK_SIZE) {
++ res = -EOVERFLOW;
++ goto out;
++ }
++ if (!buf) {
++ res = -EINVAL;
++ goto out;
++ }
++ buffer = (char *)__get_free_page(GFP_KERNEL);
++ if (!buffer) {
++ res = -ENOMEM;
++ goto out;
++ }
++ if (copy_from_user(buffer, buf, length)) {
++ res = -EFAULT;
++ goto out_free;
++ }
++ if (length < PAGE_SIZE) {
++ buffer[length] = '\0';
++ } else if (buffer[PAGE_SIZE-1]) {
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ /*
++ * Usage: echo "add_group GROUP_NAME [FLAT]" >/proc/scsi_tgt/scsi_tgt
++ * or echo "del_group GROUP_NAME" >/proc/scsi_tgt/scsi_tgt
++ * or echo "rename_group OLD_NAME NEW_NAME" >/proc/scsi_tgt/scsi_tgt"
++ * or echo "assign H:C:I:L HANDLER_NAME" >/proc/scsi_tgt/scsi_tgt
++ */
++ p = buffer;
++ if (p[strlen(p) - 1] == '\n')
++ p[strlen(p) - 1] = '\0';
++ if (!strncasecmp("assign ", p, 7)) {
++ p += 7;
++ action = SCST_PROC_ACTION_ASSIGN;
++ } else if (!strncasecmp("add_group ", p, 10)) {
++ p += 10;
++ action = SCST_PROC_ACTION_ADD_GROUP;
++ } else if (!strncasecmp("del_group ", p, 10)) {
++ p += 10;
++ action = SCST_PROC_ACTION_DEL_GROUP;
++ } else if (!strncasecmp("rename_group ", p, 13)) {
++ p += 13;
++ action = SCST_PROC_ACTION_RENAME_GROUP;
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out_free;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_free_resume;
++ }
++
++ res = length;
++
++ while (isspace(*p) && *p != '\0')
++ p++;
++
++ switch (action) {
++ case SCST_PROC_ACTION_ADD_GROUP:
++ case SCST_PROC_ACTION_DEL_GROUP:
++ case SCST_PROC_ACTION_RENAME_GROUP:
++ pp = p;
++ while (!isspace(*pp) && *pp != '\0')
++ pp++;
++ if (*pp != '\0') {
++ *pp = '\0';
++ pp++;
++ while (isspace(*pp) && *pp != '\0')
++ pp++;
++ if (*pp != '\0') {
++ switch (action) {
++ case SCST_PROC_ACTION_ADD_GROUP:
++ ppp = pp;
++ while (!isspace(*ppp) && *ppp != '\0')
++ ppp++;
++ if (*ppp != '\0') {
++ *ppp = '\0';
++ ppp++;
++ while (isspace(*ppp) && *ppp != '\0')
++ ppp++;
++ if (*ppp != '\0') {
++ PRINT_ERROR("%s", "Too many "
++ "arguments");
++ res = -EINVAL;
++ goto out_up_free;
++ }
++ }
++ if (strcasecmp(pp, "FLAT") != 0) {
++ PRINT_ERROR("Unexpected "
++ "argument %s", pp);
++ res = -EINVAL;
++ goto out_up_free;
++ } else
++ addr_method = SCST_LUN_ADDR_METHOD_FLAT;
++ break;
++ case SCST_PROC_ACTION_DEL_GROUP:
++ PRINT_ERROR("%s", "Too many "
++ "arguments");
++ res = -EINVAL;
++ goto out_up_free;
++ }
++ }
++ }
++
++ if (strcmp(p, SCST_DEFAULT_ACG_NAME) == 0) {
++ PRINT_ERROR("Attempt to add/delete/rename predefined "
++ "group \"%s\"", p);
++ res = -EINVAL;
++ goto out_up_free;
++ }
++
++ list_for_each_entry(a, &scst_acg_list, acg_list_entry) {
++ if (strcmp(a->acg_name, p) == 0) {
++ TRACE_DBG("group (acg) %p %s found",
++ a, a->acg_name);
++ acg = a;
++ break;
++ }
++ }
++
++ switch (action) {
++ case SCST_PROC_ACTION_ADD_GROUP:
++ if (acg) {
++ PRINT_ERROR("acg name %s exist", p);
++ res = -EINVAL;
++ goto out_up_free;
++ }
++ rc = scst_proc_group_add(p, addr_method);
++ break;
++ case SCST_PROC_ACTION_DEL_GROUP:
++ if (acg == NULL) {
++ PRINT_ERROR("acg name %s not found", p);
++ res = -EINVAL;
++ goto out_up_free;
++ }
++ rc = scst_proc_del_free_acg(acg, 1);
++ break;
++ case SCST_PROC_ACTION_RENAME_GROUP:
++ if (acg == NULL) {
++ PRINT_ERROR("acg name %s not found", p);
++ res = -EINVAL;
++ goto out_up_free;
++ }
++
++ p = pp;
++ while (!isspace(*pp) && *pp != '\0')
++ pp++;
++ if (*pp != '\0') {
++ *pp = '\0';
++ pp++;
++ while (isspace(*pp) && *pp != '\0')
++ pp++;
++ if (*pp != '\0') {
++ PRINT_ERROR("%s", "Too many arguments");
++ res = -EINVAL;
++ goto out_up_free;
++ }
++ }
++ rc = scst_proc_rename_acg(acg, p);
++ break;
++ }
++ break;
++ case SCST_PROC_ACTION_ASSIGN:
++ rc = scst_proc_assign_handler(p);
++ break;
++ }
++
++ if (rc != 0)
++ res = rc;
++
++out_up_free:
++ mutex_unlock(&scst_mutex);
++
++out_free_resume:
++ scst_resume_activity();
++
++out_free:
++ free_page((unsigned long)buffer);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* The activity supposed to be suspended and scst_mutex held */
++static int scst_proc_assign_handler(char *buf)
++{
++ int res = 0;
++ char *p = buf, *e, *ee;
++ unsigned long host, channel = 0, id = 0, lun = 0;
++ struct scst_device *d, *dev = NULL;
++ struct scst_dev_type *dt, *handler = NULL;
++
++ TRACE_ENTRY();
++
++ while (isspace(*p) && *p != '\0')
++ p++;
++
++ host = simple_strtoul(p, &p, 0);
++ if ((host == ULONG_MAX) || (*p != ':'))
++ goto out_synt_err;
++ p++;
++ channel = simple_strtoul(p, &p, 0);
++ if ((channel == ULONG_MAX) || (*p != ':'))
++ goto out_synt_err;
++ p++;
++ id = simple_strtoul(p, &p, 0);
++ if ((channel == ULONG_MAX) || (*p != ':'))
++ goto out_synt_err;
++ p++;
++ lun = simple_strtoul(p, &p, 0);
++ if (lun == ULONG_MAX)
++ goto out_synt_err;
++
++ e = p;
++ e++;
++ while (isspace(*e) && *e != '\0')
++ e++;
++ ee = e;
++ while (!isspace(*ee) && *ee != '\0')
++ ee++;
++ *ee = '\0';
++
++ TRACE_DBG("Dev %ld:%ld:%ld:%ld, handler %s", host, channel, id, lun, e);
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if ((d->virt_id == 0) &&
++ d->scsi_dev->host->host_no == host &&
++ d->scsi_dev->channel == channel &&
++ d->scsi_dev->id == id &&
++ d->scsi_dev->lun == lun) {
++ dev = d;
++ TRACE_DBG("Dev %p (%ld:%ld:%ld:%ld) found",
++ dev, host, channel, id, lun);
++ break;
++ }
++ }
++
++ if (dev == NULL) {
++ PRINT_ERROR("Device %ld:%ld:%ld:%ld not found",
++ host, channel, id, lun);
++ res = -EINVAL;
++ goto out;
++ }
++
++ list_for_each_entry(dt, &scst_dev_type_list, dev_type_list_entry) {
++ if (!strcmp(dt->name, e)) {
++ handler = dt;
++ TRACE_DBG("Dev handler %p with name %s found",
++ dt, dt->name);
++ break;
++ }
++ }
++
++ if (handler == NULL) {
++ PRINT_ERROR("Handler %s not found", e);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (dev->scsi_dev->type != handler->type) {
++ PRINT_ERROR("Type %d of device %s differs from type "
++ "%d of dev handler %s", dev->type,
++ dev->handler->name, handler->type, handler->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ res = scst_assign_dev_handler(dev, handler);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_synt_err:
++ PRINT_ERROR("Syntax error on %s", p);
++ res = -EINVAL;
++ goto out;
++}
++
++static ssize_t scst_proc_groups_devices_write(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *off)
++{
++ int res, action, rc, read_only = 0;
++ char *buffer, *p, *e = NULL;
++ unsigned int virt_lun;
++ struct scst_acg *acg =
++ (struct scst_acg *)PDE(file->f_dentry->d_inode)->data;
++ struct scst_acg_dev *acg_dev = NULL, *acg_dev_tmp;
++ struct scst_device *d, *dev = NULL;
++
++ TRACE_ENTRY();
++
++ if (length > SCST_PROC_BLOCK_SIZE) {
++ res = -EOVERFLOW;
++ goto out;
++ }
++ if (!buf) {
++ res = -EINVAL;
++ goto out;
++ }
++ buffer = (char *)__get_free_page(GFP_KERNEL);
++ if (!buffer) {
++ res = -ENOMEM;
++ goto out;
++ }
++ if (copy_from_user(buffer, buf, length)) {
++ res = -EFAULT;
++ goto out_free;
++ }
++ if (length < PAGE_SIZE) {
++ buffer[length] = '\0';
++ } else if (buffer[PAGE_SIZE-1]) {
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ /*
++ * Usage: echo "add|del H:C:I:L lun [READ_ONLY]" \
++ * >/proc/scsi_tgt/groups/GROUP_NAME/devices
++ * or echo "replace H:C:I:L lun [READ_ONLY]" \
++ * >/proc/scsi_tgt/groups/GROUP_NAME/devices
++ * or echo "add|del V_NAME lun [READ_ONLY]" \
++ * >/proc/scsi_tgt/groups/GROUP_NAME/devices
++ * or echo "replace V_NAME lun [READ_ONLY]" \
++ * >/proc/scsi_tgt/groups/GROUP_NAME/devices
++ * or echo "clear" >/proc/scsi_tgt/groups/GROUP_NAME/devices
++ */
++ p = buffer;
++ if (p[strlen(p) - 1] == '\n')
++ p[strlen(p) - 1] = '\0';
++ if (!strncasecmp("clear", p, 5)) {
++ action = SCST_PROC_ACTION_CLEAR;
++ } else if (!strncasecmp("add ", p, 4)) {
++ p += 4;
++ action = SCST_PROC_ACTION_ADD;
++ } else if (!strncasecmp("del ", p, 4)) {
++ p += 4;
++ action = SCST_PROC_ACTION_DEL;
++ } else if (!strncasecmp("replace ", p, 8)) {
++ p += 8;
++ action = SCST_PROC_ACTION_REPLACE;
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out_free;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_free_resume;
++ }
++
++ res = length;
++
++ switch (action) {
++ case SCST_PROC_ACTION_ADD:
++ case SCST_PROC_ACTION_DEL:
++ case SCST_PROC_ACTION_REPLACE:
++ while (isspace(*p) && *p != '\0')
++ p++;
++ e = p; /* save p */
++ while (!isspace(*e) && *e != '\0')
++ e++;
++ *e = 0;
++
++ list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
++ if (!strcmp(d->virt_name, p)) {
++ dev = d;
++ TRACE_DBG("Device %p (%s) found", dev, p);
++ break;
++ }
++ }
++ if (dev == NULL) {
++ PRINT_ERROR("Device %s not found", p);
++ res = -EINVAL;
++ goto out_free_up;
++ }
++ break;
++ }
++
++ /* ToDo: create separate functions */
++
++ switch (action) {
++ case SCST_PROC_ACTION_ADD:
++ case SCST_PROC_ACTION_REPLACE:
++ {
++ bool dev_replaced = false;
++
++ e++;
++ while (isspace(*e) && *e != '\0')
++ e++;
++ virt_lun = simple_strtoul(e, &e, 0);
++
++ while (isspace(*e) && *e != '\0')
++ e++;
++
++ if (*e != '\0') {
++ if (!strncasecmp("READ_ONLY", e, 9))
++ read_only = 1;
++ else {
++ PRINT_ERROR("Unknown option \"%s\"", e);
++ res = -EINVAL;
++ goto out_free_up;
++ }
++ }
++
++ list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
++ acg_dev_list_entry) {
++ if (acg_dev_tmp->lun == virt_lun) {
++ acg_dev = acg_dev_tmp;
++ break;
++ }
++ }
++ if (acg_dev != NULL) {
++ if (action == SCST_PROC_ACTION_ADD) {
++ PRINT_ERROR("virt lun %d already exists in "
++ "group %s", virt_lun, acg->acg_name);
++ res = -EEXIST;
++ goto out_free_up;
++ } else {
++ /* Replace */
++ rc = scst_acg_del_lun(acg, acg_dev->lun,
++ false);
++ if (rc) {
++ res = rc;
++ goto out_free_up;
++ }
++ dev_replaced = true;
++ }
++ }
++
++ rc = scst_acg_add_lun(acg, NULL, dev, virt_lun, read_only,
++ false, NULL);
++ if (rc) {
++ res = rc;
++ goto out_free_up;
++ }
++
++ if (action == SCST_PROC_ACTION_ADD)
++ scst_report_luns_changed(acg);
++
++ if (dev_replaced) {
++ struct scst_tgt_dev *tgt_dev;
++
++ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
++ dev_tgt_dev_list_entry) {
++ if ((tgt_dev->acg_dev->acg == acg) &&
++ (tgt_dev->lun == virt_lun)) {
++ TRACE_MGMT_DBG("INQUIRY DATA HAS CHANGED"
++ " on tgt_dev %p", tgt_dev);
++ scst_gen_aen_or_ua(tgt_dev,
++ SCST_LOAD_SENSE(scst_sense_inquery_data_changed));
++ }
++ }
++ }
++ break;
++ }
++ case SCST_PROC_ACTION_DEL:
++ {
++ /*
++ * This code doesn't handle if there are >1 LUNs for the same
++ * device in the group. Instead, it always deletes the first
++ * entry. It wasn't fixed for compatibility reasons, because
++ * procfs is now obsoleted.
++ */
++ struct scst_acg_dev *a;
++ list_for_each_entry(a, &acg->acg_dev_list, acg_dev_list_entry) {
++ if (a->dev == dev) {
++ rc = scst_acg_del_lun(acg, a->lun, true);
++ if (rc) {
++ res = rc;
++ goto out_free_up;
++ }
++ break;
++ }
++ }
++ PRINT_ERROR("Device is not found in group %s", acg->acg_name);
++ break;
++ }
++ case SCST_PROC_ACTION_CLEAR:
++ list_for_each_entry_safe(acg_dev, acg_dev_tmp,
++ &acg->acg_dev_list,
++ acg_dev_list_entry) {
++ rc = scst_acg_del_lun(acg, acg_dev->lun,
++ list_is_last(&acg_dev->acg_dev_list_entry,
++ &acg->acg_dev_list));
++ if (rc) {
++ res = rc;
++ goto out_free_up;
++ }
++ }
++ break;
++ }
++
++out_free_up:
++ mutex_unlock(&scst_mutex);
++
++out_free_resume:
++ scst_resume_activity();
++
++out_free:
++ free_page((unsigned long)buffer);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_proc_groups_names_write(struct file *file,
++ const char __user *buf,
++ size_t length, loff_t *off)
++{
++ int res = length, rc = 0, action;
++ char *buffer, *p, *pp = NULL;
++ struct scst_acg *acg =
++ (struct scst_acg *)PDE(file->f_dentry->d_inode)->data;
++ struct scst_acn *n, *nn;
++
++ TRACE_ENTRY();
++
++ if (length > SCST_PROC_BLOCK_SIZE) {
++ res = -EOVERFLOW;
++ goto out;
++ }
++ if (!buf) {
++ res = -EINVAL;
++ goto out;
++ }
++ buffer = (char *)__get_free_page(GFP_KERNEL);
++ if (!buffer) {
++ res = -ENOMEM;
++ goto out;
++ }
++ if (copy_from_user(buffer, buf, length)) {
++ res = -EFAULT;
++ goto out_free;
++ }
++ if (length < PAGE_SIZE) {
++ buffer[length] = '\0';
++ } else if (buffer[PAGE_SIZE-1]) {
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ /*
++ * Usage: echo "add|del NAME" >/proc/scsi_tgt/groups/GROUP_NAME/names
++ * or echo "move NAME NEW_GROUP_NAME" >/proc/scsi_tgt/groups/OLD_GROUP_NAME/names"
++ * or echo "clear" >/proc/scsi_tgt/groups/GROUP_NAME/names
++ */
++ p = buffer;
++ if (p[strlen(p) - 1] == '\n')
++ p[strlen(p) - 1] = '\0';
++ if (!strncasecmp("clear", p, 5)) {
++ action = SCST_PROC_ACTION_CLEAR;
++ } else if (!strncasecmp("add ", p, 4)) {
++ p += 4;
++ action = SCST_PROC_ACTION_ADD;
++ } else if (!strncasecmp("del ", p, 4)) {
++ p += 4;
++ action = SCST_PROC_ACTION_DEL;
++ } else if (!strncasecmp("move ", p, 5)) {
++ p += 5;
++ action = SCST_PROC_ACTION_MOVE;
++ } else {
++ PRINT_ERROR("Unknown action \"%s\"", p);
++ res = -EINVAL;
++ goto out_free;
++ }
++
++ switch (action) {
++ case SCST_PROC_ACTION_ADD:
++ case SCST_PROC_ACTION_DEL:
++ case SCST_PROC_ACTION_MOVE:
++ while (isspace(*p) && *p != '\0')
++ p++;
++ pp = p;
++ while (!isspace(*pp) && *pp != '\0')
++ pp++;
++ if (*pp != '\0') {
++ *pp = '\0';
++ pp++;
++ while (isspace(*pp) && *pp != '\0')
++ pp++;
++ if (*pp != '\0') {
++ switch (action) {
++ case SCST_PROC_ACTION_ADD:
++ case SCST_PROC_ACTION_DEL:
++ PRINT_ERROR("%s", "Too many "
++ "arguments");
++ res = -EINVAL;
++ goto out_free;
++ }
++ }
++ }
++ break;
++ }
++
++ rc = scst_suspend_activity(true);
++ if (rc != 0)
++ goto out_free;
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out_free_resume;
++ }
++
++ switch (action) {
++ case SCST_PROC_ACTION_ADD:
++ rc = scst_acg_add_acn(acg, p);
++ break;
++ case SCST_PROC_ACTION_DEL:
++ rc = scst_acg_remove_name(acg, p, true);
++ break;
++ case SCST_PROC_ACTION_MOVE:
++ {
++ struct scst_acg *a, *new_acg = NULL;
++ char *name = p;
++ p = pp;
++ while (!isspace(*pp) && *pp != '\0')
++ pp++;
++ if (*pp != '\0') {
++ *pp = '\0';
++ pp++;
++ while (isspace(*pp) && *pp != '\0')
++ pp++;
++ if (*pp != '\0') {
++ PRINT_ERROR("%s", "Too many arguments");
++ res = -EINVAL;
++ goto out_free_unlock;
++ }
++ }
++ list_for_each_entry(a, &scst_acg_list, acg_list_entry) {
++ if (strcmp(a->acg_name, p) == 0) {
++ TRACE_DBG("group (acg) %p %s found",
++ a, a->acg_name);
++ new_acg = a;
++ break;
++ }
++ }
++ if (new_acg == NULL) {
++ PRINT_ERROR("Group %s not found", p);
++ res = -EINVAL;
++ goto out_free_unlock;
++ }
++ rc = scst_acg_remove_name(acg, name, false);
++ if (rc != 0)
++ goto out_free_unlock;
++ rc = scst_acg_add_acn(new_acg, name);
++ if (rc != 0)
++ scst_acg_add_acn(acg, name);
++ break;
++ }
++ case SCST_PROC_ACTION_CLEAR:
++ list_for_each_entry_safe(n, nn, &acg->acn_list,
++ acn_list_entry) {
++ scst_del_free_acn(n, false);
++ }
++ scst_check_reassign_sessions();
++ break;
++ }
++
++out_free_unlock:
++ mutex_unlock(&scst_mutex);
++
++out_free_resume:
++ scst_resume_activity();
++
++out_free:
++ free_page((unsigned long)buffer);
++
++out:
++ if (rc < 0)
++ res = rc;
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_version_info_show(struct seq_file *seq, void *v)
++{
++ TRACE_ENTRY();
++
++ seq_printf(seq, "%s\n", SCST_VERSION_STRING);
++
++#ifdef CONFIG_SCST_STRICT_SERIALIZING
++ seq_printf(seq, "STRICT_SERIALIZING\n");
++#endif
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ seq_printf(seq, "EXTRACHECKS\n");
++#endif
++
++#ifdef CONFIG_SCST_TRACING
++ seq_printf(seq, "TRACING\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++ seq_printf(seq, "DEBUG\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_TM
++ seq_printf(seq, "DEBUG_TM\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_RETRY
++ seq_printf(seq, "DEBUG_RETRY\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_OOM
++ seq_printf(seq, "DEBUG_OOM\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG_SN
++ seq_printf(seq, "DEBUG_SN\n");
++#endif
++
++#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
++ seq_printf(seq, "USE_EXPECTED_VALUES\n");
++#endif
++
++#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
++ seq_printf(seq, "TEST_IO_IN_SIRQ\n");
++#endif
++
++#ifdef CONFIG_SCST_STRICT_SECURITY
++ seq_printf(seq, "STRICT_SECURITY\n");
++#endif
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static struct scst_proc_data scst_version_proc_data = {
++ SCST_DEF_RW_SEQ_OP(NULL)
++ .show = scst_version_info_show,
++};
++
++static int scst_help_info_show(struct seq_file *seq, void *v)
++{
++ TRACE_ENTRY();
++
++ seq_printf(seq, "%s\n", scst_proc_help_string);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static struct scst_proc_data scst_help_proc_data = {
++ SCST_DEF_RW_SEQ_OP(NULL)
++ .show = scst_help_info_show,
++};
++
++static int scst_dev_handler_type_info_show(struct seq_file *seq, void *v)
++{
++ struct scst_dev_type *dev_type = (struct scst_dev_type *)seq->private;
++
++ TRACE_ENTRY();
++
++ seq_printf(seq, "%d - %s\n", dev_type->type,
++ dev_type->type > (int)ARRAY_SIZE(scst_proc_dev_handler_type)
++ ? "unknown" : scst_proc_dev_handler_type[dev_type->type]);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static struct scst_proc_data scst_dev_handler_type_proc_data = {
++ SCST_DEF_RW_SEQ_OP(NULL)
++ .show = scst_dev_handler_type_info_show,
++};
++
++static int scst_sessions_info_show(struct seq_file *seq, void *v)
++{
++ int res = 0;
++ struct scst_acg *acg;
++ struct scst_session *sess;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ seq_printf(seq, "%-20s %-45s %-35s %-15s\n",
++ "Target name", "Initiator name",
++ "Group name", "Active/All Commands Count");
++
++ list_for_each_entry(acg, &scst_acg_list, acg_list_entry) {
++ list_for_each_entry(sess, &acg->acg_sess_list,
++ acg_sess_list_entry) {
++ int active_cmds = 0, t;
++ for (t = TGT_DEV_HASH_SIZE-1; t >= 0; t--) {
++ struct list_head *sess_tgt_dev_list_head =
++ &sess->sess_tgt_dev_list_hash[t];
++ struct scst_tgt_dev *tgt_dev;
++ list_for_each_entry(tgt_dev,
++ sess_tgt_dev_list_head,
++ sess_tgt_dev_list_entry) {
++ active_cmds += atomic_read(&tgt_dev->tgt_dev_cmd_count);
++ }
++ }
++ seq_printf(seq, "%-20s %-45s %-35s %d/%d\n",
++ sess->tgt->tgtt->name,
++ sess->initiator_name,
++ acg->acg_name, active_cmds,
++ atomic_read(&sess->sess_cmd_count));
++ }
++ }
++
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_proc_data scst_sessions_proc_data = {
++ SCST_DEF_RW_SEQ_OP(NULL)
++ .show = scst_sessions_info_show,
++};
++
++static struct scst_proc_data scst_sgv_proc_data = {
++ SCST_DEF_RW_SEQ_OP(NULL)
++ .show = sgv_procinfo_show,
++};
++
++static int scst_groups_names_show(struct seq_file *seq, void *v)
++{
++ int res = 0;
++ struct scst_acg *acg = (struct scst_acg *)seq->private;
++ struct scst_acn *name;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ list_for_each_entry(name, &acg->acn_list, acn_list_entry) {
++ seq_printf(seq, "%s\n", name->name);
++ }
++
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_proc_data scst_groups_names_proc_data = {
++ SCST_DEF_RW_SEQ_OP(scst_proc_groups_names_write)
++ .show = scst_groups_names_show,
++};
++
++static int scst_groups_addr_method_show(struct seq_file *seq, void *v)
++{
++ int res = 0;
++ struct scst_acg *acg = (struct scst_acg *)seq->private;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ switch (acg->addr_method) {
++ case SCST_LUN_ADDR_METHOD_FLAT:
++ seq_printf(seq, "%s\n", "FLAT");
++ break;
++ case SCST_LUN_ADDR_METHOD_PERIPHERAL:
++ seq_printf(seq, "%s\n", "PERIPHERAL");
++ break;
++ default:
++ seq_printf(seq, "%s\n", "UNKNOWN");
++ break;
++ }
++
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++static struct scst_proc_data scst_groups_addr_method_proc_data = {
++ SCST_DEF_RW_SEQ_OP(NULL)
++ .show = scst_groups_addr_method_show,
++};
++static int scst_groups_devices_show(struct seq_file *seq, void *v)
++{
++ int res = 0;
++ struct scst_acg *acg = (struct scst_acg *)seq->private;
++ struct scst_acg_dev *acg_dev;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ seq_printf(seq, "%-60s%-13s%s\n", "Device (host:ch:id:lun or name)",
++ "LUN", "Options");
++
++ list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
++ seq_printf(seq, "%-60s%-13lld%s\n",
++ acg_dev->dev->virt_name,
++ (long long unsigned int)acg_dev->lun,
++ acg_dev->rd_only ? "RO" : "");
++ }
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_proc_data scst_groups_devices_proc_data = {
++ SCST_DEF_RW_SEQ_OP(scst_proc_groups_devices_write)
++ .show = scst_groups_devices_show,
++};
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++static int scst_proc_read_tlb(const struct scst_trace_log *tbl,
++ struct seq_file *seq,
++ unsigned long log_level, int *first)
++{
++ const struct scst_trace_log *t = tbl;
++ int res = 0;
++
++ while (t->token) {
++ if (log_level & t->val) {
++ seq_printf(seq, "%s%s", *first ? "" : " | ", t->token);
++ *first = 0;
++ }
++ t++;
++ }
++ return res;
++}
++
++int scst_proc_log_entry_read(struct seq_file *seq, unsigned long log_level,
++ const struct scst_trace_log *tbl)
++{
++ int res = 0, first = 1;
++
++ TRACE_ENTRY();
++
++ scst_proc_read_tlb(scst_proc_trace_tbl, seq, log_level, &first);
++
++ if (tbl)
++ scst_proc_read_tlb(tbl, seq, log_level, &first);
++
++ seq_printf(seq, "%s\n", first ? "none" : "");
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++EXPORT_SYMBOL_GPL(scst_proc_log_entry_read);
++
++static int log_info_show(struct seq_file *seq, void *v)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_log_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = scst_proc_log_entry_read(seq, trace_flag,
++ scst_proc_local_trace_tbl);
++
++ mutex_unlock(&scst_log_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_proc_data scst_log_proc_data = {
++ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_tgt_gen_write_log)
++ .show = log_info_show,
++ .data = "scsi_tgt",
++};
++
++#endif
++
++static int scst_tgt_info_show(struct seq_file *seq, void *v)
++{
++ int res = 0;
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ seq_printf(seq, "%-60s%s\n", "Device (host:ch:id:lun or name)",
++ "Device handler");
++ list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
++ seq_printf(seq, "%-60s%s\n",
++ dev->virt_name, dev->handler->name);
++ }
++
++ mutex_unlock(&scst_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_proc_data scst_tgt_proc_data = {
++ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_tgt_gen_write)
++ .show = scst_tgt_info_show,
++};
++
++static int scst_threads_info_show(struct seq_file *seq, void *v)
++{
++ TRACE_ENTRY();
++
++ seq_printf(seq, "%d\n", scst_main_cmd_threads.nr_threads);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static struct scst_proc_data scst_threads_proc_data = {
++ SCST_DEF_RW_SEQ_OP(scst_proc_threads_write)
++ .show = scst_threads_info_show,
++};
++
++static int scst_scsi_tgtinfo_show(struct seq_file *seq, void *v)
++{
++ struct scst_tgt *vtt = seq->private;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ if (vtt->tgtt->read_proc)
++ res = vtt->tgtt->read_proc(seq, vtt);
++
++ mutex_unlock(&scst_proc_mutex);
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_proc_data scst_scsi_tgt_proc_data = {
++ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_tgt_write)
++ .show = scst_scsi_tgtinfo_show,
++};
++
++static int scst_dev_handler_info_show(struct seq_file *seq, void *v)
++{
++ struct scst_dev_type *dev_type = seq->private;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_proc_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ if (dev_type->read_proc)
++ res = dev_type->read_proc(seq, dev_type);
++
++ mutex_unlock(&scst_proc_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_proc_data scst_dev_handler_proc_data = {
++ SCST_DEF_RW_SEQ_OP(scst_proc_scsi_dev_handler_write)
++ .show = scst_dev_handler_info_show,
++};
++
++struct proc_dir_entry *scst_create_proc_entry(struct proc_dir_entry *root,
++ const char *name, struct scst_proc_data *pdata)
++{
++ struct proc_dir_entry *p = NULL;
++
++ TRACE_ENTRY();
++
++ if (root) {
++ mode_t mode;
++
++ mode = S_IFREG | S_IRUGO | (pdata->seq_op.write ? S_IWUSR : 0);
++ p = create_proc_entry(name, mode, root);
++ if (p == NULL) {
++ PRINT_ERROR("Fail to create entry %s in /proc", name);
++ } else {
++ p->proc_fops = &pdata->seq_op;
++ p->data = pdata->data;
++ }
++ }
++
++ TRACE_EXIT();
++ return p;
++}
++EXPORT_SYMBOL_GPL(scst_create_proc_entry);
++
++int scst_single_seq_open(struct inode *inode, struct file *file)
++{
++ struct scst_proc_data *pdata = container_of(PDE(inode)->proc_fops,
++ struct scst_proc_data, seq_op);
++ return single_open(file, pdata->show, PDE(inode)->data);
++}
++EXPORT_SYMBOL_GPL(scst_single_seq_open);
++
++struct proc_dir_entry *scst_proc_get_tgt_root(
++ struct scst_tgt_template *vtt)
++{
++ return vtt->proc_tgt_root;
++}
++EXPORT_SYMBOL_GPL(scst_proc_get_tgt_root);
++
++struct proc_dir_entry *scst_proc_get_dev_type_root(
++ struct scst_dev_type *dtt)
++{
++ return dtt->proc_dev_type_root;
++}
++EXPORT_SYMBOL_GPL(scst_proc_get_dev_type_root);
+diff -uprN orig/linux-2.6.36/include/scst/scst_sgv.h linux-2.6.36/include/scst/scst_sgv.h
+--- orig/linux-2.6.36/include/scst/scst_sgv.h
++++ linux-2.6.36/include/scst/scst_sgv.h
+@@ -0,0 +1,98 @@
++/*
++ * include/scst_sgv.h
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * Include file for SCST SGV cache.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++#ifndef __SCST_SGV_H
++#define __SCST_SGV_H
++
++/** SGV pool routines and flag bits **/
++
++/* Set if the allocated object must be not from the cache */
++#define SGV_POOL_ALLOC_NO_CACHED 1
++
++/* Set if there should not be any memory allocations on a cache miss */
++#define SGV_POOL_NO_ALLOC_ON_CACHE_MISS 2
++
++/* Set an object should be returned even if it doesn't have SG vector built */
++#define SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL 4
++
++/*
++ * Set if the allocated object must be a new one, i.e. from the cache,
++ * but not cached
++ */
++#define SGV_POOL_ALLOC_GET_NEW 8
++
++struct sgv_pool_obj;
++struct sgv_pool;
++
++/*
++ * Structure to keep a memory limit for an SCST object
++ */
++struct scst_mem_lim {
++ /* How much memory allocated under this object */
++ atomic_t alloced_pages;
++
++ /*
++ * How much memory allowed to allocated under this object. Put here
++ * mostly to save a possible cache miss accessing scst_max_dev_cmd_mem.
++ */
++ int max_allowed_pages;
++};
++
++/* Types of clustering */
++enum sgv_clustering_types {
++ /* No clustering performed */
++ sgv_no_clustering = 0,
++
++ /*
++ * A page will only be merged with the latest previously allocated
++ * page, so the order of pages in the SG will be preserved.
++ */
++ sgv_tail_clustering,
++
++ /*
++ * Free merging of pages at any place in the SG is allowed. This mode
++ * usually provides the best merging rate.
++ */
++ sgv_full_clustering,
++};
++
++struct sgv_pool *sgv_pool_create(const char *name,
++ enum sgv_clustering_types clustered, int single_alloc_pages,
++ bool shared, int purge_interval);
++void sgv_pool_del(struct sgv_pool *pool);
++
++void sgv_pool_get(struct sgv_pool *pool);
++void sgv_pool_put(struct sgv_pool *pool);
++
++void sgv_pool_flush(struct sgv_pool *pool);
++
++void sgv_pool_set_allocator(struct sgv_pool *pool,
++ struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *),
++ void (*free_pages_fn)(struct scatterlist *, int, void *));
++
++struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
++ gfp_t gfp_mask, int flags, int *count,
++ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv);
++void sgv_pool_free(struct sgv_pool_obj *sgv, struct scst_mem_lim *mem_lim);
++
++void *sgv_get_priv(struct sgv_pool_obj *sgv);
++
++void scst_init_mem_lim(struct scst_mem_lim *mem_lim);
++
++#endif /* __SCST_SGV_H */
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_mem.h linux-2.6.36/drivers/scst/scst_mem.h
+--- orig/linux-2.6.36/drivers/scst/scst_mem.h
++++ linux-2.6.36/drivers/scst/scst_mem.h
+@@ -0,0 +1,151 @@
++/*
++ * scst_mem.h
++ *
++ * Copyright (C) 2006 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/scatterlist.h>
++#include <linux/workqueue.h>
++
++#define SGV_POOL_ELEMENTS 11
++
++/*
++ * sg_num is indexed by the page number, pg_count is indexed by the sg number.
++ * Made in one entry to simplify the code (eg all sizeof(*) parts) and save
++ * some CPU cache for non-clustered case.
++ */
++struct trans_tbl_ent {
++ unsigned short sg_num;
++ unsigned short pg_count;
++};
++
++/*
++ * SGV pool object
++ */
++struct sgv_pool_obj {
++ int cache_num;
++ int pages;
++
++ /* jiffies, protected by sgv_pool_lock */
++ unsigned long time_stamp;
++
++ struct list_head recycling_list_entry;
++ struct list_head sorted_recycling_list_entry;
++
++ struct sgv_pool *owner_pool;
++ int orig_sg;
++ int orig_length;
++ int sg_count;
++ void *allocator_priv;
++ struct trans_tbl_ent *trans_tbl;
++ struct scatterlist *sg_entries;
++ struct scatterlist sg_entries_data[0];
++};
++
++/*
++ * SGV pool statistics accounting structure
++ */
++struct sgv_pool_cache_acc {
++ atomic_t total_alloc, hit_alloc;
++ atomic_t merged;
++};
++
++/*
++ * SGV pool allocation functions
++ */
++struct sgv_pool_alloc_fns {
++ struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp_mask,
++ void *priv);
++ void (*free_pages_fn)(struct scatterlist *sg, int sg_count,
++ void *priv);
++};
++
++/*
++ * SGV pool
++ */
++struct sgv_pool {
++ enum sgv_clustering_types clustering_type;
++ int single_alloc_pages;
++ int max_cached_pages;
++
++ struct sgv_pool_alloc_fns alloc_fns;
++
++ /* <=4K, <=8, <=16, <=32, <=64, <=128, <=256, <=512, <=1024, <=2048 */
++ struct kmem_cache *caches[SGV_POOL_ELEMENTS];
++
++ spinlock_t sgv_pool_lock; /* outer lock for sgv_pools_lock! */
++
++ int purge_interval;
++
++ /* Protected by sgv_pool_lock, if necessary */
++ unsigned int purge_work_scheduled:1;
++
++ /* Protected by sgv_pool_lock */
++ struct list_head sorted_recycling_list;
++
++ int inactive_cached_pages; /* protected by sgv_pool_lock */
++
++ /* Protected by sgv_pool_lock */
++ struct list_head recycling_lists[SGV_POOL_ELEMENTS];
++
++ int cached_pages, cached_entries; /* protected by sgv_pool_lock */
++
++ struct sgv_pool_cache_acc cache_acc[SGV_POOL_ELEMENTS];
++
++ struct delayed_work sgv_purge_work;
++
++ struct list_head sgv_active_pools_list_entry;
++
++ atomic_t big_alloc, big_pages, big_merged;
++ atomic_t other_alloc, other_pages, other_merged;
++
++ atomic_t sgv_pool_ref;
++
++ int max_caches;
++
++ /* SCST_MAX_NAME + few more bytes to match scst_user expectations */
++ char cache_names[SGV_POOL_ELEMENTS][SCST_MAX_NAME + 10];
++ char name[SCST_MAX_NAME + 10];
++
++ struct mm_struct *owner_mm;
++
++ struct list_head sgv_pools_list_entry;
++
++ struct kobject sgv_kobj;
++
++ /* sysfs release completion */
++ struct completion sgv_kobj_release_cmpl;
++};
++
++static inline struct scatterlist *sgv_pool_sg(struct sgv_pool_obj *obj)
++{
++ return obj->sg_entries;
++}
++
++int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark);
++void scst_sgv_pools_deinit(void);
++
++ssize_t sgv_sysfs_stat_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++ssize_t sgv_sysfs_stat_reset(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count);
++ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count);
++
++void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev);
++void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev);
++void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev);
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_mem.c linux-2.6.36/drivers/scst/scst_mem.c
+--- orig/linux-2.6.36/drivers/scst/scst_mem.c
++++ linux-2.6.36/drivers/scst/scst_mem.c
+@@ -0,0 +1,1880 @@
++/*
++ * scst_mem.c
++ *
++ * Copyright (C) 2006 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/unistd.h>
++#include <linux/string.h>
++
++#include <scst/scst.h>
++#include "scst_priv.h"
++#include "scst_mem.h"
++
++#define SGV_DEFAULT_PURGE_INTERVAL (60 * HZ)
++#define SGV_MIN_SHRINK_INTERVAL (1 * HZ)
++
++/* Max pages freed from a pool per shrinking iteration */
++#define MAX_PAGES_PER_POOL 50
++
++static struct sgv_pool *sgv_norm_clust_pool, *sgv_norm_pool, *sgv_dma_pool;
++
++static atomic_t sgv_pages_total = ATOMIC_INIT(0);
++
++/* Both read-only */
++static int sgv_hi_wmk;
++static int sgv_lo_wmk;
++
++static int sgv_max_local_pages, sgv_max_trans_pages;
++
++static DEFINE_SPINLOCK(sgv_pools_lock); /* inner lock for sgv_pool_lock! */
++static DEFINE_MUTEX(sgv_pools_mutex);
++
++/* Both protected by sgv_pools_lock */
++static struct sgv_pool *sgv_cur_purge_pool;
++static LIST_HEAD(sgv_active_pools_list);
++
++static atomic_t sgv_releases_on_hiwmk = ATOMIC_INIT(0);
++static atomic_t sgv_releases_on_hiwmk_failed = ATOMIC_INIT(0);
++
++static atomic_t sgv_other_total_alloc = ATOMIC_INIT(0);
++
++static struct shrinker sgv_shrinker;
++
++/*
++ * Protected by sgv_pools_mutex AND sgv_pools_lock for writes,
++ * either one for reads.
++ */
++static LIST_HEAD(sgv_pools_list);
++
++static inline bool sgv_pool_clustered(const struct sgv_pool *pool)
++{
++ return pool->clustering_type != sgv_no_clustering;
++}
++
++void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev)
++{
++ tgt_dev->gfp_mask = __GFP_NOWARN;
++ tgt_dev->pool = sgv_norm_pool;
++ clear_bit(SCST_TGT_DEV_CLUST_POOL, &tgt_dev->tgt_dev_flags);
++}
++
++void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev)
++{
++ TRACE_MEM("%s", "Use clustering");
++ tgt_dev->gfp_mask = __GFP_NOWARN;
++ tgt_dev->pool = sgv_norm_clust_pool;
++ set_bit(SCST_TGT_DEV_CLUST_POOL, &tgt_dev->tgt_dev_flags);
++}
++
++void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev)
++{
++ TRACE_MEM("%s", "Use ISA DMA memory");
++ tgt_dev->gfp_mask = __GFP_NOWARN | GFP_DMA;
++ tgt_dev->pool = sgv_dma_pool;
++ clear_bit(SCST_TGT_DEV_CLUST_POOL, &tgt_dev->tgt_dev_flags);
++}
++
++/* Must be no locks */
++static void sgv_dtor_and_free(struct sgv_pool_obj *obj)
++{
++ struct sgv_pool *pool = obj->owner_pool;
++
++ TRACE_MEM("Destroying sgv obj %p", obj);
++
++ if (obj->sg_count != 0) {
++ pool->alloc_fns.free_pages_fn(obj->sg_entries,
++ obj->sg_count, obj->allocator_priv);
++ }
++ if (obj->sg_entries != obj->sg_entries_data) {
++ if (obj->trans_tbl !=
++ (struct trans_tbl_ent *)obj->sg_entries_data) {
++ /* kfree() handles NULL parameter */
++ kfree(obj->trans_tbl);
++ obj->trans_tbl = NULL;
++ }
++ kfree(obj->sg_entries);
++ }
++
++ kmem_cache_free(pool->caches[obj->cache_num], obj);
++ return;
++}
++
++/* Might be called under sgv_pool_lock */
++static inline void sgv_del_from_active(struct sgv_pool *pool)
++{
++ struct list_head *next;
++
++ TRACE_MEM("Deleting sgv pool %p from the active list", pool);
++
++ spin_lock_bh(&sgv_pools_lock);
++
++ next = pool->sgv_active_pools_list_entry.next;
++ list_del(&pool->sgv_active_pools_list_entry);
++
++ if (sgv_cur_purge_pool == pool) {
++ TRACE_MEM("Sgv pool %p is sgv cur purge pool", pool);
++
++ if (next == &sgv_active_pools_list)
++ next = next->next;
++
++ if (next == &sgv_active_pools_list) {
++ sgv_cur_purge_pool = NULL;
++ TRACE_MEM("%s", "Sgv active list now empty");
++ } else {
++ sgv_cur_purge_pool = list_entry(next, typeof(*pool),
++ sgv_active_pools_list_entry);
++ TRACE_MEM("New sgv cur purge pool %p",
++ sgv_cur_purge_pool);
++ }
++ }
++
++ spin_unlock_bh(&sgv_pools_lock);
++ return;
++}
++
++/* Must be called under sgv_pool_lock held */
++static void sgv_dec_cached_entries(struct sgv_pool *pool, int pages)
++{
++ pool->cached_entries--;
++ pool->cached_pages -= pages;
++
++ if (pool->cached_entries == 0)
++ sgv_del_from_active(pool);
++
++ return;
++}
++
++/* Must be called under sgv_pool_lock held */
++static void __sgv_purge_from_cache(struct sgv_pool_obj *obj)
++{
++ int pages = obj->pages;
++ struct sgv_pool *pool = obj->owner_pool;
++
++ TRACE_MEM("Purging sgv obj %p from pool %p (new cached_entries %d)",
++ obj, pool, pool->cached_entries-1);
++
++ list_del(&obj->sorted_recycling_list_entry);
++ list_del(&obj->recycling_list_entry);
++
++ pool->inactive_cached_pages -= pages;
++ sgv_dec_cached_entries(pool, pages);
++
++ atomic_sub(pages, &sgv_pages_total);
++
++ return;
++}
++
++/* Must be called under sgv_pool_lock held */
++static bool sgv_purge_from_cache(struct sgv_pool_obj *obj, int min_interval,
++ unsigned long cur_time)
++{
++ EXTRACHECKS_BUG_ON(min_interval < 0);
++
++ TRACE_MEM("Checking if sgv obj %p should be purged (cur time %ld, "
++ "obj time %ld, time to purge %ld)", obj, cur_time,
++ obj->time_stamp, obj->time_stamp + min_interval);
++
++ if (time_after_eq(cur_time, (obj->time_stamp + min_interval))) {
++ __sgv_purge_from_cache(obj);
++ return true;
++ }
++ return false;
++}
++
++/* No locks */
++static int sgv_shrink_pool(struct sgv_pool *pool, int nr, int min_interval,
++ unsigned long cur_time)
++{
++ int freed = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_MEM("Trying to shrink pool %p (nr %d, min_interval %d)",
++ pool, nr, min_interval);
++
++ if (pool->purge_interval < 0) {
++ TRACE_MEM("Not shrinkable pool %p, skipping", pool);
++ goto out;
++ }
++
++ spin_lock_bh(&pool->sgv_pool_lock);
++
++ while (!list_empty(&pool->sorted_recycling_list) &&
++ (atomic_read(&sgv_pages_total) > sgv_lo_wmk)) {
++ struct sgv_pool_obj *obj = list_entry(
++ pool->sorted_recycling_list.next,
++ struct sgv_pool_obj, sorted_recycling_list_entry);
++
++ if (sgv_purge_from_cache(obj, min_interval, cur_time)) {
++ int pages = obj->pages;
++
++ freed += pages;
++ nr -= pages;
++
++ TRACE_MEM("%d pages purged from pool %p (nr left %d, "
++ "total freed %d)", pages, pool, nr, freed);
++
++ spin_unlock_bh(&pool->sgv_pool_lock);
++ sgv_dtor_and_free(obj);
++ spin_lock_bh(&pool->sgv_pool_lock);
++ } else
++ break;
++
++ if ((nr <= 0) || (freed >= MAX_PAGES_PER_POOL)) {
++ if (freed >= MAX_PAGES_PER_POOL)
++ TRACE_MEM("%d pages purged from pool %p, "
++ "leaving", freed, pool);
++ break;
++ }
++ }
++
++ spin_unlock_bh(&pool->sgv_pool_lock);
++
++out:
++ TRACE_EXIT_RES(nr);
++ return nr;
++}
++
++/* No locks */
++static int __sgv_shrink(int nr, int min_interval)
++{
++ struct sgv_pool *pool;
++ unsigned long cur_time = jiffies;
++ int prev_nr = nr;
++ bool circle = false;
++
++ TRACE_ENTRY();
++
++ TRACE_MEM("Trying to shrink %d pages from all sgv pools "
++ "(min_interval %d)", nr, min_interval);
++
++ while (nr > 0) {
++ struct list_head *next;
++
++ spin_lock_bh(&sgv_pools_lock);
++
++ pool = sgv_cur_purge_pool;
++ if (pool == NULL) {
++ if (list_empty(&sgv_active_pools_list)) {
++ TRACE_MEM("%s", "Active pools list is empty");
++ goto out_unlock;
++ }
++
++ pool = list_entry(sgv_active_pools_list.next,
++ typeof(*pool),
++ sgv_active_pools_list_entry);
++ }
++ sgv_pool_get(pool);
++
++ next = pool->sgv_active_pools_list_entry.next;
++ if (next == &sgv_active_pools_list) {
++ if (circle && (prev_nr == nr)) {
++ TRACE_MEM("Full circle done, but no progress, "
++ "leaving (nr %d)", nr);
++ goto out_unlock_put;
++ }
++ circle = true;
++ prev_nr = nr;
++
++ next = next->next;
++ }
++
++ sgv_cur_purge_pool = list_entry(next, typeof(*pool),
++ sgv_active_pools_list_entry);
++ TRACE_MEM("New cur purge pool %p", sgv_cur_purge_pool);
++
++ spin_unlock_bh(&sgv_pools_lock);
++
++ nr = sgv_shrink_pool(pool, nr, min_interval, cur_time);
++
++ sgv_pool_put(pool);
++ }
++
++out:
++ TRACE_EXIT_RES(nr);
++ return nr;
++
++out_unlock:
++ spin_unlock_bh(&sgv_pools_lock);
++ goto out;
++
++out_unlock_put:
++ spin_unlock_bh(&sgv_pools_lock);
++ sgv_pool_put(pool);
++ goto out;
++}
++
++static int sgv_shrink(struct shrinker *shrinker, int nr, gfp_t gfpm)
++{
++ TRACE_ENTRY();
++
++ if (nr > 0) {
++ nr = __sgv_shrink(nr, SGV_MIN_SHRINK_INTERVAL);
++ TRACE_MEM("Left %d", nr);
++ } else {
++ struct sgv_pool *pool;
++ int inactive_pages = 0;
++
++ spin_lock_bh(&sgv_pools_lock);
++ list_for_each_entry(pool, &sgv_active_pools_list,
++ sgv_active_pools_list_entry) {
++ if (pool->purge_interval > 0)
++ inactive_pages += pool->inactive_cached_pages;
++ }
++ spin_unlock_bh(&sgv_pools_lock);
++
++ nr = max((int)0, inactive_pages - sgv_lo_wmk);
++ TRACE_MEM("Can free %d (total %d)", nr,
++ atomic_read(&sgv_pages_total));
++ }
++
++ TRACE_EXIT_RES(nr);
++ return nr;
++}
++
++static void sgv_purge_work_fn(struct delayed_work *work)
++{
++ unsigned long cur_time = jiffies;
++ struct sgv_pool *pool = container_of(work, struct sgv_pool,
++ sgv_purge_work);
++
++ TRACE_ENTRY();
++
++ TRACE_MEM("Purge work for pool %p", pool);
++
++ spin_lock_bh(&pool->sgv_pool_lock);
++
++ pool->purge_work_scheduled = false;
++
++ while (!list_empty(&pool->sorted_recycling_list)) {
++ struct sgv_pool_obj *obj = list_entry(
++ pool->sorted_recycling_list.next,
++ struct sgv_pool_obj, sorted_recycling_list_entry);
++
++ if (sgv_purge_from_cache(obj, pool->purge_interval, cur_time)) {
++ spin_unlock_bh(&pool->sgv_pool_lock);
++ sgv_dtor_and_free(obj);
++ spin_lock_bh(&pool->sgv_pool_lock);
++ } else {
++ /*
++ * Let's reschedule it for full period to not get here
++ * too often. In the worst case we have shrinker
++ * to reclaim buffers quickier.
++ */
++ TRACE_MEM("Rescheduling purge work for pool %p (delay "
++ "%d HZ/%d sec)", pool, pool->purge_interval,
++ pool->purge_interval/HZ);
++ schedule_delayed_work(&pool->sgv_purge_work,
++ pool->purge_interval);
++ pool->purge_work_scheduled = true;
++ break;
++ }
++ }
++
++ spin_unlock_bh(&pool->sgv_pool_lock);
++
++ TRACE_MEM("Leaving purge work for pool %p", pool);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int sgv_check_full_clustering(struct scatterlist *sg, int cur, int hint)
++{
++ int res = -1;
++ int i = hint;
++ unsigned long pfn_cur = page_to_pfn(sg_page(&sg[cur]));
++ int len_cur = sg[cur].length;
++ unsigned long pfn_cur_next = pfn_cur + (len_cur >> PAGE_SHIFT);
++ int full_page_cur = (len_cur & (PAGE_SIZE - 1)) == 0;
++ unsigned long pfn, pfn_next;
++ bool full_page;
++
++#if 0
++ TRACE_MEM("pfn_cur %ld, pfn_cur_next %ld, len_cur %d, full_page_cur %d",
++ pfn_cur, pfn_cur_next, len_cur, full_page_cur);
++#endif
++
++ /* check the hint first */
++ if (i >= 0) {
++ pfn = page_to_pfn(sg_page(&sg[i]));
++ pfn_next = pfn + (sg[i].length >> PAGE_SHIFT);
++ full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0;
++
++ if ((pfn == pfn_cur_next) && full_page_cur)
++ goto out_head;
++
++ if ((pfn_next == pfn_cur) && full_page)
++ goto out_tail;
++ }
++
++ /* ToDo: implement more intelligent search */
++ for (i = cur - 1; i >= 0; i--) {
++ pfn = page_to_pfn(sg_page(&sg[i]));
++ pfn_next = pfn + (sg[i].length >> PAGE_SHIFT);
++ full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0;
++
++ if ((pfn == pfn_cur_next) && full_page_cur)
++ goto out_head;
++
++ if ((pfn_next == pfn_cur) && full_page)
++ goto out_tail;
++ }
++
++out:
++ return res;
++
++out_tail:
++ TRACE_MEM("SG segment %d will be tail merged with segment %d", cur, i);
++ sg[i].length += len_cur;
++ sg_clear(&sg[cur]);
++ res = i;
++ goto out;
++
++out_head:
++ TRACE_MEM("SG segment %d will be head merged with segment %d", cur, i);
++ sg_assign_page(&sg[i], sg_page(&sg[cur]));
++ sg[i].length += len_cur;
++ sg_clear(&sg[cur]);
++ res = i;
++ goto out;
++}
++
++static int sgv_check_tail_clustering(struct scatterlist *sg, int cur, int hint)
++{
++ int res = -1;
++ unsigned long pfn_cur = page_to_pfn(sg_page(&sg[cur]));
++ int len_cur = sg[cur].length;
++ int prev;
++ unsigned long pfn_prev;
++ bool full_page;
++
++#ifdef SCST_HIGHMEM
++ if (page >= highmem_start_page) {
++ TRACE_MEM("%s", "HIGHMEM page allocated, no clustering")
++ goto out;
++ }
++#endif
++
++#if 0
++ TRACE_MEM("pfn_cur %ld, pfn_cur_next %ld, len_cur %d, full_page_cur %d",
++ pfn_cur, pfn_cur_next, len_cur, full_page_cur);
++#endif
++
++ if (cur == 0)
++ goto out;
++
++ prev = cur - 1;
++ pfn_prev = page_to_pfn(sg_page(&sg[prev])) +
++ (sg[prev].length >> PAGE_SHIFT);
++ full_page = (sg[prev].length & (PAGE_SIZE - 1)) == 0;
++
++ if ((pfn_prev == pfn_cur) && full_page) {
++ TRACE_MEM("SG segment %d will be tail merged with segment %d",
++ cur, prev);
++ sg[prev].length += len_cur;
++ sg_clear(&sg[cur]);
++ res = prev;
++ }
++
++out:
++ return res;
++}
++
++static void sgv_free_sys_sg_entries(struct scatterlist *sg, int sg_count,
++ void *priv)
++{
++ int i;
++
++ TRACE_MEM("sg=%p, sg_count=%d", sg, sg_count);
++
++ for (i = 0; i < sg_count; i++) {
++ struct page *p = sg_page(&sg[i]);
++ int len = sg[i].length;
++ int pages =
++ (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
++
++ TRACE_MEM("page %lx, len %d, pages %d",
++ (unsigned long)p, len, pages);
++
++ while (pages > 0) {
++ int order = 0;
++
++/*
++ * __free_pages() doesn't like freeing pages with not that order with
++ * which they were allocated, so disable this small optimization.
++ */
++#if 0
++ if (len > 0) {
++ while (((1 << order) << PAGE_SHIFT) < len)
++ order++;
++ len = 0;
++ }
++#endif
++ TRACE_MEM("free_pages(): order %d, page %lx",
++ order, (unsigned long)p);
++
++ __free_pages(p, order);
++
++ pages -= 1 << order;
++ p += 1 << order;
++ }
++ }
++}
++
++static struct page *sgv_alloc_sys_pages(struct scatterlist *sg,
++ gfp_t gfp_mask, void *priv)
++{
++ struct page *page = alloc_pages(gfp_mask, 0);
++
++ sg_set_page(sg, page, PAGE_SIZE, 0);
++ TRACE_MEM("page=%p, sg=%p, priv=%p", page, sg, priv);
++ if (page == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of "
++ "sg page failed");
++ }
++ return page;
++}
++
++static int sgv_alloc_sg_entries(struct scatterlist *sg, int pages,
++ gfp_t gfp_mask, enum sgv_clustering_types clustering_type,
++ struct trans_tbl_ent *trans_tbl,
++ const struct sgv_pool_alloc_fns *alloc_fns, void *priv)
++{
++ int sg_count = 0;
++ int pg, i, j;
++ int merged = -1;
++
++ TRACE_MEM("pages=%d, clustering_type=%d", pages, clustering_type);
++
++#if 0
++ gfp_mask |= __GFP_COLD;
++#endif
++#ifdef CONFIG_SCST_STRICT_SECURITY
++ gfp_mask |= __GFP_ZERO;
++#endif
++
++ for (pg = 0; pg < pages; pg++) {
++ void *rc;
++#ifdef CONFIG_SCST_DEBUG_OOM
++ if (((gfp_mask & __GFP_NOFAIL) != __GFP_NOFAIL) &&
++ ((scst_random() % 10000) == 55))
++ rc = NULL;
++ else
++#endif
++ rc = alloc_fns->alloc_pages_fn(&sg[sg_count], gfp_mask,
++ priv);
++ if (rc == NULL)
++ goto out_no_mem;
++
++ /*
++ * This code allows compiler to see full body of the clustering
++ * functions and gives it a chance to generate better code.
++ * At least, the resulting code is smaller, comparing to
++ * calling them using a function pointer.
++ */
++ if (clustering_type == sgv_full_clustering)
++ merged = sgv_check_full_clustering(sg, sg_count, merged);
++ else if (clustering_type == sgv_tail_clustering)
++ merged = sgv_check_tail_clustering(sg, sg_count, merged);
++ else
++ merged = -1;
++
++ if (merged == -1)
++ sg_count++;
++
++ TRACE_MEM("pg=%d, merged=%d, sg_count=%d", pg, merged,
++ sg_count);
++ }
++
++ if ((clustering_type != sgv_no_clustering) && (trans_tbl != NULL)) {
++ pg = 0;
++ for (i = 0; i < pages; i++) {
++ int n = (sg[i].length >> PAGE_SHIFT) +
++ ((sg[i].length & ~PAGE_MASK) != 0);
++ trans_tbl[i].pg_count = pg;
++ for (j = 0; j < n; j++)
++ trans_tbl[pg++].sg_num = i+1;
++ TRACE_MEM("i=%d, n=%d, pg_count=%d", i, n,
++ trans_tbl[i].pg_count);
++ }
++ }
++
++out:
++ TRACE_MEM("sg_count=%d", sg_count);
++ return sg_count;
++
++out_no_mem:
++ alloc_fns->free_pages_fn(sg, sg_count, priv);
++ sg_count = 0;
++ goto out;
++}
++
++static int sgv_alloc_arrays(struct sgv_pool_obj *obj,
++ int pages_to_alloc, gfp_t gfp_mask)
++{
++ int sz, tsz = 0;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ sz = pages_to_alloc * sizeof(obj->sg_entries[0]);
++
++ obj->sg_entries = kmalloc(sz, gfp_mask);
++ if (unlikely(obj->sg_entries == NULL)) {
++ TRACE(TRACE_OUT_OF_MEM, "Allocation of sgv_pool_obj "
++ "SG vector failed (size %d)", sz);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ sg_init_table(obj->sg_entries, pages_to_alloc);
++
++ if (sgv_pool_clustered(obj->owner_pool)) {
++ if (pages_to_alloc <= sgv_max_trans_pages) {
++ obj->trans_tbl =
++ (struct trans_tbl_ent *)obj->sg_entries_data;
++ /*
++ * No need to clear trans_tbl, if needed, it will be
++ * fully rewritten in sgv_alloc_sg_entries()
++ */
++ } else {
++ tsz = pages_to_alloc * sizeof(obj->trans_tbl[0]);
++ obj->trans_tbl = kzalloc(tsz, gfp_mask);
++ if (unlikely(obj->trans_tbl == NULL)) {
++ TRACE(TRACE_OUT_OF_MEM, "Allocation of "
++ "trans_tbl failed (size %d)", tsz);
++ res = -ENOMEM;
++ goto out_free;
++ }
++ }
++ }
++
++ TRACE_MEM("pages_to_alloc %d, sz %d, tsz %d, obj %p, sg_entries %p, "
++ "trans_tbl %p", pages_to_alloc, sz, tsz, obj, obj->sg_entries,
++ obj->trans_tbl);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(obj->sg_entries);
++ obj->sg_entries = NULL;
++ goto out;
++}
++
++static struct sgv_pool_obj *sgv_get_obj(struct sgv_pool *pool, int cache_num,
++ int pages, gfp_t gfp_mask, bool get_new)
++{
++ struct sgv_pool_obj *obj;
++
++ spin_lock_bh(&pool->sgv_pool_lock);
++
++ if (unlikely(get_new)) {
++ /* Used only for buffers preallocation */
++ goto get_new;
++ }
++
++ if (likely(!list_empty(&pool->recycling_lists[cache_num]))) {
++ obj = list_entry(pool->recycling_lists[cache_num].next,
++ struct sgv_pool_obj, recycling_list_entry);
++
++ list_del(&obj->sorted_recycling_list_entry);
++ list_del(&obj->recycling_list_entry);
++
++ pool->inactive_cached_pages -= pages;
++
++ spin_unlock_bh(&pool->sgv_pool_lock);
++ goto out;
++ }
++
++get_new:
++ if (pool->cached_entries == 0) {
++ TRACE_MEM("Adding pool %p to the active list", pool);
++ spin_lock_bh(&sgv_pools_lock);
++ list_add_tail(&pool->sgv_active_pools_list_entry,
++ &sgv_active_pools_list);
++ spin_unlock_bh(&sgv_pools_lock);
++ }
++
++ pool->cached_entries++;
++ pool->cached_pages += pages;
++
++ spin_unlock_bh(&pool->sgv_pool_lock);
++
++ TRACE_MEM("New cached entries %d (pool %p)", pool->cached_entries,
++ pool);
++
++ obj = kmem_cache_alloc(pool->caches[cache_num],
++ gfp_mask & ~(__GFP_HIGHMEM|GFP_DMA));
++ if (likely(obj)) {
++ memset(obj, 0, sizeof(*obj));
++ obj->cache_num = cache_num;
++ obj->pages = pages;
++ obj->owner_pool = pool;
++ } else {
++ spin_lock_bh(&pool->sgv_pool_lock);
++ sgv_dec_cached_entries(pool, pages);
++ spin_unlock_bh(&pool->sgv_pool_lock);
++ }
++
++out:
++ return obj;
++}
++
++static void sgv_put_obj(struct sgv_pool_obj *obj)
++{
++ struct sgv_pool *pool = obj->owner_pool;
++ struct list_head *entry;
++ struct list_head *list = &pool->recycling_lists[obj->cache_num];
++ int pages = obj->pages;
++
++ spin_lock_bh(&pool->sgv_pool_lock);
++
++ TRACE_MEM("sgv %p, cache num %d, pages %d, sg_count %d", obj,
++ obj->cache_num, pages, obj->sg_count);
++
++ if (sgv_pool_clustered(pool)) {
++ /* Make objects with less entries more preferred */
++ __list_for_each(entry, list) {
++ struct sgv_pool_obj *tmp = list_entry(entry,
++ struct sgv_pool_obj, recycling_list_entry);
++
++ TRACE_MEM("tmp %p, cache num %d, pages %d, sg_count %d",
++ tmp, tmp->cache_num, tmp->pages, tmp->sg_count);
++
++ if (obj->sg_count <= tmp->sg_count)
++ break;
++ }
++ entry = entry->prev;
++ } else
++ entry = list;
++
++ TRACE_MEM("Adding in %p (list %p)", entry, list);
++ list_add(&obj->recycling_list_entry, entry);
++
++ list_add_tail(&obj->sorted_recycling_list_entry,
++ &pool->sorted_recycling_list);
++
++ obj->time_stamp = jiffies;
++
++ pool->inactive_cached_pages += pages;
++
++ if (!pool->purge_work_scheduled) {
++ TRACE_MEM("Scheduling purge work for pool %p", pool);
++ pool->purge_work_scheduled = true;
++ schedule_delayed_work(&pool->sgv_purge_work,
++ pool->purge_interval);
++ }
++
++ spin_unlock_bh(&pool->sgv_pool_lock);
++ return;
++}
++
++/* No locks */
++static int sgv_hiwmk_check(int pages_to_alloc)
++{
++ int res = 0;
++ int pages = pages_to_alloc;
++
++ pages += atomic_read(&sgv_pages_total);
++
++ if (unlikely(pages > sgv_hi_wmk)) {
++ pages -= sgv_hi_wmk;
++ atomic_inc(&sgv_releases_on_hiwmk);
++
++ pages = __sgv_shrink(pages, 0);
++ if (pages > 0) {
++ TRACE(TRACE_OUT_OF_MEM, "Requested amount of "
++ "memory (%d pages) for being executed "
++ "commands together with the already "
++ "allocated memory exceeds the allowed "
++ "maximum %d. Should you increase "
++ "scst_max_cmd_mem?", pages_to_alloc,
++ sgv_hi_wmk);
++ atomic_inc(&sgv_releases_on_hiwmk_failed);
++ res = -ENOMEM;
++ goto out_unlock;
++ }
++ }
++
++ atomic_add(pages_to_alloc, &sgv_pages_total);
++
++out_unlock:
++ TRACE_MEM("pages_to_alloc %d, new total %d", pages_to_alloc,
++ atomic_read(&sgv_pages_total));
++
++ return res;
++}
++
++/* No locks */
++static void sgv_hiwmk_uncheck(int pages)
++{
++ atomic_sub(pages, &sgv_pages_total);
++ TRACE_MEM("pages %d, new total %d", pages,
++ atomic_read(&sgv_pages_total));
++ return;
++}
++
++/* No locks */
++static bool sgv_check_allowed_mem(struct scst_mem_lim *mem_lim, int pages)
++{
++ int alloced;
++ bool res = true;
++
++ alloced = atomic_add_return(pages, &mem_lim->alloced_pages);
++ if (unlikely(alloced > mem_lim->max_allowed_pages)) {
++ TRACE(TRACE_OUT_OF_MEM, "Requested amount of memory "
++ "(%d pages) for being executed commands on a device "
++ "together with the already allocated memory exceeds "
++ "the allowed maximum %d. Should you increase "
++ "scst_max_dev_cmd_mem?", pages,
++ mem_lim->max_allowed_pages);
++ atomic_sub(pages, &mem_lim->alloced_pages);
++ res = false;
++ }
++
++ TRACE_MEM("mem_lim %p, pages %d, res %d, new alloced %d", mem_lim,
++ pages, res, atomic_read(&mem_lim->alloced_pages));
++
++ return res;
++}
++
++/* No locks */
++static void sgv_uncheck_allowed_mem(struct scst_mem_lim *mem_lim, int pages)
++{
++ atomic_sub(pages, &mem_lim->alloced_pages);
++
++ TRACE_MEM("mem_lim %p, pages %d, new alloced %d", mem_lim,
++ pages, atomic_read(&mem_lim->alloced_pages));
++ return;
++}
++
++/**
++ * sgv_pool_alloc - allocate an SG vector from the SGV pool
++ * @pool: the cache to alloc from
++ * @size: size of the resulting SG vector in bytes
++ * @gfp_mask: the allocation mask
++ * @flags: the allocation flags
++ * @count: the resulting count of SG entries in the resulting SG vector
++ * @sgv: the resulting SGV object
++ * @mem_lim: memory limits
++ * @priv: pointer to private for this allocation data
++ *
++ * Description:
++ * Allocate an SG vector from the SGV pool and returns pointer to it or
++ * NULL in case of any error. See the SGV pool documentation for more details.
++ */
++struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
++ gfp_t gfp_mask, int flags, int *count,
++ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv)
++{
++ struct sgv_pool_obj *obj;
++ int cache_num, pages, cnt;
++ struct scatterlist *res = NULL;
++ int pages_to_alloc;
++ int no_cached = flags & SGV_POOL_ALLOC_NO_CACHED;
++ bool allowed_mem_checked = false, hiwmk_checked = false;
++
++ TRACE_ENTRY();
++
++ if (unlikely(size == 0))
++ goto out;
++
++ EXTRACHECKS_BUG_ON((gfp_mask & __GFP_NOFAIL) == __GFP_NOFAIL);
++
++ pages = ((size + PAGE_SIZE - 1) >> PAGE_SHIFT);
++ if (pool->single_alloc_pages == 0) {
++ int pages_order = get_order(size);
++ cache_num = pages_order;
++ pages_to_alloc = (1 << pages_order);
++ } else {
++ cache_num = 0;
++ pages_to_alloc = max(pool->single_alloc_pages, pages);
++ }
++
++ TRACE_MEM("size=%d, pages=%d, pages_to_alloc=%d, cache num=%d, "
++ "flags=%x, no_cached=%d, *sgv=%p", size, pages,
++ pages_to_alloc, cache_num, flags, no_cached, *sgv);
++
++ if (*sgv != NULL) {
++ obj = *sgv;
++
++ TRACE_MEM("Supplied obj %p, cache num %d", obj, obj->cache_num);
++
++ EXTRACHECKS_BUG_ON(obj->sg_count != 0);
++
++ if (unlikely(!sgv_check_allowed_mem(mem_lim, pages_to_alloc)))
++ goto out_fail_free_sg_entries;
++ allowed_mem_checked = true;
++
++ if (unlikely(sgv_hiwmk_check(pages_to_alloc) != 0))
++ goto out_fail_free_sg_entries;
++ hiwmk_checked = true;
++ } else if ((pages_to_alloc <= pool->max_cached_pages) && !no_cached) {
++ if (unlikely(!sgv_check_allowed_mem(mem_lim, pages_to_alloc)))
++ goto out_fail;
++ allowed_mem_checked = true;
++
++ obj = sgv_get_obj(pool, cache_num, pages_to_alloc, gfp_mask,
++ flags & SGV_POOL_ALLOC_GET_NEW);
++ if (unlikely(obj == NULL)) {
++ TRACE(TRACE_OUT_OF_MEM, "Allocation of "
++ "sgv_pool_obj failed (size %d)", size);
++ goto out_fail;
++ }
++
++ if (obj->sg_count != 0) {
++ TRACE_MEM("Cached obj %p", obj);
++ atomic_inc(&pool->cache_acc[cache_num].hit_alloc);
++ goto success;
++ }
++
++ if (flags & SGV_POOL_NO_ALLOC_ON_CACHE_MISS) {
++ if (!(flags & SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL))
++ goto out_fail_free;
++ }
++
++ TRACE_MEM("Brand new obj %p", obj);
++
++ if (pages_to_alloc <= sgv_max_local_pages) {
++ obj->sg_entries = obj->sg_entries_data;
++ sg_init_table(obj->sg_entries, pages_to_alloc);
++ TRACE_MEM("sg_entries %p", obj->sg_entries);
++ if (sgv_pool_clustered(pool)) {
++ obj->trans_tbl = (struct trans_tbl_ent *)
++ (obj->sg_entries + pages_to_alloc);
++ TRACE_MEM("trans_tbl %p", obj->trans_tbl);
++ /*
++ * No need to clear trans_tbl, if needed, it
++ * will be fully rewritten in
++ * sgv_alloc_sg_entries().
++ */
++ }
++ } else {
++ if (unlikely(sgv_alloc_arrays(obj, pages_to_alloc,
++ gfp_mask) != 0))
++ goto out_fail_free;
++ }
++
++ if ((flags & SGV_POOL_NO_ALLOC_ON_CACHE_MISS) &&
++ (flags & SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL))
++ goto out_return;
++
++ obj->allocator_priv = priv;
++
++ if (unlikely(sgv_hiwmk_check(pages_to_alloc) != 0))
++ goto out_fail_free_sg_entries;
++ hiwmk_checked = true;
++ } else {
++ int sz;
++
++ pages_to_alloc = pages;
++
++ if (unlikely(!sgv_check_allowed_mem(mem_lim, pages_to_alloc)))
++ goto out_fail;
++ allowed_mem_checked = true;
++
++ if (flags & SGV_POOL_NO_ALLOC_ON_CACHE_MISS)
++ goto out_return2;
++
++ sz = sizeof(*obj) + pages * sizeof(obj->sg_entries[0]);
++
++ obj = kmalloc(sz, gfp_mask);
++ if (unlikely(obj == NULL)) {
++ TRACE(TRACE_OUT_OF_MEM, "Allocation of "
++ "sgv_pool_obj failed (size %d)", size);
++ goto out_fail;
++ }
++ memset(obj, 0, sizeof(*obj));
++
++ obj->owner_pool = pool;
++ cache_num = -1;
++ obj->cache_num = cache_num;
++ obj->pages = pages_to_alloc;
++ obj->allocator_priv = priv;
++
++ obj->sg_entries = obj->sg_entries_data;
++ sg_init_table(obj->sg_entries, pages);
++
++ if (unlikely(sgv_hiwmk_check(pages_to_alloc) != 0))
++ goto out_fail_free_sg_entries;
++ hiwmk_checked = true;
++
++ TRACE_MEM("Big or no_cached obj %p (size %d)", obj, sz);
++ }
++
++ obj->sg_count = sgv_alloc_sg_entries(obj->sg_entries,
++ pages_to_alloc, gfp_mask, pool->clustering_type,
++ obj->trans_tbl, &pool->alloc_fns, priv);
++ if (unlikely(obj->sg_count <= 0)) {
++ obj->sg_count = 0;
++ if ((flags & SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL) &&
++ (cache_num >= 0))
++ goto out_return1;
++ else
++ goto out_fail_free_sg_entries;
++ }
++
++ if (cache_num >= 0) {
++ atomic_add(pages_to_alloc - obj->sg_count,
++ &pool->cache_acc[cache_num].merged);
++ } else {
++ if (no_cached) {
++ atomic_add(pages_to_alloc,
++ &pool->other_pages);
++ atomic_add(pages_to_alloc - obj->sg_count,
++ &pool->other_merged);
++ } else {
++ atomic_add(pages_to_alloc,
++ &pool->big_pages);
++ atomic_add(pages_to_alloc - obj->sg_count,
++ &pool->big_merged);
++ }
++ }
++
++success:
++ if (cache_num >= 0) {
++ int sg;
++ atomic_inc(&pool->cache_acc[cache_num].total_alloc);
++ if (sgv_pool_clustered(pool))
++ cnt = obj->trans_tbl[pages-1].sg_num;
++ else
++ cnt = pages;
++ sg = cnt-1;
++ obj->orig_sg = sg;
++ obj->orig_length = obj->sg_entries[sg].length;
++ if (sgv_pool_clustered(pool)) {
++ obj->sg_entries[sg].length =
++ (pages - obj->trans_tbl[sg].pg_count) << PAGE_SHIFT;
++ }
++ } else {
++ cnt = obj->sg_count;
++ if (no_cached)
++ atomic_inc(&pool->other_alloc);
++ else
++ atomic_inc(&pool->big_alloc);
++ }
++
++ *count = cnt;
++ res = obj->sg_entries;
++ *sgv = obj;
++
++ if (size & ~PAGE_MASK)
++ obj->sg_entries[cnt-1].length -=
++ PAGE_SIZE - (size & ~PAGE_MASK);
++
++ TRACE_MEM("obj=%p, sg_entries %p (size=%d, pages=%d, sg_count=%d, "
++ "count=%d, last_len=%d)", obj, obj->sg_entries, size, pages,
++ obj->sg_count, *count, obj->sg_entries[obj->orig_sg].length);
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++
++out_return:
++ obj->allocator_priv = priv;
++ obj->owner_pool = pool;
++
++out_return1:
++ *sgv = obj;
++ TRACE_MEM("Returning failed obj %p (count %d)", obj, *count);
++
++out_return2:
++ *count = pages_to_alloc;
++ res = NULL;
++ goto out_uncheck;
++
++out_fail_free_sg_entries:
++ if (obj->sg_entries != obj->sg_entries_data) {
++ if (obj->trans_tbl !=
++ (struct trans_tbl_ent *)obj->sg_entries_data) {
++ /* kfree() handles NULL parameter */
++ kfree(obj->trans_tbl);
++ obj->trans_tbl = NULL;
++ }
++ kfree(obj->sg_entries);
++ obj->sg_entries = NULL;
++ }
++
++out_fail_free:
++ if (cache_num >= 0) {
++ spin_lock_bh(&pool->sgv_pool_lock);
++ sgv_dec_cached_entries(pool, pages_to_alloc);
++ spin_unlock_bh(&pool->sgv_pool_lock);
++
++ kmem_cache_free(pool->caches[obj->cache_num], obj);
++ } else
++ kfree(obj);
++
++out_fail:
++ res = NULL;
++ *count = 0;
++ *sgv = NULL;
++ TRACE_MEM("%s", "Allocation failed");
++
++out_uncheck:
++ if (hiwmk_checked)
++ sgv_hiwmk_uncheck(pages_to_alloc);
++ if (allowed_mem_checked)
++ sgv_uncheck_allowed_mem(mem_lim, pages_to_alloc);
++ goto out;
++}
++EXPORT_SYMBOL_GPL(sgv_pool_alloc);
++
++/**
++ * sgv_get_priv - return the private allocation data
++ *
++ * Allows to get the allocation private data for this SGV
++ * cache object. The private data supposed to be set by sgv_pool_alloc().
++ */
++void *sgv_get_priv(struct sgv_pool_obj *obj)
++{
++ return obj->allocator_priv;
++}
++EXPORT_SYMBOL_GPL(sgv_get_priv);
++
++/**
++ * sgv_pool_free - free previously allocated SG vector
++ * @sgv: the SGV object to free
++ * @mem_lim: memory limits
++ *
++ * Description:
++ * Frees previously allocated SG vector and updates memory limits
++ */
++void sgv_pool_free(struct sgv_pool_obj *obj, struct scst_mem_lim *mem_lim)
++{
++ int pages = (obj->sg_count != 0) ? obj->pages : 0;
++
++ TRACE_MEM("Freeing obj %p, cache num %d, pages %d, sg_entries %p, "
++ "sg_count %d, allocator_priv %p", obj, obj->cache_num, pages,
++ obj->sg_entries, obj->sg_count, obj->allocator_priv);
++
++/*
++ * Enable it if you are investigating a data corruption and want to make
++ * sure that target or dev handler didn't leave the pages mapped somewhere and,
++ * hence, provoked a data corruption.
++ *
++ * Make sure the check value for _count is set correctly. In most cases, 1 is
++ * correct, but, e.g., iSCSI-SCST can call it with value 2, because
++ * it frees the corresponding cmd before the last put_page() call from
++ * net_put_page() for the last page in the SG. Also, user space dev handlers
++ * usually have their memory mapped in their address space.
++ */
++#if 0
++ {
++ struct scatterlist *sg = obj->sg_entries;
++ int i;
++ for (i = 0; i < obj->sg_count; i++) {
++ struct page *p = sg_page(&sg[i]);
++ int len = sg[i].length;
++ int pages = (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
++ while (pages > 0) {
++ if (atomic_read(&p->_count) != 1) {
++ PRINT_WARNING("Freeing page %p with "
++ "additional owners (_count %d). "
++ "Data corruption possible!",
++ p, atomic_read(&p->_count));
++ WARN_ON(1);
++ }
++ pages--;
++ p++;
++ }
++ }
++ }
++#endif
++
++ if (obj->cache_num >= 0) {
++ obj->sg_entries[obj->orig_sg].length = obj->orig_length;
++ sgv_put_obj(obj);
++ } else {
++ obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries,
++ obj->sg_count, obj->allocator_priv);
++ kfree(obj);
++ sgv_hiwmk_uncheck(pages);
++ }
++
++ sgv_uncheck_allowed_mem(mem_lim, pages);
++ return;
++}
++EXPORT_SYMBOL_GPL(sgv_pool_free);
++
++/**
++ * scst_alloc() - allocates an SG vector
++ *
++ * Allocates and returns pointer to SG vector with data size "size".
++ * In *count returned the count of entries in the vector.
++ * Returns NULL for failure.
++ */
++struct scatterlist *scst_alloc(int size, gfp_t gfp_mask, int *count)
++{
++ struct scatterlist *res;
++ int pages = (size >> PAGE_SHIFT) + ((size & ~PAGE_MASK) != 0);
++ struct sgv_pool_alloc_fns sys_alloc_fns = {
++ sgv_alloc_sys_pages, sgv_free_sys_sg_entries };
++ int no_fail = ((gfp_mask & __GFP_NOFAIL) == __GFP_NOFAIL);
++ int cnt;
++
++ TRACE_ENTRY();
++
++ atomic_inc(&sgv_other_total_alloc);
++
++ if (unlikely(sgv_hiwmk_check(pages) != 0)) {
++ if (!no_fail) {
++ res = NULL;
++ goto out;
++ } else {
++ /*
++ * Update active_pages_total since alloc can't fail.
++ * If it wasn't updated then the counter would cross 0
++ * on free again.
++ */
++ sgv_hiwmk_uncheck(-pages);
++ }
++ }
++
++ res = kmalloc(pages*sizeof(*res), gfp_mask);
++ if (res == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate sg for %d pages",
++ pages);
++ goto out_uncheck;
++ }
++
++ sg_init_table(res, pages);
++
++ /*
++ * If we allow use clustering here, we will have troubles in
++ * scst_free() to figure out how many pages are in the SG vector.
++ * So, let's always don't use clustering.
++ */
++ cnt = sgv_alloc_sg_entries(res, pages, gfp_mask, sgv_no_clustering,
++ NULL, &sys_alloc_fns, NULL);
++ if (cnt <= 0)
++ goto out_free;
++
++ if (size & ~PAGE_MASK)
++ res[cnt-1].length -= PAGE_SIZE - (size & ~PAGE_MASK);
++
++ *count = cnt;
++
++out:
++ TRACE_MEM("Alloced sg %p (count %d, no_fail %d)", res, *count, no_fail);
++
++ TRACE_EXIT_HRES(res);
++ return res;
++
++out_free:
++ kfree(res);
++ res = NULL;
++
++out_uncheck:
++ if (!no_fail)
++ sgv_hiwmk_uncheck(pages);
++ goto out;
++}
++EXPORT_SYMBOL_GPL(scst_alloc);
++
++/**
++ * scst_free() - frees SG vector
++ *
++ * Frees SG vector returned by scst_alloc().
++ */
++void scst_free(struct scatterlist *sg, int count)
++{
++ TRACE_MEM("Freeing sg=%p", sg);
++
++ sgv_hiwmk_uncheck(count);
++
++ sgv_free_sys_sg_entries(sg, count, NULL);
++ kfree(sg);
++ return;
++}
++EXPORT_SYMBOL_GPL(scst_free);
++
++/* Must be called under sgv_pools_mutex */
++static void sgv_pool_init_cache(struct sgv_pool *pool, int cache_num)
++{
++ int size;
++ int pages;
++ struct sgv_pool_obj *obj;
++
++ atomic_set(&pool->cache_acc[cache_num].total_alloc, 0);
++ atomic_set(&pool->cache_acc[cache_num].hit_alloc, 0);
++ atomic_set(&pool->cache_acc[cache_num].merged, 0);
++
++ if (pool->single_alloc_pages == 0)
++ pages = 1 << cache_num;
++ else
++ pages = pool->single_alloc_pages;
++
++ if (pages <= sgv_max_local_pages) {
++ size = sizeof(*obj) + pages *
++ (sizeof(obj->sg_entries[0]) +
++ ((pool->clustering_type != sgv_no_clustering) ?
++ sizeof(obj->trans_tbl[0]) : 0));
++ } else if (pages <= sgv_max_trans_pages) {
++ /*
++ * sg_entries is allocated outside object,
++ * but trans_tbl is still embedded.
++ */
++ size = sizeof(*obj) + pages *
++ (((pool->clustering_type != sgv_no_clustering) ?
++ sizeof(obj->trans_tbl[0]) : 0));
++ } else {
++ size = sizeof(*obj);
++ /* both sgv and trans_tbl are kmalloc'ed() */
++ }
++
++ TRACE_MEM("pages=%d, size=%d", pages, size);
++
++ scnprintf(pool->cache_names[cache_num],
++ sizeof(pool->cache_names[cache_num]),
++ "%s-%uK", pool->name, (pages << PAGE_SHIFT) >> 10);
++ pool->caches[cache_num] = kmem_cache_create(
++ pool->cache_names[cache_num], size, 0, SCST_SLAB_FLAGS, NULL
++ );
++ return;
++}
++
++/* Must be called under sgv_pools_mutex */
++static int sgv_pool_init(struct sgv_pool *pool, const char *name,
++ enum sgv_clustering_types clustering_type, int single_alloc_pages,
++ int purge_interval)
++{
++ int res = -ENOMEM;
++ int i;
++
++ TRACE_ENTRY();
++
++ if (single_alloc_pages < 0) {
++ PRINT_ERROR("Wrong single_alloc_pages value %d",
++ single_alloc_pages);
++ res = -EINVAL;
++ goto out;
++ }
++
++ memset(pool, 0, sizeof(*pool));
++
++ atomic_set(&pool->big_alloc, 0);
++ atomic_set(&pool->big_pages, 0);
++ atomic_set(&pool->big_merged, 0);
++ atomic_set(&pool->other_alloc, 0);
++ atomic_set(&pool->other_pages, 0);
++ atomic_set(&pool->other_merged, 0);
++
++ pool->clustering_type = clustering_type;
++ pool->single_alloc_pages = single_alloc_pages;
++ if (purge_interval != 0) {
++ pool->purge_interval = purge_interval;
++ if (purge_interval < 0) {
++ /* Let's pretend that it's always scheduled */
++ pool->purge_work_scheduled = 1;
++ }
++ } else
++ pool->purge_interval = SGV_DEFAULT_PURGE_INTERVAL;
++ if (single_alloc_pages == 0) {
++ pool->max_caches = SGV_POOL_ELEMENTS;
++ pool->max_cached_pages = 1 << (SGV_POOL_ELEMENTS - 1);
++ } else {
++ pool->max_caches = 1;
++ pool->max_cached_pages = single_alloc_pages;
++ }
++ pool->alloc_fns.alloc_pages_fn = sgv_alloc_sys_pages;
++ pool->alloc_fns.free_pages_fn = sgv_free_sys_sg_entries;
++
++ TRACE_MEM("name %s, sizeof(*obj)=%zd, clustering_type=%d, "
++ "single_alloc_pages=%d, max_caches=%d, max_cached_pages=%d",
++ name, sizeof(struct sgv_pool_obj), clustering_type,
++ single_alloc_pages, pool->max_caches, pool->max_cached_pages);
++
++ strlcpy(pool->name, name, sizeof(pool->name)-1);
++
++ pool->owner_mm = current->mm;
++
++ for (i = 0; i < pool->max_caches; i++) {
++ sgv_pool_init_cache(pool, i);
++ if (pool->caches[i] == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "Allocation of sgv_pool "
++ "cache %s(%d) failed", name, i);
++ goto out_free;
++ }
++ }
++
++ atomic_set(&pool->sgv_pool_ref, 1);
++ spin_lock_init(&pool->sgv_pool_lock);
++ INIT_LIST_HEAD(&pool->sorted_recycling_list);
++ for (i = 0; i < pool->max_caches; i++)
++ INIT_LIST_HEAD(&pool->recycling_lists[i]);
++
++ INIT_DELAYED_WORK(&pool->sgv_purge_work,
++ (void (*)(struct work_struct *))sgv_purge_work_fn);
++
++ spin_lock_bh(&sgv_pools_lock);
++ list_add_tail(&pool->sgv_pools_list_entry, &sgv_pools_list);
++ spin_unlock_bh(&sgv_pools_lock);
++
++ res = scst_sgv_sysfs_create(pool);
++ if (res != 0)
++ goto out_del;
++
++ res = 0;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ spin_lock_bh(&sgv_pools_lock);
++ list_del(&pool->sgv_pools_list_entry);
++ spin_unlock_bh(&sgv_pools_lock);
++
++out_free:
++ for (i = 0; i < pool->max_caches; i++) {
++ if (pool->caches[i]) {
++ kmem_cache_destroy(pool->caches[i]);
++ pool->caches[i] = NULL;
++ } else
++ break;
++ }
++ goto out;
++}
++
++static void sgv_evaluate_local_max_pages(void)
++{
++ int space4sgv_ttbl = PAGE_SIZE - sizeof(struct sgv_pool_obj);
++
++ sgv_max_local_pages = space4sgv_ttbl /
++ (sizeof(struct trans_tbl_ent) + sizeof(struct scatterlist));
++
++ sgv_max_trans_pages = space4sgv_ttbl / sizeof(struct trans_tbl_ent);
++
++ TRACE_MEM("sgv_max_local_pages %d, sgv_max_trans_pages %d",
++ sgv_max_local_pages, sgv_max_trans_pages);
++ return;
++}
++
++/**
++ * sgv_pool_flush - flushe the SGV pool
++ *
++ * Flushes, i.e. frees, all the cached entries in the SGV pool.
++ */
++void sgv_pool_flush(struct sgv_pool *pool)
++{
++ int i;
++
++ TRACE_ENTRY();
++
++ for (i = 0; i < pool->max_caches; i++) {
++ struct sgv_pool_obj *obj;
++
++ spin_lock_bh(&pool->sgv_pool_lock);
++
++ while (!list_empty(&pool->recycling_lists[i])) {
++ obj = list_entry(pool->recycling_lists[i].next,
++ struct sgv_pool_obj, recycling_list_entry);
++
++ __sgv_purge_from_cache(obj);
++
++ spin_unlock_bh(&pool->sgv_pool_lock);
++
++ EXTRACHECKS_BUG_ON(obj->owner_pool != pool);
++ sgv_dtor_and_free(obj);
++
++ spin_lock_bh(&pool->sgv_pool_lock);
++ }
++ spin_unlock_bh(&pool->sgv_pool_lock);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(sgv_pool_flush);
++
++static void sgv_pool_destroy(struct sgv_pool *pool)
++{
++ int i;
++
++ TRACE_ENTRY();
++
++ cancel_delayed_work_sync(&pool->sgv_purge_work);
++
++ sgv_pool_flush(pool);
++
++ mutex_lock(&sgv_pools_mutex);
++ spin_lock_bh(&sgv_pools_lock);
++ list_del(&pool->sgv_pools_list_entry);
++ spin_unlock_bh(&sgv_pools_lock);
++ mutex_unlock(&sgv_pools_mutex);
++
++ scst_sgv_sysfs_del(pool);
++
++ for (i = 0; i < pool->max_caches; i++) {
++ if (pool->caches[i])
++ kmem_cache_destroy(pool->caches[i]);
++ pool->caches[i] = NULL;
++ }
++
++ kfree(pool);
++
++ TRACE_EXIT();
++ return;
++}
++
++/**
++ * sgv_pool_set_allocator - set custom pages allocator
++ * @pool: the cache
++ * @alloc_pages_fn: pages allocation function
++ * @free_pages_fn: pages freeing function
++ *
++ * Description:
++ * Allows to set custom pages allocator for the SGV pool.
++ * See the SGV pool documentation for more details.
++ */
++void sgv_pool_set_allocator(struct sgv_pool *pool,
++ struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *),
++ void (*free_pages_fn)(struct scatterlist *, int, void *))
++{
++ pool->alloc_fns.alloc_pages_fn = alloc_pages_fn;
++ pool->alloc_fns.free_pages_fn = free_pages_fn;
++ return;
++}
++EXPORT_SYMBOL_GPL(sgv_pool_set_allocator);
++
++/**
++ * sgv_pool_create - creates and initializes an SGV pool
++ * @name: the name of the SGV pool
++ * @clustered: sets type of the pages clustering.
++ * @single_alloc_pages: if 0, then the SGV pool will work in the set of
++ * power 2 size buffers mode. If >0, then the SGV pool will
++ * work in the fixed size buffers mode. In this case
++ * single_alloc_pages sets the size of each buffer in pages.
++ * @shared: sets if the SGV pool can be shared between devices or not.
++ * The cache sharing allowed only between devices created inside
++ * the same address space. If an SGV pool is shared, each
++ * subsequent call of sgv_pool_create() with the same cache name
++ * will not create a new cache, but instead return a reference
++ * to it.
++ * @purge_interval: sets the cache purging interval. I.e., an SG buffer
++ * will be freed if it's unused for time t
++ * purge_interval <= t < 2*purge_interval. If purge_interval
++ * is 0, then the default interval will be used (60 seconds).
++ * If purge_interval <0, then the automatic purging will be
++ * disabled.
++ *
++ * Description:
++ * Returns the resulting SGV pool or NULL in case of any error.
++ */
++struct sgv_pool *sgv_pool_create(const char *name,
++ enum sgv_clustering_types clustering_type,
++ int single_alloc_pages, bool shared, int purge_interval)
++{
++ struct sgv_pool *pool;
++ int rc;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&sgv_pools_mutex);
++
++ list_for_each_entry(pool, &sgv_pools_list, sgv_pools_list_entry) {
++ if (strcmp(pool->name, name) == 0) {
++ if (shared) {
++ if (pool->owner_mm != current->mm) {
++ PRINT_ERROR("Attempt of a shared use "
++ "of SGV pool %s with "
++ "different MM", name);
++ goto out_unlock;
++ }
++ sgv_pool_get(pool);
++ goto out_unlock;
++ } else {
++ PRINT_ERROR("SGV pool %s already exists", name);
++ pool = NULL;
++ goto out_unlock;
++ }
++ }
++ }
++
++ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
++ if (pool == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of sgv_pool failed");
++ goto out_unlock;
++ }
++
++ rc = sgv_pool_init(pool, name, clustering_type, single_alloc_pages,
++ purge_interval);
++ if (rc != 0)
++ goto out_free;
++
++out_unlock:
++ mutex_unlock(&sgv_pools_mutex);
++
++ TRACE_EXIT_RES(pool != NULL);
++ return pool;
++
++out_free:
++ kfree(pool);
++ goto out_unlock;
++}
++EXPORT_SYMBOL_GPL(sgv_pool_create);
++
++/**
++ * sgv_pool_get - increase ref counter for the corresponding SGV pool
++ *
++ * Increases ref counter for the corresponding SGV pool
++ */
++void sgv_pool_get(struct sgv_pool *pool)
++{
++ atomic_inc(&pool->sgv_pool_ref);
++ TRACE_MEM("Incrementing sgv pool %p ref (new value %d)",
++ pool, atomic_read(&pool->sgv_pool_ref));
++ return;
++}
++EXPORT_SYMBOL_GPL(sgv_pool_get);
++
++/**
++ * sgv_pool_put - decrease ref counter for the corresponding SGV pool
++ *
++ * Decreases ref counter for the corresponding SGV pool. If the ref
++ * counter reaches 0, the cache will be destroyed.
++ */
++void sgv_pool_put(struct sgv_pool *pool)
++{
++ TRACE_MEM("Decrementing sgv pool %p ref (new value %d)",
++ pool, atomic_read(&pool->sgv_pool_ref)-1);
++ if (atomic_dec_and_test(&pool->sgv_pool_ref))
++ sgv_pool_destroy(pool);
++ return;
++}
++EXPORT_SYMBOL_GPL(sgv_pool_put);
++
++/**
++ * sgv_pool_del - deletes the corresponding SGV pool
++ * @pool: the cache to delete.
++ *
++ * Description:
++ * If the cache is shared, it will decrease its reference counter.
++ * If the reference counter reaches 0, the cache will be destroyed.
++ */
++void sgv_pool_del(struct sgv_pool *pool)
++{
++ TRACE_ENTRY();
++
++ sgv_pool_put(pool);
++
++ TRACE_EXIT();
++ return;
++}
++EXPORT_SYMBOL_GPL(sgv_pool_del);
++
++/* Both parameters in pages */
++int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ sgv_hi_wmk = mem_hwmark;
++ sgv_lo_wmk = mem_lwmark;
++
++ sgv_evaluate_local_max_pages();
++
++ sgv_norm_pool = sgv_pool_create("sgv", sgv_no_clustering, 0, false, 0);
++ if (sgv_norm_pool == NULL)
++ goto out_err;
++
++ sgv_norm_clust_pool = sgv_pool_create("sgv-clust",
++ sgv_full_clustering, 0, false, 0);
++ if (sgv_norm_clust_pool == NULL)
++ goto out_free_norm;
++
++ sgv_dma_pool = sgv_pool_create("sgv-dma", sgv_no_clustering, 0,
++ false, 0);
++ if (sgv_dma_pool == NULL)
++ goto out_free_clust;
++
++ sgv_shrinker.shrink = sgv_shrink;
++ sgv_shrinker.seeks = DEFAULT_SEEKS;
++ register_shrinker(&sgv_shrinker);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free_clust:
++ sgv_pool_destroy(sgv_norm_clust_pool);
++
++out_free_norm:
++ sgv_pool_destroy(sgv_norm_pool);
++
++out_err:
++ res = -ENOMEM;
++ goto out;
++}
++
++void scst_sgv_pools_deinit(void)
++{
++ TRACE_ENTRY();
++
++ unregister_shrinker(&sgv_shrinker);
++
++ sgv_pool_destroy(sgv_dma_pool);
++ sgv_pool_destroy(sgv_norm_pool);
++ sgv_pool_destroy(sgv_norm_clust_pool);
++
++ flush_scheduled_work();
++
++ TRACE_EXIT();
++ return;
++}
++
++ssize_t sgv_sysfs_stat_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct sgv_pool *pool;
++ int i, total = 0, hit = 0, merged = 0, allocated = 0;
++ int oa, om, res;
++
++ pool = container_of(kobj, struct sgv_pool, sgv_kobj);
++
++ for (i = 0; i < SGV_POOL_ELEMENTS; i++) {
++ int t;
++
++ hit += atomic_read(&pool->cache_acc[i].hit_alloc);
++ total += atomic_read(&pool->cache_acc[i].total_alloc);
++
++ t = atomic_read(&pool->cache_acc[i].total_alloc) -
++ atomic_read(&pool->cache_acc[i].hit_alloc);
++ allocated += t * (1 << i);
++ merged += atomic_read(&pool->cache_acc[i].merged);
++ }
++
++ res = sprintf(buf, "%-30s %-11s %-11s %-11s %-11s", "Name", "Hit", "Total",
++ "% merged", "Cached (P/I/O)");
++
++ res += sprintf(&buf[res], "\n%-30s %-11d %-11d %-11d %d/%d/%d\n",
++ pool->name, hit, total,
++ (allocated != 0) ? merged*100/allocated : 0,
++ pool->cached_pages, pool->inactive_cached_pages,
++ pool->cached_entries);
++
++ for (i = 0; i < SGV_POOL_ELEMENTS; i++) {
++ int t = atomic_read(&pool->cache_acc[i].total_alloc) -
++ atomic_read(&pool->cache_acc[i].hit_alloc);
++ allocated = t * (1 << i);
++ merged = atomic_read(&pool->cache_acc[i].merged);
++
++ res += sprintf(&buf[res], " %-28s %-11d %-11d %d\n",
++ pool->cache_names[i],
++ atomic_read(&pool->cache_acc[i].hit_alloc),
++ atomic_read(&pool->cache_acc[i].total_alloc),
++ (allocated != 0) ? merged*100/allocated : 0);
++ }
++
++ allocated = atomic_read(&pool->big_pages);
++ merged = atomic_read(&pool->big_merged);
++ oa = atomic_read(&pool->other_pages);
++ om = atomic_read(&pool->other_merged);
++
++ res += sprintf(&buf[res], " %-40s %d/%-9d %d/%d\n", "big/other",
++ atomic_read(&pool->big_alloc), atomic_read(&pool->other_alloc),
++ (allocated != 0) ? merged*100/allocated : 0,
++ (oa != 0) ? om/oa : 0);
++
++ return res;
++}
++
++ssize_t sgv_sysfs_stat_reset(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ struct sgv_pool *pool;
++ int i;
++
++ TRACE_ENTRY();
++
++ pool = container_of(kobj, struct sgv_pool, sgv_kobj);
++
++ for (i = 0; i < SGV_POOL_ELEMENTS; i++) {
++ atomic_set(&pool->cache_acc[i].hit_alloc, 0);
++ atomic_set(&pool->cache_acc[i].total_alloc, 0);
++ atomic_set(&pool->cache_acc[i].merged, 0);
++ }
++
++ atomic_set(&pool->big_pages, 0);
++ atomic_set(&pool->big_merged, 0);
++ atomic_set(&pool->big_alloc, 0);
++ atomic_set(&pool->other_pages, 0);
++ atomic_set(&pool->other_merged, 0);
++ atomic_set(&pool->other_alloc, 0);
++
++ PRINT_INFO("Statistics for SGV pool %s resetted", pool->name);
++
++ TRACE_EXIT_RES(count);
++ return count;
++}
++
++ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct sgv_pool *pool;
++ int inactive_pages = 0, res;
++
++ TRACE_ENTRY();
++
++ spin_lock_bh(&sgv_pools_lock);
++ list_for_each_entry(pool, &sgv_active_pools_list,
++ sgv_active_pools_list_entry) {
++ inactive_pages += pool->inactive_cached_pages;
++ }
++ spin_unlock_bh(&sgv_pools_lock);
++
++ res = sprintf(buf, "%-42s %d/%d\n%-42s %d/%d\n%-42s %d/%d\n"
++ "%-42s %-11d\n",
++ "Inactive/active pages", inactive_pages,
++ atomic_read(&sgv_pages_total) - inactive_pages,
++ "Hi/lo watermarks [pages]", sgv_hi_wmk, sgv_lo_wmk,
++ "Hi watermark releases/failures",
++ atomic_read(&sgv_releases_on_hiwmk),
++ atomic_read(&sgv_releases_on_hiwmk_failed),
++ "Other allocs", atomic_read(&sgv_other_total_alloc));
++
++ TRACE_EXIT();
++ return res;
++}
++
++ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ TRACE_ENTRY();
++
++ atomic_set(&sgv_releases_on_hiwmk, 0);
++ atomic_set(&sgv_releases_on_hiwmk_failed, 0);
++ atomic_set(&sgv_other_total_alloc, 0);
++
++ PRINT_INFO("%s", "Global SGV pool statistics resetted");
++
++ TRACE_EXIT_RES(count);
++ return count;
++}
++
+diff -uprN orig/linux-2.6.36/Documentation/scst/sgv_cache.txt linux-2.6.36/Documentation/scst/sgv_cache.txt
+--- orig/linux-2.6.36/Documentation/scst/sgv_cache.txt
++++ linux-2.6.36/Documentation/scst/sgv_cache.txt
+@@ -0,0 +1,224 @@
++ SCST SGV CACHE.
++
++ PROGRAMMING INTERFACE DESCRIPTION.
++
++ For SCST version 1.0.2
++
++SCST SGV cache is a memory management subsystem in SCST. One can call it
++a "memory pool", but Linux kernel already have a mempool interface,
++which serves different purposes. SGV cache provides to SCST core, target
++drivers and backend dev handlers facilities to allocate, build and cache
++SG vectors for data buffers. The main advantage of it is the caching
++facility, when it doesn't free to the system each vector, which is not
++used anymore, but keeps it for a while (possibly indefinitely) to let it
++be reused by the next consecutive command. This allows to:
++
++ - Reduce commands processing latencies and, hence, improve performance;
++
++ - Make commands processing latencies predictable, which is essential
++ for RT applications.
++
++The freed SG vectors are kept by the SGV cache either for some (possibly
++indefinite) time, or, optionally, until the system needs more memory and
++asks to free some using the set_shrinker() interface. Also the SGV cache
++allows to:
++
++ - Cluster pages together. "Cluster" means merging adjacent pages in a
++single SG entry. It allows to have less SG entries in the resulting SG
++vector, hence improve performance handling it as well as allow to
++work with bigger buffers on hardware with limited SG capabilities.
++
++ - Set custom page allocator functions. For instance, scst_user device
++handler uses this facility to eliminate unneeded mapping/unmapping of
++user space pages and avoid unneeded IOCTL calls for buffers allocations.
++In fileio_tgt application, which uses a regular malloc() function to
++allocate data buffers, this facility allows ~30% less CPU load and
++considerable performance increase.
++
++ - Prevent each initiator or all initiators altogether to allocate too
++much memory and DoS the target. Consider 10 initiators, which can have
++access to 10 devices each. Any of them can queue up to 64 commands, each
++can transfer up to 1MB of data. So, all of them in a peak can allocate
++up to 10*10*64 = ~6.5GB of memory for data buffers. This amount must be
++limited somehow and the SGV cache performs this function.
++
++From implementation POV the SGV cache is a simple extension of the kmem
++cache. It can work in 2 modes:
++
++1. With fixed size buffers.
++
++2. With a set of power 2 size buffers. In this mode each SGV cache
++(struct sgv_pool) has SGV_POOL_ELEMENTS (11 currently) of kmem caches.
++Each of those kmem caches keeps SGV cache objects (struct sgv_pool_obj)
++corresponding to SG vectors with size of order X pages. For instance,
++request to allocate 4 pages will be served from kmem cache[2], since the
++order of the of number of requested pages is 2. If later request to
++allocate 11KB comes, the same SG vector with 4 pages will be reused (see
++below). This mode is in average allows less memory overhead comparing
++with the fixed size buffers mode.
++
++Consider how the SGV cache works in the set of buffers mode. When a
++request to allocate new SG vector comes, sgv_pool_alloc() via
++sgv_get_obj() checks if there is already a cached vector with that
++order. If yes, then that vector will be reused and its length, if
++necessary, will be modified to match the requested size. In the above
++example request for 11KB buffer, 4 pages vector will be reused and
++modified using trans_tbl to contain 3 pages and the last entry will be
++modified to contain the requested length - 2*PAGE_SIZE. If there is no
++cached object, then a new sgv_pool_obj will be allocated from the
++corresponding kmem cache, chosen by the order of number of requested
++pages. Then that vector will be filled by pages and returned.
++
++In the fixed size buffers mode the SGV cache works similarly, except
++that it always allocate buffer with the predefined fixed size. I.e.
++even for 4K request the whole buffer with predefined size, say, 1MB,
++will be used.
++
++In both modes, if size of a request exceeds the maximum allowed for
++caching buffer size, the requested buffer will be allocated, but not
++cached.
++
++Freed cached sgv_pool_obj objects are actually freed to the system
++either by the purge work, which is scheduled once in 60 seconds, or in
++sgv_shrink() called by system, when it's asking for memory.
++
++ Interface.
++
++struct sgv_pool *sgv_pool_create(const char *name,
++ enum sgv_clustering_types clustered, int single_alloc_pages,
++ bool shared, int purge_interval)
++
++This function creates and initializes an SGV cache. It has the following
++arguments:
++
++ - name - the name of the SGV cache
++
++ - clustered - sets type of the pages clustering. The type can be:
++
++ * sgv_no_clustering - no clustering performed.
++
++ * sgv_tail_clustering - a page will only be merged with the latest
++ previously allocated page, so the order of pages in the SG will be
++ preserved
++
++ * sgv_full_clustering - free merging of pages at any place in
++ the SG is allowed. This mode usually provides the best merging
++ rate.
++
++ - single_alloc_pages - if 0, then the SGV cache will work in the set of
++ power 2 size buffers mode. If >0, then the SGV cache will work in the
++ fixed size buffers mode. In this case single_alloc_pages sets the
++ size of each buffer in pages.
++
++ - shared - sets if the SGV cache can be shared between devices or not.
++ The cache sharing allowed only between devices created inside the same
++ address space. If an SGV cache is shared, each subsequent call of
++ sgv_pool_create() with the same cache name will not create a new cache,
++ but instead return a reference to it.
++
++ - purge_interval - sets the cache purging interval. I.e. an SG buffer
++ will be freed if it's unused for time t purge_interval <= t <
++ 2*purge_interval. If purge_interval is 0, then the default interval
++ will be used (60 seconds). If purge_interval <0, then the automatic
++ purging will be disabled. Shrinking by the system's demand will also
++ be disabled.
++
++Returns the resulting SGV cache or NULL in case of any error.
++
++void sgv_pool_del(struct sgv_pool *pool)
++
++This function deletes the corresponding SGV cache. If the cache is
++shared, it will decrease its reference counter. If the reference counter
++reaches 0, the cache will be destroyed.
++
++void sgv_pool_flush(struct sgv_pool *pool)
++
++This function flushes, i.e. frees, all the cached entries in the SGV
++cache.
++
++void sgv_pool_set_allocator(struct sgv_pool *pool,
++ struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp, void *priv),
++ void (*free_pages_fn)(struct scatterlist *sg, int sg_count, void *priv));
++
++This function allows to set for the SGV cache a custom pages allocator. For
++instance, scst_user uses such function to supply to the cache mapped from
++user space pages.
++
++alloc_pages_fn() has the following parameters:
++
++ - sg - SG entry, to which the allocated page should be added.
++
++ - gfp - the allocation GFP flags
++
++ - priv - pointer to a private data supplied to sgv_pool_alloc()
++
++This function should return the allocated page or NULL, if no page was
++allocated.
++
++free_pages_fn() has the following parameters:
++
++ - sg - SG vector to free
++
++ - sg_count - number of SG entries in the sg
++
++ - priv - pointer to a private data supplied to the corresponding sgv_pool_alloc()
++
++struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
++ gfp_t gfp_mask, int flags, int *count,
++ struct sgv_pool_obj **sgv, struct scst_mem_lim *mem_lim, void *priv)
++
++This function allocates an SG vector from the SGV cache. It has the
++following parameters:
++
++ - pool - the cache to alloc from
++
++ - size - size of the resulting SG vector in bytes
++
++ - gfp_mask - the allocation mask
++
++ - flags - the allocation flags. The following flags are possible and
++ can be set using OR operation:
++
++ * SGV_POOL_ALLOC_NO_CACHED - the SG vector must not be cached.
++
++ * SGV_POOL_NO_ALLOC_ON_CACHE_MISS - don't do an allocation on a
++ cache miss.
++
++ * SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL - return an empty SGV object,
++ i.e. without the SG vector, if the allocation can't be completed.
++ For instance, because SGV_POOL_NO_ALLOC_ON_CACHE_MISS flag set.
++
++ - count - the resulting count of SG entries in the resulting SG vector.
++
++ - sgv - the resulting SGV object. It should be used to free the
++ resulting SG vector.
++
++ - mem_lim - memory limits, see below.
++
++ - priv - pointer to private for this allocation data. This pointer will
++ be supplied to alloc_pages_fn() and free_pages_fn() and can be
++ retrieved by sgv_get_priv().
++
++This function returns pointer to the resulting SG vector or NULL in case
++of any error.
++
++void sgv_pool_free(struct sgv_pool_obj *sgv, struct scst_mem_lim *mem_lim)
++
++This function frees previously allocated SG vector, referenced by SGV
++cache object sgv.
++
++void *sgv_get_priv(struct sgv_pool_obj *sgv)
++
++This function allows to get the allocation private data for this SGV
++cache object sgv. The private data are set by sgv_pool_alloc().
++
++void scst_init_mem_lim(struct scst_mem_lim *mem_lim)
++
++This function initializes memory limits structure mem_lim according to
++the current system configuration. This structure should be latter used
++to track and limit allocated by one or more SGV caches memory.
++
++ Runtime information and statistics.
++
++Runtime information and statistics is available in /sys/kernel/scst_tgt/sgv.
++
+diff -uprN orig/linux-2.6.36/include/scst/scst_user.h linux-2.6.36/include/scst/scst_user.h
+--- orig/linux-2.6.36/include/scst/scst_user.h
++++ linux-2.6.36/include/scst/scst_user.h
+@@ -0,0 +1,322 @@
++/*
++ * include/scst_user.h
++ *
++ * Copyright (C) 2007 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * Contains constants and data structures for scst_user module.
++ * See http://scst.sourceforge.net/doc/scst_user_spec.txt or
++ * scst_user_spec.txt for description.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef __SCST_USER_H
++#define __SCST_USER_H
++
++#include <scst/scst_const.h>
++
++#define DEV_USER_NAME "scst_user"
++#define DEV_USER_PATH "/dev/"
++#define DEV_USER_VERSION_NAME "2.0.0.1"
++#define DEV_USER_VERSION \
++ DEV_USER_VERSION_NAME "$Revision: 3165 $" SCST_CONST_VERSION
++
++#define SCST_USER_PARSE_STANDARD 0
++#define SCST_USER_PARSE_CALL 1
++#define SCST_USER_PARSE_EXCEPTION 2
++#define SCST_USER_MAX_PARSE_OPT SCST_USER_PARSE_EXCEPTION
++
++#define SCST_USER_ON_FREE_CMD_CALL 0
++#define SCST_USER_ON_FREE_CMD_IGNORE 1
++#define SCST_USER_MAX_ON_FREE_CMD_OPT SCST_USER_ON_FREE_CMD_IGNORE
++
++#define SCST_USER_MEM_NO_REUSE 0
++#define SCST_USER_MEM_REUSE_READ 1
++#define SCST_USER_MEM_REUSE_WRITE 2
++#define SCST_USER_MEM_REUSE_ALL 3
++#define SCST_USER_MAX_MEM_REUSE_OPT SCST_USER_MEM_REUSE_ALL
++
++#define SCST_USER_PARTIAL_TRANSFERS_NOT_SUPPORTED 0
++#define SCST_USER_PARTIAL_TRANSFERS_SUPPORTED_ORDERED 1
++#define SCST_USER_PARTIAL_TRANSFERS_SUPPORTED 2
++#define SCST_USER_MAX_PARTIAL_TRANSFERS_OPT \
++ SCST_USER_PARTIAL_TRANSFERS_SUPPORTED
++
++#ifndef aligned_u64
++#define aligned_u64 uint64_t __attribute__((aligned(8)))
++#endif
++
++/*************************************************************
++ ** Private ucmd states
++ *************************************************************/
++#define UCMD_STATE_NEW 0
++#define UCMD_STATE_PARSING 1
++#define UCMD_STATE_BUF_ALLOCING 2
++#define UCMD_STATE_EXECING 3
++#define UCMD_STATE_ON_FREEING 4
++#define UCMD_STATE_ON_FREE_SKIPPED 5
++#define UCMD_STATE_ON_CACHE_FREEING 6
++#define UCMD_STATE_TM_EXECING 7
++
++#define UCMD_STATE_ATTACH_SESS 0x20
++#define UCMD_STATE_DETACH_SESS 0x21
++
++struct scst_user_opt {
++ uint8_t parse_type;
++ uint8_t on_free_cmd_type;
++ uint8_t memory_reuse_type;
++ uint8_t partial_transfers_type;
++ int32_t partial_len;
++
++ /* SCSI control mode page parameters, see SPC */
++ uint8_t tst;
++ uint8_t queue_alg;
++ uint8_t tas;
++ uint8_t swp;
++ uint8_t d_sense;
++
++ uint8_t has_own_order_mgmt;
++};
++
++struct scst_user_dev_desc {
++ aligned_u64 version_str;
++ aligned_u64 license_str;
++ uint8_t type;
++ uint8_t sgv_shared;
++ uint8_t sgv_disable_clustered_pool;
++ int32_t sgv_single_alloc_pages;
++ int32_t sgv_purge_interval;
++ struct scst_user_opt opt;
++ uint32_t block_size;
++ uint8_t enable_pr_cmds_notifications;
++ char name[SCST_MAX_NAME];
++ char sgv_name[SCST_MAX_NAME];
++};
++
++struct scst_user_sess {
++ aligned_u64 sess_h;
++ aligned_u64 lun;
++ uint16_t threads_num;
++ uint8_t rd_only;
++ uint16_t scsi_transport_version;
++ uint16_t phys_transport_version;
++ char initiator_name[SCST_MAX_EXTERNAL_NAME];
++ char target_name[SCST_MAX_EXTERNAL_NAME];
++};
++
++struct scst_user_scsi_cmd_parse {
++ aligned_u64 sess_h;
++
++ uint8_t cdb[SCST_MAX_CDB_SIZE];
++ uint16_t cdb_len;
++ uint16_t ext_cdb_len;
++
++ int32_t timeout;
++ int32_t bufflen;
++ int32_t out_bufflen;
++
++ uint32_t op_flags;
++
++ uint8_t queue_type;
++ uint8_t data_direction;
++
++ uint8_t expected_values_set;
++ uint8_t expected_data_direction;
++ int32_t expected_transfer_len;
++ int32_t expected_out_transfer_len;
++
++ uint32_t sn;
++};
++
++struct scst_user_scsi_cmd_alloc_mem {
++ aligned_u64 sess_h;
++
++ uint8_t cdb[SCST_MAX_CDB_SIZE];
++ uint16_t cdb_len;
++ uint16_t ext_cdb_len;
++
++ int32_t alloc_len;
++
++ uint8_t queue_type;
++ uint8_t data_direction;
++
++ uint32_t sn;
++};
++
++struct scst_user_scsi_cmd_exec {
++ aligned_u64 sess_h;
++
++ uint8_t cdb[SCST_MAX_CDB_SIZE];
++ uint16_t cdb_len;
++ uint16_t ext_cdb_len;
++
++ int32_t data_len;
++ int32_t bufflen;
++ int32_t alloc_len;
++ aligned_u64 pbuf;
++ uint8_t queue_type;
++ uint8_t data_direction;
++ uint8_t partial;
++ int32_t timeout;
++
++ aligned_u64 p_out_buf;
++ int32_t out_bufflen;
++
++ uint32_t sn;
++
++ uint32_t parent_cmd_h;
++ int32_t parent_cmd_data_len;
++ uint32_t partial_offset;
++};
++
++struct scst_user_scsi_on_free_cmd {
++ aligned_u64 pbuf;
++ int32_t resp_data_len;
++ uint8_t buffer_cached;
++ uint8_t aborted;
++ uint8_t status;
++ uint8_t delivery_status;
++};
++
++struct scst_user_on_cached_mem_free {
++ aligned_u64 pbuf;
++};
++
++struct scst_user_tm {
++ aligned_u64 sess_h;
++ uint32_t fn;
++ uint32_t cmd_h_to_abort;
++ uint32_t cmd_sn;
++ uint8_t cmd_sn_set;
++};
++
++struct scst_user_get_cmd {
++ uint32_t cmd_h;
++ uint32_t subcode;
++ union {
++ aligned_u64 preply;
++ struct scst_user_sess sess;
++ struct scst_user_scsi_cmd_parse parse_cmd;
++ struct scst_user_scsi_cmd_alloc_mem alloc_cmd;
++ struct scst_user_scsi_cmd_exec exec_cmd;
++ struct scst_user_scsi_on_free_cmd on_free_cmd;
++ struct scst_user_on_cached_mem_free on_cached_mem_free;
++ struct scst_user_tm tm_cmd;
++ };
++};
++
++/* Be careful adding new members here, this structure is allocated on stack! */
++struct scst_user_scsi_cmd_reply_parse {
++ uint8_t status;
++ union {
++ struct {
++ uint8_t queue_type;
++ uint8_t data_direction;
++ uint16_t cdb_len;
++ uint32_t op_flags;
++ int32_t data_len;
++ int32_t bufflen;
++ };
++ struct {
++ uint8_t sense_len;
++ aligned_u64 psense_buffer;
++ };
++ };
++};
++
++/* Be careful adding new members here, this structure is allocated on stack! */
++struct scst_user_scsi_cmd_reply_alloc_mem {
++ aligned_u64 pbuf;
++};
++
++/* Be careful adding new members here, this structure is allocated on stack! */
++struct scst_user_scsi_cmd_reply_exec {
++ int32_t resp_data_len;
++ aligned_u64 pbuf;
++
++#define SCST_EXEC_REPLY_BACKGROUND 0
++#define SCST_EXEC_REPLY_COMPLETED 1
++ uint8_t reply_type;
++
++ uint8_t status;
++ uint8_t sense_len;
++ aligned_u64 psense_buffer;
++};
++
++/* Be careful adding new members here, this structure is allocated on stack! */
++struct scst_user_reply_cmd {
++ uint32_t cmd_h;
++ uint32_t subcode;
++ union {
++ int32_t result;
++ struct scst_user_scsi_cmd_reply_parse parse_reply;
++ struct scst_user_scsi_cmd_reply_alloc_mem alloc_reply;
++ struct scst_user_scsi_cmd_reply_exec exec_reply;
++ };
++};
++
++/* Be careful adding new members here, this structure is allocated on stack! */
++struct scst_user_get_ext_cdb {
++ uint32_t cmd_h;
++ aligned_u64 ext_cdb_buffer;
++};
++
++/* Be careful adding new members here, this structure is allocated on stack! */
++struct scst_user_prealloc_buffer_in {
++ aligned_u64 pbuf;
++ uint32_t bufflen;
++ uint8_t for_clust_pool;
++};
++
++/* Be careful adding new members here, this structure is allocated on stack! */
++struct scst_user_prealloc_buffer_out {
++ uint32_t cmd_h;
++};
++
++/* Be careful adding new members here, this structure is allocated on stack! */
++union scst_user_prealloc_buffer {
++ struct scst_user_prealloc_buffer_in in;
++ struct scst_user_prealloc_buffer_out out;
++};
++
++#define SCST_USER_REGISTER_DEVICE _IOW('u', 1, struct scst_user_dev_desc)
++#define SCST_USER_UNREGISTER_DEVICE _IO('u', 2)
++#define SCST_USER_SET_OPTIONS _IOW('u', 3, struct scst_user_opt)
++#define SCST_USER_GET_OPTIONS _IOR('u', 4, struct scst_user_opt)
++#define SCST_USER_REPLY_AND_GET_CMD _IOWR('u', 5, struct scst_user_get_cmd)
++#define SCST_USER_REPLY_CMD _IOW('u', 6, struct scst_user_reply_cmd)
++#define SCST_USER_FLUSH_CACHE _IO('u', 7)
++#define SCST_USER_DEVICE_CAPACITY_CHANGED _IO('u', 8)
++#define SCST_USER_GET_EXTENDED_CDB _IOWR('u', 9, struct scst_user_get_ext_cdb)
++#define SCST_USER_PREALLOC_BUFFER _IOWR('u', 10, union scst_user_prealloc_buffer)
++
++/* Values for scst_user_get_cmd.subcode */
++#define SCST_USER_ATTACH_SESS \
++ _IOR('s', UCMD_STATE_ATTACH_SESS, struct scst_user_sess)
++#define SCST_USER_DETACH_SESS \
++ _IOR('s', UCMD_STATE_DETACH_SESS, struct scst_user_sess)
++#define SCST_USER_PARSE \
++ _IOWR('s', UCMD_STATE_PARSING, struct scst_user_scsi_cmd_parse)
++#define SCST_USER_ALLOC_MEM \
++ _IOWR('s', UCMD_STATE_BUF_ALLOCING, struct scst_user_scsi_cmd_alloc_mem)
++#define SCST_USER_EXEC \
++ _IOWR('s', UCMD_STATE_EXECING, struct scst_user_scsi_cmd_exec)
++#define SCST_USER_ON_FREE_CMD \
++ _IOR('s', UCMD_STATE_ON_FREEING, struct scst_user_scsi_on_free_cmd)
++#define SCST_USER_ON_CACHED_MEM_FREE \
++ _IOR('s', UCMD_STATE_ON_CACHE_FREEING, \
++ struct scst_user_on_cached_mem_free)
++#define SCST_USER_TASK_MGMT \
++ _IOWR('s', UCMD_STATE_TM_EXECING, struct scst_user_tm)
++
++#endif /* __SCST_USER_H */
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_user.c linux-2.6.36/drivers/scst/dev_handlers/scst_user.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_user.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_user.c
+@@ -0,0 +1,3739 @@
++/*
++ * scst_user.c
++ *
++ * Copyright (C) 2007 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI virtual user space device handler
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/kthread.h>
++#include <linux/delay.h>
++#include <linux/poll.h>
++#include <linux/stddef.h>
++#include <linux/slab.h>
++
++#define LOG_PREFIX DEV_USER_NAME
++
++#include <scst/scst.h>
++#include <scst/scst_user.h>
++#include "scst_dev_handler.h"
++
++#define DEV_USER_CMD_HASH_ORDER 6
++#define DEV_USER_ATTACH_TIMEOUT (5*HZ)
++
++struct scst_user_dev {
++ struct rw_semaphore dev_rwsem;
++
++ /*
++ * Must be kept here, because it's needed on the cleanup time,
++ * when corresponding scst_dev is already dead.
++ */
++ struct scst_cmd_threads udev_cmd_threads;
++
++ /* Protected by udev_cmd_threads.cmd_list_lock */
++ struct list_head ready_cmd_list;
++
++ /* Protected by dev_rwsem or don't need any protection */
++ unsigned int blocking:1;
++ unsigned int cleanup_done:1;
++ unsigned int tst:3;
++ unsigned int queue_alg:4;
++ unsigned int tas:1;
++ unsigned int swp:1;
++ unsigned int d_sense:1;
++ unsigned int has_own_order_mgmt:1;
++
++ int (*generic_parse)(struct scst_cmd *cmd,
++ int (*get_block)(struct scst_cmd *cmd));
++
++ int block;
++ int def_block;
++
++ struct scst_mem_lim udev_mem_lim;
++ struct sgv_pool *pool;
++ struct sgv_pool *pool_clust;
++
++ uint8_t parse_type;
++ uint8_t on_free_cmd_type;
++ uint8_t memory_reuse_type;
++ uint8_t partial_transfers_type;
++ uint32_t partial_len;
++
++ struct scst_dev_type devtype;
++
++ /* Both protected by udev_cmd_threads.cmd_list_lock */
++ unsigned int handle_counter;
++ struct list_head ucmd_hash[1 << DEV_USER_CMD_HASH_ORDER];
++
++ struct scst_device *sdev;
++
++ int virt_id;
++ struct list_head dev_list_entry;
++ char name[SCST_MAX_NAME];
++
++ struct list_head cleanup_list_entry;
++ struct completion cleanup_cmpl;
++};
++
++/* Most fields are unprotected, since only one thread at time can access them */
++struct scst_user_cmd {
++ struct scst_cmd *cmd;
++ struct scst_user_dev *dev;
++
++ atomic_t ucmd_ref;
++
++ unsigned int buff_cached:1;
++ unsigned int buf_dirty:1;
++ unsigned int background_exec:1;
++ unsigned int aborted:1;
++
++ struct scst_user_cmd *buf_ucmd;
++
++ int cur_data_page;
++ int num_data_pages;
++ int first_page_offset;
++ unsigned long ubuff;
++ struct page **data_pages;
++ struct sgv_pool_obj *sgv;
++
++ /*
++ * Special flags, which can be accessed asynchronously (hence "long").
++ * Protected by udev_cmd_threads.cmd_list_lock.
++ */
++ unsigned long sent_to_user:1;
++ unsigned long jammed:1;
++ unsigned long this_state_unjammed:1;
++ unsigned long seen_by_user:1; /* here only as a small optimization */
++
++ unsigned int state;
++
++ struct list_head ready_cmd_list_entry;
++
++ unsigned int h;
++ struct list_head hash_list_entry;
++
++ int user_cmd_payload_len;
++ struct scst_user_get_cmd user_cmd;
++
++ /* cmpl used only by ATTACH_SESS, mcmd used only by TM */
++ union {
++ struct completion *cmpl;
++ struct scst_mgmt_cmd *mcmd;
++ };
++ int result;
++};
++
++static struct scst_user_cmd *dev_user_alloc_ucmd(struct scst_user_dev *dev,
++ gfp_t gfp_mask);
++static void dev_user_free_ucmd(struct scst_user_cmd *ucmd);
++
++static int dev_user_parse(struct scst_cmd *cmd);
++static int dev_user_alloc_data_buf(struct scst_cmd *cmd);
++static int dev_user_exec(struct scst_cmd *cmd);
++static void dev_user_on_free_cmd(struct scst_cmd *cmd);
++static int dev_user_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
++ struct scst_tgt_dev *tgt_dev);
++
++static int dev_user_disk_done(struct scst_cmd *cmd);
++static int dev_user_tape_done(struct scst_cmd *cmd);
++
++static struct page *dev_user_alloc_pages(struct scatterlist *sg,
++ gfp_t gfp_mask, void *priv);
++static void dev_user_free_sg_entries(struct scatterlist *sg, int sg_count,
++ void *priv);
++
++static void dev_user_add_to_ready(struct scst_user_cmd *ucmd);
++
++static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy,
++ unsigned long *flags);
++
++static int dev_user_process_reply_on_free(struct scst_user_cmd *ucmd);
++static int dev_user_process_reply_tm_exec(struct scst_user_cmd *ucmd,
++ int status);
++static int dev_user_process_reply_sess(struct scst_user_cmd *ucmd, int status);
++static int dev_user_register_dev(struct file *file,
++ const struct scst_user_dev_desc *dev_desc);
++static int dev_user_unregister_dev(struct file *file);
++static int dev_user_flush_cache(struct file *file);
++static int dev_user_capacity_changed(struct file *file);
++static int dev_user_prealloc_buffer(struct file *file, void __user *arg);
++static int __dev_user_set_opt(struct scst_user_dev *dev,
++ const struct scst_user_opt *opt);
++static int dev_user_set_opt(struct file *file, const struct scst_user_opt *opt);
++static int dev_user_get_opt(struct file *file, void __user *arg);
++
++static unsigned int dev_user_poll(struct file *filp, poll_table *wait);
++static long dev_user_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg);
++static int dev_user_release(struct inode *inode, struct file *file);
++static int dev_user_exit_dev(struct scst_user_dev *dev);
++
++static ssize_t dev_user_sysfs_commands_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++
++static struct kobj_attribute dev_user_commands_attr =
++ __ATTR(commands, S_IRUGO, dev_user_sysfs_commands_show, NULL);
++
++static const struct attribute *dev_user_dev_attrs[] = {
++ &dev_user_commands_attr.attr,
++ NULL,
++};
++
++static int dev_usr_parse(struct scst_cmd *cmd);
++
++/** Data **/
++
++static struct kmem_cache *user_cmd_cachep;
++static struct kmem_cache *user_get_cmd_cachep;
++
++static DEFINE_MUTEX(dev_priv_mutex);
++
++static const struct file_operations dev_user_fops = {
++ .poll = dev_user_poll,
++ .unlocked_ioctl = dev_user_ioctl,
++#ifdef CONFIG_COMPAT
++ .compat_ioctl = dev_user_ioctl,
++#endif
++ .release = dev_user_release,
++};
++
++static struct scst_dev_type dev_user_devtype = {
++ .name = DEV_USER_NAME,
++ .type = -1,
++ .parse = dev_usr_parse,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static int dev_user_major;
++
++static struct class *dev_user_sysfs_class;
++
++static DEFINE_SPINLOCK(dev_list_lock);
++static LIST_HEAD(dev_list);
++
++static DEFINE_SPINLOCK(cleanup_lock);
++static LIST_HEAD(cleanup_list);
++static DECLARE_WAIT_QUEUE_HEAD(cleanup_list_waitQ);
++static struct task_struct *cleanup_thread;
++
++/*
++ * Skip this command if result is not 0. Must be called under
++ * udev_cmd_threads.cmd_list_lock and IRQ off.
++ */
++static inline bool ucmd_get_check(struct scst_user_cmd *ucmd)
++{
++ int r = atomic_inc_return(&ucmd->ucmd_ref);
++ int res;
++ if (unlikely(r == 1)) {
++ TRACE_DBG("ucmd %p is being destroyed", ucmd);
++ atomic_dec(&ucmd->ucmd_ref);
++ res = true;
++ /*
++ * Necessary code is serialized by cmd_list_lock in
++ * cmd_remove_hash()
++ */
++ } else {
++ TRACE_DBG("ucmd %p, new ref_cnt %d", ucmd,
++ atomic_read(&ucmd->ucmd_ref));
++ res = false;
++ }
++ return res;
++}
++
++static inline void ucmd_get(struct scst_user_cmd *ucmd)
++{
++ TRACE_DBG("ucmd %p, ucmd_ref %d", ucmd, atomic_read(&ucmd->ucmd_ref));
++ atomic_inc(&ucmd->ucmd_ref);
++ /*
++ * For the same reason as in kref_get(). Let's be safe and
++ * always do it.
++ */
++ smp_mb__after_atomic_inc();
++}
++
++/* Must not be called under cmd_list_lock!! */
++static inline void ucmd_put(struct scst_user_cmd *ucmd)
++{
++ TRACE_DBG("ucmd %p, ucmd_ref %d", ucmd, atomic_read(&ucmd->ucmd_ref));
++
++ EXTRACHECKS_BUG_ON(atomic_read(&ucmd->ucmd_ref) == 0);
++
++ if (atomic_dec_and_test(&ucmd->ucmd_ref))
++ dev_user_free_ucmd(ucmd);
++}
++
++static inline int calc_num_pg(unsigned long buf, int len)
++{
++ len += buf & ~PAGE_MASK;
++ return (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
++}
++
++static void __dev_user_not_reg(void)
++{
++ TRACE_MGMT_DBG("%s", "Device not registered");
++ return;
++}
++
++static inline int dev_user_check_reg(struct scst_user_dev *dev)
++{
++ if (dev == NULL) {
++ __dev_user_not_reg();
++ return -ENODEV;
++ }
++ return 0;
++}
++
++static inline int scst_user_cmd_hashfn(int h)
++{
++ return h & ((1 << DEV_USER_CMD_HASH_ORDER) - 1);
++}
++
++static inline struct scst_user_cmd *__ucmd_find_hash(struct scst_user_dev *dev,
++ unsigned int h)
++{
++ struct list_head *head;
++ struct scst_user_cmd *ucmd;
++
++ head = &dev->ucmd_hash[scst_user_cmd_hashfn(h)];
++ list_for_each_entry(ucmd, head, hash_list_entry) {
++ if (ucmd->h == h) {
++ TRACE_DBG("Found ucmd %p", ucmd);
++ return ucmd;
++ }
++ }
++ return NULL;
++}
++
++static void cmd_insert_hash(struct scst_user_cmd *ucmd)
++{
++ struct list_head *head;
++ struct scst_user_dev *dev = ucmd->dev;
++ struct scst_user_cmd *u;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock, flags);
++ do {
++ ucmd->h = dev->handle_counter++;
++ u = __ucmd_find_hash(dev, ucmd->h);
++ } while (u != NULL);
++ head = &dev->ucmd_hash[scst_user_cmd_hashfn(ucmd->h)];
++ list_add_tail(&ucmd->hash_list_entry, head);
++ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock, flags);
++
++ TRACE_DBG("Inserted ucmd %p, h=%d (dev %s)", ucmd, ucmd->h, dev->name);
++ return;
++}
++
++static inline void cmd_remove_hash(struct scst_user_cmd *ucmd)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&ucmd->dev->udev_cmd_threads.cmd_list_lock, flags);
++ list_del(&ucmd->hash_list_entry);
++ spin_unlock_irqrestore(&ucmd->dev->udev_cmd_threads.cmd_list_lock, flags);
++
++ TRACE_DBG("Removed ucmd %p, h=%d", ucmd, ucmd->h);
++ return;
++}
++
++static void dev_user_free_ucmd(struct scst_user_cmd *ucmd)
++{
++ TRACE_ENTRY();
++
++ TRACE_MEM("Freeing ucmd %p", ucmd);
++
++ cmd_remove_hash(ucmd);
++ EXTRACHECKS_BUG_ON(ucmd->cmd != NULL);
++
++ kmem_cache_free(user_cmd_cachep, ucmd);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct page *dev_user_alloc_pages(struct scatterlist *sg,
++ gfp_t gfp_mask, void *priv)
++{
++ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)priv;
++ int offset = 0;
++
++ TRACE_ENTRY();
++
++ /* *sg supposed to be zeroed */
++
++ TRACE_MEM("ucmd %p, ubuff %lx, ucmd->cur_data_page %d", ucmd,
++ ucmd->ubuff, ucmd->cur_data_page);
++
++ if (ucmd->cur_data_page == 0) {
++ TRACE_MEM("ucmd->first_page_offset %d",
++ ucmd->first_page_offset);
++ offset = ucmd->first_page_offset;
++ ucmd_get(ucmd);
++ }
++
++ if (ucmd->cur_data_page >= ucmd->num_data_pages)
++ goto out;
++
++ sg_set_page(sg, ucmd->data_pages[ucmd->cur_data_page],
++ PAGE_SIZE - offset, offset);
++ ucmd->cur_data_page++;
++
++ TRACE_MEM("page=%p, length=%d, offset=%d", sg_page(sg), sg->length,
++ sg->offset);
++ TRACE_BUFFER("Page data", sg_virt(sg), sg->length);
++
++out:
++ TRACE_EXIT();
++ return sg_page(sg);
++}
++
++static void dev_user_on_cached_mem_free(struct scst_user_cmd *ucmd)
++{
++ TRACE_ENTRY();
++
++ TRACE_MEM("Preparing ON_CACHED_MEM_FREE (ucmd %p, h %d, ubuff %lx)",
++ ucmd, ucmd->h, ucmd->ubuff);
++
++ ucmd->user_cmd_payload_len =
++ offsetof(struct scst_user_get_cmd, on_cached_mem_free) +
++ sizeof(ucmd->user_cmd.on_cached_mem_free);
++ ucmd->user_cmd.cmd_h = ucmd->h;
++ ucmd->user_cmd.subcode = SCST_USER_ON_CACHED_MEM_FREE;
++ ucmd->user_cmd.on_cached_mem_free.pbuf = ucmd->ubuff;
++
++ ucmd->state = UCMD_STATE_ON_CACHE_FREEING;
++
++ dev_user_add_to_ready(ucmd);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void dev_user_unmap_buf(struct scst_user_cmd *ucmd)
++{
++ int i;
++
++ TRACE_ENTRY();
++
++ TRACE_MEM("Unmapping data pages (ucmd %p, ubuff %lx, num %d)", ucmd,
++ ucmd->ubuff, ucmd->num_data_pages);
++
++ for (i = 0; i < ucmd->num_data_pages; i++) {
++ struct page *page = ucmd->data_pages[i];
++
++ if (ucmd->buf_dirty)
++ SetPageDirty(page);
++
++ page_cache_release(page);
++ }
++
++ kfree(ucmd->data_pages);
++ ucmd->data_pages = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++static void __dev_user_free_sg_entries(struct scst_user_cmd *ucmd)
++{
++ TRACE_ENTRY();
++
++ BUG_ON(ucmd->data_pages == NULL);
++
++ TRACE_MEM("Freeing data pages (ucmd=%p, ubuff=%lx, buff_cached=%d)",
++ ucmd, ucmd->ubuff, ucmd->buff_cached);
++
++ dev_user_unmap_buf(ucmd);
++
++ if (ucmd->buff_cached)
++ dev_user_on_cached_mem_free(ucmd);
++ else
++ ucmd_put(ucmd);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void dev_user_free_sg_entries(struct scatterlist *sg, int sg_count,
++ void *priv)
++{
++ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)priv;
++
++ TRACE_MEM("Freeing data pages (sg=%p, sg_count=%d, priv %p)", sg,
++ sg_count, ucmd);
++
++ __dev_user_free_sg_entries(ucmd);
++
++ return;
++}
++
++static inline int is_buff_cached(struct scst_user_cmd *ucmd)
++{
++ int mem_reuse_type = ucmd->dev->memory_reuse_type;
++
++ if ((mem_reuse_type == SCST_USER_MEM_REUSE_ALL) ||
++ ((ucmd->cmd->data_direction == SCST_DATA_READ) &&
++ (mem_reuse_type == SCST_USER_MEM_REUSE_READ)) ||
++ ((ucmd->cmd->data_direction == SCST_DATA_WRITE) &&
++ (mem_reuse_type == SCST_USER_MEM_REUSE_WRITE)))
++ return 1;
++ else
++ return 0;
++}
++
++static inline int is_need_offs_page(unsigned long buf, int len)
++{
++ return ((buf & ~PAGE_MASK) != 0) &&
++ ((buf & PAGE_MASK) != ((buf+len-1) & PAGE_MASK));
++}
++
++/*
++ * Returns 0 for success, <0 for fatal failure, >0 - need pages.
++ * Unmaps the buffer, if needed in case of error
++ */
++static int dev_user_alloc_sg(struct scst_user_cmd *ucmd, int cached_buff)
++{
++ int res = 0;
++ struct scst_cmd *cmd = ucmd->cmd;
++ struct scst_user_dev *dev = ucmd->dev;
++ struct sgv_pool *pool;
++ gfp_t gfp_mask;
++ int flags = 0;
++ int bufflen, orig_bufflen;
++ int last_len = 0;
++ int out_sg_pages = 0;
++
++ TRACE_ENTRY();
++
++ gfp_mask = __GFP_NOWARN;
++ gfp_mask |= (scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
++
++ if (cmd->data_direction != SCST_DATA_BIDI) {
++ orig_bufflen = cmd->bufflen;
++ pool = (struct sgv_pool *)cmd->tgt_dev->dh_priv;
++ } else {
++ /* Make out_sg->offset 0 */
++ int len = cmd->bufflen + ucmd->first_page_offset;
++ out_sg_pages = (len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
++ orig_bufflen = (out_sg_pages << PAGE_SHIFT) + cmd->out_bufflen;
++ pool = dev->pool;
++ }
++ bufflen = orig_bufflen;
++
++ EXTRACHECKS_BUG_ON(bufflen == 0);
++
++ if (cached_buff) {
++ flags |= SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL;
++ if (ucmd->ubuff == 0)
++ flags |= SGV_POOL_NO_ALLOC_ON_CACHE_MISS;
++ } else {
++ TRACE_MEM("%s", "Not cached buff");
++ flags |= SGV_POOL_ALLOC_NO_CACHED;
++ if (ucmd->ubuff == 0) {
++ res = 1;
++ goto out;
++ }
++ bufflen += ucmd->first_page_offset;
++ if (is_need_offs_page(ucmd->ubuff, orig_bufflen))
++ last_len = bufflen & ~PAGE_MASK;
++ else
++ last_len = orig_bufflen & ~PAGE_MASK;
++ }
++ ucmd->buff_cached = cached_buff;
++
++ cmd->sg = sgv_pool_alloc(pool, bufflen, gfp_mask, flags, &cmd->sg_cnt,
++ &ucmd->sgv, &dev->udev_mem_lim, ucmd);
++ if (cmd->sg != NULL) {
++ struct scst_user_cmd *buf_ucmd =
++ (struct scst_user_cmd *)sgv_get_priv(ucmd->sgv);
++
++ TRACE_MEM("Buf ucmd %p (cmd->sg_cnt %d, last seg len %d, "
++ "last_len %d, bufflen %d)", buf_ucmd, cmd->sg_cnt,
++ cmd->sg[cmd->sg_cnt-1].length, last_len, bufflen);
++
++ ucmd->ubuff = buf_ucmd->ubuff;
++ ucmd->buf_ucmd = buf_ucmd;
++
++ EXTRACHECKS_BUG_ON((ucmd->data_pages != NULL) &&
++ (ucmd != buf_ucmd));
++
++ if (last_len != 0) {
++ cmd->sg[cmd->sg_cnt-1].length &= PAGE_MASK;
++ cmd->sg[cmd->sg_cnt-1].length += last_len;
++ }
++
++ TRACE_MEM("Buf alloced (ucmd %p, cached_buff %d, ubuff %lx, "
++ "last seg len %d)", ucmd, cached_buff, ucmd->ubuff,
++ cmd->sg[cmd->sg_cnt-1].length);
++
++ if (cmd->data_direction == SCST_DATA_BIDI) {
++ cmd->out_sg = &cmd->sg[out_sg_pages];
++ cmd->out_sg_cnt = cmd->sg_cnt - out_sg_pages;
++ cmd->sg_cnt = out_sg_pages;
++ TRACE_MEM("cmd %p, out_sg %p, out_sg_cnt %d, sg_cnt %d",
++ cmd, cmd->out_sg, cmd->out_sg_cnt, cmd->sg_cnt);
++ }
++
++ if (unlikely(cmd->sg_cnt > cmd->tgt_dev->max_sg_cnt)) {
++ static int ll;
++ if ((ll < 10) || TRACING_MINOR()) {
++ PRINT_INFO("Unable to complete command due to "
++ "SG IO count limitation (requested %d, "
++ "available %d, tgt lim %d)",
++ cmd->sg_cnt, cmd->tgt_dev->max_sg_cnt,
++ cmd->tgt->sg_tablesize);
++ ll++;
++ }
++ cmd->sg = NULL;
++ /* sgv will be freed in dev_user_free_sgv() */
++ res = -1;
++ }
++ } else {
++ TRACE_MEM("Buf not alloced (ucmd %p, h %d, buff_cached, %d, "
++ "sg_cnt %d, ubuff %lx, sgv %p", ucmd, ucmd->h,
++ ucmd->buff_cached, cmd->sg_cnt, ucmd->ubuff, ucmd->sgv);
++ if (unlikely(cmd->sg_cnt == 0)) {
++ TRACE_MEM("Refused allocation (ucmd %p)", ucmd);
++ BUG_ON(ucmd->sgv != NULL);
++ res = -1;
++ } else {
++ switch (ucmd->state) {
++ case UCMD_STATE_BUF_ALLOCING:
++ res = 1;
++ break;
++ case UCMD_STATE_EXECING:
++ res = -1;
++ break;
++ default:
++ BUG();
++ break;
++ }
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_alloc_space(struct scst_user_cmd *ucmd)
++{
++ int rc, res = SCST_CMD_STATE_DEFAULT;
++ struct scst_cmd *cmd = ucmd->cmd;
++
++ TRACE_ENTRY();
++
++ ucmd->state = UCMD_STATE_BUF_ALLOCING;
++ scst_cmd_set_dh_data_buff_alloced(cmd);
++
++ rc = dev_user_alloc_sg(ucmd, is_buff_cached(ucmd));
++ if (rc == 0)
++ goto out;
++ else if (rc < 0) {
++ scst_set_busy(cmd);
++ res = scst_set_cmd_abnormal_done_state(cmd);
++ goto out;
++ }
++
++ if (!(cmd->data_direction & SCST_DATA_WRITE) &&
++ !scst_is_cmd_local(cmd)) {
++ TRACE_DBG("Delayed alloc, ucmd %p", ucmd);
++ goto out;
++ }
++
++ ucmd->user_cmd_payload_len =
++ offsetof(struct scst_user_get_cmd, alloc_cmd) +
++ sizeof(ucmd->user_cmd.alloc_cmd);
++ ucmd->user_cmd.cmd_h = ucmd->h;
++ ucmd->user_cmd.subcode = SCST_USER_ALLOC_MEM;
++ ucmd->user_cmd.alloc_cmd.sess_h = (unsigned long)cmd->tgt_dev;
++ memcpy(ucmd->user_cmd.alloc_cmd.cdb, cmd->cdb, cmd->cdb_len);
++ ucmd->user_cmd.alloc_cmd.cdb_len = cmd->cdb_len;
++ ucmd->user_cmd.alloc_cmd.ext_cdb_len = cmd->ext_cdb_len;
++ ucmd->user_cmd.alloc_cmd.alloc_len = ucmd->buff_cached ?
++ (cmd->sg_cnt << PAGE_SHIFT) : cmd->bufflen;
++ ucmd->user_cmd.alloc_cmd.queue_type = cmd->queue_type;
++ ucmd->user_cmd.alloc_cmd.data_direction = cmd->data_direction;
++ ucmd->user_cmd.alloc_cmd.sn = cmd->tgt_sn;
++
++ dev_user_add_to_ready(ucmd);
++
++ res = SCST_CMD_STATE_STOP;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct scst_user_cmd *dev_user_alloc_ucmd(struct scst_user_dev *dev,
++ gfp_t gfp_mask)
++{
++ struct scst_user_cmd *ucmd = NULL;
++
++ TRACE_ENTRY();
++
++ ucmd = kmem_cache_zalloc(user_cmd_cachep, gfp_mask);
++ if (unlikely(ucmd == NULL)) {
++ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate "
++ "user cmd (gfp_mask %x)", gfp_mask);
++ goto out;
++ }
++ ucmd->dev = dev;
++ atomic_set(&ucmd->ucmd_ref, 1);
++
++ cmd_insert_hash(ucmd);
++
++ TRACE_MEM("ucmd %p allocated", ucmd);
++
++out:
++ TRACE_EXIT_HRES((unsigned long)ucmd);
++ return ucmd;
++}
++
++static int dev_user_get_block(struct scst_cmd *cmd)
++{
++ struct scst_user_dev *dev = (struct scst_user_dev *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ TRACE_EXIT_RES(dev->block);
++ return dev->block;
++}
++
++static int dev_user_parse(struct scst_cmd *cmd)
++{
++ int rc, res = SCST_CMD_STATE_DEFAULT;
++ struct scst_user_cmd *ucmd;
++ int atomic = scst_cmd_atomic(cmd);
++ struct scst_user_dev *dev = (struct scst_user_dev *)cmd->dev->dh_priv;
++ gfp_t gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
++
++ TRACE_ENTRY();
++
++ if (cmd->dh_priv == NULL) {
++ ucmd = dev_user_alloc_ucmd(dev, gfp_mask);
++ if (unlikely(ucmd == NULL)) {
++ if (atomic) {
++ res = SCST_CMD_STATE_NEED_THREAD_CTX;
++ goto out;
++ } else {
++ scst_set_busy(cmd);
++ goto out_error;
++ }
++ }
++ ucmd->cmd = cmd;
++ cmd->dh_priv = ucmd;
++ } else {
++ ucmd = (struct scst_user_cmd *)cmd->dh_priv;
++ TRACE_DBG("Used ucmd %p, state %x", ucmd, ucmd->state);
++ }
++
++ TRACE_DBG("ucmd %p, cmd %p, state %x", ucmd, cmd, ucmd->state);
++
++ if (ucmd->state == UCMD_STATE_PARSING) {
++ /* We've already done */
++ goto done;
++ }
++
++ EXTRACHECKS_BUG_ON(ucmd->state != UCMD_STATE_NEW);
++
++ switch (dev->parse_type) {
++ case SCST_USER_PARSE_STANDARD:
++ TRACE_DBG("PARSE STANDARD: ucmd %p", ucmd);
++ rc = dev->generic_parse(cmd, dev_user_get_block);
++ if (rc != 0)
++ goto out_invalid;
++ break;
++
++ case SCST_USER_PARSE_EXCEPTION:
++ TRACE_DBG("PARSE EXCEPTION: ucmd %p", ucmd);
++ rc = dev->generic_parse(cmd, dev_user_get_block);
++ if ((rc == 0) && (cmd->op_flags & SCST_INFO_VALID))
++ break;
++ else if (rc == SCST_CMD_STATE_NEED_THREAD_CTX) {
++ TRACE_MEM("Restarting PARSE to thread context "
++ "(ucmd %p)", ucmd);
++ res = SCST_CMD_STATE_NEED_THREAD_CTX;
++ goto out;
++ }
++ /* else go through */
++
++ case SCST_USER_PARSE_CALL:
++ TRACE_DBG("Preparing PARSE for user space (ucmd=%p, h=%d, "
++ "bufflen %d)", ucmd, ucmd->h, cmd->bufflen);
++ ucmd->user_cmd_payload_len =
++ offsetof(struct scst_user_get_cmd, parse_cmd) +
++ sizeof(ucmd->user_cmd.parse_cmd);
++ ucmd->user_cmd.cmd_h = ucmd->h;
++ ucmd->user_cmd.subcode = SCST_USER_PARSE;
++ ucmd->user_cmd.parse_cmd.sess_h = (unsigned long)cmd->tgt_dev;
++ memcpy(ucmd->user_cmd.parse_cmd.cdb, cmd->cdb, cmd->cdb_len);
++ ucmd->user_cmd.parse_cmd.cdb_len = cmd->cdb_len;
++ ucmd->user_cmd.parse_cmd.ext_cdb_len = cmd->ext_cdb_len;
++ ucmd->user_cmd.parse_cmd.timeout = cmd->timeout / HZ;
++ ucmd->user_cmd.parse_cmd.bufflen = cmd->bufflen;
++ ucmd->user_cmd.parse_cmd.out_bufflen = cmd->out_bufflen;
++ ucmd->user_cmd.parse_cmd.queue_type = cmd->queue_type;
++ ucmd->user_cmd.parse_cmd.data_direction = cmd->data_direction;
++ ucmd->user_cmd.parse_cmd.expected_values_set =
++ cmd->expected_values_set;
++ ucmd->user_cmd.parse_cmd.expected_data_direction =
++ cmd->expected_data_direction;
++ ucmd->user_cmd.parse_cmd.expected_transfer_len =
++ cmd->expected_transfer_len;
++ ucmd->user_cmd.parse_cmd.expected_out_transfer_len =
++ cmd->expected_out_transfer_len;
++ ucmd->user_cmd.parse_cmd.sn = cmd->tgt_sn;
++ ucmd->user_cmd.parse_cmd.op_flags = cmd->op_flags;
++ ucmd->state = UCMD_STATE_PARSING;
++ dev_user_add_to_ready(ucmd);
++ res = SCST_CMD_STATE_STOP;
++ goto out;
++
++ default:
++ BUG();
++ goto out;
++ }
++
++done:
++ if (cmd->bufflen == 0) {
++ /*
++ * According to SPC bufflen 0 for data transfer commands isn't
++ * an error, so we need to fix the transfer direction.
++ */
++ cmd->data_direction = SCST_DATA_NONE;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_invalid:
++ PRINT_ERROR("PARSE failed (ucmd %p, rc %d)", ucmd, rc);
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++
++out_error:
++ res = scst_set_cmd_abnormal_done_state(cmd);
++ goto out;
++}
++
++static int dev_user_alloc_data_buf(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)cmd->dh_priv;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON((ucmd->state != UCMD_STATE_NEW) &&
++ (ucmd->state != UCMD_STATE_PARSING) &&
++ (ucmd->state != UCMD_STATE_BUF_ALLOCING));
++
++ res = dev_user_alloc_space(ucmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void dev_user_flush_dcache(struct scst_user_cmd *ucmd)
++{
++ struct scst_user_cmd *buf_ucmd = ucmd->buf_ucmd;
++ unsigned long start = buf_ucmd->ubuff;
++ int i, bufflen = ucmd->cmd->bufflen;
++
++ TRACE_ENTRY();
++
++ if (start == 0)
++ goto out;
++
++ /*
++ * Possibly, flushing of all the pages from ucmd->cmd->sg can be
++ * faster, since it should be cache hot, while ucmd->buf_ucmd and
++ * buf_ucmd->data_pages are cache cold. But, from other side,
++ * sizeof(buf_ucmd->data_pages[0]) is considerably smaller, than
++ * sizeof(ucmd->cmd->sg[0]), so on big buffers going over
++ * data_pages array can lead to less cache misses. So, real numbers are
++ * needed. ToDo.
++ */
++
++ for (i = 0; (bufflen > 0) && (i < buf_ucmd->num_data_pages); i++) {
++ struct page *page;
++ page = buf_ucmd->data_pages[i];
++#ifdef ARCH_HAS_FLUSH_ANON_PAGE
++ struct vm_area_struct *vma = find_vma(current->mm, start);
++ if (vma != NULL)
++ flush_anon_page(vma, page, start);
++#endif
++ flush_dcache_page(page);
++ start += PAGE_SIZE;
++ bufflen -= PAGE_SIZE;
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int dev_user_exec(struct scst_cmd *cmd)
++{
++ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)cmd->dh_priv;
++ int res = SCST_EXEC_COMPLETED;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Preparing EXEC for user space (ucmd=%p, h=%d, "
++ "bufflen %d, data_len %d, ubuff %lx)", ucmd, ucmd->h,
++ cmd->bufflen, cmd->data_len, ucmd->ubuff);
++
++ if (cmd->data_direction & SCST_DATA_WRITE)
++ dev_user_flush_dcache(ucmd);
++
++ BUILD_BUG_ON(sizeof(ucmd->user_cmd.exec_cmd.cdb) != sizeof(cmd->cdb));
++
++ ucmd->user_cmd_payload_len =
++ offsetof(struct scst_user_get_cmd, exec_cmd) +
++ sizeof(ucmd->user_cmd.exec_cmd);
++ ucmd->user_cmd.cmd_h = ucmd->h;
++ ucmd->user_cmd.subcode = SCST_USER_EXEC;
++ ucmd->user_cmd.exec_cmd.sess_h = (unsigned long)cmd->tgt_dev;
++ memcpy(ucmd->user_cmd.exec_cmd.cdb, cmd->cdb, cmd->cdb_len);
++ ucmd->user_cmd.exec_cmd.cdb_len = cmd->cdb_len;
++ ucmd->user_cmd.exec_cmd.ext_cdb_len = cmd->ext_cdb_len;
++ ucmd->user_cmd.exec_cmd.bufflen = cmd->bufflen;
++ ucmd->user_cmd.exec_cmd.data_len = cmd->data_len;
++ ucmd->user_cmd.exec_cmd.pbuf = ucmd->ubuff;
++ if ((ucmd->ubuff == 0) && (cmd->data_direction != SCST_DATA_NONE)) {
++ ucmd->user_cmd.exec_cmd.alloc_len = ucmd->buff_cached ?
++ (cmd->sg_cnt << PAGE_SHIFT) : cmd->bufflen;
++ }
++ ucmd->user_cmd.exec_cmd.queue_type = cmd->queue_type;
++ ucmd->user_cmd.exec_cmd.data_direction = cmd->data_direction;
++ ucmd->user_cmd.exec_cmd.partial = 0;
++ ucmd->user_cmd.exec_cmd.timeout = cmd->timeout / HZ;
++ ucmd->user_cmd.exec_cmd.p_out_buf = ucmd->ubuff +
++ (cmd->sg_cnt << PAGE_SHIFT);
++ ucmd->user_cmd.exec_cmd.out_bufflen = cmd->out_bufflen;
++ ucmd->user_cmd.exec_cmd.sn = cmd->tgt_sn;
++
++ ucmd->state = UCMD_STATE_EXECING;
++
++ dev_user_add_to_ready(ucmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void dev_user_free_sgv(struct scst_user_cmd *ucmd)
++{
++ if (ucmd->sgv != NULL) {
++ sgv_pool_free(ucmd->sgv, &ucmd->dev->udev_mem_lim);
++ ucmd->sgv = NULL;
++ } else if (ucmd->data_pages != NULL) {
++ /* We mapped pages, but for some reason didn't allocate them */
++ ucmd_get(ucmd);
++ __dev_user_free_sg_entries(ucmd);
++ }
++ return;
++}
++
++static void dev_user_on_free_cmd(struct scst_cmd *cmd)
++{
++ struct scst_user_cmd *ucmd = (struct scst_user_cmd *)cmd->dh_priv;
++
++ TRACE_ENTRY();
++
++ if (unlikely(ucmd == NULL))
++ goto out;
++
++ TRACE_MEM("ucmd %p, cmd %p, buff_cached %d, ubuff %lx", ucmd, ucmd->cmd,
++ ucmd->buff_cached, ucmd->ubuff);
++
++ ucmd->cmd = NULL;
++ if ((cmd->data_direction & SCST_DATA_WRITE) && ucmd->buf_ucmd != NULL)
++ ucmd->buf_ucmd->buf_dirty = 1;
++
++ if (ucmd->dev->on_free_cmd_type == SCST_USER_ON_FREE_CMD_IGNORE) {
++ ucmd->state = UCMD_STATE_ON_FREE_SKIPPED;
++ /* The state assignment must be before freeing sgv! */
++ goto out_reply;
++ }
++
++ if (unlikely(!ucmd->seen_by_user)) {
++ TRACE_MGMT_DBG("Not seen by user ucmd %p", ucmd);
++ goto out_reply;
++ }
++
++ ucmd->user_cmd_payload_len =
++ offsetof(struct scst_user_get_cmd, on_free_cmd) +
++ sizeof(ucmd->user_cmd.on_free_cmd);
++ ucmd->user_cmd.cmd_h = ucmd->h;
++ ucmd->user_cmd.subcode = SCST_USER_ON_FREE_CMD;
++ ucmd->user_cmd.on_free_cmd.pbuf = ucmd->ubuff;
++ ucmd->user_cmd.on_free_cmd.resp_data_len = cmd->resp_data_len;
++ ucmd->user_cmd.on_free_cmd.buffer_cached = ucmd->buff_cached;
++ ucmd->user_cmd.on_free_cmd.aborted = ucmd->aborted;
++ ucmd->user_cmd.on_free_cmd.status = cmd->status;
++ ucmd->user_cmd.on_free_cmd.delivery_status = cmd->delivery_status;
++
++ ucmd->state = UCMD_STATE_ON_FREEING;
++
++ dev_user_add_to_ready(ucmd);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_reply:
++ dev_user_process_reply_on_free(ucmd);
++ goto out;
++}
++
++static void dev_user_set_block(struct scst_cmd *cmd, int block)
++{
++ struct scst_user_dev *dev = (struct scst_user_dev *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ TRACE_DBG("dev %p, new block %d", dev, block);
++ if (block != 0)
++ dev->block = block;
++ else
++ dev->block = dev->def_block;
++ return;
++}
++
++static int dev_user_disk_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ res = scst_block_generic_dev_done(cmd, dev_user_set_block);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_tape_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ res = scst_tape_generic_dev_done(cmd, dev_user_set_block);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void dev_user_add_to_ready(struct scst_user_cmd *ucmd)
++{
++ struct scst_user_dev *dev = ucmd->dev;
++ unsigned long flags;
++ int do_wake = in_interrupt();
++
++ TRACE_ENTRY();
++
++ if (ucmd->cmd)
++ do_wake |= ucmd->cmd->preprocessing_only;
++
++ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock, flags);
++
++ ucmd->this_state_unjammed = 0;
++
++ if ((ucmd->state == UCMD_STATE_PARSING) ||
++ (ucmd->state == UCMD_STATE_BUF_ALLOCING)) {
++ /*
++ * If we don't put such commands in the queue head, then under
++ * high load we might delay threads, waiting for memory
++ * allocations, for too long and start loosing NOPs, which
++ * would lead to consider us by remote initiators as
++ * unresponsive and stuck => broken connections, etc. If none
++ * of our commands completed in NOP timeout to allow the head
++ * commands to go, then we are really overloaded and/or stuck.
++ */
++ TRACE_DBG("Adding ucmd %p (state %d) to head of ready "
++ "cmd list", ucmd, ucmd->state);
++ list_add(&ucmd->ready_cmd_list_entry,
++ &dev->ready_cmd_list);
++ } else if (unlikely(ucmd->state == UCMD_STATE_TM_EXECING) ||
++ unlikely(ucmd->state == UCMD_STATE_ATTACH_SESS) ||
++ unlikely(ucmd->state == UCMD_STATE_DETACH_SESS)) {
++ TRACE_MGMT_DBG("Adding mgmt ucmd %p (state %d) to head of "
++ "ready cmd list", ucmd, ucmd->state);
++ list_add(&ucmd->ready_cmd_list_entry,
++ &dev->ready_cmd_list);
++ do_wake = 1;
++ } else {
++ if ((ucmd->cmd != NULL) &&
++ unlikely((ucmd->cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))) {
++ TRACE_DBG("Adding HQ ucmd %p to head of ready cmd list",
++ ucmd);
++ list_add(&ucmd->ready_cmd_list_entry,
++ &dev->ready_cmd_list);
++ } else {
++ TRACE_DBG("Adding ucmd %p to ready cmd list", ucmd);
++ list_add_tail(&ucmd->ready_cmd_list_entry,
++ &dev->ready_cmd_list);
++ }
++ do_wake |= ((ucmd->state == UCMD_STATE_ON_CACHE_FREEING) ||
++ (ucmd->state == UCMD_STATE_ON_FREEING));
++ }
++
++ if (do_wake) {
++ TRACE_DBG("Waking up dev %p", dev);
++ wake_up(&dev->udev_cmd_threads.cmd_list_waitQ);
++ }
++
++ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock, flags);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int dev_user_map_buf(struct scst_user_cmd *ucmd, unsigned long ubuff,
++ int num_pg)
++{
++ int res = 0, rc;
++ int i;
++ struct task_struct *tsk = current;
++
++ TRACE_ENTRY();
++
++ if (unlikely(ubuff == 0))
++ goto out_nomem;
++
++ BUG_ON(ucmd->data_pages != NULL);
++
++ ucmd->num_data_pages = num_pg;
++
++ ucmd->data_pages =
++ kmalloc(sizeof(*ucmd->data_pages) * ucmd->num_data_pages,
++ GFP_KERNEL);
++ if (ucmd->data_pages == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "Unable to allocate data_pages array "
++ "(num_data_pages=%d)", ucmd->num_data_pages);
++ res = -ENOMEM;
++ goto out_nomem;
++ }
++
++ TRACE_MEM("Mapping buffer (ucmd %p, ubuff %lx, ucmd->num_data_pages %d,"
++ " first_page_offset %d, len %d)", ucmd, ubuff,
++ ucmd->num_data_pages, (int)(ubuff & ~PAGE_MASK),
++ (ucmd->cmd != NULL) ? ucmd->cmd->bufflen : -1);
++
++ down_read(&tsk->mm->mmap_sem);
++ rc = get_user_pages(tsk, tsk->mm, ubuff, ucmd->num_data_pages,
++ 1/*writable*/, 0/*don't force*/, ucmd->data_pages, NULL);
++ up_read(&tsk->mm->mmap_sem);
++
++ /* get_user_pages() flushes dcache */
++
++ if (rc < ucmd->num_data_pages)
++ goto out_unmap;
++
++ ucmd->ubuff = ubuff;
++ ucmd->first_page_offset = (ubuff & ~PAGE_MASK);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_nomem:
++ if (ucmd->cmd != NULL)
++ scst_set_busy(ucmd->cmd);
++ /* go through */
++
++out_err:
++ if (ucmd->cmd != NULL)
++ scst_set_cmd_abnormal_done_state(ucmd->cmd);
++ goto out;
++
++out_unmap:
++ PRINT_ERROR("Failed to get %d user pages (rc %d)",
++ ucmd->num_data_pages, rc);
++ if (rc > 0) {
++ for (i = 0; i < rc; i++)
++ page_cache_release(ucmd->data_pages[i]);
++ }
++ kfree(ucmd->data_pages);
++ ucmd->data_pages = NULL;
++ res = -EFAULT;
++ if (ucmd->cmd != NULL)
++ scst_set_cmd_error(ucmd->cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_err;
++}
++
++static int dev_user_process_reply_alloc(struct scst_user_cmd *ucmd,
++ struct scst_user_reply_cmd *reply)
++{
++ int res = 0;
++ struct scst_cmd *cmd = ucmd->cmd;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("ucmd %p, pbuf %llx", ucmd, reply->alloc_reply.pbuf);
++
++ if (likely(reply->alloc_reply.pbuf != 0)) {
++ int pages;
++ if (ucmd->buff_cached) {
++ if (unlikely((reply->alloc_reply.pbuf & ~PAGE_MASK) != 0)) {
++ PRINT_ERROR("Supplied pbuf %llx isn't "
++ "page aligned",
++ reply->alloc_reply.pbuf);
++ goto out_hwerr;
++ }
++ pages = cmd->sg_cnt;
++ } else
++ pages = calc_num_pg(reply->alloc_reply.pbuf,
++ cmd->bufflen);
++ res = dev_user_map_buf(ucmd, reply->alloc_reply.pbuf, pages);
++ } else {
++ scst_set_busy(ucmd->cmd);
++ scst_set_cmd_abnormal_done_state(ucmd->cmd);
++ }
++
++out_process:
++ scst_post_alloc_data_buf(cmd);
++ scst_process_active_cmd(cmd, false);
++
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_hwerr:
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++ scst_set_cmd_abnormal_done_state(ucmd->cmd);
++ res = -EINVAL;
++ goto out_process;
++}
++
++static int dev_user_process_reply_parse(struct scst_user_cmd *ucmd,
++ struct scst_user_reply_cmd *reply)
++{
++ int res = 0, rc;
++ struct scst_user_scsi_cmd_reply_parse *preply =
++ &reply->parse_reply;
++ struct scst_cmd *cmd = ucmd->cmd;
++
++ TRACE_ENTRY();
++
++ if (preply->status != 0)
++ goto out_status;
++
++ if (unlikely(preply->queue_type > SCST_CMD_QUEUE_ACA))
++ goto out_inval;
++
++ if (unlikely((preply->data_direction != SCST_DATA_WRITE) &&
++ (preply->data_direction != SCST_DATA_READ) &&
++ (preply->data_direction != SCST_DATA_BIDI) &&
++ (preply->data_direction != SCST_DATA_NONE)))
++ goto out_inval;
++
++ if (unlikely((preply->data_direction != SCST_DATA_NONE) &&
++ (preply->bufflen == 0)))
++ goto out_inval;
++
++ if (unlikely((preply->bufflen < 0) || (preply->data_len < 0)))
++ goto out_inval;
++
++ if (unlikely(preply->cdb_len > SCST_MAX_CDB_SIZE))
++ goto out_inval;
++
++ TRACE_DBG("ucmd %p, queue_type %x, data_direction, %x, bufflen %d, "
++ "data_len %d, pbuf %llx, cdb_len %d, op_flags %x", ucmd,
++ preply->queue_type, preply->data_direction, preply->bufflen,
++ preply->data_len, reply->alloc_reply.pbuf, preply->cdb_len,
++ preply->op_flags);
++
++ cmd->queue_type = preply->queue_type;
++ cmd->data_direction = preply->data_direction;
++ cmd->bufflen = preply->bufflen;
++ cmd->data_len = preply->data_len;
++ if (preply->cdb_len > 0)
++ cmd->cdb_len = preply->cdb_len;
++ if (preply->op_flags & SCST_INFO_VALID)
++ cmd->op_flags = preply->op_flags;
++
++out_process:
++ scst_post_parse(cmd);
++ scst_process_active_cmd(cmd, false);
++
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_inval:
++ PRINT_ERROR("Invalid parse_reply parameters (LUN %lld, op %x, cmd %p)",
++ (long long unsigned int)cmd->lun, cmd->cdb[0], cmd);
++ PRINT_BUFFER("Invalid parse_reply", reply, sizeof(*reply));
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++ res = -EINVAL;
++ goto out_abnormal;
++
++out_hwerr_res_set:
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
++
++out_abnormal:
++ scst_set_cmd_abnormal_done_state(cmd);
++ goto out_process;
++
++out_status:
++ TRACE_DBG("ucmd %p returned with error from user status %x",
++ ucmd, preply->status);
++
++ if (preply->sense_len != 0) {
++ int sense_len;
++
++ res = scst_alloc_sense(cmd, 0);
++ if (res != 0)
++ goto out_hwerr_res_set;
++
++ sense_len = min_t(int, cmd->sense_buflen, preply->sense_len);
++
++ rc = copy_from_user(cmd->sense,
++ (void __user *)(unsigned long)preply->psense_buffer,
++ sense_len);
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d sense's bytes", rc);
++ res = -EFAULT;
++ goto out_hwerr_res_set;
++ }
++ cmd->sense_valid_len = sense_len;
++ }
++ scst_set_cmd_error_status(cmd, preply->status);
++ goto out_abnormal;
++}
++
++static int dev_user_process_reply_on_free(struct scst_user_cmd *ucmd)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("ON FREE ucmd %p", ucmd);
++
++ dev_user_free_sgv(ucmd);
++ ucmd_put(ucmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_process_reply_on_cache_free(struct scst_user_cmd *ucmd)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("ON CACHE FREE ucmd %p", ucmd);
++
++ ucmd_put(ucmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_process_reply_exec(struct scst_user_cmd *ucmd,
++ struct scst_user_reply_cmd *reply)
++{
++ int res = 0;
++ struct scst_user_scsi_cmd_reply_exec *ereply =
++ &reply->exec_reply;
++ struct scst_cmd *cmd = ucmd->cmd;
++
++ TRACE_ENTRY();
++
++ if (ereply->reply_type == SCST_EXEC_REPLY_COMPLETED) {
++ if (ucmd->background_exec) {
++ TRACE_DBG("Background ucmd %p finished", ucmd);
++ ucmd_put(ucmd);
++ goto out;
++ }
++ if (unlikely(ereply->resp_data_len > cmd->bufflen))
++ goto out_inval;
++ if (unlikely((cmd->data_direction != SCST_DATA_READ) &&
++ (ereply->resp_data_len != 0)))
++ goto out_inval;
++ } else if (ereply->reply_type == SCST_EXEC_REPLY_BACKGROUND) {
++ if (unlikely(ucmd->background_exec))
++ goto out_inval;
++ if (unlikely((cmd->data_direction & SCST_DATA_READ) ||
++ (cmd->resp_data_len != 0)))
++ goto out_inval;
++ /*
++ * background_exec assignment must be after ucmd get.
++ * Otherwise, due to reorder, in dev_user_process_reply()
++ * it is possible that ucmd is destroyed before it "got" here.
++ */
++ ucmd_get(ucmd);
++ ucmd->background_exec = 1;
++ TRACE_DBG("Background ucmd %p", ucmd);
++ goto out_compl;
++ } else
++ goto out_inval;
++
++ TRACE_DBG("ucmd %p, status %d, resp_data_len %d", ucmd,
++ ereply->status, ereply->resp_data_len);
++
++ cmd->atomic = 0;
++
++ if (ereply->resp_data_len != 0) {
++ if (ucmd->ubuff == 0) {
++ int pages, rc;
++ if (unlikely(ereply->pbuf == 0))
++ goto out_busy;
++ if (ucmd->buff_cached) {
++ if (unlikely((ereply->pbuf & ~PAGE_MASK) != 0)) {
++ PRINT_ERROR("Supplied pbuf %llx isn't "
++ "page aligned", ereply->pbuf);
++ goto out_hwerr;
++ }
++ pages = cmd->sg_cnt;
++ } else
++ pages = calc_num_pg(ereply->pbuf, cmd->bufflen);
++ rc = dev_user_map_buf(ucmd, ereply->pbuf, pages);
++ if ((rc != 0) || (ucmd->ubuff == 0))
++ goto out_compl;
++
++ rc = dev_user_alloc_sg(ucmd, ucmd->buff_cached);
++ if (unlikely(rc != 0))
++ goto out_busy;
++ } else
++ dev_user_flush_dcache(ucmd);
++ cmd->may_need_dma_sync = 1;
++ scst_set_resp_data_len(cmd, ereply->resp_data_len);
++ } else if (cmd->resp_data_len != ereply->resp_data_len) {
++ if (ucmd->ubuff == 0) {
++ /*
++ * We have an empty SG, so can't call
++ * scst_set_resp_data_len()
++ */
++ cmd->resp_data_len = ereply->resp_data_len;
++ cmd->resid_possible = 1;
++ } else
++ scst_set_resp_data_len(cmd, ereply->resp_data_len);
++ }
++
++ cmd->status = ereply->status;
++ if (ereply->sense_len != 0) {
++ int sense_len, rc;
++
++ res = scst_alloc_sense(cmd, 0);
++ if (res != 0)
++ goto out_compl;
++
++ sense_len = min((int)cmd->sense_buflen, (int)ereply->sense_len);
++
++ rc = copy_from_user(cmd->sense,
++ (void __user *)(unsigned long)ereply->psense_buffer,
++ sense_len);
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d sense's bytes", rc);
++ res = -EFAULT;
++ goto out_hwerr_res_set;
++ }
++ cmd->sense_valid_len = sense_len;
++ }
++
++out_compl:
++ cmd->completed = 1;
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_DIRECT);
++ /* !! At this point cmd can be already freed !! */
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_inval:
++ PRINT_ERROR("Invalid exec_reply parameters (LUN %lld, op %x, cmd %p)",
++ (long long unsigned int)cmd->lun, cmd->cdb[0], cmd);
++ PRINT_BUFFER("Invalid exec_reply", reply, sizeof(*reply));
++
++out_hwerr:
++ res = -EINVAL;
++
++out_hwerr_res_set:
++ if (ucmd->background_exec) {
++ ucmd_put(ucmd);
++ goto out;
++ } else {
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_compl;
++ }
++
++out_busy:
++ scst_set_busy(cmd);
++ goto out_compl;
++}
++
++static int dev_user_process_reply(struct scst_user_dev *dev,
++ struct scst_user_reply_cmd *reply)
++{
++ int res = 0;
++ struct scst_user_cmd *ucmd;
++ int state;
++
++ TRACE_ENTRY();
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ ucmd = __ucmd_find_hash(dev, reply->cmd_h);
++ if (unlikely(ucmd == NULL)) {
++ TRACE_MGMT_DBG("cmd_h %d not found", reply->cmd_h);
++ res = -ESRCH;
++ goto out_unlock;
++ }
++
++ if (unlikely(ucmd_get_check(ucmd))) {
++ TRACE_MGMT_DBG("Found being destroyed cmd_h %d", reply->cmd_h);
++ res = -ESRCH;
++ goto out_unlock;
++ }
++
++ /* To sync. with dev_user_process_reply_exec(). See comment there. */
++ smp_mb();
++ if (ucmd->background_exec) {
++ state = UCMD_STATE_EXECING;
++ goto unlock_process;
++ }
++
++ if (unlikely(ucmd->this_state_unjammed)) {
++ TRACE_MGMT_DBG("Reply on unjammed ucmd %p, ignoring",
++ ucmd);
++ goto out_unlock_put;
++ }
++
++ if (unlikely(!ucmd->sent_to_user)) {
++ TRACE_MGMT_DBG("Ucmd %p isn't in the sent to user "
++ "state %x", ucmd, ucmd->state);
++ res = -EINVAL;
++ goto out_unlock_put;
++ }
++
++ if (unlikely(reply->subcode != ucmd->user_cmd.subcode))
++ goto out_wrong_state;
++
++ if (unlikely(_IOC_NR(reply->subcode) != ucmd->state))
++ goto out_wrong_state;
++
++ state = ucmd->state;
++ ucmd->sent_to_user = 0;
++
++unlock_process:
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ switch (state) {
++ case UCMD_STATE_PARSING:
++ res = dev_user_process_reply_parse(ucmd, reply);
++ break;
++
++ case UCMD_STATE_BUF_ALLOCING:
++ res = dev_user_process_reply_alloc(ucmd, reply);
++ break;
++
++ case UCMD_STATE_EXECING:
++ res = dev_user_process_reply_exec(ucmd, reply);
++ break;
++
++ case UCMD_STATE_ON_FREEING:
++ res = dev_user_process_reply_on_free(ucmd);
++ break;
++
++ case UCMD_STATE_ON_CACHE_FREEING:
++ res = dev_user_process_reply_on_cache_free(ucmd);
++ break;
++
++ case UCMD_STATE_TM_EXECING:
++ res = dev_user_process_reply_tm_exec(ucmd, reply->result);
++ break;
++
++ case UCMD_STATE_ATTACH_SESS:
++ case UCMD_STATE_DETACH_SESS:
++ res = dev_user_process_reply_sess(ucmd, reply->result);
++ break;
++
++ default:
++ BUG();
++ break;
++ }
++
++out_put:
++ ucmd_put(ucmd);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_wrong_state:
++ PRINT_ERROR("Command's %p subcode %x doesn't match internal "
++ "command's state %x or reply->subcode (%x) != ucmd->subcode "
++ "(%x)", ucmd, _IOC_NR(reply->subcode), ucmd->state,
++ reply->subcode, ucmd->user_cmd.subcode);
++ res = -EINVAL;
++ dev_user_unjam_cmd(ucmd, 0, NULL);
++
++out_unlock_put:
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ goto out_put;
++
++out_unlock:
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ goto out;
++}
++
++static int dev_user_reply_cmd(struct file *file, void __user *arg)
++{
++ int res = 0, rc;
++ struct scst_user_dev *dev;
++ struct scst_user_reply_cmd reply;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (unlikely(res != 0)) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ rc = copy_from_user(&reply, arg, sizeof(reply));
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ res = -EFAULT;
++ goto out_up;
++ }
++
++ TRACE_DBG("Reply for dev %s", dev->name);
++
++ TRACE_BUFFER("Reply", &reply, sizeof(reply));
++
++ res = dev_user_process_reply(dev, &reply);
++ if (unlikely(res < 0))
++ goto out_up;
++
++out_up:
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_get_ext_cdb(struct file *file, void __user *arg)
++{
++ int res = 0, rc;
++ struct scst_user_dev *dev;
++ struct scst_user_cmd *ucmd;
++ struct scst_cmd *cmd = NULL;
++ struct scst_user_get_ext_cdb get;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (unlikely(res != 0)) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ rc = copy_from_user(&get, arg, sizeof(get));
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ res = -EFAULT;
++ goto out_up;
++ }
++
++ TRACE_MGMT_DBG("Get ext cdb for dev %s", dev->name);
++
++ TRACE_BUFFER("Get ext cdb", &get, sizeof(get));
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ ucmd = __ucmd_find_hash(dev, get.cmd_h);
++ if (unlikely(ucmd == NULL)) {
++ TRACE_MGMT_DBG("cmd_h %d not found", get.cmd_h);
++ res = -ESRCH;
++ goto out_unlock;
++ }
++
++ if (unlikely(ucmd_get_check(ucmd))) {
++ TRACE_MGMT_DBG("Found being destroyed cmd_h %d", get.cmd_h);
++ res = -ESRCH;
++ goto out_unlock;
++ }
++
++ if ((ucmd->cmd != NULL) && (ucmd->state <= UCMD_STATE_EXECING) &&
++ (ucmd->sent_to_user || ucmd->background_exec)) {
++ cmd = ucmd->cmd;
++ scst_cmd_get(cmd);
++ } else {
++ TRACE_MGMT_DBG("Invalid ucmd state %d for cmd_h %d",
++ ucmd->state, get.cmd_h);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ if (cmd == NULL)
++ goto out_put;
++
++ if (cmd->ext_cdb == NULL)
++ goto out_cmd_put;
++
++ TRACE_BUFFER("EXT CDB", cmd->ext_cdb, cmd->ext_cdb_len);
++ rc = copy_to_user((void __user *)(unsigned long)get.ext_cdb_buffer,
++ cmd->ext_cdb, cmd->ext_cdb_len);
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Failed to copy to user %d bytes", rc);
++ res = -EFAULT;
++ goto out_cmd_put;
++ }
++
++out_cmd_put:
++ scst_cmd_put(cmd);
++
++out_put:
++ ucmd_put(ucmd);
++
++out_up:
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unlock:
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ goto out_up;
++}
++
++static int dev_user_process_scst_commands(struct scst_user_dev *dev)
++ __releases(&dev->udev_cmd_threads.cmd_list_lock)
++ __acquires(&dev->udev_cmd_threads.cmd_list_lock)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ while (!list_empty(&dev->udev_cmd_threads.active_cmd_list)) {
++ struct scst_cmd *cmd = list_entry(
++ dev->udev_cmd_threads.active_cmd_list.next, typeof(*cmd),
++ cmd_list_entry);
++ TRACE_DBG("Deleting cmd %p from active cmd list", cmd);
++ list_del(&cmd->cmd_list_entry);
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ scst_process_active_cmd(cmd, false);
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ res++;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Called under udev_cmd_threads.cmd_list_lock and IRQ off */
++static struct scst_user_cmd *__dev_user_get_next_cmd(struct list_head *cmd_list)
++ __releases(&dev->udev_cmd_threads.cmd_list_lock)
++ __acquires(&dev->udev_cmd_threads.cmd_list_lock)
++{
++ struct scst_user_cmd *u;
++
++again:
++ u = NULL;
++ if (!list_empty(cmd_list)) {
++ u = list_entry(cmd_list->next, typeof(*u),
++ ready_cmd_list_entry);
++
++ TRACE_DBG("Found ready ucmd %p", u);
++ list_del(&u->ready_cmd_list_entry);
++
++ EXTRACHECKS_BUG_ON(u->this_state_unjammed);
++
++ if (u->cmd != NULL) {
++ if (u->state == UCMD_STATE_EXECING) {
++ struct scst_user_dev *dev = u->dev;
++ int rc;
++
++ EXTRACHECKS_BUG_ON(u->jammed);
++
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ rc = scst_check_local_events(u->cmd);
++ if (unlikely(rc != 0)) {
++ u->cmd->scst_cmd_done(u->cmd,
++ SCST_CMD_STATE_DEFAULT,
++ SCST_CONTEXT_DIRECT);
++ /*
++ * !! At this point cmd & u can be !!
++ * !! already freed !!
++ */
++ spin_lock_irq(
++ &dev->udev_cmd_threads.cmd_list_lock);
++ goto again;
++ }
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ } else if (unlikely(test_bit(SCST_CMD_ABORTED,
++ &u->cmd->cmd_flags))) {
++ switch (u->state) {
++ case UCMD_STATE_PARSING:
++ case UCMD_STATE_BUF_ALLOCING:
++ TRACE_MGMT_DBG("Aborting ucmd %p", u);
++ dev_user_unjam_cmd(u, 0, NULL);
++ goto again;
++ case UCMD_STATE_EXECING:
++ EXTRACHECKS_BUG_ON(1);
++ }
++ }
++ }
++ u->sent_to_user = 1;
++ u->seen_by_user = 1;
++ }
++ return u;
++}
++
++static inline int test_cmd_threads(struct scst_user_dev *dev)
++{
++ int res = !list_empty(&dev->udev_cmd_threads.active_cmd_list) ||
++ !list_empty(&dev->ready_cmd_list) ||
++ !dev->blocking || dev->cleanup_done ||
++ signal_pending(current);
++ return res;
++}
++
++/* Called under udev_cmd_threads.cmd_list_lock and IRQ off */
++static int dev_user_get_next_cmd(struct scst_user_dev *dev,
++ struct scst_user_cmd **ucmd)
++{
++ int res = 0;
++ wait_queue_t wait;
++
++ TRACE_ENTRY();
++
++ init_waitqueue_entry(&wait, current);
++
++ while (1) {
++ if (!test_cmd_threads(dev)) {
++ add_wait_queue_exclusive_head(
++ &dev->udev_cmd_threads.cmd_list_waitQ,
++ &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_cmd_threads(dev))
++ break;
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ schedule();
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&dev->udev_cmd_threads.cmd_list_waitQ,
++ &wait);
++ }
++
++ dev_user_process_scst_commands(dev);
++
++ *ucmd = __dev_user_get_next_cmd(&dev->ready_cmd_list);
++ if (*ucmd != NULL)
++ break;
++
++ if (!dev->blocking || dev->cleanup_done) {
++ res = -EAGAIN;
++ TRACE_DBG("No ready commands, returning %d", res);
++ break;
++ }
++
++ if (signal_pending(current)) {
++ res = -EINTR;
++ TRACE_DBG("Signal pending, returning %d", res);
++ break;
++ }
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_reply_get_cmd(struct file *file, void __user *arg)
++{
++ int res = 0, rc;
++ struct scst_user_dev *dev;
++ struct scst_user_get_cmd *cmd;
++ struct scst_user_reply_cmd *reply;
++ struct scst_user_cmd *ucmd;
++ uint64_t ureply;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (unlikely(res != 0)) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ /* get_user() can't be used with 64-bit values on x86_32 */
++ rc = copy_from_user(&ureply, (uint64_t __user *)
++ &((struct scst_user_get_cmd __user *)arg)->preply,
++ sizeof(ureply));
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ res = -EFAULT;
++ goto out_up;
++ }
++
++ TRACE_DBG("ureply %lld (dev %s)", (long long unsigned int)ureply,
++ dev->name);
++
++ cmd = kmem_cache_alloc(user_get_cmd_cachep, GFP_KERNEL);
++ if (unlikely(cmd == NULL)) {
++ res = -ENOMEM;
++ goto out_up;
++ }
++
++ if (ureply != 0) {
++ unsigned long u = (unsigned long)ureply;
++ reply = (struct scst_user_reply_cmd *)cmd;
++ rc = copy_from_user(reply, (void __user *)u, sizeof(*reply));
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ res = -EFAULT;
++ goto out_free;
++ }
++
++ TRACE_BUFFER("Reply", reply, sizeof(*reply));
++
++ res = dev_user_process_reply(dev, reply);
++ if (unlikely(res < 0))
++ goto out_free;
++ }
++
++ kmem_cache_free(user_get_cmd_cachep, cmd);
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++again:
++ res = dev_user_get_next_cmd(dev, &ucmd);
++ if (res == 0) {
++ int len;
++ /*
++ * A misbehaving user space handler can make ucmd to get dead
++ * immediately after we released the lock, which can lead to
++ * copy of dead data to the user space, which can lead to a
++ * leak of sensitive information.
++ */
++ if (unlikely(ucmd_get_check(ucmd))) {
++ /* Oops, this ucmd is already being destroyed. Retry. */
++ goto again;
++ }
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ EXTRACHECKS_BUG_ON(ucmd->user_cmd_payload_len == 0);
++
++ len = ucmd->user_cmd_payload_len;
++ TRACE_DBG("ucmd %p (user_cmd %p), payload_len %d (len %d)",
++ ucmd, &ucmd->user_cmd, ucmd->user_cmd_payload_len, len);
++ TRACE_BUFFER("UCMD", &ucmd->user_cmd, len);
++ rc = copy_to_user(arg, &ucmd->user_cmd, len);
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Copy to user failed (%d), requeuing ucmd "
++ "%p back to head of ready cmd list", rc, ucmd);
++ res = -EFAULT;
++ /* Requeue ucmd back */
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ list_add(&ucmd->ready_cmd_list_entry,
++ &dev->ready_cmd_list);
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ }
++#ifdef CONFIG_SCST_EXTRACHECKS
++ else
++ ucmd->user_cmd_payload_len = 0;
++#endif
++ ucmd_put(ucmd);
++ } else
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++out_up:
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kmem_cache_free(user_get_cmd_cachep, cmd);
++ goto out_up;
++}
++
++static long dev_user_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ long res, rc;
++
++ TRACE_ENTRY();
++
++ switch (cmd) {
++ case SCST_USER_REPLY_AND_GET_CMD:
++ TRACE_DBG("%s", "REPLY_AND_GET_CMD");
++ res = dev_user_reply_get_cmd(file, (void __user *)arg);
++ break;
++
++ case SCST_USER_REPLY_CMD:
++ TRACE_DBG("%s", "REPLY_CMD");
++ res = dev_user_reply_cmd(file, (void __user *)arg);
++ break;
++
++ case SCST_USER_GET_EXTENDED_CDB:
++ TRACE_DBG("%s", "GET_EXTENDED_CDB");
++ res = dev_user_get_ext_cdb(file, (void __user *)arg);
++ break;
++
++ case SCST_USER_REGISTER_DEVICE:
++ {
++ struct scst_user_dev_desc *dev_desc;
++ TRACE_DBG("%s", "REGISTER_DEVICE");
++ dev_desc = kmalloc(sizeof(*dev_desc), GFP_KERNEL);
++ if (dev_desc == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++ rc = copy_from_user(dev_desc, (void __user *)arg,
++ sizeof(*dev_desc));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %ld user's bytes", rc);
++ res = -EFAULT;
++ kfree(dev_desc);
++ goto out;
++ }
++ TRACE_BUFFER("dev_desc", dev_desc, sizeof(*dev_desc));
++ dev_desc->name[sizeof(dev_desc->name)-1] = '\0';
++ dev_desc->sgv_name[sizeof(dev_desc->sgv_name)-1] = '\0';
++ res = dev_user_register_dev(file, dev_desc);
++ kfree(dev_desc);
++ break;
++ }
++
++ case SCST_USER_UNREGISTER_DEVICE:
++ TRACE_DBG("%s", "UNREGISTER_DEVICE");
++ res = dev_user_unregister_dev(file);
++ break;
++
++ case SCST_USER_FLUSH_CACHE:
++ TRACE_DBG("%s", "FLUSH_CACHE");
++ res = dev_user_flush_cache(file);
++ break;
++
++ case SCST_USER_SET_OPTIONS:
++ {
++ struct scst_user_opt opt;
++ TRACE_DBG("%s", "SET_OPTIONS");
++ rc = copy_from_user(&opt, (void __user *)arg, sizeof(opt));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %ld user's bytes", rc);
++ res = -EFAULT;
++ goto out;
++ }
++ TRACE_BUFFER("opt", &opt, sizeof(opt));
++ res = dev_user_set_opt(file, &opt);
++ break;
++ }
++
++ case SCST_USER_GET_OPTIONS:
++ TRACE_DBG("%s", "GET_OPTIONS");
++ res = dev_user_get_opt(file, (void __user *)arg);
++ break;
++
++ case SCST_USER_DEVICE_CAPACITY_CHANGED:
++ TRACE_DBG("%s", "CAPACITY_CHANGED");
++ res = dev_user_capacity_changed(file);
++ break;
++
++ case SCST_USER_PREALLOC_BUFFER:
++ TRACE_DBG("%s", "PREALLOC_BUFFER");
++ res = dev_user_prealloc_buffer(file, (void __user *)arg);
++ break;
++
++ default:
++ PRINT_ERROR("Invalid ioctl cmd %x", cmd);
++ res = -EINVAL;
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static unsigned int dev_user_poll(struct file *file, poll_table *wait)
++{
++ int res = 0;
++ struct scst_user_dev *dev;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (unlikely(res != 0)) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ if (!list_empty(&dev->ready_cmd_list) ||
++ !list_empty(&dev->udev_cmd_threads.active_cmd_list)) {
++ res |= POLLIN | POLLRDNORM;
++ goto out_unlock;
++ }
++
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ TRACE_DBG("Before poll_wait() (dev %s)", dev->name);
++ poll_wait(file, &dev->udev_cmd_threads.cmd_list_waitQ, wait);
++ TRACE_DBG("After poll_wait() (dev %s)", dev->name);
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ if (!list_empty(&dev->ready_cmd_list) ||
++ !list_empty(&dev->udev_cmd_threads.active_cmd_list)) {
++ res |= POLLIN | POLLRDNORM;
++ goto out_unlock;
++ }
++
++out_unlock:
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/*
++ * Called under udev_cmd_threads.cmd_list_lock, but can drop it inside,
++ * then reacquire.
++ */
++static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy,
++ unsigned long *flags)
++ __releases(&dev->udev_cmd_threads.cmd_list_lock)
++ __acquires(&dev->udev_cmd_threads.cmd_list_lock)
++{
++ int state = ucmd->state;
++ struct scst_user_dev *dev = ucmd->dev;
++
++ TRACE_ENTRY();
++
++ if (ucmd->this_state_unjammed)
++ goto out;
++
++ TRACE_MGMT_DBG("Unjamming ucmd %p (busy %d, state %x)", ucmd, busy,
++ state);
++
++ ucmd->jammed = 1;
++ ucmd->this_state_unjammed = 1;
++ ucmd->sent_to_user = 0;
++
++ switch (state) {
++ case UCMD_STATE_PARSING:
++ case UCMD_STATE_BUF_ALLOCING:
++ if (test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags))
++ ucmd->aborted = 1;
++ else {
++ if (busy)
++ scst_set_busy(ucmd->cmd);
++ else
++ scst_set_cmd_error(ucmd->cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ scst_set_cmd_abnormal_done_state(ucmd->cmd);
++
++ if (state == UCMD_STATE_PARSING)
++ scst_post_parse(ucmd->cmd);
++ else
++ scst_post_alloc_data_buf(ucmd->cmd);
++
++ TRACE_MGMT_DBG("Adding ucmd %p to active list", ucmd);
++ list_add(&ucmd->cmd->cmd_list_entry,
++ &ucmd->cmd->cmd_threads->active_cmd_list);
++ wake_up(&ucmd->cmd->cmd_threads->cmd_list_waitQ);
++ break;
++
++ case UCMD_STATE_EXECING:
++ if (flags != NULL)
++ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock,
++ *flags);
++ else
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ TRACE_MGMT_DBG("EXEC: unjamming ucmd %p", ucmd);
++
++ if (test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags))
++ ucmd->aborted = 1;
++ else {
++ if (busy)
++ scst_set_busy(ucmd->cmd);
++ else
++ scst_set_cmd_error(ucmd->cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++
++ ucmd->cmd->scst_cmd_done(ucmd->cmd, SCST_CMD_STATE_DEFAULT,
++ SCST_CONTEXT_DIRECT);
++ /* !! At this point cmd and ucmd can be already freed !! */
++
++ if (flags != NULL)
++ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock,
++ *flags);
++ else
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ break;
++
++ case UCMD_STATE_ON_FREEING:
++ case UCMD_STATE_ON_CACHE_FREEING:
++ case UCMD_STATE_TM_EXECING:
++ case UCMD_STATE_ATTACH_SESS:
++ case UCMD_STATE_DETACH_SESS:
++ if (flags != NULL)
++ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock,
++ *flags);
++ else
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ switch (state) {
++ case UCMD_STATE_ON_FREEING:
++ dev_user_process_reply_on_free(ucmd);
++ break;
++
++ case UCMD_STATE_ON_CACHE_FREEING:
++ dev_user_process_reply_on_cache_free(ucmd);
++ break;
++
++ case UCMD_STATE_TM_EXECING:
++ dev_user_process_reply_tm_exec(ucmd,
++ SCST_MGMT_STATUS_FAILED);
++ break;
++
++ case UCMD_STATE_ATTACH_SESS:
++ case UCMD_STATE_DETACH_SESS:
++ dev_user_process_reply_sess(ucmd, -EFAULT);
++ break;
++ }
++
++ if (flags != NULL)
++ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock,
++ *flags);
++ else
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ break;
++
++ default:
++ PRINT_CRIT_ERROR("Wrong ucmd state %x", state);
++ BUG();
++ break;
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int dev_user_unjam_dev(struct scst_user_dev *dev)
++ __releases(&dev->udev_cmd_threads.cmd_list_lock)
++ __acquires(&dev->udev_cmd_threads.cmd_list_lock)
++{
++ int i, res = 0;
++ struct scst_user_cmd *ucmd;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Unjamming dev %p", dev);
++
++ sgv_pool_flush(dev->pool);
++ sgv_pool_flush(dev->pool_clust);
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++repeat:
++ for (i = 0; i < (int)ARRAY_SIZE(dev->ucmd_hash); i++) {
++ struct list_head *head = &dev->ucmd_hash[i];
++
++ list_for_each_entry(ucmd, head, hash_list_entry) {
++ res++;
++
++ if (!ucmd->sent_to_user)
++ continue;
++
++ if (ucmd_get_check(ucmd))
++ continue;
++
++ TRACE_MGMT_DBG("ucmd %p, state %x, scst_cmd %p", ucmd,
++ ucmd->state, ucmd->cmd);
++
++ dev_user_unjam_cmd(ucmd, 0, NULL);
++
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ ucmd_put(ucmd);
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ goto repeat;
++ }
++ }
++
++ if (dev_user_process_scst_commands(dev) != 0)
++ goto repeat;
++
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_process_reply_tm_exec(struct scst_user_cmd *ucmd,
++ int status)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("TM reply (ucmd %p, fn %d, status %d)", ucmd,
++ ucmd->user_cmd.tm_cmd.fn, status);
++
++ if (status == SCST_MGMT_STATUS_TASK_NOT_EXIST) {
++ /*
++ * It is possible that user space seen TM cmd before cmd
++ * to abort or will never see it at all, because it was
++ * aborted on the way there. So, it is safe to return
++ * success instead, because, if there is the TM cmd at this
++ * point, then the cmd to abort apparrently does exist.
++ */
++ status = SCST_MGMT_STATUS_SUCCESS;
++ }
++
++ scst_async_mcmd_completed(ucmd->mcmd, status);
++
++ ucmd_put(ucmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void dev_user_abort_ready_commands(struct scst_user_dev *dev)
++{
++ struct scst_user_cmd *ucmd;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ spin_lock_irqsave(&dev->udev_cmd_threads.cmd_list_lock, flags);
++again:
++ list_for_each_entry(ucmd, &dev->ready_cmd_list, ready_cmd_list_entry) {
++ if ((ucmd->cmd != NULL) && !ucmd->seen_by_user &&
++ test_bit(SCST_CMD_ABORTED, &ucmd->cmd->cmd_flags)) {
++ switch (ucmd->state) {
++ case UCMD_STATE_PARSING:
++ case UCMD_STATE_BUF_ALLOCING:
++ case UCMD_STATE_EXECING:
++ TRACE_MGMT_DBG("Aborting ready ucmd %p", ucmd);
++ list_del(&ucmd->ready_cmd_list_entry);
++ dev_user_unjam_cmd(ucmd, 0, &flags);
++ goto again;
++ }
++ }
++ }
++
++ spin_unlock_irqrestore(&dev->udev_cmd_threads.cmd_list_lock, flags);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int dev_user_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
++ struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_user_cmd *ucmd;
++ struct scst_user_dev *dev =
++ (struct scst_user_dev *)tgt_dev->dev->dh_priv;
++ struct scst_user_cmd *ucmd_to_abort = NULL;
++
++ TRACE_ENTRY();
++
++ /*
++ * In the used approach we don't do anything with hung devices, which
++ * stopped responding and/or have stuck commands. We forcedly abort such
++ * commands only if they not yet sent to the user space or if the device
++ * is getting unloaded, e.g. if its handler program gets killed. This is
++ * because it's pretty hard to distinguish between stuck and temporary
++ * overloaded states of the device. There are several reasons for that:
++ *
++ * 1. Some commands need a lot of time to complete (several hours),
++ * so for an impatient user such command(s) will always look as
++ * stuck.
++ *
++ * 2. If we forcedly abort, i.e. abort before it's actually completed
++ * in the user space, just one command, we will have to put the whole
++ * device offline until we are sure that no more previously aborted
++ * commands will get executed. Otherwise, we might have a possibility
++ * for data corruption, when aborted and reported as completed
++ * command actually gets executed *after* new commands sent
++ * after the force abort was done. Many journaling file systems and
++ * databases use "provide required commands order via queue draining"
++ * approach and not putting the whole device offline after the forced
++ * abort will break it. This makes our decision, if a command stuck
++ * or not, cost a lot.
++ *
++ * So, we leave policy definition if a device stuck or not to
++ * the user space and simply let all commands live until they are
++ * completed or their devices get closed/killed. This approach is very
++ * much OK, but can affect management commands, which need activity
++ * suspending via scst_suspend_activity() function such as devices or
++ * targets registration/removal. But during normal life such commands
++ * should be rare. Plus, when possible, scst_suspend_activity() will
++ * return after timeout EBUSY status to allow caller to not stuck
++ * forever as well.
++ *
++ * But, anyway, ToDo, we should reimplement that in the SCST core, so
++ * stuck commands would affect only related devices.
++ */
++
++ dev_user_abort_ready_commands(dev);
++
++ /* We can't afford missing TM command due to memory shortage */
++ ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL|__GFP_NOFAIL);
++
++ ucmd->user_cmd_payload_len =
++ offsetof(struct scst_user_get_cmd, tm_cmd) +
++ sizeof(ucmd->user_cmd.tm_cmd);
++ ucmd->user_cmd.cmd_h = ucmd->h;
++ ucmd->user_cmd.subcode = SCST_USER_TASK_MGMT;
++ ucmd->user_cmd.tm_cmd.sess_h = (unsigned long)tgt_dev;
++ ucmd->user_cmd.tm_cmd.fn = mcmd->fn;
++ ucmd->user_cmd.tm_cmd.cmd_sn = mcmd->cmd_sn;
++ ucmd->user_cmd.tm_cmd.cmd_sn_set = mcmd->cmd_sn_set;
++
++ if (mcmd->cmd_to_abort != NULL) {
++ ucmd_to_abort =
++ (struct scst_user_cmd *)mcmd->cmd_to_abort->dh_priv;
++ if (ucmd_to_abort != NULL)
++ ucmd->user_cmd.tm_cmd.cmd_h_to_abort = ucmd_to_abort->h;
++ }
++
++ TRACE_MGMT_DBG("Preparing TM ucmd %p (h %d, fn %d, cmd_to_abort %p, "
++ "ucmd_to_abort %p, cmd_h_to_abort %d, mcmd %p)", ucmd, ucmd->h,
++ mcmd->fn, mcmd->cmd_to_abort, ucmd_to_abort,
++ ucmd->user_cmd.tm_cmd.cmd_h_to_abort, mcmd);
++
++ ucmd->mcmd = mcmd;
++ ucmd->state = UCMD_STATE_TM_EXECING;
++
++ scst_prepare_async_mcmd(mcmd);
++
++ dev_user_add_to_ready(ucmd);
++
++ TRACE_EXIT();
++ return SCST_DEV_TM_NOT_COMPLETED;
++}
++
++static int dev_user_attach(struct scst_device *sdev)
++{
++ int res = 0;
++ struct scst_user_dev *dev = NULL, *d;
++
++ TRACE_ENTRY();
++
++ spin_lock(&dev_list_lock);
++ list_for_each_entry(d, &dev_list, dev_list_entry) {
++ if (strcmp(d->name, sdev->virt_name) == 0) {
++ dev = d;
++ break;
++ }
++ }
++ spin_unlock(&dev_list_lock);
++ if (dev == NULL) {
++ PRINT_ERROR("Device %s not found", sdev->virt_name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ sdev->dh_priv = dev;
++ sdev->tst = dev->tst;
++ sdev->queue_alg = dev->queue_alg;
++ sdev->swp = dev->swp;
++ sdev->tas = dev->tas;
++ sdev->d_sense = dev->d_sense;
++ sdev->has_own_order_mgmt = dev->has_own_order_mgmt;
++
++ dev->sdev = sdev;
++
++ PRINT_INFO("Attached user space virtual device \"%s\"",
++ dev->name);
++
++out:
++ TRACE_EXIT();
++ return res;
++}
++
++static void dev_user_detach(struct scst_device *sdev)
++{
++ struct scst_user_dev *dev = (struct scst_user_dev *)sdev->dh_priv;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("virt_id %d", sdev->virt_id);
++
++ PRINT_INFO("Detached user space virtual device \"%s\"",
++ dev->name);
++
++ /* dev will be freed by the caller */
++ sdev->dh_priv = NULL;
++ dev->sdev = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++static int dev_user_process_reply_sess(struct scst_user_cmd *ucmd, int status)
++{
++ int res = 0;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("ucmd %p, cmpl %p, status %d", ucmd, ucmd->cmpl, status);
++
++ spin_lock_irqsave(&ucmd->dev->udev_cmd_threads.cmd_list_lock, flags);
++
++ if (ucmd->state == UCMD_STATE_ATTACH_SESS) {
++ TRACE_MGMT_DBG("%s", "ATTACH_SESS finished");
++ ucmd->result = status;
++ } else if (ucmd->state == UCMD_STATE_DETACH_SESS) {
++ TRACE_MGMT_DBG("%s", "DETACH_SESS finished");
++ } else
++ BUG();
++
++ if (ucmd->cmpl != NULL)
++ complete_all(ucmd->cmpl);
++
++ spin_unlock_irqrestore(&ucmd->dev->udev_cmd_threads.cmd_list_lock, flags);
++
++ ucmd_put(ucmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_attach_tgt(struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_user_dev *dev =
++ (struct scst_user_dev *)tgt_dev->dev->dh_priv;
++ int res = 0, rc;
++ struct scst_user_cmd *ucmd;
++ DECLARE_COMPLETION_ONSTACK(cmpl);
++ struct scst_tgt_template *tgtt = tgt_dev->sess->tgt->tgtt;
++ struct scst_tgt *tgt = tgt_dev->sess->tgt;
++
++ TRACE_ENTRY();
++
++ tgt_dev->active_cmd_threads = &dev->udev_cmd_threads;
++
++ /*
++ * We can't replace tgt_dev->pool, because it can be used to allocate
++ * memory for SCST local commands, like REPORT LUNS, where there is no
++ * corresponding ucmd. Otherwise we will crash in dev_user_alloc_sg().
++ */
++ if (test_bit(SCST_TGT_DEV_CLUST_POOL, &tgt_dev->tgt_dev_flags))
++ tgt_dev->dh_priv = dev->pool_clust;
++ else
++ tgt_dev->dh_priv = dev->pool;
++
++ ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL);
++ if (ucmd == NULL)
++ goto out_nomem;
++
++ ucmd->cmpl = &cmpl;
++
++ ucmd->user_cmd_payload_len = offsetof(struct scst_user_get_cmd, sess) +
++ sizeof(ucmd->user_cmd.sess);
++ ucmd->user_cmd.cmd_h = ucmd->h;
++ ucmd->user_cmd.subcode = SCST_USER_ATTACH_SESS;
++ ucmd->user_cmd.sess.sess_h = (unsigned long)tgt_dev;
++ ucmd->user_cmd.sess.lun = (uint64_t)tgt_dev->lun;
++ ucmd->user_cmd.sess.threads_num = tgt_dev->sess->tgt->tgtt->threads_num;
++ ucmd->user_cmd.sess.rd_only = tgt_dev->acg_dev->rd_only;
++ if (tgtt->get_phys_transport_version != NULL)
++ ucmd->user_cmd.sess.phys_transport_version =
++ tgtt->get_phys_transport_version(tgt);
++ if (tgtt->get_scsi_transport_version != NULL)
++ ucmd->user_cmd.sess.scsi_transport_version =
++ tgtt->get_scsi_transport_version(tgt);
++ strlcpy(ucmd->user_cmd.sess.initiator_name,
++ tgt_dev->sess->initiator_name,
++ sizeof(ucmd->user_cmd.sess.initiator_name)-1);
++ strlcpy(ucmd->user_cmd.sess.target_name,
++ tgt_dev->sess->tgt->tgt_name,
++ sizeof(ucmd->user_cmd.sess.target_name)-1);
++
++ TRACE_MGMT_DBG("Preparing ATTACH_SESS %p (h %d, sess_h %llx, LUN %llx, "
++ "threads_num %d, rd_only %d, initiator %s, target %s)",
++ ucmd, ucmd->h, ucmd->user_cmd.sess.sess_h,
++ ucmd->user_cmd.sess.lun, ucmd->user_cmd.sess.threads_num,
++ ucmd->user_cmd.sess.rd_only, ucmd->user_cmd.sess.initiator_name,
++ ucmd->user_cmd.sess.target_name);
++
++ ucmd->state = UCMD_STATE_ATTACH_SESS;
++
++ ucmd_get(ucmd);
++
++ dev_user_add_to_ready(ucmd);
++
++ rc = wait_for_completion_timeout(ucmd->cmpl, DEV_USER_ATTACH_TIMEOUT);
++ if (rc > 0)
++ res = ucmd->result;
++ else {
++ PRINT_ERROR("%s", "ATTACH_SESS command timeout");
++ res = -EFAULT;
++ }
++
++ BUG_ON(irqs_disabled());
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++ ucmd->cmpl = NULL;
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ ucmd_put(ucmd);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_nomem:
++ res = -ENOMEM;
++ goto out;
++}
++
++static void dev_user_detach_tgt(struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_user_dev *dev =
++ (struct scst_user_dev *)tgt_dev->dev->dh_priv;
++ struct scst_user_cmd *ucmd;
++
++ TRACE_ENTRY();
++
++ /*
++ * We can't miss TM command due to memory shortage, because it might
++ * lead to a memory leak in the user space handler.
++ */
++ ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL|__GFP_NOFAIL);
++ if (ucmd == NULL)
++ goto out;
++
++ TRACE_MGMT_DBG("Preparing DETACH_SESS %p (h %d, sess_h %llx)", ucmd,
++ ucmd->h, ucmd->user_cmd.sess.sess_h);
++
++ ucmd->user_cmd_payload_len = offsetof(struct scst_user_get_cmd, sess) +
++ sizeof(ucmd->user_cmd.sess);
++ ucmd->user_cmd.cmd_h = ucmd->h;
++ ucmd->user_cmd.subcode = SCST_USER_DETACH_SESS;
++ ucmd->user_cmd.sess.sess_h = (unsigned long)tgt_dev;
++
++ ucmd->state = UCMD_STATE_DETACH_SESS;
++
++ dev_user_add_to_ready(ucmd);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* No locks are needed, but the activity must be suspended */
++static void dev_user_setup_functions(struct scst_user_dev *dev)
++{
++ TRACE_ENTRY();
++
++ dev->devtype.parse = dev_user_parse;
++ dev->devtype.alloc_data_buf = dev_user_alloc_data_buf;
++ dev->devtype.dev_done = NULL;
++
++ if (dev->parse_type != SCST_USER_PARSE_CALL) {
++ switch (dev->devtype.type) {
++ case TYPE_DISK:
++ dev->generic_parse = scst_sbc_generic_parse;
++ dev->devtype.dev_done = dev_user_disk_done;
++ break;
++
++ case TYPE_TAPE:
++ dev->generic_parse = scst_tape_generic_parse;
++ dev->devtype.dev_done = dev_user_tape_done;
++ break;
++
++ case TYPE_MOD:
++ dev->generic_parse = scst_modisk_generic_parse;
++ dev->devtype.dev_done = dev_user_disk_done;
++ break;
++
++ case TYPE_ROM:
++ dev->generic_parse = scst_cdrom_generic_parse;
++ dev->devtype.dev_done = dev_user_disk_done;
++ break;
++
++ case TYPE_MEDIUM_CHANGER:
++ dev->generic_parse = scst_changer_generic_parse;
++ break;
++
++ case TYPE_PROCESSOR:
++ dev->generic_parse = scst_processor_generic_parse;
++ break;
++
++ case TYPE_RAID:
++ dev->generic_parse = scst_raid_generic_parse;
++ break;
++
++ default:
++ PRINT_INFO("Unknown SCSI type %x, using PARSE_CALL "
++ "for it", dev->devtype.type);
++ dev->parse_type = SCST_USER_PARSE_CALL;
++ break;
++ }
++ } else {
++ dev->generic_parse = NULL;
++ dev->devtype.dev_done = NULL;
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static int dev_user_check_version(const struct scst_user_dev_desc *dev_desc)
++{
++ char str[sizeof(DEV_USER_VERSION) > 20 ? sizeof(DEV_USER_VERSION) : 20];
++ int res = 0, rc;
++
++ rc = copy_from_user(str,
++ (void __user *)(unsigned long)dev_desc->license_str,
++ sizeof(str));
++ if (rc != 0) {
++ PRINT_ERROR("%s", "Unable to get license string");
++ res = -EFAULT;
++ goto out;
++ }
++ str[sizeof(str)-1] = '\0';
++
++ if ((strcmp(str, "GPL") != 0) &&
++ (strcmp(str, "GPL v2") != 0) &&
++ (strcmp(str, "Dual BSD/GPL") != 0) &&
++ (strcmp(str, "Dual MIT/GPL") != 0) &&
++ (strcmp(str, "Dual MPL/GPL") != 0)) {
++ /* ->name already 0-terminated in dev_user_ioctl() */
++ PRINT_ERROR("Unsupported license of user device %s (%s). "
++ "Ask license@scst-tgt.com for more info.",
++ dev_desc->name, str);
++ res = -EPERM;
++ goto out;
++ }
++
++ rc = copy_from_user(str,
++ (void __user *)(unsigned long)dev_desc->version_str,
++ sizeof(str));
++ if (rc != 0) {
++ PRINT_ERROR("%s", "Unable to get version string");
++ res = -EFAULT;
++ goto out;
++ }
++ str[sizeof(str)-1] = '\0';
++
++ if (strcmp(str, DEV_USER_VERSION) != 0) {
++ /* ->name already 0-terminated in dev_user_ioctl() */
++ PRINT_ERROR("Incorrect version of user device %s (%s). "
++ "Expected: %s", dev_desc->name, str,
++ DEV_USER_VERSION);
++ res = -EINVAL;
++ goto out;
++ }
++
++out:
++ return res;
++}
++
++static int dev_user_register_dev(struct file *file,
++ const struct scst_user_dev_desc *dev_desc)
++{
++ int res, i;
++ struct scst_user_dev *dev, *d;
++ int block;
++
++ TRACE_ENTRY();
++
++ res = dev_user_check_version(dev_desc);
++ if (res != 0)
++ goto out;
++
++ switch (dev_desc->type) {
++ case TYPE_DISK:
++ case TYPE_ROM:
++ case TYPE_MOD:
++ if (dev_desc->block_size == 0) {
++ PRINT_ERROR("Wrong block size %d",
++ dev_desc->block_size);
++ res = -EINVAL;
++ goto out;
++ }
++ block = scst_calc_block_shift(dev_desc->block_size);
++ if (block == -1) {
++ res = -EINVAL;
++ goto out;
++ }
++ break;
++ default:
++ block = dev_desc->block_size;
++ break;
++ }
++
++ if (!try_module_get(THIS_MODULE)) {
++ PRINT_ERROR("%s", "Fail to get module");
++ res = -ETXTBSY;
++ goto out;
++ }
++
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (dev == NULL) {
++ res = -ENOMEM;
++ goto out_put;
++ }
++
++ init_rwsem(&dev->dev_rwsem);
++ INIT_LIST_HEAD(&dev->ready_cmd_list);
++ if (file->f_flags & O_NONBLOCK) {
++ TRACE_DBG("%s", "Non-blocking operations");
++ dev->blocking = 0;
++ } else
++ dev->blocking = 1;
++ for (i = 0; i < (int)ARRAY_SIZE(dev->ucmd_hash); i++)
++ INIT_LIST_HEAD(&dev->ucmd_hash[i]);
++
++ scst_init_threads(&dev->udev_cmd_threads);
++
++ strlcpy(dev->name, dev_desc->name, sizeof(dev->name)-1);
++
++ scst_init_mem_lim(&dev->udev_mem_lim);
++
++ scnprintf(dev->devtype.name, sizeof(dev->devtype.name), "%s",
++ (dev_desc->sgv_name[0] == '\0') ? dev->name :
++ dev_desc->sgv_name);
++ dev->pool = sgv_pool_create(dev->devtype.name, sgv_no_clustering,
++ dev_desc->sgv_single_alloc_pages,
++ dev_desc->sgv_shared,
++ dev_desc->sgv_purge_interval);
++ if (dev->pool == NULL) {
++ res = -ENOMEM;
++ goto out_deinit_threads;
++ }
++ sgv_pool_set_allocator(dev->pool, dev_user_alloc_pages,
++ dev_user_free_sg_entries);
++
++ if (!dev_desc->sgv_disable_clustered_pool) {
++ scnprintf(dev->devtype.name, sizeof(dev->devtype.name),
++ "%s-clust",
++ (dev_desc->sgv_name[0] == '\0') ? dev->name :
++ dev_desc->sgv_name);
++ dev->pool_clust = sgv_pool_create(dev->devtype.name,
++ sgv_tail_clustering,
++ dev_desc->sgv_single_alloc_pages,
++ dev_desc->sgv_shared,
++ dev_desc->sgv_purge_interval);
++ if (dev->pool_clust == NULL) {
++ res = -ENOMEM;
++ goto out_free0;
++ }
++ sgv_pool_set_allocator(dev->pool_clust, dev_user_alloc_pages,
++ dev_user_free_sg_entries);
++ } else {
++ dev->pool_clust = dev->pool;
++ sgv_pool_get(dev->pool_clust);
++ }
++
++ scnprintf(dev->devtype.name, sizeof(dev->devtype.name), "%s",
++ dev->name);
++ dev->devtype.type = dev_desc->type;
++ dev->devtype.threads_num = -1;
++ dev->devtype.parse_atomic = 1;
++ dev->devtype.alloc_data_buf_atomic = 1;
++ dev->devtype.dev_done_atomic = 1;
++ dev->devtype.dev_attrs = dev_user_dev_attrs;
++ dev->devtype.attach = dev_user_attach;
++ dev->devtype.detach = dev_user_detach;
++ dev->devtype.attach_tgt = dev_user_attach_tgt;
++ dev->devtype.detach_tgt = dev_user_detach_tgt;
++ dev->devtype.exec = dev_user_exec;
++ dev->devtype.on_free_cmd = dev_user_on_free_cmd;
++ dev->devtype.task_mgmt_fn = dev_user_task_mgmt_fn;
++ if (dev_desc->enable_pr_cmds_notifications)
++ dev->devtype.pr_cmds_notifications = 1;
++
++ init_completion(&dev->cleanup_cmpl);
++ dev->block = block;
++ dev->def_block = block;
++
++ res = __dev_user_set_opt(dev, &dev_desc->opt);
++ if (res != 0)
++ goto out_free;
++
++ TRACE_MEM("dev %p, name %s", dev, dev->name);
++
++ spin_lock(&dev_list_lock);
++
++ list_for_each_entry(d, &dev_list, dev_list_entry) {
++ if (strcmp(d->name, dev->name) == 0) {
++ PRINT_ERROR("Device %s already exist",
++ dev->name);
++ res = -EEXIST;
++ spin_unlock(&dev_list_lock);
++ goto out_free;
++ }
++ }
++
++ list_add_tail(&dev->dev_list_entry, &dev_list);
++
++ spin_unlock(&dev_list_lock);
++
++ res = scst_register_virtual_dev_driver(&dev->devtype);
++ if (res < 0)
++ goto out_del_free;
++
++ dev->virt_id = scst_register_virtual_device(&dev->devtype, dev->name);
++ if (dev->virt_id < 0) {
++ res = dev->virt_id;
++ goto out_unreg_handler;
++ }
++
++ mutex_lock(&dev_priv_mutex);
++ if (file->private_data != NULL) {
++ mutex_unlock(&dev_priv_mutex);
++ PRINT_ERROR("%s", "Device already registered");
++ res = -EINVAL;
++ goto out_unreg_drv;
++ }
++ file->private_data = dev;
++ mutex_unlock(&dev_priv_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unreg_drv:
++ scst_unregister_virtual_device(dev->virt_id);
++
++out_unreg_handler:
++ scst_unregister_virtual_dev_driver(&dev->devtype);
++
++out_del_free:
++ spin_lock(&dev_list_lock);
++ list_del(&dev->dev_list_entry);
++ spin_unlock(&dev_list_lock);
++
++out_free:
++ sgv_pool_del(dev->pool_clust);
++
++out_free0:
++ sgv_pool_del(dev->pool);
++
++out_deinit_threads:
++ scst_deinit_threads(&dev->udev_cmd_threads);
++
++ kfree(dev);
++
++out_put:
++ module_put(THIS_MODULE);
++ goto out;
++}
++
++static int dev_user_unregister_dev(struct file *file)
++{
++ int res;
++ struct scst_user_dev *dev;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (res != 0) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out_up;
++
++ up_read(&dev->dev_rwsem);
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ if (dev == NULL) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out_resume;
++ }
++
++ dev->blocking = 0;
++ wake_up_all(&dev->udev_cmd_threads.cmd_list_waitQ);
++
++ down_write(&dev->dev_rwsem);
++ file->private_data = NULL;
++ mutex_unlock(&dev_priv_mutex);
++
++ dev_user_exit_dev(dev);
++
++ up_write(&dev->dev_rwsem); /* to make lockdep happy */
++
++ kfree(dev);
++
++out_resume:
++ scst_resume_activity();
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_up:
++ up_read(&dev->dev_rwsem);
++ goto out;
++}
++
++static int dev_user_flush_cache(struct file *file)
++{
++ int res;
++ struct scst_user_dev *dev;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (res != 0) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out_up;
++
++ sgv_pool_flush(dev->pool);
++ sgv_pool_flush(dev->pool_clust);
++
++ scst_resume_activity();
++
++out_up:
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_capacity_changed(struct file *file)
++{
++ int res;
++ struct scst_user_dev *dev;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (res != 0) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ scst_capacity_data_changed(dev->sdev);
++
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_prealloc_buffer(struct file *file, void __user *arg)
++{
++ int res = 0, rc;
++ struct scst_user_dev *dev;
++ union scst_user_prealloc_buffer pre;
++ aligned_u64 pbuf;
++ uint32_t bufflen;
++ struct scst_user_cmd *ucmd;
++ int pages, sg_cnt;
++ struct sgv_pool *pool;
++ struct scatterlist *sg;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (unlikely(res != 0)) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ rc = copy_from_user(&pre.in, arg, sizeof(pre.in));
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ res = -EFAULT;
++ goto out_up;
++ }
++
++ TRACE_MEM("Prealloc buffer with size %dKB for dev %s",
++ pre.in.bufflen / 1024, dev->name);
++ TRACE_BUFFER("Input param", &pre.in, sizeof(pre.in));
++
++ pbuf = pre.in.pbuf;
++ bufflen = pre.in.bufflen;
++
++ ucmd = dev_user_alloc_ucmd(dev, GFP_KERNEL);
++ if (ucmd == NULL) {
++ res = -ENOMEM;
++ goto out_up;
++ }
++
++ ucmd->buff_cached = 1;
++
++ TRACE_MEM("ucmd %p, pbuf %llx", ucmd, pbuf);
++
++ if (unlikely((pbuf & ~PAGE_MASK) != 0)) {
++ PRINT_ERROR("Supplied pbuf %llx isn't page aligned", pbuf);
++ res = -EINVAL;
++ goto out_put;
++ }
++
++ pages = calc_num_pg(pbuf, bufflen);
++ res = dev_user_map_buf(ucmd, pbuf, pages);
++ if (res != 0)
++ goto out_put;
++
++ if (pre.in.for_clust_pool)
++ pool = dev->pool_clust;
++ else
++ pool = dev->pool;
++
++ sg = sgv_pool_alloc(pool, bufflen, GFP_KERNEL, SGV_POOL_ALLOC_GET_NEW,
++ &sg_cnt, &ucmd->sgv, &dev->udev_mem_lim, ucmd);
++ if (sg != NULL) {
++ struct scst_user_cmd *buf_ucmd =
++ (struct scst_user_cmd *)sgv_get_priv(ucmd->sgv);
++
++ TRACE_MEM("Buf ucmd %p (sg_cnt %d, last seg len %d, "
++ "bufflen %d)", buf_ucmd, sg_cnt,
++ sg[sg_cnt-1].length, bufflen);
++
++ EXTRACHECKS_BUG_ON(ucmd != buf_ucmd);
++
++ ucmd->buf_ucmd = buf_ucmd;
++ } else {
++ res = -ENOMEM;
++ goto out_put;
++ }
++
++ dev_user_free_sgv(ucmd);
++
++ pre.out.cmd_h = ucmd->h;
++ rc = copy_to_user(arg, &pre.out, sizeof(pre.out));
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Failed to copy to user %d bytes", rc);
++ res = -EFAULT;
++ goto out_put;
++ }
++
++out_put:
++ ucmd_put(ucmd);
++
++out_up:
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int __dev_user_set_opt(struct scst_user_dev *dev,
++ const struct scst_user_opt *opt)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("dev %s, parse_type %x, on_free_cmd_type %x, "
++ "memory_reuse_type %x, partial_transfers_type %x, "
++ "partial_len %d", dev->name, opt->parse_type,
++ opt->on_free_cmd_type, opt->memory_reuse_type,
++ opt->partial_transfers_type, opt->partial_len);
++
++ if (opt->parse_type > SCST_USER_MAX_PARSE_OPT ||
++ opt->on_free_cmd_type > SCST_USER_MAX_ON_FREE_CMD_OPT ||
++ opt->memory_reuse_type > SCST_USER_MAX_MEM_REUSE_OPT ||
++ opt->partial_transfers_type > SCST_USER_MAX_PARTIAL_TRANSFERS_OPT) {
++ PRINT_ERROR("%s", "Invalid option");
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (((opt->tst != SCST_CONTR_MODE_ONE_TASK_SET) &&
++ (opt->tst != SCST_CONTR_MODE_SEP_TASK_SETS)) ||
++ ((opt->queue_alg != SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) &&
++ (opt->queue_alg != SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER)) ||
++ (opt->swp > 1) || (opt->tas > 1) || (opt->has_own_order_mgmt > 1) ||
++ (opt->d_sense > 1)) {
++ PRINT_ERROR("Invalid SCSI option (tst %x, queue_alg %x, swp %x,"
++ " tas %x, d_sense %d, has_own_order_mgmt %x)", opt->tst,
++ opt->queue_alg, opt->swp, opt->tas, opt->d_sense,
++ opt->has_own_order_mgmt);
++ res = -EINVAL;
++ goto out;
++ }
++
++ dev->parse_type = opt->parse_type;
++ dev->on_free_cmd_type = opt->on_free_cmd_type;
++ dev->memory_reuse_type = opt->memory_reuse_type;
++ dev->partial_transfers_type = opt->partial_transfers_type;
++ dev->partial_len = opt->partial_len;
++
++ dev->tst = opt->tst;
++ dev->queue_alg = opt->queue_alg;
++ dev->swp = opt->swp;
++ dev->tas = opt->tas;
++ dev->tst = opt->tst;
++ dev->d_sense = opt->d_sense;
++ dev->has_own_order_mgmt = opt->has_own_order_mgmt;
++ if (dev->sdev != NULL) {
++ dev->sdev->tst = opt->tst;
++ dev->sdev->queue_alg = opt->queue_alg;
++ dev->sdev->swp = opt->swp;
++ dev->sdev->tas = opt->tas;
++ dev->sdev->d_sense = opt->d_sense;
++ dev->sdev->has_own_order_mgmt = opt->has_own_order_mgmt;
++ }
++
++ dev_user_setup_functions(dev);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_set_opt(struct file *file, const struct scst_user_opt *opt)
++{
++ int res;
++ struct scst_user_dev *dev;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (res != 0) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out_up;
++
++ res = __dev_user_set_opt(dev, opt);
++
++ scst_resume_activity();
++
++out_up:
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_user_get_opt(struct file *file, void __user *arg)
++{
++ int res, rc;
++ struct scst_user_dev *dev;
++ struct scst_user_opt opt;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&dev_priv_mutex);
++ dev = (struct scst_user_dev *)file->private_data;
++ res = dev_user_check_reg(dev);
++ if (res != 0) {
++ mutex_unlock(&dev_priv_mutex);
++ goto out;
++ }
++ down_read(&dev->dev_rwsem);
++ mutex_unlock(&dev_priv_mutex);
++
++ opt.parse_type = dev->parse_type;
++ opt.on_free_cmd_type = dev->on_free_cmd_type;
++ opt.memory_reuse_type = dev->memory_reuse_type;
++ opt.partial_transfers_type = dev->partial_transfers_type;
++ opt.partial_len = dev->partial_len;
++ opt.tst = dev->tst;
++ opt.queue_alg = dev->queue_alg;
++ opt.tas = dev->tas;
++ opt.swp = dev->swp;
++ opt.d_sense = dev->d_sense;
++ opt.has_own_order_mgmt = dev->has_own_order_mgmt;
++
++ TRACE_DBG("dev %s, parse_type %x, on_free_cmd_type %x, "
++ "memory_reuse_type %x, partial_transfers_type %x, "
++ "partial_len %d", dev->name, opt.parse_type,
++ opt.on_free_cmd_type, opt.memory_reuse_type,
++ opt.partial_transfers_type, opt.partial_len);
++
++ rc = copy_to_user(arg, &opt, sizeof(opt));
++ if (unlikely(rc != 0)) {
++ PRINT_ERROR("Failed to copy to user %d bytes", rc);
++ res = -EFAULT;
++ goto out_up;
++ }
++
++out_up:
++ up_read(&dev->dev_rwsem);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int dev_usr_parse(struct scst_cmd *cmd)
++{
++ BUG();
++ return SCST_CMD_STATE_DEFAULT;
++}
++
++static int dev_user_exit_dev(struct scst_user_dev *dev)
++{
++ TRACE_ENTRY();
++
++ TRACE(TRACE_MGMT, "Releasing dev %s", dev->name);
++
++ spin_lock(&dev_list_lock);
++ list_del(&dev->dev_list_entry);
++ spin_unlock(&dev_list_lock);
++
++ dev->blocking = 0;
++ wake_up_all(&dev->udev_cmd_threads.cmd_list_waitQ);
++
++ spin_lock(&cleanup_lock);
++ list_add_tail(&dev->cleanup_list_entry, &cleanup_list);
++ spin_unlock(&cleanup_lock);
++
++ wake_up(&cleanup_list_waitQ);
++
++ scst_unregister_virtual_device(dev->virt_id);
++ scst_unregister_virtual_dev_driver(&dev->devtype);
++
++ sgv_pool_flush(dev->pool_clust);
++ sgv_pool_flush(dev->pool);
++
++ TRACE_MGMT_DBG("Unregistering finished (dev %p)", dev);
++
++ dev->cleanup_done = 1;
++
++ wake_up(&cleanup_list_waitQ);
++ wake_up(&dev->udev_cmd_threads.cmd_list_waitQ);
++
++ wait_for_completion(&dev->cleanup_cmpl);
++
++ sgv_pool_del(dev->pool_clust);
++ sgv_pool_del(dev->pool);
++
++ scst_deinit_threads(&dev->udev_cmd_threads);
++
++ TRACE_MGMT_DBG("Releasing completed (dev %p)", dev);
++
++ module_put(THIS_MODULE);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static int __dev_user_release(void *arg)
++{
++ struct scst_user_dev *dev = (struct scst_user_dev *)arg;
++ dev_user_exit_dev(dev);
++ kfree(dev);
++ return 0;
++}
++
++static int dev_user_release(struct inode *inode, struct file *file)
++{
++ struct scst_user_dev *dev;
++ struct task_struct *t;
++
++ TRACE_ENTRY();
++
++ dev = (struct scst_user_dev *)file->private_data;
++ if (dev == NULL)
++ goto out;
++ file->private_data = NULL;
++
++ TRACE_MGMT_DBG("Going to release dev %s", dev->name);
++
++ t = kthread_run(__dev_user_release, dev, "scst_usr_released");
++ if (IS_ERR(t)) {
++ PRINT_CRIT_ERROR("kthread_run() failed (%ld), releasing device "
++ "%p directly. If you have several devices under load "
++ "it might deadlock!", PTR_ERR(t), dev);
++ __dev_user_release(dev);
++ }
++
++out:
++ TRACE_EXIT();
++ return 0;
++}
++
++static int dev_user_process_cleanup(struct scst_user_dev *dev)
++{
++ struct scst_user_cmd *ucmd;
++ int rc = 0, res = 1;
++
++ TRACE_ENTRY();
++
++ BUG_ON(dev->blocking);
++ wake_up_all(&dev->udev_cmd_threads.cmd_list_waitQ); /* just in case */
++
++ while (1) {
++ int rc1;
++
++ TRACE_DBG("Cleanuping dev %p", dev);
++
++ rc1 = dev_user_unjam_dev(dev);
++ if ((rc1 == 0) && (rc == -EAGAIN) && dev->cleanup_done)
++ break;
++
++ spin_lock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ rc = dev_user_get_next_cmd(dev, &ucmd);
++ if (rc == 0)
++ dev_user_unjam_cmd(ucmd, 1, NULL);
++
++ spin_unlock_irq(&dev->udev_cmd_threads.cmd_list_lock);
++
++ if (rc == -EAGAIN) {
++ if (!dev->cleanup_done) {
++ TRACE_DBG("No more commands (dev %p)", dev);
++ goto out;
++ }
++ }
++ }
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++{
++ int i;
++ for (i = 0; i < (int)ARRAY_SIZE(dev->ucmd_hash); i++) {
++ struct list_head *head = &dev->ucmd_hash[i];
++ struct scst_user_cmd *ucmd2;
++again:
++ list_for_each_entry(ucmd2, head, hash_list_entry) {
++ PRINT_ERROR("Lost ucmd %p (state %x, ref %d)", ucmd2,
++ ucmd2->state, atomic_read(&ucmd2->ucmd_ref));
++ ucmd_put(ucmd2);
++ goto again;
++ }
++ }
++}
++#endif
++
++ TRACE_DBG("Cleanuping done (dev %p)", dev);
++ complete_all(&dev->cleanup_cmpl);
++ res = 0;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t dev_user_sysfs_commands_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0, ppos, i;
++ struct scst_device *dev;
++ struct scst_user_dev *udev;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ udev = (struct scst_user_dev *)dev->dh_priv;
++
++ spin_lock_irqsave(&udev->udev_cmd_threads.cmd_list_lock, flags);
++ for (i = 0; i < (int)ARRAY_SIZE(udev->ucmd_hash); i++) {
++ struct list_head *head = &udev->ucmd_hash[i];
++ struct scst_user_cmd *ucmd;
++ list_for_each_entry(ucmd, head, hash_list_entry) {
++ ppos = pos;
++ pos += scnprintf(&buf[pos],
++ SCST_SYSFS_BLOCK_SIZE - pos,
++ "ucmd %p (state %x, ref %d), "
++ "sent_to_user %d, seen_by_user %d, "
++ "aborted %d, jammed %d, scst_cmd %p\n",
++ ucmd, ucmd->state,
++ atomic_read(&ucmd->ucmd_ref),
++ ucmd->sent_to_user, ucmd->seen_by_user,
++ ucmd->aborted, ucmd->jammed, ucmd->cmd);
++ if (pos >= SCST_SYSFS_BLOCK_SIZE-1) {
++ ppos += scnprintf(&buf[ppos],
++ SCST_SYSFS_BLOCK_SIZE - ppos, "...\n");
++ pos = ppos;
++ break;
++ }
++ }
++ }
++ spin_unlock_irqrestore(&udev->udev_cmd_threads.cmd_list_lock, flags);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static inline int test_cleanup_list(void)
++{
++ int res = !list_empty(&cleanup_list) ||
++ unlikely(kthread_should_stop());
++ return res;
++}
++
++static int dev_user_cleanup_thread(void *arg)
++{
++ TRACE_ENTRY();
++
++ PRINT_INFO("Cleanup thread started, PID %d", current->pid);
++
++ current->flags |= PF_NOFREEZE;
++
++ spin_lock(&cleanup_lock);
++ while (!kthread_should_stop()) {
++ wait_queue_t wait;
++ init_waitqueue_entry(&wait, current);
++
++ if (!test_cleanup_list()) {
++ add_wait_queue_exclusive(&cleanup_list_waitQ, &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_cleanup_list())
++ break;
++ spin_unlock(&cleanup_lock);
++ schedule();
++ spin_lock(&cleanup_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&cleanup_list_waitQ, &wait);
++ }
++
++ /*
++ * We have to poll devices, because commands can go from SCST
++ * core on cmd_list_waitQ and we have no practical way to
++ * detect them.
++ */
++
++ while (1) {
++ struct scst_user_dev *dev;
++ LIST_HEAD(cl_devs);
++
++ while (!list_empty(&cleanup_list)) {
++ int rc;
++
++ dev = list_entry(cleanup_list.next,
++ typeof(*dev), cleanup_list_entry);
++ list_del(&dev->cleanup_list_entry);
++
++ spin_unlock(&cleanup_lock);
++ rc = dev_user_process_cleanup(dev);
++ spin_lock(&cleanup_lock);
++
++ if (rc != 0)
++ list_add_tail(&dev->cleanup_list_entry,
++ &cl_devs);
++ }
++
++ if (list_empty(&cl_devs))
++ break;
++
++ spin_unlock(&cleanup_lock);
++ msleep(100);
++ spin_lock(&cleanup_lock);
++
++ while (!list_empty(&cl_devs)) {
++ dev = list_entry(cl_devs.next, typeof(*dev),
++ cleanup_list_entry);
++ list_move_tail(&dev->cleanup_list_entry,
++ &cleanup_list);
++ }
++ }
++ }
++ spin_unlock(&cleanup_lock);
++
++ /*
++ * If kthread_should_stop() is true, we are guaranteed to be
++ * on the module unload, so cleanup_list must be empty.
++ */
++ BUG_ON(!list_empty(&cleanup_list));
++
++ PRINT_INFO("Cleanup thread PID %d finished", current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static int __init init_scst_user(void)
++{
++ int res = 0;
++ struct max_get_reply {
++ union {
++ struct scst_user_get_cmd g;
++ struct scst_user_reply_cmd r;
++ };
++ };
++ struct device *dev;
++
++ TRACE_ENTRY();
++
++ user_cmd_cachep = KMEM_CACHE(scst_user_cmd, SCST_SLAB_FLAGS);
++ if (user_cmd_cachep == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++
++ user_get_cmd_cachep = KMEM_CACHE(max_get_reply, SCST_SLAB_FLAGS);
++ if (user_get_cmd_cachep == NULL) {
++ res = -ENOMEM;
++ goto out_cache;
++ }
++
++ dev_user_devtype.module = THIS_MODULE;
++
++ res = scst_register_virtual_dev_driver(&dev_user_devtype);
++ if (res < 0)
++ goto out_cache1;
++
++ dev_user_sysfs_class = class_create(THIS_MODULE, DEV_USER_NAME);
++ if (IS_ERR(dev_user_sysfs_class)) {
++ PRINT_ERROR("%s", "Unable create sysfs class for SCST user "
++ "space handler");
++ res = PTR_ERR(dev_user_sysfs_class);
++ goto out_unreg;
++ }
++
++ dev_user_major = register_chrdev(0, DEV_USER_NAME, &dev_user_fops);
++ if (dev_user_major < 0) {
++ PRINT_ERROR("register_chrdev() failed: %d", res);
++ res = dev_user_major;
++ goto out_class;
++ }
++
++ dev = device_create(dev_user_sysfs_class, NULL,
++ MKDEV(dev_user_major, 0),
++ NULL,
++ DEV_USER_NAME);
++ if (IS_ERR(dev)) {
++ res = PTR_ERR(dev);
++ goto out_chrdev;
++ }
++
++ cleanup_thread = kthread_run(dev_user_cleanup_thread, NULL,
++ "scst_usr_cleanupd");
++ if (IS_ERR(cleanup_thread)) {
++ res = PTR_ERR(cleanup_thread);
++ PRINT_ERROR("kthread_create() failed: %d", res);
++ goto out_dev;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_dev:
++ device_destroy(dev_user_sysfs_class, MKDEV(dev_user_major, 0));
++
++out_chrdev:
++ unregister_chrdev(dev_user_major, DEV_USER_NAME);
++
++out_class:
++ class_destroy(dev_user_sysfs_class);
++
++out_unreg:
++ scst_unregister_dev_driver(&dev_user_devtype);
++
++out_cache1:
++ kmem_cache_destroy(user_get_cmd_cachep);
++
++out_cache:
++ kmem_cache_destroy(user_cmd_cachep);
++ goto out;
++}
++
++static void __exit exit_scst_user(void)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ rc = kthread_stop(cleanup_thread);
++ if (rc < 0)
++ TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
++
++ unregister_chrdev(dev_user_major, DEV_USER_NAME);
++ device_destroy(dev_user_sysfs_class, MKDEV(dev_user_major, 0));
++ class_destroy(dev_user_sysfs_class);
++
++ scst_unregister_virtual_dev_driver(&dev_user_devtype);
++
++ kmem_cache_destroy(user_get_cmd_cachep);
++ kmem_cache_destroy(user_cmd_cachep);
++
++ TRACE_EXIT();
++ return;
++}
++
++module_init(init_scst_user);
++module_exit(exit_scst_user);
++
++MODULE_AUTHOR("Vladislav Bolkhovitin");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("User space device handler for SCST");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_vdisk.c linux-2.6.36/drivers/scst/dev_handlers/scst_vdisk.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_vdisk.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_vdisk.c
+@@ -0,0 +1,4228 @@
++/*
++ * scst_vdisk.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 Ming Zhang <blackmagic02881 at gmail dot com>
++ * Copyright (C) 2007 Ross Walker <rswwalker at hotmail dot com>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI disk (type 0) and CDROM (type 5) dev handler using files
++ * on file systems or block devices (VDISK)
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/unistd.h>
++#include <linux/smp_lock.h>
++#include <linux/spinlock.h>
++#include <linux/init.h>
++#include <linux/uio.h>
++#include <linux/list.h>
++#include <linux/ctype.h>
++#include <linux/writeback.h>
++#include <linux/vmalloc.h>
++#include <asm/atomic.h>
++#include <linux/kthread.h>
++#include <linux/sched.h>
++#include <linux/version.h>
++#include <asm/div64.h>
++#include <asm/unaligned.h>
++#include <linux/slab.h>
++#include <linux/bio.h>
++
++#define LOG_PREFIX "dev_vdisk"
++
++#include <scst/scst.h>
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++#define TRACE_ORDER 0x80000000
++
++static struct scst_trace_log vdisk_local_trace_tbl[] = {
++ { TRACE_ORDER, "order" },
++ { 0, NULL }
++};
++#define trace_log_tbl vdisk_local_trace_tbl
++
++#define VDISK_TRACE_TLB_HELP ", order"
++
++#endif
++
++#include "scst_dev_handler.h"
++
++/* 8 byte ASCII Vendor */
++#define SCST_FIO_VENDOR "SCST_FIO"
++#define SCST_BIO_VENDOR "SCST_BIO"
++/* 4 byte ASCII Product Revision Level - left aligned */
++#define SCST_FIO_REV " 200"
++
++#define MAX_USN_LEN (20+1) /* For '\0' */
++
++#define INQ_BUF_SZ 128
++#define EVPD 0x01
++#define CMDDT 0x02
++
++#define MSENSE_BUF_SZ 256
++#define DBD 0x08 /* disable block descriptor */
++#define WP 0x80 /* write protect */
++#define DPOFUA 0x10 /* DPOFUA bit */
++#define WCE 0x04 /* write cache enable */
++
++#define PF 0x10 /* page format */
++#define SP 0x01 /* save pages */
++#define PS 0x80 /* parameter saveable */
++
++#define BYTE 8
++#define DEF_DISK_BLOCKSIZE_SHIFT 9
++#define DEF_DISK_BLOCKSIZE (1 << DEF_DISK_BLOCKSIZE_SHIFT)
++#define DEF_CDROM_BLOCKSIZE_SHIFT 11
++#define DEF_CDROM_BLOCKSIZE (1 << DEF_CDROM_BLOCKSIZE_SHIFT)
++#define DEF_SECTORS 56
++#define DEF_HEADS 255
++#define LEN_MEM (32 * 1024)
++#define DEF_RD_ONLY 0
++#define DEF_WRITE_THROUGH 0
++#define DEF_NV_CACHE 0
++#define DEF_O_DIRECT 0
++#define DEF_REMOVABLE 0
++
++#define VDISK_NULLIO_SIZE (3LL*1024*1024*1024*1024/2)
++
++#define DEF_TST SCST_CONTR_MODE_SEP_TASK_SETS
++/*
++ * Since we can't control backstorage device's reordering, we have to always
++ * report unrestricted reordering.
++ */
++#define DEF_QUEUE_ALG_WT SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER
++#define DEF_QUEUE_ALG SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER
++#define DEF_SWP 0
++#define DEF_TAS 0
++
++#define DEF_DSENSE SCST_CONTR_MODE_FIXED_SENSE
++
++static unsigned int random_values[256] = {
++ 9862592UL, 3744545211UL, 2348289082UL, 4036111983UL,
++ 435574201UL, 3110343764UL, 2383055570UL, 1826499182UL,
++ 4076766377UL, 1549935812UL, 3696752161UL, 1200276050UL,
++ 3878162706UL, 1783530428UL, 2291072214UL, 125807985UL,
++ 3407668966UL, 547437109UL, 3961389597UL, 969093968UL,
++ 56006179UL, 2591023451UL, 1849465UL, 1614540336UL,
++ 3699757935UL, 479961779UL, 3768703953UL, 2529621525UL,
++ 4157893312UL, 3673555386UL, 4091110867UL, 2193909423UL,
++ 2800464448UL, 3052113233UL, 450394455UL, 3424338713UL,
++ 2113709130UL, 4082064373UL, 3708640918UL, 3841182218UL,
++ 3141803315UL, 1032476030UL, 1166423150UL, 1169646901UL,
++ 2686611738UL, 575517645UL, 2829331065UL, 1351103339UL,
++ 2856560215UL, 2402488288UL, 867847666UL, 8524618UL,
++ 704790297UL, 2228765657UL, 231508411UL, 1425523814UL,
++ 2146764591UL, 1287631730UL, 4142687914UL, 3879884598UL,
++ 729945311UL, 310596427UL, 2263511876UL, 1983091134UL,
++ 3500916580UL, 1642490324UL, 3858376049UL, 695342182UL,
++ 780528366UL, 1372613640UL, 1100993200UL, 1314818946UL,
++ 572029783UL, 3775573540UL, 776262915UL, 2684520905UL,
++ 1007252738UL, 3505856396UL, 1974886670UL, 3115856627UL,
++ 4194842288UL, 2135793908UL, 3566210707UL, 7929775UL,
++ 1321130213UL, 2627281746UL, 3587067247UL, 2025159890UL,
++ 2587032000UL, 3098513342UL, 3289360258UL, 130594898UL,
++ 2258149812UL, 2275857755UL, 3966929942UL, 1521739999UL,
++ 4191192765UL, 958953550UL, 4153558347UL, 1011030335UL,
++ 524382185UL, 4099757640UL, 498828115UL, 2396978754UL,
++ 328688935UL, 826399828UL, 3174103611UL, 3921966365UL,
++ 2187456284UL, 2631406787UL, 3930669674UL, 4282803915UL,
++ 1776755417UL, 374959755UL, 2483763076UL, 844956392UL,
++ 2209187588UL, 3647277868UL, 291047860UL, 3485867047UL,
++ 2223103546UL, 2526736133UL, 3153407604UL, 3828961796UL,
++ 3355731910UL, 2322269798UL, 2752144379UL, 519897942UL,
++ 3430536488UL, 1801511593UL, 1953975728UL, 3286944283UL,
++ 1511612621UL, 1050133852UL, 409321604UL, 1037601109UL,
++ 3352316843UL, 4198371381UL, 617863284UL, 994672213UL,
++ 1540735436UL, 2337363549UL, 1242368492UL, 665473059UL,
++ 2330728163UL, 3443103219UL, 2291025133UL, 3420108120UL,
++ 2663305280UL, 1608969839UL, 2278959931UL, 1389747794UL,
++ 2226946970UL, 2131266900UL, 3856979144UL, 1894169043UL,
++ 2692697628UL, 3797290626UL, 3248126844UL, 3922786277UL,
++ 343705271UL, 3739749888UL, 2191310783UL, 2962488787UL,
++ 4119364141UL, 1403351302UL, 2984008923UL, 3822407178UL,
++ 1932139782UL, 2323869332UL, 2793574182UL, 1852626483UL,
++ 2722460269UL, 1136097522UL, 1005121083UL, 1805201184UL,
++ 2212824936UL, 2979547931UL, 4133075915UL, 2585731003UL,
++ 2431626071UL, 134370235UL, 3763236829UL, 1171434827UL,
++ 2251806994UL, 1289341038UL, 3616320525UL, 392218563UL,
++ 1544502546UL, 2993937212UL, 1957503701UL, 3579140080UL,
++ 4270846116UL, 2030149142UL, 1792286022UL, 366604999UL,
++ 2625579499UL, 790898158UL, 770833822UL, 815540197UL,
++ 2747711781UL, 3570468835UL, 3976195842UL, 1257621341UL,
++ 1198342980UL, 1860626190UL, 3247856686UL, 351473955UL,
++ 993440563UL, 340807146UL, 1041994520UL, 3573925241UL,
++ 480246395UL, 2104806831UL, 1020782793UL, 3362132583UL,
++ 2272911358UL, 3440096248UL, 2356596804UL, 259492703UL,
++ 3899500740UL, 252071876UL, 2177024041UL, 4284810959UL,
++ 2775999888UL, 2653420445UL, 2876046047UL, 1025771859UL,
++ 1994475651UL, 3564987377UL, 4112956647UL, 1821511719UL,
++ 3113447247UL, 455315102UL, 1585273189UL, 2311494568UL,
++ 774051541UL, 1898115372UL, 2637499516UL, 247231365UL,
++ 1475014417UL, 803585727UL, 3911097303UL, 1714292230UL,
++ 476579326UL, 2496900974UL, 3397613314UL, 341202244UL,
++ 807790202UL, 4221326173UL, 499979741UL, 1301488547UL,
++ 1056807896UL, 3525009458UL, 1174811641UL, 3049738746UL,
++};
++
++struct scst_vdisk_dev {
++ uint32_t block_size;
++ uint64_t nblocks;
++ int block_shift;
++ loff_t file_size; /* in bytes */
++
++ /*
++ * This lock can be taken on both SIRQ and thread context, but in
++ * all cases for each particular instance it's taken consistenly either
++ * on SIRQ or thread context. Mix of them is forbidden.
++ */
++ spinlock_t flags_lock;
++
++ /*
++ * Below flags are protected by flags_lock or suspended activity
++ * with scst_vdisk_mutex.
++ */
++ unsigned int rd_only:1;
++ unsigned int wt_flag:1;
++ unsigned int nv_cache:1;
++ unsigned int o_direct_flag:1;
++ unsigned int media_changed:1;
++ unsigned int prevent_allow_medium_removal:1;
++ unsigned int nullio:1;
++ unsigned int blockio:1;
++ unsigned int cdrom_empty:1;
++ unsigned int removable:1;
++
++ int virt_id;
++ char name[16+1]; /* Name of the virtual device,
++ must be <= SCSI Model + 1 */
++ char *filename; /* File name, protected by
++ scst_mutex and suspended activities */
++ uint16_t command_set_version;
++
++ /* All 4 protected by vdisk_serial_rwlock */
++ unsigned int t10_dev_id_set:1; /* true if t10_dev_id manually set */
++ unsigned int usn_set:1; /* true if usn manually set */
++ char t10_dev_id[16+8+2]; /* T10 device ID */
++ char usn[MAX_USN_LEN];
++
++ struct scst_device *dev;
++ struct list_head vdev_list_entry;
++
++ struct scst_dev_type *vdev_devt;
++};
++
++struct scst_vdisk_thr {
++ struct scst_thr_data_hdr hdr;
++ struct file *fd;
++ struct block_device *bdev;
++ struct iovec *iv;
++ int iv_count;
++};
++
++/* Context RA patch supposed to be applied on the kernel */
++#define DEF_NUM_THREADS 8
++static int num_threads = DEF_NUM_THREADS;
++
++module_param_named(num_threads, num_threads, int, S_IRUGO);
++MODULE_PARM_DESC(num_threads, "vdisk threads count");
++
++static int vdisk_attach(struct scst_device *dev);
++static void vdisk_detach(struct scst_device *dev);
++static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev);
++static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev);
++static int vdisk_parse(struct scst_cmd *);
++static int vdisk_do_job(struct scst_cmd *cmd);
++static int vcdrom_parse(struct scst_cmd *);
++static int vcdrom_exec(struct scst_cmd *cmd);
++static void vdisk_exec_read(struct scst_cmd *cmd,
++ struct scst_vdisk_thr *thr, loff_t loff);
++static void vdisk_exec_write(struct scst_cmd *cmd,
++ struct scst_vdisk_thr *thr, loff_t loff);
++static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
++ u64 lba_start, int write);
++static int blockio_flush(struct block_device *bdev);
++static void vdisk_exec_verify(struct scst_cmd *cmd,
++ struct scst_vdisk_thr *thr, loff_t loff);
++static void vdisk_exec_read_capacity(struct scst_cmd *cmd);
++static void vdisk_exec_read_capacity16(struct scst_cmd *cmd);
++static void vdisk_exec_inquiry(struct scst_cmd *cmd);
++static void vdisk_exec_request_sense(struct scst_cmd *cmd);
++static void vdisk_exec_mode_sense(struct scst_cmd *cmd);
++static void vdisk_exec_mode_select(struct scst_cmd *cmd);
++static void vdisk_exec_log(struct scst_cmd *cmd);
++static void vdisk_exec_read_toc(struct scst_cmd *cmd);
++static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd);
++static int vdisk_fsync(struct scst_vdisk_thr *thr, loff_t loff,
++ loff_t len, struct scst_cmd *cmd, struct scst_device *dev);
++static ssize_t vdisk_add_fileio_device(const char *device_name, char *params);
++static ssize_t vdisk_add_blockio_device(const char *device_name, char *params);
++static ssize_t vdisk_add_nullio_device(const char *device_name, char *params);
++static ssize_t vdisk_del_device(const char *device_name);
++static ssize_t vcdrom_add_device(const char *device_name, char *params);
++static ssize_t vcdrom_del_device(const char *device_name);
++static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
++ struct scst_tgt_dev *tgt_dev);
++static uint64_t vdisk_gen_dev_id_num(const char *virt_dev_name);
++
++/** SYSFS **/
++
++static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdisk_sysfs_blocksize_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdisk_sysfs_rd_only_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdisk_sysfs_wt_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdisk_sysfs_nv_cache_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdisk_sysfs_o_direct_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdisk_sysfs_resync_size_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count);
++static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count);
++static ssize_t vdev_sysfs_t10_dev_id_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++static ssize_t vdev_sysfs_usn_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count);
++static ssize_t vdev_sysfs_usn_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++
++static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count);
++
++static struct kobj_attribute vdev_size_attr =
++ __ATTR(size_mb, S_IRUGO, vdev_sysfs_size_show, NULL);
++static struct kobj_attribute vdisk_blocksize_attr =
++ __ATTR(blocksize, S_IRUGO, vdisk_sysfs_blocksize_show, NULL);
++static struct kobj_attribute vdisk_rd_only_attr =
++ __ATTR(read_only, S_IRUGO, vdisk_sysfs_rd_only_show, NULL);
++static struct kobj_attribute vdisk_wt_attr =
++ __ATTR(write_through, S_IRUGO, vdisk_sysfs_wt_show, NULL);
++static struct kobj_attribute vdisk_nv_cache_attr =
++ __ATTR(nv_cache, S_IRUGO, vdisk_sysfs_nv_cache_show, NULL);
++static struct kobj_attribute vdisk_o_direct_attr =
++ __ATTR(o_direct, S_IRUGO, vdisk_sysfs_o_direct_show, NULL);
++static struct kobj_attribute vdisk_removable_attr =
++ __ATTR(removable, S_IRUGO, vdisk_sysfs_removable_show, NULL);
++static struct kobj_attribute vdisk_filename_attr =
++ __ATTR(filename, S_IRUGO, vdev_sysfs_filename_show, NULL);
++static struct kobj_attribute vdisk_resync_size_attr =
++ __ATTR(resync_size, S_IWUSR, NULL, vdisk_sysfs_resync_size_store);
++static struct kobj_attribute vdev_t10_dev_id_attr =
++ __ATTR(t10_dev_id, S_IWUSR|S_IRUGO, vdev_sysfs_t10_dev_id_show,
++ vdev_sysfs_t10_dev_id_store);
++static struct kobj_attribute vdev_usn_attr =
++ __ATTR(usn, S_IWUSR|S_IRUGO, vdev_sysfs_usn_show, vdev_sysfs_usn_store);
++
++static struct kobj_attribute vcdrom_filename_attr =
++ __ATTR(filename, S_IRUGO|S_IWUSR, vdev_sysfs_filename_show,
++ vcdrom_sysfs_filename_store);
++
++static const struct attribute *vdisk_fileio_attrs[] = {
++ &vdev_size_attr.attr,
++ &vdisk_blocksize_attr.attr,
++ &vdisk_rd_only_attr.attr,
++ &vdisk_wt_attr.attr,
++ &vdisk_nv_cache_attr.attr,
++ &vdisk_o_direct_attr.attr,
++ &vdisk_removable_attr.attr,
++ &vdisk_filename_attr.attr,
++ &vdisk_resync_size_attr.attr,
++ &vdev_t10_dev_id_attr.attr,
++ &vdev_usn_attr.attr,
++ NULL,
++};
++
++static const struct attribute *vdisk_blockio_attrs[] = {
++ &vdev_size_attr.attr,
++ &vdisk_blocksize_attr.attr,
++ &vdisk_rd_only_attr.attr,
++ &vdisk_nv_cache_attr.attr,
++ &vdisk_removable_attr.attr,
++ &vdisk_filename_attr.attr,
++ &vdisk_resync_size_attr.attr,
++ &vdev_t10_dev_id_attr.attr,
++ &vdev_usn_attr.attr,
++ NULL,
++};
++
++static const struct attribute *vdisk_nullio_attrs[] = {
++ &vdev_size_attr.attr,
++ &vdisk_blocksize_attr.attr,
++ &vdisk_rd_only_attr.attr,
++ &vdisk_removable_attr.attr,
++ &vdev_t10_dev_id_attr.attr,
++ &vdev_usn_attr.attr,
++ NULL,
++};
++
++static const struct attribute *vcdrom_attrs[] = {
++ &vdev_size_attr.attr,
++ &vcdrom_filename_attr.attr,
++ &vdev_t10_dev_id_attr.attr,
++ &vdev_usn_attr.attr,
++ NULL,
++};
++
++/* Protects vdisks addition/deletion and related activities, like search */
++static DEFINE_MUTEX(scst_vdisk_mutex);
++
++/* Protects devices t10_dev_id and usn */
++static DEFINE_RWLOCK(vdisk_serial_rwlock);
++
++/* Protected by scst_vdisk_mutex */
++static LIST_HEAD(vdev_list);
++
++static struct kmem_cache *vdisk_thr_cachep;
++
++/*
++ * Be careful changing "name" field, since it is the name of the corresponding
++ * /sys/kernel/scst_tgt entry, hence a part of user space ABI.
++ */
++
++static struct scst_dev_type vdisk_file_devtype = {
++ .name = "vdisk_fileio",
++ .type = TYPE_DISK,
++ .exec_sync = 1,
++ .threads_num = -1,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = vdisk_attach,
++ .detach = vdisk_detach,
++ .attach_tgt = vdisk_attach_tgt,
++ .detach_tgt = vdisk_detach_tgt,
++ .parse = vdisk_parse,
++ .exec = vdisk_do_job,
++ .task_mgmt_fn = vdisk_task_mgmt_fn,
++ .add_device = vdisk_add_fileio_device,
++ .del_device = vdisk_del_device,
++ .dev_attrs = vdisk_fileio_attrs,
++ .add_device_parameters = "filename, blocksize, write_through, "
++ "nv_cache, o_direct, read_only, removable",
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++ .trace_tbl = vdisk_local_trace_tbl,
++ .trace_tbl_help = VDISK_TRACE_TLB_HELP,
++#endif
++};
++
++static struct kmem_cache *blockio_work_cachep;
++
++static struct scst_dev_type vdisk_blk_devtype = {
++ .name = "vdisk_blockio",
++ .type = TYPE_DISK,
++ .threads_num = 1,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = vdisk_attach,
++ .detach = vdisk_detach,
++ .attach_tgt = vdisk_attach_tgt,
++ .detach_tgt = vdisk_detach_tgt,
++ .parse = vdisk_parse,
++ .exec = vdisk_do_job,
++ .task_mgmt_fn = vdisk_task_mgmt_fn,
++ .add_device = vdisk_add_blockio_device,
++ .del_device = vdisk_del_device,
++ .dev_attrs = vdisk_blockio_attrs,
++ .add_device_parameters = "filename, blocksize, nv_cache, read_only, "
++ "removable",
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++ .trace_tbl = vdisk_local_trace_tbl,
++ .trace_tbl_help = VDISK_TRACE_TLB_HELP,
++#endif
++};
++
++static struct scst_dev_type vdisk_null_devtype = {
++ .name = "vdisk_nullio",
++ .type = TYPE_DISK,
++ .threads_num = 0,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = vdisk_attach,
++ .detach = vdisk_detach,
++ .attach_tgt = vdisk_attach_tgt,
++ .detach_tgt = vdisk_detach_tgt,
++ .parse = vdisk_parse,
++ .exec = vdisk_do_job,
++ .task_mgmt_fn = vdisk_task_mgmt_fn,
++ .add_device = vdisk_add_nullio_device,
++ .del_device = vdisk_del_device,
++ .dev_attrs = vdisk_nullio_attrs,
++ .add_device_parameters = "blocksize, read_only, removable",
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++ .trace_tbl = vdisk_local_trace_tbl,
++ .trace_tbl_help = VDISK_TRACE_TLB_HELP,
++#endif
++};
++
++static struct scst_dev_type vcdrom_devtype = {
++ .name = "vcdrom",
++ .type = TYPE_ROM,
++ .exec_sync = 1,
++ .threads_num = -1,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = vdisk_attach,
++ .detach = vdisk_detach,
++ .attach_tgt = vdisk_attach_tgt,
++ .detach_tgt = vdisk_detach_tgt,
++ .parse = vcdrom_parse,
++ .exec = vcdrom_exec,
++ .task_mgmt_fn = vdisk_task_mgmt_fn,
++ .add_device = vcdrom_add_device,
++ .del_device = vcdrom_del_device,
++ .dev_attrs = vcdrom_attrs,
++ .add_device_parameters = NULL,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++ .trace_tbl = vdisk_local_trace_tbl,
++ .trace_tbl_help = VDISK_TRACE_TLB_HELP,
++#endif
++};
++
++static struct scst_vdisk_thr nullio_thr_data;
++
++static const char *vdev_get_filename(const struct scst_vdisk_dev *virt_dev)
++{
++ if (virt_dev->filename != NULL)
++ return virt_dev->filename;
++ else
++ return "none";
++}
++
++/* Returns fd, use IS_ERR(fd) to get error status */
++static struct file *vdev_open_fd(const struct scst_vdisk_dev *virt_dev)
++{
++ int open_flags = 0;
++ struct file *fd;
++
++ TRACE_ENTRY();
++
++ if (virt_dev->dev->rd_only)
++ open_flags |= O_RDONLY;
++ else
++ open_flags |= O_RDWR;
++ if (virt_dev->o_direct_flag)
++ open_flags |= O_DIRECT;
++ if (virt_dev->wt_flag && !virt_dev->nv_cache)
++ open_flags |= O_SYNC;
++ TRACE_DBG("Opening file %s, flags 0x%x",
++ virt_dev->filename, open_flags);
++ fd = filp_open(virt_dev->filename, O_LARGEFILE | open_flags, 0600);
++
++ TRACE_EXIT();
++ return fd;
++}
++
++static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev)
++{
++ struct inode *inode;
++ struct file *fd;
++
++ TRACE_ENTRY();
++
++ if (!virt_dev->blockio || virt_dev->rd_only || virt_dev->nv_cache)
++ goto out;
++
++ fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600);
++ if (IS_ERR(fd)) {
++ PRINT_ERROR("filp_open(%s) returned error %ld",
++ virt_dev->filename, PTR_ERR(fd));
++ goto out;
++ }
++
++ inode = fd->f_dentry->d_inode;
++
++ if (!S_ISBLK(inode->i_mode)) {
++ PRINT_ERROR("%s is NOT a block device", virt_dev->filename);
++ goto out_close;
++ }
++
++ if (blockio_flush(inode->i_bdev) != 0) {
++ PRINT_WARNING("Device %s doesn't support barriers, switching "
++ "to NV_CACHE mode. Read README for more details.",
++ virt_dev->filename);
++ virt_dev->nv_cache = 1;
++ }
++
++out_close:
++ filp_close(fd, NULL);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Returns 0 on success and file size in *file_size, error code otherwise */
++static int vdisk_get_file_size(const char *filename, bool blockio,
++ loff_t *file_size)
++{
++ struct inode *inode;
++ int res = 0;
++ struct file *fd;
++
++ TRACE_ENTRY();
++
++ *file_size = 0;
++
++ fd = filp_open(filename, O_LARGEFILE | O_RDONLY, 0600);
++ if (IS_ERR(fd)) {
++ res = PTR_ERR(fd);
++ PRINT_ERROR("filp_open(%s) returned error %d", filename, res);
++ goto out;
++ }
++
++ inode = fd->f_dentry->d_inode;
++
++ if (blockio && !S_ISBLK(inode->i_mode)) {
++ PRINT_ERROR("File %s is NOT a block device", filename);
++ res = -EINVAL;
++ goto out_close;
++ }
++
++ if (S_ISREG(inode->i_mode))
++ /* Nothing to do */;
++ else if (S_ISBLK(inode->i_mode))
++ inode = inode->i_bdev->bd_inode;
++ else {
++ res = -EINVAL;
++ goto out_close;
++ }
++
++ *file_size = inode->i_size;
++
++out_close:
++ filp_close(fd, NULL);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int vdisk_attach(struct scst_device *dev)
++{
++ int res = 0;
++ loff_t err;
++ struct scst_vdisk_dev *virt_dev = NULL, *vv;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("virt_id %d (%s)", dev->virt_id, dev->virt_name);
++
++ if (dev->virt_id == 0) {
++ PRINT_ERROR("%s", "Not a virtual device");
++ res = -EINVAL;
++ goto out;
++ }
++
++ /*
++ * scst_vdisk_mutex must be already taken before
++ * scst_register_virtual_device()
++ */
++ list_for_each_entry(vv, &vdev_list, vdev_list_entry) {
++ if (strcmp(vv->name, dev->virt_name) == 0) {
++ virt_dev = vv;
++ break;
++ }
++ }
++
++ if (virt_dev == NULL) {
++ PRINT_ERROR("Device %s not found", dev->virt_name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ virt_dev->dev = dev;
++
++ dev->rd_only = virt_dev->rd_only;
++
++ if (!virt_dev->cdrom_empty) {
++ if (virt_dev->nullio)
++ err = VDISK_NULLIO_SIZE;
++ else {
++ res = vdisk_get_file_size(virt_dev->filename,
++ virt_dev->blockio, &err);
++ if (res != 0)
++ goto out;
++ }
++ virt_dev->file_size = err;
++
++ TRACE_DBG("size of file: %lld", (long long unsigned int)err);
++
++ vdisk_blockio_check_flush_support(virt_dev);
++ } else
++ virt_dev->file_size = 0;
++
++ virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
++
++ if (!virt_dev->cdrom_empty) {
++ PRINT_INFO("Attached SCSI target virtual %s %s "
++ "(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld,"
++ " cyln=%lld%s)",
++ (dev->type == TYPE_DISK) ? "disk" : "cdrom",
++ virt_dev->name, vdev_get_filename(virt_dev),
++ virt_dev->file_size >> 20, virt_dev->block_size,
++ (long long unsigned int)virt_dev->nblocks,
++ (long long unsigned int)virt_dev->nblocks/64/32,
++ virt_dev->nblocks < 64*32
++ ? " !WARNING! cyln less than 1" : "");
++ } else {
++ PRINT_INFO("Attached empty SCSI target virtual cdrom %s",
++ virt_dev->name);
++ }
++
++ dev->dh_priv = virt_dev;
++
++ dev->tst = DEF_TST;
++ dev->d_sense = DEF_DSENSE;
++ if (virt_dev->wt_flag && !virt_dev->nv_cache)
++ dev->queue_alg = DEF_QUEUE_ALG_WT;
++ else
++ dev->queue_alg = DEF_QUEUE_ALG;
++ dev->swp = DEF_SWP;
++ dev->tas = DEF_TAS;
++
++out:
++ TRACE_EXIT();
++ return res;
++}
++
++/* scst_mutex supposed to be held */
++static void vdisk_detach(struct scst_device *dev)
++{
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)dev->dh_priv;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("virt_id %d", dev->virt_id);
++
++ PRINT_INFO("Detached virtual device %s (\"%s\")",
++ virt_dev->name, vdev_get_filename(virt_dev));
++
++ /* virt_dev will be freed by the caller */
++ dev->dh_priv = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++static void vdisk_free_thr_data(struct scst_thr_data_hdr *d)
++{
++ struct scst_vdisk_thr *thr =
++ container_of(d, struct scst_vdisk_thr, hdr);
++
++ TRACE_ENTRY();
++
++ if (thr->fd)
++ filp_close(thr->fd, NULL);
++
++ kfree(thr->iv);
++
++ kmem_cache_free(vdisk_thr_cachep, thr);
++
++ TRACE_EXIT();
++ return;
++}
++
++static struct scst_vdisk_thr *vdisk_init_thr_data(
++ struct scst_tgt_dev *tgt_dev)
++{
++ struct scst_vdisk_thr *res;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)tgt_dev->dev->dh_priv;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(virt_dev->nullio);
++
++ res = kmem_cache_zalloc(vdisk_thr_cachep, GFP_KERNEL);
++ if (res == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Unable to allocate struct "
++ "scst_vdisk_thr");
++ goto out;
++ }
++
++ if (!virt_dev->cdrom_empty) {
++ res->fd = vdev_open_fd(virt_dev);
++ if (IS_ERR(res->fd)) {
++ PRINT_ERROR("filp_open(%s) returned an error %ld",
++ virt_dev->filename, PTR_ERR(res->fd));
++ goto out_free;
++ }
++ if (virt_dev->blockio)
++ res->bdev = res->fd->f_dentry->d_inode->i_bdev;
++ else
++ res->bdev = NULL;
++ } else
++ res->fd = NULL;
++
++ scst_add_thr_data(tgt_dev, &res->hdr, vdisk_free_thr_data);
++
++out:
++ TRACE_EXIT_HRES((unsigned long)res);
++ return res;
++
++out_free:
++ kmem_cache_free(vdisk_thr_cachep, res);
++ res = NULL;
++ goto out;
++}
++
++static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /* Nothing to do */
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev)
++{
++ TRACE_ENTRY();
++
++ scst_del_all_thr_data(tgt_dev);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int vdisk_do_job(struct scst_cmd *cmd)
++{
++ int rc, res;
++ uint64_t lba_start = 0;
++ loff_t data_len = 0;
++ uint8_t *cdb = cmd->cdb;
++ int opcode = cdb[0];
++ loff_t loff;
++ struct scst_device *dev = cmd->dev;
++ struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)dev->dh_priv;
++ struct scst_thr_data_hdr *d;
++ struct scst_vdisk_thr *thr = NULL;
++ int fua = 0;
++
++ TRACE_ENTRY();
++
++ switch (cmd->queue_type) {
++ case SCST_CMD_QUEUE_ORDERED:
++ TRACE(TRACE_ORDER, "ORDERED cmd %p (op %x)", cmd, cmd->cdb[0]);
++ break;
++ case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
++ TRACE(TRACE_ORDER, "HQ cmd %p (op %x)", cmd, cmd->cdb[0]);
++ break;
++ default:
++ break;
++ }
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++
++ if (!virt_dev->nullio) {
++ d = scst_find_thr_data(tgt_dev);
++ if (unlikely(d == NULL)) {
++ thr = vdisk_init_thr_data(tgt_dev);
++ if (thr == NULL) {
++ scst_set_busy(cmd);
++ goto out_compl;
++ }
++ scst_thr_data_get(&thr->hdr);
++ } else
++ thr = container_of(d, struct scst_vdisk_thr, hdr);
++ } else {
++ thr = &nullio_thr_data;
++ scst_thr_data_get(&thr->hdr);
++ }
++
++ switch (opcode) {
++ case READ_6:
++ case WRITE_6:
++ case VERIFY_6:
++ lba_start = (((cdb[1] & 0x1f) << (BYTE * 2)) +
++ (cdb[2] << (BYTE * 1)) +
++ (cdb[3] << (BYTE * 0)));
++ data_len = cmd->bufflen;
++ break;
++ case READ_10:
++ case READ_12:
++ case WRITE_10:
++ case WRITE_12:
++ case VERIFY:
++ case WRITE_VERIFY:
++ case WRITE_VERIFY_12:
++ case VERIFY_12:
++ lba_start |= ((u64)cdb[2]) << 24;
++ lba_start |= ((u64)cdb[3]) << 16;
++ lba_start |= ((u64)cdb[4]) << 8;
++ lba_start |= ((u64)cdb[5]);
++ data_len = cmd->bufflen;
++ break;
++ case READ_16:
++ case WRITE_16:
++ case WRITE_VERIFY_16:
++ case VERIFY_16:
++ lba_start |= ((u64)cdb[2]) << 56;
++ lba_start |= ((u64)cdb[3]) << 48;
++ lba_start |= ((u64)cdb[4]) << 40;
++ lba_start |= ((u64)cdb[5]) << 32;
++ lba_start |= ((u64)cdb[6]) << 24;
++ lba_start |= ((u64)cdb[7]) << 16;
++ lba_start |= ((u64)cdb[8]) << 8;
++ lba_start |= ((u64)cdb[9]);
++ data_len = cmd->bufflen;
++ break;
++ case SYNCHRONIZE_CACHE:
++ lba_start |= ((u64)cdb[2]) << 24;
++ lba_start |= ((u64)cdb[3]) << 16;
++ lba_start |= ((u64)cdb[4]) << 8;
++ lba_start |= ((u64)cdb[5]);
++ data_len = ((cdb[7] << (BYTE * 1)) + (cdb[8] << (BYTE * 0)))
++ << virt_dev->block_shift;
++ if (data_len == 0)
++ data_len = virt_dev->file_size -
++ ((loff_t)lba_start << virt_dev->block_shift);
++ break;
++ }
++
++ loff = (loff_t)lba_start << virt_dev->block_shift;
++ TRACE_DBG("cmd %p, lba_start %lld, loff %lld, data_len %lld", cmd,
++ (long long unsigned int)lba_start,
++ (long long unsigned int)loff,
++ (long long unsigned int)data_len);
++ if (unlikely(loff < 0) || unlikely(data_len < 0) ||
++ unlikely((loff + data_len) > virt_dev->file_size)) {
++ PRINT_INFO("Access beyond the end of the device "
++ "(%lld of %lld, len %lld)",
++ (long long unsigned int)loff,
++ (long long unsigned int)virt_dev->file_size,
++ (long long unsigned int)data_len);
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_block_out_range_error));
++ goto out_compl;
++ }
++
++ switch (opcode) {
++ case WRITE_10:
++ case WRITE_12:
++ case WRITE_16:
++ fua = (cdb[1] & 0x8);
++ if (fua) {
++ TRACE(TRACE_ORDER, "FUA: loff=%lld, "
++ "data_len=%lld", (long long unsigned int)loff,
++ (long long unsigned int)data_len);
++ }
++ break;
++ }
++
++ switch (opcode) {
++ case READ_6:
++ case READ_10:
++ case READ_12:
++ case READ_16:
++ if (virt_dev->blockio) {
++ blockio_exec_rw(cmd, thr, lba_start, 0);
++ goto out_thr;
++ } else
++ vdisk_exec_read(cmd, thr, loff);
++ break;
++ case WRITE_6:
++ case WRITE_10:
++ case WRITE_12:
++ case WRITE_16:
++ {
++ if (virt_dev->blockio) {
++ blockio_exec_rw(cmd, thr, lba_start, 1);
++ goto out_thr;
++ } else
++ vdisk_exec_write(cmd, thr, loff);
++ /* O_SYNC flag is used for WT devices */
++ if (fua)
++ vdisk_fsync(thr, loff, data_len, cmd, dev);
++ break;
++ }
++ case WRITE_VERIFY:
++ case WRITE_VERIFY_12:
++ case WRITE_VERIFY_16:
++ {
++ /* ToDo: BLOCKIO VERIFY */
++ vdisk_exec_write(cmd, thr, loff);
++ /* O_SYNC flag is used for WT devices */
++ if (scsi_status_is_good(cmd->status))
++ vdisk_exec_verify(cmd, thr, loff);
++ break;
++ }
++ case SYNCHRONIZE_CACHE:
++ {
++ int immed = cdb[1] & 0x2;
++ TRACE(TRACE_ORDER, "SYNCHRONIZE_CACHE: "
++ "loff=%lld, data_len=%lld, immed=%d",
++ (long long unsigned int)loff,
++ (long long unsigned int)data_len, immed);
++ if (immed) {
++ scst_cmd_get(cmd); /* to protect dev */
++ cmd->completed = 1;
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT,
++ SCST_CONTEXT_SAME);
++ vdisk_fsync(thr, loff, data_len, NULL, dev);
++ /* ToDo: vdisk_fsync() error processing */
++ scst_cmd_put(cmd);
++ goto out_thr;
++ } else {
++ vdisk_fsync(thr, loff, data_len, cmd, dev);
++ break;
++ }
++ }
++ case VERIFY_6:
++ case VERIFY:
++ case VERIFY_12:
++ case VERIFY_16:
++ vdisk_exec_verify(cmd, thr, loff);
++ break;
++ case MODE_SENSE:
++ case MODE_SENSE_10:
++ vdisk_exec_mode_sense(cmd);
++ break;
++ case MODE_SELECT:
++ case MODE_SELECT_10:
++ vdisk_exec_mode_select(cmd);
++ break;
++ case LOG_SELECT:
++ case LOG_SENSE:
++ vdisk_exec_log(cmd);
++ break;
++ case ALLOW_MEDIUM_REMOVAL:
++ vdisk_exec_prevent_allow_medium_removal(cmd);
++ break;
++ case READ_TOC:
++ vdisk_exec_read_toc(cmd);
++ break;
++ case START_STOP:
++ vdisk_fsync(thr, 0, virt_dev->file_size, cmd, dev);
++ break;
++ case RESERVE:
++ case RESERVE_10:
++ case RELEASE:
++ case RELEASE_10:
++ case TEST_UNIT_READY:
++ break;
++ case INQUIRY:
++ vdisk_exec_inquiry(cmd);
++ break;
++ case REQUEST_SENSE:
++ vdisk_exec_request_sense(cmd);
++ break;
++ case READ_CAPACITY:
++ vdisk_exec_read_capacity(cmd);
++ break;
++ case SERVICE_ACTION_IN:
++ if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
++ vdisk_exec_read_capacity16(cmd);
++ break;
++ }
++ /* else go through */
++ case REPORT_LUNS:
++ default:
++ TRACE_DBG("Invalid opcode %d", opcode);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ }
++
++out_compl:
++ cmd->completed = 1;
++
++out_done:
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++
++out_thr:
++ if (likely(thr != NULL))
++ scst_thr_data_put(&thr->hdr);
++
++ res = SCST_EXEC_COMPLETED;
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int vdisk_get_block_shift(struct scst_cmd *cmd)
++{
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ return virt_dev->block_shift;
++}
++
++static int vdisk_parse(struct scst_cmd *cmd)
++{
++ scst_sbc_generic_parse(cmd, vdisk_get_block_shift);
++ return SCST_CMD_STATE_DEFAULT;
++}
++
++static int vcdrom_parse(struct scst_cmd *cmd)
++{
++ scst_cdrom_generic_parse(cmd, vdisk_get_block_shift);
++ return SCST_CMD_STATE_DEFAULT;
++}
++
++static int vcdrom_exec(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_COMPLETED;
++ int opcode = cmd->cdb[0];
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++
++ TRACE_ENTRY();
++
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++
++ if (virt_dev->cdrom_empty && (opcode != INQUIRY)) {
++ TRACE_DBG("%s", "CDROM empty");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_not_ready));
++ goto out_done;
++ }
++
++ if (virt_dev->media_changed && scst_is_ua_command(cmd)) {
++ spin_lock(&virt_dev->flags_lock);
++ if (virt_dev->media_changed) {
++ virt_dev->media_changed = 0;
++ TRACE_DBG("%s", "Reporting media changed");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_medium_changed_UA));
++ spin_unlock(&virt_dev->flags_lock);
++ goto out_done;
++ }
++ spin_unlock(&virt_dev->flags_lock);
++ }
++
++ res = vdisk_do_job(cmd);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_done:
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++ goto out;
++}
++
++static uint64_t vdisk_gen_dev_id_num(const char *virt_dev_name)
++{
++ unsigned int dev_id_num, i;
++
++ for (dev_id_num = 0, i = 0; i < strlen(virt_dev_name); i++) {
++ unsigned int rv = random_values[(int)(virt_dev_name[i])];
++ /* Do some rotating of the bits */
++ dev_id_num ^= ((rv << i) | (rv >> (32 - i)));
++ }
++
++ return ((uint64_t)scst_get_setup_id() << 32) | dev_id_num;
++}
++
++static void vdisk_exec_inquiry(struct scst_cmd *cmd)
++{
++ int32_t length, i, resp_len = 0;
++ uint8_t *address;
++ uint8_t *buf;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++
++ /* ToDo: Performance Boost:
++ * 1. remove kzalloc, buf
++ * 2. do all checks before touching *address
++ * 3. zero *address
++ * 4. write directly to *address
++ */
++
++ TRACE_ENTRY();
++
++ buf = kzalloc(INQ_BUF_SZ, GFP_KERNEL);
++ if (buf == NULL) {
++ scst_set_busy(cmd);
++ goto out;
++ }
++
++ length = scst_get_buf_first(cmd, &address);
++ TRACE_DBG("length %d", length);
++ if (unlikely(length <= 0)) {
++ if (length < 0) {
++ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ goto out_free;
++ }
++
++ if (cmd->cdb[1] & CMDDT) {
++ TRACE_DBG("%s", "INQUIRY: CMDDT is unsupported");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_put;
++ }
++
++ buf[0] = cmd->dev->type; /* type dev */
++ if (virt_dev->removable)
++ buf[1] = 0x80; /* removable */
++ /* Vital Product */
++ if (cmd->cdb[1] & EVPD) {
++ if (0 == cmd->cdb[2]) {
++ /* supported vital product data pages */
++ buf[3] = 3;
++ buf[4] = 0x0; /* this page */
++ buf[5] = 0x80; /* unit serial number */
++ buf[6] = 0x83; /* device identification */
++ if (virt_dev->dev->type == TYPE_DISK) {
++ buf[3] += 1;
++ buf[7] = 0xB0; /* block limits */
++ }
++ resp_len = buf[3] + 4;
++ } else if (0x80 == cmd->cdb[2]) {
++ /* unit serial number */
++ int usn_len;
++ read_lock(&vdisk_serial_rwlock);
++ usn_len = strlen(virt_dev->usn);
++ buf[1] = 0x80;
++ buf[3] = usn_len;
++ strncpy(&buf[4], virt_dev->usn, usn_len);
++ read_unlock(&vdisk_serial_rwlock);
++ resp_len = buf[3] + 4;
++ } else if (0x83 == cmd->cdb[2]) {
++ /* device identification */
++ int num = 4;
++
++ buf[1] = 0x83;
++ /* T10 vendor identifier field format (faked) */
++ buf[num + 0] = 0x2; /* ASCII */
++ buf[num + 1] = 0x1; /* Vendor ID */
++ if (virt_dev->blockio)
++ memcpy(&buf[num + 4], SCST_BIO_VENDOR, 8);
++ else
++ memcpy(&buf[num + 4], SCST_FIO_VENDOR, 8);
++
++ read_lock(&vdisk_serial_rwlock);
++ i = strlen(virt_dev->t10_dev_id);
++ memcpy(&buf[num + 12], virt_dev->t10_dev_id, i);
++ read_unlock(&vdisk_serial_rwlock);
++
++ buf[num + 3] = 8 + i;
++ num += buf[num + 3];
++
++ num += 4;
++
++ /*
++ * Relative target port identifier
++ */
++ buf[num + 0] = 0x01; /* binary */
++ /* Relative target port id */
++ buf[num + 1] = 0x10 | 0x04;
++
++ put_unaligned(cpu_to_be16(cmd->tgt->rel_tgt_id),
++ (__be16 *)&buf[num + 4 + 2]);
++
++ buf[num + 3] = 4;
++ num += buf[num + 3];
++
++ num += 4;
++
++ /*
++ * IEEE id
++ */
++ buf[num + 0] = 0x01; /* binary */
++
++ /* EUI-64 */
++ buf[num + 1] = 0x02;
++ buf[num + 2] = 0x00;
++ buf[num + 3] = 0x08;
++
++ /* IEEE id */
++ buf[num + 4] = virt_dev->t10_dev_id[0];
++ buf[num + 5] = virt_dev->t10_dev_id[1];
++ buf[num + 6] = virt_dev->t10_dev_id[2];
++
++ /* IEEE ext id */
++ buf[num + 7] = virt_dev->t10_dev_id[3];
++ buf[num + 8] = virt_dev->t10_dev_id[4];
++ buf[num + 9] = virt_dev->t10_dev_id[5];
++ buf[num + 10] = virt_dev->t10_dev_id[6];
++ buf[num + 11] = virt_dev->t10_dev_id[7];
++ num += buf[num + 3];
++
++ resp_len = num;
++ buf[2] = (resp_len >> 8) & 0xFF;
++ buf[3] = resp_len & 0xFF;
++ resp_len += 4;
++ } else if ((0xB0 == cmd->cdb[2]) &&
++ (virt_dev->dev->type == TYPE_DISK)) {
++ /* block limits */
++ int max_transfer;
++ buf[1] = 0xB0;
++ buf[3] = 0x1C;
++ /* Optimal transfer granuality is PAGE_SIZE */
++ put_unaligned(cpu_to_be16(max_t(int,
++ PAGE_SIZE/virt_dev->block_size, 1)),
++ (uint16_t *)&buf[6]);
++ /* Max transfer len is min of sg limit and 8M */
++ max_transfer = min_t(int,
++ cmd->tgt_dev->max_sg_cnt << PAGE_SHIFT,
++ 8*1024*1024) / virt_dev->block_size;
++ put_unaligned(cpu_to_be32(max_transfer),
++ (uint32_t *)&buf[8]);
++ /*
++ * Let's have optimal transfer len 1MB. Better to not
++ * set it at all, because we don't have such limit,
++ * but some initiators may not understand that (?).
++ * From other side, too big transfers are not optimal,
++ * because SGV cache supports only <4M buffers.
++ */
++ put_unaligned(cpu_to_be32(min_t(int,
++ max_transfer,
++ 1*1024*1024 / virt_dev->block_size)),
++ (uint32_t *)&buf[12]);
++ resp_len = buf[3] + 4;
++ } else {
++ TRACE_DBG("INQUIRY: Unsupported EVPD page %x",
++ cmd->cdb[2]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_put;
++ }
++ } else {
++ int len, num;
++
++ if (cmd->cdb[2] != 0) {
++ TRACE_DBG("INQUIRY: Unsupported page %x", cmd->cdb[2]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_put;
++ }
++
++ buf[2] = 5; /* Device complies to SPC-3 */
++ buf[3] = 0x12; /* HiSup + data in format specified in SPC */
++ buf[4] = 31;/* n - 4 = 35 - 4 = 31 for full 36 byte data */
++ buf[6] = 1; /* MultiP 1 */
++ buf[7] = 2; /* CMDQUE 1, BQue 0 => commands queuing supported */
++
++ /*
++ * 8 byte ASCII Vendor Identification of the target
++ * - left aligned.
++ */
++ if (virt_dev->blockio)
++ memcpy(&buf[8], SCST_BIO_VENDOR, 8);
++ else
++ memcpy(&buf[8], SCST_FIO_VENDOR, 8);
++
++ /*
++ * 16 byte ASCII Product Identification of the target - left
++ * aligned.
++ */
++ memset(&buf[16], ' ', 16);
++ len = min(strlen(virt_dev->name), (size_t)16);
++ memcpy(&buf[16], virt_dev->name, len);
++
++ /*
++ * 4 byte ASCII Product Revision Level of the target - left
++ * aligned.
++ */
++ memcpy(&buf[32], SCST_FIO_REV, 4);
++
++ /** Version descriptors **/
++
++ buf[4] += 58 - 36;
++ num = 0;
++
++ /* SAM-3 T10/1561-D revision 14 */
++ buf[58 + num] = 0x0;
++ buf[58 + num + 1] = 0x76;
++ num += 2;
++
++ /* Physical transport */
++ if (cmd->tgtt->get_phys_transport_version != NULL) {
++ uint16_t v = cmd->tgtt->get_phys_transport_version(cmd->tgt);
++ if (v != 0) {
++ *((__be16 *)&buf[58 + num]) = cpu_to_be16(v);
++ num += 2;
++ }
++ }
++
++ /* SCSI transport */
++ if (cmd->tgtt->get_scsi_transport_version != NULL) {
++ *((__be16 *)&buf[58 + num]) =
++ cpu_to_be16(cmd->tgtt->get_scsi_transport_version(cmd->tgt));
++ num += 2;
++ }
++
++ /* SPC-3 T10/1416-D revision 23 */
++ buf[58 + num] = 0x3;
++ buf[58 + num + 1] = 0x12;
++ num += 2;
++
++ /* Device command set */
++ if (virt_dev->command_set_version != 0) {
++ *((__be16 *)&buf[58 + num]) =
++ cpu_to_be16(virt_dev->command_set_version);
++ num += 2;
++ }
++
++ buf[4] += num;
++ resp_len = buf[4] + 5;
++ }
++
++ BUG_ON(resp_len >= INQ_BUF_SZ);
++
++ if (length > resp_len)
++ length = resp_len;
++ memcpy(address, buf, length);
++
++out_put:
++ scst_put_buf(cmd, address);
++ if (length < cmd->resp_data_len)
++ scst_set_resp_data_len(cmd, length);
++
++out_free:
++ kfree(buf);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void vdisk_exec_request_sense(struct scst_cmd *cmd)
++{
++ int32_t length, sl;
++ uint8_t *address;
++ uint8_t b[SCST_STANDARD_SENSE_LEN];
++
++ TRACE_ENTRY();
++
++ sl = scst_set_sense(b, sizeof(b), cmd->dev->d_sense,
++ SCST_LOAD_SENSE(scst_sense_no_sense));
++
++ length = scst_get_buf_first(cmd, &address);
++ TRACE_DBG("length %d", length);
++ if (length < 0) {
++ PRINT_ERROR("scst_get_buf_first() failed: %d)", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out;
++ }
++
++ length = min(sl, length);
++ memcpy(address, b, length);
++ scst_set_resp_data_len(cmd, length);
++
++ scst_put_buf(cmd, address);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * <<Following mode pages info copied from ST318451LW with some corrections>>
++ *
++ * ToDo: revise them
++ */
++static int vdisk_err_recov_pg(unsigned char *p, int pcontrol,
++ struct scst_vdisk_dev *virt_dev)
++{ /* Read-Write Error Recovery page for mode_sense */
++ const unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0,
++ 5, 0, 0xff, 0xff};
++
++ memcpy(p, err_recov_pg, sizeof(err_recov_pg));
++ if (1 == pcontrol)
++ memset(p + 2, 0, sizeof(err_recov_pg) - 2);
++ return sizeof(err_recov_pg);
++}
++
++static int vdisk_disconnect_pg(unsigned char *p, int pcontrol,
++ struct scst_vdisk_dev *virt_dev)
++{ /* Disconnect-Reconnect page for mode_sense */
++ const unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0};
++
++ memcpy(p, disconnect_pg, sizeof(disconnect_pg));
++ if (1 == pcontrol)
++ memset(p + 2, 0, sizeof(disconnect_pg) - 2);
++ return sizeof(disconnect_pg);
++}
++
++static int vdisk_rigid_geo_pg(unsigned char *p, int pcontrol,
++ struct scst_vdisk_dev *virt_dev)
++{
++ unsigned char geo_m_pg[] = {0x04, 0x16, 0, 0, 0, DEF_HEADS, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0x3a, 0x98/* 15K RPM */, 0, 0};
++ int32_t ncyl, n, rem;
++ uint64_t dividend;
++
++ memcpy(p, geo_m_pg, sizeof(geo_m_pg));
++ /*
++ * Divide virt_dev->nblocks by (DEF_HEADS * DEF_SECTORS) and store
++ * the quotient in ncyl and the remainder in rem.
++ */
++ dividend = virt_dev->nblocks;
++ rem = do_div(dividend, DEF_HEADS * DEF_SECTORS);
++ ncyl = dividend;
++ if (rem != 0)
++ ncyl++;
++ memcpy(&n, p + 2, sizeof(u32));
++ n = n | ((__force u32)cpu_to_be32(ncyl) >> 8);
++ memcpy(p + 2, &n, sizeof(u32));
++ if (1 == pcontrol)
++ memset(p + 2, 0, sizeof(geo_m_pg) - 2);
++ return sizeof(geo_m_pg);
++}
++
++static int vdisk_format_pg(unsigned char *p, int pcontrol,
++ struct scst_vdisk_dev *virt_dev)
++{ /* Format device page for mode_sense */
++ const unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0x40, 0, 0, 0};
++
++ memcpy(p, format_pg, sizeof(format_pg));
++ p[10] = (DEF_SECTORS >> 8) & 0xff;
++ p[11] = DEF_SECTORS & 0xff;
++ p[12] = (virt_dev->block_size >> 8) & 0xff;
++ p[13] = virt_dev->block_size & 0xff;
++ if (1 == pcontrol)
++ memset(p + 2, 0, sizeof(format_pg) - 2);
++ return sizeof(format_pg);
++}
++
++static int vdisk_caching_pg(unsigned char *p, int pcontrol,
++ struct scst_vdisk_dev *virt_dev)
++{ /* Caching page for mode_sense */
++ const unsigned char caching_pg[] = {0x8, 18, 0x10, 0, 0xff, 0xff, 0, 0,
++ 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
++
++ memcpy(p, caching_pg, sizeof(caching_pg));
++ p[2] |= !(virt_dev->wt_flag || virt_dev->nv_cache) ? WCE : 0;
++ if (1 == pcontrol)
++ memset(p + 2, 0, sizeof(caching_pg) - 2);
++ return sizeof(caching_pg);
++}
++
++static int vdisk_ctrl_m_pg(unsigned char *p, int pcontrol,
++ struct scst_vdisk_dev *virt_dev)
++{ /* Control mode page for mode_sense */
++ const unsigned char ctrl_m_pg[] = {0xa, 0xa, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0x2, 0x4b};
++
++ memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
++ switch (pcontrol) {
++ case 0:
++ p[2] |= virt_dev->dev->tst << 5;
++ p[2] |= virt_dev->dev->d_sense << 2;
++ p[3] |= virt_dev->dev->queue_alg << 4;
++ p[4] |= virt_dev->dev->swp << 3;
++ p[5] |= virt_dev->dev->tas << 6;
++ break;
++ case 1:
++ memset(p + 2, 0, sizeof(ctrl_m_pg) - 2);
++#if 0 /*
++ * It's too early to implement it, since we can't control the
++ * backstorage device parameters. ToDo
++ */
++ p[2] |= 7 << 5; /* TST */
++ p[3] |= 0xF << 4; /* QUEUE ALGORITHM MODIFIER */
++#endif
++ p[2] |= 1 << 2; /* D_SENSE */
++ p[4] |= 1 << 3; /* SWP */
++ p[5] |= 1 << 6; /* TAS */
++ break;
++ case 2:
++ p[2] |= DEF_TST << 5;
++ p[2] |= DEF_DSENSE << 2;
++ if (virt_dev->wt_flag || virt_dev->nv_cache)
++ p[3] |= DEF_QUEUE_ALG_WT << 4;
++ else
++ p[3] |= DEF_QUEUE_ALG << 4;
++ p[4] |= DEF_SWP << 3;
++ p[5] |= DEF_TAS << 6;
++ break;
++ default:
++ BUG();
++ }
++ return sizeof(ctrl_m_pg);
++}
++
++static int vdisk_iec_m_pg(unsigned char *p, int pcontrol,
++ struct scst_vdisk_dev *virt_dev)
++{ /* Informational Exceptions control mode page for mode_sense */
++ const unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
++ 0, 0, 0x0, 0x0};
++ memcpy(p, iec_m_pg, sizeof(iec_m_pg));
++ if (1 == pcontrol)
++ memset(p + 2, 0, sizeof(iec_m_pg) - 2);
++ return sizeof(iec_m_pg);
++}
++
++static void vdisk_exec_mode_sense(struct scst_cmd *cmd)
++{
++ int32_t length;
++ uint8_t *address;
++ uint8_t *buf;
++ struct scst_vdisk_dev *virt_dev;
++ uint32_t blocksize;
++ uint64_t nblocks;
++ unsigned char dbd, type;
++ int pcontrol, pcode, subpcode;
++ unsigned char dev_spec;
++ int msense_6, offset = 0, len;
++ unsigned char *bp;
++
++ TRACE_ENTRY();
++
++ buf = kzalloc(MSENSE_BUF_SZ, GFP_KERNEL);
++ if (buf == NULL) {
++ scst_set_busy(cmd);
++ goto out;
++ }
++
++ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ blocksize = virt_dev->block_size;
++ nblocks = virt_dev->nblocks;
++
++ type = cmd->dev->type; /* type dev */
++ dbd = cmd->cdb[1] & DBD;
++ pcontrol = (cmd->cdb[2] & 0xc0) >> 6;
++ pcode = cmd->cdb[2] & 0x3f;
++ subpcode = cmd->cdb[3];
++ msense_6 = (MODE_SENSE == cmd->cdb[0]);
++ dev_spec = (virt_dev->dev->rd_only ||
++ cmd->tgt_dev->acg_dev->rd_only) ? WP : 0;
++
++ if (!virt_dev->blockio)
++ dev_spec |= DPOFUA;
++
++ length = scst_get_buf_first(cmd, &address);
++ if (unlikely(length <= 0)) {
++ if (length < 0) {
++ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ goto out_free;
++ }
++
++ if (0x3 == pcontrol) {
++ TRACE_DBG("%s", "MODE SENSE: Saving values not supported");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_saving_params_unsup));
++ goto out_put;
++ }
++
++ if (msense_6) {
++ buf[1] = type;
++ buf[2] = dev_spec;
++ offset = 4;
++ } else {
++ buf[2] = type;
++ buf[3] = dev_spec;
++ offset = 8;
++ }
++
++ if (0 != subpcode) {
++ /* TODO: Control Extension page */
++ TRACE_DBG("%s", "MODE SENSE: Only subpage 0 is supported");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_put;
++ }
++
++ if (!dbd) {
++ /* Create block descriptor */
++ buf[offset - 1] = 0x08; /* block descriptor length */
++ if (nblocks >> 32) {
++ buf[offset + 0] = 0xFF;
++ buf[offset + 1] = 0xFF;
++ buf[offset + 2] = 0xFF;
++ buf[offset + 3] = 0xFF;
++ } else {
++ /* num blks */
++ buf[offset + 0] = (nblocks >> (BYTE * 3)) & 0xFF;
++ buf[offset + 1] = (nblocks >> (BYTE * 2)) & 0xFF;
++ buf[offset + 2] = (nblocks >> (BYTE * 1)) & 0xFF;
++ buf[offset + 3] = (nblocks >> (BYTE * 0)) & 0xFF;
++ }
++ buf[offset + 4] = 0; /* density code */
++ buf[offset + 5] = (blocksize >> (BYTE * 2)) & 0xFF;/* blklen */
++ buf[offset + 6] = (blocksize >> (BYTE * 1)) & 0xFF;
++ buf[offset + 7] = (blocksize >> (BYTE * 0)) & 0xFF;
++
++ offset += 8; /* increment offset */
++ }
++
++ bp = buf + offset;
++
++ switch (pcode) {
++ case 0x1: /* Read-Write error recovery page, direct access */
++ len = vdisk_err_recov_pg(bp, pcontrol, virt_dev);
++ break;
++ case 0x2: /* Disconnect-Reconnect page, all devices */
++ len = vdisk_disconnect_pg(bp, pcontrol, virt_dev);
++ break;
++ case 0x3: /* Format device page, direct access */
++ len = vdisk_format_pg(bp, pcontrol, virt_dev);
++ break;
++ case 0x4: /* Rigid disk geometry */
++ len = vdisk_rigid_geo_pg(bp, pcontrol, virt_dev);
++ break;
++ case 0x8: /* Caching page, direct access */
++ len = vdisk_caching_pg(bp, pcontrol, virt_dev);
++ break;
++ case 0xa: /* Control Mode page, all devices */
++ len = vdisk_ctrl_m_pg(bp, pcontrol, virt_dev);
++ break;
++ case 0x1c: /* Informational Exceptions Mode page, all devices */
++ len = vdisk_iec_m_pg(bp, pcontrol, virt_dev);
++ break;
++ case 0x3f: /* Read all Mode pages */
++ len = vdisk_err_recov_pg(bp, pcontrol, virt_dev);
++ len += vdisk_disconnect_pg(bp + len, pcontrol, virt_dev);
++ len += vdisk_format_pg(bp + len, pcontrol, virt_dev);
++ len += vdisk_caching_pg(bp + len, pcontrol, virt_dev);
++ len += vdisk_ctrl_m_pg(bp + len, pcontrol, virt_dev);
++ len += vdisk_iec_m_pg(bp + len, pcontrol, virt_dev);
++ len += vdisk_rigid_geo_pg(bp + len, pcontrol, virt_dev);
++ break;
++ default:
++ TRACE_DBG("MODE SENSE: Unsupported page %x", pcode);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_put;
++ }
++
++ offset += len;
++
++ if (msense_6)
++ buf[0] = offset - 1;
++ else {
++ buf[0] = ((offset - 2) >> 8) & 0xff;
++ buf[1] = (offset - 2) & 0xff;
++ }
++
++ if (offset > length)
++ offset = length;
++ memcpy(address, buf, offset);
++
++out_put:
++ scst_put_buf(cmd, address);
++ if (offset < cmd->resp_data_len)
++ scst_set_resp_data_len(cmd, offset);
++
++out_free:
++ kfree(buf);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int vdisk_set_wt(struct scst_vdisk_dev *virt_dev, int wt)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if ((virt_dev->wt_flag == wt) || virt_dev->nullio || virt_dev->nv_cache)
++ goto out;
++
++ spin_lock(&virt_dev->flags_lock);
++ virt_dev->wt_flag = wt;
++ spin_unlock(&virt_dev->flags_lock);
++
++ scst_dev_del_all_thr_data(virt_dev->dev);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void vdisk_ctrl_m_pg_select(unsigned char *p,
++ struct scst_vdisk_dev *virt_dev)
++{
++ struct scst_device *dev = virt_dev->dev;
++ int old_swp = dev->swp, old_tas = dev->tas, old_dsense = dev->d_sense;
++
++#if 0
++ /* Not implemented yet, see comment in vdisk_ctrl_m_pg() */
++ dev->tst = p[2] >> 5;
++ dev->queue_alg = p[3] >> 4;
++#endif
++ dev->swp = (p[4] & 0x8) >> 3;
++ dev->tas = (p[5] & 0x40) >> 6;
++ dev->d_sense = (p[2] & 0x4) >> 2;
++
++ PRINT_INFO("Device %s: new control mode page parameters: SWP %x "
++ "(was %x), TAS %x (was %x), D_SENSE %d (was %d)",
++ virt_dev->name, dev->swp, old_swp, dev->tas, old_tas,
++ dev->d_sense, old_dsense);
++ return;
++}
++
++static void vdisk_exec_mode_select(struct scst_cmd *cmd)
++{
++ int32_t length;
++ uint8_t *address;
++ struct scst_vdisk_dev *virt_dev;
++ int mselect_6, offset;
++
++ TRACE_ENTRY();
++
++ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ mselect_6 = (MODE_SELECT == cmd->cdb[0]);
++
++ length = scst_get_buf_first(cmd, &address);
++ if (unlikely(length <= 0)) {
++ if (length < 0) {
++ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ goto out;
++ }
++
++ if (!(cmd->cdb[1] & PF) || (cmd->cdb[1] & SP)) {
++ TRACE(TRACE_MINOR|TRACE_SCSI, "MODE SELECT: Unsupported "
++ "value(s) of PF and/or SP bits (cdb[1]=%x)",
++ cmd->cdb[1]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out_put;
++ }
++
++ if (mselect_6)
++ offset = 4;
++ else
++ offset = 8;
++
++ if (address[offset - 1] == 8) {
++ offset += 8;
++ } else if (address[offset - 1] != 0) {
++ PRINT_ERROR("%s", "MODE SELECT: Wrong parameters list "
++ "lenght");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
++ goto out_put;
++ }
++
++ while (length > offset + 2) {
++ if (address[offset] & PS) {
++ PRINT_ERROR("%s", "MODE SELECT: Illegal PS bit");
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_invalid_field_in_parm_list));
++ goto out_put;
++ }
++ if ((address[offset] & 0x3f) == 0x8) {
++ /* Caching page */
++ if (address[offset + 1] != 18) {
++ PRINT_ERROR("%s", "MODE SELECT: Invalid "
++ "caching page request");
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_invalid_field_in_parm_list));
++ goto out_put;
++ }
++ if (vdisk_set_wt(virt_dev,
++ (address[offset + 2] & WCE) ? 0 : 1) != 0) {
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_put;
++ }
++ break;
++ } else if ((address[offset] & 0x3f) == 0xA) {
++ /* Control page */
++ if (address[offset + 1] != 0xA) {
++ PRINT_ERROR("%s", "MODE SELECT: Invalid "
++ "control page request");
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_invalid_field_in_parm_list));
++ goto out_put;
++ }
++ vdisk_ctrl_m_pg_select(&address[offset], virt_dev);
++ } else {
++ PRINT_ERROR("MODE SELECT: Invalid request %x",
++ address[offset] & 0x3f);
++ scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
++ scst_sense_invalid_field_in_parm_list));
++ goto out_put;
++ }
++ offset += address[offset + 1];
++ }
++
++out_put:
++ scst_put_buf(cmd, address);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void vdisk_exec_log(struct scst_cmd *cmd)
++{
++ TRACE_ENTRY();
++
++ /* No log pages are supported */
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++
++ TRACE_EXIT();
++ return;
++}
++
++static void vdisk_exec_read_capacity(struct scst_cmd *cmd)
++{
++ int32_t length;
++ uint8_t *address;
++ struct scst_vdisk_dev *virt_dev;
++ uint32_t blocksize;
++ uint64_t nblocks;
++ uint8_t buffer[8];
++
++ TRACE_ENTRY();
++
++ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ blocksize = virt_dev->block_size;
++ nblocks = virt_dev->nblocks;
++
++ if ((cmd->cdb[8] & 1) == 0) {
++ uint64_t lba = be64_to_cpu(get_unaligned((__be64 *)&cmd->cdb[2]));
++ if (lba != 0) {
++ TRACE_DBG("PMI zero and LBA not zero (cmd %p)", cmd);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++ }
++
++ /* Last block on the virt_dev is (nblocks-1) */
++ memset(buffer, 0, sizeof(buffer));
++ if (nblocks >> 32) {
++ buffer[0] = 0xFF;
++ buffer[1] = 0xFF;
++ buffer[2] = 0xFF;
++ buffer[3] = 0xFF;
++ } else {
++ buffer[0] = ((nblocks - 1) >> (BYTE * 3)) & 0xFF;
++ buffer[1] = ((nblocks - 1) >> (BYTE * 2)) & 0xFF;
++ buffer[2] = ((nblocks - 1) >> (BYTE * 1)) & 0xFF;
++ buffer[3] = ((nblocks - 1) >> (BYTE * 0)) & 0xFF;
++ }
++ buffer[4] = (blocksize >> (BYTE * 3)) & 0xFF;
++ buffer[5] = (blocksize >> (BYTE * 2)) & 0xFF;
++ buffer[6] = (blocksize >> (BYTE * 1)) & 0xFF;
++ buffer[7] = (blocksize >> (BYTE * 0)) & 0xFF;
++
++ length = scst_get_buf_first(cmd, &address);
++ if (unlikely(length <= 0)) {
++ if (length < 0) {
++ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ goto out;
++ }
++
++ length = min_t(int, length, sizeof(buffer));
++
++ memcpy(address, buffer, length);
++
++ scst_put_buf(cmd, address);
++
++ if (length < cmd->resp_data_len)
++ scst_set_resp_data_len(cmd, length);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
++{
++ int32_t length;
++ uint8_t *address;
++ struct scst_vdisk_dev *virt_dev;
++ uint32_t blocksize;
++ uint64_t nblocks;
++ uint8_t buffer[32];
++
++ TRACE_ENTRY();
++
++ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ blocksize = virt_dev->block_size;
++ nblocks = virt_dev->nblocks - 1;
++
++ if ((cmd->cdb[14] & 1) == 0) {
++ uint64_t lba = be64_to_cpu(get_unaligned((__be64 *)&cmd->cdb[2]));
++ if (lba != 0) {
++ TRACE_DBG("PMI zero and LBA not zero (cmd %p)", cmd);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++ }
++
++ memset(buffer, 0, sizeof(buffer));
++
++ buffer[0] = nblocks >> 56;
++ buffer[1] = (nblocks >> 48) & 0xFF;
++ buffer[2] = (nblocks >> 40) & 0xFF;
++ buffer[3] = (nblocks >> 32) & 0xFF;
++ buffer[4] = (nblocks >> 24) & 0xFF;
++ buffer[5] = (nblocks >> 16) & 0xFF;
++ buffer[6] = (nblocks >> 8) & 0xFF;
++ buffer[7] = nblocks & 0xFF;
++
++ buffer[8] = (blocksize >> (BYTE * 3)) & 0xFF;
++ buffer[9] = (blocksize >> (BYTE * 2)) & 0xFF;
++ buffer[10] = (blocksize >> (BYTE * 1)) & 0xFF;
++ buffer[11] = (blocksize >> (BYTE * 0)) & 0xFF;
++
++ switch (blocksize) {
++ case 512:
++ buffer[13] = 3;
++ break;
++ case 1024:
++ buffer[13] = 2;
++ break;
++ case 2048:
++ buffer[13] = 1;
++ break;
++ case 4096:
++ default:
++ buffer[13] = 0;
++ break;
++ }
++
++ length = scst_get_buf_first(cmd, &address);
++ if (unlikely(length <= 0)) {
++ if (length < 0) {
++ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ goto out;
++ }
++
++ length = min_t(int, length, sizeof(buffer));
++
++ memcpy(address, buffer, length);
++
++ scst_put_buf(cmd, address);
++
++ if (length < cmd->resp_data_len)
++ scst_set_resp_data_len(cmd, length);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void vdisk_exec_read_toc(struct scst_cmd *cmd)
++{
++ int32_t length, off = 0;
++ uint8_t *address;
++ struct scst_vdisk_dev *virt_dev;
++ uint32_t nblocks;
++ uint8_t buffer[4+8+8] = { 0x00, 0x0a, 0x01, 0x01, 0x00, 0x14,
++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
++
++ TRACE_ENTRY();
++
++ if (cmd->dev->type != TYPE_ROM) {
++ PRINT_ERROR("%s", "READ TOC for non-CDROM device");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_opcode));
++ goto out;
++ }
++
++ if (cmd->cdb[2] & 0x0e/*Format*/) {
++ PRINT_ERROR("%s", "READ TOC: invalid requested data format");
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++
++ if ((cmd->cdb[6] != 0 && (cmd->cdb[2] & 0x01)) ||
++ (cmd->cdb[6] > 1 && cmd->cdb[6] != 0xAA)) {
++ PRINT_ERROR("READ TOC: invalid requested track number %x",
++ cmd->cdb[6]);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ goto out;
++ }
++
++ length = scst_get_buf_first(cmd, &address);
++ if (unlikely(length <= 0)) {
++ if (length < 0) {
++ PRINT_ERROR("scst_get_buf_first() failed: %d", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++ goto out;
++ }
++
++ virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ /* ToDo when you have > 8TB ROM device. */
++ nblocks = (uint32_t)virt_dev->nblocks;
++
++ /* Header */
++ memset(buffer, 0, sizeof(buffer));
++ buffer[2] = 0x01; /* First Track/Session */
++ buffer[3] = 0x01; /* Last Track/Session */
++ off = 4;
++ if (cmd->cdb[6] <= 1) {
++ /* Fistr TOC Track Descriptor */
++ /* ADDR 0x10 - Q Sub-channel encodes current position data
++ CONTROL 0x04 - Data track, recoreded uninterrupted */
++ buffer[off+1] = 0x14;
++ /* Track Number */
++ buffer[off+2] = 0x01;
++ off += 8;
++ }
++ if (!(cmd->cdb[2] & 0x01)) {
++ /* Lead-out area TOC Track Descriptor */
++ buffer[off+1] = 0x14;
++ /* Track Number */
++ buffer[off+2] = 0xAA;
++ /* Track Start Address */
++ buffer[off+4] = (nblocks >> (BYTE * 3)) & 0xFF;
++ buffer[off+5] = (nblocks >> (BYTE * 2)) & 0xFF;
++ buffer[off+6] = (nblocks >> (BYTE * 1)) & 0xFF;
++ buffer[off+7] = (nblocks >> (BYTE * 0)) & 0xFF;
++ off += 8;
++ }
++
++ buffer[1] = off - 2; /* Data Length */
++
++ if (off > length)
++ off = length;
++ memcpy(address, buffer, off);
++
++ scst_put_buf(cmd, address);
++
++ if (off < cmd->resp_data_len)
++ scst_set_resp_data_len(cmd, off);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd)
++{
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++
++ TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]);
++
++ spin_lock(&virt_dev->flags_lock);
++ virt_dev->prevent_allow_medium_removal = cmd->cdb[4] & 0x01 ? 1 : 0;
++ spin_unlock(&virt_dev->flags_lock);
++
++ return;
++}
++
++static int vdisk_fsync(struct scst_vdisk_thr *thr, loff_t loff,
++ loff_t len, struct scst_cmd *cmd, struct scst_device *dev)
++{
++ int res = 0;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)dev->dh_priv;
++ struct file *file;
++
++ TRACE_ENTRY();
++
++ /* Hopefully, the compiler will generate the single comparison */
++ if (virt_dev->nv_cache || virt_dev->wt_flag ||
++ virt_dev->o_direct_flag || virt_dev->nullio)
++ goto out;
++
++ if (virt_dev->blockio) {
++ res = blockio_flush(thr->bdev);
++ goto out;
++ }
++
++ file = thr->fd;
++
++#if 0 /* For sparse files we might need to sync metadata as well */
++ res = generic_write_sync(file, loff, len);
++#else
++ res = filemap_write_and_wait_range(file->f_mapping, loff, len);
++#endif
++ if (unlikely(res != 0)) {
++ PRINT_ERROR("sync range failed (%d)", res);
++ if (cmd != NULL) {
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_write_error));
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct iovec *vdisk_alloc_iv(struct scst_cmd *cmd,
++ struct scst_vdisk_thr *thr)
++{
++ int iv_count;
++
++ iv_count = min_t(int, scst_get_buf_count(cmd), UIO_MAXIOV);
++ if (iv_count > thr->iv_count) {
++ kfree(thr->iv);
++ /* It can't be called in atomic context */
++ thr->iv = kmalloc(sizeof(*thr->iv) * iv_count, GFP_KERNEL);
++ if (thr->iv == NULL) {
++ PRINT_ERROR("Unable to allocate iv (%d)", iv_count);
++ scst_set_busy(cmd);
++ goto out;
++ }
++ thr->iv_count = iv_count;
++ }
++
++out:
++ return thr->iv;
++}
++
++static void vdisk_exec_read(struct scst_cmd *cmd,
++ struct scst_vdisk_thr *thr, loff_t loff)
++{
++ mm_segment_t old_fs;
++ loff_t err;
++ ssize_t length, full_len;
++ uint8_t __user *address;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ struct file *fd = thr->fd;
++ struct iovec *iv;
++ int iv_count, i;
++ bool finished = false;
++
++ TRACE_ENTRY();
++
++ if (virt_dev->nullio)
++ goto out;
++
++ iv = vdisk_alloc_iv(cmd, thr);
++ if (iv == NULL)
++ goto out;
++
++ length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
++ if (unlikely(length < 0)) {
++ PRINT_ERROR("scst_get_buf_first() failed: %zd", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out;
++ }
++
++ old_fs = get_fs();
++ set_fs(get_ds());
++
++ while (1) {
++ iv_count = 0;
++ full_len = 0;
++ i = -1;
++ while (length > 0) {
++ full_len += length;
++ i++;
++ iv_count++;
++ iv[i].iov_base = address;
++ iv[i].iov_len = length;
++ if (iv_count == UIO_MAXIOV)
++ break;
++ length = scst_get_buf_next(cmd,
++ (uint8_t __force **)&address);
++ }
++ if (length == 0) {
++ finished = true;
++ if (unlikely(iv_count == 0))
++ break;
++ } else if (unlikely(length < 0)) {
++ PRINT_ERROR("scst_get_buf_next() failed: %zd", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_set_fs;
++ }
++
++ TRACE_DBG("(iv_count %d, full_len %zd)", iv_count, full_len);
++ /* SEEK */
++ if (fd->f_op->llseek)
++ err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
++ else
++ err = default_llseek(fd, loff, 0/*SEEK_SET*/);
++ if (err != loff) {
++ PRINT_ERROR("lseek trouble %lld != %lld",
++ (long long unsigned int)err,
++ (long long unsigned int)loff);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_set_fs;
++ }
++
++ /* READ */
++ err = vfs_readv(fd, (struct iovec __force __user *)iv, iv_count,
++ &fd->f_pos);
++
++ if ((err < 0) || (err < full_len)) {
++ PRINT_ERROR("readv() returned %lld from %zd",
++ (long long unsigned int)err,
++ full_len);
++ if (err == -EAGAIN)
++ scst_set_busy(cmd);
++ else {
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_read_error));
++ }
++ goto out_set_fs;
++ }
++
++ for (i = 0; i < iv_count; i++)
++ scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
++
++ if (finished)
++ break;
++
++ loff += full_len;
++ length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
++ };
++
++ set_fs(old_fs);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_set_fs:
++ set_fs(old_fs);
++ for (i = 0; i < iv_count; i++)
++ scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
++ goto out;
++}
++
++static void vdisk_exec_write(struct scst_cmd *cmd,
++ struct scst_vdisk_thr *thr, loff_t loff)
++{
++ mm_segment_t old_fs;
++ loff_t err;
++ ssize_t length, full_len, saved_full_len;
++ uint8_t __user *address;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ struct file *fd = thr->fd;
++ struct iovec *iv, *eiv;
++ int i, iv_count, eiv_count;
++ bool finished = false;
++
++ TRACE_ENTRY();
++
++ if (virt_dev->nullio)
++ goto out;
++
++ iv = vdisk_alloc_iv(cmd, thr);
++ if (iv == NULL)
++ goto out;
++
++ length = scst_get_buf_first(cmd, (uint8_t __force **)&address);
++ if (unlikely(length < 0)) {
++ PRINT_ERROR("scst_get_buf_first() failed: %zd", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out;
++ }
++
++ old_fs = get_fs();
++ set_fs(get_ds());
++
++ while (1) {
++ iv_count = 0;
++ full_len = 0;
++ i = -1;
++ while (length > 0) {
++ full_len += length;
++ i++;
++ iv_count++;
++ iv[i].iov_base = address;
++ iv[i].iov_len = length;
++ if (iv_count == UIO_MAXIOV)
++ break;
++ length = scst_get_buf_next(cmd,
++ (uint8_t __force **)&address);
++ }
++ if (length == 0) {
++ finished = true;
++ if (unlikely(iv_count == 0))
++ break;
++ } else if (unlikely(length < 0)) {
++ PRINT_ERROR("scst_get_buf_next() failed: %zd", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_set_fs;
++ }
++
++ saved_full_len = full_len;
++ eiv = iv;
++ eiv_count = iv_count;
++restart:
++ TRACE_DBG("writing(eiv_count %d, full_len %zd)", eiv_count, full_len);
++
++ /* SEEK */
++ if (fd->f_op->llseek)
++ err = fd->f_op->llseek(fd, loff, 0 /*SEEK_SET */);
++ else
++ err = default_llseek(fd, loff, 0 /*SEEK_SET */);
++ if (err != loff) {
++ PRINT_ERROR("lseek trouble %lld != %lld",
++ (long long unsigned int)err,
++ (long long unsigned int)loff);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_set_fs;
++ }
++
++ /* WRITE */
++ err = vfs_writev(fd, (struct iovec __force __user *)eiv, eiv_count,
++ &fd->f_pos);
++
++ if (err < 0) {
++ PRINT_ERROR("write() returned %lld from %zd",
++ (long long unsigned int)err,
++ full_len);
++ if (err == -EAGAIN)
++ scst_set_busy(cmd);
++ else {
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_write_error));
++ }
++ goto out_set_fs;
++ } else if (err < full_len) {
++ /*
++ * Probably that's wrong, but sometimes write() returns
++ * value less, than requested. Let's restart.
++ */
++ int e = eiv_count;
++ TRACE_MGMT_DBG("write() returned %d from %zd "
++ "(iv_count=%d)", (int)err, full_len,
++ eiv_count);
++ if (err == 0) {
++ PRINT_INFO("Suspicious: write() returned 0 from "
++ "%zd (iv_count=%d)", full_len, eiv_count);
++ }
++ full_len -= err;
++ for (i = 0; i < e; i++) {
++ if ((long long)eiv->iov_len < err) {
++ err -= eiv->iov_len;
++ eiv++;
++ eiv_count--;
++ } else {
++ eiv->iov_base =
++ (uint8_t __force __user *)eiv->iov_base + err;
++ eiv->iov_len -= err;
++ break;
++ }
++ }
++ goto restart;
++ }
++
++ for (i = 0; i < iv_count; i++)
++ scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
++
++ if (finished)
++ break;
++
++ loff += saved_full_len;
++ length = scst_get_buf_next(cmd, (uint8_t __force **)&address);
++ }
++
++ set_fs(old_fs);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_set_fs:
++ set_fs(old_fs);
++ for (i = 0; i < iv_count; i++)
++ scst_put_buf(cmd, (void __force *)(iv[i].iov_base));
++ goto out;
++}
++
++struct scst_blockio_work {
++ atomic_t bios_inflight;
++ struct scst_cmd *cmd;
++};
++
++static inline void blockio_check_finish(struct scst_blockio_work *blockio_work)
++{
++ /* Decrement the bios in processing, and if zero signal completion */
++ if (atomic_dec_and_test(&blockio_work->bios_inflight)) {
++ blockio_work->cmd->completed = 1;
++ blockio_work->cmd->scst_cmd_done(blockio_work->cmd,
++ SCST_CMD_STATE_DEFAULT, scst_estimate_context());
++ kmem_cache_free(blockio_work_cachep, blockio_work);
++ }
++ return;
++}
++
++static void blockio_endio(struct bio *bio, int error)
++{
++ struct scst_blockio_work *blockio_work = bio->bi_private;
++
++ if (unlikely(!bio_flagged(bio, BIO_UPTODATE))) {
++ if (error == 0) {
++ PRINT_ERROR("Not up to date bio with error 0 for "
++ "cmd %p, returning -EIO", blockio_work->cmd);
++ error = -EIO;
++ }
++ }
++
++ if (unlikely(error != 0)) {
++ static DEFINE_SPINLOCK(blockio_endio_lock);
++ unsigned long flags;
++
++ PRINT_ERROR("cmd %p returned error %d", blockio_work->cmd,
++ error);
++
++ /* To protect from several bios finishing simultaneously */
++ spin_lock_irqsave(&blockio_endio_lock, flags);
++
++ if (bio->bi_rw & REQ_WRITE)
++ scst_set_cmd_error(blockio_work->cmd,
++ SCST_LOAD_SENSE(scst_sense_write_error));
++ else
++ scst_set_cmd_error(blockio_work->cmd,
++ SCST_LOAD_SENSE(scst_sense_read_error));
++
++ spin_unlock_irqrestore(&blockio_endio_lock, flags);
++ }
++
++ blockio_check_finish(blockio_work);
++
++ bio_put(bio);
++ return;
++}
++
++static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
++ u64 lba_start, int write)
++{
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ struct block_device *bdev = thr->bdev;
++ struct request_queue *q = bdev_get_queue(bdev);
++ int length, max_nr_vecs = 0;
++ uint8_t *address;
++ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
++ int need_new_bio;
++ struct scst_blockio_work *blockio_work;
++ int bios = 0;
++
++ TRACE_ENTRY();
++
++ if (virt_dev->nullio)
++ goto out;
++
++ /* Allocate and initialize blockio_work struct */
++ blockio_work = kmem_cache_alloc(blockio_work_cachep, GFP_KERNEL);
++ if (blockio_work == NULL)
++ goto out_no_mem;
++
++ blockio_work->cmd = cmd;
++
++ if (q)
++ max_nr_vecs = min(bio_get_nr_vecs(bdev), BIO_MAX_PAGES);
++ else
++ max_nr_vecs = 1;
++
++ need_new_bio = 1;
++
++ length = scst_get_buf_first(cmd, &address);
++ while (length > 0) {
++ int len, bytes, off, thislen;
++ uint8_t *addr;
++ u64 lba_start0;
++
++ addr = address;
++ off = offset_in_page(addr);
++ len = length;
++ thislen = 0;
++ lba_start0 = lba_start;
++
++ while (len > 0) {
++ int rc;
++ struct page *page = virt_to_page(addr);
++
++ if (need_new_bio) {
++ bio = bio_kmalloc(GFP_KERNEL, max_nr_vecs);
++ if (!bio) {
++ PRINT_ERROR("Failed to create bio "
++ "for data segment %d (cmd %p)",
++ cmd->get_sg_buf_entry_num, cmd);
++ goto out_no_bio;
++ }
++
++ bios++;
++ need_new_bio = 0;
++ bio->bi_end_io = blockio_endio;
++ bio->bi_sector = lba_start0 <<
++ (virt_dev->block_shift - 9);
++ bio->bi_bdev = bdev;
++ bio->bi_private = blockio_work;
++ /*
++ * Better to fail fast w/o any local recovery
++ * and retries.
++ */
++ bio->bi_rw |= REQ_FAILFAST_DEV |
++ REQ_FAILFAST_TRANSPORT |
++ REQ_FAILFAST_DRIVER;
++#if 0 /* It could be win, but could be not, so a performance study is needed */
++ bio->bi_rw |= REQ_SYNC;
++#endif
++ if (!hbio)
++ hbio = tbio = bio;
++ else
++ tbio = tbio->bi_next = bio;
++ }
++
++ bytes = min_t(unsigned int, len, PAGE_SIZE - off);
++
++ rc = bio_add_page(bio, page, bytes, off);
++ if (rc < bytes) {
++ BUG_ON(rc != 0);
++ need_new_bio = 1;
++ lba_start0 += thislen >> virt_dev->block_shift;
++ thislen = 0;
++ continue;
++ }
++
++ addr += PAGE_SIZE;
++ thislen += bytes;
++ len -= bytes;
++ off = 0;
++ }
++
++ lba_start += length >> virt_dev->block_shift;
++
++ scst_put_buf(cmd, address);
++ length = scst_get_buf_next(cmd, &address);
++ }
++
++ /* +1 to prevent erroneous too early command completion */
++ atomic_set(&blockio_work->bios_inflight, bios+1);
++
++ while (hbio) {
++ bio = hbio;
++ hbio = hbio->bi_next;
++ bio->bi_next = NULL;
++ submit_bio((write != 0), bio);
++ }
++
++ if (q && q->unplug_fn)
++ q->unplug_fn(q);
++
++ blockio_check_finish(blockio_work);
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_no_bio:
++ while (hbio) {
++ bio = hbio;
++ hbio = hbio->bi_next;
++ bio_put(bio);
++ }
++ kmem_cache_free(blockio_work_cachep, blockio_work);
++
++out_no_mem:
++ scst_set_busy(cmd);
++ goto out;
++}
++
++static int blockio_flush(struct block_device *bdev)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ res = blkdev_issue_flush(bdev, GFP_KERNEL, NULL, BLKDEV_IFL_WAIT);
++ if (res != 0)
++ PRINT_ERROR("blkdev_issue_flush() failed: %d", res);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void vdisk_exec_verify(struct scst_cmd *cmd,
++ struct scst_vdisk_thr *thr, loff_t loff)
++{
++ mm_segment_t old_fs;
++ loff_t err;
++ ssize_t length, len_mem = 0;
++ uint8_t *address_sav, *address;
++ int compare;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)cmd->dev->dh_priv;
++ struct file *fd = thr->fd;
++ uint8_t *mem_verify = NULL;
++
++ TRACE_ENTRY();
++
++ if (vdisk_fsync(thr, loff, cmd->bufflen, cmd, cmd->dev) != 0)
++ goto out;
++
++ /*
++ * Until the cache is cleared prior the verifying, there is not
++ * much point in this code. ToDo.
++ *
++ * Nevertherless, this code is valuable if the data have not read
++ * from the file/disk yet.
++ */
++
++ /* SEEK */
++ old_fs = get_fs();
++ set_fs(get_ds());
++
++ if (!virt_dev->nullio) {
++ if (fd->f_op->llseek)
++ err = fd->f_op->llseek(fd, loff, 0/*SEEK_SET*/);
++ else
++ err = default_llseek(fd, loff, 0/*SEEK_SET*/);
++ if (err != loff) {
++ PRINT_ERROR("lseek trouble %lld != %lld",
++ (long long unsigned int)err,
++ (long long unsigned int)loff);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_set_fs;
++ }
++ }
++
++ mem_verify = vmalloc(LEN_MEM);
++ if (mem_verify == NULL) {
++ PRINT_ERROR("Unable to allocate memory %d for verify",
++ LEN_MEM);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out_set_fs;
++ }
++
++ length = scst_get_buf_first(cmd, &address);
++ address_sav = address;
++ if (!length && cmd->data_len) {
++ length = cmd->data_len;
++ compare = 0;
++ } else
++ compare = 1;
++
++ while (length > 0) {
++ len_mem = (length > LEN_MEM) ? LEN_MEM : length;
++ TRACE_DBG("Verify: length %zd - len_mem %zd", length, len_mem);
++
++ if (!virt_dev->nullio)
++ err = vfs_read(fd, (char __force __user *)mem_verify,
++ len_mem, &fd->f_pos);
++ else
++ err = len_mem;
++ if ((err < 0) || (err < len_mem)) {
++ PRINT_ERROR("verify() returned %lld from %zd",
++ (long long unsigned int)err, len_mem);
++ if (err == -EAGAIN)
++ scst_set_busy(cmd);
++ else {
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_read_error));
++ }
++ if (compare)
++ scst_put_buf(cmd, address_sav);
++ goto out_set_fs;
++ }
++ if (compare && memcmp(address, mem_verify, len_mem) != 0) {
++ TRACE_DBG("Verify: error memcmp length %zd", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_miscompare_error));
++ scst_put_buf(cmd, address_sav);
++ goto out_set_fs;
++ }
++ length -= len_mem;
++ address += len_mem;
++ if (compare && length <= 0) {
++ scst_put_buf(cmd, address_sav);
++ length = scst_get_buf_next(cmd, &address);
++ address_sav = address;
++ }
++ }
++
++ if (length < 0) {
++ PRINT_ERROR("scst_get_buf_() failed: %zd", length);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ }
++
++out_set_fs:
++ set_fs(old_fs);
++ if (mem_verify)
++ vfree(mem_verify);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
++ struct scst_tgt_dev *tgt_dev)
++{
++ TRACE_ENTRY();
++
++ if ((mcmd->fn == SCST_LUN_RESET) || (mcmd->fn == SCST_TARGET_RESET)) {
++ /* Restore default values */
++ struct scst_device *dev = tgt_dev->dev;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)dev->dh_priv;
++
++ dev->tst = DEF_TST;
++ dev->d_sense = DEF_DSENSE;
++ if (virt_dev->wt_flag && !virt_dev->nv_cache)
++ dev->queue_alg = DEF_QUEUE_ALG_WT;
++ else
++ dev->queue_alg = DEF_QUEUE_ALG;
++ dev->swp = DEF_SWP;
++ dev->tas = DEF_TAS;
++
++ spin_lock(&virt_dev->flags_lock);
++ virt_dev->prevent_allow_medium_removal = 0;
++ spin_unlock(&virt_dev->flags_lock);
++ } else if (mcmd->fn == SCST_PR_ABORT_ALL) {
++ struct scst_device *dev = tgt_dev->dev;
++ struct scst_vdisk_dev *virt_dev =
++ (struct scst_vdisk_dev *)dev->dh_priv;
++ spin_lock(&virt_dev->flags_lock);
++ virt_dev->prevent_allow_medium_removal = 0;
++ spin_unlock(&virt_dev->flags_lock);
++ }
++
++ TRACE_EXIT();
++ return SCST_DEV_TM_NOT_COMPLETED;
++}
++
++static void vdisk_report_registering(const struct scst_vdisk_dev *virt_dev)
++{
++ char buf[128];
++ int i, j;
++
++ i = snprintf(buf, sizeof(buf), "Registering virtual %s device %s ",
++ virt_dev->vdev_devt->name, virt_dev->name);
++ j = i;
++
++ if (virt_dev->wt_flag)
++ i += snprintf(&buf[i], sizeof(buf) - i, "(WRITE_THROUGH");
++
++ if (virt_dev->nv_cache)
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sNV_CACHE",
++ (j == i) ? "(" : ", ");
++
++ if (virt_dev->rd_only)
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sREAD_ONLY",
++ (j == i) ? "(" : ", ");
++
++ if (virt_dev->o_direct_flag)
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sO_DIRECT",
++ (j == i) ? "(" : ", ");
++
++ if (virt_dev->nullio)
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sNULLIO",
++ (j == i) ? "(" : ", ");
++
++ if (virt_dev->blockio)
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sBLOCKIO",
++ (j == i) ? "(" : ", ");
++
++ if (virt_dev->removable)
++ i += snprintf(&buf[i], sizeof(buf) - i, "%sREMOVABLE",
++ (j == i) ? "(" : ", ");
++
++ if (j == i)
++ PRINT_INFO("%s", buf);
++ else
++ PRINT_INFO("%s)", buf);
++
++ return;
++}
++
++static int vdisk_resync_size(struct scst_vdisk_dev *virt_dev)
++{
++ loff_t file_size;
++ int res = 0;
++
++ BUG_ON(virt_dev->nullio);
++
++ res = vdisk_get_file_size(virt_dev->filename,
++ virt_dev->blockio, &file_size);
++ if (res != 0)
++ goto out;
++
++ if (file_size == virt_dev->file_size) {
++ PRINT_INFO("Size of virtual disk %s remained the same",
++ virt_dev->name);
++ goto out;
++ }
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out;
++
++ virt_dev->file_size = file_size;
++ virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
++
++ scst_dev_del_all_thr_data(virt_dev->dev);
++
++ PRINT_INFO("New size of SCSI target virtual disk %s "
++ "(fs=%lldMB, bs=%d, nblocks=%lld, cyln=%lld%s)",
++ virt_dev->name, virt_dev->file_size >> 20,
++ virt_dev->block_size,
++ (long long unsigned int)virt_dev->nblocks,
++ (long long unsigned int)virt_dev->nblocks/64/32,
++ virt_dev->nblocks < 64*32 ? " !WARNING! cyln less "
++ "than 1" : "");
++
++ scst_capacity_data_changed(virt_dev->dev);
++
++ scst_resume_activity();
++
++out:
++ return res;
++}
++
++static int vdev_create(struct scst_dev_type *devt,
++ const char *name, struct scst_vdisk_dev **res_virt_dev)
++{
++ int res = 0;
++ struct scst_vdisk_dev *virt_dev;
++ uint64_t dev_id_num;
++ int dev_id_len;
++ char dev_id_str[17];
++ int32_t i;
++
++ virt_dev = kzalloc(sizeof(*virt_dev), GFP_KERNEL);
++ if (virt_dev == NULL) {
++ PRINT_ERROR("Allocation of virtual device %s failed",
++ devt->name);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ spin_lock_init(&virt_dev->flags_lock);
++ virt_dev->vdev_devt = devt;
++
++ virt_dev->rd_only = DEF_RD_ONLY;
++ virt_dev->removable = DEF_REMOVABLE;
++
++ virt_dev->block_size = DEF_DISK_BLOCKSIZE;
++ virt_dev->block_shift = DEF_DISK_BLOCKSIZE_SHIFT;
++
++ if (strlen(name) >= sizeof(virt_dev->name)) {
++ PRINT_ERROR("Name %s is too long (max allowed %zd)", name,
++ sizeof(virt_dev->name)-1);
++ res = -EINVAL;
++ goto out_free;
++ }
++ strcpy(virt_dev->name, name);
++
++ dev_id_num = vdisk_gen_dev_id_num(virt_dev->name);
++ dev_id_len = scnprintf(dev_id_str, sizeof(dev_id_str), "%llx",
++ dev_id_num);
++
++ i = strlen(virt_dev->name) + 1; /* for ' ' */
++ memset(virt_dev->t10_dev_id, ' ', i + dev_id_len);
++ memcpy(virt_dev->t10_dev_id, virt_dev->name, i-1);
++ memcpy(virt_dev->t10_dev_id + i, dev_id_str, dev_id_len);
++ TRACE_DBG("t10_dev_id %s", virt_dev->t10_dev_id);
++
++ virt_dev->t10_dev_id_set = 1; /* temporary */
++
++ scnprintf(virt_dev->usn, sizeof(virt_dev->usn), "%llx", dev_id_num);
++ TRACE_DBG("usn %s", virt_dev->usn);
++
++ virt_dev->usn_set = 1; /* temporary */
++
++ *res_virt_dev = virt_dev;
++
++out:
++ return res;
++
++out_free:
++ kfree(virt_dev);
++ goto out;
++}
++
++static void vdev_destroy(struct scst_vdisk_dev *virt_dev)
++{
++ kfree(virt_dev->filename);
++ kfree(virt_dev);
++ return;
++}
++
++/* scst_vdisk_mutex supposed to be held */
++static struct scst_vdisk_dev *vdev_find(const char *name)
++{
++ struct scst_vdisk_dev *res, *vv;
++
++ TRACE_ENTRY();
++
++ res = NULL;
++ list_for_each_entry(vv, &vdev_list, vdev_list_entry) {
++ if (strcmp(vv->name, name) == 0) {
++ res = vv;
++ break;
++ }
++ }
++
++ TRACE_EXIT_HRES((unsigned long)res);
++ return res;
++}
++
++static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev,
++ char *params, const char *allowed_params[])
++{
++ int res = 0;
++ unsigned long val;
++ char *param, *p, *pp;
++
++ TRACE_ENTRY();
++
++ while (1) {
++ param = scst_get_next_token_str(&params);
++ if (param == NULL)
++ break;
++
++ p = scst_get_next_lexem(&param);
++ if (*p == '\0') {
++ PRINT_ERROR("Syntax error at %s (device %s)",
++ param, virt_dev->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (allowed_params != NULL) {
++ const char **a = allowed_params;
++ bool allowed = false;
++
++ while (*a != NULL) {
++ if (!strcasecmp(*a, p)) {
++ allowed = true;
++ break;
++ }
++ a++;
++ }
++
++ if (!allowed) {
++ PRINT_ERROR("Unknown parameter %s (device %s)", p,
++ virt_dev->name);
++ res = -EINVAL;
++ goto out;
++ }
++ }
++
++ pp = scst_get_next_lexem(&param);
++ if (*pp == '\0') {
++ PRINT_ERROR("Parameter %s value missed for device %s",
++ p, virt_dev->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (scst_get_next_lexem(&param)[0] != '\0') {
++ PRINT_ERROR("Too many parameter's %s values (device %s)",
++ p, virt_dev->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (!strcasecmp("filename", p)) {
++ if (*pp != '/') {
++ PRINT_ERROR("Filename %s must be global "
++ "(device %s)", pp, virt_dev->name);
++ res = -EINVAL;
++ goto out;
++ }
++
++ virt_dev->filename = kstrdup(pp, GFP_KERNEL);
++ if (virt_dev->filename == NULL) {
++ PRINT_ERROR("Unable to duplicate file name %s "
++ "(device %s)", pp, virt_dev->name);
++ res = -ENOMEM;
++ goto out;
++ }
++ continue;
++ }
++
++ res = strict_strtoul(pp, 0, &val);
++ if (res != 0) {
++ PRINT_ERROR("strict_strtoul() for %s failed: %d "
++ "(device %s)", pp, res, virt_dev->name);
++ goto out;
++ }
++
++ if (!strcasecmp("write_through", p)) {
++ virt_dev->wt_flag = val;
++ TRACE_DBG("WRITE THROUGH %d", virt_dev->wt_flag);
++ } else if (!strcasecmp("nv_cache", p)) {
++ virt_dev->nv_cache = val;
++ TRACE_DBG("NON-VOLATILE CACHE %d", virt_dev->nv_cache);
++ } else if (!strcasecmp("o_direct", p)) {
++#if 0
++ virt_dev->o_direct_flag = val;
++ TRACE_DBG("O_DIRECT %d", virt_dev->o_direct_flag);
++#else
++ PRINT_INFO("O_DIRECT flag doesn't currently"
++ " work, ignoring it, use fileio_tgt "
++ "in O_DIRECT mode instead (device %s)", virt_dev->name);
++#endif
++ } else if (!strcasecmp("read_only", p)) {
++ virt_dev->rd_only = val;
++ TRACE_DBG("READ ONLY %d", virt_dev->rd_only);
++ } else if (!strcasecmp("removable", p)) {
++ virt_dev->removable = val;
++ TRACE_DBG("REMOVABLE %d", virt_dev->removable);
++ } else if (!strcasecmp("blocksize", p)) {
++ virt_dev->block_size = val;
++ virt_dev->block_shift = scst_calc_block_shift(
++ virt_dev->block_size);
++ if (virt_dev->block_shift < 9) {
++ res = -EINVAL;
++ goto out;
++ }
++ TRACE_DBG("block_size %d, block_shift %d",
++ virt_dev->block_size,
++ virt_dev->block_shift);
++ } else {
++ PRINT_ERROR("Unknown parameter %s (device %s)", p,
++ virt_dev->name);
++ res = -EINVAL;
++ goto out;
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* scst_vdisk_mutex supposed to be held */
++static int vdev_fileio_add_device(const char *device_name, char *params)
++{
++ int res = 0;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ res = vdev_create(&vdisk_file_devtype, device_name, &virt_dev);
++ if (res != 0)
++ goto out;
++
++ virt_dev->command_set_version = 0x04C0; /* SBC-3 */
++
++ virt_dev->wt_flag = DEF_WRITE_THROUGH;
++ virt_dev->nv_cache = DEF_NV_CACHE;
++ virt_dev->o_direct_flag = DEF_O_DIRECT;
++
++ res = vdev_parse_add_dev_params(virt_dev, params, NULL);
++ if (res != 0)
++ goto out_destroy;
++
++ if (virt_dev->rd_only && (virt_dev->wt_flag || virt_dev->nv_cache)) {
++ PRINT_ERROR("Write options on read only device %s",
++ virt_dev->name);
++ res = -EINVAL;
++ goto out_destroy;
++ }
++
++ if (virt_dev->filename == NULL) {
++ PRINT_ERROR("File name required (device %s)", virt_dev->name);
++ res = -EINVAL;
++ goto out_destroy;
++ }
++
++ list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
++
++ vdisk_report_registering(virt_dev);
++
++ virt_dev->virt_id = scst_register_virtual_device(virt_dev->vdev_devt,
++ virt_dev->name);
++ if (virt_dev->virt_id < 0) {
++ res = virt_dev->virt_id;
++ goto out_del;
++ }
++
++ TRACE_DBG("Registered virt_dev %s with id %d", virt_dev->name,
++ virt_dev->virt_id);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ list_del(&virt_dev->vdev_list_entry);
++
++out_destroy:
++ vdev_destroy(virt_dev);
++ goto out;
++}
++
++/* scst_vdisk_mutex supposed to be held */
++static int vdev_blockio_add_device(const char *device_name, char *params)
++{
++ int res = 0;
++ const char *allowed_params[] = { "filename", "read_only", "removable",
++ "blocksize", "nv_cache", NULL };
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ res = vdev_create(&vdisk_blk_devtype, device_name, &virt_dev);
++ if (res != 0)
++ goto out;
++
++ virt_dev->command_set_version = 0x04C0; /* SBC-3 */
++
++ virt_dev->blockio = 1;
++
++ res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
++ if (res != 0)
++ goto out_destroy;
++
++ if (virt_dev->filename == NULL) {
++ PRINT_ERROR("File name required (device %s)", virt_dev->name);
++ res = -EINVAL;
++ goto out_destroy;
++ }
++
++ list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
++
++ vdisk_report_registering(virt_dev);
++
++ virt_dev->virt_id = scst_register_virtual_device(virt_dev->vdev_devt,
++ virt_dev->name);
++ if (virt_dev->virt_id < 0) {
++ res = virt_dev->virt_id;
++ goto out_del;
++ }
++
++ TRACE_DBG("Registered virt_dev %s with id %d", virt_dev->name,
++ virt_dev->virt_id);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ list_del(&virt_dev->vdev_list_entry);
++
++out_destroy:
++ vdev_destroy(virt_dev);
++ goto out;
++}
++
++/* scst_vdisk_mutex supposed to be held */
++static int vdev_nullio_add_device(const char *device_name, char *params)
++{
++ int res = 0;
++ const char *allowed_params[] = { "read_only", "removable",
++ "blocksize", NULL };
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ res = vdev_create(&vdisk_null_devtype, device_name, &virt_dev);
++ if (res != 0)
++ goto out;
++
++ virt_dev->command_set_version = 0x04C0; /* SBC-3 */
++
++ virt_dev->nullio = 1;
++
++ res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
++ if (res != 0)
++ goto out_destroy;
++
++ list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
++
++ vdisk_report_registering(virt_dev);
++
++ virt_dev->virt_id = scst_register_virtual_device(virt_dev->vdev_devt,
++ virt_dev->name);
++ if (virt_dev->virt_id < 0) {
++ res = virt_dev->virt_id;
++ goto out_del;
++ }
++
++ TRACE_DBG("Registered virt_dev %s with id %d", virt_dev->name,
++ virt_dev->virt_id);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ list_del(&virt_dev->vdev_list_entry);
++
++out_destroy:
++ vdev_destroy(virt_dev);
++ goto out;
++}
++
++static ssize_t vdisk_add_fileio_device(const char *device_name, char *params)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = vdev_fileio_add_device(device_name, params);
++
++ mutex_unlock(&scst_vdisk_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t vdisk_add_blockio_device(const char *device_name, char *params)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = vdev_blockio_add_device(device_name, params);
++
++ mutex_unlock(&scst_vdisk_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++}
++
++static ssize_t vdisk_add_nullio_device(const char *device_name, char *params)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = vdev_nullio_add_device(device_name, params);
++
++ mutex_unlock(&scst_vdisk_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++}
++
++/* scst_vdisk_mutex supposed to be held */
++static void vdev_del_device(struct scst_vdisk_dev *virt_dev)
++{
++ TRACE_ENTRY();
++
++ scst_unregister_virtual_device(virt_dev->virt_id);
++
++ list_del(&virt_dev->vdev_list_entry);
++
++ PRINT_INFO("Virtual device %s unregistered", virt_dev->name);
++ TRACE_DBG("virt_id %d unregistered", virt_dev->virt_id);
++
++ vdev_destroy(virt_dev);
++
++ return;
++}
++
++static ssize_t vdisk_del_device(const char *device_name)
++{
++ int res = 0;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ virt_dev = vdev_find(device_name);
++ if (virt_dev == NULL) {
++ PRINT_ERROR("Device %s not found", device_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ vdev_del_device(virt_dev);
++
++out_unlock:
++ mutex_unlock(&scst_vdisk_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* scst_vdisk_mutex supposed to be held */
++static ssize_t __vcdrom_add_device(const char *device_name, char *params)
++{
++ int res = 0;
++ const char *allowed_params[] = { NULL }; /* no params */
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ res = vdev_create(&vcdrom_devtype, device_name, &virt_dev);
++ if (res != 0)
++ goto out;
++
++ virt_dev->command_set_version = 0x02A0; /* MMC-3 */
++
++ virt_dev->rd_only = 1;
++ virt_dev->removable = 1;
++ virt_dev->cdrom_empty = 1;
++
++ virt_dev->block_size = DEF_CDROM_BLOCKSIZE;
++ virt_dev->block_shift = DEF_CDROM_BLOCKSIZE_SHIFT;
++
++ res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
++ if (res != 0)
++ goto out_destroy;
++
++ list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
++
++ vdisk_report_registering(virt_dev);
++
++ virt_dev->virt_id = scst_register_virtual_device(virt_dev->vdev_devt,
++ virt_dev->name);
++ if (virt_dev->virt_id < 0) {
++ res = virt_dev->virt_id;
++ goto out_del;
++ }
++
++ TRACE_DBG("Registered virt_dev %s with id %d", virt_dev->name,
++ virt_dev->virt_id);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ list_del(&virt_dev->vdev_list_entry);
++
++out_destroy:
++ vdev_destroy(virt_dev);
++ goto out;
++}
++
++static ssize_t vcdrom_add_device(const char *device_name, char *params)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ res = __vcdrom_add_device(device_name, params);
++
++ mutex_unlock(&scst_vdisk_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++}
++
++static ssize_t vcdrom_del_device(const char *device_name)
++{
++ int res = 0;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ virt_dev = vdev_find(device_name);
++ if (virt_dev == NULL) {
++ PRINT_ERROR("Device %s not found", device_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ vdev_del_device(virt_dev);
++
++out_unlock:
++ mutex_unlock(&scst_vdisk_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
++ char *buffer)
++{
++ loff_t err;
++ char *old_fn, *p, *pp;
++ const char *filename = NULL;
++ int length = strlen(buffer);
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ p = buffer;
++
++ while (isspace(*p) && *p != '\0')
++ p++;
++ filename = p;
++ p = &buffer[length-1];
++ pp = &buffer[length];
++ while (isspace(*p) && (*p != '\0')) {
++ pp = p;
++ p--;
++ }
++ *pp = '\0';
++
++ res = scst_suspend_activity(true);
++ if (res != 0)
++ goto out;
++
++ /* To sync with detach*() functions */
++ mutex_lock(&scst_mutex);
++
++ if (*filename == '\0') {
++ virt_dev->cdrom_empty = 1;
++ TRACE_DBG("%s", "No media");
++ } else if (*filename != '/') {
++ PRINT_ERROR("File path \"%s\" is not absolute", filename);
++ res = -EINVAL;
++ goto out_unlock;
++ } else
++ virt_dev->cdrom_empty = 0;
++
++ old_fn = virt_dev->filename;
++
++ if (!virt_dev->cdrom_empty) {
++ int len = strlen(filename) + 1;
++ char *fn = kmalloc(len, GFP_KERNEL);
++ if (fn == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s",
++ "Allocation of filename failed");
++ res = -ENOMEM;
++ goto out_unlock;
++ }
++
++ strlcpy(fn, filename, len);
++ virt_dev->filename = fn;
++
++ res = vdisk_get_file_size(virt_dev->filename,
++ virt_dev->blockio, &err);
++ if (res != 0)
++ goto out_free_fn;
++ } else {
++ err = 0;
++ virt_dev->filename = NULL;
++ }
++
++ if (virt_dev->prevent_allow_medium_removal) {
++ PRINT_ERROR("Prevent medium removal for "
++ "virtual device with name %s", virt_dev->name);
++ res = -EINVAL;
++ goto out_free_fn;
++ }
++
++ virt_dev->file_size = err;
++ virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
++ if (!virt_dev->cdrom_empty)
++ virt_dev->media_changed = 1;
++
++ mutex_unlock(&scst_mutex);
++
++ scst_dev_del_all_thr_data(virt_dev->dev);
++
++ if (!virt_dev->cdrom_empty) {
++ PRINT_INFO("Changed SCSI target virtual cdrom %s "
++ "(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld,"
++ " cyln=%lld%s)", virt_dev->name,
++ vdev_get_filename(virt_dev),
++ virt_dev->file_size >> 20, virt_dev->block_size,
++ (long long unsigned int)virt_dev->nblocks,
++ (long long unsigned int)virt_dev->nblocks/64/32,
++ virt_dev->nblocks < 64*32 ? " !WARNING! cyln less "
++ "than 1" : "");
++ } else {
++ PRINT_INFO("Removed media from SCSI target virtual cdrom %s",
++ virt_dev->name);
++ }
++
++ kfree(old_fn);
++
++out_resume:
++ scst_resume_activity();
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free_fn:
++ kfree(virt_dev->filename);
++ virt_dev->filename = old_fn;
++
++out_unlock:
++ mutex_unlock(&scst_mutex);
++ goto out_resume;
++}
++
++static int vcdrom_sysfs_process_filename_store(struct scst_sysfs_work_item *work)
++{
++ int res;
++ struct scst_device *dev = work->dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ /* It's safe, since we taken dev_kobj and dh_priv NULLed in attach() */
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ res = vcdrom_change(virt_dev, work->buf);
++
++ kobject_put(&dev->dev_kobj);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ char *i_buf;
++ struct scst_sysfs_work_item *work;
++ struct scst_device *dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ i_buf = kmalloc(count+1, GFP_KERNEL);
++ if (i_buf == NULL) {
++ PRINT_ERROR("Unable to alloc intermediate buffer with size %zd",
++ count+1);
++ res = -ENOMEM;
++ goto out;
++ }
++ memcpy(i_buf, buf, count);
++ i_buf[count] = '\0';
++
++ res = scst_alloc_sysfs_work(vcdrom_sysfs_process_filename_store,
++ false, &work);
++ if (res != 0)
++ goto out_free;
++
++ work->buf = i_buf;
++ work->dev = dev;
++
++ kobject_get(&dev->dev_kobj);
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(i_buf);
++ goto out;
++}
++
++static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ pos = sprintf(buf, "%lld\n", virt_dev->file_size / 1024 / 1024);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t vdisk_sysfs_blocksize_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ pos = sprintf(buf, "%d\n%s", (int)virt_dev->block_size,
++ (virt_dev->block_size == DEF_DISK_BLOCKSIZE) ? "" :
++ SCST_SYSFS_KEY_MARK "\n");
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t vdisk_sysfs_rd_only_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ pos = sprintf(buf, "%d\n%s", virt_dev->rd_only ? 1 : 0,
++ (virt_dev->rd_only == DEF_RD_ONLY) ? "" :
++ SCST_SYSFS_KEY_MARK "");
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t vdisk_sysfs_wt_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ pos = sprintf(buf, "%d\n%s", virt_dev->wt_flag ? 1 : 0,
++ (virt_dev->wt_flag == DEF_WRITE_THROUGH) ? "" :
++ SCST_SYSFS_KEY_MARK "");
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t vdisk_sysfs_nv_cache_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ pos = sprintf(buf, "%d\n%s", virt_dev->nv_cache ? 1 : 0,
++ (virt_dev->nv_cache == DEF_NV_CACHE) ? "" :
++ SCST_SYSFS_KEY_MARK "");
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t vdisk_sysfs_o_direct_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ pos = sprintf(buf, "%d\n%s", virt_dev->o_direct_flag ? 1 : 0,
++ (virt_dev->o_direct_flag == DEF_O_DIRECT) ? "" :
++ SCST_SYSFS_KEY_MARK "");
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ pos = sprintf(buf, "%d\n", virt_dev->removable ? 1 : 0);
++
++ if ((virt_dev->dev->type != TYPE_ROM) &&
++ (virt_dev->removable != DEF_REMOVABLE))
++ pos += sprintf(&buf[pos], "%s\n", SCST_SYSFS_KEY_MARK);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static int vdev_sysfs_process_get_filename(struct scst_sysfs_work_item *work)
++{
++ int res = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = work->dev;
++
++ if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
++ res = -EINTR;
++ goto out_put;
++ }
++
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ if (virt_dev == NULL)
++ goto out_unlock;
++
++ if (virt_dev->filename != NULL)
++ work->res_buf = kasprintf(GFP_KERNEL, "%s\n%s\n",
++ vdev_get_filename(virt_dev), SCST_SYSFS_KEY_MARK);
++ else
++ work->res_buf = kasprintf(GFP_KERNEL, "%s\n",
++ vdev_get_filename(virt_dev));
++
++out_unlock:
++ mutex_unlock(&scst_vdisk_mutex);
++
++out_put:
++ kobject_put(&dev->dev_kobj);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int res = 0;
++ struct scst_device *dev;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ res = scst_alloc_sysfs_work(vdev_sysfs_process_get_filename,
++ true, &work);
++ if (res != 0)
++ goto out;
++
++ work->dev = dev;
++
++ kobject_get(&dev->dev_kobj);
++
++ scst_sysfs_work_get(work);
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res != 0)
++ goto out_put;
++
++ res = snprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n", work->res_buf);
++
++out_put:
++ scst_sysfs_work_put(work);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int vdisk_sysfs_process_resync_size_store(
++ struct scst_sysfs_work_item *work)
++{
++ int res;
++ struct scst_device *dev = work->dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ /* It's safe, since we taken dev_kobj and dh_priv NULLed in attach() */
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ res = vdisk_resync_size(virt_dev);
++
++ kobject_put(&dev->dev_kobj);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t vdisk_sysfs_resync_size_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_device *dev;
++ struct scst_sysfs_work_item *work;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++
++ res = scst_alloc_sysfs_work(vdisk_sysfs_process_resync_size_store,
++ false, &work);
++ if (res != 0)
++ goto out;
++
++ work->dev = dev;
++
++ kobject_get(&dev->dev_kobj);
++
++ res = scst_sysfs_queue_wait_work(work);
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res, i;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ write_lock(&vdisk_serial_rwlock);
++
++ if ((count > sizeof(virt_dev->t10_dev_id)) ||
++ ((count == sizeof(virt_dev->t10_dev_id)) &&
++ (buf[count-1] != '\n'))) {
++ PRINT_ERROR("T10 device id is too long (max %zd "
++ "characters)", sizeof(virt_dev->t10_dev_id)-1);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ memset(virt_dev->t10_dev_id, 0, sizeof(virt_dev->t10_dev_id));
++ memcpy(virt_dev->t10_dev_id, buf, count);
++
++ i = 0;
++ while (i < sizeof(virt_dev->t10_dev_id)) {
++ if (virt_dev->t10_dev_id[i] == '\n') {
++ virt_dev->t10_dev_id[i] = '\0';
++ break;
++ }
++ i++;
++ }
++
++ virt_dev->t10_dev_id_set = 1;
++
++ res = count;
++
++ PRINT_INFO("T10 device id for device %s changed to %s", virt_dev->name,
++ virt_dev->t10_dev_id);
++
++out_unlock:
++ write_unlock(&vdisk_serial_rwlock);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t vdev_sysfs_t10_dev_id_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ read_lock(&vdisk_serial_rwlock);
++ pos = sprintf(buf, "%s\n%s", virt_dev->t10_dev_id,
++ virt_dev->t10_dev_id_set ? SCST_SYSFS_KEY_MARK "\n" : "");
++ read_unlock(&vdisk_serial_rwlock);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t vdev_sysfs_usn_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res, i;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = dev->dh_priv;
++
++ write_lock(&vdisk_serial_rwlock);
++
++ if ((count > sizeof(virt_dev->usn)) ||
++ ((count == sizeof(virt_dev->usn)) &&
++ (buf[count-1] != '\n'))) {
++ PRINT_ERROR("USN is too long (max %zd "
++ "characters)", sizeof(virt_dev->usn)-1);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ memset(virt_dev->usn, 0, sizeof(virt_dev->usn));
++ memcpy(virt_dev->usn, buf, count);
++
++ i = 0;
++ while (i < sizeof(virt_dev->usn)) {
++ if (virt_dev->usn[i] == '\n') {
++ virt_dev->usn[i] = '\0';
++ break;
++ }
++ i++;
++ }
++
++ virt_dev->usn_set = 1;
++
++ res = count;
++
++ PRINT_INFO("USN for device %s changed to %s", virt_dev->name,
++ virt_dev->usn);
++
++out_unlock:
++ write_unlock(&vdisk_serial_rwlock);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t vdev_sysfs_usn_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos = 0;
++ struct scst_device *dev;
++ struct scst_vdisk_dev *virt_dev;
++
++ TRACE_ENTRY();
++
++ dev = container_of(kobj, struct scst_device, dev_kobj);
++ virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
++
++ read_lock(&vdisk_serial_rwlock);
++ pos = sprintf(buf, "%s\n%s", virt_dev->usn,
++ virt_dev->usn_set ? SCST_SYSFS_KEY_MARK "\n" : "");
++ read_unlock(&vdisk_serial_rwlock);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static int __init init_scst_vdisk(struct scst_dev_type *devtype)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ devtype->module = THIS_MODULE;
++
++ res = scst_register_virtual_dev_driver(devtype);
++ if (res < 0)
++ goto out;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++}
++
++static void exit_scst_vdisk(struct scst_dev_type *devtype)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_vdisk_mutex);
++ while (1) {
++ struct scst_vdisk_dev *virt_dev;
++
++ if (list_empty(&vdev_list))
++ break;
++
++ virt_dev = list_entry(vdev_list.next, typeof(*virt_dev),
++ vdev_list_entry);
++
++ vdev_del_device(virt_dev);
++ }
++ mutex_unlock(&scst_vdisk_mutex);
++
++ scst_unregister_virtual_dev_driver(devtype);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int __init init_scst_vdisk_driver(void)
++{
++ int res;
++
++ vdisk_thr_cachep = KMEM_CACHE(scst_vdisk_thr, SCST_SLAB_FLAGS);
++ if (vdisk_thr_cachep == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++
++ blockio_work_cachep = KMEM_CACHE(scst_blockio_work, SCST_SLAB_FLAGS);
++ if (blockio_work_cachep == NULL) {
++ res = -ENOMEM;
++ goto out_free_vdisk_cache;
++ }
++
++ if (num_threads < 1) {
++ PRINT_ERROR("num_threads can not be less than 1, use "
++ "default %d", DEF_NUM_THREADS);
++ num_threads = DEF_NUM_THREADS;
++ }
++
++ vdisk_file_devtype.threads_num = num_threads;
++ vcdrom_devtype.threads_num = num_threads;
++
++ atomic_set(&nullio_thr_data.hdr.ref, 1); /* never destroy it */
++
++ res = init_scst_vdisk(&vdisk_file_devtype);
++ if (res != 0)
++ goto out_free_slab;
++
++ res = init_scst_vdisk(&vdisk_blk_devtype);
++ if (res != 0)
++ goto out_free_vdisk;
++
++ res = init_scst_vdisk(&vdisk_null_devtype);
++ if (res != 0)
++ goto out_free_blk;
++
++ res = init_scst_vdisk(&vcdrom_devtype);
++ if (res != 0)
++ goto out_free_null;
++
++out:
++ return res;
++
++out_free_null:
++ exit_scst_vdisk(&vdisk_null_devtype);
++
++out_free_blk:
++ exit_scst_vdisk(&vdisk_blk_devtype);
++
++out_free_vdisk:
++ exit_scst_vdisk(&vdisk_file_devtype);
++
++out_free_slab:
++ kmem_cache_destroy(blockio_work_cachep);
++
++out_free_vdisk_cache:
++ kmem_cache_destroy(vdisk_thr_cachep);
++ goto out;
++}
++
++static void __exit exit_scst_vdisk_driver(void)
++{
++ exit_scst_vdisk(&vdisk_null_devtype);
++ exit_scst_vdisk(&vdisk_blk_devtype);
++ exit_scst_vdisk(&vdisk_file_devtype);
++ exit_scst_vdisk(&vcdrom_devtype);
++
++ kmem_cache_destroy(blockio_work_cachep);
++ kmem_cache_destroy(vdisk_thr_cachep);
++}
++
++module_init(init_scst_vdisk_driver);
++module_exit(exit_scst_vdisk_driver);
++
++MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCSI disk (type 0) and CDROM (type 5) dev handler for "
++ "SCST using files on file systems or block devices");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/Documentation/scst/README.scst linux-2.6.36/Documentation/scst/README.scst
+--- orig/linux-2.6.36/Documentation/scst/README.scst
++++ linux-2.6.36/Documentation/scst/README.scst
+@@ -0,0 +1,1453 @@
++Generic SCSI target mid-level for Linux (SCST)
++==============================================
++
++SCST is designed to provide unified, consistent interface between SCSI
++target drivers and Linux kernel and simplify target drivers development
++as much as possible. Detail description of SCST's features and internals
++could be found on its Internet page http://scst.sourceforge.net.
++
++SCST supports the following I/O modes:
++
++ * Pass-through mode with one to many relationship, i.e. when multiple
++ initiators can connect to the exported pass-through devices, for
++ the following SCSI devices types: disks (type 0), tapes (type 1),
++ processors (type 3), CDROMs (type 5), MO disks (type 7), medium
++ changers (type 8) and RAID controllers (type 0xC).
++
++ * FILEIO mode, which allows to use files on file systems or block
++ devices as virtual remotely available SCSI disks or CDROMs with
++ benefits of the Linux page cache.
++
++ * BLOCKIO mode, which performs direct block IO with a block device,
++ bypassing page-cache for all operations. This mode works ideally with
++ high-end storage HBAs and for applications that either do not need
++ caching between application and disk or need the large block
++ throughput.
++
++ * "Performance" device handlers, which provide in pseudo pass-through
++ mode a way for direct performance measurements without overhead of
++ actual data transferring from/to underlying SCSI device.
++
++In addition, SCST supports advanced per-initiator access and devices
++visibility management, so different initiators could see different set
++of devices with different access permissions. See below for details.
++
++Full list of SCST features and comparison with other Linux targets you
++can find on http://scst.sourceforge.net/comparison.html.
++
++Installation
++------------
++
++To see your devices remotely, you need to add a corresponding LUN for
++them (see below how). By default, no local devices are seen remotely.
++There must be LUN 0 in each LUNs set (security group), i.e. LUs
++numeration must not start from, e.g., 1. Otherwise you will see no
++devices on remote initiators and SCST core will write into the kernel
++log message: "tgt_dev for LUN 0 not found, command to unexisting LU?"
++
++It is highly recommended to use scstadmin utility for configuring
++devices and security groups.
++
++The flow of SCST inialization should be as the following:
++
++1. Load of SCST modules with necessary module parameters, if needed.
++
++2. Configure targets, devices, LUNs, etc. using either scstadmin
++(recommended), or the sysfs interface directly as described below.
++
++If you experience problems during modules load or running, check your
++kernel logs (or run dmesg command for the few most recent messages).
++
++IMPORTANT: Without loading appropriate device handler, corresponding devices
++========= will be invisible for remote initiators, which could lead to holes
++ in the LUN addressing, so automatic device scanning by remote SCSI
++ mid-level could not notice the devices. Therefore you will have
++ to add them manually via
++ 'echo "- - -" >/sys/class/scsi_host/hostX/scan',
++ where X - is the host number.
++
++IMPORTANT: Working of target and initiator on the same host is
++========= supported, except the following 2 cases: swap over target exported
++ device and using a writable mmap over a file from target
++ exported device. The latter means you can't mount a file
++ system over target exported device. In other words, you can
++ freely use any sg, sd, st, etc. devices imported from target
++ on the same host, but you can't mount file systems or put
++ swap on them. This is a limitation of Linux memory/cache
++ manager, because in this case an OOM deadlock like: system
++ needs some memory -> it decides to clear some cache -> cache
++ needs to write on target exported device -> initiator sends
++ request to the target -> target needs memory -> system needs
++ even more memory -> deadlock.
++
++IMPORTANT: In the current version simultaneous access to local SCSI devices
++========= via standard high-level SCSI drivers (sd, st, sg, etc.) and
++ SCST's target drivers is unsupported. Especially it is
++ important for execution via sg and st commands that change
++ the state of devices and their parameters, because that could
++ lead to data corruption. If any such command is done, at
++ least related device handler(s) must be restarted. For block
++ devices READ/WRITE commands using direct disk handler are
++ generally safe.
++
++Usage in failover mode
++----------------------
++
++It is recommended to use TEST UNIT READY ("tur") command to check if
++SCST target is alive in MPIO configurations.
++
++Device handlers
++---------------
++
++Device specific drivers (device handlers) are plugins for SCST, which
++help SCST to analyze incoming requests and determine parameters,
++specific to various types of devices. If an appropriate device handler
++for a SCSI device type isn't loaded, SCST doesn't know how to handle
++devices of this type, so they will be invisible for remote initiators
++(more precisely, "LUN not supported" sense code will be returned).
++
++In addition to device handlers for real devices, there are VDISK, user
++space and "performance" device handlers.
++
++VDISK device handler works over files on file systems and makes from
++them virtual remotely available SCSI disks or CDROM's. In addition, it
++allows to work directly over a block device, e.g. local IDE or SCSI disk
++or ever disk partition, where there is no file systems overhead. Using
++block devices comparing to sending SCSI commands directly to SCSI
++mid-level via scsi_do_req()/scsi_execute_async() has advantage that data
++are transferred via system cache, so it is possible to fully benefit from
++caching and read ahead performed by Linux's VM subsystem. The only
++disadvantage here that in the FILEIO mode there is superfluous data
++copying between the cache and SCST's buffers. This issue is going to be
++addressed in the next release. Virtual CDROM's are useful for remote
++installation. See below for details how to setup and use VDISK device
++handler.
++
++"Performance" device handlers for disks, MO disks and tapes in their
++exec() method skip (pretend to execute) all READ and WRITE operations
++and thus provide a way for direct link performance measurements without
++overhead of actual data transferring from/to underlying SCSI device.
++
++NOTE: Since "perf" device handlers on READ operations don't touch the
++==== commands' data buffer, it is returned to remote initiators as it
++ was allocated, without even being zeroed. Thus, "perf" device
++ handlers impose some security risk, so use them with caution.
++
++Compilation options
++-------------------
++
++There are the following compilation options, that could be change using
++your favorite kernel configuration Makefile target, e.g. "make xconfig":
++
++ - CONFIG_SCST_DEBUG - if defined, turns on some debugging code,
++ including some logging. Makes the driver considerably bigger and slower,
++ producing large amount of log data.
++
++ - CONFIG_SCST_TRACING - if defined, turns on ability to log events. Makes the
++ driver considerably bigger and leads to some performance loss.
++
++ - CONFIG_SCST_EXTRACHECKS - if defined, adds extra validity checks in
++ the various places.
++
++ - CONFIG_SCST_USE_EXPECTED_VALUES - if not defined (default), initiator
++ supplied expected data transfer length and direction will be used
++ only for verification purposes to return error or warn in case if one
++ of them is invalid. Instead, locally decoded from SCSI command values
++ will be used. This is necessary for security reasons, because
++ otherwise a faulty initiator can crash target by supplying invalid
++ value in one of those parameters. This is especially important in
++ case of pass-through mode. If CONFIG_SCST_USE_EXPECTED_VALUES is
++ defined, initiator supplied expected data transfer length and
++ direction will override the locally decoded values. This might be
++ necessary if internal SCST commands translation table doesn't contain
++ SCSI command, which is used in your environment. You can know that if
++ you enable "minor" trace level and have messages like "Unknown
++ opcode XX for YY. Should you update scst_scsi_op_table?" in your
++ kernel log and your initiator returns an error. Also report those
++ messages in the SCST mailing list scst-devel@lists.sourceforge.net.
++ Note, that not all SCSI transports support supplying expected values.
++
++ - CONFIG_SCST_DEBUG_TM - if defined, turns on task management functions
++ debugging, when on LUN 6 some of the commands will be delayed for
++ about 60 sec., so making the remote initiator send TM functions, eg
++ ABORT TASK and TARGET RESET. Also define
++ CONFIG_SCST_TM_DBG_GO_OFFLINE symbol in the Makefile if you want that
++ the device eventually become completely unresponsive, or otherwise to
++ circle around ABORTs and RESETs code. Needs CONFIG_SCST_DEBUG turned
++ on.
++
++ - CONFIG_SCST_STRICT_SERIALIZING - if defined, makes SCST send all commands to
++ underlying SCSI device synchronously, one after one. This makes task
++ management more reliable, with cost of some performance penalty. This
++ is mostly actual for stateful SCSI devices like tapes, where the
++ result of command's execution depends from device's settings defined
++ by previous commands. Disk and RAID devices are stateless in the most
++ cases. The current SCSI core in Linux doesn't allow to abort all
++ commands reliably if they sent asynchronously to a stateful device.
++ Turned off by default, turn it on if you use stateful device(s) and
++ need as much error recovery reliability as possible. As a side effect
++ of CONFIG_SCST_STRICT_SERIALIZING, on kernels below 2.6.30 no kernel
++ patching is necessary for pass-through device handlers (scst_disk,
++ etc.).
++
++ - CONFIG_SCST_TEST_IO_IN_SIRQ - if defined, allows SCST to submit selected
++ SCSI commands (TUR and READ/WRITE) from soft-IRQ context (tasklets).
++ Enabling it will decrease amount of context switches and slightly
++ improve performance. The goal of this option is to be able to measure
++ overhead of the context switches. If after enabling this option you
++ don't see under load in vmstat output on the target significant
++ decrease of amount of context switches, then your target driver
++ doesn't submit commands to SCST in IRQ context. For instance,
++ iSCSI-SCST doesn't do that, but qla2x00t with
++ CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD disabled - does. This option is
++ designed to be used with vdisk NULLIO backend.
++
++ WARNING! Using this option enabled with other backend than vdisk
++ NULLIO is unsafe and can lead you to a kernel crash!
++
++ - CONFIG_SCST_STRICT_SECURITY - if defined, makes SCST zero allocated data
++ buffers. Undefining it (default) considerably improves performance
++ and eases CPU load, but could create a security hole (information
++ leakage), so enable it, if you have strict security requirements.
++
++ - CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING - if defined,
++ in case when TASK MANAGEMENT function ABORT TASK is trying to abort a
++ command, which has already finished, remote initiator, which sent the
++ ABORT TASK request, will receive TASK NOT EXIST (or ABORT FAILED)
++ response for the ABORT TASK request. This is more logical response,
++ since, because the command finished, attempt to abort it failed, but
++ some initiators, particularly VMware iSCSI initiator, consider TASK
++ NOT EXIST response as if the target got crazy and try to RESET it.
++ Then sometimes get crazy itself. So, this option is disabled by
++ default.
++
++ - CONFIG_SCST_MEASURE_LATENCY - if defined, provides in "latency" files
++ global and per-LUN average commands processing latency statistic. You
++ can clear already measured results by writing 0 in each file. Note,
++ you need a non-preemptible kernel to have correct results.
++
++HIGHMEM kernel configurations are fully supported, but not recommended
++for performance reasons.
++
++Module parameters
++-----------------
++
++Module scst supports the following parameters:
++
++ - scst_threads - allows to set count of SCST's threads. By default it
++ is CPU count.
++
++ - scst_max_cmd_mem - sets maximum amount of memory in MB allowed to be
++ consumed by the SCST commands for data buffers at any given time. By
++ default it is approximately TotalMem/4.
++
++SCST sysfs interface
++--------------------
++
++Root of SCST sysfs interface is /sys/kernel/scst_tgt. It has the
++following entries:
++
++ - devices - this is a root subdirectory for all SCST devices
++
++ - handlers - this is a root subdirectory for all SCST dev handlers
++
++ - max_tasklet_cmd - specifies how many commands at max can be queued in
++ the SCST core simultaneously from all connected initiators to allow
++ processing commands in soft-IRQ context in tasklets. If the count of
++ the commands exceeds this value, then all of them will be processed
++ only in threads. This is to to prevent possible starvation under
++ heavy load and in some cases to improve performance by more evenly
++ spreading load over available CPUs.
++
++ - sgv - this is a root subdirectory for all SCST SGV caches
++
++ - targets - this is a root subdirectory for all SCST targets
++
++ - setup_id - allows to read and write SCST setup ID. This ID can be
++ used in cases, when the same SCST configuration should be installed
++ on several targets, but exported from those targets devices should
++ have different IDs and SNs. For instance, VDISK dev handler uses this
++ ID to generate T10 vendor specific identifier and SN of the devices.
++
++ - threads - allows to read and set number of global SCST I/O threads.
++ Those threads used with async. dev handlers, for instance, vdisk
++ BLOCKIO or NULLIO.
++
++ - trace_level - allows to enable and disable various tracing
++ facilities. See content of this file for help how to use it.
++
++ - version - read-only attribute, which allows to see version of
++ SCST and enabled optional features.
++
++ - last_sysfs_mgmt_res - read-only attribute returning completion status
++ of the last management command. In the sysfs implementation there are
++ some problems between internal sysfs and internal SCST locking. To
++ avoid them in some cases sysfs calls can return error with errno
++ EAGAIN. This doesn't mean the operation failed. It only means that
++ the operation queued and not yet completed. To wait for it to
++ complete, an management tool should poll this file. If the operation
++ hasn't yet completed, it will also return EAGAIN. But after it's
++ completed, it will return the result of this operation (0 for success
++ or -errno for error).
++
++Each SCST sysfs file (attribute) can contain in the last line mark
++"[key]". It is automatically added mark used to allow scstadmin to see
++which attributes it should save in the config file. You can ignore it.
++
++"Devices" subdirectory contains subdirectories for each SCST devices.
++
++Content of each device's subdirectory is dev handler specific. See
++documentation for your dev handlers for more info about it as well as
++SysfsRules file for more info about common to all dev handlers rules.
++SCST dev handlers can have the following common entries:
++
++ - exported - subdirectory containing links to all LUNs where this
++ device was exported.
++
++ - handler - if dev handler determined for this device, this link points
++ to it. The handler can be not set for pass-through devices.
++
++ - threads_num - shows and allows to set number of threads in this device's
++ threads pool. If 0 - no threads will be created, and global SCST
++ threads pool will be used. If <0 - creation of the threads pool is
++ prohibited.
++
++ - threads_pool_type - shows and allows to sets threads pool type.
++ Possible values: "per_initiator" and "shared". When the value is
++ "per_initiator" (default), each session from each initiator will use
++ separate dedicated pool of threads. When the value is "shared", all
++ sessions from all initiators will share the same per-device pool of
++ threads. Valid only if threads_num attribute >0.
++
++ - dump_prs - allows to dump persistent reservations information in the
++ kernel log.
++
++ - type - SCSI type of this device
++
++See below for more information about other entries of this subdirectory
++of the standard SCST dev handlers.
++
++"Handlers" subdirectory contains subdirectories for each SCST dev
++handler.
++
++Content of each handler's subdirectory is dev handler specific. See
++documentation for your dev handlers for more info about it as well as
++SysfsRules file for more info about common to all dev handlers rules.
++SCST dev handlers can have the following common entries:
++
++ - mgmt - this entry allows to create virtual devices and their
++ attributes (for virtual devices dev handlers) or assign/unassign real
++ SCSI devices to/from this dev handler (for pass-through dev
++ handlers).
++
++ - trace_level - allows to enable and disable various tracing
++ facilities. See content of this file for help how to use it.
++
++ - type - SCSI type of devices served by this dev handler.
++
++See below for more information about other entries of this subdirectory
++of the standard SCST dev handlers.
++
++"Sgv" subdirectory contains statistic information of SCST SGV caches. It
++has the following entries:
++
++ - None, one or more subdirectories for each existing SGV cache.
++
++ - global_stats - file containing global SGV caches statistics.
++
++Each SGV cache's subdirectory has the following item:
++
++ - stats - file containing statistics for this SGV caches.
++
++"Targets" subdirectory contains subdirectories for each SCST target.
++
++Content of each target's subdirectory is target specific. See
++documentation for your target for more info about it as well as
++SysfsRules file for more info about common to all targets rules.
++Every target should have at least the following entries:
++
++ - ini_groups - subdirectory, which contains and allows to define
++ initiator-oriented access control information, see below.
++
++ - luns - subdirectory, which contains list of available LUNs in the
++ target-oriented access control and allows to define it, see below.
++
++ - sessions - subdirectory containing connected to this target sessions.
++
++ - enabled - using this attribute you can enable or disable this target/
++ It allows to finish configuring it before it starts accepting new
++ connections. 0 by default.
++
++ - addr_method - used LUNs addressing method. Possible values:
++ "Peripheral" and "Flat". Most initiators work well with Peripheral
++ addressing method (default), but some (HP-UX, for instance) may
++ require Flat method. This attribute is also available in the
++ initiators security groups, so you can assign the addressing method
++ on per-initiator basis.
++
++ - io_grouping_type - defines how I/O from sessions to this target are
++ grouped together. This I/O grouping is very important for
++ performance. By setting this attribute in a right value, you can
++ considerably increase performance of your setup. This grouping is
++ performed only if you use CFQ I/O scheduler on the target and for
++ devices with threads_num >= 0 and, if threads_num > 0, with
++ threads_pool_type "per_initiator". Possible values:
++ "this_group_only", "never", "auto", or I/O group number >0. When the
++ value is "this_group_only" all I/O from all sessions in this target
++ will be grouped together. When the value is "never", I/O from
++ different sessions will not be grouped together, i.e. all sessions in
++ this target will have separate dedicated I/O groups. When the value
++ is "auto" (default), all I/O from initiators with the same name
++ (iSCSI initiator name, for instance) in all targets will be grouped
++ together with a separate dedicated I/O group for each initiator name.
++ For iSCSI this mode works well, but other transports usually use
++ different initiator names for different sessions, so using such
++ transports in MPIO configurations you should either use value
++ "this_group_only", or an explicit I/O group number. This attribute is
++ also available in the initiators security groups, so you can assign
++ the I/O grouping on per-initiator basis. See below for more info how
++ to use this attribute.
++
++ - rel_tgt_id - allows to read or write SCSI Relative Target Port
++ Identifier attribute. This identifier is used to identify SCSI Target
++ Ports by some SCSI commands, mainly by Persistent Reservations
++ commands. This identifier must be unique among all SCST targets, but
++ for convenience SCST allows disabled targets to have not unique
++ rel_tgt_id. In this case SCST will not allow to enable this target
++ until rel_tgt_id becomes unique. This attribute initialized unique by
++ SCST by default.
++
++A target driver may have also the following entries:
++
++ - "hw_target" - if the target driver supports both hardware and virtual
++ targets (for instance, an FC adapter supporting NPIV, which has
++ hardware targets for its physical ports as well as virtual NPIV
++ targets), this read only attribute for all hardware targets will
++ exist and contain value 1.
++
++Subdirectory "sessions" contains one subdirectory for each connected
++session with name equal to name of the connected initiator.
++
++Each session subdirectory contains the following entries:
++
++ - initiator_name - contains initiator name
++
++ - force_close - optional write-only attribute, which allows to force
++ close this session.
++
++ - active_commands - contains number of active, i.e. not yet or being
++ executed, SCSI commands in this session.
++
++ - commands - contains overall number of SCSI commands in this session.
++
++ - latency - if CONFIG_SCST_MEASURE_LATENCY enabled, contains latency
++ statistics for this session.
++
++ - luns - a link pointing out to the corresponding LUNs set (security
++ group) where this session was attached to.
++
++ - One or more "lunX" subdirectories, where 'X' is a number, for each LUN
++ this session has (see below).
++
++ - other target driver specific attributes and subdirectories.
++
++See below description of the VDISK's sysfs interface for samples.
++
++Access and devices visibility management (LUN masking)
++------------------------------------------------------
++
++Access and devices visibility management allows for an initiator or
++group of initiators to see different devices with different LUNs
++with necessary access permissions.
++
++SCST supports two modes of access control:
++
++1. Target-oriented. In this mode you define for each target a default
++set of LUNs, which are accessible to all initiators, connected to that
++target. This is a regular access control mode, which people usually mean
++thinking about access control in general. For instance, in IET this is
++the only supported mode.
++
++2. Initiator-oriented. In this mode you define which LUNs are accessible
++for each initiator. In this mode you should create for each set of one
++or more initiators, which should access to the same set of devices with
++the same LUNs, a separate security group, then add to it devices and
++names of allowed initiator(s).
++
++Both modes can be used simultaneously. In this case the
++initiator-oriented mode has higher priority, than the target-oriented,
++i.e. initiators are at first searched in all defined security groups for
++this target and, if none matches, the default target's set of LUNs is
++used. This set of LUNs might be empty, then the initiator will not see
++any LUNs from the target.
++
++You can at any time find out which set of LUNs each session is assigned
++to by looking where link
++/sys/kernel/scst_tgt/targets/target_driver/target_name/sessions/initiator_name/luns
++points to.
++
++To configure the target-oriented access control SCST provides the
++following interface. Each target's sysfs subdirectory
++(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "luns"
++subdirectory. This subdirectory contains the list of already defined
++target-oriented access control LUNs for this target as well as file
++"mgmt". This file has the following commands, which you can send to it,
++for instance, using "echo" shell command. You can always get a small
++help about supported commands by looking inside this file. "Parameters"
++are one or more param_name=value pairs separated by ';'.
++
++ - "add H:C:I:L lun [parameters]" - adds a pass-through device with
++ host:channel:id:lun with LUN "lun". Optionally, the device could be
++ marked as read only by using parameter "read_only". The recommended
++ way to find out H:C:I:L numbers is use of lsscsi utility.
++
++ - "replace H:C:I:L lun [parameters]" - replaces by pass-through device
++ with host:channel:id:lun existing with LUN "lun" device with
++ generation of INQUIRY DATA HAS CHANGED Unit Attention. If the old
++ device doesn't exist, this command acts as the "add" command.
++ Optionally, the device could be marked as read only by using
++ parameter "read_only". The recommended way to find out H:C:I:L
++ numbers is use of lsscsi utility.
++
++ - "add VNAME lun [parameters]" - adds a virtual device with name VNAME
++ with LUN "lun". Optionally, the device could be marked as read only
++ by using parameter "read_only".
++
++ - "replace VNAME lun [parameters]" - replaces by virtual device
++ with name VNAME existing with LUN "lun" device with generation of
++ INQUIRY DATA HAS CHANGED Unit Attention. If the old device doesn't
++ exist, this command acts as the "add" command. Optionally, the device
++ could be marked as read only by using parameter "read_only".
++
++ - "del lun" - deletes LUN lun
++
++ - "clear" - clears the list of devices
++
++To configure the initiator-oriented access control SCST provides the
++following interface. Each target's sysfs subdirectory
++(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "ini_groups"
++subdirectory. This subdirectory contains the list of already defined
++security groups for this target as well as file "mgmt". This file has
++the following commands, which you can send to it, for instance, using
++"echo" shell command. You can always get a small help about supported
++commands by looking inside this file.
++
++ - "create GROUP_NAME" - creates a new security group.
++
++ - "del GROUP_NAME" - deletes a new security group.
++
++Each security group's subdirectory contains 2 subdirectories: initiators
++and luns.
++
++Each "initiators" subdirectory contains list of added to this groups
++initiator as well as as well as file "mgmt". This file has the following
++commands, which you can send to it, for instance, using "echo" shell
++command. You can always get a small help about supported commands by
++looking inside this file.
++
++ - "add INITIATOR_NAME" - adds initiator with name INITIATOR_NAME to the
++ group.
++
++ - "del INITIATOR_NAME" - deletes initiator with name INITIATOR_NAME
++ from the group.
++
++ - "move INITIATOR_NAME DEST_GROUP_NAME" moves initiator with name
++ INITIATOR_NAME from the current group to group with name
++ DEST_GROUP_NAME.
++
++ - "clear" - deletes all initiators from this group.
++
++For "add" and "del" commands INITIATOR_NAME can be a simple DOS-type
++patterns, containing '*' and '?' symbols. '*' means match all any
++symbols, '?' means match only any single symbol. For instance,
++"blah.xxx" will match "bl?h.*". Additionally, you can use negative sign
++'!' to revert the value of the pattern. For instance, "ah.xxx" will
++match "!bl?h.*".
++
++Each "luns" subdirectory contains the list of already defined LUNs for
++this group as well as file "mgmt". Content of this file as well as list
++of available in it commands is fully identical to the "luns"
++subdirectory of the target-oriented access control.
++
++Examples:
++
++ - echo "create INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/mgmt -
++ creates security group INI for target iqn.2006-10.net.vlnb:tgt1.
++
++ - echo "add 2:0:1:0 11" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI/luns/mgmt -
++ adds a pass-through device sitting on host 2, channel 0, ID 1, LUN 0
++ to group with name INI as LUN 11.
++
++ - echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI/luns/mgmt -
++ adds a virtual disk with name disk1 to group with name INI as LUN 0.
++
++ - echo "add 21:*:e0:?b:83:*" >/sys/kernel/scst_tgt/targets/21:00:00:a0:8c:54:52:12/ini_groups/INI/initiators/mgmt -
++ adds a pattern to group with name INI to Fibre Channel target with
++ WWN 21:00:00:a0:8c:54:52:12, which matches WWNs of Fibre Channel
++ initiator ports.
++
++Consider you need to have an iSCSI target with name
++"iqn.2007-05.com.example:storage.disk1.sys1.xyz", which should export
++virtual device "dev1" with LUN 0 and virtual device "dev2" with LUN 1,
++but initiator with name
++"iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" should see only
++virtual device "dev2" read only with LUN 0. To achieve that you should
++do the following commands:
++
++# echo "iqn.2007-05.com.example:storage.disk1.sys1.xyz" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++# echo "add dev1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt
++# echo "add dev2 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt
++# echo "create SPEC_INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/mgmt
++# echo "add dev2 0 read_only=1" \
++ >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/SPEC_INI/luns/mgmt
++# echo "iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" \
++ >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/SPEC_INI/initiators/mgmt
++
++For Fibre Channel or SAS in the above example you should use target's
++and initiator ports WWNs instead of iSCSI names.
++
++It is highly recommended to use scstadmin utility instead of described
++in this section low level interface.
++
++IMPORTANT
++=========
++
++There must be LUN 0 in each set of LUNs, i.e. LUs numeration must not
++start from, e.g., 1. Otherwise you will see no devices on remote
++initiators and SCST core will write into the kernel log message: "tgt_dev
++for LUN 0 not found, command to unexisting LU?"
++
++IMPORTANT
++=========
++
++All the access control must be fully configured BEFORE the corresponding
++target is enabled. When you enable a target, it will immediately start
++accepting new connections, hence creating new sessions, and those new
++sessions will be assigned to security groups according to the
++*currently* configured access control settings. For instance, to
++the default target's set of LUNs, instead of "HOST004" group as you may
++need, because "HOST004" doesn't exist yet. So, you must configure all
++the security groups before new connections from the initiators are
++created, i.e. before the target enabled.
++
++VDISK device handler
++--------------------
++
++VDISK has 4 built-in dev handlers: vdisk_fileio, vdisk_blockio,
++vdisk_nullio and vcdrom. Roots of their sysfs interface are
++/sys/kernel/scst_tgt/handlers/handler_name, e.g. for vdisk_fileio:
++/sys/kernel/scst_tgt/handlers/vdisk_fileio. Each root has the following
++entries:
++
++ - None, one or more links to devices with name equal to names
++ of the corresponding devices.
++
++ - trace_level - allows to enable and disable various tracing
++ facilities. See content of this file for help how to use it.
++
++ - mgmt - main management entry, which allows to add/delete VDISK
++ devices with the corresponding type.
++
++The "mgmt" file has the following commands, which you can send to it,
++for instance, using "echo" shell command. You can always get a small
++help about supported commands by looking inside this file. "Parameters"
++are one or more param_name=value pairs separated by ';'.
++
++ - echo "add_device device_name [parameters]" - adds a virtual device
++ with name device_name and specified parameters (see below)
++
++ - echo "del_device device_name" - deletes a virtual device with name
++ device_name.
++
++Handler vdisk_fileio provides FILEIO mode to create virtual devices.
++This mode uses as backend files and accesses to them using regular
++read()/write() file calls. This allows to use full power of Linux page
++cache. The following parameters possible for vdisk_fileio:
++
++ - filename - specifies path and file name of the backend file. The path
++ must be absolute.
++
++ - blocksize - specifies block size used by this virtual device. The
++ block size must be power of 2 and >= 512 bytes. Default is 512.
++
++ - write_through - disables write back caching. Note, this option
++ has sense only if you also *manually* disable write-back cache in
++ *all* your backstorage devices and make sure it's actually disabled,
++ since many devices are known to lie about this mode to get better
++ benchmark results. Default is 0.
++
++ - read_only - read only. Default is 0.
++
++ - o_direct - disables both read and write caching. This mode isn't
++ currently fully implemented, you should use user space fileio_tgt
++ program in O_DIRECT mode instead (see below).
++
++ - nv_cache - enables "non-volatile cache" mode. In this mode it is
++ assumed that the target has a GOOD UPS with ability to cleanly
++ shutdown target in case of power failure and it is software/hardware
++ bugs free, i.e. all data from the target's cache are guaranteed
++ sooner or later to go to the media. Hence all data synchronization
++ with media operations, like SYNCHRONIZE_CACHE, are ignored in order
++ to bring more performance. Also in this mode target reports to
++ initiators that the corresponding device has write-through cache to
++ disable all write-back cache workarounds used by initiators. Use with
++ extreme caution, since in this mode after a crash of the target
++ journaled file systems don't guarantee the consistency after journal
++ recovery, therefore manual fsck MUST be ran. Note, that since usually
++ the journal barrier protection (see "IMPORTANT" note below) turned
++ off, enabling NV_CACHE could change nothing from data protection
++ point of view, since no data synchronization with media operations
++ will go from the initiator. This option overrides "write_through"
++ option. Disabled by default.
++
++ - removable - with this flag set the device is reported to remote
++ initiators as removable.
++
++Handler vdisk_blockio provides BLOCKIO mode to create virtual devices.
++This mode performs direct block I/O with a block device, bypassing the
++page cache for all operations. This mode works ideally with high-end
++storage HBAs and for applications that either do not need caching
++between application and disk or need the large block throughput. See
++below for more info.
++
++The following parameters possible for vdisk_blockio: filename,
++blocksize, nv_cache, read_only, removable. See vdisk_fileio above for
++description of those parameters.
++
++Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
++this mode no real I/O is done, but success returned to initiators.
++Intended to be used for performance measurements at the same way as
++"*_perf" handlers. The following parameters possible for vdisk_nullio:
++blocksize, read_only, removable. See vdisk_fileio above for description
++of those parameters.
++
++Handler vcdrom allows emulation of a virtual CDROM device using an ISO
++file as backend. It doesn't have any parameters.
++
++For example:
++
++echo "add_device disk1 filename=/disk1; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
++
++will create a FILEIO virtual device disk1 with backend file /disk1
++with block size 4K and NV_CACHE enabled.
++
++Each vdisk_fileio's device has the following attributes in
++/sys/kernel/scst_tgt/devices/device_name:
++
++ - filename - contains path and file name of the backend file.
++
++ - blocksize - contains block size used by this virtual device.
++
++ - write_through - contains status of write back caching of this virtual
++ device.
++
++ - read_only - contains read only status of this virtual device.
++
++ - o_direct - contains O_DIRECT status of this virtual device.
++
++ - nv_cache - contains NV_CACHE status of this virtual device.
++
++ - removable - contains removable status of this virtual device.
++
++ - size_mb - contains size of this virtual device in MB.
++
++ - t10_dev_id - contains and allows to set T10 vendor specific
++ identifier for Device Identification VPD page (0x83) of INQUIRY data.
++ By default VDISK handler always generates t10_dev_id for every new
++ created device at creation time based on the device name and
++ scst_vdisk_ID scst_vdisk.ko module parameter (see below).
++
++ - usn - contains the virtual device's serial number of INQUIRY data. It
++ is created at the device creation time based on the device name and
++ scst_vdisk_ID scst_vdisk.ko module parameter (see below).
++
++ - type - contains SCSI type of this virtual device.
++
++ - resync_size - write only attribute, which makes vdisk_fileio to
++ rescan size of the backend file. It is useful if you changed it, for
++ instance, if you resized it.
++
++For example:
++
++/sys/kernel/scst_tgt/devices/disk1
++|-- blocksize
++|-- exported
++| |-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0
++| |-- export1 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/INI/luns/0
++| |-- export2 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0
++| |-- export3 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI1/luns/0
++| |-- export4 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI2/luns/0
++|-- filename
++|-- handler -> ../../handlers/vdisk_fileio
++|-- nv_cache
++|-- o_direct
++|-- read_only
++|-- removable
++|-- resync_size
++|-- size_mb
++|-- t10_dev_id
++|-- threads_num
++|-- threads_pool_type
++|-- type
++|-- usn
++`-- write_through
++
++Each vdisk_blockio's device has the following attributes in
++/sys/kernel/scst_tgt/devices/device_name: blocksize, filename, nv_cache,
++read_only, removable, resync_size, size_mb, t10_dev_id, threads_num,
++threads_pool_type, type, usn. See above description of those parameters.
++
++Each vdisk_nullio's device has the following attributes in
++/sys/kernel/scst_tgt/devices/device_name: blocksize, read_only,
++removable, size_mb, t10_dev_id, threads_num, threads_pool_type, type,
++usn. See above description of those parameters.
++
++Each vcdrom's device has the following attributes in
++/sys/kernel/scst_tgt/devices/device_name: filename, size_mb,
++t10_dev_id, threads_num, threads_pool_type, type, usn. See above
++description of those parameters. Exception is filename attribute. For
++vcdrom it is writable. Writing to it allows to virtually insert or
++change virtual CD media in the virtual CDROM device. For example:
++
++ - echo "/image.iso" >/sys/kernel/scst_tgt/devices/cdrom/filename - will
++ insert file /image.iso as virtual media to the virtual CDROM cdrom.
++
++ - echo "" >/sys/kernel/scst_tgt/devices/cdrom/filename - will remove
++ "media" from the virtual CDROM cdrom.
++
++Additionally VDISK handler has module parameter "num_threads", which
++specifies count of I/O threads for each FILEIO VDISK's or VCDROM device.
++If you have a workload, which tends to produce rather random accesses
++(e.g. DB-like), you should increase this count to a bigger value, like
++32. If you have a rather sequential workload, you should decrease it to
++a lower value, like number of CPUs on the target or even 1. Due to some
++limitations of Linux I/O subsystem, increasing number of I/O threads too
++much leads to sequential performance drop, especially with deadline
++scheduler, so decreasing it can improve sequential performance. The
++default provides a good compromise between random and sequential
++accesses.
++
++You shouldn't be afraid to have too many VDISK I/O threads if you have
++many VDISK devices. Kernel threads consume very little amount of
++resources (several KBs) and only necessary threads will be used by SCST,
++so the threads will not trash your system.
++
++CAUTION: If you partitioned/formatted your device with block size X, *NEVER*
++======== ever try to export and then mount it (even accidentally) with another
++ block size. Otherwise you can *instantly* damage it pretty
++ badly as well as all your data on it. Messages on initiator
++ like: "attempt to access beyond end of device" is the sign of
++ such damage.
++
++ Moreover, if you want to compare how well different block sizes
++ work for you, you **MUST** EVERY TIME AFTER CHANGING BLOCK SIZE
++ **COMPLETELY** **WIPE OFF** ALL THE DATA FROM THE DEVICE. In
++ other words, THE **WHOLE** DEVICE **MUST** HAVE ONLY **ZEROS**
++ AS THE DATA AFTER YOU SWITCH TO NEW BLOCK SIZE. Switching block
++ sizes isn't like switching between FILEIO and BLOCKIO, after
++ changing block size all previously written with another block
++ size data MUST BE ERASED. Otherwise you will have a full set of
++ very weird behaviors, because blocks addressing will be
++ changed, but initiators in most cases will not have a
++ possibility to detect that old addresses written on the device
++ in, e.g., partition table, don't refer anymore to what they are
++ intended to refer.
++
++IMPORTANT: Some disk and partition table management utilities don't support
++========= block sizes >512 bytes, therefore make sure that your favorite one
++ supports it. Currently only cfdisk is known to work only with
++ 512 bytes blocks, other utilities like fdisk on Linux or
++ standard disk manager on Windows are proved to work well with
++ non-512 bytes blocks. Note, if you export a disk file or
++ device with some block size, different from one, with which
++ it was already partitioned, you could get various weird
++ things like utilities hang up or other unexpected behavior.
++ Hence, to be sure, zero the exported file or device before
++ the first access to it from the remote initiator with another
++ block size. On Window initiator make sure you "Set Signature"
++ in the disk manager on the imported from the target drive
++ before doing any other partitioning on it. After you
++ successfully mounted a file system over non-512 bytes block
++ size device, the block size stops matter, any program will
++ work with files on such file system.
++
++Persistent Reservations
++-----------------------
++
++SCST implements Persistent Reservations with full set of capabilities,
++including "Persistence Through Power Loss".
++
++The "Persistence Through Power Loss" data are saved in /var/lib/scst/pr
++with files with names the same as the names of the corresponding
++devices. Also this directory contains backup versions of those files
++with suffix ".1". Those backup files are used in case of power or other
++failure to prevent Persistent Reservation information from corruption
++during update.
++
++The Persistent Reservations available on all transports implementing
++get_initiator_port_transport_id() callback. Transports not implementing
++this callback will act in one of 2 possible scenarios ("all or
++nothing"):
++
++1. If a device has such transport connected and doesn't have persistent
++reservations, it will refuse Persistent Reservations commands as if it
++doesn't support them.
++
++2. If a device has persistent reservations, all initiators newly
++connecting via such transports will not see this device. After all
++persistent reservations from this device are released, upon reconnect
++the initiators will see it.
++
++Caching
++-------
++
++By default for performance reasons VDISK FILEIO devices use write back
++caching policy.
++
++Generally, write back caching is safe for use and danger of it is
++greatly overestimated, because most modern (especially, Enterprise
++level) applications are well prepared to work with write back cached
++storage. Particularly, such are all transactions-based applications.
++Those applications flush cache to completely avoid ANY data loss on a
++crash or power failure. For instance, journaled file systems flush cache
++on each meta data update, so they survive power/hardware/software
++failures pretty well.
++
++Since locally on initiators write back caching is always on, if an
++application cares about its data consistency, it does flush the cache
++when necessary or on any write, if open files with O_SYNC. If it doesn't
++care, it doesn't flush the cache. As soon as the cache flushes
++propagated to the storage, write back caching on it doesn't make any
++difference. If application doesn't flush the cache, it's doomed to loose
++data in case of a crash or power failure doesn't matter where this cache
++located, locally or on the storage.
++
++To illustrate that consider, for example, a user who wants to copy /src
++directory to /dst directory reliably, i.e. after the copy finished no
++power failure or software/hardware crash could lead to a loss of the
++data in /dst. There are 2 ways to achieve this. Let's suppose for
++simplicity cp opens files for writing with O_SYNC flag, hence bypassing
++the local cache.
++
++1. Slow. Make the device behind /dst working in write through caching
++mode and then run "cp -a /src /dst".
++
++2. Fast. Let the device behind /dst working in write back caching mode
++and then run "cp -a /src /dst; sync". The reliability of the result is
++the same, but it's much faster than (1). Nobody would care if a crash
++happens during the copy, because after recovery simply leftovers from
++the not completed attempt would be deleted and the operation would be
++restarted from the very beginning.
++
++So, you can see in (2) there is no danger of ANY data loss from the
++write back caching. Moreover, since on practice cp doesn't open files
++for writing with O_SYNC flag, to get the copy done reliably, sync
++command must be called after cp anyway, so enabling write back caching
++wouldn't make any difference for reliability.
++
++Also you can consider it from another side. Modern HDDs have at least
++16MB of cache working in write back mode by default, so for a 10 drives
++RAID it is 160MB of a write back cache. How many people are happy with
++it and how many disabled write back cache of their HDDs? Almost all and
++almost nobody correspondingly? Moreover, many HDDs lie about state of
++their cache and report write through while working in write back mode.
++They are also successfully used.
++
++Note, Linux I/O subsystem guarantees to propagated cache flushes to the
++storage only using data protection barriers, which usually turned off by
++default (see http://lwn.net/Articles/283161). Without barriers enabled
++Linux doesn't provide a guarantee that after sync()/fsync() all written
++data really hit permanent storage. They can be stored in the cache of
++your backstorage devices and, hence, lost on a power failure event.
++Thus, ever with write-through cache mode, you still either need to
++enable barriers on your backend file system on the target (for direct
++/dev/sdX devices this is, indeed, impossible), or need a good UPS to
++protect yourself from not committed data loss. Some info about barriers
++from the XFS point of view could be found at
++http://oss.sgi.com/projects/xfs/faq.html#wcache. On Linux initiators for
++Ext3 and ReiserFS file systems the barrier protection could be turned on
++using "barrier=1" and "barrier=flush" mount options correspondingly. You
++can check if the barriers turn on or off by looking in /proc/mounts.
++Windows and, AFAIK, other UNIX'es don't need any special explicit
++options and do necessary barrier actions on write-back caching devices
++by default.
++
++To limit this data loss with write back caching you can use files in
++/proc/sys/vm to limit amount of unflushed data in the system cache.
++
++If you for some reason have to use VDISK FILEIO devices in write through
++caching mode, don't forget to disable internal caching on their backend
++devices or make sure they have additional battery or supercapacitors
++power supply on board. Otherwise, you still on a power failure would
++loose all the unsaved yet data in the devices internal cache.
++
++Note, on some real-life workloads write through caching might perform
++better, than write back one with the barrier protection turned on.
++
++BLOCKIO VDISK mode
++------------------
++
++This module works best for these types of scenarios:
++
++1) Data that are not aligned to 4K sector boundaries and <4K block sizes
++are used, which is normally found in virtualization environments where
++operating systems start partitions on odd sectors (Windows and it's
++sector 63).
++
++2) Large block data transfers normally found in database loads/dumps and
++streaming media.
++
++3) Advanced relational database systems that perform their own caching
++which prefer or demand direct IO access and, because of the nature of
++their data access, can actually see worse performance with
++non-discriminate caching.
++
++4) Multiple layers of targets were the secondary and above layers need
++to have a consistent view of the primary targets in order to preserve
++data integrity which a page cache backed IO type might not provide
++reliably.
++
++Also it has an advantage over FILEIO that it doesn't copy data between
++the system cache and the commands data buffers, so it saves a
++considerable amount of CPU power and memory bandwidth.
++
++IMPORTANT: Since data in BLOCKIO and FILEIO modes are not consistent between
++========= each other, if you try to use a device in both those modes
++ simultaneously, you will almost instantly corrupt your data
++ on that device.
++
++IMPORTANT: If SCST 1.x BLOCKIO worked by default in NV_CACHE mode, when
++========= each device reported to remote initiators as having write through
++ caching. But if your backend block device has internal write
++ back caching it might create a possibility for data loss of
++ the cached in the internal cache data in case of a power
++ failure. Starting from SCST 2.0 BLOCKIO works by default in
++ non-NV_CACHE mode, when each device reported to remote
++ initiators as having write back caching, and synchronizes the
++ internal device's cache on each SYNCHRONIZE_CACHE command
++ from the initiators. It might lead to some PERFORMANCE LOSS,
++ so if you are are sure in your power supply and want to
++ restore 1.x behavior, your should recreate your BLOCKIO
++ devices in NV_CACHE mode.
++
++Pass-through mode
++-----------------
++
++In the pass-through mode (i.e. using the pass-through device handlers
++scst_disk, scst_tape, etc) SCSI commands, coming from remote initiators,
++are passed to local SCSI devices on target as is, without any
++modifications.
++
++SCST supports 1 to many pass-through, when several initiators can safely
++connect a single pass-through device (a tape, for instance). For such
++cases SCST emulates all the necessary functionality.
++
++In the sysfs interface all real SCSI devices are listed in
++/sys/kernel/scst_tgt/devices in form host:channel:id:lun numbers, for
++instance 1:0:0:0. The recommended way to match those numbers to your
++devices is use of lsscsi utility.
++
++Each pass-through dev handler has in its root subdirectory
++/sys/kernel/scst_tgt/handlers/handler_name, e.g.
++/sys/kernel/scst_tgt/handlers/dev_disk, "mgmt" file. It allows the
++following commands. They can be sent to it using, e.g., echo command.
++
++ - "add_device" - this command assigns SCSI device with
++host:channel:id:lun numbers to this dev handler.
++
++echo "add_device 1:0:0:0" >/sys/kernel/scst_tgt/handlers/dev_disk/mgmt
++
++will assign SCSI device 1:0:0:0 to this dev handler.
++
++ - "del_device" - this command unassigns SCSI device with
++host:channel:id:lun numbers from this dev handler.
++
++As usually, on read the "mgmt" file returns small help about available
++commands.
++
++You need to manually assign each your real SCSI device to the
++corresponding pass-through dev handler using the "add_device" command,
++otherwise the real SCSI devices will not be visible remotely. The
++assignment isn't done automatically, because it could lead to the
++pass-through dev handlers load and initialization problems if any of the
++local real SCSI devices are malfunctioning.
++
++As any other hardware, the local SCSI hardware can not handle commands
++with amount of data and/or segments count in scatter-gather array bigger
++some values. Therefore, when using the pass-through mode you should note
++that values for maximum number of segments and maximum amount of
++transferred data (max_sectors) for each SCSI command on devices on
++initiators can not be bigger, than corresponding values of the
++corresponding SCSI devices on the target. Otherwise you will see
++symptoms like small transfers work well, but large ones stall and
++messages like: "Unable to complete command due to SG IO count
++limitation" are printed in the kernel logs.
++
++You can't control from the user space limit of the scatter-gather
++segments, but for block devices usually it is sufficient if you set on
++the initiators /sys/block/DEVICE_NAME/queue/max_sectors_kb in the same
++or lower value as in /sys/block/DEVICE_NAME/queue/max_hw_sectors_kb for
++the corresponding devices on the target.
++
++For not-block devices SCSI commands are usually generated directly by
++applications, so, if you experience large transfers stalls, you should
++check documentation for your application how to limit the transfer
++sizes.
++
++Another way to solve this issue is to build SG entries with more than 1
++page each. See the following patch as an example:
++http://scst.sourceforge.net/sgv_big_order_alloc.diff
++
++Performance
++-----------
++
++SCST from the very beginning has been designed and implemented to
++provide the best possible performance. Since there is no "one fit all"
++the best performance configuration for different setups and loads, SCST
++provides extensive set of settings to allow to tune it for the best
++performance in each particular case. You don't have to necessary use
++those settings. If you don't, SCST will do very good job to autotune for
++you, so the resulting performance will, in average, be better
++(sometimes, much better) than with other SCSI targets. But in some cases
++you can by manual tuning improve it even more.
++
++Before doing any performance measurements note that performance results
++are very much dependent from your type of load, so it is crucial that
++you choose access mode (FILEIO, BLOCKIO, O_DIRECT, pass-through), which
++suits your needs the best.
++
++In order to get the maximum performance you should:
++
++1. For SCST:
++
++ - Disable in Makefile CONFIG_SCST_STRICT_SERIALIZING, CONFIG_SCST_EXTRACHECKS,
++ CONFIG_SCST_TRACING, CONFIG_SCST_DEBUG*, CONFIG_SCST_STRICT_SECURITY,
++ CONFIG_SCST_MEASURE_LATENCY
++
++2. For target drivers:
++
++ - Disable in Makefiles CONFIG_SCST_EXTRACHECKS, CONFIG_SCST_TRACING,
++ CONFIG_SCST_DEBUG*
++
++3. For device handlers, including VDISK:
++
++ - Disable in Makefile CONFIG_SCST_TRACING and CONFIG_SCST_DEBUG.
++
++4. Make sure you have io_grouping_type option set correctly, especially
++in the following cases:
++
++ - Several initiators share your target's backstorage. It can be a
++ shared LU using some cluster FS, like VMFS, as well as can be
++ different LUs located on the same backstorage (RAID array). For
++ instance, if you have 3 initiators and each of them using its own
++ dedicated FILEIO device file from the same RAID-6 array on the
++ target.
++
++ In this case for the best performance you should have
++ io_grouping_type option set in value "never" in all the LUNs' targets
++ and security groups.
++
++ - Your initiator connected to your target in MPIO mode. In this case for
++ the best performance you should:
++
++ * Either connect all the sessions from the initiator to a single
++ target or security group and have io_grouping_type option set in
++ value "this_group_only" in the target or security group,
++
++ * Or, if it isn't possible to connect all the sessions from the
++ initiator to a single target or security group, assign the same
++ numeric io_grouping_type value for each target/security group this
++ initiator connected to. The exact value itself doesn't matter,
++ important only that all the targets/security groups use the same
++ value.
++
++Don't forget, io_grouping_type makes sense only if you use CFQ I/O
++scheduler on the target and for devices with threads_num >= 0 and, if
++threads_num > 0, with threads_pool_type "per_initiator".
++
++You can check if in your setup io_grouping_type set correctly as well as
++if the "auto" io_grouping_type value works for you by tests like the
++following:
++
++ - For not MPIO case you can run single thread sequential reading, e.g.
++ using buffered dd, from one initiator, then run the same single
++ thread sequential reading from the second initiator in parallel. If
++ io_grouping_type is set correctly the aggregate throughput measured
++ on the target should only slightly decrease as well as all initiators
++ should have nearly equal share of it. If io_grouping_type is not set
++ correctly, the aggregate throughput and/or throughput on any
++ initiator will decrease significantly, in 2 times or even more. For
++ instance, you have 80MB/s single thread sequential reading from the
++ target on any initiator. When then both initiators are reading in
++ parallel you should see on the target aggregate throughput something
++ like 70-75MB/s with correct io_grouping_type and something like
++ 35-40MB/s or 8-10MB/s on any initiator with incorrect.
++
++ - For the MPIO case it's quite easier. With incorrect io_grouping_type
++ you simply won't see performance increase from adding the second
++ session (assuming your hardware is capable to transfer data through
++ both sessions in parallel), or can even see a performance decrease.
++
++5. If you are going to use your target in an VM environment, for
++instance as a shared storage with VMware, make sure all your VMs
++connected to the target via *separate* sessions. For instance, for iSCSI
++it means that each VM has own connection to the target, not all VMs
++connected using a single connection. You can check it using SCST sysfs
++interface. For other transports you should use available facilities,
++like NPIV for Fibre Channel, to make separate sessions for each VM. If
++you miss it, you can greatly loose performance of parallel access to
++your target from different VMs. This isn't related to the case if your
++VMs are using the same shared storage, like with VMFS, for instance. In
++this case all your VM hosts will be connected to the target via separate
++sessions, which is enough.
++
++6. For other target and initiator software parts:
++
++ - Make sure you applied on your kernel all available SCST patches.
++ If for your kernel version this patch doesn't exist, it is strongly
++ recommended to upgrade your kernel to version, for which this patch
++ exists.
++
++ - Don't enable debug/hacking features in the kernel, i.e. use them as
++ they are by default.
++
++ - The default kernel read-ahead and queuing settings are optimized
++ for locally attached disks, therefore they are not optimal if they
++ attached remotely (SCSI target case), which sometimes could lead to
++ unexpectedly low throughput. You should increase read-ahead size to at
++ least 512KB or even more on all initiators and the target.
++
++ You should also limit on all initiators maximum amount of sectors per
++ SCSI command. This tuning is also recommended on targets with large
++ read-ahead values. To do it on Linux, run:
++
++ echo “64†> /sys/block/sdX/queue/max_sectors_kb
++
++ where specify instead of X your imported from target device letter,
++ like 'b', i.e. sdb.
++
++ To increase read-ahead size on Linux, run:
++
++ blockdev --setra N /dev/sdX
++
++ where N is a read-ahead number in 512-byte sectors and X is a device
++ letter like above.
++
++ Note: you need to set read-ahead setting for device sdX again after
++ you changed the maximum amount of sectors per SCSI command for that
++ device.
++
++ Note2: you need to restart SCST after you changed read-ahead settings
++ on the target.
++
++ - You may need to increase amount of requests that OS on initiator
++ sends to the target device. To do it on Linux initiators, run
++
++ echo “64†> /sys/block/sdX/queue/nr_requests
++
++ where X is a device letter like above.
++
++ You may also experiment with other parameters in /sys/block/sdX
++ directory, they also affect performance. If you find the best values,
++ please share them with us.
++
++ - On the target use CFQ IO scheduler. In most cases it has performance
++ advantage over other IO schedulers, sometimes huge (2+ times
++ aggregate throughput increase).
++
++ - It is recommended to turn the kernel preemption off, i.e. set
++ the kernel preemption model to "No Forced Preemption (Server)".
++
++ - Looks like XFS is the best filesystem on the target to store device
++ files, because it allows considerably better linear write throughput,
++ than ext3.
++
++7. For hardware on target.
++
++ - Make sure that your target hardware (e.g. target FC or network card)
++ and underlaying IO hardware (e.g. IO card, like SATA, SCSI or RAID to
++ which your disks connected) don't share the same PCI bus. You can
++ check it using lspci utility. They have to work in parallel, so it
++ will be better if they don't compete for the bus. The problem is not
++ only in the bandwidth, which they have to share, but also in the
++ interaction between cards during that competition. This is very
++ important, because in some cases if target and backend storage
++ controllers share the same PCI bus, it could lead up to 5-10 times
++ less performance, than expected. Moreover, some motherboard (by
++ Supermicro, particularly) have serious stability issues if there are
++ several high speed devices on the same bus working in parallel. If
++ you have no choice, but PCI bus sharing, set in the BIOS PCI latency
++ as low as possible.
++
++8. If you use VDISK IO module in FILEIO mode, NV_CACHE option will
++provide you the best performance. But using it make sure you use a good
++UPS with ability to shutdown the target on the power failure.
++
++Baseline performance numbers you can find in those measurements:
++http://lkml.org/lkml/2009/3/30/283.
++
++IMPORTANT: If you use on initiator some versions of Windows (at least W2K)
++========= you can't get good write performance for VDISK FILEIO devices with
++ default 512 bytes block sizes. You could get about 10% of the
++ expected one. This is because of the partition alignment, which
++ is (simplifying) incompatible with how Linux page cache
++ works, so for each write the corresponding block must be read
++ first. Use 4096 bytes block sizes for VDISK devices and you
++ will have the expected write performance. Actually, any OS on
++ initiators, not only Windows, will benefit from block size
++ max(PAGE_SIZE, BLOCK_SIZE_ON_UNDERLYING_FS), where PAGE_SIZE
++ is the page size, BLOCK_SIZE_ON_UNDERLYING_FS is block size
++ on the underlying FS, on which the device file located, or 0,
++ if a device node is used. Both values are from the target.
++ See also important notes about setting block sizes >512 bytes
++ for VDISK FILEIO devices above.
++
++9. In some cases, for instance working with SSD devices, which consume 100%
++of a single CPU load for data transfers in their internal threads, to
++maximize IOPS it can be needed to assign for those threads dedicated
++CPUs using Linux CPU affinity facilities. No IRQ processing should be
++done on those CPUs. Check that using /proc/interrupts. See taskset
++command and Documentation/IRQ-affinity.txt in your kernel's source tree
++for how to assign IRQ affinity to tasks and IRQs.
++
++The reason for that is that processing of coming commands in SIRQ
++context might be done on the same CPUs as SSD devices' threads doing data
++transfers. As the result, those threads won't receive all the processing
++power of those CPUs and perform worse.
++
++Work if target's backstorage or link is too slow
++------------------------------------------------
++
++Under high I/O load, when your target's backstorage gets overloaded, or
++working over a slow link between initiator and target, when the link
++can't serve all the queued commands on time, you can experience I/O
++stalls or see in the kernel log abort or reset messages.
++
++At first, consider the case of too slow target's backstorage. On some
++seek intensive workloads even fast disks or RAIDs, which able to serve
++continuous data stream on 500+ MB/s speed, can be as slow as 0.3 MB/s.
++Another possible cause for that can be MD/LVM/RAID on your target as in
++http://lkml.org/lkml/2008/2/27/96 (check the whole thread as well).
++
++Thus, in such situations simply processing of one or more commands takes
++too long time, hence initiator decides that they are stuck on the target
++and tries to recover. Particularly, it is known that the default amount
++of simultaneously queued commands (48) is sometimes too high if you do
++intensive writes from VMware on a target disk, which uses LVM in the
++snapshot mode. In this case value like 16 or even 8-10 depending of your
++backstorage speed could be more appropriate.
++
++Unfortunately, currently SCST lacks dynamic I/O flow control, when the
++queue depth on the target is dynamically decreased/increased based on
++how slow/fast the backstorage speed comparing to the target link. So,
++there are 6 possible actions, which you can do to workaround or fix this
++issue in this case:
++
++1. Ignore incoming task management (TM) commands. It's fine if there are
++not too many of them, so average performance isn't hurt and the
++corresponding device isn't getting put offline, i.e. if the backstorage
++isn't too slow.
++
++2. Decrease /sys/block/sdX/device/queue_depth on the initiator in case
++if it's Linux (see below how) or/and SCST_MAX_TGT_DEV_COMMANDS constant
++in scst_priv.h file until you stop seeing incoming TM commands.
++ISCSI-SCST driver also has its own iSCSI specific parameter for that,
++see its README file.
++
++To decrease device queue depth on Linux initiators you can run command:
++
++# echo Y >/sys/block/sdX/device/queue_depth
++
++where Y is the new number of simultaneously queued commands, X - your
++imported device letter, like 'a' for sda device. There are no special
++limitations for Y value, it can be any value from 1 to possible maximum
++(usually, 32), so start from dividing the current value on 2, i.e. set
++16, if /sys/block/sdX/device/queue_depth contains 32.
++
++3. Increase the corresponding timeout on the initiator. For Linux it is
++located in
++/sys/devices/platform/host*/session*/target*:0:0/*:0:0:1/timeout. It can
++be done automatically by an udev rule. For instance, the following
++rule will increase it to 300 seconds:
++
++SUBSYSTEM=="scsi", KERNEL=="[0-9]*:[0-9]*", ACTION=="add", ATTR{type}=="0|7|14", ATTR{timeout}="300"
++
++By default, this timeout is 30 or 60 seconds, depending on your distribution.
++
++4. Try to avoid such seek intensive workloads.
++
++5. Increase speed of the target's backstorage.
++
++6. Implement in SCST dynamic I/O flow control. This will be an ultimate
++solution. See "Dynamic I/O flow control" section on
++http://scst.sourceforge.net/contributing.html page for possible
++implementation idea.
++
++Next, consider the case of too slow link between initiator and target,
++when the initiator tries to simultaneously push N commands to the target
++over it. In this case time to serve those commands, i.e. send or receive
++data for them over the link, can be more, than timeout for any single
++command, hence one or more commands in the tail of the queue can not be
++served on time less than the timeout, so the initiator will decide that
++they are stuck on the target and will try to recover.
++
++To workaround/fix this issue in this case you can use ways 1, 2, 3, 6
++above or (7): increase speed of the link between target and initiator.
++But for some initiators implementations for WRITE commands there might
++be cases when target has no way to detect the issue, so dynamic I/O flow
++control will not be able to help. In those cases you could also need on
++the initiator(s) to either decrease the queue depth (way 2), or increase
++the corresponding timeout (way 3).
++
++Note, that logged messages about QUEUE_FULL status are quite different
++by nature. This is a normal work, just SCSI flow control in action.
++Simply don't enable "mgmt_minor" logging level, or, alternatively, if
++you are confident in the worst case performance of your back-end storage
++or initiator-target link, you can increase SCST_MAX_TGT_DEV_COMMANDS in
++scst_priv.h to 64. Usually initiators don't try to push more commands on
++the target.
++
++Credits
++-------
++
++Thanks to:
++
++ * Mark Buechler <mark.buechler@gmail.com> for a lot of useful
++ suggestions, bug reports and help in debugging.
++
++ * Ming Zhang <mingz@ele.uri.edu> for fixes and comments.
++
++ * Nathaniel Clark <nate@misrule.us> for fixes and comments.
++
++ * Calvin Morrow <calvin.morrow@comcast.net> for testing and useful
++ suggestions.
++
++ * Hu Gang <hugang@soulinfo.com> for the original version of the
++ LSI target driver.
++
++ * Erik Habbinga <erikhabbinga@inphase-tech.com> for fixes and support
++ of the LSI target driver.
++
++ * Ross S. W. Walker <rswwalker@hotmail.com> for the original block IO
++ code and Vu Pham <huongvp@yahoo.com> who updated it for the VDISK dev
++ handler.
++
++ * Michael G. Byrnes <michael.byrnes@hp.com> for fixes.
++
++ * Alessandro Premoli <a.premoli@andxor.it> for fixes
++
++ * Nathan Bullock <nbullock@yottayotta.com> for fixes.
++
++ * Terry Greeniaus <tgreeniaus@yottayotta.com> for fixes.
++
++ * Krzysztof Blaszkowski <kb@sysmikro.com.pl> for many fixes and bug reports.
++
++ * Jianxi Chen <pacers@users.sourceforge.net> for fixing problem with
++ devices >2TB in size
++
++ * Bart Van Assche <bvanassche@acm.org> for a lot of help
++
++ * Daniel Debonzi <debonzi@linux.vnet.ibm.com> for a big part of the
++ initial SCST sysfs tree implementation
++
++Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
+diff -uprN orig/linux-2.6.36/Documentation/scst/SysfsRules linux-2.6.36/Documentation/scst/SysfsRules
+--- orig/linux-2.6.36/Documentation/scst/SysfsRules
++++ linux-2.6.36/Documentation/scst/SysfsRules
+@@ -0,0 +1,933 @@
++ SCST SYSFS interface rules
++ ==========================
++
++This file describes SYSFS interface rules, which all SCST target
++drivers, dev handlers and management utilities MUST follow. This allows
++to have a simple, self-documented, target drivers and dev handlers
++independent management interface.
++
++Words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
++"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
++document are to be interpreted as described in RFC 2119.
++
++In this document "key attribute" means a configuration attribute with
++not default value, which must be configured during the target driver's
++initialization. A key attribute MUST have in the last line keyword
++"[key]". If a default value set to a key attribute, it becomes a regular
++none-key attribute. For instance, iSCSI target has attribute DataDigest.
++Default value for this attribute is "None". It value "CRC32C" is set to
++this attribute, it will become a key attribute. If value "None" is again
++set, this attribute will become back to a none-key attribute.
++
++Each user configurable attribute with a not default value MUST be marked
++as key attribute.
++
++Key attributes SHOULD NOT have sysfs names finished on digits, because
++such names SHOULD be used to store several attributes with the same name
++on the sysfs tree where duplicated names are not allowed. For instance,
++iSCSI targets can have several incoming user names, so the corresponding
++attribute should have sysfs name "IncomingUser". If there are 2 user
++names, they should have sysfs names "IncomingUser" and "IncomingUser1".
++In other words, all "IncomingUser[0-9]*" names should be considered as
++different instances of the same "IncomingUser" attribute.
++
++I. Rules for target drivers
++===========================
++
++SCST core for each target driver (struct scst_tgt_template) creates a
++root subdirectory in /sys/kernel/scst_tgt/targets with name
++scst_tgt_template.name (called "target_driver_name" further in this
++document).
++
++For each target (struct scst_tgt) SCST core creates a root subdirectory
++in /sys/kernel/scst_tgt/targets/target_driver_name with name
++scst_tgt.tgt_name (called "target_name" further in this document).
++
++There are 2 type of targets possible: hardware and virtual targets.
++Hardware targets are targets corresponding to real hardware, for
++instance, a Fibre Channel adapter's port. Virtual targets are hardware
++independent targets, which can be dynamically added or removed, for
++instance, an iSCSI target, or NPIV Fibre Channel target.
++
++A target driver supporting virtual targets MUST support "mgmt" attribute
++and "add_target"/"del_target" commands.
++
++If target driver supports both hardware and virtual targets (for
++instance, an FC adapter supporting NPIV, which has hardware targets for
++its physical ports as well as virtual NPIV targets), it MUST create each
++hardware target with hw_target mark to make SCST core create "hw_target"
++attribute (see below).
++
++Attributes for target drivers
++-----------------------------
++
++A target driver MAY support in its root subdirectory the following
++optional attributes. Target drivers MAY also support there other
++read-only or read-writable attributes.
++
++1. "enabled" - this attribute MUST allow to enable and disable target
++driver as a whole, i.e. if disabled, the target driver MUST NOT accept
++new connections. The goal of this attribute is to allow the target
++driver's initial configuration. For instance, iSCSI target may need to
++have discovery user names and passwords set before it starts serving
++discovery connections.
++
++This attribute MUST have read and write permissions for superuser and be
++read-only for other users.
++
++On read it MUST return 0, if the target driver is disabled, and 1, if it
++is enabled.
++
++On write it MUST accept '0' character as request to disable and '1' as
++request to enable, but MAY also accept other driver specific commands.
++
++During disabling the target driver MAY close already connected sessions
++in all targets, but this is OPTIONAL.
++
++MUST be 0 by default.
++
++2. "trace_level" - this attribute SHOULD allow to change log level of this
++driver.
++
++This attribute SHOULD have read and write permissions for superuser and be
++read-only for other users.
++
++On read it SHOULD return a help text about available command and log levels.
++
++On write it SHOULD accept commands to change log levels according to the
++help text.
++
++For example:
++
++out_of_mem | minor | pid | line | function | special | mgmt | mgmt_dbg | flow_control | conn
++
++Usage:
++ echo "all|none|default" >trace_level
++ echo "value DEC|0xHEX|0OCT" >trace_level
++ echo "add|del TOKEN" >trace_level
++
++where TOKEN is one of [debug, function, line, pid,
++ entryexit, buff, mem, sg, out_of_mem,
++ special, scsi, mgmt, minor,
++ mgmt_dbg, scsi_serializing,
++ retry, recv_bot, send_bot, recv_top,
++ send_top, d_read, d_write, conn, conn_dbg, iov, pdu, net_page]
++
++3. "version" - this read-only for all attribute SHOULD return version of
++the target driver and some info about its enabled compile time facilities.
++
++For example:
++
++2.0.0
++EXTRACHECKS
++DEBUG
++
++4. "mgmt" - if supported this attribute MUST allow to add and delete
++targets, if virtual targets are supported by this driver, as well as it
++MAY allow to add and delete the target driver's or its targets'
++attributes.
++
++This attribute MUST have read and write permissions for superuser and be
++read-only for other users.
++
++On read it MUST return a help string describing available commands,
++parameters and attributes.
++
++To achieve that the target driver should just set in its struct
++scst_tgt_template correctly the following fields: mgmt_cmd_help,
++add_target_parameters, tgtt_optional_attributes and
++tgt_optional_attributes.
++
++For example:
++
++Usage: echo "add_target target_name [parameters]" >mgmt
++ echo "del_target target_name" >mgmt
++ echo "add_attribute <attribute> <value>" >mgmt
++ echo "del_attribute <attribute> <value>" >mgmt
++ echo "add_target_attribute target_name <attribute> <value>" >mgmt
++ echo "del_target_attribute target_name <attribute> <value>" >mgmt
++
++where parameters are one or more param_name=value pairs separated by ';'
++
++The following target driver attributes available: IncomingUser, OutgoingUser
++The following target attributes available: IncomingUser, OutgoingUser, allowed_portal
++
++4.1. "add_target" - if supported, this command MUST add new target with
++name "target_name" and specified optional or required parameters. Each
++parameter MUST be in form "parameter=value". All parameters MUST be
++separated by ';' symbol.
++
++All target drivers supporting creation of virtual targets MUST support
++this command.
++
++All target drivers supporting "add_target" command MUST support all
++read-only targets' key attributes as parameters to "add_target" command
++with the attributes' names as parameters' names and the attributes'
++values as parameters' values.
++
++For example:
++
++echo "add_target TARGET1 parameter1=1; parameter2=2" >mgmt
++
++will add target with name "TARGET1" and parameters with names
++"parameter1" and "parameter2" with values 1 and 2 correspondingly.
++
++4.2. "del_target" - if supported, this command MUST delete target with
++name "target_name". If "add_target" command is supported "del_target"
++MUST also be supported.
++
++4.3. "add_attribute" - if supported, this command MUST add a target
++driver's attribute with the specified name and one or more values.
++
++All target drivers supporting run time creation of the target driver's
++key attributes MUST support this command.
++
++For example, for iSCSI target:
++
++echo "add_attribute IncomingUser name password" >mgmt
++
++will add for discovery sessions an incoming user (attribute
++/sys/kernel/scst_tgt/targets/iscsi/IncomingUser) with name "name" and
++password "password".
++
++4.4. "del_attribute" - if supported, this command MUST delete target
++driver's attribute with the specified name and values. The values MUST
++be specified, because in some cases attributes MAY internally be
++distinguished by values. For instance, iSCSI target might have several
++incoming users. If not needed, target driver might ignore the values.
++
++If "add_attribute" command is supported "del_attribute" MUST
++also be supported.
++
++4.5. "add_target_attribute" - if supported, this command MUST add new
++attribute for the specified target with the specified name and one or
++more values.
++
++All target drivers supporting run time creation of targets' key
++attributes MUST support this command.
++
++For example:
++
++echo "add_target_attribute iqn.2006-10.net.vlnb:tgt IncomingUser name password" >mgmt
++
++will add for target with name "iqn.2006-10.net.vlnb:tgt" an incoming
++user (attribute
++/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/IncomingUser)
++with name "name" and password "password".
++
++4.6. "del_target_attribute" - if supported, this command MUST delete
++target's attribute with the specified name and values. The values MUST
++be specified, because in some cases attributes MAY internally be
++distinguished by values. For instance, iSCSI target might have several
++incoming users. If not needed, target driver might ignore the values.
++
++If "add_target_attribute" command is supported "del_target_attribute"
++MUST also be supported.
++
++Attributes for targets
++----------------------
++
++Each target MAY support in its root subdirectory the following optional
++attributes. Target drivers MAY also support there other read-only or
++read-writable attributes.
++
++1. "enabled" - this attribute MUST allow to enable and disable the
++corresponding target, i.e. if disabled, the target MUST NOT accept new
++connections. The goal of this attribute is to allow the target's initial
++configuration. For instance, each target needs to have its LUNs setup
++before it starts serving initiators. Another example is iSCSI target,
++which may need to have initialized a number of iSCSI parameters before
++it starts accepting new iSCSI connections.
++
++This attribute MUST have read and write permissions for superuser and be
++read-only for other users.
++
++On read it MUST return 0, if the target is disabled, and 1, if it is
++enabled.
++
++On write it MUST accept '0' character as request to disable and '1' as
++request to enable. Other requests MUST be rejected.
++
++SCST core provides some facilities, which MUST be used to implement this
++attribute.
++
++During disabling the target driver MAY close already connected sessions
++to the target, but this is OPTIONAL.
++
++MUST be 0 by default.
++
++SCST core will automatically create for all targets the following
++attributes:
++
++1. "rel_tgt_id" - allows to read or write SCSI Relative Target Port
++Identifier attribute.
++
++2. "hw_target" - allows to distinguish hardware and virtual targets, if
++the target driver supports both.
++
++To provide OPTIONAL force close session functionality target drivers
++MUST implement it using "force_close" write only session's attribute,
++which on write to it MUST close the corresponding session.
++
++See SCST core's README for more info about those attributes.
++
++II. Rules for dev handlers
++==========================
++
++There are 2 types of dev handlers: parent dev handlers and children dev
++handlers. The children dev handlers depend from the parent dev handlers.
++
++SCST core for each parent dev handler (struct scst_dev_type with
++parent member with value NULL) creates a root subdirectory in
++/sys/kernel/scst_tgt/handlers with name scst_dev_type.name (called
++"dev_handler_name" further in this document).
++
++Parent dev handlers can have one or more subdirectories for children dev
++handlers with names scst_dev_type.name of them.
++
++Only one level of the dev handlers' parent/children hierarchy is
++allowed. Parent dev handlers, which support children dev handlers, MUST
++NOT handle devices and MUST be only placeholders for the children dev
++handlers.
++
++Further in this document children dev handlers or parent dev handlers,
++which don't support children, will be called "end level dev handlers".
++
++End level dev handlers can be recognized by existence of the "mgmt"
++attribute.
++
++For each device (struct scst_device) SCST core creates a root
++subdirectory in /sys/kernel/scst_tgt/devices/device_name with name
++scst_device.virt_name (called "device_name" further in this document).
++
++Attributes for dev handlers
++---------------------------
++
++Each dev handler MUST have it in its root subdirectory "mgmt" attribute,
++which MUST support "add_device" and "del_device" attributes as described
++below.
++
++Parent dev handlers and end level dev handlers without parents MAY
++support in its root subdirectory the following optional attributes. They
++MAY also support there other read-only or read-writable attributes.
++
++1. "trace_level" - this attribute SHOULD allow to change log level of this
++driver.
++
++This attribute SHOULD have read and write permissions for superuser and be
++read-only for other users.
++
++On read it SHOULD return a help text about available command and log levels.
++
++On write it SHOULD accept commands to change log levels according to the
++help text.
++
++For example:
++
++out_of_mem | minor | pid | line | function | special | mgmt | mgmt_dbg
++
++Usage:
++ echo "all|none|default" >trace_level
++ echo "value DEC|0xHEX|0OCT" >trace_level
++ echo "add|del TOKEN" >trace_level
++
++where TOKEN is one of [debug, function, line, pid,
++ entryexit, buff, mem, sg, out_of_mem,
++ special, scsi, mgmt, minor,
++ mgmt_dbg, scsi_serializing,
++ retry, recv_bot, send_bot, recv_top,
++ send_top]
++
++2. "version" - this read-only for all attribute SHOULD return version of
++the dev handler and some info about its enabled compile time facilities.
++
++For example:
++
++2.0.0
++EXTRACHECKS
++DEBUG
++
++End level dev handlers in their root subdirectories MUST support "mgmt"
++attribute and MAY support other read-only or read-writable attributes.
++This attribute MUST have read and write permissions for superuser and be
++read-only for other users.
++
++Attribute "mgmt" for virtual devices dev handlers
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++For virtual devices dev handlers "mgmt" attribute MUST allow to add and
++delete devices as well as it MAY allow to add and delete the dev
++handler's or its devices' attributes.
++
++On read it MUST return a help string describing available commands and
++parameters.
++
++To achieve that the dev handler should just set in its struct
++scst_dev_type correctly the following fields: mgmt_cmd_help,
++add_device_parameters, devt_optional_attributes and
++dev_optional_attributes.
++
++For example:
++
++Usage: echo "add_device device_name [parameters]" >mgmt
++ echo "del_device device_name" >mgmt
++ echo "add_attribute <attribute> <value>" >mgmt
++ echo "del_attribute <attribute> <value>" >mgmt
++ echo "add_device_attribute device_name <attribute> <value>" >mgmt
++ echo "del_device_attribute device_name <attribute> <value>" >mgmt
++
++where parameters are one or more param_name=value pairs separated by ';'
++
++The following parameters available: filename, blocksize, write_through, nv_cache, o_direct, read_only, removable
++The following device driver attributes available: AttributeX, AttributeY
++The following device attributes available: AttributeDX, AttributeDY
++
++1. "add_device" - this command MUST add new device with name
++"device_name" and specified optional or required parameters. Each
++parameter MUST be in form "parameter=value". All parameters MUST be
++separated by ';' symbol.
++
++All dev handlers supporting "add_device" command MUST support all
++read-only devices' key attributes as parameters to "add_device" command
++with the attributes' names as parameters' names and the attributes'
++values as parameters' values.
++
++For example:
++
++echo "add_device device1 parameter1=1; parameter2=2" >mgmt
++
++will add device with name "device1" and parameters with names
++"parameter1" and "parameter2" with values 1 and 2 correspondingly.
++
++2. "del_device" - this command MUST delete device with name
++"device_name".
++
++3. "add_attribute" - if supported, this command MUST add a device
++driver's attribute with the specified name and one or more values.
++
++All dev handlers supporting run time creation of the dev handler's
++key attributes MUST support this command.
++
++For example:
++
++echo "add_attribute AttributeX ValueX" >mgmt
++
++will add attribute
++/sys/kernel/scst_tgt/handlers/dev_handler_name/AttributeX with value ValueX.
++
++4. "del_attribute" - if supported, this command MUST delete device
++driver's attribute with the specified name and values. The values MUST
++be specified, because in some cases attributes MAY internally be
++distinguished by values. If not needed, dev handler might ignore the
++values.
++
++If "add_attribute" command is supported "del_attribute" MUST also be
++supported.
++
++5. "add_device_attribute" - if supported, this command MUST add new
++attribute for the specified device with the specified name and one or
++more values.
++
++All dev handlers supporting run time creation of devices' key attributes
++MUST support this command.
++
++For example:
++
++echo "add_device_attribute device1 AttributeDX ValueDX" >mgmt
++
++will add for device with name "device1" attribute
++/sys/kernel/scst_tgt/devices/device_name/AttributeDX) with value
++ValueDX.
++
++6. "del_device_attribute" - if supported, this command MUST delete
++device's attribute with the specified name and values. The values MUST
++be specified, because in some cases attributes MAY internally be
++distinguished by values. If not needed, dev handler might ignore the
++values.
++
++If "add_device_attribute" command is supported "del_device_attribute"
++MUST also be supported.
++
++Attribute "mgmt" for pass-through devices dev handlers
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++For pass-through devices dev handlers "mgmt" attribute MUST allow to
++assign and unassign this dev handler to existing SCSI devices via
++"add_device" and "del_device" commands correspondingly.
++
++On read it MUST return a help string describing available commands and
++parameters.
++
++For example:
++
++Usage: echo "add_device H:C:I:L" >mgmt
++ echo "del_device H:C:I:L" >mgmt
++
++1. "add_device" - this command MUST assign SCSI device with
++host:channel:id:lun numbers to this dev handler.
++
++All pass-through dev handlers MUST support this command.
++
++For example:
++
++echo "add_device 1:0:0:0" >mgmt
++
++will assign SCSI device 1:0:0:0 to this dev handler.
++
++2. "del_device" - this command MUST unassign SCSI device with
++host:channel:id:lun numbers from this dev handler.
++
++SCST core will automatically create for all dev handlers the following
++attributes:
++
++1. "type" - SCSI type of device this dev handler can handle.
++
++See SCST core's README for more info about those attributes.
++
++Attributes for devices
++----------------------
++
++Each device MAY support in its root subdirectory any read-only or
++read-writable attributes.
++
++SCST core will automatically create for all devices the following
++attributes:
++
++1. "type" - SCSI type of this device
++
++See SCST core's README for more info about those attributes.
++
++III. Rules for management utilities
++===================================
++
++Rules summary
++-------------
++
++A management utility (scstadmin) SHOULD NOT keep any knowledge specific
++to any device, dev handler, target or target driver. It SHOULD only know
++the common SCST SYSFS rules, which all dev handlers and target drivers
++MUST follow. Namely:
++
++Common rules:
++~~~~~~~~~~~~~
++
++1. All key attributes MUST be marked by mark "[key]" in the last line of
++the attribute.
++
++2. All not key attributes don't matter and SHOULD be ignored.
++
++For target drivers and targets:
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++1. If target driver supports adding new targets, it MUST have "mgmt"
++attribute, which MUST support "add_target" and "del_target" commands as
++specified above.
++
++2. If target driver supports run time adding new key attributes, it MUST
++have "mgmt" attribute, which MUST support "add_attribute" and
++"del_attribute" commands as specified above.
++
++3. If target driver supports both hardware and virtual targets, all its
++hardware targets MUST have "hw_target" attribute with value 1.
++
++4. If target has read-only key attributes, the add_target command MUST
++support them as parameters.
++
++5. If target supports run time adding new key attributes, the target
++driver MUST have "mgmt" attribute, which MUST support
++"add_target_attribute" and "del_target_attribute" commands as specified
++above.
++
++6. Both target drivers and targets MAY support "enable" attribute. If
++supported, after configuring the corresponding target driver or target
++"1" MUST be written to this attribute in the following order: at first,
++for all targets of the target driver, then for the target driver.
++
++For devices and dev handlers:
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++1. Each dev handler in its root subdirectory MUST have "mgmt" attribute.
++
++2. Each dev handler MUST support "add_device" and "del_device" commands
++to the "mgmt" attribute as specified above.
++
++3. If dev handler driver supports run time adding new key attributes, it
++MUST support "add_attribute" and "del_attribute" commands to the "mgmt"
++attribute as specified above.
++
++4. All device handlers have links in the root subdirectory pointing to
++their devices.
++
++5. If device has read-only key attributes, the "add_device" command MUST
++support them as parameters.
++
++6. If device supports run time adding new key attributes, its dev
++handler MUST support "add_device_attribute" and "del_device_attribute"
++commands to the "mgmt" attribute as specified above.
++
++7. Each device has "handler" link to its dev handler's root
++subdirectory.
++
++How to distinguish and process different types of attributes
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++Since management utilities only interested in key attributes, they
++should simply ignore all non-key attributes, like
++devices/device_name/type or targets/target_driver/target_name/version
++doesn't matter if they are read-only or writable. So, the word "key"
++will be omitted later in this section.
++
++At first, any attribute can be a key attribute, doesn't matter how it's
++created.
++
++All the existing on the configuration save time attributes should be
++treated the same. Management utilities shouldn't try to separate anyhow
++them in config files.
++
++1. Always existing attributes
++-----------------------------
++
++There are 2 type of them:
++
++1.1. Writable, like devices/device_name/t10_dev_id or
++targets/qla2x00tgt/target_name/explicit_confirmation. They are the
++simplest and all the values can just be read and written from/to them.
++
++On the configuration save time they can be distinguished as existing.
++
++On the write configuration time they can be distinguished as existing
++and writable.
++
++1.2. Read-only, like devices/fileio_device_name/filename or
++devices/fileio_device_name/block_size. They are also easy to distinguish
++looking at the permissions.
++
++On the configuration save time they can be distinguished the same as for
++(1.1) as existing.
++
++On the write configuration time they can be distinguished as existing
++and read-only. They all should be passed to "add_target" or
++"add_device" commands for virtual targets and devices correspondingly.
++To apply changes to them, the whole corresponding object
++(fileio_device_name in this example) should be removed then recreated.
++
++2. Optional
++-----------
++
++For instance, targets/iscsi/IncomingUser or
++targets/iscsi/target_name/IncomingUser. There are 4 types of them:
++
++2.1. Global for target drivers and dev handlers
++-----------------------------------------------
++
++For instance, targets/iscsi/IncomingUser or handlers/vdisk_fileio/XX
++(none at the moment).
++
++On the configuration save time they can be distinguished the same as for
++(1.1).
++
++On the write configuration time they can be distinguished as one of 4
++choices:
++
++2.1.1. Existing and writable. In this case they should be treated as
++(1.1)
++
++2.1.2. Existing and read-only. In this case they should be treated as
++(1.2).
++
++2.1.3. Not existing. In this case they should be added using
++"add_attribute" command.
++
++2.1.4. Existing in the sysfs tree and not existing in the config file.
++In this case they should be deleted using "del_attribute" command.
++
++2.2. Global for targets
++-----------------------
++
++For instance, targets/iscsi/target_name/IncomingUser.
++
++On the configuration save time they can be distinguished the same as (1.1).
++
++On the write configuration time they can be distinguished as one of 4
++choices:
++
++2.2.1. Existing and writable. In this case they should be treated as
++(1.1).
++
++2.2.2. Existing and read-only. In this case they should be treated as
++(1.2).
++
++2.2.3. Not existing. In this case they should be added using
++"add_target_attribute" command.
++
++2.2.4. Existing in the sysfs tree and not existing in the config file.
++In this case they should be deleted using "del_target_attribute"
++command.
++
++2.3. Global for devices
++-----------------------
++
++For instance, devices/nullio/t10_dev_id.
++
++On the configuration save time they can be distinguished the same as (1.1).
++
++On the write configuration time they can be distinguished as one of 4
++choices:
++
++2.3.1. Existing and writable. In this case they should be treated as
++(1.1)
++
++2.3.2. Existing and read-only. In this case they should be treated as
++(1.2).
++
++2.3.3. Not existing. In this case they should be added using
++"add_device_attribute" command for the corresponding handler, e.g.
++devices/nullio/handler/.
++
++2.3.4. Existing in the sysfs tree and not existing in the config file.
++In this case they should be deleted using "del_device_attribute"
++command for the corresponding handler, e.g. devices/nullio/handler/.
++
++Thus, management utility should implement only 8 procedures: (1.1),
++(1.2), (2.1.3), (2.1.4), (2.2.3), (2.2.4), (2.3.3), (2.3.4).
++
++How to distinguish hardware and virtual targets
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++A target is hardware:
++
++ * if exist both "hw_target" attribute and "mgmt" management file
++
++ * or if both don't exist
++
++A target is virtual if there is "mgmt" file and "hw_target" attribute
++doesn't exist.
++
++Algorithm to convert current SCST configuration to config file
++--------------------------------------------------------------
++
++A management utility SHOULD use the following algorithm when converting
++current SCST configuration to a config file.
++
++For all attributes with digits at the end the name, the digits part
++should be omitted from the attributes' names during the store. For
++instance, "IncomingUser1" should be stored as "IncomingUser".
++
++1. Scan all attributes in /sys/kernel/scst_tgt (not recursive) and store
++all found key attributes.
++
++2. Scan all subdirectories of /sys/kernel/scst_tgt/handlers. Each
++subdirectory with "mgmt" attribute is a root subdirectory of a dev
++handler with name the name of the subdirectory. For each found dev
++handler do the following:
++
++2.1. Store the dev handler's name. Store also its path to the root
++subdirectory, if it isn't default (/sys/kernel/scst_tgt/handlers/handler_name).
++
++2.2. Store all dev handler's key attributes.
++
++2.3. Go through all links in the root subdirectory pointing to
++/sys/kernel/scst_tgt/devices and for each device:
++
++2.3.1. For virtual devices dev handlers:
++
++2.3.1.1. Store the name of the device.
++
++2.3.1.2. Store all key attributes. Mark all read only key attributes
++during storing, they will be parameters for the device's creation.
++
++2.3.2. For pass-through devices dev handlers:
++
++2.3.2.1. Store the H:C:I:L name of the device. Optionally, instead of
++the name unique T10 vendor device ID found using command:
++
++sg_inq -p 0x83 /dev/sdX
++
++can be stored. It will allow to reliably find out this device if on the
++next reboot it will have another host:channel:id:lin numbers. The sdX
++device can be found as the last letters after ':' in
++/sys/kernel/scst_tgt/devices/H:C:I:L/scsi_device/device/block:sdX.
++
++3. Go through all subdirectories in /sys/kernel/scst_tgt/targets. For
++each target driver:
++
++3.1. Store the name of the target driver.
++
++3.2. Store all its key attributes.
++
++3.3. Go through all target's subdirectories. For each target:
++
++3.3.1. Store the name of the target.
++
++3.3.2. Mark if the target is hardware or virtual target. The target is a
++hardware target if it has "hw_target" attribute or its target driver
++doesn't have "mgmt" attribute.
++
++3.3.3. Store all key attributes. Mark all read only key attributes
++during storing, they will be parameters for the target's creation.
++
++3.3.4. Scan all "luns" subdirectory and store:
++
++ - LUN.
++
++ - LU's device name.
++
++ - Key attributes.
++
++3.3.5. Scan all "ini_groups" subdirectories. For each group store the following:
++
++ - The group's name.
++
++ - The group's LUNs (the same info as for 3.3.4).
++
++ - The group's initiators.
++
++3.3.6. Store value of "enabled" attribute, if it exists.
++
++3.4. Store value of "enabled" attribute, if it exists.
++
++Algorithm to initialize SCST from config file
++---------------------------------------------
++
++A management utility SHOULD use the following algorithm when doing
++initial SCST configuration from a config file. All necessary kernel
++modules and user space programs supposed to be already loaded, hence all
++dev handlers' entries in /sys/kernel/scst_tgt/handlers as well as all
++entries for hardware targets already created.
++
++1. Set stored values for all stored global (/sys/kernel/scst_tgt)
++attributes.
++
++2. For each dev driver:
++
++2.1. Set stored values for all already existing stored attributes.
++
++2.2. Create not existing stored attributes using "add_attribute" command.
++
++2.3. For virtual devices dev handlers for each stored device:
++
++2.3.1. Create the device using "add_device" command using marked read
++only attributes as parameters.
++
++2.3.2. Set stored values for all already existing stored attributes.
++
++2.3.3. Create not existing stored attributes using
++"add_device_attribute" command.
++
++2.4. For pass-through dev handlers for each stores device:
++
++2.4.1. Assign the corresponding pass-through device to this dev handler
++using "add_device" command.
++
++3. For each target driver:
++
++3.1. Set stored values for all already existing stored attributes.
++
++3.2. Create not existing stored attributes using "add_attribute" command.
++
++3.3. For each target:
++
++3.3.1. For virtual targets:
++
++3.3.1.1. Create the target using "add_target" command using marked read
++only attributes as parameters.
++
++3.3.1.2. Set stored values for all already existing stored attributes.
++
++3.3.1.3. Create not existing stored attributes using
++"add_target_attribute" command.
++
++3.3.2. For hardware targets for each target:
++
++3.3.2.1. Set stored values for all already existing stored attributes.
++
++3.3.2.2. Create not existing stored attributes using
++"add_target_attribute" command.
++
++3.3.3. Setup LUNs
++
++3.3.4. Setup ini_groups, their LUNs and initiators' names.
++
++3.3.5. If this target supports enabling, enable it.
++
++3.4. If this target driver supports enabling, enable it.
++
++Algorithm to apply changes in config file to currently running SCST
++-------------------------------------------------------------------
++
++A management utility SHOULD use the following algorithm when applying
++changes in config file to currently running SCST.
++
++Not all changes can be applied on enabled targets or enabled target
++drivers. From other side, for some target drivers enabling/disabling is
++a very long and disruptive operation, which should be performed as rare
++as possible. Thus, the management utility SHOULD support additional
++option, which, if set, will make it to disable all affected targets
++before doing any change with them.
++
++1. Scan all attributes in /sys/kernel/scst_tgt (not recursive) and
++compare stored and actual key attributes. Apply all changes.
++
++2. Scan all subdirectories of /sys/kernel/scst_tgt/handlers. Each
++subdirectory with "mgmt" attribute is a root subdirectory of a dev
++handler with name the name of the subdirectory. For each found dev
++handler do the following:
++
++2.1. Compare stored and actual key attributes. Apply all changes. Create
++new attributes using "add_attribute" commands and delete not needed any
++more attributes using "del_attribute" command.
++
++2.2. Compare existing devices (links in the root subdirectory pointing
++to /sys/kernel/scst_tgt/devices) and stored devices in the config file.
++Delete all not needed devices and create new devices.
++
++2.3. For all existing devices:
++
++2.3.1. Compare stored and actual key attributes. Apply all changes.
++Create new attributes using "add_device_attribute" commands and delete
++not needed any more attributes using "del_device_attribute" command.
++
++2.3.2. If any read only key attribute for virtual device should be
++changed, delete the devices and recreate it.
++
++3. Go through all subdirectories in /sys/kernel/scst_tgt/targets. For
++each target driver:
++
++3.1. If this target driver should be disabled, disable it.
++
++3.2. Compare stored and actual key attributes. Apply all changes. Create
++new attributes using "add_attribute" commands and delete not needed any
++more attributes using "del_attribute" command.
++
++3.3. Go through all target's subdirectories. Compare existing and stored
++targets. Delete all not needed targets and create new targets.
++
++3.4. For all existing targets:
++
++3.4.1. If this target should be disabled, disable it.
++
++3.4.2. Compare stored and actual key attributes. Apply all changes.
++Create new attributes using "add_target_attribute" commands and delete
++not needed any more attributes using "del_target_attribute" command.
++
++3.4.3. If any read only key attribute for virtual target should be
++changed, delete the target and recreate it.
++
++3.4.4. Scan all "luns" subdirectory and apply necessary changes, using
++"replace" commands to replace one LUN by another, if needed.
++
++3.4.5. Scan all "ini_groups" subdirectories and apply necessary changes,
++using "replace" commands to replace one LUN by another and "move"
++command to move initiator from one group to another, if needed. It MUST
++be done in the following order:
++
++ - Necessary initiators deleted, if they aren't going to be moved
++
++ - LUNs updated
++
++ - Necessary initiators added or moved
++
++3.4.6. If this target should be enabled, enable it.
++
++3.5. If this target driver should be enabled, enable it.
++
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/Makefile linux-2.6.36/drivers/scst/dev_handlers/Makefile
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/Makefile
++++ linux-2.6.36/drivers/scst/dev_handlers/Makefile
+@@ -0,0 +1,14 @@
++ccflags-y += -Wno-unused-parameter
++
++obj-m := scst_cdrom.o scst_changer.o scst_disk.o scst_modisk.o scst_tape.o \
++ scst_vdisk.o scst_raid.o scst_processor.o scst_user.o
++
++obj-$(CONFIG_SCST_DISK) += scst_disk.o
++obj-$(CONFIG_SCST_TAPE) += scst_tape.o
++obj-$(CONFIG_SCST_CDROM) += scst_cdrom.o
++obj-$(CONFIG_SCST_MODISK) += scst_modisk.o
++obj-$(CONFIG_SCST_CHANGER) += scst_changer.o
++obj-$(CONFIG_SCST_RAID) += scst_raid.o
++obj-$(CONFIG_SCST_PROCESSOR) += scst_processor.o
++obj-$(CONFIG_SCST_VDISK) += scst_vdisk.o
++obj-$(CONFIG_SCST_USER) += scst_user.o
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_cdrom.c linux-2.6.36/drivers/scst/dev_handlers/scst_cdrom.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_cdrom.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_cdrom.c
+@@ -0,0 +1,302 @@
++/*
++ * scst_cdrom.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI CDROM (type 5) dev handler
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/cdrom.h>
++#include <scsi/scsi_host.h>
++#include <linux/slab.h>
++
++#define LOG_PREFIX "dev_cdrom"
++
++#include <scst/scst.h>
++#include "scst_dev_handler.h"
++
++#define CDROM_NAME "dev_cdrom"
++
++#define CDROM_DEF_BLOCK_SHIFT 11
++
++struct cdrom_params {
++ int block_shift;
++};
++
++static int cdrom_attach(struct scst_device *);
++static void cdrom_detach(struct scst_device *);
++static int cdrom_parse(struct scst_cmd *);
++static int cdrom_done(struct scst_cmd *);
++
++static struct scst_dev_type cdrom_devtype = {
++ .name = CDROM_NAME,
++ .type = TYPE_ROM,
++ .threads_num = 1,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = cdrom_attach,
++ .detach = cdrom_detach,
++ .parse = cdrom_parse,
++ .dev_done = cdrom_done,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++/**************************************************************
++ * Function: cdrom_attach
++ *
++ * Argument:
++ *
++ * Returns : 1 if attached, error code otherwise
++ *
++ * Description:
++ *************************************************************/
++static int cdrom_attach(struct scst_device *dev)
++{
++ int res, rc;
++ uint8_t cmd[10];
++ const int buffer_size = 512;
++ uint8_t *buffer = NULL;
++ int retries;
++ unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
++ enum dma_data_direction data_dir;
++ struct cdrom_params *params;
++
++ TRACE_ENTRY();
++
++ if (dev->scsi_dev == NULL ||
++ dev->scsi_dev->type != dev->type) {
++ PRINT_ERROR("%s", "SCSI device not define or illegal type");
++ res = -ENODEV;
++ goto out;
++ }
++
++ params = kzalloc(sizeof(*params), GFP_KERNEL);
++ if (params == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s",
++ "Unable to allocate struct cdrom_params");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ buffer = kmalloc(buffer_size, GFP_KERNEL);
++ if (!buffer) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
++ res = -ENOMEM;
++ goto out_free_params;
++ }
++
++ /* Clear any existing UA's and get cdrom capacity (cdrom block size) */
++ memset(cmd, 0, sizeof(cmd));
++ cmd[0] = READ_CAPACITY;
++ cmd[1] = (dev->scsi_dev->scsi_level <= SCSI_2) ?
++ ((dev->scsi_dev->lun << 5) & 0xe0) : 0;
++ retries = SCST_DEV_UA_RETRIES;
++ while (1) {
++ memset(buffer, 0, buffer_size);
++ memset(sense_buffer, 0, sizeof(sense_buffer));
++ data_dir = SCST_DATA_READ;
++
++ TRACE_DBG("%s", "Doing READ_CAPACITY");
++ rc = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
++ buffer_size, sense_buffer,
++ SCST_GENERIC_CDROM_REG_TIMEOUT, 3, 0
++ , NULL
++ );
++
++ TRACE_DBG("READ_CAPACITY done: %x", rc);
++
++ if ((rc == 0) ||
++ !scst_analyze_sense(sense_buffer,
++ sizeof(sense_buffer), SCST_SENSE_KEY_VALID,
++ UNIT_ATTENTION, 0, 0))
++ break;
++
++ if (!--retries) {
++ PRINT_ERROR("UA not cleared after %d retries",
++ SCST_DEV_UA_RETRIES);
++ params->block_shift = CDROM_DEF_BLOCK_SHIFT;
++ res = -ENODEV;
++ goto out_free_buf;
++ }
++ }
++
++ if (rc == 0) {
++ int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
++ (buffer[6] << 8) | (buffer[7] << 0));
++ if (sector_size == 0)
++ params->block_shift = CDROM_DEF_BLOCK_SHIFT;
++ else
++ params->block_shift =
++ scst_calc_block_shift(sector_size);
++ TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
++ sector_size, dev->scsi_dev->scsi_level, SCSI_2);
++ } else {
++ params->block_shift = CDROM_DEF_BLOCK_SHIFT;
++ TRACE(TRACE_MINOR, "Read capacity failed: %x, using default "
++ "sector size %d", rc, params->block_shift);
++ PRINT_BUFF_FLAG(TRACE_MINOR, "Returned sense", sense_buffer,
++ sizeof(sense_buffer));
++ }
++
++ res = scst_obtain_device_parameters(dev);
++ if (res != 0) {
++ PRINT_ERROR("Failed to obtain control parameters for device "
++ "%s", dev->virt_name);
++ goto out_free_buf;
++ }
++
++out_free_buf:
++ kfree(buffer);
++
++out_free_params:
++ if (res == 0)
++ dev->dh_priv = params;
++ else
++ kfree(params);
++
++out:
++ TRACE_EXIT();
++ return res;
++}
++
++/************************************************************
++ * Function: cdrom_detach
++ *
++ * Argument:
++ *
++ * Returns : None
++ *
++ * Description: Called to detach this device type driver
++ ************************************************************/
++static void cdrom_detach(struct scst_device *dev)
++{
++ struct cdrom_params *params =
++ (struct cdrom_params *)dev->dh_priv;
++
++ TRACE_ENTRY();
++
++ kfree(params);
++ dev->dh_priv = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++static int cdrom_get_block_shift(struct scst_cmd *cmd)
++{
++ struct cdrom_params *params = (struct cdrom_params *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ return params->block_shift;
++}
++
++/********************************************************************
++ * Function: cdrom_parse
++ *
++ * Argument:
++ *
++ * Returns : The state of the command
++ *
++ * Description: This does the parsing of the command
++ *
++ * Note: Not all states are allowed on return
++ ********************************************************************/
++static int cdrom_parse(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ scst_cdrom_generic_parse(cmd, cdrom_get_block_shift);
++
++ cmd->retries = SCST_PASSTHROUGH_RETRIES;
++
++ return res;
++}
++
++static void cdrom_set_block_shift(struct scst_cmd *cmd, int block_shift)
++{
++ struct cdrom_params *params = (struct cdrom_params *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ if (block_shift != 0)
++ params->block_shift = block_shift;
++ else
++ params->block_shift = CDROM_DEF_BLOCK_SHIFT;
++ return;
++}
++
++/********************************************************************
++ * Function: cdrom_done
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: This is the completion routine for the command,
++ * it is used to extract any necessary information
++ * about a command.
++ ********************************************************************/
++static int cdrom_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ res = scst_block_generic_dev_done(cmd, cdrom_set_block_shift);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int __init cdrom_init(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ cdrom_devtype.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&cdrom_devtype);
++ if (res < 0)
++ goto out;
++
++out:
++ TRACE_EXIT();
++ return res;
++
++}
++
++static void __exit cdrom_exit(void)
++{
++ TRACE_ENTRY();
++ scst_unregister_dev_driver(&cdrom_devtype);
++ TRACE_EXIT();
++ return;
++}
++
++module_init(cdrom_init);
++module_exit(cdrom_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
++MODULE_DESCRIPTION("SCSI CDROM (type 5) dev handler for SCST");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_changer.c linux-2.6.36/drivers/scst/dev_handlers/scst_changer.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_changer.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_changer.c
+@@ -0,0 +1,223 @@
++/*
++ * scst_changer.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI medium changer (type 8) dev handler
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <scsi/scsi_host.h>
++#include <linux/slab.h>
++
++#define LOG_PREFIX "dev_changer"
++
++#include <scst/scst.h>
++#include "scst_dev_handler.h"
++
++#define CHANGER_NAME "dev_changer"
++
++#define CHANGER_RETRIES 2
++
++static int changer_attach(struct scst_device *);
++/* static void changer_detach(struct scst_device *); */
++static int changer_parse(struct scst_cmd *);
++/* static int changer_done(struct scst_cmd *); */
++
++static struct scst_dev_type changer_devtype = {
++ .name = CHANGER_NAME,
++ .type = TYPE_MEDIUM_CHANGER,
++ .threads_num = 1,
++ .parse_atomic = 1,
++/* .dev_done_atomic = 1, */
++ .attach = changer_attach,
++/* .detach = changer_detach, */
++ .parse = changer_parse,
++/* .dev_done = changer_done */
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++/**************************************************************
++ * Function: changer_attach
++ *
++ * Argument:
++ *
++ * Returns : 1 if attached, error code otherwise
++ *
++ * Description:
++ *************************************************************/
++static int changer_attach(struct scst_device *dev)
++{
++ int res, rc;
++ int retries;
++
++ TRACE_ENTRY();
++
++ if (dev->scsi_dev == NULL ||
++ dev->scsi_dev->type != dev->type) {
++ PRINT_ERROR("%s", "SCSI device not define or illegal type");
++ res = -ENODEV;
++ goto out;
++ }
++
++ /*
++ * If the device is offline, don't try to read capacity or any
++ * of the other stuff
++ */
++ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) {
++ TRACE_DBG("%s", "Device is offline");
++ res = -ENODEV;
++ goto out;
++ }
++
++ retries = SCST_DEV_UA_RETRIES;
++ do {
++ TRACE_DBG("%s", "Doing TEST_UNIT_READY");
++ rc = scsi_test_unit_ready(dev->scsi_dev,
++ SCST_GENERIC_CHANGER_TIMEOUT, CHANGER_RETRIES
++ , NULL);
++ TRACE_DBG("TEST_UNIT_READY done: %x", rc);
++ } while ((--retries > 0) && rc);
++
++ if (rc) {
++ PRINT_WARNING("Unit not ready: %x", rc);
++ /* Let's try not to be too smart and continue processing */
++ }
++
++ res = scst_obtain_device_parameters(dev);
++ if (res != 0) {
++ PRINT_ERROR("Failed to obtain control parameters for device "
++ "%s", dev->virt_name);
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_HRES(res);
++ return res;
++}
++
++/************************************************************
++ * Function: changer_detach
++ *
++ * Argument:
++ *
++ * Returns : None
++ *
++ * Description: Called to detach this device type driver
++ ************************************************************/
++#if 0
++void changer_detach(struct scst_device *dev)
++{
++ TRACE_ENTRY();
++
++ TRACE_EXIT();
++ return;
++}
++#endif
++
++/********************************************************************
++ * Function: changer_parse
++ *
++ * Argument:
++ *
++ * Returns : The state of the command
++ *
++ * Description: This does the parsing of the command
++ *
++ * Note: Not all states are allowed on return
++ ********************************************************************/
++static int changer_parse(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ scst_changer_generic_parse(cmd, NULL);
++
++ cmd->retries = SCST_PASSTHROUGH_RETRIES;
++
++ return res;
++}
++
++/********************************************************************
++ * Function: changer_done
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: This is the completion routine for the command,
++ * it is used to extract any necessary information
++ * about a command.
++ ********************************************************************/
++#if 0
++int changer_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->is_send_status and
++ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
++ * therefore change them only if necessary
++ */
++
++#if 0
++ switch (cmd->cdb[0]) {
++ default:
++ /* It's all good */
++ break;
++ }
++#endif
++
++ TRACE_EXIT();
++ return res;
++}
++#endif
++
++static int __init changer_init(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ changer_devtype.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&changer_devtype);
++ if (res < 0)
++ goto out;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void __exit changer_exit(void)
++{
++ TRACE_ENTRY();
++ scst_unregister_dev_driver(&changer_devtype);
++ TRACE_EXIT();
++ return;
++}
++
++module_init(changer_init);
++module_exit(changer_exit);
++
++MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCSI medium changer (type 8) dev handler for SCST");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_dev_handler.h linux-2.6.36/drivers/scst/dev_handlers/scst_dev_handler.h
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_dev_handler.h
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_dev_handler.h
+@@ -0,0 +1,27 @@
++#ifndef __SCST_DEV_HANDLER_H
++#define __SCST_DEV_HANDLER_H
++
++#include <linux/module.h>
++#include <scsi/scsi_eh.h>
++#include <scst/scst_debug.h>
++
++#define SCST_DEV_UA_RETRIES 5
++#define SCST_PASSTHROUGH_RETRIES 0
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++
++#ifdef CONFIG_SCST_DEBUG
++#define SCST_DEFAULT_DEV_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_PID | \
++ TRACE_LINE | TRACE_FUNCTION | TRACE_MGMT | TRACE_MINOR | \
++ TRACE_MGMT_DEBUG | TRACE_SPECIAL)
++#else
++#define SCST_DEFAULT_DEV_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
++ TRACE_SPECIAL)
++#endif
++
++static unsigned long dh_trace_flag = SCST_DEFAULT_DEV_LOG_FLAGS;
++#define trace_flag dh_trace_flag
++
++#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */
++
++#endif /* __SCST_DEV_HANDLER_H */
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_disk.c linux-2.6.36/drivers/scst/dev_handlers/scst_disk.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_disk.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_disk.c
+@@ -0,0 +1,380 @@
++/*
++ * scst_disk.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI disk (type 0) dev handler
++ * &
++ * SCSI disk (type 0) "performance" device handler (skip all READ and WRITE
++ * operations).
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <scsi/scsi_host.h>
++#include <linux/slab.h>
++
++#define LOG_PREFIX "dev_disk"
++
++#include <scst/scst.h>
++#include "scst_dev_handler.h"
++
++# define DISK_NAME "dev_disk"
++# define DISK_PERF_NAME "dev_disk_perf"
++
++#define DISK_DEF_BLOCK_SHIFT 9
++
++struct disk_params {
++ int block_shift;
++};
++
++static int disk_attach(struct scst_device *dev);
++static void disk_detach(struct scst_device *dev);
++static int disk_parse(struct scst_cmd *cmd);
++static int disk_done(struct scst_cmd *cmd);
++static int disk_exec(struct scst_cmd *cmd);
++
++static struct scst_dev_type disk_devtype = {
++ .name = DISK_NAME,
++ .type = TYPE_DISK,
++ .threads_num = 1,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = disk_attach,
++ .detach = disk_detach,
++ .parse = disk_parse,
++ .dev_done = disk_done,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static struct scst_dev_type disk_devtype_perf = {
++ .name = DISK_PERF_NAME,
++ .type = TYPE_DISK,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = disk_attach,
++ .detach = disk_detach,
++ .parse = disk_parse,
++ .dev_done = disk_done,
++ .exec = disk_exec,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static int __init init_scst_disk_driver(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ disk_devtype.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&disk_devtype);
++ if (res < 0)
++ goto out;
++
++ disk_devtype_perf.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&disk_devtype_perf);
++ if (res < 0)
++ goto out_unreg;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unreg:
++ scst_unregister_dev_driver(&disk_devtype);
++ goto out;
++}
++
++static void __exit exit_scst_disk_driver(void)
++{
++ TRACE_ENTRY();
++
++ scst_unregister_dev_driver(&disk_devtype_perf);
++ scst_unregister_dev_driver(&disk_devtype);
++
++ TRACE_EXIT();
++ return;
++}
++
++module_init(init_scst_disk_driver);
++module_exit(exit_scst_disk_driver);
++
++/**************************************************************
++ * Function: disk_attach
++ *
++ * Argument:
++ *
++ * Returns : 1 if attached, error code otherwise
++ *
++ * Description:
++ *************************************************************/
++static int disk_attach(struct scst_device *dev)
++{
++ int res, rc;
++ uint8_t cmd[10];
++ const int buffer_size = 512;
++ uint8_t *buffer = NULL;
++ int retries;
++ unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
++ enum dma_data_direction data_dir;
++ struct disk_params *params;
++
++ TRACE_ENTRY();
++
++ if (dev->scsi_dev == NULL ||
++ dev->scsi_dev->type != dev->type) {
++ PRINT_ERROR("%s", "SCSI device not define or illegal type");
++ res = -ENODEV;
++ goto out;
++ }
++
++ params = kzalloc(sizeof(*params), GFP_KERNEL);
++ if (params == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s",
++ "Unable to allocate struct disk_params");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ buffer = kmalloc(buffer_size, GFP_KERNEL);
++ if (!buffer) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
++ res = -ENOMEM;
++ goto out_free_params;
++ }
++
++ /* Clear any existing UA's and get disk capacity (disk block size) */
++ memset(cmd, 0, sizeof(cmd));
++ cmd[0] = READ_CAPACITY;
++ cmd[1] = (dev->scsi_dev->scsi_level <= SCSI_2) ?
++ ((dev->scsi_dev->lun << 5) & 0xe0) : 0;
++ retries = SCST_DEV_UA_RETRIES;
++ while (1) {
++ memset(buffer, 0, buffer_size);
++ memset(sense_buffer, 0, sizeof(sense_buffer));
++ data_dir = SCST_DATA_READ;
++
++ TRACE_DBG("%s", "Doing READ_CAPACITY");
++ rc = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
++ buffer_size, sense_buffer,
++ SCST_GENERIC_DISK_REG_TIMEOUT, 3, 0
++ , NULL
++ );
++
++ TRACE_DBG("READ_CAPACITY done: %x", rc);
++
++ if ((rc == 0) ||
++ !scst_analyze_sense(sense_buffer,
++ sizeof(sense_buffer), SCST_SENSE_KEY_VALID,
++ UNIT_ATTENTION, 0, 0))
++ break;
++ if (!--retries) {
++ PRINT_ERROR("UA not clear after %d retries",
++ SCST_DEV_UA_RETRIES);
++ res = -ENODEV;
++ goto out_free_buf;
++ }
++ }
++ if (rc == 0) {
++ int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
++ (buffer[6] << 8) | (buffer[7] << 0));
++ if (sector_size == 0)
++ params->block_shift = DISK_DEF_BLOCK_SHIFT;
++ else
++ params->block_shift =
++ scst_calc_block_shift(sector_size);
++ } else {
++ params->block_shift = DISK_DEF_BLOCK_SHIFT;
++ TRACE(TRACE_MINOR, "Read capacity failed: %x, using default "
++ "sector size %d", rc, params->block_shift);
++ PRINT_BUFF_FLAG(TRACE_MINOR, "Returned sense", sense_buffer,
++ sizeof(sense_buffer));
++ }
++
++ res = scst_obtain_device_parameters(dev);
++ if (res != 0) {
++ PRINT_ERROR("Failed to obtain control parameters for device "
++ "%s", dev->virt_name);
++ goto out_free_buf;
++ }
++
++out_free_buf:
++ kfree(buffer);
++
++out_free_params:
++ if (res == 0)
++ dev->dh_priv = params;
++ else
++ kfree(params);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/************************************************************
++ * Function: disk_detach
++ *
++ * Argument:
++ *
++ * Returns : None
++ *
++ * Description: Called to detach this device type driver
++ ************************************************************/
++static void disk_detach(struct scst_device *dev)
++{
++ struct disk_params *params =
++ (struct disk_params *)dev->dh_priv;
++
++ TRACE_ENTRY();
++
++ kfree(params);
++ dev->dh_priv = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++static int disk_get_block_shift(struct scst_cmd *cmd)
++{
++ struct disk_params *params = (struct disk_params *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ return params->block_shift;
++}
++
++/********************************************************************
++ * Function: disk_parse
++ *
++ * Argument:
++ *
++ * Returns : The state of the command
++ *
++ * Description: This does the parsing of the command
++ *
++ * Note: Not all states are allowed on return
++ ********************************************************************/
++static int disk_parse(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ scst_sbc_generic_parse(cmd, disk_get_block_shift);
++
++ cmd->retries = SCST_PASSTHROUGH_RETRIES;
++
++ return res;
++}
++
++static void disk_set_block_shift(struct scst_cmd *cmd, int block_shift)
++{
++ struct disk_params *params = (struct disk_params *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ if (block_shift != 0)
++ params->block_shift = block_shift;
++ else
++ params->block_shift = DISK_DEF_BLOCK_SHIFT;
++ return;
++}
++
++/********************************************************************
++ * Function: disk_done
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: This is the completion routine for the command,
++ * it is used to extract any necessary information
++ * about a command.
++ ********************************************************************/
++static int disk_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ res = scst_block_generic_dev_done(cmd, disk_set_block_shift);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/********************************************************************
++ * Function: disk_exec
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: Make SCST do nothing for data READs and WRITES.
++ * Intended for raw line performance testing
++ ********************************************************************/
++static int disk_exec(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_NOT_COMPLETED, rc;
++ int opcode = cmd->cdb[0];
++
++ TRACE_ENTRY();
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++
++ switch (opcode) {
++ case WRITE_6:
++ case WRITE_10:
++ case WRITE_12:
++ case WRITE_16:
++ case READ_6:
++ case READ_10:
++ case READ_12:
++ case READ_16:
++ cmd->completed = 1;
++ goto out_done;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_done:
++ res = SCST_EXEC_COMPLETED;
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++ goto out;
++}
++
++MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCSI disk (type 0) dev handler for SCST");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_modisk.c linux-2.6.36/drivers/scst/dev_handlers/scst_modisk.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_modisk.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_modisk.c
+@@ -0,0 +1,399 @@
++/*
++ * scst_modisk.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI MO disk (type 7) dev handler
++ * &
++ * SCSI MO disk (type 7) "performance" device handler (skip all READ and WRITE
++ * operations).
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <scsi/scsi_host.h>
++#include <linux/slab.h>
++
++#define LOG_PREFIX "dev_modisk"
++
++#include <scst/scst.h>
++#include "scst_dev_handler.h"
++
++# define MODISK_NAME "dev_modisk"
++# define MODISK_PERF_NAME "dev_modisk_perf"
++
++#define MODISK_DEF_BLOCK_SHIFT 10
++
++struct modisk_params {
++ int block_shift;
++};
++
++static int modisk_attach(struct scst_device *);
++static void modisk_detach(struct scst_device *);
++static int modisk_parse(struct scst_cmd *);
++static int modisk_done(struct scst_cmd *);
++static int modisk_exec(struct scst_cmd *);
++
++static struct scst_dev_type modisk_devtype = {
++ .name = MODISK_NAME,
++ .type = TYPE_MOD,
++ .threads_num = 1,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = modisk_attach,
++ .detach = modisk_detach,
++ .parse = modisk_parse,
++ .dev_done = modisk_done,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static struct scst_dev_type modisk_devtype_perf = {
++ .name = MODISK_PERF_NAME,
++ .type = TYPE_MOD,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = modisk_attach,
++ .detach = modisk_detach,
++ .parse = modisk_parse,
++ .dev_done = modisk_done,
++ .exec = modisk_exec,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static int __init init_scst_modisk_driver(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ modisk_devtype.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&modisk_devtype);
++ if (res < 0)
++ goto out;
++
++ modisk_devtype_perf.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&modisk_devtype_perf);
++ if (res < 0)
++ goto out_unreg;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unreg:
++ scst_unregister_dev_driver(&modisk_devtype);
++ goto out;
++}
++
++static void __exit exit_scst_modisk_driver(void)
++{
++ TRACE_ENTRY();
++
++ scst_unregister_dev_driver(&modisk_devtype_perf);
++ scst_unregister_dev_driver(&modisk_devtype);
++
++ TRACE_EXIT();
++ return;
++}
++
++module_init(init_scst_modisk_driver);
++module_exit(exit_scst_modisk_driver);
++
++/**************************************************************
++ * Function: modisk_attach
++ *
++ * Argument:
++ *
++ * Returns : 1 if attached, error code otherwise
++ *
++ * Description:
++ *************************************************************/
++static int modisk_attach(struct scst_device *dev)
++{
++ int res, rc;
++ uint8_t cmd[10];
++ const int buffer_size = 512;
++ uint8_t *buffer = NULL;
++ int retries;
++ unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
++ enum dma_data_direction data_dir;
++ struct modisk_params *params;
++
++ TRACE_ENTRY();
++
++ if (dev->scsi_dev == NULL ||
++ dev->scsi_dev->type != dev->type) {
++ PRINT_ERROR("%s", "SCSI device not define or illegal type");
++ res = -ENODEV;
++ goto out;
++ }
++
++ params = kzalloc(sizeof(*params), GFP_KERNEL);
++ if (params == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s",
++ "Unable to allocate struct modisk_params");
++ res = -ENOMEM;
++ goto out;
++ }
++ params->block_shift = MODISK_DEF_BLOCK_SHIFT;
++
++ /*
++ * If the device is offline, don't try to read capacity or any
++ * of the other stuff
++ */
++ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) {
++ TRACE_DBG("%s", "Device is offline");
++ res = -ENODEV;
++ goto out_free_params;
++ }
++
++ buffer = kmalloc(buffer_size, GFP_KERNEL);
++ if (!buffer) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
++ res = -ENOMEM;
++ goto out_free_params;
++ }
++
++ /*
++ * Clear any existing UA's and get modisk capacity (modisk block
++ * size).
++ */
++ memset(cmd, 0, sizeof(cmd));
++ cmd[0] = READ_CAPACITY;
++ cmd[1] = (dev->scsi_dev->scsi_level <= SCSI_2) ?
++ ((dev->scsi_dev->lun << 5) & 0xe0) : 0;
++ retries = SCST_DEV_UA_RETRIES;
++ while (1) {
++ memset(buffer, 0, buffer_size);
++ memset(sense_buffer, 0, sizeof(sense_buffer));
++ data_dir = SCST_DATA_READ;
++
++ TRACE_DBG("%s", "Doing READ_CAPACITY");
++ rc = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
++ buffer_size, sense_buffer,
++ SCST_GENERIC_MODISK_REG_TIMEOUT, 3, 0
++ , NULL
++ );
++
++ TRACE_DBG("READ_CAPACITY done: %x", rc);
++
++ if (!rc || !scst_analyze_sense(sense_buffer,
++ sizeof(sense_buffer), SCST_SENSE_KEY_VALID,
++ UNIT_ATTENTION, 0, 0))
++ break;
++
++ if (!--retries) {
++ PRINT_ERROR("UA not cleared after %d retries",
++ SCST_DEV_UA_RETRIES);
++ res = -ENODEV;
++ goto out_free_buf;
++ }
++ }
++
++ if (rc == 0) {
++ int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
++ (buffer[6] << 8) | (buffer[7] << 0));
++ if (sector_size == 0)
++ params->block_shift = MODISK_DEF_BLOCK_SHIFT;
++ else
++ params->block_shift =
++ scst_calc_block_shift(sector_size);
++ TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
++ sector_size, dev->scsi_dev->scsi_level, SCSI_2);
++ } else {
++ params->block_shift = MODISK_DEF_BLOCK_SHIFT;
++ TRACE(TRACE_MINOR, "Read capacity failed: %x, using default "
++ "sector size %d", rc, params->block_shift);
++ PRINT_BUFF_FLAG(TRACE_MINOR, "Returned sense", sense_buffer,
++ sizeof(sense_buffer));
++ }
++
++ res = scst_obtain_device_parameters(dev);
++ if (res != 0) {
++ PRINT_ERROR("Failed to obtain control parameters for device "
++ "%s: %x", dev->virt_name, res);
++ goto out_free_buf;
++ }
++
++out_free_buf:
++ kfree(buffer);
++
++out_free_params:
++ if (res == 0)
++ dev->dh_priv = params;
++ else
++ kfree(params);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/************************************************************
++ * Function: modisk_detach
++ *
++ * Argument:
++ *
++ * Returns : None
++ *
++ * Description: Called to detach this device type driver
++ ************************************************************/
++static void modisk_detach(struct scst_device *dev)
++{
++ struct modisk_params *params =
++ (struct modisk_params *)dev->dh_priv;
++
++ TRACE_ENTRY();
++
++ kfree(params);
++ dev->dh_priv = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++static int modisk_get_block_shift(struct scst_cmd *cmd)
++{
++ struct modisk_params *params =
++ (struct modisk_params *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ return params->block_shift;
++}
++
++/********************************************************************
++ * Function: modisk_parse
++ *
++ * Argument:
++ *
++ * Returns : The state of the command
++ *
++ * Description: This does the parsing of the command
++ *
++ * Note: Not all states are allowed on return
++ ********************************************************************/
++static int modisk_parse(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ scst_modisk_generic_parse(cmd, modisk_get_block_shift);
++
++ cmd->retries = SCST_PASSTHROUGH_RETRIES;
++
++ return res;
++}
++
++static void modisk_set_block_shift(struct scst_cmd *cmd, int block_shift)
++{
++ struct modisk_params *params =
++ (struct modisk_params *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be
++ * called, when there are existing commands.
++ */
++ if (block_shift != 0)
++ params->block_shift = block_shift;
++ else
++ params->block_shift = MODISK_DEF_BLOCK_SHIFT;
++ return;
++}
++
++/********************************************************************
++ * Function: modisk_done
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: This is the completion routine for the command,
++ * it is used to extract any necessary information
++ * about a command.
++ ********************************************************************/
++static int modisk_done(struct scst_cmd *cmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ res = scst_block_generic_dev_done(cmd, modisk_set_block_shift);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/********************************************************************
++ * Function: modisk_exec
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: Make SCST do nothing for data READs and WRITES.
++ * Intended for raw line performance testing
++ ********************************************************************/
++static int modisk_exec(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_NOT_COMPLETED, rc;
++ int opcode = cmd->cdb[0];
++
++ TRACE_ENTRY();
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++
++ switch (opcode) {
++ case WRITE_6:
++ case WRITE_10:
++ case WRITE_12:
++ case WRITE_16:
++ case READ_6:
++ case READ_10:
++ case READ_12:
++ case READ_16:
++ cmd->completed = 1;
++ goto out_done;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_done:
++ res = SCST_EXEC_COMPLETED;
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++ goto out;
++}
++
++MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCSI MO disk (type 7) dev handler for SCST");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_processor.c linux-2.6.36/drivers/scst/dev_handlers/scst_processor.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_processor.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_processor.c
+@@ -0,0 +1,223 @@
++/*
++ * scst_processor.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI medium processor (type 3) dev handler
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <scsi/scsi_host.h>
++#include <linux/slab.h>
++
++#define LOG_PREFIX "dev_processor"
++
++#include <scst/scst.h>
++#include "scst_dev_handler.h"
++
++#define PROCESSOR_NAME "dev_processor"
++
++#define PROCESSOR_RETRIES 2
++
++static int processor_attach(struct scst_device *);
++/*static void processor_detach(struct scst_device *);*/
++static int processor_parse(struct scst_cmd *);
++/*static int processor_done(struct scst_cmd *);*/
++
++static struct scst_dev_type processor_devtype = {
++ .name = PROCESSOR_NAME,
++ .type = TYPE_PROCESSOR,
++ .threads_num = 1,
++ .parse_atomic = 1,
++/* .dev_done_atomic = 1,*/
++ .attach = processor_attach,
++/* .detach = processor_detach,*/
++ .parse = processor_parse,
++/* .dev_done = processor_done*/
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++/**************************************************************
++ * Function: processor_attach
++ *
++ * Argument:
++ *
++ * Returns : 1 if attached, error code otherwise
++ *
++ * Description:
++ *************************************************************/
++static int processor_attach(struct scst_device *dev)
++{
++ int res, rc;
++ int retries;
++
++ TRACE_ENTRY();
++
++ if (dev->scsi_dev == NULL ||
++ dev->scsi_dev->type != dev->type) {
++ PRINT_ERROR("%s", "SCSI device not define or illegal type");
++ res = -ENODEV;
++ goto out;
++ }
++
++ /*
++ * If the device is offline, don't try to read capacity or any
++ * of the other stuff
++ */
++ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) {
++ TRACE_DBG("%s", "Device is offline");
++ res = -ENODEV;
++ goto out;
++ }
++
++ retries = SCST_DEV_UA_RETRIES;
++ do {
++ TRACE_DBG("%s", "Doing TEST_UNIT_READY");
++ rc = scsi_test_unit_ready(dev->scsi_dev,
++ SCST_GENERIC_PROCESSOR_TIMEOUT, PROCESSOR_RETRIES
++ , NULL);
++ TRACE_DBG("TEST_UNIT_READY done: %x", rc);
++ } while ((--retries > 0) && rc);
++
++ if (rc) {
++ PRINT_WARNING("Unit not ready: %x", rc);
++ /* Let's try not to be too smart and continue processing */
++ }
++
++ res = scst_obtain_device_parameters(dev);
++ if (res != 0) {
++ PRINT_ERROR("Failed to obtain control parameters for device "
++ "%s", dev->virt_name);
++ goto out;
++ }
++
++out:
++ TRACE_EXIT();
++ return res;
++}
++
++/************************************************************
++ * Function: processor_detach
++ *
++ * Argument:
++ *
++ * Returns : None
++ *
++ * Description: Called to detach this device type driver
++ ************************************************************/
++#if 0
++void processor_detach(struct scst_device *dev)
++{
++ TRACE_ENTRY();
++
++ TRACE_EXIT();
++ return;
++}
++#endif
++
++/********************************************************************
++ * Function: processor_parse
++ *
++ * Argument:
++ *
++ * Returns : The state of the command
++ *
++ * Description: This does the parsing of the command
++ *
++ * Note: Not all states are allowed on return
++ ********************************************************************/
++static int processor_parse(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ scst_processor_generic_parse(cmd, NULL);
++
++ cmd->retries = SCST_PASSTHROUGH_RETRIES;
++
++ return res;
++}
++
++/********************************************************************
++ * Function: processor_done
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: This is the completion routine for the command,
++ * it is used to extract any necessary information
++ * about a command.
++ ********************************************************************/
++#if 0
++int processor_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->is_send_status and
++ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
++ * therefore change them only if necessary.
++ */
++
++#if 0
++ switch (cmd->cdb[0]) {
++ default:
++ /* It's all good */
++ break;
++ }
++#endif
++
++ TRACE_EXIT();
++ return res;
++}
++#endif
++
++static int __init processor_init(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ processor_devtype.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&processor_devtype);
++ if (res < 0)
++ goto out;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void __exit processor_exit(void)
++{
++ TRACE_ENTRY();
++ scst_unregister_dev_driver(&processor_devtype);
++ TRACE_EXIT();
++ return;
++}
++
++module_init(processor_init);
++module_exit(processor_exit);
++
++MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCSI medium processor (type 3) dev handler for SCST");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_raid.c linux-2.6.36/drivers/scst/dev_handlers/scst_raid.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_raid.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_raid.c
+@@ -0,0 +1,224 @@
++/*
++ * scst_raid.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI raid(controller) (type 0xC) dev handler
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#define LOG_PREFIX "dev_raid"
++
++#include <scsi/scsi_host.h>
++#include <linux/slab.h>
++
++#include <scst/scst.h>
++#include "scst_dev_handler.h"
++
++#define RAID_NAME "dev_raid"
++
++#define RAID_RETRIES 2
++
++static int raid_attach(struct scst_device *);
++/* static void raid_detach(struct scst_device *); */
++static int raid_parse(struct scst_cmd *);
++/* static int raid_done(struct scst_cmd *); */
++
++static struct scst_dev_type raid_devtype = {
++ .name = RAID_NAME,
++ .type = TYPE_RAID,
++ .threads_num = 1,
++ .parse_atomic = 1,
++/* .dev_done_atomic = 1,*/
++ .attach = raid_attach,
++/* .detach = raid_detach,*/
++ .parse = raid_parse,
++/* .dev_done = raid_done,*/
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++/**************************************************************
++ * Function: raid_attach
++ *
++ * Argument:
++ *
++ * Returns : 1 if attached, error code otherwise
++ *
++ * Description:
++ *************************************************************/
++static int raid_attach(struct scst_device *dev)
++{
++ int res, rc;
++ int retries;
++
++ TRACE_ENTRY();
++
++ if (dev->scsi_dev == NULL ||
++ dev->scsi_dev->type != dev->type) {
++ PRINT_ERROR("%s", "SCSI device not define or illegal type");
++ res = -ENODEV;
++ goto out;
++ }
++
++ /*
++ * If the device is offline, don't try to read capacity or any
++ * of the other stuff
++ */
++ if (dev->scsi_dev->sdev_state == SDEV_OFFLINE) {
++ TRACE_DBG("%s", "Device is offline");
++ res = -ENODEV;
++ goto out;
++ }
++
++ retries = SCST_DEV_UA_RETRIES;
++ do {
++ TRACE_DBG("%s", "Doing TEST_UNIT_READY");
++ rc = scsi_test_unit_ready(dev->scsi_dev,
++ SCST_GENERIC_RAID_TIMEOUT, RAID_RETRIES
++ , NULL);
++ TRACE_DBG("TEST_UNIT_READY done: %x", rc);
++ } while ((--retries > 0) && rc);
++
++ if (rc) {
++ PRINT_WARNING("Unit not ready: %x", rc);
++ /* Let's try not to be too smart and continue processing */
++ }
++
++ res = scst_obtain_device_parameters(dev);
++ if (res != 0) {
++ PRINT_ERROR("Failed to obtain control parameters for device "
++ "%s", dev->virt_name);
++ goto out;
++ }
++
++out:
++ TRACE_EXIT();
++ return res;
++}
++
++/************************************************************
++ * Function: raid_detach
++ *
++ * Argument:
++ *
++ * Returns : None
++ *
++ * Description: Called to detach this device type driver
++ ************************************************************/
++#if 0
++void raid_detach(struct scst_device *dev)
++{
++ TRACE_ENTRY();
++
++ TRACE_EXIT();
++ return;
++}
++#endif
++
++/********************************************************************
++ * Function: raid_parse
++ *
++ * Argument:
++ *
++ * Returns : The state of the command
++ *
++ * Description: This does the parsing of the command
++ *
++ * Note: Not all states are allowed on return
++ ********************************************************************/
++static int raid_parse(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ scst_raid_generic_parse(cmd, NULL);
++
++ cmd->retries = SCST_PASSTHROUGH_RETRIES;
++
++ return res;
++}
++
++/********************************************************************
++ * Function: raid_done
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: This is the completion routine for the command,
++ * it is used to extract any necessary information
++ * about a command.
++ ********************************************************************/
++#if 0
++int raid_done(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ /*
++ * SCST sets good defaults for cmd->is_send_status and
++ * cmd->resp_data_len based on cmd->status and cmd->data_direction,
++ * therefore change them only if necessary.
++ */
++
++#if 0
++ switch (cmd->cdb[0]) {
++ default:
++ /* It's all good */
++ break;
++ }
++#endif
++
++ TRACE_EXIT();
++ return res;
++}
++#endif
++
++static int __init raid_init(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ raid_devtype.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&raid_devtype);
++ if (res < 0)
++ goto out;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++}
++
++static void __exit raid_exit(void)
++{
++ TRACE_ENTRY();
++ scst_unregister_dev_driver(&raid_devtype);
++ TRACE_EXIT();
++ return;
++}
++
++module_init(raid_init);
++module_exit(raid_exit);
++
++MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCSI raid(controller) (type 0xC) dev handler for SCST");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/dev_handlers/scst_tape.c linux-2.6.36/drivers/scst/dev_handlers/scst_tape.c
+--- orig/linux-2.6.36/drivers/scst/dev_handlers/scst_tape.c
++++ linux-2.6.36/drivers/scst/dev_handlers/scst_tape.c
+@@ -0,0 +1,432 @@
++/*
++ * scst_tape.c
++ *
++ * Copyright (C) 2004 - 2011 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ * Copyright (C) 2010 - 2011 SCST Ltd.
++ *
++ * SCSI tape (type 1) dev handler
++ * &
++ * SCSI tape (type 1) "performance" device handler (skip all READ and WRITE
++ * operations).
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <scsi/scsi_host.h>
++#include <linux/slab.h>
++
++#define LOG_PREFIX "dev_tape"
++
++#include <scst/scst.h>
++#include "scst_dev_handler.h"
++
++# define TAPE_NAME "dev_tape"
++# define TAPE_PERF_NAME "dev_tape_perf"
++
++#define TAPE_RETRIES 2
++
++#define TAPE_DEF_BLOCK_SIZE 512
++
++/* The fixed bit in READ/WRITE/VERIFY */
++#define SILI_BIT 2
++
++struct tape_params {
++ int block_size;
++};
++
++static int tape_attach(struct scst_device *);
++static void tape_detach(struct scst_device *);
++static int tape_parse(struct scst_cmd *);
++static int tape_done(struct scst_cmd *);
++static int tape_exec(struct scst_cmd *);
++
++static struct scst_dev_type tape_devtype = {
++ .name = TAPE_NAME,
++ .type = TYPE_TAPE,
++ .threads_num = 1,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = tape_attach,
++ .detach = tape_detach,
++ .parse = tape_parse,
++ .dev_done = tape_done,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static struct scst_dev_type tape_devtype_perf = {
++ .name = TAPE_PERF_NAME,
++ .type = TYPE_TAPE,
++ .parse_atomic = 1,
++ .dev_done_atomic = 1,
++ .attach = tape_attach,
++ .detach = tape_detach,
++ .parse = tape_parse,
++ .dev_done = tape_done,
++ .exec = tape_exec,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static int __init init_scst_tape_driver(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ tape_devtype.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&tape_devtype);
++ if (res < 0)
++ goto out;
++
++ tape_devtype_perf.module = THIS_MODULE;
++
++ res = scst_register_dev_driver(&tape_devtype_perf);
++ if (res < 0)
++ goto out_unreg;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unreg:
++ scst_unregister_dev_driver(&tape_devtype);
++ goto out;
++}
++
++static void __exit exit_scst_tape_driver(void)
++{
++ TRACE_ENTRY();
++
++ scst_unregister_dev_driver(&tape_devtype_perf);
++ scst_unregister_dev_driver(&tape_devtype);
++
++ TRACE_EXIT();
++ return;
++}
++
++module_init(init_scst_tape_driver);
++module_exit(exit_scst_tape_driver);
++
++/**************************************************************
++ * Function: tape_attach
++ *
++ * Argument:
++ *
++ * Returns : 1 if attached, error code otherwise
++ *
++ * Description:
++ *************************************************************/
++static int tape_attach(struct scst_device *dev)
++{
++ int res, rc;
++ int retries;
++ struct scsi_mode_data data;
++ const int buffer_size = 512;
++ uint8_t *buffer = NULL;
++ struct tape_params *params;
++
++ TRACE_ENTRY();
++
++ if (dev->scsi_dev == NULL ||
++ dev->scsi_dev->type != dev->type) {
++ PRINT_ERROR("%s", "SCSI device not define or illegal type");
++ res = -ENODEV;
++ goto out;
++ }
++
++ params = kzalloc(sizeof(*params), GFP_KERNEL);
++ if (params == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s",
++ "Unable to allocate struct tape_params");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ params->block_size = TAPE_DEF_BLOCK_SIZE;
++
++ buffer = kmalloc(buffer_size, GFP_KERNEL);
++ if (!buffer) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "Memory allocation failure");
++ res = -ENOMEM;
++ goto out_free_req;
++ }
++
++ retries = SCST_DEV_UA_RETRIES;
++ do {
++ TRACE_DBG("%s", "Doing TEST_UNIT_READY");
++ rc = scsi_test_unit_ready(dev->scsi_dev,
++ SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES
++ , NULL);
++ TRACE_DBG("TEST_UNIT_READY done: %x", rc);
++ } while ((--retries > 0) && rc);
++
++ if (rc) {
++ PRINT_WARNING("Unit not ready: %x", rc);
++ /* Let's try not to be too smart and continue processing */
++ goto obtain;
++ }
++
++ TRACE_DBG("%s", "Doing MODE_SENSE");
++ rc = scsi_mode_sense(dev->scsi_dev,
++ ((dev->scsi_dev->scsi_level <= SCSI_2) ?
++ ((dev->scsi_dev->lun << 5) & 0xe0) : 0),
++ 0 /* Mode Page 0 */,
++ buffer, buffer_size,
++ SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES,
++ &data, NULL);
++ TRACE_DBG("MODE_SENSE done: %x", rc);
++
++ if (rc == 0) {
++ int medium_type, mode, speed, density;
++ if (buffer[3] == 8) {
++ params->block_size = ((buffer[9] << 16) |
++ (buffer[10] << 8) |
++ (buffer[11] << 0));
++ } else
++ params->block_size = TAPE_DEF_BLOCK_SIZE;
++ medium_type = buffer[1];
++ mode = (buffer[2] & 0x70) >> 4;
++ speed = buffer[2] & 0x0f;
++ density = buffer[4];
++ TRACE_DBG("Tape: lun %d. bs %d. type 0x%02x mode 0x%02x "
++ "speed 0x%02x dens 0x%02x", dev->scsi_dev->lun,
++ params->block_size, medium_type, mode, speed, density);
++ } else {
++ PRINT_ERROR("MODE_SENSE failed: %x", rc);
++ res = -ENODEV;
++ goto out_free_buf;
++ }
++
++obtain:
++ res = scst_obtain_device_parameters(dev);
++ if (res != 0) {
++ PRINT_ERROR("Failed to obtain control parameters for device "
++ "%s", dev->virt_name);
++ goto out_free_buf;
++ }
++
++out_free_buf:
++ kfree(buffer);
++
++out_free_req:
++ if (res == 0)
++ dev->dh_priv = params;
++ else
++ kfree(params);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/************************************************************
++ * Function: tape_detach
++ *
++ * Argument:
++ *
++ * Returns : None
++ *
++ * Description: Called to detach this device type driver
++ ************************************************************/
++static void tape_detach(struct scst_device *dev)
++{
++ struct tape_params *params =
++ (struct tape_params *)dev->dh_priv;
++
++ TRACE_ENTRY();
++
++ kfree(params);
++ dev->dh_priv = NULL;
++
++ TRACE_EXIT();
++ return;
++}
++
++static int tape_get_block_size(struct scst_cmd *cmd)
++{
++ struct tape_params *params = (struct tape_params *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be called,
++ * when there are existing commands.
++ */
++ return params->block_size;
++}
++
++/********************************************************************
++ * Function: tape_parse
++ *
++ * Argument:
++ *
++ * Returns : The state of the command
++ *
++ * Description: This does the parsing of the command
++ *
++ * Note: Not all states are allowed on return
++ ********************************************************************/
++static int tape_parse(struct scst_cmd *cmd)
++{
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ scst_tape_generic_parse(cmd, tape_get_block_size);
++
++ cmd->retries = SCST_PASSTHROUGH_RETRIES;
++
++ return res;
++}
++
++static void tape_set_block_size(struct scst_cmd *cmd, int block_size)
++{
++ struct tape_params *params = (struct tape_params *)cmd->dev->dh_priv;
++ /*
++ * No need for locks here, since *_detach() can not be called, when
++ * there are existing commands.
++ */
++ params->block_size = block_size;
++ return;
++}
++
++/********************************************************************
++ * Function: tape_done
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: This is the completion routine for the command,
++ * it is used to extract any necessary information
++ * about a command.
++ ********************************************************************/
++static int tape_done(struct scst_cmd *cmd)
++{
++ int opcode = cmd->cdb[0];
++ int status = cmd->status;
++ int res = SCST_CMD_STATE_DEFAULT;
++
++ TRACE_ENTRY();
++
++ if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET))
++ res = scst_tape_generic_dev_done(cmd, tape_set_block_size);
++ else if ((status == SAM_STAT_CHECK_CONDITION) &&
++ SCST_SENSE_VALID(cmd->sense)) {
++ struct tape_params *params;
++
++ TRACE_DBG("Extended sense %x", cmd->sense[0] & 0x7F);
++
++ if ((cmd->sense[0] & 0x7F) != 0x70) {
++ PRINT_ERROR("Sense format 0x%x is not supported",
++ cmd->sense[0] & 0x7F);
++ scst_set_cmd_error(cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ goto out;
++ }
++
++ if (opcode == READ_6 && !(cmd->cdb[1] & SILI_BIT) &&
++ (cmd->sense[2] & 0xe0)) {
++ /* EOF, EOM, or ILI */
++ int TransferLength, Residue = 0;
++ if ((cmd->sense[2] & 0x0f) == BLANK_CHECK)
++ /* No need for EOM in this case */
++ cmd->sense[2] &= 0xcf;
++ TransferLength = ((cmd->cdb[2] << 16) |
++ (cmd->cdb[3] << 8) | cmd->cdb[4]);
++ /* Compute the residual count */
++ if ((cmd->sense[0] & 0x80) != 0) {
++ Residue = ((cmd->sense[3] << 24) |
++ (cmd->sense[4] << 16) |
++ (cmd->sense[5] << 8) |
++ cmd->sense[6]);
++ }
++ TRACE_DBG("Checking the sense key "
++ "sn[2]=%x cmd->cdb[0,1]=%x,%x TransLen/Resid"
++ " %d/%d", (int)cmd->sense[2], cmd->cdb[0],
++ cmd->cdb[1], TransferLength, Residue);
++ if (TransferLength > Residue) {
++ int resp_data_len = TransferLength - Residue;
++ if (cmd->cdb[1] & SCST_TRANSFER_LEN_TYPE_FIXED) {
++ /*
++ * No need for locks here, since
++ * *_detach() can not be called, when
++ * there are existing commands.
++ */
++ params = (struct tape_params *)
++ cmd->dev->dh_priv;
++ resp_data_len *= params->block_size;
++ }
++ scst_set_resp_data_len(cmd, resp_data_len);
++ }
++ }
++ }
++
++out:
++ TRACE_DBG("cmd->is_send_status=%x, cmd->resp_data_len=%d, "
++ "res=%d", cmd->is_send_status, cmd->resp_data_len, res);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/********************************************************************
++ * Function: tape_exec
++ *
++ * Argument:
++ *
++ * Returns :
++ *
++ * Description: Make SCST do nothing for data READs and WRITES.
++ * Intended for raw line performance testing
++ ********************************************************************/
++static int tape_exec(struct scst_cmd *cmd)
++{
++ int res = SCST_EXEC_NOT_COMPLETED, rc;
++ int opcode = cmd->cdb[0];
++
++ TRACE_ENTRY();
++
++ rc = scst_check_local_events(cmd);
++ if (unlikely(rc != 0))
++ goto out_done;
++
++ cmd->status = 0;
++ cmd->msg_status = 0;
++ cmd->host_status = DID_OK;
++ cmd->driver_status = 0;
++
++ switch (opcode) {
++ case WRITE_6:
++ case READ_6:
++ cmd->completed = 1;
++ goto out_done;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_done:
++ res = SCST_EXEC_COMPLETED;
++ cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
++ goto out;
++}
++
++MODULE_AUTHOR("Vladislav Bolkhovitin & Leonid Stoljar");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCSI tape (type 1) dev handler for SCST");
++MODULE_VERSION(SCST_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/fcst/Makefile linux-2.6.36/drivers/scst/fcst/Makefile
+--- orig/linux-2.6.36/drivers/scst/fcst/Makefile
++++ linux-2.6.36/drivers/scst/fcst/Makefile
+@@ -0,0 +1,7 @@
++obj-$(CONFIG_FCST) += fcst.o
++
++fcst-objs := \
++ ft_cmd.o \
++ ft_io.o \
++ ft_scst.o \
++ ft_sess.o
+diff -uprN orig/linux-2.6.36/drivers/scst/fcst/Kconfig linux-2.6.36/drivers/scst/fcst/Kconfig
+--- orig/linux-2.6.36/drivers/scst/fcst/Kconfig
++++ linux-2.6.36/drivers/scst/fcst/Kconfig
+@@ -0,0 +1,5 @@
++config FCST
++ tristate "SCST target module for Fibre Channel using libfc"
++ depends on LIBFC && SCST
++ ---help---
++ Supports using libfc HBAs as target adapters with SCST
+diff -uprN orig/linux-2.6.36/drivers/scst/fcst/fcst.h linux-2.6.36/drivers/scst/fcst/fcst.h
+--- orig/linux-2.6.36/drivers/scst/fcst/fcst.h
++++ linux-2.6.36/drivers/scst/fcst/fcst.h
+@@ -0,0 +1,151 @@
++/*
++ * Copyright (c) 2010 Cisco Systems, Inc.
++ *
++ * This program is free software; you may redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ * $Id$
++ */
++#ifndef __SCSI_FCST_H__
++#define __SCSI_FCST_H__
++
++#include <scst/scst.h>
++
++#define FT_VERSION "0.3"
++#define FT_MODULE "fcst"
++
++#define FT_MAX_HW_PENDING_TIME 20 /* max I/O time in seconds */
++
++/*
++ * Debug options.
++ */
++#define FT_DEBUG_CONF 0x01 /* configuration messages */
++#define FT_DEBUG_SESS 0x02 /* session messages */
++#define FT_DEBUG_IO 0x04 /* I/O operations */
++
++extern unsigned int ft_debug_logging; /* debug options */
++
++#define FT_ERR(fmt, args...) \
++ printk(KERN_ERR FT_MODULE ": %s: " fmt, __func__, ##args)
++
++#define FT_DEBUG(mask, fmt, args...) \
++ do { \
++ if (ft_debug_logging & (mask)) \
++ printk(KERN_INFO FT_MODULE ": %s: " fmt, \
++ __func__, ##args); \
++ } while (0)
++
++#define FT_CONF_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_CONF, fmt, ##args)
++#define FT_SESS_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_SESS, fmt, ##args)
++#define FT_IO_DBG(fmt, args...) FT_DEBUG(FT_DEBUG_IO, fmt, ##args)
++
++#define FT_NAMELEN 32 /* length of ASCI WWPNs including pad */
++
++/*
++ * Session (remote port).
++ */
++struct ft_sess {
++ u32 port_id; /* for hash lookup use only */
++ u32 params;
++ u16 max_payload; /* max transmitted payload size */
++ u32 max_lso_payload; /* max offloaded payload size */
++ u64 port_name; /* port name for transport ID */
++ struct ft_tport *tport;
++ struct hlist_node hash; /* linkage in ft_sess_hash table */
++ struct rcu_head rcu;
++ struct kref kref; /* ref for hash and outstanding I/Os */
++ struct scst_session *scst_sess;
++};
++
++/*
++ * Hash table of sessions per local port.
++ * Hash lookup by remote port FC_ID.
++ */
++#define FT_SESS_HASH_BITS 6
++#define FT_SESS_HASH_SIZE (1 << FT_SESS_HASH_BITS)
++
++/*
++ * Per local port data.
++ * This is created when the first session logs into the local port.
++ * Deleted when tpg is deleted or last session is logged off.
++ */
++struct ft_tport {
++ u32 sess_count; /* number of sessions in hash */
++ u8 enabled:1;
++ struct rcu_head rcu;
++ struct hlist_head hash[FT_SESS_HASH_SIZE]; /* list of sessions */
++ struct fc_lport *lport;
++ struct scst_tgt *tgt;
++};
++
++/*
++ * Commands
++ */
++struct ft_cmd {
++ int serial; /* order received, for debugging */
++ struct fc_seq *seq; /* sequence in exchange mgr */
++ struct fc_frame *req_frame; /* original request frame */
++ u32 write_data_len; /* data received from initiator */
++ u32 read_data_len; /* data sent to initiator */
++ u32 xfer_rdy_len; /* max xfer ready offset */
++ u32 max_lso_payload; /* max offloaded (LSO) data payload */
++ u16 max_payload; /* max transmitted data payload */
++ struct scst_cmd *scst_cmd;
++};
++
++extern struct list_head ft_lport_list;
++extern struct mutex ft_lport_lock;
++extern struct scst_tgt_template ft_scst_template;
++
++/*
++ * libfc interface.
++ */
++int ft_prli(struct fc_rport_priv *, u32 spp_len,
++ const struct fc_els_spp *, struct fc_els_spp *);
++void ft_prlo(struct fc_rport_priv *);
++void ft_recv(struct fc_lport *, struct fc_seq *, struct fc_frame *);
++
++/*
++ * SCST interface.
++ */
++int ft_send_response(struct scst_cmd *);
++int ft_send_xfer_rdy(struct scst_cmd *);
++void ft_cmd_timeout(struct scst_cmd *);
++void ft_cmd_free(struct scst_cmd *);
++void ft_cmd_tm_done(struct scst_mgmt_cmd *);
++int ft_tgt_detect(struct scst_tgt_template *);
++int ft_tgt_release(struct scst_tgt *);
++int ft_tgt_enable(struct scst_tgt *, bool);
++bool ft_tgt_enabled(struct scst_tgt *);
++int ft_report_aen(struct scst_aen *);
++int ft_get_transport_id(struct scst_session *, uint8_t **);
++
++/*
++ * Session interface.
++ */
++int ft_lport_notify(struct notifier_block *, unsigned long, void *);
++void ft_lport_add(struct fc_lport *, void *);
++void ft_lport_del(struct fc_lport *, void *);
++
++/*
++ * other internal functions.
++ */
++int ft_thread(void *);
++void ft_recv_req(struct ft_sess *, struct fc_seq *, struct fc_frame *);
++void ft_recv_write_data(struct scst_cmd *, struct fc_frame *);
++int ft_send_read_data(struct scst_cmd *);
++struct ft_tpg *ft_lport_find_tpg(struct fc_lport *);
++struct ft_node_acl *ft_acl_get(struct ft_tpg *, struct fc_rport_priv *);
++void ft_cmd_dump(struct scst_cmd *, const char *);
++
++#endif /* __SCSI_FCST_H__ */
+diff -uprN orig/linux-2.6.36/drivers/scst/fcst/ft_cmd.c linux-2.6.36/drivers/scst/fcst/ft_cmd.c
+--- orig/linux-2.6.36/drivers/scst/fcst/ft_cmd.c
++++ linux-2.6.36/drivers/scst/fcst/ft_cmd.c
+@@ -0,0 +1,686 @@
++/*
++ * Copyright (c) 2010 Cisco Systems, Inc.
++ *
++ * This program is free software; you may redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <scsi/libfc.h>
++#include <scsi/fc_encode.h>
++#include "fcst.h"
++
++/*
++ * Append string to buffer safely.
++ * Also prepends a space if there's already something the buf.
++ */
++static void ft_cmd_flag(char *buf, size_t len, const char *desc)
++{
++ if (buf[0])
++ strlcat(buf, " ", len);
++ strlcat(buf, desc, len);
++}
++
++/*
++ * Debug: dump command.
++ */
++void ft_cmd_dump(struct scst_cmd *cmd, const char *caller)
++{
++ static atomic_t serial;
++ struct ft_cmd *fcmd;
++ struct fc_exch *ep;
++ char prefix[30];
++ char buf[150];
++
++ if (!(ft_debug_logging & FT_DEBUG_IO))
++ return;
++
++ fcmd = scst_cmd_get_tgt_priv(cmd);
++ ep = fc_seq_exch(fcmd->seq);
++ snprintf(prefix, sizeof(prefix), FT_MODULE ": cmd %2x",
++ atomic_inc_return(&serial) & 0xff);
++
++ printk(KERN_INFO "%s %s oid %x oxid %x resp_len %u\n",
++ prefix, caller, ep->oid, ep->oxid,
++ scst_cmd_get_resp_data_len(cmd));
++ printk(KERN_INFO "%s scst_cmd %p wlen %u rlen %u\n",
++ prefix, cmd, fcmd->write_data_len, fcmd->read_data_len);
++ printk(KERN_INFO "%s exp_dir %x exp_xfer_len %d exp_in_len %d\n",
++ prefix, cmd->expected_data_direction,
++ cmd->expected_transfer_len, cmd->expected_out_transfer_len);
++ printk(KERN_INFO "%s dir %x data_len %d bufflen %d out_bufflen %d\n",
++ prefix, cmd->data_direction, cmd->data_len,
++ cmd->bufflen, cmd->out_bufflen);
++ printk(KERN_INFO "%s sg_cnt reg %d in %d tgt %d tgt_in %d\n",
++ prefix, cmd->sg_cnt, cmd->out_sg_cnt,
++ cmd->tgt_sg_cnt, cmd->tgt_out_sg_cnt);
++
++ buf[0] = '\0';
++ if (cmd->sent_for_exec)
++ ft_cmd_flag(buf, sizeof(buf), "sent");
++ if (cmd->completed)
++ ft_cmd_flag(buf, sizeof(buf), "comp");
++ if (cmd->ua_ignore)
++ ft_cmd_flag(buf, sizeof(buf), "ua_ign");
++ if (cmd->atomic)
++ ft_cmd_flag(buf, sizeof(buf), "atom");
++ if (cmd->double_ua_possible)
++ ft_cmd_flag(buf, sizeof(buf), "dbl_ua_poss");
++ if (cmd->is_send_status)
++ ft_cmd_flag(buf, sizeof(buf), "send_stat");
++ if (cmd->retry)
++ ft_cmd_flag(buf, sizeof(buf), "retry");
++ if (cmd->internal)
++ ft_cmd_flag(buf, sizeof(buf), "internal");
++ if (cmd->unblock_dev)
++ ft_cmd_flag(buf, sizeof(buf), "unblock_dev");
++ if (cmd->cmd_hw_pending)
++ ft_cmd_flag(buf, sizeof(buf), "hw_pend");
++ if (cmd->tgt_need_alloc_data_buf)
++ ft_cmd_flag(buf, sizeof(buf), "tgt_need_alloc");
++ if (cmd->tgt_data_buf_alloced)
++ ft_cmd_flag(buf, sizeof(buf), "tgt_alloced");
++ if (cmd->dh_data_buf_alloced)
++ ft_cmd_flag(buf, sizeof(buf), "dh_alloced");
++ if (cmd->expected_values_set)
++ ft_cmd_flag(buf, sizeof(buf), "exp_val");
++ if (cmd->sg_buff_modified)
++ ft_cmd_flag(buf, sizeof(buf), "sg_buf_mod");
++ if (cmd->preprocessing_only)
++ ft_cmd_flag(buf, sizeof(buf), "pre_only");
++ if (cmd->sn_set)
++ ft_cmd_flag(buf, sizeof(buf), "sn_set");
++ if (cmd->hq_cmd_inced)
++ ft_cmd_flag(buf, sizeof(buf), "hq_cmd_inc");
++ if (cmd->set_sn_on_restart_cmd)
++ ft_cmd_flag(buf, sizeof(buf), "set_sn_on_restart");
++ if (cmd->no_sgv)
++ ft_cmd_flag(buf, sizeof(buf), "no_sgv");
++ if (cmd->may_need_dma_sync)
++ ft_cmd_flag(buf, sizeof(buf), "dma_sync");
++ if (cmd->out_of_sn)
++ ft_cmd_flag(buf, sizeof(buf), "oo_sn");
++ if (cmd->inc_expected_sn_on_done)
++ ft_cmd_flag(buf, sizeof(buf), "inc_sn_exp");
++ if (cmd->done)
++ ft_cmd_flag(buf, sizeof(buf), "done");
++ if (cmd->finished)
++ ft_cmd_flag(buf, sizeof(buf), "fin");
++
++ printk(KERN_INFO "%s flags %s\n", prefix, buf);
++ printk(KERN_INFO "%s lun %lld sn %d tag %lld cmd_flags %lx\n",
++ prefix, cmd->lun, cmd->sn, cmd->tag, cmd->cmd_flags);
++ printk(KERN_INFO "%s tgt_sn %d op_flags %x op %s\n",
++ prefix, cmd->tgt_sn, cmd->op_flags, cmd->op_name);
++ printk(KERN_INFO "%s status %x msg_status %x "
++ "host_status %x driver_status %x\n",
++ prefix, cmd->status, cmd->msg_status,
++ cmd->host_status, cmd->driver_status);
++ printk(KERN_INFO "%s cdb_len %d ext_cdb_len %u\n",
++ prefix, cmd->cdb_len, cmd->ext_cdb_len);
++ snprintf(buf, sizeof(buf), "%s cdb ", prefix);
++ print_hex_dump(KERN_INFO, buf, DUMP_PREFIX_NONE,
++ 16, 4, cmd->cdb, SCST_MAX_CDB_SIZE, 0);
++}
++
++/*
++ * Debug: dump mgmt command.
++ */
++static void ft_cmd_tm_dump(struct scst_mgmt_cmd *mcmd, const char *caller)
++{
++ struct ft_cmd *fcmd;
++ struct fc_exch *ep;
++ char prefix[30];
++ char buf[150];
++
++ if (!(ft_debug_logging & FT_DEBUG_IO))
++ return;
++ fcmd = scst_mgmt_cmd_get_tgt_priv(mcmd);
++ ep = fc_seq_exch(fcmd->seq);
++
++ snprintf(prefix, sizeof(prefix), FT_MODULE ": mcmd");
++
++ printk(KERN_INFO "%s %s oid %x oxid %x lun %lld\n",
++ prefix, caller, ep->oid, ep->oxid,
++ (unsigned long long)mcmd->lun);
++ printk(KERN_INFO "%s state %d fn %d fin_wait %d done_wait %d comp %d\n",
++ prefix, mcmd->state, mcmd->fn,
++ mcmd->cmd_finish_wait_count, mcmd->cmd_done_wait_count,
++ mcmd->completed_cmd_count);
++ buf[0] = '\0';
++ if (mcmd->needs_unblocking)
++ ft_cmd_flag(buf, sizeof(buf), "needs_unblock");
++ if (mcmd->lun_set)
++ ft_cmd_flag(buf, sizeof(buf), "lun_set");
++ if (mcmd->cmd_sn_set)
++ ft_cmd_flag(buf, sizeof(buf), "cmd_sn_set");
++ printk(KERN_INFO "%s flags %s\n", prefix, buf);
++ if (mcmd->cmd_to_abort)
++ ft_cmd_dump(mcmd->cmd_to_abort, caller);
++}
++
++/*
++ * Free command.
++ */
++void ft_cmd_free(struct scst_cmd *cmd)
++{
++ struct ft_cmd *fcmd;
++
++ fcmd = scst_cmd_get_tgt_priv(cmd);
++ if (fcmd) {
++ scst_cmd_set_tgt_priv(cmd, NULL);
++ fc_frame_free(fcmd->req_frame);
++ kfree(fcmd);
++ }
++}
++
++/*
++ * Send response, after data if applicable.
++ */
++int ft_send_response(struct scst_cmd *cmd)
++{
++ struct ft_cmd *fcmd;
++ struct fc_frame *fp;
++ struct fcp_resp_with_ext *fcp;
++ struct fc_lport *lport;
++ struct fc_exch *ep;
++ unsigned int slen;
++ size_t len;
++ int resid = 0;
++ int bi_resid = 0;
++ int error;
++ int dir;
++ u32 status;
++
++ ft_cmd_dump(cmd, __func__);
++ fcmd = scst_cmd_get_tgt_priv(cmd);
++ ep = fc_seq_exch(fcmd->seq);
++ lport = ep->lp;
++
++ if (scst_cmd_aborted(cmd)) {
++ FT_IO_DBG("cmd aborted did %x oxid %x\n", ep->did, ep->oxid);
++ scst_set_delivery_status(cmd, SCST_CMD_DELIVERY_ABORTED);
++ goto done;
++ }
++
++ if (!scst_cmd_get_is_send_status(cmd)) {
++ FT_IO_DBG("send status not set. feature not implemented\n");
++ return SCST_TGT_RES_FATAL_ERROR;
++ }
++
++ status = scst_cmd_get_status(cmd);
++ dir = scst_cmd_get_data_direction(cmd);
++
++ slen = scst_cmd_get_sense_buffer_len(cmd);
++ len = sizeof(*fcp) + slen;
++
++ /*
++ * Send read data and set underflow/overflow residual count.
++ * For bi-directional comands, the bi_resid is for the read direction.
++ */
++ if (dir & SCST_DATA_WRITE)
++ resid = (signed)scst_cmd_get_bufflen(cmd) -
++ fcmd->write_data_len;
++ if (dir & SCST_DATA_READ) {
++ error = ft_send_read_data(cmd);
++ if (error) {
++ FT_ERR("ft_send_read_data returned %d\n", error);
++ return error;
++ }
++
++ if (dir == SCST_DATA_BIDI) {
++ bi_resid = (signed)scst_cmd_get_out_bufflen(cmd) -
++ scst_cmd_get_resp_data_len(cmd);
++ if (bi_resid)
++ len += sizeof(__be32);
++ } else
++ resid = (signed)scst_cmd_get_bufflen(cmd) -
++ scst_cmd_get_resp_data_len(cmd);
++ }
++
++ fp = fc_frame_alloc(lport, len);
++ if (!fp)
++ return SCST_TGT_RES_QUEUE_FULL;
++
++ fcp = fc_frame_payload_get(fp, len);
++ memset(fcp, 0, sizeof(*fcp));
++ fcp->resp.fr_status = status;
++
++ if (slen) {
++ fcp->resp.fr_flags |= FCP_SNS_LEN_VAL;
++ fcp->ext.fr_sns_len = htonl(slen);
++ memcpy(fcp + 1, scst_cmd_get_sense_buffer(cmd), slen);
++ }
++ if (bi_resid) {
++ if (bi_resid < 0) {
++ fcp->resp.fr_flags |= FCP_BIDI_READ_OVER;
++ bi_resid = -bi_resid;
++ } else
++ fcp->resp.fr_flags |= FCP_BIDI_READ_UNDER;
++ *(__be32 *)((u8 *)(fcp + 1) + slen) = htonl(bi_resid);
++ }
++ if (resid) {
++ if (resid < 0) {
++ resid = -resid;
++ fcp->resp.fr_flags |= FCP_RESID_OVER;
++ } else
++ fcp->resp.fr_flags |= FCP_RESID_UNDER;
++ fcp->ext.fr_resid = htonl(resid);
++ }
++ FT_IO_DBG("response did %x oxid %x\n", ep->did, ep->oxid);
++
++ /*
++ * Send response.
++ */
++ fcmd->seq = lport->tt.seq_start_next(fcmd->seq);
++ fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP,
++ FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0);
++
++ lport->tt.seq_send(lport, fcmd->seq, fp);
++done:
++ lport->tt.exch_done(fcmd->seq);
++ scst_tgt_cmd_done(cmd, SCST_CONTEXT_SAME);
++ return SCST_TGT_RES_SUCCESS;
++}
++
++/*
++ * FC sequence response handler for follow-on sequences (data) and aborts.
++ */
++static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
++{
++ struct scst_cmd *cmd = arg;
++ struct fc_frame_header *fh;
++
++ /*
++ * If an error is being reported, it must be FC_EX_CLOSED.
++ * Timeouts don't occur on incoming requests, and there are
++ * currently no other errors.
++ * The PRLO handler will be also called by libfc to delete
++ * the session and all pending commands, so we ignore this response.
++ */
++ if (IS_ERR(fp)) {
++ FT_IO_DBG("exchange error %ld - not handled\n", -PTR_ERR(fp));
++ return;
++ }
++
++ fh = fc_frame_header_get(fp);
++ switch (fh->fh_r_ctl) {
++ case FC_RCTL_DD_SOL_DATA: /* write data */
++ ft_recv_write_data(cmd, fp);
++ break;
++ case FC_RCTL_DD_UNSOL_CTL: /* command */
++ case FC_RCTL_DD_SOL_CTL: /* transfer ready */
++ case FC_RCTL_DD_DATA_DESC: /* transfer ready */
++ default:
++ printk(KERN_INFO "%s: unhandled frame r_ctl %x\n",
++ __func__, fh->fh_r_ctl);
++ fc_frame_free(fp);
++ break;
++ }
++}
++
++/*
++ * Command timeout.
++ * SCST calls this when the command has taken too long in the device handler.
++ */
++void ft_cmd_timeout(struct scst_cmd *cmd)
++{
++ FT_IO_DBG("timeout not implemented\n"); /* XXX TBD */
++}
++
++/*
++ * Send TX_RDY (transfer ready).
++ */
++static int ft_send_xfer_rdy_off(struct scst_cmd *cmd, u32 offset, u32 len)
++{
++ struct ft_cmd *fcmd;
++ struct fc_frame *fp;
++ struct fcp_txrdy *txrdy;
++ struct fc_lport *lport;
++ struct fc_exch *ep;
++
++ fcmd = scst_cmd_get_tgt_priv(cmd);
++ if (fcmd->xfer_rdy_len < len + offset)
++ fcmd->xfer_rdy_len = len + offset;
++
++ ep = fc_seq_exch(fcmd->seq);
++ lport = ep->lp;
++ fp = fc_frame_alloc(lport, sizeof(*txrdy));
++ if (!fp)
++ return SCST_TGT_RES_QUEUE_FULL;
++
++ txrdy = fc_frame_payload_get(fp, sizeof(*txrdy));
++ memset(txrdy, 0, sizeof(*txrdy));
++ txrdy->ft_data_ro = htonl(offset);
++ txrdy->ft_burst_len = htonl(len);
++
++ fcmd->seq = lport->tt.seq_start_next(fcmd->seq);
++ fc_fill_fc_hdr(fp, FC_RCTL_DD_DATA_DESC, ep->did, ep->sid, FC_TYPE_FCP,
++ FC_FC_EX_CTX | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
++ lport->tt.seq_send(lport, fcmd->seq, fp);
++ return SCST_TGT_RES_SUCCESS;
++}
++
++/*
++ * Send TX_RDY (transfer ready).
++ */
++int ft_send_xfer_rdy(struct scst_cmd *cmd)
++{
++ return ft_send_xfer_rdy_off(cmd, 0, scst_cmd_get_bufflen(cmd));
++}
++
++/*
++ * Send a FCP response including SCSI status and optional FCP rsp_code.
++ * status is SAM_STAT_GOOD (zero) if code is valid.
++ * This is used in error cases, such as allocation failures.
++ */
++static void ft_send_resp_status(struct fc_seq *sp, u32 status,
++ enum fcp_resp_rsp_codes code)
++{
++ struct fc_frame *fp;
++ size_t len;
++ struct fcp_resp_with_ext *fcp;
++ struct fcp_resp_rsp_info *info;
++ struct fc_lport *lport;
++ struct fc_exch *ep;
++
++ ep = fc_seq_exch(sp);
++
++ FT_IO_DBG("FCP error response: did %x oxid %x status %x code %x\n",
++ ep->did, ep->oxid, status, code);
++ lport = ep->lp;
++ len = sizeof(*fcp);
++ if (status == SAM_STAT_GOOD)
++ len += sizeof(*info);
++ fp = fc_frame_alloc(lport, len);
++ if (!fp)
++ goto out;
++ fcp = fc_frame_payload_get(fp, len);
++ memset(fcp, 0, len);
++ fcp->resp.fr_status = status;
++ if (status == SAM_STAT_GOOD) {
++ fcp->ext.fr_rsp_len = htonl(sizeof(*info));
++ fcp->resp.fr_flags |= FCP_RSP_LEN_VAL;
++ info = (struct fcp_resp_rsp_info *)(fcp + 1);
++ info->rsp_code = code;
++ }
++
++ sp = lport->tt.seq_start_next(sp);
++ fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP,
++ FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0);
++
++ lport->tt.seq_send(lport, sp, fp);
++out:
++ lport->tt.exch_done(sp);
++}
++
++/*
++ * Send error or task management response.
++ * Always frees the fcmd and associated state.
++ */
++static void ft_send_resp_code(struct ft_cmd *fcmd, enum fcp_resp_rsp_codes code)
++{
++ ft_send_resp_status(fcmd->seq, SAM_STAT_GOOD, code);
++ fc_frame_free(fcmd->req_frame);
++ kfree(fcmd);
++}
++
++void ft_cmd_tm_done(struct scst_mgmt_cmd *mcmd)
++{
++ struct ft_cmd *fcmd;
++ enum fcp_resp_rsp_codes code;
++
++ ft_cmd_tm_dump(mcmd, __func__);
++ fcmd = scst_mgmt_cmd_get_tgt_priv(mcmd);
++ switch (scst_mgmt_cmd_get_status(mcmd)) {
++ case SCST_MGMT_STATUS_SUCCESS:
++ code = FCP_TMF_CMPL;
++ break;
++ case SCST_MGMT_STATUS_REJECTED:
++ code = FCP_TMF_REJECTED;
++ break;
++ case SCST_MGMT_STATUS_LUN_NOT_EXIST:
++ code = FCP_TMF_INVALID_LUN;
++ break;
++ case SCST_MGMT_STATUS_TASK_NOT_EXIST:
++ case SCST_MGMT_STATUS_FN_NOT_SUPPORTED:
++ case SCST_MGMT_STATUS_FAILED:
++ default:
++ code = FCP_TMF_FAILED;
++ break;
++ }
++ FT_IO_DBG("tm cmd done fn %d code %d\n", mcmd->fn, code);
++ ft_send_resp_code(fcmd, code);
++}
++
++/*
++ * Handle an incoming FCP task management command frame.
++ * Note that this may be called directly from the softirq context.
++ */
++static void ft_recv_tm(struct scst_session *scst_sess,
++ struct ft_cmd *fcmd, struct fcp_cmnd *fcp)
++{
++ struct scst_rx_mgmt_params params;
++ int ret;
++
++ memset(&params, 0, sizeof(params));
++ params.lun = fcp->fc_lun;
++ params.lun_len = sizeof(fcp->fc_lun);
++ params.lun_set = 1;
++ params.atomic = SCST_ATOMIC;
++ params.tgt_priv = fcmd;
++
++ switch (fcp->fc_tm_flags) {
++ case FCP_TMF_LUN_RESET:
++ params.fn = SCST_LUN_RESET;
++ break;
++ case FCP_TMF_TGT_RESET:
++ params.fn = SCST_TARGET_RESET;
++ params.lun_set = 0;
++ break;
++ case FCP_TMF_CLR_TASK_SET:
++ params.fn = SCST_CLEAR_TASK_SET;
++ break;
++ case FCP_TMF_ABT_TASK_SET:
++ params.fn = SCST_ABORT_TASK_SET;
++ break;
++ case FCP_TMF_CLR_ACA:
++ params.fn = SCST_CLEAR_ACA;
++ break;
++ default:
++ /*
++ * FCP4r01 indicates having a combination of
++ * tm_flags set is invalid.
++ */
++ FT_IO_DBG("invalid FCP tm_flags %x\n", fcp->fc_tm_flags);
++ ft_send_resp_code(fcmd, FCP_CMND_FIELDS_INVALID);
++ return;
++ }
++ FT_IO_DBG("submit tm cmd fn %d\n", params.fn);
++ ret = scst_rx_mgmt_fn(scst_sess, &params);
++ FT_IO_DBG("scst_rx_mgmt_fn ret %d\n", ret);
++ if (ret)
++ ft_send_resp_code(fcmd, FCP_TMF_FAILED);
++}
++
++/*
++ * Handle an incoming FCP command frame.
++ * Note that this may be called directly from the softirq context.
++ */
++static void ft_recv_cmd(struct ft_sess *sess, struct fc_seq *sp,
++ struct fc_frame *fp)
++{
++ static atomic_t serial;
++ struct scst_cmd *cmd;
++ struct ft_cmd *fcmd;
++ struct fcp_cmnd *fcp;
++ struct fc_lport *lport;
++ int data_dir;
++ u32 data_len;
++ int cdb_len;
++
++ lport = fc_seq_exch(sp)->lp;
++ fcmd = kzalloc(sizeof(*fcmd), GFP_ATOMIC);
++ if (!fcmd)
++ goto busy;
++ fcmd->serial = atomic_inc_return(&serial); /* debug only */
++ fcmd->seq = sp;
++ fcmd->max_payload = sess->max_payload;
++ fcmd->max_lso_payload = sess->max_lso_payload;
++ fcmd->req_frame = fp;
++
++ fcp = fc_frame_payload_get(fp, sizeof(*fcp));
++ if (!fcp)
++ goto err;
++ if (fcp->fc_tm_flags) {
++ ft_recv_tm(sess->scst_sess, fcmd, fcp);
++ return;
++ }
++
++ /*
++ * re-check length including specified CDB length.
++ * data_len is just after the CDB.
++ */
++ cdb_len = fcp->fc_flags & FCP_CFL_LEN_MASK;
++ fcp = fc_frame_payload_get(fp, sizeof(*fcp) + cdb_len);
++ if (!fcp)
++ goto err;
++ cdb_len += sizeof(fcp->fc_cdb);
++ data_len = ntohl(*(__be32 *)(fcp->fc_cdb + cdb_len));
++
++ cmd = scst_rx_cmd(sess->scst_sess, fcp->fc_lun, sizeof(fcp->fc_lun),
++ fcp->fc_cdb, cdb_len, SCST_ATOMIC);
++ if (!cmd) {
++ kfree(fcmd);
++ goto busy;
++ }
++ fcmd->scst_cmd = cmd;
++ scst_cmd_set_tgt_priv(cmd, fcmd);
++
++ switch (fcp->fc_flags & (FCP_CFL_RDDATA | FCP_CFL_WRDATA)) {
++ case 0:
++ data_dir = SCST_DATA_NONE;
++ break;
++ case FCP_CFL_RDDATA:
++ data_dir = SCST_DATA_READ;
++ break;
++ case FCP_CFL_WRDATA:
++ data_dir = SCST_DATA_WRITE;
++ break;
++ case FCP_CFL_RDDATA | FCP_CFL_WRDATA:
++ data_dir = SCST_DATA_BIDI;
++ break;
++ }
++ scst_cmd_set_expected(cmd, data_dir, data_len);
++
++ switch (fcp->fc_pri_ta & FCP_PTA_MASK) {
++ case FCP_PTA_SIMPLE:
++ scst_cmd_set_queue_type(cmd, SCST_CMD_QUEUE_SIMPLE);
++ break;
++ case FCP_PTA_HEADQ:
++ scst_cmd_set_queue_type(cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
++ break;
++ case FCP_PTA_ACA:
++ scst_cmd_set_queue_type(cmd, SCST_CMD_QUEUE_ACA);
++ break;
++ case FCP_PTA_ORDERED:
++ default:
++ scst_cmd_set_queue_type(cmd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ }
++
++ lport->tt.seq_set_resp(sp, ft_recv_seq, cmd);
++ scst_cmd_init_done(cmd, SCST_CONTEXT_THREAD);
++ return;
++
++err:
++ ft_send_resp_code(fcmd, FCP_CMND_FIELDS_INVALID);
++ return;
++
++busy:
++ FT_IO_DBG("cmd allocation failure - sending BUSY\n");
++ ft_send_resp_status(sp, SAM_STAT_BUSY, 0);
++ fc_frame_free(fp);
++}
++
++/*
++ * Send FCP ELS-4 Reject.
++ */
++static void ft_cmd_ls_rjt(struct fc_seq *sp, enum fc_els_rjt_reason reason,
++ enum fc_els_rjt_explan explan)
++{
++ struct fc_frame *fp;
++ struct fc_els_ls_rjt *rjt;
++ struct fc_lport *lport;
++ struct fc_exch *ep;
++
++ ep = fc_seq_exch(sp);
++ lport = ep->lp;
++ fp = fc_frame_alloc(lport, sizeof(*rjt));
++ if (!fp)
++ return;
++
++ rjt = fc_frame_payload_get(fp, sizeof(*rjt));
++ memset(rjt, 0, sizeof(*rjt));
++ rjt->er_cmd = ELS_LS_RJT;
++ rjt->er_reason = reason;
++ rjt->er_explan = explan;
++
++ sp = lport->tt.seq_start_next(sp);
++ fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, FC_TYPE_FCP,
++ FC_FC_EX_CTX | FC_FC_END_SEQ | FC_FC_LAST_SEQ, 0);
++ lport->tt.seq_send(lport, sp, fp);
++}
++
++/*
++ * Handle an incoming FCP ELS-4 command frame.
++ * Note that this may be called directly from the softirq context.
++ */
++static void ft_recv_els4(struct ft_sess *sess, struct fc_seq *sp,
++ struct fc_frame *fp)
++{
++ u8 op = fc_frame_payload_op(fp);
++
++ switch (op) {
++ case ELS_SRR: /* TBD */
++ default:
++ FT_IO_DBG("unsupported ELS-4 op %x\n", op);
++ ft_cmd_ls_rjt(sp, ELS_RJT_INVAL, ELS_EXPL_NONE);
++ fc_frame_free(fp);
++ break;
++ }
++}
++
++/*
++ * Handle an incoming FCP frame.
++ * Note that this may be called directly from the softirq context.
++ */
++void ft_recv_req(struct ft_sess *sess, struct fc_seq *sp, struct fc_frame *fp)
++{
++ struct fc_frame_header *fh = fc_frame_header_get(fp);
++
++ switch (fh->fh_r_ctl) {
++ case FC_RCTL_DD_UNSOL_CMD:
++ ft_recv_cmd(sess, sp, fp);
++ break;
++ case FC_RCTL_ELS4_REQ:
++ ft_recv_els4(sess, sp, fp);
++ break;
++ default:
++ printk(KERN_INFO "%s: unhandled frame r_ctl %x\n",
++ __func__, fh->fh_r_ctl);
++ fc_frame_free(fp);
++ sess->tport->lport->tt.exch_done(sp);
++ break;
++ }
++}
+diff -uprN orig/linux-2.6.36/drivers/scst/fcst/ft_io.c linux-2.6.36/drivers/scst/fcst/ft_io.c
+--- orig/linux-2.6.36/drivers/scst/fcst/ft_io.c
++++ linux-2.6.36/drivers/scst/fcst/ft_io.c
+@@ -0,0 +1,272 @@
++/*
++ * Copyright (c) 2010 Cisco Systems, Inc.
++ *
++ * Portions based on drivers/scsi/libfc/fc_fcp.c and subject to the following:
++ *
++ * Copyright (c) 2007 Intel Corporation. All rights reserved.
++ * Copyright (c) 2008 Red Hat, Inc. All rights reserved.
++ * Copyright (c) 2008 Mike Christie
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <scsi/libfc.h>
++#include <scsi/fc_encode.h>
++#include "fcst.h"
++
++/*
++ * Receive write data frame.
++ */
++void ft_recv_write_data(struct scst_cmd *cmd, struct fc_frame *fp)
++{
++ struct ft_cmd *fcmd;
++ struct fc_frame_header *fh;
++ unsigned int bufflen;
++ u32 rel_off;
++ size_t frame_len;
++ size_t mem_len;
++ size_t tlen;
++ void *from;
++ void *to;
++ int dir;
++ u8 *buf;
++
++ dir = scst_cmd_get_data_direction(cmd);
++ if (dir == SCST_DATA_BIDI) {
++ mem_len = scst_get_out_buf_first(cmd, &buf);
++ bufflen = scst_cmd_get_out_bufflen(cmd);
++ } else {
++ mem_len = scst_get_buf_first(cmd, &buf);
++ bufflen = scst_cmd_get_bufflen(cmd);
++ }
++ to = buf;
++
++ fcmd = scst_cmd_get_tgt_priv(cmd);
++ fh = fc_frame_header_get(fp);
++ frame_len = fr_len(fp);
++ rel_off = ntohl(fh->fh_parm_offset);
++
++ FT_IO_DBG("sid %x oxid %x payload_len %zd rel_off %x\n",
++ ntoh24(fh->fh_s_id), ntohs(fh->fh_ox_id),
++ frame_len - sizeof(*fh), rel_off);
++
++ if (!(ntoh24(fh->fh_f_ctl) & FC_FC_REL_OFF))
++ goto drop;
++ if (frame_len <= sizeof(*fh))
++ goto drop;
++ frame_len -= sizeof(*fh);
++ from = fc_frame_payload_get(fp, 0);
++
++ if (rel_off >= bufflen)
++ goto drop;
++ if (frame_len + rel_off > bufflen)
++ frame_len = bufflen - rel_off;
++
++ while (frame_len) {
++ if (!mem_len) {
++ if (dir == SCST_DATA_BIDI) {
++ scst_put_out_buf(cmd, buf);
++ mem_len = scst_get_out_buf_next(cmd, &buf);
++ } else {
++ scst_put_buf(cmd, buf);
++ mem_len = scst_get_buf_next(cmd, &buf);
++ }
++ to = buf;
++ if (!mem_len)
++ break;
++ }
++ if (rel_off) {
++ if (rel_off >= mem_len) {
++ rel_off -= mem_len;
++ mem_len = 0;
++ continue;
++ }
++ mem_len -= rel_off;
++ to += rel_off;
++ rel_off = 0;
++ }
++
++ tlen = min(mem_len, frame_len);
++ memcpy(to, from, tlen);
++
++ from += tlen;
++ frame_len -= tlen;
++ mem_len -= tlen;
++ to += tlen;
++ fcmd->write_data_len += tlen;
++ }
++ if (mem_len) {
++ if (dir == SCST_DATA_BIDI)
++ scst_put_out_buf(cmd, buf);
++ else
++ scst_put_buf(cmd, buf);
++ }
++ if (fcmd->write_data_len == cmd->data_len)
++ scst_rx_data(cmd, SCST_RX_STATUS_SUCCESS, SCST_CONTEXT_THREAD);
++drop:
++ fc_frame_free(fp);
++}
++
++/*
++ * Send read data back to initiator.
++ */
++int ft_send_read_data(struct scst_cmd *cmd)
++{
++ struct ft_cmd *fcmd;
++ struct fc_frame *fp = NULL;
++ struct fc_exch *ep;
++ struct fc_lport *lport;
++ size_t remaining;
++ u32 fh_off = 0;
++ u32 frame_off;
++ size_t frame_len = 0;
++ size_t mem_len;
++ u32 mem_off;
++ size_t tlen;
++ struct page *page;
++ int use_sg;
++ int error;
++ void *to = NULL;
++ u8 *from = NULL;
++ int loop_limit = 10000;
++
++ fcmd = scst_cmd_get_tgt_priv(cmd);
++ ep = fc_seq_exch(fcmd->seq);
++ lport = ep->lp;
++
++ frame_off = fcmd->read_data_len;
++ tlen = scst_cmd_get_resp_data_len(cmd);
++ FT_IO_DBG("oid %x oxid %x resp_len %zd frame_off %u\n",
++ ep->oid, ep->oxid, tlen, frame_off);
++ if (tlen <= frame_off)
++ return SCST_TGT_RES_SUCCESS;
++ remaining = tlen - frame_off;
++ if (remaining > UINT_MAX)
++ FT_ERR("oid %x oxid %x resp_len %zd frame_off %u\n",
++ ep->oid, ep->oxid, tlen, frame_off);
++
++ mem_len = scst_get_buf_first(cmd, &from);
++ mem_off = 0;
++ if (!mem_len) {
++ FT_IO_DBG("mem_len 0\n");
++ return SCST_TGT_RES_SUCCESS;
++ }
++ FT_IO_DBG("sid %x oxid %x mem_len %zd frame_off %u remaining %zd\n",
++ ep->sid, ep->oxid, mem_len, frame_off, remaining);
++
++ /*
++ * If we've already transferred some of the data, skip through
++ * the buffer over the data already sent and continue with the
++ * same sequence. Otherwise, get a new sequence for the data.
++ */
++ if (frame_off) {
++ tlen = frame_off;
++ while (mem_len <= tlen) {
++ tlen -= mem_len;
++ scst_put_buf(cmd, from);
++ mem_len = scst_get_buf_next(cmd, &from);
++ if (!mem_len)
++ return SCST_TGT_RES_SUCCESS;
++ }
++ mem_len -= tlen;
++ mem_off = tlen;
++ } else
++ fcmd->seq = lport->tt.seq_start_next(fcmd->seq);
++
++ /* no scatter/gather in skb for odd word length due to fc_seq_send() */
++ use_sg = !(remaining % 4) && lport->sg_supp;
++
++ while (remaining) {
++ if (!loop_limit) {
++ FT_ERR("hit loop limit. remaining %zx mem_len %zx "
++ "frame_len %zx tlen %zx\n",
++ remaining, mem_len, frame_len, tlen);
++ break;
++ }
++ loop_limit--;
++ if (!mem_len) {
++ scst_put_buf(cmd, from);
++ mem_len = scst_get_buf_next(cmd, &from);
++ mem_off = 0;
++ if (!mem_len) {
++ FT_ERR("mem_len 0 from get_buf_next\n");
++ break;
++ }
++ }
++ if (!frame_len) {
++ frame_len = fcmd->max_lso_payload;
++ frame_len = min(frame_len, remaining);
++ fp = fc_frame_alloc(lport, use_sg ? 0 : frame_len);
++ if (!fp) {
++ FT_IO_DBG("frame_alloc failed. "
++ "use_sg %d frame_len %zd\n",
++ use_sg, frame_len);
++ break;
++ }
++ fr_max_payload(fp) = fcmd->max_payload;
++ to = fc_frame_payload_get(fp, 0);
++ fh_off = frame_off;
++ frame_off += frame_len;
++ }
++ tlen = min(mem_len, frame_len);
++ BUG_ON(!tlen);
++ BUG_ON(tlen > remaining);
++ BUG_ON(tlen > mem_len);
++ BUG_ON(tlen > frame_len);
++
++ if (use_sg) {
++ page = virt_to_page(from + mem_off);
++ get_page(page);
++ tlen = min_t(size_t, tlen,
++ PAGE_SIZE - (mem_off & ~PAGE_MASK));
++ skb_fill_page_desc(fp_skb(fp),
++ skb_shinfo(fp_skb(fp))->nr_frags,
++ page, mem_off, tlen);
++ fr_len(fp) += tlen;
++ fp_skb(fp)->data_len += tlen;
++ fp_skb(fp)->truesize +=
++ PAGE_SIZE << compound_order(page);
++ } else {
++ memcpy(to, from + mem_off, tlen);
++ to += tlen;
++ }
++
++ mem_len -= tlen;
++ mem_off += tlen;
++ frame_len -= tlen;
++ remaining -= tlen;
++
++ if (frame_len)
++ continue;
++ fc_fill_fc_hdr(fp, FC_RCTL_DD_SOL_DATA, ep->did, ep->sid,
++ FC_TYPE_FCP,
++ remaining ? (FC_FC_EX_CTX | FC_FC_REL_OFF) :
++ (FC_FC_EX_CTX | FC_FC_REL_OFF | FC_FC_END_SEQ),
++ fh_off);
++ error = lport->tt.seq_send(lport, fcmd->seq, fp);
++ if (error) {
++ WARN_ON(1);
++ /* XXX For now, initiator will retry */
++ } else
++ fcmd->read_data_len = frame_off;
++ }
++ if (mem_len)
++ scst_put_buf(cmd, from);
++ if (remaining) {
++ FT_IO_DBG("remaining read data %zd\n", remaining);
++ return SCST_TGT_RES_QUEUE_FULL;
++ }
++ return SCST_TGT_RES_SUCCESS;
++}
+diff -uprN orig/linux-2.6.36/drivers/scst/fcst/ft_scst.c linux-2.6.36/drivers/scst/fcst/ft_scst.c
+--- orig/linux-2.6.36/drivers/scst/fcst/ft_scst.c
++++ linux-2.6.36/drivers/scst/fcst/ft_scst.c
+@@ -0,0 +1,96 @@
++/*
++ * Copyright (c) 2010 Cisco Systems, Inc.
++ *
++ * This program is free software; you may redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <scsi/libfc.h>
++#include "fcst.h"
++
++MODULE_AUTHOR("Joe Eykholt <jeykholt@cisco.com>");
++MODULE_DESCRIPTION("Fibre-Channel SCST target");
++MODULE_LICENSE("GPL v2");
++
++unsigned int ft_debug_logging;
++module_param_named(debug_logging, ft_debug_logging, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug_logging, "log levels bigmask");
++
++DEFINE_MUTEX(ft_lport_lock);
++
++/*
++ * Provider ops for libfc.
++ */
++static struct fc4_prov ft_prov = {
++ .prli = ft_prli,
++ .prlo = ft_prlo,
++ .recv = ft_recv,
++ .module = THIS_MODULE,
++};
++
++static struct notifier_block ft_notifier = {
++ .notifier_call = ft_lport_notify
++};
++
++/*
++ * SCST target ops and configuration.
++ * XXX - re-check uninitialized fields
++ */
++struct scst_tgt_template ft_scst_template = {
++ .sg_tablesize = 128, /* XXX get true limit from libfc */
++ .xmit_response_atomic = 1,
++ .rdy_to_xfer_atomic = 1,
++ .xmit_response = ft_send_response,
++ .rdy_to_xfer = ft_send_xfer_rdy,
++ .on_hw_pending_cmd_timeout = ft_cmd_timeout,
++ .on_free_cmd = ft_cmd_free,
++ .task_mgmt_fn_done = ft_cmd_tm_done,
++ .detect = ft_tgt_detect,
++ .release = ft_tgt_release,
++ .report_aen = ft_report_aen,
++ .enable_target = ft_tgt_enable,
++ .is_target_enabled = ft_tgt_enabled,
++ .get_initiator_port_transport_id = ft_get_transport_id,
++ .max_hw_pending_time = FT_MAX_HW_PENDING_TIME,
++ .name = FT_MODULE,
++};
++
++static int __init ft_module_init(void)
++{
++ int err;
++
++ err = scst_register_target_template(&ft_scst_template);
++ if (err)
++ return err;
++ err = fc_fc4_register_provider(FC_TYPE_FCP, &ft_prov);
++ if (err) {
++ scst_unregister_target_template(&ft_scst_template);
++ return err;
++ }
++ blocking_notifier_chain_register(&fc_lport_notifier_head, &ft_notifier);
++ fc_lport_iterate(ft_lport_add, NULL);
++ return 0;
++}
++module_init(ft_module_init);
++
++static void __exit ft_module_exit(void)
++{
++ blocking_notifier_chain_unregister(&fc_lport_notifier_head,
++ &ft_notifier);
++ fc_fc4_deregister_provider(FC_TYPE_FCP, &ft_prov);
++ fc_lport_iterate(ft_lport_del, NULL);
++ scst_unregister_target_template(&ft_scst_template);
++ synchronize_rcu();
++}
++module_exit(ft_module_exit);
+diff -uprN orig/linux-2.6.36/drivers/scst/fcst/ft_sess.c linux-2.6.36/drivers/scst/fcst/ft_sess.c
+--- orig/linux-2.6.36/drivers/scst/fcst/ft_sess.c
++++ linux-2.6.36/drivers/scst/fcst/ft_sess.c
+@@ -0,0 +1,570 @@
++/*
++ * Copyright (c) 2010 Cisco Systems, Inc.
++ *
++ * This program is free software; you may redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/mutex.h>
++#include <linux/hash.h>
++#include <asm/unaligned.h>
++#include <scsi/libfc.h>
++#include <scsi/fc/fc_els.h>
++#include "fcst.h"
++
++static int ft_tport_count;
++
++static ssize_t ft_format_wwn(char *buf, size_t len, u64 wwn)
++{
++ u8 b[8];
++
++ put_unaligned_be64(wwn, b);
++ return snprintf(buf, len,
++ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
++ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
++}
++
++/*
++ * Lookup or allocate target local port.
++ * Caller holds ft_lport_lock.
++ */
++static struct ft_tport *ft_tport_create(struct fc_lport *lport)
++{
++ struct ft_tport *tport;
++ char name[FT_NAMELEN];
++ int i;
++
++ ft_format_wwn(name, sizeof(name), lport->wwpn);
++ FT_SESS_DBG("create %s\n", name);
++
++ tport = rcu_dereference(lport->prov[FC_TYPE_FCP]);
++ if (tport)
++ return tport;
++
++ tport = kzalloc(sizeof(*tport), GFP_KERNEL);
++ if (!tport)
++ return NULL;
++
++ tport->tgt = scst_register_target(&ft_scst_template, name);
++ if (!tport->tgt) {
++ kfree(tport);
++ return NULL;
++ }
++ scst_tgt_set_tgt_priv(tport->tgt, tport);
++ ft_tport_count++;
++
++ tport->lport = lport;
++ for (i = 0; i < FT_SESS_HASH_SIZE; i++)
++ INIT_HLIST_HEAD(&tport->hash[i]);
++
++ rcu_assign_pointer(lport->prov[FC_TYPE_FCP], tport);
++ return tport;
++}
++
++/*
++ * Free tport via RCU.
++ */
++static void ft_tport_rcu_free(struct rcu_head *rcu)
++{
++ struct ft_tport *tport = container_of(rcu, struct ft_tport, rcu);
++
++ kfree(tport);
++}
++
++/*
++ * Delete target local port, if any, associated with the local port.
++ * Caller holds ft_lport_lock.
++ */
++static void ft_tport_delete(struct ft_tport *tport)
++{
++ struct fc_lport *lport;
++ struct scst_tgt *tgt;
++
++ tgt = tport->tgt;
++ BUG_ON(!tgt);
++ FT_SESS_DBG("delete %s\n", scst_get_tgt_name(tgt));
++ scst_unregister_target(tgt);
++ lport = tport->lport;
++ BUG_ON(tport != lport->prov[FC_TYPE_FCP]);
++ rcu_assign_pointer(lport->prov[FC_TYPE_FCP], NULL);
++ tport->lport = NULL;
++ call_rcu(&tport->rcu, ft_tport_rcu_free);
++ ft_tport_count--;
++}
++
++/*
++ * Add local port.
++ * Called thru fc_lport_iterate().
++ */
++void ft_lport_add(struct fc_lport *lport, void *arg)
++{
++ mutex_lock(&ft_lport_lock);
++ ft_tport_create(lport);
++ mutex_unlock(&ft_lport_lock);
++}
++
++/*
++ * Delete local port.
++ * Called thru fc_lport_iterate().
++ */
++void ft_lport_del(struct fc_lport *lport, void *arg)
++{
++ struct ft_tport *tport;
++
++ mutex_lock(&ft_lport_lock);
++ tport = lport->prov[FC_TYPE_FCP];
++ if (tport)
++ ft_tport_delete(tport);
++ mutex_unlock(&ft_lport_lock);
++}
++
++/*
++ * Notification of local port change from libfc.
++ * Create or delete local port and associated tport.
++ */
++int ft_lport_notify(struct notifier_block *nb, unsigned long event, void *arg)
++{
++ struct fc_lport *lport = arg;
++
++ switch (event) {
++ case FC_LPORT_EV_ADD:
++ ft_lport_add(lport, NULL);
++ break;
++ case FC_LPORT_EV_DEL:
++ ft_lport_del(lport, NULL);
++ break;
++ }
++ return NOTIFY_DONE;
++}
++
++/*
++ * Find session in local port.
++ * Sessions and hash lists are RCU-protected.
++ * A reference is taken which must be eventually freed.
++ */
++static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id)
++{
++ struct ft_tport *tport;
++ struct hlist_head *head;
++ struct hlist_node *pos;
++ struct ft_sess *sess = NULL;
++
++ rcu_read_lock();
++ tport = rcu_dereference(lport->prov[FC_TYPE_FCP]);
++ if (!tport)
++ goto out;
++
++ head = &tport->hash[hash_32(port_id, FT_SESS_HASH_BITS)];
++ hlist_for_each_entry_rcu(sess, pos, head, hash) {
++ if (sess->port_id == port_id) {
++ kref_get(&sess->kref);
++ rcu_read_unlock();
++ FT_SESS_DBG("port_id %x found %p\n", port_id, sess);
++ return sess;
++ }
++ }
++out:
++ rcu_read_unlock();
++ FT_SESS_DBG("port_id %x not found\n", port_id);
++ return NULL;
++}
++
++/*
++ * Allocate session and enter it in the hash for the local port.
++ * Caller holds ft_lport_lock.
++ */
++static int ft_sess_create(struct ft_tport *tport, struct fc_rport_priv *rdata,
++ u32 fcp_parm)
++{
++ struct ft_sess *sess;
++ struct scst_session *scst_sess;
++ struct hlist_head *head;
++ struct hlist_node *pos;
++ u32 port_id;
++ char name[FT_NAMELEN];
++
++ port_id = rdata->ids.port_id;
++ if (!rdata->maxframe_size) {
++ FT_SESS_DBG("port_id %x maxframe_size 0\n", port_id);
++ return FC_SPP_RESP_CONF;
++ }
++
++ head = &tport->hash[hash_32(port_id, FT_SESS_HASH_BITS)];
++ hlist_for_each_entry_rcu(sess, pos, head, hash) {
++ if (sess->port_id == port_id) {
++ sess->params = fcp_parm;
++ return 0;
++ }
++ }
++
++ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
++ if (!sess)
++ return FC_SPP_RESP_RES; /* out of resources */
++
++ sess->port_name = rdata->ids.port_name;
++ sess->max_payload = rdata->maxframe_size;
++ sess->max_lso_payload = rdata->maxframe_size;
++ if (tport->lport->seq_offload)
++ sess->max_lso_payload = tport->lport->lso_max;
++ sess->params = fcp_parm;
++ sess->tport = tport;
++ sess->port_id = port_id;
++ kref_init(&sess->kref); /* ref for table entry */
++
++ ft_format_wwn(name, sizeof(name), rdata->ids.port_name);
++ FT_SESS_DBG("register %s\n", name);
++ scst_sess = scst_register_session(tport->tgt, 0, name, sess, NULL,
++ NULL);
++ if (!scst_sess) {
++ kfree(sess);
++ return FC_SPP_RESP_RES; /* out of resources */
++ }
++ sess->scst_sess = scst_sess;
++ hlist_add_head_rcu(&sess->hash, head);
++ tport->sess_count++;
++
++ FT_SESS_DBG("port_id %x sess %p\n", port_id, sess);
++
++ rdata->prli_count++;
++ return 0;
++}
++
++/*
++ * Unhash the session.
++ * Caller holds ft_lport_lock.
++ */
++static void ft_sess_unhash(struct ft_sess *sess)
++{
++ struct ft_tport *tport = sess->tport;
++
++ hlist_del_rcu(&sess->hash);
++ BUG_ON(!tport->sess_count);
++ tport->sess_count--;
++ sess->port_id = -1;
++ sess->params = 0;
++}
++
++/*
++ * Delete session from hash.
++ * Caller holds ft_lport_lock.
++ */
++static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id)
++{
++ struct hlist_head *head;
++ struct hlist_node *pos;
++ struct ft_sess *sess;
++
++ head = &tport->hash[hash_32(port_id, FT_SESS_HASH_BITS)];
++ hlist_for_each_entry_rcu(sess, pos, head, hash) {
++ if (sess->port_id == port_id) {
++ ft_sess_unhash(sess);
++ return sess;
++ }
++ }
++ return NULL;
++}
++
++/*
++ * Remove session and send PRLO.
++ * This is called when the target is being deleted.
++ * Caller holds ft_lport_lock.
++ */
++static void ft_sess_close(struct ft_sess *sess)
++{
++ struct fc_lport *lport;
++ u32 port_id;
++
++ lport = sess->tport->lport;
++ port_id = sess->port_id;
++ if (port_id == -1)
++ return;
++ FT_SESS_DBG("port_id %x\n", port_id);
++ ft_sess_unhash(sess);
++ /* XXX should send LOGO or PRLO to rport */
++}
++
++/*
++ * Allocate and fill in the SPC Transport ID for persistent reservations.
++ */
++int ft_get_transport_id(struct scst_session *scst_sess, uint8_t **result)
++{
++ struct ft_sess *sess;
++ struct {
++ u8 format_proto; /* format and protocol ID (0 for FC) */
++ u8 __resv1[7];
++ __be64 port_name; /* N_Port Name */
++ u8 __resv2[8];
++ } __attribute__((__packed__)) *id;
++
++ if (!scst_sess)
++ return SCSI_TRANSPORTID_PROTOCOLID_FCP2;
++
++ id = kzalloc(sizeof(*id), GFP_KERNEL);
++ if (!id)
++ return -ENOMEM;
++
++ sess = scst_sess_get_tgt_priv(scst_sess);
++ id->port_name = cpu_to_be64(sess->port_name);
++ id->format_proto = SCSI_TRANSPORTID_PROTOCOLID_FCP2;
++ *result = (uint8_t *)id;
++ return 0;
++}
++
++/*
++ * libfc ops involving sessions.
++ */
++
++/*
++ * Handle PRLI (process login) request.
++ * This could be a PRLI we're sending or receiving.
++ * Caller holds ft_lport_lock.
++ */
++static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len,
++ const struct fc_els_spp *rspp, struct fc_els_spp *spp)
++{
++ struct ft_tport *tport;
++ u32 fcp_parm;
++ int ret;
++
++ if (rspp->spp_flags & (FC_SPP_OPA_VAL | FC_SPP_RPA_VAL))
++ return FC_SPP_RESP_NO_PA;
++
++ /*
++ * If both target and initiator bits are off, the SPP is invalid.
++ */
++ fcp_parm = ntohl(rspp->spp_params); /* requested parameters */
++ if (!(fcp_parm & (FCP_SPPF_INIT_FCN | FCP_SPPF_TARG_FCN)))
++ return FC_SPP_RESP_INVL;
++
++ /*
++ * Create session (image pair) only if requested by
++ * EST_IMG_PAIR flag and if the requestor is an initiator.
++ */
++ if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) {
++ spp->spp_flags |= FC_SPP_EST_IMG_PAIR;
++
++ if (!(fcp_parm & FCP_SPPF_INIT_FCN))
++ return FC_SPP_RESP_CONF;
++ tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]);
++ if (!tport || !tport->enabled)
++ return 0; /* not a target for this local port */
++
++ ret = ft_sess_create(tport, rdata, fcp_parm);
++ if (ret)
++ return ret;
++ }
++
++ /*
++ * OR in our service parameters with other provider (initiator), if any.
++ * If the initiator indicates RETRY, we must support that, too.
++ * Don't force RETRY on the initiator, though.
++ */
++ fcp_parm = ntohl(spp->spp_params); /* response parameters */
++ spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN);
++ return FC_SPP_RESP_ACK;
++}
++
++/**
++ * tcm_fcp_prli() - Handle incoming or outgoing PRLI for the FCP target
++ * @rdata: remote port private
++ * @spp_len: service parameter page length
++ * @rspp: received service parameter page (NULL for outgoing PRLI)
++ * @spp: response service parameter page
++ *
++ * Returns spp response code.
++ */
++int ft_prli(struct fc_rport_priv *rdata, u32 spp_len,
++ const struct fc_els_spp *rspp, struct fc_els_spp *spp)
++{
++ int ret;
++
++ FT_SESS_DBG("starting PRLI port_id %x\n", rdata->ids.port_id);
++ mutex_lock(&ft_lport_lock);
++ ret = ft_prli_locked(rdata, spp_len, rspp, spp);
++ mutex_unlock(&ft_lport_lock);
++ FT_SESS_DBG("port_id %x flags %x parms %x ret %x\n",
++ rdata->ids.port_id,
++ rspp->spp_flags,
++ ntohl(spp->spp_params), ret);
++ return ret;
++}
++
++static void ft_sess_rcu_free(struct rcu_head *rcu)
++{
++ struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu);
++
++ kfree(sess);
++}
++
++static void ft_sess_free(struct kref *kref)
++{
++ struct ft_sess *sess = container_of(kref, struct ft_sess, kref);
++ struct scst_session *scst_sess;
++
++ scst_sess = sess->scst_sess;
++ FT_SESS_DBG("unregister %s\n", scst_sess->initiator_name);
++ scst_unregister_session(scst_sess, 0, NULL);
++ call_rcu(&sess->rcu, ft_sess_rcu_free);
++}
++
++static void ft_sess_put(struct ft_sess *sess)
++{
++ int sess_held = atomic_read(&sess->kref.refcount);
++
++ BUG_ON(!sess_held);
++ kref_put(&sess->kref, ft_sess_free);
++}
++
++/*
++ * Delete ft_sess for PRLO.
++ * Called with ft_lport_lock held.
++ */
++static struct ft_sess *ft_sess_lookup_delete(struct fc_rport_priv *rdata)
++{
++ struct ft_sess *sess;
++ struct ft_tport *tport;
++
++ tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]);
++ if (!tport)
++ return NULL;
++ sess = ft_sess_delete(tport, rdata->ids.port_id);
++ if (sess)
++ sess->params = 0;
++ return sess;
++}
++
++/*
++ * Handle PRLO.
++ */
++void ft_prlo(struct fc_rport_priv *rdata)
++{
++ struct ft_sess *sess;
++
++ mutex_lock(&ft_lport_lock);
++ sess = ft_sess_lookup_delete(rdata);
++ mutex_unlock(&ft_lport_lock);
++ if (!sess)
++ return;
++
++ /*
++ * Release the session hold from the table.
++ * When all command-starting threads have returned,
++ * kref will call ft_sess_free which will unregister
++ * the session.
++ * fcmds referencing the session are safe.
++ */
++ ft_sess_put(sess); /* release from table */
++ rdata->prli_count--;
++}
++
++/*
++ * Handle incoming FCP request.
++ *
++ * Caller has verified that the frame is type FCP.
++ * Note that this may be called directly from the softirq context.
++ */
++void ft_recv(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp)
++{
++ struct ft_sess *sess;
++ struct fc_frame_header *fh;
++ u32 sid;
++
++ fh = fc_frame_header_get(fp);
++ sid = ntoh24(fh->fh_s_id);
++
++ FT_SESS_DBG("sid %x preempt %x\n", sid, preempt_count());
++
++ sess = ft_sess_get(lport, sid);
++ if (!sess) {
++ FT_SESS_DBG("sid %x sess lookup failed\n", sid);
++ lport->tt.exch_done(sp);
++ /* TBD XXX - if FCP_CMND, send LOGO */
++ fc_frame_free(fp);
++ return;
++ }
++ FT_SESS_DBG("sid %x sess lookup returned %p preempt %x\n",
++ sid, sess, preempt_count());
++ ft_recv_req(sess, sp, fp);
++ ft_sess_put(sess);
++}
++
++/*
++ * Release all sessions for a target.
++ * Called through scst_unregister_target() as well as directly.
++ * Caller holds ft_lport_lock.
++ */
++int ft_tgt_release(struct scst_tgt *tgt)
++{
++ struct ft_tport *tport;
++ struct hlist_head *head;
++ struct hlist_node *pos;
++ struct ft_sess *sess;
++
++ tport = scst_tgt_get_tgt_priv(tgt);
++ tport->enabled = 0;
++ tport->lport->service_params &= ~FCP_SPPF_TARG_FCN;
++
++ for (head = tport->hash; head < &tport->hash[FT_SESS_HASH_SIZE]; head++)
++ hlist_for_each_entry_rcu(sess, pos, head, hash)
++ ft_sess_close(sess);
++
++ synchronize_rcu();
++ return 0;
++}
++
++int ft_tgt_enable(struct scst_tgt *tgt, bool enable)
++{
++ struct ft_tport *tport;
++ int ret = 0;
++
++ mutex_lock(&ft_lport_lock);
++ if (enable) {
++ FT_SESS_DBG("enable tgt %s\n", tgt->tgt_name);
++ tport = scst_tgt_get_tgt_priv(tgt);
++ tport->enabled = 1;
++ tport->lport->service_params |= FCP_SPPF_TARG_FCN;
++ } else {
++ FT_SESS_DBG("disable tgt %s\n", tgt->tgt_name);
++ ft_tgt_release(tgt);
++ }
++ mutex_unlock(&ft_lport_lock);
++ return ret;
++}
++
++bool ft_tgt_enabled(struct scst_tgt *tgt)
++{
++ struct ft_tport *tport;
++
++ tport = scst_tgt_get_tgt_priv(tgt);
++ return tport->enabled;
++}
++
++int ft_tgt_detect(struct scst_tgt_template *tt)
++{
++ return ft_tport_count;
++}
++
++/*
++ * Report AEN (Asynchronous Event Notification) from device to initiator.
++ * See notes in scst.h.
++ */
++int ft_report_aen(struct scst_aen *aen)
++{
++ struct ft_sess *sess;
++
++ sess = scst_sess_get_tgt_priv(scst_aen_get_sess(aen));
++ FT_SESS_DBG("AEN event %d sess to %x lun %lld\n",
++ aen->event_fn, sess->port_id, scst_aen_get_lun(aen));
++ return SCST_AEN_RES_FAILED; /* XXX TBD */
++}
+diff -uprN orig/linux-2.6.36/Documentation/scst/README.fcst linux-2.6.36/Documentation/scst/README.fcst
+--- orig/linux-2.6.36/Documentation/scst/README.fcst
++++ linux-2.6.36/Documentation/scst/README.fcst
+@@ -0,0 +1,99 @@
++fcst README v1.0 06/10/2010
++
++$Id$
++
++FCST is a module that depends on libfc and SCST to provide FC target support.
++
++To build for linux-2.6.34, do:
++
++1. Get the kernel source:
++
++ KERNEL=linux-2.6.34
++
++ cd /usr/src/kernels
++ URL_DIR=http://www.kernel.org/pub/linux/kernel/v2.6
++ TARFILE=$KERNEL.tar.bz2
++ wget -o $TARFILE $URL_DIR/$TARFILE
++ tar xfj $TARFILE
++ cd $KERNEL
++
++2. Apply patches needed for libfc target hooks and point-to-point fixes:
++
++ KDIR=/usr/src/kernels/$KERNEL
++ PDIR=/usr/src/scst/trunk/fcst/linux-patches # use your dir here
++
++ cd $PDIR
++ for patch in `grep -v '^#' series-2.6.34`
++ do
++ (cd $KDIR; patch -p1) < $patch
++ done
++
++3. Apply SCST patches to the kernel
++ See trunk/scst/README
++ The readahead patches are not needed in 2.6.33 or later.
++
++4. Configure, make, and install your kernel
++
++5. Install SCST
++ See trunk/scst/README. Make sure you are building sysfs SCST build,
++ because FCST supports only it. You need to do
++
++ cd trunk/scst
++ make
++ make install
++
++6. Make FCST
++ In the directory containing this README, just do
++ make
++ make install
++
++7. Install the FCoE admin tools, including dcbd and fcoeadm.
++ Some distros may have these.
++ You should be able to use the source at
++ http://www.open-fcoe.org/openfc/downloads/2.6.34/open-fcoe-2.6.34.tar.gz
++
++8. Bring up SCST and configure the devices.
++
++9. Bring up an FCoE initiator (we'll enable target mode on it later):
++ modprobe fcoe
++ fcoeadm -c eth3
++
++ The other end can be an initiator as well, in point-to-point mode
++ over a full-duplex loss-less link (enable pause on both sides).
++ Alternatively, the other end can be an FCoE switch.
++
++10. Use fcc (part of the open-fcoe contrib tools in step 7) to see the
++ initiator setup. To get the FCoE port name for eth3
++
++ # fcc
++ FC HBAs:
++ HBA Port Name Port ID State Device
++ host4 20:00:00:1b:21:06:58:21 01:01:02 Online eth3
++
++ host4 Remote Ports:
++ Path Port Name Port ID State Roles
++ 4:0-0 10:00:50:41:4c:4f:3b:00 01:01:01 Online FCP Initiator
++
++ In the above example, there's one local host on eth3, and it's in
++ a point-to-point connection with the remote initiator with Port_id 010101.
++
++11. Load fcst
++
++ modprobe fcst
++
++12. Add any disks (configured in step 8) you want to export
++ Note that you must have a LUN 0.
++
++ LPORT=20:00:00:1b:21:06:58:21 # the local Port_Name
++
++ cd /sys/kernel/scst_tgt/targets/fcst/$LPORT
++ echo add disk-name 0 > luns/mgmt
++ echo add disk-name 1 > luns/mgmt
++
++13. Enable the initiator:
++
++ echo 1 > $LPORT/enabled
++
++14. As a temporary workaround, you may need to reset the interface
++ on the initiator side so it sees the SCST device as a target and
++ discovers LUNs. You can avoid this by bringing up the initiator last.
+diff -uprN orig/linux-2.6.36/include/scst/iscsi_scst.h linux-2.6.36/include/scst/iscsi_scst.h
+--- orig/linux-2.6.36/include/scst/iscsi_scst.h
++++ linux-2.6.36/include/scst/iscsi_scst.h
+@@ -0,0 +1,220 @@
++/*
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef _ISCSI_SCST_U_H
++#define _ISCSI_SCST_U_H
++
++#ifndef __KERNEL__
++#include <sys/uio.h>
++#endif
++
++#include "iscsi_scst_ver.h"
++#include "iscsi_scst_itf_ver.h"
++
++/* The maximum length of 223 bytes in the RFC. */
++#define ISCSI_NAME_LEN 256
++
++#define ISCSI_PORTAL_LEN 64
++
++/* Full name is iSCSI name + connected portal */
++#define ISCSI_FULL_NAME_LEN (ISCSI_NAME_LEN + ISCSI_PORTAL_LEN)
++
++#define ISCSI_LISTEN_PORT 3260
++
++#define SCSI_ID_LEN 24
++
++#ifndef aligned_u64
++#define aligned_u64 uint64_t __attribute__((aligned(8)))
++#endif
++
++#define ISCSI_MAX_ATTR_NAME_LEN 50
++#define ISCSI_MAX_ATTR_VALUE_LEN 512
++
++enum {
++ key_initial_r2t,
++ key_immediate_data,
++ key_max_connections,
++ key_max_recv_data_length,
++ key_max_xmit_data_length,
++ key_max_burst_length,
++ key_first_burst_length,
++ key_default_wait_time,
++ key_default_retain_time,
++ key_max_outstanding_r2t,
++ key_data_pdu_inorder,
++ key_data_sequence_inorder,
++ key_error_recovery_level,
++ key_header_digest,
++ key_data_digest,
++ key_ofmarker,
++ key_ifmarker,
++ key_ofmarkint,
++ key_ifmarkint,
++ session_key_last,
++};
++
++enum {
++ key_queued_cmnds,
++ key_rsp_timeout,
++ key_nop_in_interval,
++ key_max_sessions,
++ target_key_last,
++};
++
++enum {
++ key_session,
++ key_target,
++};
++
++struct iscsi_kern_target_info {
++ u32 tid;
++ u32 cookie;
++ char name[ISCSI_NAME_LEN];
++ u32 attrs_num;
++ aligned_u64 attrs_ptr;
++};
++
++struct iscsi_kern_session_info {
++ u32 tid;
++ aligned_u64 sid;
++ char initiator_name[ISCSI_NAME_LEN];
++ char full_initiator_name[ISCSI_FULL_NAME_LEN];
++ u32 exp_cmd_sn;
++ s32 session_params[session_key_last];
++ s32 target_params[target_key_last];
++};
++
++#define DIGEST_ALL (DIGEST_NONE | DIGEST_CRC32C)
++#define DIGEST_NONE (1 << 0)
++#define DIGEST_CRC32C (1 << 1)
++
++struct iscsi_kern_conn_info {
++ u32 tid;
++ aligned_u64 sid;
++
++ u32 cid;
++ u32 stat_sn;
++ u32 exp_stat_sn;
++ int fd;
++};
++
++struct iscsi_kern_attr {
++ u32 mode;
++ char name[ISCSI_MAX_ATTR_NAME_LEN];
++};
++
++struct iscsi_kern_mgmt_cmd_res_info {
++ u32 tid;
++ u32 cookie;
++ u32 req_cmd;
++ u32 result;
++ char value[ISCSI_MAX_ATTR_VALUE_LEN];
++};
++
++struct iscsi_kern_params_info {
++ u32 tid;
++ aligned_u64 sid;
++
++ u32 params_type;
++ u32 partial;
++
++ s32 session_params[session_key_last];
++ s32 target_params[target_key_last];
++};
++
++enum iscsi_kern_event_code {
++ E_ADD_TARGET,
++ E_DEL_TARGET,
++ E_MGMT_CMD,
++ E_ENABLE_TARGET,
++ E_DISABLE_TARGET,
++ E_GET_ATTR_VALUE,
++ E_SET_ATTR_VALUE,
++ E_CONN_CLOSE,
++};
++
++struct iscsi_kern_event {
++ u32 tid;
++ aligned_u64 sid;
++ u32 cid;
++ u32 code;
++ u32 cookie;
++ char target_name[ISCSI_NAME_LEN];
++ u32 param1_size;
++ u32 param2_size;
++};
++
++struct iscsi_kern_register_info {
++ union {
++ aligned_u64 version;
++ struct {
++ int max_data_seg_len;
++ int max_queued_cmds;
++ };
++ };
++};
++
++struct iscsi_kern_attr_info {
++ u32 tid;
++ u32 cookie;
++ struct iscsi_kern_attr attr;
++};
++
++struct iscsi_kern_initiator_info {
++ u32 tid;
++ char full_initiator_name[ISCSI_FULL_NAME_LEN];
++};
++
++#define DEFAULT_NR_QUEUED_CMNDS 32
++#define MIN_NR_QUEUED_CMNDS 1
++#define MAX_NR_QUEUED_CMNDS 256
++
++#define DEFAULT_RSP_TIMEOUT 30
++#define MIN_RSP_TIMEOUT 2
++#define MAX_RSP_TIMEOUT 65535
++
++#define DEFAULT_NOP_IN_INTERVAL 30
++#define MIN_NOP_IN_INTERVAL 0
++#define MAX_NOP_IN_INTERVAL 65535
++
++#define NETLINK_ISCSI_SCST 25
++
++#define REGISTER_USERD _IOWR('s', 0, struct iscsi_kern_register_info)
++#define ADD_TARGET _IOW('s', 1, struct iscsi_kern_target_info)
++#define DEL_TARGET _IOW('s', 2, struct iscsi_kern_target_info)
++#define ADD_SESSION _IOW('s', 3, struct iscsi_kern_session_info)
++#define DEL_SESSION _IOW('s', 4, struct iscsi_kern_session_info)
++#define ADD_CONN _IOW('s', 5, struct iscsi_kern_conn_info)
++#define DEL_CONN _IOW('s', 6, struct iscsi_kern_conn_info)
++#define ISCSI_PARAM_SET _IOW('s', 7, struct iscsi_kern_params_info)
++#define ISCSI_PARAM_GET _IOWR('s', 8, struct iscsi_kern_params_info)
++
++#define ISCSI_ATTR_ADD _IOW('s', 9, struct iscsi_kern_attr_info)
++#define ISCSI_ATTR_DEL _IOW('s', 10, struct iscsi_kern_attr_info)
++#define MGMT_CMD_CALLBACK _IOW('s', 11, struct iscsi_kern_mgmt_cmd_res_info)
++
++#define ISCSI_INITIATOR_ALLOWED _IOW('s', 12, struct iscsi_kern_initiator_info)
++
++static inline int iscsi_is_key_internal(int key)
++{
++ switch (key) {
++ case key_max_xmit_data_length:
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++#endif
+diff -uprN orig/linux-2.6.36/include/scst/iscsi_scst_ver.h linux-2.6.36/include/scst/iscsi_scst_ver.h
+--- orig/linux-2.6.36/include/scst/iscsi_scst_ver.h
++++ linux-2.6.36/include/scst/iscsi_scst_ver.h
+@@ -0,0 +1,20 @@
++/*
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++/* #define CONFIG_SCST_PROC */
++
++#define ISCSI_VERSION_STRING_SUFFIX
++
++#define ISCSI_VERSION_STRING "2.0.0" ISCSI_VERSION_STRING_SUFFIX
+diff -uprN orig/linux-2.6.36/include/scst/iscsi_scst_itf_ver.h linux-2.6.36/include/scst/iscsi_scst_itf_ver.h
+--- orig/linux-2.6.36/include/scst/iscsi_scst_itf_ver.h
++++ linux-2.6.36/include/scst/iscsi_scst_itf_ver.h
+@@ -0,0 +1,3 @@
++/* Autogenerated, don't edit */
++
++#define ISCSI_SCST_INTERFACE_VERSION ISCSI_VERSION_STRING "_" "31815603fdea2196eb9774eac0e41bf15c9a9130"
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/Makefile linux-2.6.36/drivers/scst/iscsi-scst/Makefile
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/Makefile
++++ linux-2.6.36/drivers/scst/iscsi-scst/Makefile
+@@ -0,0 +1,4 @@
++iscsi-scst-y := iscsi.o nthread.o config.o digest.o \
++ conn.o session.o target.o event.o param.o
++
++obj-$(CONFIG_SCST_ISCSI) += iscsi-scst.o
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/Kconfig linux-2.6.36/drivers/scst/iscsi-scst/Kconfig
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/Kconfig
++++ linux-2.6.36/drivers/scst/iscsi-scst/Kconfig
+@@ -0,0 +1,25 @@
++config SCST_ISCSI
++ tristate "ISCSI Target"
++ depends on SCST && INET
++ default SCST
++ help
++ ISCSI target driver for SCST framework. The iSCSI protocol has been
++ defined in RFC 3720. To use it you should download from
++ http://scst.sourceforge.net the user space part of it.
++
++config SCST_ISCSI_DEBUG_DIGEST_FAILURES
++ bool "Simulate iSCSI digest failures"
++ depends on SCST_ISCSI
++ help
++ Simulates iSCSI digest failures in random places. Even when iSCSI
++ traffic is sent over a TCP connection, the 16-bit TCP checksum is too
++ weak for the requirements of a storage protocol. Furthermore, there
++ are also instances where the TCP checksum does not protect iSCSI
++ data, as when data is corrupted while being transferred on a PCI bus
++ or while in memory. The iSCSI protocol therefore defines a 32-bit CRC
++ digest on iSCSI packets in order to detect data corruption on an
++ end-to-end basis. CRCs can be used on iSCSI PDU headers and/or data.
++ Enabling this option allows to test digest failure recovery in the
++ iSCSI initiator that is talking to SCST.
++
++ If unsure, say "N".
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/config.c linux-2.6.36/drivers/scst/iscsi-scst/config.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/config.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/config.c
+@@ -0,0 +1,1032 @@
++/*
++ * Copyright (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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.
++ *
++ * 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.
++ */
++
++#include "iscsi.h"
++
++/* Protected by target_mgmt_mutex */
++int ctr_open_state;
++
++/* Protected by target_mgmt_mutex */
++static LIST_HEAD(iscsi_attrs_list);
++
++static ssize_t iscsi_version_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ TRACE_ENTRY();
++
++ sprintf(buf, "%s\n", ISCSI_VERSION_STRING);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ strcat(buf, "EXTRACHECKS\n");
++#endif
++
++#ifdef CONFIG_SCST_TRACING
++ strcat(buf, "TRACING\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++ strcat(buf, "DEBUG\n");
++#endif
++
++#ifdef CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES
++ strcat(buf, "DEBUG_DIGEST_FAILURES\n");
++#endif
++
++ TRACE_EXIT();
++ return strlen(buf);
++}
++
++static struct kobj_attribute iscsi_version_attr =
++ __ATTR(version, S_IRUGO, iscsi_version_show, NULL);
++
++static ssize_t iscsi_open_state_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ switch (ctr_open_state) {
++ case ISCSI_CTR_OPEN_STATE_CLOSED:
++ sprintf(buf, "%s\n", "closed");
++ break;
++ case ISCSI_CTR_OPEN_STATE_OPEN:
++ sprintf(buf, "%s\n", "open");
++ break;
++ case ISCSI_CTR_OPEN_STATE_CLOSING:
++ sprintf(buf, "%s\n", "closing");
++ break;
++ default:
++ sprintf(buf, "%s\n", "unknown");
++ break;
++ }
++
++ return strlen(buf);
++}
++
++static struct kobj_attribute iscsi_open_state_attr =
++ __ATTR(open_state, S_IRUGO, iscsi_open_state_show, NULL);
++
++const struct attribute *iscsi_attrs[] = {
++ &iscsi_version_attr.attr,
++ &iscsi_open_state_attr.attr,
++ NULL,
++};
++
++/* target_mgmt_mutex supposed to be locked */
++static int add_conn(void __user *ptr)
++{
++ int err, rc;
++ struct iscsi_session *session;
++ struct iscsi_kern_conn_info info;
++ struct iscsi_target *target;
++
++ TRACE_ENTRY();
++
++ rc = copy_from_user(&info, ptr, sizeof(info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out;
++ }
++
++ target = target_lookup_by_id(info.tid);
++ if (target == NULL) {
++ PRINT_ERROR("Target %d not found", info.tid);
++ err = -ENOENT;
++ goto out;
++ }
++
++ mutex_lock(&target->target_mutex);
++
++ session = session_lookup(target, info.sid);
++ if (!session) {
++ PRINT_ERROR("Session %lld not found",
++ (long long unsigned int)info.tid);
++ err = -ENOENT;
++ goto out_unlock;
++ }
++
++ err = __add_conn(session, &info);
++
++out_unlock:
++ mutex_unlock(&target->target_mutex);
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int del_conn(void __user *ptr)
++{
++ int err, rc;
++ struct iscsi_session *session;
++ struct iscsi_kern_conn_info info;
++ struct iscsi_target *target;
++
++ TRACE_ENTRY();
++
++ rc = copy_from_user(&info, ptr, sizeof(info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out;
++ }
++
++ target = target_lookup_by_id(info.tid);
++ if (target == NULL) {
++ PRINT_ERROR("Target %d not found", info.tid);
++ err = -ENOENT;
++ goto out;
++ }
++
++ mutex_lock(&target->target_mutex);
++
++ session = session_lookup(target, info.sid);
++ if (!session) {
++ PRINT_ERROR("Session %llx not found",
++ (long long unsigned int)info.sid);
++ err = -ENOENT;
++ goto out_unlock;
++ }
++
++ err = __del_conn(session, &info);
++
++out_unlock:
++ mutex_unlock(&target->target_mutex);
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int add_session(void __user *ptr)
++{
++ int err, rc;
++ struct iscsi_kern_session_info *info;
++ struct iscsi_target *target;
++
++ TRACE_ENTRY();
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ PRINT_ERROR("Can't alloc info (size %zd)", sizeof(*info));
++ err = -ENOMEM;
++ goto out;
++ }
++
++ rc = copy_from_user(info, ptr, sizeof(*info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out_free;
++ }
++
++ info->initiator_name[sizeof(info->initiator_name)-1] = '\0';
++ info->full_initiator_name[sizeof(info->full_initiator_name)-1] = '\0';
++
++ target = target_lookup_by_id(info->tid);
++ if (target == NULL) {
++ PRINT_ERROR("Target %d not found", info->tid);
++ err = -ENOENT;
++ goto out_free;
++ }
++
++ err = __add_session(target, info);
++
++out_free:
++ kfree(info);
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int del_session(void __user *ptr)
++{
++ int err, rc;
++ struct iscsi_kern_session_info *info;
++ struct iscsi_target *target;
++
++ TRACE_ENTRY();
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ PRINT_ERROR("Can't alloc info (size %zd)", sizeof(*info));
++ err = -ENOMEM;
++ goto out;
++ }
++
++ rc = copy_from_user(info, ptr, sizeof(*info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out_free;
++ }
++
++ info->initiator_name[sizeof(info->initiator_name)-1] = '\0';
++
++ target = target_lookup_by_id(info->tid);
++ if (target == NULL) {
++ PRINT_ERROR("Target %d not found", info->tid);
++ err = -ENOENT;
++ goto out_free;
++ }
++
++ mutex_lock(&target->target_mutex);
++ err = __del_session(target, info->sid);
++ mutex_unlock(&target->target_mutex);
++
++out_free:
++ kfree(info);
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int iscsi_params_config(void __user *ptr, int set)
++{
++ int err, rc;
++ struct iscsi_kern_params_info info;
++ struct iscsi_target *target;
++
++ TRACE_ENTRY();
++
++ rc = copy_from_user(&info, ptr, sizeof(info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out;
++ }
++
++ target = target_lookup_by_id(info.tid);
++ if (target == NULL) {
++ PRINT_ERROR("Target %d not found", info.tid);
++ err = -ENOENT;
++ goto out;
++ }
++
++ mutex_lock(&target->target_mutex);
++ err = iscsi_params_set(target, &info, set);
++ mutex_unlock(&target->target_mutex);
++
++ if (err < 0)
++ goto out;
++
++ if (!set) {
++ rc = copy_to_user(ptr, &info, sizeof(info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy to user %d bytes", rc);
++ err = -EFAULT;
++ goto out;
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int iscsi_initiator_allowed(void __user *ptr)
++{
++ int err = 0, rc;
++ struct iscsi_kern_initiator_info cinfo;
++ struct iscsi_target *target;
++
++ TRACE_ENTRY();
++
++ rc = copy_from_user(&cinfo, ptr, sizeof(cinfo));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out;
++ }
++
++ cinfo.full_initiator_name[sizeof(cinfo.full_initiator_name)-1] = '\0';
++
++ target = target_lookup_by_id(cinfo.tid);
++ if (target == NULL) {
++ PRINT_ERROR("Target %d not found", cinfo.tid);
++ err = -ENOENT;
++ goto out;
++ }
++
++ err = scst_initiator_has_luns(target->scst_tgt,
++ cinfo.full_initiator_name);
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int mgmt_cmd_callback(void __user *ptr)
++{
++ int err = 0, rc;
++ struct iscsi_kern_mgmt_cmd_res_info cinfo;
++ struct scst_sysfs_user_info *info;
++
++ TRACE_ENTRY();
++
++ rc = copy_from_user(&cinfo, ptr, sizeof(cinfo));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out;
++ }
++
++ cinfo.value[sizeof(cinfo.value)-1] = '\0';
++
++ info = scst_sysfs_user_get_info(cinfo.cookie);
++ TRACE_DBG("cookie %u, info %p, result %d", cinfo.cookie, info,
++ cinfo.result);
++ if (info == NULL) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ info->info_status = 0;
++
++ if (cinfo.result != 0) {
++ info->info_status = cinfo.result;
++ goto out_complete;
++ }
++
++ switch (cinfo.req_cmd) {
++ case E_ENABLE_TARGET:
++ case E_DISABLE_TARGET:
++ {
++ struct iscsi_target *target;
++
++ target = target_lookup_by_id(cinfo.tid);
++ if (target == NULL) {
++ PRINT_ERROR("Target %d not found", cinfo.tid);
++ err = -ENOENT;
++ goto out_status;
++ }
++
++ target->tgt_enabled = (cinfo.req_cmd == E_ENABLE_TARGET) ? 1 : 0;
++ break;
++ }
++
++ case E_GET_ATTR_VALUE:
++ info->data = kstrdup(cinfo.value, GFP_KERNEL);
++ if (info->data == NULL) {
++ PRINT_ERROR("Can't dublicate value %s", cinfo.value);
++ info->info_status = -ENOMEM;
++ goto out_complete;
++ }
++ break;
++ }
++
++out_complete:
++ complete(&info->info_completion);
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++
++out_status:
++ info->info_status = err;
++ goto out_complete;
++}
++
++static ssize_t iscsi_attr_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos;
++ struct iscsi_attr *tgt_attr;
++ void *value;
++
++ TRACE_ENTRY();
++
++ tgt_attr = container_of(attr, struct iscsi_attr, attr);
++
++ pos = iscsi_sysfs_send_event(
++ (tgt_attr->target != NULL) ? tgt_attr->target->tid : 0,
++ E_GET_ATTR_VALUE, tgt_attr->name, NULL, &value);
++
++ if (pos != 0)
++ goto out;
++
++ pos = scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n", (char *)value);
++
++ kfree(value);
++
++out:
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t iscsi_attr_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ char *buffer;
++ struct iscsi_attr *tgt_attr;
++
++ TRACE_ENTRY();
++
++ buffer = kzalloc(count+1, GFP_KERNEL);
++ if (buffer == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++ memcpy(buffer, buf, count);
++ buffer[count] = '\0';
++
++ tgt_attr = container_of(attr, struct iscsi_attr, attr);
++
++ TRACE_DBG("attr %s, buffer %s", tgt_attr->attr.attr.name, buffer);
++
++ res = iscsi_sysfs_send_event(
++ (tgt_attr->target != NULL) ? tgt_attr->target->tid : 0,
++ E_SET_ATTR_VALUE, tgt_attr->name, buffer, NULL);
++
++ kfree(buffer);
++
++ if (res == 0)
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * target_mgmt_mutex supposed to be locked. If target != 0, target_mutex
++ * supposed to be locked as well.
++ */
++int iscsi_add_attr(struct iscsi_target *target,
++ const struct iscsi_kern_attr *attr_info)
++{
++ int res = 0;
++ struct iscsi_attr *tgt_attr;
++ struct list_head *attrs_list;
++ const char *name;
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++ static struct lock_class_key __key;
++#endif
++
++ TRACE_ENTRY();
++
++ if (target != NULL) {
++ attrs_list = &target->attrs_list;
++ name = target->name;
++ } else {
++ attrs_list = &iscsi_attrs_list;
++ name = "global";
++ }
++
++ list_for_each_entry(tgt_attr, attrs_list, attrs_list_entry) {
++ /* Both for sure NULL-terminated */
++ if (strcmp(tgt_attr->name, attr_info->name) == 0) {
++ PRINT_ERROR("Attribute %s for %s already exist",
++ attr_info->name, name);
++ res = -EEXIST;
++ goto out;
++ }
++ }
++
++ TRACE_DBG("Adding %s's attr %s with mode %x", name,
++ attr_info->name, attr_info->mode);
++
++ tgt_attr = kzalloc(sizeof(*tgt_attr), GFP_KERNEL);
++ if (tgt_attr == NULL) {
++ PRINT_ERROR("Unable to allocate user (size %zd)",
++ sizeof(*tgt_attr));
++ res = -ENOMEM;
++ goto out;
++ }
++
++ tgt_attr->target = target;
++
++ tgt_attr->name = kstrdup(attr_info->name, GFP_KERNEL);
++ if (tgt_attr->name == NULL) {
++ PRINT_ERROR("Unable to allocate attr %s name/value (target %s)",
++ attr_info->name, name);
++ res = -ENOMEM;
++ goto out_free;
++ }
++
++ list_add(&tgt_attr->attrs_list_entry, attrs_list);
++
++ tgt_attr->attr.attr.name = tgt_attr->name;
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++ tgt_attr->attr.attr.key = &__key;
++#endif
++ tgt_attr->attr.attr.mode = attr_info->mode & (S_IRUGO | S_IWUGO);
++ tgt_attr->attr.show = iscsi_attr_show;
++ tgt_attr->attr.store = iscsi_attr_store;
++
++ TRACE_DBG("tgt_attr %p, attr %p", tgt_attr, &tgt_attr->attr.attr);
++
++ res = sysfs_create_file(
++ (target != NULL) ? scst_sysfs_get_tgt_kobj(target->scst_tgt) :
++ scst_sysfs_get_tgtt_kobj(&iscsi_template),
++ &tgt_attr->attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Unable to create file '%s' for target '%s'",
++ tgt_attr->attr.attr.name, name);
++ goto out_del;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_del:
++ list_del(&tgt_attr->attrs_list_entry);
++
++out_free:
++ kfree(tgt_attr->name);
++ kfree(tgt_attr);
++ goto out;
++}
++
++void __iscsi_del_attr(struct iscsi_target *target,
++ struct iscsi_attr *tgt_attr)
++{
++ TRACE_ENTRY();
++
++ TRACE_DBG("Deleting attr %s (target %s, tgt_attr %p, attr %p)",
++ tgt_attr->name, (target != NULL) ? target->name : "global",
++ tgt_attr, &tgt_attr->attr.attr);
++
++ list_del(&tgt_attr->attrs_list_entry);
++
++ sysfs_remove_file((target != NULL) ?
++ scst_sysfs_get_tgt_kobj(target->scst_tgt) :
++ scst_sysfs_get_tgtt_kobj(&iscsi_template),
++ &tgt_attr->attr.attr);
++
++ kfree(tgt_attr->name);
++ kfree(tgt_attr);
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * target_mgmt_mutex supposed to be locked. If target != 0, target_mutex
++ * supposed to be locked as well.
++ */
++static int iscsi_del_attr(struct iscsi_target *target,
++ const char *attr_name)
++{
++ int res = 0;
++ struct iscsi_attr *tgt_attr, *a;
++ struct list_head *attrs_list;
++
++ TRACE_ENTRY();
++
++ if (target != NULL)
++ attrs_list = &target->attrs_list;
++ else
++ attrs_list = &iscsi_attrs_list;
++
++ tgt_attr = NULL;
++ list_for_each_entry(a, attrs_list, attrs_list_entry) {
++ /* Both for sure NULL-terminated */
++ if (strcmp(a->name, attr_name) == 0) {
++ tgt_attr = a;
++ break;
++ }
++ }
++
++ if (tgt_attr == NULL) {
++ PRINT_ERROR("attr %s not found (target %s)", attr_name,
++ (target != NULL) ? target->name : "global");
++ res = -ENOENT;
++ goto out;
++ }
++
++ __iscsi_del_attr(target, tgt_attr);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int iscsi_attr_cmd(void __user *ptr, unsigned int cmd)
++{
++ int rc, err = 0;
++ struct iscsi_kern_attr_info info;
++ struct iscsi_target *target;
++ struct scst_sysfs_user_info *i = NULL;
++
++ TRACE_ENTRY();
++
++ rc = copy_from_user(&info, ptr, sizeof(info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out;
++ }
++
++ info.attr.name[sizeof(info.attr.name)-1] = '\0';
++
++ if (info.cookie != 0) {
++ i = scst_sysfs_user_get_info(info.cookie);
++ TRACE_DBG("cookie %u, uinfo %p", info.cookie, i);
++ if (i == NULL) {
++ err = -EINVAL;
++ goto out;
++ }
++ }
++
++ target = target_lookup_by_id(info.tid);
++
++ if (target != NULL)
++ mutex_lock(&target->target_mutex);
++
++ switch (cmd) {
++ case ISCSI_ATTR_ADD:
++ err = iscsi_add_attr(target, &info.attr);
++ break;
++ case ISCSI_ATTR_DEL:
++ err = iscsi_del_attr(target, info.attr.name);
++ break;
++ default:
++ BUG();
++ }
++
++ if (target != NULL)
++ mutex_unlock(&target->target_mutex);
++
++ if (i != NULL) {
++ i->info_status = err;
++ complete(&i->info_completion);
++ }
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int add_target(void __user *ptr)
++{
++ int err, rc;
++ struct iscsi_kern_target_info *info;
++ struct scst_sysfs_user_info *uinfo;
++
++ TRACE_ENTRY();
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ PRINT_ERROR("Can't alloc info (size %zd)", sizeof(*info));
++ err = -ENOMEM;
++ goto out;
++ }
++
++ rc = copy_from_user(info, ptr, sizeof(*info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out_free;
++ }
++
++ if (target_lookup_by_id(info->tid) != NULL) {
++ PRINT_ERROR("Target %u already exist!", info->tid);
++ err = -EEXIST;
++ goto out_free;
++ }
++
++ info->name[sizeof(info->name)-1] = '\0';
++
++ if (info->cookie != 0) {
++ uinfo = scst_sysfs_user_get_info(info->cookie);
++ TRACE_DBG("cookie %u, uinfo %p", info->cookie, uinfo);
++ if (uinfo == NULL) {
++ err = -EINVAL;
++ goto out_free;
++ }
++ } else
++ uinfo = NULL;
++
++ err = __add_target(info);
++
++ if (uinfo != NULL) {
++ uinfo->info_status = err;
++ complete(&uinfo->info_completion);
++ }
++
++out_free:
++ kfree(info);
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int del_target(void __user *ptr)
++{
++ int err, rc;
++ struct iscsi_kern_target_info info;
++ struct scst_sysfs_user_info *uinfo;
++
++ TRACE_ENTRY();
++
++ rc = copy_from_user(&info, ptr, sizeof(info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy %d user's bytes", rc);
++ err = -EFAULT;
++ goto out;
++ }
++
++ info.name[sizeof(info.name)-1] = '\0';
++
++ if (info.cookie != 0) {
++ uinfo = scst_sysfs_user_get_info(info.cookie);
++ TRACE_DBG("cookie %u, uinfo %p", info.cookie, uinfo);
++ if (uinfo == NULL) {
++ err = -EINVAL;
++ goto out;
++ }
++ } else
++ uinfo = NULL;
++
++ err = __del_target(info.tid);
++
++ if (uinfo != NULL) {
++ uinfo->info_status = err;
++ complete(&uinfo->info_completion);
++ }
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++static int iscsi_register(void __user *arg)
++{
++ struct iscsi_kern_register_info reg;
++ char ver[sizeof(ISCSI_SCST_INTERFACE_VERSION)+1];
++ int res, rc;
++
++ TRACE_ENTRY();
++
++ rc = copy_from_user(&reg, arg, sizeof(reg));
++ if (rc != 0) {
++ PRINT_ERROR("%s", "Unable to get register info");
++ res = -EFAULT;
++ goto out;
++ }
++
++ rc = copy_from_user(ver, (void __user *)(unsigned long)reg.version,
++ sizeof(ver));
++ if (rc != 0) {
++ PRINT_ERROR("%s", "Unable to get version string");
++ res = -EFAULT;
++ goto out;
++ }
++ ver[sizeof(ver)-1] = '\0';
++
++ if (strcmp(ver, ISCSI_SCST_INTERFACE_VERSION) != 0) {
++ PRINT_ERROR("Incorrect version of user space %s (expected %s)",
++ ver, ISCSI_SCST_INTERFACE_VERSION);
++ res = -EINVAL;
++ goto out;
++ }
++
++ memset(&reg, 0, sizeof(reg));
++ reg.max_data_seg_len = ISCSI_CONN_IOV_MAX << PAGE_SHIFT;
++ reg.max_queued_cmds = scst_get_max_lun_commands(NULL, NO_SUCH_LUN);
++
++ res = 0;
++
++ rc = copy_to_user(arg, &reg, sizeof(reg));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy to user %d bytes", rc);
++ res = -EFAULT;
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ long err;
++
++ TRACE_ENTRY();
++
++ if (cmd == REGISTER_USERD) {
++ err = iscsi_register((void __user *)arg);
++ goto out;
++ }
++
++ err = mutex_lock_interruptible(&target_mgmt_mutex);
++ if (err < 0)
++ goto out;
++
++ switch (cmd) {
++ case ADD_TARGET:
++ err = add_target((void __user *)arg);
++ break;
++
++ case DEL_TARGET:
++ err = del_target((void __user *)arg);
++ break;
++
++ case ISCSI_ATTR_ADD:
++ case ISCSI_ATTR_DEL:
++ err = iscsi_attr_cmd((void __user *)arg, cmd);
++ break;
++
++ case MGMT_CMD_CALLBACK:
++ err = mgmt_cmd_callback((void __user *)arg);
++ break;
++
++ case ISCSI_INITIATOR_ALLOWED:
++ err = iscsi_initiator_allowed((void __user *)arg);
++ break;
++
++ case ADD_SESSION:
++ err = add_session((void __user *)arg);
++ break;
++
++ case DEL_SESSION:
++ err = del_session((void __user *)arg);
++ break;
++
++ case ISCSI_PARAM_SET:
++ err = iscsi_params_config((void __user *)arg, 1);
++ break;
++
++ case ISCSI_PARAM_GET:
++ err = iscsi_params_config((void __user *)arg, 0);
++ break;
++
++ case ADD_CONN:
++ err = add_conn((void __user *)arg);
++ break;
++
++ case DEL_CONN:
++ err = del_conn((void __user *)arg);
++ break;
++
++ default:
++ PRINT_ERROR("Invalid ioctl cmd %x", cmd);
++ err = -EINVAL;
++ goto out_unlock;
++ }
++
++out_unlock:
++ mutex_unlock(&target_mgmt_mutex);
++
++out:
++ TRACE_EXIT_RES(err);
++ return err;
++}
++
++static int open(struct inode *inode, struct file *file)
++{
++ bool already;
++
++ mutex_lock(&target_mgmt_mutex);
++ already = (ctr_open_state != ISCSI_CTR_OPEN_STATE_CLOSED);
++ if (!already)
++ ctr_open_state = ISCSI_CTR_OPEN_STATE_OPEN;
++ mutex_unlock(&target_mgmt_mutex);
++
++ if (already) {
++ PRINT_WARNING("%s", "Attempt to second open the control "
++ "device!");
++ return -EBUSY;
++ } else
++ return 0;
++}
++
++static int release(struct inode *inode, struct file *filp)
++{
++ struct iscsi_attr *attr, *t;
++
++ TRACE(TRACE_MGMT, "%s", "Releasing allocated resources");
++
++ mutex_lock(&target_mgmt_mutex);
++ ctr_open_state = ISCSI_CTR_OPEN_STATE_CLOSING;
++ mutex_unlock(&target_mgmt_mutex);
++
++ target_del_all();
++
++ mutex_lock(&target_mgmt_mutex);
++
++ list_for_each_entry_safe(attr, t, &iscsi_attrs_list,
++ attrs_list_entry) {
++ __iscsi_del_attr(NULL, attr);
++ }
++
++ ctr_open_state = ISCSI_CTR_OPEN_STATE_CLOSED;
++
++ mutex_unlock(&target_mgmt_mutex);
++
++ return 0;
++}
++
++const struct file_operations ctr_fops = {
++ .owner = THIS_MODULE,
++ .unlocked_ioctl = ioctl,
++ .compat_ioctl = ioctl,
++ .open = open,
++ .release = release,
++};
++
++#ifdef CONFIG_SCST_DEBUG
++static void iscsi_dump_char(int ch, unsigned char *text, int *pos)
++{
++ int i = *pos;
++
++ if (ch < 0) {
++ while ((i % 16) != 0) {
++ printk(KERN_CONT " ");
++ text[i] = ' ';
++ i++;
++ if ((i % 16) == 0)
++ printk(KERN_CONT " | %.16s |\n", text);
++ else if ((i % 4) == 0)
++ printk(KERN_CONT " |");
++ }
++ i = 0;
++ goto out;
++ }
++
++ text[i] = (ch < 0x20 || (ch >= 0x80 && ch <= 0xa0)) ? ' ' : ch;
++ printk(KERN_CONT " %02x", ch);
++ i++;
++ if ((i % 16) == 0) {
++ printk(KERN_CONT " | %.16s |\n", text);
++ i = 0;
++ } else if ((i % 4) == 0)
++ printk(KERN_CONT " |");
++
++out:
++ *pos = i;
++ return;
++}
++
++void iscsi_dump_pdu(struct iscsi_pdu *pdu)
++{
++ unsigned char text[16];
++ int pos = 0;
++
++ if (trace_flag & TRACE_D_DUMP_PDU) {
++ unsigned char *buf;
++ int i;
++
++ buf = (void *)&pdu->bhs;
++ printk(KERN_DEBUG "BHS: (%p,%zd)\n", buf, sizeof(pdu->bhs));
++ for (i = 0; i < (int)sizeof(pdu->bhs); i++)
++ iscsi_dump_char(*buf++, text, &pos);
++ iscsi_dump_char(-1, text, &pos);
++
++ buf = (void *)pdu->ahs;
++ printk(KERN_DEBUG "AHS: (%p,%d)\n", buf, pdu->ahssize);
++ for (i = 0; i < pdu->ahssize; i++)
++ iscsi_dump_char(*buf++, text, &pos);
++ iscsi_dump_char(-1, text, &pos);
++
++ printk(KERN_DEBUG "Data: (%d)\n", pdu->datasize);
++ }
++}
++
++unsigned long iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(struct iscsi_cmnd *cmnd)
++{
++ unsigned long flag;
++
++ if (cmnd->cmd_req != NULL)
++ cmnd = cmnd->cmd_req;
++
++ if (cmnd->scst_cmd == NULL)
++ flag = TRACE_MGMT_DEBUG;
++ else {
++ int status = scst_cmd_get_status(cmnd->scst_cmd);
++ if ((status == SAM_STAT_TASK_SET_FULL) ||
++ (status == SAM_STAT_BUSY))
++ flag = TRACE_FLOW_CONTROL;
++ else
++ flag = TRACE_MGMT_DEBUG;
++ }
++ return flag;
++}
++
++#endif /* CONFIG_SCST_DEBUG */
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/conn.c linux-2.6.36/drivers/scst/iscsi-scst/conn.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/conn.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/conn.c
+@@ -0,0 +1,910 @@
++/*
++ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/file.h>
++#include <linux/ip.h>
++#include <net/tcp.h>
++
++#include "iscsi.h"
++#include "digest.h"
++
++static int print_conn_state(char *p, size_t size, struct iscsi_conn *conn)
++{
++ int pos = 0;
++
++ if (conn->closing) {
++ pos += scnprintf(p, size, "%s", "closing");
++ goto out;
++ }
++
++ switch (conn->rd_state) {
++ case ISCSI_CONN_RD_STATE_PROCESSING:
++ pos += scnprintf(&p[pos], size - pos, "%s", "read_processing ");
++ break;
++ case ISCSI_CONN_RD_STATE_IN_LIST:
++ pos += scnprintf(&p[pos], size - pos, "%s", "in_read_list ");
++ break;
++ }
++
++ switch (conn->wr_state) {
++ case ISCSI_CONN_WR_STATE_PROCESSING:
++ pos += scnprintf(&p[pos], size - pos, "%s", "write_processing ");
++ break;
++ case ISCSI_CONN_WR_STATE_IN_LIST:
++ pos += scnprintf(&p[pos], size - pos, "%s", "in_write_list ");
++ break;
++ case ISCSI_CONN_WR_STATE_SPACE_WAIT:
++ pos += scnprintf(&p[pos], size - pos, "%s", "space_waiting ");
++ break;
++ }
++
++ if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags))
++ pos += scnprintf(&p[pos], size - pos, "%s", "reinstating ");
++ else if (pos == 0)
++ pos += scnprintf(&p[pos], size - pos, "%s", "established idle ");
++
++out:
++ return pos;
++}
++
++static void iscsi_conn_release(struct kobject *kobj)
++{
++ struct iscsi_conn *conn;
++
++ TRACE_ENTRY();
++
++ conn = container_of(kobj, struct iscsi_conn, conn_kobj);
++ complete_all(&conn->conn_kobj_release_cmpl);
++
++ TRACE_EXIT();
++ return;
++}
++
++struct kobj_type iscsi_conn_ktype = {
++ .release = iscsi_conn_release,
++};
++
++static ssize_t iscsi_get_initiator_ip(struct iscsi_conn *conn,
++ char *buf, int size)
++{
++ int pos;
++ struct sock *sk;
++
++ TRACE_ENTRY();
++
++ sk = conn->sock->sk;
++ switch (sk->sk_family) {
++ case AF_INET:
++ pos = scnprintf(buf, size,
++ "%pI4", &inet_sk(sk)->inet_daddr);
++ break;
++ case AF_INET6:
++ pos = scnprintf(buf, size, "[%p6]",
++ &inet6_sk(sk)->daddr);
++ break;
++ default:
++ pos = scnprintf(buf, size, "Unknown family %d",
++ sk->sk_family);
++ break;
++ }
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static ssize_t iscsi_conn_ip_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos;
++ struct iscsi_conn *conn;
++
++ TRACE_ENTRY();
++
++ conn = container_of(kobj, struct iscsi_conn, conn_kobj);
++
++ pos = iscsi_get_initiator_ip(conn, buf, SCST_SYSFS_BLOCK_SIZE);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static struct kobj_attribute iscsi_conn_ip_attr =
++ __ATTR(ip, S_IRUGO, iscsi_conn_ip_show, NULL);
++
++static ssize_t iscsi_conn_cid_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos;
++ struct iscsi_conn *conn;
++
++ TRACE_ENTRY();
++
++ conn = container_of(kobj, struct iscsi_conn, conn_kobj);
++
++ pos = sprintf(buf, "%u", conn->cid);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static struct kobj_attribute iscsi_conn_cid_attr =
++ __ATTR(cid, S_IRUGO, iscsi_conn_cid_show, NULL);
++
++static ssize_t iscsi_conn_state_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos;
++ struct iscsi_conn *conn;
++
++ TRACE_ENTRY();
++
++ conn = container_of(kobj, struct iscsi_conn, conn_kobj);
++
++ pos = print_conn_state(buf, SCST_SYSFS_BLOCK_SIZE, conn);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static struct kobj_attribute iscsi_conn_state_attr =
++ __ATTR(state, S_IRUGO, iscsi_conn_state_show, NULL);
++
++static void conn_sysfs_del(struct iscsi_conn *conn)
++{
++ int rc;
++
++ TRACE_ENTRY();
++
++ kobject_del(&conn->conn_kobj);
++ kobject_put(&conn->conn_kobj);
++
++ rc = wait_for_completion_timeout(&conn->conn_kobj_release_cmpl, HZ);
++ if (rc == 0) {
++ PRINT_INFO("Waiting for releasing sysfs entry "
++ "for conn %p (%d refs)...", conn,
++ atomic_read(&conn->conn_kobj.kref.refcount));
++ wait_for_completion(&conn->conn_kobj_release_cmpl);
++ PRINT_INFO("Done waiting for releasing sysfs "
++ "entry for conn %p", conn);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static int conn_sysfs_add(struct iscsi_conn *conn)
++{
++ int res;
++ struct iscsi_session *session = conn->session;
++ struct iscsi_conn *c;
++ int n = 1;
++ char addr[64];
++
++ TRACE_ENTRY();
++
++ iscsi_get_initiator_ip(conn, addr, sizeof(addr));
++
++restart:
++ list_for_each_entry(c, &session->conn_list, conn_list_entry) {
++ if (strcmp(addr, kobject_name(&conn->conn_kobj)) == 0) {
++ char c_addr[64];
++
++ iscsi_get_initiator_ip(conn, c_addr, sizeof(c_addr));
++
++ TRACE_DBG("Duplicated conn from the same initiator "
++ "%s found", c_addr);
++
++ snprintf(addr, sizeof(addr), "%s_%d", c_addr, n);
++ n++;
++ goto restart;
++ }
++ }
++
++ init_completion(&conn->conn_kobj_release_cmpl);
++
++ res = kobject_init_and_add(&conn->conn_kobj, &iscsi_conn_ktype,
++ scst_sysfs_get_sess_kobj(session->scst_sess), addr);
++ if (res != 0) {
++ PRINT_ERROR("Unable create sysfs entries for conn %s",
++ addr);
++ goto out;
++ }
++
++ TRACE_DBG("conn %p, conn_kobj %p", conn, &conn->conn_kobj);
++
++ res = sysfs_create_file(&conn->conn_kobj,
++ &iscsi_conn_state_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
++ iscsi_conn_state_attr.attr.name, addr);
++ goto out_err;
++ }
++
++ res = sysfs_create_file(&conn->conn_kobj,
++ &iscsi_conn_cid_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
++ iscsi_conn_cid_attr.attr.name, addr);
++ goto out_err;
++ }
++
++ res = sysfs_create_file(&conn->conn_kobj,
++ &iscsi_conn_ip_attr.attr);
++ if (res != 0) {
++ PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
++ iscsi_conn_ip_attr.attr.name, addr);
++ goto out_err;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_err:
++ conn_sysfs_del(conn);
++ goto out;
++}
++
++/* target_mutex supposed to be locked */
++struct iscsi_conn *conn_lookup(struct iscsi_session *session, u16 cid)
++{
++ struct iscsi_conn *conn;
++
++ /*
++ * We need to find the latest conn to correctly handle
++ * multi-reinstatements
++ */
++ list_for_each_entry_reverse(conn, &session->conn_list,
++ conn_list_entry) {
++ if (conn->cid == cid)
++ return conn;
++ }
++ return NULL;
++}
++
++void iscsi_make_conn_rd_active(struct iscsi_conn *conn)
++{
++ TRACE_ENTRY();
++
++ spin_lock_bh(&iscsi_rd_lock);
++
++ TRACE_DBG("conn %p, rd_state %x, rd_data_ready %d", conn,
++ conn->rd_state, conn->rd_data_ready);
++
++ /*
++ * Let's start processing ASAP not waiting for all the being waited
++ * data be received, even if we need several wakup iteration to receive
++ * them all, because starting ASAP, i.e. in parallel, is better for
++ * performance, especially on multi-CPU/core systems.
++ */
++
++ conn->rd_data_ready = 1;
++
++ if (conn->rd_state == ISCSI_CONN_RD_STATE_IDLE) {
++ list_add_tail(&conn->rd_list_entry, &iscsi_rd_list);
++ conn->rd_state = ISCSI_CONN_RD_STATE_IN_LIST;
++ wake_up(&iscsi_rd_waitQ);
++ }
++
++ spin_unlock_bh(&iscsi_rd_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++void iscsi_make_conn_wr_active(struct iscsi_conn *conn)
++{
++ TRACE_ENTRY();
++
++ spin_lock_bh(&iscsi_wr_lock);
++
++ TRACE_DBG("conn %p, wr_state %x, wr_space_ready %d", conn,
++ conn->wr_state, conn->wr_space_ready);
++
++ /*
++ * Let's start sending waiting to be sent data ASAP, even if there's
++ * still not all the needed buffers ready and we need several wakup
++ * iteration to send them all, because starting ASAP, i.e. in parallel,
++ * is better for performance, especially on multi-CPU/core systems.
++ */
++
++ if (conn->wr_state == ISCSI_CONN_WR_STATE_IDLE) {
++ list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
++ conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
++ wake_up(&iscsi_wr_waitQ);
++ }
++
++ spin_unlock_bh(&iscsi_wr_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++void __mark_conn_closed(struct iscsi_conn *conn, int flags)
++{
++ spin_lock_bh(&iscsi_rd_lock);
++ conn->closing = 1;
++ if (flags & ISCSI_CONN_ACTIVE_CLOSE)
++ conn->active_close = 1;
++ if (flags & ISCSI_CONN_DELETING)
++ conn->deleting = 1;
++ spin_unlock_bh(&iscsi_rd_lock);
++
++ iscsi_make_conn_rd_active(conn);
++}
++
++void mark_conn_closed(struct iscsi_conn *conn)
++{
++ __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE);
++}
++
++static void __iscsi_state_change(struct sock *sk)
++{
++ struct iscsi_conn *conn = sk->sk_user_data;
++
++ TRACE_ENTRY();
++
++ if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
++ if (!conn->closing) {
++ PRINT_ERROR("Connection with initiator %s "
++ "unexpectedly closed!",
++ conn->session->initiator_name);
++ TRACE_MGMT_DBG("conn %p, sk state %d", conn,
++ sk->sk_state);
++ __mark_conn_closed(conn, 0);
++ }
++ } else
++ iscsi_make_conn_rd_active(conn);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void iscsi_state_change(struct sock *sk)
++{
++ struct iscsi_conn *conn = sk->sk_user_data;
++
++ __iscsi_state_change(sk);
++ conn->old_state_change(sk);
++
++ return;
++}
++
++static void iscsi_data_ready(struct sock *sk, int len)
++{
++ struct iscsi_conn *conn = sk->sk_user_data;
++
++ TRACE_ENTRY();
++
++ iscsi_make_conn_rd_active(conn);
++
++ conn->old_data_ready(sk, len);
++
++ TRACE_EXIT();
++ return;
++}
++
++void __iscsi_write_space_ready(struct iscsi_conn *conn)
++{
++ TRACE_ENTRY();
++
++ spin_lock_bh(&iscsi_wr_lock);
++ conn->wr_space_ready = 1;
++ if ((conn->wr_state == ISCSI_CONN_WR_STATE_SPACE_WAIT)) {
++ TRACE_DBG("wr space ready (conn %p)", conn);
++ list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
++ conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
++ wake_up(&iscsi_wr_waitQ);
++ }
++ spin_unlock_bh(&iscsi_wr_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void iscsi_write_space_ready(struct sock *sk)
++{
++ struct iscsi_conn *conn = sk->sk_user_data;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Write space ready for conn %p", conn);
++
++ __iscsi_write_space_ready(conn);
++
++ conn->old_write_space(sk);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void conn_rsp_timer_fn(unsigned long arg)
++{
++ struct iscsi_conn *conn = (struct iscsi_conn *)arg;
++ struct iscsi_cmnd *cmnd;
++ unsigned long j = jiffies;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Timer (conn %p)", conn);
++
++ spin_lock_bh(&conn->write_list_lock);
++
++ if (!list_empty(&conn->write_timeout_list)) {
++ unsigned long timeout_time;
++ cmnd = list_entry(conn->write_timeout_list.next,
++ struct iscsi_cmnd, write_timeout_list_entry);
++
++ timeout_time = j + conn->rsp_timeout + ISCSI_ADD_SCHED_TIME;
++
++ if (unlikely(time_after_eq(j, cmnd->write_start +
++ conn->rsp_timeout))) {
++ if (!conn->closing) {
++ PRINT_ERROR("Timeout sending data/waiting "
++ "for reply to/from initiator "
++ "%s (SID %llx), closing connection",
++ conn->session->initiator_name,
++ (long long unsigned int)
++ conn->session->sid);
++ /*
++ * We must call mark_conn_closed() outside of
++ * write_list_lock or we will have a circular
++ * locking dependency with iscsi_rd_lock.
++ */
++ spin_unlock_bh(&conn->write_list_lock);
++ mark_conn_closed(conn);
++ goto out;
++ }
++ } else if (!timer_pending(&conn->rsp_timer) ||
++ time_after(conn->rsp_timer.expires, timeout_time)) {
++ TRACE_DBG("Restarting timer on %ld (conn %p)",
++ timeout_time, conn);
++ /*
++ * Timer might have been restarted while we were
++ * entering here.
++ *
++ * Since we have not empty write_timeout_list, we are
++ * safe to restart the timer, because we not race with
++ * del_timer_sync() in conn_free().
++ */
++ mod_timer(&conn->rsp_timer, timeout_time);
++ }
++ }
++
++ spin_unlock_bh(&conn->write_list_lock);
++
++ if (unlikely(conn->conn_tm_active)) {
++ TRACE_MGMT_DBG("TM active: making conn %p RD active", conn);
++ iscsi_make_conn_rd_active(conn);
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void conn_nop_in_delayed_work_fn(struct delayed_work *work)
++{
++ struct iscsi_conn *conn = container_of(work, struct iscsi_conn,
++ nop_in_delayed_work);
++
++ TRACE_ENTRY();
++
++ if (time_after_eq(jiffies, conn->last_rcv_time +
++ conn->nop_in_interval)) {
++ iscsi_send_nop_in(conn);
++ }
++
++ if ((conn->nop_in_interval > 0) &&
++ !test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags)) {
++ TRACE_DBG("Reschedule Nop-In work for conn %p", conn);
++ schedule_delayed_work(&conn->nop_in_delayed_work,
++ conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called from rd thread only */
++void iscsi_check_tm_data_wait_timeouts(struct iscsi_conn *conn, bool force)
++{
++ struct iscsi_cmnd *cmnd;
++ unsigned long j = jiffies;
++ bool aborted_cmds_pending;
++ unsigned long timeout_time = j + ISCSI_TM_DATA_WAIT_TIMEOUT +
++ ISCSI_ADD_SCHED_TIME;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG_FLAG(force ? TRACE_CONN_OC_DBG : TRACE_MGMT_DEBUG,
++ "j %ld (TIMEOUT %d, force %d)", j,
++ ISCSI_TM_DATA_WAIT_TIMEOUT + ISCSI_ADD_SCHED_TIME, force);
++
++ iscsi_extracheck_is_rd_thread(conn);
++
++again:
++ spin_lock_bh(&iscsi_rd_lock);
++ spin_lock(&conn->write_list_lock);
++
++ aborted_cmds_pending = false;
++ list_for_each_entry(cmnd, &conn->write_timeout_list,
++ write_timeout_list_entry) {
++ if (test_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags)) {
++ TRACE_DBG_FLAG(force ? TRACE_CONN_OC_DBG : TRACE_MGMT_DEBUG,
++ "Checking aborted cmnd %p (scst_state %d, "
++ "on_write_timeout_list %d, write_start %ld, "
++ "r2t_len_to_receive %d)", cmnd,
++ cmnd->scst_state, cmnd->on_write_timeout_list,
++ cmnd->write_start, cmnd->r2t_len_to_receive);
++ if ((cmnd->r2t_len_to_receive != 0) &&
++ (time_after_eq(j, cmnd->write_start + ISCSI_TM_DATA_WAIT_TIMEOUT) ||
++ force)) {
++ spin_unlock(&conn->write_list_lock);
++ spin_unlock_bh(&iscsi_rd_lock);
++ iscsi_fail_data_waiting_cmnd(cmnd);
++ goto again;
++ }
++ aborted_cmds_pending = true;
++ }
++ }
++
++ if (aborted_cmds_pending) {
++ if (!force &&
++ (!timer_pending(&conn->rsp_timer) ||
++ time_after(conn->rsp_timer.expires, timeout_time))) {
++ TRACE_MGMT_DBG("Mod timer on %ld (conn %p)",
++ timeout_time, conn);
++ mod_timer(&conn->rsp_timer, timeout_time);
++ }
++ } else {
++ TRACE_MGMT_DBG("Clearing conn_tm_active for conn %p", conn);
++ conn->conn_tm_active = 0;
++ }
++
++ spin_unlock(&conn->write_list_lock);
++ spin_unlock_bh(&iscsi_rd_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* target_mutex supposed to be locked */
++void conn_reinst_finished(struct iscsi_conn *conn)
++{
++ struct iscsi_cmnd *cmnd, *t;
++
++ TRACE_ENTRY();
++
++ clear_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags);
++
++ list_for_each_entry_safe(cmnd, t, &conn->reinst_pending_cmd_list,
++ reinst_pending_cmd_list_entry) {
++ TRACE_MGMT_DBG("Restarting reinst pending cmnd %p",
++ cmnd);
++
++ list_del(&cmnd->reinst_pending_cmd_list_entry);
++
++ /* Restore the state for preliminary completion/cmnd_done() */
++ cmnd->scst_state = ISCSI_CMD_STATE_AFTER_PREPROC;
++
++ iscsi_restart_cmnd(cmnd);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static void conn_activate(struct iscsi_conn *conn)
++{
++ TRACE_MGMT_DBG("Enabling conn %p", conn);
++
++ /* Catch double bind */
++ BUG_ON(conn->sock->sk->sk_state_change == iscsi_state_change);
++
++ write_lock_bh(&conn->sock->sk->sk_callback_lock);
++
++ conn->old_state_change = conn->sock->sk->sk_state_change;
++ conn->sock->sk->sk_state_change = iscsi_state_change;
++
++ conn->old_data_ready = conn->sock->sk->sk_data_ready;
++ conn->sock->sk->sk_data_ready = iscsi_data_ready;
++
++ conn->old_write_space = conn->sock->sk->sk_write_space;
++ conn->sock->sk->sk_write_space = iscsi_write_space_ready;
++
++ write_unlock_bh(&conn->sock->sk->sk_callback_lock);
++
++ /*
++ * Check, if conn was closed while we were initializing it.
++ * This function will make conn rd_active, if necessary.
++ */
++ __iscsi_state_change(conn->sock->sk);
++
++ return;
++}
++
++/*
++ * Note: the code below passes a kernel space pointer (&opt) to setsockopt()
++ * while the declaration of setsockopt specifies that it expects a user space
++ * pointer. This seems to work fine, and this approach is also used in some
++ * other parts of the Linux kernel (see e.g. fs/ocfs2/cluster/tcp.c).
++ */
++static int conn_setup_sock(struct iscsi_conn *conn)
++{
++ int res = 0;
++ int opt = 1;
++ mm_segment_t oldfs;
++ struct iscsi_session *session = conn->session;
++
++ TRACE_DBG("%llx", (long long unsigned int)session->sid);
++
++ conn->sock = SOCKET_I(conn->file->f_dentry->d_inode);
++
++ if (conn->sock->ops->sendpage == NULL) {
++ PRINT_ERROR("Socket for sid %llx doesn't support sendpage()",
++ (long long unsigned int)session->sid);
++ res = -EINVAL;
++ goto out;
++ }
++
++#if 0
++ conn->sock->sk->sk_allocation = GFP_NOIO;
++#endif
++ conn->sock->sk->sk_user_data = conn;
++
++ oldfs = get_fs();
++ set_fs(get_ds());
++ conn->sock->ops->setsockopt(conn->sock, SOL_TCP, TCP_NODELAY,
++ (void __force __user *)&opt, sizeof(opt));
++ set_fs(oldfs);
++
++out:
++ return res;
++}
++
++/* target_mutex supposed to be locked */
++int conn_free(struct iscsi_conn *conn)
++{
++ struct iscsi_session *session = conn->session;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Freeing conn %p (sess=%p, %#Lx %u)", conn,
++ session, (long long unsigned int)session->sid, conn->cid);
++
++ del_timer_sync(&conn->rsp_timer);
++
++ conn_sysfs_del(conn);
++
++ BUG_ON(atomic_read(&conn->conn_ref_cnt) != 0);
++ BUG_ON(!list_empty(&conn->cmd_list));
++ BUG_ON(!list_empty(&conn->write_list));
++ BUG_ON(!list_empty(&conn->write_timeout_list));
++ BUG_ON(conn->conn_reinst_successor != NULL);
++ BUG_ON(!test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags));
++
++ /* Just in case if new conn gets freed before the old one */
++ if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags)) {
++ struct iscsi_conn *c;
++ TRACE_MGMT_DBG("Freeing being reinstated conn %p", conn);
++ list_for_each_entry(c, &session->conn_list,
++ conn_list_entry) {
++ if (c->conn_reinst_successor == conn) {
++ c->conn_reinst_successor = NULL;
++ break;
++ }
++ }
++ }
++
++ list_del(&conn->conn_list_entry);
++
++ fput(conn->file);
++ conn->file = NULL;
++ conn->sock = NULL;
++
++ free_page((unsigned long)conn->read_iov);
++
++ kfree(conn);
++
++ if (list_empty(&session->conn_list)) {
++ BUG_ON(session->sess_reinst_successor != NULL);
++ session_free(session, true);
++ }
++
++ return 0;
++}
++
++/* target_mutex supposed to be locked */
++static int iscsi_conn_alloc(struct iscsi_session *session,
++ struct iscsi_kern_conn_info *info, struct iscsi_conn **new_conn)
++{
++ struct iscsi_conn *conn;
++ int res = 0;
++
++ conn = kzalloc(sizeof(*conn), GFP_KERNEL);
++ if (!conn) {
++ res = -ENOMEM;
++ goto out_err;
++ }
++
++ TRACE_MGMT_DBG("Creating connection %p for sid %#Lx, cid %u", conn,
++ (long long unsigned int)session->sid, info->cid);
++
++ /* Changing it, change ISCSI_CONN_IOV_MAX as well !! */
++ conn->read_iov = (struct iovec *)get_zeroed_page(GFP_KERNEL);
++ if (conn->read_iov == NULL) {
++ res = -ENOMEM;
++ goto out_err_free_conn;
++ }
++
++ atomic_set(&conn->conn_ref_cnt, 0);
++ conn->session = session;
++ if (session->sess_reinstating)
++ __set_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags);
++ conn->cid = info->cid;
++ conn->stat_sn = info->stat_sn;
++ conn->exp_stat_sn = info->exp_stat_sn;
++ conn->rd_state = ISCSI_CONN_RD_STATE_IDLE;
++ conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
++
++ conn->hdigest_type = session->sess_params.header_digest;
++ conn->ddigest_type = session->sess_params.data_digest;
++ res = digest_init(conn);
++ if (res != 0)
++ goto out_free_iov;
++
++ conn->target = session->target;
++ spin_lock_init(&conn->cmd_list_lock);
++ INIT_LIST_HEAD(&conn->cmd_list);
++ spin_lock_init(&conn->write_list_lock);
++ INIT_LIST_HEAD(&conn->write_list);
++ INIT_LIST_HEAD(&conn->write_timeout_list);
++ setup_timer(&conn->rsp_timer, conn_rsp_timer_fn, (unsigned long)conn);
++ init_waitqueue_head(&conn->read_state_waitQ);
++ init_completion(&conn->ready_to_free);
++ INIT_LIST_HEAD(&conn->reinst_pending_cmd_list);
++ INIT_LIST_HEAD(&conn->nop_req_list);
++ spin_lock_init(&conn->nop_req_list_lock);
++
++ conn->nop_in_ttt = 0;
++ INIT_DELAYED_WORK(&conn->nop_in_delayed_work,
++ (void (*)(struct work_struct *))conn_nop_in_delayed_work_fn);
++ conn->last_rcv_time = jiffies;
++ conn->rsp_timeout = session->tgt_params.rsp_timeout * HZ;
++ conn->nop_in_interval = session->tgt_params.nop_in_interval * HZ;
++ if (conn->nop_in_interval > 0) {
++ TRACE_DBG("Schedule Nop-In work for conn %p", conn);
++ schedule_delayed_work(&conn->nop_in_delayed_work,
++ conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
++ }
++
++ conn->file = fget(info->fd);
++
++ res = conn_setup_sock(conn);
++ if (res != 0)
++ goto out_fput;
++
++ res = conn_sysfs_add(conn);
++ if (res != 0)
++ goto out_fput;
++
++ list_add_tail(&conn->conn_list_entry, &session->conn_list);
++
++ *new_conn = conn;
++
++out:
++ return res;
++
++out_fput:
++ fput(conn->file);
++
++out_free_iov:
++ free_page((unsigned long)conn->read_iov);
++
++out_err_free_conn:
++ kfree(conn);
++
++out_err:
++ goto out;
++}
++
++/* target_mutex supposed to be locked */
++int __add_conn(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
++{
++ struct iscsi_conn *conn, *new_conn = NULL;
++ int err;
++ bool reinstatement = false;
++
++ conn = conn_lookup(session, info->cid);
++ if ((conn != NULL) &&
++ !test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags)) {
++ /* conn reinstatement */
++ reinstatement = true;
++ } else if (!list_empty(&session->conn_list)) {
++ err = -EEXIST;
++ goto out;
++ }
++
++ err = iscsi_conn_alloc(session, info, &new_conn);
++ if (err != 0)
++ goto out;
++
++ if (reinstatement) {
++ TRACE_MGMT_DBG("Reinstating conn (old %p, new %p)", conn,
++ new_conn);
++ conn->conn_reinst_successor = new_conn;
++ __set_bit(ISCSI_CONN_REINSTATING, &new_conn->conn_aflags);
++ __mark_conn_closed(conn, 0);
++ }
++
++ conn_activate(new_conn);
++
++out:
++ return err;
++}
++
++/* target_mutex supposed to be locked */
++int __del_conn(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
++{
++ struct iscsi_conn *conn;
++ int err = -EEXIST;
++
++ conn = conn_lookup(session, info->cid);
++ if (!conn) {
++ PRINT_WARNING("Connection %d not found", info->cid);
++ return err;
++ }
++
++ PRINT_INFO("Deleting connection with initiator %s (%p)",
++ conn->session->initiator_name, conn);
++
++ __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE|ISCSI_CONN_DELETING);
++
++ return 0;
++}
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++
++void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn)
++{
++ if (unlikely(current != conn->rd_task)) {
++ printk(KERN_EMERG "conn %p rd_task != current %p (pid %d)\n",
++ conn, current, current->pid);
++ while (in_softirq())
++ local_bh_enable();
++ printk(KERN_EMERG "rd_state %x\n", conn->rd_state);
++ printk(KERN_EMERG "rd_task %p\n", conn->rd_task);
++ printk(KERN_EMERG "rd_task->pid %d\n", conn->rd_task->pid);
++ BUG();
++ }
++}
++
++void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn)
++{
++ if (unlikely(current != conn->wr_task)) {
++ printk(KERN_EMERG "conn %p wr_task != current %p (pid %d)\n",
++ conn, current, current->pid);
++ while (in_softirq())
++ local_bh_enable();
++ printk(KERN_EMERG "wr_state %x\n", conn->wr_state);
++ printk(KERN_EMERG "wr_task %p\n", conn->wr_task);
++ printk(KERN_EMERG "wr_task->pid %d\n", conn->wr_task->pid);
++ BUG();
++ }
++}
++
++#endif /* CONFIG_SCST_EXTRACHECKS */
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/digest.c linux-2.6.36/drivers/scst/iscsi-scst/digest.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/digest.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/digest.c
+@@ -0,0 +1,244 @@
++/*
++ * iSCSI digest handling.
++ *
++ * Copyright (C) 2004 - 2006 Xiranet Communications GmbH
++ * <arne.redlich@xiranet.com>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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.
++ *
++ * 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.
++ */
++
++#include <linux/types.h>
++#include <linux/scatterlist.h>
++
++#include "iscsi.h"
++#include "digest.h"
++#include <linux/crc32c.h>
++
++void digest_alg_available(int *val)
++{
++#if defined(CONFIG_LIBCRC32C_MODULE) || defined(CONFIG_LIBCRC32C)
++ int crc32c = 1;
++#else
++ int crc32c = 0;
++#endif
++
++ if ((*val & DIGEST_CRC32C) && !crc32c) {
++ PRINT_ERROR("%s", "CRC32C digest algorithm not available "
++ "in kernel");
++ *val |= ~DIGEST_CRC32C;
++ }
++}
++
++/**
++ * initialize support for digest calculation.
++ *
++ * digest_init -
++ * @conn: ptr to connection to make use of digests
++ *
++ * @return: 0 on success, < 0 on error
++ */
++int digest_init(struct iscsi_conn *conn)
++{
++ if (!(conn->hdigest_type & DIGEST_ALL))
++ conn->hdigest_type = DIGEST_NONE;
++
++ if (!(conn->ddigest_type & DIGEST_ALL))
++ conn->ddigest_type = DIGEST_NONE;
++
++ return 0;
++}
++
++static __be32 evaluate_crc32_from_sg(struct scatterlist *sg, int nbytes,
++ uint32_t padding)
++{
++ u32 crc = ~0;
++ int pad_bytes = ((nbytes + 3) & -4) - nbytes;
++
++#ifdef CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES
++ if (((scst_random() % 100000) == 752)) {
++ PRINT_INFO("%s", "Simulating digest failure");
++ return 0;
++ }
++#endif
++
++#if defined(CONFIG_LIBCRC32C_MODULE) || defined(CONFIG_LIBCRC32C)
++ while (nbytes > 0) {
++ int d = min(nbytes, (int)(sg->length));
++ crc = crc32c(crc, sg_virt(sg), d);
++ nbytes -= d;
++ sg++;
++ }
++
++ if (pad_bytes)
++ crc = crc32c(crc, (u8 *)&padding, pad_bytes);
++#endif
++
++ return (__force __be32)~cpu_to_le32(crc);
++}
++
++static __be32 digest_header(struct iscsi_pdu *pdu)
++{
++ struct scatterlist sg[2];
++ unsigned int nbytes = sizeof(struct iscsi_hdr);
++ int asize = (pdu->ahssize + 3) & -4;
++
++ sg_init_table(sg, 2);
++
++ sg_set_buf(&sg[0], &pdu->bhs, nbytes);
++ if (pdu->ahssize) {
++ sg_set_buf(&sg[1], pdu->ahs, asize);
++ nbytes += asize;
++ }
++ EXTRACHECKS_BUG_ON((nbytes & 3) != 0);
++ return evaluate_crc32_from_sg(sg, nbytes, 0);
++}
++
++static __be32 digest_data(struct iscsi_cmnd *cmd, u32 size, u32 offset,
++ uint32_t padding)
++{
++ struct scatterlist *sg = cmd->sg;
++ int idx, count;
++ struct scatterlist saved_sg;
++ __be32 crc;
++
++ offset += sg[0].offset;
++ idx = offset >> PAGE_SHIFT;
++ offset &= ~PAGE_MASK;
++
++ count = get_pgcnt(size, offset);
++
++ TRACE_DBG("req %p, idx %d, count %d, sg_cnt %d, size %d, "
++ "offset %d", cmd, idx, count, cmd->sg_cnt, size, offset);
++ BUG_ON(idx + count > cmd->sg_cnt);
++
++ saved_sg = sg[idx];
++ sg[idx].offset = offset;
++ sg[idx].length -= offset - saved_sg.offset;
++
++ crc = evaluate_crc32_from_sg(sg + idx, size, padding);
++
++ sg[idx] = saved_sg;
++ return crc;
++}
++
++int digest_rx_header(struct iscsi_cmnd *cmnd)
++{
++ __be32 crc;
++
++ crc = digest_header(&cmnd->pdu);
++ if (unlikely(crc != cmnd->hdigest)) {
++ PRINT_ERROR("%s", "RX header digest failed");
++ return -EIO;
++ } else
++ TRACE_DBG("RX header digest OK for cmd %p", cmnd);
++
++ return 0;
++}
++
++void digest_tx_header(struct iscsi_cmnd *cmnd)
++{
++ cmnd->hdigest = digest_header(&cmnd->pdu);
++ TRACE_DBG("TX header digest for cmd %p: %x", cmnd, cmnd->hdigest);
++}
++
++int digest_rx_data(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_cmnd *req;
++ struct iscsi_data_out_hdr *req_hdr;
++ u32 offset;
++ __be32 crc;
++ int res = 0;
++
++ switch (cmnd_opcode(cmnd)) {
++ case ISCSI_OP_SCSI_DATA_OUT:
++ req = cmnd->cmd_req;
++ if (unlikely(req == NULL)) {
++ /* It can be for prelim completed commands */
++ req = cmnd;
++ goto out;
++ }
++ req_hdr = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs;
++ offset = be32_to_cpu(req_hdr->buffer_offset);
++ break;
++
++ default:
++ req = cmnd;
++ offset = 0;
++ }
++
++ /*
++ * We need to skip the digest check for prelim completed commands,
++ * because we use shared data buffer for them, so, most likely, the
++ * check will fail. Plus, for such commands we sometimes don't have
++ * sg_cnt set correctly (cmnd_prepare_get_rejected_cmd_data() doesn't
++ * do it).
++ */
++ if (unlikely(req->prelim_compl_flags != 0))
++ goto out;
++
++ /*
++ * Temporary to not crash with write residual overflows. ToDo. Until
++ * that let's always have succeeded data digests for such overflows.
++ * In ideal, we should allocate additional one or more sg's for the
++ * overflowed data and free them here or on req release. It's quite
++ * not trivial for such virtually never used case, so let's do it,
++ * when it gets needed.
++ */
++ if (unlikely(offset + cmnd->pdu.datasize > req->bufflen)) {
++ PRINT_WARNING("Skipping RX data digest check for residual "
++ "overflow command op %x (data size %d, buffer size %d)",
++ cmnd_hdr(req)->scb[0], offset + cmnd->pdu.datasize,
++ req->bufflen);
++ goto out;
++ }
++
++ crc = digest_data(req, cmnd->pdu.datasize, offset,
++ cmnd->conn->rpadding);
++
++ if (unlikely(crc != cmnd->ddigest)) {
++ TRACE(TRACE_MINOR|TRACE_MGMT_DEBUG, "%s", "RX data digest "
++ "failed");
++ TRACE_MGMT_DBG("Calculated crc %x, ddigest %x, offset %d", crc,
++ cmnd->ddigest, offset);
++ iscsi_dump_pdu(&cmnd->pdu);
++ res = -EIO;
++ } else
++ TRACE_DBG("RX data digest OK for cmd %p", cmnd);
++
++out:
++ return res;
++}
++
++void digest_tx_data(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_data_in_hdr *hdr;
++ u32 offset;
++
++ TRACE_DBG("%s:%d req %p, own_sg %d, sg %p, sgcnt %d cmnd %p, "
++ "own_sg %d, sg %p, sgcnt %d", __func__, __LINE__,
++ cmnd->parent_req, cmnd->parent_req->own_sg,
++ cmnd->parent_req->sg, cmnd->parent_req->sg_cnt,
++ cmnd, cmnd->own_sg, cmnd->sg, cmnd->sg_cnt);
++
++ switch (cmnd_opcode(cmnd)) {
++ case ISCSI_OP_SCSI_DATA_IN:
++ hdr = (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs;
++ offset = be32_to_cpu(hdr->buffer_offset);
++ break;
++ default:
++ offset = 0;
++ }
++
++ cmnd->ddigest = digest_data(cmnd, cmnd->pdu.datasize, offset, 0);
++ TRACE_DBG("TX data digest for cmd %p: %x (offset %d, opcode %x)", cmnd,
++ cmnd->ddigest, offset, cmnd_opcode(cmnd));
++}
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/digest.h linux-2.6.36/drivers/scst/iscsi-scst/digest.h
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/digest.h
++++ linux-2.6.36/drivers/scst/iscsi-scst/digest.h
+@@ -0,0 +1,31 @@
++/*
++ * iSCSI digest handling.
++ *
++ * Copyright (C) 2004 Xiranet Communications GmbH <arne.redlich@xiranet.com>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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.
++ *
++ * 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.
++ */
++
++#ifndef __ISCSI_DIGEST_H__
++#define __ISCSI_DIGEST_H__
++
++extern void digest_alg_available(int *val);
++
++extern int digest_init(struct iscsi_conn *conn);
++
++extern int digest_rx_header(struct iscsi_cmnd *cmnd);
++extern int digest_rx_data(struct iscsi_cmnd *cmnd);
++
++extern void digest_tx_header(struct iscsi_cmnd *cmnd);
++extern void digest_tx_data(struct iscsi_cmnd *cmnd);
++
++#endif /* __ISCSI_DIGEST_H__ */
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/event.c linux-2.6.36/drivers/scst/iscsi-scst/event.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/event.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/event.c
+@@ -0,0 +1,165 @@
++/*
++ * Event notification code.
++ *
++ * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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.
++ *
++ * 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.
++ *
++ */
++
++#include <net/tcp.h>
++#include <scst/iscsi_scst.h>
++#include "iscsi.h"
++
++static struct sock *nl;
++static u32 iscsid_pid;
++
++static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
++{
++ u32 uid, pid, seq;
++ char *data;
++
++ pid = NETLINK_CREDS(skb)->pid;
++ uid = NETLINK_CREDS(skb)->uid;
++ seq = nlh->nlmsg_seq;
++ data = NLMSG_DATA(nlh);
++
++ iscsid_pid = pid;
++
++ return 0;
++}
++
++static void event_recv_skb(struct sk_buff *skb)
++{
++ int err;
++ struct nlmsghdr *nlh;
++ u32 rlen;
++
++ while (skb->len >= NLMSG_SPACE(0)) {
++ nlh = (struct nlmsghdr *)skb->data;
++ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
++ goto out;
++ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
++ if (rlen > skb->len)
++ rlen = skb->len;
++ err = event_recv_msg(skb, nlh);
++ if (err)
++ netlink_ack(skb, nlh, -err);
++ else if (nlh->nlmsg_flags & NLM_F_ACK)
++ netlink_ack(skb, nlh, 0);
++ skb_pull(skb, rlen);
++ }
++
++out:
++ return;
++}
++
++/* event_mutex supposed to be held */
++static int __event_send(const void *buf, int buf_len)
++{
++ int res = 0, len;
++ struct sk_buff *skb;
++ struct nlmsghdr *nlh;
++ static u32 seq; /* protected by event_mutex */
++
++ TRACE_ENTRY();
++
++ if (ctr_open_state != ISCSI_CTR_OPEN_STATE_OPEN)
++ goto out;
++
++ len = NLMSG_SPACE(buf_len);
++
++ skb = alloc_skb(NLMSG_SPACE(len), GFP_KERNEL);
++ if (skb == NULL) {
++ PRINT_ERROR("alloc_skb() failed (len %d)", len);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ nlh = __nlmsg_put(skb, iscsid_pid, seq++, NLMSG_DONE,
++ len - sizeof(*nlh), 0);
++
++ memcpy(NLMSG_DATA(nlh), buf, buf_len);
++ res = netlink_unicast(nl, skb, iscsid_pid, 0);
++ if (res <= 0) {
++ if (res != -ECONNREFUSED)
++ PRINT_ERROR("netlink_unicast() failed: %d", res);
++ else
++ TRACE(TRACE_MINOR, "netlink_unicast() failed: %s. "
++ "Not functioning user space?",
++ "Connection refused");
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++int event_send(u32 tid, u64 sid, u32 cid, u32 cookie,
++ enum iscsi_kern_event_code code,
++ const char *param1, const char *param2)
++{
++ int err;
++ static DEFINE_MUTEX(event_mutex);
++ struct iscsi_kern_event event;
++ int param1_size, param2_size;
++
++ param1_size = (param1 != NULL) ? strlen(param1) : 0;
++ param2_size = (param2 != NULL) ? strlen(param2) : 0;
++
++ event.tid = tid;
++ event.sid = sid;
++ event.cid = cid;
++ event.code = code;
++ event.cookie = cookie;
++ event.param1_size = param1_size;
++ event.param2_size = param2_size;
++
++ mutex_lock(&event_mutex);
++
++ err = __event_send(&event, sizeof(event));
++ if (err <= 0)
++ goto out_unlock;
++
++ if (param1_size > 0) {
++ err = __event_send(param1, param1_size);
++ if (err <= 0)
++ goto out_unlock;
++ }
++
++ if (param2_size > 0) {
++ err = __event_send(param2, param2_size);
++ if (err <= 0)
++ goto out_unlock;
++ }
++
++out_unlock:
++ mutex_unlock(&event_mutex);
++ return err;
++}
++
++int __init event_init(void)
++{
++ nl = netlink_kernel_create(&init_net, NETLINK_ISCSI_SCST, 1,
++ event_recv_skb, NULL, THIS_MODULE);
++ if (!nl) {
++ PRINT_ERROR("%s", "netlink_kernel_create() failed");
++ return -ENOMEM;
++ } else
++ return 0;
++}
++
++void event_exit(void)
++{
++ netlink_kernel_release(nl);
++}
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/iscsi.c linux-2.6.36/drivers/scst/iscsi-scst/iscsi.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/iscsi.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/iscsi.c
+@@ -0,0 +1,3956 @@
++/*
++ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/hash.h>
++#include <linux/kthread.h>
++#include <linux/scatterlist.h>
++#include <linux/ctype.h>
++#include <net/tcp.h>
++#include <scsi/scsi.h>
++#include <asm/byteorder.h>
++#include <asm/unaligned.h>
++
++#include "iscsi.h"
++#include "digest.h"
++
++#ifndef GENERATING_UPSTREAM_PATCH
++#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++#warning "Patch put_page_callback-<kernel-version>.patch not applied on your\
++ kernel or CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION\
++ config option not set. ISCSI-SCST will be working with not the best\
++ performance. Refer README file for details."
++#endif
++#endif
++
++#define ISCSI_INIT_WRITE_WAKE 0x1
++
++static int ctr_major;
++static char ctr_name[] = "iscsi-scst-ctl";
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++unsigned long iscsi_trace_flag = ISCSI_DEFAULT_LOG_FLAGS;
++#endif
++
++static struct kmem_cache *iscsi_cmnd_cache;
++
++DEFINE_SPINLOCK(iscsi_rd_lock);
++LIST_HEAD(iscsi_rd_list);
++DECLARE_WAIT_QUEUE_HEAD(iscsi_rd_waitQ);
++
++DEFINE_SPINLOCK(iscsi_wr_lock);
++LIST_HEAD(iscsi_wr_list);
++DECLARE_WAIT_QUEUE_HEAD(iscsi_wr_waitQ);
++
++static struct page *dummy_page;
++static struct scatterlist dummy_sg;
++
++struct iscsi_thread_t {
++ struct task_struct *thr;
++ struct list_head threads_list_entry;
++};
++
++static LIST_HEAD(iscsi_threads_list);
++
++static void cmnd_remove_data_wait_hash(struct iscsi_cmnd *cmnd);
++static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status);
++static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess);
++static void req_cmnd_release(struct iscsi_cmnd *req);
++static int cmnd_insert_data_wait_hash(struct iscsi_cmnd *cmnd);
++static void __cmnd_abort(struct iscsi_cmnd *cmnd);
++static void iscsi_cmnd_init_write(struct iscsi_cmnd *rsp, int flags);
++static void iscsi_set_resid_no_scst_cmd(struct iscsi_cmnd *rsp);
++static void iscsi_set_resid(struct iscsi_cmnd *rsp);
++
++static void iscsi_set_not_received_data_len(struct iscsi_cmnd *req,
++ unsigned int not_received)
++{
++ req->not_received_data_len = not_received;
++ if (req->scst_cmd != NULL)
++ scst_cmd_set_write_not_received_data_len(req->scst_cmd,
++ not_received);
++ return;
++}
++
++static void req_del_from_write_timeout_list(struct iscsi_cmnd *req)
++{
++ struct iscsi_conn *conn;
++
++ TRACE_ENTRY();
++
++ if (!req->on_write_timeout_list)
++ goto out;
++
++ conn = req->conn;
++
++ TRACE_DBG("Deleting cmd %p from conn %p write_timeout_list",
++ req, conn);
++
++ spin_lock_bh(&conn->write_list_lock);
++
++ /* Recheck, since it can be changed behind us */
++ if (unlikely(!req->on_write_timeout_list))
++ goto out_unlock;
++
++ list_del(&req->write_timeout_list_entry);
++ req->on_write_timeout_list = 0;
++
++out_unlock:
++ spin_unlock_bh(&conn->write_list_lock);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static inline u32 cmnd_write_size(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
++
++ if (hdr->flags & ISCSI_CMD_WRITE)
++ return be32_to_cpu(hdr->data_length);
++ return 0;
++}
++
++static inline int cmnd_read_size(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
++
++ if (hdr->flags & ISCSI_CMD_READ) {
++ struct iscsi_ahs_hdr *ahdr;
++
++ if (!(hdr->flags & ISCSI_CMD_WRITE))
++ return be32_to_cpu(hdr->data_length);
++
++ ahdr = (struct iscsi_ahs_hdr *)cmnd->pdu.ahs;
++ if (ahdr != NULL) {
++ uint8_t *p = (uint8_t *)ahdr;
++ unsigned int size = 0;
++ do {
++ int s;
++
++ ahdr = (struct iscsi_ahs_hdr *)p;
++
++ if (ahdr->ahstype == ISCSI_AHSTYPE_RLENGTH) {
++ struct iscsi_rlength_ahdr *rh =
++ (struct iscsi_rlength_ahdr *)ahdr;
++ return be32_to_cpu(rh->read_length);
++ }
++
++ s = 3 + be16_to_cpu(ahdr->ahslength);
++ s = (s + 3) & -4;
++ size += s;
++ p += s;
++ } while (size < cmnd->pdu.ahssize);
++ }
++ return -1;
++ }
++ return 0;
++}
++
++void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd)
++{
++ int status;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(cmnd->r2t_len_to_receive != 0);
++ EXTRACHECKS_BUG_ON(cmnd->r2t_len_to_send != 0);
++
++ req_del_from_write_timeout_list(cmnd);
++
++ /*
++ * Let's remove cmnd from the hash earlier to keep it smaller.
++ * Also we have to remove hashed req from the hash before sending
++ * response. Otherwise we can have a race, when for some reason cmd's
++ * release (and, hence, removal from the hash) is delayed after the
++ * transmission and initiator sends cmd with the same ITT, hence
++ * the new command will be erroneously rejected as a duplicate.
++ */
++ if (cmnd->hashed)
++ cmnd_remove_data_wait_hash(cmnd);
++
++ if (unlikely(test_bit(ISCSI_CONN_REINSTATING,
++ &cmnd->conn->conn_aflags))) {
++ struct iscsi_target *target = cmnd->conn->session->target;
++ bool get_out;
++
++ mutex_lock(&target->target_mutex);
++
++ get_out = test_bit(ISCSI_CONN_REINSTATING,
++ &cmnd->conn->conn_aflags);
++ /* Let's don't look dead */
++ if (scst_cmd_get_cdb(cmnd->scst_cmd)[0] == TEST_UNIT_READY)
++ get_out = false;
++
++ if (!get_out)
++ goto unlock_cont;
++
++ TRACE_MGMT_DBG("Pending cmnd %p, because conn %p is "
++ "reinstated", cmnd, cmnd->conn);
++
++ cmnd->scst_state = ISCSI_CMD_STATE_REINST_PENDING;
++ list_add_tail(&cmnd->reinst_pending_cmd_list_entry,
++ &cmnd->conn->reinst_pending_cmd_list);
++
++unlock_cont:
++ mutex_unlock(&target->target_mutex);
++
++ if (get_out)
++ goto out;
++ }
++
++ if (unlikely(cmnd->prelim_compl_flags != 0)) {
++ if (test_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags)) {
++ TRACE_MGMT_DBG("cmnd %p (scst_cmd %p) aborted", cmnd,
++ cmnd->scst_cmd);
++ req_cmnd_release_force(cmnd);
++ goto out;
++ }
++
++ if (cmnd->scst_cmd == NULL) {
++ TRACE_MGMT_DBG("Finishing preliminary completed cmd %p "
++ "with NULL scst_cmd", cmnd);
++ req_cmnd_release(cmnd);
++ goto out;
++ }
++
++ status = SCST_PREPROCESS_STATUS_ERROR_SENSE_SET;
++ } else
++ status = SCST_PREPROCESS_STATUS_SUCCESS;
++
++ cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED;
++
++ scst_restart_cmd(cmnd->scst_cmd, status, SCST_CONTEXT_THREAD);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static struct iscsi_cmnd *iscsi_create_tm_clone(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_cmnd *tm_clone;
++
++ TRACE_ENTRY();
++
++ tm_clone = cmnd_alloc(cmnd->conn, NULL);
++ if (tm_clone != NULL) {
++ set_bit(ISCSI_CMD_ABORTED, &tm_clone->prelim_compl_flags);
++ tm_clone->pdu = cmnd->pdu;
++
++ TRACE_MGMT_DBG("TM clone %p for cmnd %p created",
++ tm_clone, cmnd);
++ } else
++ PRINT_ERROR("Failed to create TM clone for cmnd %p", cmnd);
++
++ TRACE_EXIT_HRES((unsigned long)tm_clone);
++ return tm_clone;
++}
++
++void iscsi_fail_data_waiting_cmnd(struct iscsi_cmnd *cmnd)
++{
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Failing data waiting cmnd %p", cmnd);
++
++ /*
++ * There is no race with conn_abort(), since all functions
++ * called from single read thread
++ */
++ iscsi_extracheck_is_rd_thread(cmnd->conn);
++
++ /* This cmnd is going to die without response */
++ cmnd->r2t_len_to_receive = 0;
++ cmnd->r2t_len_to_send = 0;
++
++ if (cmnd->pending) {
++ struct iscsi_session *session = cmnd->conn->session;
++ struct iscsi_cmnd *tm_clone;
++
++ TRACE_MGMT_DBG("Unpending cmnd %p (sn %u, exp_cmd_sn %u)", cmnd,
++ cmnd->pdu.bhs.sn, session->exp_cmd_sn);
++
++ /*
++ * If cmnd is pending, then the next command, if any, must be
++ * pending too. So, just insert a clone instead of cmnd to
++ * fill the hole in SNs. Then we can release cmnd.
++ */
++
++ tm_clone = iscsi_create_tm_clone(cmnd);
++
++ spin_lock(&session->sn_lock);
++
++ if (tm_clone != NULL) {
++ TRACE_MGMT_DBG("Adding tm_clone %p after its cmnd",
++ tm_clone);
++ list_add(&tm_clone->pending_list_entry,
++ &cmnd->pending_list_entry);
++ }
++
++ list_del(&cmnd->pending_list_entry);
++ cmnd->pending = 0;
++
++ spin_unlock(&session->sn_lock);
++ }
++
++ req_cmnd_release_force(cmnd);
++
++ TRACE_EXIT();
++ return;
++}
++
++struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *conn,
++ struct iscsi_cmnd *parent)
++{
++ struct iscsi_cmnd *cmnd;
++
++ /* ToDo: __GFP_NOFAIL?? */
++ cmnd = kmem_cache_zalloc(iscsi_cmnd_cache, GFP_KERNEL|__GFP_NOFAIL);
++
++ atomic_set(&cmnd->ref_cnt, 1);
++ cmnd->scst_state = ISCSI_CMD_STATE_NEW;
++ cmnd->conn = conn;
++ cmnd->parent_req = parent;
++
++ if (parent == NULL) {
++ conn_get(conn);
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ atomic_set(&cmnd->net_ref_cnt, 0);
++#endif
++ INIT_LIST_HEAD(&cmnd->rsp_cmd_list);
++ INIT_LIST_HEAD(&cmnd->rx_ddigest_cmd_list);
++ cmnd->target_task_tag = ISCSI_RESERVED_TAG_CPU32;
++
++ spin_lock_bh(&conn->cmd_list_lock);
++ list_add_tail(&cmnd->cmd_list_entry, &conn->cmd_list);
++ spin_unlock_bh(&conn->cmd_list_lock);
++ }
++
++ TRACE_DBG("conn %p, parent %p, cmnd %p", conn, parent, cmnd);
++ return cmnd;
++}
++
++/* Frees a command. Also frees the additional header. */
++static void cmnd_free(struct iscsi_cmnd *cmnd)
++{
++ TRACE_ENTRY();
++
++ TRACE_DBG("cmnd %p", cmnd);
++
++ if (unlikely(test_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags))) {
++ TRACE_MGMT_DBG("Free aborted cmd %p (scst cmd %p, state %d, "
++ "parent_req %p)", cmnd, cmnd->scst_cmd,
++ cmnd->scst_state, cmnd->parent_req);
++ }
++
++ /* Catch users from cmd_list or rsp_cmd_list */
++ EXTRACHECKS_BUG_ON(atomic_read(&cmnd->ref_cnt) != 0);
++
++ kfree(cmnd->pdu.ahs);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (unlikely(cmnd->on_write_list || cmnd->on_write_timeout_list)) {
++ struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
++
++ PRINT_CRIT_ERROR("cmnd %p still on some list?, %x, %x, %x, "
++ "%x, %x, %x, %x", cmnd, req->opcode, req->scb[0],
++ req->flags, req->itt, be32_to_cpu(req->data_length),
++ req->cmd_sn, be32_to_cpu((__force __be32)(cmnd->pdu.datasize)));
++
++ if (unlikely(cmnd->parent_req)) {
++ struct iscsi_scsi_cmd_hdr *preq =
++ cmnd_hdr(cmnd->parent_req);
++ PRINT_CRIT_ERROR("%p %x %u", preq, preq->opcode,
++ preq->scb[0]);
++ }
++ BUG();
++ }
++#endif
++
++ kmem_cache_free(iscsi_cmnd_cache, cmnd);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void iscsi_dec_active_cmds(struct iscsi_cmnd *req)
++{
++ struct iscsi_session *sess = req->conn->session;
++
++ TRACE_DBG("Decrementing active_cmds (req %p, sess %p, "
++ "new value %d)", req, sess,
++ atomic_read(&sess->active_cmds)-1);
++
++ EXTRACHECKS_BUG_ON(!req->dec_active_cmds);
++
++ atomic_dec(&sess->active_cmds);
++ smp_mb__after_atomic_dec();
++ req->dec_active_cmds = 0;
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (unlikely(atomic_read(&sess->active_cmds) < 0)) {
++ PRINT_CRIT_ERROR("active_cmds < 0 (%d)!!",
++ atomic_read(&sess->active_cmds));
++ BUG();
++ }
++#endif
++ return;
++}
++
++/* Might be called under some lock and on SIRQ */
++void cmnd_done(struct iscsi_cmnd *cmnd)
++{
++ TRACE_ENTRY();
++
++ TRACE_DBG("cmnd %p", cmnd);
++
++ if (unlikely(test_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags))) {
++ TRACE_MGMT_DBG("Done aborted cmd %p (scst cmd %p, state %d, "
++ "parent_req %p)", cmnd, cmnd->scst_cmd,
++ cmnd->scst_state, cmnd->parent_req);
++ }
++
++ EXTRACHECKS_BUG_ON(cmnd->on_rx_digest_list);
++ EXTRACHECKS_BUG_ON(cmnd->hashed);
++
++ req_del_from_write_timeout_list(cmnd);
++
++ if (cmnd->parent_req == NULL) {
++ struct iscsi_conn *conn = cmnd->conn;
++ struct iscsi_cmnd *rsp, *t;
++
++ TRACE_DBG("Deleting req %p from conn %p", cmnd, conn);
++
++ spin_lock_bh(&conn->cmd_list_lock);
++ list_del(&cmnd->cmd_list_entry);
++ spin_unlock_bh(&conn->cmd_list_lock);
++
++ conn_put(conn);
++
++ EXTRACHECKS_BUG_ON(!list_empty(&cmnd->rx_ddigest_cmd_list));
++
++ /* Order between above and below code is important! */
++
++ if ((cmnd->scst_cmd != NULL) || (cmnd->scst_aen != NULL)) {
++ switch (cmnd->scst_state) {
++ case ISCSI_CMD_STATE_PROCESSED:
++ TRACE_DBG("cmd %p PROCESSED", cmnd);
++ scst_tgt_cmd_done(cmnd->scst_cmd,
++ SCST_CONTEXT_DIRECT_ATOMIC);
++ break;
++
++ case ISCSI_CMD_STATE_AFTER_PREPROC:
++ {
++ /* It can be for some aborted commands */
++ struct scst_cmd *scst_cmd = cmnd->scst_cmd;
++ TRACE_DBG("cmd %p AFTER_PREPROC", cmnd);
++ cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED;
++ cmnd->scst_cmd = NULL;
++ scst_restart_cmd(scst_cmd,
++ SCST_PREPROCESS_STATUS_ERROR_FATAL,
++ SCST_CONTEXT_THREAD);
++ break;
++ }
++
++ case ISCSI_CMD_STATE_AEN:
++ TRACE_DBG("cmd %p AEN PROCESSED", cmnd);
++ scst_aen_done(cmnd->scst_aen);
++ break;
++
++ case ISCSI_CMD_STATE_OUT_OF_SCST_PRELIM_COMPL:
++ break;
++
++ default:
++ PRINT_CRIT_ERROR("Unexpected cmnd scst state "
++ "%d", cmnd->scst_state);
++ BUG();
++ break;
++ }
++ }
++
++ if (cmnd->own_sg) {
++ TRACE_DBG("own_sg for req %p", cmnd);
++ if (cmnd->sg != &dummy_sg)
++ scst_free(cmnd->sg, cmnd->sg_cnt);
++#ifdef CONFIG_SCST_DEBUG
++ cmnd->own_sg = 0;
++ cmnd->sg = NULL;
++ cmnd->sg_cnt = -1;
++#endif
++ }
++
++ if (unlikely(cmnd->dec_active_cmds))
++ iscsi_dec_active_cmds(cmnd);
++
++ list_for_each_entry_safe(rsp, t, &cmnd->rsp_cmd_list,
++ rsp_cmd_list_entry) {
++ cmnd_free(rsp);
++ }
++
++ cmnd_free(cmnd);
++ } else {
++ struct iscsi_cmnd *parent = cmnd->parent_req;
++
++ if (cmnd->own_sg) {
++ TRACE_DBG("own_sg for rsp %p", cmnd);
++ if ((cmnd->sg != &dummy_sg) && (cmnd->sg != cmnd->rsp_sg))
++ scst_free(cmnd->sg, cmnd->sg_cnt);
++#ifdef CONFIG_SCST_DEBUG
++ cmnd->own_sg = 0;
++ cmnd->sg = NULL;
++ cmnd->sg_cnt = -1;
++#endif
++ }
++
++ EXTRACHECKS_BUG_ON(cmnd->dec_active_cmds);
++
++ if (cmnd == parent->main_rsp) {
++ TRACE_DBG("Finishing main rsp %p (req %p)", cmnd,
++ parent);
++ parent->main_rsp = NULL;
++ }
++
++ cmnd_put(parent);
++ /*
++ * cmnd will be freed on the last parent's put and can already
++ * be freed!!
++ */
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * Corresponding conn may also get destroyed after this function, except only
++ * if it's called from the read thread!
++ *
++ * It can't be called in parallel with iscsi_cmnds_init_write()!
++ */
++void req_cmnd_release_force(struct iscsi_cmnd *req)
++{
++ struct iscsi_cmnd *rsp, *t;
++ struct iscsi_conn *conn = req->conn;
++ LIST_HEAD(cmds_list);
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("req %p", req);
++
++ BUG_ON(req == conn->read_cmnd);
++
++ spin_lock_bh(&conn->write_list_lock);
++ list_for_each_entry_safe(rsp, t, &conn->write_list, write_list_entry) {
++ if (rsp->parent_req != req)
++ continue;
++
++ cmd_del_from_write_list(rsp);
++
++ list_add_tail(&rsp->write_list_entry, &cmds_list);
++ }
++ spin_unlock_bh(&conn->write_list_lock);
++
++ list_for_each_entry_safe(rsp, t, &cmds_list, write_list_entry) {
++ TRACE_MGMT_DBG("Putting write rsp %p", rsp);
++ list_del(&rsp->write_list_entry);
++ cmnd_put(rsp);
++ }
++
++ /* Supposed nobody can add responses in the list anymore */
++ list_for_each_entry_reverse(rsp, &req->rsp_cmd_list,
++ rsp_cmd_list_entry) {
++ bool r;
++
++ if (rsp->force_cleanup_done)
++ continue;
++
++ rsp->force_cleanup_done = 1;
++
++ if (cmnd_get_check(rsp))
++ continue;
++
++ spin_lock_bh(&conn->write_list_lock);
++ r = rsp->on_write_list || rsp->write_processing_started;
++ spin_unlock_bh(&conn->write_list_lock);
++
++ cmnd_put(rsp);
++
++ if (r)
++ continue;
++
++ /*
++ * If both on_write_list and write_processing_started not set,
++ * we can safely put() rsp.
++ */
++ TRACE_MGMT_DBG("Putting rsp %p", rsp);
++ cmnd_put(rsp);
++ }
++
++ if (req->main_rsp != NULL) {
++ TRACE_MGMT_DBG("Putting main rsp %p", req->main_rsp);
++ cmnd_put(req->main_rsp);
++ req->main_rsp = NULL;
++ }
++
++ req_cmnd_release(req);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void req_cmnd_pre_release(struct iscsi_cmnd *req)
++{
++ struct iscsi_cmnd *c, *t;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("req %p", req);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ BUG_ON(req->release_called);
++ req->release_called = 1;
++#endif
++
++ if (unlikely(test_bit(ISCSI_CMD_ABORTED, &req->prelim_compl_flags))) {
++ TRACE_MGMT_DBG("Release aborted req cmd %p (scst cmd %p, "
++ "state %d)", req, req->scst_cmd, req->scst_state);
++ }
++
++ BUG_ON(req->parent_req != NULL);
++
++ if (unlikely(req->hashed)) {
++ /* It sometimes can happen during errors recovery */
++ cmnd_remove_data_wait_hash(req);
++ }
++
++ if (unlikely(req->main_rsp != NULL)) {
++ TRACE_DBG("Sending main rsp %p", req->main_rsp);
++ if (cmnd_opcode(req) == ISCSI_OP_SCSI_CMD) {
++ if (req->scst_cmd != NULL)
++ iscsi_set_resid(req->main_rsp);
++ else
++ iscsi_set_resid_no_scst_cmd(req->main_rsp);
++ }
++ iscsi_cmnd_init_write(req->main_rsp, ISCSI_INIT_WRITE_WAKE);
++ req->main_rsp = NULL;
++ }
++
++ list_for_each_entry_safe(c, t, &req->rx_ddigest_cmd_list,
++ rx_ddigest_cmd_list_entry) {
++ cmd_del_from_rx_ddigest_list(c);
++ cmnd_put(c);
++ }
++
++ EXTRACHECKS_BUG_ON(req->pending);
++
++ if (unlikely(req->dec_active_cmds))
++ iscsi_dec_active_cmds(req);
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * Corresponding conn may also get destroyed after this function, except only
++ * if it's called from the read thread!
++ */
++static void req_cmnd_release(struct iscsi_cmnd *req)
++{
++ TRACE_ENTRY();
++
++ req_cmnd_pre_release(req);
++ cmnd_put(req);
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * Corresponding conn may also get destroyed after this function, except only
++ * if it's called from the read thread!
++ */
++void rsp_cmnd_release(struct iscsi_cmnd *cmnd)
++{
++ TRACE_DBG("%p", cmnd);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ BUG_ON(cmnd->release_called);
++ cmnd->release_called = 1;
++#endif
++
++ EXTRACHECKS_BUG_ON(cmnd->parent_req == NULL);
++
++ cmnd_put(cmnd);
++ return;
++}
++
++static struct iscsi_cmnd *iscsi_alloc_rsp(struct iscsi_cmnd *parent)
++{
++ struct iscsi_cmnd *rsp;
++
++ TRACE_ENTRY();
++
++ rsp = cmnd_alloc(parent->conn, parent);
++
++ TRACE_DBG("Adding rsp %p to parent %p", rsp, parent);
++ list_add_tail(&rsp->rsp_cmd_list_entry, &parent->rsp_cmd_list);
++
++ cmnd_get(parent);
++
++ TRACE_EXIT_HRES((unsigned long)rsp);
++ return rsp;
++}
++
++static inline struct iscsi_cmnd *iscsi_alloc_main_rsp(struct iscsi_cmnd *parent)
++{
++ struct iscsi_cmnd *rsp;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(parent->main_rsp != NULL);
++
++ rsp = iscsi_alloc_rsp(parent);
++ parent->main_rsp = rsp;
++
++ TRACE_EXIT_HRES((unsigned long)rsp);
++ return rsp;
++}
++
++static void iscsi_cmnds_init_write(struct list_head *send, int flags)
++{
++ struct iscsi_cmnd *rsp = list_entry(send->next, struct iscsi_cmnd,
++ write_list_entry);
++ struct iscsi_conn *conn = rsp->conn;
++ struct list_head *pos, *next;
++
++ BUG_ON(list_empty(send));
++
++ if (!(conn->ddigest_type & DIGEST_NONE)) {
++ list_for_each(pos, send) {
++ rsp = list_entry(pos, struct iscsi_cmnd,
++ write_list_entry);
++
++ if (rsp->pdu.datasize != 0) {
++ TRACE_DBG("Doing data digest (%p:%x)", rsp,
++ cmnd_opcode(rsp));
++ digest_tx_data(rsp);
++ }
++ }
++ }
++
++ spin_lock_bh(&conn->write_list_lock);
++ list_for_each_safe(pos, next, send) {
++ rsp = list_entry(pos, struct iscsi_cmnd, write_list_entry);
++
++ TRACE_DBG("%p:%x", rsp, cmnd_opcode(rsp));
++
++ BUG_ON(conn != rsp->conn);
++
++ list_del(&rsp->write_list_entry);
++ cmd_add_on_write_list(conn, rsp);
++ }
++ spin_unlock_bh(&conn->write_list_lock);
++
++ if (flags & ISCSI_INIT_WRITE_WAKE)
++ iscsi_make_conn_wr_active(conn);
++
++ return;
++}
++
++static void iscsi_cmnd_init_write(struct iscsi_cmnd *rsp, int flags)
++{
++ LIST_HEAD(head);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ if (unlikely(rsp->on_write_list)) {
++ PRINT_CRIT_ERROR("cmd already on write list (%x %x %x "
++ "%u %u %d %d", rsp->pdu.bhs.itt,
++ cmnd_opcode(rsp), cmnd_scsicode(rsp),
++ rsp->hdigest, rsp->ddigest,
++ list_empty(&rsp->rsp_cmd_list), rsp->hashed);
++ BUG();
++ }
++#endif
++ list_add_tail(&rsp->write_list_entry, &head);
++ iscsi_cmnds_init_write(&head, flags);
++ return;
++}
++
++static void iscsi_set_resid_no_scst_cmd(struct iscsi_cmnd *rsp)
++{
++ struct iscsi_cmnd *req = rsp->parent_req;
++ struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
++ struct iscsi_scsi_rsp_hdr *rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
++ int resid, out_resid;
++
++ TRACE_ENTRY();
++
++ BUG_ON(req->scst_cmd != NULL);
++
++ TRACE_DBG("req %p, rsp %p, outstanding_r2t %d, r2t_len_to_receive %d, "
++ "r2t_len_to_send %d, not_received_data_len %d", req, rsp,
++ req->outstanding_r2t, req->r2t_len_to_receive,
++ req->r2t_len_to_send, req->not_received_data_len);
++
++ if ((req_hdr->flags & ISCSI_CMD_READ) &&
++ (req_hdr->flags & ISCSI_CMD_WRITE)) {
++ out_resid = req->not_received_data_len;
++ if (out_resid > 0) {
++ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
++ rsp_hdr->residual_count = cpu_to_be32(out_resid);
++ } else if (out_resid < 0) {
++ out_resid = -out_resid;
++ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW;
++ rsp_hdr->residual_count = cpu_to_be32(out_resid);
++ }
++
++ resid = cmnd_read_size(req);
++ if (resid > 0) {
++ rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_UNDERFLOW;
++ rsp_hdr->bi_residual_count = cpu_to_be32(resid);
++ } else if (resid < 0) {
++ resid = -resid;
++ rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_OVERFLOW;
++ rsp_hdr->bi_residual_count = cpu_to_be32(resid);
++ }
++ } else if (req_hdr->flags & ISCSI_CMD_READ) {
++ resid = be32_to_cpu(req_hdr->data_length);
++ if (resid > 0) {
++ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
++ rsp_hdr->residual_count = cpu_to_be32(resid);
++ }
++ } else if (req_hdr->flags & ISCSI_CMD_WRITE) {
++ resid = req->not_received_data_len;
++ if (resid > 0) {
++ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
++ rsp_hdr->residual_count = cpu_to_be32(resid);
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static void iscsi_set_resid(struct iscsi_cmnd *rsp)
++{
++ struct iscsi_cmnd *req = rsp->parent_req;
++ struct scst_cmd *scst_cmd = req->scst_cmd;
++ struct iscsi_scsi_cmd_hdr *req_hdr;
++ struct iscsi_scsi_rsp_hdr *rsp_hdr;
++ int resid, out_resid;
++
++ TRACE_ENTRY();
++
++ if (likely(!scst_get_resid(scst_cmd, &resid, &out_resid))) {
++ TRACE_DBG("No residuals for req %p", req);
++ goto out;
++ }
++
++ TRACE_DBG("req %p, resid %d, out_resid %d", req, resid, out_resid);
++
++ req_hdr = cmnd_hdr(req);
++ rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
++
++ if ((req_hdr->flags & ISCSI_CMD_READ) &&
++ (req_hdr->flags & ISCSI_CMD_WRITE)) {
++ if (out_resid > 0) {
++ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
++ rsp_hdr->residual_count = cpu_to_be32(out_resid);
++ } else if (out_resid < 0) {
++ out_resid = -out_resid;
++ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW;
++ rsp_hdr->residual_count = cpu_to_be32(out_resid);
++ }
++
++ if (resid > 0) {
++ rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_UNDERFLOW;
++ rsp_hdr->bi_residual_count = cpu_to_be32(resid);
++ } else if (resid < 0) {
++ resid = -resid;
++ rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_OVERFLOW;
++ rsp_hdr->bi_residual_count = cpu_to_be32(resid);
++ }
++ } else {
++ if (resid > 0) {
++ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
++ rsp_hdr->residual_count = cpu_to_be32(resid);
++ } else if (resid < 0) {
++ resid = -resid;
++ rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW;
++ rsp_hdr->residual_count = cpu_to_be32(resid);
++ }
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void send_data_rsp(struct iscsi_cmnd *req, u8 status, int send_status)
++{
++ struct iscsi_cmnd *rsp;
++ struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
++ struct iscsi_data_in_hdr *rsp_hdr;
++ u32 pdusize, size, offset, sn;
++ LIST_HEAD(send);
++
++ TRACE_DBG("req %p", req);
++
++ pdusize = req->conn->session->sess_params.max_xmit_data_length;
++ size = req->bufflen;
++ offset = 0;
++ sn = 0;
++
++ while (1) {
++ rsp = iscsi_alloc_rsp(req);
++ TRACE_DBG("rsp %p", rsp);
++ rsp->sg = req->sg;
++ rsp->sg_cnt = req->sg_cnt;
++ rsp->bufflen = req->bufflen;
++ rsp_hdr = (struct iscsi_data_in_hdr *)&rsp->pdu.bhs;
++
++ rsp_hdr->opcode = ISCSI_OP_SCSI_DATA_IN;
++ rsp_hdr->itt = req_hdr->itt;
++ rsp_hdr->ttt = ISCSI_RESERVED_TAG;
++ rsp_hdr->buffer_offset = cpu_to_be32(offset);
++ rsp_hdr->data_sn = cpu_to_be32(sn);
++
++ if (size <= pdusize) {
++ TRACE_DBG("offset %d, size %d", offset, size);
++ rsp->pdu.datasize = size;
++ if (send_status) {
++ TRACE_DBG("status %x", status);
++
++ EXTRACHECKS_BUG_ON((cmnd_hdr(req)->flags & ISCSI_CMD_WRITE) != 0);
++
++ rsp_hdr->flags = ISCSI_FLG_FINAL | ISCSI_FLG_STATUS;
++ rsp_hdr->cmd_status = status;
++
++ iscsi_set_resid(rsp);
++ }
++ list_add_tail(&rsp->write_list_entry, &send);
++ break;
++ }
++
++ TRACE_DBG("pdusize %d, offset %d, size %d", pdusize, offset,
++ size);
++
++ rsp->pdu.datasize = pdusize;
++
++ size -= pdusize;
++ offset += pdusize;
++ sn++;
++
++ list_add_tail(&rsp->write_list_entry, &send);
++ }
++ iscsi_cmnds_init_write(&send, 0);
++ return;
++}
++
++static void iscsi_init_status_rsp(struct iscsi_cmnd *rsp,
++ int status, const u8 *sense_buf, int sense_len)
++{
++ struct iscsi_cmnd *req = rsp->parent_req;
++ struct iscsi_scsi_rsp_hdr *rsp_hdr;
++ struct scatterlist *sg;
++
++ TRACE_ENTRY();
++
++ rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
++ rsp_hdr->opcode = ISCSI_OP_SCSI_RSP;
++ rsp_hdr->flags = ISCSI_FLG_FINAL;
++ rsp_hdr->response = ISCSI_RESPONSE_COMMAND_COMPLETED;
++ rsp_hdr->cmd_status = status;
++ rsp_hdr->itt = cmnd_hdr(req)->itt;
++
++ if (SCST_SENSE_VALID(sense_buf)) {
++ TRACE_DBG("%s", "SENSE VALID");
++
++ sg = rsp->sg = rsp->rsp_sg;
++ rsp->sg_cnt = 2;
++ rsp->own_sg = 1;
++
++ sg_init_table(sg, 2);
++ sg_set_buf(&sg[0], &rsp->sense_hdr, sizeof(rsp->sense_hdr));
++ sg_set_buf(&sg[1], sense_buf, sense_len);
++
++ rsp->sense_hdr.length = cpu_to_be16(sense_len);
++
++ rsp->pdu.datasize = sizeof(rsp->sense_hdr) + sense_len;
++ rsp->bufflen = rsp->pdu.datasize;
++ } else {
++ rsp->pdu.datasize = 0;
++ rsp->bufflen = 0;
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline struct iscsi_cmnd *create_status_rsp(struct iscsi_cmnd *req,
++ int status, const u8 *sense_buf, int sense_len)
++{
++ struct iscsi_cmnd *rsp;
++
++ TRACE_ENTRY();
++
++ rsp = iscsi_alloc_rsp(req);
++ TRACE_DBG("rsp %p", rsp);
++
++ iscsi_init_status_rsp(rsp, status, sense_buf, sense_len);
++ iscsi_set_resid(rsp);
++
++ TRACE_EXIT_HRES((unsigned long)rsp);
++ return rsp;
++}
++
++/*
++ * Initializes data receive fields. Can be called only when they have not been
++ * initialized yet.
++ */
++static int iscsi_set_prelim_r2t_len_to_receive(struct iscsi_cmnd *req)
++{
++ struct iscsi_scsi_cmd_hdr *req_hdr = (struct iscsi_scsi_cmd_hdr *)&req->pdu.bhs;
++ int res = 0;
++ unsigned int not_received;
++
++ TRACE_ENTRY();
++
++ if (req_hdr->flags & ISCSI_CMD_FINAL) {
++ if (req_hdr->flags & ISCSI_CMD_WRITE)
++ iscsi_set_not_received_data_len(req,
++ be32_to_cpu(req_hdr->data_length) -
++ req->pdu.datasize);
++ goto out;
++ }
++
++ BUG_ON(req->outstanding_r2t != 0);
++
++ res = cmnd_insert_data_wait_hash(req);
++ if (res != 0) {
++ /*
++ * We have to close connection, because otherwise a data
++ * corruption is possible if we allow to receive data
++ * for this request in another request with dublicated ITT.
++ */
++ mark_conn_closed(req->conn);
++ goto out;
++ }
++
++ /*
++ * We need to wait for one or more PDUs. Let's simplify
++ * other code and pretend we need to receive 1 byte.
++ * In data_out_start() we will correct it.
++ */
++ req->outstanding_r2t = 1;
++ req_add_to_write_timeout_list(req);
++ req->r2t_len_to_receive = 1;
++ req->r2t_len_to_send = 0;
++
++ not_received = be32_to_cpu(req_hdr->data_length) - req->pdu.datasize;
++ not_received -= min_t(unsigned int, not_received,
++ req->conn->session->sess_params.first_burst_length);
++ iscsi_set_not_received_data_len(req, not_received);
++
++ TRACE_DBG("req %p, op %x, outstanding_r2t %d, r2t_len_to_receive %d, "
++ "r2t_len_to_send %d, not_received_data_len %d", req,
++ cmnd_opcode(req), req->outstanding_r2t, req->r2t_len_to_receive,
++ req->r2t_len_to_send, req->not_received_data_len);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int create_preliminary_no_scst_rsp(struct iscsi_cmnd *req,
++ int status, const u8 *sense_buf, int sense_len)
++{
++ struct iscsi_cmnd *rsp;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (req->prelim_compl_flags != 0) {
++ TRACE_MGMT_DBG("req %p already prelim completed", req);
++ goto out;
++ }
++
++ req->scst_state = ISCSI_CMD_STATE_OUT_OF_SCST_PRELIM_COMPL;
++
++ BUG_ON(req->scst_cmd != NULL);
++
++ res = iscsi_preliminary_complete(req, req, true);
++
++ rsp = iscsi_alloc_main_rsp(req);
++ TRACE_DBG("main rsp %p", rsp);
++
++ iscsi_init_status_rsp(rsp, status, sense_buf, sense_len);
++
++ /* Resid will be set in req_cmnd_release() */
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++int set_scst_preliminary_status_rsp(struct iscsi_cmnd *req,
++ bool get_data, int key, int asc, int ascq)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (req->scst_cmd == NULL) {
++ /* There must be already error set */
++ goto complete;
++ }
++
++ scst_set_cmd_error(req->scst_cmd, key, asc, ascq);
++
++complete:
++ res = iscsi_preliminary_complete(req, req, get_data);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int create_reject_rsp(struct iscsi_cmnd *req, int reason, bool get_data)
++{
++ int res = 0;
++ struct iscsi_cmnd *rsp;
++ struct iscsi_reject_hdr *rsp_hdr;
++ struct scatterlist *sg;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Reject: req %p, reason %x", req, reason);
++
++ if (cmnd_opcode(req) == ISCSI_OP_SCSI_CMD) {
++ if (req->scst_cmd == NULL) {
++ /* BUSY status must be already set */
++ struct iscsi_scsi_rsp_hdr *rsp_hdr1;
++ rsp_hdr1 = (struct iscsi_scsi_rsp_hdr *)&req->main_rsp->pdu.bhs;
++ BUG_ON(rsp_hdr1->cmd_status == 0);
++ /*
++ * Let's not send REJECT here. The initiator will retry
++ * and, hopefully, next time we will not fail allocating
++ * scst_cmd, so we will then send the REJECT.
++ */
++ goto out;
++ } else {
++ /*
++ * "In all the cases in which a pre-instantiated SCSI
++ * task is terminated because of the reject, the target
++ * MUST issue a proper SCSI command response with CHECK
++ * CONDITION as described in Section 10.4.3 Response" -
++ * RFC 3720.
++ */
++ set_scst_preliminary_status_rsp(req, get_data,
++ SCST_LOAD_SENSE(scst_sense_invalid_message));
++ }
++ }
++
++ rsp = iscsi_alloc_main_rsp(req);
++ rsp_hdr = (struct iscsi_reject_hdr *)&rsp->pdu.bhs;
++
++ rsp_hdr->opcode = ISCSI_OP_REJECT;
++ rsp_hdr->ffffffff = ISCSI_RESERVED_TAG;
++ rsp_hdr->reason = reason;
++
++ sg = rsp->sg = rsp->rsp_sg;
++ rsp->sg_cnt = 1;
++ rsp->own_sg = 1;
++ sg_init_one(sg, &req->pdu.bhs, sizeof(struct iscsi_hdr));
++ rsp->bufflen = rsp->pdu.datasize = sizeof(struct iscsi_hdr);
++
++ res = iscsi_preliminary_complete(req, req, true);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static inline int iscsi_get_allowed_cmds(struct iscsi_session *sess)
++{
++ int res = max(-1, (int)sess->tgt_params.queued_cmnds -
++ atomic_read(&sess->active_cmds)-1);
++ TRACE_DBG("allowed cmds %d (sess %p, active_cmds %d)", res,
++ sess, atomic_read(&sess->active_cmds));
++ return res;
++}
++
++static __be32 cmnd_set_sn(struct iscsi_cmnd *cmnd, int set_stat_sn)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++ struct iscsi_session *sess = conn->session;
++ __be32 res;
++
++ spin_lock(&sess->sn_lock);
++
++ if (set_stat_sn)
++ cmnd->pdu.bhs.sn = (__force u32)cpu_to_be32(conn->stat_sn++);
++ cmnd->pdu.bhs.exp_sn = (__force u32)cpu_to_be32(sess->exp_cmd_sn);
++ cmnd->pdu.bhs.max_sn = (__force u32)cpu_to_be32(sess->exp_cmd_sn +
++ iscsi_get_allowed_cmds(sess));
++
++ res = cpu_to_be32(conn->stat_sn);
++
++ spin_unlock(&sess->sn_lock);
++ return res;
++}
++
++/* Called under sn_lock */
++static void update_stat_sn(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++ u32 exp_stat_sn;
++
++ cmnd->pdu.bhs.exp_sn = exp_stat_sn = be32_to_cpu((__force __be32)cmnd->pdu.bhs.exp_sn);
++ TRACE_DBG("%x,%x", cmnd_opcode(cmnd), exp_stat_sn);
++ if ((int)(exp_stat_sn - conn->exp_stat_sn) > 0 &&
++ (int)(exp_stat_sn - conn->stat_sn) <= 0) {
++ /* free pdu resources */
++ cmnd->conn->exp_stat_sn = exp_stat_sn;
++ }
++ return;
++}
++
++static struct iscsi_cmnd *cmnd_find_itt_get(struct iscsi_conn *conn, __be32 itt)
++{
++ struct iscsi_cmnd *cmnd, *found_cmnd = NULL;
++
++ spin_lock_bh(&conn->cmd_list_lock);
++ list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
++ if ((cmnd->pdu.bhs.itt == itt) && !cmnd_get_check(cmnd)) {
++ found_cmnd = cmnd;
++ break;
++ }
++ }
++ spin_unlock_bh(&conn->cmd_list_lock);
++
++ return found_cmnd;
++}
++
++/**
++ ** We use the ITT hash only to find original request PDU for subsequent
++ ** Data-Out PDUs.
++ **/
++
++/* Must be called under cmnd_data_wait_hash_lock */
++static struct iscsi_cmnd *__cmnd_find_data_wait_hash(struct iscsi_conn *conn,
++ __be32 itt)
++{
++ struct list_head *head;
++ struct iscsi_cmnd *cmnd;
++
++ head = &conn->session->cmnd_data_wait_hash[cmnd_hashfn(itt)];
++
++ list_for_each_entry(cmnd, head, hash_list_entry) {
++ if (cmnd->pdu.bhs.itt == itt)
++ return cmnd;
++ }
++ return NULL;
++}
++
++static struct iscsi_cmnd *cmnd_find_data_wait_hash(struct iscsi_conn *conn,
++ __be32 itt)
++{
++ struct iscsi_cmnd *res;
++ struct iscsi_session *session = conn->session;
++
++ spin_lock(&session->cmnd_data_wait_hash_lock);
++ res = __cmnd_find_data_wait_hash(conn, itt);
++ spin_unlock(&session->cmnd_data_wait_hash_lock);
++
++ return res;
++}
++
++static inline u32 get_next_ttt(struct iscsi_conn *conn)
++{
++ u32 ttt;
++ struct iscsi_session *session = conn->session;
++
++ /* Not compatible with MC/S! */
++
++ iscsi_extracheck_is_rd_thread(conn);
++
++ if (unlikely(session->next_ttt == ISCSI_RESERVED_TAG_CPU32))
++ session->next_ttt++;
++ ttt = session->next_ttt++;
++
++ return ttt;
++}
++
++static int cmnd_insert_data_wait_hash(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_session *session = cmnd->conn->session;
++ struct iscsi_cmnd *tmp;
++ struct list_head *head;
++ int err = 0;
++ __be32 itt = cmnd->pdu.bhs.itt;
++
++ if (unlikely(cmnd->hashed)) {
++ /*
++ * It can be for preliminary completed commands, when this
++ * function already failed.
++ */
++ goto out;
++ }
++
++ /*
++ * We don't need TTT, because ITT/buffer_offset pair is sufficient
++ * to find out the original request and buffer for Data-Out PDUs, but
++ * crazy iSCSI spec requires us to send this superfluous field in
++ * R2T PDUs and some initiators may rely on it.
++ */
++ cmnd->target_task_tag = get_next_ttt(cmnd->conn);
++
++ TRACE_DBG("%p:%x", cmnd, itt);
++ if (unlikely(itt == ISCSI_RESERVED_TAG)) {
++ PRINT_ERROR("%s", "ITT is RESERVED_TAG");
++ PRINT_BUFFER("Incorrect BHS", &cmnd->pdu.bhs,
++ sizeof(cmnd->pdu.bhs));
++ err = -ISCSI_REASON_PROTOCOL_ERROR;
++ goto out;
++ }
++
++ spin_lock(&session->cmnd_data_wait_hash_lock);
++
++ head = &session->cmnd_data_wait_hash[cmnd_hashfn(itt)];
++
++ tmp = __cmnd_find_data_wait_hash(cmnd->conn, itt);
++ if (likely(!tmp)) {
++ TRACE_DBG("Adding cmnd %p to the hash (ITT %x)", cmnd,
++ cmnd->pdu.bhs.itt);
++ list_add_tail(&cmnd->hash_list_entry, head);
++ cmnd->hashed = 1;
++ } else {
++ PRINT_ERROR("Task %x in progress, cmnd %p", itt, cmnd);
++ err = -ISCSI_REASON_TASK_IN_PROGRESS;
++ }
++
++ spin_unlock(&session->cmnd_data_wait_hash_lock);
++
++out:
++ return err;
++}
++
++static void cmnd_remove_data_wait_hash(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_session *session = cmnd->conn->session;
++ struct iscsi_cmnd *tmp;
++
++ spin_lock(&session->cmnd_data_wait_hash_lock);
++
++ tmp = __cmnd_find_data_wait_hash(cmnd->conn, cmnd->pdu.bhs.itt);
++
++ if (likely(tmp && tmp == cmnd)) {
++ TRACE_DBG("Deleting cmnd %p from the hash (ITT %x)", cmnd,
++ cmnd->pdu.bhs.itt);
++ list_del(&cmnd->hash_list_entry);
++ cmnd->hashed = 0;
++ } else
++ PRINT_ERROR("%p:%x not found", cmnd, cmnd->pdu.bhs.itt);
++
++ spin_unlock(&session->cmnd_data_wait_hash_lock);
++
++ return;
++}
++
++static void cmnd_prepare_get_rejected_immed_data(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++ struct scatterlist *sg = cmnd->sg;
++ char __user *addr;
++ u32 size;
++ unsigned int i;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG_FLAG(iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(cmnd),
++ "Skipping (cmnd %p, ITT %x, op %x, cmd op %x, "
++ "datasize %u, scst_cmd %p, scst state %d)", cmnd,
++ cmnd->pdu.bhs.itt, cmnd_opcode(cmnd), cmnd_hdr(cmnd)->scb[0],
++ cmnd->pdu.datasize, cmnd->scst_cmd, cmnd->scst_state);
++
++ iscsi_extracheck_is_rd_thread(conn);
++
++ size = cmnd->pdu.datasize;
++ if (!size)
++ goto out;
++
++ /* We already checked pdu.datasize in check_segment_length() */
++
++ /*
++ * There are no problems with the safety from concurrent
++ * accesses to dummy_page in dummy_sg, since data only
++ * will be read and then discarded.
++ */
++ sg = &dummy_sg;
++ if (cmnd->sg == NULL) {
++ /* just in case */
++ cmnd->sg = sg;
++ cmnd->bufflen = PAGE_SIZE;
++ cmnd->own_sg = 1;
++ }
++
++ addr = (char __force __user *)(page_address(sg_page(&sg[0])));
++ conn->read_size = size;
++ for (i = 0; size > PAGE_SIZE; i++, size -= PAGE_SIZE) {
++ /* We already checked pdu.datasize in check_segment_length() */
++ BUG_ON(i >= ISCSI_CONN_IOV_MAX);
++ conn->read_iov[i].iov_base = addr;
++ conn->read_iov[i].iov_len = PAGE_SIZE;
++ }
++ conn->read_iov[i].iov_base = addr;
++ conn->read_iov[i].iov_len = size;
++ conn->read_msg.msg_iov = conn->read_iov;
++ conn->read_msg.msg_iovlen = ++i;
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++int iscsi_preliminary_complete(struct iscsi_cmnd *req,
++ struct iscsi_cmnd *orig_req, bool get_data)
++{
++ int res = 0;
++ bool set_r2t_len;
++ struct iscsi_hdr *orig_req_hdr = &orig_req->pdu.bhs;
++
++ TRACE_ENTRY();
++
++#ifdef CONFIG_SCST_DEBUG
++ {
++ struct iscsi_hdr *req_hdr = &req->pdu.bhs;
++ TRACE_DBG_FLAG(iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(orig_req),
++ "Prelim completed req %p, orig_req %p (FINAL %x, "
++ "outstanding_r2t %d)", req, orig_req,
++ (req_hdr->flags & ISCSI_CMD_FINAL),
++ orig_req->outstanding_r2t);
++ }
++#endif
++
++ iscsi_extracheck_is_rd_thread(req->conn);
++ BUG_ON(req->parent_req != NULL);
++
++ if (test_bit(ISCSI_CMD_PRELIM_COMPLETED, &req->prelim_compl_flags)) {
++ TRACE_MGMT_DBG("req %p already prelim completed", req);
++ /* To not try to get data twice */
++ get_data = false;
++ }
++
++ /*
++ * We need to receive all outstanding PDUs, even if direction isn't
++ * WRITE. Test of PRELIM_COMPLETED is needed, because
++ * iscsi_set_prelim_r2t_len_to_receive() could also have failed before.
++ */
++ set_r2t_len = !orig_req->hashed &&
++ (cmnd_opcode(orig_req) == ISCSI_OP_SCSI_CMD) &&
++ !test_bit(ISCSI_CMD_PRELIM_COMPLETED,
++ &orig_req->prelim_compl_flags);
++
++ TRACE_DBG("get_data %d, set_r2t_len %d", get_data, set_r2t_len);
++
++ if (get_data)
++ cmnd_prepare_get_rejected_immed_data(req);
++
++ if (test_bit(ISCSI_CMD_PRELIM_COMPLETED, &orig_req->prelim_compl_flags))
++ goto out_set;
++
++ if (set_r2t_len)
++ res = iscsi_set_prelim_r2t_len_to_receive(orig_req);
++ else if (orig_req_hdr->flags & ISCSI_CMD_WRITE) {
++ /*
++ * We will get here if orig_req prelim completed in the middle
++ * of data receiving. We won't send more R2T's, so
++ * r2t_len_to_send is final and won't be updated anymore in
++ * future.
++ */
++ iscsi_set_not_received_data_len(orig_req,
++ orig_req->r2t_len_to_send);
++ }
++
++out_set:
++ set_bit(ISCSI_CMD_PRELIM_COMPLETED, &orig_req->prelim_compl_flags);
++ set_bit(ISCSI_CMD_PRELIM_COMPLETED, &req->prelim_compl_flags);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn,
++ struct iscsi_cmnd *cmd, u32 offset, u32 size)
++{
++ struct scatterlist *sg = cmd->sg;
++ unsigned int bufflen = cmd->bufflen;
++ unsigned int idx, i, buff_offs;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("cmd %p, sg %p, offset %u, size %u", cmd, cmd->sg,
++ offset, size);
++
++ iscsi_extracheck_is_rd_thread(conn);
++
++ buff_offs = offset;
++ idx = (offset + sg[0].offset) >> PAGE_SHIFT;
++ offset &= ~PAGE_MASK;
++
++ conn->read_msg.msg_iov = conn->read_iov;
++ conn->read_size = size;
++
++ i = 0;
++ while (1) {
++ unsigned int sg_len;
++ char __user *addr;
++
++ if (unlikely(buff_offs >= bufflen)) {
++ TRACE_DBG("Residual overflow (cmd %p, buff_offs %d, "
++ "bufflen %d)", cmd, buff_offs, bufflen);
++ idx = 0;
++ sg = &dummy_sg;
++ offset = 0;
++ }
++
++ addr = (char __force __user *)(sg_virt(&sg[idx]));
++ EXTRACHECKS_BUG_ON(addr == NULL);
++ sg_len = sg[idx].length - offset;
++
++ conn->read_iov[i].iov_base = addr + offset;
++
++ if (size <= sg_len) {
++ TRACE_DBG("idx=%d, i=%d, offset=%u, size=%d, addr=%p",
++ idx, i, offset, size, addr);
++ conn->read_iov[i].iov_len = size;
++ conn->read_msg.msg_iovlen = i+1;
++ break;
++ }
++ conn->read_iov[i].iov_len = sg_len;
++
++ TRACE_DBG("idx=%d, i=%d, offset=%u, size=%d, sg_len=%u, "
++ "addr=%p", idx, i, offset, size, sg_len, addr);
++
++ size -= sg_len;
++ buff_offs += sg_len;
++
++ i++;
++ if (unlikely(i >= ISCSI_CONN_IOV_MAX)) {
++ PRINT_ERROR("Initiator %s violated negotiated "
++ "parameters by sending too much data (size "
++ "left %d)", conn->session->initiator_name,
++ size);
++ mark_conn_closed(conn);
++ res = -EINVAL;
++ break;
++ }
++
++ idx++;
++ offset = 0;
++ }
++
++ TRACE_DBG("msg_iov=%p, msg_iovlen=%zd",
++ conn->read_msg.msg_iov, conn->read_msg.msg_iovlen);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void send_r2t(struct iscsi_cmnd *req)
++{
++ struct iscsi_session *sess = req->conn->session;
++ struct iscsi_cmnd *rsp;
++ struct iscsi_r2t_hdr *rsp_hdr;
++ u32 offset, burst;
++ LIST_HEAD(send);
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(req->r2t_len_to_send == 0);
++
++ /*
++ * There is no race with data_out_start() and conn_abort(), since
++ * all functions called from single read thread
++ */
++ iscsi_extracheck_is_rd_thread(req->conn);
++
++ /*
++ * We don't need to check for PRELIM_COMPLETED here, because for such
++ * commands we set r2t_len_to_send = 0, hence made sure we won't be
++ * called here.
++ */
++
++ EXTRACHECKS_BUG_ON(req->outstanding_r2t >
++ sess->sess_params.max_outstanding_r2t);
++
++ if (req->outstanding_r2t == sess->sess_params.max_outstanding_r2t)
++ goto out;
++
++ burst = sess->sess_params.max_burst_length;
++ offset = be32_to_cpu(cmnd_hdr(req)->data_length) -
++ req->r2t_len_to_send;
++
++ do {
++ rsp = iscsi_alloc_rsp(req);
++ rsp->pdu.bhs.ttt = (__force __be32)req->target_task_tag;
++ rsp_hdr = (struct iscsi_r2t_hdr *)&rsp->pdu.bhs;
++ rsp_hdr->opcode = ISCSI_OP_R2T;
++ rsp_hdr->flags = ISCSI_FLG_FINAL;
++ rsp_hdr->lun = cmnd_hdr(req)->lun;
++ rsp_hdr->itt = cmnd_hdr(req)->itt;
++ rsp_hdr->r2t_sn = (__force u32)cpu_to_be32(req->r2t_sn++);
++ rsp_hdr->buffer_offset = cpu_to_be32(offset);
++ if (req->r2t_len_to_send > burst) {
++ rsp_hdr->data_length = cpu_to_be32(burst);
++ req->r2t_len_to_send -= burst;
++ offset += burst;
++ } else {
++ rsp_hdr->data_length = cpu_to_be32(req->r2t_len_to_send);
++ req->r2t_len_to_send = 0;
++ }
++
++ TRACE_WRITE("req %p, data_length %u, buffer_offset %u, "
++ "r2t_sn %u, outstanding_r2t %u", req,
++ be32_to_cpu(rsp_hdr->data_length),
++ be32_to_cpu(rsp_hdr->buffer_offset),
++ be32_to_cpu((__force __be32)rsp_hdr->r2t_sn), req->outstanding_r2t);
++
++ list_add_tail(&rsp->write_list_entry, &send);
++ req->outstanding_r2t++;
++
++ } while ((req->outstanding_r2t < sess->sess_params.max_outstanding_r2t) &&
++ (req->r2t_len_to_send != 0));
++
++ iscsi_cmnds_init_write(&send, ISCSI_INIT_WRITE_WAKE);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int iscsi_pre_exec(struct scst_cmd *scst_cmd)
++{
++ int res = SCST_PREPROCESS_STATUS_SUCCESS;
++ struct iscsi_cmnd *req = (struct iscsi_cmnd *)
++ scst_cmd_get_tgt_priv(scst_cmd);
++ struct iscsi_cmnd *c, *t;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
++
++ /* If data digest isn't used this list will be empty */
++ list_for_each_entry_safe(c, t, &req->rx_ddigest_cmd_list,
++ rx_ddigest_cmd_list_entry) {
++ TRACE_DBG("Checking digest of RX ddigest cmd %p", c);
++ if (digest_rx_data(c) != 0) {
++ scst_set_cmd_error(scst_cmd,
++ SCST_LOAD_SENSE(iscsi_sense_crc_error));
++ res = SCST_PREPROCESS_STATUS_ERROR_SENSE_SET;
++ /*
++ * The rest of rx_ddigest_cmd_list will be freed
++ * in req_cmnd_release()
++ */
++ goto out;
++ }
++ cmd_del_from_rx_ddigest_list(c);
++ cmnd_put(c);
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int nop_out_start(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++ struct iscsi_hdr *req_hdr = &cmnd->pdu.bhs;
++ u32 size, tmp;
++ int i, err = 0;
++
++ TRACE_DBG("%p", cmnd);
++
++ iscsi_extracheck_is_rd_thread(conn);
++
++ if (!(req_hdr->flags & ISCSI_FLG_FINAL)) {
++ PRINT_ERROR("%s", "Initiator sent Nop-Out with not a single "
++ "PDU");
++ err = -ISCSI_REASON_PROTOCOL_ERROR;
++ goto out;
++ }
++
++ if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG) {
++ if (unlikely(!(cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE)))
++ PRINT_ERROR("%s", "Initiator sent RESERVED tag for "
++ "non-immediate Nop-Out command");
++ }
++
++ update_stat_sn(cmnd);
++
++ size = cmnd->pdu.datasize;
++
++ if (size) {
++ conn->read_msg.msg_iov = conn->read_iov;
++ if (cmnd->pdu.bhs.itt != ISCSI_RESERVED_TAG) {
++ struct scatterlist *sg;
++
++ cmnd->sg = sg = scst_alloc(size, GFP_KERNEL,
++ &cmnd->sg_cnt);
++ if (sg == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "Allocating buffer for"
++ " %d Nop-Out payload failed", size);
++ err = -ISCSI_REASON_OUT_OF_RESOURCES;
++ goto out;
++ }
++
++ /* We already checked it in check_segment_length() */
++ BUG_ON(cmnd->sg_cnt > (signed)ISCSI_CONN_IOV_MAX);
++
++ cmnd->own_sg = 1;
++ cmnd->bufflen = size;
++
++ for (i = 0; i < cmnd->sg_cnt; i++) {
++ conn->read_iov[i].iov_base =
++ (void __force __user *)(page_address(sg_page(&sg[i])));
++ tmp = min_t(u32, size, PAGE_SIZE);
++ conn->read_iov[i].iov_len = tmp;
++ conn->read_size += tmp;
++ size -= tmp;
++ }
++ BUG_ON(size != 0);
++ } else {
++ /*
++ * There are no problems with the safety from concurrent
++ * accesses to dummy_page, since for ISCSI_RESERVED_TAG
++ * the data only read and then discarded.
++ */
++ for (i = 0; i < (signed)ISCSI_CONN_IOV_MAX; i++) {
++ conn->read_iov[i].iov_base =
++ (void __force __user *)(page_address(dummy_page));
++ tmp = min_t(u32, size, PAGE_SIZE);
++ conn->read_iov[i].iov_len = tmp;
++ conn->read_size += tmp;
++ size -= tmp;
++ }
++
++ /* We already checked size in check_segment_length() */
++ BUG_ON(size != 0);
++ }
++
++ conn->read_msg.msg_iovlen = i;
++ TRACE_DBG("msg_iov=%p, msg_iovlen=%zd", conn->read_msg.msg_iov,
++ conn->read_msg.msg_iovlen);
++ }
++
++out:
++ return err;
++}
++
++int cmnd_rx_continue(struct iscsi_cmnd *req)
++{
++ struct iscsi_conn *conn = req->conn;
++ struct iscsi_session *session = conn->session;
++ struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
++ struct scst_cmd *scst_cmd = req->scst_cmd;
++ scst_data_direction dir;
++ bool unsolicited_data_expected = false;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("scsi command: %x", req_hdr->scb[0]);
++
++ EXTRACHECKS_BUG_ON(req->scst_state != ISCSI_CMD_STATE_AFTER_PREPROC);
++
++ dir = scst_cmd_get_data_direction(scst_cmd);
++
++ /*
++ * Check for preliminary completion here to save R2Ts. For TASK QUEUE
++ * FULL statuses that might be a big performance win.
++ */
++ if (unlikely(scst_cmd_prelim_completed(scst_cmd) ||
++ unlikely(req->prelim_compl_flags != 0))) {
++ /*
++ * If necessary, ISCSI_CMD_ABORTED will be set by
++ * iscsi_xmit_response().
++ */
++ res = iscsi_preliminary_complete(req, req, true);
++ goto trace;
++ }
++
++ /* For prelim completed commands sg & K can be already set! */
++
++ if (dir & SCST_DATA_WRITE) {
++ req->bufflen = scst_cmd_get_write_fields(scst_cmd, &req->sg,
++ &req->sg_cnt);
++ unsolicited_data_expected = !(req_hdr->flags & ISCSI_CMD_FINAL);
++
++ if (unlikely(session->sess_params.initial_r2t &&
++ unsolicited_data_expected)) {
++ PRINT_ERROR("Initiator %s violated negotiated "
++ "parameters: initial R2T is required (ITT %x, "
++ "op %x)", session->initiator_name,
++ req->pdu.bhs.itt, req_hdr->scb[0]);
++ goto out_close;
++ }
++
++ if (unlikely(!session->sess_params.immediate_data &&
++ req->pdu.datasize)) {
++ PRINT_ERROR("Initiator %s violated negotiated "
++ "parameters: forbidden immediate data sent "
++ "(ITT %x, op %x)", session->initiator_name,
++ req->pdu.bhs.itt, req_hdr->scb[0]);
++ goto out_close;
++ }
++
++ if (unlikely(session->sess_params.first_burst_length < req->pdu.datasize)) {
++ PRINT_ERROR("Initiator %s violated negotiated "
++ "parameters: immediate data len (%d) > "
++ "first_burst_length (%d) (ITT %x, op %x)",
++ session->initiator_name,
++ req->pdu.datasize,
++ session->sess_params.first_burst_length,
++ req->pdu.bhs.itt, req_hdr->scb[0]);
++ goto out_close;
++ }
++
++ req->r2t_len_to_receive = be32_to_cpu(req_hdr->data_length) -
++ req->pdu.datasize;
++
++ /*
++ * In case of residual overflow req->r2t_len_to_receive and
++ * req->pdu.datasize might be > req->bufflen
++ */
++
++ res = cmnd_insert_data_wait_hash(req);
++ if (unlikely(res != 0)) {
++ /*
++ * We have to close connection, because otherwise a data
++ * corruption is possible if we allow to receive data
++ * for this request in another request with dublicated
++ * ITT.
++ */
++ goto out_close;
++ }
++
++ if (unsolicited_data_expected) {
++ req->outstanding_r2t = 1;
++ req->r2t_len_to_send = req->r2t_len_to_receive -
++ min_t(unsigned int,
++ session->sess_params.first_burst_length -
++ req->pdu.datasize,
++ req->r2t_len_to_receive);
++ } else
++ req->r2t_len_to_send = req->r2t_len_to_receive;
++
++ req_add_to_write_timeout_list(req);
++
++ if (req->pdu.datasize) {
++ res = cmnd_prepare_recv_pdu(conn, req, 0, req->pdu.datasize);
++ /* For performance better to send R2Ts ASAP */
++ if (likely(res == 0) && (req->r2t_len_to_send != 0))
++ send_r2t(req);
++ }
++ } else {
++ req->sg = scst_cmd_get_sg(scst_cmd);
++ req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
++ req->bufflen = scst_cmd_get_bufflen(scst_cmd);
++
++ if (unlikely(!(req_hdr->flags & ISCSI_CMD_FINAL) ||
++ req->pdu.datasize)) {
++ PRINT_ERROR("Unexpected unsolicited data (ITT %x "
++ "CDB %x)", req->pdu.bhs.itt, req_hdr->scb[0]);
++ set_scst_preliminary_status_rsp(req, true,
++ SCST_LOAD_SENSE(iscsi_sense_unexpected_unsolicited_data));
++ }
++ }
++
++trace:
++ TRACE_DBG("req=%p, dir=%d, unsolicited_data_expected=%d, "
++ "r2t_len_to_receive=%d, r2t_len_to_send=%d, bufflen=%d, "
++ "own_sg %d", req, dir, unsolicited_data_expected,
++ req->r2t_len_to_receive, req->r2t_len_to_send, req->bufflen,
++ req->own_sg);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_close:
++ mark_conn_closed(conn);
++ res = -EINVAL;
++ goto out;
++}
++
++static int scsi_cmnd_start(struct iscsi_cmnd *req)
++{
++ struct iscsi_conn *conn = req->conn;
++ struct iscsi_session *session = conn->session;
++ struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
++ struct scst_cmd *scst_cmd;
++ scst_data_direction dir;
++ struct iscsi_ahs_hdr *ahdr;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("scsi command: %x", req_hdr->scb[0]);
++
++ TRACE_DBG("Incrementing active_cmds (cmd %p, sess %p, "
++ "new value %d)", req, session,
++ atomic_read(&session->active_cmds)+1);
++ atomic_inc(&session->active_cmds);
++ req->dec_active_cmds = 1;
++
++ scst_cmd = scst_rx_cmd(session->scst_sess,
++ (uint8_t *)&req_hdr->lun, sizeof(req_hdr->lun),
++ req_hdr->scb, sizeof(req_hdr->scb), SCST_NON_ATOMIC);
++ if (scst_cmd == NULL) {
++ res = create_preliminary_no_scst_rsp(req, SAM_STAT_BUSY,
++ NULL, 0);
++ goto out;
++ }
++
++ req->scst_cmd = scst_cmd;
++ scst_cmd_set_tag(scst_cmd, (__force u32)req_hdr->itt);
++ scst_cmd_set_tgt_priv(scst_cmd, req);
++
++ if ((req_hdr->flags & ISCSI_CMD_READ) &&
++ (req_hdr->flags & ISCSI_CMD_WRITE)) {
++ int sz = cmnd_read_size(req);
++ if (unlikely(sz < 0)) {
++ PRINT_ERROR("%s", "BIDI data transfer, but initiator "
++ "not supplied Bidirectional Read Expected Data "
++ "Transfer Length AHS");
++ set_scst_preliminary_status_rsp(req, true,
++ SCST_LOAD_SENSE(scst_sense_parameter_value_invalid));
++ } else {
++ dir = SCST_DATA_BIDI;
++ scst_cmd_set_expected(scst_cmd, dir, sz);
++ scst_cmd_set_expected_out_transfer_len(scst_cmd,
++ be32_to_cpu(req_hdr->data_length));
++#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd);
++#endif
++ }
++ } else if (req_hdr->flags & ISCSI_CMD_READ) {
++ dir = SCST_DATA_READ;
++ scst_cmd_set_expected(scst_cmd, dir,
++ be32_to_cpu(req_hdr->data_length));
++#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd);
++#endif
++ } else if (req_hdr->flags & ISCSI_CMD_WRITE) {
++ dir = SCST_DATA_WRITE;
++ scst_cmd_set_expected(scst_cmd, dir,
++ be32_to_cpu(req_hdr->data_length));
++ } else {
++ dir = SCST_DATA_NONE;
++ scst_cmd_set_expected(scst_cmd, dir, 0);
++ }
++
++ switch (req_hdr->flags & ISCSI_CMD_ATTR_MASK) {
++ case ISCSI_CMD_SIMPLE:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_SIMPLE);
++ break;
++ case ISCSI_CMD_HEAD_OF_QUEUE:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
++ break;
++ case ISCSI_CMD_ORDERED:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ case ISCSI_CMD_ACA:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_ACA);
++ break;
++ case ISCSI_CMD_UNTAGGED:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
++ break;
++ default:
++ PRINT_ERROR("Unknown task code %x, use ORDERED instead",
++ req_hdr->flags & ISCSI_CMD_ATTR_MASK);
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ }
++
++ scst_cmd_set_tgt_sn(scst_cmd, req_hdr->cmd_sn);
++
++ ahdr = (struct iscsi_ahs_hdr *)req->pdu.ahs;
++ if (ahdr != NULL) {
++ uint8_t *p = (uint8_t *)ahdr;
++ unsigned int size = 0;
++ do {
++ int s;
++
++ ahdr = (struct iscsi_ahs_hdr *)p;
++
++ if (ahdr->ahstype == ISCSI_AHSTYPE_CDB) {
++ struct iscsi_cdb_ahdr *eca =
++ (struct iscsi_cdb_ahdr *)ahdr;
++ scst_cmd_set_ext_cdb(scst_cmd, eca->cdb,
++ be16_to_cpu(ahdr->ahslength) - 1);
++ break;
++ }
++ s = 3 + be16_to_cpu(ahdr->ahslength);
++ s = (s + 3) & -4;
++ size += s;
++ p += s;
++ } while (size < req->pdu.ahssize);
++ }
++
++ TRACE_DBG("START Command (itt %x, queue_type %d)",
++ req_hdr->itt, scst_cmd_get_queue_type(scst_cmd));
++ req->scst_state = ISCSI_CMD_STATE_RX_CMD;
++ conn->rx_task = current;
++ scst_cmd_init_stage1_done(scst_cmd, SCST_CONTEXT_DIRECT, 0);
++
++ if (req->scst_state != ISCSI_CMD_STATE_RX_CMD)
++ res = cmnd_rx_continue(req);
++ else {
++ TRACE_DBG("Delaying req %p post processing (scst_state %d)",
++ req, req->scst_state);
++ res = 1;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int data_out_start(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++ struct iscsi_data_out_hdr *req_hdr =
++ (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs;
++ struct iscsi_cmnd *orig_req;
++#if 0
++ struct iscsi_hdr *orig_req_hdr;
++#endif
++ u32 offset = be32_to_cpu(req_hdr->buffer_offset);
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ /*
++ * There is no race with send_r2t() and conn_abort(), since
++ * all functions called from single read thread
++ */
++ iscsi_extracheck_is_rd_thread(cmnd->conn);
++
++ update_stat_sn(cmnd);
++
++ orig_req = cmnd_find_data_wait_hash(conn, req_hdr->itt);
++ cmnd->cmd_req = orig_req;
++ if (unlikely(orig_req == NULL)) {
++ /*
++ * It shouldn't happen, since we don't abort any request until
++ * we received all related PDUs from the initiator or timeout
++ * them. Let's quietly drop such PDUs.
++ */
++ TRACE_MGMT_DBG("Unable to find scsi task ITT %x",
++ cmnd->pdu.bhs.itt);
++ res = iscsi_preliminary_complete(cmnd, cmnd, true);
++ goto out;
++ }
++
++ if (unlikely(orig_req->r2t_len_to_receive < cmnd->pdu.datasize)) {
++ if (orig_req->prelim_compl_flags != 0) {
++ /* We can have fake r2t_len_to_receive */
++ goto go;
++ }
++ PRINT_ERROR("Data size (%d) > R2T length to receive (%d)",
++ cmnd->pdu.datasize, orig_req->r2t_len_to_receive);
++ set_scst_preliminary_status_rsp(orig_req, false,
++ SCST_LOAD_SENSE(iscsi_sense_incorrect_amount_of_data));
++ goto go;
++ }
++
++ /* Crazy iSCSI spec requires us to make this unneeded check */
++#if 0 /* ...but some initiators (Windows) don't care to correctly set it */
++ orig_req_hdr = &orig_req->pdu.bhs;
++ if (unlikely(orig_req_hdr->lun != req_hdr->lun)) {
++ PRINT_ERROR("Wrong LUN (%lld) in Data-Out PDU (expected %lld), "
++ "orig_req %p, cmnd %p", (unsigned long long)req_hdr->lun,
++ (unsigned long long)orig_req_hdr->lun, orig_req, cmnd);
++ create_reject_rsp(orig_req, ISCSI_REASON_PROTOCOL_ERROR, false);
++ goto go;
++ }
++#endif
++
++go:
++ if (req_hdr->flags & ISCSI_FLG_FINAL)
++ orig_req->outstanding_r2t--;
++
++ if (unlikely(orig_req->prelim_compl_flags != 0)) {
++ res = iscsi_preliminary_complete(cmnd, orig_req, true);
++ goto out;
++ }
++
++ TRACE_WRITE("cmnd %p, orig_req %p, offset %u, datasize %u", cmnd,
++ orig_req, offset, cmnd->pdu.datasize);
++
++ res = cmnd_prepare_recv_pdu(conn, orig_req, offset, cmnd->pdu.datasize);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void data_out_end(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_data_out_hdr *req_hdr =
++ (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs;
++ struct iscsi_cmnd *req;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_BUG_ON(cmnd == NULL);
++ req = cmnd->cmd_req;
++ if (unlikely(req == NULL))
++ goto out;
++
++ TRACE_DBG("cmnd %p, req %p", cmnd, req);
++
++ iscsi_extracheck_is_rd_thread(cmnd->conn);
++
++ if (!(cmnd->conn->ddigest_type & DIGEST_NONE) &&
++ !cmnd->ddigest_checked) {
++ cmd_add_on_rx_ddigest_list(req, cmnd);
++ cmnd_get(cmnd);
++ }
++
++ /*
++ * Now we received the data and can adjust r2t_len_to_receive of the
++ * orig req. We couldn't do it earlier, because it will break data
++ * receiving errors recovery (calls of iscsi_fail_data_waiting_cmnd()).
++ */
++ req->r2t_len_to_receive -= cmnd->pdu.datasize;
++
++ if (unlikely(req->prelim_compl_flags != 0)) {
++ /*
++ * We need to call iscsi_preliminary_complete() again
++ * to handle the case if we just been aborted. This call must
++ * be done before zeroing r2t_len_to_send to correctly calc.
++ * residual.
++ */
++ iscsi_preliminary_complete(cmnd, req, false);
++
++ /*
++ * We might need to wait for one or more PDUs. Let's simplify
++ * other code and not perform exact r2t_len_to_receive
++ * calculation.
++ */
++ req->r2t_len_to_receive = req->outstanding_r2t;
++ req->r2t_len_to_send = 0;
++ }
++
++ TRACE_DBG("req %p, FINAL %x, outstanding_r2t %d, r2t_len_to_receive %d,"
++ " r2t_len_to_send %d", req, req_hdr->flags & ISCSI_FLG_FINAL,
++ req->outstanding_r2t, req->r2t_len_to_receive,
++ req->r2t_len_to_send);
++
++ if (!(req_hdr->flags & ISCSI_FLG_FINAL))
++ goto out;
++
++ if (req->r2t_len_to_receive == 0) {
++ if (!req->pending)
++ iscsi_restart_cmnd(req);
++ } else if (req->r2t_len_to_send != 0)
++ send_r2t(req);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* Might be called under target_mutex and cmd_list_lock */
++static void __cmnd_abort(struct iscsi_cmnd *cmnd)
++{
++ unsigned long timeout_time = jiffies + ISCSI_TM_DATA_WAIT_TIMEOUT +
++ ISCSI_ADD_SCHED_TIME;
++ struct iscsi_conn *conn = cmnd->conn;
++
++ TRACE_MGMT_DBG("Aborting cmd %p, scst_cmd %p (scst state %x, "
++ "ref_cnt %d, on_write_timeout_list %d, write_start %ld, ITT %x, "
++ "sn %u, op %x, r2t_len_to_receive %d, r2t_len_to_send %d, "
++ "CDB op %x, size to write %u, outstanding_r2t %d, "
++ "sess->exp_cmd_sn %u, conn %p, rd_task %p)",
++ cmnd, cmnd->scst_cmd, cmnd->scst_state,
++ atomic_read(&cmnd->ref_cnt), cmnd->on_write_timeout_list,
++ cmnd->write_start, cmnd->pdu.bhs.itt, cmnd->pdu.bhs.sn,
++ cmnd_opcode(cmnd), cmnd->r2t_len_to_receive,
++ cmnd->r2t_len_to_send, cmnd_scsicode(cmnd),
++ cmnd_write_size(cmnd), cmnd->outstanding_r2t,
++ cmnd->conn->session->exp_cmd_sn, cmnd->conn,
++ cmnd->conn->rd_task);
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ TRACE_MGMT_DBG("net_ref_cnt %d", atomic_read(&cmnd->net_ref_cnt));
++#endif
++
++ /*
++ * Lock to sync with iscsi_check_tm_data_wait_timeouts(), including
++ * CMD_ABORTED bit set.
++ */
++ spin_lock_bh(&iscsi_rd_lock);
++
++ /*
++ * We suppose that preliminary commands completion is tested by
++ * comparing prelim_compl_flags with 0. Otherwise a race is possible,
++ * like sending command in SCST core as PRELIM_COMPLETED, while it
++ * wasn't aborted in it yet and have as the result a wrong success
++ * status sent to the initiator.
++ */
++ set_bit(ISCSI_CMD_ABORTED, &cmnd->prelim_compl_flags);
++
++ TRACE_MGMT_DBG("Setting conn_tm_active for conn %p", conn);
++ conn->conn_tm_active = 1;
++
++ spin_unlock_bh(&iscsi_rd_lock);
++
++ /*
++ * We need the lock to sync with req_add_to_write_timeout_list() and
++ * close races for rsp_timer.expires.
++ */
++ spin_lock_bh(&conn->write_list_lock);
++ if (!timer_pending(&conn->rsp_timer) ||
++ time_after(conn->rsp_timer.expires, timeout_time)) {
++ TRACE_MGMT_DBG("Mod timer on %ld (conn %p)", timeout_time,
++ conn);
++ mod_timer(&conn->rsp_timer, timeout_time);
++ } else
++ TRACE_MGMT_DBG("Timer for conn %p is going to fire on %ld "
++ "(timeout time %ld)", conn, conn->rsp_timer.expires,
++ timeout_time);
++ spin_unlock_bh(&conn->write_list_lock);
++
++ return;
++}
++
++/* Must be called from the read or conn close thread */
++static int cmnd_abort(struct iscsi_cmnd *req, int *status)
++{
++ struct iscsi_task_mgt_hdr *req_hdr =
++ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
++ struct iscsi_cmnd *cmnd;
++ int res = -1;
++
++ req_hdr->ref_cmd_sn = be32_to_cpu((__force __be32)req_hdr->ref_cmd_sn);
++
++ if (!before(req_hdr->ref_cmd_sn, req_hdr->cmd_sn)) {
++ TRACE(TRACE_MGMT, "ABORT TASK: RefCmdSN(%u) > CmdSN(%u)",
++ req_hdr->ref_cmd_sn, req_hdr->cmd_sn);
++ *status = ISCSI_RESPONSE_UNKNOWN_TASK;
++ goto out;
++ }
++
++ cmnd = cmnd_find_itt_get(req->conn, req_hdr->rtt);
++ if (cmnd) {
++ struct iscsi_conn *conn = cmnd->conn;
++ struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
++
++ if (req_hdr->lun != hdr->lun) {
++ PRINT_ERROR("ABORT TASK: LUN mismatch: req LUN "
++ "%llx, cmd LUN %llx, rtt %u",
++ (long long unsigned)be64_to_cpu(req_hdr->lun),
++ (long long unsigned)be64_to_cpu(hdr->lun),
++ req_hdr->rtt);
++ *status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ goto out_put;
++ }
++
++ if (cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) {
++ if (req_hdr->ref_cmd_sn != req_hdr->cmd_sn) {
++ PRINT_ERROR("ABORT TASK: RefCmdSN(%u) != TM "
++ "cmd CmdSN(%u) for immediate command "
++ "%p", req_hdr->ref_cmd_sn,
++ req_hdr->cmd_sn, cmnd);
++ *status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ goto out_put;
++ }
++ } else {
++ if (req_hdr->ref_cmd_sn != hdr->cmd_sn) {
++ PRINT_ERROR("ABORT TASK: RefCmdSN(%u) != "
++ "CmdSN(%u) for command %p",
++ req_hdr->ref_cmd_sn, req_hdr->cmd_sn,
++ cmnd);
++ *status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ goto out_put;
++ }
++ }
++
++ if (before(req_hdr->cmd_sn, hdr->cmd_sn) ||
++ (req_hdr->cmd_sn == hdr->cmd_sn)) {
++ PRINT_ERROR("ABORT TASK: SN mismatch: req SN %x, "
++ "cmd SN %x, rtt %u", req_hdr->cmd_sn,
++ hdr->cmd_sn, req_hdr->rtt);
++ *status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ goto out_put;
++ }
++
++ spin_lock_bh(&conn->cmd_list_lock);
++ __cmnd_abort(cmnd);
++ spin_unlock_bh(&conn->cmd_list_lock);
++
++ cmnd_put(cmnd);
++ res = 0;
++ } else {
++ TRACE_MGMT_DBG("cmd RTT %x not found", req_hdr->rtt);
++ /*
++ * iSCSI RFC:
++ *
++ * b) If the Referenced Task Tag does not identify an existing task,
++ * but if the CmdSN indicated by the RefCmdSN field in the Task
++ * Management function request is within the valid CmdSN window
++ * and less than the CmdSN of the Task Management function
++ * request itself, then targets must consider the CmdSN received
++ * and return the "Function complete" response.
++ *
++ * c) If the Referenced Task Tag does not identify an existing task
++ * and if the CmdSN indicated by the RefCmdSN field in the Task
++ * Management function request is outside the valid CmdSN window,
++ * then targets must return the "Task does not exist" response.
++ *
++ * 128 seems to be a good "window".
++ */
++ if (between(req_hdr->ref_cmd_sn, req_hdr->cmd_sn - 128,
++ req_hdr->cmd_sn)) {
++ *status = ISCSI_RESPONSE_FUNCTION_COMPLETE;
++ res = 0;
++ } else
++ *status = ISCSI_RESPONSE_UNKNOWN_TASK;
++ }
++
++out:
++ return res;
++
++out_put:
++ cmnd_put(cmnd);
++ goto out;
++}
++
++/* Must be called from the read or conn close thread */
++static int target_abort(struct iscsi_cmnd *req, int all)
++{
++ struct iscsi_target *target = req->conn->session->target;
++ struct iscsi_task_mgt_hdr *req_hdr =
++ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
++ struct iscsi_session *session;
++ struct iscsi_conn *conn;
++ struct iscsi_cmnd *cmnd;
++
++ mutex_lock(&target->target_mutex);
++
++ list_for_each_entry(session, &target->session_list,
++ session_list_entry) {
++ list_for_each_entry(conn, &session->conn_list,
++ conn_list_entry) {
++ spin_lock_bh(&conn->cmd_list_lock);
++ list_for_each_entry(cmnd, &conn->cmd_list,
++ cmd_list_entry) {
++ if (cmnd == req)
++ continue;
++ if (all)
++ __cmnd_abort(cmnd);
++ else if (req_hdr->lun == cmnd_hdr(cmnd)->lun)
++ __cmnd_abort(cmnd);
++ }
++ spin_unlock_bh(&conn->cmd_list_lock);
++ }
++ }
++
++ mutex_unlock(&target->target_mutex);
++ return 0;
++}
++
++/* Must be called from the read or conn close thread */
++static void task_set_abort(struct iscsi_cmnd *req)
++{
++ struct iscsi_session *session = req->conn->session;
++ struct iscsi_task_mgt_hdr *req_hdr =
++ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
++ struct iscsi_target *target = session->target;
++ struct iscsi_conn *conn;
++ struct iscsi_cmnd *cmnd;
++
++ mutex_lock(&target->target_mutex);
++
++ list_for_each_entry(conn, &session->conn_list, conn_list_entry) {
++ spin_lock_bh(&conn->cmd_list_lock);
++ list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
++ struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
++ if (cmnd == req)
++ continue;
++ if (req_hdr->lun != hdr->lun)
++ continue;
++ if (before(req_hdr->cmd_sn, hdr->cmd_sn) ||
++ req_hdr->cmd_sn == hdr->cmd_sn)
++ continue;
++ __cmnd_abort(cmnd);
++ }
++ spin_unlock_bh(&conn->cmd_list_lock);
++ }
++
++ mutex_unlock(&target->target_mutex);
++ return;
++}
++
++/* Must be called from the read or conn close thread */
++void conn_abort(struct iscsi_conn *conn)
++{
++ struct iscsi_cmnd *cmnd, *r, *t;
++
++ TRACE_MGMT_DBG("Aborting conn %p", conn);
++
++ iscsi_extracheck_is_rd_thread(conn);
++
++ cancel_delayed_work_sync(&conn->nop_in_delayed_work);
++
++ /* No locks, we are the only user */
++ list_for_each_entry_safe(r, t, &conn->nop_req_list,
++ nop_req_list_entry) {
++ list_del(&r->nop_req_list_entry);
++ cmnd_put(r);
++ }
++
++ spin_lock_bh(&conn->cmd_list_lock);
++again:
++ list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
++ __cmnd_abort(cmnd);
++ if (cmnd->r2t_len_to_receive != 0) {
++ if (!cmnd_get_check(cmnd)) {
++ spin_unlock_bh(&conn->cmd_list_lock);
++
++ /* ToDo: this is racy for MC/S */
++ iscsi_fail_data_waiting_cmnd(cmnd);
++
++ cmnd_put(cmnd);
++
++ /*
++ * We are in the read thread, so we may not
++ * worry that after cmnd release conn gets
++ * released as well.
++ */
++ spin_lock_bh(&conn->cmd_list_lock);
++ goto again;
++ }
++ }
++ }
++ spin_unlock_bh(&conn->cmd_list_lock);
++
++ return;
++}
++
++static void execute_task_management(struct iscsi_cmnd *req)
++{
++ struct iscsi_conn *conn = req->conn;
++ struct iscsi_session *sess = conn->session;
++ struct iscsi_task_mgt_hdr *req_hdr =
++ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
++ int rc, status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ int function = req_hdr->function & ISCSI_FUNCTION_MASK;
++ struct scst_rx_mgmt_params params;
++
++ TRACE(TRACE_MGMT, "iSCSI TM fn %d", function);
++
++ TRACE_MGMT_DBG("TM req %p, ITT %x, RTT %x, sn %u, con %p", req,
++ req->pdu.bhs.itt, req_hdr->rtt, req_hdr->cmd_sn, conn);
++
++ iscsi_extracheck_is_rd_thread(conn);
++
++ spin_lock(&sess->sn_lock);
++ sess->tm_active++;
++ sess->tm_sn = req_hdr->cmd_sn;
++ if (sess->tm_rsp != NULL) {
++ struct iscsi_cmnd *tm_rsp = sess->tm_rsp;
++
++ TRACE_MGMT_DBG("Dropping delayed TM rsp %p", tm_rsp);
++
++ sess->tm_rsp = NULL;
++ sess->tm_active--;
++
++ spin_unlock(&sess->sn_lock);
++
++ BUG_ON(sess->tm_active < 0);
++
++ rsp_cmnd_release(tm_rsp);
++ } else
++ spin_unlock(&sess->sn_lock);
++
++ memset(&params, 0, sizeof(params));
++ params.atomic = SCST_NON_ATOMIC;
++ params.tgt_priv = req;
++
++ if ((function != ISCSI_FUNCTION_ABORT_TASK) &&
++ (req_hdr->rtt != ISCSI_RESERVED_TAG)) {
++ PRINT_ERROR("Invalid RTT %x (TM fn %d)", req_hdr->rtt,
++ function);
++ rc = -1;
++ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ goto reject;
++ }
++
++ /* cmd_sn is already in CPU format converted in cmnd_rx_start() */
++
++ switch (function) {
++ case ISCSI_FUNCTION_ABORT_TASK:
++ rc = cmnd_abort(req, &status);
++ if (rc == 0) {
++ params.fn = SCST_ABORT_TASK;
++ params.tag = (__force u32)req_hdr->rtt;
++ params.tag_set = 1;
++ params.lun = (uint8_t *)&req_hdr->lun;
++ params.lun_len = sizeof(req_hdr->lun);
++ params.lun_set = 1;
++ params.cmd_sn = req_hdr->cmd_sn;
++ params.cmd_sn_set = 1;
++ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
++ &params);
++ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ }
++ break;
++ case ISCSI_FUNCTION_ABORT_TASK_SET:
++ task_set_abort(req);
++ params.fn = SCST_ABORT_TASK_SET;
++ params.lun = (uint8_t *)&req_hdr->lun;
++ params.lun_len = sizeof(req_hdr->lun);
++ params.lun_set = 1;
++ params.cmd_sn = req_hdr->cmd_sn;
++ params.cmd_sn_set = 1;
++ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
++ &params);
++ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ break;
++ case ISCSI_FUNCTION_CLEAR_TASK_SET:
++ task_set_abort(req);
++ params.fn = SCST_CLEAR_TASK_SET;
++ params.lun = (uint8_t *)&req_hdr->lun;
++ params.lun_len = sizeof(req_hdr->lun);
++ params.lun_set = 1;
++ params.cmd_sn = req_hdr->cmd_sn;
++ params.cmd_sn_set = 1;
++ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
++ &params);
++ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ break;
++ case ISCSI_FUNCTION_CLEAR_ACA:
++ params.fn = SCST_CLEAR_ACA;
++ params.lun = (uint8_t *)&req_hdr->lun;
++ params.lun_len = sizeof(req_hdr->lun);
++ params.lun_set = 1;
++ params.cmd_sn = req_hdr->cmd_sn;
++ params.cmd_sn_set = 1;
++ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
++ &params);
++ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ break;
++ case ISCSI_FUNCTION_TARGET_COLD_RESET:
++ case ISCSI_FUNCTION_TARGET_WARM_RESET:
++ target_abort(req, 1);
++ params.fn = SCST_TARGET_RESET;
++ params.cmd_sn = req_hdr->cmd_sn;
++ params.cmd_sn_set = 1;
++ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
++ &params);
++ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ break;
++ case ISCSI_FUNCTION_LOGICAL_UNIT_RESET:
++ target_abort(req, 0);
++ params.fn = SCST_LUN_RESET;
++ params.lun = (uint8_t *)&req_hdr->lun;
++ params.lun_len = sizeof(req_hdr->lun);
++ params.lun_set = 1;
++ params.cmd_sn = req_hdr->cmd_sn;
++ params.cmd_sn_set = 1;
++ rc = scst_rx_mgmt_fn(conn->session->scst_sess,
++ &params);
++ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ break;
++ case ISCSI_FUNCTION_TASK_REASSIGN:
++ rc = -1;
++ status = ISCSI_RESPONSE_ALLEGIANCE_REASSIGNMENT_UNSUPPORTED;
++ break;
++ default:
++ PRINT_ERROR("Unknown TM function %d", function);
++ rc = -1;
++ status = ISCSI_RESPONSE_FUNCTION_REJECTED;
++ break;
++ }
++
++reject:
++ if (rc != 0)
++ iscsi_send_task_mgmt_resp(req, status);
++
++ return;
++}
++
++static void nop_out_exec(struct iscsi_cmnd *req)
++{
++ struct iscsi_cmnd *rsp;
++ struct iscsi_nop_in_hdr *rsp_hdr;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("%p", req);
++
++ if (req->pdu.bhs.itt != ISCSI_RESERVED_TAG) {
++ rsp = iscsi_alloc_main_rsp(req);
++
++ rsp_hdr = (struct iscsi_nop_in_hdr *)&rsp->pdu.bhs;
++ rsp_hdr->opcode = ISCSI_OP_NOP_IN;
++ rsp_hdr->flags = ISCSI_FLG_FINAL;
++ rsp_hdr->itt = req->pdu.bhs.itt;
++ rsp_hdr->ttt = ISCSI_RESERVED_TAG;
++
++ if (req->pdu.datasize)
++ BUG_ON(req->sg == NULL);
++ else
++ BUG_ON(req->sg != NULL);
++
++ if (req->sg) {
++ rsp->sg = req->sg;
++ rsp->sg_cnt = req->sg_cnt;
++ rsp->bufflen = req->bufflen;
++ }
++
++ /* We already checked it in check_segment_length() */
++ BUG_ON(get_pgcnt(req->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX);
++
++ rsp->pdu.datasize = req->pdu.datasize;
++ } else {
++ bool found = false;
++ struct iscsi_cmnd *r;
++ struct iscsi_conn *conn = req->conn;
++
++ TRACE_DBG("Receive Nop-In response (ttt 0x%08x)",
++ be32_to_cpu(req->pdu.bhs.ttt));
++
++ spin_lock_bh(&conn->nop_req_list_lock);
++ list_for_each_entry(r, &conn->nop_req_list,
++ nop_req_list_entry) {
++ if (req->pdu.bhs.ttt == r->pdu.bhs.ttt) {
++ list_del(&r->nop_req_list_entry);
++ found = true;
++ break;
++ }
++ }
++ spin_unlock_bh(&conn->nop_req_list_lock);
++
++ if (found)
++ cmnd_put(r);
++ else
++ TRACE_MGMT_DBG("%s", "Got Nop-out response without "
++ "corresponding Nop-In request");
++ }
++
++ req_cmnd_release(req);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void logout_exec(struct iscsi_cmnd *req)
++{
++ struct iscsi_logout_req_hdr *req_hdr;
++ struct iscsi_cmnd *rsp;
++ struct iscsi_logout_rsp_hdr *rsp_hdr;
++
++ PRINT_INFO("Logout received from initiator %s",
++ req->conn->session->initiator_name);
++ TRACE_DBG("%p", req);
++
++ req_hdr = (struct iscsi_logout_req_hdr *)&req->pdu.bhs;
++ rsp = iscsi_alloc_main_rsp(req);
++ rsp_hdr = (struct iscsi_logout_rsp_hdr *)&rsp->pdu.bhs;
++ rsp_hdr->opcode = ISCSI_OP_LOGOUT_RSP;
++ rsp_hdr->flags = ISCSI_FLG_FINAL;
++ rsp_hdr->itt = req_hdr->itt;
++ rsp->should_close_conn = 1;
++
++ req_cmnd_release(req);
++
++ return;
++}
++
++static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd)
++{
++ TRACE_ENTRY();
++
++ TRACE_DBG("cmnd %p, op %x, SN %u", cmnd, cmnd_opcode(cmnd),
++ cmnd->pdu.bhs.sn);
++
++ iscsi_extracheck_is_rd_thread(cmnd->conn);
++
++ if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_CMD) {
++ if (cmnd->r2t_len_to_receive == 0)
++ iscsi_restart_cmnd(cmnd);
++ else if (cmnd->r2t_len_to_send != 0)
++ send_r2t(cmnd);
++ goto out;
++ }
++
++ if (cmnd->prelim_compl_flags != 0) {
++ TRACE_MGMT_DBG("Terminating prelim completed non-SCSI cmnd %p "
++ "(op %x)", cmnd, cmnd_opcode(cmnd));
++ req_cmnd_release(cmnd);
++ goto out;
++ }
++
++ switch (cmnd_opcode(cmnd)) {
++ case ISCSI_OP_NOP_OUT:
++ nop_out_exec(cmnd);
++ break;
++ case ISCSI_OP_SCSI_TASK_MGT_MSG:
++ execute_task_management(cmnd);
++ break;
++ case ISCSI_OP_LOGOUT_CMD:
++ logout_exec(cmnd);
++ break;
++ default:
++ PRINT_CRIT_ERROR("Unexpected cmnd op %x", cmnd_opcode(cmnd));
++ BUG();
++ break;
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void set_cork(struct socket *sock, int on)
++{
++ int opt = on;
++ mm_segment_t oldfs;
++
++ oldfs = get_fs();
++ set_fs(get_ds());
++ sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK,
++ (void __force __user *)&opt, sizeof(opt));
++ set_fs(oldfs);
++ return;
++}
++
++void cmnd_tx_start(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++
++ TRACE_DBG("conn %p, cmnd %p, opcode %x", conn, cmnd, cmnd_opcode(cmnd));
++ iscsi_cmnd_set_length(&cmnd->pdu);
++
++ iscsi_extracheck_is_wr_thread(conn);
++
++ set_cork(conn->sock, 1);
++
++ conn->write_iop = conn->write_iov;
++ conn->write_iop->iov_base = (void __force __user *)(&cmnd->pdu.bhs);
++ conn->write_iop->iov_len = sizeof(cmnd->pdu.bhs);
++ conn->write_iop_used = 1;
++ conn->write_size = sizeof(cmnd->pdu.bhs) + cmnd->pdu.datasize;
++ conn->write_offset = 0;
++
++ switch (cmnd_opcode(cmnd)) {
++ case ISCSI_OP_NOP_IN:
++ if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG)
++ cmnd->pdu.bhs.sn = (__force u32)cmnd_set_sn(cmnd, 0);
++ else
++ cmnd_set_sn(cmnd, 1);
++ break;
++ case ISCSI_OP_SCSI_RSP:
++ cmnd_set_sn(cmnd, 1);
++ break;
++ case ISCSI_OP_SCSI_TASK_MGT_RSP:
++ cmnd_set_sn(cmnd, 1);
++ break;
++ case ISCSI_OP_TEXT_RSP:
++ cmnd_set_sn(cmnd, 1);
++ break;
++ case ISCSI_OP_SCSI_DATA_IN:
++ {
++ struct iscsi_data_in_hdr *rsp =
++ (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs;
++ u32 offset = be32_to_cpu(rsp->buffer_offset);
++
++ TRACE_DBG("cmnd %p, offset %u, datasize %u, bufflen %u", cmnd,
++ offset, cmnd->pdu.datasize, cmnd->bufflen);
++
++ BUG_ON(offset > cmnd->bufflen);
++ BUG_ON(offset + cmnd->pdu.datasize > cmnd->bufflen);
++
++ conn->write_offset = offset;
++
++ cmnd_set_sn(cmnd, (rsp->flags & ISCSI_FLG_FINAL) ? 1 : 0);
++ break;
++ }
++ case ISCSI_OP_LOGOUT_RSP:
++ cmnd_set_sn(cmnd, 1);
++ break;
++ case ISCSI_OP_R2T:
++ cmnd->pdu.bhs.sn = (__force u32)cmnd_set_sn(cmnd, 0);
++ break;
++ case ISCSI_OP_ASYNC_MSG:
++ cmnd_set_sn(cmnd, 1);
++ break;
++ case ISCSI_OP_REJECT:
++ cmnd_set_sn(cmnd, 1);
++ break;
++ default:
++ PRINT_ERROR("Unexpected cmnd op %x", cmnd_opcode(cmnd));
++ break;
++ }
++
++ iscsi_dump_pdu(&cmnd->pdu);
++ return;
++}
++
++void cmnd_tx_end(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++
++ TRACE_DBG("%p:%x (should_close_conn %d, should_close_all_conn %d)",
++ cmnd, cmnd_opcode(cmnd), cmnd->should_close_conn,
++ cmnd->should_close_all_conn);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ switch (cmnd_opcode(cmnd)) {
++ case ISCSI_OP_NOP_IN:
++ case ISCSI_OP_SCSI_RSP:
++ case ISCSI_OP_SCSI_TASK_MGT_RSP:
++ case ISCSI_OP_TEXT_RSP:
++ case ISCSI_OP_R2T:
++ case ISCSI_OP_ASYNC_MSG:
++ case ISCSI_OP_REJECT:
++ case ISCSI_OP_SCSI_DATA_IN:
++ case ISCSI_OP_LOGOUT_RSP:
++ break;
++ default:
++ PRINT_CRIT_ERROR("unexpected cmnd op %x", cmnd_opcode(cmnd));
++ BUG();
++ break;
++ }
++#endif
++
++ if (unlikely(cmnd->should_close_conn)) {
++ if (cmnd->should_close_all_conn) {
++ PRINT_INFO("Closing all connections for target %x at "
++ "initiator's %s request",
++ cmnd->conn->session->target->tid,
++ conn->session->initiator_name);
++ target_del_all_sess(cmnd->conn->session->target, 0);
++ } else {
++ PRINT_INFO("Closing connection at initiator's %s "
++ "request", conn->session->initiator_name);
++ mark_conn_closed(conn);
++ }
++ }
++
++ set_cork(cmnd->conn->sock, 0);
++ return;
++}
++
++/*
++ * Push the command for execution. This functions reorders the commands.
++ * Called from the read thread.
++ *
++ * Basically, since we don't support MC/S and TCP guarantees data delivery
++ * order, all that SN's stuff isn't needed at all (commands delivery order is
++ * a natural commands execution order), but insane iSCSI spec requires
++ * us to check it and we have to, because some crazy initiators can rely
++ * on the SN's based order and reorder requests during sending. For all other
++ * normal initiators all that code is a NOP.
++ */
++static void iscsi_push_cmnd(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_session *session = cmnd->conn->session;
++ struct list_head *entry;
++ u32 cmd_sn;
++
++ TRACE_DBG("cmnd %p, iSCSI opcode %x, sn %u, exp sn %u", cmnd,
++ cmnd_opcode(cmnd), cmnd->pdu.bhs.sn, session->exp_cmd_sn);
++
++ iscsi_extracheck_is_rd_thread(cmnd->conn);
++
++ BUG_ON(cmnd->parent_req != NULL);
++
++ if (cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) {
++ TRACE_DBG("Immediate cmd %p (cmd_sn %u)", cmnd,
++ cmnd->pdu.bhs.sn);
++ iscsi_cmnd_exec(cmnd);
++ goto out;
++ }
++
++ spin_lock(&session->sn_lock);
++
++ cmd_sn = cmnd->pdu.bhs.sn;
++ if (cmd_sn == session->exp_cmd_sn) {
++ while (1) {
++ session->exp_cmd_sn = ++cmd_sn;
++
++ if (unlikely(session->tm_active > 0)) {
++ if (before(cmd_sn, session->tm_sn)) {
++ struct iscsi_conn *conn = cmnd->conn;
++
++ spin_unlock(&session->sn_lock);
++
++ spin_lock_bh(&conn->cmd_list_lock);
++ __cmnd_abort(cmnd);
++ spin_unlock_bh(&conn->cmd_list_lock);
++
++ spin_lock(&session->sn_lock);
++ }
++ iscsi_check_send_delayed_tm_resp(session);
++ }
++
++ spin_unlock(&session->sn_lock);
++
++ iscsi_cmnd_exec(cmnd);
++
++ spin_lock(&session->sn_lock);
++
++ if (list_empty(&session->pending_list))
++ break;
++ cmnd = list_entry(session->pending_list.next,
++ struct iscsi_cmnd,
++ pending_list_entry);
++ if (cmnd->pdu.bhs.sn != cmd_sn)
++ break;
++
++ list_del(&cmnd->pending_list_entry);
++ cmnd->pending = 0;
++
++ TRACE_MGMT_DBG("Processing pending cmd %p (cmd_sn %u)",
++ cmnd, cmd_sn);
++ }
++ } else {
++ int drop = 0;
++
++ TRACE_DBG("Pending cmd %p (cmd_sn %u, exp_cmd_sn %u)",
++ cmnd, cmd_sn, session->exp_cmd_sn);
++
++ /*
++ * iSCSI RFC 3720: "The target MUST silently ignore any
++ * non-immediate command outside of [from ExpCmdSN to MaxCmdSN
++ * inclusive] range". But we won't honor the MaxCmdSN
++ * requirement, because, since we adjust MaxCmdSN from the
++ * separate write thread, rarely it is possible that initiator
++ * can legally send command with CmdSN>MaxSN. But it won't
++ * hurt anything, in the worst case it will lead to
++ * additional QUEUE FULL status.
++ */
++
++ if (unlikely(before(cmd_sn, session->exp_cmd_sn))) {
++ TRACE_MGMT_DBG("Ignoring out of expected range cmd_sn "
++ "(sn %u, exp_sn %u, op %x, CDB op %x)", cmd_sn,
++ session->exp_cmd_sn, cmnd_opcode(cmnd),
++ cmnd_scsicode(cmnd));
++ drop = 1;
++ }
++
++#if 0
++ if (unlikely(after(cmd_sn, session->exp_cmd_sn +
++ iscsi_get_allowed_cmds(session)))) {
++ TRACE_MGMT_DBG("Too large cmd_sn %u (exp_cmd_sn %u, "
++ "max_sn %u)", cmd_sn, session->exp_cmd_sn,
++ iscsi_get_allowed_cmds(session));
++ drop = 1;
++ }
++#endif
++
++ spin_unlock(&session->sn_lock);
++
++ if (unlikely(drop)) {
++ req_cmnd_release_force(cmnd);
++ goto out;
++ }
++
++ if (unlikely(test_bit(ISCSI_CMD_ABORTED,
++ &cmnd->prelim_compl_flags))) {
++ struct iscsi_cmnd *tm_clone;
++
++ TRACE_MGMT_DBG("Aborted pending cmnd %p, creating TM "
++ "clone (scst cmd %p, state %d)", cmnd,
++ cmnd->scst_cmd, cmnd->scst_state);
++
++ tm_clone = iscsi_create_tm_clone(cmnd);
++ if (tm_clone != NULL) {
++ iscsi_cmnd_exec(cmnd);
++ cmnd = tm_clone;
++ }
++ }
++
++ TRACE_MGMT_DBG("Pending cmnd %p (op %x, sn %u, exp sn %u)",
++ cmnd, cmnd_opcode(cmnd), cmd_sn, session->exp_cmd_sn);
++
++ spin_lock(&session->sn_lock);
++ list_for_each(entry, &session->pending_list) {
++ struct iscsi_cmnd *tmp =
++ list_entry(entry, struct iscsi_cmnd,
++ pending_list_entry);
++ if (before(cmd_sn, tmp->pdu.bhs.sn))
++ break;
++ }
++ list_add_tail(&cmnd->pending_list_entry, entry);
++ cmnd->pending = 1;
++ }
++
++ spin_unlock(&session->sn_lock);
++out:
++ return;
++}
++
++static int check_segment_length(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++ struct iscsi_session *session = conn->session;
++
++ if (unlikely(cmnd->pdu.datasize > session->sess_params.max_recv_data_length)) {
++ PRINT_ERROR("Initiator %s violated negotiated parameters: "
++ "data too long (ITT %x, datasize %u, "
++ "max_recv_data_length %u", session->initiator_name,
++ cmnd->pdu.bhs.itt, cmnd->pdu.datasize,
++ session->sess_params.max_recv_data_length);
++ mark_conn_closed(conn);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++int cmnd_rx_start(struct iscsi_cmnd *cmnd)
++{
++ int res, rc = 0;
++
++ iscsi_dump_pdu(&cmnd->pdu);
++
++ res = check_segment_length(cmnd);
++ if (res != 0)
++ goto out;
++
++ cmnd->pdu.bhs.sn = be32_to_cpu((__force __be32)cmnd->pdu.bhs.sn);
++
++ switch (cmnd_opcode(cmnd)) {
++ case ISCSI_OP_SCSI_CMD:
++ res = scsi_cmnd_start(cmnd);
++ if (unlikely(res < 0))
++ goto out;
++ update_stat_sn(cmnd);
++ break;
++ case ISCSI_OP_SCSI_DATA_OUT:
++ res = data_out_start(cmnd);
++ goto out;
++ case ISCSI_OP_NOP_OUT:
++ rc = nop_out_start(cmnd);
++ break;
++ case ISCSI_OP_SCSI_TASK_MGT_MSG:
++ case ISCSI_OP_LOGOUT_CMD:
++ update_stat_sn(cmnd);
++ break;
++ case ISCSI_OP_TEXT_CMD:
++ case ISCSI_OP_SNACK_CMD:
++ default:
++ rc = -ISCSI_REASON_UNSUPPORTED_COMMAND;
++ break;
++ }
++
++ if (unlikely(rc < 0)) {
++ PRINT_ERROR("Error %d (iSCSI opcode %x, ITT %x)", rc,
++ cmnd_opcode(cmnd), cmnd->pdu.bhs.itt);
++ res = create_reject_rsp(cmnd, -rc, true);
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++void cmnd_rx_end(struct iscsi_cmnd *cmnd)
++{
++ TRACE_ENTRY();
++
++ TRACE_DBG("cmnd %p, opcode %x", cmnd, cmnd_opcode(cmnd));
++
++ cmnd->conn->last_rcv_time = jiffies;
++ TRACE_DBG("Updated last_rcv_time %ld", cmnd->conn->last_rcv_time);
++
++ switch (cmnd_opcode(cmnd)) {
++ case ISCSI_OP_SCSI_CMD:
++ case ISCSI_OP_NOP_OUT:
++ case ISCSI_OP_SCSI_TASK_MGT_MSG:
++ case ISCSI_OP_LOGOUT_CMD:
++ iscsi_push_cmnd(cmnd);
++ goto out;
++ case ISCSI_OP_SCSI_DATA_OUT:
++ data_out_end(cmnd);
++ break;
++ default:
++ PRINT_ERROR("Unexpected cmnd op %x", cmnd_opcode(cmnd));
++ break;
++ }
++
++ req_cmnd_release(cmnd);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++static int iscsi_alloc_data_buf(struct scst_cmd *cmd)
++{
++ /*
++ * sock->ops->sendpage() is async zero copy operation,
++ * so we must be sure not to free and reuse
++ * the command's buffer before the sending was completed
++ * by the network layers. It is possible only if we
++ * don't use SGV cache.
++ */
++ EXTRACHECKS_BUG_ON(!(scst_cmd_get_data_direction(cmd) & SCST_DATA_READ));
++ scst_cmd_set_no_sgv(cmd);
++ return 1;
++}
++#endif
++
++static void iscsi_preprocessing_done(struct scst_cmd *scst_cmd)
++{
++ struct iscsi_cmnd *req = (struct iscsi_cmnd *)
++ scst_cmd_get_tgt_priv(scst_cmd);
++
++ TRACE_DBG("req %p", req);
++
++ if (req->conn->rx_task == current)
++ req->scst_state = ISCSI_CMD_STATE_AFTER_PREPROC;
++ else {
++ /*
++ * We wait for the state change without any protection, so
++ * without cmnd_get() it is possible that req will die
++ * "immediately" after the state assignment and
++ * iscsi_make_conn_rd_active() will operate on dead data.
++ * We use the ordered version of cmnd_get(), because "get"
++ * must be done before the state assignment.
++ *
++ * We protected from the race on calling cmnd_rx_continue(),
++ * because there can be only one read thread processing
++ * connection.
++ */
++ cmnd_get(req);
++ req->scst_state = ISCSI_CMD_STATE_AFTER_PREPROC;
++ iscsi_make_conn_rd_active(req->conn);
++ if (unlikely(req->conn->closing)) {
++ TRACE_DBG("Waking up closing conn %p", req->conn);
++ wake_up(&req->conn->read_state_waitQ);
++ }
++ cmnd_put(req);
++ }
++
++ return;
++}
++
++/* No locks */
++static void iscsi_try_local_processing(struct iscsi_cmnd *req)
++{
++ struct iscsi_conn *conn = req->conn;
++ bool local;
++
++ TRACE_ENTRY();
++
++ spin_lock_bh(&iscsi_wr_lock);
++ switch (conn->wr_state) {
++ case ISCSI_CONN_WR_STATE_IN_LIST:
++ list_del(&conn->wr_list_entry);
++ /* go through */
++ case ISCSI_CONN_WR_STATE_IDLE:
++#ifdef CONFIG_SCST_EXTRACHECKS
++ conn->wr_task = current;
++#endif
++ conn->wr_state = ISCSI_CONN_WR_STATE_PROCESSING;
++ conn->wr_space_ready = 0;
++ local = true;
++ break;
++ default:
++ local = false;
++ break;
++ }
++ spin_unlock_bh(&iscsi_wr_lock);
++
++ if (local) {
++ int rc = 1;
++
++ do {
++ rc = iscsi_send(conn);
++ if (rc <= 0)
++ break;
++ } while (req->not_processed_rsp_cnt != 0);
++
++ spin_lock_bh(&iscsi_wr_lock);
++#ifdef CONFIG_SCST_EXTRACHECKS
++ conn->wr_task = NULL;
++#endif
++ if ((rc == -EAGAIN) && !conn->wr_space_ready) {
++ TRACE_DBG("EAGAIN, setting WR_STATE_SPACE_WAIT "
++ "(conn %p)", conn);
++ conn->wr_state = ISCSI_CONN_WR_STATE_SPACE_WAIT;
++ } else if (test_write_ready(conn)) {
++ list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
++ conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
++ wake_up(&iscsi_wr_waitQ);
++ } else
++ conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
++ spin_unlock_bh(&iscsi_wr_lock);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
++{
++ int is_send_status = scst_cmd_get_is_send_status(scst_cmd);
++ struct iscsi_cmnd *req = (struct iscsi_cmnd *)
++ scst_cmd_get_tgt_priv(scst_cmd);
++ struct iscsi_conn *conn = req->conn;
++ int status = scst_cmd_get_status(scst_cmd);
++ u8 *sense = scst_cmd_get_sense_buffer(scst_cmd);
++ int sense_len = scst_cmd_get_sense_buffer_len(scst_cmd);
++ struct iscsi_cmnd *wr_rsp, *our_rsp;
++
++ EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
++
++ scst_cmd_set_tgt_priv(scst_cmd, NULL);
++
++ EXTRACHECKS_BUG_ON(req->scst_state != ISCSI_CMD_STATE_RESTARTED);
++
++ if (unlikely(scst_cmd_aborted(scst_cmd)))
++ set_bit(ISCSI_CMD_ABORTED, &req->prelim_compl_flags);
++
++ if (unlikely(req->prelim_compl_flags != 0)) {
++ if (test_bit(ISCSI_CMD_ABORTED, &req->prelim_compl_flags)) {
++ TRACE_MGMT_DBG("req %p (scst_cmd %p) aborted", req,
++ req->scst_cmd);
++ scst_set_delivery_status(req->scst_cmd,
++ SCST_CMD_DELIVERY_ABORTED);
++ req->scst_state = ISCSI_CMD_STATE_PROCESSED;
++ req_cmnd_release_force(req);
++ goto out;
++ }
++
++ TRACE_DBG("Prelim completed req %p", req);
++
++ /*
++ * We could preliminary have finished req before we
++ * knew its device, so check if we return correct sense
++ * format.
++ */
++ scst_check_convert_sense(scst_cmd);
++
++ if (!req->own_sg) {
++ req->sg = scst_cmd_get_sg(scst_cmd);
++ req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
++ }
++ } else {
++ EXTRACHECKS_BUG_ON(req->own_sg);
++ req->sg = scst_cmd_get_sg(scst_cmd);
++ req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
++ }
++
++ req->bufflen = scst_cmd_get_adjusted_resp_data_len(scst_cmd);
++
++ req->scst_state = ISCSI_CMD_STATE_PROCESSED;
++
++ TRACE_DBG("req %p, is_send_status=%x, req->bufflen=%d, req->sg=%p, "
++ "req->sg_cnt %d", req, is_send_status, req->bufflen, req->sg,
++ req->sg_cnt);
++
++ EXTRACHECKS_BUG_ON(req->hashed);
++ if (req->main_rsp != NULL)
++ EXTRACHECKS_BUG_ON(cmnd_opcode(req->main_rsp) != ISCSI_OP_REJECT);
++
++ if (unlikely((req->bufflen != 0) && !is_send_status)) {
++ PRINT_CRIT_ERROR("%s", "Sending DATA without STATUS is "
++ "unsupported");
++ scst_set_cmd_error(scst_cmd,
++ SCST_LOAD_SENSE(scst_sense_hardw_error));
++ BUG(); /* ToDo */
++ }
++
++ /*
++ * We need to decrement active_cmds before adding any responses into
++ * the write queue to eliminate a race, when all responses sent
++ * with wrong MaxCmdSN.
++ */
++ if (likely(req->dec_active_cmds))
++ iscsi_dec_active_cmds(req);
++
++ if (req->bufflen != 0) {
++ /*
++ * Check above makes sure that is_send_status is set,
++ * so status is valid here, but in future that could change.
++ * ToDo
++ */
++ if ((status != SAM_STAT_CHECK_CONDITION) &&
++ ((cmnd_hdr(req)->flags & (ISCSI_CMD_WRITE|ISCSI_CMD_READ)) !=
++ (ISCSI_CMD_WRITE|ISCSI_CMD_READ))) {
++ send_data_rsp(req, status, is_send_status);
++ } else {
++ struct iscsi_cmnd *rsp;
++ send_data_rsp(req, 0, 0);
++ if (is_send_status) {
++ rsp = create_status_rsp(req, status, sense,
++ sense_len);
++ iscsi_cmnd_init_write(rsp, 0);
++ }
++ }
++ } else if (is_send_status) {
++ struct iscsi_cmnd *rsp;
++ rsp = create_status_rsp(req, status, sense, sense_len);
++ iscsi_cmnd_init_write(rsp, 0);
++ }
++#ifdef CONFIG_SCST_EXTRACHECKS
++ else
++ BUG();
++#endif
++
++ /*
++ * There's no need for protection, since we are not going to
++ * dereference them.
++ */
++ wr_rsp = list_entry(conn->write_list.next, struct iscsi_cmnd,
++ write_list_entry);
++ our_rsp = list_entry(req->rsp_cmd_list.next, struct iscsi_cmnd,
++ rsp_cmd_list_entry);
++ if (wr_rsp == our_rsp) {
++ /*
++ * This is our rsp, so let's try to process it locally to
++ * decrease latency. We need to call pre_release before
++ * processing to handle some error recovery cases.
++ */
++ if (scst_get_active_cmd_count(scst_cmd) <= 2) {
++ req_cmnd_pre_release(req);
++ iscsi_try_local_processing(req);
++ cmnd_put(req);
++ } else {
++ /*
++ * There's too much backend activity, so it could be
++ * better to push it to the write thread.
++ */
++ goto out_push_to_wr_thread;
++ }
++ } else
++ goto out_push_to_wr_thread;
++
++out:
++ return SCST_TGT_RES_SUCCESS;
++
++out_push_to_wr_thread:
++ TRACE_DBG("Waking up write thread (conn %p)", conn);
++ req_cmnd_release(req);
++ iscsi_make_conn_wr_active(conn);
++ goto out;
++}
++
++/* Called under sn_lock */
++static bool iscsi_is_delay_tm_resp(struct iscsi_cmnd *rsp)
++{
++ bool res = 0;
++ struct iscsi_task_mgt_hdr *req_hdr =
++ (struct iscsi_task_mgt_hdr *)&rsp->parent_req->pdu.bhs;
++ int function = req_hdr->function & ISCSI_FUNCTION_MASK;
++ struct iscsi_session *sess = rsp->conn->session;
++
++ TRACE_ENTRY();
++
++ /* This should be checked for immediate TM commands as well */
++
++ switch (function) {
++ default:
++ if (before(sess->exp_cmd_sn, req_hdr->cmd_sn))
++ res = 1;
++ break;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Called under sn_lock, but might drop it inside, then reaquire */
++static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess)
++ __acquires(&sn_lock)
++ __releases(&sn_lock)
++{
++ struct iscsi_cmnd *tm_rsp = sess->tm_rsp;
++
++ TRACE_ENTRY();
++
++ if (tm_rsp == NULL)
++ goto out;
++
++ if (iscsi_is_delay_tm_resp(tm_rsp))
++ goto out;
++
++ TRACE_MGMT_DBG("Sending delayed rsp %p", tm_rsp);
++
++ sess->tm_rsp = NULL;
++ sess->tm_active--;
++
++ spin_unlock(&sess->sn_lock);
++
++ BUG_ON(sess->tm_active < 0);
++
++ iscsi_cmnd_init_write(tm_rsp, ISCSI_INIT_WRITE_WAKE);
++
++ spin_lock(&sess->sn_lock);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
++{
++ struct iscsi_cmnd *rsp;
++ struct iscsi_task_mgt_hdr *req_hdr =
++ (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
++ struct iscsi_task_rsp_hdr *rsp_hdr;
++ struct iscsi_session *sess = req->conn->session;
++ int fn = req_hdr->function & ISCSI_FUNCTION_MASK;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("TM req %p finished", req);
++ TRACE(TRACE_MGMT, "iSCSI TM fn %d finished, status %d", fn, status);
++
++ rsp = iscsi_alloc_rsp(req);
++ rsp_hdr = (struct iscsi_task_rsp_hdr *)&rsp->pdu.bhs;
++
++ rsp_hdr->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP;
++ rsp_hdr->flags = ISCSI_FLG_FINAL;
++ rsp_hdr->itt = req_hdr->itt;
++ rsp_hdr->response = status;
++
++ if (fn == ISCSI_FUNCTION_TARGET_COLD_RESET) {
++ rsp->should_close_conn = 1;
++ rsp->should_close_all_conn = 1;
++ }
++
++ BUG_ON(sess->tm_rsp != NULL);
++
++ spin_lock(&sess->sn_lock);
++ if (iscsi_is_delay_tm_resp(rsp)) {
++ TRACE_MGMT_DBG("Delaying TM fn %d response %p "
++ "(req %p), because not all affected commands "
++ "received (TM cmd sn %u, exp sn %u)",
++ req_hdr->function & ISCSI_FUNCTION_MASK, rsp, req,
++ req_hdr->cmd_sn, sess->exp_cmd_sn);
++ sess->tm_rsp = rsp;
++ spin_unlock(&sess->sn_lock);
++ goto out_release;
++ }
++ sess->tm_active--;
++ spin_unlock(&sess->sn_lock);
++
++ BUG_ON(sess->tm_active < 0);
++
++ iscsi_cmnd_init_write(rsp, ISCSI_INIT_WRITE_WAKE);
++
++out_release:
++ req_cmnd_release(req);
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline int iscsi_get_mgmt_response(int status)
++{
++ switch (status) {
++ case SCST_MGMT_STATUS_SUCCESS:
++ return ISCSI_RESPONSE_FUNCTION_COMPLETE;
++
++ case SCST_MGMT_STATUS_TASK_NOT_EXIST:
++ return ISCSI_RESPONSE_UNKNOWN_TASK;
++
++ case SCST_MGMT_STATUS_LUN_NOT_EXIST:
++ return ISCSI_RESPONSE_UNKNOWN_LUN;
++
++ case SCST_MGMT_STATUS_FN_NOT_SUPPORTED:
++ return ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;
++
++ case SCST_MGMT_STATUS_REJECTED:
++ case SCST_MGMT_STATUS_FAILED:
++ default:
++ return ISCSI_RESPONSE_FUNCTION_REJECTED;
++ }
++}
++
++static void iscsi_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
++{
++ int fn = scst_mgmt_cmd_get_fn(scst_mcmd);
++ struct iscsi_cmnd *req = (struct iscsi_cmnd *)
++ scst_mgmt_cmd_get_tgt_priv(scst_mcmd);
++ int status =
++ iscsi_get_mgmt_response(scst_mgmt_cmd_get_status(scst_mcmd));
++
++ if ((status == ISCSI_RESPONSE_UNKNOWN_TASK) &&
++ (fn == SCST_ABORT_TASK)) {
++ /* If we are here, we found the task, so must succeed */
++ status = ISCSI_RESPONSE_FUNCTION_COMPLETE;
++ }
++
++ TRACE_MGMT_DBG("req %p, scst_mcmd %p, fn %d, scst status %d, status %d",
++ req, scst_mcmd, fn, scst_mgmt_cmd_get_status(scst_mcmd),
++ status);
++
++ switch (fn) {
++ case SCST_NEXUS_LOSS_SESS:
++ case SCST_ABORT_ALL_TASKS_SESS:
++ /* They are internal */
++ break;
++ default:
++ iscsi_send_task_mgmt_resp(req, status);
++ scst_mgmt_cmd_set_tgt_priv(scst_mcmd, NULL);
++ break;
++ }
++ return;
++}
++
++static int iscsi_scsi_aen(struct scst_aen *aen)
++{
++ int res = SCST_AEN_RES_SUCCESS;
++ __be64 lun = scst_aen_get_lun(aen);
++ const uint8_t *sense = scst_aen_get_sense(aen);
++ int sense_len = scst_aen_get_sense_len(aen);
++ struct iscsi_session *sess = scst_sess_get_tgt_priv(
++ scst_aen_get_sess(aen));
++ struct iscsi_conn *conn;
++ bool found;
++ struct iscsi_cmnd *fake_req, *rsp;
++ struct iscsi_async_msg_hdr *rsp_hdr;
++ struct scatterlist *sg;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("SCSI AEN to sess %p (initiator %s)", sess,
++ sess->initiator_name);
++
++ mutex_lock(&sess->target->target_mutex);
++
++ found = false;
++ list_for_each_entry_reverse(conn, &sess->conn_list, conn_list_entry) {
++ if (!test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags) &&
++ (conn->conn_reinst_successor == NULL)) {
++ found = true;
++ break;
++ }
++ }
++ if (!found) {
++ TRACE_MGMT_DBG("Unable to find alive conn for sess %p", sess);
++ goto out_err;
++ }
++
++ /* Create a fake request */
++ fake_req = cmnd_alloc(conn, NULL);
++ if (fake_req == NULL) {
++ PRINT_ERROR("%s", "Unable to alloc fake AEN request");
++ goto out_err;
++ }
++
++ mutex_unlock(&sess->target->target_mutex);
++
++ rsp = iscsi_alloc_main_rsp(fake_req);
++ if (rsp == NULL) {
++ PRINT_ERROR("%s", "Unable to alloc AEN rsp");
++ goto out_err_free_req;
++ }
++
++ fake_req->scst_state = ISCSI_CMD_STATE_AEN;
++ fake_req->scst_aen = aen;
++
++ rsp_hdr = (struct iscsi_async_msg_hdr *)&rsp->pdu.bhs;
++
++ rsp_hdr->opcode = ISCSI_OP_ASYNC_MSG;
++ rsp_hdr->flags = ISCSI_FLG_FINAL;
++ rsp_hdr->lun = lun; /* it's already in SCSI form */
++ rsp_hdr->ffffffff = __constant_cpu_to_be32(0xffffffff);
++ rsp_hdr->async_event = ISCSI_ASYNC_SCSI;
++
++ sg = rsp->sg = rsp->rsp_sg;
++ rsp->sg_cnt = 2;
++ rsp->own_sg = 1;
++
++ sg_init_table(sg, 2);
++ sg_set_buf(&sg[0], &rsp->sense_hdr, sizeof(rsp->sense_hdr));
++ sg_set_buf(&sg[1], sense, sense_len);
++
++ rsp->sense_hdr.length = cpu_to_be16(sense_len);
++ rsp->pdu.datasize = sizeof(rsp->sense_hdr) + sense_len;
++ rsp->bufflen = rsp->pdu.datasize;
++
++ req_cmnd_release(fake_req);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_err_free_req:
++ req_cmnd_release(fake_req);
++
++out_err:
++ mutex_unlock(&sess->target->target_mutex);
++ res = SCST_AEN_RES_FAILED;
++ goto out;
++}
++
++static int iscsi_report_aen(struct scst_aen *aen)
++{
++ int res;
++ int event_fn = scst_aen_get_event_fn(aen);
++
++ TRACE_ENTRY();
++
++ switch (event_fn) {
++ case SCST_AEN_SCSI:
++ res = iscsi_scsi_aen(aen);
++ break;
++ default:
++ TRACE_MGMT_DBG("Unsupported AEN %d", event_fn);
++ res = SCST_AEN_RES_NOT_SUPPORTED;
++ break;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int iscsi_get_initiator_port_transport_id(struct scst_session *scst_sess,
++ uint8_t **transport_id)
++{
++ struct iscsi_session *sess;
++ int res = 0;
++ union iscsi_sid sid;
++ int tr_id_size;
++ uint8_t *tr_id;
++ uint8_t q;
++
++ TRACE_ENTRY();
++
++ if (scst_sess == NULL) {
++ res = SCSI_TRANSPORTID_PROTOCOLID_ISCSI;
++ goto out;
++ }
++
++ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
++
++ sid = *(union iscsi_sid *)&sess->sid;
++ sid.id.tsih = 0;
++
++ tr_id_size = 4 + strlen(sess->initiator_name) + 5 +
++ snprintf(&q, sizeof(q), "%llx", sid.id64) + 1;
++ tr_id_size = (tr_id_size + 3) & -4;
++
++ tr_id = kzalloc(tr_id_size, GFP_KERNEL);
++ if (tr_id == NULL) {
++ PRINT_ERROR("Allocation of TransportID (size %d) failed",
++ tr_id_size);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ tr_id[0] = 0x40 | SCSI_TRANSPORTID_PROTOCOLID_ISCSI;
++ sprintf(&tr_id[4], "%s,i,0x%llx", sess->initiator_name, sid.id64);
++
++ put_unaligned(cpu_to_be16(tr_id_size - 4),
++ (__be16 *)&tr_id[2]);
++
++ *transport_id = tr_id;
++
++ TRACE_DBG("Created tid '%s'", &tr_id[4]);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++void iscsi_send_nop_in(struct iscsi_conn *conn)
++{
++ struct iscsi_cmnd *req, *rsp;
++ struct iscsi_nop_in_hdr *rsp_hdr;
++
++ TRACE_ENTRY();
++
++ req = cmnd_alloc(conn, NULL);
++ if (req == NULL) {
++ PRINT_ERROR("%s", "Unable to alloc fake Nop-In request");
++ goto out_err;
++ }
++
++ rsp = iscsi_alloc_main_rsp(req);
++ if (rsp == NULL) {
++ PRINT_ERROR("%s", "Unable to alloc Nop-In rsp");
++ goto out_err_free_req;
++ }
++
++ cmnd_get(rsp);
++
++ rsp_hdr = (struct iscsi_nop_in_hdr *)&rsp->pdu.bhs;
++ rsp_hdr->opcode = ISCSI_OP_NOP_IN;
++ rsp_hdr->flags = ISCSI_FLG_FINAL;
++ rsp_hdr->itt = ISCSI_RESERVED_TAG;
++ rsp_hdr->ttt = (__force __be32)conn->nop_in_ttt++;
++
++ if (conn->nop_in_ttt == ISCSI_RESERVED_TAG_CPU32)
++ conn->nop_in_ttt = 0;
++
++ /* Supposed that all other fields are zeroed */
++
++ TRACE_DBG("Sending Nop-In request (ttt 0x%08x)", rsp_hdr->ttt);
++ spin_lock_bh(&conn->nop_req_list_lock);
++ list_add_tail(&rsp->nop_req_list_entry, &conn->nop_req_list);
++ spin_unlock_bh(&conn->nop_req_list_lock);
++
++out_err_free_req:
++ req_cmnd_release(req);
++
++out_err:
++ TRACE_EXIT();
++ return;
++}
++
++static int iscsi_target_detect(struct scst_tgt_template *templ)
++{
++ /* Nothing to do */
++ return 0;
++}
++
++static int iscsi_target_release(struct scst_tgt *scst_tgt)
++{
++ /* Nothing to do */
++ return 0;
++}
++
++static struct scst_trace_log iscsi_local_trace_tbl[] = {
++ { TRACE_D_WRITE, "d_write" },
++ { TRACE_CONN_OC, "conn" },
++ { TRACE_CONN_OC_DBG, "conn_dbg" },
++ { TRACE_D_IOV, "iov" },
++ { TRACE_D_DUMP_PDU, "pdu" },
++ { TRACE_NET_PG, "net_page" },
++ { 0, NULL }
++};
++
++#define ISCSI_TRACE_TBL_HELP ", d_write, conn, conn_dbg, iov, pdu, net_page"
++
++static uint16_t iscsi_get_scsi_transport_version(struct scst_tgt *scst_tgt)
++{
++ return 0x0960; /* iSCSI */
++}
++
++struct scst_tgt_template iscsi_template = {
++ .name = "iscsi",
++ .sg_tablesize = 0xFFFF /* no limit */,
++ .threads_num = 0,
++ .no_clustering = 1,
++ .xmit_response_atomic = 0,
++ .tgtt_attrs = iscsi_attrs,
++ .tgt_attrs = iscsi_tgt_attrs,
++ .sess_attrs = iscsi_sess_attrs,
++ .enable_target = iscsi_enable_target,
++ .is_target_enabled = iscsi_is_target_enabled,
++ .add_target = iscsi_sysfs_add_target,
++ .del_target = iscsi_sysfs_del_target,
++ .mgmt_cmd = iscsi_sysfs_mgmt_cmd,
++ .tgtt_optional_attributes = "IncomingUser, OutgoingUser",
++ .tgt_optional_attributes = "IncomingUser, OutgoingUser, allowed_portal",
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = ISCSI_DEFAULT_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++ .trace_tbl = iscsi_local_trace_tbl,
++ .trace_tbl_help = ISCSI_TRACE_TBL_HELP,
++#endif
++ .detect = iscsi_target_detect,
++ .release = iscsi_target_release,
++ .xmit_response = iscsi_xmit_response,
++#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ .alloc_data_buf = iscsi_alloc_data_buf,
++#endif
++ .preprocessing_done = iscsi_preprocessing_done,
++ .pre_exec = iscsi_pre_exec,
++ .task_mgmt_affected_cmds_done = iscsi_task_mgmt_affected_cmds_done,
++ .task_mgmt_fn_done = iscsi_task_mgmt_fn_done,
++ .report_aen = iscsi_report_aen,
++ .get_initiator_port_transport_id = iscsi_get_initiator_port_transport_id,
++ .get_scsi_transport_version = iscsi_get_scsi_transport_version,
++};
++
++static __init int iscsi_run_threads(int count, char *name, int (*fn)(void *))
++{
++ int res = 0;
++ int i;
++ struct iscsi_thread_t *thr;
++
++ for (i = 0; i < count; i++) {
++ thr = kmalloc(sizeof(*thr), GFP_KERNEL);
++ if (!thr) {
++ res = -ENOMEM;
++ PRINT_ERROR("Failed to allocate thr %d", res);
++ goto out;
++ }
++ thr->thr = kthread_run(fn, NULL, "%s%d", name, i);
++ if (IS_ERR(thr->thr)) {
++ res = PTR_ERR(thr->thr);
++ PRINT_ERROR("kthread_create() failed: %d", res);
++ kfree(thr);
++ goto out;
++ }
++ list_add_tail(&thr->threads_list_entry, &iscsi_threads_list);
++ }
++
++out:
++ return res;
++}
++
++static void iscsi_stop_threads(void)
++{
++ struct iscsi_thread_t *t, *tmp;
++
++ list_for_each_entry_safe(t, tmp, &iscsi_threads_list,
++ threads_list_entry) {
++ int rc = kthread_stop(t->thr);
++ if (rc < 0)
++ TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
++ list_del(&t->threads_list_entry);
++ kfree(t);
++ }
++ return;
++}
++
++static int __init iscsi_init(void)
++{
++ int err = 0;
++ int num;
++
++ PRINT_INFO("iSCSI SCST Target - version %s", ISCSI_VERSION_STRING);
++
++ dummy_page = alloc_pages(GFP_KERNEL, 0);
++ if (dummy_page == NULL) {
++ PRINT_ERROR("%s", "Dummy page allocation failed");
++ goto out;
++ }
++
++ sg_init_table(&dummy_sg, 1);
++ sg_set_page(&dummy_sg, dummy_page, PAGE_SIZE, 0);
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ err = net_set_get_put_page_callbacks(iscsi_get_page_callback,
++ iscsi_put_page_callback);
++ if (err != 0) {
++ PRINT_INFO("Unable to set page callbackes: %d", err);
++ goto out_free_dummy;
++ }
++#else
++#ifndef GENERATING_UPSTREAM_PATCH
++ PRINT_WARNING("%s",
++ "CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION "
++ "not enabled in your kernel. ISCSI-SCST will be working with "
++ "not the best performance. Refer README file for details.");
++#endif
++#endif
++
++ ctr_major = register_chrdev(0, ctr_name, &ctr_fops);
++ if (ctr_major < 0) {
++ PRINT_ERROR("failed to register the control device %d",
++ ctr_major);
++ err = ctr_major;
++ goto out_callb;
++ }
++
++ err = event_init();
++ if (err < 0)
++ goto out_reg;
++
++ iscsi_cmnd_cache = KMEM_CACHE(iscsi_cmnd, SCST_SLAB_FLAGS);
++ if (!iscsi_cmnd_cache) {
++ err = -ENOMEM;
++ goto out_event;
++ }
++
++ err = scst_register_target_template(&iscsi_template);
++ if (err < 0)
++ goto out_kmem;
++
++ iscsi_conn_ktype.sysfs_ops = scst_sysfs_get_sysfs_ops();
++
++ num = max((int)num_online_cpus(), 2);
++
++ err = iscsi_run_threads(num, "iscsird", istrd);
++ if (err != 0)
++ goto out_thr;
++
++ err = iscsi_run_threads(num, "iscsiwr", istwr);
++ if (err != 0)
++ goto out_thr;
++
++out:
++ return err;
++
++out_thr:
++ iscsi_stop_threads();
++
++ scst_unregister_target_template(&iscsi_template);
++
++out_kmem:
++ kmem_cache_destroy(iscsi_cmnd_cache);
++
++out_event:
++ event_exit();
++
++out_reg:
++ unregister_chrdev(ctr_major, ctr_name);
++
++out_callb:
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ net_set_get_put_page_callbacks(NULL, NULL);
++
++out_free_dummy:
++#endif
++ __free_pages(dummy_page, 0);
++ goto out;
++}
++
++static void __exit iscsi_exit(void)
++{
++ iscsi_stop_threads();
++
++ unregister_chrdev(ctr_major, ctr_name);
++
++ event_exit();
++
++ kmem_cache_destroy(iscsi_cmnd_cache);
++
++ scst_unregister_target_template(&iscsi_template);
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ net_set_get_put_page_callbacks(NULL, NULL);
++#endif
++
++ __free_pages(dummy_page, 0);
++ return;
++}
++
++module_init(iscsi_init);
++module_exit(iscsi_exit);
++
++MODULE_VERSION(ISCSI_VERSION_STRING);
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCST iSCSI Target");
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/iscsi_dbg.h linux-2.6.36/drivers/scst/iscsi-scst/iscsi_dbg.h
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/iscsi_dbg.h
++++ linux-2.6.36/drivers/scst/iscsi-scst/iscsi_dbg.h
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef ISCSI_DBG_H
++#define ISCSI_DBG_H
++
++#define LOG_PREFIX "iscsi-scst"
++
++#include <scst/scst_debug.h>
++
++#define TRACE_D_WRITE 0x80000000
++#define TRACE_CONN_OC 0x40000000
++#define TRACE_D_IOV 0x20000000
++#define TRACE_D_DUMP_PDU 0x10000000
++#define TRACE_NET_PG 0x08000000
++#define TRACE_CONN_OC_DBG 0x04000000
++
++#ifdef CONFIG_SCST_DEBUG
++#define ISCSI_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_LINE | TRACE_PID | \
++ TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_DEBUG | \
++ TRACE_MINOR | TRACE_SPECIAL | TRACE_CONN_OC)
++#else
++#define ISCSI_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
++ TRACE_SPECIAL)
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++struct iscsi_pdu;
++struct iscsi_cmnd;
++extern void iscsi_dump_pdu(struct iscsi_pdu *pdu);
++extern unsigned long iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(
++ struct iscsi_cmnd *cmnd);
++#else
++#define iscsi_dump_pdu(x) do {} while (0)
++#define iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(x) do {} while (0)
++#endif
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++extern unsigned long iscsi_trace_flag;
++#define trace_flag iscsi_trace_flag
++#endif
++
++#define TRACE_CONN_CLOSE(args...) TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_CONN_OC, args)
++#define TRACE_CONN_CLOSE_DBG(args...) TRACE(TRACE_CONN_OC_DBG, args)
++#define TRACE_NET_PAGE(args...) TRACE_DBG_FLAG(TRACE_NET_PG, args)
++#define TRACE_WRITE(args...) TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_D_WRITE, args)
++
++#endif
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/iscsi.h linux-2.6.36/drivers/scst/iscsi-scst/iscsi.h
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/iscsi.h
++++ linux-2.6.36/drivers/scst/iscsi-scst/iscsi.h
+@@ -0,0 +1,743 @@
++/*
++ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef __ISCSI_H__
++#define __ISCSI_H__
++
++#include <linux/pagemap.h>
++#include <linux/mm.h>
++#include <linux/net.h>
++#include <net/sock.h>
++
++#include <scst/scst.h>
++#include <scst/iscsi_scst.h>
++#include "iscsi_hdr.h"
++#include "iscsi_dbg.h"
++
++#define iscsi_sense_crc_error ABORTED_COMMAND, 0x47, 0x05
++#define iscsi_sense_unexpected_unsolicited_data ABORTED_COMMAND, 0x0C, 0x0C
++#define iscsi_sense_incorrect_amount_of_data ABORTED_COMMAND, 0x0C, 0x0D
++
++struct iscsi_sess_params {
++ int initial_r2t;
++ int immediate_data;
++ int max_connections;
++ unsigned int max_recv_data_length;
++ unsigned int max_xmit_data_length;
++ unsigned int max_burst_length;
++ unsigned int first_burst_length;
++ int default_wait_time;
++ int default_retain_time;
++ unsigned int max_outstanding_r2t;
++ int data_pdu_inorder;
++ int data_sequence_inorder;
++ int error_recovery_level;
++ int header_digest;
++ int data_digest;
++ int ofmarker;
++ int ifmarker;
++ int ofmarkint;
++ int ifmarkint;
++};
++
++struct iscsi_tgt_params {
++ int queued_cmnds;
++ unsigned int rsp_timeout;
++ unsigned int nop_in_interval;
++};
++
++struct network_thread_info {
++ struct task_struct *task;
++ unsigned int ready;
++};
++
++struct iscsi_target;
++struct iscsi_cmnd;
++
++struct iscsi_attr {
++ struct list_head attrs_list_entry;
++ struct kobj_attribute attr;
++ struct iscsi_target *target;
++ const char *name;
++};
++
++struct iscsi_target {
++ struct scst_tgt *scst_tgt;
++
++ struct mutex target_mutex;
++
++ struct list_head session_list; /* protected by target_mutex */
++
++ struct list_head target_list_entry;
++ u32 tid;
++
++ unsigned int tgt_enabled:1;
++
++ /* Protected by target_mutex */
++ struct list_head attrs_list;
++
++ char name[ISCSI_NAME_LEN];
++};
++
++#define ISCSI_HASH_ORDER 8
++#define cmnd_hashfn(itt) (BUILD_BUG_ON(!__same_type(itt, __be32)), \
++ hash_long((__force u32)(itt), ISCSI_HASH_ORDER))
++
++struct iscsi_session {
++ struct iscsi_target *target;
++ struct scst_session *scst_sess;
++
++ struct list_head pending_list; /* protected by sn_lock */
++
++ /* Unprotected, since accessed only from a single read thread */
++ u32 next_ttt;
++
++ /* Read only, if there are connection(s) */
++ struct iscsi_tgt_params tgt_params;
++ atomic_t active_cmds;
++
++ spinlock_t sn_lock;
++ u32 exp_cmd_sn; /* protected by sn_lock */
++
++ /* All 3 protected by sn_lock */
++ int tm_active;
++ u32 tm_sn;
++ struct iscsi_cmnd *tm_rsp;
++
++ /* Read only, if there are connection(s) */
++ struct iscsi_sess_params sess_params;
++
++ /*
++ * In some corner cases commands can be deleted from the hash
++ * not from the corresponding read thread. So, let's simplify
++ * errors recovery and have this lock.
++ */
++ spinlock_t cmnd_data_wait_hash_lock;
++ struct list_head cmnd_data_wait_hash[1 << ISCSI_HASH_ORDER];
++
++ struct list_head conn_list; /* protected by target_mutex */
++
++ struct list_head session_list_entry;
++
++ /* All protected by target_mutex, where necessary */
++ struct iscsi_session *sess_reinst_successor;
++ unsigned int sess_reinstating:1;
++ unsigned int sess_shutting_down:1;
++
++ /* All don't need any protection */
++ char *initiator_name;
++ u64 sid;
++};
++
++#define ISCSI_CONN_IOV_MAX (PAGE_SIZE/sizeof(struct iovec))
++
++#define ISCSI_CONN_RD_STATE_IDLE 0
++#define ISCSI_CONN_RD_STATE_IN_LIST 1
++#define ISCSI_CONN_RD_STATE_PROCESSING 2
++
++#define ISCSI_CONN_WR_STATE_IDLE 0
++#define ISCSI_CONN_WR_STATE_IN_LIST 1
++#define ISCSI_CONN_WR_STATE_SPACE_WAIT 2
++#define ISCSI_CONN_WR_STATE_PROCESSING 3
++
++struct iscsi_conn {
++ struct iscsi_session *session; /* owning session */
++
++ /* Both protected by session->sn_lock */
++ u32 stat_sn;
++ u32 exp_stat_sn;
++
++#define ISCSI_CONN_REINSTATING 1
++#define ISCSI_CONN_SHUTTINGDOWN 2
++ unsigned long conn_aflags;
++
++ spinlock_t cmd_list_lock; /* BH lock */
++
++ /* Protected by cmd_list_lock */
++ struct list_head cmd_list; /* in/outcoming pdus */
++
++ atomic_t conn_ref_cnt;
++
++ spinlock_t write_list_lock;
++ /* List of data pdus to be sent. Protected by write_list_lock */
++ struct list_head write_list;
++ /* List of data pdus being sent. Protected by write_list_lock */
++ struct list_head write_timeout_list;
++
++ /* Protected by write_list_lock */
++ struct timer_list rsp_timer;
++ unsigned int rsp_timeout; /* in jiffies */
++
++ /*
++ * All 2 protected by iscsi_wr_lock. Modified independently to the
++ * above field, hence the alignment.
++ */
++ unsigned short wr_state __attribute__((aligned(sizeof(long))));
++ unsigned short wr_space_ready:1;
++
++ struct list_head wr_list_entry;
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ struct task_struct *wr_task;
++#endif
++
++ /*
++ * All are unprotected, since accessed only from a single write
++ * thread.
++ */
++ struct iscsi_cmnd *write_cmnd;
++ struct iovec *write_iop;
++ int write_iop_used;
++ struct iovec write_iov[2];
++ u32 write_size;
++ u32 write_offset;
++ int write_state;
++
++ /* Both don't need any protection */
++ struct file *file;
++ struct socket *sock;
++
++ void (*old_state_change)(struct sock *);
++ void (*old_data_ready)(struct sock *, int);
++ void (*old_write_space)(struct sock *);
++
++ /* Both read only. Stay here for better CPU cache locality. */
++ int hdigest_type;
++ int ddigest_type;
++
++ /* All 6 protected by iscsi_rd_lock */
++ unsigned short rd_state;
++ unsigned short rd_data_ready:1;
++ /* Let's save some cache footprint by putting them here */
++ unsigned short closing:1;
++ unsigned short active_close:1;
++ unsigned short deleting:1;
++ unsigned short conn_tm_active:1;
++
++ struct list_head rd_list_entry;
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ struct task_struct *rd_task;
++#endif
++
++ unsigned long last_rcv_time;
++
++ /*
++ * All are unprotected, since accessed only from a single read
++ * thread.
++ */
++ struct iscsi_cmnd *read_cmnd;
++ struct msghdr read_msg;
++ u32 read_size;
++ int read_state;
++ struct iovec *read_iov;
++ struct task_struct *rx_task;
++ uint32_t rpadding;
++
++ struct iscsi_target *target;
++
++ struct list_head conn_list_entry; /* list entry in session conn_list */
++
++ /* All protected by target_mutex, where necessary */
++ struct iscsi_conn *conn_reinst_successor;
++ struct list_head reinst_pending_cmd_list;
++
++ wait_queue_head_t read_state_waitQ;
++ struct completion ready_to_free;
++
++ /* Doesn't need any protection */
++ u16 cid;
++
++ struct delayed_work nop_in_delayed_work;
++ unsigned int nop_in_interval; /* in jiffies */
++ struct list_head nop_req_list;
++ spinlock_t nop_req_list_lock;
++ u32 nop_in_ttt;
++
++ /* Don't need any protection */
++ struct kobject conn_kobj;
++ struct completion conn_kobj_release_cmpl;
++};
++
++struct iscsi_pdu {
++ struct iscsi_hdr bhs;
++ void *ahs;
++ unsigned int ahssize;
++ unsigned int datasize;
++};
++
++typedef void (iscsi_show_info_t)(struct seq_file *seq,
++ struct iscsi_target *target);
++
++/** Commands' states **/
++
++/* New command and SCST processes it */
++#define ISCSI_CMD_STATE_NEW 0
++
++/* SCST processes cmd after scst_rx_cmd() */
++#define ISCSI_CMD_STATE_RX_CMD 1
++
++/* The command returned from preprocessing_done() */
++#define ISCSI_CMD_STATE_AFTER_PREPROC 2
++
++/* The command is waiting for session or connection reinstatement finished */
++#define ISCSI_CMD_STATE_REINST_PENDING 3
++
++/* scst_restart_cmd() called and SCST processing it */
++#define ISCSI_CMD_STATE_RESTARTED 4
++
++/* SCST done processing */
++#define ISCSI_CMD_STATE_PROCESSED 5
++
++/* AEN processing */
++#define ISCSI_CMD_STATE_AEN 6
++
++/* Out of SCST core preliminary completed */
++#define ISCSI_CMD_STATE_OUT_OF_SCST_PRELIM_COMPL 7
++
++/*
++ * Most of the fields don't need any protection, since accessed from only a
++ * single thread, except where noted.
++ *
++ * ToDo: Eventually divide request and response structures in 2 separate
++ * structures and stop this IET-derived garbage.
++ */
++struct iscsi_cmnd {
++ struct iscsi_conn *conn;
++
++ /*
++ * Some flags used under conn->write_list_lock, but all modified only
++ * from single read thread or when there are no references to cmd.
++ */
++ unsigned int hashed:1;
++ unsigned int should_close_conn:1;
++ unsigned int should_close_all_conn:1;
++ unsigned int pending:1;
++ unsigned int own_sg:1;
++ unsigned int on_write_list:1;
++ unsigned int write_processing_started:1;
++ unsigned int force_cleanup_done:1;
++ unsigned int dec_active_cmds:1;
++ unsigned int ddigest_checked:1;
++#ifdef CONFIG_SCST_EXTRACHECKS
++ unsigned int on_rx_digest_list:1;
++ unsigned int release_called:1;
++#endif
++
++ /*
++ * We suppose that preliminary commands completion is tested by
++ * comparing prelim_compl_flags with 0. Otherwise, because of the
++ * gap between setting different flags a race is possible,
++ * like sending command in SCST core as PRELIM_COMPLETED, while it
++ * wasn't aborted in it yet and have as the result a wrong success
++ * status sent to the initiator.
++ */
++#define ISCSI_CMD_ABORTED 0
++#define ISCSI_CMD_PRELIM_COMPLETED 1
++ unsigned long prelim_compl_flags;
++
++ struct list_head hash_list_entry;
++
++ /*
++ * Unions are for readability and grepability and to save some
++ * cache footprint.
++ */
++
++ union {
++ /*
++ * Used only to abort not yet sent responses. Usage in
++ * cmnd_done() is only a side effect to have a lockless
++ * accesss to this list from always only a single thread
++ * at any time. So, all responses live in the parent
++ * until it has the last reference put.
++ */
++ struct list_head rsp_cmd_list;
++ struct list_head rsp_cmd_list_entry;
++ };
++
++ union {
++ struct list_head pending_list_entry;
++ struct list_head reinst_pending_cmd_list_entry;
++ };
++
++ union {
++ struct list_head write_list_entry;
++ struct list_head write_timeout_list_entry;
++ };
++
++ /* Both protected by conn->write_list_lock */
++ unsigned int on_write_timeout_list:1;
++ unsigned long write_start;
++
++ /*
++ * All unprotected, since could be accessed from only a single
++ * thread at time
++ */
++ struct iscsi_cmnd *parent_req;
++ struct iscsi_cmnd *cmd_req;
++
++ /*
++ * All unprotected, since could be accessed from only a single
++ * thread at time
++ */
++ union {
++ /* Request only fields */
++ struct {
++ struct list_head rx_ddigest_cmd_list;
++ struct list_head rx_ddigest_cmd_list_entry;
++
++ int scst_state;
++ union {
++ struct scst_cmd *scst_cmd;
++ struct scst_aen *scst_aen;
++ };
++
++ struct iscsi_cmnd *main_rsp;
++
++ /*
++ * Protected on modify by conn->write_list_lock, hence
++ * modified independently to the above field, hence the
++ * alignment.
++ */
++ int not_processed_rsp_cnt
++ __attribute__((aligned(sizeof(long))));
++ };
++
++ /* Response only fields */
++ struct {
++ struct scatterlist rsp_sg[2];
++ struct iscsi_sense_data sense_hdr;
++ };
++ };
++
++ atomic_t ref_cnt;
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ atomic_t net_ref_cnt;
++#endif
++
++ struct iscsi_pdu pdu;
++
++ struct scatterlist *sg;
++ int sg_cnt;
++ unsigned int bufflen;
++ u32 r2t_sn;
++ unsigned int r2t_len_to_receive;
++ unsigned int r2t_len_to_send;
++ unsigned int outstanding_r2t;
++ u32 target_task_tag;
++ __be32 hdigest;
++ __be32 ddigest;
++
++ struct list_head cmd_list_entry;
++ struct list_head nop_req_list_entry;
++
++ unsigned int not_received_data_len;
++};
++
++/* Max time to wait for our response satisfied for aborted commands */
++#define ISCSI_TM_DATA_WAIT_TIMEOUT (10 * HZ)
++
++/*
++ * Needed addition to all timeouts to complete a burst of commands at once.
++ * Otherwise, a part of the burst can be timeouted only in double timeout time.
++ */
++#define ISCSI_ADD_SCHED_TIME HZ
++
++#define ISCSI_CTR_OPEN_STATE_CLOSED 0
++#define ISCSI_CTR_OPEN_STATE_OPEN 1
++#define ISCSI_CTR_OPEN_STATE_CLOSING 2
++
++extern struct mutex target_mgmt_mutex;
++
++extern int ctr_open_state;
++extern const struct file_operations ctr_fops;
++
++extern spinlock_t iscsi_rd_lock;
++extern struct list_head iscsi_rd_list;
++extern wait_queue_head_t iscsi_rd_waitQ;
++
++extern spinlock_t iscsi_wr_lock;
++extern struct list_head iscsi_wr_list;
++extern wait_queue_head_t iscsi_wr_waitQ;
++
++/* iscsi.c */
++extern struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *,
++ struct iscsi_cmnd *parent);
++extern int cmnd_rx_start(struct iscsi_cmnd *);
++extern int cmnd_rx_continue(struct iscsi_cmnd *req);
++extern void cmnd_rx_end(struct iscsi_cmnd *);
++extern void cmnd_tx_start(struct iscsi_cmnd *);
++extern void cmnd_tx_end(struct iscsi_cmnd *);
++extern void req_cmnd_release_force(struct iscsi_cmnd *req);
++extern void rsp_cmnd_release(struct iscsi_cmnd *);
++extern void cmnd_done(struct iscsi_cmnd *cmnd);
++extern void conn_abort(struct iscsi_conn *conn);
++extern void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd);
++extern void iscsi_fail_data_waiting_cmnd(struct iscsi_cmnd *cmnd);
++extern void iscsi_send_nop_in(struct iscsi_conn *conn);
++extern int iscsi_preliminary_complete(struct iscsi_cmnd *req,
++ struct iscsi_cmnd *orig_req, bool get_data);
++extern int set_scst_preliminary_status_rsp(struct iscsi_cmnd *req,
++ bool get_data, int key, int asc, int ascq);
++
++/* conn.c */
++extern struct kobj_type iscsi_conn_ktype;
++extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16);
++extern void conn_reinst_finished(struct iscsi_conn *);
++extern int __add_conn(struct iscsi_session *, struct iscsi_kern_conn_info *);
++extern int __del_conn(struct iscsi_session *, struct iscsi_kern_conn_info *);
++extern int conn_free(struct iscsi_conn *);
++extern void iscsi_make_conn_rd_active(struct iscsi_conn *conn);
++#define ISCSI_CONN_ACTIVE_CLOSE 1
++#define ISCSI_CONN_DELETING 2
++extern void __mark_conn_closed(struct iscsi_conn *, int);
++extern void mark_conn_closed(struct iscsi_conn *);
++extern void iscsi_make_conn_wr_active(struct iscsi_conn *);
++extern void iscsi_check_tm_data_wait_timeouts(struct iscsi_conn *conn,
++ bool force);
++extern void __iscsi_write_space_ready(struct iscsi_conn *conn);
++
++/* nthread.c */
++extern int iscsi_send(struct iscsi_conn *conn);
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++extern void iscsi_get_page_callback(struct page *page);
++extern void iscsi_put_page_callback(struct page *page);
++#endif
++extern int istrd(void *arg);
++extern int istwr(void *arg);
++extern void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd);
++extern void req_add_to_write_timeout_list(struct iscsi_cmnd *req);
++
++/* target.c */
++extern const struct attribute *iscsi_tgt_attrs[];
++extern int iscsi_enable_target(struct scst_tgt *scst_tgt, bool enable);
++extern bool iscsi_is_target_enabled(struct scst_tgt *scst_tgt);
++extern ssize_t iscsi_sysfs_send_event(uint32_t tid,
++ enum iscsi_kern_event_code code,
++ const char *param1, const char *param2, void **data);
++extern struct iscsi_target *target_lookup_by_id(u32);
++extern int __add_target(struct iscsi_kern_target_info *);
++extern int __del_target(u32 id);
++extern ssize_t iscsi_sysfs_add_target(const char *target_name, char *params);
++extern ssize_t iscsi_sysfs_del_target(const char *target_name);
++extern ssize_t iscsi_sysfs_mgmt_cmd(char *cmd);
++extern void target_del_session(struct iscsi_target *target,
++ struct iscsi_session *session, int flags);
++extern void target_del_all_sess(struct iscsi_target *target, int flags);
++extern void target_del_all(void);
++
++/* config.c */
++extern const struct attribute *iscsi_attrs[];
++extern int iscsi_add_attr(struct iscsi_target *target,
++ const struct iscsi_kern_attr *user_info);
++extern void __iscsi_del_attr(struct iscsi_target *target,
++ struct iscsi_attr *tgt_attr);
++
++/* session.c */
++extern const struct attribute *iscsi_sess_attrs[];
++extern const struct file_operations session_seq_fops;
++extern struct iscsi_session *session_lookup(struct iscsi_target *, u64);
++extern void sess_reinst_finished(struct iscsi_session *);
++extern int __add_session(struct iscsi_target *,
++ struct iscsi_kern_session_info *);
++extern int __del_session(struct iscsi_target *, u64);
++extern int session_free(struct iscsi_session *session, bool del);
++
++/* params.c */
++extern const char *iscsi_get_digest_name(int val, char *res);
++extern const char *iscsi_get_bool_value(int val);
++extern int iscsi_params_set(struct iscsi_target *,
++ struct iscsi_kern_params_info *, int);
++
++/* event.c */
++extern int event_send(u32, u64, u32, u32, enum iscsi_kern_event_code,
++ const char *param1, const char *param2);
++extern int event_init(void);
++extern void event_exit(void);
++
++#define get_pgcnt(size, offset) \
++ ((((size) + ((offset) & ~PAGE_MASK)) + PAGE_SIZE - 1) >> PAGE_SHIFT)
++
++static inline void iscsi_cmnd_get_length(struct iscsi_pdu *pdu)
++{
++#if defined(__BIG_ENDIAN)
++ pdu->ahssize = pdu->bhs.length.ahslength * 4;
++ pdu->datasize = pdu->bhs.length.datalength;
++#elif defined(__LITTLE_ENDIAN)
++ pdu->ahssize = ((__force __u32)pdu->bhs.length & 0xff) * 4;
++ pdu->datasize = be32_to_cpu((__force __be32)((__force __u32)pdu->bhs.length & ~0xff));
++#else
++#error
++#endif
++}
++
++static inline void iscsi_cmnd_set_length(struct iscsi_pdu *pdu)
++{
++#if defined(__BIG_ENDIAN)
++ pdu->bhs.length.ahslength = pdu->ahssize / 4;
++ pdu->bhs.length.datalength = pdu->datasize;
++#elif defined(__LITTLE_ENDIAN)
++ pdu->bhs.length = cpu_to_be32(pdu->datasize) | (__force __be32)(pdu->ahssize / 4);
++#else
++#error
++#endif
++}
++
++extern struct scst_tgt_template iscsi_template;
++
++/*
++ * Skip this command if result is not 0. Must be called under
++ * corresponding lock.
++ */
++static inline bool cmnd_get_check(struct iscsi_cmnd *cmnd)
++{
++ int r = atomic_inc_return(&cmnd->ref_cnt);
++ int res;
++ if (unlikely(r == 1)) {
++ TRACE_DBG("cmnd %p is being destroyed", cmnd);
++ atomic_dec(&cmnd->ref_cnt);
++ res = 1;
++ /* Necessary code is serialized by locks in cmnd_done() */
++ } else {
++ TRACE_DBG("cmnd %p, new ref_cnt %d", cmnd,
++ atomic_read(&cmnd->ref_cnt));
++ res = 0;
++ }
++ return res;
++}
++
++static inline void cmnd_get(struct iscsi_cmnd *cmnd)
++{
++ atomic_inc(&cmnd->ref_cnt);
++ TRACE_DBG("cmnd %p, new cmnd->ref_cnt %d", cmnd,
++ atomic_read(&cmnd->ref_cnt));
++ /*
++ * For the same reason as in kref_get(). Let's be safe and
++ * always do it.
++ */
++ smp_mb__after_atomic_inc();
++}
++
++static inline void cmnd_put(struct iscsi_cmnd *cmnd)
++{
++ TRACE_DBG("cmnd %p, new ref_cnt %d", cmnd,
++ atomic_read(&cmnd->ref_cnt)-1);
++
++ EXTRACHECKS_BUG_ON(atomic_read(&cmnd->ref_cnt) == 0);
++
++ if (atomic_dec_and_test(&cmnd->ref_cnt))
++ cmnd_done(cmnd);
++}
++
++/* conn->write_list_lock supposed to be locked and BHs off */
++static inline void cmd_add_on_write_list(struct iscsi_conn *conn,
++ struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_cmnd *parent = cmnd->parent_req;
++
++ TRACE_DBG("cmnd %p", cmnd);
++ /* See comment in iscsi_restart_cmnd() */
++ EXTRACHECKS_BUG_ON(cmnd->parent_req->hashed &&
++ (cmnd_opcode(cmnd) != ISCSI_OP_R2T));
++ list_add_tail(&cmnd->write_list_entry, &conn->write_list);
++ cmnd->on_write_list = 1;
++
++ parent->not_processed_rsp_cnt++;
++ TRACE_DBG("not processed rsp cnt %d (parent %p)",
++ parent->not_processed_rsp_cnt, parent);
++}
++
++/* conn->write_list_lock supposed to be locked and BHs off */
++static inline void cmd_del_from_write_list(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_cmnd *parent = cmnd->parent_req;
++
++ TRACE_DBG("%p", cmnd);
++ list_del(&cmnd->write_list_entry);
++ cmnd->on_write_list = 0;
++
++ parent->not_processed_rsp_cnt--;
++ TRACE_DBG("not processed rsp cnt %d (parent %p)",
++ parent->not_processed_rsp_cnt, parent);
++ EXTRACHECKS_BUG_ON(parent->not_processed_rsp_cnt < 0);
++}
++
++static inline void cmd_add_on_rx_ddigest_list(struct iscsi_cmnd *req,
++ struct iscsi_cmnd *cmnd)
++{
++ TRACE_DBG("Adding RX ddigest cmd %p to digest list "
++ "of req %p", cmnd, req);
++ list_add_tail(&cmnd->rx_ddigest_cmd_list_entry,
++ &req->rx_ddigest_cmd_list);
++#ifdef CONFIG_SCST_EXTRACHECKS
++ cmnd->on_rx_digest_list = 1;
++#endif
++}
++
++static inline void cmd_del_from_rx_ddigest_list(struct iscsi_cmnd *cmnd)
++{
++ TRACE_DBG("Deleting RX digest cmd %p from digest list", cmnd);
++ list_del(&cmnd->rx_ddigest_cmd_list_entry);
++#ifdef CONFIG_SCST_EXTRACHECKS
++ cmnd->on_rx_digest_list = 0;
++#endif
++}
++
++static inline int test_write_ready(struct iscsi_conn *conn)
++{
++ /*
++ * No need for write_list protection, in the worst case we will be
++ * restarted again.
++ */
++ return !list_empty(&conn->write_list) || conn->write_cmnd;
++}
++
++static inline void conn_get(struct iscsi_conn *conn)
++{
++ atomic_inc(&conn->conn_ref_cnt);
++ TRACE_DBG("conn %p, new conn_ref_cnt %d", conn,
++ atomic_read(&conn->conn_ref_cnt));
++ /*
++ * For the same reason as in kref_get(). Let's be safe and
++ * always do it.
++ */
++ smp_mb__after_atomic_inc();
++}
++
++static inline void conn_put(struct iscsi_conn *conn)
++{
++ TRACE_DBG("conn %p, new conn_ref_cnt %d", conn,
++ atomic_read(&conn->conn_ref_cnt)-1);
++ BUG_ON(atomic_read(&conn->conn_ref_cnt) == 0);
++
++ /*
++ * Make it always ordered to protect from undesired side effects like
++ * accessing just destroyed by close_conn() conn caused by reordering
++ * of this atomic_dec().
++ */
++ smp_mb__before_atomic_dec();
++ atomic_dec(&conn->conn_ref_cnt);
++}
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++extern void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn);
++extern void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn);
++#else
++static inline void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn) {}
++static inline void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn) {}
++#endif
++
++#endif /* __ISCSI_H__ */
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/iscsi_hdr.h linux-2.6.36/drivers/scst/iscsi-scst/iscsi_hdr.h
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/iscsi_hdr.h
++++ linux-2.6.36/drivers/scst/iscsi-scst/iscsi_hdr.h
+@@ -0,0 +1,525 @@
++/*
++ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef __ISCSI_HDR_H__
++#define __ISCSI_HDR_H__
++
++#include <linux/types.h>
++#include <asm/byteorder.h>
++
++#define ISCSI_VERSION 0
++
++#ifndef __packed
++#define __packed __attribute__ ((packed))
++#endif
++
++/* iSCSI command PDU header. See also section 10.3 in RFC 3720. */
++struct iscsi_hdr {
++ u8 opcode; /* 0 */
++ u8 flags;
++ u8 spec1[2];
++#if defined(__BIG_ENDIAN_BITFIELD)
++ struct { /* 4 */
++ unsigned ahslength:8;
++ unsigned datalength:24;
++ } length;
++#elif defined(__LITTLE_ENDIAN_BITFIELD)
++ __be32 length; /* 4 */
++#endif
++ __be64 lun; /* 8 */
++ __be32 itt; /* 16 */
++ __be32 ttt; /* 20 */
++
++ /*
++ * SN fields most time stay converted to the CPU form and only received
++ * and send in the BE form.
++ */
++ u32 sn; /* 24 */
++ u32 exp_sn; /* 28 */
++ u32 max_sn; /* 32 */
++
++ __be32 spec3[3]; /* 36 */
++} __packed; /* 48 */
++
++/* Opcode encoding bits */
++#define ISCSI_OP_RETRY 0x80
++#define ISCSI_OP_IMMEDIATE 0x40
++#define ISCSI_OPCODE_MASK 0x3F
++
++/* Client to Server Message Opcode values */
++#define ISCSI_OP_NOP_OUT 0x00
++#define ISCSI_OP_SCSI_CMD 0x01
++#define ISCSI_OP_SCSI_TASK_MGT_MSG 0x02
++#define ISCSI_OP_LOGIN_CMD 0x03
++#define ISCSI_OP_TEXT_CMD 0x04
++#define ISCSI_OP_SCSI_DATA_OUT 0x05
++#define ISCSI_OP_LOGOUT_CMD 0x06
++#define ISCSI_OP_SNACK_CMD 0x10
++
++/* Server to Client Message Opcode values */
++#define ISCSI_OP_NOP_IN 0x20
++#define ISCSI_OP_SCSI_RSP 0x21
++#define ISCSI_OP_SCSI_TASK_MGT_RSP 0x22
++#define ISCSI_OP_LOGIN_RSP 0x23
++#define ISCSI_OP_TEXT_RSP 0x24
++#define ISCSI_OP_SCSI_DATA_IN 0x25
++#define ISCSI_OP_LOGOUT_RSP 0x26
++#define ISCSI_OP_R2T 0x31
++#define ISCSI_OP_ASYNC_MSG 0x32
++#define ISCSI_OP_REJECT 0x3f
++
++struct iscsi_ahs_hdr {
++ __be16 ahslength;
++ u8 ahstype;
++} __packed;
++
++#define ISCSI_AHSTYPE_CDB 1
++#define ISCSI_AHSTYPE_RLENGTH 2
++
++union iscsi_sid {
++ struct {
++ u8 isid[6]; /* Initiator Session ID */
++ __be16 tsih; /* Target Session ID */
++ } id;
++ __be64 id64;
++} __packed;
++
++struct iscsi_scsi_cmd_hdr {
++ u8 opcode;
++ u8 flags;
++ __be16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ __be64 lun;
++ __be32 itt;
++ __be32 data_length;
++ u32 cmd_sn;
++ u32 exp_stat_sn;
++ u8 scb[16];
++} __packed;
++
++#define ISCSI_CMD_FINAL 0x80
++#define ISCSI_CMD_READ 0x40
++#define ISCSI_CMD_WRITE 0x20
++#define ISCSI_CMD_ATTR_MASK 0x07
++#define ISCSI_CMD_UNTAGGED 0x00
++#define ISCSI_CMD_SIMPLE 0x01
++#define ISCSI_CMD_ORDERED 0x02
++#define ISCSI_CMD_HEAD_OF_QUEUE 0x03
++#define ISCSI_CMD_ACA 0x04
++
++struct iscsi_cdb_ahdr {
++ __be16 ahslength;
++ u8 ahstype;
++ u8 reserved;
++ u8 cdb[0];
++} __packed;
++
++struct iscsi_rlength_ahdr {
++ __be16 ahslength;
++ u8 ahstype;
++ u8 reserved;
++ __be32 read_length;
++} __packed;
++
++struct iscsi_scsi_rsp_hdr {
++ u8 opcode;
++ u8 flags;
++ u8 response;
++ u8 cmd_status;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd1[2];
++ __be32 itt;
++ __be32 snack;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ u32 exp_data_sn;
++ __be32 bi_residual_count;
++ __be32 residual_count;
++} __packed;
++
++#define ISCSI_FLG_RESIDUAL_UNDERFLOW 0x02
++#define ISCSI_FLG_RESIDUAL_OVERFLOW 0x04
++#define ISCSI_FLG_BIRESIDUAL_UNDERFLOW 0x08
++#define ISCSI_FLG_BIRESIDUAL_OVERFLOW 0x10
++
++#define ISCSI_RESPONSE_COMMAND_COMPLETED 0x00
++#define ISCSI_RESPONSE_TARGET_FAILURE 0x01
++
++struct iscsi_sense_data {
++ __be16 length;
++ u8 data[0];
++} __packed;
++
++struct iscsi_task_mgt_hdr {
++ u8 opcode;
++ u8 function;
++ __be16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ __be64 lun;
++ __be32 itt;
++ __be32 rtt;
++ u32 cmd_sn;
++ u32 exp_stat_sn;
++ u32 ref_cmd_sn;
++ u32 exp_data_sn;
++ u32 rsvd2[2];
++} __packed;
++
++#define ISCSI_FUNCTION_MASK 0x7f
++
++#define ISCSI_FUNCTION_ABORT_TASK 1
++#define ISCSI_FUNCTION_ABORT_TASK_SET 2
++#define ISCSI_FUNCTION_CLEAR_ACA 3
++#define ISCSI_FUNCTION_CLEAR_TASK_SET 4
++#define ISCSI_FUNCTION_LOGICAL_UNIT_RESET 5
++#define ISCSI_FUNCTION_TARGET_WARM_RESET 6
++#define ISCSI_FUNCTION_TARGET_COLD_RESET 7
++#define ISCSI_FUNCTION_TASK_REASSIGN 8
++
++struct iscsi_task_rsp_hdr {
++ u8 opcode;
++ u8 flags;
++ u8 response;
++ u8 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd2[2];
++ __be32 itt;
++ u32 rsvd3;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ u32 rsvd4[3];
++} __packed;
++
++#define ISCSI_RESPONSE_FUNCTION_COMPLETE 0
++#define ISCSI_RESPONSE_UNKNOWN_TASK 1
++#define ISCSI_RESPONSE_UNKNOWN_LUN 2
++#define ISCSI_RESPONSE_TASK_ALLEGIANT 3
++#define ISCSI_RESPONSE_ALLEGIANCE_REASSIGNMENT_UNSUPPORTED 4
++#define ISCSI_RESPONSE_FUNCTION_UNSUPPORTED 5
++#define ISCSI_RESPONSE_NO_AUTHORIZATION 6
++#define ISCSI_RESPONSE_FUNCTION_REJECTED 255
++
++struct iscsi_data_out_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ __be64 lun;
++ __be32 itt;
++ __be32 ttt;
++ u32 rsvd2;
++ u32 exp_stat_sn;
++ u32 rsvd3;
++ __be32 data_sn;
++ __be32 buffer_offset;
++ u32 rsvd4;
++} __packed;
++
++struct iscsi_data_in_hdr {
++ u8 opcode;
++ u8 flags;
++ u8 rsvd1;
++ u8 cmd_status;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd2[2];
++ __be32 itt;
++ __be32 ttt;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ __be32 data_sn;
++ __be32 buffer_offset;
++ __be32 residual_count;
++} __packed;
++
++#define ISCSI_FLG_STATUS 0x01
++
++struct iscsi_r2t_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ __be64 lun;
++ __be32 itt;
++ __be32 ttt;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ u32 r2t_sn;
++ __be32 buffer_offset;
++ __be32 data_length;
++} __packed;
++
++struct iscsi_async_msg_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ __be64 lun;
++ __be32 ffffffff;
++ u32 rsvd2;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ u8 async_event;
++ u8 async_vcode;
++ __be16 param1;
++ __be16 param2;
++ __be16 param3;
++ u32 rsvd3;
++} __packed;
++
++#define ISCSI_ASYNC_SCSI 0
++#define ISCSI_ASYNC_LOGOUT 1
++#define ISCSI_ASYNC_DROP_CONNECTION 2
++#define ISCSI_ASYNC_DROP_SESSION 3
++#define ISCSI_ASYNC_PARAM_REQUEST 4
++#define ISCSI_ASYNC_VENDOR 255
++
++struct iscsi_text_req_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd2[2];
++ __be32 itt;
++ __be32 ttt;
++ u32 cmd_sn;
++ u32 exp_stat_sn;
++ u32 rsvd3[4];
++} __packed;
++
++struct iscsi_text_rsp_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd2[2];
++ __be32 itt;
++ __be32 ttt;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ u32 rsvd3[3];
++} __packed;
++
++struct iscsi_login_req_hdr {
++ u8 opcode;
++ u8 flags;
++ u8 max_version; /* Max. version supported */
++ u8 min_version; /* Min. version supported */
++ u8 ahslength;
++ u8 datalength[3];
++ union iscsi_sid sid;
++ __be32 itt; /* Initiator Task Tag */
++ __be16 cid; /* Connection ID */
++ u16 rsvd1;
++ u32 cmd_sn;
++ u32 exp_stat_sn;
++ u32 rsvd2[4];
++} __packed;
++
++struct iscsi_login_rsp_hdr {
++ u8 opcode;
++ u8 flags;
++ u8 max_version; /* Max. version supported */
++ u8 active_version; /* Active version */
++ u8 ahslength;
++ u8 datalength[3];
++ union iscsi_sid sid;
++ __be32 itt; /* Initiator Task Tag */
++ u32 rsvd1;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ u8 status_class; /* see Login RSP Status classes below */
++ u8 status_detail; /* see Login RSP Status details below */
++ u8 rsvd2[10];
++} __packed;
++
++#define ISCSI_FLG_FINAL 0x80
++#define ISCSI_FLG_TRANSIT 0x80
++#define ISCSI_FLG_CSG_SECURITY 0x00
++#define ISCSI_FLG_CSG_LOGIN 0x04
++#define ISCSI_FLG_CSG_FULL_FEATURE 0x0c
++#define ISCSI_FLG_CSG_MASK 0x0c
++#define ISCSI_FLG_NSG_SECURITY 0x00
++#define ISCSI_FLG_NSG_LOGIN 0x01
++#define ISCSI_FLG_NSG_FULL_FEATURE 0x03
++#define ISCSI_FLG_NSG_MASK 0x03
++
++/* Login Status response classes */
++#define ISCSI_STATUS_SUCCESS 0x00
++#define ISCSI_STATUS_REDIRECT 0x01
++#define ISCSI_STATUS_INITIATOR_ERR 0x02
++#define ISCSI_STATUS_TARGET_ERR 0x03
++
++/* Login Status response detail codes */
++/* Class-0 (Success) */
++#define ISCSI_STATUS_ACCEPT 0x00
++
++/* Class-1 (Redirection) */
++#define ISCSI_STATUS_TGT_MOVED_TEMP 0x01
++#define ISCSI_STATUS_TGT_MOVED_PERM 0x02
++
++/* Class-2 (Initiator Error) */
++#define ISCSI_STATUS_INIT_ERR 0x00
++#define ISCSI_STATUS_AUTH_FAILED 0x01
++#define ISCSI_STATUS_TGT_FORBIDDEN 0x02
++#define ISCSI_STATUS_TGT_NOT_FOUND 0x03
++#define ISCSI_STATUS_TGT_REMOVED 0x04
++#define ISCSI_STATUS_NO_VERSION 0x05
++#define ISCSI_STATUS_TOO_MANY_CONN 0x06
++#define ISCSI_STATUS_MISSING_FIELDS 0x07
++#define ISCSI_STATUS_CONN_ADD_FAILED 0x08
++#define ISCSI_STATUS_INV_SESSION_TYPE 0x09
++#define ISCSI_STATUS_SESSION_NOT_FOUND 0x0a
++#define ISCSI_STATUS_INV_REQ_TYPE 0x0b
++
++/* Class-3 (Target Error) */
++#define ISCSI_STATUS_TARGET_ERROR 0x00
++#define ISCSI_STATUS_SVC_UNAVAILABLE 0x01
++#define ISCSI_STATUS_NO_RESOURCES 0x02
++
++struct iscsi_logout_req_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd2[2];
++ __be32 itt;
++ __be16 cid;
++ u16 rsvd3;
++ u32 cmd_sn;
++ u32 exp_stat_sn;
++ u32 rsvd4[4];
++} __packed;
++
++struct iscsi_logout_rsp_hdr {
++ u8 opcode;
++ u8 flags;
++ u8 response;
++ u8 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd2[2];
++ __be32 itt;
++ u32 rsvd3;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ u32 rsvd4;
++ __be16 time2wait;
++ __be16 time2retain;
++ u32 rsvd5;
++} __packed;
++
++struct iscsi_snack_req_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd2[2];
++ __be32 itt;
++ __be32 ttt;
++ u32 rsvd3;
++ u32 exp_stat_sn;
++ u32 rsvd4[2];
++ __be32 beg_run;
++ __be32 run_length;
++} __packed;
++
++struct iscsi_reject_hdr {
++ u8 opcode;
++ u8 flags;
++ u8 reason;
++ u8 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ u32 rsvd2[2];
++ __be32 ffffffff;
++ __be32 rsvd3;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ __be32 data_sn;
++ u32 rsvd4[2];
++} __packed;
++
++#define ISCSI_REASON_RESERVED 0x01
++#define ISCSI_REASON_DATA_DIGEST_ERROR 0x02
++#define ISCSI_REASON_DATA_SNACK_REJECT 0x03
++#define ISCSI_REASON_PROTOCOL_ERROR 0x04
++#define ISCSI_REASON_UNSUPPORTED_COMMAND 0x05
++#define ISCSI_REASON_IMMEDIATE_COMMAND_REJECT 0x06
++#define ISCSI_REASON_TASK_IN_PROGRESS 0x07
++#define ISCSI_REASON_INVALID_DATA_ACK 0x08
++#define ISCSI_REASON_INVALID_PDU_FIELD 0x09
++#define ISCSI_REASON_OUT_OF_RESOURCES 0x0a
++#define ISCSI_REASON_NEGOTIATION_RESET 0x0b
++#define ISCSI_REASON_WAITING_LOGOUT 0x0c
++
++struct iscsi_nop_out_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ __be64 lun;
++ __be32 itt;
++ __be32 ttt;
++ u32 cmd_sn;
++ u32 exp_stat_sn;
++ u32 rsvd2[4];
++} __packed;
++
++struct iscsi_nop_in_hdr {
++ u8 opcode;
++ u8 flags;
++ u16 rsvd1;
++ u8 ahslength;
++ u8 datalength[3];
++ __be64 lun;
++ __be32 itt;
++ __be32 ttt;
++ u32 stat_sn;
++ u32 exp_cmd_sn;
++ u32 max_cmd_sn;
++ u32 rsvd2[3];
++} __packed;
++
++#define ISCSI_RESERVED_TAG_CPU32 (0xffffffffU)
++#define ISCSI_RESERVED_TAG (__constant_cpu_to_be32(ISCSI_RESERVED_TAG_CPU32))
++
++#define cmnd_hdr(cmnd) ((struct iscsi_scsi_cmd_hdr *) (&((cmnd)->pdu.bhs)))
++#define cmnd_opcode(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OPCODE_MASK)
++#define cmnd_scsicode(cmnd) (cmnd_hdr((cmnd))->scb[0])
++
++#endif /* __ISCSI_HDR_H__ */
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/nthread.c linux-2.6.36/drivers/scst/iscsi-scst/nthread.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/nthread.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/nthread.c
+@@ -0,0 +1,1838 @@
++/*
++ * Network threads.
++ *
++ * Copyright (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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.
++ *
++ * 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.
++ */
++
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/kthread.h>
++#include <asm/ioctls.h>
++#include <linux/delay.h>
++#include <net/tcp.h>
++
++#include "iscsi.h"
++#include "digest.h"
++
++enum rx_state {
++ RX_INIT_BHS, /* Must be zero for better "switch" optimization. */
++ RX_BHS,
++ RX_CMD_START,
++ RX_DATA,
++ RX_END,
++
++ RX_CMD_CONTINUE,
++ RX_INIT_HDIGEST,
++ RX_CHECK_HDIGEST,
++ RX_INIT_DDIGEST,
++ RX_CHECK_DDIGEST,
++ RX_AHS,
++ RX_PADDING,
++};
++
++enum tx_state {
++ TX_INIT = 0, /* Must be zero for better "switch" optimization. */
++ TX_BHS_DATA,
++ TX_INIT_PADDING,
++ TX_PADDING,
++ TX_INIT_DDIGEST,
++ TX_DDIGEST,
++ TX_END,
++};
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++static void iscsi_check_closewait(struct iscsi_conn *conn)
++{
++ struct iscsi_cmnd *cmnd;
++
++ TRACE_ENTRY();
++
++ TRACE_CONN_CLOSE_DBG("conn %p, sk_state %d", conn,
++ conn->sock->sk->sk_state);
++
++ if (conn->sock->sk->sk_state != TCP_CLOSE) {
++ TRACE_CONN_CLOSE_DBG("conn %p, skipping", conn);
++ goto out;
++ }
++
++ /*
++ * No data are going to be sent, so all queued buffers can be freed
++ * now. In many cases TCP does that only in close(), but we can't rely
++ * on user space on calling it.
++ */
++
++again:
++ spin_lock_bh(&conn->cmd_list_lock);
++ list_for_each_entry(cmnd, &conn->cmd_list, cmd_list_entry) {
++ struct iscsi_cmnd *rsp;
++ int restart = 0;
++
++ TRACE_CONN_CLOSE_DBG("cmd %p, scst_state %x, "
++ "r2t_len_to_receive %d, ref_cnt %d, parent_req %p, "
++ "net_ref_cnt %d, sg %p", cmnd, cmnd->scst_state,
++ cmnd->r2t_len_to_receive, atomic_read(&cmnd->ref_cnt),
++ cmnd->parent_req, atomic_read(&cmnd->net_ref_cnt),
++ cmnd->sg);
++
++ BUG_ON(cmnd->parent_req != NULL);
++
++ if (cmnd->sg != NULL) {
++ int i;
++
++ if (cmnd_get_check(cmnd))
++ continue;
++
++ for (i = 0; i < cmnd->sg_cnt; i++) {
++ struct page *page = sg_page(&cmnd->sg[i]);
++ TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, "
++ "_count %d", page, page->net_priv,
++ atomic_read(&page->_count));
++
++ if (page->net_priv != NULL) {
++ if (restart == 0) {
++ spin_unlock_bh(&conn->cmd_list_lock);
++ restart = 1;
++ }
++ while (page->net_priv != NULL)
++ iscsi_put_page_callback(page);
++ }
++ }
++ cmnd_put(cmnd);
++
++ if (restart)
++ goto again;
++ }
++
++ list_for_each_entry(rsp, &cmnd->rsp_cmd_list,
++ rsp_cmd_list_entry) {
++ TRACE_CONN_CLOSE_DBG(" rsp %p, ref_cnt %d, "
++ "net_ref_cnt %d, sg %p",
++ rsp, atomic_read(&rsp->ref_cnt),
++ atomic_read(&rsp->net_ref_cnt), rsp->sg);
++
++ if ((rsp->sg != cmnd->sg) && (rsp->sg != NULL)) {
++ int i;
++
++ if (cmnd_get_check(rsp))
++ continue;
++
++ for (i = 0; i < rsp->sg_cnt; i++) {
++ struct page *page =
++ sg_page(&rsp->sg[i]);
++ TRACE_CONN_CLOSE_DBG(
++ " page %p, net_priv %p, "
++ "_count %d",
++ page, page->net_priv,
++ atomic_read(&page->_count));
++
++ if (page->net_priv != NULL) {
++ if (restart == 0) {
++ spin_unlock_bh(&conn->cmd_list_lock);
++ restart = 1;
++ }
++ while (page->net_priv != NULL)
++ iscsi_put_page_callback(page);
++ }
++ }
++ cmnd_put(rsp);
++
++ if (restart)
++ goto again;
++ }
++ }
++ }
++ spin_unlock_bh(&conn->cmd_list_lock);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++#else
++static inline void iscsi_check_closewait(struct iscsi_conn *conn) {};
++#endif
++
++static void free_pending_commands(struct iscsi_conn *conn)
++{
++ struct iscsi_session *session = conn->session;
++ struct list_head *pending_list = &session->pending_list;
++ int req_freed;
++ struct iscsi_cmnd *cmnd;
++
++ spin_lock(&session->sn_lock);
++ do {
++ req_freed = 0;
++ list_for_each_entry(cmnd, pending_list, pending_list_entry) {
++ TRACE_CONN_CLOSE_DBG("Pending cmd %p"
++ "(conn %p, cmd_sn %u, exp_cmd_sn %u)",
++ cmnd, conn, cmnd->pdu.bhs.sn,
++ session->exp_cmd_sn);
++ if ((cmnd->conn == conn) &&
++ (session->exp_cmd_sn == cmnd->pdu.bhs.sn)) {
++ TRACE_MGMT_DBG("Freeing pending cmd %p "
++ "(cmd_sn %u, exp_cmd_sn %u)",
++ cmnd, cmnd->pdu.bhs.sn,
++ session->exp_cmd_sn);
++
++ list_del(&cmnd->pending_list_entry);
++ cmnd->pending = 0;
++
++ session->exp_cmd_sn++;
++
++ spin_unlock(&session->sn_lock);
++
++ req_cmnd_release_force(cmnd);
++
++ req_freed = 1;
++ spin_lock(&session->sn_lock);
++ break;
++ }
++ }
++ } while (req_freed);
++ spin_unlock(&session->sn_lock);
++
++ return;
++}
++
++static void free_orphaned_pending_commands(struct iscsi_conn *conn)
++{
++ struct iscsi_session *session = conn->session;
++ struct list_head *pending_list = &session->pending_list;
++ int req_freed;
++ struct iscsi_cmnd *cmnd;
++
++ spin_lock(&session->sn_lock);
++ do {
++ req_freed = 0;
++ list_for_each_entry(cmnd, pending_list, pending_list_entry) {
++ TRACE_CONN_CLOSE_DBG("Pending cmd %p"
++ "(conn %p, cmd_sn %u, exp_cmd_sn %u)",
++ cmnd, conn, cmnd->pdu.bhs.sn,
++ session->exp_cmd_sn);
++ if (cmnd->conn == conn) {
++ TRACE_MGMT_DBG("Freeing orphaned pending "
++ "cmnd %p (cmd_sn %u, exp_cmd_sn %u)",
++ cmnd, cmnd->pdu.bhs.sn,
++ session->exp_cmd_sn);
++
++ list_del(&cmnd->pending_list_entry);
++ cmnd->pending = 0;
++
++ if (session->exp_cmd_sn == cmnd->pdu.bhs.sn)
++ session->exp_cmd_sn++;
++
++ spin_unlock(&session->sn_lock);
++
++ req_cmnd_release_force(cmnd);
++
++ req_freed = 1;
++ spin_lock(&session->sn_lock);
++ break;
++ }
++ }
++ } while (req_freed);
++ spin_unlock(&session->sn_lock);
++
++ return;
++}
++
++#ifdef CONFIG_SCST_DEBUG
++static void trace_conn_close(struct iscsi_conn *conn)
++{
++ struct iscsi_cmnd *cmnd;
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ struct iscsi_cmnd *rsp;
++#endif
++
++#if 0
++ if (time_after(jiffies, start_waiting + 10*HZ))
++ trace_flag |= TRACE_CONN_OC_DBG;
++#endif
++
++ spin_lock_bh(&conn->cmd_list_lock);
++ list_for_each_entry(cmnd, &conn->cmd_list,
++ cmd_list_entry) {
++ TRACE_CONN_CLOSE_DBG(
++ "cmd %p, scst_cmd %p, scst_state %x, scst_cmd state "
++ "%d, r2t_len_to_receive %d, ref_cnt %d, sn %u, "
++ "parent_req %p, pending %d",
++ cmnd, cmnd->scst_cmd, cmnd->scst_state,
++ ((cmnd->parent_req == NULL) && cmnd->scst_cmd) ?
++ cmnd->scst_cmd->state : -1,
++ cmnd->r2t_len_to_receive, atomic_read(&cmnd->ref_cnt),
++ cmnd->pdu.bhs.sn, cmnd->parent_req, cmnd->pending);
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ TRACE_CONN_CLOSE_DBG("net_ref_cnt %d, sg %p",
++ atomic_read(&cmnd->net_ref_cnt),
++ cmnd->sg);
++ if (cmnd->sg != NULL) {
++ int i;
++ for (i = 0; i < cmnd->sg_cnt; i++) {
++ struct page *page = sg_page(&cmnd->sg[i]);
++ TRACE_CONN_CLOSE_DBG("page %p, "
++ "net_priv %p, _count %d",
++ page, page->net_priv,
++ atomic_read(&page->_count));
++ }
++ }
++
++ BUG_ON(cmnd->parent_req != NULL);
++
++ list_for_each_entry(rsp, &cmnd->rsp_cmd_list,
++ rsp_cmd_list_entry) {
++ TRACE_CONN_CLOSE_DBG(" rsp %p, "
++ "ref_cnt %d, net_ref_cnt %d, sg %p",
++ rsp, atomic_read(&rsp->ref_cnt),
++ atomic_read(&rsp->net_ref_cnt), rsp->sg);
++ if (rsp->sg != cmnd->sg && rsp->sg) {
++ int i;
++ for (i = 0; i < rsp->sg_cnt; i++) {
++ TRACE_CONN_CLOSE_DBG(" page %p, "
++ "net_priv %p, _count %d",
++ sg_page(&rsp->sg[i]),
++ sg_page(&rsp->sg[i])->net_priv,
++ atomic_read(&sg_page(&rsp->sg[i])->
++ _count));
++ }
++ }
++ }
++#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */
++ }
++ spin_unlock_bh(&conn->cmd_list_lock);
++ return;
++}
++#else /* CONFIG_SCST_DEBUG */
++static void trace_conn_close(struct iscsi_conn *conn) {}
++#endif /* CONFIG_SCST_DEBUG */
++
++void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd)
++{
++ int fn = scst_mgmt_cmd_get_fn(scst_mcmd);
++ void *priv = scst_mgmt_cmd_get_tgt_priv(scst_mcmd);
++
++ TRACE_MGMT_DBG("scst_mcmd %p, fn %d, priv %p", scst_mcmd, fn, priv);
++
++ switch (fn) {
++ case SCST_NEXUS_LOSS_SESS:
++ case SCST_ABORT_ALL_TASKS_SESS:
++ {
++ struct iscsi_conn *conn = (struct iscsi_conn *)priv;
++ struct iscsi_session *sess = conn->session;
++ struct iscsi_conn *c;
++
++ if (sess->sess_reinst_successor != NULL)
++ scst_reassign_persistent_sess_states(
++ sess->sess_reinst_successor->scst_sess,
++ sess->scst_sess);
++
++ mutex_lock(&sess->target->target_mutex);
++
++ /*
++ * We can't mark sess as shutting down earlier, because until
++ * now it might have pending commands. Otherwise, in case of
++ * reinstatement, it might lead to data corruption, because
++ * commands in being reinstated session can be executed
++ * after commands in the new session.
++ */
++ sess->sess_shutting_down = 1;
++ list_for_each_entry(c, &sess->conn_list, conn_list_entry) {
++ if (!test_bit(ISCSI_CONN_SHUTTINGDOWN, &c->conn_aflags)) {
++ sess->sess_shutting_down = 0;
++ break;
++ }
++ }
++
++ if (conn->conn_reinst_successor != NULL) {
++ BUG_ON(!test_bit(ISCSI_CONN_REINSTATING,
++ &conn->conn_reinst_successor->conn_aflags));
++ conn_reinst_finished(conn->conn_reinst_successor);
++ conn->conn_reinst_successor = NULL;
++ } else if (sess->sess_reinst_successor != NULL) {
++ sess_reinst_finished(sess->sess_reinst_successor);
++ sess->sess_reinst_successor = NULL;
++ }
++ mutex_unlock(&sess->target->target_mutex);
++
++ complete_all(&conn->ready_to_free);
++ break;
++ }
++ default:
++ /* Nothing to do */
++ break;
++ }
++
++ return;
++}
++
++/* No locks */
++static void close_conn(struct iscsi_conn *conn)
++{
++ struct iscsi_session *session = conn->session;
++ struct iscsi_target *target = conn->target;
++ typeof(jiffies) start_waiting = jiffies;
++ typeof(jiffies) shut_start_waiting = start_waiting;
++ bool pending_reported = 0, wait_expired = 0, shut_expired = 0;
++ bool reinst;
++ uint32_t tid, cid;
++ uint64_t sid;
++
++#define CONN_PENDING_TIMEOUT ((typeof(jiffies))10*HZ)
++#define CONN_WAIT_TIMEOUT ((typeof(jiffies))10*HZ)
++#define CONN_REG_SHUT_TIMEOUT ((typeof(jiffies))125*HZ)
++#define CONN_DEL_SHUT_TIMEOUT ((typeof(jiffies))10*HZ)
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Closing connection %p (conn_ref_cnt=%d)", conn,
++ atomic_read(&conn->conn_ref_cnt));
++
++ iscsi_extracheck_is_rd_thread(conn);
++
++ BUG_ON(!conn->closing);
++
++ if (conn->active_close) {
++ /* We want all our already send operations to complete */
++ conn->sock->ops->shutdown(conn->sock, RCV_SHUTDOWN);
++ } else {
++ conn->sock->ops->shutdown(conn->sock,
++ RCV_SHUTDOWN|SEND_SHUTDOWN);
++ }
++
++ mutex_lock(&session->target->target_mutex);
++
++ set_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags);
++ reinst = (conn->conn_reinst_successor != NULL);
++
++ mutex_unlock(&session->target->target_mutex);
++
++ if (reinst) {
++ int rc;
++ int lun = 0;
++
++ /* Abort all outstanding commands */
++ rc = scst_rx_mgmt_fn_lun(session->scst_sess,
++ SCST_ABORT_ALL_TASKS_SESS, (uint8_t *)&lun, sizeof(lun),
++ SCST_NON_ATOMIC, conn);
++ if (rc != 0)
++ PRINT_ERROR("SCST_ABORT_ALL_TASKS_SESS failed %d", rc);
++ } else {
++ int rc;
++ int lun = 0;
++
++ rc = scst_rx_mgmt_fn_lun(session->scst_sess,
++ SCST_NEXUS_LOSS_SESS, (uint8_t *)&lun, sizeof(lun),
++ SCST_NON_ATOMIC, conn);
++ if (rc != 0)
++ PRINT_ERROR("SCST_NEXUS_LOSS_SESS failed %d", rc);
++ }
++
++ if (conn->read_state != RX_INIT_BHS) {
++ struct iscsi_cmnd *cmnd = conn->read_cmnd;
++
++ if (cmnd->scst_state == ISCSI_CMD_STATE_RX_CMD) {
++ TRACE_CONN_CLOSE_DBG("Going to wait for cmnd %p to "
++ "change state from RX_CMD", cmnd);
++ }
++ wait_event(conn->read_state_waitQ,
++ cmnd->scst_state != ISCSI_CMD_STATE_RX_CMD);
++
++ TRACE_CONN_CLOSE_DBG("Releasing conn->read_cmnd %p (conn %p)",
++ conn->read_cmnd, conn);
++
++ conn->read_cmnd = NULL;
++ conn->read_state = RX_INIT_BHS;
++ req_cmnd_release_force(cmnd);
++ }
++
++ conn_abort(conn);
++
++ /* ToDo: not the best way to wait */
++ while (atomic_read(&conn->conn_ref_cnt) != 0) {
++ if (conn->conn_tm_active)
++ iscsi_check_tm_data_wait_timeouts(conn, true);
++
++ mutex_lock(&target->target_mutex);
++ spin_lock(&session->sn_lock);
++ if (session->tm_rsp && session->tm_rsp->conn == conn) {
++ struct iscsi_cmnd *tm_rsp = session->tm_rsp;
++ TRACE_MGMT_DBG("Dropping delayed TM rsp %p", tm_rsp);
++ session->tm_rsp = NULL;
++ session->tm_active--;
++ WARN_ON(session->tm_active < 0);
++ spin_unlock(&session->sn_lock);
++ mutex_unlock(&target->target_mutex);
++
++ rsp_cmnd_release(tm_rsp);
++ } else {
++ spin_unlock(&session->sn_lock);
++ mutex_unlock(&target->target_mutex);
++ }
++
++ /* It's safe to check it without sn_lock */
++ if (!list_empty(&session->pending_list)) {
++ TRACE_CONN_CLOSE_DBG("Disposing pending commands on "
++ "connection %p (conn_ref_cnt=%d)", conn,
++ atomic_read(&conn->conn_ref_cnt));
++
++ free_pending_commands(conn);
++
++ if (time_after(jiffies,
++ start_waiting + CONN_PENDING_TIMEOUT)) {
++ if (!pending_reported) {
++ TRACE_CONN_CLOSE("%s",
++ "Pending wait time expired");
++ pending_reported = 1;
++ }
++ free_orphaned_pending_commands(conn);
++ }
++ }
++
++ iscsi_make_conn_wr_active(conn);
++
++ /* That's for active close only, actually */
++ if (time_after(jiffies, start_waiting + CONN_WAIT_TIMEOUT) &&
++ !wait_expired) {
++ TRACE_CONN_CLOSE("Wait time expired (conn %p, "
++ "sk_state %d)",
++ conn, conn->sock->sk->sk_state);
++ conn->sock->ops->shutdown(conn->sock, SEND_SHUTDOWN);
++ wait_expired = 1;
++ shut_start_waiting = jiffies;
++ }
++
++ if (wait_expired && !shut_expired &&
++ time_after(jiffies, shut_start_waiting +
++ conn->deleting ? CONN_DEL_SHUT_TIMEOUT :
++ CONN_REG_SHUT_TIMEOUT)) {
++ TRACE_CONN_CLOSE("Wait time after shutdown expired "
++ "(conn %p, sk_state %d)", conn,
++ conn->sock->sk->sk_state);
++ conn->sock->sk->sk_prot->disconnect(conn->sock->sk, 0);
++ shut_expired = 1;
++ }
++
++ if (conn->deleting)
++ msleep(200);
++ else
++ msleep(1000);
++
++ TRACE_CONN_CLOSE_DBG("conn %p, conn_ref_cnt %d left, "
++ "wr_state %d, exp_cmd_sn %u",
++ conn, atomic_read(&conn->conn_ref_cnt),
++ conn->wr_state, session->exp_cmd_sn);
++
++ trace_conn_close(conn);
++
++ /* It might never be called for being closed conn */
++ __iscsi_write_space_ready(conn);
++
++ iscsi_check_closewait(conn);
++ }
++
++ write_lock_bh(&conn->sock->sk->sk_callback_lock);
++ conn->sock->sk->sk_state_change = conn->old_state_change;
++ conn->sock->sk->sk_data_ready = conn->old_data_ready;
++ conn->sock->sk->sk_write_space = conn->old_write_space;
++ write_unlock_bh(&conn->sock->sk->sk_callback_lock);
++
++ while (1) {
++ bool t;
++
++ spin_lock_bh(&iscsi_wr_lock);
++ t = (conn->wr_state == ISCSI_CONN_WR_STATE_IDLE);
++ spin_unlock_bh(&iscsi_wr_lock);
++
++ if (t && (atomic_read(&conn->conn_ref_cnt) == 0))
++ break;
++
++ TRACE_CONN_CLOSE_DBG("Waiting for wr thread (conn %p), "
++ "wr_state %x", conn, conn->wr_state);
++ msleep(50);
++ }
++
++ wait_for_completion(&conn->ready_to_free);
++
++ tid = target->tid;
++ sid = session->sid;
++ cid = conn->cid;
++
++ mutex_lock(&target->target_mutex);
++ conn_free(conn);
++ mutex_unlock(&target->target_mutex);
++
++ /*
++ * We can't send E_CONN_CLOSE earlier, because otherwise we would have
++ * a race, when the user space tried to destroy session, which still
++ * has connections.
++ *
++ * !! All target, session and conn can be already dead here !!
++ */
++ TRACE_CONN_CLOSE("Notifying user space about closing connection %p",
++ conn);
++ event_send(tid, sid, cid, 0, E_CONN_CLOSE, NULL, NULL);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int close_conn_thr(void *arg)
++{
++ struct iscsi_conn *conn = (struct iscsi_conn *)arg;
++
++ TRACE_ENTRY();
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ /*
++ * To satisfy iscsi_extracheck_is_rd_thread() in functions called
++ * on the connection close. It is safe, because at this point conn
++ * can't be used by any other thread.
++ */
++ conn->rd_task = current;
++#endif
++ close_conn(conn);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++/* No locks */
++static void start_close_conn(struct iscsi_conn *conn)
++{
++ struct task_struct *t;
++
++ TRACE_ENTRY();
++
++ t = kthread_run(close_conn_thr, conn, "iscsi_conn_cleanup");
++ if (IS_ERR(t)) {
++ PRINT_ERROR("kthread_run() failed (%ld), closing conn %p "
++ "directly", PTR_ERR(t), conn);
++ close_conn(conn);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline void iscsi_conn_init_read(struct iscsi_conn *conn,
++ void __user *data, size_t len)
++{
++ conn->read_iov[0].iov_base = data;
++ conn->read_iov[0].iov_len = len;
++ conn->read_msg.msg_iov = conn->read_iov;
++ conn->read_msg.msg_iovlen = 1;
++ conn->read_size = len;
++ return;
++}
++
++static void iscsi_conn_prepare_read_ahs(struct iscsi_conn *conn,
++ struct iscsi_cmnd *cmnd)
++{
++ int asize = (cmnd->pdu.ahssize + 3) & -4;
++
++ /* ToDo: __GFP_NOFAIL ?? */
++ cmnd->pdu.ahs = kmalloc(asize, __GFP_NOFAIL|GFP_KERNEL);
++ BUG_ON(cmnd->pdu.ahs == NULL);
++ iscsi_conn_init_read(conn, (void __force __user *)cmnd->pdu.ahs, asize);
++ return;
++}
++
++static struct iscsi_cmnd *iscsi_get_send_cmnd(struct iscsi_conn *conn)
++{
++ struct iscsi_cmnd *cmnd = NULL;
++
++ spin_lock_bh(&conn->write_list_lock);
++ if (!list_empty(&conn->write_list)) {
++ cmnd = list_entry(conn->write_list.next, struct iscsi_cmnd,
++ write_list_entry);
++ cmd_del_from_write_list(cmnd);
++ cmnd->write_processing_started = 1;
++ } else {
++ spin_unlock_bh(&conn->write_list_lock);
++ goto out;
++ }
++ spin_unlock_bh(&conn->write_list_lock);
++
++ if (unlikely(test_bit(ISCSI_CMD_ABORTED,
++ &cmnd->parent_req->prelim_compl_flags))) {
++ TRACE_MGMT_DBG("Going to send acmd %p (scst cmd %p, "
++ "state %d, parent_req %p)", cmnd, cmnd->scst_cmd,
++ cmnd->scst_state, cmnd->parent_req);
++ }
++
++ if (unlikely(cmnd_opcode(cmnd) == ISCSI_OP_SCSI_TASK_MGT_RSP)) {
++#ifdef CONFIG_SCST_DEBUG
++ struct iscsi_task_mgt_hdr *req_hdr =
++ (struct iscsi_task_mgt_hdr *)&cmnd->parent_req->pdu.bhs;
++ struct iscsi_task_rsp_hdr *rsp_hdr =
++ (struct iscsi_task_rsp_hdr *)&cmnd->pdu.bhs;
++ TRACE_MGMT_DBG("Going to send TM response %p (status %d, "
++ "fn %d, parent_req %p)", cmnd, rsp_hdr->response,
++ req_hdr->function & ISCSI_FUNCTION_MASK,
++ cmnd->parent_req);
++#endif
++ }
++
++out:
++ return cmnd;
++}
++
++/* Returns number of bytes left to receive or <0 for error */
++static int do_recv(struct iscsi_conn *conn)
++{
++ int res;
++ mm_segment_t oldfs;
++ struct msghdr msg;
++ int first_len;
++
++ EXTRACHECKS_BUG_ON(conn->read_cmnd == NULL);
++
++ if (unlikely(conn->closing)) {
++ res = -EIO;
++ goto out;
++ }
++
++ /*
++ * We suppose that if sock_recvmsg() returned less data than requested,
++ * then next time it will return -EAGAIN, so there's no point to call
++ * it again.
++ */
++
++restart:
++ memset(&msg, 0, sizeof(msg));
++ msg.msg_iov = conn->read_msg.msg_iov;
++ msg.msg_iovlen = conn->read_msg.msg_iovlen;
++ first_len = msg.msg_iov->iov_len;
++
++ oldfs = get_fs();
++ set_fs(get_ds());
++ res = sock_recvmsg(conn->sock, &msg, conn->read_size,
++ MSG_DONTWAIT | MSG_NOSIGNAL);
++ set_fs(oldfs);
++
++ TRACE_DBG("msg_iovlen %zd, first_len %d, read_size %d, res %d",
++ msg.msg_iovlen, first_len, conn->read_size, res);
++
++ if (res > 0) {
++ /*
++ * To save some considerable effort and CPU power we
++ * suppose that TCP functions adjust
++ * conn->read_msg.msg_iov and conn->read_msg.msg_iovlen
++ * on amount of copied data. This BUG_ON is intended
++ * to catch if it is changed in the future.
++ */
++ BUG_ON((res >= first_len) &&
++ (conn->read_msg.msg_iov->iov_len != 0));
++ conn->read_size -= res;
++ if (conn->read_size != 0) {
++ if (res >= first_len) {
++ int done = 1 + ((res - first_len) >> PAGE_SHIFT);
++ TRACE_DBG("done %d", done);
++ conn->read_msg.msg_iov += done;
++ conn->read_msg.msg_iovlen -= done;
++ }
++ }
++ res = conn->read_size;
++ } else {
++ switch (res) {
++ case -EAGAIN:
++ TRACE_DBG("EAGAIN received for conn %p", conn);
++ res = conn->read_size;
++ break;
++ case -ERESTARTSYS:
++ TRACE_DBG("ERESTARTSYS received for conn %p", conn);
++ goto restart;
++ default:
++ if (!conn->closing) {
++ PRINT_ERROR("sock_recvmsg() failed: %d", res);
++ mark_conn_closed(conn);
++ }
++ if (res == 0)
++ res = -EIO;
++ break;
++ }
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int iscsi_rx_check_ddigest(struct iscsi_conn *conn)
++{
++ struct iscsi_cmnd *cmnd = conn->read_cmnd;
++ int res;
++
++ res = do_recv(conn);
++ if (res == 0) {
++ conn->read_state = RX_END;
++
++ if (cmnd->pdu.datasize <= 16*1024) {
++ /*
++ * It's cache hot, so let's compute it inline. The
++ * choice here about what will expose more latency:
++ * possible cache misses or the digest calculation.
++ */
++ TRACE_DBG("cmnd %p, opcode %x: checking RX "
++ "ddigest inline", cmnd, cmnd_opcode(cmnd));
++ cmnd->ddigest_checked = 1;
++ res = digest_rx_data(cmnd);
++ if (unlikely(res != 0)) {
++ struct iscsi_cmnd *orig_req;
++ if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_DATA_OUT)
++ orig_req = cmnd->cmd_req;
++ else
++ orig_req = cmnd;
++ if (unlikely(orig_req->scst_cmd == NULL)) {
++ /* Just drop it */
++ iscsi_preliminary_complete(cmnd, orig_req, false);
++ } else {
++ set_scst_preliminary_status_rsp(orig_req, false,
++ SCST_LOAD_SENSE(iscsi_sense_crc_error));
++ /*
++ * Let's prelim complete cmnd too to
++ * handle the DATA OUT case
++ */
++ iscsi_preliminary_complete(cmnd, orig_req, false);
++ }
++ res = 0;
++ }
++ } else if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_CMD) {
++ cmd_add_on_rx_ddigest_list(cmnd, cmnd);
++ cmnd_get(cmnd);
++ } else if (cmnd_opcode(cmnd) != ISCSI_OP_SCSI_DATA_OUT) {
++ /*
++ * We could get here only for Nop-Out. ISCSI RFC
++ * doesn't specify how to deal with digest errors in
++ * this case. Let's just drop the command.
++ */
++ TRACE_DBG("cmnd %p, opcode %x: checking NOP RX "
++ "ddigest", cmnd, cmnd_opcode(cmnd));
++ res = digest_rx_data(cmnd);
++ if (unlikely(res != 0)) {
++ iscsi_preliminary_complete(cmnd, cmnd, false);
++ res = 0;
++ }
++ }
++ }
++
++ return res;
++}
++
++/* No locks, conn is rd processing */
++static int process_read_io(struct iscsi_conn *conn, int *closed)
++{
++ struct iscsi_cmnd *cmnd = conn->read_cmnd;
++ int res;
++
++ TRACE_ENTRY();
++
++ /* In case of error cmnd will be freed in close_conn() */
++
++ do {
++ switch (conn->read_state) {
++ case RX_INIT_BHS:
++ EXTRACHECKS_BUG_ON(conn->read_cmnd != NULL);
++ cmnd = cmnd_alloc(conn, NULL);
++ conn->read_cmnd = cmnd;
++ iscsi_conn_init_read(cmnd->conn,
++ (void __force __user *)&cmnd->pdu.bhs,
++ sizeof(cmnd->pdu.bhs));
++ conn->read_state = RX_BHS;
++ /* go through */
++
++ case RX_BHS:
++ res = do_recv(conn);
++ if (res == 0) {
++ iscsi_cmnd_get_length(&cmnd->pdu);
++ if (cmnd->pdu.ahssize == 0) {
++ if ((conn->hdigest_type & DIGEST_NONE) == 0)
++ conn->read_state = RX_INIT_HDIGEST;
++ else
++ conn->read_state = RX_CMD_START;
++ } else {
++ iscsi_conn_prepare_read_ahs(conn, cmnd);
++ conn->read_state = RX_AHS;
++ }
++ }
++ break;
++
++ case RX_CMD_START:
++ res = cmnd_rx_start(cmnd);
++ if (res == 0) {
++ if (cmnd->pdu.datasize == 0)
++ conn->read_state = RX_END;
++ else
++ conn->read_state = RX_DATA;
++ } else if (res > 0)
++ conn->read_state = RX_CMD_CONTINUE;
++ else
++ BUG_ON(!conn->closing);
++ break;
++
++ case RX_CMD_CONTINUE:
++ if (cmnd->scst_state == ISCSI_CMD_STATE_RX_CMD) {
++ TRACE_DBG("cmnd %p is still in RX_CMD state",
++ cmnd);
++ res = 1;
++ break;
++ }
++ res = cmnd_rx_continue(cmnd);
++ if (unlikely(res != 0))
++ BUG_ON(!conn->closing);
++ else {
++ if (cmnd->pdu.datasize == 0)
++ conn->read_state = RX_END;
++ else
++ conn->read_state = RX_DATA;
++ }
++ break;
++
++ case RX_DATA:
++ res = do_recv(conn);
++ if (res == 0) {
++ int psz = ((cmnd->pdu.datasize + 3) & -4) - cmnd->pdu.datasize;
++ if (psz != 0) {
++ TRACE_DBG("padding %d bytes", psz);
++ iscsi_conn_init_read(conn,
++ (void __force __user *)&conn->rpadding, psz);
++ conn->read_state = RX_PADDING;
++ } else if ((conn->ddigest_type & DIGEST_NONE) != 0)
++ conn->read_state = RX_END;
++ else
++ conn->read_state = RX_INIT_DDIGEST;
++ }
++ break;
++
++ case RX_END:
++ if (unlikely(conn->read_size != 0)) {
++ PRINT_CRIT_ERROR("conn read_size !=0 on RX_END "
++ "(conn %p, op %x, read_size %d)", conn,
++ cmnd_opcode(cmnd), conn->read_size);
++ BUG();
++ }
++ conn->read_cmnd = NULL;
++ conn->read_state = RX_INIT_BHS;
++
++ cmnd_rx_end(cmnd);
++
++ EXTRACHECKS_BUG_ON(conn->read_size != 0);
++
++ /*
++ * To maintain fairness. Res must be 0 here anyway, the
++ * assignment is only to remove compiler warning about
++ * uninitialized variable.
++ */
++ res = 0;
++ goto out;
++
++ case RX_INIT_HDIGEST:
++ iscsi_conn_init_read(conn,
++ (void __force __user *)&cmnd->hdigest, sizeof(u32));
++ conn->read_state = RX_CHECK_HDIGEST;
++ /* go through */
++
++ case RX_CHECK_HDIGEST:
++ res = do_recv(conn);
++ if (res == 0) {
++ res = digest_rx_header(cmnd);
++ if (unlikely(res != 0)) {
++ PRINT_ERROR("rx header digest for "
++ "initiator %s failed (%d)",
++ conn->session->initiator_name,
++ res);
++ mark_conn_closed(conn);
++ } else
++ conn->read_state = RX_CMD_START;
++ }
++ break;
++
++ case RX_INIT_DDIGEST:
++ iscsi_conn_init_read(conn,
++ (void __force __user *)&cmnd->ddigest,
++ sizeof(u32));
++ conn->read_state = RX_CHECK_DDIGEST;
++ /* go through */
++
++ case RX_CHECK_DDIGEST:
++ res = iscsi_rx_check_ddigest(conn);
++ break;
++
++ case RX_AHS:
++ res = do_recv(conn);
++ if (res == 0) {
++ if ((conn->hdigest_type & DIGEST_NONE) == 0)
++ conn->read_state = RX_INIT_HDIGEST;
++ else
++ conn->read_state = RX_CMD_START;
++ }
++ break;
++
++ case RX_PADDING:
++ res = do_recv(conn);
++ if (res == 0) {
++ if ((conn->ddigest_type & DIGEST_NONE) == 0)
++ conn->read_state = RX_INIT_DDIGEST;
++ else
++ conn->read_state = RX_END;
++ }
++ break;
++
++ default:
++ PRINT_CRIT_ERROR("%d %x", conn->read_state, cmnd_opcode(cmnd));
++ res = -1; /* to keep compiler happy */
++ BUG();
++ }
++ } while (res == 0);
++
++ if (unlikely(conn->closing)) {
++ start_close_conn(conn);
++ *closed = 1;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * Called under iscsi_rd_lock and BHs disabled, but will drop it inside,
++ * then reaquire.
++ */
++static void scst_do_job_rd(void)
++ __acquires(&iscsi_rd_lock)
++ __releases(&iscsi_rd_lock)
++{
++ TRACE_ENTRY();
++
++ /*
++ * We delete/add to tail connections to maintain fairness between them.
++ */
++
++ while (!list_empty(&iscsi_rd_list)) {
++ int closed = 0, rc;
++ struct iscsi_conn *conn = list_entry(iscsi_rd_list.next,
++ typeof(*conn), rd_list_entry);
++
++ list_del(&conn->rd_list_entry);
++
++ BUG_ON(conn->rd_state == ISCSI_CONN_RD_STATE_PROCESSING);
++ conn->rd_data_ready = 0;
++ conn->rd_state = ISCSI_CONN_RD_STATE_PROCESSING;
++#ifdef CONFIG_SCST_EXTRACHECKS
++ conn->rd_task = current;
++#endif
++ spin_unlock_bh(&iscsi_rd_lock);
++
++ rc = process_read_io(conn, &closed);
++
++ spin_lock_bh(&iscsi_rd_lock);
++
++ if (unlikely(closed))
++ continue;
++
++ if (unlikely(conn->conn_tm_active)) {
++ spin_unlock_bh(&iscsi_rd_lock);
++ iscsi_check_tm_data_wait_timeouts(conn, false);
++ spin_lock_bh(&iscsi_rd_lock);
++ }
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ conn->rd_task = NULL;
++#endif
++ if ((rc == 0) || conn->rd_data_ready) {
++ list_add_tail(&conn->rd_list_entry, &iscsi_rd_list);
++ conn->rd_state = ISCSI_CONN_RD_STATE_IN_LIST;
++ } else
++ conn->rd_state = ISCSI_CONN_RD_STATE_IDLE;
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline int test_rd_list(void)
++{
++ int res = !list_empty(&iscsi_rd_list) ||
++ unlikely(kthread_should_stop());
++ return res;
++}
++
++int istrd(void *arg)
++{
++ TRACE_ENTRY();
++
++ PRINT_INFO("Read thread started, PID %d", current->pid);
++
++ current->flags |= PF_NOFREEZE;
++
++ spin_lock_bh(&iscsi_rd_lock);
++ while (!kthread_should_stop()) {
++ wait_queue_t wait;
++ init_waitqueue_entry(&wait, current);
++
++ if (!test_rd_list()) {
++ add_wait_queue_exclusive_head(&iscsi_rd_waitQ, &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_rd_list())
++ break;
++ spin_unlock_bh(&iscsi_rd_lock);
++ schedule();
++ spin_lock_bh(&iscsi_rd_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&iscsi_rd_waitQ, &wait);
++ }
++ scst_do_job_rd();
++ }
++ spin_unlock_bh(&iscsi_rd_lock);
++
++ /*
++ * If kthread_should_stop() is true, we are guaranteed to be
++ * on the module unload, so iscsi_rd_list must be empty.
++ */
++ BUG_ON(!list_empty(&iscsi_rd_list));
++
++ PRINT_INFO("Read thread PID %d finished", current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++static inline void __iscsi_get_page_callback(struct iscsi_cmnd *cmd)
++{
++ int v;
++
++ TRACE_NET_PAGE("cmd %p, new net_ref_cnt %d",
++ cmd, atomic_read(&cmd->net_ref_cnt)+1);
++
++ v = atomic_inc_return(&cmd->net_ref_cnt);
++ if (v == 1) {
++ TRACE_NET_PAGE("getting cmd %p", cmd);
++ cmnd_get(cmd);
++ }
++ return;
++}
++
++void iscsi_get_page_callback(struct page *page)
++{
++ struct iscsi_cmnd *cmd = (struct iscsi_cmnd *)page->net_priv;
++
++ TRACE_NET_PAGE("page %p, _count %d", page,
++ atomic_read(&page->_count));
++
++ __iscsi_get_page_callback(cmd);
++ return;
++}
++
++static inline void __iscsi_put_page_callback(struct iscsi_cmnd *cmd)
++{
++ TRACE_NET_PAGE("cmd %p, new net_ref_cnt %d", cmd,
++ atomic_read(&cmd->net_ref_cnt)-1);
++
++ if (atomic_dec_and_test(&cmd->net_ref_cnt)) {
++ int i, sg_cnt = cmd->sg_cnt;
++ for (i = 0; i < sg_cnt; i++) {
++ struct page *page = sg_page(&cmd->sg[i]);
++ TRACE_NET_PAGE("Clearing page %p", page);
++ if (page->net_priv == cmd)
++ page->net_priv = NULL;
++ }
++ cmnd_put(cmd);
++ }
++ return;
++}
++
++void iscsi_put_page_callback(struct page *page)
++{
++ struct iscsi_cmnd *cmd = (struct iscsi_cmnd *)page->net_priv;
++
++ TRACE_NET_PAGE("page %p, _count %d", page,
++ atomic_read(&page->_count));
++
++ __iscsi_put_page_callback(cmd);
++ return;
++}
++
++static void check_net_priv(struct iscsi_cmnd *cmd, struct page *page)
++{
++ if ((atomic_read(&cmd->net_ref_cnt) == 1) && (page->net_priv == cmd)) {
++ TRACE_DBG("sendpage() not called get_page(), zeroing net_priv "
++ "%p (page %p)", page->net_priv, page);
++ page->net_priv = NULL;
++ }
++ return;
++}
++#else
++static inline void check_net_priv(struct iscsi_cmnd *cmd, struct page *page) {}
++static inline void __iscsi_get_page_callback(struct iscsi_cmnd *cmd) {}
++static inline void __iscsi_put_page_callback(struct iscsi_cmnd *cmd) {}
++#endif
++
++void req_add_to_write_timeout_list(struct iscsi_cmnd *req)
++{
++ struct iscsi_conn *conn;
++ bool set_conn_tm_active = false;
++
++ TRACE_ENTRY();
++
++ if (req->on_write_timeout_list)
++ goto out;
++
++ conn = req->conn;
++
++ TRACE_DBG("Adding req %p to conn %p write_timeout_list",
++ req, conn);
++
++ spin_lock_bh(&conn->write_list_lock);
++
++ /* Recheck, since it can be changed behind us */
++ if (unlikely(req->on_write_timeout_list)) {
++ spin_unlock_bh(&conn->write_list_lock);
++ goto out;
++ }
++
++ req->on_write_timeout_list = 1;
++ req->write_start = jiffies;
++
++ list_add_tail(&req->write_timeout_list_entry,
++ &conn->write_timeout_list);
++
++ if (!timer_pending(&conn->rsp_timer)) {
++ unsigned long timeout_time;
++ if (unlikely(conn->conn_tm_active ||
++ test_bit(ISCSI_CMD_ABORTED,
++ &req->prelim_compl_flags))) {
++ set_conn_tm_active = true;
++ timeout_time = req->write_start +
++ ISCSI_TM_DATA_WAIT_TIMEOUT +
++ ISCSI_ADD_SCHED_TIME;
++ } else
++ timeout_time = req->write_start +
++ conn->rsp_timeout + ISCSI_ADD_SCHED_TIME;
++
++ TRACE_DBG("Starting timer on %ld (con %p, write_start %ld)",
++ timeout_time, conn, req->write_start);
++
++ conn->rsp_timer.expires = timeout_time;
++ add_timer(&conn->rsp_timer);
++ } else if (unlikely(test_bit(ISCSI_CMD_ABORTED,
++ &req->prelim_compl_flags))) {
++ unsigned long timeout_time = jiffies +
++ ISCSI_TM_DATA_WAIT_TIMEOUT + ISCSI_ADD_SCHED_TIME;
++ set_conn_tm_active = true;
++ if (time_after(conn->rsp_timer.expires, timeout_time)) {
++ TRACE_MGMT_DBG("Mod timer on %ld (conn %p)",
++ timeout_time, conn);
++ mod_timer(&conn->rsp_timer, timeout_time);
++ }
++ }
++
++ spin_unlock_bh(&conn->write_list_lock);
++
++ /*
++ * conn_tm_active can be already cleared by
++ * iscsi_check_tm_data_wait_timeouts(). write_list_lock is an inner
++ * lock for iscsi_rd_lock.
++ */
++ if (unlikely(set_conn_tm_active)) {
++ spin_lock_bh(&iscsi_rd_lock);
++ TRACE_MGMT_DBG("Setting conn_tm_active for conn %p", conn);
++ conn->conn_tm_active = 1;
++ spin_unlock_bh(&iscsi_rd_lock);
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int write_data(struct iscsi_conn *conn)
++{
++ mm_segment_t oldfs;
++ struct file *file;
++ struct iovec *iop;
++ struct socket *sock;
++ ssize_t (*sock_sendpage)(struct socket *, struct page *, int, size_t,
++ int);
++ ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
++ struct iscsi_cmnd *write_cmnd = conn->write_cmnd;
++ struct iscsi_cmnd *ref_cmd;
++ struct page *page;
++ struct scatterlist *sg;
++ int saved_size, size, sendsize;
++ int length, offset, idx;
++ int flags, res, count, sg_size;
++ bool do_put = false, ref_cmd_to_parent;
++
++ TRACE_ENTRY();
++
++ iscsi_extracheck_is_wr_thread(conn);
++
++ if (!write_cmnd->own_sg) {
++ ref_cmd = write_cmnd->parent_req;
++ ref_cmd_to_parent = true;
++ } else {
++ ref_cmd = write_cmnd;
++ ref_cmd_to_parent = false;
++ }
++
++ req_add_to_write_timeout_list(write_cmnd->parent_req);
++
++ file = conn->file;
++ size = conn->write_size;
++ saved_size = size;
++ iop = conn->write_iop;
++ count = conn->write_iop_used;
++
++ if (iop) {
++ while (1) {
++ loff_t off = 0;
++ int rest;
++
++ BUG_ON(count > (signed)(sizeof(conn->write_iov) /
++ sizeof(conn->write_iov[0])));
++retry:
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ res = vfs_writev(file,
++ (struct iovec __force __user *)iop,
++ count, &off);
++ set_fs(oldfs);
++ TRACE_WRITE("sid %#Lx, cid %u, res %d, iov_len %ld",
++ (long long unsigned int)conn->session->sid,
++ conn->cid, res, (long)iop->iov_len);
++ if (unlikely(res <= 0)) {
++ if (res == -EAGAIN) {
++ conn->write_iop = iop;
++ conn->write_iop_used = count;
++ goto out_iov;
++ } else if (res == -EINTR)
++ goto retry;
++ goto out_err;
++ }
++
++ rest = res;
++ size -= res;
++ while ((typeof(rest))iop->iov_len <= rest && rest) {
++ rest -= iop->iov_len;
++ iop++;
++ count--;
++ }
++ if (count == 0) {
++ conn->write_iop = NULL;
++ conn->write_iop_used = 0;
++ if (size)
++ break;
++ goto out_iov;
++ }
++ BUG_ON(iop > conn->write_iov + sizeof(conn->write_iov)
++ /sizeof(conn->write_iov[0]));
++ iop->iov_base += rest;
++ iop->iov_len -= rest;
++ }
++ }
++
++ sg = write_cmnd->sg;
++ if (unlikely(sg == NULL)) {
++ PRINT_INFO("WARNING: Data missed (cmd %p)!", write_cmnd);
++ res = 0;
++ goto out;
++ }
++
++ /* To protect from too early transfer completion race */
++ __iscsi_get_page_callback(ref_cmd);
++ do_put = true;
++
++ sock = conn->sock;
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ sock_sendpage = sock->ops->sendpage;
++#else
++ if ((write_cmnd->parent_req->scst_cmd != NULL) &&
++ scst_cmd_get_dh_data_buff_alloced(write_cmnd->parent_req->scst_cmd))
++ sock_sendpage = sock_no_sendpage;
++ else
++ sock_sendpage = sock->ops->sendpage;
++#endif
++
++ flags = MSG_DONTWAIT;
++ sg_size = size;
++
++ if (sg != write_cmnd->rsp_sg) {
++ offset = conn->write_offset + sg[0].offset;
++ idx = offset >> PAGE_SHIFT;
++ offset &= ~PAGE_MASK;
++ length = min(size, (int)PAGE_SIZE - offset);
++ TRACE_WRITE("write_offset %d, sg_size %d, idx %d, offset %d, "
++ "length %d", conn->write_offset, sg_size, idx, offset,
++ length);
++ } else {
++ idx = 0;
++ offset = conn->write_offset;
++ while (offset >= sg[idx].length) {
++ offset -= sg[idx].length;
++ idx++;
++ }
++ length = sg[idx].length - offset;
++ offset += sg[idx].offset;
++ sock_sendpage = sock_no_sendpage;
++ TRACE_WRITE("rsp_sg: write_offset %d, sg_size %d, idx %d, "
++ "offset %d, length %d", conn->write_offset, sg_size,
++ idx, offset, length);
++ }
++ page = sg_page(&sg[idx]);
++
++ while (1) {
++ sendpage = sock_sendpage;
++
++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
++ {
++ static DEFINE_SPINLOCK(net_priv_lock);
++ spin_lock(&net_priv_lock);
++ if (unlikely(page->net_priv != NULL)) {
++ if (page->net_priv != ref_cmd) {
++ /*
++ * This might happen if user space
++ * supplies to scst_user the same
++ * pages in different commands or in
++ * case of zero-copy FILEIO, when
++ * several initiators request the same
++ * data simultaneously.
++ */
++ TRACE_DBG("net_priv isn't NULL and != "
++ "ref_cmd (write_cmnd %p, ref_cmd "
++ "%p, sg %p, idx %d, page %p, "
++ "net_priv %p)",
++ write_cmnd, ref_cmd, sg, idx,
++ page, page->net_priv);
++ sendpage = sock_no_sendpage;
++ }
++ } else
++ page->net_priv = ref_cmd;
++ spin_unlock(&net_priv_lock);
++ }
++#endif
++ sendsize = min(size, length);
++ if (size <= sendsize) {
++retry2:
++ res = sendpage(sock, page, offset, size, flags);
++ TRACE_WRITE("Final %s sid %#Lx, cid %u, res %d (page "
++ "index %lu, offset %u, size %u, cmd %p, "
++ "page %p)", (sendpage != sock_no_sendpage) ?
++ "sendpage" : "sock_no_sendpage",
++ (long long unsigned int)conn->session->sid,
++ conn->cid, res, page->index,
++ offset, size, write_cmnd, page);
++ if (unlikely(res <= 0)) {
++ if (res == -EINTR)
++ goto retry2;
++ else
++ goto out_res;
++ }
++
++ check_net_priv(ref_cmd, page);
++ if (res == size) {
++ conn->write_size = 0;
++ res = saved_size;
++ goto out_put;
++ }
++
++ offset += res;
++ size -= res;
++ goto retry2;
++ }
++
++retry1:
++ res = sendpage(sock, page, offset, sendsize, flags | MSG_MORE);
++ TRACE_WRITE("%s sid %#Lx, cid %u, res %d (page index %lu, "
++ "offset %u, sendsize %u, size %u, cmd %p, page %p)",
++ (sendpage != sock_no_sendpage) ? "sendpage" :
++ "sock_no_sendpage",
++ (unsigned long long)conn->session->sid, conn->cid,
++ res, page->index, offset, sendsize, size,
++ write_cmnd, page);
++ if (unlikely(res <= 0)) {
++ if (res == -EINTR)
++ goto retry1;
++ else
++ goto out_res;
++ }
++
++ check_net_priv(ref_cmd, page);
++
++ size -= res;
++
++ if (res == sendsize) {
++ idx++;
++ EXTRACHECKS_BUG_ON(idx >= ref_cmd->sg_cnt);
++ page = sg_page(&sg[idx]);
++ length = sg[idx].length;
++ offset = sg[idx].offset;
++ } else {
++ offset += res;
++ sendsize -= res;
++ goto retry1;
++ }
++ }
++
++out_off:
++ conn->write_offset += sg_size - size;
++
++out_iov:
++ conn->write_size = size;
++ if ((saved_size == size) && res == -EAGAIN)
++ goto out_put;
++
++ res = saved_size - size;
++
++out_put:
++ if (do_put)
++ __iscsi_put_page_callback(ref_cmd);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_res:
++ check_net_priv(ref_cmd, page);
++ if (res == -EAGAIN)
++ goto out_off;
++ /* else go through */
++
++out_err:
++#ifndef CONFIG_SCST_DEBUG
++ if (!conn->closing)
++#endif
++ {
++ PRINT_ERROR("error %d at sid:cid %#Lx:%u, cmnd %p", res,
++ (long long unsigned int)conn->session->sid,
++ conn->cid, conn->write_cmnd);
++ }
++ if (ref_cmd_to_parent &&
++ ((ref_cmd->scst_cmd != NULL) || (ref_cmd->scst_aen != NULL))) {
++ if (ref_cmd->scst_state == ISCSI_CMD_STATE_AEN)
++ scst_set_aen_delivery_status(ref_cmd->scst_aen,
++ SCST_AEN_RES_FAILED);
++ else
++ scst_set_delivery_status(ref_cmd->scst_cmd,
++ SCST_CMD_DELIVERY_FAILED);
++ }
++ goto out_put;
++}
++
++static int exit_tx(struct iscsi_conn *conn, int res)
++{
++ iscsi_extracheck_is_wr_thread(conn);
++
++ switch (res) {
++ case -EAGAIN:
++ case -ERESTARTSYS:
++ break;
++ default:
++#ifndef CONFIG_SCST_DEBUG
++ if (!conn->closing)
++#endif
++ {
++ PRINT_ERROR("Sending data failed: initiator %s, "
++ "write_size %d, write_state %d, res %d",
++ conn->session->initiator_name,
++ conn->write_size,
++ conn->write_state, res);
++ }
++ conn->write_state = TX_END;
++ conn->write_size = 0;
++ mark_conn_closed(conn);
++ break;
++ }
++ return res;
++}
++
++static int tx_ddigest(struct iscsi_cmnd *cmnd, int state)
++{
++ int res, rest = cmnd->conn->write_size;
++ struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT};
++ struct kvec iov;
++
++ iscsi_extracheck_is_wr_thread(cmnd->conn);
++
++ TRACE_DBG("Sending data digest %x (cmd %p)", cmnd->ddigest, cmnd);
++
++ iov.iov_base = (char *)(&cmnd->ddigest) + (sizeof(u32) - rest);
++ iov.iov_len = rest;
++
++ res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest);
++ if (res > 0) {
++ cmnd->conn->write_size -= res;
++ if (!cmnd->conn->write_size)
++ cmnd->conn->write_state = state;
++ } else
++ res = exit_tx(cmnd->conn, res);
++
++ return res;
++}
++
++static void init_tx_hdigest(struct iscsi_cmnd *cmnd)
++{
++ struct iscsi_conn *conn = cmnd->conn;
++ struct iovec *iop;
++
++ iscsi_extracheck_is_wr_thread(conn);
++
++ digest_tx_header(cmnd);
++
++ BUG_ON(conn->write_iop_used >=
++ (signed)(sizeof(conn->write_iov)/sizeof(conn->write_iov[0])));
++
++ iop = &conn->write_iop[conn->write_iop_used];
++ conn->write_iop_used++;
++ iop->iov_base = (void __force __user *)&(cmnd->hdigest);
++ iop->iov_len = sizeof(u32);
++ conn->write_size += sizeof(u32);
++
++ return;
++}
++
++static int tx_padding(struct iscsi_cmnd *cmnd, int state)
++{
++ int res, rest = cmnd->conn->write_size;
++ struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT};
++ struct kvec iov;
++ static const uint32_t padding;
++
++ iscsi_extracheck_is_wr_thread(cmnd->conn);
++
++ TRACE_DBG("Sending %d padding bytes (cmd %p)", rest, cmnd);
++
++ iov.iov_base = (char *)(&padding) + (sizeof(uint32_t) - rest);
++ iov.iov_len = rest;
++
++ res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest);
++ if (res > 0) {
++ cmnd->conn->write_size -= res;
++ if (!cmnd->conn->write_size)
++ cmnd->conn->write_state = state;
++ } else
++ res = exit_tx(cmnd->conn, res);
++
++ return res;
++}
++
++static int iscsi_do_send(struct iscsi_conn *conn, int state)
++{
++ int res;
++
++ iscsi_extracheck_is_wr_thread(conn);
++
++ res = write_data(conn);
++ if (res > 0) {
++ if (!conn->write_size)
++ conn->write_state = state;
++ } else
++ res = exit_tx(conn, res);
++
++ return res;
++}
++
++/*
++ * No locks, conn is wr processing.
++ *
++ * IMPORTANT! Connection conn must be protected by additional conn_get()
++ * upon entrance in this function, because otherwise it could be destroyed
++ * inside as a result of cmnd release.
++ */
++int iscsi_send(struct iscsi_conn *conn)
++{
++ struct iscsi_cmnd *cmnd = conn->write_cmnd;
++ int ddigest, res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("conn %p, write_cmnd %p", conn, cmnd);
++
++ iscsi_extracheck_is_wr_thread(conn);
++
++ ddigest = conn->ddigest_type != DIGEST_NONE ? 1 : 0;
++
++ switch (conn->write_state) {
++ case TX_INIT:
++ BUG_ON(cmnd != NULL);
++ cmnd = conn->write_cmnd = iscsi_get_send_cmnd(conn);
++ if (!cmnd)
++ goto out;
++ cmnd_tx_start(cmnd);
++ if (!(conn->hdigest_type & DIGEST_NONE))
++ init_tx_hdigest(cmnd);
++ conn->write_state = TX_BHS_DATA;
++ case TX_BHS_DATA:
++ res = iscsi_do_send(conn, cmnd->pdu.datasize ?
++ TX_INIT_PADDING : TX_END);
++ if (res <= 0 || conn->write_state != TX_INIT_PADDING)
++ break;
++ case TX_INIT_PADDING:
++ cmnd->conn->write_size = ((cmnd->pdu.datasize + 3) & -4) -
++ cmnd->pdu.datasize;
++ if (cmnd->conn->write_size != 0)
++ conn->write_state = TX_PADDING;
++ else if (ddigest)
++ conn->write_state = TX_INIT_DDIGEST;
++ else
++ conn->write_state = TX_END;
++ break;
++ case TX_PADDING:
++ res = tx_padding(cmnd, ddigest ? TX_INIT_DDIGEST : TX_END);
++ if (res <= 0 || conn->write_state != TX_INIT_DDIGEST)
++ break;
++ case TX_INIT_DDIGEST:
++ cmnd->conn->write_size = sizeof(u32);
++ conn->write_state = TX_DDIGEST;
++ case TX_DDIGEST:
++ res = tx_ddigest(cmnd, TX_END);
++ break;
++ default:
++ PRINT_CRIT_ERROR("%d %d %x", res, conn->write_state,
++ cmnd_opcode(cmnd));
++ BUG();
++ }
++
++ if (res == 0)
++ goto out;
++
++ if (conn->write_state != TX_END)
++ goto out;
++
++ if (unlikely(conn->write_size)) {
++ PRINT_CRIT_ERROR("%d %x %u", res, cmnd_opcode(cmnd),
++ conn->write_size);
++ BUG();
++ }
++ cmnd_tx_end(cmnd);
++
++ rsp_cmnd_release(cmnd);
++
++ conn->write_cmnd = NULL;
++ conn->write_state = TX_INIT;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * Called under iscsi_wr_lock and BHs disabled, but will drop it inside,
++ * then reaquire.
++ */
++static void scst_do_job_wr(void)
++ __acquires(&iscsi_wr_lock)
++ __releases(&iscsi_wr_lock)
++{
++ TRACE_ENTRY();
++
++ /*
++ * We delete/add to tail connections to maintain fairness between them.
++ */
++
++ while (!list_empty(&iscsi_wr_list)) {
++ int rc;
++ struct iscsi_conn *conn = list_entry(iscsi_wr_list.next,
++ typeof(*conn), wr_list_entry);
++
++ TRACE_DBG("conn %p, wr_state %x, wr_space_ready %d, "
++ "write ready %d", conn, conn->wr_state,
++ conn->wr_space_ready, test_write_ready(conn));
++
++ list_del(&conn->wr_list_entry);
++
++ BUG_ON(conn->wr_state == ISCSI_CONN_WR_STATE_PROCESSING);
++
++ conn->wr_state = ISCSI_CONN_WR_STATE_PROCESSING;
++ conn->wr_space_ready = 0;
++#ifdef CONFIG_SCST_EXTRACHECKS
++ conn->wr_task = current;
++#endif
++ spin_unlock_bh(&iscsi_wr_lock);
++
++ conn_get(conn);
++
++ rc = iscsi_send(conn);
++
++ spin_lock_bh(&iscsi_wr_lock);
++#ifdef CONFIG_SCST_EXTRACHECKS
++ conn->wr_task = NULL;
++#endif
++ if ((rc == -EAGAIN) && !conn->wr_space_ready) {
++ TRACE_DBG("EAGAIN, setting WR_STATE_SPACE_WAIT "
++ "(conn %p)", conn);
++ conn->wr_state = ISCSI_CONN_WR_STATE_SPACE_WAIT;
++ } else if (test_write_ready(conn)) {
++ list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
++ conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
++ } else
++ conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
++
++ conn_put(conn);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline int test_wr_list(void)
++{
++ int res = !list_empty(&iscsi_wr_list) ||
++ unlikely(kthread_should_stop());
++ return res;
++}
++
++int istwr(void *arg)
++{
++ TRACE_ENTRY();
++
++ PRINT_INFO("Write thread started, PID %d", current->pid);
++
++ current->flags |= PF_NOFREEZE;
++
++ spin_lock_bh(&iscsi_wr_lock);
++ while (!kthread_should_stop()) {
++ wait_queue_t wait;
++ init_waitqueue_entry(&wait, current);
++
++ if (!test_wr_list()) {
++ add_wait_queue_exclusive_head(&iscsi_wr_waitQ, &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (test_wr_list())
++ break;
++ spin_unlock_bh(&iscsi_wr_lock);
++ schedule();
++ spin_lock_bh(&iscsi_wr_lock);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&iscsi_wr_waitQ, &wait);
++ }
++ scst_do_job_wr();
++ }
++ spin_unlock_bh(&iscsi_wr_lock);
++
++ /*
++ * If kthread_should_stop() is true, we are guaranteed to be
++ * on the module unload, so iscsi_wr_list must be empty.
++ */
++ BUG_ON(!list_empty(&iscsi_wr_list));
++
++ PRINT_INFO("Write thread PID %d finished", current->pid);
++
++ TRACE_EXIT();
++ return 0;
++}
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/param.c linux-2.6.36/drivers/scst/iscsi-scst/param.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/param.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/param.c
+@@ -0,0 +1,306 @@
++/*
++ * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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.
++ *
++ * 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.
++ */
++
++#include "iscsi.h"
++#include "digest.h"
++
++#define CHECK_PARAM(info, iparams, word, min, max) \
++do { \
++ if (!(info)->partial || ((info)->partial & 1 << key_##word)) { \
++ TRACE_DBG("%s: %u", #word, (iparams)[key_##word]); \
++ if ((iparams)[key_##word] < (min) || \
++ (iparams)[key_##word] > (max)) { \
++ if ((iparams)[key_##word] < (min)) { \
++ (iparams)[key_##word] = (min); \
++ PRINT_WARNING("%s: %u is too small, resetting " \
++ "it to allowed min %u", \
++ #word, (iparams)[key_##word], (min)); \
++ } else { \
++ PRINT_WARNING("%s: %u is too big, resetting " \
++ "it to allowed max %u", \
++ #word, (iparams)[key_##word], (max)); \
++ (iparams)[key_##word] = (max); \
++ } \
++ } \
++ } \
++} while (0)
++
++#define SET_PARAM(params, info, iparams, word) \
++({ \
++ int changed = 0; \
++ if (!(info)->partial || ((info)->partial & 1 << key_##word)) { \
++ if ((params)->word != (iparams)[key_##word]) \
++ changed = 1; \
++ (params)->word = (iparams)[key_##word]; \
++ TRACE_DBG("%s set to %u", #word, (params)->word); \
++ } \
++ changed; \
++})
++
++#define GET_PARAM(params, info, iparams, word) \
++do { \
++ (iparams)[key_##word] = (params)->word; \
++} while (0)
++
++const char *iscsi_get_bool_value(int val)
++{
++ if (val)
++ return "Yes";
++ else
++ return "No";
++}
++
++const char *iscsi_get_digest_name(int val, char *res)
++{
++ int pos = 0;
++
++ if (val & DIGEST_NONE)
++ pos = sprintf(&res[pos], "%s", "None");
++
++ if (val & DIGEST_CRC32C)
++ pos += sprintf(&res[pos], "%s%s", (pos != 0) ? ", " : "",
++ "CRC32C");
++
++ if (pos == 0)
++ sprintf(&res[pos], "%s", "Unknown");
++
++ return res;
++}
++
++static void log_params(struct iscsi_sess_params *params)
++{
++ char digest_name[64];
++
++ PRINT_INFO("Negotiated parameters: InitialR2T %s, ImmediateData %s, "
++ "MaxConnections %d, MaxRecvDataSegmentLength %d, "
++ "MaxXmitDataSegmentLength %d, ",
++ iscsi_get_bool_value(params->initial_r2t),
++ iscsi_get_bool_value(params->immediate_data), params->max_connections,
++ params->max_recv_data_length, params->max_xmit_data_length);
++ PRINT_INFO(" MaxBurstLength %d, FirstBurstLength %d, "
++ "DefaultTime2Wait %d, DefaultTime2Retain %d, ",
++ params->max_burst_length, params->first_burst_length,
++ params->default_wait_time, params->default_retain_time);
++ PRINT_INFO(" MaxOutstandingR2T %d, DataPDUInOrder %s, "
++ "DataSequenceInOrder %s, ErrorRecoveryLevel %d, ",
++ params->max_outstanding_r2t,
++ iscsi_get_bool_value(params->data_pdu_inorder),
++ iscsi_get_bool_value(params->data_sequence_inorder),
++ params->error_recovery_level);
++ PRINT_INFO(" HeaderDigest %s, DataDigest %s, OFMarker %s, "
++ "IFMarker %s, OFMarkInt %d, IFMarkInt %d",
++ iscsi_get_digest_name(params->header_digest, digest_name),
++ iscsi_get_digest_name(params->data_digest, digest_name),
++ iscsi_get_bool_value(params->ofmarker),
++ iscsi_get_bool_value(params->ifmarker),
++ params->ofmarkint, params->ifmarkint);
++}
++
++/* target_mutex supposed to be locked */
++static void sess_params_check(struct iscsi_kern_params_info *info)
++{
++ int32_t *iparams = info->session_params;
++ const int max_len = ISCSI_CONN_IOV_MAX * PAGE_SIZE;
++
++ CHECK_PARAM(info, iparams, initial_r2t, 0, 1);
++ CHECK_PARAM(info, iparams, immediate_data, 0, 1);
++ CHECK_PARAM(info, iparams, max_connections, 1, 1);
++ CHECK_PARAM(info, iparams, max_recv_data_length, 512, max_len);
++ CHECK_PARAM(info, iparams, max_xmit_data_length, 512, max_len);
++ CHECK_PARAM(info, iparams, max_burst_length, 512, max_len);
++ CHECK_PARAM(info, iparams, first_burst_length, 512, max_len);
++ CHECK_PARAM(info, iparams, max_outstanding_r2t, 1, 65535);
++ CHECK_PARAM(info, iparams, error_recovery_level, 0, 0);
++ CHECK_PARAM(info, iparams, data_pdu_inorder, 0, 1);
++ CHECK_PARAM(info, iparams, data_sequence_inorder, 0, 1);
++
++ digest_alg_available(&iparams[key_header_digest]);
++ digest_alg_available(&iparams[key_data_digest]);
++
++ CHECK_PARAM(info, iparams, ofmarker, 0, 0);
++ CHECK_PARAM(info, iparams, ifmarker, 0, 0);
++
++ return;
++}
++
++/* target_mutex supposed to be locked */
++static void sess_params_set(struct iscsi_sess_params *params,
++ struct iscsi_kern_params_info *info)
++{
++ int32_t *iparams = info->session_params;
++
++ SET_PARAM(params, info, iparams, initial_r2t);
++ SET_PARAM(params, info, iparams, immediate_data);
++ SET_PARAM(params, info, iparams, max_connections);
++ SET_PARAM(params, info, iparams, max_recv_data_length);
++ SET_PARAM(params, info, iparams, max_xmit_data_length);
++ SET_PARAM(params, info, iparams, max_burst_length);
++ SET_PARAM(params, info, iparams, first_burst_length);
++ SET_PARAM(params, info, iparams, default_wait_time);
++ SET_PARAM(params, info, iparams, default_retain_time);
++ SET_PARAM(params, info, iparams, max_outstanding_r2t);
++ SET_PARAM(params, info, iparams, data_pdu_inorder);
++ SET_PARAM(params, info, iparams, data_sequence_inorder);
++ SET_PARAM(params, info, iparams, error_recovery_level);
++ SET_PARAM(params, info, iparams, header_digest);
++ SET_PARAM(params, info, iparams, data_digest);
++ SET_PARAM(params, info, iparams, ofmarker);
++ SET_PARAM(params, info, iparams, ifmarker);
++ SET_PARAM(params, info, iparams, ofmarkint);
++ SET_PARAM(params, info, iparams, ifmarkint);
++ return;
++}
++
++static void sess_params_get(struct iscsi_sess_params *params,
++ struct iscsi_kern_params_info *info)
++{
++ int32_t *iparams = info->session_params;
++
++ GET_PARAM(params, info, iparams, initial_r2t);
++ GET_PARAM(params, info, iparams, immediate_data);
++ GET_PARAM(params, info, iparams, max_connections);
++ GET_PARAM(params, info, iparams, max_recv_data_length);
++ GET_PARAM(params, info, iparams, max_xmit_data_length);
++ GET_PARAM(params, info, iparams, max_burst_length);
++ GET_PARAM(params, info, iparams, first_burst_length);
++ GET_PARAM(params, info, iparams, default_wait_time);
++ GET_PARAM(params, info, iparams, default_retain_time);
++ GET_PARAM(params, info, iparams, max_outstanding_r2t);
++ GET_PARAM(params, info, iparams, data_pdu_inorder);
++ GET_PARAM(params, info, iparams, data_sequence_inorder);
++ GET_PARAM(params, info, iparams, error_recovery_level);
++ GET_PARAM(params, info, iparams, header_digest);
++ GET_PARAM(params, info, iparams, data_digest);
++ GET_PARAM(params, info, iparams, ofmarker);
++ GET_PARAM(params, info, iparams, ifmarker);
++ GET_PARAM(params, info, iparams, ofmarkint);
++ GET_PARAM(params, info, iparams, ifmarkint);
++ return;
++}
++
++/* target_mutex supposed to be locked */
++static void tgt_params_check(struct iscsi_session *session,
++ struct iscsi_kern_params_info *info)
++{
++ int32_t *iparams = info->target_params;
++
++ CHECK_PARAM(info, iparams, queued_cmnds, MIN_NR_QUEUED_CMNDS,
++ min_t(int, MAX_NR_QUEUED_CMNDS,
++ scst_get_max_lun_commands(session->scst_sess, NO_SUCH_LUN)));
++ CHECK_PARAM(info, iparams, rsp_timeout, MIN_RSP_TIMEOUT,
++ MAX_RSP_TIMEOUT);
++ CHECK_PARAM(info, iparams, nop_in_interval, MIN_NOP_IN_INTERVAL,
++ MAX_NOP_IN_INTERVAL);
++ return;
++}
++
++/* target_mutex supposed to be locked */
++static int iscsi_tgt_params_set(struct iscsi_session *session,
++ struct iscsi_kern_params_info *info, int set)
++{
++ struct iscsi_tgt_params *params = &session->tgt_params;
++ int32_t *iparams = info->target_params;
++
++ if (set) {
++ struct iscsi_conn *conn;
++
++ tgt_params_check(session, info);
++
++ SET_PARAM(params, info, iparams, queued_cmnds);
++ SET_PARAM(params, info, iparams, rsp_timeout);
++ SET_PARAM(params, info, iparams, nop_in_interval);
++
++ PRINT_INFO("Target parameters set for session %llx: "
++ "QueuedCommands %d, Response timeout %d, Nop-In "
++ "interval %d", session->sid, params->queued_cmnds,
++ params->rsp_timeout, params->nop_in_interval);
++
++ list_for_each_entry(conn, &session->conn_list,
++ conn_list_entry) {
++ conn->rsp_timeout = session->tgt_params.rsp_timeout * HZ;
++ conn->nop_in_interval = session->tgt_params.nop_in_interval * HZ;
++ spin_lock_bh(&iscsi_rd_lock);
++ if (!conn->closing && (conn->nop_in_interval > 0)) {
++ TRACE_DBG("Schedule Nop-In work for conn %p", conn);
++ schedule_delayed_work(&conn->nop_in_delayed_work,
++ conn->nop_in_interval + ISCSI_ADD_SCHED_TIME);
++ }
++ spin_unlock_bh(&iscsi_rd_lock);
++ }
++ } else {
++ GET_PARAM(params, info, iparams, queued_cmnds);
++ GET_PARAM(params, info, iparams, rsp_timeout);
++ GET_PARAM(params, info, iparams, nop_in_interval);
++ }
++
++ return 0;
++}
++
++/* target_mutex supposed to be locked */
++static int iscsi_sess_params_set(struct iscsi_session *session,
++ struct iscsi_kern_params_info *info, int set)
++{
++ struct iscsi_sess_params *params;
++
++ if (set)
++ sess_params_check(info);
++
++ params = &session->sess_params;
++
++ if (set) {
++ sess_params_set(params, info);
++ log_params(params);
++ } else
++ sess_params_get(params, info);
++
++ return 0;
++}
++
++/* target_mutex supposed to be locked */
++int iscsi_params_set(struct iscsi_target *target,
++ struct iscsi_kern_params_info *info, int set)
++{
++ int err;
++ struct iscsi_session *session;
++
++ if (info->sid == 0) {
++ PRINT_ERROR("sid must not be %d", 0);
++ err = -EINVAL;
++ goto out;
++ }
++
++ session = session_lookup(target, info->sid);
++ if (session == NULL) {
++ PRINT_ERROR("Session for sid %llx not found", info->sid);
++ err = -ENOENT;
++ goto out;
++ }
++
++ if (set && !list_empty(&session->conn_list) &&
++ (info->params_type != key_target)) {
++ err = -EBUSY;
++ goto out;
++ }
++
++ if (info->params_type == key_session)
++ err = iscsi_sess_params_set(session, info, set);
++ else if (info->params_type == key_target)
++ err = iscsi_tgt_params_set(session, info, set);
++ else
++ err = -EINVAL;
++
++out:
++ return err;
++}
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/session.c linux-2.6.36/drivers/scst/iscsi-scst/session.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/session.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/session.c
+@@ -0,0 +1,499 @@
++/*
++ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include "iscsi.h"
++
++/* target_mutex supposed to be locked */
++struct iscsi_session *session_lookup(struct iscsi_target *target, u64 sid)
++{
++ struct iscsi_session *session;
++
++ list_for_each_entry(session, &target->session_list,
++ session_list_entry) {
++ if (session->sid == sid)
++ return session;
++ }
++ return NULL;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int iscsi_session_alloc(struct iscsi_target *target,
++ struct iscsi_kern_session_info *info, struct iscsi_session **result)
++{
++ int err;
++ unsigned int i;
++ struct iscsi_session *session;
++ char *name = NULL;
++
++ session = kzalloc(sizeof(*session), GFP_KERNEL);
++ if (!session)
++ return -ENOMEM;
++
++ session->target = target;
++ session->sid = info->sid;
++ atomic_set(&session->active_cmds, 0);
++ session->exp_cmd_sn = info->exp_cmd_sn;
++
++ session->initiator_name = kstrdup(info->initiator_name, GFP_KERNEL);
++ if (!session->initiator_name) {
++ err = -ENOMEM;
++ goto err;
++ }
++
++ name = info->full_initiator_name;
++
++ INIT_LIST_HEAD(&session->conn_list);
++ INIT_LIST_HEAD(&session->pending_list);
++
++ spin_lock_init(&session->sn_lock);
++
++ spin_lock_init(&session->cmnd_data_wait_hash_lock);
++ for (i = 0; i < ARRAY_SIZE(session->cmnd_data_wait_hash); i++)
++ INIT_LIST_HEAD(&session->cmnd_data_wait_hash[i]);
++
++ session->next_ttt = 1;
++
++ session->scst_sess = scst_register_session(target->scst_tgt, 0,
++ name, session, NULL, NULL);
++ if (session->scst_sess == NULL) {
++ PRINT_ERROR("%s", "scst_register_session() failed");
++ err = -ENOMEM;
++ goto err;
++ }
++
++ TRACE_MGMT_DBG("Session %p created: target %p, tid %u, sid %#Lx",
++ session, target, target->tid, info->sid);
++
++ *result = session;
++ return 0;
++
++err:
++ if (session) {
++ kfree(session->initiator_name);
++ kfree(session);
++ }
++ return err;
++}
++
++/* target_mutex supposed to be locked */
++void sess_reinst_finished(struct iscsi_session *sess)
++{
++ struct iscsi_conn *c;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Enabling reinstate successor sess %p", sess);
++
++ BUG_ON(!sess->sess_reinstating);
++
++ list_for_each_entry(c, &sess->conn_list, conn_list_entry) {
++ conn_reinst_finished(c);
++ }
++ sess->sess_reinstating = 0;
++
++ TRACE_EXIT();
++ return;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++int __add_session(struct iscsi_target *target,
++ struct iscsi_kern_session_info *info)
++{
++ struct iscsi_session *new_sess = NULL, *sess, *old_sess;
++ int err = 0, i;
++ union iscsi_sid sid;
++ bool reinstatement = false;
++ struct iscsi_kern_params_info *params_info;
++
++ TRACE_MGMT_DBG("Adding session SID %llx", info->sid);
++
++ err = iscsi_session_alloc(target, info, &new_sess);
++ if (err != 0)
++ goto out;
++
++ mutex_lock(&target->target_mutex);
++
++ sess = session_lookup(target, info->sid);
++ if (sess != NULL) {
++ PRINT_ERROR("Attempt to add session with existing SID %llx",
++ info->sid);
++ err = -EEXIST;
++ goto out_err_unlock;
++ }
++
++ params_info = kmalloc(sizeof(*params_info), GFP_KERNEL);
++ if (params_info == NULL) {
++ PRINT_ERROR("Unable to allocate params info (size %zd)",
++ sizeof(*params_info));
++ err = -ENOMEM;
++ goto out_err_unlock;
++ }
++
++ sid = *(union iscsi_sid *)&info->sid;
++ sid.id.tsih = 0;
++ old_sess = NULL;
++
++ /*
++ * We need to find the latest session to correctly handle
++ * multi-reinstatements
++ */
++ list_for_each_entry_reverse(sess, &target->session_list,
++ session_list_entry) {
++ union iscsi_sid s = *(union iscsi_sid *)&sess->sid;
++ s.id.tsih = 0;
++ if ((sid.id64 == s.id64) &&
++ (strcmp(info->initiator_name, sess->initiator_name) == 0)) {
++ if (!sess->sess_shutting_down) {
++ /* session reinstatement */
++ old_sess = sess;
++ }
++ break;
++ }
++ }
++ sess = NULL;
++
++ list_add_tail(&new_sess->session_list_entry, &target->session_list);
++
++ memset(params_info, 0, sizeof(*params_info));
++ params_info->tid = target->tid;
++ params_info->sid = info->sid;
++ params_info->params_type = key_session;
++ for (i = 0; i < session_key_last; i++)
++ params_info->session_params[i] = info->session_params[i];
++
++ err = iscsi_params_set(target, params_info, 1);
++ if (err != 0)
++ goto out_del;
++
++ memset(params_info, 0, sizeof(*params_info));
++ params_info->tid = target->tid;
++ params_info->sid = info->sid;
++ params_info->params_type = key_target;
++ for (i = 0; i < target_key_last; i++)
++ params_info->target_params[i] = info->target_params[i];
++
++ err = iscsi_params_set(target, params_info, 1);
++ if (err != 0)
++ goto out_del;
++
++ kfree(params_info);
++ params_info = NULL;
++
++ if (old_sess != NULL) {
++ reinstatement = true;
++
++ TRACE_MGMT_DBG("Reinstating sess %p with SID %llx (old %p, "
++ "SID %llx)", new_sess, new_sess->sid, old_sess,
++ old_sess->sid);
++
++ new_sess->sess_reinstating = 1;
++ old_sess->sess_reinst_successor = new_sess;
++
++ target_del_session(old_sess->target, old_sess, 0);
++ }
++
++ mutex_unlock(&target->target_mutex);
++
++ if (reinstatement) {
++ /*
++ * Mutex target_mgmt_mutex won't allow to add connections to
++ * the new session after target_mutex was dropped, so it's safe
++ * to replace the initial UA without it. We can't do it under
++ * target_mutex, because otherwise we can establish a
++ * circular locking dependency between target_mutex and
++ * scst_mutex in SCST core (iscsi_report_aen() called by
++ * SCST core under scst_mutex).
++ */
++ scst_set_initial_UA(new_sess->scst_sess,
++ SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
++ }
++
++out:
++ return err;
++
++out_del:
++ list_del(&new_sess->session_list_entry);
++ kfree(params_info);
++
++out_err_unlock:
++ mutex_unlock(&target->target_mutex);
++
++ scst_unregister_session(new_sess->scst_sess, 1, NULL);
++ new_sess->scst_sess = NULL;
++
++ mutex_lock(&target->target_mutex);
++ session_free(new_sess, false);
++ mutex_unlock(&target->target_mutex);
++ goto out;
++}
++
++static void __session_free(struct iscsi_session *session)
++{
++ kfree(session->initiator_name);
++ kfree(session);
++}
++
++static void iscsi_unreg_sess_done(struct scst_session *scst_sess)
++{
++ struct iscsi_session *session;
++
++ TRACE_ENTRY();
++
++ session = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
++
++ session->scst_sess = NULL;
++ __session_free(session);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* target_mutex supposed to be locked */
++int session_free(struct iscsi_session *session, bool del)
++{
++ unsigned int i;
++
++ TRACE_MGMT_DBG("Freeing session %p (SID %llx)",
++ session, session->sid);
++
++ BUG_ON(!list_empty(&session->conn_list));
++ if (unlikely(atomic_read(&session->active_cmds) != 0)) {
++ PRINT_CRIT_ERROR("active_cmds not 0 (%d)!!",
++ atomic_read(&session->active_cmds));
++ BUG();
++ }
++
++ for (i = 0; i < ARRAY_SIZE(session->cmnd_data_wait_hash); i++)
++ BUG_ON(!list_empty(&session->cmnd_data_wait_hash[i]));
++
++ if (session->sess_reinst_successor != NULL)
++ sess_reinst_finished(session->sess_reinst_successor);
++
++ if (session->sess_reinstating) {
++ struct iscsi_session *s;
++ TRACE_MGMT_DBG("Freeing being reinstated sess %p", session);
++ list_for_each_entry(s, &session->target->session_list,
++ session_list_entry) {
++ if (s->sess_reinst_successor == session) {
++ s->sess_reinst_successor = NULL;
++ break;
++ }
++ }
++ }
++
++ if (del)
++ list_del(&session->session_list_entry);
++
++ if (session->scst_sess != NULL) {
++ /*
++ * We must NOT call scst_unregister_session() in the waiting
++ * mode, since we are under target_mutex. Otherwise we can
++ * establish a circular locking dependency between target_mutex
++ * and scst_mutex in SCST core (iscsi_report_aen() called by
++ * SCST core under scst_mutex).
++ */
++ scst_unregister_session(session->scst_sess, 0,
++ iscsi_unreg_sess_done);
++ } else
++ __session_free(session);
++
++ return 0;
++}
++
++/* target_mutex supposed to be locked */
++int __del_session(struct iscsi_target *target, u64 sid)
++{
++ struct iscsi_session *session;
++
++ session = session_lookup(target, sid);
++ if (!session)
++ return -ENOENT;
++
++ if (!list_empty(&session->conn_list)) {
++ PRINT_ERROR("%llx still have connections",
++ (long long unsigned int)session->sid);
++ return -EBUSY;
++ }
++
++ return session_free(session, true);
++}
++
++#define ISCSI_SESS_BOOL_PARAM_ATTR(name, exported_name) \
++static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
++ struct kobj_attribute *attr, char *buf) \
++{ \
++ int pos; \
++ struct scst_session *scst_sess; \
++ struct iscsi_session *sess; \
++ \
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
++ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
++ \
++ pos = sprintf(buf, "%s\n", \
++ iscsi_get_bool_value(sess->sess_params.name)); \
++ \
++ return pos; \
++} \
++ \
++static struct kobj_attribute iscsi_sess_attr_##name = \
++ __ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
++
++#define ISCSI_SESS_INT_PARAM_ATTR(name, exported_name) \
++static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
++ struct kobj_attribute *attr, char *buf) \
++{ \
++ int pos; \
++ struct scst_session *scst_sess; \
++ struct iscsi_session *sess; \
++ \
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
++ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
++ \
++ pos = sprintf(buf, "%d\n", sess->sess_params.name); \
++ \
++ return pos; \
++} \
++ \
++static struct kobj_attribute iscsi_sess_attr_##name = \
++ __ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
++
++#define ISCSI_SESS_DIGEST_PARAM_ATTR(name, exported_name) \
++static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
++ struct kobj_attribute *attr, char *buf) \
++{ \
++ int pos; \
++ struct scst_session *scst_sess; \
++ struct iscsi_session *sess; \
++ char digest_name[64]; \
++ \
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj); \
++ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess); \
++ \
++ pos = sprintf(buf, "%s\n", iscsi_get_digest_name( \
++ sess->sess_params.name, digest_name)); \
++ \
++ return pos; \
++} \
++ \
++static struct kobj_attribute iscsi_sess_attr_##name = \
++ __ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
++
++ISCSI_SESS_BOOL_PARAM_ATTR(initial_r2t, InitialR2T);
++ISCSI_SESS_BOOL_PARAM_ATTR(immediate_data, ImmediateData);
++ISCSI_SESS_INT_PARAM_ATTR(max_recv_data_length, MaxRecvDataSegmentLength);
++ISCSI_SESS_INT_PARAM_ATTR(max_xmit_data_length, MaxXmitDataSegmentLength);
++ISCSI_SESS_INT_PARAM_ATTR(max_burst_length, MaxBurstLength);
++ISCSI_SESS_INT_PARAM_ATTR(first_burst_length, FirstBurstLength);
++ISCSI_SESS_INT_PARAM_ATTR(max_outstanding_r2t, MaxOutstandingR2T);
++ISCSI_SESS_DIGEST_PARAM_ATTR(header_digest, HeaderDigest);
++ISCSI_SESS_DIGEST_PARAM_ATTR(data_digest, DataDigest);
++
++static ssize_t iscsi_sess_sid_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos;
++ struct scst_session *scst_sess;
++ struct iscsi_session *sess;
++
++ TRACE_ENTRY();
++
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
++ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
++
++ pos = sprintf(buf, "%llx\n", sess->sid);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static struct kobj_attribute iscsi_attr_sess_sid =
++ __ATTR(sid, S_IRUGO, iscsi_sess_sid_show, NULL);
++
++static ssize_t iscsi_sess_reinstating_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos;
++ struct scst_session *scst_sess;
++ struct iscsi_session *sess;
++
++ TRACE_ENTRY();
++
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
++ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
++
++ pos = sprintf(buf, "%d\n", sess->sess_reinstating ? 1 : 0);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static struct kobj_attribute iscsi_sess_attr_reinstating =
++ __ATTR(reinstating, S_IRUGO, iscsi_sess_reinstating_show, NULL);
++
++static ssize_t iscsi_sess_force_close_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buf, size_t count)
++{
++ int res;
++ struct scst_session *scst_sess;
++ struct iscsi_session *sess;
++ struct iscsi_conn *conn;
++
++ TRACE_ENTRY();
++
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
++ sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
++
++ if (mutex_lock_interruptible(&sess->target->target_mutex) != 0) {
++ res = -EINTR;
++ goto out;
++ }
++
++ PRINT_INFO("Deleting session %llx with initiator %s (%p)",
++ (long long unsigned int)sess->sid, sess->initiator_name, sess);
++
++ list_for_each_entry(conn, &sess->conn_list, conn_list_entry) {
++ TRACE_MGMT_DBG("Deleting connection with initiator %p", conn);
++ __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE|ISCSI_CONN_DELETING);
++ }
++
++ mutex_unlock(&sess->target->target_mutex);
++
++ res = count;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static struct kobj_attribute iscsi_sess_attr_force_close =
++ __ATTR(force_close, S_IWUSR, NULL, iscsi_sess_force_close_store);
++
++const struct attribute *iscsi_sess_attrs[] = {
++ &iscsi_sess_attr_initial_r2t.attr,
++ &iscsi_sess_attr_immediate_data.attr,
++ &iscsi_sess_attr_max_recv_data_length.attr,
++ &iscsi_sess_attr_max_xmit_data_length.attr,
++ &iscsi_sess_attr_max_burst_length.attr,
++ &iscsi_sess_attr_first_burst_length.attr,
++ &iscsi_sess_attr_max_outstanding_r2t.attr,
++ &iscsi_sess_attr_header_digest.attr,
++ &iscsi_sess_attr_data_digest.attr,
++ &iscsi_attr_sess_sid.attr,
++ &iscsi_sess_attr_reinstating.attr,
++ &iscsi_sess_attr_force_close.attr,
++ NULL,
++};
++
+diff -uprN orig/linux-2.6.36/drivers/scst/iscsi-scst/target.c linux-2.6.36/drivers/scst/iscsi-scst/target.c
+--- orig/linux-2.6.36/drivers/scst/iscsi-scst/target.c
++++ linux-2.6.36/drivers/scst/iscsi-scst/target.c
+@@ -0,0 +1,533 @@
++/*
++ * Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
++ * Copyright (C) 2007 - 2010 Vladislav Bolkhovitin
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/delay.h>
++
++#include "iscsi.h"
++#include "digest.h"
++
++#define MAX_NR_TARGETS (1UL << 30)
++
++DEFINE_MUTEX(target_mgmt_mutex);
++
++/* All 3 protected by target_mgmt_mutex */
++static LIST_HEAD(target_list);
++static u32 next_target_id;
++static u32 nr_targets;
++
++/* target_mgmt_mutex supposed to be locked */
++struct iscsi_target *target_lookup_by_id(u32 id)
++{
++ struct iscsi_target *target;
++
++ list_for_each_entry(target, &target_list, target_list_entry) {
++ if (target->tid == id)
++ return target;
++ }
++ return NULL;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static struct iscsi_target *target_lookup_by_name(const char *name)
++{
++ struct iscsi_target *target;
++
++ list_for_each_entry(target, &target_list, target_list_entry) {
++ if (!strcmp(target->name, name))
++ return target;
++ }
++ return NULL;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++static int iscsi_target_create(struct iscsi_kern_target_info *info, u32 tid,
++ struct iscsi_target **out_target)
++{
++ int err = -EINVAL, len;
++ char *name = info->name;
++ struct iscsi_target *target;
++
++ TRACE_MGMT_DBG("Creating target tid %u, name %s", tid, name);
++
++ len = strlen(name);
++ if (!len) {
++ PRINT_ERROR("The length of the target name is zero %u", tid);
++ goto out;
++ }
++
++ if (!try_module_get(THIS_MODULE)) {
++ PRINT_ERROR("Fail to get module %u", tid);
++ goto out;
++ }
++
++ target = kzalloc(sizeof(*target), GFP_KERNEL);
++ if (!target) {
++ err = -ENOMEM;
++ goto out_put;
++ }
++
++ target->tid = info->tid = tid;
++
++ strlcpy(target->name, name, sizeof(target->name));
++
++ mutex_init(&target->target_mutex);
++ INIT_LIST_HEAD(&target->session_list);
++ INIT_LIST_HEAD(&target->attrs_list);
++
++ target->scst_tgt = scst_register_target(&iscsi_template, target->name);
++ if (!target->scst_tgt) {
++ PRINT_ERROR("%s", "scst_register_target() failed");
++ err = -EBUSY;
++ goto out_free;
++ }
++
++ scst_tgt_set_tgt_priv(target->scst_tgt, target);
++
++ list_add_tail(&target->target_list_entry, &target_list);
++
++ *out_target = target;
++
++ return 0;
++
++out_free:
++ kfree(target);
++
++out_put:
++ module_put(THIS_MODULE);
++
++out:
++ return err;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++int __add_target(struct iscsi_kern_target_info *info)
++{
++ int err;
++ u32 tid = info->tid;
++ struct iscsi_target *target = NULL; /* to calm down sparse */
++ struct iscsi_kern_params_info *params_info;
++ struct iscsi_kern_attr *attr_info;
++ union add_info_union {
++ struct iscsi_kern_params_info params_info;
++ struct iscsi_kern_attr attr_info;
++ } *add_info;
++ int i, rc;
++ unsigned long attrs_ptr_long;
++ struct iscsi_kern_attr __user *attrs_ptr;
++
++ if (nr_targets > MAX_NR_TARGETS) {
++ err = -EBUSY;
++ goto out;
++ }
++
++ if (target_lookup_by_name(info->name)) {
++ PRINT_ERROR("Target %s already exist!", info->name);
++ err = -EEXIST;
++ goto out;
++ }
++
++ if (tid && target_lookup_by_id(tid)) {
++ PRINT_ERROR("Target %u already exist!", tid);
++ err = -EEXIST;
++ goto out;
++ }
++
++ add_info = kmalloc(sizeof(*add_info), GFP_KERNEL);
++ if (add_info == NULL) {
++ PRINT_ERROR("Unable to allocate additional info (size %zd)",
++ sizeof(*add_info));
++ err = -ENOMEM;
++ goto out;
++ }
++ params_info = (struct iscsi_kern_params_info *)add_info;
++ attr_info = (struct iscsi_kern_attr *)add_info;
++
++ if (tid == 0) {
++ do {
++ if (!++next_target_id)
++ ++next_target_id;
++ } while (target_lookup_by_id(next_target_id));
++
++ tid = next_target_id;
++ }
++
++ err = iscsi_target_create(info, tid, &target);
++ if (err != 0)
++ goto out_free;
++
++ nr_targets++;
++
++ mutex_lock(&target->target_mutex);
++
++ attrs_ptr_long = info->attrs_ptr;
++ attrs_ptr = (struct iscsi_kern_attr __user *)attrs_ptr_long;
++ for (i = 0; i < info->attrs_num; i++) {
++ memset(attr_info, 0, sizeof(*attr_info));
++
++ rc = copy_from_user(attr_info, attrs_ptr, sizeof(*attr_info));
++ if (rc != 0) {
++ PRINT_ERROR("Failed to copy users of target %s "
++ "failed", info->name);
++ err = -EFAULT;
++ goto out_del_unlock;
++ }
++
++ attr_info->name[sizeof(attr_info->name)-1] = '\0';
++
++ err = iscsi_add_attr(target, attr_info);
++ if (err != 0)
++ goto out_del_unlock;
++
++ attrs_ptr++;
++ }
++
++ mutex_unlock(&target->target_mutex);
++
++ err = tid;
++
++out_free:
++ kfree(add_info);
++
++out:
++ return err;
++
++out_del_unlock:
++ mutex_unlock(&target->target_mutex);
++ __del_target(tid);
++ goto out_free;
++}
++
++static void target_destroy(struct iscsi_target *target)
++{
++ struct iscsi_attr *attr, *t;
++
++ TRACE_MGMT_DBG("Destroying target tid %u", target->tid);
++
++ list_for_each_entry_safe(attr, t, &target->attrs_list,
++ attrs_list_entry) {
++ __iscsi_del_attr(target, attr);
++ }
++
++ scst_unregister_target(target->scst_tgt);
++
++ kfree(target);
++
++ module_put(THIS_MODULE);
++ return;
++}
++
++/* target_mgmt_mutex supposed to be locked */
++int __del_target(u32 id)
++{
++ struct iscsi_target *target;
++ int err;
++
++ target = target_lookup_by_id(id);
++ if (!target) {
++ err = -ENOENT;
++ goto out;
++ }
++
++ mutex_lock(&target->target_mutex);
++
++ if (!list_empty(&target->session_list)) {
++ err = -EBUSY;
++ goto out_unlock;
++ }
++
++ list_del(&target->target_list_entry);
++ nr_targets--;
++
++ mutex_unlock(&target->target_mutex);
++
++ target_destroy(target);
++ return 0;
++
++out_unlock:
++ mutex_unlock(&target->target_mutex);
++
++out:
++ return err;
++}
++
++/* target_mutex supposed to be locked */
++void target_del_session(struct iscsi_target *target,
++ struct iscsi_session *session, int flags)
++{
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Deleting session %p", session);
++
++ if (!list_empty(&session->conn_list)) {
++ struct iscsi_conn *conn, *tc;
++ list_for_each_entry_safe(conn, tc, &session->conn_list,
++ conn_list_entry) {
++ TRACE_MGMT_DBG("Mark conn %p closing", conn);
++ __mark_conn_closed(conn, flags);
++ }
++ } else {
++ TRACE_MGMT_DBG("Freeing session %p without connections",
++ session);
++ __del_session(target, session->sid);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* target_mutex supposed to be locked */
++void target_del_all_sess(struct iscsi_target *target, int flags)
++{
++ struct iscsi_session *session, *ts;
++
++ TRACE_ENTRY();
++
++ if (!list_empty(&target->session_list)) {
++ TRACE_MGMT_DBG("Deleting all sessions from target %p", target);
++ list_for_each_entry_safe(session, ts, &target->session_list,
++ session_list_entry) {
++ target_del_session(target, session, flags);
++ }
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++void target_del_all(void)
++{
++ struct iscsi_target *target, *t;
++ bool first = true;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("%s", "Deleting all targets");
++
++ /* Not the best, ToDo */
++ while (1) {
++ mutex_lock(&target_mgmt_mutex);
++
++ if (list_empty(&target_list))
++ break;
++
++ /*
++ * In the first iteration we won't delete targets to go at
++ * first through all sessions of all targets and close their
++ * connections. Otherwise we can stuck for noticeable time
++ * waiting during a target's unregistration for the activities
++ * suspending over active connection. This can especially got
++ * bad if any being wait connection itself stuck waiting for
++ * something and can be recovered only by connection close.
++ * Let's for such cases not wait while such connection recover
++ * theyself, but act in advance.
++ */
++
++ list_for_each_entry_safe(target, t, &target_list,
++ target_list_entry) {
++ mutex_lock(&target->target_mutex);
++
++ if (!list_empty(&target->session_list)) {
++ target_del_all_sess(target,
++ ISCSI_CONN_ACTIVE_CLOSE |
++ ISCSI_CONN_DELETING);
++ } else if (!first) {
++ TRACE_MGMT_DBG("Deleting target %p", target);
++ list_del(&target->target_list_entry);
++ nr_targets--;
++ mutex_unlock(&target->target_mutex);
++ target_destroy(target);
++ continue;
++ }
++
++ mutex_unlock(&target->target_mutex);
++ }
++ mutex_unlock(&target_mgmt_mutex);
++ msleep(100);
++
++ first = false;
++ }
++
++ mutex_unlock(&target_mgmt_mutex);
++
++ TRACE_MGMT_DBG("%s", "Deleting all targets finished");
++
++ TRACE_EXIT();
++ return;
++}
++
++static ssize_t iscsi_tgt_tid_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ int pos;
++ struct scst_tgt *scst_tgt;
++ struct iscsi_target *tgt;
++
++ TRACE_ENTRY();
++
++ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ tgt = (struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt);
++
++ pos = sprintf(buf, "%u\n", tgt->tid);
++
++ TRACE_EXIT_RES(pos);
++ return pos;
++}
++
++static struct kobj_attribute iscsi_tgt_attr_tid =
++ __ATTR(tid, S_IRUGO, iscsi_tgt_tid_show, NULL);
++
++const struct attribute *iscsi_tgt_attrs[] = {
++ &iscsi_tgt_attr_tid.attr,
++ NULL,
++};
++
++ssize_t iscsi_sysfs_send_event(uint32_t tid, enum iscsi_kern_event_code code,
++ const char *param1, const char *param2, void **data)
++{
++ int res;
++ struct scst_sysfs_user_info *info;
++
++ TRACE_ENTRY();
++
++ if (ctr_open_state != ISCSI_CTR_OPEN_STATE_OPEN) {
++ PRINT_ERROR("%s", "User space process not connected");
++ res = -EPERM;
++ goto out;
++ }
++
++ res = scst_sysfs_user_add_info(&info);
++ if (res != 0)
++ goto out;
++
++ TRACE_DBG("Sending event %d (tid %d, param1 %s, param2 %s, cookie %d, "
++ "info %p)", tid, code, param1, param2, info->info_cookie, info);
++
++ res = event_send(tid, 0, 0, info->info_cookie, code, param1, param2);
++ if (res <= 0) {
++ PRINT_ERROR("event_send() failed: %d", res);
++ if (res == 0)
++ res = -EFAULT;
++ goto out_free;
++ }
++
++ /*
++ * It may wait 30 secs in blocking connect to an unreacheable
++ * iSNS server. It must be fixed, but not now. ToDo.
++ */
++ res = scst_wait_info_completion(info, 31 * HZ);
++
++ if (data != NULL)
++ *data = info->data;
++
++out_free:
++ scst_sysfs_user_del_info(info);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++int iscsi_enable_target(struct scst_tgt *scst_tgt, bool enable)
++{
++ struct iscsi_target *tgt =
++ (struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt);
++ int res;
++ uint32_t type;
++
++ TRACE_ENTRY();
++
++ if (enable)
++ type = E_ENABLE_TARGET;
++ else
++ type = E_DISABLE_TARGET;
++
++ TRACE_DBG("%s target %d", enable ? "Enabling" : "Disabling", tgt->tid);
++
++ res = iscsi_sysfs_send_event(tgt->tid, type, NULL, NULL, NULL);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++bool iscsi_is_target_enabled(struct scst_tgt *scst_tgt)
++{
++ struct iscsi_target *tgt =
++ (struct iscsi_target *)scst_tgt_get_tgt_priv(scst_tgt);
++
++ return tgt->tgt_enabled;
++}
++
++ssize_t iscsi_sysfs_add_target(const char *target_name, char *params)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ res = iscsi_sysfs_send_event(0, E_ADD_TARGET, target_name,
++ params, NULL);
++ if (res > 0) {
++ /* It's tid */
++ res = 0;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++ssize_t iscsi_sysfs_del_target(const char *target_name)
++{
++ int res = 0, tid;
++
++ TRACE_ENTRY();
++
++ /* We don't want to have tgt visible after the mutex unlock */
++ {
++ struct iscsi_target *tgt;
++ mutex_lock(&target_mgmt_mutex);
++ tgt = target_lookup_by_name(target_name);
++ if (tgt == NULL) {
++ PRINT_ERROR("Target %s not found", target_name);
++ mutex_unlock(&target_mgmt_mutex);
++ res = -ENOENT;
++ goto out;
++ }
++ tid = tgt->tid;
++ mutex_unlock(&target_mgmt_mutex);
++ }
++
++ TRACE_DBG("Deleting target %s (tid %d)", target_name, tid);
++
++ res = iscsi_sysfs_send_event(tid, E_DEL_TARGET, NULL, NULL, NULL);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++ssize_t iscsi_sysfs_mgmt_cmd(char *cmd)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending mgmt cmd %s", cmd);
++
++ res = iscsi_sysfs_send_event(0, E_MGMT_CMD, cmd, NULL, NULL);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
+diff -uprN orig/linux-2.6.36/Documentation/scst/README.iscsi linux-2.6.36/Documentation/scst/README.iscsi
+--- orig/linux-2.6.36/Documentation/scst/README.iscsi
++++ linux-2.6.36/Documentation/scst/README.iscsi
+@@ -0,0 +1,741 @@
++iSCSI SCST target driver
++========================
++
++ISCSI-SCST is a deeply reworked fork of iSCSI Enterprise Target (IET)
++(http://iscsitarget.sourceforge.net). Reasons of the fork were:
++
++ - To be able to use full power of SCST core.
++
++ - To fix all the problems, corner cases issues and iSCSI standard
++ violations which IET has.
++
++See for more info http://iscsi-scst.sourceforge.net.
++
++Usage
++-----
++
++See in http://iscsi-scst.sourceforge.net/iscsi-scst-howto.txt how to
++configure iSCSI-SCST.
++
++If you want to use Intel CRC32 offload and have corresponding hardware,
++you should load crc32c-intel module. Then iSCSI-SCST will do all digest
++calculations using this facility.
++
++In 2.0.0 usage of iscsi-scstd.conf as well as iscsi-scst-adm utility is
++obsolete. Use the sysfs interface facilities instead.
++
++The flow of iSCSI-SCST inialization should be as the following:
++
++1. Load of SCST and iSCSI-SCST kernel modules with necessary module
++parameters, if needed.
++
++2. Start iSCSI-SCST service.
++
++3. Configure targets, devices, LUNs, etc. either using scstadmin
++(recommended), or using the sysfs interface directly as described below.
++
++It is recommended to use TEST UNIT READY ("tur") command to check if
++iSCSI-SCST target is alive in MPIO configurations.
++
++Also see SCST README file how to tune for the best performance.
++
++CAUTION: Working of target and initiator on the same host isn't fully
++======= supported. See SCST README file for details.
++
++Sysfs interface
++---------------
++
++Root of SCST sysfs interface is /sys/kernel/scst_tgt. Root of iSCSI-SCST
++is /sys/kernel/scst_tgt/targets/iscsi. It has the following entries:
++
++ - None, one or more subdirectories for targets with name equal to names
++ of the corresponding targets.
++
++ - IncomingUser[num] - optional one or more attributes containing user
++ name and password for incoming discovery user name. Not exist by
++ default and can be added through "mgmt" entry, see below.
++
++ - OutgoingUser - optional attribute containing user name and password
++ for outgoing discovery user name. Not exist by default and can be
++ added through "mgmt" entry, see below.
++
++ - iSNSServer - contains name or IP address of iSNS server with optional
++ "AccessControl" attribute, which allows to enable iSNS access
++ control. Empty by default.
++
++ - allowed_portal[num] - optional attribute, which specifies, on which
++ portals (target's IP addresses) this target will be available. If not
++ specified (default) the target will be available on all all portals.
++ As soon as at least one allowed_portal specified, the target will be
++ accessible for initiators only on the specified portals. There might
++ be any number of the allowed_portal attributes. The portals
++ specification in the allowed_portal attributes can be a simple
++ DOS-type patterns, containing '*' and '?' symbols. '*' means match
++ all any symbols, '?' means match only any single symbol. For
++ instance, "10.170.77.2" will match "10.170.7?.*". Additionally, you
++ can use negative sign '!' to revert the value of the pattern. For
++ instance, "10.170.67.2" will match "!10.170.7?.*". See examples
++ below.
++
++ - enabled - using this attribute you can enable or disable iSCSI-SCST
++ accept new connections. It allows to finish configuring global
++ iSCSI-SCST attributes before it starts accepting new connections. 0
++ by default.
++
++ - open_state - read-only attribute, which allows to see if the user
++ space part of iSCSI-SCST connected to the kernel part.
++
++ - per_portal_acl - if set, makes iSCSI-SCST work in the per-portal
++ access control mode. In this mode iSCSI-SCST registers all initiators
++ in SCST core as "initiator_name#portal_IP_address" pattern, like
++ "iqn.2006-10.net.vlnb:ini#10.170.77.2" for initiator
++ iqn.2006-10.net.vlnb connected through portal 10.170.77.2. This mode
++ allows to make particular initiators be able to use only particular
++ portals on the target and don't see/be able to connect through
++ others. See below for more details.
++
++ - trace_level - allows to enable and disable various tracing
++ facilities. See content of this file for help how to use it.
++
++ - version - read-only attribute, which allows to see version of
++ iSCSI-SCST and enabled optional features.
++
++ - mgmt - main management entry, which allows to configure iSCSI-SCST.
++ Namely, add/delete targets as well as add/delete optional global and
++ per-target attributes. See content of this file for help how to use
++ it.
++
++Each iSCSI-SCST sysfs file (attribute) can contain in the last line mark
++"[key]". It is automatically added mark used to allow scstadmin to see
++which attributes it should save in the config file. You can ignore it.
++
++Each target subdirectory contains the following entries:
++
++ - ini_groups - subdirectory defining initiator groups for this target,
++ used to define per-initiator access control. See SCST core README for
++ more details.
++
++ - luns - subdirectory defining LUNs of this target. See SCST core
++ README for more details.
++
++ - sessions - subdirectory containing connected to this target sessions.
++
++ - IncomingUser[num] - optional one or more attributes containing user
++ name and password for incoming user name. Not exist by default and can
++ be added through the "mgmt" entry, see above.
++
++ - OutgoingUser - optional attribute containing user name and password
++ for outgoing user name. Not exist by default and can be added through
++ the "mgmt" entry, see above.
++
++ - Entries defining default iSCSI parameters values used during iSCSI
++ parameters negotiation. Only entries which can be changed or make
++ sense are listed there.
++
++ - QueuedCommands - defines maximum number of commands queued to any
++ session of this target. Default is 32 commands.
++
++ - RspTimeout - defines the maximum time in seconds a command can wait for
++ response from initiator, otherwise the corresponding connection will
++ be closed. For performance reasons it is implemented as a timer,
++ which once in RspTimeout time checks the oldest command waiting for
++ response and, if it's older than RspTimeout, then it closes the
++ connection. Hence, a stalled connection will be closed in time
++ between RspTimeout and 2*RspTimeout. Default is 30 seconds.
++
++ - NopInInterval - defines interval between NOP-In requests, which the
++ target will send on idle connections to check if the initiator is
++ still alive. If there is no NOP-Out reply from the initiator in
++ RspTimeout time, the corresponding connection will be closed. Default
++ is 30 seconds. If it's set to 0, then NOP-In requests are disabled.
++
++ - enabled - using this attribute you can enable or disable iSCSI-SCST
++ accept new connections to this target. It allows to finish
++ configuring it before it starts accepting new connections. 0 by
++ default.
++
++ - rel_tgt_id - allows to read or write SCSI Relative Target Port
++ Identifier attribute. This identifier is used to identify SCSI Target
++ Ports by some SCSI commands, mainly by Persistent Reservations
++ commands. This identifier must be unique among all SCST targets, but
++ for convenience SCST allows disabled targets to have not unique
++ rel_tgt_id. In this case SCST will not allow to enable this target
++ until rel_tgt_id becomes unique. This attribute initialized unique by
++ SCST by default.
++
++ - redirect - allows to temporarily or permanently redirect login to the
++ target to another portal. Discovery sessions will not be impacted,
++ but normal sessions will be redirected before security negotiation.
++ The destination should be specified using format "<ip_addr>[:port] temp|perm".
++ IPv6 addresses need to be enclosed in [] brackets. To remove
++ redirection, provide an empty string. For example:
++ echo "10.170.77.2:32600 temp" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/redirect
++ will temporarily redirect login to portal 10.170.77.2 and port 32600.
++
++ - tid - TID of this target.
++
++Subdirectory "sessions" contains one subdirectory for each connected
++session with name equal to name of the connected initiator.
++
++Each session subdirectory contains the following entries:
++
++ - One subdirectory for each TCP connection in this session. ISCSI-SCST
++ supports 1 connection per session, but the session subdirectory can
++ contain several connections: one active and other being closed.
++
++ - Entries defining negotiated iSCSI parameters. Only parameters which
++ can be changed or make sense are listed there.
++
++ - initiator_name - contains initiator name
++
++ - sid - contains SID of this session
++
++ - reinstating - contains reinstatement state of this session
++
++ - force_close - write-only attribute, which allows to force close this
++ session. This is the only writable session attribute.
++
++ - active_commands - contains number of active, i.e. not yet or being
++ executed, SCSI commands in this session.
++
++ - commands - contains overall number of SCSI commands in this session.
++
++Each connection subdirectory contains the following entries:
++
++ - cid - contains CID of this connection.
++
++ - ip - contains IP address of the connected initiator.
++
++ - state - contains processing state of this connection.
++
++Below is a sample script, which configures 1 virtual disk "disk1" using
++/disk1 image and one target iqn.2006-10.net.vlnb:tgt with all default
++parameters:
++
++#!/bin/bash
++
++modprobe scst
++modprobe scst_vdisk
++
++echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
++
++service iscsi-scst start
++
++echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
++
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
++
++Below is another sample script, which configures 1 real local SCSI disk
++0:0:1:0 and one target iqn.2006-10.net.vlnb:tgt with all default parameters:
++
++#!/bin/bash
++
++modprobe scst
++modprobe scst_disk
++
++echo "add_device 0:0:1:0" >/sys/kernel/scst_tgt/handlers/dev_disk/mgmt
++
++service iscsi-scst start
++
++echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo "add 0:0:1:0 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
++
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
++
++Below is an advanced sample script, which configures more virtual
++devices of various types, including virtual CDROM and 2 targets, one
++with all default parameters, another one with some not default
++parameters, incoming and outgoing user names for CHAP authentification,
++and special permissions for initiator iqn.2005-03.org.open-iscsi:cacdcd2520,
++which will see another set of devices. Also this sample configures CHAP
++authentication for discovery sessions and iSNS server with access
++control.
++
++#!/bin/bash
++
++modprobe scst
++modprobe scst_vdisk
++
++echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
++echo "add_device disk2 filename=/disk2; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
++echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
++echo "add_device nullio" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
++echo "add_device cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
++
++service iscsi-scst start
++
++echo "192.168.1.16 AccessControl" >/sys/kernel/scst_tgt/targets/iscsi/iSNSServer
++echo "add_attribute IncomingUser joeD 12charsecret" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo "add_attribute OutgoingUser jackD 12charsecret1" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++
++echo "add_target iqn.2006-10.net.vlnb:tgt" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++
++echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
++echo "add cdrom 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
++
++echo "add_target iqn.2006-10.net.vlnb:tgt1" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 IncomingUser1 joe2 12charsecret2" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 IncomingUser joe 12charsecret" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo "add_target_attribute iqn.2006-10.net.vlnb:tgt1 OutgoingUser jim1 12charpasswd" >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo "No" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/InitialR2T
++echo "Yes" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ImmediateData
++echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxRecvDataSegmentLength
++echo "8192" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxXmitDataSegmentLength
++echo "131072" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxBurstLength
++echo "32768" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/FirstBurstLength
++echo "1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/MaxOutstandingR2T
++echo "CRC32C,None" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/HeaderDigest
++echo "CRC32C,None" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/DataDigest
++echo "32" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/QueuedCommands
++
++echo "add disk2 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/mgmt
++echo "add nullio 26" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/mgmt
++
++echo "create special_ini" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/mgmt
++echo "add blockio 0 read_only=1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/special_ini/luns/mgmt
++echo "add iqn.2005-03.org.open-iscsi:cacdcd2520" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/special_ini/initiators/mgmt
++
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/enabled
++
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/enabled
++
++The resulting overall SCST sysfs hierarchy with an initiator connected to
++both iSCSI-SCST targets will look like:
++
++/sys/kernel/scst_tgt
++|-- devices
++| |-- blockio
++| | |-- blocksize
++| | |-- exported
++| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/special_ini/luns/0
++| | |-- filename
++| | |-- handler -> ../../handlers/vdisk_blockio
++| | |-- nv_cache
++| | |-- read_only
++| | |-- removable
++| | |-- resync_size
++| | |-- size_mb
++| | |-- t10_dev_id
++| | |-- threads_num
++| | |-- threads_pool_type
++| | |-- type
++| | `-- usn
++| |-- cdrom
++| | |-- exported
++| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/1
++| | |-- filename
++| | |-- handler -> ../../handlers/vcdrom
++| | |-- size_mb
++| | |-- t10_dev_id
++| | |-- threads_num
++| | |-- threads_pool_type
++| | |-- type
++| | `-- usn
++| |-- disk1
++| | |-- blocksize
++| | |-- exported
++| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0
++| | |-- filename
++| | |-- handler -> ../../handlers/vdisk_fileio
++| | |-- nv_cache
++| | |-- o_direct
++| | |-- read_only
++| | |-- removable
++| | |-- resync_size
++| | |-- size_mb
++| | |-- t10_dev_id
++| | |-- type
++| | |-- usn
++| | `-- write_through
++| |-- disk2
++| | |-- blocksize
++| | |-- exported
++| | | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0
++| | |-- filename
++| | |-- handler -> ../../handlers/vdisk_fileio
++| | |-- nv_cache
++| | |-- o_direct
++| | |-- read_only
++| | |-- removable
++| | |-- resync_size
++| | |-- size_mb
++| | |-- t10_dev_id
++| | |-- threads_num
++| | |-- threads_pool_type
++| | |-- threads_num
++| | |-- threads_pool_type
++| | |-- type
++| | |-- usn
++| | `-- write_through
++| `-- nullio
++| |-- blocksize
++| |-- exported
++| | `-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/26
++| |-- handler -> ../../handlers/vdisk_nullio
++| |-- read_only
++| |-- removable
++| |-- size_mb
++| |-- t10_dev_id
++| |-- threads_num
++| |-- threads_pool_type
++| |-- type
++| `-- usn
++|-- handlers
++| |-- vcdrom
++| | |-- cdrom -> ../../devices/cdrom
++| | |-- mgmt
++| | |-- trace_level
++| | `-- type
++| |-- vdisk_blockio
++| | |-- blockio -> ../../devices/blockio
++| | |-- mgmt
++| | |-- trace_level
++| | `-- type
++| |-- vdisk_fileio
++| | |-- disk1 -> ../../devices/disk1
++| | |-- disk2 -> ../../devices/disk2
++| | |-- mgmt
++| | |-- trace_level
++| | `-- type
++| `-- vdisk_nullio
++| |-- mgmt
++| |-- nullio -> ../../devices/nullio
++| |-- trace_level
++| `-- type
++|-- sgv
++| |-- global_stats
++| |-- sgv
++| | `-- stats
++| |-- sgv-clust
++| | `-- stats
++| `-- sgv-dma
++| `-- stats
++|-- targets
++| `-- iscsi
++| |-- IncomingUser
++| |-- OutgoingUser
++| |-- enabled
++| |-- iSNSServer
++| |-- iqn.2006-10.net.vlnb:tgt
++| | |-- DataDigest
++| | |-- FirstBurstLength
++| | |-- HeaderDigest
++| | |-- ImmediateData
++| | |-- InitialR2T
++| | |-- MaxBurstLength
++| | |-- MaxOutstandingR2T
++| | |-- MaxRecvDataSegmentLength
++| | |-- MaxXmitDataSegmentLength
++| | |-- NopInInterval
++| | |-- QueuedCommands
++| | |-- RspTimeout
++| | |-- enabled
++| | |-- ini_groups
++| | | `-- mgmt
++| | |-- luns
++| | | |-- 0
++| | | | |-- device -> ../../../../../devices/disk1
++| | | | `-- read_only
++| | | |-- 1
++| | | | |-- device -> ../../../../../devices/cdrom
++| | | | `-- read_only
++| | | `-- mgmt
++| | |-- per_portal_acl
++| | |-- redirect
++| | |-- rel_tgt_id
++| | |-- sessions
++| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
++| | | |-- 10.170.75.2
++| | | | |-- cid
++| | | | |-- ip
++| | | | `-- state
++| | | |-- DataDigest
++| | | |-- FirstBurstLength
++| | | |-- HeaderDigest
++| | | |-- ImmediateData
++| | | |-- InitialR2T
++| | | |-- MaxBurstLength
++| | | |-- MaxOutstandingR2T
++| | | |-- MaxRecvDataSegmentLength
++| | | |-- MaxXmitDataSegmentLength
++| | | |-- active_commands
++| | | |-- commands
++| | | |-- force_close
++| | | |-- initiator_name
++| | | |-- luns -> ../../luns
++| | | |-- reinstating
++| | | `-- sid
++| | `-- tid
++| |-- iqn.2006-10.net.vlnb:tgt1
++| | |-- DataDigest
++| | |-- FirstBurstLength
++| | |-- HeaderDigest
++| | |-- ImmediateData
++| | |-- IncomingUser
++| | |-- IncomingUser1
++| | |-- InitialR2T
++| | |-- MaxBurstLength
++| | |-- MaxOutstandingR2T
++| | |-- MaxRecvDataSegmentLength
++| | |-- MaxXmitDataSegmentLength
++| | |-- OutgoingUser
++| | |-- NopInInterval
++| | |-- QueuedCommands
++| | |-- RspTimeout
++| | |-- enabled
++| | |-- ini_groups
++| | | |-- mgmt
++| | | `-- special_ini
++| | | |-- initiators
++| | | | |-- iqn.2005-03.org.open-iscsi:cacdcd2520
++| | | | `-- mgmt
++| | | `-- luns
++| | | |-- 0
++| | | | |-- device -> ../../../../../../../devices/blockio
++| | | | `-- read_only
++| | | `-- mgmt
++| | |-- luns
++| | | |-- 0
++| | | | |-- device -> ../../../../../devices/disk2
++| | | | `-- read_only
++| | | |-- 26
++| | | | |-- device -> ../../../../../devices/nullio
++| | | | `-- read_only
++| | | `-- mgmt
++| | |-- per_portal_acl
++| | |-- redirect
++| | |-- rel_tgt_id
++| | |-- sessions
++| | | `-- iqn.2005-03.org.open-iscsi:cacdcd2520
++| | | |-- 10.170.75.2
++| | | | |-- cid
++| | | | |-- ip
++| | | | `-- state
++| | | |-- DataDigest
++| | | |-- FirstBurstLength
++| | | |-- HeaderDigest
++| | | |-- ImmediateData
++| | | |-- InitialR2T
++| | | |-- MaxBurstLength
++| | | |-- MaxOutstandingR2T
++| | | |-- MaxRecvDataSegmentLength
++| | | |-- MaxXmitDataSegmentLength
++| | | |-- active_commands
++| | | |-- commands
++| | | |-- force_close
++| | | |-- initiator_name
++| | | |-- luns -> ../../ini_groups/special_ini/luns
++| | | |-- reinstating
++| | | `-- sid
++| | `-- tid
++| |-- mgmt
++| |-- open_state
++| |-- trace_level
++| `-- version
++|-- threads
++|-- trace_level
++`-- version
++
++Advanced initiators access control
++----------------------------------
++
++ISCSI-SCST allows you to optionally control visibility and accessibility
++of your target and its portals (IP addresses) to remote initiators. This
++control includes both the target's portals SendTargets discovery as well
++as regular LUNs access.
++
++This facility supersedes the obsolete initiators.[allow,deny] method,
++which is going to be removed in one of the future versions.
++
++This facility is available only in the sysfs build of iSCSI-SCST.
++
++By default, all portals are available for the initiators.
++
++1. If you want to enable/disable one or more target's portals for all
++initiators, you should define one ore more allowed_portal attributes.
++For example:
++
++echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal 10.170.77.2' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++
++will enable only portal 10.170.77.2 and disable all other portals
++
++echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal 10.170.77.2' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal 10.170.75.2' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++
++will enable only portals 10.170.77.2 and 10.170.75.2 and disable all
++other portals.
++
++echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal 10.170.7?.2' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++
++will enable only portals 10.170.7x.2 and disable all other portals.
++
++echo 'add_target_attribute iqn.2006-10.net.vlnb:tgt allowed_portal !*' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++
++will disable all portals.
++
++2. If you want to want to allow only only specific set of initiators be
++able to connect to your target, you should don't add any default LUNs
++for the target and create for allowed initiators a security group to
++which they will be assigned.
++
++For example, we want initiator iqn.2005-03.org.vlnb:cacdcd2520 and only
++it be able to access target iqn.2006-10.net.vlnb:tgt:
++
++echo 'add_target iqn.2006-10.net.vlnb:tgt' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo 'create allowed_ini' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/mgmt
++echo 'add dev1 0' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/allowed_ini/luns/mgmt
++echo 'add iqn.2005-03.org.vlnb:cacdcd2520' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/allowed_ini/initiators/mgmt
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
++
++Since there will be no default LUNs for the target, all initiators other
++than iqn.2005-03.org.vlnb:cacdcd2520 will be blocked from accessing it.
++
++Alternatively, you can create an empty security group and filter out in
++it all initiators except the allowed one:
++
++echo 'add_target iqn.2006-10.net.vlnb:tgt' >/sys/kernel/scst_tgt/targets/iscsi/mgmt
++echo 'add dev1 0' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/mgmt
++echo 'create denied_inis' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/mgmt
++echo 'add !iqn.2005-03.org.vlnb:cacdcd2520' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/denied_inis/initiators/mgmt
++echo 1 >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/enabled
++
++3. If you want to enable/disable one or more target's portals for
++particular initiators, you should set per_portal_acl attribute to 1 and
++specify SCST access control to those initiators. If an SCST security
++group doesn't have any LUNs, all the initiator, which should be assigned
++to it, will not see this target and/or its portal. For example:
++
++(We assume that an empty group "BLOCKING_GROUP" is already created by for
++target iqn.2006-10.net.vlnb:tgt by command (see above for more information):
++"echo 'create BLOCKING_GROUP' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/mgmt)
++
++echo 'add iqn.2005-03.org.vlnb:cacdcd2520#10.170.77.2' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/BLOCKING_GROUP/initiators/mgmt
++
++will block access of initiator iqn.2005-03.org.vlnb:cacdcd2520 to
++target iqn.2006-10.net.vlnb:tgt portal 10.170.77.2.
++
++Another example:
++
++echo 'add iqn.2005-03.org.vlnb:cacdcd2520*' >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/BLOCKING_GROUP/initiators/mgmt
++
++will block access of initiator iqn.2005-03.org.vlnb:cacdcd2520 to
++all target iqn.2006-10.net.vlnb:tgt portals.
++
++Troubleshooting
++---------------
++
++If you have any problems, start troubleshooting from looking at the
++kernel and system logs. In the kernel log iSCSI-SCST and SCST core send
++their messages, in the system log iscsi-scstd sends its messages. In
++most Linux distributions both those logs are put to /var/log/messages
++file.
++
++Then, it might be helpful to increase level of logging. For kernel
++modules you should make the debug build by enabling CONFIG_SCST_DEBUG.
++
++If after looking on the logs the reason of your problem is still unclear
++for you, report to SCST mailing list scst-devel@lists.sourceforge.net.
++
++Work if target's backstorage or link is too slow
++------------------------------------------------
++
++In some cases you can experience I/O stalls or see in the kernel log
++abort or reset messages. It can happen under high I/O load, when your
++target's backstorage gets overloaded, or working over a slow link, when
++the link can't serve all the queued commands on time,
++
++To workaround it you can reduce QueuedCommands parameter for the
++corresponding target to some lower value, like 8 (default is 32).
++
++Also see SCST README file for more details about that issue and ways to
++prevent it.
++
++Performance advices
++-------------------
++
++1. If you use Windows XP or Windows 2003+ as initiators, you can
++consider to decrease TcpAckFrequency parameter to 1. See
++http://support.microsoft.com/kb/328890/ or google for "TcpAckFrequency"
++for more details.
++
++2. See how to get the maximum throughput from iSCSI, for instance, at
++http://virtualgeek.typepad.com/virtual_geek/2009/01/a-multivendor-post-to-help-our-mutual-iscsi-customers-using-vmware.html.
++It's about VMware, but its recommendations apply to other environments
++as well.
++
++3. ISCSI initiators built in pre-CentOS/RHEL 5 reported to have some
++performance problems. If you use it, it is strongly advised to upgrade.
++
++4. If you are going to use your target in an VM environment, for
++instance as a shared storage with VMware, make sure all your VMs
++connected to the target via *separate* sessions, i.e. each VM has own
++connection to the target, not all VMs connected using a single
++connection. You can check it using SCST sysfs interface. If you
++miss it, you can greatly loose performance of parallel access to your
++target from different VMs. This isn't related to the case if your VMs
++are using the same shared storage, like with VMFS, for instance. In this
++case all your VM hosts will be connected to the target via separate
++sessions, which is enough.
++
++5. Many dual port network adapters are not able to transfer data
++simultaneously on both ports, i.e. they transfer data via both ports on
++the same speed as via any single port. Thus, using such adapters in MPIO
++configuration can't improve performance. To allow MPIO to have double
++performance you should either use separate network adapters, or find a
++dual-port adapter capable to to transfer data simultaneously on both
++ports. You can check it by running 2 iperf's through both ports in
++parallel.
++
++6. Since network offload works much better in the write direction, than
++for reading (simplifying, in the read direction often there's additional
++data copy) in many cases with 10GbE in a single initiator-target pair
++the initiator's CPU is a bottleneck, so you can see the initiator can
++read data on much slower rate, than write. You can check it by watching
++*each particular* CPU load to find out if any of them is close to 100%
++load, including IRQ processing load. Note, many tools like vmstat give
++aggregate load on all CPUs, so with 4 cores 25% corresponds to 100% load
++of any single CPU.
++
++7. See SCST core's README for more advices. Especially pay attention to
++have io_grouping_type option set correctly.
++
++Compilation options
++-------------------
++
++There are the following compilation options, that could be commented
++in/out in the kernel's module Makefile:
++
++ - CONFIG_SCST_DEBUG - turns on some debugging code, including some logging.
++ Makes the driver considerably bigger and slower, producing large amount of
++ log data.
++
++ - CONFIG_SCST_TRACING - turns on ability to log events. Makes the driver
++ considerably bigger and leads to some performance loss.
++
++ - CONFIG_SCST_EXTRACHECKS - adds extra validity checks in the various places.
++
++ - CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES - simulates digest failures in
++ random places.
++
++Credits
++-------
++
++Thanks to:
++
++ * Ming Zhang <blackmagic02881@gmail.com> for fixes
++
++ * Krzysztof Blaszkowski <kb@sysmikro.com.pl> for many fixes
++
++ * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> for comments and help in
++ debugging
++
++ * Tomasz Chmielewski <mangoo@wpkg.org> for testing and suggestions
++
++ * Bart Van Assche <bart.vanassche@gmail.com> for a lot of help
++
++Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
++
+diff -uprN orig/linux-2.6.36/drivers/scsi/qla2xxx/qla2x_tgt.h linux-2.6.36/drivers/scsi/qla2xxx/qla2x_tgt.h
+--- orig/linux-2.6.36/drivers/scsi/qla2xxx/qla2x_tgt.h
++++ linux-2.6.36/drivers/scsi/qla2xxx/qla2x_tgt.h
+@@ -0,0 +1,131 @@
++/*
++ * qla2x_tgt.h
++ *
++ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * Additional file for the target driver support.
++ *
++ * 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.
++ */
++/*
++ * This should be included only from within qla2xxx module.
++ */
++
++#ifndef __QLA2X_TGT_H
++#define __QLA2X_TGT_H
++
++extern request_t *qla2x00_req_pkt(scsi_qla_host_t *ha);
++
++#ifdef CONFIG_SCSI_QLA2XXX_TARGET
++
++#include "qla2x_tgt_def.h"
++
++extern struct qla_tgt_data qla_target;
++
++void qla_set_tgt_mode(scsi_qla_host_t *ha);
++void qla_clear_tgt_mode(scsi_qla_host_t *ha);
++
++static inline bool qla_tgt_mode_enabled(scsi_qla_host_t *ha)
++{
++ return ha->host->active_mode & MODE_TARGET;
++}
++
++static inline bool qla_ini_mode_enabled(scsi_qla_host_t *ha)
++{
++ return ha->host->active_mode & MODE_INITIATOR;
++}
++
++static inline void qla_reverse_ini_mode(scsi_qla_host_t *ha)
++{
++ if (ha->host->active_mode & MODE_INITIATOR)
++ ha->host->active_mode &= ~MODE_INITIATOR;
++ else
++ ha->host->active_mode |= MODE_INITIATOR;
++}
++
++/********************************************************************\
++ * ISP Queue types left out of new QLogic driver (from old version)
++\********************************************************************/
++
++/*
++ * qla2x00_do_en_dis_lun
++ * Issue enable or disable LUN entry IOCB.
++ *
++ * Input:
++ * ha = adapter block pointer.
++ *
++ * Caller MUST have hardware lock held. This function might release it,
++ * then reaquire.
++ */
++static inline void
++__qla2x00_send_enable_lun(scsi_qla_host_t *ha, int enable)
++{
++ elun_entry_t *pkt;
++
++ BUG_ON(IS_FWI2_CAPABLE(ha));
++
++ pkt = (elun_entry_t *)qla2x00_req_pkt(ha);
++ if (pkt != NULL) {
++ pkt->entry_type = ENABLE_LUN_TYPE;
++ if (enable) {
++ pkt->command_count = QLA2X00_COMMAND_COUNT_INIT;
++ pkt->immed_notify_count = QLA2X00_IMMED_NOTIFY_COUNT_INIT;
++ pkt->timeout = 0xffff;
++ } else {
++ pkt->command_count = 0;
++ pkt->immed_notify_count = 0;
++ pkt->timeout = 0;
++ }
++ DEBUG2(printk(KERN_DEBUG
++ "scsi%lu:ENABLE_LUN IOCB imm %u cmd %u timeout %u\n",
++ ha->host_no, pkt->immed_notify_count,
++ pkt->command_count, pkt->timeout));
++
++ /* Issue command to ISP */
++ qla2x00_isp_cmd(ha);
++
++ } else
++ qla_clear_tgt_mode(ha);
++#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
++ if (!pkt)
++ printk(KERN_ERR "%s: **** FAILED ****\n", __func__);
++#endif
++
++ return;
++}
++
++/*
++ * qla2x00_send_enable_lun
++ * Issue enable LUN entry IOCB.
++ *
++ * Input:
++ * ha = adapter block pointer.
++ * enable = enable/disable flag.
++ */
++static inline void
++qla2x00_send_enable_lun(scsi_qla_host_t *ha, bool enable)
++{
++ if (!IS_FWI2_CAPABLE(ha)) {
++ unsigned long flags;
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ __qla2x00_send_enable_lun(ha, enable);
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ }
++}
++
++extern void qla2xxx_add_targets(void);
++
++#endif /* CONFIG_SCSI_QLA2XXX_TARGET */
++
++#endif /* __QLA2X_TGT_H */
+diff -uprN orig/linux-2.6.36/drivers/scsi/qla2xxx/qla2x_tgt_def.h linux-2.6.36/drivers/scsi/qla2xxx/qla2x_tgt_def.h
+--- orig/linux-2.6.36/drivers/scsi/qla2xxx/qla2x_tgt_def.h
++++ linux-2.6.36/drivers/scsi/qla2xxx/qla2x_tgt_def.h
+@@ -0,0 +1,729 @@
++/*
++ * qla2x_tgt_def.h
++ *
++ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
++ * Copyright (C) 2007 - 2010 ID7 Ltd.
++ *
++ * Additional file for the target driver support.
++ *
++ * 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.
++ */
++/*
++ * This is the global def file that is useful for including from the
++ * target portion.
++ */
++
++#ifndef __QLA2X_TGT_DEF_H
++#define __QLA2X_TGT_DEF_H
++
++#include "qla_def.h"
++
++#ifndef CONFIG_SCSI_QLA2XXX_TARGET
++#error __FILE__ " included without CONFIG_SCSI_QLA2XXX_TARGET"
++#endif
++
++#ifndef ENTER
++#define ENTER(a)
++#endif
++
++#ifndef LEAVE
++#define LEAVE(a)
++#endif
++
++/*
++ * Must be changed on any change in any initiator visible interfaces or
++ * data in the target add-on
++ */
++#define QLA2X_TARGET_MAGIC 267
++
++/*
++ * Must be changed on any change in any target visible interfaces or
++ * data in the initiator
++ */
++#define QLA2X_INITIATOR_MAGIC 57319
++
++#define QLA2X_INI_MODE_STR_EXCLUSIVE "exclusive"
++#define QLA2X_INI_MODE_STR_DISABLED "disabled"
++#define QLA2X_INI_MODE_STR_ENABLED "enabled"
++
++#define QLA2X_INI_MODE_EXCLUSIVE 0
++#define QLA2X_INI_MODE_DISABLED 1
++#define QLA2X_INI_MODE_ENABLED 2
++
++#define QLA2X00_COMMAND_COUNT_INIT 250
++#define QLA2X00_IMMED_NOTIFY_COUNT_INIT 250
++
++/*
++ * Used to mark which completion handles (for RIO Status's) are for CTIO's
++ * vs. regular (non-target) info. This is checked for in
++ * qla2x00_process_response_queue() to see if a handle coming back in a
++ * multi-complete should come to the tgt driver or be handled there by qla2xxx
++ */
++#define CTIO_COMPLETION_HANDLE_MARK BIT_29
++#if (CTIO_COMPLETION_HANDLE_MARK <= MAX_OUTSTANDING_COMMANDS)
++#error "Hackish CTIO_COMPLETION_HANDLE_MARK no longer larger than MAX_OUTSTANDING_COMMANDS"
++#endif
++#define HANDLE_IS_CTIO_COMP(h) (h & CTIO_COMPLETION_HANDLE_MARK)
++
++/* Used to mark CTIO as intermediate */
++#define CTIO_INTERMEDIATE_HANDLE_MARK BIT_30
++
++#ifndef OF_SS_MODE_0
++/*
++ * ISP target entries - Flags bit definitions.
++ */
++#define OF_SS_MODE_0 0
++#define OF_SS_MODE_1 1
++#define OF_SS_MODE_2 2
++#define OF_SS_MODE_3 3
++
++#define OF_EXPL_CONF BIT_5 /* Explicit Confirmation Requested */
++#define OF_DATA_IN BIT_6 /* Data in to initiator */
++ /* (data from target to initiator) */
++#define OF_DATA_OUT BIT_7 /* Data out from initiator */
++ /* (data from initiator to target) */
++#define OF_NO_DATA (BIT_7 | BIT_6)
++#define OF_INC_RC BIT_8 /* Increment command resource count */
++#define OF_FAST_POST BIT_9 /* Enable mailbox fast posting. */
++#define OF_CONF_REQ BIT_13 /* Confirmation Requested */
++#define OF_TERM_EXCH BIT_14 /* Terminate exchange */
++#define OF_SSTS BIT_15 /* Send SCSI status */
++#endif
++
++#ifndef DATASEGS_PER_COMMAND32
++#define DATASEGS_PER_COMMAND32 3
++#define DATASEGS_PER_CONT32 7
++#define QLA_MAX_SG32(ql) \
++ (((ql) > 0) ? (DATASEGS_PER_COMMAND32 + DATASEGS_PER_CONT32*((ql) - 1)) : 0)
++
++#define DATASEGS_PER_COMMAND64 2
++#define DATASEGS_PER_CONT64 5
++#define QLA_MAX_SG64(ql) \
++ (((ql) > 0) ? (DATASEGS_PER_COMMAND64 + DATASEGS_PER_CONT64*((ql) - 1)) : 0)
++#endif
++
++#ifndef DATASEGS_PER_COMMAND_24XX
++#define DATASEGS_PER_COMMAND_24XX 1
++#define DATASEGS_PER_CONT_24XX 5
++#define QLA_MAX_SG_24XX(ql) \
++ (min(1270, ((ql) > 0) ? (DATASEGS_PER_COMMAND_24XX + DATASEGS_PER_CONT_24XX*((ql) - 1)) : 0))
++#endif
++
++/********************************************************************\
++ * ISP Queue types left out of new QLogic driver (from old version)
++\********************************************************************/
++
++#ifndef ENABLE_LUN_TYPE
++#define ENABLE_LUN_TYPE 0x0B /* Enable LUN entry. */
++/*
++ * ISP queue - enable LUN entry structure definition.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t sys_define_2; /* System defined. */
++ uint8_t reserved_8;
++ uint8_t reserved_1;
++ uint16_t reserved_2;
++ uint32_t reserved_3;
++ uint8_t status;
++ uint8_t reserved_4;
++ uint8_t command_count; /* Number of ATIOs allocated. */
++ uint8_t immed_notify_count; /* Number of Immediate Notify entries allocated. */
++ uint16_t reserved_5;
++ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
++ uint16_t reserved_6[20];
++} __attribute__((packed)) elun_entry_t;
++#define ENABLE_LUN_SUCCESS 0x01
++#define ENABLE_LUN_RC_NONZERO 0x04
++#define ENABLE_LUN_INVALID_REQUEST 0x06
++#define ENABLE_LUN_ALREADY_ENABLED 0x3E
++#endif
++
++#ifndef MODIFY_LUN_TYPE
++#define MODIFY_LUN_TYPE 0x0C /* Modify LUN entry. */
++/*
++ * ISP queue - modify LUN entry structure definition.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t sys_define_2; /* System defined. */
++ uint8_t reserved_8;
++ uint8_t reserved_1;
++ uint8_t operators;
++ uint8_t reserved_2;
++ uint32_t reserved_3;
++ uint8_t status;
++ uint8_t reserved_4;
++ uint8_t command_count; /* Number of ATIOs allocated. */
++ uint8_t immed_notify_count; /* Number of Immediate Notify */
++ /* entries allocated. */
++ uint16_t reserved_5;
++ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
++ uint16_t reserved_7[20];
++} __attribute__((packed)) modify_lun_entry_t;
++#define MODIFY_LUN_SUCCESS 0x01
++#define MODIFY_LUN_CMD_ADD BIT_0
++#define MODIFY_LUN_CMD_SUB BIT_1
++#define MODIFY_LUN_IMM_ADD BIT_2
++#define MODIFY_LUN_IMM_SUB BIT_3
++#endif
++
++#define GET_TARGET_ID(ha, iocb) ((HAS_EXTENDED_IDS(ha)) \
++ ? le16_to_cpu((iocb)->target.extended) \
++ : (uint16_t)(iocb)->target.id.standard)
++
++#ifndef IMMED_NOTIFY_TYPE
++#define IMMED_NOTIFY_TYPE 0x0D /* Immediate notify entry. */
++/*
++ * ISP queue - immediate notify entry structure definition.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t sys_define_2; /* System defined. */
++ target_id_t target;
++ uint16_t lun;
++ uint8_t target_id;
++ uint8_t reserved_1;
++ uint16_t status_modifier;
++ uint16_t status;
++ uint16_t task_flags;
++ uint16_t seq_id;
++ uint16_t srr_rx_id;
++ uint32_t srr_rel_offs;
++ uint16_t srr_ui;
++#define SRR_IU_DATA_IN 0x1
++#define SRR_IU_DATA_OUT 0x5
++#define SRR_IU_STATUS 0x7
++ uint16_t srr_ox_id;
++ uint8_t reserved_2[30];
++ uint16_t ox_id;
++} __attribute__((packed)) notify_entry_t;
++#endif
++
++#ifndef NOTIFY_ACK_TYPE
++#define NOTIFY_ACK_TYPE 0x0E /* Notify acknowledge entry. */
++/*
++ * ISP queue - notify acknowledge entry structure definition.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t sys_define_2; /* System defined. */
++ target_id_t target;
++ uint8_t target_id;
++ uint8_t reserved_1;
++ uint16_t flags;
++ uint16_t resp_code;
++ uint16_t status;
++ uint16_t task_flags;
++ uint16_t seq_id;
++ uint16_t srr_rx_id;
++ uint32_t srr_rel_offs;
++ uint16_t srr_ui;
++ uint16_t srr_flags;
++ uint16_t srr_reject_code;
++ uint8_t srr_reject_vendor_uniq;
++ uint8_t srr_reject_code_expl;
++ uint8_t reserved_2[26];
++ uint16_t ox_id;
++} __attribute__((packed)) nack_entry_t;
++#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
++#define NOTIFY_ACK_SRR_FLAGS_REJECT 1
++
++#define NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM 0x9
++
++#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL 0
++#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_UNABLE_TO_SUPPLY_DATA 0x2a
++
++#define NOTIFY_ACK_SUCCESS 0x01
++#endif
++
++#ifndef ACCEPT_TGT_IO_TYPE
++#define ACCEPT_TGT_IO_TYPE 0x16 /* Accept target I/O entry. */
++/*
++ * ISP queue - Accept Target I/O (ATIO) entry structure definition.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t sys_define_2; /* System defined. */
++ target_id_t target;
++ uint16_t rx_id;
++ uint16_t flags;
++ uint16_t status;
++ uint8_t command_ref;
++ uint8_t task_codes;
++ uint8_t task_flags;
++ uint8_t execution_codes;
++ uint8_t cdb[MAX_CMDSZ];
++ uint32_t data_length;
++ uint16_t lun;
++ uint8_t initiator_port_name[WWN_SIZE]; /* on qla23xx */
++ uint16_t reserved_32[6];
++ uint16_t ox_id;
++} __attribute__((packed)) atio_entry_t;
++#endif
++
++#ifndef CONTINUE_TGT_IO_TYPE
++#define CONTINUE_TGT_IO_TYPE 0x17
++/*
++ * ISP queue - Continue Target I/O (CTIO) entry for status mode 0
++ * structure definition.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t handle; /* System defined handle */
++ target_id_t target;
++ uint16_t rx_id;
++ uint16_t flags;
++ uint16_t status;
++ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
++ uint16_t dseg_count; /* Data segment count. */
++ uint32_t relative_offset;
++ uint32_t residual;
++ uint16_t reserved_1[3];
++ uint16_t scsi_status;
++ uint32_t transfer_length;
++ uint32_t dseg_0_address[0];
++} __attribute__((packed)) ctio_common_entry_t;
++#define ATIO_PATH_INVALID 0x07
++#define ATIO_CANT_PROV_CAP 0x16
++#define ATIO_CDB_VALID 0x3D
++
++#define ATIO_EXEC_READ BIT_1
++#define ATIO_EXEC_WRITE BIT_0
++#endif
++
++#ifndef CTIO_A64_TYPE
++#define CTIO_A64_TYPE 0x1F
++typedef struct {
++ ctio_common_entry_t common;
++ uint32_t dseg_0_address; /* Data segment 0 address. */
++ uint32_t dseg_0_length; /* Data segment 0 length. */
++ uint32_t dseg_1_address; /* Data segment 1 address. */
++ uint32_t dseg_1_length; /* Data segment 1 length. */
++ uint32_t dseg_2_address; /* Data segment 2 address. */
++ uint32_t dseg_2_length; /* Data segment 2 length. */
++} __attribute__((packed)) ctio_entry_t;
++#define CTIO_SUCCESS 0x01
++#define CTIO_ABORTED 0x02
++#define CTIO_INVALID_RX_ID 0x08
++#define CTIO_TIMEOUT 0x0B
++#define CTIO_LIP_RESET 0x0E
++#define CTIO_TARGET_RESET 0x17
++#define CTIO_PORT_UNAVAILABLE 0x28
++#define CTIO_PORT_LOGGED_OUT 0x29
++#define CTIO_PORT_CONF_CHANGED 0x2A
++#define CTIO_SRR_RECEIVED 0x45
++
++#endif
++
++#ifndef CTIO_RET_TYPE
++#define CTIO_RET_TYPE 0x17 /* CTIO return entry */
++/*
++ * ISP queue - CTIO returned entry structure definition.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t handle; /* System defined handle. */
++ target_id_t target;
++ uint16_t rx_id;
++ uint16_t flags;
++ uint16_t status;
++ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
++ uint16_t dseg_count; /* Data segment count. */
++ uint32_t relative_offset;
++ uint32_t residual;
++ uint16_t reserved_1[2];
++ uint16_t sense_length;
++ uint16_t scsi_status;
++ uint16_t response_length;
++ uint8_t sense_data[26];
++} __attribute__((packed)) ctio_ret_entry_t;
++#endif
++
++#define ATIO_TYPE7 0x06 /* Accept target I/O entry for 24xx */
++
++typedef struct {
++ uint8_t r_ctl;
++ uint8_t d_id[3];
++ uint8_t cs_ctl;
++ uint8_t s_id[3];
++ uint8_t type;
++ uint8_t f_ctl[3];
++ uint8_t seq_id;
++ uint8_t df_ctl;
++ uint16_t seq_cnt;
++ uint16_t ox_id;
++ uint16_t rx_id;
++ uint32_t parameter;
++} __attribute__((packed)) fcp_hdr_t;
++
++typedef struct {
++ uint8_t d_id[3];
++ uint8_t r_ctl;
++ uint8_t s_id[3];
++ uint8_t cs_ctl;
++ uint8_t f_ctl[3];
++ uint8_t type;
++ uint16_t seq_cnt;
++ uint8_t df_ctl;
++ uint8_t seq_id;
++ uint16_t rx_id;
++ uint16_t ox_id;
++ uint32_t parameter;
++} __attribute__((packed)) fcp_hdr_le_t;
++
++#define F_CTL_EXCH_CONTEXT_RESP BIT_23
++#define F_CTL_SEQ_CONTEXT_RESIP BIT_22
++#define F_CTL_LAST_SEQ BIT_20
++#define F_CTL_END_SEQ BIT_19
++#define F_CTL_SEQ_INITIATIVE BIT_16
++
++#define R_CTL_BASIC_LINK_SERV 0x80
++#define R_CTL_B_ACC 0x4
++#define R_CTL_B_RJT 0x5
++
++typedef struct {
++ uint64_t lun;
++ uint8_t cmnd_ref;
++ uint8_t task_attr:3;
++ uint8_t reserved:5;
++ uint8_t task_mgmt_flags;
++#define FCP_CMND_TASK_MGMT_CLEAR_ACA 6
++#define FCP_CMND_TASK_MGMT_TARGET_RESET 5
++#define FCP_CMND_TASK_MGMT_LU_RESET 4
++#define FCP_CMND_TASK_MGMT_CLEAR_TASK_SET 2
++#define FCP_CMND_TASK_MGMT_ABORT_TASK_SET 1
++ uint8_t wrdata:1;
++ uint8_t rddata:1;
++ uint8_t add_cdb_len:6;
++ uint8_t cdb[16];
++ /* Valid only if add_cdb_len=0, otherwise this is additional CDB data */
++ uint32_t data_length;
++} __attribute__((packed)) fcp_cmnd_t;
++
++/*
++ * ISP queue - Accept Target I/O (ATIO) type 7 entry for 24xx structure
++ * definition.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t fcp_cmnd_len_low;
++ uint8_t fcp_cmnd_len_high:4;
++ uint8_t attr:4;
++ uint32_t exchange_addr;
++#define ATIO_EXCHANGE_ADDRESS_UNKNOWN 0xFFFFFFFF
++ fcp_hdr_t fcp_hdr;
++ fcp_cmnd_t fcp_cmnd;
++} __attribute__((packed)) atio7_entry_t;
++
++#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
++
++/*
++ * ISP queue - Continue Target I/O (ATIO) type 7 entry (for 24xx) structure
++ * definition.
++ */
++
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t handle; /* System defined handle */
++ uint16_t nport_handle;
++#define CTIO7_NHANDLE_UNRECOGNIZED 0xFFFF
++ uint16_t timeout;
++ uint16_t dseg_count; /* Data segment count. */
++ uint8_t vp_index;
++ uint8_t add_flags;
++ uint8_t initiator_id[3];
++ uint8_t reserved;
++ uint32_t exchange_addr;
++} __attribute__((packed)) ctio7_common_entry_t;
++
++typedef struct {
++ ctio7_common_entry_t common;
++ uint16_t reserved1;
++ uint16_t flags;
++ uint32_t residual;
++ uint16_t ox_id;
++ uint16_t scsi_status;
++ uint32_t relative_offset;
++ uint32_t reserved2;
++ uint32_t transfer_length;
++ uint32_t reserved3;
++ uint32_t dseg_0_address[2]; /* Data segment 0 address. */
++ uint32_t dseg_0_length; /* Data segment 0 length. */
++} __attribute__((packed)) ctio7_status0_entry_t;
++
++typedef struct {
++ ctio7_common_entry_t common;
++ uint16_t sense_length;
++ uint16_t flags;
++ uint32_t residual;
++ uint16_t ox_id;
++ uint16_t scsi_status;
++ uint16_t response_len;
++ uint16_t reserved;
++ uint8_t sense_data[24];
++} __attribute__((packed)) ctio7_status1_entry_t;
++
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t handle; /* System defined handle */
++ uint16_t status;
++ uint16_t timeout;
++ uint16_t dseg_count; /* Data segment count. */
++ uint8_t reserved1[6];
++ uint32_t exchange_address;
++ uint16_t reserved2;
++ uint16_t flags;
++ uint32_t residual;
++ uint16_t ox_id;
++ uint16_t reserved3;
++ uint32_t relative_offset;
++ uint8_t reserved4[24];
++} __attribute__((packed)) ctio7_fw_entry_t;
++
++/* CTIO7 flags values */
++#define CTIO7_FLAGS_SEND_STATUS BIT_15
++#define CTIO7_FLAGS_TERMINATE BIT_14
++#define CTIO7_FLAGS_CONFORM_REQ BIT_13
++#define CTIO7_FLAGS_DONT_RET_CTIO BIT_8
++#define CTIO7_FLAGS_STATUS_MODE_0 0
++#define CTIO7_FLAGS_STATUS_MODE_1 BIT_6
++#define CTIO7_FLAGS_EXPLICIT_CONFORM BIT_5
++#define CTIO7_FLAGS_CONFIRM_SATISF BIT_4
++#define CTIO7_FLAGS_DSD_PTR BIT_2
++#define CTIO7_FLAGS_DATA_IN BIT_1
++#define CTIO7_FLAGS_DATA_OUT BIT_0
++
++/*
++ * ISP queue - immediate notify entry structure definition for 24xx.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t reserved;
++ uint16_t nport_handle;
++ uint16_t reserved_2;
++ uint16_t flags;
++#define NOTIFY24XX_FLAGS_GLOBAL_TPRLO BIT_1
++#define NOTIFY24XX_FLAGS_PUREX_IOCB BIT_0
++ uint16_t srr_rx_id;
++ uint16_t status;
++ uint8_t status_subcode;
++ uint8_t reserved_3;
++ uint32_t exchange_address;
++ uint32_t srr_rel_offs;
++ uint16_t srr_ui;
++ uint16_t srr_ox_id;
++ uint8_t reserved_4[19];
++ uint8_t vp_index;
++ uint32_t reserved_5;
++ uint8_t port_id[3];
++ uint8_t reserved_6;
++ uint16_t reserved_7;
++ uint16_t ox_id;
++} __attribute__((packed)) notify24xx_entry_t;
++
++#define ELS_PLOGI 0x3
++#define ELS_FLOGI 0x4
++#define ELS_LOGO 0x5
++#define ELS_PRLI 0x20
++#define ELS_PRLO 0x21
++#define ELS_TPRLO 0x24
++#define ELS_PDISC 0x50
++#define ELS_ADISC 0x52
++
++/*
++ * ISP queue - notify acknowledge entry structure definition for 24xx.
++ */
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t handle;
++ uint16_t nport_handle;
++ uint16_t reserved_1;
++ uint16_t flags;
++ uint16_t srr_rx_id;
++ uint16_t status;
++ uint8_t status_subcode;
++ uint8_t reserved_3;
++ uint32_t exchange_address;
++ uint32_t srr_rel_offs;
++ uint16_t srr_ui;
++ uint16_t srr_flags;
++ uint8_t reserved_4[19];
++ uint8_t vp_index;
++ uint8_t srr_reject_vendor_uniq;
++ uint8_t srr_reject_code_expl;
++ uint8_t srr_reject_code;
++ uint8_t reserved_5[7];
++ uint16_t ox_id;
++} __attribute__((packed)) nack24xx_entry_t;
++
++/*
++ * ISP queue - ABTS received/response entries structure definition for 24xx.
++ */
++#define ABTS_RECV_24XX 0x54 /* ABTS received (for 24xx) */
++#define ABTS_RESP_24XX 0x55 /* ABTS responce (for 24xx) */
++
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint8_t reserved_1[6];
++ uint16_t nport_handle;
++ uint8_t reserved_2[3];
++ uint8_t reserved_3:4;
++ uint8_t sof_type:4;
++ uint32_t exchange_address;
++ fcp_hdr_le_t fcp_hdr_le;
++ uint8_t reserved_4[16];
++ uint32_t exchange_addr_to_abort;
++} __attribute__((packed)) abts24_recv_entry_t;
++
++#define ABTS_PARAM_ABORT_SEQ BIT_0
++
++typedef struct {
++ uint16_t reserved;
++ uint8_t seq_id_last;
++ uint8_t seq_id_valid;
++#define SEQ_ID_VALID 0x80
++#define SEQ_ID_INVALID 0x00
++ uint16_t rx_id;
++ uint16_t ox_id;
++ uint16_t high_seq_cnt;
++ uint16_t low_seq_cnt;
++} __attribute__((packed)) ba_acc_le_t;
++
++typedef struct {
++ uint8_t vendor_uniq;
++ uint8_t reason_expl;
++ uint8_t reason_code;
++#define BA_RJT_REASON_CODE_INVALID_COMMAND 0x1
++#define BA_RJT_REASON_CODE_UNABLE_TO_PERFORM 0x9
++ uint8_t reserved;
++} __attribute__((packed)) ba_rjt_le_t;
++
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t handle;
++ uint16_t reserved_1;
++ uint16_t nport_handle;
++ uint16_t control_flags;
++#define ABTS_CONTR_FLG_TERM_EXCHG BIT_0
++ uint8_t reserved_2;
++ uint8_t reserved_3:4;
++ uint8_t sof_type:4;
++ uint32_t exchange_address;
++ fcp_hdr_le_t fcp_hdr_le;
++ union {
++ ba_acc_le_t ba_acct;
++ ba_rjt_le_t ba_rjt;
++ } __attribute__((packed)) payload;
++ uint32_t reserved_4;
++ uint32_t exchange_addr_to_abort;
++} __attribute__((packed)) abts24_resp_entry_t;
++
++typedef struct {
++ uint8_t entry_type; /* Entry type. */
++ uint8_t entry_count; /* Entry count. */
++ uint8_t sys_define; /* System defined. */
++ uint8_t entry_status; /* Entry Status. */
++ uint32_t handle;
++ uint16_t compl_status;
++#define ABTS_RESP_COMPL_SUCCESS 0
++#define ABTS_RESP_COMPL_SUBCODE_ERROR 0x31
++ uint16_t nport_handle;
++ uint16_t reserved_1;
++ uint8_t reserved_2;
++ uint8_t reserved_3:4;
++ uint8_t sof_type:4;
++ uint32_t exchange_address;
++ fcp_hdr_le_t fcp_hdr_le;
++ uint8_t reserved_4[8];
++ uint32_t error_subcode1;
++#define ABTS_RESP_SUBCODE_ERR_ABORTED_EXCH_NOT_TERM 0x1E
++ uint32_t error_subcode2;
++ uint32_t exchange_addr_to_abort;
++} __attribute__((packed)) abts24_resp_fw_entry_t;
++
++/********************************************************************\
++ * Type Definitions used by initiator & target halves
++\********************************************************************/
++
++typedef enum {
++ ADD_TARGET = 0,
++ REMOVE_TARGET,
++ DISABLE_TARGET_MODE,
++ ENABLE_TARGET_MODE,
++} qla2x_tgt_host_action_t;
++
++/* Changing it don't forget to change QLA2X_TARGET_MAGIC! */
++struct qla_tgt_data {
++ int magic;
++
++ /* Callbacks */
++ void (*tgt24_atio_pkt)(scsi_qla_host_t *ha, atio7_entry_t *pkt);
++ void (*tgt_response_pkt)(scsi_qla_host_t *ha, response_t *pkt);
++ void (*tgt2x_ctio_completion)(scsi_qla_host_t *ha, uint32_t handle);
++ void (*tgt_async_event)(uint16_t code, scsi_qla_host_t *ha,
++ uint16_t *mailbox);
++ int (*tgt_host_action)(scsi_qla_host_t *ha, qla2x_tgt_host_action_t
++ action);
++ void (*tgt_fc_port_added)(scsi_qla_host_t *ha, fc_port_t *fcport);
++ void (*tgt_fc_port_deleted)(scsi_qla_host_t *ha, fc_port_t *fcport);
++};
++
++int qla2xxx_tgt_register_driver(struct qla_tgt_data *tgt);
++
++void qla2xxx_tgt_unregister_driver(void);
++
++int qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha);
++int qla2x00_wait_for_hba_online(scsi_qla_host_t *ha);
++
++#endif /* __QLA2X_TGT_DEF_H */
+diff -uprN orig/linux-2.6.36/drivers/scst/qla2xxx-target/Makefile linux-2.6.36/drivers/scst/qla2xxx-target/Makefile
+--- orig/linux-2.6.36/drivers/scst/qla2xxx-target/Makefile
++++ linux-2.6.36/drivers/scst/qla2xxx-target/Makefile
+@@ -0,0 +1,5 @@
++ccflags-y += -Idrivers/scsi/qla2xxx
++
++qla2x00tgt-y := qla2x00t.o
++
++obj-$(CONFIG_SCST_QLA_TGT_ADDON) += qla2x00tgt.o
+diff -uprN orig/linux-2.6.36/drivers/scst/qla2xxx-target/Kconfig linux-2.6.36/drivers/scst/qla2xxx-target/Kconfig
+--- orig/linux-2.6.36/drivers/scst/qla2xxx-target/Kconfig
++++ linux-2.6.36/drivers/scst/qla2xxx-target/Kconfig
+@@ -0,0 +1,30 @@
++config SCST_QLA_TGT_ADDON
++ tristate "QLogic 2XXX Target Mode Add-On"
++ depends on SCST && SCSI_QLA_FC && SCSI_QLA2XXX_TARGET
++ default SCST
++ help
++ Target mode add-on driver for QLogic 2xxx Fibre Channel host adapters.
++ Visit http://scst.sourceforge.net for more info about this driver.
++
++config QLA_TGT_DEBUG_WORK_IN_THREAD
++ bool "Use threads context only"
++ depends on SCST_QLA_TGT_ADDON
++ help
++ Makes SCST process incoming commands from the qla2x00t target
++ driver and call the driver's callbacks in internal SCST
++ threads context instead of SIRQ context, where thise commands
++ were received. Useful for debugging and lead to some
++ performance loss.
++
++ If unsure, say "N".
++
++config QLA_TGT_DEBUG_SRR
++ bool "SRR debugging"
++ depends on SCST_QLA_TGT_ADDON
++ help
++ Turns on retransmitting packets (SRR)
++ debugging. In this mode some CTIOs will be "broken" to force the
++ initiator to issue a retransmit request. Useful for debugging and lead to big
++ performance loss.
++
++ If unsure, say "N".
+diff -uprN orig/linux-2.6.36/drivers/scst/qla2xxx-target/qla2x00t.c linux-2.6.36/drivers/scst/qla2xxx-target/qla2x00t.c
+--- orig/linux-2.6.36/drivers/scst/qla2xxx-target/qla2x00t.c
++++ linux-2.6.36/drivers/scst/qla2xxx-target/qla2x00t.c
+@@ -0,0 +1,5486 @@
++/*
++ * qla2x00t.c
++ *
++ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
++ * Copyright (C) 2006 - 2010 ID7 Ltd.
++ *
++ * QLogic 22xx/23xx/24xx/25xx FC target driver.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/version.h>
++#include <linux/blkdev.h>
++#include <linux/interrupt.h>
++#include <scsi/scsi.h>
++#include <scsi/scsi_host.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/list.h>
++
++#include <scst/scst.h>
++
++#include "qla2x00t.h"
++
++/*
++ * This driver calls qla2x00_req_pkt() and qla2x00_issue_marker(), which
++ * must be called under HW lock and could unlock/lock it inside.
++ * It isn't an issue, since in the current implementation on the time when
++ * those functions are called:
++ *
++ * - Either context is IRQ and only IRQ handler can modify HW data,
++ * including rings related fields,
++ *
++ * - Or access to target mode variables from struct q2t_tgt doesn't
++ * cross those functions boundaries, except tgt_stop, which
++ * additionally protected by irq_cmd_count.
++ */
++
++#ifndef CONFIG_SCSI_QLA2XXX_TARGET
++#error "CONFIG_SCSI_QLA2XXX_TARGET is NOT DEFINED"
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++#define Q2T_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_LINE | TRACE_PID | \
++ TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_DEBUG | \
++ TRACE_MINOR | TRACE_SPECIAL)
++#else
++# ifdef CONFIG_SCST_TRACING
++#define Q2T_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
++ TRACE_SPECIAL)
++# endif
++#endif
++
++static int q2t_target_detect(struct scst_tgt_template *templ);
++static int q2t_target_release(struct scst_tgt *scst_tgt);
++static int q2x_xmit_response(struct scst_cmd *scst_cmd);
++static int __q24_xmit_response(struct q2t_cmd *cmd, int xmit_type);
++static int q2t_rdy_to_xfer(struct scst_cmd *scst_cmd);
++static void q2t_on_free_cmd(struct scst_cmd *scst_cmd);
++static void q2t_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd);
++static int q2t_get_initiator_port_transport_id(struct scst_session *scst_sess,
++ uint8_t **transport_id);
++
++/* Predefs for callbacks handed to qla2xxx(target) */
++static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *pkt);
++static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt);
++static void q2t_async_event(uint16_t code, scsi_qla_host_t *ha,
++ uint16_t *mailbox);
++static void q2x_ctio_completion(scsi_qla_host_t *ha, uint32_t handle);
++static int q2t_host_action(scsi_qla_host_t *ha,
++ qla2x_tgt_host_action_t action);
++static void q2t_fc_port_added(scsi_qla_host_t *ha, fc_port_t *fcport);
++static void q2t_fc_port_deleted(scsi_qla_host_t *ha, fc_port_t *fcport);
++static int q2t_issue_task_mgmt(struct q2t_sess *sess, uint8_t *lun,
++ int lun_size, int fn, void *iocb, int flags);
++static void q2x_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
++ atio_entry_t *atio, int ha_locked);
++static void q24_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
++ atio7_entry_t *atio, int ha_locked);
++static void q2t_reject_free_srr_imm(scsi_qla_host_t *ha, struct srr_imm *imm,
++ int ha_lock);
++static int q2t_cut_cmd_data_head(struct q2t_cmd *cmd, unsigned int offset);
++static void q2t_clear_tgt_db(struct q2t_tgt *tgt, bool local_only);
++static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd);
++static int q2t_unreg_sess(struct q2t_sess *sess);
++static uint16_t q2t_get_scsi_transport_version(struct scst_tgt *scst_tgt);
++static uint16_t q2t_get_phys_transport_version(struct scst_tgt *scst_tgt);
++
++/** SYSFS **/
++
++static ssize_t q2t_version_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf);
++
++struct kobj_attribute q2t_version_attr =
++ __ATTR(version, S_IRUGO, q2t_version_show, NULL);
++
++static const struct attribute *q2t_attrs[] = {
++ &q2t_version_attr.attr,
++ NULL,
++};
++
++static ssize_t q2t_show_expl_conf_enabled(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buffer);
++static ssize_t q2t_store_expl_conf_enabled(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buffer, size_t size);
++
++struct kobj_attribute q2t_expl_conf_attr =
++ __ATTR(explicit_confirmation, S_IRUGO|S_IWUSR,
++ q2t_show_expl_conf_enabled, q2t_store_expl_conf_enabled);
++
++static ssize_t q2t_abort_isp_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buffer, size_t size);
++
++struct kobj_attribute q2t_abort_isp_attr =
++ __ATTR(abort_isp, S_IWUSR, NULL, q2t_abort_isp_store);
++
++static const struct attribute *q2t_tgt_attrs[] = {
++ &q2t_expl_conf_attr.attr,
++ &q2t_abort_isp_attr.attr,
++ NULL,
++};
++
++static int q2t_enable_tgt(struct scst_tgt *tgt, bool enable);
++static bool q2t_is_tgt_enabled(struct scst_tgt *tgt);
++
++/*
++ * Global Variables
++ */
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++#define trace_flag q2t_trace_flag
++static unsigned long q2t_trace_flag = Q2T_DEFAULT_LOG_FLAGS;
++#endif
++
++static struct scst_tgt_template tgt2x_template = {
++ .name = "qla2x00t",
++ .sg_tablesize = 0,
++ .use_clustering = 1,
++#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
++ .xmit_response_atomic = 0,
++ .rdy_to_xfer_atomic = 0,
++#else
++ .xmit_response_atomic = 1,
++ .rdy_to_xfer_atomic = 1,
++#endif
++ .max_hw_pending_time = Q2T_MAX_HW_PENDING_TIME,
++ .detect = q2t_target_detect,
++ .release = q2t_target_release,
++ .xmit_response = q2x_xmit_response,
++ .rdy_to_xfer = q2t_rdy_to_xfer,
++ .on_free_cmd = q2t_on_free_cmd,
++ .task_mgmt_fn_done = q2t_task_mgmt_fn_done,
++ .get_initiator_port_transport_id = q2t_get_initiator_port_transport_id,
++ .get_scsi_transport_version = q2t_get_scsi_transport_version,
++ .get_phys_transport_version = q2t_get_phys_transport_version,
++ .on_hw_pending_cmd_timeout = q2t_on_hw_pending_cmd_timeout,
++ .enable_target = q2t_enable_tgt,
++ .is_target_enabled = q2t_is_tgt_enabled,
++ .tgtt_attrs = q2t_attrs,
++ .tgt_attrs = q2t_tgt_attrs,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = Q2T_DEFAULT_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static struct kmem_cache *q2t_cmd_cachep;
++static struct kmem_cache *q2t_mgmt_cmd_cachep;
++static mempool_t *q2t_mgmt_cmd_mempool;
++
++static DECLARE_RWSEM(q2t_unreg_rwsem);
++
++/* It's not yet supported */
++static inline int scst_cmd_get_ppl_offset(struct scst_cmd *scst_cmd)
++{
++ return 0;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static inline void q2t_sess_get(struct q2t_sess *sess)
++{
++ sess->sess_ref++;
++ TRACE_DBG("sess %p, new sess_ref %d", sess, sess->sess_ref);
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static inline void q2t_sess_put(struct q2t_sess *sess)
++{
++ TRACE_DBG("sess %p, new sess_ref %d", sess, sess->sess_ref-1);
++ BUG_ON(sess->sess_ref == 0);
++
++ sess->sess_ref--;
++ if (sess->sess_ref == 0)
++ q2t_unreg_sess(sess);
++}
++
++/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
++static inline struct q2t_sess *q2t_find_sess_by_loop_id(struct q2t_tgt *tgt,
++ uint16_t lid)
++{
++ struct q2t_sess *sess;
++ BUG_ON(tgt == NULL);
++ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
++ if (lid == (sess->loop_id))
++ return sess;
++ }
++ return NULL;
++}
++
++/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
++static inline struct q2t_sess *q2t_find_sess_by_s_id(struct q2t_tgt *tgt,
++ const uint8_t *s_id)
++{
++ struct q2t_sess *sess;
++ BUG_ON(tgt == NULL);
++ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
++ if ((sess->s_id.b.al_pa == s_id[2]) &&
++ (sess->s_id.b.area == s_id[1]) &&
++ (sess->s_id.b.domain == s_id[0]))
++ return sess;
++ }
++ return NULL;
++}
++
++/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
++static inline struct q2t_sess *q2t_find_sess_by_s_id_le(struct q2t_tgt *tgt,
++ const uint8_t *s_id)
++{
++ struct q2t_sess *sess;
++ BUG_ON(tgt == NULL);
++ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
++ if ((sess->s_id.b.al_pa == s_id[0]) &&
++ (sess->s_id.b.area == s_id[1]) &&
++ (sess->s_id.b.domain == s_id[2]))
++ return sess;
++ }
++ return NULL;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static inline void q2t_exec_queue(scsi_qla_host_t *ha)
++{
++ qla2x00_isp_cmd(ha);
++}
++
++/* Might release hw lock, then reaquire!! */
++static inline int q2t_issue_marker(scsi_qla_host_t *ha, int ha_locked)
++{
++ /* Send marker if required */
++ if (unlikely(ha->marker_needed != 0)) {
++ int rc = qla2x00_issue_marker(ha, ha_locked);
++ if (rc != QLA_SUCCESS) {
++ PRINT_ERROR("qla2x00t(%ld): issue_marker() "
++ "failed", ha->instance);
++ }
++ return rc;
++ }
++ return QLA_SUCCESS;
++}
++
++/*
++ * Registers with initiator driver (but target mode isn't enabled till
++ * it's turned on via sysfs)
++ */
++static int q2t_target_detect(struct scst_tgt_template *tgtt)
++{
++ int res, rc;
++ struct qla_tgt_data t = {
++ .magic = QLA2X_TARGET_MAGIC,
++ .tgt24_atio_pkt = q24_atio_pkt,
++ .tgt_response_pkt = q2t_response_pkt,
++ .tgt2x_ctio_completion = q2x_ctio_completion,
++ .tgt_async_event = q2t_async_event,
++ .tgt_host_action = q2t_host_action,
++ .tgt_fc_port_added = q2t_fc_port_added,
++ .tgt_fc_port_deleted = q2t_fc_port_deleted,
++ };
++
++ TRACE_ENTRY();
++
++ rc = qla2xxx_tgt_register_driver(&t);
++ if (rc < 0) {
++ res = rc;
++ PRINT_ERROR("qla2x00t: Unable to register driver: %d", res);
++ goto out;
++ }
++
++ if (rc != QLA2X_INITIATOR_MAGIC) {
++ PRINT_ERROR("qla2x00t: Wrong version of the initiator part: "
++ "%d", rc);
++ res = -EINVAL;
++ goto out;
++ }
++
++ qla2xxx_add_targets();
++
++ res = 0;
++
++ PRINT_INFO("qla2x00t: %s", "Target mode driver for QLogic 2x00 controller "
++ "registered successfully");
++
++out:
++ TRACE_EXIT();
++ return res;
++}
++
++static void q2t_free_session_done(struct scst_session *scst_sess)
++{
++ struct q2t_sess *sess;
++ struct q2t_tgt *tgt;
++ scsi_qla_host_t *ha;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ BUG_ON(scst_sess == NULL);
++ sess = (struct q2t_sess *)scst_sess_get_tgt_priv(scst_sess);
++ BUG_ON(sess == NULL);
++ tgt = sess->tgt;
++
++ TRACE_MGMT_DBG("Unregistration of sess %p finished", sess);
++
++ kfree(sess);
++
++ if (tgt == NULL)
++ goto out;
++
++ TRACE_DBG("empty(sess_list) %d sess_count %d",
++ list_empty(&tgt->sess_list), tgt->sess_count);
++
++ ha = tgt->ha;
++
++ /*
++ * We need to protect against race, when tgt is freed before or
++ * inside wake_up()
++ */
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ tgt->sess_count--;
++ if (tgt->sess_count == 0)
++ wake_up_all(&tgt->waitQ);
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q2t_unreg_sess(struct q2t_sess *sess)
++{
++ int res = 1;
++
++ TRACE_ENTRY();
++
++ BUG_ON(sess == NULL);
++ BUG_ON(sess->sess_ref != 0);
++
++ TRACE_MGMT_DBG("Deleting sess %p from tgt %p", sess, sess->tgt);
++ list_del(&sess->sess_list_entry);
++
++ if (sess->deleted)
++ list_del(&sess->del_list_entry);
++
++ PRINT_INFO("qla2x00t(%ld): %ssession for loop_id %d deleted",
++ sess->tgt->ha->instance, sess->local ? "local " : "",
++ sess->loop_id);
++
++ scst_unregister_session(sess->scst_sess, 0, q2t_free_session_done);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q2t_reset(scsi_qla_host_t *ha, void *iocb, int mcmd)
++{
++ struct q2t_sess *sess;
++ int loop_id;
++ uint16_t lun = 0;
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ notify24xx_entry_t *n = (notify24xx_entry_t *)iocb;
++ loop_id = le16_to_cpu(n->nport_handle);
++ } else
++ loop_id = GET_TARGET_ID(ha, (notify_entry_t *)iocb);
++
++ if (loop_id == 0xFFFF) {
++ /* Global event */
++ q2t_clear_tgt_db(ha->tgt, 1);
++ if (!list_empty(&ha->tgt->sess_list)) {
++ sess = list_entry(ha->tgt->sess_list.next,
++ typeof(*sess), sess_list_entry);
++ switch (mcmd) {
++ case Q2T_NEXUS_LOSS_SESS:
++ mcmd = Q2T_NEXUS_LOSS;
++ break;
++
++ case Q2T_ABORT_ALL_SESS:
++ mcmd = Q2T_ABORT_ALL;
++ break;
++
++ case Q2T_NEXUS_LOSS:
++ case Q2T_ABORT_ALL:
++ break;
++
++ default:
++ PRINT_ERROR("qla2x00t(%ld): Not allowed "
++ "command %x in %s", ha->instance,
++ mcmd, __func__);
++ sess = NULL;
++ break;
++ }
++ } else
++ sess = NULL;
++ } else
++ sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id);
++
++ if (sess == NULL) {
++ res = -ESRCH;
++ ha->tgt->tm_to_unknown = 1;
++ goto out;
++ }
++
++ TRACE_MGMT_DBG("scsi(%ld): resetting (session %p from port "
++ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, "
++ "mcmd %x, loop_id %d)", ha->host_no, sess,
++ sess->port_name[0], sess->port_name[1],
++ sess->port_name[2], sess->port_name[3],
++ sess->port_name[4], sess->port_name[5],
++ sess->port_name[6], sess->port_name[7],
++ mcmd, loop_id);
++
++ res = q2t_issue_task_mgmt(sess, (uint8_t *)&lun, sizeof(lun),
++ mcmd, iocb, Q24_MGMT_SEND_NACK);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static void q2t_clear_tgt_db(struct q2t_tgt *tgt, bool local_only)
++{
++ struct q2t_sess *sess, *sess_tmp;
++
++ TRACE_ENTRY();
++
++ TRACE(TRACE_MGMT, "qla2x00t: Clearing targets DB %p", tgt);
++
++ list_for_each_entry_safe(sess, sess_tmp, &tgt->sess_list,
++ sess_list_entry) {
++ if (local_only && !sess->local)
++ continue;
++ if (local_only && sess->local)
++ TRACE_MGMT_DBG("Putting local session %p from port "
++ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
++ sess, sess->port_name[0], sess->port_name[1],
++ sess->port_name[2], sess->port_name[3],
++ sess->port_name[4], sess->port_name[5],
++ sess->port_name[6], sess->port_name[7]);
++ q2t_sess_put(sess);
++ }
++
++ /* At this point tgt could be already dead */
++
++ TRACE_MGMT_DBG("Finished clearing tgt %p DB", tgt);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Called in a thread context */
++static void q2t_alloc_session_done(struct scst_session *scst_sess,
++ void *data, int result)
++{
++ TRACE_ENTRY();
++
++ if (result != 0) {
++ struct q2t_sess *sess = (struct q2t_sess *)data;
++ struct q2t_tgt *tgt = sess->tgt;
++ scsi_qla_host_t *ha = tgt->ha;
++ unsigned long flags;
++
++ PRINT_INFO("qla2x00t(%ld): Session initialization failed",
++ ha->instance);
++
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ q2t_sess_put(sess);
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static void q2t_del_sess_timer_fn(unsigned long arg)
++{
++ struct q2t_tgt *tgt = (struct q2t_tgt *)arg;
++ scsi_qla_host_t *ha = tgt->ha;
++ struct q2t_sess *sess;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ while (!list_empty(&tgt->del_sess_list)) {
++ sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
++ del_list_entry);
++ if (time_after_eq(jiffies, sess->expires)) {
++ /*
++ * sess will be deleted from del_sess_list in
++ * q2t_unreg_sess()
++ */
++ TRACE_MGMT_DBG("Timeout: sess %p about to be deleted",
++ sess);
++ q2t_sess_put(sess);
++ } else {
++ tgt->sess_del_timer.expires = sess->expires;
++ add_timer(&tgt->sess_del_timer);
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* pha->hardware_lock supposed to be held on entry */
++static void q2t_undelete_sess(struct q2t_sess *sess)
++{
++ list_del(&sess->del_list_entry);
++ sess->deleted = 0;
++}
++
++/*
++ * Must be called under tgt_mutex.
++ *
++ * Adds an extra ref to allow to drop hw lock after adding sess to the list.
++ * Caller must put it.
++ */
++static struct q2t_sess *q2t_create_sess(scsi_qla_host_t *ha, fc_port_t *fcport,
++ bool local)
++{
++ char *wwn_str;
++ const int wwn_str_len = 3*WWN_SIZE+2;
++ struct q2t_tgt *tgt = ha->tgt;
++ struct q2t_sess *sess;
++
++ TRACE_ENTRY();
++
++ /* Check to avoid double sessions */
++ spin_lock_irq(&ha->hardware_lock);
++ list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
++ if ((sess->port_name[0] == fcport->port_name[0]) &&
++ (sess->port_name[1] == fcport->port_name[1]) &&
++ (sess->port_name[2] == fcport->port_name[2]) &&
++ (sess->port_name[3] == fcport->port_name[3]) &&
++ (sess->port_name[4] == fcport->port_name[4]) &&
++ (sess->port_name[5] == fcport->port_name[5]) &&
++ (sess->port_name[6] == fcport->port_name[6]) &&
++ (sess->port_name[7] == fcport->port_name[7])) {
++ TRACE_MGMT_DBG("Double sess %p found (s_id %x:%x:%x, "
++ "loop_id %d), updating to d_id %x:%x:%x, "
++ "loop_id %d", sess, sess->s_id.b.domain,
++ sess->s_id.b.al_pa, sess->s_id.b.area,
++ sess->loop_id, fcport->d_id.b.domain,
++ fcport->d_id.b.al_pa, fcport->d_id.b.area,
++ fcport->loop_id);
++
++ if (sess->deleted)
++ q2t_undelete_sess(sess);
++
++ q2t_sess_get(sess);
++ sess->s_id = fcport->d_id;
++ sess->loop_id = fcport->loop_id;
++ sess->conf_compl_supported = fcport->conf_compl_supported;
++ if (sess->local && !local)
++ sess->local = 0;
++ spin_unlock_irq(&ha->hardware_lock);
++ goto out;
++ }
++ }
++ spin_unlock_irq(&ha->hardware_lock);
++
++ /* We are under tgt_mutex, so a new sess can't be added behind us */
++
++ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
++ if (sess == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): session allocation failed, "
++ "all commands from port %02x:%02x:%02x:%02x:"
++ "%02x:%02x:%02x:%02x will be refused", ha->instance,
++ fcport->port_name[0], fcport->port_name[1],
++ fcport->port_name[2], fcport->port_name[3],
++ fcport->port_name[4], fcport->port_name[5],
++ fcport->port_name[6], fcport->port_name[7]);
++ goto out;
++ }
++
++ sess->sess_ref = 2; /* plus 1 extra ref, see above */
++ sess->tgt = ha->tgt;
++ sess->s_id = fcport->d_id;
++ sess->loop_id = fcport->loop_id;
++ sess->conf_compl_supported = fcport->conf_compl_supported;
++ sess->local = local;
++ BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
++ memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
++
++ wwn_str = kmalloc(wwn_str_len, GFP_KERNEL);
++ if (wwn_str == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): Allocation of wwn_str failed. "
++ "All commands from port %02x:%02x:%02x:%02x:%02x:%02x:"
++ "%02x:%02x will be refused", ha->instance,
++ fcport->port_name[0], fcport->port_name[1],
++ fcport->port_name[2], fcport->port_name[3],
++ fcport->port_name[4], fcport->port_name[5],
++ fcport->port_name[6], fcport->port_name[7]);
++ goto out_free_sess;
++ }
++
++ sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
++ fcport->port_name[0], fcport->port_name[1],
++ fcport->port_name[2], fcport->port_name[3],
++ fcport->port_name[4], fcport->port_name[5],
++ fcport->port_name[6], fcport->port_name[7]);
++
++ /* Let's do the session creation async'ly */
++ sess->scst_sess = scst_register_session(tgt->scst_tgt, 1, wwn_str,
++ sess, sess, q2t_alloc_session_done);
++ if (sess->scst_sess == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): scst_register_session() "
++ "failed for host %ld (wwn %s, loop_id %d), all "
++ "commands from it will be refused", ha->instance,
++ ha->host_no, wwn_str, fcport->loop_id);
++ goto out_free_sess_wwn;
++ }
++
++ spin_lock_irq(&ha->hardware_lock);
++ TRACE_MGMT_DBG("Adding sess %p to tgt %p", sess, tgt);
++ list_add_tail(&sess->sess_list_entry, &tgt->sess_list);
++ tgt->sess_count++;
++ spin_unlock_irq(&ha->hardware_lock);
++
++ PRINT_INFO("qla2x00t(%ld): %ssession for wwn %s (loop_id %d, "
++ "s_id %x:%x:%x, confirmed completion %ssupported) added",
++ ha->instance, local ? "local " : "", wwn_str, fcport->loop_id,
++ sess->s_id.b.domain, sess->s_id.b.al_pa, sess->s_id.b.area,
++ sess->conf_compl_supported ? "" : "not ");
++
++ kfree(wwn_str);
++
++out:
++ TRACE_EXIT_HRES(sess);
++ return sess;
++
++out_free_sess_wwn:
++ kfree(wwn_str);
++ /* go through */
++
++out_free_sess:
++ kfree(sess);
++ sess = NULL;
++ goto out;
++}
++
++/* pha->hardware_lock supposed to be held on entry */
++static void q2t_reappear_sess(struct q2t_sess *sess, const char *reason)
++{
++ q2t_undelete_sess(sess);
++
++ PRINT_INFO("qla2x00t(%ld): %ssession for port %02x:"
++ "%02x:%02x:%02x:%02x:%02x:%02x:%02x (loop ID %d) "
++ "reappeared%s", sess->tgt->ha->instance,
++ sess->local ? "local " : "", sess->port_name[0],
++ sess->port_name[1], sess->port_name[2], sess->port_name[3],
++ sess->port_name[4], sess->port_name[5], sess->port_name[6],
++ sess->port_name[7], sess->loop_id, reason);
++ TRACE_MGMT_DBG("Appeared sess %p", sess);
++}
++
++static void q2t_fc_port_added(scsi_qla_host_t *ha, fc_port_t *fcport)
++{
++ struct q2t_tgt *tgt;
++ struct q2t_sess *sess;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&ha->tgt_mutex);
++
++ tgt = ha->tgt;
++
++ if ((tgt == NULL) || (fcport->port_type != FCT_INITIATOR))
++ goto out_unlock;
++
++ if (tgt->tgt_stop)
++ goto out_unlock;
++
++ spin_lock_irq(&ha->hardware_lock);
++
++ sess = q2t_find_sess_by_loop_id(tgt, fcport->loop_id);
++ if (sess == NULL) {
++ spin_unlock_irq(&ha->hardware_lock);
++ sess = q2t_create_sess(ha, fcport, false);
++ spin_lock_irq(&ha->hardware_lock);
++ if (sess != NULL)
++ q2t_sess_put(sess); /* put the extra creation ref */
++ } else {
++ if (sess->deleted)
++ q2t_reappear_sess(sess, "");
++ }
++
++ if (sess->local) {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): local session for "
++ "port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
++ "(loop ID %d) became global", ha->instance,
++ fcport->port_name[0], fcport->port_name[1],
++ fcport->port_name[2], fcport->port_name[3],
++ fcport->port_name[4], fcport->port_name[5],
++ fcport->port_name[6], fcport->port_name[7],
++ sess->loop_id);
++ sess->local = 0;
++ }
++
++ spin_unlock_irq(&ha->hardware_lock);
++
++out_unlock:
++ mutex_unlock(&ha->tgt_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void q2t_fc_port_deleted(scsi_qla_host_t *ha, fc_port_t *fcport)
++{
++ struct q2t_tgt *tgt;
++ struct q2t_sess *sess;
++ uint32_t dev_loss_tmo;
++
++ TRACE_ENTRY();
++
++ mutex_lock(&ha->tgt_mutex);
++
++ tgt = ha->tgt;
++
++ if ((tgt == NULL) || (fcport->port_type != FCT_INITIATOR))
++ goto out_unlock;
++
++ dev_loss_tmo = ha->port_down_retry_count + 5;
++
++ if (tgt->tgt_stop)
++ goto out_unlock;
++
++ spin_lock_irq(&ha->hardware_lock);
++
++ sess = q2t_find_sess_by_loop_id(tgt, fcport->loop_id);
++ if (sess == NULL)
++ goto out_unlock_ha;
++
++ if (!sess->deleted) {
++ int add_tmr;
++
++ add_tmr = list_empty(&tgt->del_sess_list);
++
++ TRACE_MGMT_DBG("Scheduling sess %p to deletion", sess);
++ list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
++ sess->deleted = 1;
++
++ PRINT_INFO("qla2x00t(%ld): %ssession for port %02x:%02x:%02x:"
++ "%02x:%02x:%02x:%02x:%02x (loop ID %d) scheduled for "
++ "deletion in %d secs", ha->instance,
++ sess->local ? "local " : "",
++ fcport->port_name[0], fcport->port_name[1],
++ fcport->port_name[2], fcport->port_name[3],
++ fcport->port_name[4], fcport->port_name[5],
++ fcport->port_name[6], fcport->port_name[7],
++ sess->loop_id, dev_loss_tmo);
++
++ sess->expires = jiffies + dev_loss_tmo * HZ;
++ if (add_tmr)
++ mod_timer(&tgt->sess_del_timer, sess->expires);
++ }
++
++out_unlock_ha:
++ spin_unlock_irq(&ha->hardware_lock);
++
++out_unlock:
++ mutex_unlock(&ha->tgt_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++
++static inline int test_tgt_sess_count(struct q2t_tgt *tgt)
++{
++ unsigned long flags;
++ int res;
++
++ /*
++ * We need to protect against race, when tgt is freed before or
++ * inside wake_up()
++ */
++ spin_lock_irqsave(&tgt->ha->hardware_lock, flags);
++ TRACE_DBG("tgt %p, empty(sess_list)=%d sess_count=%d",
++ tgt, list_empty(&tgt->sess_list), tgt->sess_count);
++ res = (tgt->sess_count == 0);
++ spin_unlock_irqrestore(&tgt->ha->hardware_lock, flags);
++
++ return res;
++}
++
++/* Must be called under tgt_host_action_mutex or q2t_unreg_rwsem write locked */
++static void q2t_target_stop(struct scst_tgt *scst_tgt)
++{
++ struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++ scsi_qla_host_t *ha = tgt->ha;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Stopping target for host %ld(%p)", ha->host_no, ha);
++
++ /*
++ * Mutex needed to sync with q2t_fc_port_[added,deleted].
++ * Lock is needed, because we still can get an incoming packet.
++ */
++
++ mutex_lock(&ha->tgt_mutex);
++ spin_lock_irq(&ha->hardware_lock);
++ tgt->tgt_stop = 1;
++ q2t_clear_tgt_db(tgt, false);
++ spin_unlock_irq(&ha->hardware_lock);
++ mutex_unlock(&ha->tgt_mutex);
++
++ del_timer_sync(&tgt->sess_del_timer);
++
++ TRACE_MGMT_DBG("Waiting for sess works (tgt %p)", tgt);
++ spin_lock_irq(&tgt->sess_work_lock);
++ while (!list_empty(&tgt->sess_works_list)) {
++ spin_unlock_irq(&tgt->sess_work_lock);
++ flush_scheduled_work();
++ spin_lock_irq(&tgt->sess_work_lock);
++ }
++ spin_unlock_irq(&tgt->sess_work_lock);
++
++ TRACE_MGMT_DBG("Waiting for tgt %p: list_empty(sess_list)=%d "
++ "sess_count=%d", tgt, list_empty(&tgt->sess_list),
++ tgt->sess_count);
++
++ wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
++
++ /* Big hammer */
++ if (!ha->host_shutting_down && qla_tgt_mode_enabled(ha))
++ qla2x00_disable_tgt_mode(ha);
++
++ /* Wait for sessions to clear out (just in case) */
++ wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
++
++ TRACE_MGMT_DBG("Waiting for %d IRQ commands to complete (tgt %p)",
++ tgt->irq_cmd_count, tgt);
++
++ mutex_lock(&ha->tgt_mutex);
++ spin_lock_irq(&ha->hardware_lock);
++ while (tgt->irq_cmd_count != 0) {
++ spin_unlock_irq(&ha->hardware_lock);
++ udelay(2);
++ spin_lock_irq(&ha->hardware_lock);
++ }
++ ha->tgt = NULL;
++ spin_unlock_irq(&ha->hardware_lock);
++ mutex_unlock(&ha->tgt_mutex);
++
++ TRACE_MGMT_DBG("Stop of tgt %p finished", tgt);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called under tgt_host_action_mutex or q2t_unreg_rwsem write locked */
++static int q2t_target_release(struct scst_tgt *scst_tgt)
++{
++ struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++ scsi_qla_host_t *ha = tgt->ha;
++
++ TRACE_ENTRY();
++
++ q2t_target_stop(scst_tgt);
++
++ ha->q2t_tgt = NULL;
++ scst_tgt_set_tgt_priv(scst_tgt, NULL);
++
++ TRACE_MGMT_DBG("Release of tgt %p finished", tgt);
++
++ kfree(tgt);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q2x_modify_command_count(scsi_qla_host_t *ha, int cmd_count,
++ int imm_count)
++{
++ modify_lun_entry_t *pkt;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending MODIFY_LUN (ha=%p, cmd=%d, imm=%d)",
++ ha, cmd_count, imm_count);
++
++ /* Sending marker isn't necessary, since we called from ISR */
++
++ pkt = (modify_lun_entry_t *)qla2x00_req_pkt(ha);
++ if (pkt == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out;
++ }
++
++ ha->tgt->modify_lun_expected++;
++
++ pkt->entry_type = MODIFY_LUN_TYPE;
++ pkt->entry_count = 1;
++ if (cmd_count < 0) {
++ pkt->operators = MODIFY_LUN_CMD_SUB; /* Subtract from command count */
++ pkt->command_count = -cmd_count;
++ } else if (cmd_count > 0) {
++ pkt->operators = MODIFY_LUN_CMD_ADD; /* Add to command count */
++ pkt->command_count = cmd_count;
++ }
++
++ if (imm_count < 0) {
++ pkt->operators |= MODIFY_LUN_IMM_SUB;
++ pkt->immed_notify_count = -imm_count;
++ } else if (imm_count > 0) {
++ pkt->operators |= MODIFY_LUN_IMM_ADD;
++ pkt->immed_notify_count = imm_count;
++ }
++
++ pkt->timeout = 0; /* Use default */
++
++ TRACE_BUFFER("MODIFY LUN packet data", pkt, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q2x_send_notify_ack(scsi_qla_host_t *ha, notify_entry_t *iocb,
++ uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
++ uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan)
++{
++ nack_entry_t *ntfy;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending NOTIFY_ACK (ha=%p)", ha);
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
++ goto out;
++
++ ntfy = (nack_entry_t *)qla2x00_req_pkt(ha);
++ if (ntfy == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out;
++ }
++
++ if (ha->tgt != NULL)
++ ha->tgt->notify_ack_expected++;
++
++ ntfy->entry_type = NOTIFY_ACK_TYPE;
++ ntfy->entry_count = 1;
++ SET_TARGET_ID(ha, ntfy->target, GET_TARGET_ID(ha, iocb));
++ ntfy->status = iocb->status;
++ ntfy->task_flags = iocb->task_flags;
++ ntfy->seq_id = iocb->seq_id;
++ /* Do not increment here, the chip isn't decrementing */
++ /* ntfy->flags = __constant_cpu_to_le16(NOTIFY_ACK_RES_COUNT); */
++ ntfy->flags |= cpu_to_le16(add_flags);
++ ntfy->srr_rx_id = iocb->srr_rx_id;
++ ntfy->srr_rel_offs = iocb->srr_rel_offs;
++ ntfy->srr_ui = iocb->srr_ui;
++ ntfy->srr_flags = cpu_to_le16(srr_flags);
++ ntfy->srr_reject_code = cpu_to_le16(srr_reject_code);
++ ntfy->srr_reject_code_expl = srr_explan;
++ ntfy->ox_id = iocb->ox_id;
++
++ if (resp_code_valid) {
++ ntfy->resp_code = cpu_to_le16(resp_code);
++ ntfy->flags |= __constant_cpu_to_le16(
++ NOTIFY_ACK_TM_RESP_CODE_VALID);
++ }
++
++ TRACE(TRACE_SCSI, "qla2x00t(%ld): Sending Notify Ack Seq %#x -> I %#x "
++ "St %#x RC %#x", ha->instance,
++ le16_to_cpu(iocb->seq_id), GET_TARGET_ID(ha, iocb),
++ le16_to_cpu(iocb->status), le16_to_cpu(ntfy->resp_code));
++ TRACE_BUFFER("Notify Ack packet data", ntfy, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q24_send_abts_resp(scsi_qla_host_t *ha,
++ const abts24_recv_entry_t *abts, uint32_t status, bool ids_reversed)
++{
++ abts24_resp_entry_t *resp;
++ uint32_t f_ctl;
++ uint8_t *p;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending task mgmt ABTS response (ha=%p, atio=%p, "
++ "status=%x", ha, abts, status);
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
++ goto out;
++
++ resp = (abts24_resp_entry_t *)qla2x00_req_pkt(ha);
++ if (resp == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out;
++ }
++
++ resp->entry_type = ABTS_RESP_24XX;
++ resp->entry_count = 1;
++ resp->nport_handle = abts->nport_handle;
++ resp->sof_type = abts->sof_type;
++ resp->exchange_address = abts->exchange_address;
++ resp->fcp_hdr_le = abts->fcp_hdr_le;
++ f_ctl = __constant_cpu_to_le32(F_CTL_EXCH_CONTEXT_RESP |
++ F_CTL_LAST_SEQ | F_CTL_END_SEQ |
++ F_CTL_SEQ_INITIATIVE);
++ p = (uint8_t *)&f_ctl;
++ resp->fcp_hdr_le.f_ctl[0] = *p++;
++ resp->fcp_hdr_le.f_ctl[1] = *p++;
++ resp->fcp_hdr_le.f_ctl[2] = *p;
++ if (ids_reversed) {
++ resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.d_id[0];
++ resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.d_id[1];
++ resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.d_id[2];
++ resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.s_id[0];
++ resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.s_id[1];
++ resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.s_id[2];
++ } else {
++ resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0];
++ resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1];
++ resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2];
++ resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0];
++ resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1];
++ resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2];
++ }
++ resp->exchange_addr_to_abort = abts->exchange_addr_to_abort;
++ if (status == SCST_MGMT_STATUS_SUCCESS) {
++ resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_ACC;
++ resp->payload.ba_acct.seq_id_valid = SEQ_ID_INVALID;
++ resp->payload.ba_acct.low_seq_cnt = 0x0000;
++ resp->payload.ba_acct.high_seq_cnt = 0xFFFF;
++ resp->payload.ba_acct.ox_id = abts->fcp_hdr_le.ox_id;
++ resp->payload.ba_acct.rx_id = abts->fcp_hdr_le.rx_id;
++ } else {
++ resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_RJT;
++ resp->payload.ba_rjt.reason_code =
++ BA_RJT_REASON_CODE_UNABLE_TO_PERFORM;
++ /* Other bytes are zero */
++ }
++
++ TRACE_BUFFER("ABTS RESP packet data", resp, REQUEST_ENTRY_SIZE);
++
++ ha->tgt->abts_resp_expected++;
++
++ q2t_exec_queue(ha);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q24_retry_term_exchange(scsi_qla_host_t *ha,
++ abts24_resp_fw_entry_t *entry)
++{
++ ctio7_status1_entry_t *ctio;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending retry TERM EXCH CTIO7 (ha=%p)", ha);
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
++ goto out;
++
++ ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
++ if (ctio == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out;
++ }
++
++ /*
++ * We've got on entrance firmware's response on by us generated
++ * ABTS response. So, in it ID fields are reversed.
++ */
++
++ ctio->common.entry_type = CTIO_TYPE7;
++ ctio->common.entry_count = 1;
++ ctio->common.nport_handle = entry->nport_handle;
++ ctio->common.handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
++ ctio->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
++ ctio->common.initiator_id[0] = entry->fcp_hdr_le.d_id[0];
++ ctio->common.initiator_id[1] = entry->fcp_hdr_le.d_id[1];
++ ctio->common.initiator_id[2] = entry->fcp_hdr_le.d_id[2];
++ ctio->common.exchange_addr = entry->exchange_addr_to_abort;
++ ctio->flags = __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_TERMINATE);
++ ctio->ox_id = entry->fcp_hdr_le.ox_id;
++
++ TRACE_BUFFER("CTIO7 retry TERM EXCH packet data", ctio, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++ q24_send_abts_resp(ha, (abts24_recv_entry_t *)entry,
++ SCST_MGMT_STATUS_SUCCESS, true);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q24_handle_abts(scsi_qla_host_t *ha, abts24_recv_entry_t *abts)
++{
++ uint32_t tag;
++ int rc;
++ struct q2t_mgmt_cmd *mcmd;
++ struct q2t_sess *sess;
++
++ TRACE_ENTRY();
++
++ if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) {
++ PRINT_ERROR("qla2x00t(%ld): ABTS: Abort Sequence not "
++ "supported", ha->instance);
++ goto out_err;
++ }
++
++ tag = abts->exchange_addr_to_abort;
++
++ if (tag == ATIO_EXCHANGE_ADDRESS_UNKNOWN) {
++ TRACE_MGMT_DBG("qla2x00t(%ld): ABTS: Unknown Exchange "
++ "Address received", ha->instance);
++ goto out_err;
++ }
++
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort (s_id=%x:%x:%x, "
++ "tag=%d, param=%x)", ha->instance, abts->fcp_hdr_le.s_id[2],
++ abts->fcp_hdr_le.s_id[1], abts->fcp_hdr_le.s_id[0], tag,
++ le32_to_cpu(abts->fcp_hdr_le.parameter));
++
++ sess = q2t_find_sess_by_s_id_le(ha->tgt, abts->fcp_hdr_le.s_id);
++ if (sess == NULL) {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort for unexisting "
++ "session", ha->instance);
++ ha->tgt->tm_to_unknown = 1;
++ goto out_err;
++ }
++
++ mcmd = mempool_alloc(q2t_mgmt_cmd_mempool, GFP_ATOMIC);
++ if (mcmd == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s: Allocation of ABORT cmd failed",
++ ha->instance, __func__);
++ goto out_err;
++ }
++ memset(mcmd, 0, sizeof(*mcmd));
++
++ mcmd->sess = sess;
++ memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts));
++
++ rc = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, tag,
++ SCST_ATOMIC, mcmd);
++ if (rc != 0) {
++ PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_tag() failed: %d",
++ ha->instance, rc);
++ goto out_err_free;
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_err_free:
++ mempool_free(mcmd, q2t_mgmt_cmd_mempool);
++
++out_err:
++ q24_send_abts_resp(ha, abts, SCST_MGMT_STATUS_REJECTED, false);
++ goto out;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q24_send_task_mgmt_ctio(scsi_qla_host_t *ha,
++ struct q2t_mgmt_cmd *mcmd, uint32_t resp_code)
++{
++ const atio7_entry_t *atio = &mcmd->orig_iocb.atio7;
++ ctio7_status1_entry_t *ctio;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x",
++ ha, atio, resp_code);
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
++ goto out;
++
++ ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
++ if (ctio == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out;
++ }
++
++ ctio->common.entry_type = CTIO_TYPE7;
++ ctio->common.entry_count = 1;
++ ctio->common.handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
++ ctio->common.nport_handle = mcmd->sess->loop_id;
++ ctio->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
++ ctio->common.initiator_id[0] = atio->fcp_hdr.s_id[2];
++ ctio->common.initiator_id[1] = atio->fcp_hdr.s_id[1];
++ ctio->common.initiator_id[2] = atio->fcp_hdr.s_id[0];
++ ctio->common.exchange_addr = atio->exchange_addr;
++ ctio->flags = (atio->attr << 9) | __constant_cpu_to_le16(
++ CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS);
++ ctio->ox_id = swab16(atio->fcp_hdr.ox_id);
++ ctio->scsi_status = __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID);
++ ctio->response_len = __constant_cpu_to_le16(8);
++ ((uint32_t *)ctio->sense_data)[0] = cpu_to_be32(resp_code);
++
++ TRACE_BUFFER("CTIO7 TASK MGMT packet data", ctio, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q24_send_notify_ack(scsi_qla_host_t *ha,
++ notify24xx_entry_t *iocb, uint16_t srr_flags,
++ uint8_t srr_reject_code, uint8_t srr_explan)
++{
++ nack24xx_entry_t *nack;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending NOTIFY_ACK24 (ha=%p)", ha);
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, 1) != QLA_SUCCESS)
++ goto out;
++
++ if (ha->tgt != NULL)
++ ha->tgt->notify_ack_expected++;
++
++ nack = (nack24xx_entry_t *)qla2x00_req_pkt(ha);
++ if (nack == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out;
++ }
++
++ nack->entry_type = NOTIFY_ACK_TYPE;
++ nack->entry_count = 1;
++ nack->nport_handle = iocb->nport_handle;
++ if (le16_to_cpu(iocb->status) == IMM_NTFY_ELS) {
++ nack->flags = iocb->flags &
++ __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
++ }
++ nack->srr_rx_id = iocb->srr_rx_id;
++ nack->status = iocb->status;
++ nack->status_subcode = iocb->status_subcode;
++ nack->exchange_address = iocb->exchange_address;
++ nack->srr_rel_offs = iocb->srr_rel_offs;
++ nack->srr_ui = iocb->srr_ui;
++ nack->srr_flags = cpu_to_le16(srr_flags);
++ nack->srr_reject_code = srr_reject_code;
++ nack->srr_reject_code_expl = srr_explan;
++ nack->ox_id = iocb->ox_id;
++
++ TRACE(TRACE_SCSI, "qla2x00t(%ld): Sending 24xx Notify Ack %d",
++ ha->instance, nack->status);
++ TRACE_BUFFER("24xx Notify Ack packet data", nack, sizeof(*nack));
++
++ q2t_exec_queue(ha);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static uint32_t q2t_convert_to_fc_tm_status(int scst_mstatus)
++{
++ uint32_t res;
++
++ switch (scst_mstatus) {
++ case SCST_MGMT_STATUS_SUCCESS:
++ res = FC_TM_SUCCESS;
++ break;
++ case SCST_MGMT_STATUS_TASK_NOT_EXIST:
++ res = FC_TM_BAD_CMD;
++ break;
++ case SCST_MGMT_STATUS_FN_NOT_SUPPORTED:
++ case SCST_MGMT_STATUS_REJECTED:
++ res = FC_TM_REJECT;
++ break;
++ case SCST_MGMT_STATUS_LUN_NOT_EXIST:
++ case SCST_MGMT_STATUS_FAILED:
++ default:
++ res = FC_TM_FAILED;
++ break;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* SCST Callback */
++static void q2t_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
++{
++ struct q2t_mgmt_cmd *mcmd;
++ unsigned long flags;
++ scsi_qla_host_t *ha;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("scst_mcmd (%p) status %#x state %#x", scst_mcmd,
++ scst_mcmd->status, scst_mcmd->state);
++
++ mcmd = scst_mgmt_cmd_get_tgt_priv(scst_mcmd);
++ if (unlikely(mcmd == NULL)) {
++ PRINT_ERROR("qla2x00t: scst_mcmd %p tgt_spec is NULL", mcmd);
++ goto out;
++ }
++
++ ha = mcmd->sess->tgt->ha;
++
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ if (IS_FWI2_CAPABLE(ha)) {
++ if (mcmd->flags == Q24_MGMT_SEND_NACK) {
++ q24_send_notify_ack(ha,
++ &mcmd->orig_iocb.notify_entry24, 0, 0, 0);
++ } else {
++ if (scst_mcmd->fn == SCST_ABORT_TASK)
++ q24_send_abts_resp(ha, &mcmd->orig_iocb.abts,
++ scst_mgmt_cmd_get_status(scst_mcmd),
++ false);
++ else
++ q24_send_task_mgmt_ctio(ha, mcmd,
++ q2t_convert_to_fc_tm_status(
++ scst_mgmt_cmd_get_status(scst_mcmd)));
++ }
++ } else {
++ uint32_t resp_code = q2t_convert_to_fc_tm_status(
++ scst_mgmt_cmd_get_status(scst_mcmd));
++ q2x_send_notify_ack(ha, &mcmd->orig_iocb.notify_entry, 0,
++ resp_code, 1, 0, 0, 0);
++ }
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++ scst_mgmt_cmd_set_tgt_priv(scst_mcmd, NULL);
++ mempool_free(mcmd, q2t_mgmt_cmd_mempool);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* No locks */
++static int q2t_pci_map_calc_cnt(struct q2t_prm *prm)
++{
++ int res = 0;
++
++ BUG_ON(prm->cmd->sg_cnt == 0);
++
++ prm->sg = (struct scatterlist *)prm->cmd->sg;
++ prm->seg_cnt = pci_map_sg(prm->tgt->ha->pdev, prm->cmd->sg,
++ prm->cmd->sg_cnt, prm->cmd->dma_data_direction);
++ if (unlikely(prm->seg_cnt == 0))
++ goto out_err;
++
++ prm->cmd->sg_mapped = 1;
++
++ /*
++ * If greater than four sg entries then we need to allocate
++ * the continuation entries
++ */
++ if (prm->seg_cnt > prm->tgt->datasegs_per_cmd) {
++ prm->req_cnt += (uint16_t)(prm->seg_cnt -
++ prm->tgt->datasegs_per_cmd) /
++ prm->tgt->datasegs_per_cont;
++ if (((uint16_t)(prm->seg_cnt - prm->tgt->datasegs_per_cmd)) %
++ prm->tgt->datasegs_per_cont)
++ prm->req_cnt++;
++ }
++
++out:
++ TRACE_DBG("seg_cnt=%d, req_cnt=%d, res=%d", prm->seg_cnt,
++ prm->req_cnt, res);
++ return res;
++
++out_err:
++ PRINT_ERROR("qla2x00t(%ld): PCI mapping failed: sg_cnt=%d",
++ prm->tgt->ha->instance, prm->cmd->sg_cnt);
++ res = -1;
++ goto out;
++}
++
++static inline void q2t_unmap_sg(scsi_qla_host_t *ha, struct q2t_cmd *cmd)
++{
++ EXTRACHECKS_BUG_ON(!cmd->sg_mapped);
++ pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
++ cmd->sg_mapped = 0;
++}
++
++static int q2t_check_reserve_free_req(scsi_qla_host_t *ha, uint32_t req_cnt)
++{
++ int res = SCST_TGT_RES_SUCCESS;
++ device_reg_t __iomem *reg = ha->iobase;
++ uint32_t cnt;
++
++ TRACE_ENTRY();
++
++ if (ha->req_q_cnt < (req_cnt + 2)) {
++ if (IS_FWI2_CAPABLE(ha))
++ cnt = (uint16_t)RD_REG_DWORD(
++ &reg->isp24.req_q_out);
++ else
++ cnt = qla2x00_debounce_register(
++ ISP_REQ_Q_OUT(ha, &reg->isp));
++ TRACE_DBG("Request ring circled: cnt=%d, "
++ "ha->req_ring_index=%d, ha->req_q_cnt=%d, req_cnt=%d",
++ cnt, ha->req_ring_index, ha->req_q_cnt, req_cnt);
++ if (ha->req_ring_index < cnt)
++ ha->req_q_cnt = cnt - ha->req_ring_index;
++ else
++ ha->req_q_cnt = ha->request_q_length -
++ (ha->req_ring_index - cnt);
++ }
++
++ if (unlikely(ha->req_q_cnt < (req_cnt + 2))) {
++ TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): There is no room in the "
++ "request ring: ha->req_ring_index=%d, ha->req_q_cnt=%d, "
++ "req_cnt=%d", ha->instance, ha->req_ring_index,
++ ha->req_q_cnt, req_cnt);
++ res = SCST_TGT_RES_QUEUE_FULL;
++ goto out;
++ }
++
++ ha->req_q_cnt -= req_cnt;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static inline void *q2t_get_req_pkt(scsi_qla_host_t *ha)
++{
++ /* Adjust ring index. */
++ ha->req_ring_index++;
++ if (ha->req_ring_index == ha->request_q_length) {
++ ha->req_ring_index = 0;
++ ha->request_ring_ptr = ha->request_ring;
++ } else {
++ ha->request_ring_ptr++;
++ }
++ return (cont_entry_t *)ha->request_ring_ptr;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static inline uint32_t q2t_make_handle(scsi_qla_host_t *ha)
++{
++ uint32_t h;
++
++ h = ha->current_handle;
++ /* always increment cmd handle */
++ do {
++ ++h;
++ if (h > MAX_OUTSTANDING_COMMANDS)
++ h = 1; /* 0 is Q2T_NULL_HANDLE */
++ if (h == ha->current_handle) {
++ TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): Ran out of "
++ "empty cmd slots in ha %p", ha->instance, ha);
++ h = Q2T_NULL_HANDLE;
++ break;
++ }
++ } while ((h == Q2T_NULL_HANDLE) ||
++ (h == Q2T_SKIP_HANDLE) ||
++ (ha->cmds[h-1] != NULL));
++
++ if (h != Q2T_NULL_HANDLE)
++ ha->current_handle = h;
++
++ return h;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static void q2x_build_ctio_pkt(struct q2t_prm *prm)
++{
++ uint32_t h;
++ ctio_entry_t *pkt;
++ scsi_qla_host_t *ha = prm->tgt->ha;
++
++ pkt = (ctio_entry_t *)ha->request_ring_ptr;
++ prm->pkt = pkt;
++ memset(pkt, 0, sizeof(*pkt));
++
++ if (prm->tgt->tgt_enable_64bit_addr)
++ pkt->common.entry_type = CTIO_A64_TYPE;
++ else
++ pkt->common.entry_type = CONTINUE_TGT_IO_TYPE;
++
++ pkt->common.entry_count = (uint8_t)prm->req_cnt;
++
++ h = q2t_make_handle(ha);
++ if (h != Q2T_NULL_HANDLE)
++ ha->cmds[h-1] = prm->cmd;
++
++ pkt->common.handle = h | CTIO_COMPLETION_HANDLE_MARK;
++ pkt->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
++
++ /* Set initiator ID */
++ h = GET_TARGET_ID(ha, &prm->cmd->atio.atio2x);
++ SET_TARGET_ID(ha, pkt->common.target, h);
++
++ pkt->common.rx_id = prm->cmd->atio.atio2x.rx_id;
++ pkt->common.relative_offset = cpu_to_le32(prm->cmd->offset);
++
++ TRACE(TRACE_DEBUG|TRACE_SCSI, "qla2x00t(%ld): handle(scst_cmd) -> %08x, "
++ "timeout %d L %#x -> I %#x E %#x", ha->instance,
++ pkt->common.handle, Q2T_TIMEOUT,
++ le16_to_cpu(prm->cmd->atio.atio2x.lun),
++ GET_TARGET_ID(ha, &pkt->common), pkt->common.rx_id);
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q24_build_ctio_pkt(struct q2t_prm *prm)
++{
++ uint32_t h;
++ ctio7_status0_entry_t *pkt;
++ scsi_qla_host_t *ha = prm->tgt->ha;
++ atio7_entry_t *atio = &prm->cmd->atio.atio7;
++ int res = SCST_TGT_RES_SUCCESS;
++
++ TRACE_ENTRY();
++
++ pkt = (ctio7_status0_entry_t *)ha->request_ring_ptr;
++ prm->pkt = pkt;
++ memset(pkt, 0, sizeof(*pkt));
++
++ pkt->common.entry_type = CTIO_TYPE7;
++ pkt->common.entry_count = (uint8_t)prm->req_cnt;
++
++ h = q2t_make_handle(ha);
++ if (unlikely(h == Q2T_NULL_HANDLE)) {
++ /*
++ * CTIO type 7 from the firmware doesn't provide a way to
++ * know the initiator's LOOP ID, hence we can't find
++ * the session and, so, the command.
++ */
++ res = SCST_TGT_RES_QUEUE_FULL;
++ goto out;
++ } else
++ ha->cmds[h-1] = prm->cmd;
++
++ pkt->common.handle = h | CTIO_COMPLETION_HANDLE_MARK;
++ pkt->common.nport_handle = prm->cmd->loop_id;
++ pkt->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
++ pkt->common.initiator_id[0] = atio->fcp_hdr.s_id[2];
++ pkt->common.initiator_id[1] = atio->fcp_hdr.s_id[1];
++ pkt->common.initiator_id[2] = atio->fcp_hdr.s_id[0];
++ pkt->common.exchange_addr = atio->exchange_addr;
++ pkt->flags |= (atio->attr << 9);
++ pkt->ox_id = swab16(atio->fcp_hdr.ox_id);
++ pkt->relative_offset = cpu_to_le32(prm->cmd->offset);
++
++out:
++ TRACE(TRACE_DEBUG|TRACE_SCSI, "qla2x00t(%ld): handle(scst_cmd) -> %08x, "
++ "timeout %d, ox_id %#x", ha->instance, pkt->common.handle,
++ Q2T_TIMEOUT, le16_to_cpu(pkt->ox_id));
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. We have already made sure
++ * that there is sufficient amount of request entries to not drop it.
++ */
++static void q2t_load_cont_data_segments(struct q2t_prm *prm)
++{
++ int cnt;
++ uint32_t *dword_ptr;
++ int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
++
++ TRACE_ENTRY();
++
++ /* Build continuation packets */
++ while (prm->seg_cnt > 0) {
++ cont_a64_entry_t *cont_pkt64 =
++ (cont_a64_entry_t *)q2t_get_req_pkt(prm->tgt->ha);
++
++ /*
++ * Make sure that from cont_pkt64 none of
++ * 64-bit specific fields used for 32-bit
++ * addressing. Cast to (cont_entry_t *) for
++ * that.
++ */
++
++ memset(cont_pkt64, 0, sizeof(*cont_pkt64));
++
++ cont_pkt64->entry_count = 1;
++ cont_pkt64->sys_define = 0;
++
++ if (enable_64bit_addressing) {
++ cont_pkt64->entry_type = CONTINUE_A64_TYPE;
++ dword_ptr =
++ (uint32_t *)&cont_pkt64->dseg_0_address;
++ } else {
++ cont_pkt64->entry_type = CONTINUE_TYPE;
++ dword_ptr =
++ (uint32_t *)&((cont_entry_t *)
++ cont_pkt64)->dseg_0_address;
++ }
++
++ /* Load continuation entry data segments */
++ for (cnt = 0;
++ cnt < prm->tgt->datasegs_per_cont && prm->seg_cnt;
++ cnt++, prm->seg_cnt--) {
++ *dword_ptr++ =
++ cpu_to_le32(pci_dma_lo32
++ (sg_dma_address(prm->sg)));
++ if (enable_64bit_addressing) {
++ *dword_ptr++ =
++ cpu_to_le32(pci_dma_hi32
++ (sg_dma_address
++ (prm->sg)));
++ }
++ *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
++
++ TRACE_SG("S/G Segment Cont. phys_addr=%llx:%llx, len=%d",
++ (long long unsigned int)pci_dma_hi32(sg_dma_address(prm->sg)),
++ (long long unsigned int)pci_dma_lo32(sg_dma_address(prm->sg)),
++ (int)sg_dma_len(prm->sg));
++
++ prm->sg++;
++ }
++
++ TRACE_BUFFER("Continuation packet data",
++ cont_pkt64, REQUEST_ENTRY_SIZE);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. We have already made sure
++ * that there is sufficient amount of request entries to not drop it.
++ */
++static void q2x_load_data_segments(struct q2t_prm *prm)
++{
++ int cnt;
++ uint32_t *dword_ptr;
++ int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
++ ctio_common_entry_t *pkt = (ctio_common_entry_t *)prm->pkt;
++
++ TRACE_DBG("iocb->scsi_status=%x, iocb->flags=%x",
++ le16_to_cpu(pkt->scsi_status), le16_to_cpu(pkt->flags));
++
++ pkt->transfer_length = cpu_to_le32(prm->cmd->bufflen);
++
++ /* Setup packet address segment pointer */
++ dword_ptr = pkt->dseg_0_address;
++
++ if (prm->seg_cnt == 0) {
++ /* No data transfer */
++ *dword_ptr++ = 0;
++ *dword_ptr = 0;
++
++ TRACE_BUFFER("No data, CTIO packet data", pkt,
++ REQUEST_ENTRY_SIZE);
++ goto out;
++ }
++
++ /* Set total data segment count */
++ pkt->dseg_count = cpu_to_le16(prm->seg_cnt);
++
++ /* If scatter gather */
++ TRACE_SG("%s", "Building S/G data segments...");
++ /* Load command entry data segments */
++ for (cnt = 0;
++ (cnt < prm->tgt->datasegs_per_cmd) && prm->seg_cnt;
++ cnt++, prm->seg_cnt--) {
++ *dword_ptr++ =
++ cpu_to_le32(pci_dma_lo32(sg_dma_address(prm->sg)));
++ if (enable_64bit_addressing) {
++ *dword_ptr++ =
++ cpu_to_le32(pci_dma_hi32
++ (sg_dma_address(prm->sg)));
++ }
++ *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
++
++ TRACE_SG("S/G Segment phys_addr=%llx:%llx, len=%d",
++ (long long unsigned int)pci_dma_hi32(sg_dma_address(prm->sg)),
++ (long long unsigned int)pci_dma_lo32(sg_dma_address(prm->sg)),
++ (int)sg_dma_len(prm->sg));
++
++ prm->sg++;
++ }
++
++ TRACE_BUFFER("Scatter/gather, CTIO packet data", pkt,
++ REQUEST_ENTRY_SIZE);
++
++ q2t_load_cont_data_segments(prm);
++
++out:
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. We have already made sure
++ * that there is sufficient amount of request entries to not drop it.
++ */
++static void q24_load_data_segments(struct q2t_prm *prm)
++{
++ int cnt;
++ uint32_t *dword_ptr;
++ int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
++ ctio7_status0_entry_t *pkt = (ctio7_status0_entry_t *)prm->pkt;
++
++ TRACE_DBG("iocb->scsi_status=%x, iocb->flags=%x",
++ le16_to_cpu(pkt->scsi_status), le16_to_cpu(pkt->flags));
++
++ pkt->transfer_length = cpu_to_le32(prm->cmd->bufflen);
++
++ /* Setup packet address segment pointer */
++ dword_ptr = pkt->dseg_0_address;
++
++ if (prm->seg_cnt == 0) {
++ /* No data transfer */
++ *dword_ptr++ = 0;
++ *dword_ptr = 0;
++
++ TRACE_BUFFER("No data, CTIO7 packet data", pkt,
++ REQUEST_ENTRY_SIZE);
++ goto out;
++ }
++
++ /* Set total data segment count */
++ pkt->common.dseg_count = cpu_to_le16(prm->seg_cnt);
++
++ /* If scatter gather */
++ TRACE_SG("%s", "Building S/G data segments...");
++ /* Load command entry data segments */
++ for (cnt = 0;
++ (cnt < prm->tgt->datasegs_per_cmd) && prm->seg_cnt;
++ cnt++, prm->seg_cnt--) {
++ *dword_ptr++ =
++ cpu_to_le32(pci_dma_lo32(sg_dma_address(prm->sg)));
++ if (enable_64bit_addressing) {
++ *dword_ptr++ =
++ cpu_to_le32(pci_dma_hi32(
++ sg_dma_address(prm->sg)));
++ }
++ *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
++
++ TRACE_SG("S/G Segment phys_addr=%llx:%llx, len=%d",
++ (long long unsigned int)pci_dma_hi32(sg_dma_address(
++ prm->sg)),
++ (long long unsigned int)pci_dma_lo32(sg_dma_address(
++ prm->sg)),
++ (int)sg_dma_len(prm->sg));
++
++ prm->sg++;
++ }
++
++ q2t_load_cont_data_segments(prm);
++
++out:
++ return;
++}
++
++static inline int q2t_has_data(struct q2t_cmd *cmd)
++{
++ return cmd->bufflen > 0;
++}
++
++static int q2t_pre_xmit_response(struct q2t_cmd *cmd,
++ struct q2t_prm *prm, int xmit_type, unsigned long *flags)
++{
++ int res;
++ struct q2t_tgt *tgt = cmd->tgt;
++ scsi_qla_host_t *ha = tgt->ha;
++ uint16_t full_req_cnt;
++ struct scst_cmd *scst_cmd = cmd->scst_cmd;
++
++ TRACE_ENTRY();
++
++ if (unlikely(cmd->aborted)) {
++ TRACE_MGMT_DBG("qla2x00t(%ld): terminating exchange "
++ "for aborted cmd=%p (scst_cmd=%p, tag=%d)",
++ ha->instance, cmd, scst_cmd, cmd->tag);
++
++ cmd->state = Q2T_STATE_ABORTED;
++ scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED);
++
++ if (IS_FWI2_CAPABLE(ha))
++ q24_send_term_exchange(ha, cmd, &cmd->atio.atio7, 0);
++ else
++ q2x_send_term_exchange(ha, cmd, &cmd->atio.atio2x, 0);
++ /* !! At this point cmd could be already freed !! */
++ res = Q2T_PRE_XMIT_RESP_CMD_ABORTED;
++ goto out;
++ }
++
++ TRACE(TRACE_SCSI, "qla2x00t(%ld): tag=%lld", ha->instance,
++ scst_cmd_get_tag(scst_cmd));
++
++ prm->cmd = cmd;
++ prm->tgt = tgt;
++ prm->rq_result = scst_cmd_get_status(scst_cmd);
++ prm->sense_buffer = scst_cmd_get_sense_buffer(scst_cmd);
++ prm->sense_buffer_len = scst_cmd_get_sense_buffer_len(scst_cmd);
++ prm->sg = NULL;
++ prm->seg_cnt = -1;
++ prm->req_cnt = 1;
++ prm->add_status_pkt = 0;
++
++ TRACE_DBG("rq_result=%x, xmit_type=%x", prm->rq_result, xmit_type);
++ if (prm->rq_result != 0)
++ TRACE_BUFFER("Sense", prm->sense_buffer, prm->sense_buffer_len);
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, 0) != QLA_SUCCESS) {
++ res = SCST_TGT_RES_FATAL_ERROR;
++ goto out;
++ }
++
++ TRACE_DBG("CTIO start: ha(%d)", (int)ha->instance);
++
++ if ((xmit_type & Q2T_XMIT_DATA) && q2t_has_data(cmd)) {
++ if (q2t_pci_map_calc_cnt(prm) != 0) {
++ res = SCST_TGT_RES_QUEUE_FULL;
++ goto out;
++ }
++ }
++
++ full_req_cnt = prm->req_cnt;
++
++ if (xmit_type & Q2T_XMIT_STATUS) {
++ /* Bidirectional transfers not supported (yet) */
++ if (unlikely(scst_get_resid(scst_cmd, &prm->residual, NULL))) {
++ if (prm->residual > 0) {
++ TRACE_DBG("Residual underflow: %d (tag %lld, "
++ "op %x, bufflen %d, rq_result %x)",
++ prm->residual, scst_cmd->tag,
++ scst_cmd->cdb[0], cmd->bufflen,
++ prm->rq_result);
++ prm->rq_result |= SS_RESIDUAL_UNDER;
++ } else if (prm->residual < 0) {
++ TRACE_DBG("Residual overflow: %d (tag %lld, "
++ "op %x, bufflen %d, rq_result %x)",
++ prm->residual, scst_cmd->tag,
++ scst_cmd->cdb[0], cmd->bufflen,
++ prm->rq_result);
++ prm->rq_result |= SS_RESIDUAL_OVER;
++ prm->residual = -prm->residual;
++ }
++ }
++
++ /*
++ * If Q2T_XMIT_DATA is not set, add_status_pkt will be ignored
++ * in *xmit_response() below
++ */
++ if (q2t_has_data(cmd)) {
++ if (SCST_SENSE_VALID(prm->sense_buffer) ||
++ (IS_FWI2_CAPABLE(ha) &&
++ (prm->rq_result != 0))) {
++ prm->add_status_pkt = 1;
++ full_req_cnt++;
++ }
++ }
++ }
++
++ TRACE_DBG("req_cnt=%d, full_req_cnt=%d, add_status_pkt=%d",
++ prm->req_cnt, full_req_cnt, prm->add_status_pkt);
++
++ /* Acquire ring specific lock */
++ spin_lock_irqsave(&ha->hardware_lock, *flags);
++
++ /* Does F/W have an IOCBs for this request */
++ res = q2t_check_reserve_free_req(ha, full_req_cnt);
++ if (unlikely(res != SCST_TGT_RES_SUCCESS) &&
++ (xmit_type & Q2T_XMIT_DATA))
++ goto out_unlock_free_unmap;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unlock_free_unmap:
++ if (cmd->sg_mapped)
++ q2t_unmap_sg(ha, cmd);
++
++ /* Release ring specific lock */
++ spin_unlock_irqrestore(&ha->hardware_lock, *flags);
++ goto out;
++}
++
++static inline int q2t_need_explicit_conf(scsi_qla_host_t *ha,
++ struct q2t_cmd *cmd, int sending_sense)
++{
++ if (ha->enable_class_2)
++ return 0;
++
++ if (sending_sense)
++ return cmd->conf_compl_supported;
++ else
++ return ha->enable_explicit_conf && cmd->conf_compl_supported;
++}
++
++static void q2x_init_ctio_ret_entry(ctio_ret_entry_t *ctio_m1,
++ struct q2t_prm *prm)
++{
++ TRACE_ENTRY();
++
++ prm->sense_buffer_len = min((uint32_t)prm->sense_buffer_len,
++ (uint32_t)sizeof(ctio_m1->sense_data));
++
++ ctio_m1->flags = __constant_cpu_to_le16(OF_SSTS | OF_FAST_POST |
++ OF_NO_DATA | OF_SS_MODE_1);
++ ctio_m1->flags |= __constant_cpu_to_le16(OF_INC_RC);
++ if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) {
++ ctio_m1->flags |= __constant_cpu_to_le16(OF_EXPL_CONF |
++ OF_CONF_REQ);
++ }
++ ctio_m1->scsi_status = cpu_to_le16(prm->rq_result);
++ ctio_m1->residual = cpu_to_le32(prm->residual);
++ if (SCST_SENSE_VALID(prm->sense_buffer)) {
++ if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) {
++ ctio_m1->flags |= __constant_cpu_to_le16(OF_EXPL_CONF |
++ OF_CONF_REQ);
++ }
++ ctio_m1->scsi_status |= __constant_cpu_to_le16(
++ SS_SENSE_LEN_VALID);
++ ctio_m1->sense_length = cpu_to_le16(prm->sense_buffer_len);
++ memcpy(ctio_m1->sense_data, prm->sense_buffer,
++ prm->sense_buffer_len);
++ } else {
++ memset(ctio_m1->sense_data, 0, sizeof(ctio_m1->sense_data));
++ ctio_m1->sense_length = 0;
++ }
++
++ /* Sense with len > 26, is it possible ??? */
++
++ TRACE_EXIT();
++ return;
++}
++
++static int __q2x_xmit_response(struct q2t_cmd *cmd, int xmit_type)
++{
++ int res;
++ unsigned long flags;
++ scsi_qla_host_t *ha;
++ struct q2t_prm prm;
++ ctio_common_entry_t *pkt;
++
++ TRACE_ENTRY();
++
++ memset(&prm, 0, sizeof(prm));
++
++ res = q2t_pre_xmit_response(cmd, &prm, xmit_type, &flags);
++ if (unlikely(res != SCST_TGT_RES_SUCCESS)) {
++ if (res == Q2T_PRE_XMIT_RESP_CMD_ABORTED)
++ res = SCST_TGT_RES_SUCCESS;
++ goto out;
++ }
++
++ /* Here ha->hardware_lock already locked */
++
++ ha = prm.tgt->ha;
++
++ q2x_build_ctio_pkt(&prm);
++ pkt = (ctio_common_entry_t *)prm.pkt;
++
++ if (q2t_has_data(cmd) && (xmit_type & Q2T_XMIT_DATA)) {
++ pkt->flags |= __constant_cpu_to_le16(OF_FAST_POST | OF_DATA_IN);
++ pkt->flags |= __constant_cpu_to_le16(OF_INC_RC);
++
++ q2x_load_data_segments(&prm);
++
++ if (prm.add_status_pkt == 0) {
++ if (xmit_type & Q2T_XMIT_STATUS) {
++ pkt->scsi_status = cpu_to_le16(prm.rq_result);
++ pkt->residual = cpu_to_le32(prm.residual);
++ pkt->flags |= __constant_cpu_to_le16(OF_SSTS);
++ if (q2t_need_explicit_conf(ha, cmd, 0)) {
++ pkt->flags |= __constant_cpu_to_le16(
++ OF_EXPL_CONF |
++ OF_CONF_REQ);
++ }
++ }
++ } else {
++ /*
++ * We have already made sure that there is sufficient
++ * amount of request entries to not drop HW lock in
++ * req_pkt().
++ */
++ ctio_ret_entry_t *ctio_m1 =
++ (ctio_ret_entry_t *)q2t_get_req_pkt(ha);
++
++ TRACE_DBG("%s", "Building additional status packet");
++
++ memcpy(ctio_m1, pkt, sizeof(*ctio_m1));
++ ctio_m1->entry_count = 1;
++ ctio_m1->dseg_count = 0;
++
++ /* Real finish is ctio_m1's finish */
++ pkt->handle |= CTIO_INTERMEDIATE_HANDLE_MARK;
++ pkt->flags &= ~__constant_cpu_to_le16(OF_INC_RC);
++
++ q2x_init_ctio_ret_entry(ctio_m1, &prm);
++ TRACE_BUFFER("Status CTIO packet data", ctio_m1,
++ REQUEST_ENTRY_SIZE);
++ }
++ } else
++ q2x_init_ctio_ret_entry((ctio_ret_entry_t *)pkt, &prm);
++
++ cmd->state = Q2T_STATE_PROCESSED; /* Mid-level is done processing */
++
++ TRACE_BUFFER("Xmitting", pkt, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++ /* Release ring specific lock */
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++#ifdef CONFIG_QLA_TGT_DEBUG_SRR
++static void q2t_check_srr_debug(struct q2t_cmd *cmd, int *xmit_type)
++{
++#if 0 /* This is not a real status packets lost, so it won't lead to SRR */
++ if ((*xmit_type & Q2T_XMIT_STATUS) && (scst_random() % 200) == 50) {
++ *xmit_type &= ~Q2T_XMIT_STATUS;
++ TRACE_MGMT_DBG("Dropping cmd %p (tag %d) status", cmd,
++ cmd->tag);
++ }
++#endif
++
++ if (q2t_has_data(cmd) && (cmd->sg_cnt > 1) &&
++ ((scst_random() % 100) == 20)) {
++ int i, leave = 0;
++ unsigned int tot_len = 0;
++
++ while (leave == 0)
++ leave = scst_random() % cmd->sg_cnt;
++
++ for (i = 0; i < leave; i++)
++ tot_len += cmd->sg[i].length;
++
++ TRACE_MGMT_DBG("Cutting cmd %p (tag %d) buffer tail to len %d, "
++ "sg_cnt %d (cmd->bufflen %d, cmd->sg_cnt %d)", cmd,
++ cmd->tag, tot_len, leave, cmd->bufflen, cmd->sg_cnt);
++
++ cmd->bufflen = tot_len;
++ cmd->sg_cnt = leave;
++ }
++
++ if (q2t_has_data(cmd) && ((scst_random() % 100) == 70)) {
++ unsigned int offset = scst_random() % cmd->bufflen;
++
++ TRACE_MGMT_DBG("Cutting cmd %p (tag %d) buffer head "
++ "to offset %d (cmd->bufflen %d)", cmd, cmd->tag,
++ offset, cmd->bufflen);
++ if (offset == 0)
++ *xmit_type &= ~Q2T_XMIT_DATA;
++ else if (q2t_cut_cmd_data_head(cmd, offset)) {
++ TRACE_MGMT_DBG("q2t_cut_cmd_data_head() failed (tag %d)",
++ cmd->tag);
++ }
++ }
++}
++#else
++static inline void q2t_check_srr_debug(struct q2t_cmd *cmd, int *xmit_type) {}
++#endif
++
++static int q2x_xmit_response(struct scst_cmd *scst_cmd)
++{
++ int xmit_type = Q2T_XMIT_DATA, res;
++ int is_send_status = scst_cmd_get_is_send_status(scst_cmd);
++ struct q2t_cmd *cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ BUG_ON(!q2t_has_data(cmd) && !is_send_status);
++#endif
++
++#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
++ EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
++#endif
++
++ if (is_send_status)
++ xmit_type |= Q2T_XMIT_STATUS;
++
++ cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(scst_cmd);
++ cmd->sg = scst_cmd_get_sg(scst_cmd);
++ cmd->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
++ cmd->data_direction = scst_cmd_get_data_direction(scst_cmd);
++ cmd->dma_data_direction = scst_to_tgt_dma_dir(cmd->data_direction);
++ cmd->offset = scst_cmd_get_ppl_offset(scst_cmd);
++ cmd->aborted = scst_cmd_aborted(scst_cmd);
++
++ q2t_check_srr_debug(cmd, &xmit_type);
++
++ TRACE_DBG("is_send_status=%x, cmd->bufflen=%d, cmd->sg_cnt=%d, "
++ "cmd->data_direction=%d", is_send_status, cmd->bufflen,
++ cmd->sg_cnt, cmd->data_direction);
++
++ if (IS_FWI2_CAPABLE(cmd->tgt->ha))
++ res = __q24_xmit_response(cmd, xmit_type);
++ else
++ res = __q2x_xmit_response(cmd, xmit_type);
++
++ return res;
++}
++
++static void q24_init_ctio_ret_entry(ctio7_status0_entry_t *ctio,
++ struct q2t_prm *prm)
++{
++ ctio7_status1_entry_t *ctio1;
++
++ TRACE_ENTRY();
++
++ prm->sense_buffer_len = min((uint32_t)prm->sense_buffer_len,
++ (uint32_t)sizeof(ctio1->sense_data));
++ ctio->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_SEND_STATUS);
++ if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) {
++ ctio->flags |= __constant_cpu_to_le16(
++ CTIO7_FLAGS_EXPLICIT_CONFORM |
++ CTIO7_FLAGS_CONFORM_REQ);
++ }
++ ctio->residual = cpu_to_le32(prm->residual);
++ ctio->scsi_status = cpu_to_le16(prm->rq_result);
++ if (SCST_SENSE_VALID(prm->sense_buffer)) {
++ int i;
++ ctio1 = (ctio7_status1_entry_t *)ctio;
++ if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) {
++ ctio1->flags |= __constant_cpu_to_le16(
++ CTIO7_FLAGS_EXPLICIT_CONFORM |
++ CTIO7_FLAGS_CONFORM_REQ);
++ }
++ ctio1->flags &= ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
++ ctio1->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1);
++ ctio1->scsi_status |= __constant_cpu_to_le16(SS_SENSE_LEN_VALID);
++ ctio1->sense_length = cpu_to_le16(prm->sense_buffer_len);
++ for (i = 0; i < prm->sense_buffer_len/4; i++)
++ ((uint32_t *)ctio1->sense_data)[i] =
++ cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]);
++#if 0
++ if (unlikely((prm->sense_buffer_len % 4) != 0)) {
++ static int q;
++ if (q < 10) {
++ PRINT_INFO("qla2x00t(%ld): %d bytes of sense "
++ "lost", prm->tgt->ha->instance,
++ prm->sense_buffer_len % 4);
++ q++;
++ }
++ }
++#endif
++ } else {
++ ctio1 = (ctio7_status1_entry_t *)ctio;
++ ctio1->flags &= ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
++ ctio1->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1);
++ ctio1->sense_length = 0;
++ memset(ctio1->sense_data, 0, sizeof(ctio1->sense_data));
++ }
++
++ /* Sense with len > 24, is it possible ??? */
++
++ TRACE_EXIT();
++ return;
++}
++
++static int __q24_xmit_response(struct q2t_cmd *cmd, int xmit_type)
++{
++ int res;
++ unsigned long flags;
++ scsi_qla_host_t *ha;
++ struct q2t_prm prm;
++ ctio7_status0_entry_t *pkt;
++
++ TRACE_ENTRY();
++
++ memset(&prm, 0, sizeof(prm));
++
++ res = q2t_pre_xmit_response(cmd, &prm, xmit_type, &flags);
++ if (unlikely(res != SCST_TGT_RES_SUCCESS)) {
++ if (res == Q2T_PRE_XMIT_RESP_CMD_ABORTED)
++ res = SCST_TGT_RES_SUCCESS;
++ goto out;
++ }
++
++ /* Here ha->hardware_lock already locked */
++
++ ha = prm.tgt->ha;
++
++ res = q24_build_ctio_pkt(&prm);
++ if (unlikely(res != SCST_TGT_RES_SUCCESS))
++ goto out_unmap_unlock;
++
++ pkt = (ctio7_status0_entry_t *)prm.pkt;
++
++ if (q2t_has_data(cmd) && (xmit_type & Q2T_XMIT_DATA)) {
++ pkt->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_IN |
++ CTIO7_FLAGS_STATUS_MODE_0);
++
++ q24_load_data_segments(&prm);
++
++ if (prm.add_status_pkt == 0) {
++ if (xmit_type & Q2T_XMIT_STATUS) {
++ pkt->scsi_status = cpu_to_le16(prm.rq_result);
++ pkt->residual = cpu_to_le32(prm.residual);
++ pkt->flags |= __constant_cpu_to_le16(
++ CTIO7_FLAGS_SEND_STATUS);
++ if (q2t_need_explicit_conf(ha, cmd, 0)) {
++ pkt->flags |= __constant_cpu_to_le16(
++ CTIO7_FLAGS_EXPLICIT_CONFORM |
++ CTIO7_FLAGS_CONFORM_REQ);
++ }
++ }
++ } else {
++ /*
++ * We have already made sure that there is sufficient
++ * amount of request entries to not drop HW lock in
++ * req_pkt().
++ */
++ ctio7_status1_entry_t *ctio =
++ (ctio7_status1_entry_t *)q2t_get_req_pkt(ha);
++
++ TRACE_DBG("%s", "Building additional status packet");
++
++ memcpy(ctio, pkt, sizeof(*ctio));
++ ctio->common.entry_count = 1;
++ ctio->common.dseg_count = 0;
++ ctio->flags &= ~__constant_cpu_to_le16(
++ CTIO7_FLAGS_DATA_IN);
++
++ /* Real finish is ctio_m1's finish */
++ pkt->common.handle |= CTIO_INTERMEDIATE_HANDLE_MARK;
++ pkt->flags |= __constant_cpu_to_le16(
++ CTIO7_FLAGS_DONT_RET_CTIO);
++ q24_init_ctio_ret_entry((ctio7_status0_entry_t *)ctio,
++ &prm);
++ TRACE_BUFFER("Status CTIO7", ctio, REQUEST_ENTRY_SIZE);
++ }
++ } else
++ q24_init_ctio_ret_entry(pkt, &prm);
++
++ cmd->state = Q2T_STATE_PROCESSED; /* Mid-level is done processing */
++
++ TRACE_BUFFER("Xmitting CTIO7", pkt, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out_unlock:
++ /* Release ring specific lock */
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unmap_unlock:
++ if (cmd->sg_mapped)
++ q2t_unmap_sg(ha, cmd);
++ goto out_unlock;
++}
++
++static int __q2t_rdy_to_xfer(struct q2t_cmd *cmd)
++{
++ int res = SCST_TGT_RES_SUCCESS;
++ unsigned long flags;
++ scsi_qla_host_t *ha;
++ struct q2t_tgt *tgt = cmd->tgt;
++ struct q2t_prm prm;
++ void *p;
++
++ TRACE_ENTRY();
++
++ memset(&prm, 0, sizeof(prm));
++ prm.cmd = cmd;
++ prm.tgt = tgt;
++ prm.sg = NULL;
++ prm.req_cnt = 1;
++ ha = tgt->ha;
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, 0) != QLA_SUCCESS) {
++ res = SCST_TGT_RES_FATAL_ERROR;
++ goto out;
++ }
++
++ TRACE_DBG("CTIO_start: ha(%d)", (int)ha->instance);
++
++ /* Calculate number of entries and segments required */
++ if (q2t_pci_map_calc_cnt(&prm) != 0) {
++ res = SCST_TGT_RES_QUEUE_FULL;
++ goto out;
++ }
++
++ /* Acquire ring specific lock */
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++
++ /* Does F/W have an IOCBs for this request */
++ res = q2t_check_reserve_free_req(ha, prm.req_cnt);
++ if (res != SCST_TGT_RES_SUCCESS)
++ goto out_unlock_free_unmap;
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ ctio7_status0_entry_t *pkt;
++ res = q24_build_ctio_pkt(&prm);
++ if (unlikely(res != SCST_TGT_RES_SUCCESS))
++ goto out_unlock_free_unmap;
++ pkt = (ctio7_status0_entry_t *)prm.pkt;
++ pkt->flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT |
++ CTIO7_FLAGS_STATUS_MODE_0);
++ q24_load_data_segments(&prm);
++ p = pkt;
++ } else {
++ ctio_common_entry_t *pkt;
++ q2x_build_ctio_pkt(&prm);
++ pkt = (ctio_common_entry_t *)prm.pkt;
++ pkt->flags = __constant_cpu_to_le16(OF_FAST_POST | OF_DATA_OUT);
++ q2x_load_data_segments(&prm);
++ p = pkt;
++ }
++
++ cmd->state = Q2T_STATE_NEED_DATA;
++
++ TRACE_BUFFER("Xfering", p, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out_unlock:
++ /* Release ring specific lock */
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_unlock_free_unmap:
++ if (cmd->sg_mapped)
++ q2t_unmap_sg(ha, cmd);
++ goto out_unlock;
++}
++
++static int q2t_rdy_to_xfer(struct scst_cmd *scst_cmd)
++{
++ int res;
++ struct q2t_cmd *cmd;
++
++ TRACE_ENTRY();
++
++ TRACE(TRACE_SCSI, "qla2x00t: tag=%lld", scst_cmd_get_tag(scst_cmd));
++
++ cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
++ cmd->bufflen = scst_cmd_get_write_fields(scst_cmd, &cmd->sg,
++ &cmd->sg_cnt);
++ cmd->data_direction = scst_cmd_get_data_direction(scst_cmd);
++ cmd->dma_data_direction = scst_to_tgt_dma_dir(cmd->data_direction);
++
++ res = __q2t_rdy_to_xfer(cmd);
++
++ TRACE_EXIT();
++ return res;
++}
++
++/* If hardware_lock held on entry, might drop it, then reaquire */
++static void q2x_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
++ atio_entry_t *atio, int ha_locked)
++{
++ ctio_ret_entry_t *ctio;
++ unsigned long flags = 0; /* to stop compiler's warning */
++ int do_tgt_cmd_done = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending TERM EXCH CTIO (ha=%p)", ha);
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, ha_locked) != QLA_SUCCESS)
++ goto out;
++
++ if (!ha_locked)
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++
++ ctio = (ctio_ret_entry_t *)qla2x00_req_pkt(ha);
++ if (ctio == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out_unlock;
++ }
++
++ ctio->entry_type = CTIO_RET_TYPE;
++ ctio->entry_count = 1;
++ if (cmd != NULL) {
++ if (cmd->state < Q2T_STATE_PROCESSED) {
++ PRINT_ERROR("qla2x00t(%ld): Terminating cmd %p with "
++ "incorrect state %d", ha->instance, cmd,
++ cmd->state);
++ } else
++ do_tgt_cmd_done = 1;
++ }
++ ctio->handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
++
++ /* Set IDs */
++ SET_TARGET_ID(ha, ctio->target, GET_TARGET_ID(ha, atio));
++ ctio->rx_id = atio->rx_id;
++
++ /* Most likely, it isn't needed */
++ ctio->residual = atio->data_length;
++ if (ctio->residual != 0)
++ ctio->scsi_status |= SS_RESIDUAL_UNDER;
++
++ ctio->flags = __constant_cpu_to_le16(OF_FAST_POST | OF_TERM_EXCH |
++ OF_NO_DATA | OF_SS_MODE_1);
++ ctio->flags |= __constant_cpu_to_le16(OF_INC_RC);
++
++ TRACE_BUFFER("CTIO TERM EXCH packet data", ctio, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out_unlock:
++ if (!ha_locked)
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++ if (do_tgt_cmd_done) {
++ if (!ha_locked && !in_interrupt()) {
++ msleep(250); /* just in case */
++ scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_DIRECT);
++ } else
++ scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_TASKLET);
++ /* !! At this point cmd could be already freed !! */
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* If hardware_lock held on entry, might drop it, then reaquire */
++static void q24_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
++ atio7_entry_t *atio, int ha_locked)
++{
++ ctio7_status1_entry_t *ctio;
++ unsigned long flags = 0; /* to stop compiler's warning */
++ int do_tgt_cmd_done = 0;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Sending TERM EXCH CTIO7 (ha=%p)", ha);
++
++ /* Send marker if required */
++ if (q2t_issue_marker(ha, ha_locked) != QLA_SUCCESS)
++ goto out;
++
++ if (!ha_locked)
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++
++ ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
++ if (ctio == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out_unlock;
++ }
++
++ ctio->common.entry_type = CTIO_TYPE7;
++ ctio->common.entry_count = 1;
++ if (cmd != NULL) {
++ ctio->common.nport_handle = cmd->loop_id;
++ if (cmd->state < Q2T_STATE_PROCESSED) {
++ PRINT_ERROR("qla2x00t(%ld): Terminating cmd %p with "
++ "incorrect state %d", ha->instance, cmd,
++ cmd->state);
++ } else
++ do_tgt_cmd_done = 1;
++ } else
++ ctio->common.nport_handle = CTIO7_NHANDLE_UNRECOGNIZED;
++ ctio->common.handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
++ ctio->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
++ ctio->common.initiator_id[0] = atio->fcp_hdr.s_id[2];
++ ctio->common.initiator_id[1] = atio->fcp_hdr.s_id[1];
++ ctio->common.initiator_id[2] = atio->fcp_hdr.s_id[0];
++ ctio->common.exchange_addr = atio->exchange_addr;
++ ctio->flags = (atio->attr << 9) | __constant_cpu_to_le16(
++ CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_TERMINATE);
++ ctio->ox_id = swab16(atio->fcp_hdr.ox_id);
++
++ /* Most likely, it isn't needed */
++ ctio->residual = atio->fcp_cmnd.data_length;
++ if (ctio->residual != 0)
++ ctio->scsi_status |= SS_RESIDUAL_UNDER;
++
++ TRACE_BUFFER("CTIO7 TERM EXCH packet data", ctio, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out_unlock:
++ if (!ha_locked)
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++ if (do_tgt_cmd_done) {
++ if (!ha_locked && !in_interrupt()) {
++ msleep(250); /* just in case */
++ scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_DIRECT);
++ } else
++ scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_TASKLET);
++ /* !! At this point cmd could be already freed !! */
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static inline void q2t_free_cmd(struct q2t_cmd *cmd)
++{
++ EXTRACHECKS_BUG_ON(cmd->sg_mapped);
++
++ if (unlikely(cmd->free_sg))
++ kfree(cmd->sg);
++ kmem_cache_free(q2t_cmd_cachep, cmd);
++}
++
++static void q2t_on_free_cmd(struct scst_cmd *scst_cmd)
++{
++ struct q2t_cmd *cmd;
++
++ TRACE_ENTRY();
++
++ TRACE(TRACE_SCSI, "qla2x00t: Freeing command %p, tag %lld",
++ scst_cmd, scst_cmd_get_tag(scst_cmd));
++
++ cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
++ scst_cmd_set_tgt_priv(scst_cmd, NULL);
++
++ q2t_free_cmd(cmd);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q2t_prepare_srr_ctio(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
++ void *ctio)
++{
++ struct srr_ctio *sc;
++ struct q2t_tgt *tgt = ha->tgt;
++ int res = 0;
++ struct srr_imm *imm;
++
++ tgt->ctio_srr_id++;
++
++ TRACE_MGMT_DBG("qla2x00t(%ld): CTIO with SRR "
++ "status received", ha->instance);
++
++ if (ctio == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): SRR CTIO, "
++ "but ctio is NULL", ha->instance);
++ res = -EINVAL;
++ goto out;
++ }
++
++ if (cmd->scst_cmd != NULL)
++ scst_update_hw_pending_start(cmd->scst_cmd);
++
++ sc = kzalloc(sizeof(*sc), GFP_ATOMIC);
++ if (sc != NULL) {
++ sc->cmd = cmd;
++ /* IRQ is already OFF */
++ spin_lock(&tgt->srr_lock);
++ sc->srr_id = tgt->ctio_srr_id;
++ list_add_tail(&sc->srr_list_entry,
++ &tgt->srr_ctio_list);
++ TRACE_MGMT_DBG("CTIO SRR %p added (id %d)",
++ sc, sc->srr_id);
++ if (tgt->imm_srr_id == tgt->ctio_srr_id) {
++ int found = 0;
++ list_for_each_entry(imm, &tgt->srr_imm_list,
++ srr_list_entry) {
++ if (imm->srr_id == sc->srr_id) {
++ found = 1;
++ break;
++ }
++ }
++ if (found) {
++ TRACE_MGMT_DBG("%s", "Scheduling srr work");
++ schedule_work(&tgt->srr_work);
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): imm_srr_id "
++ "== ctio_srr_id (%d), but there is no "
++ "corresponding SRR IMM, deleting CTIO "
++ "SRR %p", ha->instance, tgt->ctio_srr_id,
++ sc);
++ list_del(&sc->srr_list_entry);
++ spin_unlock(&tgt->srr_lock);
++
++ kfree(sc);
++ res = -EINVAL;
++ goto out;
++ }
++ }
++ spin_unlock(&tgt->srr_lock);
++ } else {
++ struct srr_imm *ti;
++ PRINT_ERROR("qla2x00t(%ld): Unable to allocate SRR CTIO entry",
++ ha->instance);
++ spin_lock(&tgt->srr_lock);
++ list_for_each_entry_safe(imm, ti, &tgt->srr_imm_list,
++ srr_list_entry) {
++ if (imm->srr_id == tgt->ctio_srr_id) {
++ TRACE_MGMT_DBG("IMM SRR %p deleted "
++ "(id %d)", imm, imm->srr_id);
++ list_del(&imm->srr_list_entry);
++ q2t_reject_free_srr_imm(ha, imm, 1);
++ }
++ }
++ spin_unlock(&tgt->srr_lock);
++ res = -ENOMEM;
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static int q2t_term_ctio_exchange(scsi_qla_host_t *ha, void *ctio,
++ struct q2t_cmd *cmd, uint32_t status)
++{
++ int term = 0;
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ if (ctio != NULL) {
++ ctio7_fw_entry_t *c = (ctio7_fw_entry_t *)ctio;
++ term = !(c->flags &
++ __constant_cpu_to_le16(OF_TERM_EXCH));
++ } else
++ term = 1;
++ if (term) {
++ q24_send_term_exchange(ha, cmd,
++ &cmd->atio.atio7, 1);
++ }
++ } else {
++ if (status != CTIO_SUCCESS)
++ q2x_modify_command_count(ha, 1, 0);
++#if 0 /* seems, it isn't needed */
++ if (ctio != NULL) {
++ ctio_common_entry_t *c = (ctio_common_entry_t *)ctio;
++ term = !(c->flags &
++ __constant_cpu_to_le16(
++ CTIO7_FLAGS_TERMINATE));
++ } else
++ term = 1;
++ if (term) {
++ q2x_send_term_exchange(ha, cmd,
++ &cmd->atio.atio2x, 1);
++ }
++#endif
++ }
++ return term;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static inline struct q2t_cmd *q2t_get_cmd(scsi_qla_host_t *ha, uint32_t handle)
++{
++ handle--;
++ if (ha->cmds[handle] != NULL) {
++ struct q2t_cmd *cmd = ha->cmds[handle];
++ ha->cmds[handle] = NULL;
++ return cmd;
++ } else
++ return NULL;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static struct q2t_cmd *q2t_ctio_to_cmd(scsi_qla_host_t *ha, uint32_t handle,
++ void *ctio)
++{
++ struct q2t_cmd *cmd = NULL;
++
++ /* Clear out internal marks */
++ handle &= ~(CTIO_COMPLETION_HANDLE_MARK | CTIO_INTERMEDIATE_HANDLE_MARK);
++
++ if (handle != Q2T_NULL_HANDLE) {
++ if (unlikely(handle == Q2T_SKIP_HANDLE)) {
++ TRACE_DBG("%s", "SKIP_HANDLE CTIO");
++ goto out;
++ }
++ /* handle-1 is actually used */
++ if (unlikely(handle > MAX_OUTSTANDING_COMMANDS)) {
++ PRINT_ERROR("qla2x00t(%ld): Wrong handle %x "
++ "received", ha->instance, handle);
++ goto out;
++ }
++ cmd = q2t_get_cmd(ha, handle);
++ if (unlikely(cmd == NULL)) {
++ PRINT_WARNING("qla2x00t(%ld): Suspicious: unable to "
++ "find the command with handle %x",
++ ha->instance, handle);
++ goto out;
++ }
++ } else if (ctio != NULL) {
++ uint16_t loop_id;
++ int tag;
++ struct q2t_sess *sess;
++ struct scst_cmd *scst_cmd;
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ /* We can't get loop ID from CTIO7 */
++ PRINT_ERROR("qla2x00t(%ld): Wrong CTIO received: "
++ "QLA24xx doesn't support NULL handles",
++ ha->instance);
++ goto out;
++ } else {
++ ctio_common_entry_t *c = (ctio_common_entry_t *)ctio;
++ loop_id = GET_TARGET_ID(ha, c);
++ tag = c->rx_id;
++ }
++
++ sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id);
++ if (sess == NULL) {
++ PRINT_WARNING("qla2x00t(%ld): Suspicious: "
++ "ctio_completion for non-existing session "
++ "(loop_id %d, tag %d)",
++ ha->instance, loop_id, tag);
++ goto out;
++ }
++
++ scst_cmd = scst_find_cmd_by_tag(sess->scst_sess, tag);
++ if (scst_cmd == NULL) {
++ PRINT_WARNING("qla2x00t(%ld): Suspicious: unable to "
++ "find the command with tag %d (loop_id %d)",
++ ha->instance, tag, loop_id);
++ goto out;
++ }
++
++ cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
++ TRACE_DBG("Found q2t_cmd %p (tag %d)", cmd, tag);
++ }
++
++out:
++ return cmd;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
++ uint32_t status, void *ctio)
++{
++ struct scst_cmd *scst_cmd;
++ struct q2t_cmd *cmd;
++ enum scst_exec_context context;
++
++ TRACE_ENTRY();
++
++#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
++ context = SCST_CONTEXT_THREAD;
++#else
++ context = SCST_CONTEXT_TASKLET;
++#endif
++
++ TRACE(TRACE_DEBUG|TRACE_SCSI, "qla2x00t(%ld): handle(ctio %p "
++ "status %#x) <- %08x", ha->instance, ctio, status, handle);
++
++ if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) {
++ /* That could happen only in case of an error/reset/abort */
++ if (status != CTIO_SUCCESS) {
++ TRACE_MGMT_DBG("Intermediate CTIO received (status %x)",
++ status);
++ }
++ goto out;
++ }
++
++ cmd = q2t_ctio_to_cmd(ha, handle, ctio);
++ if (cmd == NULL) {
++ if (status != CTIO_SUCCESS)
++ q2t_term_ctio_exchange(ha, ctio, NULL, status);
++ goto out;
++ }
++
++ scst_cmd = cmd->scst_cmd;
++
++ if (cmd->sg_mapped)
++ q2t_unmap_sg(ha, cmd);
++
++ if (unlikely(status != CTIO_SUCCESS)) {
++ switch (status & 0xFFFF) {
++ case CTIO_LIP_RESET:
++ case CTIO_TARGET_RESET:
++ case CTIO_ABORTED:
++ case CTIO_TIMEOUT:
++ case CTIO_INVALID_RX_ID:
++ /* They are OK */
++ TRACE(TRACE_MINOR_AND_MGMT_DBG,
++ "qla2x00t(%ld): CTIO with "
++ "status %#x received, state %x, scst_cmd %p, "
++ "op %x (LIP_RESET=e, ABORTED=2, TARGET_RESET=17, "
++ "TIMEOUT=b, INVALID_RX_ID=8)", ha->instance,
++ status, cmd->state, scst_cmd, scst_cmd->cdb[0]);
++ break;
++
++ case CTIO_PORT_LOGGED_OUT:
++ case CTIO_PORT_UNAVAILABLE:
++ PRINT_INFO("qla2x00t(%ld): CTIO with PORT LOGGED "
++ "OUT (29) or PORT UNAVAILABLE (28) status %x "
++ "received (state %x, scst_cmd %p, op %x)",
++ ha->instance, status, cmd->state, scst_cmd,
++ scst_cmd->cdb[0]);
++ break;
++
++ case CTIO_SRR_RECEIVED:
++ if (q2t_prepare_srr_ctio(ha, cmd, ctio) != 0)
++ break;
++ else
++ goto out;
++
++ default:
++ PRINT_ERROR("qla2x00t(%ld): CTIO with error status "
++ "0x%x received (state %x, scst_cmd %p, op %x)",
++ ha->instance, status, cmd->state, scst_cmd,
++ scst_cmd->cdb[0]);
++ break;
++ }
++
++ if (cmd->state != Q2T_STATE_NEED_DATA)
++ if (q2t_term_ctio_exchange(ha, ctio, cmd, status))
++ goto out;
++ }
++
++ if (cmd->state == Q2T_STATE_PROCESSED) {
++ TRACE_DBG("Command %p finished", cmd);
++ } else if (cmd->state == Q2T_STATE_NEED_DATA) {
++ int rx_status = SCST_RX_STATUS_SUCCESS;
++
++ cmd->state = Q2T_STATE_DATA_IN;
++
++ if (unlikely(status != CTIO_SUCCESS))
++ rx_status = SCST_RX_STATUS_ERROR;
++ else
++ cmd->write_data_transferred = 1;
++
++ TRACE_DBG("Data received, context %x, rx_status %d",
++ context, rx_status);
++
++ scst_rx_data(scst_cmd, rx_status, context);
++ goto out;
++ } else if (cmd->state == Q2T_STATE_ABORTED) {
++ TRACE_MGMT_DBG("Aborted command %p (tag %d) finished", cmd,
++ cmd->tag);
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): A command in state (%d) should "
++ "not return a CTIO complete", ha->instance, cmd->state);
++ }
++
++ if (unlikely(status != CTIO_SUCCESS)) {
++ TRACE_MGMT_DBG("%s", "Finishing failed CTIO");
++ scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED);
++ }
++
++ scst_tgt_cmd_done(scst_cmd, context);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++/* called via callback from qla2xxx */
++static void q2x_ctio_completion(scsi_qla_host_t *ha, uint32_t handle)
++{
++ struct q2t_tgt *tgt = ha->tgt;
++
++ TRACE_ENTRY();
++
++ if (likely(tgt != NULL)) {
++ tgt->irq_cmd_count++;
++ q2t_do_ctio_completion(ha, handle, CTIO_SUCCESS, NULL);
++ tgt->irq_cmd_count--;
++ } else {
++ TRACE_DBG("CTIO, but target mode not enabled (ha %p handle "
++ "%#x)", ha, handle);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/* ha->hardware_lock is supposed to be held on entry */
++static int q2x_do_send_cmd_to_scst(struct q2t_cmd *cmd)
++{
++ int res = 0;
++ struct q2t_sess *sess = cmd->sess;
++ uint16_t lun;
++ atio_entry_t *atio = &cmd->atio.atio2x;
++ scst_data_direction dir;
++ int context;
++
++ TRACE_ENTRY();
++
++ /* make it be in network byte order */
++ lun = swab16(le16_to_cpu(atio->lun));
++ cmd->scst_cmd = scst_rx_cmd(sess->scst_sess, (uint8_t *)&lun,
++ sizeof(lun), atio->cdb, Q2T_MAX_CDB_LEN,
++ SCST_ATOMIC);
++
++ if (cmd->scst_cmd == NULL) {
++ PRINT_ERROR("%s", "qla2x00t: scst_rx_cmd() failed");
++ res = -EFAULT;
++ goto out;
++ }
++
++ cmd->tag = atio->rx_id;
++ scst_cmd_set_tag(cmd->scst_cmd, cmd->tag);
++ scst_cmd_set_tgt_priv(cmd->scst_cmd, cmd);
++
++ if ((atio->execution_codes & (ATIO_EXEC_READ | ATIO_EXEC_WRITE)) ==
++ (ATIO_EXEC_READ | ATIO_EXEC_WRITE))
++ dir = SCST_DATA_BIDI;
++ else if (atio->execution_codes & ATIO_EXEC_READ)
++ dir = SCST_DATA_READ;
++ else if (atio->execution_codes & ATIO_EXEC_WRITE)
++ dir = SCST_DATA_WRITE;
++ else
++ dir = SCST_DATA_NONE;
++ scst_cmd_set_expected(cmd->scst_cmd, dir,
++ le32_to_cpu(atio->data_length));
++
++ switch (atio->task_codes) {
++ case ATIO_SIMPLE_QUEUE:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_SIMPLE);
++ break;
++ case ATIO_HEAD_OF_QUEUE:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
++ break;
++ case ATIO_ORDERED_QUEUE:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ case ATIO_ACA_QUEUE:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ACA);
++ break;
++ case ATIO_UNTAGGED:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
++ break;
++ default:
++ PRINT_ERROR("qla2x00t: unknown task code %x, use "
++ "ORDERED instead", atio->task_codes);
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ }
++
++#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
++ context = SCST_CONTEXT_THREAD;
++#else
++ context = SCST_CONTEXT_TASKLET;
++#endif
++
++ TRACE_DBG("Context %x", context);
++ TRACE(TRACE_SCSI, "qla2x00t: START Command (tag %d, queue_type %d)",
++ cmd->tag, scst_cmd_get_queue_type(cmd->scst_cmd));
++ scst_cmd_init_done(cmd->scst_cmd, context);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* ha->hardware_lock is supposed to be held on entry */
++static int q24_do_send_cmd_to_scst(struct q2t_cmd *cmd)
++{
++ int res = 0;
++ struct q2t_sess *sess = cmd->sess;
++ atio7_entry_t *atio = &cmd->atio.atio7;
++ scst_data_direction dir;
++ int context;
++
++ TRACE_ENTRY();
++
++ cmd->scst_cmd = scst_rx_cmd(sess->scst_sess,
++ (uint8_t *)&atio->fcp_cmnd.lun, sizeof(atio->fcp_cmnd.lun),
++ atio->fcp_cmnd.cdb, Q2T_MAX_CDB_LEN, SCST_ATOMIC);
++
++ if (cmd->scst_cmd == NULL) {
++ PRINT_ERROR("%s", "qla2x00t: scst_rx_cmd() failed");
++ res = -EFAULT;
++ goto out;
++ }
++
++ cmd->tag = atio->exchange_addr;
++ scst_cmd_set_tag(cmd->scst_cmd, cmd->tag);
++ scst_cmd_set_tgt_priv(cmd->scst_cmd, cmd);
++
++ if (atio->fcp_cmnd.rddata && atio->fcp_cmnd.wrdata)
++ dir = SCST_DATA_BIDI;
++ else if (atio->fcp_cmnd.rddata)
++ dir = SCST_DATA_READ;
++ else if (atio->fcp_cmnd.wrdata)
++ dir = SCST_DATA_WRITE;
++ else
++ dir = SCST_DATA_NONE;
++ scst_cmd_set_expected(cmd->scst_cmd, dir,
++ be32_to_cpu(atio->fcp_cmnd.data_length));
++
++ switch (atio->fcp_cmnd.task_attr) {
++ case ATIO_SIMPLE_QUEUE:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_SIMPLE);
++ break;
++ case ATIO_HEAD_OF_QUEUE:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
++ break;
++ case ATIO_ORDERED_QUEUE:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ case ATIO_ACA_QUEUE:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ACA);
++ break;
++ case ATIO_UNTAGGED:
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
++ break;
++ default:
++ PRINT_ERROR("qla2x00t: unknown task code %x, use "
++ "ORDERED instead", atio->fcp_cmnd.task_attr);
++ scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ }
++
++#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
++ context = SCST_CONTEXT_THREAD;
++#else
++ context = SCST_CONTEXT_TASKLET;
++#endif
++
++ TRACE_DBG("Context %x", context);
++ TRACE(TRACE_SCSI, "qla2x00t: START Command %p (tag %d, queue type %x)",
++ cmd, cmd->tag, scst_cmd_get_queue_type(cmd->scst_cmd));
++ scst_cmd_init_done(cmd->scst_cmd, context);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q2t_do_send_cmd_to_scst(scsi_qla_host_t *ha,
++ struct q2t_cmd *cmd, struct q2t_sess *sess)
++{
++ int res;
++
++ TRACE_ENTRY();
++
++ cmd->sess = sess;
++ cmd->loop_id = sess->loop_id;
++ cmd->conf_compl_supported = sess->conf_compl_supported;
++
++ if (IS_FWI2_CAPABLE(ha))
++ res = q24_do_send_cmd_to_scst(cmd);
++ else
++ res = q2x_do_send_cmd_to_scst(cmd);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q2t_send_cmd_to_scst(scsi_qla_host_t *ha, atio_t *atio)
++{
++ int res = 0;
++ struct q2t_tgt *tgt = ha->tgt;
++ struct q2t_sess *sess;
++ struct q2t_cmd *cmd;
++
++ TRACE_ENTRY();
++
++ if (unlikely(tgt->tgt_stop)) {
++ TRACE_MGMT_DBG("New command while device %p is shutting "
++ "down", tgt);
++ res = -EFAULT;
++ goto out;
++ }
++
++ cmd = kmem_cache_zalloc(q2t_cmd_cachep, GFP_ATOMIC);
++ if (cmd == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): Allocation of cmd "
++ "failed", ha->instance);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ memcpy(&cmd->atio.atio2x, atio, sizeof(*atio));
++ cmd->state = Q2T_STATE_NEW;
++ cmd->tgt = ha->tgt;
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ atio7_entry_t *a = (atio7_entry_t *)atio;
++ sess = q2t_find_sess_by_s_id(tgt, a->fcp_hdr.s_id);
++ if (unlikely(sess == NULL)) {
++ TRACE_MGMT_DBG("qla2x00t(%ld): Unable to find "
++ "wwn login (s_id %x:%x:%x), trying to create "
++ "it manually", ha->instance,
++ a->fcp_hdr.s_id[0], a->fcp_hdr.s_id[1],
++ a->fcp_hdr.s_id[2]);
++ goto out_sched;
++ }
++ } else {
++ sess = q2t_find_sess_by_loop_id(tgt,
++ GET_TARGET_ID(ha, (atio_entry_t *)atio));
++ if (unlikely(sess == NULL)) {
++ TRACE_MGMT_DBG("qla2x00t(%ld): Unable to find "
++ "wwn login (loop_id=%d), trying to create it "
++ "manually", ha->instance,
++ GET_TARGET_ID(ha, (atio_entry_t *)atio));
++ goto out_sched;
++ }
++ }
++
++ if (unlikely(sess->deleted))
++ q2t_reappear_sess(sess, " by new commands");
++
++ res = q2t_do_send_cmd_to_scst(ha, cmd, sess);
++ if (unlikely(res != 0))
++ goto out_free_cmd;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free_cmd:
++ q2t_free_cmd(cmd);
++ goto out;
++
++out_sched:
++ {
++ struct q2t_sess_work_param *prm;
++ unsigned long flags;
++
++ prm = kzalloc(sizeof(*prm), GFP_ATOMIC);
++ if (prm == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): Unable to create session "
++ "work, command will be refused", ha->instance);
++ res = -1;
++ goto out_free_cmd;
++ }
++
++ TRACE_MGMT_DBG("Scheduling work to find session for cmd %p",
++ cmd);
++
++ prm->cmd = cmd;
++
++ spin_lock_irqsave(&tgt->sess_work_lock, flags);
++ if (!tgt->sess_works_pending)
++ tgt->tm_to_unknown = 0;
++ list_add_tail(&prm->sess_works_list_entry, &tgt->sess_works_list);
++ tgt->sess_works_pending = 1;
++ spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
++
++ schedule_work(&tgt->sess_work);
++ }
++ goto out;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q2t_issue_task_mgmt(struct q2t_sess *sess, uint8_t *lun,
++ int lun_size, int fn, void *iocb, int flags)
++{
++ int res = 0, rc = -1;
++ struct q2t_mgmt_cmd *mcmd;
++
++ TRACE_ENTRY();
++
++ mcmd = mempool_alloc(q2t_mgmt_cmd_mempool, GFP_ATOMIC);
++ if (mcmd == NULL) {
++ PRINT_CRIT_ERROR("qla2x00t(%ld): Allocation of management "
++ "command failed, some commands and their data could "
++ "leak", sess->tgt->ha->instance);
++ res = -ENOMEM;
++ goto out;
++ }
++ memset(mcmd, 0, sizeof(*mcmd));
++
++ mcmd->sess = sess;
++ if (iocb) {
++ memcpy(&mcmd->orig_iocb.notify_entry, iocb,
++ sizeof(mcmd->orig_iocb.notify_entry));
++ }
++ mcmd->flags = flags;
++
++ switch (fn) {
++ case Q2T_CLEAR_ACA:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): CLEAR_ACA received",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_ACA,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ case Q2T_TARGET_RESET:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): TARGET_RESET received",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_TARGET_RESET,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ case Q2T_LUN_RESET:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): LUN_RESET received",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ case Q2T_CLEAR_TS:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): CLEAR_TS received",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_TASK_SET,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ case Q2T_ABORT_TS:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): ABORT_TS received",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_ABORT_TASK_SET,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ case Q2T_ABORT_ALL:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Doing ABORT_ALL_TASKS",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess,
++ SCST_ABORT_ALL_TASKS,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ case Q2T_ABORT_ALL_SESS:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Doing ABORT_ALL_TASKS_SESS",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess,
++ SCST_ABORT_ALL_TASKS_SESS,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ case Q2T_NEXUS_LOSS_SESS:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Doing NEXUS_LOSS_SESS",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_NEXUS_LOSS_SESS,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ case Q2T_NEXUS_LOSS:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Doing NEXUS_LOSS",
++ sess->tgt->ha->instance);
++ rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_NEXUS_LOSS,
++ lun, lun_size, SCST_ATOMIC, mcmd);
++ break;
++
++ default:
++ PRINT_ERROR("qla2x00t(%ld): Unknown task mgmt fn 0x%x",
++ sess->tgt->ha->instance, fn);
++ rc = -1;
++ break;
++ }
++
++ if (rc != 0) {
++ PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_lun() failed: %d",
++ sess->tgt->ha->instance, rc);
++ res = -EFAULT;
++ goto out_free;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ mempool_free(mcmd, q2t_mgmt_cmd_mempool);
++ goto out;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q2t_handle_task_mgmt(scsi_qla_host_t *ha, void *iocb)
++{
++ int res = 0;
++ struct q2t_tgt *tgt;
++ struct q2t_sess *sess;
++ uint8_t *lun;
++ uint16_t lun_data;
++ int lun_size;
++ int fn;
++
++ TRACE_ENTRY();
++
++ tgt = ha->tgt;
++ if (IS_FWI2_CAPABLE(ha)) {
++ atio7_entry_t *a = (atio7_entry_t *)iocb;
++ lun = (uint8_t *)&a->fcp_cmnd.lun;
++ lun_size = sizeof(a->fcp_cmnd.lun);
++ fn = a->fcp_cmnd.task_mgmt_flags;
++ sess = q2t_find_sess_by_s_id(tgt, a->fcp_hdr.s_id);
++ if (sess != NULL) {
++ sess->s_id.b.al_pa = a->fcp_hdr.s_id[2];
++ sess->s_id.b.area = a->fcp_hdr.s_id[1];
++ sess->s_id.b.domain = a->fcp_hdr.s_id[0];
++ }
++ } else {
++ notify_entry_t *n = (notify_entry_t *)iocb;
++ /* make it be in network byte order */
++ lun_data = swab16(le16_to_cpu(n->lun));
++ lun = (uint8_t *)&lun_data;
++ lun_size = sizeof(lun_data);
++ fn = n->task_flags >> IMM_NTFY_TASK_MGMT_SHIFT;
++ sess = q2t_find_sess_by_loop_id(tgt, GET_TARGET_ID(ha, n));
++ }
++
++ if (sess == NULL) {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): task mgmt fn 0x%x for "
++ "non-existant session", ha->instance, fn);
++ tgt->tm_to_unknown = 1;
++ res = -ESRCH;
++ goto out;
++ }
++
++ res = q2t_issue_task_mgmt(sess, lun, lun_size, fn, iocb, 0);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static int q2t_abort_task(scsi_qla_host_t *ha, notify_entry_t *iocb)
++{
++ int res = 0, rc;
++ struct q2t_mgmt_cmd *mcmd;
++ struct q2t_sess *sess;
++ int loop_id;
++ uint32_t tag;
++
++ TRACE_ENTRY();
++
++ loop_id = GET_TARGET_ID(ha, iocb);
++ tag = le16_to_cpu(iocb->seq_id);
++
++ sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id);
++ if (sess == NULL) {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): task abort for unexisting "
++ "session", ha->instance);
++ ha->tgt->tm_to_unknown = 1;
++ res = -EFAULT;
++ goto out;
++ }
++
++ mcmd = mempool_alloc(q2t_mgmt_cmd_mempool, GFP_ATOMIC);
++ if (mcmd == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s: Allocation of ABORT cmd failed",
++ ha->instance, __func__);
++ res = -ENOMEM;
++ goto out;
++ }
++ memset(mcmd, 0, sizeof(*mcmd));
++
++ mcmd->sess = sess;
++ memcpy(&mcmd->orig_iocb.notify_entry, iocb,
++ sizeof(mcmd->orig_iocb.notify_entry));
++
++ rc = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, tag,
++ SCST_ATOMIC, mcmd);
++ if (rc != 0) {
++ PRINT_ERROR("qla2x00t(%ld): scst_rx_mgmt_fn_tag() failed: %d",
++ ha->instance, rc);
++ res = -EFAULT;
++ goto out_free;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ mempool_free(mcmd, q2t_mgmt_cmd_mempool);
++ goto out;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static int q24_handle_els(scsi_qla_host_t *ha, notify24xx_entry_t *iocb)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): ELS opcode %x", ha->instance,
++ iocb->status_subcode);
++
++ switch (iocb->status_subcode) {
++ case ELS_PLOGI:
++ case ELS_FLOGI:
++ case ELS_PRLI:
++ case ELS_LOGO:
++ case ELS_PRLO:
++ res = q2t_reset(ha, iocb, Q2T_NEXUS_LOSS_SESS);
++ break;
++
++ case ELS_PDISC:
++ case ELS_ADISC:
++ {
++ struct q2t_tgt *tgt = ha->tgt;
++ if (tgt->link_reinit_iocb_pending) {
++ q24_send_notify_ack(ha, &tgt->link_reinit_iocb, 0, 0, 0);
++ tgt->link_reinit_iocb_pending = 0;
++ }
++ res = 1; /* send notify ack */
++ break;
++ }
++
++ default:
++ PRINT_ERROR("qla2x00t(%ld): Unsupported ELS command %x "
++ "received", ha->instance, iocb->status_subcode);
++ res = q2t_reset(ha, iocb, Q2T_NEXUS_LOSS_SESS);
++ break;
++ }
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int q2t_cut_cmd_data_head(struct q2t_cmd *cmd, unsigned int offset)
++{
++ int res = 0;
++ int cnt, first_sg, first_page = 0, first_page_offs = 0, i;
++ unsigned int l;
++ int cur_dst, cur_src;
++ struct scatterlist *sg;
++ size_t bufflen = 0;
++
++ TRACE_ENTRY();
++
++ first_sg = -1;
++ cnt = 0;
++ l = 0;
++ for (i = 0; i < cmd->sg_cnt; i++) {
++ l += cmd->sg[i].length;
++ if (l > offset) {
++ int sg_offs = l - cmd->sg[i].length;
++ first_sg = i;
++ if (cmd->sg[i].offset == 0) {
++ first_page_offs = offset % PAGE_SIZE;
++ first_page = (offset - sg_offs) >> PAGE_SHIFT;
++ } else {
++ TRACE_SG("i=%d, sg[i].offset=%d, "
++ "sg_offs=%d", i, cmd->sg[i].offset, sg_offs);
++ if ((cmd->sg[i].offset + sg_offs) > offset) {
++ first_page_offs = offset - sg_offs;
++ first_page = 0;
++ } else {
++ int sec_page_offs = sg_offs +
++ (PAGE_SIZE - cmd->sg[i].offset);
++ first_page_offs = sec_page_offs % PAGE_SIZE;
++ first_page = 1 +
++ ((offset - sec_page_offs) >>
++ PAGE_SHIFT);
++ }
++ }
++ cnt = cmd->sg_cnt - i + (first_page_offs != 0);
++ break;
++ }
++ }
++ if (first_sg == -1) {
++ PRINT_ERROR("qla2x00t(%ld): Wrong offset %d, buf length %d",
++ cmd->tgt->ha->instance, offset, cmd->bufflen);
++ res = -EINVAL;
++ goto out;
++ }
++
++ TRACE_SG("offset=%d, first_sg=%d, first_page=%d, "
++ "first_page_offs=%d, cmd->bufflen=%d, cmd->sg_cnt=%d", offset,
++ first_sg, first_page, first_page_offs, cmd->bufflen,
++ cmd->sg_cnt);
++
++ sg = kmalloc(cnt * sizeof(sg[0]), GFP_KERNEL);
++ if (sg == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): Unable to allocate cut "
++ "SG (len %zd)", cmd->tgt->ha->instance,
++ cnt * sizeof(sg[0]));
++ res = -ENOMEM;
++ goto out;
++ }
++ sg_init_table(sg, cnt);
++
++ cur_dst = 0;
++ cur_src = first_sg;
++ if (first_page_offs != 0) {
++ int fpgs;
++ sg_set_page(&sg[cur_dst], &sg_page(&cmd->sg[cur_src])[first_page],
++ PAGE_SIZE - first_page_offs, first_page_offs);
++ bufflen += sg[cur_dst].length;
++ TRACE_SG("cur_dst=%d, cur_src=%d, sg[].page=%p, "
++ "sg[].offset=%d, sg[].length=%d, bufflen=%zu",
++ cur_dst, cur_src, sg_page(&sg[cur_dst]), sg[cur_dst].offset,
++ sg[cur_dst].length, bufflen);
++ cur_dst++;
++
++ fpgs = (cmd->sg[cur_src].length >> PAGE_SHIFT) +
++ ((cmd->sg[cur_src].length & ~PAGE_MASK) != 0);
++ first_page++;
++ if (fpgs > first_page) {
++ sg_set_page(&sg[cur_dst],
++ &sg_page(&cmd->sg[cur_src])[first_page],
++ cmd->sg[cur_src].length - PAGE_SIZE*first_page,
++ 0);
++ TRACE_SG("fpgs=%d, cur_dst=%d, cur_src=%d, "
++ "sg[].page=%p, sg[].length=%d, bufflen=%zu",
++ fpgs, cur_dst, cur_src, sg_page(&sg[cur_dst]),
++ sg[cur_dst].length, bufflen);
++ bufflen += sg[cur_dst].length;
++ cur_dst++;
++ }
++ cur_src++;
++ }
++
++ while (cur_src < cmd->sg_cnt) {
++ sg_set_page(&sg[cur_dst], sg_page(&cmd->sg[cur_src]),
++ cmd->sg[cur_src].length, cmd->sg[cur_src].offset);
++ TRACE_SG("cur_dst=%d, cur_src=%d, "
++ "sg[].page=%p, sg[].length=%d, sg[].offset=%d, "
++ "bufflen=%zu", cur_dst, cur_src, sg_page(&sg[cur_dst]),
++ sg[cur_dst].length, sg[cur_dst].offset, bufflen);
++ bufflen += sg[cur_dst].length;
++ cur_dst++;
++ cur_src++;
++ }
++
++ if (cmd->free_sg)
++ kfree(cmd->sg);
++
++ cmd->sg = sg;
++ cmd->free_sg = 1;
++ cmd->sg_cnt = cur_dst;
++ cmd->bufflen = bufflen;
++ cmd->offset += offset;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static inline int q2t_srr_adjust_data(struct q2t_cmd *cmd,
++ uint32_t srr_rel_offs, int *xmit_type)
++{
++ int res = 0;
++ int rel_offs;
++
++ rel_offs = srr_rel_offs - cmd->offset;
++ TRACE_MGMT_DBG("srr_rel_offs=%d, rel_offs=%d", srr_rel_offs, rel_offs);
++
++ *xmit_type = Q2T_XMIT_ALL;
++
++ if (rel_offs < 0) {
++ PRINT_ERROR("qla2x00t(%ld): SRR rel_offs (%d) "
++ "< 0", cmd->tgt->ha->instance, rel_offs);
++ res = -1;
++ } else if (rel_offs == cmd->bufflen)
++ *xmit_type = Q2T_XMIT_STATUS;
++ else if (rel_offs > 0)
++ res = q2t_cut_cmd_data_head(cmd, rel_offs);
++
++ return res;
++}
++
++/* No locks, thread context */
++static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
++ struct srr_imm *imm)
++{
++ notify24xx_entry_t *ntfy = &imm->imm.notify_entry24;
++ struct q2t_cmd *cmd = sctio->cmd;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("SRR cmd %p, srr_ui %x", cmd, ntfy->srr_ui);
++
++ switch (ntfy->srr_ui) {
++ case SRR_IU_STATUS:
++ spin_lock_irq(&ha->hardware_lock);
++ q24_send_notify_ack(ha, ntfy,
++ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
++ spin_unlock_irq(&ha->hardware_lock);
++ __q24_xmit_response(cmd, Q2T_XMIT_STATUS);
++ break;
++ case SRR_IU_DATA_IN:
++ cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(cmd->scst_cmd);
++ if (q2t_has_data(cmd)) {
++ uint32_t offset;
++ int xmit_type;
++ offset = le32_to_cpu(imm->imm.notify_entry24.srr_rel_offs);
++ if (q2t_srr_adjust_data(cmd, offset, &xmit_type) != 0)
++ goto out_reject;
++ spin_lock_irq(&ha->hardware_lock);
++ q24_send_notify_ack(ha, ntfy,
++ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
++ spin_unlock_irq(&ha->hardware_lock);
++ __q24_xmit_response(cmd, xmit_type);
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): SRR for in data for cmd "
++ "without them (tag %d, SCSI status %d), "
++ "reject", ha->instance, cmd->tag,
++ scst_cmd_get_status(cmd->scst_cmd));
++ goto out_reject;
++ }
++ break;
++ case SRR_IU_DATA_OUT:
++ cmd->bufflen = scst_cmd_get_write_fields(cmd->scst_cmd,
++ &cmd->sg, &cmd->sg_cnt);
++ if (q2t_has_data(cmd)) {
++ uint32_t offset;
++ int xmit_type;
++ offset = le32_to_cpu(imm->imm.notify_entry24.srr_rel_offs);
++ if (q2t_srr_adjust_data(cmd, offset, &xmit_type) != 0)
++ goto out_reject;
++ spin_lock_irq(&ha->hardware_lock);
++ q24_send_notify_ack(ha, ntfy,
++ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
++ spin_unlock_irq(&ha->hardware_lock);
++ if (xmit_type & Q2T_XMIT_DATA)
++ __q2t_rdy_to_xfer(cmd);
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): SRR for out data for cmd "
++ "without them (tag %d, SCSI status %d), "
++ "reject", ha->instance, cmd->tag,
++ scst_cmd_get_status(cmd->scst_cmd));
++ goto out_reject;
++ }
++ break;
++ default:
++ PRINT_ERROR("qla2x00t(%ld): Unknown srr_ui value %x",
++ ha->instance, ntfy->srr_ui);
++ goto out_reject;
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_reject:
++ spin_lock_irq(&ha->hardware_lock);
++ q24_send_notify_ack(ha, ntfy, NOTIFY_ACK_SRR_FLAGS_REJECT,
++ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
++ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
++ if (cmd->state == Q2T_STATE_NEED_DATA) {
++ cmd->state = Q2T_STATE_DATA_IN;
++ scst_rx_data(cmd->scst_cmd, SCST_RX_STATUS_ERROR,
++ SCST_CONTEXT_THREAD);
++ } else
++ q24_send_term_exchange(ha, cmd, &cmd->atio.atio7, 1);
++ spin_unlock_irq(&ha->hardware_lock);
++ goto out;
++}
++
++/* No locks, thread context */
++static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
++ struct srr_imm *imm)
++{
++ notify_entry_t *ntfy = &imm->imm.notify_entry;
++ struct q2t_cmd *cmd = sctio->cmd;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("SRR cmd %p, srr_ui %x", cmd, ntfy->srr_ui);
++
++ switch (ntfy->srr_ui) {
++ case SRR_IU_STATUS:
++ spin_lock_irq(&ha->hardware_lock);
++ q2x_send_notify_ack(ha, ntfy, 0, 0, 0,
++ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
++ spin_unlock_irq(&ha->hardware_lock);
++ __q2x_xmit_response(cmd, Q2T_XMIT_STATUS);
++ break;
++ case SRR_IU_DATA_IN:
++ cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(cmd->scst_cmd);
++ if (q2t_has_data(cmd)) {
++ uint32_t offset;
++ int xmit_type;
++ offset = le32_to_cpu(imm->imm.notify_entry.srr_rel_offs);
++ if (q2t_srr_adjust_data(cmd, offset, &xmit_type) != 0)
++ goto out_reject;
++ spin_lock_irq(&ha->hardware_lock);
++ q2x_send_notify_ack(ha, ntfy, 0, 0, 0,
++ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
++ spin_unlock_irq(&ha->hardware_lock);
++ __q2x_xmit_response(cmd, xmit_type);
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): SRR for in data for cmd "
++ "without them (tag %d, SCSI status %d), "
++ "reject", ha->instance, cmd->tag,
++ scst_cmd_get_status(cmd->scst_cmd));
++ goto out_reject;
++ }
++ break;
++ case SRR_IU_DATA_OUT:
++ cmd->bufflen = scst_cmd_get_write_fields(cmd->scst_cmd,
++ &cmd->sg, &cmd->sg_cnt);
++ if (q2t_has_data(cmd)) {
++ uint32_t offset;
++ int xmit_type;
++ offset = le32_to_cpu(imm->imm.notify_entry.srr_rel_offs);
++ if (q2t_srr_adjust_data(cmd, offset, &xmit_type) != 0)
++ goto out_reject;
++ spin_lock_irq(&ha->hardware_lock);
++ q2x_send_notify_ack(ha, ntfy, 0, 0, 0,
++ NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
++ spin_unlock_irq(&ha->hardware_lock);
++ if (xmit_type & Q2T_XMIT_DATA)
++ __q2t_rdy_to_xfer(cmd);
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): SRR for out data for cmd "
++ "without them (tag %d, SCSI status %d), "
++ "reject", ha->instance, cmd->tag,
++ scst_cmd_get_status(cmd->scst_cmd));
++ goto out_reject;
++ }
++ break;
++ default:
++ PRINT_ERROR("qla2x00t(%ld): Unknown srr_ui value %x",
++ ha->instance, ntfy->srr_ui);
++ goto out_reject;
++ }
++
++out:
++ TRACE_EXIT();
++ return;
++
++out_reject:
++ spin_lock_irq(&ha->hardware_lock);
++ q2x_send_notify_ack(ha, ntfy, 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_REJECT,
++ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
++ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
++ if (cmd->state == Q2T_STATE_NEED_DATA) {
++ cmd->state = Q2T_STATE_DATA_IN;
++ scst_rx_data(cmd->scst_cmd, SCST_RX_STATUS_ERROR,
++ SCST_CONTEXT_THREAD);
++ } else
++ q2x_send_term_exchange(ha, cmd, &cmd->atio.atio2x, 1);
++ spin_unlock_irq(&ha->hardware_lock);
++ goto out;
++}
++
++static void q2t_reject_free_srr_imm(scsi_qla_host_t *ha, struct srr_imm *imm,
++ int ha_locked)
++{
++ if (!ha_locked)
++ spin_lock_irq(&ha->hardware_lock);
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ q24_send_notify_ack(ha, &imm->imm.notify_entry24,
++ NOTIFY_ACK_SRR_FLAGS_REJECT,
++ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
++ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
++ } else {
++ q2x_send_notify_ack(ha, &imm->imm.notify_entry,
++ 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_REJECT,
++ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
++ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
++ }
++
++ if (!ha_locked)
++ spin_unlock_irq(&ha->hardware_lock);
++
++ kfree(imm);
++ return;
++}
++
++static void q2t_handle_srr_work(struct work_struct *work)
++{
++ struct q2t_tgt *tgt = container_of(work, struct q2t_tgt, srr_work);
++ scsi_qla_host_t *ha = tgt->ha;
++ struct srr_ctio *sctio;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("SRR work (tgt %p)", tgt);
++
++restart:
++ spin_lock_irq(&tgt->srr_lock);
++ list_for_each_entry(sctio, &tgt->srr_ctio_list, srr_list_entry) {
++ struct srr_imm *imm;
++ struct q2t_cmd *cmd;
++ struct srr_imm *i, *ti;
++
++ imm = NULL;
++ list_for_each_entry_safe(i, ti, &tgt->srr_imm_list,
++ srr_list_entry) {
++ if (i->srr_id == sctio->srr_id) {
++ list_del(&i->srr_list_entry);
++ if (imm) {
++ PRINT_ERROR("qla2x00t(%ld): There must "
++ "be only one IMM SRR per CTIO SRR "
++ "(IMM SRR %p, id %d, CTIO %p",
++ ha->instance, i, i->srr_id, sctio);
++ q2t_reject_free_srr_imm(ha, i, 0);
++ } else
++ imm = i;
++ }
++ }
++
++ TRACE_MGMT_DBG("IMM SRR %p, CTIO SRR %p (id %d)", imm, sctio,
++ sctio->srr_id);
++
++ if (imm == NULL) {
++ TRACE_MGMT_DBG("Not found matching IMM for SRR CTIO "
++ "(id %d)", sctio->srr_id);
++ continue;
++ } else
++ list_del(&sctio->srr_list_entry);
++
++ spin_unlock_irq(&tgt->srr_lock);
++
++ cmd = sctio->cmd;
++
++ /* Restore the originals, except bufflen */
++ cmd->offset = scst_cmd_get_ppl_offset(cmd->scst_cmd);
++ if (cmd->free_sg) {
++ kfree(cmd->sg);
++ cmd->free_sg = 0;
++ }
++ cmd->sg = scst_cmd_get_sg(cmd->scst_cmd);
++ cmd->sg_cnt = scst_cmd_get_sg_cnt(cmd->scst_cmd);
++
++ TRACE_MGMT_DBG("SRR cmd %p (scst_cmd %p, tag %d, op %x), "
++ "sg_cnt=%d, offset=%d", cmd, cmd->scst_cmd,
++ cmd->tag, cmd->scst_cmd->cdb[0], cmd->sg_cnt,
++ cmd->offset);
++
++ if (IS_FWI2_CAPABLE(ha))
++ q24_handle_srr(ha, sctio, imm);
++ else
++ q2x_handle_srr(ha, sctio, imm);
++
++ kfree(imm);
++ kfree(sctio);
++ goto restart;
++ }
++ spin_unlock_irq(&tgt->srr_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++static void q2t_prepare_srr_imm(scsi_qla_host_t *ha, void *iocb)
++{
++ struct srr_imm *imm;
++ struct q2t_tgt *tgt = ha->tgt;
++ notify_entry_t *iocb2x = (notify_entry_t *)iocb;
++ notify24xx_entry_t *iocb24 = (notify24xx_entry_t *)iocb;
++ struct srr_ctio *sctio;
++
++ tgt->imm_srr_id++;
++
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): SRR received", ha->instance);
++
++ imm = kzalloc(sizeof(*imm), GFP_ATOMIC);
++ if (imm != NULL) {
++ memcpy(&imm->imm.notify_entry, iocb,
++ sizeof(imm->imm.notify_entry));
++
++ /* IRQ is already OFF */
++ spin_lock(&tgt->srr_lock);
++ imm->srr_id = tgt->imm_srr_id;
++ list_add_tail(&imm->srr_list_entry,
++ &tgt->srr_imm_list);
++ TRACE_MGMT_DBG("IMM NTFY SRR %p added (id %d, ui %x)", imm,
++ imm->srr_id, iocb24->srr_ui);
++ if (tgt->imm_srr_id == tgt->ctio_srr_id) {
++ int found = 0;
++ list_for_each_entry(sctio, &tgt->srr_ctio_list,
++ srr_list_entry) {
++ if (sctio->srr_id == imm->srr_id) {
++ found = 1;
++ break;
++ }
++ }
++ if (found) {
++ TRACE_MGMT_DBG("%s", "Scheduling srr work");
++ schedule_work(&tgt->srr_work);
++ } else {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): imm_srr_id "
++ "== ctio_srr_id (%d), but there is no "
++ "corresponding SRR CTIO, deleting IMM "
++ "SRR %p", ha->instance, tgt->ctio_srr_id,
++ imm);
++ list_del(&imm->srr_list_entry);
++
++ kfree(imm);
++
++ spin_unlock(&tgt->srr_lock);
++ goto out_reject;
++ }
++ }
++ spin_unlock(&tgt->srr_lock);
++ } else {
++ struct srr_ctio *ts;
++
++ PRINT_ERROR("qla2x00t(%ld): Unable to allocate SRR IMM "
++ "entry, SRR request will be rejected", ha->instance);
++
++ /* IRQ is already OFF */
++ spin_lock(&tgt->srr_lock);
++ list_for_each_entry_safe(sctio, ts, &tgt->srr_ctio_list,
++ srr_list_entry) {
++ if (sctio->srr_id == tgt->imm_srr_id) {
++ TRACE_MGMT_DBG("CTIO SRR %p deleted "
++ "(id %d)", sctio, sctio->srr_id);
++ list_del(&sctio->srr_list_entry);
++ if (IS_FWI2_CAPABLE(ha)) {
++ q24_send_term_exchange(ha, sctio->cmd,
++ &sctio->cmd->atio.atio7, 1);
++ } else {
++ q2x_send_term_exchange(ha, sctio->cmd,
++ &sctio->cmd->atio.atio2x, 1);
++ }
++ kfree(sctio);
++ }
++ }
++ spin_unlock(&tgt->srr_lock);
++ goto out_reject;
++ }
++
++out:
++ return;
++
++out_reject:
++ if (IS_FWI2_CAPABLE(ha)) {
++ q24_send_notify_ack(ha, iocb24,
++ NOTIFY_ACK_SRR_FLAGS_REJECT,
++ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
++ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
++ } else {
++ q2x_send_notify_ack(ha, iocb2x,
++ 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_REJECT,
++ NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM,
++ NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
++ }
++ goto out;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q2t_handle_imm_notify(scsi_qla_host_t *ha, void *iocb)
++{
++ uint16_t status;
++ uint32_t add_flags = 0;
++ int send_notify_ack = 1;
++ notify_entry_t *iocb2x = (notify_entry_t *)iocb;
++ notify24xx_entry_t *iocb24 = (notify24xx_entry_t *)iocb;
++
++ TRACE_ENTRY();
++
++ status = le16_to_cpu(iocb2x->status);
++
++ TRACE_BUFF_FLAG(TRACE_BUFF, "IMMED Notify Coming Up",
++ iocb, sizeof(*iocb2x));
++
++ switch (status) {
++ case IMM_NTFY_LIP_RESET:
++ {
++ if (IS_FWI2_CAPABLE(ha)) {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): LIP reset (loop %#x), "
++ "subcode %x", ha->instance,
++ le16_to_cpu(iocb24->nport_handle),
++ iocb24->status_subcode);
++ } else {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): LIP reset (I %#x)",
++ ha->instance, GET_TARGET_ID(ha, iocb2x));
++ /* set the Clear LIP reset event flag */
++ add_flags |= NOTIFY_ACK_CLEAR_LIP_RESET;
++ }
++ if (q2t_reset(ha, iocb, Q2T_ABORT_ALL) == 0)
++ send_notify_ack = 0;
++ break;
++ }
++
++ case IMM_NTFY_LIP_LINK_REINIT:
++ {
++ struct q2t_tgt *tgt = ha->tgt;
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): LINK REINIT (loop %#x, "
++ "subcode %x)", ha->instance,
++ le16_to_cpu(iocb24->nport_handle),
++ iocb24->status_subcode);
++ if (tgt->link_reinit_iocb_pending)
++ q24_send_notify_ack(ha, &tgt->link_reinit_iocb, 0, 0, 0);
++ memcpy(&tgt->link_reinit_iocb, iocb24, sizeof(*iocb24));
++ tgt->link_reinit_iocb_pending = 1;
++ /*
++ * QLogic requires to wait after LINK REINIT for possible
++ * PDISC or ADISC ELS commands
++ */
++ send_notify_ack = 0;
++ break;
++ }
++
++ case IMM_NTFY_PORT_LOGOUT:
++ if (IS_FWI2_CAPABLE(ha)) {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Port logout (loop "
++ "%#x, subcode %x)", ha->instance,
++ le16_to_cpu(iocb24->nport_handle),
++ iocb24->status_subcode);
++ } else {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Port logout (S "
++ "%08x -> L %#x)", ha->instance,
++ le16_to_cpu(iocb2x->seq_id),
++ le16_to_cpu(iocb2x->lun));
++ }
++ if (q2t_reset(ha, iocb, Q2T_NEXUS_LOSS_SESS) == 0)
++ send_notify_ack = 0;
++ /* The sessions will be cleared in the callback, if needed */
++ break;
++
++ case IMM_NTFY_GLBL_TPRLO:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Global TPRLO (%x)",
++ ha->instance, status);
++ if (q2t_reset(ha, iocb, Q2T_NEXUS_LOSS) == 0)
++ send_notify_ack = 0;
++ /* The sessions will be cleared in the callback, if needed */
++ break;
++
++ case IMM_NTFY_PORT_CONFIG:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Port config changed (%x)",
++ ha->instance, status);
++ if (q2t_reset(ha, iocb, Q2T_ABORT_ALL) == 0)
++ send_notify_ack = 0;
++ /* The sessions will be cleared in the callback, if needed */
++ break;
++
++ case IMM_NTFY_GLBL_LOGO:
++ PRINT_WARNING("qla2x00t(%ld): Link failure detected",
++ ha->instance);
++ /* I_T nexus loss */
++ if (q2t_reset(ha, iocb, Q2T_NEXUS_LOSS) == 0)
++ send_notify_ack = 0;
++ break;
++
++ case IMM_NTFY_IOCB_OVERFLOW:
++ PRINT_ERROR("qla2x00t(%ld): Cannot provide requested "
++ "capability (IOCB overflowed the immediate notify "
++ "resource count)", ha->instance);
++ break;
++
++ case IMM_NTFY_ABORT_TASK:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Abort Task (S %08x I %#x -> "
++ "L %#x)", ha->instance, le16_to_cpu(iocb2x->seq_id),
++ GET_TARGET_ID(ha, iocb2x), le16_to_cpu(iocb2x->lun));
++ if (q2t_abort_task(ha, iocb2x) == 0)
++ send_notify_ack = 0;
++ break;
++
++ case IMM_NTFY_RESOURCE:
++ PRINT_ERROR("qla2x00t(%ld): Out of resources, host %ld",
++ ha->instance, ha->host_no);
++ break;
++
++ case IMM_NTFY_MSG_RX:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Immediate notify task %x",
++ ha->instance, iocb2x->task_flags);
++ if (q2t_handle_task_mgmt(ha, iocb2x) == 0)
++ send_notify_ack = 0;
++ break;
++
++ case IMM_NTFY_ELS:
++ if (q24_handle_els(ha, iocb24) == 0)
++ send_notify_ack = 0;
++ break;
++
++ case IMM_NTFY_SRR:
++ q2t_prepare_srr_imm(ha, iocb);
++ send_notify_ack = 0;
++ break;
++
++ default:
++ PRINT_ERROR("qla2x00t(%ld): Received unknown immediate "
++ "notify status %x", ha->instance, status);
++ break;
++ }
++
++ if (send_notify_ack) {
++ if (IS_FWI2_CAPABLE(ha))
++ q24_send_notify_ack(ha, iocb24, 0, 0, 0);
++ else
++ q2x_send_notify_ack(ha, iocb2x, add_flags, 0, 0, 0,
++ 0, 0);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q2x_send_busy(scsi_qla_host_t *ha, atio_entry_t *atio)
++{
++ ctio_ret_entry_t *ctio;
++
++ TRACE_ENTRY();
++
++ /* Sending marker isn't necessary, since we called from ISR */
++
++ ctio = (ctio_ret_entry_t *)qla2x00_req_pkt(ha);
++ if (ctio == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out;
++ }
++
++ ctio->entry_type = CTIO_RET_TYPE;
++ ctio->entry_count = 1;
++ ctio->handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
++ ctio->scsi_status = __constant_cpu_to_le16(SAM_STAT_BUSY);
++ ctio->residual = atio->data_length;
++ if (ctio->residual != 0)
++ ctio->scsi_status |= SS_RESIDUAL_UNDER;
++
++ /* Set IDs */
++ SET_TARGET_ID(ha, ctio->target, GET_TARGET_ID(ha, atio));
++ ctio->rx_id = atio->rx_id;
++
++ ctio->flags = __constant_cpu_to_le16(OF_SSTS | OF_FAST_POST |
++ OF_NO_DATA | OF_SS_MODE_1);
++ ctio->flags |= __constant_cpu_to_le16(OF_INC_RC);
++ /*
++ * CTIO from fw w/o scst_cmd doesn't provide enough info to retry it,
++ * if the explicit conformation is used.
++ */
++
++ TRACE_BUFFER("CTIO BUSY packet data", ctio, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q24_send_busy(scsi_qla_host_t *ha, atio7_entry_t *atio,
++ uint16_t status)
++{
++ ctio7_status1_entry_t *ctio;
++ struct q2t_sess *sess;
++
++ TRACE_ENTRY();
++
++ sess = q2t_find_sess_by_s_id(ha->tgt, atio->fcp_hdr.s_id);
++ if (sess == NULL) {
++ q24_send_term_exchange(ha, NULL, atio, 1);
++ goto out;
++ }
++
++ /* Sending marker isn't necessary, since we called from ISR */
++
++ ctio = (ctio7_status1_entry_t *)qla2x00_req_pkt(ha);
++ if (ctio == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): %s failed: unable to allocate "
++ "request packet", ha->instance, __func__);
++ goto out;
++ }
++
++ ctio->common.entry_type = CTIO_TYPE7;
++ ctio->common.entry_count = 1;
++ ctio->common.handle = Q2T_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
++ ctio->common.nport_handle = sess->loop_id;
++ ctio->common.timeout = __constant_cpu_to_le16(Q2T_TIMEOUT);
++ ctio->common.initiator_id[0] = atio->fcp_hdr.s_id[2];
++ ctio->common.initiator_id[1] = atio->fcp_hdr.s_id[1];
++ ctio->common.initiator_id[2] = atio->fcp_hdr.s_id[0];
++ ctio->common.exchange_addr = atio->exchange_addr;
++ ctio->flags = (atio->attr << 9) | __constant_cpu_to_le16(
++ CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS |
++ CTIO7_FLAGS_DONT_RET_CTIO);
++ /*
++ * CTIO from fw w/o scst_cmd doesn't provide enough info to retry it,
++ * if the explicit conformation is used.
++ */
++ ctio->ox_id = swab16(atio->fcp_hdr.ox_id);
++ ctio->scsi_status = cpu_to_le16(status);
++ ctio->residual = atio->fcp_cmnd.data_length;
++ if (ctio->residual != 0)
++ ctio->scsi_status |= SS_RESIDUAL_UNDER;
++
++ TRACE_BUFFER("CTIO7 BUSY packet data", ctio, REQUEST_ENTRY_SIZE);
++
++ q2t_exec_queue(ha);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++/* called via callback from qla2xxx */
++static void q24_atio_pkt(scsi_qla_host_t *ha, atio7_entry_t *atio)
++{
++ int rc;
++ struct q2t_tgt *tgt = ha->tgt;
++
++ TRACE_ENTRY();
++
++ if (unlikely(tgt == NULL)) {
++ TRACE_MGMT_DBG("ATIO pkt, but no tgt (ha %p)", ha);
++ goto out;
++ }
++
++ TRACE(TRACE_SCSI, "qla2x00t(%ld): ATIO pkt %p: type %02x count %02x",
++ ha->instance, atio, atio->entry_type, atio->entry_count);
++
++ /*
++ * In tgt_stop mode we also should allow all requests to pass.
++ * Otherwise, some commands can stuck.
++ */
++
++ tgt->irq_cmd_count++;
++
++ switch (atio->entry_type) {
++ case ATIO_TYPE7:
++ if (unlikely(atio->entry_count > 1) ||
++ unlikely(atio->fcp_cmnd.add_cdb_len != 0)) {
++ PRINT_ERROR("qla2x00t(%ld): Multi entry ATIO7 IOCBs "
++ "(%d), ie with CDBs>16 bytes (%d), are not "
++ "supported", ha->instance, atio->entry_count,
++ atio->fcp_cmnd.add_cdb_len);
++ break;
++ }
++ TRACE_DBG("ATIO_TYPE7 instance %ld, lun %Lx, read/write %d/%d, "
++ "data_length %04x, s_id %x:%x:%x", ha->instance,
++ atio->fcp_cmnd.lun, atio->fcp_cmnd.rddata,
++ atio->fcp_cmnd.wrdata,
++ be32_to_cpu(atio->fcp_cmnd.data_length),
++ atio->fcp_hdr.s_id[0], atio->fcp_hdr.s_id[1],
++ atio->fcp_hdr.s_id[2]);
++ TRACE_BUFFER("Incoming ATIO7 packet data", atio,
++ REQUEST_ENTRY_SIZE);
++ PRINT_BUFF_FLAG(TRACE_SCSI, "FCP CDB", atio->fcp_cmnd.cdb,
++ sizeof(atio->fcp_cmnd.cdb));
++ if (unlikely(atio->exchange_addr ==
++ ATIO_EXCHANGE_ADDRESS_UNKNOWN)) {
++ TRACE(TRACE_OUT_OF_MEM, "qla2x00t(%ld): ATIO_TYPE7 "
++ "received with UNKNOWN exchange address, "
++ "sending QUEUE_FULL", ha->instance);
++ q24_send_busy(ha, atio, SAM_STAT_TASK_SET_FULL);
++ break;
++ }
++ if (likely(atio->fcp_cmnd.task_mgmt_flags == 0))
++ rc = q2t_send_cmd_to_scst(ha, (atio_t *)atio);
++ else
++ rc = q2t_handle_task_mgmt(ha, atio);
++ if (unlikely(rc != 0)) {
++ if (rc == -ESRCH) {
++#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
++ q24_send_busy(ha, atio, SAM_STAT_BUSY);
++#else
++ q24_send_term_exchange(ha, NULL, atio, 1);
++#endif
++ } else {
++ PRINT_INFO("qla2x00t(%ld): Unable to send "
++ "command to SCST, sending BUSY status",
++ ha->instance);
++ q24_send_busy(ha, atio, SAM_STAT_BUSY);
++ }
++ }
++ break;
++
++ case IMMED_NOTIFY_TYPE:
++ {
++ notify_entry_t *pkt = (notify_entry_t *)atio;
++ if (unlikely(pkt->entry_status != 0)) {
++ PRINT_ERROR("qla2x00t(%ld): Received ATIO packet %x "
++ "with error status %x", ha->instance,
++ pkt->entry_type, pkt->entry_status);
++ break;
++ }
++ TRACE_DBG("%s", "IMMED_NOTIFY ATIO");
++ q2t_handle_imm_notify(ha, pkt);
++ break;
++ }
++
++ default:
++ PRINT_ERROR("qla2x00t(%ld): Received unknown ATIO atio "
++ "type %x", ha->instance, atio->entry_type);
++ break;
++ }
++
++ tgt->irq_cmd_count--;
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/* ha->hardware_lock supposed to be held on entry */
++/* called via callback from qla2xxx */
++static void q2t_response_pkt(scsi_qla_host_t *ha, response_t *pkt)
++{
++ struct q2t_tgt *tgt = ha->tgt;
++
++ TRACE_ENTRY();
++
++ if (unlikely(tgt == NULL)) {
++ PRINT_ERROR("qla2x00t(%ld): Response pkt %x received, but no "
++ "tgt (ha %p)", ha->instance, pkt->entry_type, ha);
++ goto out;
++ }
++
++ TRACE(TRACE_SCSI, "qla2x00t(%ld): pkt %p: T %02x C %02x S %02x "
++ "handle %#x", ha->instance, pkt, pkt->entry_type,
++ pkt->entry_count, pkt->entry_status, pkt->handle);
++
++ /*
++ * In tgt_stop mode we also should allow all requests to pass.
++ * Otherwise, some commands can stuck.
++ */
++
++ if (unlikely(pkt->entry_status != 0)) {
++ PRINT_ERROR("qla2x00t(%ld): Received response packet %x "
++ "with error status %x", ha->instance, pkt->entry_type,
++ pkt->entry_status);
++ switch (pkt->entry_type) {
++ case ACCEPT_TGT_IO_TYPE:
++ case IMMED_NOTIFY_TYPE:
++ case ABTS_RECV_24XX:
++ goto out;
++ default:
++ break;
++ }
++ }
++
++ tgt->irq_cmd_count++;
++
++ switch (pkt->entry_type) {
++ case CTIO_TYPE7:
++ {
++ ctio7_fw_entry_t *entry = (ctio7_fw_entry_t *)pkt;
++ TRACE_DBG("CTIO_TYPE7: instance %ld",
++ ha->instance);
++ TRACE_BUFFER("Incoming CTIO7 packet data", entry,
++ REQUEST_ENTRY_SIZE);
++ q2t_do_ctio_completion(ha, entry->handle,
++ le16_to_cpu(entry->status)|(pkt->entry_status << 16),
++ entry);
++ break;
++ }
++
++ case ACCEPT_TGT_IO_TYPE:
++ {
++ atio_entry_t *atio;
++ int rc;
++ atio = (atio_entry_t *)pkt;
++ TRACE_DBG("ACCEPT_TGT_IO instance %ld status %04x "
++ "lun %04x read/write %d data_length %04x "
++ "target_id %02x rx_id %04x ",
++ ha->instance, le16_to_cpu(atio->status),
++ le16_to_cpu(atio->lun),
++ atio->execution_codes,
++ le32_to_cpu(atio->data_length),
++ GET_TARGET_ID(ha, atio), atio->rx_id);
++ TRACE_BUFFER("Incoming ATIO packet data", atio,
++ REQUEST_ENTRY_SIZE);
++ if (atio->status != __constant_cpu_to_le16(ATIO_CDB_VALID)) {
++ PRINT_ERROR("qla2x00t(%ld): ATIO with error "
++ "status %x received", ha->instance,
++ le16_to_cpu(atio->status));
++ break;
++ }
++ TRACE_BUFFER("Incoming ATIO packet data", atio, REQUEST_ENTRY_SIZE);
++ PRINT_BUFF_FLAG(TRACE_SCSI, "FCP CDB", atio->cdb,
++ sizeof(atio->cdb));
++ rc = q2t_send_cmd_to_scst(ha, (atio_t *)atio);
++ if (unlikely(rc != 0)) {
++ if (rc == -ESRCH) {
++#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
++ q2x_send_busy(ha, atio);
++#else
++ q2x_send_term_exchange(ha, NULL, atio, 1);
++#endif
++ } else {
++ PRINT_INFO("qla2x00t(%ld): Unable to send "
++ "command to SCST, sending BUSY status",
++ ha->instance);
++ q2x_send_busy(ha, atio);
++ }
++ }
++ }
++ break;
++
++ case CONTINUE_TGT_IO_TYPE:
++ {
++ ctio_common_entry_t *entry = (ctio_common_entry_t *)pkt;
++ TRACE_DBG("CONTINUE_TGT_IO: instance %ld", ha->instance);
++ TRACE_BUFFER("Incoming CTIO packet data", entry,
++ REQUEST_ENTRY_SIZE);
++ q2t_do_ctio_completion(ha, entry->handle,
++ le16_to_cpu(entry->status)|(pkt->entry_status << 16),
++ entry);
++ break;
++ }
++
++ case CTIO_A64_TYPE:
++ {
++ ctio_common_entry_t *entry = (ctio_common_entry_t *)pkt;
++ TRACE_DBG("CTIO_A64: instance %ld", ha->instance);
++ TRACE_BUFFER("Incoming CTIO_A64 packet data", entry,
++ REQUEST_ENTRY_SIZE);
++ q2t_do_ctio_completion(ha, entry->handle,
++ le16_to_cpu(entry->status)|(pkt->entry_status << 16),
++ entry);
++ break;
++ }
++
++ case IMMED_NOTIFY_TYPE:
++ TRACE_DBG("%s", "IMMED_NOTIFY");
++ q2t_handle_imm_notify(ha, (notify_entry_t *)pkt);
++ break;
++
++ case NOTIFY_ACK_TYPE:
++ if (tgt->notify_ack_expected > 0) {
++ nack_entry_t *entry = (nack_entry_t *)pkt;
++ TRACE_DBG("NOTIFY_ACK seq %08x status %x",
++ le16_to_cpu(entry->seq_id),
++ le16_to_cpu(entry->status));
++ TRACE_BUFFER("Incoming NOTIFY_ACK packet data", pkt,
++ RESPONSE_ENTRY_SIZE);
++ tgt->notify_ack_expected--;
++ if (entry->status != __constant_cpu_to_le16(NOTIFY_ACK_SUCCESS)) {
++ PRINT_ERROR("qla2x00t(%ld): NOTIFY_ACK "
++ "failed %x", ha->instance,
++ le16_to_cpu(entry->status));
++ }
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): Unexpected NOTIFY_ACK "
++ "received", ha->instance);
++ }
++ break;
++
++ case ABTS_RECV_24XX:
++ TRACE_DBG("ABTS_RECV_24XX: instance %ld", ha->instance);
++ TRACE_BUFF_FLAG(TRACE_BUFF, "Incoming ABTS_RECV "
++ "packet data", pkt, REQUEST_ENTRY_SIZE);
++ q24_handle_abts(ha, (abts24_recv_entry_t *)pkt);
++ break;
++
++ case ABTS_RESP_24XX:
++ if (tgt->abts_resp_expected > 0) {
++ abts24_resp_fw_entry_t *entry =
++ (abts24_resp_fw_entry_t *)pkt;
++ TRACE_DBG("ABTS_RESP_24XX: compl_status %x",
++ entry->compl_status);
++ TRACE_BUFF_FLAG(TRACE_BUFF, "Incoming ABTS_RESP "
++ "packet data", pkt, REQUEST_ENTRY_SIZE);
++ tgt->abts_resp_expected--;
++ if (le16_to_cpu(entry->compl_status) != ABTS_RESP_COMPL_SUCCESS) {
++ if ((entry->error_subcode1 == 0x1E) &&
++ (entry->error_subcode2 == 0)) {
++ /*
++ * We've got a race here: aborted exchange not
++ * terminated, i.e. response for the aborted
++ * command was sent between the abort request
++ * was received and processed. Unfortunately,
++ * the firmware has a silly requirement that
++ * all aborted exchanges must be explicitely
++ * terminated, otherwise it refuses to send
++ * responses for the abort requests. So, we
++ * have to (re)terminate the exchange and
++ * retry the abort response.
++ */
++ q24_retry_term_exchange(ha, entry);
++ } else
++ PRINT_ERROR("qla2x00t(%ld): ABTS_RESP_24XX "
++ "failed %x (subcode %x:%x)", ha->instance,
++ entry->compl_status, entry->error_subcode1,
++ entry->error_subcode2);
++ }
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): Unexpected ABTS_RESP_24XX "
++ "received", ha->instance);
++ }
++ break;
++
++ case MODIFY_LUN_TYPE:
++ if (tgt->modify_lun_expected > 0) {
++ modify_lun_entry_t *entry = (modify_lun_entry_t *)pkt;
++ TRACE_DBG("MODIFY_LUN %x, imm %c%d, cmd %c%d",
++ entry->status,
++ (entry->operators & MODIFY_LUN_IMM_ADD) ? '+'
++ : (entry->operators & MODIFY_LUN_IMM_SUB) ? '-'
++ : ' ',
++ entry->immed_notify_count,
++ (entry->operators & MODIFY_LUN_CMD_ADD) ? '+'
++ : (entry->operators & MODIFY_LUN_CMD_SUB) ? '-'
++ : ' ',
++ entry->command_count);
++ tgt->modify_lun_expected--;
++ if (entry->status != MODIFY_LUN_SUCCESS) {
++ PRINT_ERROR("qla2x00t(%ld): MODIFY_LUN "
++ "failed %x", ha->instance,
++ entry->status);
++ }
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): Unexpected MODIFY_LUN "
++ "received", (ha != NULL) ? (long)ha->instance : -1);
++ }
++ break;
++
++ case ENABLE_LUN_TYPE:
++ {
++ elun_entry_t *entry = (elun_entry_t *)pkt;
++ TRACE_DBG("ENABLE_LUN %x imm %u cmd %u ",
++ entry->status, entry->immed_notify_count,
++ entry->command_count);
++ if (entry->status == ENABLE_LUN_ALREADY_ENABLED) {
++ TRACE_DBG("LUN is already enabled: %#x",
++ entry->status);
++ entry->status = ENABLE_LUN_SUCCESS;
++ } else if (entry->status == ENABLE_LUN_RC_NONZERO) {
++ TRACE_DBG("ENABLE_LUN succeeded, but with "
++ "error: %#x", entry->status);
++ entry->status = ENABLE_LUN_SUCCESS;
++ } else if (entry->status != ENABLE_LUN_SUCCESS) {
++ PRINT_ERROR("qla2x00t(%ld): ENABLE_LUN "
++ "failed %x", ha->instance, entry->status);
++ qla_clear_tgt_mode(ha);
++ } /* else success */
++ break;
++ }
++
++ default:
++ PRINT_ERROR("qla2x00t(%ld): Received unknown response pkt "
++ "type %x", ha->instance, pkt->entry_type);
++ break;
++ }
++
++ tgt->irq_cmd_count--;
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
++ */
++static void q2t_async_event(uint16_t code, scsi_qla_host_t *ha,
++ uint16_t *mailbox)
++{
++ struct q2t_tgt *tgt = ha->tgt;
++
++ TRACE_ENTRY();
++
++ if (unlikely(tgt == NULL)) {
++ TRACE_DBG("ASYNC EVENT %#x, but no tgt (ha %p)", code, ha);
++ goto out;
++ }
++
++ /*
++ * In tgt_stop mode we also should allow all requests to pass.
++ * Otherwise, some commands can stuck.
++ */
++
++ tgt->irq_cmd_count++;
++
++ switch (code) {
++ case MBA_RESET: /* Reset */
++ case MBA_SYSTEM_ERR: /* System Error */
++ case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
++ case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
++ case MBA_ATIO_TRANSFER_ERR: /* ATIO Queue Transfer Error */
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): System error async event %#x "
++ "occured", ha->instance, code);
++ break;
++
++ case MBA_LOOP_UP:
++ {
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Async LOOP_UP occured "
++ "(m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", ha->instance,
++ le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]),
++ le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4]));
++ if (tgt->link_reinit_iocb_pending) {
++ q24_send_notify_ack(ha, &tgt->link_reinit_iocb, 0, 0, 0);
++ tgt->link_reinit_iocb_pending = 0;
++ }
++ break;
++ }
++
++ case MBA_LIP_OCCURRED:
++ case MBA_LOOP_DOWN:
++ case MBA_LIP_RESET:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Async event %#x occured "
++ "(m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", ha->instance,
++ code, le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]),
++ le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4]));
++ break;
++
++ case MBA_PORT_UPDATE:
++ case MBA_RSCN_UPDATE:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Port update async event %#x "
++ "occured: updating the ports database (m[1]=%x, m[2]=%x, "
++ "m[3]=%x, m[4]=%x)", ha->instance, code,
++ le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]),
++ le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4]));
++ /* .mark_all_devices_lost() is handled by the initiator driver */
++ break;
++
++ default:
++ TRACE(TRACE_MGMT, "qla2x00t(%ld): Async event %#x occured: "
++ "ignore (m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)",
++ ha->instance, code,
++ le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]),
++ le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4]));
++ break;
++ }
++
++ tgt->irq_cmd_count--;
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int q2t_get_target_name(scsi_qla_host_t *ha, char **wwn)
++{
++ const int wwn_len = 3*WWN_SIZE+2;
++ int res = 0;
++ char *name;
++
++ name = kmalloc(wwn_len, GFP_KERNEL);
++ if (name == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "%s", "qla2x00t: Allocation of tgt "
++ "name failed");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ sprintf(name, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
++ ha->port_name[0], ha->port_name[1],
++ ha->port_name[2], ha->port_name[3],
++ ha->port_name[4], ha->port_name[5],
++ ha->port_name[6], ha->port_name[7]);
++
++ *wwn = name;
++
++out:
++ return res;
++}
++
++static int q24_get_loop_id(scsi_qla_host_t *ha, atio7_entry_t *atio7,
++ uint16_t *loop_id)
++{
++ dma_addr_t gid_list_dma;
++ struct gid_list_info *gid_list;
++ char *id_iter;
++ int res, rc, i;
++ uint16_t entries;
++
++ TRACE_ENTRY();
++
++ gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
++ &gid_list_dma, GFP_KERNEL);
++ if (gid_list == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): DMA Alloc failed of %zd",
++ ha->instance, GID_LIST_SIZE);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ /* Get list of logged in devices */
++ rc = qla2x00_get_id_list(ha, gid_list, gid_list_dma, &entries);
++ if (rc != QLA_SUCCESS) {
++ PRINT_ERROR("qla2x00t(%ld): get_id_list() failed: %x",
++ ha->instance, rc);
++ res = -1;
++ goto out_free_id_list;
++ }
++
++ id_iter = (char *)gid_list;
++ res = -1;
++ for (i = 0; i < entries; i++) {
++ struct gid_list_info *gid = (struct gid_list_info *)id_iter;
++ if ((gid->al_pa == atio7->fcp_hdr.s_id[2]) &&
++ (gid->area == atio7->fcp_hdr.s_id[1]) &&
++ (gid->domain == atio7->fcp_hdr.s_id[0])) {
++ *loop_id = le16_to_cpu(gid->loop_id);
++ res = 0;
++ break;
++ }
++ id_iter += ha->gid_list_info_size;
++ }
++
++ if (res != 0) {
++ if ((atio7->fcp_hdr.s_id[0] == 0xFF) &&
++ (atio7->fcp_hdr.s_id[1] == 0xFC)) {
++ /*
++ * This is Domain Controller. It should be OK to drop
++ * SCSI commands from it.
++ */
++ TRACE_MGMT_DBG("Unable to find initiator with S_ID "
++ "%x:%x:%x", atio7->fcp_hdr.s_id[0],
++ atio7->fcp_hdr.s_id[1], atio7->fcp_hdr.s_id[2]);
++ } else
++ PRINT_ERROR("qla2x00t(%ld): Unable to find initiator with "
++ "S_ID %x:%x:%x", ha->instance,
++ atio7->fcp_hdr.s_id[0], atio7->fcp_hdr.s_id[1],
++ atio7->fcp_hdr.s_id[2]);
++ }
++
++out_free_id_list:
++ dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, gid_list, gid_list_dma);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Must be called under tgt_mutex */
++static struct q2t_sess *q2t_make_local_sess(scsi_qla_host_t *ha, atio_t *atio)
++{
++ struct q2t_sess *sess = NULL;
++ fc_port_t *fcport = NULL;
++ uint16_t loop_id = 0xFFFF; /* to remove warning */
++ int rc;
++
++ TRACE_ENTRY();
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ rc = q24_get_loop_id(ha, (atio7_entry_t *)atio, &loop_id);
++ if (rc != 0)
++ goto out;
++ } else
++ loop_id = GET_TARGET_ID(ha, (atio_entry_t *)atio);
++
++ fcport = kzalloc(sizeof(*fcport), GFP_KERNEL);
++ if (fcport == NULL) {
++ PRINT_ERROR("qla2x00t(%ld): Allocation of tmp FC port failed",
++ ha->instance);
++ goto out;
++ }
++
++ TRACE_MGMT_DBG("loop_id %d", loop_id);
++
++ fcport->loop_id = loop_id;
++
++ rc = qla2x00_get_port_database(ha, fcport, 0);
++ if (rc != QLA_SUCCESS) {
++ PRINT_ERROR("qla2x00t(%ld): Failed to retrieve fcport "
++ "information -- get_port_database() returned %x "
++ "(loop_id=0x%04x)", ha->instance, rc, loop_id);
++ goto out_free_fcport;
++ }
++
++ sess = q2t_create_sess(ha, fcport, true);
++
++out_free_fcport:
++ kfree(fcport);
++
++out:
++ TRACE_EXIT_HRES((unsigned long)sess);
++ return sess;
++}
++
++static int q2t_exec_sess_work(struct q2t_tgt *tgt,
++ struct q2t_sess_work_param *prm)
++{
++ scsi_qla_host_t *ha = tgt->ha;
++ int res = 0;
++ struct q2t_sess *sess = NULL;
++ struct q2t_cmd *cmd = prm->cmd;
++ atio_t *atio = (atio_t *)&cmd->atio;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("cmd %p", cmd);
++
++ mutex_lock(&ha->tgt_mutex);
++ spin_lock_irq(&ha->hardware_lock);
++
++ if (tgt->tgt_stop)
++ goto send;
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ atio7_entry_t *a = (atio7_entry_t *)atio;
++ sess = q2t_find_sess_by_s_id(tgt, a->fcp_hdr.s_id);
++ } else
++ sess = q2t_find_sess_by_loop_id(tgt,
++ GET_TARGET_ID(ha, (atio_entry_t *)atio));
++
++ if (sess != NULL) {
++ TRACE_MGMT_DBG("sess %p found", sess);
++ q2t_sess_get(sess);
++ } else {
++ /*
++ * We are under tgt_mutex, so a new sess can't be added
++ * behind us.
++ */
++ spin_unlock_irq(&ha->hardware_lock);
++ sess = q2t_make_local_sess(ha, atio);
++ spin_lock_irq(&ha->hardware_lock);
++ /* sess has got an extra creation ref */
++ }
++
++send:
++ if (!tgt->tm_to_unknown && !tgt->tgt_stop && (sess != NULL)) {
++ TRACE_MGMT_DBG("Sending work cmd %p to SCST", cmd);
++ res = q2t_do_send_cmd_to_scst(ha, cmd, sess);
++ } else {
++ /*
++ * Cmd might be already aborted behind us, so be safe and
++ * abort it. It should be OK, initiator will retry it. It has
++ * not sent to SCST yet, so pass NULL as the second argument.
++ */
++ TRACE_MGMT_DBG("Terminating work cmd %p", cmd);
++ if (IS_FWI2_CAPABLE(ha))
++ q24_send_term_exchange(ha, NULL , &cmd->atio.atio7, 1);
++ else
++ q2x_send_term_exchange(ha, NULL, &cmd->atio.atio2x, 1);
++ q2t_free_cmd(cmd);
++ }
++
++ if (sess != NULL)
++ q2t_sess_put(sess);
++
++ spin_unlock_irq(&ha->hardware_lock);
++ mutex_unlock(&ha->tgt_mutex);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static void q2t_sess_work_fn(struct work_struct *work)
++{
++ struct q2t_tgt *tgt = container_of(work, struct q2t_tgt, sess_work);
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Sess work (tgt %p)", tgt);
++
++ spin_lock_irq(&tgt->sess_work_lock);
++ while (!list_empty(&tgt->sess_works_list)) {
++ int rc;
++ struct q2t_sess_work_param *prm = list_entry(
++ tgt->sess_works_list.next, typeof(*prm),
++ sess_works_list_entry);
++
++ /*
++ * This work can be scheduled on several CPUs at time, so we
++ * must delete the entry to eliminate double processing
++ */
++ list_del(&prm->sess_works_list_entry);
++
++ spin_unlock_irq(&tgt->sess_work_lock);
++
++ rc = q2t_exec_sess_work(tgt, prm);
++
++ spin_lock_irq(&tgt->sess_work_lock);
++
++ if (rc != 0) {
++ TRACE_MGMT_DBG("Unable to complete sess work (tgt %p), "
++ "freeing cmd %p", tgt, prm->cmd);
++ q2t_free_cmd(prm->cmd);
++ }
++
++ kfree(prm);
++ }
++ spin_unlock_irq(&tgt->sess_work_lock);
++
++ spin_lock_irq(&tgt->ha->hardware_lock);
++ spin_lock(&tgt->sess_work_lock);
++ if (list_empty(&tgt->sess_works_list)) {
++ tgt->sess_works_pending = 0;
++ tgt->tm_to_unknown = 0;
++ }
++ spin_unlock(&tgt->sess_work_lock);
++ spin_unlock_irq(&tgt->ha->hardware_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++/* ha->hardware_lock supposed to be held and IRQs off */
++static void q2t_cleanup_hw_pending_cmd(scsi_qla_host_t *ha, struct q2t_cmd *cmd)
++{
++ uint32_t h;
++
++ for (h = 0; h < MAX_OUTSTANDING_COMMANDS; h++) {
++ if (ha->cmds[h] == cmd) {
++ TRACE_DBG("Clearing handle %d for cmd %p", h, cmd);
++ ha->cmds[h] = NULL;
++ break;
++ }
++ }
++ return;
++}
++
++static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd)
++{
++ struct q2t_cmd *cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
++ struct q2t_tgt *tgt = cmd->tgt;
++ scsi_qla_host_t *ha = tgt->ha;
++ unsigned long flags;
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Cmd %p HW pending for too long (state %x)", cmd,
++ cmd->state);
++
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++
++ if (cmd->sg_mapped)
++ q2t_unmap_sg(ha, cmd);
++
++ if (cmd->state == Q2T_STATE_PROCESSED) {
++ TRACE_MGMT_DBG("Force finishing cmd %p", cmd);
++ } else if (cmd->state == Q2T_STATE_NEED_DATA) {
++ TRACE_MGMT_DBG("Force rx_data cmd %p", cmd);
++
++ q2t_cleanup_hw_pending_cmd(ha, cmd);
++
++ scst_rx_data(scst_cmd, SCST_RX_STATUS_ERROR_FATAL,
++ SCST_CONTEXT_THREAD);
++ goto out_unlock;
++ } else if (cmd->state == Q2T_STATE_ABORTED) {
++ TRACE_MGMT_DBG("Force finishing aborted cmd %p (tag %d)",
++ cmd, cmd->tag);
++ } else {
++ PRINT_ERROR("qla2x00t(%ld): A command in state (%d) should "
++ "not be HW pending", ha->instance, cmd->state);
++ goto out_unlock;
++ }
++
++ q2t_cleanup_hw_pending_cmd(ha, cmd);
++
++ scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED);
++ scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_THREAD);
++
++out_unlock:
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ TRACE_EXIT();
++ return;
++}
++
++/* Must be called under tgt_host_action_mutex */
++static int q2t_add_target(scsi_qla_host_t *ha)
++{
++ int res, rc;
++ char *wwn;
++ int sg_tablesize;
++ struct q2t_tgt *tgt;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Registering target for host %ld(%p)", ha->host_no, ha);
++
++ BUG_ON((ha->q2t_tgt != NULL) || (ha->tgt != NULL));
++
++ tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
++ if (tgt == NULL) {
++ TRACE(TRACE_OUT_OF_MEM, "qla2x00t: %s", "Allocation of tgt "
++ "failed");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ tgt->ha = ha;
++ init_waitqueue_head(&tgt->waitQ);
++ INIT_LIST_HEAD(&tgt->sess_list);
++ INIT_LIST_HEAD(&tgt->del_sess_list);
++ init_timer(&tgt->sess_del_timer);
++ tgt->sess_del_timer.data = (unsigned long)tgt;
++ tgt->sess_del_timer.function = q2t_del_sess_timer_fn;
++ spin_lock_init(&tgt->sess_work_lock);
++ INIT_WORK(&tgt->sess_work, q2t_sess_work_fn);
++ INIT_LIST_HEAD(&tgt->sess_works_list);
++ spin_lock_init(&tgt->srr_lock);
++ INIT_LIST_HEAD(&tgt->srr_ctio_list);
++ INIT_LIST_HEAD(&tgt->srr_imm_list);
++ INIT_WORK(&tgt->srr_work, q2t_handle_srr_work);
++
++ ha->q2t_tgt = tgt;
++
++ if (q2t_get_target_name(ha, &wwn) != 0)
++ goto out_free;
++
++ tgt->scst_tgt = scst_register_target(&tgt2x_template, wwn);
++
++ kfree(wwn);
++
++ if (!tgt->scst_tgt) {
++ PRINT_ERROR("qla2x00t(%ld): scst_register_target() "
++ "failed for host %ld(%p)", ha->instance,
++ ha->host_no, ha);
++ res = -ENOMEM;
++ goto out_free;
++ }
++
++ if (IS_FWI2_CAPABLE(ha)) {
++ PRINT_INFO("qla2x00t(%ld): using 64 Bit PCI "
++ "addressing", ha->instance);
++ tgt->tgt_enable_64bit_addr = 1;
++ /* 3 is reserved */
++ sg_tablesize =
++ QLA_MAX_SG_24XX(ha->request_q_length - 3);
++ tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND_24XX;
++ tgt->datasegs_per_cont = DATASEGS_PER_CONT_24XX;
++ } else {
++ if (ha->flags.enable_64bit_addressing) {
++ PRINT_INFO("qla2x00t(%ld): 64 Bit PCI "
++ "addressing enabled", ha->instance);
++ tgt->tgt_enable_64bit_addr = 1;
++ /* 3 is reserved */
++ sg_tablesize =
++ QLA_MAX_SG64(ha->request_q_length - 3);
++ tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND64;
++ tgt->datasegs_per_cont = DATASEGS_PER_CONT64;
++ } else {
++ PRINT_INFO("qla2x00t(%ld): Using 32 Bit "
++ "PCI addressing", ha->instance);
++ sg_tablesize =
++ QLA_MAX_SG32(ha->request_q_length - 3);
++ tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND32;
++ tgt->datasegs_per_cont = DATASEGS_PER_CONT32;
++ }
++ }
++
++ rc = sysfs_create_link(scst_sysfs_get_tgt_kobj(tgt->scst_tgt),
++ &ha->host->shost_dev.kobj, "host");
++ if (rc != 0)
++ PRINT_ERROR("qla2x00t(%ld): Unable to create \"host\" link for "
++ "target %s", ha->instance,
++ scst_get_tgt_name(tgt->scst_tgt));
++
++ scst_tgt_set_sg_tablesize(tgt->scst_tgt, sg_tablesize);
++ scst_tgt_set_tgt_priv(tgt->scst_tgt, tgt);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ ha->q2t_tgt = NULL;
++ kfree(tgt);
++ goto out;
++}
++
++/* Must be called under tgt_host_action_mutex */
++static int q2t_remove_target(scsi_qla_host_t *ha)
++{
++ TRACE_ENTRY();
++
++ if ((ha->q2t_tgt == NULL) || (ha->tgt != NULL)) {
++ PRINT_ERROR("qla2x00t(%ld): Can't remove "
++ "existing target", ha->instance);
++ }
++
++ TRACE_DBG("Unregistering target for host %ld(%p)", ha->host_no, ha);
++ scst_unregister_target(ha->tgt->scst_tgt);
++ /*
++ * Free of tgt happens via callback q2t_target_release
++ * called from scst_unregister_target, so we shouldn't touch
++ * it again.
++ */
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static int q2t_host_action(scsi_qla_host_t *ha,
++ qla2x_tgt_host_action_t action)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ BUG_ON(ha == NULL);
++
++ /* To sync with q2t_exit() */
++ if (down_read_trylock(&q2t_unreg_rwsem) == 0)
++ goto out;
++
++ mutex_lock(&ha->tgt_host_action_mutex);
++
++ switch (action) {
++ case ADD_TARGET:
++ res = q2t_add_target(ha);
++ break;
++ case REMOVE_TARGET:
++ res = q2t_remove_target(ha);
++ break;
++ case ENABLE_TARGET_MODE:
++ {
++ fc_port_t *fcport;
++
++ if (qla_tgt_mode_enabled(ha)) {
++ PRINT_INFO("qla2x00t(%ld): Target mode already "
++ "enabled", ha->instance);
++ break;
++ }
++
++ if ((ha->q2t_tgt == NULL) || (ha->tgt != NULL)) {
++ PRINT_ERROR("qla2x00t(%ld): Can't enable target mode "
++ "for not existing target", ha->instance);
++ break;
++ }
++
++ PRINT_INFO("qla2x00t(%ld): Enabling target mode",
++ ha->instance);
++
++ spin_lock_irq(&ha->hardware_lock);
++ ha->tgt = ha->q2t_tgt;
++ ha->tgt->tgt_stop = 0;
++ spin_unlock_irq(&ha->hardware_lock);
++ list_for_each_entry_rcu(fcport, &ha->fcports, list) {
++ q2t_fc_port_added(ha, fcport);
++ }
++ TRACE_DBG("Enable tgt mode for host %ld(%ld,%p)",
++ ha->host_no, ha->instance, ha);
++ qla2x00_enable_tgt_mode(ha);
++ break;
++ }
++
++ case DISABLE_TARGET_MODE:
++ if (!qla_tgt_mode_enabled(ha)) {
++ PRINT_INFO("qla2x00t(%ld): Target mode already "
++ "disabled", ha->instance);
++ break;
++ }
++
++ PRINT_INFO("qla2x00t(%ld): Disabling target mode",
++ ha->instance);
++
++ BUG_ON(ha->tgt == NULL);
++
++ q2t_target_stop(ha->tgt->scst_tgt);
++ break;
++
++ default:
++ PRINT_ERROR("qla2x00t(%ld): %s: unsupported action %d",
++ ha->instance, __func__, action);
++ res = -EINVAL;
++ break;
++ }
++
++ mutex_unlock(&ha->tgt_host_action_mutex);
++
++ up_read(&q2t_unreg_rwsem);
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int q2t_enable_tgt(struct scst_tgt *scst_tgt, bool enable)
++{
++ struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++ scsi_qla_host_t *ha = tgt->ha;
++ int res;
++
++ if (enable)
++ res = q2t_host_action(ha, ENABLE_TARGET_MODE);
++ else
++ res = q2t_host_action(ha, DISABLE_TARGET_MODE);
++
++ return res;
++}
++
++static bool q2t_is_tgt_enabled(struct scst_tgt *scst_tgt)
++{
++ struct q2t_tgt *tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++ scsi_qla_host_t *ha = tgt->ha;
++
++ return qla_tgt_mode_enabled(ha);
++}
++
++static int q2t_get_initiator_port_transport_id(struct scst_session *scst_sess,
++ uint8_t **transport_id)
++{
++ struct q2t_sess *sess;
++ int res = 0;
++ int tr_id_size;
++ uint8_t *tr_id;
++
++ TRACE_ENTRY();
++
++ if (scst_sess == NULL) {
++ res = SCSI_TRANSPORTID_PROTOCOLID_FCP2;
++ goto out;
++ }
++
++ sess = (struct q2t_sess *)scst_sess_get_tgt_priv(scst_sess);
++
++ tr_id_size = 24;
++
++ tr_id = kzalloc(tr_id_size, GFP_KERNEL);
++ if (tr_id == NULL) {
++ PRINT_ERROR("qla2x00t: Allocation of TransportID (size %d) "
++ "failed", tr_id_size);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ tr_id[0] = SCSI_TRANSPORTID_PROTOCOLID_FCP2;
++
++ BUILD_BUG_ON(sizeof(sess->port_name) != 8);
++ memcpy(&tr_id[8], sess->port_name, 8);
++
++ *transport_id = tr_id;
++
++ TRACE_BUFF_FLAG(TRACE_DEBUG, "Created tid", tr_id, tr_id_size);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t q2t_show_expl_conf_enabled(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buffer)
++{
++ struct scst_tgt *scst_tgt;
++ struct q2t_tgt *tgt;
++ scsi_qla_host_t *ha;
++ ssize_t size;
++
++ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++ ha = tgt->ha;
++
++ size = scnprintf(buffer, PAGE_SIZE, "%d\n%s", ha->enable_explicit_conf,
++ ha->enable_explicit_conf ? SCST_SYSFS_KEY_MARK "\n" : "");
++
++ return size;
++}
++
++static ssize_t q2t_store_expl_conf_enabled(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buffer, size_t size)
++{
++ struct scst_tgt *scst_tgt;
++ struct q2t_tgt *tgt;
++ scsi_qla_host_t *ha;
++ unsigned long flags;
++
++ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++ ha = tgt->ha;
++
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++
++ switch (buffer[0]) {
++ case '0':
++ ha->enable_explicit_conf = 0;
++ PRINT_INFO("qla2x00t(%ld): explicit conformations disabled",
++ ha->instance);
++ break;
++ case '1':
++ ha->enable_explicit_conf = 1;
++ PRINT_INFO("qla2x00t(%ld): explicit conformations enabled",
++ ha->instance);
++ break;
++ default:
++ PRINT_ERROR("%s: qla2x00t(%ld): Requested action not "
++ "understood: %s", __func__, ha->instance, buffer);
++ break;
++ }
++
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
++ return size;
++}
++
++static ssize_t q2t_abort_isp_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buffer, size_t size)
++{
++ struct scst_tgt *scst_tgt;
++ struct q2t_tgt *tgt;
++ scsi_qla_host_t *ha;
++
++ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ tgt = (struct q2t_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++ ha = tgt->ha;
++
++ PRINT_INFO("qla2x00t(%ld): Aborting ISP", ha->instance);
++
++ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
++ qla2x00_wait_for_hba_online(ha);
++
++ return size;
++}
++
++static ssize_t q2t_version_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ sprintf(buf, "%s\n", Q2T_VERSION_STRING);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ strcat(buf, "EXTRACHECKS\n");
++#endif
++
++#ifdef CONFIG_SCST_TRACING
++ strcat(buf, "TRACING\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++ strcat(buf, "DEBUG\n");
++#endif
++
++#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
++ strcat(buf, "QLA_TGT_DEBUG_WORK_IN_THREAD\n");
++#endif
++
++ TRACE_EXIT();
++ return strlen(buf);
++}
++
++static uint16_t q2t_get_scsi_transport_version(struct scst_tgt *scst_tgt)
++{
++ /* FCP-2 */
++ return 0x0900;
++}
++
++static uint16_t q2t_get_phys_transport_version(struct scst_tgt *scst_tgt)
++{
++ return 0x0DA0; /* FC-FS */
++}
++
++static int __init q2t_init(void)
++{
++ int res = 0;
++
++ TRACE_ENTRY();
++
++ BUILD_BUG_ON(sizeof(atio7_entry_t) != sizeof(atio_entry_t));
++
++ PRINT_INFO("qla2x00t: Initializing QLogic Fibre Channel HBA Driver "
++ "target mode addon version %s", Q2T_VERSION_STRING);
++
++ q2t_cmd_cachep = KMEM_CACHE(q2t_cmd, SCST_SLAB_FLAGS);
++ if (q2t_cmd_cachep == NULL) {
++ res = -ENOMEM;
++ goto out;
++ }
++
++ q2t_mgmt_cmd_cachep = KMEM_CACHE(q2t_mgmt_cmd, SCST_SLAB_FLAGS);
++ if (q2t_mgmt_cmd_cachep == NULL) {
++ res = -ENOMEM;
++ goto out_cmd_free;
++ }
++
++ q2t_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab,
++ mempool_free_slab, q2t_mgmt_cmd_cachep);
++ if (q2t_mgmt_cmd_mempool == NULL) {
++ res = -ENOMEM;
++ goto out_kmem_free;
++ }
++
++ res = scst_register_target_template(&tgt2x_template);
++ if (res < 0)
++ goto out_mempool_free;
++
++ /*
++ * qla2xxx_tgt_register_driver() happens in q2t_target_detect
++ * called via scst_register_target_template()
++ */
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++ scst_unregister_target_template(&tgt2x_template);
++ qla2xxx_tgt_unregister_driver();
++
++out_mempool_free:
++ mempool_destroy(q2t_mgmt_cmd_mempool);
++
++out_kmem_free:
++ kmem_cache_destroy(q2t_mgmt_cmd_cachep);
++
++out_cmd_free:
++ kmem_cache_destroy(q2t_cmd_cachep);
++ goto out;
++}
++
++static void __exit q2t_exit(void)
++{
++ TRACE_ENTRY();
++
++ PRINT_INFO("qla2x00t: %s", "Unloading QLogic Fibre Channel HBA Driver "
++ "target mode addon driver");
++
++ /* To sync with q2t_host_action() */
++ down_write(&q2t_unreg_rwsem);
++
++ scst_unregister_target_template(&tgt2x_template);
++
++ /*
++ * Now we have everywhere target mode disabled and no possibilities
++ * to call us through sysfs, so we can safely remove all the references
++ * to our functions.
++ */
++ qla2xxx_tgt_unregister_driver();
++
++ mempool_destroy(q2t_mgmt_cmd_mempool);
++ kmem_cache_destroy(q2t_mgmt_cmd_cachep);
++ kmem_cache_destroy(q2t_cmd_cachep);
++
++ /* Let's make lockdep happy */
++ up_write(&q2t_unreg_rwsem);
++
++ TRACE_EXIT();
++ return;
++}
++
++module_init(q2t_init);
++module_exit(q2t_exit);
++
++MODULE_AUTHOR("Vladislav Bolkhovitin and others");
++MODULE_DESCRIPTION("Target mode addon for qla2[2,3,4,5+]xx");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(Q2T_VERSION_STRING);
+diff -uprN orig/linux-2.6.36/drivers/scst/qla2xxx-target/qla2x00t.h linux-2.6.36/drivers/scst/qla2xxx-target/qla2x00t.h
+--- orig/linux-2.6.36/drivers/scst/qla2xxx-target/qla2x00t.h
++++ linux-2.6.36/drivers/scst/qla2xxx-target/qla2x00t.h
+@@ -0,0 +1,273 @@
++/*
++ * qla2x00t.h
++ *
++ * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2004 - 2005 Leonid Stoljar
++ * Copyright (C) 2006 Nathaniel Clark <nate@misrule.us>
++ * Copyright (C) 2006 - 2010 ID7 Ltd.
++ *
++ * QLogic 22xx/23xx/24xx/25xx FC target driver.
++ *
++ * 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, version 2
++ * of the License.
++ *
++ * 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.
++ */
++
++#ifndef __QLA2X00T_H
++#define __QLA2X00T_H
++
++#include <qla_def.h>
++#include <qla2x_tgt.h>
++#include <qla2x_tgt_def.h>
++
++#include <scst_debug.h>
++
++/* Version numbers, the same as for the kernel */
++#define Q2T_VERSION(a, b, c, d) (((a) << 030) + ((b) << 020) + (c) << 010 + (d))
++#define Q2T_VERSION_CODE Q2T_VERSION(1, 0, 2, 0)
++#define Q2T_VERSION_STRING "2.0.0"
++#define Q2T_PROC_VERSION_NAME "version"
++
++#define Q2T_MAX_CDB_LEN 16
++#define Q2T_TIMEOUT 10 /* in seconds */
++
++#define Q2T_MAX_HW_PENDING_TIME 60 /* in seconds */
++
++/* Immediate notify status constants */
++#define IMM_NTFY_LIP_RESET 0x000E
++#define IMM_NTFY_LIP_LINK_REINIT 0x000F
++#define IMM_NTFY_IOCB_OVERFLOW 0x0016
++#define IMM_NTFY_ABORT_TASK 0x0020
++#define IMM_NTFY_PORT_LOGOUT 0x0029
++#define IMM_NTFY_PORT_CONFIG 0x002A
++#define IMM_NTFY_GLBL_TPRLO 0x002D
++#define IMM_NTFY_GLBL_LOGO 0x002E
++#define IMM_NTFY_RESOURCE 0x0034
++#define IMM_NTFY_MSG_RX 0x0036
++#define IMM_NTFY_SRR 0x0045
++#define IMM_NTFY_ELS 0x0046
++
++/* Immediate notify task flags */
++#define IMM_NTFY_TASK_MGMT_SHIFT 8
++
++#define Q2T_CLEAR_ACA 0x40
++#define Q2T_TARGET_RESET 0x20
++#define Q2T_LUN_RESET 0x10
++#define Q2T_CLEAR_TS 0x04
++#define Q2T_ABORT_TS 0x02
++#define Q2T_ABORT_ALL_SESS 0xFFFF
++#define Q2T_ABORT_ALL 0xFFFE
++#define Q2T_NEXUS_LOSS_SESS 0xFFFD
++#define Q2T_NEXUS_LOSS 0xFFFC
++
++/* Notify Acknowledge flags */
++#define NOTIFY_ACK_RES_COUNT BIT_8
++#define NOTIFY_ACK_CLEAR_LIP_RESET BIT_5
++#define NOTIFY_ACK_TM_RESP_CODE_VALID BIT_4
++
++/* Command's states */
++#define Q2T_STATE_NEW 0 /* New command and SCST processing it */
++#define Q2T_STATE_NEED_DATA 1 /* SCST needs data to continue */
++#define Q2T_STATE_DATA_IN 2 /* Data arrived and SCST processing it */
++#define Q2T_STATE_PROCESSED 3 /* SCST done processing */
++#define Q2T_STATE_ABORTED 4 /* Command aborted */
++
++/* Special handles */
++#define Q2T_NULL_HANDLE 0
++#define Q2T_SKIP_HANDLE (0xFFFFFFFF & ~CTIO_COMPLETION_HANDLE_MARK)
++
++/* ATIO task_codes field */
++#define ATIO_SIMPLE_QUEUE 0
++#define ATIO_HEAD_OF_QUEUE 1
++#define ATIO_ORDERED_QUEUE 2
++#define ATIO_ACA_QUEUE 4
++#define ATIO_UNTAGGED 5
++
++/* TM failed response codes, see FCP (9.4.11 FCP_RSP_INFO) */
++#define FC_TM_SUCCESS 0
++#define FC_TM_BAD_FCP_DATA 1
++#define FC_TM_BAD_CMD 2
++#define FC_TM_FCP_DATA_MISMATCH 3
++#define FC_TM_REJECT 4
++#define FC_TM_FAILED 5
++
++/*
++ * Error code of q2t_pre_xmit_response() meaning that cmd's exchange was
++ * terminated, so no more actions is needed and success should be returned
++ * to SCST. Must be different from any SCST_TGT_RES_* codes.
++ */
++#define Q2T_PRE_XMIT_RESP_CMD_ABORTED 0x1717
++
++#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
++#define pci_dma_lo32(a) (a & 0xffffffff)
++#define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff)
++#else
++#define pci_dma_lo32(a) (a & 0xffffffff)
++#define pci_dma_hi32(a) 0
++#endif
++
++struct q2t_tgt {
++ struct scst_tgt *scst_tgt;
++ scsi_qla_host_t *ha;
++
++ /*
++ * To sync between IRQ handlers and q2t_target_release(). Needed,
++ * because req_pkt() can drop/reaquire HW lock inside. Protected by
++ * HW lock.
++ */
++ int irq_cmd_count;
++
++ int datasegs_per_cmd, datasegs_per_cont;
++
++ /* Target's flags, serialized by ha->hardware_lock */
++ unsigned int tgt_enable_64bit_addr:1; /* 64-bits PCI addressing enabled */
++ unsigned int link_reinit_iocb_pending:1;
++ unsigned int tm_to_unknown:1; /* TM to unknown session was sent */
++ unsigned int sess_works_pending:1; /* there are sess_work entries */
++
++ /*
++ * Protected by tgt_mutex AND hardware_lock for writing and tgt_mutex
++ * OR hardware_lock for reading.
++ */
++ unsigned long tgt_stop; /* the driver is being stopped */
++
++ /* Count of sessions refering q2t_tgt. Protected by hardware_lock. */
++ int sess_count;
++
++ /* Protected by hardware_lock. Addition also protected by tgt_mutex. */
++ struct list_head sess_list;
++
++ /* Protected by hardware_lock */
++ struct list_head del_sess_list;
++ struct timer_list sess_del_timer;
++
++ spinlock_t sess_work_lock;
++ struct list_head sess_works_list;
++ struct work_struct sess_work;
++
++ notify24xx_entry_t link_reinit_iocb;
++ wait_queue_head_t waitQ;
++ int notify_ack_expected;
++ int abts_resp_expected;
++ int modify_lun_expected;
++
++ int ctio_srr_id;
++ int imm_srr_id;
++ spinlock_t srr_lock;
++ struct list_head srr_ctio_list;
++ struct list_head srr_imm_list;
++ struct work_struct srr_work;
++
++ struct list_head tgt_list_entry;
++};
++
++/*
++ * Equivilant to IT Nexus (Initiator-Target)
++ */
++struct q2t_sess {
++ uint16_t loop_id;
++ port_id_t s_id;
++
++ unsigned int conf_compl_supported:1;
++ unsigned int deleted:1;
++ unsigned int local:1;
++
++ struct scst_session *scst_sess;
++ struct q2t_tgt *tgt;
++
++ int sess_ref; /* protected by hardware_lock */
++
++ struct list_head sess_list_entry;
++ unsigned long expires;
++ struct list_head del_list_entry;
++
++ uint8_t port_name[WWN_SIZE];
++};
++
++struct q2t_cmd {
++ struct q2t_sess *sess;
++ int state;
++ struct scst_cmd *scst_cmd;
++
++ unsigned int conf_compl_supported:1;/* to save extra sess dereferences */
++ unsigned int sg_mapped:1;
++ unsigned int free_sg:1;
++ unsigned int aborted:1; /* Needed in case of SRR */
++ unsigned int write_data_transferred:1;
++
++ struct scatterlist *sg; /* cmd data buffer SG vector */
++ int sg_cnt; /* SG segments count */
++ int bufflen; /* cmd buffer length */
++ int offset;
++ scst_data_direction data_direction;
++ uint32_t tag;
++ dma_addr_t dma_handle;
++ enum dma_data_direction dma_data_direction;
++
++ uint16_t loop_id; /* to save extra sess dereferences */
++ struct q2t_tgt *tgt; /* to save extra sess dereferences */
++
++ union {
++ atio7_entry_t atio7;
++ atio_entry_t atio2x;
++ } __attribute__((packed)) atio;
++};
++
++struct q2t_sess_work_param {
++ struct list_head sess_works_list_entry;
++ struct q2t_cmd *cmd;
++};
++
++struct q2t_mgmt_cmd {
++ struct q2t_sess *sess;
++ unsigned int flags;
++#define Q24_MGMT_SEND_NACK 1
++ union {
++ atio7_entry_t atio7;
++ notify_entry_t notify_entry;
++ notify24xx_entry_t notify_entry24;
++ abts24_recv_entry_t abts;
++ } __attribute__((packed)) orig_iocb;
++};
++
++struct q2t_prm {
++ struct q2t_cmd *cmd;
++ struct q2t_tgt *tgt;
++ void *pkt;
++ struct scatterlist *sg; /* cmd data buffer SG vector */
++ int seg_cnt;
++ int req_cnt;
++ uint16_t rq_result;
++ uint16_t scsi_status;
++ unsigned char *sense_buffer;
++ int sense_buffer_len;
++ int residual;
++ int add_status_pkt;
++};
++
++struct srr_imm {
++ struct list_head srr_list_entry;
++ int srr_id;
++ union {
++ notify_entry_t notify_entry;
++ notify24xx_entry_t notify_entry24;
++ } __attribute__((packed)) imm;
++};
++
++struct srr_ctio {
++ struct list_head srr_list_entry;
++ int srr_id;
++ struct q2t_cmd *cmd;
++};
++
++#define Q2T_XMIT_DATA 1
++#define Q2T_XMIT_STATUS 2
++#define Q2T_XMIT_ALL (Q2T_XMIT_STATUS|Q2T_XMIT_DATA)
++
++#endif /* __QLA2X00T_H */
+diff -uprN orig/linux-2.6.36/Documentation/scst/README.qla2x00t linux-2.6.36/Documentation/scst/README.qla2x00t
+--- orig/linux-2.6.36/Documentation/scst/README.qla2x00t
++++ linux-2.6.36/Documentation/scst/README.qla2x00t
+@@ -0,0 +1,526 @@
++Target driver for Qlogic 22xx/23xx/24xx/25xx Fibre Channel cards
++================================================================
++
++Version 2.0.0, XX XXXXX 2010
++----------------------------
++
++This driver consists from two parts: the target mode driver itself and
++the changed initiator driver from Linux kernel, which is, particularly,
++intended to perform all the initialization and shutdown tasks. The
++initiator driver was changed to provide the target mode support and all
++necessary callbacks, but it's still capable to work as initiator only.
++Mode, when a host acts as the initiator and the target simultaneously,
++is supported as well.
++
++This version is compatible with SCST core version 2.0.0 and higher and
++Linux kernel 2.6.26 and higher. Sorry, kernels below 2.6.26 are not
++supported, because it's too hard to backport used initiator driver to
++older kernels.
++
++NPIV is partially supported by this driver. You can create virtual
++targets using standard Linux interface by echoing wwpn:wwnn into
++/sys/class/fc_host/hostX/vport_create and work with them, but SCST core
++will not see those virtual targets and, hence, provide the
++target-oriented access control for them. However, the initiator-oriented
++access control will still work very well. Note, you need NPIV-supporting
++firmware as well as NPIV-supporting switches to use NPIV.
++
++The original initiator driver was taken from the kernel 2.6.26. Also the
++following 2.6.26.x commits have been applied to it (upstream ID):
++048feec5548c0582ee96148c61b87cccbcb5f9be,
++031e134e5f95233d80fb1b62fdaf5e1be587597c,
++5f3a9a207f1fccde476dd31b4c63ead2967d934f,
++85821c906cf3563a00a3d98fa380a2581a7a5ff1,
++3c01b4f9fbb43fc911acd33ea7a14ea7a4f9866b,
++8eca3f39c4b11320787f7b216f63214aee8415a9.
++
++See also "ToDo" file for list of known issues and unimplemented
++features.
++
++Installation
++------------
++
++Only vanilla kernels from kernel.org and RHEL/CentOS 5.2 kernels are
++supported, but SCST should work on other (vendors') kernels, if you
++manage to successfully compile it on them. The main problem with
++vendors' kernels is that they often contain patches, which will appear
++only in the next version of the vanilla kernel, therefore it's quite
++hard to track such changes. Thus, if during compilation for some vendor
++kernel your compiler complains about redefinition of some symbol, you
++should either switch to vanilla kernel, or add or change as necessary
++the corresponding to that symbol "#if LINUX_VERSION_CODE" statement.
++
++Before installation make sure that the link
++"/lib/modules/`you_kernel_version`/build" points to the source code for
++your currently running kernel.
++
++Then you should replace (or link) by the initiator driver from this
++package "qla2xxx" subdirectory in kernel_source/drivers/scsi/ of the
++currently running kernel and using your favorite kernel configuration
++tool enable in the QLogic QLA2XXX Fibre Channel driver target mode
++support (CONFIG_SCSI_QLA2XXX_TARGET). Then rebuild the kernel and its
++modules. During this step you will compile the initiator driver. To
++install it, install the built kernel and its modules.
++
++Then edit qla2x00-target/Makefile and set SCST_INC_DIR variable to point
++to the directory, where SCST's public include files are located. If you
++install QLA2x00 target driver's source code in the SCST's directory,
++then SCST_INC_DIR will be set correctly for you.
++
++Also you can set SCST_DIR variable to the directory, where SCST was
++built, but this is optional. If you don't set it or set incorrectly,
++during the compilation you will get a bunch of harmless warnings like
++"WARNING: "scst_rx_data" [/XXX/qla2x00tgt.ko] undefined!"
++
++To compile the target driver, type 'make' in qla2x00-target/
++subdirectory. It will build qla2x00tgt.ko module.
++
++To install the target driver, type 'make install' in qla2x00-target/
++subdirectory. The target driver will be installed in
++/lib/modules/`you_kernel_version`/extra. To uninstall it, type 'make
++uninstall'.
++
++Usage
++-----
++
++After the drivers are loaded and adapters successfully initialized by
++the initiator driver, including firmware image load, you should
++configure exported devices using the corresponding interface of SCST
++core. It is highly recommended to use scstadmin utility for that
++purpose.
++
++Then target mode should be enabled via a sysfs interface on a per card
++basis, like:
++
++echo "1" >/sys/kernel/scst_tgt/targets/qla2x00t/target/enabled
++
++See below for full description of the driver's sysfs interface.
++
++With the obsolete proc interface you should instead use
++target_mode_enabled under the appropriate scsi_host entry, like:
++
++echo "1" >/sys/class/scsi_host/host0/target_mode_enabled
++
++You can find some installation and configuration HOWTOs in
++http://scst.sourceforge.net/qla2x00t-howto.html and
++https://forums.openfiler.com/viewtopic.php?id=3422.
++
++IMPORTANT USAGE NOTES
++---------------------
++
++1. It is strongly recommended to use firmware version 5.x or higher
++for 24xx/25xx adapters. See
++http://sourceforge.net/mailarchive/forum.php?thread_name=4B4CD39F.6020401%40vlnb.net&forum_name=scst-devel
++for more details why.
++
++2. If you reload qla2x00tgt module, you should also reload qla2xxx
++module, otherwise your initiators could not see the target, when it is
++enabled after qla2x00tgt module load.
++
++3. If you delete and then add back with the same WWN an NPIV initiator
++on the initiator side, make sure it has the same port_id as well. In
++Fibre Channel initiators identified by port_id (s_id in FC terms), so if
++the recreated NPIV initiator has another port_id, which was already used
++by another (NPIV) initiator, those initiators could be confused by the
++target and assigned to incorrect security groups, hence they could see
++incorrect LUNs.
++
++If you can't ensure the same port_id's for recreated initiators, it is
++safer to restart qla2x00tgt and qla2xxx modules on the target to make
++sure the target doesn't have any initiator port_id cached.
++
++Initiator and target modes
++--------------------------
++
++When qla2xxx compiled with CONFIG_SCSI_QLA2XXX_TARGET enabled, it has
++parameter "qlini_mode", which determines when initiator mode will be
++enabled. Possible values:
++
++ - "exclusive" (default ) - initiator mode will be enabled on load,
++disabled on enabling target mode and then on disabling target mode
++enabled back.
++
++ - "disabled" - initiator mode will never be enabled.
++
++ - "enabled" - initiator mode will always stay enabled.
++
++Usage of mode "disabled" is recommended, if you have incorrectly
++functioning your target's initiators, which if once seen a port in
++initiator mode, later refuse to see it as a target. Although this mode
++does make a noticeable difference, it isn't absolutely strong, since the
++firmware once initialized requires a HBA to be in either initiator, or
++target mode, so until you enable target mode on a port, your initiators
++will report this port as working in initiator mode. If you need
++absolutely strong assurance that initiator mode never enabled, you can
++consider using patch
++unsupported-patches/qla_delayed_hw_init_tgt_mode_from_the_beginning.diff.
++See description of it inside the patch.
++
++Use mode "enabled" if you need your QLA adapters to work in both
++initiator and target modes at the same time.
++
++You can always see which modes are currently active in active_mode sysfs
++attribute.
++
++In all the modes you can at any time use sysfs attribute
++ini_mode_force_reverse to force enable or disable initiator mode on any
++particular port. Setting this attribute to 1 will reverse current status
++of the initiator mode from enabled to disabled and vice versa.
++
++Explicit conformation
++---------------------
++
++This option should (actually, almost always must) be enabled by echoing
++"1" in /sys/kernel/scst_tgt/targets/qla2x00t/target/host/explicit_conform_enabled,
++if a target card exports at least one stateful SCSI device, like tape,
++and class 2 isn't used, otherwise link-level errors could lead to loss
++of the target/initiator state synchronization. Also check if initiator
++supports this feature, it is reported in the kernel logs ("confirmed
++completion supported" or not). No major performance degradation was
++noticed, if it is enabled. Supported only for 23xx+. Disabled by
++default.
++
++Class 2
++-------
++
++Class 2 is the close equivalent of the TCP in the IP world. If you
++enable it, all the Fibre Channel packets will be acknowledged. By
++default, class 3 is used, which is UDP-like. Enable it by echoing "1" in
++/sys/kernel/scst_tgt/targets/qla2x00t/target/host/class2_enabled. This
++option needs a special firmware with class 2 support. Disabled by
++default.
++
++Compilation options
++-------------------
++
++There are the following compilation options, that could be commented
++in/out in Makefile:
++
++ - CONFIG_SCST_DEBUG - turns on some debugging code, including some logging.
++ Makes the driver considerably bigger and slower, producing large amount of
++ log data.
++
++ - CONFIG_SCST_TRACING - turns on ability to log events. Makes the driver
++ considerably bigger and leads to some performance loss.
++
++ - CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD - makes SCST process incoming
++ commands from the qla2x00t target driver and call the driver's
++ callbacks in internal SCST threads context instead of SIRQ context,
++ where those commands were received. Useful for debugging and lead to
++ some performance loss.
++
++ - CONFIG_QLA_TGT_DEBUG_SRR - turns on retransmitting packets (SRR)
++ debugging. In this mode some CTIOs will be "broken" to force the
++ initiator to issue a retransmit request.
++
++Sysfs interface
++---------------
++
++Starting from 2.0.0 this driver has sysfs interface. The procfs
++interface from version 2.0.0 is obsolete and will be removed in one of
++the next versions.
++
++Root of SCST sysfs interface is /sys/kernel/scst_tgt. Root of this
++driver is /sys/kernel/scst_tgt/targets/qla2x00t. It has the following
++entries:
++
++ - None, one or more subdirectories for targets with name equal to port
++ names of the corresponding targets.
++
++ - trace_level - allows to enable and disable various tracing
++ facilities. See content of this file for help how to use it.
++
++ - version - read-only attribute, which allows to see version of
++ this driver and enabled optional features.
++
++Each target subdirectory contains the following entries:
++
++ - host - link pointing on the corresponding scsi_host of the initiator
++ driver
++
++ - ini_groups - subdirectory defining initiator groups for this target,
++ used to define per-initiator access control. See SCST core README for
++ more details.
++
++ - luns - subdirectory defining LUNs of this target. See SCST core
++ README for more details.
++
++ - sessions - subdirectory containing connected to this target sessions.
++
++ - enabled - using this attribute you can enable or disable target mode
++ of this FC port. It allows to finish configuring it before it starts
++ accepting new connections. 0 by default.
++
++ - explicit_confirmation - allows to enable explicit conformations, see
++ above.
++
++ - rel_tgt_id - allows to read or write SCSI Relative Target Port
++ Identifier attribute. This identifier is used to identify SCSI Target
++ Ports by some SCSI commands, mainly by Persistent Reservations
++ commands. This identifier must be unique among all SCST targets, but
++ for convenience SCST allows disabled targets to have not unique
++ rel_tgt_id. In this case SCST will not allow to enable this target
++ until rel_tgt_id becomes unique. This attribute initialized unique by
++ SCST by default.
++
++Subdirectory "sessions" contains one subdirectory for each connected
++session with name equal to port name of the connected initiator.
++
++Each session subdirectory contains the following entries:
++
++ - initiator_name - contains initiator's port name
++
++ - active_commands - contains number of active, i.e. not yet or being
++ executed, SCSI commands in this session.
++
++ - commands - contains overall number of SCSI commands in this session.
++
++Below is a sample script, which configures 1 virtual disk "disk1" using
++/disk1 image for usage with 25:00:00:f0:98:87:92:f3 target. All
++initiators connected to this target will see this device.
++
++#!/bin/bash
++
++modprobe scst
++modprobe scst_vdisk
++
++echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
++
++modprobe qla2x00tgt
++
++echo "add disk1 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
++echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
++
++Below is another sample script, which configures 1 real local SCSI disk
++0:0:1:0 for usage with 25:00:00:f0:98:87:92:f3 target:
++
++#!/bin/bash
++
++modprobe scst
++modprobe scst_disk
++
++echo "add_device 0:0:1:0" >/sys/kernel/scst_tgt/handlers/dev_disk/mgmt
++
++modprobe qla2x00tgt
++
++echo "add 0:0:1:0 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
++echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
++
++Below is an advanced sample script, which configures more virtual
++devices of various types, including virtual CDROM. In this script
++initiator 25:00:00:f0:99:87:94:a3 will see disk1 and disk2 devices, all
++other initiators will see read only blockio, nullio and cdrom devices.
++
++#!/bin/bash
++
++modprobe scst
++modprobe scst_vdisk
++
++echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
++echo "add_device disk2 filename=/disk2; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
++echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
++echo "add_device nullio" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
++echo "add_device cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt
++
++modprobe qla2x00tgt
++
++echo "add blockio 0 read_only=1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
++echo "add nullio 1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
++echo "add cdrom 2" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
++
++echo "create 25:00:00:f0:99:87:94:a3" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/mgmt
++echo "add disk1 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/mgmt
++echo "add disk2 1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/mgmt
++echo "add 25:00:00:f0:99:87:94:a3" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/initiators/mgmt
++
++echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
++
++The resulting overall SCST sysfs hierarchy with initiator
++25:00:00:f0:99:87:94:a3 connected will look like:
++
++/sys/kernel/scst_tgt
++|-- devices
++| |-- blockio
++| | |-- blocksize
++| | |-- exported
++| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/0
++| | |-- filename
++| | |-- handler -> ../../handlers/vdisk_blockio
++| | |-- nv_cache
++| | |-- read_only
++| | |-- removable
++| | |-- resync_size
++| | |-- size_mb
++| | |-- t10_dev_id
++| | |-- threads_num
++| | |-- threads_pool_type
++| | |-- type
++| | `-- usn
++| |-- cdrom
++| | |-- exported
++| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/2
++| | |-- filename
++| | |-- handler -> ../../handlers/vcdrom
++| | |-- size_mb
++| | |-- t10_dev_id
++| | |-- threads_num
++| | |-- threads_pool_type
++| | |-- type
++| | `-- usn
++| |-- disk1
++| | |-- blocksize
++| | |-- exported
++| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/0
++| | |-- filename
++| | |-- handler -> ../../handlers/vdisk_fileio
++| | |-- nv_cache
++| | |-- o_direct
++| | |-- read_only
++| | |-- removable
++| | |-- resync_size
++| | |-- size_mb
++| | |-- t10_dev_id
++| | |-- threads_num
++| | |-- threads_pool_type
++| | |-- type
++| | |-- usn
++| | `-- write_through
++| |-- disk2
++| | |-- blocksize
++| | |-- exported
++| | | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/1
++| | |-- filename
++| | |-- handler -> ../../handlers/vdisk_fileio
++| | |-- nv_cache
++| | |-- o_direct
++| | |-- read_only
++| | |-- removable
++| | |-- resync_size
++| | |-- size_mb
++| | |-- t10_dev_id
++| | |-- threads_num
++| | |-- threads_pool_type
++| | |-- type
++| | |-- usn
++| | `-- write_through
++| `-- nullio
++| |-- blocksize
++| |-- exported
++| | `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/1
++| |-- handler -> ../../handlers/vdisk_nullio
++| |-- read_only
++| |-- removable
++| |-- size_mb
++| |-- t10_dev_id
++| |-- threads_num
++| |-- threads_pool_type
++| |-- type
++| `-- usn
++|-- handlers
++| |-- vcdrom
++| | |-- cdrom -> ../../devices/cdrom
++| | |-- mgmt
++| | |-- trace_level
++| | `-- type
++| |-- vdisk_blockio
++| | |-- blockio -> ../../devices/blockio
++| | |-- mgmt
++| | |-- trace_level
++| | `-- type
++| |-- vdisk_fileio
++| | |-- disk1 -> ../../devices/disk1
++| | |-- disk2 -> ../../devices/disk2
++| | |-- mgmt
++| | |-- trace_level
++| | `-- type
++| `-- vdisk_nullio
++| |-- mgmt
++| |-- nullio -> ../../devices/nullio
++| |-- trace_level
++| `-- type
++|-- sgv
++| |-- global_stats
++| |-- sgv
++| | `-- stats
++| |-- sgv-clust
++| | `-- stats
++| `-- sgv-dma
++| `-- stats
++|-- targets
++| `-- qla2x00t
++| |-- 25:00:00:f0:98:87:92:f3
++| | |-- enabled
++| | |-- explicit_confirmation
++| | |-- host -> ../../../../../class/scsi_host/host4
++| | |-- ini_groups
++| | | |-- 25:00:00:f0:99:87:94:a3
++| | | | |-- initiators
++| | | | | |-- 25:00:00:f0:99:87:94:a3
++| | | | | `-- mgmt
++| | | | `-- luns
++| | | | |-- 0
++| | | | | |-- device -> ../../../../../../../devices/disk1
++| | | | | `-- read_only
++| | | | |-- 1
++| | | | | |-- device -> ../../../../../../../devices/disk2
++| | | | | `-- read_only
++| | | | `-- mgmt
++| | | `-- mgmt
++| | |-- luns
++| | | |-- 0
++| | | | |-- device -> ../../../../../devices/blockio
++| | | | `-- read_only
++| | | |-- 1
++| | | | |-- device -> ../../../../../devices/nullio
++| | | | `-- read_only
++| | | |-- 2
++| | | | |-- device -> ../../../../../devices/cdrom
++| | | | `-- read_only
++| | | `-- mgmt
++| | |-- rel_tgt_id
++| | `-- sessions
++| | `-- 25:00:00:f0:99:87:94:a3
++| | |-- active_commands
++| | |-- commands
++| | |-- initiator_name
++| | `-- luns -> ../../ini_groups/25:00:00:f0:99:87:94:a3/luns
++| |-- trace_level
++| `-- version
++|-- threads
++|-- trace_level
++`-- version
++
++Performance advices
++-------------------
++
++1. If you are going to use your target in an VM environment, for
++instance as a shared storage with VMware, make sure all your VMs
++connected to the target via *separate* sessions. You can check it using
++SCST proc or sysfs interface. You should use available facilities, like
++NPIV, to make separate sessions for each VM. If you miss it, you can
++greatly loose performance of parallel access to your target from
++different VMs. This isn't related to the case if your VMs are using the
++same shared storage, like with VMFS, for instance. In this case all your
++VM hosts will be connected to the target via separate sessions, which is
++enough.
++
++2. See SCST core's README for more advices. Especially pay attention to
++have io_grouping_type option set correctly.
++
++Credits
++-------
++
++Thanks to:
++
++ * QLogic support for their invaluable help.
++
++ * Nathaniel Clark <nate@misrule.us> for porting to new 2.6 kernel
++initiator driver.
++
++ * Mark Buechler <mark.buechler@gmail.com> for the original
++WWN-based authentification, a lot of useful suggestions, bug reports and
++help in debugging.
++
++ * Ming Zhang <mingz@ele.uri.edu> for fixes.
++
++Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
+diff -uprN orig/linux-2.6.36/drivers/scst/srpt/Kconfig linux-2.6.36/drivers/scst/srpt/Kconfig
+--- orig/linux-2.6.36/drivers/scst/srpt/Kconfig
++++ linux-2.6.36/drivers/scst/srpt/Kconfig
+@@ -0,0 +1,12 @@
++config SCST_SRPT
++ tristate "InfiniBand SCSI RDMA Protocol target support"
++ depends on INFINIBAND && SCST
++ ---help---
++
++ Support for the SCSI RDMA Protocol (SRP) Target driver. The
++ SRP protocol is a protocol that allows an initiator to access
++ a block storage device on another host (target) over a network
++ that supports the RDMA protocol. Currently the RDMA protocol is
++ supported by InfiniBand and by iWarp network hardware. More
++ information about the SRP protocol can be found on the website
++ of the INCITS T10 technical committee (http://www.t10.org/).
+diff -uprN orig/linux-2.6.36/drivers/scst/srpt/Makefile linux-2.6.36/drivers/scst/srpt/Makefile
+--- orig/linux-2.6.36/drivers/scst/srpt/Makefile
++++ linux-2.6.36/drivers/scst/srpt/Makefile
+@@ -0,0 +1,1 @@
++obj-$(CONFIG_SCST_SRPT) += ib_srpt.o
+diff -uprN orig/linux-2.6.36/drivers/scst/srpt/ib_dm_mad.h linux-2.6.36/drivers/scst/srpt/ib_dm_mad.h
+--- orig/linux-2.6.36/drivers/scst/srpt/ib_dm_mad.h
++++ linux-2.6.36/drivers/scst/srpt/ib_dm_mad.h
+@@ -0,0 +1,139 @@
++/*
++ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++#ifndef IB_DM_MAD_H
++#define IB_DM_MAD_H
++
++#include <linux/types.h>
++
++#include <rdma/ib_mad.h>
++
++enum {
++ /*
++ * See also section 13.4.7 Status Field, table 115 MAD Common Status
++ * Field Bit Values and also section 16.3.1.1 Status Field in the
++ * InfiniBand Architecture Specification.
++ */
++ DM_MAD_STATUS_UNSUP_METHOD = 0x0008,
++ DM_MAD_STATUS_UNSUP_METHOD_ATTR = 0x000c,
++ DM_MAD_STATUS_INVALID_FIELD = 0x001c,
++ DM_MAD_STATUS_NO_IOC = 0x0100,
++
++ /*
++ * See also the Device Management chapter, section 16.3.3 Attributes,
++ * table 279 Device Management Attributes in the InfiniBand
++ * Architecture Specification.
++ */
++ DM_ATTR_CLASS_PORT_INFO = 0x01,
++ DM_ATTR_IOU_INFO = 0x10,
++ DM_ATTR_IOC_PROFILE = 0x11,
++ DM_ATTR_SVC_ENTRIES = 0x12
++};
++
++struct ib_dm_hdr {
++ u8 reserved[28];
++};
++
++/*
++ * Structure of management datagram sent by the SRP target implementation.
++ * Contains a management datagram header, reliable multi-packet transaction
++ * protocol (RMPP) header and ib_dm_hdr. Notes:
++ * - The SRP target implementation does not use RMPP or ib_dm_hdr when sending
++ * management datagrams.
++ * - The header size must be exactly 64 bytes (IB_MGMT_DEVICE_HDR), since this
++ * is the header size that is passed to ib_create_send_mad() in ib_srpt.c.
++ * - The maximum supported size for a management datagram when not using RMPP
++ * is 256 bytes -- 64 bytes header and 192 (IB_MGMT_DEVICE_DATA) bytes data.
++ */
++struct ib_dm_mad {
++ struct ib_mad_hdr mad_hdr;
++ struct ib_rmpp_hdr rmpp_hdr;
++ struct ib_dm_hdr dm_hdr;
++ u8 data[IB_MGMT_DEVICE_DATA];
++};
++
++/*
++ * IOUnitInfo as defined in section 16.3.3.3 IOUnitInfo of the InfiniBand
++ * Architecture Specification.
++ */
++struct ib_dm_iou_info {
++ __be16 change_id;
++ u8 max_controllers;
++ u8 op_rom;
++ u8 controller_list[128];
++};
++
++/*
++ * IOControllerprofile as defined in section 16.3.3.4 IOControllerProfile of
++ * the InfiniBand Architecture Specification.
++ */
++struct ib_dm_ioc_profile {
++ __be64 guid;
++ __be32 vendor_id;
++ __be32 device_id;
++ __be16 device_version;
++ __be16 reserved1;
++ __be32 subsys_vendor_id;
++ __be32 subsys_device_id;
++ __be16 io_class;
++ __be16 io_subclass;
++ __be16 protocol;
++ __be16 protocol_version;
++ __be16 service_conn;
++ __be16 initiators_supported;
++ __be16 send_queue_depth;
++ u8 reserved2;
++ u8 rdma_read_depth;
++ __be32 send_size;
++ __be32 rdma_size;
++ u8 op_cap_mask;
++ u8 svc_cap_mask;
++ u8 num_svc_entries;
++ u8 reserved3[9];
++ u8 id_string[64];
++};
++
++struct ib_dm_svc_entry {
++ u8 name[40];
++ __be64 id;
++};
++
++/*
++ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture
++ * Specification. See also section B.7, table B.8 in the T10 SRP r16a document.
++ */
++struct ib_dm_svc_entries {
++ struct ib_dm_svc_entry service_entries[4];
++};
++
++#endif
+diff -uprN orig/linux-2.6.36/drivers/scst/srpt/ib_srpt.c linux-2.6.36/drivers/scst/srpt/ib_srpt.c
+--- orig/linux-2.6.36/drivers/scst/srpt/ib_srpt.c
++++ linux-2.6.36/drivers/scst/srpt/ib_srpt.c
+@@ -0,0 +1,3698 @@
++/*
++ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
++ * Copyright (C) 2008 Vladislav Bolkhovitin <vst@vlnb.net>
++ * Copyright (C) 2008 - 2010 Bart Van Assche <bart.vanassche@gmail.com>
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/ctype.h>
++#include <linux/kthread.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <asm/atomic.h>
++#include "ib_srpt.h"
++#define LOG_PREFIX "ib_srpt" /* Prefix for SCST tracing macros. */
++#include <scst/scst_debug.h>
++
++/* Name of this kernel module. */
++#define DRV_NAME "ib_srpt"
++#define DRV_VERSION "2.0.0"
++#define DRV_RELDATE "October 25, 2010"
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++/* Flags to be used in SCST debug tracing statements. */
++#define DEFAULT_SRPT_TRACE_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR \
++ | TRACE_MGMT | TRACE_SPECIAL)
++/* Name of the entry that will be created under /proc/scsi_tgt/ib_srpt. */
++#define SRPT_PROC_TRACE_LEVEL_NAME "trace_level"
++#endif
++
++#define MELLANOX_SRPT_ID_STRING "SCST SRP target"
++
++MODULE_AUTHOR("Vu Pham");
++MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol target "
++ "v" DRV_VERSION " (" DRV_RELDATE ")");
++MODULE_LICENSE("Dual BSD/GPL");
++
++/*
++ * Local data types.
++ */
++
++enum threading_mode {
++ MODE_ALL_IN_SIRQ = 0,
++ MODE_IB_COMPLETION_IN_THREAD = 1,
++ MODE_IB_COMPLETION_IN_SIRQ = 2,
++};
++
++/*
++ * Global Variables
++ */
++
++static u64 srpt_service_guid;
++/* List of srpt_device structures. */
++static atomic_t srpt_device_count;
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++static unsigned long trace_flag = DEFAULT_SRPT_TRACE_FLAGS;
++module_param(trace_flag, long, 0644);
++MODULE_PARM_DESC(trace_flag, "SCST trace flags.");
++#endif
++
++static int thread = 1;
++module_param(thread, int, 0444);
++MODULE_PARM_DESC(thread,
++ "IB completion and SCSI command processing context. Defaults"
++ " to one, i.e. process IB completions and SCSI commands in"
++ " kernel thread context. 0 means soft IRQ whenever possible"
++ " and 2 means process IB completions in soft IRQ context and"
++ " SCSI commands in kernel thread context.");
++
++static unsigned srp_max_rdma_size = DEFAULT_MAX_RDMA_SIZE;
++module_param(srp_max_rdma_size, int, 0744);
++MODULE_PARM_DESC(srp_max_rdma_size,
++ "Maximum size of SRP RDMA transfers for new connections.");
++
++static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;
++module_param(srp_max_req_size, int, 0444);
++MODULE_PARM_DESC(srp_max_req_size,
++ "Maximum size of SRP request messages in bytes.");
++
++static unsigned int srp_max_rsp_size = DEFAULT_MAX_RSP_SIZE;
++module_param(srp_max_rsp_size, int, 0444);
++MODULE_PARM_DESC(thread,
++ "Maximum size of SRP response messages in bytes.");
++
++static int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;
++module_param(srpt_srq_size, int, 0444);
++MODULE_PARM_DESC(srpt_srq_size,
++ "Shared receive queue (SRQ) size.");
++
++static int srpt_sq_size = DEF_SRPT_SQ_SIZE;
++module_param(srpt_sq_size, int, 0444);
++MODULE_PARM_DESC(srpt_sq_size,
++ "Per-channel send queue (SQ) size.");
++
++static bool use_port_guid_in_session_name;
++module_param(use_port_guid_in_session_name, bool, 0444);
++MODULE_PARM_DESC(use_port_guid_in_session_name,
++ "Use target port ID in the SCST session name such that"
++ " redundant paths between multiport systems can be masked.");
++
++static int srpt_get_u64_x(char *buffer, struct kernel_param *kp)
++{
++ return sprintf(buffer, "0x%016llx", *(u64 *)kp->arg);
++}
++module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid,
++ 0444);
++MODULE_PARM_DESC(srpt_service_guid,
++ "Using this value for ioc_guid, id_ext, and cm_listen_id"
++ " instead of using the node_guid of the first HCA.");
++
++static void srpt_add_one(struct ib_device *device);
++static void srpt_remove_one(struct ib_device *device);
++static void srpt_unregister_mad_agent(struct srpt_device *sdev);
++static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx);
++static void srpt_release_channel(struct scst_session *scst_sess);
++
++static struct ib_client srpt_client = {
++ .name = DRV_NAME,
++ .add = srpt_add_one,
++ .remove = srpt_remove_one
++};
++
++/**
++ * srpt_test_and_set_channel_state() - Test and set the channel state.
++ *
++ * @ch: RDMA channel.
++ * @old: channel state to compare with.
++ * @new: state to change the channel state to if the current state matches the
++ * argument 'old'.
++ *
++ * Returns the previous channel state.
++ */
++static enum rdma_ch_state
++srpt_test_and_set_channel_state(struct srpt_rdma_ch *ch,
++ enum rdma_ch_state old,
++ enum rdma_ch_state new)
++{
++ return atomic_cmpxchg(&ch->state, old, new);
++}
++
++/**
++ * srpt_event_handler() - Asynchronous IB event callback function.
++ *
++ * Callback function called by the InfiniBand core when an asynchronous IB
++ * event occurs. This callback may occur in interrupt context. See also
++ * section 11.5.2, Set Asynchronous Event Handler in the InfiniBand
++ * Architecture Specification.
++ */
++static void srpt_event_handler(struct ib_event_handler *handler,
++ struct ib_event *event)
++{
++ struct srpt_device *sdev;
++ struct srpt_port *sport;
++
++ TRACE_ENTRY();
++
++ sdev = ib_get_client_data(event->device, &srpt_client);
++ if (!sdev || sdev->device != event->device)
++ return;
++
++ TRACE_DBG("ASYNC event= %d on device= %s",
++ event->event, sdev->device->name);
++
++ switch (event->event) {
++ case IB_EVENT_PORT_ERR:
++ if (event->element.port_num <= sdev->device->phys_port_cnt) {
++ sport = &sdev->port[event->element.port_num - 1];
++ sport->lid = 0;
++ sport->sm_lid = 0;
++ }
++ break;
++ case IB_EVENT_PORT_ACTIVE:
++ case IB_EVENT_LID_CHANGE:
++ case IB_EVENT_PKEY_CHANGE:
++ case IB_EVENT_SM_CHANGE:
++ case IB_EVENT_CLIENT_REREGISTER:
++ /*
++ * Refresh port data asynchronously. Note: it is safe to call
++ * schedule_work() even if &sport->work is already on the
++ * global workqueue because schedule_work() tests for the
++ * work_pending() condition before adding &sport->work to the
++ * global work queue.
++ */
++ if (event->element.port_num <= sdev->device->phys_port_cnt) {
++ sport = &sdev->port[event->element.port_num - 1];
++ if (!sport->lid && !sport->sm_lid)
++ schedule_work(&sport->work);
++ }
++ break;
++ default:
++ PRINT_ERROR("received unrecognized IB event %d", event->event);
++ break;
++ }
++
++ TRACE_EXIT();
++}
++
++/**
++ * srpt_srq_event() - SRQ event callback function.
++ */
++static void srpt_srq_event(struct ib_event *event, void *ctx)
++{
++ PRINT_INFO("SRQ event %d", event->event);
++}
++
++/**
++ * srpt_qp_event() - QP event callback function.
++ */
++static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
++{
++ TRACE_DBG("QP event %d on cm_id=%p sess_name=%s state=%d",
++ event->event, ch->cm_id, ch->sess_name,
++ atomic_read(&ch->state));
++
++ switch (event->event) {
++ case IB_EVENT_COMM_EST:
++ ib_cm_notify(ch->cm_id, event->event);
++ break;
++ case IB_EVENT_QP_LAST_WQE_REACHED:
++ if (srpt_test_and_set_channel_state(ch, RDMA_CHANNEL_LIVE,
++ RDMA_CHANNEL_DISCONNECTING) == RDMA_CHANNEL_LIVE) {
++ PRINT_INFO("disconnected session %s.", ch->sess_name);
++ ib_send_cm_dreq(ch->cm_id, NULL, 0);
++ }
++ break;
++ default:
++ PRINT_ERROR("received unrecognized IB QP event %d",
++ event->event);
++ break;
++ }
++}
++
++/**
++ * srpt_set_ioc() - Helper function for initializing an IOUnitInfo structure.
++ *
++ * @slot: one-based slot number.
++ * @value: four-bit value.
++ *
++ * Copies the lowest four bits of value in element slot of the array of four
++ * bit elements called c_list (controller list). The index slot is one-based.
++ */
++static void srpt_set_ioc(u8 *c_list, u32 slot, u8 value)
++{
++ u16 id;
++ u8 tmp;
++
++ id = (slot - 1) / 2;
++ if (slot & 0x1) {
++ tmp = c_list[id] & 0xf;
++ c_list[id] = (value << 4) | tmp;
++ } else {
++ tmp = c_list[id] & 0xf0;
++ c_list[id] = (value & 0xf) | tmp;
++ }
++}
++
++/**
++ * srpt_get_class_port_info() - Copy ClassPortInfo to a management datagram.
++ *
++ * See also section 16.3.3.1 ClassPortInfo in the InfiniBand Architecture
++ * Specification.
++ */
++static void srpt_get_class_port_info(struct ib_dm_mad *mad)
++{
++ struct ib_class_port_info *cif;
++
++ cif = (struct ib_class_port_info *)mad->data;
++ memset(cif, 0, sizeof *cif);
++ cif->base_version = 1;
++ cif->class_version = 1;
++ cif->resp_time_value = 20;
++
++ mad->mad_hdr.status = 0;
++}
++
++/**
++ * srpt_get_iou() - Write IOUnitInfo to a management datagram.
++ *
++ * See also section 16.3.3.3 IOUnitInfo in the InfiniBand Architecture
++ * Specification. See also section B.7, table B.6 in the SRP r16a document.
++ */
++static void srpt_get_iou(struct ib_dm_mad *mad)
++{
++ struct ib_dm_iou_info *ioui;
++ u8 slot;
++ int i;
++
++ ioui = (struct ib_dm_iou_info *)mad->data;
++ ioui->change_id = __constant_cpu_to_be16(1);
++ ioui->max_controllers = 16;
++
++ /* set present for slot 1 and empty for the rest */
++ srpt_set_ioc(ioui->controller_list, 1, 1);
++ for (i = 1, slot = 2; i < 16; i++, slot++)
++ srpt_set_ioc(ioui->controller_list, slot, 0);
++
++ mad->mad_hdr.status = 0;
++}
++
++/**
++ * srpt_get_ioc() - Write IOControllerprofile to a management datagram.
++ *
++ * See also section 16.3.3.4 IOControllerProfile in the InfiniBand
++ * Architecture Specification. See also section B.7, table B.7 in the SRP
++ * r16a document.
++ */
++static void srpt_get_ioc(struct srpt_device *sdev, u32 slot,
++ struct ib_dm_mad *mad)
++{
++ struct ib_dm_ioc_profile *iocp;
++
++ iocp = (struct ib_dm_ioc_profile *)mad->data;
++
++ if (!slot || slot > 16) {
++ mad->mad_hdr.status
++ = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
++ return;
++ }
++
++ if (slot > 2) {
++ mad->mad_hdr.status
++ = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
++ return;
++ }
++
++ memset(iocp, 0, sizeof *iocp);
++ strcpy(iocp->id_string, MELLANOX_SRPT_ID_STRING);
++ iocp->guid = cpu_to_be64(srpt_service_guid);
++ iocp->vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
++ iocp->device_id = cpu_to_be32(sdev->dev_attr.vendor_part_id);
++ iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver);
++ iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
++ iocp->subsys_device_id = 0x0;
++ iocp->io_class = __constant_cpu_to_be16(SRP_REV16A_IB_IO_CLASS);
++ iocp->io_subclass = __constant_cpu_to_be16(SRP_IO_SUBCLASS);
++ iocp->protocol = __constant_cpu_to_be16(SRP_PROTOCOL);
++ iocp->protocol_version = __constant_cpu_to_be16(SRP_PROTOCOL_VERSION);
++ iocp->send_queue_depth = cpu_to_be16(sdev->srq_size);
++ iocp->rdma_read_depth = 4;
++ iocp->send_size = cpu_to_be32(srp_max_req_size);
++ iocp->rdma_size = cpu_to_be32(min(max(srp_max_rdma_size, 256U),
++ 1U << 24));
++ iocp->num_svc_entries = 1;
++ iocp->op_cap_mask = SRP_SEND_TO_IOC | SRP_SEND_FROM_IOC |
++ SRP_RDMA_READ_FROM_IOC | SRP_RDMA_WRITE_FROM_IOC;
++
++ mad->mad_hdr.status = 0;
++}
++
++/**
++ * srpt_get_svc_entries() - Write ServiceEntries to a management datagram.
++ *
++ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture
++ * Specification. See also section B.7, table B.8 in the SRP r16a document.
++ */
++static void srpt_get_svc_entries(u64 ioc_guid,
++ u16 slot, u8 hi, u8 lo, struct ib_dm_mad *mad)
++{
++ struct ib_dm_svc_entries *svc_entries;
++
++ WARN_ON(!ioc_guid);
++
++ if (!slot || slot > 16) {
++ mad->mad_hdr.status
++ = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
++ return;
++ }
++
++ if (slot > 2 || lo > hi || hi > 1) {
++ mad->mad_hdr.status
++ = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
++ return;
++ }
++
++ svc_entries = (struct ib_dm_svc_entries *)mad->data;
++ memset(svc_entries, 0, sizeof *svc_entries);
++ svc_entries->service_entries[0].id = cpu_to_be64(ioc_guid);
++ snprintf(svc_entries->service_entries[0].name,
++ sizeof(svc_entries->service_entries[0].name),
++ "%s%016llx",
++ SRP_SERVICE_NAME_PREFIX,
++ ioc_guid);
++
++ mad->mad_hdr.status = 0;
++}
++
++/**
++ * srpt_mgmt_method_get() - Process a received management datagram.
++ * @sp: source port through which the MAD has been received.
++ * @rq_mad: received MAD.
++ * @rsp_mad: response MAD.
++ */
++static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad,
++ struct ib_dm_mad *rsp_mad)
++{
++ u16 attr_id;
++ u32 slot;
++ u8 hi, lo;
++
++ attr_id = be16_to_cpu(rq_mad->mad_hdr.attr_id);
++ switch (attr_id) {
++ case DM_ATTR_CLASS_PORT_INFO:
++ srpt_get_class_port_info(rsp_mad);
++ break;
++ case DM_ATTR_IOU_INFO:
++ srpt_get_iou(rsp_mad);
++ break;
++ case DM_ATTR_IOC_PROFILE:
++ slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);
++ srpt_get_ioc(sp->sdev, slot, rsp_mad);
++ break;
++ case DM_ATTR_SVC_ENTRIES:
++ slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);
++ hi = (u8) ((slot >> 8) & 0xff);
++ lo = (u8) (slot & 0xff);
++ slot = (u16) ((slot >> 16) & 0xffff);
++ srpt_get_svc_entries(srpt_service_guid,
++ slot, hi, lo, rsp_mad);
++ break;
++ default:
++ rsp_mad->mad_hdr.status =
++ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
++ break;
++ }
++}
++
++/**
++ * srpt_mad_send_handler() - Post MAD-send callback function.
++ */
++static void srpt_mad_send_handler(struct ib_mad_agent *mad_agent,
++ struct ib_mad_send_wc *mad_wc)
++{
++ ib_destroy_ah(mad_wc->send_buf->ah);
++ ib_free_send_mad(mad_wc->send_buf);
++}
++
++/**
++ * srpt_mad_recv_handler() - MAD reception callback function.
++ */
++static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent,
++ struct ib_mad_recv_wc *mad_wc)
++{
++ struct srpt_port *sport = (struct srpt_port *)mad_agent->context;
++ struct ib_ah *ah;
++ struct ib_mad_send_buf *rsp;
++ struct ib_dm_mad *dm_mad;
++
++ if (!mad_wc || !mad_wc->recv_buf.mad)
++ return;
++
++ ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,
++ mad_wc->recv_buf.grh, mad_agent->port_num);
++ if (IS_ERR(ah))
++ goto err;
++
++ BUILD_BUG_ON(offsetof(struct ib_dm_mad, data) != IB_MGMT_DEVICE_HDR);
++
++ rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,
++ mad_wc->wc->pkey_index, 0,
++ IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA,
++ GFP_KERNEL);
++ if (IS_ERR(rsp))
++ goto err_rsp;
++
++ rsp->ah = ah;
++
++ dm_mad = rsp->mad;
++ memcpy(dm_mad, mad_wc->recv_buf.mad, sizeof *dm_mad);
++ dm_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
++ dm_mad->mad_hdr.status = 0;
++
++ switch (mad_wc->recv_buf.mad->mad_hdr.method) {
++ case IB_MGMT_METHOD_GET:
++ srpt_mgmt_method_get(sport, mad_wc->recv_buf.mad, dm_mad);
++ break;
++ case IB_MGMT_METHOD_SET:
++ dm_mad->mad_hdr.status =
++ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
++ break;
++ default:
++ dm_mad->mad_hdr.status =
++ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD);
++ break;
++ }
++
++ if (!ib_post_send_mad(rsp, NULL)) {
++ ib_free_recv_mad(mad_wc);
++ /* will destroy_ah & free_send_mad in send completion */
++ return;
++ }
++
++ ib_free_send_mad(rsp);
++
++err_rsp:
++ ib_destroy_ah(ah);
++err:
++ ib_free_recv_mad(mad_wc);
++}
++
++/**
++ * srpt_refresh_port() - Configure a HCA port.
++ *
++ * Enable InfiniBand management datagram processing, update the cached sm_lid,
++ * lid and gid values, and register a callback function for processing MADs
++ * on the specified port.
++ *
++ * Note: It is safe to call this function more than once for the same port.
++ */
++static int srpt_refresh_port(struct srpt_port *sport)
++{
++ struct ib_mad_reg_req reg_req;
++ struct ib_port_modify port_modify;
++ struct ib_port_attr port_attr;
++ int ret;
++
++ TRACE_ENTRY();
++
++ memset(&port_modify, 0, sizeof port_modify);
++ port_modify.set_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;
++ port_modify.clr_port_cap_mask = 0;
++
++ ret = ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);
++ if (ret)
++ goto err_mod_port;
++
++ ret = ib_query_port(sport->sdev->device, sport->port, &port_attr);
++ if (ret)
++ goto err_query_port;
++
++ sport->sm_lid = port_attr.sm_lid;
++ sport->lid = port_attr.lid;
++
++ ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid);
++ if (ret)
++ goto err_query_port;
++
++ if (!sport->mad_agent) {
++ memset(&reg_req, 0, sizeof reg_req);
++ reg_req.mgmt_class = IB_MGMT_CLASS_DEVICE_MGMT;
++ reg_req.mgmt_class_version = IB_MGMT_BASE_VERSION;
++ set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask);
++ set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask);
++
++ sport->mad_agent = ib_register_mad_agent(sport->sdev->device,
++ sport->port,
++ IB_QPT_GSI,
++ &reg_req, 0,
++ srpt_mad_send_handler,
++ srpt_mad_recv_handler,
++ sport);
++ if (IS_ERR(sport->mad_agent)) {
++ ret = PTR_ERR(sport->mad_agent);
++ sport->mad_agent = NULL;
++ goto err_query_port;
++ }
++ }
++
++ TRACE_EXIT_RES(0);
++
++ return 0;
++
++err_query_port:
++
++ port_modify.set_port_cap_mask = 0;
++ port_modify.clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;
++ ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);
++
++err_mod_port:
++
++ TRACE_EXIT_RES(ret);
++
++ return ret;
++}
++
++/**
++ * srpt_unregister_mad_agent() - Unregister MAD callback functions.
++ *
++ * Note: It is safe to call this function more than once for the same device.
++ */
++static void srpt_unregister_mad_agent(struct srpt_device *sdev)
++{
++ struct ib_port_modify port_modify = {
++ .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP,
++ };
++ struct srpt_port *sport;
++ int i;
++
++ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
++ sport = &sdev->port[i - 1];
++ WARN_ON(sport->port != i);
++ if (ib_modify_port(sdev->device, i, 0, &port_modify) < 0)
++ PRINT_ERROR("%s", "disabling MAD processing failed.");
++ if (sport->mad_agent) {
++ ib_unregister_mad_agent(sport->mad_agent);
++ sport->mad_agent = NULL;
++ }
++ }
++}
++
++/**
++ * srpt_alloc_ioctx() - Allocate an SRPT I/O context structure.
++ */
++static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev,
++ int ioctx_size, int dma_size,
++ enum dma_data_direction dir)
++{
++ struct srpt_ioctx *ioctx;
++
++ ioctx = kmalloc(ioctx_size, GFP_KERNEL);
++ if (!ioctx)
++ goto err;
++
++ ioctx->buf = kmalloc(dma_size, GFP_KERNEL);
++ if (!ioctx->buf)
++ goto err_free_ioctx;
++
++ ioctx->dma = ib_dma_map_single(sdev->device, ioctx->buf, dma_size, dir);
++ if (ib_dma_mapping_error(sdev->device, ioctx->dma))
++ goto err_free_buf;
++
++ return ioctx;
++
++err_free_buf:
++ kfree(ioctx->buf);
++err_free_ioctx:
++ kfree(ioctx);
++err:
++ return NULL;
++}
++
++/**
++ * srpt_free_ioctx() - Free an SRPT I/O context structure.
++ */
++static void srpt_free_ioctx(struct srpt_device *sdev, struct srpt_ioctx *ioctx,
++ int dma_size, enum dma_data_direction dir)
++{
++ if (!ioctx)
++ return;
++
++ ib_dma_unmap_single(sdev->device, ioctx->dma, dma_size, dir);
++ kfree(ioctx->buf);
++ kfree(ioctx);
++}
++
++/**
++ * srpt_alloc_ioctx_ring() - Allocate a ring of SRPT I/O context structures.
++ * @sdev: Device to allocate the I/O context ring for.
++ * @ring_size: Number of elements in the I/O context ring.
++ * @ioctx_size: I/O context size.
++ * @dma_size: DMA buffer size.
++ * @dir: DMA data direction.
++ */
++static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev,
++ int ring_size, int ioctx_size,
++ int dma_size, enum dma_data_direction dir)
++{
++ struct srpt_ioctx **ring;
++ int i;
++
++ TRACE_ENTRY();
++
++ WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx)
++ && ioctx_size != sizeof(struct srpt_send_ioctx));
++ WARN_ON(dma_size != srp_max_req_size && dma_size != srp_max_rsp_size);
++
++ ring = kmalloc(ring_size * sizeof(ring[0]), GFP_KERNEL);
++ if (!ring)
++ goto out;
++ for (i = 0; i < ring_size; ++i) {
++ ring[i] = srpt_alloc_ioctx(sdev, ioctx_size, dma_size, dir);
++ if (!ring[i])
++ goto err;
++ ring[i]->index = i;
++ }
++ goto out;
++
++err:
++ while (--i >= 0)
++ srpt_free_ioctx(sdev, ring[i], dma_size, dir);
++ kfree(ring);
++out:
++ TRACE_EXIT_RES(ring);
++ return ring;
++}
++
++/**
++ * srpt_free_ioctx_ring() - Free the ring of SRPT I/O context structures.
++ */
++static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring,
++ struct srpt_device *sdev, int ring_size,
++ int dma_size, enum dma_data_direction dir)
++{
++ int i;
++
++ WARN_ON(dma_size != srp_max_req_size && dma_size != srp_max_rsp_size);
++
++ for (i = 0; i < ring_size; ++i)
++ srpt_free_ioctx(sdev, ioctx_ring[i], dma_size, dir);
++ kfree(ioctx_ring);
++}
++
++/**
++ * srpt_get_cmd_state() - Get the state of a SCSI command.
++ */
++static enum srpt_command_state srpt_get_cmd_state(struct srpt_send_ioctx *ioctx)
++{
++ BUG_ON(!ioctx);
++
++ return atomic_read(&ioctx->state);
++}
++
++/**
++ * srpt_set_cmd_state() - Set the state of a SCSI command.
++ * @new: New state to be set.
++ *
++ * Does not modify the state of aborted commands. Returns the previous command
++ * state.
++ */
++static enum srpt_command_state srpt_set_cmd_state(struct srpt_send_ioctx *ioctx,
++ enum srpt_command_state new)
++{
++ enum srpt_command_state previous;
++
++ BUG_ON(!ioctx);
++
++ do {
++ previous = atomic_read(&ioctx->state);
++ } while (previous != SRPT_STATE_DONE
++ && atomic_cmpxchg(&ioctx->state, previous, new) != previous);
++
++ return previous;
++}
++
++/**
++ * srpt_test_and_set_cmd_state() - Test and set the state of a command.
++ * @old: State to compare against.
++ * @new: New state to be set if the current state matches 'old'.
++ *
++ * Returns the previous command state.
++ */
++static enum srpt_command_state
++srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx,
++ enum srpt_command_state old,
++ enum srpt_command_state new)
++{
++ WARN_ON(!ioctx);
++ WARN_ON(old == SRPT_STATE_DONE);
++ WARN_ON(new == SRPT_STATE_NEW);
++
++ return atomic_cmpxchg(&ioctx->state, old, new);
++}
++
++/**
++ * srpt_post_recv() - Post an IB receive request.
++ */
++static int srpt_post_recv(struct srpt_device *sdev,
++ struct srpt_recv_ioctx *ioctx)
++{
++ struct ib_sge list;
++ struct ib_recv_wr wr, *bad_wr;
++
++ BUG_ON(!sdev);
++ wr.wr_id = encode_wr_id(IB_WC_RECV, ioctx->ioctx.index);
++
++ list.addr = ioctx->ioctx.dma;
++ list.length = srp_max_req_size;
++ list.lkey = sdev->mr->lkey;
++
++ wr.next = NULL;
++ wr.sg_list = &list;
++ wr.num_sge = 1;
++
++ return ib_post_srq_recv(sdev->srq, &wr, &bad_wr);
++}
++
++/**
++ * srpt_post_send() - Post an IB send request.
++ * @ch: RDMA channel to post the send request on.
++ * @ioctx: I/O context of the send request.
++ * @len: length of the request to be sent in bytes.
++ *
++ * Returns zero upon success and a non-zero value upon failure.
++ */
++static int srpt_post_send(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx, int len)
++{
++ struct ib_sge list;
++ struct ib_send_wr wr, *bad_wr;
++ struct srpt_device *sdev = ch->sport->sdev;
++ int ret;
++
++ ret = -ENOMEM;
++ if (atomic_dec_return(&ch->sq_wr_avail) < 0) {
++ PRINT_WARNING("%s", "IB send queue full (needed 1)");
++ goto out;
++ }
++
++ ib_dma_sync_single_for_device(sdev->device, ioctx->ioctx.dma, len,
++ DMA_TO_DEVICE);
++
++ list.addr = ioctx->ioctx.dma;
++ list.length = len;
++ list.lkey = sdev->mr->lkey;
++
++ wr.next = NULL;
++ wr.wr_id = encode_wr_id(IB_WC_SEND, ioctx->ioctx.index);
++ wr.sg_list = &list;
++ wr.num_sge = 1;
++ wr.opcode = IB_WR_SEND;
++ wr.send_flags = IB_SEND_SIGNALED;
++
++ ret = ib_post_send(ch->qp, &wr, &bad_wr);
++
++out:
++ if (ret < 0)
++ atomic_inc(&ch->sq_wr_avail);
++ return ret;
++}
++
++/**
++ * srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request.
++ * @ioctx: Pointer to the I/O context associated with the request.
++ * @srp_cmd: Pointer to the SRP_CMD request data.
++ * @dir: Pointer to the variable to which the transfer direction will be
++ * written.
++ * @data_len: Pointer to the variable to which the total data length of all
++ * descriptors in the SRP_CMD request will be written.
++ *
++ * This function initializes ioctx->nrbuf and ioctx->r_bufs.
++ *
++ * Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors;
++ * -ENOMEM when memory allocation fails and zero upon success.
++ */
++static int srpt_get_desc_tbl(struct srpt_send_ioctx *ioctx,
++ struct srp_cmd *srp_cmd,
++ scst_data_direction *dir, u64 *data_len)
++{
++ struct srp_indirect_buf *idb;
++ struct srp_direct_buf *db;
++ unsigned add_cdb_offset;
++ int ret;
++
++ /*
++ * The pointer computations below will only be compiled correctly
++ * if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[], so check
++ * whether srp_cmd::add_data has been declared as a byte pointer.
++ */
++ BUILD_BUG_ON(!__same_type(srp_cmd->add_data[0], (s8)0)
++ && !__same_type(srp_cmd->add_data[0], (u8)0));
++
++ BUG_ON(!dir);
++ BUG_ON(!data_len);
++
++ ret = 0;
++ *data_len = 0;
++
++ /*
++ * The lower four bits of the buffer format field contain the DATA-IN
++ * buffer descriptor format, and the highest four bits contain the
++ * DATA-OUT buffer descriptor format.
++ */
++ *dir = SCST_DATA_NONE;
++ if (srp_cmd->buf_fmt & 0xf)
++ /* DATA-IN: transfer data from target to initiator. */
++ *dir = SCST_DATA_READ;
++ else if (srp_cmd->buf_fmt >> 4)
++ /* DATA-OUT: transfer data from initiator to target. */
++ *dir = SCST_DATA_WRITE;
++
++ /*
++ * According to the SRP spec, the lower two bits of the 'ADDITIONAL
++ * CDB LENGTH' field are reserved and the size in bytes of this field
++ * is four times the value specified in bits 3..7. Hence the "& ~3".
++ */
++ add_cdb_offset = srp_cmd->add_cdb_len & ~3;
++ if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_DIRECT) ||
++ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_DIRECT)) {
++ ioctx->n_rbuf = 1;
++ ioctx->rbufs = &ioctx->single_rbuf;
++
++ db = (struct srp_direct_buf *)(srp_cmd->add_data
++ + add_cdb_offset);
++ memcpy(ioctx->rbufs, db, sizeof *db);
++ *data_len = be32_to_cpu(db->len);
++ } else if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_INDIRECT) ||
++ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_INDIRECT)) {
++ idb = (struct srp_indirect_buf *)(srp_cmd->add_data
++ + add_cdb_offset);
++
++ ioctx->n_rbuf = be32_to_cpu(idb->table_desc.len) / sizeof *db;
++
++ if (ioctx->n_rbuf >
++ (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) {
++ PRINT_ERROR("received unsupported SRP_CMD request type"
++ " (%u out + %u in != %u / %zu)",
++ srp_cmd->data_out_desc_cnt,
++ srp_cmd->data_in_desc_cnt,
++ be32_to_cpu(idb->table_desc.len),
++ sizeof(*db));
++ ioctx->n_rbuf = 0;
++ ret = -EINVAL;
++ goto out;
++ }
++
++ if (ioctx->n_rbuf == 1)
++ ioctx->rbufs = &ioctx->single_rbuf;
++ else {
++ ioctx->rbufs =
++ kmalloc(ioctx->n_rbuf * sizeof *db, GFP_ATOMIC);
++ if (!ioctx->rbufs) {
++ ioctx->n_rbuf = 0;
++ ret = -ENOMEM;
++ goto out;
++ }
++ }
++
++ db = idb->desc_list;
++ memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db);
++ *data_len = be32_to_cpu(idb->len);
++ }
++out:
++ return ret;
++}
++
++/**
++ * srpt_init_ch_qp() - Initialize queue pair attributes.
++ *
++ * Initialized the attributes of queue pair 'qp' by allowing local write,
++ * remote read and remote write. Also transitions 'qp' to state IB_QPS_INIT.
++ */
++static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp)
++{
++ struct ib_qp_attr *attr;
++ int ret;
++
++ attr = kzalloc(sizeof *attr, GFP_KERNEL);
++ if (!attr)
++ return -ENOMEM;
++
++ attr->qp_state = IB_QPS_INIT;
++ attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ |
++ IB_ACCESS_REMOTE_WRITE;
++ attr->port_num = ch->sport->port;
++ attr->pkey_index = 0;
++
++ ret = ib_modify_qp(qp, attr,
++ IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PORT |
++ IB_QP_PKEY_INDEX);
++
++ kfree(attr);
++ return ret;
++}
++
++/**
++ * srpt_ch_qp_rtr() - Change the state of a channel to 'ready to receive' (RTR).
++ * @ch: channel of the queue pair.
++ * @qp: queue pair to change the state of.
++ *
++ * Returns zero upon success and a negative value upon failure.
++ *
++ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.
++ * If this structure ever becomes larger, it might be necessary to allocate
++ * it dynamically instead of on the stack.
++ */
++static int srpt_ch_qp_rtr(struct srpt_rdma_ch *ch, struct ib_qp *qp)
++{
++ struct ib_qp_attr qp_attr;
++ int attr_mask;
++ int ret;
++
++ qp_attr.qp_state = IB_QPS_RTR;
++ ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);
++ if (ret)
++ goto out;
++
++ qp_attr.max_dest_rd_atomic = 4;
++
++ ret = ib_modify_qp(qp, &qp_attr, attr_mask);
++
++out:
++ return ret;
++}
++
++/**
++ * srpt_ch_qp_rts() - Change the state of a channel to 'ready to send' (RTS).
++ * @ch: channel of the queue pair.
++ * @qp: queue pair to change the state of.
++ *
++ * Returns zero upon success and a negative value upon failure.
++ *
++ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.
++ * If this structure ever becomes larger, it might be necessary to allocate
++ * it dynamically instead of on the stack.
++ */
++static int srpt_ch_qp_rts(struct srpt_rdma_ch *ch, struct ib_qp *qp)
++{
++ struct ib_qp_attr qp_attr;
++ int attr_mask;
++ int ret;
++
++ qp_attr.qp_state = IB_QPS_RTS;
++ ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);
++ if (ret)
++ goto out;
++
++ qp_attr.max_rd_atomic = 4;
++
++ ret = ib_modify_qp(qp, &qp_attr, attr_mask);
++
++out:
++ return ret;
++}
++
++/**
++ * srpt_get_send_ioctx() - Obtain an I/O context for sending to the initiator.
++ */
++static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)
++{
++ struct srpt_send_ioctx *ioctx;
++ unsigned long flags;
++
++ BUG_ON(!ch);
++
++ ioctx = NULL;
++ spin_lock_irqsave(&ch->spinlock, flags);
++ if (!list_empty(&ch->free_list)) {
++ ioctx = list_first_entry(&ch->free_list,
++ struct srpt_send_ioctx, free_list);
++ list_del(&ioctx->free_list);
++ }
++ spin_unlock_irqrestore(&ch->spinlock, flags);
++
++ if (!ioctx)
++ return ioctx;
++
++ BUG_ON(ioctx->ch != ch);
++ atomic_set(&ioctx->state, SRPT_STATE_NEW);
++ ioctx->n_rbuf = 0;
++ ioctx->rbufs = NULL;
++ ioctx->n_rdma = 0;
++ ioctx->n_rdma_ius = 0;
++ ioctx->rdma_ius = NULL;
++ ioctx->mapped_sg_count = 0;
++ ioctx->scmnd = NULL;
++
++ return ioctx;
++}
++
++/**
++ * srpt_put_send_ioctx() - Free up resources.
++ */
++static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx)
++{
++ struct srpt_rdma_ch *ch;
++ unsigned long flags;
++
++ BUG_ON(!ioctx);
++ ch = ioctx->ch;
++ BUG_ON(!ch);
++
++ WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE);
++
++ ioctx->scmnd = NULL;
++
++ /*
++ * If the WARN_ON() below gets triggered this means that
++ * srpt_unmap_sg_to_ib_sge() has not been called before
++ * scst_tgt_cmd_done().
++ */
++ WARN_ON(ioctx->mapped_sg_count);
++
++ if (ioctx->n_rbuf > 1) {
++ kfree(ioctx->rbufs);
++ ioctx->rbufs = NULL;
++ ioctx->n_rbuf = 0;
++ }
++
++ spin_lock_irqsave(&ch->spinlock, flags);
++ list_add(&ioctx->free_list, &ch->free_list);
++ spin_unlock_irqrestore(&ch->spinlock, flags);
++}
++
++/**
++ * srpt_abort_scst_cmd() - Abort a SCSI command.
++ * @ioctx: I/O context associated with the SCSI command.
++ * @context: Preferred execution context.
++ */
++static void srpt_abort_scst_cmd(struct srpt_send_ioctx *ioctx,
++ enum scst_exec_context context)
++{
++ struct scst_cmd *scmnd;
++ enum srpt_command_state state;
++
++ TRACE_ENTRY();
++
++ BUG_ON(!ioctx);
++
++ /*
++ * If the command is in a state where the SCST core is waiting for the
++ * ib_srpt driver, change the state to the next state. Changing the
++ * state of the command from SRPT_STATE_NEED_DATA to SRPT_STATE_DATA_IN
++ * ensures that srpt_xmit_response() will call this function a second
++ * time.
++ */
++ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
++ SRPT_STATE_DATA_IN);
++ if (state != SRPT_STATE_NEED_DATA) {
++ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_DATA_IN,
++ SRPT_STATE_DONE);
++ if (state != SRPT_STATE_DATA_IN) {
++ state = srpt_test_and_set_cmd_state(ioctx,
++ SRPT_STATE_CMD_RSP_SENT, SRPT_STATE_DONE);
++ }
++ }
++ if (state == SRPT_STATE_DONE)
++ goto out;
++
++ scmnd = ioctx->scmnd;
++ WARN_ON(!scmnd);
++ if (!scmnd)
++ goto out;
++
++ WARN_ON(ioctx != scst_cmd_get_tgt_priv(scmnd));
++
++ TRACE_DBG("Aborting cmd with state %d and tag %lld",
++ state, scst_cmd_get_tag(scmnd));
++
++ switch (state) {
++ case SRPT_STATE_NEW:
++ case SRPT_STATE_DATA_IN:
++ /*
++ * Do nothing - defer abort processing until
++ * srpt_xmit_response() is invoked.
++ */
++ WARN_ON(!scst_cmd_aborted(scmnd));
++ break;
++ case SRPT_STATE_NEED_DATA:
++ /* SCST_DATA_WRITE - RDMA read error or RDMA read timeout. */
++ scst_rx_data(ioctx->scmnd, SCST_RX_STATUS_ERROR, context);
++ break;
++ case SRPT_STATE_CMD_RSP_SENT:
++ /*
++ * SRP_RSP sending failed or the SRP_RSP send completion has
++ * not been received in time.
++ */
++ srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
++ srpt_put_send_ioctx(ioctx);
++ scst_set_delivery_status(scmnd, SCST_CMD_DELIVERY_ABORTED);
++ scst_tgt_cmd_done(scmnd, context);
++ break;
++ case SRPT_STATE_MGMT_RSP_SENT:
++ /*
++ * Management command response sending failed. This state is
++ * never reached since there is no scmnd associated with
++ * management commands. Note: the SCST core frees these
++ * commands immediately after srpt_tsk_mgmt_done() returned.
++ */
++ WARN_ON("ERROR: unexpected command state");
++ break;
++ default:
++ WARN_ON("ERROR: unexpected command state");
++ break;
++ }
++
++out:
++ ;
++
++ TRACE_EXIT();
++}
++
++/**
++ * srpt_handle_send_err_comp() - Process an IB_WC_SEND error completion.
++ */
++static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id,
++ enum scst_exec_context context)
++{
++ struct srpt_send_ioctx *ioctx;
++ enum srpt_command_state state;
++ struct scst_cmd *scmnd;
++ u32 index;
++
++ atomic_inc(&ch->sq_wr_avail);
++
++ index = idx_from_wr_id(wr_id);
++ ioctx = ch->ioctx_ring[index];
++ state = srpt_get_cmd_state(ioctx);
++ scmnd = ioctx->scmnd;
++
++ EXTRACHECKS_WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
++ && state != SRPT_STATE_MGMT_RSP_SENT
++ && state != SRPT_STATE_NEED_DATA
++ && state != SRPT_STATE_DONE);
++
++ /* If SRP_RSP sending failed, undo the ch->req_lim change. */
++ if (state == SRPT_STATE_CMD_RSP_SENT
++ || state == SRPT_STATE_MGMT_RSP_SENT)
++ atomic_dec(&ch->req_lim);
++ if (state != SRPT_STATE_DONE) {
++ if (scmnd)
++ srpt_abort_scst_cmd(ioctx, context);
++ else {
++ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
++ srpt_put_send_ioctx(ioctx);
++ }
++ } else
++ PRINT_ERROR("Received more than one IB error completion"
++ " for wr_id = %u.", (unsigned)index);
++}
++
++/**
++ * srpt_handle_send_comp() - Process an IB send completion notification.
++ */
++static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx,
++ enum scst_exec_context context)
++{
++ enum srpt_command_state state;
++
++ atomic_inc(&ch->sq_wr_avail);
++
++ state = srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
++
++ EXTRACHECKS_WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
++ && state != SRPT_STATE_MGMT_RSP_SENT
++ && state != SRPT_STATE_DONE);
++
++ if (state != SRPT_STATE_DONE) {
++ struct scst_cmd *scmnd;
++
++ scmnd = ioctx->scmnd;
++ EXTRACHECKS_WARN_ON((state == SRPT_STATE_MGMT_RSP_SENT)
++ != (scmnd == NULL));
++ if (scmnd) {
++ srpt_unmap_sg_to_ib_sge(ch, ioctx);
++ srpt_put_send_ioctx(ioctx);
++ scst_tgt_cmd_done(scmnd, context);
++ } else
++ srpt_put_send_ioctx(ioctx);
++ } else {
++ PRINT_ERROR("IB completion has been received too late for"
++ " wr_id = %u.", ioctx->ioctx.index);
++ }
++}
++
++/**
++ * srpt_handle_rdma_comp() - Process an IB RDMA completion notification.
++ */
++static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx,
++ enum scst_exec_context context)
++{
++ enum srpt_command_state state;
++ struct scst_cmd *scmnd;
++
++ EXTRACHECKS_WARN_ON(ioctx->n_rdma <= 0);
++ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
++
++ scmnd = ioctx->scmnd;
++ if (scmnd) {
++ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
++ SRPT_STATE_DATA_IN);
++ if (state == SRPT_STATE_NEED_DATA)
++ scst_rx_data(ioctx->scmnd, SCST_RX_STATUS_SUCCESS,
++ context);
++ else
++ PRINT_ERROR("%s[%d]: wrong state = %d", __func__,
++ __LINE__, state);
++ } else
++ PRINT_ERROR("%s[%d]: scmnd == NULL", __func__, __LINE__);
++}
++
++/**
++ * srpt_handle_rdma_err_comp() - Process an IB RDMA error completion.
++ */
++static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx,
++ u8 opcode,
++ enum scst_exec_context context)
++{
++ struct scst_cmd *scmnd;
++ enum srpt_command_state state;
++
++ scmnd = ioctx->scmnd;
++ state = srpt_get_cmd_state(ioctx);
++ if (scmnd) {
++ switch (opcode) {
++ case IB_WC_RDMA_READ:
++ if (ioctx->n_rdma <= 0) {
++ PRINT_ERROR("Received invalid RDMA read error"
++ " completion with idx %d",
++ ioctx->ioctx.index);
++ break;
++ }
++ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
++ if (state == SRPT_STATE_NEED_DATA)
++ srpt_abort_scst_cmd(ioctx, context);
++ else
++ PRINT_ERROR("%s[%d]: wrong state = %d",
++ __func__, __LINE__, state);
++ break;
++ case IB_WC_RDMA_WRITE:
++ scst_set_delivery_status(scmnd,
++ SCST_CMD_DELIVERY_ABORTED);
++ break;
++ default:
++ PRINT_ERROR("%s[%d]: opcode = %u", __func__, __LINE__,
++ opcode);
++ break;
++ }
++ } else
++ PRINT_ERROR("%s[%d]: scmnd == NULL", __func__, __LINE__);
++}
++
++/**
++ * srpt_build_cmd_rsp() - Build an SRP_RSP response.
++ * @ch: RDMA channel through which the request has been received.
++ * @ioctx: I/O context associated with the SRP_CMD request. The response will
++ * be built in the buffer ioctx->buf points at and hence this function will
++ * overwrite the request data.
++ * @tag: tag of the request for which this response is being generated.
++ * @status: value for the STATUS field of the SRP_RSP information unit.
++ * @sense_data: pointer to sense data to be included in the response.
++ * @sense_data_len: length in bytes of the sense data.
++ *
++ * Returns the size in bytes of the SRP_RSP response.
++ *
++ * An SRP_RSP response contains a SCSI status or service response. See also
++ * section 6.9 in the SRP r16a document for the format of an SRP_RSP
++ * response. See also SPC-2 for more information about sense data.
++ */
++static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx, u64 tag,
++ int status, const u8 *sense_data,
++ int sense_data_len)
++{
++ struct srp_rsp *srp_rsp;
++ int max_sense_len;
++
++ /*
++ * The lowest bit of all SAM-3 status codes is zero (see also
++ * paragraph 5.3 in SAM-3).
++ */
++ EXTRACHECKS_WARN_ON(status & 1);
++
++ srp_rsp = ioctx->ioctx.buf;
++ BUG_ON(!srp_rsp);
++ memset(srp_rsp, 0, sizeof *srp_rsp);
++
++ srp_rsp->opcode = SRP_RSP;
++ srp_rsp->req_lim_delta = __constant_cpu_to_be32(1
++ + atomic_xchg(&ch->req_lim_delta, 0));
++ srp_rsp->tag = tag;
++ srp_rsp->status = status;
++
++ if (!SCST_SENSE_VALID(sense_data))
++ sense_data_len = 0;
++ else {
++ BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));
++ max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);
++ if (sense_data_len > max_sense_len) {
++ PRINT_WARNING("truncated sense data from %d to %d"
++ " bytes", sense_data_len, max_sense_len);
++ sense_data_len = max_sense_len;
++ }
++
++ srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
++ srp_rsp->sense_data_len = cpu_to_be32(sense_data_len);
++ memcpy(srp_rsp + 1, sense_data, sense_data_len);
++ }
++
++ return sizeof(*srp_rsp) + sense_data_len;
++}
++
++/**
++ * srpt_build_tskmgmt_rsp() - Build a task management response.
++ * @ch: RDMA channel through which the request has been received.
++ * @ioctx: I/O context in which the SRP_RSP response will be built.
++ * @rsp_code: RSP_CODE that will be stored in the response.
++ * @tag: Tag of the request for which this response is being generated.
++ *
++ * Returns the size in bytes of the SRP_RSP response.
++ *
++ * An SRP_RSP response contains a SCSI status or service response. See also
++ * section 6.9 in the SRP r16a document for the format of an SRP_RSP
++ * response.
++ */
++static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx,
++ u8 rsp_code, u64 tag)
++{
++ struct srp_rsp *srp_rsp;
++ int resp_data_len;
++ int resp_len;
++
++ resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
++ resp_len = sizeof(*srp_rsp) + resp_data_len;
++
++ srp_rsp = ioctx->ioctx.buf;
++ BUG_ON(!srp_rsp);
++ memset(srp_rsp, 0, sizeof *srp_rsp);
++
++ srp_rsp->opcode = SRP_RSP;
++ srp_rsp->req_lim_delta = __constant_cpu_to_be32(1
++ + atomic_xchg(&ch->req_lim_delta, 0));
++ srp_rsp->tag = tag;
++
++ if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
++ srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
++ srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
++ srp_rsp->data[3] = rsp_code;
++ }
++
++ return resp_len;
++}
++
++/**
++ * srpt_handle_cmd() - Process SRP_CMD.
++ */
++static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
++ struct srpt_recv_ioctx *recv_ioctx,
++ struct srpt_send_ioctx *send_ioctx,
++ enum scst_exec_context context)
++{
++ struct scst_cmd *scmnd;
++ struct srp_cmd *srp_cmd;
++ scst_data_direction dir;
++ u64 data_len;
++ int ret;
++ int atomic;
++
++ BUG_ON(!send_ioctx);
++
++ srp_cmd = recv_ioctx->ioctx.buf;
++
++ atomic = context == SCST_CONTEXT_TASKLET ? SCST_ATOMIC
++ : SCST_NON_ATOMIC;
++ scmnd = scst_rx_cmd(ch->scst_sess, (u8 *) &srp_cmd->lun,
++ sizeof srp_cmd->lun, srp_cmd->cdb,
++ sizeof srp_cmd->cdb, atomic);
++ if (!scmnd) {
++ PRINT_ERROR("0x%llx: allocation of an SCST command failed",
++ srp_cmd->tag);
++ goto err;
++ }
++
++ send_ioctx->scmnd = scmnd;
++
++ ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len);
++ if (ret) {
++ PRINT_ERROR("0x%llx: parsing SRP descriptor table failed.",
++ srp_cmd->tag);
++ scst_set_cmd_error(scmnd,
++ SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
++ }
++
++ switch (srp_cmd->task_attr) {
++ case SRP_CMD_HEAD_OF_Q:
++ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
++ break;
++ case SRP_CMD_ORDERED_Q:
++ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ case SRP_CMD_SIMPLE_Q:
++ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_SIMPLE);
++ break;
++ case SRP_CMD_ACA:
++ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_ACA);
++ break;
++ default:
++ scst_cmd_set_queue_type(scmnd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ }
++
++ scst_cmd_set_tag(scmnd, srp_cmd->tag);
++ scst_cmd_set_tgt_priv(scmnd, send_ioctx);
++ scst_cmd_set_expected(scmnd, dir, data_len);
++ scst_cmd_init_done(scmnd, context);
++
++ return 0;
++
++err:
++ srpt_put_send_ioctx(send_ioctx);
++ return -1;
++}
++
++/**
++ * srpt_handle_tsk_mgmt() - Process an SRP_TSK_MGMT information unit.
++ *
++ * Returns SCST_MGMT_STATUS_SUCCESS upon success.
++ *
++ * Each task management function is performed by calling one of the
++ * scst_rx_mgmt_fn*() functions. These functions will either report failure
++ * or process the task management function asynchronously. The function
++ * srpt_tsk_mgmt_done() will be called by the SCST core upon completion of the
++ * task management function. When srpt_handle_tsk_mgmt() reports failure
++ * (i.e. returns -1) a response will have been built in ioctx->buf. This
++ * information unit has to be sent back by the caller.
++ *
++ * For more information about SRP_TSK_MGMT information units, see also section
++ * 6.7 in the SRP r16a document.
++ */
++static u8 srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
++ struct srpt_recv_ioctx *recv_ioctx,
++ struct srpt_send_ioctx *send_ioctx)
++{
++ struct srp_tsk_mgmt *srp_tsk;
++ struct srpt_mgmt_ioctx *mgmt_ioctx;
++ int ret;
++
++ ret = SCST_MGMT_STATUS_FAILED;
++
++ BUG_ON(!send_ioctx);
++
++ srp_tsk = recv_ioctx->ioctx.buf;
++
++ TRACE_DBG("recv_tsk_mgmt= %d for task_tag= %lld"
++ " using tag= %lld cm_id= %p sess= %p",
++ srp_tsk->tsk_mgmt_func, srp_tsk->task_tag, srp_tsk->tag,
++ ch->cm_id, ch->scst_sess);
++
++ mgmt_ioctx = kmalloc(sizeof *mgmt_ioctx, GFP_ATOMIC);
++ if (!mgmt_ioctx) {
++ PRINT_ERROR("tag 0x%llx: memory allocation for task management"
++ " function failed. Ignoring task management request"
++ " (func %d).", srp_tsk->task_tag,
++ srp_tsk->tsk_mgmt_func);
++ goto err;
++ }
++
++ mgmt_ioctx->ioctx = send_ioctx;
++ BUG_ON(mgmt_ioctx->ioctx->ch != ch);
++ mgmt_ioctx->tag = srp_tsk->tag;
++
++ switch (srp_tsk->tsk_mgmt_func) {
++ case SRP_TSK_ABORT_TASK:
++ TRACE_DBG("%s", "Processing SRP_TSK_ABORT_TASK");
++ ret = scst_rx_mgmt_fn_tag(ch->scst_sess,
++ SCST_ABORT_TASK,
++ srp_tsk->task_tag,
++ SCST_ATOMIC, mgmt_ioctx);
++ break;
++ case SRP_TSK_ABORT_TASK_SET:
++ TRACE_DBG("%s", "Processing SRP_TSK_ABORT_TASK_SET");
++ ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
++ SCST_ABORT_TASK_SET,
++ (u8 *) &srp_tsk->lun,
++ sizeof srp_tsk->lun,
++ SCST_ATOMIC, mgmt_ioctx);
++ break;
++ case SRP_TSK_CLEAR_TASK_SET:
++ TRACE_DBG("%s", "Processing SRP_TSK_CLEAR_TASK_SET");
++ ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
++ SCST_CLEAR_TASK_SET,
++ (u8 *) &srp_tsk->lun,
++ sizeof srp_tsk->lun,
++ SCST_ATOMIC, mgmt_ioctx);
++ break;
++ case SRP_TSK_LUN_RESET:
++ TRACE_DBG("%s", "Processing SRP_TSK_LUN_RESET");
++ ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
++ SCST_LUN_RESET,
++ (u8 *) &srp_tsk->lun,
++ sizeof srp_tsk->lun,
++ SCST_ATOMIC, mgmt_ioctx);
++ break;
++ case SRP_TSK_CLEAR_ACA:
++ TRACE_DBG("%s", "Processing SRP_TSK_CLEAR_ACA");
++ ret = scst_rx_mgmt_fn_lun(ch->scst_sess,
++ SCST_CLEAR_ACA,
++ (u8 *) &srp_tsk->lun,
++ sizeof srp_tsk->lun,
++ SCST_ATOMIC, mgmt_ioctx);
++ break;
++ default:
++ TRACE_DBG("%s", "Unsupported task management function.");
++ ret = SCST_MGMT_STATUS_FN_NOT_SUPPORTED;
++ }
++
++ if (ret != SCST_MGMT_STATUS_SUCCESS)
++ goto err;
++ return ret;
++
++err:
++ kfree(mgmt_ioctx);
++ return ret;
++}
++
++static u8 scst_to_srp_tsk_mgmt_status(const int scst_mgmt_status)
++{
++ switch (scst_mgmt_status) {
++ case SCST_MGMT_STATUS_SUCCESS:
++ return SRP_TSK_MGMT_SUCCESS;
++ case SCST_MGMT_STATUS_FN_NOT_SUPPORTED:
++ return SRP_TSK_MGMT_FUNC_NOT_SUPP;
++ case SCST_MGMT_STATUS_TASK_NOT_EXIST:
++ case SCST_MGMT_STATUS_LUN_NOT_EXIST:
++ case SCST_MGMT_STATUS_REJECTED:
++ case SCST_MGMT_STATUS_FAILED:
++ default:
++ break;
++ }
++ return SRP_TSK_MGMT_FAILED;
++}
++
++/**
++ * srpt_handle_new_iu() - Process a newly received information unit.
++ * @ch: RDMA channel through which the information unit has been received.
++ * @ioctx: SRPT I/O context associated with the information unit.
++ */
++static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
++ struct srpt_recv_ioctx *recv_ioctx,
++ struct srpt_send_ioctx *send_ioctx,
++ enum scst_exec_context context)
++{
++ struct srp_cmd *srp_cmd;
++ enum rdma_ch_state ch_state;
++
++ BUG_ON(!ch);
++ BUG_ON(!recv_ioctx);
++
++ ib_dma_sync_single_for_cpu(ch->sport->sdev->device,
++ recv_ioctx->ioctx.dma, srp_max_req_size,
++ DMA_FROM_DEVICE);
++
++ ch_state = atomic_read(&ch->state);
++ srp_cmd = recv_ioctx->ioctx.buf;
++ if (unlikely(ch_state == RDMA_CHANNEL_CONNECTING)) {
++ list_add_tail(&recv_ioctx->wait_list, &ch->cmd_wait_list);
++ goto out;
++ }
++
++ if (unlikely(ch_state == RDMA_CHANNEL_DISCONNECTING))
++ goto post_recv;
++
++ if (srp_cmd->opcode == SRP_CMD || srp_cmd->opcode == SRP_TSK_MGMT) {
++ if (!send_ioctx)
++ send_ioctx = srpt_get_send_ioctx(ch);
++ if (unlikely(!send_ioctx)) {
++ list_add_tail(&recv_ioctx->wait_list,
++ &ch->cmd_wait_list);
++ goto out;
++ }
++ }
++
++ WARN_ON(ch_state != RDMA_CHANNEL_LIVE);
++
++ switch (srp_cmd->opcode) {
++ case SRP_CMD:
++ srpt_handle_cmd(ch, recv_ioctx, send_ioctx, context);
++ break;
++ case SRP_TSK_MGMT:
++ srpt_handle_tsk_mgmt(ch, recv_ioctx, send_ioctx);
++ break;
++ case SRP_I_LOGOUT:
++ PRINT_ERROR("%s", "Not yet implemented: SRP_I_LOGOUT");
++ break;
++ case SRP_CRED_RSP:
++ TRACE_DBG("%s", "received SRP_CRED_RSP");
++ break;
++ case SRP_AER_RSP:
++ TRACE_DBG("%s", "received SRP_AER_RSP");
++ break;
++ case SRP_RSP:
++ PRINT_ERROR("%s", "Received SRP_RSP");
++ break;
++ default:
++ PRINT_ERROR("received IU with unknown opcode 0x%x",
++ srp_cmd->opcode);
++ break;
++ }
++
++post_recv:
++ srpt_post_recv(ch->sport->sdev, recv_ioctx);
++out:
++ return;
++}
++
++static void srpt_process_rcv_completion(struct ib_cq *cq,
++ struct srpt_rdma_ch *ch,
++ enum scst_exec_context context,
++ struct ib_wc *wc)
++{
++ struct srpt_device *sdev = ch->sport->sdev;
++ struct srpt_recv_ioctx *ioctx;
++ u32 index;
++
++ index = idx_from_wr_id(wc->wr_id);
++ if (wc->status == IB_WC_SUCCESS) {
++ int req_lim;
++
++ req_lim = atomic_dec_return(&ch->req_lim);
++ if (unlikely(req_lim < 0))
++ PRINT_ERROR("req_lim = %d < 0", req_lim);
++ ioctx = sdev->ioctx_ring[index];
++ srpt_handle_new_iu(ch, ioctx, NULL, context);
++ } else {
++ PRINT_INFO("receiving failed for idx %u with status %d",
++ index, wc->status);
++ }
++}
++
++/**
++ * srpt_process_send_completion() - Process an IB send completion.
++ *
++ * Note: Although this has not yet been observed during tests, at least in
++ * theory it is possible that the srpt_get_send_ioctx() call invoked by
++ * srpt_handle_new_iu() fails. This is possible because the req_lim_delta
++ * value in each response is set to one, and it is possible that this response
++ * makes the initiator send a new request before the send completion for that
++ * response has been processed. This could e.g. happen if the call to
++ * srpt_put_send_iotcx() is delayed because of a higher priority interrupt or
++ * if IB retransmission causes generation of the send completion to be
++ * delayed. Incoming information units for which srpt_get_send_ioctx() fails
++ * are queued on cmd_wait_list. The code below processes these delayed
++ * requests one at a time.
++ */
++static void srpt_process_send_completion(struct ib_cq *cq,
++ struct srpt_rdma_ch *ch,
++ enum scst_exec_context context,
++ struct ib_wc *wc)
++{
++ struct srpt_send_ioctx *send_ioctx;
++ uint32_t index;
++ u8 opcode;
++
++ index = idx_from_wr_id(wc->wr_id);
++ opcode = opcode_from_wr_id(wc->wr_id);
++ send_ioctx = ch->ioctx_ring[index];
++ if (wc->status == IB_WC_SUCCESS) {
++ if (opcode == IB_WC_SEND)
++ srpt_handle_send_comp(ch, send_ioctx, context);
++ else {
++ EXTRACHECKS_WARN_ON(wc->opcode != IB_WC_RDMA_READ);
++ srpt_handle_rdma_comp(ch, send_ioctx, context);
++ }
++ } else {
++ if (opcode == IB_WC_SEND) {
++ PRINT_INFO("sending response for idx %u failed with"
++ " status %d", index, wc->status);
++ srpt_handle_send_err_comp(ch, wc->wr_id, context);
++ } else {
++ PRINT_INFO("RDMA %s for idx %u failed with status %d",
++ opcode == IB_WC_RDMA_READ ? "read"
++ : opcode == IB_WC_RDMA_WRITE ? "write"
++ : "???", index, wc->status);
++ srpt_handle_rdma_err_comp(ch, send_ioctx, opcode,
++ context);
++ }
++ }
++
++ while (unlikely(opcode == IB_WC_SEND
++ && !list_empty(&ch->cmd_wait_list)
++ && atomic_read(&ch->state) == RDMA_CHANNEL_LIVE
++ && (send_ioctx = srpt_get_send_ioctx(ch)) != NULL)) {
++ struct srpt_recv_ioctx *recv_ioctx;
++
++ recv_ioctx = list_first_entry(&ch->cmd_wait_list,
++ struct srpt_recv_ioctx,
++ wait_list);
++ list_del(&recv_ioctx->wait_list);
++ srpt_handle_new_iu(ch, recv_ioctx, send_ioctx, context);
++ }
++}
++
++static void srpt_process_completion(struct ib_cq *cq,
++ struct srpt_rdma_ch *ch,
++ enum scst_exec_context context)
++{
++ struct ib_wc *const wc = ch->wc;
++ int i, n;
++
++ EXTRACHECKS_WARN_ON(cq != ch->cq);
++
++ ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
++ while ((n = ib_poll_cq(cq, ARRAY_SIZE(ch->wc), wc)) > 0) {
++ for (i = 0; i < n; i++) {
++ if (opcode_from_wr_id(wc[i].wr_id) & IB_WC_RECV)
++ srpt_process_rcv_completion(cq, ch, context,
++ &wc[i]);
++ else
++ srpt_process_send_completion(cq, ch, context,
++ &wc[i]);
++ }
++ }
++}
++
++/**
++ * srpt_completion() - IB completion queue callback function.
++ *
++ * Notes:
++ * - It is guaranteed that a completion handler will never be invoked
++ * concurrently on two different CPUs for the same completion queue. See also
++ * Documentation/infiniband/core_locking.txt and the implementation of
++ * handle_edge_irq() in kernel/irq/chip.c.
++ * - When threaded IRQs are enabled, completion handlers are invoked in thread
++ * context instead of interrupt context.
++ */
++static void srpt_completion(struct ib_cq *cq, void *ctx)
++{
++ struct srpt_rdma_ch *ch = ctx;
++
++ BUG_ON(!ch);
++ atomic_inc(&ch->processing_compl);
++ switch (thread) {
++ case MODE_IB_COMPLETION_IN_THREAD:
++ wake_up_interruptible(&ch->wait_queue);
++ break;
++ case MODE_IB_COMPLETION_IN_SIRQ:
++ srpt_process_completion(cq, ch, SCST_CONTEXT_THREAD);
++ break;
++ case MODE_ALL_IN_SIRQ:
++ srpt_process_completion(cq, ch, SCST_CONTEXT_TASKLET);
++ break;
++ }
++ atomic_dec(&ch->processing_compl);
++}
++
++static int srpt_compl_thread(void *arg)
++{
++ struct srpt_rdma_ch *ch;
++
++ /* Hibernation / freezing of the SRPT kernel thread is not supported. */
++ current->flags |= PF_NOFREEZE;
++
++ ch = arg;
++ BUG_ON(!ch);
++ PRINT_INFO("Session %s: kernel thread %s (PID %d) started",
++ ch->sess_name, ch->thread->comm, current->pid);
++ while (!kthread_should_stop()) {
++ wait_event_interruptible(ch->wait_queue,
++ (srpt_process_completion(ch->cq, ch,
++ SCST_CONTEXT_THREAD),
++ kthread_should_stop()));
++ }
++ PRINT_INFO("Session %s: kernel thread %s (PID %d) stopped",
++ ch->sess_name, ch->thread->comm, current->pid);
++ return 0;
++}
++
++/**
++ * srpt_create_ch_ib() - Create receive and send completion queues.
++ */
++static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
++{
++ struct ib_qp_init_attr *qp_init;
++ struct srpt_device *sdev = ch->sport->sdev;
++ int ret;
++
++ EXTRACHECKS_WARN_ON(ch->rq_size < 1);
++
++ ret = -ENOMEM;
++ qp_init = kzalloc(sizeof *qp_init, GFP_KERNEL);
++ if (!qp_init)
++ goto out;
++
++ ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,
++ ch->rq_size + srpt_sq_size, 0);
++ if (IS_ERR(ch->cq)) {
++ ret = PTR_ERR(ch->cq);
++ PRINT_ERROR("failed to create CQ cqe= %d ret= %d",
++ ch->rq_size + srpt_sq_size, ret);
++ goto out;
++ }
++
++ qp_init->qp_context = (void *)ch;
++ qp_init->event_handler
++ = (void(*)(struct ib_event *, void*))srpt_qp_event;
++ qp_init->send_cq = ch->cq;
++ qp_init->recv_cq = ch->cq;
++ qp_init->srq = sdev->srq;
++ qp_init->sq_sig_type = IB_SIGNAL_REQ_WR;
++ qp_init->qp_type = IB_QPT_RC;
++ qp_init->cap.max_send_wr = srpt_sq_size;
++ qp_init->cap.max_send_sge = SRPT_DEF_SG_PER_WQE;
++
++ ch->qp = ib_create_qp(sdev->pd, qp_init);
++ if (IS_ERR(ch->qp)) {
++ ret = PTR_ERR(ch->qp);
++ PRINT_ERROR("failed to create_qp ret= %d", ret);
++ goto err_destroy_cq;
++ }
++
++ atomic_set(&ch->sq_wr_avail, qp_init->cap.max_send_wr);
++
++ TRACE_DBG("%s: max_cqe= %d max_sge= %d sq_size = %d"
++ " cm_id= %p", __func__, ch->cq->cqe,
++ qp_init->cap.max_send_sge, qp_init->cap.max_send_wr,
++ ch->cm_id);
++
++ ret = srpt_init_ch_qp(ch, ch->qp);
++ if (ret)
++ goto err_destroy_qp;
++
++ if (thread == MODE_IB_COMPLETION_IN_THREAD) {
++ init_waitqueue_head(&ch->wait_queue);
++
++ TRACE_DBG("creating IB completion thread for session %s",
++ ch->sess_name);
++
++ ch->thread = kthread_run(srpt_compl_thread, ch,
++ "ib_srpt_compl");
++ if (IS_ERR(ch->thread)) {
++ PRINT_ERROR("failed to create kernel thread %ld",
++ PTR_ERR(ch->thread));
++ ch->thread = NULL;
++ goto err_destroy_qp;
++ }
++ } else
++ ib_req_notify_cq(ch->cq, IB_CQ_NEXT_COMP);
++
++out:
++ kfree(qp_init);
++ return ret;
++
++err_destroy_qp:
++ ib_destroy_qp(ch->qp);
++err_destroy_cq:
++ ib_destroy_cq(ch->cq);
++ goto out;
++}
++
++static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch)
++{
++ if (ch->thread)
++ kthread_stop(ch->thread);
++
++ ib_destroy_qp(ch->qp);
++ ib_destroy_cq(ch->cq);
++}
++
++/**
++ * srpt_unregister_channel() - Start RDMA channel disconnection.
++ *
++ * Note: The caller must hold ch->sdev->spinlock.
++ */
++static void srpt_unregister_channel(struct srpt_rdma_ch *ch)
++ __acquires(&ch->sport->sdev->spinlock)
++ __releases(&ch->sport->sdev->spinlock)
++{
++ struct srpt_device *sdev;
++ struct ib_qp_attr qp_attr;
++ int ret;
++
++ sdev = ch->sport->sdev;
++ list_del(&ch->list);
++ atomic_set(&ch->state, RDMA_CHANNEL_DISCONNECTING);
++ spin_unlock_irq(&sdev->spinlock);
++
++ qp_attr.qp_state = IB_QPS_ERR;
++ ret = ib_modify_qp(ch->qp, &qp_attr, IB_QP_STATE);
++ if (ret < 0)
++ PRINT_ERROR("Setting queue pair in error state failed: %d",
++ ret);
++
++ while (atomic_read(&ch->processing_compl))
++ ;
++
++ /*
++ * At this point it is guaranteed that no new commands will be sent to
++ * the SCST core for channel ch, which is a requirement for
++ * scst_unregister_session().
++ */
++
++ TRACE_DBG("unregistering session %p", ch->scst_sess);
++ scst_unregister_session(ch->scst_sess, 0, srpt_release_channel);
++ spin_lock_irq(&sdev->spinlock);
++}
++
++/**
++ * srpt_release_channel_by_cmid() - Release a channel.
++ * @cm_id: Pointer to the CM ID of the channel to be released.
++ *
++ * Note: Must be called from inside srpt_cm_handler to avoid a race between
++ * accessing sdev->spinlock and the call to kfree(sdev) in srpt_remove_one()
++ * (the caller of srpt_cm_handler holds the cm_id spinlock; srpt_remove_one()
++ * waits until all SCST sessions for the associated IB device have been
++ * unregistered and SCST session registration involves a call to
++ * ib_destroy_cm_id(), which locks the cm_id spinlock and hence waits until
++ * this function has finished).
++ */
++static void srpt_release_channel_by_cmid(struct ib_cm_id *cm_id)
++{
++ struct srpt_device *sdev;
++ struct srpt_rdma_ch *ch;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
++
++ sdev = cm_id->context;
++ BUG_ON(!sdev);
++ spin_lock_irq(&sdev->spinlock);
++ list_for_each_entry(ch, &sdev->rch_list, list) {
++ if (ch->cm_id == cm_id) {
++ srpt_unregister_channel(ch);
++ break;
++ }
++ }
++ spin_unlock_irq(&sdev->spinlock);
++
++ TRACE_EXIT();
++}
++
++/**
++ * srpt_find_channel() - Look up an RDMA channel.
++ * @cm_id: Pointer to the CM ID of the channel to be looked up.
++ *
++ * Return NULL if no matching RDMA channel has been found.
++ */
++static struct srpt_rdma_ch *srpt_find_channel(struct srpt_device *sdev,
++ struct ib_cm_id *cm_id)
++{
++ struct srpt_rdma_ch *ch;
++ bool found;
++
++ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
++ BUG_ON(!sdev);
++
++ found = false;
++ spin_lock_irq(&sdev->spinlock);
++ list_for_each_entry(ch, &sdev->rch_list, list) {
++ if (ch->cm_id == cm_id) {
++ found = true;
++ break;
++ }
++ }
++ spin_unlock_irq(&sdev->spinlock);
++
++ return found ? ch : NULL;
++}
++
++/**
++ * srpt_release_channel() - Release all resources associated with an RDMA channel.
++ *
++ * Notes:
++ * - The caller must have removed the channel from the channel list before
++ * calling this function.
++ * - Must be called as a callback function via scst_unregister_session(). Never
++ * call this function directly because doing so would trigger several race
++ * conditions.
++ * - Do not access ch->sport or ch->sport->sdev in this function because the
++ * memory that was allocated for the sport and/or sdev data structures may
++ * already have been freed at the time this function is called.
++ */
++static void srpt_release_channel(struct scst_session *scst_sess)
++{
++ struct srpt_rdma_ch *ch;
++
++ TRACE_ENTRY();
++
++ ch = scst_sess_get_tgt_priv(scst_sess);
++ BUG_ON(!ch);
++ WARN_ON(atomic_read(&ch->state) != RDMA_CHANNEL_DISCONNECTING);
++
++ TRACE_DBG("destroying cm_id %p", ch->cm_id);
++ BUG_ON(!ch->cm_id);
++ ib_destroy_cm_id(ch->cm_id);
++
++ srpt_destroy_ch_ib(ch);
++
++ srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
++ ch->sport->sdev, ch->rq_size,
++ srp_max_rsp_size, DMA_TO_DEVICE);
++
++ kfree(ch);
++
++ TRACE_EXIT();
++}
++
++/**
++ * srpt_enable_target() - Allows to enable a target via sysfs.
++ */
++static int srpt_enable_target(struct scst_tgt *scst_tgt, bool enable)
++{
++ struct srpt_device *sdev = scst_tgt_get_tgt_priv(scst_tgt);
++
++ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
++
++ if (!sdev)
++ return -ENOENT;
++
++ TRACE_DBG("%s target %s", enable ? "Enabling" : "Disabling",
++ sdev->device->name);
++
++ spin_lock_irq(&sdev->spinlock);
++ sdev->enabled = enable;
++ spin_unlock_irq(&sdev->spinlock);
++
++ return 0;
++}
++
++/**
++ * srpt_is_target_enabled() - Allows to query a targets status via sysfs.
++ */
++static bool srpt_is_target_enabled(struct scst_tgt *scst_tgt)
++{
++ struct srpt_device *sdev = scst_tgt_get_tgt_priv(scst_tgt);
++ bool res;
++
++ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
++
++ if (!sdev)
++ return false;
++
++ spin_lock_irq(&sdev->spinlock);
++ res = sdev->enabled;
++ spin_unlock_irq(&sdev->spinlock);
++ return res;
++}
++
++/**
++ * srpt_cm_req_recv() - Process the event IB_CM_REQ_RECEIVED.
++ *
++ * Ownership of the cm_id is transferred to the SCST session if this functions
++ * returns zero. Otherwise the caller remains the owner of cm_id.
++ */
++static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
++ struct ib_cm_req_event_param *param,
++ void *private_data)
++{
++ struct srpt_device *sdev = cm_id->context;
++ struct srp_login_req *req;
++ struct srp_login_rsp *rsp;
++ struct srp_login_rej *rej;
++ struct ib_cm_rep_param *rep_param;
++ struct srpt_rdma_ch *ch, *tmp_ch;
++ u32 it_iu_len;
++ int i;
++ int ret = 0;
++
++ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
++
++ if (WARN_ON(!sdev || !private_data))
++ return -EINVAL;
++
++ req = (struct srp_login_req *)private_data;
++
++ it_iu_len = be32_to_cpu(req->req_it_iu_len);
++
++ PRINT_INFO("Received SRP_LOGIN_REQ with"
++ " i_port_id 0x%llx:0x%llx, t_port_id 0x%llx:0x%llx and it_iu_len %d"
++ " on port %d (guid=0x%llx:0x%llx)",
++ be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]),
++ be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]),
++ be64_to_cpu(*(__be64 *)&req->target_port_id[0]),
++ be64_to_cpu(*(__be64 *)&req->target_port_id[8]),
++ it_iu_len,
++ param->port,
++ be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]),
++ be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8]));
++
++ rsp = kzalloc(sizeof *rsp, GFP_KERNEL);
++ rej = kzalloc(sizeof *rej, GFP_KERNEL);
++ rep_param = kzalloc(sizeof *rep_param, GFP_KERNEL);
++
++ if (!rsp || !rej || !rep_param) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ if (it_iu_len > srp_max_req_size || it_iu_len < 64) {
++ rej->reason = __constant_cpu_to_be32(
++ SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE);
++ ret = -EINVAL;
++ PRINT_ERROR("rejected SRP_LOGIN_REQ because its"
++ " length (%d bytes) is out of range (%d .. %d)",
++ it_iu_len, 64, srp_max_req_size);
++ goto reject;
++ }
++
++ if (!srpt_is_target_enabled(sdev->scst_tgt)) {
++ rej->reason = __constant_cpu_to_be32(
++ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
++ ret = -EINVAL;
++ PRINT_ERROR("rejected SRP_LOGIN_REQ because the target %s"
++ " has not yet been enabled", sdev->device->name);
++ goto reject;
++ }
++
++ if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {
++ rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;
++
++ spin_lock_irq(&sdev->spinlock);
++
++ list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) {
++ if (!memcmp(ch->i_port_id, req->initiator_port_id, 16)
++ && !memcmp(ch->t_port_id, req->target_port_id, 16)
++ && param->port == ch->sport->port
++ && param->listen_id == ch->sport->sdev->cm_id
++ && ch->cm_id) {
++ enum rdma_ch_state prev_state;
++
++ /* found an existing channel */
++ TRACE_DBG("Found existing channel name= %s"
++ " cm_id= %p state= %d",
++ ch->sess_name, ch->cm_id,
++ atomic_read(&ch->state));
++
++ prev_state = atomic_xchg(&ch->state,
++ RDMA_CHANNEL_DISCONNECTING);
++ if (prev_state == RDMA_CHANNEL_CONNECTING)
++ srpt_unregister_channel(ch);
++
++ spin_unlock_irq(&sdev->spinlock);
++
++ rsp->rsp_flags =
++ SRP_LOGIN_RSP_MULTICHAN_TERMINATED;
++
++ if (prev_state == RDMA_CHANNEL_LIVE) {
++ ib_send_cm_dreq(ch->cm_id, NULL, 0);
++ PRINT_INFO("disconnected"
++ " session %s because a new"
++ " SRP_LOGIN_REQ has been received.",
++ ch->sess_name);
++ } else if (prev_state ==
++ RDMA_CHANNEL_CONNECTING) {
++ PRINT_ERROR("%s", "rejected"
++ " SRP_LOGIN_REQ because another login"
++ " request is being processed.");
++ ib_send_cm_rej(ch->cm_id,
++ IB_CM_REJ_NO_RESOURCES,
++ NULL, 0, NULL, 0);
++ }
++
++ spin_lock_irq(&sdev->spinlock);
++ }
++ }
++
++ spin_unlock_irq(&sdev->spinlock);
++
++ } else
++ rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;
++
++ if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid)
++ || *(__be64 *)(req->target_port_id + 8) !=
++ cpu_to_be64(srpt_service_guid)) {
++ rej->reason = __constant_cpu_to_be32(
++ SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL);
++ ret = -ENOMEM;
++ PRINT_ERROR("%s", "rejected SRP_LOGIN_REQ because it"
++ " has an invalid target port identifier.");
++ goto reject;
++ }
++
++ ch = kzalloc(sizeof *ch, GFP_KERNEL);
++ if (!ch) {
++ rej->reason = __constant_cpu_to_be32(
++ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
++ PRINT_ERROR("%s",
++ "rejected SRP_LOGIN_REQ because out of memory.");
++ ret = -ENOMEM;
++ goto reject;
++ }
++
++ memcpy(ch->i_port_id, req->initiator_port_id, 16);
++ memcpy(ch->t_port_id, req->target_port_id, 16);
++ ch->sport = &sdev->port[param->port - 1];
++ ch->cm_id = cm_id;
++ /*
++ * Avoid QUEUE_FULL conditions by limiting the number of buffers used
++ * for the SRP protocol to the SCST SCSI command queue size.
++ */
++ ch->rq_size = min(SRPT_RQ_SIZE, scst_get_max_lun_commands(NULL, 0));
++ atomic_set(&ch->processing_compl, 0);
++ atomic_set(&ch->state, RDMA_CHANNEL_CONNECTING);
++ INIT_LIST_HEAD(&ch->cmd_wait_list);
++
++ spin_lock_init(&ch->spinlock);
++ ch->ioctx_ring = (struct srpt_send_ioctx **)
++ srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size,
++ sizeof(*ch->ioctx_ring[0]),
++ srp_max_rsp_size, DMA_TO_DEVICE);
++ if (!ch->ioctx_ring)
++ goto free_ch;
++
++ INIT_LIST_HEAD(&ch->free_list);
++ for (i = 0; i < ch->rq_size; i++) {
++ ch->ioctx_ring[i]->ch = ch;
++ list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list);
++ }
++
++ ret = srpt_create_ch_ib(ch);
++ if (ret) {
++ rej->reason = __constant_cpu_to_be32(
++ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
++ PRINT_ERROR("%s", "rejected SRP_LOGIN_REQ because creating"
++ " a new RDMA channel failed.");
++ goto free_ring;
++ }
++
++ ret = srpt_ch_qp_rtr(ch, ch->qp);
++ if (ret) {
++ rej->reason = __constant_cpu_to_be32(
++ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
++ PRINT_ERROR("rejected SRP_LOGIN_REQ because enabling"
++ " RTR failed (error code = %d)", ret);
++ goto destroy_ib;
++ }
++
++ if (use_port_guid_in_session_name) {
++ /*
++ * If the kernel module parameter use_port_guid_in_session_name
++ * has been specified, use a combination of the target port
++ * GUID and the initiator port ID as the session name. This
++ * was the original behavior of the SRP target implementation
++ * (i.e. before the SRPT was included in OFED 1.3).
++ */
++ snprintf(ch->sess_name, sizeof(ch->sess_name),
++ "0x%016llx%016llx",
++ be64_to_cpu(*(__be64 *)
++ &sdev->port[param->port - 1].gid.raw[8]),
++ be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));
++ } else {
++ /*
++ * Default behavior: use the initator port identifier as the
++ * session name.
++ */
++ snprintf(ch->sess_name, sizeof(ch->sess_name),
++ "0x%016llx%016llx",
++ be64_to_cpu(*(__be64 *)ch->i_port_id),
++ be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));
++ }
++
++ TRACE_DBG("registering session %s", ch->sess_name);
++
++ BUG_ON(!sdev->scst_tgt);
++ ch->scst_sess = scst_register_session(sdev->scst_tgt, 0, ch->sess_name,
++ ch, NULL, NULL);
++ if (!ch->scst_sess) {
++ rej->reason = __constant_cpu_to_be32(
++ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
++ TRACE_DBG("%s", "Failed to create SCST session");
++ goto release_channel;
++ }
++
++ TRACE_DBG("Establish connection sess=%p name=%s cm_id=%p",
++ ch->scst_sess, ch->sess_name, ch->cm_id);
++
++ /* create srp_login_response */
++ rsp->opcode = SRP_LOGIN_RSP;
++ rsp->tag = req->tag;
++ rsp->max_it_iu_len = req->req_it_iu_len;
++ rsp->max_ti_iu_len = req->req_it_iu_len;
++ ch->max_ti_iu_len = it_iu_len;
++ rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
++ | SRP_BUF_FORMAT_INDIRECT);
++ rsp->req_lim_delta = cpu_to_be32(ch->rq_size);
++ atomic_set(&ch->req_lim, ch->rq_size);
++ atomic_set(&ch->req_lim_delta, 0);
++
++ /* create cm reply */
++ rep_param->qp_num = ch->qp->qp_num;
++ rep_param->private_data = (void *)rsp;
++ rep_param->private_data_len = sizeof *rsp;
++ rep_param->rnr_retry_count = 7;
++ rep_param->flow_control = 1;
++ rep_param->failover_accepted = 0;
++ rep_param->srq = 1;
++ rep_param->responder_resources = 4;
++ rep_param->initiator_depth = 4;
++
++ ret = ib_send_cm_rep(cm_id, rep_param);
++ if (ret) {
++ PRINT_ERROR("sending SRP_LOGIN_REQ response failed"
++ " (error code = %d)", ret);
++ goto release_channel;
++ }
++
++ spin_lock_irq(&sdev->spinlock);
++ list_add_tail(&ch->list, &sdev->rch_list);
++ spin_unlock_irq(&sdev->spinlock);
++
++ goto out;
++
++release_channel:
++ atomic_set(&ch->state, RDMA_CHANNEL_DISCONNECTING);
++ scst_unregister_session(ch->scst_sess, 0, NULL);
++ ch->scst_sess = NULL;
++
++destroy_ib:
++ srpt_destroy_ch_ib(ch);
++
++free_ring:
++ srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
++ ch->sport->sdev, ch->rq_size,
++ srp_max_rsp_size, DMA_TO_DEVICE);
++
++free_ch:
++ kfree(ch);
++
++reject:
++ rej->opcode = SRP_LOGIN_REJ;
++ rej->tag = req->tag;
++ rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
++ | SRP_BUF_FORMAT_INDIRECT);
++
++ ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
++ (void *)rej, sizeof *rej);
++
++out:
++ kfree(rep_param);
++ kfree(rsp);
++ kfree(rej);
++
++ return ret;
++}
++
++static void srpt_cm_rej_recv(struct ib_cm_id *cm_id)
++{
++ PRINT_INFO("Received InfiniBand REJ packet for cm_id %p.", cm_id);
++ srpt_release_channel_by_cmid(cm_id);
++}
++
++/**
++ * srpt_cm_rtu_recv() - Process an IB_CM_RTU_RECEIVED or IB_CM_USER_ESTABLISHED event.
++ *
++ * An IB_CM_RTU_RECEIVED message indicates that the connection is established
++ * and that the recipient may begin transmitting (RTU = ready to use).
++ */
++static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id)
++{
++ struct srpt_rdma_ch *ch;
++ int ret;
++
++ ch = srpt_find_channel(cm_id->context, cm_id);
++ WARN_ON(!ch);
++ if (!ch)
++ goto out;
++
++ if (srpt_test_and_set_channel_state(ch, RDMA_CHANNEL_CONNECTING,
++ RDMA_CHANNEL_LIVE) == RDMA_CHANNEL_CONNECTING) {
++ struct srpt_recv_ioctx *ioctx, *ioctx_tmp;
++
++ ret = srpt_ch_qp_rts(ch, ch->qp);
++
++ list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->cmd_wait_list,
++ wait_list) {
++ list_del(&ioctx->wait_list);
++ srpt_handle_new_iu(ch, ioctx, NULL,
++ SCST_CONTEXT_THREAD);
++ }
++ if (ret && srpt_test_and_set_channel_state(ch,
++ RDMA_CHANNEL_LIVE,
++ RDMA_CHANNEL_DISCONNECTING) == RDMA_CHANNEL_LIVE) {
++ TRACE_DBG("cm_id=%p sess_name=%s state=%d",
++ cm_id, ch->sess_name,
++ atomic_read(&ch->state));
++ ib_send_cm_dreq(ch->cm_id, NULL, 0);
++ }
++ }
++
++out:
++ ;
++}
++
++static void srpt_cm_timewait_exit(struct ib_cm_id *cm_id)
++{
++ PRINT_INFO("Received InfiniBand TimeWait exit for cm_id %p.", cm_id);
++ srpt_release_channel_by_cmid(cm_id);
++}
++
++static void srpt_cm_rep_error(struct ib_cm_id *cm_id)
++{
++ PRINT_INFO("Received InfiniBand REP error for cm_id %p.", cm_id);
++ srpt_release_channel_by_cmid(cm_id);
++}
++
++/**
++ * srpt_cm_dreq_recv() - Process reception of a DREQ message.
++ */
++static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id)
++{
++ struct srpt_rdma_ch *ch;
++
++ ch = srpt_find_channel(cm_id->context, cm_id);
++ if (!ch) {
++ TRACE_DBG("Received DREQ for channel %p which is already"
++ " being unregistered.", cm_id);
++ goto out;
++ }
++
++ TRACE_DBG("cm_id= %p ch->state= %d", cm_id, atomic_read(&ch->state));
++
++ switch (atomic_read(&ch->state)) {
++ case RDMA_CHANNEL_LIVE:
++ case RDMA_CHANNEL_CONNECTING:
++ ib_send_cm_drep(ch->cm_id, NULL, 0);
++ PRINT_INFO("Received DREQ and sent DREP for session %s.",
++ ch->sess_name);
++ break;
++ case RDMA_CHANNEL_DISCONNECTING:
++ default:
++ break;
++ }
++
++out:
++ ;
++}
++
++/**
++ * srpt_cm_drep_recv() - Process reception of a DREP message.
++ */
++static void srpt_cm_drep_recv(struct ib_cm_id *cm_id)
++{
++ PRINT_INFO("Received InfiniBand DREP message for cm_id %p.", cm_id);
++ srpt_release_channel_by_cmid(cm_id);
++}
++
++/**
++ * srpt_cm_handler() - IB connection manager callback function.
++ *
++ * A non-zero return value will cause the caller destroy the CM ID.
++ *
++ * Note: srpt_cm_handler() must only return a non-zero value when transferring
++ * ownership of the cm_id to a channel by srpt_cm_req_recv() failed. Returning
++ * a non-zero value in any other case will trigger a race with the
++ * ib_destroy_cm_id() call in srpt_release_channel().
++ */
++static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
++{
++ int ret;
++
++ ret = 0;
++ switch (event->event) {
++ case IB_CM_REQ_RECEIVED:
++ ret = srpt_cm_req_recv(cm_id, &event->param.req_rcvd,
++ event->private_data);
++ break;
++ case IB_CM_REJ_RECEIVED:
++ srpt_cm_rej_recv(cm_id);
++ break;
++ case IB_CM_RTU_RECEIVED:
++ case IB_CM_USER_ESTABLISHED:
++ srpt_cm_rtu_recv(cm_id);
++ break;
++ case IB_CM_DREQ_RECEIVED:
++ srpt_cm_dreq_recv(cm_id);
++ break;
++ case IB_CM_DREP_RECEIVED:
++ srpt_cm_drep_recv(cm_id);
++ break;
++ case IB_CM_TIMEWAIT_EXIT:
++ srpt_cm_timewait_exit(cm_id);
++ break;
++ case IB_CM_REP_ERROR:
++ srpt_cm_rep_error(cm_id);
++ break;
++ case IB_CM_DREQ_ERROR:
++ PRINT_INFO("%s", "Received IB DREQ ERROR event.");
++ break;
++ case IB_CM_MRA_RECEIVED:
++ PRINT_INFO("%s", "Received IB MRA event");
++ break;
++ default:
++ PRINT_ERROR("received unrecognized IB CM event %d",
++ event->event);
++ break;
++ }
++
++ return ret;
++}
++
++/**
++ * srpt_map_sg_to_ib_sge() - Map an SG list to an IB SGE list.
++ */
++static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx,
++ struct scst_cmd *scmnd)
++{
++ struct scatterlist *sg;
++ int sg_cnt;
++ scst_data_direction dir;
++ struct rdma_iu *riu;
++ struct srp_direct_buf *db;
++ dma_addr_t dma_addr;
++ struct ib_sge *sge;
++ u64 raddr;
++ u32 rsize;
++ u32 tsize;
++ u32 dma_len;
++ int count, nrdma;
++ int i, j, k;
++
++ BUG_ON(!ch);
++ BUG_ON(!ioctx);
++ BUG_ON(!scmnd);
++ dir = scst_cmd_get_data_direction(scmnd);
++ BUG_ON(dir == SCST_DATA_NONE);
++ /*
++ * Cache 'dir' because it is needed in srpt_unmap_sg_to_ib_sge()
++ * and because scst_set_cmd_error_status() resets scmnd->data_direction.
++ */
++ ioctx->dir = dir;
++ if (dir == SCST_DATA_WRITE) {
++ scst_cmd_get_write_fields(scmnd, &sg, &sg_cnt);
++ WARN_ON(!sg);
++ } else {
++ sg = scst_cmd_get_sg(scmnd);
++ sg_cnt = scst_cmd_get_sg_cnt(scmnd);
++ WARN_ON(!sg);
++ }
++ ioctx->sg = sg;
++ ioctx->sg_cnt = sg_cnt;
++ count = ib_dma_map_sg(ch->sport->sdev->device, sg, sg_cnt,
++ scst_to_tgt_dma_dir(dir));
++ if (unlikely(!count))
++ return -EBUSY;
++
++ ioctx->mapped_sg_count = count;
++
++ if (ioctx->rdma_ius && ioctx->n_rdma_ius)
++ nrdma = ioctx->n_rdma_ius;
++ else {
++ nrdma = count / SRPT_DEF_SG_PER_WQE + ioctx->n_rbuf;
++
++ ioctx->rdma_ius = kzalloc(nrdma * sizeof *riu,
++ scst_cmd_atomic(scmnd)
++ ? GFP_ATOMIC : GFP_KERNEL);
++ if (!ioctx->rdma_ius)
++ goto free_mem;
++
++ ioctx->n_rdma_ius = nrdma;
++ }
++
++ db = ioctx->rbufs;
++ tsize = (dir == SCST_DATA_READ)
++ ? scst_cmd_get_adjusted_resp_data_len(scmnd)
++ : scst_cmd_get_bufflen(scmnd);
++ dma_len = sg_dma_len(&sg[0]);
++ riu = ioctx->rdma_ius;
++
++ /*
++ * For each remote desc - calculate the #ib_sge.
++ * If #ib_sge < SRPT_DEF_SG_PER_WQE per rdma operation then
++ * each remote desc rdma_iu is required a rdma wr;
++ * else
++ * we need to allocate extra rdma_iu to carry extra #ib_sge in
++ * another rdma wr
++ */
++ for (i = 0, j = 0;
++ j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {
++ rsize = be32_to_cpu(db->len);
++ raddr = be64_to_cpu(db->va);
++ riu->raddr = raddr;
++ riu->rkey = be32_to_cpu(db->key);
++ riu->sge_cnt = 0;
++
++ /* calculate how many sge required for this remote_buf */
++ while (rsize > 0 && tsize > 0) {
++
++ if (rsize >= dma_len) {
++ tsize -= dma_len;
++ rsize -= dma_len;
++ raddr += dma_len;
++
++ if (tsize > 0) {
++ ++j;
++ if (j < count)
++ dma_len = sg_dma_len(&sg[j]);
++ }
++ } else {
++ tsize -= rsize;
++ dma_len -= rsize;
++ rsize = 0;
++ }
++
++ ++riu->sge_cnt;
++
++ if (rsize > 0 && riu->sge_cnt == SRPT_DEF_SG_PER_WQE) {
++ ++ioctx->n_rdma;
++ riu->sge =
++ kmalloc(riu->sge_cnt * sizeof *riu->sge,
++ scst_cmd_atomic(scmnd)
++ ? GFP_ATOMIC : GFP_KERNEL);
++ if (!riu->sge)
++ goto free_mem;
++
++ ++riu;
++ riu->sge_cnt = 0;
++ riu->raddr = raddr;
++ riu->rkey = be32_to_cpu(db->key);
++ }
++ }
++
++ ++ioctx->n_rdma;
++ riu->sge = kmalloc(riu->sge_cnt * sizeof *riu->sge,
++ scst_cmd_atomic(scmnd)
++ ? GFP_ATOMIC : GFP_KERNEL);
++ if (!riu->sge)
++ goto free_mem;
++ }
++
++ db = ioctx->rbufs;
++ tsize = (dir == SCST_DATA_READ)
++ ? scst_cmd_get_adjusted_resp_data_len(scmnd)
++ : scst_cmd_get_bufflen(scmnd);
++ riu = ioctx->rdma_ius;
++ dma_len = sg_dma_len(&sg[0]);
++ dma_addr = sg_dma_address(&sg[0]);
++
++ /* this second loop is really mapped sg_addres to rdma_iu->ib_sge */
++ for (i = 0, j = 0;
++ j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {
++ rsize = be32_to_cpu(db->len);
++ sge = riu->sge;
++ k = 0;
++
++ while (rsize > 0 && tsize > 0) {
++ sge->addr = dma_addr;
++ sge->lkey = ch->sport->sdev->mr->lkey;
++
++ if (rsize >= dma_len) {
++ sge->length =
++ (tsize < dma_len) ? tsize : dma_len;
++ tsize -= dma_len;
++ rsize -= dma_len;
++
++ if (tsize > 0) {
++ ++j;
++ if (j < count) {
++ dma_len = sg_dma_len(&sg[j]);
++ dma_addr =
++ sg_dma_address(&sg[j]);
++ }
++ }
++ } else {
++ sge->length = (tsize < rsize) ? tsize : rsize;
++ tsize -= rsize;
++ dma_len -= rsize;
++ dma_addr += rsize;
++ rsize = 0;
++ }
++
++ ++k;
++ if (k == riu->sge_cnt && rsize > 0) {
++ ++riu;
++ sge = riu->sge;
++ k = 0;
++ } else if (rsize > 0)
++ ++sge;
++ }
++ }
++
++ return 0;
++
++free_mem:
++ srpt_unmap_sg_to_ib_sge(ch, ioctx);
++
++ return -ENOMEM;
++}
++
++/**
++ * srpt_unmap_sg_to_ib_sge() - Unmap an IB SGE list.
++ */
++static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx)
++{
++ struct scst_cmd *scmnd;
++ struct scatterlist *sg;
++ scst_data_direction dir;
++
++ EXTRACHECKS_BUG_ON(!ch);
++ EXTRACHECKS_BUG_ON(!ioctx);
++ EXTRACHECKS_BUG_ON(ioctx->n_rdma && !ioctx->rdma_ius);
++
++ while (ioctx->n_rdma)
++ kfree(ioctx->rdma_ius[--ioctx->n_rdma].sge);
++
++ kfree(ioctx->rdma_ius);
++ ioctx->rdma_ius = NULL;
++
++ if (ioctx->mapped_sg_count) {
++ scmnd = ioctx->scmnd;
++ EXTRACHECKS_BUG_ON(!scmnd);
++ EXTRACHECKS_WARN_ON(ioctx->scmnd != scmnd);
++ EXTRACHECKS_WARN_ON(ioctx != scst_cmd_get_tgt_priv(scmnd));
++ sg = ioctx->sg;
++ EXTRACHECKS_WARN_ON(!sg);
++ dir = ioctx->dir;
++ EXTRACHECKS_BUG_ON(dir == SCST_DATA_NONE);
++ ib_dma_unmap_sg(ch->sport->sdev->device, sg, ioctx->sg_cnt,
++ scst_to_tgt_dma_dir(dir));
++ ioctx->mapped_sg_count = 0;
++ }
++}
++
++/**
++ * srpt_perform_rdmas() - Perform IB RDMA.
++ *
++ * Returns zero upon success or a negative number upon failure.
++ */
++static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx,
++ scst_data_direction dir)
++{
++ struct ib_send_wr wr;
++ struct ib_send_wr *bad_wr;
++ struct rdma_iu *riu;
++ int i;
++ int ret;
++ int sq_wr_avail;
++
++ if (dir == SCST_DATA_WRITE) {
++ ret = -ENOMEM;
++ sq_wr_avail = atomic_sub_return(ioctx->n_rdma,
++ &ch->sq_wr_avail);
++ if (sq_wr_avail < 0) {
++ PRINT_WARNING("IB send queue full (needed %d)",
++ ioctx->n_rdma);
++ goto out;
++ }
++ }
++
++ ret = 0;
++ riu = ioctx->rdma_ius;
++ memset(&wr, 0, sizeof wr);
++
++ for (i = 0; i < ioctx->n_rdma; ++i, ++riu) {
++ if (dir == SCST_DATA_READ) {
++ wr.opcode = IB_WR_RDMA_WRITE;
++ wr.wr_id = encode_wr_id(IB_WC_RDMA_WRITE,
++ ioctx->ioctx.index);
++ } else {
++ wr.opcode = IB_WR_RDMA_READ;
++ wr.wr_id = encode_wr_id(IB_WC_RDMA_READ,
++ ioctx->ioctx.index);
++ }
++ wr.next = NULL;
++ wr.wr.rdma.remote_addr = riu->raddr;
++ wr.wr.rdma.rkey = riu->rkey;
++ wr.num_sge = riu->sge_cnt;
++ wr.sg_list = riu->sge;
++
++ /* only get completion event for the last rdma wr */
++ if (i == (ioctx->n_rdma - 1) && dir == SCST_DATA_WRITE)
++ wr.send_flags = IB_SEND_SIGNALED;
++
++ ret = ib_post_send(ch->qp, &wr, &bad_wr);
++ if (ret)
++ goto out;
++ }
++
++out:
++ if (unlikely(dir == SCST_DATA_WRITE && ret < 0))
++ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
++ return ret;
++}
++
++/**
++ * srpt_xfer_data() - Start data transfer from initiator to target.
++ *
++ * Returns an SCST_TGT_RES_... status code.
++ *
++ * Note: Must not block.
++ */
++static int srpt_xfer_data(struct srpt_rdma_ch *ch,
++ struct srpt_send_ioctx *ioctx,
++ struct scst_cmd *scmnd)
++{
++ int ret;
++
++ ret = srpt_map_sg_to_ib_sge(ch, ioctx, scmnd);
++ if (ret) {
++ PRINT_ERROR("%s[%d] ret=%d", __func__, __LINE__, ret);
++ ret = SCST_TGT_RES_QUEUE_FULL;
++ goto out;
++ }
++
++ ret = srpt_perform_rdmas(ch, ioctx, scst_cmd_get_data_direction(scmnd));
++ if (ret) {
++ if (ret == -EAGAIN || ret == -ENOMEM) {
++ PRINT_INFO("%s[%d] queue full -- ret=%d",
++ __func__, __LINE__, ret);
++ ret = SCST_TGT_RES_QUEUE_FULL;
++ } else {
++ PRINT_ERROR("%s[%d] fatal error -- ret=%d",
++ __func__, __LINE__, ret);
++ ret = SCST_TGT_RES_FATAL_ERROR;
++ }
++ goto out_unmap;
++ }
++
++ ret = SCST_TGT_RES_SUCCESS;
++
++out:
++ return ret;
++out_unmap:
++ srpt_unmap_sg_to_ib_sge(ch, ioctx);
++ goto out;
++}
++
++/**
++ * srpt_pending_cmd_timeout() - SCST command HCA processing timeout callback.
++ *
++ * Called by the SCST core if no IB completion notification has been received
++ * within max_hw_pending_time seconds.
++ */
++static void srpt_pending_cmd_timeout(struct scst_cmd *scmnd)
++{
++ struct srpt_send_ioctx *ioctx;
++ enum srpt_command_state state;
++
++ ioctx = scst_cmd_get_tgt_priv(scmnd);
++ BUG_ON(!ioctx);
++
++ state = srpt_get_cmd_state(ioctx);
++ switch (state) {
++ case SRPT_STATE_NEW:
++ case SRPT_STATE_DATA_IN:
++ case SRPT_STATE_DONE:
++ /*
++ * srpt_pending_cmd_timeout() should never be invoked for
++ * commands in this state.
++ */
++ PRINT_ERROR("Processing SCST command %p (SRPT state %d) took"
++ " too long -- aborting", scmnd, state);
++ break;
++ case SRPT_STATE_NEED_DATA:
++ case SRPT_STATE_CMD_RSP_SENT:
++ case SRPT_STATE_MGMT_RSP_SENT:
++ default:
++ PRINT_ERROR("Command %p: IB completion for idx %u has not"
++ " been received in time (SRPT command state %d)",
++ scmnd, ioctx->ioctx.index, state);
++ break;
++ }
++
++ srpt_abort_scst_cmd(ioctx, SCST_CONTEXT_SAME);
++}
++
++/**
++ * srpt_rdy_to_xfer() - Transfers data from initiator to target.
++ *
++ * Called by the SCST core to transfer data from the initiator to the target
++ * (SCST_DATA_WRITE). Must not block.
++ */
++static int srpt_rdy_to_xfer(struct scst_cmd *scmnd)
++{
++ struct srpt_rdma_ch *ch;
++ struct srpt_send_ioctx *ioctx;
++ enum srpt_command_state new_state;
++ enum rdma_ch_state ch_state;
++ int ret;
++
++ ioctx = scst_cmd_get_tgt_priv(scmnd);
++ BUG_ON(!ioctx);
++
++ new_state = srpt_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA);
++ WARN_ON(new_state == SRPT_STATE_DONE);
++
++ ch = ioctx->ch;
++ WARN_ON(ch != scst_sess_get_tgt_priv(scst_cmd_get_session(scmnd)));
++ BUG_ON(!ch);
++
++ ch_state = atomic_read(&ch->state);
++ if (ch_state == RDMA_CHANNEL_DISCONNECTING) {
++ TRACE_DBG("cmd with tag %lld: channel disconnecting",
++ scst_cmd_get_tag(scmnd));
++ srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN);
++ ret = SCST_TGT_RES_FATAL_ERROR;
++ goto out;
++ } else if (ch_state == RDMA_CHANNEL_CONNECTING) {
++ ret = SCST_TGT_RES_QUEUE_FULL;
++ goto out;
++ }
++ ret = srpt_xfer_data(ch, ioctx, scmnd);
++
++out:
++ return ret;
++}
++
++/**
++ * srpt_xmit_response() - Transmits the response to a SCSI command.
++ *
++ * Callback function called by the SCST core. Must not block. Must ensure that
++ * scst_tgt_cmd_done() will get invoked when returning SCST_TGT_RES_SUCCESS.
++ */
++static int srpt_xmit_response(struct scst_cmd *scmnd)
++{
++ struct srpt_rdma_ch *ch;
++ struct srpt_send_ioctx *ioctx;
++ enum srpt_command_state state;
++ int ret;
++ scst_data_direction dir;
++ int resp_len;
++
++ ret = SCST_TGT_RES_SUCCESS;
++
++ ioctx = scst_cmd_get_tgt_priv(scmnd);
++ BUG_ON(!ioctx);
++
++ ch = scst_sess_get_tgt_priv(scst_cmd_get_session(scmnd));
++ BUG_ON(!ch);
++
++ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEW,
++ SRPT_STATE_CMD_RSP_SENT);
++ if (state != SRPT_STATE_NEW) {
++ state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_DATA_IN,
++ SRPT_STATE_CMD_RSP_SENT);
++ if (state != SRPT_STATE_DATA_IN)
++ PRINT_ERROR("Unexpected command state %d",
++ srpt_get_cmd_state(ioctx));
++ }
++
++ if (unlikely(scst_cmd_aborted(scmnd))) {
++ atomic_inc(&ch->req_lim_delta);
++ srpt_abort_scst_cmd(ioctx, SCST_CONTEXT_SAME);
++ goto out;
++ }
++
++ EXTRACHECKS_BUG_ON(scst_cmd_atomic(scmnd));
++
++ dir = scst_cmd_get_data_direction(scmnd);
++
++ /* For read commands, transfer the data to the initiator. */
++ if (dir == SCST_DATA_READ
++ && scst_cmd_get_adjusted_resp_data_len(scmnd)) {
++ ret = srpt_xfer_data(ch, ioctx, scmnd);
++ if (ret == SCST_TGT_RES_QUEUE_FULL) {
++ srpt_set_cmd_state(ioctx, state);
++ PRINT_WARNING("xfer_data failed for tag %llu"
++ " - retrying", scst_cmd_get_tag(scmnd));
++ goto out;
++ } else if (ret != SCST_TGT_RES_SUCCESS) {
++ PRINT_ERROR("xfer_data failed for tag %llu",
++ scst_cmd_get_tag(scmnd));
++ goto out;
++ }
++ }
++
++ atomic_inc(&ch->req_lim);
++
++ resp_len = srpt_build_cmd_rsp(ch, ioctx,
++ scst_cmd_get_tag(scmnd),
++ scst_cmd_get_status(scmnd),
++ scst_cmd_get_sense_buffer(scmnd),
++ scst_cmd_get_sense_buffer_len(scmnd));
++
++ if (srpt_post_send(ch, ioctx, resp_len)) {
++ srpt_unmap_sg_to_ib_sge(ch, ioctx);
++ srpt_set_cmd_state(ioctx, state);
++ atomic_dec(&ch->req_lim);
++ PRINT_WARNING("sending response failed for tag %llu - retrying",
++ scst_cmd_get_tag(scmnd));
++ ret = SCST_TGT_RES_QUEUE_FULL;
++ }
++
++out:
++ return ret;
++}
++
++/**
++ * srpt_tsk_mgmt_done() - SCST callback function that sends back the response
++ * for a task management request.
++ *
++ * Must not block.
++ */
++static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd)
++{
++ struct srpt_rdma_ch *ch;
++ struct srpt_mgmt_ioctx *mgmt_ioctx;
++ struct srpt_send_ioctx *ioctx;
++ enum srpt_command_state new_state;
++ int rsp_len;
++
++ mgmt_ioctx = scst_mgmt_cmd_get_tgt_priv(mcmnd);
++ BUG_ON(!mgmt_ioctx);
++
++ ioctx = mgmt_ioctx->ioctx;
++ BUG_ON(!ioctx);
++
++ ch = ioctx->ch;
++ BUG_ON(!ch);
++
++ TRACE_DBG("%s: tsk_mgmt_done for tag= %lld status=%d",
++ __func__, mgmt_ioctx->tag, scst_mgmt_cmd_get_status(mcmnd));
++
++ WARN_ON(in_irq());
++
++ new_state = srpt_set_cmd_state(ioctx, SRPT_STATE_MGMT_RSP_SENT);
++ WARN_ON(new_state == SRPT_STATE_DONE);
++
++ atomic_inc(&ch->req_lim);
++
++ rsp_len = srpt_build_tskmgmt_rsp(ch, ioctx,
++ scst_to_srp_tsk_mgmt_status(
++ scst_mgmt_cmd_get_status(mcmnd)),
++ mgmt_ioctx->tag);
++ /*
++ * Note: the srpt_post_send() call below sends the task management
++ * response asynchronously. It is possible that the SCST core has
++ * already freed the struct scst_mgmt_cmd structure before the
++ * response is sent. This is fine however.
++ */
++ if (srpt_post_send(ch, ioctx, rsp_len)) {
++ PRINT_ERROR("%s", "Sending SRP_RSP response failed.");
++ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
++ srpt_put_send_ioctx(ioctx);
++ atomic_dec(&ch->req_lim);
++ }
++
++ scst_mgmt_cmd_set_tgt_priv(mcmnd, NULL);
++
++ kfree(mgmt_ioctx);
++}
++
++/**
++ * srpt_get_initiator_port_transport_id() - SCST TransportID callback function.
++ *
++ * See also SPC-3, section 7.5.4.5, TransportID for initiator ports using SRP.
++ */
++static int srpt_get_initiator_port_transport_id(struct scst_session *scst_sess,
++ uint8_t **transport_id)
++{
++ struct srpt_rdma_ch *ch;
++ struct spc_rdma_transport_id {
++ uint8_t protocol_identifier;
++ uint8_t reserved[7];
++ uint8_t i_port_id[16];
++ };
++ struct spc_rdma_transport_id *tr_id;
++ int res;
++
++ TRACE_ENTRY();
++
++ if (!scst_sess) {
++ res = SCSI_TRANSPORTID_PROTOCOLID_SRP;
++ goto out;
++ }
++
++ ch = scst_sess_get_tgt_priv(scst_sess);
++ BUG_ON(!ch);
++
++ BUILD_BUG_ON(sizeof(*tr_id) != 24);
++
++ tr_id = kzalloc(sizeof(struct spc_rdma_transport_id), GFP_KERNEL);
++ if (!tr_id) {
++ PRINT_ERROR("%s", "Allocation of TransportID failed");
++ res = -ENOMEM;
++ goto out;
++ }
++
++ res = 0;
++ tr_id->protocol_identifier = SCSI_TRANSPORTID_PROTOCOLID_SRP;
++ memcpy(tr_id->i_port_id, ch->i_port_id, sizeof(ch->i_port_id));
++
++ *transport_id = (uint8_t *)tr_id;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ * srpt_on_free_cmd() - Free command-private data.
++ *
++ * Called by the SCST core. May be called in IRQ context.
++ */
++static void srpt_on_free_cmd(struct scst_cmd *scmnd)
++{
++}
++
++static void srpt_refresh_port_work(struct work_struct *work)
++{
++ struct srpt_port *sport = container_of(work, struct srpt_port, work);
++
++ srpt_refresh_port(sport);
++}
++
++/**
++ * srpt_detect() - Returns the number of target adapters.
++ *
++ * Callback function called by the SCST core.
++ */
++static int srpt_detect(struct scst_tgt_template *tp)
++{
++ int device_count;
++
++ TRACE_ENTRY();
++
++ device_count = atomic_read(&srpt_device_count);
++
++ TRACE_EXIT_RES(device_count);
++
++ return device_count;
++}
++
++/**
++ * srpt_release() - Free the resources associated with an SCST target.
++ *
++ * Callback function called by the SCST core from scst_unregister_target().
++ */
++static int srpt_release(struct scst_tgt *scst_tgt)
++{
++ struct srpt_device *sdev = scst_tgt_get_tgt_priv(scst_tgt);
++ struct srpt_rdma_ch *ch;
++
++ TRACE_ENTRY();
++
++ EXTRACHECKS_WARN_ON_ONCE(irqs_disabled());
++
++ BUG_ON(!scst_tgt);
++ if (WARN_ON(!sdev))
++ return -ENODEV;
++
++ spin_lock_irq(&sdev->spinlock);
++ while (!list_empty(&sdev->rch_list)) {
++ ch = list_first_entry(&sdev->rch_list, typeof(*ch), list);
++ srpt_unregister_channel(ch);
++ }
++ spin_unlock_irq(&sdev->spinlock);
++
++ scst_tgt_set_tgt_priv(scst_tgt, NULL);
++
++ TRACE_EXIT();
++
++ return 0;
++}
++
++/**
++ * srpt_get_scsi_transport_version() - Returns the SCSI transport version.
++ * This function is called from scst_pres.c, the code that implements
++ * persistent reservation support.
++ */
++static uint16_t srpt_get_scsi_transport_version(struct scst_tgt *scst_tgt)
++{
++ return 0x0940; /* SRP */
++}
++
++static ssize_t show_req_lim(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_session *scst_sess;
++ struct srpt_rdma_ch *ch;
++
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
++ ch = scst_sess_get_tgt_priv(scst_sess);
++ if (!ch)
++ return -ENOENT;
++ return sprintf(buf, "%d\n", atomic_read(&ch->req_lim));
++}
++
++static ssize_t show_req_lim_delta(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_session *scst_sess;
++ struct srpt_rdma_ch *ch;
++
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
++ ch = scst_sess_get_tgt_priv(scst_sess);
++ if (!ch)
++ return -ENOENT;
++ return sprintf(buf, "%d\n", atomic_read(&ch->req_lim_delta));
++}
++
++static const struct kobj_attribute srpt_req_lim_attr =
++ __ATTR(req_lim, S_IRUGO, show_req_lim, NULL);
++static const struct kobj_attribute srpt_req_lim_delta_attr =
++ __ATTR(req_lim_delta, S_IRUGO, show_req_lim_delta, NULL);
++
++static const struct attribute *srpt_sess_attrs[] = {
++ &srpt_req_lim_attr.attr,
++ &srpt_req_lim_delta_attr.attr,
++ NULL
++};
++
++/* SCST target template for the SRP target implementation. */
++static struct scst_tgt_template srpt_template = {
++ .name = DRV_NAME,
++ .sg_tablesize = SRPT_DEF_SG_TABLESIZE,
++ .max_hw_pending_time = 60/*seconds*/,
++ .enable_target = srpt_enable_target,
++ .is_target_enabled = srpt_is_target_enabled,
++ .sess_attrs = srpt_sess_attrs,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = DEFAULT_SRPT_TRACE_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++ .detect = srpt_detect,
++ .release = srpt_release,
++ .xmit_response = srpt_xmit_response,
++ .rdy_to_xfer = srpt_rdy_to_xfer,
++ .on_hw_pending_cmd_timeout = srpt_pending_cmd_timeout,
++ .on_free_cmd = srpt_on_free_cmd,
++ .task_mgmt_fn_done = srpt_tsk_mgmt_done,
++ .get_initiator_port_transport_id = srpt_get_initiator_port_transport_id,
++ .get_scsi_transport_version = srpt_get_scsi_transport_version,
++};
++
++/**
++ * srpt_dev_release() - Device release callback function.
++ *
++ * The callback function srpt_dev_release() is called whenever a
++ * device is removed from the /sys/class/infiniband_srpt device class.
++ * Although this function has been left empty, a release function has been
++ * defined such that upon module removal no complaint is logged about a
++ * missing release function.
++ */
++static void srpt_dev_release(struct device *dev)
++{
++}
++
++static ssize_t show_login_info(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct srpt_device *sdev;
++ struct srpt_port *sport;
++ int i;
++ int len;
++
++ sdev = container_of(dev, struct srpt_device, dev);
++ len = 0;
++ for (i = 0; i < sdev->device->phys_port_cnt; i++) {
++ sport = &sdev->port[i];
++
++ len += sprintf(buf + len,
++ "tid_ext=%016llx,ioc_guid=%016llx,pkey=ffff,"
++ "dgid=%04x%04x%04x%04x%04x%04x%04x%04x,"
++ "service_id=%016llx\n",
++ srpt_service_guid,
++ srpt_service_guid,
++ be16_to_cpu(((__be16 *) sport->gid.raw)[0]),
++ be16_to_cpu(((__be16 *) sport->gid.raw)[1]),
++ be16_to_cpu(((__be16 *) sport->gid.raw)[2]),
++ be16_to_cpu(((__be16 *) sport->gid.raw)[3]),
++ be16_to_cpu(((__be16 *) sport->gid.raw)[4]),
++ be16_to_cpu(((__be16 *) sport->gid.raw)[5]),
++ be16_to_cpu(((__be16 *) sport->gid.raw)[6]),
++ be16_to_cpu(((__be16 *) sport->gid.raw)[7]),
++ srpt_service_guid);
++ }
++
++ return len;
++}
++
++static struct class_attribute srpt_class_attrs[] = {
++ __ATTR_NULL,
++};
++
++static struct device_attribute srpt_dev_attrs[] = {
++ __ATTR(login_info, S_IRUGO, show_login_info, NULL),
++ __ATTR_NULL,
++};
++
++static struct class srpt_class = {
++ .name = "infiniband_srpt",
++ .dev_release = srpt_dev_release,
++ .class_attrs = srpt_class_attrs,
++ .dev_attrs = srpt_dev_attrs,
++};
++
++/**
++ * srpt_add_one() - Infiniband device addition callback function.
++ */
++static void srpt_add_one(struct ib_device *device)
++{
++ struct srpt_device *sdev;
++ struct srpt_port *sport;
++ struct ib_srq_init_attr srq_attr;
++ int i;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("device = %p, device->dma_ops = %p", device, device->dma_ops);
++
++ sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
++ if (!sdev)
++ goto err;
++
++ sdev->device = device;
++ INIT_LIST_HEAD(&sdev->rch_list);
++ spin_lock_init(&sdev->spinlock);
++
++ sdev->scst_tgt = scst_register_target(&srpt_template, NULL);
++ if (!sdev->scst_tgt) {
++ PRINT_ERROR("SCST registration failed for %s.",
++ sdev->device->name);
++ goto free_dev;
++ }
++
++ scst_tgt_set_tgt_priv(sdev->scst_tgt, sdev);
++
++ sdev->dev.class = &srpt_class;
++ sdev->dev.parent = device->dma_device;
++ dev_set_name(&sdev->dev, "srpt-%s", device->name);
++
++ if (device_register(&sdev->dev))
++ goto unregister_tgt;
++
++ if (ib_query_device(device, &sdev->dev_attr))
++ goto err_dev;
++
++ sdev->pd = ib_alloc_pd(device);
++ if (IS_ERR(sdev->pd))
++ goto err_dev;
++
++ sdev->mr = ib_get_dma_mr(sdev->pd, IB_ACCESS_LOCAL_WRITE);
++ if (IS_ERR(sdev->mr))
++ goto err_pd;
++
++ sdev->srq_size = min(srpt_srq_size, sdev->dev_attr.max_srq_wr);
++
++ srq_attr.event_handler = srpt_srq_event;
++ srq_attr.srq_context = (void *)sdev;
++ srq_attr.attr.max_wr = sdev->srq_size;
++ srq_attr.attr.max_sge = 1;
++ srq_attr.attr.srq_limit = 0;
++
++ sdev->srq = ib_create_srq(sdev->pd, &srq_attr);
++ if (IS_ERR(sdev->srq))
++ goto err_mr;
++
++ TRACE_DBG("%s: create SRQ #wr= %d max_allow=%d dev= %s", __func__,
++ sdev->srq_size, sdev->dev_attr.max_srq_wr, device->name);
++
++ if (!srpt_service_guid)
++ srpt_service_guid = be64_to_cpu(device->node_guid);
++
++ sdev->cm_id = ib_create_cm_id(device, srpt_cm_handler, sdev);
++ if (IS_ERR(sdev->cm_id))
++ goto err_srq;
++
++ /* print out target login information */
++ TRACE_DBG("Target login info: id_ext=%016llx,"
++ "ioc_guid=%016llx,pkey=ffff,service_id=%016llx",
++ srpt_service_guid, srpt_service_guid, srpt_service_guid);
++
++ /*
++ * We do not have a consistent service_id (ie. also id_ext of target_id)
++ * to identify this target. We currently use the guid of the first HCA
++ * in the system as service_id; therefore, the target_id will change
++ * if this HCA is gone bad and replaced by different HCA
++ */
++ if (ib_cm_listen(sdev->cm_id, cpu_to_be64(srpt_service_guid), 0, NULL))
++ goto err_cm;
++
++ INIT_IB_EVENT_HANDLER(&sdev->event_handler, sdev->device,
++ srpt_event_handler);
++ if (ib_register_event_handler(&sdev->event_handler))
++ goto err_cm;
++
++ sdev->ioctx_ring = (struct srpt_recv_ioctx **)
++ srpt_alloc_ioctx_ring(sdev, sdev->srq_size,
++ sizeof(*sdev->ioctx_ring[0]),
++ srp_max_req_size, DMA_FROM_DEVICE);
++ if (!sdev->ioctx_ring)
++ goto err_event;
++
++ for (i = 0; i < sdev->srq_size; ++i)
++ srpt_post_recv(sdev, sdev->ioctx_ring[i]);
++
++ WARN_ON(sdev->device->phys_port_cnt
++ > sizeof(sdev->port)/sizeof(sdev->port[0]));
++
++ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
++ sport = &sdev->port[i - 1];
++ sport->sdev = sdev;
++ sport->port = i;
++ INIT_WORK(&sport->work, srpt_refresh_port_work);
++ if (srpt_refresh_port(sport)) {
++ PRINT_ERROR("MAD registration failed for %s-%d.",
++ sdev->device->name, i);
++ goto err_ring;
++ }
++ }
++
++ atomic_inc(&srpt_device_count);
++out:
++ ib_set_client_data(device, &srpt_client, sdev);
++
++ TRACE_EXIT();
++ return;
++
++err_ring:
++ srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
++ sdev->srq_size, srp_max_req_size,
++ DMA_FROM_DEVICE);
++err_event:
++ ib_unregister_event_handler(&sdev->event_handler);
++err_cm:
++ ib_destroy_cm_id(sdev->cm_id);
++err_srq:
++ ib_destroy_srq(sdev->srq);
++err_mr:
++ ib_dereg_mr(sdev->mr);
++err_pd:
++ ib_dealloc_pd(sdev->pd);
++err_dev:
++ device_unregister(&sdev->dev);
++unregister_tgt:
++ scst_unregister_target(sdev->scst_tgt);
++free_dev:
++ kfree(sdev);
++err:
++ sdev = NULL;
++ PRINT_INFO("%s(%s) failed.", __func__, device->name);
++ goto out;
++}
++
++/**
++ * srpt_remove_one() - InfiniBand device removal callback function.
++ */
++static void srpt_remove_one(struct ib_device *device)
++{
++ int i;
++ struct srpt_device *sdev;
++
++ TRACE_ENTRY();
++
++ sdev = ib_get_client_data(device, &srpt_client);
++ if (!sdev) {
++ PRINT_INFO("%s(%s): nothing to do.", __func__, device->name);
++ return;
++ }
++
++ srpt_unregister_mad_agent(sdev);
++
++ ib_unregister_event_handler(&sdev->event_handler);
++
++ /* Cancel any work queued by the just unregistered IB event handler. */
++ for (i = 0; i < sdev->device->phys_port_cnt; i++)
++ cancel_work_sync(&sdev->port[i].work);
++
++ ib_destroy_cm_id(sdev->cm_id);
++ ib_destroy_srq(sdev->srq);
++ ib_dereg_mr(sdev->mr);
++ ib_dealloc_pd(sdev->pd);
++
++ device_unregister(&sdev->dev);
++
++ /*
++ * Unregistering an SCST target must happen after destroying sdev->cm_id
++ * such that no new SRP_LOGIN_REQ information units can arrive while
++ * destroying the SCST target.
++ */
++ scst_unregister_target(sdev->scst_tgt);
++ sdev->scst_tgt = NULL;
++
++ srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
++ sdev->srq_size, srp_max_req_size, DMA_FROM_DEVICE);
++ sdev->ioctx_ring = NULL;
++ kfree(sdev);
++
++ TRACE_EXIT();
++}
++
++/**
++ * srpt_init_module() - Kernel module initialization.
++ *
++ * Note: Since ib_register_client() registers callback functions, and since at
++ * least one of these callback functions (srpt_add_one()) calls SCST functions,
++ * the SCST target template must be registered before ib_register_client() is
++ * called.
++ */
++static int __init srpt_init_module(void)
++{
++ int ret;
++
++ ret = -EINVAL;
++ if (srp_max_req_size < MIN_MAX_REQ_SIZE) {
++ PRINT_ERROR("invalid value %d for kernel module parameter"
++ " srp_max_req_size -- must be at least %d.",
++ srp_max_req_size,
++ MIN_MAX_REQ_SIZE);
++ goto out;
++ }
++
++ if (srp_max_rsp_size < MIN_MAX_RSP_SIZE) {
++ PRINT_ERROR("invalid value %d for kernel module parameter"
++ " srp_max_rsp_size -- must be at least %d.",
++ srp_max_rsp_size,
++ MIN_MAX_RSP_SIZE);
++ goto out;
++ }
++
++ if (srpt_srq_size < MIN_SRPT_SRQ_SIZE
++ || srpt_srq_size > MAX_SRPT_SRQ_SIZE) {
++ PRINT_ERROR("invalid value %d for kernel module parameter"
++ " srpt_srq_size -- must be in the range [%d..%d].",
++ srpt_srq_size, MIN_SRPT_SRQ_SIZE,
++ MAX_SRPT_SRQ_SIZE);
++ goto out;
++ }
++
++ if (srpt_sq_size < MIN_SRPT_SQ_SIZE) {
++ PRINT_ERROR("invalid value %d for kernel module parameter"
++ " srpt_sq_size -- must be at least %d.",
++ srpt_srq_size, MIN_SRPT_SQ_SIZE);
++ goto out;
++ }
++
++ ret = class_register(&srpt_class);
++ if (ret) {
++ PRINT_ERROR("%s", "couldn't register class ib_srpt");
++ goto out;
++ }
++
++ switch (thread) {
++ case MODE_ALL_IN_SIRQ:
++ /*
++ * Process both IB completions and SCST commands in SIRQ
++ * context. May lead to soft lockups and other scary behavior
++ * under sufficient load.
++ */
++ srpt_template.rdy_to_xfer_atomic = true;
++ break;
++ case MODE_IB_COMPLETION_IN_THREAD:
++ /*
++ * Process IB completions in the kernel thread associated with
++ * the RDMA channel, and process SCST commands in the kernel
++ * threads created by the SCST core.
++ */
++ srpt_template.rdy_to_xfer_atomic = false;
++ break;
++ case MODE_IB_COMPLETION_IN_SIRQ:
++ default:
++ /*
++ * Process IB completions in SIRQ context and SCST commands in
++ * the kernel threads created by the SCST core.
++ */
++ srpt_template.rdy_to_xfer_atomic = false;
++ break;
++ }
++
++ ret = scst_register_target_template(&srpt_template);
++ if (ret < 0) {
++ PRINT_ERROR("%s", "couldn't register with scst");
++ ret = -ENODEV;
++ goto out_unregister_class;
++ }
++
++ ret = ib_register_client(&srpt_client);
++ if (ret) {
++ PRINT_ERROR("%s", "couldn't register IB client");
++ goto out_unregister_procfs;
++ }
++
++ return 0;
++
++out_unregister_procfs:
++ scst_unregister_target_template(&srpt_template);
++out_unregister_class:
++ class_unregister(&srpt_class);
++out:
++ return ret;
++}
++
++static void __exit srpt_cleanup_module(void)
++{
++ TRACE_ENTRY();
++
++ ib_unregister_client(&srpt_client);
++ scst_unregister_target_template(&srpt_template);
++ class_unregister(&srpt_class);
++
++ TRACE_EXIT();
++}
++
++module_init(srpt_init_module);
++module_exit(srpt_cleanup_module);
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ * indent-tabs-mode: t
++ * End:
++ */
+diff -uprN orig/linux-2.6.36/drivers/scst/srpt/ib_srpt.h linux-2.6.36/drivers/scst/srpt/ib_srpt.h
+--- orig/linux-2.6.36/drivers/scst/srpt/ib_srpt.h
++++ linux-2.6.36/drivers/scst/srpt/ib_srpt.h
+@@ -0,0 +1,353 @@
++/*
++ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
++ * Copyright (C) 2009 - 2010 Bart Van Assche <bart.vanassche@gmail.com>
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++#ifndef IB_SRPT_H
++#define IB_SRPT_H
++
++#include <linux/version.h>
++#include <linux/types.h>
++#include <linux/list.h>
++
++#include <rdma/ib_verbs.h>
++#include <rdma/ib_sa.h>
++#include <rdma/ib_cm.h>
++
++#include <scsi/srp.h>
++
++#include <scst/scst.h>
++
++#include "ib_dm_mad.h"
++
++/*
++ * The prefix the ServiceName field must start with in the device management
++ * ServiceEntries attribute pair. See also the SRP r16a document.
++ */
++#define SRP_SERVICE_NAME_PREFIX "SRP.T10:"
++
++enum {
++ /*
++ * SRP IOControllerProfile attributes for SRP target ports that have
++ * not been defined in <scsi/srp.h>. Source: section B.7, table B.7
++ * in the SRP r16a document.
++ */
++ SRP_PROTOCOL = 0x0108,
++ SRP_PROTOCOL_VERSION = 0x0001,
++ SRP_IO_SUBCLASS = 0x609e,
++ SRP_SEND_TO_IOC = 0x01,
++ SRP_SEND_FROM_IOC = 0x02,
++ SRP_RDMA_READ_FROM_IOC = 0x08,
++ SRP_RDMA_WRITE_FROM_IOC = 0x20,
++
++ /*
++ * srp_login_cmd.req_flags bitmasks. See also table 9 in the SRP r16a
++ * document.
++ */
++ SRP_MTCH_ACTION = 0x03, /* MULTI-CHANNEL ACTION */
++ SRP_LOSOLNT = 0x10, /* logout solicited notification */
++ SRP_CRSOLNT = 0x20, /* credit request solicited notification */
++ SRP_AESOLNT = 0x40, /* asynchronous event solicited notification */
++
++ /*
++ * srp_cmd.sol_nt / srp_tsk_mgmt.sol_not bitmasks. See also tables
++ * 18 and 20 in the T10 r16a document.
++ */
++ SRP_SCSOLNT = 0x02, /* SCSOLNT = successful solicited notification */
++ SRP_UCSOLNT = 0x04, /* UCSOLNT = unsuccessful solicited notification */
++
++ /*
++ * srp_rsp.sol_not / srp_t_logout.sol_not bitmasks. See also tables
++ * 16 and 22 in the T10 r16a document.
++ */
++ SRP_SOLNT = 0x01, /* SOLNT = solicited notification */
++
++ /* See also table 24 in the T10 r16a document. */
++ SRP_TSK_MGMT_SUCCESS = 0x00,
++ SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04,
++ SRP_TSK_MGMT_FAILED = 0x05,
++
++ /* See also table 21 in the T10 r16a document. */
++ SRP_CMD_SIMPLE_Q = 0x0,
++ SRP_CMD_HEAD_OF_Q = 0x1,
++ SRP_CMD_ORDERED_Q = 0x2,
++ SRP_CMD_ACA = 0x4,
++
++ SRP_LOGIN_RSP_MULTICHAN_NO_CHAN = 0x0,
++ SRP_LOGIN_RSP_MULTICHAN_TERMINATED = 0x1,
++ SRP_LOGIN_RSP_MULTICHAN_MAINTAINED = 0x2,
++
++ SRPT_DEF_SG_TABLESIZE = 128,
++ SRPT_DEF_SG_PER_WQE = 16,
++
++ MIN_SRPT_SQ_SIZE = 16,
++ DEF_SRPT_SQ_SIZE = 4096,
++ SRPT_RQ_SIZE = 128,
++ MIN_SRPT_SRQ_SIZE = 4,
++ DEFAULT_SRPT_SRQ_SIZE = 4095,
++ MAX_SRPT_SRQ_SIZE = 65535,
++
++ MIN_MAX_REQ_SIZE = 996,
++ DEFAULT_MAX_REQ_SIZE
++ = sizeof(struct srp_cmd)/*48*/
++ + sizeof(struct srp_indirect_buf)/*20*/
++ + 128 * sizeof(struct srp_direct_buf)/*16*/,
++
++ MIN_MAX_RSP_SIZE = sizeof(struct srp_rsp)/*36*/ + 4,
++ DEFAULT_MAX_RSP_SIZE = 256, /* leaves 220 bytes for sense data */
++
++ DEFAULT_MAX_RDMA_SIZE = 65536,
++};
++
++static inline u64 encode_wr_id(u8 opcode, u32 idx)
++{ return ((u64)opcode << 32) | idx; }
++static inline u8 opcode_from_wr_id(u64 wr_id)
++{ return wr_id >> 32; }
++static inline u32 idx_from_wr_id(u64 wr_id)
++{ return (u32)wr_id; }
++
++struct rdma_iu {
++ u64 raddr;
++ u32 rkey;
++ struct ib_sge *sge;
++ u32 sge_cnt;
++ int mem_id;
++};
++
++/**
++ * enum srpt_command_state - SCSI command state managed by SRPT.
++ * @SRPT_STATE_NEW: New command arrived and is being processed.
++ * @SRPT_STATE_NEED_DATA: Processing a write or bidir command and waiting
++ * for data arrival.
++ * @SRPT_STATE_DATA_IN: Data for the write or bidir command arrived and is
++ * being processed.
++ * @SRPT_STATE_CMD_RSP_SENT: SRP_RSP for SRP_CMD has been sent.
++ * @SRPT_STATE_MGMT_RSP_SENT: SRP_RSP for SRP_TSK_MGMT has been sent.
++ * @SRPT_STATE_DONE: Command processing finished successfully, command
++ * processing has been aborted or command processing
++ * failed.
++ */
++enum srpt_command_state {
++ SRPT_STATE_NEW = 0,
++ SRPT_STATE_NEED_DATA = 1,
++ SRPT_STATE_DATA_IN = 2,
++ SRPT_STATE_CMD_RSP_SENT = 3,
++ SRPT_STATE_MGMT_RSP_SENT = 4,
++ SRPT_STATE_DONE = 5,
++};
++
++/**
++ * struct srpt_ioctx - Shared SRPT I/O context information.
++ * @buf: Pointer to the buffer.
++ * @dma: DMA address of the buffer.
++ * @index: Index of the I/O context in its ioctx_ring array.
++ */
++struct srpt_ioctx {
++ void *buf;
++ dma_addr_t dma;
++ uint32_t index;
++};
++
++/**
++ * struct srpt_recv_ioctx - SRPT receive I/O context.
++ * @ioctx: See above.
++ * @wait_list: Node for insertion in srpt_rdma_ch.cmd_wait_list.
++ */
++struct srpt_recv_ioctx {
++ struct srpt_ioctx ioctx;
++ struct list_head wait_list;
++};
++
++/**
++ * struct srpt_send_ioctx - SRPT send I/O context.
++ * @ioctx: See above.
++ * @free_list: Allows to make this struct an entry in srpt_rdma_ch.free_list.
++ * @state: I/O context state. See also enum srpt_command_state.
++ */
++struct srpt_send_ioctx {
++ struct srpt_ioctx ioctx;
++ struct srpt_rdma_ch *ch;
++ struct rdma_iu *rdma_ius;
++ struct srp_direct_buf *rbufs;
++ struct srp_direct_buf single_rbuf;
++ struct scatterlist *sg;
++ struct list_head free_list;
++ int sg_cnt;
++ int mapped_sg_count;
++ u16 n_rdma_ius;
++ u8 n_rdma;
++ u8 n_rbuf;
++
++ struct scst_cmd *scmnd;
++ scst_data_direction dir;
++ atomic_t state;
++};
++
++/**
++ * struct srpt_mgmt_ioctx - SCST management command context information.
++ * @ioctx: SRPT I/O context associated with the management command.
++ * @tag: SCSI tag of the management command.
++ */
++struct srpt_mgmt_ioctx {
++ struct srpt_send_ioctx *ioctx;
++ u64 tag;
++};
++
++/**
++ * enum rdma_ch_state - SRP channel state.
++ */
++enum rdma_ch_state {
++ RDMA_CHANNEL_CONNECTING,
++ RDMA_CHANNEL_LIVE,
++ RDMA_CHANNEL_DISCONNECTING
++};
++
++/**
++ * struct srpt_rdma_ch - RDMA channel.
++ * @wait_queue: Allows the kernel thread to wait for more work.
++ * @thread: Kernel thread that processes the IB queues associated with
++ * the channel.
++ * @cm_id: IB CM ID associated with the channel.
++ * @rq_size: IB receive queue size.
++ * @processing_compl: whether or not an IB completion is being processed.
++ * @qp: IB queue pair used for communicating over this channel.
++ * @sq_wr_avail: number of work requests available in the send queue.
++ * @cq: IB completion queue for this channel.
++ * @sport: pointer to the information of the HCA port used by this
++ * channel.
++ * @i_port_id: 128-bit initiator port identifier copied from SRP_LOGIN_REQ.
++ * @t_port_id: 128-bit target port identifier copied from SRP_LOGIN_REQ.
++ * @max_ti_iu_len: maximum target-to-initiator information unit length.
++ * @supports_cred_req: whether or not the initiator supports SRP_CRED_REQ.
++ * @req_lim: request limit: maximum number of requests that may be sent
++ * by the initiator without having received a response.
++ * @state: channel state. See also enum rdma_ch_state.
++ * @list: node for insertion in the srpt_device.rch_list list.
++ * @cmd_wait_list: list of SCST commands that arrived before the RTU event. This
++ * list contains struct srpt_ioctx elements and is protected
++ * against concurrent modification by the cm_id spinlock.
++ * @spinlock: Protects free_list.
++ * @free_list: Head of list with free send I/O contexts.
++ * @scst_sess: SCST session information associated with this SRP channel.
++ * @sess_name: SCST session name.
++ */
++struct srpt_rdma_ch {
++ wait_queue_head_t wait_queue;
++ struct task_struct *thread;
++ struct ib_cm_id *cm_id;
++ struct ib_qp *qp;
++ int rq_size;
++ atomic_t processing_compl;
++ struct ib_cq *cq;
++ atomic_t sq_wr_avail;
++ struct srpt_port *sport;
++ u8 i_port_id[16];
++ u8 t_port_id[16];
++ int max_ti_iu_len;
++ atomic_t req_lim;
++ atomic_t req_lim_delta;
++ spinlock_t spinlock;
++ struct list_head free_list;
++ struct srpt_send_ioctx **ioctx_ring;
++ struct ib_wc wc[16];
++ atomic_t state;
++ struct list_head list;
++ struct list_head cmd_wait_list;
++
++ struct scst_session *scst_sess;
++ u8 sess_name[36];
++};
++
++/**
++ * struct srpt_port - Information associated by SRPT with a single IB port.
++ * @sdev: backpointer to the HCA information.
++ * @mad_agent: per-port management datagram processing information.
++ * @port: one-based port number.
++ * @sm_lid: cached value of the port's sm_lid.
++ * @lid: cached value of the port's lid.
++ * @gid: cached value of the port's gid.
++ * @work: work structure for refreshing the aforementioned cached values.
++ */
++struct srpt_port {
++ struct srpt_device *sdev;
++ struct ib_mad_agent *mad_agent;
++ u8 port;
++ u16 sm_lid;
++ u16 lid;
++ union ib_gid gid;
++ struct work_struct work;
++};
++
++/**
++ * struct srpt_device - Information associated by SRPT with a single HCA.
++ * @device: backpointer to the struct ib_device managed by the IB core.
++ * @pd: IB protection domain.
++ * @mr: L_Key (local key) with write access to all local memory.
++ * @srq: Per-HCA SRQ (shared receive queue).
++ * @cm_id: connection identifier.
++ * @dev_attr: attributes of the InfiniBand device as obtained during the
++ * ib_client.add() callback.
++ * @ioctx_ring: Per-HCA I/O context ring.
++ * @rch_list: per-device channel list -- see also srpt_rdma_ch.list.
++ * @spinlock: protects rch_list.
++ * @srpt_port: information about the ports owned by this HCA.
++ * @event_handler: per-HCA asynchronous IB event handler.
++ * @dev: per-port srpt-<portname> device instance.
++ * @scst_tgt: SCST target information associated with this HCA.
++ * @enabled: Whether or not this SCST target is enabled.
++ */
++struct srpt_device {
++ struct ib_device *device;
++ struct ib_pd *pd;
++ struct ib_mr *mr;
++ struct ib_srq *srq;
++ struct ib_cm_id *cm_id;
++ struct ib_device_attr dev_attr;
++ int srq_size;
++ struct srpt_recv_ioctx **ioctx_ring;
++ struct list_head rch_list;
++ spinlock_t spinlock;
++ struct srpt_port port[2];
++ struct ib_event_handler event_handler;
++ struct device dev;
++ struct scst_tgt *scst_tgt;
++ bool enabled;
++};
++
++#endif /* IB_SRPT_H */
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ * indent-tabs-mode: t
++ * End:
++ */
+diff -uprN orig/linux-2.6.36/Documentation/scst/README.srpt linux-2.6.36/Documentation/scst/README.srpt
+--- orig/linux-2.6.36/Documentation/scst/README.srpt
++++ linux-2.6.36/Documentation/scst/README.srpt
+@@ -0,0 +1,109 @@
++SCSI RDMA Protocol (SRP) Target driver for Linux
++=================================================
++
++The SRP Target driver is designed to work directly on top of the
++OpenFabrics OFED-1.x software stack (http://www.openfabrics.org) or
++the Infiniband drivers in the Linux kernel tree
++(http://www.kernel.org). The SRP target driver also interfaces with
++the generic SCSI target mid-level driver called SCST
++(http://scst.sourceforge.net).
++
++How-to run
++-----------
++
++A. On srp target machine
++1. Please refer to SCST's README for loading scst driver and its
++dev_handlers drivers (scst_disk, scst_vdisk block or file IO mode, nullio, ...)
++
++Example 1: working with real back-end scsi disks
++a. modprobe scst
++b. modprobe scst_disk
++c. cat /proc/scsi_tgt/scsi_tgt
++
++ibstor00:~ # cat /proc/scsi_tgt/scsi_tgt
++Device (host:ch:id:lun or name) Device handler
++0:0:0:0 dev_disk
++4:0:0:0 dev_disk
++5:0:0:0 dev_disk
++6:0:0:0 dev_disk
++7:0:0:0 dev_disk
++
++Now you want to exclude the first scsi disk and expose the last 4 scsi disks as
++IB/SRP luns for I/O
++echo "add 4:0:0:0 0" >/proc/scsi_tgt/groups/Default/devices
++echo "add 5:0:0:0 1" >/proc/scsi_tgt/groups/Default/devices
++echo "add 6:0:0:0 2" >/proc/scsi_tgt/groups/Default/devices
++echo "add 7:0:0:0 3" >/proc/scsi_tgt/groups/Default/devices
++
++Example 2: working with VDISK FILEIO mode (using md0 device and file 10G-file)
++a. modprobe scst
++b. modprobe scst_vdisk
++c. echo "open vdisk0 /dev/md0" > /proc/scsi_tgt/vdisk/vdisk
++d. echo "open vdisk1 /10G-file" > /proc/scsi_tgt/vdisk/vdisk
++e. echo "add vdisk0 0" >/proc/scsi_tgt/groups/Default/devices
++f. echo "add vdisk1 1" >/proc/scsi_tgt/groups/Default/devices
++
++Example 3: working with VDISK BLOCKIO mode (using md0 device, sda, and cciss/c1d0)
++a. modprobe scst
++b. modprobe scst_vdisk
++c. echo "open vdisk0 /dev/md0 BLOCKIO" > /proc/scsi_tgt/vdisk/vdisk
++d. echo "open vdisk1 /dev/sda BLOCKIO" > /proc/scsi_tgt/vdisk/vdisk
++e. echo "open vdisk2 /dev/cciss/c1d0 BLOCKIO" > /proc/scsi_tgt/vdisk/vdisk
++f. echo "add vdisk0 0" >/proc/scsi_tgt/groups/Default/devices
++g. echo "add vdisk1 1" >/proc/scsi_tgt/groups/Default/devices
++h. echo "add vdisk2 2" >/proc/scsi_tgt/groups/Default/devices
++
++2. modprobe ib_srpt
++
++B. On initiator machines you can manualy do the following steps:
++1. modprobe ib_srp
++2. ibsrpdm -c (to discover new SRP target)
++3. echo <new target info> > /sys/class/infiniband_srp/srp-mthca0-1/add_target
++4. fdisk -l (will show new discovered scsi disks)
++
++Example:
++Assume that you use port 1 of first HCA in the system ie. mthca0
++
++[root@lab104 ~]# ibsrpdm -c -d /dev/infiniband/umad0
++id_ext=0002c90200226cf4,ioc_guid=0002c90200226cf4,
++dgid=fe800000000000000002c90200226cf5,pkey=ffff,service_id=0002c90200226cf4
++[root@lab104 ~]# echo id_ext=0002c90200226cf4,ioc_guid=0002c90200226cf4,
++dgid=fe800000000000000002c90200226cf5,pkey=ffff,service_id=0002c90200226cf4 >
++/sys/class/infiniband_srp/srp-mthca0-1/add_target
++
++OR
++
+++ You can edit /etc/infiniband/openib.conf to load srp driver and srp HA daemon
++automatically ie. set SRP_LOAD=yes, and SRPHA_ENABLE=yes
+++ To set up and use high availability feature you need dm-multipath driver
++and multipath tool
+++ Please refer to OFED-1.x SRP's user manual for more in-details instructions
++on how-to enable/use HA feature
++
++To minimize QUEUE_FULL conditions, you can apply scst_increase_max_tgt_cmds
++patch from SRPT package from http://sourceforge.net/project/showfiles.php?group_id=110471
++
++Performance notes
++-----------------
++
++In some cases, for instance working with SSD devices, which consume 100%
++of a single CPU load for data transfers in their internal threads, to
++maximize IOPS it can be needed to assign for those threads dedicated
++CPUs using Linux CPU affinity facilities. No IRQ processing should be
++done on those CPUs. Check that using /proc/interrupts. See taskset
++command and Documentation/IRQ-affinity.txt in your kernel's source tree
++for how to assign CPU affinity to tasks and IRQs.
++
++The reason for that is that processing of coming commands in SIRQ context
++can be done on the same CPUs as SSD devices' threads doing data
++transfers. As the result, those threads won't receive all the CPU power
++and perform worse.
++
++Alternatively to CPU affinity assignment, you can try to enable SRP
++target's internal thread. It will allows Linux CPU scheduler to better
++distribute load among available CPUs. To enable SRP target driver's
++internal thread you should load ib_srpt module with parameter
++"thread=1".
++
++Send questions about this driver to scst-devel@lists.sourceforge.net, CC:
++Vu Pham <vuhuong@mellanox.com> and Bart Van Assche <bart.vanassche@gmail.com>.
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_local/Kconfig linux-2.6.36/drivers/scst/scst_local/Kconfig
+--- orig/linux-2.6.36/drivers/scst/scst_local/Kconfig
++++ linux-2.6.36/drivers/scst/scst_local/Kconfig
+@@ -0,0 +1,22 @@
++config SCST_LOCAL
++ tristate "SCST Local driver"
++ depends on SCST && !HIGHMEM4G && !HIGHMEM64G
++ ---help---
++ This module provides a LLD SCSI driver that connects to
++ the SCST target mode subsystem in a loop-back manner.
++ It allows you to test target-mode device-handlers locally.
++ You will need the SCST subsystem as well.
++
++ If unsure whether you really want or need this, say N.
++
++config SCST_LOCAL_FORCE_DIRECT_PROCESSING
++ bool "Force local processing"
++ depends on SCST_LOCAL
++ help
++ This experimental option forces scst_local to make SCST process
++ SCSI commands in the same context, in which they was submitted.
++ Otherwise, they will be processed in SCST threads. Setting this
++ option to "Y" will give some performance increase, but might be
++ unsafe.
++
++ If unsure, say "N".
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_local/Makefile linux-2.6.36/drivers/scst/scst_local/Makefile
+--- orig/linux-2.6.36/drivers/scst/scst_local/Makefile
++++ linux-2.6.36/drivers/scst/scst_local/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_SCST_LOCAL) += scst_local.o
++
+diff -uprN orig/linux-2.6.36/drivers/scst/scst_local/scst_local.c linux-2.6.36/drivers/scst/scst_local/scst_local.c
+--- orig/linux-2.6.36/drivers/scst/scst_local/scst_local.c
++++ linux-2.6.36/drivers/scst/scst_local/scst_local.c
+@@ -0,0 +1,1563 @@
++/*
++ * Copyright (C) 2008 - 2010 Richard Sharpe
++ * Copyright (C) 1992 Eric Youngdale
++ * Copyright (C) 2008 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
++ *
++ * Simulate a host adapter and an SCST target adapter back to back
++ *
++ * Based on the scsi_debug.c driver originally by Eric Youngdale and
++ * others, including D Gilbert et al
++ *
++ */
++
++#include <linux/module.h>
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/moduleparam.h>
++#include <linux/scatterlist.h>
++#include <linux/slab.h>
++#include <linux/completion.h>
++#include <linux/spinlock.h>
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_host.h>
++#include <scsi/scsi_tcq.h>
++
++#define LOG_PREFIX "scst_local"
++
++/* SCST includes ... */
++#include <scst/scst_const.h>
++#include <scst/scst.h>
++#include <scst/scst_debug.h>
++
++#ifdef CONFIG_SCST_DEBUG
++#define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_PID | \
++ TRACE_LINE | TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_DEBUG | \
++ TRACE_MINOR | TRACE_SPECIAL)
++#else
++# ifdef CONFIG_SCST_TRACING
++#define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
++ TRACE_SPECIAL)
++# endif
++#endif
++
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++#define trace_flag scst_local_trace_flag
++static unsigned long scst_local_trace_flag = SCST_LOCAL_DEFAULT_LOG_FLAGS;
++#endif
++
++#define TRUE 1
++#define FALSE 0
++
++#define SCST_LOCAL_VERSION "1.0.0"
++static const char *scst_local_version_date = "20100910";
++
++/* Some statistics */
++static atomic_t num_aborts = ATOMIC_INIT(0);
++static atomic_t num_dev_resets = ATOMIC_INIT(0);
++static atomic_t num_target_resets = ATOMIC_INIT(0);
++
++static bool scst_local_add_default_tgt = true;
++module_param_named(add_default_tgt, scst_local_add_default_tgt, bool, S_IRUGO);
++MODULE_PARM_DESC(add_default_tgt, "add (default) or not on start default "
++ "target scst_local_tgt with default session scst_local_host");
++
++struct scst_aen_work_item {
++ struct list_head work_list_entry;
++ struct scst_aen *aen;
++};
++
++struct scst_local_tgt {
++ struct scst_tgt *scst_tgt;
++ struct list_head sessions_list; /* protected by scst_local_mutex */
++ struct list_head tgts_list_entry;
++
++ /* SCSI version descriptors */
++ uint16_t scsi_transport_version;
++ uint16_t phys_transport_version;
++};
++
++struct scst_local_sess {
++ struct scst_session *scst_sess;
++
++ unsigned int unregistering:1;
++
++ struct device dev;
++ struct Scsi_Host *shost;
++ struct scst_local_tgt *tgt;
++
++ int number;
++
++ struct mutex tr_id_mutex;
++ uint8_t *transport_id;
++ int transport_id_len;
++
++ struct work_struct aen_work;
++ spinlock_t aen_lock;
++ struct list_head aen_work_list; /* protected by aen_lock */
++
++ struct list_head sessions_list_entry;
++};
++
++#define to_scst_lcl_sess(d) \
++ container_of(d, struct scst_local_sess, dev)
++
++static int __scst_local_add_adapter(struct scst_local_tgt *tgt,
++ const char *initiator_name, struct scst_local_sess **out_sess,
++ bool locked);
++static int scst_local_add_adapter(struct scst_local_tgt *tgt,
++ const char *initiator_name, struct scst_local_sess **out_sess);
++static void scst_local_remove_adapter(struct scst_local_sess *sess);
++static int scst_local_add_target(const char *target_name,
++ struct scst_local_tgt **out_tgt);
++static void __scst_local_remove_target(struct scst_local_tgt *tgt);
++static void scst_local_remove_target(struct scst_local_tgt *tgt);
++
++static atomic_t scst_local_sess_num = ATOMIC_INIT(0);
++
++static LIST_HEAD(scst_local_tgts_list);
++static DEFINE_MUTEX(scst_local_mutex);
++
++static DECLARE_RWSEM(scst_local_exit_rwsem);
++
++MODULE_AUTHOR("Richard Sharpe, Vladislav Bolkhovitin + ideas from SCSI_DEBUG");
++MODULE_DESCRIPTION("SCSI+SCST local adapter driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(SCST_LOCAL_VERSION);
++
++static int scst_local_get_sas_transport_id(struct scst_local_sess *sess,
++ uint8_t **transport_id, int *len)
++{
++ int res = 0;
++ int tr_id_size = 0;
++ uint8_t *tr_id = NULL;
++
++ TRACE_ENTRY();
++
++ tr_id_size = 24; /* A SAS TransportID */
++
++ tr_id = kzalloc(tr_id_size, GFP_KERNEL);
++ if (tr_id == NULL) {
++ PRINT_ERROR("Allocation of TransportID (size %d) failed",
++ tr_id_size);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ tr_id[0] = 0x00 | SCSI_TRANSPORTID_PROTOCOLID_SAS;
++
++ /*
++ * Assemble a valid SAS address = 0x5OOUUIIR12345678 ... Does SCST
++ * have one?
++ */
++
++ tr_id[4] = 0x5F;
++ tr_id[5] = 0xEE;
++ tr_id[6] = 0xDE;
++ tr_id[7] = 0x40 | ((sess->number >> 4) & 0x0F);
++ tr_id[8] = 0x0F | (sess->number & 0xF0);
++ tr_id[9] = 0xAD;
++ tr_id[10] = 0xE0;
++ tr_id[11] = 0x50;
++
++ *transport_id = tr_id;
++ *len = tr_id_size;
++
++ TRACE_DBG("Created tid '%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'",
++ tr_id[4], tr_id[5], tr_id[6], tr_id[7],
++ tr_id[8], tr_id[9], tr_id[10], tr_id[11]);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_local_get_initiator_port_transport_id(
++ struct scst_session *scst_sess, uint8_t **transport_id)
++{
++ int res = 0;
++ int tr_id_size = 0;
++ uint8_t *tr_id = NULL;
++ struct scst_local_sess *sess;
++
++ TRACE_ENTRY();
++
++ if (scst_sess == NULL) {
++ res = SCSI_TRANSPORTID_PROTOCOLID_SAS;
++ goto out;
++ }
++
++ sess = (struct scst_local_sess *)scst_sess_get_tgt_priv(scst_sess);
++
++ mutex_lock(&sess->tr_id_mutex);
++
++ if (sess->transport_id == NULL) {
++ res = scst_local_get_sas_transport_id(sess,
++ transport_id, &tr_id_size);
++ goto out_unlock;
++ }
++
++ tr_id_size = sess->transport_id_len;
++ BUG_ON(tr_id_size == 0);
++
++ tr_id = kzalloc(tr_id_size, GFP_KERNEL);
++ if (tr_id == NULL) {
++ PRINT_ERROR("Allocation of TransportID (size %d) failed",
++ tr_id_size);
++ res = -ENOMEM;
++ goto out;
++ }
++
++ memcpy(tr_id, sess->transport_id, sess->transport_id_len);
++
++out_unlock:
++ mutex_unlock(&sess->tr_id_mutex);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/**
++ ** Tgtt attributes
++ **/
++
++static ssize_t scst_local_version_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ sprintf(buf, "%s/%s\n", SCST_LOCAL_VERSION, scst_local_version_date);
++
++#ifdef CONFIG_SCST_EXTRACHECKS
++ strcat(buf, "EXTRACHECKS\n");
++#endif
++
++#ifdef CONFIG_SCST_TRACING
++ strcat(buf, "TRACING\n");
++#endif
++
++#ifdef CONFIG_SCST_DEBUG
++ strcat(buf, "DEBUG\n");
++#endif
++
++ TRACE_EXIT();
++ return strlen(buf);
++}
++
++static struct kobj_attribute scst_local_version_attr =
++ __ATTR(version, S_IRUGO, scst_local_version_show, NULL);
++
++static ssize_t scst_local_stats_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++
++{
++ return sprintf(buf, "Aborts: %d, Device Resets: %d, Target Resets: %d",
++ atomic_read(&num_aborts), atomic_read(&num_dev_resets),
++ atomic_read(&num_target_resets));
++}
++
++static struct kobj_attribute scst_local_stats_attr =
++ __ATTR(stats, S_IRUGO, scst_local_stats_show, NULL);
++
++static const struct attribute *scst_local_tgtt_attrs[] = {
++ &scst_local_version_attr.attr,
++ &scst_local_stats_attr.attr,
++ NULL,
++};
++
++/**
++ ** Tgt attributes
++ **/
++
++static ssize_t scst_local_scsi_transport_version_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_tgt *scst_tgt;
++ struct scst_local_tgt *tgt;
++ ssize_t res;
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++
++ if (tgt->scsi_transport_version != 0)
++ res = sprintf(buf, "0x%x\n%s", tgt->scsi_transport_version,
++ SCST_SYSFS_KEY_MARK "\n");
++ else
++ res = sprintf(buf, "0x%x\n", 0x0BE0); /* SAS */
++
++ up_read(&scst_local_exit_rwsem);
++ return res;
++}
++
++static ssize_t scst_local_scsi_transport_version_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buffer, size_t size)
++{
++ ssize_t res;
++ struct scst_tgt *scst_tgt;
++ struct scst_local_tgt *tgt;
++ unsigned long val;
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++
++ res = strict_strtoul(buffer, 0, &val);
++ if (res != 0) {
++ PRINT_ERROR("strict_strtoul() for %s failed: %zd", buffer, res);
++ goto out_up;
++ }
++
++ tgt->scsi_transport_version = val;
++
++ res = size;
++
++out_up:
++ up_read(&scst_local_exit_rwsem);
++ return res;
++}
++
++static struct kobj_attribute scst_local_scsi_transport_version_attr =
++ __ATTR(scsi_transport_version, S_IRUGO | S_IWUSR,
++ scst_local_scsi_transport_version_show,
++ scst_local_scsi_transport_version_store);
++
++static ssize_t scst_local_phys_transport_version_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ struct scst_tgt *scst_tgt;
++ struct scst_local_tgt *tgt;
++ ssize_t res;
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++
++ res = sprintf(buf, "0x%x\n%s", tgt->phys_transport_version,
++ (tgt->phys_transport_version != 0) ?
++ SCST_SYSFS_KEY_MARK "\n" : "");
++
++ up_read(&scst_local_exit_rwsem);
++ return res;
++}
++
++static ssize_t scst_local_phys_transport_version_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buffer, size_t size)
++{
++ ssize_t res;
++ struct scst_tgt *scst_tgt;
++ struct scst_local_tgt *tgt;
++ unsigned long val;
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ scst_tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
++ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++
++ res = strict_strtoul(buffer, 0, &val);
++ if (res != 0) {
++ PRINT_ERROR("strict_strtoul() for %s failed: %zd", buffer, res);
++ goto out_up;
++ }
++
++ tgt->phys_transport_version = val;
++
++ res = size;
++
++out_up:
++ up_read(&scst_local_exit_rwsem);
++ return res;
++}
++
++static struct kobj_attribute scst_local_phys_transport_version_attr =
++ __ATTR(phys_transport_version, S_IRUGO | S_IWUSR,
++ scst_local_phys_transport_version_show,
++ scst_local_phys_transport_version_store);
++
++static const struct attribute *scst_local_tgt_attrs[] = {
++ &scst_local_scsi_transport_version_attr.attr,
++ &scst_local_phys_transport_version_attr.attr,
++ NULL,
++};
++
++/**
++ ** Session attributes
++ **/
++
++static ssize_t scst_local_transport_id_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ ssize_t res;
++ struct scst_session *scst_sess;
++ struct scst_local_sess *sess;
++ uint8_t *tr_id;
++ int tr_id_len, i;
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
++ sess = (struct scst_local_sess *)scst_sess_get_tgt_priv(scst_sess);
++
++ mutex_lock(&sess->tr_id_mutex);
++
++ if (sess->transport_id != NULL) {
++ tr_id = sess->transport_id;
++ tr_id_len = sess->transport_id_len;
++ } else {
++ res = scst_local_get_sas_transport_id(sess, &tr_id, &tr_id_len);
++ if (res != 0)
++ goto out_unlock;
++ }
++
++ res = 0;
++ for (i = 0; i < tr_id_len; i++)
++ res += sprintf(&buf[res], "%c", tr_id[i]);
++
++ if (sess->transport_id == NULL)
++ kfree(tr_id);
++
++out_unlock:
++ mutex_unlock(&sess->tr_id_mutex);
++ up_read(&scst_local_exit_rwsem);
++ return res;
++}
++
++static ssize_t scst_local_transport_id_store(struct kobject *kobj,
++ struct kobj_attribute *attr, const char *buffer, size_t size)
++{
++ ssize_t res;
++ struct scst_session *scst_sess;
++ struct scst_local_sess *sess;
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ scst_sess = container_of(kobj, struct scst_session, sess_kobj);
++ sess = (struct scst_local_sess *)scst_sess_get_tgt_priv(scst_sess);
++
++ mutex_lock(&sess->tr_id_mutex);
++
++ if (sess->transport_id != NULL) {
++ kfree(sess->transport_id);
++ sess->transport_id = NULL;
++ sess->transport_id_len = 0;
++ }
++
++ if (size == 0)
++ goto out_res;
++
++ sess->transport_id = kzalloc(size, GFP_KERNEL);
++ if (sess->transport_id == NULL) {
++ PRINT_ERROR("Allocation of transport_id (size %zd) failed",
++ size);
++ res = -ENOMEM;
++ goto out_unlock;
++ }
++
++ sess->transport_id_len = size;
++
++ memcpy(sess->transport_id, buffer, sess->transport_id_len);
++
++out_res:
++ res = size;
++
++out_unlock:
++ mutex_unlock(&sess->tr_id_mutex);
++ up_read(&scst_local_exit_rwsem);
++ return res;
++}
++
++static struct kobj_attribute scst_local_transport_id_attr =
++ __ATTR(transport_id, S_IRUGO | S_IWUSR,
++ scst_local_transport_id_show,
++ scst_local_transport_id_store);
++
++static const struct attribute *scst_local_sess_attrs[] = {
++ &scst_local_transport_id_attr.attr,
++ NULL,
++};
++
++static ssize_t scst_local_sysfs_add_target(const char *target_name, char *params)
++{
++ int res;
++ struct scst_local_tgt *tgt;
++ char *param, *p;
++
++ TRACE_ENTRY();
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ res = scst_local_add_target(target_name, &tgt);
++ if (res != 0)
++ goto out_up;
++
++ while (1) {
++ param = scst_get_next_token_str(&params);
++ if (param == NULL)
++ break;
++
++ p = scst_get_next_lexem(&param);
++ if (*p == '\0')
++ break;
++
++ if (strcasecmp("session_name", p) != 0) {
++ PRINT_ERROR("Unknown parameter %s", p);
++ res = -EINVAL;
++ goto out_remove;
++ }
++
++ p = scst_get_next_lexem(&param);
++ if (*p == '\0') {
++ PRINT_ERROR("Wrong session name %s", p);
++ res = -EINVAL;
++ goto out_remove;
++ }
++
++ res = scst_local_add_adapter(tgt, p, NULL);
++ if (res != 0)
++ goto out_remove;
++ }
++
++out_up:
++ up_read(&scst_local_exit_rwsem);
++
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_remove:
++ scst_local_remove_target(tgt);
++ goto out_up;
++}
++
++static ssize_t scst_local_sysfs_del_target(const char *target_name)
++{
++ int res;
++ struct scst_local_tgt *tgt;
++ bool deleted = false;
++
++ TRACE_ENTRY();
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ mutex_lock(&scst_local_mutex);
++ list_for_each_entry(tgt, &scst_local_tgts_list, tgts_list_entry) {
++ if (strcmp(target_name, tgt->scst_tgt->tgt_name) == 0) {
++ __scst_local_remove_target(tgt);
++ deleted = true;
++ break;
++ }
++ }
++ mutex_unlock(&scst_local_mutex);
++
++ if (!deleted) {
++ PRINT_ERROR("Target %s not found", target_name);
++ res = -ENOENT;
++ goto out_up;
++ }
++
++ res = 0;
++
++out_up:
++ up_read(&scst_local_exit_rwsem);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static ssize_t scst_local_sysfs_mgmt_cmd(char *buf)
++{
++ ssize_t res;
++ char *command, *target_name, *session_name;
++ struct scst_local_tgt *t, *tgt;
++
++ TRACE_ENTRY();
++
++ if (down_read_trylock(&scst_local_exit_rwsem) == 0)
++ return -ENOENT;
++
++ command = scst_get_next_lexem(&buf);
++
++ target_name = scst_get_next_lexem(&buf);
++ if (*target_name == '\0') {
++ PRINT_ERROR("%s", "Target name required");
++ res = -EINVAL;
++ goto out_up;
++ }
++
++ mutex_lock(&scst_local_mutex);
++
++ tgt = NULL;
++ list_for_each_entry(t, &scst_local_tgts_list, tgts_list_entry) {
++ if (strcmp(t->scst_tgt->tgt_name, target_name) == 0) {
++ tgt = t;
++ break;
++ }
++ }
++ if (tgt == NULL) {
++ PRINT_ERROR("Target %s not found", target_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ session_name = scst_get_next_lexem(&buf);
++ if (*session_name == '\0') {
++ PRINT_ERROR("%s", "Session name required");
++ res = -EINVAL;
++ goto out_unlock;
++ }
++
++ if (strcasecmp("add_session", command) == 0) {
++ res = __scst_local_add_adapter(tgt, session_name, NULL, true);
++ } else if (strcasecmp("del_session", command) == 0) {
++ struct scst_local_sess *s, *sess = NULL;
++ list_for_each_entry(s, &tgt->sessions_list,
++ sessions_list_entry) {
++ if (strcmp(s->scst_sess->initiator_name, session_name) == 0) {
++ sess = s;
++ break;
++ }
++ }
++ if (sess == NULL) {
++ PRINT_ERROR("Session %s not found (target %s)",
++ session_name, target_name);
++ res = -EINVAL;
++ goto out_unlock;
++ }
++ scst_local_remove_adapter(sess);
++ }
++
++ res = 0;
++
++out_unlock:
++ mutex_unlock(&scst_local_mutex);
++
++out_up:
++ up_read(&scst_local_exit_rwsem);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_local_abort(struct scsi_cmnd *SCpnt)
++{
++ struct scst_local_sess *sess;
++ int ret;
++ DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
++
++ TRACE_ENTRY();
++
++ sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host));
++
++ ret = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, SCpnt->tag,
++ FALSE, &dev_reset_completion);
++
++ /* Now wait for the completion ... */
++ wait_for_completion_interruptible(&dev_reset_completion);
++
++ atomic_inc(&num_aborts);
++
++ if (ret == 0)
++ ret = SUCCESS;
++
++ TRACE_EXIT_RES(ret);
++ return ret;
++}
++
++static int scst_local_device_reset(struct scsi_cmnd *SCpnt)
++{
++ struct scst_local_sess *sess;
++ uint16_t lun;
++ int ret;
++ DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
++
++ TRACE_ENTRY();
++
++ sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host));
++
++ lun = SCpnt->device->lun;
++ lun = cpu_to_be16(lun);
++
++ ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET,
++ (const uint8_t *)&lun, sizeof(lun), FALSE,
++ &dev_reset_completion);
++
++ /* Now wait for the completion ... */
++ wait_for_completion_interruptible(&dev_reset_completion);
++
++ atomic_inc(&num_dev_resets);
++
++ if (ret == 0)
++ ret = SUCCESS;
++
++ TRACE_EXIT_RES(ret);
++ return ret;
++}
++
++static int scst_local_target_reset(struct scsi_cmnd *SCpnt)
++{
++ struct scst_local_sess *sess;
++ uint16_t lun;
++ int ret;
++ DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
++
++ TRACE_ENTRY();
++
++ sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host));
++
++ lun = SCpnt->device->lun;
++ lun = cpu_to_be16(lun);
++
++ ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_TARGET_RESET,
++ (const uint8_t *)&lun, sizeof(lun), FALSE,
++ &dev_reset_completion);
++
++ /* Now wait for the completion ... */
++ wait_for_completion_interruptible(&dev_reset_completion);
++
++ atomic_inc(&num_target_resets);
++
++ if (ret == 0)
++ ret = SUCCESS;
++
++ TRACE_EXIT_RES(ret);
++ return ret;
++}
++
++static void copy_sense(struct scsi_cmnd *cmnd, struct scst_cmd *scst_cmnd)
++{
++ int scst_cmnd_sense_len = scst_cmd_get_sense_buffer_len(scst_cmnd);
++
++ TRACE_ENTRY();
++
++ scst_cmnd_sense_len = (SCSI_SENSE_BUFFERSIZE < scst_cmnd_sense_len ?
++ SCSI_SENSE_BUFFERSIZE : scst_cmnd_sense_len);
++ memcpy(cmnd->sense_buffer, scst_cmd_get_sense_buffer(scst_cmnd),
++ scst_cmnd_sense_len);
++
++ TRACE_BUFFER("Sense set", cmnd->sense_buffer, scst_cmnd_sense_len);
++
++ TRACE_EXIT();
++ return;
++}
++
++/*
++ * Utility function to handle processing of done and allow
++ * easy insertion of error injection if desired
++ */
++static int scst_local_send_resp(struct scsi_cmnd *cmnd,
++ struct scst_cmd *scst_cmnd,
++ void (*done)(struct scsi_cmnd *),
++ int scsi_result)
++{
++ int ret = 0;
++
++ TRACE_ENTRY();
++
++ if (scst_cmnd) {
++ /* The buffer isn't ours, so let's be safe and restore it */
++ scst_check_restore_sg_buff(scst_cmnd);
++
++ /* Simulate autosense by this driver */
++ if (unlikely(SCST_SENSE_VALID(scst_cmnd->sense)))
++ copy_sense(cmnd, scst_cmnd);
++ }
++
++ cmnd->result = scsi_result;
++
++ done(cmnd);
++
++ TRACE_EXIT_RES(ret);
++ return ret;
++}
++
++/*
++ * This does the heavy lifting ... we pass all the commands on to the
++ * target driver and have it do its magic ...
++ */
++static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
++ void (*done)(struct scsi_cmnd *))
++ __acquires(&h->host_lock)
++ __releases(&h->host_lock)
++{
++ struct scst_local_sess *sess;
++ struct scatterlist *sgl = NULL;
++ int sgl_count = 0;
++ uint16_t lun;
++ struct scst_cmd *scst_cmd = NULL;
++ scst_data_direction dir;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("lun %d, cmd: 0x%02X", SCpnt->device->lun, SCpnt->cmnd[0]);
++
++ sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host));
++
++ scsi_set_resid(SCpnt, 0);
++
++ /*
++ * We save a pointer to the done routine in SCpnt->scsi_done and
++ * we save that as tgt specific stuff below.
++ */
++ SCpnt->scsi_done = done;
++
++ /*
++ * Tell the target that we have a command ... but first we need
++ * to get the LUN into a format that SCST understand
++ */
++ lun = SCpnt->device->lun;
++ lun = cpu_to_be16(lun);
++ scst_cmd = scst_rx_cmd(sess->scst_sess, (const uint8_t *)&lun,
++ sizeof(lun), SCpnt->cmnd, SCpnt->cmd_len, TRUE);
++ if (!scst_cmd) {
++ PRINT_ERROR("%s", "scst_rx_cmd() failed");
++ return -ENOMEM;
++ }
++
++ scst_cmd_set_tag(scst_cmd, SCpnt->tag);
++ switch (scsi_get_tag_type(SCpnt->device)) {
++ case MSG_SIMPLE_TAG:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_SIMPLE);
++ break;
++ case MSG_HEAD_TAG:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
++ break;
++ case MSG_ORDERED_TAG:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_ORDERED);
++ break;
++ case SCSI_NO_TAG:
++ default:
++ scst_cmd_set_queue_type(scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
++ break;
++ }
++
++ sgl = scsi_sglist(SCpnt);
++ sgl_count = scsi_sg_count(SCpnt);
++
++ dir = SCST_DATA_NONE;
++ switch (SCpnt->sc_data_direction) {
++ case DMA_TO_DEVICE:
++ dir = SCST_DATA_WRITE;
++ scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
++ scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count);
++ break;
++ case DMA_FROM_DEVICE:
++ dir = SCST_DATA_READ;
++ scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
++ scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count);
++ break;
++ case DMA_BIDIRECTIONAL:
++ /* Some of these symbols are only defined after 2.6.24 */
++ dir = SCST_DATA_BIDI;
++ scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
++ scst_cmd_set_expected_out_transfer_len(scst_cmd,
++ scsi_in(SCpnt)->length);
++ scst_cmd_set_tgt_sg(scst_cmd, scsi_in(SCpnt)->table.sgl,
++ scsi_in(SCpnt)->table.nents);
++ scst_cmd_set_tgt_out_sg(scst_cmd, sgl, sgl_count);
++ break;
++ case DMA_NONE:
++ default:
++ dir = SCST_DATA_NONE;
++ scst_cmd_set_expected(scst_cmd, dir, 0);
++ break;
++ }
++
++ /* Save the correct thing below depending on version */
++ scst_cmd_set_tgt_priv(scst_cmd, SCpnt);
++
++#ifdef CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING
++ {
++ struct Scsi_Host *h = SCpnt->device->host;
++ spin_unlock_irq(h->host_lock);
++ scst_cmd_init_done(scst_cmd, scst_estimate_context_direct());
++ spin_lock_irq(h->host_lock);
++ }
++#else
++ /*
++ * Unfortunately, we called with IRQs disabled, so have no choice,
++ * except to pass to the thread context.
++ */
++ scst_cmd_init_done(scst_cmd, SCST_CONTEXT_THREAD);
++#endif
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static int scst_local_targ_pre_exec(struct scst_cmd *scst_cmd)
++{
++ int res = SCST_PREPROCESS_STATUS_SUCCESS;
++
++ TRACE_ENTRY();
++
++ if (scst_cmd_get_dh_data_buff_alloced(scst_cmd) &&
++ (scst_cmd_get_data_direction(scst_cmd) & SCST_DATA_WRITE))
++ scst_copy_sg(scst_cmd, SCST_SG_COPY_FROM_TARGET);
++
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++/* Must be called under sess->aen_lock. Drops then reacquires it inside. */
++static void scst_process_aens(struct scst_local_sess *sess,
++ bool cleanup_only)
++{
++ struct scst_aen_work_item *work_item = NULL;
++
++ TRACE_ENTRY();
++
++ TRACE_DBG("Target work sess %p", sess);
++
++ while (!list_empty(&sess->aen_work_list)) {
++ work_item = list_entry(sess->aen_work_list.next,
++ struct scst_aen_work_item, work_list_entry);
++ list_del(&work_item->work_list_entry);
++
++ spin_unlock(&sess->aen_lock);
++
++ if (cleanup_only)
++ goto done;
++
++ BUG_ON(work_item->aen->event_fn != SCST_AEN_SCSI);
++
++ /* Let's always rescan */
++ scsi_scan_target(&sess->shost->shost_gendev, 0, 0,
++ SCAN_WILD_CARD, 1);
++
++done:
++ scst_aen_done(work_item->aen);
++ kfree(work_item);
++
++ spin_lock(&sess->aen_lock);
++ }
++
++ TRACE_EXIT();
++ return;
++}
++
++static void scst_aen_work_fn(struct work_struct *work)
++{
++ struct scst_local_sess *sess =
++ container_of(work, struct scst_local_sess, aen_work);
++
++ TRACE_ENTRY();
++
++ TRACE_MGMT_DBG("Target work %p)", sess);
++
++ spin_lock(&sess->aen_lock);
++ scst_process_aens(sess, false);
++ spin_unlock(&sess->aen_lock);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int scst_local_report_aen(struct scst_aen *aen)
++{
++ int res = 0;
++ int event_fn = scst_aen_get_event_fn(aen);
++ struct scst_local_sess *sess;
++ struct scst_aen_work_item *work_item = NULL;
++
++ TRACE_ENTRY();
++
++ sess = (struct scst_local_sess *)scst_sess_get_tgt_priv(
++ scst_aen_get_sess(aen));
++ switch (event_fn) {
++ case SCST_AEN_SCSI:
++ /*
++ * Allocate a work item and place it on the queue
++ */
++ work_item = kzalloc(sizeof(*work_item), GFP_KERNEL);
++ if (!work_item) {
++ PRINT_ERROR("%s", "Unable to allocate work item "
++ "to handle AEN!");
++ return -ENOMEM;
++ }
++
++ spin_lock(&sess->aen_lock);
++
++ if (unlikely(sess->unregistering)) {
++ spin_unlock(&sess->aen_lock);
++ kfree(work_item);
++ res = SCST_AEN_RES_NOT_SUPPORTED;
++ goto out;
++ }
++
++ list_add_tail(&work_item->work_list_entry, &sess->aen_work_list);
++ work_item->aen = aen;
++
++ spin_unlock(&sess->aen_lock);
++
++ schedule_work(&sess->aen_work);
++ break;
++
++ default:
++ TRACE_MGMT_DBG("Unsupported AEN %d", event_fn);
++ res = SCST_AEN_RES_NOT_SUPPORTED;
++ break;
++ }
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++}
++
++static int scst_local_targ_detect(struct scst_tgt_template *tgt_template)
++{
++ TRACE_ENTRY();
++
++ TRACE_EXIT();
++ return 0;
++};
++
++static int scst_local_targ_release(struct scst_tgt *tgt)
++{
++ TRACE_ENTRY();
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static int scst_local_targ_xmit_response(struct scst_cmd *scst_cmd)
++{
++ struct scsi_cmnd *SCpnt = NULL;
++ void (*done)(struct scsi_cmnd *);
++
++ TRACE_ENTRY();
++
++ if (unlikely(scst_cmd_aborted(scst_cmd))) {
++ scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED);
++ scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
++ return SCST_TGT_RES_SUCCESS;
++ }
++
++ if (scst_cmd_get_dh_data_buff_alloced(scst_cmd) &&
++ (scst_cmd_get_data_direction(scst_cmd) & SCST_DATA_READ))
++ scst_copy_sg(scst_cmd, SCST_SG_COPY_TO_TARGET);
++
++ SCpnt = scst_cmd_get_tgt_priv(scst_cmd);
++ done = SCpnt->scsi_done;
++
++ /*
++ * This might have to change to use the two status flags
++ */
++ if (scst_cmd_get_is_send_status(scst_cmd)) {
++ int resid = 0, out_resid = 0;
++
++ /* Calculate the residual ... */
++ if (likely(!scst_get_resid(scst_cmd, &resid, &out_resid))) {
++ TRACE_DBG("No residuals for request %p", SCpnt);
++ } else {
++ if (out_resid != 0)
++ PRINT_ERROR("Unable to return OUT residual %d "
++ "(op %02x)", out_resid, SCpnt->cmnd[0]);
++ }
++
++ scsi_set_resid(SCpnt, resid);
++
++ /*
++ * It seems like there is no way to set out_resid ...
++ */
++
++ (void)scst_local_send_resp(SCpnt, scst_cmd, done,
++ scst_cmd_get_status(scst_cmd));
++ }
++
++ /* Now tell SCST that the command is done ... */
++ scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
++
++ TRACE_EXIT();
++ return SCST_TGT_RES_SUCCESS;
++}
++
++static void scst_local_targ_task_mgmt_done(struct scst_mgmt_cmd *mgmt_cmd)
++{
++ struct completion *compl;
++
++ TRACE_ENTRY();
++
++ compl = (struct completion *)scst_mgmt_cmd_get_tgt_priv(mgmt_cmd);
++ if (compl)
++ complete(compl);
++
++ TRACE_EXIT();
++ return;
++}
++
++static uint16_t scst_local_get_scsi_transport_version(struct scst_tgt *scst_tgt)
++{
++ struct scst_local_tgt *tgt;
++
++ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++
++ if (tgt->scsi_transport_version == 0)
++ return 0x0BE0; /* SAS */
++ else
++ return tgt->scsi_transport_version;
++}
++
++static uint16_t scst_local_get_phys_transport_version(struct scst_tgt *scst_tgt)
++{
++ struct scst_local_tgt *tgt;
++
++ tgt = (struct scst_local_tgt *)scst_tgt_get_tgt_priv(scst_tgt);
++
++ return tgt->phys_transport_version;
++}
++
++static struct scst_tgt_template scst_local_targ_tmpl = {
++ .name = "scst_local",
++ .sg_tablesize = 0xffff,
++ .xmit_response_atomic = 1,
++ .enabled_attr_not_needed = 1,
++ .tgtt_attrs = scst_local_tgtt_attrs,
++ .tgt_attrs = scst_local_tgt_attrs,
++ .sess_attrs = scst_local_sess_attrs,
++ .add_target = scst_local_sysfs_add_target,
++ .del_target = scst_local_sysfs_del_target,
++ .mgmt_cmd = scst_local_sysfs_mgmt_cmd,
++ .add_target_parameters = "session_name",
++ .mgmt_cmd_help = " echo \"add_session target_name session_name\" >mgmt\n"
++ " echo \"del_session target_name session_name\" >mgmt\n",
++ .detect = scst_local_targ_detect,
++ .release = scst_local_targ_release,
++ .pre_exec = scst_local_targ_pre_exec,
++ .xmit_response = scst_local_targ_xmit_response,
++ .task_mgmt_fn_done = scst_local_targ_task_mgmt_done,
++ .report_aen = scst_local_report_aen,
++ .get_initiator_port_transport_id = scst_local_get_initiator_port_transport_id,
++ .get_scsi_transport_version = scst_local_get_scsi_transport_version,
++ .get_phys_transport_version = scst_local_get_phys_transport_version,
++#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
++ .default_trace_flags = SCST_LOCAL_DEFAULT_LOG_FLAGS,
++ .trace_flags = &trace_flag,
++#endif
++};
++
++static struct scsi_host_template scst_lcl_ini_driver_template = {
++ .name = SCST_LOCAL_NAME,
++ .queuecommand = scst_local_queuecommand,
++ .eh_abort_handler = scst_local_abort,
++ .eh_device_reset_handler = scst_local_device_reset,
++ .eh_target_reset_handler = scst_local_target_reset,
++ .can_queue = 256,
++ .this_id = -1,
++ /* SCST doesn't support sg chaining */
++ .sg_tablesize = SG_MAX_SINGLE_ALLOC,
++ .cmd_per_lun = 32,
++ .max_sectors = 0xffff,
++ /* SCST doesn't support sg chaining */
++ .use_clustering = ENABLE_CLUSTERING,
++ .skip_settle_delay = 1,
++ .module = THIS_MODULE,
++};
++
++/*
++ * LLD Bus and functions
++ */
++
++static int scst_local_driver_probe(struct device *dev)
++{
++ int ret;
++ struct scst_local_sess *sess;
++ struct Scsi_Host *hpnt;
++
++ TRACE_ENTRY();
++
++ sess = to_scst_lcl_sess(dev);
++
++ TRACE_DBG("sess %p", sess);
++
++ hpnt = scsi_host_alloc(&scst_lcl_ini_driver_template, sizeof(*sess));
++ if (NULL == hpnt) {
++ PRINT_ERROR("%s", "scsi_register() failed");
++ ret = -ENODEV;
++ goto out;
++ }
++
++ sess->shost = hpnt;
++
++ hpnt->max_id = 0; /* Don't want more than one id */
++ hpnt->max_lun = 0xFFFF;
++
++ /*
++ * Because of a change in the size of this field at 2.6.26
++ * we use this check ... it allows us to work on earlier
++ * kernels. If we don't, max_cmd_size gets set to 4 (and we get
++ * a compiler warning) so a scan never occurs.
++ */
++ hpnt->max_cmd_len = 260;
++
++ ret = scsi_add_host(hpnt, &sess->dev);
++ if (ret) {
++ PRINT_ERROR("%s", "scsi_add_host() failed");
++ ret = -ENODEV;
++ scsi_host_put(hpnt);
++ goto out;
++ }
++
++out:
++ TRACE_EXIT_RES(ret);
++ return ret;
++}
++
++static int scst_local_driver_remove(struct device *dev)
++{
++ struct scst_local_sess *sess;
++
++ TRACE_ENTRY();
++
++ sess = to_scst_lcl_sess(dev);
++ if (!sess) {
++ PRINT_ERROR("%s", "Unable to locate sess info");
++ return -ENODEV;
++ }
++
++ scsi_remove_host(sess->shost);
++ scsi_host_put(sess->shost);
++
++ TRACE_EXIT();
++ return 0;
++}
++
++static int scst_local_bus_match(struct device *dev,
++ struct device_driver *dev_driver)
++{
++ TRACE_ENTRY();
++
++ TRACE_EXIT();
++ return 1;
++}
++
++static struct bus_type scst_local_lld_bus = {
++ .name = "scst_local_bus",
++ .match = scst_local_bus_match,
++ .probe = scst_local_driver_probe,
++ .remove = scst_local_driver_remove,
++};
++
++static struct device_driver scst_local_driver = {
++ .name = SCST_LOCAL_NAME,
++ .bus = &scst_local_lld_bus,
++};
++
++static struct device *scst_local_root;
++
++static void scst_local_release_adapter(struct device *dev)
++{
++ struct scst_local_sess *sess;
++
++ TRACE_ENTRY();
++
++ sess = to_scst_lcl_sess(dev);
++ if (sess == NULL)
++ goto out;
++
++ spin_lock(&sess->aen_lock);
++ sess->unregistering = 1;
++ scst_process_aens(sess, true);
++ spin_unlock(&sess->aen_lock);
++
++ cancel_work_sync(&sess->aen_work);
++
++ scst_unregister_session(sess->scst_sess, TRUE, NULL);
++
++ kfree(sess);
++
++out:
++ TRACE_EXIT();
++ return;
++}
++
++static int __scst_local_add_adapter(struct scst_local_tgt *tgt,
++ const char *initiator_name, struct scst_local_sess **out_sess,
++ bool locked)
++{
++ int res;
++ struct scst_local_sess *sess;
++
++ TRACE_ENTRY();
++
++ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
++ if (NULL == sess) {
++ PRINT_ERROR("Unable to alloc scst_lcl_host (size %zu)",
++ sizeof(*sess));
++ res = -ENOMEM;
++ goto out;
++ }
++
++ sess->tgt = tgt;
++ sess->number = atomic_inc_return(&scst_local_sess_num);
++ mutex_init(&sess->tr_id_mutex);
++
++ /*
++ * Init this stuff we need for scheduling AEN work
++ */
++ INIT_WORK(&sess->aen_work, scst_aen_work_fn);
++ spin_lock_init(&sess->aen_lock);
++ INIT_LIST_HEAD(&sess->aen_work_list);
++
++ sess->scst_sess = scst_register_session(tgt->scst_tgt, 0,
++ initiator_name, (void *)sess, NULL, NULL);
++ if (sess->scst_sess == NULL) {
++ PRINT_ERROR("%s", "scst_register_session failed");
++ kfree(sess);
++ res = -EFAULT;
++ goto out_free;
++ }
++
++ sess->dev.bus = &scst_local_lld_bus;
++ sess->dev.parent = scst_local_root;
++ sess->dev.release = &scst_local_release_adapter;
++ sess->dev.init_name = kobject_name(&sess->scst_sess->sess_kobj);
++
++ res = device_register(&sess->dev);
++ if (res != 0)
++ goto unregister_session;
++
++ res = sysfs_create_link(scst_sysfs_get_sess_kobj(sess->scst_sess),
++ &sess->shost->shost_dev.kobj, "host");
++ if (res != 0) {
++ PRINT_ERROR("Unable to create \"host\" link for target "
++ "%s", scst_get_tgt_name(tgt->scst_tgt));
++ goto unregister_dev;
++ }
++
++ if (!locked)
++ mutex_lock(&scst_local_mutex);
++ list_add_tail(&sess->sessions_list_entry, &tgt->sessions_list);
++ if (!locked)
++ mutex_unlock(&scst_local_mutex);
++
++ if (scst_initiator_has_luns(tgt->scst_tgt, initiator_name))
++ scsi_scan_target(&sess->shost->shost_gendev, 0, 0,
++ SCAN_WILD_CARD, 1);
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++unregister_dev:
++ device_unregister(&sess->dev);
++
++unregister_session:
++ scst_unregister_session(sess->scst_sess, TRUE, NULL);
++
++out_free:
++ kfree(sess);
++ goto out;
++}
++
++static int scst_local_add_adapter(struct scst_local_tgt *tgt,
++ const char *initiator_name, struct scst_local_sess **out_sess)
++{
++ return __scst_local_add_adapter(tgt, initiator_name, out_sess, false);
++}
++
++/* Must be called under scst_local_mutex */
++static void scst_local_remove_adapter(struct scst_local_sess *sess)
++{
++ TRACE_ENTRY();
++
++ list_del(&sess->sessions_list_entry);
++
++ device_unregister(&sess->dev);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int scst_local_add_target(const char *target_name,
++ struct scst_local_tgt **out_tgt)
++{
++ int res;
++ struct scst_local_tgt *tgt;
++
++ TRACE_ENTRY();
++
++ tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
++ if (NULL == tgt) {
++ PRINT_ERROR("Unable to alloc tgt (size %zu)", sizeof(*tgt));
++ res = -ENOMEM;
++ goto out;
++ }
++
++ INIT_LIST_HEAD(&tgt->sessions_list);
++
++ tgt->scst_tgt = scst_register_target(&scst_local_targ_tmpl, target_name);
++ if (tgt->scst_tgt == NULL) {
++ PRINT_ERROR("%s", "scst_register_target() failed:");
++ res = -EFAULT;
++ goto out_free;
++ }
++
++ scst_tgt_set_tgt_priv(tgt->scst_tgt, tgt);
++
++ mutex_lock(&scst_local_mutex);
++ list_add_tail(&tgt->tgts_list_entry, &scst_local_tgts_list);
++ mutex_unlock(&scst_local_mutex);
++
++ if (out_tgt != NULL)
++ *out_tgt = tgt;
++
++ res = 0;
++
++out:
++ TRACE_EXIT_RES(res);
++ return res;
++
++out_free:
++ kfree(tgt);
++ goto out;
++}
++
++/* Must be called under scst_local_mutex */
++static void __scst_local_remove_target(struct scst_local_tgt *tgt)
++{
++ struct scst_local_sess *sess, *ts;
++
++ TRACE_ENTRY();
++
++ list_for_each_entry_safe(sess, ts, &tgt->sessions_list,
++ sessions_list_entry) {
++ scst_local_remove_adapter(sess);
++ }
++
++ list_del(&tgt->tgts_list_entry);
++
++ scst_unregister_target(tgt->scst_tgt);
++
++ kfree(tgt);
++
++ TRACE_EXIT();
++ return;
++}
++
++static void scst_local_remove_target(struct scst_local_tgt *tgt)
++{
++ TRACE_ENTRY();
++
++ mutex_lock(&scst_local_mutex);
++ __scst_local_remove_target(tgt);
++ mutex_unlock(&scst_local_mutex);
++
++ TRACE_EXIT();
++ return;
++}
++
++static int __init scst_local_init(void)
++{
++ int ret;
++ struct scst_local_tgt *tgt;
++
++ TRACE_ENTRY();
++
++ scst_local_root = root_device_register(SCST_LOCAL_NAME);
++ if (IS_ERR(scst_local_root)) {
++ ret = PTR_ERR(scst_local_root);
++ goto out;
++ }
++
++ ret = bus_register(&scst_local_lld_bus);
++ if (ret < 0) {
++ PRINT_ERROR("bus_register() error: %d", ret);
++ goto dev_unreg;
++ }
++
++ ret = driver_register(&scst_local_driver);
++ if (ret < 0) {
++ PRINT_ERROR("driver_register() error: %d", ret);
++ goto bus_unreg;
++ }
++
++ ret = scst_register_target_template(&scst_local_targ_tmpl);
++ if (ret != 0) {
++ PRINT_ERROR("Unable to register target template: %d", ret);
++ goto driver_unreg;
++ }
++
++ /*
++ * If we are using sysfs, then don't add a default target unless
++ * we are told to do so. When using procfs, we always add a default
++ * target because that was what the earliest versions did. Just
++ * remove the preprocessor directives when no longer needed.
++ */
++ if (!scst_local_add_default_tgt)
++ goto out;
++
++ ret = scst_local_add_target("scst_local_tgt", &tgt);
++ if (ret != 0)
++ goto tgt_templ_unreg;
++
++ ret = scst_local_add_adapter(tgt, "scst_local_host", NULL);
++ if (ret != 0)
++ goto tgt_unreg;
++
++out:
++ TRACE_EXIT_RES(ret);
++ return ret;
++
++tgt_unreg:
++ scst_local_remove_target(tgt);
++
++tgt_templ_unreg:
++ scst_unregister_target_template(&scst_local_targ_tmpl);
++
++driver_unreg:
++ driver_unregister(&scst_local_driver);
++
++bus_unreg:
++ bus_unregister(&scst_local_lld_bus);
++
++dev_unreg:
++ root_device_unregister(scst_local_root);
++
++ goto out;
++}
++
++static void __exit scst_local_exit(void)
++{
++ struct scst_local_tgt *tgt, *tt;
++
++ TRACE_ENTRY();
++
++ down_write(&scst_local_exit_rwsem);
++
++ mutex_lock(&scst_local_mutex);
++ list_for_each_entry_safe(tgt, tt, &scst_local_tgts_list,
++ tgts_list_entry) {
++ __scst_local_remove_target(tgt);
++ }
++ mutex_unlock(&scst_local_mutex);
++
++ driver_unregister(&scst_local_driver);
++ bus_unregister(&scst_local_lld_bus);
++ root_device_unregister(scst_local_root);
++
++ /* Now unregister the target template */
++ scst_unregister_target_template(&scst_local_targ_tmpl);
++
++ /* To make lockdep happy */
++ up_write(&scst_local_exit_rwsem);
++
++ TRACE_EXIT();
++ return;
++}
++
++device_initcall(scst_local_init);
++module_exit(scst_local_exit);
++
+diff -uprN orig/linux-2.6.36/Documentation/scst/README.scst_local linux-2.6.36/Documentation/scst/README.scst_local
+--- orig/linux-2.6.36/Documentation/scst/README.scst_local
++++ linux-2.6.36/Documentation/scst/README.scst_local
+@@ -0,0 +1,259 @@
++SCST Local ...
++Richard Sharpe, 30-Nov-2008
++
++This is the SCST Local driver. Its function is to allow you to access devices
++that are exported via SCST directly on the same Linux system that they are
++exported from.
++
++No assumptions are made in the code about the device types on the target, so
++any device handlers that you load in SCST should be visible, including tapes
++and so forth.
++
++You can freely use any sg, sd, st, etc. devices imported from target,
++except the following: you can't mount file systems or put swap on them.
++This is a limitation of Linux memory/cache manager. See SCST README file
++for details.
++
++To build, simply issue 'make' in the scst_local directory.
++
++Try 'modinfo scst_local' for a listing of module parameters so far.
++
++Here is how I have used it so far:
++
++1. Load up scst:
++
++ modprobe scst
++ modprobe scst_vdisk
++
++2. Create a virtual disk (or your own device handler):
++
++ dd if=/dev/zero of=/some/path/vdisk1.img bs=16384 count=1000000
++ echo "add_device vm_disk1 filename=/some/path/vdisk1.img" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
++
++3. Load the scst_local driver:
++
++ insmod scst_local
++ echo "add vm_disk1 0" >/sys/kernel/scst_tgt/targets/scst_local/scst_local_tgt/luns/mgmt
++
++4. Check what you have
++
++ cat /proc/scsi/scsi
++ Attached devices:
++ Host: scsi0 Channel: 00 Id: 00 Lun: 00
++ Vendor: ATA Model: ST9320320AS Rev: 0303
++ Type: Direct-Access ANSI SCSI revision: 05
++ Host: scsi4 Channel: 00 Id: 00 Lun: 00
++ Vendor: TSSTcorp Model: CD/DVDW TS-L632D Rev: TO04
++ Type: CD-ROM ANSI SCSI revision: 05
++ Host: scsi7 Channel: 00 Id: 00 Lun: 00
++ Vendor: SCST_FIO Model: vm_disk1 Rev: 200
++ Type: Direct-Access ANSI SCSI revision: 04
++
++Or instead of manually "add_device" in (2) and step (3) write a
++scstadmin config:
++
++HANDLER vdisk_fileio {
++ DEVICE vm_disk1 {
++ filename /some/path/vdisk1.img
++ }
++}
++
++TARGET_DRIVER scst_local {
++ TARGET scst_local_tgt {
++ LUN 0 vm_disk1
++ }
++}
++
++then:
++
++ insmod scst_local
++ scstadmin -config conf_file.cfg
++
++More advanced examples:
++
++For (3) you can:
++
++ insmod scst_local add_default_tgt=0
++ echo "add_target scst_local_tgt session_name=scst_local_host" >/sys/kernel/scst_tgt/targets/scst_local//mgmt
++ echo "add vm_disk1 0" >/sys/kernel/scst_tgt/targets/scst_local/scst_local_tgt/luns/mgmt
++
++Scst_local module's parameter add_default_tgt disables creation of
++default target "scst_local_tgt" and session "scst_local_host", so you
++needed to create it manually.
++
++There can be any number of targets and sessions created. Each SCST
++session corresponds to SCSI host. You can change which LUNs assigned to
++each session by using SCST access control. This mode is intended for
++user space target drivers (see below).
++
++Alternatively, you can write an scstadmin's config file conf_file.cfg:
++
++HANDLER vdisk_fileio {
++ DEVICE vm_disk1 {
++ filename /some/path/vdisk1.img
++ }
++}
++
++TARGET_DRIVER scst_local {
++ TARGET scst_local_tgt {
++ session_name scst_local_host
++
++ LUN 0 vm_disk1
++ }
++}
++
++then:
++
++ insmod scst_local add_default_tgt=0
++ scstadmin -config conf_file.cfg
++
++NOTE! Although scstadmin allows to create scst_local's sessions using
++"session_name" expression, it doesn't save existing sessions during
++writing config file by "write_config" command. If you need this
++functionality, feel free to send a request for it in SCST development
++mailing list.
++
++5. Have fun.
++
++Some of this was coded while in Santa Clara, some in Bangalore, and some in
++Hyderabad. Noe doubt some will be coded on the way back to Santa Clara.
++
++The code still has bugs, so if you encounter any, email me the fixes at:
++
++ realrichardsharpe@gmail.com
++
++I am thinking of renaming this to something more interesting.
++
++Sysfs interface
++===============
++
++See SCST's README for a common SCST sysfs description.
++
++Root of this driver is /sys/kernel/scst_tgt/targets/scst_local. It has
++the following additional entry:
++
++ - stats - read-only attribute with some statistical information.
++
++Each target subdirectory contains the following additional entries:
++
++ - phys_transport_version - contains and allows to change physical
++ transport version descriptor. It determines by which phisical
++ interface this target will look like. See SPC for more details. By
++ default, it is not defined (0).
++
++ - scsi_transport_version - contains and allows to change SCSI
++ transport version descriptor. It determines by which SCSI
++ transport this target will look like. See SPC for more details. By
++ default, it is SAS.
++
++Each session subdirectory contains the following additional entries:
++
++ - transport_id - contains this host's TransportID. This TransportID
++ used to identify initiator in Persisten Reservation commands. If you
++ change scsi_transport_version for a target, make sure you set for all
++ its sessions correct TransportID. See SPC for more details.
++
++ - host - links to the corresponding SCSI host. Using it you can find
++ local sg/bsg/sd/etc. devices of this session. For instance, this
++ links points out to host12, so you can find your sg devices by:
++
++$ lsscsi -g|grep "\[12:"
++[12:0:0:0] disk SCST_FIO rd1 200 /dev/sdc /dev/sg2
++[12:0:0:1] disk SCST_FIO nullio 200 /dev/sdd /dev/sg3
++
++They are /dev/sg2 and /dev/sg3.
++
++The following management commands available via /sys/kernel/scst_tgt/targets/scst_local/mgmt:
++
++ - add_target target_name [session_name=sess_name; [session_name=sess_name1;] [...]] -
++ creates a target with optionally one or more sessions.
++
++ - del_target target_name - deletes a target.
++
++ - add_session target_name session_name - adds to target target_name
++ session (SCSI host) with name session_name.
++
++ - del_session target_name session_name - deletes session session_name
++ from target target_name.
++
++Note on performance
++===================
++
++Although this driver implemented in the most performance effective way,
++including zero-copy passing data between SCSI/block subsystems and SCST,
++in many cases it is NOT suited to measure performance as a NULL link.
++For example, it is not suited for max IOPS measurements. This is because
++for such cases not performance of the link between the target and
++initiator is the bottleneck, but CPU or memory speed on the target or
++initiator. For scst_local you have both initiator and target on the same
++system, which means each your initiator and target are much less
++CPU/memory powerful.
++
++User space target drivers
++=========================
++
++Scst_local can be used to write full featured SCST target drivers in
++user space:
++
++1. For each SCSI target a user space target driver should create an
++ scst_local's target using "add_target" command.
++
++2. Then the user space target driver should, if needed, set its SCSI and
++ physical transport version descriptors using attributes
++ scsi_transport_version and phys_transport_version correspondingly in
++ /sys/kernel/scst_tgt/targets/scst_local/target_name directory.
++
++3. For incoming session (I_T nexus) from an initiator the user space
++ target driver should create scst_local's session using "add_session"
++ command.
++
++4. Then, if needed, the user space target driver should set TransportID
++ for this session (I_T nexus) using attribute
++ /sys/kernel/scst_tgt/targets/scst_local/target_name/sessions/session_name/transport_id
++
++5. Then the user space target driver should find out sg/bsg devices for
++ the LUNs the created session has using link
++ /sys/kernel/scst_tgt/targets/scst_local/target_name/sessions/session_name/host
++ as described above.
++
++6. Then the user space target driver can start serving the initiator using
++ found sg/bsg devices.
++
++For other connected initiators steps 3-6 should be repeated.
++
++Change log
++==========
++
++V0.1 24-Sep-2008 (Hyderabad) Initial coding, pretty chatty and messy,
++ but worked.
++
++V0.2 25-Sep-2008 (Hong Kong) Cleaned up the code a lot, reduced the log
++ chatter, fixed a bug where multiple LUNs did not
++ work. Also, added logging control. Tested with
++ five virtual disks. They all came up as /dev/sdb
++ through /dev/sdf and I could dd to them. Also
++ fixed a bug preventing multiple adapters.
++
++V0.3 26-Sep-2008 (Santa Clara) Added back a copyright plus cleaned up some
++ unused functions and structures.
++
++V0.4 5-Oct-2008 (Santa Clara) Changed name to scst_local as suggested, cleaned
++ up some unused variables (made them used) and
++ change allocation to a kmem_cache pool.
++
++V0.5 5-Oct-2008 (Santa Clara) Added mgmt commands to handle dev reset and
++ aborts. Not sure if aborts works. Also corrected
++ the version info and renamed readme to README.
++
++V0.6 7-Oct-2008 (Santa Clara) Removed some redundant code and made some
++ changes suggested by Vladislav.
++
++V0.7 11-Oct-2008 (Santa Clara) Moved into the scst tree. Cleaned up some
++ unused functions, used TRACE macros etc.
++
++V0.9 30-Nov-2008 (Mtn View) Cleaned up an additional problem with symbols not
++ being defined in older version of the kernel. Also
++ fixed some English and cleaned up this doc.
++
++V1.0 10-Sep-2010 (Moscow) Sysfs management added. Reviewed and cleaned up.
++
diff --git a/main/linux-scst/setlocalversion.patch b/main/linux-scst/setlocalversion.patch
new file mode 100644
index 0000000000..d82eb170ab
--- /dev/null
+++ b/main/linux-scst/setlocalversion.patch
@@ -0,0 +1,11 @@
+--- ./scripts/setlocalversion.orig
++++ ./scripts/setlocalversion
+@@ -43,7 +43,7 @@
+ fi
+
+ # Check for git and a git repo.
+- if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
++ if [ -d "$srctree"/.git ] && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+
+ # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
+ # it, because this version is defined in the top level Makefile.
diff --git a/main/linux-scst/unionfs-2.5.7_for_2.6.36.diff b/main/linux-scst/unionfs-2.5.7_for_2.6.36.diff
new file mode 100644
index 0000000000..fabe758098
--- /dev/null
+++ b/main/linux-scst/unionfs-2.5.7_for_2.6.36.diff
@@ -0,0 +1,11253 @@
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 4303614..5ade4a8 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -112,6 +112,8 @@ udf.txt
+ - info and mount options for the UDF filesystem.
+ ufs.txt
+ - info on the ufs filesystem.
++unionfs/
++ - info on the unionfs filesystem
+ vfat.txt
+ - info on using the VFAT filesystem used in Windows NT and Windows 95
+ vfs.txt
+diff --git a/Documentation/filesystems/unionfs/00-INDEX b/Documentation/filesystems/unionfs/00-INDEX
+new file mode 100644
+index 0000000..96fdf67
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/00-INDEX
+@@ -0,0 +1,10 @@
++00-INDEX
++ - this file.
++concepts.txt
++ - A brief introduction of concepts.
++issues.txt
++ - A summary of known issues with unionfs.
++rename.txt
++ - Information regarding rename operations.
++usage.txt
++ - Usage information and examples.
+diff --git a/Documentation/filesystems/unionfs/concepts.txt b/Documentation/filesystems/unionfs/concepts.txt
+new file mode 100644
+index 0000000..b853788
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/concepts.txt
+@@ -0,0 +1,287 @@
++Unionfs 2.x CONCEPTS:
++=====================
++
++This file describes the concepts needed by a namespace unification file
++system.
++
++
++Branch Priority:
++================
++
++Each branch is assigned a unique priority - starting from 0 (highest
++priority). No two branches can have the same priority.
++
++
++Branch Mode:
++============
++
++Each branch is assigned a mode - read-write or read-only. This allows
++directories on media mounted read-write to be used in a read-only manner.
++
++
++Whiteouts:
++==========
++
++A whiteout removes a file name from the namespace. Whiteouts are needed when
++one attempts to remove a file on a read-only branch.
++
++Suppose we have a two-branch union, where branch 0 is read-write and branch
++1 is read-only. And a file 'foo' on branch 1:
++
++./b0/
++./b1/
++./b1/foo
++
++The unified view would simply be:
++
++./union/
++./union/foo
++
++Since 'foo' is stored on a read-only branch, it cannot be removed. A
++whiteout is used to remove the name 'foo' from the unified namespace. Again,
++since branch 1 is read-only, the whiteout cannot be created there. So, we
++try on a higher priority (lower numerically) branch and create the whiteout
++there.
++
++./b0/
++./b0/.wh.foo
++./b1/
++./b1/foo
++
++Later, when Unionfs traverses branches (due to lookup or readdir), it
++eliminate 'foo' from the namespace (as well as the whiteout itself.)
++
++
++Opaque Directories:
++===================
++
++Assume we have a unionfs mount comprising of two branches. Branch 0 is
++empty; branch 1 has the directory /a and file /a/f. Let's say we mount a
++union of branch 0 as read-write and branch 1 as read-only. Now, let's say
++we try to perform the following operation in the union:
++
++ rm -fr a
++
++Because branch 1 is not writable, we cannot physically remove the file /a/f
++or the directory /a. So instead, we will create a whiteout in branch 0
++named /.wh.a, masking out the name "a" from branch 1. Next, let's say we
++try to create a directory named "a" as follows:
++
++ mkdir a
++
++Because we have a whiteout for "a" already, Unionfs behaves as if "a"
++doesn't exist, and thus will delete the whiteout and replace it with an
++actual directory named "a".
++
++The problem now is that if you try to "ls" in the union, Unionfs will
++perform is normal directory name unification, for *all* directories named
++"a" in all branches. This will cause the file /a/f from branch 1 to
++re-appear in the union's namespace, which violates Unix semantics.
++
++To avoid this problem, we have a different form of whiteouts for
++directories, called "opaque directories" (same as BSD Union Mount does).
++Whenever we replace a whiteout with a directory, that directory is marked as
++opaque. In Unionfs 2.x, it means that we create a file named
++/a/.wh.__dir_opaque in branch 0, after having created directory /a there.
++When unionfs notices that a directory is opaque, it stops all namespace
++operations (including merging readdir contents) at that opaque directory.
++This prevents re-exposing names from masked out directories.
++
++
++Duplicate Elimination:
++======================
++
++It is possible for files on different branches to have the same name.
++Unionfs then has to select which instance of the file to show to the user.
++Given the fact that each branch has a priority associated with it, the
++simplest solution is to take the instance from the highest priority
++(numerically lowest value) and "hide" the others.
++
++
++Unlinking:
++=========
++
++Unlink operation on non-directory instances is optimized to remove the
++maximum possible objects in case multiple underlying branches have the same
++file name. The unlink operation will first try to delete file instances
++from highest priority branch and then move further to delete from remaining
++branches in order of their decreasing priority. Consider a case (F..D..F),
++where F is a file and D is a directory of the same name; here, some
++intermediate branch could have an empty directory instance with the same
++name, so this operation also tries to delete this directory instance and
++proceed further to delete from next possible lower priority branch. The
++unionfs unlink operation will smoothly delete the files with same name from
++all possible underlying branches. In case if some error occurs, it creates
++whiteout in highest priority branch that will hide file instance in rest of
++the branches. An error could occur either if an unlink operations in any of
++the underlying branch failed or if a branch has no write permission.
++
++This unlinking policy is known as "delete all" and it has the benefit of
++overall reducing the number of inodes used by duplicate files, and further
++reducing the total number of inodes consumed by whiteouts. The cost is of
++extra processing, but testing shows this extra processing is well worth the
++savings.
++
++
++Copyup:
++=======
++
++When a change is made to the contents of a file's data or meta-data, they
++have to be stored somewhere. The best way is to create a copy of the
++original file on a branch that is writable, and then redirect the write
++though to this copy. The copy must be made on a higher priority branch so
++that lookup and readdir return this newer "version" of the file rather than
++the original (see duplicate elimination).
++
++An entire unionfs mount can be read-only or read-write. If it's read-only,
++then none of the branches will be written to, even if some of the branches
++are physically writeable. If the unionfs mount is read-write, then the
++leftmost (highest priority) branch must be writeable (for copyup to take
++place); the remaining branches can be any mix of read-write and read-only.
++
++In a writeable mount, unionfs will create new files/dir in the leftmost
++branch. If one tries to modify a file in a read-only branch/media, unionfs
++will copyup the file to the leftmost branch and modify it there. If you try
++to modify a file from a writeable branch which is not the leftmost branch,
++then unionfs will modify it in that branch; this is useful if you, say,
++unify differnet packages (e.g., apache, sendmail, ftpd, etc.) and you want
++changes to specific package files to remain logically in the directory where
++they came from.
++
++Cache Coherency:
++================
++
++Unionfs users often want to be able to modify files and directories directly
++on the lower branches, and have those changes be visible at the Unionfs
++level. This means that data (e.g., pages) and meta-data (dentries, inodes,
++open files, etc.) have to be synchronized between the upper and lower
++layers. In other words, the newest changes from a layer below have to be
++propagated to the Unionfs layer above. If the two layers are not in sync, a
++cache incoherency ensues, which could lead to application failures and even
++oopses. The Linux kernel, however, has a rather limited set of mechanisms
++to ensure this inter-layer cache coherency---so Unionfs has to do most of
++the hard work on its own.
++
++Maintaining Invariants:
++
++The way Unionfs ensures cache coherency is as follows. At each entry point
++to a Unionfs file system method, we call a utility function to validate the
++primary objects of this method. Generally, we call unionfs_file_revalidate
++on open files, and __unionfs_d_revalidate_chain on dentries (which also
++validates inodes). These utility functions check to see whether the upper
++Unionfs object is in sync with any of the lower objects that it represents.
++The checks we perform include whether the Unionfs superblock has a newer
++generation number, or if any of the lower objects mtime's or ctime's are
++newer. (Note: generation numbers change when branch-management commands are
++issued, so in a way, maintaining cache coherency is also very important for
++branch-management.) If indeed we determine that any Unionfs object is no
++longer in sync with its lower counterparts, then we rebuild that object
++similarly to how we do so for branch-management.
++
++While rebuilding Unionfs's objects, we also purge any page mappings and
++truncate inode pages (see fs/unionfs/dentry.c:purge_inode_data). This is to
++ensure that Unionfs will re-get the newer data from the lower branches. We
++perform this purging only if the Unionfs operation in question is a reading
++operation; if Unionfs is performing a data writing operation (e.g., ->write,
++->commit_write, etc.) then we do NOT flush the lower mappings/pages: this is
++because (1) a self-deadlock could occur and (2) the upper Unionfs pages are
++considered more authoritative anyway, as they are newer and will overwrite
++any lower pages.
++
++Unionfs maintains the following important invariant regarding mtime's,
++ctime's, and atime's: the upper inode object's times are the max() of all of
++the lower ones. For non-directory objects, there's only one object below,
++so the mapping is simple; for directory objects, there could me multiple
++lower objects and we have to sync up with the newest one of all the lower
++ones. This invariant is important to maintain, especially for directories
++(besides, we need this to be POSIX compliant). A union could comprise
++multiple writable branches, each of which could change. If we don't reflect
++the newest possible mtime/ctime, some applications could fail. For example,
++NFSv2/v3 exports check for newer directory mtimes on the server to determine
++if the client-side attribute cache should be purged.
++
++To maintain these important invariants, of course, Unionfs carefully
++synchronizes upper and lower times in various places. For example, if we
++copy-up a file to a top-level branch, the parent directory where the file
++was copied up to will now have a new mtime: so after a successful copy-up,
++we sync up with the new top-level branch's parent directory mtime.
++
++Implementation:
++
++This cache-coherency implementation is efficient because it defers any
++synchronizing between the upper and lower layers until absolutely needed.
++Consider the example a common situation where users perform a lot of lower
++changes, such as untarring a whole package. While these take place,
++typically the user doesn't access the files via Unionfs; only after the
++lower changes are done, does the user try to access the lower files. With
++our cache-coherency implementation, the entirety of the changes to the lower
++branches will not result in a single CPU cycle spent at the Unionfs level
++until the user invokes a system call that goes through Unionfs.
++
++We have considered two alternate cache-coherency designs. (1) Using the
++dentry/inode notify functionality to register interest in finding out about
++any lower changes. This is a somewhat limited and also a heavy-handed
++approach which could result in many notifications to the Unionfs layer upon
++each small change at the lower layer (imagine a file being modified multiple
++times in rapid succession). (2) Rewriting the VFS to support explicit
++callbacks from lower objects to upper objects. We began exploring such an
++implementation, but found it to be very complicated--it would have resulted
++in massive VFS/MM changes which are unlikely to be accepted by the LKML
++community. We therefore believe that our current cache-coherency design and
++implementation represent the best approach at this time.
++
++Limitations:
++
++Our implementation works in that as long as a user process will have caused
++Unionfs to be called, directly or indirectly, even to just do
++->d_revalidate; then we will have purged the current Unionfs data and the
++process will see the new data. For example, a process that continually
++re-reads the same file's data will see the NEW data as soon as the lower
++file had changed, upon the next read(2) syscall (even if the file is still
++open!) However, this doesn't work when the process re-reads the open file's
++data via mmap(2) (unless the user unmaps/closes the file and remaps/reopens
++it). Once we respond to ->readpage(s), then the kernel maps the page into
++the process's address space and there doesn't appear to be a way to force
++the kernel to invalidate those pages/mappings, and force the process to
++re-issue ->readpage. If there's a way to invalidate active mappings and
++force a ->readpage, let us know please (invalidate_inode_pages2 doesn't do
++the trick).
++
++Our current Unionfs code has to perform many file-revalidation calls. It
++would be really nice if the VFS would export an optional file system hook
++->file_revalidate (similarly to dentry->d_revalidate) that will be called
++before each VFS op that has a "struct file" in it.
++
++Certain file systems have micro-second granularity (or better) for inode
++times, and asynchronous actions could cause those times to change with some
++small delay. In such cases, Unionfs may see a changed inode time that only
++differs by a tiny fraction of a second: such a change may be a false
++positive indication that the lower object has changed, whereas if unionfs
++waits a little longer, that false indication will not be seen. (These false
++positives are harmless, because they would at most cause unionfs to
++re-validate an object that may need no revalidation, and print a debugging
++message that clutters the console/logs.) Therefore, to minimize the chances
++of these situations, we delay the detection of changed times by a small
++factor of a few seconds, called UNIONFS_MIN_CC_TIME (which defaults to 3
++seconds, as does NFS). This means that we will detect the change, only a
++couple of seconds later, if indeed the time change persists in the lower
++file object. This delayed detection has an added performance benefit: we
++reduce the number of times that unionfs has to revalidate objects, in case
++there's a lot of concurrent activity on both the upper and lower objects,
++for the same file(s). Lastly, this delayed time attribute detection is
++similar to how NFS clients operate (e.g., acregmin).
++
++Finally, there is no way currently in Linux to prevent lower directories
++from being moved around (i.e., topology changes); there's no way to prevent
++modifications to directory sub-trees of whole file systems which are mounted
++read-write. It is therefore possible for in-flight operations in unionfs to
++take place, while a lower directory is being moved around. Therefore, if
++you try to, say, create a new file in a directory through unionfs, while the
++directory is being moved around directly, then the new file may get created
++in the new location where that directory was moved to. This is a somewhat
++similar behaviour in NFS: an NFS client could be creating a new file while
++th NFS server is moving th directory around; the file will get successfully
++created in the new location. (The one exception in unionfs is that if the
++branch is marked read-only by unionfs, then a copyup will take place.)
++
++For more information, see <http://unionfs.filesystems.org/>.
+diff --git a/Documentation/filesystems/unionfs/issues.txt b/Documentation/filesystems/unionfs/issues.txt
+new file mode 100644
+index 0000000..f4b7e7e
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/issues.txt
+@@ -0,0 +1,28 @@
++KNOWN Unionfs 2.x ISSUES:
++=========================
++
++1. Unionfs should not use lookup_one_len() on the underlying f/s as it
++ confuses NFSv4. Currently, unionfs_lookup() passes lookup intents to the
++ lower file-system, this eliminates part of the problem. The remaining
++ calls to lookup_one_len may need to be changed to pass an intent. We are
++ currently introducing VFS changes to fs/namei.c's do_path_lookup() to
++ allow proper file lookup and opening in stackable file systems.
++
++2. Lockdep (a debugging feature) isn't aware of stacking, and so it
++ incorrectly complains about locking problems. The problem boils down to
++ this: Lockdep considers all objects of a certain type to be in the same
++ class, for example, all inodes. Lockdep doesn't like to see a lock held
++ on two inodes within the same task, and warns that it could lead to a
++ deadlock. However, stackable file systems do precisely that: they lock
++ an upper object, and then a lower object, in a strict order to avoid
++ locking problems; in addition, Unionfs, as a fan-out file system, may
++ have to lock several lower inodes. We are currently looking into Lockdep
++ to see how to make it aware of stackable file systems. For now, we
++ temporarily disable lockdep when calling vfs methods on lower objects,
++ but only for those places where lockdep complained. While this solution
++ may seem unclean, it is not without precedent: other places in the kernel
++ also do similar temporary disabling, of course after carefully having
++ checked that it is the right thing to do. Anyway, you get any warnings
++ from Lockdep, please report them to the Unionfs maintainers.
++
++For more information, see <http://unionfs.filesystems.org/>.
+diff --git a/Documentation/filesystems/unionfs/rename.txt b/Documentation/filesystems/unionfs/rename.txt
+new file mode 100644
+index 0000000..e20bb82
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/rename.txt
+@@ -0,0 +1,31 @@
++Rename is a complex beast. The following table shows which rename(2) operations
++should succeed and which should fail.
++
++o: success
++E: error (either unionfs or vfs)
++X: EXDEV
++
++none = file does not exist
++file = file is a file
++dir = file is a empty directory
++child= file is a non-empty directory
++wh = file is a directory containing only whiteouts; this makes it logically
++ empty
++
++ none file dir child wh
++file o o E E E
++dir o E o E o
++child X E X E X
++wh o E o E o
++
++
++Renaming directories:
++=====================
++
++Whenever a empty (either physically or logically) directory is being renamed,
++the following sequence of events should take place:
++
++1) Remove whiteouts from both source and destination directory
++2) Rename source to destination
++3) Make destination opaque to prevent anything under it from showing up
++
+diff --git a/Documentation/filesystems/unionfs/usage.txt b/Documentation/filesystems/unionfs/usage.txt
+new file mode 100644
+index 0000000..1adde69
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/usage.txt
+@@ -0,0 +1,134 @@
++Unionfs is a stackable unification file system, which can appear to merge
++the contents of several directories (branches), while keeping their physical
++content separate. Unionfs is useful for unified source tree management,
++merged contents of split CD-ROM, merged separate software package
++directories, data grids, and more. Unionfs allows any mix of read-only and
++read-write branches, as well as insertion and deletion of branches anywhere
++in the fan-out. To maintain Unix semantics, Unionfs handles elimination of
++duplicates, partial-error conditions, and more.
++
++GENERAL SYNTAX
++==============
++
++# mount -t unionfs -o <OPTIONS>,<BRANCH-OPTIONS> none MOUNTPOINT
++
++OPTIONS can be any legal combination of:
++
++- ro # mount file system read-only
++- rw # mount file system read-write
++- remount # remount the file system (see Branch Management below)
++- incgen # increment generation no. (see Cache Consistency below)
++
++BRANCH-OPTIONS can be either (1) a list of branches given to the "dirs="
++option, or (2) a list of individual branch manipulation commands, combined
++with the "remount" option, and is further described in the "Branch
++Management" section below.
++
++The syntax for the "dirs=" mount option is:
++
++ dirs=branch[=ro|=rw][:...]
++
++The "dirs=" option takes a colon-delimited list of directories to compose
++the union, with an optional branch mode for each of those directories.
++Directories that come earlier (specified first, on the left) in the list
++have a higher precedence than those which come later. Additionally,
++read-only or read-write permissions of the branch can be specified by
++appending =ro or =rw (default) to each directory. See the Copyup section in
++concepts.txt, for a description of Unionfs's behavior when mixing read-only
++and read-write branches and mounts.
++
++Syntax:
++
++ dirs=/branch1[=ro|=rw]:/branch2[=ro|=rw]:...:/branchN[=ro|=rw]
++
++Example:
++
++ dirs=/writable_branch=rw:/read-only_branch=ro
++
++
++BRANCH MANAGEMENT
++=================
++
++Once you mount your union for the first time, using the "dirs=" option, you
++can then change the union's overall mode or reconfigure the branches, using
++the remount option, as follows.
++
++To downgrade a union from read-write to read-only:
++
++# mount -t unionfs -o remount,ro none MOUNTPOINT
++
++To upgrade a union from read-only to read-write:
++
++# mount -t unionfs -o remount,rw none MOUNTPOINT
++
++To delete a branch /foo, regardless where it is in the current union:
++
++# mount -t unionfs -o remount,del=/foo none MOUNTPOINT
++
++To insert (add) a branch /foo before /bar:
++
++# mount -t unionfs -o remount,add=/bar:/foo none MOUNTPOINT
++
++To insert (add) a branch /foo (with the "rw" mode flag) before /bar:
++
++# mount -t unionfs -o remount,add=/bar:/foo=rw none MOUNTPOINT
++
++To insert (add) a branch /foo (in "rw" mode) at the very beginning (i.e., a
++new highest-priority branch), you can use the above syntax, or use a short
++hand version as follows:
++
++# mount -t unionfs -o remount,add=/foo none MOUNTPOINT
++
++To append a branch to the very end (new lowest-priority branch):
++
++# mount -t unionfs -o remount,add=:/foo none MOUNTPOINT
++
++To append a branch to the very end (new lowest-priority branch), in
++read-only mode:
++
++# mount -t unionfs -o remount,add=:/foo=ro none MOUNTPOINT
++
++Finally, to change the mode of one existing branch, say /foo, from read-only
++to read-write, and change /bar from read-write to read-only:
++
++# mount -t unionfs -o remount,mode=/foo=rw,mode=/bar=ro none MOUNTPOINT
++
++Note: in Unionfs 2.x, you cannot set the leftmost branch to readonly because
++then Unionfs won't have any writable place for copyups to take place.
++Moreover, the VFS can get confused when it tries to modify something in a
++file system mounted read-write, but isn't permitted to write to it.
++Instead, you should set the whole union as readonly, as described above.
++If, however, you must set the leftmost branch as readonly, perhaps so you
++can get a snapshot of it at a point in time, then you should insert a new
++writable top-level branch, and mark the one you want as readonly. This can
++be accomplished as follows, assuming that /foo is your current leftmost
++branch:
++
++# mount -t tmpfs -o size=NNN /new
++# mount -t unionfs -o remount,add=/new,mode=/foo=ro none MOUNTPOINT
++<do what you want safely in /foo>
++# mount -t unionfs -o remount,del=/new,mode=/foo=rw none MOUNTPOINT
++<check if there's anything in /new you want to preserve>
++# umount /new
++
++CACHE CONSISTENCY
++=================
++
++If you modify any file on any of the lower branches directly, while there is
++a Unionfs 2.x mounted above any of those branches, you should tell Unionfs
++to purge its caches and re-get the objects. To do that, you have to
++increment the generation number of the superblock using the following
++command:
++
++# mount -t unionfs -o remount,incgen none MOUNTPOINT
++
++Note that the older way of incrementing the generation number using an
++ioctl, is no longer supported in Unionfs 2.0 and newer. Ioctls in general
++are not encouraged. Plus, an ioctl is per-file concept, whereas the
++generation number is a per-file-system concept. Worse, such an ioctl
++requires an open file, which then has to be invalidated by the very nature
++of the generation number increase (read: the old generation increase ioctl
++was pretty racy).
++
++
++For more information, see <http://unionfs.filesystems.org/>.
+diff --git a/MAINTAINERS b/MAINTAINERS
+index f2a2b8e..11d7f45 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -5917,6 +5917,14 @@ F: Documentation/cdrom/
+ F: drivers/cdrom/cdrom.c
+ F: include/linux/cdrom.h
+
++UNIONFS
++P: Erez Zadok
++M: ezk@cs.sunysb.edu
++L: unionfs@filesystems.org
++W: http://unionfs.filesystems.org/
++T: git git.kernel.org/pub/scm/linux/kernel/git/ezk/unionfs.git
++S: Maintained
++
+ UNSORTED BLOCK IMAGES (UBI)
+ M: Artem Bityutskiy <dedekind1@gmail.com>
+ W: http://www.linux-mtd.infradead.org/
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 3d18530..65b6aa1 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -169,6 +169,7 @@ if MISC_FILESYSTEMS
+ source "fs/adfs/Kconfig"
+ source "fs/affs/Kconfig"
+ source "fs/ecryptfs/Kconfig"
++source "fs/unionfs/Kconfig"
+ source "fs/hfs/Kconfig"
+ source "fs/hfsplus/Kconfig"
+ source "fs/befs/Kconfig"
+diff --git a/fs/Makefile b/fs/Makefile
+index e6ec1d3..787332e 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -84,6 +84,7 @@ obj-$(CONFIG_ISO9660_FS) += isofs/
+ obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
+ obj-$(CONFIG_HFS_FS) += hfs/
+ obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
++obj-$(CONFIG_UNION_FS) += unionfs/
+ obj-$(CONFIG_VXFS_FS) += freevxfs/
+ obj-$(CONFIG_NFS_FS) += nfs/
+ obj-$(CONFIG_EXPORTFS) += exportfs/
+diff --git a/fs/namei.c b/fs/namei.c
+index 24896e8..db22420 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -385,6 +385,7 @@ void release_open_intent(struct nameidata *nd)
+ else
+ fput(nd->intent.open.file);
+ }
++EXPORT_SYMBOL_GPL(release_open_intent);
+
+ static inline struct dentry *
+ do_revalidate(struct dentry *dentry, struct nameidata *nd)
+diff --git a/fs/splice.c b/fs/splice.c
+index 8f1dfae..7a57fab 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -1092,8 +1092,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+ * Attempt to initiate a splice from pipe to file.
+ */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+- loff_t *ppos, size_t len, unsigned int flags)
++long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags)
+ {
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
+ loff_t *, size_t, unsigned int);
+@@ -1116,13 +1116,14 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+
+ return splice_write(pipe, out, ppos, len, flags);
+ }
++EXPORT_SYMBOL_GPL(vfs_splice_from);
+
+ /*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+- struct pipe_inode_info *pipe, size_t len,
+- unsigned int flags)
++long vfs_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
+ {
+ ssize_t (*splice_read)(struct file *, loff_t *,
+ struct pipe_inode_info *, size_t, unsigned int);
+@@ -1142,6 +1143,7 @@ static long do_splice_to(struct file *in, loff_t *ppos,
+
+ return splice_read(in, ppos, pipe, len, flags);
+ }
++EXPORT_SYMBOL_GPL(vfs_splice_to);
+
+ /**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+@@ -1211,7 +1213,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+ size_t read_len;
+ loff_t pos = sd->pos, prev_pos = pos;
+
+- ret = do_splice_to(in, &pos, pipe, len, flags);
++ ret = vfs_splice_to(in, &pos, pipe, len, flags);
+ if (unlikely(ret <= 0))
+ goto out_release;
+
+@@ -1270,8 +1272,8 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
+ {
+ struct file *file = sd->u.file;
+
+- return do_splice_from(pipe, file, &file->f_pos, sd->total_len,
+- sd->flags);
++ return vfs_splice_from(pipe, file, &file->f_pos, sd->total_len,
++ sd->flags);
+ }
+
+ /**
+@@ -1368,7 +1370,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
+ } else
+ off = &out->f_pos;
+
+- ret = do_splice_from(ipipe, out, off, len, flags);
++ ret = vfs_splice_from(ipipe, out, off, len, flags);
+
+ if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+ ret = -EFAULT;
+@@ -1388,7 +1390,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
+ } else
+ off = &in->f_pos;
+
+- ret = do_splice_to(in, off, opipe, len, flags);
++ ret = vfs_splice_to(in, off, opipe, len, flags);
+
+ if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+ ret = -EFAULT;
+diff --git a/fs/stack.c b/fs/stack.c
+index 4a6f7f4..7eeef12 100644
+--- a/fs/stack.c
++++ b/fs/stack.c
+@@ -1,8 +1,20 @@
++/*
++ * Copyright (c) 2006-2009 Erez Zadok
++ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2006-2009 Stony Brook University
++ * Copyright (c) 2006-2009 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
+ #include <linux/module.h>
+ #include <linux/fs.h>
+ #include <linux/fs_stack.h>
+
+-/* does _NOT_ require i_mutex to be held.
++/*
++ * does _NOT_ require i_mutex to be held.
+ *
+ * This function cannot be inlined since i_size_{read,write} is rather
+ * heavy-weight on 32-bit systems
+diff --git a/fs/unionfs/Kconfig b/fs/unionfs/Kconfig
+new file mode 100644
+index 0000000..f3c1ac4
+--- /dev/null
++++ b/fs/unionfs/Kconfig
+@@ -0,0 +1,24 @@
++config UNION_FS
++ tristate "Union file system (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ help
++ Unionfs is a stackable unification file system, which appears to
++ merge the contents of several directories (branches), while keeping
++ their physical content separate.
++
++ See <http://unionfs.filesystems.org> for details
++
++config UNION_FS_XATTR
++ bool "Unionfs extended attributes"
++ depends on UNION_FS
++ help
++ Extended attributes are name:value pairs associated with inodes by
++ the kernel or by users (see the attr(5) manual page).
++
++ If unsure, say N.
++
++config UNION_FS_DEBUG
++ bool "Debug Unionfs"
++ depends on UNION_FS
++ help
++ If you say Y here, you can turn on debugging output from Unionfs.
+diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
+new file mode 100644
+index 0000000..86c32ba
+--- /dev/null
++++ b/fs/unionfs/Makefile
+@@ -0,0 +1,17 @@
++UNIONFS_VERSION="2.5.7 (for 2.6.36)"
++
++EXTRA_CFLAGS += -DUNIONFS_VERSION=\"$(UNIONFS_VERSION)\"
++
++obj-$(CONFIG_UNION_FS) += unionfs.o
++
++unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
++ rdstate.o copyup.o dirhelper.o rename.o unlink.o \
++ lookup.o commonfops.o dirfops.o sioq.o mmap.o whiteout.o
++
++unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
++
++unionfs-$(CONFIG_UNION_FS_DEBUG) += debug.o
++
++ifeq ($(CONFIG_UNION_FS_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
+new file mode 100644
+index 0000000..51ea65e
+--- /dev/null
++++ b/fs/unionfs/commonfops.c
+@@ -0,0 +1,896 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * 1) Copyup the file
++ * 2) Rename the file to '.unionfs<original inode#><counter>' - obviously
++ * stolen from NFS's silly rename
++ */
++static int copyup_deleted_file(struct file *file, struct dentry *dentry,
++ struct dentry *parent, int bstart, int bindex)
++{
++ static unsigned int counter;
++ const int i_inosize = sizeof(dentry->d_inode->i_ino) * 2;
++ const int countersize = sizeof(counter) * 2;
++ const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1;
++ char name[nlen + 1];
++ int err;
++ struct dentry *tmp_dentry = NULL;
++ struct dentry *lower_dentry;
++ struct dentry *lower_dir_dentry = NULL;
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bstart);
++
++ sprintf(name, ".unionfs%*.*lx",
++ i_inosize, i_inosize, lower_dentry->d_inode->i_ino);
++
++ /*
++ * Loop, looking for an unused temp name to copyup to.
++ *
++ * It's somewhat silly that we look for a free temp tmp name in the
++ * source branch (bstart) instead of the dest branch (bindex), where
++ * the final name will be created. We _will_ catch it if somehow
++ * the name exists in the dest branch, but it'd be nice to catch it
++ * sooner than later.
++ */
++retry:
++ tmp_dentry = NULL;
++ do {
++ char *suffix = name + nlen - countersize;
++
++ dput(tmp_dentry);
++ counter++;
++ sprintf(suffix, "%*.*x", countersize, countersize, counter);
++
++ pr_debug("unionfs: trying to rename %s to %s\n",
++ dentry->d_name.name, name);
++
++ tmp_dentry = lookup_lck_len(name, lower_dentry->d_parent,
++ nlen);
++ if (IS_ERR(tmp_dentry)) {
++ err = PTR_ERR(tmp_dentry);
++ goto out;
++ }
++ } while (tmp_dentry->d_inode != NULL); /* need negative dentry */
++ dput(tmp_dentry);
++
++ err = copyup_named_file(parent->d_inode, file, name, bstart, bindex,
++ i_size_read(file->f_path.dentry->d_inode));
++ if (err) {
++ if (unlikely(err == -EEXIST))
++ goto retry;
++ goto out;
++ }
++
++ /* bring it to the same state as an unlinked file */
++ lower_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
++ if (!unionfs_lower_inode_idx(dentry->d_inode, bindex)) {
++ atomic_inc(&lower_dentry->d_inode->i_count);
++ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
++ lower_dentry->d_inode);
++ }
++ lower_dir_dentry = lock_parent(lower_dentry);
++ err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
++ unlock_dir(lower_dir_dentry);
++
++out:
++ if (!err)
++ unionfs_check_dentry(dentry);
++ return err;
++}
++
++/*
++ * put all references held by upper struct file and free lower file pointer
++ * array
++ */
++static void cleanup_file(struct file *file)
++{
++ int bindex, bstart, bend;
++ struct file **lower_files;
++ struct file *lower_file;
++ struct super_block *sb = file->f_path.dentry->d_sb;
++
++ lower_files = UNIONFS_F(file)->lower_files;
++ bstart = fbstart(file);
++ bend = fbend(file);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ int i; /* holds (possibly) updated branch index */
++ int old_bid;
++
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ if (!lower_file)
++ continue;
++
++ /*
++ * Find new index of matching branch with an open
++ * file, since branches could have been added or
++ * deleted causing the one with open files to shift.
++ */
++ old_bid = UNIONFS_F(file)->saved_branch_ids[bindex];
++ i = branch_id_to_idx(sb, old_bid);
++ if (unlikely(i < 0)) {
++ printk(KERN_ERR "unionfs: no superblock for "
++ "file %p\n", file);
++ continue;
++ }
++
++ /* decrement count of open files */
++ branchput(sb, i);
++ /*
++ * fput will perform an mntput for us on the correct branch.
++ * Although we're using the file's old branch configuration,
++ * bindex, which is the old index, correctly points to the
++ * right branch in the file's branch list. In other words,
++ * we're going to mntput the correct branch even if branches
++ * have been added/removed.
++ */
++ fput(lower_file);
++ UNIONFS_F(file)->lower_files[bindex] = NULL;
++ UNIONFS_F(file)->saved_branch_ids[bindex] = -1;
++ }
++
++ UNIONFS_F(file)->lower_files = NULL;
++ kfree(lower_files);
++ kfree(UNIONFS_F(file)->saved_branch_ids);
++ /* set to NULL because caller needs to know if to kfree on error */
++ UNIONFS_F(file)->saved_branch_ids = NULL;
++}
++
++/* open all lower files for a given file */
++static int open_all_files(struct file *file)
++{
++ int bindex, bstart, bend, err = 0;
++ struct file *lower_file;
++ struct dentry *lower_dentry;
++ struct dentry *dentry = file->f_path.dentry;
++ struct super_block *sb = dentry->d_sb;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++
++ dget(lower_dentry);
++ unionfs_mntget(dentry, bindex);
++ branchget(sb, bindex);
++
++ lower_file =
++ dentry_open(lower_dentry,
++ unionfs_lower_mnt_idx(dentry, bindex),
++ file->f_flags, current_cred());
++ if (IS_ERR(lower_file)) {
++ branchput(sb, bindex);
++ err = PTR_ERR(lower_file);
++ goto out;
++ } else {
++ unionfs_set_lower_file_idx(file, bindex, lower_file);
++ }
++ }
++out:
++ return err;
++}
++
++/* open the highest priority file for a given upper file */
++static int open_highest_file(struct file *file, bool willwrite)
++{
++ int bindex, bstart, bend, err = 0;
++ struct file *lower_file;
++ struct dentry *lower_dentry;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent = dget_parent(dentry);
++ struct inode *parent_inode = parent->d_inode;
++ struct super_block *sb = dentry->d_sb;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++ if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) {
++ for (bindex = bstart - 1; bindex >= 0; bindex--) {
++ err = copyup_file(parent_inode, file, bstart, bindex,
++ i_size_read(dentry->d_inode));
++ if (!err)
++ break;
++ }
++ atomic_set(&UNIONFS_F(file)->generation,
++ atomic_read(&UNIONFS_I(dentry->d_inode)->
++ generation));
++ goto out;
++ }
++
++ dget(lower_dentry);
++ unionfs_mntget(dentry, bstart);
++ lower_file = dentry_open(lower_dentry,
++ unionfs_lower_mnt_idx(dentry, bstart),
++ file->f_flags, current_cred());
++ if (IS_ERR(lower_file)) {
++ err = PTR_ERR(lower_file);
++ goto out;
++ }
++ branchget(sb, bstart);
++ unionfs_set_lower_file(file, lower_file);
++ /* Fix up the position. */
++ lower_file->f_pos = file->f_pos;
++
++ memcpy(&lower_file->f_ra, &file->f_ra, sizeof(struct file_ra_state));
++out:
++ dput(parent);
++ return err;
++}
++
++/* perform a delayed copyup of a read-write file on a read-only branch */
++static int do_delayed_copyup(struct file *file, struct dentry *parent)
++{
++ int bindex, bstart, bend, err = 0;
++ struct dentry *dentry = file->f_path.dentry;
++ struct inode *parent_inode = parent->d_inode;
++
++ bstart = fbstart(file);
++ bend = fbend(file);
++
++ BUG_ON(!S_ISREG(dentry->d_inode->i_mode));
++
++ unionfs_check_file(file);
++ for (bindex = bstart - 1; bindex >= 0; bindex--) {
++ if (!d_deleted(dentry))
++ err = copyup_file(parent_inode, file, bstart,
++ bindex,
++ i_size_read(dentry->d_inode));
++ else
++ err = copyup_deleted_file(file, dentry, parent,
++ bstart, bindex);
++ /* if succeeded, set lower open-file flags and break */
++ if (!err) {
++ struct file *lower_file;
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ lower_file->f_flags = file->f_flags;
++ break;
++ }
++ }
++ if (err || (bstart <= fbstart(file)))
++ goto out;
++ bend = fbend(file);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ if (unionfs_lower_file_idx(file, bindex)) {
++ branchput(dentry->d_sb, bindex);
++ fput(unionfs_lower_file_idx(file, bindex));
++ unionfs_set_lower_file_idx(file, bindex, NULL);
++ }
++ }
++ path_put_lowers(dentry, bstart, bend, false);
++ iput_lowers(dentry->d_inode, bstart, bend, false);
++ /* for reg file, we only open it "once" */
++ fbend(file) = fbstart(file);
++ dbend(dentry) = dbstart(dentry);
++ ibend(dentry->d_inode) = ibstart(dentry->d_inode);
++
++out:
++ unionfs_check_file(file);
++ return err;
++}
++
++/*
++ * Helper function for unionfs_file_revalidate/locked.
++ * Expects dentry/parent to be locked already, and revalidated.
++ */
++static int __unionfs_file_revalidate(struct file *file, struct dentry *dentry,
++ struct dentry *parent,
++ struct super_block *sb, int sbgen,
++ int dgen, bool willwrite)
++{
++ int fgen;
++ int bstart, bend, orig_brid;
++ int size;
++ int err = 0;
++
++ fgen = atomic_read(&UNIONFS_F(file)->generation);
++
++ /*
++ * There are two cases we are interested in. The first is if the
++ * generation is lower than the super-block. The second is if
++ * someone has copied up this file from underneath us, we also need
++ * to refresh things.
++ */
++ if (d_deleted(dentry) ||
++ (sbgen <= fgen &&
++ dbstart(dentry) == fbstart(file) &&
++ unionfs_lower_file(file)))
++ goto out_may_copyup;
++
++ /* save orig branch ID */
++ orig_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
++
++ /* First we throw out the existing files. */
++ cleanup_file(file);
++
++ /* Now we reopen the file(s) as in unionfs_open. */
++ bstart = fbstart(file) = dbstart(dentry);
++ bend = fbend(file) = dbend(dentry);
++
++ size = sizeof(struct file *) * sbmax(sb);
++ UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file)->lower_files)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ size = sizeof(int) * sbmax(sb);
++ UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ if (S_ISDIR(dentry->d_inode->i_mode)) {
++ /* We need to open all the files. */
++ err = open_all_files(file);
++ if (err)
++ goto out;
++ } else {
++ int new_brid;
++ /* We only open the highest priority branch. */
++ err = open_highest_file(file, willwrite);
++ if (err)
++ goto out;
++ new_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
++ if (unlikely(new_brid != orig_brid && sbgen > fgen)) {
++ /*
++ * If we re-opened the file on a different branch
++ * than the original one, and this was due to a new
++ * branch inserted, then update the mnt counts of
++ * the old and new branches accordingly.
++ */
++ unionfs_mntget(dentry, bstart);
++ unionfs_mntput(sb->s_root,
++ branch_id_to_idx(sb, orig_brid));
++ }
++ /* regular files have only one open lower file */
++ fbend(file) = fbstart(file);
++ }
++ atomic_set(&UNIONFS_F(file)->generation,
++ atomic_read(&UNIONFS_I(dentry->d_inode)->generation));
++
++out_may_copyup:
++ /* Copyup on the first write to a file on a readonly branch. */
++ if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
++ !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
++ is_robranch(dentry)) {
++ pr_debug("unionfs: do delay copyup of \"%s\"\n",
++ dentry->d_name.name);
++ err = do_delayed_copyup(file, parent);
++ /* regular files have only one open lower file */
++ if (!err && !S_ISDIR(dentry->d_inode->i_mode))
++ fbend(file) = fbstart(file);
++ }
++
++out:
++ if (err) {
++ kfree(UNIONFS_F(file)->lower_files);
++ kfree(UNIONFS_F(file)->saved_branch_ids);
++ }
++ return err;
++}
++
++/*
++ * Revalidate the struct file
++ * @file: file to revalidate
++ * @parent: parent dentry (locked by caller)
++ * @willwrite: true if caller may cause changes to the file; false otherwise.
++ * Caller must lock/unlock dentry's branch configuration.
++ */
++int unionfs_file_revalidate(struct file *file, struct dentry *parent,
++ bool willwrite)
++{
++ struct super_block *sb;
++ struct dentry *dentry;
++ int sbgen, dgen;
++ int err = 0;
++
++ dentry = file->f_path.dentry;
++ sb = dentry->d_sb;
++ verify_locked(dentry);
++ verify_locked(parent);
++
++ /*
++ * First revalidate the dentry inside struct file,
++ * but not unhashed dentries.
++ */
++ if (!d_deleted(dentry) &&
++ !__unionfs_d_revalidate(dentry, parent, willwrite)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
++ dgen = atomic_read(&UNIONFS_D(dentry)->generation);
++
++ if (unlikely(sbgen > dgen)) { /* XXX: should never happen */
++ pr_debug("unionfs: failed to revalidate dentry (%s)\n",
++ dentry->d_name.name);
++ err = -ESTALE;
++ goto out;
++ }
++
++ err = __unionfs_file_revalidate(file, dentry, parent, sb,
++ sbgen, dgen, willwrite);
++out:
++ return err;
++}
++
++/* unionfs_open helper function: open a directory */
++static int __open_dir(struct inode *inode, struct file *file)
++{
++ struct dentry *lower_dentry;
++ struct file *lower_file;
++ int bindex, bstart, bend;
++ struct vfsmount *mnt;
++
++ bstart = fbstart(file) = dbstart(file->f_path.dentry);
++ bend = fbend(file) = dbend(file->f_path.dentry);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry =
++ unionfs_lower_dentry_idx(file->f_path.dentry, bindex);
++ if (!lower_dentry)
++ continue;
++
++ dget(lower_dentry);
++ unionfs_mntget(file->f_path.dentry, bindex);
++ mnt = unionfs_lower_mnt_idx(file->f_path.dentry, bindex);
++ lower_file = dentry_open(lower_dentry, mnt, file->f_flags,
++ current_cred());
++ if (IS_ERR(lower_file))
++ return PTR_ERR(lower_file);
++
++ unionfs_set_lower_file_idx(file, bindex, lower_file);
++
++ /*
++ * The branchget goes after the open, because otherwise
++ * we would miss the reference on release.
++ */
++ branchget(inode->i_sb, bindex);
++ }
++
++ return 0;
++}
++
++/* unionfs_open helper function: open a file */
++static int __open_file(struct inode *inode, struct file *file,
++ struct dentry *parent)
++{
++ struct dentry *lower_dentry;
++ struct file *lower_file;
++ int lower_flags;
++ int bindex, bstart, bend;
++
++ lower_dentry = unionfs_lower_dentry(file->f_path.dentry);
++ lower_flags = file->f_flags;
++
++ bstart = fbstart(file) = dbstart(file->f_path.dentry);
++ bend = fbend(file) = dbend(file->f_path.dentry);
++
++ /*
++ * check for the permission for lower file. If the error is
++ * COPYUP_ERR, copyup the file.
++ */
++ if (lower_dentry->d_inode && is_robranch(file->f_path.dentry)) {
++ /*
++ * if the open will change the file, copy it up otherwise
++ * defer it.
++ */
++ if (lower_flags & O_TRUNC) {
++ int size = 0;
++ int err = -EROFS;
++
++ /* copyup the file */
++ for (bindex = bstart - 1; bindex >= 0; bindex--) {
++ err = copyup_file(parent->d_inode, file,
++ bstart, bindex, size);
++ if (!err)
++ break;
++ }
++ return err;
++ } else {
++ /*
++ * turn off writeable flags, to force delayed copyup
++ * by caller.
++ */
++ lower_flags &= ~(OPEN_WRITE_FLAGS);
++ }
++ }
++
++ dget(lower_dentry);
++
++ /*
++ * dentry_open will decrement mnt refcnt if err.
++ * otherwise fput() will do an mntput() for us upon file close.
++ */
++ unionfs_mntget(file->f_path.dentry, bstart);
++ lower_file =
++ dentry_open(lower_dentry,
++ unionfs_lower_mnt_idx(file->f_path.dentry, bstart),
++ lower_flags, current_cred());
++ if (IS_ERR(lower_file))
++ return PTR_ERR(lower_file);
++
++ unionfs_set_lower_file(file, lower_file);
++ branchget(inode->i_sb, bstart);
++
++ return 0;
++}
++
++int unionfs_open(struct inode *inode, struct file *file)
++{
++ int err = 0;
++ struct file *lower_file = NULL;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ int bindex = 0, bstart = 0, bend = 0;
++ int size;
++ int valid = 0;
++
++ unionfs_read_lock(inode->i_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ /* don't open unhashed/deleted files */
++ if (d_deleted(dentry)) {
++ err = -ENOENT;
++ goto out_nofree;
++ }
++
++ /* XXX: should I change 'false' below to the 'willwrite' flag? */
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out_nofree;
++ }
++
++ file->private_data =
++ kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file))) {
++ err = -ENOMEM;
++ goto out_nofree;
++ }
++ fbstart(file) = -1;
++ fbend(file) = -1;
++ atomic_set(&UNIONFS_F(file)->generation,
++ atomic_read(&UNIONFS_I(inode)->generation));
++
++ size = sizeof(struct file *) * sbmax(inode->i_sb);
++ UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file)->lower_files)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ size = sizeof(int) * sbmax(inode->i_sb);
++ UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ bstart = fbstart(file) = dbstart(dentry);
++ bend = fbend(file) = dbend(dentry);
++
++ /*
++ * open all directories and make the unionfs file struct point to
++ * these lower file structs
++ */
++ if (S_ISDIR(inode->i_mode))
++ err = __open_dir(inode, file); /* open a dir */
++ else
++ err = __open_file(inode, file, parent); /* open a file */
++
++ /* freeing the allocated resources, and fput the opened files */
++ if (err) {
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ if (!lower_file)
++ continue;
++
++ branchput(dentry->d_sb, bindex);
++ /* fput calls dput for lower_dentry */
++ fput(lower_file);
++ }
++ }
++
++out:
++ if (err) {
++ kfree(UNIONFS_F(file)->lower_files);
++ kfree(UNIONFS_F(file)->saved_branch_ids);
++ kfree(UNIONFS_F(file));
++ }
++out_nofree:
++ if (!err) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_copy_attr_times(inode);
++ unionfs_check_file(file);
++ unionfs_check_inode(inode);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(inode->i_sb);
++ return err;
++}
++
++/*
++ * release all lower object references & free the file info structure
++ *
++ * No need to grab sb info's rwsem.
++ */
++int unionfs_file_release(struct inode *inode, struct file *file)
++{
++ struct file *lower_file = NULL;
++ struct unionfs_file_info *fileinfo;
++ struct unionfs_inode_info *inodeinfo;
++ struct super_block *sb = inode->i_sb;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ int bindex, bstart, bend;
++ int fgen, err = 0;
++
++ /*
++ * Since mm/memory.c:might_fault() (under PROVE_LOCKING) was
++ * modified in 2.6.29-rc1 to call might_lock_read on mmap_sem, this
++ * has been causing false positives in file system stacking layers.
++ * In particular, our ->mmap is called after sys_mmap2 already holds
++ * mmap_sem, then we lock our own mutexes; but earlier, it's
++ * possible for lockdep to have locked our mutexes first, and then
++ * we call a lower ->readdir which could call might_fault. The
++ * different ordering of the locks is what lockdep complains about
++ * -- unnecessarily. Therefore, we have no choice but to tell
++ * lockdep to temporarily turn off lockdep here. Note: the comments
++ * inside might_sleep also suggest that it would have been
++ * nicer to only annotate paths that needs that might_lock_read.
++ */
++ lockdep_off();
++ unionfs_read_lock(sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ /*
++ * We try to revalidate, but the VFS ignores return return values
++ * from file->release, so we must always try to succeed here,
++ * including to do the kfree and dput below. So if revalidation
++ * failed, all we can do is print some message and keep going.
++ */
++ err = unionfs_file_revalidate(file, parent,
++ UNIONFS_F(file)->wrote_to_file);
++ if (!err)
++ unionfs_check_file(file);
++ fileinfo = UNIONFS_F(file);
++ BUG_ON(file->f_path.dentry->d_inode != inode);
++ inodeinfo = UNIONFS_I(inode);
++
++ /* fput all the lower files */
++ fgen = atomic_read(&fileinfo->generation);
++ bstart = fbstart(file);
++ bend = fbend(file);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_file = unionfs_lower_file_idx(file, bindex);
++
++ if (lower_file) {
++ unionfs_set_lower_file_idx(file, bindex, NULL);
++ fput(lower_file);
++ branchput(sb, bindex);
++ }
++
++ /* if there are no more refs to the dentry, dput it */
++ if (d_deleted(dentry)) {
++ dput(unionfs_lower_dentry_idx(dentry, bindex));
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ }
++ }
++
++ kfree(fileinfo->lower_files);
++ kfree(fileinfo->saved_branch_ids);
++
++ if (fileinfo->rdstate) {
++ fileinfo->rdstate->access = jiffies;
++ spin_lock(&inodeinfo->rdlock);
++ inodeinfo->rdcount++;
++ list_add_tail(&fileinfo->rdstate->cache,
++ &inodeinfo->readdircache);
++ mark_inode_dirty(inode);
++ spin_unlock(&inodeinfo->rdlock);
++ fileinfo->rdstate = NULL;
++ }
++ kfree(fileinfo);
++
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(sb);
++ lockdep_on();
++ return err;
++}
++
++/* pass the ioctl to the lower fs */
++static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct file *lower_file;
++ int err;
++
++ lower_file = unionfs_lower_file(file);
++
++ err = -ENOTTY;
++ if (!lower_file || !lower_file->f_op)
++ goto out;
++ if (lower_file->f_op->unlocked_ioctl) {
++ err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
++#ifdef CONFIG_COMPAT
++ } else if (lower_file->f_op->ioctl) {
++ err = lower_file->f_op->compat_ioctl(
++ lower_file->f_path.dentry->d_inode,
++ lower_file, cmd, arg);
++#endif
++ }
++
++out:
++ return err;
++}
++
++/*
++ * return to user-space the branch indices containing the file in question
++ *
++ * We use fd_set and therefore we are limited to the number of the branches
++ * to FD_SETSIZE, which is currently 1024 - plenty for most people
++ */
++static int unionfs_ioctl_queryfile(struct file *file, struct dentry *parent,
++ unsigned int cmd, unsigned long arg)
++{
++ int err = 0;
++ fd_set branchlist;
++ int bstart = 0, bend = 0, bindex = 0;
++ int orig_bstart, orig_bend;
++ struct dentry *dentry, *lower_dentry;
++ struct vfsmount *mnt;
++
++ dentry = file->f_path.dentry;
++ orig_bstart = dbstart(dentry);
++ orig_bend = dbend(dentry);
++ err = unionfs_partial_lookup(dentry, parent);
++ if (err)
++ goto out;
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ FD_ZERO(&branchlist);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ if (likely(lower_dentry->d_inode))
++ FD_SET(bindex, &branchlist);
++ /* purge any lower objects after partial_lookup */
++ if (bindex < orig_bstart || bindex > orig_bend) {
++ dput(lower_dentry);
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
++ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
++ NULL);
++ mnt = unionfs_lower_mnt_idx(dentry, bindex);
++ if (!mnt)
++ continue;
++ unionfs_mntput(dentry, bindex);
++ unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
++ }
++ }
++ /* restore original dentry's offsets */
++ dbstart(dentry) = orig_bstart;
++ dbend(dentry) = orig_bend;
++ ibstart(dentry->d_inode) = orig_bstart;
++ ibend(dentry->d_inode) = orig_bend;
++
++ err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set));
++ if (unlikely(err))
++ err = -EFAULT;
++
++out:
++ return err < 0 ? err : bend;
++}
++
++long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ long err;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++
++ /* check if asked for local commands */
++ switch (cmd) {
++ case UNIONFS_IOCTL_INCGEN:
++ /* Increment the superblock generation count */
++ pr_info("unionfs: incgen ioctl deprecated; "
++ "use \"-o remount,incgen\"\n");
++ err = -ENOSYS;
++ break;
++
++ case UNIONFS_IOCTL_QUERYFILE:
++ /* Return list of branches containing the given file */
++ err = unionfs_ioctl_queryfile(file, parent, cmd, arg);
++ break;
++
++ default:
++ /* pass the ioctl down */
++ err = do_ioctl(file, cmd, arg);
++ break;
++ }
++
++out:
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++int unionfs_flush(struct file *file, fl_owner_t id)
++{
++ int err = 0;
++ struct file *lower_file = NULL;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ int bindex, bstart, bend;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent,
++ UNIONFS_F(file)->wrote_to_file);
++ if (unlikely(err))
++ goto out;
++ unionfs_check_file(file);
++
++ bstart = fbstart(file);
++ bend = fbend(file);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_file = unionfs_lower_file_idx(file, bindex);
++
++ if (lower_file && lower_file->f_op &&
++ lower_file->f_op->flush) {
++ err = lower_file->f_op->flush(lower_file, id);
++ if (err)
++ goto out;
++ }
++
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
+diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
+new file mode 100644
+index 0000000..bba3a75
+--- /dev/null
++++ b/fs/unionfs/copyup.c
+@@ -0,0 +1,896 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * For detailed explanation of copyup see:
++ * Documentation/filesystems/unionfs/concepts.txt
++ */
++
++#ifdef CONFIG_UNION_FS_XATTR
++/* copyup all extended attrs for a given dentry */
++static int copyup_xattrs(struct dentry *old_lower_dentry,
++ struct dentry *new_lower_dentry)
++{
++ int err = 0;
++ ssize_t list_size = -1;
++ char *name_list = NULL;
++ char *attr_value = NULL;
++ char *name_list_buf = NULL;
++
++ /* query the actual size of the xattr list */
++ list_size = vfs_listxattr(old_lower_dentry, NULL, 0);
++ if (list_size <= 0) {
++ err = list_size;
++ goto out;
++ }
++
++ /* allocate space for the actual list */
++ name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
++ if (unlikely(!name_list || IS_ERR(name_list))) {
++ err = PTR_ERR(name_list);
++ goto out;
++ }
++
++ name_list_buf = name_list; /* save for kfree at end */
++
++ /* now get the actual xattr list of the source file */
++ list_size = vfs_listxattr(old_lower_dentry, name_list, list_size);
++ if (list_size <= 0) {
++ err = list_size;
++ goto out;
++ }
++
++ /* allocate space to hold each xattr's value */
++ attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
++ if (unlikely(!attr_value || IS_ERR(attr_value))) {
++ err = PTR_ERR(name_list);
++ goto out;
++ }
++
++ /* in a loop, get and set each xattr from src to dst file */
++ while (*name_list) {
++ ssize_t size;
++
++ /* Lock here since vfs_getxattr doesn't lock for us */
++ mutex_lock(&old_lower_dentry->d_inode->i_mutex);
++ size = vfs_getxattr(old_lower_dentry, name_list,
++ attr_value, XATTR_SIZE_MAX);
++ mutex_unlock(&old_lower_dentry->d_inode->i_mutex);
++ if (size < 0) {
++ err = size;
++ goto out;
++ }
++ if (size > XATTR_SIZE_MAX) {
++ err = -E2BIG;
++ goto out;
++ }
++ /* Don't lock here since vfs_setxattr does it for us. */
++ err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
++ size, 0);
++ /*
++ * Selinux depends on "security.*" xattrs, so to maintain
++ * the security of copied-up files, if Selinux is active,
++ * then we must copy these xattrs as well. So we need to
++ * temporarily get FOWNER privileges.
++ * XXX: move entire copyup code to SIOQ.
++ */
++ if (err == -EPERM && !capable(CAP_FOWNER)) {
++ const struct cred *old_creds;
++ struct cred *new_creds;
++
++ new_creds = prepare_creds();
++ if (unlikely(!new_creds)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ cap_raise(new_creds->cap_effective, CAP_FOWNER);
++ old_creds = override_creds(new_creds);
++ err = vfs_setxattr(new_lower_dentry, name_list,
++ attr_value, size, 0);
++ revert_creds(old_creds);
++ }
++ if (err < 0)
++ goto out;
++ name_list += strlen(name_list) + 1;
++ }
++out:
++ unionfs_xattr_kfree(name_list_buf);
++ unionfs_xattr_kfree(attr_value);
++ /* Ignore if xattr isn't supported */
++ if (err == -ENOTSUPP || err == -EOPNOTSUPP)
++ err = 0;
++ return err;
++}
++#endif /* CONFIG_UNION_FS_XATTR */
++
++/*
++ * Determine the mode based on the copyup flags, and the existing dentry.
++ *
++ * Handle file systems which may not support certain options. For example
++ * jffs2 doesn't allow one to chmod a symlink. So we ignore such harmless
++ * errors, rather than propagating them up, which results in copyup errors
++ * and errors returned back to users.
++ */
++static int copyup_permissions(struct super_block *sb,
++ struct dentry *old_lower_dentry,
++ struct dentry *new_lower_dentry)
++{
++ struct inode *i = old_lower_dentry->d_inode;
++ struct iattr newattrs;
++ int err;
++
++ newattrs.ia_atime = i->i_atime;
++ newattrs.ia_mtime = i->i_mtime;
++ newattrs.ia_ctime = i->i_ctime;
++ newattrs.ia_gid = i->i_gid;
++ newattrs.ia_uid = i->i_uid;
++ newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME |
++ ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
++ ATTR_GID | ATTR_UID;
++ mutex_lock(&new_lower_dentry->d_inode->i_mutex);
++ err = notify_change(new_lower_dentry, &newattrs);
++ if (err)
++ goto out;
++
++ /* now try to change the mode and ignore EOPNOTSUPP on symlinks */
++ newattrs.ia_mode = i->i_mode;
++ newattrs.ia_valid = ATTR_MODE | ATTR_FORCE;
++ err = notify_change(new_lower_dentry, &newattrs);
++ if (err == -EOPNOTSUPP &&
++ S_ISLNK(new_lower_dentry->d_inode->i_mode)) {
++ printk(KERN_WARNING
++ "unionfs: changing \"%s\" symlink mode unsupported\n",
++ new_lower_dentry->d_name.name);
++ err = 0;
++ }
++
++out:
++ mutex_unlock(&new_lower_dentry->d_inode->i_mutex);
++ return err;
++}
++
++/*
++ * create the new device/file/directory - use copyup_permission to copyup
++ * times, and mode
++ *
++ * if the object being copied up is a regular file, the file is only created,
++ * the contents have to be copied up separately
++ */
++static int __copyup_ndentry(struct dentry *old_lower_dentry,
++ struct dentry *new_lower_dentry,
++ struct dentry *new_lower_parent_dentry,
++ char *symbuf)
++{
++ int err = 0;
++ umode_t old_mode = old_lower_dentry->d_inode->i_mode;
++ struct sioq_args args;
++
++ if (S_ISDIR(old_mode)) {
++ args.mkdir.parent = new_lower_parent_dentry->d_inode;
++ args.mkdir.dentry = new_lower_dentry;
++ args.mkdir.mode = old_mode;
++
++ run_sioq(__unionfs_mkdir, &args);
++ err = args.err;
++ } else if (S_ISLNK(old_mode)) {
++ args.symlink.parent = new_lower_parent_dentry->d_inode;
++ args.symlink.dentry = new_lower_dentry;
++ args.symlink.symbuf = symbuf;
++
++ run_sioq(__unionfs_symlink, &args);
++ err = args.err;
++ } else if (S_ISBLK(old_mode) || S_ISCHR(old_mode) ||
++ S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) {
++ args.mknod.parent = new_lower_parent_dentry->d_inode;
++ args.mknod.dentry = new_lower_dentry;
++ args.mknod.mode = old_mode;
++ args.mknod.dev = old_lower_dentry->d_inode->i_rdev;
++
++ run_sioq(__unionfs_mknod, &args);
++ err = args.err;
++ } else if (S_ISREG(old_mode)) {
++ struct nameidata nd;
++ err = init_lower_nd(&nd, LOOKUP_CREATE);
++ if (unlikely(err < 0))
++ goto out;
++ args.create.nd = &nd;
++ args.create.parent = new_lower_parent_dentry->d_inode;
++ args.create.dentry = new_lower_dentry;
++ args.create.mode = old_mode;
++
++ run_sioq(__unionfs_create, &args);
++ err = args.err;
++ release_lower_nd(&nd, err);
++ } else {
++ printk(KERN_CRIT "unionfs: unknown inode type %d\n",
++ old_mode);
++ BUG();
++ }
++
++out:
++ return err;
++}
++
++static int __copyup_reg_data(struct dentry *dentry,
++ struct dentry *new_lower_dentry, int new_bindex,
++ struct dentry *old_lower_dentry, int old_bindex,
++ struct file **copyup_file, loff_t len)
++{
++ struct super_block *sb = dentry->d_sb;
++ struct file *input_file;
++ struct file *output_file;
++ struct vfsmount *output_mnt;
++ mm_segment_t old_fs;
++ char *buf = NULL;
++ ssize_t read_bytes, write_bytes;
++ loff_t size;
++ int err = 0;
++
++ /* open old file */
++ unionfs_mntget(dentry, old_bindex);
++ branchget(sb, old_bindex);
++ /* dentry_open calls dput and mntput if it returns an error */
++ input_file = dentry_open(old_lower_dentry,
++ unionfs_lower_mnt_idx(dentry, old_bindex),
++ O_RDONLY | O_LARGEFILE, current_cred());
++ if (IS_ERR(input_file)) {
++ dput(old_lower_dentry);
++ err = PTR_ERR(input_file);
++ goto out;
++ }
++ if (unlikely(!input_file->f_op || !input_file->f_op->read)) {
++ err = -EINVAL;
++ goto out_close_in;
++ }
++
++ /* open new file */
++ dget(new_lower_dentry);
++ output_mnt = unionfs_mntget(sb->s_root, new_bindex);
++ branchget(sb, new_bindex);
++ output_file = dentry_open(new_lower_dentry, output_mnt,
++ O_RDWR | O_LARGEFILE, current_cred());
++ if (IS_ERR(output_file)) {
++ err = PTR_ERR(output_file);
++ goto out_close_in2;
++ }
++ if (unlikely(!output_file->f_op || !output_file->f_op->write)) {
++ err = -EINVAL;
++ goto out_close_out;
++ }
++
++ /* allocating a buffer */
++ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (unlikely(!buf)) {
++ err = -ENOMEM;
++ goto out_close_out;
++ }
++
++ input_file->f_pos = 0;
++ output_file->f_pos = 0;
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++
++ size = len;
++ err = 0;
++ do {
++ if (len >= PAGE_SIZE)
++ size = PAGE_SIZE;
++ else if ((len < PAGE_SIZE) && (len > 0))
++ size = len;
++
++ len -= PAGE_SIZE;
++
++ read_bytes =
++ input_file->f_op->read(input_file,
++ (char __user *)buf, size,
++ &input_file->f_pos);
++ if (read_bytes <= 0) {
++ err = read_bytes;
++ break;
++ }
++
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ write_bytes =
++ output_file->f_op->write(output_file,
++ (char __user *)buf,
++ read_bytes,
++ &output_file->f_pos);
++ lockdep_on();
++ if ((write_bytes < 0) || (write_bytes < read_bytes)) {
++ err = write_bytes;
++ break;
++ }
++ } while ((read_bytes > 0) && (len > 0));
++
++ set_fs(old_fs);
++
++ kfree(buf);
++
++ if (!err)
++ err = output_file->f_op->fsync(output_file, 0);
++
++ if (err)
++ goto out_close_out;
++
++ if (copyup_file) {
++ *copyup_file = output_file;
++ goto out_close_in;
++ }
++
++out_close_out:
++ fput(output_file);
++
++out_close_in2:
++ branchput(sb, new_bindex);
++
++out_close_in:
++ fput(input_file);
++
++out:
++ branchput(sb, old_bindex);
++
++ return err;
++}
++
++/*
++ * dput the lower references for old and new dentry & clear a lower dentry
++ * pointer
++ */
++static void __clear(struct dentry *dentry, struct dentry *old_lower_dentry,
++ int old_bstart, int old_bend,
++ struct dentry *new_lower_dentry, int new_bindex)
++{
++ /* get rid of the lower dentry and all its traces */
++ unionfs_set_lower_dentry_idx(dentry, new_bindex, NULL);
++ dbstart(dentry) = old_bstart;
++ dbend(dentry) = old_bend;
++
++ dput(new_lower_dentry);
++ dput(old_lower_dentry);
++}
++
++/*
++ * Copy up a dentry to a file of specified name.
++ *
++ * @dir: used to pull the ->i_sb to access other branches
++ * @dentry: the non-negative dentry whose lower_inode we should copy
++ * @bstart: the branch of the lower_inode to copy from
++ * @new_bindex: the branch to create the new file in
++ * @name: the name of the file to create
++ * @namelen: length of @name
++ * @copyup_file: the "struct file" to return (optional)
++ * @len: how many bytes to copy-up?
++ */
++int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart,
++ int new_bindex, const char *name, int namelen,
++ struct file **copyup_file, loff_t len)
++{
++ struct dentry *new_lower_dentry;
++ struct dentry *old_lower_dentry = NULL;
++ struct super_block *sb;
++ int err = 0;
++ int old_bindex;
++ int old_bstart;
++ int old_bend;
++ struct dentry *new_lower_parent_dentry = NULL;
++ mm_segment_t oldfs;
++ char *symbuf = NULL;
++
++ verify_locked(dentry);
++
++ old_bindex = bstart;
++ old_bstart = dbstart(dentry);
++ old_bend = dbend(dentry);
++
++ BUG_ON(new_bindex < 0);
++ BUG_ON(new_bindex >= old_bindex);
++
++ sb = dir->i_sb;
++
++ err = is_robranch_super(sb, new_bindex);
++ if (err)
++ goto out;
++
++ /* Create the directory structure above this dentry. */
++ new_lower_dentry = create_parents(dir, dentry, name, new_bindex);
++ if (IS_ERR(new_lower_dentry)) {
++ err = PTR_ERR(new_lower_dentry);
++ goto out;
++ }
++
++ old_lower_dentry = unionfs_lower_dentry_idx(dentry, old_bindex);
++ /* we conditionally dput this old_lower_dentry at end of function */
++ dget(old_lower_dentry);
++
++ /* For symlinks, we must read the link before we lock the directory. */
++ if (S_ISLNK(old_lower_dentry->d_inode->i_mode)) {
++
++ symbuf = kmalloc(PATH_MAX, GFP_KERNEL);
++ if (unlikely(!symbuf)) {
++ __clear(dentry, old_lower_dentry,
++ old_bstart, old_bend,
++ new_lower_dentry, new_bindex);
++ err = -ENOMEM;
++ goto out_free;
++ }
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = old_lower_dentry->d_inode->i_op->readlink(
++ old_lower_dentry,
++ (char __user *)symbuf,
++ PATH_MAX);
++ set_fs(oldfs);
++ if (err < 0) {
++ __clear(dentry, old_lower_dentry,
++ old_bstart, old_bend,
++ new_lower_dentry, new_bindex);
++ goto out_free;
++ }
++ symbuf[err] = '\0';
++ }
++
++ /* Now we lock the parent, and create the object in the new branch. */
++ new_lower_parent_dentry = lock_parent(new_lower_dentry);
++
++ /* create the new inode */
++ err = __copyup_ndentry(old_lower_dentry, new_lower_dentry,
++ new_lower_parent_dentry, symbuf);
++
++ if (err) {
++ __clear(dentry, old_lower_dentry,
++ old_bstart, old_bend,
++ new_lower_dentry, new_bindex);
++ goto out_unlock;
++ }
++
++ /* We actually copyup the file here. */
++ if (S_ISREG(old_lower_dentry->d_inode->i_mode))
++ err = __copyup_reg_data(dentry, new_lower_dentry, new_bindex,
++ old_lower_dentry, old_bindex,
++ copyup_file, len);
++ if (err)
++ goto out_unlink;
++
++ /* Set permissions. */
++ err = copyup_permissions(sb, old_lower_dentry, new_lower_dentry);
++ if (err)
++ goto out_unlink;
++
++#ifdef CONFIG_UNION_FS_XATTR
++ /* Selinux uses extended attributes for permissions. */
++ err = copyup_xattrs(old_lower_dentry, new_lower_dentry);
++ if (err)
++ goto out_unlink;
++#endif /* CONFIG_UNION_FS_XATTR */
++
++ /* do not allow files getting deleted to be re-interposed */
++ if (!d_deleted(dentry))
++ unionfs_reinterpose(dentry);
++
++ goto out_unlock;
++
++out_unlink:
++ /*
++ * copyup failed, because we possibly ran out of space or
++ * quota, or something else happened so let's unlink; we don't
++ * really care about the return value of vfs_unlink
++ */
++ vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry);
++
++ if (copyup_file) {
++ /* need to close the file */
++
++ fput(*copyup_file);
++ branchput(sb, new_bindex);
++ }
++
++ /*
++ * TODO: should we reset the error to something like -EIO?
++ *
++ * If we don't reset, the user may get some nonsensical errors, but
++ * on the other hand, if we reset to EIO, we guarantee that the user
++ * will get a "confusing" error message.
++ */
++
++out_unlock:
++ unlock_dir(new_lower_parent_dentry);
++
++out_free:
++ /*
++ * If old_lower_dentry was not a file, then we need to dput it. If
++ * it was a file, then it was already dput indirectly by other
++ * functions we call above which operate on regular files.
++ */
++ if (old_lower_dentry && old_lower_dentry->d_inode &&
++ !S_ISREG(old_lower_dentry->d_inode->i_mode))
++ dput(old_lower_dentry);
++ kfree(symbuf);
++
++ if (err) {
++ /*
++ * if directory creation succeeded, but inode copyup failed,
++ * then purge new dentries.
++ */
++ if (dbstart(dentry) < old_bstart &&
++ ibstart(dentry->d_inode) > dbstart(dentry))
++ __clear(dentry, NULL, old_bstart, old_bend,
++ unionfs_lower_dentry(dentry), dbstart(dentry));
++ goto out;
++ }
++ if (!S_ISDIR(dentry->d_inode->i_mode)) {
++ unionfs_postcopyup_release(dentry);
++ if (!unionfs_lower_inode(dentry->d_inode)) {
++ /*
++ * If we got here, then we copied up to an
++ * unlinked-open file, whose name is .unionfsXXXXX.
++ */
++ struct inode *inode = new_lower_dentry->d_inode;
++ atomic_inc(&inode->i_count);
++ unionfs_set_lower_inode_idx(dentry->d_inode,
++ ibstart(dentry->d_inode),
++ inode);
++ }
++ }
++ unionfs_postcopyup_setmnt(dentry);
++ /* sync inode times from copied-up inode to our inode */
++ unionfs_copy_attr_times(dentry->d_inode);
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++out:
++ return err;
++}
++
++/*
++ * This function creates a copy of a file represented by 'file' which
++ * currently resides in branch 'bstart' to branch 'new_bindex.' The copy
++ * will be named "name".
++ */
++int copyup_named_file(struct inode *dir, struct file *file, char *name,
++ int bstart, int new_bindex, loff_t len)
++{
++ int err = 0;
++ struct file *output_file = NULL;
++
++ err = copyup_dentry(dir, file->f_path.dentry, bstart, new_bindex,
++ name, strlen(name), &output_file, len);
++ if (!err) {
++ fbstart(file) = new_bindex;
++ unionfs_set_lower_file_idx(file, new_bindex, output_file);
++ }
++
++ return err;
++}
++
++/*
++ * This function creates a copy of a file represented by 'file' which
++ * currently resides in branch 'bstart' to branch 'new_bindex'.
++ */
++int copyup_file(struct inode *dir, struct file *file, int bstart,
++ int new_bindex, loff_t len)
++{
++ int err = 0;
++ struct file *output_file = NULL;
++ struct dentry *dentry = file->f_path.dentry;
++
++ err = copyup_dentry(dir, dentry, bstart, new_bindex,
++ dentry->d_name.name, dentry->d_name.len,
++ &output_file, len);
++ if (!err) {
++ fbstart(file) = new_bindex;
++ unionfs_set_lower_file_idx(file, new_bindex, output_file);
++ }
++
++ return err;
++}
++
++/* purge a dentry's lower-branch states (dput/mntput, etc.) */
++static void __cleanup_dentry(struct dentry *dentry, int bindex,
++ int old_bstart, int old_bend)
++{
++ int loop_start;
++ int loop_end;
++ int new_bstart = -1;
++ int new_bend = -1;
++ int i;
++
++ loop_start = min(old_bstart, bindex);
++ loop_end = max(old_bend, bindex);
++
++ /*
++ * This loop sets the bstart and bend for the new dentry by
++ * traversing from left to right. It also dputs all negative
++ * dentries except bindex
++ */
++ for (i = loop_start; i <= loop_end; i++) {
++ if (!unionfs_lower_dentry_idx(dentry, i))
++ continue;
++
++ if (i == bindex) {
++ new_bend = i;
++ if (new_bstart < 0)
++ new_bstart = i;
++ continue;
++ }
++
++ if (!unionfs_lower_dentry_idx(dentry, i)->d_inode) {
++ dput(unionfs_lower_dentry_idx(dentry, i));
++ unionfs_set_lower_dentry_idx(dentry, i, NULL);
++
++ unionfs_mntput(dentry, i);
++ unionfs_set_lower_mnt_idx(dentry, i, NULL);
++ } else {
++ if (new_bstart < 0)
++ new_bstart = i;
++ new_bend = i;
++ }
++ }
++
++ if (new_bstart < 0)
++ new_bstart = bindex;
++ if (new_bend < 0)
++ new_bend = bindex;
++ dbstart(dentry) = new_bstart;
++ dbend(dentry) = new_bend;
++
++}
++
++/* set lower inode ptr and update bstart & bend if necessary */
++static void __set_inode(struct dentry *upper, struct dentry *lower,
++ int bindex)
++{
++ unionfs_set_lower_inode_idx(upper->d_inode, bindex,
++ igrab(lower->d_inode));
++ if (likely(ibstart(upper->d_inode) > bindex))
++ ibstart(upper->d_inode) = bindex;
++ if (likely(ibend(upper->d_inode) < bindex))
++ ibend(upper->d_inode) = bindex;
++
++}
++
++/* set lower dentry ptr and update bstart & bend if necessary */
++static void __set_dentry(struct dentry *upper, struct dentry *lower,
++ int bindex)
++{
++ unionfs_set_lower_dentry_idx(upper, bindex, lower);
++ if (likely(dbstart(upper) > bindex))
++ dbstart(upper) = bindex;
++ if (likely(dbend(upper) < bindex))
++ dbend(upper) = bindex;
++}
++
++/*
++ * This function replicates the directory structure up-to given dentry
++ * in the bindex branch.
++ */
++struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
++ const char *name, int bindex)
++{
++ int err;
++ struct dentry *child_dentry;
++ struct dentry *parent_dentry;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *lower_dentry = NULL;
++ const char *childname;
++ unsigned int childnamelen;
++ int nr_dentry;
++ int count = 0;
++ int old_bstart;
++ int old_bend;
++ struct dentry **path = NULL;
++ struct super_block *sb;
++
++ verify_locked(dentry);
++
++ err = is_robranch_super(dir->i_sb, bindex);
++ if (err) {
++ lower_dentry = ERR_PTR(err);
++ goto out;
++ }
++
++ old_bstart = dbstart(dentry);
++ old_bend = dbend(dentry);
++
++ lower_dentry = ERR_PTR(-ENOMEM);
++
++ /* There is no sense allocating any less than the minimum. */
++ nr_dentry = 1;
++ path = kmalloc(nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
++ if (unlikely(!path))
++ goto out;
++
++ /* assume the negative dentry of unionfs as the parent dentry */
++ parent_dentry = dentry;
++
++ /*
++ * This loop finds the first parent that exists in the given branch.
++ * We start building the directory structure from there. At the end
++ * of the loop, the following should hold:
++ * - child_dentry is the first nonexistent child
++ * - parent_dentry is the first existent parent
++ * - path[0] is the = deepest child
++ * - path[count] is the first child to create
++ */
++ do {
++ child_dentry = parent_dentry;
++
++ /* find the parent directory dentry in unionfs */
++ parent_dentry = dget_parent(child_dentry);
++
++ /* find out the lower_parent_dentry in the given branch */
++ lower_parent_dentry =
++ unionfs_lower_dentry_idx(parent_dentry, bindex);
++
++ /* grow path table */
++ if (count == nr_dentry) {
++ void *p;
++
++ nr_dentry *= 2;
++ p = krealloc(path, nr_dentry * sizeof(struct dentry *),
++ GFP_KERNEL);
++ if (unlikely(!p)) {
++ lower_dentry = ERR_PTR(-ENOMEM);
++ goto out;
++ }
++ path = p;
++ }
++
++ /* store the child dentry */
++ path[count++] = child_dentry;
++ } while (!lower_parent_dentry);
++ count--;
++
++ sb = dentry->d_sb;
++
++ /*
++ * This code goes between the begin/end labels and basically
++ * emulates a while(child_dentry != dentry), only cleaner and
++ * shorter than what would be a much longer while loop.
++ */
++begin:
++ /* get lower parent dir in the current branch */
++ lower_parent_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex);
++ dput(parent_dentry);
++
++ /* init the values to lookup */
++ childname = child_dentry->d_name.name;
++ childnamelen = child_dentry->d_name.len;
++
++ if (child_dentry != dentry) {
++ /* lookup child in the underlying file system */
++ lower_dentry = lookup_lck_len(childname, lower_parent_dentry,
++ childnamelen);
++ if (IS_ERR(lower_dentry))
++ goto out;
++ } else {
++ /*
++ * Is the name a whiteout of the child name ? lookup the
++ * whiteout child in the underlying file system
++ */
++ lower_dentry = lookup_lck_len(name, lower_parent_dentry,
++ strlen(name));
++ if (IS_ERR(lower_dentry))
++ goto out;
++
++ /* Replace the current dentry (if any) with the new one */
++ dput(unionfs_lower_dentry_idx(dentry, bindex));
++ unionfs_set_lower_dentry_idx(dentry, bindex,
++ lower_dentry);
++
++ __cleanup_dentry(dentry, bindex, old_bstart, old_bend);
++ goto out;
++ }
++
++ if (lower_dentry->d_inode) {
++ /*
++ * since this already exists we dput to avoid
++ * multiple references on the same dentry
++ */
++ dput(lower_dentry);
++ } else {
++ struct sioq_args args;
++
++ /* it's a negative dentry, create a new dir */
++ lower_parent_dentry = lock_parent(lower_dentry);
++
++ args.mkdir.parent = lower_parent_dentry->d_inode;
++ args.mkdir.dentry = lower_dentry;
++ args.mkdir.mode = child_dentry->d_inode->i_mode;
++
++ run_sioq(__unionfs_mkdir, &args);
++ err = args.err;
++
++ if (!err)
++ err = copyup_permissions(dir->i_sb, child_dentry,
++ lower_dentry);
++ unlock_dir(lower_parent_dentry);
++ if (err) {
++ dput(lower_dentry);
++ lower_dentry = ERR_PTR(err);
++ goto out;
++ }
++
++ }
++
++ __set_inode(child_dentry, lower_dentry, bindex);
++ __set_dentry(child_dentry, lower_dentry, bindex);
++ /*
++ * update times of this dentry, but also the parent, because if
++ * we changed, the parent may have changed too.
++ */
++ fsstack_copy_attr_times(parent_dentry->d_inode,
++ lower_parent_dentry->d_inode);
++ unionfs_copy_attr_times(child_dentry->d_inode);
++
++ parent_dentry = child_dentry;
++ child_dentry = path[--count];
++ goto begin;
++out:
++ /* cleanup any leftover locks from the do/while loop above */
++ if (IS_ERR(lower_dentry))
++ while (count)
++ dput(path[count--]);
++ kfree(path);
++ return lower_dentry;
++}
++
++/*
++ * Post-copyup helper to ensure we have valid mnts: set lower mnt of
++ * dentry+parents to the first parent node that has an mnt.
++ */
++void unionfs_postcopyup_setmnt(struct dentry *dentry)
++{
++ struct dentry *parent, *hasone;
++ int bindex = dbstart(dentry);
++
++ if (unionfs_lower_mnt_idx(dentry, bindex))
++ return;
++ hasone = dentry->d_parent;
++ /* this loop should stop at root dentry */
++ while (!unionfs_lower_mnt_idx(hasone, bindex))
++ hasone = hasone->d_parent;
++ parent = dentry;
++ while (!unionfs_lower_mnt_idx(parent, bindex)) {
++ unionfs_set_lower_mnt_idx(parent, bindex,
++ unionfs_mntget(hasone, bindex));
++ parent = parent->d_parent;
++ }
++}
++
++/*
++ * Post-copyup helper to release all non-directory source objects of a
++ * copied-up file. Regular files should have only one lower object.
++ */
++void unionfs_postcopyup_release(struct dentry *dentry)
++{
++ int bstart, bend;
++
++ BUG_ON(S_ISDIR(dentry->d_inode->i_mode));
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ path_put_lowers(dentry, bstart + 1, bend, false);
++ iput_lowers(dentry->d_inode, bstart + 1, bend, false);
++
++ dbend(dentry) = bstart;
++ ibend(dentry->d_inode) = ibstart(dentry->d_inode) = bstart;
++}
+diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
+new file mode 100644
+index 0000000..100d2c6
+--- /dev/null
++++ b/fs/unionfs/debug.c
+@@ -0,0 +1,532 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * Helper debugging functions for maintainers (and for users to report back
++ * useful information back to maintainers)
++ */
++
++/* it's always useful to know what part of the code called us */
++#define PRINT_CALLER(fname, fxn, line) \
++ do { \
++ if (!printed_caller) { \
++ pr_debug("PC:%s:%s:%d\n", (fname), (fxn), (line)); \
++ printed_caller = 1; \
++ } \
++ } while (0)
++
++/*
++ * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on
++ * the fan-out of various Unionfs objects. We check that no lower objects
++ * exist outside the start/end branch range; that all objects within are
++ * non-NULL (with some allowed exceptions); that for every lower file
++ * there's a lower dentry+inode; that the start/end ranges match for all
++ * corresponding lower objects; that open files/symlinks have only one lower
++ * objects, but directories can have several; and more.
++ */
++void __unionfs_check_inode(const struct inode *inode,
++ const char *fname, const char *fxn, int line)
++{
++ int bindex;
++ int istart, iend;
++ struct inode *lower_inode;
++ struct super_block *sb;
++ int printed_caller = 0;
++ void *poison_ptr;
++
++ /* for inodes now */
++ BUG_ON(!inode);
++ sb = inode->i_sb;
++ istart = ibstart(inode);
++ iend = ibend(inode);
++ /* don't check inode if no lower branches */
++ if (istart < 0 && iend < 0)
++ return;
++ if (unlikely(istart > iend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci0: inode=%p istart/end=%d:%d\n",
++ inode, istart, iend);
++ }
++ if (unlikely((istart == -1 && iend != -1) ||
++ (istart != -1 && iend == -1))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci1: inode=%p istart/end=%d:%d\n",
++ inode, istart, iend);
++ }
++ if (!S_ISDIR(inode->i_mode)) {
++ if (unlikely(iend != istart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci2: inode=%p istart=%d iend=%d\n",
++ inode, istart, iend);
++ }
++ }
++
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ if (unlikely(!UNIONFS_I(inode))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci3: no inode_info %p\n", inode);
++ return;
++ }
++ if (unlikely(!UNIONFS_I(inode)->lower_inodes)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci4: no lower_inodes %p\n", inode);
++ return;
++ }
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (lower_inode) {
++ memset(&poison_ptr, POISON_INUSE, sizeof(void *));
++ if (unlikely(bindex < istart || bindex > iend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci5: inode/linode=%p:%p bindex=%d "
++ "istart/end=%d:%d\n", inode,
++ lower_inode, bindex, istart, iend);
++ } else if (unlikely(lower_inode == poison_ptr)) {
++ /* freed inode! */
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci6: inode/linode=%p:%p bindex=%d "
++ "istart/end=%d:%d\n", inode,
++ lower_inode, bindex, istart, iend);
++ }
++ continue;
++ }
++ /* if we get here, then lower_inode == NULL */
++ if (bindex < istart || bindex > iend)
++ continue;
++ /*
++ * directories can have NULL lower inodes in b/t start/end,
++ * but NOT if at the start/end range.
++ */
++ if (unlikely(S_ISDIR(inode->i_mode) &&
++ bindex > istart && bindex < iend))
++ continue;
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci7: inode/linode=%p:%p "
++ "bindex=%d istart/end=%d:%d\n",
++ inode, lower_inode, bindex, istart, iend);
++ }
++}
++
++void __unionfs_check_dentry(const struct dentry *dentry,
++ const char *fname, const char *fxn, int line)
++{
++ int bindex;
++ int dstart, dend, istart, iend;
++ struct dentry *lower_dentry;
++ struct inode *inode, *lower_inode;
++ struct super_block *sb;
++ struct vfsmount *lower_mnt;
++ int printed_caller = 0;
++ void *poison_ptr;
++
++ BUG_ON(!dentry);
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ dstart = dbstart(dentry);
++ dend = dbend(dentry);
++ /* don't check dentry/mnt if no lower branches */
++ if (dstart < 0 && dend < 0)
++ goto check_inode;
++ BUG_ON(dstart > dend);
++
++ if (unlikely((dstart == -1 && dend != -1) ||
++ (dstart != -1 && dend == -1))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CD0: dentry=%p dstart/end=%d:%d\n",
++ dentry, dstart, dend);
++ }
++ /*
++ * check for NULL dentries inside the start/end range, or
++ * non-NULL dentries outside the start/end range.
++ */
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (lower_dentry) {
++ if (unlikely(bindex < dstart || bindex > dend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CD1: dentry/lower=%p:%p(%p) "
++ "bindex=%d dstart/end=%d:%d\n",
++ dentry, lower_dentry,
++ (lower_dentry ? lower_dentry->d_inode :
++ (void *) -1L),
++ bindex, dstart, dend);
++ }
++ } else { /* lower_dentry == NULL */
++ if (bindex < dstart || bindex > dend)
++ continue;
++ /*
++ * Directories can have NULL lower inodes in b/t
++ * start/end, but NOT if at the start/end range.
++ * Ignore this rule, however, if this is a NULL
++ * dentry or a deleted dentry.
++ */
++ if (unlikely(!d_deleted((struct dentry *) dentry) &&
++ inode &&
++ !(inode && S_ISDIR(inode->i_mode) &&
++ bindex > dstart && bindex < dend))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CD2: dentry/lower=%p:%p(%p) "
++ "bindex=%d dstart/end=%d:%d\n",
++ dentry, lower_dentry,
++ (lower_dentry ?
++ lower_dentry->d_inode :
++ (void *) -1L),
++ bindex, dstart, dend);
++ }
++ }
++ }
++
++ /* check for vfsmounts same as for dentries */
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
++ if (lower_mnt) {
++ if (unlikely(bindex < dstart || bindex > dend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CM0: dentry/lmnt=%p:%p bindex=%d "
++ "dstart/end=%d:%d\n", dentry,
++ lower_mnt, bindex, dstart, dend);
++ }
++ } else { /* lower_mnt == NULL */
++ if (bindex < dstart || bindex > dend)
++ continue;
++ /*
++ * Directories can have NULL lower inodes in b/t
++ * start/end, but NOT if at the start/end range.
++ * Ignore this rule, however, if this is a NULL
++ * dentry.
++ */
++ if (unlikely(inode &&
++ !(inode && S_ISDIR(inode->i_mode) &&
++ bindex > dstart && bindex < dend))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CM1: dentry/lmnt=%p:%p "
++ "bindex=%d dstart/end=%d:%d\n",
++ dentry, lower_mnt, bindex,
++ dstart, dend);
++ }
++ }
++ }
++
++check_inode:
++ /* for inodes now */
++ if (!inode)
++ return;
++ istart = ibstart(inode);
++ iend = ibend(inode);
++ /* don't check inode if no lower branches */
++ if (istart < 0 && iend < 0)
++ return;
++ BUG_ON(istart > iend);
++ if (unlikely((istart == -1 && iend != -1) ||
++ (istart != -1 && iend == -1))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI0: dentry/inode=%p:%p istart/end=%d:%d\n",
++ dentry, inode, istart, iend);
++ }
++ if (unlikely(istart != dstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI1: dentry/inode=%p:%p istart=%d dstart=%d\n",
++ dentry, inode, istart, dstart);
++ }
++ if (unlikely(iend != dend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI2: dentry/inode=%p:%p iend=%d dend=%d\n",
++ dentry, inode, iend, dend);
++ }
++
++ if (!S_ISDIR(inode->i_mode)) {
++ if (unlikely(dend != dstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI3: dentry/inode=%p:%p dstart=%d dend=%d\n",
++ dentry, inode, dstart, dend);
++ }
++ if (unlikely(iend != istart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI4: dentry/inode=%p:%p istart=%d iend=%d\n",
++ dentry, inode, istart, iend);
++ }
++ }
++
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (lower_inode) {
++ memset(&poison_ptr, POISON_INUSE, sizeof(void *));
++ if (unlikely(bindex < istart || bindex > iend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI5: dentry/linode=%p:%p bindex=%d "
++ "istart/end=%d:%d\n", dentry,
++ lower_inode, bindex, istart, iend);
++ } else if (unlikely(lower_inode == poison_ptr)) {
++ /* freed inode! */
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI6: dentry/linode=%p:%p bindex=%d "
++ "istart/end=%d:%d\n", dentry,
++ lower_inode, bindex, istart, iend);
++ }
++ continue;
++ }
++ /* if we get here, then lower_inode == NULL */
++ if (bindex < istart || bindex > iend)
++ continue;
++ /*
++ * directories can have NULL lower inodes in b/t start/end,
++ * but NOT if at the start/end range.
++ */
++ if (unlikely(S_ISDIR(inode->i_mode) &&
++ bindex > istart && bindex < iend))
++ continue;
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI7: dentry/linode=%p:%p "
++ "bindex=%d istart/end=%d:%d\n",
++ dentry, lower_inode, bindex, istart, iend);
++ }
++
++ /*
++ * If it's a directory, then intermediate objects b/t start/end can
++ * be NULL. But, check that all three are NULL: lower dentry, mnt,
++ * and inode.
++ */
++ if (dstart >= 0 && dend >= 0 && S_ISDIR(inode->i_mode))
++ for (bindex = dstart+1; bindex < dend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ lower_dentry = unionfs_lower_dentry_idx(dentry,
++ bindex);
++ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
++ if (unlikely(!((lower_inode && lower_dentry &&
++ lower_mnt) ||
++ (!lower_inode &&
++ !lower_dentry && !lower_mnt)))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Cx: lmnt/ldentry/linode=%p:%p:%p "
++ "bindex=%d dstart/end=%d:%d\n",
++ lower_mnt, lower_dentry, lower_inode,
++ bindex, dstart, dend);
++ }
++ }
++ /* check if lower inode is newer than upper one (it shouldn't) */
++ if (unlikely(is_newer_lower(dentry) && !is_negative_lower(dentry))) {
++ PRINT_CALLER(fname, fxn, line);
++ for (bindex = ibstart(inode); bindex <= ibend(inode);
++ bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (unlikely(!lower_inode))
++ continue;
++ pr_debug(" CI8: bindex=%d mtime/lmtime=%lu.%lu/%lu.%lu "
++ "ctime/lctime=%lu.%lu/%lu.%lu\n",
++ bindex,
++ inode->i_mtime.tv_sec,
++ inode->i_mtime.tv_nsec,
++ lower_inode->i_mtime.tv_sec,
++ lower_inode->i_mtime.tv_nsec,
++ inode->i_ctime.tv_sec,
++ inode->i_ctime.tv_nsec,
++ lower_inode->i_ctime.tv_sec,
++ lower_inode->i_ctime.tv_nsec);
++ }
++ }
++}
++
++void __unionfs_check_file(const struct file *file,
++ const char *fname, const char *fxn, int line)
++{
++ int bindex;
++ int dstart, dend, fstart, fend;
++ struct dentry *dentry;
++ struct file *lower_file;
++ struct inode *inode;
++ struct super_block *sb;
++ int printed_caller = 0;
++
++ BUG_ON(!file);
++ dentry = file->f_path.dentry;
++ sb = dentry->d_sb;
++ dstart = dbstart(dentry);
++ dend = dbend(dentry);
++ BUG_ON(dstart > dend);
++ fstart = fbstart(file);
++ fend = fbend(file);
++ BUG_ON(fstart > fend);
++
++ if (unlikely((fstart == -1 && fend != -1) ||
++ (fstart != -1 && fend == -1))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF0: file/dentry=%p:%p fstart/end=%d:%d\n",
++ file, dentry, fstart, fend);
++ }
++ if (unlikely(fstart != dstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF1: file/dentry=%p:%p fstart=%d dstart=%d\n",
++ file, dentry, fstart, dstart);
++ }
++ if (unlikely(fend != dend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF2: file/dentry=%p:%p fend=%d dend=%d\n",
++ file, dentry, fend, dend);
++ }
++ inode = dentry->d_inode;
++ if (!S_ISDIR(inode->i_mode)) {
++ if (unlikely(fend != fstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF3: file/inode=%p:%p fstart=%d fend=%d\n",
++ file, inode, fstart, fend);
++ }
++ if (unlikely(dend != dstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF4: file/dentry=%p:%p dstart=%d dend=%d\n",
++ file, dentry, dstart, dend);
++ }
++ }
++
++ /*
++ * check for NULL dentries inside the start/end range, or
++ * non-NULL dentries outside the start/end range.
++ */
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ if (lower_file) {
++ if (unlikely(bindex < fstart || bindex > fend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF5: file/lower=%p:%p bindex=%d "
++ "fstart/end=%d:%d\n", file,
++ lower_file, bindex, fstart, fend);
++ }
++ } else { /* lower_file == NULL */
++ if (bindex >= fstart && bindex <= fend) {
++ /*
++ * directories can have NULL lower inodes in
++ * b/t start/end, but NOT if at the
++ * start/end range.
++ */
++ if (unlikely(!(S_ISDIR(inode->i_mode) &&
++ bindex > fstart &&
++ bindex < fend))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF6: file/lower=%p:%p "
++ "bindex=%d fstart/end=%d:%d\n",
++ file, lower_file, bindex,
++ fstart, fend);
++ }
++ }
++ }
++ }
++
++ __unionfs_check_dentry(dentry, fname, fxn, line);
++}
++
++void __unionfs_check_nd(const struct nameidata *nd,
++ const char *fname, const char *fxn, int line)
++{
++ struct file *file;
++ int printed_caller = 0;
++
++ if (unlikely(!nd))
++ return;
++ if (nd->flags & LOOKUP_OPEN) {
++ file = nd->intent.open.file;
++ if (unlikely(file->f_path.dentry &&
++ strcmp(file->f_path.dentry->d_sb->s_type->name,
++ UNIONFS_NAME))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CND1: lower_file of type %s\n",
++ file->f_path.dentry->d_sb->s_type->name);
++ }
++ }
++}
++
++/* useful to track vfsmount leaks that could cause EBUSY on unmount */
++void __show_branch_counts(const struct super_block *sb,
++ const char *file, const char *fxn, int line)
++{
++ int i;
++ struct vfsmount *mnt;
++
++ pr_debug("BC:");
++ for (i = 0; i < sbmax(sb); i++) {
++ if (likely(sb->s_root))
++ mnt = UNIONFS_D(sb->s_root)->lower_paths[i].mnt;
++ else
++ mnt = NULL;
++ printk(KERN_CONT "%d:",
++ (mnt ? atomic_read(&mnt->mnt_count) : -99));
++ }
++ printk(KERN_CONT "%s:%s:%d\n", file, fxn, line);
++}
++
++void __show_inode_times(const struct inode *inode,
++ const char *file, const char *fxn, int line)
++{
++ struct inode *lower_inode;
++ int bindex;
++
++ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (unlikely(!lower_inode))
++ continue;
++ pr_debug("IT(%lu:%d): %s:%s:%d "
++ "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n",
++ inode->i_ino, bindex,
++ file, fxn, line,
++ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
++ lower_inode->i_mtime.tv_sec,
++ lower_inode->i_mtime.tv_nsec,
++ inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
++ lower_inode->i_ctime.tv_sec,
++ lower_inode->i_ctime.tv_nsec);
++ }
++}
++
++void __show_dinode_times(const struct dentry *dentry,
++ const char *file, const char *fxn, int line)
++{
++ struct inode *inode = dentry->d_inode;
++ struct inode *lower_inode;
++ int bindex;
++
++ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++ pr_debug("DT(%s:%lu:%d): %s:%s:%d "
++ "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n",
++ dentry->d_name.name, inode->i_ino, bindex,
++ file, fxn, line,
++ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
++ lower_inode->i_mtime.tv_sec,
++ lower_inode->i_mtime.tv_nsec,
++ inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
++ lower_inode->i_ctime.tv_sec,
++ lower_inode->i_ctime.tv_nsec);
++ }
++}
++
++void __show_inode_counts(const struct inode *inode,
++ const char *file, const char *fxn, int line)
++{
++ struct inode *lower_inode;
++ int bindex;
++
++ if (unlikely(!inode)) {
++ pr_debug("SiC: Null inode\n");
++ return;
++ }
++ for (bindex = sbstart(inode->i_sb); bindex <= sbend(inode->i_sb);
++ bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (unlikely(!lower_inode))
++ continue;
++ pr_debug("SIC(%lu:%d:%d): lc=%d %s:%s:%d\n",
++ inode->i_ino, bindex,
++ atomic_read(&(inode)->i_count),
++ atomic_read(&(lower_inode)->i_count),
++ file, fxn, line);
++ }
++}
+diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
+new file mode 100644
+index 0000000..a0c3bba
+--- /dev/null
++++ b/fs/unionfs/dentry.c
+@@ -0,0 +1,397 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++bool is_negative_lower(const struct dentry *dentry)
++{
++ int bindex;
++ struct dentry *lower_dentry;
++
++ BUG_ON(!dentry);
++ /* cache coherency: check if file was deleted on lower branch */
++ if (dbstart(dentry) < 0)
++ return true;
++ for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ /* unhashed (i.e., unlinked) lower dentries don't count */
++ if (lower_dentry && lower_dentry->d_inode &&
++ !d_deleted(lower_dentry) &&
++ !(lower_dentry->d_flags & DCACHE_NFSFS_RENAMED))
++ return false;
++ }
++ return true;
++}
++
++static inline void __dput_lowers(struct dentry *dentry, int start, int end)
++{
++ struct dentry *lower_dentry;
++ int bindex;
++
++ if (start < 0)
++ return;
++ for (bindex = start; bindex <= end; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ dput(lower_dentry);
++ }
++}
++
++/*
++ * Purge and invalidate as many data pages of a unionfs inode. This is
++ * called when the lower inode has changed, and we want to force processes
++ * to re-get the new data.
++ */
++static inline void purge_inode_data(struct inode *inode)
++{
++ /* remove all non-private mappings */
++ unmap_mapping_range(inode->i_mapping, 0, 0, 0);
++ /* invalidate as many pages as possible */
++ invalidate_mapping_pages(inode->i_mapping, 0, -1);
++ /*
++ * Don't try to truncate_inode_pages here, because this could lead
++ * to a deadlock between some of address_space ops and dentry
++ * revalidation: the address space op is invoked with a lock on our
++ * own page, and truncate_inode_pages will block on locked pages.
++ */
++}
++
++/*
++ * Revalidate a single file/symlink/special dentry. Assume that info nodes
++ * of the @dentry and its @parent are locked. Assume parent is valid,
++ * otherwise return false (and let's hope the VFS will try to re-lookup this
++ * dentry). Returns true if valid, false otherwise.
++ */
++bool __unionfs_d_revalidate(struct dentry *dentry, struct dentry *parent,
++ bool willwrite)
++{
++ bool valid = true; /* default is valid */
++ struct dentry *lower_dentry;
++ struct dentry *result;
++ int bindex, bstart, bend;
++ int sbgen, dgen, pdgen;
++ int positive = 0;
++ int interpose_flag;
++
++ verify_locked(dentry);
++ verify_locked(parent);
++
++ /* if the dentry is unhashed, do NOT revalidate */
++ if (d_deleted(dentry))
++ goto out;
++
++ dgen = atomic_read(&UNIONFS_D(dentry)->generation);
++
++ if (is_newer_lower(dentry)) {
++ /* root dentry is always valid */
++ if (IS_ROOT(dentry)) {
++ unionfs_copy_attr_times(dentry->d_inode);
++ } else {
++ /*
++ * reset generation number to zero, guaranteed to be
++ * "old"
++ */
++ dgen = 0;
++ atomic_set(&UNIONFS_D(dentry)->generation, dgen);
++ }
++ if (!willwrite)
++ purge_inode_data(dentry->d_inode);
++ }
++
++ sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
++
++ BUG_ON(dbstart(dentry) == -1);
++ if (dentry->d_inode)
++ positive = 1;
++
++ /* if our dentry is valid, then validate all lower ones */
++ if (sbgen == dgen)
++ goto validate_lowers;
++
++ /* The root entry should always be valid */
++ BUG_ON(IS_ROOT(dentry));
++
++ /* We can't work correctly if our parent isn't valid. */
++ pdgen = atomic_read(&UNIONFS_D(parent)->generation);
++
++ /* Free the pointers for our inodes and this dentry. */
++ path_put_lowers_all(dentry, false);
++
++ interpose_flag = INTERPOSE_REVAL_NEG;
++ if (positive) {
++ interpose_flag = INTERPOSE_REVAL;
++ iput_lowers_all(dentry->d_inode, true);
++ }
++
++ if (realloc_dentry_private_data(dentry) != 0) {
++ valid = false;
++ goto out;
++ }
++
++ result = unionfs_lookup_full(dentry, parent, interpose_flag);
++ if (result) {
++ if (IS_ERR(result)) {
++ valid = false;
++ goto out;
++ }
++ /*
++ * current unionfs_lookup_backend() doesn't return
++ * a valid dentry
++ */
++ dput(dentry);
++ dentry = result;
++ }
++
++ if (unlikely(positive && is_negative_lower(dentry))) {
++ /* call make_bad_inode here ? */
++ d_drop(dentry);
++ valid = false;
++ goto out;
++ }
++
++ /*
++ * if we got here then we have revalidated our dentry and all lower
++ * ones, so we can return safely.
++ */
++ if (!valid) /* lower dentry revalidation failed */
++ goto out;
++
++ /*
++ * If the parent's gen no. matches the superblock's gen no., then
++ * we can update our denty's gen no. If they didn't match, then it
++ * was OK to revalidate this dentry with a stale parent, but we'll
++ * purposely not update our dentry's gen no. (so it can be redone);
++ * and, we'll mark our parent dentry as invalid so it'll force it
++ * (and our dentry) to be revalidated.
++ */
++ if (pdgen == sbgen)
++ atomic_set(&UNIONFS_D(dentry)->generation, sbgen);
++ goto out;
++
++validate_lowers:
++
++ /* The revalidation must occur across all branches */
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ BUG_ON(bstart == -1);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry || !lower_dentry->d_op
++ || !lower_dentry->d_op->d_revalidate)
++ continue;
++ /*
++ * Don't pass nameidata to lower file system, because we
++ * don't want an arbitrary lower file being opened or
++ * returned to us: it may be useless to us because of the
++ * fanout nature of unionfs (cf. file/directory open-file
++ * invariants). We will open lower files as and when needed
++ * later on.
++ */
++ if (!lower_dentry->d_op->d_revalidate(lower_dentry, NULL))
++ valid = false;
++ }
++
++ if (!dentry->d_inode ||
++ ibstart(dentry->d_inode) < 0 ||
++ ibend(dentry->d_inode) < 0) {
++ valid = false;
++ goto out;
++ }
++
++ if (valid) {
++ /*
++ * If we get here, and we copy the meta-data from the lower
++ * inode to our inode, then it is vital that we have already
++ * purged all unionfs-level file data. We do that in the
++ * caller (__unionfs_d_revalidate) by calling
++ * purge_inode_data.
++ */
++ unionfs_copy_attr_all(dentry->d_inode,
++ unionfs_lower_inode(dentry->d_inode));
++ fsstack_copy_inode_size(dentry->d_inode,
++ unionfs_lower_inode(dentry->d_inode));
++ }
++
++out:
++ return valid;
++}
++
++/*
++ * Determine if the lower inode objects have changed from below the unionfs
++ * inode. Return true if changed, false otherwise.
++ *
++ * We check if the mtime or ctime have changed. However, the inode times
++ * can be changed by anyone without much protection, including
++ * asynchronously. This can sometimes cause unionfs to find that the lower
++ * file system doesn't change its inode times quick enough, resulting in a
++ * false positive indication (which is harmless, it just makes unionfs do
++ * extra work in re-validating the objects). To minimize the chances of
++ * these situations, we still consider such small time changes valid, but we
++ * don't print debugging messages unless the time changes are greater than
++ * UNIONFS_MIN_CC_TIME (which defaults to 3 seconds, as with NFS's acregmin)
++ * because significant changes are more likely due to users manually
++ * touching lower files.
++ */
++bool is_newer_lower(const struct dentry *dentry)
++{
++ int bindex;
++ struct inode *inode;
++ struct inode *lower_inode;
++
++ /* ignore if we're called on semi-initialized dentries/inodes */
++ if (!dentry || !UNIONFS_D(dentry))
++ return false;
++ inode = dentry->d_inode;
++ if (!inode || !UNIONFS_I(inode)->lower_inodes ||
++ ibstart(inode) < 0 || ibend(inode) < 0)
++ return false;
++
++ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++
++ /* check if mtime/ctime have changed */
++ if (unlikely(timespec_compare(&inode->i_mtime,
++ &lower_inode->i_mtime) < 0)) {
++ if ((lower_inode->i_mtime.tv_sec -
++ inode->i_mtime.tv_sec) > UNIONFS_MIN_CC_TIME) {
++ pr_info("unionfs: new lower inode mtime "
++ "(bindex=%d, name=%s)\n", bindex,
++ dentry->d_name.name);
++ show_dinode_times(dentry);
++ }
++ return true;
++ }
++ if (unlikely(timespec_compare(&inode->i_ctime,
++ &lower_inode->i_ctime) < 0)) {
++ if ((lower_inode->i_ctime.tv_sec -
++ inode->i_ctime.tv_sec) > UNIONFS_MIN_CC_TIME) {
++ pr_info("unionfs: new lower inode ctime "
++ "(bindex=%d, name=%s)\n", bindex,
++ dentry->d_name.name);
++ show_dinode_times(dentry);
++ }
++ return true;
++ }
++ }
++
++ /*
++ * Last check: if this is a positive dentry, but somehow all lower
++ * dentries are negative or unhashed, then this dentry needs to be
++ * revalidated, because someone probably deleted the objects from
++ * the lower branches directly.
++ */
++ if (is_negative_lower(dentry))
++ return true;
++
++ return false; /* default: lower is not newer */
++}
++
++static int unionfs_d_revalidate(struct dentry *dentry,
++ struct nameidata *nd_unused)
++{
++ bool valid = true;
++ int err = 1; /* 1 means valid for the VFS */
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (valid) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_dentry(dentry);
++ } else {
++ d_drop(dentry);
++ err = valid;
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return err;
++}
++
++static void unionfs_d_release(struct dentry *dentry)
++{
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ if (unlikely(!UNIONFS_D(dentry)))
++ goto out; /* skip if no lower branches */
++ /* must lock our branch configuration here */
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ unionfs_check_dentry(dentry);
++ /* this could be a negative dentry, so check first */
++ if (dbstart(dentry) < 0) {
++ unionfs_unlock_dentry(dentry);
++ goto out; /* due to a (normal) failed lookup */
++ }
++
++ /* Release all the lower dentries */
++ path_put_lowers_all(dentry, true);
++
++ unionfs_unlock_dentry(dentry);
++
++out:
++ free_dentry_private_data(dentry);
++ unionfs_read_unlock(dentry->d_sb);
++ return;
++}
++
++/*
++ * Called when we're removing the last reference to our dentry. So we
++ * should drop all lower references too.
++ */
++static void unionfs_d_iput(struct dentry *dentry, struct inode *inode)
++{
++ int rc;
++
++ BUG_ON(!dentry);
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (!UNIONFS_D(dentry) || dbstart(dentry) < 0)
++ goto drop_lower_inodes;
++ path_put_lowers_all(dentry, false);
++
++drop_lower_inodes:
++ rc = atomic_read(&inode->i_count);
++ if (rc == 1 && inode->i_nlink == 1 && ibstart(inode) >= 0) {
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ iput(unionfs_lower_inode(inode));
++ lockdep_on();
++ unionfs_set_lower_inode(inode, NULL);
++ /* XXX: may need to set start/end to -1? */
++ }
++
++ iput(inode);
++
++ unionfs_unlock_dentry(dentry);
++ unionfs_read_unlock(dentry->d_sb);
++}
++
++struct dentry_operations unionfs_dops = {
++ .d_revalidate = unionfs_d_revalidate,
++ .d_release = unionfs_d_release,
++ .d_iput = unionfs_d_iput,
++};
+diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
+new file mode 100644
+index 0000000..7da0ff0
+--- /dev/null
++++ b/fs/unionfs/dirfops.c
+@@ -0,0 +1,302 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/* Make sure our rdstate is playing by the rules. */
++static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
++{
++ BUG_ON(rdstate->offset >= DIREOF);
++ BUG_ON(rdstate->cookie >= MAXRDCOOKIE);
++}
++
++struct unionfs_getdents_callback {
++ struct unionfs_dir_state *rdstate;
++ void *dirent;
++ int entries_written;
++ int filldir_called;
++ int filldir_error;
++ filldir_t filldir;
++ struct super_block *sb;
++};
++
++/* based on generic filldir in fs/readir.c */
++static int unionfs_filldir(void *dirent, const char *oname, int namelen,
++ loff_t offset, u64 ino, unsigned int d_type)
++{
++ struct unionfs_getdents_callback *buf = dirent;
++ struct filldir_node *found = NULL;
++ int err = 0;
++ int is_whiteout;
++ char *name = (char *) oname;
++
++ buf->filldir_called++;
++
++ is_whiteout = is_whiteout_name(&name, &namelen);
++
++ found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout);
++
++ if (found) {
++ /*
++ * If we had non-whiteout entry in dir cache, then mark it
++ * as a whiteout and but leave it in the dir cache.
++ */
++ if (is_whiteout && !found->whiteout)
++ found->whiteout = is_whiteout;
++ goto out;
++ }
++
++ /* if 'name' isn't a whiteout, filldir it. */
++ if (!is_whiteout) {
++ off_t pos = rdstate2offset(buf->rdstate);
++ u64 unionfs_ino = ino;
++
++ err = buf->filldir(buf->dirent, name, namelen, pos,
++ unionfs_ino, d_type);
++ buf->rdstate->offset++;
++ verify_rdstate_offset(buf->rdstate);
++ }
++ /*
++ * If we did fill it, stuff it in our hash, otherwise return an
++ * error.
++ */
++ if (err) {
++ buf->filldir_error = err;
++ goto out;
++ }
++ buf->entries_written++;
++ err = add_filldir_node(buf->rdstate, name, namelen,
++ buf->rdstate->bindex, is_whiteout);
++ if (err)
++ buf->filldir_error = err;
++
++out:
++ return err;
++}
++
++static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err = 0;
++ struct file *lower_file = NULL;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ struct inode *inode = NULL;
++ struct unionfs_getdents_callback buf;
++ struct unionfs_dir_state *uds;
++ int bend;
++ loff_t offset;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, false);
++ if (unlikely(err))
++ goto out;
++
++ inode = dentry->d_inode;
++
++ uds = UNIONFS_F(file)->rdstate;
++ if (!uds) {
++ if (file->f_pos == DIREOF) {
++ goto out;
++ } else if (file->f_pos > 0) {
++ uds = find_rdstate(inode, file->f_pos);
++ if (unlikely(!uds)) {
++ err = -ESTALE;
++ goto out;
++ }
++ UNIONFS_F(file)->rdstate = uds;
++ } else {
++ init_rdstate(file);
++ uds = UNIONFS_F(file)->rdstate;
++ }
++ }
++ bend = fbend(file);
++
++ while (uds->bindex <= bend) {
++ lower_file = unionfs_lower_file_idx(file, uds->bindex);
++ if (!lower_file) {
++ uds->bindex++;
++ uds->dirpos = 0;
++ continue;
++ }
++
++ /* prepare callback buffer */
++ buf.filldir_called = 0;
++ buf.filldir_error = 0;
++ buf.entries_written = 0;
++ buf.dirent = dirent;
++ buf.filldir = filldir;
++ buf.rdstate = uds;
++ buf.sb = inode->i_sb;
++
++ /* Read starting from where we last left off. */
++ offset = vfs_llseek(lower_file, uds->dirpos, SEEK_SET);
++ if (offset < 0) {
++ err = offset;
++ goto out;
++ }
++ err = vfs_readdir(lower_file, unionfs_filldir, &buf);
++
++ /* Save the position for when we continue. */
++ offset = vfs_llseek(lower_file, 0, SEEK_CUR);
++ if (offset < 0) {
++ err = offset;
++ goto out;
++ }
++ uds->dirpos = offset;
++
++ /* Copy the atime. */
++ fsstack_copy_attr_atime(inode,
++ lower_file->f_path.dentry->d_inode);
++
++ if (err < 0)
++ goto out;
++
++ if (buf.filldir_error)
++ break;
++
++ if (!buf.entries_written) {
++ uds->bindex++;
++ uds->dirpos = 0;
++ }
++ }
++
++ if (!buf.filldir_error && uds->bindex >= bend) {
++ /* Save the number of hash entries for next time. */
++ UNIONFS_I(inode)->hashsize = uds->hashentries;
++ free_rdstate(uds);
++ UNIONFS_F(file)->rdstate = NULL;
++ file->f_pos = DIREOF;
++ } else {
++ file->f_pos = rdstate2offset(uds);
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * This is not meant to be a generic repositioning function. If you do
++ * things that aren't supported, then we return EINVAL.
++ *
++ * What is allowed:
++ * (1) seeking to the same position that you are currently at
++ * This really has no effect, but returns where you are.
++ * (2) seeking to the beginning of the file
++ * This throws out all state, and lets you begin again.
++ */
++static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin)
++{
++ struct unionfs_dir_state *rdstate;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ loff_t err;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, false);
++ if (unlikely(err))
++ goto out;
++
++ rdstate = UNIONFS_F(file)->rdstate;
++
++ /*
++ * we let users seek to their current position, but not anywhere
++ * else.
++ */
++ if (!offset) {
++ switch (origin) {
++ case SEEK_SET:
++ if (rdstate) {
++ free_rdstate(rdstate);
++ UNIONFS_F(file)->rdstate = NULL;
++ }
++ init_rdstate(file);
++ err = 0;
++ break;
++ case SEEK_CUR:
++ err = file->f_pos;
++ break;
++ case SEEK_END:
++ /* Unsupported, because we would break everything. */
++ err = -EINVAL;
++ break;
++ }
++ } else {
++ switch (origin) {
++ case SEEK_SET:
++ if (rdstate) {
++ if (offset == rdstate2offset(rdstate))
++ err = offset;
++ else if (file->f_pos == DIREOF)
++ err = DIREOF;
++ else
++ err = -EINVAL;
++ } else {
++ struct inode *inode;
++ inode = dentry->d_inode;
++ rdstate = find_rdstate(inode, offset);
++ if (rdstate) {
++ UNIONFS_F(file)->rdstate = rdstate;
++ err = rdstate->offset;
++ } else {
++ err = -EINVAL;
++ }
++ }
++ break;
++ case SEEK_CUR:
++ case SEEK_END:
++ /* Unsupported, because we would break everything. */
++ err = -EINVAL;
++ break;
++ }
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * Trimmed directory options, we shouldn't pass everything down since
++ * we don't want to operate on partial directories.
++ */
++struct file_operations unionfs_dir_fops = {
++ .llseek = unionfs_dir_llseek,
++ .read = generic_read_dir,
++ .readdir = unionfs_readdir,
++ .unlocked_ioctl = unionfs_ioctl,
++ .open = unionfs_open,
++ .release = unionfs_file_release,
++ .flush = unionfs_flush,
++ .fsync = unionfs_fsync,
++ .fasync = unionfs_fasync,
++};
+diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
+new file mode 100644
+index 0000000..033343b
+--- /dev/null
++++ b/fs/unionfs/dirhelper.c
+@@ -0,0 +1,158 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++#define RD_NONE 0
++#define RD_CHECK_EMPTY 1
++/* The callback structure for check_empty. */
++struct unionfs_rdutil_callback {
++ int err;
++ int filldir_called;
++ struct unionfs_dir_state *rdstate;
++ int mode;
++};
++
++/* This filldir function makes sure only whiteouts exist within a directory. */
++static int readdir_util_callback(void *dirent, const char *oname, int namelen,
++ loff_t offset, u64 ino, unsigned int d_type)
++{
++ int err = 0;
++ struct unionfs_rdutil_callback *buf = dirent;
++ int is_whiteout;
++ struct filldir_node *found;
++ char *name = (char *) oname;
++
++ buf->filldir_called = 1;
++
++ if (name[0] == '.' && (namelen == 1 ||
++ (name[1] == '.' && namelen == 2)))
++ goto out;
++
++ is_whiteout = is_whiteout_name(&name, &namelen);
++
++ found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout);
++ /* If it was found in the table there was a previous whiteout. */
++ if (found)
++ goto out;
++
++ /*
++ * if it wasn't found and isn't a whiteout, the directory isn't
++ * empty.
++ */
++ err = -ENOTEMPTY;
++ if ((buf->mode == RD_CHECK_EMPTY) && !is_whiteout)
++ goto out;
++
++ err = add_filldir_node(buf->rdstate, name, namelen,
++ buf->rdstate->bindex, is_whiteout);
++
++out:
++ buf->err = err;
++ return err;
++}
++
++/* Is a directory logically empty? */
++int check_empty(struct dentry *dentry, struct dentry *parent,
++ struct unionfs_dir_state **namelist)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct vfsmount *mnt;
++ struct super_block *sb;
++ struct file *lower_file;
++ struct unionfs_rdutil_callback *buf = NULL;
++ int bindex, bstart, bend, bopaque;
++
++ sb = dentry->d_sb;
++
++
++ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
++
++ err = unionfs_partial_lookup(dentry, parent);
++ if (err)
++ goto out;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ bopaque = dbopaque(dentry);
++ if (0 <= bopaque && bopaque < bend)
++ bend = bopaque;
++
++ buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
++ if (unlikely(!buf)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ buf->err = 0;
++ buf->mode = RD_CHECK_EMPTY;
++ buf->rdstate = alloc_rdstate(dentry->d_inode, bstart);
++ if (unlikely(!buf->rdstate)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ /* Process the lower directories with rdutil_callback as a filldir. */
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ if (!lower_dentry->d_inode)
++ continue;
++ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
++ continue;
++
++ dget(lower_dentry);
++ mnt = unionfs_mntget(dentry, bindex);
++ branchget(sb, bindex);
++ lower_file = dentry_open(lower_dentry, mnt, O_RDONLY, current_cred());
++ if (IS_ERR(lower_file)) {
++ err = PTR_ERR(lower_file);
++ branchput(sb, bindex);
++ goto out;
++ }
++
++ do {
++ buf->filldir_called = 0;
++ buf->rdstate->bindex = bindex;
++ err = vfs_readdir(lower_file,
++ readdir_util_callback, buf);
++ if (buf->err)
++ err = buf->err;
++ } while ((err >= 0) && buf->filldir_called);
++
++ /* fput calls dput for lower_dentry */
++ fput(lower_file);
++ branchput(sb, bindex);
++
++ if (err < 0)
++ goto out;
++ }
++
++out:
++ if (buf) {
++ if (namelist && !err)
++ *namelist = buf->rdstate;
++ else if (buf->rdstate)
++ free_rdstate(buf->rdstate);
++ kfree(buf);
++ }
++
++
++ return err;
++}
+diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
+new file mode 100644
+index 0000000..5b77eac
+--- /dev/null
++++ b/fs/unionfs/fanout.h
+@@ -0,0 +1,407 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _FANOUT_H_
++#define _FANOUT_H_
++
++/*
++ * Inode to private data
++ *
++ * Since we use containers and the struct inode is _inside_ the
++ * unionfs_inode_info structure, UNIONFS_I will always (given a non-NULL
++ * inode pointer), return a valid non-NULL pointer.
++ */
++static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode)
++{
++ return container_of(inode, struct unionfs_inode_info, vfs_inode);
++}
++
++#define ibstart(ino) (UNIONFS_I(ino)->bstart)
++#define ibend(ino) (UNIONFS_I(ino)->bend)
++
++/* Dentry to private data */
++#define UNIONFS_D(dent) ((struct unionfs_dentry_info *)(dent)->d_fsdata)
++#define dbstart(dent) (UNIONFS_D(dent)->bstart)
++#define dbend(dent) (UNIONFS_D(dent)->bend)
++#define dbopaque(dent) (UNIONFS_D(dent)->bopaque)
++
++/* Superblock to private data */
++#define UNIONFS_SB(super) ((struct unionfs_sb_info *)(super)->s_fs_info)
++#define sbstart(sb) 0
++#define sbend(sb) (UNIONFS_SB(sb)->bend)
++#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1)
++#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id)
++
++/* File to private Data */
++#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data))
++#define fbstart(file) (UNIONFS_F(file)->bstart)
++#define fbend(file) (UNIONFS_F(file)->bend)
++
++/* macros to manipulate branch IDs in stored in our superblock */
++static inline int branch_id(struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ return UNIONFS_SB(sb)->data[index].branch_id;
++}
++
++static inline void set_branch_id(struct super_block *sb, int index, int val)
++{
++ BUG_ON(!sb || index < 0);
++ UNIONFS_SB(sb)->data[index].branch_id = val;
++}
++
++static inline void new_branch_id(struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id);
++}
++
++/*
++ * Find new index of matching branch with an existing superblock of a known
++ * (possibly old) id. This is needed because branches could have been
++ * added/deleted causing the branches of any open files to shift.
++ *
++ * @sb: the new superblock which may have new/different branch IDs
++ * @id: the old/existing id we're looking for
++ * Returns index of newly found branch (0 or greater), -1 otherwise.
++ */
++static inline int branch_id_to_idx(struct super_block *sb, int id)
++{
++ int i;
++ for (i = 0; i < sbmax(sb); i++) {
++ if (branch_id(sb, i) == id)
++ return i;
++ }
++ /* in the non-ODF code, this should really never happen */
++ printk(KERN_WARNING "unionfs: cannot find branch with id %d\n", id);
++ return -1;
++}
++
++/* File to lower file. */
++static inline struct file *unionfs_lower_file(const struct file *f)
++{
++ BUG_ON(!f);
++ return UNIONFS_F(f)->lower_files[fbstart(f)];
++}
++
++static inline struct file *unionfs_lower_file_idx(const struct file *f,
++ int index)
++{
++ BUG_ON(!f || index < 0);
++ return UNIONFS_F(f)->lower_files[index];
++}
++
++static inline void unionfs_set_lower_file_idx(struct file *f, int index,
++ struct file *val)
++{
++ BUG_ON(!f || index < 0);
++ UNIONFS_F(f)->lower_files[index] = val;
++ /* save branch ID (may be redundant?) */
++ UNIONFS_F(f)->saved_branch_ids[index] =
++ branch_id((f)->f_path.dentry->d_sb, index);
++}
++
++static inline void unionfs_set_lower_file(struct file *f, struct file *val)
++{
++ BUG_ON(!f);
++ unionfs_set_lower_file_idx((f), fbstart(f), (val));
++}
++
++/* Inode to lower inode. */
++static inline struct inode *unionfs_lower_inode(const struct inode *i)
++{
++ BUG_ON(!i);
++ return UNIONFS_I(i)->lower_inodes[ibstart(i)];
++}
++
++static inline struct inode *unionfs_lower_inode_idx(const struct inode *i,
++ int index)
++{
++ BUG_ON(!i || index < 0);
++ return UNIONFS_I(i)->lower_inodes[index];
++}
++
++static inline void unionfs_set_lower_inode_idx(struct inode *i, int index,
++ struct inode *val)
++{
++ BUG_ON(!i || index < 0);
++ UNIONFS_I(i)->lower_inodes[index] = val;
++}
++
++static inline void unionfs_set_lower_inode(struct inode *i, struct inode *val)
++{
++ BUG_ON(!i);
++ UNIONFS_I(i)->lower_inodes[ibstart(i)] = val;
++}
++
++/* Superblock to lower superblock. */
++static inline struct super_block *unionfs_lower_super(
++ const struct super_block *sb)
++{
++ BUG_ON(!sb);
++ return UNIONFS_SB(sb)->data[sbstart(sb)].sb;
++}
++
++static inline struct super_block *unionfs_lower_super_idx(
++ const struct super_block *sb,
++ int index)
++{
++ BUG_ON(!sb || index < 0);
++ return UNIONFS_SB(sb)->data[index].sb;
++}
++
++static inline void unionfs_set_lower_super_idx(struct super_block *sb,
++ int index,
++ struct super_block *val)
++{
++ BUG_ON(!sb || index < 0);
++ UNIONFS_SB(sb)->data[index].sb = val;
++}
++
++static inline void unionfs_set_lower_super(struct super_block *sb,
++ struct super_block *val)
++{
++ BUG_ON(!sb);
++ UNIONFS_SB(sb)->data[sbstart(sb)].sb = val;
++}
++
++/* Branch count macros. */
++static inline int branch_count(const struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ return atomic_read(&UNIONFS_SB(sb)->data[index].open_files);
++}
++
++static inline void set_branch_count(struct super_block *sb, int index, int val)
++{
++ BUG_ON(!sb || index < 0);
++ atomic_set(&UNIONFS_SB(sb)->data[index].open_files, val);
++}
++
++static inline void branchget(struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ atomic_inc(&UNIONFS_SB(sb)->data[index].open_files);
++}
++
++static inline void branchput(struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ atomic_dec(&UNIONFS_SB(sb)->data[index].open_files);
++}
++
++/* Dentry macros */
++static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index,
++ struct dentry *val)
++{
++ BUG_ON(!dent || index < 0);
++ UNIONFS_D(dent)->lower_paths[index].dentry = val;
++}
++
++static inline struct dentry *unionfs_lower_dentry_idx(
++ const struct dentry *dent,
++ int index)
++{
++ BUG_ON(!dent || index < 0);
++ return UNIONFS_D(dent)->lower_paths[index].dentry;
++}
++
++static inline struct dentry *unionfs_lower_dentry(const struct dentry *dent)
++{
++ BUG_ON(!dent);
++ return unionfs_lower_dentry_idx(dent, dbstart(dent));
++}
++
++static inline void unionfs_set_lower_mnt_idx(struct dentry *dent, int index,
++ struct vfsmount *mnt)
++{
++ BUG_ON(!dent || index < 0);
++ UNIONFS_D(dent)->lower_paths[index].mnt = mnt;
++}
++
++static inline struct vfsmount *unionfs_lower_mnt_idx(
++ const struct dentry *dent,
++ int index)
++{
++ BUG_ON(!dent || index < 0);
++ return UNIONFS_D(dent)->lower_paths[index].mnt;
++}
++
++static inline struct vfsmount *unionfs_lower_mnt(const struct dentry *dent)
++{
++ BUG_ON(!dent);
++ return unionfs_lower_mnt_idx(dent, dbstart(dent));
++}
++
++/* Macros for locking a dentry. */
++enum unionfs_dentry_lock_class {
++ UNIONFS_DMUTEX_NORMAL,
++ UNIONFS_DMUTEX_ROOT,
++ UNIONFS_DMUTEX_PARENT,
++ UNIONFS_DMUTEX_CHILD,
++ UNIONFS_DMUTEX_WHITEOUT,
++ UNIONFS_DMUTEX_REVAL_PARENT, /* for file/dentry revalidate */
++ UNIONFS_DMUTEX_REVAL_CHILD, /* for file/dentry revalidate */
++};
++
++static inline void unionfs_lock_dentry(struct dentry *d,
++ unsigned int subclass)
++{
++ BUG_ON(!d);
++ mutex_lock_nested(&UNIONFS_D(d)->lock, subclass);
++}
++
++static inline void unionfs_unlock_dentry(struct dentry *d)
++{
++ BUG_ON(!d);
++ mutex_unlock(&UNIONFS_D(d)->lock);
++}
++
++static inline struct dentry *unionfs_lock_parent(struct dentry *d,
++ unsigned int subclass)
++{
++ struct dentry *p;
++
++ BUG_ON(!d);
++ p = dget_parent(d);
++ if (p != d)
++ mutex_lock_nested(&UNIONFS_D(p)->lock, subclass);
++ return p;
++}
++
++static inline void unionfs_unlock_parent(struct dentry *d, struct dentry *p)
++{
++ BUG_ON(!d);
++ BUG_ON(!p);
++ if (p != d) {
++ BUG_ON(!mutex_is_locked(&UNIONFS_D(p)->lock));
++ mutex_unlock(&UNIONFS_D(p)->lock);
++ }
++ dput(p);
++}
++
++static inline void verify_locked(struct dentry *d)
++{
++ BUG_ON(!d);
++ BUG_ON(!mutex_is_locked(&UNIONFS_D(d)->lock));
++}
++
++/* macros to put lower objects */
++
++/*
++ * iput lower inodes of an unionfs dentry, from bstart to bend. If
++ * @free_lower is true, then also kfree the memory used to hold the lower
++ * object pointers.
++ */
++static inline void iput_lowers(struct inode *inode,
++ int bstart, int bend, bool free_lower)
++{
++ struct inode *lower_inode;
++ int bindex;
++
++ BUG_ON(!inode);
++ BUG_ON(!UNIONFS_I(inode));
++ BUG_ON(bstart < 0);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (lower_inode) {
++ unionfs_set_lower_inode_idx(inode, bindex, NULL);
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ iput(lower_inode);
++ lockdep_on();
++ }
++ }
++
++ if (free_lower) {
++ kfree(UNIONFS_I(inode)->lower_inodes);
++ UNIONFS_I(inode)->lower_inodes = NULL;
++ }
++}
++
++/* iput all lower inodes, and reset start/end branch indices to -1 */
++static inline void iput_lowers_all(struct inode *inode, bool free_lower)
++{
++ int bstart, bend;
++
++ BUG_ON(!inode);
++ BUG_ON(!UNIONFS_I(inode));
++ bstart = ibstart(inode);
++ bend = ibend(inode);
++ BUG_ON(bstart < 0);
++
++ iput_lowers(inode, bstart, bend, free_lower);
++ ibstart(inode) = ibend(inode) = -1;
++}
++
++/*
++ * dput/mntput all lower dentries and vfsmounts of an unionfs dentry, from
++ * bstart to bend. If @free_lower is true, then also kfree the memory used
++ * to hold the lower object pointers.
++ *
++ * XXX: implement using path_put VFS macros
++ */
++static inline void path_put_lowers(struct dentry *dentry,
++ int bstart, int bend, bool free_lower)
++{
++ struct dentry *lower_dentry;
++ struct vfsmount *lower_mnt;
++ int bindex;
++
++ BUG_ON(!dentry);
++ BUG_ON(!UNIONFS_D(dentry));
++ BUG_ON(bstart < 0);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (lower_dentry) {
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ dput(lower_dentry);
++ }
++ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
++ if (lower_mnt) {
++ unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
++ mntput(lower_mnt);
++ }
++ }
++
++ if (free_lower) {
++ kfree(UNIONFS_D(dentry)->lower_paths);
++ UNIONFS_D(dentry)->lower_paths = NULL;
++ }
++}
++
++/*
++ * dput/mntput all lower dentries and vfsmounts, and reset start/end branch
++ * indices to -1.
++ */
++static inline void path_put_lowers_all(struct dentry *dentry, bool free_lower)
++{
++ int bstart, bend;
++
++ BUG_ON(!dentry);
++ BUG_ON(!UNIONFS_D(dentry));
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ BUG_ON(bstart < 0);
++
++ path_put_lowers(dentry, bstart, bend, free_lower);
++ dbstart(dentry) = dbend(dentry) = -1;
++}
++
++#endif /* not _FANOUT_H */
+diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
+new file mode 100644
+index 0000000..1c694c3
+--- /dev/null
++++ b/fs/unionfs/file.c
+@@ -0,0 +1,382 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++static ssize_t unionfs_read(struct file *file, char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ int err;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, false);
++ if (unlikely(err))
++ goto out;
++
++ lower_file = unionfs_lower_file(file);
++ err = vfs_read(lower_file, buf, count, ppos);
++ /* update our inode atime upon a successful lower read */
++ if (err >= 0) {
++ fsstack_copy_attr_atime(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ unionfs_check_file(file);
++ }
++
++out:
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static ssize_t unionfs_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ int err = 0;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++
++ lower_file = unionfs_lower_file(file);
++ err = vfs_write(lower_file, buf, count, ppos);
++ /* update our inode times+sizes upon a successful lower write */
++ if (err >= 0) {
++ fsstack_copy_inode_size(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ fsstack_copy_attr_times(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ UNIONFS_F(file)->wrote_to_file = true; /* for delayed copyup */
++ unionfs_check_file(file);
++ }
++
++out:
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static int unionfs_file_readdir(struct file *file, void *dirent,
++ filldir_t filldir)
++{
++ return -ENOTDIR;
++}
++
++static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ int err = 0;
++ bool willwrite;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ const struct vm_operations_struct *saved_vm_ops = NULL;
++
++ /*
++ * Since mm/memory.c:might_fault() (under PROVE_LOCKING) was
++ * modified in 2.6.29-rc1 to call might_lock_read on mmap_sem, this
++ * has been causing false positives in file system stacking layers.
++ * In particular, our ->mmap is called after sys_mmap2 already holds
++ * mmap_sem, then we lock our own mutexes; but earlier, it's
++ * possible for lockdep to have locked our mutexes first, and then
++ * we call a lower ->readdir which could call might_fault. The
++ * different ordering of the locks is what lockdep complains about
++ * -- unnecessarily. Therefore, we have no choice but to tell
++ * lockdep to temporarily turn off lockdep here. Note: the comments
++ * inside might_sleep also suggest that it would have been
++ * nicer to only annotate paths that needs that might_lock_read.
++ */
++ lockdep_off();
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ /* This might be deferred to mmap's writepage */
++ willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
++ err = unionfs_file_revalidate(file, parent, willwrite);
++ if (unlikely(err))
++ goto out;
++ unionfs_check_file(file);
++
++ /*
++ * File systems which do not implement ->writepage may use
++ * generic_file_readonly_mmap as their ->mmap op. If you call
++ * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
++ * But we cannot call the lower ->mmap op, so we can't tell that
++ * writeable mappings won't work. Therefore, our only choice is to
++ * check if the lower file system supports the ->writepage, and if
++ * not, return EINVAL (the same error that
++ * generic_file_readonly_mmap returns in that case).
++ */
++ lower_file = unionfs_lower_file(file);
++ if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
++ err = -EINVAL;
++ printk(KERN_ERR "unionfs: branch %d file system does not "
++ "support writeable mmap\n", fbstart(file));
++ goto out;
++ }
++
++ /*
++ * find and save lower vm_ops.
++ *
++ * XXX: the VFS should have a cleaner way of finding the lower vm_ops
++ */
++ if (!UNIONFS_F(file)->lower_vm_ops) {
++ err = lower_file->f_op->mmap(lower_file, vma);
++ if (err) {
++ printk(KERN_ERR "unionfs: lower mmap failed %d\n", err);
++ goto out;
++ }
++ saved_vm_ops = vma->vm_ops;
++ err = do_munmap(current->mm, vma->vm_start,
++ vma->vm_end - vma->vm_start);
++ if (err) {
++ printk(KERN_ERR "unionfs: do_munmap failed %d\n", err);
++ goto out;
++ }
++ }
++
++ file->f_mapping->a_ops = &unionfs_dummy_aops;
++ err = generic_file_mmap(file, vma);
++ file->f_mapping->a_ops = &unionfs_aops;
++ if (err) {
++ printk(KERN_ERR "unionfs: generic_file_mmap failed %d\n", err);
++ goto out;
++ }
++ vma->vm_ops = &unionfs_vm_ops;
++ if (!UNIONFS_F(file)->lower_vm_ops)
++ UNIONFS_F(file)->lower_vm_ops = saved_vm_ops;
++
++out:
++ if (!err) {
++ /* copyup could cause parent dir times to change */
++ unionfs_copy_attr_times(parent->d_inode);
++ unionfs_check_file(file);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ lockdep_on();
++ return err;
++}
++
++int unionfs_fsync(struct file *file, int datasync)
++{
++ int bindex, bstart, bend;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *lower_dentry;
++ struct dentry *parent;
++ struct inode *lower_inode, *inode;
++ int err = -EINVAL;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++ unionfs_check_file(file);
++
++ bstart = fbstart(file);
++ bend = fbend(file);
++ if (bstart < 0 || bend < 0)
++ goto out;
++
++ inode = dentry->d_inode;
++ if (unlikely(!inode)) {
++ printk(KERN_ERR
++ "unionfs: null lower inode in unionfs_fsync\n");
++ goto out;
++ }
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode || !lower_inode->i_fop->fsync)
++ continue;
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ mutex_lock(&lower_inode->i_mutex);
++ err = lower_inode->i_fop->fsync(lower_file, datasync);
++ if (!err && bindex == bstart)
++ fsstack_copy_attr_times(inode, lower_inode);
++ mutex_unlock(&lower_inode->i_mutex);
++ if (err)
++ goto out;
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++int unionfs_fasync(int fd, struct file *file, int flag)
++{
++ int bindex, bstart, bend;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ struct inode *lower_inode, *inode;
++ int err = 0;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++ unionfs_check_file(file);
++
++ bstart = fbstart(file);
++ bend = fbend(file);
++ if (bstart < 0 || bend < 0)
++ goto out;
++
++ inode = dentry->d_inode;
++ if (unlikely(!inode)) {
++ printk(KERN_ERR
++ "unionfs: null lower inode in unionfs_fasync\n");
++ goto out;
++ }
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode || !lower_inode->i_fop->fasync)
++ continue;
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ mutex_lock(&lower_inode->i_mutex);
++ err = lower_inode->i_fop->fasync(fd, lower_file, flag);
++ if (!err && bindex == bstart)
++ fsstack_copy_attr_times(inode, lower_inode);
++ mutex_unlock(&lower_inode->i_mutex);
++ if (err)
++ goto out;
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static ssize_t unionfs_splice_read(struct file *file, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
++{
++ ssize_t err;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, false);
++ if (unlikely(err))
++ goto out;
++
++ lower_file = unionfs_lower_file(file);
++ err = vfs_splice_to(lower_file, ppos, pipe, len, flags);
++ /* update our inode atime upon a successful lower splice-read */
++ if (err >= 0) {
++ fsstack_copy_attr_atime(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ unionfs_check_file(file);
++ }
++
++out:
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static ssize_t unionfs_splice_write(struct pipe_inode_info *pipe,
++ struct file *file, loff_t *ppos,
++ size_t len, unsigned int flags)
++{
++ ssize_t err = 0;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++
++ lower_file = unionfs_lower_file(file);
++ err = vfs_splice_from(pipe, lower_file, ppos, len, flags);
++ /* update our inode times+sizes upon a successful lower write */
++ if (err >= 0) {
++ fsstack_copy_inode_size(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ fsstack_copy_attr_times(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ unionfs_check_file(file);
++ }
++
++out:
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++struct file_operations unionfs_main_fops = {
++ .llseek = generic_file_llseek,
++ .read = unionfs_read,
++ .write = unionfs_write,
++ .readdir = unionfs_file_readdir,
++ .unlocked_ioctl = unionfs_ioctl,
++#ifdef CONFIG_COMPAT
++ .compat_ioctl = unionfs_ioctl,
++#endif
++ .mmap = unionfs_mmap,
++ .open = unionfs_open,
++ .flush = unionfs_flush,
++ .release = unionfs_file_release,
++ .fsync = unionfs_fsync,
++ .fasync = unionfs_fasync,
++ .splice_read = unionfs_splice_read,
++ .splice_write = unionfs_splice_write,
++};
+diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
+new file mode 100644
+index 0000000..4c36f16
+--- /dev/null
++++ b/fs/unionfs/inode.c
+@@ -0,0 +1,1061 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * Find a writeable branch to create new object in. Checks all writeble
++ * branches of the parent inode, from istart to iend order; if none are
++ * suitable, also tries branch 0 (which may require a copyup).
++ *
++ * Return a lower_dentry we can use to create object in, or ERR_PTR.
++ */
++static struct dentry *find_writeable_branch(struct inode *parent,
++ struct dentry *dentry)
++{
++ int err = -EINVAL;
++ int bindex, istart, iend;
++ struct dentry *lower_dentry = NULL;
++
++ istart = ibstart(parent);
++ iend = ibend(parent);
++ if (istart < 0)
++ goto out;
++
++begin:
++ for (bindex = istart; bindex <= iend; bindex++) {
++ /* skip non-writeable branches */
++ err = is_robranch_super(dentry->d_sb, bindex);
++ if (err) {
++ err = -EROFS;
++ continue;
++ }
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ /*
++ * check for whiteouts in writeable branch, and remove them
++ * if necessary.
++ */
++ err = check_unlink_whiteout(dentry, lower_dentry, bindex);
++ if (err > 0) /* ignore if whiteout found and removed */
++ err = 0;
++ if (err)
++ continue;
++ /* if get here, we can write to the branch */
++ break;
++ }
++ /*
++ * If istart wasn't already branch 0, and we got any error, then try
++ * branch 0 (which may require copyup)
++ */
++ if (err && istart > 0) {
++ istart = iend = 0;
++ goto begin;
++ }
++
++ /*
++ * If we tried even branch 0, and still got an error, abort. But if
++ * the error was an EROFS, then we should try to copyup.
++ */
++ if (err && err != -EROFS)
++ goto out;
++
++ /*
++ * If we get here, then check if copyup needed. If lower_dentry is
++ * NULL, create the entire dentry directory structure in branch 0.
++ */
++ if (!lower_dentry) {
++ bindex = 0;
++ lower_dentry = create_parents(parent, dentry,
++ dentry->d_name.name, bindex);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++ }
++ err = 0; /* all's well */
++out:
++ if (err)
++ return ERR_PTR(err);
++ return lower_dentry;
++}
++
++static int unionfs_create(struct inode *dir, struct dentry *dentry,
++ int mode, struct nameidata *nd_unused)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *parent;
++ int valid = 0;
++ struct nameidata lower_nd;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE; /* same as what real_lookup does */
++ goto out;
++ }
++
++ lower_dentry = find_writeable_branch(dir, dentry);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++
++ lower_parent_dentry = lock_parent(lower_dentry);
++ if (IS_ERR(lower_parent_dentry)) {
++ err = PTR_ERR(lower_parent_dentry);
++ goto out_unlock;
++ }
++
++ err = init_lower_nd(&lower_nd, LOOKUP_CREATE);
++ if (unlikely(err < 0))
++ goto out_unlock;
++ err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode,
++ &lower_nd);
++ release_lower_nd(&lower_nd, err);
++
++ if (!err) {
++ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
++ if (!err) {
++ unionfs_copy_attr_times(dir);
++ fsstack_copy_inode_size(dir,
++ lower_parent_dentry->d_inode);
++ /* update no. of links on parent directory */
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ }
++ }
++
++out_unlock:
++ unlock_dir(lower_parent_dentry);
++out:
++ if (!err) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * unionfs_lookup is the only special function which takes a dentry, yet we
++ * do NOT want to call __unionfs_d_revalidate_chain because by definition,
++ * we don't have a valid dentry here yet.
++ */
++static struct dentry *unionfs_lookup(struct inode *dir,
++ struct dentry *dentry,
++ struct nameidata *nd_unused)
++{
++ struct dentry *ret, *parent;
++ int err = 0;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++
++ /*
++ * As long as we lock/dget the parent, then can skip validating the
++ * parent now; we may have to rebuild this dentry on the next
++ * ->d_revalidate, however.
++ */
++
++ /* allocate dentry private data. We free it in ->d_release */
++ err = new_dentry_private_data(dentry, UNIONFS_DMUTEX_CHILD);
++ if (unlikely(err)) {
++ ret = ERR_PTR(err);
++ goto out;
++ }
++
++ ret = unionfs_lookup_full(dentry, parent, INTERPOSE_LOOKUP);
++
++ if (!IS_ERR(ret)) {
++ if (ret)
++ dentry = ret;
++ /* lookup_full can return multiple positive dentries */
++ if (dentry->d_inode && !S_ISDIR(dentry->d_inode->i_mode)) {
++ BUG_ON(dbstart(dentry) < 0);
++ unionfs_postcopyup_release(dentry);
++ }
++ unionfs_copy_attr_times(dentry->d_inode);
++ }
++
++ unionfs_check_inode(dir);
++ if (!IS_ERR(ret))
++ unionfs_check_dentry(dentry);
++ unionfs_check_dentry(parent);
++ unionfs_unlock_dentry(dentry); /* locked in new_dentry_private data */
++
++out:
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return ret;
++}
++
++static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
++ struct dentry *new_dentry)
++{
++ int err = 0;
++ struct dentry *lower_old_dentry = NULL;
++ struct dentry *lower_new_dentry = NULL;
++ struct dentry *lower_dir_dentry = NULL;
++ struct dentry *old_parent, *new_parent;
++ char *name = NULL;
++ bool valid;
++
++ unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ old_parent = dget_parent(old_dentry);
++ new_parent = dget_parent(new_dentry);
++ unionfs_double_lock_parents(old_parent, new_parent);
++ unionfs_double_lock_dentry(old_dentry, new_dentry);
++
++ valid = __unionfs_d_revalidate(old_dentry, old_parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ if (new_dentry->d_inode) {
++ valid = __unionfs_d_revalidate(new_dentry, new_parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ }
++
++ lower_new_dentry = unionfs_lower_dentry(new_dentry);
++
++ /* check for a whiteout in new dentry branch, and delete it */
++ err = check_unlink_whiteout(new_dentry, lower_new_dentry,
++ dbstart(new_dentry));
++ if (err > 0) { /* whiteout found and removed successfully */
++ lower_dir_dentry = dget_parent(lower_new_dentry);
++ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++ dput(lower_dir_dentry);
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ err = 0;
++ }
++ if (err)
++ goto out;
++
++ /* check if parent hierachy is needed, then link in same branch */
++ if (dbstart(old_dentry) != dbstart(new_dentry)) {
++ lower_new_dentry = create_parents(dir, new_dentry,
++ new_dentry->d_name.name,
++ dbstart(old_dentry));
++ err = PTR_ERR(lower_new_dentry);
++ if (IS_COPYUP_ERR(err))
++ goto docopyup;
++ if (!lower_new_dentry || IS_ERR(lower_new_dentry))
++ goto out;
++ }
++ lower_new_dentry = unionfs_lower_dentry(new_dentry);
++ lower_old_dentry = unionfs_lower_dentry(old_dentry);
++
++ BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
++ lower_dir_dentry = lock_parent(lower_new_dentry);
++ err = is_robranch(old_dentry);
++ if (!err) {
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
++ lower_new_dentry);
++ lockdep_on();
++ }
++ unlock_dir(lower_dir_dentry);
++
++docopyup:
++ if (IS_COPYUP_ERR(err)) {
++ int old_bstart = dbstart(old_dentry);
++ int bindex;
++
++ for (bindex = old_bstart - 1; bindex >= 0; bindex--) {
++ err = copyup_dentry(old_parent->d_inode,
++ old_dentry, old_bstart,
++ bindex, old_dentry->d_name.name,
++ old_dentry->d_name.len, NULL,
++ i_size_read(old_dentry->d_inode));
++ if (err)
++ continue;
++ lower_new_dentry =
++ create_parents(dir, new_dentry,
++ new_dentry->d_name.name,
++ bindex);
++ lower_old_dentry = unionfs_lower_dentry(old_dentry);
++ lower_dir_dentry = lock_parent(lower_new_dentry);
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ /* do vfs_link */
++ err = vfs_link(lower_old_dentry,
++ lower_dir_dentry->d_inode,
++ lower_new_dentry);
++ lockdep_on();
++ unlock_dir(lower_dir_dentry);
++ goto check_link;
++ }
++ goto out;
++ }
++
++check_link:
++ if (err || !lower_new_dentry->d_inode)
++ goto out;
++
++ /* Its a hard link, so use the same inode */
++ new_dentry->d_inode = igrab(old_dentry->d_inode);
++ d_add(new_dentry, new_dentry->d_inode);
++ unionfs_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode);
++ fsstack_copy_inode_size(dir, lower_new_dentry->d_parent->d_inode);
++
++ /* propagate number of hard-links */
++ old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode);
++ /* new dentry's ctime may have changed due to hard-link counts */
++ unionfs_copy_attr_times(new_dentry->d_inode);
++
++out:
++ if (!new_dentry->d_inode)
++ d_drop(new_dentry);
++
++ kfree(name);
++ if (!err)
++ unionfs_postcopyup_setmnt(new_dentry);
++
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(new_dentry);
++ unionfs_check_dentry(old_dentry);
++
++ unionfs_double_unlock_dentry(old_dentry, new_dentry);
++ unionfs_double_unlock_parents(old_parent, new_parent);
++ dput(new_parent);
++ dput(old_parent);
++ unionfs_read_unlock(old_dentry->d_sb);
++
++ return err;
++}
++
++static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
++ const char *symname)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct dentry *wh_dentry = NULL;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *parent;
++ char *name = NULL;
++ int valid = 0;
++ umode_t mode;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ /*
++ * It's only a bug if this dentry was not negative and couldn't be
++ * revalidated (shouldn't happen).
++ */
++ BUG_ON(!valid && dentry->d_inode);
++
++ lower_dentry = find_writeable_branch(dir, dentry);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++
++ lower_parent_dentry = lock_parent(lower_dentry);
++ if (IS_ERR(lower_parent_dentry)) {
++ err = PTR_ERR(lower_parent_dentry);
++ goto out_unlock;
++ }
++
++ mode = S_IALLUGO;
++ err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname);
++ if (!err) {
++ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
++ if (!err) {
++ unionfs_copy_attr_times(dir);
++ fsstack_copy_inode_size(dir,
++ lower_parent_dentry->d_inode);
++ /* update no. of links on parent directory */
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ }
++ }
++
++out_unlock:
++ unlock_dir(lower_parent_dentry);
++out:
++ dput(wh_dentry);
++ kfree(name);
++
++ if (!err) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static int unionfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *parent;
++ int bindex = 0, bstart;
++ char *name = NULL;
++ int valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE; /* same as what real_lookup does */
++ goto out;
++ }
++
++ bstart = dbstart(dentry);
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ /* check for a whiteout in new dentry branch, and delete it */
++ err = check_unlink_whiteout(dentry, lower_dentry, bstart);
++ if (err > 0) /* whiteout found and removed successfully */
++ err = 0;
++ if (err) {
++ /* exit if the error returned was NOT -EROFS */
++ if (!IS_COPYUP_ERR(err))
++ goto out;
++ bstart--;
++ }
++
++ /* check if copyup's needed, and mkdir */
++ for (bindex = bstart; bindex >= 0; bindex--) {
++ int i;
++ int bend = dbend(dentry);
++
++ if (is_robranch_super(dentry->d_sb, bindex))
++ continue;
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry) {
++ lower_dentry = create_parents(dir, dentry,
++ dentry->d_name.name,
++ bindex);
++ if (!lower_dentry || IS_ERR(lower_dentry)) {
++ printk(KERN_ERR "unionfs: lower dentry "
++ " NULL for bindex = %d\n", bindex);
++ continue;
++ }
++ }
++
++ lower_parent_dentry = lock_parent(lower_dentry);
++
++ if (IS_ERR(lower_parent_dentry)) {
++ err = PTR_ERR(lower_parent_dentry);
++ goto out;
++ }
++
++ err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry,
++ mode);
++
++ unlock_dir(lower_parent_dentry);
++
++ /* did the mkdir succeed? */
++ if (err)
++ break;
++
++ for (i = bindex + 1; i <= bend; i++) {
++ /* XXX: use path_put_lowers? */
++ if (unionfs_lower_dentry_idx(dentry, i)) {
++ dput(unionfs_lower_dentry_idx(dentry, i));
++ unionfs_set_lower_dentry_idx(dentry, i, NULL);
++ }
++ }
++ dbend(dentry) = bindex;
++
++ /*
++ * Only INTERPOSE_LOOKUP can return a value other than 0 on
++ * err.
++ */
++ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
++ if (!err) {
++ unionfs_copy_attr_times(dir);
++ fsstack_copy_inode_size(dir,
++ lower_parent_dentry->d_inode);
++
++ /* update number of links on parent directory */
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ }
++
++ err = make_dir_opaque(dentry, dbstart(dentry));
++ if (err) {
++ printk(KERN_ERR "unionfs: mkdir: error creating "
++ ".wh.__dir_opaque: %d\n", err);
++ goto out;
++ }
++
++ /* we are done! */
++ break;
++ }
++
++out:
++ if (!dentry->d_inode)
++ d_drop(dentry);
++
++ kfree(name);
++
++ if (!err) {
++ unionfs_copy_attr_times(dentry->d_inode);
++ unionfs_postcopyup_setmnt(dentry);
++ }
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return err;
++}
++
++static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
++ dev_t dev)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct dentry *wh_dentry = NULL;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *parent;
++ char *name = NULL;
++ int valid = 0;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ /*
++ * It's only a bug if this dentry was not negative and couldn't be
++ * revalidated (shouldn't happen).
++ */
++ BUG_ON(!valid && dentry->d_inode);
++
++ lower_dentry = find_writeable_branch(dir, dentry);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++
++ lower_parent_dentry = lock_parent(lower_dentry);
++ if (IS_ERR(lower_parent_dentry)) {
++ err = PTR_ERR(lower_parent_dentry);
++ goto out_unlock;
++ }
++
++ err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
++ if (!err) {
++ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
++ if (!err) {
++ unionfs_copy_attr_times(dir);
++ fsstack_copy_inode_size(dir,
++ lower_parent_dentry->d_inode);
++ /* update no. of links on parent directory */
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ }
++ }
++
++out_unlock:
++ unlock_dir(lower_parent_dentry);
++out:
++ dput(wh_dentry);
++ kfree(name);
++
++ if (!err) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/* requires sb, dentry, and parent to already be locked */
++static int __unionfs_readlink(struct dentry *dentry, char __user *buf,
++ int bufsiz)
++{
++ int err;
++ struct dentry *lower_dentry;
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ if (!lower_dentry->d_inode->i_op ||
++ !lower_dentry->d_inode->i_op->readlink) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
++ buf, bufsiz);
++ if (err >= 0)
++ fsstack_copy_attr_atime(dentry->d_inode,
++ lower_dentry->d_inode);
++
++out:
++ return err;
++}
++
++static int unionfs_readlink(struct dentry *dentry, char __user *buf,
++ int bufsiz)
++{
++ int err;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ err = __unionfs_readlink(dentry, buf, bufsiz);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return err;
++}
++
++static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ char *buf;
++ int len = PAGE_SIZE, err;
++ mm_segment_t old_fs;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ /* This is freed by the put_link method assuming a successful call. */
++ buf = kmalloc(len, GFP_KERNEL);
++ if (unlikely(!buf)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ /* read the symlink, and then we will follow it */
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = __unionfs_readlink(dentry, buf, len);
++ set_fs(old_fs);
++ if (err < 0) {
++ kfree(buf);
++ buf = NULL;
++ goto out;
++ }
++ buf[err] = 0;
++ nd_set_link(nd, buf);
++ err = 0;
++
++out:
++ if (err >= 0) {
++ unionfs_check_nd(nd);
++ unionfs_check_dentry(dentry);
++ }
++
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return ERR_PTR(err);
++}
++
++/* this @nd *IS* still used */
++static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd,
++ void *cookie)
++{
++ struct dentry *parent;
++ char *buf;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false)))
++ printk(KERN_ERR
++ "unionfs: put_link failed to revalidate dentry\n");
++
++ unionfs_check_dentry(dentry);
++#if 0
++ /* XXX: can't run this check b/c this fxn can receive a poisoned 'nd' PTR */
++ unionfs_check_nd(nd);
++#endif
++ buf = nd_get_link(nd);
++ if (!IS_ERR(buf))
++ kfree(buf);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++}
++
++/*
++ * This is a variant of fs/namei.c:permission() or inode_permission() which
++ * skips over EROFS tests (because we perform copyup on EROFS).
++ */
++static int __inode_permission(struct inode *inode, int mask)
++{
++ int retval;
++
++ /* nobody gets write access to an immutable file */
++ if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
++ return -EACCES;
++
++ /* Ordinary permission routines do not understand MAY_APPEND. */
++ if (inode->i_op && inode->i_op->permission) {
++ retval = inode->i_op->permission(inode, mask);
++ if (!retval) {
++ /*
++ * Exec permission on a regular file is denied if none
++ * of the execute bits are set.
++ *
++ * This check should be done by the ->permission()
++ * method.
++ */
++ if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
++ !(inode->i_mode & S_IXUGO))
++ return -EACCES;
++ }
++ } else {
++ retval = generic_permission(inode, mask, NULL);
++ }
++ if (retval)
++ return retval;
++
++ return security_inode_permission(inode,
++ mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
++}
++
++/*
++ * Don't grab the superblock read-lock in unionfs_permission, which prevents
++ * a deadlock with the branch-management "add branch" code (which grabbed
++ * the write lock). It is safe to not grab the read lock here, because even
++ * with branch management taking place, there is no chance that
++ * unionfs_permission, or anything it calls, will use stale branch
++ * information.
++ */
++static int unionfs_permission(struct inode *inode, int mask)
++{
++ struct inode *lower_inode = NULL;
++ int err = 0;
++ int bindex, bstart, bend;
++ const int is_file = !S_ISDIR(inode->i_mode);
++ const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);
++ struct inode *inode_grabbed = igrab(inode);
++ struct dentry *dentry = d_find_alias(inode);
++
++ if (dentry)
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (!UNIONFS_I(inode)->lower_inodes) {
++ if (is_file) /* dirs can be unlinked but chdir'ed to */
++ err = -ESTALE; /* force revalidate */
++ goto out;
++ }
++ bstart = ibstart(inode);
++ bend = ibend(inode);
++ if (unlikely(bstart < 0 || bend < 0)) {
++ /*
++ * With branch-management, we can get a stale inode here.
++ * If so, we return ESTALE back to link_path_walk, which
++ * would discard the dcache entry and re-lookup the
++ * dentry+inode. This should be equivalent to issuing
++ * __unionfs_d_revalidate_chain on nd.dentry here.
++ */
++ if (is_file) /* dirs can be unlinked but chdir'ed to */
++ err = -ESTALE; /* force revalidate */
++ goto out;
++ }
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++
++ /*
++ * check the condition for D-F-D underlying files/directories,
++ * we don't have to check for files, if we are checking for
++ * directories.
++ */
++ if (!is_file && !S_ISDIR(lower_inode->i_mode))
++ continue;
++
++ /*
++ * We check basic permissions, but we ignore any conditions
++ * such as readonly file systems or branches marked as
++ * readonly, because those conditions should lead to a
++ * copyup taking place later on. However, if user never had
++ * access to the file, then no copyup could ever take place.
++ */
++ err = __inode_permission(lower_inode, mask);
++ if (err && err != -EACCES && err != EPERM && bindex > 0) {
++ umode_t mode = lower_inode->i_mode;
++ if ((is_robranch_super(inode->i_sb, bindex) ||
++ __is_rdonly(lower_inode)) &&
++ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
++ err = 0;
++ if (IS_COPYUP_ERR(err))
++ err = 0;
++ }
++
++ /*
++ * NFS HACK: NFSv2/3 return EACCES on readonly-exported,
++ * locally readonly-mounted file systems, instead of EROFS
++ * like other file systems do. So we have no choice here
++ * but to intercept this and ignore it for NFS branches
++ * marked readonly. Specifically, we avoid using NFS's own
++ * "broken" ->permission method, and rely on
++ * generic_permission() to do basic checking for us.
++ */
++ if (err && err == -EACCES &&
++ is_robranch_super(inode->i_sb, bindex) &&
++ lower_inode->i_sb->s_magic == NFS_SUPER_MAGIC)
++ err = generic_permission(lower_inode, mask, NULL);
++
++ /*
++ * The permissions are an intersection of the overall directory
++ * permissions, so we fail if one fails.
++ */
++ if (err)
++ goto out;
++
++ /* only the leftmost file matters. */
++ if (is_file || write_mask) {
++ if (is_file && write_mask) {
++ err = get_write_access(lower_inode);
++ if (!err)
++ put_write_access(lower_inode);
++ }
++ break;
++ }
++ }
++ /* sync times which may have changed (asynchronously) below */
++ unionfs_copy_attr_times(inode);
++
++out:
++ unionfs_check_inode(inode);
++ if (dentry) {
++ unionfs_unlock_dentry(dentry);
++ dput(dentry);
++ }
++ iput(inode_grabbed);
++ return err;
++}
++
++static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
++{
++ int err = 0;
++ struct dentry *lower_dentry;
++ struct dentry *parent;
++ struct inode *inode;
++ struct inode *lower_inode;
++ int bstart, bend, bindex;
++ loff_t size;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ inode = dentry->d_inode;
++
++ /*
++ * mode change is for clearing setuid/setgid. Allow lower filesystem
++ * to reinterpret it in its own way.
++ */
++ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
++ ia->ia_valid &= ~ATTR_MODE;
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++ if (!lower_dentry) { /* should never happen after above revalidate */
++ err = -EINVAL;
++ goto out;
++ }
++ lower_inode = unionfs_lower_inode(inode);
++
++ /* check if user has permission to change lower inode */
++ err = inode_change_ok(lower_inode, ia);
++ if (err)
++ goto out;
++
++ /* copyup if the file is on a read only branch */
++ if (is_robranch_super(dentry->d_sb, bstart)
++ || __is_rdonly(lower_inode)) {
++ /* check if we have a branch to copy up to */
++ if (bstart <= 0) {
++ err = -EACCES;
++ goto out;
++ }
++
++ if (ia->ia_valid & ATTR_SIZE)
++ size = ia->ia_size;
++ else
++ size = i_size_read(inode);
++ /* copyup to next available branch */
++ for (bindex = bstart - 1; bindex >= 0; bindex--) {
++ err = copyup_dentry(parent->d_inode,
++ dentry, bstart, bindex,
++ dentry->d_name.name,
++ dentry->d_name.len,
++ NULL, size);
++ if (!err)
++ break;
++ }
++ if (err)
++ goto out;
++ /* get updated lower_dentry/inode after copyup */
++ lower_dentry = unionfs_lower_dentry(dentry);
++ lower_inode = unionfs_lower_inode(inode);
++ }
++
++ /*
++ * If shrinking, first truncate upper level to cancel writing dirty
++ * pages beyond the new eof; and also if its' maxbytes is more
++ * limiting (fail with -EFBIG before making any change to the lower
++ * level). There is no need to vmtruncate the upper level
++ * afterwards in the other cases: we fsstack_copy_inode_size from
++ * the lower level.
++ */
++ if (ia->ia_valid & ATTR_SIZE) {
++ size = i_size_read(inode);
++ if (ia->ia_size < size || (ia->ia_size > size &&
++ inode->i_sb->s_maxbytes < lower_inode->i_sb->s_maxbytes)) {
++ err = vmtruncate(inode, ia->ia_size);
++ if (err)
++ goto out;
++ }
++ }
++
++ /* notify the (possibly copied-up) lower inode */
++ /*
++ * Note: we use lower_dentry->d_inode, because lower_inode may be
++ * unlinked (no inode->i_sb and i_ino==0. This happens if someone
++ * tries to open(), unlink(), then ftruncate() a file.
++ */
++ mutex_lock(&lower_dentry->d_inode->i_mutex);
++ err = notify_change(lower_dentry, ia);
++ mutex_unlock(&lower_dentry->d_inode->i_mutex);
++ if (err)
++ goto out;
++
++ /* get attributes from the first lower inode */
++ if (ibstart(inode) >= 0)
++ unionfs_copy_attr_all(inode, lower_inode);
++ /*
++ * unionfs_copy_attr_all will copy the lower times to our inode if
++ * the lower ones are newer (useful for cache coherency). However,
++ * ->setattr is the only place in which we may have to copy the
++ * lower inode times absolutely, to support utimes(2).
++ */
++ if (ia->ia_valid & ATTR_MTIME_SET)
++ inode->i_mtime = lower_inode->i_mtime;
++ if (ia->ia_valid & ATTR_CTIME)
++ inode->i_ctime = lower_inode->i_ctime;
++ if (ia->ia_valid & ATTR_ATIME_SET)
++ inode->i_atime = lower_inode->i_atime;
++ fsstack_copy_inode_size(inode, lower_inode);
++
++out:
++ if (!err)
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return err;
++}
++
++struct inode_operations unionfs_symlink_iops = {
++ .readlink = unionfs_readlink,
++ .permission = unionfs_permission,
++ .follow_link = unionfs_follow_link,
++ .setattr = unionfs_setattr,
++ .put_link = unionfs_put_link,
++};
++
++struct inode_operations unionfs_dir_iops = {
++ .create = unionfs_create,
++ .lookup = unionfs_lookup,
++ .link = unionfs_link,
++ .unlink = unionfs_unlink,
++ .symlink = unionfs_symlink,
++ .mkdir = unionfs_mkdir,
++ .rmdir = unionfs_rmdir,
++ .mknod = unionfs_mknod,
++ .rename = unionfs_rename,
++ .permission = unionfs_permission,
++ .setattr = unionfs_setattr,
++#ifdef CONFIG_UNION_FS_XATTR
++ .setxattr = unionfs_setxattr,
++ .getxattr = unionfs_getxattr,
++ .removexattr = unionfs_removexattr,
++ .listxattr = unionfs_listxattr,
++#endif /* CONFIG_UNION_FS_XATTR */
++};
++
++struct inode_operations unionfs_main_iops = {
++ .permission = unionfs_permission,
++ .setattr = unionfs_setattr,
++#ifdef CONFIG_UNION_FS_XATTR
++ .setxattr = unionfs_setxattr,
++ .getxattr = unionfs_getxattr,
++ .removexattr = unionfs_removexattr,
++ .listxattr = unionfs_listxattr,
++#endif /* CONFIG_UNION_FS_XATTR */
++};
+diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
+new file mode 100644
+index 0000000..b63c17e
+--- /dev/null
++++ b/fs/unionfs/lookup.c
+@@ -0,0 +1,569 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * Lookup one path component @name relative to a <base,mnt> path pair.
++ * Behaves nearly the same as lookup_one_len (i.e., return negative dentry
++ * on ENOENT), but uses the @mnt passed, so it can cross bind mounts and
++ * other lower mounts properly. If @new_mnt is non-null, will fill in the
++ * new mnt there. Caller is responsible to dput/mntput/path_put returned
++ * @dentry and @new_mnt.
++ */
++struct dentry *__lookup_one(struct dentry *base, struct vfsmount *mnt,
++ const char *name, struct vfsmount **new_mnt)
++{
++ struct dentry *dentry = NULL;
++ struct nameidata lower_nd;
++ int err;
++
++ /* we use flags=0 to get basic lookup */
++ err = vfs_path_lookup(base, mnt, name, 0, &lower_nd);
++
++ switch (err) {
++ case 0: /* no error */
++ dentry = lower_nd.path.dentry;
++ if (new_mnt)
++ *new_mnt = lower_nd.path.mnt; /* rc already inc'ed */
++ break;
++ case -ENOENT:
++ /*
++ * We don't consider ENOENT an error, and we want to return
++ * a negative dentry (ala lookup_one_len). As we know
++ * there was no inode for this name before (-ENOENT), then
++ * it's safe to call lookup_one_len (which doesn't take a
++ * vfsmount).
++ */
++ dentry = lookup_lck_len(name, base, strlen(name));
++ if (new_mnt)
++ *new_mnt = mntget(lower_nd.path.mnt);
++ break;
++ default: /* all other real errors */
++ dentry = ERR_PTR(err);
++ break;
++ }
++
++ return dentry;
++}
++
++/*
++ * This is a utility function that fills in a unionfs dentry.
++ * Caller must lock this dentry with unionfs_lock_dentry.
++ *
++ * Returns: 0 (ok), or -ERRNO if an error occurred.
++ * XXX: get rid of _partial_lookup and make callers call _lookup_full directly
++ */
++int unionfs_partial_lookup(struct dentry *dentry, struct dentry *parent)
++{
++ struct dentry *tmp;
++ int err = -ENOSYS;
++
++ tmp = unionfs_lookup_full(dentry, parent, INTERPOSE_PARTIAL);
++
++ if (!tmp) {
++ err = 0;
++ goto out;
++ }
++ if (IS_ERR(tmp)) {
++ err = PTR_ERR(tmp);
++ goto out;
++ }
++ /* XXX: need to change the interface */
++ BUG_ON(tmp != dentry);
++out:
++ return err;
++}
++
++/* The dentry cache is just so we have properly sized dentries. */
++static struct kmem_cache *unionfs_dentry_cachep;
++int unionfs_init_dentry_cache(void)
++{
++ unionfs_dentry_cachep =
++ kmem_cache_create("unionfs_dentry",
++ sizeof(struct unionfs_dentry_info),
++ 0, SLAB_RECLAIM_ACCOUNT, NULL);
++
++ return (unionfs_dentry_cachep ? 0 : -ENOMEM);
++}
++
++void unionfs_destroy_dentry_cache(void)
++{
++ if (unionfs_dentry_cachep)
++ kmem_cache_destroy(unionfs_dentry_cachep);
++}
++
++void free_dentry_private_data(struct dentry *dentry)
++{
++ if (!dentry || !dentry->d_fsdata)
++ return;
++ kfree(UNIONFS_D(dentry)->lower_paths);
++ UNIONFS_D(dentry)->lower_paths = NULL;
++ kmem_cache_free(unionfs_dentry_cachep, dentry->d_fsdata);
++ dentry->d_fsdata = NULL;
++}
++
++static inline int __realloc_dentry_private_data(struct dentry *dentry)
++{
++ struct unionfs_dentry_info *info = UNIONFS_D(dentry);
++ void *p;
++ int size;
++
++ BUG_ON(!info);
++
++ size = sizeof(struct path) * sbmax(dentry->d_sb);
++ p = krealloc(info->lower_paths, size, GFP_ATOMIC);
++ if (unlikely(!p))
++ return -ENOMEM;
++
++ info->lower_paths = p;
++
++ info->bstart = -1;
++ info->bend = -1;
++ info->bopaque = -1;
++ info->bcount = sbmax(dentry->d_sb);
++ atomic_set(&info->generation,
++ atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
++
++ memset(info->lower_paths, 0, size);
++
++ return 0;
++}
++
++/* UNIONFS_D(dentry)->lock must be locked */
++int realloc_dentry_private_data(struct dentry *dentry)
++{
++ if (!__realloc_dentry_private_data(dentry))
++ return 0;
++
++ kfree(UNIONFS_D(dentry)->lower_paths);
++ free_dentry_private_data(dentry);
++ return -ENOMEM;
++}
++
++/* allocate new dentry private data */
++int new_dentry_private_data(struct dentry *dentry, int subclass)
++{
++ struct unionfs_dentry_info *info = UNIONFS_D(dentry);
++
++ BUG_ON(info);
++
++ info = kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC);
++ if (unlikely(!info))
++ return -ENOMEM;
++
++ mutex_init(&info->lock);
++ mutex_lock_nested(&info->lock, subclass);
++
++ info->lower_paths = NULL;
++
++ dentry->d_fsdata = info;
++
++ if (!__realloc_dentry_private_data(dentry))
++ return 0;
++
++ mutex_unlock(&info->lock);
++ free_dentry_private_data(dentry);
++ return -ENOMEM;
++}
++
++/*
++ * scan through the lower dentry objects, and set bstart to reflect the
++ * starting branch
++ */
++void update_bstart(struct dentry *dentry)
++{
++ int bindex;
++ int bstart = dbstart(dentry);
++ int bend = dbend(dentry);
++ struct dentry *lower_dentry;
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ if (lower_dentry->d_inode) {
++ dbstart(dentry) = bindex;
++ break;
++ }
++ dput(lower_dentry);
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ }
++}
++
++
++/*
++ * Initialize a nameidata structure (the intent part) we can pass to a lower
++ * file system. Returns 0 on success or -error (only -ENOMEM possible).
++ * Inside that nd structure, this function may also return an allocated
++ * struct file (for open intents). The caller, when done with this nd, must
++ * kfree the intent file (using release_lower_nd).
++ *
++ * XXX: this code, and the callers of this code, should be redone using
++ * vfs_path_lookup() when (1) the nameidata structure is refactored into a
++ * separate intent-structure, and (2) open_namei() is broken into a VFS-only
++ * function and a method that other file systems can call.
++ */
++int init_lower_nd(struct nameidata *nd, unsigned int flags)
++{
++ int err = 0;
++#ifdef ALLOC_LOWER_ND_FILE
++ /*
++ * XXX: one day we may need to have the lower return an open file
++ * for us. It is not needed in 2.6.23-rc1 for nfs2/nfs3, but may
++ * very well be needed for nfs4.
++ */
++ struct file *file;
++#endif /* ALLOC_LOWER_ND_FILE */
++
++ memset(nd, 0, sizeof(struct nameidata));
++ if (!flags)
++ return err;
++
++ switch (flags) {
++ case LOOKUP_CREATE:
++ nd->intent.open.flags |= O_CREAT;
++ /* fall through: shared code for create/open cases */
++ case LOOKUP_OPEN:
++ nd->flags = flags;
++ nd->intent.open.flags |= (FMODE_READ | FMODE_WRITE);
++#ifdef ALLOC_LOWER_ND_FILE
++ file = kzalloc(sizeof(struct file), GFP_KERNEL);
++ if (unlikely(!file)) {
++ err = -ENOMEM;
++ break; /* exit switch statement and thus return */
++ }
++ nd->intent.open.file = file;
++#endif /* ALLOC_LOWER_ND_FILE */
++ break;
++ default:
++ /*
++ * We should never get here, for now.
++ * We can add new cases here later on.
++ */
++ pr_debug("unionfs: unknown nameidata flag 0x%x\n", flags);
++ BUG();
++ break;
++ }
++
++ return err;
++}
++
++void release_lower_nd(struct nameidata *nd, int err)
++{
++ if (!nd->intent.open.file)
++ return;
++ else if (!err)
++ release_open_intent(nd);
++#ifdef ALLOC_LOWER_ND_FILE
++ kfree(nd->intent.open.file);
++#endif /* ALLOC_LOWER_ND_FILE */
++}
++
++/*
++ * Main (and complex) driver function for Unionfs's lookup
++ *
++ * Returns: NULL (ok), ERR_PTR if an error occurred, or a non-null non-error
++ * PTR if d_splice returned a different dentry.
++ *
++ * If lookupmode is INTERPOSE_PARTIAL/REVAL/REVAL_NEG, the passed dentry's
++ * inode info must be locked. If lookupmode is INTERPOSE_LOOKUP (i.e., a
++ * newly looked-up dentry), then unionfs_lookup_backend will return a locked
++ * dentry's info, which the caller must unlock.
++ */
++struct dentry *unionfs_lookup_full(struct dentry *dentry,
++ struct dentry *parent, int lookupmode)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct vfsmount *lower_mnt;
++ struct vfsmount *lower_dir_mnt;
++ struct dentry *wh_lower_dentry = NULL;
++ struct dentry *lower_dir_dentry = NULL;
++ struct dentry *d_interposed = NULL;
++ int bindex, bstart, bend, bopaque;
++ int opaque, num_positive = 0;
++ const char *name;
++ int namelen;
++ int pos_start, pos_end;
++
++ /*
++ * We should already have a lock on this dentry in the case of a
++ * partial lookup, or a revalidation. Otherwise it is returned from
++ * new_dentry_private_data already locked.
++ */
++ verify_locked(dentry);
++ verify_locked(parent);
++
++ /* must initialize dentry operations */
++ dentry->d_op = &unionfs_dops;
++
++ /* We never partial lookup the root directory. */
++ if (IS_ROOT(dentry))
++ goto out;
++
++ name = dentry->d_name.name;
++ namelen = dentry->d_name.len;
++
++ /* No dentries should get created for possible whiteout names. */
++ if (!is_validname(name)) {
++ err = -EPERM;
++ goto out_free;
++ }
++
++ /* Now start the actual lookup procedure. */
++ bstart = dbstart(parent);
++ bend = dbend(parent);
++ bopaque = dbopaque(parent);
++ BUG_ON(bstart < 0);
++
++ /* adjust bend to bopaque if needed */
++ if ((bopaque >= 0) && (bopaque < bend))
++ bend = bopaque;
++
++ /* lookup all possible dentries */
++ for (bindex = bstart; bindex <= bend; bindex++) {
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
++
++ /* skip if we already have a positive lower dentry */
++ if (lower_dentry) {
++ if (dbstart(dentry) < 0)
++ dbstart(dentry) = bindex;
++ if (bindex > dbend(dentry))
++ dbend(dentry) = bindex;
++ if (lower_dentry->d_inode)
++ num_positive++;
++ continue;
++ }
++
++ lower_dir_dentry =
++ unionfs_lower_dentry_idx(parent, bindex);
++ /* if the lower dentry's parent does not exist, skip this */
++ if (!lower_dir_dentry || !lower_dir_dentry->d_inode)
++ continue;
++
++ /* also skip it if the parent isn't a directory. */
++ if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
++ continue; /* XXX: should be BUG_ON */
++
++ /* check for whiteouts: stop lookup if found */
++ wh_lower_dentry = lookup_whiteout(name, lower_dir_dentry);
++ if (IS_ERR(wh_lower_dentry)) {
++ err = PTR_ERR(wh_lower_dentry);
++ goto out_free;
++ }
++ if (wh_lower_dentry->d_inode) {
++ dbend(dentry) = dbopaque(dentry) = bindex;
++ if (dbstart(dentry) < 0)
++ dbstart(dentry) = bindex;
++ dput(wh_lower_dentry);
++ break;
++ }
++ dput(wh_lower_dentry);
++
++ /* Now do regular lookup; lookup @name */
++ lower_dir_mnt = unionfs_lower_mnt_idx(parent, bindex);
++ lower_mnt = NULL; /* XXX: needed? */
++
++ lower_dentry = __lookup_one(lower_dir_dentry, lower_dir_mnt,
++ name, &lower_mnt);
++
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out_free;
++ }
++ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
++ if (!lower_mnt)
++ lower_mnt = unionfs_mntget(dentry->d_sb->s_root,
++ bindex);
++ unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt);
++
++ /* adjust dbstart/end */
++ if (dbstart(dentry) < 0)
++ dbstart(dentry) = bindex;
++ if (bindex > dbend(dentry))
++ dbend(dentry) = bindex;
++ /*
++ * We always store the lower dentries above, and update
++ * dbstart/dbend, even if the whole unionfs dentry is
++ * negative (i.e., no lower inodes).
++ */
++ if (!lower_dentry->d_inode)
++ continue;
++ num_positive++;
++
++ /*
++ * check if we just found an opaque directory, if so, stop
++ * lookups here.
++ */
++ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
++ continue;
++ opaque = is_opaque_dir(dentry, bindex);
++ if (opaque < 0) {
++ err = opaque;
++ goto out_free;
++ } else if (opaque) {
++ dbend(dentry) = dbopaque(dentry) = bindex;
++ break;
++ }
++ dbend(dentry) = bindex;
++
++ /* update parent directory's atime with the bindex */
++ fsstack_copy_attr_atime(parent->d_inode,
++ lower_dir_dentry->d_inode);
++ }
++
++ /* sanity checks, then decide if to process a negative dentry */
++ BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0);
++ BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0);
++
++ if (num_positive > 0)
++ goto out_positive;
++
++ /*** handle NEGATIVE dentries ***/
++
++ /*
++ * If negative, keep only first lower negative dentry, to save on
++ * memory.
++ */
++ if (dbstart(dentry) < dbend(dentry)) {
++ path_put_lowers(dentry, dbstart(dentry) + 1,
++ dbend(dentry), false);
++ dbend(dentry) = dbstart(dentry);
++ }
++ if (lookupmode == INTERPOSE_PARTIAL)
++ goto out;
++ if (lookupmode == INTERPOSE_LOOKUP) {
++ /*
++ * If all we found was a whiteout in the first available
++ * branch, then create a negative dentry for a possibly new
++ * file to be created.
++ */
++ if (dbopaque(dentry) < 0)
++ goto out;
++ /* XXX: need to get mnt here */
++ bindex = dbstart(dentry);
++ if (unionfs_lower_dentry_idx(dentry, bindex))
++ goto out;
++ lower_dir_dentry =
++ unionfs_lower_dentry_idx(parent, bindex);
++ if (!lower_dir_dentry || !lower_dir_dentry->d_inode)
++ goto out;
++ if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
++ goto out; /* XXX: should be BUG_ON */
++ /* XXX: do we need to cross bind mounts here? */
++ lower_dentry = lookup_lck_len(name, lower_dir_dentry, namelen);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++ /* XXX: need to mntget/mntput as needed too! */
++ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
++ /* XXX: wrong mnt for crossing bind mounts! */
++ lower_mnt = unionfs_mntget(dentry->d_sb->s_root, bindex);
++ unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt);
++
++ goto out;
++ }
++
++ /* if we're revalidating a positive dentry, don't make it negative */
++ if (lookupmode != INTERPOSE_REVAL)
++ d_add(dentry, NULL);
++
++ goto out;
++
++out_positive:
++ /*** handle POSITIVE dentries ***/
++
++ /*
++ * This unionfs dentry is positive (at least one lower inode
++ * exists), so scan entire dentry from beginning to end, and remove
++ * any negative lower dentries, if any. Then, update dbstart/dbend
++ * to reflect the start/end of positive dentries.
++ */
++ pos_start = pos_end = -1;
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry,
++ bindex);
++ if (lower_dentry && lower_dentry->d_inode) {
++ if (pos_start < 0)
++ pos_start = bindex;
++ if (bindex > pos_end)
++ pos_end = bindex;
++ continue;
++ }
++ path_put_lowers(dentry, bindex, bindex, false);
++ }
++ if (pos_start >= 0)
++ dbstart(dentry) = pos_start;
++ if (pos_end >= 0)
++ dbend(dentry) = pos_end;
++
++ /* Partial lookups need to re-interpose, or throw away older negs. */
++ if (lookupmode == INTERPOSE_PARTIAL) {
++ if (dentry->d_inode) {
++ unionfs_reinterpose(dentry);
++ goto out;
++ }
++
++ /*
++ * This dentry was positive, so it is as if we had a
++ * negative revalidation.
++ */
++ lookupmode = INTERPOSE_REVAL_NEG;
++ update_bstart(dentry);
++ }
++
++ /*
++ * Interpose can return a dentry if d_splice returned a different
++ * dentry.
++ */
++ d_interposed = unionfs_interpose(dentry, dentry->d_sb, lookupmode);
++ if (IS_ERR(d_interposed))
++ err = PTR_ERR(d_interposed);
++ else if (d_interposed)
++ dentry = d_interposed;
++
++ if (!err)
++ goto out;
++ d_drop(dentry);
++
++out_free:
++ /* should dput/mntput all the underlying dentries on error condition */
++ if (dbstart(dentry) >= 0)
++ path_put_lowers_all(dentry, false);
++ /* free lower_paths unconditionally */
++ kfree(UNIONFS_D(dentry)->lower_paths);
++ UNIONFS_D(dentry)->lower_paths = NULL;
++
++out:
++ if (dentry && UNIONFS_D(dentry)) {
++ BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0);
++ BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0);
++ }
++ if (d_interposed && UNIONFS_D(d_interposed)) {
++ BUG_ON(dbstart(d_interposed) < 0 && dbend(d_interposed) >= 0);
++ BUG_ON(dbstart(d_interposed) >= 0 && dbend(d_interposed) < 0);
++ }
++
++ if (!err && d_interposed)
++ return d_interposed;
++ return ERR_PTR(err);
++}
+diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
+new file mode 100644
+index 0000000..258386e
+--- /dev/null
++++ b/fs/unionfs/main.c
+@@ -0,0 +1,758 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++
++static void unionfs_fill_inode(struct dentry *dentry,
++ struct inode *inode)
++{
++ struct inode *lower_inode;
++ struct dentry *lower_dentry;
++ int bindex, bstart, bend;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry) {
++ unionfs_set_lower_inode_idx(inode, bindex, NULL);
++ continue;
++ }
++
++ /* Initialize the lower inode to the new lower inode. */
++ if (!lower_dentry->d_inode)
++ continue;
++
++ unionfs_set_lower_inode_idx(inode, bindex,
++ igrab(lower_dentry->d_inode));
++ }
++
++ ibstart(inode) = dbstart(dentry);
++ ibend(inode) = dbend(dentry);
++
++ /* Use attributes from the first branch. */
++ lower_inode = unionfs_lower_inode(inode);
++
++ /* Use different set of inode ops for symlinks & directories */
++ if (S_ISLNK(lower_inode->i_mode))
++ inode->i_op = &unionfs_symlink_iops;
++ else if (S_ISDIR(lower_inode->i_mode))
++ inode->i_op = &unionfs_dir_iops;
++
++ /* Use different set of file ops for directories */
++ if (S_ISDIR(lower_inode->i_mode))
++ inode->i_fop = &unionfs_dir_fops;
++
++ /* properly initialize special inodes */
++ if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
++ S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
++ init_special_inode(inode, lower_inode->i_mode,
++ lower_inode->i_rdev);
++
++ /* all well, copy inode attributes */
++ unionfs_copy_attr_all(inode, lower_inode);
++ fsstack_copy_inode_size(inode, lower_inode);
++}
++
++/*
++ * Connect a unionfs inode dentry/inode with several lower ones. This is
++ * the classic stackable file system "vnode interposition" action.
++ *
++ * @sb: unionfs's super_block
++ */
++struct dentry *unionfs_interpose(struct dentry *dentry, struct super_block *sb,
++ int flag)
++{
++ int err = 0;
++ struct inode *inode;
++ int need_fill_inode = 1;
++ struct dentry *spliced = NULL;
++
++ verify_locked(dentry);
++
++ /*
++ * We allocate our new inode below by calling unionfs_iget,
++ * which will initialize some of the new inode's fields
++ */
++
++ /*
++ * On revalidate we've already got our own inode and just need
++ * to fix it up.
++ */
++ if (flag == INTERPOSE_REVAL) {
++ inode = dentry->d_inode;
++ UNIONFS_I(inode)->bstart = -1;
++ UNIONFS_I(inode)->bend = -1;
++ atomic_set(&UNIONFS_I(inode)->generation,
++ atomic_read(&UNIONFS_SB(sb)->generation));
++
++ UNIONFS_I(inode)->lower_inodes =
++ kcalloc(sbmax(sb), sizeof(struct inode *), GFP_KERNEL);
++ if (unlikely(!UNIONFS_I(inode)->lower_inodes)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ } else {
++ /* get unique inode number for unionfs */
++ inode = unionfs_iget(sb, iunique(sb, UNIONFS_ROOT_INO));
++ if (IS_ERR(inode)) {
++ err = PTR_ERR(inode);
++ goto out;
++ }
++ if (atomic_read(&inode->i_count) > 1)
++ goto skip;
++ }
++
++ need_fill_inode = 0;
++ unionfs_fill_inode(dentry, inode);
++
++skip:
++ /* only (our) lookup wants to do a d_add */
++ switch (flag) {
++ case INTERPOSE_DEFAULT:
++ /* for operations which create new inodes */
++ d_add(dentry, inode);
++ break;
++ case INTERPOSE_REVAL_NEG:
++ d_instantiate(dentry, inode);
++ break;
++ case INTERPOSE_LOOKUP:
++ spliced = d_splice_alias(inode, dentry);
++ if (spliced && spliced != dentry) {
++ /*
++ * d_splice can return a dentry if it was
++ * disconnected and had to be moved. We must ensure
++ * that the private data of the new dentry is
++ * correct and that the inode info was filled
++ * properly. Finally we must return this new
++ * dentry.
++ */
++ spliced->d_op = &unionfs_dops;
++ spliced->d_fsdata = dentry->d_fsdata;
++ dentry->d_fsdata = NULL;
++ dentry = spliced;
++ if (need_fill_inode) {
++ need_fill_inode = 0;
++ unionfs_fill_inode(dentry, inode);
++ }
++ goto out_spliced;
++ } else if (!spliced) {
++ if (need_fill_inode) {
++ need_fill_inode = 0;
++ unionfs_fill_inode(dentry, inode);
++ goto out_spliced;
++ }
++ }
++ break;
++ case INTERPOSE_REVAL:
++ /* Do nothing. */
++ break;
++ default:
++ printk(KERN_CRIT "unionfs: invalid interpose flag passed!\n");
++ BUG();
++ }
++ goto out;
++
++out_spliced:
++ if (!err)
++ return spliced;
++out:
++ return ERR_PTR(err);
++}
++
++/* like interpose above, but for an already existing dentry */
++void unionfs_reinterpose(struct dentry *dentry)
++{
++ struct dentry *lower_dentry;
++ struct inode *inode;
++ int bindex, bstart, bend;
++
++ verify_locked(dentry);
++
++ /* This is pre-allocated inode */
++ inode = dentry->d_inode;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++
++ if (!lower_dentry->d_inode)
++ continue;
++ if (unionfs_lower_inode_idx(inode, bindex))
++ continue;
++ unionfs_set_lower_inode_idx(inode, bindex,
++ igrab(lower_dentry->d_inode));
++ }
++ ibstart(inode) = dbstart(dentry);
++ ibend(inode) = dbend(dentry);
++}
++
++/*
++ * make sure the branch we just looked up (nd) makes sense:
++ *
++ * 1) we're not trying to stack unionfs on top of unionfs
++ * 2) it exists
++ * 3) is a directory
++ */
++int check_branch(struct nameidata *nd)
++{
++ /* XXX: remove in ODF code -- stacking unions allowed there */
++ if (!strcmp(nd->path.dentry->d_sb->s_type->name, UNIONFS_NAME))
++ return -EINVAL;
++ if (!nd->path.dentry->d_inode)
++ return -ENOENT;
++ if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
++ return -ENOTDIR;
++ return 0;
++}
++
++/* checks if two lower_dentries have overlapping branches */
++static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2)
++{
++ struct dentry *dent = NULL;
++
++ dent = dent1;
++ while ((dent != dent2) && (dent->d_parent != dent))
++ dent = dent->d_parent;
++
++ if (dent == dent2)
++ return 1;
++
++ dent = dent2;
++ while ((dent != dent1) && (dent->d_parent != dent))
++ dent = dent->d_parent;
++
++ return (dent == dent1);
++}
++
++/*
++ * Parse "ro" or "rw" options, but default to "rw" if no mode options was
++ * specified. Fill the mode bits in @perms. If encounter an unknown
++ * string, return -EINVAL. Otherwise return 0.
++ */
++int parse_branch_mode(const char *name, int *perms)
++{
++ if (!name || !strcmp(name, "rw")) {
++ *perms = MAY_READ | MAY_WRITE;
++ return 0;
++ }
++ if (!strcmp(name, "ro")) {
++ *perms = MAY_READ;
++ return 0;
++ }
++ return -EINVAL;
++}
++
++/*
++ * parse the dirs= mount argument
++ *
++ * We don't need to lock the superblock private data's rwsem, as we get
++ * called only by unionfs_read_super - it is still a long time before anyone
++ * can even get a reference to us.
++ */
++static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
++ *lower_root_info, char *options)
++{
++ struct nameidata nd;
++ char *name;
++ int err = 0;
++ int branches = 1;
++ int bindex = 0;
++ int i = 0;
++ int j = 0;
++ struct dentry *dent1;
++ struct dentry *dent2;
++
++ if (options[0] == '\0') {
++ printk(KERN_ERR "unionfs: no branches specified\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ /*
++ * Each colon means we have a separator, this is really just a rough
++ * guess, since strsep will handle empty fields for us.
++ */
++ for (i = 0; options[i]; i++)
++ if (options[i] == ':')
++ branches++;
++
++ /* allocate space for underlying pointers to lower dentry */
++ UNIONFS_SB(sb)->data =
++ kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL);
++ if (unlikely(!UNIONFS_SB(sb)->data)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ lower_root_info->lower_paths =
++ kcalloc(branches, sizeof(struct path), GFP_KERNEL);
++ if (unlikely(!lower_root_info->lower_paths)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */
++ branches = 0;
++ while ((name = strsep(&options, ":")) != NULL) {
++ int perms;
++ char *mode = strchr(name, '=');
++
++ if (!name)
++ continue;
++ if (!*name) { /* bad use of ':' (extra colons) */
++ err = -EINVAL;
++ goto out;
++ }
++
++ branches++;
++
++ /* strip off '=' if any */
++ if (mode)
++ *mode++ = '\0';
++
++ err = parse_branch_mode(mode, &perms);
++ if (err) {
++ printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
++ "branch %d\n", mode, bindex);
++ goto out;
++ }
++ /* ensure that leftmost branch is writeable */
++ if (!bindex && !(perms & MAY_WRITE)) {
++ printk(KERN_ERR "unionfs: leftmost branch cannot be "
++ "read-only (use \"-o ro\" to create a "
++ "read-only union)\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ err = path_lookup(name, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory '%s' (error %d)\n",
++ name, err);
++ goto out;
++ }
++
++ err = check_branch(&nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: lower directory "
++ "'%s' is not a valid branch\n", name);
++ path_put(&nd.path);
++ goto out;
++ }
++
++ lower_root_info->lower_paths[bindex].dentry = nd.path.dentry;
++ lower_root_info->lower_paths[bindex].mnt = nd.path.mnt;
++
++ set_branchperms(sb, bindex, perms);
++ set_branch_count(sb, bindex, 0);
++ new_branch_id(sb, bindex);
++
++ if (lower_root_info->bstart < 0)
++ lower_root_info->bstart = bindex;
++ lower_root_info->bend = bindex;
++ bindex++;
++ }
++
++ if (branches == 0) {
++ printk(KERN_ERR "unionfs: no branches specified\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ BUG_ON(branches != (lower_root_info->bend + 1));
++
++ /*
++ * Ensure that no overlaps exist in the branches.
++ *
++ * This test is required because the Linux kernel has no support
++ * currently for ensuring coherency between stackable layers and
++ * branches. If we were to allow overlapping branches, it would be
++ * possible, for example, to delete a file via one branch, which
++ * would not be reflected in another branch. Such incoherency could
++ * lead to inconsistencies and even kernel oopses. Rather than
++ * implement hacks to work around some of these cache-coherency
++ * problems, we prevent branch overlapping, for now. A complete
++ * solution will involve proper kernel/VFS support for cache
++ * coherency, at which time we could safely remove this
++ * branch-overlapping test.
++ */
++ for (i = 0; i < branches; i++) {
++ dent1 = lower_root_info->lower_paths[i].dentry;
++ for (j = i + 1; j < branches; j++) {
++ dent2 = lower_root_info->lower_paths[j].dentry;
++ if (is_branch_overlap(dent1, dent2)) {
++ printk(KERN_ERR "unionfs: branches %d and "
++ "%d overlap\n", i, j);
++ err = -EINVAL;
++ goto out;
++ }
++ }
++ }
++
++out:
++ if (err) {
++ for (i = 0; i < branches; i++)
++ path_put(&lower_root_info->lower_paths[i]);
++
++ kfree(lower_root_info->lower_paths);
++ kfree(UNIONFS_SB(sb)->data);
++
++ /*
++ * MUST clear the pointers to prevent potential double free if
++ * the caller dies later on
++ */
++ lower_root_info->lower_paths = NULL;
++ UNIONFS_SB(sb)->data = NULL;
++ }
++ return err;
++}
++
++/*
++ * Parse mount options. See the manual page for usage instructions.
++ *
++ * Returns the dentry object of the lower-level (lower) directory;
++ * We want to mount our stackable file system on top of that lower directory.
++ */
++static struct unionfs_dentry_info *unionfs_parse_options(
++ struct super_block *sb,
++ char *options)
++{
++ struct unionfs_dentry_info *lower_root_info;
++ char *optname;
++ int err = 0;
++ int bindex;
++ int dirsfound = 0;
++
++ /* allocate private data area */
++ err = -ENOMEM;
++ lower_root_info =
++ kzalloc(sizeof(struct unionfs_dentry_info), GFP_KERNEL);
++ if (unlikely(!lower_root_info))
++ goto out_error;
++ lower_root_info->bstart = -1;
++ lower_root_info->bend = -1;
++ lower_root_info->bopaque = -1;
++
++ while ((optname = strsep(&options, ",")) != NULL) {
++ char *optarg;
++
++ if (!optname || !*optname)
++ continue;
++
++ optarg = strchr(optname, '=');
++ if (optarg)
++ *optarg++ = '\0';
++
++ /*
++ * All of our options take an argument now. Insert ones that
++ * don't, above this check.
++ */
++ if (!optarg) {
++ printk(KERN_ERR "unionfs: %s requires an argument\n",
++ optname);
++ err = -EINVAL;
++ goto out_error;
++ }
++
++ if (!strcmp("dirs", optname)) {
++ if (++dirsfound > 1) {
++ printk(KERN_ERR
++ "unionfs: multiple dirs specified\n");
++ err = -EINVAL;
++ goto out_error;
++ }
++ err = parse_dirs_option(sb, lower_root_info, optarg);
++ if (err)
++ goto out_error;
++ continue;
++ }
++
++ err = -EINVAL;
++ printk(KERN_ERR
++ "unionfs: unrecognized option '%s'\n", optname);
++ goto out_error;
++ }
++ if (dirsfound != 1) {
++ printk(KERN_ERR "unionfs: dirs option required\n");
++ err = -EINVAL;
++ goto out_error;
++ }
++ goto out;
++
++out_error:
++ if (lower_root_info && lower_root_info->lower_paths) {
++ for (bindex = lower_root_info->bstart;
++ bindex >= 0 && bindex <= lower_root_info->bend;
++ bindex++)
++ path_put(&lower_root_info->lower_paths[bindex]);
++ }
++
++ kfree(lower_root_info->lower_paths);
++ kfree(lower_root_info);
++
++ kfree(UNIONFS_SB(sb)->data);
++ UNIONFS_SB(sb)->data = NULL;
++
++ lower_root_info = ERR_PTR(err);
++out:
++ return lower_root_info;
++}
++
++/*
++ * our custom d_alloc_root work-alike
++ *
++ * we can't use d_alloc_root if we want to use our own interpose function
++ * unchanged, so we simply call our own "fake" d_alloc_root
++ */
++static struct dentry *unionfs_d_alloc_root(struct super_block *sb)
++{
++ struct dentry *ret = NULL;
++
++ if (sb) {
++ static const struct qstr name = {
++ .name = "/",
++ .len = 1
++ };
++
++ ret = d_alloc(NULL, &name);
++ if (likely(ret)) {
++ ret->d_op = &unionfs_dops;
++ ret->d_sb = sb;
++ ret->d_parent = ret;
++ }
++ }
++ return ret;
++}
++
++/*
++ * There is no need to lock the unionfs_super_info's rwsem as there is no
++ * way anyone can have a reference to the superblock at this point in time.
++ */
++static int unionfs_read_super(struct super_block *sb, void *raw_data,
++ int silent)
++{
++ int err = 0;
++ struct unionfs_dentry_info *lower_root_info = NULL;
++ int bindex, bstart, bend;
++
++ if (!raw_data) {
++ printk(KERN_ERR
++ "unionfs: read_super: missing data argument\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ /* Allocate superblock private data */
++ sb->s_fs_info = kzalloc(sizeof(struct unionfs_sb_info), GFP_KERNEL);
++ if (unlikely(!UNIONFS_SB(sb))) {
++ printk(KERN_CRIT "unionfs: read_super: out of memory\n");
++ err = -ENOMEM;
++ goto out;
++ }
++
++ UNIONFS_SB(sb)->bend = -1;
++ atomic_set(&UNIONFS_SB(sb)->generation, 1);
++ init_rwsem(&UNIONFS_SB(sb)->rwsem);
++ UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */
++
++ lower_root_info = unionfs_parse_options(sb, raw_data);
++ if (IS_ERR(lower_root_info)) {
++ printk(KERN_ERR
++ "unionfs: read_super: error while parsing options "
++ "(err = %ld)\n", PTR_ERR(lower_root_info));
++ err = PTR_ERR(lower_root_info);
++ lower_root_info = NULL;
++ goto out_free;
++ }
++ if (lower_root_info->bstart == -1) {
++ err = -ENOENT;
++ goto out_free;
++ }
++
++ /* set the lower superblock field of upper superblock */
++ bstart = lower_root_info->bstart;
++ BUG_ON(bstart != 0);
++ sbend(sb) = bend = lower_root_info->bend;
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ struct dentry *d = lower_root_info->lower_paths[bindex].dentry;
++ atomic_inc(&d->d_sb->s_active);
++ unionfs_set_lower_super_idx(sb, bindex, d->d_sb);
++ }
++
++ /* max Bytes is the maximum bytes from highest priority branch */
++ sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
++
++ /*
++ * Our c/m/atime granularity is 1 ns because we may stack on file
++ * systems whose granularity is as good. This is important for our
++ * time-based cache coherency.
++ */
++ sb->s_time_gran = 1;
++
++ sb->s_op = &unionfs_sops;
++
++ /* See comment next to the definition of unionfs_d_alloc_root */
++ sb->s_root = unionfs_d_alloc_root(sb);
++ if (unlikely(!sb->s_root)) {
++ err = -ENOMEM;
++ goto out_dput;
++ }
++
++ /* link the upper and lower dentries */
++ sb->s_root->d_fsdata = NULL;
++ err = new_dentry_private_data(sb->s_root, UNIONFS_DMUTEX_ROOT);
++ if (unlikely(err))
++ goto out_freedpd;
++
++ /* Set the lower dentries for s_root */
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ struct dentry *d;
++ struct vfsmount *m;
++
++ d = lower_root_info->lower_paths[bindex].dentry;
++ m = lower_root_info->lower_paths[bindex].mnt;
++
++ unionfs_set_lower_dentry_idx(sb->s_root, bindex, d);
++ unionfs_set_lower_mnt_idx(sb->s_root, bindex, m);
++ }
++ dbstart(sb->s_root) = bstart;
++ dbend(sb->s_root) = bend;
++
++ /* Set the generation number to one, since this is for the mount. */
++ atomic_set(&UNIONFS_D(sb->s_root)->generation, 1);
++
++ /*
++ * Call interpose to create the upper level inode. Only
++ * INTERPOSE_LOOKUP can return a value other than 0 on err.
++ */
++ err = PTR_ERR(unionfs_interpose(sb->s_root, sb, 0));
++ unionfs_unlock_dentry(sb->s_root);
++ if (!err)
++ goto out;
++ /* else fall through */
++
++out_freedpd:
++ if (UNIONFS_D(sb->s_root)) {
++ kfree(UNIONFS_D(sb->s_root)->lower_paths);
++ free_dentry_private_data(sb->s_root);
++ }
++ dput(sb->s_root);
++
++out_dput:
++ if (lower_root_info && !IS_ERR(lower_root_info)) {
++ for (bindex = lower_root_info->bstart;
++ bindex <= lower_root_info->bend; bindex++) {
++ struct dentry *d;
++ d = lower_root_info->lower_paths[bindex].dentry;
++ /* drop refs we took earlier */
++ atomic_dec(&d->d_sb->s_active);
++ path_put(&lower_root_info->lower_paths[bindex]);
++ }
++ kfree(lower_root_info->lower_paths);
++ kfree(lower_root_info);
++ lower_root_info = NULL;
++ }
++
++out_free:
++ kfree(UNIONFS_SB(sb)->data);
++ kfree(UNIONFS_SB(sb));
++ sb->s_fs_info = NULL;
++
++out:
++ if (lower_root_info && !IS_ERR(lower_root_info)) {
++ kfree(lower_root_info->lower_paths);
++ kfree(lower_root_info);
++ }
++ return err;
++}
++
++static int unionfs_get_sb(struct file_system_type *fs_type,
++ int flags, const char *dev_name,
++ void *raw_data, struct vfsmount *mnt)
++{
++ int err;
++ err = get_sb_nodev(fs_type, flags, raw_data, unionfs_read_super, mnt);
++ if (!err)
++ UNIONFS_SB(mnt->mnt_sb)->dev_name =
++ kstrdup(dev_name, GFP_KERNEL);
++ return err;
++}
++
++static struct file_system_type unionfs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = UNIONFS_NAME,
++ .get_sb = unionfs_get_sb,
++ .kill_sb = generic_shutdown_super,
++ .fs_flags = FS_REVAL_DOT,
++};
++
++static int __init init_unionfs_fs(void)
++{
++ int err;
++
++ pr_info("Registering unionfs " UNIONFS_VERSION "\n");
++
++ err = unionfs_init_filldir_cache();
++ if (unlikely(err))
++ goto out;
++ err = unionfs_init_inode_cache();
++ if (unlikely(err))
++ goto out;
++ err = unionfs_init_dentry_cache();
++ if (unlikely(err))
++ goto out;
++ err = init_sioq();
++ if (unlikely(err))
++ goto out;
++ err = register_filesystem(&unionfs_fs_type);
++out:
++ if (unlikely(err)) {
++ stop_sioq();
++ unionfs_destroy_filldir_cache();
++ unionfs_destroy_inode_cache();
++ unionfs_destroy_dentry_cache();
++ }
++ return err;
++}
++
++static void __exit exit_unionfs_fs(void)
++{
++ stop_sioq();
++ unionfs_destroy_filldir_cache();
++ unionfs_destroy_inode_cache();
++ unionfs_destroy_dentry_cache();
++ unregister_filesystem(&unionfs_fs_type);
++ pr_info("Completed unionfs module unload\n");
++}
++
++MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
++ " (http://www.fsl.cs.sunysb.edu)");
++MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION
++ " (http://unionfs.filesystems.org)");
++MODULE_LICENSE("GPL");
++
++module_init(init_unionfs_fs);
++module_exit(exit_unionfs_fs);
+diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
+new file mode 100644
+index 0000000..1f70535
+--- /dev/null
++++ b/fs/unionfs/mmap.c
+@@ -0,0 +1,89 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2006 Shaya Potter
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++
++/*
++ * XXX: we need a dummy readpage handler because generic_file_mmap (which we
++ * use in unionfs_mmap) checks for the existence of
++ * mapping->a_ops->readpage, else it returns -ENOEXEC. The VFS will need to
++ * be fixed to allow a file system to define vm_ops->fault without any
++ * address_space_ops whatsoever.
++ *
++ * Otherwise, we don't want to use our readpage method at all.
++ */
++static int unionfs_readpage(struct file *file, struct page *page)
++{
++ BUG();
++ return -EINVAL;
++}
++
++static int unionfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ int err;
++ struct file *file, *lower_file;
++ const struct vm_operations_struct *lower_vm_ops;
++ struct vm_area_struct lower_vma;
++
++ BUG_ON(!vma);
++ memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
++ file = lower_vma.vm_file;
++ lower_vm_ops = UNIONFS_F(file)->lower_vm_ops;
++ BUG_ON(!lower_vm_ops);
++
++ lower_file = unionfs_lower_file(file);
++ BUG_ON(!lower_file);
++ /*
++ * XXX: vm_ops->fault may be called in parallel. Because we have to
++ * resort to temporarily changing the vma->vm_file to point to the
++ * lower file, a concurrent invocation of unionfs_fault could see a
++ * different value. In this workaround, we keep a different copy of
++ * the vma structure in our stack, so we never expose a different
++ * value of the vma->vm_file called to us, even temporarily. A
++ * better fix would be to change the calling semantics of ->fault to
++ * take an explicit file pointer.
++ */
++ lower_vma.vm_file = lower_file;
++ err = lower_vm_ops->fault(&lower_vma, vmf);
++ return err;
++}
++
++/*
++ * XXX: the default address_space_ops for unionfs is empty. We cannot set
++ * our inode->i_mapping->a_ops to NULL because too many code paths expect
++ * the a_ops vector to be non-NULL.
++ */
++struct address_space_operations unionfs_aops = {
++ /* empty on purpose */
++};
++
++/*
++ * XXX: we need a second, dummy address_space_ops vector, to be used
++ * temporarily during unionfs_mmap, because the latter calls
++ * generic_file_mmap, which checks if ->readpage exists, else returns
++ * -ENOEXEC.
++ */
++struct address_space_operations unionfs_dummy_aops = {
++ .readpage = unionfs_readpage,
++};
++
++struct vm_operations_struct unionfs_vm_ops = {
++ .fault = unionfs_fault,
++};
+diff --git a/fs/unionfs/rdstate.c b/fs/unionfs/rdstate.c
+new file mode 100644
+index 0000000..f745fbc
+--- /dev/null
++++ b/fs/unionfs/rdstate.c
+@@ -0,0 +1,285 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/* This file contains the routines for maintaining readdir state. */
++
++/*
++ * There are two structures here, rdstate which is a hash table
++ * of the second structure which is a filldir_node.
++ */
++
++/*
++ * This is a struct kmem_cache for filldir nodes, because we allocate a lot
++ * of them and they shouldn't waste memory. If the node has a small name
++ * (as defined by the dentry structure), then we use an inline name to
++ * preserve kmalloc space.
++ */
++static struct kmem_cache *unionfs_filldir_cachep;
++
++int unionfs_init_filldir_cache(void)
++{
++ unionfs_filldir_cachep =
++ kmem_cache_create("unionfs_filldir",
++ sizeof(struct filldir_node), 0,
++ SLAB_RECLAIM_ACCOUNT, NULL);
++
++ return (unionfs_filldir_cachep ? 0 : -ENOMEM);
++}
++
++void unionfs_destroy_filldir_cache(void)
++{
++ if (unionfs_filldir_cachep)
++ kmem_cache_destroy(unionfs_filldir_cachep);
++}
++
++/*
++ * This is a tuning parameter that tells us roughly how big to make the
++ * hash table in directory entries per page. This isn't perfect, but
++ * at least we get a hash table size that shouldn't be too overloaded.
++ * The following averages are based on my home directory.
++ * 14.44693 Overall
++ * 12.29 Single Page Directories
++ * 117.93 Multi-page directories
++ */
++#define DENTPAGE 4096
++#define DENTPERONEPAGE 12
++#define DENTPERPAGE 118
++#define MINHASHSIZE 1
++static int guesstimate_hash_size(struct inode *inode)
++{
++ struct inode *lower_inode;
++ int bindex;
++ int hashsize = MINHASHSIZE;
++
++ if (UNIONFS_I(inode)->hashsize > 0)
++ return UNIONFS_I(inode)->hashsize;
++
++ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++
++ if (i_size_read(lower_inode) == DENTPAGE)
++ hashsize += DENTPERONEPAGE;
++ else
++ hashsize += (i_size_read(lower_inode) / DENTPAGE) *
++ DENTPERPAGE;
++ }
++
++ return hashsize;
++}
++
++int init_rdstate(struct file *file)
++{
++ BUG_ON(sizeof(loff_t) !=
++ (sizeof(unsigned int) + sizeof(unsigned int)));
++ BUG_ON(UNIONFS_F(file)->rdstate != NULL);
++
++ UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_path.dentry->d_inode,
++ fbstart(file));
++
++ return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
++}
++
++struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos)
++{
++ struct unionfs_dir_state *rdstate = NULL;
++ struct list_head *pos;
++
++ spin_lock(&UNIONFS_I(inode)->rdlock);
++ list_for_each(pos, &UNIONFS_I(inode)->readdircache) {
++ struct unionfs_dir_state *r =
++ list_entry(pos, struct unionfs_dir_state, cache);
++ if (fpos == rdstate2offset(r)) {
++ UNIONFS_I(inode)->rdcount--;
++ list_del(&r->cache);
++ rdstate = r;
++ break;
++ }
++ }
++ spin_unlock(&UNIONFS_I(inode)->rdlock);
++ return rdstate;
++}
++
++struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex)
++{
++ int i = 0;
++ int hashsize;
++ unsigned long mallocsize = sizeof(struct unionfs_dir_state);
++ struct unionfs_dir_state *rdstate;
++
++ hashsize = guesstimate_hash_size(inode);
++ mallocsize += hashsize * sizeof(struct list_head);
++ mallocsize = __roundup_pow_of_two(mallocsize);
++
++ /* This should give us about 500 entries anyway. */
++ if (mallocsize > PAGE_SIZE)
++ mallocsize = PAGE_SIZE;
++
++ hashsize = (mallocsize - sizeof(struct unionfs_dir_state)) /
++ sizeof(struct list_head);
++
++ rdstate = kmalloc(mallocsize, GFP_KERNEL);
++ if (unlikely(!rdstate))
++ return NULL;
++
++ spin_lock(&UNIONFS_I(inode)->rdlock);
++ if (UNIONFS_I(inode)->cookie >= (MAXRDCOOKIE - 1))
++ UNIONFS_I(inode)->cookie = 1;
++ else
++ UNIONFS_I(inode)->cookie++;
++
++ rdstate->cookie = UNIONFS_I(inode)->cookie;
++ spin_unlock(&UNIONFS_I(inode)->rdlock);
++ rdstate->offset = 1;
++ rdstate->access = jiffies;
++ rdstate->bindex = bindex;
++ rdstate->dirpos = 0;
++ rdstate->hashentries = 0;
++ rdstate->size = hashsize;
++ for (i = 0; i < rdstate->size; i++)
++ INIT_LIST_HEAD(&rdstate->list[i]);
++
++ return rdstate;
++}
++
++static void free_filldir_node(struct filldir_node *node)
++{
++ if (node->namelen >= DNAME_INLINE_LEN_MIN)
++ kfree(node->name);
++ kmem_cache_free(unionfs_filldir_cachep, node);
++}
++
++void free_rdstate(struct unionfs_dir_state *state)
++{
++ struct filldir_node *tmp;
++ int i;
++
++ for (i = 0; i < state->size; i++) {
++ struct list_head *head = &(state->list[i]);
++ struct list_head *pos, *n;
++
++ /* traverse the list and deallocate space */
++ list_for_each_safe(pos, n, head) {
++ tmp = list_entry(pos, struct filldir_node, file_list);
++ list_del(&tmp->file_list);
++ free_filldir_node(tmp);
++ }
++ }
++
++ kfree(state);
++}
++
++struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
++ const char *name, int namelen,
++ int is_whiteout)
++{
++ int index;
++ unsigned int hash;
++ struct list_head *head;
++ struct list_head *pos;
++ struct filldir_node *cursor = NULL;
++ int found = 0;
++
++ BUG_ON(namelen <= 0);
++
++ hash = full_name_hash(name, namelen);
++ index = hash % rdstate->size;
++
++ head = &(rdstate->list[index]);
++ list_for_each(pos, head) {
++ cursor = list_entry(pos, struct filldir_node, file_list);
++
++ if (cursor->namelen == namelen && cursor->hash == hash &&
++ !strncmp(cursor->name, name, namelen)) {
++ /*
++ * a duplicate exists, and hence no need to create
++ * entry to the list
++ */
++ found = 1;
++
++ /*
++ * if a duplicate is found in this branch, and is
++ * not due to the caller looking for an entry to
++ * whiteout, then the file system may be corrupted.
++ */
++ if (unlikely(!is_whiteout &&
++ cursor->bindex == rdstate->bindex))
++ printk(KERN_ERR "unionfs: filldir: possible "
++ "I/O error: a file is duplicated "
++ "in the same branch %d: %s\n",
++ rdstate->bindex, cursor->name);
++ break;
++ }
++ }
++
++ if (!found)
++ cursor = NULL;
++
++ return cursor;
++}
++
++int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
++ int namelen, int bindex, int whiteout)
++{
++ struct filldir_node *new;
++ unsigned int hash;
++ int index;
++ int err = 0;
++ struct list_head *head;
++
++ BUG_ON(namelen <= 0);
++
++ hash = full_name_hash(name, namelen);
++ index = hash % rdstate->size;
++ head = &(rdstate->list[index]);
++
++ new = kmem_cache_alloc(unionfs_filldir_cachep, GFP_KERNEL);
++ if (unlikely(!new)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ INIT_LIST_HEAD(&new->file_list);
++ new->namelen = namelen;
++ new->hash = hash;
++ new->bindex = bindex;
++ new->whiteout = whiteout;
++
++ if (namelen < DNAME_INLINE_LEN_MIN) {
++ new->name = new->iname;
++ } else {
++ new->name = kmalloc(namelen + 1, GFP_KERNEL);
++ if (unlikely(!new->name)) {
++ kmem_cache_free(unionfs_filldir_cachep, new);
++ new = NULL;
++ goto out;
++ }
++ }
++
++ memcpy(new->name, name, namelen);
++ new->name[namelen] = '\0';
++
++ rdstate->hashentries++;
++
++ list_add(&(new->file_list), head);
++out:
++ return err;
++}
+diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
+new file mode 100644
+index 0000000..936700e
+--- /dev/null
++++ b/fs/unionfs/rename.c
+@@ -0,0 +1,517 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * This is a helper function for rename, used when rename ends up with hosed
++ * over dentries and we need to revert.
++ */
++static int unionfs_refresh_lower_dentry(struct dentry *dentry,
++ struct dentry *parent, int bindex)
++{
++ struct dentry *lower_dentry;
++ struct dentry *lower_parent;
++ int err = 0;
++
++ verify_locked(dentry);
++
++ lower_parent = unionfs_lower_dentry_idx(parent, bindex);
++
++ BUG_ON(!S_ISDIR(lower_parent->d_inode->i_mode));
++
++ lower_dentry = lookup_one_len(dentry->d_name.name, lower_parent,
++ dentry->d_name.len);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++
++ dput(unionfs_lower_dentry_idx(dentry, bindex));
++ iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
++ unionfs_set_lower_inode_idx(dentry->d_inode, bindex, NULL);
++
++ if (!lower_dentry->d_inode) {
++ dput(lower_dentry);
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ } else {
++ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
++ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
++ igrab(lower_dentry->d_inode));
++ }
++
++out:
++ return err;
++}
++
++static int __unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct dentry *old_parent,
++ struct inode *new_dir, struct dentry *new_dentry,
++ struct dentry *new_parent,
++ int bindex)
++{
++ int err = 0;
++ struct dentry *lower_old_dentry;
++ struct dentry *lower_new_dentry;
++ struct dentry *lower_old_dir_dentry;
++ struct dentry *lower_new_dir_dentry;
++ struct dentry *trap;
++
++ lower_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
++ lower_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);
++
++ if (!lower_new_dentry) {
++ lower_new_dentry =
++ create_parents(new_parent->d_inode,
++ new_dentry, new_dentry->d_name.name,
++ bindex);
++ if (IS_ERR(lower_new_dentry)) {
++ err = PTR_ERR(lower_new_dentry);
++ if (IS_COPYUP_ERR(err))
++ goto out;
++ printk(KERN_ERR "unionfs: error creating directory "
++ "tree for rename, bindex=%d err=%d\n",
++ bindex, err);
++ goto out;
++ }
++ }
++
++ /* check for and remove whiteout, if any */
++ err = check_unlink_whiteout(new_dentry, lower_new_dentry, bindex);
++ if (err > 0) /* ignore if whiteout found and successfully removed */
++ err = 0;
++ if (err)
++ goto out;
++
++ /* check of old_dentry branch is writable */
++ err = is_robranch_super(old_dentry->d_sb, bindex);
++ if (err)
++ goto out;
++
++ dget(lower_old_dentry);
++ dget(lower_new_dentry);
++ lower_old_dir_dentry = dget_parent(lower_old_dentry);
++ lower_new_dir_dentry = dget_parent(lower_new_dentry);
++
++ trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
++ /* source should not be ancenstor of target */
++ if (trap == lower_old_dentry) {
++ err = -EINVAL;
++ goto out_err_unlock;
++ }
++ /* target should not be ancenstor of source */
++ if (trap == lower_new_dentry) {
++ err = -ENOTEMPTY;
++ goto out_err_unlock;
++ }
++ err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
++ lower_new_dir_dentry->d_inode, lower_new_dentry);
++out_err_unlock:
++ if (!err) {
++ /* update parent dir times */
++ fsstack_copy_attr_times(old_dir, lower_old_dir_dentry->d_inode);
++ fsstack_copy_attr_times(new_dir, lower_new_dir_dentry->d_inode);
++ }
++ unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
++
++ dput(lower_old_dir_dentry);
++ dput(lower_new_dir_dentry);
++ dput(lower_old_dentry);
++ dput(lower_new_dentry);
++
++out:
++ if (!err) {
++ /* Fixup the new_dentry. */
++ if (bindex < dbstart(new_dentry))
++ dbstart(new_dentry) = bindex;
++ else if (bindex > dbend(new_dentry))
++ dbend(new_dentry) = bindex;
++ }
++
++ return err;
++}
++
++/*
++ * Main rename code. This is sufficiently complex, that it's documented in
++ * Documentation/filesystems/unionfs/rename.txt. This routine calls
++ * __unionfs_rename() above to perform some of the work.
++ */
++static int do_unionfs_rename(struct inode *old_dir,
++ struct dentry *old_dentry,
++ struct dentry *old_parent,
++ struct inode *new_dir,
++ struct dentry *new_dentry,
++ struct dentry *new_parent)
++{
++ int err = 0;
++ int bindex;
++ int old_bstart, old_bend;
++ int new_bstart, new_bend;
++ int do_copyup = -1;
++ int local_err = 0;
++ int eio = 0;
++ int revert = 0;
++
++ old_bstart = dbstart(old_dentry);
++ old_bend = dbend(old_dentry);
++
++ new_bstart = dbstart(new_dentry);
++ new_bend = dbend(new_dentry);
++
++ /* Rename source to destination. */
++ err = __unionfs_rename(old_dir, old_dentry, old_parent,
++ new_dir, new_dentry, new_parent,
++ old_bstart);
++ if (err) {
++ if (!IS_COPYUP_ERR(err))
++ goto out;
++ do_copyup = old_bstart - 1;
++ } else {
++ revert = 1;
++ }
++
++ /*
++ * Unlink all instances of destination that exist to the left of
++ * bstart of source. On error, revert back, goto out.
++ */
++ for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) {
++ struct dentry *unlink_dentry;
++ struct dentry *unlink_dir_dentry;
++
++ BUG_ON(bindex < 0);
++ unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
++ if (!unlink_dentry)
++ continue;
++
++ unlink_dir_dentry = lock_parent(unlink_dentry);
++ err = is_robranch_super(old_dir->i_sb, bindex);
++ if (!err)
++ err = vfs_unlink(unlink_dir_dentry->d_inode,
++ unlink_dentry);
++
++ fsstack_copy_attr_times(new_parent->d_inode,
++ unlink_dir_dentry->d_inode);
++ /* propagate number of hard-links */
++ new_parent->d_inode->i_nlink =
++ unionfs_get_nlinks(new_parent->d_inode);
++
++ unlock_dir(unlink_dir_dentry);
++ if (!err) {
++ if (bindex != new_bstart) {
++ dput(unlink_dentry);
++ unionfs_set_lower_dentry_idx(new_dentry,
++ bindex, NULL);
++ }
++ } else if (IS_COPYUP_ERR(err)) {
++ do_copyup = bindex - 1;
++ } else if (revert) {
++ goto revert;
++ }
++ }
++
++ if (do_copyup != -1) {
++ for (bindex = do_copyup; bindex >= 0; bindex--) {
++ /*
++ * copyup the file into some left directory, so that
++ * you can rename it
++ */
++ err = copyup_dentry(old_parent->d_inode,
++ old_dentry, old_bstart, bindex,
++ old_dentry->d_name.name,
++ old_dentry->d_name.len, NULL,
++ i_size_read(old_dentry->d_inode));
++ /* if copyup failed, try next branch to the left */
++ if (err)
++ continue;
++ /*
++ * create whiteout before calling __unionfs_rename
++ * because the latter will change the old_dentry's
++ * lower name and parent dir, resulting in the
++ * whiteout getting created in the wrong dir.
++ */
++ err = create_whiteout(old_dentry, bindex);
++ if (err) {
++ printk(KERN_ERR "unionfs: can't create a "
++ "whiteout for %s in rename (err=%d)\n",
++ old_dentry->d_name.name, err);
++ continue;
++ }
++ err = __unionfs_rename(old_dir, old_dentry, old_parent,
++ new_dir, new_dentry, new_parent,
++ bindex);
++ break;
++ }
++ }
++
++ /* make it opaque */
++ if (S_ISDIR(old_dentry->d_inode->i_mode)) {
++ err = make_dir_opaque(old_dentry, dbstart(old_dentry));
++ if (err)
++ goto revert;
++ }
++
++ /*
++ * Create whiteout for source, only if:
++ * (1) There is more than one underlying instance of source.
++ * (We did a copy_up is taken care of above).
++ */
++ if ((old_bstart != old_bend) && (do_copyup == -1)) {
++ err = create_whiteout(old_dentry, old_bstart);
++ if (err) {
++ /* can't fix anything now, so we exit with -EIO */
++ printk(KERN_ERR "unionfs: can't create a whiteout for "
++ "%s in rename!\n", old_dentry->d_name.name);
++ err = -EIO;
++ }
++ }
++
++out:
++ return err;
++
++revert:
++ /* Do revert here. */
++ local_err = unionfs_refresh_lower_dentry(new_dentry, new_parent,
++ old_bstart);
++ if (local_err) {
++ printk(KERN_ERR "unionfs: revert failed in rename: "
++ "the new refresh failed\n");
++ eio = -EIO;
++ }
++
++ local_err = unionfs_refresh_lower_dentry(old_dentry, old_parent,
++ old_bstart);
++ if (local_err) {
++ printk(KERN_ERR "unionfs: revert failed in rename: "
++ "the old refresh failed\n");
++ eio = -EIO;
++ goto revert_out;
++ }
++
++ if (!unionfs_lower_dentry_idx(new_dentry, bindex) ||
++ !unionfs_lower_dentry_idx(new_dentry, bindex)->d_inode) {
++ printk(KERN_ERR "unionfs: revert failed in rename: "
++ "the object disappeared from under us!\n");
++ eio = -EIO;
++ goto revert_out;
++ }
++
++ if (unionfs_lower_dentry_idx(old_dentry, bindex) &&
++ unionfs_lower_dentry_idx(old_dentry, bindex)->d_inode) {
++ printk(KERN_ERR "unionfs: revert failed in rename: "
++ "the object was created underneath us!\n");
++ eio = -EIO;
++ goto revert_out;
++ }
++
++ local_err = __unionfs_rename(new_dir, new_dentry, new_parent,
++ old_dir, old_dentry, old_parent,
++ old_bstart);
++
++ /* If we can't fix it, then we cop-out with -EIO. */
++ if (local_err) {
++ printk(KERN_ERR "unionfs: revert failed in rename!\n");
++ eio = -EIO;
++ }
++
++ local_err = unionfs_refresh_lower_dentry(new_dentry, new_parent,
++ bindex);
++ if (local_err)
++ eio = -EIO;
++ local_err = unionfs_refresh_lower_dentry(old_dentry, old_parent,
++ bindex);
++ if (local_err)
++ eio = -EIO;
++
++revert_out:
++ if (eio)
++ err = eio;
++ return err;
++}
++
++/*
++ * We can't copyup a directory, because it may involve huge numbers of
++ * children, etc. Doing that in the kernel would be bad, so instead we
++ * return EXDEV to the user-space utility that caused this, and let the
++ * user-space recurse and ask us to copy up each file separately.
++ */
++static int may_rename_dir(struct dentry *dentry, struct dentry *parent)
++{
++ int err, bstart;
++
++ err = check_empty(dentry, parent, NULL);
++ if (err == -ENOTEMPTY) {
++ if (is_robranch(dentry))
++ return -EXDEV;
++ } else if (err) {
++ return err;
++ }
++
++ bstart = dbstart(dentry);
++ if (dbend(dentry) == bstart || dbopaque(dentry) == bstart)
++ return 0;
++
++ dbstart(dentry) = bstart + 1;
++ err = check_empty(dentry, parent, NULL);
++ dbstart(dentry) = bstart;
++ if (err == -ENOTEMPTY)
++ err = -EXDEV;
++ return err;
++}
++
++/*
++ * The locking rules in unionfs_rename are complex. We could use a simpler
++ * superblock-level name-space lock for renames and copy-ups.
++ */
++int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry)
++{
++ int err = 0;
++ struct dentry *wh_dentry;
++ struct dentry *old_parent, *new_parent;
++ int valid = true;
++
++ unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ old_parent = dget_parent(old_dentry);
++ new_parent = dget_parent(new_dentry);
++ /* un/lock parent dentries only if they differ from old/new_dentry */
++ if (old_parent != old_dentry &&
++ old_parent != new_dentry)
++ unionfs_lock_dentry(old_parent, UNIONFS_DMUTEX_REVAL_PARENT);
++ if (new_parent != old_dentry &&
++ new_parent != new_dentry &&
++ new_parent != old_parent)
++ unionfs_lock_dentry(new_parent, UNIONFS_DMUTEX_REVAL_CHILD);
++ unionfs_double_lock_dentry(old_dentry, new_dentry);
++
++ valid = __unionfs_d_revalidate(old_dentry, old_parent, false);
++ if (!valid) {
++ err = -ESTALE;
++ goto out;
++ }
++ if (!d_deleted(new_dentry) && new_dentry->d_inode) {
++ valid = __unionfs_d_revalidate(new_dentry, new_parent, false);
++ if (!valid) {
++ err = -ESTALE;
++ goto out;
++ }
++ }
++
++ if (!S_ISDIR(old_dentry->d_inode->i_mode))
++ err = unionfs_partial_lookup(old_dentry, old_parent);
++ else
++ err = may_rename_dir(old_dentry, old_parent);
++
++ if (err)
++ goto out;
++
++ err = unionfs_partial_lookup(new_dentry, new_parent);
++ if (err)
++ goto out;
++
++ /*
++ * if new_dentry is already lower because of whiteout,
++ * simply override it even if the whited-out dir is not empty.
++ */
++ wh_dentry = find_first_whiteout(new_dentry);
++ if (!IS_ERR(wh_dentry)) {
++ dput(wh_dentry);
++ } else if (new_dentry->d_inode) {
++ if (S_ISDIR(old_dentry->d_inode->i_mode) !=
++ S_ISDIR(new_dentry->d_inode->i_mode)) {
++ err = S_ISDIR(old_dentry->d_inode->i_mode) ?
++ -ENOTDIR : -EISDIR;
++ goto out;
++ }
++
++ if (S_ISDIR(new_dentry->d_inode->i_mode)) {
++ struct unionfs_dir_state *namelist = NULL;
++ /* check if this unionfs directory is empty or not */
++ err = check_empty(new_dentry, new_parent, &namelist);
++ if (err)
++ goto out;
++
++ if (!is_robranch(new_dentry))
++ err = delete_whiteouts(new_dentry,
++ dbstart(new_dentry),
++ namelist);
++
++ free_rdstate(namelist);
++
++ if (err)
++ goto out;
++ }
++ }
++
++ err = do_unionfs_rename(old_dir, old_dentry, old_parent,
++ new_dir, new_dentry, new_parent);
++ if (err)
++ goto out;
++
++ /*
++ * force re-lookup since the dir on ro branch is not renamed, and
++ * lower dentries still indicate the un-renamed ones.
++ */
++ if (S_ISDIR(old_dentry->d_inode->i_mode))
++ atomic_dec(&UNIONFS_D(old_dentry)->generation);
++ else
++ unionfs_postcopyup_release(old_dentry);
++ if (new_dentry->d_inode && !S_ISDIR(new_dentry->d_inode->i_mode)) {
++ unionfs_postcopyup_release(new_dentry);
++ unionfs_postcopyup_setmnt(new_dentry);
++ if (!unionfs_lower_inode(new_dentry->d_inode)) {
++ /*
++ * If we get here, it means that no copyup was
++ * needed, and that a file by the old name already
++ * existing on the destination branch; that file got
++ * renamed earlier in this function, so all we need
++ * to do here is set the lower inode.
++ */
++ struct inode *inode;
++ inode = unionfs_lower_inode(old_dentry->d_inode);
++ igrab(inode);
++ unionfs_set_lower_inode_idx(new_dentry->d_inode,
++ dbstart(new_dentry),
++ inode);
++ }
++ }
++ /* if all of this renaming succeeded, update our times */
++ unionfs_copy_attr_times(old_dentry->d_inode);
++ unionfs_copy_attr_times(new_dentry->d_inode);
++ unionfs_check_inode(old_dir);
++ unionfs_check_inode(new_dir);
++ unionfs_check_dentry(old_dentry);
++ unionfs_check_dentry(new_dentry);
++
++out:
++ if (err) /* clear the new_dentry stuff created */
++ d_drop(new_dentry);
++
++ unionfs_double_unlock_dentry(old_dentry, new_dentry);
++ if (new_parent != old_dentry &&
++ new_parent != new_dentry &&
++ new_parent != old_parent)
++ unionfs_unlock_dentry(new_parent);
++ if (old_parent != old_dentry &&
++ old_parent != new_dentry)
++ unionfs_unlock_dentry(old_parent);
++ dput(new_parent);
++ dput(old_parent);
++ unionfs_read_unlock(old_dentry->d_sb);
++
++ return err;
++}
+diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
+new file mode 100644
+index 0000000..760c580
+--- /dev/null
++++ b/fs/unionfs/sioq.c
+@@ -0,0 +1,101 @@
++/*
++ * Copyright (c) 2006-2010 Erez Zadok
++ * Copyright (c) 2006 Charles P. Wright
++ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2006 Junjiro Okajima
++ * Copyright (c) 2006 David P. Quigley
++ * Copyright (c) 2006-2010 Stony Brook University
++ * Copyright (c) 2006-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * Super-user IO work Queue - sometimes we need to perform actions which
++ * would fail due to the unix permissions on the parent directory (e.g.,
++ * rmdir a directory which appears empty, but in reality contains
++ * whiteouts).
++ */
++
++static struct workqueue_struct *superio_workqueue;
++
++int __init init_sioq(void)
++{
++ int err;
++
++ superio_workqueue = create_workqueue("unionfs_siod");
++ if (!IS_ERR(superio_workqueue))
++ return 0;
++
++ err = PTR_ERR(superio_workqueue);
++ printk(KERN_ERR "unionfs: create_workqueue failed %d\n", err);
++ superio_workqueue = NULL;
++ return err;
++}
++
++void stop_sioq(void)
++{
++ if (superio_workqueue)
++ destroy_workqueue(superio_workqueue);
++}
++
++void run_sioq(work_func_t func, struct sioq_args *args)
++{
++ INIT_WORK(&args->work, func);
++
++ init_completion(&args->comp);
++ while (!queue_work(superio_workqueue, &args->work)) {
++ /* TODO: do accounting if needed */
++ schedule();
++ }
++ wait_for_completion(&args->comp);
++}
++
++void __unionfs_create(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct create_args *c = &args->create;
++
++ args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd);
++ complete(&args->comp);
++}
++
++void __unionfs_mkdir(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct mkdir_args *m = &args->mkdir;
++
++ args->err = vfs_mkdir(m->parent, m->dentry, m->mode);
++ complete(&args->comp);
++}
++
++void __unionfs_mknod(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct mknod_args *m = &args->mknod;
++
++ args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
++ complete(&args->comp);
++}
++
++void __unionfs_symlink(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct symlink_args *s = &args->symlink;
++
++ args->err = vfs_symlink(s->parent, s->dentry, s->symbuf);
++ complete(&args->comp);
++}
++
++void __unionfs_unlink(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct unlink_args *u = &args->unlink;
++
++ args->err = vfs_unlink(u->parent, u->dentry);
++ complete(&args->comp);
++}
+diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
+new file mode 100644
+index 0000000..b26d248
+--- /dev/null
++++ b/fs/unionfs/sioq.h
+@@ -0,0 +1,91 @@
++/*
++ * Copyright (c) 2006-2010 Erez Zadok
++ * Copyright (c) 2006 Charles P. Wright
++ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2006 Junjiro Okajima
++ * Copyright (c) 2006 David P. Quigley
++ * Copyright (c) 2006-2010 Stony Brook University
++ * Copyright (c) 2006-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _SIOQ_H
++#define _SIOQ_H
++
++struct deletewh_args {
++ struct unionfs_dir_state *namelist;
++ struct dentry *dentry;
++ int bindex;
++};
++
++struct is_opaque_args {
++ struct dentry *dentry;
++};
++
++struct create_args {
++ struct inode *parent;
++ struct dentry *dentry;
++ umode_t mode;
++ struct nameidata *nd;
++};
++
++struct mkdir_args {
++ struct inode *parent;
++ struct dentry *dentry;
++ umode_t mode;
++};
++
++struct mknod_args {
++ struct inode *parent;
++ struct dentry *dentry;
++ umode_t mode;
++ dev_t dev;
++};
++
++struct symlink_args {
++ struct inode *parent;
++ struct dentry *dentry;
++ char *symbuf;
++};
++
++struct unlink_args {
++ struct inode *parent;
++ struct dentry *dentry;
++};
++
++
++struct sioq_args {
++ struct completion comp;
++ struct work_struct work;
++ int err;
++ void *ret;
++
++ union {
++ struct deletewh_args deletewh;
++ struct is_opaque_args is_opaque;
++ struct create_args create;
++ struct mkdir_args mkdir;
++ struct mknod_args mknod;
++ struct symlink_args symlink;
++ struct unlink_args unlink;
++ };
++};
++
++/* Extern definitions for SIOQ functions */
++extern int __init init_sioq(void);
++extern void stop_sioq(void);
++extern void run_sioq(work_func_t func, struct sioq_args *args);
++
++/* Extern definitions for our privilege escalation helpers */
++extern void __unionfs_create(struct work_struct *work);
++extern void __unionfs_mkdir(struct work_struct *work);
++extern void __unionfs_mknod(struct work_struct *work);
++extern void __unionfs_symlink(struct work_struct *work);
++extern void __unionfs_unlink(struct work_struct *work);
++extern void __delete_whiteouts(struct work_struct *work);
++extern void __is_opaque_dir(struct work_struct *work);
++
++#endif /* not _SIOQ_H */
+diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c
+new file mode 100644
+index 0000000..570a344
+--- /dev/null
++++ b/fs/unionfs/subr.c
+@@ -0,0 +1,95 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * returns the right n_link value based on the inode type
++ */
++int unionfs_get_nlinks(const struct inode *inode)
++{
++ /* don't bother to do all the work since we're unlinked */
++ if (inode->i_nlink == 0)
++ return 0;
++
++ if (!S_ISDIR(inode->i_mode))
++ return unionfs_lower_inode(inode)->i_nlink;
++
++ /*
++ * For directories, we return 1. The only place that could cares
++ * about links is readdir, and there's d_type there so even that
++ * doesn't matter.
++ */
++ return 1;
++}
++
++/* copy a/m/ctime from the lower branch with the newest times */
++void unionfs_copy_attr_times(struct inode *upper)
++{
++ int bindex;
++ struct inode *lower;
++
++ if (!upper)
++ return;
++ if (ibstart(upper) < 0) {
++#ifdef CONFIG_UNION_FS_DEBUG
++ WARN_ON(ibstart(upper) < 0);
++#endif /* CONFIG_UNION_FS_DEBUG */
++ return;
++ }
++ for (bindex = ibstart(upper); bindex <= ibend(upper); bindex++) {
++ lower = unionfs_lower_inode_idx(upper, bindex);
++ if (!lower)
++ continue; /* not all lower dir objects may exist */
++ if (unlikely(timespec_compare(&upper->i_mtime,
++ &lower->i_mtime) < 0))
++ upper->i_mtime = lower->i_mtime;
++ if (unlikely(timespec_compare(&upper->i_ctime,
++ &lower->i_ctime) < 0))
++ upper->i_ctime = lower->i_ctime;
++ if (unlikely(timespec_compare(&upper->i_atime,
++ &lower->i_atime) < 0))
++ upper->i_atime = lower->i_atime;
++ }
++}
++
++/*
++ * A unionfs/fanout version of fsstack_copy_attr_all. Uses a
++ * unionfs_get_nlinks to properly calcluate the number of links to a file.
++ * Also, copies the max() of all a/m/ctimes for all lower inodes (which is
++ * important if the lower inode is a directory type)
++ */
++void unionfs_copy_attr_all(struct inode *dest,
++ const struct inode *src)
++{
++ dest->i_mode = src->i_mode;
++ dest->i_uid = src->i_uid;
++ dest->i_gid = src->i_gid;
++ dest->i_rdev = src->i_rdev;
++
++ unionfs_copy_attr_times(dest);
++
++ dest->i_blkbits = src->i_blkbits;
++ dest->i_flags = src->i_flags;
++
++ /*
++ * Update the nlinks AFTER updating the above fields, because the
++ * get_links callback may depend on them.
++ */
++ dest->i_nlink = unionfs_get_nlinks(dest);
++}
+diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
+new file mode 100644
+index 0000000..45bb9bf
+--- /dev/null
++++ b/fs/unionfs/super.c
+@@ -0,0 +1,1029 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * The inode cache is used with alloc_inode for both our inode info and the
++ * vfs inode.
++ */
++static struct kmem_cache *unionfs_inode_cachep;
++
++struct inode *unionfs_iget(struct super_block *sb, unsigned long ino)
++{
++ int size;
++ struct unionfs_inode_info *info;
++ struct inode *inode;
++
++ inode = iget_locked(sb, ino);
++ if (!inode)
++ return ERR_PTR(-ENOMEM);
++ if (!(inode->i_state & I_NEW))
++ return inode;
++
++ info = UNIONFS_I(inode);
++ memset(info, 0, offsetof(struct unionfs_inode_info, vfs_inode));
++ info->bstart = -1;
++ info->bend = -1;
++ atomic_set(&info->generation,
++ atomic_read(&UNIONFS_SB(inode->i_sb)->generation));
++ spin_lock_init(&info->rdlock);
++ info->rdcount = 1;
++ info->hashsize = -1;
++ INIT_LIST_HEAD(&info->readdircache);
++
++ size = sbmax(inode->i_sb) * sizeof(struct inode *);
++ info->lower_inodes = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!info->lower_inodes)) {
++ printk(KERN_CRIT "unionfs: no kernel memory when allocating "
++ "lower-pointer array!\n");
++ iget_failed(inode);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ inode->i_version++;
++ inode->i_op = &unionfs_main_iops;
++ inode->i_fop = &unionfs_main_fops;
++
++ inode->i_mapping->a_ops = &unionfs_aops;
++
++ /*
++ * reset times so unionfs_copy_attr_all can keep out time invariants
++ * right (upper inode time being the max of all lower ones).
++ */
++ inode->i_atime.tv_sec = inode->i_atime.tv_nsec = 0;
++ inode->i_mtime.tv_sec = inode->i_mtime.tv_nsec = 0;
++ inode->i_ctime.tv_sec = inode->i_ctime.tv_nsec = 0;
++ unlock_new_inode(inode);
++ return inode;
++}
++
++/*
++ * final actions when unmounting a file system
++ *
++ * No need to lock rwsem.
++ */
++static void unionfs_put_super(struct super_block *sb)
++{
++ int bindex, bstart, bend;
++ struct unionfs_sb_info *spd;
++ int leaks = 0;
++
++ spd = UNIONFS_SB(sb);
++ if (!spd)
++ return;
++
++ bstart = sbstart(sb);
++ bend = sbend(sb);
++
++ /* Make sure we have no leaks of branchget/branchput. */
++ for (bindex = bstart; bindex <= bend; bindex++)
++ if (unlikely(branch_count(sb, bindex) != 0)) {
++ printk(KERN_CRIT
++ "unionfs: branch %d has %d references left!\n",
++ bindex, branch_count(sb, bindex));
++ leaks = 1;
++ }
++ WARN_ON(leaks != 0);
++
++ /* decrement lower super references */
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ struct super_block *s;
++ s = unionfs_lower_super_idx(sb, bindex);
++ unionfs_set_lower_super_idx(sb, bindex, NULL);
++ atomic_dec(&s->s_active);
++ }
++
++ kfree(spd->dev_name);
++ kfree(spd->data);
++ kfree(spd);
++ sb->s_fs_info = NULL;
++}
++
++/*
++ * Since people use this to answer the "How big of a file can I write?"
++ * question, we report the size of the highest priority branch as the size of
++ * the union.
++ */
++static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ int err = 0;
++ struct super_block *sb;
++ struct dentry *lower_dentry;
++ struct dentry *parent;
++ struct path lower_path;
++ bool valid;
++
++ sb = dentry->d_sb;
++
++ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ unionfs_check_dentry(dentry);
++
++ lower_dentry = unionfs_lower_dentry(sb->s_root);
++ lower_path.dentry = lower_dentry;
++ lower_path.mnt = unionfs_mntget(sb->s_root, 0);
++ err = vfs_statfs(&lower_path, buf);
++ mntput(lower_path.mnt);
++
++ /* set return buf to our f/s to avoid confusing user-level utils */
++ buf->f_type = UNIONFS_SUPER_MAGIC;
++ /*
++ * Our maximum file name can is shorter by a few bytes because every
++ * file name could potentially be whited-out.
++ *
++ * XXX: this restriction goes away with ODF.
++ */
++ unionfs_set_max_namelen(&buf->f_namelen);
++
++ /*
++ * reset two fields to avoid confusing user-land.
++ * XXX: is this still necessary?
++ */
++ memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t));
++ memset(&buf->f_spare, 0, sizeof(buf->f_spare));
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(sb);
++ return err;
++}
++
++/* handle mode changing during remount */
++static noinline_for_stack int do_remount_mode_option(
++ char *optarg,
++ int cur_branches,
++ struct unionfs_data *new_data,
++ struct path *new_lower_paths)
++{
++ int err = -EINVAL;
++ int perms, idx;
++ char *modename = strchr(optarg, '=');
++ struct nameidata nd;
++
++ /* by now, optarg contains the branch name */
++ if (!*optarg) {
++ printk(KERN_ERR
++ "unionfs: no branch specified for mode change\n");
++ goto out;
++ }
++ if (!modename) {
++ printk(KERN_ERR "unionfs: branch \"%s\" requires a mode\n",
++ optarg);
++ goto out;
++ }
++ *modename++ = '\0';
++ err = parse_branch_mode(modename, &perms);
++ if (err) {
++ printk(KERN_ERR "unionfs: invalid mode \"%s\" for \"%s\"\n",
++ modename, optarg);
++ goto out;
++ }
++
++ /*
++ * Find matching branch index. For now, this assumes that nothing
++ * has been mounted on top of this Unionfs stack. Once we have /odf
++ * and cache-coherency resolved, we'll address the branch-path
++ * uniqueness.
++ */
++ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory \"%s\" (error %d)\n",
++ optarg, err);
++ goto out;
++ }
++ for (idx = 0; idx < cur_branches; idx++)
++ if (nd.path.mnt == new_lower_paths[idx].mnt &&
++ nd.path.dentry == new_lower_paths[idx].dentry)
++ break;
++ path_put(&nd.path); /* no longer needed */
++ if (idx == cur_branches) {
++ err = -ENOENT; /* err may have been reset above */
++ printk(KERN_ERR "unionfs: branch \"%s\" "
++ "not found\n", optarg);
++ goto out;
++ }
++ /* check/change mode for existing branch */
++ /* we don't warn if perms==branchperms */
++ new_data[idx].branchperms = perms;
++ err = 0;
++out:
++ return err;
++}
++
++/* handle branch deletion during remount */
++static noinline_for_stack int do_remount_del_option(
++ char *optarg, int cur_branches,
++ struct unionfs_data *new_data,
++ struct path *new_lower_paths)
++{
++ int err = -EINVAL;
++ int idx;
++ struct nameidata nd;
++
++ /* optarg contains the branch name to delete */
++
++ /*
++ * Find matching branch index. For now, this assumes that nothing
++ * has been mounted on top of this Unionfs stack. Once we have /odf
++ * and cache-coherency resolved, we'll address the branch-path
++ * uniqueness.
++ */
++ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory \"%s\" (error %d)\n",
++ optarg, err);
++ goto out;
++ }
++ for (idx = 0; idx < cur_branches; idx++)
++ if (nd.path.mnt == new_lower_paths[idx].mnt &&
++ nd.path.dentry == new_lower_paths[idx].dentry)
++ break;
++ path_put(&nd.path); /* no longer needed */
++ if (idx == cur_branches) {
++ printk(KERN_ERR "unionfs: branch \"%s\" "
++ "not found\n", optarg);
++ err = -ENOENT;
++ goto out;
++ }
++ /* check if there are any open files on the branch to be deleted */
++ if (atomic_read(&new_data[idx].open_files) > 0) {
++ err = -EBUSY;
++ goto out;
++ }
++
++ /*
++ * Now we have to delete the branch. First, release any handles it
++ * has. Then, move the remaining array indexes past "idx" in
++ * new_data and new_lower_paths one to the left. Finally, adjust
++ * cur_branches.
++ */
++ path_put(&new_lower_paths[idx]);
++
++ if (idx < cur_branches - 1) {
++ /* if idx==cur_branches-1, we delete last branch: easy */
++ memmove(&new_data[idx], &new_data[idx+1],
++ (cur_branches - 1 - idx) *
++ sizeof(struct unionfs_data));
++ memmove(&new_lower_paths[idx], &new_lower_paths[idx+1],
++ (cur_branches - 1 - idx) * sizeof(struct path));
++ }
++
++ err = 0;
++out:
++ return err;
++}
++
++/* handle branch insertion during remount */
++static noinline_for_stack int do_remount_add_option(
++ char *optarg, int cur_branches,
++ struct unionfs_data *new_data,
++ struct path *new_lower_paths,
++ int *high_branch_id)
++{
++ int err = -EINVAL;
++ int perms;
++ int idx = 0; /* default: insert at beginning */
++ char *new_branch , *modename = NULL;
++ struct nameidata nd;
++
++ /*
++ * optarg can be of several forms:
++ *
++ * /bar:/foo insert /foo before /bar
++ * /bar:/foo=ro insert /foo in ro mode before /bar
++ * /foo insert /foo in the beginning (prepend)
++ * :/foo insert /foo at the end (append)
++ */
++ if (*optarg == ':') { /* append? */
++ new_branch = optarg + 1; /* skip ':' */
++ idx = cur_branches;
++ goto found_insertion_point;
++ }
++ new_branch = strchr(optarg, ':');
++ if (!new_branch) { /* prepend? */
++ new_branch = optarg;
++ goto found_insertion_point;
++ }
++ *new_branch++ = '\0'; /* holds path+mode of new branch */
++
++ /*
++ * Find matching branch index. For now, this assumes that nothing
++ * has been mounted on top of this Unionfs stack. Once we have /odf
++ * and cache-coherency resolved, we'll address the branch-path
++ * uniqueness.
++ */
++ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory \"%s\" (error %d)\n",
++ optarg, err);
++ goto out;
++ }
++ for (idx = 0; idx < cur_branches; idx++)
++ if (nd.path.mnt == new_lower_paths[idx].mnt &&
++ nd.path.dentry == new_lower_paths[idx].dentry)
++ break;
++ path_put(&nd.path); /* no longer needed */
++ if (idx == cur_branches) {
++ printk(KERN_ERR "unionfs: branch \"%s\" "
++ "not found\n", optarg);
++ err = -ENOENT;
++ goto out;
++ }
++
++ /*
++ * At this point idx will hold the index where the new branch should
++ * be inserted before.
++ */
++found_insertion_point:
++ /* find the mode for the new branch */
++ if (new_branch)
++ modename = strchr(new_branch, '=');
++ if (modename)
++ *modename++ = '\0';
++ if (!new_branch || !*new_branch) {
++ printk(KERN_ERR "unionfs: null new branch\n");
++ err = -EINVAL;
++ goto out;
++ }
++ err = parse_branch_mode(modename, &perms);
++ if (err) {
++ printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
++ "branch \"%s\"\n", modename, new_branch);
++ goto out;
++ }
++ err = path_lookup(new_branch, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory \"%s\" (error %d)\n",
++ new_branch, err);
++ goto out;
++ }
++ /*
++ * It's probably safe to check_mode the new branch to insert. Note:
++ * we don't allow inserting branches which are unionfs's by
++ * themselves (check_branch returns EINVAL in that case). This is
++ * because this code base doesn't support stacking unionfs: the ODF
++ * code base supports that correctly.
++ */
++ err = check_branch(&nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: lower directory "
++ "\"%s\" is not a valid branch\n", optarg);
++ path_put(&nd.path);
++ goto out;
++ }
++
++ /*
++ * Now we have to insert the new branch. But first, move the bits
++ * to make space for the new branch, if needed. Finally, adjust
++ * cur_branches.
++ * We don't release nd here; it's kept until umount/remount.
++ */
++ if (idx < cur_branches) {
++ /* if idx==cur_branches, we append: easy */
++ memmove(&new_data[idx+1], &new_data[idx],
++ (cur_branches - idx) * sizeof(struct unionfs_data));
++ memmove(&new_lower_paths[idx+1], &new_lower_paths[idx],
++ (cur_branches - idx) * sizeof(struct path));
++ }
++ new_lower_paths[idx].dentry = nd.path.dentry;
++ new_lower_paths[idx].mnt = nd.path.mnt;
++
++ new_data[idx].sb = nd.path.dentry->d_sb;
++ atomic_set(&new_data[idx].open_files, 0);
++ new_data[idx].branchperms = perms;
++ new_data[idx].branch_id = ++*high_branch_id; /* assign new branch ID */
++
++ err = 0;
++out:
++ return err;
++}
++
++
++/*
++ * Support branch management options on remount.
++ *
++ * See Documentation/filesystems/unionfs/ for details.
++ *
++ * @flags: numeric mount options
++ * @options: mount options string
++ *
++ * This function can rearrange a mounted union dynamically, adding and
++ * removing branches, including changing branch modes. Clearly this has to
++ * be done safely and atomically. Luckily, the VFS already calls this
++ * function with lock_super(sb) and lock_kernel() held, preventing
++ * concurrent mixing of new mounts, remounts, and unmounts. Moreover,
++ * do_remount_sb(), our caller function, already called shrink_dcache_sb(sb)
++ * to purge dentries/inodes from our superblock, and also called
++ * fsync_super(sb) to purge any dirty pages. So we're good.
++ *
++ * XXX: however, our remount code may also need to invalidate mapped pages
++ * so as to force them to be re-gotten from the (newly reconfigured) lower
++ * branches. This has to wait for proper mmap and cache coherency support
++ * in the VFS.
++ *
++ */
++static int unionfs_remount_fs(struct super_block *sb, int *flags,
++ char *options)
++{
++ int err = 0;
++ int i;
++ char *optionstmp, *tmp_to_free; /* kstrdup'ed of "options" */
++ char *optname;
++ int cur_branches = 0; /* no. of current branches */
++ int new_branches = 0; /* no. of branches actually left in the end */
++ int add_branches; /* est. no. of branches to add */
++ int del_branches; /* est. no. of branches to del */
++ int max_branches; /* max possible no. of branches */
++ struct unionfs_data *new_data = NULL, *tmp_data = NULL;
++ struct path *new_lower_paths = NULL, *tmp_lower_paths = NULL;
++ struct inode **new_lower_inodes = NULL;
++ int new_high_branch_id; /* new high branch ID */
++ int size; /* memory allocation size, temp var */
++ int old_ibstart, old_ibend;
++
++ unionfs_write_lock(sb);
++
++ /*
++ * The VFS will take care of "ro" and "rw" flags, and we can safely
++ * ignore MS_SILENT, but anything else left over is an error. So we
++ * need to check if any other flags may have been passed (none are
++ * allowed/supported as of now).
++ */
++ if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) {
++ printk(KERN_ERR
++ "unionfs: remount flags 0x%x unsupported\n", *flags);
++ err = -EINVAL;
++ goto out_error;
++ }
++
++ /*
++ * If 'options' is NULL, it's probably because the user just changed
++ * the union to a "ro" or "rw" and the VFS took care of it. So
++ * nothing to do and we're done.
++ */
++ if (!options || options[0] == '\0')
++ goto out_error;
++
++ /*
++ * Find out how many branches we will have in the end, counting
++ * "add" and "del" commands. Copy the "options" string because
++ * strsep modifies the string and we need it later.
++ */
++ tmp_to_free = kstrdup(options, GFP_KERNEL);
++ optionstmp = tmp_to_free;
++ if (unlikely(!optionstmp)) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ cur_branches = sbmax(sb); /* current no. branches */
++ new_branches = sbmax(sb);
++ del_branches = 0;
++ add_branches = 0;
++ new_high_branch_id = sbhbid(sb); /* save current high_branch_id */
++ while ((optname = strsep(&optionstmp, ",")) != NULL) {
++ char *optarg;
++
++ if (!optname || !*optname)
++ continue;
++
++ optarg = strchr(optname, '=');
++ if (optarg)
++ *optarg++ = '\0';
++
++ if (!strcmp("add", optname))
++ add_branches++;
++ else if (!strcmp("del", optname))
++ del_branches++;
++ }
++ kfree(tmp_to_free);
++ /* after all changes, will we have at least one branch left? */
++ if ((new_branches + add_branches - del_branches) < 1) {
++ printk(KERN_ERR
++ "unionfs: no branches left after remount\n");
++ err = -EINVAL;
++ goto out_free;
++ }
++
++ /*
++ * Since we haven't actually parsed all the add/del options, nor
++ * have we checked them for errors, we don't know for sure how many
++ * branches we will have after all changes have taken place. In
++ * fact, the total number of branches left could be less than what
++ * we have now. So we need to allocate space for a temporary
++ * placeholder that is at least as large as the maximum number of
++ * branches we *could* have, which is the current number plus all
++ * the additions. Once we're done with these temp placeholders, we
++ * may have to re-allocate the final size, copy over from the temp,
++ * and then free the temps (done near the end of this function).
++ */
++ max_branches = cur_branches + add_branches;
++ /* allocate space for new pointers to lower dentry */
++ tmp_data = kcalloc(max_branches,
++ sizeof(struct unionfs_data), GFP_KERNEL);
++ if (unlikely(!tmp_data)) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ /* allocate space for new pointers to lower paths */
++ tmp_lower_paths = kcalloc(max_branches,
++ sizeof(struct path), GFP_KERNEL);
++ if (unlikely(!tmp_lower_paths)) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ /* copy current info into new placeholders, incrementing refcnts */
++ memcpy(tmp_data, UNIONFS_SB(sb)->data,
++ cur_branches * sizeof(struct unionfs_data));
++ memcpy(tmp_lower_paths, UNIONFS_D(sb->s_root)->lower_paths,
++ cur_branches * sizeof(struct path));
++ for (i = 0; i < cur_branches; i++)
++ path_get(&tmp_lower_paths[i]); /* drop refs at end of fxn */
++
++ /*******************************************************************
++ * For each branch command, do path_lookup on the requested branch,
++ * and apply the change to a temp branch list. To handle errors, we
++ * already dup'ed the old arrays (above), and increased the refcnts
++ * on various f/s objects. So now we can do all the path_lookups
++ * and branch-management commands on the new arrays. If it fail mid
++ * way, we free the tmp arrays and *put all objects. If we succeed,
++ * then we free old arrays and *put its objects, and then replace
++ * the arrays with the new tmp list (we may have to re-allocate the
++ * memory because the temp lists could have been larger than what we
++ * actually needed).
++ *******************************************************************/
++
++ while ((optname = strsep(&options, ",")) != NULL) {
++ char *optarg;
++
++ if (!optname || !*optname)
++ continue;
++ /*
++ * At this stage optname holds a comma-delimited option, but
++ * without the commas. Next, we need to break the string on
++ * the '=' symbol to separate CMD=ARG, where ARG itself can
++ * be KEY=VAL. For example, in mode=/foo=rw, CMD is "mode",
++ * KEY is "/foo", and VAL is "rw".
++ */
++ optarg = strchr(optname, '=');
++ if (optarg)
++ *optarg++ = '\0';
++ /* incgen remount option (instead of old ioctl) */
++ if (!strcmp("incgen", optname)) {
++ err = 0;
++ goto out_no_change;
++ }
++
++ /*
++ * All of our options take an argument now. (Insert ones
++ * that don't above this check.) So at this stage optname
++ * contains the CMD part and optarg contains the ARG part.
++ */
++ if (!optarg || !*optarg) {
++ printk(KERN_ERR "unionfs: all remount options require "
++ "an argument (%s)\n", optname);
++ err = -EINVAL;
++ goto out_release;
++ }
++
++ if (!strcmp("add", optname)) {
++ err = do_remount_add_option(optarg, new_branches,
++ tmp_data,
++ tmp_lower_paths,
++ &new_high_branch_id);
++ if (err)
++ goto out_release;
++ new_branches++;
++ if (new_branches > UNIONFS_MAX_BRANCHES) {
++ printk(KERN_ERR "unionfs: command exceeds "
++ "%d branches\n", UNIONFS_MAX_BRANCHES);
++ err = -E2BIG;
++ goto out_release;
++ }
++ continue;
++ }
++ if (!strcmp("del", optname)) {
++ err = do_remount_del_option(optarg, new_branches,
++ tmp_data,
++ tmp_lower_paths);
++ if (err)
++ goto out_release;
++ new_branches--;
++ continue;
++ }
++ if (!strcmp("mode", optname)) {
++ err = do_remount_mode_option(optarg, new_branches,
++ tmp_data,
++ tmp_lower_paths);
++ if (err)
++ goto out_release;
++ continue;
++ }
++
++ /*
++ * When you use "mount -o remount,ro", mount(8) will
++ * reportedly pass the original dirs= string from
++ * /proc/mounts. So for now, we have to ignore dirs= and
++ * not consider it an error, unless we want to allow users
++ * to pass dirs= in remount. Note that to allow the VFS to
++ * actually process the ro/rw remount options, we have to
++ * return 0 from this function.
++ */
++ if (!strcmp("dirs", optname)) {
++ printk(KERN_WARNING
++ "unionfs: remount ignoring option \"%s\"\n",
++ optname);
++ continue;
++ }
++
++ err = -EINVAL;
++ printk(KERN_ERR
++ "unionfs: unrecognized option \"%s\"\n", optname);
++ goto out_release;
++ }
++
++out_no_change:
++
++ /******************************************************************
++ * WE'RE ALMOST DONE: check if leftmost branch might be read-only,
++ * see if we need to allocate a small-sized new vector, copy the
++ * vectors to their correct place, release the refcnt of the older
++ * ones, and return. Also handle invalidating any pages that will
++ * have to be re-read.
++ *******************************************************************/
++
++ if (!(tmp_data[0].branchperms & MAY_WRITE)) {
++ printk(KERN_ERR "unionfs: leftmost branch cannot be read-only "
++ "(use \"remount,ro\" to create a read-only union)\n");
++ err = -EINVAL;
++ goto out_release;
++ }
++
++ /* (re)allocate space for new pointers to lower dentry */
++ size = new_branches * sizeof(struct unionfs_data);
++ new_data = krealloc(tmp_data, size, GFP_KERNEL);
++ if (unlikely(!new_data)) {
++ err = -ENOMEM;
++ goto out_release;
++ }
++
++ /* allocate space for new pointers to lower paths */
++ size = new_branches * sizeof(struct path);
++ new_lower_paths = krealloc(tmp_lower_paths, size, GFP_KERNEL);
++ if (unlikely(!new_lower_paths)) {
++ err = -ENOMEM;
++ goto out_release;
++ }
++
++ /* allocate space for new pointers to lower inodes */
++ new_lower_inodes = kcalloc(new_branches,
++ sizeof(struct inode *), GFP_KERNEL);
++ if (unlikely(!new_lower_inodes)) {
++ err = -ENOMEM;
++ goto out_release;
++ }
++
++ /*
++ * OK, just before we actually put the new set of branches in place,
++ * we need to ensure that our own f/s has no dirty objects left.
++ * Luckily, do_remount_sb() already calls shrink_dcache_sb(sb) and
++ * fsync_super(sb), taking care of dentries, inodes, and dirty
++ * pages. So all that's left is for us to invalidate any leftover
++ * (non-dirty) pages to ensure that they will be re-read from the
++ * new lower branches (and to support mmap).
++ */
++
++ /*
++ * Once we finish the remounting successfully, our superblock
++ * generation number will have increased. This will be detected by
++ * our dentry-revalidation code upon subsequent f/s operations
++ * through unionfs. The revalidation code will rebuild the union of
++ * lower inodes for a given unionfs inode and invalidate any pages
++ * of such "stale" inodes (by calling our purge_inode_data
++ * function). This revalidation will happen lazily and
++ * incrementally, as users perform operations on cached inodes. We
++ * would like to encourage this revalidation to happen sooner if
++ * possible, so we like to try to invalidate as many other pages in
++ * our superblock as we can. We used to call drop_pagecache_sb() or
++ * a variant thereof, but either method was racy (drop_caches alone
++ * is known to be racy). So now we let the revalidation happen on a
++ * per file basis in ->d_revalidate.
++ */
++
++ /* grab new lower super references; release old ones */
++ for (i = 0; i < new_branches; i++)
++ atomic_inc(&new_data[i].sb->s_active);
++ for (i = 0; i < sbmax(sb); i++)
++ atomic_dec(&UNIONFS_SB(sb)->data[i].sb->s_active);
++
++ /* copy new vectors into their correct place */
++ tmp_data = UNIONFS_SB(sb)->data;
++ UNIONFS_SB(sb)->data = new_data;
++ new_data = NULL; /* so don't free good pointers below */
++ tmp_lower_paths = UNIONFS_D(sb->s_root)->lower_paths;
++ UNIONFS_D(sb->s_root)->lower_paths = new_lower_paths;
++ new_lower_paths = NULL; /* so don't free good pointers below */
++
++ /* update our unionfs_sb_info and root dentry index of last branch */
++ i = sbmax(sb); /* save no. of branches to release at end */
++ sbend(sb) = new_branches - 1;
++ dbend(sb->s_root) = new_branches - 1;
++ old_ibstart = ibstart(sb->s_root->d_inode);
++ old_ibend = ibend(sb->s_root->d_inode);
++ ibend(sb->s_root->d_inode) = new_branches - 1;
++ UNIONFS_D(sb->s_root)->bcount = new_branches;
++ new_branches = i; /* no. of branches to release below */
++
++ /*
++ * Update lower inodes: 3 steps
++ * 1. grab ref on all new lower inodes
++ */
++ for (i = dbstart(sb->s_root); i <= dbend(sb->s_root); i++) {
++ struct dentry *lower_dentry =
++ unionfs_lower_dentry_idx(sb->s_root, i);
++ igrab(lower_dentry->d_inode);
++ new_lower_inodes[i] = lower_dentry->d_inode;
++ }
++ /* 2. release reference on all older lower inodes */
++ iput_lowers(sb->s_root->d_inode, old_ibstart, old_ibend, true);
++ /* 3. update root dentry's inode to new lower_inodes array */
++ UNIONFS_I(sb->s_root->d_inode)->lower_inodes = new_lower_inodes;
++ new_lower_inodes = NULL;
++
++ /* maxbytes may have changed */
++ sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
++ /* update high branch ID */
++ sbhbid(sb) = new_high_branch_id;
++
++ /* update our sb->generation for revalidating objects */
++ i = atomic_inc_return(&UNIONFS_SB(sb)->generation);
++ atomic_set(&UNIONFS_D(sb->s_root)->generation, i);
++ atomic_set(&UNIONFS_I(sb->s_root->d_inode)->generation, i);
++ if (!(*flags & MS_SILENT))
++ pr_info("unionfs: %s: new generation number %d\n",
++ UNIONFS_SB(sb)->dev_name, i);
++ /* finally, update the root dentry's times */
++ unionfs_copy_attr_times(sb->s_root->d_inode);
++ err = 0; /* reset to success */
++
++ /*
++ * The code above falls through to the next label, and releases the
++ * refcnts of the older ones (stored in tmp_*): if we fell through
++ * here, it means success. However, if we jump directly to this
++ * label from any error above, then an error occurred after we
++ * grabbed various refcnts, and so we have to release the
++ * temporarily constructed structures.
++ */
++out_release:
++ /* no need to cleanup/release anything in tmp_data */
++ if (tmp_lower_paths)
++ for (i = 0; i < new_branches; i++)
++ path_put(&tmp_lower_paths[i]);
++out_free:
++ kfree(tmp_lower_paths);
++ kfree(tmp_data);
++ kfree(new_lower_paths);
++ kfree(new_data);
++ kfree(new_lower_inodes);
++out_error:
++ unionfs_check_dentry(sb->s_root);
++ unionfs_write_unlock(sb);
++ return err;
++}
++
++/*
++ * Called by iput() when the inode reference count reached zero
++ * and the inode is not hashed anywhere. Used to clear anything
++ * that needs to be, before the inode is completely destroyed and put
++ * on the inode free list.
++ *
++ * No need to lock sb info's rwsem.
++ */
++static void unionfs_evict_inode(struct inode *inode)
++{
++ int bindex, bstart, bend;
++ struct inode *lower_inode;
++ struct list_head *pos, *n;
++ struct unionfs_dir_state *rdstate;
++
++ truncate_inode_pages(&inode->i_data, 0);
++ end_writeback(inode);
++
++ list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
++ rdstate = list_entry(pos, struct unionfs_dir_state, cache);
++ list_del(&rdstate->cache);
++ free_rdstate(rdstate);
++ }
++
++ /*
++ * Decrement a reference to a lower_inode, which was incremented
++ * by our read_inode when it was created initially.
++ */
++ bstart = ibstart(inode);
++ bend = ibend(inode);
++ if (bstart >= 0) {
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++ unionfs_set_lower_inode_idx(inode, bindex, NULL);
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ iput(lower_inode);
++ lockdep_on();
++ }
++ }
++
++ kfree(UNIONFS_I(inode)->lower_inodes);
++ UNIONFS_I(inode)->lower_inodes = NULL;
++}
++
++static struct inode *unionfs_alloc_inode(struct super_block *sb)
++{
++ struct unionfs_inode_info *i;
++
++ i = kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL);
++ if (unlikely(!i))
++ return NULL;
++
++ /* memset everything up to the inode to 0 */
++ memset(i, 0, offsetof(struct unionfs_inode_info, vfs_inode));
++
++ i->vfs_inode.i_version = 1;
++ return &i->vfs_inode;
++}
++
++static void unionfs_destroy_inode(struct inode *inode)
++{
++ kmem_cache_free(unionfs_inode_cachep, UNIONFS_I(inode));
++}
++
++/* unionfs inode cache constructor */
++static void init_once(void *obj)
++{
++ struct unionfs_inode_info *i = obj;
++
++ inode_init_once(&i->vfs_inode);
++}
++
++int unionfs_init_inode_cache(void)
++{
++ int err = 0;
++
++ unionfs_inode_cachep =
++ kmem_cache_create("unionfs_inode_cache",
++ sizeof(struct unionfs_inode_info), 0,
++ SLAB_RECLAIM_ACCOUNT, init_once);
++ if (unlikely(!unionfs_inode_cachep))
++ err = -ENOMEM;
++ return err;
++}
++
++/* unionfs inode cache destructor */
++void unionfs_destroy_inode_cache(void)
++{
++ if (unionfs_inode_cachep)
++ kmem_cache_destroy(unionfs_inode_cachep);
++}
++
++/*
++ * Called when we have a dirty inode, right here we only throw out
++ * parts of our readdir list that are too old.
++ *
++ * No need to grab sb info's rwsem.
++ */
++static int unionfs_write_inode(struct inode *inode,
++ struct writeback_control *wbc)
++{
++ struct list_head *pos, *n;
++ struct unionfs_dir_state *rdstate;
++
++ spin_lock(&UNIONFS_I(inode)->rdlock);
++ list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
++ rdstate = list_entry(pos, struct unionfs_dir_state, cache);
++ /* We keep this list in LRU order. */
++ if ((rdstate->access + RDCACHE_JIFFIES) > jiffies)
++ break;
++ UNIONFS_I(inode)->rdcount--;
++ list_del(&rdstate->cache);
++ free_rdstate(rdstate);
++ }
++ spin_unlock(&UNIONFS_I(inode)->rdlock);
++
++ return 0;
++}
++
++/*
++ * Used only in nfs, to kill any pending RPC tasks, so that subsequent
++ * code can actually succeed and won't leave tasks that need handling.
++ */
++static void unionfs_umount_begin(struct super_block *sb)
++{
++ struct super_block *lower_sb;
++ int bindex, bstart, bend;
++
++ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
++
++ bstart = sbstart(sb);
++ bend = sbend(sb);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_sb = unionfs_lower_super_idx(sb, bindex);
++
++ if (lower_sb && lower_sb->s_op &&
++ lower_sb->s_op->umount_begin)
++ lower_sb->s_op->umount_begin(lower_sb);
++ }
++
++ unionfs_read_unlock(sb);
++}
++
++static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt)
++{
++ struct super_block *sb = mnt->mnt_sb;
++ int ret = 0;
++ char *tmp_page;
++ char *path;
++ int bindex, bstart, bend;
++ int perms;
++
++ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
++
++ unionfs_lock_dentry(sb->s_root, UNIONFS_DMUTEX_CHILD);
++
++ tmp_page = (char *) __get_free_page(GFP_KERNEL);
++ if (unlikely(!tmp_page)) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ bstart = sbstart(sb);
++ bend = sbend(sb);
++
++ seq_printf(m, ",dirs=");
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ struct path p;
++ p.dentry = unionfs_lower_dentry_idx(sb->s_root, bindex);
++ p.mnt = unionfs_lower_mnt_idx(sb->s_root, bindex);
++ path = d_path(&p, tmp_page, PAGE_SIZE);
++ if (IS_ERR(path)) {
++ ret = PTR_ERR(path);
++ goto out;
++ }
++
++ perms = branchperms(sb, bindex);
++
++ seq_printf(m, "%s=%s", path,
++ perms & MAY_WRITE ? "rw" : "ro");
++ if (bindex != bend)
++ seq_printf(m, ":");
++ }
++
++out:
++ free_page((unsigned long) tmp_page);
++
++ unionfs_unlock_dentry(sb->s_root);
++
++ unionfs_read_unlock(sb);
++
++ return ret;
++}
++
++struct super_operations unionfs_sops = {
++ .put_super = unionfs_put_super,
++ .statfs = unionfs_statfs,
++ .remount_fs = unionfs_remount_fs,
++ .evict_inode = unionfs_evict_inode,
++ .umount_begin = unionfs_umount_begin,
++ .show_options = unionfs_show_options,
++ .write_inode = unionfs_write_inode,
++ .alloc_inode = unionfs_alloc_inode,
++ .destroy_inode = unionfs_destroy_inode,
++};
+diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
+new file mode 100644
+index 0000000..d49c834
+--- /dev/null
++++ b/fs/unionfs/union.h
+@@ -0,0 +1,669 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _UNION_H_
++#define _UNION_H_
++
++#include <linux/dcache.h>
++#include <linux/file.h>
++#include <linux/list.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/mount.h>
++#include <linux/namei.h>
++#include <linux/page-flags.h>
++#include <linux/pagemap.h>
++#include <linux/poll.h>
++#include <linux/security.h>
++#include <linux/seq_file.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/smp_lock.h>
++#include <linux/statfs.h>
++#include <linux/string.h>
++#include <linux/vmalloc.h>
++#include <linux/writeback.h>
++#include <linux/buffer_head.h>
++#include <linux/xattr.h>
++#include <linux/fs_stack.h>
++#include <linux/magic.h>
++#include <linux/log2.h>
++#include <linux/poison.h>
++#include <linux/mman.h>
++#include <linux/backing-dev.h>
++#include <linux/splice.h>
++
++#include <asm/system.h>
++
++#include <linux/union_fs.h>
++
++/* the file system name */
++#define UNIONFS_NAME "unionfs"
++
++/* unionfs root inode number */
++#define UNIONFS_ROOT_INO 1
++
++/* number of times we try to get a unique temporary file name */
++#define GET_TMPNAM_MAX_RETRY 5
++
++/* maximum number of branches we support, to avoid memory blowup */
++#define UNIONFS_MAX_BRANCHES 128
++
++/* minimum time (seconds) required for time-based cache-coherency */
++#define UNIONFS_MIN_CC_TIME 3
++
++/* Operations vectors defined in specific files. */
++extern struct file_operations unionfs_main_fops;
++extern struct file_operations unionfs_dir_fops;
++extern struct inode_operations unionfs_main_iops;
++extern struct inode_operations unionfs_dir_iops;
++extern struct inode_operations unionfs_symlink_iops;
++extern struct super_operations unionfs_sops;
++extern struct dentry_operations unionfs_dops;
++extern struct address_space_operations unionfs_aops, unionfs_dummy_aops;
++extern struct vm_operations_struct unionfs_vm_ops;
++
++/* How long should an entry be allowed to persist */
++#define RDCACHE_JIFFIES (5*HZ)
++
++/* compatibility with Real-Time patches */
++#ifdef CONFIG_PREEMPT_RT
++# define unionfs_rw_semaphore compat_rw_semaphore
++#else /* not CONFIG_PREEMPT_RT */
++# define unionfs_rw_semaphore rw_semaphore
++#endif /* not CONFIG_PREEMPT_RT */
++
++/* file private data. */
++struct unionfs_file_info {
++ int bstart;
++ int bend;
++ atomic_t generation;
++
++ struct unionfs_dir_state *rdstate;
++ struct file **lower_files;
++ int *saved_branch_ids; /* IDs of branches when file was opened */
++ const struct vm_operations_struct *lower_vm_ops;
++ bool wrote_to_file; /* for delayed copyup */
++};
++
++/* unionfs inode data in memory */
++struct unionfs_inode_info {
++ int bstart;
++ int bend;
++ atomic_t generation;
++ /* Stuff for readdir over NFS. */
++ spinlock_t rdlock;
++ struct list_head readdircache;
++ int rdcount;
++ int hashsize;
++ int cookie;
++
++ /* The lower inodes */
++ struct inode **lower_inodes;
++
++ struct inode vfs_inode;
++};
++
++/* unionfs dentry data in memory */
++struct unionfs_dentry_info {
++ /*
++ * The semaphore is used to lock the dentry as soon as we get into a
++ * unionfs function from the VFS. Our lock ordering is that children
++ * go before their parents.
++ */
++ struct mutex lock;
++ int bstart;
++ int bend;
++ int bopaque;
++ int bcount;
++ atomic_t generation;
++ struct path *lower_paths;
++};
++
++/* These are the pointers to our various objects. */
++struct unionfs_data {
++ struct super_block *sb; /* lower super_block */
++ atomic_t open_files; /* number of open files on branch */
++ int branchperms;
++ int branch_id; /* unique branch ID at re/mount time */
++};
++
++/* unionfs super-block data in memory */
++struct unionfs_sb_info {
++ int bend;
++
++ atomic_t generation;
++
++ /*
++ * This rwsem is used to make sure that a branch management
++ * operation...
++ * 1) will not begin before all currently in-flight operations
++ * complete.
++ * 2) any new operations do not execute until the currently
++ * running branch management operation completes.
++ *
++ * The write_lock_owner records the PID of the task which grabbed
++ * the rw_sem for writing. If the same task also tries to grab the
++ * read lock, we allow it. This prevents a self-deadlock when
++ * branch-management is used on a pivot_root'ed union, because we
++ * have to ->lookup paths which belong to the same union.
++ */
++ struct unionfs_rw_semaphore rwsem;
++ pid_t write_lock_owner; /* PID of rw_sem owner (write lock) */
++ int high_branch_id; /* last unique branch ID given */
++ char *dev_name; /* to identify different unions in pr_debug */
++ struct unionfs_data *data;
++};
++
++/*
++ * structure for making the linked list of entries by readdir on left branch
++ * to compare with entries on right branch
++ */
++struct filldir_node {
++ struct list_head file_list; /* list for directory entries */
++ char *name; /* name entry */
++ int hash; /* name hash */
++ int namelen; /* name len since name is not 0 terminated */
++
++ /*
++ * we can check for duplicate whiteouts and files in the same branch
++ * in order to return -EIO.
++ */
++ int bindex;
++
++ /* is this a whiteout entry? */
++ int whiteout;
++
++ /* Inline name, so we don't need to separately kmalloc small ones */
++ char iname[DNAME_INLINE_LEN_MIN];
++};
++
++/* Directory hash table. */
++struct unionfs_dir_state {
++ unsigned int cookie; /* the cookie, based off of rdversion */
++ unsigned int offset; /* The entry we have returned. */
++ int bindex;
++ loff_t dirpos; /* offset within the lower level directory */
++ int size; /* How big is the hash table? */
++ int hashentries; /* How many entries have been inserted? */
++ unsigned long access;
++
++ /* This cache list is used when the inode keeps us around. */
++ struct list_head cache;
++ struct list_head list[0];
++};
++
++/* externs needed for fanout.h or sioq.h */
++extern int unionfs_get_nlinks(const struct inode *inode);
++extern void unionfs_copy_attr_times(struct inode *upper);
++extern void unionfs_copy_attr_all(struct inode *dest, const struct inode *src);
++
++/* include miscellaneous macros */
++#include "fanout.h"
++#include "sioq.h"
++
++/* externs for cache creation/deletion routines */
++extern void unionfs_destroy_filldir_cache(void);
++extern int unionfs_init_filldir_cache(void);
++extern int unionfs_init_inode_cache(void);
++extern void unionfs_destroy_inode_cache(void);
++extern int unionfs_init_dentry_cache(void);
++extern void unionfs_destroy_dentry_cache(void);
++
++/* Initialize and free readdir-specific state. */
++extern int init_rdstate(struct file *file);
++extern struct unionfs_dir_state *alloc_rdstate(struct inode *inode,
++ int bindex);
++extern struct unionfs_dir_state *find_rdstate(struct inode *inode,
++ loff_t fpos);
++extern void free_rdstate(struct unionfs_dir_state *state);
++extern int add_filldir_node(struct unionfs_dir_state *rdstate,
++ const char *name, int namelen, int bindex,
++ int whiteout);
++extern struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
++ const char *name, int namelen,
++ int is_whiteout);
++
++extern struct dentry **alloc_new_dentries(int objs);
++extern struct unionfs_data *alloc_new_data(int objs);
++
++/* We can only use 32-bits of offset for rdstate --- blech! */
++#define DIREOF (0xfffff)
++#define RDOFFBITS 20 /* This is the number of bits in DIREOF. */
++#define MAXRDCOOKIE (0xfff)
++/* Turn an rdstate into an offset. */
++static inline off_t rdstate2offset(struct unionfs_dir_state *buf)
++{
++ off_t tmp;
++
++ tmp = ((buf->cookie & MAXRDCOOKIE) << RDOFFBITS)
++ | (buf->offset & DIREOF);
++ return tmp;
++}
++
++/* Macros for locking a super_block. */
++enum unionfs_super_lock_class {
++ UNIONFS_SMUTEX_NORMAL,
++ UNIONFS_SMUTEX_PARENT, /* when locking on behalf of file */
++ UNIONFS_SMUTEX_CHILD, /* when locking on behalf of dentry */
++};
++static inline void unionfs_read_lock(struct super_block *sb, int subclass)
++{
++ if (UNIONFS_SB(sb)->write_lock_owner &&
++ UNIONFS_SB(sb)->write_lock_owner == current->pid)
++ return;
++ down_read_nested(&UNIONFS_SB(sb)->rwsem, subclass);
++}
++static inline void unionfs_read_unlock(struct super_block *sb)
++{
++ if (UNIONFS_SB(sb)->write_lock_owner &&
++ UNIONFS_SB(sb)->write_lock_owner == current->pid)
++ return;
++ up_read(&UNIONFS_SB(sb)->rwsem);
++}
++static inline void unionfs_write_lock(struct super_block *sb)
++{
++ down_write(&UNIONFS_SB(sb)->rwsem);
++ UNIONFS_SB(sb)->write_lock_owner = current->pid;
++}
++static inline void unionfs_write_unlock(struct super_block *sb)
++{
++ up_write(&UNIONFS_SB(sb)->rwsem);
++ UNIONFS_SB(sb)->write_lock_owner = 0;
++}
++
++static inline void unionfs_double_lock_dentry(struct dentry *d1,
++ struct dentry *d2)
++{
++ BUG_ON(d1 == d2);
++ if (d1 < d2) {
++ unionfs_lock_dentry(d1, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(d2, UNIONFS_DMUTEX_CHILD);
++ } else {
++ unionfs_lock_dentry(d2, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(d1, UNIONFS_DMUTEX_CHILD);
++ }
++}
++
++static inline void unionfs_double_unlock_dentry(struct dentry *d1,
++ struct dentry *d2)
++{
++ BUG_ON(d1 == d2);
++ if (d1 < d2) { /* unlock in reverse order than double_lock_dentry */
++ unionfs_unlock_dentry(d1);
++ unionfs_unlock_dentry(d2);
++ } else {
++ unionfs_unlock_dentry(d2);
++ unionfs_unlock_dentry(d1);
++ }
++}
++
++static inline void unionfs_double_lock_parents(struct dentry *p1,
++ struct dentry *p2)
++{
++ if (p1 == p2) {
++ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_PARENT);
++ return;
++ }
++ if (p1 < p2) {
++ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_PARENT);
++ unionfs_lock_dentry(p2, UNIONFS_DMUTEX_REVAL_CHILD);
++ } else {
++ unionfs_lock_dentry(p2, UNIONFS_DMUTEX_REVAL_PARENT);
++ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_CHILD);
++ }
++}
++
++static inline void unionfs_double_unlock_parents(struct dentry *p1,
++ struct dentry *p2)
++{
++ if (p1 == p2) {
++ unionfs_unlock_dentry(p1);
++ return;
++ }
++ if (p1 < p2) { /* unlock in reverse order of double_lock_parents */
++ unionfs_unlock_dentry(p1);
++ unionfs_unlock_dentry(p2);
++ } else {
++ unionfs_unlock_dentry(p2);
++ unionfs_unlock_dentry(p1);
++ }
++}
++
++extern int new_dentry_private_data(struct dentry *dentry, int subclass);
++extern int realloc_dentry_private_data(struct dentry *dentry);
++extern void free_dentry_private_data(struct dentry *dentry);
++extern void update_bstart(struct dentry *dentry);
++extern int init_lower_nd(struct nameidata *nd, unsigned int flags);
++extern void release_lower_nd(struct nameidata *nd, int err);
++
++/*
++ * EXTERNALS:
++ */
++
++/* replicates the directory structure up to given dentry in given branch */
++extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
++ const char *name, int bindex);
++
++/* partial lookup */
++extern int unionfs_partial_lookup(struct dentry *dentry,
++ struct dentry *parent);
++extern struct dentry *unionfs_lookup_full(struct dentry *dentry,
++ struct dentry *parent,
++ int lookupmode);
++
++/* copies a file from dbstart to newbindex branch */
++extern int copyup_file(struct inode *dir, struct file *file, int bstart,
++ int newbindex, loff_t size);
++extern int copyup_named_file(struct inode *dir, struct file *file,
++ char *name, int bstart, int new_bindex,
++ loff_t len);
++/* copies a dentry from dbstart to newbindex branch */
++extern int copyup_dentry(struct inode *dir, struct dentry *dentry,
++ int bstart, int new_bindex, const char *name,
++ int namelen, struct file **copyup_file, loff_t len);
++/* helper functions for post-copyup actions */
++extern void unionfs_postcopyup_setmnt(struct dentry *dentry);
++extern void unionfs_postcopyup_release(struct dentry *dentry);
++
++/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */
++extern int check_empty(struct dentry *dentry, struct dentry *parent,
++ struct unionfs_dir_state **namelist);
++/* whiteout and opaque directory helpers */
++extern char *alloc_whname(const char *name, int len);
++extern bool is_whiteout_name(char **namep, int *namelenp);
++extern bool is_validname(const char *name);
++extern struct dentry *lookup_whiteout(const char *name,
++ struct dentry *lower_parent);
++extern struct dentry *find_first_whiteout(struct dentry *dentry);
++extern int unlink_whiteout(struct dentry *wh_dentry);
++extern int check_unlink_whiteout(struct dentry *dentry,
++ struct dentry *lower_dentry, int bindex);
++extern int create_whiteout(struct dentry *dentry, int start);
++extern int delete_whiteouts(struct dentry *dentry, int bindex,
++ struct unionfs_dir_state *namelist);
++extern int is_opaque_dir(struct dentry *dentry, int bindex);
++extern int make_dir_opaque(struct dentry *dir, int bindex);
++extern void unionfs_set_max_namelen(long *namelen);
++
++extern void unionfs_reinterpose(struct dentry *this_dentry);
++extern struct super_block *unionfs_duplicate_super(struct super_block *sb);
++
++/* Locking functions. */
++extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl);
++extern int unionfs_getlk(struct file *file, struct file_lock *fl);
++
++/* Common file operations. */
++extern int unionfs_file_revalidate(struct file *file, struct dentry *parent,
++ bool willwrite);
++extern int unionfs_open(struct inode *inode, struct file *file);
++extern int unionfs_file_release(struct inode *inode, struct file *file);
++extern int unionfs_flush(struct file *file, fl_owner_t id);
++extern long unionfs_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg);
++extern int unionfs_fsync(struct file *file, int datasync);
++extern int unionfs_fasync(int fd, struct file *file, int flag);
++
++/* Inode operations */
++extern struct inode *unionfs_iget(struct super_block *sb, unsigned long ino);
++extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry);
++extern int unionfs_unlink(struct inode *dir, struct dentry *dentry);
++extern int unionfs_rmdir(struct inode *dir, struct dentry *dentry);
++
++extern bool __unionfs_d_revalidate(struct dentry *dentry,
++ struct dentry *parent, bool willwrite);
++extern bool is_negative_lower(const struct dentry *dentry);
++extern bool is_newer_lower(const struct dentry *dentry);
++extern void purge_sb_data(struct super_block *sb);
++
++/* The values for unionfs_interpose's flag. */
++#define INTERPOSE_DEFAULT 0
++#define INTERPOSE_LOOKUP 1
++#define INTERPOSE_REVAL 2
++#define INTERPOSE_REVAL_NEG 3
++#define INTERPOSE_PARTIAL 4
++
++extern struct dentry *unionfs_interpose(struct dentry *this_dentry,
++ struct super_block *sb, int flag);
++
++#ifdef CONFIG_UNION_FS_XATTR
++/* Extended attribute functions. */
++extern void *unionfs_xattr_alloc(size_t size, size_t limit);
++static inline void unionfs_xattr_kfree(const void *p)
++{
++ kfree(p);
++}
++extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
++ void *value, size_t size);
++extern int unionfs_removexattr(struct dentry *dentry, const char *name);
++extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list,
++ size_t size);
++extern int unionfs_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags);
++#endif /* CONFIG_UNION_FS_XATTR */
++
++/* The root directory is unhashed, but isn't deleted. */
++static inline int d_deleted(struct dentry *d)
++{
++ return d_unhashed(d) && (d != d->d_sb->s_root);
++}
++
++/* unionfs_permission, check if we should bypass error to facilitate copyup */
++#define IS_COPYUP_ERR(err) ((err) == -EROFS)
++
++/* unionfs_open, check if we need to copyup the file */
++#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND)
++#define IS_WRITE_FLAG(flag) ((flag) & OPEN_WRITE_FLAGS)
++
++static inline int branchperms(const struct super_block *sb, int index)
++{
++ BUG_ON(index < 0);
++ return UNIONFS_SB(sb)->data[index].branchperms;
++}
++
++static inline int set_branchperms(struct super_block *sb, int index, int perms)
++{
++ BUG_ON(index < 0);
++ UNIONFS_SB(sb)->data[index].branchperms = perms;
++ return perms;
++}
++
++/* check if readonly lower inode, but possibly unlinked (no inode->i_sb) */
++static inline int __is_rdonly(const struct inode *inode)
++{
++ /* if unlinked, can't be readonly (?) */
++ if (!inode->i_sb)
++ return 0;
++ return IS_RDONLY(inode);
++
++}
++/* Is this file on a read-only branch? */
++static inline int is_robranch_super(const struct super_block *sb, int index)
++{
++ int ret;
++
++ ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
++ return ret;
++}
++
++/* Is this file on a read-only branch? */
++static inline int is_robranch_idx(const struct dentry *dentry, int index)
++{
++ struct super_block *lower_sb;
++
++ BUG_ON(index < 0);
++
++ if (!(branchperms(dentry->d_sb, index) & MAY_WRITE))
++ return -EROFS;
++
++ lower_sb = unionfs_lower_super_idx(dentry->d_sb, index);
++ BUG_ON(lower_sb == NULL);
++ /*
++ * test sb flags directly, not IS_RDONLY(lower_inode) because the
++ * lower_dentry could be a negative.
++ */
++ if (lower_sb->s_flags & MS_RDONLY)
++ return -EROFS;
++
++ return 0;
++}
++
++static inline int is_robranch(const struct dentry *dentry)
++{
++ int index;
++
++ index = UNIONFS_D(dentry)->bstart;
++ BUG_ON(index < 0);
++
++ return is_robranch_idx(dentry, index);
++}
++
++/*
++ * EXTERNALS:
++ */
++extern int check_branch(struct nameidata *nd);
++extern int parse_branch_mode(const char *name, int *perms);
++
++/* locking helpers */
++static inline struct dentry *lock_parent(struct dentry *dentry)
++{
++ struct dentry *dir = dget_parent(dentry);
++ mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
++ return dir;
++}
++static inline struct dentry *lock_parent_wh(struct dentry *dentry)
++{
++ struct dentry *dir = dget_parent(dentry);
++
++ mutex_lock_nested(&dir->d_inode->i_mutex, UNIONFS_DMUTEX_WHITEOUT);
++ return dir;
++}
++
++static inline void unlock_dir(struct dentry *dir)
++{
++ mutex_unlock(&dir->d_inode->i_mutex);
++ dput(dir);
++}
++
++/* lock base inode mutex before calling lookup_one_len */
++static inline struct dentry *lookup_lck_len(const char *name,
++ struct dentry *base, int len)
++{
++ struct dentry *d;
++ mutex_lock(&base->d_inode->i_mutex);
++ d = lookup_one_len(name, base, len);
++ mutex_unlock(&base->d_inode->i_mutex);
++ return d;
++}
++
++static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
++ int bindex)
++{
++ struct vfsmount *mnt;
++
++ BUG_ON(!dentry || bindex < 0);
++
++ mnt = mntget(unionfs_lower_mnt_idx(dentry, bindex));
++#ifdef CONFIG_UNION_FS_DEBUG
++ if (!mnt)
++ pr_debug("unionfs: mntget: mnt=%p bindex=%d\n",
++ mnt, bindex);
++#endif /* CONFIG_UNION_FS_DEBUG */
++
++ return mnt;
++}
++
++static inline void unionfs_mntput(struct dentry *dentry, int bindex)
++{
++ struct vfsmount *mnt;
++
++ if (!dentry && bindex < 0)
++ return;
++ BUG_ON(!dentry || bindex < 0);
++
++ mnt = unionfs_lower_mnt_idx(dentry, bindex);
++#ifdef CONFIG_UNION_FS_DEBUG
++ /*
++ * Directories can have NULL lower objects in between start/end, but
++ * NOT if at the start/end range. We cannot verify that this dentry
++ * is a type=DIR, because it may already be a negative dentry. But
++ * if dbstart is greater than dbend, we know that this couldn't have
++ * been a regular file: it had to have been a directory.
++ */
++ if (!mnt && !(bindex > dbstart(dentry) && bindex < dbend(dentry)))
++ pr_debug("unionfs: mntput: mnt=%p bindex=%d\n", mnt, bindex);
++#endif /* CONFIG_UNION_FS_DEBUG */
++ mntput(mnt);
++}
++
++#ifdef CONFIG_UNION_FS_DEBUG
++
++/* useful for tracking code reachability */
++#define UDBG pr_debug("DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
++
++#define unionfs_check_inode(i) __unionfs_check_inode((i), \
++ __FILE__, __func__, __LINE__)
++#define unionfs_check_dentry(d) __unionfs_check_dentry((d), \
++ __FILE__, __func__, __LINE__)
++#define unionfs_check_file(f) __unionfs_check_file((f), \
++ __FILE__, __func__, __LINE__)
++#define unionfs_check_nd(n) __unionfs_check_nd((n), \
++ __FILE__, __func__, __LINE__)
++#define show_branch_counts(sb) __show_branch_counts((sb), \
++ __FILE__, __func__, __LINE__)
++#define show_inode_times(i) __show_inode_times((i), \
++ __FILE__, __func__, __LINE__)
++#define show_dinode_times(d) __show_dinode_times((d), \
++ __FILE__, __func__, __LINE__)
++#define show_inode_counts(i) __show_inode_counts((i), \
++ __FILE__, __func__, __LINE__)
++
++extern void __unionfs_check_inode(const struct inode *inode, const char *fname,
++ const char *fxn, int line);
++extern void __unionfs_check_dentry(const struct dentry *dentry,
++ const char *fname, const char *fxn,
++ int line);
++extern void __unionfs_check_file(const struct file *file,
++ const char *fname, const char *fxn, int line);
++extern void __unionfs_check_nd(const struct nameidata *nd,
++ const char *fname, const char *fxn, int line);
++extern void __show_branch_counts(const struct super_block *sb,
++ const char *file, const char *fxn, int line);
++extern void __show_inode_times(const struct inode *inode,
++ const char *file, const char *fxn, int line);
++extern void __show_dinode_times(const struct dentry *dentry,
++ const char *file, const char *fxn, int line);
++extern void __show_inode_counts(const struct inode *inode,
++ const char *file, const char *fxn, int line);
++
++#else /* not CONFIG_UNION_FS_DEBUG */
++
++/* we leave useful hooks for these check functions throughout the code */
++#define unionfs_check_inode(i) do { } while (0)
++#define unionfs_check_dentry(d) do { } while (0)
++#define unionfs_check_file(f) do { } while (0)
++#define unionfs_check_nd(n) do { } while (0)
++#define show_branch_counts(sb) do { } while (0)
++#define show_inode_times(i) do { } while (0)
++#define show_dinode_times(d) do { } while (0)
++#define show_inode_counts(i) do { } while (0)
++
++#endif /* not CONFIG_UNION_FS_DEBUG */
++
++#endif /* not _UNION_H_ */
+diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
+new file mode 100644
+index 0000000..542c513
+--- /dev/null
++++ b/fs/unionfs/unlink.c
+@@ -0,0 +1,278 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * Helper function for Unionfs's unlink operation.
++ *
++ * The main goal of this function is to optimize the unlinking of non-dir
++ * objects in unionfs by deleting all possible lower inode objects from the
++ * underlying branches having same dentry name as the non-dir dentry on
++ * which this unlink operation is called. This way we delete as many lower
++ * inodes as possible, and save space. Whiteouts need to be created in
++ * branch0 only if unlinking fails on any of the lower branch other than
++ * branch0, or if a lower branch is marked read-only.
++ *
++ * Also, while unlinking a file, if we encounter any dir type entry in any
++ * intermediate branch, then we remove the directory by calling vfs_rmdir.
++ * The following special cases are also handled:
++
++ * (1) If an error occurs in branch0 during vfs_unlink, then we return
++ * appropriate error.
++ *
++ * (2) If we get an error during unlink in any of other lower branch other
++ * than branch0, then we create a whiteout in branch0.
++ *
++ * (3) If a whiteout already exists in any intermediate branch, we delete
++ * all possible inodes only up to that branch (this is an "opaqueness"
++ * as as per Documentation/filesystems/unionfs/concepts.txt).
++ *
++ */
++static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry,
++ struct dentry *parent)
++{
++ struct dentry *lower_dentry;
++ struct dentry *lower_dir_dentry;
++ int bindex;
++ int err = 0;
++
++ err = unionfs_partial_lookup(dentry, parent);
++ if (err)
++ goto out;
++
++ /* trying to unlink all possible valid instances */
++ for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry || !lower_dentry->d_inode)
++ continue;
++
++ lower_dir_dentry = lock_parent(lower_dentry);
++
++ /* avoid destroying the lower inode if the object is in use */
++ dget(lower_dentry);
++ err = is_robranch_super(dentry->d_sb, bindex);
++ if (!err) {
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
++ err = vfs_unlink(lower_dir_dentry->d_inode,
++ lower_dentry);
++ else
++ err = vfs_rmdir(lower_dir_dentry->d_inode,
++ lower_dentry);
++ lockdep_on();
++ }
++
++ /* if lower object deletion succeeds, update inode's times */
++ if (!err)
++ unionfs_copy_attr_times(dentry->d_inode);
++ dput(lower_dentry);
++ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++ unlock_dir(lower_dir_dentry);
++
++ if (err)
++ break;
++ }
++
++ /*
++ * Create the whiteout in branch 0 (highest priority) only if (a)
++ * there was an error in any intermediate branch other than branch 0
++ * due to failure of vfs_unlink/vfs_rmdir or (b) a branch marked or
++ * mounted read-only.
++ */
++ if (err) {
++ if ((bindex == 0) ||
++ ((bindex == dbstart(dentry)) &&
++ (!IS_COPYUP_ERR(err))))
++ goto out;
++ else {
++ if (!IS_COPYUP_ERR(err))
++ pr_debug("unionfs: lower object deletion "
++ "failed in branch:%d\n", bindex);
++ err = create_whiteout(dentry, sbstart(dentry->d_sb));
++ }
++ }
++
++out:
++ if (!err)
++ inode_dec_link_count(dentry->d_inode);
++
++ /* We don't want to leave negative leftover dentries for revalidate. */
++ if (!err && (dbopaque(dentry) != -1))
++ update_bstart(dentry);
++
++ return err;
++}
++
++int unionfs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ int err = 0;
++ struct inode *inode = dentry->d_inode;
++ struct dentry *parent;
++ int valid;
++
++ BUG_ON(S_ISDIR(inode->i_mode));
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ unionfs_check_dentry(dentry);
++
++ err = unionfs_unlink_whiteout(dir, dentry, parent);
++ /* call d_drop so the system "forgets" about us */
++ if (!err) {
++ unionfs_postcopyup_release(dentry);
++ unionfs_postcopyup_setmnt(parent);
++ if (inode->i_nlink == 0) /* drop lower inodes */
++ iput_lowers_all(inode, false);
++ d_drop(dentry);
++ /*
++ * if unlink/whiteout succeeded, parent dir mtime has
++ * changed
++ */
++ unionfs_copy_attr_times(dir);
++ }
++
++out:
++ if (!err) {
++ unionfs_check_dentry(dentry);
++ unionfs_check_inode(dir);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry,
++ struct unionfs_dir_state *namelist)
++{
++ int err;
++ struct dentry *lower_dentry;
++ struct dentry *lower_dir_dentry = NULL;
++
++ /* Here we need to remove whiteout entries. */
++ err = delete_whiteouts(dentry, dbstart(dentry), namelist);
++ if (err)
++ goto out;
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ lower_dir_dentry = lock_parent(lower_dentry);
++
++ /* avoid destroying the lower inode if the file is in use */
++ dget(lower_dentry);
++ err = is_robranch(dentry);
++ if (!err)
++ err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
++ dput(lower_dentry);
++
++ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++ /* propagate number of hard-links */
++ dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode);
++
++out:
++ if (lower_dir_dentry)
++ unlock_dir(lower_dir_dentry);
++ return err;
++}
++
++int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ int err = 0;
++ struct unionfs_dir_state *namelist = NULL;
++ struct dentry *parent;
++ int dstart, dend;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ unionfs_check_dentry(dentry);
++
++ /* check if this unionfs directory is empty or not */
++ err = check_empty(dentry, parent, &namelist);
++ if (err)
++ goto out;
++
++ err = unionfs_rmdir_first(dir, dentry, namelist);
++ dstart = dbstart(dentry);
++ dend = dbend(dentry);
++ /*
++ * We create a whiteout for the directory if there was an error to
++ * rmdir the first directory entry in the union. Otherwise, we
++ * create a whiteout only if there is no chance that a lower
++ * priority branch might also have the same named directory. IOW,
++ * if there is not another same-named directory at a lower priority
++ * branch, then we don't need to create a whiteout for it.
++ */
++ if (!err) {
++ if (dstart < dend)
++ err = create_whiteout(dentry, dstart);
++ } else {
++ int new_err;
++
++ if (dstart == 0)
++ goto out;
++
++ /* exit if the error returned was NOT -EROFS */
++ if (!IS_COPYUP_ERR(err))
++ goto out;
++
++ new_err = create_whiteout(dentry, dstart - 1);
++ if (new_err != -EEXIST)
++ err = new_err;
++ }
++
++out:
++ /*
++ * Drop references to lower dentry/inode so storage space for them
++ * can be reclaimed. Then, call d_drop so the system "forgets"
++ * about us.
++ */
++ if (!err) {
++ iput_lowers_all(dentry->d_inode, false);
++ dput(unionfs_lower_dentry_idx(dentry, dstart));
++ unionfs_set_lower_dentry_idx(dentry, dstart, NULL);
++ d_drop(dentry);
++ /* update our lower vfsmnts, in case a copyup took place */
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_dentry(dentry);
++ unionfs_check_inode(dir);
++ }
++
++ if (namelist)
++ free_rdstate(namelist);
++
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
+diff --git a/fs/unionfs/whiteout.c b/fs/unionfs/whiteout.c
+new file mode 100644
+index 0000000..405073a
+--- /dev/null
++++ b/fs/unionfs/whiteout.c
+@@ -0,0 +1,584 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/*
++ * whiteout and opaque directory helpers
++ */
++
++/* What do we use for whiteouts. */
++#define UNIONFS_WHPFX ".wh."
++#define UNIONFS_WHLEN 4
++/*
++ * If a directory contains this file, then it is opaque. We start with the
++ * .wh. flag so that it is blocked by lookup.
++ */
++#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque"
++#define UNIONFS_DIR_OPAQUE UNIONFS_WHPFX UNIONFS_DIR_OPAQUE_NAME
++
++/* construct whiteout filename */
++char *alloc_whname(const char *name, int len)
++{
++ char *buf;
++
++ buf = kmalloc(len + UNIONFS_WHLEN + 1, GFP_KERNEL);
++ if (unlikely(!buf))
++ return ERR_PTR(-ENOMEM);
++
++ strcpy(buf, UNIONFS_WHPFX);
++ strlcat(buf, name, len + UNIONFS_WHLEN + 1);
++
++ return buf;
++}
++
++/*
++ * XXX: this can be inline or CPP macro, but is here to keep all whiteout
++ * code in one place.
++ */
++void unionfs_set_max_namelen(long *namelen)
++{
++ *namelen -= UNIONFS_WHLEN;
++}
++
++/* check if @namep is a whiteout, update @namep and @namelenp accordingly */
++bool is_whiteout_name(char **namep, int *namelenp)
++{
++ if (*namelenp > UNIONFS_WHLEN &&
++ !strncmp(*namep, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
++ *namep += UNIONFS_WHLEN;
++ *namelenp -= UNIONFS_WHLEN;
++ return true;
++ }
++ return false;
++}
++
++/* is the filename valid == !(whiteout for a file or opaque dir marker) */
++bool is_validname(const char *name)
++{
++ if (!strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN))
++ return false;
++ if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME,
++ sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1))
++ return false;
++ return true;
++}
++
++/*
++ * Look for a whiteout @name in @lower_parent directory. If error, return
++ * ERR_PTR. Caller must dput() the returned dentry if not an error.
++ *
++ * XXX: some callers can reuse the whname allocated buffer to avoid repeated
++ * free then re-malloc calls. Need to provide a different API for those
++ * callers.
++ */
++struct dentry *lookup_whiteout(const char *name, struct dentry *lower_parent)
++{
++ char *whname = NULL;
++ int err = 0, namelen;
++ struct dentry *wh_dentry = NULL;
++
++ namelen = strlen(name);
++ whname = alloc_whname(name, namelen);
++ if (unlikely(IS_ERR(whname))) {
++ err = PTR_ERR(whname);
++ goto out;
++ }
++
++ /* check if whiteout exists in this branch: lookup .wh.foo */
++ wh_dentry = lookup_lck_len(whname, lower_parent, strlen(whname));
++ if (IS_ERR(wh_dentry)) {
++ err = PTR_ERR(wh_dentry);
++ goto out;
++ }
++
++ /* check if negative dentry (ENOENT) */
++ if (!wh_dentry->d_inode)
++ goto out;
++
++ /* whiteout found: check if valid type */
++ if (!S_ISREG(wh_dentry->d_inode->i_mode)) {
++ printk(KERN_ERR "unionfs: invalid whiteout %s entry type %d\n",
++ whname, wh_dentry->d_inode->i_mode);
++ dput(wh_dentry);
++ err = -EIO;
++ goto out;
++ }
++
++out:
++ kfree(whname);
++ if (err)
++ wh_dentry = ERR_PTR(err);
++ return wh_dentry;
++}
++
++/* find and return first whiteout in parent directory, else ENOENT */
++struct dentry *find_first_whiteout(struct dentry *dentry)
++{
++ int bindex, bstart, bend;
++ struct dentry *parent, *lower_parent, *wh_dentry;
++
++ parent = dget_parent(dentry);
++
++ bstart = dbstart(parent);
++ bend = dbend(parent);
++ wh_dentry = ERR_PTR(-ENOENT);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_parent = unionfs_lower_dentry_idx(parent, bindex);
++ if (!lower_parent)
++ continue;
++ wh_dentry = lookup_whiteout(dentry->d_name.name, lower_parent);
++ if (IS_ERR(wh_dentry))
++ continue;
++ if (wh_dentry->d_inode)
++ break;
++ dput(wh_dentry);
++ wh_dentry = ERR_PTR(-ENOENT);
++ }
++
++ dput(parent);
++
++ return wh_dentry;
++}
++
++/*
++ * Unlink a whiteout dentry. Returns 0 or -errno. Caller must hold and
++ * release dentry reference.
++ */
++int unlink_whiteout(struct dentry *wh_dentry)
++{
++ int err;
++ struct dentry *lower_dir_dentry;
++
++ /* dget and lock parent dentry */
++ lower_dir_dentry = lock_parent_wh(wh_dentry);
++
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry);
++ lockdep_on();
++ unlock_dir(lower_dir_dentry);
++
++ /*
++ * Whiteouts are special files and should be deleted no matter what
++ * (as if they never existed), in order to allow this create
++ * operation to succeed. This is especially important in sticky
++ * directories: a whiteout may have been created by one user, but
++ * the newly created file may be created by another user.
++ * Therefore, in order to maintain Unix semantics, if the vfs_unlink
++ * above failed, then we have to try to directly unlink the
++ * whiteout. Note: in the ODF version of unionfs, whiteout are
++ * handled much more cleanly.
++ */
++ if (err == -EPERM) {
++ struct inode *inode = lower_dir_dentry->d_inode;
++ err = inode->i_op->unlink(inode, wh_dentry);
++ }
++ if (err)
++ printk(KERN_ERR "unionfs: could not unlink whiteout %s, "
++ "err = %d\n", wh_dentry->d_name.name, err);
++
++ return err;
++
++}
++
++/*
++ * Helper function when creating new objects (create, symlink, mknod, etc.).
++ * Checks to see if there's a whiteout in @lower_dentry's parent directory,
++ * whose name is taken from @dentry. Then tries to remove that whiteout, if
++ * found. If <dentry,bindex> is a branch marked readonly, return -EROFS.
++ * If it finds both a regular file and a whiteout, return -EIO (this should
++ * never happen).
++ *
++ * Return 0 if no whiteout was found. Return 1 if one was found and
++ * successfully removed. Therefore a value >= 0 tells the caller that
++ * @lower_dentry belongs to a good branch to create the new object in).
++ * Return -ERRNO if an error occurred during whiteout lookup or in trying to
++ * unlink the whiteout.
++ */
++int check_unlink_whiteout(struct dentry *dentry, struct dentry *lower_dentry,
++ int bindex)
++{
++ int err;
++ struct dentry *wh_dentry = NULL;
++ struct dentry *lower_dir_dentry = NULL;
++
++ /* look for whiteout dentry first */
++ lower_dir_dentry = dget_parent(lower_dentry);
++ wh_dentry = lookup_whiteout(dentry->d_name.name, lower_dir_dentry);
++ dput(lower_dir_dentry);
++ if (IS_ERR(wh_dentry)) {
++ err = PTR_ERR(wh_dentry);
++ goto out;
++ }
++
++ if (!wh_dentry->d_inode) { /* no whiteout exists*/
++ err = 0;
++ goto out_dput;
++ }
++
++ /* check if regular file and whiteout were both found */
++ if (unlikely(lower_dentry->d_inode)) {
++ err = -EIO;
++ printk(KERN_ERR "unionfs: found both whiteout and regular "
++ "file in directory %s (branch %d)\n",
++ lower_dir_dentry->d_name.name, bindex);
++ goto out_dput;
++ }
++
++ /* check if branch is writeable */
++ err = is_robranch_super(dentry->d_sb, bindex);
++ if (err)
++ goto out_dput;
++
++ /* .wh.foo has been found, so let's unlink it */
++ err = unlink_whiteout(wh_dentry);
++ if (!err)
++ err = 1; /* a whiteout was found and successfully removed */
++out_dput:
++ dput(wh_dentry);
++out:
++ return err;
++}
++
++/*
++ * Pass an unionfs dentry and an index. It will try to create a whiteout
++ * for the filename in dentry, and will try in branch 'index'. On error,
++ * it will proceed to a branch to the left.
++ */
++int create_whiteout(struct dentry *dentry, int start)
++{
++ int bstart, bend, bindex;
++ struct dentry *lower_dir_dentry;
++ struct dentry *lower_dentry;
++ struct dentry *lower_wh_dentry;
++ struct nameidata nd;
++ char *name = NULL;
++ int err = -EINVAL;
++
++ verify_locked(dentry);
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ /* create dentry's whiteout equivalent */
++ name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
++ if (unlikely(IS_ERR(name))) {
++ err = PTR_ERR(name);
++ goto out;
++ }
++
++ for (bindex = start; bindex >= 0; bindex--) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++
++ if (!lower_dentry) {
++ /*
++ * if lower dentry is not present, create the
++ * entire lower dentry directory structure and go
++ * ahead. Since we want to just create whiteout, we
++ * only want the parent dentry, and hence get rid of
++ * this dentry.
++ */
++ lower_dentry = create_parents(dentry->d_inode,
++ dentry,
++ dentry->d_name.name,
++ bindex);
++ if (!lower_dentry || IS_ERR(lower_dentry)) {
++ int ret = PTR_ERR(lower_dentry);
++ if (!IS_COPYUP_ERR(ret))
++ printk(KERN_ERR
++ "unionfs: create_parents for "
++ "whiteout failed: bindex=%d "
++ "err=%d\n", bindex, ret);
++ continue;
++ }
++ }
++
++ lower_wh_dentry =
++ lookup_lck_len(name, lower_dentry->d_parent,
++ dentry->d_name.len + UNIONFS_WHLEN);
++ if (IS_ERR(lower_wh_dentry))
++ continue;
++
++ /*
++ * The whiteout already exists. This used to be impossible,
++ * but now is possible because of opaqueness.
++ */
++ if (lower_wh_dentry->d_inode) {
++ dput(lower_wh_dentry);
++ err = 0;
++ goto out;
++ }
++
++ err = init_lower_nd(&nd, LOOKUP_CREATE);
++ if (unlikely(err < 0))
++ goto out;
++ lower_dir_dentry = lock_parent_wh(lower_wh_dentry);
++ err = is_robranch_super(dentry->d_sb, bindex);
++ if (!err)
++ err = vfs_create(lower_dir_dentry->d_inode,
++ lower_wh_dentry,
++ current_umask() & S_IRUGO,
++ &nd);
++ unlock_dir(lower_dir_dentry);
++ dput(lower_wh_dentry);
++ release_lower_nd(&nd, err);
++
++ if (!err || !IS_COPYUP_ERR(err))
++ break;
++ }
++
++ /* set dbopaque so that lookup will not proceed after this branch */
++ if (!err)
++ dbopaque(dentry) = bindex;
++
++out:
++ kfree(name);
++ return err;
++}
++
++/*
++ * Delete all of the whiteouts in a given directory for rmdir.
++ *
++ * lower directory inode should be locked
++ */
++static int do_delete_whiteouts(struct dentry *dentry, int bindex,
++ struct unionfs_dir_state *namelist)
++{
++ int err = 0;
++ struct dentry *lower_dir_dentry = NULL;
++ struct dentry *lower_dentry;
++ char *name = NULL, *p;
++ struct inode *lower_dir;
++ int i;
++ struct list_head *pos;
++ struct filldir_node *cursor;
++
++ /* Find out lower parent dentry */
++ lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
++ lower_dir = lower_dir_dentry->d_inode;
++ BUG_ON(!S_ISDIR(lower_dir->i_mode));
++
++ err = -ENOMEM;
++ name = __getname();
++ if (unlikely(!name))
++ goto out;
++ strcpy(name, UNIONFS_WHPFX);
++ p = name + UNIONFS_WHLEN;
++
++ err = 0;
++ for (i = 0; !err && i < namelist->size; i++) {
++ list_for_each(pos, &namelist->list[i]) {
++ cursor =
++ list_entry(pos, struct filldir_node,
++ file_list);
++ /* Only operate on whiteouts in this branch. */
++ if (cursor->bindex != bindex)
++ continue;
++ if (!cursor->whiteout)
++ continue;
++
++ strlcpy(p, cursor->name, PATH_MAX - UNIONFS_WHLEN);
++ lower_dentry =
++ lookup_lck_len(name, lower_dir_dentry,
++ cursor->namelen +
++ UNIONFS_WHLEN);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ break;
++ }
++ if (lower_dentry->d_inode)
++ err = vfs_unlink(lower_dir, lower_dentry);
++ dput(lower_dentry);
++ if (err)
++ break;
++ }
++ }
++
++ __putname(name);
++
++ /* After all of the removals, we should copy the attributes once. */
++ fsstack_copy_attr_times(dentry->d_inode, lower_dir_dentry->d_inode);
++
++out:
++ return err;
++}
++
++
++void __delete_whiteouts(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct deletewh_args *d = &args->deletewh;
++
++ args->err = do_delete_whiteouts(d->dentry, d->bindex, d->namelist);
++ complete(&args->comp);
++}
++
++/* delete whiteouts in a dir (for rmdir operation) using sioq if necessary */
++int delete_whiteouts(struct dentry *dentry, int bindex,
++ struct unionfs_dir_state *namelist)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *lower_dir_dentry;
++ struct inode *lower_dir;
++ struct sioq_args args;
++
++ sb = dentry->d_sb;
++
++ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
++ BUG_ON(bindex < dbstart(dentry));
++ BUG_ON(bindex > dbend(dentry));
++ err = is_robranch_super(sb, bindex);
++ if (err)
++ goto out;
++
++ lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
++ lower_dir = lower_dir_dentry->d_inode;
++ BUG_ON(!S_ISDIR(lower_dir->i_mode));
++
++ if (!inode_permission(lower_dir, MAY_WRITE | MAY_EXEC)) {
++ err = do_delete_whiteouts(dentry, bindex, namelist);
++ } else {
++ args.deletewh.namelist = namelist;
++ args.deletewh.dentry = dentry;
++ args.deletewh.bindex = bindex;
++ run_sioq(__delete_whiteouts, &args);
++ err = args.err;
++ }
++
++out:
++ return err;
++}
++
++/****************************************************************************
++ * Opaque directory helpers *
++ ****************************************************************************/
++
++/*
++ * is_opaque_dir: returns 0 if it is NOT an opaque dir, 1 if it is, and
++ * -errno if an error occurred trying to figure this out.
++ */
++int is_opaque_dir(struct dentry *dentry, int bindex)
++{
++ int err = 0;
++ struct dentry *lower_dentry;
++ struct dentry *wh_lower_dentry;
++ struct inode *lower_inode;
++ struct sioq_args args;
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ lower_inode = lower_dentry->d_inode;
++
++ BUG_ON(!S_ISDIR(lower_inode->i_mode));
++
++ mutex_lock(&lower_inode->i_mutex);
++
++ if (!inode_permission(lower_inode, MAY_EXEC)) {
++ wh_lower_dentry =
++ lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry,
++ sizeof(UNIONFS_DIR_OPAQUE) - 1);
++ } else {
++ args.is_opaque.dentry = lower_dentry;
++ run_sioq(__is_opaque_dir, &args);
++ wh_lower_dentry = args.ret;
++ }
++
++ mutex_unlock(&lower_inode->i_mutex);
++
++ if (IS_ERR(wh_lower_dentry)) {
++ err = PTR_ERR(wh_lower_dentry);
++ goto out;
++ }
++
++ /* This is an opaque dir iff wh_lower_dentry is positive */
++ err = !!wh_lower_dentry->d_inode;
++
++ dput(wh_lower_dentry);
++out:
++ return err;
++}
++
++void __is_opaque_dir(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++
++ args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->is_opaque.dentry,
++ sizeof(UNIONFS_DIR_OPAQUE) - 1);
++ complete(&args->comp);
++}
++
++int make_dir_opaque(struct dentry *dentry, int bindex)
++{
++ int err = 0;
++ struct dentry *lower_dentry, *diropq;
++ struct inode *lower_dir;
++ struct nameidata nd;
++ const struct cred *old_creds;
++ struct cred *new_creds;
++
++ /*
++ * Opaque directory whiteout markers are special files (like regular
++ * whiteouts), and should appear to the users as if they don't
++ * exist. They should be created/deleted regardless of directory
++ * search/create permissions, but only for the duration of this
++ * creation of the .wh.__dir_opaque: file. Note, this does not
++ * circumvent normal ->permission).
++ */
++ new_creds = prepare_creds();
++ if (unlikely(!new_creds)) {
++ err = -ENOMEM;
++ goto out_err;
++ }
++ cap_raise(new_creds->cap_effective, CAP_DAC_READ_SEARCH);
++ cap_raise(new_creds->cap_effective, CAP_DAC_OVERRIDE);
++ old_creds = override_creds(new_creds);
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ lower_dir = lower_dentry->d_inode;
++ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) ||
++ !S_ISDIR(lower_dir->i_mode));
++
++ mutex_lock(&lower_dir->i_mutex);
++ diropq = lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry,
++ sizeof(UNIONFS_DIR_OPAQUE) - 1);
++ if (IS_ERR(diropq)) {
++ err = PTR_ERR(diropq);
++ goto out;
++ }
++
++ err = init_lower_nd(&nd, LOOKUP_CREATE);
++ if (unlikely(err < 0))
++ goto out;
++ if (!diropq->d_inode)
++ err = vfs_create(lower_dir, diropq, S_IRUGO, &nd);
++ if (!err)
++ dbopaque(dentry) = bindex;
++ release_lower_nd(&nd, err);
++
++ dput(diropq);
++
++out:
++ mutex_unlock(&lower_dir->i_mutex);
++ revert_creds(old_creds);
++out_err:
++ return err;
++}
+diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c
+new file mode 100644
+index 0000000..9002e06
+--- /dev/null
++++ b/fs/unionfs/xattr.c
+@@ -0,0 +1,173 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "union.h"
++
++/* This is lifted from fs/xattr.c */
++void *unionfs_xattr_alloc(size_t size, size_t limit)
++{
++ void *ptr;
++
++ if (size > limit)
++ return ERR_PTR(-E2BIG);
++
++ if (!size) /* size request, no buffer is needed */
++ return NULL;
++
++ ptr = kmalloc(size, GFP_KERNEL);
++ if (unlikely(!ptr))
++ return ERR_PTR(-ENOMEM);
++ return ptr;
++}
++
++/*
++ * BKL held by caller.
++ * dentry->d_inode->i_mutex locked
++ */
++ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value,
++ size_t size)
++{
++ struct dentry *lower_dentry = NULL;
++ struct dentry *parent;
++ int err = -EOPNOTSUPP;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ err = vfs_getxattr(lower_dentry, (char *) name, value, size);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * BKL held by caller.
++ * dentry->d_inode->i_mutex locked
++ */
++int unionfs_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
++{
++ struct dentry *lower_dentry = NULL;
++ struct dentry *parent;
++ int err = -EOPNOTSUPP;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ err = vfs_setxattr(lower_dentry, (char *) name, (void *) value,
++ size, flags);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * BKL held by caller.
++ * dentry->d_inode->i_mutex locked
++ */
++int unionfs_removexattr(struct dentry *dentry, const char *name)
++{
++ struct dentry *lower_dentry = NULL;
++ struct dentry *parent;
++ int err = -EOPNOTSUPP;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ err = vfs_removexattr(lower_dentry, (char *) name);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * BKL held by caller.
++ * dentry->d_inode->i_mutex locked
++ */
++ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
++{
++ struct dentry *lower_dentry = NULL;
++ struct dentry *parent;
++ int err = -EOPNOTSUPP;
++ char *encoded_list = NULL;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ encoded_list = list;
++ err = vfs_listxattr(lower_dentry, encoded_list, size);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
+diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
+index da317c7..64f1ced 100644
+--- a/include/linux/fs_stack.h
++++ b/include/linux/fs_stack.h
+@@ -1,7 +1,19 @@
++/*
++ * Copyright (c) 2006-2009 Erez Zadok
++ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2006-2009 Stony Brook University
++ * Copyright (c) 2006-2009 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
+ #ifndef _LINUX_FS_STACK_H
+ #define _LINUX_FS_STACK_H
+
+-/* This file defines generic functions used primarily by stackable
++/*
++ * This file defines generic functions used primarily by stackable
+ * filesystems; none of these functions require i_mutex to be held.
+ */
+
+diff --git a/include/linux/magic.h b/include/linux/magic.h
+index eb9800f..9770154 100644
+--- a/include/linux/magic.h
++++ b/include/linux/magic.h
+@@ -47,6 +47,8 @@
+ #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
+ #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs"
+
++#define UNIONFS_SUPER_MAGIC 0xf15f083d
++
+ #define SMB_SUPER_MAGIC 0x517B
+ #define USBDEVICE_SUPER_MAGIC 0x9fa2
+ #define CGROUP_SUPER_MAGIC 0x27e0eb
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index 05b441d..dca6f9a 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -72,6 +72,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
+
+ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+ int (*open)(struct inode *, struct file *));
++extern void release_open_intent(struct nameidata *);
+
+ extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 997c3b4..54f5501 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -81,6 +81,11 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ struct splice_pipe_desc *);
+ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+ splice_direct_actor *);
++extern long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++extern long vfs_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
+
+ /*
+ * for dynamic pipe sizing
+diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
+new file mode 100644
+index 0000000..c84d97e
+--- /dev/null
++++ b/include/linux/union_fs.h
+@@ -0,0 +1,22 @@
++/*
++ * Copyright (c) 2003-2009 Erez Zadok
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2003-2009 Stony Brook University
++ * Copyright (c) 2003-2009 The Research Foundation of SUNY
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _LINUX_UNION_FS_H
++#define _LINUX_UNION_FS_H
++
++/*
++ * DEFINITIONS FOR USER AND KERNEL CODE:
++ */
++# define UNIONFS_IOCTL_INCGEN _IOR(0x15, 11, int)
++# define UNIONFS_IOCTL_QUERYFILE _IOR(0x15, 15, int)
++
++#endif /* _LINUX_UNIONFS_H */
++
+diff --git a/security/security.c b/security/security.c
+index c53949f..eb71394 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -528,6 +528,7 @@ int security_inode_permission(struct inode *inode, int mask)
+ return 0;
+ return security_ops->inode_permission(inode, mask);
+ }
++EXPORT_SYMBOL(security_inode_permission);
+
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+ {
diff --git a/main/linux-vserver/APKBUILD b/main/linux-vserver/APKBUILD
new file mode 100644
index 0000000000..b59cc857a0
--- /dev/null
+++ b/main/linux-vserver/APKBUILD
@@ -0,0 +1,137 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+_flavor=vserver
+pkgname=linux-${_flavor}
+pkgver=2.6.38.7
+
+_vsver=vs2.3.0.37-rc17
+if [ "${pkgver##*.*.*.*}" = "$pkgver" ]; then
+ _kernver=$pkgver
+else
+ _kernver=${pkgver%.*}
+fi
+
+pkgrel=1
+pkgdesc="Linux kernel with vserver"
+url="http://linux-vserver.org/"
+depends="mkinitfs linux-firmware"
+makedepends="perl installkernel"
+options="!strip"
+_config=${config:-kernelconfig.${CARCH}}
+install=
+source="http://www.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
+ http://www.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
+ http://vserver.13thfloor.at/Experimental/patch-$pkgver-$_vsver.diff
+ kernelconfig.x86
+ kernelconfig.x86_64
+ "
+subpackages="$pkgname-dev"
+arch="all"
+license="GPL-2"
+
+_abi_release=${pkgver}-${_vsver}
+
+prepare() {
+ cd "$srcdir"/linux-$_kernver
+ if [ "$_kernver" != "$pkgver" ]; then
+ bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 -N || return 1
+ fi
+
+ # first apply patches in specified order
+ for i in $source; do
+ i=${i##*/}
+ case $i in
+ *.patch|*.diff)
+ msg "Applying $i..."
+ patch -s -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+
+ mkdir -p "$srcdir"/build
+ cp "$srcdir"/$_config "$srcdir"/build/.config || return 1
+ make -C "$srcdir"/linux-$_kernver O="$srcdir"/build HOSTCC="${CC:-gcc}" \
+ silentoldconfig
+}
+
+# this is so we can do: 'abuild menuconfig' to reconfigure kernel
+menuconfig() {
+ cd "$srcdir"/build
+ make menuconfig
+ cp .config "$startdir"/$_config || return 1
+}
+
+build() {
+ cd "$srcdir"/build
+ make CC="${CC:-gcc}" \
+ KBUILD_BUILD_VERSION="$((pkgrel + 1 ))-Alpine" \
+ || return 1
+}
+
+package() {
+ cd "$srcdir"/build
+ mkdir -p "$pkgdir"/boot "$pkgdir"/lib/modules
+ make -j1 modules_install install \
+ INSTALL_MOD_PATH="$pkgdir" \
+ INSTALL_PATH="$pkgdir"/boot \
+ || return 1
+
+ rm -rf "$pkgdir"/lib/modules/*/build \
+ "$pkgdir"/lib/modules/*/source
+ rm -rf "$pkgdir"/lib/firmware
+
+ install -D include/config/kernel.release \
+ "$pkgdir"/usr/share/kernel/$_flavor/kernel.release
+}
+
+dev() {
+ # copy the only the parts that we really need for build 3rd party
+ # kernel modules and install those as /usr/src/linux-headers,
+ # simlar to what ubuntu does
+ #
+ # this way you dont need to install the 300-400 kernel sources to
+ # build a tiny kernel module
+ #
+ pkgdesc="Headers and script for third party modules for grsec kernel"
+ local dir="$subpkgdir"/usr/src/linux-headers-${_abi_release}
+
+ # first we import config, run prepare to set up for building
+ # external modules, and create the scripts
+ mkdir -p "$dir"
+ cp "$srcdir"/$_config "$dir"/.config
+ make -j1 -C "$srcdir"/linux-$_kernver O="$dir" HOSTCC="${CC:-gcc}" \
+ silentoldconfig prepare scripts
+
+ # remove the stuff that poits to real sources. we want 3rd party
+ # modules to believe this is the soruces
+ rm "$dir"/Makefile "$dir"/source
+
+ # copy the needed stuff from real sources
+ #
+ # this is taken from ubuntu kernel build script
+ # http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-jaunty.git;a=blob;f=debian/rules.d/3-binary-indep.mk;hb=HEAD
+ cd "$srcdir"/linux-$_kernver
+ find . -path './include/*' -prune -o -path './scripts/*' -prune \
+ -o -type f \( -name 'Makefile*' -o -name 'Kconfig*' \
+ -o -name 'Kbuild*' -o -name '*.sh' -o -name '*.pl' \
+ -o -name '*.lds' \) | cpio -pdm "$dir"
+ cp -a drivers/media/dvb/dvb-core/*.h "$dir"/drivers/media/dvb/dvb-core
+ cp -a drivers/media/video/*.h "$dir"/drivers/media/video
+ cp -a drivers/media/dvb/frontends/*.h "$dir"/drivers/media/dvb/frontends
+ cp -a scripts include "$dir"
+ find $(find arch -name include -type d -print) -type f \
+ | cpio -pdm "$dir"
+
+ install -Dm644 "$srcdir"/build/Module.symvers \
+ "$dir"/Module.symvers
+
+ mkdir -p "$subpkgdir"/lib/modules/${_abi_release}
+ ln -sf /usr/src/linux-headers-${_abi_release} \
+ "$subpkgdir"/lib/modules/${_abi_release}/build
+}
+
+md5sums="7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2
+2639b4b98a2dcfc8b7f091543f289205 patch-2.6.38.7.bz2
+b9581dbf023e47a9f776c8eec8927418 patch-2.6.38.7-vs2.3.0.37-rc17.diff
+bacde2f6f0ac4bac379d4bdfda09322a kernelconfig.x86
+f409d26e7fe848308b7ddaf210bfaeb8 kernelconfig.x86_64"
diff --git a/main/linux-vserver/kernelconfig.x86 b/main/linux-vserver/kernelconfig.x86
new file mode 100644
index 0000000000..4d16762c62
--- /dev/null
+++ b/main/linux-vserver/kernelconfig.x86
@@ -0,0 +1,5047 @@
+#
+# Automatically generated make config: don't edit
+# Linux/i386 2.6.38.4-vs2.3.0.37-rc15 Kernel Configuration
+# Sat Apr 30 14:37:00 2011
+#
+# CONFIG_64BIT is not set
+CONFIG_X86_32=y
+# CONFIG_X86_64 is not set
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf32-i386"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+# CONFIG_NEED_DMA_MAP_STATE is not set
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME_VSYSCALL is not set
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ZONE_DMA32 is not set
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+# CONFIG_AUDIT_ARCH is not set
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_X86_32_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_32_LAZY_GS=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
+CONFIG_KTIME_SCALAR=y
+CONFIG_ARCH_CPU_PROBE_RELEASE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+# CONFIG_AUTO_IRQ_AFFINITY is not set
+# CONFIG_IRQ_PER_CPU is not set
+# CONFIG_HARDIRQS_SW_RESEND is not set
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+CONFIG_RCU_FAST_NO_HZ=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=m
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+# CONFIG_CPUSETS is not set
+CONFIG_CGROUP_CPUACCT=y
+# CONFIG_RESOURCE_COUNTERS is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+# CONFIG_JUMP_LABEL is not set
+CONFIG_OPTPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_KRETPROBES=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_DEV_THROTTLING is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_PADATA=y
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_X86_MPPARSE=y
+# CONFIG_X86_BIGSMP is not set
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_MRST is not set
+# CONFIG_X86_RDC321X is not set
+# CONFIG_X86_32_NON_STANDARD is not set
+# CONFIG_X86_32_IRIS is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_PARAVIRT_GUEST=y
+# CONFIG_XEN_PRIVILEGED_GUEST is not set
+CONFIG_KVM_CLOCK=y
+CONFIG_KVM_GUEST=y
+# CONFIG_LGUEST_GUEST is not set
+CONFIG_PARAVIRT=y
+# CONFIG_PARAVIRT_SPINLOCKS is not set
+CONFIG_PARAVIRT_CLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_MEMTEST is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+# CONFIG_X86_GENERIC is not set
+CONFIG_X86_CPU=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=5
+CONFIG_X86_CMPXCHG=y
+CONFIG_CMPXCHG_LOCAL=y
+CONFIG_X86_L1_CACHE_SHIFT=5
+CONFIG_X86_XADD=y
+# CONFIG_X86_PPRO_FENCE is not set
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=5
+CONFIG_X86_DEBUGCTLMSR=y
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_CYRIX_32=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_TRANSMETA_32=y
+CONFIG_CPU_SUP_UMC_32=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_IOMMU_API is not set
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+# CONFIG_X86_MCE is not set
+CONFIG_VM86=y
+# CONFIG_TOSHIBA is not set
+CONFIG_I8K=m
+# CONFIG_X86_REBOOTFIXUPS is not set
+CONFIG_MICROCODE=m
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_2G_OPT is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
+CONFIG_NEED_NODE_MEMMAP_SIZE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ILLEGAL_POINTER_VALUE=0
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_HAVE_MEMBLOCK=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
+# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
+# CONFIG_HIGHPTE is not set
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW=64
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+# CONFIG_EFI is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_300=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=300
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_COMPAT_VDSO is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM_OPS=y
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+# CONFIG_ACPI_POWER_METER is not set
+CONFIG_ACPI_EC_DEBUGFS=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_IPMI=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=m
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+CONFIG_ACPI_HED=m
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=m
+CONFIG_ACPI_APEI_EINJ=m
+CONFIG_ACPI_APEI_ERST_DEBUG=y
+# CONFIG_SFI is not set
+# CONFIG_APM is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_PCC_CPUFREQ=m
+CONFIG_X86_ACPI_CPUFREQ=m
+# CONFIG_X86_POWERNOW_K6 is not set
+# CONFIG_X86_POWERNOW_K7 is not set
+CONFIG_X86_POWERNOW_K8=m
+# CONFIG_X86_GX_SUSPMOD is not set
+CONFIG_X86_SPEEDSTEP_CENTRINO=m
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
+# CONFIG_X86_SPEEDSTEP_ICH is not set
+# CONFIG_X86_SPEEDSTEP_SMI is not set
+CONFIG_X86_P4_CLOCKMOD=m
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+# CONFIG_X86_LONGRUN is not set
+# CONFIG_X86_LONGHAUL is not set
+# CONFIG_X86_E_POWERSAVER is not set
+
+#
+# shared options
+#
+CONFIG_X86_SPEEDSTEP_LIB=m
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_INTEL_IDLE=y
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_CNB20LE_QUIRK=y
+# CONFIG_DMAR is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_PCIEAER is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_STUB=m
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+CONFIG_PCI_IOAPIC=y
+CONFIG_ISA_DMA_API=y
+# CONFIG_ISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+# CONFIG_OLPC is not set
+# CONFIG_OLPC_OPENFIRMWARE is not set
+CONFIG_AMD_NB=y
+CONFIG_PCCARD=m
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+CONFIG_HOTPLUG_PCI=m
+CONFIG_HOTPLUG_PCI_FAKE=m
+# CONFIG_HOTPLUG_PCI_COMPAQ is not set
+# CONFIG_HOTPLUG_PCI_IBM is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_SHPC=m
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_HAVE_ATOMIC_IOMAP=y
+CONFIG_HAVE_TEXT_POKE_SMP=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+# CONFIG_IP_PIMSM_V1 is not set
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETLABEL=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_NFCT=y
+CONFIG_IP_VS_PE_SIP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_SCTP=m
+CONFIG_NET_SCTPPROBE=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+CONFIG_RDS=m
+# CONFIG_RDS_RDMA is not set
+# CONFIG_RDS_TCP is not set
+# CONFIG_RDS_DEBUG is not set
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_PHONET=m
+# CONFIG_PHONET_PIPECTRLR is not set
+CONFIG_IEEE802154=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_CLS_CGROUP is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+CONFIG_RPS=y
+CONFIG_XPS=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_DEV=m
+# CONFIG_CAN_CALC_BITTIMING is not set
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_JANZ_ICAN3=m
+# CONFIG_PCH_CAN is not set
+CONFIG_CAN_SJA1000=m
+CONFIG_CAN_SJA1000_PLATFORM=m
+CONFIG_CAN_EMS_PCI=m
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PLX_PCI=m
+
+#
+# CAN USB interfaces
+#
+# CONFIG_CAN_EMS_USB is not set
+# CONFIG_CAN_ESD_USB2 is not set
+CONFIG_CAN_SOFTING=m
+CONFIG_CAN_SOFTING_CS=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+# CONFIG_TOSHIBA_FIR is not set
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_RXKAD=m
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+# CONFIG_RFKILL_INPUT is not set
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NET_9P_RDMA=m
+# CONFIG_NET_9P_DEBUG is not set
+CONFIG_CAIF=m
+# CONFIG_CAIF_DEBUG is not set
+CONFIG_CAIF_NETDEV=m
+CONFIG_CEPH_LIB=m
+# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=m
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_AR7_PARTS=m
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_HAVE_MTD_OTP=y
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+CONFIG_SSFDC=m
+CONFIG_SM_FTL=m
+CONFIG_MTD_OOPS=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_AMD76XROM=m
+CONFIG_MTD_ICHXROM=m
+CONFIG_MTD_ESB2ROM=m
+CONFIG_MTD_CK804XROM=m
+CONFIG_MTD_SCB2_FLASH=m
+CONFIG_MTD_NETtel=m
+CONFIG_MTD_L440GX=m
+CONFIG_MTD_PCI=m
+CONFIG_MTD_PCMCIA=m
+# CONFIG_MTD_PCMCIA_ANONYMOUS is not set
+# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_INTEL_VR_NOR=m
+CONFIG_MTD_PLATRAM=m
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+CONFIG_MTD_PMC551_BUGFIX=y
+# CONFIG_MTD_PMC551_DEBUG is not set
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DATAFLASH_OTP is not set
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_MTD_SST25L is not set
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+# CONFIG_MTD_DOCPROBE_HIGH is not set
+# CONFIG_MTD_DOCPROBE_55AA is not set
+CONFIG_MTD_NAND_ECC=m
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_SM_COMMON=m
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_DENALI=m
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_RICOH=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CAFE=m
+# CONFIG_MTD_NAND_CS553X is not set
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_ALAUDA=m
+CONFIG_MTD_ONENAND=m
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OTP=y
+CONFIG_MTD_ONENAND_2X_PROGRAM=y
+CONFIG_MTD_ONENAND_SIM=m
+
+#
+# LPDDR flash memory drivers
+#
+CONFIG_MTD_LPDDR=m
+CONFIG_MTD_QINFO_PROBE=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_AX88796=m
+# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=m
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_VROOT=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_AD525X_DPOT_SPI=m
+CONFIG_IBM_ASM=m
+CONFIG_PHANTOM=m
+CONFIG_SGI_IOC4=m
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
+CONFIG_ICS932S401=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_CS5535_MFGPT=m
+CONFIG_CS5535_MFGPT_DEFAULT_IRQ=7
+CONFIG_CS5535_CLOCK_EVENT_SRC=m
+CONFIG_HP_ILO=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1780=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_TI_DAC7512=m
+CONFIG_VMWARE_BALLOON=m
+CONFIG_BMP085=m
+CONFIG_PCH_PHUB=m
+CONFIG_C2PORT=m
+CONFIG_C2PORT_DURAMAR_2150=m
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_AT25=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93CX6=m
+CONFIG_CB710_CORE=m
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
+CONFIG_IWMC3200TOP=m
+# CONFIG_IWMC3200TOP_DEBUG is not set
+# CONFIG_IWMC3200TOP_DEBUGFS is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_FC_TGT_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_HOST_SMP=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+# CONFIG_BE2ISCSI is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_HPSA=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_3W_SAS=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
+CONFIG_SCSI_MVSAS=m
+CONFIG_SCSI_MVSAS_DEBUG=y
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_ARCMSR=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_MPT2SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
+# CONFIG_SCSI_MPT2SAS_LOGGING is not set
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_FLASHPOINT is not set
+CONFIG_VMWARE_PVSCSI=m
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+CONFIG_FCOE=m
+CONFIG_FCOE_FNIC=m
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_EATA=m
+# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set
+# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+CONFIG_SCSI_IPR_TRACE=y
+# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_NSP32 is not set
+CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_PMCRAID is not set
+CONFIG_SCSI_PM8001=m
+CONFIG_SCSI_SRP=m
+# CONFIG_SCSI_BFA_FC is not set
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_SCSI_OSD_DPRINT_SENSE=1
+# CONFIG_SCSI_OSD_DEBUG is not set
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_SATA_INIC162X=m
+CONFIG_SATA_ACARD_AHCI=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SX4=m
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+CONFIG_ATA_PIIX=m
+CONFIG_SATA_MV=m
+CONFIG_SATA_NV=m
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+
+#
+# PATA SFF controllers with BMDMA
+#
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+CONFIG_PATA_ATP867X=m
+CONFIG_PATA_CMD64X=m
+CONFIG_PATA_CS5520=m
+CONFIG_PATA_CS5530=m
+# CONFIG_PATA_CS5535 is not set
+CONFIG_PATA_CS5536=m
+CONFIG_PATA_CYPRESS=m
+CONFIG_PATA_EFAR=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+CONFIG_PATA_HPT3X2N=m
+CONFIG_PATA_HPT3X3=m
+CONFIG_PATA_HPT3X3_DMA=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87415=m
+CONFIG_PATA_OLDPIIX=m
+CONFIG_PATA_OPTIDMA=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_PDC_OLD=m
+CONFIG_PATA_RADISYS=m
+CONFIG_PATA_RDC=m
+CONFIG_PATA_SC1200=m
+CONFIG_PATA_SCH=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_TOSHIBA=m
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+
+#
+# PIO-only SFF controllers
+#
+CONFIG_PATA_CMD640_PCI=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_OPTI=m
+CONFIG_PATA_PCMCIA=m
+CONFIG_PATA_PLATFORM=m
+CONFIG_PATA_RZ1000=m
+
+#
+# Generic fallback / legacy drivers
+#
+CONFIG_PATA_ACPI=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_LEGACY=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_AUTODETECT is not set
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MULTICORE_RAID456 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_OHCI_DEBUG=y
+CONFIG_FIREWIRE_SBP2=m
+CONFIG_FIREWIRE_NET=m
+CONFIG_FIREWIRE_NOSY=m
+CONFIG_I2O=m
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+CONFIG_ARCNET=m
+CONFIG_ARCNET_1201=m
+CONFIG_ARCNET_1051=m
+CONFIG_ARCNET_RAW=m
+CONFIG_ARCNET_CAP=m
+CONFIG_ARCNET_COM90xx=m
+CONFIG_ARCNET_COM90xxIO=m
+CONFIG_ARCNET_RIM_I=m
+CONFIG_ARCNET_COM20020=m
+CONFIG_ARCNET_COM20020_PCI=m
+CONFIG_MII=m
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_BCM63XX_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MICREL_PHY=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_MDIO_GPIO=m
+CONFIG_NET_ETHERNET=y
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ETHOC=m
+CONFIG_DNET=m
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_DE2104X_DSL=0
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_HP100=m
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_KSZ884X_PCI=m
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SMSC9420=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_KS8842=m
+CONFIG_KS8851=m
+CONFIG_KS8851_MLL=m
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_ATL2=m
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_IP1000=m
+CONFIG_IGB=m
+CONFIG_IGB_DCA=y
+CONFIG_IGBVF=m
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_CNIC=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_ATL1C=m
+CONFIG_JME=m
+CONFIG_STMMAC_ETH=m
+# CONFIG_STMMAC_DA is not set
+# CONFIG_STMMAC_DUAL_MAC is not set
+CONFIG_PCH_GBE=m
+CONFIG_NETDEV_10000=y
+CONFIG_MDIO=m
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3_DEPENDS=y
+CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4_DEPENDS=y
+CONFIG_CHELSIO_T4=m
+CONFIG_CHELSIO_T4VF_DEPENDS=y
+CONFIG_CHELSIO_T4VF=m
+CONFIG_ENIC=m
+CONFIG_IXGBE=m
+CONFIG_IXGBE_DCA=y
+# CONFIG_IXGBEVF is not set
+CONFIG_IXGB=m
+CONFIG_S2IO=m
+CONFIG_VXGE=m
+# CONFIG_VXGE_DEBUG_TRACE_ALL is not set
+CONFIG_MYRI10GE=m
+CONFIG_MYRI10GE_DCA=y
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_QLCNIC=m
+CONFIG_QLGE=m
+CONFIG_BNA=m
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_BE2NET=m
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AIRO=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_AT76C50X_USB=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+CONFIG_ADM8211=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_MWL8K=m
+CONFIG_ATH_COMMON=m
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH5K_PCI=y
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K=m
+# CONFIG_ATH9K_DEBUGFS is not set
+CONFIG_ATH9K_RATE_CONTROL=y
+CONFIG_ATH9K_HTC=m
+# CONFIG_ATH9K_HTC_DEBUGFS is not set
+CONFIG_AR9170_USB=m
+CONFIG_AR9170_LEDS=y
+CONFIG_CARL9170=m
+CONFIG_CARL9170_LEDS=y
+CONFIG_CARL9170_WPC=y
+CONFIG_B43=m
+CONFIG_B43_PCI_AUTOSELECT=y
+CONFIG_B43_PCICORE_AUTOSELECT=y
+CONFIG_B43_PCMCIA=y
+CONFIG_B43_SDIO=y
+CONFIG_B43_PIO=y
+CONFIG_B43_PHY_N=y
+CONFIG_B43_PHY_LP=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_PCI_AUTOSELECT=y
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_HWRNG=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
+CONFIG_IWLWIFI=m
+
+#
+# Debugging Options
+#
+# CONFIG_IWLWIFI_DEBUG is not set
+CONFIG_IWLAGN=m
+CONFIG_IWL4965=y
+CONFIG_IWL5000=y
+CONFIG_IWL3945=m
+CONFIG_IWM=m
+# CONFIG_IWM_DEBUG is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_CS=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_LIBERTAS_MESH=y
+CONFIG_HERMES=m
+# CONFIG_HERMES_PRISM is not set
+CONFIG_HERMES_CACHE_FW_ON_INIT=y
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ORINOCO_USB=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_P54_PCI=m
+CONFIG_P54_SPI=m
+# CONFIG_P54_SPI_DEFAULT_EEPROM is not set
+CONFIG_P54_LEDS=y
+CONFIG_RT2X00=m
+CONFIG_RT2400PCI=m
+CONFIG_RT2500PCI=m
+CONFIG_RT61PCI=m
+CONFIG_RT2800PCI=m
+CONFIG_RT2800PCI_RT33XX=y
+# CONFIG_RT2800PCI_RT35XX is not set
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT33XX=y
+# CONFIG_RT2800USB_RT35XX is not set
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RT2800_LIB=m
+CONFIG_RT2X00_LIB_PCI=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_HT=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_RTL8192CE=m
+CONFIG_RTLWIFI=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SPI=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_HT=y
+CONFIG_WL12XX_SPI=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_WL12XX_SDIO_TEST=m
+CONFIG_WL12XX_PLATFORM_DATA=y
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+CONFIG_WIMAX_I2400M=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_WIMAX_I2400M_SDIO=m
+CONFIG_WIMAX_IWMC3200_SDIO=y
+CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_CDC_PHONET=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_ARCNET_COM20020_CS=m
+CONFIG_WAN=y
+CONFIG_LANMEDIA=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=m
+CONFIG_HDLC_RAW_ETH=m
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_X25=m
+CONFIG_PCI200SYN=m
+CONFIG_WANXL=m
+# CONFIG_WANXL_BUILD_FIRMWARE is not set
+CONFIG_PC300TOO=m
+CONFIG_FARSYNC=m
+CONFIG_DSCC4=m
+CONFIG_DSCC4_PCISYNC=y
+CONFIG_DSCC4_PCI_RST=y
+CONFIG_DLCI=m
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=m
+CONFIG_CYCLADES_SYNC=m
+CONFIG_CYCLOMX_X25=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+CONFIG_SBNI=m
+CONFIG_SBNI_MULTILINE=y
+CONFIG_ATM_DRIVERS=y
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_USE_TASKLET=y
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_ATM_SOLOS=m
+CONFIG_IEEE802154_DRIVERS=m
+CONFIG_IEEE802154_FAKEHARD=m
+
+#
+# CAIF transport drivers
+#
+CONFIG_CAIF_TTY=m
+CONFIG_CAIF_SPI_SLAVE=m
+# CONFIG_CAIF_SPI_SYNC is not set
+CONFIG_FDDI=y
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_SKFP=m
+CONFIG_HIPPI=y
+CONFIG_ROADRUNNER=m
+# CONFIG_ROADRUNNER_LARGE_RINGS is not set
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOATM=m
+CONFIG_PPPOL2TP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+CONFIG_VMXNET3=m
+CONFIG_ISDN=y
+# CONFIG_ISDN_I4L is not set
+CONFIG_ISDN_CAPI=m
+# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set
+# CONFIG_CAPI_TRACE is not set
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_CAPI=y
+# CONFIG_GIGASET_DUMMYLL is not set
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+CONFIG_GIGASET_M101=m
+# CONFIG_GIGASET_DEBUG is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+CONFIG_MISDN=m
+CONFIG_MISDN_DSP=m
+CONFIG_MISDN_L1OIP=m
+
+#
+# mISDN hardware drivers
+#
+CONFIG_MISDN_HFCPCI=m
+CONFIG_MISDN_HFCMULTI=m
+CONFIG_MISDN_HFCUSB=m
+CONFIG_MISDN_AVMFRITZ=m
+# CONFIG_MISDN_SPEEDFAX is not set
+# CONFIG_MISDN_INFINEON is not set
+# CONFIG_MISDN_W6692 is not set
+# CONFIG_MISDN_NETJET is not set
+CONFIG_MISDN_IPAC=m
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_POLLDEV=m
+CONFIG_INPUT_SPARSEKMAP=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT2160 is not set
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_GPIO_POLLED=m
+CONFIG_KEYBOARD_TCA6416=m
+CONFIG_KEYBOARD_MATRIX=m
+CONFIG_KEYBOARD_LM8323=m
+# CONFIG_KEYBOARD_MAX7359 is not set
+CONFIG_KEYBOARD_MCS=m
+CONFIG_KEYBOARD_NEWTON=m
+# CONFIG_KEYBOARD_OPENCORES is not set
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_GPIO=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_AD7877=m
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_AD7879_SPI=m
+CONFIG_TOUCHSCREEN_BU21013=m
+CONFIG_TOUCHSCREEN_CY8CTMG110=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_QT602240=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_UCB1400=m
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+# CONFIG_TOUCHSCREEN_MC13783 is not set
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
+CONFIG_TOUCHSCREEN_USB_NEXIO=y
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_ST1232=m
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_AD714X_I2C=m
+CONFIG_INPUT_AD714X_SPI=m
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_APANEL=m
+# CONFIG_INPUT_WISTRON_BTNS is not set
+CONFIG_INPUT_ATLAS_BTNS=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_PCF50633_PMU=m
+CONFIG_INPUT_PCF8574=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_ADXL34X_I2C=m
+CONFIG_INPUT_ADXL34X_SPI=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_INPUT_CMA3000_I2C=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_ALTERA_PS2=m
+CONFIG_SERIO_PS2MULT=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_COMPUTONE=m
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+CONFIG_ISI=m
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_N_GSM is not set
+CONFIG_RISCOM8=m
+CONFIG_SPECIALIX=m
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MAX3100=m
+CONFIG_SERIAL_MAX3107=m
+CONFIG_SERIAL_MRST_MAX3110=m
+CONFIG_SERIAL_MFD_HSU=m
+CONFIG_SERIAL_UARTLITE=m
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_SERIAL_TIMBERDALE=m
+CONFIG_SERIAL_ALTERA_JTAGUART=m
+CONFIG_SERIAL_ALTERA_UART=m
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
+CONFIG_SERIAL_IFX6X60=m
+CONFIG_SERIAL_PCH_UART=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_HVC_DRIVER=y
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=m
+CONFIG_R3964=m
+CONFIG_APPLICOM=m
+# CONFIG_SONYPI is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+CONFIG_MWAVE=m
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+CONFIG_TELCLOCK=m
+CONFIG_DEVPORT=y
+CONFIG_RAMOOPS=m
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_MUX=m
+
+#
+# Multiplexer I2C Chip support
+#
+CONFIG_I2C_MUX_GPIO=m
+CONFIG_I2C_MUX_PCA9541=m
+CONFIG_I2C_MUX_PCA954x=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_SMBUS=m
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+
+#
+# ACPI drivers
+#
+CONFIG_I2C_SCMI=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=m
+CONFIG_I2C_INTEL_MID=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_XILINX=m
+CONFIG_I2C_EG20T=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_STUB=m
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+CONFIG_SPI_BUTTERFLY=m
+CONFIG_SPI_GPIO=m
+CONFIG_SPI_LM70_LLP=m
+CONFIG_SPI_PXA2XX=m
+CONFIG_SPI_PXA2XX_PCI=y
+CONFIG_SPI_TOPCLIFF_PCH=m
+# CONFIG_SPI_XILINX is not set
+CONFIG_SPI_DESIGNWARE=m
+CONFIG_SPI_DW_PCI=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+CONFIG_GPIO_MAX730X=m
+
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_BASIC_MMIO=m
+CONFIG_GPIO_IT8761E=m
+CONFIG_GPIO_SCH=m
+CONFIG_GPIO_VX855=m
+
+#
+# I2C GPIO expanders:
+#
+CONFIG_GPIO_MAX7300=m
+CONFIG_GPIO_MAX732X=m
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_ADP5588=m
+
+#
+# PCI GPIO expanders:
+#
+CONFIG_GPIO_CS5535=m
+# CONFIG_GPIO_LANGWELL is not set
+CONFIG_GPIO_PCH=m
+CONFIG_GPIO_ML_IOH=m
+CONFIG_GPIO_TIMBERDALE=y
+CONFIG_GPIO_RDC321X=m
+
+#
+# SPI GPIO expanders:
+#
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MCP23S08=m
+# CONFIG_GPIO_MC33880 is not set
+CONFIG_GPIO_74X164=m
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_GPIO_UCB1400 is not set
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_GPIO_JANZ_TTL=m
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_GPIO=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PDA_POWER=m
+CONFIG_TEST_POWER=m
+CONFIG_BATTERY_DS2760=m
+CONFIG_BATTERY_DS2782=m
+CONFIG_BATTERY_BQ20Z75=m
+CONFIG_BATTERY_BQ27x00=m
+CONFIG_BATTERY_MAX17040=m
+CONFIG_BATTERY_MAX17042=m
+CONFIG_CHARGER_PCF50633=m
+CONFIG_CHARGER_ISP1704=m
+CONFIG_CHARGER_GPIO=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7411=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7475=m
+CONFIG_SENSORS_ASC7621=m
+CONFIG_SENSORS_K8TEMP=m
+CONFIG_SENSORS_K10TEMP=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS620=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_G760A=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_GPIO_FAN=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_PKGTEMP=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_JC42=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LTC4215=m
+CONFIG_SENSORS_LTC4245=m
+CONFIG_SENSORS_LTC4261=m
+CONFIG_SENSORS_LM95241=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SHT21=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMM665=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
+CONFIG_SENSORS_EMC2103=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_ADS7871=m
+CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=m
+CONFIG_SENSORS_TMP401=m
+CONFIG_SENSORS_TMP421=m
+CONFIG_SENSORS_VIA_CPUTEMP=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83795=m
+CONFIG_SENSORS_W83795_FANCTRL=y
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_LIS3_I2C=m
+CONFIG_SENSORS_APPLESMC=m
+# CONFIG_SENSORS_MC13783_ADC is not set
+
+#
+# ACPI drivers
+#
+CONFIG_SENSORS_ATK0110=m
+CONFIG_SENSORS_LIS3LV02D=m
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_F71808E_WDT=m
+CONFIG_SP5100_TCO=m
+CONFIG_GEODE_WDT=m
+CONFIG_SC520_WDT=m
+# CONFIG_SBC_FITPC2_WATCHDOG is not set
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_WAFER_WDT=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_ITCO_WDT=m
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_IT8712F_WDT=m
+CONFIG_IT87_WDT=m
+# CONFIG_HP_WATCHDOG is not set
+CONFIG_SC1200_WDT=m
+CONFIG_PC87413_WDT=m
+CONFIG_NV_TCO=m
+CONFIG_60XX_WDT=m
+CONFIG_SBC8360_WDT=m
+# CONFIG_SBC7240_WDT is not set
+CONFIG_CPU5_WDT=m
+CONFIG_SMSC_SCH311X_WDT=m
+CONFIG_SMSC37B787_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83697HF_WDT=m
+CONFIG_W83697UG_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+CONFIG_SSB_SDIOHOST=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_MFD_SUPPORT=y
+CONFIG_MFD_CORE=m
+CONFIG_MFD_SM501=m
+# CONFIG_MFD_SM501_GPIO is not set
+CONFIG_HTC_PASIC3=m
+CONFIG_UCB1400_CORE=m
+CONFIG_TPS65010=m
+CONFIG_TPS6507X=m
+# CONFIG_MFD_TMIO is not set
+CONFIG_MFD_WM8400=m
+# CONFIG_MFD_WM831X_SPI is not set
+CONFIG_MFD_PCF50633=m
+CONFIG_MFD_MC13783=m
+CONFIG_MFD_MC13XXX=m
+CONFIG_PCF50633_ADC=m
+CONFIG_PCF50633_GPIO=m
+CONFIG_ABX500_CORE=y
+# CONFIG_EZX_PCAP is not set
+# CONFIG_AB8500_CORE is not set
+CONFIG_MFD_CS5535=m
+CONFIG_MFD_TIMBERDALE=m
+CONFIG_LPC_SCH=m
+CONFIG_MFD_RDC321X=m
+CONFIG_MFD_JANZ_CMODIO=m
+CONFIG_MFD_VX855=m
+CONFIG_MFD_WL1273_CORE=m
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_REGULATOR_BQ24022=m
+CONFIG_REGULATOR_MAX1586=m
+CONFIG_REGULATOR_MAX8649=m
+CONFIG_REGULATOR_MAX8660=m
+CONFIG_REGULATOR_MAX8952=m
+CONFIG_REGULATOR_WM8400=m
+CONFIG_REGULATOR_PCF50633=m
+CONFIG_REGULATOR_LP3971=m
+CONFIG_REGULATOR_LP3972=m
+CONFIG_REGULATOR_MC13XXX_CORE=m
+CONFIG_REGULATOR_MC13783=m
+CONFIG_REGULATOR_MC13892=m
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_ISL6271A=m
+# CONFIG_REGULATOR_AD5398 is not set
+CONFIG_REGULATOR_TPS6524X=m
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_RC_CORE=m
+CONFIG_LIRC=m
+CONFIG_RC_MAP=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_RC5_SZ_DECODER=m
+CONFIG_IR_LIRC_CODEC=m
+# CONFIG_IR_ENE is not set
+CONFIG_IR_IMON=m
+# CONFIG_IR_MCEUSB is not set
+# CONFIG_IR_NUVOTON is not set
+# CONFIG_IR_STREAMZAP is not set
+CONFIG_IR_WINBOND_CIR=m
+CONFIG_RC_LOOPBACK=m
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_MEDIA_TUNER_TDA18218=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_V4L2_MEM2MEM_DEV=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+
+#
+# RDS decoders
+#
+CONFIG_VIDEO_SAA6588=m
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_ADV7180=m
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_BT866=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_MT9V011=m
+CONFIG_VIDEO_TCM825X=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_SAA7191=m
+CONFIG_VIDEO_TVP514X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_TVP7002=m
+CONFIG_VIDEO_VPX3220=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_THS7303=m
+CONFIG_VIDEO_ADV7343=m
+CONFIG_VIDEO_AK881X=m
+
+#
+# Video improvement chips
+#
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+# CONFIG_VIDEO_CPIA2 is not set
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_ZR36060=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_RC=y
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_TIMBERDALE=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_MPEG=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CX18_ALSA=m
+CONFIG_VIDEO_SAA7164=m
+CONFIG_VIDEO_CAFE_CCIC=m
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_VIA_CAMERA is not set
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_IMX074 is not set
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9T031=m
+CONFIG_SOC_CAMERA_MT9T112=m
+CONFIG_SOC_CAMERA_MT9V022=m
+CONFIG_SOC_CAMERA_RJ54N1=m
+CONFIG_SOC_CAMERA_TW9910=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_SOC_CAMERA_OV2640=m
+# CONFIG_SOC_CAMERA_OV6650 is not set
+CONFIG_SOC_CAMERA_OV772X=m
+CONFIG_SOC_CAMERA_OV9640=m
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+# CONFIG_USB_GSPCA_KONICA is not set
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+# CONFIG_USB_GSPCA_SQ930X is not set
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_RC=y
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_USB_ET61X251=m
+CONFIG_USB_SN9C102=m
+# CONFIG_USB_PWC is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MEM2MEM_TESTDEV=m
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_I2C_SI4713 is not set
+# CONFIG_RADIO_SI4713 is not set
+CONFIG_USB_DSBR=m
+# CONFIG_RADIO_SI470X is not set
+CONFIG_USB_MR800=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_TIMBERDALE=m
+CONFIG_RADIO_WL1273=m
+CONFIG_DVB_MAX_ADAPTERS=8
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_CE6230=m
+# CONFIG_DVB_USB_FRIIO is not set
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_AZ6027=m
+# CONFIG_DVB_USB_LME2510 is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_SMS_SIANO_MDTV=m
+
+#
+# Siano module components
+#
+CONFIG_SMS_USB_DRV=m
+CONFIG_SMS_SDIO_DRV=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported SDMC DM1105 Adapters
+#
+CONFIG_DVB_DM1105=m
+CONFIG_DVB_FIREDTV=m
+CONFIG_DVB_FIREDTV_FIREWIRE=y
+# CONFIG_DVB_FIREDTV_IEEE1394 is not set
+CONFIG_DVB_FIREDTV_INPUT=y
+
+#
+# Supported Earthsoft PT1 Adapters
+#
+# CONFIG_DVB_PT1 is not set
+
+#
+# Supported Mantis Adapters
+#
+CONFIG_MANTIS_CORE=m
+CONFIG_DVB_MANTIS=m
+CONFIG_DVB_HOPPER=m
+
+#
+# Supported nGene Adapters
+#
+CONFIG_DVB_NGENE=m
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+CONFIG_DVB_STV090x=m
+CONFIG_DVB_STV6110x=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10036=m
+CONFIG_DVB_ZL10039=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_STV6110=m
+CONFIG_DVB_STV0900=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_MB86A16=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+CONFIG_DVB_DIB8000=m
+CONFIG_DVB_MB86A20S=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_TDA665x=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+CONFIG_AGP=m
+# CONFIG_AGP_ALI is not set
+# CONFIG_AGP_ATI is not set
+# CONFIG_AGP_AMD is not set
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_INTEL=m
+# CONFIG_AGP_NVIDIA is not set
+CONFIG_AGP_SIS=m
+# CONFIG_AGP_SWORKS is not set
+CONFIG_AGP_VIA=m
+# CONFIG_AGP_EFFICEON is not set
+# CONFIG_VGA_ARB is not set
+CONFIG_VGA_SWITCHEROO=y
+CONFIG_DRM=m
+CONFIG_DRM_KMS_HELPER=m
+CONFIG_DRM_TTM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+# CONFIG_DRM_RADEON_KMS is not set
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+# CONFIG_DRM_I915_KMS is not set
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+# CONFIG_STUB_POULSBO is not set
+CONFIG_VGASTATE=m
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=m
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=m
+# CONFIG_FB_WMT_GE_ROPS is not set
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_HECUBA=m
+CONFIG_FB_SVGALIB=m
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+CONFIG_FB_PM2=m
+CONFIG_FB_PM2_FIFO_DISCONNECT=y
+CONFIG_FB_CYBER2000=m
+CONFIG_FB_ARC=m
+CONFIG_FB_VGA16=m
+CONFIG_FB_UVESA=m
+CONFIG_FB_N411=m
+CONFIG_FB_HGA=m
+CONFIG_FB_S1D13XXX=m
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+# CONFIG_FB_I810 is not set
+CONFIG_FB_LE80578=m
+CONFIG_FB_CARILLO_RANCH=m
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_INTEL_I2C=y
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_S3=m
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+CONFIG_FB_SIS=m
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+CONFIG_FB_VIA=m
+# CONFIG_FB_VIA_DIRECT_PROCFS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_3DFX_I2C=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_VT8623=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_ARK=m
+CONFIG_FB_PM3=m
+CONFIG_FB_CARMINE=m
+CONFIG_FB_CARMINE_DRAM_EVAL=y
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
+CONFIG_FB_GEODE=y
+CONFIG_FB_GEODE_LX=m
+CONFIG_FB_GEODE_GX=m
+CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_TMIO=m
+CONFIG_FB_TMIO_ACCELL=y
+CONFIG_FB_SM501=m
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_METRONOME=m
+CONFIG_FB_MB862XX=m
+# CONFIG_FB_MB862XX_PCI_GDC is not set
+CONFIG_FB_BROADSHEET=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_L4F00242T03=m
+CONFIG_LCD_LMS283GF05=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_ILI9320=m
+CONFIG_LCD_TDO24M=m
+CONFIG_LCD_VGG2432A4=m
+CONFIG_LCD_PLATFORM=m
+CONFIG_LCD_S6E63M0=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_PROGEAR=m
+CONFIG_BACKLIGHT_CARILLO_RANCH=m
+CONFIG_BACKLIGHT_MBP_NVIDIA=m
+CONFIG_BACKLIGHT_SAHARA=m
+CONFIG_BACKLIGHT_ADP8860=m
+CONFIG_BACKLIGHT_PCF50633=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_RAWMIDI_SEQ=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_PCSP=m
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_ALOOP is not set
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ASIHPI=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_CTXFI=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_INDIGOIOX=m
+CONFIG_SND_INDIGODJX=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_ES1968_INPUT=y
+CONFIG_SND_FM801=m
+# CONFIG_SND_FM801_TEA575X_BOOL is not set
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDA_HWDEP=y
+# CONFIG_SND_HDA_RECONFIG is not set
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_INPUT_BEEP_MODE=0
+CONFIG_SND_HDA_INPUT_JACK=y
+# CONFIG_SND_HDA_PATCH_LOADER is not set
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_CODEC_HDMI=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_GENERIC=y
+# CONFIG_SND_HDA_POWER_SAVE is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_LX6464ES=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MAESTRO3_INPUT=y
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+# CONFIG_SND_SIS7019 is not set
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+# CONFIG_SND_USB_CAIAQ_INPUT is not set
+CONFIG_SND_USB_US122L=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_PDAUDIOCF=m
+CONFIG_SND_SOC=m
+# CONFIG_SND_SOC_CACHE_LZO is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+CONFIG_SND_SOC_ALL_CODECS=m
+CONFIG_SND_SOC_WM_HUBS=m
+CONFIG_SND_SOC_AD1836=m
+CONFIG_SND_SOC_AD193X=m
+CONFIG_SND_SOC_AD73311=m
+CONFIG_SND_SOC_ADS117X=m
+CONFIG_SND_SOC_AK4104=m
+CONFIG_SND_SOC_AK4535=m
+CONFIG_SND_SOC_AK4642=m
+CONFIG_SND_SOC_AK4671=m
+CONFIG_SND_SOC_ALC5623=m
+CONFIG_SND_SOC_CS42L51=m
+CONFIG_SND_SOC_CS4270=m
+CONFIG_SND_SOC_CX20442=m
+CONFIG_SND_SOC_L3=m
+CONFIG_SND_SOC_DA7210=m
+CONFIG_SND_SOC_MAX98088=m
+CONFIG_SND_SOC_PCM3008=m
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_SSM2602=m
+CONFIG_SND_SOC_TLV320AIC23=m
+CONFIG_SND_SOC_TLV320AIC26=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_TLV320DAC33=m
+CONFIG_SND_SOC_UDA134X=m
+CONFIG_SND_SOC_UDA1380=m
+CONFIG_SND_SOC_WL1273=m
+CONFIG_SND_SOC_WM8400=m
+CONFIG_SND_SOC_WM8510=m
+CONFIG_SND_SOC_WM8523=m
+CONFIG_SND_SOC_WM8580=m
+CONFIG_SND_SOC_WM8711=m
+CONFIG_SND_SOC_WM8727=m
+CONFIG_SND_SOC_WM8728=m
+CONFIG_SND_SOC_WM8731=m
+CONFIG_SND_SOC_WM8737=m
+CONFIG_SND_SOC_WM8741=m
+CONFIG_SND_SOC_WM8750=m
+CONFIG_SND_SOC_WM8753=m
+CONFIG_SND_SOC_WM8770=m
+CONFIG_SND_SOC_WM8776=m
+CONFIG_SND_SOC_WM8804=m
+CONFIG_SND_SOC_WM8900=m
+CONFIG_SND_SOC_WM8903=m
+CONFIG_SND_SOC_WM8904=m
+CONFIG_SND_SOC_WM8940=m
+CONFIG_SND_SOC_WM8955=m
+CONFIG_SND_SOC_WM8960=m
+CONFIG_SND_SOC_WM8961=m
+CONFIG_SND_SOC_WM8962=m
+CONFIG_SND_SOC_WM8971=m
+CONFIG_SND_SOC_WM8974=m
+CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_WM8985=m
+CONFIG_SND_SOC_WM8988=m
+CONFIG_SND_SOC_WM8990=m
+CONFIG_SND_SOC_WM8993=m
+CONFIG_SND_SOC_WM8995=m
+CONFIG_SND_SOC_WM9081=m
+CONFIG_SND_SOC_MAX9877=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SOC_WM2000=m
+CONFIG_SND_SOC_WM9090=m
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_3M_PCT=m
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+CONFIG_HID_CANDO=m
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_PRODIKEYS=m
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+CONFIG_HID_EGALAX=m
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+CONFIG_HID_MAGICMOUSE=m
+# CONFIG_HID_MICROSOFT is not set
+CONFIG_HID_MOSART=m
+# CONFIG_HID_MONTEREY is not set
+CONFIG_HID_MULTITOUCH=m
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_ORTEK=m
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_ROCCAT_KONE=m
+CONFIG_HID_ROCCAT_KONEPLUS=m
+# CONFIG_HID_ROCCAT_PYRA is not set
+# CONFIG_HID_SAMSUNG is not set
+CONFIG_HID_SONY=m
+CONFIG_HID_STANTUM=m
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_HID_ZYDACRON=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+CONFIG_USB_WUSB=m
+CONFIG_USB_WUSB_CBAF=m
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_XHCI_HCD=m
+# CONFIG_USB_XHCI_HCD_DEBUGGING is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OXU210HP_HCD=m
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_ISP1760_HCD=m
+CONFIG_USB_ISP1362_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_SSB=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_WHCI_HCD=m
+CONFIG_USB_HWA_HCD=m
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+# CONFIG_USB_UAS is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7715_PARPORT=y
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_SAMBA is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+# CONFIG_USB_SERIAL_SSU100 is not set
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+# CONFIG_USB_LEGOTOWER is not set
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+# CONFIG_USB_TRANCEVIBRATOR is not set
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=m
+CONFIG_NOP_USB_XCEIV=m
+CONFIG_UWB=m
+CONFIG_UWB_HWA=m
+CONFIG_UWB_WHCI=m
+CONFIG_UWB_I1480U=m
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+CONFIG_MMC_TEST=m
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_SDHCI_PCI=m
+CONFIG_MMC_RICOH_MMC=y
+CONFIG_MMC_SDHCI_PLTFM=m
+CONFIG_MMC_WBSD=m
+CONFIG_MMC_TIFM_SD=m
+CONFIG_MMC_SDRICOH_CS=m
+CONFIG_MMC_CB710=m
+CONFIG_MMC_VIA_SDMMC=m
+# CONFIG_MMC_USHC is not set
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_NET5501=m
+CONFIG_LEDS_ALIX2=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+CONFIG_LEDS_LP3944=m
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+CONFIG_LEDS_CLEVO_MAIL=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_REGULATOR=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_INTEL_SS4200=m
+CONFIG_LEDS_LT3593=m
+CONFIG_LEDS_DELL_NETBOOKS=m
+# CONFIG_LEDS_MC13783 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_NFC_DEVICES is not set
+CONFIG_ACCESSIBILITY=y
+# CONFIG_A11Y_BRAILLE_CONSOLE is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_AMSO1100=m
+# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_INFINIBAND_CXGB4=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_INFINIBAND_NES=m
+# CONFIG_INFINIBAND_NES_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_TEST=m
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+# CONFIG_RTC_DRV_DS3232 is not set
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+# CONFIG_RTC_DRV_ISL12022 is not set
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=m
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8581=m
+CONFIG_RTC_DRV_RX8025=m
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_DS3234=m
+CONFIG_RTC_DRV_PCF2123=m
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=m
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_PCF50633=m
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_MC13XXX is not set
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_INTEL_MID_DMAC is not set
+CONFIG_INTEL_IOATDMA=m
+CONFIG_TIMB_DMA=m
+CONFIG_PCH_DMA=m
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+# CONFIG_ASYNC_TX_DMA is not set
+CONFIG_DMATEST=m
+CONFIG_DCA=m
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+CONFIG_CFAG12864B=m
+CONFIG_CFAG12864B_RATE=20
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+# CONFIG_UIO_PCI_GENERIC is not set
+CONFIG_UIO_NETX=m
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_ET131X is not set
+# CONFIG_SLICOSS is not set
+# CONFIG_VIDEO_GO7007 is not set
+# CONFIG_VIDEO_CX25821 is not set
+# CONFIG_VIDEO_TM6000 is not set
+CONFIG_USB_DABUSB=m
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_W35UND is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+CONFIG_BRCM80211=m
+CONFIG_BRCM80211_PCI=y
+# CONFIG_BRCMFMAC is not set
+# CONFIG_RT2860 is not set
+# CONFIG_RT2870 is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_PANEL is not set
+# CONFIG_R8187SE is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTL8192E is not set
+# CONFIG_R8712U is not set
+# CONFIG_TRANZPORT is not set
+# CONFIG_POHMELFS is not set
+CONFIG_AUTOFS_FS=m
+# CONFIG_IDE_PHISON is not set
+# CONFIG_LINE6_USB is not set
+CONFIG_DRM_VMWGFX=m
+CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_NOUVEAU_BACKLIGHT=y
+CONFIG_DRM_NOUVEAU_DEBUG=y
+
+#
+# I2C encoder or helper chips
+#
+# CONFIG_DRM_I2C_CH7006 is not set
+CONFIG_DRM_I2C_SIL164=m
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+CONFIG_HYPERV=m
+CONFIG_HYPERV_STORAGE=m
+CONFIG_HYPERV_BLOCK=m
+CONFIG_HYPERV_NET=m
+CONFIG_HYPERV_UTILS=m
+# CONFIG_VME_BUS is not set
+# CONFIG_DX_SEP is not set
+# CONFIG_IIO is not set
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_ZRAM is not set
+# CONFIG_WLAGS49_H2 is not set
+# CONFIG_WLAGS49_H25 is not set
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_VIDEO_DT3155 is not set
+# CONFIG_CRYSTALHD is not set
+# CONFIG_CXT1E1 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_ST_BT is not set
+# CONFIG_FB_XGI is not set
+# CONFIG_LIRC_STAGING is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_EASYCAP is not set
+# CONFIG_SOLO6X10 is not set
+# CONFIG_ACPI_QUICKSTART is not set
+CONFIG_MACH_NO_WESTBRIDGE=y
+# CONFIG_SBE_2T3E3 is not set
+# CONFIG_ATH6K_LEGACY is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_ACER_WMI=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_DELL_LAPTOP=m
+CONFIG_DELL_WMI=m
+CONFIG_FUJITSU_LAPTOP=m
+# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
+# CONFIG_TC1100_WMI is not set
+CONFIG_HP_WMI=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+# CONFIG_SONYPI_COMPAT is not set
+# CONFIG_IDEAPAD_LAPTOP is not set
+CONFIG_THINKPAD_ACPI=m
+CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y
+# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_SENSORS_HDAPS=m
+CONFIG_INTEL_MENLOW=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_EEEPC_WMI=m
+CONFIG_ACPI_WMI=m
+CONFIG_MSI_WMI=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_TOPSTAR_LAPTOP is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_TOSHIBA_BT_RFKILL=m
+CONFIG_ACPI_CMPC=m
+# CONFIG_INTEL_IPS is not set
+# CONFIG_IBM_RTL is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+# CONFIG_EDD_OFF is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+CONFIG_DMIID=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=m
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_HISTOGRAM=y
+# CONFIG_FSCACHE_DEBUG is not set
+# CONFIG_FSCACHE_OBJECT_LIST is not set
+CONFIG_CACHEFILES=m
+# CONFIG_CACHEFILES_DEBUG is not set
+# CONFIG_CACHEFILES_HISTOGRAM is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=m
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_LOGFS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_LZO is not set
+CONFIG_SQUASHFS_XZ=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_EXOFS_FS=m
+# CONFIG_EXOFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+# CONFIG_NFS_FSCACHE is not set
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_DEPRECATED=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_XPRT_RDMA=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_CEPH_FS=m
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_DFS_UPCALL=y
+# CONFIG_CIFS_FSCACHE is not set
+# CONFIG_CIFS_ACL is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_BKL=y
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LKDTM is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_RING_BUFFER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_TEST_KSTRTOX=m
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_DEBUG_SET_MODULE_RONX=y
+CONFIG_DOUBLEFAULT=y
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_OPTIMIZE_INLINING is not set
+
+#
+# Linux VServer
+#
+CONFIG_VSERVER_AUTO_LBACK=y
+CONFIG_VSERVER_AUTO_SINGLE=y
+CONFIG_VSERVER_COWBL=y
+# CONFIG_VSERVER_VTIME is not set
+# CONFIG_VSERVER_DEVICE is not set
+CONFIG_VSERVER_PROC_SECURE=y
+# CONFIG_TAGGING_NONE is not set
+# CONFIG_TAGGING_UID16 is not set
+# CONFIG_TAGGING_GID16 is not set
+CONFIG_TAGGING_ID24=y
+# CONFIG_TAGGING_INTERN is not set
+# CONFIG_TAG_NFSD is not set
+# CONFIG_VSERVER_PRIVACY is not set
+CONFIG_VSERVER_CONTEXTS=256
+CONFIG_VSERVER_WARN=y
+CONFIG_VSERVER_WARN_DEVPTS=y
+# CONFIG_VSERVER_DEBUG is not set
+# CONFIG_VSERVER_LEGACY_MEM is not set
+CONFIG_QUOTES_ISO8859=y
+# CONFIG_QUOTES_UTF8 is not set
+# CONFIG_QUOTES_ASCII is not set
+CONFIG_VSERVER=y
+CONFIG_VSERVER_SECURITY=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_TRUSTED_KEYS=m
+CONFIG_ENCRYPTED_KEYS=m
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_IMA is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y
+CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_FPU=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C_INTEL=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_AES_NI_INTEL=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SALSA20_586=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_TWOFISH_586=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_USER_API=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+# CONFIG_CRYPTO_DEV_GEODE is not set
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_APIC_ARCHITECTURE=y
+CONFIG_KVM_MMIO=y
+CONFIG_KVM_ASYNC_PF=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_KVM_AMD=m
+CONFIG_VHOST_NET=m
+# CONFIG_LGUEST is not set
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_BTREE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_NLATTR=y
+CONFIG_AVERAGE=y
diff --git a/main/linux-vserver/kernelconfig.x86_64 b/main/linux-vserver/kernelconfig.x86_64
new file mode 100644
index 0000000000..75208dbb99
--- /dev/null
+++ b/main/linux-vserver/kernelconfig.x86_64
@@ -0,0 +1,5004 @@
+#
+# Automatically generated make config: don't edit
+# Linux/x86_64 2.6.38.2-vs2.3.0.37-rc10 Kernel Configuration
+# Thu Apr 7 20:07:22 2011
+#
+CONFIG_64BIT=y
+# CONFIG_X86_32 is not set
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_X86_64_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
+# CONFIG_KTIME_SCALAR is not set
+CONFIG_ARCH_CPU_PROBE_RELEASE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+# CONFIG_AUTO_IRQ_AFFINITY is not set
+# CONFIG_IRQ_PER_CPU is not set
+# CONFIG_HARDIRQS_SW_RESEND is not set
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+CONFIG_RCU_FAST_NO_HZ=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=m
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+# CONFIG_PROC_PID_CPUSET is not set
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+# CONFIG_CGROUP_MEM_RES_CTLR is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+# CONFIG_JUMP_LABEL is not set
+CONFIG_OPTPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_KRETPROBES=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_DEV_THROTTLING is not set
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CFQ_GROUP_IOSCHED is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_PADATA=y
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_VSMP is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_PARAVIRT_GUEST=y
+CONFIG_XEN=y
+CONFIG_XEN_DOM0=y
+CONFIG_XEN_PRIVILEGED_GUEST=y
+CONFIG_XEN_PVHVM=y
+CONFIG_XEN_MAX_DOMAIN_MEMORY=128
+CONFIG_XEN_SAVE_RESTORE=y
+# CONFIG_XEN_DEBUG_FS is not set
+CONFIG_KVM_CLOCK=y
+CONFIG_KVM_GUEST=y
+CONFIG_PARAVIRT=y
+# CONFIG_PARAVIRT_SPINLOCKS is not set
+CONFIG_PARAVIRT_CLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_MEMTEST is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_CPU=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_CMPXCHG=y
+CONFIG_CMPXCHG_LOCAL=y
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_XADD=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+CONFIG_GART_IOMMU=y
+# CONFIG_CALGARY_IOMMU is not set
+# CONFIG_AMD_IOMMU is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_IOMMU_API is not set
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+# CONFIG_X86_MCE is not set
+CONFIG_I8K=m
+CONFIG_MICROCODE=m
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_DIRECT_GBPAGES=y
+# CONFIG_NUMA is not set
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
+# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW=64
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+# CONFIG_EFI is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_300=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=300
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_COMPAT_VDSO is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM_OPS=y
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+# CONFIG_ACPI_POWER_METER is not set
+CONFIG_ACPI_EC_DEBUGFS=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_IPMI=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=m
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+CONFIG_ACPI_HED=m
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=m
+CONFIG_ACPI_APEI_EINJ=m
+CONFIG_ACPI_APEI_ERST_DEBUG=y
+# CONFIG_SFI is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_PCC_CPUFREQ=m
+CONFIG_X86_ACPI_CPUFREQ=m
+CONFIG_X86_POWERNOW_K8=m
+CONFIG_X86_SPEEDSTEP_CENTRINO=m
+CONFIG_X86_P4_CLOCKMOD=m
+
+#
+# shared options
+#
+CONFIG_X86_SPEEDSTEP_LIB=m
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_INTEL_IDLE=y
+
+#
+# Memory power savings
+#
+# CONFIG_I7300_IDLE is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_XEN=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_CNB20LE_QUIRK=y
+# CONFIG_DMAR is not set
+# CONFIG_INTR_REMAP is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_PCIEAER is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_STUB=m
+CONFIG_XEN_PCIDEV_FRONTEND=y
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+CONFIG_PCI_IOAPIC=y
+CONFIG_ISA_DMA_API=y
+CONFIG_AMD_NB=y
+CONFIG_PCCARD=m
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+CONFIG_HOTPLUG_PCI=m
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_SHPC=m
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_HAVE_TEXT_POKE_SMP=y
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+# CONFIG_IP_PIMSM_V1 is not set
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETLABEL=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_NFCT=y
+CONFIG_IP_VS_PE_SIP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_SCTP=m
+CONFIG_NET_SCTPPROBE=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+CONFIG_RDS=m
+# CONFIG_RDS_RDMA is not set
+# CONFIG_RDS_TCP is not set
+# CONFIG_RDS_DEBUG is not set
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_PHONET=m
+# CONFIG_PHONET_PIPECTRLR is not set
+CONFIG_IEEE802154=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_CLS_CGROUP is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+CONFIG_RPS=y
+CONFIG_XPS=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_DEV=m
+# CONFIG_CAN_CALC_BITTIMING is not set
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_JANZ_ICAN3=m
+# CONFIG_PCH_CAN is not set
+CONFIG_CAN_SJA1000=m
+CONFIG_CAN_SJA1000_PLATFORM=m
+CONFIG_CAN_EMS_PCI=m
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PLX_PCI=m
+
+#
+# CAN USB interfaces
+#
+# CONFIG_CAN_EMS_USB is not set
+# CONFIG_CAN_ESD_USB2 is not set
+CONFIG_CAN_SOFTING=m
+CONFIG_CAN_SOFTING_CS=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_RXKAD=m
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+# CONFIG_RFKILL_INPUT is not set
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NET_9P_RDMA=m
+# CONFIG_NET_9P_DEBUG is not set
+CONFIG_CAIF=m
+# CONFIG_CAIF_DEBUG is not set
+CONFIG_CAIF_NETDEV=m
+CONFIG_CEPH_LIB=m
+# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=m
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+CONFIG_SYS_HYPERVISOR=y
+CONFIG_CONNECTOR=m
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_AR7_PARTS=m
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_HAVE_MTD_OTP=y
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+CONFIG_SSFDC=m
+CONFIG_SM_FTL=m
+CONFIG_MTD_OOPS=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_AMD76XROM=m
+CONFIG_MTD_ICHXROM=m
+CONFIG_MTD_ESB2ROM=m
+CONFIG_MTD_CK804XROM=m
+CONFIG_MTD_SCB2_FLASH=m
+CONFIG_MTD_NETtel=m
+CONFIG_MTD_L440GX=m
+CONFIG_MTD_PCI=m
+CONFIG_MTD_PCMCIA=m
+# CONFIG_MTD_PCMCIA_ANONYMOUS is not set
+# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_INTEL_VR_NOR=m
+CONFIG_MTD_PLATRAM=m
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+CONFIG_MTD_PMC551_BUGFIX=y
+# CONFIG_MTD_PMC551_DEBUG is not set
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DATAFLASH_OTP is not set
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_MTD_SST25L is not set
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+# CONFIG_MTD_DOCPROBE_HIGH is not set
+# CONFIG_MTD_DOCPROBE_55AA is not set
+CONFIG_MTD_NAND_ECC=m
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_SM_COMMON=m
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_DENALI=m
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_RICOH=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CAFE=m
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_ALAUDA=m
+CONFIG_MTD_ONENAND=m
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OTP=y
+CONFIG_MTD_ONENAND_2X_PROGRAM=y
+CONFIG_MTD_ONENAND_SIM=m
+
+#
+# LPDDR flash memory drivers
+#
+CONFIG_MTD_LPDDR=m
+CONFIG_MTD_QINFO_PROBE=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_AX88796=m
+# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=m
+# CONFIG_PARIDE is not set
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_VROOT=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_AD525X_DPOT_SPI=m
+CONFIG_IBM_ASM=m
+CONFIG_PHANTOM=m
+CONFIG_SGI_IOC4=m
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
+CONFIG_ICS932S401=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_CS5535_MFGPT=m
+CONFIG_CS5535_MFGPT_DEFAULT_IRQ=7
+CONFIG_CS5535_CLOCK_EVENT_SRC=m
+CONFIG_HP_ILO=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1780=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_TI_DAC7512=m
+CONFIG_VMWARE_BALLOON=m
+CONFIG_BMP085=m
+CONFIG_PCH_PHUB=m
+CONFIG_C2PORT=m
+CONFIG_C2PORT_DURAMAR_2150=m
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_AT25=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93CX6=m
+CONFIG_CB710_CORE=m
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
+CONFIG_IWMC3200TOP=m
+# CONFIG_IWMC3200TOP_DEBUG is not set
+# CONFIG_IWMC3200TOP_DEBUGFS is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_FC_TGT_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_HOST_SMP=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+# CONFIG_BE2ISCSI is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_HPSA=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_3W_SAS=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
+CONFIG_SCSI_MVSAS=m
+CONFIG_SCSI_MVSAS_DEBUG=y
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_ARCMSR=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_MPT2SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
+# CONFIG_SCSI_MPT2SAS_LOGGING is not set
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_BUSLOGIC=m
+CONFIG_VMWARE_PVSCSI=m
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+CONFIG_FCOE=m
+CONFIG_FCOE_FNIC=m
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_EATA=m
+# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set
+# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+CONFIG_SCSI_IPR_TRACE=y
+# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_PMCRAID is not set
+CONFIG_SCSI_PM8001=m
+CONFIG_SCSI_SRP=m
+# CONFIG_SCSI_BFA_FC is not set
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_SCSI_OSD_DPRINT_SENSE=1
+# CONFIG_SCSI_OSD_DEBUG is not set
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_SATA_INIC162X=m
+CONFIG_SATA_ACARD_AHCI=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SX4=m
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+CONFIG_ATA_PIIX=m
+CONFIG_SATA_MV=m
+CONFIG_SATA_NV=m
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+
+#
+# PATA SFF controllers with BMDMA
+#
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+CONFIG_PATA_ATP867X=m
+CONFIG_PATA_CMD64X=m
+CONFIG_PATA_CS5520=m
+CONFIG_PATA_CS5530=m
+CONFIG_PATA_CS5536=m
+CONFIG_PATA_CYPRESS=m
+CONFIG_PATA_EFAR=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+CONFIG_PATA_HPT3X2N=m
+CONFIG_PATA_HPT3X3=m
+CONFIG_PATA_HPT3X3_DMA=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87415=m
+CONFIG_PATA_OLDPIIX=m
+CONFIG_PATA_OPTIDMA=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_PDC_OLD=m
+CONFIG_PATA_RADISYS=m
+CONFIG_PATA_RDC=m
+CONFIG_PATA_SC1200=m
+CONFIG_PATA_SCH=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_TOSHIBA=m
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+
+#
+# PIO-only SFF controllers
+#
+CONFIG_PATA_CMD640_PCI=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_OPTI=m
+CONFIG_PATA_PCMCIA=m
+CONFIG_PATA_PLATFORM=m
+CONFIG_PATA_RZ1000=m
+
+#
+# Generic fallback / legacy drivers
+#
+CONFIG_PATA_ACPI=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_LEGACY=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_AUTODETECT is not set
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MULTICORE_RAID456 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_OHCI_DEBUG=y
+CONFIG_FIREWIRE_SBP2=m
+CONFIG_FIREWIRE_NET=m
+CONFIG_FIREWIRE_NOSY=m
+CONFIG_I2O=m
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+CONFIG_ARCNET=m
+CONFIG_ARCNET_1201=m
+CONFIG_ARCNET_1051=m
+CONFIG_ARCNET_RAW=m
+CONFIG_ARCNET_CAP=m
+CONFIG_ARCNET_COM90xx=m
+CONFIG_ARCNET_COM90xxIO=m
+CONFIG_ARCNET_RIM_I=m
+CONFIG_ARCNET_COM20020=m
+CONFIG_ARCNET_COM20020_PCI=m
+CONFIG_MII=m
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_BCM63XX_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MICREL_PHY=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_MDIO_GPIO=m
+CONFIG_NET_ETHERNET=y
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ETHOC=m
+CONFIG_DNET=m
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_DE2104X_DSL=0
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_HP100=m
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_KSZ884X_PCI=m
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SMSC9420=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_KS8842=m
+CONFIG_KS8851=m
+CONFIG_KS8851_MLL=m
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_ATL2=m
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_IP1000=m
+CONFIG_IGB=m
+CONFIG_IGB_DCA=y
+CONFIG_IGBVF=m
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_CNIC=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_ATL1C=m
+CONFIG_JME=m
+CONFIG_STMMAC_ETH=m
+# CONFIG_STMMAC_DA is not set
+# CONFIG_STMMAC_DUAL_MAC is not set
+CONFIG_PCH_GBE=m
+CONFIG_NETDEV_10000=y
+CONFIG_MDIO=m
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3_DEPENDS=y
+CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4_DEPENDS=y
+CONFIG_CHELSIO_T4=m
+CONFIG_CHELSIO_T4VF_DEPENDS=y
+CONFIG_CHELSIO_T4VF=m
+CONFIG_ENIC=m
+CONFIG_IXGBE=m
+CONFIG_IXGBE_DCA=y
+# CONFIG_IXGBEVF is not set
+CONFIG_IXGB=m
+CONFIG_S2IO=m
+CONFIG_VXGE=m
+# CONFIG_VXGE_DEBUG_TRACE_ALL is not set
+CONFIG_MYRI10GE=m
+CONFIG_MYRI10GE_DCA=y
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_QLCNIC=m
+CONFIG_QLGE=m
+CONFIG_BNA=m
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_BE2NET=m
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AIRO=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_AT76C50X_USB=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+CONFIG_ADM8211=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_MWL8K=m
+CONFIG_ATH_COMMON=m
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH5K_PCI=y
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K=m
+# CONFIG_ATH9K_DEBUGFS is not set
+CONFIG_ATH9K_RATE_CONTROL=y
+CONFIG_ATH9K_HTC=m
+# CONFIG_ATH9K_HTC_DEBUGFS is not set
+CONFIG_AR9170_USB=m
+CONFIG_AR9170_LEDS=y
+CONFIG_CARL9170=m
+CONFIG_CARL9170_LEDS=y
+CONFIG_CARL9170_WPC=y
+CONFIG_B43=m
+CONFIG_B43_PCI_AUTOSELECT=y
+CONFIG_B43_PCICORE_AUTOSELECT=y
+CONFIG_B43_PCMCIA=y
+CONFIG_B43_SDIO=y
+CONFIG_B43_PIO=y
+CONFIG_B43_PHY_N=y
+CONFIG_B43_PHY_LP=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_PCI_AUTOSELECT=y
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_HWRNG=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
+CONFIG_IWLWIFI=m
+
+#
+# Debugging Options
+#
+# CONFIG_IWLWIFI_DEBUG is not set
+CONFIG_IWLAGN=m
+CONFIG_IWL4965=y
+CONFIG_IWL5000=y
+CONFIG_IWL3945=m
+CONFIG_IWM=m
+# CONFIG_IWM_DEBUG is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_CS=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_LIBERTAS_MESH=y
+CONFIG_HERMES=m
+# CONFIG_HERMES_PRISM is not set
+CONFIG_HERMES_CACHE_FW_ON_INIT=y
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ORINOCO_USB=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_P54_PCI=m
+CONFIG_P54_SPI=m
+# CONFIG_P54_SPI_DEFAULT_EEPROM is not set
+CONFIG_P54_LEDS=y
+CONFIG_RT2X00=m
+CONFIG_RT2400PCI=m
+CONFIG_RT2500PCI=m
+CONFIG_RT61PCI=m
+CONFIG_RT2800PCI=m
+CONFIG_RT2800PCI_RT33XX=y
+# CONFIG_RT2800PCI_RT35XX is not set
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT33XX=y
+# CONFIG_RT2800USB_RT35XX is not set
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RT2800_LIB=m
+CONFIG_RT2X00_LIB_PCI=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_HT=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_RTL8192CE=m
+CONFIG_RTLWIFI=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SPI=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_HT=y
+CONFIG_WL12XX_SPI=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_WL12XX_SDIO_TEST=m
+CONFIG_WL12XX_PLATFORM_DATA=y
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+CONFIG_WIMAX_I2400M=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_WIMAX_I2400M_SDIO=m
+CONFIG_WIMAX_IWMC3200_SDIO=y
+CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_CDC_PHONET=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_ARCNET_COM20020_CS=m
+CONFIG_WAN=y
+CONFIG_LANMEDIA=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=m
+CONFIG_HDLC_RAW_ETH=m
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_X25=m
+CONFIG_PCI200SYN=m
+CONFIG_WANXL=m
+# CONFIG_WANXL_BUILD_FIRMWARE is not set
+CONFIG_PC300TOO=m
+CONFIG_FARSYNC=m
+CONFIG_DSCC4=m
+CONFIG_DSCC4_PCISYNC=y
+CONFIG_DSCC4_PCI_RST=y
+CONFIG_DLCI=m
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=m
+CONFIG_CYCLADES_SYNC=m
+CONFIG_CYCLOMX_X25=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+CONFIG_SBNI=m
+CONFIG_SBNI_MULTILINE=y
+CONFIG_ATM_DRIVERS=y
+CONFIG_ATM_DUMMY=m
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_USE_TASKLET=y
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_ATM_SOLOS=m
+CONFIG_IEEE802154_DRIVERS=m
+CONFIG_IEEE802154_FAKEHARD=m
+
+#
+# CAIF transport drivers
+#
+CONFIG_CAIF_TTY=m
+CONFIG_CAIF_SPI_SLAVE=m
+# CONFIG_CAIF_SPI_SYNC is not set
+CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_FDDI=y
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_SKFP=m
+CONFIG_HIPPI=y
+CONFIG_ROADRUNNER=m
+# CONFIG_ROADRUNNER_LARGE_RINGS is not set
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOATM=m
+CONFIG_PPPOL2TP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+CONFIG_VMXNET3=m
+CONFIG_ISDN=y
+# CONFIG_ISDN_I4L is not set
+CONFIG_ISDN_CAPI=m
+# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set
+# CONFIG_CAPI_TRACE is not set
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_CAPI=y
+# CONFIG_GIGASET_DUMMYLL is not set
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+CONFIG_GIGASET_M101=m
+# CONFIG_GIGASET_DEBUG is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+CONFIG_MISDN=m
+CONFIG_MISDN_DSP=m
+CONFIG_MISDN_L1OIP=m
+
+#
+# mISDN hardware drivers
+#
+CONFIG_MISDN_HFCPCI=m
+CONFIG_MISDN_HFCMULTI=m
+CONFIG_MISDN_HFCUSB=m
+CONFIG_MISDN_AVMFRITZ=m
+# CONFIG_MISDN_SPEEDFAX is not set
+# CONFIG_MISDN_INFINEON is not set
+# CONFIG_MISDN_W6692 is not set
+# CONFIG_MISDN_NETJET is not set
+CONFIG_MISDN_IPAC=m
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_POLLDEV=m
+CONFIG_INPUT_SPARSEKMAP=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+CONFIG_XEN_KBDDEV_FRONTEND=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT2160 is not set
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_GPIO_POLLED=m
+CONFIG_KEYBOARD_TCA6416=m
+CONFIG_KEYBOARD_MATRIX=m
+CONFIG_KEYBOARD_LM8323=m
+# CONFIG_KEYBOARD_MAX7359 is not set
+CONFIG_KEYBOARD_MCS=m
+CONFIG_KEYBOARD_NEWTON=m
+# CONFIG_KEYBOARD_OPENCORES is not set
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_GPIO=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_AD7877=m
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_AD7879_SPI=m
+CONFIG_TOUCHSCREEN_BU21013=m
+CONFIG_TOUCHSCREEN_CY8CTMG110=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_QT602240=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_UCB1400=m
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+# CONFIG_TOUCHSCREEN_MC13783 is not set
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
+CONFIG_TOUCHSCREEN_USB_NEXIO=y
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_ST1232=m
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_AD714X_I2C=m
+CONFIG_INPUT_AD714X_SPI=m
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_APANEL=m
+CONFIG_INPUT_ATLAS_BTNS=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_PCF50633_PMU=m
+CONFIG_INPUT_PCF8574=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_ADXL34X_I2C=m
+CONFIG_INPUT_ADXL34X_SPI=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_INPUT_CMA3000_I2C=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_ALTERA_PS2=m
+CONFIG_SERIO_PS2MULT=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_COMPUTONE=m
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+CONFIG_ISI=m
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_N_GSM is not set
+CONFIG_RISCOM8=m
+CONFIG_SPECIALIX=m
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MAX3100=m
+CONFIG_SERIAL_MAX3107=m
+CONFIG_SERIAL_MRST_MAX3110=m
+CONFIG_SERIAL_MFD_HSU=m
+CONFIG_SERIAL_UARTLITE=m
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_SERIAL_TIMBERDALE=m
+CONFIG_SERIAL_ALTERA_JTAGUART=m
+CONFIG_SERIAL_ALTERA_UART=m
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
+CONFIG_SERIAL_IFX6X60=m
+CONFIG_SERIAL_PCH_UART=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_XEN=y
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=m
+CONFIG_R3964=m
+CONFIG_APPLICOM=m
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+CONFIG_MWAVE=m
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+CONFIG_TELCLOCK=m
+CONFIG_DEVPORT=y
+CONFIG_RAMOOPS=m
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_MUX=m
+
+#
+# Multiplexer I2C Chip support
+#
+CONFIG_I2C_MUX_GPIO=m
+CONFIG_I2C_MUX_PCA9541=m
+CONFIG_I2C_MUX_PCA954x=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_SMBUS=m
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+
+#
+# ACPI drivers
+#
+CONFIG_I2C_SCMI=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=m
+CONFIG_I2C_INTEL_MID=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_XILINX=m
+CONFIG_I2C_EG20T=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+CONFIG_SPI_BUTTERFLY=m
+CONFIG_SPI_GPIO=m
+CONFIG_SPI_LM70_LLP=m
+# CONFIG_SPI_PXA2XX_PCI is not set
+CONFIG_SPI_TOPCLIFF_PCH=m
+# CONFIG_SPI_XILINX is not set
+CONFIG_SPI_DESIGNWARE=m
+CONFIG_SPI_DW_PCI=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+CONFIG_GPIO_MAX730X=m
+
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_BASIC_MMIO=m
+CONFIG_GPIO_IT8761E=m
+CONFIG_GPIO_SCH=m
+CONFIG_GPIO_VX855=m
+
+#
+# I2C GPIO expanders:
+#
+CONFIG_GPIO_MAX7300=m
+CONFIG_GPIO_MAX732X=m
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_ADP5588=m
+
+#
+# PCI GPIO expanders:
+#
+CONFIG_GPIO_CS5535=m
+# CONFIG_GPIO_LANGWELL is not set
+CONFIG_GPIO_PCH=m
+CONFIG_GPIO_ML_IOH=m
+CONFIG_GPIO_TIMBERDALE=y
+CONFIG_GPIO_RDC321X=m
+
+#
+# SPI GPIO expanders:
+#
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MCP23S08=m
+# CONFIG_GPIO_MC33880 is not set
+CONFIG_GPIO_74X164=m
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_GPIO_UCB1400 is not set
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_GPIO_JANZ_TTL=m
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_GPIO=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PDA_POWER=m
+CONFIG_TEST_POWER=m
+CONFIG_BATTERY_DS2760=m
+CONFIG_BATTERY_DS2782=m
+CONFIG_BATTERY_BQ20Z75=m
+CONFIG_BATTERY_BQ27x00=m
+CONFIG_BATTERY_MAX17040=m
+CONFIG_BATTERY_MAX17042=m
+CONFIG_CHARGER_PCF50633=m
+CONFIG_CHARGER_ISP1704=m
+CONFIG_CHARGER_GPIO=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7411=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7475=m
+CONFIG_SENSORS_ASC7621=m
+CONFIG_SENSORS_K8TEMP=m
+CONFIG_SENSORS_K10TEMP=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS620=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_G760A=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_GPIO_FAN=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_PKGTEMP=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_JC42=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LTC4215=m
+CONFIG_SENSORS_LTC4245=m
+CONFIG_SENSORS_LTC4261=m
+CONFIG_SENSORS_LM95241=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SHT21=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMM665=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
+CONFIG_SENSORS_EMC2103=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_ADS7871=m
+CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=m
+CONFIG_SENSORS_TMP401=m
+CONFIG_SENSORS_TMP421=m
+CONFIG_SENSORS_VIA_CPUTEMP=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83795=m
+CONFIG_SENSORS_W83795_FANCTRL=y
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_LIS3_I2C=m
+CONFIG_SENSORS_APPLESMC=m
+# CONFIG_SENSORS_MC13783_ADC is not set
+
+#
+# ACPI drivers
+#
+CONFIG_SENSORS_ATK0110=m
+CONFIG_SENSORS_LIS3LV02D=m
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_F71808E_WDT=m
+CONFIG_SP5100_TCO=m
+CONFIG_GEODE_WDT=m
+CONFIG_SC520_WDT=m
+# CONFIG_SBC_FITPC2_WATCHDOG is not set
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_WAFER_WDT=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_ITCO_WDT=m
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_IT8712F_WDT=m
+CONFIG_IT87_WDT=m
+# CONFIG_HP_WATCHDOG is not set
+CONFIG_SC1200_WDT=m
+CONFIG_PC87413_WDT=m
+CONFIG_NV_TCO=m
+CONFIG_60XX_WDT=m
+CONFIG_SBC8360_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_SMSC_SCH311X_WDT=m
+CONFIG_SMSC37B787_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83697HF_WDT=m
+CONFIG_W83697UG_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+CONFIG_SSB_SDIOHOST=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_MFD_SUPPORT=y
+CONFIG_MFD_CORE=m
+CONFIG_MFD_SM501=m
+# CONFIG_MFD_SM501_GPIO is not set
+CONFIG_HTC_PASIC3=m
+CONFIG_UCB1400_CORE=m
+CONFIG_TPS65010=m
+CONFIG_TPS6507X=m
+# CONFIG_MFD_TMIO is not set
+CONFIG_MFD_WM8400=m
+# CONFIG_MFD_WM831X_SPI is not set
+CONFIG_MFD_PCF50633=m
+CONFIG_MFD_MC13783=m
+CONFIG_MFD_MC13XXX=m
+CONFIG_PCF50633_ADC=m
+CONFIG_PCF50633_GPIO=m
+CONFIG_ABX500_CORE=y
+# CONFIG_EZX_PCAP is not set
+# CONFIG_AB8500_CORE is not set
+CONFIG_MFD_CS5535=m
+CONFIG_MFD_TIMBERDALE=m
+CONFIG_LPC_SCH=m
+CONFIG_MFD_RDC321X=m
+CONFIG_MFD_JANZ_CMODIO=m
+CONFIG_MFD_VX855=m
+CONFIG_MFD_WL1273_CORE=m
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_REGULATOR_BQ24022=m
+CONFIG_REGULATOR_MAX1586=m
+CONFIG_REGULATOR_MAX8649=m
+CONFIG_REGULATOR_MAX8660=m
+CONFIG_REGULATOR_MAX8952=m
+CONFIG_REGULATOR_WM8400=m
+CONFIG_REGULATOR_PCF50633=m
+CONFIG_REGULATOR_LP3971=m
+CONFIG_REGULATOR_LP3972=m
+CONFIG_REGULATOR_MC13XXX_CORE=m
+CONFIG_REGULATOR_MC13783=m
+CONFIG_REGULATOR_MC13892=m
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_ISL6271A=m
+# CONFIG_REGULATOR_AD5398 is not set
+CONFIG_REGULATOR_TPS6524X=m
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_RC_CORE=m
+CONFIG_LIRC=m
+CONFIG_RC_MAP=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_RC5_SZ_DECODER=m
+CONFIG_IR_LIRC_CODEC=m
+# CONFIG_IR_ENE is not set
+CONFIG_IR_IMON=m
+# CONFIG_IR_MCEUSB is not set
+# CONFIG_IR_NUVOTON is not set
+# CONFIG_IR_STREAMZAP is not set
+CONFIG_IR_WINBOND_CIR=m
+CONFIG_RC_LOOPBACK=m
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_MEDIA_TUNER_TDA18218=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_V4L2_MEM2MEM_DEV=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+
+#
+# RDS decoders
+#
+CONFIG_VIDEO_SAA6588=m
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_ADV7180=m
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_BT866=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_MT9V011=m
+CONFIG_VIDEO_TCM825X=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_SAA7191=m
+CONFIG_VIDEO_TVP514X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_TVP7002=m
+CONFIG_VIDEO_VPX3220=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_THS7303=m
+CONFIG_VIDEO_ADV7343=m
+CONFIG_VIDEO_AK881X=m
+
+#
+# Video improvement chips
+#
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+# CONFIG_VIDEO_CPIA2 is not set
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_ZR36060=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_RC=y
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_TIMBERDALE=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_MPEG=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CX18_ALSA=m
+CONFIG_VIDEO_SAA7164=m
+CONFIG_VIDEO_CAFE_CCIC=m
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_VIA_CAMERA is not set
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_IMX074 is not set
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9T031=m
+CONFIG_SOC_CAMERA_MT9T112=m
+CONFIG_SOC_CAMERA_MT9V022=m
+CONFIG_SOC_CAMERA_RJ54N1=m
+CONFIG_SOC_CAMERA_TW9910=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_SOC_CAMERA_OV2640=m
+# CONFIG_SOC_CAMERA_OV6650 is not set
+CONFIG_SOC_CAMERA_OV772X=m
+CONFIG_SOC_CAMERA_OV9640=m
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+# CONFIG_USB_GSPCA_KONICA is not set
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+# CONFIG_USB_GSPCA_SQ930X is not set
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_RC=y
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_USB_ET61X251=m
+CONFIG_USB_SN9C102=m
+# CONFIG_USB_PWC is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MEM2MEM_TESTDEV=m
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_I2C_SI4713 is not set
+# CONFIG_RADIO_SI4713 is not set
+CONFIG_USB_DSBR=m
+# CONFIG_RADIO_SI470X is not set
+CONFIG_USB_MR800=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_TIMBERDALE=m
+CONFIG_RADIO_WL1273=m
+CONFIG_DVB_MAX_ADAPTERS=8
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_CE6230=m
+# CONFIG_DVB_USB_FRIIO is not set
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_AZ6027=m
+# CONFIG_DVB_USB_LME2510 is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_SMS_SIANO_MDTV=m
+
+#
+# Siano module components
+#
+CONFIG_SMS_USB_DRV=m
+CONFIG_SMS_SDIO_DRV=m
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported SDMC DM1105 Adapters
+#
+CONFIG_DVB_DM1105=m
+CONFIG_DVB_FIREDTV=m
+CONFIG_DVB_FIREDTV_FIREWIRE=y
+# CONFIG_DVB_FIREDTV_IEEE1394 is not set
+CONFIG_DVB_FIREDTV_INPUT=y
+
+#
+# Supported Earthsoft PT1 Adapters
+#
+# CONFIG_DVB_PT1 is not set
+
+#
+# Supported Mantis Adapters
+#
+CONFIG_MANTIS_CORE=m
+CONFIG_DVB_MANTIS=m
+CONFIG_DVB_HOPPER=m
+
+#
+# Supported nGene Adapters
+#
+CONFIG_DVB_NGENE=m
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+CONFIG_DVB_STV090x=m
+CONFIG_DVB_STV6110x=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10036=m
+CONFIG_DVB_ZL10039=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_STV6110=m
+CONFIG_DVB_STV0900=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_MB86A16=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+CONFIG_DVB_DIB8000=m
+CONFIG_DVB_MB86A20S=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_TDA665x=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+CONFIG_AGP=m
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_INTEL=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_VIA=m
+# CONFIG_VGA_ARB is not set
+CONFIG_VGA_SWITCHEROO=y
+CONFIG_DRM=m
+CONFIG_DRM_KMS_HELPER=m
+CONFIG_DRM_TTM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+# CONFIG_DRM_RADEON_KMS is not set
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+# CONFIG_DRM_I915_KMS is not set
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+# CONFIG_STUB_POULSBO is not set
+CONFIG_VGASTATE=m
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=m
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=m
+# CONFIG_FB_WMT_GE_ROPS is not set
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_HECUBA=m
+CONFIG_FB_SVGALIB=m
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+CONFIG_FB_PM2=m
+CONFIG_FB_PM2_FIFO_DISCONNECT=y
+CONFIG_FB_CYBER2000=m
+CONFIG_FB_ARC=m
+CONFIG_FB_VGA16=m
+CONFIG_FB_UVESA=m
+CONFIG_FB_N411=m
+CONFIG_FB_HGA=m
+CONFIG_FB_S1D13XXX=m
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_LE80578=m
+CONFIG_FB_CARILLO_RANCH=m
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_INTEL_I2C=y
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_S3=m
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+CONFIG_FB_SIS=m
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+CONFIG_FB_VIA=m
+# CONFIG_FB_VIA_DIRECT_PROCFS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_3DFX_I2C=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_VT8623=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_ARK=m
+CONFIG_FB_PM3=m
+CONFIG_FB_CARMINE=m
+CONFIG_FB_CARMINE_DRAM_EVAL=y
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
+CONFIG_FB_GEODE=y
+CONFIG_FB_GEODE_LX=m
+CONFIG_FB_GEODE_GX=m
+CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_TMIO=m
+CONFIG_FB_TMIO_ACCELL=y
+CONFIG_FB_SM501=m
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_XEN_FBDEV_FRONTEND=m
+CONFIG_FB_METRONOME=m
+CONFIG_FB_MB862XX=m
+# CONFIG_FB_MB862XX_PCI_GDC is not set
+CONFIG_FB_BROADSHEET=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_L4F00242T03=m
+CONFIG_LCD_LMS283GF05=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_ILI9320=m
+CONFIG_LCD_TDO24M=m
+CONFIG_LCD_VGG2432A4=m
+CONFIG_LCD_PLATFORM=m
+CONFIG_LCD_S6E63M0=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_PROGEAR=m
+CONFIG_BACKLIGHT_CARILLO_RANCH=m
+CONFIG_BACKLIGHT_MBP_NVIDIA=m
+CONFIG_BACKLIGHT_SAHARA=m
+CONFIG_BACKLIGHT_ADP8860=m
+CONFIG_BACKLIGHT_PCF50633=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_RAWMIDI_SEQ=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_PCSP=m
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_ALOOP is not set
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ASIHPI=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_CTXFI=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_INDIGOIOX=m
+CONFIG_SND_INDIGODJX=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_ES1968_INPUT=y
+CONFIG_SND_FM801=m
+# CONFIG_SND_FM801_TEA575X_BOOL is not set
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDA_HWDEP=y
+# CONFIG_SND_HDA_RECONFIG is not set
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_INPUT_BEEP_MODE=0
+CONFIG_SND_HDA_INPUT_JACK=y
+# CONFIG_SND_HDA_PATCH_LOADER is not set
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_CODEC_HDMI=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_GENERIC=y
+# CONFIG_SND_HDA_POWER_SAVE is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_LX6464ES=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MAESTRO3_INPUT=y
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+# CONFIG_SND_USB_CAIAQ_INPUT is not set
+CONFIG_SND_USB_US122L=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_PDAUDIOCF=m
+CONFIG_SND_SOC=m
+# CONFIG_SND_SOC_CACHE_LZO is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+CONFIG_SND_SOC_ALL_CODECS=m
+CONFIG_SND_SOC_WM_HUBS=m
+CONFIG_SND_SOC_AD1836=m
+CONFIG_SND_SOC_AD193X=m
+CONFIG_SND_SOC_AD73311=m
+CONFIG_SND_SOC_ADS117X=m
+CONFIG_SND_SOC_AK4104=m
+CONFIG_SND_SOC_AK4535=m
+CONFIG_SND_SOC_AK4642=m
+CONFIG_SND_SOC_AK4671=m
+CONFIG_SND_SOC_ALC5623=m
+CONFIG_SND_SOC_CS42L51=m
+CONFIG_SND_SOC_CS4270=m
+CONFIG_SND_SOC_CX20442=m
+CONFIG_SND_SOC_L3=m
+CONFIG_SND_SOC_DA7210=m
+CONFIG_SND_SOC_MAX98088=m
+CONFIG_SND_SOC_PCM3008=m
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_SSM2602=m
+CONFIG_SND_SOC_TLV320AIC23=m
+CONFIG_SND_SOC_TLV320AIC26=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_TLV320DAC33=m
+CONFIG_SND_SOC_UDA134X=m
+CONFIG_SND_SOC_UDA1380=m
+CONFIG_SND_SOC_WL1273=m
+CONFIG_SND_SOC_WM8400=m
+CONFIG_SND_SOC_WM8510=m
+CONFIG_SND_SOC_WM8523=m
+CONFIG_SND_SOC_WM8580=m
+CONFIG_SND_SOC_WM8711=m
+CONFIG_SND_SOC_WM8727=m
+CONFIG_SND_SOC_WM8728=m
+CONFIG_SND_SOC_WM8731=m
+CONFIG_SND_SOC_WM8737=m
+CONFIG_SND_SOC_WM8741=m
+CONFIG_SND_SOC_WM8750=m
+CONFIG_SND_SOC_WM8753=m
+CONFIG_SND_SOC_WM8770=m
+CONFIG_SND_SOC_WM8776=m
+CONFIG_SND_SOC_WM8804=m
+CONFIG_SND_SOC_WM8900=m
+CONFIG_SND_SOC_WM8903=m
+CONFIG_SND_SOC_WM8904=m
+CONFIG_SND_SOC_WM8940=m
+CONFIG_SND_SOC_WM8955=m
+CONFIG_SND_SOC_WM8960=m
+CONFIG_SND_SOC_WM8961=m
+CONFIG_SND_SOC_WM8962=m
+CONFIG_SND_SOC_WM8971=m
+CONFIG_SND_SOC_WM8974=m
+CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_WM8985=m
+CONFIG_SND_SOC_WM8988=m
+CONFIG_SND_SOC_WM8990=m
+CONFIG_SND_SOC_WM8993=m
+CONFIG_SND_SOC_WM8995=m
+CONFIG_SND_SOC_WM9081=m
+CONFIG_SND_SOC_MAX9877=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SOC_WM2000=m
+CONFIG_SND_SOC_WM9090=m
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_3M_PCT=m
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+CONFIG_HID_CANDO=m
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_PRODIKEYS=m
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+CONFIG_HID_EGALAX=m
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+CONFIG_HID_MAGICMOUSE=m
+# CONFIG_HID_MICROSOFT is not set
+CONFIG_HID_MOSART=m
+# CONFIG_HID_MONTEREY is not set
+CONFIG_HID_MULTITOUCH=m
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_ORTEK=m
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_ROCCAT_KONE=m
+CONFIG_HID_ROCCAT_KONEPLUS=m
+# CONFIG_HID_ROCCAT_PYRA is not set
+# CONFIG_HID_SAMSUNG is not set
+CONFIG_HID_SONY=m
+CONFIG_HID_STANTUM=m
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_HID_ZYDACRON=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+CONFIG_USB_WUSB=m
+CONFIG_USB_WUSB_CBAF=m
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_XHCI_HCD=m
+# CONFIG_USB_XHCI_HCD_DEBUGGING is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OXU210HP_HCD=m
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_ISP1760_HCD=m
+CONFIG_USB_ISP1362_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_SSB=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_WHCI_HCD=m
+CONFIG_USB_HWA_HCD=m
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+# CONFIG_USB_UAS is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7715_PARPORT=y
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_SAMBA is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+# CONFIG_USB_SERIAL_SSU100 is not set
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+# CONFIG_USB_LEGOTOWER is not set
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+# CONFIG_USB_TRANCEVIBRATOR is not set
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=m
+CONFIG_NOP_USB_XCEIV=m
+CONFIG_UWB=m
+CONFIG_UWB_HWA=m
+CONFIG_UWB_WHCI=m
+CONFIG_UWB_I1480U=m
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+CONFIG_MMC_TEST=m
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_SDHCI_PCI=m
+CONFIG_MMC_RICOH_MMC=y
+CONFIG_MMC_SDHCI_PLTFM=m
+CONFIG_MMC_WBSD=m
+CONFIG_MMC_TIFM_SD=m
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_SDRICOH_CS=m
+CONFIG_MMC_CB710=m
+CONFIG_MMC_VIA_SDMMC=m
+# CONFIG_MMC_USHC is not set
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_NET5501=m
+CONFIG_LEDS_ALIX2=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+CONFIG_LEDS_LP3944=m
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+CONFIG_LEDS_CLEVO_MAIL=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_REGULATOR=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_INTEL_SS4200=m
+CONFIG_LEDS_LT3593=m
+CONFIG_LEDS_DELL_NETBOOKS=m
+# CONFIG_LEDS_MC13783 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_NFC_DEVICES is not set
+CONFIG_ACCESSIBILITY=y
+# CONFIG_A11Y_BRAILLE_CONSOLE is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+# CONFIG_INFINIBAND_IPATH is not set
+# CONFIG_INFINIBAND_QIB is not set
+CONFIG_INFINIBAND_AMSO1100=m
+# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_INFINIBAND_CXGB4=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_INFINIBAND_NES=m
+# CONFIG_INFINIBAND_NES_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_TEST=m
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+# CONFIG_RTC_DRV_DS3232 is not set
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+# CONFIG_RTC_DRV_ISL12022 is not set
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=m
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8581=m
+CONFIG_RTC_DRV_RX8025=m
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_DS3234=m
+CONFIG_RTC_DRV_PCF2123=m
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=m
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_PCF50633=m
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_MC13XXX is not set
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_INTEL_MID_DMAC is not set
+CONFIG_INTEL_IOATDMA=m
+CONFIG_TIMB_DMA=m
+CONFIG_PCH_DMA=m
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+# CONFIG_ASYNC_TX_DMA is not set
+CONFIG_DMATEST=m
+CONFIG_DCA=m
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+CONFIG_CFAG12864B=m
+CONFIG_CFAG12864B_RATE=20
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+# CONFIG_UIO_PCI_GENERIC is not set
+CONFIG_UIO_NETX=m
+
+#
+# Xen driver support
+#
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DEV_EVTCHN=y
+CONFIG_XEN_BACKEND=y
+CONFIG_XENFS=y
+CONFIG_XEN_COMPAT_XENFS=y
+CONFIG_XEN_SYS_HYPERVISOR=y
+CONFIG_XEN_XENBUS_FRONTEND=y
+CONFIG_XEN_GNTDEV=m
+CONFIG_XEN_PLATFORM_PCI=m
+CONFIG_SWIOTLB_XEN=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_ET131X is not set
+# CONFIG_SLICOSS is not set
+# CONFIG_VIDEO_GO7007 is not set
+# CONFIG_VIDEO_CX25821 is not set
+# CONFIG_VIDEO_TM6000 is not set
+CONFIG_USB_DABUSB=m
+CONFIG_USB_SE401=m
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_W35UND is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+CONFIG_BRCM80211=m
+CONFIG_BRCM80211_PCI=y
+# CONFIG_BRCMFMAC is not set
+# CONFIG_RT2860 is not set
+# CONFIG_RT2870 is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_PANEL is not set
+# CONFIG_R8187SE is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTL8192E is not set
+# CONFIG_R8712U is not set
+# CONFIG_TRANZPORT is not set
+# CONFIG_POHMELFS is not set
+CONFIG_AUTOFS_FS=m
+# CONFIG_IDE_PHISON is not set
+# CONFIG_LINE6_USB is not set
+CONFIG_DRM_VMWGFX=m
+CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_NOUVEAU_BACKLIGHT=y
+CONFIG_DRM_NOUVEAU_DEBUG=y
+
+#
+# I2C encoder or helper chips
+#
+# CONFIG_DRM_I2C_CH7006 is not set
+CONFIG_DRM_I2C_SIL164=m
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+CONFIG_HYPERV=m
+CONFIG_HYPERV_STORAGE=m
+CONFIG_HYPERV_BLOCK=m
+CONFIG_HYPERV_NET=m
+CONFIG_HYPERV_UTILS=m
+# CONFIG_VME_BUS is not set
+# CONFIG_DX_SEP is not set
+# CONFIG_IIO is not set
+# CONFIG_ZRAM is not set
+# CONFIG_WLAGS49_H2 is not set
+# CONFIG_WLAGS49_H25 is not set
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_VIDEO_DT3155 is not set
+# CONFIG_CRYSTALHD is not set
+# CONFIG_CXT1E1 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_ST_BT is not set
+# CONFIG_FB_XGI is not set
+# CONFIG_LIRC_STAGING is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_EASYCAP is not set
+# CONFIG_SOLO6X10 is not set
+# CONFIG_ACPI_QUICKSTART is not set
+CONFIG_MACH_NO_WESTBRIDGE=y
+# CONFIG_SBE_2T3E3 is not set
+# CONFIG_ATH6K_LEGACY is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_ACER_WMI=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_DELL_LAPTOP=m
+CONFIG_DELL_WMI=m
+CONFIG_FUJITSU_LAPTOP=m
+# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
+CONFIG_HP_WMI=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+# CONFIG_SONYPI_COMPAT is not set
+# CONFIG_IDEAPAD_LAPTOP is not set
+CONFIG_THINKPAD_ACPI=m
+CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y
+# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_SENSORS_HDAPS=m
+CONFIG_INTEL_MENLOW=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_EEEPC_WMI=m
+CONFIG_ACPI_WMI=m
+CONFIG_MSI_WMI=m
+CONFIG_ACPI_ASUS=m
+# CONFIG_TOPSTAR_LAPTOP is not set
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_TOSHIBA_BT_RFKILL=m
+CONFIG_ACPI_CMPC=m
+# CONFIG_INTEL_IPS is not set
+# CONFIG_IBM_RTL is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+# CONFIG_EDD_OFF is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+CONFIG_DMIID=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=m
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_QUOTACTL_COMPAT=y
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_HISTOGRAM=y
+# CONFIG_FSCACHE_DEBUG is not set
+# CONFIG_FSCACHE_OBJECT_LIST is not set
+CONFIG_CACHEFILES=m
+# CONFIG_CACHEFILES_DEBUG is not set
+# CONFIG_CACHEFILES_HISTOGRAM is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=m
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_LOGFS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_LZO is not set
+CONFIG_SQUASHFS_XZ=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_EXOFS_FS=m
+# CONFIG_EXOFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+# CONFIG_NFS_FSCACHE is not set
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_DEPRECATED=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_XPRT_RDMA=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_CEPH_FS=m
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_DFS_UPCALL=y
+# CONFIG_CIFS_FSCACHE is not set
+# CONFIG_CIFS_ACL is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_BKL=y
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LKDTM is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_RING_BUFFER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_TEST_KSTRTOX=m
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_DEBUG_SET_MODULE_RONX=y
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_OPTIMIZE_INLINING is not set
+
+#
+# Linux VServer
+#
+CONFIG_VSERVER_AUTO_LBACK=y
+CONFIG_VSERVER_AUTO_SINGLE=y
+CONFIG_VSERVER_COWBL=y
+# CONFIG_VSERVER_VTIME is not set
+# CONFIG_VSERVER_DEVICE is not set
+CONFIG_VSERVER_PROC_SECURE=y
+# CONFIG_TAGGING_NONE is not set
+# CONFIG_TAGGING_UID16 is not set
+# CONFIG_TAGGING_GID16 is not set
+CONFIG_TAGGING_ID24=y
+# CONFIG_TAGGING_INTERN is not set
+# CONFIG_TAG_NFSD is not set
+# CONFIG_VSERVER_PRIVACY is not set
+CONFIG_VSERVER_CONTEXTS=768
+CONFIG_VSERVER_WARN=y
+CONFIG_VSERVER_WARN_DEVPTS=y
+# CONFIG_VSERVER_DEBUG is not set
+# CONFIG_VSERVER_LEGACY_MEM is not set
+CONFIG_QUOTES_ISO8859=y
+# CONFIG_QUOTES_UTF8 is not set
+# CONFIG_QUOTES_ASCII is not set
+CONFIG_VSERVER=y
+CONFIG_VSERVER_SECURITY=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_TRUSTED_KEYS=m
+CONFIG_ENCRYPTED_KEYS=m
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_IMA is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y
+CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_FPU=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C_INTEL=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_AES_NI_INTEL=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SALSA20_X86_64=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_TWOFISH_X86_64=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_USER_API=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_APIC_ARCHITECTURE=y
+CONFIG_KVM_MMIO=y
+CONFIG_KVM_ASYNC_PF=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_KVM_AMD=m
+CONFIG_VHOST_NET=m
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_BTREE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_NLATTR=y
+CONFIG_AVERAGE=y
diff --git a/main/live-media/APKBUILD b/main/live-media/APKBUILD
new file mode 100644
index 0000000000..a9871f4286
--- /dev/null
+++ b/main/live-media/APKBUILD
@@ -0,0 +1,47 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=live-media
+pkgver=2011.01.24
+pkgrel=0
+pkgdesc="A set of C++ libraries for multimedia streaming"
+url="http://live555.com/liveMedia"
+arch="all"
+license="LGPL"
+depends=
+makedepends=
+subpackages="$pkgname-dev"
+source="http://live555.com/liveMedia/public/live.$pkgver.tar.gz"
+
+_builddir="$srcdir"/live
+
+prepare() {
+ cd "$_builddir"
+ sed -e "/^COMPILE_OPTS/s/$/ $CFLAGS -fPIC -DPIC/" \
+ -e 's/\(LIBRARY_LINK =\).*/\1 $(LD) -o/g' \
+ -e 's/\(LIBRARY_LINK_OPTS =\).*/\1 $(LINK_OPTS) -r -Bstatic/g' \
+ -i config.linux
+}
+
+build() {
+ cd "$_builddir"
+ ./genMakefiles linux
+ make C_COMPILER="${CC:-gcc}" CPLUSPLUS_COMPILER="${CXX:-g++}" \
+ || return 1
+}
+
+package() {
+ local dir
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/lib
+ for f in BasicUsageEnvironment UsageEnvironment liveMedia groupsock; do
+ mkdir -p "$pkgdir"/usr/include/$f
+ cp $f/include/*.h* "$pkgdir"/usr/include/$f
+ cp $f/lib${f}.a "$pkgdir"/usr/lib
+ done
+
+ mkdir -p "$pkgdir"/usr/bin
+ for testprog in `find testProgs -type f -perm 755`; do
+ install ${testprog} "$pkgdir"/usr/bin
+ done
+}
+
+md5sums="0626e80c774fb27c651c3daf6cc3fb91 live.2011.01.24.tar.gz"
diff --git a/main/lm_sensors/APKBUILD b/main/lm_sensors/APKBUILD
new file mode 100644
index 0000000000..83b16539e4
--- /dev/null
+++ b/main/lm_sensors/APKBUILD
@@ -0,0 +1,74 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lm_sensors
+pkgver=3.3.0
+pkgrel=0
+pkgdesc="Collection of user space tools for general SMBus access and hardware monitoring."
+url="http://www.lm-sensors.org/"
+arch="all"
+license="GPL"
+depends="sysfsutils rrdtool"
+makedepends="perl rrdtool-dev bison flex"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-detect"
+#install=sensors.install
+source="http://dl.lm-sensors.org/lm-sensors/releases/$pkgname-$pkgver.tar.bz2
+ lm_sensors-3.1.0-sensors-detect-alpine.patch
+ fancontrol.initd
+ lm_sensors.initd
+ sensord.confd
+ sensord.initd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ sed -i -e 's:^# \(PROG_EXTRA\):\1:' Makefile
+ # Respect LDFLAGS
+ sed -i -e 's/\$(LIBDIR)$/\$(LIBDIR) \$(LDFLAGS)/g' Makefile
+ sed -i -e 's/\$(LIBSHSONAME) -o/$(LIBSHSONAME) \$(LDFLAGS) -o/g' \
+ lib/Module.mk
+
+ # do not check for libiconv in ldconfig cache
+ sed -i -e 's/^LIBICONV.*/LIBICONV ?=/' prog/sensors/Module.mk || return 1
+
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ export CFLAGS="$CFLAGS -fno-stack-protector"
+ make PREFIX=/usr user || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make user_install \
+ PREFIX=/usr \
+ MANDIR=/usr/share/man \
+ DESTDIR="$pkgdir" || return 1
+
+ cd "$srcdir"
+ install -Dm755 fancontrol.initd "$pkgdir"/etc/init.d/fancontrol
+ install -Dm755 lm_sensors.initd "$pkgdir"/etc/init.d/lm_sensors
+ install -Dm755 sensord.initd "$pkgdir"/etc/init.d/sensord
+ install -Dm755 sensord.confd "$pkgdir"/etc/conf.d/sensord
+}
+
+detect() {
+ depends="perl"
+ pkgdesc="Detection/migration scripts for lm_sensors"
+ mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/usr/sbin
+ cd "$pkgdir"
+ mv usr/bin/sensors-conf-convert "$subpkgdir"/usr/bin/
+ mv usr/sbin/sensors-detect "$subpkgdir"/usr/bin/
+}
+
+md5sums="5eb18d7531ead4f54f28a1133a606535 lm_sensors-3.3.0.tar.bz2
+b6e7de1a1768f7a6ea2e00c226331877 lm_sensors-3.1.0-sensors-detect-alpine.patch
+58f4c9193a903711ace7fa0754693bd2 fancontrol.initd
+2c7e97203da2c39bc9fbfc2a4849cfd4 lm_sensors.initd
+82e075236a61334abb3adf46280380d3 sensord.confd
+6f3a880988e7cdbcb20870e3c6d1e554 sensord.initd"
diff --git a/main/lm_sensors/fancontrol.initd b/main/lm_sensors/fancontrol.initd
new file mode 100644
index 0000000000..fb163abc23
--- /dev/null
+++ b/main/lm_sensors/fancontrol.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-apps/lm_sensors/files/fancontrol-init.d,v 1.1 2007/05/17 07:31:41 phreak Exp $
+
+CONFIG=/etc/fancontrol
+PID=/var/run/fancontrol.pid
+
+depend() {
+ after lm_sensors
+}
+
+checkconfig() {
+ if [ ! -f ${CONFIG} ]; then
+ eerror "Configuration file ${CONFIG} not found"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting fancontrol"
+ start-stop-daemon --start --quiet --background --pidfile ${PID} \
+ --exec /usr/sbin/fancontrol -- ${CONFIG}
+ eend ${?}
+}
+
+stop() {
+ ebegin "Stopping fancontrol"
+ start-stop-daemon --stop --pidfile ${PID}
+ eend ${?}
+}
diff --git a/main/lm_sensors/lm_sensors-3.1.0-sensors-detect-alpine.patch b/main/lm_sensors/lm_sensors-3.1.0-sensors-detect-alpine.patch
new file mode 100644
index 0000000000..9271c6bac2
--- /dev/null
+++ b/main/lm_sensors/lm_sensors-3.1.0-sensors-detect-alpine.patch
@@ -0,0 +1,39 @@
+diff -ru lm_sensors-3.1.0.orig/prog/detect/sensors-detect lm_sensors-3.1.0/prog/detect/sensors-detect
+--- lm_sensors-3.1.0.orig/prog/detect/sensors-detect 2009-04-14 07:14:22.000000000 +0000
++++ lm_sensors-3.1.0/prog/detect/sensors-detect 2009-04-14 07:44:48.000000000 +0000
+@@ -5282,19 +5282,24 @@
+ }
+ }
+
+- my $have_sysconfig = -d '/etc/sysconfig';
+- printf "Do you want to \%s /etc/sysconfig/lm_sensors? (\%s): ",
+- (-e '/etc/sysconfig/lm_sensors' ? 'overwrite' : 'generate'),
+- ($have_sysconfig ? 'YES/no' : 'yes/NO');
++ my $config = '/etc/conf.d/lm_sensors';
++ my $have_config = -f $config;
++ printf "Do you want to \%s \%s? (\%s): ",
++ (-e $config ? 'overwrite' : 'generate'),
++ $config,
++ ($have_config ? 'YES/no' : 'yes/NO');
+ $_ = <STDIN>;
+- if (($have_sysconfig and not m/^\s*n/i) or m/^\s*y/i) {
+- unless ($have_sysconfig) {
+- mkdir('/etc/sysconfig', 0777)
+- or die "Sorry, can't create /etc/sysconfig ($!)";
+- }
+- open(local *SYSCONFIG, ">/etc/sysconfig/lm_sensors")
+- or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)";
++ if (($have_config and not m/^\s*n/i) or m/^\s*y/i) {
++ open(local *SYSCONFIG, ">$config")
++ or die "Sorry, can't create $config ($!)";
+ print SYSCONFIG "# Generated by sensors-detect on " . scalar localtime() . "\n";
++ print SYSCONFIG
++ "\n".
++ "# Load modules at startup\n".
++ "LOADMODULES=yes\n\n".
++ "# Initialize sensors at startup\n".
++ "INITSENSORS=yes\n\n";
++
+ print SYSCONFIG <<'EOT';
+ # This file is sourced by /etc/init.d/lm_sensors and defines the modules to
+ # be loaded/unloaded.
diff --git a/main/lm_sensors/lm_sensors.initd b/main/lm_sensors/lm_sensors.initd
new file mode 100644
index 0000000000..18fb353706
--- /dev/null
+++ b/main/lm_sensors/lm_sensors.initd
@@ -0,0 +1,105 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-apps/lm_sensors/files/lm_sensors-3-init.d,v 1.1 2008/03/17 07:59:28 dberkholz Exp $
+
+checkconfig() {
+ if [ ! -f /etc/conf.d/lm_sensors ]; then
+ eerror "/etc/conf.d/lm_sensors does not exist, try running sensors-detect"
+ return 1
+ fi
+
+ if [ "${LOADMODULES}" = "yes" -a -f /proc/modules ]; then
+ if [ -z "${MODULE_0}" ]; then
+ eerror "MODULE_0 is not set in /etc/conf.d/lm_sensors, try running sensors-detect"
+ return 1
+ fi
+ fi
+}
+
+start() {
+ checkconfig || return 1
+
+ if [ "${LOADMODULES}" = "yes" -a -f /proc/modules ]; then
+ einfo "Loading lm_sensors modules..."
+
+ mount | grep sysfs >/dev/null 2>&1
+ if [ ${?} = 0 ]; then
+ if ! ( [ -e /sys/i2c ] || [ -e /sys/bus/i2c ] ); then
+ ebegin " Loading i2c-core"
+ modprobe i2c-core >/dev/null 2>&1
+ if [ ${?} != 0 ]; then
+ eerror " Could not load i2c-core!"
+ eend 1
+ fi
+ ( [ -e /sys/i2c ] || [ -e /sys/bus/i2c ] ) || return 1
+ eend 0
+ fi
+ elif ! [ -e /proc/sys/dev/sensors ]; then
+ ebegin " Loading i2c-proc"
+ modprobe i2c-proc >/dev/null 2>&1
+ if [ ${?} != 0 ]; then
+ eerror " Could not load i2c-proc!"
+ eend 1
+ fi
+ [ -e /proc/sys/dev/sensors ] || return 1
+ eend 0
+ fi
+
+ i=0
+ while true; do
+ module=`eval echo '$'MODULE_${i}`
+ module_args=`eval echo '$'MODULE_${i}_ARGS`
+ if [ -z "${module}" ]; then
+ break
+ fi
+ ebegin " Loading ${module}"
+ modprobe ${module} ${module_args} >/dev/null 2>&1
+ eend $?
+ i=$(($i+1))
+ done
+ fi
+
+ if [ "${INITSENSORS}" = "yes" ]; then
+ if ! [ -f /etc/sensors3.conf ]; then
+ eerror "/etc/sensors3.conf does not exist!"
+ return 1
+ fi
+
+ ebegin "Initializing sensors"
+ /usr/bin/sensors -s >/dev/null 2>&1
+ eend ${?}
+ fi
+}
+
+stop() {
+ checkconfig || return 1
+
+ if [ "${LOADMODULES}" = "yes" -a -f /proc/modules ]; then
+ einfo "Unloading lm_sensors modules..."
+
+ # find the highest possible MODULE_ number
+ i=0
+ while true; do
+ module=`eval echo '$'MODULE_${i}`
+ if [ -z "${module}" ] ; then
+ break
+ fi
+ i=$(($i+1))
+ done
+
+ while [ ${i} -gt 0 ]; do
+ i=$(($i-1))
+ module=`eval echo '$'MODULE_${i}`
+ ebegin " Unloading ${module}"
+ rmmod ${module} >/dev/null 2>&1
+ eend $?
+ done
+
+ if [ -e /proc/sys/dev/sensors ] ; then
+ ebegin " Unloading i2c-proc"
+ rmmod i2c-proc >/dev/null 2>&1
+ eend $?
+ fi
+ fi
+}
diff --git a/main/lm_sensors/sensord.confd b/main/lm_sensors/sensord.confd
new file mode 100644
index 0000000000..d82841aebd
--- /dev/null
+++ b/main/lm_sensors/sensord.confd
@@ -0,0 +1,3 @@
+# Extra options to pass to the sensord daemon,
+# see sensord(8) for more information
+SENSORD_OPTIONS=""
diff --git a/main/lm_sensors/sensord.initd b/main/lm_sensors/sensord.initd
new file mode 100644
index 0000000000..cb99dce3f0
--- /dev/null
+++ b/main/lm_sensors/sensord.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-apps/lm_sensors/files/sensord-init.d,v 1.1 2007/05/17 07:31:41 phreak Exp $
+
+CONFIG=/etc/sensors.conf
+
+depend() {
+ need logger
+ use lm_sensors
+}
+
+checkconfig() {
+ if [ ! -f ${CONFIG} ]; then
+ eerror "Configuration file ${CONFIG} not found"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting sensord"
+ start-stop-daemon --start --exec /usr/sbin/sensord \
+ -- --config-file ${CONFIG} ${SENSORD_OPTIONS}
+ eend ${?}
+}
+
+stop() {
+ ebegin "Stopping sensord"
+ start-stop-daemon --stop --pidfile /var/run/sensord.pid
+ eend ${?}
+}
diff --git a/main/lm_sensors/sensors.install b/main/lm_sensors/sensors.install
new file mode 100644
index 0000000000..d593f84144
--- /dev/null
+++ b/main/lm_sensors/sensors.install
@@ -0,0 +1,12 @@
+post_install() {
+ echo ">>> to control the lm_sensors daemon type"
+ echo ">>> \"/etc/rc.d/sensors start|stop|restart\" "
+ echo ">>> --------------------------------------"
+ echo ">>> before you can use the fancontrol daemon"
+ echo ">>> first create a fancontrol config file, use \"pwmconfig\""
+ echo ">>> then type \"/etc/rc.d/fancontrol start|stop|restart\" "
+ echo ">>> --------------------------------------"
+ echo ">>> to decode memory SPD timings modprobe eeprom module"
+ echo ">>> and get this perl script from"
+ echo ">>> \"http://www.lm-sensors.org/browser/lm-sensors/trunk/prog/eeprom/decode-dimms.pl\""
+}
diff --git a/main/lockfile-progs/APKBUILD b/main/lockfile-progs/APKBUILD
new file mode 100644
index 0000000000..a1c5aad9f8
--- /dev/null
+++ b/main/lockfile-progs/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Duane Hughes <duanejevon@gmail.com
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lockfile-progs
+pkgver=0.1.15
+pkgrel=0
+pkgdesc="Programs for locking and unlocking files and mailboxes"
+url="http://packages.debian.org/sid/lockfile-progs"
+arch="all"
+license="GPL"
+depends="liblockfile"
+makedepends="liblockfile-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://ftp.debian.org/debian/pool/main/l/lockfile-progs/${pkgname}_$pkgver.tar.gz"
+
+_builddir="$srcdir"/sid
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ install -d "$pkgdir"/usr/bin
+ install -d "$pkgdir"/usr/share/man
+ install -m 755 "$_builddir"/bin/* "$pkgdir"/usr/bin
+ install -m 644 "$_builddir"/man/* "$pkgdir"/usr/share/man
+}
+
+md5sums="abfcda83a1868073673f4d78066b8f8a lockfile-progs_0.1.15.tar.gz"
diff --git a/main/logcheck/APKBUILD b/main/logcheck/APKBUILD
new file mode 100644
index 0000000000..e437f2c788
--- /dev/null
+++ b/main/logcheck/APKBUILD
@@ -0,0 +1,30 @@
+# Contributor: Duane Hughes <duanejevon@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=logcheck
+pkgver=1.3.13
+pkgrel=0
+pkgdesc="Bash scripts used to monitor system log files for anomalies"
+url="http://packages.debian.org/source/sid/logcheck"
+arch="noarch"
+license="GPL"
+depends="lockfile-progs"
+makedepends=
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages="$pkgname-doc"
+source="http://ftp.debian.org/debian/pool/main/l/logcheck/${pkgname}_$pkgver.tar.gz
+ logcheck.cron.d
+ "
+
+_builddir="$srcdir"/$pkgname
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ install -D -m 644 "$srcdir"/logcheck.cron.d "$pkgdir"/etc/logcheck/logcheck.cron.sample
+ install -d "$pkgdir"/usr/share/man
+ cp -a "$_builddir"/docs/* "$pkgdir"/usr/share/man
+}
+
+md5sums="e2ff14f522bf2e30d5947c85fed44973 logcheck_1.3.13.tar.gz
+89be84c722a958659df9a937826cbdc2 logcheck.cron.d"
diff --git a/main/logcheck/logcheck.cron.d b/main/logcheck/logcheck.cron.d
new file mode 100644
index 0000000000..58cd047bb6
--- /dev/null
+++ b/main/logcheck/logcheck.cron.d
@@ -0,0 +1,9 @@
+# /etc/cron.d/logcheck: crontab entries for the logcheck package
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+MAILTO=root
+
+@reboot logcheck if [ -x /usr/sbin/logcheck ]; then nice -n10 /usr/sbin/logcheck -R; fi
+2 * * * * logcheck if [ -x /usr/sbin/logcheck ]; then nice -n10 /usr/sbin/logcheck; fi
+
+# EOF
diff --git a/main/logcheck/logcheck.post-install b/main/logcheck/logcheck.post-install
new file mode 100644
index 0000000000..c3439021c3
--- /dev/null
+++ b/main/logcheck/logcheck.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+chown -R logcheck /etc/logcheck /var/lock/logcheck /var/lib/logcheck
diff --git a/main/logcheck/logcheck.pre-install b/main/logcheck/logcheck.pre-install
new file mode 100644
index 0000000000..d6ea64154d
--- /dev/null
+++ b/main/logcheck/logcheck.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup logcheck 2>/dev/null
+adduser -S -H -h /dev/null -s /bin/false -D -G logcheck logcheck 2>/dev/null
+exit 0
diff --git a/main/logrotate/APKBUILD b/main/logrotate/APKBUILD
new file mode 100644
index 0000000000..517023bbf0
--- /dev/null
+++ b/main/logrotate/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=logrotate
+pkgver=3.7.9
+pkgrel=2
+pkgdesc="Tool to rotate logfiles"
+url="https://fedorahosted.org/logrotate/"
+arch="all"
+license="GPL"
+depends=
+makedepends="popt-dev wget"
+subpackages="$pkgname-doc"
+source="https://fedorahosted.org/releases/l/o/logrotate/logrotate-$pkgver.tar.gz
+ logrotate-3.7.9-atomic-create.patch
+ logrotate-3.7.9-shred.patch
+ logrotate-3.7.9-statefile.patch
+ logrotate.conf"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ install -d "$pkgdir"/etc/logrotate.d
+ install -Dm755 logrotate "$pkgdir"/usr/sbin/logrotate
+ install -Dm644 logrotate.8 "$pkgdir"/usr/share/man/man8/logrotate.8
+ install -Dm644 ../logrotate.conf "$pkgdir"/etc/logrotate.conf
+ install -Dm755 examples/logrotate.cron "$pkgdir"/etc/periodic/daily/logrotate
+}
+
+md5sums="eeba9dbca62a9210236f4b83195e4ea5 logrotate-3.7.9.tar.gz
+0273f868dc4208eed0a442759d86e77c logrotate-3.7.9-atomic-create.patch
+74216579397b03c44d1d85dd233306d8 logrotate-3.7.9-shred.patch
+82ebd23da8a7f0650a4c80577dbdc739 logrotate-3.7.9-statefile.patch
+fef6415a79a6fede8cf9b9b6b8410090 logrotate.conf"
diff --git a/main/logrotate/logrotate-3.7.9-atomic-create.patch b/main/logrotate/logrotate-3.7.9-atomic-create.patch
new file mode 100644
index 0000000000..b888dc0231
--- /dev/null
+++ b/main/logrotate/logrotate-3.7.9-atomic-create.patch
@@ -0,0 +1,70 @@
+diff --git a/logrotate.c b/logrotate.c
+index 3748918..fbe232a 100644
+--- a/logrotate.c
++++ b/logrotate.c
+@@ -194,31 +194,41 @@ static int runScript(char *logfn, char *script)
+ int createOutputFile(char *fileName, int flags, struct stat *sb)
+ {
+ int fd;
++ char template[PATH_MAX + 1];
++ mode_t umask_value;
++ snprintf(template, PATH_MAX, "%s/logrotate_temp.XXXXXX", ourDirName(fileName));
++
++ umask_value = umask(0000);
++ fd = mkstemp(template);
++ umask(umask_value);
++
++ if (fd < 0) {
++ message(MESS_ERROR, "error creating unique temp file: %s\n",
++ strerror(errno));
++ return -1;
++ }
++
++ if (fchown(fd, sb->st_uid, sb->st_gid)) {
++ message(MESS_ERROR, "error setting owner of %s: %s\n",
++ fileName, strerror(errno));
++ close(fd);
++ return -1;
++ }
++
++ if (fchmod(fd, sb->st_mode)) {
++ message(MESS_ERROR, "error setting mode of %s: %s\n",
++ fileName, strerror(errno));
++ close(fd);
++ return -1;
++ }
++
++ if (rename(template, fileName)) {
++ message(MESS_ERROR, "error renaming temp file to %s: %s\n",
++ fileName, strerror(errno));
++ close(fd);
++ return -1;
++ }
+
+- fd = open(fileName, flags, sb->st_mode);
+- if (fd < 0) {
+- message(MESS_ERROR, "error creating output file %s: %s\n",
+- fileName, strerror(errno));
+- return -1;
+- }
+- if (fchmod(fd, (S_IRUSR | S_IWUSR) & sb->st_mode)) {
+- message(MESS_ERROR, "error setting mode of %s: %s\n",
+- fileName, strerror(errno));
+- close(fd);
+- return -1;
+- }
+- if (fchown(fd, sb->st_uid, sb->st_gid)) {
+- message(MESS_ERROR, "error setting owner of %s: %s\n",
+- fileName, strerror(errno));
+- close(fd);
+- return -1;
+- }
+- if (fchmod(fd, sb->st_mode)) {
+- message(MESS_ERROR, "error setting mode of %s: %s\n",
+- fileName, strerror(errno));
+- close(fd);
+- return -1;
+- }
+ return fd;
+ }
+
diff --git a/main/logrotate/logrotate-3.7.9-shred.patch b/main/logrotate/logrotate-3.7.9-shred.patch
new file mode 100644
index 0000000000..d9780007f3
--- /dev/null
+++ b/main/logrotate/logrotate-3.7.9-shred.patch
@@ -0,0 +1,151 @@
+Index: logrotate.c
+===================================================================
+--- logrotate.c (revision 310)
++++ logrotate.c (working copy)
+@@ -71,7 +71,7 @@
+ char *mailCommand = DEFAULT_MAIL_COMMAND;
+ time_t nowSecs = 0;
+
+-static int shred_file(char *filename, struct logInfo *log);
++static int shred_file(int fd, char *filename, struct logInfo *log);
+
+ static int globerr(const char *pathname, int theerr)
+ {
+@@ -231,59 +231,79 @@
+ return fd;
+ }
+
+-#define SHRED_CALL "shred -u "
+-#define SHRED_COUNT_FLAG "-n "
+ #define DIGITS 10
++
+ /* unlink, but try to call shred from GNU fileutils */
+-static int shred_file(char *filename, struct logInfo *log)
++static int shred_file(int fd, char *filename, struct logInfo *log)
+ {
+- int len, ret;
+- char *cmd;
+ char count[DIGITS]; /* that's a lot of shredding :) */
++ const char **fullCommand;
++ int id = 0;
++ int status;
+
+ if (!(log->flags & LOG_FLAG_SHRED)) {
+ return unlink(filename);
+ }
+
+- len = strlen(filename) + strlen(SHRED_CALL);
+- len += strlen(SHRED_COUNT_FLAG) + DIGITS;
+- cmd = malloc(len);
++ message(MESS_DEBUG, "Using shred to remove the file %s\n", filename);
+
+- if (!cmd) {
+- message(MESS_ERROR, "malloc error while shredding");
+- return unlink(filename);
++ if (log->shred_cycles != 0) {
++ fullCommand = alloca(sizeof(*fullCommand) * 6);
+ }
+- strcpy(cmd, SHRED_CALL);
++ else {
++ fullCommand = alloca(sizeof(*fullCommand) * 4);
++ }
++ fullCommand[id++] = "shred";
++ fullCommand[id++] = "-u";
++
+ if (log->shred_cycles != 0) {
+- strcat(cmd, SHRED_COUNT_FLAG);
++ fullCommand[id++] = "-n";
+ snprintf(count, DIGITS - 1, "%d", log->shred_cycles);
+- strcat(count, " ");
+- strcat(cmd, count);
++ fullCommand[id++] = count;
+ }
+- strcat(cmd, filename);
+- ret = system(cmd);
+- free(cmd);
+- if (ret != 0) {
++ fullCommand[id++] = "-";
++ fullCommand[id++] = NULL;
++
++ if (!fork()) {
++ dup2(fd, 1);
++ close(fd);
++
++ execvp(fullCommand[0], (void *) fullCommand);
++ exit(1);
++ }
++
++ wait(&status);
++
++ if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+ message(MESS_ERROR, "Failed to shred %s\n, trying unlink", filename);
+- if (ret != -1) {
+- message(MESS_NORMAL, "Shred returned %d\n", ret);
+- }
+ return unlink(filename);
+- } else {
+- return ret;
+ }
++
++ /* We have to unlink it after shred anyway,
++ * because it doesn't remove the file itself */
++ return unlink(filename);
+ }
+
+ static int removeLogFile(char *name, struct logInfo *log)
+ {
+- message(MESS_DEBUG, "removing old log %s\n", name);
++ int fd;
++ message(MESS_DEBUG, "removing old log %s\n", name);
+
+- if (!debug && shred_file(name, log)) {
+- message(MESS_ERROR, "Failed to remove old log %s: %s\n",
+- name, strerror(errno));
+- return 1;
+- }
+- return 0;
++ if ((fd = open(name, O_RDWR)) < 0) {
++ message(MESS_ERROR, "error opening %s: %s\n",
++ name, strerror(errno));
++ return 1;
++ }
++
++ if (!debug && shred_file(fd, name, log)) {
++ message(MESS_ERROR, "Failed to remove old log %s: %s\n",
++ name, strerror(errno));
++ close(fd);
++ return 1;
++ }
++
++ close(fd);
++ return 0;
+ }
+
+ static int compressLogFile(char *name, struct logInfo *log, struct stat *sb)
+@@ -310,7 +330,7 @@
+ compressedName = alloca(strlen(name) + strlen(log->compress_ext) + 2);
+ sprintf(compressedName, "%s%s", name, log->compress_ext);
+
+- if ((inFile = open(name, O_RDONLY)) < 0) {
++ if ((inFile = open(name, O_RDWR)) < 0) {
+ message(MESS_ERROR, "unable to open %s for compression\n", name);
+ return 1;
+ }
+@@ -357,7 +377,6 @@
+ exit(1);
+ }
+
+- close(inFile);
+ close(outFile);
+
+ wait(&status);
+@@ -373,7 +392,8 @@
+ /* If we can't change atime/mtime, it's not a disaster.
+ It might possibly fail under SELinux. */
+
+- shred_file(name, log);
++ shred_file(inFile, name, log);
++ close(inFile);
+
+ return 0;
+ }
diff --git a/main/logrotate/logrotate-3.7.9-statefile.patch b/main/logrotate/logrotate-3.7.9-statefile.patch
new file mode 100644
index 0000000000..daa02402fa
--- /dev/null
+++ b/main/logrotate/logrotate-3.7.9-statefile.patch
@@ -0,0 +1,96 @@
+Index: logrotate.c
+===================================================================
+--- logrotate.c (revision 314)
++++ logrotate.c (working copy)
+@@ -45,6 +45,12 @@
+ #define GLOB_ABORTED GLOB_ABEND
+ #endif
+
++#ifdef PATH_MAX
++#define STATEFILE_BUFFER_SIZE 2 * PATH_MAX + 16
++#else
++#define STATEFILE_BUFFER_SIZE 4096
++#endif
++
+ struct logState {
+ char *fn;
+ struct tm lastRotated; /* only tm.mon, tm_mday, tm_year are good! */
+@@ -82,6 +88,34 @@
+ return 1;
+ }
+
++static void unescape(char *arg)
++{
++ char *p = arg;
++ char *next;
++ char escaped;
++ while ((next = strchr(p, '\\')) != NULL) {
++
++ p = next;
++
++ switch (p[1]) {
++ case 'n':
++ escaped = '\n';
++ break;
++ case '\\':
++ escaped = '\\';
++ break;
++ default:
++ ++p;
++ continue;
++ }
++
++ /* Overwrite the backslash with the intended character,
++ * and shift everything down one */
++ *p++ = escaped;
++ memmove(p, p+1, 1 + strlen(p+1));
++ }
++}
++
+ #define HASH_SIZE_MIN 64
+ static int allocateHash(void)
+ {
+@@ -1546,7 +1580,13 @@
+ for (chptr = p->fn; *chptr; chptr++) {
+ switch (*chptr) {
+ case '"':
++ case '\\':
+ fputc('\\', f);
++ break;
++ case '\n':
++ fputc('\\', f);
++ fputc('n', f);
++ continue;
+ }
+
+ fputc(*chptr, f);
+@@ -1567,7 +1607,8 @@
+ static int readState(char *stateFilename)
+ {
+ FILE *f;
+- char buf[1024];
++ char buf[STATEFILE_BUFFER_SIZE];
++ char *filename;
+ const char **argv;
+ int argc;
+ int year, month, day;
+@@ -1678,7 +1719,10 @@
+
+ year -= 1900, month -= 1;
+
+- if ((st = findState(argv[0])) == NULL)
++ filename = strdup(argv[0]);
++ unescape(filename);
++
++ if ((st = findState(filename)) == NULL)
+ return 1;
+
+ st->lastRotated.tm_mon = month;
+@@ -1690,6 +1734,7 @@
+ st->lastRotated = *localtime(&lr_time);
+
+ free(argv);
++ free(filename);
+ }
+
+ fclose(f);
diff --git a/main/logrotate/logrotate.conf b/main/logrotate/logrotate.conf
new file mode 100644
index 0000000000..125268ae80
--- /dev/null
+++ b/main/logrotate/logrotate.conf
@@ -0,0 +1,20 @@
+# see "man logrotate" for details
+# rotate log files weekly
+weekly
+
+# keep 4 weeks worth of backlogs
+rotate 4
+
+# create new (empty) log files after rotating old ones
+create
+
+# use date as a suffix of the rotated file
+dateext
+
+# uncomment this if you want your log files compressed
+compress
+
+# apk packages drop log rotation information into this directory
+include /etc/logrotate.d
+
+# system-specific logs may be also be configured here.
diff --git a/main/lsof/APKBUILD b/main/lsof/APKBUILD
new file mode 100644
index 0000000000..e2536cd0ab
--- /dev/null
+++ b/main/lsof/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lsof
+pkgver=4.84
+pkgrel=1
+pkgdesc="LiSt Open Files"
+url="http://people.freebsd.org/~abe/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends=""
+source="ftp://sunsite.ualberta.ca/pub/Mirror/$pkgname/${pkgname}_$pkgver.tar.bz2"
+
+_builddir="$srcdir"/${pkgname}_${pkgver}/${pkgname}_${pkgver}_src
+
+prepare() {
+ # theres a tarball in teh tarball...
+ cd "$srcdir"/${pkgname}_${pkgver}
+ tar -xf ${pkgname}_${pkgver}_src.tar
+
+ cd "$_builddir"
+ sed -e "s|/\* #define\tHASSECURITY\t1 \*/|#define\tHASSECURITY\t1|" \
+ -i dialects/linux/machine.h
+}
+
+build () {
+ cd "$_builddir"
+ ./Configure -n linux
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -D -m0755 -o root -g root lsof "$pkgdir"/usr/sbin/lsof
+ install -D -m0644 -o root -g root lsof.8 \
+ "$pkgdir"/usr/share/man/man8/lsof.8
+}
+md5sums="a09326df500ef7e4550af546868338d6 lsof_4.84.tar.bz2"
diff --git a/main/lsscsi/APKBUILD b/main/lsscsi/APKBUILD
new file mode 100644
index 0000000000..84d65b4296
--- /dev/null
+++ b/main/lsscsi/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=lsscsi
+pkgver=0.24b1
+pkgrel=1
+pkgdesc="Lists information about SCSI devices"
+url="http://sg.danny.cz/scsi/lsscsi.html"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://sg.danny.cz/scsi/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+#prepare() {
+# cd "$_builddir"
+# apply patches here
+#}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="897114e504c7b606edb9dd7114b68020 lsscsi-0.24b1.tgz"
diff --git a/main/lsyncd/APKBUILD b/main/lsyncd/APKBUILD
new file mode 100644
index 0000000000..61a797cf3f
--- /dev/null
+++ b/main/lsyncd/APKBUILD
@@ -0,0 +1,52 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lsyncd
+pkgver=2.0.4
+pkgrel=2
+pkgdesc="Live Syncing (Mirror) Daemon"
+url="http://code.google.com/p/lsyncd/"
+arch="all"
+license="GPLv2+"
+depends="rsync"
+depends_dev=
+makedepends="$depends_dev lua-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://lsyncd.googlecode.com/files/lsyncd-$pkgver.tar.gz
+ $pkgname.initd"
+
+_builddir="$srcdir"/lsyncd-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ mkdir -p "$pkgdir/etc/lsyncd"
+ cp "$_builddir"/examples/*.lua \
+ "$pkgdir"/etc/lsyncd/
+ install -Dm755 "$srcdir/$pkgname.initd" \
+ "$pkgdir/etc/init.d/$pkgname" || return 1
+
+}
+
+md5sums="0b4557dd3d87a02ae0cbd7b5fc16cd0c lsyncd-2.0.4.tar.gz
+b3d38982ef1a6e09a76586418ec6c35d lsyncd.initd"
diff --git a/main/lsyncd/lsyncd.initd b/main/lsyncd/lsyncd.initd
new file mode 100644
index 0000000000..5578b1a2af
--- /dev/null
+++ b/main/lsyncd/lsyncd.initd
@@ -0,0 +1,32 @@
+#!/sbin/runscript
+
+NAME=lsyncd
+DAEMON=/usr/bin/$NAME
+PIDFILE=/var/run/$NAME.pid
+USER=root
+GROUP=root
+CONF=/etc/lsyncd/lsyncd.lua
+
+depend() {
+ need net
+}
+
+start() {
+ touch "$PIDFILE"
+ chown $USER:$GROUP "$PIDFILE"
+ ebegin "Starting $NAME"
+ start-stop-daemon --start --quiet \
+ --pidfile "$PIDFILE" \
+ --user "$USER" --group "$GROUP" \
+ --chdir /etc/lsyncd \
+ --exec "$DAEMON" -- \
+ "$CONF" -pidfile "$PIDFILE"
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping $NAME"
+ start-stop-daemon --stop --quiet \
+ --pidfile "$PIDFILE"
+ eend $?
+}
diff --git a/main/ltrace/APKBUILD b/main/ltrace/APKBUILD
new file mode 100644
index 0000000000..c6503a8d76
--- /dev/null
+++ b/main/ltrace/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ltrace
+pkgver=0.5.3
+pkgrel=1
+pkgdesc="Tracks runtime library calls in dynamically linked programs"
+url="http://ltrace.alioth.debian.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="libelf-dev"
+subpackages="$pkgname-doc"
+source="http://ftp.debian.org/debian/pool/main/l/$pkgname/${pkgname}_$pkgver.orig.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make install INSTALL=install DESTDIR="$pkgdir" || return 1
+}
+md5sums="3fa7fe715ab879db08bd06d1d59fd90f ltrace_0.5.3.orig.tar.gz"
diff --git a/main/lua-alt-getopt/APKBUILD b/main/lua-alt-getopt/APKBUILD
new file mode 100644
index 0000000000..5fc0da4a5b
--- /dev/null
+++ b/main/lua-alt-getopt/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinlinux.org>
+pkgname=lua-alt-getopt
+pkgver=0.7.0
+pkgrel=1
+pkgdesc="Lua module for processing options similar to getopt_long(3)"
+url="http://luaforge.net/projects/alt-getopt/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends=
+install=
+subpackages=
+source="http://mova.org/~cheusov/pub/lua_alt_getopt/lua-alt-getopt-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+}
+
+package() {
+ cd "$_builddir"
+ install -Dm644 alt_getopt.lua "$pkgdir"/usr/share/lua/5.1/alt_getopt.lua
+}
+
+md5sums="f504578b1287ea02759add231b972812 lua-alt-getopt-0.7.0.tar.gz"
diff --git a/main/lua-bitlib/APKBUILD b/main/lua-bitlib/APKBUILD
new file mode 100644
index 0000000000..709eaf0768
--- /dev/null
+++ b/main/lua-bitlib/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-bitlib
+_name=bitlib
+pkgver=26
+pkgrel=2
+pkgdesc="A lua library providing bitwise operations"
+url="http://luaforge.net/projects/bitlib"
+arch="all"
+license="MIT/X11"
+depends="lua"
+makedepends="lua-dev"
+subpackages="$pkgname-dev"
+source="http://luaforge.net/frs/download.php/4231/bitlib-26.tar.gz"
+replaces="bitlib"
+
+_builddir="$srcdir"/$_name-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="b76cb74aef951250f8fa7a65f39bb3d8 bitlib-26.tar.gz"
diff --git a/main/lua-discount/APKBUILD b/main/lua-discount/APKBUILD
new file mode 100644
index 0000000000..1736b0f77c
--- /dev/null
+++ b/main/lua-discount/APKBUILD
@@ -0,0 +1,23 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-discount
+pkgver=1.2.10.1
+pkgrel=2
+pkgdesc="Lua binding to discount, a Markdown implementation in C"
+url="http://asbradbury.org/projects/lua-discount"
+arch="all"
+license="BSD"
+depends="lua"
+makedepends="lua-dev"
+install=
+subpackages=
+source="http://luaforge.net/frs/download.php/3758/lua-discount-1.2.10.1.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ make || return 1
+ install -D -m644 discount.so "$pkgdir"/usr/lib/lua/5.1/discount.so
+}
+
+md5sums="7dc7055816dc755aacb48bfd5eb2eb5b lua-discount-1.2.10.1.tar.gz"
diff --git a/main/lua-dns/APKBUILD b/main/lua-dns/APKBUILD
new file mode 100644
index 0000000000..23f7d0497d
--- /dev/null
+++ b/main/lua-dns/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-dns
+pkgver=20080404
+pkgrel=1
+pkgdesc="a DNS client library written in Lua using LuaSocket"
+url="http://ztact.com/software/dns.lua"
+arch="noarch"
+license="GPL"
+depends="lua lua-socket"
+makedepends=
+install=
+subpackages=
+source="http://ztact.com/files/src/ztact-lua/dns.lua
+ http://ztact.com/files/src/ztact-lua/ztact.lua
+ "
+
+prepare() {
+ :
+}
+
+build() {
+ :
+}
+
+package() {
+ install -d "$pkgdir"/usr/share/lua/5.1
+ install -m 644 "$srcdir"/*.lua "$pkgdir"/usr/share/lua/5.1/
+}
+
+md5sums="8a085a4cf7accf2f6e798c507709bc78 dns.lua
+a83eb072dece91c5db043f5884ee00b0 ztact.lua"
diff --git a/main/lua-expat/APKBUILD b/main/lua-expat/APKBUILD
new file mode 100644
index 0000000000..5336e5ba35
--- /dev/null
+++ b/main/lua-expat/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=lua-expat
+_name=luaexpat
+pkgver=1.1
+pkgrel=2
+pkgdesc="LuaExpat is a SAX XML parser based on the Expat library. LuaExpat is free software and uses the same license as Lua 5.0."
+url="http://luaforge.net/projects/luaexpat/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends="lua-dev expat-dev"
+install=
+source="http://luaforge.net/frs/download.php/2469/$_name-$pkgver.tar.gz
+newconfig"
+replaces="luaexpat"
+
+build() {
+ cd "$srcdir/$_name-$pkgver"
+ mv ../newconfig ./config
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_name-$pkgver"
+ make LUA_DIR="$pkgdir"/usr/share/lua/5.1 LUA_LIBDIR="$pkgdir"/usr/lib/lua/5.1 install
+
+}
+
+md5sums="6ecb895ccf5cff1e7f2facd438b1f8d0 luaexpat-1.1.tar.gz
+eb947b7aa99b487289b02c1ab1b8ccd3 newconfig"
diff --git a/main/lua-expat/newconfig b/main/lua-expat/newconfig
new file mode 100644
index 0000000000..7d8d6331fc
--- /dev/null
+++ b/main/lua-expat/newconfig
@@ -0,0 +1,26 @@
+LUA_LIBDIR= usr/lib/lua/5.1
+LUA_DIR= usr/share/lua/5.1
+LUA_INC= /usr/include
+EXPAT_INC= /usr/include
+
+# OS dependent
+LIB_OPTION= -shared
+
+LIBNAME= $T.so.$V
+LUA_VERSION_NUM= 514
+COMPAT_DIR= ../compat/src
+
+# Compilation parameters
+CWARNS = -Wall -pedantic \
+ -Waggregate-return \
+ -Wcast-align \
+ -Wmissing-prototypes \
+ -Wstrict-prototypes \
+ -Wnested-externs \
+ -Wpointer-arith \
+ -Wshadow \
+ -Wwrite-strings
+
+CFLAGS = $(CWARNS) -ansi -O2 -I$(LUA_INC) \
+ -I$(COMPAT_DIR) -I$(EXPAT_INC)
+CC = gcc
diff --git a/main/lua-filesystem/APKBUILD b/main/lua-filesystem/APKBUILD
new file mode 100644
index 0000000000..eefd598175
--- /dev/null
+++ b/main/lua-filesystem/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-filesystem
+pkgver=1.5.0
+pkgrel=1
+pkgdesc="Lua library to complement the set of functions related to file systems"
+url="http://www.keplerproject.org/luafilesystem/"
+arch="all"
+license="GPL"
+depends=
+makedepends="lua-dev wget"
+install=
+subpackages=
+source="https://github.com/downloads/keplerproject/luafilesystem/luafilesystem-$pkgver.tar.gz"
+
+_builddir="$srcdir"/luafilesystem-$pkgver
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make LUA_LIBDIR="$pkgdir"/usr/lib/lua/5.1 install
+}
+
+md5sums="3cf4882bbce956e7a0b010f148f194a3 luafilesystem-1.5.0.tar.gz"
diff --git a/main/lua-iconv/0001-lua-iconv-make-close-available-from-lua.patch b/main/lua-iconv/0001-lua-iconv-make-close-available-from-lua.patch
new file mode 100644
index 0000000000..885c378367
--- /dev/null
+++ b/main/lua-iconv/0001-lua-iconv-make-close-available-from-lua.patch
@@ -0,0 +1,25 @@
+From 3281ed1babad138daa3ebe892b4f3d7ce5b9c85c Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Wed, 17 Feb 2010 08:54:06 +0000
+Subject: [PATCH] lua-iconv: make close() available from lua
+
+Seems like this was forgotten
+---
+ luaiconv.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/luaiconv.c b/luaiconv.c
+index 514f1fb..0c6ef06 100644
+--- a/luaiconv.c
++++ b/luaiconv.c
+@@ -204,6 +204,7 @@ static const luaL_reg inconvFuncs[] = {
+ { "open", Liconv_open },
+ { "new", Liconv_open },
+ { "iconv", Liconv },
++ { "close", Liconv_close },
+ #ifdef HAS_ICONVLIST
+ { "list", Liconvlist },
+ #endif
+--
+1.6.6.1
+
diff --git a/main/lua-iconv/APKBUILD b/main/lua-iconv/APKBUILD
new file mode 100644
index 0000000000..fd14aace1c
--- /dev/null
+++ b/main/lua-iconv/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor:
+# Maintainer:
+pkgname=lua-iconv
+pkgver=6
+pkgrel=2
+pkgdesc="Lua binding to the POSIX 'iconv' library"
+url="http://luaforge.net/projects/lua-iconv/"
+arch="all"
+license="MIT"
+depends=
+makedepends="libiconv-dev lua-dev"
+install=
+subpackages=
+source="http://luaforge.net/frs/download.php/4181/lua-iconv-6.tar.gz
+ 0001-lua-iconv-make-close-available-from-lua.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -p1 -i "$srcdir"/0001-lua-iconv-make-close-available-from-lua.patch
+}
+
+build() {
+ cd "$_builddir"
+ make CFLAGS="$CFLAGS" LFLAGS="-llua -liconv -shared $LDFLAGS" \
+ || return 1
+}
+
+package() {
+ cd "$_builddir"
+ # tests fail
+ # make DESTDIR="$pkgdir" INSTALL_PATH=/usr/lib/lua/5.1 install
+ install -D -s iconv.so "$pkgdir"/usr/lib/lua/5.1/iconv.so
+}
+
+md5sums="2cec334c5786d7c420a53003d6cb93d4 lua-iconv-6.tar.gz
+88e23691e79f357a6048f226e8ed8e23 0001-lua-iconv-make-close-available-from-lua.patch"
diff --git a/main/lua-imlib2/APKBUILD b/main/lua-imlib2/APKBUILD
new file mode 100644
index 0000000000..56fa02b28a
--- /dev/null
+++ b/main/lua-imlib2/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-imlib2
+pkgver=0.1
+pkgrel=1
+pkgdesc="A LUA binding to the Imlib2 image manipulation library"
+url="http://asbradbury.org/projects/lua-imlib2/"
+arch="all"
+license="MIT"
+depends=
+makedepends="lua-dev imlib2-dev"
+install=
+source="http://luaforge.net/frs/download.php/3042/lua-imlib2-$pkgver.tar.gz"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -D limlib2.so "$pkgdir"/usr/lib/lua/5.1/limlib2.so
+ install -D imlib2.lua "$pkgdir"/usr/share/lua/5.1/imlib2.lua
+}
+
+md5sums="f90d5d70ea8af6b66ee2e3071a08ec00 lua-imlib2-0.1.tar.gz"
diff --git a/main/lua-json4/APKBUILD b/main/lua-json4/APKBUILD
new file mode 100644
index 0000000000..332f49ad34
--- /dev/null
+++ b/main/lua-json4/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-json4
+_name=json4lua
+pkgver=0.9.20
+pkgrel=1
+pkgdesc="JSON encoding / decoding module for Lua (JSON4lua)"
+url="http://json.luaforge.net/"
+arch="all"
+license="GPL-2"
+depends="lua"
+source="http://luaforge.net/frs/download.php/1375/JSON4Lua-$pkgver.zip"
+replaces="json4lua"
+
+build() {
+ # do nothing, but keep it to make abuild happy
+ :
+}
+
+package() {
+ install -D "$srcdir"/json/json.lua "$pkgdir"/usr/share/lua/5.1/json.lua
+}
+
+md5sums="0a2071a24d7752f52d5cc9cac8800743 JSON4Lua-0.9.20.zip"
diff --git a/main/lua-lgob/0001-poppler-reflect-the-poppler_page_get_text-API-change.patch b/main/lua-lgob/0001-poppler-reflect-the-poppler_page_get_text-API-change.patch
new file mode 100644
index 0000000000..177c26b653
--- /dev/null
+++ b/main/lua-lgob/0001-poppler-reflect-the-poppler_page_get_text-API-change.patch
@@ -0,0 +1,42 @@
+From 096324789b3471be367c3075b51204b94cd70905 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Thu, 30 Dec 2010 08:06:52 +0000
+Subject: [PATCH] poppler: reflect the poppler_page_get_text API change
+
+http://cgit.freedesktop.org/poppler/poppler/commit/?id=b257428150e2c13dcc24fd8f75e4ee2c679ab414
+---
+ poppler/src/poppler.def | 11 ++++++++++-
+ 1 files changed, 10 insertions(+), 1 deletions(-)
+
+diff --git a/poppler/src/poppler.def b/poppler/src/poppler.def
+index fbe20de..255587a 100644
+--- a/poppler/src/poppler.def
++++ b/poppler/src/poppler.def
+@@ -1499,7 +1499,7 @@ defFunction('poppler_page_render_to_ps',
+ }
+ )
+
+-defFunction('poppler_page_get_text',
++defFunction('poppler_page_get_selected_text',
+ {
+ class = 'PopplerPage',
+ since = '0.1',
+@@ -1508,6 +1508,15 @@ defFunction('poppler_page_get_text',
+ }
+ )
+
++defFunction('poppler_page_get_text',
++ {
++ class = 'PopplerPage',
++ since = '0.1',
++ args = {'GObject* none'},
++ ret = 'char* full'
++ }
++)
++
+ defFunction('poppler_page_get_selection_region',
+ {
+ class = 'PopplerPage',
+--
+1.7.3.4
+
diff --git a/main/lua-lgob/APKBUILD b/main/lua-lgob/APKBUILD
new file mode 100644
index 0000000000..629e0f2d02
--- /dev/null
+++ b/main/lua-lgob/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-lgob
+pkgver=11.04
+pkgrel=1
+pkgdesc="Set of Lua bindings that uses gobject-instrospection"
+url="http://oproj.tuxfamily.org"
+arch="all"
+license="GPL-3"
+depends="lua"
+makedepends="lua-dev cairo-dev gtk+-dev pango-dev vte-dev gtkspell-dev
+ webkit-dev atk-dev gstreamer-dev gst-plugins-base-dev poppler-gtk-dev
+ gtksourceview-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.tuxfamily.org/oproj/lgob/lgob-$pkgver.tar.bz2
+ 0001-poppler-reflect-the-poppler_page_get_text-API-change.patch
+ "
+
+# 'goocanvas', 'clutter', 'cluttergtk'
+_mods="codegen common gobject loader cairo gdk gtk pango pangocairo vte webkit
+ atk gst gtkspell gtksourceview poppler"
+_builddir="$srcdir"/lgob-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/lgob-$pkgver
+}
+
+package() {
+ cd "$srcdir"/lgob-$pkgver
+ for i in $_mods; do
+ ./build.lua $i "$pkgdir"/usr || return 1
+ done
+ mkdir -p "$pkgdir"/usr/share/doc/$pkgname
+ cp -r examples "$pkgdir"/usr/share/doc/$pkgname/
+}
+
+md5sums="1e943299ab2462e4d9d9c4443d65fafb lgob-11.04.tar.bz2
+4042ebd70fb247f6f8fc1bd17ca11ea3 0001-poppler-reflect-the-poppler_page_get_text-API-change.patch"
diff --git a/main/lua-md5/APKBUILD b/main/lua-md5/APKBUILD
new file mode 100644
index 0000000000..9901639ea4
--- /dev/null
+++ b/main/lua-md5/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname="lua-md5"
+_name="md5"
+pkgver=1.1.2
+pkgrel=2
+pkgdesc="Basic cryptographic facilities for Lua"
+url="http://www.keplerproject.org/md5/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends="lua-dev"
+source="http://luaforge.net/frs/download.php/3355/$_name-$pkgver.tar.gz"
+replaces="md5"
+
+build() {
+ cd "$srcdir/$_name-$pkgver"
+ make CFLAGS="$CFLAGS" || return 1
+}
+
+package() {
+ cd "$srcdir/$_name-$pkgver"
+ make PREFIX="$pkgdir"/usr install
+}
+
+md5sums="68874cff64547f2157d5ecdc3572b544 md5-1.1.2.tar.gz"
diff --git a/main/lua-openrc/APKBUILD b/main/lua-openrc/APKBUILD
new file mode 100644
index 0000000000..aa69615f60
--- /dev/null
+++ b/main/lua-openrc/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor:
+# Maintainer:
+pkgname=lua-openrc
+pkgver=0.1
+pkgrel=3
+pkgdesc="Lua module for OpenRC"
+url="http://git.alpinelinux.org/cgit/lua-openrc/"
+arch="all"
+license="GPL"
+depends=lua
+makedepends="lua-dev openrc-dev"
+install=
+subpackages=
+source="http://git.alpinelinux.org/cgit/lua-openrc.git/snapshot/lua-openrc-$pkgver.tar.bz2"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -Dm755 rc.so "$pkgdir"/usr/lib/lua/5.1/rc.so
+}
+
+md5sums="9a9ace6b5567179852b1ee04196a0ec3 lua-openrc-0.1.tar.bz2"
diff --git a/main/lua-pc/APKBUILD b/main/lua-pc/APKBUILD
new file mode 100644
index 0000000000..65933a677c
--- /dev/null
+++ b/main/lua-pc/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-pc
+_name=lpc
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="Lua Process Call"
+url="http://lua.net-core.org/sputnik.lua?p=Telesto:About"
+arch="all"
+license="MIT/X11"
+makedepends="lua-dev"
+depends="lua"
+source="http://lua.net-core.org/dl/telesto/lpc-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_name-$pkgver"
+ make CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS -shared"
+}
+
+package() {
+ cd "$srcdir/$_name-$pkgver"
+ # does not respect DESTDIR
+ make install PREFIX="$pkgdir"/usr
+}
+
+md5sums="d1516818de2d94ea0c9d748726cf0d72 lpc-1.0.0.tar.gz"
diff --git a/main/lua-penlight/APKBUILD b/main/lua-penlight/APKBUILD
new file mode 100644
index 0000000000..5ce6fa8dd4
--- /dev/null
+++ b/main/lua-penlight/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-penlight
+pkgver=0.9.0
+pkgrel=0
+pkgdesc="Lua libraries for extended operations on tables, lists and strings"
+url="http://penlight.luaforge.net/"
+arch="noarch"
+license="GPL"
+depends="lua-filesystem"
+makedepends="wget"
+install=
+subpackages="$pkgname-doc"
+source="https://github.com/downloads/stevedonovan/Penlight/penlight-$pkgver.zip"
+
+_builddir="$srcdir"/penlight-$pkgver
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/share/lua/5.1/ \
+ "$pkgdir"/usr/share/doc/$pkgname
+ cp -r lua/pl "$pkgdir"/usr/share/lua/5.1/
+ cp -r docs/* "$pkgdir"/usr/share/doc/$pkgname/
+ cp -r examples "$pkgdir"/usr/share/doc/$pkgname/
+}
+
+md5sums="06305bd0e846626d7b04150bdd587d26 penlight-0.9.0.zip"
diff --git a/main/lua-posix/APKBUILD b/main/lua-posix/APKBUILD
new file mode 100644
index 0000000000..14a99af687
--- /dev/null
+++ b/main/lua-posix/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-posix
+_name=luaposix
+pkgver=5.1.11
+pkgrel=0
+pkgdesc="POSIX library for Lua"
+url="http://luaforge.net/projects/luaposix/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends="lua-dev"
+source="http://luaforge.net/frs/download.php/4813/luaposix-$pkgver.tar.gz"
+replaces="luaposix"
+
+_builddir="$srcdir"/$_name
+build() {
+ cd "$_builddir"
+ make PREFIX=/usr || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make PREFIX=/usr DESTDIR="$pkgdir" install
+}
+
+md5sums="edb76911dbdabe98dec49e3d8a126227 luaposix-5.1.11.tar.gz"
diff --git a/main/lua-posixtz/APKBUILD b/main/lua-posixtz/APKBUILD
new file mode 100644
index 0000000000..238c7dd2f9
--- /dev/null
+++ b/main/lua-posixtz/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-posixtz
+pkgver=0.3
+pkgrel=0
+pkgdesc="Lua module to extract POSIX timezone from tzdata"
+url="http://git.alpinelinux.org/cgit/ncopa/posixtz.git/"
+arch="all"
+license="GPLv2"
+depends=
+makedepends="lua-dev"
+install=
+subpackages=
+source="http://git.alpinelinux.org/cgit/ncopa/posixtz.git/snapshot/posixtz-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/posixtz-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make core.so || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -D core.so "$pkgdir"/usr/lib/lua/5.1/posixtz/core.so
+ install -D posixtz.lua "$pkgdir"/usr/share/lua/5.1/posixtz.lua
+}
+
+md5sums="99efce32b3f870e1b071ce47f3a98a18 posixtz-0.3.tar.bz2"
diff --git a/main/lua-pty/APKBUILD b/main/lua-pty/APKBUILD
new file mode 100644
index 0000000000..0fc4b1d010
--- /dev/null
+++ b/main/lua-pty/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-pty
+_name=lpty
+pkgver=0.9.1
+_ver=${pkgver%.*}
+_pver=${pkgver##*.}
+pkgrel=1
+pkgdesc="Lua module to control other programs via PTYs."
+url="http://www.tset.de/lpty/"
+arch="all"
+license="MIT/X11"
+depends=
+makedepends="lua-dev"
+subpackages=
+source="http://www.tset.de/downloads/lpty-${_ver}-${_pver}.tar.gz"
+
+_builddir="$srcdir"/lpty-${_ver}-${_pver}
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ gcc -fPIC -shared -o lpty.so lpty.c
+}
+
+package() {
+ cd "$_builddir"
+ install -D lpty.so "$pkgdir"/usr/lib/lua/5.1/lpty.so
+}
+
+md5sums="936be0bb1018de37370df9c32eebb8bb lpty-0.9-1.tar.gz"
diff --git a/main/lua-rex/APKBUILD b/main/lua-rex/APKBUILD
new file mode 100644
index 0000000000..744570ceb1
--- /dev/null
+++ b/main/lua-rex/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-rex
+pkgver=2.5.2
+pkgrel=1
+pkgdesc="Lua bindings to regular expression library pcre and posix"
+url="http://lrexlib.luaforge.net/"
+arch="all"
+license="MIT"
+depends="lua-rex-pcre lua-rex-posix"
+makedepends="pcre-dev lua-dev"
+install=
+subpackages="$pkgname-pcre $pkgname-posix"
+source="http://luaforge.net/frs/download.php/4685/lrexlib-2.5.2.zip"
+
+_builddir="$srcdir"/lrexlib-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ sed -i -e "s/^MYCFLAGS.*/MYCFLAGS = $CFLAGS -fPIC/" src/defaults.mak
+ sed -i -e "s/^LD .*/LD = gcc/" \
+ src/common.mak
+}
+
+build() {
+ cd "$_builddir"
+ make -j1 -C src/pcre
+ make -j1 -C src/posix
+}
+
+package() {
+ mkdir -p "$pkgdir"
+}
+
+pcre() {
+ pkgdesc="Lua bindings to pcre regular expressions library"
+ cd "$_builddir"
+ install -d "$subpkgdir"/usr/lib/lua/5.1
+ cp -a src/pcre/rex_pcre.so* "$subpkgdir"/usr/lib/lua/5.1
+}
+
+posix() {
+ pkgdesc="Lua bindings to posix regular expressions library"
+ cd "$_builddir"
+ install -d "$subpkgdir"/usr/lib/lua/5.1
+ cp -a src/posix/rex_posix.so* "$subpkgdir"/usr/lib/lua/5.1
+}
+
+md5sums="f622dbbd4f552e8edfd3c9250ebb7e92 lrexlib-2.5.2.zip"
diff --git a/main/lua-sec/APKBUILD b/main/lua-sec/APKBUILD
new file mode 100644
index 0000000000..cb6874f012
--- /dev/null
+++ b/main/lua-sec/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-sec
+_name=luasec
+pkgver=0.4
+pkgrel=0
+pkgdesc="TLS/SSL Support for Lua"
+url="http://www.inf.puc-rio.br/~brunoos/luasec/"
+arch="all"
+license="MIT"
+depends="lua-socket"
+makedepends="lua-dev openssl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://www.inf.puc-rio.br/~brunoos/luasec/download/luasec-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_name-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make linux || return 1
+}
+
+package() {
+ _luasharedir=/usr/share/lua/5.1
+ _lualibdir=/usr/lib/lua/5.1
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/$_luasharedir "$pkgdir"/$_lualibdir
+ make LUAPATH="$pkgdir"/$_luasharedir \
+ LUACPATH="$pkgdir"/$_lualibdir \
+ install
+ mkdir -p "$pkgdir"/usr/share/doc/$pkgname
+ cp -r samples "$pkgdir"/usr/share/doc/$pkgname/
+}
+
+md5sums="712158d60207bdbb6215fc7e07d8db24 luasec-0.4.tar.gz"
diff --git a/main/lua-socket/APKBUILD b/main/lua-socket/APKBUILD
new file mode 100644
index 0000000000..5939dd425d
--- /dev/null
+++ b/main/lua-socket/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=lua-socket
+_name=luasocket
+pkgver=2.0.2
+pkgrel=2
+pkgdesc="Luasocket is the most comprehensive networking support library for the Lua language."
+url="http://luaforge.net/projects/luasocket/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends="lua-dev"
+install=
+source="http://luaforge.net/frs/download.php/2664/luasocket-$pkgver.tar.gz"
+replaces=luasocket
+
+build() {
+ cd "$srcdir/$_name-$pkgver"
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_name-$pkgver"
+ make INSTALL_TOP_SHARE="$pkgdir/usr/share/lua/5.1" INSTALL_TOP_LIB="$pkgdir/usr/lib/lua/5.1" install
+
+}
+
+md5sums="41445b138deb7bcfe97bff957503da8e luasocket-2.0.2.tar.gz"
diff --git a/main/lua-sql-mysql/APKBUILD b/main/lua-sql-mysql/APKBUILD
new file mode 100644
index 0000000000..7980797efb
--- /dev/null
+++ b/main/lua-sql-mysql/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <natanael.copa@gmail.com>
+pkgname=lua-sql-mysql
+_name=luasql-mysql
+pkgver=2.1.1
+pkgrel=3
+pkgdesc="MySQL driver for LuaSQL (luasql-mysql)"
+url="http://www.keplerproject.org/luasql/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends="lua-dev mysql-dev"
+install=
+subpackages=
+source="http://luaforge.net/frs/download.php/2686/luasql-$pkgver.tar.gz"
+replaces=luasql-mysql
+
+build() {
+ cd "$srcdir"/luasql-$pkgver
+
+ # The config has DRIVER_INCS but it seems like its not respected
+ # so we just fix the .c file
+ sed -i -e 's:^\#include "mysql.h":\#include <mysql/mysql.h>:' \
+ src/ls_mysql.c || return 1
+
+ make CFLAGS="$CFLAGS" T=mysql DRIVER_LIBS="-lmysqlclient" || return 1
+}
+
+package() {
+ cd "$srcdir"/luasql-$pkgver
+ install -D src/mysql.so "$pkgdir"/usr/lib/lua/5.1/luasql/mysql.so
+}
+
+md5sums="63bdd57de4b9d1be336ba112d8cb69eb luasql-2.1.1.tar.gz"
diff --git a/main/lua-sql-postgres/APKBUILD b/main/lua-sql-postgres/APKBUILD
new file mode 100644
index 0000000000..dd08ba193e
--- /dev/null
+++ b/main/lua-sql-postgres/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=lua-sql-postgres
+pkgver=2.1.1
+pkgrel=3
+pkgdesc="PostgreSQL driver for LuaSQL"
+url="http://www.keplerproject.org/luasql/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends="lua-dev postgresql-dev"
+install=
+subpackages=
+source="http://luaforge.net/frs/download.php/2686/luasql-$pkgver.tar.gz"
+replaces=luasql-postgres
+
+build() {
+ cd "$srcdir/luasql-$pkgver"
+ make CFLAGS="$CFLAGS" T=postgres DRIVER_LIBS="-lpq" || return 1
+}
+
+package() {
+ cd "$srcdir/luasql-$pkgver"
+ install -D src/postgres.so "$pkgdir"/usr/lib/lua/5.1/luasql/postgres.so
+}
+
+md5sums="63bdd57de4b9d1be336ba112d8cb69eb luasql-2.1.1.tar.gz"
diff --git a/main/lua-sql-sqlite3/APKBUILD b/main/lua-sql-sqlite3/APKBUILD
new file mode 100644
index 0000000000..faaaa2b789
--- /dev/null
+++ b/main/lua-sql-sqlite3/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <natanael.copa@gmail.com>
+pkgname=lua-sql-sqlite3
+pkgver=2.1.1
+pkgrel=3
+pkgdesc="LuaSQL driver for sqlite3"
+url="http://www.keplerproject.org/luasql/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends="lua-dev sqlite-dev"
+install=
+subpackages=
+source="http://luaforge.net/frs/download.php/2686/luasql-$pkgver.tar.gz"
+replaces=luasql-sqlite3
+
+build() {
+ cd "$srcdir"/luasql-$pkgver
+ make CFLAGS="$CFLAGS" T=sqlite3 DRIVER_LIBS="-lsqlite3" || return 1
+}
+
+package() {
+ cd "$srcdir"/luasql-$pkgver
+ install -D src/sqlite3.so "$pkgdir"/usr/lib/lua/5.1/luasql/sqlite3.so
+}
+
+md5sums="63bdd57de4b9d1be336ba112d8cb69eb luasql-2.1.1.tar.gz"
diff --git a/main/lua-stdlib/APKBUILD b/main/lua-stdlib/APKBUILD
new file mode 100644
index 0000000000..685b1d1c92
--- /dev/null
+++ b/main/lua-stdlib/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natnae
+pkgname=lua-stdlib
+pkgver=13
+pkgrel=1
+pkgdesc="Lua library of modules for common programming tasks"
+url="http://luaforge.net/projects/stdlib/"
+arch="noarch"
+license="MIT/X"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://luaforge.net/frs/download.php/4581/stdlib-13.tar.gz"
+
+_builddir="$srcdir"/stdlib
+_luashare=/usr/share/lua/5.1
+build() {
+ cd "$_builddir"
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/$_luashare
+ install -m644 modules/*.lua "$pkgdir"/$_luashare/
+ mkdir -p "$pkgdir"/usr/share/doc/$pkgname
+ install -m644 modules/*.html "$pkgdir"/usr/share/doc/$pkgname/
+}
+
+md5sums="592cbfb622a0a9a7d8c6d7ca6657bc05 stdlib-13.tar.gz"
diff --git a/main/lua-uuid/APKBUILD b/main/lua-uuid/APKBUILD
new file mode 100644
index 0000000000..61621738d7
--- /dev/null
+++ b/main/lua-uuid/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-uuid
+pkgver=2010.11
+pkgrel=0
+pkgdesc="Lua library generating universally unique identifiers based on libuuid"
+url="http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#luuid"
+arch="all"
+license="Public Domain"
+depends=
+makedepends="lua-dev util-linux-ng-dev"
+install=
+subpackages=
+source="http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/5.1/luuid.tar.gz"
+
+# seems like they just update the upstream source package. Version is found in
+# luuid.c
+
+_builddir="$srcdir"/uuid
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make so || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -Dm755 uuid.so "$pkgdir"/usr/lib/lua/5.1/uuid.so
+}
+
+md5sums="d479786745a71398c3b1e0dfd75a4e03 luuid.tar.gz"
diff --git a/main/lua-xctrl/APKBUILD b/main/lua-xctrl/APKBUILD
new file mode 100644
index 0000000000..5b9242e57f
--- /dev/null
+++ b/main/lua-xctrl/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-xctrl
+pkgver=2010.10.26
+_x=${pkgver%%.*}
+_y=${pkgver%.*}
+_y=${_y#*.}
+_z=${pkgver##*.}
+_ver=${_x}-${_y}-${_z}
+pkgrel=1
+pkgdesc="Lua module that allows you to query and manipulate various aspects of an X11 window manager"
+url="http://jkp.t35.com/lua/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="lua-dev libx11-dev libxmu-dev libiconv-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://jkp.t35.com/files/xctrl-$_ver.tar.gz"
+
+_builddir="$srcdir"/xctrl-$_ver
+_lua_libdir=/usr/lib/lua/5.1
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ export EXTRA_CFLAGS="-fPIC"
+ export EXTRA_LDFLAGS="-liconv"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/$_lua_libdir "$pkgdir"/usr/share/doc/$pkgname
+ install src/xctrl.so "$pkgdir"/$_lua_libdir/xctrl.so
+ install doc/lxctrl.html "$pkgdir"/usr/share/doc/$pkgname/lxctrl.html
+}
+
+md5sums="edbe3385f1a660d1419d2d896c8cf106 xctrl-2010-10-26.tar.gz"
diff --git a/main/lua-xml/APKBUILD b/main/lua-xml/APKBUILD
new file mode 100644
index 0000000000..55c11fdbb0
--- /dev/null
+++ b/main/lua-xml/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-xml
+_name=LuaXML
+pkgver=101012
+pkgrel=0
+pkgdesc="a minimal set of functions for the processing of XML data in Lua"
+url="http://viremo.eludi.net/LuaXML/index.html"
+arch="all"
+license="MIT"
+depends=
+makedepends="lua-dev"
+install=
+subpackages=
+source="http://viremo.eludi.net/LuaXML/LuaXML_$pkgver.zip"
+
+_builddir="$srcdir"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -m755 -D LuaXML_lib.so "$pkgdir"/usr/lib/lua/5.1/LuaXML_lib.so\
+ || return 1
+ install -m755 -D LuaXml.lua "$pkgdir"/usr/share/lua/5.1/LuaXml.lua \
+ || return 1
+}
+
+md5sums="81c2f0c7c4238d3115e3c3e1ebc7d194 LuaXML_101012.zip"
diff --git a/main/lua-zlib/APKBUILD b/main/lua-zlib/APKBUILD
new file mode 100644
index 0000000000..4ae90bd9ad
--- /dev/null
+++ b/main/lua-zlib/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor:
+# Maintainer:
+pkgname=lua-zlib
+_name=lzlib
+pkgver=0.4
+_ver=$pkgver-work2
+pkgrel=2
+pkgdesc="Lua bindings to the ZLib compression library"
+url="http://luaforge.net/projects/lzlib/"
+arch="all"
+license="MIT"
+depends="lua"
+makedepends="lua-dev zlib-dev"
+install=
+subpackages=
+source="http://luaforge.net/frs/download.php/3826/lzlib-$_ver.tar.gz"
+
+_builddir="$srcdir"/$_name-$_ver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -Dm755 zlib.so "$pkgdir"/usr/lib/lua/5.1/zlib.so
+ install -Dm644 gzip.lua "$pkgdir"/usr/share/lua/5.1/gzip.lua
+}
+
+md5sums="9d29ec26d3ccbd86ea4d95dcc602911a lzlib-0.4-work2.tar.gz"
diff --git a/main/lua/APKBUILD b/main/lua/APKBUILD
new file mode 100644
index 0000000000..90f3009b0e
--- /dev/null
+++ b/main/lua/APKBUILD
@@ -0,0 +1,61 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua
+pkgver=5.1.4_p3
+_ver=${pkgver%_p*}
+pkgrel=2
+pkgdesc="A powerful light-weight programming language designed for extending applications."
+url="http://www.lua.org/"
+arch="all"
+license="MIT"
+depends=
+makedepends="libtool"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.$pkgname.org/ftp/$pkgname-$_ver.tar.gz
+ http://www.lua.org/ftp/patch-lua-5.1.4-${pkgver#*_p}
+ lua-5.1-make.patch
+ lua-5.1-module_paths.patch
+ lua-5.1-readline.patch
+ "
+
+_builddir="$srcdir"/lua-$_ver
+build ()
+{
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ patch*|*.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+
+ # correct lua versioning
+ sed -i -e 's/\(LIB_VERSION = \)6:1:1/\16:4:1/' src/Makefile
+
+ # we want packages to find our things
+ sed -i -e 's:/usr/local:/usr:' etc/lua.pc
+
+ cd src
+ make CFLAGS=" -DLUA_USE_LINUX $CFLAGS" \
+ RPATH="/usr/lib" \
+ LIB_LIBS="-lpthread -lm -ldl" \
+ V=$pkgver \
+ gentoo_all || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make INSTALL_TOP="$pkgdir"/usr INSTALL_LIB="$pkgdir"/usr/lib \
+ V=$pkgver gentoo_install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ install -D -m 644 etc/lua.pc "$pkgdir"/usr/lib/pkgconfig/lua.pc
+ install -D -m 644 doc/lua.1 "$pkgdir"/usr/share/man/man1/lua.1
+ install -D -m 644 doc/luac.1 "$pkgdir"/usr/share/man/man1/luac.1
+}
+md5sums="d0870f2de55d59c1c8419f36e8fac150 lua-5.1.4.tar.gz
+998ef7886183f61d3a5ca891a9ce6a79 patch-lua-5.1.4-3
+0145ff6036eb6bfdab427dc8f0c3f3c0 lua-5.1-make.patch
+e60ef15deefb72a5930c498f1184aced lua-5.1-module_paths.patch
+f2205b897edb31292a1f597a7fd638cb lua-5.1-readline.patch"
diff --git a/main/lua/lua-5.1-make.patch b/main/lua/lua-5.1-make.patch
new file mode 100644
index 0000000000..d051a21cb6
--- /dev/null
+++ b/main/lua/lua-5.1-make.patch
@@ -0,0 +1,64 @@
+--- lua-5.1.1.orig/Makefile 2006-06-02 12:53:38.000000000 +0200
++++ lua-5.1.1/Makefile 2006-11-16 02:16:53.000000000 +0100
+@@ -127,3 +127,22 @@
+ .PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho newer
+
+ # (end of Makefile)
++
++# Use libtool for binary installs, etc.
++
++export V
++export LIBTOOL = libtool --quiet --tag=CC
++# See libtool manual about how to set this
++
++gentoo_clean:
++ cd src; $(MAKE) $@
++
++gentoo_test: gentoo_linux
++ test/lua.static test/hello.lua
++
++gentoo_install:
++ mkdir -p $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB)
++ cd src; $(LIBTOOL) --mode=install $(INSTALL_EXEC) lua luac $(INSTALL_BIN)
++ cd src; $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
++ cd src; $(LIBTOOL) --mode=install $(INSTALL_DATA) liblua.la $(INSTALL_LIB)
++ cd src; $(LIBTOOL) --mode=install $(INSTALL_DATA) liblua.a $(INSTALL_LIB)
+--- lua-5.1.1.orig/src/Makefile 2006-03-22 01:41:49.000000000 +0100
++++ lua-5.1.1/src/Makefile 2006-11-16 02:10:27.000000000 +0100
+@@ -176,3 +176,36 @@
+ ltm.h lzio.h lmem.h lopcodes.h lundump.h
+
+ # (end of Makefile)
++
++export LIBTOOL = libtool --quiet --tag=CC
++export LIB_VERSION = 6:1:1
++
++# The following rules use libtool for compiling and linking in order to
++# provide shared library support.
++
++LIB_NAME = liblua.la
++LIB_OBJS = $(CORE_O:.o=.lo) $(LIB_O:.o=.lo)
++
++%.lo %.o: %.c
++ $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
++
++$(LIB_NAME): $(LIB_OBJS)
++ $(LIBTOOL) --mode=link $(CC) -version-info $(LIB_VERSION) \
++ -rpath $(RPATH) -o $(LIB_NAME) $(LIB_OBJS) $(LIB_LIBS)
++
++$(LIB_NAME:.la=.a): $(LIB_OBJS)
++ $(LIBTOOL) --mode=link $(CC) -static -o $(LIB_NAME:.la=.a) $(LIB_OBJS)
++
++$(LUA_T): $(LUA_O) $(LIB_NAME)
++ $(LIBTOOL) --mode=link $(CC) -Wl,-E -o $@ $(LUA_O) $(LUA_LIBS) -llua
++
++lua_test: $(LUA_O) $(LIB_NAME)
++ $(LIBTOOL) --mode=link $(CC) -static -Wl,-E -o $@ $(LUA_O) $(LIB_NAME) $(LUA_LIBS)
++
++$(LUAC_T): $(LUAC_O) $(LIB_NAME)
++ $(LIBTOOL) --mode=link $(CC) -static -o $@ $(LUAC_O) $(LIB_NAME)
++
++gentoo_clean:
++ $(LIBTOOL) --mode=clean $(RM) $(ALL_O:.o=.lo) $(LIB_NAME) lua luac
++
++gentoo_all: $(LIB_NAME) $(LIB_NAME:.la=.a) $(LUA_T) lua_test $(LUAC_T)
diff --git a/main/lua/lua-5.1-module_paths.patch b/main/lua/lua-5.1-module_paths.patch
new file mode 100644
index 0000000000..29ac4c3bf4
--- /dev/null
+++ b/main/lua/lua-5.1-module_paths.patch
@@ -0,0 +1,30 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## src_luaconf.h.dpatch by John V. Belmonte <jbelmonte@debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Set Lua's default PATH and CPATH.
+
+@DPATCH@
+diff -urNad trunk~/src/luaconf.h trunk/src/luaconf.h
+--- trunk~/src/luaconf.h 2006-02-10 12:44:06.000000000 -0500
++++ trunk/src/luaconf.h 2006-02-17 21:32:55.000000000 -0500
+@@ -83,13 +83,17 @@
+
+ #else
+ #define LUA_ROOT "/usr/local/"
++#define LUA_ROOT2 "/usr/"
+ #define LUA_LDIR LUA_ROOT "share/lua/5.1/"
++#define LUA_LDIR2 LUA_ROOT2 "share/lua/5.1/"
+ #define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
++#define LUA_CDIR2 LUA_ROOT2 "lib/lua/5.1/"
+ #define LUA_PATH_DEFAULT \
+ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
+- LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
++ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
++ LUA_LDIR2"?.lua;" LUA_LDIR2"?/init.lua"
+ #define LUA_CPATH_DEFAULT \
+- "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
++ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR2"?.so;" LUA_CDIR"loadall.so"
+ #endif
+
+
diff --git a/main/lua/lua-5.1-readline.patch b/main/lua/lua-5.1-readline.patch
new file mode 100644
index 0000000000..f144861efb
--- /dev/null
+++ b/main/lua/lua-5.1-readline.patch
@@ -0,0 +1,10 @@
+--- lua-5.1.1.orig/src/luaconf.h 2006-04-10 20:27:23.000000000 +0200
++++ lua-5.1.1/src/luaconf.h 2006-11-15 14:53:07.000000000 +0100
+@@ -36,7 +36,6 @@
+ #if defined(LUA_USE_LINUX)
+ #define LUA_USE_POSIX
+ #define LUA_USE_DLOPEN /* needs an extra library: -ldl */
+-#define LUA_USE_READLINE /* needs some extra libraries */
+ #endif
+
+ #if defined(LUA_USE_MACOSX)
diff --git a/main/lvm2/APKBUILD b/main/lvm2/APKBUILD
new file mode 100644
index 0000000000..04f832c3b9
--- /dev/null
+++ b/main/lvm2/APKBUILD
@@ -0,0 +1,63 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lvm2
+pkgver=2.02.85
+pkgrel=0
+pkgdesc="Logical Volume Manager 2 utilities"
+url="http://sourceware.org/lvm2/"
+arch="all"
+license="GPL"
+depends=
+makedepends="pkgconfig"
+source="ftp://sources.redhat.com/pub/$pkgname/LVM2.$pkgver.tgz
+ lvm.initd
+ lvm.confd
+ "
+subpackages="$pkgname-dev $pkgname-doc device-mapper:dm $pkgname-libs"
+
+build () {
+ cd "$srcdir"/LVM2.$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libdir=/lib \
+ --sbindir=/sbin \
+ --localstatedir=/var \
+ --disable-nls \
+ --disable-readline \
+ --enable-pkgconfig \
+ --enable-applib \
+ CLDFLAGS="$LDFLAGS" \
+ || return 1
+
+ # TODO: fix parallel builds
+ make -j1 || return 1
+}
+
+package() {
+ cd "$srcdir"/LVM2.$pkgver
+ make -j1 DESTDIR="$pkgdir" \
+ install || return 1
+ #usrlibdir="$pkgdir"/lib \
+ install -d "$pkgdir"/etc/lvm/archive "$pkgdir"/etc/lvm/backup
+ install -Dm755 "$srcdir"/lvm.initd "$pkgdir"/etc/init.d/lvm
+ install -Dm644 "$srcdir"/lvm.confd "$pkgdir"/etc/conf.d/lvm
+ cd "$pkgdir"/lib || return 1
+ ln -s libdevmapper.so.1.02 libdevmapper.so || return 1
+}
+
+dm() {
+ pkgdesc="Device mapper userspace library and tools from LVM2"
+ mkdir -p "$subpkgdir"/sbin "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libdevmapper.so.* "$subpkgdir"/lib/
+ mv "$pkgdir"/sbin/dm* "$subpkgdir"/sbin/
+}
+
+libs() {
+ pkgdesc="LVM2 shared libraries"
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/liblvm2*.so.* "$subpkgdir"/lib/
+}
+
+md5sums="91785ca438e5ce679dd3a386b183d552 LVM2.2.02.85.tgz
+6f65f902cf19f144a42b8d6aceadf395 lvm.initd
+ec36d5fe4561220304e406c5c797e71f lvm.confd"
diff --git a/main/lvm2/lvm.confd b/main/lvm2/lvm.confd
new file mode 100644
index 0000000000..9d150f6efc
--- /dev/null
+++ b/main/lvm2/lvm.confd
@@ -0,0 +1,5 @@
+# LVM should normally only be started after mdadm-raid is available
+# this is because LVM physical volumes are very often MD devices.
+
+rc_after="mdadm-raid"
+
diff --git a/main/lvm2/lvm.initd b/main/lvm2/lvm.initd
new file mode 100644
index 0000000000..f077d7f1d9
--- /dev/null
+++ b/main/lvm2/lvm.initd
@@ -0,0 +1,38 @@
+#!/sbin/runscript
+
+depend() {
+ before checkfs fsck
+ after hwdrivers modules device-mapper
+}
+
+dm_in_proc() {
+ local rc=0 i=
+ for i in devices misc; do
+ grep -qs 'device-mapper' /proc/$i
+ rc=$(($rc + $?))
+ done
+ return $rc
+}
+
+start() {
+ local rc=0 msg=
+ ebegin "Setting up the Logical Volume Manager"
+ if [ -e /proc/modules ] && ! dm_in_proc; then
+ modprobe dm-mod 2>/dev/null
+ fi
+ if [ -d /proc/lvm ] || dm_in_proc; then
+ vgscan --mknodes --ignorelockingfailure >/dev/null 2>&1 &&\
+ vgchange --ignorelockingfailure -a y >/dev/null 2>&1
+ rc=$?
+ else
+ rc=1
+ fi
+ eend $rc
+}
+
+stop() {
+ ebegin "Shutting down the Logical Volume Manager"
+ vgchange --ignorelockingfailure -a n >/dev/null 2>&1
+ eend $?
+}
+
diff --git a/main/lxdm/APKBUILD b/main/lxdm/APKBUILD
new file mode 100644
index 0000000000..05f9931dc1
--- /dev/null
+++ b/main/lxdm/APKBUILD
@@ -0,0 +1,55 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=lxdm
+pkgver=0.3.0
+pkgrel=2
+pkgdesc="LXDE desktop login manager"
+url="http://wiki.lxde.org/en/LXDM"
+license="GPL"
+depends="bash"
+makedepends="autoconf automake gtk+-dev consolekit-dev"
+install=
+source="http://downloads.sourceforge.net/lxde/$pkgname-$pkgver.tar.gz
+ lxdm.initd
+ lxdm-execinfo.patch
+ lxdm-nopam.patch"
+arch="all"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i..."
+ patch -s -p1 -N -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+
+ autoreconf
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --without-pam
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+
+md5sums="1d0688e088edab7c3c563263eb2f9654 lxdm-0.3.0.tar.gz
+d6455d172d5d897f6bfcefe9a1a632c7 lxdm.initd
+045da38f5bb183ccacc489ea7e50e927 lxdm-execinfo.patch
+0d44e8cd97894fd680e3f09e680c3481 lxdm-nopam.patch"
diff --git a/main/lxdm/lxdm-execinfo.patch b/main/lxdm/lxdm-execinfo.patch
new file mode 100644
index 0000000000..b81ef2fc84
--- /dev/null
+++ b/main/lxdm/lxdm-execinfo.patch
@@ -0,0 +1,47 @@
+--- lxdm-0.3.0/configure.ac
++++ lxdm-0.3.0.mod/configure.ac
+@@ -23,7 +23,7 @@
+
+ # Checks for header files.
+ AC_PATH_X
+-AC_CHECK_HEADERS([shadow.h stdlib.h string.h unistd.h])
++AC_CHECK_HEADERS([shadow.h stdlib.h string.h unistd.h execinfo.h])
+
+ # Checks for typedefs, structures, and compiler characteristics.
+ AC_TYPE_PID_T
+Only in lxdm-0.3.0: data/LoginReady
+Only in lxdm-0.3.0: data/PostLogin
+Only in lxdm-0.3.0: data/PostLogout
+Only in lxdm-0.3.0: data/PreLogin
+Only in lxdm-0.3.0: data/PreReboot
+Only in lxdm-0.3.0: data/PreShutdown
+--- lxdm-0.3.0/src/lxdm.c
++++ lxdm-0.3.0.mod/src/lxdm.c
+@@ -51,7 +51,9 @@
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
+
++#ifdef HAVE_EXECINFO_H
+ #include <execinfo.h>
++#endif
+
+ #include <utmp.h>
+
+@@ -1480,6 +1482,7 @@
+
+ static void log_sigsegv(void)
+ {
++#ifdef HAVE_EXECINFO_H
+ void *array[40];
+ size_t size;
+ char **bt_strs;
+@@ -1492,6 +1495,9 @@
+ fprintf(stderr, "%s\n", bt_strs[i]);
+
+ free(bt_strs);
++#else
++ fprintf(stderr, "backtrace is unavailable\n");
++#endif
+ }
+
+ static void sigsegv_handler(int sig)
diff --git a/main/lxdm/lxdm-nopam.patch b/main/lxdm/lxdm-nopam.patch
new file mode 100644
index 0000000000..86c808fcb6
--- /dev/null
+++ b/main/lxdm/lxdm-nopam.patch
@@ -0,0 +1,18 @@
+--- lxdm-0.3.0/src/lxdm.c
++++ lxdm-0.3.0.mod/src/lxdm.c
+@@ -152,6 +152,7 @@
+ while( waitpid(-1, 0, WNOHANG) > 0 ) ;
+ }
+
++#if HAVE_LIBPAM
+ static void close_pam_session(pam_handle_t *pamh)
+ {
+ int err;
+@@ -161,6 +162,7 @@
+ pam_end(pamh, err);
+ pamh = NULL;
+ }
++#endif
+
+ static LXSession *lxsession_find_greeter(void)
+ {
diff --git a/main/lxdm/lxdm.initd b/main/lxdm/lxdm.initd
new file mode 100755
index 0000000000..d0f17a24f8
--- /dev/null
+++ b/main/lxdm/lxdm.initd
@@ -0,0 +1,12 @@
+#!/sbin/runscript
+
+depends() {
+ needs localmount
+}
+
+description="Lightweight Login Manager"
+command="/usr/sbin/lxdm"
+command_args="-d"
+pidfile="/var/run/lxdm.pid"
+
+# uses the openrc templates for start()/stop()
diff --git a/main/lynx/APKBUILD b/main/lynx/APKBUILD
new file mode 100644
index 0000000000..c2ebe03e70
--- /dev/null
+++ b/main/lynx/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+pkgname=lynx
+pkgver=2.8.7
+pkgrel=2
+pkgdesc="Cross-platform text-based browser"
+url="http://lynx.isc.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev gettext zlib-dev glib-dev perl pkgconfig ncurses-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://lynx.isc.org/current/$pkgname${pkgver}rel.$pkgrel.tar.bz2"
+
+_builddir="$srcdir/${pkgname}2-8-7"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+doc() {
+ cd "$_builddir"
+ install -Dm644 docs/* "$subpkgdir"/usr/share/doc/$pkgname
+ mv "$pkgdir"/usr/man/ "$subpkgdir"/usr/share/
+}
+
+md5sums="cb936aef812e4e463ab86cbbe14d4db9 lynx2.8.7rel.2.tar.bz2"
diff --git a/main/lzo/APKBUILD b/main/lzo/APKBUILD
new file mode 100644
index 0000000000..958e0ac12c
--- /dev/null
+++ b/main/lzo/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=lzo
+pkgver=2.03
+pkgrel=5
+pkgdesc="LZO -- a real-time data compression library"
+url="http://www.oberhumer.com/opensource/lzo"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-dev"
+source="http://www.oberhumer.com/opensource/lzo/download/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-shared
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="0c3d078c2e8ea5a88971089a2f02a726 lzo-2.03.tar.gz"
diff --git a/main/m4/APKBUILD b/main/m4/APKBUILD
new file mode 100644
index 0000000000..7216a43b7a
--- /dev/null
+++ b/main/m4/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=m4
+pkgver=1.4.16
+pkgrel=0
+pkgdesc="GNU macro processor"
+url="http://www.gnu.org/software/m4"
+depends=
+arch="all"
+license="GPL"
+subpackages="m4-doc"
+source="ftp://ftp.gnu.org/gnu/m4/$pkgname-$pkgver.tar.gz
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make install DESTDIR="$pkgdir"
+}
+
+md5sums="a5dfb4f2b7370e9d34293d23fd09b280 m4-1.4.16.tar.gz"
diff --git a/main/make/APKBUILD b/main/make/APKBUILD
new file mode 100644
index 0000000000..57cdf613d7
--- /dev/null
+++ b/main/make/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=make
+pkgver=3.82
+pkgrel=1
+pkgdesc="GNU make utility to maintain groups of programs"
+url="http://www.gnu.org/software/make"
+arch="all"
+license=GPL
+depends=
+subpackages="$pkgname-doc"
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="7f7c000e3b30c6840f2e9cf86b254fac make-3.82.tar.gz"
diff --git a/main/makedepend/APKBUILD b/main/makedepend/APKBUILD
new file mode 100644
index 0000000000..17cc40fe4a
--- /dev/null
+++ b/main/makedepend/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=makedepend
+pkgver=1.0.3
+pkgrel=0
+pkgdesc="utility for making makefile dependencies"
+url="http://www.freedesktop.org/"
+arch="all"
+license="MIT"
+depends=
+depends_dev=
+makedepends="$depends_dev xproto"
+install=""
+subpackages="$pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/util/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="4e6cb97bbecfbb34f3f644a75e513093 makedepend-1.0.3.tar.bz2"
diff --git a/main/makekit/APKBUILD b/main/makekit/APKBUILD
new file mode 100644
index 0000000000..18ed2b2e38
--- /dev/null
+++ b/main/makekit/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=makekit
+pkgver=0.1
+pkgrel=0
+pkgdesc="modular build system for POSIX environments"
+url="http://mkbuild.sourceforge.net/"
+arch="noarch"
+license="BSD"
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install=""
+subpackages=
+source="http://downloads.sourceforge.net/project/mkbuild/makekit-$pkgver.tar.gz"
+
+_builddir="$srcdir"/makekit-$pkgver/build
+prepare() {
+ local i
+ cd "$_builddir"/..
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ mkdir -p "$_builddir"
+ cd "$_builddir"
+ ../configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="46b64e4a029b9b7ae09b24230cc5dc81 makekit-0.1.tar.gz"
diff --git a/main/man-pages/APKBUILD b/main/man-pages/APKBUILD
new file mode 100644
index 0000000000..106b0a6799
--- /dev/null
+++ b/main/man-pages/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=man-pages
+pkgver=3.32
+_posixver=2003-a
+pkgrel=2
+pkgdesc="Linux man pages"
+url="http://www.kernel.org/doc/man-pages/"
+arch="noarch"
+license="GPL"
+depends=
+makedepends=""
+options="!strip"
+source="http://www.kernel.org/pub/linux/docs/$pkgname/$pkgname-$pkgver.tar.gz
+ http://www.kernel.org/pub/linux/docs/$pkgname/$pkgname-posix/$pkgname-posix-${_posixver}.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ mkdir -p "$srcdir"/$pkgname-$pkgver/man0
+ for sect in 0 1 3; do
+ sed -i "/^\.so /s/man${sect}p/man$sect/" \
+ "$srcdir"/$pkgname-posix-${_posixver}/man${sect}p/*
+ mv "$srcdir"/$pkgname-posix-${_posixver}/man${sect}p/* \
+ "$srcdir"/$pkgname-$pkgver/man$sect/
+ done
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make prefix="$pkgdir"/usr install || return 1
+ # provided by libiconv-doc
+ rm "$pkgdir"/usr/share/man/man3/iconv*
+
+}
+md5sums="cc6c2d4d4eb364fd8da718c412db09d4 man-pages-3.32.tar.gz
+7c78aff03c0a6767ba483d34f19e4b09 man-pages-posix-2003-a.tar.bz2"
diff --git a/main/man/APKBUILD b/main/man/APKBUILD
new file mode 100644
index 0000000000..f1e8aa306a
--- /dev/null
+++ b/main/man/APKBUILD
@@ -0,0 +1,44 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=man
+pkgver=1.6f
+pkgrel=5
+pkgdesc="A utility for reading man pages"
+url="http://primates.ximian.com/~flucifredi/man/"
+arch="all"
+license="GPL"
+depends="groff gawk"
+subpackages="$pkgname-doc"
+source="http://primates.ximian.com/~flucifredi/$pkgname/$pkgname-$pkgver.tar.gz
+ whatis.periodic.daily
+ $pkgname-troff.patch"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ local i
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p1 -i $i || return 1
+ done
+}
+
+build () {
+ cd "$_builddir"
+ ./configure -confdir=/etc +sgid +fhs +lang none
+ sed -i "s/\\/usr\\/bin\\/awk/\\/usr\\/bin\\/gawk/" ./conf_script
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make PREFIX="$pkgdir" install || return 1
+
+ sed -i -e "s|-Tlatin1||g" \
+ -e "s|less -is|less|g" \
+ "$pkgdir"/etc/man.conf
+ install -D -m744 ../whatis.periodic.daily \
+ "$pkgdir"/etc/periodic/daily/whatis
+}
+md5sums="67aaaa6df35215e812fd7d89472c44b6 man-1.6f.tar.gz
+9cb02e4491777430a9ad3b503e87ec0d whatis.periodic.daily
+21541cb3073259f7fb9335675ca41b0e man-troff.patch"
diff --git a/main/man/man-troff.patch b/main/man/man-troff.patch
new file mode 100644
index 0000000000..e08e9316b2
--- /dev/null
+++ b/main/man/man-troff.patch
@@ -0,0 +1,16 @@
+diff -Naur man-1.5p-orig/src/man.conf.in man-1.5p/src/man.conf.in
+--- man-1.5p-orig/src/man.conf.in 2005-01-08 10:50:45.000000000 -0800
++++ man-1.5p/src/man.conf.in 2005-03-18 13:22:17.000000000 -0800
+@@ -88,9 +88,9 @@
+ # If you have a new troff (version 1.18.1?) and its colored output
+ # causes problems, add the -c option to TROFF, NROFF, JNROFF.
+ #
+-TROFF @troff@
+-NROFF @nroff@
+-JNROFF @jnroff@
++TROFF @troff@ -c
++NROFF @nroff@ -c
++JNROFF @jnroff@ -c
+ EQN @eqn@
+ NEQN @neqn@
+ JNEQN @jneqn@
diff --git a/main/man/test.out b/main/man/test.out
new file mode 100644
index 0000000000..b2ea959ca3
--- /dev/null
+++ b/main/man/test.out
@@ -0,0 +1,289 @@
+execve("/usr/bin/man", ["man", "fopen"], [/* 14 vars */]) = 0
+mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0xb781c000
+stat("/etc/ld.so.cache", {st_mode=S_IFREG|0644, st_size=7627, ...}) = 0
+open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
+mmap2(NULL, 7627, PROT_READ, MAP_SHARED, 3, 0) = 0xb781a000
+close(3) = 0
+open("/lib/libc.so.0.9.32", O_RDONLY) = 3
+fstat(3, {st_mode=S_IFREG|0755, st_size=306224, ...}) = 0
+mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0xb7819000
+read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@\260\0\0004\0\0\0"..., 4096) = 4096
+mmap2(NULL, 327680, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77c9000
+mmap2(0xb77c9000, 298552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0xb77c9000
+mmap2(0xb7812000, 4862, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x49) = 0xb7812000
+mmap2(0xb7814000, 16644, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7814000
+close(3) = 0
+munmap(0xb7819000, 4096) = 0
+munmap(0xb781a000, 7627) = 0
+stat("/lib/ld-uClibc.so.0.9.32", {st_mode=S_IFREG|0755, st_size=25248, ...}) = 0
+mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0xb781b000
+set_thread_area({entry_number:-1 -> 6, base_addr:0xb781b6a0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
+open("/dev/urandom", O_RDONLY) = 3
+read(3, "\252\2559i", 4) = 4
+close(3) = 0
+mprotect(0xb7812000, 4096, PROT_READ) = 0
+mprotect(0xb7824000, 4096, PROT_READ) = 0
+ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
+ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
+brk(0) = 0xb7971000
+brk(0xb7972000) = 0xb7972000
+getuid32() = 1000
+geteuid32() = 1000
+getgid32() = 1000
+getegid32() = 1000
+ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
+ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
+ioctl(0, TIOCGWINSZ, {ws_row=59, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
+open("/etc/man.conf", O_RDONLY) = 3
+ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf8abc08) = -1 ENOTTY (Inappropriate ioctl for device)
+brk(0xb7973000) = 0xb7973000
+read(3, "#\n# Generated automatically from"..., 4096) = 4096
+brk(0xb7976000) = 0xb7976000
+brk(0xb7979000) = 0xb7979000
+brk(0xb797c000) = 0xb797c000
+brk(0xb797f000) = 0xb797f000
+brk(0xb7982000) = 0xb7982000
+brk(0xb7985000) = 0xb7985000
+brk(0xb7988000) = 0xb7988000
+brk(0xb798b000) = 0xb798b000
+brk(0xb798e000) = 0xb798e000
+brk(0xb7991000) = 0xb7991000
+brk(0xb7994000) = 0xb7994000
+brk(0xb7997000) = 0xb7997000
+brk(0xb799a000) = 0xb799a000
+brk(0xb799d000) = 0xb799d000
+read(3, " when man is invoked without opt"..., 4096) = 439
+read(3, "", 4096) = 0
+stat("/usr/local/share/man", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+stat("/usr/share/man", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+stat("/usr/man", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+stat("/usr/local/man", 0xbf8a7ac8) = -1 ENOENT (No such file or directory)
+stat("/usr/X11R6/man", 0xbf8a7ac8) = -1 ENOENT (No such file or directory)
+ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
+ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
+open("/usr/local/share/man/html1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/man1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/local/cat1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/cat1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/html1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/man1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=24576, ...}) = 0
+brk(0xb799e000) = 0xb799e000
+getdents(4, /* 195 entries */, 4096) = 4092
+getdents(4, /* 105 entries */, 4096) = 2228
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/share/man/man1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=24576, ...}) = 0
+getdents(4, /* 195 entries */, 4096) = 4092
+getdents(4, /* 105 entries */, 4096) = 2228
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/var/cache/man/cat1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/cat1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+getdents(4, /* 2 entries */, 4096) = 32
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/share/man/cat1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+getdents(4, /* 2 entries */, 4096) = 32
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/man/html1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/man1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/cat1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/cat1/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/html1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/man1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/local/cat1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/cat1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/html1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/man1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/cat1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/cat1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/html1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/man1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/cat1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/cat1p/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/html8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/man8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/local/cat8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/cat8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/html8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/man8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+brk(0xb799f000) = 0xb799f000
+getdents(4, /* 20 entries */, 4096) = 460
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/share/man/man8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+getdents(4, /* 20 entries */, 4096) = 460
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/var/cache/man/cat8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/cat8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+getdents(4, /* 2 entries */, 4096) = 32
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/share/man/cat8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+getdents(4, /* 2 entries */, 4096) = 32
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/man/html8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/man8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/cat8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/cat8/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/html2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/man2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/local/cat2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/cat2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/html2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/man2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=36864, ...}) = 0
+getdents(4, /* 172 entries */, 4096) = 4084
+getdents(4, /* 173 entries */, 4096) = 4096
+getdents(4, /* 77 entries */, 4096) = 1772
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/share/man/man2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=36864, ...}) = 0
+getdents(4, /* 172 entries */, 4096) = 4084
+getdents(4, /* 173 entries */, 4096) = 4096
+getdents(4, /* 77 entries */, 4096) = 1772
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/var/cache/man/cat2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/cat2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/html2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/man2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/cat2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/cat2/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/html3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/man3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=90112, ...}) = 0
+getdents(4, /* 2 entries */, 4096) = 32
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/local/share/man/man3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=90112, ...}) = 0
+getdents(4, /* 2 entries */, 4096) = 32
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/var/cache/man/local/cat3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/local/share/man/cat3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/html3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/share/man/man3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=299008, ...}) = 0
+getdents(4, /* 153 entries */, 4096) = 4080
+getdents(4, /* 150 entries */, 4096) = 4084
+getdents(4, /* 148 entries */, 4096) = 4088
+getdents(4, /* 150 entries */, 4096) = 4076
+getdents(4, /* 151 entries */, 4096) = 4088
+getdents(4, /* 153 entries */, 4096) = 4092
+getdents(4, /* 149 entries */, 4096) = 4096
+getdents(4, /* 154 entries */, 4096) = 4076
+getdents(4, /* 147 entries */, 4096) = 4080
+getdents(4, /* 155 entries */, 4096) = 4084
+getdents(4, /* 143 entries */, 4096) = 4088
+getdents(4, /* 152 entries */, 4096) = 4092
+getdents(4, /* 153 entries */, 4096) = 4084
+getdents(4, /* 150 entries */, 4096) = 4080
+getdents(4, /* 152 entries */, 4096) = 4076
+getdents(4, /* 152 entries */, 4096) = 4080
+getdents(4, /* 145 entries */, 4096) = 4080
+getdents(4, /* 156 entries */, 4096) = 4072
+getdents(4, /* 148 entries */, 4096) = 4072
+getdents(4, /* 155 entries */, 4096) = 4088
+getdents(4, /* 150 entries */, 4096) = 4080
+getdents(4, /* 147 entries */, 4096) = 4068
+getdents(4, /* 153 entries */, 4096) = 4088
+getdents(4, /* 149 entries */, 4096) = 4092
+getdents(4, /* 143 entries */, 4096) = 4084
+getdents(4, /* 151 entries */, 4096) = 4084
+getdents(4, /* 152 entries */, 4096) = 4096
+getdents(4, /* 153 entries */, 4096) = 4076
+getdents(4, /* 152 entries */, 4096) = 4080
+getdents(4, /* 86 entries */, 4096) = 2340
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/share/man/man3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=299008, ...}) = 0
+getdents(4, /* 153 entries */, 4096) = 4080
+getdents(4, /* 150 entries */, 4096) = 4084
+getdents(4, /* 148 entries */, 4096) = 4088
+getdents(4, /* 150 entries */, 4096) = 4076
+getdents(4, /* 151 entries */, 4096) = 4088
+getdents(4, /* 153 entries */, 4096) = 4092
+getdents(4, /* 149 entries */, 4096) = 4096
+getdents(4, /* 154 entries */, 4096) = 4076
+getdents(4, /* 147 entries */, 4096) = 4080
+getdents(4, /* 155 entries */, 4096) = 4084
+getdents(4, /* 143 entries */, 4096) = 4088
+getdents(4, /* 152 entries */, 4096) = 4092
+getdents(4, /* 153 entries */, 4096) = 4084
+getdents(4, /* 150 entries */, 4096) = 4080
+getdents(4, /* 152 entries */, 4096) = 4076
+getdents(4, /* 152 entries */, 4096) = 4080
+getdents(4, /* 145 entries */, 4096) = 4080
+getdents(4, /* 156 entries */, 4096) = 4072
+getdents(4, /* 148 entries */, 4096) = 4072
+getdents(4, /* 155 entries */, 4096) = 4088
+getdents(4, /* 150 entries */, 4096) = 4080
+getdents(4, /* 147 entries */, 4096) = 4068
+getdents(4, /* 153 entries */, 4096) = 4088
+getdents(4, /* 149 entries */, 4096) = 4092
+getdents(4, /* 143 entries */, 4096) = 4084
+getdents(4, /* 151 entries */, 4096) = 4084
+getdents(4, /* 152 entries */, 4096) = 4096
+getdents(4, /* 153 entries */, 4096) = 4076
+getdents(4, /* 152 entries */, 4096) = 4080
+getdents(4, /* 86 entries */, 4096) = 2340
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+access("/usr/share/man/man3/fopen.3", R_OK) = 0
+open("/usr/man/html3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/man3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+getdents(4, /* 2 entries */, 4096) = 32
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/usr/man/man3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
+fstat(4, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
+getdents(4, /* 2 entries */, 4096) = 32
+getdents(4, /* 0 entries */, 4096) = 0
+close(4) = 0
+open("/var/cache/man/cat3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+open("/usr/man/cat3/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
+access("/usr/share/man/man3/fopen.3", R_OK) = 0
+open("/usr/share/man/man3/fopen.3", O_RDONLY) = 4
+ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf8a6b78) = -1 ENOTTY (Inappropriate ioctl for device)
+read(4, ".\\\" Copyright (c) 1990, 1991 The"..., 4096) = 4096
+close(4) = 0
+stat("/usr/share/man/man3/fopen.3", {st_mode=S_IFREG|0644, st_size=8720, ...}) = 0
+stat("/var/cache/man/cat3/fopen.3.bz2", 0xbf8a8b48) = -1 ENOENT (No such file or directory)
+stat("/var/cache/man/cat3/fopen.3.bz2", 0xbf8a8c28) = -1 ENOENT (No such file or directory)
+open("/var/cache/man/cat3/fopen.3.bz2", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 ENOENT (No such file or directory)
+ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
+ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
+open("/usr/share/man/man3/fopen.3", O_RDONLY) = 4
+ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf8a2b38) = -1 ENOTTY (Inappropriate ioctl for device)
+read(4, ".\\\" Copyright (c) 1990, 1991 The"..., 4096) = 4096
+close(4) = 0
+rt_sigaction(SIGINT, {0xb782cd1c, [INT], SA_RESTORER|SA_RESTART, 0xb77d43b7}, {SIG_DFL, [], 0}, 8) = 0
+rt_sigaction(SIGINT, {SIG_IGN, [], SA_RESTORER, 0xb77d43b7}, {0xb782cd1c, [INT], SA_RESTORER|SA_RESTART, 0xb77d43b7}, 8) = 0
+rt_sigaction(SIGQUIT, {SIG_IGN, [], SA_RESTORER, 0xb77d43b7}, {SIG_DFL, [], 0}, 8) = 0
+rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
+clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0xbf8a8bb4) = 31161
+waitpid(31161, <stdin>:1:1: bad syntax
+<stdin>: Not a manual
+[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 31161
+rt_sigaction(SIGINT, {0xb782cd1c, [INT], SA_RESTORER|SA_RESTART, 0xb77d43b7}, NULL, 8) = 0
+rt_sigaction(SIGQUIT, {SIG_DFL, [], SA_RESTORER, 0xb77d43b7}, NULL, 8) = 0
+rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
+--- SIGCHLD (Child exited) @ 0 (0) ---
+rt_sigaction(SIGINT, {SIG_DFL, [INT], SA_RESTORER|SA_RESTART, 0xb77d43b7}, {0xb782cd1c, [INT], SA_RESTORER|SA_RESTART, 0xb77d43b7}, 8) = 0
+exit_group(0) = ?
diff --git a/main/man/whatis.periodic.daily b/main/man/whatis.periodic.daily
new file mode 100755
index 0000000000..00d40dd9af
--- /dev/null
+++ b/main/man/whatis.periodic.daily
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Make sure MANPATH is complete
+. /etc/profile
+. /etc/profile.d/* 2>/dev/null
+
+# Update the "whatis" database
+/usr/sbin/makewhatis -u -w
+
diff --git a/main/mc/APKBUILD b/main/mc/APKBUILD
new file mode 100644
index 0000000000..50e58f2b28
--- /dev/null
+++ b/main/mc/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mc
+pkgver=4.7.0.8
+pkgrel=1
+pkgdesc="A filemanager/shell that emulates Norton Commander"
+url="http://www.ibiblio.org/mc/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="e2fsprogs-dev glib-dev pcre-dev slang-dev"
+source="http://www.midnight-commander.org/downloads/mc-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --libexecdir=/usr/lib \
+ --mandir=/usr/share/man \
+ --sysconfdir=/etc \
+ --enable-background \
+ --enable-charset \
+ --enable-largefile \
+ --with-edit \
+ --with-mmap \
+ --with-screen=slang \
+ --with-subshell \
+ --with-vfs \
+ --without-debug \
+ --without-gnome \
+ --without-gpm-mouse \
+ --without-included-gettext \
+ --without-samba \
+ --without-x \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="f05be872a7c272e8ad682cb51a1c5c5f mc-4.7.0.8.tar.bz2"
diff --git a/main/mdadm/APKBUILD b/main/mdadm/APKBUILD
new file mode 100644
index 0000000000..65d151c14c
--- /dev/null
+++ b/main/mdadm/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Carlo Landmeter <clandmeter at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mdadm
+pkgver=3.2.2
+pkgrel=0
+pkgdesc="a tool for managing Linux Software RAID arrays"
+url="http://neil.brown.name/blog/mdadm"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="groff"
+subpackages="$pkgname-doc"
+source="http://www.kernel.org/pub/linux/utils/raid/${pkgname}/${pkgname}-${pkgver}.tar.gz
+ ${pkgname}.initd
+ ${pkgname}.confd
+ mdadm-raid.initd
+ uclibc-bswap.patch
+ "
+
+prepare() {
+ cd "$srcdir/$pkgname-$pkgver"
+ patch -p1 -i "$srcdir"/uclibc-bswap.patch || return 1
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR=$pkgdir INSTALL=install install
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m755 -D "$srcdir"/$pkgname-raid.initd "$pkgdir"/etc/init.d/$pkgname-raid
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ install -m644 -D mdadm.conf-example "$pkgdir"/etc/mdadm.conf
+}
+
+md5sums="109c8bdd68daf146e693359b781ded65 mdadm-3.2.2.tar.gz
+ce57e798431f7ab89f9b07a7daaa4852 mdadm.initd
+16d2b8eb2e17184357db503470fdd8eb mdadm.confd
+ec48f19ee921eb49eb49a845bf01f1ff mdadm-raid.initd
+e6dde992d7da016f25161d6637474d26 uclibc-bswap.patch"
diff --git a/main/mdadm/mdadm-raid.initd b/main/mdadm/mdadm-raid.initd
new file mode 100644
index 0000000000..4692f76534
--- /dev/null
+++ b/main/mdadm/mdadm-raid.initd
@@ -0,0 +1,48 @@
+#!/sbin/runscript
+
+# script to start raid devices described in /etc/mdadm.conf.
+depend() {
+ before checkfs fsck
+ after modules
+}
+
+array_devices() {
+ awk '/^ARRAY/ {print $2}' /etc/mdadm.conf
+}
+
+start() {
+ [ -f /etc/mdadm.conf ] || return 0
+ # start all devices that are not already started
+ [ -f /proc/mdstat ] || modprobe -k md > /dev/null 2>&1
+ local tostart=
+ for i in $(array_devices); do
+ [ -b "$i" ] && continue
+ tostart="$tostart $i"
+ done
+ [ -z "$tostart" ] && return 0
+
+ ebegin "Starting RAID devices"
+ mdadm --assemble --scan --quiet $tostart
+ eend $?
+}
+
+is_mounted_as() {
+ local mnt
+ for mnt in $(awk "\$1 == \"$1\" {print \$2}" /proc/mounts); do
+ [ "$mnt" = "$2" ] && return 0
+ done
+ return 1
+}
+
+stop() {
+ # stop all raid devices except anything mounted as /
+ [ -f /etc/mdadm.conf ] || return 0
+ ebegin "Stopping RAID devices"
+ local tostop=
+ for i in $(array_devices); do
+ is_mounted_as $i / && continue
+ tostop="$tostop $i"
+ done
+ mdadm --stop --quiet $tostop
+ eend $?
+}
diff --git a/main/mdadm/mdadm.confd b/main/mdadm/mdadm.confd
new file mode 100644
index 0000000000..f1ed9c41d2
--- /dev/null
+++ b/main/mdadm/mdadm.confd
@@ -0,0 +1,5 @@
+# Misc options to pass to mdadm in monitor mode.
+# For more info, run `mdadm --monitor --help` or see
+# the mdadm(8) manpage.
+
+OPTS="--syslog"
diff --git a/main/mdadm/mdadm.initd b/main/mdadm/mdadm.initd
new file mode 100644
index 0000000000..77384e2658
--- /dev/null
+++ b/main/mdadm/mdadm.initd
@@ -0,0 +1,28 @@
+#!/sbin/runscript
+
+# Sample init.d file for alpine linux.
+
+NAME=mdadm
+DAEMON=/sbin/$NAME
+
+depend() {
+ use logger dns net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet --background \
+ --exec ${DAEMON} -- \
+ --monitor --scan \
+ --daemonise ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --exec ${DAEMON}
+ eend $?
+}
+
diff --git a/main/mdadm/uclibc-bswap.patch b/main/mdadm/uclibc-bswap.patch
new file mode 100644
index 0000000000..b1d0428dc8
--- /dev/null
+++ b/main/mdadm/uclibc-bswap.patch
@@ -0,0 +1,18 @@
+--- ./mdadm.h.orig
++++ ./mdadm.h
+@@ -104,12 +104,15 @@
+ * and there is no standard conversion function so... */
+ /* And dietlibc doesn't think byteswap is ok, so.. */
+ /* #include <byteswap.h> */
++#undef bswap_16
+ #define bswap_16(x) (((x) & 0x00ffU) << 8 | \
+ ((x) & 0xff00U) >> 8)
++#undef bswap_32
+ #define bswap_32(x) (((x) & 0x000000ffU) << 24 | \
+ ((x) & 0xff000000U) >> 24 | \
+ ((x) & 0x0000ff00U) << 8 | \
+ ((x) & 0x00ff0000U) >> 8)
++#undef bswap_64
+ #define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \
+ ((x) & 0xff00000000000000ULL) >> 56 | \
+ ((x) & 0x000000000000ff00ULL) << 40 | \
diff --git a/main/memcached/0001-fix-type-punning-issues.patch b/main/memcached/0001-fix-type-punning-issues.patch
new file mode 100644
index 0000000000..eb2c7355d1
--- /dev/null
+++ b/main/memcached/0001-fix-type-punning-issues.patch
@@ -0,0 +1,73 @@
+commit df15887584f0025e7b188e408dd3c9f638d68518
+Author: Dan McGee <dan@archlinux.org>
+Date: Tue Nov 2 18:43:00 2010 -0500
+
+ Fix type-punning issues exposed with GCC 4.5.1
+
+ The errors below are due to pointer magic that isn't allowed if following C
+ strict-aliasing rules:
+
+ memcached.c: In function .complete_incr_bin.:
+ memcached.c:1023:16: error: dereferencing type-punned pointer will break
+ strict-aliasing rules
+ memcached.c:1044:13: error: dereferencing type-punned pointer will break
+ strict-aliasing rules
+ memcached.c:1061:17: error: dereferencing type-punned pointer will break
+ strict-aliasing rules
+
+ Fix this by introducing a union type that allows access to the uint64_t
+ member as necessary, but doesn't add any additional length to the structure.
+ The size remains the same before and after; the only difference is explict
+ casts are now refactored into union member accesses and all compilers should
+ be happy.
+
+ Signed-off-by: Dan McGee <dan@archlinux.org>
+
+diff --git a/memcached.h b/memcached.h
+index 4a7295b..74a6592 100644
+--- a/memcached.h
++++ b/memcached.h
+@@ -77,18 +77,22 @@
+ #define TAIL_REPAIR_TIME (3 * 3600)
+
+ /* warning: don't use these macros with a function, as it evals its arg twice */
+-#define ITEM_get_cas(i) ((uint64_t)(((i)->it_flags & ITEM_CAS) ? \
+- *(uint64_t*)&((i)->end[0]) : 0x0))
+-#define ITEM_set_cas(i,v) { if ((i)->it_flags & ITEM_CAS) { \
+- *(uint64_t*)&((i)->end[0]) = v; } }
++#define ITEM_get_cas(i) (((i)->it_flags & ITEM_CAS) ? \
++ (i)->data->cas : (uint64_t)0)
+
+-#define ITEM_key(item) (((char*)&((item)->end[0])) \
++#define ITEM_set_cas(i,v) { \
++ if ((i)->it_flags & ITEM_CAS) { \
++ (i)->data->cas = v; \
++ } \
++}
++
++#define ITEM_key(item) (((char*)&((item)->data)) \
+ + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
+
+-#define ITEM_suffix(item) ((char*) &((item)->end[0]) + (item)->nkey + 1 \
++#define ITEM_suffix(item) ((char*) &((item)->data) + (item)->nkey + 1 \
+ + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
+
+-#define ITEM_data(item) ((char*) &((item)->end[0]) + (item)->nkey + 1 \
++#define ITEM_data(item) ((char*) &((item)->data) + (item)->nkey + 1 \
+ + (item)->nsuffix \
+ + (((item)->it_flags & ITEM_CAS) ? sizeof(uint64_t) : 0))
+
+@@ -302,7 +306,12 @@ typedef struct _stritem {
+ uint8_t it_flags; /* ITEM_* above */
+ uint8_t slabs_clsid;/* which slab class we're in */
+ uint8_t nkey; /* key length, w/terminating null and padding */
+- void * end[];
++ /* this odd type prevents type-punning issues when we do
++ * the little shuffle to save space when not using CAS. */
++ union {
++ uint64_t cas;
++ char end;
++ } data[];
+ /* if it_flags & ITEM_CAS we have 8 bytes CAS */
+ /* then null-terminated key */
+ /* then " flags length\r\n" (no terminating null) */
diff --git a/main/memcached/APKBUILD b/main/memcached/APKBUILD
new file mode 100644
index 0000000000..fbbd9b1929
--- /dev/null
+++ b/main/memcached/APKBUILD
@@ -0,0 +1,50 @@
+# Contributor: Jeff Bilyk <jbilyk@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=memcached
+pkgver=1.4.5
+pkgrel=1
+pkgdesc="Distributed memory object caching system"
+url="http://memcached.org"
+arch="all"
+license="GPL"
+depends="perl"
+depends_dev="libevent-dev"
+makedepends="$depends_dev"
+install="$pkgname.pre-install"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://memcached.googlecode.com/files/$pkgname-$pkgver.tar.gz
+ 0001-fix-type-punning-issues.patch
+ $pkgname.confd
+ $pkgname.initd"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -m755 -D "$srcdir/$pkgname.initd" \
+ "$pkgdir/etc/init.d/$pkgname" || return 1
+ install -m644 -D "$srcdir/$pkgname.confd" \
+ "$pkgdir/etc/conf.d/$pkgname" || return 1
+}
+
+md5sums="583441a25f937360624024f2881e5ea8 memcached-1.4.5.tar.gz
+a5b61a9b9a92a2619d9e99338a9a2a64 0001-fix-type-punning-issues.patch
+9d7396bf77c72ca3845118424cd1898b memcached.confd
+cc344c9aead89042ca2fbf45cd3930a6 memcached.initd"
diff --git a/main/memcached/memcached.confd b/main/memcached/memcached.confd
new file mode 100644
index 0000000000..7acf662a84
--- /dev/null
+++ b/main/memcached/memcached.confd
@@ -0,0 +1,35 @@
+# Copyright 2003 Gentoo Technologies, Inc
+# $Header: /var/cvsroot/gentoo-x86/net-misc/memcached/files/1.3.3/conf,v 1.1 2009/05/26 00:03:09 robbat2 Exp $
+# memcached config file
+
+MEMCACHED_BINARY="/usr/bin/memcached"
+
+#Specify memory usage in megabytes (do not use letters)
+#64MB is default
+MEMUSAGE="64"
+
+#User to run as
+MEMCACHED_RUNAS="memcached"
+
+#Specify maximum number of concurrent connections
+#1024 is default
+MAXCONN="1024"
+
+#Listen for connections on what address?
+# If this is empty, memcached will listen on 0.0.0.0
+# be sure you have a firewall in place!
+LISTENON=""
+
+#Listen for connections on what port?
+PORT="11211"
+
+# Listen for UDP connecitons on what port? 0 means turn off UDP
+UDPPORT="${PORT}"
+
+#PID file location
+# '-${PORT}.${CONF}.pid' will be appended to this!
+# You do not normally need to change this.
+PIDBASE="/var/run/memcached/memcached"
+
+#Other Options
+MISC_OPTS=""
diff --git a/main/memcached/memcached.initd b/main/memcached/memcached.initd
new file mode 100644
index 0000000000..74b2c60918
--- /dev/null
+++ b/main/memcached/memcached.initd
@@ -0,0 +1,80 @@
+#!/sbin/runscript
+# $Header: /var/cvsroot/gentoo-x86/net-misc/memcached/files/1.3.3/init,v 1.1 2009/05/26 00:03:09 robbat2 Exp $
+
+CONF="${SVCNAME#*.}"
+CONFBASE="/etc/conf.d/memcached"
+
+[ -z "${PIDBASE}" ] && PIDBASE="/var/run/memcached/memcached"
+[ "${CONF}" == "memcached" ] && CONF=''
+
+if [ -n "${CONF}" ]; then
+ PIDFILE="${PIDBASE}-${PORT}.${CONF}.pid"
+ CONFSRC="${CONFBASE}.${CONF}"
+ if [ -f "${CONFSRC}" ]; then
+ source "${CONFSRC}"
+ else
+ eerror "The configuration file $CONFSRC was not found!"
+ fi
+else
+ PIDFILE="${PIDBASE}-${PORT}.pid"
+ CONFSRC="${CONFBASE}"
+fi
+
+depend() {
+ need net
+ # per bug #269022, accurate time is important for memcached!
+ # We include the full list of ways it might be set on boot.
+ after ntp-client ntpd rdate openrdate adjtimex hwclock
+}
+
+checkconfig() {
+ if [ -z "${LISTENON}" ]; then
+ ewarn "You should edit $CONFSRC and specify an address to listen on."
+ ewarn "Listening on any address (check your firewall!)"
+ fi
+
+}
+
+start() {
+ if [ -n "${CONF}" ]; then
+ ebegin "Starting memcached (${CONF})"
+ else
+ ebegin "Starting memcached"
+ fi
+ checkconfig
+ local dir="$(dirname ${PIDFILE})"
+ if [ ! -d "${dir}" ]; then
+ einfo " Creating ${dir}"
+ mkdir -p "${dir}"
+ fi
+ chown ${MEMCACHED_RUNAS} "${dir}"
+ if [ -f "${PIDFILE}" ]; then
+ einfo " Removing stale pidfile ${PIDFILE}"
+ rm -f "${PIDFILE}" 1>/dev/null
+ fi
+
+ if [ -z "${LISTENON}" ]; then
+ c_LISTENON=""
+ else
+ c_LISTENON="-l ${LISTENON}"
+ fi
+
+ /sbin/start-stop-daemon --start --pidfile "${PIDFILE}" \
+ --exec "${MEMCACHED_BINARY}" \
+ --startas "${MEMCACHED_BINARY}" -- \
+ -d -p ${PORT} -U ${UDPPORT} ${c_LISTENON} -m ${MEMUSAGE} \
+ -c ${MAXCONN} -u ${MEMCACHED_RUNAS} -P "${PIDFILE}" \
+ ${MISC_OPTS}
+ eend $?
+}
+
+stop() {
+ if [ -n "${CONF}" ]; then
+ ebegin "Stopping memcached (${CONF})"
+ else
+ ebegin "Stopping memcached"
+ fi
+ start-stop-daemon --stop --quiet --pidfile "${PIDFILE}"
+ rm -f "${PIDFILE}"
+ eend $?
+}
diff --git a/main/memcached/memcached.pre-install b/main/memcached/memcached.pre-install
new file mode 100644
index 0000000000..f9d7c71690
--- /dev/null
+++ b/main/memcached/memcached.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -H -s /bin/false -D memcached 2>/dev/null
+exit 0
+
diff --git a/main/mercurial/APKBUILD b/main/mercurial/APKBUILD
new file mode 100644
index 0000000000..6b958ad63d
--- /dev/null
+++ b/main/mercurial/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mercurial
+pkgver=1.8.4
+pkgrel=1
+pkgdesc="A scalable distributed SCM tool"
+url="http://www.selenic.com/mercurial"
+arch="all"
+license="GPL"
+depends="python"
+makedepends="python-dev"
+subpackages="$pkgname-doc"
+source="http://www.selenic.com/$pkgname/release/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ python setup.py build
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ python setup.py install --root="$pkgdir" || return 1
+ install -d "$pkgdir"/usr/share/man/man1 "$pkgdir"/usr/share/man/man5
+ install -m644 doc/hg.1 ""$pkgdir"/usr/share/man/man1" || return 1
+ install -m644 doc/hgrc.5 doc/hgignore.5 "$pkgdir"/usr/share/man/man5 \
+ || return 1
+ install -m755 contrib/hgk "$pkgdir"/usr/bin || return 1
+ install -m644 -D contrib/bash_completion \
+ "$pkgdir"/etc/bash_completion.d/hg || return 1
+ vimpath="$pkgdir"/usr/share/vim/vimfiles
+ install -Dm644 contrib/vim/HGAnnotate.vim \
+ "${vimpath}/syntax/HGAnnotate.vim" || return 1
+}
+md5sums="b3dcc3de473e003dd1cc0500dcd9de47 mercurial-1.8.4.tar.gz"
diff --git a/main/mesa-demos/APKBUILD b/main/mesa-demos/APKBUILD
new file mode 100644
index 0000000000..1b371db139
--- /dev/null
+++ b/main/mesa-demos/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa
+pkgname=mesa-demos
+pkgver=8.0.1
+pkgrel=0
+pkgdesc="Mesa demos and utils"
+url="http://mesa3d.sourceforge.net"
+arch="all"
+license="custom"
+depends=""
+depends_dev=
+makedepends="$depends_dev mesa-dev glew-dev automake autoconf libtool"
+install=""
+subpackages=
+source="ftp://ftp.freedesktop.org/pub/mesa/demos/$pkgver/$pkgname-$pkgver.tar.bz2
+ sincos.patch"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr
+ make V=1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="320c2a4b6edc6faba35d9cb1e2a30bf4 mesa-demos-8.0.1.tar.bz2
+75be22556a657f0a157028233832d167 sincos.patch"
diff --git a/main/mesa-demos/sincos.patch b/main/mesa-demos/sincos.patch
new file mode 100644
index 0000000000..38da0285d1
--- /dev/null
+++ b/main/mesa-demos/sincos.patch
@@ -0,0 +1,32 @@
+--- ./src/egl/opengles2/es2gears.c.orig
++++ ./src/egl/opengles2/es2gears.c
+@@ -109,13 +109,15 @@
+ c[4] = 1;
+ v = gear->vertices;
+ for (i = 0; i < teeth; i++) {
++ GLint j;
+ s[0] = s[4];
+ c[0] = c[4];
+- sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]);
+- sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
+- sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
+- sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
+
++ for (j=1; j <=4; j++) {
++ s[j] = sin(i * 2.0 * M_PI / teeth + da * j);
++ c[j] = cos(i * 2.0 * M_PI / teeth + da * j);
++ }
++
+ normal[0] = 0.0;
+ normal[1] = 0.0;
+ normal[2] = 1.0;
+@@ -199,7 +201,8 @@
+ {
+ double s, c;
+
+- sincos(angle, &s, &c);
++ s = sin(angle);
++ c = cos(angle);
+ GLfloat r[16] = {
+ x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
+ x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
diff --git a/main/mesa/APKBUILD b/main/mesa/APKBUILD
new file mode 100644
index 0000000000..40cbe65f7e
--- /dev/null
+++ b/main/mesa/APKBUILD
@@ -0,0 +1,130 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mesa
+pkgver=7.10.3
+pkgrel=0
+pkgdesc="Mesa DRI OpenGL library"
+url="http://www.mesa3d.org"
+arch="all"
+license="LGPL"
+depends=
+subpackages="$pkgname-dev
+ $pkgname-dri-ati:ati
+ $pkgname-dri-intel:intel
+ $pkgname-dri-mach64:mach64
+ $pkgname-dri-mga:mga
+ $pkgname-dri-r128:r128
+ $pkgname-dri-savage:savage
+ $pkgname-dri-swrast:swrast
+ $pkgname-dri-tdfx:tdfx
+ $pkgname-dri-unichrome:unichrome
+ $pkgname-dri-nouveau:nouveau
+ $pkgname-egl
+ "
+
+makedepends="pkgconfig libdrm-dev libxxf86vm-dev libxdamage-dev expat-dev
+ dri2proto xextproto libx11-dev glproto python libxt-dev makedepend
+ talloc-dev py-libxml2 flex bison"
+source="ftp://ftp.freedesktop.org/pub/mesa/$pkgver/MesaLib-$pkgver.tar.bz2
+ mesa-7.10-uclibc.patch
+ mesa-7.10-uclibc-glsl.patch
+ mesa-7.10-uclibc-gallium.patch
+ Mesa-7.10.1-nouveau-compile.patch
+ "
+
+depends_dev="libdrm-dev dri2proto libx11-dev libxext-dev libxxf86vm-dev
+ libxdamage-dev libxfixes-dev libxcb-dev glproto"
+
+_dri_driverdir=/usr/lib/xorg/modules/dri
+
+_builddir="$srcdir/Mesa-$pkgver"
+
+case "$CHOST" in
+x86_64-*)
+ _intel_dri="i915_dri i965_dri"
+ ;;
+i[3456789]86-*)
+ _intel_dri="i810_dri i915_dri i965_dri"
+ subpackages="$subpackages $pkgname-dri-sis:sis"
+ ;;
+esac
+
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 -i $i || return 1
+ done
+}
+
+dev() {
+ default_dev;
+ depends="$depends_dev mesa mesa-egl"
+}
+
+build() {
+ cd "$_builddir"
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr \
+ --with-dri-driverdir=$_dri_driverdir \
+ --disable-asm \
+ --disable-glx-tls \
+ --with-driver=dri \
+ --with-state-trackers=dri,glx,egl \
+ --enable-xcb \
+ --enable-egl \
+ --enable-gles2 \
+ --enable-gallium-nouveau \
+ --enable-gallium-swrast \
+ --disable-gallium-egl \
+ --disable-glut \
+ --disable-glw || return 1
+
+ make || return 1
+
+ # check so we dont have any bind NOW
+ scanelf -Rb . | grep NOW && return 1
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+}
+
+egl() {
+ replaces="mesa"
+ pkgdesc="Mesa OpenGLES support library and modules"
+
+ install -d "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libEGL.so* "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/lib/egl "$subpkgdir"/usr/lib/egl
+}
+
+_mv_dri() {
+ pkgdesc="Mesa DRI driver for $@"
+ install -d "$subpkgdir"/$_dri_driverdir
+
+ while [ $# -gt 0 ]; do
+ mv "$pkgdir"/$_dri_driverdir/${1}.so \
+ "$subpkgdir"/$_dri_driverdir/ || return 1
+ shift
+ done
+}
+
+ati() { _mv_dri radeon_dri r200_dri r300_dri r600_dri; }
+intel() { _mv_dri $_intel_dri; }
+mach64() { _mv_dri mach64_dri; }
+mga() { _mv_dri mga_dri; }
+r128() { _mv_dri r128_dri; }
+savage() { _mv_dri savage_dri; }
+sis() { _mv_dri sis_dri; }
+tdfx() { _mv_dri tdfx_dri; }
+unichrome() { _mv_dri unichrome_dri; }
+nouveau() { _mv_dri nouveau_dri; }
+swrast() { _mv_dri swrast_dri; }
+
+md5sums="8c38fe8266be8e1ed1d84076ba5a703b MesaLib-7.10.3.tar.bz2
+9c8c161f954f0d08895cd9d45e63f498 mesa-7.10-uclibc.patch
+03e9685b0d714e915c35fd0fb5fde810 mesa-7.10-uclibc-glsl.patch
+90a2ea438ff328443a0436a91a74d518 mesa-7.10-uclibc-gallium.patch
+34e3d4bb5f16bae55929958083087c0a Mesa-7.10.1-nouveau-compile.patch"
diff --git a/main/mesa/Mesa-7.10.1-nouveau-compile.patch b/main/mesa/Mesa-7.10.1-nouveau-compile.patch
new file mode 100644
index 0000000000..96dafceb07
--- /dev/null
+++ b/main/mesa/Mesa-7.10.1-nouveau-compile.patch
@@ -0,0 +1,139 @@
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_clear.c.ark 2011-04-11 10:26:00.717291484 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_clear.c 2011-04-11 10:26:05.600624698 +0200
+@@ -24,6 +24,8 @@
+ #include "pipe/p_defines.h"
+ #include "pipe/p_state.h"
+
++#include <nouveau/nv04_pushbuf.h>
++
+ #include "nv50_context.h"
+
+ void
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_context.c.ark 2011-04-11 10:25:55.913958268 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_context.c 2011-04-11 10:26:00.663958154 +0200
+@@ -23,6 +23,8 @@
+ #include "draw/draw_context.h"
+ #include "pipe/p_defines.h"
+
++#include <nouveau/nv04_pushbuf.h>
++
+ #include "nv50_context.h"
+ #include "nv50_screen.h"
+ #include "nv50_resource.h"
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_push.c.ark 2011-04-11 10:25:50.250625073 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_push.c 2011-04-11 10:25:55.873958269 +0200
+@@ -4,6 +4,8 @@
+ #include "util/u_format.h"
+ #include "util/u_split_prim.h"
+
++#include <nouveau/nv04_pushbuf.h>
++
+ #include "nv50_context.h"
+ #include "nv50_resource.h"
+
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_query.c.ark 2011-04-11 10:25:44.790625206 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_query.c 2011-04-11 10:25:50.183958407 +0200
+@@ -23,6 +23,8 @@
+ #include "pipe/p_context.h"
+ #include "util/u_inlines.h"
+
++#include <nouveau/nv04_pushbuf.h>
++
+ #include "nv50_context.h"
+
+ struct nv50_query {
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_screen.c.ark 2011-04-11 10:25:32.790625497 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_screen.c 2011-04-11 10:25:38.633958688 +0200
+@@ -23,6 +23,8 @@
+ #include "util/u_format_s3tc.h"
+ #include "pipe/p_screen.h"
+
++#include <nouveau/nv04_pushbuf.h>
++
+ #include "nv50_context.h"
+ #include "nv50_screen.h"
+ #include "nv50_resource.h"
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_shader_state.c.ark 2011-04-11 10:25:38.710625354 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_shader_state.c 2011-04-11 10:25:44.713958540 +0200
+@@ -26,6 +26,8 @@
+ #include "pipe/p_state.h"
+ #include "util/u_inlines.h"
+
++#include <nouveau/nv04_pushbuf.h>
++
+ #include "nv50_context.h"
+
+ static void
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_state_validate.c.ark 2011-04-11 10:25:27.520625626 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_state_validate.c 2011-04-11 10:25:32.737292166 +0200
+@@ -22,6 +22,7 @@
+
+ #include "util/u_format.h"
+
++#include <nouveau/nv04_pushbuf.h>
+ #include "nv50_context.h"
+ #include "nv50_resource.h"
+ #include "nouveau/nouveau_stateobj.h"
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_surface.c.ark 2011-04-11 10:25:22.407292417 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_surface.c 2011-04-11 10:25:27.450625628 +0200
+@@ -22,6 +22,7 @@
+
+ #define __NOUVEAU_PUSH_H__
+ #include <stdint.h>
++#include <nouveau/nv04_pushbuf.h>
+ #include "nouveau/nouveau_pushbuf.h"
+ #include "nv50_context.h"
+ #include "nv50_resource.h"
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_transfer.c.ark 2011-04-11 10:25:14.903959267 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_transfer.c 2011-04-11 10:25:22.353959086 +0200
+@@ -4,6 +4,8 @@
+ #include "util/u_format.h"
+ #include "util/u_math.h"
+
++#include <nouveau/nv04_pushbuf.h>
++
+ #include "nv50_context.h"
+ #include "nv50_transfer.h"
+ #include "nv50_resource.h"
+--- Mesa-7.10.1/src/gallium/drivers/nv50/nv50_vbo.c.ark 2011-04-11 10:25:01.717292921 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nv50/nv50_vbo.c 2011-04-11 10:25:14.850625935 +0200
+@@ -26,6 +26,8 @@
+ #include "util/u_format.h"
+ #include "util/u_split_prim.h"
+
++#include <nouveau/nv04_pushbuf.h>
++
+ #include "nv50_context.h"
+ #include "nv50_resource.h"
+
+--- Mesa-7.10.1/src/gallium/drivers/nvfx/nv04_2d.c.ark 2011-04-11 10:23:22.800628664 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nvfx/nv04_2d.c 2011-04-11 10:25:01.640626257 +0200
+@@ -39,6 +39,7 @@
+ #include <nouveau/nouveau_bo.h>
+ #include <nouveau/nouveau_notifier.h>
+ #include <nouveau/nouveau_grobj.h>
++#include <nouveau/nv04_pushbuf.h>
+ #include "nv04_2d.h"
+
+ #include "nouveau/nv_object.xml.h"
+--- Mesa-7.10.1/src/gallium/drivers/nvfx/nvfx_screen.c.ark 2011-04-11 10:27:59.380621927 +0200
++++ Mesa-7.10.1/src/gallium/drivers/nvfx/nvfx_screen.c 2011-04-11 10:28:02.833955176 +0200
+@@ -3,6 +3,7 @@
+ #include "util/u_format_s3tc.h"
+ #include "util/u_simple_screen.h"
+
++#include <nouveau/nv04_pushbuf.h>
+ #include "nouveau/nouveau_screen.h"
+ #include "nouveau/nv_object.xml.h"
+ #include "nvfx_context.h"
+--- Mesa-7.10.1/src/mesa/drivers/dri/nouveau/nv04_context.c.ark 2011-04-11 10:27:27.220622711 +0200
++++ Mesa-7.10.1/src/mesa/drivers/dri/nouveau/nv04_context.c 2011-04-11 11:09:24.147228063 +0200
+@@ -24,6 +24,8 @@
+ *
+ */
+
++#include <stdint.h>
++#include <nouveau/nv04_pushbuf.h>
+ #include "nouveau_driver.h"
+ #include "nouveau_context.h"
+ #include "nouveau_fbo.h"
diff --git a/main/mesa/fix-glx1.3-crash-xorg19.patch b/main/mesa/fix-glx1.3-crash-xorg19.patch
new file mode 100644
index 0000000000..bd09b9e71a
--- /dev/null
+++ b/main/mesa/fix-glx1.3-crash-xorg19.patch
@@ -0,0 +1,73 @@
+From 8f13c69e7658df3a97e388f210dae175639d6d8d Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Fri, 16 Jul 2010 12:24:53 +0100
+Subject: [PATCH] intel: Fix invalidate before initialisation
+
+Fixes:
+
+ Bug 29091 - 1.9RC5 server crash when starting GLX 1.3 app with mesa 7.8
+ Intel dri2 driver.
+ https://bugs.freedesktop.org/show_bug.cgi?id=29091
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+---
+ src/mesa/drivers/dri/common/dri_util.c | 2 +-
+ src/mesa/drivers/dri/intel/intel_screen.c | 19 +++++++++++++++----
+ 2 files changed, 16 insertions(+), 5 deletions(-)
+
+diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
+index 75c9882..9a9bfed 100644
+--- a/src/mesa/drivers/dri/common/dri_util.c
++++ b/src/mesa/drivers/dri/common/dri_util.c
+@@ -432,7 +432,7 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
+ */
+ (void) attrs;
+
+- pdp = malloc(sizeof *pdp);
++ pdp = calloc(1, sizeof *pdp);
+ if (!pdp) {
+ return NULL;
+ }
+diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
+index 6e4bb64..083b7bb 100644
+--- a/src/mesa/drivers/dri/intel/intel_screen.c
++++ b/src/mesa/drivers/dri/intel/intel_screen.c
+@@ -102,10 +102,21 @@ static const __DRItexBufferExtension intelTexBufferExtension = {
+ intelSetTexBuffer2,
+ };
+
++static inline struct intel_context *
++to_intel_context(__DRIdrawable *drawable)
++{
++ if (drawable->driContextPriv == NULL)
++ return NULL;
++
++ return drawable->driContextPriv->driverPrivate;
++}
++
+ static void
+ intelDRI2Flush(__DRIdrawable *drawable)
+ {
+- struct intel_context *intel = drawable->driContextPriv->driverPrivate;
++ struct intel_context *intel = to_intel_context(drawable);
++ if (!intel)
++ return;
+
+ if (intel->gen < 4)
+ INTEL_FIREVERTICES(intel);
+@@ -117,9 +128,9 @@ intelDRI2Flush(__DRIdrawable *drawable)
+ static void
+ intelDRI2Invalidate(__DRIdrawable *drawable)
+ {
+- struct intel_context *intel = drawable->driContextPriv->driverPrivate;
+-
+- intel->using_dri2_swapbuffers = GL_TRUE;
++ struct intel_context *intel = to_intel_context(drawable);
++ if (intel)
++ intel->using_dri2_swapbuffers = GL_TRUE;
+ dri2InvalidateDrawable(drawable);
+ }
+
+--
+1.7.1
+
diff --git a/main/mesa/mesa-7.10-uclibc-gallium.patch b/main/mesa/mesa-7.10-uclibc-gallium.patch
new file mode 100644
index 0000000000..a14743bc17
--- /dev/null
+++ b/main/mesa/mesa-7.10-uclibc-gallium.patch
@@ -0,0 +1,20 @@
+--- Mesa-7.10.orig/src/gallium/auxiliary/util/u_debug_symbol.c
++++ Mesa-7.10/src/gallium/auxiliary/util/u_debug_symbol.c
+@@ -145,7 +145,7 @@
+ }
+ #endif
+
+-#ifdef __GLIBC__
++#if defined(__GLIBC__) && !defined(__UCLIBC__)
+ #include <execinfo.h>
+
+ /* This can only provide dynamic symbols, or binary offsets into a file.
+@@ -171,7 +171,7 @@
+ return;
+ #endif
+
+-#ifdef __GLIBC__
++#if defined(__GLIBC__) && !defined(__UCLIBC__)
+ debug_symbol_name_glibc(addr, buf, size);
+ if(buf[0])
+ return;
diff --git a/main/mesa/mesa-7.10-uclibc-glsl.patch b/main/mesa/mesa-7.10-uclibc-glsl.patch
new file mode 100644
index 0000000000..df7ee1b3b3
--- /dev/null
+++ b/main/mesa/mesa-7.10-uclibc-glsl.patch
@@ -0,0 +1,11 @@
+--- Mesa-7.10.orig/src/glsl/strtod.c
++++ Mesa-7.10/src/glsl/strtod.c
+@@ -44,7 +44,7 @@
+ double
+ glsl_strtod(const char *s, char **end)
+ {
+-#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__)
++#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && !defined(__UCLIBC__)
+ static locale_t loc = NULL;
+ if (!loc) {
+ loc = newlocale(LC_CTYPE_MASK, "C", NULL);
diff --git a/main/mesa/mesa-7.10-uclibc.patch b/main/mesa/mesa-7.10-uclibc.patch
new file mode 100644
index 0000000000..54d7d8c833
--- /dev/null
+++ b/main/mesa/mesa-7.10-uclibc.patch
@@ -0,0 +1,13 @@
+--- Mesa-7.10/src/mesa/main/imports.c
++++ Mesa-7.10.mod/src/mesa/main/imports.c
+@@ -757,7 +757,7 @@
+ float
+ _mesa_strtof( const char *s, char **end )
+ {
+-#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__)
++#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && !defined(__UCLIBC__)
+ static locale_t loc = NULL;
+ if (!loc) {
+ loc = newlocale(LC_CTYPE_MASK, "C", NULL);
+Only in Mesa-7.10.mod: src/mesa/main/imports.c.orig
+Only in Mesa-7.10.mod: src/mesa/main/imports.c.rej
diff --git a/main/metacity/APKBUILD b/main/metacity/APKBUILD
new file mode 100644
index 0000000000..4ce453a1c3
--- /dev/null
+++ b/main/metacity/APKBUILD
@@ -0,0 +1,54 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=metacity
+pkgver=2.30.3
+pkgrel=4
+pkgdesc="GTK+ window manager"
+url="http://projects.gnome.org/metacity"
+arch="all"
+license="GPL"
+depends="zenity"
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ gnome-desktop-dev
+ libwnck-dev
+ librsvg-dev
+ libxcomposite-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages="$pkgname-dev"
+replaces_dev="$pkgname"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-compositor \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="553784f376d96b902e19ff437cd5b339 metacity-2.30.3.tar.bz2"
diff --git a/main/metacity/metacity.post-install b/main/metacity/metacity.post-install
new file mode 100644
index 0000000000..4b16502e4a
--- /dev/null
+++ b/main/metacity/metacity.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in metacity.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/metacity/metacity.post-upgrade b/main/metacity/metacity.post-upgrade
new file mode 100644
index 0000000000..4b16502e4a
--- /dev/null
+++ b/main/metacity/metacity.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in metacity.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/metacity/metacity.pre-deinstall b/main/metacity/metacity.pre-deinstall
new file mode 100644
index 0000000000..3fab274c9e
--- /dev/null
+++ b/main/metacity/metacity.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in metacity.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/mg/APKBUILD b/main/mg/APKBUILD
new file mode 100644
index 0000000000..bf7c3c4996
--- /dev/null
+++ b/main/mg/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Lee Hinman <hinman@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mg
+pkgver=20110120
+pkgrel=1
+pkgdesc="mg is Micro GNU/emacs, this is a portable version of the mg maintained by the OpenBSD team."
+url="http://homepage.boetes.org/software/mg"
+arch="all"
+license="public-domain BSD"
+depends=
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://homepage.boetes.org/software/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ sed -i -e '/^CFLAGS/s/-Werror//' Makefile.in
+}
+
+build() {
+ cd "$_builddir"
+ ./configure
+ make prefix=/usr mandir=/usr/share/man || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make INSTALL=install DESTDIR="$pkgdir" prefix=/usr \
+ mandir=/usr/share/man install || return 1
+ install -Dm644 tutorial "$pkgdir"/usr/share/doc/$pkgname/tutorial
+}
+
+md5sums="f2fa8016a491aa2a9d4c5698c593f31b mg-20110120.tar.gz"
diff --git a/main/micro-tetris/APKBUILD b/main/micro-tetris/APKBUILD
new file mode 100644
index 0000000000..adb2774327
--- /dev/null
+++ b/main/micro-tetris/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinepinux.org>
+pkgname=micro-tetris
+pkgver=1.2.0
+pkgrel=1
+pkgdesc="Micro Tetris, based on 1989 IOCCC Obfuscated Tetris"
+url="http://git.vmlinux.org/tetris.git/"
+arch="all"
+license="ISC"
+depends=
+makedepends=
+install=
+subpackages=
+source="ftp://ftp.vmlinux.org/pub/People/jocke/micro-tetris/tetris-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/tetris-$pkgver
+prepare() {
+ cd "$_builddir"
+ sed -i -e "/install/s:bin/tetris:usr/bin/tetris:" Makefile
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="017942718be2760f1b060e63d6799fed tetris-1.2.0.tar.bz2"
diff --git a/main/midori/APKBUILD b/main/midori/APKBUILD
new file mode 100644
index 0000000000..452cb7670d
--- /dev/null
+++ b/main/midori/APKBUILD
@@ -0,0 +1,51 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=midori
+pkgver=0.3.6
+pkgrel=0
+pkgdesc="A lightweight web browser based on Gtk WebKit"
+url="http://www.twotoasts.de/index.php?/pages/midori_summary.html"
+arch="all"
+license="GPL"
+depends="
+ desktop-file-utils
+ hicolor-icon-theme
+ "
+makedepends="
+ gettext-dev
+ git
+ intltool
+ libidn-dev
+ libnotify-dev
+ librsvg-dev
+ libunique-dev
+ libxml2-dev
+ paxctl
+ pkgconfig
+ python
+ sqlite-dev
+ webkit-dev
+ "
+install="$pkgname.post-install $pkgname.post-upgrade $pkgname.post-deinstall"
+source="http://archive.xfce.org/src/apps/midori/${pkgver%.*}/midori-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --jobs=${MAKEFLAGS/-j/} \
+ --enable-libidn \
+ --enable-addons \
+ --disable-vala \
+ --disable-hildon \
+ --enable-unique \
+ --enable-nls \
+ || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ # PAX does not like the JIT
+ paxctl -c -m -p "$pkgdir"/usr/bin/midori
+}
+md5sums="c4cb0686601b1c470c317de3d3f8e8fd midori-0.3.6.tar.bz2"
diff --git a/main/midori/midori.post-deinstall b/main/midori/midori.post-deinstall
new file mode 100644
index 0000000000..00ebf0b316
--- /dev/null
+++ b/main/midori/midori.post-deinstall
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+update-desktop-database -q
+gtk-update-icon-cache -f -q -t /usr/share/icons/hicolor
+
diff --git a/main/midori/midori.post-install b/main/midori/midori.post-install
new file mode 100644
index 0000000000..9f24aeca93
--- /dev/null
+++ b/main/midori/midori.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+gtk-update-icon-cache -f -q -t /usr/share/icons/hicolor
+update-desktop-database -q
diff --git a/main/midori/midori.post-upgrade b/main/midori/midori.post-upgrade
new file mode 120000
index 0000000000..41bc70a939
--- /dev/null
+++ b/main/midori/midori.post-upgrade
@@ -0,0 +1 @@
+midori.post-install \ No newline at end of file
diff --git a/main/mini_httpd/APKBUILD b/main/mini_httpd/APKBUILD
new file mode 100644
index 0000000000..c62aec1398
--- /dev/null
+++ b/main/mini_httpd/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mini_httpd
+pkgver=1.19
+pkgrel=6
+pkgdesc="Small forking webserver with ssl and ipv6 support"
+url="http://www.acme.com/software/mini_httpd/"
+arch="all"
+license="BSD"
+depends="logrotate"
+makedepends="openssl-dev"
+subpackages="$pkgname-doc"
+source="http://www.acme.com/software/mini_httpd/$pkgname-$pkgver.tar.gz
+ $pkgname.conf.sample
+ $pkgname.initd
+ $pkgname.logrotate
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make CFLAGS="${CFLAGS} -DUSE_SSL" \
+ LDFLAGS="${LDFLAGS}" \
+ SSL_LIBS="-lssl -lcrypto" \
+ || return 1
+# SSL_DEFS="-DUSE_SSL" \
+
+ # does not respect DESTDIR
+ make install \
+ BINDIR="$pkgdir"/usr/sbin \
+ MANDIR="$pkgdir"/usr/share/man
+
+ # rename htpasswd to mini_htpasswd
+ mv "$pkgdir"/usr/sbin/htpasswd "$pkgdir"/usr/sbin/mini_htpasswd
+ mv "$pkgdir"/usr/share/man/man1/htpasswd.1 \
+ "$pkgdir"/usr/share/man/man1/mini_htpasswd.1
+
+ mkdir -p "$pkgdir"/var/www/localhost/htdocs
+ install -D -m644 ../mini_httpd.conf.sample \
+ "$pkgdir"/etc/mini_httpd.conf
+ install -D -m755 ../mini_httpd.initd "$pkgdir"/etc/init.d/mini_httpd
+ install -D -m644 ../mini_httpd.logrotate \
+ "$pkgdir"/etc/logrotate.d/mini_httpd
+ install -d "$pkgdir"/var/run/mini_httpd "$pkgdir"/var/log/mini_httpd
+}
+
+md5sums="7c68293ad265ecfe2edea917912f6f1f mini_httpd-1.19.tar.gz
+bca5b3b1cdc00cf31f0b54797518b893 mini_httpd.conf.sample
+02a9a415c365aa40c27211afbaa545c7 mini_httpd.initd
+915683e9c7e1cef7ce9b1bbaa31ab680 mini_httpd.logrotate"
diff --git a/main/mini_httpd/mini_httpd.conf.sample b/main/mini_httpd/mini_httpd.conf.sample
new file mode 100644
index 0000000000..002f4f0c7e
--- /dev/null
+++ b/main/mini_httpd/mini_httpd.conf.sample
@@ -0,0 +1,52 @@
+## /etc/mini_httpd.conf
+##
+## do not leave empty lines in here!
+## format is: key=value
+##
+## run in debug-mode?
+#debug
+##
+## what interface to bind to?
+## (default is binding to any interface)
+#host=www.example.org
+port=80
+#port=443
+user=nobody
+##
+## The DOCROOT
+dir=/var/www/localhost/htdocs
+##
+## CGI:
+## ? match a single char
+## * matches any string excluding "/"
+## ** matches any string including "/"
+## separate multiple patterns with "|"
+#cgipat=**.sh|**.cgi
+##
+## chroot:
+chroot
+#nochroot
+##
+## The init.d script will override logfile here, so you need to set the
+## MINI_HTTPD_OPTS in /etc/conf.d/ in order to enable the logfile option here
+#logfile=/var/log/mini_httpd/mini_httpd.log
+##
+#charset=iso-8859-1
+##
+## control the caching: (in secs)
+#maxage 60
+##
+## useless setting (just modifies the http-header)
+## (see mini_httpd(8) and http://www.w3.org/P3P/ for more info)
+#p3p
+##
+## virtual hosting:
+#vhost
+##
+## cache-control: send this "max-age" in all HTTP-responses:
+#max-age=0
+##
+## ssl:
+#nossl
+#ssl
+#certfile=/etc/mini_httpd/mini_httpd.pem
diff --git a/main/mini_httpd/mini_httpd.initd b/main/mini_httpd/mini_httpd.initd
new file mode 100644
index 0000000000..ad1917be3e
--- /dev/null
+++ b/main/mini_httpd/mini_httpd.initd
@@ -0,0 +1,26 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/www-servers/mini_httpd/files/mini_httpd.init,v 1.2 2007/08/26 21:20:21 bangert Exp $
+
+pidfile=/var/run/mini_httpd/${SVCNAME}.pid
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting $SVCNAME"
+ start-stop-daemon --quiet --start --exec /usr/sbin/mini_httpd \
+ --pidfile $pidfile -- -i $pidfile \
+ ${MINI_HTTPD_OPTS:--C /etc/${SVCNAME}.conf -l /var/log/mini_httpd/${SVCNAME}.log}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping $SVCNAME"
+ start-stop-daemon --quiet --stop --pidfile $pidfile
+ eend $?
+}
+
diff --git a/main/mini_httpd/mini_httpd.logrotate b/main/mini_httpd/mini_httpd.logrotate
new file mode 100644
index 0000000000..bbd448b80a
--- /dev/null
+++ b/main/mini_httpd/mini_httpd.logrotate
@@ -0,0 +1,16 @@
+/var/log/mini_httpd/*.log {
+ weekly
+ missingok
+ copytruncate
+ rotate 7
+ compress
+ notifempty
+ sharedscripts
+ postrotate
+ for i in /var/run/mini_httpd*.pid /var/run/mini_httpd/*.pid; do \
+ if [ -f "$i" ]; then \
+ /etc/init.d/$(basename $i .pid) restart > /dev/null 2>&1 || true ; \
+ fi; \
+ done;
+ endscript
+}
diff --git a/main/minicom/APKBUILD b/main/minicom/APKBUILD
new file mode 100644
index 0000000000..6868c5022b
--- /dev/null
+++ b/main/minicom/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=minicom
+pkgver=2.4
+pkgrel=2
+pkgdesc="menu driven communications program for terminals"
+url="http://alioth.debian.org/projects/minicom"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev libiconv-dev gettext-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://alioth.debian.org/frs/download.php/3195/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ #--without-libintl-prefix
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="700976a3c2dcc8bbd50ab9bb1c08837b minicom-2.4.tar.gz"
diff --git a/main/mkfontdir/APKBUILD b/main/mkfontdir/APKBUILD
new file mode 100644
index 0000000000..7437411ae1
--- /dev/null
+++ b/main/mkfontdir/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mkfontdir
+pkgver=1.0.5
+pkgrel=1
+pkgdesc="create an index of X font files in a directory"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends="mkfontscale"
+makedepends="pkgconfig"
+install=
+triggers="$pkgname.trigger:/usr/share/fonts/*"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="9365ac66d19186eaf030482d312fca06 mkfontdir-1.0.5.tar.bz2"
diff --git a/main/mkfontdir/mkfontdir.trigger b/main/mkfontdir/mkfontdir.trigger
new file mode 100644
index 0000000000..4fce36a118
--- /dev/null
+++ b/main/mkfontdir/mkfontdir.trigger
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+for i in "$@"; do
+ mkfontdir "$i"
+done
+
diff --git a/main/mkfontscale/APKBUILD b/main/mkfontscale/APKBUILD
new file mode 100644
index 0000000000..8e6902d193
--- /dev/null
+++ b/main/mkfontscale/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mkfontscale
+pkgver=1.0.7
+pkgrel=2
+pkgdesc="X.org font scale"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libfontenc-dev freetype-dev xproto zlib-dev"
+install=
+triggers="$pkgname.trigger:/usr/share/fonts/*"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="96ca346f185c0ab48e42bf5bb0375da5 mkfontscale-1.0.7.tar.bz2"
diff --git a/main/mkfontscale/mkfontscale.trigger b/main/mkfontscale/mkfontscale.trigger
new file mode 100644
index 0000000000..2357e06dc0
--- /dev/null
+++ b/main/mkfontscale/mkfontscale.trigger
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+for i in "$@"; do
+ mkfontscale "$i"
+done
+
diff --git a/main/mkinitfs/0001-init-fix-progressbar-when-not-quiet.patch b/main/mkinitfs/0001-init-fix-progressbar-when-not-quiet.patch
new file mode 100644
index 0000000000..7a82978f17
--- /dev/null
+++ b/main/mkinitfs/0001-init-fix-progressbar-when-not-quiet.patch
@@ -0,0 +1,27 @@
+From b9ad256b04db3965bf21ed7ee25ddfd7c166d102 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Wed, 27 Apr 2011 09:15:20 +0000
+Subject: [PATCH] init: fix progressbar when not quiet
+
+see http://bugs.alpinelinux.org/issues/613
+---
+ initramfs-init.in | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/initramfs-init.in b/initramfs-init.in
+index 7b09722..a0e594d 100755
+--- a/initramfs-init.in
++++ b/initramfs-init.in
+@@ -462,6 +462,9 @@ fi
+
+ # install new root
+ ebegin "Installing packages to root filesystem"
++# insert newline unless quiet to fix progress bar
++[ -n "$KOPT_quiet" ] || echo ""
++
+ if [ "$KOPT_chart" = yes ]; then
+ pkgs="$pkgs acct"
+ fi
+--
+1.7.4.5
+
diff --git a/main/mkinitfs/APKBUILD b/main/mkinitfs/APKBUILD
new file mode 100644
index 0000000000..5d4d760345
--- /dev/null
+++ b/main/mkinitfs/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mkinitfs
+pkgver=2.3.4
+pkgrel=2
+pkgdesc="Tool to generate initramfs images for Alpine"
+url=http://git.alpinelinux.org/cgit/mkinitfs
+depends="busybox apk-tools>=2.0"
+triggers="$pkgname.trigger:/usr/share/kernel/*"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2
+ 0001-init-fix-progressbar-when-not-quiet.patch
+ eglibc.patch
+ "
+arch="noarch"
+license="GPL-2"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ # If we are using eglibc/glibc we need to include eglibc libs
+ # instead of uclibc libs.
+ for i in $source; do
+ case $i in
+ eglibc.patch)
+ case "$CHOST" in
+ *-gnu)
+ patch -p1 -i "$srcdir"/eglibc.patch || return 1
+ ;;
+ esac
+ ;;
+ *.patch)
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make VERSION=$pkgver-r$pkgrel || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make install DESTDIR="$pkgdir" || return 1
+}
+md5sums="abec6dced89e137dc60542c1e5f938ac mkinitfs-2.3.4.tar.bz2
+4ea4389d5dff0a69d6792420574d2f1f 0001-init-fix-progressbar-when-not-quiet.patch
+e59c2f7de496fe430b07e32fd812ebe0 eglibc.patch"
diff --git a/main/mkinitfs/eglibc.patch b/main/mkinitfs/eglibc.patch
new file mode 100644
index 0000000000..24f1e1e9a3
--- /dev/null
+++ b/main/mkinitfs/eglibc.patch
@@ -0,0 +1,17 @@
+--- a/files.d/base
++++ b/files.d/base
+@@ -7,11 +7,11 @@
+ /lib/libdl.so*
+ /lib/libm-[0-9]*
+ /lib/libm.so.*
+-/lib/libuClibc-[0-9]*
++/lib/libc-[0-9]*
+ /lib/libc.so.*
+ /lib/libz.*
+-/lib/ld-uClibc-[0-9]*
+-/lib/ld-uClibc.so*
++/lib/ld-[0-9]*
++/lib/ld-linux.so*
+ /lib/mdev
+ /sbin/apk
+ /etc/modprobe.d/blacklist
diff --git a/main/mkinitfs/mkinitfs.trigger b/main/mkinitfs/mkinitfs.trigger
new file mode 100644
index 0000000000..4069d923f5
--- /dev/null
+++ b/main/mkinitfs/mkinitfs.trigger
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+for i in "$@"; do
+ # get last element in path
+ flavor=${i##*/}
+ if ! [ -f "$i"/kernel.release ]; then
+ # kernel was uninstalled
+ rm -f $( readlink -f /boot/initramfs-$flavor ) \
+ /boot/initramfs-$flavor /boot/vmlinuz-$flavor \
+ /boot/$flavor /boot/$flavor.gz /$flavor /$flavor.gz
+ continue
+ fi
+ abi_release=$(cat "$i"/kernel.release)
+ initfs=initramfs-$abi_release
+ mkinitfs -o /boot/$initfs $abi_release
+ ln -sf $initfs /boot/initramfs-$flavor
+ ln -sf vmlinuz-$abi_release /boot/vmlinuz-$flavor
+
+ #this is for compat. to be removed eventually...
+ ln -sf vmlinuz-$flavor /boot/$flavor
+ ln -sf initramfs-$flavor /boot/$flavor.gz
+ ln -sf /boot/vmlinuz-$flavor /$flavor
+ ln -sf /boot/initramfs-$flavor /$flavor.gz
+
+ # Update the /boot/extlinux.conf to point to correct kernel
+ f=/boot/extlinux.conf
+ if [ -f $f ] && grep -q -- "kernel /$flavor" $f; then
+ sed -i -e "s:kernel /$flavor:kernel /boot/vmlinuz-$flavor:" \
+ -e "s:initrd=/$flavor.gz:initrd=/boot/initramfs-$flavor:" \
+ -e "s:initrd /$flavor.gz:initrd /boot/initramfs-$flavor:" \
+ $f
+ fi
+
+done
+
+# extlinux will use path relative partition, so if /boot is on a
+# separate partition we want /boot/<kernel> resolve to /<kernel>
+if ! [ -e /boot/boot ]; then
+ ln -sf / /boot/boot
+fi
+
+# cleanup unused initramfs
+for i in /boot/initramfs-[0-9]*; do
+ [ -f $i ] || continue
+ if ! [ -f /boot/vmlinuz-${i#/boot/initramfs-} ]; then
+ rm "$i"
+ fi
+done
+
+exit 0
diff --git a/main/mlmmj/APKBUILD b/main/mlmmj/APKBUILD
new file mode 100644
index 0000000000..87f1525e77
--- /dev/null
+++ b/main/mlmmj/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mlmmj
+pkgver=1.2.17.1
+pkgrel=0
+pkgdesc="Mailing list managing made joyful"
+url="http://mlmmj.org/"
+arch="all"
+license="MIT"
+subpackages="$pkgname-doc"
+depends=
+makedepends=
+source="http://mlmmj.org/releases/mlmmj-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ install -d "$pkgdir"/usr/share/mlmmj/texts
+ cp -r listtexts/* "$pkgdir"/usr/share/mlmmj/texts/
+}
+md5sums="c705d8bf3003df6810c9775ce86e7af0 mlmmj-1.2.17.1.tar.gz"
diff --git a/main/module-init-tools/APKBUILD b/main/module-init-tools/APKBUILD
new file mode 100644
index 0000000000..ac718dde98
--- /dev/null
+++ b/main/module-init-tools/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanel Copa <ncopa@alpinelinux.org>
+pkgname=module-init-tools
+pkgver=3.16
+pkgrel=0
+pkgdesc="Utilities for inserting and removing modules from the Linux kernel"
+url="http://www.kernel.org"
+arch="all"
+license='GPL'
+depends=
+source="http://www.kernel.org/pub/linux/utils/kernel/module-init-tools/module-init-tools-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr --exec-prefix=/
+ make DOCBOOKTOMAN=: || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" INSTALL=install install || return 1
+
+ # remove empty manpages.
+ rm -r "$pkgdir/usr"
+}
+
+md5sums="bc44832c6e41707b8447e2847d2019f5 module-init-tools-3.16.tar.bz2"
diff --git a/main/monkeysphere/APKBUILD b/main/monkeysphere/APKBUILD
new file mode 100644
index 0000000000..bf11966175
--- /dev/null
+++ b/main/monkeysphere/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=monkeysphere
+pkgver=0.35
+pkgrel=0
+pkgdesc="openpgp web of trust certification tools for SSH and TLS servers"
+url="http://web.monkeysphere.info/"
+arch="noarch"
+license="GPL3"
+depends="openssl gnupg"
+depends_dev=""
+install=""
+subpackages="$pkgname-doc"
+source="http://archive.monkeysphere.info/debian/pool/${pkgname}/m/${pkgname}/${pkgname}_${pkgver}.orig.tar.gz"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="481ac14c9fdef0ccd1944c593bd4f517 monkeysphere_0.35.orig.tar.gz"
diff --git a/main/mousepad/APKBUILD b/main/mousepad/APKBUILD
new file mode 100644
index 0000000000..49a34cb1bb
--- /dev/null
+++ b/main/mousepad/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mousepad
+pkgver=0.2.16
+pkgrel=2
+pkgdesc="Simple Text Editor for Xfce4 (based on Gedit)"
+url="http://foo-projects.org/~benny/xfce/apps.html"
+arch="all"
+license="GPL-2"
+makedepends="libxfcegui4-dev"
+depends="desktop-file-utils"
+install=
+source="http://archive.xfce.org/src/apps/mousepad/${pkgver%.*}/mousepad-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="d98854edb76d823ac20b266fdf5a64a1 mousepad-0.2.16.tar.bz2"
diff --git a/main/mpc/APKBUILD b/main/mpc/APKBUILD
new file mode 100644
index 0000000000..ca928e54e3
--- /dev/null
+++ b/main/mpc/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mpc
+pkgver=0.20
+pkgrel=0
+pkgdesc="Minimalist command line interface to MPD"
+url="http://mpd.wikia.com/wiki/Client:Mpc"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-doc"
+depends=
+makedepends="libmpdclient-dev"
+source="http://downloads.sourceforge.net/project/musicpd/$pkgname/$pkgver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/mpc-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/mpc-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="24c81ad6afe6099e8d7a6826ef4b7105 mpc-0.20.tar.bz2"
diff --git a/main/mpd/APKBUILD b/main/mpd/APKBUILD
new file mode 100644
index 0000000000..af8ebb1092
--- /dev/null
+++ b/main/mpd/APKBUILD
@@ -0,0 +1,55 @@
+# Contributor: Sebastian Wicki <gandro@gmx.net>
+# Maintainer: Natanael Copa <natanael.copa@gmail.com>
+pkgname=mpd
+pkgver=0.16.3
+pkgrel=0
+pkgdesc="Music daemon that plays MP3, FLAC, and Ogg Vorbis files"
+url="http://musicpd.org"
+pkgusers="mpd"
+pkggroups="mpd audio"
+arch="all"
+license="GPL2"
+depends=
+makedepends="pkgconfig lame-dev glib-dev curl-dev libao-dev libmad-dev flac-dev
+ libogg-dev faad2-dev libid3tag-dev libvorbis-dev alsa-lib-dev
+ libsamplerate-dev libshout-dev"
+install="$pkgname.pre-install"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/project/musicpd/mpd/${pkgver}/mpd-${pkgver}.tar.bz2
+ mpd.initd
+ mpd.confd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-shout \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+
+ #provide a config that works by default
+ install -d "$pkgdir"/etc
+ sed -e 's:\#pid_file.*:pid_file\t\t/var/run/mpd/mpd.pid:' \
+ -e 's:\#user.*:user\t\tmpd:' \
+ -e 's:\#log_file.*:log_file\t\t/var/log/mpd/mpd.log:' \
+ doc/mpdconf.example > "$pkgdir"/etc/mpd.conf
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ install -d -g audio -o mpd -m775 \
+ "$pkgdir"/var/run/mpd \
+ "$pkgdir"/var/log/mpd \
+ "$pkgdir"/var/lib/mpd/playlists \
+ "$pkgdir"/var/lib/mpd/music
+}
+md5sums="6e708c02b0e8c288aec855eecf441a5a mpd-0.16.3.tar.bz2
+31d1515232d688d610d1664a0fb2a6a0 mpd.initd
+dbd301041953a5cf9c2b9de8f23eb6bb mpd.confd"
diff --git a/main/mpd/mpd.confd b/main/mpd/mpd.confd
new file mode 100644
index 0000000000..720306e89e
--- /dev/null
+++ b/main/mpd/mpd.confd
@@ -0,0 +1,7 @@
+# conf.d file for music player daemon
+
+#
+# Specify daemon $OPTS here.
+#
+
+OPTS=""
diff --git a/main/mpd/mpd.initd b/main/mpd/mpd.initd
new file mode 100644
index 0000000000..10601dc47d
--- /dev/null
+++ b/main/mpd/mpd.initd
@@ -0,0 +1,44 @@
+#!/sbin/runscript
+
+# init.d file for music player daemon
+
+NAME=mpd
+DAEMON=/usr/bin/$NAME
+CONF=/etc/mpd.conf
+
+depend() {
+ need localmount
+ use net netmount nfsmount esound pulseaudio
+ after firewall
+}
+
+checkconfig() {
+ [ -f "$CONF" ] && return 0
+ eerror "configuration file $CONF is missing"
+ return 1
+}
+
+get_pidfile() {
+ pidfile=$(awk '$1 == "pid_file" { print $2 }' "$CONF")
+ pidfile=${pidfile:-/var/run/mpd/$NAME.pid}
+}
+
+start() {
+ checkconfig || return 1
+ get_pidfile
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet \
+ --pidfile $pidfile\
+ --exec ${DAEMON} -- ${MPD_OPTS}
+ eend $?
+}
+
+stop() {
+ get_pidfile
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --pidfile $pidfile \
+ --exec ${DAEMON}
+ eend $?
+}
+
diff --git a/main/mpd/mpd.pre-install b/main/mpd/mpd.pre-install
new file mode 100644
index 0000000000..4baabab1a8
--- /dev/null
+++ b/main/mpd/mpd.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -h /var/lib/mpd -s /bin/false -G audio -D mpd 2>/dev/null || true
+
diff --git a/main/mpfr3/APKBUILD b/main/mpfr3/APKBUILD
new file mode 100644
index 0000000000..6287f20ab1
--- /dev/null
+++ b/main/mpfr3/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mpfr3
+pkgver=3.0.0
+pkgrel=3
+pkgdesc="multiple-precision floating-point library"
+url="http://www.mpfr.org/"
+arch="all"
+license="GPL LGPL"
+depends=
+makedepends="gmp-dev texinfo"
+source="http://www.mpfr.org/mpfr-current/mpfr-$pkgver.tar.bz2"
+subpackages="$pkgname-doc mpfr-dev"
+
+_builddir="$srcdir"/mpfr-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --build=${CBUILD} \
+ --host=${CHOST} \
+ --enable-shared || return 1;
+ make || return 1;
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="${pkgdir}" install || return 1;
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+dev() {
+ replaces=mpfr
+ default_dev
+}
+md5sums="f45bac3584922c8004a10060ab1a8f9f mpfr-3.0.0.tar.bz2"
diff --git a/main/mpg123/APKBUILD b/main/mpg123/APKBUILD
new file mode 100644
index 0000000000..7aaca4e1de
--- /dev/null
+++ b/main/mpg123/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mpg123
+pkgver=1.13.3
+pkgrel=0
+pkgdesc="A console based real time MPEG Audio Player for Layer 1, 2 and 3"
+url="http://sourceforge.net/projects/mpg123"
+arch="all"
+license="GPL2 LGPL2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libtool alsa-lib-dev"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-dependency-tracking \
+ --with-ipv6 \
+ --with-pic \
+ --with-optimization=0 \
+ --with-cpu=i386_fpu \
+ --with-audio="alsa oss" || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+# mpg123 needs the output_*.la files so we move them back from -dev package
+dev() {
+ default_dev
+ mv "$subpkgdir"/usr/lib/mpg123/output_* "$pkgdir"/usr/lib/mpg123/
+}
+
+md5sums="b1f990ce76dcf2fdf9d53ac39fc6bc7e mpg123-1.13.3.tar.bz2"
diff --git a/main/mplayer/APKBUILD b/main/mplayer/APKBUILD
new file mode 100644
index 0000000000..c7eff9e030
--- /dev/null
+++ b/main/mplayer/APKBUILD
@@ -0,0 +1,70 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mplayer
+pkgver=1.0_rc4
+_ver=${pkgver%_*}${pkgver#*_}
+pkgrel=3
+pkgdesc="A movie player for linux"
+url="http://www.mplayerhq.hu/"
+arch="all"
+license="GPL"
+depends=
+subpackages="$pkgname-doc"
+makedepends="libxxf86dga-dev libxv-dev libmad-dev lame-dev libao-dev
+ libtheora-dev xvidcore-dev zlib-dev sdl-dev freetype-dev
+ x264-dev faac-dev ttf-dejavu libxvmc-dev alsa-lib-dev live-media-dev
+ mesa-dev"
+
+# cdparanoia libcaca lirc-utils libgl-dev smbclient-dev
+# aalib-dev jack-audio-connection-kit libmng-dev libxss-dev
+
+source="http://www.mplayerhq.hu/MPlayer/releases/MPlayer-$_ver.tar.bz2"
+_builddir="$srcdir"/MPlayer-$_ver
+
+build() {
+ cd "$_builddir"
+
+ export GCC_SPECS=/usr/share/gcc/hardenednopie.specs
+ ./configure --prefix=/usr \
+ --disable-gui \
+ --disable-gif \
+ --disable-arts \
+ --enable-x11 \
+ --enable-runtime-cpudetection \
+ --confdir=/etc/mplayer \
+ --disable-nas \
+ --enable-gl \
+ --disable-tv-v4l1 \
+ --enable-tv-v4l2 \
+ --enable-largefiles \
+ --disable-liblzo \
+ --disable-speex \
+ --disable-openal \
+ --disable-fribidi \
+ --disable-libdv \
+ --disable-musepack \
+ --language=all\
+ --disable-esd \
+ --disable-mga \
+ --disable-lirc \
+ --enable-debug \
+ --enable-radio \
+ --enable-radio-capture \
+ --extra-cflags="-I/usr/lib/live-media -O2" \
+ --disable-nemesi \
+ --enable-freetype \
+ --enable-xvmc \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ install -Dm644 etc/codecs.conf etc/input.conf etc/example.conf \
+ "$pkgdir"/etc/mplayer/ || return 1
+ install -dm755 "$pkgdir"/usr/share/mplayer/
+ ln -s /usr/share/fonts/TTF/DejaVuSans.ttf \
+ "$pkgdir"/usr/share/mplayer/subfont.ttf || return 1
+ rm -rf "$pkgdir"/usr/share/mplayer/font
+}
+md5sums="1699c94de39da9c4c5d34e8f58e418f0 MPlayer-1.0rc4.tar.bz2"
diff --git a/main/mplayer/liba52_gcc_bug.patch b/main/mplayer/liba52_gcc_bug.patch
new file mode 100644
index 0000000000..c0d42f876f
--- /dev/null
+++ b/main/mplayer/liba52_gcc_bug.patch
@@ -0,0 +1,10 @@
+--- mplayer/configure.old 2009-04-16 12:02:10.000000000 +0200
++++ mplayer/configure 2009-05-22 15:23:38.000000000 +0200
+@@ -6410,6 +6410,7 @@
+ def_liba52='#undef CONFIG_LIBA52'
+ def_liba52_internal="#undef CONFIG_LIBA52_INTERNAL"
+ if test "$_liba52_internal" = yes ; then
++ test "$cc_vendor" = gnu && test "$cc_version" = 4.4.0 && CFLAGS=$(echo $CFLAGS|sed "s/ *-O4 */ -O2 /")
+ _liba52=yes
+ def_liba52_internal="#define CONFIG_LIBA52_INTERNAL 1"
+ _res_comment="internal"
diff --git a/main/mplayer/mplayer/configure.orig b/main/mplayer/mplayer/configure.orig
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/main/mplayer/mplayer/configure.orig
diff --git a/main/mplayer/mplayer/configure.rej b/main/mplayer/mplayer/configure.rej
new file mode 100644
index 0000000000..c0d42f876f
--- /dev/null
+++ b/main/mplayer/mplayer/configure.rej
@@ -0,0 +1,10 @@
+--- mplayer/configure.old 2009-04-16 12:02:10.000000000 +0200
++++ mplayer/configure 2009-05-22 15:23:38.000000000 +0200
+@@ -6410,6 +6410,7 @@
+ def_liba52='#undef CONFIG_LIBA52'
+ def_liba52_internal="#undef CONFIG_LIBA52_INTERNAL"
+ if test "$_liba52_internal" = yes ; then
++ test "$cc_vendor" = gnu && test "$cc_version" = 4.4.0 && CFLAGS=$(echo $CFLAGS|sed "s/ *-O4 */ -O2 /")
+ _liba52=yes
+ def_liba52_internal="#define CONFIG_LIBA52_INTERNAL 1"
+ _res_comment="internal"
diff --git a/main/mrtg/APKBUILD b/main/mrtg/APKBUILD
new file mode 100644
index 0000000000..9e4cdc388d
--- /dev/null
+++ b/main/mrtg/APKBUILD
@@ -0,0 +1,35 @@
+# Contributor: Jeff Bilyk<jbilyk at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mrtg
+pkgver=2.17.2
+pkgrel=0
+pkgdesc="MRTG Network Latency Monitoring"
+url="http://oss.oetiker.ch/mrtg/"
+source="http://oss.oetiker.ch/mrtg/pub/$pkgname-$pkgver.tar.gz
+ mrtg.initd mrtg.confd"
+subpackages="$pkgname-doc"
+depends="perl"
+makedepends="gd-dev libpng-dev zlib-dev"
+arch="all"
+license="GPL"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --bindir=/usr/bin \
+ --libdir=/usr/lib \
+ --datadir=/usr/share/doc \
+ --mandir=/usr/share/doc/man \
+ || return 1
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make install DESTDIR="$pkgdir"
+}
+
+md5sums="f4c251ef883da2509188711eff4577ad mrtg-2.17.2.tar.gz
+47053d5e51ac8eefe3807d5168219f78 mrtg.initd
+a8d246d324b90fd1e37cc912d4651372 mrtg.confd"
diff --git a/main/mrtg/mrtg.confd b/main/mrtg/mrtg.confd
new file mode 100644
index 0000000000..f3be157baf
--- /dev/null
+++ b/main/mrtg/mrtg.confd
@@ -0,0 +1,17 @@
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-analyzer/mrtg/files/mrtg.confd,v 1.1 2005/01/26 10:35:05 ka0ttic Exp $
+
+MRTG_CONF="/etc/mrtg.conf"
+MRTG_PID="/var/run/mrtg.pid"
+
+# uncomment and set the following, if you'd like to run mrtg as a
+# different user/group
+#MRTG_USER=""
+#MRTG_GROUP=""
+
+# uncomment if you'd like to enable logging
+#MRTG_LOG="/var/log/mrtg.log"
+
+# set any extra options here
+MRTG_OPTS=""
diff --git a/main/mrtg/mrtg.initd b/main/mrtg/mrtg.initd
new file mode 100644
index 0000000000..31adb2cf0a
--- /dev/null
+++ b/main/mrtg/mrtg.initd
@@ -0,0 +1,53 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-analyzer/mrtg/files/mrtg.rc,v 1.7 2007/04/19 19:08:08 cedk Exp $
+
+depend() {
+ need net
+
+ # if monitoring snmp variables on this machine:
+ # use net-snmpd
+}
+
+checkconfig() {
+ if ! [ -f "${MRTG_CONF} ]; then
+ eerror "Please create ${MRTG_CONF} (try man cfgmaker)"
+ return 1
+ fi
+
+ mrtg --check ${MRTG_CONF}
+ return $?
+}
+
+start() {
+ # mrtg will not run if LANG=*utf8
+ # use grep instead of bash regexp for bug #159786
+ echo $LANG | grep -q -E '((^[A-Za-z0-9\_\@\-]+\.)|(^))([uU][tT][fF]-?8)$' && LANG='C'
+
+ checkconfig || return $?
+
+ # enable logging?
+ [ -n "${MRTG_LOG}" ] && \
+ MRTG_OPTS="${MRTG_OPTS} --logging ${MRTG_LOG}"
+
+ # run as a different user?
+ [ -n "${MRTG_USER}" ] && \
+ MRTG_OPTS="${MRTG_OPTS} --user ${MRTG_USER}"
+
+ # run as a different group?
+ [ -n "${MRTG_GROUP}" ] && \
+ MRTG_OPTS="${MRTG_OPTS} --group ${MRTG_GROUP}"
+
+ ebegin "Starting mrtg"
+ start-stop-daemon --start --quiet --pidfile ${MRTG_PID} --name mrtg\
+ --exec /usr/bin/mrtg -- --daemon --pid-file=${MRTG_PID} \
+ ${MRTG_OPTS} ${MRTG_CONF} >/dev/null
+ eend $? "Failed to start mrtg"
+}
+
+stop() {
+ ebegin "Stopping mrtg"
+ start-stop-daemon --stop --quiet --pidfile ${MRTG_PID}
+ eend $? "Failed to stop mrtg"
+}
diff --git a/main/mrxvt/APKBUILD b/main/mrxvt/APKBUILD
new file mode 100644
index 0000000000..4b4ac62e33
--- /dev/null
+++ b/main/mrxvt/APKBUILD
@@ -0,0 +1,54 @@
+# Contributor: Mark Constable <markc@renta.net>
+# Maintainer: Mark Constable <markc@renta.net>
+pkgname=mrxvt
+pkgver=0.5.4
+pkgrel=4
+pkgdesc="A multi-tabbed X terminal emulator based on rxvt code"
+url="http://materm.sourceforge.net/wiki/pmwiki.php"
+arch="all"
+license="GPL"
+makedepends="libpng-dev jpeg-dev libxft-dev libxpm-dev libx11-dev"
+subpackages="$pkgname-doc"
+source="
+ http://downloads.sourceforge.net/sourceforge/materm/$pkgname-$pkgver.tar.gz
+ mrxvt-0.5.4-002-fix-segfault-when-wd-empty.patch
+ mrxvt.desktop
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -p1 < ../mrxvt-0.5.4-002-fix-segfault-when-wd-empty.patch || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-xft \
+ --enable-text-shadow \
+ --enable-transparency \
+ --enable-smart-resize \
+ --enable-menubar \
+ --disable-ourstrings \
+ --enable-linespace \
+ --enable-256colors \
+ --enable-xim \
+ --enable-thai \
+ --enable-greek \
+ --enable-cjk \
+ --enable-backspace-key \
+ --with-save-lines=2048 || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR=$pkgdir install || return 1
+ install -Dm644 ../mrxvt.desktop $pkgdir/usr/share/applications/mrxvt.desktop
+
+}
+md5sums="0232c8868484751dcb931a28f0756f69 mrxvt-0.5.4.tar.gz
+e4a8bb2521246aba85f8dcaa01aed527 mrxvt-0.5.4-002-fix-segfault-when-wd-empty.patch
+6ba3bcd484c8dad1b0b48465ded54de3 mrxvt.desktop"
diff --git a/main/mrxvt/mrxvt-0.5.4-002-fix-segfault-when-wd-empty.patch b/main/mrxvt/mrxvt-0.5.4-002-fix-segfault-when-wd-empty.patch
new file mode 100644
index 0000000000..c9af740e50
--- /dev/null
+++ b/main/mrxvt/mrxvt-0.5.4-002-fix-segfault-when-wd-empty.patch
@@ -0,0 +1,12 @@
+diff -ru a/src/tabbar.c b/src/tabbar.c
+--- a/src/tabbar.c 2009-08-19 21:12:48.000000000 +0000
++++ b/src/tabbar.c 2009-08-19 21:13:35.000000000 +0000
+@@ -1314,7 +1314,7 @@
+ if( p.we_wordc > 1)
+ rxvt_msg( DBG_ERROR, DBG_TABBAR,
+ "Too many words when expanding %s\n", cwdOption );
+- else
++ else if( NOT_NULL( *p.we_wordv ) )
+ {
+ filename = *p.we_wordv;
+
diff --git a/main/mrxvt/mrxvt.desktop b/main/mrxvt/mrxvt.desktop
new file mode 100644
index 0000000000..fc2173ddb7
--- /dev/null
+++ b/main/mrxvt/mrxvt.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=mrxvt
+Comment=MultiTabbed rxvt Terminal
+Exec=mrxvt
+Icon=mrxvt
+Terminal=false
+Type=Application
+Categories=Application;TerminalEmulator;
+GenericName=Terminal
diff --git a/main/msmtp/APKBUILD b/main/msmtp/APKBUILD
new file mode 100644
index 0000000000..207f705f87
--- /dev/null
+++ b/main/msmtp/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=msmtp
+pkgver=1.4.24
+pkgrel=0
+pkgdesc="SMTP client with a sendmail compatible interface"
+url="http://msmtp.sourceforge.net/"
+arch="all"
+license="GPLv3+"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/project/msmtp/msmtp/$pkgver/msmtp-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/msmtp-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="3ed704fbd3e7419cab5c65bb7928d9ba msmtp-1.4.24.tar.bz2"
diff --git a/main/mt-st/APKBUILD b/main/mt-st/APKBUILD
new file mode 100644
index 0000000000..add803b271
--- /dev/null
+++ b/main/mt-st/APKBUILD
@@ -0,0 +1,41 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=mt-st
+pkgver=1.1
+pkgrel=1
+pkgdesc="Linux SCSI tape driver aware magnetic tape control"
+url="http://www.ibiblio.org/pub/linux/system/backup/"
+arch="all"
+license="GPL2"
+depends=
+makedepends=
+install="$pkgname.post-deinstall"
+subpackages="$pkgname-doc"
+source="http://www.ibiblio.org/pub/linux/system/backup/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+#prepare() {
+# cd "$_builddir"
+# # apply patches here
+#}
+
+build() {
+ cd "$_builddir"
+# ./configure --prefix=/usr \
+# --sysconfdir=/etc \
+# --mandir=/usr/share/man \
+# --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ for dir in sbin bin usr/share/man/man1 usr/share/man/man8
+ do
+ mkdir -p $pkgdir/$dir || return 1
+ done
+ make SBINDIR=$pkgdir/sbin BINDIR=$pkgdir/bin \
+ MANDIR=$pkgdir/usr/share/man install || return 1
+}
+
+md5sums="fdd5f5ec673c9f630a102ceff7612774 mt-st-1.1.tar.gz"
diff --git a/main/mt-st/mt-st.post-deinstall b/main/mt-st/mt-st.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/mt-st/mt-st.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/mtools/APKBUILD b/main/mtools/APKBUILD
new file mode 100644
index 0000000000..05f1ee0c43
--- /dev/null
+++ b/main/mtools/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mtools
+pkgver=4.0.16
+pkgrel=0
+pkgdesc="A collection of utilities to access MS-DOS disks from Unix without mounting them"
+url="http://www.gnu.org/software/mtools/"
+arch="all"
+license="GPL"
+depends=
+makedepends="texinfo"
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.bz2"
+subpackages="$pkgname-doc"
+
+build () {
+ cd $srcdir/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --sysconfdir=/etc \
+ --without-x
+ make || return 1
+}
+
+package() {
+ cd $srcdir/$pkgname-$pkgver
+ make -j1 install DESTDIR="$pkgdir"
+}
+
+md5sums="e9b07f35272210f407012abaf5d1b9b5 mtools-4.0.16.tar.bz2"
diff --git a/main/mtx/APKBUILD b/main/mtx/APKBUILD
new file mode 100644
index 0000000000..a9f5911835
--- /dev/null
+++ b/main/mtx/APKBUILD
@@ -0,0 +1,24 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname="mtx"
+pkgver=1.3.12
+pkgrel=2
+pkgdesc="SCSI Media Changer and Backup Device Control"
+url="http://mtx.opensource-sw.net/"
+arch="all"
+license="GPL2"
+depends=""
+makedepends=""
+install=""
+subpackages=""
+source="http://downloads.sourceforge.net/mtx/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --datadir=/usr/share
+ make || return 1
+ make prefix="$pkgdir" install
+}
+
+md5sums="ce8f0e44671fb0c7d9ec30bb0bfa8b5c mtx-1.3.12.tar.gz"
diff --git a/main/multipath-tools/APKBUILD b/main/multipath-tools/APKBUILD
new file mode 100644
index 0000000000..5355205dbe
--- /dev/null
+++ b/main/multipath-tools/APKBUILD
@@ -0,0 +1,47 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname="multipath-tools"
+pkgver=0.4.9
+pkgrel=2
+pkgdesc="Device Mapper Multipathing Driver"
+url="http://christophe.varoqui.free.fr/"
+arch="all"
+license="GPL"
+depends=
+makedepends="lvm2-dev libaio-dev readline-dev ncurses-dev udev-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://christophe.varoqui.free.fr/$pkgname/$pkgname-$pkgver.tar.bz2
+ multipath-tools-0.4.9-build.patch
+ multipath-tools-0.4.8-kparted-ext-partitions.patch"
+
+_builddir="$srcdir"
+
+prepare() {
+ cd $_builddir
+ find . -name Makefile -exec sed -i -e 's/glibc/uclibc/g' {} \;
+ for i in ../*.patch
+ do
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+}
+
+build() {
+ cd $_builddir
+ make -j1 prefix="/usr" \
+ sysconfdir="/etc" \
+ mandir="/usr/share/man" \
+ infodir="/usr/share/info" || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ install -D -m644 ../$pkgname.conf $pkgdir/etc/multipath.conf
+ install -D -m755 ../$pkgname.initd $pkgdir/etc/init.d/multipathd
+}
+
+md5sums="a6d4b48afc28f1f50f5ee4b1b06d2765 multipath-tools-0.4.9.tar.bz2
+751a7e079fef26cced73e2fc31ad7f11 multipath-tools-0.4.9-build.patch
+68ea053e02e9f5c4883b24b3f9bb2bf1 multipath-tools-0.4.8-kparted-ext-partitions.patch"
diff --git a/main/multipath-tools/multipath-tools-0.4.8-kparted-ext-partitions.patch b/main/multipath-tools/multipath-tools-0.4.8-kparted-ext-partitions.patch
new file mode 100644
index 0000000000..3f70fd70e4
--- /dev/null
+++ b/main/multipath-tools/multipath-tools-0.4.8-kparted-ext-partitions.patch
@@ -0,0 +1,28 @@
+From c421c9282791696264d1333fb2552835140354c3 Mon Sep 17 00:00:00 2001
+From: Robin H. Johnson <robbat2@gentoo.org>
+Date: Thu, 5 Nov 2009 03:44:12 +0000
+Subject: [PATCH] kpartx: Fix broken calculation of extended partitions that caused random devices to be used instead of the correct parent device.
+
+Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
+---
+ kpartx/dos.c | 4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/kpartx/dos.c b/kpartx/dos.c
+index 1691105..317fc56 100644
+--- a/kpartx/dos.c
++++ b/kpartx/dos.c
+@@ -53,7 +53,9 @@ read_extended_partition(int fd, struct partition *ep, int en,
+ if (n < ns) {
+ sp[n].start = here + le32_to_cpu(p.start_sect);
+ sp[n].size = le32_to_cpu(p.nr_sects);
+- sp[n].container = en + 1;
++ // This line seems to have no understandable
++ // purpose, and causes the wrong device to be used
++ //sp[n].container = en + 1;
+ n++;
+ } else {
+ fprintf(stderr,
+--
+1.6.4
+
diff --git a/main/multipath-tools/multipath-tools-0.4.9-buffer-overflows.patch b/main/multipath-tools/multipath-tools-0.4.9-buffer-overflows.patch
new file mode 100644
index 0000000000..38719acebe
--- /dev/null
+++ b/main/multipath-tools/multipath-tools-0.4.9-buffer-overflows.patch
@@ -0,0 +1,22 @@
+--- multipath-tools-0.4.9.orig/libmultipath/prioritizers/datacore.c 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/libmultipath/prioritizers/datacore.c 2010-11-28 12:22:12.037228583 -0800
+@@ -94,7 +94,7 @@
+ if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
+ return 0;
+
+- snprintf(vendor, 9, "%.8s\n", inqBuffp + 8);
++ snprintf(vendor, 8, "%.8s\n", inqBuffp + 8);
+ snprintf(product, 17, "%.16s", inqBuffp + 16);
+ snprintf(luname, 21, "%.19s", inqBuffp + 36);
+ snprintf(wwpn, 17, "%.16s", inqBuffp + 96);
+--- multipath-tools-0.4.9.orig/libmultipath/prioritizers/hds.c 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/libmultipath/prioritizers/hds.c 2010-11-28 12:22:44.199483997 -0800
+@@ -123,7 +123,7 @@
+ return -1;
+ }
+
+- snprintf (vendor, 9, "%.8s", inqBuffp + 8);
++ snprintf (vendor, 8, "%.8s", inqBuffp + 8);
+ snprintf (product, 17, "%.16s", inqBuffp + 16);
+ snprintf (serial, 5, "%.4s", inqBuffp + 40);
+ snprintf (ldev, 5, "%.4s", inqBuffp + 44);
diff --git a/main/multipath-tools/multipath-tools-0.4.9-build.patch b/main/multipath-tools/multipath-tools-0.4.9-build.patch
new file mode 100644
index 0000000000..8c4b1da45d
--- /dev/null
+++ b/main/multipath-tools/multipath-tools-0.4.9-build.patch
@@ -0,0 +1,138 @@
+--- multipath-tools-0.4.9.orig/kpartx/Makefile 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/kpartx/Makefile 2010-10-22 00:48:25.615627572 -0700
+@@ -6,7 +6,7 @@
+
+ CFLAGS += -I. -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+
+-LDFLAGS = -ldevmapper
++LIBS = -ldevmapper
+ OBJS = bsd.o dos.o kpartx.o solaris.o unixware.o dasd.o sun.o \
+ gpt.o mac.o crc32.o lopart.o xstrncpy.o devmapper.o
+ EXEC = kpartx
+@@ -14,8 +14,7 @@
+ all: $(EXEC)
+
+ $(EXEC): $(OBJS)
+- $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
+- $(GZIP) $(EXEC).8 > $(EXEC).8.gz
++ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(EXEC)
+
+ install: $(EXEC) $(EXEC).8
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
+@@ -23,13 +22,14 @@
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir)
+ $(INSTALL_PROGRAM) -m 755 kpartx_id $(DESTDIR)$(libudevdir)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d
+- $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/
++ $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/66-kpartx.rules
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
+- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
++ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
+
+ uninstall:
+ rm -f $(DESTDIR)$(bindir)/$(EXEC)
+- rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
++ rm -f $(DESTDIR)$(mandir)/$(EXEC).8
++ rm -f $(DESTDIR)/etc/udev/rules.d/66-kpartx.rules
+
+ clean:
+- rm -f core *.o $(EXEC) *.gz
++ rm -f core *.o $(EXEC)
+--- multipath-tools-0.4.9.orig/Makefile.inc 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/Makefile.inc 2010-10-21 23:51:12.768868148 -0700
+@@ -32,11 +32,10 @@
+ syslibdir = $(prefix)/$(LIB)
+ libdir = $(prefix)/$(LIB)/multipath
+
+-GZIP = /bin/gzip -9 -c
+ INSTALL_PROGRAM = install
+
+-OPTFLAGS = -pipe -g -Wall -Wunused -Wstrict-prototypes
+-CFLAGS = $(OPTFLAGS) -fPIC -DLIB_STRING=\"${LIB}\"
++OPTFLAGS = -Wall -Wunused -Wstrict-prototypes
++CFLAGS += $(OPTFLAGS) -fPIC -DLIB_STRING=\"${LIB}\"
+ SHARED_FLAGS = -shared
+
+ %.o: %.c
+--- multipath-tools-0.4.9.orig/multipath/Makefile 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/multipath/Makefile 2010-10-22 00:47:13.952010117 -0700
+@@ -7,32 +7,30 @@
+ OBJS = main.o
+
+ CFLAGS += -I$(multipathdir)
+-LDFLAGS += -lpthread -ldevmapper -ldl -lmultipath -L$(multipathdir)
++LIBS = -lpthread -ldevmapper -ldl -lmultipath -L$(multipathdir)
+
+ EXEC = multipath
+
+ all: $(EXEC)
+
+ $(EXEC): $(OBJS)
+- $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS)
+- $(GZIP) $(EXEC).8 > $(EXEC).8.gz
+- $(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
++ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(EXEC)
+
+ install:
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d
+- $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/
++ $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/65-multipath.rules
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
+- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
++ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
+- $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
++ $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(man5dir)
+
+ uninstall:
+- rm $(DESTDIR)/etc/udev/rules.d/multipath.rules
+- rm $(DESTDIR)$(bindir)/$(EXEC)
+- rm $(DESTDIR)$(mandir)/$(EXEC).8.gz
+- rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
++ rm -f $(DESTDIR)/etc/udev/rules.d/65-multipath.rules
++ rm -f $(DESTDIR)$(bindir)/$(EXEC)
++ rm -f $(DESTDIR)$(mandir)/$(EXEC).8
++ rm -f $(DESTDIR)$(man5dir)/$(EXEC).conf.5
+
+ clean:
+- rm -f core *.o $(EXEC) *.gz
++ rm -f core *.o $(EXEC)
+--- multipath-tools-0.4.9.orig/multipathd/Makefile 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/multipathd/Makefile 2010-10-22 00:48:02.502428428 -0700
+@@ -6,7 +6,7 @@
+ # basic flags setting
+ #
+ CFLAGS += -I$(multipathdir)
+-LDFLAGS += -lpthread -ldevmapper -lreadline -lncurses -ldl \
++LIBS += -lpthread -ldevmapper -lreadline -lncurses -ldl \
+ -lmultipath -L$(multipathdir)
+
+ #
+@@ -28,21 +28,20 @@
+ all : $(EXEC)
+
+ $(EXEC): $(OBJS)
+- $(CC) $(CFLAGS) $(LDFLAGS) -o $(EXEC) $(OBJS)
+- $(GZIP) $(EXEC).8 > $(EXEC).8.gz
++ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(EXEC)
+
+ install:
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
+- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
++ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
+
+ uninstall:
+ rm -f $(DESTDIR)$(bindir)/$(EXEC)
+ rm -f $(DESTDIR)$(rcdir)/$(EXEC)
+- rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
++ rm -f $(DESTDIR)$(mandir)/$(EXEC).8
+
+ clean:
+- rm -f core *.o $(EXEC) *.gz
++ rm -f core *.o $(EXEC)
+
diff --git a/main/multipath-tools/multipath-tools.conf b/main/multipath-tools/multipath-tools.conf
new file mode 100644
index 0000000000..11194176df
--- /dev/null
+++ b/main/multipath-tools/multipath-tools.conf
@@ -0,0 +1,113 @@
+##
+## This is a template multipath-tools configuration file
+## Uncomment the lines relevent to your environment
+##
+#defaults {
+# udev_dir /dev
+# polling_interval 10
+# selector "round-robin 0"
+# path_grouping_policy multibus
+# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n"
+# prio_callout /bin/true
+# path_checker directio
+# rr_min_io 100
+# rr_weight priorities
+# failback immediate
+# no_path_retry fail
+# user_friendly_names no
+#}
+#blacklist {
+# wwid 26353900f02796769
+# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
+# devnode "^hd[a-z][[0-9]*]"
+# devnode "^cciss!c[0-9]d[0-9]*[p[0-9]*]"
+# device {
+# vendor DEC.*
+# product MSA[15]00
+# }
+#}
+#blacklist_exceptions {
+# devnode "^dasd[c-d]+[0-9]*"
+# wwid "IBM.75000000092461.4d00.34"
+#}
+#multipaths {
+# multipath {
+# wwid 3600508b4000156d700012000000b0000
+# alias yellow
+# path_grouping_policy multibus
+# path_checker directio
+# path_selector "round-robin 0"
+# failback manual
+# rr_weight priorities
+# no_path_retry 5
+# rr_min_io 100
+# }
+# multipath {
+# wwid 1DEC_____321816758474
+# alias red
+# }
+#}
+#devices {
+# device {
+# vendor "COMPAQ "
+# product "HSV110 (C)COMPAQ"
+# path_grouping_policy multibus
+# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n"
+# path_checker directio
+# path_selector "round-robin 0"
+# hardware_handler "0"
+# failback 15
+# rr_weight priorities
+# no_path_retry queue
+# rr_min_io 100
+# product_blacklist LUN_Z
+# }
+# device {
+# vendor "COMPAQ "
+# product "MSA1000 "
+# path_grouping_policy multibus
+# }
+#}
+
+#defaults {
+# udev_dir /dev
+# user_friendly_names yes
+#}
+
+#blacklist {
+# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
+# devnode "^hd[a-z]"
+# devnode "^sda"
+# devnode "^sdb"
+# devnode "^sdc"
+# devnode "^sdd"
+# devnode "^sda[0-9]"
+# devnode "^sdb[0-9]"
+# device {
+# vendor DELL
+# product "PERC|Universal"
+# }
+#}
+
+#devices {
+# device {
+# vendor DELL
+# product MD3000i
+# hardware_handler "1 rdac"
+# path_checker rdac
+# path_grouping_policy group_by_prio
+# prio_callout "/sbin/mpath_prio_rdac /dev/%n"
+# failback immediate
+# getuid_callout "/lib/udev/scsi_id -g -u -s /block/%n"
+# }
+#}
+
+#multipaths {
+# multipath {
+# device {
+# vendor DELL
+# product MD3000i
+# }
+# }
+#}
+
diff --git a/main/multipath-tools/multipath-tools.initd b/main/multipath-tools/multipath-tools.initd
new file mode 100644
index 0000000000..931bc313d0
--- /dev/null
+++ b/main/multipath-tools/multipath-tools.initd
@@ -0,0 +1,20 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/sys-fs/multipath-tools/files/rc-multipathd,v 1.5 2009/03/17 22:48:13 solar Exp $
+
+depend() {
+ after firewall
+}
+
+start() {
+ ebegin "Starting multipathd"
+ start-stop-daemon --start --quiet --exec /sbin/multipathd
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping multipathd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/multipathd.pid
+ eend $?
+}
diff --git a/main/mutt/APKBUILD b/main/mutt/APKBUILD
new file mode 100644
index 0000000000..e27b44dd0b
--- /dev/null
+++ b/main/mutt/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: Andrew Manison<amanison@anselsystems.com>
+# Maintainer: Andrew Manison<amanison@anselsystems.com>
+pkgname=mutt
+pkgver=1.4.2.3
+pkgrel=4
+pkgdesc="a small but very powerful text-mode email client"
+url="http://www.mutt.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev ncurses-dev libiconv-dev gettext-dev"
+install=
+subpackages="$pkgname-doc"
+source="ftp://ftp.mutt.org/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-imap \
+ --enable-pop \
+ --enable-smtp \
+ --with-curses \
+ --with-mailpath=/var/spool/mail \
+ --with-docdir=/usr/share/doc/mutt \
+ --without-included-gettext \
+ --with-ssl
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="dcb94661827dd090fa813e73e122ea0c mutt-1.4.2.3.tar.gz"
diff --git a/main/mysql/0001-prefer-dynamic-library.patch b/main/mysql/0001-prefer-dynamic-library.patch
new file mode 100644
index 0000000000..f2ff4da620
--- /dev/null
+++ b/main/mysql/0001-prefer-dynamic-library.patch
@@ -0,0 +1,72 @@
+From 7c79a4adc72407b7265bc1508f6950d505ab1a17 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Fri, 1 Apr 2011 12:58:59 +0000
+Subject: [PATCH] prefer dynamic library
+
+we link to the dynamic library *and* the static so we get all used
+symbols in the client apps.
+
+Linking to dynamic will make mysql client 300k instead of 3M
+---
+ client/CMakeLists.txt | 20 ++++++++++----------
+ 1 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
+index 80c5bbd..21c6a58 100644
+--- a/client/CMakeLists.txt
++++ b/client/CMakeLists.txt
+@@ -28,41 +28,41 @@ INCLUDE_DIRECTORIES(
+ ADD_DEFINITIONS(${READLINE_DEFINES})
+ ADD_DEFINITIONS(${SSL_DEFINES})
+ MYSQL_ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc)
+-TARGET_LINK_LIBRARIES(mysql mysqlclient)
++TARGET_LINK_LIBRARIES(mysql libmysql mysqlclient)
+ IF(UNIX)
+ TARGET_LINK_LIBRARIES(mysql ${READLINE_LIBRARY})
+ ENDIF(UNIX)
+
+ MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc COMPONENT Test)
+ SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS")
+-TARGET_LINK_LIBRARIES(mysqltest mysqlclient regex)
++TARGET_LINK_LIBRARIES(mysqltest libmysql mysqlclient regex)
+
+
+ MYSQL_ADD_EXECUTABLE(mysqlcheck mysqlcheck.c)
+-TARGET_LINK_LIBRARIES(mysqlcheck mysqlclient)
++TARGET_LINK_LIBRARIES(mysqlcheck libmysql mysqlclient)
+
+ MYSQL_ADD_EXECUTABLE(mysqldump mysqldump.c ../sql-common/my_user.c)
+-TARGET_LINK_LIBRARIES(mysqldump mysqlclient)
++TARGET_LINK_LIBRARIES(mysqldump libmysql mysqlclient)
+
+ MYSQL_ADD_EXECUTABLE(mysqlimport mysqlimport.c)
+-TARGET_LINK_LIBRARIES(mysqlimport mysqlclient)
++TARGET_LINK_LIBRARIES(mysqlimport libmysql mysqlclient)
+
+ MYSQL_ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c)
+-TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient)
++TARGET_LINK_LIBRARIES(mysql_upgrade libmysql mysqlclient)
+ ADD_DEPENDENCIES(mysql_upgrade GenFixPrivs)
+
+ MYSQL_ADD_EXECUTABLE(mysqlshow mysqlshow.c)
+-TARGET_LINK_LIBRARIES(mysqlshow mysqlclient)
++TARGET_LINK_LIBRARIES(mysqlshow libmysql mysqlclient)
+
+ MYSQL_ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc)
+-TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient)
++TARGET_LINK_LIBRARIES(mysqlbinlog libmysql mysqlclient)
+
+ MYSQL_ADD_EXECUTABLE(mysqladmin mysqladmin.cc)
+-TARGET_LINK_LIBRARIES(mysqladmin mysqlclient)
++TARGET_LINK_LIBRARIES(mysqladmin libmysql mysqlclient)
+
+ MYSQL_ADD_EXECUTABLE(mysqlslap mysqlslap.c)
+ SET_SOURCE_FILES_PROPERTIES(mysqlslap.c PROPERTIES COMPILE_FLAGS "-DTHREADS")
+-TARGET_LINK_LIBRARIES(mysqlslap mysqlclient)
++TARGET_LINK_LIBRARIES(mysqlslap libmysql mysqlclient)
+
+ # "WIN32" also covers 64 bit. "echo" is used in some files below "mysql-test/".
+ IF(WIN32)
+--
+1.7.4.2
+
diff --git a/main/mysql/APKBUILD b/main/mysql/APKBUILD
new file mode 100644
index 0000000000..eaf95fa203
--- /dev/null
+++ b/main/mysql/APKBUILD
@@ -0,0 +1,191 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=mysql
+pkgver=5.5.13
+pkgrel=0
+pkgdesc="A fast SQL database server"
+url="http://www.mysql.com/"
+pkgusers="mysql"
+pkggroups="mysql"
+arch="all"
+license='GPL'
+depends="mysql-common"
+depends_dev="openssl-dev zlib-dev"
+makedepends="libtool readline-dev openssl-dev ncurses-dev zlib-dev cmake bison perl libaio-dev"
+source="ftp://mirror.switch.ch/mirror/mysql/Downloads/MySQL-5.5/mysql-$pkgver.tar.gz
+ 0001-prefer-dynamic-library.patch
+ $pkgname.initd
+ "
+subpackages="$pkgname-doc $pkgname-dev $pkgname-libs $pkgname-test:mytest
+ $pkgname-common $pkgname-client $pkgname-bench"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ cmake . -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=/usr \
+ -DDEFAULT_CHARSET=utf8 \
+ -DDEFAULT_COLLATION=utf8_general_ci \
+ -DENABLED_LOCAL_INFILE=ON \
+ -DINSTALL_DOCDIR=share/doc/mysql \
+ -DINSTALL_DOCREADMEDIR=share/doc/mysql \
+ -DINSTALL_INCLUDEDIR=include/mysql \
+ -DINSTALL_INFODIR=share/info \
+ -DINSTALL_LAYOUT=RPM \
+ -DINSTALL_LIBDIR=lib \
+ -DINSTALL_MANDIR=share/man \
+ -DINSTALL_MYSQLDATADIR="/var/lib/mysql" \
+ -DINSTALL_MYSQLSHAREDIR=share/mysql \
+ -DINSTALL_MYSQLTESTDIR=share/mysql-test \
+ -DINSTALL_PLUGINDIR=lib/mysql/plugin \
+ -DINSTALL_SCRIPTDIR=bin \
+ -DINSTALL_SHAREDIR=share/mysql \
+ -DINSTALL_SQLBENCHDIR=share \
+ -DINSTALL_SUPPORTFILESDIR=share/mysql \
+ -DMYSQL_DATADIR="/var/lib/mysql" \
+ -DMYSQL_UNIX_ADDR="/var/run/mysqld/mysqld.sock" \
+ -DSYSCONFDIR=/etc/mysql \
+ -DWITHOUT_ARCHIVE_STORAGE_ENGINE=1 \
+ -DWITHOUT_BLACKHOLE_STORAGE_ENGINE=1 \
+ -DWITHOUT_EMBEDDED_SERVER=ON \
+ -DWITHOUT_EXAMPLE_STORAGE_ENGINE=1 \
+ -DWITHOUT_FEDERATED_STORAGE_ENGINE=1 \
+ -DWITH_EXTRA_CHARSETS=complex \
+ -DWITH_INNOBASE_STORAGE_ENGINE=1 \
+ -DWITH_PARTITION_STORAGE_ENGINE=1 \
+ -DWITH_READLINE=ON \
+ -DWITH_SSL=system \
+ -DWITH_ZLIB=system \
+ || return 1
+ make || return 1
+}
+
+# -DWITH_LIBWRAP=ON \
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir/" install || return 1
+
+ install -Dm 755 "$startdir"/$pkgname.initd \
+ "$pkgdir"/etc/init.d/$pkgname || return 1
+
+ # use small example config as default, which has tcp disabled
+ install -D "$pkgdir"/usr/share/mysql/my-medium.cnf \
+ "$pkgdir"/etc/mysql/my.cnf || return 1
+
+ install -dDo mysql "$pkgdir"/var/log/mysql || return 1
+ install -dDo mysql "$pkgdir"/var/run/mysqld || return 1
+
+ # libmysqlclient_r is no more. Upstream tries to replace it with
+ # symlinks but that really doesn't work (wrong soname in particular).
+ # We'll keep just the devel libmysqlclient_r.so link, so that
+ # rebuilding without any source change is enough to get rid of
+ # dependency on libmysqlclient_r.
+ rm -f "$pkgdir"/usr/lib/libmysqlclient_r.so*
+ ln -s libmysqlclient.so "$pkgdir"/usr/lib/libmysqlclient_r.so
+
+ # mysql-test includes one executable that doesn't belong under
+ # /usr/share, so move it and provide a symlink
+ mv "$pkgdir"/usr/share/mysql-test/lib/My/SafeProcess/my_safe_process \
+ "$pkgdir"/usr/bin
+ ln -s ../../../../../bin/my_safe_process \
+ "$pkgdir"/usr/share/mysql-test/lib/My/SafeProcess/my_safe_process
+
+}
+
+dev(){
+ default_dev
+ replaces="libmysqlclient"
+}
+
+libs() {
+ pkgdesc="MySQL client library"
+ # some files moved
+ replaces="mysql libmysqlclient"
+ depends="mysql-common"
+ mkdir -p "$subpkgdir"/usr/lib \
+ "$subpkgdir"/usr/share/mysql \
+ || return 1
+ mv "$pkgdir"/usr/lib/libmysqlclient.so* \
+ "$subpkgdir"/usr/lib/ || return 1
+}
+
+common() {
+ pkgdesc="MySQL common files for both server and client"
+ replaces="mysql"
+ mkdir -p "$subpkgdir"/usr/share/mysql \
+ mv "$pkgdir"/etc "$subpkgdir"/ || return 1
+ mv "$pkgdir"/usr/share/mysql/english \
+ "$pkgdir"/usr/share/mysql/czech \
+ "$pkgdir"/usr/share/mysql/danish \
+ "$pkgdir"/usr/share/mysql/dutch \
+ "$pkgdir"/usr/share/mysql/estonian \
+ "$pkgdir"/usr/share/mysql/french \
+ "$pkgdir"/usr/share/mysql/german \
+ "$pkgdir"/usr/share/mysql/greek \
+ "$pkgdir"/usr/share/mysql/hungarian \
+ "$pkgdir"/usr/share/mysql/italian \
+ "$pkgdir"/usr/share/mysql/japanese \
+ "$pkgdir"/usr/share/mysql/korean \
+ "$pkgdir"/usr/share/mysql/norwegian \
+ "$pkgdir"/usr/share/mysql/norwegian-ny \
+ "$pkgdir"/usr/share/mysql/polish \
+ "$pkgdir"/usr/share/mysql/portuguese \
+ "$pkgdir"/usr/share/mysql/romanian \
+ "$pkgdir"/usr/share/mysql/russian \
+ "$pkgdir"/usr/share/mysql/serbian \
+ "$pkgdir"/usr/share/mysql/slovak \
+ "$pkgdir"/usr/share/mysql/spanish \
+ "$pkgdir"/usr/share/mysql/swedish \
+ "$pkgdir"/usr/share/mysql/ukrainian \
+ "$pkgdir"/usr/share/mysql/charsets \
+ "$subpkgdir"/usr/share/mysql/ \
+ || return 1
+}
+
+mytest() {
+ pkgdesc="The test suite distributed with MySQL"
+ mkdir -p "$subpkgdir"/usr || return 1
+ mv "$pkgdir"/usr/share/mysql-test \
+ "$subpkgdir"/usr/share/ \
+ || return 1
+ mv "$pkgdir"/usr/bin/mysql_client_test \
+ "$pkgdir"/usr/bin/my_safe_process \
+ "$pkgdir"/usr/bin/ \
+ || return 1
+}
+
+client() {
+ pkgdesc="client for the MySQL database"
+ depends="mysql-common"
+ install=""
+ local bins="myisam_ftdump mysql mysqlaccess mysqladmin mysqlbug
+ mysqlcheck mysql_client_test mysqldump mysqldumpslow mysql_find_rows
+ mysql_fix_extensions mysqlimport mysqlshow mysql_waitpid"
+
+ mkdir -p "$subpkgdir"/usr/bin/ || return 1
+
+ for i in $bins; do
+ mv "$pkgdir"/usr/bin/${i} "$subpkgdir"/usr/bin/ || return 1
+ done
+}
+
+bench() {
+ pkgdesc="MySQL benchmark scripts and data"
+ replaces="mysql"
+ mkdir -p "$subpkgdir"/usr/share/
+ mv "$pkgdir"/usr/share/sql-bench "$subpkgdir"/usr/share/
+}
+
+md5sums="f0e519e90ee7c00fceb0730edf859d7b mysql-5.5.13.tar.gz
+4e07e045a3abcb457c9c148dfd929ed6 0001-prefer-dynamic-library.patch
+d46df8ab94cb5686862ff90c0a6bf707 mysql.initd"
diff --git a/main/mysql/mysql.initd b/main/mysql/mysql.initd
new file mode 100644
index 0000000000..698067d49d
--- /dev/null
+++ b/main/mysql/mysql.initd
@@ -0,0 +1,58 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-db/mysql/files/mysql.init,v 1.7 2004/07/14 21:41:15 agriffis Exp $
+
+opts="${opts} setup"
+pidfile=/var/run/mysqld/mysqld.pid
+
+depend() {
+ need net
+ after firewall
+ use dns
+}
+
+setup() {
+ ebegin "Creating a new MySQL database"
+ mysql_install_db --user=mysql --rpm
+ eend $?
+}
+
+checkconfig() {
+ if [ ! -f /etc/mysql/my.cnf ] ; then
+ eerror "No /etc/mysql/my.cnf file exists!"
+ fi
+
+ dir=`my_print_defaults mysqld | grep -- --datadir | sed -e "s|^.*=\(.*\)|\1|"`
+
+ dir=${dir:-/var/lib/mysql}
+ [ -d ${dir}/mysql ] && return 0
+
+ if [ -z "$AUTO_SETUP" ] ; then
+ eerror "Database not found in $dir"
+ eerror "You can run '/etc/init.d/mysql setup' to setup a new database."
+ return 1
+ fi
+ setup
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting mysqld"
+ start-stop-daemon --pidfile $pidfile \
+ --start \
+ --background \
+ --stdout /dev/null \
+ --stderr /dev/null \
+ --wait 500 \
+ -- \
+ /usr/bin/mysqld_safe --pid-file=$pidfile
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping mysqld"
+ start-stop-daemon --stop --quiet \
+ --pidfile $pidfile --retry 20
+ eend $?
+}
diff --git a/main/nagios-plugins/APKBUILD b/main/nagios-plugins/APKBUILD
new file mode 100644
index 0000000000..8cdc5d3c8f
--- /dev/null
+++ b/main/nagios-plugins/APKBUILD
@@ -0,0 +1,55 @@
+# Maintainer: Jeff Bilyk <jbilyk@gmail.com>
+pkgname=nagios-plugins
+pkgver=1.4.15
+pkgrel=5
+pkgdesc="Plugins for Nagios to check services on hosts"
+url="http://nagiosplugins.org"
+arch="all"
+license="GPL-2"
+depends="nagios fping net-snmp-tools bind-tools nrpe-plugin"
+makedepends="net-snmp-tools openssl-dev openldap-dev mysql-dev postgresql-dev libpq"
+source="http://downloads.sourceforge.net/nagiosplug/$pkgname-$pkgver.tar.gz"
+pkgusers="nagios"
+pkggroups="nagios"
+subpackages="$pkgname-contrib"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --bindir=/usr/sbin \
+ --libexecdir=/usr/lib/nagios/plugins \
+ --localstatedir=/var/nagios \
+ --with-ps-command="/bin/ps" \
+ --with-ps-format="%d %s %s %s" \
+ --with-ps-varlist="&procpid,&procuid,&procpcpu,procprog" \
+ --with-ps-cols=4 \
+ --with-ping-command="/bin/ping -c %d %s"
+ make all || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+contrib() {
+ pkgdesc="Contrib Plugins for Nagios"
+ cd "$pkgdir"
+ mkdir -p ${pkgdir}-contrib
+ cd ${pkgdir}-contrib
+ mkdir -p "${pkgdir}"-contrib/usr/lib/nagios/plugins/
+ cp "$srcdir"/$pkgname-$pkgver/contrib/*.sh "${pkgdir}"-contrib/usr/lib/nagios/plugins/
+ cp "$srcdir"/$pkgname-$pkgver/contrib/*.pl "${pkgdir}"-contrib/usr/lib/nagios/plugins/
+ cp "$srcdir"/$pkgname-$pkgver/contrib/*.pm "${pkgdir}"-contrib/usr/lib/nagios/plugins/
+ cp "$srcdir"/$pkgname-$pkgver/contrib/*.py "${pkgdir}"-contrib/usr/lib/nagios/plugins/
+ chmod a+x "${pkgdir}"-contrib/usr/lib/nagios/plugins/*.sh
+ chmod a+x "${pkgdir}"-contrib/usr/lib/nagios/plugins/*.pl
+ chmod a+x "${pkgdir}"-contrib/usr/lib/nagios/plugins/*.pm
+ chmod a+x "${pkgdir}"-contrib/usr/lib/nagios/plugins/*.py
+}
+
+
+md5sums="56abd6ade8aa860b38c4ca4a6ac5ab0d nagios-plugins-1.4.15.tar.gz"
diff --git a/main/nagios/APKBUILD b/main/nagios/APKBUILD
new file mode 100644
index 0000000000..2bf7b6b54e
--- /dev/null
+++ b/main/nagios/APKBUILD
@@ -0,0 +1,65 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=nagios
+pkgver=3.2.3
+pkgrel=6
+pkgdesc="Popular monitoring tool"
+url="http://www.nagios.org/"
+arch="all"
+license="GPL-2"
+depends="perl"
+install="$pkgname.pre-install"
+makedepends="gd-dev pkgconfig perl-dev libpng-dev libjpeg"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ nagios.confd
+ nagios.initd
+ lighttpd-nagios.conf"
+subpackages="${pkgname}-web"
+pkgusers="nagios"
+pkggroups="nagios"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/nagios \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --datadir=/usr/share/nagios \
+ --localstatedir=/var \
+ --bindir=/usr/sbin \
+ --sbindir=/usr/lib/nagios/cgi-bin \
+ --datadir=/usr/share/nagios/htdocs \
+ --libexecdir=/usr/lib/nagios/plugins \
+ --localstatedir=/var/nagios \
+ --with-nagios-user=nagios \
+ --with-nagios-group=nagios \
+ --enable-embedded-perl \
+ --with-perlcache
+ make all || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ make DESTDIR="$pkgdir" install-config
+ make DESTDIR="$pkgdir" install-commandmode
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+
+web() {
+ #depends="php lighttpd"
+ arch="noarch"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/share "$subpkgdir"/usr/
+ install -m644 -D "$srcdir"/lighttpd-nagios.conf "$subpkgdir"/etc/lighttpd/nagios.conf
+}
+
+md5sums="fe1be46e6976a52acdb021a782b5d04b nagios-3.2.3.tar.gz
+431dfe7403323e247a88b97beade5d78 nagios.confd
+2ead8695b32222abe922692664aa9de1 nagios.initd
+d63c36f47d26f1f71ae2faf272eec640 lighttpd-nagios.conf"
diff --git a/main/nagios/lighttpd-nagios.conf b/main/nagios/lighttpd-nagios.conf
new file mode 100644
index 0000000000..cb7081d841
--- /dev/null
+++ b/main/nagios/lighttpd-nagios.conf
@@ -0,0 +1,29 @@
+###
+# Sample nagios lighttpd config
+###
+
+server.modules += ("mod_cgi")
+server.modules += ("mod_auth")
+server.modules += ("mod_alias")
+
+auth.require += ( "/nagios" =>
+ (
+ "method" => "digest",
+ "realm" => "nagios",
+ "require" => "valid-user"
+ )
+)
+
+$HTTP["url"] =~ "^/nagios/cgi-bin/" {
+ dir-listing.activate = "disable"
+ cgi.assign = (
+ ".pl" => "/usr/bin/perl",
+ ".cgi" => ""
+ )
+}
+
+alias.url += (
+ "/nagios/cgi-bin" => "/usr/lib/nagios/cgi-bin",
+ "/nagios" => "/usr/share/nagios/htdocs"
+)
+
diff --git a/main/nagios/nagios.confd b/main/nagios/nagios.confd
new file mode 100644
index 0000000000..0abb80c6e8
--- /dev/null
+++ b/main/nagios/nagios.confd
@@ -0,0 +1,9 @@
+# Sample conf.d file for alpine linux
+
+#
+# Specify daemon $OPTS here.
+#
+
+OPTS=""
+USER="nobody"
+GROUP="nobody"
diff --git a/main/nagios/nagios.initd b/main/nagios/nagios.initd
new file mode 100644
index 0000000000..e0b3bcf0c3
--- /dev/null
+++ b/main/nagios/nagios.initd
@@ -0,0 +1,39 @@
+#!/sbin/runscript
+
+# Sample init.d file for alpine linux.
+
+NAME=nagios
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet --background \
+ --make-pidfile --pidfile /var/run/${NAME}.pid \
+ --exec ${DAEMON} -- ${OPTS} /etc/nagios/nagios.cfg
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --exec ${DAEMON} \
+ --pidfile /var/run/${NAME}.pid \
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading ${NAME}"
+ if ! service_started "${NAME}" ; then
+ eend 1 "${NAME} is not started"
+ return 1
+ fi
+ start-stop-daemon --stop --oknodo --signal HUP \
+ --exec ${DAEMON} --pidfile /var/run/${NAME}.pid
+ eend $?
+}
+
diff --git a/main/nagios/nagios.pre-install b/main/nagios/nagios.pre-install
new file mode 100644
index 0000000000..52ca329000
--- /dev/null
+++ b/main/nagios/nagios.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup -S nagios 2>/dev/null
+adduser -S -G nagios -H -h /var/nagios -s /bin/false nagios 2>/dev/null
+exit 0
diff --git a/main/nagiosql/APKBUILD b/main/nagiosql/APKBUILD
new file mode 100644
index 0000000000..2dfb8ce695
--- /dev/null
+++ b/main/nagiosql/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Jeff Bilyk <jbilyk@gmail.com>
+pkgname=nagiosql
+pkgver=3.0.3
+_pkgverdown=303
+_pkgvermaj=3
+pkgrel=1
+pkgdesc="Web frontend to configure Nagios"
+url="http://www.nagiosql.org"
+arch="all"
+license="GPL"
+depends="lighttpd mysql php php-gettext php-ftp php-pear"
+makedepends=
+source="http://downloads.sourceforge.net/$pkgname/${pkgname}${_pkgverdown}.tar.gz
+http://download.pear.php.net/package/HTML_Template_IT-1.3.0.tgz"
+
+_builddir="$srcdir"/${pkgname}${_pkgvermaj}
+
+build() {
+ cd "$_builddir"
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/share/webapps/nagiosql
+ mkdir -p "$pkgdir"/usr/share/pear
+ cp -r "$srcdir"/HTML_Template_IT-1.3.0/* "$pkgdir"/usr/share/pear/
+ cp -r "$_builddir"/* "$pkgdir"/usr/share/webapps/nagiosql/
+ touch "$pkgdir"/usr/share/webapps/nagiosql/install/ENABLE_INSTALLER
+}
+
+md5sums="3b15650942cf0fea3b6bbec1700ace38 nagiosql303.tar.gz
+cbd2fcffd32a39da7b260397156bddbb HTML_Template_IT-1.3.0.tgz"
diff --git a/main/nano/APKBUILD b/main/nano/APKBUILD
new file mode 100644
index 0000000000..b90a26bc42
--- /dev/null
+++ b/main/nano/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=nano
+pkgver=2.2.6
+pkgrel=1
+pkgdesc="Text Editor. GNU nano is designed to be a free replacement for the Pico text editor."
+url="http://www.nano-editor.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://www.nano-editor.org/dist/v${pkgver%.*}/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls \
+ --disable-speller
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="03233ae480689a008eb98feb1b599807 nano-2.2.6.tar.gz"
diff --git a/main/nasm/APKBUILD b/main/nasm/APKBUILD
new file mode 100644
index 0000000000..e976ae2926
--- /dev/null
+++ b/main/nasm/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=nasm
+pkgver=2.09.08
+pkgrel=0
+pkgdesc="80x86 assembler designed for portability and modularity"
+url="http://nasm.sourceforge.net"
+arch="all"
+license="LGPL"
+depends=
+source="http://www.nasm.us/pub/nasm/releasebuilds/$pkgver/$pkgname-$pkgver.tar.bz2"
+
+subpackages="$pkgname-doc"
+
+build () {
+ cd "$srcdir/$pkgname-$pkgver"
+ export CFLAGS=
+ export CXXFLAGS=
+ ./configure --prefix=/usr
+ make nasmlib.o || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make INSTALLROOT="$pkgdir" install
+}
+md5sums="6abfa388a74ee47e163fdb30ecfd40f9 nasm-2.09.08.tar.bz2"
diff --git a/main/nautilus/APKBUILD b/main/nautilus/APKBUILD
new file mode 100644
index 0000000000..90df7a7469
--- /dev/null
+++ b/main/nautilus/APKBUILD
@@ -0,0 +1,62 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=nautilus
+pkgver=2.32.2
+pkgrel=2
+pkgdesc="GNOME file manager"
+url="http://projects.gnome.org/nautilus"
+arch="all"
+license="GPL"
+depends="zenity"
+depends_dev="gtk+-dev
+ gconf-dev
+ libx11-dev
+ gnome-doc-utils
+ libgnome-dev
+ gnome-desktop-dev
+ libwnck-dev
+ librsvg-dev
+ libunique-dev
+
+ libxcursor-dev
+ libxcomposite-dev
+ libxi-dev
+ libxau-dev
+ libxdmcp-dev
+ libxext-dev
+ libxcb-dev"
+makedepends="$depends_dev intltool gobject-introspection-dev"
+install="$pkgname.post-install $pkgname.pre-deinstall $pkgname.post-upgrade"
+subpackages="$pkgname-dev"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
+ make DESTDIR="$pkgdir" install || return 1
+
+ rm -rf ${pkgdir}/usr/share/mime
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="51565aa10d1625dff56e381228346911 nautilus-2.32.2.tar.bz2"
diff --git a/main/nautilus/nautilus.post-install b/main/nautilus/nautilus.post-install
new file mode 100644
index 0000000000..a4c26c32a9
--- /dev/null
+++ b/main/nautilus/nautilus.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in apps_nautilus_preferences.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/nautilus/nautilus.post-upgrade b/main/nautilus/nautilus.post-upgrade
new file mode 100644
index 0000000000..a4c26c32a9
--- /dev/null
+++ b/main/nautilus/nautilus.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in apps_nautilus_preferences.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/nautilus/nautilus.pre-deinstall b/main/nautilus/nautilus.pre-deinstall
new file mode 100644
index 0000000000..6902c6b290
--- /dev/null
+++ b/main/nautilus/nautilus.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in apps_nautilus_preferences.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/ncftp/APKBUILD b/main/ncftp/APKBUILD
new file mode 100644
index 0000000000..582ff63310
--- /dev/null
+++ b/main/ncftp/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=ncftp
+pkgver=3.2.5
+pkgrel=1
+pkgdesc="A set of free application programs implementing FTP"
+url="http://www.ncftp.com/"
+arch="all"
+license="custom"
+depends=
+makedepends="ncurses-dev"
+install="$pkgname.post-install"
+source="ftp://ftp.$pkgname.com/$pkgname/$pkgname-$pkgver-src.tar.bz2"
+subpackages="$pkgname-doc $pkgname-bookmarks"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ mkdir -p "$pkgdir"/usr/share || return 1
+}
+
+build () {
+ cd "$_builddir" || return 1
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man || return 1
+
+ cd "$_builddir"/libncftp
+ make shared || return 1
+ cd "$_builddir" || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"/libncftp
+ make PREFIX="${pkgdir}"/usr soinstall || return 1
+ cd "$_builddir" || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ install -D doc/LICENSE.txt "$pkgdir"/usr/share/licenses/"$pkgname"/LICENSE || return 1
+}
+
+bookmarks () {
+ install=""
+ mkdir -p "$subpkgdir"/usr/bin || return 1
+ mv "$pkgdir"/usr/bin/ncftpbookmarks "$subpkgdir"/usr/bin/ || return 1
+}
+
+md5sums="b05c7a6d5269c04891f02f43d4312b30 ncftp-3.2.5-src.tar.bz2"
diff --git a/main/ncftp/ncftp.post-install b/main/ncftp/ncftp.post-install
new file mode 100644
index 0000000000..e1ccb7b839
--- /dev/null
+++ b/main/ncftp/ncftp.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+echo '*'
+echo '* If you like to install the ncurses based bookmark manager run: '
+echo '*'
+echo '* apk_add ncftp-bookmarks'
+echo '*'
+exit 0
diff --git a/main/ncurses/APKBUILD b/main/ncurses/APKBUILD
new file mode 100644
index 0000000000..12bee4e515
--- /dev/null
+++ b/main/ncurses/APKBUILD
@@ -0,0 +1,87 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ncurses
+pkgver=5.9
+pkgrel=0
+pkgdesc="Console display library"
+url="http://www.gnu.org/software/ncurses/"
+arch="all"
+license=MIT
+depends=
+source="ftp://ftp.gnu.org/pub/gnu/${pkgname}/${pkgname}-${pkgver}.tar.gz"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-base $pkgname-terminfo
+ $pkgname-widec-libs:widec $pkgname-libs"
+
+build() {
+ local _confopts="--mandir=/usr/share/man
+ --disable-ada
+ --disable-termcap
+ --without-cxx-binding
+ --with-terminfo-dirs="/etc/terminfo:/usr/share/terminfo"
+ --with-shared"
+ cd "$srcdir/$pkgname-$pkgver"
+
+ mkdir ncurses-build ncursesw-build
+ cd ncurses-build
+ ../configure $_confopts || return 1
+ make libs || return 1
+ make -C progs || return 1
+
+ cd ../ncursesw-build
+ ../configure $_confopts --enable-widec --without-progs || return 1
+ make libs || return 1
+ cd ..
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 -C ncurses-build DESTDIR="$pkgdir" install.libs \
+ install.progs install.data || return 1
+
+ make -j1 -C ncursesw-build DESTDIR="$pkgdir" install.libs \
+ install.includes install.man || return 1
+
+ # Install basic terms in /etc/terminfo
+ for i in ansi console dumb linux rxvt screen sun vt52 vt100 vt102 \
+ vt200 vt220 xterm xterm-color xterm-xfree86; do
+ local termfile=$(find "$pkgdir"/usr/share/terminfo/ -name "$i" 2>/dev/null)
+ local basedir=$(basename $(dirname "$termfile"))
+
+ [ -z "$termfile" ] && continue
+
+ install -d "$pkgdir"/etc/terminfo/$basedir
+ mv ${termfile} "$pkgdir"/etc/terminfo/$basedir/
+ ln -s ../../../../etc/terminfo/$basedir/$i \
+ "$pkgdir"/usr/share/terminfo/$basedir/$i
+ done
+}
+
+terminfo() {
+ rm -rf $subpkgdir
+ mkdir -p $subpkgdir/usr/share
+ mv $pkgdir/usr/share/terminfo $subpkgdir/usr/share
+}
+
+widec() {
+ pkgdesc="Ncurses wide character libraries"
+ depends="ncurses-base"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/lib*w.so.* "$subpkgdir"/usr/lib/
+}
+
+libs() {
+ pkgdesc="Ncurses libraries"
+ replaces="ncurses"
+ depends="ncurses-base"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/lib "$subpkgdir"/usr/
+}
+
+
+base() {
+ pkgdesc="Descriptions of common terminals"
+ replaces="ncurses"
+ mkdir -p "$subpkgdir"/etc
+ mv "$pkgdir"/etc/terminfo "$subpkgdir"/etc/
+}
+
+md5sums="8cb9c412e5f2d96bc6f459aa8c6282a1 ncurses-5.9.tar.gz"
diff --git a/main/neon/APKBUILD b/main/neon/APKBUILD
new file mode 100644
index 0000000000..7c661c0f05
--- /dev/null
+++ b/main/neon/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=neon
+pkgver=0.29.6
+pkgrel=1
+pkgdesc="HTTP and WebDAV client library with a C interface"
+url="http://www.webdav.org/neon/"
+arch="all"
+license="GPL LGPL"
+makedepends="expat-dev openssl-dev zlib-dev"
+depends=
+depends_dev="$makedepends"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.webdav.org/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build () {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --with-ssl \
+ --with-expat \
+ --without-gssapi \
+ --disable-nls \
+ --disable-socks \
+ --enable-shared \
+ --disable-static \
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="591e0c82e6979e7e615211b386b8f6bc neon-0.29.6.tar.gz"
diff --git a/main/net-snmp/APKBUILD b/main/net-snmp/APKBUILD
new file mode 100644
index 0000000000..083f65e960
--- /dev/null
+++ b/main/net-snmp/APKBUILD
@@ -0,0 +1,75 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=net-snmp
+pkgver=5.6.1
+pkgrel=2
+pkgdesc="Simple Network Management Protocol"
+url="http://www.net-snmp.org/"
+arch="all"
+license="GPL"
+depends=
+depends_dev="openssl-dev"
+makedepends="perl-dev openssl-dev"
+subpackages="$pkgname-doc $pkgname-dev $pkgname-tools"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ snmpd.initd
+ snmpd.confd
+ snmptrapd.initd
+ snmptrapd.confd
+ "
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ cd "$_builddir"
+
+ export lt_cv_sys_max_cmd_len=8192
+
+ #build fails on: libnetsnmpmibs.so: undefined reference to `pthread_create'
+ LDFLAGS="$LDFLAGS -lpthread"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-default-snmp-version="3" \
+ --with-sys-contact="root@unknown" \
+ --with-sys-location="unknown" \
+ --with-logfile="/var/log/net-snmpd.log" \
+ --enable-ucd-snmp-compatibility \
+ --with-persistent-directory="/var/lib/net-snmp" \
+ --with-openssl \
+ --enable-ipv6 \
+ --enable-shared \
+ --enable-as-needed \
+ --disable-embedded-perl
+ # embedded-perl seems to create TEXTREL's
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ install -m755 -D "$srcdir"/snmpd.initd "$pkgdir"/etc/init.d/snmpd
+ install -m644 -D "$srcdir"/snmpd.confd "$pkgdir"/etc/conf.d/snmpd
+ install -m755 -D "$srcdir"/snmptrapd.initd "$pkgdir"/etc/init.d/snmptrapd
+ install -m644 -D "$srcdir"/snmptrapd.confd "$pkgdir"/etc/conf.d/snmptrapd
+ install -m644 -D EXAMPLE.conf "$pkgdir"/etc/snmp/snmpd.conf.example
+ mkdir -p "$pkgdir"/var/lib/net-snmp
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+tools() {
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr
+}
+
+
+md5sums="b4e30ead5783b0bb1d280172c6095ea4 net-snmp-5.6.1.tar.gz
+198a4a7b80557fa8112394df5ec9914e snmpd.initd
+96510a2f3bc9f21648b03f7e8d76c0d3 snmpd.confd
+7ce3e9e880fc6313ae87eb000bae4bda snmptrapd.initd
+363f7728a76bdfc46e29b7e1f5cf4950 snmptrapd.confd"
diff --git a/main/net-snmp/snmpd.confd b/main/net-snmp/snmpd.confd
new file mode 100644
index 0000000000..ad48a1d94d
--- /dev/null
+++ b/main/net-snmp/snmpd.confd
@@ -0,0 +1,14 @@
+# Initial (empty) options.
+OPTS=""
+
+# Enable connection logging.
+#SNMPD_FLAGS="${OPTS} -a"
+
+# Enable syslog and disable file log.
+#SNMPD_FLAGS="${OPTS} -Lsd -Lf /dev/null"
+
+# Enable agentx socket as /var/agentx/master
+# *NOTE* Before uncommenting this, make sure
+# the /var/agentx directory exists.
+#SNMPD_FLAGS="${OPTS} -x /var/agentx/master"
+
diff --git a/main/net-snmp/snmpd.initd b/main/net-snmp/snmpd.initd
new file mode 100644
index 0000000000..f768bb36bf
--- /dev/null
+++ b/main/net-snmp/snmpd.initd
@@ -0,0 +1,31 @@
+#!/sbin/runscript
+
+NAME=snmpd
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ use logger
+ need net
+ after firewall
+}
+
+checkconfig() {
+ if [ ! -e /etc/snmp/snmpd.conf ] ; then
+ eerror "You need an /etc/snmp/snmpd.conf config file to run snmpd"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet --background \
+ --exec ${DAEMON} -- -p /var/run/${NAME}.pid ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet --pidfile /var/run/${NAME}.pid
+ eend $?
+}
diff --git a/main/net-snmp/snmptrapd.confd b/main/net-snmp/snmptrapd.confd
new file mode 100644
index 0000000000..d9cee614ea
--- /dev/null
+++ b/main/net-snmp/snmptrapd.confd
@@ -0,0 +1,12 @@
+# extra flags to pass to snmptrapd
+OPTS=""
+
+# ignore authentication failure traps
+#SNMPTRAPD_FLAGS="${OPTS} -a"
+
+# log messages to specified file
+#SNMPTRAPD_FLAGS="${OPTS} -Lf /var/log/snmptrapd.log"
+
+# log messages to syslog with the specified facility
+# where facility is: 'd' = LOG_DAEMON, 'u' = LOG_USER, [0-7] = LOG_LOCAL[0-7]
+#SNMPTRAPD_FLAGS="${OPTS} -Ls d"
diff --git a/main/net-snmp/snmptrapd.initd b/main/net-snmp/snmptrapd.initd
new file mode 100644
index 0000000000..bbc592be27
--- /dev/null
+++ b/main/net-snmp/snmptrapd.initd
@@ -0,0 +1,23 @@
+#!/sbin/runscript
+
+NAME=snmptrapd
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ use logger
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet --background \
+ --exec ${DAEMON} -- -p /var/run/${NAME}.pid ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet --pidfile /var/run/${NAME}.pid
+ eend $?
+}
diff --git a/main/netcat-openbsd/APKBUILD b/main/netcat-openbsd/APKBUILD
new file mode 100644
index 0000000000..0ea0d739e5
--- /dev/null
+++ b/main/netcat-openbsd/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Leonardo Arena <rnalrd@alpinelinux.org>
+pkgname=netcat-openbsd
+pkgver=1.89
+pkgrel=0
+pkgdesc="The TCP/IP swiss army knife. OpenBSD variant."
+url="http://packages.debian.org/sid/netcat-openbsd"
+arch="all"
+license="GPL"
+depends=
+depends_dev="glib-dev"
+makedepends="$depends_dev"
+install="$pkgname.post-deinstall"
+subpackages="$pkgname-doc"
+source="http://ftp.debian.org/debian/pool/main/n/$pkgname/${pkgname}_${pkgver}.orig.tar.gz
+ netcat-openbsd_1.89-4.diff"
+
+_builddir="$srcdir"/$pkgname-$pkgver.orig
+
+prepare() {
+ cd "$_builddir"
+
+ for i in ../*.diff
+ do
+ msg "Applying patch $i"
+ patch -p1 -i $i || return 1
+ done
+
+ for i in `cat debian/patches/series`
+ do
+ echo "Applying patch $i" 1>&2
+ patch -p1 -i "debian/patches/$i" || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make CFLAGS="$CFLAGS -DDEBIAN_VERSION=\"\\\"4\\\"\"" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -d $pkgdir/usr/bin/
+ install -d $pkgdir/usr/share/man/man1/
+ install nc $pkgdir/usr/bin/nc
+ install nc.1 $pkgdir/usr/share/man/man1/nc.openbsd.1
+}
+
+md5sums="7238ce15aae43069e96ba7faf03f153e netcat-openbsd_1.89.orig.tar.gz
+8e88cb91ca8cad6f9a75d3b84e028298 netcat-openbsd_1.89-4.diff"
diff --git a/main/netcat-openbsd/netcat-openbsd.post-deinstall b/main/netcat-openbsd/netcat-openbsd.post-deinstall
new file mode 100644
index 0000000000..c59247ad41
--- /dev/null
+++ b/main/netcat-openbsd/netcat-openbsd.post-deinstall
@@ -0,0 +1,2 @@
+#!/bin/sh
+busybox --install -s
diff --git a/main/netcat-openbsd/netcat-openbsd_1.89-4.diff b/main/netcat-openbsd/netcat-openbsd_1.89-4.diff
new file mode 100644
index 0000000000..ad62c46957
--- /dev/null
+++ b/main/netcat-openbsd/netcat-openbsd_1.89-4.diff
@@ -0,0 +1,2793 @@
+--- netcat-openbsd-1.89.orig/Makefile
++++ netcat-openbsd-1.89/Makefile
+@@ -1,6 +1,21 @@
+ # $OpenBSD: Makefile,v 1.6 2001/09/02 18:45:41 jakob Exp $
+
+ PROG= nc
+-SRCS= netcat.c atomicio.c socks.c
++SRCS= netcat.c atomicio.c socks.c \
++ openbsd-compat/base64.c openbsd-compat/readpassphrase.c
+
+-.include <bsd.prog.mk>
++CC = gcc
++override CFLAGS += `pkg-config --cflags glib-2.0`
++INC = -Iopenbsd-compat
++LIBS = `pkg-config --libs glib-2.0`
++OBJS = $(SRCS:.c=.o)
++
++all: nc
++nc: $(OBJS)
++ $(CC) $(LIBS) $(OBJS) -o nc
++
++$(OBJS): %.o: %.c
++ $(CC) $(CFLAGS) $(INC) -c $< -o $@
++
++clean:
++ rm -f $(OBJS) nc
+--- netcat-openbsd-1.89.orig/debian/rules
++++ netcat-openbsd-1.89/debian/rules
+@@ -0,0 +1,64 @@
++#!/usr/bin/make -f
++#export DH_VERBOSE=1
++
++DEB_CFLAGS = -g -Wall
++ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
++DEB_CFLAGS += -O0
++else
++DEB_CFLAGS += -O2
++endif
++ifneq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
++INSTALL_PROG = install -m 0755
++else
++INSTALL_PROG = install -s -m 0755
++endif
++DEB_VER = $(shell dpkg-parsechangelog | sed -n 's/^Version: //p')
++
++patch: patch-stamp
++patch-stamp:
++ QUILT_PATCHES=debian/patches quilt push -a || test $$? = 2
++ touch patch-stamp
++
++unpatch:
++ QUILT_PATCHES=debian/patches quilt pop -a -R || test $$? = 2
++ rm -rf .pc patch-stamp
++
++build: build-stamp
++build-stamp: patch-stamp
++
++ $(MAKE) CFLAGS='$(DEB_CFLAGS) -DDEBIAN_VERSION=\"$(DEB_VER)\"'
++ touch build-stamp
++
++clean: unpatch
++ dh_testdir
++ dh_clean patch-stamp build-stamp
++ $(MAKE) clean
++
++install:
++ dh_testdir
++ dh_testroot
++ dh_clean -k
++ dh_installdirs
++
++ $(INSTALL_PROG) nc $(CURDIR)/debian/netcat-openbsd/bin/nc.openbsd
++ cp nc.1 $(CURDIR)/debian/netcat-openbsd/usr/share/man/man1/nc_openbsd.1
++
++binary-indep: build install
++
++binary-arch: build install
++ dh_testdir
++ dh_testroot
++ dh_installchangelogs
++ dh_installdocs
++ dh_installexamples debian/examples/*
++ dh_link
++ dh_strip
++ dh_compress -Xexamples
++ dh_fixperms
++ dh_installdeb
++ dh_shlibdeps
++ dh_gencontrol
++ dh_md5sums
++ dh_builddeb
++
++binary: binary-indep binary-arch
+--- netcat-openbsd-1.89.orig/debian/changelog
++++ netcat-openbsd-1.89/debian/changelog
+@@ -0,0 +1,44 @@
++netcat-openbsd (1.89-4) unstable; urgency=low
++
++ * Quit immediately after EOF if -q is not given (i.e. make the default
++ equivalent to -q 0). This is the standard upstream behavior and what
++ other Linux distributions use. It is different from netcat-traditional,
++ but compatibility with other versions of OpenBSD netcat is more
++ important. (Closes: #502188)
++
++ -- Decklin Foster <decklin@red-bean.com> Sun, 18 Apr 2010 20:05:08 -0400
++
++netcat-openbsd (1.89-3) unstable; urgency=low
++
++ * Silence -z flag, for compatibility with netcat-traditional (Closes:
++ #464564)
++ * Move stray line in socks.c to quilt patch series (Closes: #485160)
++ * Add missing documentation for -q option to man page.
++
++ -- Decklin Foster <decklin@red-bean.com> Thu, 19 Jun 2008 16:20:01 -0400
++
++netcat-openbsd (1.89-2) unstable; urgency=low
++
++ * Replace references to "netcat-base" with "netcat-traditional" (future
++ name of the old netcat package).
++
++ -- Decklin Foster <decklin@red-bean.com> Wed, 30 Jan 2008 18:24:46 -0500
++
++netcat-openbsd (1.89-1) unstable; urgency=low
++
++ * Initial release. (Closes: #145798)
++ * Includes support for:
++ - IPv6 (Closes: #461317)
++ - Unix domain sockets (Closes: #348564)
++ - SOCKS (Closes: #142898)
++ * Conflict with netcat versions older than netcat-traditional, so that we
++ can use alternatives.
++ * Port some features over from netcat-traditional:
++ - Exit successfully when printing help text (-h), and include the Debian
++ revision.
++ - Add the -q (quit on standard input EOF) flag.
++ - Add support for specifying ports by name (/etc/services). Unlike the
++ old hack for this, nc will first try to find a named service, then fall
++ back to numeric parsing, so no escaping is needed.
++
++ -- Decklin Foster <decklin@red-bean.com> Mon, 21 Jan 2008 18:41:37 -0500
+--- netcat-openbsd-1.89.orig/debian/netcat-openbsd.prerm
++++ netcat-openbsd-1.89/debian/netcat-openbsd.prerm
+@@ -0,0 +1,7 @@
++#!/bin/sh -e
++
++if [ "$1" = "remove" ]; then
++ update-alternatives --remove nc /bin/nc.openbsd
++fi
++
++#DEBHELPER#
+--- netcat-openbsd-1.89.orig/debian/copyright
++++ netcat-openbsd-1.89/debian/copyright
+@@ -0,0 +1,130 @@
++The netcat-openbsd Debian package was created by Soren Hansen
++<soren@ubuntu.com> and by Decklin Foster <decklin@red-bean.com>, based
++loosely on the original netcat package. The code itself was rewritten
++by the OpenBSD project, from the original implementation by Hobbit
++<hobbit@atstake.com>.
++
++Sources can be found at:
++
++ http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/nc/
++
++Copyright and license of netcat.c:
++
++ Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
++
++ Redistribution and use in source and binary forms, with or without
++ modification, are permitted provided that the following conditions
++ are met:
++
++ 1. Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++ 2. Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++ 3. The name of the author may not be used to endorse or promote products
++ derived from this software without specific prior written permission.
++
++ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++
++Copyright and license of atomicio.c:
++
++ Copyright (c) 2005 Anil Madhavapeddy. All rights served.
++ Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
++ All rights reserved.
++
++ Redistribution and use in source and binary forms, with or without
++ modification, are permitted provided that the following conditions
++ are met:
++ 1. Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++ 2. Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++
++ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++
++ Copyright (c) 2005 Anil Madhavapeddy. All rights served.
++ Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
++
++Copyright of socks.c (license is identical to that of atomicio.c):
++
++ Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
++ Copyright (c) 2004, 2005 Damien Miller. All rights reserved.
++
++Copyright and license of readpassphrase.c:
++
++ Copyright (c) 2000-2002, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
++
++ Permission to use, copy, modify, and distribute this software for any
++ purpose with or without fee is hereby granted, provided that the above
++ copyright notice and this permission notice appear in all copies.
++
++ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++
++ Sponsored in part by the Defense Advanced Research Projects
++ Agency (DARPA) and Air Force Research Laboratory, Air Force
++ Materiel Command, USAF, under agreement number F39502-99-1-0512.
++
++Copyright and license of base64.c:
++
++ Copyright (c) 1996 by Internet Software Consortium.
++
++ Permission to use, copy, modify, and distribute this software for any
++ purpose with or without fee is hereby granted, provided that the above
++ copyright notice and this permission notice appear in all copies.
++
++ THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
++ ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
++ OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
++ CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
++ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
++ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
++ ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
++ SOFTWARE.
++
++ Portions Copyright (c) 1995 by International Business Machines, Inc.
++
++ International Business Machines, Inc. (hereinafter called IBM) grants
++ permission under its copyrights to use, copy, modify, and distribute this
++ Software with or without fee, provided that the above copyright notice and
++ all paragraphs of this notice appear in all copies, and that the name of IBM
++ not be used in connection with the marketing of any product incorporating
++ the Software or modifications thereof, without specific, written prior
++ permission.
++
++ To the extent it has a right to do so, IBM grants an immunity from suit
++ under its patents, if any, for the use, sale or manufacture of products to
++ the extent that such products are used for performing Domain Name System
++ dynamic updates in TCP/IP networks by means of the Software. No immunity is
++ granted for any product per se or for any other function of any product.
++
++ THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
++ INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
++ PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
++ DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
++ OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
++ IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+--- netcat-openbsd-1.89.orig/debian/compat
++++ netcat-openbsd-1.89/debian/compat
+@@ -0,0 +1 @@
++4
+--- netcat-openbsd-1.89.orig/debian/control
++++ netcat-openbsd-1.89/debian/control
+@@ -0,0 +1,24 @@
++Source: netcat-openbsd
++Section: net
++Priority: optional
++Maintainer: Decklin Foster <decklin@red-bean.com>
++Standards-Version: 3.7.3
++Build-Depends: quilt, debhelper (>= 4.0.0), libglib2.0-dev
++
++Package: netcat-openbsd
++Architecture: any
++Depends: ${shlibs:Depends}
++Provides: netcat
++Conflicts: netcat (<< 1.10-35)
++Replaces: netcat (<< 1.10-35)
++Description: TCP/IP swiss army knife
++ A simple Unix utility which reads and writes data across network
++ connections using TCP or UDP protocol. It is designed to be a reliable
++ "back-end" tool that can be used directly or easily driven by other
++ programs and scripts. At the same time it is a feature-rich network
++ debugging and exploration tool, since it can create almost any kind of
++ connection you would need and has several interesting built-in
++ capabilities.
++ .
++ This package contains the OpenBSD rewrite of netcat, including support
++ for IPv6, proxies, and Unix sockets.
+--- netcat-openbsd-1.89.orig/debian/netcat-openbsd.README.Debian
++++ netcat-openbsd-1.89/debian/netcat-openbsd.README.Debian
+@@ -0,0 +1,41 @@
++OpenBSD netcat for Debian
++-------------------------
++
++This package has been rebased on OpenBSD's implementation of netcat. The
++code has been massively cleaned up, and important functionality has been
++added.
++
++ -- Soren Hansen <soren@ubuntu.com> Tue, 15 Jan 2008 10:38:34 +0100
++
++The OpenBSD implementation has been split from netcat-traditional for
++two reasons (not counting sentimental value):
++
++ 1. Netcat should be part of the base system; OpenBSD netcat uses
++ strlcpy. While there is already a perfectly good implementation of
++ strlcpy in Debian, it is part of glib, which is not included in base.
++ 2. Packages should not be replaced under users' feet; a transitional
++ package will be provided for lenny so that users can note the new
++ package and switch if they wish.
++
++You may install this package alongside netcat-traditional; they both
++use the alternatives system for nc(1) as well as the deprecated alias
++netcat(1). Other implementations of netcat with compatible command line
++options are encouraged to also do so and provide the virtual package
++"netcat".
++
++The following features from netcat-traditional will not be added to this
++package:
++
++ * The -e and -c options (This should be done by redirecting the
++ appropriate file descriptors, not within netcat. How to do so should
++ be better documented.)
++ * Printing "connection refused" messages when -v is not specified
++ (because there is only one level of verbosity in this netcat, and
++ that message is primarily what the option is for.)
++
++Anything else that netcat-traditional does that this package doesn't
++is a bug. Wherever possible, command-line compatibility with the BSDs
++and Fedora is desired, but it should be easy to use netcat-openbsd as a
++"drop-in" replacement for netcat-traditional as well.
++
++ -- Decklin Foster <decklin@red-bean.com> Tue, 22 Jan 2008 18:50:08 -0500
+--- netcat-openbsd-1.89.orig/debian/netcat-openbsd.postinst
++++ netcat-openbsd-1.89/debian/netcat-openbsd.postinst
+@@ -0,0 +1,13 @@
++#!/bin/sh -e
++
++if [ "$1" = "configure" ]; then
++ update-alternatives \
++ --install /bin/nc nc /bin/nc.openbsd 50 \
++ --slave /bin/netcat netcat /bin/nc.openbsd \
++ --slave /usr/share/man/man1/nc.1.gz nc.1.gz \
++ /usr/share/man/man1/nc_openbsd.1.gz \
++ --slave /usr/share/man/man1/netcat.1.gz netcat.1.gz \
++ /usr/share/man/man1/nc_openbsd.1.gz
++fi
++
++#DEBHELPER#
+--- netcat-openbsd-1.89.orig/debian/netcat-openbsd.dirs
++++ netcat-openbsd-1.89/debian/netcat-openbsd.dirs
+@@ -0,0 +1,2 @@
++bin
++usr/share/man/man1
+--- netcat-openbsd-1.89.orig/debian/examples/irc
++++ netcat-openbsd-1.89/debian/examples/irc
+@@ -0,0 +1,79 @@
++#! /bin/sh
++## Shit-simple script to supply the "privmsg <recipient>" of IRC typein, and
++## keep the connection alive. Pipe this thru "nc -v -w 5 irc-server port".
++## Note that this mechanism makes the script easy to debug without being live,
++## since it just echoes everything bound for the server.
++## if you want autologin-type stuff, construct some appropriate files and
++## shovel them in using the "<" mechanism.
++
++# magic arg: if "tick", do keepalive process instead of main loop
++if test "$1" = "tick" ; then
++# ignore most signals; the parent will nuke the kid
++# doesn't stop ^Z, of course.
++ trap '' 1 2 3 13 14 15 16
++ while true ; do
++ sleep 60
++ echo "PONG !"
++ done
++fi
++
++# top level: fire ourselves off as the keepalive process, and keep track of it
++sh $0 tick &
++ircpp=$!
++echo "[Keepalive: $ircpp]" >&2
++# catch our own batch of signals: hup int quit pipe alrm term urg
++trap 'kill -9 $ircpp ; exit 0' 1 2 3 13 14 15 16
++sleep 2
++
++sender=''
++savecmd=''
++
++# the big honkin' loop...
++while read xx yy ; do
++ case "${xx}" in
++# blank line: do nothing
++ "")
++ continue
++ ;;
++# new channel or recipient; if bare ">", we're back to raw literal mode.
++ ">")
++ if test "${yy}" ; then
++ sender="privmsg ${yy} :"
++ else
++ sender=''
++ fi
++ continue
++ ;;
++# send crud from a file, one line per second. Can you say "skr1pt kidz"??
++# *Note: uses current "recipient" if set.
++ "<")
++ if test -f "${yy}" ; then
++ ( while read zz ; do
++ sleep 1
++ echo "${sender}${zz}"
++ done ) < "$yy"
++ echo "[done]" >&2
++ else
++ echo "[File $yy not found]" >&2
++ fi
++ continue
++ ;;
++# do and save a single command, for quick repeat
++ "/")
++ if test "${yy}" ; then
++ savecmd="${yy}"
++ fi
++ echo "${savecmd}"
++ ;;
++# default case goes to recipient, just like always
++ *)
++ echo "${sender}${xx} ${yy}"
++ continue
++ ;;
++ esac
++done
++
++# parting shot, if you want it
++echo "quit :Bye all!"
++kill -9 $ircpp
++exit 0
+--- netcat-openbsd-1.89.orig/debian/examples/README
++++ netcat-openbsd-1.89/debian/examples/README
+@@ -0,0 +1,5 @@
++A collection of example scripts that use netcat as a backend, each
++documented by its own internal comments.
++
++I'll be the first to admit that some of these are seriously *sick*,
++but they do work and are quite useful to me on a daily basis.
+--- netcat-openbsd-1.89.orig/debian/examples/web
++++ netcat-openbsd-1.89/debian/examples/web
+@@ -0,0 +1,148 @@
++#! /bin/sh
++## The web sucks. It is a mighty dismal kludge built out of a thousand
++## tiny dismal kludges all band-aided together, and now these bottom-line
++## clueless pinheads who never heard of "TCP handshake" want to run
++## *commerce* over the damn thing. Ye godz. Welcome to TV of the next
++## century -- six million channels of worthless shit to choose from, and
++## about as much security as today's cable industry!
++##
++## Having grown mightily tired of pain in the ass browsers, I decided
++## to build the minimalist client. It doesn't handle POST, just GETs, but
++## the majority of cgi forms handlers apparently ignore the method anyway.
++## A distinct advantage is that it *doesn't* pass on any other information
++## to the server, like Referer: or info about your local machine such as
++## Netscum tries to!
++##
++## Since the first version, this has become the *almost*-minimalist client,
++## but it saves a lot of typing now. And with netcat as its backend, it's
++## totally the balls. Don't have netcat? Get it here in /src/hacks!
++## _H* 950824, updated 951009 et seq.
++##
++## args: hostname [port]. You feed it the filename-parts of URLs.
++## In the loop, HOST, PORT, and SAVE do the right things; a null line
++## gets the previous spec again [useful for initial timeouts]; EOF to exit.
++## Relative URLs behave like a "cd" to wherever the last slash appears, or
++## just use the last component with the saved preceding "directory" part.
++## "\" clears the "filename" part and asks for just the "directory", and
++## ".." goes up one "directory" level while retaining the "filename" part.
++## Play around; you'll get used to it.
++
++if test "$1" = "" ; then
++ echo Needs hostname arg.
++ exit 1
++fi
++umask 022
++
++# optional PATH fixup
++# PATH=${HOME}:${PATH} ; export PATH
++
++test "${PAGER}" || PAGER=more
++BACKEND="nc -v -w 15"
++TMPAGE=/tmp/web$$
++host="$1"
++port="80"
++if test "$2" != "" ; then
++ port="$2"
++fi
++
++spec="/"
++specD="/"
++specF=''
++saving=''
++
++# be vaguely smart about temp file usage. Use your own homedir if you're
++# paranoid about someone symlink-racing your shell script, jeez.
++rm -f ${TMPAGE}
++test -f ${TMPAGE} && echo "Can't use ${TMPAGE}" && exit 1
++
++# get loopy. Yes, I know "echo -n" aint portable. Everything echoed would
++# need "\c" tacked onto the end in an SV universe, which you can fix yourself.
++while echo -n "${specD}${specF} " && read spec ; do
++ case $spec in
++ HOST)
++ echo -n 'New host: '
++ read host
++ continue
++ ;;
++ PORT)
++ echo -n 'New port: '
++ read port
++ continue
++ ;;
++ SAVE)
++ echo -n 'Save file: '
++ read saving
++# if we've already got a page, save it
++ test "${saving}" && test -f ${TMPAGE} &&
++ echo "=== ${host}:${specD}${specF} ===" >> $saving &&
++ cat ${TMPAGE} >> $saving && echo '' >> $saving
++ continue
++ ;;
++# changing the logic a bit here. Keep a state-concept of "current dir"
++# and "current file". Dir is /foo/bar/ ; file is "baz" or null.
++# leading slash: create whole new state.
++ /*)
++ specF=`echo "${spec}" | sed 's|.*/||'`
++ specD=`echo "${spec}" | sed 's|\(.*/\).*|\1|'`
++ spec="${specD}${specF}"
++ ;;
++# embedded slash: adding to the path. "file" part can be blank, too
++ */*)
++ specF=`echo "${spec}" | sed 's|.*/||'`
++ specD=`echo "${specD}${spec}" | sed 's|\(.*/\).*|\1|'`
++ ;;
++# dotdot: jump "up" one level and just reprompt [confirms what it did...]
++ ..)
++ specD=`echo "${specD}" | sed 's|\(.*/\)..*/|\1|'`
++ continue
++ ;;
++# blank line: do nothing, which will re-get the current one
++ '')
++ ;;
++# hack-quoted blank line: "\" means just zero out "file" part
++ '\')
++ specF=''
++ ;;
++# sigh
++ '?')
++ echo Help yourself. Read the script fer krissake.
++ continue
++ ;;
++# anything else is taken as a "file" part
++ *)
++ specF=${spec}
++ ;;
++ esac
++
++# now put it together and stuff it down a connection. Some lame non-unix
++# http servers assume they'll never get simple-query format, and wait till
++# an extra newline arrives. If you're up against one of these, change
++# below to (echo GET "$spec" ; echo '') | $BACKEND ...
++ spec="${specD}${specF}"
++ echo GET "${spec}" | $BACKEND $host $port > ${TMPAGE}
++ ${PAGER} ${TMPAGE}
++
++# save in a format that still shows the URLs we hit after a de-html run
++ if test "${saving}" ; then
++ echo "=== ${host}:${spec} ===" >> $saving
++ cat ${TMPAGE} >> $saving
++ echo '' >> $saving
++ fi
++done
++rm -f ${TMPAGE}
++exit 0
++
++#######
++# Encoding notes, finally from RFC 1738:
++# %XX -- hex-encode of special chars
++# allowed alphas in a URL: $_-.+!*'(),
++# relative names *not* described, but obviously used all over the place
++# transport://user:pass@host:port/path/name?query-string
++# wais: port 210, //host:port/database?search or /database/type/file?
++# cgi-bin/script?arg1=foo&arg2=bar&... scripts have to parse xxx&yyy&zzz
++# ISMAP imagemap stuff: /bin/foobar.map?xxx,yyy -- have to guess at coords!
++# local access-ctl files: ncsa: .htaccess ; cern: .www_acl
++#######
++# SEARCH ENGINES: fortunately, all are GET forms or at least work that way...
++# multi-word args for most cases: foo+bar
++# See 'websearch' for concise results of this research...
+--- netcat-openbsd-1.89.orig/debian/examples/webrelay
++++ netcat-openbsd-1.89/debian/examples/webrelay
+@@ -0,0 +1,44 @@
++#! /bin/sh
++## web relay -- a degenerate version of webproxy, usable with browsers that
++## don't understand proxies. This just forwards connections to a given server.
++## No query logging, no access control [although you can add it to XNC for
++## your own run], and full-URL links will undoubtedly confuse the browser
++## if it can't reach the server directly. This was actually written before
++## the full proxy was, and it shows.
++## The arguments in this case are the destination server and optional port.
++## Please flame pinheads who use self-referential absolute links.
++
++# set these as you wish: proxy port...
++PORT=8000
++# any extra args to the listening "nc", for instance "-s inside-net-addr"
++XNC=''
++
++# functionality switch, which has to be done fast to start the next listener
++case "${1}${RDEST}" in
++ "")
++ echo needs hostname
++ exit 1
++ ;;
++esac
++
++case "${1}" in
++ "")
++# no args: fire off new relayer process NOW. Will hang around for 10 minutes
++ nc -w 600 -l -n -p $PORT -e "$0" $XNC < /dev/null > /dev/null 2>&1 &
++# and handle this request, which will simply fail if vars not set yet.
++ exec nc -w 15 $RDEST $RPORT
++ ;;
++esac
++
++# Fall here for setup; this can now be slower.
++RDEST="$1"
++RPORT="$2"
++test "$RPORT" || RPORT=80
++export RDEST RPORT
++
++# Launch the first relayer same as above, but let its error msgs show up
++# will hang around for a minute, and exit if no new connections arrive.
++nc -v -w 600 -l -p $PORT -e "$0" $XNC < /dev/null > /dev/null &
++echo \
++ "Relay to ${RDEST}:${RPORT} running -- point your browser here on port $PORT"
++exit 0
+--- netcat-openbsd-1.89.orig/debian/examples/ncp
++++ netcat-openbsd-1.89/debian/examples/ncp
+@@ -0,0 +1,46 @@
++#! /bin/sh
++## Like "rcp" but uses netcat on a high port.
++## do "ncp targetfile" on the RECEIVING machine
++## then do "ncp sourcefile receivinghost" on the SENDING machine
++## if invoked as "nzp" instead, compresses transit data.
++
++## pick your own personal favorite port, which will be used on both ends.
++## You should probably change this for your own uses.
++MYPORT=23456
++
++## if "nc" isn't systemwide or in your PATH, add the right place
++# PATH=${HOME}:${PATH} ; export PATH
++
++test "$3" && echo "too many args" && exit 1
++test ! "$1" && echo "no args?" && exit 1
++me=`echo $0 | sed 's+.*/++'`
++test "$me" = "nzp" && echo '[compressed mode]'
++
++# if second arg, it's a host to send an [extant] file to.
++if test "$2" ; then
++ test ! -f "$1" && echo "can't find $1" && exit 1
++ if test "$me" = "nzp" ; then
++ compress -c < "$1" | nc -v -w 2 $2 $MYPORT && exit 0
++ else
++ nc -v -w 2 $2 $MYPORT < "$1" && exit 0
++ fi
++ echo "transfer FAILED!"
++ exit 1
++fi
++
++# fall here for receiver. Ask before trashing existing files
++if test -f "$1" ; then
++ echo -n "Overwrite $1? "
++ read aa
++ test ! "$aa" = "y" && echo "[punted!]" && exit 1
++fi
++# 30 seconds oughta be pleeeeenty of time, but change if you want.
++if test "$me" = "nzp" ; then
++ nc -v -w 30 -p $MYPORT -l < /dev/null | uncompress -c > "$1" && exit 0
++else
++ nc -v -w 30 -p $MYPORT -l < /dev/null > "$1" && exit 0
++fi
++echo "transfer FAILED!"
++# clean up, since even if the transfer failed, $1 is already trashed
++rm -f "$1"
++exit 1
+--- netcat-openbsd-1.89.orig/debian/examples/probe
++++ netcat-openbsd-1.89/debian/examples/probe
+@@ -0,0 +1,50 @@
++#! /bin/sh
++## launch a whole buncha shit at yon victim in no particular order; capture
++## stderr+stdout in one place. Run as root for rservice and low -p to work.
++## Fairly thorough example of using netcat to collect a lot of host info.
++## Will set off every intrusion alarm in existence on a paranoid machine!
++
++# where .d files are kept; "." if nothing else
++DDIR=../data
++# address of some well-connected router that groks LSRR
++GATE=192.157.69.11
++
++# might conceivably wanna change this for different run styles
++UCMD='nc -v -w 8'
++
++test ! "$1" && echo Needs victim arg && exit 1
++
++echo '' | $UCMD -w 9 -r "$1" 13 79 6667 2>&1
++echo '0' | $UCMD "$1" 79 2>&1
++# if LSRR was passed thru, should get refusal here:
++$UCMD -z -r -g $GATE "$1" 6473 2>&1
++$UCMD -r -z "$1" 6000 4000-4004 111 53 2105 137-140 1-20 540-550 95 87 2>&1
++# -s `hostname` may be wrong for some multihomed machines
++echo 'UDP echoecho!' | nc -u -p 7 -s `hostname` -w 3 "$1" 7 19 2>&1
++echo '113,10158' | $UCMD -p 10158 "$1" 113 2>&1
++rservice bin bin | $UCMD -p 1019 "$1" shell 2>&1
++echo QUIT | $UCMD -w 8 -r "$1" 25 158 159 119 110 109 1109 142-144 220 23 2>&1
++# newline after any telnet trash
++echo ''
++echo PASV | $UCMD -r "$1" 21 2>&1
++echo 'GET /' | $UCMD -w 10 "$1" 80 81 210 70 2>&1
++# sometimes contains useful directory info:
++echo 'GET /robots.txt' | $UCMD -w 10 "$1" 80 2>&1
++# now the big red lights go on
++rservice bin bin 9600/9600 | $UCMD -p 1020 "$1" login 2>&1
++rservice root root | $UCMD -r "$1" exec 2>&1
++echo 'BEGIN big udp -- everything may look "open" if packet-filtered'
++data -g < ${DDIR}/nfs-0.d | $UCMD -i 1 -u "$1" 2049 | od -x 2>&1
++# no wait-time, uses RTT hack
++nc -v -z -u -r "$1" 111 66-70 88 53 87 161-164 121-123 213 49 2>&1
++nc -v -z -u -r "$1" 137-140 694-712 747-770 175-180 2103 510-530 2>&1
++echo 'END big udp'
++$UCMD -r -z "$1" 175-180 2000-2003 530-533 1524 1525 666 213 8000 6250 2>&1
++# Use our identd-sniffer!
++iscan "$1" 21 25 79 80 111 53 6667 6000 2049 119 2>&1
++# this gets pretty intrusive, but what the fuck. Probe for portmap first
++if nc -w 5 -z -u "$1" 111 ; then
++ showmount -e "$1" 2>&1
++ rpcinfo -p "$1" 2>&1
++fi
++exit 0
+--- netcat-openbsd-1.89.orig/debian/examples/webproxy
++++ netcat-openbsd-1.89/debian/examples/webproxy
+@@ -0,0 +1,141 @@
++#! /bin/sh
++## Web proxy, following the grand tradition of Web things being handled by
++## gross scripts. Uses netcat to listen on a high port [default 8000],
++## picks apart requests and sends them on to the right place. Point this
++## at the browser client machine you'll be coming from [to limit access to
++## only it], and point the browser's concept of an HTTP proxy to the
++## machine running this. Takes a single argument of the client that will
++## be using it, and rejects connections from elsewhere. LOGS the queries
++## to a configurable logfile, which can be an interesting read later on!
++## If the argument is "reset", the listener and logfile are cleaned up.
++##
++## This works surprisingly fast and well, for a shell script, although may
++## randomly fail when hammered by a browser that tries to open several
++## connections at once. Drop the "maximum connections" in your browser if
++## this is a problem.
++##
++## A more degenerate case of this, or preferably a small C program that
++## does the same thing under inetd, could handle a small site's worth of
++## proxy queries. Given the way browsers are evolving, proxies like this
++## can play an important role in protecting your own privacy.
++##
++## If you grabbed this in ASCII mode, search down for "eew" and make sure
++## the embedded-CR check is intact, or requests might hang.
++##
++## Doesn't handle POST forms. Who cares, if you're just watching HTTV?
++## Dumbness here has a highly desirable side effect: it only sends the first
++## GET line, since that's all you really ever need to send, and suppresses
++## the other somewhat revealing trash that most browsers insist on sending.
++##
++## To use the proxy, export `http_proxy' in your environment, e.g.
++## `http_proxy=http://localhost:8000'.
++
++# set these as you wish: proxy port...
++PORT=8000
++# logfile spec: a real file or /dev/null if you don't care
++LFILE=${0}.log
++# optional: where to dump connect info, so you can see if anything went wrong
++# CFILE=${0}.conn
++# optional extra args to the listener "nc", for instance "-s inside-net-addr"
++# XNC=''
++
++# functionality switch has to be done fast, so the next listener can start
++# prelaunch check: if no current client and no args, bail.
++case "${1}${CLIENT}" in
++ "")
++ echo needs client hostname
++ exit 1
++ ;;
++esac
++
++case "${1}" in
++ "")
++# Make like inetd, and run the next relayer process NOW. All the redirection
++# is necessary so this shell has NO remaining channel open to the net.
++# This will hang around for 10 minutes, and exit if no new connections arrive.
++# Using -n for speed, avoiding any DNS/port lookups.
++ nc -w 600 -n -l -p $PORT -e "$0" $XNC "$CLIENT" < /dev/null > /dev/null \
++ 2> $CFILE &
++ ;;
++esac
++
++# no client yet and had an arg, this checking can be much slower now
++umask 077
++
++if test "$1" ; then
++# if magic arg, just clean up and then hit our own port to cause server exit
++ if test "$1" = "reset" ; then
++ rm -f $LFILE
++ test -f "$CFILE" && rm -f $CFILE
++ nc -w 1 -n 127.0.0.1 $PORT < /dev/null > /dev/null 2>&1
++ exit 0
++ fi
++# find our ass with both hands
++ test ! -f "$0" && echo "Oops, cannot find my own corporeal being" && exit 1
++# correct launch: set up client access control, passed along thru environment.
++ CLIENT="$1"
++ export CLIENT
++ test "$CFILE" || CFILE=/dev/null
++ export CFILE
++ touch "$CFILE"
++# tell us what happened during the last run, if possible
++ if test -f "$CFILE" ; then
++ echo "Last connection results:"
++ cat $CFILE
++ fi
++
++# ping client machine and get its bare IP address
++ CLIENT=`nc -z -v -w 8 "$1" 22000 2>&1 | sed 's/.*\[\(..*\)\].*/\1/'`
++ test ! "$CLIENT" && echo "Can't find address of $1" && exit 1
++
++# if this was an initial launch, be informative about it
++ echo "=== Launch: $CLIENT" >> $LFILE
++ echo "Proxy running -- will accept connections on $PORT from $CLIENT"
++ echo " Logging queries to $LFILE"
++ test -f "$CFILE" && echo " and connection fuckups to $CFILE"
++
++# and run the first listener, showing us output just for the first hit
++ nc -v -w 600 -n -l -p $PORT -e "$0" $XNC "$CLIENT" &
++ exit 0
++fi
++
++# Fall here to handle a page.
++# GET type://host.name:80/file/path HTTP/1.0
++# Additional: trash
++# More: trash
++# <newline>
++
++read x1 x2 x3 x4
++echo "=== query: $x1 $x2 $x3 $x4" >> $LFILE
++test "$x4" && echo "extra junk after request: $x4" && exit 0
++# nuke questionable characters and split up the request
++hurl=`echo "$x2" | sed -e "s+.*//++" -e 's+[\`'\''|$;<>{}\\!*()"]++g'`
++# echo massaged hurl: $hurl >> $LFILE
++hh=`echo "$hurl" | sed -e "s+/.*++" -e "s+:.*++"`
++hp=`echo "$hurl" | sed -e "s+.*:++" -e "s+/.*++"`
++test "$hp" = "$hh" && hp=80
++hf=`echo "$hurl" | sed -e "s+[^/]*++"`
++# echo total split: $hh : $hp : $hf >> $LFILE
++# suck in and log the entire request, because we're curious
++# Fails on multipart stuff like forms; oh well...
++if test "$x3" ; then
++ while read xx ; do
++ echo "${xx}" >> $LFILE
++ test "${xx}" || break
++# eew, buried returns, gross but necessary for DOS stupidity:
++ test "${xx}" = " " && break
++ done
++fi
++# check for non-GET *after* we log the query...
++test "$x1" != "GET" && echo "sorry, this proxy only does GETs" && exit 0
++# no, you can *not* phone home, you miserable piece of shit
++test "`echo $hh | fgrep -i netscap`" && \
++ echo "access to Netscam's servers <b>DENIED.</b>" && exit 0
++# Do it. 30 sec net-wait time oughta be *plenty*...
++# Some braindead servers have forgotten how to handle the simple-query syntax.
++# If necessary, replace below with (echo "$x1 $hf" ; echo '') | nc...
++echo "$x1 $hf" | nc -w 30 "$hh" "$hp" 2> /dev/null || \
++ echo "oops, can't get to $hh : $hp".
++echo "sent \"$x1 $hf\" to $hh : $hp" >> $LFILE
++exit 0
++
+--- netcat-openbsd-1.89.orig/debian/examples/alta
++++ netcat-openbsd-1.89/debian/examples/alta
+@@ -0,0 +1,33 @@
++#! /bin/sh
++## special handler for altavista, since they only hand out chunks of 10 at
++## a time. Tries to isolate out results without the leading/trailing trash.
++## multiword arguments are foo+bar, as usual.
++## Second optional arg switches the "what" field, to e.g. "news"
++
++test "${1}" = "" && echo 'Needs an argument to search for!' && exit 1
++WHAT="web"
++test "${2}" && WHAT="${2}"
++
++# convert multiple args
++PLUSARG="`echo $* | sed 's/ /+/g'`"
++
++# Plug in arg. only doing simple-q for now; pg=aq for advanced-query
++# embedded quotes define phrases; otherwise it goes wild on multi-words
++QB="GET /cgi-bin/query?pg=q&what=${WHAT}&fmt=c&q=\"${PLUSARG}\""
++
++# ping 'em once, to get the routing warm
++nc -z -w 8 www.altavista.digital.com 24015 2> /dev/null
++echo "=== Altavista ==="
++
++for xx in 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 \
++ 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 ; do
++ echo "${QB}&stq=${xx}" | nc -w 15 www.altavista.digital.com 80 | \
++ egrep '^<a href="http://'
++done
++
++exit 0
++
++# old filter stuff
++ sed -e '/Documents .* matching .* query /,/query?.*stq=.* Document/p' \
++ -e d
++
+--- netcat-openbsd-1.89.orig/debian/examples/iscan
++++ netcat-openbsd-1.89/debian/examples/iscan
+@@ -0,0 +1,35 @@
++#! /bin/sh
++## duplicate DaveG's ident-scan thingie using netcat. Oooh, he'll be pissed.
++## args: target port [port port port ...]
++## hose stdout *and* stderr together.
++##
++## advantages: runs slower than ident-scan, giving remote inetd less cause
++## for alarm, and only hits the few known daemon ports you specify.
++## disadvantages: requires numeric-only port args, the output sleazitude,
++## and won't work for r-services when coming from high source ports.
++
++case "${2}" in
++ "" ) echo needs HOST and at least one PORT ; exit 1 ;;
++esac
++
++# ping 'em once and see if they *are* running identd
++nc -z -w 9 "$1" 113 || { echo "oops, $1 isn't running identd" ; exit 0 ; }
++
++# generate a randomish base port
++RP=`expr $$ % 999 + 31337`
++
++TRG="$1"
++shift
++
++while test "$1" ; do
++ nc -v -w 8 -p ${RP} "$TRG" ${1} < /dev/null > /dev/null &
++ PROC=$!
++ sleep 3
++ echo "${1},${RP}" | nc -w 4 -r "$TRG" 113 2>&1
++ sleep 2
++# does this look like a lamer script or what...
++ kill -HUP $PROC
++ RP=`expr ${RP} + 1`
++ shift
++done
++
+--- netcat-openbsd-1.89.orig/debian/examples/websearch
++++ netcat-openbsd-1.89/debian/examples/websearch
+@@ -0,0 +1,77 @@
++#! /bin/sh
++## Hit the major search engines. Hose the [large] output to a file!
++## autoconverts multiple arguments into the right format for given servers --
++## usually worda+wordb, with certain lame exceptions like dejanews.
++## Extracting and post-sorting the URLs is highly recommended...
++##
++## Altavista currently handled by a separate script; may merge at some point.
++##
++## _H* original 950824, updated 951218 and 960209
++
++test "${1}" = "" && echo 'Needs argument[s] to search for!' && exit 1
++PLUSARG="`echo $* | sed 's/ /+/g'`"
++PIPEARG="`echo ${PLUSARG} | sed 's/+/|/g'`"
++IFILE=/tmp/.webq.$$
++
++# Don't have "nc"? Get "netcat" from avian.org and add it to your toolkit.
++doquery () {
++ echo GET "$1" | nc -v -i 1 -w 30 "$2" "$3"
++}
++
++# changed since original: now supplying port numbers and separator lines...
++
++echo "=== Yahoo ==="
++doquery "/bin/search?p=${PLUSARG}&n=300&w=w&s=a" search.yahoo.com 80
++
++echo '' ; echo "=== Webcrawler ==="
++doquery "/cgi-bin/WebQuery?searchText=${PLUSARG}&maxHits=300" webcrawler.com 80
++
++# the infoseek lamers want "registration" before they do a real search, but...
++echo '' ; echo "=== Infoseek ==="
++echo " is broken."
++# doquery "WW/IS/Titles?qt=${PLUSARG}" www2.infoseek.com 80
++# ... which doesn't work cuz their lame server wants the extra newlines, WITH
++# CRLF pairs ferkrissake. Fuck 'em for now, they're hopelessly broken. If
++# you want to play, the basic idea and query formats follow.
++# echo "GET /WW/IS/Titles?qt=${PLUSARG}" > $IFILE
++# echo "" >> $IFILE
++# nc -v -w 30 guide-p.infoseek.com 80 < $IFILE
++
++# this is kinda flakey; might have to do twice??
++echo '' ; echo "=== Opentext ==="
++doquery "/omw/simplesearch?SearchFor=${PLUSARG}&mode=phrase" \
++ search.opentext.com 80
++
++# looks like inktomi will only take hits=100, or defaults back to 30
++# we try to suppress all the stupid rating dots here, too
++echo '' ; echo "=== Inktomi ==="
++doquery "/query/?query=${PLUSARG}&hits=100" ink3.cs.berkeley.edu 1234 | \
++ sed '/^<IMG ALT.*inktomi.*\.gif">$/d'
++
++#djnews lame shit limits hits to 120 and has nonstandard format
++echo '' ; echo "=== Dejanews ==="
++doquery "/cgi-bin/nph-dnquery?query=${PIPEARG}+maxhits=110+format=terse+defaultOp=AND" \
++ smithers.dejanews.com 80
++
++# OLD lycos: used to work until they fucking BROKE it...
++# doquery "/cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=1" \
++# query5.lycos.cs.cmu.edu 80
++# NEW lycos: wants the User-agent field present in query or it returns nothing
++# 960206: webmaster@lycos duly bitched at
++# 960208: reply received; here's how we will now handle it:
++echo \
++"GET /cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=terse&matchmode=and&minscore=.5 HTTP/1.x" \
++ > $IFILE
++echo "User-agent: *FUCK OFF*" >> $IFILE
++echo "Why: go ask todd@pointcom.com (Todd Whitney)" >> $IFILE
++echo '' >> $IFILE
++echo '' ; echo "=== Lycos ==="
++nc -v -i 1 -w 30 twelve.srv.lycos.com 80 < $IFILE
++
++rm -f $IFILE
++exit 0
++
++# CURRENTLY BROKEN [?]
++# infoseek
++
++# some args need to be redone to ensure whatever "and" mode applies
+--- netcat-openbsd-1.89.orig/debian/examples/bsh
++++ netcat-openbsd-1.89/debian/examples/bsh
+@@ -0,0 +1,29 @@
++#! /bin/sh
++## a little wrapper to "password" and re-launch a shell-listener.
++## Arg is taken as the port to listen on. Define "NC" to point wherever.
++
++NC=nc
++
++case "$1" in
++ ?* )
++ LPN="$1"
++ export LPN
++ sleep 1
++ echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 &
++ echo "launched on port $LPN"
++ exit 0
++ ;;
++esac
++
++# here we play inetd
++echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 &
++
++while read qq ; do
++case "$qq" in
++# here's yer password
++ gimme )
++ cd /
++ exec csh -i
++ ;;
++esac
++done
+--- netcat-openbsd-1.89.orig/debian/examples/dist.sh
++++ netcat-openbsd-1.89/debian/examples/dist.sh
+@@ -0,0 +1,23 @@
++#! /bin/sh
++## This is a quick example listen-exec server, which was used for a while to
++## distribute netcat prereleases. It illustrates use of netcat both as a
++## "fake inetd" and a syslogger, and how easy it then is to crock up a fairly
++## functional server that restarts its own listener and does full connection
++## logging. In a half-screen of shell script!!
++
++PORT=31337
++
++sleep 1
++SRC=`tail -1 dist.log`
++echo "<36>elite: ${SRC}" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1
++echo ";;; Hi, ${SRC}..."
++echo ";;; This is a PRERELEASE version of 'netcat', tar/gzip/uuencoded."
++echo ";;; Unless you are capturing this somehow, it won't do you much good."
++echo ";;; Ready?? Here it comes! Have phun ..."
++sleep 8
++cat dist.file
++sleep 1
++./nc -v -l -p ${PORT} -e dist.sh < /dev/null >> dist.log 2>&1 &
++sleep 1
++echo "<36>elite: done" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1
++exit 0
+--- netcat-openbsd-1.89.orig/debian/examples/contrib/ncmeter
++++ netcat-openbsd-1.89/debian/examples/contrib/ncmeter
+@@ -0,0 +1,82 @@
++#! /bin/bash
++
++# script to measure the speed of netcat.
++# start with one argument for usage information
++#
++# Tools that are used by this script are:
++# nc, bc, wc, sed, awk
++#
++# Author: Karsten Priegnitz (koem@petoria.de)
++
++NCPORT=23457
++WAIT=1
++
++# determine the programme's name
++me=`echo $0 | sed 's+.*/++'`
++
++# check number of arguments provided
++if [ $# -ne 0 -a $# -ne 2 ]; then
++ echo "Usage:"
++ echo
++ echo " On the transmitter side:"
++ echo " $me <receivers ip-address> <amount of data>"
++ echo
++ echo " The <amount of data> is to be given in byte but you"
++ echo " also can supply M or K for MegaByte and KiloByte."
++ echo " Example: $me 10.1.1.3 20M"
++ echo
++ echo " On the receiver side:"
++ echo " $me"
++ echo
++ echo " Start $me on the receiver side before starting it"
++ echo " on the transmitter side. Stop the receiver by pressing"
++ echo " and holding Ctrl-C."
++ exit 1
++fi
++
++# are we the receiver?
++if [ $# -eq 0 ]; then
++ # yes, we are
++ while true; do
++ echo "waiting to receive data... (quit: press and hold Ctrl-C)"
++
++ # wait for data and count bytes
++ AMOUNT=`nc -v -w 120 -l -p $NCPORT | wc -c | awk '{print $1}'`
++
++ # display amount of data received
++ echo $AMOUNT byte of data received
++ echo
++
++ # sleep, so that the loop can be
++ # interrupted by pressing Ctrl-C
++ sleep 1
++ done
++fi
++
++# we are the sender
++echo "sending data..."
++
++# calculate the amount of data to be sent
++AMOUNT=`echo $2|sed s/[mM]/\*1048576/g | sed s/[kK]/\*1024/g | bc`
++
++# send data and measure the time spent
++TEMP=/tmp/$me.tx
++( time -p dd if=/dev/zero bs=$AMOUNT count=1 2>/dev/null | nc -v -w $WAIT $1 $NCPORT ) 2>"$TEMP" || cat "$TEMP"
++
++# read the time needed
++REAL=`grep "^real" "$TEMP" | awk '{print $2}'`
++rm "$TEMP"
++# subtract the wait times
++DOUBLEWAIT=$(($WAIT * 2))
++NEEDED=`echo $REAL - $DOUBLEWAIT|bc`
++
++# calculate and print speed
++BPS=`echo "scale=3;$AMOUNT / $NEEDED"|bc`
++KBPS=`echo "scale=3;$AMOUNT / $NEEDED / 1024"|bc`
++MBPS=`echo "scale=3;$AMOUNT / $NEEDED / 1048576"|bc`
++
++echo "time needed: ${NEEDED}s"
++echo "byte per second: $BPS"
++echo "KByte per second: $KBPS"
++echo "MByte per second: $MBPS"
++
+--- netcat-openbsd-1.89.orig/debian/patches/send-crlf.patch
++++ netcat-openbsd-1.89/debian/patches/send-crlf.patch
+@@ -0,0 +1,109 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-06-19 16:49:57.000000000 -0400
+++++ netcat-openbsd-1.89/netcat.c 2008-06-19 17:04:22.000000000 -0400
++@@ -73,6 +73,7 @@
++ #define UDP_SCAN_TIMEOUT 3 /* Seconds */
++
++ /* Command Line Options */
+++int Cflag = 0; /* CRLF line-ending */
++ int dflag; /* detached, no stdin */
++ int iflag; /* Interval Flag */
++ int jflag; /* use jumbo frames if we can */
++@@ -136,7 +137,7 @@
++ sv = NULL;
++
++ while ((ch = getopt(argc, argv,
++- "46Ddhi:jklnP:p:rSs:tT:Uuvw:X:x:z")) != -1) {
+++ "46Ddhi:jklnP:p:rSs:tT:Uuvw:X:x:zC")) != -1) {
++ switch (ch) {
++ case '4':
++ family = AF_INET;
++@@ -226,6 +227,9 @@
++ case 'T':
++ Tflag = parse_iptos(optarg);
++ break;
+++ case 'C':
+++ Cflag = 1;
+++ break;
++ default:
++ usage(1);
++ }
++@@ -738,8 +742,16 @@
++ else if (n == 0) {
++ goto shutdown_wr;
++ } else {
++- if (atomicio(vwrite, nfd, buf, n) != n)
++- return;
+++ if ((Cflag) && (buf[n-1]=='\n')) {
+++ if (atomicio(vwrite, nfd, buf, n-1) != (n-1))
+++ return;
+++ if (atomicio(vwrite, nfd, "\r\n", 2) != 2)
+++ return;
+++ }
+++ else {
+++ if (atomicio(vwrite, nfd, buf, n) != n)
+++ return;
+++ }
++ }
++ }
++ else if (pfd[1].revents & POLLHUP) {
++@@ -944,6 +956,7 @@
++ #endif
++ " \t-s addr\t Local source address\n\
++ \t-T ToS\t Set IP Type of Service\n\
+++ \t-C Send CRLF as line-ending\n\
++ \t-t Answer TELNET negotiation\n\
++ \t-U Use UNIX domain socket\n\
++ \t-u UDP mode\n\
++@@ -959,7 +972,7 @@
++ void
++ usage(int ret)
++ {
++- fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-P proxy_username] [-p source_port]\n");
+++ fprintf(stderr, "usage: nc [-46DdhklnrStUuvzC] [-i interval] [-P proxy_username] [-p source_port]\n");
++ fprintf(stderr, "\t [-s source_ip_address] [-T ToS] [-w timeout] [-X proxy_protocol]\n");
++ fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n");
++ if (ret)
++Index: netcat-openbsd-1.89/nc.1
++===================================================================
++--- netcat-openbsd-1.89.orig/nc.1 2008-06-19 16:49:39.000000000 -0400
+++++ netcat-openbsd-1.89/nc.1 2008-06-19 16:54:36.000000000 -0400
++@@ -34,7 +34,7 @@
++ .Sh SYNOPSIS
++ .Nm nc
++ .Bk -words
++-.Op Fl 46DdhklnrStUuvz
+++.Op Fl 46DdhklnrStUuvzC
++ .Op Fl i Ar interval
++ .Op Fl P Ar proxy_username
++ .Op Fl p Ar source_port
++@@ -140,6 +140,10 @@
++ It is an error to use this option in conjunction with the
++ .Fl l
++ option.
+++.It Fl q
+++after EOF on stdin, wait the specified number of seconds and then quit. If
+++.Ar seconds
+++is negative, wait forever.
++ .It Fl r
++ Specifies that source and/or destination ports should be chosen randomly
++ instead of sequentially within a range or in the order that the system
++@@ -159,6 +163,8 @@
++ .Dq reliability ,
++ or an 8-bit hexadecimal value preceded by
++ .Dq 0x .
+++.It Fl C
+++Send CRLF as line-ending
++ .It Fl t
++ Causes
++ .Nm
++@@ -317,7 +323,7 @@
++ of requests required by the server.
++ As another example, an email may be submitted to an SMTP server using:
++ .Bd -literal -offset indent
++-$ nc localhost 25 \*(Lt\*(Lt EOF
+++$ nc [-C] localhost 25 \*(Lt\*(Lt EOF
++ HELO host.example.com
++ MAIL FROM:\*(Ltuser@host.example.com\*(Gt
++ RCPT TO:\*(Ltuser2@host.example.com\*(Gt
+--- netcat-openbsd-1.89.orig/debian/patches/udp-scan-timeout.patch
++++ netcat-openbsd-1.89/debian/patches/udp-scan-timeout.patch
+@@ -0,0 +1,50 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-22 16:17:30.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-22 16:17:34.000000000 -0500
++@@ -69,6 +69,8 @@
++ #define CONNECTION_FAILED 1
++ #define CONNECTION_TIMEOUT 2
++
+++#define UDP_SCAN_TIMEOUT 3 /* Seconds */
+++
++ /* Command Line Options */
++ int dflag; /* detached, no stdin */
++ int iflag; /* Interval Flag */
++@@ -376,7 +378,7 @@
++ continue;
++
++ ret = 0;
++- if (vflag) {
+++ if (vflag && !uflag) {
++ /* For UDP, make sure we are connected. */
++ if (uflag) {
++ if (udptest(s) == -1) {
++@@ -841,15 +843,20 @@
++ int
++ udptest(int s)
++ {
++- int i, ret;
+++ int i, t;
++
++- for (i = 0; i <= 3; i++) {
++- if (write(s, "X", 1) == 1)
++- ret = 1;
++- else
++- ret = -1;
+++ if ((write(s, "X", 1) != 1) ||
+++ ((write(s, "X", 1) != 1) && (errno == ECONNREFUSED)))
+++ return -1;
+++
+++ /* Give the remote host some time to reply. */
+++ for (i = 0, t = (timeout == -1) ? UDP_SCAN_TIMEOUT : (timeout / 1000);
+++ i < t; i++) {
+++ sleep(1);
+++ if ((write(s, "X", 1) != 1) && (errno == ECONNREFUSED))
+++ return -1;
++ }
++- return (ret);
+++ return 1;
++ }
++
++ void
+--- netcat-openbsd-1.89.orig/debian/patches/silence-z.patch
++++ netcat-openbsd-1.89/debian/patches/silence-z.patch
+@@ -0,0 +1,13 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-06-19 16:33:52.000000000 -0400
+++++ netcat-openbsd-1.89/netcat.c 2008-06-19 16:34:58.000000000 -0400
++@@ -364,7 +364,7 @@
++ continue;
++
++ ret = 0;
++- if (vflag || zflag) {
+++ if (vflag) {
++ /* For UDP, make sure we are connected. */
++ if (uflag) {
++ if (udptest(s) == -1) {
+--- netcat-openbsd-1.89.orig/debian/patches/reuseaddr.patch
++++ netcat-openbsd-1.89/debian/patches/reuseaddr.patch
+@@ -0,0 +1,15 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-22 16:17:25.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-22 16:17:27.000000000 -0500
++@@ -554,6 +554,10 @@
++ if ((s = socket(res0->ai_family, res0->ai_socktype,
++ res0->ai_protocol)) < 0)
++ continue;
+++
+++ ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
+++ if (ret == -1)
+++ err(1, NULL);
++ #ifdef SO_REUSEPORT
++ ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
++ if (ret == -1)
+--- netcat-openbsd-1.89.orig/debian/patches/gcc-warnings.patch
++++ netcat-openbsd-1.89/debian/patches/gcc-warnings.patch
+@@ -0,0 +1,157 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-22 20:39:46.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-22 20:42:35.000000000 -0500
++@@ -127,7 +127,7 @@
++ struct servent *sv;
++ socklen_t len;
++ struct sockaddr_storage cliaddr;
++- char *proxy;
+++ char *proxy = NULL;
++ const char *proxyhost = "", *proxyport = NULL;
++ struct addrinfo proxyhints;
++
++@@ -800,14 +800,12 @@
++ obuf[1] = DONT;
++ if ((*p == DO) || (*p == DONT))
++ obuf[1] = WONT;
++- if (obuf) {
++- p++;
++- obuf[2] = *p;
++- obuf[3] = '\0';
++- if (atomicio(vwrite, nfd, obuf, 3) != 3)
++- warn("Write Error!");
++- obuf[0] = '\0';
++- }
+++ p++;
+++ obuf[2] = *p;
+++ obuf[3] = '\0';
+++ if (atomicio(vwrite, nfd, obuf, 3) != 3)
+++ warn("Write Error!");
+++ obuf[0] = '\0';
++ }
++ }
++
++Index: netcat-openbsd-1.89/socks.c
++===================================================================
++--- netcat-openbsd-1.89.orig/socks.c 2008-01-22 20:36:26.000000000 -0500
+++++ netcat-openbsd-1.89/socks.c 2008-01-22 20:39:46.000000000 -0500
++@@ -169,11 +169,11 @@
++ buf[2] = SOCKS_NOAUTH;
++ cnt = atomicio(vwrite, proxyfd, buf, 3);
++ if (cnt != 3)
++- err(1, "write failed (%d/3)", cnt);
+++ err(1, "write failed (%d/3)", (int)cnt);
++
++ cnt = atomicio(read, proxyfd, buf, 2);
++ if (cnt != 2)
++- err(1, "read failed (%d/3)", cnt);
+++ err(1, "read failed (%d/3)", (int)cnt);
++
++ if (buf[1] == SOCKS_NOMETHOD)
++ errx(1, "authentication method negotiation failed");
++@@ -222,11 +222,11 @@
++
++ cnt = atomicio(vwrite, proxyfd, buf, wlen);
++ if (cnt != wlen)
++- err(1, "write failed (%d/%d)", cnt, wlen);
+++ err(1, "write failed (%d/%d)", (int)cnt, (int)wlen);
++
++ cnt = atomicio(read, proxyfd, buf, 10);
++ if (cnt != 10)
++- err(1, "read failed (%d/10)", cnt);
+++ err(1, "read failed (%d/10)", (int)cnt);
++ if (buf[1] != 0)
++ errx(1, "connection failed, SOCKS error %d", buf[1]);
++ } else if (socksv == 4) {
++@@ -244,11 +244,11 @@
++
++ cnt = atomicio(vwrite, proxyfd, buf, wlen);
++ if (cnt != wlen)
++- err(1, "write failed (%d/%d)", cnt, wlen);
+++ err(1, "write failed (%d/%d)", (int)cnt, (int)wlen);
++
++ cnt = atomicio(read, proxyfd, buf, 8);
++ if (cnt != 8)
++- err(1, "read failed (%d/8)", cnt);
+++ err(1, "read failed (%d/8)", (int)cnt);
++ if (buf[1] != 90)
++ errx(1, "connection failed, SOCKS error %d", buf[1]);
++ } else if (socksv == -1) {
++@@ -260,39 +260,39 @@
++
++ /* Try to be sane about numeric IPv6 addresses */
++ if (strchr(host, ':') != NULL) {
++- r = snprintf(buf, sizeof(buf),
+++ r = snprintf((char*)buf, sizeof(buf),
++ "CONNECT [%s]:%d HTTP/1.0\r\n",
++ host, ntohs(serverport));
++ } else {
++- r = snprintf(buf, sizeof(buf),
+++ r = snprintf((char*)buf, sizeof(buf),
++ "CONNECT %s:%d HTTP/1.0\r\n",
++ host, ntohs(serverport));
++ }
++ if (r == -1 || (size_t)r >= sizeof(buf))
++ errx(1, "hostname too long");
++- r = strlen(buf);
+++ r = strlen((char*)buf);
++
++ cnt = atomicio(vwrite, proxyfd, buf, r);
++ if (cnt != r)
++- err(1, "write failed (%d/%d)", cnt, r);
+++ err(1, "write failed (%d/%d)", (int)cnt, (int)r);
++
++ if (authretry > 1) {
++ char resp[1024];
++
++ proxypass = getproxypass(proxyuser, proxyhost);
++- r = snprintf(buf, sizeof(buf), "%s:%s",
+++ r = snprintf((char*)buf, sizeof(buf), "%s:%s",
++ proxyuser, proxypass);
++ if (r == -1 || (size_t)r >= sizeof(buf) ||
++- b64_ntop(buf, strlen(buf), resp,
+++ b64_ntop(buf, strlen((char*)buf), resp,
++ sizeof(resp)) == -1)
++ errx(1, "Proxy username/password too long");
++- r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
+++ r = snprintf((char*)buf, sizeof((char*)buf), "Proxy-Authorization: "
++ "Basic %s\r\n", resp);
++ if (r == -1 || (size_t)r >= sizeof(buf))
++ errx(1, "Proxy auth response too long");
++- r = strlen(buf);
+++ r = strlen((char*)buf);
++ if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r)
++- err(1, "write failed (%d/%d)", cnt, r);
+++ err(1, "write failed (%d/%d)", (int)cnt, r);
++ }
++
++ /* Terminate headers */
++@@ -300,22 +300,22 @@
++ err(1, "write failed (2/%d)", r);
++
++ /* Read status reply */
++- proxy_read_line(proxyfd, buf, sizeof(buf));
+++ proxy_read_line(proxyfd, (char*)buf, sizeof(buf));
++ if (proxyuser != NULL &&
++- strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
+++ strncmp((char*)buf, "HTTP/1.0 407 ", 12) == 0) {
++ if (authretry > 1) {
++ fprintf(stderr, "Proxy authentication "
++ "failed\n");
++ }
++ close(proxyfd);
++ goto again;
++- } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 &&
++- strncmp(buf, "HTTP/1.1 200 ", 12) != 0)
+++ } else if (strncmp((char*)buf, "HTTP/1.0 200 ", 12) != 0 &&
+++ strncmp((char*)buf, "HTTP/1.1 200 ", 12) != 0)
++ errx(1, "Proxy error: \"%s\"", buf);
++
++ /* Headers continue until we hit an empty line */
++ for (r = 0; r < HTTP_MAXHDRS; r++) {
++- proxy_read_line(proxyfd, buf, sizeof(buf));
+++ proxy_read_line(proxyfd, (char*)buf, sizeof(buf));
++ if (*buf == '\0')
++ break;
++ }
+--- netcat-openbsd-1.89.orig/debian/patches/openbsd-compat.patch
++++ netcat-openbsd-1.89/debian/patches/openbsd-compat.patch
+@@ -0,0 +1,54 @@
++Index: netcat-openbsd-1.89/openbsd-compat/readpassphrase.c
++===================================================================
++--- netcat-openbsd-1.89.orig/openbsd-compat/readpassphrase.c 2008-01-22 18:21:56.000000000 -0500
+++++ netcat-openbsd-1.89/openbsd-compat/readpassphrase.c 2008-01-22 18:22:58.000000000 -0500
++@@ -31,6 +31,12 @@
++ #include <unistd.h>
++ #include <readpassphrase.h>
++
+++#ifdef TCSASOFT
+++# define _T_FLUSH (TCSAFLUSH|TCSASOFT)
+++#else
+++# define _T_FLUSH (TCSAFLUSH)
+++#endif
+++
++ static volatile sig_atomic_t signo;
++
++ static void handler(int);
++@@ -92,9 +98,11 @@
++ memcpy(&term, &oterm, sizeof(term));
++ if (!(flags & RPP_ECHO_ON))
++ term.c_lflag &= ~(ECHO | ECHONL);
+++#ifdef VSTATUS
++ if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
++ term.c_cc[VSTATUS] = _POSIX_VDISABLE;
++- (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
+++#endif
+++ (void)tcsetattr(input, _T_FLUSH, &term);
++ } else {
++ memset(&term, 0, sizeof(term));
++ term.c_lflag |= ECHO;
++@@ -129,7 +137,7 @@
++
++ /* Restore old terminal settings and signals. */
++ if (memcmp(&term, &oterm, sizeof(term)) != 0) {
++- while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
+++ while (tcsetattr(input, _T_FLUSH, &oterm) == -1 &&
++ errno == EINTR)
++ continue;
++ }
++@@ -164,14 +172,6 @@
++ return(nr == -1 ? NULL : buf);
++ }
++
++-char *
++-getpass(const char *prompt)
++-{
++- static char buf[_PASSWORD_LEN + 1];
++-
++- return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
++-}
++-
++ static void handler(int s)
++ {
++
+--- netcat-openbsd-1.89.orig/debian/patches/socks-b64-prototype.patch
++++ netcat-openbsd-1.89/debian/patches/socks-b64-prototype.patch
+@@ -0,0 +1,13 @@
++Index: netcat-openbsd-1.89/socks.c
++===================================================================
++--- netcat-openbsd-1.89.orig/socks.c 2008-06-19 16:30:45.000000000 -0400
+++++ netcat-openbsd-1.89/socks.c 2008-06-19 16:30:36.000000000 -0400
++@@ -53,6 +53,8 @@
++ #define SOCKS_DOMAIN 3
++ #define SOCKS_IPV6 4
++
+++extern int b64_ntop(unsigned char const *, size_t, char *, size_t);
+++
++ int remote_connect(const char *, const char *, struct addrinfo);
++ int socks_connect(const char *, const char *, struct addrinfo,
++ const char *, const char *, struct addrinfo, int,
+--- netcat-openbsd-1.89.orig/debian/patches/connect-timeout.patch
++++ netcat-openbsd-1.89/debian/patches/connect-timeout.patch
+@@ -0,0 +1,120 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-22 16:17:27.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-22 16:17:30.000000000 -0500
++@@ -65,6 +65,10 @@
++ #define PORT_MAX 65535
++ #define PORT_MAX_LEN 6
++
+++#define CONNECTION_SUCCESS 0
+++#define CONNECTION_FAILED 1
+++#define CONNECTION_TIMEOUT 2
+++
++ /* Command Line Options */
++ int dflag; /* detached, no stdin */
++ int iflag; /* Interval Flag */
++@@ -104,6 +108,9 @@
++ int parse_iptos(char *);
++ void usage(int);
++
+++static int connect_with_timeout(int fd, const struct sockaddr *sa,
+++ socklen_t salen, int ctimeout);
+++
++ int
++ main(int argc, char *argv[])
++ {
++@@ -508,13 +515,15 @@
++ }
++
++ set_common_sockopts(s);
++-
++- if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
+++ if ((error = connect_with_timeout(s, res0->ai_addr, res0->ai_addrlen, timeout)) == CONNECTION_SUCCESS)
++ break;
++- else if (vflag)
+++ else if (vflag && error == CONNECTION_FAILED)
++ warn("connect to %s port %s (%s) failed", host, port,
++ uflag ? "udp" : "tcp");
++-
+++ else if (vflag && error == CONNECTION_TIMEOUT)
+++ warn("connect to %s port %s (%s) timed out", host, port,
+++ uflag ? "udp" : "tcp");
+++
++ close(s);
++ s = -1;
++ } while ((res0 = res0->ai_next) != NULL);
++@@ -524,6 +533,74 @@
++ return (s);
++ }
++
+++static int connect_with_timeout(int fd, const struct sockaddr *sa,
+++ socklen_t salen, int ctimeout)
+++{
+++ int err;
+++ struct timeval tv, *tvp = NULL;
+++ fd_set connect_fdset;
+++ socklen_t len;
+++ int orig_flags;
+++
+++ orig_flags = fcntl(fd, F_GETFL, 0);
+++ if (fcntl(fd, F_SETFL, orig_flags | O_NONBLOCK) < 0 ) {
+++ warn("can't set O_NONBLOCK - timeout not avaliable");
+++ if (connect(fd, sa, salen) == 0)
+++ return CONNECTION_SUCCESS;
+++ else
+++ return CONNECTION_FAILED;
+++ }
+++
+++ /* set connect timeout */
+++ if (ctimeout > 0) {
+++ tv.tv_sec = (time_t)ctimeout/1000;
+++ tv.tv_usec = 0;
+++ tvp = &tv;
+++ }
+++
+++ /* attempt the connection */
+++ err = connect(fd, sa, salen);
+++
+++ if (err != 0 && errno == EINPROGRESS) {
+++ /* connection is proceeding
+++ * it is complete (or failed) when select returns */
+++
+++ /* initialize connect_fdset */
+++ FD_ZERO(&connect_fdset);
+++ FD_SET(fd, &connect_fdset);
+++
+++ /* call select */
+++ do {
+++ err = select(fd + 1, NULL, &connect_fdset,
+++ NULL, tvp);
+++ } while (err < 0 && errno == EINTR);
+++
+++ /* select error */
+++ if (err < 0)
+++ errx(1,"select error: %s", strerror(errno));
+++
+++ /* we have reached a timeout */
+++ if (err == 0)
+++ return CONNECTION_TIMEOUT;
+++
+++ /* select returned successfully, but we must test socket
+++ * error for result */
+++ len = sizeof(err);
+++ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
+++ errx(1, "getsockopt error: %s", strerror(errno));
+++
+++ /* setup errno according to the result returned by
+++ * getsockopt */
+++ if (err != 0)
+++ errno = err;
+++ }
+++
+++ /* return aborted if an error occured, and valid otherwise */
+++ fcntl(fd, F_SETFL, orig_flags);
+++ return (err != 0)? CONNECTION_FAILED : CONNECTION_SUCCESS;
+++}
+++
+++
++ /*
++ * local_listen()
++ * Returns a socket listening on a local port, binds to specified source
+--- netcat-openbsd-1.89.orig/debian/patches/quit-timer.patch
++++ netcat-openbsd-1.89/debian/patches/quit-timer.patch
+@@ -0,0 +1,84 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2010-04-18 20:02:55.240980186 -0400
+++++ netcat-openbsd-1.89/netcat.c 2010-04-18 20:04:41.987984568 -0400
++@@ -47,6 +47,7 @@
++ #include <errno.h>
++ #include <netdb.h>
++ #include <poll.h>
+++#include <signal.h>
++ #include <stdarg.h>
++ #include <stdio.h>
++ #include <stdlib.h>
++@@ -82,6 +83,7 @@
++ int nflag; /* Don't do name look up */
++ char *Pflag; /* Proxy username */
++ char *pflag; /* Localport flag */
+++int qflag = -1; /* Quit after some secs */
++ int rflag; /* Random ports flag */
++ char *sflag; /* Source Address */
++ int tflag; /* Telnet Emulation */
++@@ -114,6 +116,7 @@
++
++ static int connect_with_timeout(int fd, const struct sockaddr *sa,
++ socklen_t salen, int ctimeout);
+++static void quit();
++
++ int
++ main(int argc, char *argv[])
++@@ -137,7 +140,7 @@
++ sv = NULL;
++
++ while ((ch = getopt(argc, argv,
++- "46Ddhi:jklnP:p:rSs:tT:Uuvw:X:x:zC")) != -1) {
+++ "46Ddhi:jklnP:p:q:rSs:tT:Uuvw:X:x:zC")) != -1) {
++ switch (ch) {
++ case '4':
++ family = AF_INET;
++@@ -187,6 +190,9 @@
++ case 'p':
++ pflag = optarg;
++ break;
+++ case 'q':
+++ qflag = (int)strtoul(optarg, &endp, 10);
+++ break;
++ case 'r':
++ rflag = 1;
++ break;
++@@ -756,7 +762,13 @@
++ }
++ else if (pfd[1].revents & POLLHUP) {
++ shutdown_wr:
++- shutdown(nfd, SHUT_WR);
+++ /* if user asked to die after a while, arrange for it */
+++ if (qflag > 0) {
+++ signal(SIGALRM, quit);
+++ alarm(qflag);
+++ } else {
+++ shutdown(nfd, SHUT_WR);
+++ }
++ pfd[1].fd = -1;
++ pfd[1].events = 0;
++ }
++@@ -951,6 +963,7 @@
++ \t-n Suppress name/port resolutions\n\
++ \t-P proxyuser\tUsername for proxy authentication\n\
++ \t-p port\t Specify local port for remote connects\n\
+++ \t-q secs\t quit after EOF on stdin and delay of secs\n\
++ \t-r Randomize remote ports\n "
++ #ifdef TCP_MD5SIG
++ " \t-S Enable the TCP MD5 signature option\n"
++@@ -979,3 +992,13 @@
++ if (ret)
++ exit(1);
++ }
+++
+++/*
+++ * quit()
+++ * handler for a "-q" timeout (exit 0 instead of 1)
+++ */
+++static void quit()
+++{
+++ /* XXX: should explicitly close fds here */
+++ exit(0);
+++}
+--- netcat-openbsd-1.89.orig/debian/patches/help-version-exit.patch
++++ netcat-openbsd-1.89/debian/patches/help-version-exit.patch
+@@ -0,0 +1,21 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-25 13:14:34.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-25 13:15:49.000000000 -0500
++@@ -937,6 +937,7 @@
++ void
++ help(void)
++ {
+++ fprintf(stderr, "OpenBSD netcat (Debian patchlevel " DEBIAN_VERSION ")\n");
++ usage(0);
++ fprintf(stderr, "\tCommand Summary:\n\
++ \t-4 Use IPv4\n\
++@@ -966,7 +967,7 @@
++ \t-x addr[:port]\tSpecify proxy address and port\n\
++ \t-z Zero-I/O mode [used for scanning]\n\
++ Port numbers can be individual or ranges: lo-hi [inclusive]\n");
++- exit(1);
+++ exit(0);
++ }
++
++ void
+--- netcat-openbsd-1.89.orig/debian/patches/pollhup.patch
++++ netcat-openbsd-1.89/debian/patches/pollhup.patch
+@@ -0,0 +1,50 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-22 16:17:18.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-22 16:17:25.000000000 -0500
++@@ -618,9 +618,7 @@
++ if ((n = read(nfd, buf, plen)) < 0)
++ return;
++ else if (n == 0) {
++- shutdown(nfd, SHUT_RD);
++- pfd[0].fd = -1;
++- pfd[0].events = 0;
+++ goto shutdown_rd;
++ } else {
++ if (tflag)
++ atelnet(nfd, buf, n);
++@@ -628,18 +626,30 @@
++ return;
++ }
++ }
+++ else if (pfd[0].revents & POLLHUP) {
+++ shutdown_rd:
+++ shutdown(nfd, SHUT_RD);
+++ pfd[0].fd = -1;
+++ pfd[0].events = 0;
+++ }
++
++- if (!dflag && pfd[1].revents & POLLIN) {
+++ if (!dflag) {
+++ if(pfd[1].revents & POLLIN) {
++ if ((n = read(wfd, buf, plen)) < 0)
++ return;
++ else if (n == 0) {
++- shutdown(nfd, SHUT_WR);
++- pfd[1].fd = -1;
++- pfd[1].events = 0;
+++ goto shutdown_wr;
++ } else {
++ if (atomicio(vwrite, nfd, buf, n) != n)
++ return;
++ }
+++ }
+++ else if (pfd[1].revents & POLLHUP) {
+++ shutdown_wr:
+++ shutdown(nfd, SHUT_WR);
+++ pfd[1].fd = -1;
+++ pfd[1].events = 0;
+++ }
++ }
++ }
++ }
+--- netcat-openbsd-1.89.orig/debian/patches/no-strtonum.patch
++++ netcat-openbsd-1.89/debian/patches/no-strtonum.patch
+@@ -0,0 +1,107 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-22 16:17:17.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-22 16:17:18.000000000 -0500
++@@ -67,7 +67,7 @@
++
++ /* Command Line Options */
++ int dflag; /* detached, no stdin */
++-unsigned int iflag; /* Interval Flag */
+++int iflag; /* Interval Flag */
++ int jflag; /* use jumbo frames if we can */
++ int kflag; /* More than one connect */
++ int lflag; /* Bind to local port */
++@@ -108,13 +108,13 @@
++ main(int argc, char *argv[])
++ {
++ int ch, s, ret, socksv;
++- char *host, *uport;
+++ char *host, *uport, *endp;
++ struct addrinfo hints;
++ struct servent *sv;
++ socklen_t len;
++ struct sockaddr_storage cliaddr;
++ char *proxy;
++- const char *errstr, *proxyhost = "", *proxyport = NULL;
+++ const char *proxyhost = "", *proxyport = NULL;
++ struct addrinfo proxyhints;
++
++ ret = 1;
++@@ -122,6 +122,7 @@
++ socksv = 5;
++ host = NULL;
++ uport = NULL;
+++ endp = NULL;
++ sv = NULL;
++
++ while ((ch = getopt(argc, argv,
++@@ -153,9 +154,9 @@
++ help();
++ break;
++ case 'i':
++- iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
++- if (errstr)
++- errx(1, "interval %s: %s", errstr, optarg);
+++ iflag = (int)strtoul(optarg, &endp, 10);
+++ if (iflag < 0 || *endp != '\0')
+++ errx(1, "interval cannot be negative");
++ break;
++ case 'j':
++ jflag = 1;
++@@ -191,9 +192,11 @@
++ vflag = 1;
++ break;
++ case 'w':
++- timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
++- if (errstr)
++- errx(1, "timeout %s: %s", errstr, optarg);
+++ timeout = (int)strtoul(optarg, &endp, 10);
+++ if (timeout < 0 || *endp != '\0')
+++ errx(1, "timeout cannot be negative");
+++ if (timeout >= (INT_MAX / 1000))
+++ errx(1, "timeout too large");
++ timeout *= 1000;
++ break;
++ case 'x':
++@@ -680,8 +683,7 @@
++ void
++ build_ports(char *p)
++ {
++- const char *errstr;
++- char *n;
+++ char *n, *endp;
++ int hi, lo, cp;
++ int x = 0;
++
++@@ -693,12 +695,12 @@
++ n++;
++
++ /* Make sure the ports are in order: lowest->highest. */
++- hi = strtonum(n, 1, PORT_MAX, &errstr);
++- if (errstr)
++- errx(1, "port number %s: %s", errstr, n);
++- lo = strtonum(p, 1, PORT_MAX, &errstr);
++- if (errstr)
++- errx(1, "port number %s: %s", errstr, p);
+++ hi = (int)strtoul(n, &endp, 10);
+++ if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
+++ errx(1, "port range not valid");
+++ lo = (int)strtoul(p, &endp, 10);
+++ if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
+++ errx(1, "port range not valid");
++
++ if (lo > hi) {
++ cp = hi;
++@@ -729,9 +731,9 @@
++ }
++ }
++ } else {
++- hi = strtonum(p, 1, PORT_MAX, &errstr);
++- if (errstr)
++- errx(1, "port number %s: %s", errstr, p);
+++ hi = (int)strtoul(p, &endp, 10);
+++ if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
+++ errx(1, "port range not valid");
++ portlist[0] = calloc(1, PORT_MAX_LEN);
++ if (portlist[0] == NULL)
++ err(1, NULL);
+--- netcat-openbsd-1.89.orig/debian/patches/nc-1.84-udp_stop.patch
++++ netcat-openbsd-1.89/debian/patches/nc-1.84-udp_stop.patch
+@@ -0,0 +1,14 @@
++Index: netcat-1.84/netcat.c
++===================================================================
++--- netcat-1.84.orig/netcat.c 2008-01-15 10:10:22.373351813 +0100
+++++ netcat-1.84/netcat.c 2008-01-15 10:10:24.840730278 +0100
++@@ -799,6 +799,9 @@
++ hi = lo;
++ lo = cp;
++ }
+++ else if (pfd[0].revents & POLLERR)
+++ if (write(nfd, "", 1) == -1)
+++ warn("Write error");
++
++ /* Load ports sequentially. */
++ for (cp = lo; cp <= hi; cp++) {
+--- netcat-openbsd-1.89.orig/debian/patches/glib-strlcpy.patch
++++ netcat-openbsd-1.89/debian/patches/glib-strlcpy.patch
+@@ -0,0 +1,96 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2007-02-20 09:11:17.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-21 18:48:23.000000000 -0500
++@@ -55,6 +55,8 @@
++ #include <limits.h>
++ #include "atomicio.h"
++
+++#include <glib.h>
+++
++ #ifndef SUN_LEN
++ #define SUN_LEN(su) \
++ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
++@@ -414,7 +416,7 @@
++ memset(&sun, 0, sizeof(struct sockaddr_un));
++ sun.sun_family = AF_UNIX;
++
++- if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
+++ if (g_strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
++ sizeof(sun.sun_path)) {
++ close(s);
++ errno = ENAMETOOLONG;
++@@ -445,7 +447,7 @@
++ memset(&sun, 0, sizeof(struct sockaddr_un));
++ sun.sun_family = AF_UNIX;
++
++- if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
+++ if (g_strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
++ sizeof(sun.sun_path)) {
++ close(s);
++ errno = ENAMETOOLONG;
++@@ -549,11 +551,11 @@
++ if ((s = socket(res0->ai_family, res0->ai_socktype,
++ res0->ai_protocol)) < 0)
++ continue;
++-
+++ #ifdef SO_REUSEPORT
++ ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
++ if (ret == -1)
++ err(1, NULL);
++-
+++ #endif
++ set_common_sockopts(s);
++
++ if (bind(s, (struct sockaddr *)res0->ai_addr,
++@@ -719,7 +721,8 @@
++ char *c;
++
++ for (x = 0; x <= (hi - lo); x++) {
++- y = (arc4random() & 0xFFFF) % (hi - lo);
+++ /* use random instead of arc4random */
+++ y = (random() & 0xFFFF) % (hi - lo);
++ c = portlist[x];
++ portlist[x] = portlist[y];
++ portlist[y] = c;
++@@ -761,21 +764,25 @@
++ {
++ int x = 1;
++
+++#ifdef TCP_MD5SIG
++ if (Sflag) {
++ if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
++ &x, sizeof(x)) == -1)
++ err(1, NULL);
++ }
+++#endif
++ if (Dflag) {
++ if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
++ &x, sizeof(x)) == -1)
++ err(1, NULL);
++ }
+++#ifdef SO_JUMBO
++ if (jflag) {
++ if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
++ &x, sizeof(x)) == -1)
++ err(1, NULL);
++ }
+++#endif
++ if (Tflag != -1) {
++ if (setsockopt(s, IPPROTO_IP, IP_TOS,
++ &Tflag, sizeof(Tflag)) == -1)
++@@ -816,9 +823,11 @@
++ \t-n Suppress name/port resolutions\n\
++ \t-P proxyuser\tUsername for proxy authentication\n\
++ \t-p port\t Specify local port for remote connects\n\
++- \t-r Randomize remote ports\n\
++- \t-S Enable the TCP MD5 signature option\n\
++- \t-s addr\t Local source address\n\
+++ \t-r Randomize remote ports\n "
+++#ifdef TCP_MD5SIG
+++" \t-S Enable the TCP MD5 signature option\n"
+++#endif
+++" \t-s addr\t Local source address\n\
++ \t-T ToS\t Set IP Type of Service\n\
++ \t-t Answer TELNET negotiation\n\
++ \t-U Use UNIX domain socket\n\
+--- netcat-openbsd-1.89.orig/debian/patches/verbose-numeric-port.patch
++++ netcat-openbsd-1.89/debian/patches/verbose-numeric-port.patch
+@@ -0,0 +1,54 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-22 16:17:34.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-22 16:17:44.000000000 -0500
++@@ -41,6 +41,7 @@
++ #include <netinet/tcp.h>
++ #include <netinet/ip.h>
++ #include <arpa/telnet.h>
+++#include <arpa/inet.h>
++
++ #include <err.h>
++ #include <errno.h>
++@@ -317,16 +318,15 @@
++ if (uflag) {
++ int rv, plen;
++ char buf[8192];
++- struct sockaddr_storage z;
++
++- len = sizeof(z);
+++ len = sizeof(cliaddr);
++ plen = jflag ? 8192 : 1024;
++ rv = recvfrom(s, buf, plen, MSG_PEEK,
++- (struct sockaddr *)&z, &len);
+++ (struct sockaddr *)&cliaddr, &len);
++ if (rv < 0)
++ err(1, "recvfrom");
++
++- rv = connect(s, (struct sockaddr *)&z, len);
+++ rv = connect(s, (struct sockaddr *)&cliaddr, len);
++ if (rv < 0)
++ err(1, "connect");
++
++@@ -337,6 +337,21 @@
++ &len);
++ }
++
+++ if(vflag) {
+++ /* Don't look up port if -n. */
+++ if (nflag)
+++ sv = NULL;
+++ else
+++ sv = getservbyport(ntohs(atoi(uport)),
+++ uflag ? "udp" : "tcp");
+++
+++ fprintf(stderr, "Connection from %s port %s [%s/%s] accepted\n",
+++ inet_ntoa(((struct sockaddr_in *)(&cliaddr))->sin_addr),
+++ uport,
+++ uflag ? "udp" : "tcp",
+++ sv ? sv->s_name : "*");
+++ }
+++
++ readwrite(connfd);
++ close(connfd);
++ if (family != AF_UNIX)
+--- netcat-openbsd-1.89.orig/debian/patches/series
++++ netcat-openbsd-1.89/debian/patches/series
+@@ -0,0 +1,15 @@
++openbsd-compat.patch
++socks-b64-prototype.patch
++silence-z.patch
++glib-strlcpy.patch
++no-strtonum.patch
++pollhup.patch
++reuseaddr.patch
++connect-timeout.patch
++udp-scan-timeout.patch
++verbose-numeric-port.patch
++send-crlf.patch
++help-version-exit.patch
++quit-timer.patch
++getservbyname.patch
++gcc-warnings.patch
+--- netcat-openbsd-1.89.orig/debian/patches/getservbyname.patch
++++ netcat-openbsd-1.89/debian/patches/getservbyname.patch
+@@ -0,0 +1,24 @@
++Index: netcat-openbsd-1.89/netcat.c
++===================================================================
++--- netcat-openbsd-1.89.orig/netcat.c 2008-01-22 20:39:46.000000000 -0500
+++++ netcat-openbsd-1.89/netcat.c 2008-01-22 20:43:36.000000000 -0500
++@@ -819,11 +819,18 @@
++ void
++ build_ports(char *p)
++ {
+++ struct servent *sv;
++ char *n, *endp;
++ int hi, lo, cp;
++ int x = 0;
++
++- if ((n = strchr(p, '-')) != NULL) {
+++ sv = getservbyname(p, uflag ? "udp" : "tcp");
+++ if (sv) {
+++ portlist[0] = calloc(1, PORT_MAX_LEN);
+++ if (portlist[0] == NULL)
+++ err(1, NULL);
+++ snprintf(portlist[0], PORT_MAX_LEN, "%d", ntohs(sv->s_port));
+++ } else if ((n = strchr(p, '-')) != NULL) {
++ if (lflag)
++ errx(1, "Cannot use -l with multiple ports!");
++
+--- netcat-openbsd-1.89.orig/openbsd-compat/readpassphrase.h
++++ netcat-openbsd-1.89/openbsd-compat/readpassphrase.h
+@@ -0,0 +1,40 @@
++/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */
++
++/*
++ * Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Sponsored in part by the Defense Advanced Research Projects
++ * Agency (DARPA) and Air Force Research Laboratory, Air Force
++ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
++ */
++
++#ifndef _READPASSPHRASE_H_
++#define _READPASSPHRASE_H_
++
++#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */
++#define RPP_ECHO_ON 0x01 /* Leave echo on. */
++#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */
++#define RPP_FORCELOWER 0x04 /* Force input to lower case. */
++#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */
++#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */
++#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */
++
++#include <sys/cdefs.h>
++
++__BEGIN_DECLS
++char * readpassphrase(const char *, char *, size_t, int);
++__END_DECLS
++
++#endif /* !_READPASSPHRASE_H_ */
+--- netcat-openbsd-1.89.orig/openbsd-compat/base64.c
++++ netcat-openbsd-1.89/openbsd-compat/base64.c
+@@ -0,0 +1,308 @@
++/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */
++
++/*
++ * Copyright (c) 1996 by Internet Software Consortium.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
++ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
++ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
++ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
++ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
++ * SOFTWARE.
++ */
++
++/*
++ * Portions Copyright (c) 1995 by International Business Machines, Inc.
++ *
++ * International Business Machines, Inc. (hereinafter called IBM) grants
++ * permission under its copyrights to use, copy, modify, and distribute this
++ * Software with or without fee, provided that the above copyright notice and
++ * all paragraphs of this notice appear in all copies, and that the name of IBM
++ * not be used in connection with the marketing of any product incorporating
++ * the Software or modifications thereof, without specific, written prior
++ * permission.
++ *
++ * To the extent it has a right to do so, IBM grants an immunity from suit
++ * under its patents, if any, for the use, sale or manufacture of products to
++ * the extent that such products are used for performing Domain Name System
++ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
++ * granted for any product per se or for any other function of any product.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
++ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
++ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
++ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
++ */
++
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <arpa/nameser.h>
++
++#include <ctype.h>
++#include <resolv.h>
++#include <stdio.h>
++
++#include <stdlib.h>
++#include <string.h>
++
++static const char Base64[] =
++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
++static const char Pad64 = '=';
++
++/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
++ The following encoding technique is taken from RFC 1521 by Borenstein
++ and Freed. It is reproduced here in a slightly edited form for
++ convenience.
++
++ A 65-character subset of US-ASCII is used, enabling 6 bits to be
++ represented per printable character. (The extra 65th character, "=",
++ is used to signify a special processing function.)
++
++ The encoding process represents 24-bit groups of input bits as output
++ strings of 4 encoded characters. Proceeding from left to right, a
++ 24-bit input group is formed by concatenating 3 8-bit input groups.
++ These 24 bits are then treated as 4 concatenated 6-bit groups, each
++ of which is translated into a single digit in the base64 alphabet.
++
++ Each 6-bit group is used as an index into an array of 64 printable
++ characters. The character referenced by the index is placed in the
++ output string.
++
++ Table 1: The Base64 Alphabet
++
++ Value Encoding Value Encoding Value Encoding Value Encoding
++ 0 A 17 R 34 i 51 z
++ 1 B 18 S 35 j 52 0
++ 2 C 19 T 36 k 53 1
++ 3 D 20 U 37 l 54 2
++ 4 E 21 V 38 m 55 3
++ 5 F 22 W 39 n 56 4
++ 6 G 23 X 40 o 57 5
++ 7 H 24 Y 41 p 58 6
++ 8 I 25 Z 42 q 59 7
++ 9 J 26 a 43 r 60 8
++ 10 K 27 b 44 s 61 9
++ 11 L 28 c 45 t 62 +
++ 12 M 29 d 46 u 63 /
++ 13 N 30 e 47 v
++ 14 O 31 f 48 w (pad) =
++ 15 P 32 g 49 x
++ 16 Q 33 h 50 y
++
++ Special processing is performed if fewer than 24 bits are available
++ at the end of the data being encoded. A full encoding quantum is
++ always completed at the end of a quantity. When fewer than 24 input
++ bits are available in an input group, zero bits are added (on the
++ right) to form an integral number of 6-bit groups. Padding at the
++ end of the data is performed using the '=' character.
++
++ Since all base64 input is an integral number of octets, only the
++ -------------------------------------------------
++ following cases can arise:
++
++ (1) the final quantum of encoding input is an integral
++ multiple of 24 bits; here, the final unit of encoded
++ output will be an integral multiple of 4 characters
++ with no "=" padding,
++ (2) the final quantum of encoding input is exactly 8 bits;
++ here, the final unit of encoded output will be two
++ characters followed by two "=" padding characters, or
++ (3) the final quantum of encoding input is exactly 16 bits;
++ here, the final unit of encoded output will be three
++ characters followed by one "=" padding character.
++ */
++
++int
++b64_ntop(src, srclength, target, targsize)
++ u_char const *src;
++ size_t srclength;
++ char *target;
++ size_t targsize;
++{
++ size_t datalength = 0;
++ u_char input[3];
++ u_char output[4];
++ int i;
++
++ while (2 < srclength) {
++ input[0] = *src++;
++ input[1] = *src++;
++ input[2] = *src++;
++ srclength -= 3;
++
++ output[0] = input[0] >> 2;
++ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
++ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
++ output[3] = input[2] & 0x3f;
++
++ if (datalength + 4 > targsize)
++ return (-1);
++ target[datalength++] = Base64[output[0]];
++ target[datalength++] = Base64[output[1]];
++ target[datalength++] = Base64[output[2]];
++ target[datalength++] = Base64[output[3]];
++ }
++
++ /* Now we worry about padding. */
++ if (0 != srclength) {
++ /* Get what's left. */
++ input[0] = input[1] = input[2] = '\0';
++ for (i = 0; i < srclength; i++)
++ input[i] = *src++;
++
++ output[0] = input[0] >> 2;
++ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
++ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
++
++ if (datalength + 4 > targsize)
++ return (-1);
++ target[datalength++] = Base64[output[0]];
++ target[datalength++] = Base64[output[1]];
++ if (srclength == 1)
++ target[datalength++] = Pad64;
++ else
++ target[datalength++] = Base64[output[2]];
++ target[datalength++] = Pad64;
++ }
++ if (datalength >= targsize)
++ return (-1);
++ target[datalength] = '\0'; /* Returned value doesn't count \0. */
++ return (datalength);
++}
++
++/* skips all whitespace anywhere.
++ converts characters, four at a time, starting at (or after)
++ src from base - 64 numbers into three 8 bit bytes in the target area.
++ it returns the number of data bytes stored at the target, or -1 on error.
++ */
++
++int
++b64_pton(src, target, targsize)
++ char const *src;
++ u_char *target;
++ size_t targsize;
++{
++ int tarindex, state, ch;
++ char *pos;
++
++ state = 0;
++ tarindex = 0;
++
++ while ((ch = *src++) != '\0') {
++ if (isspace(ch)) /* Skip whitespace anywhere. */
++ continue;
++
++ if (ch == Pad64)
++ break;
++
++ pos = strchr(Base64, ch);
++ if (pos == 0) /* A non-base64 character. */
++ return (-1);
++
++ switch (state) {
++ case 0:
++ if (target) {
++ if (tarindex >= targsize)
++ return (-1);
++ target[tarindex] = (pos - Base64) << 2;
++ }
++ state = 1;
++ break;
++ case 1:
++ if (target) {
++ if (tarindex + 1 >= targsize)
++ return (-1);
++ target[tarindex] |= (pos - Base64) >> 4;
++ target[tarindex+1] = ((pos - Base64) & 0x0f)
++ << 4 ;
++ }
++ tarindex++;
++ state = 2;
++ break;
++ case 2:
++ if (target) {
++ if (tarindex + 1 >= targsize)
++ return (-1);
++ target[tarindex] |= (pos - Base64) >> 2;
++ target[tarindex+1] = ((pos - Base64) & 0x03)
++ << 6;
++ }
++ tarindex++;
++ state = 3;
++ break;
++ case 3:
++ if (target) {
++ if (tarindex >= targsize)
++ return (-1);
++ target[tarindex] |= (pos - Base64);
++ }
++ tarindex++;
++ state = 0;
++ break;
++ }
++ }
++
++ /*
++ * We are done decoding Base-64 chars. Let's see if we ended
++ * on a byte boundary, and/or with erroneous trailing characters.
++ */
++
++ if (ch == Pad64) { /* We got a pad char. */
++ ch = *src++; /* Skip it, get next. */
++ switch (state) {
++ case 0: /* Invalid = in first position */
++ case 1: /* Invalid = in second position */
++ return (-1);
++
++ case 2: /* Valid, means one byte of info */
++ /* Skip any number of spaces. */
++ for (; ch != '\0'; ch = *src++)
++ if (!isspace(ch))
++ break;
++ /* Make sure there is another trailing = sign. */
++ if (ch != Pad64)
++ return (-1);
++ ch = *src++; /* Skip the = */
++ /* Fall through to "single trailing =" case. */
++ /* FALLTHROUGH */
++
++ case 3: /* Valid, means two bytes of info */
++ /*
++ * We know this char is an =. Is there anything but
++ * whitespace after it?
++ */
++ for (; ch != '\0'; ch = *src++)
++ if (!isspace(ch))
++ return (-1);
++
++ /*
++ * Now make sure for cases 2 and 3 that the "extra"
++ * bits that slopped past the last full byte were
++ * zeros. If we don't check them, they become a
++ * subliminal channel.
++ */
++ if (target && target[tarindex] != 0)
++ return (-1);
++ }
++ } else {
++ /*
++ * We ended by seeing the end of the string. Make sure we
++ * have no partial bytes lying around.
++ */
++ if (state != 0)
++ return (-1);
++ }
++
++ return (tarindex);
++}
+--- netcat-openbsd-1.89.orig/openbsd-compat/readpassphrase.c
++++ netcat-openbsd-1.89/openbsd-compat/readpassphrase.c
+@@ -0,0 +1,179 @@
++/* $OpenBSD: readpassphrase.c,v 1.21 2008/01/17 16:27:07 millert Exp $ */
++
++/*
++ * Copyright (c) 2000-2002, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Sponsored in part by the Defense Advanced Research Projects
++ * Agency (DARPA) and Air Force Research Laboratory, Air Force
++ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
++ */
++
++#include <ctype.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <paths.h>
++#include <pwd.h>
++#include <signal.h>
++#include <string.h>
++#include <termios.h>
++#include <unistd.h>
++#include <readpassphrase.h>
++
++static volatile sig_atomic_t signo;
++
++static void handler(int);
++
++char *
++readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
++{
++ ssize_t nr;
++ int input, output, save_errno;
++ char ch, *p, *end;
++ struct termios term, oterm;
++ struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
++ struct sigaction savetstp, savettin, savettou, savepipe;
++
++ /* I suppose we could alloc on demand in this case (XXX). */
++ if (bufsiz == 0) {
++ errno = EINVAL;
++ return(NULL);
++ }
++
++restart:
++ signo = 0;
++ nr = -1;
++ save_errno = 0;
++ /*
++ * Read and write to /dev/tty if available. If not, read from
++ * stdin and write to stderr unless a tty is required.
++ */
++ if ((flags & RPP_STDIN) ||
++ (input = output = open(_PATH_TTY, O_RDWR)) == -1) {
++ if (flags & RPP_REQUIRE_TTY) {
++ errno = ENOTTY;
++ return(NULL);
++ }
++ input = STDIN_FILENO;
++ output = STDERR_FILENO;
++ }
++
++ /*
++ * Catch signals that would otherwise cause the user to end
++ * up with echo turned off in the shell. Don't worry about
++ * things like SIGXCPU and SIGVTALRM for now.
++ */
++ sigemptyset(&sa.sa_mask);
++ sa.sa_flags = 0; /* don't restart system calls */
++ sa.sa_handler = handler;
++ (void)sigaction(SIGALRM, &sa, &savealrm);
++ (void)sigaction(SIGHUP, &sa, &savehup);
++ (void)sigaction(SIGINT, &sa, &saveint);
++ (void)sigaction(SIGPIPE, &sa, &savepipe);
++ (void)sigaction(SIGQUIT, &sa, &savequit);
++ (void)sigaction(SIGTERM, &sa, &saveterm);
++ (void)sigaction(SIGTSTP, &sa, &savetstp);
++ (void)sigaction(SIGTTIN, &sa, &savettin);
++ (void)sigaction(SIGTTOU, &sa, &savettou);
++
++ /* Turn off echo if possible. */
++ if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
++ memcpy(&term, &oterm, sizeof(term));
++ if (!(flags & RPP_ECHO_ON))
++ term.c_lflag &= ~(ECHO | ECHONL);
++ if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
++ term.c_cc[VSTATUS] = _POSIX_VDISABLE;
++ (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
++ } else {
++ memset(&term, 0, sizeof(term));
++ term.c_lflag |= ECHO;
++ memset(&oterm, 0, sizeof(oterm));
++ oterm.c_lflag |= ECHO;
++ }
++
++ /* No I/O if we are already backgrounded. */
++ if (signo != SIGTTOU && signo != SIGTTIN) {
++ if (!(flags & RPP_STDIN))
++ (void)write(output, prompt, strlen(prompt));
++ end = buf + bufsiz - 1;
++ p = buf;
++ while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
++ if (p < end) {
++ if ((flags & RPP_SEVENBIT))
++ ch &= 0x7f;
++ if (isalpha(ch)) {
++ if ((flags & RPP_FORCELOWER))
++ ch = (char)tolower(ch);
++ if ((flags & RPP_FORCEUPPER))
++ ch = (char)toupper(ch);
++ }
++ *p++ = ch;
++ }
++ }
++ *p = '\0';
++ save_errno = errno;
++ if (!(term.c_lflag & ECHO))
++ (void)write(output, "\n", 1);
++ }
++
++ /* Restore old terminal settings and signals. */
++ if (memcmp(&term, &oterm, sizeof(term)) != 0) {
++ while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
++ errno == EINTR)
++ continue;
++ }
++ (void)sigaction(SIGALRM, &savealrm, NULL);
++ (void)sigaction(SIGHUP, &savehup, NULL);
++ (void)sigaction(SIGINT, &saveint, NULL);
++ (void)sigaction(SIGQUIT, &savequit, NULL);
++ (void)sigaction(SIGPIPE, &savepipe, NULL);
++ (void)sigaction(SIGTERM, &saveterm, NULL);
++ (void)sigaction(SIGTSTP, &savetstp, NULL);
++ (void)sigaction(SIGTTIN, &savettin, NULL);
++ (void)sigaction(SIGTTOU, &savettou, NULL);
++ if (input != STDIN_FILENO)
++ (void)close(input);
++
++ /*
++ * If we were interrupted by a signal, resend it to ourselves
++ * now that we have restored the signal handlers.
++ */
++ if (signo) {
++ kill(getpid(), signo);
++ switch (signo) {
++ case SIGTSTP:
++ case SIGTTIN:
++ case SIGTTOU:
++ goto restart;
++ }
++ }
++
++ if (save_errno)
++ errno = save_errno;
++ return(nr == -1 ? NULL : buf);
++}
++
++char *
++getpass(const char *prompt)
++{
++ static char buf[_PASSWORD_LEN + 1];
++
++ return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
++}
++
++static void handler(int s)
++{
++
++ signo = s;
++}
diff --git a/main/newt/APKBUILD b/main/newt/APKBUILD
new file mode 100644
index 0000000000..6ecb58e583
--- /dev/null
+++ b/main/newt/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=newt
+pkgver=0.52.11
+pkgrel=2
+pkgdesc="Redhat's Newt windowing toolkit development files"
+url="https://fedorahosted.org/newt/"
+arch="all"
+license="LGPL-2"
+depends=
+makedepends="slang-dev popt-dev python-dev ncurses-dev wget"
+subpackages="$pkgname-dev $pkgname-doc py-newt:py"
+source="https://fedorahosted.org/releases/n/e/newt/newt-$pkgver.tar.gz
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ [ -r "$i" ] || continue
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
+ sed -i -e 's:-lslang:-lslang -lncurses:g' \
+ -e 's:instroot:DESTDIR:g' Makefile.in || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --without-gpm \
+ --without-tcl \
+ --disable-nls
+ make RPM_OPT_FLAGS="$CFLAGS" || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ # TODO: fix the make install target to not try install po files
+ make -j1 DESTDIR="$pkgdir" prefix="/usr" RPM_OPT_FLAGS="ERROR" install \
+ || true
+}
+
+py() {
+ pkgdesc="A NEWT module for Python"
+ mkdir -p "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/lib/python* "$subpkgdir"/usr/lib/
+}
+
+md5sums="4b9a0685ecd180c42d2c4a5806e3fc52 newt-0.52.11.tar.gz"
diff --git a/main/nfs-utils/APKBUILD b/main/nfs-utils/APKBUILD
new file mode 100644
index 0000000000..633625d410
--- /dev/null
+++ b/main/nfs-utils/APKBUILD
@@ -0,0 +1,92 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=nfs-utils
+pkgver=1.2.3
+pkgrel=0
+pkgdesc="kernel-mode NFS"
+url="http://nfs.sourceforge.net/"
+arch="all"
+license="GPL"
+depends="rpcbind"
+makedepends="util-linux-ng-dev libtirpc-dev libcap-dev"
+subpackages="$pkgname-doc rpcgen"
+source="http://downloads.sourceforge.net/nfs/$pkgname-$pkgver.tar.bz2
+ nfs.initd
+ nfsmount.initd
+ rpc.gssd.initd
+ rpc.idmapd.initd
+ rpc.pipefs.initd
+ rpc.statd.initd
+ rpc.svcgssd.initd
+
+ nfs.confd
+ nfs.exports
+ nfs-utils-no-exec.patch
+ nfs-utils-mtab-sym.patch"
+
+prepare() {
+ cd "$srcdir/$pkgname-$pkgver"
+ for i in "$srcdir"/*.patch; do
+ msg "Applying $i"
+ patch -p0 -i "${i}" || return 1
+ done
+ sed -i -e '/^#include <libio.h>/d' support/include/sockaddr.h
+ # busybox install fix
+ sed -i 's/--mode 755/-m755/g' \
+ tools/nfs-iostat/Makefile.am \
+ tools/nfs-iostat/Makefile.in \
+ tools/mountstats/Makefile.am \
+ tools/mountstats/Makefile.in
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --without-tcp-wrappers \
+ --disable-nfsv4 \
+ --enable-uuid \
+ --disable-gss \
+ --enable-mount \
+ --enable-nfsv3 \
+ --with-statedir=/var/lib/nfs
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+
+ for i in nfs rpc.gssd rpc.pipefs rpc.svcgssd nfsmount rpc.idmapd \
+ rpc.statd; do
+ install -m755 -D "$srcdir"/$i.initd "$pkgdir"/etc/init.d/$i \
+ || return 1
+ done
+
+
+ install -m644 -D "$srcdir"/nfs.confd "$pkgdir"/etc/conf.d/nfs
+ install -m644 -D "$srcdir"/nfs.exports "$pkgdir"/etc/exports
+}
+
+rpcgen() {
+ pkgdesc="Remote Procedure Call (RPC) protocol compiler"
+ cd "$srcdir/$pkgname-$pkgver"
+ install -m755 -D tools/rpcgen/rpcgen "$subpkgdir"/usr/bin/rpcgen
+}
+
+md5sums="1131dc5f27c4f3905a6e7ee0d594fd4d nfs-utils-1.2.3.tar.bz2
+f1873e0441b8c3b4b90023c038d755ec nfs.initd
+d514fb87ce5de9909f43d99012352f09 nfsmount.initd
+144b0e1f7d32265abe4c499a47af6154 rpc.gssd.initd
+650f68e51a02ba84c272960fc302c445 rpc.idmapd.initd
+80772890099fafdb8af3d6dd3db242c2 rpc.pipefs.initd
+37fdb069a5fcabea507012497bb95c53 rpc.statd.initd
+20e71ab412555b2dc9b50f346f68e5c8 rpc.svcgssd.initd
+09135438d6df50b868bbe5a2260f973c nfs.confd
+4f1bb7b2412ce5952ecb5ec22d8ed99d nfs.exports
+5e0963b0889e779ff36af0299d17d6cb nfs-utils-no-exec.patch
+a3a7338f8de3ac37c1ffc05bdcb77d16 nfs-utils-mtab-sym.patch"
diff --git a/main/nfs-utils/nfs-utils-mtab-sym.patch b/main/nfs-utils/nfs-utils-mtab-sym.patch
new file mode 100644
index 0000000000..1ebbd99b57
--- /dev/null
+++ b/main/nfs-utils/nfs-utils-mtab-sym.patch
@@ -0,0 +1,38 @@
+--- utils/mount/fstab.c
++++ utils/mount/fstab.c
+@@ -57,7 +57,7 @@ mtab_does_not_exist(void) {
+ return var_mtab_does_not_exist;
+ }
+
+-static int
++int
+ mtab_is_a_symlink(void) {
+ get_mtab_info();
+ return var_mtab_is_a_symlink;
+--- utils/mount/fstab.h
++++ utils/mount/fstab.h
+@@ -7,6 +7,7 @@
+ #define _PATH_FSTAB "/etc/fstab"
+ #endif
+
++int mtab_is_a_symlink(void);
+ int mtab_is_writable(void);
+ int mtab_does_not_exist(void);
+ void reset_mtab_info(void);
+--- utils/mount/mount.c
++++ utils/mount/mount.c
+@@ -230,6 +230,13 @@ create_mtab (void) {
+ int flags;
+ mntFILE *mfp;
+
++ /* Avoid writing if the mtab is a symlink to /proc/mounts, since
++ that would create a file /proc/mounts in case the proc filesystem
++ is not mounted, and the fchmod below would also fail. */
++ if (mtab_is_a_symlink()) {
++ return EX_SUCCESS;
++ }
++
+ lock_mtab();
+
+ mfp = nfs_setmntent (MOUNTED, "a+");
+
diff --git a/main/nfs-utils/nfs-utils-no-exec.patch b/main/nfs-utils/nfs-utils-no-exec.patch
new file mode 100644
index 0000000000..94a73d366f
--- /dev/null
+++ b/main/nfs-utils/nfs-utils-no-exec.patch
@@ -0,0 +1,13 @@
+--- utils/mount/mount.c Wed Apr 8 09:25:26 2009
++++ utils/mount/mount.c Wed Apr 8 09:25:26 2009
+@@ -407,10 +407,6 @@
+ mount_error(NULL, mount_point, ENOTDIR);
+ return 1;
+ }
+- if (access(mount_point, X_OK) < 0) {
+- mount_error(NULL, mount_point, errno);
+- return 1;
+- }
+
+ return 0;
+ }
diff --git a/main/nfs-utils/nfs.confd b/main/nfs-utils/nfs.confd
new file mode 100644
index 0000000000..98a143a654
--- /dev/null
+++ b/main/nfs-utils/nfs.confd
@@ -0,0 +1,30 @@
+# /etc/conf.d/nfs
+
+# If you wish to set the port numbers for lockd,
+# please see /etc/sysctl.conf
+
+# Number of servers to be started up by default
+OPTS_RPC_NFSD="8"
+
+# Options to pass to rpc.mountd
+# ex. OPTS_RPC_MOUNTD="-p 32767"
+OPTS_RPC_MOUNTD=""
+
+# Options to pass to rpc.statd
+# ex. OPTS_RPC_STATD="-p 32765 -o 32766"
+OPTS_RPC_STATD=""
+
+# Options to pass to rpc.idmapd
+OPTS_RPC_IDMAPD=""
+
+# Options to pass to rpc.gssd
+OPTS_RPC_GSSD=""
+
+# Options to pass to rpc.svcgssd
+OPTS_RPC_SVCGSSD=""
+
+# Options to pass to rpc.rquotad (requires sys-fs/quota)
+OPTS_RPC_RQUOTAD=""
+
+# Timeout (in seconds) for exportfs
+EXPORTFS_TIMEOUT=30
diff --git a/main/nfs-utils/nfs.exports b/main/nfs-utils/nfs.exports
new file mode 100644
index 0000000000..dc0b839271
--- /dev/null
+++ b/main/nfs-utils/nfs.exports
@@ -0,0 +1,7 @@
+# /etc/exports
+#
+# See exports(5) for a description.
+
+# use exportfs -arv to reread
+#/export 192.168.1.10(rw,no_root_squash)
+
diff --git a/main/nfs-utils/nfs.initd b/main/nfs-utils/nfs.initd
new file mode 100644
index 0000000000..6f6ba98ceb
--- /dev/null
+++ b/main/nfs-utils/nfs.initd
@@ -0,0 +1,154 @@
+#!/sbin/runscript
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-fs/nfs-utils/files/nfs.initd,v 1.19 2009/05/30 22:01:43 vapier Exp $
+
+opts="reload"
+
+# This variable is used for controlling whether or not to run exportfs -ua;
+# see stop() for more information
+restarting=no
+
+# The binary locations
+exportfs=/usr/sbin/exportfs
+ mountd=/usr/sbin/rpc.mountd
+ nfsd=/usr/sbin/rpc.nfsd
+smnotify=/usr/sbin/sm-notify
+
+depend() {
+ local myneed=""
+ if [ -e /etc/exports ] ; then
+ if awk '!/^[[:space:]]*#/ && $2 ~ /sec=/ { exit 0 } END { exit 1 }' /etc/exports ; then
+ myneed="${myneed} rpc.svcgssd"
+ fi
+ fi
+ config /etc/exports
+ need portmap rpc.statd ${myneed} ${NFS_NEEDED_SERVICES}
+ use ypbind net dns rpc.rquotad rpc.idmapd rpc.svcgssd
+ after quota
+}
+
+mkdir_nfsdirs() {
+ local d
+ for d in rpc_pipefs v4recovery v4root ; do
+ d="/var/lib/nfs/${d}"
+ [ ! -d "${d}" ] && mkdir -p "${d}"
+ done
+}
+
+waitfor_exportfs() {
+ local pid=$1
+ ( sleep ${EXPORTFS_TIMEOUT:-30}; kill -9 $pid 2>/dev/null ) &
+ wait $1
+}
+
+mount_nfsd() {
+ if [ -e /proc/modules ] ; then
+ # Make sure nfs support is loaded in the kernel #64709
+ if ! grep -qs nfsd /proc/filesystems ; then
+ modprobe -q nfsd
+ fi
+ # Restart idmapd if needed #220747
+ if grep -qs nfsd /proc/modules ; then
+ killall -q -HUP rpc.idmapd
+ fi
+ fi
+
+ # This is the new "kernel 2.6 way" to handle the exports file
+ if grep -qs nfsd /proc/filesystems ; then
+ if ! grep -qs "nfsd /proc/fs/nfsd" /proc/mounts ; then
+ ebegin "Mounting nfsd filesystem in /proc"
+ mount -t nfsd -o nodev,noexec,nosuid nfsd /proc/fs/nfsd
+ eend $?
+ fi
+ fi
+}
+
+start_it() {
+ ebegin "Starting NFS $1"
+ shift
+ "$@"
+ eend $?
+ ret=$((ret + $?))
+}
+start() {
+ mount_nfsd
+ mkdir_nfsdirs
+
+ # Exportfs likes to hang if networking isn't working.
+ # If that's the case, then try to kill it so the
+ # bootup process can continue.
+ if grep -qs '^[[:space:]]*/' /etc/exports ; then
+ ebegin "Exporting NFS directories"
+ ${exportfs} -r &
+ waitfor_exportfs $!
+ eend $?
+ fi
+
+ local ret=0
+ start_it mountd ${mountd} ${OPTS_RPC_MOUNTD}
+ start_it daemon ${nfsd} ${OPTS_RPC_NFSD}
+ [ -x "${smnotify}" ] && start_it smnotify ${smnotify} ${OPTS_SMNOTIFY}
+ return ${ret}
+}
+
+stop() {
+ local ret=0
+
+ # Don't check NFSSERVER variable since it might have changed,
+ # instead use --oknodo to smooth things over
+ ebegin "Stopping NFS mountd"
+ start-stop-daemon --stop --oknodo --exec ${mountd}
+ eend $?
+ ret=$((ret + $?))
+
+ # nfsd sets its process name to [nfsd] so don't look for $nfsd
+ ebegin "Stopping NFS daemon"
+ start-stop-daemon --stop --oknodo --name nfsd --user root --signal 2
+ eend $?
+ ret=$((ret + $?))
+ # in case things don't work out ... #228127
+ rpc.nfsd 0
+
+ # When restarting the NFS server, running "exportfs -ua" probably
+ # isn't what the user wants. Running it causes all entries listed
+ # in xtab to be removed from the kernel export tables, and the
+ # xtab file is cleared. This effectively shuts down all NFS
+ # activity, leaving all clients holding stale NFS filehandles,
+ # *even* when the NFS server has restarted.
+ #
+ # That's what you would want if you were shutting down the NFS
+ # server for good, or for a long period of time, but not when the
+ # NFS server will be running again in short order. In this case,
+ # then "exportfs -r" will reread the xtab, and all the current
+ # clients will be able to resume NFS activity, *without* needing
+ # to umount/(re)mount the filesystem.
+ if [ "${restarting}" = no -o "${RC_CMD}" = "restart" ] ; then
+ ebegin "Unexporting NFS directories"
+ # Exportfs likes to hang if networking isn't working.
+ # If that's the case, then try to kill it so the
+ # shutdown process can continue.
+ ${exportfs} -ua &
+ waitfor_exportfs $!
+ eend $?
+ fi
+
+ return ${ret}
+}
+
+reload() {
+ # Exportfs likes to hang if networking isn't working.
+ # If that's the case, then try to kill it so the
+ # bootup process can continue.
+ ebegin "Reloading /etc/exports"
+ ${exportfs} -r 1>&2 &
+ waitfor_exportfs $!
+ eend $?
+}
+
+restart() {
+ # See long comment in stop() regarding "restarting" and exportfs -ua
+ restarting=yes
+ svc_stop
+ svc_start
+}
diff --git a/main/nfs-utils/nfsmount.initd b/main/nfs-utils/nfsmount.initd
new file mode 100644
index 0000000000..9ae2c520d2
--- /dev/null
+++ b/main/nfs-utils/nfsmount.initd
@@ -0,0 +1,42 @@
+#!/sbin/runscript
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-fs/nfs-utils/files/nfsmount.initd,v 1.13 2009/01/31 22:15:02 vapier Exp $
+
+[ -e /etc/conf.d/nfs ] && . /etc/conf.d/nfs
+
+depend() {
+ local myneed=""
+ if [ -e /etc/fstab ] ; then
+ awk '!/^[[:space:]]*#/ && $3 == "nfs4" { exit ($4 ~ /sec=krb/ ? 10 : 20) }' /etc/fstab
+ local ret=$?
+ [ ${ret} -eq 10 ] && myneed="${myneed} rpc.gssd"
+ [ ${ret} -eq 20 ] && myneed="${myneed} rpc.idmapd"
+ fi
+ config /etc/fstab
+ need net portmap rpc.statd ${myneed}
+ use ypbind dns rpc.idmapd rpc.gssd
+}
+
+start() {
+ if [ -x /usr/sbin/sm-notify ] ; then
+ ebegin "Starting NFS sm-notify"
+ /usr/sbin/sm-notify ${OPTS_SMNOTIFY}
+ eend $?
+ fi
+
+ # Make sure nfs support is loaded in the kernel #64709
+ if [ -e /proc/modules ] && ! grep -qs 'nfs$' /proc/filesystems ; then
+ modprobe -q nfs
+ fi
+
+ ebegin "Mounting NFS filesystems"
+ mount -a -t nfs,nfs4
+ eend $?
+}
+
+stop() {
+ ebegin "Unmounting NFS filesystems"
+ umount -a -t nfs,nfs4
+ eend $?
+}
diff --git a/main/nfs-utils/rpc.gssd.initd b/main/nfs-utils/rpc.gssd.initd
new file mode 100644
index 0000000000..f1b8f87745
--- /dev/null
+++ b/main/nfs-utils/rpc.gssd.initd
@@ -0,0 +1,24 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-fs/nfs-utils/files/rpc.gssd.initd,v 1.11 2008/10/26 09:02:47 vapier Exp $
+
+[ -e /etc/conf.d/nfs ] && . /etc/conf.d/nfs
+
+depend() {
+ use ypbind net
+ need portmap rpc.pipefs
+ after quota
+}
+
+start() {
+ ebegin "Starting gssd"
+ start-stop-daemon --start --exec /usr/sbin/rpc.gssd -- ${OPTS_RPC_GSSD}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping gssd"
+ start-stop-daemon --stop --exec /usr/sbin/rpc.gssd
+ eend $?
+}
diff --git a/main/nfs-utils/rpc.idmapd.initd b/main/nfs-utils/rpc.idmapd.initd
new file mode 100644
index 0000000000..52838b5da7
--- /dev/null
+++ b/main/nfs-utils/rpc.idmapd.initd
@@ -0,0 +1,26 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-fs/nfs-utils/files/rpc.idmapd.initd,v 1.8 2009/03/14 18:43:18 vapier Exp $
+
+[ -e /etc/conf.d/nfs ] && . /etc/conf.d/nfs
+
+rpc_bin=/usr/sbin/rpc.idmapd
+
+depend() {
+ use ypbind net
+ need portmap rpc.pipefs
+ after quota
+}
+
+start() {
+ ebegin "Starting idmapd"
+ ${rpc_bin} ${OPTS_RPC_IDMAPD}
+ eend $? "make sure DNOTIFY support is enabled ..."
+}
+
+stop() {
+ ebegin "Stopping idmapd"
+ start-stop-daemon --stop --exec ${rpc_bin}
+ eend $?
+}
diff --git a/main/nfs-utils/rpc.pipefs.initd b/main/nfs-utils/rpc.pipefs.initd
new file mode 100644
index 0000000000..701ac77892
--- /dev/null
+++ b/main/nfs-utils/rpc.pipefs.initd
@@ -0,0 +1,24 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-fs/nfs-utils/files/rpc.pipefs.initd,v 1.1 2008/10/26 09:02:47 vapier Exp $
+
+mount_pipefs() {
+ # if rpc_pipefs is not available, try to load sunrpc for it #219566
+ grep -qs rpc_pipefs /proc/filesystems || modprobe -q sunrpc
+ # if still not available, let's bail
+ grep -qs rpc_pipefs /proc/filesystems || return 1
+
+ # now just do it for kicks
+ mkdir -p /var/lib/nfs/rpc_pipefs
+ mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs
+}
+
+start() {
+ # if things are already mounted, let's just return
+ grep -qs "rpc_pipefs /var/lib/nfs/rpc_pipefs" /proc/mounts && return 0
+
+ ebegin "Mounting RPC pipefs"
+ mount_pipefs
+ eend $?
+}
diff --git a/main/nfs-utils/rpc.statd.initd b/main/nfs-utils/rpc.statd.initd
new file mode 100644
index 0000000000..b19e5a3881
--- /dev/null
+++ b/main/nfs-utils/rpc.statd.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-fs/nfs-utils/files/rpc.statd.initd,v 1.7 2009/01/31 22:16:11 vapier Exp $
+
+[ -e /etc/conf.d/nfs ] && . /etc/conf.d/nfs
+
+rpc_bin=/usr/sbin/rpc.statd
+rpc_pid=/var/run/rpc.statd.pid
+
+depend() {
+ use ypbind net
+ need portmap
+ after quota
+}
+
+start() {
+ # Don't start rpc.statd if already started by someone else ...
+ # Don't try and kill it if it's already dead ...
+ if killall -q -0 ${rpc_bin} ; then
+ return 0
+ fi
+
+ ebegin "Starting NFS statd"
+ start-stop-daemon --start --exec ${rpc_bin} -- --no-notify ${OPTS_RPC_STATD}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping NFS statd"
+ start-stop-daemon --stop --exec ${rpc_bin} --pidfile /var/run/rpc.statd.pid
+ eend $?
+}
diff --git a/main/nfs-utils/rpc.svcgssd.initd b/main/nfs-utils/rpc.svcgssd.initd
new file mode 100644
index 0000000000..74383e24db
--- /dev/null
+++ b/main/nfs-utils/rpc.svcgssd.initd
@@ -0,0 +1,24 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-fs/nfs-utils/files/rpc.svcgssd.initd,v 1.5 2008/10/26 09:02:47 vapier Exp $
+
+[ -e /etc/conf.d/nfs ] && . /etc/conf.d/nfs
+
+depend() {
+ use ypbind net
+ need portmap rpc.pipefs
+ after quota
+}
+
+start() {
+ ebegin "Starting svcgssd"
+ start-stop-daemon --start --exec /usr/sbin/rpc.svcgssd -- ${OPTS_RPC_SVCGSSD}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping svcgssd"
+ start-stop-daemon --stop --exec /usr/sbin/rpc.svcgssd
+ eend $?
+}
diff --git a/main/nginx/APKBUILD b/main/nginx/APKBUILD
new file mode 100644
index 0000000000..d6727fb4e8
--- /dev/null
+++ b/main/nginx/APKBUILD
@@ -0,0 +1,61 @@
+# Contributor: Jeff Bilyk <jbilyk@gmail.com>
+# Maintainer: Cameron Banta <cbanta@gmail.com>
+pkgname=nginx
+pkgver=1.0.4
+pkgrel=0
+pkgdesc="nginx [engine x] is a HTTP and reverse proxy server"
+url="http://www.nginx.org"
+arch="all"
+license="Custom"
+depends=
+makedepends="pcre-dev openssl-dev zlib-dev"
+#install="$pkgname.pre-install $pkgname.post-install"
+install=
+subpackages=
+source="http://nginx.org/download/$pkgname-$pkgver.tar.gz
+ nginx.initd
+ nginx.logrotate
+ $install
+ "
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --conf-path=/etc/$pkgname/$pkgname.conf \
+ --pid-path=/var/run/$pkgname.pid \
+ --lock-path=/var/run/$pkgname.lock \
+ --error-log-path=/var/log/$pkgname/error.log \
+ --http-log-path=/var/log/$pkgname/access.log \
+ --with-http_ssl_module \
+ --with-http_gzip_static_module \
+ --http-client-body-temp-path=/tmp/$pkgname/client-body \
+ --http-proxy-temp-path=/tmp/$pkgname/proxy \
+ --http-fastcgi-temp-path=/tmp/$pkgname/fastcgi \
+ --with-mail \
+ --with-mail_ssl_module \
+ --with-ipv6 \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.logrotate "$pkgdir"/etc/logrotate.d/$pkgname
+
+ install -m644 -D LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="d23f6e6b07b57ac061e790b1ed64bb98 nginx-1.0.4.tar.gz
+b06f6e23753385be0076539ba1806cb6 nginx.initd
+8823274a834332d3db4f62bf7dd1fb7d nginx.logrotate"
diff --git a/main/nginx/nginx.initd b/main/nginx/nginx.initd
new file mode 100644
index 0000000000..e175bb413b
--- /dev/null
+++ b/main/nginx/nginx.initd
@@ -0,0 +1,72 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/www-servers/nginx/files/nginx.init-r2,v 1.1 2010/01/03 19:51:41 djc Exp $
+
+opts="${opts} upgrade reload configtest"
+
+depend() {
+ need net
+ use dns logger netmount
+}
+
+start() {
+ configtest || return 1
+ ebegin "Starting nginx"
+ start-stop-daemon --start --pidfile /var/run/nginx.pid \
+ --exec /usr/sbin/nginx -- -c /etc/nginx/nginx.conf
+ eend $? "Failed to start nginx"
+}
+
+stop() {
+ configtest || return 1
+ ebegin "Stopping nginx"
+ start-stop-daemon --stop --pidfile /var/run/nginx.pid
+ eend $? "Failed to stop nginx"
+ rm -f /var/run/nginx.pid
+}
+
+reload() {
+ configtest || return 1
+ ebegin "Refreshing nginx' configuration"
+ kill -HUP `cat /var/run/nginx.pid` &>/dev/null
+ eend $? "Failed to reload nginx"
+}
+
+upgrade() {
+ configtest || return 1
+ ebegin "Upgrading nginx"
+
+ einfo "Sending USR2 to old binary"
+ kill -USR2 `cat /var/run/nginx.pid` &>/dev/null
+
+ einfo "Sleeping 3 seconds before pid-files checking"
+ sleep 3
+
+ if [ ! -f /var/run/nginx.pid.oldbin ]; then
+ eerror "File with old pid not found"
+ return 1
+ fi
+
+ if [ ! -f /var/run/nginx.pid ]; then
+ eerror "New binary failed to start"
+ return 1
+ fi
+
+ einfo "Sleeping 3 seconds before WINCH"
+ sleep 3 ; kill -WINCH `cat /var/run/nginx.pid.oldbin`
+
+ einfo "Sending QUIT to old binary"
+ kill -QUIT `cat /var/run/nginx.pid.oldbin`
+
+ einfo "Upgrade completed"
+
+ eend $? "Upgrade failed"
+}
+
+configtest() {
+ ebegin "Checking nginx' configuration"
+ mkdir -p /tmp/nginx
+ /usr/sbin/nginx -c /etc/nginx/nginx.conf -t
+ eend $? "failed, please correct errors above"
+}
diff --git a/main/nginx/nginx.logrotate b/main/nginx/nginx.logrotate
new file mode 100644
index 0000000000..7778b1108b
--- /dev/null
+++ b/main/nginx/nginx.logrotate
@@ -0,0 +1,12 @@
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/www-servers/nginx/files/nginx.logrotate,v 1.1 2010/01/03 20:29:40 djc Exp $
+
+/var/log/nginx/*.log {
+ missingok
+ sharedscripts
+ postrotate
+ kill -USR1 `cat /var/run/nginx.pid`
+ endscript
+}
+
diff --git a/main/ngircd/APKBUILD b/main/ngircd/APKBUILD
new file mode 100644
index 0000000000..099aba8174
--- /dev/null
+++ b/main/ngircd/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ngircd
+pkgver=17.1
+pkgrel=0
+pkgdesc="Next Generation IRC Daemon"
+url="http://ngircd.barton.de/"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev zlib-dev"
+install="$pkgname.pre-install"
+source="ftp://ftp.berlios.de/pub/$pkgname/$pkgname-$pkgver.tar.gz
+ $pkgname.initd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ sed -i \
+ -e "s:/usr/local/etc/ngircd.motd:/etc/ngircd/ngircd.motd:" \
+ -e "s:;ServerUID = 65534:ServerUID = ngircd:" \
+ -e "s:;ServerGID = 65534:ServerGID = nogroup:" \
+ doc/sample-ngircd.conf
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/ngircd \
+ --mandir=/usr/share/man \
+ --without-ident \
+ --with-openssl
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm755 ../$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+
+md5sums="b4ad0b1f18875ff3f2e92f076e64496b ngircd-17.1.tar.gz
+50d8388540a2e3eb0630e8ac6369f394 ngircd.initd"
diff --git a/main/ngircd/ngircd.initd b/main/ngircd/ngircd.initd
new file mode 100644
index 0000000000..2c87b16696
--- /dev/null
+++ b/main/ngircd/ngircd.initd
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-irc/ngircd/files/ngircd.init.d,v 1.3 2006/01/02 15:31:27 swegener Exp $
+
+depend() {
+ need net
+ after firewall
+ provide ircd
+}
+
+start() {
+ ebegin "Starting ngIRCd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ngircd
+ eend $? "Failed to start ngIRCd"
+}
+
+stop() {
+ ebegin "Stopping ngIRCd"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/ngircd
+ eend $? "Failed to stop ngIRCd"
+}
diff --git a/main/ngircd/ngircd.pre-install b/main/ngircd/ngircd.pre-install
new file mode 100644
index 0000000000..062e37ae4f
--- /dev/null
+++ b/main/ngircd/ngircd.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -H -h /etc/ngircd -s /bin/false -D ngircd 2>/dev/null
+exit 0
diff --git a/main/nload/APKBUILD b/main/nload/APKBUILD
new file mode 100644
index 0000000000..08642cb6db
--- /dev/null
+++ b/main/nload/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Jeff Bilyk <jbilyk at gmail.com>
+# Maintainer:
+pkgname=nload
+pkgver=0.7.2
+pkgrel=1
+pkgdesc="Console network traffic and bandwidth monitor"
+url="http://www.roland-riegel.de/nload"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="5b851ecf898edcd1f465946745e95eb6 nload-0.7.2.tar.gz"
diff --git a/main/nmap/APKBUILD b/main/nmap/APKBUILD
new file mode 100644
index 0000000000..7b68d1726b
--- /dev/null
+++ b/main/nmap/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=nmap
+pkgver=5.51
+pkgrel=0
+pkgdesc="A network exploration tool and security/port scanner"
+url="http:/nmap.org"
+arch="all"
+license="custom:GPL"
+depends=
+makedepends="libpcap-dev openssl-dev lua-dev"
+install=
+subpackages="$pkgname-doc"
+replaces="nmap-nse"
+source="http://nmap.org/dist/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --without-zenmap \
+ --with-liblua=/usr/include \
+ --with-openssl=/usr/lib
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ # install custom GPL2 license
+ install -D -m644 COPYING ${pkgdir}/usr/share/licenses/${pkgname}/LICENSE
+}
+
+md5sums="aa9ecd85e9908cac6387158920aaf1d2 nmap-5.51.tgz"
diff --git a/main/nmap/nmap-4.53-uclibc++-output.cc.patch b/main/nmap/nmap-4.53-uclibc++-output.cc.patch
new file mode 100644
index 0000000000..3253fc26b3
--- /dev/null
+++ b/main/nmap/nmap-4.53-uclibc++-output.cc.patch
@@ -0,0 +1,11 @@
+--- nmap/output.cc.orig 2007-12-15 09:54:07.000000000 -0800
++++ nmap/output.cc 2007-12-15 09:54:19.000000000 -0800
+@@ -1904,7 +1904,7 @@
+
+ /* Compares this record to another. First compare the directory names, then
+ compare the file names. */
+- bool operator<(const struct data_file_record& other) {
++ bool operator<(const struct data_file_record& other) const {
+ int cmp;
+
+ cmp = dir.compare(other.dir);
diff --git a/main/nrpe/APKBUILD b/main/nrpe/APKBUILD
new file mode 100644
index 0000000000..3e7ba13eb2
--- /dev/null
+++ b/main/nrpe/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Jeff Bilyk <jbilyk@gmail.com>
+pkgname=nrpe
+pkgver=2.12
+pkgrel=8
+pkgusers="nagios"
+pkggroups="nagios"
+pkgdesc="NRPE allows you to remotely execute Nagios plugins on other Linux/Unix machines."
+url="http://www.nagios.org/download/addons"
+arch="all"
+license="GPL"
+depends=""
+makedepends="openssl-dev perl"
+install="nrpe.pre-install"
+subpackages="$pkgname-plugin"
+source="http://downloads.sourceforge.net/nagios/$pkgname-$pkgver.tar.gz
+ nrpe.initd
+ nrpe.confd"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --libexecdir=/usr/lib/nagios/plugins \
+ --enable-command-args
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install install-daemon-config
+ #remove plugin since its in separate package
+ rm -rf "$pkgdir"/usr/lib
+ install -Dm755 "$srcdir"/nrpe.initd "$pkgdir"/etc/init.d/nrpe
+ install -Dm644 "$srcdir"/nrpe.confd "$pkgdir"/etc/conf.d/nrpe
+}
+
+plugin() {
+ pkgdesc="Nagios plugin to check result via NRPE daemon"
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$subpkgdir" install-plugin
+}
+
+md5sums="b2d75e2962f1e3151ef58794d60c9e97 nrpe-2.12.tar.gz
+3263044303bbfdfbbc8127cfa991ab51 nrpe.initd
+6bd25a1ace9e108c5014a83adcad15b3 nrpe.confd"
diff --git a/main/nrpe/nrpe.confd b/main/nrpe/nrpe.confd
new file mode 100644
index 0000000000..18cd229511
--- /dev/null
+++ b/main/nrpe/nrpe.confd
@@ -0,0 +1,2 @@
+# override the default options.
+# nrpe_options="-c /etc/nrpe.cfg"
diff --git a/main/nrpe/nrpe.initd b/main/nrpe/nrpe.initd
new file mode 100644
index 0000000000..92fe3837ee
--- /dev/null
+++ b/main/nrpe/nrpe.initd
@@ -0,0 +1,37 @@
+#!/sbin/runscript
+
+# Sample init.d file for alpine linux.
+
+daemon=/usr/bin/nrpe
+conf=/etc/nrpe.cfg
+
+depend() {
+ need net
+ after firewall
+}
+
+get_pidfile() {
+ if [ -r $conf ]; then
+ pidfile=$(awk -F= '/^pid_file/ {print $2}' $conf)
+ fi
+ pidfile=${pidfile:-/var/run/nrpe.pid}
+}
+
+start() {
+ get_pidfile
+ ebegin "Starting NRPE"
+ start-stop-daemon --start --quiet \
+ --pidfile $pidfile \
+ --exec $daemon -- -d ${nrpe_options:- -c $conf}
+ eend $?
+}
+
+stop() {
+ get_pidfile
+ ebegin "Stopping NRPE"
+ start-stop-daemon --stop --quiet \
+ --exec $daemon \
+ --pidfile $pidfile
+ eend $?
+}
+
diff --git a/main/nrpe/nrpe.pre-install b/main/nrpe/nrpe.pre-install
new file mode 100644
index 0000000000..5b7b5f68bd
--- /dev/null
+++ b/main/nrpe/nrpe.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -H -h /dev/null -s /bin/false -D nagios 2>/dev/null
+addgroup nagios 2>/dev/null
+exit 0
diff --git a/main/nsd/0010-stop-unlink-pid-error.patch b/main/nsd/0010-stop-unlink-pid-error.patch
new file mode 100644
index 0000000000..24175df337
--- /dev/null
+++ b/main/nsd/0010-stop-unlink-pid-error.patch
@@ -0,0 +1,26 @@
+This patch prevents nsd from attempting to unlink the pidfile on nsd
+shutdown. The reason for this is because we get a permission denied
+error in nsd.log when it attempts to do so.
+
+I think this is needed because of how normal OpenRC init scripts are
+designed and handled.
+
+See the included /etc/init.d/nsd (nsd.initd) for my conversion of the
+nsdc script that's normally distributed with nsd. The included nsdc
+script is a wrapper for the converted OpenRC init script, designed to
+maintain compatibility.
+
+Matt Smith <msmith@alpinelinux.org>
+
+
+--- a/server.c
++++ b/server.c
+@@ -1167,7 +1167,7 @@
+ close(fd);
+
+ /* Unlink it if possible... */
+- unlinkpid(nsd->pidfile);
++ //unlinkpid(nsd->pidfile);
+
+ if(reload_listener.fd > 0) {
+ sig_atomic_t cmd = NSD_QUIT;
diff --git a/main/nsd/APKBUILD b/main/nsd/APKBUILD
new file mode 100644
index 0000000000..a110b94a8f
--- /dev/null
+++ b/main/nsd/APKBUILD
@@ -0,0 +1,76 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=nsd
+pkgver=3.2.8
+pkgrel=0
+pkgdesc="NSD is an authoritative only, high performance, simple and open source name server."
+url="http://www.nlnetlabs.nl/projects/nsd/"
+arch="all"
+license="BSD"
+depends=
+depends_dev=
+makedepends="$depends_dev openssl-dev"
+install="$pkgname.pre-install $pkgname.post-deinstall"
+subpackages="$pkgname-doc"
+pkgusers="nsd"
+pkggroups="nsd"
+source="http://www.nlnetlabs.nl/downloads/$pkgname/$pkgname-$pkgver.tar.gz
+ 0010-stop-unlink-pid-error.patch
+ nsdc
+ nsd.initd
+ nsd.confd
+ "
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+
+ ./configure \
+ --sbindir=/usr/sbin \
+ --mandir=/usr/share/man \
+ --with-user=nsd \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+
+ install -m755 -D "$srcdir"/nsdc \
+ "$pkgdir"/usr/sbin/nsdc || return 1
+ install -m755 -D "$srcdir"/$pkgname.initd \
+ "$pkgdir"/etc/init.d/nsd || return 1
+ install -m644 -D "$srcdir"/$pkgname.confd \
+ "$pkgdir"/etc/conf.d/nsd || return 1
+
+ chown nsd "$pkgdir"/var/db/nsd || return 1
+}
+
+doc() {
+ arch="noarch"
+
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname || return 1
+ cp -a "$_builddir"/doc/* \
+ "$subpkgdir"/usr/share/doc/$pkgname/ || return 1
+ cp -a "$_builddir"/contrib/ \
+ "$subpkgdir"/usr/share/doc/$pkgname/ || return 1
+ mv "$pkgdir"/usr/share/man \
+ "$subpkgdir"/usr/share/man || return 1
+}
+
+md5sums="963c2123853e7759ffb772da40c68838 nsd-3.2.8.tar.gz
+cc592572846b978a6f52130a8e518ab3 0010-stop-unlink-pid-error.patch
+3aa94004a39319db89a329e9f24fb9da nsdc
+4c0eef07caac9083aeeb9b15602d014d nsd.initd
+37bd648259fdd919c79aaa0168b4423c nsd.confd"
diff --git a/main/nsd/nsd.confd b/main/nsd/nsd.confd
new file mode 100644
index 0000000000..e37f716baf
--- /dev/null
+++ b/main/nsd/nsd.confd
@@ -0,0 +1,15 @@
+#
+# Specify nsd options here.
+#
+
+# configuration file default
+configfile="/etc/nsd/nsd.conf"
+
+# The directory where NSD binaries reside
+sbindir="/usr/sbin"
+
+# how verbose is zonec run. Specify Nothing (empty string), -v or -vv.
+ZONEC_VERBOSE=-v
+
+# how patch is done. Specify 1 (with use of textfiles, default) or 0 (without)
+PATCH_STYLE=1
diff --git a/main/nsd/nsd.initd b/main/nsd/nsd.initd
new file mode 100644
index 0000000000..f400080494
--- /dev/null
+++ b/main/nsd/nsd.initd
@@ -0,0 +1,420 @@
+#!/sbin/runscript
+#
+# nsdc.sh -- a shell script to manage the beast
+#
+# Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
+#
+# See LICENSE for the license.
+#
+# OpenRC conversion by Matt Smith <msmith@alpinelinux.org>
+#
+#
+
+name=nsd
+daemon=/usr/sbin/${name}
+initd=/etc/init.d/${name}
+
+description="NSD, authoritative only high performance name server."
+
+extra_commands="stats reload running patch rebuild update notify do_start do_stop"
+description_reload="Reloads the nsd database file."
+description_running="Prints message and exits nonzero if server is not running."
+description_patch="Merge zone transfer changes back to zone files."
+description_rebuild="Compile database file from zone files."
+description_update="Try to update all slave zones hosted on this server."
+description_notify="Send notify messages to all secondary servers."
+description_do_start="Internal command; use 'start' instead."
+description_do_stop="Internal command; use 'stop' instead."
+
+depend() {
+ need net
+ after firewall
+}
+
+#
+# You sure heard this many times before: NO USER SERVICEABLE PARTS BELOW
+#
+
+# see if user selects a different config file, with -c <filename>
+if test "x$1" = "x-c"; then
+ shift
+ if [ -e $1 ]; then
+ configfile=$1
+ shift
+ else
+ echo "`basename $0`: Config file "$1" does not exist."
+ exit 1
+ fi
+fi
+
+# locate nsd-checkconf : in sbindir, PATH, nsdc_dir or .
+nsd_checkconf=""
+if [ -e ${sbindir}/nsd-checkconf ]; then
+ nsd_checkconf=${sbindir}/nsd-checkconf
+else
+ if which nsd-checkconf >/dev/null 2>&1 ; then
+ if which nsd-checkconf 2>&1 | grep "^[Nn]o " >/dev/null; then
+ nsd_checkconf=""
+ else
+ nsd_checkconf=`which nsd-checkconf`
+ fi
+ fi
+ if [ -z "${nsd_checkconf}" -a -e `dirname $0`/nsd-checkconf ]; then
+ nsd_checkconf=`dirname $0`/nsd-checkconf
+ fi
+ if [ -z "${nsd_checkconf}" -a -e ./nsd-checkconf ]; then
+ nsd_checkconf=./nsd-checkconf
+ fi
+ if [ -z "${nsd_checkconf}" ]; then
+ echo "`basename $0`: Could not find nsd programs" \
+ "in $sbindir, in PATH=$PATH, in cwd=`pwd`," \
+ "or in dir of nsdc=`dirname $0`"
+ exit 1
+ fi
+fi
+
+# check the config syntax before using it
+${nsd_checkconf} ${configfile}
+if test $? -ne 0 ; then
+ ${initd} describe
+ exit 1
+fi
+
+# Read some settings from the config file.
+dbfile=`${nsd_checkconf} -o database ${configfile}`
+pidfile=`${nsd_checkconf} -o pidfile ${configfile}`
+difffile=`${nsd_checkconf} -o difffile ${configfile}`
+zonesdir=`${nsd_checkconf} -o zonesdir ${configfile}`
+lockfile="${dbfile}.lock" # still needed
+sbindir=`dirname ${nsd_checkconf}`
+
+# move to zonesdir (if specified), and make absolute pathnames.
+if test -n "${zonesdir}"; then
+ zonesdir=`dirname ${zonesdir}/.`
+ if echo "${zonesdir}" | grep "^[^/]" >/dev/null; then
+ zonesdir=`pwd`/${zonesdir}
+ fi
+ if echo "${dbfile}" | grep "^[^/]" >/dev/null; then
+ dbfile=${zonesdir}/${dbfile}
+ fi
+ if echo "${pidfile}" | grep "^[^/]" >/dev/null; then
+ pidfile=${zonesdir}/${pidfile}
+ fi
+ if echo "${lockfile}" | grep "^[^/]" >/dev/null; then
+ lockfile=${zonesdir}/${lockfile}
+ fi
+ if echo "${difffile}" | grep "^[^/]" >/dev/null; then
+ difffile=${zonesdir}/${difffile}
+ fi
+fi
+
+# for bash: -C or noclobber. For tcsh: noclobber. For bourne: -C.
+noclobber_set="set -C"
+# ugly check for tcsh
+if echo /bin/sh | grep tcsh >/dev/null; then
+ noclobber_set="set noclobber"
+fi
+
+#
+# useful routines
+#
+signal() {
+ if [ -s ${pidfile} ]
+ then
+ kill -"$1" `cat ${pidfile}` && return 0
+ else
+ echo "nsd is not running"
+ fi
+ return 1
+}
+
+lock_file() {
+ (umask 222; ${noclobber_set}; echo "$$" >${lockfile})
+}
+
+lock() {
+ lock_file
+ if [ $? = 1 ]
+ then
+ # check if the lockfile has not gone stale
+ LPID=`cat ${lockfile}`
+ echo database locked by PID: $LPID
+ if kill -0 $LPID 2>/dev/null; then
+ exit 1
+ fi
+
+ # locking process does not exist, consider lockfile stale
+ echo stale lockfile, removing... && rm -f ${lockfile} && lock_file
+ fi
+
+ if [ $? = 1 ]
+ then
+ echo lock failed
+ exit 1
+ fi
+ return 0
+}
+
+unlock() {
+ rm -f ${lockfile}
+}
+
+do_start() {
+ if test -x ${sbindir}/nsd; then
+ ${sbindir}/nsd -c ${configfile}
+ test $? = 0 || (echo "nsd startup failed."; exit 1)
+ else
+ echo "${sbindir}/nsd not an executable file, nsd startup failed."; exit 1
+ fi
+}
+
+controlled_sleep() {
+ if [ $1 -ge 25 ]; then
+ sleep 1
+ fi
+}
+
+controlled_stop() {
+ pid=$1
+ try=1
+
+ while [ $try -ne 0 ]; do
+ if [ ${try} -gt 50 ]; then
+ echo "nsdc stop failed"
+ return 1
+ else
+ if [ $try -eq 1 ]; then
+ kill -TERM ${pid}
+ else
+ kill -TERM ${pid} >/dev/null 2>&1
+ fi
+
+ # really stopped?
+ kill -0 ${pid} >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ controlled_sleep ${try}
+ try=`expr ${try} + 1`
+ else
+ try=0
+ fi
+ fi
+ done
+
+ return 0
+}
+
+do_controlled_stop() {
+ if [ -s ${pidfile} ]; then
+ pid=`cat ${pidfile}`
+ controlled_stop ${pid} && return 0
+ else
+ echo "nsd is not running, starting anyway" && return 0
+ fi
+ return 1
+}
+
+do_stop() {
+ signal "TERM"
+}
+
+do_reload() {
+ signal "HUP"
+}
+
+# send_updates zone_name {ip_spec key_spec}
+send_updates() {
+ local zonename=$1
+ shift 1
+ # extract port number (if any)
+ port=`${nsd_checkconf} -o port ${configfile}`
+ if test -n "${port}"; then
+ port="-p ${port}"
+ fi
+ update_sent="no"
+
+ while test $# -gt 0; do
+ ip_spec=$1
+ key_spec=$2
+ shift 2
+ # only localhost is allowed.
+ # see if zone has 127.0.0.1 or ::1 as allowed.
+ if test Z${ip_spec} = "Z127.0.0.1" -o Z${ip_spec} = "Z::1"; then
+ secret=""
+ if test K${key_spec} != KNOKEY -a K${key_spec} != KBLOCKED; then
+ secret=`${nsd_checkconf} -s ${key_spec} ${configfile}`
+ algo=`${nsd_checkconf} -a ${key_spec} ${configfile}`
+ secret="-y ${key_spec}:${secret}:${algo}"
+ fi
+ if test K${key_spec} != KBLOCKED; then
+ #echo "${sbindir}/nsd-notify -a ${ip_spec} ${port} ${secret} -z ${zonename} ${ip_spec}"
+ ${sbindir}/nsd-notify -a ${ip_spec} ${port} ${secret} -z ${zonename} ${ip_spec} && update_sent="yes"
+ fi
+ fi
+ done
+ if test ${update_sent} = no; then
+ req_xfr=`${nsd_checkconf} -z "${zonename}" -o request-xfr ${configfile}`
+ if test -n "${req_xfr}"; then
+ # must be a slave zone (has request-xfr).
+ echo "`basename $0`: Could not send notify for slave zone ${zonename}: not configured (with allow-notify: 127.0.0.1 or ::1)"
+ fi
+ fi
+}
+
+# send_notify zone_name ifc_spec {ip_spec key_spec}
+send_notify() {
+ local zonename=$1
+ # set local interface
+ ifc_spec=""
+ if test I$2 != INOIFC; then
+ ifc_spec="-a $2"
+ fi
+ shift 2
+
+ while test $# -gt 0; do
+ ip_spec=$1
+ key_spec=$2
+ shift 2
+ secret=""
+
+ if test K${key_spec} != KNOKEY -a K${key_spec} != KBLOCKED; then
+ secret=`${nsd_checkconf} -s ${key_spec} ${configfile}`
+ algo=`${nsd_checkconf} -a ${key_spec} ${configfile}`
+ secret="-y ${key_spec}:${secret}:${algo}"
+ fi
+ if test K${key_spec} != KBLOCKED; then
+ port=""
+ ipaddr=${ip_spec}
+ if echo ${ip_spec} | grep @ >/dev/null; then
+ port="-p "`echo ${ip_spec} | sed -e 's/[^@]*@\([0-9]*\)/\1/'`
+ ipaddr=`echo ${ip_spec} | sed -e 's/\([^@]*\)@[0-9]*/\1/'`
+ fi
+ #echo "${sbindir}/nsd-notify ${ifc_spec} ${port} ${secret} -z ${zonename} ${ipaddr}"
+ ${sbindir}/nsd-notify ${ifc_spec} ${port} ${secret} -z ${zonename} ${ipaddr}
+ fi
+ done
+}
+
+# do_patch {with-textfile}
+do_patch() {
+ if test I$1 = I1; then
+ lock && mv ${difffile} ${difffile}.$$ && \
+ ${sbindir}/nsd-patch -c ${configfile} -x ${difffile}.$$ && \
+ rm -f ${difffile}.$$ && unlock && do_rebuild
+ result=$?
+ else # without textfile
+ lock && mv ${difffile} ${difffile}.$$ && \
+ ${sbindir}/nsd-patch -c ${configfile} -x ${difffile}.$$ -s -o ${dbfile}.$$ \
+ && rm -f ${difffile}.$$ && unlock && \
+ mv ${dbfile}.$$ ${dbfile}
+ result=$?
+ fi
+
+ return ${result}
+}
+
+do_rebuild() {
+ lock && \
+ ${sbindir}/zonec ${ZONEC_VERBOSE} -c ${configfile} -f ${dbfile}.$$ && \
+ mv ${dbfile}.$$ ${dbfile}
+ result=$?
+ unlock
+ [ $result != 0 ] && echo "${dbfile} is unmodified"
+ rm -f ${dbfile}.$$
+ return ${result}
+}
+
+start() {
+ ebegin "Starting ${name}"
+ if test -s ${pidfile} && kill -"0" `cat ${pidfile}`
+ then
+ (echo "process `cat ${pidfile}` exists, please use restart"; exit 1)
+ else
+ start-stop-daemon --start --quiet \
+ --pidfile ${pidfile} \
+ --exec ${initd} -- do_start
+ fi
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${name}"
+ start-stop-daemon --stop --quiet \
+ --pidfile ${pidfile} \
+ --exec ${initd} -- do_stop
+ eend $?
+}
+
+stats() {
+ signal "USR1"
+}
+
+reload() {
+ do_reload
+}
+
+running() {
+ signal "0"
+}
+
+patch() {
+ # patch queue clearen
+ if test -s ${difffile}; then
+ #${sbindir}/nsd-patch -c ${configfile} -x ${difffile} -l #debug
+ #echo ${sbindir}/nsd-patch -c ${configfile} -x ${difffile}
+ if do_patch ${PATCH_STYLE}; then
+ do_reload
+ else
+ unlock
+ # try to move back the transfer data
+ if [ -e ${difffile}.$$ -a ! -e ${difffile} ]; then
+ mv ${difffile}.$$ ${difffile}
+ fi
+ echo "`basename $0`: patch failed."
+ exit 1
+ fi
+ else
+ echo "`basename $0`: no patch necessary."
+ fi
+}
+
+rebuild() {
+ do_rebuild
+}
+
+update() {
+ # send notifies to localhost for all zones that allow it
+ echo "Sending notify to localhost to update secondary zones..."
+ if [ -s ${pidfile} ]; then
+ zoneslist=`${nsd_checkconf} -o zones ${configfile}`
+ for zonename in ${zoneslist}; do
+ notify_allow=`${nsd_checkconf} -z "${zonename}" -o allow-notify ${configfile}`
+ if test "" != "${notify_allow}"; then
+ send_updates ${zonename} ${notify_allow}
+ fi
+ done
+ else
+ echo "nsd is not running"
+ fi
+}
+
+notify() {
+ # send notifies to all slaves
+ echo "Sending notify to slave servers..."
+ zoneslist=`${nsd_checkconf} -o zones ${configfile}`
+ for zonename in ${zoneslist}; do
+ notify=`${nsd_checkconf} -z "${zonename}" -o notify ${configfile}`
+ local_ifc=`${nsd_checkconf} -z "${zonename}" -o outgoing-interface ${configfile}`
+ if test "" = "${local_ifc}"; then
+ local_ifc="NOIFC"
+ fi
+ if test "" != "${notify}"; then
+ for ifc in ${local_ifc}; do
+ send_notify ${zonename} ${ifc} ${notify}
+ done
+ fi
+ done
+}
+
+restart() {
+ do_controlled_stop && do_start
+}
diff --git a/main/nsd/nsd.post-deinstall b/main/nsd/nsd.post-deinstall
new file mode 100644
index 0000000000..4d5fc40932
--- /dev/null
+++ b/main/nsd/nsd.post-deinstall
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+deluser nsd 2>/dev/null
+exit 0
diff --git a/main/nsd/nsd.pre-install b/main/nsd/nsd.pre-install
new file mode 100644
index 0000000000..daabc70b38
--- /dev/null
+++ b/main/nsd/nsd.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -S -H -h /var/db/nsd -s /bin/false nsd 2>/dev/null
+exit 0
diff --git a/main/nsd/nsdc b/main/nsd/nsdc
new file mode 100644
index 0000000000..ff4cb5c6b7
--- /dev/null
+++ b/main/nsd/nsdc
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# nsdc replacement script by Matt Smith <msmith@alpinelinux.org>
+#
+
+usage() {
+ echo "Usage: `basename $0` {start|stop|reload|rebuild|restart|"
+ echo " running|update|notify|patch}"
+ echo "commands:"
+ echo " start Start nsd server."
+ echo " stop Stop nsd server."
+ echo " reload Nsd server reloads database file."
+ echo " rebuild Compile database file from zone files."
+ echo " restart Stop the nsd server and start it again."
+ echo " running Prints message and exit nonzero if server not running."
+ echo " update Try to update all slave zones hosted on this server."
+ echo " notify Send notify messages to all secondary servers."
+ echo " patch Merge zone transfer changes back to zone files."
+}
+
+if [ $# -eq 0 ]; then
+ usage
+else
+ case "$1" in
+ "-h"|"--help")
+ usage;;
+ *)
+ /etc/init.d/nsd $*
+ esac
+fi
diff --git a/main/nspr/APKBUILD b/main/nspr/APKBUILD
new file mode 100644
index 0000000000..c34ddf9147
--- /dev/null
+++ b/main/nspr/APKBUILD
@@ -0,0 +1,74 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=nspr
+pkgver=4.8.8
+pkgrel=0
+pkgdesc="Netscape Portable Runtime"
+url="http://www.mozilla.org/projects/nspr/"
+arch="all"
+license="MPL-1.1 GPL-2 LGPL-2.1"
+depends=
+makedepends="autoconf automake sed"
+subpackages="$pkgname-dev"
+source="ftp://ftp.mozilla.org/pub/mozilla.org/nspr/releases/v$pkgver/src/nspr-$pkgver.tar.gz
+ nspr-4.7.0-prtime.patch
+ nspr-4.8-sonames.patch
+ nspr-4.8-config.patch
+ nspr-4.8-pkgconfig-gentoo-3.patch
+ nspr-bb-shell.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ mkdir build inst
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+ # respect LDFLAGS
+ sed -i -e 's/\$(MKSHLIB) \$(OBJS)/\$(MKSHLIB) \$(LDFLAGS) \$(OBJS)/g' \
+ mozilla/nsprpub/config/rules.mk
+ cd mozilla/nsprpub && rm -f aclocal.m4 && aclocal && autoconf
+}
+
+build() {
+ local conf=
+ if [ "$CARCH" = "x86_64" ];then
+ conf="--enable-64bit"
+ fi
+ cd "$_builddir"/build
+ ../mozilla/nsprpub/configure --prefix=/usr \
+ $conf \
+ || return 1
+ make SO_VERSION=$pkgver CC="${CC:-gcc}" CXX="${CXX:-g++}" || return 1
+}
+
+package() {
+ local file=
+ replaces="nspr-dev"
+
+ cd "$_builddir"/build
+ make SO_VERSION=$pkgver DESTDIR="$pkgdir" install || return 1
+
+ cd "$pkgdir"/usr/lib
+ rm -f *.a
+
+ cd "$_builddir"/build/config
+ install -Dm755 nspr-config "$pkgdir"/usr/bin/nspr-config || return 1
+ install -Dm644 nspr.pc "$pkgdir"/usr/lib/pkgconfig/nspr.pc || return 1
+ rm -rf "$pkgdir"/usr/bin/prerr.properties \
+ "$pkgdir"/usr/bin/compile-et.pl \
+ "$pkgdir"/usr/share/aclocal/nspr.m4 \
+ "$pkgdir"/usr/include/nspr/md
+}
+
+md5sums="b3a961d2e0ff3331745220984c70b6a9 nspr-4.8.8.tar.gz
+c48e1f47799c1cff7e3bf46dc0e653f1 nspr-4.7.0-prtime.patch
+5c9f15c65561af93ff5e148d8b64e212 nspr-4.8-sonames.patch
+c790c638a7c9fd1d731272f464f065c6 nspr-4.8-config.patch
+c31984cfcc167eb010aed949ace236ae nspr-4.8-pkgconfig-gentoo-3.patch
+6574eabdfbfcd246e0dfaf1aa8b0e695 nspr-bb-shell.patch"
diff --git a/main/nspr/nspr-4.7.0-prtime.patch b/main/nspr/nspr-4.7.0-prtime.patch
new file mode 100644
index 0000000000..74d5534d5a
--- /dev/null
+++ b/main/nspr/nspr-4.7.0-prtime.patch
@@ -0,0 +1,26 @@
+--- a/mozilla/nsprpub/pr/src/misc/prtime.c.orig 2007-09-14 19:41:08.000000000 +0200
++++ b/mozilla/nsprpub/pr/src/misc/prtime.c 2007-09-14 19:42:17.000000000 +0200
+@@ -1536,7 +1536,7 @@
+ case TT_EET: zone_offset = 2 * 60; break;
+ case TT_JST: zone_offset = 9 * 60; break;
+ default:
+- PR_ASSERT (0);
++ return PR_FAILURE;
+ break;
+ }
+ }
+@@ -1578,11 +1578,12 @@
+ struct tm localTime;
+ time_t secs;
+
+- PR_ASSERT(result->tm_month > -1 &&
++ if (!(result->tm_month > -1 &&
+ result->tm_mday > 0 &&
+ result->tm_hour > -1 &&
+ result->tm_min > -1 &&
+- result->tm_sec > -1);
++ result->tm_sec > -1))
++ return PR_FAILURE;
+
+ /*
+ * To obtain time_t from a tm structure representing the local
diff --git a/main/nspr/nspr-4.8-config.patch b/main/nspr/nspr-4.8-config.patch
new file mode 100644
index 0000000000..4db2517e4e
--- /dev/null
+++ b/main/nspr/nspr-4.8-config.patch
@@ -0,0 +1,47 @@
+--- a/mozilla/nsprpub/lib/libc/src/Makefile.in.orig 2005-06-01 14:28:26.000000000 +0000
++++ b/mozilla/nsprpub/lib/libc/src/Makefile.in 2006-01-15 02:50:39.000000000 +0000
+@@ -112,6 +112,10 @@
+ MKSHLIB += -R '$$ORIGIN'
+ endif
+
++ifeq ($(OS_ARCH), Linux)
++DSO_LDOPTS +=-Wl,-R,'$$ORIGIN'
++endif
++
+ ifeq ($(OS_ARCH),OS2)
+ MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
+ GARBAGE += $(MAPFILE)
+--- a/mozilla/nsprpub/lib/ds/Makefile.in.orig 2005-06-01 14:28:25.000000000 +0000
++++ b/mozilla/nsprpub/lib/ds/Makefile.in 2006-01-15 02:52:30.000000000 +0000
+@@ -102,6 +102,10 @@
+ MKSHLIB += -R '$$ORIGIN'
+ endif
+
++ifeq ($(OS_ARCH), Linux)
++DSO_LDOPTS += -Wl,-R,'$$ORIGIN'
++endif
++
+ ifeq ($(OS_ARCH),OS2)
+ MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
+ GARBAGE += $(MAPFILE)
+--- a/mozilla/nsprpub/pr/src/Makefile.in.orig 2005-06-01 14:28:27.000000000 +0000
++++ b/mozilla/nsprpub/pr/src/Makefile.in 2006-01-15 03:29:36.000000000 +0000
+@@ -168,6 +168,7 @@
+ else
+ OS_LIBS = -ldl
+ endif
++DSO_LDOPTS +=-Wl,-R,'$$ORIGIN'
+ endif
+
+ ifeq ($(OS_ARCH),HP-UX)
+--- a/mozilla/nsprpub/config/nspr-config.in.orig 2005-05-11 00:53:41.000000000 +0000
++++ b/mozilla/nsprpub/config/nspr-config.in 2006-01-15 06:37:58.000000000 +0000
+@@ -122,7 +122,7 @@
+ fi
+
+ if test "$echo_libs" = "yes"; then
+- libdirs=-L$libdir
++ libdirs="-Wl,-R$libdir -L$libdir"
+ if test -n "$lib_plds"; then
+ libdirs="$libdirs -lplds${major_version}"
+ fi
diff --git a/main/nspr/nspr-4.8-pkgconfig-gentoo-3.patch b/main/nspr/nspr-4.8-pkgconfig-gentoo-3.patch
new file mode 100644
index 0000000000..89e042d957
--- /dev/null
+++ b/main/nspr/nspr-4.8-pkgconfig-gentoo-3.patch
@@ -0,0 +1,115 @@
+diff -urN nspr-4.8-orig/mozilla/nsprpub/config/config.mk nspr-4.8/mozilla/nsprpub/config/config.mk
+--- nspr-4.8-orig/mozilla/nsprpub/config/config.mk 2009-09-12 00:43:47.678357452 -0500
++++ nspr-4.8/mozilla/nsprpub/config/config.mk 2009-09-12 00:44:19.383381757 -0500
+@@ -162,3 +162,4 @@
+ RELEASE_INCLUDE_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/include
+ RELEASE_BIN_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/bin
+ RELEASE_LIB_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/lib
++RELEASE_PC_DIR = $(RELEASE_LIB_DIR)/pkgconfig
+diff -urN nspr-4.8-orig/mozilla/nsprpub/config/Makefile.in nspr-4.8/mozilla/nsprpub/config/Makefile.in
+--- nspr-4.8-orig/mozilla/nsprpub/config/Makefile.in 2009-09-12 00:43:47.678357452 -0500
++++ nspr-4.8/mozilla/nsprpub/config/Makefile.in 2009-09-12 00:44:19.384379661 -0500
+@@ -52,9 +52,10 @@
+
+ # autoconf.mk must be deleted last (from the top-level directory)
+ # because it is included by every makefile.
+-DIST_GARBAGE = nsprincl.mk nsprincl.sh nspr-config
++DIST_GARBAGE = nsprincl.mk nsprincl.sh nspr-config nspr.pc
+
+ RELEASE_BINS = nspr-config
++RELEASE_PC = nspr.pc
+
+ include $(topsrcdir)/config/config.mk
+
+diff -urN nspr-4.8-orig/mozilla/nsprpub/config/nspr-config.in nspr-4.8/mozilla/nsprpub/config/nspr-config.in
+--- nspr-4.8-orig/mozilla/nsprpub/config/nspr-config.in 2009-09-12 00:43:47.677356194 -0500
++++ nspr-4.8/mozilla/nsprpub/config/nspr-config.in 2009-09-12 00:45:53.723359547 -0500
+@@ -92,13 +92,13 @@
+
+ # Set variables that may be dependent upon other variables
+ if test -z "$exec_prefix"; then
+- exec_prefix=@exec_prefix@
++ exec_prefix=`pkg-config --variable=exec_prefix nspr`
+ fi
+ if test -z "$includedir"; then
+- includedir=@includedir@
++ includedir=`pkg-config --variable=includedir nspr`
+ fi
+ if test -z "$libdir"; then
+- libdir=@libdir@
++ libdir=`pkg-config --variable=libdir nspr`
+ fi
+
+ if test "$echo_prefix" = "yes"; then
+diff -urN nspr-4.8-orig/mozilla/nsprpub/config/nspr.pc.in nspr-4.8/mozilla/nsprpub/config/nspr.pc.in
+--- nspr-4.8-orig/mozilla/nsprpub/config/nspr.pc.in 1969-12-31 18:00:00.000000000 -0600
++++ nspr-4.8/mozilla/nsprpub/config/nspr.pc.in 2009-09-12 00:44:19.410432811 -0500
+@@ -0,0 +1,11 @@
++prefix=@prefix@
++exec_prefix=@exec_prefix@
++libdir=@libdir@
++includedir=@includedir@
++
++Name: NSPR
++Description: The Netscape Portable Runtime
++Version: @MOD_MAJOR_VERSION@.@MOD_MINOR_VERSION@.@MOD_PATCH_VERSION@
++Libs: -L${libdir} -lplds@MOD_MAJOR_VERSION@ -lplc@MOD_MAJOR_VERSION@ -lnspr@MOD_MAJOR_VERSION@ -lpthread -Wl,-R${libdir}
++Cflags: -I${includedir}
++
+diff -urN nspr-4.8-orig/mozilla/nsprpub/config/rules.mk nspr-4.8/mozilla/nsprpub/config/rules.mk
+--- nspr-4.8-orig/mozilla/nsprpub/config/rules.mk 2009-09-12 00:43:47.677356194 -0500
++++ nspr-4.8/mozilla/nsprpub/config/rules.mk 2009-09-12 00:44:19.435517111 -0500
+@@ -211,7 +211,7 @@
+ rm -rf $(wildcard *.OBJ *.OBJD) dist $(ALL_TRASH) $(DIST_GARBAGE)
+ +$(LOOP_OVER_DIRS)
+
+-install:: $(RELEASE_BINS) $(RELEASE_HEADERS) $(RELEASE_LIBS)
++install:: $(RELEASE_BINS) $(RELEASE_HEADERS) $(RELEASE_LIBS) $(RELEASE_PC)
+ ifdef RELEASE_BINS
+ $(NSINSTALL) -t -m 0755 $(RELEASE_BINS) $(DESTDIR)$(bindir)
+ endif
+@@ -221,6 +221,9 @@
+ ifdef RELEASE_LIBS
+ $(NSINSTALL) -t -m 0755 $(RELEASE_LIBS) $(DESTDIR)$(libdir)/$(lib_subdir)
+ endif
++ifdef RELEASE_PC
++ $(NSINSTALL) -t -m 0644 $(RELEASE_PC) $(DESTDIR)$(libdir)/pkgconfig/
++endif
+ +$(LOOP_OVER_DIRS)
+
+ release:: export
+@@ -272,6 +275,23 @@
+ fi
+ cp $(RELEASE_HEADERS) $(RELEASE_HEADERS_DEST)
+ endif
++ifdef RELEASE_PC
++ @echo "Copying pkg-config files to release directory"
++ @if test -z "$(BUILD_NUMBER)"; then \
++ echo "BUILD_NUMBER must be defined"; \
++ false; \
++ else \
++ true; \
++ fi
++ @if test ! -d $(RELEASE_PC_DEST); then \
++ rm -rf $(RELEASE_PC_DEST); \
++ $(NSINSTALL) -D $(RELEASE_PC_DEST);\
++ else \
++ true; \
++ fi
++ cp $(RELEASE_PC) $(RELEASE_PC_DEST)
++endif
++
+ +$(LOOP_OVER_DIRS)
+
+ alltags:
+diff -urN nspr-4.8-orig/mozilla/nsprpub/configure.in nspr-4.8/mozilla/nsprpub/configure.in
+--- nspr-4.8-orig/mozilla/nsprpub/configure.in 2009-09-12 00:43:47.678357452 -0500
++++ nspr-4.8/mozilla/nsprpub/configure.in 2009-09-12 00:44:19.451396074 -0500
+@@ -2871,6 +2871,7 @@
+ config/nsprincl.mk
+ config/nsprincl.sh
+ config/nspr-config
++config/nspr.pc
+ lib/Makefile
+ lib/ds/Makefile
+ lib/libc/Makefile
diff --git a/main/nspr/nspr-4.8-sonames.patch b/main/nspr/nspr-4.8-sonames.patch
new file mode 100644
index 0000000000..d0f5ad801d
--- /dev/null
+++ b/main/nspr/nspr-4.8-sonames.patch
@@ -0,0 +1,256 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 81_sonames.dpatch by Mike Hommey <glandium@debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Add soname support
+
+@DPATCH@
+
+diff --git a/mozilla/nsprpub/config/rules.mk b/mozilla/nsprpub/config/rules.mk
+index 794b1ae..235929d 100644
+--- a/mozilla/nsprpub/config/rules.mk
++++ b/mozilla/nsprpub/config/rules.mk
+@@ -132,6 +132,29 @@ SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_shr.a
+ else
+ ifdef MKSHLIB
+ SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
++SONAME = $(notdir $(SHARED_LIBRARY))
++
++ifdef SO_VERSION
++ifneq (,$(findstring $(SONAME),$(MKSHLIB)))
++SO_VERSION_MAJOR := $(shell echo $(SO_VERSION) | sed 's/^\([^.]*\)\(\.[^.]*\)\?\(\.[^.]*\)\?/\1/')
++SO_VERSION_MINOR := $(shell echo $(SO_VERSION) | sed 's/^\([^.]*\)\(\.[^.]*\)\?\(\.[^.]*\)\?/\2/')
++SO_VERSION_MICRO := $(shell echo $(SO_VERSION) | sed 's/^\([^.]*\)\(\.[^.]*\)\?\(\.[^.]*\)\?/\3/')
++
++SHARED_LIBRARY_LINKS := $(SONAME)
++ifdef SO_VERSION_MINOR
++SHARED_LIBRARY_LINKS += $(SONAME).$(SO_VERSION_MAJOR)
++endif
++ifdef SO_VERSION_MICRO
++SHARED_LIBRARY_LINKS += $(SHARED_LIBRARY).$(SO_VERSION_MAJOR)$(SO_VERSION_MINOR)
++endif
++
++SONAME := $(SONAME).$(SO_VERSION_MAJOR)
++SHARED_LIBRARY := $(SHARED_LIBRARY).$(SO_VERSION)
++
++MKSHLINKS = (cd $(1) && for link in $(SHARED_LIBRARY_LINKS); do rm -f $$link; ln -s $(notdir $(SHARED_LIBRARY)) $$link; done)
++endif
++endif
++
+ endif
+ endif
+
+@@ -165,7 +188,7 @@ OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
+ endif
+
+ ALL_TRASH = $(TARGETS) $(OBJS) $(RES) $(filter-out . .., $(OBJDIR)) LOGS TAGS $(GARBAGE) \
+- $(NOSUCHFILE) \
++ $(SHARED_LIBRARY_LINKS) $(NOSUCHFILE) \
+ so_locations
+
+ ifndef RELEASE_LIBS_DEST
+@@ -215,6 +238,7 @@ ifdef RELEASE_HEADERS
+ endif
+ ifdef RELEASE_LIBS
+ $(NSINSTALL) -t -m 0755 $(RELEASE_LIBS) $(DESTDIR)$(libdir)/$(lib_subdir)
++ $(call MKSHLINKS,$(DESTDIR)$(libdir)/$(lib_subdir))
+ endif
+ +$(LOOP_OVER_DIRS)
+
+@@ -310,6 +334,8 @@ $(IMPORT_LIBRARY): $(SHARED_LIBRARY)
+ endif
+ endif
+
++$(SHARED_LIBRARY_LINKS): %: $(SHARED_LIBRARY)
++
+ $(SHARED_LIBRARY): $(OBJS) $(RES) $(MAPFILE)
+ @$(MAKE_OBJDIR)
+ rm -f $@
+@@ -332,6 +358,7 @@ ifdef MT
+ endif # MSVC with manifest tool
+ else # WINNT && !GCC
+ $(MKSHLIB) $(OBJS) $(RES) $(LDFLAGS) $(EXTRA_LIBS)
++ $(call MKSHLINKS,.)
+ endif # WINNT && !GCC
+ endif # AIX 4.1
+ ifdef ENABLE_STRIP
+diff --git a/mozilla/nsprpub/configure.in b/mozilla/nsprpub/configure.in
+index 772e288..e4cea9a 100644
+--- a/mozilla/nsprpub/configure.in
++++ b/mozilla/nsprpub/configure.in
+@@ -1113,7 +1113,7 @@ case "$target" in
+ AC_DEFINE(_PR_STAT_HAS_ST_ATIMESPEC)
+ MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)'
+ DSO_CFLAGS=-fPIC
+- DSO_LDOPTS='-shared -Wl,-soname,$(@:$(OBJDIR)/%.so=%.so)'
++ DSO_LDOPTS='-shared -Wl,-soname,$(SONAME)'
+ STRIP="$STRIP -d"
+ case "$target_os" in
+ bsdi4.2* | bsdi4.3* | bsdi5.*)
+@@ -1311,7 +1311,7 @@ tools are selected during the Xcode/Developer Tools installation.])
+ fi
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ DSO_CFLAGS=-fPIC
+- DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
++ DSO_LDOPTS='-shared -Wl,-soname -Wl,$(SONAME)'
+ MDCPUCFG_H=_freebsd.cfg
+ PR_MD_CSRCS=freebsd.c
+ ;;
+@@ -1326,7 +1326,7 @@ tools are selected during the Xcode/Developer Tools installation.])
+ # workaround this problem.
+ AC_DEFINE(_PR_POLL_WITH_SELECT)
+ AC_DEFINE(_USE_BIG_FDS)
+- DSO_LDOPTS='-b +h $(notdir $@)'
++ DSO_LDOPTS='-b +h $(SONAME)'
+ PR_MD_CSRCS=hpux.c
+ if test "$OS_TEST" = "ia64"; then
+ DLL_SUFFIX=so
+@@ -1579,7 +1579,7 @@ arm-android-eabi)
+ PR_MD_CSRCS=linux.c
+ MKSHLIB='$(CC) $(DSO_LDOPTS) $(WRAP_MALLOC_LIB) -o $@'
+ DSO_CFLAGS=-fPIC
+- DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
++ DSO_LDOPTS='-shared -Wl,-soname -Wl,$(SONAME)'
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS="-g -fno-inline" # most people on linux use gcc/gdb, and that
+ # combo is not yet good at debugging inlined
+@@ -1610,7 +1610,7 @@ arm-android-eabi)
+ PR_MD_CSRCS=linux.c
+ MKSHLIB='$(CC) $(DSO_LDOPTS) $(WRAP_MALLOC_LIB) -o $@'
+ DSO_CFLAGS=-fPIC
+- DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
++ DSO_LDOPTS='-shared -Wl,-soname -Wl,$(SONAME)'
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS="-g -fno-inline" # most people on linux use gcc/gdb, and that
+ # combo is not yet good at debugging inlined
+@@ -1943,7 +1943,7 @@ mips-nec-sysv*)
+ else
+ OBJECT_FMT=ELF
+ DLL_SUFFIX=so
+- DSO_LDOPTS='-shared -Wl,-soname,$(notdir $@)'
++ DSO_LDOPTS='-shared -Wl,-soname,$(SONAME)'
+ fi
+ fi
+
+@@ -1989,7 +1989,7 @@ mips-sony-newsos*)
+ AC_DEFINE(HAVE_POINTER_LOCALTIME_R)
+ MDCPUCFG_H=_nto.cfg
+ PR_MD_CSRCS=nto.c
+- MKSHLIB='$(CC) $(DSO_LDOPTS) -Wl,-soname -Wl,$(notdir $@) -o $@'
++ MKSHLIB='$(CC) $(DSO_LDOPTS) -Wl,-soname -Wl,$(SONAME) -o $@'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS=-shared
+ OS_LIBS="$OS_LIBS -lsocket"
+@@ -2052,7 +2052,7 @@ mips-sony-newsos*)
+ if echo $OS_RELEASE | grep -c V4.0 >/dev/null; then
+ AC_DEFINE(OSF1V4_MAP_PRIVATE_BUG)
+ fi
+- DSO_LDOPTS='-shared -all -expect_unresolved "*" -soname $(notdir $@)'
++ DSO_LDOPTS='-shared -all -expect_unresolved "*" -soname $(SONAME)'
+ MDCPUCFG_H=_osf1.cfg
+ PR_MD_CSRCS=osf1.c
+ ;;
+@@ -2119,7 +2119,7 @@ mips-sony-newsos*)
+ _OPTIMIZE_FLAGS='-O -F Olimit,4000'
+ fi
+
+- DSO_LDOPTS='-G -z defs -h $(@:$(OBJDIR)/%.so=%.so)'
++ DSO_LDOPTS='-G -z defs -h $(SONAME)'
+
+ if test "$OS_RELEASE" = "5.43"; then
+ AC_DEFINE(IP_MULTICAST)
+@@ -2184,13 +2184,13 @@ mips-sony-newsos*)
+ if `$CC -print-prog-name=ld` -v 2>&1 | grep -c GNU >/dev/null; then
+ GCC_USE_GNU_LD=1
+ fi
+- DSO_LDOPTS='-shared -Wl,-h,$(notdir $@),-z,combreloc,-z,defs,-z,ignore'
++ DSO_LDOPTS='-shared -Wl,-h,$(SONAME),-z,combreloc,-z,defs,-z,ignore'
+ if test -n "$USE_B_DIRECT"; then
+ DSO_LDOPTS="$DSO_LDOPTS,-Bdirect"
+ fi
+ else
+ DSO_CFLAGS=-KPIC
+- DSO_LDOPTS='-G -h $(notdir $@) -z combreloc -z defs -z ignore'
++ DSO_LDOPTS='-G -h $(SONAME) -z combreloc -z defs -z ignore'
+ if test -n "$USE_B_DIRECT"; then
+ DSO_LDOPTS="$DSO_LDOPTS -Bdirect"
+ fi
+diff --git a/mozilla/nsprpub/lib/ds/Makefile.in b/mozilla/nsprpub/lib/ds/Makefile.in
+index 82dca03..ab4e64d 100644
+--- a/mozilla/nsprpub/lib/ds/Makefile.in
++++ b/mozilla/nsprpub/lib/ds/Makefile.in
+@@ -122,6 +122,7 @@ endif
+
+ LIBRARY_NAME = plds
+ LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
++SO_VERSION = 0d
+
+ RELEASE_HEADERS = $(HEADERS)
+ RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+@@ -176,11 +177,13 @@ endif
+ export:: $(TARGETS)
+ $(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
++ $(call MKSHLINKS,$(dist_libdir))
+ ifdef SHARED_LIBRARY
+ ifeq ($(OS_ARCH),HP-UX)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
+ else
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
++ $(call MKSHLINKS,$(dist_bindir))
+ endif
+ endif
+diff --git a/mozilla/nsprpub/lib/libc/src/Makefile.in b/mozilla/nsprpub/lib/libc/src/Makefile.in
+index 2cafb1a..0d74a4a 100644
+--- a/mozilla/nsprpub/lib/libc/src/Makefile.in
++++ b/mozilla/nsprpub/lib/libc/src/Makefile.in
+@@ -68,6 +68,7 @@ CSRCS =\
+
+ LIBRARY_NAME = plc
+ LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
++SO_VERSION = 0d
+
+ RELEASE_LIBS = $(TARGETS)
+
+@@ -177,11 +178,13 @@ endif
+
+ export:: $(TARGETS)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
++ $(call MKSHLINKS,$(dist_libdir))
+ ifdef SHARED_LIBRARY
+ ifeq ($(OS_ARCH),HP-UX)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
+ else
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
++ $(call MKSHLINKS,$(dist_bindir))
+ endif
+ endif
+diff --git a/mozilla/nsprpub/pr/src/Makefile.in b/mozilla/nsprpub/pr/src/Makefile.in
+index 3514ab1..a86766e 100644
+--- a/mozilla/nsprpub/pr/src/Makefile.in
++++ b/mozilla/nsprpub/pr/src/Makefile.in
+@@ -325,6 +325,7 @@ endif
+
+ LIBRARY_NAME = nspr
+ LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
++SO_VERSION = 0d
+
+ RELEASE_LIBS = $(TARGETS)
+
+@@ -391,12 +392,14 @@ endif
+
+ export:: $(TARGETS)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
++ $(call MKSHLINKS,$(dist_libdir))
+ ifdef SHARED_LIBRARY
+ ifeq ($(OS_ARCH),HP-UX)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
+ else
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
++ $(call MKSHLINKS,$(dist_bindir))
+ endif
+ endif
+
diff --git a/main/nspr/nspr-bb-shell.patch b/main/nspr/nspr-bb-shell.patch
new file mode 100644
index 0000000000..a336c2a56c
--- /dev/null
+++ b/main/nspr/nspr-bb-shell.patch
@@ -0,0 +1,13 @@
+diff --git a/mozilla/nsprpub/configure.in b/mozilla/nsprpub/configure.in
+index 25dcca1..b508762 100644
+--- a/mozilla/nsprpub/configure.in
++++ b/mozilla/nsprpub/configure.in
+@@ -511,7 +511,7 @@ if test "$target" != "$host"; then
+
+ AC_MSG_CHECKING([whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works])
+ AC_TRY_COMPILE([], [return(0);],
+- [ac_cv_prog_host_cc_works=1 AC_MSG_RESULT([yes])],
++ [ac_cv_prog_host_cc_works=1; AC_MSG_RESULT([yes])],
+ AC_MSG_ERROR([installation or configuration problem: $host compiler $HOST_CC cannot create executables.]) )
+
+ CC=$_SAVE_CC
diff --git a/main/nss/APKBUILD b/main/nss/APKBUILD
new file mode 100644
index 0000000000..d50a28e02f
--- /dev/null
+++ b/main/nss/APKBUILD
@@ -0,0 +1,145 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=nss
+pkgver=3.12.10
+_ver=${pkgver//./_}
+pkgrel=0
+pkgdesc="Mozilla Network Security Services"
+url="http://www.mozilla.org/projects/security/pki/nss/"
+arch="all"
+license="MPL GPL"
+depends=
+makedepends="nspr-dev sqlite-dev zlib-dev perl"
+subpackages="$pkgname-dev $pkgname-tools"
+source="ftp://ftp.mozilla.org/pub/security/$pkgname/releases/NSS_${_ver}_RTM/src/$pkgname-$pkgver.tar.gz
+ nss-no-rpath.patch
+ nss.pc.in
+ nss-config.in
+ add_spi+cacert_ca_certs.patch
+ ssl-renegotiate-transitional.patch"
+depends_dev="nspr-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -Np1 -i ""$srcdir"/add_spi+cacert_ca_certs.patch" || return 1
+ patch -Np1 -i ""$srcdir"/ssl-renegotiate-transitional.patch" || return 1
+ patch -Np0 -i ""$srcdir"/nss-no-rpath.patch" || return 1
+
+ # Respect LDFLAGS
+ sed -i -e 's/\$(MKSHLIB) -o/\$(MKSHLIB) \$(LDFLAGS) -o/g' \
+ mozilla/security/coreconf/rules.mk
+
+}
+
+build() {
+ cd "$_builddir"
+ unset CFLAGS
+ unset CXXFLAGS
+ export BUILD_OPT=1
+ export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
+ export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1
+ export FREEBL_NO_DEPEND=0
+ export NSPR_INCLUDE_DIR=`pkg-config --cflags-only-I nspr | sed 's/-I//'`
+ export NSPR_LIB_DIR=`pkg-config --libs-only-L nspr | sed 's/-L.//'`
+ export XCFLAGS="${CFLAGS}"
+ if [ "$CARCH" = "x86_64" ]; then
+ export USE_64=1
+ fi
+ make -j 1 -C mozilla/security/coreconf || return 1
+ make -j 1 -C mozilla/security/dbm || return 1
+ make -j 1 -C mozilla/security/nss || return 1
+}
+
+package() {
+ replaces="nss-dev libnss"
+
+ cd "$_builddir"
+
+ install -m755 -d "$pkgdir"/usr/lib/pkgconfig
+ install -m755 -d "$pkgdir"/usr/bin
+ install -m755 -d "$pkgdir"/usr/include/nss
+
+ NSS_VMAJOR=`awk '/#define.*NSS_VMAJOR/ {print $3}' mozilla/security/nss/lib/nss/nss.h `
+ msg "DEBUG: $NSS_VMAJOR"
+ NSS_VMINOR=`awk '/#define.*NSS_VMINOR/ {print $3}' mozilla/security/nss/lib/nss/nss.h`
+ NSS_VPATCH=`awk '/#define.*NSS_VPATCH"/ {print $3}' mozilla/security/nss/lib/nss/nss.h`
+
+ # pkgconfig files
+ sed "$srcdir"/nss.pc.in \
+ -e "s,%libdir%,/usr/lib,g" \
+ -e "s,%prefix%,/usr,g" \
+ -e "s,%exec_prefix%,/usr/bin,g" \
+ -e "s,%includedir%,/usr/include/nss,g" \
+ -e "s,%NSPR_VERSION%,$pkgver,g" \
+ -e "s,%NSS_VERSION%,$pkgver,g" \
+ > "$pkgdir"/usr/lib/pkgconfig/nss.pc \
+ || return 1
+ ln -sf nss.pc "$pkgdir"/usr/lib/pkgconfig/mozilla-nss.pc || return 1
+ chmod 644 "$pkgdir"/usr/lib/pkgconfig/*.pc || return 1
+
+ # nss-config
+ sed "$srcdir"/nss-config.in \
+ -e "s,@libdir@,/usr/lib,g" \
+ -e "s,@prefix@,/usr/bin,g" \
+ -e "s,@exec_prefix@,/usr/bin,g" \
+ -e "s,@includedir@,/usr/include/nss,g" \
+ -e "s,@MOD_MAJOR_VERSION@,${NSS_VMAJOR},g" \
+ -e "s,@MOD_MINOR_VERSION@,${NSS_VMINOR},g" \
+ -e "s,@MOD_PATCH_VERSION@,${NSS_VPATCH},g" \
+ > "$pkgdir"/usr/bin/nss-config || return 1
+ chmod 755 "$pkgdir"/usr/bin/nss-config || return 1
+ local minor=${pkgver#*.}
+ minor=${minor%.*}
+ for file in libsoftokn3.so libfreebl3.so libnss3.so libnssutil3.so \
+ libssl3.so libsmime3.so libnssckbi.so libnssdbm3.so; do
+ install -m755 mozilla/dist/*.OBJ/lib/${file} \
+ "$pkgdir"/usr/lib/${file}.$minor || return 1
+ ln -s $file.$minor "$pkgdir"/usr/lib/$file
+ done
+ install -m644 mozilla/dist/*.OBJ/lib/libcrmf.a "$pkgdir"/usr/lib/ \
+ || return 1
+ install -m644 mozilla/dist/*.OBJ/lib/*.chk "$pkgdir"/usr/lib/ \
+ || return 1
+
+ for file in certutil cmsutil crlutil modutil pk12util shlibsign \
+ signtool signver ssltap; do
+ install -m755 mozilla/dist/*.OBJ/bin/${file} "$pkgdir"/usr/bin/\
+ || return 1
+ done
+ install -m644 mozilla/dist/public/nss/*.h "$pkgdir"/usr/include/nss/ \
+ || return 1
+}
+
+dev() {
+ local i= j=
+ depends="$pkgname $depends_dev"
+
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/nss-config "$subpkgdir"/usr/bin
+
+ cd "$pkgdir" || return 0
+ for i in usr/include usr/lib/pkgconfig usr/lib/*.a; do
+ if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
+ d="$subpkgdir/${i%/*}" # dirname $i
+ mkdir -p "$d"
+ mv "$pkgdir/$i" "$d"
+ rmdir "$pkgdir/${i%/*}" 2>/dev/null
+ fi
+ done
+
+ return 0
+}
+
+tools() {
+ pkgdesc="Tools for the Network Security Services"
+ replaces="nss"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="027954e894f02732f4e66cd854261145 nss-3.12.10.tar.gz
+e5c97db0c884d5f4cfda21e562dc9bba nss-no-rpath.patch
+c547b030c57fe1ed8b77c73bf52b3ded nss.pc.in
+46bee81908f1e5b26d6a7a2e14c64d9f nss-config.in
+7f39c19b1dfd62d7db7d8bf19f156fed add_spi+cacert_ca_certs.patch
+d83c7b61abb7e9f8f7bcd157183d1ade ssl-renegotiate-transitional.patch"
diff --git a/main/nss/add_spi+cacert_ca_certs.patch b/main/nss/add_spi+cacert_ca_certs.patch
new file mode 100644
index 0000000000..1cc7c18f54
--- /dev/null
+++ b/main/nss/add_spi+cacert_ca_certs.patch
@@ -0,0 +1,561 @@
+--- a/mozilla/security/nss/lib/ckfw/builtins/certdata.txt
++++ b/mozilla/security/nss/lib/ckfw/builtins/certdata.txt
+@@ -20926,3 +20926,558 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
+ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
+ CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
+ CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
++
++#
++# Certificate "CAcert.org Class 1 Root CA"
++#
++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
++CKA_TOKEN CK_BBOOL CK_TRUE
++CKA_PRIVATE CK_BBOOL CK_FALSE
++CKA_MODIFIABLE CK_BBOOL CK_FALSE
++CKA_LABEL UTF8 "CAcert.org Class 1 Root CA"
++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
++CKA_SUBJECT MULTILINE_OCTAL
++\060\171\061\020\060\016\006\003\125\004\012\023\007\122\157\157
++\164\040\103\101\061\036\060\034\006\003\125\004\013\023\025\150
++\164\164\160\072\057\057\167\167\167\056\143\141\143\145\162\164
++\056\157\162\147\061\042\060\040\006\003\125\004\003\023\031\103
++\101\040\103\145\162\164\040\123\151\147\156\151\156\147\040\101
++\165\164\150\157\162\151\164\171\061\041\060\037\006\011\052\206
++\110\206\367\015\001\011\001\026\022\163\165\160\160\157\162\164
++\100\143\141\143\145\162\164\056\157\162\147
++END
++CKA_ID UTF8 "0"
++CKA_ISSUER MULTILINE_OCTAL
++\060\171\061\020\060\016\006\003\125\004\012\023\007\122\157\157
++\164\040\103\101\061\036\060\034\006\003\125\004\013\023\025\150
++\164\164\160\072\057\057\167\167\167\056\143\141\143\145\162\164
++\056\157\162\147\061\042\060\040\006\003\125\004\003\023\031\103
++\101\040\103\145\162\164\040\123\151\147\156\151\156\147\040\101
++\165\164\150\157\162\151\164\171\061\041\060\037\006\011\052\206
++\110\206\367\015\001\011\001\026\022\163\165\160\160\157\162\164
++\100\143\141\143\145\162\164\056\157\162\147
++END
++CKA_SERIAL_NUMBER MULTILINE_OCTAL
++\002\001\000
++END
++CKA_VALUE MULTILINE_OCTAL
++\060\202\007\075\060\202\005\045\240\003\002\001\002\002\001\000
++\060\015\006\011\052\206\110\206\367\015\001\001\004\005\000\060
++\171\061\020\060\016\006\003\125\004\012\023\007\122\157\157\164
++\040\103\101\061\036\060\034\006\003\125\004\013\023\025\150\164
++\164\160\072\057\057\167\167\167\056\143\141\143\145\162\164\056
++\157\162\147\061\042\060\040\006\003\125\004\003\023\031\103\101
++\040\103\145\162\164\040\123\151\147\156\151\156\147\040\101\165
++\164\150\157\162\151\164\171\061\041\060\037\006\011\052\206\110
++\206\367\015\001\011\001\026\022\163\165\160\160\157\162\164\100
++\143\141\143\145\162\164\056\157\162\147\060\036\027\015\060\063
++\060\063\063\060\061\062\062\071\064\071\132\027\015\063\063\060
++\063\062\071\061\062\062\071\064\071\132\060\171\061\020\060\016
++\006\003\125\004\012\023\007\122\157\157\164\040\103\101\061\036
++\060\034\006\003\125\004\013\023\025\150\164\164\160\072\057\057
++\167\167\167\056\143\141\143\145\162\164\056\157\162\147\061\042
++\060\040\006\003\125\004\003\023\031\103\101\040\103\145\162\164
++\040\123\151\147\156\151\156\147\040\101\165\164\150\157\162\151
++\164\171\061\041\060\037\006\011\052\206\110\206\367\015\001\011
++\001\026\022\163\165\160\160\157\162\164\100\143\141\143\145\162
++\164\056\157\162\147\060\202\002\042\060\015\006\011\052\206\110
++\206\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002
++\012\002\202\002\001\000\316\042\300\342\106\175\354\066\050\007
++\120\226\362\240\063\100\214\113\361\073\146\077\061\345\153\002
++\066\333\326\174\366\361\210\217\116\167\066\005\101\225\371\011
++\360\022\317\106\206\163\140\267\156\176\350\300\130\144\256\315
++\260\255\105\027\014\143\372\147\012\350\326\322\277\076\347\230
++\304\360\114\372\340\003\273\065\135\154\041\336\236\040\331\272
++\315\146\062\067\162\372\367\010\365\307\315\130\311\216\347\016
++\136\352\076\376\034\241\024\012\025\154\206\204\133\144\146\052
++\172\251\113\123\171\365\210\242\173\356\057\012\141\053\215\262
++\176\115\126\245\023\354\352\332\222\236\254\104\101\036\130\140
++\145\005\146\370\300\104\275\313\224\367\102\176\013\367\145\150
++\230\121\005\360\363\005\221\004\035\033\027\202\354\310\127\273
++\303\153\172\210\361\260\162\314\045\133\040\221\354\026\002\022
++\217\062\351\027\030\110\320\307\005\056\002\060\102\270\045\234
++\005\153\077\252\072\247\353\123\110\367\350\322\266\007\230\334
++\033\306\064\177\177\311\034\202\172\005\130\053\010\133\363\070
++\242\253\027\135\146\311\230\327\236\020\213\242\322\335\164\232
++\367\161\014\162\140\337\315\157\230\063\235\226\064\166\076\044
++\172\222\260\016\225\036\157\346\240\105\070\107\252\327\101\355
++\112\267\022\366\327\033\203\212\017\056\330\011\266\131\327\252
++\004\377\322\223\175\150\056\335\213\113\253\130\272\057\215\352
++\225\247\240\303\124\211\245\373\333\213\121\042\235\262\303\276
++\021\276\054\221\206\213\226\170\255\040\323\212\057\032\077\306
++\320\121\145\207\041\261\031\001\145\177\105\034\207\365\174\320
++\101\114\117\051\230\041\375\063\037\165\014\004\121\372\031\167
++\333\324\024\034\356\201\303\035\365\230\267\151\006\221\042\335
++\000\120\314\201\061\254\022\007\173\070\332\150\133\346\053\324
++\176\311\137\255\350\353\162\114\363\001\345\113\040\277\232\246
++\127\312\221\000\001\213\241\165\041\067\265\143\015\147\076\106
++\117\160\040\147\316\305\326\131\333\002\340\360\322\313\315\272
++\142\267\220\101\350\335\040\344\051\274\144\051\102\310\042\334
++\170\232\377\103\354\230\033\011\121\113\132\132\302\161\361\304
++\313\163\251\345\241\013\002\003\001\000\001\243\202\001\316\060
++\202\001\312\060\035\006\003\125\035\016\004\026\004\024\026\265
++\062\033\324\307\363\340\346\216\363\275\322\260\072\356\262\071
++\030\321\060\201\243\006\003\125\035\043\004\201\233\060\201\230
++\200\024\026\265\062\033\324\307\363\340\346\216\363\275\322\260
++\072\356\262\071\030\321\241\175\244\173\060\171\061\020\060\016
++\006\003\125\004\012\023\007\122\157\157\164\040\103\101\061\036
++\060\034\006\003\125\004\013\023\025\150\164\164\160\072\057\057
++\167\167\167\056\143\141\143\145\162\164\056\157\162\147\061\042
++\060\040\006\003\125\004\003\023\031\103\101\040\103\145\162\164
++\040\123\151\147\156\151\156\147\040\101\165\164\150\157\162\151
++\164\171\061\041\060\037\006\011\052\206\110\206\367\015\001\011
++\001\026\022\163\165\160\160\157\162\164\100\143\141\143\145\162
++\164\056\157\162\147\202\001\000\060\017\006\003\125\035\023\001
++\001\377\004\005\060\003\001\001\377\060\062\006\003\125\035\037
++\004\053\060\051\060\047\240\045\240\043\206\041\150\164\164\160
++\163\072\057\057\167\167\167\056\143\141\143\145\162\164\056\157
++\162\147\057\162\145\166\157\153\145\056\143\162\154\060\060\006
++\011\140\206\110\001\206\370\102\001\004\004\043\026\041\150\164
++\164\160\163\072\057\057\167\167\167\056\143\141\143\145\162\164
++\056\157\162\147\057\162\145\166\157\153\145\056\143\162\154\060
++\064\006\011\140\206\110\001\206\370\102\001\010\004\047\026\045
++\150\164\164\160\072\057\057\167\167\167\056\143\141\143\145\162
++\164\056\157\162\147\057\151\156\144\145\170\056\160\150\160\077
++\151\144\075\061\060\060\126\006\011\140\206\110\001\206\370\102
++\001\015\004\111\026\107\124\157\040\147\145\164\040\171\157\165
++\162\040\157\167\156\040\143\145\162\164\151\146\151\143\141\164
++\145\040\146\157\162\040\106\122\105\105\040\150\145\141\144\040
++\157\166\145\162\040\164\157\040\150\164\164\160\072\057\057\167
++\167\167\056\143\141\143\145\162\164\056\157\162\147\060\015\006
++\011\052\206\110\206\367\015\001\001\004\005\000\003\202\002\001
++\000\050\307\356\234\202\002\272\134\200\022\312\065\012\035\201
++\157\211\152\231\314\362\150\017\177\247\341\215\130\225\076\275
++\362\006\303\220\132\254\265\140\366\231\103\001\243\210\160\234
++\235\142\235\244\207\257\147\130\015\060\066\073\346\255\110\323
++\313\164\002\206\161\076\342\053\003\150\361\064\142\100\106\073
++\123\352\050\364\254\373\146\225\123\212\115\135\375\073\331\140
++\327\312\171\151\073\261\145\222\246\306\201\202\134\234\315\353
++\115\001\212\245\337\021\125\252\025\312\037\067\300\202\230\160
++\141\333\152\174\226\243\216\056\124\076\117\041\251\220\357\334
++\202\277\334\350\105\255\115\220\163\010\074\224\145\260\004\231
++\166\177\342\274\302\152\025\252\227\004\067\044\330\036\224\116
++\155\016\121\276\326\304\217\312\226\155\367\103\337\350\060\145
++\047\073\173\273\103\103\143\304\103\367\262\354\150\314\341\031
++\216\042\373\230\341\173\132\076\001\067\073\213\010\260\242\363
++\225\116\032\313\233\315\232\261\333\262\160\360\055\112\333\330
++\260\343\157\105\110\063\022\377\376\074\062\052\124\367\304\367
++\212\360\210\043\302\107\376\144\172\161\300\321\036\246\143\260
++\007\176\244\057\323\001\217\334\237\053\266\306\010\251\017\223
++\110\045\374\022\375\237\102\334\363\304\076\366\127\260\327\335
++\151\321\006\167\064\012\113\322\312\240\377\034\306\214\311\026
++\276\304\314\062\067\150\163\137\010\373\121\367\111\123\066\005
++\012\225\002\114\362\171\032\020\366\330\072\165\234\363\035\361
++\242\015\160\147\206\033\263\026\365\057\345\244\353\171\206\371
++\075\013\302\163\013\245\231\254\157\374\147\270\345\057\013\246
++\030\044\215\173\321\110\065\051\030\100\254\223\140\341\226\206
++\120\264\172\131\330\217\041\013\237\317\202\221\306\073\277\153
++\334\007\221\271\227\126\043\252\266\154\224\306\110\006\074\344
++\316\116\252\344\366\057\011\334\123\157\056\374\164\353\072\143
++\231\302\246\254\211\274\247\262\104\240\015\212\020\343\154\362
++\044\313\372\233\237\160\107\056\336\024\213\324\262\040\011\226
++\242\144\361\044\034\334\241\065\234\025\262\324\274\125\056\175
++\006\365\234\016\125\364\132\326\223\332\166\255\045\163\114\305
++\103
++END
++
++# Trust for Certificate "CAcert.org Class 1 Root CA"
++CKA_CLASS CK_OBJECT_CLASS CKO_NETSCAPE_TRUST
++CKA_TOKEN CK_BBOOL CK_TRUE
++CKA_PRIVATE CK_BBOOL CK_FALSE
++CKA_MODIFIABLE CK_BBOOL CK_FALSE
++CKA_LABEL UTF8 "CAcert.org Class 1 Root CA"
++CKA_CERT_SHA1_HASH MULTILINE_OCTAL
++\023\134\354\066\364\234\270\351\073\032\262\160\315\200\210\106
++\166\316\217\063
++END
++CKA_CERT_MD5_HASH MULTILINE_OCTAL
++\246\033\067\136\071\015\234\066\124\356\275\040\061\106\037\153
++END
++CKA_ISSUER MULTILINE_OCTAL
++\060\171\061\020\060\016\006\003\125\004\012\023\007\122\157\157
++\164\040\103\101\061\036\060\034\006\003\125\004\013\023\025\150
++\164\164\160\072\057\057\167\167\167\056\143\141\143\145\162\164
++\056\157\162\147\061\042\060\040\006\003\125\004\003\023\031\103
++\101\040\103\145\162\164\040\123\151\147\156\151\156\147\040\101
++\165\164\150\157\162\151\164\171\061\041\060\037\006\011\052\206
++\110\206\367\015\001\011\001\026\022\163\165\160\160\157\162\164
++\100\143\141\143\145\162\164\056\157\162\147
++END
++CKA_SERIAL_NUMBER MULTILINE_OCTAL
++\002\001\000
++END
++CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
++
++#
++# Certificate "CAcert.org Class 3 Root CA"
++#
++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
++CKA_TOKEN CK_BBOOL CK_TRUE
++CKA_PRIVATE CK_BBOOL CK_FALSE
++CKA_MODIFIABLE CK_BBOOL CK_FALSE
++CKA_LABEL UTF8 "CAcert.org Class 3 Root CA"
++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
++CKA_SUBJECT MULTILINE_OCTAL
++\060\124\061\024\060\022\006\003\125\004\012\023\013\103\101\143
++\145\162\164\040\111\156\143\056\061\036\060\034\006\003\125\004
++\013\023\025\150\164\164\160\072\057\057\167\167\167\056\103\101
++\143\145\162\164\056\157\162\147\061\034\060\032\006\003\125\004
++\003\023\023\103\101\143\145\162\164\040\103\154\141\163\163\040
++\063\040\122\157\157\164
++END
++CKA_ID UTF8 "0"
++CKA_ISSUER MULTILINE_OCTAL
++\060\171\061\020\060\016\006\003\125\004\012\023\007\122\157\157
++\164\040\103\101\061\036\060\034\006\003\125\004\013\023\025\150
++\164\164\160\072\057\057\167\167\167\056\143\141\143\145\162\164
++\056\157\162\147\061\042\060\040\006\003\125\004\003\023\031\103
++\101\040\103\145\162\164\040\123\151\147\156\151\156\147\040\101
++\165\164\150\157\162\151\164\171\061\041\060\037\006\011\052\206
++\110\206\367\015\001\011\001\026\022\163\165\160\160\157\162\164
++\100\143\141\143\145\162\164\056\157\162\147
++END
++CKA_SERIAL_NUMBER MULTILINE_OCTAL
++\002\001\001
++END
++CKA_VALUE MULTILINE_OCTAL
++\060\202\006\010\060\202\003\360\240\003\002\001\002\002\001\001
++\060\015\006\011\052\206\110\206\367\015\001\001\004\005\000\060
++\171\061\020\060\016\006\003\125\004\012\023\007\122\157\157\164
++\040\103\101\061\036\060\034\006\003\125\004\013\023\025\150\164
++\164\160\072\057\057\167\167\167\056\143\141\143\145\162\164\056
++\157\162\147\061\042\060\040\006\003\125\004\003\023\031\103\101
++\040\103\145\162\164\040\123\151\147\156\151\156\147\040\101\165
++\164\150\157\162\151\164\171\061\041\060\037\006\011\052\206\110
++\206\367\015\001\011\001\026\022\163\165\160\160\157\162\164\100
++\143\141\143\145\162\164\056\157\162\147\060\036\027\015\060\065
++\061\060\061\064\060\067\063\066\065\065\132\027\015\063\063\060
++\063\062\070\060\067\063\066\065\065\132\060\124\061\024\060\022
++\006\003\125\004\012\023\013\103\101\143\145\162\164\040\111\156
++\143\056\061\036\060\034\006\003\125\004\013\023\025\150\164\164
++\160\072\057\057\167\167\167\056\103\101\143\145\162\164\056\157
++\162\147\061\034\060\032\006\003\125\004\003\023\023\103\101\143
++\145\162\164\040\103\154\141\163\163\040\063\040\122\157\157\164
++\060\202\002\042\060\015\006\011\052\206\110\206\367\015\001\001
++\001\005\000\003\202\002\017\000\060\202\002\012\002\202\002\001
++\000\253\111\065\021\110\174\322\046\176\123\224\317\103\251\335
++\050\327\102\052\213\363\207\170\031\130\174\017\236\332\211\175
++\341\373\353\162\220\015\164\241\226\144\253\237\240\044\231\163
++\332\342\125\166\307\027\173\365\004\254\106\270\303\276\177\144
++\215\020\154\044\363\141\234\300\362\220\372\121\346\365\151\001
++\143\303\017\126\342\112\102\317\342\104\214\045\050\250\305\171
++\011\175\106\271\212\363\351\363\064\051\010\105\344\034\237\313
++\224\004\034\201\250\024\263\230\145\304\103\354\116\202\215\011
++\321\275\252\133\215\222\320\354\336\220\305\177\012\302\343\353
++\346\061\132\136\164\076\227\063\131\350\303\003\075\140\063\277
++\367\321\157\107\304\315\356\142\203\122\156\056\010\232\244\331
++\025\030\221\246\205\222\107\260\256\110\353\155\267\041\354\205
++\032\150\162\065\253\377\360\020\135\300\364\224\247\152\325\073
++\222\176\114\220\005\176\223\301\054\213\244\216\142\164\025\161
++\156\013\161\003\352\257\025\070\232\324\322\005\162\157\214\371
++\053\353\132\162\045\371\071\106\343\162\033\076\004\303\144\047
++\042\020\052\212\117\130\247\003\255\276\264\056\023\355\135\252
++\110\327\325\175\324\052\173\134\372\106\004\120\344\314\016\102
++\133\214\355\333\362\317\374\226\223\340\333\021\066\124\142\064
++\070\217\014\140\233\073\227\126\070\255\363\322\133\213\240\133
++\352\116\226\270\174\327\325\240\206\160\100\323\221\051\267\242
++\074\255\365\214\273\317\032\222\212\344\064\173\300\330\154\137
++\351\012\302\303\247\040\232\132\337\054\135\122\134\272\107\325
++\233\357\044\050\160\070\040\057\325\177\051\300\262\101\003\150
++\222\314\340\234\314\227\113\105\357\072\020\012\253\160\072\230
++\225\160\255\065\261\352\205\053\244\034\200\041\061\251\256\140
++\172\200\046\110\000\270\001\300\223\143\125\042\221\074\126\347
++\257\333\072\045\363\217\061\124\352\046\213\201\131\371\241\321
++\123\021\305\173\235\003\366\164\021\340\155\261\054\077\054\206
++\221\231\161\232\246\167\213\064\140\321\024\264\054\254\235\257
++\214\020\323\237\304\152\370\157\023\374\163\131\367\146\102\164
++\036\212\343\370\334\322\157\230\234\313\107\230\225\100\005\373
++\351\002\003\001\000\001\243\201\277\060\201\274\060\017\006\003
++\125\035\023\001\001\377\004\005\060\003\001\001\377\060\135\006
++\010\053\006\001\005\005\007\001\001\004\121\060\117\060\043\006
++\010\053\006\001\005\005\007\060\001\206\027\150\164\164\160\072
++\057\057\157\143\163\160\056\103\101\143\145\162\164\056\157\162
++\147\057\060\050\006\010\053\006\001\005\005\007\060\002\206\034
++\150\164\164\160\072\057\057\167\167\167\056\103\101\143\145\162
++\164\056\157\162\147\057\143\141\056\143\162\164\060\112\006\003
++\125\035\040\004\103\060\101\060\077\006\010\053\006\001\004\001
++\201\220\112\060\063\060\061\006\010\053\006\001\005\005\007\002
++\001\026\045\150\164\164\160\072\057\057\167\167\167\056\103\101
++\143\145\162\164\056\157\162\147\057\151\156\144\145\170\056\160
++\150\160\077\151\144\075\061\060\060\015\006\011\052\206\110\206
++\367\015\001\001\004\005\000\003\202\002\001\000\177\010\210\241
++\332\032\120\111\332\211\373\241\010\162\363\212\367\036\304\072
++\264\171\133\040\060\261\105\336\302\135\323\145\151\361\302\135
++\124\124\074\205\137\271\173\102\221\302\231\375\033\121\233\253
++\106\245\241\020\123\236\155\210\254\163\156\054\063\246\360\364
++\236\340\165\301\076\210\105\251\341\146\103\376\126\132\321\172
++\101\170\367\100\332\112\072\361\013\133\245\273\026\006\346\302
++\347\223\271\205\115\227\117\261\036\070\103\200\357\233\015\214
++\357\270\247\140\000\207\127\175\036\104\034\313\043\357\233\074
++\231\235\257\265\051\034\105\171\026\226\115\047\155\361\034\154
++\303\302\125\144\263\274\024\342\363\244\037\036\062\374\047\025
++\005\317\335\056\256\076\202\141\173\360\041\020\030\366\104\352
++\123\071\371\334\320\232\040\340\306\273\340\273\132\117\304\231
++\310\007\275\265\275\242\333\056\142\015\102\064\101\274\377\213
++\212\365\121\042\252\210\060\000\342\260\324\274\276\145\272\325
++\003\127\171\233\350\334\310\115\370\120\355\221\245\122\050\242
++\254\373\066\130\076\351\224\053\221\120\207\033\326\136\326\214
++\314\367\017\020\014\122\116\320\026\141\345\345\012\154\277\027
++\307\162\106\127\234\230\365\154\140\143\172\157\136\271\116\057
++\310\271\271\273\152\205\274\230\015\355\371\076\227\204\064\224
++\256\000\257\241\345\347\222\156\116\275\363\342\331\024\213\134
++\322\353\001\154\240\027\245\055\020\353\234\172\112\275\275\356
++\316\375\355\042\100\253\160\070\210\365\012\207\152\302\253\005
++\140\311\110\005\332\123\301\336\104\167\152\263\363\074\074\355
++\200\274\246\070\112\051\044\137\376\131\073\233\045\172\126\143
++\000\144\271\135\244\142\175\127\066\117\255\203\357\037\222\123
++\240\216\167\127\335\345\141\021\075\043\000\220\114\074\372\243
++\140\223\004\243\257\065\366\016\152\217\117\112\140\247\205\005
++\154\106\241\217\364\307\166\343\241\131\127\367\161\262\304\156
++\024\134\155\155\101\146\337\033\223\261\324\000\303\356\313\317
++\074\075\041\200\251\137\143\145\374\335\340\137\244\364\053\360
++\205\161\101\324\147\045\373\032\261\227\256\326\231\202\023\101
++\322\156\245\033\231\047\200\347\013\251\250\000
++END
++
++# Trust for Certificate "CAcert.org Class 3 Root CA"
++CKA_CLASS CK_OBJECT_CLASS CKO_NETSCAPE_TRUST
++CKA_TOKEN CK_BBOOL CK_TRUE
++CKA_PRIVATE CK_BBOOL CK_FALSE
++CKA_MODIFIABLE CK_BBOOL CK_FALSE
++CKA_LABEL UTF8 "CAcert.org Class 3 Root CA"
++CKA_CERT_SHA1_HASH MULTILINE_OCTAL
++\333\114\102\151\007\077\351\302\243\175\211\012\134\033\030\304
++\030\116\052\055
++END
++CKA_CERT_MD5_HASH MULTILINE_OCTAL
++\163\077\065\124\035\104\311\351\132\112\357\121\255\003\006\266
++END
++CKA_ISSUER MULTILINE_OCTAL
++\060\171\061\020\060\016\006\003\125\004\012\023\007\122\157\157
++\164\040\103\101\061\036\060\034\006\003\125\004\013\023\025\150
++\164\164\160\072\057\057\167\167\167\056\143\141\143\145\162\164
++\056\157\162\147\061\042\060\040\006\003\125\004\003\023\031\103
++\101\040\103\145\162\164\040\123\151\147\156\151\156\147\040\101
++\165\164\150\157\162\151\164\171\061\041\060\037\006\011\052\206
++\110\206\367\015\001\011\001\026\022\163\165\160\160\157\162\164
++\100\143\141\143\145\162\164\056\157\162\147
++END
++CKA_SERIAL_NUMBER MULTILINE_OCTAL
++\002\001\001
++END
++CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
++
++#
++# Certificate "Software in the Public Interest, Inc. Root CA (2008)"
++#
++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
++CKA_TOKEN CK_BBOOL CK_TRUE
++CKA_PRIVATE CK_BBOOL CK_FALSE
++CKA_MODIFIABLE CK_BBOOL CK_FALSE
++CKA_LABEL UTF8 "Software in the Public Interest, Inc. Root CA (2008)"
++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
++CKA_SUBJECT MULTILINE_OCTAL
++\060\201\274\061\013\060\011\006\003\125\004\006\023\002\125\123
++\061\020\060\016\006\003\125\004\010\023\007\111\156\144\151\141
++\156\141\061\025\060\023\006\003\125\004\007\023\014\111\156\144
++\151\141\156\141\160\157\154\151\163\061\050\060\046\006\003\125
++\004\012\023\037\123\157\146\164\167\141\162\145\040\151\156\040
++\164\150\145\040\120\165\142\154\151\143\040\111\156\164\145\162
++\145\163\164\061\023\060\021\006\003\125\004\013\023\012\150\157
++\163\164\155\141\163\164\145\162\061\036\060\034\006\003\125\004
++\003\023\025\103\145\162\164\151\146\151\143\141\164\145\040\101
++\165\164\150\157\162\151\164\171\061\045\060\043\006\011\052\206
++\110\206\367\015\001\011\001\026\026\150\157\163\164\155\141\163
++\164\145\162\100\163\160\151\055\151\156\143\056\157\162\147
++END
++CKA_ID UTF8 "0"
++CKA_ISSUER MULTILINE_OCTAL
++\060\201\274\061\013\060\011\006\003\125\004\006\023\002\125\123
++\061\020\060\016\006\003\125\004\010\023\007\111\156\144\151\141
++\156\141\061\025\060\023\006\003\125\004\007\023\014\111\156\144
++\151\141\156\141\160\157\154\151\163\061\050\060\046\006\003\125
++\004\012\023\037\123\157\146\164\167\141\162\145\040\151\156\040
++\164\150\145\040\120\165\142\154\151\143\040\111\156\164\145\162
++\145\163\164\061\023\060\021\006\003\125\004\013\023\012\150\157
++\163\164\155\141\163\164\145\162\061\036\060\034\006\003\125\004
++\003\023\025\103\145\162\164\151\146\151\143\141\164\145\040\101
++\165\164\150\157\162\151\164\171\061\045\060\043\006\011\052\206
++\110\206\367\015\001\011\001\026\026\150\157\163\164\155\141\163
++\164\145\162\100\163\160\151\055\151\156\143\056\157\162\147
++END
++CKA_SERIAL_NUMBER MULTILINE_OCTAL
++\002\011\000\350\216\266\311\370\052\024\050
++END
++CKA_VALUE MULTILINE_OCTAL
++\060\202\010\016\060\202\005\366\240\003\002\001\002\002\011\000
++\350\216\266\311\370\052\024\050\060\015\006\011\052\206\110\206
++\367\015\001\001\005\005\000\060\201\274\061\013\060\011\006\003
++\125\004\006\023\002\125\123\061\020\060\016\006\003\125\004\010
++\023\007\111\156\144\151\141\156\141\061\025\060\023\006\003\125
++\004\007\023\014\111\156\144\151\141\156\141\160\157\154\151\163
++\061\050\060\046\006\003\125\004\012\023\037\123\157\146\164\167
++\141\162\145\040\151\156\040\164\150\145\040\120\165\142\154\151
++\143\040\111\156\164\145\162\145\163\164\061\023\060\021\006\003
++\125\004\013\023\012\150\157\163\164\155\141\163\164\145\162\061
++\036\060\034\006\003\125\004\003\023\025\103\145\162\164\151\146
++\151\143\141\164\145\040\101\165\164\150\157\162\151\164\171\061
++\045\060\043\006\011\052\206\110\206\367\015\001\011\001\026\026
++\150\157\163\164\155\141\163\164\145\162\100\163\160\151\055\151
++\156\143\056\157\162\147\060\036\027\015\060\070\060\065\061\063
++\060\070\060\067\065\066\132\027\015\061\070\060\065\061\061\060
++\070\060\067\065\066\132\060\201\274\061\013\060\011\006\003\125
++\004\006\023\002\125\123\061\020\060\016\006\003\125\004\010\023
++\007\111\156\144\151\141\156\141\061\025\060\023\006\003\125\004
++\007\023\014\111\156\144\151\141\156\141\160\157\154\151\163\061
++\050\060\046\006\003\125\004\012\023\037\123\157\146\164\167\141
++\162\145\040\151\156\040\164\150\145\040\120\165\142\154\151\143
++\040\111\156\164\145\162\145\163\164\061\023\060\021\006\003\125
++\004\013\023\012\150\157\163\164\155\141\163\164\145\162\061\036
++\060\034\006\003\125\004\003\023\025\103\145\162\164\151\146\151
++\143\141\164\145\040\101\165\164\150\157\162\151\164\171\061\045
++\060\043\006\011\052\206\110\206\367\015\001\011\001\026\026\150
++\157\163\164\155\141\163\164\145\162\100\163\160\151\055\151\156
++\143\056\157\162\147\060\202\002\042\060\015\006\011\052\206\110
++\206\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002
++\012\002\202\002\001\000\334\066\346\107\102\302\304\121\165\051
++\207\100\303\330\216\041\006\322\030\116\353\357\040\275\220\074
++\205\020\023\214\051\133\224\143\366\364\055\361\006\102\221\271
++\031\304\102\151\010\277\213\066\105\352\050\005\063\111\110\240
++\047\103\223\065\212\101\330\170\263\360\357\263\156\055\335\321
++\313\175\352\364\165\046\323\076\220\072\356\327\347\054\004\265
++\174\341\365\174\305\116\357\167\275\134\242\223\063\222\316\175
++\201\110\317\153\265\042\054\010\203\375\323\325\317\073\055\375
++\265\111\220\133\366\255\115\023\312\336\323\246\235\123\121\161
++\143\106\370\112\026\134\230\356\055\155\232\026\241\166\220\342
++\140\103\231\326\211\326\154\056\172\230\262\013\003\054\343\172
++\117\307\335\343\314\343\112\152\215\171\122\372\364\301\257\056
++\217\052\010\313\033\051\202\222\162\103\274\316\210\251\252\247
++\212\121\103\125\205\232\067\003\170\223\310\360\275\264\101\310
++\007\102\232\313\065\227\172\212\201\145\336\035\124\010\001\361
++\144\134\267\027\032\121\274\036\303\131\207\166\030\026\230\356
++\277\366\147\201\213\006\065\305\113\155\131\031\307\322\306\110
++\276\156\024\050\203\112\020\234\033\365\157\274\251\216\365\151
++\376\262\301\125\314\347\024\311\371\133\024\123\121\007\352\316
++\075\344\117\050\037\074\141\011\327\063\322\156\247\156\324\307
++\023\011\157\153\135\024\356\235\211\033\245\152\362\366\370\320
++\162\216\352\162\037\057\064\152\051\012\305\012\354\034\100\205
++\022\367\246\245\323\117\255\300\205\214\114\174\163\040\314\123
++\030\361\262\130\114\001\365\277\352\144\325\134\071\305\316\154
++\314\123\132\126\272\101\017\045\337\153\120\266\307\212\240\275
++\002\302\305\073\125\245\262\144\042\204\121\050\126\256\061\356
++\136\373\013\026\115\106\005\221\200\104\355\254\155\360\127\250
++\372\353\141\110\240\313\033\263\037\216\315\305\041\167\003\204
++\036\374\254\243\103\010\143\214\355\371\047\357\264\260\135\147
++\326\117\355\320\213\076\135\133\311\221\275\226\002\204\075\305
++\115\274\102\077\164\375\074\135\254\134\110\066\136\207\061\057
++\030\154\304\150\356\241\213\311\131\320\030\343\000\200\263\124
++\047\056\231\360\025\123\002\003\001\000\001\243\202\002\017\060
++\202\002\013\060\035\006\003\125\035\016\004\026\004\024\064\161
++\321\070\327\025\066\203\107\153\327\067\144\102\073\216\215\122
++\235\253\060\201\361\006\003\125\035\043\004\201\351\060\201\346
++\200\024\064\161\321\070\327\025\066\203\107\153\327\067\144\102
++\073\216\215\122\235\253\241\201\302\244\201\277\060\201\274\061
++\013\060\011\006\003\125\004\006\023\002\125\123\061\020\060\016
++\006\003\125\004\010\023\007\111\156\144\151\141\156\141\061\025
++\060\023\006\003\125\004\007\023\014\111\156\144\151\141\156\141
++\160\157\154\151\163\061\050\060\046\006\003\125\004\012\023\037
++\123\157\146\164\167\141\162\145\040\151\156\040\164\150\145\040
++\120\165\142\154\151\143\040\111\156\164\145\162\145\163\164\061
++\023\060\021\006\003\125\004\013\023\012\150\157\163\164\155\141
++\163\164\145\162\061\036\060\034\006\003\125\004\003\023\025\103
++\145\162\164\151\146\151\143\141\164\145\040\101\165\164\150\157
++\162\151\164\171\061\045\060\043\006\011\052\206\110\206\367\015
++\001\011\001\026\026\150\157\163\164\155\141\163\164\145\162\100
++\163\160\151\055\151\156\143\056\157\162\147\202\011\000\350\216
++\266\311\370\052\024\050\060\017\006\003\125\035\023\001\001\377
++\004\005\060\003\001\001\377\060\021\006\011\140\206\110\001\206
++\370\102\001\001\004\004\003\002\000\007\060\011\006\003\125\035
++\022\004\002\060\000\060\056\006\011\140\206\110\001\206\370\102
++\001\015\004\041\026\037\123\157\146\164\167\141\162\145\040\151
++\156\040\164\150\145\040\120\165\142\154\151\143\040\111\156\164
++\145\162\145\163\164\060\060\006\011\140\206\110\001\206\370\102
++\001\004\004\043\026\041\150\164\164\160\163\072\057\057\143\141
++\056\163\160\151\055\151\156\143\056\157\162\147\057\143\141\055
++\143\162\154\056\160\145\155\060\062\006\011\140\206\110\001\206
++\370\102\001\003\004\045\026\043\150\164\164\160\163\072\057\057
++\143\141\056\163\160\151\055\151\156\143\056\157\162\147\057\143
++\145\162\164\055\143\162\154\056\160\145\155\060\041\006\003\125
++\035\021\004\032\060\030\201\026\150\157\163\164\155\141\163\164
++\145\162\100\163\160\151\055\151\156\143\056\157\162\147\060\016
++\006\003\125\035\017\001\001\377\004\004\003\002\001\006\060\015
++\006\011\052\206\110\206\367\015\001\001\005\005\000\003\202\002
++\001\000\264\315\275\340\271\352\262\003\053\176\062\351\336\162
++\077\311\113\202\136\235\342\257\125\011\242\014\124\350\317\030
++\074\050\040\035\251\273\003\002\057\122\071\042\371\027\317\255
++\147\220\263\003\177\330\025\343\153\176\273\233\126\001\257\065
++\324\332\271\307\147\027\233\324\325\016\067\263\040\101\056\014
++\001\304\133\371\145\076\302\141\350\322\360\152\225\160\303\306
++\157\325\065\244\254\131\162\341\211\337\241\240\235\044\275\051
++\171\351\141\052\331\323\036\311\106\244\010\170\101\222\162\017
++\253\024\165\355\011\360\242\360\134\357\303\012\142\040\267\302
++\050\146\256\114\057\056\217\105\143\046\226\360\356\061\346\213
++\125\233\252\072\371\202\071\035\210\074\342\007\165\032\341\017
++\261\060\274\161\062\322\072\376\372\241\211\363\103\054\326\162
++\304\171\247\025\110\005\300\330\055\162\002\343\313\075\026\152
++\272\311\270\021\020\342\111\205\314\226\107\140\005\045\056\357
++\165\131\063\365\107\031\026\357\332\154\137\007\310\246\120\266
++\035\313\146\064\045\374\146\203\353\305\266\060\101\370\106\104
++\142\250\301\014\124\346\352\114\132\050\346\256\306\267\376\177
++\073\226\250\056\356\307\150\076\335\000\075\051\257\052\143\253
++\137\356\111\052\055\305\334\373\321\306\323\321\227\126\122\206
++\266\224\353\324\140\121\267\374\036\233\314\002\233\324\037\217
++\371\112\217\266\056\050\073\027\314\305\246\005\343\322\323\265
++\306\003\311\341\110\102\233\313\077\344\027\340\376\015\001\225
++\011\272\270\015\161\344\011\160\167\102\330\115\341\102\251\140
++\203\327\027\211\103\322\324\335\247\030\266\253\324\044\045\207
++\265\324\342\374\056\042\151\275\255\150\054\377\162\265\230\252
++\006\234\347\052\152\270\241\223\166\316\260\363\177\234\341\340
++\117\270\330\206\106\245\063\002\054\045\141\067\052\222\310\254
++\201\164\150\143\207\063\166\275\005\177\136\325\325\002\155\275
++\257\377\052\132\252\111\354\230\171\107\123\221\366\016\064\132
++\311\245\306\353\262\343\305\254\266\240\160\065\273\310\121\151
++\320\362\265\242\062\156\274\077\240\067\071\174\161\066\246\005
++\337\014\022\344\026\247\305\326\313\143\243\225\160\077\346\004
++\243\140
++END
++
++# Trust for Certificate "Software in the Public Interest, Inc. Root CA (2008)"
++CKA_CLASS CK_OBJECT_CLASS CKO_NETSCAPE_TRUST
++CKA_TOKEN CK_BBOOL CK_TRUE
++CKA_PRIVATE CK_BBOOL CK_FALSE
++CKA_MODIFIABLE CK_BBOOL CK_FALSE
++CKA_LABEL UTF8 "Software in the Public Interest, Inc. Root CA (2008)"
++CKA_CERT_SHA1_HASH MULTILINE_OCTAL
++\257\160\210\103\203\202\002\025\315\141\306\274\354\375\067\044
++\251\220\103\034
++END
++CKA_CERT_MD5_HASH MULTILINE_OCTAL
++\052\107\237\140\273\203\164\157\001\003\327\013\015\366\015\170
++END
++CKA_ISSUER MULTILINE_OCTAL
++\060\201\274\061\013\060\011\006\003\125\004\006\023\002\125\123
++\061\020\060\016\006\003\125\004\010\023\007\111\156\144\151\141
++\156\141\061\025\060\023\006\003\125\004\007\023\014\111\156\144
++\151\141\156\141\160\157\154\151\163\061\050\060\046\006\003\125
++\004\012\023\037\123\157\146\164\167\141\162\145\040\151\156\040
++\164\150\145\040\120\165\142\154\151\143\040\111\156\164\145\162
++\145\163\164\061\023\060\021\006\003\125\004\013\023\012\150\157
++\163\164\155\141\163\164\145\162\061\036\060\034\006\003\125\004
++\003\023\025\103\145\162\164\151\146\151\143\141\164\145\040\101
++\165\164\150\157\162\151\164\171\061\045\060\043\006\011\052\206
++\110\206\367\015\001\011\001\026\026\150\157\163\164\155\141\163
++\164\145\162\100\163\160\151\055\151\156\143\056\157\162\147
++END
++CKA_SERIAL_NUMBER MULTILINE_OCTAL
++\002\011\000\350\216\266\311\370\052\024\050
++END
++CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR
++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
diff --git a/main/nss/nss-config.in b/main/nss/nss-config.in
new file mode 100644
index 0000000000..f8f893e71a
--- /dev/null
+++ b/main/nss/nss-config.in
@@ -0,0 +1,145 @@
+#!/bin/sh
+
+prefix=@prefix@
+
+major_version=@MOD_MAJOR_VERSION@
+minor_version=@MOD_MINOR_VERSION@
+patch_version=@MOD_PATCH_VERSION@
+
+usage()
+{
+ cat <<EOF
+Usage: nss-config [OPTIONS] [LIBRARIES]
+Options:
+ [--prefix[=DIR]]
+ [--exec-prefix[=DIR]]
+ [--includedir[=DIR]]
+ [--libdir[=DIR]]
+ [--version]
+ [--libs]
+ [--cflags]
+Dynamic Libraries:
+ nss
+ nssutil
+ ssl
+ smime
+EOF
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+lib_ssl=yes
+lib_smime=yes
+lib_nss=yes
+lib_nssutil=yes
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --prefix=*)
+ prefix=$optarg
+ ;;
+ --prefix)
+ echo_prefix=yes
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ ;;
+ --exec-prefix)
+ echo_exec_prefix=yes
+ ;;
+ --includedir=*)
+ includedir=$optarg
+ ;;
+ --includedir)
+ echo_includedir=yes
+ ;;
+ --libdir=*)
+ libdir=$optarg
+ ;;
+ --libdir)
+ echo_libdir=yes
+ ;;
+ --version)
+ echo ${major_version}.${minor_version}.${patch_version}
+ ;;
+ --cflags)
+ echo_cflags=yes
+ ;;
+ --libs)
+ echo_libs=yes
+ ;;
+ ssl)
+ lib_ssl=yes
+ ;;
+ smime)
+ lib_smime=yes
+ ;;
+ nss)
+ lib_nss=yes
+ ;;
+ nssutil)
+ lib_nssutil=yes
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+
+# Set variables that may be dependent upon other variables
+if test -z "$exec_prefix"; then
+ exec_prefix=`pkg-config --variable=exec_prefix nss`
+fi
+if test -z "$includedir"; then
+ includedir=`pkg-config --variable=includedir nss`
+fi
+if test -z "$libdir"; then
+ libdir=`pkg-config --variable=libdir nss`
+fi
+
+if test "$echo_prefix" = "yes"; then
+ echo $prefix
+fi
+
+if test "$echo_exec_prefix" = "yes"; then
+ echo $exec_prefix
+fi
+
+if test "$echo_includedir" = "yes"; then
+ echo $includedir
+fi
+
+if test "$echo_libdir" = "yes"; then
+ echo $libdir
+fi
+
+if test "$echo_cflags" = "yes"; then
+ echo -I$includedir
+fi
+
+if test "$echo_libs" = "yes"; then
+ libdirs="-Wl,-rpath-link,$libdir -L$libdir"
+ if test -n "$lib_ssl"; then
+ libdirs="$libdirs -lssl${major_version}"
+ fi
+ if test -n "$lib_smime"; then
+ libdirs="$libdirs -lsmime${major_version}"
+ fi
+ if test -n "$lib_nss"; then
+ libdirs="$libdirs -lnss${major_version}"
+ fi
+ if test -n "$lib_nssutil"; then
+ libdirs="$libdirs -lnssutil${major_version}"
+ fi
+ echo $libdirs
+fi
+
diff --git a/main/nss/nss-no-rpath.patch b/main/nss/nss-no-rpath.patch
new file mode 100644
index 0000000000..35ea573154
--- /dev/null
+++ b/main/nss/nss-no-rpath.patch
@@ -0,0 +1,14 @@
+--- ./mozilla/security/nss/cmd/platlibs.mk.withrpath 2007-02-19 07:17:06.000000000 +0100
++++ ./mozilla/security/nss/cmd/platlibs.mk 2007-02-19 07:18:07.000000000 +0100
+@@ -52,9 +52,9 @@
+
+ ifeq ($(OS_ARCH), Linux)
+ ifeq ($(USE_64), 1)
+-EXTRA_SHARED_LIBS += -Wl,-rpath,'$$ORIGIN/../lib64:$$ORIGIN/../lib'
++#EXTRA_SHARED_LIBS += -Wl,-rpath,'$$ORIGIN/../lib64:$$ORIGIN/../lib'
+ else
+-EXTRA_SHARED_LIBS += -Wl,-rpath,'$$ORIGIN/../lib'
++#EXTRA_SHARED_LIBS += -Wl,-rpath,'$$ORIGIN/../lib'
+ endif
+ endif
+
diff --git a/main/nss/nss.pc.in b/main/nss/nss.pc.in
new file mode 100644
index 0000000000..d47b9e1469
--- /dev/null
+++ b/main/nss/nss.pc.in
@@ -0,0 +1,11 @@
+prefix=%prefix%
+exec_prefix=%exec_prefix%
+libdir=%libdir%
+includedir=%includedir%
+
+Name: NSS
+Description: Network Security Services
+Version: %NSS_VERSION%
+Requires: nspr >= %NSPR_VERSION%
+Libs: -lssl3 -lsmime3 -lnss3 -lnssutil3
+Cflags: -I${includedir}
diff --git a/main/nss/ssl-renegotiate-transitional.patch b/main/nss/ssl-renegotiate-transitional.patch
new file mode 100644
index 0000000000..f457c55518
--- /dev/null
+++ b/main/nss/ssl-renegotiate-transitional.patch
@@ -0,0 +1,21 @@
+Enable transitional scheme for ssl renegotiation:
+
+(from mozilla/security/nss/lib/ssl/ssl.h)
+Disallow unsafe renegotiation in server sockets only, but allow clients
+to continue to renegotiate with vulnerable servers.
+This value should only be used during the transition period when few
+servers have been upgraded.
+
+diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c
+index f1d1921..c074360 100644
+--- a/mozilla/security/nss/lib/ssl/sslsock.c
++++ b/mozilla/security/nss/lib/ssl/sslsock.c
+@@ -181,7 +181,7 @@ static sslOptions ssl_defaults = {
+ PR_FALSE, /* noLocks */
+ PR_FALSE, /* enableSessionTickets */
+ PR_FALSE, /* enableDeflate */
+- 2, /* enableRenegotiation (default: requires extension) */
++ 3, /* enableRenegotiation (default: transitional) */
+ PR_FALSE, /* requireSafeNegotiation */
+ };
+
diff --git a/main/ntfs-3g/APKBUILD b/main/ntfs-3g/APKBUILD
new file mode 100644
index 0000000000..29c32668fb
--- /dev/null
+++ b/main/ntfs-3g/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ntfs-3g
+pkgver=2011.4.12
+pkgrel=1
+pkgdesc="A userspace ntfs driver with write support"
+url="http://www.tuxera.com/community/ntfs-3g-download/"
+arch="all"
+license="GPL"
+depends=
+makedepends="attr-dev"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://tuxera.com/opensource/ntfs-3g_ntfsprogs-$pkgver.tgz"
+
+_builddir="$srcdir"/ntfs-3g_ntfsprogs-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" LDCONFIG=: install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="9c4ce318373b15332239a77a9d2a39fe ntfs-3g_ntfsprogs-2011.4.12.tgz"
diff --git a/main/ntfs-3g/nocxx.patch b/main/ntfs-3g/nocxx.patch
new file mode 100644
index 0000000000..beb1ab9006
--- /dev/null
+++ b/main/ntfs-3g/nocxx.patch
@@ -0,0 +1,15 @@
+--- a/configure 2004-12-07 21:34:23.205172545 +0000
++++ b/configure 2004-12-07 21:37:17.726654782 +0000
+@@ -5148,10 +5148,8 @@
+ :
+ else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&5
+-echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&2;}
+- { (exit 1); exit 1; }; }
++See \`config.log' for more details." >&5;}
++ { echo "C++ sucks, ignoring ..." >&5; }; }
+ fi
+
+ ac_ext=cc
diff --git a/main/ntop/APKBUILD b/main/ntop/APKBUILD
new file mode 100644
index 0000000000..caec386033
--- /dev/null
+++ b/main/ntop/APKBUILD
@@ -0,0 +1,55 @@
+# Contributor:
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=ntop
+pkgver=4.0.3
+pkgrel=2
+pkgdesc="Network traffic probe"
+url="http://www.ntop.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="autoconf automake freetype-dev gdbm-dev geoip-dev libart-lgpl-dev
+ libevent-dev libpcap-dev libpng-dev libtool libxml2-dev lua-dev
+ openssl-dev python-dev rrdtool-dev wget zlib-dev"
+install="$pkgname.post-install"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/project/$pkgname/$pkgname/Stable/$pkgname-$pkgver.tgz
+ ntop.initd
+ ntop.confd
+ ntop-update-geoip-db"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ ./autogen.sh --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-snmp
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ install -m755 -D "$srcdir"/ntop-update-geoip-db \
+ "$pkgdir"/usr/bin/ntop-update-geoip-db
+ # ntop internal db dir
+ mkdir -p $pkgdir/var/lib/ntop
+}
+
+md5sums="f064393a2090e5bda102cd49c2707789 ntop-4.0.3.tgz
+7fd4edf07305e0f52867256c946a5747 ntop.initd
+1303915a8435560acf27748ea0cea484 ntop.confd
+080de490aeed421775e6f2472d86cb94 ntop-update-geoip-db"
diff --git a/main/ntop/ntop-update-geoip-db b/main/ntop/ntop-update-geoip-db
new file mode 100644
index 0000000000..2bf3faaf68
--- /dev/null
+++ b/main/ntop/ntop-update-geoip-db
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+BASE_URL=http://geolite.maxmind.com/download/geoip/database
+
+echo "Updating NTOP GeoIP databases..."
+
+cd /var/lib/ntop || exit
+
+for u in asnum/GeoIPASNum.dat.gz GeoLiteCity.dat.gz ; do
+ FILE_GZ=${u#*/}
+ FILE=${FILE_GZ%.gz}
+ wget -nv -O ${FILE_GZ} ${BASE_URL}/${u} &&
+ gunzip < ${FILE_GZ} > .${FILE} &&
+ mv -f .${FILE} ${FILE} &&
+ rm -f ${FILE_GZ} ||
+ exit
+done
+
+/etc/init.d/ntop --quiet status && /etc/init.d/ntop restart
+
+echo "NTOP GeoIP databases were successfully updated"
diff --git a/main/ntop/ntop.confd b/main/ntop/ntop.confd
new file mode 100644
index 0000000000..352a26fa9b
--- /dev/null
+++ b/main/ntop/ntop.confd
@@ -0,0 +1,9 @@
+# Config file for /etc/init.d/ntop
+
+# Set preferred options here
+#NTOP_OPTS="--http-server 3000 --https-server 0 --interface eth0"
+
+# suggestions from bug #136983 (use it in case you experience ntop hangs)
+#NTOP_OPTS="u ntop -P /var/lib/ntop --disable-schedyield --http-server 3000 --https-server 3001"
+
+NTOP_OPTS="-u ntop -P /var/lib/ntop"
diff --git a/main/ntop/ntop.initd b/main/ntop/ntop.initd
new file mode 100644
index 0000000000..ffc2923790
--- /dev/null
+++ b/main/ntop/ntop.initd
@@ -0,0 +1,30 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+depend() {
+ need net
+}
+
+checkconfig() {
+ if [ ! -e /var/lib/ntop/ntop_pw.db ]; then
+ eerror "You need to set a password first by running"
+ eerror "ntop --set-admin-password"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ntop"
+ export LC_ALL=C # apparently doesn't work with some locales (#191576 and #205382)
+ export GDFONTPATH=/usr/share/fonts/corefonts # apparently the only font that works (#231705)
+ start-stop-daemon --start --exec /usr/bin/ntop -- -d -L ${NTOP_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ntop"
+ start-stop-daemon --stop --retry 30 --pidfile /var/run/ntop.pid
+ eend $?
+}
diff --git a/main/ntop/ntop.post-install b/main/ntop/ntop.post-install
new file mode 100755
index 0000000000..ede8a22f3c
--- /dev/null
+++ b/main/ntop/ntop.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+adduser -h /var/lib/ntop -s /bin/false -S -H -D ntop &>/dev/null
+chown ntop /var/lib/ntop
diff --git a/main/obex-data-server/APKBUILD b/main/obex-data-server/APKBUILD
new file mode 100644
index 0000000000..fc8464c745
--- /dev/null
+++ b/main/obex-data-server/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=obex-data-server
+pkgver=0.4.6
+pkgrel=0
+pkgdesc="D-Bus service for Obex access"
+url="http://wiki.muiline.com/obex-data-server"
+license="GPLv2+"
+arch="all"
+depends="!obexd"
+subpackages="$pkgname-doc"
+makedepends="dbus-glib-dev openobex-dev gtk+-dev libusb-compat-dev bluez-dev"
+source="http://tadas.dailyda.com/software/obex-data-server-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build ()
+{
+ cd $srcdir/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-bip=gdk-pixbuf
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="961ca5db6fe9c97024e133cc6203cc4d obex-data-server-0.4.6.tar.gz"
diff --git a/main/obexd/APKBUILD b/main/obexd/APKBUILD
new file mode 100644
index 0000000000..5e6087284a
--- /dev/null
+++ b/main/obexd/APKBUILD
@@ -0,0 +1,44 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=obexd
+pkgver=0.40
+pkgrel=1
+pkgdesc="D-Bus service for Obex Server"
+url="http://www.bluez.org/"
+arch="all"
+license="GPL2"
+depends="!obex-data-server"
+subpackages="$pkgname-client"
+makedepends="dbus-glib-dev openobex-dev glib-dev bluez-dev libical-dev"
+source="http://www.kernel.org/pub/linux/bluetooth/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --libexecdir=/usr/lib/obexd \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+_mv_files() {
+ local i
+ for i in "$@"; do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i || return 1
+ done
+}
+
+client() {
+ pkgdesc="D-Bus service for Obex Client access"
+ depends=
+ cd "$pkgdir"
+ _mv_files usr/lib/obexd/obex-client \
+ usr/share/dbus-*/services/obex-client.service
+}
+
+md5sums="f303592b7664b246965c1d6e9361c919 obexd-0.40.tar.bz2"
diff --git a/main/oidentd/APKBUILD b/main/oidentd/APKBUILD
new file mode 100644
index 0000000000..f7d9ca7522
--- /dev/null
+++ b/main/oidentd/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=oidentd
+pkgver=2.0.8
+pkgrel=3
+pkgdesc="Configurable IDENT server that supports NAT/IP masq."
+url="http://dev.ojnk.net/"
+arch="all"
+license="GPL"
+depends=""
+makedepends=""
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/ojnk/$pkgname-$pkgver.tar.gz
+oidentd.conf
+oidentd.initd
+oidentd.confd"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ install -D -m755 "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -D -m644 "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ install -D -m644 "$srcdir"/$pkgname.conf "$pkgdir"/etc/$pkgname.conf
+
+}
+
+md5sums="c3d9a56255819ef8904b867284386911 oidentd-2.0.8.tar.gz
+d9c40e4d6a0bde685a359ad49b4eada2 oidentd.conf
+96c45c9956d357d4ca9f5d474d58451b oidentd.initd
+05a43d3987754f179f4e31bbe61ff315 oidentd.confd"
diff --git a/main/oidentd/oidentd.conf b/main/oidentd/oidentd.conf
new file mode 100644
index 0000000000..03b28d8278
--- /dev/null
+++ b/main/oidentd/oidentd.conf
@@ -0,0 +1,22 @@
+# Configuration for oidentd
+# see oidentd.conf(5)
+#
+default {
+ default {
+ deny spoof
+ deny spoof_all
+ deny spoof_privport
+ allow random
+ allow random_numeric
+ allow numeric
+ deny hide
+ }
+}
+
+# you may want to hide root connections
+#user "root" {
+# default {
+# force reply "UNKNOWN"
+# }
+#}
+
diff --git a/main/oidentd/oidentd.confd b/main/oidentd/oidentd.confd
new file mode 100644
index 0000000000..3116889e67
--- /dev/null
+++ b/main/oidentd/oidentd.confd
@@ -0,0 +1,4 @@
+# oidentd start-up options
+USER="nobody"
+GROUP="nobody"
+OPTIONS=""
diff --git a/main/oidentd/oidentd.initd b/main/oidentd/oidentd.initd
new file mode 100644
index 0000000000..f718976f51
--- /dev/null
+++ b/main/oidentd/oidentd.initd
@@ -0,0 +1,43 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-misc/oidentd/files/oidentd-2.0.7-init,v 1.4 2007/10/24 11:38:14 uberlord Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+check_config() {
+ if [ -z "${USER}" ]
+ then
+ eerror "Please set \$USER in /etc/conf.d/oidentd!"
+ return 1
+ fi
+ if [ -z "${GROUP}" ]
+ then
+ eerror "Please set \$GROUP in /etc/conf.d/oidentd!"
+ return 1
+ fi
+
+ if [ "$(sysctl -n security.bsd.see_other_uids 2>/dev/null)" = "0" ]; then
+ eerror "${SVCNAME} cannot work if the sysctl security.bsd.see_other_uids is 0"
+ return 1
+ fi
+}
+
+
+start() {
+ check_config || return 1
+ ebegin "Starting oidentd"
+ OPTIONS="${OPTIONS} -u ${USER} -g ${GROUP}"
+ start-stop-daemon --start --quiet --exec /usr/sbin/oidentd -- $OPTIONS
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping oidentd"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/oidentd
+ eend $?
+}
+
diff --git a/main/open-iscsi-grsec/APKBUILD b/main/open-iscsi-grsec/APKBUILD
new file mode 100644
index 0000000000..611761be9e
--- /dev/null
+++ b/main/open-iscsi-grsec/APKBUILD
@@ -0,0 +1,54 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+
+_flavor=grsec
+_realname=open-iscsi
+_realver=2.0-872
+# source the kernel version
+if [ -f ../../main/linux-$_flavor/APKBUILD ]; then
+ . ../../main/linux-$_flavor/APKBUILD
+fi
+_kver=$pkgver
+_kernelver=$pkgver-r$pkgrel
+_abi_release=$pkgver-${_flavor}
+_kpkgrel=$pkgrel
+_ksrc=/usr/src/linux-headers-${_abi_release}
+
+_iscsiver=$_realver
+
+pkgname=${_realname}-${_flavor}
+pkgver=$_kver
+_mypkgrel=0
+pkgrel=$(($_kpkgrel + $_mypkgrel))
+pkgdesc="$_flavor kernel modules for open-iscsi $_iscsiver"
+url="http://www.open-iscsi.org"
+arch="all"
+license="GPL-2"
+depends="linux-${_flavor}=${_kernelver}"
+install=
+makedepends="linux-${_flavor}-dev=${_kernelver}"
+subpackages=
+source="http://www.open-iscsi.org/bits/$_realname-$_realver.tar.gz
+ Makefile.kernel.patch"
+
+_builddir="$srcdir/$_realname-$_realver"
+
+prepare() {
+ cd "$_builddir"
+ patch -p2 < "$srcdir"/Makefile.kernel.patch || return 1
+}
+
+build() {
+ cd "$_builddir"
+ unset ARCH
+ make KSRC="$_ksrc" kernel || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make KSRC="$_ksrc" DESTDIR="$pkgdir" \
+ INSTALL_MOD_DIR="extra/drivers/scsi" \
+ install_kernel
+}
+
+md5sums="b4df94f08c241352bb964043b3e44779 open-iscsi-2.0-872.tar.gz
+f0c851e9190c859987d9f561d6eeb7f5 Makefile.kernel.patch"
diff --git a/main/open-iscsi-grsec/Makefile.kernel.patch b/main/open-iscsi-grsec/Makefile.kernel.patch
new file mode 100644
index 0000000000..23ef208332
--- /dev/null
+++ b/main/open-iscsi-grsec/Makefile.kernel.patch
@@ -0,0 +1,11 @@
+--- src/open-iscsi-2.0-871/kernel/Makefile
++++ Makefile
+@@ -102,6 +102,8 @@
+
+ linux_2_6_30: $(unpatch_code)
+
++linux_2_6_38: $(unpatch_code)
++
+
+ do_unpatch_code:
+ echo "Un-patching source code for use with linux-2.6.14 and up ..."
diff --git a/main/open-iscsi/APKBUILD b/main/open-iscsi/APKBUILD
new file mode 100644
index 0000000000..a06795af2d
--- /dev/null
+++ b/main/open-iscsi/APKBUILD
@@ -0,0 +1,44 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=open-iscsi
+pkgver=2.0.872
+_realver=${pkgver%.*}-${pkgver##*.}
+pkgrel=2
+pkgdesc="High performance, transport independent, multi-platform iSCSI initiator"
+url="http://www.open-iscsi.org"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="openssl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://kernel.org/pub/linux/kernel/people/mnc/open-iscsi/releases/open-iscsi-$_realver.tar.gz
+ iscsid.initd
+ iscsid.confd"
+
+_builddir="$srcdir"/$pkgname-$_realver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make user || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install_user
+ mkdir -p $pkgdir/usr/bin
+ mkdir -p $pkgdir/usr/sbin
+ mv $pkgdir/sbin/iscsi-iname $pkgdir/usr/bin
+ mv $pkgdir/sbin/iscsi_discovery $pkgdir/usr/bin
+ mv $pkgdir/sbin/iscsiadm $pkgdir/usr/bin
+ mv $pkgdir/sbin/iscsid $pkgdir/usr/sbin
+ install -Dm755 "$srcdir"/iscsid.initd "$pkgdir"/etc/init.d/iscsid
+ install -Dm644 "$srcdir"/iscsid.confd "$pkgdir"/etc/conf.d/iscsid
+}
+
+md5sums="b4df94f08c241352bb964043b3e44779 open-iscsi-2.0-872.tar.gz
+95cc696720bb9f267f38ac69d5c2e07c iscsid.initd
+b762b687d4628791b4362df22cf22d34 iscsid.confd"
diff --git a/main/open-iscsi/iscsid.confd b/main/open-iscsi/iscsid.confd
new file mode 100644
index 0000000000..1c4cc40542
--- /dev/null
+++ b/main/open-iscsi/iscsid.confd
@@ -0,0 +1,13 @@
+# /etc/conf.d/iscsid
+
+# config file to use
+CONFIG_FILE=/etc/iscsi/iscsid.conf
+
+# you need to specify an initiatorname in the file
+INITIATORNAME_FILE=/etc/iscsi/initiatorname.iscsi
+
+# options to pass to iscsid
+OPTS="-i ${INITIATORNAME_FILE}"
+
+# Start automatic targets when iscsid is started
+AUTOSTARTTARGETS="yes"
diff --git a/main/open-iscsi/iscsid.initd b/main/open-iscsi/iscsid.initd
new file mode 100644
index 0000000000..fdc19c5cf7
--- /dev/null
+++ b/main/open-iscsi/iscsid.initd
@@ -0,0 +1,124 @@
+#!/sbin/runscript
+
+opts="${opts} starttargets stoptargets restarttargets"
+
+depend() {
+ after modules
+ use net
+}
+
+checkconfig() {
+ if [ ! -e /etc/conf.d/${SVCNAME} ]; then
+ eerror "Config file /etc/conf.d/${SVCNAME} does not exist!"
+ return 1
+ fi
+ if [ ! -e "${CONFIG_FILE}" ]; then
+ eerror "Config file ${CONFIG_FILE} does not exist!"
+ return 1
+ fi
+ if [ ! -e ${INITIATORNAME_FILE} ] || [ ! "$(grep "^InitiatorName=iqn\." ${INITIATORNAME_FILE})" ]; then
+ ewarn "${INITIATORNAME_FILE} should contain a string with your initiatior name."
+ IQN=iqn.$(date +%Y-%m).$(hostname -f | awk 'BEGIN { FS=".";}{x=NF; while (x>0) {printf $x ;x--; if (x>0) printf ".";} print ""}'):openiscsi
+ IQN=${IQN}-$(echo ${RANDOM}${RANDOM}${RANDOM}${RANDOM}${RANDOM} | md5sum | sed -e "s/\(.*\) -/\1/g" -e 's/ //g')
+ ebegin "Creating InitiatorName ${IQN} in ${INITIATORNAME_FILE}"
+ echo "InitiatorName=${IQN}" >> "${INITIATORNAME_FILE}"
+ eend $?
+ fi
+}
+
+do_modules() {
+ msg="$1"
+ shift
+ modules="${1}"
+ shift
+ modopts="$@"
+ for m in ${modules}
+ do
+ if [ -n "$(find /lib/modules/`uname -r` | grep ${m})" ]
+ then
+ ebegin "${msg} ${m}"
+ modprobe ${modopts} ${m}
+ ret=$?
+ eend ${ret}
+ if [ ${ret} -ne 0 ]; then
+ return ${ret}
+ fi
+ else
+ ebegin "${msg} ${m}: not found"
+ return 1
+ fi
+ done
+ return 0
+}
+
+start() {
+ ebegin "Checking open-iSCSI configuration"
+ checkconfig
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ eend 1
+ return 1
+ fi
+ ebegin "Loading iSCSI modules"
+ do_modules 'Loading' 'libiscsi scsi_transport_iscsi iscsi_tcp'
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ eend 1
+ return 1
+ fi
+
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start --quiet --exec /usr/sbin/iscsid -- ${OPTS}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ eend $?
+ return $?
+ fi
+
+ # Start automatic targets when iscsid is started
+ if [ "${AUTOSTARTTARGETS}" = "yes" ]; then
+ starttargets
+ return $?
+ fi
+ return 0
+}
+
+stop() {
+ local ret=
+ stoptargets
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --signal HUP --stop --quiet --exec /usr/sbin/iscsid #--pidfile $PID_FILE
+ ret=$?
+ eend $ret
+
+ # ugly, but pid file is not removed by iscsid
+ rm -f $PID_FILE
+ return $ret
+}
+
+starttargets() {
+ ebegin "Setting up iSCSI targets"
+ /usr/bin/iscsiadm -m node --loginall=automatic
+ ret=$?
+ eend $ret
+ return $ret
+}
+
+stoptargets() {
+ ebegin "Disconnecting iSCSI targets"
+ sync
+ /usr/bin/iscsiadm -m node --logoutall=all
+ ret=$?
+ eend $ret
+ return $ret
+}
+
+restarttargets() {
+ stoptargets
+ starttargets
+}
+
+status() {
+ ebegin "Showing current active iSCSI sessions"
+ /usr/bin/iscsiadm -m session
+}
diff --git a/main/open-vm-tools-grsec/APKBUILD b/main/open-vm-tools-grsec/APKBUILD
new file mode 100644
index 0000000000..7bd425a21a
--- /dev/null
+++ b/main/open-vm-tools-grsec/APKBUILD
@@ -0,0 +1,64 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+_flavor=grsec
+_realname=open-vm-tools
+_realver=2011.02.23
+_realsubver=368700
+
+# source the kernel version
+if [ -f ../../main/linux-${_flavor}/APKBUILD ]; then
+ . ../../main/linux-${_flavor}/APKBUILD
+fi
+
+_kver=$pkgver
+_kernelver="$pkgver-r$pkgrel"
+_abi_release=${pkgver}-${_flavor}
+_kpkgrel=$pkgrel
+pkgname="$_realname-$_flavor"
+pkgver=$_kver
+_mypkgrel=1
+pkgrel=$(($_kpkgrel + $_mypkgrel))
+
+pkgdesc="The Open Virtual Machine Tools are the open source implementation of VMware Tools."
+url="http://open-vm-tools.sourceforge.net/"
+arch="all"
+license="LGPL"
+subpackages=""
+depends="linux-${_flavor}=${_kernelver}"
+makedepends="glib-dev gettext-dev linux-${_flavor}-dev=${_kernelver}"
+source="http://downloads.sourceforge.net/open-vm-tools/open-vm-tools-$_realver-$_realsubver.tar.gz
+ vmware-modules.initd
+ "
+
+_builddir="$srcdir/$_realname-$_realver-$_realsubver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --without-pam \
+ --without-x \
+ --without-dnet \
+ --without-icu \
+ --without-procps \
+ --with-kernel-release="$_abi_release" \
+ || return 1
+ cd "$_builddir"/modules
+ make -j1 modules || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -D -m755 "$srcdir"/vmware-modules.initd \
+ "$pkgdir"/etc/init.d/vmware-modules || return 1
+ mkdir -p $pkgdir/lib/modules/$_abi_release/misc/
+ cd "$_builddir"/modules
+ for module in `find -type f -name '*.ko'`; do
+ install -D -m644 $module "$pkgdir/lib/modules/$_abi_release/misc/"
+ done
+}
+
+md5sums="488601e384daeab2c6ffd81e1a95cad7 open-vm-tools-2011.02.23-368700.tar.gz
+afba2c3487d0b12cee80eb2f04b05ba1 vmware-modules.initd"
diff --git a/main/open-vm-tools-grsec/vmware-modules.initd b/main/open-vm-tools-grsec/vmware-modules.initd
new file mode 100644
index 0000000000..942f4504e6
--- /dev/null
+++ b/main/open-vm-tools-grsec/vmware-modules.initd
@@ -0,0 +1,25 @@
+#!/sbin/runscript
+
+MODULES="vmblock vmci vmhgfs vmsync vmxnet vsock vmw_balloon"
+
+depend() {
+ before open-vm-tools
+}
+
+
+start() {
+ ebegin "Loading VMware kernel modules"
+ for mod in $MODULES; do
+ modprobe -q $mod
+ done
+ eend $?
+}
+
+stop() {
+ ebegin "Unloading VMware kernel modules"
+ for mod in $MODULES; do
+ rmmod $mod
+ done
+ eend $?
+}
+
diff --git a/main/open-vm-tools-vserver/APKBUILD b/main/open-vm-tools-vserver/APKBUILD
new file mode 100644
index 0000000000..2ecd0e84b4
--- /dev/null
+++ b/main/open-vm-tools-vserver/APKBUILD
@@ -0,0 +1,63 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+_flavor=vserver
+_realname=open-vm-tools
+_realver=2011.04.25
+_realsubver=402641
+
+# source the kernel version
+if [ -f ../../main/linux-${_flavor}/APKBUILD ]; then
+ . ../../main/linux-${_flavor}/APKBUILD
+fi
+
+_kver=$pkgver
+_kernelver="$pkgver-r$pkgrel"
+_kpkgrel=$pkgrel
+pkgname="$_realname-$_flavor"
+pkgver=$_kver
+_mypkgrel=0
+pkgrel=$(($_kpkgrel + $_mypkgrel))
+
+pkgdesc="The Open Virtual Machine Tools are the open source implementation of VMware Tools."
+url="http://open-vm-tools.sourceforge.net/"
+arch="all"
+license="LGPL"
+subpackages=""
+depends="linux-${_flavor}=${_kernelver}"
+makedepends="glib-dev gettext-dev linux-${_flavor}-dev=${_kernelver}"
+source="http://downloads.sourceforge.net/open-vm-tools/open-vm-tools-$_realver-$_realsubver.tar.gz
+ vmware-modules.initd
+ "
+
+_builddir="$srcdir/$_realname-$_realver-$_realsubver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --without-pam \
+ --without-x \
+ --without-dnet \
+ --without-icu \
+ --without-procps \
+ --with-kernel-release="${_abi_release}" \
+ || return 1
+ cd "$_builddir"/modules
+ make -j1 modules || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -D -m755 "$srcdir"/vmware-modules.initd \
+ "$pkgdir"/etc/init.d/vmware-modules || return 1
+ mkdir -p $pkgdir/lib/modules/"${_abi_release}"/misc/
+ cd "$_builddir"/modules
+ for module in `find -type f -name '*.ko'`; do
+ install -D -m644 $module "$pkgdir/lib/modules/"${_abi_release}"/misc/"
+ done
+}
+
+md5sums="f6d87599523de31f02aaf229bf2ff08c open-vm-tools-2011.04.25-402641.tar.gz
+afba2c3487d0b12cee80eb2f04b05ba1 vmware-modules.initd"
diff --git a/main/open-vm-tools-vserver/vmware-modules.initd b/main/open-vm-tools-vserver/vmware-modules.initd
new file mode 100644
index 0000000000..942f4504e6
--- /dev/null
+++ b/main/open-vm-tools-vserver/vmware-modules.initd
@@ -0,0 +1,25 @@
+#!/sbin/runscript
+
+MODULES="vmblock vmci vmhgfs vmsync vmxnet vsock vmw_balloon"
+
+depend() {
+ before open-vm-tools
+}
+
+
+start() {
+ ebegin "Loading VMware kernel modules"
+ for mod in $MODULES; do
+ modprobe -q $mod
+ done
+ eend $?
+}
+
+stop() {
+ ebegin "Unloading VMware kernel modules"
+ for mod in $MODULES; do
+ rmmod $mod
+ done
+ eend $?
+}
+
diff --git a/main/open-vm-tools/APKBUILD b/main/open-vm-tools/APKBUILD
new file mode 100644
index 0000000000..d6e04a0656
--- /dev/null
+++ b/main/open-vm-tools/APKBUILD
@@ -0,0 +1,91 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=open-vm-tools
+pkgver=2011.05.27
+_pkgsubver=420096
+pkgrel=0
+pkgdesc="The Open Virtual Machine Tools are the open source implementation of VMware Tools."
+url="http://open-vm-tools.sourceforge.net/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-gtk $pkgname-dev"
+install="$pkgname.pre-install"
+makedepends="procps-dev libdnet-dev icu-dev glib-dev pkgconfig bash
+ libtirpc-dev rpcgen icu-dev automake autoconf
+ gtk+-dev libxext-dev libxinerama-dev libxtst-dev gtkmm-dev
+ libnotify-dev libxrandr-dev
+ "
+source="http://downloads.sourceforge.net/open-vm-tools/open-vm-tools-$pkgver-$_pkgsubver.tar.gz
+ getloadavg-uclibc.patch
+ codeset-uclibc.patch
+ ecvt.patch
+ iconv-uclibc.patch
+ libm.patch
+ open-vm-tools.initd
+ procmgrposix.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver-$_pkgsubver
+
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ [ -r "$i" ] || continue
+ patch -p1 -i "$i" || return 1
+ done
+
+ sed -i -e 's/__unused1/st_atim.tv_nsec/g' \
+ -e 's/__unused2/st_mtim.tv_nsec/g' \
+ -e 's/__unused3/st_ctim.tv_nsec/g' \
+ lib/file/filePosix.c lib/hgfsServer/hgfsServerLinux.c \
+ || return 1
+
+ # workaround automake-1.10 issue
+ # http://ramblingfoo.blogspot.com/2007/07/required-file-configrpath-not-found.html
+ touch config/config.rpath
+ aclocal -I m4 && autoconf && automake
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-unity \
+ --with-dnet \
+ --with-icu \
+ --with-procps \
+ --with-x \
+ --without-kernel-modules \
+ --without-pam \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install DESTDIR=$pkgdir || return 1
+ install -Dm755 "$srcdir"/open-vm-tools.initd \
+ "$pkgdir"/etc/init.d/open-vm-tools
+ find "$pkgdir" -name '*.la' -delete
+}
+
+gtk() {
+ pkgdesc="Xorg apps and plugins for open-vm-tools"
+ mkdir -p "$subpkgdir"/usr/bin \
+ "$subpkgdir"/usr/lib/open-vm-tools/plugins \
+ "$subpkgdir"/etc/
+ mv "$pkgdir"/usr/bin/vmware-toolbox \
+ "$pkgdir"/usr/bin/vmware-user-suid-wrapper \
+ "$subpkgdir"/usr/bin/
+ mv "$pkgdir"/etc/xdg "$subpkgdir"/etc/
+ mv "$pkgdir"/usr/lib/open-vm-tools/plugins/vmusr \
+ "$subpkgdir"/usr/lib/open-vm-tools/plugins/
+}
+
+md5sums="3e43d4857d412d02115e69db193830b5 open-vm-tools-2011.05.27-420096.tar.gz
+49e2e394d0b567fa71fcd295e96bc1c8 getloadavg-uclibc.patch
+82840b6bed002284b9bd2358707ee826 codeset-uclibc.patch
+840e4d6ff3f53fc22bdedf4d64aabc91 ecvt.patch
+89c7449323ddac4666b73a8467baf95a iconv-uclibc.patch
+7d02fc25aba5c248f3d98dac238f175b libm.patch
+c96644aa42d611fae853a3a2095efc47 open-vm-tools.initd
+7b833102a56009bdfc2fef2fb9ffa297 procmgrposix.patch"
diff --git a/main/open-vm-tools/codeset-uclibc.patch b/main/open-vm-tools/codeset-uclibc.patch
new file mode 100644
index 0000000000..b26df16611
--- /dev/null
+++ b/main/open-vm-tools/codeset-uclibc.patch
@@ -0,0 +1,20 @@
+--- ./lib/misc/codesetOld.c.orig
++++ ./lib/misc/codesetOld.c
+@@ -723,7 +723,7 @@
+ {
+ char *codeset;
+
+-#if defined(__linux__)
++#if defined(__linux__) && !defined(__UCLIBC__)
+
+ locale_t new = newlocale(LC_CTYPE_MASK, "", NULL);
+ if (!new) {
+@@ -739,7 +739,7 @@
+ codeset = Util_SafeStrdup(nl_langinfo_l(CODESET, new));
+ freelocale(new);
+
+-#elif defined(sun)
++#elif defined(sun) || defined(__UCLIBC__)
+
+ char *locale = setlocale(LC_CTYPE, NULL);
+ if (!setlocale(LC_CTYPE, "")) {
diff --git a/main/open-vm-tools/ecvt.patch b/main/open-vm-tools/ecvt.patch
new file mode 100644
index 0000000000..53e88e9989
--- /dev/null
+++ b/main/open-vm-tools/ecvt.patch
@@ -0,0 +1,205 @@
+commit e996e91ca5951c50769dcaa8e074daa973006849
+Author: Natanael Copa <ncopa@alpinelinux.org>
+Date: Thu Jul 8 06:39:36 2010 +0000
+
+ add ecvt() implementation
+
+diff --git a/lib/string/Makefile.am b/lib/string/Makefile.am
+index 1edab81..5f2e7ab 100644
+--- a/lib/string/Makefile.am
++++ b/lib/string/Makefile.am
+@@ -23,6 +23,7 @@ libString_la_SOURCES += bsd_vsnprintf.c
+ libString_la_SOURCES += bsd_vsnwprintf.c
+ libString_la_SOURCES += convertutf.c
+ libString_la_SOURCES += str.c
++libString_la_SOURCES += ecvt.c
+
+ AM_CFLAGS = @LIB_STRING_CPPFLAGS@
+
+diff --git a/lib/string/bsd_output_shared.c b/lib/string/bsd_output_shared.c
+index 3616947..321d6f1 100644
+--- a/lib/string/bsd_output_shared.c
++++ b/lib/string/bsd_output_shared.c
+@@ -64,6 +64,9 @@
+
+ #ifndef NO_FLOATING_POINT
+
++extern char* ecvt(double arg, int ndigits, int *decptp, int *signp);
++extern char* fcvt(double arg, int ndigits, int *decptp, int *signp);
++
+ /*
+ *-----------------------------------------------------------------------------
+ *
+diff --git a/lib/string/ecvt.c b/lib/string/ecvt.c
+new file mode 100644
+index 0000000..1979c3d
+--- /dev/null
++++ b/lib/string/ecvt.c
+@@ -0,0 +1,167 @@
++/*
++ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
++ *
++ * @APPLE_LICENSE_HEADER_START@
++ *
++ * This file contains Original Code and/or Modifications of Original Code
++ * as defined in and that are subject to the Apple Public Source License
++ * Version 2.0 (the 'License'). You may not use this file except in
++ * compliance with the License. Please obtain a copy of the License at
++ * http://www.opensource.apple.com/apsl/ and read it before using this
++ * file.
++ *
++ * The Original Code and all software distributed under the License are
++ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
++ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
++ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
++ * Please see the License for the specific language governing rights and
++ * limitations under the License.
++ *
++ * @APPLE_LICENSE_HEADER_END@
++ */
++/*
++ * ecvt converts to decimal
++ * the number of digits is specified by ndigit
++ * decptp is set to the position of the decimal point
++ * signp is set to 0 for positive, 1 for negative
++ */
++
++
++static double ecvt_rint(double x);
++
++static char *cvt();
++
++/* big enough to handle %.20f conversion of 1e308 */
++#define NDIG 350
++
++char*
++ecvt(arg, ndigits, decptp, signp)
++double arg;
++int ndigits, *decptp, *signp;
++{
++ return(cvt(arg, ndigits, decptp, signp, 1));
++}
++
++char*
++fcvt(arg, ndigits, decptp, signp)
++double arg;
++int ndigits, *decptp, *signp;
++{
++ return(cvt(arg, ndigits, decptp, signp, 0));
++}
++
++static char*
++cvt(arg, ndigits, decptp, signp, eflag)
++double arg;
++int ndigits, *decptp, *signp;
++int eflag;
++{
++ register int decpt;
++ double fi, fj;
++ register char *p, *p1;
++ static char buf[NDIG] = { 0 };
++ double modf();
++
++ if (ndigits < 0)
++ ndigits = 0;
++ if (ndigits >= NDIG-1)
++ ndigits = NDIG-2;
++
++ decpt = 0;
++ *signp = 0;
++ p = &buf[0];
++
++ if (arg == 0) {
++ *decptp = 0;
++ while (p < &buf[ndigits])
++ *p++ = '0';
++ *p = '\0';
++ return(buf);
++ } else if (arg < 0) {
++ *signp = 1;
++ arg = -arg;
++ }
++
++ arg = modf(arg, &fi);
++ p1 = &buf[NDIG];
++
++ /*
++ * Do integer part
++ */
++ if (fi != 0) {
++ while (fi != 0) {
++ fj = modf(fi/10, &fi);
++ /**--p1 = (int)((fj+.03)*10) + '0';*/
++ *--p1 = (int)ecvt_rint((fj)*10) + '0';
++ decpt++;
++ }
++ while (p1 < &buf[NDIG])
++ *p++ = *p1++;
++ } else if (arg > 0) {
++ while ((fj = arg*10) < 1) {
++ arg = fj;
++ decpt--;
++ }
++ }
++ *decptp = decpt;
++
++ /*
++ * do fraction part
++ * p pts to where fraction should be concatenated
++ * p1 is how far conversion must go to
++ */
++ p1 = &buf[ndigits];
++ if (eflag==0) {
++ /* fcvt must provide ndigits after decimal pt */
++ p1 += decpt;
++ /* if decpt was negative, we might done for fcvt */
++ if (p1 < &buf[0]) {
++ buf[0] = '\0';
++ return(buf);
++ }
++ }
++ while (p <= p1 && p < &buf[NDIG]) {
++ arg *= 10;
++ arg = modf(arg, &fj);
++ *p++ = (int)fj + '0';
++ }
++ /*
++ * if we converted all the way to the end of the
++ * buf, don't mess with rounding since there's nothing
++ * significant out here anyway
++ */
++ if (p1 >= &buf[NDIG]) {
++ buf[NDIG-1] = '\0';
++ return(buf);
++ }
++ /*
++ * round by adding 5 to last digit and propagating
++ * carries
++ */
++ p = p1;
++ *p1 += 5;
++ while (*p1 > '9') {
++ *p1 = '0';
++ if (p1 > buf)
++ ++*--p1;
++ else {
++ *p1 = '1';
++ (*decptp)++;
++ if (eflag == 0) {
++ if (p > buf)
++ *p = '0';
++ p++;
++ }
++ }
++ }
++ *p = '\0';
++ return(buf);
++}
++
++static double ecvt_rint(double x)
++{
++ asm("frndint" : "=t" (x) : "0" (x));
++ return(x);
++}
++
diff --git a/main/open-vm-tools/getloadavg-uclibc.patch b/main/open-vm-tools/getloadavg-uclibc.patch
new file mode 100644
index 0000000000..ccc4c388ed
--- /dev/null
+++ b/main/open-vm-tools/getloadavg-uclibc.patch
@@ -0,0 +1,19 @@
+--- a/lib/misc/hostinfoPosix.c
++++ b/lib/misc/hostinfoPosix.c
+@@ -1398,7 +1398,15 @@
+ float *avg1, // IN/OUT:
+ float *avg2) // IN/OUT:
+ {
+-#if defined(__linux__) || defined(__APPLE__)
++#if defined(__UCLIBC__)
++ FILE *f;
++ if ((f = fopen("/proc/loadavg", "r")) == NULL)
++ return FALSE;
++ fscanf(f, "%f %f %f", avg0, avg1, avg2);
++ fclose(f);
++ return TRUE;
++
++#elif defined(GLIBC_VERSION_22) || defined(__APPLE__)
+ double avg[3];
+ int res;
+
diff --git a/main/open-vm-tools/iconv-uclibc.patch b/main/open-vm-tools/iconv-uclibc.patch
new file mode 100644
index 0000000000..2588125fb8
--- /dev/null
+++ b/main/open-vm-tools/iconv-uclibc.patch
@@ -0,0 +1,13 @@
+--- ./configure.ac
++++ ./configure.ac
+@@ -1085,6 +1085,9 @@
+ AC_DEFINE([NO_MULTIMON], 1, [Define to 1 if building without multimon support.])
+ fi
+
++AM_ICONV
++LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD $LIBICONV"
++
+ LIB_AUTH_CPPFLAGS="$LIB_AUTH_CPPFLAGS $PAM_CPPFLAGS"
+ if test "$HAVE_CRYPT" = "yes"; then
+ LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD -lcrypt"
+
diff --git a/main/open-vm-tools/libm.patch b/main/open-vm-tools/libm.patch
new file mode 100644
index 0000000000..cd013f4d20
--- /dev/null
+++ b/main/open-vm-tools/libm.patch
@@ -0,0 +1,18 @@
+--- a/hgfsmounter/Makefile.am
++++ b/hgfsmounter/Makefile.am
+@@ -23,6 +23,7 @@
+ mount_vmhgfs_LDADD += ../lib/panicDefault/libPanicDefault.la
+ mount_vmhgfs_LDADD += ../lib/panic/libPanic.la
+ mount_vmhgfs_LDADD += ../lib/stubs/libStubs.la
++mount_vmhgfs_LDADD += -lm
+
+ mount_vmhgfs_SOURCES =
+ mount_vmhgfs_SOURCES += hgfsmounter.c
+--- a/rpctool/Makefile.am
++++ b/rpctool/Makefile.am
+@@ -25,4 +25,5 @@
+ vmware_rpctool_LDADD += ../lib/message/libMessage.la
+ vmware_rpctool_LDADD += ../lib/backdoor/libBackdoor.la
+ vmware_rpctool_LDADD += ../lib/string/libString.la
++vmware_rpctool_LDADD += -lm
+
diff --git a/main/open-vm-tools/open-vm-tools.initd b/main/open-vm-tools/open-vm-tools.initd
new file mode 100644
index 0000000000..e54b84aaff
--- /dev/null
+++ b/main/open-vm-tools/open-vm-tools.initd
@@ -0,0 +1,76 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/app-emulation/open-vm-tools/files/open-vm-tools.initd,v 1.2 2009/12/20 14:05:43 vadimk Exp $
+
+DND_TMPDIR="/tmp/VMwareDnD"
+USER_GROUP="root:vmware"
+DND_TMPDIR_PERMS="1777"
+GUESTD_BIN="/usr/bin/vmtoolsd"
+PIDFILE="/var/run/vmtoolsd.pid"
+MOUNTPOINT="/proc/fs/vmblock/mountPoint"
+
+depend() {
+ before net X
+}
+
+start() {
+ if [ "${VM_DRAG_AND_DROP}" == "yes" ];
+ then
+
+ if ! grep -q -w vmblock /proc/modules;
+ then
+ ebegin "Loading vmblock module"
+ modprobe vmblock
+ eend $?
+ sleep 0.25
+ fi
+
+ if [[ ! -d "${DND_TMPDIR}" ]];
+ then
+ # einfo "Creating the VM drag and drop directory"
+ mkdir "${DND_TMPDIR}"
+ chown "${USER_GROUP}" "${DND_TMPDIR}"
+ chmod "${DND_TMPDIR_PERMS}" "${DND_TMPDIR}"
+ fi
+
+ # DnD_TMPDIR must exist before vmblock can be mounted
+ ebegin "Mounting vmblock device"
+ mount -t vmblock none ${MOUNTPOINT}
+ eend $?
+ fi
+
+ ebegin "Starting vmtoolsd"
+ start-stop-daemon --chuid "${USER_GROUP}" --start --quiet --background --make-pidfile --pidfile "${PIDFILE}" --exec ${GUESTD_BIN}
+ eend $?
+}
+
+stop() {
+ local ret
+
+ if [ "${VM_DRAG_AND_DROP}" == "yes" ];
+ then
+ ebegin "Cleaning the contents of ${DND_TMPDIR}"
+ # First check, whether ${DND_TMPDIR} isn valid... we shouldn't risk deleting the content of ""/*
+ if [[ ! -z "${DND_TMPDIR}" ]] && [[ "${DND_TMPDIR}" != "/" ]];
+ then
+ rm -rf ${DND_TMPDIR}/*
+ ret=0
+ else
+ eerror "Not cleaning up ${DND_TMPDIR}, please check definition of variable"
+ ret=1
+ fi
+ eend $ret
+
+ ebegin "Unmounting vmblock device"
+ if grep -q -w "${MOUNTPOINT}" /proc/mounts;
+ then
+ umount ${MOUNTPOINT} 1>&2 > /dev/null
+ fi
+ eend 0
+ fi
+
+ ebegin "Stopping vmtoolsd"
+ start-stop-daemon --stop --quiet --pidfile "${PIDFILE}"
+ eend $?
+}
diff --git a/main/open-vm-tools/open-vm-tools.pre-install b/main/open-vm-tools/open-vm-tools.pre-install
new file mode 100644
index 0000000000..10b989ae53
--- /dev/null
+++ b/main/open-vm-tools/open-vm-tools.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+addgroup vmware 2>/dev/null
+exit 0
+
diff --git a/main/open-vm-tools/procmgrposix.patch b/main/open-vm-tools/procmgrposix.patch
new file mode 100644
index 0000000000..510c48a722
--- /dev/null
+++ b/main/open-vm-tools/procmgrposix.patch
@@ -0,0 +1,11 @@
+--- a/lib/procMgr/procMgrPosix.c
++++ b/lib/procMgr/procMgrPosix.c
+@@ -114,7 +114,7 @@
+ #define SOLARIS_BASH_PATH "/usr/bin/bash"
+ #endif
+
+-#if defined(linux) && !defined(GLIBC_VERSION_23)
++#if defined(linux) && !defined(GLIBC_VERSION_23) && !defined(__UCLIBC__)
+ /*
+ * Implements the system calls (they are not wrapped by glibc til 2.3.2).
+ *
diff --git a/main/openal-soft/APKBUILD b/main/openal-soft/APKBUILD
new file mode 100644
index 0000000000..fdf1df20e3
--- /dev/null
+++ b/main/openal-soft/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer:
+pkgname=openal-soft
+pkgver=1.12.854
+pkgrel=0
+pkgdesc="software implementation of OpenAL API"
+url="http://kcat.strangesoft.net/openal.html"
+arch="all"
+license="LGPL"
+depends="alsa-lib"
+depends_dev="alsa-lib-dev"
+makedepends="$depends_dev cmake"
+install=""
+subpackages="$pkgname-dev"
+source="http://kcat.strangesoft.net/openal-releases/${pkgname}-${pkgver}.tar.bz2
+ openal-fegetround.patch"
+
+_srcdir="${srcdir}/${pkgname}-${pkgver}"
+_builddir="${srcdir}/build"
+prepare() {
+ local i
+
+ cd "$_srcdir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ mkdir -p "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ cmake -DCMAKE_INSTALL_PREFIX="/usr" "$_srcdir" || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="fbf36451fdebd6466edbdc0ee7db9603 openal-soft-1.12.854.tar.bz2
+e75032e44d64f268358d9755ff5200c6 openal-fegetround.patch"
diff --git a/main/openal-soft/openal-fegetround.patch b/main/openal-soft/openal-fegetround.patch
new file mode 100644
index 0000000000..261ab595a0
--- /dev/null
+++ b/main/openal-soft/openal-fegetround.patch
@@ -0,0 +1,20 @@
+--- openal-soft-1.12.854.orig/Alc/ALu.c
++++ openal-soft-1.12.854.mod/Alc/ALu.c
+@@ -1345,7 +1345,7 @@
+ int fpuState;
+ ALuint i, c;
+
+-#if defined(HAVE_FESETROUND)
++#if 0
+ fpuState = fegetround();
+ fesetround(FE_TOWARDZERO);
+ #elif defined(HAVE__CONTROLFP)
+@@ -1489,7 +1489,7 @@
+ size -= SamplesToDo;
+ }
+
+-#if defined(HAVE_FESETROUND)
++#if 0
+ fesetround(fpuState);
+ #elif defined(HAVE__CONTROLFP)
+ _controlfp(fpuState, 0xfffff);
diff --git a/main/openbox/APKBUILD b/main/openbox/APKBUILD
new file mode 100644
index 0000000000..35e2320707
--- /dev/null
+++ b/main/openbox/APKBUILD
@@ -0,0 +1,78 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openbox
+pkgver=3.4.11.2
+pkgrel=1
+pkgdesc="A highly configurable and standards-compliant X11 window manager"
+url="http://openbox.org"
+arch="all"
+license="GPLv2+"
+depends=
+depends_dev="pango-dev libxml2-dev libxcursor-dev libxrandr-dev libxinerama-dev startup-notification-dev"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-libs $pkgname-gnome $pkgname-kde"
+source="http://openbox.org/dist/openbox/openbox-$pkgver.tar.gz
+ http://icculus.org/openbox/tools/setlayout.c"
+
+_builddir="$srcdir"/openbox-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-static \
+ || return 1
+ make || return 1
+ gcc $CFLAGS $LDFLAGS -o setlayout "$srcdir"/setlayout.c -lX11 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ install "$_builddir"/setlayout "$pkgdir"/usr/bin/setlayout
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+libs() {
+ pkgdesc="Shared libraries for openbox"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/lib*.so.* "$subpkgdir"/usr/lib/
+}
+
+gnome() {
+ pkgdesc="GNOME integration for openbox"
+ mkdir -p "$subpkgdir"/usr/bin \
+ "$subpkgdir"/usr/share/xsessions
+
+ mv "$pkgdir"/usr/bin/*gnome* \
+ "$pkgdir"/usr/bin/gdm-control \
+ "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/usr/share/*gnome* \
+ "$subpkgdir"/usr/share/ || return 1
+ mv "$pkgdir"/usr/share/xsessions/*gnome* \
+ "$subpkgdir"/usr/share/xsessions/ || return 1
+}
+
+kde() {
+ pkgdesc="KDE integration for openbox"
+ mkdir -p "$subpkgdir"/usr/bin \
+ "$subpkgdir"/usr/share/xsessions
+
+ mv "$pkgdir"/usr/bin/*kde* \
+ "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/usr/share/xsessions/*kde* \
+ "$subpkgdir"/usr/share/xsessions/ || return 1
+}
+
+md5sums="30e669134fa81df810fe7d1dc59cd931 openbox-3.4.11.2.tar.gz
+16ca0d290cae2f4c16a35e9cdfb6f503 setlayout.c"
diff --git a/main/openjdk6/APKBUILD b/main/openjdk6/APKBUILD
new file mode 100644
index 0000000000..07c642ac1d
--- /dev/null
+++ b/main/openjdk6/APKBUILD
@@ -0,0 +1,178 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=openjdk6
+pkgver=1.6.0_p22
+icedteaver=1.10.1
+pkgrel=1
+pkgdesc="Sun OpenJDK 6 via IcedTea"
+url="http://icedtea.classpath.org/"
+arch="all"
+license="GPL-2 with Classpath"
+depends="$pkgname-jre"
+makedepends="java-gcj-compat findutils tar zip gawk pkgconfig util-linux-ng
+ nss-dev cups-dev jpeg-dev giflib-dev libpng-dev libxt-dev
+ libxp-dev libxtst-dev libxinerama-dev libiconv-dev
+ libxrender-dev alsa-lib-dev freetype-dev xulrunner-dev
+ gtk+2.0-dev"
+install=""
+subpackages="$pkgname-jre-lib:jrelib $pkgname-jre $pkgname-jre-base:jrebase
+ $pkgname-doc:doc"
+BOOTSTRAP_JAVA_HOME=/usr/lib/jvm/java-1.5-gcj/
+OPENJDK_VERSION=b22
+OPENJDK_DATE=28_feb_2011
+XALAN2_VER=2_7_1
+XERCES_VER=2.9.0
+RHINO_VER=1_7R2
+ANT_VER=1.8.2
+JAXWS_DROP_ZIP=jdk6-jaxws-b20.zip
+JAXP_DROP_ZIP=jaxp144_01.zip
+JAF_DROP_ZIP=jdk6-jaf-b20.zip
+source="http://download.java.net/openjdk/jdk6/promoted/$OPENJDK_VERSION/openjdk-6-src-$OPENJDK_VERSION-$OPENJDK_DATE.tar.gz
+ http://icedtea.classpath.org/download/source/icedtea6-$icedteaver.tar.gz
+ http://archive.apache.org/dist/ant/binaries/apache-ant-$ANT_VER-bin.tar.gz
+ http://archive.apache.org/dist/xml/xalan-j/xalan-j_$XALAN2_VER-bin-2jars.tar.gz
+ http://archive.apache.org/dist/xml/xerces-j/Xerces-J-bin.$XERCES_VER.tar.gz
+ ftp://ftp.mozilla.org/pub/mozilla.org/js/rhino$RHINO_VER.zip
+ http://icedtea.classpath.org/download/drops/$JAXWS_DROP_ZIP
+ http://icedtea.classpath.org/download/drops/$JAXP_DROP_ZIP
+ http://icedtea.classpath.org/download/drops/$JAF_DROP_ZIP
+ icedtea-hotspot-uclibc-fixes.patch
+ icedtea-jdk-iconv-uclibc.patch
+ icedtea-jdk-execinfo.patch
+ icedtea-jdk-no-lib-nsl.patch
+ "
+
+_builddir="$srcdir/icedtea6-$icedteaver"
+INSTALL_BASE=/usr/lib/jvm/java-1.6-openjdk
+CPU=`uname -m | sed -e 's/i.86/i386/g' -e 's/x86_64/amd64/g'`
+
+unpack() {
+ if [ -z "$force" ]; then
+ md5check || return 1
+ initdcheck || return 1
+ fi
+ mkdir -p "$srcdir"
+ msg "Unpacking sources..."
+ tar -C "$srcdir" -zxf icedtea6-$icedteaver.tar.gz || return 1
+ tar -C "$srcdir" -zxf apache-ant-$ANT_VER-bin.tar.gz || return 1
+ tar -C "$srcdir" -zxf xalan-j_$XALAN2_VER-bin-2jars.tar.gz || return 1
+ tar -C "$srcdir" -zxf Xerces-J-bin.$XERCES_VER.tar.gz || return 1
+ unzip -o -q "rhino$RHINO_VER.zip" -d "$srcdir" || return 1
+}
+
+prepare() {
+ cd "$_builddir"
+
+ # Busybox sha256 does not support longopts
+ sed -e "s/--check/-c/g" -i Makefile.in
+
+ cp ../icedtea-*.patch patches
+}
+
+build() {
+ export JAVA_HOME=$BOOTSTRAP_JAVA_HOME
+ export PATH=$JAVA_HOME/bin:$srcdir/apache-ant-$ANT_VER/bin:$PATH
+ export DISTRIBUTION_PATCHES=`echo $source | awk -v RS=' ' '/icedtea-[^ ]*\.patch/ { printf "patches/%s ",$1 }'`
+
+ JOBS=`echo $MAKEFLAGS | sed -n -e 's/.*-j\([0-9]\+\).*/\1/p'`
+ if [ "$JOBS" ]; then
+ confjobs="--with-parallel-jobs=$JOBS"
+ else
+ confjobs=""
+ fi
+
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ --disable-dependency-tracking \
+ --with-gcj $confjobs \
+ --with-openjdk-src-zip=$srcdir/openjdk-6-src-$OPENJDK_VERSION-$OPENJDK_DATE.tar.gz \
+ --with-jaxp-drop-zip=$srcdir/$JAXP_DROP_ZIP \
+ --with-jaf-drop-zip=$srcdir/$JAF_DROP_ZIP \
+ --with-jaxws-drop-zip=$srcdir/$JAXWS_DROP_ZIP \
+ --with-jdk-home=$BOOTSTRAP_JAVA_HOME \
+ --with-ant-home=$srcdir/apache-ant-$ANT_VER \
+ --with-xalan2-jar=$srcdir/xalan-j_$XALAN2_VER/xalan.jar \
+ --with-xalan2-serializer-jar=$srcdir/xalan-j_$XALAN2_VER/serializer.jar \
+ --with-xerces2-jar=$srcdir/xerces-${XERCES_VER//./_}/xercesImpl.jar \
+ --with-rhino=$srcdir/rhino$RHINO_VER/js.jar \
+ --with-pkgversion=Alpine \
+ || return 1
+
+ make || return 1
+}
+
+package() {
+ mkdir -p "$pkgdir"/$INSTALL_BASE
+ cp -a "$_builddir"/openjdk.build/j2sdk-image/* "$pkgdir"/$INSTALL_BASE
+ rm "$pkgdir"/$INSTALL_BASE/src.zip
+}
+
+jrelib() {
+ pkgdesc="OpenJDK 6 Java Runtime (class libraries)"
+ arch="noarch"
+ depends=""
+
+ for A in jre/lib/zi jre/lib/images jre/lib/*.jar jre/lib/security \
+ jre/lib/ext/*.jar jre/lib/cmm jre/ASSEMBLY_EXCEPTION \
+ jre/THIRD_PARTY_README jre/LICENSE ; do
+ dirname=${A%/*}
+ mkdir -p "$subpkgdir"/$INSTALL_BASE/$dirname
+ mv "$pkgdir"/$INSTALL_BASE/$A "$subpkgdir"/$INSTALL_BASE/$dirname
+ done
+}
+
+jrebase() {
+ pkgdesc="OpenJDK 6 Java Runtime (no GUI support)"
+ depends="$pkgname-jre-lib java-common"
+
+ mkdir -p "$subpkgdir"/$INSTALL_BASE/bin
+
+ for A in java orbd rmid servertool unpack200 keytool \
+ pack200 rmiregistry tnameserv ; do
+ mv "$pkgdir"/$INSTALL_BASE/bin/$A "$subpkgdir"/$INSTALL_BASE/bin
+ done
+
+ # rest of the jre subdir (which were not taken by -jre subpkg)
+ mv "$pkgdir"/$INSTALL_BASE/jre "$subpkgdir"/$INSTALL_BASE
+}
+
+jre() {
+ pkgdesc="OpenJDK 6 Java Runtime"
+ depends=""
+
+ mkdir -p "$subpkgdir"
+ for A in jre/bin/policytool \
+ bin/appletviewer \
+ bin/policytool \
+ jre/lib/$CPU/xawt \
+ jre/lib/$CPU/libsplashscreen.so ; do
+ dirname=${A%/*}
+ mkdir -p "$subpkgdir"/$INSTALL_BASE/$dirname
+ mv "$pkgdir"/$INSTALL_BASE/$A "$subpkgdir"/$INSTALL_BASE/$dirname
+ done
+}
+
+doc() {
+ default_doc
+
+ mkdir -p "$subpkgdir"/$INSTALL_BASE/
+ mv "$pkgdir"/$INSTALL_BASE/man "$subpkgdir"/$INSTALL_BASE/
+}
+
+md5sums="2d2bbbb0f9b81f1fec41ec730da8a933 openjdk-6-src-b22-28_feb_2011.tar.gz
+f3b31b9f591afc752372addacb1eb335 icedtea6-1.10.1.tar.gz
+afb0c7950a663f94e65da9f3be676d8f apache-ant-1.8.2-bin.tar.gz
+3ccda39bcd08b780436dfd2f22fb23d5 xalan-j_2_7_1-bin-2jars.tar.gz
+138f2d1cddd823281d5dfb700f2bd7d4 Xerces-J-bin.2.9.0.tar.gz
+40d0a9abec8169e42920214b37fa8e0e rhino1_7R2.zip
+91adfd41e6f001add4f92ae31216b1e3 jdk6-jaxws-b20.zip
+ef7a8b3624ea904bf584bc46d79b5e75 jaxp144_01.zip
+bc95c133620bd68c161cac9891592901 jdk6-jaf-b20.zip
+dc6a1e28a97d897d7a1057c11696727d icedtea-hotspot-uclibc-fixes.patch
+7c0814181e5adc0763c5c0a24b01d4cb icedtea-jdk-iconv-uclibc.patch
+dae2ba8b87e2106b53974ace07e4ca72 icedtea-jdk-execinfo.patch
+c4bb40d5b1ff690b27900c5cd06bc1e5 icedtea-jdk-no-lib-nsl.patch"
diff --git a/main/openjdk6/icedtea-hotspot-uclibc-fixes.patch b/main/openjdk6/icedtea-hotspot-uclibc-fixes.patch
new file mode 100644
index 0000000000..fb75ffc340
--- /dev/null
+++ b/main/openjdk6/icedtea-hotspot-uclibc-fixes.patch
@@ -0,0 +1,90 @@
+--- openjdk.orig/hotspot/src/os/linux/vm/os_linux.cpp
++++ openjdk/hotspot/src/os/linux/vm/os_linux.cpp
+@@ -53,7 +53,6 @@
+ # include <string.h>
+ # include <syscall.h>
+ # include <sys/sysinfo.h>
+-# include <gnu/libc-version.h>
+ # include <sys/ipc.h>
+ # include <sys/shm.h>
+ # include <link.h>
+@@ -553,9 +552,7 @@
+ os::Linux::set_glibc_version(str);
+ } else {
+ // _CS_GNU_LIBC_VERSION is not supported, try gnu_get_libc_version()
+- static char _gnu_libc_version[32];
+- jio_snprintf(_gnu_libc_version, sizeof(_gnu_libc_version),
+- "glibc %s %s", gnu_get_libc_version(), gnu_get_libc_release());
++ static char _gnu_libc_version[32] = "2.9";
+ os::Linux::set_glibc_version(_gnu_libc_version);
+ }
+
+@@ -2434,11 +2431,7 @@
+ // If we are running with earlier version, which did not have symbol versions,
+ // we should use the base version.
+ void* os::Linux::libnuma_dlsym(void* handle, const char *name) {
+- void *f = dlvsym(handle, name, "libnuma_1.1");
+- if (f == NULL) {
+- f = dlsym(handle, name);
+- }
+- return f;
++ return dlsym(handle, name);
+ }
+
+ bool os::Linux::libnuma_init() {
+@@ -4446,7 +4439,22 @@
+ // Linux doesn't yet have a (official) notion of processor sets,
+ // so just return the system wide load average.
+ int os::loadavg(double loadavg[], int nelem) {
+- return ::getloadavg(loadavg, nelem);
++
++ FILE *LOADAVG;
++ double avg[3] = { 0.0, 0.0, 0.0 };
++ int i, res = -1;;
++
++ if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
++ fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
++ res = 0;
++ fclose(LOADAVG);
++ }
++
++ for (i = 0; (i < nelem) && (i < 3); i++) {
++ loadavg[i] = avg[i];
++ }
++
++ return res;
+ }
+
+ void os::pause() {
+Only in openjdk: hotspot/src/os/linux/vm/os_linux.cpp.orig
+--- openjdk.orig/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp
++++ openjdk/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp
+@@ -231,14 +231,14 @@
+ // checking for nanness
+ #ifdef SOLARIS
+ #ifdef SPARC
+-inline int g_isnan(float f) { return isnanf(f); }
++inline int g_isnan(float f) { return __isnanf(f); }
+ #else
+ // isnanf() broken on Intel Solaris use isnand()
+ inline int g_isnan(float f) { return isnand(f); }
+ #endif
+ inline int g_isnan(double f) { return isnand(f); }
+ #elif LINUX
+-inline int g_isnan(float f) { return isnanf(f); }
++inline int g_isnan(float f) { return __isnanf(f); }
+ inline int g_isnan(double f) { return isnan(f); }
+ #else
+ #error "missing platform-specific definition here"
+@@ -252,8 +252,8 @@
+
+ // Checking for finiteness
+
+-inline int g_isfinite(jfloat f) { return finite(f); }
+-inline int g_isfinite(jdouble f) { return finite(f); }
++inline int g_isfinite(jfloat f) { return isfinite(f); }
++inline int g_isfinite(jdouble f) { return isfinite(f); }
+
+
+ // Wide characters
+Only in openjdk: hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp.orig
diff --git a/main/openjdk6/icedtea-jdk-execinfo.patch b/main/openjdk6/icedtea-jdk-execinfo.patch
new file mode 100644
index 0000000000..fb17ab6927
--- /dev/null
+++ b/main/openjdk6/icedtea-jdk-execinfo.patch
@@ -0,0 +1,40 @@
+--- openjdk.orig/jdk/src/solaris/native/sun/awt/awt_xembed_server.c
++++ openjdk/jdk/src/solaris/native/sun/awt/awt_xembed_server.c
+@@ -35,7 +35,7 @@
+ #include <X11/Xlib.h>
+ #include <X11/Xatom.h>
+ #include <Xm/MwmUtil.h>
+-#ifdef __linux__
++#if defined(__linux__) && ! defined(__UCLIBC__)
+ #include <execinfo.h>
+ #endif
+ #include <stdio.h>
+@@ -835,7 +835,7 @@
+ AWT_UNLOCK();
+ }
+
+-#ifdef __linux__
++#if defined(__linux__) && ! defined(__UCLIBC__)
+ void
+ print_stack (void)
+ {
+--- openjdk.orig/jdk/src/solaris/native/sun/xawt/XToolkit.c
++++ openjdk/jdk/src/solaris/native/sun/xawt/XToolkit.c
+@@ -27,7 +27,7 @@
+ #include <X11/Xutil.h>
+ #include <X11/Xos.h>
+ #include <X11/Xatom.h>
+-#ifdef __linux__
++#if defined(__linux__) && ! defined(__UCLIBC__)
+ #include <execinfo.h>
+ #endif
+
+@@ -689,7 +689,7 @@
+ return ret;
+ }
+
+-#ifdef __linux__
++#if defined(__linux__) && ! defined(__UCLIBC__)
+ void print_stack(void)
+ {
+ void *array[10];
diff --git a/main/openjdk6/icedtea-jdk-iconv-uclibc.patch b/main/openjdk6/icedtea-jdk-iconv-uclibc.patch
new file mode 100644
index 0000000000..68f858167f
--- /dev/null
+++ b/main/openjdk6/icedtea-jdk-iconv-uclibc.patch
@@ -0,0 +1,39 @@
+Index: openjdk/jdk/make/java/npt/Makefile
+===================================================================
+--- openjdk/jdk/make/java/npt/Makefile 2010-06-13 15:11:02.598512448 +0200
++++ openjdk/jdk/make/java/npt/Makefile 2010-06-13 15:11:28.504759286 +0200
+@@ -65,6 +65,8 @@
+ # We don't want to link against -ljava
+ JAVALIB=
+
++LDLIBS += -liconv
++
+ # Add -export options to explicitly spell exported symbols
+ ifeq ($(PLATFORM), windows)
+ OTHER_LCF += -export:nptInitialize -export:nptTerminate
+Index: icedtea6-1.8/openjdk-ecj/jdk/make/java/instrument/Makefile
+===================================================================
+--- openjdk/jdk/make/java/instrument/Makefile 2010-06-13 15:12:14.688505195 +0200
++++ openjdk/jdk/make/java/instrument/Makefile 2010-06-13 15:12:32.641425670 +0200
+@@ -123,6 +123,8 @@
+ # We don't want to link against -ljava
+ JAVALIB=
+
++LDLIBS += -liconv
++
+ #
+ # Add to ambient vpath so we pick up the library files
+ #
+Index: openjdk/jdk/make/sun/splashscreen/Makefile
+===================================================================
+--- openjdk/jdk/make/sun/splashscreen/Makefile 2010-06-13 15:12:48.951840824 +0200
++++ openjdk/jdk/make/sun/splashscreen/Makefile 2010-06-13 15:13:01.191422891 +0200
+@@ -55,6 +55,8 @@
+
+ JAVALIB=
+
++LDLIBS += -liconv
++
+ #
+ # C Flags
+ #
diff --git a/main/openjdk6/icedtea-jdk-no-lib-nsl.patch b/main/openjdk6/icedtea-jdk-no-lib-nsl.patch
new file mode 100644
index 0000000000..26f89bb546
--- /dev/null
+++ b/main/openjdk6/icedtea-jdk-no-lib-nsl.patch
@@ -0,0 +1,84 @@
+--- openjdk.orig/hotspot/agent/src/os/solaris/dbx/Makefile
++++ openjdk/hotspot/agent/src/os/solaris/dbx/Makefile
+@@ -50,7 +50,7 @@
+ CFLAGS_32bit := -xarch=v8
+ CFLAGS_64bit := -xarch=v9
+ CFLAGS := -PIC -xO3 $(INCLUDES)
+-LIBS := -lsocket -lnsl -lrtld_db
++LIBS := -lsocket -lrtld_db
+ LDFLAGS := -G
+
+ ifneq "$(ARCH)" "i486"
+--- openjdk.orig/jdk/make/java/hpi/hpi_common.gmk
++++ openjdk/jdk/make/java/hpi/hpi_common.gmk
+@@ -86,5 +86,5 @@
+ # Things that must be linked in.
+ #
+ ifneq ($(PLATFORM), windows)
+-OTHER_LDLIBS += $(LIBSOCKET) -lnsl $(LIBM) -ldl
++OTHER_LDLIBS += $(LIBSOCKET) $(LIBM) -ldl
+ endif
+--- openjdk.orig/jdk/make/java/java/Makefile
++++ openjdk/jdk/make/java/java/Makefile
+@@ -205,7 +205,7 @@
+ OTHER_LDLIBS += $(JVMLIB) -libpath:$(OBJDIR)/../../../fdlibm/$(OBJDIRNAME) fdlibm.lib \
+ -libpath:$(OBJDIR)/../../../verify/$(OBJDIRNAME) verify.lib
+ else
+-OTHER_LDLIBS += $(JVMLIB) -lverify $(LIBSOCKET) -lnsl -ldl \
++OTHER_LDLIBS += $(JVMLIB) -lverify $(LIBSOCKET) -ldl \
+ -L$(OBJDIR)/../../../fdlibm/$(OBJDIRNAME) -lfdlibm.$(ARCH)
+ endif
+
+--- openjdk.orig/jdk/make/java/java_hprof_demo/Makefile
++++ openjdk/jdk/make/java/java_hprof_demo/Makefile
+@@ -83,7 +83,7 @@
+ ifeq ($(PLATFORM), windows)
+ OTHER_LDLIBS += wsock32.lib winmm.lib
+ else
+- OTHER_LDLIBS += $(LIBSOCKET) -lnsl -ldl
++ OTHER_LDLIBS += $(LIBSOCKET) -ldl
+ endif
+
+ #
+--- openjdk.orig/jdk/make/java/net/Makefile
++++ openjdk/jdk/make/java/net/Makefile
+@@ -97,7 +97,7 @@
+ # Will not compile at warning level 3 if warnings are fatal
+ COMPILER_WARNINGS_FATAL=false
+ else
+- OTHER_LDLIBS = $(LIBSOCKET) -lnsl -ldl $(JVMLIB)
++ OTHER_LDLIBS = $(LIBSOCKET) -ldl $(JVMLIB)
+ endif
+ ifeq ($(PLATFORM), linux)
+ OTHER_LDLIBS += -lpthread
+--- openjdk.orig/jdk/make/jpda/transport/socket/Makefile
++++ openjdk/jdk/make/jpda/transport/socket/Makefile
+@@ -42,11 +42,11 @@
+ endif
+
+ ifeq ($(PLATFORM), linux)
+- OTHER_LDLIBS += -lnsl $(LIBSOCKET) -lpthread
++ OTHER_LDLIBS += $(LIBSOCKET) -lpthread
+ endif
+
+ ifeq ($(PLATFORM), solaris)
+- OTHER_LDLIBS += -lnsl $(LIBSOCKET)
++ OTHER_LDLIBS += $(LIBSOCKET)
+ endif
+
+ ifeq ($(PLATFORM), windows)
+--- openjdk.orig/jdk/make/mkdemo/jvmti/hprof/Makefile
++++ openjdk/jdk/make/mkdemo/jvmti/hprof/Makefile
+@@ -39,10 +39,10 @@
+ EXTRA_LIBS += wsock32.lib winmm.lib
+ endif
+ ifeq ($(PLATFORM), solaris)
+- OTHER_LDLIBS += $(LIBSOCKET) -lnsl -ldl
++ OTHER_LDLIBS += $(LIBSOCKET) -ldl
+ endif
+ ifeq ($(PLATFORM), linux)
+- OTHER_LDLIBS += $(LIBSOCKET) -lnsl -ldl -lpthread
++ OTHER_LDLIBS += $(LIBSOCKET) -ldl -lpthread
+ endif
+
+ #
diff --git a/main/openldap/APKBUILD b/main/openldap/APKBUILD
new file mode 100644
index 0000000000..51961c8bc1
--- /dev/null
+++ b/main/openldap/APKBUILD
@@ -0,0 +1,118 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openldap
+pkgver=2.4.25
+pkgrel=2
+pkgdesc="LDAP Server"
+url="http://www.openldap.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="db-dev openssl-dev groff unixodbc-dev libtool"
+depends_dev="openssl-dev"
+subpackages="$pkgname-dev $pkgname-doc libldap $pkgname-back-sql:sql
+ $pkgname-back-bdb:bdb $pkgname-back-hdb:hdb $pkgname-back-ldap:ldap
+ $pkgname-back-meta:meta $pkgname-back-monitor:monitor"
+
+install="$pkgname.pre-install $pkgname.post-install"
+source="ftp://ftp.$pkgname.org/pub/OpenLDAP/$pkgname-release/$pkgname-$pkgver.tgz
+ openldap-2.4-ppolicy.patch
+ openldap-2.4.11-libldap_r.patch
+ openldap-back-sql-fix-64bit.patch
+ slapd.initd
+ slapd.confd
+ slurpd.initd
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ sed -e '/^STRIP/s,-s,,g' \
+ -i build/top.mk || return 1
+}
+
+# berkdb crypt ipv6 ssl
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --libexecdir=/usr/lib \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --localstatedir=/var/lib/openldap \
+ --enable-slapd \
+ --enable-crypt \
+ --enable-modules \
+ --enable-dynamic \
+ --enable-bdb=mod \
+ --enable-hdb=mod \
+ --enable-dnssrv=mod \
+ --enable-ldap=mod \
+ --enable-meta=mod \
+ --enable-monitor=mod \
+ --enable-null=mod \
+ --enable-passwd=mod \
+ --enable-relay=mod \
+ --enable-shell=mod \
+ --enable-sock=mod \
+ --enable-sql=mod \
+ --with-tls=openssl
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/openldap/*.la \
+ "$pkgdir"/usr/lib/*.la || return 1
+
+ install -d "$pkgdir"/var/run/openldap
+ sed -i -e 's:/var/lib/openldap/run:/var/run/openldap:g' \
+ -e 's:back_bdb.la:back_bdb.so:' \
+ -e 's:back_hdb.la:back_hdb.so:' \
+ -e 's:back_ldap.la:back_ldap.so:' \
+ "$pkgdir"/etc/openldap/slapd.conf
+
+ mv "$pkgdir"/usr/lib/slapd "$pkgdir"/usr/sbin/
+ chmod g+r "$pkgdir"/etc/openldap/slapd.conf
+ install -Dm755 ../slapd.initd "$pkgdir"/etc/init.d/slapd
+ install -Dm755 ../slapd.confd "$pkgdir"/etc/conf.d/slapd
+ install -Dm755 ../slurpd.initd "$pkgdir"/etc/init.d/slurpd
+ # FIXME: symlinks in sbin are symlinked to /usr/lib/slapd
+ ln -s /usr/sbin/slapd "$pkgdir"/usr/lib/slapd
+}
+
+libldap() {
+ pkgdesc="OpenLDAP libraries"
+ depends=
+ install=
+ mkdir -p "$subpkgdir"/usr/lib "$subpkgdir"/etc/openldap
+ mv "$pkgdir"/usr/lib/*.so* "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/etc/openldap/ldap.conf "$subpkgdir"/etc/openldap/
+}
+
+_backend() {
+ pkgdesc="OpenLDAP ${2:-$1} backend"
+ mkdir -p "$subpkgdir"/usr/lib/openldap
+ mv "$pkgdir"/usr/lib/openldap/back_$1* "$subpkgdir"/usr/lib/openldap/
+}
+
+bdb() { _backend bdb ; }
+hdb() { _backend hdb ; }
+sql() { _backend sql ODBC; }
+ldap() { _backend ldap LDAP; }
+meta() { _backend meta; }
+monitor() { _backend monitor; }
+
+
+md5sums="ec63f9c2add59f323a0459128846905b openldap-2.4.25.tgz
+2524e490ba334a760fa57057c16da7a9 openldap-2.4-ppolicy.patch
+d19d0502f046078ecd737e29e7552fa8 openldap-2.4.11-libldap_r.patch
+226eefb3e17810f453b76cbc9d1bdbad openldap-back-sql-fix-64bit.patch
+a729bf553d12b4a9fbda0ff5202a0443 slapd.initd
+b672311fca605c398240cd37a2ae080a slapd.confd
+fa5ce0005ef5f1160b6ff126f97aaa1a slurpd.initd"
diff --git a/main/openldap/openldap-2.4-ppolicy.patch b/main/openldap/openldap-2.4-ppolicy.patch
new file mode 100644
index 0000000000..c05790e3e2
--- /dev/null
+++ b/main/openldap/openldap-2.4-ppolicy.patch
@@ -0,0 +1,13 @@
+diff -urN ./clients.orig/tools/common.c ./clients/tools/common.c
+--- ./clients.orig/tools/common.c 2007-09-01 01:13:50.000000000 +0200
++++ ./clients/tools/common.c 2008-01-13 21:50:06.000000000 +0100
+@@ -1262,8 +1262,8 @@
+ int nsctrls = 0;
+
+ #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
++ LDAPControl c;
+ if ( ppolicy ) {
+- LDAPControl c;
+ c.ldctl_oid = LDAP_CONTROL_PASSWORDPOLICYREQUEST;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
diff --git a/main/openldap/openldap-2.4.11-libldap_r.patch b/main/openldap/openldap-2.4.11-libldap_r.patch
new file mode 100644
index 0000000000..448249a3b5
--- /dev/null
+++ b/main/openldap/openldap-2.4.11-libldap_r.patch
@@ -0,0 +1,11 @@
+diff -Nuar openldap-2.4.11.orig/servers/slapd/slapi/Makefile.in openldap-2.4.11/servers/slapd/slapi/Makefile.in
+--- openldap-2.4.11.orig/servers/slapd/slapi/Makefile.in 2008-02-11 15:26:49.000000000 -0800
++++ openldap-2.4.11/servers/slapd/slapi/Makefile.in 2008-10-14 02:10:18.402799262 -0700
+@@ -37,6 +37,7 @@
+ XLIBS = $(LIBRARY)
+ XXLIBS =
+ NT_LINK_LIBS = $(AC_LIBS)
++UNIX_LINK_LIBS = ../../../libraries/libldap_r/libldap_r.la $(LTHREAD_LIBS)
+
+ XINCPATH = -I$(srcdir)/.. -I$(srcdir)
+ XDEFS = $(MODULES_CPPFLAGS)
diff --git a/main/openldap/openldap-back-sql-fix-64bit.patch b/main/openldap/openldap-back-sql-fix-64bit.patch
new file mode 100644
index 0000000000..82707d4e73
--- /dev/null
+++ b/main/openldap/openldap-back-sql-fix-64bit.patch
@@ -0,0 +1,82 @@
+From: Timo Teräs <timo.teras@iki.fi>
+
+Fix openldap memory corruption with back-sql on 64-bit architectures.
+
+--- openldap-2.4.25/servers/slapd/back-sql/add.c
++++ openldap-2.4.25.patched/servers/slapd/back-sql/add.c
+@@ -1217,7 +1217,7 @@
+
+ if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
+ SWORD ncols;
+- SQLINTEGER value_len;
++ SQLLEN value_len;
+
+ if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
+ SQLFreeStmt( sth, SQL_DROP );
+--- openldap-2.4.25/servers/slapd/back-sql/back-sql.h
++++ openldap-2.4.25.patched/servers/slapd/back-sql/back-sql.h
+@@ -183,7 +183,7 @@
+ UDWORD *col_prec;
+ SQLSMALLINT *col_type;
+ char **cols;
+- SQLINTEGER *value_len;
++ SQLLEN *value_len;
+ } BACKSQL_ROW_NTS;
+
+ /*
+--- openldap-2.4.25/servers/slapd/back-sql/proto-sql.h
++++ openldap-2.4.25.patched/servers/slapd/back-sql/proto-sql.h
+@@ -189,25 +189,25 @@
+ #define backsql_BindParamStr( sth, par_ind, io, str, maxlen ) \
+ SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), \
+ (io), SQL_C_CHAR, SQL_VARCHAR, \
+- (SQLUINTEGER)(maxlen), 0, (SQLPOINTER)(str), \
+- (SQLUINTEGER)(maxlen), NULL )
++ (SQLULEN)(maxlen), 0, (SQLPOINTER)(str), \
++ (SQLLEN)(maxlen), NULL )
+
+ #define backsql_BindParamBerVal( sth, par_ind, io, bv ) \
+ SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), \
+ (io), SQL_C_CHAR, SQL_VARCHAR, \
+- (SQLUINTEGER)(bv)->bv_len, 0, \
++ (SQLULEN)(bv)->bv_len, 0, \
+ (SQLPOINTER)(bv)->bv_val, \
+- (SQLUINTEGER)(bv)->bv_len, NULL )
++ (SQLLEN)(bv)->bv_len, NULL )
+
+ #define backsql_BindParamInt( sth, par_ind, io, val ) \
+ SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), \
+ (io), SQL_C_ULONG, SQL_INTEGER, \
+- 0, 0, (SQLPOINTER)(val), 0, (SQLINTEGER*)NULL )
++ 0, 0, (SQLPOINTER)(val), 0, (SQLLEN*)NULL )
+
+ #define backsql_BindParamNumID( sth, par_ind, io, val ) \
+ SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), \
+ (io), BACKSQL_C_NUMID, SQL_INTEGER, \
+- 0, 0, (SQLPOINTER)(val), 0, (SQLINTEGER*)NULL )
++ 0, 0, (SQLPOINTER)(val), 0, (SQLLEN*)NULL )
+
+ #ifdef BACKSQL_ARBITRARY_KEY
+ #define backsql_BindParamID( sth, par_ind, io, id ) \
+--- openldap-2.4.25/servers/slapd/back-sql/sql-wrap.c
++++ openldap-2.4.25.patched/servers/slapd/back-sql/sql-wrap.c
+@@ -148,7 +148,7 @@
+ } else {
+ SQLCHAR colname[ 64 ];
+ SQLSMALLINT name_len, col_type, col_scale, col_null;
+- UDWORD col_prec;
++ SQLLEN col_prec;
+ int i;
+
+ #ifdef BACKSQL_TRACE
+@@ -180,8 +180,8 @@
+ goto nomem;
+ }
+
+- row->value_len = (SQLINTEGER *)ber_memcalloc_x( row->ncols,
+- sizeof( SQLINTEGER ), ctx );
++ row->value_len = (SQLLEN *)ber_memcalloc_x( row->ncols,
++ sizeof( SQLLEN ), ctx );
+ if ( row->value_len == NULL ) {
+ goto nomem;
+ }
diff --git a/main/openldap/openldap.post-install b/main/openldap/openldap.post-install
new file mode 100644
index 0000000000..1d6affdfee
--- /dev/null
+++ b/main/openldap/openldap.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+chown -R ldap:ldap /var/lib/openldap /var/run/openldap
+chgrp ldap /etc/openldap/slapd.conf
diff --git a/main/openldap/openldap.pre-install b/main/openldap/openldap.pre-install
new file mode 100644
index 0000000000..7de7c0ce33
--- /dev/null
+++ b/main/openldap/openldap.pre-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+addgroup -S ldap 2>/dev/null
+adduser -h /usr/lib/openldap -s /bin/false -S -D -H -g "OpenLdap User" \
+ -G ldap ldap 2>/dev/null
+
+exit 0
diff --git a/main/openldap/slapd.confd b/main/openldap/slapd.confd
new file mode 100644
index 0000000000..2240ad3f30
--- /dev/null
+++ b/main/openldap/slapd.confd
@@ -0,0 +1,9 @@
+# conf.d file for openldap
+#
+# To enable both the standard unciphered server and the ssl encrypted
+# one uncomment this line or set any other server starting options
+# you may desire.
+#
+# OPTS="-h 'ldaps:// ldap:// ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock'"
+# Uncomment the below to use the new slapd configuration for openldap 2.3
+#OPTS="-F /etc/openldap/slapd.d -h 'ldaps:// ldap:// ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock'"
diff --git a/main/openldap/slapd.initd b/main/openldap/slapd.initd
new file mode 100644
index 0000000000..d66af755e6
--- /dev/null
+++ b/main/openldap/slapd.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-nds/openldap/files/slapd-initd,v 1.2 2008/10/14 10:29:44 robbat2 Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ldap-server"
+ eval start-stop-daemon --start --pidfile /var/run/openldap/slapd.pid --exec /usr/sbin/slapd -- -u ldap -g ldap "${OPTS}"
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ldap-server"
+ start-stop-daemon --stop --signal 2 --quiet --pidfile /var/run/openldap/slapd.pid
+ eend $?
+}
diff --git a/main/openldap/slurpd.initd b/main/openldap/slurpd.initd
new file mode 100644
index 0000000000..d90176b3ce
--- /dev/null
+++ b/main/openldap/slurpd.initd
@@ -0,0 +1,23 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-nds/openldap/files/slurpd-initd,v 1.1 2007/01/16 23:22:02 jokey Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting slurpd"
+ start-stop-daemon --start --quiet \
+ --exec /usr/lib/openldap/slurpd
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping slurpd"
+ start-stop-daemon --stop --quiet \
+ --exec /usr/lib/openldap/slurpd
+ eend $?
+}
diff --git a/main/opennhrp/0001-netlink-ignore-kernel-routes-for-GRE-interfaces.patch b/main/opennhrp/0001-netlink-ignore-kernel-routes-for-GRE-interfaces.patch
new file mode 100644
index 0000000000..78cf3f89b4
--- /dev/null
+++ b/main/opennhrp/0001-netlink-ignore-kernel-routes-for-GRE-interfaces.patch
@@ -0,0 +1,54 @@
+From 7747c86253114ed9702346a93587e4e6cac444aa Mon Sep 17 00:00:00 2001
+From: David Ward <david.ward@ll.mit.edu>
+Date: Tue, 29 Mar 2011 22:43:03 -0400
+Subject: [PATCH] netlink: ignore kernel routes for GRE interfaces
+
+The kernel route should not be added as a peer, except on shortcut-
+destination interfaces. It can prevent NHRP resolution requests from
+being routed correctly to a statically-configured next hop server.
+
+Signed-off-by: David Ward <david.ward@ll.mit.edu>
+---
+ nhrp/sysdep_netlink.c | 9 ++++-----
+ 1 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/nhrp/sysdep_netlink.c b/nhrp/sysdep_netlink.c
+index a76acc2..e3e588b 100644
+--- a/nhrp/sysdep_netlink.c
++++ b/nhrp/sysdep_netlink.c
+@@ -691,7 +691,8 @@ static void netlink_route_new(struct nlmsghdr *msg)
+ } else if (iface->flags & NHRP_INTERFACE_FLAG_CONFIGURED) {
+ /* Routes which might get additional outbound
+ * shortcuts */
+- if (rtm->rtm_table != iface->route_table)
++ if (rtm->rtm_table != iface->route_table ||
++ rtm->rtm_protocol == RTPROT_KERNEL)
+ return;
+ type = NHRP_PEER_TYPE_LOCAL_ROUTE;
+ }
+@@ -728,12 +729,9 @@ static void netlink_route_del(struct nlmsghdr *msg)
+ if (rta[RTA_OIF] == NULL || rta[RTA_DST] == NULL)
+ return;
+
+- /* Consider only routes from main table */
+ if (rtm->rtm_family != PF_INET)
+ return;
+
+- /* Only consider routes for local interfaces that accept
+- * shortcut connections */
+ iface = nhrp_interface_get_by_index(*(int*)RTA_DATA(rta[RTA_OIF]),
+ FALSE);
+ if (iface == NULL)
+@@ -747,7 +745,8 @@ static void netlink_route_del(struct nlmsghdr *msg)
+ } else if (iface->flags & NHRP_INTERFACE_FLAG_CONFIGURED) {
+ /* Routes which might get additional outbound
+ * shortcuts */
+- if (rtm->rtm_table != iface->route_table)
++ if (rtm->rtm_table != iface->route_table ||
++ rtm->rtm_protocol == RTPROT_KERNEL)
+ return;
+ type = NHRP_PEER_TYPE_LOCAL_ROUTE;
+ }
+--
+1.7.1
+
diff --git a/main/opennhrp/APKBUILD b/main/opennhrp/APKBUILD
new file mode 100644
index 0000000000..610fd53db6
--- /dev/null
+++ b/main/opennhrp/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=opennhrp
+pkgver=0.12.1
+pkgrel=1
+pkgdesc="NBMA Next Hop Resolution Protocol daemon"
+url="http://sourceforge.net/projects/opennhrp"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="c-ares-dev"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2
+ 0001-netlink-ignore-kernel-routes-for-GRE-interfaces.patch
+ opennhrp-0.9.3-peer-up-bgp.patch
+ $pkgname.initd
+ $pkgname.confd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+
+ sed -i -e 's/-Werror//' Make.rules
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ install -Dm755 "$srcdir"/opennhrp.initd "$pkgdir"/etc/init.d/opennhrp
+ install -Dm644 "$srcdir"/opennhrp.confd "$pkgdir"/etc/conf.d/opennhrp
+}
+md5sums="31ada6dede3c62dac491002624d34778 opennhrp-0.12.1.tar.bz2
+d6dbf1ac009615cea63e0ede894133a0 0001-netlink-ignore-kernel-routes-for-GRE-interfaces.patch
+f81539fc92800bb79668dda119a97d1d opennhrp-0.9.3-peer-up-bgp.patch
+ae65f88ccf849ef882669a8b4f0c7fc0 opennhrp.initd
+8eee86233728dc0d156bbfee6d98f338 opennhrp.confd"
diff --git a/main/opennhrp/opennhrp-0.9.3-peer-up-bgp.patch b/main/opennhrp/opennhrp-0.9.3-peer-up-bgp.patch
new file mode 100644
index 0000000000..60e4827d6f
--- /dev/null
+++ b/main/opennhrp/opennhrp-0.9.3-peer-up-bgp.patch
@@ -0,0 +1,11 @@
+diff -ru opennhrp-0.9.3.orig/etc/opennhrp-script opennhrp-0.9.3/etc/opennhrp-script
+--- opennhrp-0.9.3.orig/etc/opennhrp-script 2009-02-26 10:35:38 +0000
++++ opennhrp-0.9.3/etc/opennhrp-script 2009-02-26 10:52:26 +0000
+@@ -15,6 +15,7 @@
+ echo "Create link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)"
+ racoonctl establish-sa -w isakmp inet $NHRP_SRCNBMA $NHRP_DESTNBMA || exit 1
+ racoonctl establish-sa -w esp inet $NHRP_SRCNBMA $NHRP_DESTNBMA gre || exit 1
++ vtysh -d bgpd -c "clear bgp $NHRP_DESTADDR" 2>/dev/null || true
+ ;;
+ peer-down)
+ echo "Delete link from $NHRP_SRCADDR ($NHRP_SRCNBMA) to $NHRP_DESTADDR ($NHRP_DESTNBMA)"
diff --git a/main/opennhrp/opennhrp.confd b/main/opennhrp/opennhrp.confd
new file mode 100644
index 0000000000..c3bece169e
--- /dev/null
+++ b/main/opennhrp/opennhrp.confd
@@ -0,0 +1,2 @@
+# Uncomment the row below to enable verbose logging.
+#OPENNHRP_OPTS=-v
diff --git a/main/opennhrp/opennhrp.initd b/main/opennhrp/opennhrp.initd
new file mode 100755
index 0000000000..6ddb9eca20
--- /dev/null
+++ b/main/opennhrp/opennhrp.initd
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-analyzer/net-snmp/files/snmpd.rc7,v 1.1 2006/11/26 21:37:22 cedk Exp $
+
+PIDFILE=/var/run/opennhrp.pid
+
+depend() {
+ use logger dns
+ need net
+ after firewall ipsec
+}
+
+checkconfig() {
+ if [ ! -e /etc/opennhrp/opennhrp.conf ] ; then
+ eerror "You need an /etc/opennhrp/opennhrp.conf config file to run opennhrp"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting opennhrp"
+ start-stop-daemon --start --quiet --pidfile $PIDFILE \
+ --exec /usr/sbin/opennhrp -- -d -p $PIDFILE 2> /dev/null
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping opennhrp"
+ start-stop-daemon --stop --quiet --pidfile $PIDFILE
+ eend $?
+}
diff --git a/main/openntpd/APKBUILD b/main/openntpd/APKBUILD
new file mode 100644
index 0000000000..af55367719
--- /dev/null
+++ b/main/openntpd/APKBUILD
@@ -0,0 +1,47 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openntpd
+pkgver=3.9_p1
+_myver=3.9p1
+pkgrel=9
+pkgdesc="Lightweight NTP server ported from OpenBSD"
+url=http://www.openntpd.org/
+install=openntpd.pre-install
+
+subpackages="openntpd-doc"
+depends=
+makedepends="openssl-dev"
+arch="all"
+license=BSD
+source="
+ ftp://ftp.openbsd.org/pub/OpenBSD/OpenNTPD/openntpd-$_myver.tar.gz
+ openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff
+ openntpd.confd
+ openntpd.initd
+ "
+
+prepare() {
+ cd "$srcdir/$pkgname-$_myver"
+ patch -p1 < ../openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff
+ sed -i '/NTPD_USER/s:_ntp:ntp:' ntpd.h || return 1
+}
+
+build() {
+ cd "$srcdir/$pkgname-$_myver"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --sysconfdir=/etc \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$_myver"
+ make install DESTDIR="$pkgdir"
+ install -Dm755 ../openntpd.initd "$pkgdir/etc/init.d/ntpd"
+ install -Dm644 ../openntpd.confd "$pkgdir/etc/conf.d/ntpd"
+}
+
+md5sums="afc34175f38d08867c1403d9008600b3 openntpd-3.9p1.tar.gz
+ae2f708b860975b64126bb316aeb6641 openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff
+e3eee9eb2ea092dfdf9d887cd6df5795 openntpd.confd
+57a508a730359d526d3eb5afb525c0c3 openntpd.initd"
diff --git a/main/openntpd/openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff b/main/openntpd/openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff
new file mode 100644
index 0000000000..adca55614a
--- /dev/null
+++ b/main/openntpd/openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff
@@ -0,0 +1,43 @@
+diff -Naur openntpd-3.9p1/client.c openntpd-3.9p1-fixed/client.c
+--- openntpd-3.9p1/client.c 2006-05-14 07:29:21.000000000 +0200
++++ openntpd-3.9p1-fixed/client.c 2006-10-11 02:41:44.000000000 +0200
+@@ -116,6 +116,7 @@
+ client_query(struct ntp_peer *p)
+ {
+ int tos = IPTOS_LOWDELAY;
++ int result;
+
+ if (p->addr == NULL && client_nextaddr(p) == -1) {
+ set_next(p, error_interval());
+@@ -163,9 +164,17 @@
+ p->query->msg.xmttime.fractionl = arc4random();
+ p->query->xmttime = gettime();
+
+- if (ntp_sendmsg(p->query->fd, NULL, &p->query->msg,
+- NTP_MSGSIZE_NOAUTH, 0) == -1) {
++ if ((result = ntp_sendmsg(p->query->fd, NULL, &p->query->msg,
++ NTP_MSGSIZE_NOAUTH, 0)) < 0) {
+ set_next(p, INTERVAL_QUERY_PATHETIC);
++ if (result == -2) {
++ /*
++ * got EINVAL in sendto(), probably the local socket
++ * address got invalidated -> force re-connect()
++ */
++ close(p->query->fd);
++ p->query->fd = -1;
++ }
+ return (-1);
+ }
+
+diff -Naur openntpd-3.9p1/ntp_msg.c openntpd-3.9p1-fixed/ntp_msg.c
+--- openntpd-3.9p1/ntp_msg.c 2006-05-14 07:29:21.000000000 +0200
++++ openntpd-3.9p1-fixed/ntp_msg.c 2006-10-11 02:41:49.000000000 +0200
+@@ -98,6 +98,8 @@
+ return (-1);
+ }
+ log_warn("sendto");
++ if (errno == EINVAL)
++ return (-2);
+ return (-1);
+ }
+
diff --git a/main/openntpd/openntpd.confd b/main/openntpd/openntpd.confd
new file mode 100644
index 0000000000..6b938dc766
--- /dev/null
+++ b/main/openntpd/openntpd.confd
@@ -0,0 +1,7 @@
+# /etc/conf.d/ntpd: config file for openntpd's ntpd
+
+NTPD_HOME=/var/empty
+
+# See ntpd(8) man page ... some popular options:
+# -s Set the time immediately at startup
+NTPD_OPTS=""
diff --git a/main/openntpd/openntpd.initd b/main/openntpd/openntpd.initd
new file mode 100644
index 0000000000..825319a53d
--- /dev/null
+++ b/main/openntpd/openntpd.initd
@@ -0,0 +1,41 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/openntpd/files/openntpd.rc,v 1.7 2008/10/10 09:40:10 bangert Exp $
+
+depend() {
+ need net
+ provide ntp-client
+ use dns logger
+}
+
+checkconfig() {
+ if [ ! -f /etc/ntpd.conf ] ; then
+ eerror "Could not find /etc/ntpd.conf!"
+ return 1
+ fi
+
+ if [ -x /usr/bin/getent ] ; then
+ if [ "`getent passwd ntp | cut -d: -f 6`" != "${NTPD_HOME}" ] ; then
+ eerror "Home directory of ntp needs to be ${NTPD_HOME}"
+ eerror "Please run 'usermod -d ${NTPD_HOME} ntp'"
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+start() {
+ checkconfig || return $?
+
+ ebegin "Starting ntpd"
+ start-stop-daemon --start --exec /usr/sbin/ntpd --name ntpd -- ${NTPD_OPTS}
+ eend $? "Failed to start ntpd"
+}
+
+stop() {
+ ebegin "Stopping ntpd"
+ start-stop-daemon --stop --exec /usr/sbin/ntpd --name ntpd --user root
+ eend $? "Failed to stop openntpd"
+}
diff --git a/main/openntpd/openntpd.pre-install b/main/openntpd/openntpd.pre-install
new file mode 100644
index 0000000000..32c6f51293
--- /dev/null
+++ b/main/openntpd/openntpd.pre-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# this user should be included in alpine-baselayout-1.2.
+# included here for backward compability.
+adduser -H -h /var/empty -s /bin/false -D ntp 2>/dev/null
+
+exit 0
diff --git a/main/openobex/APKBUILD b/main/openobex/APKBUILD
new file mode 100644
index 0000000000..f91a54a19f
--- /dev/null
+++ b/main/openobex/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openobex
+pkgver=1.5
+pkgrel=4
+pkgdesc="Implementation of the OBject EXchange (OBEX) protocol"
+url="http://dev.zuckschwerdt.org/openobex/"
+arch="all"
+license="GPL LGPL"
+depends=
+depends_dev="libusb-compat-dev"
+makedepends="bluez-dev libusb-compat-dev"
+subpackages="$pkgname-dev libopenobex"
+source="http://www.kernel.org/pub/linux/bluetooth/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --enable-apps \
+ --enable-irda \
+ --enable-bluetooth \
+ --enable-usb \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+libopenobex() {
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libopenobex.so.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="fce1b82eafb74bde54fe117372393ba8 openobex-1.5.tar.bz2"
diff --git a/main/openrc/0001-Force-root-be-rw-before-localmount.patch b/main/openrc/0001-Force-root-be-rw-before-localmount.patch
new file mode 100644
index 0000000000..3381d9f0dd
--- /dev/null
+++ b/main/openrc/0001-Force-root-be-rw-before-localmount.patch
@@ -0,0 +1,26 @@
+From c92e702f6dddab58a749f5fea5479ff2affeb498 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue, 21 Dec 2010 10:29:37 +0000
+Subject: [PATCH] Force root be rw before localmount
+
+The service that pulls in root remount is mtab which we dont need/use.
+---
+ init.d/localmount.in | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/init.d/localmount.in b/init.d/localmount.in
+index a4d1116..2895894 100644
+--- a/init.d/localmount.in
++++ b/init.d/localmount.in
+@@ -6,7 +6,7 @@ description="Mounts disks and swap according to /etc/fstab."
+
+ depend()
+ {
+- need fsck
++ need fsck root
+ use lvm modules mtab
+ keyword -jail -openvz -prefix -vserver -lxc
+ }
+--
+1.7.3.4
+
diff --git a/main/openrc/0001-fsck-add-C0-and-T-options-unless-fsck-is-busybox.patch b/main/openrc/0001-fsck-add-C0-and-T-options-unless-fsck-is-busybox.patch
new file mode 100644
index 0000000000..86676e5ad7
--- /dev/null
+++ b/main/openrc/0001-fsck-add-C0-and-T-options-unless-fsck-is-busybox.patch
@@ -0,0 +1,38 @@
+From d1cb63729cb64cd3aebb14f00eaa8f03b90a57fe Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Wed, 9 Mar 2011 18:07:39 +0000
+Subject: [PATCH] fsck: add -C0 and -T options unless fsck is busybox
+
+---
+ init.d/fsck.in | 8 +++++++-
+ 1 files changed, 7 insertions(+), 1 deletions(-)
+
+diff --git a/init.d/fsck.in b/init.d/fsck.in
+index de44ea8..3b55fbd 100644
+--- a/init.d/fsck.in
++++ b/init.d/fsck.in
+@@ -30,6 +30,10 @@ _forcefsck()
+ [ -e /forcefsck ] || get_bootparam forcefsck
+ }
+
++_fsck_is_busybox() {
++ [ -L /sbin/fsck ] && [ "$(readlink -f /sbin/fsck)" = "/bin/busybox" ]
++}
++
+ start()
+ {
+ local fsck_opts= p= check_extra=
+@@ -60,7 +64,9 @@ start()
+ done
+
+ if [ "$RC_UNAME" = Linux ]; then
+- fsck_opts="$fsck_opts -C0 -T"
++ if ! _fsck_is_busybox; then
++ fsck_opts="$fsck_opts -C0 -T"
++ fi
+ if [ -z "$fsck_passno" ]; then
+ fsck_args=${fsck_args--A -p}
+ if echo 2>/dev/null >/.test.$$; then
+--
+1.7.4.1
+
diff --git a/main/openrc/APKBUILD b/main/openrc/APKBUILD
new file mode 100644
index 0000000000..812542cd1e
--- /dev/null
+++ b/main/openrc/APKBUILD
@@ -0,0 +1,78 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openrc
+pkgver=0.8.2
+_ver=${pkgver/_git*/}
+pkgrel=2
+pkgdesc="OpenRC manages the services, startup and shutdown of a host"
+url="http://git.overlays.gentoo.org/gitweb/?p=proj/openrc.git"
+arch="all"
+license='BSD-2'
+depends=""
+subpackages="$pkgname-doc $pkgname-dev"
+install="$pkgname.post-install $pkgname.post-upgrade"
+source="http://distfiles.gentoo.org/distfiles/$pkgname-$_ver.tar.bz2
+ openrc-0.4.3-mkmntdirs.patch
+
+ 0001-Force-root-be-rw-before-localmount.patch
+ 0001-fsck-add-C0-and-T-options-unless-fsck-is-busybox.patch
+ remove-rc_sys-warning.patch
+ hwclock-hctosys.patch
+
+ hostname.initd
+ hwdrivers.initd
+ keymaps.initd
+ modules.initd
+ modloop.initd
+ networking.initd
+ modloop.confd
+ "
+
+_builddir="$srcdir/$pkgname-$_ver"
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+ sed -i -e '/^sed/d' pkgconfig/Makefile
+}
+
+build() {
+ cd "$_builddir"
+ make LIBEXECDIR=/lib/rc || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make LIBEXECDIR=/lib/rc DESTDIR="$pkgdir/" install
+
+ # we cannot have anything turned on by default
+ rm -f "$pkgdir"/etc/runlevels/*/*
+
+ # we still use our ifup/ifdown based net config
+ rm -f "$pkgdir"/etc/conf.d/network "$pkgdir"/etc/init.d/network
+
+ # we override some of the scripts
+ for i in "$srcdir"/*.initd; do
+ j=${i##*/}
+ install -Dm755 $i "$pkgdir"/etc/init.d/${j%.initd}
+ done
+
+ install -D -m644 "$srcdir"/modloop.confd "$pkgdir"/etc/conf.d/modloop
+ install -d "$pkgdir"/etc/local.d
+}
+
+md5sums="a30f2e54f025b92fb40a0be5d464877d openrc-0.8.2.tar.bz2
+8c2c1c2ee0509b63966b7187a2079f4b openrc-0.4.3-mkmntdirs.patch
+4fd036ff07ed9ad7fb76af6a3ffc0695 0001-Force-root-be-rw-before-localmount.patch
+fb8baeaf32f4d53491312675f28a9939 0001-fsck-add-C0-and-T-options-unless-fsck-is-busybox.patch
+2a1749ee829877d80c3696eade59be8a remove-rc_sys-warning.patch
+95927c85beb1476bda46ab8933c5e780 hwclock-hctosys.patch
+c32e15b0858eef708497e7ee6355a055 hostname.initd
+b1e64885f301166df30be3e3cf5338ff hwdrivers.initd
+33ca3e558c42cdd17adccbc7807298f7 keymaps.initd
+098a1f16812f56fcb56eb6b6f0fa31f6 modules.initd
+408e28f247c7cc71fa104c07869417f4 modloop.initd
+af16db0d798392c7c0ed3434e4bad241 networking.initd
+c1ec888202d868710b5749f7b217d1e3 modloop.confd"
diff --git a/main/openrc/command-line-size-fix.patch b/main/openrc/command-line-size-fix.patch
new file mode 100644
index 0000000000..77fa2bd810
--- /dev/null
+++ b/main/openrc/command-line-size-fix.patch
@@ -0,0 +1,100 @@
+diff -ru a/src/librc/librc.h b/src/librc/librc.h
+--- a/src/librc/librc.h 2009-09-01 11:42:31.000000000 +0000
++++ b/src/librc/librc.h 2009-09-01 11:42:47.000000000 +0000
+@@ -72,8 +72,6 @@
+ #define librc_hidden_proto(x) hidden_proto(x)
+ #define librc_hidden_def(x) hidden_def(x)
+
+-ssize_t rc_getline(char **, size_t *, FILE *);
+-
+ librc_hidden_proto(rc_config_list)
+ librc_hidden_proto(rc_config_load)
+ librc_hidden_proto(rc_config_value)
+diff -ru a/src/librc/rc.h.in b/src/librc/rc.h.in
+--- a/src/librc/rc.h.in 2009-09-01 11:42:31.000000000 +0000
++++ b/src/librc/rc.h.in 2009-09-01 11:42:47.000000000 +0000
+@@ -517,5 +517,9 @@
+ * @return NULL terminated list of pids */
+ RC_PIDLIST *rc_find_pids(const char *, const char *const *, uid_t, pid_t);
+
++/* getline is a handy glibc function that not all libcs have, so
++ * we have our own */
++ssize_t rc_getline(char **, size_t *, FILE *);
++
+ __END_DECLS
+ #endif
+diff -ru a/src/librc/rc.map b/src/librc/rc.map
+--- a/src/librc/rc.map 2009-09-01 11:42:31.000000000 +0000
++++ b/src/librc/rc.map 2009-09-01 11:42:47.000000000 +0000
+@@ -12,6 +12,7 @@
+ rc_deptree_update_needed;
+ rc_environ_fd;
+ rc_find_pids;
++ rc_getline;
+ rc_newer_than;
+ rc_older_than;
+ rc_runlevel_exists;
+diff -ru a/src/rc/rc.c b/src/rc/rc.c
+--- a/src/rc/rc.c 2009-09-01 11:42:31.000000000 +0000
++++ b/src/rc/rc.c 2009-09-01 11:47:00.000000000 +0000
+@@ -43,10 +43,6 @@
+ #include <sys/utsname.h>
+ #include <sys/wait.h>
+
+-#ifdef __linux__
+-# include <asm/setup.h> /* for COMMAND_LINE_SIZE */
+-#endif
+-
+ #include <errno.h>
+ #include <dirent.h>
+ #include <ctype.h>
+@@ -177,10 +173,8 @@
+ proc_getent(const char *ent)
+ {
+ FILE *fp;
+- char proc[COMMAND_LINE_SIZE];
+- char *p;
+- char *value = NULL;
+- int i;
++ char *proc, *p, *value = NULL;
++ size_t i;
+
+ if (!exists("/proc/cmdline"))
+ return NULL;
+@@ -190,11 +184,11 @@
+ return NULL;
+ }
+
+- memset(proc, 0, sizeof(proc));
+- p = fgets(proc, sizeof(proc), fp);
+- if (p == NULL)
+- eerror("fgets: %s", strerror(errno));
+- else if (*proc && (p = strstr(proc, ent))) {
++ proc = NULL;
++ i = 0;
++ if (rc_getline(&proc, &i, fp) == -1 || proc == NULL)
++ eerror("rc_getline: %s", strerror(errno));
++ if (*proc && (p = strstr(proc, ent))) {
+ i = p - proc;
+ if (i == '\0' || proc[i - 1] == ' ') {
+ p += strlen(ent);
+@@ -205,6 +199,7 @@
+ } else
+ errno = ENOENT;
+ fclose(fp);
++ free(proc);
+
+ return value;
+ }
+diff -ru a/src/test/rc.funcs.list b/src/test/rc.funcs.list
+--- a/src/test/rc.funcs.list 2009-09-01 11:42:31.000000000 +0000
++++ b/src/test/rc.funcs.list 2009-09-01 11:42:57.000000000 +0000
+@@ -20,6 +20,8 @@
+ rc_deptree_update_needed@@RC_1.0
+ rc_find_pids
+ rc_find_pids@@RC_1.0
++rc_getline
++rc_getline@@RC_1.0
+ rc_newer_than
+ rc_newer_than@@RC_1.0
+ rc_older_than
diff --git a/main/openrc/dont-provide-ourself.patch b/main/openrc/dont-provide-ourself.patch
new file mode 100644
index 0000000000..2ff988f7f6
--- /dev/null
+++ b/main/openrc/dont-provide-ourself.patch
@@ -0,0 +1,14 @@
+Index: src/librc/librc-depend.c
+===================================================================
+--- a/src/librc/librc-depend.c (revision b4104957b198b38aba609ed3889e7fa605012d19)
++++ b/src/librc/librc-depend.c (revision 7fbb6ad42742ebc5e6ec244eedc85e9ac0a6236d)
+@@ -802,4 +802,9 @@
+ continue;
+ }
++
++ /* Don't provide ourself */
++ if (strcmp(type, "iprovide") == 0 &&
++ strcmp(depend, service) == 0)
++ continue;
+
+ /* .sh files are not init scripts */
diff --git a/main/openrc/hostname.initd b/main/openrc/hostname.initd
new file mode 100644
index 0000000000..995e4b95d8
--- /dev/null
+++ b/main/openrc/hostname.initd
@@ -0,0 +1,18 @@
+#!/sbin/runscript
+
+description="Sets the hostname of the machine."
+
+depend() {
+ keyword noprefix
+}
+
+start() {
+ if [ -f /etc/hostname ] ; then
+ opts="-F /etc/hostname"
+ else
+ opts="localhost"
+ fi
+ ebegin "Setting hostname"
+ hostname $opts
+ eend $?
+}
diff --git a/main/openrc/hwclock-hctosys.patch b/main/openrc/hwclock-hctosys.patch
new file mode 100644
index 0000000000..6616a9990f
--- /dev/null
+++ b/main/openrc/hwclock-hctosys.patch
@@ -0,0 +1,15 @@
+--- openrc-0.8.2.orig/init.d/hwclock.in
++++ openrc-0.8.2/init.d/hwclock.in
+@@ -94,11 +94,7 @@
+ "$utc_cmd" != --utc -o \
+ -n "$clock_args" ];
+ then
+- if yesno $clock_hctosys; then
+- _hwclock --hctosys $utc_cmd $clock_args
+- else
+- _hwclock --systz $utc_cmd $clock_args
+- fi
++ _hwclock --hctosys $utc_cmd $clock_args
+ retval=$(($retval + $?))
+ fi
+
diff --git a/main/openrc/hwdrivers.initd b/main/openrc/hwdrivers.initd
new file mode 100644
index 0000000000..3d0ebf12b5
--- /dev/null
+++ b/main/openrc/hwdrivers.initd
@@ -0,0 +1,27 @@
+#!/sbin/runscript
+
+depend() {
+ need sysfs dev
+ before checkfs fsck
+ after modloop
+ keyword novserver
+}
+
+# Load hardware drivers
+start() {
+ # check for boot option "nocoldplug"
+ if get_bootparam noautodetect; then
+ ewarn "Autodetection of hardware disabled from boot cmdline"
+ return 0
+ fi
+
+
+ ebegin "Loading hardware drivers"
+ find /sys -name modalias | xargs sort -u \
+ | xargs modprobe -a 2> /dev/null
+ # we run it twice so we detect all devices
+ find /sys -name modalias | xargs sort -u \
+ | xargs modprobe -a 2> /dev/null
+ eend 0
+}
+
diff --git a/main/openrc/keymaps.initd b/main/openrc/keymaps.initd
new file mode 100644
index 0000000000..8ee019c69d
--- /dev/null
+++ b/main/openrc/keymaps.initd
@@ -0,0 +1,20 @@
+#!/sbin/runscript
+
+description="Applies a keymap for the consoles."
+
+depend()
+{
+ need localmount
+ keyword noopenvz noprefix nouml novserver noxenu
+}
+
+start() {
+ [ -z "$KEYMAP" ] && return
+ ebegin "Setting keymap"
+ zcat "$KEYMAP" | loadkmap
+ eend $?
+}
+
+stop() {
+ return
+}
diff --git a/main/openrc/modloop.confd b/main/openrc/modloop.confd
new file mode 100644
index 0000000000..de4cbb62b8
--- /dev/null
+++ b/main/openrc/modloop.confd
@@ -0,0 +1,3 @@
+# enable loadable module support when running from RAM
+# when unionfs support is available in the kernel
+unionfs_size="32M"
diff --git a/main/openrc/modloop.initd b/main/openrc/modloop.initd
new file mode 100644
index 0000000000..714b6057a3
--- /dev/null
+++ b/main/openrc/modloop.initd
@@ -0,0 +1,100 @@
+#!/sbin/runscript
+
+# script that will mount image with modules
+
+depend() {
+ need dev
+ before checkfs fsck hwdrivers modules hwclock
+ keyword novserver
+}
+
+# read kernel options
+init_KOPT() {
+ eval set -- $(cat /proc/cmdline 2>/dev/null)
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ *=*) eval "KOPT_${1%%=*}='${1#*=}'" ;;
+ *) eval "KOPT_$(echo $1 | sed 's: :_:g')=yes" ;;
+ esac
+ shift
+ done
+}
+
+find_mnt() {
+ local dev="$1"
+ local fsfile="$2"
+ awk "\$ == \"$dev\" {print \$2}\"" "$fsfile" 2>/dev/null
+}
+
+# initialies: alpine_dev, alpine_mnt, alpine_fs, alpine_mounted
+find_media() {
+ init_KOPT
+ alpine_mounted=
+ alpine_dev=${KOPT_alpine_dev%%:*}
+ alpine_fs=${KOPT_alpine_dev#*:}
+ [ "$alpine_fs" = "$KOPT_alpine_dev" ] && unset alpine_fs
+ # first we check if alpine_dev is mounted and use this
+ alpine_mnt=$(find_mnt /dev/$alpine_dev /proc/mounts)
+ if [ -z "$alpine_mnt" ]; then
+ # then we check fstab
+ alpine_mnt=$(find_mnt /dev/$alpine_dev /etc/fstab)
+ else
+ alpine_mounted=yes
+ fi
+ # finally we fallback to /media/<devicename>
+ [ -z "$alpine_mnt" ] && alpine_mnt=/media/$alpine_dev
+}
+
+start() {
+ local modloop mount_opts
+ find_media
+ if [ -z "$alpine_dev" ] ; then
+ return 0
+ fi
+
+ modloop=${KOPT_modloop:-$KOPT_BOOT_IMAGE.cmg}
+ [ -n "$alpine_fs" ] && mount_opts="-t $alpine_fs"
+
+ ebegin "Mounting loopback device for kernel modules"
+ if [ -z "$alpine_mounted" ]; then
+ mount $mount_opts /dev/$alpine_dev $alpine_mnt 2>/dev/null
+ fi
+ mkdir -p /.modloop /lib
+
+ mount -o loop,ro -t cramfs $alpine_mnt/$modloop /.modloop
+
+ eend $? || return 1
+
+ #use unionfs is available and configured
+ if grep -q -w "unionfs$" /proc/filesystems && [ -n "$unionfs_size" ]; then
+ ebegin "UnionFS detected. Mounting modloop rw"
+ mkdir -p /.modunisonfs/modules /lib/modules
+ mount -t tmpfs -o size="$unionfs_size" tmpfs /.modunisonfs/modules
+ mount -t unionfs -o dirs=/.modunisonfs/modules=rw:/.modloop/modules=ro unionfs /lib/modules
+ eend $? || return 1
+ else
+ rm -rf /lib/modules && ln -sf /.modloop/modules /lib/
+ fi
+
+ # copy firmware if there are any
+ if [ -d $alpine_mnt/firmware ]; then
+ ebegin "Copying firmware from $alpine_mnt/firmware"
+ cp -R -a $alpine_mnt/firmware /lib/
+ eend $?
+ fi
+}
+
+stop() {
+ local rc=0
+ find_media
+ [ -z "$alpine_dev" ] && return 0
+ ebegin "Unmounting loopback device for kernel modules"
+ if mountinfo --quiet /.modloop; then
+ umount -d /.modloop || rc=1
+ fi
+ if mountinfo --quiet $alpine_mnt; then
+ umount $alpine_mnt || rc=1
+ fi
+ eend $rc
+}
+
diff --git a/main/openrc/modules.initd b/main/openrc/modules.initd
new file mode 100644
index 0000000000..ef7d1f15f1
--- /dev/null
+++ b/main/openrc/modules.initd
@@ -0,0 +1,23 @@
+#!/sbin/runscript
+
+description="Loads a user defined list of kernel modules."
+
+depend()
+{
+ before hwclock hwdrivers
+ keyword noopenvz noprefix novserver
+}
+
+
+start() {
+ if [ -f /etc/modules ] ; then
+ ebegin "Loading modules"
+ sed 's/\#.*//g' < /etc/modules |
+ while read module args
+ do
+ modprobe -q $module $args
+ done
+ eend $?
+ fi
+}
+
diff --git a/main/openrc/networking.initd b/main/openrc/networking.initd
new file mode 100644
index 0000000000..895db59eed
--- /dev/null
+++ b/main/openrc/networking.initd
@@ -0,0 +1,69 @@
+#!/sbin/runscript
+
+# note that the spoofprotect, syncoockies and ip_forward options are set in
+# /etc/sysctl.conf
+
+ifconf=/etc/network/interfaces
+ifstate=/var/run/ifstate
+
+single_iface="${SVCNAME#*.}"
+if [ "$single_iface" = "$SVCNAME" ]; then
+ single_iface=
+fi
+
+depend() {
+ after bootmisc hwdrivers modules
+ provide net
+ keyword nojail noprefix novserver
+}
+
+# find interfaces we want to start
+find_ifaces() {
+ if [ -n "$single_iface" ]; then
+ echo $single_iface
+ else
+ awk '$1 == "auto" {for (i = 2; i <= NF; i = i + 1) printf("%s ", $i)}' $ifconf
+ fi
+}
+
+# return the list of interfaces we should try stop
+find_running_ifaces() {
+ if [ -n "$single_iface" ]; then
+ echo $single_iface
+ else
+ awk -F= '{print $2}' $ifstate
+ fi
+}
+
+start() {
+ local iface= ret=1
+ ebegin "Starting networking"
+ eindent
+ for iface in $(find_ifaces); do
+ local r=0
+ ebegin "$iface"
+ if ! ifup $iface >/dev/null; then
+ ifdown $iface >/dev/null 2>&1
+ r=1
+ fi
+ # atleast one interface needs to be started for action
+ # to be success
+ eend $r && ret=0
+ done
+ eoutdent
+ return $ret
+}
+
+stop() {
+ local iface=
+ ebegin "Stopping networking"
+ eindent
+ for iface in $(find_running_ifaces); do
+ ebegin "$iface"
+ ifdown -f $iface >/dev/null
+ eend $?
+ done
+ eoutdent
+ return 0
+}
+
diff --git a/main/openrc/openrc-0.4.3-command-line-size-fix.patch b/main/openrc/openrc-0.4.3-command-line-size-fix.patch
new file mode 100644
index 0000000000..0ca4c8b1de
--- /dev/null
+++ b/main/openrc/openrc-0.4.3-command-line-size-fix.patch
@@ -0,0 +1,94 @@
+Index: src/librc/librc.h
+===================================================================
+--- a/src/librc/librc.h (revision 7c81f74b60b9d15ed472f1ca63cab0a105a84c08)
++++ b/src/librc/librc.h (revision 6abeec74301d8406ebbbd653b9fe9a0e234c09bf)
+@@ -73,6 +73,4 @@
+ #define librc_hidden_def(x) hidden_def(x)
+
+-ssize_t rc_getline(char **, size_t *, FILE *);
+-
+ librc_hidden_proto(rc_config_list)
+ librc_hidden_proto(rc_config_load)
+Index: src/librc/rc.h.in
+===================================================================
+--- a/src/librc/rc.h.in (revision c0fd1b49e49cec28c1f5a3a76f9db11c62e550dc)
++++ b/src/librc/rc.h.in (revision 6abeec74301d8406ebbbd653b9fe9a0e234c09bf)
+@@ -518,4 +518,8 @@
+ RC_PIDLIST *rc_find_pids(const char *, const char *const *, uid_t, pid_t);
+
++/* getline is a handy glibc function that not all libcs have, so
++ * we have our own */
++ssize_t rc_getline(char **, size_t *, FILE *);
++
+ __END_DECLS
+ #endif
+Index: src/librc/rc.map
+===================================================================
+--- a/src/librc/rc.map (revision 6615eb4b689d7aa1d047bd9ed75eca80beac9767)
++++ b/src/librc/rc.map (revision 6abeec74301d8406ebbbd653b9fe9a0e234c09bf)
+@@ -13,4 +13,5 @@
+ rc_environ_fd;
+ rc_find_pids;
++ rc_getline;
+ rc_newer_than;
+ rc_older_than;
+Index: src/rc/rc.c
+===================================================================
+--- a/src/rc/rc.c
++++ b/src/rc/rc.c
+@@ -43,10 +43,6 @@
+ #include <sys/utsname.h>
+ #include <sys/wait.h>
+
+-#ifdef __linux__
+-# include <asm/setup.h> /* for COMMAND_LINE_SIZE */
+-#endif
+-
+ #include <errno.h>
+ #include <dirent.h>
+ #include <ctype.h>
+@@ -176,10 +172,8 @@
+ proc_getent(const char *ent)
+ {
+ FILE *fp;
+- char proc[COMMAND_LINE_SIZE];
+- char *p;
+- char *value = NULL;
+- int i;
++ char *proc, *p, *value = NULL;
++ size_t i;
+
+ if (!exists("/proc/cmdline"))
+ return NULL;
+@@ -189,8 +183,10 @@
+ return NULL;
+ }
+
+- memset(proc, 0, sizeof(proc));
+- fgets(proc, sizeof(proc), fp);
++ proc = NULL;
++ i = 0;
++ if (rc_getline(&proc, &i, fp) == -1 || proc == NULL)
++ eerror("rc_getline: %s", strerror(errno));
+ if (*proc && (p = strstr(proc, ent))) {
+ i = p - proc;
+ if (i == '\0' || proc[i - 1] == ' ') {
+@@ -202,6 +198,7 @@
+ } else
+ errno = ENOENT;
+ fclose(fp);
++ free(proc);
+
+ return value;
+ }
+Index: src/test/rc.funcs.list
+===================================================================
+--- a/src/test/rc.funcs.list (revision 6615eb4b689d7aa1d047bd9ed75eca80beac9767)
++++ b/src/test/rc.funcs.list (revision 6abeec74301d8406ebbbd653b9fe9a0e234c09bf)
+@@ -21,4 +21,6 @@
+ rc_find_pids
+ rc_find_pids@@RC_1.0
++rc_getline
++rc_getline@@RC_1.0
+ rc_newer_than
+ rc_newer_than@@RC_1.0
diff --git a/main/openrc/openrc-0.4.3-mkmntdirs.patch b/main/openrc/openrc-0.4.3-mkmntdirs.patch
new file mode 100644
index 0000000000..01512ad7c0
--- /dev/null
+++ b/main/openrc/openrc-0.4.3-mkmntdirs.patch
@@ -0,0 +1,11 @@
+diff -ru openrc-0.4.3.orig/init.d/localmount.in openrc-0.4.3/init.d/localmount.in
+--- openrc-0.4.3.orig/init.d/localmount.in 2009-04-19 14:24:11.000000000 +0000
++++ openrc-0.4.3/init.d/localmount.in 2009-04-19 14:25:06.000000000 +0000
+@@ -13,6 +13,7 @@
+
+ start()
+ {
++ [ -x /sbin/mkmntdirs ] && mkmntdirs
+ # Mount local filesystems in /etc/fstab.
+ local types="noproc" x=
+ for x in ${net_fs_list}; do
diff --git a/main/openrc/openrc-hwclock.patch b/main/openrc/openrc-hwclock.patch
new file mode 100644
index 0000000000..593e9ba82f
--- /dev/null
+++ b/main/openrc/openrc-hwclock.patch
@@ -0,0 +1,13 @@
+Index: hwclock.in
+===================================================================
+--- a/init.d/hwclock.in (revision 1571)
++++ b/niit.d/hwclock.in (working copy)
+@@ -118,7 +118,7 @@
+
+ if ! yesno $clock_adjfile; then
+ # Some implementations don't handle adjustments
+- if LC_ALL=C hwclock --help | grep -q "\-\-noadjfile"; then
++ if LC_ALL=C hwclock --help 2>&1 | grep -q "\-\-noadjfile"; then
+ utc_cmd="$utc_cmd --noadjfile"
+ fi
+ fi
diff --git a/main/openrc/openrc.post-install b/main/openrc/openrc.post-install
new file mode 100644
index 0000000000..1057eed416
--- /dev/null
+++ b/main/openrc/openrc.post-install
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+rc_update() {
+ local svc="$1"
+ local level="$2"
+ mkdir -p /etc/runlevels/$level
+ ln -sf /etc/init.d/$svc /etc/runlevels/$level
+}
+
+if [ ! -d etc/rcS.d ] && [ ! -d etc/rcL.d ]; then
+ exit 0
+fi
+
+for i in etc/rc[SL].d/*; do
+ [ -L "$i" ] || continue
+ oldsvc=${i##*/S[0-9][0-9]}
+ # some services are renamed
+ case "$oldsvc" in
+ modutils) svc=modules;;
+ procps) svc=sysctl;;
+ bootmisc.sh) svc=bootmisc;;
+ keymap) svc=keymaps;;
+ rc.local) svc=local;;
+ *) svc=$oldsvc;;
+ esac
+
+ # add the service to correct "runlevel"
+ case "$svc" in
+ hwclock|modules|sysctl|hostname|keymaps|syslog|bootmisc)
+ rc_update $svc boot;;
+ *) rc_update $svc default;;
+ esac
+
+ rm $i
+done
+
diff --git a/main/openrc/openrc.post-upgrade b/main/openrc/openrc.post-upgrade
new file mode 100644
index 0000000000..76c2da75eb
--- /dev/null
+++ b/main/openrc/openrc.post-upgrade
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# in 0.8.0-r1 the state dir moved from /libexec/rc/init.d to /lib/rc/init.d
+
+[ -d /libexec/rc/init.d ] || exit 0
+
+for i in /libexec/rc/init.d/* ; do
+ [ -e "$i" ] || continue
+ mv $i /lib/rc/init.d/
+done
+
+rmdir /libexec/rc/init.d /libexec/rc /libexec 2>/dev/null
+
+
+# create rc.local compat
+if [ -f /etc/rc.local ]; then
+ cat >/etc/local.d/rc.local-compat.start<<__EOF__
+#!/bin/sh
+
+# this is only here for compatibility reasons
+if [ -f /etc/rc.local ]; then
+ . /etc/rc.local
+fi
+__EOF__
+ chmod +x /etc/local.d/rc.local-compat.start
+fi
+
+exit 0
diff --git a/main/openrc/remove-rc_sys-warning.patch b/main/openrc/remove-rc_sys-warning.patch
new file mode 100644
index 0000000000..4f11674888
--- /dev/null
+++ b/main/openrc/remove-rc_sys-warning.patch
@@ -0,0 +1,10 @@
+--- ./src/rc/rc.c.orig
++++ ./src/rc/rc.c
+@@ -878,7 +878,6 @@
+ if (bootlevel)
+ printf("%s\n", bootlevel);
+ } else {
+- ewarn("WARNING: rc_sys not defined in rc.conf. Falling back to automatic detection");
+ bootlevel = rc_sys_v1();
+ if (bootlevel)
+ printf("%s\n", bootlevel);
diff --git a/main/openresolv/APKBUILD b/main/openresolv/APKBUILD
new file mode 100644
index 0000000000..894a02f694
--- /dev/null
+++ b/main/openresolv/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openresolv
+pkgver=3.4.0
+pkgrel=0
+pkgdesc="A framework for managing DNS information"
+url="http://roy.marples.name/projects/openresolv"
+arch="noarch"
+license="BSD-2"
+depends=""
+subpackages="$pkgname-doc"
+source="http://roy.marples.name/downloads/openresolv/openresolv-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --libexecdir=/usr/lib \
+ --sysconfdir=/etc \
+ || return
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+md5sums="37a916c5d8157cd7c0edbb8621573804 openresolv-3.4.0.tar.bz2"
diff --git a/main/openssh/APKBUILD b/main/openssh/APKBUILD
new file mode 100644
index 0000000000..0b22131d4b
--- /dev/null
+++ b/main/openssh/APKBUILD
@@ -0,0 +1,92 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openssh
+pkgver=5.8_p2
+_myver=${pkgver%_*}${pkgver#*_}
+pkgrel=0
+pkgdesc="Port of OpenBSD's free SSH release"
+url="http://www.openssh.org/portable.html"
+arch="all"
+license="as-is"
+depends="openssh-client"
+makedepends="openssl-dev zlib-dev"
+subpackages="$pkgname-doc $pkgname-client"
+source="ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/$pkgname-$_myver.tar.gz
+ http://www.psc.edu/networking/projects/hpn-ssh/openssh${pkgver%_*}-dynwindow_noneswitch.diff.gz
+ http://www.psc.edu/networking/projects/hpn-ssh/openssh${pkgver%_*}-peaktput.diff
+ sshd.initd
+ sshd.confd
+ "
+
+_builddir="$srcdir"/$pkgname-$_myver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case "$i" in
+ *.diff.gz)
+ msg "Applying $i"
+ gunzip -c "$srcdir"/"${i##*/}" | patch -p1 -N || return 1
+ ;;
+ *.diff)
+ msg "Applying $i"
+ patch -p1 -N -i "$srcdir"/${i##*/}
+ if [ $? -gt 1 ]; then
+ return 1
+ fi
+ ;;
+ esac
+ done
+ sed -i -e '/_PATH_XAUTH/s:/usr/X11R6/bin/xauth:/usr/bin/xauth:' \
+ pathnames.h || return 1
+
+}
+
+build ()
+{
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-mantype=man \
+ --mandir=/usr/share/man \
+ --with-ldflags="${LDFLAGS}" \
+ --disable-strip \
+ --disable-lastlog \
+ --sysconfdir=/etc/ssh \
+ --datadir=/usr/share/openssh \
+ --with-privsep-path=/var/empty \
+ --with-privsep-user=sshd \
+ --with-md5-passwords \
+ --with-ssl-engine \
+ --libexecdir=/usr/lib/ssh \
+ --without-tcp-wrappers \
+ --without-pam \
+ || return 1
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ mkdir -p "$pkgdir"/var/empty
+ install -D -m755 "$srcdir"/sshd.initd "$pkgdir"/etc/init.d/sshd
+ install -D -m644 "$srcdir"/sshd.confd "$pkgdir"/etc/conf.d/sshd
+}
+
+client() {
+ pkgdesc="OpenBSD's SSH client"
+ replaces="openssh"
+ install -d "$subpkgdir"/usr/bin \
+ "$subpkgdir"/usr/lib/ssh \
+ "$subpkgdir"/etc/ssh \
+ "$subpkgdir"/var/run \
+ "$subpkgdir"/var/empty
+
+ mv "$pkgdir"/usr/bin/* "$subpkgdir"/usr/bin/
+ mv "$pkgdir"/usr/lib/ssh/ssh-keysign "$subpkgdir"/usr/lib/ssh/
+ mv "$pkgdir"/etc/ssh/ssh_config "$pkgdir"/etc/ssh/moduli \
+ "$subpkgdir"/etc/ssh/
+}
+
+md5sums="88a4a83b0e0e60cd545430d4e4bd7e0c openssh-5.8p2.tar.gz
+4c96723cb6dd02f76fe263c4d68c6a6f openssh5.8-dynwindow_noneswitch.diff.gz
+578fb646bab2d312172ec716970031b1 openssh5.8-peaktput.diff
+dda71d60ff5b4fbb61ad99fe83de6bc3 sshd.initd
+b35e9f3829f4cfca07168fcba98749c7 sshd.confd"
diff --git a/main/openssh/sshd.confd b/main/openssh/sshd.confd
new file mode 100644
index 0000000000..28952b4a28
--- /dev/null
+++ b/main/openssh/sshd.confd
@@ -0,0 +1,21 @@
+# /etc/conf.d/sshd: config file for /etc/init.d/sshd
+
+# Where is your sshd_config file stored?
+
+SSHD_CONFDIR="/etc/ssh"
+
+
+# Any random options you want to pass to sshd.
+# See the sshd(8) manpage for more info.
+
+SSHD_OPTS=""
+
+
+# Pid file to use (needs to be absolute path).
+
+#SSHD_PIDFILE="/var/run/sshd.pid"
+
+
+# Path to the sshd binary (needs to be absolute path).
+
+#SSHD_BINARY="/usr/sbin/sshd"
diff --git a/main/openssh/sshd.initd b/main/openssh/sshd.initd
new file mode 100644
index 0000000000..912d435c99
--- /dev/null
+++ b/main/openssh/sshd.initd
@@ -0,0 +1,92 @@
+#!/sbin/runscript
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/openssh/files/sshd.rc6.2,v 1.1 2011/01/24 02:55:47 vapier Exp $
+
+opts="${opts} reload checkconfig gen_keys"
+
+depend() {
+ use logger dns
+ need net
+ after firewall
+}
+
+SSHD_CONFDIR=${SSHD_CONFDIR:-/etc/ssh}
+SSHD_PIDFILE=${SSHD_PIDFILE:-/var/run/${SVCNAME}.pid}
+SSHD_BINARY=${SSHD_BINARY:-/usr/sbin/sshd}
+
+checkconfig() {
+ if [ ! -d /var/empty ] ; then
+ mkdir -p /var/empty || return 1
+ fi
+
+ if [ ! -e "${SSHD_CONFDIR}"/sshd_config ] ; then
+ eerror "You need an ${SSHD_CONFDIR}/sshd_config file to run sshd"
+ eerror "There is a sample file in /usr/share/doc/openssh"
+ return 1
+ fi
+
+ gen_keys || return 1
+
+ "${SSHD_BINARY}" -t ${myopts} || return 1
+}
+
+gen_key() {
+ local type=$1 key ks
+ [ $# -eq 1 ] && ks="${type}_"
+ key="${SSHD_CONFDIR}/ssh_host_${ks}key"
+ if [ ! -e "${key}" ] ; then
+ ebegin "Generating ${type} host key"
+ ssh-keygen -t ${type} -f "${key}" -N ''
+ eend $? || return $?
+ fi
+}
+
+gen_keys() {
+ if egrep -q '^[[:space:]]*Protocol[[:space:]]+.*1' "${SSHD_CONFDIR}"/sshd_config ; then
+ gen_key rsa1 "" || return 1
+ fi
+ gen_key dsa && gen_key rsa && gen_key ecdsa
+ return $?
+}
+
+start() {
+ local myopts=""
+ [ "${SSHD_PIDFILE}" != "/var/run/sshd.pid" ] \
+ && myopts="${myopts} -o PidFile=${SSHD_PIDFILE}"
+ [ "${SSHD_CONFDIR}" != "/etc/ssh" ] \
+ && myopts="${myopts} -f ${SSHD_CONFDIR}/sshd_config"
+
+ checkconfig || return 1
+ ebegin "Starting ${SVCNAME}"
+ start-stop-daemon --start --exec "${SSHD_BINARY}" \
+ --pidfile "${SSHD_PIDFILE}" \
+ -- ${myopts} ${SSHD_OPTS}
+ eend $?
+}
+
+stop() {
+ if [ "${RC_CMD}" = "restart" ] ; then
+ checkconfig || return 1
+ fi
+
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --exec "${SSHD_BINARY}" \
+ --pidfile "${SSHD_PIDFILE}" --quiet
+ eend $?
+
+ if [ "$RC_RUNLEVEL" = "shutdown" ]; then
+ ebegin "Shutting down ssh connections"
+ _sshd_pids=$(pgrep "${SSHD_BINARY##*/}: .* \[priv]")
+ kill -TERM $_sshd_pids 2>&1 >/dev/null
+ eend 0
+ fi
+}
+
+reload() {
+ checkconfig || return 1
+ ebegin "Reloading ${SVCNAME}"
+ start-stop-daemon --stop --signal HUP --oknodo \
+ --exec "${SSHD_BINARY}" --pidfile "${SSHD_PIDFILE}"
+ eend $?
+}
diff --git a/main/openssl/0001-crypto-hmac-support-EVP_MD_CTX_FLAG_ONESHOT-and-set-.patch b/main/openssl/0001-crypto-hmac-support-EVP_MD_CTX_FLAG_ONESHOT-and-set-.patch
new file mode 100644
index 0000000000..1c837bccb8
--- /dev/null
+++ b/main/openssl/0001-crypto-hmac-support-EVP_MD_CTX_FLAG_ONESHOT-and-set-.patch
@@ -0,0 +1,82 @@
+From 74e428937523858363f26f89d86db24932447ca1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Fri, 4 Jun 2010 09:48:39 +0300
+Subject: [PATCH 1/5] crypto/hmac: support EVP_MD_CTX_FLAG_ONESHOT and set it properly
+
+Some engines (namely VIA C7 Padlock) work only if EVP_MD_CTX_FLAG_ONESHOT
+is set before final update. This is because some crypto accelerators cannot
+perform non-finalizing transform of the digest.
+
+The usage of EVP_MD_CTX_FLAG_ONESHOT is used semantically slightly
+differently here. It is set before the final EVP_DigestUpdate call, not
+necessarily before EVP_DigestInit call. This will not cause any problems
+though.
+---
+ crypto/hmac/hmac.c | 14 +++++++++++---
+ 1 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c
+index 45015fe..55ad15c 100644
+--- a/crypto/hmac/hmac.c
++++ b/crypto/hmac/hmac.c
+@@ -66,6 +66,7 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+ {
+ int i,j,reset=0;
+ unsigned char pad[HMAC_MAX_MD_CBLOCK];
++ unsigned long flags;
+
+ if (md != NULL)
+ {
+@@ -82,6 +83,7 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+ OPENSSL_assert(j <= (int)sizeof(ctx->key));
+ if (j < len)
+ {
++ EVP_MD_CTX_set_flags(&ctx->md_ctx, EVP_MD_CTX_FLAG_ONESHOT);
+ if (!EVP_DigestInit_ex(&ctx->md_ctx,md, impl))
+ goto err;
+ if (!EVP_DigestUpdate(&ctx->md_ctx,key,len))
+@@ -105,17 +107,22 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+ {
+ for (i=0; i<HMAC_MAX_MD_CBLOCK; i++)
+ pad[i]=0x36^ctx->key[i];
++ flags = EVP_MD_CTX_test_flags(&ctx->i_ctx, EVP_MD_CTX_FLAG_ONESHOT);
++ EVP_MD_CTX_clear_flags(&ctx->i_ctx, EVP_MD_CTX_FLAG_ONESHOT);
+ if (!EVP_DigestInit_ex(&ctx->i_ctx,md, impl))
+ goto err;
+ if (!EVP_DigestUpdate(&ctx->i_ctx,pad,EVP_MD_block_size(md)))
+ goto err;
++ EVP_MD_CTX_set_flags(&ctx->i_ctx, flags);
+
+ for (i=0; i<HMAC_MAX_MD_CBLOCK; i++)
+ pad[i]=0x5c^ctx->key[i];
++ EVP_MD_CTX_clear_flags(&ctx->o_ctx, EVP_MD_CTX_FLAG_ONESHOT);
+ if (!EVP_DigestInit_ex(&ctx->o_ctx,md, impl))
+ goto err;
+ if (!EVP_DigestUpdate(&ctx->o_ctx,pad,EVP_MD_block_size(md)))
+ goto err;
++ EVP_MD_CTX_set_flags(&ctx->o_ctx, EVP_MD_CTX_FLAG_ONESHOT);
+ }
+ if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->i_ctx))
+ goto err;
+@@ -197,7 +204,8 @@ unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
+
+ if (md == NULL) md=m;
+ HMAC_CTX_init(&c);
+- if (!HMAC_Init(&c,key,key_len,evp_md))
++ HMAC_CTX_set_flags(&c, EVP_MD_CTX_FLAG_ONESHOT);
++ if (!HMAC_Init_ex(&c,key,key_len,evp_md,NULL))
+ goto err;
+ if (!HMAC_Update(&c,d,n))
+ goto err;
+@@ -212,6 +220,6 @@ unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
+ void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
+ {
+ EVP_MD_CTX_set_flags(&ctx->i_ctx, flags);
+- EVP_MD_CTX_set_flags(&ctx->o_ctx, flags);
+- EVP_MD_CTX_set_flags(&ctx->md_ctx, flags);
++ EVP_MD_CTX_set_flags(&ctx->o_ctx, flags & ~EVP_MD_CTX_FLAG_ONESHOT);
++ EVP_MD_CTX_set_flags(&ctx->md_ctx, flags & ~EVP_MD_CTX_FLAG_ONESHOT);
+ }
+--
+1.7.0.4
+
diff --git a/main/openssl/0002-apps-speed-fix-digest-speed-measurement-and-add-hmac.patch b/main/openssl/0002-apps-speed-fix-digest-speed-measurement-and-add-hmac.patch
new file mode 100644
index 0000000000..d292ad9bc0
--- /dev/null
+++ b/main/openssl/0002-apps-speed-fix-digest-speed-measurement-and-add-hmac.patch
@@ -0,0 +1,392 @@
+From ca1f332fbadc20d53d807d542fb37988a5508d32 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Thu, 3 Jun 2010 09:02:13 +0300
+Subject: [PATCH 2/5] apps/speed: fix digest speed measurement and add hmac-sha1 test
+
+Merge the common code of testing digest speed, and make it reuse
+existing context. Context creation can be heavy operation, and it's
+speed depends on if engine is used or not. As we are measuring the
+digest speed, the context creation overhead should not be included
+like hmac tests do.
+
+This also adds test for hmac-sha1 speed.
+---
+ apps/speed.c | 243 +++++++++++++++++++++-------------------------------------
+ 1 files changed, 86 insertions(+), 157 deletions(-)
+
+diff --git a/apps/speed.c b/apps/speed.c
+index 539bfff..f64289e 100644
+--- a/apps/speed.c
++++ b/apps/speed.c
+@@ -214,7 +214,7 @@ static void print_result(int alg,int run_no,int count,double time_used);
+ static int do_multi(int multi);
+ #endif
+
+-#define ALGOR_NUM 29
++#define ALGOR_NUM 30
+ #define SIZE_NUM 5
+ #define RSA_NUM 4
+ #define DSA_NUM 3
+@@ -229,9 +229,11 @@ static const char *names[ALGOR_NUM]={
+ "aes-128 cbc","aes-192 cbc","aes-256 cbc",
+ "camellia-128 cbc","camellia-192 cbc","camellia-256 cbc",
+ "evp","sha256","sha512","whirlpool",
+- "aes-128 ige","aes-192 ige","aes-256 ige"};
++ "aes-128 ige","aes-192 ige","aes-256 ige","hmac(sha1)"};
+ static double results[ALGOR_NUM][SIZE_NUM];
+ static int lengths[SIZE_NUM]={16,64,256,1024,8*1024};
++static unsigned char *buf=NULL,*buf2=NULL;
++static long c[ALGOR_NUM][SIZE_NUM];
+ #ifndef OPENSSL_NO_RSA
+ static double rsa_results[RSA_NUM][2];
+ #endif
+@@ -329,6 +331,66 @@ static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
+ }
+ #endif /* OPENSSL_NO_ECDH */
+
++#ifndef SIGALRM
++#define COND(d) (count < (d))
++#else
++#define COND(c) (run)
++#endif /* SIGALRM */
++
++static void Test_Digest(int digest, const EVP_MD *type)
++{
++ unsigned char md[EVP_MAX_MD_SIZE];
++ int j, count;
++ double d=0.0;
++ EVP_MD_CTX ctx;
++
++ EVP_MD_CTX_init(&ctx);
++ EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_ONESHOT);
++
++ for (j=0; j<SIZE_NUM; j++)
++ {
++ print_message(names[digest],c[digest][j],lengths[j]);
++ Time_F(START);
++ for (count=0,run=1; COND(c[digest][j]); count++)
++ {
++ EVP_DigestInit_ex(&ctx, type, NULL);
++ EVP_DigestUpdate(&ctx, buf, (unsigned long)lengths[j]);
++ EVP_DigestFinal_ex(&ctx, md, NULL);
++ }
++ d=Time_F(STOP);
++ print_result(digest,j,count,d);
++ }
++
++ EVP_MD_CTX_cleanup(&ctx);
++}
++
++static void Test_HMAC(int digest, const EVP_MD *type)
++{
++ unsigned char md[EVP_MAX_MD_SIZE];
++ HMAC_CTX hctx;
++ int j, count;
++ double d=0.0;
++
++ HMAC_CTX_init(&hctx);
++ HMAC_CTX_set_flags(&hctx, EVP_MD_CTX_FLAG_ONESHOT);
++ HMAC_Init_ex(&hctx,(unsigned char *)"This is a key...",
++ 16,type, NULL);
++
++ for (j=0; j<SIZE_NUM; j++)
++ {
++ print_message(names[digest],c[digest][j],lengths[j]);
++ Time_F(START);
++ for (count=0,run=1; COND(c[digest][j]); count++)
++ {
++ HMAC_Init_ex(&hctx,NULL,0,NULL,NULL);
++ HMAC_Update(&hctx,buf,lengths[j]);
++ HMAC_Final(&hctx,md,NULL);
++ }
++ d=Time_F(STOP);
++ print_result(digest,j,count,d);
++ }
++ HMAC_CTX_cleanup(&hctx);
++}
+
+ int MAIN(int, char **);
+
+@@ -337,7 +399,6 @@ int MAIN(int argc, char **argv)
+
+ int MAIN(int argc, char **argv)
+ {
+- unsigned char *buf=NULL,*buf2=NULL;
+ int mret=1;
+ long count=0,save_count=0;
+ int i,j,k;
+@@ -348,34 +409,6 @@ int MAIN(int argc, char **argv)
+ unsigned rsa_num;
+ #endif
+ unsigned char md[EVP_MAX_MD_SIZE];
+-#ifndef OPENSSL_NO_MD2
+- unsigned char md2[MD2_DIGEST_LENGTH];
+-#endif
+-#ifndef OPENSSL_NO_MDC2
+- unsigned char mdc2[MDC2_DIGEST_LENGTH];
+-#endif
+-#ifndef OPENSSL_NO_MD4
+- unsigned char md4[MD4_DIGEST_LENGTH];
+-#endif
+-#ifndef OPENSSL_NO_MD5
+- unsigned char md5[MD5_DIGEST_LENGTH];
+- unsigned char hmac[MD5_DIGEST_LENGTH];
+-#endif
+-#ifndef OPENSSL_NO_SHA
+- unsigned char sha[SHA_DIGEST_LENGTH];
+-#ifndef OPENSSL_NO_SHA256
+- unsigned char sha256[SHA256_DIGEST_LENGTH];
+-#endif
+-#ifndef OPENSSL_NO_SHA512
+- unsigned char sha512[SHA512_DIGEST_LENGTH];
+-#endif
+-#endif
+-#ifndef OPENSSL_NO_WHIRLPOOL
+- unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH];
+-#endif
+-#ifndef OPENSSL_NO_RIPEMD
+- unsigned char rmd160[RIPEMD160_DIGEST_LENGTH];
+-#endif
+ #ifndef OPENSSL_NO_RC4
+ RC4_KEY rc4_ks;
+ #endif
+@@ -473,8 +506,8 @@ int MAIN(int argc, char **argv)
+ #define D_IGE_128_AES 26
+ #define D_IGE_192_AES 27
+ #define D_IGE_256_AES 28
++#define D_HMAC_SHA1 29
+ double d=0.0;
+- long c[ALGOR_NUM][SIZE_NUM];
+ #define R_DSA_512 0
+ #define R_DSA_1024 1
+ #define R_DSA_2048 2
+@@ -783,6 +816,8 @@ int MAIN(int argc, char **argv)
+ doit[D_SHA256]=1,
+ doit[D_SHA512]=1;
+ else
++ if (strcmp(*argv,"hmac-sha1") == 0) doit[D_HMAC_SHA1]=1;
++ else
+ #ifndef OPENSSL_NO_SHA256
+ if (strcmp(*argv,"sha256") == 0) doit[D_SHA256]=1;
+ else
+@@ -1000,6 +1035,9 @@ int MAIN(int argc, char **argv)
+ #endif
+ #ifndef OPENSSL_NO_SHA1
+ BIO_printf(bio_err,"sha1 ");
++#ifndef OPENSSL_NO_HMAC
++ BIO_printf(bio_err,"hmac-sha1 ");
++#endif
+ #endif
+ #ifndef OPENSSL_NO_SHA256
+ BIO_printf(bio_err,"sha256 ");
+@@ -1270,6 +1308,7 @@ int MAIN(int argc, char **argv)
+ c[D_IGE_128_AES][0]=count;
+ c[D_IGE_192_AES][0]=count;
+ c[D_IGE_256_AES][0]=count;
++ c[D_HMAC_SHA1][0]=count;
+
+ for (i=1; i<SIZE_NUM; i++)
+ {
+@@ -1283,6 +1322,7 @@ int MAIN(int argc, char **argv)
+ c[D_SHA256][i]=c[D_SHA256][0]*4*lengths[0]/lengths[i];
+ c[D_SHA512][i]=c[D_SHA512][0]*4*lengths[0]/lengths[i];
+ c[D_WHIRLPOOL][i]=c[D_WHIRLPOOL][0]*4*lengths[0]/lengths[i];
++ c[D_HMAC_SHA1][i]=c[D_HMAC_SHA1][0]*4*lengths[0]/lengths[i];
+ }
+ for (i=1; i<SIZE_NUM; i++)
+ {
+@@ -1457,15 +1497,11 @@ int MAIN(int argc, char **argv)
+ }
+ #endif
+
+-#define COND(d) (count < (d))
+-#define COUNT(d) (d)
+ #else
+ /* not worth fixing */
+ # error "You cannot disable DES on systems without SIGALRM."
+ #endif /* OPENSSL_NO_DES */
+ #else
+-#define COND(c) (run)
+-#define COUNT(d) (count)
+ #ifndef _WIN32
+ signal(SIGALRM,sig_done);
+ #endif
+@@ -1473,161 +1509,54 @@ int MAIN(int argc, char **argv)
+
+ #ifndef OPENSSL_NO_MD2
+ if (doit[D_MD2])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_MD2],c[D_MD2][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_MD2][j]); count++)
+- EVP_Digest(buf,(unsigned long)lengths[j],&(md2[0]),NULL,EVP_md2(),NULL);
+- d=Time_F(STOP);
+- print_result(D_MD2,j,count,d);
+- }
+- }
++ Test_Digest(D_MD2, EVP_md2());
+ #endif
+ #ifndef OPENSSL_NO_MDC2
+ if (doit[D_MDC2])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_MDC2],c[D_MDC2][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_MDC2][j]); count++)
+- EVP_Digest(buf,(unsigned long)lengths[j],&(mdc2[0]),NULL,EVP_mdc2(),NULL);
+- d=Time_F(STOP);
+- print_result(D_MDC2,j,count,d);
+- }
+- }
++ Test_Digest(D_MDC2, EVP_mdc2());
+ #endif
+
+ #ifndef OPENSSL_NO_MD4
+ if (doit[D_MD4])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_MD4],c[D_MD4][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_MD4][j]); count++)
+- EVP_Digest(&(buf[0]),(unsigned long)lengths[j],&(md4[0]),NULL,EVP_md4(),NULL);
+- d=Time_F(STOP);
+- print_result(D_MD4,j,count,d);
+- }
+- }
++ Test_Digest(D_MD4, EVP_md4());
+ #endif
+
+ #ifndef OPENSSL_NO_MD5
+ if (doit[D_MD5])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_MD5],c[D_MD5][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_MD5][j]); count++)
+- EVP_Digest(&(buf[0]),(unsigned long)lengths[j],&(md5[0]),NULL,EVP_get_digestbyname("md5"),NULL);
+- d=Time_F(STOP);
+- print_result(D_MD5,j,count,d);
+- }
+- }
++ Test_Digest(D_MD5, EVP_md5());
+ #endif
+
+ #if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_HMAC)
+ if (doit[D_HMAC])
+- {
+- HMAC_CTX hctx;
+-
+- HMAC_CTX_init(&hctx);
+- HMAC_Init_ex(&hctx,(unsigned char *)"This is a key...",
+- 16,EVP_md5(), NULL);
+-
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_HMAC],c[D_HMAC][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_HMAC][j]); count++)
+- {
+- HMAC_Init_ex(&hctx,NULL,0,NULL,NULL);
+- HMAC_Update(&hctx,buf,lengths[j]);
+- HMAC_Final(&hctx,&(hmac[0]),NULL);
+- }
+- d=Time_F(STOP);
+- print_result(D_HMAC,j,count,d);
+- }
+- HMAC_CTX_cleanup(&hctx);
+- }
++ Test_HMAC(D_HMAC, EVP_md5());
++#endif
++#if !defined(OPENSSL_NO_SHA1) && !defined(OPENSSL_NO_HMAC)
++ if (doit[D_HMAC_SHA1])
++ Test_HMAC(D_HMAC_SHA1, EVP_sha1());
+ #endif
+ #ifndef OPENSSL_NO_SHA
+ if (doit[D_SHA1])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_SHA1],c[D_SHA1][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_SHA1][j]); count++)
+- EVP_Digest(buf,(unsigned long)lengths[j],&(sha[0]),NULL,EVP_sha1(),NULL);
+- d=Time_F(STOP);
+- print_result(D_SHA1,j,count,d);
+- }
+- }
++ Test_Digest(D_SHA1, EVP_sha1());
+
+ #ifndef OPENSSL_NO_SHA256
+ if (doit[D_SHA256])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_SHA256],c[D_SHA256][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_SHA256][j]); count++)
+- SHA256(buf,lengths[j],sha256);
+- d=Time_F(STOP);
+- print_result(D_SHA256,j,count,d);
+- }
+- }
++ Test_Digest(D_SHA256, EVP_sha256());
+ #endif
+
+ #ifndef OPENSSL_NO_SHA512
+ if (doit[D_SHA512])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_SHA512],c[D_SHA512][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_SHA512][j]); count++)
+- SHA512(buf,lengths[j],sha512);
+- d=Time_F(STOP);
+- print_result(D_SHA512,j,count,d);
+- }
+- }
++ Test_Digest(D_SHA512, EVP_sha512());
+ #endif
+ #endif
+
+ #ifndef OPENSSL_NO_WHIRLPOOL
+ if (doit[D_WHIRLPOOL])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_WHIRLPOOL],c[D_WHIRLPOOL][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_WHIRLPOOL][j]); count++)
+- WHIRLPOOL(buf,lengths[j],whirlpool);
+- d=Time_F(STOP);
+- print_result(D_WHIRLPOOL,j,count,d);
+- }
+- }
++ Test_Digest(D_WHIRLPOOL, EVP_whirlpool());
+ #endif
+
+ #ifndef OPENSSL_NO_RIPEMD
+ if (doit[D_RMD160])
+- {
+- for (j=0; j<SIZE_NUM; j++)
+- {
+- print_message(names[D_RMD160],c[D_RMD160][j],lengths[j]);
+- Time_F(START);
+- for (count=0,run=1; COND(c[D_RMD160][j]); count++)
+- EVP_Digest(buf,(unsigned long)lengths[j],&(rmd160[0]),NULL,EVP_ripemd160(),NULL);
+- d=Time_F(STOP);
+- print_result(D_RMD160,j,count,d);
+- }
+- }
++ Test_Digest(D_RMD160, EVP_ripemd160());
+ #endif
+ #ifndef OPENSSL_NO_RC4
+ if (doit[D_RC4])
+--
+1.7.0.4
+
diff --git a/main/openssl/0003-engines-e_padlock-backport-cvs-head-changes.patch b/main/openssl/0003-engines-e_padlock-backport-cvs-head-changes.patch
new file mode 100644
index 0000000000..a590269b99
--- /dev/null
+++ b/main/openssl/0003-engines-e_padlock-backport-cvs-head-changes.patch
@@ -0,0 +1,203 @@
+From 1d27eeb41fbc2e8f36f156d4d66d04486afee742 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Wed, 28 Jul 2010 08:29:09 +0300
+Subject: [PATCH 3/5] engines/e_padlock: backport cvs head changes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Includes support for VIA Nano 64-bit mode.
+
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+ engines/e_padlock.c | 140 ++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 files changed, 122 insertions(+), 18 deletions(-)
+
+diff --git a/engines/e_padlock.c b/engines/e_padlock.c
+index 381a746..4300f35 100644
+--- a/engines/e_padlock.c
++++ b/engines/e_padlock.c
+@@ -101,7 +101,10 @@
+ compiler choice is limited to GCC and Microsoft C. */
+ #undef COMPILE_HW_PADLOCK
+ #if !defined(I386_ONLY) && !defined(OPENSSL_NO_INLINE_ASM)
+-# if (defined(__GNUC__) && (defined(__i386__) || defined(__i386))) || \
++# if (defined(__GNUC__) && __GNUC__>=2 && \
++ (defined(__i386__) || defined(__i386) || \
++ defined(__x86_64__) || defined(__x86_64)) \
++ ) || \
+ (defined(_MSC_VER) && defined(_M_IX86))
+ # define COMPILE_HW_PADLOCK
+ static ENGINE *ENGINE_padlock (void);
+@@ -294,6 +297,7 @@ static volatile struct padlock_cipher_data *padlock_saved_context;
+ * =======================================================
+ */
+ #if defined(__GNUC__) && __GNUC__>=2
++#if defined(__i386__) || defined(__i386)
+ /*
+ * As for excessive "push %ebx"/"pop %ebx" found all over.
+ * When generating position-independent code GCC won't let
+@@ -373,21 +377,6 @@ padlock_available(void)
+ return padlock_use_ace + padlock_use_rng;
+ }
+
+-#ifndef OPENSSL_NO_AES
+-/* Our own htonl()/ntohl() */
+-static inline void
+-padlock_bswapl(AES_KEY *ks)
+-{
+- size_t i = sizeof(ks->rd_key)/sizeof(ks->rd_key[0]);
+- unsigned int *key = ks->rd_key;
+-
+- while (i--) {
+- asm volatile ("bswapl %0" : "+r"(*key));
+- key++;
+- }
+-}
+-#endif
+-
+ /* Force key reload from memory to the CPU microcode.
+ Loading EFLAGS from the stack clears EFLAGS[30]
+ which does the trick. */
+@@ -445,12 +434,127 @@ static inline void *name(size_t cnt, \
+ : "edx", "cc", "memory"); \
+ return iv; \
+ }
++#endif
++
++#elif defined(__x86_64__) || defined(__x86_64)
++
++/* Load supported features of the CPU to see if
++ the PadLock is available. */
++static int
++padlock_available(void)
++{
++ char vendor_string[16];
++ unsigned int eax, edx;
+
++ /* Are we running on the Centaur (VIA) CPU? */
++ eax = 0x00000000;
++ vendor_string[12] = 0;
++ asm volatile (
++ "cpuid\n"
++ "movl %%ebx,(%1)\n"
++ "movl %%edx,4(%1)\n"
++ "movl %%ecx,8(%1)\n"
++ : "+a"(eax) : "r"(vendor_string) : "rbx", "rcx", "rdx");
++ if (strcmp(vendor_string, "CentaurHauls") != 0)
++ return 0;
++
++ /* Check for Centaur Extended Feature Flags presence */
++ eax = 0xC0000000;
++ asm volatile ("cpuid"
++ : "+a"(eax) : : "rbx", "rcx", "rdx");
++ if (eax < 0xC0000001)
++ return 0;
++
++ /* Read the Centaur Extended Feature Flags */
++ eax = 0xC0000001;
++ asm volatile ("cpuid"
++ : "+a"(eax), "=d"(edx) : : "rbx", "rcx");
++
++ /* Fill up some flags */
++ padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
++ padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
++
++ return padlock_use_ace + padlock_use_rng;
++}
++
++/* Force key reload from memory to the CPU microcode.
++ Loading EFLAGS from the stack clears EFLAGS[30]
++ which does the trick. */
++static inline void
++padlock_reload_key(void)
++{
++ asm volatile ("pushfq; popfq");
++}
++
++#ifndef OPENSSL_NO_AES
++/*
++ * This is heuristic key context tracing. At first one
++ * believes that one should use atomic swap instructions,
++ * but it's not actually necessary. Point is that if
++ * padlock_saved_context was changed by another thread
++ * after we've read it and before we compare it with cdata,
++ * our key *shall* be reloaded upon thread context switch
++ * and we are therefore set in either case...
++ */
++static inline void
++padlock_verify_context(struct padlock_cipher_data *cdata)
++{
++ asm volatile (
++ "pushfq\n"
++" btl $30,(%%rsp)\n"
++" jnc 1f\n"
++" cmpq %2,%1\n"
++" je 1f\n"
++" popfq\n"
++" subq $8,%%rsp\n"
++"1: addq $8,%%rsp\n"
++" movq %2,%0"
++ :"+m"(padlock_saved_context)
++ : "r"(padlock_saved_context), "r"(cdata) : "cc");
++}
++
++/* Template for padlock_xcrypt_* modes */
++/* BIG FAT WARNING:
++ * The offsets used with 'leal' instructions
++ * describe items of the 'padlock_cipher_data'
++ * structure.
++ */
++#define PADLOCK_XCRYPT_ASM(name,rep_xcrypt) \
++static inline void *name(size_t cnt, \
++ struct padlock_cipher_data *cdata, \
++ void *out, const void *inp) \
++{ void *iv; \
++ asm volatile ( "leaq 16(%0),%%rdx\n" \
++ " leaq 32(%0),%%rbx\n" \
++ rep_xcrypt "\n" \
++ : "=a"(iv), "=c"(cnt), "=D"(out), "=S"(inp) \
++ : "0"(cdata), "1"(cnt), "2"(out), "3"(inp) \
++ : "rbx", "rdx", "cc", "memory"); \
++ return iv; \
++}
++#endif
++
++#endif /* cpu */
++
++#ifndef OPENSSL_NO_AES
+ /* Generate all functions with appropriate opcodes */
+ PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb, ".byte 0xf3,0x0f,0xa7,0xc8") /* rep xcryptecb */
+ PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc, ".byte 0xf3,0x0f,0xa7,0xd0") /* rep xcryptcbc */
+ PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb, ".byte 0xf3,0x0f,0xa7,0xe0") /* rep xcryptcfb */
+ PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb, ".byte 0xf3,0x0f,0xa7,0xe8") /* rep xcryptofb */
++
++/* Our own htonl()/ntohl() */
++static inline void
++padlock_bswapl(AES_KEY *ks)
++{
++ size_t i = sizeof(ks->rd_key)/sizeof(ks->rd_key[0]);
++ unsigned int *key = ks->rd_key;
++
++ while (i--) {
++ asm volatile ("bswapl %0" : "+r"(*key));
++ key++;
++ }
++}
+ #endif
+
+ /* The RNG call itself */
+@@ -481,8 +585,8 @@ padlock_xstore(void *addr, unsigned int edx_in)
+ static inline unsigned char *
+ padlock_memcpy(void *dst,const void *src,size_t n)
+ {
+- long *d=dst;
+- const long *s=src;
++ size_t *d=dst;
++ const size_t *s=src;
+
+ n /= sizeof(*d);
+ do { *d++ = *s++; } while (--n);
+--
+1.7.0.4
+
diff --git a/main/openssl/0004-engines-e_padlock-implement-sha1-sha224-sha256-accel.patch b/main/openssl/0004-engines-e_padlock-implement-sha1-sha224-sha256-accel.patch
new file mode 100644
index 0000000000..d1bb3704b7
--- /dev/null
+++ b/main/openssl/0004-engines-e_padlock-implement-sha1-sha224-sha256-accel.patch
@@ -0,0 +1,780 @@
+From b235a1c0686e5f4f32703c0eb0a75ee9902a7e89 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Wed, 28 Jul 2010 08:37:58 +0300
+Subject: [PATCH 4/5] engines/e_padlock: implement sha1/sha224/sha256 acceleration
+
+Limited support for VIA C7 that works only when EVP_MD_CTX_FLAG_ONESHOT
+is used appropriately (as done by EVP_Digest, and my previous HMAC patch).
+
+Full support for VIA Nano including partial transformation and 64-bit mode.
+
+Benchmarks from VIA Nano 1.6GHz, done with including the previous HMAC and
+apps/speed patches done. From single run, error margin of about 100-200k.
+
+No padlock
+
+type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
+sha1 20057.60k 51514.05k 99721.39k 130167.81k 142811.14k
+sha256 7757.72k 16907.18k 28937.05k 35181.23k 37568.51k
+hmac(sha1) 8582.53k 27644.69k 70402.30k 114602.67k 140167.85k
+
+With the patch
+
+sha1 37713.77k 114562.71k 259637.33k 379907.41k 438818.13k
+sha256 34262.86k 103233.75k 232476.07k 338386.60k 389860.01k
+hmac(sha1) 8424.70k 31475.11k 104036.10k 245559.30k 406667.26k
+---
+ engines/e_padlock.c | 660 +++++++++++++++++++++++++++++++++++++++++++++++----
+ 1 files changed, 613 insertions(+), 47 deletions(-)
+
+diff --git a/engines/e_padlock.c b/engines/e_padlock.c
+index 4300f35..3591c59 100644
+--- a/engines/e_padlock.c
++++ b/engines/e_padlock.c
+@@ -3,6 +3,9 @@
+ * Written by Michal Ludvig <michal@logix.cz>
+ * http://www.logix.cz/michal
+ *
++ * SHA support by Timo Teras <timo.teras@iki.fi>. Portions based on
++ * code originally written by Michal Ludvig.
++ *
+ * Big thanks to Andy Polyakov for a help with optimization,
+ * assembler fixes, port to MS Windows and a lot of other
+ * valuable work on this engine!
+@@ -64,7 +67,9 @@
+
+
+ #include <stdio.h>
++#include <stdint.h>
+ #include <string.h>
++#include <netinet/in.h>
+
+ #include <openssl/opensslconf.h>
+ #include <openssl/crypto.h>
+@@ -74,12 +79,33 @@
+ #ifndef OPENSSL_NO_AES
+ #include <openssl/aes.h>
+ #endif
++#ifndef OPENSSL_NO_SHA
++#include <openssl/sha.h>
++#endif
+ #include <openssl/rand.h>
+ #include <openssl/err.h>
+
+ #ifndef OPENSSL_NO_HW
+ #ifndef OPENSSL_NO_HW_PADLOCK
+
++/* PadLock RNG is disabled by default */
++#define PADLOCK_NO_RNG 1
++
++/* No ASM routines for SHA in MSC yet */
++#ifdef _MSC_VER
++#define OPENSSL_NO_SHA
++#endif
++
++/* 64-bit mode does not need software SHA1 as fallback, we can
++ * do all operations with padlock */
++#if defined(__x86_64__) || defined(__x86_64)
++#define PADLOCK_NEED_FALLBACK_SHA 0
++#else
++#define PADLOCK_NEED_FALLBACK_SHA 1
++#endif
++
++#define PADLOCK_MAX_FINALIZING_LENGTH 0x1FFFFFFE
++
+ /* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */
+ #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
+ # ifndef OPENSSL_NO_DYNAMIC_ENGINE
+@@ -143,58 +169,40 @@ static int padlock_available(void);
+ static int padlock_init(ENGINE *e);
+
+ /* RNG Stuff */
++#ifndef PADLOCK_NO_RNG
+ static RAND_METHOD padlock_rand;
+-
+-/* Cipher Stuff */
+-#ifndef OPENSSL_NO_AES
+-static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+ #endif
+
+ /* Engine names */
+ static const char *padlock_id = "padlock";
+ static char padlock_name[100];
+
+-/* Available features */
+-static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
+-static int padlock_use_rng = 0; /* Random Number Generator */
+-#ifndef OPENSSL_NO_AES
+-static int padlock_aes_align_required = 1;
+-#endif
++static int padlock_bind_helper(ENGINE *e);
+
+-/* ===== Engine "management" functions ===== */
+-
+-/* Prepare the ENGINE structure for registration */
+-static int
+-padlock_bind_helper(ENGINE *e)
+-{
+- /* Check available features */
+- padlock_available();
+-
+-#if 1 /* disable RNG for now, see commentary in vicinity of RNG code */
+- padlock_use_rng=0;
+-#endif
+-
+- /* Generate a nice engine name with available features */
+- BIO_snprintf(padlock_name, sizeof(padlock_name),
+- "VIA PadLock (%s, %s)",
+- padlock_use_rng ? "RNG" : "no-RNG",
+- padlock_use_ace ? "ACE" : "no-ACE");
++ /* Available features */
++enum padlock_flags {
++ PADLOCK_RNG = 0x01,
++ PADLOCK_ACE = 0x02,
++ PADLOCK_ACE2 = 0x04,
++ PADLOCK_PHE = 0x08,
++ PADLOCK_PMM = 0x10,
++ PADLOCK_NANO = 0x20,
++};
++enum padlock_flags padlock_flags;
+
+- /* Register everything or return with an error */
+- if (!ENGINE_set_id(e, padlock_id) ||
+- !ENGINE_set_name(e, padlock_name) ||
++#define PADLOCK_HAVE_RNG (padlock_flags & PADLOCK_RNG)
++#define PADLOCK_HAVE_ACE (padlock_flags & (PADLOCK_ACE|PADLOCK_ACE2))
++#define PADLOCK_HAVE_ACE1 (padlock_flags & PADLOCK_ACE)
++#define PADLOCK_HAVE_ACE2 (padlock_flags & PADLOCK_ACE2)
++#define PADLOCK_HAVE_PHE (padlock_flags & PADLOCK_PHE)
++#define PADLOCK_HAVE_PMM (padlock_flags & PADLOCK_PMM)
++#define PADLOCK_HAVE_NANO (padlock_flags & PADLOCK_NANO)
+
+- !ENGINE_set_init_function(e, padlock_init) ||
+ #ifndef OPENSSL_NO_AES
+- (padlock_use_ace && !ENGINE_set_ciphers (e, padlock_ciphers)) ||
++static int padlock_aes_align_required = 1;
+ #endif
+- (padlock_use_rng && !ENGINE_set_RAND (e, &padlock_rand))) {
+- return 0;
+- }
+
+- /* Everything looks good */
+- return 1;
+-}
++/* ===== Engine "management" functions ===== */
+
+ /* Constructor */
+ static ENGINE *
+@@ -218,7 +226,7 @@ ENGINE_padlock(void)
+ static int
+ padlock_init(ENGINE *e)
+ {
+- return (padlock_use_rng || padlock_use_ace);
++ return padlock_flags;
+ }
+
+ /* This stuff is needed if this ENGINE is being compiled into a self-contained
+@@ -371,10 +379,20 @@ padlock_available(void)
+ : "+a"(eax), "=d"(edx) : : "ecx");
+
+ /* Fill up some flags */
+- padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
+- padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
++ padlock_flags |= ((edx & (0x3<<3)) ? PADLOCK_RNG : 0);
++ padlock_flags |= ((edx & (0x3<<7)) ? PADLOCK_ACE : 0);
++ padlock_flags |= ((edx & (0x3<<9)) ? PADLOCK_ACE2 : 0);
++ padlock_flags |= ((edx & (0x3<<11)) ? PADLOCK_PHE : 0);
++ padlock_flags |= ((edx & (0x3<<13)) ? PADLOCK_PMM : 0);
++
++ /* Check for VIA Nano CPU */
++ eax = 0x00000001;
++ asm volatile ("pushl %%ebx; cpuid; popl %%ebx"
++ : "+a"(eax) : : "ecx", "edx");
++ if ((eax | 0x000F) == 0x06FF)
++ padlock_flags |= PADLOCK_NANO;
+
+- return padlock_use_ace + padlock_use_rng;
++ return padlock_flags;
+ }
+
+ /* Force key reload from memory to the CPU microcode.
+@@ -471,10 +489,14 @@ padlock_available(void)
+ : "+a"(eax), "=d"(edx) : : "rbx", "rcx");
+
+ /* Fill up some flags */
+- padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
+- padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
+-
+- return padlock_use_ace + padlock_use_rng;
++ padlock_flags |= ((edx & (0x3<<3)) ? PADLOCK_RNG : 0);
++ padlock_flags |= ((edx & (0x3<<7)) ? PADLOCK_ACE : 0);
++ padlock_flags |= ((edx & (0x3<<9)) ? PADLOCK_ACE2 : 0);
++ padlock_flags |= ((edx & (0x3<<11)) ? PADLOCK_PHE : 0);
++ padlock_flags |= ((edx & (0x3<<13)) ? PADLOCK_PMM : 0);
++ padlock_flags |= PADLOCK_NANO;
++
++ return padlock_flags;
+ }
+
+ /* Force key reload from memory to the CPU microcode.
+@@ -1263,6 +1285,496 @@ padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
+
+ #endif /* OPENSSL_NO_AES */
+
++#ifndef OPENSSL_NO_SHA
++
++static inline void
++padlock_copy_bswap(void *dst, void *src, size_t count)
++{
++ uint32_t *udst = dst, *usrc = src;
++ int i = 0;
++
++ for (i = 0; i < count; i++)
++ udst[i] = htonl(usrc[i]);
++}
++
++static unsigned long padlock_sha_prepare_padding(
++ EVP_MD_CTX *ctx,
++ unsigned char *padding,
++ unsigned char *data, size_t data_len,
++ uint64_t total)
++{
++ unsigned int padding_len;
++
++ padding_len = data_len < 56 ? SHA_CBLOCK : 2 * SHA_CBLOCK;
++ if (data_len)
++ memcpy(padding, data, data_len);
++
++ memset(padding + data_len, 0, padding_len - data_len);
++ padding[data_len] = 0x80;
++ *(uint32_t *)(padding + padding_len - 8) = htonl(total >> 32);
++ *(uint32_t *)(padding + padding_len - 4) = htonl(total & 0xffffffff);
++
++ return data_len < 56 ? 1 : 2;
++}
++
++#define PADLOCK_SHA_ALIGN(dd) (uint32_t*)(((uintptr_t)(dd) + 15) & ~15)
++#define PADLOCK_SHA_HWCTX (128+16)
++
++static void
++padlock_sha1(void *hwctx, const void *buf, unsigned long total, unsigned long now)
++{
++ unsigned long pos = total - now;
++
++ asm volatile ("xsha1"
++ : "+S"(buf), "+D"(hwctx), "+a"(pos), "+c"(total)
++ : : "memory");
++}
++
++static void
++padlock_sha1_partial(void *hwctx, const void *buf, unsigned long blocks)
++{
++ asm volatile ("xsha1"
++ : "+S"(buf), "+D"(hwctx), "+c"(blocks)
++ : "a"(-1L) : "memory");
++}
++
++static int padlock_sha1_init(EVP_MD_CTX *ctx)
++{
++ return SHA1_Init(ctx->md_data);
++}
++
++#if PADLOCK_NEED_FALLBACK_SHA
++
++static int padlock_sha1_update_eden(EVP_MD_CTX *ctx, const void *data,
++ size_t len)
++{
++ unsigned char hwctx[PADLOCK_SHA_HWCTX];
++ uint32_t *aligned = PADLOCK_SHA_ALIGN(hwctx);
++ SHA_CTX *c = ctx->md_data;
++ uint_fast64_t total;
++ const unsigned char *p = data;
++ unsigned long l = 0;
++
++ /* Calculate total length (Nl,Nh) is length in bits */
++ total = (((uint_fast64_t) c->Nh) << 29) + (c->Nl >> 3);
++ total += len;
++
++ if ((ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) &&
++ (total <= PADLOCK_MAX_FINALIZING_LENGTH)) {
++ if (c->num != 0) {
++ l = (len < SHA_CBLOCK) ? len : SHA_CBLOCK;
++ if (!SHA1_Update(c, data, l))
++ return 0;
++ p += l;
++ if (c->num != 0) {
++ p = (unsigned char *) c->data;
++ len = c->num;
++ l = 0;
++ }
++ }
++ memcpy(aligned, &c->h0, 5 * sizeof(SHA_LONG));
++ padlock_sha1(aligned, p, total, len - l);
++ memcpy(&c->h0, aligned, 5 * sizeof(SHA_LONG));
++ c->num = -1;
++ return 1;
++ }
++
++ return SHA1_Update(c, data, len);
++}
++#endif
++
++static int padlock_sha1_update(EVP_MD_CTX *ctx, const void *data,
++ size_t len)
++{
++ unsigned char hwctx[PADLOCK_SHA_HWCTX];
++ uint32_t *aligned = PADLOCK_SHA_ALIGN(hwctx);
++ SHA_CTX *c = ctx->md_data;
++ uint_fast64_t total;
++ unsigned char *p;
++ unsigned long n;
++
++ /* Calculate total length (Nl,Nh) is length in bits */
++ total = (((uint_fast64_t) c->Nh) << 29) + (c->Nl >> 3);
++ total += len;
++ c->Nh = total >> 29;
++ c->Nl = (total << 3) & 0xffffffffUL;
++
++ memcpy(aligned, &c->h0, 5 * sizeof(SHA_LONG));
++
++ /* Check partial data */
++ n = c->num;
++ if (n) {
++ p = (unsigned char *) c->data;
++ if (len >= SHA_CBLOCK || len+n >= SHA_CBLOCK) {
++ memcpy(p+n, data, SHA_CBLOCK-n);
++ padlock_sha1_partial(aligned, p, 1);
++ n = SHA_CBLOCK - n;
++ data += n;
++ len -= n;
++ c->num = 0;
++ memset(p, 0, SHA_CBLOCK);
++ } else {
++ memcpy(p+n, data, len);
++ c->num += (unsigned int)len;
++ return 1;
++ }
++ }
++
++ /* Can we finalize straight away? */
++ if ((ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) &&
++ (total <= PADLOCK_MAX_FINALIZING_LENGTH)) {
++ padlock_sha1(aligned, data, total, len);
++ memcpy(&c->h0, aligned, 5 * sizeof(SHA_LONG));
++ c->num = -1;
++ return 1;
++ }
++
++ /* Use nonfinalizing update */
++ n = len / SHA_CBLOCK;
++ if (n != 0) {
++ padlock_sha1_partial(aligned, data, n);
++ data += n * SHA_CBLOCK;
++ len -= n * SHA_CBLOCK;
++ }
++ memcpy(&c->h0, aligned, 5 * sizeof(SHA_LONG));
++
++ /* Buffer remaining bytes */
++ if (len) {
++ memcpy(c->data, data, len);
++ c->num = len;
++ }
++
++ return 1;
++}
++
++static int padlock_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++ unsigned char hwctx[PADLOCK_SHA_HWCTX];
++ uint32_t *aligned = PADLOCK_SHA_ALIGN(hwctx);
++ uint64_t total;
++ SHA_CTX *c = ctx->md_data;
++
++ if (c->num == -1) {
++ padlock_copy_bswap(md, &c->h0, 5);
++ c->num = 0;
++ return 1;
++ }
++
++ total = (((uint_fast64_t) c->Nh) << 29) + (c->Nl >> 3);
++#if PADLOCK_NEED_FALLBACK_SHA
++ if ((!PADLOCK_HAVE_NANO) && (total > PADLOCK_MAX_FINALIZING_LENGTH))
++ return SHA1_Final(md, c);
++#endif
++
++ memcpy(aligned, &c->h0, 5 * sizeof(SHA_LONG));
++ if (total > PADLOCK_MAX_FINALIZING_LENGTH) {
++ unsigned char padding[2 * SHA_CBLOCK];
++ unsigned long n;
++
++ n = padlock_sha_prepare_padding(ctx, padding,
++ (unsigned char *) c->data, c->num, total << 3);
++ padlock_sha1_partial(aligned, padding, n);
++ } else {
++ padlock_sha1(aligned, c->data, total, c->num);
++ }
++ padlock_copy_bswap(md, aligned, 5);
++ c->num = 0;
++
++ return 1;
++}
++
++static EVP_MD padlock_sha1_md = {
++ NID_sha1,
++ NID_sha1WithRSAEncryption,
++ SHA_DIGEST_LENGTH,
++ 0,
++ padlock_sha1_init,
++ padlock_sha1_update,
++ padlock_sha1_final,
++ NULL,
++ NULL,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(SHA_CTX),
++};
++
++static EVP_MD padlock_dss1_md = {
++ NID_dsa,
++ NID_dsaWithSHA1,
++ SHA_DIGEST_LENGTH,
++ 0,
++ padlock_sha1_init,
++ padlock_sha1_update,
++ padlock_sha1_final,
++ NULL,
++ NULL,
++ EVP_PKEY_DSA_method,
++ SHA_CBLOCK,
++ sizeof(SHA_CTX),
++};
++
++
++#if !defined(OPENSSL_NO_SHA256)
++
++static void
++padlock_sha256(void *hwctx, const void *buf, unsigned long total, unsigned long now)
++{
++ unsigned long pos = total - now;
++
++ asm volatile ("xsha256"
++ : "+S"(buf), "+D"(hwctx), "+a"(pos), "+c"(total)
++ : : "memory");
++}
++
++static void
++padlock_sha256_partial(void *hwctx, const void *buf, unsigned long blocks)
++{
++ asm volatile ("xsha256"
++ : "+S"(buf), "+D"(hwctx), "+c"(blocks)
++ : "a"(-1L) : "memory");
++}
++
++#if PADLOCK_NEED_FALLBACK_SHA
++
++static int padlock_sha256_update_eden(EVP_MD_CTX *ctx, const void *data,
++ size_t len)
++{
++ unsigned char hwctx[PADLOCK_SHA_HWCTX];
++ uint32_t *aligned = PADLOCK_SHA_ALIGN(hwctx);
++ SHA256_CTX *c = ctx->md_data;
++ uint_fast64_t total;
++ const unsigned char *p = data;
++ unsigned int l = 0;
++
++ /* Calculate total length (Nl,Nh) is length in bits */
++ total = (((uint_fast64_t) c->Nh) << 29) + (c->Nl >> 3);
++ total += len;
++
++ if ((ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) &&
++ (total <= PADLOCK_MAX_FINALIZING_LENGTH)) {
++ if (c->num != 0) {
++ l = (len < SHA256_CBLOCK) ? len : SHA256_CBLOCK;
++ if (!SHA256_Update(c, data, l))
++ return 0;
++ p += l;
++ if (c->num != 0) {
++ p = (unsigned char *) c->data;
++ len = c->num;
++ l = 0;
++ }
++ }
++ memcpy(aligned, c->h, sizeof(c->h));
++ padlock_sha256(aligned, p, total, len - l);
++ memcpy(c->h, aligned, sizeof(c->h));
++ c->num = -1;
++ return 1;
++ }
++
++ return SHA256_Update(c, data, len);
++}
++
++#endif
++
++static int padlock_sha256_update(EVP_MD_CTX *ctx, const void *data,
++ size_t len)
++{
++ unsigned char hwctx[PADLOCK_SHA_HWCTX];
++ uint32_t *aligned = PADLOCK_SHA_ALIGN(hwctx);
++ SHA256_CTX *c = ctx->md_data;
++ uint_fast64_t total;
++ unsigned char *p;
++ unsigned long n;
++
++ /* Calculate total length (Nl,Nh) is length in bits */
++ total = (((uint_fast64_t) c->Nh) << 29) + (c->Nl >> 3);
++ total += len;
++ c->Nh = total >> 29;
++ c->Nl = (total << 3) & 0xffffffffUL;
++
++ memcpy(aligned, c->h, sizeof(c->h));
++
++ /* Check partial data */
++ n = c->num;
++ if (n) {
++ p = (unsigned char *) c->data;
++ if (len >= SHA256_CBLOCK || len+n >= SHA256_CBLOCK) {
++ memcpy(p+n, data, SHA256_CBLOCK-n);
++ padlock_sha256_partial(aligned, p, 1);
++ n = SHA256_CBLOCK - n;
++ data += n;
++ len -= n;
++ c->num = 0;
++ memset(p, 0, SHA256_CBLOCK);
++ } else {
++ memcpy(p+n, data, len);
++ c->num += (unsigned int)len;
++ return 1;
++ }
++ }
++
++ /* Can we finalize straight away? */
++ if ((ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) &&
++ (total <= PADLOCK_MAX_FINALIZING_LENGTH)) {
++ padlock_sha256(aligned, data, total, len);
++ memcpy(c->h, aligned, sizeof(c->h));
++ c->num = -1;
++ return 1;
++ }
++
++ /* Use nonfinalizing update */
++ n = len / SHA256_CBLOCK;
++ if (n != 0) {
++ padlock_sha256_partial(aligned, data, n);
++ data += n * SHA256_CBLOCK;
++ len -= n * SHA256_CBLOCK;
++ }
++ memcpy(c->h, aligned, sizeof(c->h));
++
++ /* Buffer remaining bytes */
++ if (len) {
++ memcpy(c->data, data, len);
++ c->num = len;
++ }
++
++ return 1;
++}
++
++static int padlock_sha256_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++ unsigned char hwctx[PADLOCK_SHA_HWCTX];
++ uint32_t *aligned = PADLOCK_SHA_ALIGN(hwctx);
++ uint64_t total;
++ SHA256_CTX *c = ctx->md_data;
++
++ if (c->num == -1) {
++ padlock_copy_bswap(md, c->h, sizeof(c->h)/sizeof(c->h[0]));
++ c->num = 0;
++ return 1;
++ }
++
++ total = (((uint_fast64_t) c->Nh) << 29) + (c->Nl >> 3);
++#if PADLOCK_NEED_FALLBACK_SHA
++ if ((!PADLOCK_HAVE_NANO) && (total > PADLOCK_MAX_FINALIZING_LENGTH))
++ return SHA256_Final(md, c);
++#endif
++
++ memcpy(aligned, c->h, sizeof(c->h));
++ if (total > PADLOCK_MAX_FINALIZING_LENGTH) {
++ unsigned char padding[2 * SHA_CBLOCK];
++ unsigned long n;
++
++ n = padlock_sha_prepare_padding(ctx, padding,
++ (unsigned char *) c->data, c->num, total << 3);
++ padlock_sha256_partial(aligned, padding, n);
++ } else {
++ padlock_sha256(aligned, c->data, total, c->num);
++ }
++ padlock_copy_bswap(md, aligned, sizeof(c->h)/sizeof(c->h[0]));
++ c->num = 0;
++ return 1;
++}
++
++#if !defined(OPENSSL_NO_SHA224)
++
++static int padlock_sha224_init(EVP_MD_CTX *ctx)
++{
++ return SHA224_Init(ctx->md_data);
++}
++
++static EVP_MD padlock_sha224_md = {
++ NID_sha224,
++ NID_sha224WithRSAEncryption,
++ SHA224_DIGEST_LENGTH,
++ 0,
++ padlock_sha224_init,
++ padlock_sha256_update,
++ padlock_sha256_final,
++ NULL,
++ NULL,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(SHA256_CTX),
++};
++#endif /* !OPENSSL_NO_SHA224 */
++
++static int padlock_sha256_init(EVP_MD_CTX *ctx)
++{
++ return SHA256_Init(ctx->md_data);
++}
++
++static EVP_MD padlock_sha256_md = {
++ NID_sha256,
++ NID_sha256WithRSAEncryption,
++ SHA256_DIGEST_LENGTH,
++ 0,
++ padlock_sha256_init,
++ padlock_sha256_update,
++ padlock_sha256_final,
++ NULL,
++ NULL,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(SHA256_CTX),
++};
++#endif /* !OPENSSL_NO_SHA256 */
++
++static int padlock_digest_nids[] = {
++#if !defined(OPENSSL_NO_SHA)
++ NID_sha1,
++ NID_dsa,
++#endif
++#if !defined(OPENSSL_NO_SHA256)
++#if !defined(OPENSSL_NO_SHA224)
++ NID_sha224,
++#endif
++ NID_sha256,
++#endif
++};
++
++static int padlock_digest_nids_num = sizeof(padlock_digest_nids)/sizeof(padlock_digest_nids[0]);
++
++static int
++padlock_digests (ENGINE *e, const EVP_MD **digest, const int **nids, int nid)
++{
++ /* No specific digest => return a list of supported nids ... */
++ if (!digest) {
++ *nids = padlock_digest_nids;
++ return padlock_digest_nids_num;
++ }
++
++ /* ... or the requested "digest" otherwise */
++ switch (nid) {
++#if !defined(OPENSSL_NO_SHA)
++ case NID_sha1:
++ *digest = &padlock_sha1_md;
++ break;
++ case NID_dsa:
++ *digest = &padlock_dss1_md;
++ break;
++#endif
++#if !defined(OPENSSL_NO_SHA256)
++#if !defined(OPENSSL_NO_SHA224)
++ case NID_sha224:
++ *digest = &padlock_sha224_md;
++ break;
++#endif /* OPENSSL_NO_SHA224 */
++ case NID_sha256:
++ *digest = &padlock_sha256_md;
++ break;
++#endif /* OPENSSL_NO_SHA256 */
++ default:
++ /* Sorry, we don't support this NID */
++ *digest = NULL;
++ return 0;
++ }
++
++ return 1;
++}
++
++#endif /* OPENSSL_NO_SHA */
++
++#ifndef PADLOCK_NO_RNG
++
+ /* ===== Random Number Generator ===== */
+ /*
+ * This code is not engaged. The reason is that it does not comply
+@@ -1319,6 +1831,60 @@ static RAND_METHOD padlock_rand = {
+ padlock_rand_status, /* rand status */
+ };
+
++#endif /* PADLOCK_NO_RNG */
++
++/* Prepare the ENGINE structure for registration */
++static int
++padlock_bind_helper(ENGINE *e)
++{
++ /* Check available features */
++ padlock_available();
++
++ /* Generate a nice engine name with available features */
++ BIO_snprintf(padlock_name, sizeof(padlock_name),
++ "VIA PadLock: %s%s%s%s%s%s",
++ padlock_flags ? "" : "not supported",
++ PADLOCK_HAVE_RNG ? "RNG " : "",
++ PADLOCK_HAVE_ACE ? (PADLOCK_HAVE_ACE2 ? "ACE2 " : "ACE ") : "",
++ PADLOCK_HAVE_PHE ? "PHE " : "",
++ PADLOCK_HAVE_PMM ? "PMM " : "",
++ PADLOCK_HAVE_NANO ? "NANO " : ""
++ );
++
++#if PADLOCK_NEED_FALLBACK_SHA && !defined(OPENSSL_NO_SHA)
++ if (!PADLOCK_HAVE_NANO) {
++ padlock_sha1_md.update = padlock_sha1_update_eden;
++ padlock_dss1_md.update = padlock_sha1_update_eden;
++#if !defined(OPENSSL_NO_SHA256)
++#if !defined(OPENSSL_NO_SHA224)
++ padlock_sha224_md.update = padlock_sha256_update_eden;
++#endif
++ padlock_sha256_md.update = padlock_sha256_update_eden;
++#endif
++ }
++#endif
++
++ /* Register everything or return with an error */
++ if (!ENGINE_set_id(e, padlock_id) ||
++ !ENGINE_set_name(e, padlock_name) ||
++ !ENGINE_set_init_function(e, padlock_init)
++#ifndef OPENSSL_NO_AES
++ || (PADLOCK_HAVE_ACE && !ENGINE_set_ciphers (e, padlock_ciphers))
++#endif
++#ifndef OPENSSL_NO_SHA
++ || (PADLOCK_HAVE_PHE && !ENGINE_set_digests (e, padlock_digests))
++#endif
++#ifndef PADLOCK_NO_RNG
++ || (PADLOCK_HAVE_RNG && !ENGINE_set_RAND (e, &padlock_rand))
++#endif
++ ) {
++ return 0;
++ }
++
++ /* Everything looks good */
++ return 1;
++}
++
+ #else /* !COMPILE_HW_PADLOCK */
+ #ifndef OPENSSL_NO_DYNAMIC_ENGINE
+ OPENSSL_EXPORT
+--
+1.7.0.4
+
diff --git a/main/openssl/0005-crypto-engine-autoload-padlock-dynamic-engine.patch b/main/openssl/0005-crypto-engine-autoload-padlock-dynamic-engine.patch
new file mode 100644
index 0000000000..3c72ce26aa
--- /dev/null
+++ b/main/openssl/0005-crypto-engine-autoload-padlock-dynamic-engine.patch
@@ -0,0 +1,33 @@
+From b96276c8f11e656e4296955bf1a8d0ac2b6094fe Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Fri, 4 Jun 2010 18:02:39 +0300
+Subject: [PATCH 5/5] crypto/engine: autoload padlock dynamic engine
+
+---
+ crypto/engine/eng_all.c | 10 ++++++++++
+ 1 files changed, 10 insertions(+), 0 deletions(-)
+
+diff --git a/crypto/engine/eng_all.c b/crypto/engine/eng_all.c
+index 22c1204..827e447 100644
+--- a/crypto/engine/eng_all.c
++++ b/crypto/engine/eng_all.c
+@@ -112,6 +112,16 @@ void ENGINE_load_builtin_engines(void)
+ ENGINE_load_capi();
+ #endif
+ #endif
++#ifdef OPENSSL_NO_STATIC_ENGINE
++ {
++ ENGINE *e;
++ e = ENGINE_by_id("padlock");
++ if (e != NULL) {
++ ENGINE_add(e);
++ ENGINE_free(e);
++ }
++ }
++#endif
+ }
+
+ #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+--
+1.7.0.4
+
diff --git a/main/openssl/APKBUILD b/main/openssl/APKBUILD
new file mode 100644
index 0000000000..f8a0bedf9d
--- /dev/null
+++ b/main/openssl/APKBUILD
@@ -0,0 +1,79 @@
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=openssl
+pkgver=1.0.0d
+pkgrel=0
+pkgdesc="Toolkit for SSL v2/v3 and TLS v1"
+url="http://openssl.org"
+depends=
+makedepends="perl zlib-dev"
+depends_dev="zlib-dev"
+arch="all"
+license="openssl"
+
+subpackages="$pkgname-dev $pkgname-doc libcrypto1.0:libcrypto libssl1.0:libssl"
+
+source="http://www.openssl.org/source/${pkgname}-${pkgver}.tar.gz
+ fix-manpages.patch
+ openssl-bb-basename.patch
+ 0001-crypto-hmac-support-EVP_MD_CTX_FLAG_ONESHOT-and-set-.patch
+ 0002-apps-speed-fix-digest-speed-measurement-and-add-hmac.patch
+ 0003-engines-e_padlock-backport-cvs-head-changes.patch
+ 0004-engines-e_padlock-implement-sha1-sha224-sha256-accel.patch
+ 0005-crypto-engine-autoload-padlock-dynamic-engine.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 -N < $i || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./config --prefix=/usr \
+ --libdir=lib \
+ --openssldir=/etc/ssl \
+ shared zlib enable-montasm enable-md2 \
+ -Wa,--noexecstack \
+ || return 1
+
+ make -j1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 INSTALL_PREFIX="$pkgdir" MANDIR=/usr/share/man install
+}
+
+libcrypto() {
+ pkgdesc="Crypto library from openssl"
+ replaces="openssl libcrypto"
+ mkdir -p "$subpkgdir"/lib "$subpkgdir"/usr/lib
+ for i in "$pkgdir"/usr/lib/libcrypto*; do
+ mv $i "$subpkgdir"/lib/
+ ln -s ../../lib/${i##*/} "$subpkgdir"/usr/lib/${i##*/}
+ done
+ mv "$pkgdir"/usr/lib/engines "$subpkgdir"/usr/lib/
+}
+
+libssl() {
+ pkgdesc="SSL shared libraries"
+ replaces="openssl"
+ mkdir -p "$subpkgdir"/lib "$subpkgdir"/usr/lib
+ for i in "$pkgdir"/usr/lib/libssl*; do
+ mv $i "$subpkgdir"/lib/
+ ln -s ../../lib/${i##*/} "$subpkgdir"/usr/lib/${i##*/}
+ done
+}
+
+md5sums="40b6ea380cc8a5bf9734c2f8bf7e701e openssl-1.0.0d.tar.gz
+115c481cd59b3dba631364e8fb1778f5 fix-manpages.patch
+c6a9857a5dbd30cead0404aa7dd73977 openssl-bb-basename.patch
+1f607b8e11347e56a0906756f3d6928a 0001-crypto-hmac-support-EVP_MD_CTX_FLAG_ONESHOT-and-set-.patch
+16424fe5fb494804559f01c7ec7e64f4 0002-apps-speed-fix-digest-speed-measurement-and-add-hmac.patch
+53fbd01733b488717575e04a5aaf6664 0003-engines-e_padlock-backport-cvs-head-changes.patch
+beea8819faeefb9ab19ef90f00c53782 0004-engines-e_padlock-implement-sha1-sha224-sha256-accel.patch
+8bc7a427f6005158585386b9837f700c 0005-crypto-engine-autoload-padlock-dynamic-engine.patch"
diff --git a/main/openssl/fix-manpages.patch b/main/openssl/fix-manpages.patch
new file mode 100644
index 0000000000..7c6ac9902f
--- /dev/null
+++ b/main/openssl/fix-manpages.patch
@@ -0,0 +1,1329 @@
+diff --git a/FAQ b/FAQ
+index 2134e3a..18a8831 100644
+--- a/FAQ
++++ b/FAQ
+@@ -724,7 +724,7 @@ OpenSSL by calling CRYPTO_set_locking_callback() and
+ CRYPTO_set_id_callback(), for all versions of OpenSSL up to and
+ including 0.9.8[abc...]. As of version 0.9.9, CRYPTO_set_id_callback()
+ and associated APIs are deprecated by CRYPTO_THREADID_set_callback()
+-and friends. This is described in the threads(3) manpage.
++and friends. This is described in the openssl_threads(3) manpage.
+
+ * I've compiled a program under Windows and it crashes: why?
+
+diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c
+index 88088ce..e5da17f 100644
+--- a/crypto/rand/md_rand.c
++++ b/crypto/rand/md_rand.c
+@@ -196,7 +196,7 @@ static void ssleay_rand_add(const void *buf, int num, double add)
+ int do_not_lock;
+
+ /*
+- * (Based on the rand(3) manpage)
++ * (Based on the openssl_rand(3) manpage)
+ *
+ * The input is chopped up into units of 20 bytes (or less for
+ * the last block). Each of these blocks is run through the hash
+@@ -361,7 +361,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
+ num_ceil = (1 + (num-1)/(MD_DIGEST_LENGTH/2)) * (MD_DIGEST_LENGTH/2);
+
+ /*
+- * (Based on the rand(3) manpage:)
++ * (Based on the openssl_rand(3) manpage)
+ *
+ * For each group of 10 bytes (or less), we do the following:
+ *
+diff --git a/doc/apps/openssl.pod b/doc/apps/openssl.pod
+index 738142e..e904f05 100644
+--- a/doc/apps/openssl.pod
++++ b/doc/apps/openssl.pod
+@@ -163,7 +163,7 @@ Create or examine a netscape certificate sequence
+
+ Online Certificate Status Protocol utility.
+
+-=item L<B<passwd>|passwd(1)>
++=item L<B<passwd>|openssl-passwd(1)>
+
+ Generation of hashed passwords.
+
+@@ -401,7 +401,7 @@ L<crl(1)|crl(1)>, L<crl2pkcs7(1)|crl2pkcs7(1)>, L<dgst(1)|dgst(1)>,
+ L<dhparam(1)|dhparam(1)>, L<dsa(1)|dsa(1)>, L<dsaparam(1)|dsaparam(1)>,
+ L<enc(1)|enc(1)>, L<gendsa(1)|gendsa(1)>, L<genpkey(1)|genpkey(1)>,
+ L<genrsa(1)|genrsa(1)>, L<nseq(1)|nseq(1)>, L<openssl(1)|openssl(1)>,
+-L<passwd(1)|passwd(1)>,
++L<openssl-passwd(1)|openssl-passwd(1)>,
+ L<pkcs12(1)|pkcs12(1)>, L<pkcs7(1)|pkcs7(1)>, L<pkcs8(1)|pkcs8(1)>,
+ L<rand(1)|rand(1)>, L<req(1)|req(1)>, L<rsa(1)|rsa(1)>,
+ L<rsautl(1)|rsautl(1)>, L<s_client(1)|s_client(1)>,
+diff --git a/doc/apps/passwd.pod b/doc/apps/passwd.pod
+deleted file mode 100644
+index f449825..0000000
+--- a/doc/apps/passwd.pod
++++ /dev/null
+@@ -1,82 +0,0 @@
+-=pod
+-
+-=head1 NAME
+-
+-passwd - compute password hashes
+-
+-=head1 SYNOPSIS
+-
+-B<openssl passwd>
+-[B<-crypt>]
+-[B<-1>]
+-[B<-apr1>]
+-[B<-salt> I<string>]
+-[B<-in> I<file>]
+-[B<-stdin>]
+-[B<-noverify>]
+-[B<-quiet>]
+-[B<-table>]
+-{I<password>}
+-
+-=head1 DESCRIPTION
+-
+-The B<passwd> command computes the hash of a password typed at
+-run-time or the hash of each password in a list. The password list is
+-taken from the named file for option B<-in file>, from stdin for
+-option B<-stdin>, or from the command line, or from the terminal otherwise.
+-The Unix standard algorithm B<crypt> and the MD5-based BSD password
+-algorithm B<1> and its Apache variant B<apr1> are available.
+-
+-=head1 OPTIONS
+-
+-=over 4
+-
+-=item B<-crypt>
+-
+-Use the B<crypt> algorithm (default).
+-
+-=item B<-1>
+-
+-Use the MD5 based BSD password algorithm B<1>.
+-
+-=item B<-apr1>
+-
+-Use the B<apr1> algorithm (Apache variant of the BSD algorithm).
+-
+-=item B<-salt> I<string>
+-
+-Use the specified salt.
+-When reading a password from the terminal, this implies B<-noverify>.
+-
+-=item B<-in> I<file>
+-
+-Read passwords from I<file>.
+-
+-=item B<-stdin>
+-
+-Read passwords from B<stdin>.
+-
+-=item B<-noverify>
+-
+-Don't verify when reading a password from the terminal.
+-
+-=item B<-quiet>
+-
+-Don't output warnings when passwords given at the command line are truncated.
+-
+-=item B<-table>
+-
+-In the output list, prepend the cleartext password and a TAB character
+-to each password hash.
+-
+-=back
+-
+-=head1 EXAMPLES
+-
+-B<openssl passwd -crypt -salt xx password> prints B<xxj31ZMTZzkVA>.
+-
+-B<openssl passwd -1 -salt xxxxxxxx password> prints B<$1$xxxxxxxx$UYCIxa628.9qXjpQCjM4a.>.
+-
+-B<openssl passwd -apr1 -salt xxxxxxxx password> prints B<$apr1$xxxxxxxx$dxHfLAsjHkDRmG83UXe8K0>.
+-
+-=cut
+diff --git a/doc/crypto/BN_generate_prime.pod b/doc/crypto/BN_generate_prime.pod
+index 7dccacb..71e7078 100644
+--- a/doc/crypto/BN_generate_prime.pod
++++ b/doc/crypto/BN_generate_prime.pod
+@@ -90,7 +90,7 @@ The error codes can be obtained by L<ERR_get_error(3)|ERR_get_error(3)>.
+
+ =head1 SEE ALSO
+
+-L<bn(3)|bn(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>
++L<bn(3)|bn(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/BN_rand.pod b/doc/crypto/BN_rand.pod
+index 81f93c2..690aa85 100644
+--- a/doc/crypto/BN_rand.pod
++++ b/doc/crypto/BN_rand.pod
+@@ -45,7 +45,7 @@ The error codes can be obtained by L<ERR_get_error(3)|ERR_get_error(3)>.
+
+ =head1 SEE ALSO
+
+-L<bn(3)|bn(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>,
++L<bn(3)|bn(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<RAND_add(3)|RAND_add(3)>, L<RAND_bytes(3)|RAND_bytes(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/CONF_modules_free.pod b/doc/crypto/CONF_modules_free.pod
+index 87bc7b7..347020c 100644
+--- a/doc/crypto/CONF_modules_free.pod
++++ b/doc/crypto/CONF_modules_free.pod
+@@ -37,7 +37,7 @@ None of the functions return a value.
+ =head1 SEE ALSO
+
+ L<conf(5)|conf(5)>, L<OPENSSL_config(3)|OPENSSL_config(3)>,
+-L<CONF_modules_load_file(3), CONF_modules_load_file(3)>
++L<CONF_modules_load_file(3)|CONF_modules_load_file(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/CONF_modules_load_file.pod b/doc/crypto/CONF_modules_load_file.pod
+index 9965d69..6dd9b1d 100644
+--- a/doc/crypto/CONF_modules_load_file.pod
++++ b/doc/crypto/CONF_modules_load_file.pod
+@@ -51,7 +51,7 @@ return value of the failing module (this will always be zero or negative).
+ =head1 SEE ALSO
+
+ L<conf(5)|conf(5)>, L<OPENSSL_config(3)|OPENSSL_config(3)>,
+-L<CONF_free(3), CONF_free(3)>, L<err(3),err(3)>
++L<CONF_free(3)|CONF_free(3)>, L<openssl_err(3)|openssl_err(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/DH_generate_key.pod b/doc/crypto/DH_generate_key.pod
+index 81f09fd..0d9f1e5 100644
+--- a/doc/crypto/DH_generate_key.pod
++++ b/doc/crypto/DH_generate_key.pod
+@@ -40,7 +40,7 @@ The error codes can be obtained by L<ERR_get_error(3)|ERR_get_error(3)>.
+
+ =head1 SEE ALSO
+
+-L<dh(3)|dh(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>, L<DH_size(3)|DH_size(3)>
++L<dh(3)|dh(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>, L<DH_size(3)|DH_size(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/DH_generate_parameters.pod b/doc/crypto/DH_generate_parameters.pod
+index 9081e9e..0c0f78c 100644
+--- a/doc/crypto/DH_generate_parameters.pod
++++ b/doc/crypto/DH_generate_parameters.pod
+@@ -59,7 +59,7 @@ a usable generator.
+
+ =head1 SEE ALSO
+
+-L<dh(3)|dh(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>,
++L<dh(3)|dh(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<DH_free(3)|DH_free(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/DSA_do_sign.pod b/doc/crypto/DSA_do_sign.pod
+index 5dfc733..0a6d5f1 100644
+--- a/doc/crypto/DSA_do_sign.pod
++++ b/doc/crypto/DSA_do_sign.pod
+@@ -36,7 +36,7 @@ L<ERR_get_error(3)|ERR_get_error(3)>.
+
+ =head1 SEE ALSO
+
+-L<dsa(3)|dsa(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>,
++L<dsa(3)|dsa(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<DSA_SIG_new(3)|DSA_SIG_new(3)>,
+ L<DSA_sign(3)|DSA_sign(3)>
+
+diff --git a/doc/crypto/DSA_generate_key.pod b/doc/crypto/DSA_generate_key.pod
+index af83ccf..95080eb 100644
+--- a/doc/crypto/DSA_generate_key.pod
++++ b/doc/crypto/DSA_generate_key.pod
+@@ -24,7 +24,7 @@ The error codes can be obtained by L<ERR_get_error(3)|ERR_get_error(3)>.
+
+ =head1 SEE ALSO
+
+-L<dsa(3)|dsa(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>,
++L<dsa(3)|dsa(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<DSA_generate_parameters(3)|DSA_generate_parameters(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/DSA_generate_parameters.pod b/doc/crypto/DSA_generate_parameters.pod
+index be7c924..2b1f78f 100644
+--- a/doc/crypto/DSA_generate_parameters.pod
++++ b/doc/crypto/DSA_generate_parameters.pod
+@@ -90,7 +90,7 @@ Seed lengths E<gt> 20 are not supported.
+
+ =head1 SEE ALSO
+
+-L<dsa(3)|dsa(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>,
++L<dsa(3)|dsa(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<DSA_free(3)|DSA_free(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/DSA_sign.pod b/doc/crypto/DSA_sign.pod
+index 97389e8..2e6f6f3 100644
+--- a/doc/crypto/DSA_sign.pod
++++ b/doc/crypto/DSA_sign.pod
+@@ -55,7 +55,7 @@ Standard, DSS), ANSI X9.30
+
+ =head1 SEE ALSO
+
+-L<dsa(3)|dsa(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>,
++L<dsa(3)|dsa(3)>, L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<DSA_do_sign(3)|DSA_do_sign(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/ERR_GET_LIB.pod b/doc/crypto/ERR_GET_LIB.pod
+index 2a129da..a881bdb 100644
+--- a/doc/crypto/ERR_GET_LIB.pod
++++ b/doc/crypto/ERR_GET_LIB.pod
+@@ -41,7 +41,7 @@ The library number, function code and reason code respectively.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>, L<ERR_get_error(3)|ERR_get_error(3)>
++L<openssl_err(3)|openssl_err(3)>, L<ERR_get_error(3)|ERR_get_error(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/ERR_clear_error.pod b/doc/crypto/ERR_clear_error.pod
+index 566e1f4..0f503e7 100644
+--- a/doc/crypto/ERR_clear_error.pod
++++ b/doc/crypto/ERR_clear_error.pod
+@@ -20,7 +20,7 @@ ERR_clear_error() has no return value.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>, L<ERR_get_error(3)|ERR_get_error(3)>
++L<openssl_err(3)|openssl_err(3)>, L<ERR_get_error(3)|ERR_get_error(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/ERR_error_string.pod b/doc/crypto/ERR_error_string.pod
+index cdfa7fe..d774ec1 100644
+--- a/doc/crypto/ERR_error_string.pod
++++ b/doc/crypto/ERR_error_string.pod
+@@ -60,7 +60,7 @@ none is registered for the error code.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>, L<ERR_get_error(3)|ERR_get_error(3)>,
++L<openssl_err(3)|openssl_err(3)>, L<ERR_get_error(3)|ERR_get_error(3)>,
+ L<ERR_load_crypto_strings(3)|ERR_load_crypto_strings(3)>,
+ L<SSL_load_error_strings(3)|SSL_load_error_strings(3)>
+ L<ERR_print_errors(3)|ERR_print_errors(3)>
+diff --git a/doc/crypto/ERR_get_error.pod b/doc/crypto/ERR_get_error.pod
+index 3444304..cd3d7ce 100644
+--- a/doc/crypto/ERR_get_error.pod
++++ b/doc/crypto/ERR_get_error.pod
+@@ -61,7 +61,7 @@ The error code, or 0 if there is no error in the queue.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>, L<ERR_error_string(3)|ERR_error_string(3)>,
++L<openssl_err(3)|openssl_err(3)>, L<ERR_error_string(3)|ERR_error_string(3)>,
+ L<ERR_GET_LIB(3)|ERR_GET_LIB(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/ERR_load_crypto_strings.pod b/doc/crypto/ERR_load_crypto_strings.pod
+index 9bdec75..9c1b991 100644
+--- a/doc/crypto/ERR_load_crypto_strings.pod
++++ b/doc/crypto/ERR_load_crypto_strings.pod
+@@ -35,7 +35,7 @@ ERR_free_strings() return no values.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>, L<ERR_error_string(3)|ERR_error_string(3)>
++L<openssl_err(3)|openssl_err(3)>, L<ERR_error_string(3)|ERR_error_string(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/ERR_load_strings.pod b/doc/crypto/ERR_load_strings.pod
+index 5acdd0e..261c87d 100644
+--- a/doc/crypto/ERR_load_strings.pod
++++ b/doc/crypto/ERR_load_strings.pod
+@@ -43,7 +43,7 @@ ERR_get_next_error_library() returns a new library number.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>, L<ERR_load_strings(3)|ERR_load_strings(3)>
++L<openssl_err(3)|openssl_err(3)>, L<ERR_load_strings(3)|ERR_load_strings(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/ERR_print_errors.pod b/doc/crypto/ERR_print_errors.pod
+index b100a5f..a8b34b7 100644
+--- a/doc/crypto/ERR_print_errors.pod
++++ b/doc/crypto/ERR_print_errors.pod
+@@ -38,7 +38,7 @@ ERR_print_errors() and ERR_print_errors_fp() return no values.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>, L<ERR_error_string(3)|ERR_error_string(3)>,
++L<openssl_err(3)|openssl_err(3)>, L<ERR_error_string(3)|ERR_error_string(3)>,
+ L<ERR_get_error(3)|ERR_get_error(3)>,
+ L<ERR_load_crypto_strings(3)|ERR_load_crypto_strings(3)>,
+ L<SSL_load_error_strings(3)|SSL_load_error_strings(3)>
+diff --git a/doc/crypto/ERR_put_error.pod b/doc/crypto/ERR_put_error.pod
+index acd241f..9c0263a 100644
+--- a/doc/crypto/ERR_put_error.pod
++++ b/doc/crypto/ERR_put_error.pod
+@@ -34,7 +34,7 @@ no values.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>, L<ERR_load_strings(3)|ERR_load_strings(3)>
++L<openssl_err(3)|openssl_err(3)>, L<ERR_load_strings(3)|ERR_load_strings(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/ERR_remove_state.pod b/doc/crypto/ERR_remove_state.pod
+index 72925fb..8dd63da 100644
+--- a/doc/crypto/ERR_remove_state.pod
++++ b/doc/crypto/ERR_remove_state.pod
+@@ -25,7 +25,7 @@ ERR_remove_state() returns no value.
+
+ =head1 SEE ALSO
+
+-L<err(3)|err(3)>
++L<openssl_err(3)|openssl_err(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/EVP_BytesToKey.pod b/doc/crypto/EVP_BytesToKey.pod
+index d375c46..6d6cf39 100644
+--- a/doc/crypto/EVP_BytesToKey.pod
++++ b/doc/crypto/EVP_BytesToKey.pod
+@@ -59,7 +59,7 @@ EVP_BytesToKey() returns the size of the derived key in bytes.
+
+ =head1 SEE ALSO
+
+-L<evp(3)|evp(3)>, L<rand(3)|rand(3)>,
++L<evp(3)|evp(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<EVP_EncryptInit(3)|EVP_EncryptInit(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/EVP_OpenInit.pod b/doc/crypto/EVP_OpenInit.pod
+index 2e710da..31172e4 100644
+--- a/doc/crypto/EVP_OpenInit.pod
++++ b/doc/crypto/EVP_OpenInit.pod
+@@ -54,7 +54,7 @@ EVP_OpenFinal() returns 0 if the decrypt failed or 1 for success.
+
+ =head1 SEE ALSO
+
+-L<evp(3)|evp(3)>, L<rand(3)|rand(3)>,
++L<evp(3)|evp(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<EVP_EncryptInit(3)|EVP_EncryptInit(3)>,
+ L<EVP_SealInit(3)|EVP_SealInit(3)>
+
+diff --git a/doc/crypto/EVP_SealInit.pod b/doc/crypto/EVP_SealInit.pod
+index 7d793e1..a37101f 100644
+--- a/doc/crypto/EVP_SealInit.pod
++++ b/doc/crypto/EVP_SealInit.pod
+@@ -74,7 +74,7 @@ with B<type> set to NULL.
+
+ =head1 SEE ALSO
+
+-L<evp(3)|evp(3)>, L<rand(3)|rand(3)>,
++L<evp(3)|evp(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<EVP_EncryptInit(3)|EVP_EncryptInit(3)>,
+ L<EVP_OpenInit(3)|EVP_OpenInit(3)>
+
+diff --git a/doc/crypto/EVP_SignInit.pod b/doc/crypto/EVP_SignInit.pod
+index 620a623..090f6e1 100644
+--- a/doc/crypto/EVP_SignInit.pod
++++ b/doc/crypto/EVP_SignInit.pod
+@@ -89,7 +89,7 @@ The previous two bugs are fixed in the newer EVP_SignDigest*() function.
+ =head1 SEE ALSO
+
+ L<EVP_VerifyInit(3)|EVP_VerifyInit(3)>,
+-L<EVP_DigestInit(3)|EVP_DigestInit(3)>, L<err(3)|err(3)>,
++L<EVP_DigestInit(3)|EVP_DigestInit(3)>, L<openssl_err(3)|openssl_err(3)>,
+ L<evp(3)|evp(3)>, L<hmac(3)|hmac(3)>, L<md2(3)|md2(3)>,
+ L<md5(3)|md5(3)>, L<mdc2(3)|mdc2(3)>, L<ripemd(3)|ripemd(3)>,
+ L<sha(3)|sha(3)>, L<dgst(1)|dgst(1)>
+diff --git a/doc/crypto/EVP_VerifyInit.pod b/doc/crypto/EVP_VerifyInit.pod
+index 9097f09..2a8d225 100644
+--- a/doc/crypto/EVP_VerifyInit.pod
++++ b/doc/crypto/EVP_VerifyInit.pod
+@@ -80,7 +80,7 @@ The previous two bugs are fixed in the newer EVP_VerifyDigest*() function.
+
+ L<evp(3)|evp(3)>,
+ L<EVP_SignInit(3)|EVP_SignInit(3)>,
+-L<EVP_DigestInit(3)|EVP_DigestInit(3)>, L<err(3)|err(3)>,
++L<EVP_DigestInit(3)|EVP_DigestInit(3)>, L<openssl_err(3)|openssl_err(3)>,
+ L<evp(3)|evp(3)>, L<hmac(3)|hmac(3)>, L<md2(3)|md2(3)>,
+ L<md5(3)|md5(3)>, L<mdc2(3)|mdc2(3)>, L<ripemd(3)|ripemd(3)>,
+ L<sha(3)|sha(3)>, L<dgst(1)|dgst(1)>
+diff --git a/doc/crypto/OPENSSL_config.pod b/doc/crypto/OPENSSL_config.pod
+index e7bba2a..888de88 100644
+--- a/doc/crypto/OPENSSL_config.pod
++++ b/doc/crypto/OPENSSL_config.pod
+@@ -73,7 +73,7 @@ Neither OPENSSL_config() nor OPENSSL_no_config() return a value.
+ =head1 SEE ALSO
+
+ L<conf(5)|conf(5)>, L<CONF_load_modules_file(3)|CONF_load_modules_file(3)>,
+-L<CONF_modules_free(3),CONF_modules_free(3)>
++L<CONF_modules_free(3)|CONF_modules_free(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/RAND_add.pod b/doc/crypto/RAND_add.pod
+index 67c66f3..a6fc28a 100644
+--- a/doc/crypto/RAND_add.pod
++++ b/doc/crypto/RAND_add.pod
+@@ -65,7 +65,7 @@ The other functions do not return values.
+
+ =head1 SEE ALSO
+
+-L<rand(3)|rand(3)>, L<RAND_egd(3)|RAND_egd(3)>,
++L<openssl_rand(3)|openssl_rand(3)>, L<RAND_egd(3)|RAND_egd(3)>,
+ L<RAND_load_file(3)|RAND_load_file(3)>, L<RAND_cleanup(3)|RAND_cleanup(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/RAND_bytes.pod b/doc/crypto/RAND_bytes.pod
+index 1a9b91e..20c4110 100644
+--- a/doc/crypto/RAND_bytes.pod
++++ b/doc/crypto/RAND_bytes.pod
+@@ -38,7 +38,7 @@ method.
+
+ =head1 SEE ALSO
+
+-L<rand(3)|rand(3)>, L<ERR_get_error(3)|ERR_get_error(3)>,
++L<openssl_rand(3)|openssl_rand(3)>, L<ERR_get_error(3)|ERR_get_error(3)>,
+ L<RAND_add(3)|RAND_add(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/RAND_cleanup.pod b/doc/crypto/RAND_cleanup.pod
+index 3a8f074..c99537d 100644
+--- a/doc/crypto/RAND_cleanup.pod
++++ b/doc/crypto/RAND_cleanup.pod
+@@ -20,7 +20,7 @@ RAND_cleanup() returns no value.
+
+ =head1 SEE ALSO
+
+-L<rand(3)|rand(3)>
++L<openssl_rand(3)|openssl_rand(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/RAND_egd.pod b/doc/crypto/RAND_egd.pod
+index 8b8c61d..c367290 100644
+--- a/doc/crypto/RAND_egd.pod
++++ b/doc/crypto/RAND_egd.pod
+@@ -72,7 +72,7 @@ success, and -1 if the connection failed. The PRNG state is not considered.
+
+ =head1 SEE ALSO
+
+-L<rand(3)|rand(3)>, L<RAND_add(3)|RAND_add(3)>,
++L<openssl_rand(3)|openssl_rand(3)>, L<RAND_add(3)|RAND_add(3)>,
+ L<RAND_cleanup(3)|RAND_cleanup(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/RAND_load_file.pod b/doc/crypto/RAND_load_file.pod
+index d8c134e..a079013 100644
+--- a/doc/crypto/RAND_load_file.pod
++++ b/doc/crypto/RAND_load_file.pod
+@@ -43,7 +43,7 @@ error.
+
+ =head1 SEE ALSO
+
+-L<rand(3)|rand(3)>, L<RAND_add(3)|RAND_add(3)>, L<RAND_cleanup(3)|RAND_cleanup(3)>
++L<openssl_rand(3)|openssl_rand(3)>, L<RAND_add(3)|RAND_add(3)>, L<RAND_cleanup(3)|RAND_cleanup(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/RAND_set_rand_method.pod b/doc/crypto/RAND_set_rand_method.pod
+index e5b780f..7f3ad1b 100644
+--- a/doc/crypto/RAND_set_rand_method.pod
++++ b/doc/crypto/RAND_set_rand_method.pod
+@@ -67,7 +67,7 @@ algorithms.
+
+ =head1 SEE ALSO
+
+-L<rand(3)|rand(3)>, L<engine(3)|engine(3)>
++L<openssl_rand(3)|openssl_rand(3)>, L<engine(3)|engine(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/RSA_blinding_on.pod b/doc/crypto/RSA_blinding_on.pod
+index fd2c69a..7b98614 100644
+--- a/doc/crypto/RSA_blinding_on.pod
++++ b/doc/crypto/RSA_blinding_on.pod
+@@ -34,7 +34,7 @@ RSA_blinding_off() returns no value.
+
+ =head1 SEE ALSO
+
+-L<rsa(3)|rsa(3)>, L<rand(3)|rand(3)>
++L<rsa(3)|rsa(3)>, L<openssl_rand(3)|openssl_rand(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/RSA_generate_key.pod b/doc/crypto/RSA_generate_key.pod
+index 52dbb14..3db3487 100644
+--- a/doc/crypto/RSA_generate_key.pod
++++ b/doc/crypto/RSA_generate_key.pod
+@@ -59,7 +59,7 @@ RSA_generate_key() goes into an infinite loop for illegal input values.
+
+ =head1 SEE ALSO
+
+-L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>, L<rsa(3)|rsa(3)>,
++L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>, L<rsa(3)|rsa(3)>,
+ L<RSA_free(3)|RSA_free(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/RSA_public_encrypt.pod b/doc/crypto/RSA_public_encrypt.pod
+index ab0fe3b..3b00daf 100644
+--- a/doc/crypto/RSA_public_encrypt.pod
++++ b/doc/crypto/RSA_public_encrypt.pod
+@@ -73,7 +73,7 @@ SSL, PKCS #1 v2.0
+
+ =head1 SEE ALSO
+
+-L<ERR_get_error(3)|ERR_get_error(3)>, L<rand(3)|rand(3)>, L<rsa(3)|rsa(3)>,
++L<ERR_get_error(3)|ERR_get_error(3)>, L<openssl_rand(3)|openssl_rand(3)>, L<rsa(3)|rsa(3)>,
+ L<RSA_size(3)|RSA_size(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/RSA_sign_ASN1_OCTET_STRING.pod b/doc/crypto/RSA_sign_ASN1_OCTET_STRING.pod
+index e70380b..121f3df 100644
+--- a/doc/crypto/RSA_sign_ASN1_OCTET_STRING.pod
++++ b/doc/crypto/RSA_sign_ASN1_OCTET_STRING.pod
+@@ -48,7 +48,7 @@ These functions serve no recognizable purpose.
+ =head1 SEE ALSO
+
+ L<ERR_get_error(3)|ERR_get_error(3)>, L<objects(3)|objects(3)>,
+-L<rand(3)|rand(3)>, L<rsa(3)|rsa(3)>, L<RSA_sign(3)|RSA_sign(3)>,
++L<openssl_rand(3)|openssl_rand(3)>, L<rsa(3)|rsa(3)>, L<RSA_sign(3)|RSA_sign(3)>,
+ L<RSA_verify(3)|RSA_verify(3)>
+
+ =head1 HISTORY
+diff --git a/doc/crypto/X509_NAME_ENTRY_get_object.pod b/doc/crypto/X509_NAME_ENTRY_get_object.pod
+index 41902c0..4716e7e 100644
+--- a/doc/crypto/X509_NAME_ENTRY_get_object.pod
++++ b/doc/crypto/X509_NAME_ENTRY_get_object.pod
+@@ -65,7 +65,7 @@ set first so the relevant field information can be looked up internally.
+ =head1 SEE ALSO
+
+ L<ERR_get_error(3)|ERR_get_error(3)>, L<d2i_X509_NAME(3)|d2i_X509_NAME(3)>,
+-L<OBJ_nid2obj(3),OBJ_nid2obj(3)>
++L<OBJ_nid2obj(3)|OBJ_nid2obj(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/bn.pod b/doc/crypto/bn.pod
+index cd2f8e5..a6f8c58 100644
+--- a/doc/crypto/bn.pod
++++ b/doc/crypto/bn.pod
+@@ -167,7 +167,7 @@ of B<BIGNUM>s to external formats is described in L<BN_bn2bin(3)|BN_bn2bin(3)>.
+ =head1 SEE ALSO
+
+ L<bn_internal(3)|bn_internal(3)>,
+-L<dh(3)|dh(3)>, L<err(3)|err(3)>, L<rand(3)|rand(3)>, L<rsa(3)|rsa(3)>,
++L<dh(3)|dh(3)>, L<openssl_err(3)|openssl_err(3)>, L<openssl_rand(3)|openssl_rand(3)>, L<rsa(3)|rsa(3)>,
+ L<BN_new(3)|BN_new(3)>, L<BN_CTX_new(3)|BN_CTX_new(3)>,
+ L<BN_copy(3)|BN_copy(3)>, L<BN_swap(3)|BN_swap(3)>, L<BN_num_bytes(3)|BN_num_bytes(3)>,
+ L<BN_add(3)|BN_add(3)>, L<BN_add_word(3)|BN_add_word(3)>,
+diff --git a/doc/crypto/crypto.pod b/doc/crypto/crypto.pod
+index 7a52799..ca71202 100644
+--- a/doc/crypto/crypto.pod
++++ b/doc/crypto/crypto.pod
+@@ -46,7 +46,7 @@ L<sha(3)|sha(3)>
+
+ =item AUXILIARY FUNCTIONS
+
+-L<err(3)|err(3)>, L<threads(3)|threads(3)>, L<rand(3)|rand(3)>,
++L<openssl_err(3)|openssl_err(3)>, L<openssl_threads(3)|openssl_threads(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<OPENSSL_VERSION_NUMBER(3)|OPENSSL_VERSION_NUMBER(3)>
+
+ =item INPUT/OUTPUT, DATA ENCODING
+diff --git a/doc/crypto/des.pod b/doc/crypto/des.pod
+index 6f0cf1c..3fd2c47 100644
+--- a/doc/crypto/des.pod
++++ b/doc/crypto/des.pod
+@@ -115,7 +115,7 @@ each byte is the parity bit. The key schedule is an expanded form of
+ the key; it is used to speed the encryption process.
+
+ DES_random_key() generates a random key. The PRNG must be seeded
+-prior to using this function (see L<rand(3)|rand(3)>). If the PRNG
++prior to using this function (see L<openssl_rand(3)|openssl_rand(3)>). If the PRNG
+ could not generate a secure key, 0 is returned.
+
+ Before a DES key can be used, it must be converted into the
+@@ -317,7 +317,7 @@ the MIT Kerberos library.
+
+ =head1 SEE ALSO
+
+-crypt(3), L<des_modes(7)|des_modes(7)>, L<evp(3)|evp(3)>, L<rand(3)|rand(3)>
++crypt(3), L<des_modes(7)|des_modes(7)>, L<evp(3)|evp(3)>, L<openssl_rand(3)|openssl_rand(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/crypto/dh.pod b/doc/crypto/dh.pod
+index c3ccd06..28707bf 100644
+--- a/doc/crypto/dh.pod
++++ b/doc/crypto/dh.pod
+@@ -67,8 +67,8 @@ modify keys.
+
+ =head1 SEE ALSO
+
+-L<dhparam(1)|dhparam(1)>, L<bn(3)|bn(3)>, L<dsa(3)|dsa(3)>, L<err(3)|err(3)>,
+-L<rand(3)|rand(3)>, L<rsa(3)|rsa(3)>, L<engine(3)|engine(3)>,
++L<dhparam(1)|dhparam(1)>, L<bn(3)|bn(3)>, L<dsa(3)|dsa(3)>, L<openssl_err(3)|openssl_err(3)>,
++L<openssl_rand(3)|openssl_rand(3)>, L<rsa(3)|rsa(3)>, L<engine(3)|engine(3)>,
+ L<DH_set_method(3)|DH_set_method(3)>, L<DH_new(3)|DH_new(3)>,
+ L<DH_get_ex_new_index(3)|DH_get_ex_new_index(3)>,
+ L<DH_generate_parameters(3)|DH_generate_parameters(3)>,
+diff --git a/doc/crypto/dsa.pod b/doc/crypto/dsa.pod
+index da07d2b..3187a73 100644
+--- a/doc/crypto/dsa.pod
++++ b/doc/crypto/dsa.pod
+@@ -100,7 +100,7 @@ Standard, DSS), ANSI X9.30
+
+ =head1 SEE ALSO
+
+-L<bn(3)|bn(3)>, L<dh(3)|dh(3)>, L<err(3)|err(3)>, L<rand(3)|rand(3)>,
++L<bn(3)|bn(3)>, L<dh(3)|dh(3)>, L<openssl_err(3)|openssl_err(3)>, L<openssl_rand(3)|openssl_rand(3)>,
+ L<rsa(3)|rsa(3)>, L<sha(3)|sha(3)>, L<engine(3)|engine(3)>,
+ L<DSA_new(3)|DSA_new(3)>,
+ L<DSA_size(3)|DSA_size(3)>,
+diff --git a/doc/crypto/engine.pod b/doc/crypto/engine.pod
+index f5ab1c3..63f7ebc 100644
+--- a/doc/crypto/engine.pod
++++ b/doc/crypto/engine.pod
+@@ -594,6 +594,6 @@ implementations.
+
+ =head1 SEE ALSO
+
+-L<rsa(3)|rsa(3)>, L<dsa(3)|dsa(3)>, L<dh(3)|dh(3)>, L<rand(3)|rand(3)>
++L<rsa(3)|rsa(3)>, L<dsa(3)|dsa(3)>, L<dh(3)|dh(3)>, L<openssl_rand(3)|openssl_rand(3)>
+
+ =cut
+diff --git a/doc/crypto/err.pod b/doc/crypto/err.pod
+deleted file mode 100644
+index 6f72955..0000000
+--- a/doc/crypto/err.pod
++++ /dev/null
+@@ -1,187 +0,0 @@
+-=pod
+-
+-=head1 NAME
+-
+-err - error codes
+-
+-=head1 SYNOPSIS
+-
+- #include <openssl/err.h>
+-
+- unsigned long ERR_get_error(void);
+- unsigned long ERR_peek_error(void);
+- unsigned long ERR_get_error_line(const char **file, int *line);
+- unsigned long ERR_peek_error_line(const char **file, int *line);
+- unsigned long ERR_get_error_line_data(const char **file, int *line,
+- const char **data, int *flags);
+- unsigned long ERR_peek_error_line_data(const char **file, int *line,
+- const char **data, int *flags);
+-
+- int ERR_GET_LIB(unsigned long e);
+- int ERR_GET_FUNC(unsigned long e);
+- int ERR_GET_REASON(unsigned long e);
+-
+- void ERR_clear_error(void);
+-
+- char *ERR_error_string(unsigned long e, char *buf);
+- const char *ERR_lib_error_string(unsigned long e);
+- const char *ERR_func_error_string(unsigned long e);
+- const char *ERR_reason_error_string(unsigned long e);
+-
+- void ERR_print_errors(BIO *bp);
+- void ERR_print_errors_fp(FILE *fp);
+-
+- void ERR_load_crypto_strings(void);
+- void ERR_free_strings(void);
+-
+- void ERR_remove_state(unsigned long pid);
+-
+- void ERR_put_error(int lib, int func, int reason, const char *file,
+- int line);
+- void ERR_add_error_data(int num, ...);
+-
+- void ERR_load_strings(int lib,ERR_STRING_DATA str[]);
+- unsigned long ERR_PACK(int lib, int func, int reason);
+- int ERR_get_next_error_library(void);
+-
+-=head1 DESCRIPTION
+-
+-When a call to the OpenSSL library fails, this is usually signalled
+-by the return value, and an error code is stored in an error queue
+-associated with the current thread. The B<err> library provides
+-functions to obtain these error codes and textual error messages.
+-
+-The L<ERR_get_error(3)|ERR_get_error(3)> manpage describes how to
+-access error codes.
+-
+-Error codes contain information about where the error occurred, and
+-what went wrong. L<ERR_GET_LIB(3)|ERR_GET_LIB(3)> describes how to
+-extract this information. A method to obtain human-readable error
+-messages is described in L<ERR_error_string(3)|ERR_error_string(3)>.
+-
+-L<ERR_clear_error(3)|ERR_clear_error(3)> can be used to clear the
+-error queue.
+-
+-Note that L<ERR_remove_state(3)|ERR_remove_state(3)> should be used to
+-avoid memory leaks when threads are terminated.
+-
+-=head1 ADDING NEW ERROR CODES TO OPENSSL
+-
+-See L<ERR_put_error(3)> if you want to record error codes in the
+-OpenSSL error system from within your application.
+-
+-The remainder of this section is of interest only if you want to add
+-new error codes to OpenSSL or add error codes from external libraries.
+-
+-=head2 Reporting errors
+-
+-Each sub-library has a specific macro XXXerr() that is used to report
+-errors. Its first argument is a function code B<XXX_F_...>, the second
+-argument is a reason code B<XXX_R_...>. Function codes are derived
+-from the function names; reason codes consist of textual error
+-descriptions. For example, the function ssl23_read() reports a
+-"handshake failure" as follows:
+-
+- SSLerr(SSL_F_SSL23_READ, SSL_R_SSL_HANDSHAKE_FAILURE);
+-
+-Function and reason codes should consist of upper case characters,
+-numbers and underscores only. The error file generation script translates
+-function codes into function names by looking in the header files
+-for an appropriate function name, if none is found it just uses
+-the capitalized form such as "SSL23_READ" in the above example.
+-
+-The trailing section of a reason code (after the "_R_") is translated
+-into lower case and underscores changed to spaces.
+-
+-When you are using new function or reason codes, run B<make errors>.
+-The necessary B<#define>s will then automatically be added to the
+-sub-library's header file.
+-
+-Although a library will normally report errors using its own specific
+-XXXerr macro, another library's macro can be used. This is normally
+-only done when a library wants to include ASN1 code which must use
+-the ASN1err() macro.
+-
+-=head2 Adding new libraries
+-
+-When adding a new sub-library to OpenSSL, assign it a library number
+-B<ERR_LIB_XXX>, define a macro XXXerr() (both in B<err.h>), add its
+-name to B<ERR_str_libraries[]> (in B<crypto/err/err.c>), and add
+-C<ERR_load_XXX_strings()> to the ERR_load_crypto_strings() function
+-(in B<crypto/err/err_all.c>). Finally, add an entry
+-
+- L XXX xxx.h xxx_err.c
+-
+-to B<crypto/err/openssl.ec>, and add B<xxx_err.c> to the Makefile.
+-Running B<make errors> will then generate a file B<xxx_err.c>, and
+-add all error codes used in the library to B<xxx.h>.
+-
+-Additionally the library include file must have a certain form.
+-Typically it will initially look like this:
+-
+- #ifndef HEADER_XXX_H
+- #define HEADER_XXX_H
+-
+- #ifdef __cplusplus
+- extern "C" {
+- #endif
+-
+- /* Include files */
+-
+- #include <openssl/bio.h>
+- #include <openssl/x509.h>
+-
+- /* Macros, structures and function prototypes */
+-
+-
+- /* BEGIN ERROR CODES */
+-
+-The B<BEGIN ERROR CODES> sequence is used by the error code
+-generation script as the point to place new error codes, any text
+-after this point will be overwritten when B<make errors> is run.
+-The closing #endif etc will be automatically added by the script.
+-
+-The generated C error code file B<xxx_err.c> will load the header
+-files B<stdio.h>, B<openssl/err.h> and B<openssl/xxx.h> so the
+-header file must load any additional header files containing any
+-definitions it uses.
+-
+-=head1 USING ERROR CODES IN EXTERNAL LIBRARIES
+-
+-It is also possible to use OpenSSL's error code scheme in external
+-libraries. The library needs to load its own codes and call the OpenSSL
+-error code insertion script B<mkerr.pl> explicitly to add codes to
+-the header file and generate the C error code file. This will normally
+-be done if the external library needs to generate new ASN1 structures
+-but it can also be used to add more general purpose error code handling.
+-
+-TBA more details
+-
+-=head1 INTERNALS
+-
+-The error queues are stored in a hash table with one B<ERR_STATE>
+-entry for each pid. ERR_get_state() returns the current thread's
+-B<ERR_STATE>. An B<ERR_STATE> can hold up to B<ERR_NUM_ERRORS> error
+-codes. When more error codes are added, the old ones are overwritten,
+-on the assumption that the most recent errors are most important.
+-
+-Error strings are also stored in hash table. The hash tables can
+-be obtained by calling ERR_get_err_state_table(void) and
+-ERR_get_string_table(void) respectively.
+-
+-=head1 SEE ALSO
+-
+-L<CRYPTO_set_id_callback(3)|CRYPTO_set_id_callback(3)>,
+-L<CRYPTO_set_locking_callback(3)|CRYPTO_set_locking_callback(3)>,
+-L<ERR_get_error(3)|ERR_get_error(3)>,
+-L<ERR_GET_LIB(3)|ERR_GET_LIB(3)>,
+-L<ERR_clear_error(3)|ERR_clear_error(3)>,
+-L<ERR_error_string(3)|ERR_error_string(3)>,
+-L<ERR_print_errors(3)|ERR_print_errors(3)>,
+-L<ERR_load_crypto_strings(3)|ERR_load_crypto_strings(3)>,
+-L<ERR_remove_state(3)|ERR_remove_state(3)>,
+-L<ERR_put_error(3)|ERR_put_error(3)>,
+-L<ERR_load_strings(3)|ERR_load_strings(3)>,
+-L<SSL_get_error(3)|SSL_get_error(3)>
+-
+-=cut
+diff --git a/doc/crypto/rand.pod b/doc/crypto/rand.pod
+deleted file mode 100644
+index 1c068c8..0000000
+--- a/doc/crypto/rand.pod
++++ /dev/null
+@@ -1,175 +0,0 @@
+-=pod
+-
+-=head1 NAME
+-
+-rand - pseudo-random number generator
+-
+-=head1 SYNOPSIS
+-
+- #include <openssl/rand.h>
+-
+- int RAND_set_rand_engine(ENGINE *engine);
+-
+- int RAND_bytes(unsigned char *buf, int num);
+- int RAND_pseudo_bytes(unsigned char *buf, int num);
+-
+- void RAND_seed(const void *buf, int num);
+- void RAND_add(const void *buf, int num, int entropy);
+- int RAND_status(void);
+-
+- int RAND_load_file(const char *file, long max_bytes);
+- int RAND_write_file(const char *file);
+- const char *RAND_file_name(char *file, size_t num);
+-
+- int RAND_egd(const char *path);
+-
+- void RAND_set_rand_method(const RAND_METHOD *meth);
+- const RAND_METHOD *RAND_get_rand_method(void);
+- RAND_METHOD *RAND_SSLeay(void);
+-
+- void RAND_cleanup(void);
+-
+- /* For Win32 only */
+- void RAND_screen(void);
+- int RAND_event(UINT, WPARAM, LPARAM);
+-
+-=head1 DESCRIPTION
+-
+-Since the introduction of the ENGINE API, the recommended way of controlling
+-default implementations is by using the ENGINE API functions. The default
+-B<RAND_METHOD>, as set by RAND_set_rand_method() and returned by
+-RAND_get_rand_method(), is only used if no ENGINE has been set as the default
+-"rand" implementation. Hence, these two functions are no longer the recommened
+-way to control defaults.
+-
+-If an alternative B<RAND_METHOD> implementation is being used (either set
+-directly or as provided by an ENGINE module), then it is entirely responsible
+-for the generation and management of a cryptographically secure PRNG stream. The
+-mechanisms described below relate solely to the software PRNG implementation
+-built in to OpenSSL and used by default.
+-
+-These functions implement a cryptographically secure pseudo-random
+-number generator (PRNG). It is used by other library functions for
+-example to generate random keys, and applications can use it when they
+-need randomness.
+-
+-A cryptographic PRNG must be seeded with unpredictable data such as
+-mouse movements or keys pressed at random by the user. This is
+-described in L<RAND_add(3)|RAND_add(3)>. Its state can be saved in a seed file
+-(see L<RAND_load_file(3)|RAND_load_file(3)>) to avoid having to go through the
+-seeding process whenever the application is started.
+-
+-L<RAND_bytes(3)|RAND_bytes(3)> describes how to obtain random data from the
+-PRNG.
+-
+-=head1 INTERNALS
+-
+-The RAND_SSLeay() method implements a PRNG based on a cryptographic
+-hash function.
+-
+-The following description of its design is based on the SSLeay
+-documentation:
+-
+-First up I will state the things I believe I need for a good RNG.
+-
+-=over 4
+-
+-=item 1
+-
+-A good hashing algorithm to mix things up and to convert the RNG 'state'
+-to random numbers.
+-
+-=item 2
+-
+-An initial source of random 'state'.
+-
+-=item 3
+-
+-The state should be very large. If the RNG is being used to generate
+-4096 bit RSA keys, 2 2048 bit random strings are required (at a minimum).
+-If your RNG state only has 128 bits, you are obviously limiting the
+-search space to 128 bits, not 2048. I'm probably getting a little
+-carried away on this last point but it does indicate that it may not be
+-a bad idea to keep quite a lot of RNG state. It should be easier to
+-break a cipher than guess the RNG seed data.
+-
+-=item 4
+-
+-Any RNG seed data should influence all subsequent random numbers
+-generated. This implies that any random seed data entered will have
+-an influence on all subsequent random numbers generated.
+-
+-=item 5
+-
+-When using data to seed the RNG state, the data used should not be
+-extractable from the RNG state. I believe this should be a
+-requirement because one possible source of 'secret' semi random
+-data would be a private key or a password. This data must
+-not be disclosed by either subsequent random numbers or a
+-'core' dump left by a program crash.
+-
+-=item 6
+-
+-Given the same initial 'state', 2 systems should deviate in their RNG state
+-(and hence the random numbers generated) over time if at all possible.
+-
+-=item 7
+-
+-Given the random number output stream, it should not be possible to determine
+-the RNG state or the next random number.
+-
+-=back
+-
+-The algorithm is as follows.
+-
+-There is global state made up of a 1023 byte buffer (the 'state'), a
+-working hash value ('md'), and a counter ('count').
+-
+-Whenever seed data is added, it is inserted into the 'state' as
+-follows.
+-
+-The input is chopped up into units of 20 bytes (or less for
+-the last block). Each of these blocks is run through the hash
+-function as follows: The data passed to the hash function
+-is the current 'md', the same number of bytes from the 'state'
+-(the location determined by in incremented looping index) as
+-the current 'block', the new key data 'block', and 'count'
+-(which is incremented after each use).
+-The result of this is kept in 'md' and also xored into the
+-'state' at the same locations that were used as input into the
+-hash function. I
+-believe this system addresses points 1 (hash function; currently
+-SHA-1), 3 (the 'state'), 4 (via the 'md'), 5 (by the use of a hash
+-function and xor).
+-
+-When bytes are extracted from the RNG, the following process is used.
+-For each group of 10 bytes (or less), we do the following:
+-
+-Input into the hash function the local 'md' (which is initialized from
+-the global 'md' before any bytes are generated), the bytes that are to
+-be overwritten by the random bytes, and bytes from the 'state'
+-(incrementing looping index). From this digest output (which is kept
+-in 'md'), the top (up to) 10 bytes are returned to the caller and the
+-bottom 10 bytes are xored into the 'state'.
+-
+-Finally, after we have finished 'num' random bytes for the caller,
+-'count' (which is incremented) and the local and global 'md' are fed
+-into the hash function and the results are kept in the global 'md'.
+-
+-I believe the above addressed points 1 (use of SHA-1), 6 (by hashing
+-into the 'state' the 'old' data from the caller that is about to be
+-overwritten) and 7 (by not using the 10 bytes given to the caller to
+-update the 'state', but they are used to update 'md').
+-
+-So of the points raised, only 2 is not addressed (but see
+-L<RAND_add(3)|RAND_add(3)>).
+-
+-=head1 SEE ALSO
+-
+-L<BN_rand(3)|BN_rand(3)>, L<RAND_add(3)|RAND_add(3)>,
+-L<RAND_load_file(3)|RAND_load_file(3)>, L<RAND_egd(3)|RAND_egd(3)>,
+-L<RAND_bytes(3)|RAND_bytes(3)>,
+-L<RAND_set_rand_method(3)|RAND_set_rand_method(3)>,
+-L<RAND_cleanup(3)|RAND_cleanup(3)>
+-
+-=cut
+diff --git a/doc/crypto/rsa.pod b/doc/crypto/rsa.pod
+index 45ac53f..5fa0dcc 100644
+--- a/doc/crypto/rsa.pod
++++ b/doc/crypto/rsa.pod
+@@ -108,7 +108,7 @@ RSA was covered by a US patent which expired in September 2000.
+ =head1 SEE ALSO
+
+ L<rsa(1)|rsa(1)>, L<bn(3)|bn(3)>, L<dsa(3)|dsa(3)>, L<dh(3)|dh(3)>,
+-L<rand(3)|rand(3)>, L<engine(3)|engine(3)>, L<RSA_new(3)|RSA_new(3)>,
++L<openssl_rand(3)|openssl_rand(3)>, L<engine(3)|engine(3)>, L<RSA_new(3)|RSA_new(3)>,
+ L<RSA_public_encrypt(3)|RSA_public_encrypt(3)>,
+ L<RSA_sign(3)|RSA_sign(3)>, L<RSA_size(3)|RSA_size(3)>,
+ L<RSA_generate_key(3)|RSA_generate_key(3)>,
+diff --git a/doc/crypto/threads.pod b/doc/crypto/threads.pod
+deleted file mode 100644
+index dc0e939..0000000
+--- a/doc/crypto/threads.pod
++++ /dev/null
+@@ -1,210 +0,0 @@
+-=pod
+-
+-=head1 NAME
+-
+-CRYPTO_THREADID_set_callback, CRYPTO_THREADID_get_callback,
+-CRYPTO_THREADID_current, CRYPTO_THREADID_cmp, CRYPTO_THREADID_cpy,
+-CRYPTO_THREADID_hash, CRYPTO_set_locking_callback, CRYPTO_num_locks,
+-CRYPTO_set_dynlock_create_callback, CRYPTO_set_dynlock_lock_callback,
+-CRYPTO_set_dynlock_destroy_callback, CRYPTO_get_new_dynlockid,
+-CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support
+-
+-=head1 SYNOPSIS
+-
+- #include <openssl/crypto.h>
+-
+- /* Don't use this structure directly. */
+- typedef struct crypto_threadid_st
+- {
+- void *ptr;
+- unsigned long val;
+- } CRYPTO_THREADID;
+- /* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */
+- void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val);
+- void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr);
+- int CRYPTO_THREADID_set_callback(void (*threadid_func)(CRYPTO_THREADID *));
+- void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *);
+- void CRYPTO_THREADID_current(CRYPTO_THREADID *id);
+- int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a,
+- const CRYPTO_THREADID *b);
+- void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest,
+- const CRYPTO_THREADID *src);
+- unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id);
+-
+- int CRYPTO_num_locks(void);
+-
+- /* struct CRYPTO_dynlock_value needs to be defined by the user */
+- struct CRYPTO_dynlock_value;
+-
+- void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *
+- (*dyn_create_function)(char *file, int line));
+- void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)
+- (int mode, struct CRYPTO_dynlock_value *l,
+- const char *file, int line));
+- void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)
+- (struct CRYPTO_dynlock_value *l, const char *file, int line));
+-
+- int CRYPTO_get_new_dynlockid(void);
+-
+- void CRYPTO_destroy_dynlockid(int i);
+-
+- void CRYPTO_lock(int mode, int n, const char *file, int line);
+-
+- #define CRYPTO_w_lock(type) \
+- CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+- #define CRYPTO_w_unlock(type) \
+- CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+- #define CRYPTO_r_lock(type) \
+- CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+- #define CRYPTO_r_unlock(type) \
+- CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+- #define CRYPTO_add(addr,amount,type) \
+- CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__)
+-
+-=head1 DESCRIPTION
+-
+-OpenSSL can safely be used in multi-threaded applications provided
+-that at least two callback functions are set, locking_function and
+-threadid_func.
+-
+-locking_function(int mode, int n, const char *file, int line) is
+-needed to perform locking on shared data structures.
+-(Note that OpenSSL uses a number of global data structures that
+-will be implicitly shared whenever multiple threads use OpenSSL.)
+-Multi-threaded applications will crash at random if it is not set.
+-
+-locking_function() must be able to handle up to CRYPTO_num_locks()
+-different mutex locks. It sets the B<n>-th lock if B<mode> &
+-B<CRYPTO_LOCK>, and releases it otherwise.
+-
+-B<file> and B<line> are the file number of the function setting the
+-lock. They can be useful for debugging.
+-
+-threadid_func(CRYPTO_THREADID *id) is needed to record the currently-executing
+-thread's identifier into B<id>. The implementation of this callback should not
+-fill in B<id> directly, but should use CRYPTO_THREADID_set_numeric() if thread
+-IDs are numeric, or CRYPTO_THREADID_set_pointer() if they are pointer-based.
+-If the application does not register such a callback using
+-CRYPTO_THREADID_set_callback(), then a default implementation is used - on
+-Windows and BeOS this uses the system's default thread identifying APIs, and on
+-all other platforms it uses the address of B<errno>. The latter is satisfactory
+-for thread-safety if and only if the platform has a thread-local error number
+-facility.
+-
+-Once threadid_func() is registered, or if the built-in default implementation is
+-to be used;
+-
+-=over 4
+-
+-=item *
+-CRYPTO_THREADID_current() records the currently-executing thread ID into the
+-given B<id> object.
+-
+-=item *
+-CRYPTO_THREADID_cmp() compares two thread IDs (returning zero for equality, ie.
+-the same semantics as memcmp()).
+-
+-=item *
+-CRYPTO_THREADID_cpy() duplicates a thread ID value,
+-
+-=item *
+-CRYPTO_THREADID_hash() returns a numeric value usable as a hash-table key. This
+-is usually the exact numeric or pointer-based thread ID used internally, however
+-this also handles the unusual case where pointers are larger than 'long'
+-variables and the platform's thread IDs are pointer-based - in this case, mixing
+-is done to attempt to produce a unique numeric value even though it is not as
+-wide as the platform's true thread IDs.
+-
+-=back
+-
+-Additionally, OpenSSL supports dynamic locks, and sometimes, some parts
+-of OpenSSL need it for better performance. To enable this, the following
+-is required:
+-
+-=over 4
+-
+-=item *
+-Three additional callback function, dyn_create_function, dyn_lock_function
+-and dyn_destroy_function.
+-
+-=item *
+-A structure defined with the data that each lock needs to handle.
+-
+-=back
+-
+-struct CRYPTO_dynlock_value has to be defined to contain whatever structure
+-is needed to handle locks.
+-
+-dyn_create_function(const char *file, int line) is needed to create a
+-lock. Multi-threaded applications might crash at random if it is not set.
+-
+-dyn_lock_function(int mode, CRYPTO_dynlock *l, const char *file, int line)
+-is needed to perform locking off dynamic lock numbered n. Multi-threaded
+-applications might crash at random if it is not set.
+-
+-dyn_destroy_function(CRYPTO_dynlock *l, const char *file, int line) is
+-needed to destroy the lock l. Multi-threaded applications might crash at
+-random if it is not set.
+-
+-CRYPTO_get_new_dynlockid() is used to create locks. It will call
+-dyn_create_function for the actual creation.
+-
+-CRYPTO_destroy_dynlockid() is used to destroy locks. It will call
+-dyn_destroy_function for the actual destruction.
+-
+-CRYPTO_lock() is used to lock and unlock the locks. mode is a bitfield
+-describing what should be done with the lock. n is the number of the
+-lock as returned from CRYPTO_get_new_dynlockid(). mode can be combined
+-from the following values. These values are pairwise exclusive, with
+-undefined behaviour if misused (for example, CRYPTO_READ and CRYPTO_WRITE
+-should not be used together):
+-
+- CRYPTO_LOCK 0x01
+- CRYPTO_UNLOCK 0x02
+- CRYPTO_READ 0x04
+- CRYPTO_WRITE 0x08
+-
+-=head1 RETURN VALUES
+-
+-CRYPTO_num_locks() returns the required number of locks.
+-
+-CRYPTO_get_new_dynlockid() returns the index to the newly created lock.
+-
+-The other functions return no values.
+-
+-=head1 NOTES
+-
+-You can find out if OpenSSL was configured with thread support:
+-
+- #define OPENSSL_THREAD_DEFINES
+- #include <openssl/opensslconf.h>
+- #if defined(OPENSSL_THREADS)
+- // thread support enabled
+- #else
+- // no thread support
+- #endif
+-
+-Also, dynamic locks are currently not used internally by OpenSSL, but
+-may do so in the future.
+-
+-=head1 EXAMPLES
+-
+-B<crypto/threads/mttest.c> shows examples of the callback functions on
+-Solaris, Irix and Win32.
+-
+-=head1 HISTORY
+-
+-CRYPTO_set_locking_callback() is
+-available in all versions of SSLeay and OpenSSL.
+-CRYPTO_num_locks() was added in OpenSSL 0.9.4.
+-All functions dealing with dynamic locks were added in OpenSSL 0.9.5b-dev.
+-B<CRYPTO_THREADID> and associated functions were introduced in OpenSSL 1.0.0
+-to replace (actually, deprecate) the previous CRYPTO_set_id_callback(),
+-CRYPTO_get_id_callback(), and CRYPTO_thread_id() functions which assumed
+-thread IDs to always be represented by 'unsigned long'.
+-
+-=head1 SEE ALSO
+-
+-L<crypto(3)|crypto(3)>
+-
+-=cut
+diff --git a/doc/ssl/SSL_get_error.pod b/doc/ssl/SSL_get_error.pod
+index 48c6b15..5432293 100644
+--- a/doc/ssl/SSL_get_error.pod
++++ b/doc/ssl/SSL_get_error.pod
+@@ -105,7 +105,7 @@ OpenSSL error queue contains more information on the error.
+
+ =head1 SEE ALSO
+
+-L<ssl(3)|ssl(3)>, L<err(3)|err(3)>
++L<ssl(3)|ssl(3)>, L<openssl_err(3)|openssl_err(3)>
+
+ =head1 HISTORY
+
+diff --git a/doc/ssl/SSL_want.pod b/doc/ssl/SSL_want.pod
+index c0059c0..2e51a75 100644
+--- a/doc/ssl/SSL_want.pod
++++ b/doc/ssl/SSL_want.pod
+@@ -72,6 +72,6 @@ return 1, when the corresponding condition is true or 0 otherwise.
+
+ =head1 SEE ALSO
+
+-L<ssl(3)|ssl(3)>, L<err(3)|err(3)>, L<SSL_get_error(3)|SSL_get_error(3)>
++L<ssl(3)|ssl(3)>, L<openssl_err(3)|openssl_err(3)>, L<SSL_get_error(3)|SSL_get_error(3)>
+
+ =cut
diff --git a/main/openssl/openssl-bb-basename.patch b/main/openssl/openssl-bb-basename.patch
new file mode 100644
index 0000000000..441c7b91e3
--- /dev/null
+++ b/main/openssl/openssl-bb-basename.patch
@@ -0,0 +1,20 @@
+--- openssl-0.9.8i.orig/Makefile.org Wed Nov 5 21:43:31 2008
++++ openssl-0.9.8i/Makefile.org Wed Nov 5 22:26:40 2008
+@@ -551,7 +551,7 @@
+ filecase=-i; \
+ fi; \
+ set -e; for i in doc/apps/*.pod; do \
+- fn=`basename $$i .pod`; \
++ fn=`basename $$i .pod || true`; \
+ sec=`$(PERL) util/extract-section.pl 1 < $$i`; \
+ echo "installing man$$sec/$$fn.$${sec}$(MANSUFFIX)"; \
+ (cd `$(PERL) util/dirname.pl $$i`; \
+@@ -568,7 +568,7 @@
+ done); \
+ done; \
+ set -e; for i in doc/crypto/*.pod doc/ssl/*.pod; do \
+- fn=`basename $$i .pod`; \
++ fn=`basename $$i .pod || true`; \
+ sec=`$(PERL) util/extract-section.pl 3 < $$i`; \
+ echo "installing man$$sec/$$fn.$${sec}$(MANSUFFIX)"; \
+ (cd `$(PERL) util/dirname.pl $$i`; \
diff --git a/main/opentracker/APKBUILD b/main/opentracker/APKBUILD
new file mode 100644
index 0000000000..4ea75ad20c
--- /dev/null
+++ b/main/opentracker/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=opentracker
+pkgver=0_cvs20100625
+pkgrel=2
+pkgdesc="an open and free bittorrent tracker"
+url="http://erdgeist.org/arts/software/opentracker/"
+arch="all"
+license="GPL"
+depends=
+makedepends="libowfat-dev zlib-dev"
+install="$pkgname.pre-install"
+subpackages=
+source="http://dev.alpinelinux.org/opentracker/opentracker-$pkgver.tar.gz
+ opentracker.initd"
+
+_builddir="$srcdir"/$pkgname
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/usr/bin
+ make BINDIR="$pkgdir"/usr/bin install || return 1
+ install -m644 -D opentracker.conf.sample \
+ "$pkgdir"/etc/opentracker/opentracker.conf
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+
+md5sums="8d02a6f7a241c6b8c98e2dbde086cfcf opentracker-0_cvs20100625.tar.gz
+1e1e687e78959833463ceb55101a3173 opentracker.initd"
diff --git a/main/opentracker/opentracker.initd b/main/opentracker/opentracker.initd
new file mode 100644
index 0000000000..33d2817787
--- /dev/null
+++ b/main/opentracker/opentracker.initd
@@ -0,0 +1,38 @@
+#!/sbin/runscript
+
+# Sample init.d file for alpine linux.
+
+name=opentracker
+daemon=/usr/bin/$name
+conf=${opentracker_conf:-/etc/opentracker/opentracker.conf}
+pidfile=/var/run/opentracker.pid
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${name}"
+ start-stop-daemon --start --quiet \
+ --make-pidfile \
+ --pidfile ${pidfile} \
+ --background \
+ --stdout /dev/null \
+ --stderr /dev/null \
+ --exec ${daemon} \
+ -- \
+ -d /var/empty \
+ -f $conf \
+ -u ${opentracker_user:-opentracker} \
+ ${opentracker_opts}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${name}"
+ start-stop-daemon --stop --quiet --pidfile ${pidfile} \
+ --exec ${daemon}
+ eend $?
+}
+
diff --git a/main/opentracker/opentracker.pre-install b/main/opentracker/opentracker.pre-install
new file mode 100644
index 0000000000..c6fc95ed1b
--- /dev/null
+++ b/main/opentracker/opentracker.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -D -S -H -h /var/empty -s /sbin/false opentracker 2>/dev/null
+exit 0
+
diff --git a/main/openvpn-auth-ldap/APKBUILD b/main/openvpn-auth-ldap/APKBUILD
new file mode 100644
index 0000000000..44d3611706
--- /dev/null
+++ b/main/openvpn-auth-ldap/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openvpn-auth-ldap
+pkgver=2.0.3
+_openvpnver=2.1.3
+pkgrel=0
+pkgdesc="LDAP authentication and authorization plugin for OpenVPN 2.x"
+url="http://code.google.com/p/openvpn-auth-ldap/"
+arch="all"
+license="GPL"
+depends=
+makedepends="openvpn re2c openldap-dev"
+install=
+subpackages=
+source="http://openvpn-auth-ldap.googlecode.com/files/auth-ldap-$pkgver.tar.gz
+ http://openvpn.net/release/openvpn-$_openvpnver.tar.gz
+ "
+_builddir="$srcdir"/auth-ldap-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-openvpn="$srcdir"/openvpn-$_openvpnver
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/lib
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="03dedc57efc8d4fc2ffe2c014121299d auth-ldap-2.0.3.tar.gz
+7486d3e270ba4b033e311d3e022a0ad7 openvpn-2.1.3.tar.gz"
diff --git a/main/openvpn/APKBUILD b/main/openvpn/APKBUILD
new file mode 100644
index 0000000000..466628b6d8
--- /dev/null
+++ b/main/openvpn/APKBUILD
@@ -0,0 +1,96 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=openvpn
+pkgver=2.2.0
+pkgrel=1
+pkgdesc="A robust, and highly configurable VPN (Virtual Private Network)"
+url="http://openvpn.sourceforge.net/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc $pkgname-easy-rsa:easy_rsa"
+depends="iproute2"
+makedepends="openssl-dev lzo-dev"
+install=
+source="http://swupdate.openvpn.net/community/releases/$pkgname-$pkgver.tar.gz
+ openvpn.initd
+ openvpn.confd
+ openvpn.up
+ openvpn.down
+ openvpn-2.2.0-ipv6-20110522-1.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --sysconfdir=/etc/openvpn \
+ --enable-ssl \
+ --enable-crypto \
+ --disable-threads \
+ --enable-iproute2
+
+ make || return 1
+ cd plugin/down-root
+ make || return 1
+ cd ../..
+}
+
+package() {
+ cd "$_builddir"
+
+ make DESTDIR="$pkgdir" install || return 1
+
+ # install plugins
+ install -d "$pkgdir"/usr/lib/$pkgname
+ cp plugin/*/*.so "$pkgdir"/usr/lib/$pkgname
+
+ # install examples
+ mkdir -p "$pkgdir"/usr/share/doc/$pkgname/examples
+ cp -a sample-config-files "$pkgdir"/usr/share/doc/$pkgname/examples
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+
+ # install init.d and conf.d
+ install -Dm755 "$srcdir"/openvpn.initd "$pkgdir"/etc/init.d/openvpn
+ install -Dm644 "$srcdir"/openvpn.confd "$pkgdir"/etc/conf.d/openvpn
+
+ # install up and down scripts
+ install -Dm755 "$srcdir"/openvpn.up "$pkgdir"/etc/openvpn/up.sh
+ install -Dm755 "$srcdir"/openvpn.down "$pkgdir"/etc/openvpn/down.sh
+
+}
+
+easy_rsa() {
+ pkgdesc="OpenVPN RSA key management"
+ # easy rsa can by usefull on systems
+ # which do not have openvpn installed
+ depends="openssl"
+ # install easy-rsa
+ cd "$_builddir"
+ sed -i -e 's/--directory/-d/g; s/--mode=/-m/g' easy-rsa/2.0/Makefile
+ sed -i -e '1s|#!/bin/bash|#!/bin/sh|' easy-rsa/2.0/*
+ make -C easy-rsa/2.0 DESTDIR="$subpkgdir" \
+ PREFIX=usr/share/doc/openvpn/easy-rsa \
+ install
+}
+
+doc() {
+ default_doc
+}
+
+md5sums="4f440603eac45fec7be218b87d570834 openvpn-2.2.0.tar.gz
+ec99092827faa7226e9f548c2cd1d20c openvpn.initd
+9eca88cac6294027ec1bb7be74185c3a openvpn.confd
+dc72fecd1a1bcef937603057cd6574b1 openvpn.up
+dc3ff0bae442b9aedd947b8ffda1687a openvpn.down
+25172fa251672edc3f7a277b5d7f3f72 openvpn-2.2.0-ipv6-20110522-1.patch"
diff --git a/main/openvpn/openvpn-2.2.0-ipv6-20110522-1.patch b/main/openvpn/openvpn-2.2.0-ipv6-20110522-1.patch
new file mode 100644
index 0000000000..85819de42f
--- /dev/null
+++ b/main/openvpn/openvpn-2.2.0-ipv6-20110522-1.patch
@@ -0,0 +1,4179 @@
+diff --git openvpn-2.2.0/ChangeLog.IPv6 openvpn-2.2-ipv6-20110522-1/ChangeLog.IPv6
+new file mode 100644
+index 0000000..283fe6e
+--- /dev/null
++++ openvpn-2.2-ipv6-20110522-1/ChangeLog.IPv6
+@@ -0,0 +1,440 @@
++Do 31. Dez 15:32:40 CET 2009 Gert Doering
++
++ * Basic IPv6 p2mp functionality implemented
++
++ * new options:
++ - server-ipv6
++ - ifconfig-ipv6
++ - ifconfig-ipv6-pool
++ - route-ipv6
++ - iroute-ipv6
++
++ * modules touched:
++ - init.c: init & setup IPv6 route list & add/delete IPv6 routes
++ - tun.c: add "ifconfig" and "route" handling for IPv6
++ - multi.c: IPv6 ifconfig-pool assignments
++ put to route-hash table
++ push to client
++ - pool.c: extend pools to handle IPv4+IPv6, and also return IPv6 address
++ IPv6 address saved to file if ifconfig-pool-persist is set
++ (but ignored on read due to the way pools work)
++ - mroute.c: handle reading src/dst addresses from IPv6 packets
++ (so multi.c can check against route-hash table)
++ handle printing of IPv6 mroute_addr structure
++ - helper.c: implement "server-ipv6" macro (->ifconfig-ipv6, pool, ...)
++ - options.c: implement all the new options
++ add helper functions for IPv6 address handling
++ - forward.c: tell do_route() about IPv6 routes
++ - route.c: handle IPv6 route lists + route option lists
++ extend add_routes() to do IPv4 + IPv6 route lists
++ extend delete_routes() to do IPv4 + IPv6 route lists
++ implement add_route_ipv6(), delete_route_ipv6() to call
++ system-dependend external program to do the work
++ - push.c: handle pushing of "ifconfig-ipv6" option
++ - socket.c: helper function to check & print IPv6 address strings
++
++ * known issues:
++ - operating system support on all but Linux (ifconfig, route)
++ - route-ipv6 gateway handling
++ - iroute-ipv6 not implemented
++ - TAP support: ifconfig, routing (route needs gateway!)
++
++ * release as patch 20091231-1
++
++Thu Dec 31 17:02:08 CET 2009
++
++ * NetBSD port (NetBSD 3.1 on Sparc64)
++
++ * mroute.c, socket.c: make byte/word access to in6_addr more portable
++
++ * tun.c: fix IPv6 ifconfig arguments on NetBSD
++
++ still doesn't work on NetBSD 3.1, "ifconfig tun0 inet6..." errors with
++
++ ifconfig: SIOCAIFADDR: Address family not supported by protocol family
++
++ (sys/net/if_tun.c, needs to be revision 1.80 or later, NetBSD PR 32944,
++ included in NetBSD 4.0 and up)
++
++
++Fri Jan 1 14:07:15 CET 2010
++
++ * FreeBSD port (FreeBSD 6.3-p12 on i386)
++
++ * tun.c: implement IPv6 ifconfig setting for FreeBSD
++
++ * route.c: fix %s/%s argument to IPv6 route add/delete command for *BSD
++
++ * TEST SUCCESS: FreeBSD 6.3-p12, server-ipv6, route-ipv6, ccd/iroute-ipv6
++
++ * multi.c: implement setting and deleting of iroute-ipv6
++ (multi_add_iroutes(), multi_del_iroutes())
++ * mroute.c: add mroute_helper_add_iroute6(), mroute_helper_del_iroute6()
++ * mroute.h: add prototypes, increase MR_HELPER_NET_LEN to 129 (/0.../128)
++ * multi.c: zeroize host part of IPv6 iroutes in multi_learn_in6_addr()
++ * mroute.c: implement mroute_addr_mask_host_bits() for IPv6
++
++ * TEST SUCCESS: Linux 2.6.30 (Gentoo)/iproute2, server-ipv6, ccd/iroute-ipv6
++
++ * TEST SUCCESS: Linux 2.6.30 (Gentoo)/ifconfig, client-ipv6
++
++ * TEST FAIL: NetBSD 5.0, IPv6 client
++ - "ifconfig tun0 .../64" does not create a "connected" route
++ - adding routes fails
++
++ --> more work to do here.
++
++ * release as patch 20100101-1
++
++ * TEST FAIL:
++ FreeBSD 6.3-p12 server "--topology subnet"
++ Linux/ifconfig client
++ - BSD sends ICMP6 neighbor solicitations, which are ignored by Linux
++ - server tun interface is not in p2p mode, client tun interface *is*
++
++ * TEST SUCCESS: non-ipv6 enabled client -> "--server-ipv6" server
++ (warnings in the log file, but no malfunctions)
++
++
++Sat Jan 2 19:48:35 CET 2010
++
++ * tun.c: change "ipv6_support()", do not turn off tt->ipv6 unconditionally
++ if we don't know about OS IPv6 support - just log warning
++
++ * tun.c: implement "ifconfig inet6" setting for MacOS X / Darwin
++
++ * route.c: split *BSD system dependent part of add/delete_route_ipv6()
++ into FreeBSD/Dragonfly and NetBSD/Darwin/OpenBSD variants
++ ("2001:db8::/64" vs. "2001:db8:: --prefixlen 64").
++
++ * tun.c: on MacOS X, NetBSD and OpenBSD, explicitely set on-link route
++
++ * TEST SUCCESS: MacOS X, client-ipv6 with route-ipv6
++
++
++Sun Jan 3 10:55:31 CET 2010
++
++ * route.c: NetBSD fails with "-iface tun0", needs gateway address
++ (assume that the same syntax is needed for OpenBSD)
++
++ * route.h: introduce "remote_endpoint_ipv6" into "struct route_ipv6_list"
++
++ * init.c: pass "ifconfig_ipv6_remote" as gateway to init_route_ipv6_list()
++
++ * route.c:
++ - init_route_ipv6(): use "remote_endpoint_ipv6" as IPv6 gateway address
++ if no gateway was specified explicitely
++
++ - init_route_ipv6_list(): fill in "remote_endpoint_ipv6", if parseable
++
++ - get rid of "GATEWAY-LESS ROUTE6" warning
++
++ * route.c, add_route_ipv6()
++ - explicitely clear host bits of base address, to be able to more
++ easily set up "connected" /64 routes on NetBSD+Darwin
++
++ - split system-dependent part between Darwin and NetBSD/OpenBSD
++ (Darwin can use "-iface tun0", NetBSD/OpenBSD get gateway address)
++
++ - change Solaris comments from "known-broken" to "unknown"
++
++ * tun.c: rework NetBSD tunnel initialization and tun_read() / tun_write()
++ to work the same way OpenBSD and NetBSD do - tunnel is put into
++ "multi-af" mode, and all packet read/write activity is prepended by
++ a 32 bit value specifying the address family.
++
++ * TEST SUCCESS: NetBSD 5.0/Sparc64: client-ipv6 with route-ipv6
++
++ * TEST SUCCESS: MacOS X 10.5: client-ipv6 with route-ipv6
++
++ * (RE-)TEST SUCCESS: Linux/iproute2: server-ipv6
++ Linux/ifconfig: client-ipv6
++ FreeBSD 6.3: server-ipv6
++
++ * release as patch 20100103-1
++
++ * options.c: document all new options in "--help"
++
++ * tun.c: fix typo in Solaris-specific section
++
++ * socket.h, socket.c: change u_int32_t to uint32_t
++ (Solaris - and all the rest of the code uses "uintNN" anyway)
++
++Mon Jan 4 17:46:58 CET 2010
++
++ * socket.c: rework add_in6_addr() to use 32-bit access to struct in6_addr
++ (Solaris has no 16-bit values in union, but this is more elegant as well)
++
++ * tun.c: fix "ifconfig inet6" command for Solaris
++
++ * tun.c: make sure "tun0 inet6" is unplumbed first, cleanup leftovers
++
++ * route.c: add routes with "metric 0" on solaris, otherwise they just
++ don't work (someone who understands Solaris might want to fix this).
++
++ * Solaris "sort of" works now - ifconfig works, route add does not give
++ errors, "netstat -rn" looks right, but packets are discarded unless
++ the routes are installed with "metric 0". So we just use "metric 0"...
++
++ * CAVEAT: Solaris "ifconfig ... preferred" interferes with source address
++ selection. So if there are any active IPv6 interfaces configured with
++ "preferred", packets leaving out the tunnel will use the wrong source
++ IPv6 address. Not fixable from within OpenVPN.
++
++ * CAVEAT2: Solaris insists on doing DHCPv6 on tun0 interfaces by default,
++ so DHCPv6 solicitation packets will be seen. Since the server end has
++ no idea what to do with them, they are a harmless nuisance. Fixable
++ on the Solaris side via "ndpd.conf" (see ``man ifconfig'').
++
++ * release as patch 20100104-1
++
++Fri Jan 8 10:00:50 CET 2010
++
++ * import into git repository
++
++ * options.c: add sanity checks for most typical error cases
++ (--ifconfig-ipv6-pool configured with no --ifconfig-ipv6, etc)
++
++ * options.c: modify get_ipv6_addr() to be more flexible about netbits
++ (optional now, default to /64) and to return the address-without-netbits
++ string now (-> for options that want the IPv6 address in printable
++ form, but without /nn)
++
++ * options.c: modify --ifconfig-ipv6 to optionally accept /netbits,
++ you can do now "ifconfig-ipv6 2001:df8::1/64 2001:df8::2" or just
++ "ifconfig-ipv6 2001:df8::5 2001:df8::7", defaulting to /64
++
++ * options.h: add necessary structure elements for --ifconfig-ipv6-push
++
++ * options.c: implement "parse options" side of --ifconfig-ipv6-push
++
++Tue Jan 12 22:42:09 CET 2010
++
++ * tun.c: in TARGET_NETBSD #ifdef, distinguish between "old" code
++ (IPv4 only, but unmodified read/write) and "new" code (multi-af,
++ extra 32 bit AF on read/write of the tun interface) - pre-4.0
++ NetBSD systems don't have TUNSIFHEAD, no way to have common code.
++
++ * TEST SUCCESS: NetBSD 5.0/Sparc64: client-ipv6 with route-ipv6 (v4+v6)
++
++ * TEST SUCCESS: NetBSD 3.1/Sparc64: client-ipv6 with route-ipv6 (v4-only)
++
++Thu Jan 14 15:41:50 CET 2010
++
++ * multi.c: if "--ifconfig-push" is used together with "--ifconfig-ipv6-pool"
++ and no "--ifconfig-ipv6-push" is seen, issue warning - the current
++ implementation of pools has IPv6 tied to IPv4, so if v4 does not use
++ the pool, it breaks for IPv6. Not a *big* problem (since there is
++ enough v6, just give those users a static v6 address as well), but needs
++ to be pointed out clearly.
++
++ * release as patch 20100114-1
++
++Tue Feb 16 14:43:28 CET 2010
++
++ * options.c: print "IPv6 payload patch" release date in "--version"
++
++ * tun.c: undo change to init_tun() (moving "bool tun" and call to
++ "is_tun_p2p()" further up) - it wasn't needed and breaks "make check"
++
++ * git stuff: rebase on David Sommerseth's openvpn-testing git tree
++
++ * release as patch 20100216-1
++
++Fri Feb 26 19:59:01 CET 2010
++
++ * init.c: initialize tuntap->ipv6 in do_init_tun() (to make sure it's
++ always initialized early-enough, independent of the sequence of
++ do_ifconfig()/open_tun() [see ifconfig_order() in tun.h])
++
++ * tun.c, init.c: remove "bool ipv6" argument to tuncfg(), open_tun()
++ and open_tun_generic() - obsoleted by previous change
++
++ * tun.c: remove ipv6_support() - original purpose was unclear, and all
++ current platforms (except linux-very-old) fully support IPv6 now :-)
++
++ * tun.c: initial implementation of "netsh" IPv6-ifconfig for Win32
++
++ * RE-TEST SUCCESS: Linux/i386/ifconfig, client-tun/net30, v4+v6
++
++Sun Feb 28 17:05:57 CET 2010
++
++ * tun.c: NetBSD dependent part: correct destroying/re-creation of tun dev
++
++ * tun.c: move adding of "connected" IPv6 prefix to new helper function,
++ add_route_connected_v6_net()
++
++ * RE-TEST SUCCESS: NetBSD 5.0/Sparc64, client-tun/net30, v4+v6
++
++ * RE-TEST SUCCESS: NetBSD 3.1/Sparc64: client-tun/net30, v4-only
++
++ * RE-TEST SUCCESS: Linux/i386/iproute2: server-tun/net30, v4+v6
++
++ * tun.c: add #ifdef TARGET_DARWIN block for *_tun() functions, to
++ be able to modify close_tun() for unconfiguring IPv6
++
++ * tun.c: on close_tun() on MacOS X, need to de-configure "lo0" route for
++ configured IPv6 address
++
++ * RE-TEST SUCCESS: MacOS X (10.5)/i386: client-tun/net30, v4+v6
++
++ * route.c: implement ipv6 route adding / deletion via "netsh" for WIN32
++
++ * TEST FAIL: Windows XP fails, because the tun/tap driver does not
++ forward IPv6 frames kernel->userland if in "tun" mode
++
++ * options.c: set IPv6 version to 20100228-1
++
++ * release as patch 20100228-1
++
++Sun Mar 7 19:17:33 CET 2010
++
++ * options.c: set IPv6 version to 20100307-1
++
++ * TODO.IPv6: add note about OpenBSD TODO (#16)
++
++ * route.c: set (and remove) "magic next hop" fe80::8 for IPv6 routes on
++ Win32
++
++ * install-win32/settings.in: bump TAP driver version from 9.6 to 9.7
++ and TAP_RELDATE to "07/03/2010"
++
++ * tap-win32/proto.h: add data types and definitions needed for IPv6
++
++ * tap-win32/types.h: add m_UserToTap_IPv6 ethernet header for IPv6 packets
++
++ * tap-win32/tapdrvr.c: implement support for IPv6 in TUN mode:
++ - IPv6 packets User->OS need correct ether type
++ - IPv6 packets OS->User get correctly forwarded
++ - IPv6 neighbour discovery packets for "fe80::8" (magic address
++ installed as route-nexthop by OpenVPN.exe) get answered locally
++
++ * TEST SUCCESS: WindowsXP/32bit: client-tun/net30, v4+v6
++
++ * tun.c: if IPv6 requested in TUN mode, and TUN/TAP driver version
++ is older than 9.7, log warning and disable IPv6 (won't work anyway).
++
++ * release as patch 20100307-1
++
++Sat Jul 10 14:37:52 CEST 2010
++
++ * TEST SUCCESS: point-to-point tun mode with --ifconfig-ipv6 between
++ Solaris10/sparc and Linux (Michal Ludvig)
++ (using the whiteboard tun driver on Solaris, otherwise "no IPv6")
++
++Sun Aug 8 12:30:44 CEST 2010
++
++ * route.c: split NetBSD and OpenBSD parts of add_route_ipv6() and
++ delete_route_ipv6(), implement OpenBSD variant
++ (needs "-prefixlen nn" while NetBSD uses "/nn")
++
++ * tun.c: implement IPv6 ifconfig for OpenBSD
++
++ * tun.c: destroy tunX interface at tun_close() on OpenBSD (cleanup)
++
++ * TEST SUCCESS: OpenBSD 4.7: client-tun/net30, v4+v6
++
++Thu Sep 2 21:18:32 CEST 2010
++
++ * tun.c: the TAP binary in 2.2-beta3 has the IPv6 related changes, but
++ the version number is 9.8 now -> check for 9.8, not 9.7
++
++Wed Sep 22 22:20:37 CEST 2010
++
++ * tun.c: bugfix for Linux/iproute2/"topology subnet". Works :-)
++
++ * TEST SUCCESS: Linux/ifconfig: client-tun/net30+subnet, v4+v6
++
++ * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
++
++ * options.c: tag as 20100922-1 so "allmerged" users can see IPv6 change
++
++Fri Sep 24 17:57:41 CEST 2010
++
++ * TEST SUCCESS: Linux/<both>: client-tap, v4+v6, ping6 on connected addr
++
++ * TEST FAIL: Linux/<both>: client-tap, v6, route6 (gateway missing)
++
++Do 21. Okt 19:36:49 CEST 2010
++
++ * t_client.sh.in: cherrypick commit f25fe91a40aa3f and 6f1e61b41be52
++ (proper exit codes to signal "SKIP" if we do not want to run)
++
++So 16. Jan 17:25:23 CET 2011
++
++ * tun.c, route.c: cherrypick 121755c2cb4891f and f0eac1a5979096c67
++ (TAP driver and "topology subnet" support for Solaris)
++
++ * tun.c: add IPv6 configuration for TAP interfaces (<device>:1 inet6)
++
++ * tun.c: on close_tun on Solaris, unplumb IPv6 TUN or TAP interfaces
++
++ * TEST SUCCESS: OpenSolaris: client-tun, v4+v6
++ TEST SUCCESS: OpenSolaris: client-tap, v4+v6, ping6 on connected addr
++ TEST FAIL: OpenSolaris: client-tap, v6, route6 (gateway missing)
++
++So 24. Apr 16:51:45 CEST 2011
++
++ * rebase to "beta2.2" branch (at 2.2RC2 tag)
++
++ * mroute.c: remove mroute_helper_lock/_unlock() calls for IPv6
++ * socket.c: remove locking with L_INET_NTOA mutex
++ (all the threading stuff got removed by David Sommerseth for 2.2)
++
++ * mroute.c: remove duplicate mroute_helper_add_iroute6() and
++ mroute_helper_del_iroute6() - "git rebase" artefact
++
++ * ChangeLog.IPv6 and TODO.IPv6: add to commit
++
++ * options.c: tag as 20110424-2 (2.2RC2)
++
++ * TEST SUCCESS: Linux/ifconfig: client-tun/net30+subnet, v4+v6
++
++ * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
++
++Thu Apr 28 19:10:01 CEST 2011
++
++ * rebase to "origin/release/2.2" branch (at v2.2.0 tag)
++
++Thu May 19 20:51:12 CEST 2011
++
++ * include Windows "netsh add" -> "netsh set ... store=active" patch from
++ Seth Mos, to fix restart problems on Windows due to persistant addresses
++
++ * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
++
++Sat May 21 17:03:20 CEST 2011
++
++ * tun.c: Solaris cleanup (use CLEAR() to zero-out "ifr")
++
++ * tun.c: Windows cleanup: remove route and IPv6 address on disconnect
++
++ * route.c, route.h: remove "static" from delete_route_ipv6(), needed
++ for ipv6-route cleanup on disconnect
++
++ * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
++
++ * TEST SUCCESS: Windows 7 Home Premium: client-tun/net30, v4+v6
++
++So 22. Mai 14:46:12 CEST 2011
++
++ * Tony Lim: removing routes fails on windows if certain bits are set
++ in the "host part" (others are silently ignored) -->
++
++ * route.c: create print_in6_addr_netbits_only() helper, call from
++ add_route_ipv6() and delete_route_ipv6() to get only network part
++ of route-to-be-modified
++
++ * route.c: set 'store=active' on adding routes on WIN32 as well (Tony Lim)
++
++ * options.c: bump IPv6 release to 20110522-1
++
++ * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
++
++ * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
++
++ * TEST SUCCESS: Windows 7 Home Premium: client-tun/net30, v4+v6
++
++ * TEST SUCCESS: OpenBSD 4.7: client-tun/net30, v4+v6
++ TEST FAIL: OpenBSD 4.7: client-tun/subnet, v4
++ (seems to be due to "topology subnet has just not been implemented yet")
+diff --git openvpn-2.2.0/README.IPv6 openvpn-2.2-ipv6-20110522-1/README.IPv6
+new file mode 100644
+index 0000000..ca578f2
+--- /dev/null
++++ openvpn-2.2-ipv6-20110522-1/README.IPv6
+@@ -0,0 +1,8 @@
++This is an experimentally patched version of OpenVPN 2.1 with IPv6
++payload support.
++
++Go here for release notes and documentation:
++
++ http://www.greenie.net/ipv6/openvpn.html
++
++Gert Doering, 31.12.2009
+diff --git openvpn-2.2.0/TODO.IPv6 openvpn-2.2-ipv6-20110522-1/TODO.IPv6
+new file mode 100644
+index 0000000..167ca51
+--- /dev/null
++++ openvpn-2.2-ipv6-20110522-1/TODO.IPv6
+@@ -0,0 +1,153 @@
++known issues for IPv6 payload support in OpenVPN
++-----------------------------------------------
++
++1.) "--topology subnet" doesn't work together with IPv6 payload on FreeBSD
++ (verified for FreeBSD server, Linux/ifconfig client, problems
++ with ICMP6 neighbor solicitations from BSD not being answered by Linux)
++
++2.) NetBSD IPv6 support doesn't work
++ ("connected" route is not auto-created, "route-ipv6" adding fails)
++
++ * fixed, 3.1.10 *
++
++3.) route deletion for IPv6 routes is not yet done
++
++ * fixed for configured routes, 3.1.10 *
++ * missing for manual-ifconfig-connected (NetBSD, Darwin, Win32)
++ * fixed for Win32, 22.5.2011
++
++4.) do "ifconfig tun0 inet6 unplumb" or "ifconfig tun0 destroy" for
++ Solaris, *BSD, ... at program termination time, to clean up leftovers
++ (unless tunnel persistance is desired).
++
++ For Solaris, only the "ipv6 tun0" is affected, for the *BSDs all tun0
++ stay around.
++
++4a.) deconfigure IPv6 on tun interface on session termination, otherwise
++ one could end up with something like this (on NetBSD):
++
++tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
++ inet 10.9.0.18 -> 10.9.0.17 netmask 0xffffffff
++ inet6 fe80::a00:20ff:fece:d299%tun0 -> prefixlen 64 scopeid 0x3
++ inet6 2001:608:4:eff::2000:3 -> prefixlen 64
++ inet6 2001:608:4:eff::1:3 -> prefixlen 64
++
++ (pool was changed, previous address still active on tun0, breakage)
++
++ * semi-fixed for NetBSD, 28.2.10, always do tun0 destroy / tun0 create
++ before actual ifconfig -- tunnel still lingers after OpenVPN quits
++
++4b.) verify this - on FreeBSD, tun0 is auto-destroyed if created by
++ opening /dev/tun (and lingers if created by "ifconfig tun0 create")
++
++ -> use for persistant tunnels on not-linux?
++
++5.) add new option "ifconfig-ipv6-push"
++ (per-client static IPv6 assignment, -> radiusplugin, etc)
++
++ * implemented, 14.1.10 *
++
++6.) add new option "route-ipv6-gateway"
++
++7.) add "full" gateway handling for IPv6 in route.c
++ (right now, the routes are just sent down the tun interface, if the
++ operating system in questions supports that, without care for the
++ gateway address - which does not work for gateways that are supposed
++ to point elsewhere. Also, it doesn't work for TAP interfaces.
++
++8.) full IPv6 support for TAP interfaces
++ (main issue should be routes+gateway - and testing :-) )
++
++ test 2010/09/24: TAP itself works on linux/ifconfig+iproute2, but
++ route-via-tap doesn't work at all (route points to "tap0" which fails)
++
++17:51:14.075412 fe:ab:6e:c5:53:71 > 33:33:ff:00:00:01, ethertype IPv6 (0x86dd), length 86: 2001:608:4:a053::1:0 > ff02::1:ff00:1: ICMP6, neighbor solicitation, who has 2001:608:4:a001::1, length 32
++
++ how is iroute-via-tap supposed to work??
++
++9.) verify that iroute-ipv6 and route-ipv6 interact in the same way as
++ documented for iroute/route:
++
++ A's subnet, OpenVPN must push this route to all clients
++ EXCEPT for A, since the subnet is already owned by A.
++ OpenVPN accomplishes this by not
++ not pushing a route to a client
++ if it matches one of the client's iroutes.
++
++10.) extend "ifconfig-ipv6" to handle specification of /netbits, pushing
++ of /netbits, and correctly ifconfig'ing this
++ (default, if not specified: /64)
++
++11.) do not add ipv6-routes if tun-ipv6 is not set - complain instead
++
++ * done * 12.1.10
++
++12.) handle incoming [::] and [fe80:...] packets in tun-p2mp MULTI mode
++ (most likely those are DAD packets)
++ silently ignore DAD?
++ Or accept-and-forward iff (multicast && client2client)?
++ handle NS/NA
++
++13.) from Martin List-Petersen:
++
++ One thing, and I guess this requires modifications in
++ network-manager-openvpn: It also works, BUT ignores "push
++ route-ipv6-gateway" and "push route-ipv6 ...." (obviously routes pushed
++ from the server) entirely.
++
++14.) from ##openvpn-discussion:
++
++ new features should be #ifdef'ed
++
++ (check whether this is feasible at all)
++
++15.) IPv6 related environment variables
++
++ - document all of them in openvpn.8
++ - make sure that all existing IPv4 stuff has IPv6 counterparts
++
++16.) OpenBSD
++ - implement ifconfig/route for IPv6
++ - revert ifconfig/open_tun order to "normal" (separate commit!!!)
++ (openvpn-devel, Subject: OpenBSD)
++ - test
++
++17.) client-option (Elwood)
++ - ignore-v6-push-options yes/no
++ - ignore-v6-route-push ("as for IPv4 routes")
++
++18.) fail-save? "what if 'ip -6 addr add' fails" -> fail, or fallback to v4?
++ (-> recomment setting "ignore-v6-push-options yes")
++
++19.) safety check: if connecting over IPv6 (v6 transport) and the pushed
++ route-ipv6 network encompasses the server IPv6 address, make sure
++ we at least log a warning (until we can fiddle with external routing
++ to make this work correctly).
++
++20.) show "route add" / "route delete" commands for IPv6 in log file
++ (we show the "ifconfig" commands, so why not the routes?)
++
++ 2010-08-07: this is a null-feature - it's already there, but with
++ different debug level (M_INFO vs. D_ROUTE) so user
++ didn't notice
++
++21.) enable ipv6-only server operations
++ - decouple ipv6 pool handling from ipv4 pool
++ - make sure Rest of OpenVPN doesn't assume "there will always be IPv4"
++
++22.) implement --learn-address for IPv6
++
++23.) FreeBSD 8 seems to require explicit setting of the "ifconfig" IPv6
++ route, while FreeBSD 6+7 don't --> more testing, and code fix
++
++ workaround for the time being: just add
++
++ server-ipv6 2001:608:4:a051::/64
++ route-ipv6 2001:608:4:a051::/64
++
++ to the config
++
++ (problem + workaround applies both to tun and tap style devices)
++
++24.) implement link-local IPv6 addresses
++ (OSPFv3 over TUN/multipoint does not work right now)
+diff --git openvpn-2.2.0/forward.c openvpn-2.2-ipv6-20110522-1/forward.c
+index 87d05cc..1f3d435 100644
+--- openvpn-2.2.0/forward.c
++++ openvpn-2.2-ipv6-20110522-1/forward.c
+@@ -262,7 +262,8 @@ send_control_channel_string (struct context *c, const char *str, int msglevel)
+ static void
+ check_add_routes_action (struct context *c, const bool errors)
+ {
+- do_route (&c->options, c->c1.route_list, c->c1.tuntap, c->plugins, c->c2.es);
++ do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
++ c->c1.tuntap, c->plugins, c->c2.es);
+ update_time ();
+ event_timeout_clear (&c->c2.route_wakeup);
+ event_timeout_clear (&c->c2.route_wakeup_expire);
+diff --git openvpn-2.2.0/helper.c openvpn-2.2-ipv6-20110522-1/helper.c
+index a9d7fd9..266b246 100644
+--- openvpn-2.2.0/helper.c
++++ openvpn-2.2-ipv6-20110522-1/helper.c
+@@ -142,6 +142,55 @@ helper_client_server (struct options *o)
+
+ #if P2MP
+ #if P2MP_SERVER
++
++ /*
++ *
++ * HELPER DIRECTIVE for IPv6
++ *
++ * server-ipv6 2001:db8::/64
++ *
++ * EXPANDS TO:
++ *
++ * tun-ipv6
++ * push "tun-ipv6"
++ * ifconfig-ipv6 2001:db8::1 2001:db8::2
++ * if !nopool:
++ * ifconfig-ipv6-pool 2001:db8::1:0/64
++ *
++ */
++ if ( o->server_ipv6_defined )
++ {
++ if ( ! o->server_defined )
++ {
++ msg (M_USAGE, "--server-ipv6 must be used together with --server");
++ }
++ if ( o->server_flags & SF_NOPOOL )
++ {
++ msg( M_USAGE, "--server-ipv6 is incompatible with 'nopool' option" );
++ }
++ if ( o->ifconfig_ipv6_pool_defined )
++ {
++ msg( M_USAGE, "--server-ipv6 already defines an ifconfig-ipv6-pool, so you can't also specify --ifconfig-pool explicitly");
++ }
++
++ /* local ifconfig is "base address + 1" and "+2" */
++ o->ifconfig_ipv6_local =
++ print_in6_addr( add_in6_addr( o->server_network_ipv6, 1), 0, &o->gc );
++ o->ifconfig_ipv6_remote =
++ print_in6_addr( add_in6_addr( o->server_network_ipv6, 2), 0, &o->gc );
++
++ /* pool starts at "base address + 0x10000" */
++ ASSERT( o->server_netbits_ipv6 < 96 ); /* want 32 bits */
++ o->ifconfig_ipv6_pool_defined = true;
++ o->ifconfig_ipv6_pool_base =
++ add_in6_addr( o->server_network_ipv6, 0x10000 );
++ o->ifconfig_ipv6_pool_netbits = o->server_netbits_ipv6;
++
++ o->tun_ipv6 = true;
++
++ push_option( o, "tun-ipv6", M_USAGE );
++ }
++
+ /*
+ *
+ * HELPER DIRECTIVE:
+diff --git openvpn-2.2.0/init.c openvpn-2.2-ipv6-20110522-1/init.c
+index d47a4ef..7fc8eb7 100644
+--- openvpn-2.2.0/init.c
++++ openvpn-2.2-ipv6-20110522-1/init.c
+@@ -843,7 +843,7 @@ do_persist_tuntap (const struct options *options)
+ msg (M_FATAL|M_OPTERR,
+ "options --mktun or --rmtun should only be used together with --dev");
+ tuncfg (options->dev, options->dev_type, options->dev_node,
+- options->tun_ipv6, options->persist_mode,
++ options->persist_mode,
+ options->username, options->groupname, &options->tuntap_options);
+ if (options->persist_mode && options->lladdr)
+ set_lladdr(options->dev, options->lladdr, NULL);
+@@ -1066,6 +1066,8 @@ do_alloc_route_list (struct context *c)
+ {
+ if (c->options.routes && !c->c1.route_list)
+ c->c1.route_list = new_route_list (c->options.max_routes, &c->gc);
++ if (c->options.routes_ipv6 && !c->c1.route_ipv6_list)
++ c->c1.route_ipv6_list = new_route_ipv6_list (c->options.max_routes, &c->gc);
+ }
+
+
+@@ -1108,6 +1110,45 @@ do_init_route_list (const struct options *options,
+ }
+ }
+
++static void
++do_init_route_ipv6_list (const struct options *options,
++ struct route_ipv6_list *route_ipv6_list,
++ bool fatal,
++ struct env_set *es)
++{
++ const char *gw = NULL;
++ int dev = dev_type_enum (options->dev, options->dev_type);
++ int metric = 0;
++
++ if (dev != DEV_TYPE_TUN )
++ msg( M_WARN, "IPv6 routes on TAP devices are going to fail on some platforms (need gateway spec)" ); /* TODO-GERT */
++
++ gw = options->ifconfig_ipv6_remote; /* default GW = remote end */
++#if 0 /* not yet done for IPv6 - TODO!*/
++ if ( options->route_ipv6_default_gateway ) /* override? */
++ gw = options->route_ipv6_default_gateway;
++#endif
++
++ if (options->route_default_metric)
++ metric = options->route_default_metric;
++
++ if (!init_route_ipv6_list (route_ipv6_list,
++ options->routes_ipv6,
++ gw,
++ metric,
++ es))
++ {
++ if (fatal)
++ openvpn_exit (OPENVPN_EXIT_STATUS_ERROR); /* exit point */
++ }
++ else
++ {
++ /* copy routes to environment */
++ setenv_routes_ipv6 (es, route_ipv6_list);
++ }
++}
++
++
+ /*
+ * Called after all initialization has been completed.
+ */
+@@ -1172,12 +1213,13 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
+ void
+ do_route (const struct options *options,
+ struct route_list *route_list,
++ struct route_ipv6_list *route_ipv6_list,
+ const struct tuntap *tt,
+ const struct plugin_list *plugins,
+ struct env_set *es)
+ {
+- if (!options->route_noexec && route_list)
+- add_routes (route_list, tt, ROUTE_OPTION_FLAGS (options), es);
++ if (!options->route_noexec && ( route_list || route_ipv6_list ) )
++ add_routes (route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS (options), es);
+
+ if (plugin_defined (plugins, OPENVPN_PLUGIN_ROUTE_UP))
+ {
+@@ -1234,11 +1276,16 @@ do_init_tun (struct context *c)
+ c->options.topology,
+ c->options.ifconfig_local,
+ c->options.ifconfig_remote_netmask,
++ c->options.ifconfig_ipv6_local,
++ c->options.ifconfig_ipv6_remote,
+ addr_host (&c->c1.link_socket_addr.local),
+ addr_host (&c->c1.link_socket_addr.remote),
+ !c->options.ifconfig_nowarn,
+ c->c2.es);
+
++ /* flag tunnel for IPv6 config if --tun-ipv6 is set */
++ c->c1.tuntap->ipv6 = c->options.tun_ipv6;
++
+ init_tun_post (c->c1.tuntap,
+ &c->c2.frame,
+ &c->options.tuntap_options);
+@@ -1270,6 +1317,8 @@ do_open_tun (struct context *c)
+ /* parse and resolve the route option list */
+ if (c->options.routes && c->c1.route_list && c->c2.link_socket)
+ do_init_route_list (&c->options, c->c1.route_list, &c->c2.link_socket->info, false, c->c2.es);
++ if (c->options.routes_ipv6 && c->c1.route_ipv6_list )
++ do_init_route_ipv6_list (&c->options, c->c1.route_ipv6_list, false, c->c2.es);
+
+ /* do ifconfig */
+ if (!c->options.ifconfig_noexec
+@@ -1286,7 +1335,7 @@ do_open_tun (struct context *c)
+
+ /* open the tun device */
+ open_tun (c->options.dev, c->options.dev_type, c->options.dev_node,
+- c->options.tun_ipv6, c->c1.tuntap);
++ c->c1.tuntap);
+
+ /* set the hardware address */
+ if (c->options.lladdr)
+@@ -1315,7 +1364,8 @@ do_open_tun (struct context *c)
+
+ /* possibly add routes */
+ if (!c->options.route_delay_defined)
+- do_route (&c->options, c->c1.route_list, c->c1.tuntap, c->plugins, c->c2.es);
++ do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
++ c->c1.tuntap, c->plugins, c->c2.es);
+
+ /*
+ * Did tun/tap driver give us an MTU?
+@@ -1389,8 +1439,9 @@ do_close_tun (struct context *c, bool force)
+ #endif
+
+ /* delete any routes we added */
+- if (c->c1.route_list)
+- delete_routes (c->c1.route_list, c->c1.tuntap, ROUTE_OPTION_FLAGS (&c->options), c->c2.es);
++ if (c->c1.route_list || c->c1.route_ipv6_list )
++ delete_routes (c->c1.route_list, c->c1.route_ipv6_list,
++ c->c1.tuntap, ROUTE_OPTION_FLAGS (&c->options), c->c2.es);
+
+ /* actually close tun/tap device based on --down-pre flag */
+ if (!c->options.down_pre)
+diff --git openvpn-2.2.0/init.h openvpn-2.2-ipv6-20110522-1/init.h
+index cf5ca8a..5a1d1dc 100644
+--- openvpn-2.2.0/init.h
++++ openvpn-2.2-ipv6-20110522-1/init.h
+@@ -63,6 +63,7 @@ void init_instance (struct context *c, const struct env_set *env, const unsigned
+
+ void do_route (const struct options *options,
+ struct route_list *route_list,
++ struct route_ipv6_list *route_ipv6_list,
+ const struct tuntap *tt,
+ const struct plugin_list *plugins,
+ struct env_set *es);
+diff --git openvpn-2.2.0/misc.c openvpn-2.2-ipv6-20110522-1/misc.c
+index 4067d85..9d351f4 100644
+--- openvpn-2.2.0/misc.c
++++ openvpn-2.2-ipv6-20110522-1/misc.c
+@@ -1001,7 +1001,9 @@ setenv_str_ex (struct env_set *es,
+ {
+ const char *str = construct_name_value (name_tmp, val_tmp, &gc);
+ env_set_add (es, str);
+- /*msg (M_INFO, "SETENV_ES '%s'", str);*/
++#if DEBUG_VERBOSE_SETENV
++ msg (M_INFO, "SETENV_ES '%s'", str);
++#endif
+ }
+ else
+ env_set_del (es, name_tmp);
+diff --git openvpn-2.2.0/mroute.c openvpn-2.2-ipv6-20110522-1/mroute.c
+index 3debd80..3182f65 100644
+--- openvpn-2.2.0/mroute.c
++++ openvpn-2.2-ipv6-20110522-1/mroute.c
+@@ -88,12 +88,33 @@ mroute_get_in_addr_t (struct mroute_addr *ma, const in_addr_t src, unsigned int
+ }
+ }
+
++static inline void
++mroute_get_in6_addr (struct mroute_addr *ma, const struct in6_addr src, unsigned int mask)
++{
++ if (ma)
++ {
++ ma->type = MR_ADDR_IPV6 | mask;
++ ma->netbits = 0;
++ ma->len = 16;
++ *(struct in6_addr *)ma->addr = src;
++ }
++}
++
+ static inline bool
+ mroute_is_mcast (const in_addr_t addr)
+ {
+ return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
+ }
+
++/* RFC 4291, 2.7, "binary 11111111 at the start of an address identifies
++ * the address as being a multicast address"
++ */
++static inline bool
++mroute_is_mcast_ipv6 (const struct in6_addr addr)
++{
++ return (addr.s6_addr[0] == 0xff);
++}
++
+ #ifdef ENABLE_PF
+
+ static unsigned int
+@@ -155,10 +176,29 @@ mroute_extract_addr_ipv4 (struct mroute_addr *src,
+ }
+ break;
+ case 6:
+- {
+- msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet");
+- break;
+- }
++ if (BLEN (buf) >= (int) sizeof (struct openvpn_ipv6hdr))
++ {
++ const struct openvpn_ipv6hdr *ipv6 = (const struct openvpn_ipv6hdr *) BPTR (buf);
++#if 0 /* very basic debug */
++ struct gc_arena gc = gc_new ();
++ msg( M_INFO, "IPv6 packet! src=%s, dst=%s",
++ print_in6_addr( ipv6->saddr, 0, &gc ),
++ print_in6_addr( ipv6->daddr, 0, &gc ));
++ gc_free (&gc);
++#endif
++
++ mroute_get_in6_addr (src, ipv6->saddr, 0);
++ mroute_get_in6_addr (dest, ipv6->daddr, 0);
++
++ if (mroute_is_mcast_ipv6 (ipv6->daddr))
++ ret |= MROUTE_EXTRACT_MCAST;
++
++ ret |= MROUTE_EXTRACT_SUCCEEDED;
++ }
++ break;
++ default:
++ msg (M_WARN, "IP packet with unknown IP version=%d seen",
++ OPENVPN_IPH_GET_VER (*BPTR(buf)));
+ }
+ }
+ return ret;
+@@ -252,14 +292,36 @@ bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
+ * Zero off the host bits in an address, leaving
+ * only the network bits, using the netbits member of
+ * struct mroute_addr as the controlling parameter.
++ *
++ * TODO: this is called for route-lookup for every yet-unhashed
++ * destination address, so for lots of active net-iroutes, this
++ * might benefit from some "zeroize 32 bit at a time" improvements
+ */
+ void
+ mroute_addr_mask_host_bits (struct mroute_addr *ma)
+ {
+ in_addr_t addr = ntohl(*(in_addr_t*)ma->addr);
+- ASSERT ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4);
+- addr &= netbits_to_netmask (ma->netbits);
+- *(in_addr_t*)ma->addr = htonl (addr);
++ if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4)
++ {
++ addr &= netbits_to_netmask (ma->netbits);
++ *(in_addr_t*)ma->addr = htonl (addr);
++ }
++ else if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV6)
++ {
++ int byte = ma->len-1; /* rightmost byte in address */
++ int bits_to_clear = 128 - ma->netbits;
++
++ while( byte >= 0 && bits_to_clear > 0 )
++ {
++ if ( bits_to_clear >= 8 )
++ { ma->addr[byte--] = 0; bits_to_clear -= 8; }
++ else
++ { ma->addr[byte--] &= (~0 << bits_to_clear); bits_to_clear = 0; }
++ }
++ ASSERT( bits_to_clear == 0 );
++ }
++ else
++ ASSERT(0);
+ }
+
+ /*
+@@ -337,17 +399,24 @@ mroute_addr_print_ex (const struct mroute_addr *ma,
+ }
+ break;
+ case MR_ADDR_IPV6:
+- buf_printf (&out, "IPV6");
+- break;
+- default:
+- buf_printf (&out, "UNKNOWN");
+- break;
+- }
+- return BSTR (&out);
+- }
+- else
+- return "[NULL]";
+-}
++ {
++ buf_printf (&out, "%s",
++ print_in6_addr( *(struct in6_addr*)&maddr.addr, 0, gc));
++ if (maddr.type & MR_WITH_NETBITS)
++ {
++ buf_printf (&out, "/%d", maddr.netbits);
++ }
++ }
++ break;
++ default:
++ buf_printf (&out, "UNKNOWN");
++ break;
++ }
++ return BSTR (&out);
++ }
++ else
++ return "[NULL]";
++ }
+
+ /*
+ * mroute_helper's main job is keeping track of
+@@ -418,6 +487,40 @@ mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir)
+ }
+ }
+
++/* this is a bit inelegant, we really should have a helper to that
++ * is only passed the netbits value, and not the whole struct iroute *
++ * - thus one helper could do IPv4 and IPv6. For the sake of "not change
++ * code unrelated to IPv4" this is left for later cleanup, for now.
++ */
++void
++mroute_helper_add_iroute6 (struct mroute_helper *mh,
++ const struct iroute_ipv6 *ir6)
++{
++ if (ir6->netbits >= 0)
++ {
++ ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
++ ++mh->cache_generation;
++ ++mh->net_len_refcount[ir6->netbits];
++ if (mh->net_len_refcount[ir6->netbits] == 1)
++ mroute_helper_regenerate (mh);
++ }
++}
++
++void
++mroute_helper_del_iroute6 (struct mroute_helper *mh,
++ const struct iroute_ipv6 *ir6)
++{
++ if (ir6->netbits >= 0)
++ {
++ ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
++ ++mh->cache_generation;
++ --mh->net_len_refcount[ir6->netbits];
++ ASSERT (mh->net_len_refcount[ir6->netbits] >= 0);
++ if (!mh->net_len_refcount[ir6->netbits])
++ mroute_helper_regenerate (mh);
++ }
++}
++
+ void
+ mroute_helper_free (struct mroute_helper *mh)
+ {
+diff --git openvpn-2.2.0/mroute.h openvpn-2.2-ipv6-20110522-1/mroute.h
+index 7265001..b72b5ff 100644
+--- openvpn-2.2.0/mroute.h
++++ openvpn-2.2-ipv6-20110522-1/mroute.h
+@@ -85,7 +85,7 @@ struct mroute_addr {
+ /*
+ * Number of bits in an address. Should be raised for IPv6.
+ */
+-#define MR_HELPER_NET_LEN 32
++#define MR_HELPER_NET_LEN 129
+
+ /*
+ * Used to help maintain CIDR routing table.
+@@ -127,6 +127,8 @@ struct mroute_helper *mroute_helper_init (int ageable_ttl_secs);
+ void mroute_helper_free (struct mroute_helper *mh);
+ void mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir);
+ void mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir);
++void mroute_helper_add_iroute6 (struct mroute_helper *mh, const struct iroute_ipv6 *ir6);
++void mroute_helper_del_iroute6 (struct mroute_helper *mh, const struct iroute_ipv6 *ir6);
+
+ /*
+ * Given a raw packet in buf, return the src and dest
+diff --git openvpn-2.2.0/multi.c openvpn-2.2-ipv6-20110522-1/multi.c
+index 22c0a3f..f703b8d 100644
+--- openvpn-2.2.0/multi.c
++++ openvpn-2.2-ipv6-20110522-1/multi.c
+@@ -316,25 +316,18 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa
+ */
+ if (t->options.ifconfig_pool_defined)
+ {
+- if (dev == DEV_TYPE_TAP)
+- {
+- m->ifconfig_pool = ifconfig_pool_init (IFCONFIG_POOL_INDIV,
+- t->options.ifconfig_pool_start,
+- t->options.ifconfig_pool_end,
+- t->options.duplicate_cn);
+- }
+- else if (dev == DEV_TYPE_TUN)
+- {
+- m->ifconfig_pool = ifconfig_pool_init (
+- (t->options.topology == TOP_NET30) ? IFCONFIG_POOL_30NET : IFCONFIG_POOL_INDIV,
+- t->options.ifconfig_pool_start,
+- t->options.ifconfig_pool_end,
+- t->options.duplicate_cn);
+- }
+- else
+- {
+- ASSERT (0);
+- }
++ int pool_type = IFCONFIG_POOL_INDIV;
++
++ if ( dev == DEV_TYPE_TUN && t->options.topology == TOP_NET30 )
++ pool_type = IFCONFIG_POOL_30NET;
++
++ m->ifconfig_pool = ifconfig_pool_init (pool_type,
++ t->options.ifconfig_pool_start,
++ t->options.ifconfig_pool_end,
++ t->options.duplicate_cn,
++ t->options.ifconfig_ipv6_pool_defined,
++ t->options.ifconfig_ipv6_pool_base,
++ t->options.ifconfig_ipv6_pool_netbits );
+
+ /* reload pool data from file */
+ if (t->c1.ifconfig_pool_persist)
+@@ -429,10 +422,14 @@ multi_del_iroutes (struct multi_context *m,
+ struct multi_instance *mi)
+ {
+ const struct iroute *ir;
++ const struct iroute_ipv6 *ir6;
+ if (TUNNEL_TYPE (mi->context.c1.tuntap) == DEV_TYPE_TUN)
+ {
+ for (ir = mi->context.options.iroutes; ir != NULL; ir = ir->next)
+ mroute_helper_del_iroute (m->route_helper, ir);
++
++ for ( ir6 = mi->context.options.iroutes_ipv6; ir6 != NULL; ir6 = ir6->next )
++ mroute_helper_del_iroute6 (m->route_helper, ir6);
+ }
+ }
+
+@@ -1078,6 +1075,37 @@ multi_learn_in_addr_t (struct multi_context *m,
+ }
+ }
+
++static struct multi_instance *
++multi_learn_in6_addr (struct multi_context *m,
++ struct multi_instance *mi,
++ struct in6_addr a6,
++ int netbits, /* -1 if host route, otherwise # of network bits in address */
++ bool primary)
++{
++ struct mroute_addr addr;
++
++ addr.len = 16;
++ addr.type = MR_ADDR_IPV6;
++ addr.netbits = 0;
++ memcpy( &addr.addr, &a6, sizeof(a6) );
++
++ if (netbits >= 0)
++ {
++ addr.type |= MR_WITH_NETBITS;
++ addr.netbits = (uint8_t) netbits;
++ mroute_addr_mask_host_bits( &addr );
++ }
++
++ {
++ struct multi_instance *owner = multi_learn_addr (m, mi, &addr, 0);
++#ifdef MANAGEMENT_DEF_AUTH
++ if (management && owner)
++ management_learn_addr (management, &mi->context.c2.mda_context, &addr, primary);
++#endif
++ return owner;
++ }
++}
++
+ /*
+ * A new client has connected, add routes (server -> client)
+ * to internal routing table.
+@@ -1088,6 +1116,7 @@ multi_add_iroutes (struct multi_context *m,
+ {
+ struct gc_arena gc = gc_new ();
+ const struct iroute *ir;
++ const struct iroute_ipv6 *ir6;
+ if (TUNNEL_TYPE (mi->context.c1.tuntap) == DEV_TYPE_TUN)
+ {
+ mi->did_iroutes = true;
+@@ -1107,6 +1136,22 @@ multi_add_iroutes (struct multi_context *m,
+
+ multi_learn_in_addr_t (m, mi, ir->network, ir->netbits, false);
+ }
++ for ( ir6 = mi->context.options.iroutes_ipv6; ir6 != NULL; ir6 = ir6->next )
++ {
++ if (ir6->netbits >= 0)
++ msg (D_MULTI_LOW, "MULTI: internal route %s/%d -> %s",
++ print_in6_addr (ir6->network, 0, &gc),
++ ir6->netbits,
++ multi_instance_string (mi, false, &gc));
++ else
++ msg (D_MULTI_LOW, "MULTI: internal route %s -> %s",
++ print_in6_addr (ir6->network, 0, &gc),
++ multi_instance_string (mi, false, &gc));
++
++ mroute_helper_add_iroute6 (m->route_helper, ir6);
++
++ multi_learn_in6_addr (m, mi, ir6->network, ir6->netbits, false);
++ }
+ }
+ gc_free (&gc);
+ }
+@@ -1192,21 +1237,37 @@ multi_select_virtual_addr (struct multi_context *m, struct multi_instance *mi)
+ mi->context.c2.push_ifconfig_defined = true;
+ mi->context.c2.push_ifconfig_local = mi->context.options.push_ifconfig_local;
+ mi->context.c2.push_ifconfig_remote_netmask = mi->context.options.push_ifconfig_remote_netmask;
++
++ /* the current implementation does not allow "static IPv4, pool IPv6",
++ * (see below) so issue a warning if that happens - don't break the
++ * session, though, as we don't even know if this client WANTS IPv6
++ */
++ if ( mi->context.c1.tuntap->ipv6 &&
++ mi->context.options.ifconfig_ipv6_pool_defined &&
++ ! mi->context.options.push_ifconfig_ipv6_defined )
++ {
++ msg( M_INFO, "MULTI_sva: WARNING: if --ifconfig-push is used for IPv4, automatic IPv6 assignment from --ifconfig-ipv6-pool does not work. Use --ifconfig-ipv6-push for IPv6 then." );
++ }
+ }
+ else if (m->ifconfig_pool && mi->vaddr_handle < 0) /* otherwise, choose a pool address */
+ {
+ in_addr_t local=0, remote=0;
++ struct in6_addr remote_ipv6;
+ const char *cn = NULL;
+
+ if (!mi->context.options.duplicate_cn)
+ cn = tls_common_name (mi->context.c2.tls_multi, true);
+
+- mi->vaddr_handle = ifconfig_pool_acquire (m->ifconfig_pool, &local, &remote, cn);
++ mi->vaddr_handle = ifconfig_pool_acquire (m->ifconfig_pool, &local, &remote, &remote_ipv6, cn);
+ if (mi->vaddr_handle >= 0)
+ {
+ const int tunnel_type = TUNNEL_TYPE (mi->context.c1.tuntap);
+ const int tunnel_topology = TUNNEL_TOPOLOGY (mi->context.c1.tuntap);
+
++ msg( M_INFO, "MULTI_sva: pool returned IPv4=%s, IPv6=%s",
++ print_in_addr_t( remote, 0, &gc ),
++ print_in6_addr( remote_ipv6, 0, &gc ) );
++
+ /* set push_ifconfig_remote_netmask from pool ifconfig address(es) */
+ mi->context.c2.push_ifconfig_local = remote;
+ if (tunnel_type == DEV_TYPE_TAP || (tunnel_type == DEV_TYPE_TUN && tunnel_topology == TOP_SUBNET))
+@@ -1228,12 +1289,46 @@ multi_select_virtual_addr (struct multi_context *m, struct multi_instance *mi)
+ else
+ msg (D_MULTI_ERRORS, "MULTI: no --ifconfig-pool netmask parameter is available to push to %s",
+ multi_instance_string (mi, false, &gc));
++
++ if ( mi->context.options.ifconfig_ipv6_pool_defined )
++ {
++ mi->context.c2.push_ifconfig_ipv6_local = remote_ipv6;
++ mi->context.c2.push_ifconfig_ipv6_remote =
++ mi->context.c1.tuntap->local_ipv6;
++ mi->context.c2.push_ifconfig_ipv6_netbits =
++ mi->context.options.ifconfig_ipv6_pool_netbits;
++ mi->context.c2.push_ifconfig_ipv6_defined = true;
++ }
+ }
+ else
+ {
+ msg (D_MULTI_ERRORS, "MULTI: no free --ifconfig-pool addresses are available");
+ }
+ }
++
++ /* IPv6 push_ifconfig is a bit problematic - since IPv6 shares the
++ * pool handling with IPv4, the combination "static IPv4, dynamic IPv6"
++ * will fail (because no pool will be allocated in this case).
++ * OTOH, this doesn't make too much sense in reality - and the other
++ * way round ("dynamic IPv4, static IPv6") or "both static" makes sense
++ * -> and so it's implemented right now
++ */
++ if ( mi->context.c1.tuntap->ipv6 &&
++ mi->context.options.push_ifconfig_ipv6_defined )
++ {
++ mi->context.c2.push_ifconfig_ipv6_local =
++ mi->context.options.push_ifconfig_ipv6_local;
++ mi->context.c2.push_ifconfig_ipv6_remote =
++ mi->context.options.push_ifconfig_ipv6_remote;
++ mi->context.c2.push_ifconfig_ipv6_netbits =
++ mi->context.options.push_ifconfig_ipv6_netbits;
++ mi->context.c2.push_ifconfig_ipv6_defined = true;
++
++ msg( M_INFO, "MULTI_sva: push_ifconfig_ipv6 %s/%d",
++ print_in6_addr( mi->context.c2.push_ifconfig_ipv6_local, 0, &gc ),
++ mi->context.c2.push_ifconfig_ipv6_netbits );
++ }
++
+ gc_free (&gc);
+ }
+
+@@ -1272,6 +1367,11 @@ multi_set_virtual_addr_env (struct multi_context *m, struct multi_instance *mi)
+ SA_SET_IF_NONZERO);
+ }
+ }
++
++ /* TODO: I'm not exactly sure what these environment variables are
++ * used for, but if we have them for IPv4, we should also have
++ * them for IPv6, no?
++ */
+ }
+
+ /*
+@@ -1661,6 +1761,15 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
+ print_in_addr_t (mi->context.c2.push_ifconfig_local, 0, &gc));
+ }
+
++ if (mi->context.c2.push_ifconfig_ipv6_defined)
++ {
++ multi_learn_in6_addr (m, mi, mi->context.c2.push_ifconfig_ipv6_local, -1, true);
++ /* TODO: find out where addresses are "unlearned"!! */
++ msg (D_MULTI_LOW, "MULTI: primary virtual IPv6 for %s: %s",
++ multi_instance_string (mi, false, &gc),
++ print_in6_addr (mi->context.c2.push_ifconfig_ipv6_local, 0, &gc));
++ }
++
+ /* add routes locally, pointing to new client, if
+ --iroute options have been specified */
+ multi_add_iroutes (m, mi);
+diff --git openvpn-2.2.0/openvpn.8 openvpn-2.2-ipv6-20110522-1/openvpn.8
+index 7d213f9..11fd5ad 100644
+--- openvpn-2.2.0/openvpn.8
++++ openvpn-2.2-ipv6-20110522-1/openvpn.8
+@@ -789,6 +789,8 @@ or
+ .B \-\-dev tunX.
+ A warning will be displayed
+ if no specific IPv6 TUN support for your OS has been compiled into OpenVPN.
++
++See below for further IPv6-related configuration options.
+ .\"*********************************************************
+ .TP
+ .B \-\-dev-node node
+@@ -4936,6 +4938,57 @@ if certificates are stored as private objects.
+ .B \-\-verb
+ option can be used BEFORE this option to produce debugging information.
+ .\"*********************************************************
++.SS IPv6 Related Options
++.\"*********************************************************
++The following options exist to support IPv6 tunneling in peer-to-peer
++and client-server mode. As of now, this is just very basic
++documentation of the IPv6-related options. More documentation can be
++found on http://www.greenie.net/ipv6/openvpn.html.
++.TP
++.B --ifconfig-ipv6 ipv6addr/bits ipv6remote
++configure IPv6 address
++.B ipv6addr/bits
++on the ``tun'' device. The second parameter is used as route target for
++.B --route-ipv6
++if no gateway is specified.
++.TP
++.B --route-ipv6 ipv6addr/bits [gateway] [metric]
++setup IPv6 routing in the system to send the specified IPv6 network
++into OpenVPN's ``tun'' device
++.TP
++.B --server-ipv6 ipv6addr/bits
++convenience-function to enable a number of IPv6 related options at
++once, namely
++.B --ifconfig-ipv6, --ifconfig-ipv6-pool, --tun-ipv6
++and
++.B --push tun-ipv6
++Is only accepted if ``--mode server'' or ``--server'' is set.
++.TP
++.B --ifconfig-ipv6-pool ipv6addr/bits
++Specify an IPv6 address pool for dynamic assignment to clients. The
++pool starts at
++.B ipv6addr
++and increments by +1 for every new client (linear mode). The
++.B /bits
++setting controls the size of the pool.
++.TP
++.B --ifconfig-ipv6-push ipv6addr/bits ipv6remote
++for ccd/ per-client static IPv6 interface configuration, see
++.B --client-config-dir
++and
++.B --ifconfig-push
++for more details.
++.TP
++.B --iroute-ipv6 ipv6addr/bits
++for ccd/ per-client static IPv6 route configuration, see
++.B --iroute
++for more details how to setup and use this, and how
++.B --iroute
++and
++.B --route
++interact.
++
++.\"*********************************************************
+ .SH SCRIPTING AND ENVIRONMENTAL VARIABLES
+ OpenVPN exports a series
+ of environmental variables for use by user-defined scripts.
+diff --git openvpn-2.2.0/openvpn.h openvpn-2.2-ipv6-20110522-1/openvpn.h
+index 641bf93..e5e6e58 100644
+--- openvpn-2.2.0/openvpn.h
++++ openvpn-2.2-ipv6-20110522-1/openvpn.h
+@@ -165,6 +165,9 @@ struct context_1
+ /* list of --route directives */
+ struct route_list *route_list;
+
++ /* list of --route-ipv6 directives */
++ struct route_ipv6_list *route_ipv6_list;
++
+ /* --status file */
+ struct status_output *status_output;
+ bool status_output_owned;
+@@ -417,6 +420,11 @@ struct context_2
+ in_addr_t push_ifconfig_local;
+ in_addr_t push_ifconfig_remote_netmask;
+
++ bool push_ifconfig_ipv6_defined;
++ struct in6_addr push_ifconfig_ipv6_local;
++ int push_ifconfig_ipv6_netbits;
++ struct in6_addr push_ifconfig_ipv6_remote;
++
+ /* client authentication state, CAS_SUCCEEDED must be 0 */
+ # define CAS_SUCCEEDED 0
+ # define CAS_PENDING 1
+diff --git openvpn-2.2.0/options.c openvpn-2.2-ipv6-20110522-1/options.c
+index 7708995..bf59e00 100644
+--- openvpn-2.2.0/options.c
++++ openvpn-2.2-ipv6-20110522-1/options.c
+@@ -79,6 +79,7 @@ const char title_string[] =
+ #ifdef ENABLE_EUREPHIA
+ " [eurephia]"
+ #endif
++ " [IPv6 payload 20110522-1 (2.2.0)]"
+ " built on " __DATE__
+ ;
+
+@@ -171,6 +172,8 @@ static const char usage_message[] =
+ " addresses outside of the subnets used by either peer.\n"
+ " TAP: configure device to use IP address l as a local\n"
+ " endpoint and rn as a subnet mask.\n"
++ "--ifconfig-ipv6 l r : configure device to use IPv6 address l as local\n"
++ " endpoint (as a /64) and r as remote endpoint\n"
+ "--ifconfig-noexec : Don't actually execute ifconfig/netsh command, instead\n"
+ " pass --ifconfig parms by environment to scripts.\n"
+ "--ifconfig-nowarn : Don't warn if the --ifconfig option on this side of the\n"
+@@ -181,6 +184,10 @@ static const char usage_message[] =
+ " netmask default: 255.255.255.255\n"
+ " gateway default: taken from --route-gateway or --ifconfig\n"
+ " Specify default by leaving blank or setting to \"nil\".\n"
++ "--route-ipv6 network/bits [gateway] [metric] :\n"
++ " Add IPv6 route to routing table after connection\n"
++ " is established. Multiple routes can be specified.\n"
++ " gateway default: taken from --route-ipv6-gateway or --ifconfig\n"
+ "--max-routes n : Specify the maximum number of routes that may be defined\n"
+ " or pulled from a server.\n"
+ "--route-gateway gw|'dhcp' : Specify a default gateway for use with --route.\n"
+@@ -369,6 +376,7 @@ static const char usage_message[] =
+ "\n"
+ "Multi-Client Server options (when --mode server is used):\n"
+ "--server network netmask : Helper option to easily configure server mode.\n"
++ "--server-ipv6 network/bits : Configure IPv6 server mode.\n"
+ "--server-bridge [IP netmask pool-start-IP pool-end-IP] : Helper option to\n"
+ " easily configure ethernet bridging server mode.\n"
+ "--push \"option\" : Push a config file option back to the peer for remote\n"
+@@ -382,10 +390,16 @@ static const char usage_message[] =
+ "--ifconfig-pool-persist file [seconds] : Persist/unpersist ifconfig-pool\n"
+ " data to file, at seconds intervals (default=600).\n"
+ " If seconds=0, file will be treated as read-only.\n"
++ "--ifconfig-ipv6-pool base-IP/bits : set aside an IPv6 network block\n"
++ " to be dynamically allocated to connecting clients.\n"
+ "--ifconfig-push local remote-netmask : Push an ifconfig option to remote,\n"
+ " overrides --ifconfig-pool dynamic allocation.\n"
+ " Only valid in a client-specific config file.\n"
++ "--ifconfig-ipv6-push local/bits remote : Push an ifconfig-ipv6 option to\n"
++ " remote, overrides --ifconfig-ipv6-pool allocation.\n"
++ " Only valid in a client-specific config file.\n"
+ "--iroute network [netmask] : Route subnet to client.\n"
++ "--iroute-ipv6 network/bits : Route IPv6 subnet to client.\n"
+ " Sets up internal routes only.\n"
+ " Only valid in a client-specific config file.\n"
+ "--disable : Client is disabled.\n"
+@@ -870,6 +884,78 @@ get_ip_addr (const char *ip_string, int msglevel, bool *error)
+ return ret;
+ }
+
++/* helper: parse a text string containing an IPv6 address + netbits
++ * in "standard format" (2001:dba::/32)
++ * "/nn" is optional, default to /64 if missing
++ *
++ * return true if parsing succeeded, modify *network and *netbits
++ * return address part without "/nn" in *printable_ipv6 (if != NULL)
++ */
++bool
++get_ipv6_addr( const char * prefix_str, struct in6_addr *network,
++ unsigned int * netbits, char ** printable_ipv6, int msglevel )
++{
++ int rc;
++ char * sep, * endp;
++ int bits;
++ struct in6_addr t_network;
++
++ sep = strchr( prefix_str, '/' );
++ if ( sep == NULL )
++ {
++ bits = 64;
++ }
++ else
++ {
++ bits = strtol( sep+1, &endp, 10 );
++ if ( *endp != '\0' || bits < 0 || bits > 128 )
++ {
++ msg (msglevel, "IPv6 prefix '%s': invalid '/bits' spec", prefix_str);
++ return false;
++ }
++ }
++
++ /* temporary replace '/' in caller-provided string with '\0', otherwise
++ * inet_pton() will refuse prefix string
++ * (alternative would be to strncpy() the prefix to temporary buffer)
++ */
++
++ if ( sep != NULL ) *sep = '\0';
++
++ rc = inet_pton( AF_INET6, prefix_str, &t_network );
++
++ if ( rc == 1 && printable_ipv6 != NULL )
++ {
++ *printable_ipv6 = string_alloc( prefix_str, NULL );
++ }
++
++ if ( sep != NULL ) *sep = '/';
++
++ if ( rc != 1 )
++ {
++ msg (msglevel, "IPv6 prefix '%s': invalid IPv6 address", prefix_str);
++ return false;
++ }
++
++ if ( netbits != NULL )
++ {
++ *netbits = bits;
++ }
++ if ( network != NULL )
++ {
++ *network = t_network;
++ }
++ return true; /* parsing OK, values set */
++}
++
++static bool ipv6_addr_safe_hexplusbits( const char * ipv6_prefix_spec )
++{
++ struct in6_addr t_addr;
++ unsigned int t_bits;
++
++ return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, NULL, M_WARN );
++}
++
+ static char *
+ string_substitute (const char *src, int from, int to, struct gc_arena *gc)
+ {
+@@ -988,6 +1074,8 @@ show_p2mp_parms (const struct options *o)
+ #if P2MP_SERVER
+ msg (D_SHOW_PARMS, " server_network = %s", print_in_addr_t (o->server_network, 0, &gc));
+ msg (D_SHOW_PARMS, " server_netmask = %s", print_in_addr_t (o->server_netmask, 0, &gc));
++ msg (D_SHOW_PARMS, " server_network_ipv6 = %s", print_in6_addr (o->server_network_ipv6, 0, &gc) );
++ SHOW_INT (server_netbits_ipv6);
+ msg (D_SHOW_PARMS, " server_bridge_ip = %s", print_in_addr_t (o->server_bridge_ip, 0, &gc));
+ msg (D_SHOW_PARMS, " server_bridge_netmask = %s", print_in_addr_t (o->server_bridge_netmask, 0, &gc));
+ msg (D_SHOW_PARMS, " server_bridge_pool_start = %s", print_in_addr_t (o->server_bridge_pool_start, 0, &gc));
+@@ -1008,6 +1096,9 @@ show_p2mp_parms (const struct options *o)
+ msg (D_SHOW_PARMS, " ifconfig_pool_netmask = %s", print_in_addr_t (o->ifconfig_pool_netmask, 0, &gc));
+ SHOW_STR (ifconfig_pool_persist_filename);
+ SHOW_INT (ifconfig_pool_persist_refresh_freq);
++ SHOW_BOOL (ifconfig_ipv6_pool_defined);
++ msg (D_SHOW_PARMS, " ifconfig_ipv6_pool_base = %s", print_in6_addr (o->ifconfig_ipv6_pool_base, 0, &gc));
++ SHOW_INT (ifconfig_ipv6_pool_netbits);
+ SHOW_INT (n_bcast_buf);
+ SHOW_INT (tcp_queue_limit);
+ SHOW_INT (real_hash_size);
+@@ -1021,6 +1112,9 @@ show_p2mp_parms (const struct options *o)
+ SHOW_BOOL (push_ifconfig_defined);
+ msg (D_SHOW_PARMS, " push_ifconfig_local = %s", print_in_addr_t (o->push_ifconfig_local, 0, &gc));
+ msg (D_SHOW_PARMS, " push_ifconfig_remote_netmask = %s", print_in_addr_t (o->push_ifconfig_remote_netmask, 0, &gc));
++ SHOW_BOOL (push_ifconfig_ipv6_defined);
++ msg (D_SHOW_PARMS, " push_ifconfig_ipv6_local = %s/%d", print_in6_addr (o->push_ifconfig_ipv6_local, 0, &gc), o->push_ifconfig_ipv6_netbits );
++ msg (D_SHOW_PARMS, " push_ifconfig_ipv6_remote = %s", print_in6_addr (o->push_ifconfig_ipv6_remote, 0, &gc));
+ SHOW_BOOL (enable_c2c);
+ SHOW_BOOL (duplicate_cn);
+ SHOW_INT (cf_max);
+@@ -1075,6 +1169,25 @@ option_iroute (struct options *o,
+ o->iroutes = ir;
+ }
+
++static void
++option_iroute_ipv6 (struct options *o,
++ const char *prefix_str,
++ int msglevel)
++{
++ struct iroute_ipv6 *ir;
++
++ ALLOC_OBJ_GC (ir, struct iroute_ipv6, &o->gc);
++
++ if ( get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, NULL, msglevel ) < 0 )
++ {
++ msg (msglevel, "in --iroute-ipv6 %s: Bad IPv6 prefix specification",
++ prefix_str);
++ return;
++ }
++
++ ir->next = o->iroutes_ipv6;
++ o->iroutes_ipv6 = ir;
++}
+ #endif /* P2MP_SERVER */
+ #endif /* P2MP */
+
+@@ -1112,6 +1225,13 @@ rol_check_alloc (struct options *options)
+ options->routes = new_route_option_list (options->max_routes, &options->gc);
+ }
+
++void
++rol6_check_alloc (struct options *options)
++{
++ if (!options->routes_ipv6)
++ options->routes_ipv6 = new_route_ipv6_option_list (options->max_routes, &options->gc);
++}
++
+ #ifdef ENABLE_DEBUG
+ static void
+ show_connection_entry (const struct connection_entry *o)
+@@ -1202,6 +1322,9 @@ show_settings (const struct options *o)
+ SHOW_STR (ifconfig_remote_netmask);
+ SHOW_BOOL (ifconfig_noexec);
+ SHOW_BOOL (ifconfig_nowarn);
++ SHOW_STR (ifconfig_ipv6_local);
++ SHOW_INT (ifconfig_ipv6_netbits);
++ SHOW_STR (ifconfig_ipv6_remote);
+
+ #ifdef HAVE_GETTIMEOFDAY
+ SHOW_INT (shaper);
+@@ -1862,8 +1985,10 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
+ if (options->connection_list)
+ msg (M_USAGE, "<connection> cannot be used with --mode server");
+ #endif
++#if 0
+ if (options->tun_ipv6)
+ msg (M_USAGE, "--tun-ipv6 cannot be used with --mode server");
++#endif
+ if (options->shaper)
+ msg (M_USAGE, "--shaper cannot be used with --mode server");
+ if (options->inetd)
+@@ -1888,6 +2013,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
+ msg (M_USAGE, "--up-delay cannot be used with --mode server");
+ if (!options->ifconfig_pool_defined && options->ifconfig_pool_persist_filename)
+ msg (M_USAGE, "--ifconfig-pool-persist must be used with --ifconfig-pool");
++ if (options->ifconfig_ipv6_pool_defined && !options->ifconfig_ipv6_local )
++ msg (M_USAGE, "--ifconfig-ipv6-pool needs --ifconfig-ipv6");
++ if (options->ifconfig_ipv6_local && !options->tun_ipv6 )
++ msg (M_INFO, "Warning: --ifconfig-ipv6 without --tun-ipv6 will not do IPv6");
++
+ if (options->auth_user_pass_file)
+ msg (M_USAGE, "--auth-user-pass cannot be used with --mode server (it should be used on the client side only)");
+ if (options->ccd_exclusive && !options->client_config_dir)
+@@ -1919,6 +2049,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
+ */
+ if (options->ifconfig_pool_defined || options->ifconfig_pool_persist_filename)
+ msg (M_USAGE, "--ifconfig-pool/--ifconfig-pool-persist requires --mode server");
++ if (options->ifconfig_ipv6_pool_defined)
++ msg (M_USAGE, "--ifconfig-ipv6-pool requires --mode server");
+ if (options->real_hash_size != defaults.real_hash_size
+ || options->virtual_hash_size != defaults.virtual_hash_size)
+ msg (M_USAGE, "--hash-size requires --mode server");
+@@ -2460,6 +2592,8 @@ options_string (const struct options *o,
+ o->topology,
+ o->ifconfig_local,
+ o->ifconfig_remote_netmask,
++ o->ifconfig_ipv6_local,
++ o->ifconfig_ipv6_remote,
+ (in_addr_t)0,
+ (in_addr_t)0,
+ false,
+@@ -3785,6 +3919,30 @@ add_option (struct options *options,
+ goto err;
+ }
+ }
++ else if (streq (p[0], "ifconfig-ipv6") && p[1] && p[2] )
++ {
++ unsigned int netbits;
++ char * ipv6_local;
++
++ VERIFY_PERMISSION (OPT_P_UP);
++ if ( get_ipv6_addr( p[1], NULL, &netbits, &ipv6_local, msglevel ) &&
++ ipv6_addr_safe( p[2] ) )
++ {
++ if ( netbits < 64 || netbits > 124 )
++ {
++ msg( msglevel, "ifconfig-ipv6: /netbits must be between 64 and 124, not '/%d'", netbits );
++ goto err;
++ }
++ options->ifconfig_ipv6_local = ipv6_local;
++ options->ifconfig_ipv6_netbits = netbits;
++ options->ifconfig_ipv6_remote = p[2];
++ }
++ else
++ {
++ msg (msglevel, "ifconfig-ipv6 parms '%s' and '%s' must be valid addresses", p[1], p[2]);
++ goto err;
++ }
++ }
+ else if (streq (p[0], "ifconfig-noexec"))
+ {
+ VERIFY_PERMISSION (OPT_P_UP);
+@@ -4585,6 +4743,26 @@ add_option (struct options *options,
+ }
+ add_route_to_option_list (options->routes, p[1], p[2], p[3], p[4]);
+ }
++ else if (streq (p[0], "route-ipv6") && p[1])
++ {
++ VERIFY_PERMISSION (OPT_P_ROUTE);
++ rol6_check_alloc (options);
++ if (pull_mode)
++ {
++ if (!ipv6_addr_safe_hexplusbits (p[1]))
++ {
++ msg (msglevel, "route-ipv6 parameter network/IP '%s' must be a valid address", p[1]);
++ goto err;
++ }
++ if (p[2] && !ipv6_addr_safe (p[2]))
++ {
++ msg (msglevel, "route-ipv6 parameter gateway '%s' must be a valid address", p[2]);
++ goto err;
++ }
++ /* p[3] is metric, if present */
++ }
++ add_route_ipv6_to_option_list (options->routes_ipv6, p[1], p[2], p[3]);
++ }
+ else if (streq (p[0], "max-routes") && p[1])
+ {
+ int max_routes;
+@@ -4796,6 +4974,33 @@ add_option (struct options *options,
+ }
+ }
+ }
++ else if (streq (p[0], "server-ipv6") && p[1] )
++ {
++ const int lev = M_WARN;
++ struct in6_addr network;
++ unsigned int netbits = 0;
++
++ VERIFY_PERMISSION (OPT_P_GENERAL);
++ if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev) )
++ {
++ msg (msglevel, "error parsing --server-ipv6 parameter");
++ goto err;
++ }
++ if ( netbits != 64 )
++ {
++ msg( msglevel, "--server-ipv6 settings: only /64 supported right now (not /%d)", netbits );
++ goto err;
++ }
++ options->server_ipv6_defined = true;
++ options->server_network_ipv6 = network;
++ options->server_netbits_ipv6 = netbits;
++
++ if (p[2]) /* no "nopool" options or similar for IPv6 */
++ {
++ msg (msglevel, "error parsing --server-ipv6: %s is not a recognized flag", p[3]);
++ goto err;
++ }
++ }
+ else if (streq (p[0], "server-bridge") && p[1] && p[2] && p[3] && p[4])
+ {
+ const int lev = M_WARN;
+@@ -4880,6 +5085,28 @@ add_option (struct options *options,
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->topology = TOP_P2P;
+ }
++ else if (streq (p[0], "ifconfig-ipv6-pool") && p[1] )
++ {
++ const int lev = M_WARN;
++ struct in6_addr network;
++ unsigned int netbits = 0;
++
++ VERIFY_PERMISSION (OPT_P_GENERAL);
++ if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev ) )
++ {
++ msg (msglevel, "error parsing --ifconfig-ipv6-pool parameters");
++ goto err;
++ }
++ if ( netbits != 64 )
++ {
++ msg( msglevel, "--ifconfig-ipv6-pool settings: only /64 supported right now (not /%d)", netbits );
++ goto err;
++ }
++
++ options->ifconfig_ipv6_pool_defined = true;
++ options->ifconfig_ipv6_pool_base = network;
++ options->ifconfig_ipv6_pool_netbits = netbits;
++ }
+ else if (streq (p[0], "hash-size") && p[1] && p[2])
+ {
+ int real, virtual;
+@@ -5075,6 +5302,11 @@ add_option (struct options *options,
+ }
+ option_iroute (options, p[1], netmask, msglevel);
+ }
++ else if (streq (p[0], "iroute-ipv6") && p[1])
++ {
++ VERIFY_PERMISSION (OPT_P_INSTANCE);
++ option_iroute_ipv6 (options, p[1], msglevel);
++ }
+ else if (streq (p[0], "ifconfig-push") && p[1] && p[2])
+ {
+ in_addr_t local, remote_netmask;
+@@ -5113,6 +5345,43 @@ add_option (struct options *options,
+ goto err;
+ }
+ }
++ else if (streq (p[0], "ifconfig-ipv6-push") && p[1] )
++ {
++ struct in6_addr local, remote;
++ unsigned int netbits;
++
++ VERIFY_PERMISSION (OPT_P_INSTANCE);
++
++ if ( ! get_ipv6_addr( p[1], &local, &netbits, NULL, msglevel ) )
++ {
++ msg (msglevel, "cannot parse --ifconfig-ipv6-push addresses");
++ goto err;
++ }
++
++ if ( p[2] )
++ {
++ if ( !get_ipv6_addr( p[2], &remote, NULL, NULL, msglevel ) )
++ {
++ msg( msglevel, "cannot parse --ifconfig-ipv6-push addresses");
++ goto err;
++ }
++ }
++ else
++ {
++ if ( ! options->ifconfig_ipv6_local ||
++ ! get_ipv6_addr( options->ifconfig_ipv6_local, &remote,
++ NULL, NULL, msglevel ) )
++ {
++ msg( msglevel, "second argument to --ifconfig-ipv6-push missing and no global --ifconfig-ipv6 address set");
++ goto err;
++ }
++ }
++
++ options->push_ifconfig_ipv6_defined = true;
++ options->push_ifconfig_ipv6_local = local;
++ options->push_ifconfig_ipv6_netbits = netbits;
++ options->push_ifconfig_ipv6_remote = remote;
++ }
+ else if (streq (p[0], "disable"))
+ {
+ VERIFY_PERMISSION (OPT_P_INSTANCE);
+diff --git openvpn-2.2.0/options.h openvpn-2.2-ipv6-20110522-1/options.h
+index 7f4c0cd..dd04ee8 100644
+--- openvpn-2.2.0/options.h
++++ openvpn-2.2-ipv6-20110522-1/options.h
+@@ -205,6 +205,9 @@ struct options
+ int topology; /* one of the TOP_x values from proto.h */
+ const char *ifconfig_local;
+ const char *ifconfig_remote_netmask;
++ const char *ifconfig_ipv6_local;
++ int ifconfig_ipv6_netbits;
++ const char *ifconfig_ipv6_remote;
+ bool ifconfig_noexec;
+ bool ifconfig_nowarn;
+ #ifdef HAVE_GETTIMEOFDAY
+@@ -326,6 +329,7 @@ struct options
+ bool route_delay_defined;
+ int max_routes;
+ struct route_option_list *routes;
++ struct route_ipv6_option_list *routes_ipv6; /* IPv6 */
+ bool route_nopull;
+ bool route_gateway_via_dhcp;
+ bool allow_pull_fqdn; /* as a client, allow server to push a FQDN for certain parameters */
+@@ -355,12 +359,17 @@ struct options
+ struct plugin_option_list *plugin_list;
+ #endif
+
++ const char *tmp_dir;
++
+ #if P2MP
+
+ #if P2MP_SERVER
+ bool server_defined;
+ in_addr_t server_network;
+ in_addr_t server_netmask;
++ bool server_ipv6_defined; /* IPv6 */
++ struct in6_addr server_network_ipv6; /* IPv6 */
++ unsigned int server_netbits_ipv6; /* IPv6 */
+
+ # define SF_NOPOOL (1<<0)
+ # define SF_TCP_NODELAY_HELPER (1<<1)
+@@ -382,24 +391,33 @@ struct options
+ in_addr_t ifconfig_pool_netmask;
+ const char *ifconfig_pool_persist_filename;
+ int ifconfig_pool_persist_refresh_freq;
++
++ bool ifconfig_ipv6_pool_defined; /* IPv6 */
++ struct in6_addr ifconfig_ipv6_pool_base; /* IPv6 */
++ int ifconfig_ipv6_pool_netbits; /* IPv6 */
++
+ int real_hash_size;
+ int virtual_hash_size;
+ const char *client_connect_script;
+ const char *client_disconnect_script;
+ const char *learn_address_script;
+- const char *tmp_dir;
+ const char *client_config_dir;
+ bool ccd_exclusive;
+ bool disable;
+ int n_bcast_buf;
+ int tcp_queue_limit;
+ struct iroute *iroutes;
++ struct iroute_ipv6 *iroutes_ipv6; /* IPv6 */
+ bool push_ifconfig_defined;
+ in_addr_t push_ifconfig_local;
+ in_addr_t push_ifconfig_remote_netmask;
+ bool push_ifconfig_constraint_defined;
+ in_addr_t push_ifconfig_constraint_network;
+ in_addr_t push_ifconfig_constraint_netmask;
++ bool push_ifconfig_ipv6_defined; /* IPv6 */
++ struct in6_addr push_ifconfig_ipv6_local; /* IPv6 */
++ int push_ifconfig_ipv6_netbits; /* IPv6 */
++ struct in6_addr push_ifconfig_ipv6_remote; /* IPv6 */
+ bool enable_c2c;
+ bool duplicate_cn;
+ int cf_max;
+@@ -722,6 +740,10 @@ void options_string_import (struct options *options,
+ unsigned int *option_types_found,
+ struct env_set *es);
+
++bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network,
++ unsigned int * netbits, char ** printable_ipv6,
++ int msglevel );
++
+ /*
+ * inline functions
+ */
+diff --git openvpn-2.2.0/pool.c openvpn-2.2-ipv6-20110522-1/pool.c
+index 84333df..60dc520 100644
+--- openvpn-2.2.0/pool.c
++++ openvpn-2.2-ipv6-20110522-1/pool.c
+@@ -132,7 +132,10 @@ ifconfig_pool_verify_range (const int msglevel, const in_addr_t start, const in_
+ }
+
+ struct ifconfig_pool *
+-ifconfig_pool_init (int type, in_addr_t start, in_addr_t end, const bool duplicate_cn)
++ifconfig_pool_init (int type, in_addr_t start, in_addr_t end,
++ const bool duplicate_cn,
++ const bool ipv6_pool, const struct in6_addr ipv6_base,
++ const int ipv6_netbits )
+ {
+ struct gc_arena gc = gc_new ();
+ struct ifconfig_pool *pool = NULL;
+@@ -157,11 +160,31 @@ ifconfig_pool_init (int type, in_addr_t start, in_addr_t end, const bool duplica
+ ASSERT (0);
+ }
+
++ /* IPv6 pools are always "INDIV" type */
++ pool->ipv6 = ipv6_pool;
++
++ if ( pool->ipv6 )
++ {
++ pool->base_ipv6 = ipv6_base;
++ pool->size_ipv6 = ipv6_netbits>96? ( 1<<(128-ipv6_netbits) )
++ : IFCONFIG_POOL_MAX;
++
++ msg( D_IFCONFIG_POOL, "IFCONFIG POOL IPv6: (IPv4) size=%d, size_ipv6=%d, netbits=%d, base_ipv6=%s",
++ pool->size, pool->size_ipv6, ipv6_netbits,
++ print_in6_addr( pool->base_ipv6, 0, &gc ));
++
++ /* the current code is very simple and assumes that the IPv6
++ * pool is at least as big as the IPv4 pool, and we don't need
++ * to do separate math etc. for IPv6
++ */
++ ASSERT( pool->size < pool->size_ipv6 );
++ }
++
+ ALLOC_ARRAY_CLEAR (pool->list, struct ifconfig_pool_entry, pool->size);
+
+- msg (D_IFCONFIG_POOL, "IFCONFIG POOL: base=%s size=%d",
++ msg (D_IFCONFIG_POOL, "IFCONFIG POOL: base=%s size=%d, ipv6=%d",
+ print_in_addr_t (pool->base, 0, &gc),
+- pool->size);
++ pool->size, pool->ipv6 );
+
+ gc_free (&gc);
+ return pool;
+@@ -181,7 +204,7 @@ ifconfig_pool_free (struct ifconfig_pool *pool)
+ }
+
+ ifconfig_pool_handle
+-ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, const char *common_name)
++ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, struct in6_addr *remote_ipv6, const char *common_name)
+ {
+ int i;
+
+@@ -214,6 +237,12 @@ ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *
+ default:
+ ASSERT (0);
+ }
++
++ /* IPv6 pools are always INDIV (--linear) */
++ if ( pool->ipv6 && remote_ipv6 )
++ {
++ *remote_ipv6 = add_in6_addr( pool->base_ipv6, i );
++ }
+ }
+ return i;
+ }
+@@ -288,6 +317,19 @@ ifconfig_pool_handle_to_ip_base (const struct ifconfig_pool* pool, ifconfig_pool
+ return ret;
+ }
+
++static struct in6_addr
++ifconfig_pool_handle_to_ipv6_base (const struct ifconfig_pool* pool, ifconfig_pool_handle hand)
++{
++ struct in6_addr ret = in6addr_any;
++
++ /* IPv6 pools are always INDIV (--linear) */
++ if (hand >= 0 && hand < pool->size_ipv6 )
++ {
++ ret = add_in6_addr( pool->base_ipv6, hand );
++ }
++ return ret;
++}
++
+ static void
+ ifconfig_pool_set (struct ifconfig_pool* pool, const char *cn, const in_addr_t addr, const bool fixed)
+ {
+@@ -317,9 +359,20 @@ ifconfig_pool_list (const struct ifconfig_pool* pool, struct status_output *out)
+ if (e->common_name)
+ {
+ const in_addr_t ip = ifconfig_pool_handle_to_ip_base (pool, i);
+- status_printf (out, "%s,%s",
+- e->common_name,
+- print_in_addr_t (ip, 0, &gc));
++ if ( pool->ipv6 )
++ {
++ struct in6_addr ip6 = ifconfig_pool_handle_to_ipv6_base (pool, i);
++ status_printf (out, "%s,%s,%s",
++ e->common_name,
++ print_in_addr_t (ip, 0, &gc),
++ print_in6_addr (ip6, 0, &gc));
++ }
++ else
++ {
++ status_printf (out, "%s,%s",
++ e->common_name,
++ print_in_addr_t (ip, 0, &gc));
++ }
+ }
+ }
+ gc_free (&gc);
+@@ -409,6 +462,9 @@ ifconfig_pool_read (struct ifconfig_pool_persist *persist, struct ifconfig_pool
+ int c = *BSTR(&in);
+ if (c == '#' || c == ';')
+ continue;
++ msg( M_INFO, "ifconfig_pool_read(), in='%s', TODO: IPv6",
++ BSTR(&in) );
++
+ if (buf_parse (&in, ',', cn_buf, buf_size)
+ && buf_parse (&in, ',', ip_buf, buf_size))
+ {
+@@ -416,6 +472,7 @@ ifconfig_pool_read (struct ifconfig_pool_persist *persist, struct ifconfig_pool
+ const in_addr_t addr = getaddr (GETADDR_HOST_ORDER, ip_buf, 0, &succeeded, NULL);
+ if (succeeded)
+ {
++ msg( M_INFO, "succeeded -> ifconfig_pool_set()");
+ ifconfig_pool_set (pool, cn_buf, addr, persist->fixed);
+ }
+ }
+@@ -471,7 +528,7 @@ ifconfig_pool_test (in_addr_t start, in_addr_t end)
+ #else
+ cn = buf;
+ #endif
+- h = ifconfig_pool_acquire (p, &local, &remote, cn);
++ h = ifconfig_pool_acquire (p, &local, &remote, NULL, cn);
+ if (h < 0)
+ break;
+ msg (M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 1: l=%s r=%s cn=%s",
+@@ -506,7 +563,7 @@ ifconfig_pool_test (in_addr_t start, in_addr_t end)
+ #else
+ cn = buf;
+ #endif
+- h = ifconfig_pool_acquire (p, &local, &remote, cn);
++ h = ifconfig_pool_acquire (p, &local, &remote, NULL, cn);
+ if (h < 0)
+ break;
+ msg (M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 3: l=%s r=%s cn=%s",
+diff --git openvpn-2.2.0/pool.h openvpn-2.2-ipv6-20110522-1/pool.h
+index 81264a9..fc9d6ab 100644
+--- openvpn-2.2.0/pool.h
++++ openvpn-2.2-ipv6-20110522-1/pool.h
+@@ -52,6 +52,9 @@ struct ifconfig_pool
+ int size;
+ int type;
+ bool duplicate_cn;
++ bool ipv6;
++ struct in6_addr base_ipv6;
++ unsigned int size_ipv6;
+ struct ifconfig_pool_entry *list;
+ };
+
+@@ -63,13 +66,13 @@ struct ifconfig_pool_persist
+
+ typedef int ifconfig_pool_handle;
+
+-struct ifconfig_pool *ifconfig_pool_init (int type, in_addr_t start, in_addr_t end, const bool duplicate_cn);
++struct ifconfig_pool *ifconfig_pool_init (int type, in_addr_t start, in_addr_t end, const bool duplicate_cn, const bool ipv6_pool, const struct in6_addr ipv6_base, const int ipv6_netbits );
+
+ void ifconfig_pool_free (struct ifconfig_pool *pool);
+
+ bool ifconfig_pool_verify_range (const int msglevel, const in_addr_t start, const in_addr_t end);
+
+-ifconfig_pool_handle ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, const char *common_name);
++ifconfig_pool_handle ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, struct in6_addr *remote_ipv6, const char *common_name);
+
+ bool ifconfig_pool_release (struct ifconfig_pool* pool, ifconfig_pool_handle hand, const bool hard);
+
+diff --git openvpn-2.2.0/proto.h openvpn-2.2-ipv6-20110522-1/proto.h
+index 55f0832..b8e8997 100644
+--- openvpn-2.2.0/proto.h
++++ openvpn-2.2-ipv6-20110522-1/proto.h
+@@ -108,6 +108,21 @@ struct openvpn_iphdr {
+ };
+
+ /*
++ * IPv6 header
++ */
++struct openvpn_ipv6hdr {
++ uint8_t version_prio;
++ uint8_t flow_lbl[3];
++ uint16_t payload_len;
++ uint8_t nexthdr;
++ uint8_t hop_limit;
++
++ struct in6_addr saddr;
++ struct in6_addr daddr;
++};
++
++
++/*
+ * UDP header
+ */
+ struct openvpn_udphdr {
+diff --git openvpn-2.2.0/push.c openvpn-2.2-ipv6-20110522-1/push.c
+index 08c7f99..1fd8bea 100644
+--- openvpn-2.2.0/push.c
++++ openvpn-2.2-ipv6-20110522-1/push.c
+@@ -189,8 +189,26 @@ send_push_reply (struct context *c)
+ const int safe_cap = BCAP (&buf) - extra;
+ bool push_sent = false;
+
++ msg( M_INFO, "send_push_reply(): safe_cap=%d", safe_cap );
++
+ buf_printf (&buf, "%s", cmd);
+
++ if ( c->c2.push_ifconfig_ipv6_defined )
++ {
++ /* IPv6 is put into buffer first, could be lengthy */
++ /* TODO: push "/netbits" as well, to allow non-/64 subnet sizes
++ * (needs changes in options.c, options.h, and other places)
++ */
++ buf_printf( &buf, ",ifconfig-ipv6 %s %s",
++ print_in6_addr( c->c2.push_ifconfig_ipv6_local, 0, &gc),
++ print_in6_addr( c->c2.push_ifconfig_ipv6_remote, 0, &gc) );
++ if (BLEN (&buf) >= safe_cap)
++ {
++ msg (M_WARN, "--push ifconfig-ipv6 option is too long");
++ goto fail;
++ }
++ }
++
+ while (e)
+ {
+ if (e->enable)
+diff --git openvpn-2.2.0/route.c openvpn-2.2-ipv6-20110522-1/route.c
+index b5092fe..7c81f75 100644
+--- openvpn-2.2.0/route.c
++++ openvpn-2.2-ipv6-20110522-1/route.c
+@@ -35,6 +35,7 @@
+ #include "socket.h"
+ #include "manage.h"
+ #include "win32.h"
++#include "options.h"
+
+ #include "memdbg.h"
+
+@@ -68,6 +69,15 @@ new_route_option_list (const int max_routes, struct gc_arena *a)
+ return ret;
+ }
+
++struct route_ipv6_option_list *
++new_route_ipv6_option_list (const int max_routes, struct gc_arena *a)
++{
++ struct route_ipv6_option_list *ret;
++ ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_ipv6_option_list, struct route_ipv6_option, max_routes, a);
++ ret->capacity = max_routes;
++ return ret;
++}
++
+ struct route_option_list *
+ clone_route_option_list (const struct route_option_list *src, struct gc_arena *a)
+ {
+@@ -95,6 +105,15 @@ new_route_list (const int max_routes, struct gc_arena *a)
+ return ret;
+ }
+
++struct route_ipv6_list *
++new_route_ipv6_list (const int max_routes, struct gc_arena *a)
++{
++ struct route_ipv6_list *ret;
++ ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_ipv6_list, struct route_ipv6, max_routes, a);
++ ret->capacity = max_routes;
++ return ret;
++}
++
+ static const char *
+ route_string (const struct route *r, struct gc_arena *gc)
+ {
+@@ -311,6 +330,68 @@ init_route (struct route *r,
+ return false;
+ }
+
++static bool
++init_route_ipv6 (struct route_ipv6 *r6,
++ const struct route_ipv6_option *r6o,
++ const struct route_ipv6_list *rl6 )
++{
++ r6->option = r6o;
++ r6->defined = false;
++
++ if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, NULL, M_WARN ))
++ goto fail;
++
++ /* gateway */
++ if (is_route_parm_defined (r6o->gateway))
++ {
++ if ( inet_pton( AF_INET6, r6o->gateway, &r6->gateway ) != 1 )
++ {
++ msg( M_WARN, PACKAGE_NAME "ROUTE6: cannot parse gateway spec '%s'", r6o->gateway );
++ }
++ }
++ else if (rl6->remote_endpoint_defined)
++ {
++ r6->gateway = rl6->remote_endpoint_ipv6;
++ }
++ else
++ {
++ msg (M_WARN, PACKAGE_NAME " ROUTE6: " PACKAGE_NAME " needs a gateway parameter for a --route-ipv6 option and no default was specified by either --route-ipv6-gateway or --ifconfig-ipv6 options");
++ goto fail;
++ }
++
++ /* metric */
++
++ r6->metric_defined = false;
++ r6->metric = 0;
++ if (is_route_parm_defined (r6o->metric))
++ {
++ r6->metric = atoi (r6o->metric);
++ if (r6->metric < 0)
++ {
++ msg (M_WARN, PACKAGE_NAME " ROUTE: route metric for network %s (%s) must be >= 0",
++ r6o->prefix,
++ r6o->metric);
++ goto fail;
++ }
++ r6->metric_defined = true;
++ }
++ else if (rl6->default_metric_defined)
++ {
++ r6->metric = rl6->default_metric;
++ r6->metric_defined = true;
++ }
++
++ r6->defined = true;
++
++ return true;
++
++ fail:
++ msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve route for host/network: %s",
++ r6o->prefix);
++ r6->defined = false;
++ return false;
++}
++
+ void
+ add_route_to_option_list (struct route_option_list *l,
+ const char *network,
+@@ -331,6 +412,23 @@ add_route_to_option_list (struct route_option_list *l,
+ }
+
+ void
++add_route_ipv6_to_option_list (struct route_ipv6_option_list *l,
++ const char *prefix,
++ const char *gateway,
++ const char *metric)
++{
++ struct route_ipv6_option *ro;
++ if (l->n >= l->capacity)
++ msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d IPv6 routes -- please increase the max-routes option in the client configuration file",
++ l->capacity);
++ ro = &l->routes_ipv6[l->n];
++ ro->prefix = prefix;
++ ro->gateway = gateway;
++ ro->metric = metric;
++ ++l->n;
++}
++
++void
+ clear_route_list (struct route_list *rl)
+ {
+ const int capacity = rl->capacity;
+@@ -340,6 +438,15 @@ clear_route_list (struct route_list *rl)
+ }
+
+ void
++clear_route_ipv6_list (struct route_ipv6_list *rl6)
++{
++ const int capacity = rl6->capacity;
++ const size_t rl6_size = array_mult_safe (sizeof(struct route_ipv6), capacity, sizeof(struct route_ipv6_list));
++ memset(rl6, 0, rl6_size);
++ rl6->capacity = capacity;
++}
++
++void
+ route_list_add_default_gateway (struct route_list *rl,
+ struct env_set *es,
+ const in_addr_t addr)
+@@ -469,6 +576,72 @@ init_route_list (struct route_list *rl,
+ return ret;
+ }
+
++bool
++init_route_ipv6_list (struct route_ipv6_list *rl6,
++ const struct route_ipv6_option_list *opt6,
++ const char *remote_endpoint,
++ int default_metric,
++ struct env_set *es)
++{
++ struct gc_arena gc = gc_new ();
++ bool ret = true;
++
++ clear_route_ipv6_list (rl6);
++
++ rl6->flags = opt6->flags;
++
++ if (default_metric)
++ {
++ rl6->default_metric = default_metric;
++ rl6->default_metric_defined = true;
++ }
++
++ /* "default_gateway" is stuff for "redirect-gateway", which we don't
++ * do for IPv6 yet -> TODO
++ */
++ {
++ dmsg (D_ROUTE, "ROUTE6: default_gateway=UNDEF");
++ }
++
++ if ( is_route_parm_defined( remote_endpoint ))
++ {
++ if ( inet_pton( AF_INET6, remote_endpoint,
++ &rl6->remote_endpoint_ipv6) == 1 )
++ {
++ rl6->remote_endpoint_defined = true;
++ }
++ else
++ {
++ msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve default gateway: %s", remote_endpoint);
++ ret = false;
++ }
++ }
++ else
++ rl6->remote_endpoint_defined = false;
++
++
++ if (!(opt6->n >= 0 && opt6->n <= rl6->capacity))
++ msg (M_FATAL, PACKAGE_NAME " ROUTE6: (init) number of route options (%d) is greater than route list capacity (%d)", opt6->n, rl6->capacity);
++
++ /* parse the routes from opt to rl6 */
++ {
++ int i, j = 0;
++ for (i = 0; i < opt6->n; ++i)
++ {
++ if (!init_route_ipv6 (&rl6->routes_ipv6[j],
++ &opt6->routes_ipv6[i],
++ rl6 ))
++ ret = false;
++ else
++ ++j;
++ }
++ rl6->n = j;
++ }
++
++ gc_free (&gc);
++ return ret;
++}
++
+ static void
+ add_route3 (in_addr_t network,
+ in_addr_t netmask,
+@@ -704,10 +877,13 @@ undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *
+ }
+
+ void
+-add_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
++add_routes (struct route_list *rl, struct route_ipv6_list *rl6,
++ const struct tuntap *tt, unsigned int flags, const struct env_set *es)
+ {
+- redirect_default_route_to_vpn (rl, tt, flags, es);
+- if (!rl->routes_added)
++ if (rl)
++ redirect_default_route_to_vpn (rl, tt, flags, es);
++
++ if (rl && !rl->routes_added)
+ {
+ int i;
+
+@@ -732,12 +908,27 @@ add_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flags,
+ }
+ rl->routes_added = true;
+ }
++
++ if (rl6 && !rl6->routes_added)
++ {
++ int i;
++
++ for (i = 0; i < rl6->n; ++i)
++ {
++ struct route_ipv6 *r = &rl6->routes_ipv6[i];
++ if (flags & ROUTE_DELETE_FIRST)
++ delete_route_ipv6 (r, tt, flags, es);
++ add_route_ipv6 (r, tt, flags, es);
++ }
++ rl6->routes_added = true;
++ }
+ }
+
+ void
+-delete_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
++delete_routes (struct route_list *rl, struct route_ipv6_list *rl6,
++ const struct tuntap *tt, unsigned int flags, const struct env_set *es)
+ {
+- if (rl->routes_added)
++ if (rl && rl->routes_added)
+ {
+ int i;
+ for (i = rl->n - 1; i >= 0; --i)
+@@ -747,9 +938,28 @@ delete_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flag
+ }
+ rl->routes_added = false;
+ }
+- undo_redirect_default_route_to_vpn (rl, tt, flags, es);
+
+- clear_route_list (rl);
++ if ( rl )
++ {
++ undo_redirect_default_route_to_vpn (rl, tt, flags, es);
++ clear_route_list (rl);
++ }
++
++ if ( rl6 && rl6->routes_added )
++ {
++ int i;
++ for (i = rl6->n - 1; i >= 0; --i)
++ {
++ const struct route_ipv6 *r6 = &rl6->routes_ipv6[i];
++ delete_route_ipv6 (r6, tt, flags, es);
++ }
++ rl6->routes_added = false;
++ }
++
++ if ( rl6 )
++ {
++ clear_route_ipv6_list (rl6);
++ }
+ }
+
+ #ifdef ENABLE_DEBUG
+@@ -832,6 +1042,34 @@ setenv_routes (struct env_set *es, const struct route_list *rl)
+ setenv_route (es, &rl->routes[i], i + 1);
+ }
+
++static void
++setenv_route_ipv6 (struct env_set *es, const struct route_ipv6 *r6, int i)
++{
++ struct gc_arena gc = gc_new ();
++ if (r6->defined)
++ {
++ struct buffer name1 = alloc_buf_gc( 256, &gc );
++ struct buffer val = alloc_buf_gc( 256, &gc );
++ struct buffer name2 = alloc_buf_gc( 256, &gc );
++
++ buf_printf( &name1, "route_ipv6_network_%d", i );
++ buf_printf( &val, "%s/%d", print_in6_addr( r6->network, 0, &gc ),
++ r6->netbits );
++ setenv_str( es, BSTR(&name1), BSTR(&val) );
++
++ buf_printf( &name2, "route_ipv6_gateway_%d", i );
++ setenv_str( es, BSTR(&name2), print_in6_addr( r6->gateway, 0, &gc ));
++ }
++ gc_free (&gc);
++}
++void
++setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6)
++{
++ int i;
++ for (i = 0; i < rl6->n; ++i)
++ setenv_route_ipv6 (es, &rl6->routes_ipv6[i], i + 1);
++}
++
+ void
+ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
+ {
+@@ -1025,6 +1263,187 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
+ gc_free (&gc);
+ }
+
++
++static const char *
++print_in6_addr_netbits_only( struct in6_addr network_copy, int netbits,
++ struct gc_arena * gc)
++{
++ /* clear host bit parts of route
++ * (needed if routes are specified improperly, or if we need to
++ * explicitely setup/clear the "connected" network routes on some OSes)
++ */
++ int byte = 15;
++ int bits_to_clear = 128 - netbits;
++
++ while( byte >= 0 && bits_to_clear > 0 )
++ {
++ if ( bits_to_clear >= 8 )
++ { network_copy.s6_addr[byte--] = 0; bits_to_clear -= 8; }
++ else
++ { network_copy.s6_addr[byte--] &= (~0 << bits_to_clear); bits_to_clear = 0; }
++ }
++
++ return print_in6_addr( network_copy, 0, gc);
++}
++
++void
++add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
++{
++ struct gc_arena gc;
++ struct argv argv;
++
++ const char *network;
++ const char *gateway;
++ bool status = false;
++ const char *device = tt->actual_name;
++
++ if (!r6->defined)
++ return;
++
++ gc_init (&gc);
++ argv_init (&argv);
++
++ network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
++ gateway = print_in6_addr( r6->gateway, 0, &gc);
++
++ if ( !tt->ipv6 )
++ {
++ msg( M_INFO, "add_route_ipv6(): not adding %s/%d, no IPv6 on if %s",
++ network, r6->netbits, device );
++ return;
++ }
++
++ msg( M_INFO, "add_route_ipv6(%s/%d -> %s metric %d) dev %s",
++ network, r6->netbits, gateway, r6->metric, device );
++
++ /*
++ * Filter out routes which are essentially no-ops
++ * (not currently done for IPv6)
++ */
++
++#if defined(TARGET_LINUX)
++#ifdef CONFIG_FEATURE_IPROUTE
++ argv_printf (&argv, "%s -6 route add %s/%d dev %s",
++ iproute_path,
++ network,
++ r6->netbits,
++ device);
++ if (r6->metric_defined)
++ argv_printf_cat (&argv, " metric %d", r6->metric);
++
++#else
++ argv_printf (&argv, "%s -A inet6 add %s/%d dev %s",
++ ROUTE_PATH,
++ network,
++ r6->netbits,
++ device);
++ if (r6->metric_defined)
++ argv_printf_cat (&argv, " metric %d", r6->metric);
++#endif /*CONFIG_FEATURE_IPROUTE*/
++ argv_msg (D_ROUTE, &argv);
++ status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 add command failed");
++
++#elif defined (WIN32)
++
++ /* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */
++ argv_printf (&argv, "%s%sc interface ipv6 add route %s/%d %s",
++ get_win_sys_path(),
++ NETSH_PATH_SUFFIX,
++ network,
++ r6->netbits,
++ device);
++
++ /* next-hop depends on TUN or TAP mode:
++ * - in TAP mode, we use the "real" next-hop
++ * - in TUN mode we use a special-case link-local address that the tapdrvr
++ * knows about and will answer ND (neighbor discovery) packets for
++ */
++ if ( tt->type == DEV_TYPE_TUN )
++ argv_printf_cat( &argv, " %s", "fe80::8" );
++ else
++ argv_printf_cat( &argv, " %s", gateway );
++
++#if 0
++ if (r->metric_defined)
++ argv_printf_cat (&argv, " METRIC %d", r->metric);
++#endif
++
++ /* in some versions of Windows, routes are persistent across reboots by
++ * default, unless "store=active" is set (pointed out by Tony Lim, thanks)
++ */
++ argv_printf_cat( &argv, " store=active" );
++
++ argv_msg (D_ROUTE, &argv);
++
++ netcmd_semaphore_lock ();
++ status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add ipv6 command failed");
++ netcmd_semaphore_release ();
++
++#elif defined (TARGET_SOLARIS)
++
++ /* example: route add -inet6 2001:db8::/32 somegateway 0 */
++
++ /* for some weird reason, this does not work for me unless I set
++ * "metric 0" - otherwise, the routes will be nicely installed, but
++ * packets will just disappear somewhere. So we use "0" now...
++ */
++
++ argv_printf (&argv, "%s add -inet6 %s/%d %s 0",
++ ROUTE_PATH,
++ network,
++ r6->netbits,
++ gateway );
++
++ argv_msg (D_ROUTE, &argv);
++ status = openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route add -inet6 command failed");
++
++#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
++
++ argv_printf (&argv, "%s add -inet6 %s/%d -iface %s",
++ ROUTE_PATH,
++ network,
++ r6->netbits,
++ device );
++
++ argv_msg (D_ROUTE, &argv);
++ status = openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route add -inet6 command failed");
++
++#elif defined(TARGET_DARWIN)
++
++ argv_printf (&argv, "%s add -inet6 %s -prefixlen %d -iface %s",
++ ROUTE_PATH,
++ network, r6->netbits, device );
++
++ argv_msg (D_ROUTE, &argv);
++ status = openvpn_execve_check (&argv, es, 0, "ERROR: MacOS X route add -inet6 command failed");
++
++#elif defined(TARGET_OPENBSD)
++
++ argv_printf (&argv, "%s add -inet6 %s -prefixlen %d %s",
++ ROUTE_PATH,
++ network, r6->netbits, gateway );
++
++ argv_msg (D_ROUTE, &argv);
++ status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD route add -inet6 command failed");
++
++#elif defined(TARGET_NETBSD)
++
++ argv_printf (&argv, "%s add -inet6 %s/%d %s",
++ ROUTE_PATH,
++ network, r6->netbits, gateway );
++
++ argv_msg (D_ROUTE, &argv);
++ status = openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route add -inet6 command failed");
++
++#else
++ msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on this operating system. Try putting your routes in a --route-up script");
++#endif
++
++ r6->defined = status;
++ argv_reset (&argv);
++ gc_free (&gc);
++}
++
+ static void
+ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
+ {
+@@ -1164,6 +1583,142 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags
+ gc_free (&gc);
+ }
+
++void
++delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
++{
++ struct gc_arena gc;
++ struct argv argv;
++ const char *network;
++ const char *gateway;
++ const char *device = tt->actual_name;
++
++ if (!r6->defined)
++ return;
++
++ gc_init (&gc);
++ argv_init (&argv);
++
++ network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
++ gateway = print_in6_addr( r6->gateway, 0, &gc);
++
++ if ( !tt->ipv6 )
++ {
++ msg( M_INFO, "delete_route_ipv6(): not deleting %s/%d, no IPv6 on if %s",
++ network, r6->netbits, device );
++ return;
++ }
++
++ msg( M_INFO, "delete_route_ipv6(%s/%d)", network, r6->netbits );
++
++#if defined(TARGET_LINUX)
++#ifdef CONFIG_FEATURE_IPROUTE
++ argv_printf (&argv, "%s -6 route del %s/%d dev %s",
++ iproute_path,
++ network,
++ r6->netbits,
++ device);
++#else
++ argv_printf (&argv, "%s -A inet6 del %s/%d dev %s",
++ ROUTE_PATH,
++ network,
++ r6->netbits,
++ device);
++#endif /*CONFIG_FEATURE_IPROUTE*/
++ argv_msg (D_ROUTE, &argv);
++ openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 del command failed");
++
++#elif defined (WIN32)
++
++ /* netsh interface ipv6 delete route 2001:db8::/32 MyTunDevice */
++ argv_printf (&argv, "%s%sc interface ipv6 delete route %s/%d %s",
++ get_win_sys_path(),
++ NETSH_PATH_SUFFIX,
++ network,
++ r6->netbits,
++ device);
++
++ /* next-hop depends on TUN or TAP mode:
++ * - in TAP mode, we use the "real" next-hop
++ * - in TUN mode we use a special-case link-local address that the tapdrvr
++ * knows about and will answer ND (neighbor discovery) packets for
++ * (and "route deletion without specifying next-hop" does not work...)
++ */
++ if ( tt->type == DEV_TYPE_TUN )
++ argv_printf_cat( &argv, " %s", "fe80::8" );
++ else
++ argv_printf_cat( &argv, " %s", gateway );
++
++#if 0
++ if (r->metric_defined)
++ argv_printf_cat (&argv, "METRIC %d", r->metric);
++#endif
++
++ argv_msg (D_ROUTE, &argv);
++
++ netcmd_semaphore_lock ();
++ openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add ipv6 command failed");
++ netcmd_semaphore_release ();
++
++#elif defined (TARGET_SOLARIS)
++
++ /* example: route delete -inet6 2001:db8::/32 somegateway */
++ /* GERT-TODO: this is untested, but should work */
++
++ argv_printf (&argv, "%s delete -inet6 %s/%d %s",
++ ROUTE_PATH,
++ network,
++ r6->netbits,
++ gateway );
++
++ argv_msg (D_ROUTE, &argv);
++ openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route delete -inet6 command failed");
++
++#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
++
++ argv_printf (&argv, "%s delete -inet6 %s/%d -iface %s",
++ ROUTE_PATH,
++ network,
++ r6->netbits,
++ device );
++
++ argv_msg (D_ROUTE, &argv);
++ openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route delete -inet6 command failed");
++
++#elif defined(TARGET_DARWIN)
++
++ argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d -iface %s",
++ ROUTE_PATH,
++ network, r6->netbits, device );
++
++ argv_msg (D_ROUTE, &argv);
++ openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route delete -inet6 command failed");
++
++#elif defined(TARGET_OPENBSD)
++
++ argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d %s",
++ ROUTE_PATH,
++ network, r6->netbits, gateway );
++
++ argv_msg (D_ROUTE, &argv);
++ openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD route delete -inet6 command failed");
++
++#elif defined(TARGET_NETBSD)
++
++ argv_printf (&argv, "%s delete -inet6 %s/%d %s",
++ ROUTE_PATH,
++ network, r6->netbits, gateway );
++
++ argv_msg (D_ROUTE, &argv);
++ openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route delete -inet6 command failed");
++
++#else
++ msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on this operating system. Try putting your routes in a --route-down script");
++#endif
++
++ argv_reset (&argv);
++ gc_free (&gc);
++}
++
+ /*
+ * The --redirect-gateway option requires OS-specific code below
+ * to get the current default gateway.
+diff --git openvpn-2.2.0/route.h openvpn-2.2-ipv6-20110522-1/route.h
+index c5cbb7c..6a7704f 100644
+--- openvpn-2.2.0/route.h
++++ openvpn-2.2-ipv6-20110522-1/route.h
+@@ -92,6 +92,19 @@ struct route_option_list {
+ struct route_option routes[EMPTY_ARRAY_SIZE];
+ };
+
++struct route_ipv6_option {
++ const char *prefix; /* e.g. "2001:db8:1::/64" */
++ const char *gateway; /* e.g. "2001:db8:0::2" */
++ const char *metric; /* e.g. "5" */
++};
++
++struct route_ipv6_option_list {
++ unsigned int flags;
++ int capacity;
++ int n;
++ struct route_ipv6_option routes_ipv6[EMPTY_ARRAY_SIZE];
++};
++
+ struct route {
+ bool defined;
+ const struct route_option *option;
+@@ -113,6 +126,31 @@ struct route_list {
+ struct route routes[EMPTY_ARRAY_SIZE];
+ };
+
++struct route_ipv6 {
++ bool defined;
++ const struct route_ipv6_option *option;
++ struct in6_addr network;
++ unsigned int netbits;
++ struct in6_addr gateway;
++ bool metric_defined;
++ int metric;
++};
++
++struct route_ipv6_list {
++ bool routes_added;
++ unsigned int flags;
++ int default_metric;
++ bool default_metric_defined;
++ struct in6_addr remote_endpoint_ipv6;
++ bool remote_endpoint_defined;
++ bool did_redirect_default_gateway; /* TODO (?) */
++ bool did_local; /* TODO (?) */
++ int capacity;
++ int n;
++ struct route_ipv6 routes_ipv6[EMPTY_ARRAY_SIZE];
++};
++
++
+ #if P2MP
+ /* internal OpenVPN route */
+ struct iroute {
+@@ -120,15 +158,25 @@ struct iroute {
+ int netbits;
+ struct iroute *next;
+ };
++
++struct iroute_ipv6 {
++ struct in6_addr network;
++ unsigned int netbits;
++ struct iroute_ipv6 *next;
++};
+ #endif
+
+ struct route_option_list *new_route_option_list (const int max_routes, struct gc_arena *a);
++struct route_ipv6_option_list *new_route_ipv6_option_list (const int max_routes, struct gc_arena *a);
+ struct route_option_list *clone_route_option_list (const struct route_option_list *src, struct gc_arena *a);
+ void copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src);
+
+ struct route_list *new_route_list (const int max_routes, struct gc_arena *a);
++struct route_ipv6_list *new_route_ipv6_list (const int max_routes, struct gc_arena *a);
+
+ void add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
++void add_route_ipv6 (struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
++void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
+
+ void add_route_to_option_list (struct route_option_list *l,
+ const char *network,
+@@ -136,6 +184,11 @@ void add_route_to_option_list (struct route_option_list *l,
+ const char *gateway,
+ const char *metric);
+
++void add_route_ipv6_to_option_list (struct route_ipv6_option_list *l,
++ const char *prefix,
++ const char *gateway,
++ const char *metric);
++
+ bool init_route_list (struct route_list *rl,
+ const struct route_option_list *opt,
+ const char *remote_endpoint,
+@@ -143,21 +196,30 @@ bool init_route_list (struct route_list *rl,
+ in_addr_t remote_host,
+ struct env_set *es);
+
++bool init_route_ipv6_list (struct route_ipv6_list *rl6,
++ const struct route_ipv6_option_list *opt6,
++ const char *remote_endpoint,
++ int default_metric,
++ struct env_set *es);
++
+ void route_list_add_default_gateway (struct route_list *rl,
+ struct env_set *es,
+ const in_addr_t addr);
+
+ void add_routes (struct route_list *rl,
++ struct route_ipv6_list *rl6,
+ const struct tuntap *tt,
+ unsigned int flags,
+ const struct env_set *es);
+
+ void delete_routes (struct route_list *rl,
++ struct route_ipv6_list *rl6,
+ const struct tuntap *tt,
+ unsigned int flags,
+ const struct env_set *es);
+
+ void setenv_routes (struct env_set *es, const struct route_list *rl);
++void setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6);
+
+ bool is_special_addr (const char *addr_str);
+
+diff --git openvpn-2.2.0/socket.c openvpn-2.2-ipv6-20110522-1/socket.c
+index 4720398..c04edc9 100644
+--- openvpn-2.2.0/socket.c
++++ openvpn-2.2-ipv6-20110522-1/socket.c
+@@ -342,6 +342,24 @@ ip_addr_dotted_quad_safe (const char *dotted_quad)
+ }
+ }
+
++bool
++ipv6_addr_safe (const char *ipv6_text_addr)
++{
++ /* verify non-NULL */
++ if (!ipv6_text_addr)
++ return false;
++
++ /* verify length is within limits */
++ if (strlen (ipv6_text_addr) > INET6_ADDRSTRLEN )
++ return false;
++
++ /* verify that string will convert to IPv6 address */
++ {
++ struct in6_addr a6;
++ return inet_pton( AF_INET6, ipv6_text_addr, &a6 ) == 1;
++ }
++}
++
+ static bool
+ dns_addr_safe (const char *addr)
+ {
+@@ -2032,6 +2050,55 @@ print_in_addr_t (in_addr_t addr, unsigned int flags, struct gc_arena *gc)
+ return BSTR (&out);
+ }
+
++/*
++ * Convert an in6_addr in host byte order
++ * to an ascii representation of an IPv6 address
++ */
++const char *
++print_in6_addr (struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
++{
++ struct buffer out = alloc_buf_gc (64, gc);
++ char tmp_out_buf[64]; /* inet_ntop wants pointer to buffer */
++
++ if ( memcmp(&a6, &in6addr_any, sizeof(a6)) != 0 ||
++ !(flags & IA_EMPTY_IF_UNDEF))
++ {
++ inet_ntop (AF_INET6, &a6, tmp_out_buf, sizeof(tmp_out_buf)-1);
++ buf_printf (&out, "%s", tmp_out_buf );
++ }
++ return BSTR (&out);
++}
++
++/* add some offset to an ipv6 address
++ * (add in steps of 32 bits, taking overflow into next round)
++ */
++#ifndef s6_addr32
++# ifdef TARGET_SOLARIS
++# define s6_addr32 _S6_un._S6_u32
++# else
++# define s6_addr32 __u6_addr.__u6_addr32
++# endif
++#endif
++#ifndef UINT32_MAX
++# define UINT32_MAX (4294967295U)
++#endif
++struct in6_addr add_in6_addr( struct in6_addr base, uint32_t add )
++{
++ int i;
++ uint32_t h;
++
++ for( i=3; i>=0 && add > 0 ; i-- )
++ {
++ h = ntohl( base.s6_addr32[i] );
++ base.s6_addr32[i] = htonl( (h+add) & UINT32_MAX );
++ /* 32-bit overrun?
++ * caveat: can't do "h+add > UINT32_MAX" with 32bit math!
++ */
++ add = ( h > UINT32_MAX - add )? 1: 0;
++ }
++ return base;
++}
++
+ /* set environmental variables for ip/port in *addr */
+ void
+ setenv_sockaddr (struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, const bool flags)
+@@ -2337,6 +2404,58 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
+
+ #ifdef WIN32
+
++/*
++ * inet_ntop() and inet_pton() wrap-implementations using
++ * WSAAddressToString() and WSAStringToAddress() functions
++ */
++const char *
++inet_ntop(int af, const void *src, char *dst, socklen_t size)
++{
++ struct sockaddr_storage ss;
++ unsigned long s = size;
++
++ CLEAR(ss);
++ ss.ss_family = af;
++
++ switch(af) {
++ case AF_INET:
++ ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
++ break;
++ case AF_INET6:
++ ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
++ break;
++ default:
++ ASSERT (0);
++ }
++ // cannot direclty use &size because of strict aliasing rules
++ return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0)?
++ dst : NULL;
++}
++
++int
++inet_pton(int af, const char *src, void *dst)
++{
++ struct sockaddr_storage ss;
++ int size = sizeof(ss);
++ char src_copy[INET6_ADDRSTRLEN+1];
++
++ CLEAR(ss);
++ // stupid non-const API
++ strncpynt(src_copy, src, INET6_ADDRSTRLEN+1);
++
++ if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) {
++ switch(af) {
++ case AF_INET:
++ *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
++ return 1;
++ case AF_INET6:
++ *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
++ return 1;
++ }
++ }
++ return 0;
++}
++
+ int
+ socket_recv_queue (struct link_socket *sock, int maxsize)
+ {
+diff --git openvpn-2.2.0/socket.h openvpn-2.2-ipv6-20110522-1/socket.h
+index eef98d1..17943e7 100644
+--- openvpn-2.2.0/socket.h
++++ openvpn-2.2-ipv6-20110522-1/socket.h
+@@ -351,6 +351,8 @@ const char *print_link_socket_actual (const struct link_socket_actual *act,
+ #define IA_EMPTY_IF_UNDEF (1<<0)
+ #define IA_NET_ORDER (1<<1)
+ const char *print_in_addr_t (in_addr_t addr, unsigned int flags, struct gc_arena *gc);
++const char *print_in6_addr (struct in6_addr addr6, unsigned int flags, struct gc_arena *gc);
++struct in6_addr add_in6_addr( struct in6_addr base, uint32_t add );
+
+ #define SA_IP_PORT (1<<0)
+ #define SA_SET_IF_NONZERO (1<<1)
+@@ -404,6 +406,7 @@ int openvpn_inet_aton (const char *dotted_quad, struct in_addr *addr);
+ bool ip_addr_dotted_quad_safe (const char *dotted_quad);
+ bool ip_or_dns_addr_safe (const char *addr, const bool allow_fqdn);
+ bool mac_addr_safe (const char *mac_addr);
++bool ipv6_addr_safe (const char *ipv6_text_addr);
+
+ socket_descriptor_t create_socket_tcp (void);
+
+diff --git openvpn-2.2.0/syshead.h openvpn-2.2-ipv6-20110522-1/syshead.h
+index 63b82ba..a01c2c4 100644
+--- openvpn-2.2.0/syshead.h
++++ openvpn-2.2-ipv6-20110522-1/syshead.h
+@@ -28,6 +28,10 @@
+ /*
+ * Only include if not during configure
+ */
++#ifdef WIN32
++/* USE_PF_INET6: win32 ipv6 exists only after 0x0501 (XP) */
++#define WINVER 0x0501
++#endif
+ #ifndef PACKAGE_NAME
+ #include "config.h"
+ #endif
+@@ -339,6 +343,9 @@
+ #ifdef WIN32
+ #include <iphlpapi.h>
+ #include <wininet.h>
++/* The following two headers are needed of USE_PF_INET6 */
++#include <winsock2.h>
++#include <ws2tcpip.h>
+ #endif
+
+ #ifdef HAVE_SYS_MMAN_H
+diff --git openvpn-2.2.0/tun.c openvpn-2.2-ipv6-20110522-1/tun.c
+index 59e87dc..cea1784 100644
+--- openvpn-2.2.0/tun.c
++++ openvpn-2.2-ipv6-20110522-1/tun.c
+@@ -56,13 +56,14 @@ static void netsh_ifconfig (const struct tuntap_options *to,
+ const in_addr_t ip,
+ const in_addr_t netmask,
+ const unsigned int flags);
++static void netsh_command (const struct argv *a, int n);
+
+ static const char *netsh_get_id (const char *dev_node, struct gc_arena *gc);
+
+ #endif
+
+ #ifdef TARGET_SOLARIS
+-static void solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual);
++static void solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual, bool unplumb_inet6);
+ #include <stropts.h>
+ #endif
+
+@@ -129,30 +130,6 @@ guess_tuntap_dev (const char *dev,
+ return dev;
+ }
+
+-/*
+- * Called by the open_tun function of OSes to check if we
+- * explicitly support IPv6.
+- *
+- * In this context, explicit means that the OS expects us to
+- * do something special to the tun socket in order to support
+- * IPv6, i.e. it is not transparent.
+- *
+- * ipv6_explicitly_supported should be set to false if we don't
+- * have any explicit IPv6 code in the tun device handler.
+- *
+- * If ipv6_explicitly_supported is true, then we have explicit
+- * OS-specific tun dev code for handling IPv6. If so, tt->ipv6
+- * is set according to the --tun-ipv6 command line option.
+- */
+-static void
+-ipv6_support (bool ipv6, bool ipv6_explicitly_supported, struct tuntap* tt)
+-{
+- tt->ipv6 = false;
+- if (ipv6_explicitly_supported)
+- tt->ipv6 = ipv6;
+- else if (ipv6)
+- msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
+-}
+
+ /* --ifconfig-nowarn disables some options sanity checking */
+ static const char ifconfig_warn_how_to_silence[] = "(silence this warning with --ifconfig-nowarn)";
+@@ -423,6 +400,8 @@ init_tun (const char *dev, /* --dev option */
+ int topology, /* one of the TOP_x values */
+ const char *ifconfig_local_parm, /* --ifconfig parm 1 */
+ const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */
++ const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 IPv6 */
++ const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 IPv6 */
+ in_addr_t local_public,
+ in_addr_t remote_public,
+ const bool strict_warn,
+@@ -537,6 +516,40 @@ init_tun (const char *dev, /* --dev option */
+
+ tt->did_ifconfig_setup = true;
+ }
++
++ if (ifconfig_ipv6_local_parm && ifconfig_ipv6_remote_parm)
++ {
++ const char *ifconfig_ipv6_local = NULL;
++ const char *ifconfig_ipv6_remote = NULL;
++
++ /*
++ * Convert arguments to binary IPv6 addresses.
++ */
++
++ if ( inet_pton( AF_INET6, ifconfig_ipv6_local_parm, &tt->local_ipv6 ) != 1 ||
++ inet_pton( AF_INET6, ifconfig_ipv6_remote_parm, &tt->remote_ipv6 ) != 1 )
++ {
++ msg( M_FATAL, "init_tun: problem converting IPv6 ifconfig addresses %s and %s to binary", ifconfig_ipv6_local_parm, ifconfig_ipv6_remote_parm );
++ }
++ tt->netbits_ipv6 = 64;
++
++ /*
++ * Set ifconfig parameters
++ */
++ ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
++ ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
++
++ /*
++ * Set environmental variables with ifconfig parameters.
++ */
++ if (es)
++ {
++ setenv_str (es, "ifconfig_ipv6_local", ifconfig_ipv6_local);
++ setenv_str (es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote);
++ }
++ tt->did_ifconfig_ipv6_setup = true;
++ }
++
+ gc_free (&gc);
+ return tt;
+ }
+@@ -559,6 +572,40 @@ init_tun_post (struct tuntap *tt,
+ #endif
+ }
+
++#if defined(TARGET_WIN32) || \
++ defined(TARGET_DARWIN) || defined(TARGET_NETBSD) || defined(TARGET_OPENBSD)
++
++/* some of the platforms will auto-add a "network route" pointing
++ * to the interface on "ifconfig tunX 2001:db8::1/64", others need
++ * an extra call to "route add..."
++ * -> helper function to simplify code below
++ */
++void add_route_connected_v6_net(struct tuntap * tt,
++ const struct env_set *es)
++{
++ struct route_ipv6 r6;
++
++ r6.defined = true;
++ r6.network = tt->local_ipv6;
++ r6.netbits = tt->netbits_ipv6;
++ r6.gateway = tt->local_ipv6;
++ add_route_ipv6 (&r6, tt, 0, es);
++}
++
++void delete_route_connected_v6_net(struct tuntap * tt,
++ const struct env_set *es)
++{
++ struct route_ipv6 r6;
++
++ r6.defined = true;
++ r6.network = tt->local_ipv6;
++ r6.netbits = tt->netbits_ipv6;
++ r6.gateway = tt->local_ipv6;
++ delete_route_ipv6 (&r6, tt, 0, es);
++}
++#endif
++
++
+ /* execute the ifconfig command through the shell */
+ void
+ do_ifconfig (struct tuntap *tt,
+@@ -574,10 +621,16 @@ do_ifconfig (struct tuntap *tt,
+ const char *ifconfig_local = NULL;
+ const char *ifconfig_remote_netmask = NULL;
+ const char *ifconfig_broadcast = NULL;
++ const char *ifconfig_ipv6_local = NULL;
++ const char *ifconfig_ipv6_remote = NULL;
++ bool do_ipv6 = false;
+ struct argv argv;
+
+ argv_init (&argv);
+
++ msg( M_INFO, "do_ifconfig, tt->ipv6=%d, tt->did_ifconfig_ipv6_setup=%d",
++ tt->ipv6, tt->did_ifconfig_ipv6_setup );
++
+ /*
+ * We only handle TUN/TAP devices here, not --dev null devices.
+ */
+@@ -589,6 +642,13 @@ do_ifconfig (struct tuntap *tt,
+ ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
+ ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
+
++ if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
++ {
++ ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
++ ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
++ do_ipv6 = true;
++ }
++
+ /*
+ * If TAP-style device, generate broadcast address.
+ */
+@@ -647,7 +707,19 @@ do_ifconfig (struct tuntap *tt,
+ argv_msg (M_INFO, &argv);
+ openvpn_execve_check (&argv, es, S_FATAL, "Linux ip addr add failed");
+ }
+- tt->did_ifconfig = true;
++ if ( do_ipv6 )
++ {
++ argv_printf( &argv,
++ "%s -6 addr add %s/%d dev %s",
++ iproute_path,
++ ifconfig_ipv6_local,
++ tt->netbits_ipv6,
++ actual
++ );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, S_FATAL, "Linux ip -6 addr add failed");
++ }
++ tt->did_ifconfig = true;
+ #else
+ if (tun)
+ argv_printf (&argv,
+@@ -670,6 +742,18 @@ do_ifconfig (struct tuntap *tt,
+ );
+ argv_msg (M_INFO, &argv);
+ openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig failed");
++ if ( do_ipv6 )
++ {
++ argv_printf (&argv,
++ "%s %s inet6 add %s/%d",
++ IFCONFIG_PATH,
++ actual,
++ ifconfig_ipv6_local,
++ tt->netbits_ipv6
++ );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig inet6 failed");
++ }
+ tt->did_ifconfig = true;
+
+ #endif /*CONFIG_FEATURE_IPROUTE*/
+@@ -693,7 +777,7 @@ do_ifconfig (struct tuntap *tt,
+
+ argv_msg (M_INFO, &argv);
+ if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig phase-1 failed"))
+- solaris_error_close (tt, es, actual);
++ solaris_error_close (tt, es, actual, false);
+
+ argv_printf (&argv,
+ "%s %s netmask 255.255.255.255",
+@@ -725,7 +809,53 @@ do_ifconfig (struct tuntap *tt,
+
+ argv_msg (M_INFO, &argv);
+ if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig phase-2 failed"))
+- solaris_error_close (tt, es, actual);
++ solaris_error_close (tt, es, actual, false);
++
++ if ( do_ipv6 )
++ {
++ argv_printf (&argv, "%s %s inet6 unplumb",
++ IFCONFIG_PATH, actual );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, 0, NULL);
++
++ if ( tt->type == DEV_TYPE_TUN )
++ {
++ argv_printf (&argv,
++ "%s %s inet6 plumb %s/%d %s up",
++ IFCONFIG_PATH,
++ actual,
++ ifconfig_ipv6_local,
++ tt->netbits_ipv6,
++ ifconfig_ipv6_remote
++ );
++ }
++ else /* tap mode */
++ {
++ /* base IPv6 tap interface needs to be brought up first
++ */
++ argv_printf (&argv, "%s %s inet6 plumb up",
++ IFCONFIG_PATH, actual );
++ argv_msg (M_INFO, &argv);
++ if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 (prepare) failed"))
++ solaris_error_close (tt, es, actual, true);
++
++ /* we might need to do "ifconfig %s inet6 auto-dhcp drop"
++ * after the system has noticed the interface and fired up
++ * the DHCPv6 client - but this takes quite a while, and the
++ * server will ignore the DHCPv6 packets anyway. So we don't.
++ */
++
++ /* static IPv6 addresses need to go to a subinterface (tap0:1)
++ */
++ argv_printf (&argv,
++ "%s %s inet6 addif %s/%d up",
++ IFCONFIG_PATH, actual,
++ ifconfig_ipv6_local, tt->netbits_ipv6 );
++ }
++ argv_msg (M_INFO, &argv);
++ if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 failed"))
++ solaris_error_close (tt, es, actual, true);
++ }
+
+ if (!tun && tt->topology == TOP_SUBNET)
+ {
+@@ -787,10 +917,42 @@ do_ifconfig (struct tuntap *tt,
+ );
+ argv_msg (M_INFO, &argv);
+ openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig failed");
++ if ( do_ipv6 )
++ {
++ argv_printf (&argv,
++ "%s %s inet6 %s/%d",
++ IFCONFIG_PATH,
++ actual,
++ ifconfig_ipv6_local,
++ tt->netbits_ipv6
++ );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig inet6 failed");
++
++ /* and, hooray, we explicitely need to add a route... */
++ add_route_connected_v6_net(tt, es);
++ }
+ tt->did_ifconfig = true;
+
+ #elif defined(TARGET_NETBSD)
+
++/* whether or not NetBSD can do IPv6 can be seen by the availability of
++ * the TUNSIFHEAD ioctl() - see next TARGET_NETBSD block for more details
++ */
++#ifdef TUNSIFHEAD
++# define NETBSD_MULTI_AF
++#endif
++
++ /* as on OpenBSD and Darwin, destroy and re-create tun<x> interface
++ */
++ argv_printf (&argv, "%s %s destroy", IFCONFIG_PATH, actual );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, 0, "NetBSD ifconfig destroy failed");
++
++ argv_printf (&argv, "%s %s create", IFCONFIG_PATH, actual );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig create failed");
++
+ if (tun)
+ argv_printf (&argv,
+ "%s %s %s %s mtu %d netmask 255.255.255.255 up",
+@@ -817,6 +979,27 @@ do_ifconfig (struct tuntap *tt,
+ );
+ argv_msg (M_INFO, &argv);
+ openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig failed");
++
++ if ( do_ipv6 )
++ {
++#ifdef NETBSD_MULTI_AF
++ argv_printf (&argv,
++ "%s %s inet6 %s/%d",
++ IFCONFIG_PATH,
++ actual,
++ ifconfig_ipv6_local,
++ tt->netbits_ipv6
++ );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig inet6 failed");
++
++ /* and, hooray, we explicitely need to add a route... */
++ add_route_connected_v6_net(tt, es);
++#else
++ msg( M_INFO, "no IPv6 support for tun interfaces on NetBSD before 4.0 (if your system is newer, recompile openvpn)" );
++ tt->ipv6 = false;
++#endif
++ }
+ tt->did_ifconfig = true;
+
+ #elif defined(TARGET_DARWIN)
+@@ -882,6 +1065,22 @@ do_ifconfig (struct tuntap *tt,
+ add_route (&r, tt, 0, es);
+ }
+
++ if ( do_ipv6 )
++ {
++ argv_printf (&argv,
++ "%s %s inet6 %s/%d",
++ IFCONFIG_PATH,
++ actual,
++ ifconfig_ipv6_local,
++ tt->netbits_ipv6
++ );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, S_FATAL, "MacOS X ifconfig inet6 failed");
++
++ /* and, hooray, we explicitely need to add a route... */
++ add_route_connected_v6_net(tt, es);
++ }
++
+ #elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
+
+ /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
+@@ -920,6 +1119,19 @@ do_ifconfig (struct tuntap *tt,
+ add_route (&r, tt, 0, es);
+ }
+
++ if ( do_ipv6 )
++ {
++ argv_printf (&argv,
++ "%s %s inet6 %s/%d",
++ IFCONFIG_PATH,
++ actual,
++ ifconfig_ipv6_local,
++ tt->netbits_ipv6
++ );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, S_FATAL, "FreeBSD ifconfig inet6 failed");
++ }
++
+ #elif defined (WIN32)
+ {
+ /*
+@@ -959,6 +1171,34 @@ do_ifconfig (struct tuntap *tt,
+ tt->did_ifconfig = true;
+ }
+
++ /* IPv6 always uses "netsh" interface */
++ if ( do_ipv6 )
++ {
++ char * saved_actual;
++
++ if (!strcmp (actual, "NULL"))
++ msg (M_FATAL, "Error: When using --tun-ipv6, if you have more than one TAP-Win32 adapter, you must also specify --dev-node");
++
++ /* example: netsh interface ipv6 set address MyTap 2001:608:8003::d store=active */
++ argv_printf (&argv,
++ "%s%sc interface ipv6 set address %s %s store=active",
++ get_win_sys_path(),
++ NETSH_PATH_SUFFIX,
++ actual,
++ ifconfig_ipv6_local );
++
++ netsh_command (&argv, 4);
++
++ /* explicit route needed */
++ /* on windows, OpenVPN does ifconfig first, open_tun later, so
++ * tt->actual_name might not yet be initialized, but routing code
++ * needs to know interface name - point to "actual", restore later
++ */
++ saved_actual = tt->actual_name;
++ tt->actual_name = (char*) actual;
++ add_route_connected_v6_net(tt, es);
++ tt->actual_name = saved_actual;
++ }
+ #else
+ msg (M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script.");
+ #endif
+@@ -991,14 +1231,16 @@ open_null (struct tuntap *tt)
+ #ifndef WIN32
+ static void
+ open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
+- bool ipv6, bool ipv6_explicitly_supported, bool dynamic,
++ bool ipv6_explicitly_supported, bool dynamic,
+ struct tuntap *tt)
+ {
+ char tunname[256];
+ char dynamic_name[256];
+ bool dynamic_opened = false;
+
+- ipv6_support (ipv6, ipv6_explicitly_supported, tt);
++
++ if ( tt->ipv6 && ! ipv6_explicitly_supported )
++ msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
+
+ if (tt->type == DEV_TYPE_NULL)
+ {
+@@ -1094,16 +1336,16 @@ close_tun_generic (struct tuntap *tt)
+ #if !PEDANTIC
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+ struct ifreq ifr;
+
+- /*
+- * Set tt->ipv6 to true if
+- * (a) we have the capability of supporting --tun-ipv6, and
+- * (b) --tun-ipv6 was specified.
++ /* warn if a very old linux version is used & --tun-ipv6 set
+ */
+- ipv6_support (ipv6, LINUX_IPV6, tt);
++#if LINUX_IPV6 == 0
++ if ( tt->ipv6 )
++ msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
++#endif
+
+ /*
+ * We handle --dev null specially, we do not open /dev/null for this.
+@@ -1215,13 +1457,13 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
+ close (tt->fd);
+ tt->fd = -1;
+ }
+- open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
++ open_tun_generic (dev, dev_type, dev_node, false, true, tt);
+ }
+
+ #else
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+ ASSERT (0);
+ }
+@@ -1231,9 +1473,9 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
+ #else
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+- open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
++ open_tun_generic (dev, dev_type, dev_node, false, true, tt);
+ }
+
+ #endif /* HAVE_LINUX_IF_TUN_H */
+@@ -1253,7 +1495,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
+ #endif
+
+ void
+-tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options)
++tuncfg (const char *dev, const char *dev_type, const char *dev_node, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options)
+ {
+ struct tuntap *tt;
+
+@@ -1261,7 +1503,7 @@ tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6,
+ clear_tuntap (tt);
+ tt->type = dev_type_enum (dev, dev_type);
+ tt->options = *options;
+- open_tun (dev, dev_type, dev_node, ipv6, tt);
++ open_tun (dev, dev_type, dev_node, tt);
+ if (ioctl (tt->fd, TUNSETPERSIST, persist_mode) < 0)
+ msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
+ if (username != NULL)
+@@ -1404,7 +1646,7 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
+ #endif
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+ int if_fd, ip_muxid, arp_muxid, arp_fd, ppa = -1;
+ struct lifreq ifr;
+@@ -1415,8 +1657,11 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
+ bool is_tun;
+ struct strioctl strioc_if, strioc_ppa;
+
+- ipv6_support (ipv6, true, tt);
+- memset(&ifr, 0x0, sizeof(ifr));
++ /* improved generic TUN/TAP driver from
++ * http://www.whiteboard.ne.jp/~admin2/tuntap/
++ * has IPv6 support
++ */
++ CLEAR(ifr);
+
+ if (tt->type == DEV_TYPE_NULL)
+ {
+@@ -1570,6 +1815,18 @@ solaris_close_tun (struct tuntap *tt)
+ {
+ if (tt)
+ {
++ /* IPv6 interfaces need to be 'manually' de-configured */
++ if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
++ {
++ struct argv argv;
++ argv_init (&argv);
++ argv_printf( &argv, "%s %s inet6 unplumb",
++ IFCONFIG_PATH, tt->actual_name );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, NULL, 0, "Solaris ifconfig inet6 unplumb failed");
++ argv_reset (&argv);
++ }
++
+ if (tt->ip_fd >= 0)
+ {
+ struct lifreq ifr;
+@@ -1622,11 +1879,20 @@ close_tun (struct tuntap *tt)
+ }
+
+ static void
+-solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual)
++solaris_error_close (struct tuntap *tt, const struct env_set *es,
++ const char *actual, bool unplumb_inet6 )
+ {
+ struct argv argv;
+ argv_init (&argv);
+
++ if (unplumb_inet6)
++ {
++ argv_printf( &argv, "%s %s inet6 unplumb",
++ IFCONFIG_PATH, actual );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, es, 0, "Solaris ifconfig inet6 unplumb failed");
++ }
++
+ argv_printf (&argv,
+ "%s %s unplumb",
+ IFCONFIG_PATH,
+@@ -1683,9 +1949,9 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
+ */
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+- open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
++ open_tun_generic (dev, dev_type, dev_node, true, true, tt);
+
+ /* Enable multicast on the interface */
+ if (tt->fd >= 0)
+@@ -1706,12 +1972,31 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
+ }
+ }
+
++/* the current way OpenVPN handles tun devices on OpenBSD leads to
++ * lingering tunX interfaces after close -> for a full cleanup, they
++ * need to be explicitely destroyed
++ */
++
+ void
+ close_tun (struct tuntap* tt)
+ {
+ if (tt)
+ {
++ struct gc_arena gc = gc_new ();
++ struct argv argv;
++
++ /* setup command, close tun dev (clears tt->actual_name!), run command
++ */
++
++ argv_init (&argv);
++ argv_printf (&argv, "%s %s destroy",
++ IFCONFIG_PATH, tt->actual_name);
++
+ close_tun_generic (tt);
++
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, NULL, 0, "OpenBSD 'destroy tun interface' failed (non-critical)");
++
+ free (tt);
+ }
+ }
+@@ -1774,33 +2059,51 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
+ #elif defined(TARGET_NETBSD)
+
+ /*
+- * NetBSD does not support IPv6 on tun out of the box,
+- * but there exists a patch. When this patch is applied,
+- * only two things are left to openvpn:
+- * 1. Activate multicasting (this has already been done
+- * before by the kernel, but we make sure that nobody
+- * has deactivated multicasting inbetween.
+- * 2. Deactivate "link layer mode" (otherwise NetBSD
+- * prepends the address family to the packet, and we
+- * would run into the same trouble as with OpenBSD.
++ * NetBSD before 4.0 does not support IPv6 on tun out of the box,
++ * but there exists a patch (sys/net/if_tun.c, 1.79->1.80, see PR 32944).
++ *
++ * NetBSD 4.0 and up do, but we need to put the tun interface into
++ * "multi_af" mode, which will prepend the address family to all packets
++ * (same as OpenBSD and FreeBSD). If this is not enabled, the kernel
++ * silently drops all IPv6 packets on output and gets confused on input.
++ *
++ * On earlier versions, multi_af is not available at all, so we have
++ * two different NetBSD code variants here :-(
++ *
+ */
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+- open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
++#ifdef NETBSD_MULTI_AF
++ open_tun_generic (dev, dev_type, dev_node, true, true, tt);
++#else
++ open_tun_generic (dev, dev_type, dev_node, false, true, tt);
++#endif
++
+ if (tt->fd >= 0)
+ {
+ int i = IFF_POINTOPOINT|IFF_MULTICAST;
+ ioctl (tt->fd, TUNSIFMODE, &i); /* multicast on */
+ i = 0;
+ ioctl (tt->fd, TUNSLMODE, &i); /* link layer mode off */
++
++#ifdef NETBSD_MULTI_AF
++ i = 1;
++ if (ioctl (tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */
++ {
++ msg (M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno));
++ }
++#endif
+ }
+ }
+
+ void
+ close_tun (struct tuntap *tt)
+ {
++ /* TODO: we really should cleanup non-persistant tunX with
++ * "ifconfig tunX destroy" here...
++ */
+ if (tt)
+ {
+ close_tun_generic (tt);
+@@ -1808,6 +2111,65 @@ close_tun (struct tuntap *tt)
+ }
+ }
+
++#ifdef NETBSD_MULTI_AF
++
++static inline int
++netbsd_modify_read_write_return (int len)
++{
++ if (len > 0)
++ return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
++ else
++ return len;
++}
++
++int
++write_tun (struct tuntap* tt, uint8_t *buf, int len)
++{
++ if (tt->type == DEV_TYPE_TUN)
++ {
++ u_int32_t type;
++ struct iovec iv[2];
++ struct openvpn_iphdr *iph;
++
++ iph = (struct openvpn_iphdr *) buf;
++
++ if (tt->ipv6 && OPENVPN_IPH_GET_VER(iph->version_len) == 6)
++ type = htonl (AF_INET6);
++ else
++ type = htonl (AF_INET);
++
++ iv[0].iov_base = (char *)&type;
++ iv[0].iov_len = sizeof (type);
++ iv[1].iov_base = buf;
++ iv[1].iov_len = len;
++
++ return netbsd_modify_read_write_return (writev (tt->fd, iv, 2));
++ }
++ else
++ return write (tt->fd, buf, len);
++}
++
++int
++read_tun (struct tuntap* tt, uint8_t *buf, int len)
++{
++ if (tt->type == DEV_TYPE_TUN)
++ {
++ u_int32_t type;
++ struct iovec iv[2];
++
++ iv[0].iov_base = (char *)&type;
++ iv[0].iov_len = sizeof (type);
++ iv[1].iov_base = buf;
++ iv[1].iov_len = len;
++
++ return netbsd_modify_read_write_return (readv (tt->fd, iv, 2));
++ }
++ else
++ return read (tt->fd, buf, len);
++}
++
++#else /* not NETBSD_MULTI_AF -> older code, IPv4 only */
++
+ int
+ write_tun (struct tuntap* tt, uint8_t *buf, int len)
+ {
+@@ -1819,6 +2181,7 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
+ {
+ return read (tt->fd, buf, len);
+ }
++#endif /* NETBSD_MULTI_AF */
+
+ #elif defined(TARGET_FREEBSD)
+
+@@ -1832,9 +2195,9 @@ freebsd_modify_read_write_return (int len)
+ }
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+- open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
++ open_tun_generic (dev, dev_type, dev_node, true, true, tt);
+
+ if (tt->fd >= 0 && tt->type == DEV_TYPE_TUN)
+ {
+@@ -1920,9 +2283,9 @@ dragonfly_modify_read_write_return (int len)
+ }
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+- open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
++ open_tun_generic (dev, dev_type, dev_node, true, true, tt);
+
+ if (tt->fd >= 0)
+ {
+@@ -1991,6 +2354,61 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
+ return read (tt->fd, buf, len);
+ }
+
++#elif defined(TARGET_DARWIN)
++
++/* Darwin (MacOS X) is mostly "just use the generic stuff", but there
++ * is always one caveat...:
++ *
++ * If IPv6 is configured, and the tun device is closed, the IPv6 address
++ * configured to the tun interface changes to a lingering /128 route
++ * pointing to lo0. Need to unconfigure... (observed on 10.5)
++ */
++
++void
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
++{
++ open_tun_generic (dev, dev_type, dev_node, false, true, tt);
++}
++
++void
++close_tun (struct tuntap* tt)
++{
++ if (tt)
++ {
++ struct gc_arena gc = gc_new ();
++ struct argv argv;
++ argv_init (&argv);
++
++ if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
++ {
++ const char * ifconfig_ipv6_local =
++ print_in6_addr (tt->local_ipv6, 0, &gc);
++
++ argv_printf (&argv, "%s delete -inet6 %s",
++ ROUTE_PATH, ifconfig_ipv6_local );
++ argv_msg (M_INFO, &argv);
++ openvpn_execve_check (&argv, NULL, 0, "MacOS X 'remove inet6 route' failed (non-critical)");
++ }
++
++ close_tun_generic (tt);
++ free (tt);
++ argv_reset (&argv);
++ gc_free (&gc);
++ }
++}
++
++int
++write_tun (struct tuntap* tt, uint8_t *buf, int len)
++{
++ return write (tt->fd, buf, len);
++}
++
++int
++read_tun (struct tuntap* tt, uint8_t *buf, int len)
++{
++ return read (tt->fd, buf, len);
++}
++
+ #elif defined(WIN32)
+
+ int
+@@ -3976,7 +4394,7 @@ fork_register_dns_action (struct tuntap *tt)
+ }
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+ struct gc_arena gc = gc_new ();
+ char device_path[256];
+@@ -3987,7 +4405,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
+
+ /*netcmd_semaphore_lock ();*/
+
+- ipv6_support (ipv6, false, tt);
++ msg( M_INFO, "open_tun, tt->ipv6=%d", tt->ipv6 );
+
+ if (tt->type == DEV_TYPE_NULL)
+ {
+@@ -4109,6 +4527,16 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
+ msg (M_FATAL, "ERROR: This version of " PACKAGE_NAME " requires a TAP-Win32 driver that is at least version %d.%d -- If you recently upgraded your " PACKAGE_NAME " distribution, a reboot is probably required at this point to get Windows to see the new driver.",
+ TAP_WIN32_MIN_MAJOR,
+ TAP_WIN32_MIN_MINOR);
++
++ /* usage of numeric constants is ugly, but this is really tied to
++ * *this* version of the driver
++ */
++ if ( tt->ipv6 && tt->type == DEV_TYPE_TUN &&
++ info[0] == 9 && info[1] < 8)
++ {
++ msg( M_INFO, "WARNING: Tap-Win32 driver version %d.%d does not support IPv6 in TUN mode. IPv6 will be disabled. Upgrade to Tap-Win32 9.8 (2.2-beta3 release or later) or use TAP mode to get IPv6", (int) info[0], (int) info[1] );
++ tt->ipv6 = false;
++ }
+ }
+
+ /* get driver MTU */
+@@ -4433,6 +4861,26 @@ close_tun (struct tuntap *tt)
+
+ if (tt)
+ {
++ if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
++ {
++ struct argv argv;
++ argv_init (&argv);
++
++ /* remove route pointing to interface */
++ delete_route_connected_v6_net(tt, NULL);
++
++ /* netsh interface ipv6 delete address \"%s\" %s */
++ const char * ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
++ argv_printf (&argv,
++ "%s%sc interface ipv6 delete address %s %s",
++ get_win_sys_path(),
++ NETSH_PATH_SUFFIX,
++ tt->actual_name,
++ ifconfig_ipv6_local );
++
++ netsh_command (&argv, 1);
++ argv_reset (&argv);
++ }
+ #if 1
+ if (tt->ipapi_context_defined)
+ {
+@@ -4536,9 +4984,9 @@ ipset2ascii_all (struct gc_arena *gc)
+ #else /* generic */
+
+ void
+-open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
++open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+ {
+- open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
++ open_tun_generic (dev, dev_type, dev_node, false, true, tt);
+ }
+
+ void
+diff --git openvpn-2.2.0/tun.h openvpn-2.2-ipv6-20110522-1/tun.h
+index 011ab54..f28b8d8 100644
+--- openvpn-2.2.0/tun.h
++++ openvpn-2.2-ipv6-20110522-1/tun.h
+@@ -130,6 +130,7 @@ struct tuntap
+ int topology; /* one of the TOP_x values */
+
+ bool did_ifconfig_setup;
++ bool did_ifconfig_ipv6_setup;
+ bool did_ifconfig;
+
+ bool ipv6;
+@@ -146,6 +147,10 @@ struct tuntap
+ in_addr_t remote_netmask;
+ in_addr_t broadcast;
+
++ struct in6_addr local_ipv6;
++ struct in6_addr remote_ipv6;
++ int netbits_ipv6;
++
+ #ifdef WIN32
+ HANDLE hand;
+ struct overlapped_io reads;
+@@ -197,7 +202,7 @@ tuntap_defined (const struct tuntap *tt)
+ void clear_tuntap (struct tuntap *tuntap);
+
+ void open_tun (const char *dev, const char *dev_type, const char *dev_node,
+- bool ipv6, struct tuntap *tt);
++ struct tuntap *tt);
+
+ void close_tun (struct tuntap *tt);
+
+@@ -206,7 +211,7 @@ int write_tun (struct tuntap* tt, uint8_t *buf, int len);
+ int read_tun (struct tuntap* tt, uint8_t *buf, int len);
+
+ void tuncfg (const char *dev, const char *dev_type, const char *dev_node,
+- bool ipv6, int persist_mode, const char *username,
++ int persist_mode, const char *username,
+ const char *groupname, const struct tuntap_options *options);
+
+ const char *guess_tuntap_dev (const char *dev,
+@@ -219,6 +224,8 @@ struct tuntap *init_tun (const char *dev, /* --dev option */
+ int topology, /* one of the TOP_x values */
+ const char *ifconfig_local_parm, /* --ifconfig parm 1 */
+ const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */
++ const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 / IPv6 */
++ const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 / IPv6 */
+ in_addr_t local_public,
+ in_addr_t remote_public,
+ const bool strict_warn,
+diff --git openvpn-2.2.0/win32.c openvpn-2.2-ipv6-20110522-1/win32.c
+index 2b7bf7b..cf6cc2d 100644
+--- openvpn-2.2.0/win32.c
++++ openvpn-2.2-ipv6-20110522-1/win32.c
+@@ -874,16 +874,21 @@ win_safe_filename (const char *fn)
+ static char *
+ env_block (const struct env_set *es)
+ {
++ char * force_path = "PATH=C:\\Windows\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem";
++
+ if (es)
+ {
+ struct env_item *e;
+ char *ret;
+ char *p;
+ size_t nchars = 1;
++ bool path_seen = false;
+
+ for (e = es->list; e != NULL; e = e->next)
+ nchars += strlen (e->string) + 1;
+
++ nchars += strlen(force_path)+1;
++
+ ret = (char *) malloc (nchars);
+ check_malloc_return (ret);
+
+@@ -895,7 +900,18 @@ env_block (const struct env_set *es)
+ strcpy (p, e->string);
+ p += strlen (e->string) + 1;
+ }
++ if ( strncmp(e->string, "PATH=", 5 ) == 0 )
++ path_seen = true;
++ }
++
++ /* make sure PATH is set */
++ if ( !path_seen )
++ {
++ msg( M_INFO, "env_block: add %s", force_path );
++ strcpy( p, force_path );
++ p += strlen(force_path) + 1;
+ }
++
+ *p = '\0';
+ return ret;
+ }
+diff --git openvpn-2.2.0/win32.h openvpn-2.2-ipv6-20110522-1/win32.h
+index b6a162e..829933f 100644
+--- openvpn-2.2.0/win32.h
++++ openvpn-2.2-ipv6-20110522-1/win32.h
+@@ -269,6 +269,8 @@ char *get_win_sys_path (void);
+
+ /* call self in a subprocess */
+ void fork_to_self (const char *cmdline);
++const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
++int inet_pton(int af, const char *src, void *st);
+
+ /* Find temporary directory */
+ const char *win_get_tempdir();
diff --git a/main/openvpn/openvpn.confd b/main/openvpn/openvpn.confd
new file mode 100644
index 0000000000..72510c34ae
--- /dev/null
+++ b/main/openvpn/openvpn.confd
@@ -0,0 +1,18 @@
+# OpenVPN automatically creates an /etc/resolv.conf (or sends it to
+# resolvconf) if given DNS information by the OpenVPN server.
+# Set PEER_DNS="no" to stop this.
+PEER_DNS="yes"
+
+# OpenVPN can run in many modes. Most people will want the init script
+# to automatically detect the mode and try and apply a good default
+# configuration and setup scripts. However, there are cases where the
+# OpenVPN configuration looks like a client, but it's really a peer or
+# something else. DETECT_CLIENT controls this behaviour.
+DETECT_CLIENT="yes"
+
+# If DETECT_CLIENT is no and you have your own scripts to re-enter the openvpn
+# init script (ie, it first becomes "inactive" and the script then starts the
+# script again to make it "started") then you can state this below.
+# In other words, unless you understand service dependencies and are a
+# competent shell scripter, don't set this.
+RE_ENTER="no"
diff --git a/main/openvpn/openvpn.down b/main/openvpn/openvpn.down
new file mode 100644
index 0000000000..1c70db0ec6
--- /dev/null
+++ b/main/openvpn/openvpn.down
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Copyright (c) 2006-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# Contributed by Roy Marples (uberlord@gentoo.org)
+
+# If we have a service specific script, run this now
+if [ -x /etc/openvpn/"${SVCNAME}"-down.sh ] ; then
+ /etc/openvpn/"${SVCNAME}"-down.sh "$@"
+fi
+
+# Restore resolv.conf to how it was
+if [ "${PEER_DNS}" != "no" ]; then
+ if [ -x /sbin/resolvconf ] ; then
+ /sbin/resolvconf -d "${dev}"
+ elif [ -e /etc/resolv.conf-"${dev}".sv ] ; then
+ # Important that we copy instead of move incase resolv.conf is
+ # a symlink and not an actual file
+ cp /etc/resolv.conf-"${dev}".sv /etc/resolv.conf
+ rm -f /etc/resolv.conf-"${dev}".sv
+ fi
+fi
+
+if [ -n "${SVCNAME}" ]; then
+ # Re-enter the init script to start any dependant services
+ if /etc/init.d/"${SVCNAME}" --quiet status ; then
+ export IN_BACKGROUND=true
+ /etc/init.d/"${SVCNAME}" --quiet stop
+ fi
+fi
+
+exit 0
+
+# vim: ts=4 :
diff --git a/main/openvpn/openvpn.initd b/main/openvpn/openvpn.initd
new file mode 100644
index 0000000000..e7bcd1491c
--- /dev/null
+++ b/main/openvpn/openvpn.initd
@@ -0,0 +1,133 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+VPNDIR=${VPNDIR:-/etc/openvpn}
+VPN=${SVCNAME#*.}
+if [ -n "${VPN}" ] && [ ${SVCNAME} != "openvpn" ]; then
+ VPNPID="/var/run/openvpn.${VPN}.pid"
+else
+ VPNPID="/var/run/openvpn.pid"
+fi
+VPNCONF="${VPNDIR}/${VPN}.conf"
+
+depend() {
+ need localmount net
+ use dns
+ after bootmisc
+}
+
+checkconfig() {
+ # Linux has good dynamic tun/tap creation
+ if [ $(uname -s) = "Linux" ] ; then
+ if [ ! -e /dev/net/tun ]; then
+ if ! modprobe tun ; then
+ eerror "TUN/TAP support is not available" \
+ "in this kernel"
+ return 1
+ fi
+ fi
+ if [ -h /dev/net/tun ] && [ -c /dev/misc/net/tun ]; then
+ ebegin "Detected broken /dev/net/tun symlink, fixing..."
+ rm -f /dev/net/tun
+ ln -s /dev/misc/net/tun /dev/net/tun
+ eend $?
+ fi
+ return 0
+ fi
+
+ # Other OS's don't, so we rely on a pre-configured interface
+ # per vpn instance
+ local ifname=$(sed -n -e 's/[[:space:]]*dev[[:space:]][[:space:]]*\([^[:space:]]*\).*/\1/p' "${VPNCONF}")
+ if [ -z ${ifname} ] ; then
+ eerror "You need to specify the interface that this openvpn" \
+ "instance should use" \
+ "by using the dev option in ${VPNCONF}"
+ return 1
+ fi
+
+ if ! ifconfig "${ifname}" >/dev/null 2>/dev/null ; then
+ # Try and create it
+ echo > /dev/"${ifname}" >/dev/null
+ fi
+ if ! ifconfig "${ifname}" >/dev/null 2>/dev/null ; then
+ eerror "${VPNCONF} requires interface ${ifname}" \
+ "but that does not exist"
+ return 1
+ fi
+}
+
+start() {
+ # If we are re-called by the openvpn gentoo-up.sh script
+ # then we don't actually want to start openvpn
+ [ "${IN_BACKGROUND}" = "true" ] && return 0
+
+ ebegin "Starting ${SVCNAME}"
+
+ checkconfig || return 1
+
+ local args="" reenter=${RE_ENTER:-no}
+ # If the config file does not specify the cd option, we do
+ # But if we specify it, we override the config option which we do not want
+ if ! grep -q "^[ ]*cd[ ].*" "${VPNCONF}" ; then
+ args="${args} --cd ${VPNDIR}"
+ fi
+
+ # We mark the service as inactive and then start it.
+ # When we get an authenticated packet from the peer then we run our script
+ # which configures our DNS if any and marks us as up.
+ if [ "${DETECT_CLIENT:-yes}" = "yes" ] && \
+ grep -q "^[ ]*remote[ ].*" "${VPNCONF}" ; then
+ reenter="yes"
+ args="${args} --up-delay --up-restart"
+ args="${args} --script-security 2"
+ args="${args} --up /etc/openvpn/up.sh"
+ args="${args} --down-pre --down /etc/openvpn/down.sh"
+
+ # Warn about setting scripts as we override them
+ if grep -Eq "^[ ]*(up|down)[ ].*" "${VPNCONF}" ; then
+ ewarn "WARNING: You have defined your own up/down scripts"
+ ewarn "As you're running as a client, we now force Alpine specific"
+ ewarn "scripts to be run for up and down events."
+ ewarn "These scripts will call /etc/openvpn/${SVCNAME}-{up,down}.sh"
+ ewarn "where you can put your own code."
+ fi
+
+ # Warn about the inability to change ip/route/dns information when
+ # dropping privs
+ if grep -q "^[ ]*user[ ].*" "${VPNCONF}" ; then
+ ewarn "WARNING: You are dropping root privileges!"
+ ewarn "As such openvpn may not be able to change ip, routing"
+ ewarn "or DNS configuration."
+ fi
+ else
+ # So we're a server. Run as openvpn unless otherwise specified
+ grep -q "^[ ]*user[ ].*" "${VPNCONF}" || args="${args} --user openvpn"
+ grep -q "^[ ]*group[ ].*" "${VPNCONF}" || args="${args} --group openvpn"
+ fi
+
+ # Ensure that our scripts get the PEER_DNS variable
+ [ -n "${PEER_DNS}" ] && args="${args} --setenv PEER_DNS ${PEER_DNS}"
+
+ [ "${reenter}" = "yes" ] && mark_service_inactive "${SVCNAME}"
+ start-stop-daemon --start --exec /usr/sbin/openvpn --pidfile "${VPNPID}" \
+ -- --config "${VPNCONF}" --writepid "${VPNPID}" --daemon \
+ --setenv SVCNAME "${SVCNAME}" ${args}
+ eend $? "Check your logs to see why startup failed"
+}
+
+stop() {
+ # If we are re-called by the openvpn gentoo-down.sh script
+ # then we don't actually want to stop openvpn
+ if [ "${IN_BACKGROUND}" = "true" ] ; then
+ mark_service_inactive "${SVCNAME}"
+ return 0
+ fi
+
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --quiet \
+ --exec /usr/sbin/openvpn --pidfile "${VPNPID}"
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/main/openvpn/openvpn.up b/main/openvpn/openvpn.up
new file mode 100644
index 0000000000..4a8868702d
--- /dev/null
+++ b/main/openvpn/openvpn.up
@@ -0,0 +1,82 @@
+#!/bin/sh
+# Copyright (c) 2006-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# Contributed by Roy Marples (uberlord@gentoo.org)
+
+# Setup our resolv.conf
+# Vitally important that we use the domain entry in resolv.conf so we
+# can setup the nameservers are for the domain ONLY in resolvconf if
+# we're using a decent dns cache/forwarder like dnsmasq and NOT nscd/libc.
+# nscd/libc users will get the VPN nameservers before their other ones
+# and will use the first one that responds - maybe the LAN ones?
+# non resolvconf users just the the VPN resolv.conf
+
+# FIXME:- if we have >1 domain, then we have to use search :/
+# We need to add a flag to resolvconf to say
+# "these nameservers should only be used for the listed search domains
+# if other global nameservers are present on other interfaces"
+# This however, will break compatibility with Debians resolvconf
+# A possible workaround would be to just list multiple domain lines
+# and try and let resolvconf handle it
+
+if [ "${PEER_DNS}" != "no" ]; then
+ NS=
+ DOMAIN=
+ SEARCH=
+ i=1
+ while true ; do
+ eval opt=\$foreign_option_${i}
+ [ -z "${opt}" ] && break
+ if [ "${opt}" != "${opt#dhcp-option DOMAIN *}" ] ; then
+ if [ -z "${DOMAIN}" ] ; then
+ DOMAIN="${opt#dhcp-option DOMAIN *}"
+ else
+ SEARCH="${SEARCH}${SEARCH:+ }${opt#dhcp-option DOMAIN *}"
+ fi
+ elif [ "${opt}" != "${opt#dhcp-option DNS *}" ] ; then
+ NS="${NS}nameserver ${opt#dhcp-option DNS *}\n"
+ fi
+ i=$((${i} + 1))
+ done
+
+ if [ -n "${NS}" ] ; then
+ DNS="# Generated by openvpn for interface ${dev}\n"
+ if [ -n "${SEARCH}" ] ; then
+ DNS="${DNS}search ${DOMAIN} ${SEARCH}\n"
+ elif [ -n "${DOMAIN}" ]; then
+ DNS="${DNS}domain ${DOMAIN}\n"
+ fi
+ DNS="${DNS}${NS}"
+ if [ -x /sbin/resolvconf ] ; then
+ printf "${DNS}" | /sbin/resolvconf -a "${dev}"
+ else
+ # Preserve the existing resolv.conf
+ if [ -e /etc/resolv.conf ] ; then
+ cp /etc/resolv.conf /etc/resolv.conf-"${dev}".sv
+ fi
+ printf "${DNS}" > /etc/resolv.conf
+ chmod 644 /etc/resolv.conf
+ fi
+ fi
+fi
+
+# Below section is Gentoo specific
+# Quick summary - our init scripts are re-entrant and set the SVCNAME env var
+# as we could have >1 openvpn service
+
+if [ -n "${SVCNAME}" ]; then
+ # If we have a service specific script, run this now
+ if [ -x /etc/openvpn/"${SVCNAME}"-up.sh ] ; then
+ /etc/openvpn/"${SVCNAME}"-up.sh "$@"
+ fi
+
+ # Re-enter the init script to start any dependant services
+ if ! /etc/init.d/"${SVCNAME}" --quiet status ; then
+ export IN_BACKGROUND=true
+ /etc/init.d/${SVCNAME} --quiet start
+ fi
+fi
+
+exit 0
+
+# vim: ts=4 :
diff --git a/main/oprofile/APKBUILD b/main/oprofile/APKBUILD
new file mode 100644
index 0000000000..78e857546c
--- /dev/null
+++ b/main/oprofile/APKBUILD
@@ -0,0 +1,47 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=oprofile
+pkgver=0.9.6
+pkgrel=2
+pkgdesc="A System Profiler for Linux"
+url="http://oprofile.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="libiconv-dev popt-dev gettext-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://prdownloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ oprofile-pic.patch"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ if [ "$CARCH" != "x86_64" ]; then
+ patch -p1 -i "$srcdir"/oprofile-pic.patch
+ fi
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-kernel-support \
+ --with-pic
+ make -j1 || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+
+ #install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/knockd
+ #install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/knockd
+}
+
+md5sums="4e407093ac06200185d5a5e6437d7242 oprofile-0.9.6.tar.gz
+e7b80603bc86f120480c3d411d532ab8 oprofile-pic.patch"
diff --git a/main/oprofile/oprofile-pic.patch b/main/oprofile/oprofile-pic.patch
new file mode 100644
index 0000000000..8867ff243a
--- /dev/null
+++ b/main/oprofile/oprofile-pic.patch
@@ -0,0 +1,49 @@
+--- oprofile-0.9.6/libop/op_hw_specific.h
++++ oprofile-0.9.6.new/libop/op_hw_specific.h
+@@ -20,7 +20,8 @@
+ char v[12];
+ } v;
+ unsigned eax;
+- asm("cpuid" : "=a" (eax), "=b" (v.b), "=c" (v.c), "=d" (v.d) : "0" (0));
++ asm("push %%ebx ; cpuid ; movl %%ebx, %%esi ; pop %%ebx"
++ : "=a" (eax), "=S" (v.b), "=c" (v.c), "=d" (v.d) : "0" (0));
+ return !strncmp(v.v, vnd, 12);
+ }
+
+@@ -46,7 +47,7 @@
+
+ if (!cpuid_vendor("GenuineIntel"))
+ return;
+- asm("cpuid" : "=a" (v.eax) : "0" (1) : "ecx","ebx","edx");
++ asm("push %%ebx; cpuid; pop %%ebx" : "=a" (v.eax) : "0" (1) : "ecx","edx");
+ model = (v.ext_model << 4) + v.model;
+ if (v.family != 6 || model != 26 || v.stepping > 4)
+ return;
+@@ -57,7 +58,8 @@
+ {
+ if (cpu_type == CPU_ARCH_PERFMON) {
+ unsigned ebx, eax;
+- asm("cpuid" : "=a" (eax), "=b" (ebx) : "0" (0xa) : "ecx","edx");
++ asm("push %%ebx; cpuid; movl %%ebx, %%edx; pop %%ebx"
++ : "=a" (eax), "=d" (ebx) : "0" (0xa) : "ecx");
+ workaround_nehalem_aaj79(&ebx);
+ return ebx & num_to_mask(eax >> 24);
+ }
+@@ -68,7 +70,7 @@
+ {
+ if (cpu_type == CPU_ARCH_PERFMON) {
+ unsigned v;
+- asm("cpuid" : "=a" (v) : "0" (0xa) : "ebx","ecx","edx");
++ asm("push %%ebx; cpuid; pop %%ebx" : "=a" (v) : "0" (0xa) : "ecx","edx");
+ return (v >> 8) & 0xff;
+ }
+ return -1;
+@@ -77,7 +79,7 @@
+ static inline unsigned arch_get_counter_mask(void)
+ {
+ unsigned v;
+- asm("cpuid" : "=a" (v) : "0" (0xa) : "ebx","ecx","edx");
++ asm("push %%ebx; cpuid; pop %%ebx" : "=a" (v) : "0" (0xa) : "ecx","edx");
+ return num_to_mask((v >> 8) & 0xff);
+ }
+
diff --git a/main/orage/APKBUILD b/main/orage/APKBUILD
new file mode 100644
index 0000000000..16e88c3941
--- /dev/null
+++ b/main/orage/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=orage
+pkgver=4.8.1
+pkgrel=0
+pkgdesc="A simple calendar application with reminders for Xfce"
+url="http://www.xfce.org/projects/orage/"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-doc"
+depends="hicolor-icon-theme"
+makedepends="pkgconfig xfce4-panel-dev libnotify-dev intltool gettext-dev
+ libiconv-dev libsm-dev expat-dev e2fsprogs-dev libxfcegui4-dev autoconf automake"
+install=
+source="http://archive.xfce.org/src/apps/orage/${pkgver%.*}/orage-$pkgver.tar.bz2"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="9c1139ce03e9f309240e712cf31b6a49 orage-4.8.1.tar.bz2"
diff --git a/main/orbit2/APKBUILD b/main/orbit2/APKBUILD
new file mode 100644
index 0000000000..fdd11204bc
--- /dev/null
+++ b/main/orbit2/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=orbit2
+pkgver=2.14.19
+pkgrel=1
+pkgdesc="CORBA implementation for GNOME"
+url="http://projects.gnome.org/ORBit2"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="glib-dev libidl-dev"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/ORBit2/${pkgver%.*}/ORBit2-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/ORBit2-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/orbit*/*.la
+}
+
+md5sums="7082d317a9573ab338302243082d10d1 ORBit2-2.14.19.tar.bz2"
diff --git a/main/orc/APKBUILD b/main/orc/APKBUILD
new file mode 100644
index 0000000000..3a20abfda8
--- /dev/null
+++ b/main/orc/APKBUILD
@@ -0,0 +1,57 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=orc
+pkgver=0.4.14
+pkgrel=0
+pkgdesc="The Oil Run-time Compiler"
+url="http://code.entropywave.com/projects/orc/"
+arch="all"
+license="BSD"
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-compiler"
+source="http://code.entropywave.com/download/orc/orc-$pkgver.tar.gz"
+
+_builddir="$srcdir"/orc-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+dev() {
+ default_dev
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/orc-bugreport "$subpkgdir"/usr/bin/
+}
+
+compiler() {
+ pkgdesc="Orc compiler"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="6b3ff209e9763ebe40e152538884bd71 orc-0.4.14.tar.gz"
diff --git a/main/osmo/APKBUILD b/main/osmo/APKBUILD
new file mode 100644
index 0000000000..80a87434e8
--- /dev/null
+++ b/main/osmo/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=osmo
+pkgver=0.2.10
+pkgrel=2
+pkgdesc="A handy personal organizer"
+url="http://clayo.org/osmo/"
+arch="all"
+license="GPL"
+makedepends="gtk+-dev libnotify-dev libical-dev libxml2-dev autoconf automake"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname-pim/$pkgname-$pkgver.tar.gz
+ osmo-0.2.10-build-mo.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ msg "Applying ${i##*/}"
+ patch -p1 -i "$i" || return 1
+ done
+ aclocal && autoconf && automake
+}
+
+build() {
+ cd "$_builddir"
+ CFLAGS="$CFLAGS -I/usr/include/libical"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="a774db748228efee96186158d553ade9 osmo-0.2.10.tar.gz
+6c9939fd4df9d25e1a220585e6875c78 osmo-0.2.10-build-mo.patch"
diff --git a/main/osmo/osmo-0.2.10-build-mo.patch b/main/osmo/osmo-0.2.10-build-mo.patch
new file mode 100644
index 0000000000..ac1b9aa235
--- /dev/null
+++ b/main/osmo/osmo-0.2.10-build-mo.patch
@@ -0,0 +1,20 @@
+diff --git a/po/Makefile.am b/po/Makefile.am
+index b3c904a..f0ee467 100644
+--- a/po/Makefile.am
++++ b/po/Makefile.am
+@@ -16,8 +16,8 @@ all: $(MOFILES)
+
+ update-po: $(DOMAIN).pot $(POFILES) $(MOFILES)
+
+-%.mo: skip
+- @po=$(@:.mo=.po); if test $$po -nt $@ ; then $(MSGFMT) -c --statistics $$po -o $@; echo "$@ updated."; fi
++%.mo: %.po
++ @$(MSGFMT) -c --statistics $^ -o $@; echo "$@ updated."
+
+ %.po: $(DOMAIN).pot
+ $(MSGMERGE) $@ $< -o $@.in && mv $@.in $@
+@@ -41,4 +41,3 @@ uninstall-local:
+ clean-local:
+ rm -rf *.mo
+
+-skip:
diff --git a/main/p7zip/APKBUILD b/main/p7zip/APKBUILD
new file mode 100644
index 0000000000..24452b0074
--- /dev/null
+++ b/main/p7zip/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=p7zip
+pkgver=9.20.1
+pkgrel=0
+pkgdesc="A command-line port of the 7zip compression utility"
+url="http://p7zip.sourceforge.net"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=
+makedepends="bash"
+#install=p7zip.install
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/${pkgname}_${pkgver}_src_all.tar.bz2
+ p7zip-cc-cxx.patch"
+
+build() {
+ cd "$srcdir"/${pkgname}_${pkgver}
+ patch -p1 -i ../p7zip-cc-cxx.patch || return 1
+ sed -i "s|usr/local|usr|g" makefile
+ make all3 OPTFLAGS="${CXXFLAGS}" || return 1
+}
+
+package() {
+ cd "$srcdir"/${pkgname}_${pkgver}
+ make install DEST_HOME="$pkgdir"/usr DEST_MAN="$pkgdir"/usr/share/man \
+ DEST_SHARE_DOC="http://www.bugaco.com/7zip"
+
+ sed -i "s|"$pkgdir"/usr|/usr|g" "$pkgdir"/usr/bin/7z
+ sed -i "s|"$pkgdir"/usr|/usr|g" "$pkgdir"/usr/bin/7za
+ sed -i "s|"$pkgdir"/usr|/usr|g" "$pkgdir"/usr/bin/7zr
+# install -m755 -D contrib/VirtualFileSystemForMidnightCommander/u7z "$pkgdir"/usr/share/mc/extfs/u7z
+}
+
+md5sums="bd6caaea567dc0d995c990c5cc883c89 p7zip_9.20.1_src_all.tar.bz2
+8e8f415267bb5db179e4a8ed75985244 p7zip-cc-cxx.patch"
diff --git a/main/p7zip/p7zip-cc-cxx.patch b/main/p7zip/p7zip-cc-cxx.patch
new file mode 100644
index 0000000000..d06708b4bb
--- /dev/null
+++ b/main/p7zip/p7zip-cc-cxx.patch
@@ -0,0 +1,22 @@
+--- a/makefile.machine 2009-05-29 07:24:22.000000000 +0000
++++ b/makefile.machine 2009-05-29 07:25:22.000000000 +0000
+@@ -2,6 +2,8 @@
+ # makefile for Linux (x86, PPC, alpha ...)
+ #
+
++CXX ?= g++
++CC ?= gcc
+ OPTFLAGS=-O
+
+ ALLFLAGS=${OPTFLAGS} -s \
+@@ -9,8 +11,8 @@
+ -DNDEBUG -D_REENTRANT -DENV_UNIX \
+ $(LOCAL_FLAGS)
+
+-CXX=g++ $(ALLFLAGS)
+-CC=gcc $(ALLFLAGS)
++CXX += $(ALLFLAGS)
++CC += $(ALLFLAGS)
+ CC_SHARED=-fPIC
+ LINK_SHARED=-fPIC -shared
+
diff --git a/main/pango/APKBUILD b/main/pango/APKBUILD
new file mode 100644
index 0000000000..fa04ea722c
--- /dev/null
+++ b/main/pango/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pango
+pkgver=1.28.4
+pkgrel=5
+pkgdesc="A library for layout and rendering of text"
+url="http://www.pango.org/"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig glib-dev cairo-dev libxft-dev gettext-dev libiconv-dev
+ expat-dev gobject-introspection-dev"
+install="pango.post-install $pkgname.pre-deinstall"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev freetype-dev fontconfig-dev libxft-dev"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/pango/*/modules/*.la
+}
+
+md5sums="3f3989700f04e9117d30544a9078b3a0 pango-1.28.4.tar.bz2"
diff --git a/main/pango/pango.post-install b/main/pango/pango.post-install
new file mode 100644
index 0000000000..15a6090db5
--- /dev/null
+++ b/main/pango/pango.post-install
@@ -0,0 +1,2 @@
+#!/bin/sh
+pango-querymodules > /etc/pango/pango.modules
diff --git a/main/pango/pango.pre-deinstall b/main/pango/pango.pre-deinstall
new file mode 100644
index 0000000000..92127b59de
--- /dev/null
+++ b/main/pango/pango.pre-deinstall
@@ -0,0 +1,2 @@
+#!/bin/sh
+rm -f /etc/pango/pango.modules
diff --git a/main/pangomm/APKBUILD b/main/pangomm/APKBUILD
new file mode 100644
index 0000000000..b9af75868a
--- /dev/null
+++ b/main/pangomm/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pangomm
+pkgver=2.28.2
+pkgrel=0
+pkgdesc="C++ bindings for pango"
+url="http://gtkmm.sourceforge.net/"
+arch="all"
+license="LGPL"
+depends=""
+makedepends="pango-dev glibmm-dev cairomm-dev"
+depends_dev="$makedepends"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/pangomm/${pkgver%.*}/pangomm-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="005a474863495d3c6267429a80da6cf2 pangomm-2.28.2.tar.bz2"
diff --git a/main/parole/APKBUILD b/main/parole/APKBUILD
new file mode 100644
index 0000000000..c38bcd26a2
--- /dev/null
+++ b/main/parole/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=parole
+pkgver=0.2.0.2
+pkgrel=3
+pkgdesc="Media player for the Xfce desktop"
+url="http://goodies.xfce.org/projects/applications/parole/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="libxfcegui4-dev libxfce4util-dev intltool gstreamer-dev bash
+ gst-plugins-base-dev libsm-dev taglib-dev libnotify-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://archive.xfce.org/src/apps/parole/0.2/parole-$pkgver.tar.bz2"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --enable-browser-plugin \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="c304b07c3f17feefe3879bacd6e54515 parole-0.2.0.2.tar.bz2"
diff --git a/main/parted/APKBUILD b/main/parted/APKBUILD
new file mode 100644
index 0000000000..28cfc37210
--- /dev/null
+++ b/main/parted/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=parted
+pkgver=2.4
+pkgrel=0
+pkgdesc="Utility to create, destroy, resize, check and copy partitions"
+url="http://www.gnu.org/software/parted/parted.html"
+arch="all"
+license="GPL3"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig e2fsprogs-dev readline-dev ncurses-dev lvm2-dev"
+source="ftp://ftp.gnu.org/pub/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-debug \
+ --disable-nls \
+ --disable-Werror
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="76a6457ea88447d79d50ca331069b19c parted-2.4.tar.gz"
diff --git a/main/parted/nocxx.patch b/main/parted/nocxx.patch
new file mode 100644
index 0000000000..beb1ab9006
--- /dev/null
+++ b/main/parted/nocxx.patch
@@ -0,0 +1,15 @@
+--- a/configure 2004-12-07 21:34:23.205172545 +0000
++++ b/configure 2004-12-07 21:37:17.726654782 +0000
+@@ -5148,10 +5148,8 @@
+ :
+ else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&5
+-echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+-See \`config.log' for more details." >&2;}
+- { (exit 1); exit 1; }; }
++See \`config.log' for more details." >&5;}
++ { echo "C++ sucks, ignoring ..." >&5; }; }
+ fi
+
+ ac_ext=cc
diff --git a/main/patch/APKBUILD b/main/patch/APKBUILD
new file mode 100644
index 0000000000..c51e3d1e5a
--- /dev/null
+++ b/main/patch/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=patch
+pkgver=2.6.1
+pkgrel=2
+pkgdesc="Utility to apply diffs to files"
+url="http://www.gnu.org/software/patch/patch.html"
+arch="all"
+license='GPL'
+depends=
+source="ftp://ftp.gnu.org/gnu/patch/patch-2.6.tar.bz2"
+subpackages="$pkgname-doc"
+install="$pkgname.post-deinstall $pkgname.post-upgrade"
+
+_builddir="$srcdir"/$pkgname-2.6
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make prefix="$pkgdir"/usr mandir="$pkgdir"/usr/share/man install
+}
+
+md5sums="5729b1430ba6c2216e0f3eb18f213c81 patch-2.6.tar.bz2"
diff --git a/main/patch/patch.post-deinstall b/main/patch/patch.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/patch/patch.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/patch/patch.post-upgrade b/main/patch/patch.post-upgrade
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/patch/patch.post-upgrade
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/pax-utils/APKBUILD b/main/pax-utils/APKBUILD
new file mode 100644
index 0000000000..30267bd0a4
--- /dev/null
+++ b/main/pax-utils/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pax-utils
+pkgver=0.2.3
+pkgrel=0
+pkgdesc="ELF related utils for ELF 32/64 binaries"
+url="http://hardened.gentoo.org/pax-utils.xml"
+arch="all"
+license='GPL-2'
+depends=
+makedepends=
+source="http://dev.gentoo.org/~vapier/dist/pax-utils-$pkgver.tar.xz"
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir/" install
+}
+
+md5sums="d2d27891742d14d81b205cf4e42de28a pax-utils-0.2.3.tar.xz"
diff --git a/main/paxctl/APKBUILD b/main/paxctl/APKBUILD
new file mode 100644
index 0000000000..820c2ec6c6
--- /dev/null
+++ b/main/paxctl/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=paxctl
+pkgver=0.5
+pkgrel=2
+pkgdesc="Manage PaX releated program header flags"
+url="http://pax.grsecurity.net"
+arch="all"
+license="GPL-2"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-doc"
+source="http://pax.grsecurity.net/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ sed -i -e 's:--owner:-o:g; s:--group:-g:g; s:--mode:-m:g' Makefile
+
+ make CFLAGS="$CFLAGS" LDFLASG="$LDFLAGS" || return 1
+ make DESTDIR="$pkgdir" install
+
+ # install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ # install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="6ec138522977dc7654d33ddbe32755f0 paxctl-0.5.tar.gz"
diff --git a/main/pciutils/APKBUILD b/main/pciutils/APKBUILD
new file mode 100644
index 0000000000..288639abb8
--- /dev/null
+++ b/main/pciutils/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=pciutils
+pkgver=3.1.7
+pkgrel=2
+pkgdesc="PCI bus configuration space access library and tools"
+url="http://mj.ucw.cz/pciutils.html"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://www.kernel.org/pub/software/utils/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ make ZLIB=no \
+ PREFIX=/usr \
+ SHAREDIR=/usr/share/hwdata \
+ MANDIR=/usr/share/man \
+ all || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make PREFIX="$pkgdir"/usr \
+ SHAREDIR="$pkgdir"/usr/share/hwdata \
+ MANDIR="$pkgdir"/usr/share/man \
+ install
+
+ install -d "$pkgdir"/usr/lib
+ install -m644 lib/libpci.a "$pkgdir"/usr/lib
+ for i in config.h header.h pci.h types.h; do
+ install -D -m 644 lib/${i} "$pkgdir"/usr/include/pci/${i}
+ done
+
+}
+
+md5sums="f3e349d22a3714b4272b171649ad5235 pciutils-3.1.7.tar.gz"
diff --git a/main/pcmciautils/APKBUILD b/main/pcmciautils/APKBUILD
new file mode 100644
index 0000000000..61fd8d7fd3
--- /dev/null
+++ b/main/pcmciautils/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pcmciautils
+pkgver=017
+pkgrel=1
+pkgdesc="Utilities for inserting and removing PCMCIA cards"
+url="http://kernel.org/pub/linux/utils/kernel/pcmcia/pcmcia.html"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=
+makedepends="sysfsutils-dev bison flex"
+source="http://kernel.org/pub/linux/utils/kernel/pcmcia/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make build/ccdv || return 1
+ make -j1 LEX=flex || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir"/ install
+ ln -sf pccardctl "$pkgdir"/sbin/lspcmcia
+}
+md5sums="5245af28eeba57ec0606a874d44d10f7 pcmciautils-017.tar.bz2"
diff --git a/main/pcre/APKBUILD b/main/pcre/APKBUILD
new file mode 100644
index 0000000000..a4ae0314c0
--- /dev/null
+++ b/main/pcre/APKBUILD
@@ -0,0 +1,51 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pcre
+pkgver=8.12
+pkgrel=1
+pkgdesc="Perl-compatible regular expression library"
+url="http://pcre.sourceforge.net"
+arch="all"
+license="BSD"
+depends=
+makedepends="autoconf automake libtool"
+source="ftp://ftp.csx.cam.ac.uk/pub/software/programming/$pkgname/$pkgname-$pkgver.tar.bz2
+ uclibc-strtoq.patch"
+subpackages="$pkgname-dev $pkgname-doc libpcrecpp"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ aclocal && autoconf && automake && libtoolize
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --enable-utf8 \
+ --enable-unicode-properties \
+ --with-match-limit-recursion=8192 \
+ --htmldir=/usr/share/doc/$pkgname-$pkgver/html \
+ --docdir=/usr/share/doc/$pkgname-$pkgver
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+libpcrecpp() {
+ pkgdesc="C++ bindings for PCRE"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libpcrecpp.so* "$subpkgdir"/usr/lib/
+}
+
+md5sums="f14a9fef3c92f3fc6c5ac92d7a2c7eb3 pcre-8.12.tar.bz2
+6276c5cdbecaa14256b50ce9a9333500 uclibc-strtoq.patch"
diff --git a/main/pcre/uclibc-strtoq.patch b/main/pcre/uclibc-strtoq.patch
new file mode 100644
index 0000000000..b1de742e38
--- /dev/null
+++ b/main/pcre/uclibc-strtoq.patch
@@ -0,0 +1,18 @@
+--- ./configure.ac.orig
++++ ./configure.ac
+@@ -361,13 +361,13 @@
+ else
+ include=stdlib.h
+ fi
+- AC_COMPILE_IFELSE(AC_LANG_PROGRAM([#include <$include>],
++ AC_LINK_IFELSE(AC_LANG_PROGRAM([#include <$include>],
+ [char* e; return $fn("100", &e, 10)]),
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED(HAVE_`echo $fn | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`, 1,
+ [Define to 1 if you have `$fn'.])
+ have_strto_fn=1
+- break],
++ ],
+ [AC_MSG_RESULT(no)])
+ done
+
diff --git a/main/pdnsd/APKBUILD b/main/pdnsd/APKBUILD
new file mode 100644
index 0000000000..cdc494cb44
--- /dev/null
+++ b/main/pdnsd/APKBUILD
@@ -0,0 +1,101 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=pdnsd
+pkgver=1.2.8
+_realver=$pkgver-par
+pkgrel=0
+pkgdesc="A proxy DNS server with permanent caching"
+url="http://www.phys.uu.nl/~rombouts/pdnsd/"
+arch="all"
+license="GPL"
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install="$pkgname.pre-install $pkgname.post-deinstall"
+subpackages="$pkgname-doc"
+pkgusers="pdnsd"
+pkggroups="pdnsd"
+source="http://www.phys.uu.nl/~rombouts/pdnsd/releases/$pkgname-$_realver.tar.gz
+ pdnsd.initd
+ pdnsd.confd
+ pdnsd.conf
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ --enable-ipv6 \
+ --with-random-device=/dev/urandom \
+ --enable-tcp-subseq \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+
+ install -m755 -D "$srcdir"/$pkgname.initd \
+ "$pkgdir"/etc/init.d/$pkgname || return 1
+ install -m644 -D "$srcdir"/$pkgname.confd \
+ "$pkgdir"/etc/conf.d/$pkgname || return 1
+ install -m644 -D "$srcdir"/$pkgname.conf \
+ "$pkgdir"/etc/$pkgname.conf || return 1
+
+ chown -R pdnsd "$pkgdir"/var/cache/pdnsd || return 1
+ sed -ri 's/([ ]*run_as=)"nobody";/\1"pdnsd";/' \
+ "$pkgdir"/etc/pdnsd.conf.sample || return 1
+ sed -ri '/pid_file/d' "$pkgdir"/etc/pdnsd.conf.sample || return 1
+ sed -ri '/query_method/d' "$pkgdir"/etc/pdnsd.conf.sample || return 1
+}
+
+doc() {
+ arch="noarch"
+
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname/html || return 1
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname/txt || return 1
+ mkdir -p "$subpkgdir"/usr/share/$pkgname/contrib || return 1
+
+ # /usr/share/{man,doc/$pkgname}
+ cp -a "$pkgdir"/usr/share/ "$subpkgdir"/usr/ || return 1
+ rm -rf "$pkgdir"/usr/share/ || return 1
+ _docs="AUTHORS COPYING COPYING.BSD ChangeLog ChangeLog.old \
+ NEWS README README.par README.par.old THANKS TODO"
+ for _doc in $_docs; do
+ cp "$_builddir"/$_doc "$subpkgdir"/usr/share/doc/$pkgname/ \
+ || return 1
+ done
+ cp -R "$_builddir"/doc/html/* \
+ "$subpkgdir"/usr/share/doc/$pkgname/html/ || return 1
+ cp -R "$_builddir"/doc/txt/* \
+ "$subpkgdir"/usr/share/doc/$pkgname/txt/ || return 1
+
+ # /usr/share/$pkgname
+ mv "$pkgdir"/etc/pdnsd.conf.sample \
+ "$subpkgdir"/usr/share/$pkgname/ || return 1
+ _contribs="README change_pdnsd_server_ip.pl dhcp2pdnsd pdnsd_dhcp.pl"
+ for _contrib in $_contribs; do
+ cp -a "$_builddir"/contrib/$_contrib \
+ "$subpkgdir"/usr/share/$pkgname/contrib/ || return 1
+ done
+}
+
+md5sums="779c5d19576e561fbf2455de435e5597 pdnsd-1.2.8-par.tar.gz
+14d6c0a1e9e552999cc4efb2c1251d98 pdnsd.initd
+4bced9066febfe33b4a527f28cfb6a48 pdnsd.confd
+f7cf4b9391b67ee421485a0c24aa8a5c pdnsd.conf"
diff --git a/main/pdnsd/pdnsd.conf b/main/pdnsd/pdnsd.conf
new file mode 100644
index 0000000000..f3e6ae4b75
--- /dev/null
+++ b/main/pdnsd/pdnsd.conf
@@ -0,0 +1,51 @@
+#
+# Default Alpine Linux pdnsd config
+#
+# See /usr/share/pdnsd/pdnsd.conf.sample and the pdnsd.conf(5) manpage,
+# both available in the pdnsd-doc package.
+#
+# Comments can begin with either '#' or '//', and entire blocks may be
+# commented out with '/*' and '*/'.
+#
+global {
+ perm_cache=2048;
+ cache_dir="/var/cache/pdnsd";
+ run_as="pdnsd";
+ server_ip = any;
+ status_ctl = on;
+# paranoid=on; # This option reduces the chance of cache poisoning
+ # but may make pdnsd less efficient, unfortunately.
+ min_ttl=15m; # Retain cached entries at least 15 minutes.
+ max_ttl=1w; # One week.
+ timeout=10; # Global timeout option (10 seconds).
+ neg_domain_pol=on;
+}
+
+server {
+ label= "googledns";
+ ip = 8.8.8.8, 8.8.4.4;
+ proxy_only=on;
+ lean_query=on;
+ timeout=4; # Server timeout; this may be much shorter
+ # that the global timeout option.
+ uptest=none;
+ interval=10m; # Check every 10 minutes.
+ purge_cache=off;
+}
+
+/*
+source {
+ owner=localhost;
+# serve_aliases=on;
+ file="/etc/hosts";
+}
+*/
+
+rr {
+ name=localhost;
+ reverse=on;
+ a=127.0.0.1;
+# a=::1;
+ owner=localhost;
+ soa=localhost,root.localhost,42,86400,900,86400,86400;
+}
diff --git a/main/pdnsd/pdnsd.confd b/main/pdnsd/pdnsd.confd
new file mode 100644
index 0000000000..8f8820c8da
--- /dev/null
+++ b/main/pdnsd/pdnsd.confd
@@ -0,0 +1,18 @@
+#
+# Specify pdnsd options here.
+#
+# -4 run in IPv4 mode
+# -6 run in IPv6 mode
+# -a autodetects IPv6 supports, falls back to IPv4
+# NOTE: IPv6 mode seems to have issues.
+# -d run in daemon mode
+# -s enables the status control socket so pdnsd-ctl can be used at run-time
+# (same as setting status_ctl=on; in the config file)
+# -t enables the TCP server thread alongside the UDP server thread
+# -mut sets the query method to 'ut': udp first, fallback to tcp
+# -c specifies the config file
+# -p specifies the pid file
+# -g enables debugging/logging output at /var/cache/pdnsd/pdnsd.debug
+# -vn where n specifies the debugging verbosity level (0-3)
+
+pdnsd_opts="-4 -d -s -t -mut -c /etc/pdnsd.conf -p /var/run/pdnsd.pid"
diff --git a/main/pdnsd/pdnsd.initd b/main/pdnsd/pdnsd.initd
new file mode 100644
index 0000000000..355163ce12
--- /dev/null
+++ b/main/pdnsd/pdnsd.initd
@@ -0,0 +1,25 @@
+#!/sbin/runscript
+
+name=pdnsd
+daemon=/usr/sbin/$name
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${name}"
+ start-stop-daemon --start --quiet \
+ --pidfile /var/run/${name}.pid \
+ --exec ${daemon} -- ${pdnsd_opts}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${name}"
+ start-stop-daemon --stop --quiet \
+ --pidfile /var/run/$name.pid \
+ --exec ${daemon}
+ eend $?
+}
diff --git a/main/pdnsd/pdnsd.post-deinstall b/main/pdnsd/pdnsd.post-deinstall
new file mode 100644
index 0000000000..f5cb9e80cb
--- /dev/null
+++ b/main/pdnsd/pdnsd.post-deinstall
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+deluser pdnsd 2>/dev/null
+exit 0
diff --git a/main/pdnsd/pdnsd.pre-install b/main/pdnsd/pdnsd.pre-install
new file mode 100644
index 0000000000..1ae14a9a5e
--- /dev/null
+++ b/main/pdnsd/pdnsd.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -S -H -h /var/cache/pdnsd -s /bin/false pdnsd 2>/dev/null
+exit 0
diff --git a/main/pekwm/APKBUILD b/main/pekwm/APKBUILD
new file mode 100644
index 0000000000..a34ffe3769
--- /dev/null
+++ b/main/pekwm/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor:
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pekwm
+pkgver=0.1.12
+pkgrel=1
+pkgdesc="Fast & Light Window Manager"
+url="http://pekwm.org/projects/pekwm"
+arch="all"
+license="GPL"
+depends=
+makedepends="libiconv-dev libx11-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://pekwm.org/projects/pekwm/files/pekwm-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="1f7f9ed32cc03f565a3ad30fd6045c1f pekwm-0.1.12.tar.gz"
diff --git a/main/perdition/APKBUILD b/main/perdition/APKBUILD
new file mode 100644
index 0000000000..6d4ce2be78
--- /dev/null
+++ b/main/perdition/APKBUILD
@@ -0,0 +1,54 @@
+# Maintainer: Leonardo Arena <rnalrd@alpinelinux.org>
+pkgname=perdition
+pkgver=1.18
+pkgrel=3
+pkgdesc="A Mail retrieval proxy"
+url="http://horms.net/projects/perdition/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="gdbm-dev openssl-dev popt-dev vanessa_adt-dev vanessa_logger-dev
+ vanessa_socket-dev"
+makedepends="$depends_dev"
+install=$pkgname.post-install
+subpackages="$pkgname-doc"
+source="http://horms.net/projects/perdition/download/$pkgver/$pkgname-$pkgver.tar.bz2"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-libtool-lock \
+ --disable-mysql \
+ --disable-odbc \
+ --disable-db \
+ --disable-pg \
+ --disable-cdb \
+ --disable-nis \
+ --disable-posix-regex \
+ --disable-ldap \
+ --disable-daemon-map
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -m755 -D ../../$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D ../../$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="df84d5fc4ab78b94a9baf17c5790ba38 perdition-1.18.tar.bz2"
diff --git a/main/perdition/perdition.confd b/main/perdition/perdition.confd
new file mode 100644
index 0000000000..7b147286eb
--- /dev/null
+++ b/main/perdition/perdition.confd
@@ -0,0 +1,50 @@
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-mail/perdition/files/perdition.confd,v 1.1 2005/01/25 18:07:46 ferdy Exp $
+
+# Run time configuration parameters for /etc/init.d/perdition
+
+# User to run perdition as
+# ( change it only if you know what you're doing )
+PERDITION_USER=perdition
+
+# Where pid files will be stored
+PIDDIR=/var/run/perdition
+
+# Command line parameters to pass to perdition when run in any mode.
+# This is in addition to any mode specific flags.
+# That is, it is in addtion to any command line options supplied
+# by POP3_FLAGS, POP3S_FLAGS, IMAP4_FLAGS or IMAP4S_FLAGS
+FLAGS="-f /etc/perdition/perdition.conf"
+
+# Run an instance of perdition in POP3 mode
+# Set to "yes" to run this instance of perdition
+# Set to any other valye to not run this instance of perdition
+POP3=yes
+
+#Command line parameters to pass to perdition when run in POP3 mode
+POP3_FLAGS=
+
+# Run an instance of perdition in POP3S mode
+# Set to "yes" to run this instance of perdition
+# Set to any other valye to not run this instance of perdition
+POP3S=no
+
+#Command line parameters to pass to perdition when run in POP3S mode
+POP3S_FLAGS=
+
+# Run an instance of perdition in IMAP4 mode
+# Set to "yes" to run this instance of perdition
+# Set to any other valye to not run this instance of perdition
+IMAP4=yes
+
+#Command line parameters to pass to perdition when run in IMAP4 mode
+IMAP4_FLAGS=
+
+# Run an instance of perdition in IMAP4S mode
+# Set to "yes" to run this instance of perdition
+# Set to any other valye to not run this instance of perdition
+IMAP4S=no
+
+#Command line parameters to pass to perdition when run in IMAP4S mode
+IMAP4S_FLAGS=
diff --git a/main/perdition/perdition.initd b/main/perdition/perdition.initd
new file mode 100644
index 0000000000..0242169c4b
--- /dev/null
+++ b/main/perdition/perdition.initd
@@ -0,0 +1,76 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-mail/perdition/files/perdition.initd,v 1.2 2008/06/10 18:28:27 dertobi123 Exp $
+
+depend() {
+ need net
+}
+
+
+check_key() {
+ if [ ! -e /etc/perdition/perdition.crt.pem ] ; then
+ einfo "No SSL keys; see man perdition to create them. Or run: "
+ einfo "$ openssl req -new -x509 -nodes -out /etc/perdition/perdition.crt.pem -keyout /etc/perdition/perdition.key.pem -days 365"
+ return 1
+ fi
+}
+
+start() {
+ if [ "${POP3}" = "yes" ]; then
+ ebegin "Starting perdition services (POP3)"
+ start-stop-daemon --quiet --start --startas /usr/sbin/perdition.pop3 -p ${PIDDIR}/pop3.pid \
+ -- ${FLAGS} ${POP3_FLAGS} -u ${PERDITION_USER} --pid_file ${PIDDIR}/pop3.pid
+ eend $?
+ fi
+
+ if [ "${POP3S}" = "yes" ]; then
+ check_key || return 1
+ ebegin "Starting perdition services (POP3S)"
+ start-stop-daemon --quiet --start --startas /usr/sbin/perdition.pop3s -p ${PIDDIR}/pop3s.pid \
+ -- ${FLAGS} ${POP3S_FLAGS} -u ${PERDITION_USER} --pid_file ${PIDDIR}/pop3s.pid
+ eend $?
+ fi
+
+ if [ "${IMAP4}" = "yes" ]; then
+ ebegin "Starting perdition services (IMAP4)"
+ start-stop-daemon --quiet --start --startas /usr/sbin/perdition.imap4 -p ${PIDDIR}/imap4.pid \
+ -- ${FLAGS} ${IMAP4_FLAGS} -u ${PERDITION_USER} --pid_file ${PIDDIR}/imap4.pid
+ eend $?
+ fi
+
+ if [ "${IMAP4S}" = "yes" ]; then
+ check_key || return 1
+ ebegin "Starting perdition services (IMAP4S)"
+ start-stop-daemon --quiet --start --startas /usr/sbin/perdition.imap4s -p ${PIDDIR}/imap4s.pid \
+ -- ${FLAGS} ${IMAP4S_FLAGS} -u ${PERDITION_USER} --pid_file ${PIDDIR}/imap4s.pid
+ eend $?
+ fi
+}
+
+
+stop() {
+ if [ "${POP3}" = "yes" ]; then
+ ebegin "Shutting down perdition services (POP3)"
+ start-stop-daemon -o --quiet --stop --pidfile ${PIDDIR}/pop3.pid
+ eend $?
+ fi
+
+ if [ "${POP3S}" = "yes" ]; then
+ ebegin "Shutting down perdition services (POP3S)"
+ start-stop-daemon -o --quiet --stop --pidfile ${PIDDIR}/pop3s.pid
+ eend $?
+ fi
+
+ if [ "${IMAP4}" = "yes" ]; then
+ ebegin "Shutting down perdition services (IMAP4)"
+ start-stop-daemon -o --quiet --stop --pidfile ${PIDDIR}/imap4.pid
+ eend $?
+ fi
+
+ if [ "${IMAP4S}" = "yes" ]; then
+ ebegin "Shutting down perdition services (IMAP4S)"
+ start-stop-daemon -o --quiet --stop --pidfile ${PIDDIR}/imap4s.pid
+ eend $?
+ fi
+}
diff --git a/main/perdition/perdition.post-install b/main/perdition/perdition.post-install
new file mode 100644
index 0000000000..b2820345e5
--- /dev/null
+++ b/main/perdition/perdition.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -h /var/run/perdition -s /bin/false -S -D perdition &>/dev/null
+chown perdition /var/run/perdition
diff --git a/main/perl-apache-session/APKBUILD b/main/perl-apache-session/APKBUILD
new file mode 100644
index 0000000000..2cdf99a1bf
--- /dev/null
+++ b/main/perl-apache-session/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-apache-session
+_pkgreal=Apache-Session
+pkgver=1.89
+pkgrel=0
+pkgdesc="A persistence framework for session data"
+url="http://search.cpan.org/dist/Apache-Session/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends="perl-test-exception perl-test-deep"
+depends="$cpandepends"
+makedepends="perl-dev perl-sub-uplevel $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CH/CHORNY/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="a21d1fbb30723e8d155c1936c7d9a37c Apache-Session-1.89.tar.gz"
diff --git a/main/perl-archive-zip/APKBUILD b/main/perl-archive-zip/APKBUILD
new file mode 100644
index 0000000000..b5e4031cfc
--- /dev/null
+++ b/main/perl-archive-zip/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-archive-zip
+_realname=Archive-Zip
+pkgver=1.30
+pkgrel=2
+pkgdesc="Provide a perl interface to ZIP archive files."
+url="http://search.cpan.org/dist/Archive-Zip/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AD/ADAMK/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="40153666e7538b410e001aa8a810e702 Archive-Zip-1.30.tar.gz"
diff --git a/main/perl-astro-suntime/APKBUILD b/main/perl-astro-suntime/APKBUILD
new file mode 100644
index 0000000000..029c6c4f0c
--- /dev/null
+++ b/main/perl-astro-suntime/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-astro-suntime
+_realname=Astro-SunTime
+pkgver=0.01
+pkgrel=2
+pkgdesc="Provides a function interface to calculate sun rise/set times."
+url="http://search.cpan.org/dist/Astro-SunTime/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev perl-time-modules"
+install=
+subpackages=""
+source="http://search.cpan.org/CPAN/authors/id/R/RO/ROBF/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+
+}
+
+md5sums="4657927a49604494bfaaa153663b90b9 Astro-SunTime-0.01.tar.gz"
diff --git a/main/perl-authen-sasl/APKBUILD b/main/perl-authen-sasl/APKBUILD
new file mode 100644
index 0000000000..f7a580d811
--- /dev/null
+++ b/main/perl-authen-sasl/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-authen-sasl
+_realname=Authen-SASL
+pkgver=2.15
+pkgrel=2
+pkgdesc="SASL Authentication framework for perl"
+url="http://search.cpan.org/dist/Authen-SASL/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl perl-digest-hmac"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GB/GBARR/Authen-SASL-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="35929abb2755cf479d548672800aebee Authen-SASL-2.15.tar.gz"
diff --git a/main/perl-cache-cache/APKBUILD b/main/perl-cache-cache/APKBUILD
new file mode 100644
index 0000000000..b06d6eb7fb
--- /dev/null
+++ b/main/perl-cache-cache/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-cache-cache
+_pkgreal=Cache-Cache
+pkgver=1.06
+pkgrel=0
+pkgdesc="Persisting data storage with timeouts"
+url="http://search.cpan.org/dist/Cache-Cache/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-error perl-digest-sha1"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JS/JSWARTZ/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="4425f44ddb138a799290802e5aad46ef Cache-Cache-1.06.tar.gz"
diff --git a/main/perl-cache-simple-timedexpiry/APKBUILD b/main/perl-cache-simple-timedexpiry/APKBUILD
new file mode 100644
index 0000000000..7d4018a866
--- /dev/null
+++ b/main/perl-cache-simple-timedexpiry/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-cache-simple-timedexpiry
+pkgver=0.27
+pkgrel=0
+pkgdesc="Cache::Simple::TimedExpiry perl module"
+url="http://search.cpan.org/dist/Cache-Simple-TimedExpiry/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JE/JESSE/Cache-Simple-TimedExpiry-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Cache-Simple-TimedExpiry-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="4ef124ab7776f3c257b9ffbed917e67a Cache-Simple-TimedExpiry-0.27.tar.gz"
diff --git a/main/perl-carp-clan/APKBUILD b/main/perl-carp-clan/APKBUILD
new file mode 100644
index 0000000000..f68bdc0244
--- /dev/null
+++ b/main/perl-carp-clan/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-carp-clan
+_realname=Carp-Clan
+pkgver=6.04
+pkgrel=2
+pkgdesc="Perl - Report errors from perspective of caller of a 'clan' of modules"
+url="http://search.cpan.org/~stbey/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl perl-test-exception"
+makedepends="perl-dev"
+install=
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/ST/STBEY/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="b6316bc51bb530d994f2784615939fb2 Carp-Clan-6.04.tar.gz"
diff --git a/main/perl-cgi-emulate-psgi/APKBUILD b/main/perl-cgi-emulate-psgi/APKBUILD
new file mode 100644
index 0000000000..db6e7f212e
--- /dev/null
+++ b/main/perl-cgi-emulate-psgi/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-cgi-emulate-psgi
+_pkgreal=CGI-Emulate-PSGI
+pkgver=0.11
+pkgrel=0
+pkgdesc="PSGI adapter for CGI"
+url="http://search.cpan.org/dist/CGI-Emulate-PSGI/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-http-message"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MI/MIYAGAWA/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="da915245e3a7b4c70c3935bf688b31b1 CGI-Emulate-PSGI-0.11.tar.gz"
diff --git a/main/perl-cgi-psgi/APKBUILD b/main/perl-cgi-psgi/APKBUILD
new file mode 100644
index 0000000000..d00f1c18d5
--- /dev/null
+++ b/main/perl-cgi-psgi/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-cgi-psgi
+_pkgreal=CGI-PSGI
+pkgver=0.15
+pkgrel=0
+pkgdesc="Adapt CGI.pm to the PSGI protocol"
+url="http://search.cpan.org/dist/CGI-PSGI/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MI/MIYAGAWA/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="58a39711add2b48229710688c5f81cfd CGI-PSGI-0.15.tar.gz"
diff --git a/main/perl-cgi-session/APKBUILD b/main/perl-cgi-session/APKBUILD
new file mode 100644
index 0000000000..f50c77c626
--- /dev/null
+++ b/main/perl-cgi-session/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-cgi-session
+_name=CGI-Session
+pkgver=4.43
+pkgrel=2
+pkgdesc="perl module for persistent session data in CGI applications"
+url="http://search.cpan.org/~markstos/CGI-Session-$pkgver/"
+arch="noarch"
+license="PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MA/MARKSTOS/CGI-Session-$pkgver.tar.gz"
+
+build () {
+ cd "$srcdir"/$_name-$pkgver
+ perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make MAN1EXT=1p MAN3EXT=3pm || return 1
+}
+
+package() {
+ cd "$srcdir"/$_name-$pkgver
+ make install MAN1EXT=1p MAN3EXT=3pm DESTDIR="$pkgdir" || return 1
+ find "$pkgdir" -name perllocal.pod -delete
+ find "$pkgdir" -name .packlist -delete
+}
+md5sums="3ac7f31d5d2e11e28cc75c78d5042382 CGI-Session-4.43.tar.gz"
diff --git a/main/perl-class-accessor-chained/APKBUILD b/main/perl-class-accessor-chained/APKBUILD
new file mode 100644
index 0000000000..d4b6419965
--- /dev/null
+++ b/main/perl-class-accessor-chained/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-class-accessor-chained
+_pkgreal=Class-Accessor-Chained
+pkgver=0.01
+pkgrel=0
+pkgdesc="make chained accessors"
+url="http://search.cpan.org/dist/Class-Accessor-Chained/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-class-accessor"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RC/RCLAMP/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="9825a1f30a70e55e61bb5660b2bd7365 Class-Accessor-Chained-0.01.tar.gz"
diff --git a/main/perl-class-accessor-lite/APKBUILD b/main/perl-class-accessor-lite/APKBUILD
new file mode 100644
index 0000000000..6775c73353
--- /dev/null
+++ b/main/perl-class-accessor-lite/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-class-accessor-lite
+_pkgreal=Class-Accessor-Lite
+pkgver=0.05
+pkgrel=0
+pkgdesc="a minimalistic variant of Class::Accessor"
+url="http://search.cpan.org/dist/Class-Accessor-Lite/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/K/KA/KAZUHO/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="c487f0ebe2038363b68e9e68ae4beb54 Class-Accessor-Lite-0.05.tar.gz"
diff --git a/main/perl-class-accessor/APKBUILD b/main/perl-class-accessor/APKBUILD
new file mode 100644
index 0000000000..bbe0e6916e
--- /dev/null
+++ b/main/perl-class-accessor/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-class-accessor
+pkgver=0.34
+pkgrel=0
+pkgdesc="Class::Accessor perl module"
+url="http://search.cpan.org/dist/Class-Accessor/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/K/KA/KASEI/Class-Accessor-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Class-Accessor-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="0d9640d237a13276145f7e44b4855b89 Class-Accessor-0.34.tar.gz"
diff --git a/main/perl-class-container/APKBUILD b/main/perl-class-container/APKBUILD
new file mode 100644
index 0000000000..2254ad500d
--- /dev/null
+++ b/main/perl-class-container/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-class-container
+_pkgreal=Class-Container
+pkgver=0.12
+pkgrel=0
+pkgdesc="Glues object frameworks together transparently"
+url="http://search.cpan.org/dist/Class-Container/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-params-validate"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/K/KW/KWILLIAMS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="6896bdb4464b96ad638e22b0400acbc9 Class-Container-0.12.tar.gz"
diff --git a/main/perl-class-data-inheritable/APKBUILD b/main/perl-class-data-inheritable/APKBUILD
new file mode 100644
index 0000000000..4494b39bf8
--- /dev/null
+++ b/main/perl-class-data-inheritable/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-class-data-inheritable
+_pkgreal=Class-Data-Inheritable
+pkgver=0.08
+pkgrel=0
+pkgdesc="Inheritable, overridable class data"
+url="http://search.cpan.org/dist/Class-Data-Inheritable/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/T/TM/TMTM/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="fc0fe65926eb8fb932743559feb54eb9 Class-Data-Inheritable-0.08.tar.gz"
diff --git a/main/perl-class-inspector/APKBUILD b/main/perl-class-inspector/APKBUILD
new file mode 100644
index 0000000000..f29ea6c236
--- /dev/null
+++ b/main/perl-class-inspector/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-class-inspector
+pkgver=1.25
+pkgrel=0
+pkgdesc="Class::Inspector perl module"
+url="http://search.cpan.org/dist/Class-Inspector/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AD/ADAMK/Class-Inspector-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Class-Inspector-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="5830bff10a0966993edd14435b8a579b Class-Inspector-1.25.tar.gz"
diff --git a/main/perl-class-load/APKBUILD b/main/perl-class-load/APKBUILD
new file mode 100644
index 0000000000..0591ca7763
--- /dev/null
+++ b/main/perl-class-load/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-class-load
+pkgver=0.06
+pkgrel=0
+pkgdesc="Class::Load perl module"
+url="http://search.cpan.org/dist/Class-Load/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-test-fatal"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SA/SARTAK/Class-Load-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Class-Load-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="5aea2e7c66e69dafdbfedc00e93f9f46 Class-Load-0.06.tar.gz"
diff --git a/main/perl-class-returnvalue/APKBUILD b/main/perl-class-returnvalue/APKBUILD
new file mode 100644
index 0000000000..58da67941a
--- /dev/null
+++ b/main/perl-class-returnvalue/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-class-returnvalue
+pkgver=0.55
+pkgrel=0
+pkgdesc="Class::ReturnValue perl module"
+url="http://search.cpan.org/dist/Class-ReturnValue/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-devel-stacktrace"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JE/JESSE/Class-ReturnValue-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Class-ReturnValue-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="047fbbcfd90d5c399a1feba55781329e Class-ReturnValue-0.55.tar.gz"
diff --git a/main/perl-class-singleton/APKBUILD b/main/perl-class-singleton/APKBUILD
new file mode 100644
index 0000000000..3305f058b9
--- /dev/null
+++ b/main/perl-class-singleton/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-class-singleton
+pkgver=1.4
+pkgrel=0
+pkgdesc="Class::Singleton perl module"
+url="http://search.cpan.org/dist/Class-Singleton/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AB/ABW/Class-Singleton-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Class-Singleton-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="a18b108ab97e2107cbbe816d2b3e2ee3 Class-Singleton-1.4.tar.gz"
diff --git a/main/perl-clone/APKBUILD b/main/perl-clone/APKBUILD
new file mode 100644
index 0000000000..c7233a2bb4
--- /dev/null
+++ b/main/perl-clone/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-clone
+pkgver=0.31
+pkgrel=0
+pkgdesc="Clone perl module"
+url="http://search.cpan.org/dist/Clone/"
+arch="all"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RD/RDF/Clone-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Clone-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="65f34e7280d7b7dfb72ab6224e5767f5 Clone-0.31.tar.gz"
diff --git a/main/perl-compress-raw-bzip2/APKBUILD b/main/perl-compress-raw-bzip2/APKBUILD
new file mode 100644
index 0000000000..b9fec1bdfa
--- /dev/null
+++ b/main/perl-compress-raw-bzip2/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-compress-raw-bzip2
+_realname=Compress-Raw-Bzip2
+pkgver=2.035
+pkgrel=2
+pkgdesc="Perl low-level interface to bzip2 compression library"
+url="http://search.cpan.org/~pmqs/Compress-Raw-Bzip2-2.024/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PM/PMQS/${_realname}-${pkgver}.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ #PERL_MM_USE_DEFAULT=1 perl Makefile.PL || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="573c84ca4c7f8b3dd42bdea7a7bc5c6a Compress-Raw-Bzip2-2.035.tar.gz"
diff --git a/main/perl-compress-raw-zlib/APKBUILD b/main/perl-compress-raw-zlib/APKBUILD
new file mode 100644
index 0000000000..2289a665c6
--- /dev/null
+++ b/main/perl-compress-raw-zlib/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-compress-raw-zlib
+_realname=Compress-Raw-Zlib
+pkgver=2.035
+pkgrel=2
+pkgdesc="Perl low-level interface to zlib compression library"
+url="http://search.cpan.org/~pmqs/Compress-Raw-Zlib-2.024/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PM/PMQS/${_realname}-${pkgver}.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ #PERL_MM_USE_DEFAULT=1 perl Makefile.PL || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="5227d642c11c413270414d5a04773c33 Compress-Raw-Zlib-2.035.tar.gz"
diff --git a/main/perl-control-x10/APKBUILD b/main/perl-control-x10/APKBUILD
new file mode 100644
index 0000000000..094b46563f
--- /dev/null
+++ b/main/perl-control-x10/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-control-x10
+_realname=ControlX10-CM11
+pkgver=2.09
+pkgrel=1
+pkgdesc="Perl extension for X10 'ActiveHome' Controller"
+url="http://search.cpan.org/~bbirth/ControlX10-CM11-2.09/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/B/BB/BBIRTH/$_realname-$pkgver.tar.gz"
+_builddir="$srcdir/$_realname-$pkgver"
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+md5sums="b59c85e92eae2c14ffa63af7ac0a1d9a ControlX10-CM11-2.09.tar.gz"
diff --git a/main/perl-convert-binhex/APKBUILD b/main/perl-convert-binhex/APKBUILD
new file mode 100644
index 0000000000..6d502a4cd7
--- /dev/null
+++ b/main/perl-convert-binhex/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-convert-binhex
+_realname=Convert-BinHex
+pkgver=1.119
+pkgrel=2
+pkgdesc="Extract data from Macintosh BinHex files"
+url="http://search.cpan.org/~eryq/Convert-BinHex-1.119/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/E/ER/ERYQ/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="ba70ad1772abac6270078f28197a7961 Convert-BinHex-1.119.tar.gz"
diff --git a/main/perl-convert-color/APKBUILD b/main/perl-convert-color/APKBUILD
new file mode 100644
index 0000000000..7dcb373b38
--- /dev/null
+++ b/main/perl-convert-color/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-convert-color
+_pkgreal=Convert-Color
+pkgver=0.08
+pkgrel=0
+pkgdesc="color space conversions and named lookups"
+url="http://search.cpan.org/dist/Convert-Color/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-list-utilsby"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PE/PEVANS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="4be0690e0a0011e56a75f967ac9ab7df Convert-Color-0.08.tar.gz"
diff --git a/main/perl-convert-tnef/APKBUILD b/main/perl-convert-tnef/APKBUILD
new file mode 100644
index 0000000000..ba8aeb3bdc
--- /dev/null
+++ b/main/perl-convert-tnef/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-convert-tnef
+_realname=Convert-TNEF
+pkgver=0.17
+pkgrel=2
+pkgdesc="Perl module to read TNEF files"
+url="http://search.cpan.org/~dougw/Convert-TNEF-0.17/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DO/DOUGW/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="31cddf42fae9495b4a686b17ec68d7e0 Convert-TNEF-0.17.tar.gz"
diff --git a/main/perl-convert-uulib/APKBUILD b/main/perl-convert-uulib/APKBUILD
new file mode 100644
index 0000000000..0d3ea16624
--- /dev/null
+++ b/main/perl-convert-uulib/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-convert-uulib
+_realname=Convert-UUlib
+pkgver=1.12
+pkgrel=3
+pkgdesc="Perl interface to the uulib library"
+url="http://search.cpan.org/~mlehmann/Convert-UUlib-1.12/UUlib.pm"
+arch="all"
+license="Artistic GPL2"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/ML/MLEHMANN/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="360d29db09aa7692d8873b336b7ec9d7 Convert-UUlib-1.12.tar.gz"
diff --git a/main/perl-crypt-openssl-random/APKBUILD b/main/perl-crypt-openssl-random/APKBUILD
new file mode 100644
index 0000000000..f1d932d9cb
--- /dev/null
+++ b/main/perl-crypt-openssl-random/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-crypt-openssl-random
+_realname=Crypt-OpenSSL-Random
+pkgver=0.04
+pkgrel=4
+pkgdesc="RSA encoding and decoding, using the openSSL libraries"
+url="http://search.cpan.org/~iroberts/Crypt-OpenSSL-Random-0.04/"
+arch="all"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev openssl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/I/IR/IROBERTS/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="c56ac5dbdd46122eb9b8da59613b7b0a Crypt-OpenSSL-Random-0.04.tar.gz"
diff --git a/main/perl-crypt-openssl-rsa/APKBUILD b/main/perl-crypt-openssl-rsa/APKBUILD
new file mode 100644
index 0000000000..a0e54667c7
--- /dev/null
+++ b/main/perl-crypt-openssl-rsa/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-crypt-openssl-rsa
+_realname=Crypt-OpenSSL-RSA
+pkgver=0.26
+pkgrel=4
+pkgdesc="RSA encoding and decoding, using the openSSL libraries"
+url="http://search.cpan.org/~iroberts/Crypt-OpenSSL-RSA-0.25/"
+arch="all"
+license="Unknown"
+depends="perl perl-crypt-openssl-random"
+makedepends="perl-dev openssl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/I/IR/IROBERTS/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="baf875f01ee39b88335b8f0962fe4bbc Crypt-OpenSSL-RSA-0.26.tar.gz"
diff --git a/main/perl-css-squish/APKBUILD b/main/perl-css-squish/APKBUILD
new file mode 100644
index 0000000000..d599cd688b
--- /dev/null
+++ b/main/perl-css-squish/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-css-squish
+pkgver=0.10
+pkgrel=0
+pkgdesc="CSS::Squish perl module"
+url="http://search.cpan.org/dist/CSS-Squish/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-uri perl-test-longstring"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/T/TS/TSIBLEY/CSS-Squish-$pkgver.tar.gz"
+
+_builddir="$srcdir"/CSS-Squish-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="59f8e2c26a2a89418d2274e8ca44ae97 CSS-Squish-0.10.tar.gz"
diff --git a/main/perl-data-ical/APKBUILD b/main/perl-data-ical/APKBUILD
new file mode 100644
index 0000000000..0286f1ace8
--- /dev/null
+++ b/main/perl-data-ical/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-data-ical
+_pkgreal=Data-ICal
+pkgver=0.16
+pkgrel=0
+pkgdesc="Generates iCalendar (RFC 2445) calendar files"
+url="http://search.cpan.org/dist/Data-ICal/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-test-warn perl-text-vfile-asdata perl-class-returnvalue perl-test-longstring perl-test-nowarnings perl-class-accessor"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AL/ALEXMV/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="12430864424a7bfe77e5d62a083f792c Data-ICal-0.16.tar.gz"
diff --git a/main/perl-data-optlist/APKBUILD b/main/perl-data-optlist/APKBUILD
new file mode 100644
index 0000000000..573b3c51ef
--- /dev/null
+++ b/main/perl-data-optlist/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-data-optlist
+pkgver=0.107
+pkgrel=0
+pkgdesc="Data::OptList perl module"
+url="http://search.cpan.org/dist/Data-OptList/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-params-util perl-sub-install"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/Data-OptList-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Data-OptList-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="17177b3cfb8941780a8736f9b9b30421 Data-OptList-0.107.tar.gz"
diff --git a/main/perl-date-calc/APKBUILD b/main/perl-date-calc/APKBUILD
new file mode 100644
index 0000000000..7bdb27ddd4
--- /dev/null
+++ b/main/perl-date-calc/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-date-calc
+_realname=Date-Calc
+pkgver=6.3
+pkgrel=2
+pkgdesc="Perl module for Gregorian calendar date calculations"
+url="http://search.cpan.org/~jaslong/Mail-DKIM-0.36/"
+arch="noarch"
+license="Perl Artistic GPL"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/ST/STBEY/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install UNINST=1
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="9b64555b7051c1beb6b61daead2d01b3 Date-Calc-6.3.tar.gz"
diff --git a/main/perl-date-format/APKBUILD b/main/perl-date-format/APKBUILD
new file mode 100644
index 0000000000..4a75d83fec
--- /dev/null
+++ b/main/perl-date-format/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-date-format
+_realname=TimeDate
+pkgver=1.20
+pkgrel=2
+pkgdesc="Perl - Date formating subroutines"
+url="http://search.cpan.org/~gbarr/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl"
+makedepends="perl-dev"
+install=
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GB/GBARR/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="7da7452bce4c684e4238e6d09b390200 TimeDate-1.20.tar.gz"
diff --git a/main/perl-date-manip/APKBUILD b/main/perl-date-manip/APKBUILD
new file mode 100644
index 0000000000..6ab42f904a
--- /dev/null
+++ b/main/perl-date-manip/APKBUILD
@@ -0,0 +1,35 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-date-manip
+_realname=Date-Manip
+pkgver=6.23
+pkgrel=0
+pkgdesc="Perl - Date manipulation routines"
+url="http://search.cpan.org/~sbeck/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl perl-test-pod perl-test-inter perl-yaml-syck perl-test-pod-coverage"
+makedepends="perl-dev"
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SB/SBECK/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ perl Build.PL || return 1
+ ./Build test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ ./Build destdir="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="e00c4c5758ac3692db99422e7c389675 Date-Manip-6.23.tar.gz"
diff --git a/main/perl-datetime-format-mail/APKBUILD b/main/perl-datetime-format-mail/APKBUILD
new file mode 100644
index 0000000000..f5c3edef0b
--- /dev/null
+++ b/main/perl-datetime-format-mail/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-datetime-format-mail
+pkgver=0.3001
+pkgrel=0
+pkgdesc="DateTime::Format::Mail perl module"
+url="http://search.cpan.org/dist/DateTime-Format-Mail/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-datetime perl-params-validate"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DROLSKY/DateTime-Format-Mail-$pkgver.tar.gz"
+
+_builddir="$srcdir"/DateTime-Format-Mail-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="15e36249e866463bd0237262a8e43b16 DateTime-Format-Mail-0.3001.tar.gz"
diff --git a/main/perl-datetime-format-w3cdtf/APKBUILD b/main/perl-datetime-format-w3cdtf/APKBUILD
new file mode 100644
index 0000000000..a9acf1839c
--- /dev/null
+++ b/main/perl-datetime-format-w3cdtf/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-datetime-format-w3cdtf
+pkgver=0.06
+pkgrel=0
+pkgdesc="DateTime::Format::W3CDTF perl module"
+url="http://search.cpan.org/dist/DateTime-Format-W3CDTF/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-datetime"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GW/GWILLIAMS/DateTime-Format-W3CDTF-$pkgver.tar.gz"
+
+_builddir="$srcdir"/DateTime-Format-W3CDTF-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="7eb2a90b78e7e2232eddbd6dd6758a23 DateTime-Format-W3CDTF-0.06.tar.gz"
diff --git a/main/perl-datetime-locale/APKBUILD b/main/perl-datetime-locale/APKBUILD
new file mode 100644
index 0000000000..b85e2baceb
--- /dev/null
+++ b/main/perl-datetime-locale/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-datetime-locale
+pkgver=0.45
+pkgrel=0
+pkgdesc="DateTime::Locale perl module"
+url="http://search.cpan.org/dist/DateTime-Locale/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-list-moreutils perl-params-validate"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DROLSKY/DateTime-Locale-$pkgver.tar.gz"
+
+_builddir="$srcdir"/DateTime-Locale-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="8ba6a4b70f8fa7d987529c2e2c708862 DateTime-Locale-0.45.tar.gz"
diff --git a/main/perl-datetime-timezone/APKBUILD b/main/perl-datetime-timezone/APKBUILD
new file mode 100644
index 0000000000..0f1647a800
--- /dev/null
+++ b/main/perl-datetime-timezone/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-datetime-timezone
+pkgver=1.34
+pkgrel=0
+pkgdesc="DateTime::TimeZone perl module"
+url="http://search.cpan.org/dist/DateTime-TimeZone/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-class-load perl-params-validate perl-class-singleton"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DROLSKY/DateTime-TimeZone-$pkgver.tar.gz"
+
+_builddir="$srcdir"/DateTime-TimeZone-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="08a5951bcb1513c66daadd055e840f9d DateTime-TimeZone-1.34.tar.gz"
diff --git a/main/perl-datetime/APKBUILD b/main/perl-datetime/APKBUILD
new file mode 100644
index 0000000000..6410ab936d
--- /dev/null
+++ b/main/perl-datetime/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-datetime
+pkgver=0.70
+pkgrel=0
+pkgdesc="DateTime perl module"
+url="http://search.cpan.org/dist/DateTime/"
+arch="all"
+license="GPLv2 or Artistic"
+depends="perl perl-datetime-locale perl-test-exception perl-math-round
+ perl-datetime-timezone"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DROLSKY/DateTime-$pkgver.tar.gz"
+
+_builddir="$srcdir"/DateTime-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ unset CFLAGS
+ perl Build.PL installdirs=vendor || return 1
+ ./Build
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir"
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="228a3ca93b49e308fc7a3b7a47341ab3 DateTime-0.70.tar.gz"
diff --git a/main/perl-db/APKBUILD b/main/perl-db/APKBUILD
new file mode 100644
index 0000000000..7f8b06a897
--- /dev/null
+++ b/main/perl-db/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-db
+_realname=BerkeleyDB
+pkgver=0.43
+pkgrel=1
+pkgdesc="Perl extension for Berkeley DB version 2, 3 or 4"
+url="http://search.cpan.org/~pmqs/BerkeleyDB-0.38/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev db-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PM/PMQS/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="3d0cf0651ed8cd3fc36e328d5924a1e9 BerkeleyDB-0.43.tar.gz"
diff --git a/main/perl-db_file/APKBUILD b/main/perl-db_file/APKBUILD
new file mode 100644
index 0000000000..ba6875bfb0
--- /dev/null
+++ b/main/perl-db_file/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-db_file
+_realname=DB_File
+pkgver=1.821
+pkgrel=1
+pkgdesc="Perl5 access to Berkeley DB"
+url="http://search.cpan.org/~pmqs/DB_File-1.820/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev db-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PM/PMQS/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="aa1aa1b3bdf5e6507b04cc8522dcd1fb DB_File-1.821.tar.gz"
diff --git a/main/perl-dbd-mysql/APKBUILD b/main/perl-dbd-mysql/APKBUILD
new file mode 100644
index 0000000000..5b6d443e5f
--- /dev/null
+++ b/main/perl-dbd-mysql/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Jeff Bilyk <jbilyk at gmail>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-dbd-mysql
+_realpkgname=DBD-mysql
+pkgver=4.019
+pkgrel=0
+pkgdesc="Perl CPAN DBD::Mysql module"
+url="http://search.cpan.org/~capttofu/DBD-mysql/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl perl-dbi"
+makedepends="perl perl-dev mysql-dev zlib-dev"
+source="http://search.cpan.org/CPAN/authors/id/C/CA/CAPTTOFU/DBD-mysql-$pkgver.tar.gz"
+
+_builddir="$srcdir"/${_realpkgname}-$pkgver
+
+prepare() {
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="566d98ab8ffac9626a31f6f6d455558e DBD-mysql-4.019.tar.gz"
diff --git a/main/perl-dbd-pg/APKBUILD b/main/perl-dbd-pg/APKBUILD
new file mode 100644
index 0000000000..2b28d96f47
--- /dev/null
+++ b/main/perl-dbd-pg/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-dbd-pg
+_pkgreal=DBD-Pg
+pkgver=2.18.1
+pkgrel=0
+pkgdesc="PostgreSQL database driver for the DBI module"
+url="http://search.cpan.org/dist/DBD-Pg/"
+arch="all"
+license="GPL PerlArtistic"
+cpandepends="perl-dbi"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev postgresql-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/T/TU/TURNSTEP/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="1f4a837b3d79789ad6854443fce7a901 DBD-Pg-2.18.1.tar.gz"
diff --git a/main/perl-dbd-sqlite/APKBUILD b/main/perl-dbd-sqlite/APKBUILD
new file mode 100644
index 0000000000..02a5ade6c6
--- /dev/null
+++ b/main/perl-dbd-sqlite/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Jeff Bilyk <jbilyk at gmail>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-dbd-sqlite
+_realpkgname=DBD-SQLite
+pkgver=1.31
+pkgrel=1
+pkgdesc="Perl CPAN DBD::SQLite module"
+url="http://search.cpan.org/dist/${_realpkgname}"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl-dbi"
+makedepends="perl perl-dev"
+source="http://search.cpan.org/CPAN/authors/id/A/AD/ADAMK/${_realpkgname}-$pkgver.tar.gz"
+
+_builddir="$srcdir"/${_realpkgname}-$pkgver
+
+prepare() {
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="67b3575104efd606c8093bc416e3338d DBD-SQLite-1.31.tar.gz"
diff --git a/main/perl-dbi/APKBUILD b/main/perl-dbi/APKBUILD
new file mode 100644
index 0000000000..54b42866d6
--- /dev/null
+++ b/main/perl-dbi/APKBUILD
@@ -0,0 +1,35 @@
+# Contributor: Jeff Bilyk <jbilyk at gmail>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-dbi
+_realpkgname=DBI
+pkgver=1.616
+pkgrel=1
+pkgdesc="Database independent interface for Perl"
+url="http://search.cpan.org/dist/${_realpkgname}"
+arch="all"
+license="GPL PerlArtistic"
+depends=
+makedepends="perl perl-dev"
+subpackages="$pkgname-doc"
+source="http://www.cpan.org/authors/id/T/TI/TIMB/${_realpkgname}-$pkgver.tar.gz"
+
+_builddir="$srcdir"/${_realpkgname}-$pkgver
+
+prepare() {
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="799313e54a693beb635b47918458f7c4 DBI-1.616.tar.gz"
diff --git a/main/perl-dbix-dbschema/APKBUILD b/main/perl-dbix-dbschema/APKBUILD
new file mode 100644
index 0000000000..c5b8717d8a
--- /dev/null
+++ b/main/perl-dbix-dbschema/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-dbix-dbschema
+pkgver=0.39
+pkgrel=0
+pkgdesc="DBIx::DBSchema perl module"
+url="http://search.cpan.org/dist/DBIx-DBSchema/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-dbi"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/I/IV/IVAN/DBIx-DBSchema-$pkgver.tar.gz"
+
+_builddir="$srcdir"/DBIx-DBSchema-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="532a5cfa5bac9f947ef9b960b915a88f DBIx-DBSchema-0.39.tar.gz"
diff --git a/main/perl-dbix-searchbuilder/APKBUILD b/main/perl-dbix-searchbuilder/APKBUILD
new file mode 100644
index 0000000000..c1577981a2
--- /dev/null
+++ b/main/perl-dbix-searchbuilder/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-dbix-searchbuilder
+pkgver=1.59
+pkgrel=0
+pkgdesc="DBIx::SearchBuilder perl module"
+url="http://search.cpan.org/dist/DBIx-SearchBuilder/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-dbd-sqlite perl-want perl-class-returnvalue perl-clone
+ perl-cache-simple-timedexpiry perl-class-accessor perl-dbix-dbschema"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RU/RUZ/DBIx-SearchBuilder-$pkgver.tar.gz"
+
+_builddir="$srcdir"/DBIx-SearchBuilder-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="70a4b780fb569f71e3631bd79cebe12e DBIx-SearchBuilder-1.59.tar.gz"
diff --git a/main/perl-devel-globaldestruction/APKBUILD b/main/perl-devel-globaldestruction/APKBUILD
new file mode 100644
index 0000000000..e2ffb543ef
--- /dev/null
+++ b/main/perl-devel-globaldestruction/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-devel-globaldestruction
+pkgver=0.03
+pkgrel=0
+pkgdesc="Devel::GlobalDestruction perl module"
+url="http://search.cpan.org/dist/Devel-GlobalDestruction/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-scope-guard perl-sub-exporter"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/F/FL/FLORA/Devel-GlobalDestruction-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Devel-GlobalDestruction-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="09b70f95536464d8901675f230fbc3aa Devel-GlobalDestruction-0.03.tar.gz"
diff --git a/main/perl-devel-stacktrace-ashtml/APKBUILD b/main/perl-devel-stacktrace-ashtml/APKBUILD
new file mode 100644
index 0000000000..077c6a7cba
--- /dev/null
+++ b/main/perl-devel-stacktrace-ashtml/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-devel-stacktrace-ashtml
+pkgver=0.11
+pkgrel=0
+pkgdesc="Devel::StackTrace::AsHTML perl module"
+url="http://search.cpan.org/dist/Devel-StackTrace-AsHTML/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-devel-stacktrace"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MI/MIYAGAWA/Devel-StackTrace-AsHTML-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Devel-StackTrace-AsHTML-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="46ff8282d671f63e6a5f48bf45d86bbb Devel-StackTrace-AsHTML-0.11.tar.gz"
diff --git a/main/perl-devel-stacktrace/APKBUILD b/main/perl-devel-stacktrace/APKBUILD
new file mode 100644
index 0000000000..6e4ce6df11
--- /dev/null
+++ b/main/perl-devel-stacktrace/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+pkgname=perl-devel-stacktrace
+_pkgreal=Devel-StackTrace
+pkgver=1.27
+pkgrel=1
+pkgdesc="A Perl object representing a stack trace"
+url="http://search.cpan.org/dist/Devel-StackTrace/"
+arch="noarch"
+license="Artistic-2"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DROLSKY/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="72ba07f2dc0331d8ce3c028cc66cf20d Devel-StackTrace-1.27.tar.gz"
diff --git a/main/perl-devel-symdump/APKBUILD b/main/perl-devel-symdump/APKBUILD
new file mode 100644
index 0000000000..026e59b710
--- /dev/null
+++ b/main/perl-devel-symdump/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-devel-symdump
+_realname=Devel-Symdump
+pkgver=2.08
+pkgrel=2
+pkgdesc="Perl - Dump symbol names or the symbol table"
+url="http://search.cpan.org/~andk/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl perl-test-pod"
+makedepends="perl-dev"
+install=
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AN/ANDK/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="68e3a2f2f989bff295ee63aed5a2a1e5 Devel-Symdump-2.08.tar.gz"
diff --git a/main/perl-device-serialport/APKBUILD b/main/perl-device-serialport/APKBUILD
new file mode 100644
index 0000000000..308c2fdc2c
--- /dev/null
+++ b/main/perl-device-serialport/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-device-serialport
+_realname=Device-SerialPort
+pkgver=1.04
+pkgrel=2
+pkgdesc="Linux/POSIX emulation of Win32::SerialPort functions."
+url="http://search.cpan.org/~cook/"
+arch="x86 x86_64"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages=""
+source="http://search.cpan.org/CPAN/authors/id/C/CO/COOK/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+
+}
+
+md5sums="82c698151f934eb28c65d1838cee7d9e Device-SerialPort-1.04.tar.gz"
diff --git a/main/perl-digest-hmac/APKBUILD b/main/perl-digest-hmac/APKBUILD
new file mode 100644
index 0000000000..c9e435065a
--- /dev/null
+++ b/main/perl-digest-hmac/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-digest-hmac
+_realname=Digest-HMAC
+pkgver=1.02
+pkgrel=2
+pkgdesc="Keyed-Hashing for Message Authentication Perl module"
+url="http://search.cpan.org/~gaas/Digest-HMAC-1.01/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl perl-digest-sha1"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_realname-$pkgver
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="64c4b247d83cd64ec32aa22bf58a709b Digest-HMAC-1.02.tar.gz"
diff --git a/main/perl-digest-sha1/APKBUILD b/main/perl-digest-sha1/APKBUILD
new file mode 100644
index 0000000000..da58588cc9
--- /dev/null
+++ b/main/perl-digest-sha1/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-digest-sha1
+_realname=Digest-SHA1
+pkgver=2.13
+pkgrel=2
+pkgdesc="Perl interface to the SHA-1 algorithm"
+url="http://search.cpan.org/~gaas/Digest-SHA1-2.12/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="bd22388f268434f2b24f64e28bf1aa35 Digest-SHA1-2.13.tar.gz"
diff --git a/main/perl-email-address/APKBUILD b/main/perl-email-address/APKBUILD
new file mode 100644
index 0000000000..d35e7a595f
--- /dev/null
+++ b/main/perl-email-address/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-email-address
+pkgver=1.892
+pkgrel=0
+pkgdesc="RFC 2822 Address Parsing and Creation"
+url="http://search.cpan.org/dist/Email-Address/"
+arch="noarch"
+license="GPL+ or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/Email-Address-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Email-Address-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="047e982b0ab7434406a32759164bfe1e Email-Address-1.892.tar.gz"
diff --git a/main/perl-email-date-format/APKBUILD b/main/perl-email-date-format/APKBUILD
new file mode 100644
index 0000000000..b35b77ca53
--- /dev/null
+++ b/main/perl-email-date-format/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor:
+# Maintainer:
+pkgname=perl-email-date-format
+_pkgreal=Email-Date-Format
+pkgver=1.002
+pkgrel=0
+pkgdesc="produce RFC 8822 date strings"
+url="http://search.cpan.org/dist/Email-Date-Format/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="7ae25275da6ab272aa8b40141eac9f82 Email-Date-Format-1.002.tar.gz"
diff --git a/main/perl-encode-locale/APKBUILD b/main/perl-encode-locale/APKBUILD
new file mode 100644
index 0000000000..8f3681577a
--- /dev/null
+++ b/main/perl-encode-locale/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-encode-locale
+_realname=Encode-Locale
+pkgver=1.02
+pkgrel=0
+pkgdesc="Perl module - Determine the locale encoding"
+url="http://search.cpan.org/~gaas"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="96a950ee9b57e47e2b990b4c5dd7bf6e Encode-Locale-1.02.tar.gz"
diff --git a/main/perl-error/APKBUILD b/main/perl-error/APKBUILD
new file mode 100644
index 0000000000..229ff7a126
--- /dev/null
+++ b/main/perl-error/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-error
+_realname=Error
+pkgver=0.17016
+pkgrel=2
+pkgdesc="Perl module error/exception handling in an OO-ish way"
+url="http://search.cpan.org/~shlomif/Error-$pkgver/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SH/SHLOMIF/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_realname-$pkgver
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="eedcd3c6970568dd32092b5334328eff Error-0.17016.tar.gz"
diff --git a/main/perl-exception-class/APKBUILD b/main/perl-exception-class/APKBUILD
new file mode 100644
index 0000000000..2bedac2a58
--- /dev/null
+++ b/main/perl-exception-class/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-exception-class
+_pkgreal=Exception-Class
+pkgver=1.32
+pkgrel=0
+pkgdesc="A module that allows you to declare real exception classes in Perl"
+url="http://search.cpan.org/dist/Exception-Class/"
+arch="noarch"
+license="Artistic-2"
+cpandepends="perl-class-data-inheritable perl-devel-stacktrace"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DROLSKY/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="83788ad5a2c5e946877e4ec362e19622 Exception-Class-1.32.tar.gz"
diff --git a/main/perl-extutils-cchecker/APKBUILD b/main/perl-extutils-cchecker/APKBUILD
new file mode 100644
index 0000000000..85b5ef9b62
--- /dev/null
+++ b/main/perl-extutils-cchecker/APKBUILD
@@ -0,0 +1,30 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer:
+pkgname=perl-extutils-cchecker
+_pkgreal=ExtUtils-CChecker
+pkgver=0.06
+pkgrel=2
+pkgdesc="Perl module configuration-time utilities for using C headers, libraries, or OS features"
+url="http://search.cpan.org/dist/ExtUtils-CChecker/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl-test-exception"
+makedepends="perl-dev"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PE/PEVANS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name .packlist -name perllocal.pod -delete
+}
+
+md5sums="18d0a1a50afd5a8185c03cbed9098e4e ExtUtils-CChecker-0.06.tar.gz"
diff --git a/main/perl-fcgi-procmanager/APKBUILD b/main/perl-fcgi-procmanager/APKBUILD
new file mode 100644
index 0000000000..6b58e6c875
--- /dev/null
+++ b/main/perl-fcgi-procmanager/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-fcgi-procmanager
+pkgver=0.19
+pkgrel=0
+pkgdesc="FCGI::ProcManager perl module"
+url="http://search.cpan.org/dist/FCGI-ProcManager/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GB/GBJK/FCGI-ProcManager-$pkgver.tar.gz"
+
+_builddir="$srcdir"/FCGI-ProcManager-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="85b4eb5203f0adbf14bed39a258b9a59 FCGI-ProcManager-0.19.tar.gz"
diff --git a/main/perl-fcgi/APKBUILD b/main/perl-fcgi/APKBUILD
new file mode 100644
index 0000000000..cb8f256b8e
--- /dev/null
+++ b/main/perl-fcgi/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Leonardo Arena <rnalrd@alpinelinux.org>
+pkgname=perl-fcgi
+_realname=FCGI
+pkgver=0.72
+pkgrel=0
+pkgdesc="Perl Fast CGI module"
+url="http://search.cpan.org/~flora/FCGI"
+arch="all"
+license="unknown"
+depends=
+depends_dev=
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/F/FL/FLORA/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ # creates collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="7b793e177caa93d972c6fb7ebe7c7ae1 FCGI-0.72.tar.gz"
diff --git a/main/perl-file-listing/APKBUILD b/main/perl-file-listing/APKBUILD
new file mode 100644
index 0000000000..97e30a3a3e
--- /dev/null
+++ b/main/perl-file-listing/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-file-listing
+pkgver=6.02
+pkgrel=1
+pkgdesc="File::Listing perl module"
+url="http://search.cpan.org/dist/File-Listing/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-http-date"
+makedepends="perl-dev"
+install=""
+replaces="perl-libwww"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/File-Listing-$pkgver.tar.gz"
+
+_builddir="$srcdir"/File-Listing-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="57349906cdb1d2be954bc9ec44c961bf File-Listing-6.02.tar.gz"
diff --git a/main/perl-file-next/APKBUILD b/main/perl-file-next/APKBUILD
new file mode 100644
index 0000000000..b3231b4575
--- /dev/null
+++ b/main/perl-file-next/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-file-next
+_pkgreal=File-Next
+pkgver=1.06
+pkgrel=1
+pkgdesc="Perl module for taint-safe file-finding"
+url="http://search.cpan.org/dist/File-Next/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends=
+depends_dev=
+makedepends="perl-dev"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PE/PETDANCE/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="8d901b18e40c477acd18a6ea0fd7de64 File-Next-1.06.tar.gz"
diff --git a/main/perl-file-rsync/APKBUILD b/main/perl-file-rsync/APKBUILD
new file mode 100644
index 0000000000..745ea0d1de
--- /dev/null
+++ b/main/perl-file-rsync/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-file-rsync
+_realname=File-RsyncP
+pkgver=0.68
+pkgrel=3
+pkgdesc="Perl rsync client"
+url="http://search.cpan.org/~cbarratt/File-RsyncP-0.68/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CB/CBARRATT/$_realname-$pkgver.tar.gz
+perl-file-rsync-parallell-build-fix.patch"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd $_builddir
+ patch -p1 <../perl-file-rsync-parallell-build-fix.patch || return 1
+}
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make config && make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="ed47c5ef7ff835415692f18137cb0cf9 File-RsyncP-0.68.tar.gz
+402df47ad01369de0ffc75754529d6e4 perl-file-rsync-parallell-build-fix.patch"
diff --git a/main/perl-file-rsync/perl-file-rsync-parallell-build-fix.patch b/main/perl-file-rsync/perl-file-rsync-parallell-build-fix.patch
new file mode 100644
index 0000000000..d9316f3d19
--- /dev/null
+++ b/main/perl-file-rsync/perl-file-rsync-parallell-build-fix.patch
@@ -0,0 +1,20 @@
+diff --git a/FileList/Makefile.PL b/FileList/Makefile.PL
+index 2061b0a..3ab345f 100644
+--- a/FileList/Makefile.PL
++++ b/FileList/Makefile.PL
+@@ -16,7 +16,14 @@ WriteMakefile(
+ snprintf$(OBJ_EXT)
+ wildmatch$(OBJ_EXT)
+ ],
+- 'depend' => { 'FileList.o' => 'config.h' },
++ 'depend' => { 'FileList$(OBJ_EXT)' => 'config.h',
++ 'exclude$(OBJ_EXT)' => 'config.h',
++ 'flist$(OBJ_EXT)' => 'config.h',
++ 'hlink$(OBJ_EXT)' => 'config.h',
++ 'pool_alloc$(OBJ_EXT)' => 'config.h',
++ 'snprintf$(OBJ_EXT)' => 'config.h',
++ 'wildmatch$(OBJ_EXT)' => 'config.h',
++ },
+ 'clean' => {FILES => "configure.in config.log config.status config.h conftest* confdefs*"},
+ );
+
diff --git a/main/perl-file-sharedir/APKBUILD b/main/perl-file-sharedir/APKBUILD
new file mode 100644
index 0000000000..3954aff806
--- /dev/null
+++ b/main/perl-file-sharedir/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-file-sharedir
+pkgver=1.03
+pkgrel=0
+pkgdesc="File::ShareDir perl module"
+url="http://search.cpan.org/dist/File-ShareDir/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-class-inspector"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AD/ADAMK/File-ShareDir-$pkgver.tar.gz"
+
+_builddir="$srcdir"/File-ShareDir-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="333a0903db23b9097adfbeb37b99d561 File-ShareDir-1.03.tar.gz"
diff --git a/main/perl-file-slurp/APKBUILD b/main/perl-file-slurp/APKBUILD
new file mode 100644
index 0000000000..3a4abff3dc
--- /dev/null
+++ b/main/perl-file-slurp/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-file-slurp
+_pkgreal=File-Slurp
+pkgver=9999.18
+pkgrel=0
+pkgdesc="Simple and Efficient Reading/Writing/Modifying of Complete Files"
+url="http://search.cpan.org/dist/File-Slurp/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/U/UR/URI/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="400983e739aea5677c3a7e8cb2c23de0 File-Slurp-9999.18.tar.gz"
diff --git a/main/perl-file-tail/APKBUILD b/main/perl-file-tail/APKBUILD
new file mode 100644
index 0000000000..8440eb47c5
--- /dev/null
+++ b/main/perl-file-tail/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-file-tail
+_realname=File-Tail
+pkgver=0.99.3
+pkgrel=2
+pkgdesc="Perl - Extension for reading from continously updated files"
+url="http://search.cpan.org/~mgrabnar/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl"
+makedepends="perl-dev"
+install=
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MG/MGRABNAR/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="ef0fb7bcb4181ba593f4a09940f61d1c File-Tail-0.99.3.tar.gz"
diff --git a/main/perl-filesys-notify-simple/APKBUILD b/main/perl-filesys-notify-simple/APKBUILD
new file mode 100644
index 0000000000..77ae55a361
--- /dev/null
+++ b/main/perl-filesys-notify-simple/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-filesys-notify-simple
+pkgver=0.07
+pkgrel=0
+pkgdesc="Filesys::Notify::Simple perl module"
+url="http://search.cpan.org/dist/Filesys-Notify-Simple/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MI/MIYAGAWA/Filesys-Notify-Simple-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Filesys-Notify-Simple-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="4842ff56a79a7db0b779ce21e71bd291 Filesys-Notify-Simple-0.07.tar.gz"
diff --git a/main/perl-font-afm/APKBUILD b/main/perl-font-afm/APKBUILD
new file mode 100644
index 0000000000..bd3ac64bb8
--- /dev/null
+++ b/main/perl-font-afm/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-font-afm
+_pkgreal=Font-AFM
+pkgver=1.20
+pkgrel=0
+pkgdesc="Interface to Adobe Font Metrics files"
+url="http://search.cpan.org/dist/Font-AFM/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="b14ecf4dc4edbd63940aa354eb13c499 Font-AFM-1.20.tar.gz"
diff --git a/main/perl-getopt-long/APKBUILD b/main/perl-getopt-long/APKBUILD
new file mode 100644
index 0000000000..071dc80a4c
--- /dev/null
+++ b/main/perl-getopt-long/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-getopt-long
+_realname=Getopt-Long
+pkgver=2.38
+pkgrel=2
+pkgdesc="Extended processing of command line options"
+url="http://search.cpan.org/~jv/Getopt-Long-2.38/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JV/JV/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="4d38c78300e79a7fde4700e88759c2b3 Getopt-Long-2.38.tar.gz"
diff --git a/main/perl-hash-multivalue/APKBUILD b/main/perl-hash-multivalue/APKBUILD
new file mode 100644
index 0000000000..a68e2f0bce
--- /dev/null
+++ b/main/perl-hash-multivalue/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-hash-multivalue
+pkgver=0.08
+pkgrel=0
+pkgdesc="Hash::MultiValue perl module"
+url="http://search.cpan.org/dist/Hash-MultiValue/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MI/MIYAGAWA/Hash-MultiValue-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Hash-MultiValue-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="d8e2ae6a0685d52641b3a5de20ae4116 Hash-MultiValue-0.08.tar.gz"
diff --git a/main/perl-html-format/APKBUILD b/main/perl-html-format/APKBUILD
new file mode 100644
index 0000000000..eb4c7740ad
--- /dev/null
+++ b/main/perl-html-format/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-html-format
+_pkgreal=HTML-Format
+pkgver=2.07
+pkgrel=0
+pkgdesc="Base class for HTML formatters"
+url="http://search.cpan.org/dist/HTML-Format/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-html-tree perl-font-afm"
+cpanmakedepends="perl-file-slurp"
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/N/NI/NIGELM/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="07b43da2e23ad4f6eeacee8219c65fa4 HTML-Format-2.07.tar.gz"
diff --git a/main/perl-html-mason-psgihandler/APKBUILD b/main/perl-html-mason-psgihandler/APKBUILD
new file mode 100644
index 0000000000..bed4fbed57
--- /dev/null
+++ b/main/perl-html-mason-psgihandler/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-html-mason-psgihandler
+_pkgreal=HTML-Mason-PSGIHandler
+pkgver=0.52
+pkgrel=0
+pkgdesc="PSGI handler for HTML::Mason"
+url="http://search.cpan.org/dist/HTML-Mason-PSGIHandler/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-cgi-psgi perl-html-mason"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev perl-plack $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AB/ABH/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="42aa3272e16af0d6f35ac031d274dad8 HTML-Mason-PSGIHandler-0.52.tar.gz"
diff --git a/main/perl-html-mason/APKBUILD b/main/perl-html-mason/APKBUILD
new file mode 100644
index 0000000000..74944ed921
--- /dev/null
+++ b/main/perl-html-mason/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-html-mason
+_pkgreal=HTML-Mason
+pkgver=1.45
+pkgrel=0
+pkgdesc="High-performance, dynamic web site authoring system"
+url="http://search.cpan.org/dist/HTML-Mason/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-html-parser perl-class-container perl-params-validate perl-log-any perl-cache-cache perl-test-deep perl-exception-class"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DROLSKY/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="5ad416ae8425d81dde3daf5fab913a23 HTML-Mason-1.45.tar.gz"
diff --git a/main/perl-html-parser/APKBUILD b/main/perl-html-parser/APKBUILD
new file mode 100644
index 0000000000..8051240b2e
--- /dev/null
+++ b/main/perl-html-parser/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-html-parser
+_realname=HTML-Parser
+pkgver=3.68
+pkgrel=2
+pkgdesc="Parse section of HTML documents"
+url="http://search.cpan.org/~gaas/HTML-Parser-3.60/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="5550b2da7aa94341f1e8a17a4ac20c68 HTML-Parser-3.68.tar.gz"
diff --git a/main/perl-html-quoted/APKBUILD b/main/perl-html-quoted/APKBUILD
new file mode 100644
index 0000000000..b88a76f2d5
--- /dev/null
+++ b/main/perl-html-quoted/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-html-quoted
+pkgver=0.03
+pkgrel=0
+pkgdesc="HTML::Quoted perl module"
+url="http://search.cpan.org/dist/HTML-Quoted/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-html-parser"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RU/RUZ/HTML-Quoted-$pkgver.tar.gz"
+
+_builddir="$srcdir"/HTML-Quoted-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="dc614a27838ee3218f32738de1881e1f HTML-Quoted-0.03.tar.gz"
diff --git a/main/perl-html-rewriteattributes/APKBUILD b/main/perl-html-rewriteattributes/APKBUILD
new file mode 100644
index 0000000000..76b39c5aa9
--- /dev/null
+++ b/main/perl-html-rewriteattributes/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-html-rewriteattributes
+_pkgreal=HTML-RewriteAttributes
+pkgver=0.04
+pkgrel=0
+pkgdesc="concise attribute rewriting"
+url="http://search.cpan.org/dist/HTML-RewriteAttributes/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-html-tagset perl-html-parser perl-uri"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SA/SARTAK/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="2f14d37ad31e91f2ee0c13d2f2cd329b HTML-RewriteAttributes-0.04.tar.gz"
diff --git a/main/perl-html-scrubber/APKBUILD b/main/perl-html-scrubber/APKBUILD
new file mode 100644
index 0000000000..38c0200869
--- /dev/null
+++ b/main/perl-html-scrubber/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-html-scrubber
+pkgver=0.09
+pkgrel=0
+pkgdesc="HTML::Scrubber perl module"
+url="http://search.cpan.org/dist/HTML-Scrubber/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-html-parser"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/N/NI/NIGELM/HTML-Scrubber-$pkgver.tar.gz"
+
+_builddir="$srcdir"/HTML-Scrubber-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="a0f7bd0a29a4c7b1bec5495ad9bfb00e HTML-Scrubber-0.09.tar.gz"
diff --git a/main/perl-html-tagset/APKBUILD b/main/perl-html-tagset/APKBUILD
new file mode 100644
index 0000000000..891eb35061
--- /dev/null
+++ b/main/perl-html-tagset/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-html-tagset
+_pkgreal=HTML-Tagset
+pkgver=3.20
+pkgrel=0
+pkgdesc="data tables useful in parsing HTML"
+url="http://search.cpan.org/dist/HTML-Tagset/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PE/PETDANCE/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="d2bfa18fe1904df7f683e96611e87437 HTML-Tagset-3.20.tar.gz"
diff --git a/main/perl-html-tree/APKBUILD b/main/perl-html-tree/APKBUILD
new file mode 100644
index 0000000000..c564a23e1c
--- /dev/null
+++ b/main/perl-html-tree/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-html-tree
+_pkgreal=HTML-Tree
+pkgver=4.2
+pkgrel=0
+pkgdesc="Class for objects that represent HTML elements"
+url="http://search.cpan.org/dist/HTML-Tree/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-html-tagset perl-html-parser"
+cpanmakedepends="perl-html-tagset perl-test-exception perl-html-parser"
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JF/JFEARN/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="a145ad037ac54b6192c0046383d267da HTML-Tree-4.2.tar.gz"
diff --git a/main/perl-http-body/APKBUILD b/main/perl-http-body/APKBUILD
new file mode 100644
index 0000000000..e8a266e6b2
--- /dev/null
+++ b/main/perl-http-body/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-http-body
+pkgver=1.12
+pkgrel=0
+pkgdesc="HTTP::Body perl module"
+url="http://search.cpan.org/dist/HTTP-Body/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-http-message perl-uri"
+makedepends="perl-dev perl-test-deep"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GE/GETTY/HTTP-Body-$pkgver.tar.gz"
+
+_builddir="$srcdir"/HTTP-Body-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="6546d9a91362b06b67264f374f0b2fab HTTP-Body-1.12.tar.gz"
diff --git a/main/perl-http-cookies/APKBUILD b/main/perl-http-cookies/APKBUILD
new file mode 100644
index 0000000000..25cb397f92
--- /dev/null
+++ b/main/perl-http-cookies/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-http-cookies
+pkgver=6.00
+pkgrel=1
+pkgdesc="HTTP::Cookies perl module"
+url="http://search.cpan.org/dist/HTTP-Cookies/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-http-date perl-http-message"
+makedepends="perl-dev"
+install=""
+replaces="perl-libwww"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/HTTP-Cookies-$pkgver.tar.gz"
+
+_builddir="$srcdir"/HTTP-Cookies-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="21bed72b30a46604c152b7e25cf1cb45 HTTP-Cookies-6.00.tar.gz"
diff --git a/main/perl-http-daemon/APKBUILD b/main/perl-http-daemon/APKBUILD
new file mode 100644
index 0000000000..a156183228
--- /dev/null
+++ b/main/perl-http-daemon/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-http-daemon
+pkgver=6.00
+pkgrel=1
+pkgdesc="HTTP::Daemon perl module"
+url="http://search.cpan.org/dist/HTTP-Daemon/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-http-date perl-http-message"
+makedepends="perl-dev"
+install=""
+replaces="perl-libwww"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/HTTP-Daemon-$pkgver.tar.gz"
+
+_builddir="$srcdir"/HTTP-Daemon-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="36c8048775b8b53a6fb7c9d781658926 HTTP-Daemon-6.00.tar.gz"
diff --git a/main/perl-http-date/APKBUILD b/main/perl-http-date/APKBUILD
new file mode 100644
index 0000000000..ec4aea5343
--- /dev/null
+++ b/main/perl-http-date/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-http-date
+_realname=HTTP-Date
+pkgver=6.00
+pkgrel=1
+pkgdesc="Perl module date conversion routines"
+url="http://search.cpan.org/~gaas"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+replaces="perl-libwww"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="41b875ac89c14d7f66515b52cdd12acd HTTP-Date-6.00.tar.gz"
diff --git a/main/perl-http-message/APKBUILD b/main/perl-http-message/APKBUILD
new file mode 100644
index 0000000000..22aa01ef3e
--- /dev/null
+++ b/main/perl-http-message/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-http-message
+pkgver=6.02
+pkgrel=2
+pkgdesc="HTTP::Message perl module"
+url="http://search.cpan.org/dist/HTTP-Message/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-uri perl-html-parser perl-encode-locale perl-lwp-mediatypes
+ perl-http-date"
+makedepends="perl-dev"
+install=""
+replaces="perl-libwww"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/HTTP-Message-$pkgver.tar.gz"
+
+_builddir="$srcdir"/HTTP-Message-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="a6b28e44f7b5e5573362f042d522a456 HTTP-Message-6.02.tar.gz"
diff --git a/main/perl-http-negotiate/APKBUILD b/main/perl-http-negotiate/APKBUILD
new file mode 100644
index 0000000000..995ea11fa9
--- /dev/null
+++ b/main/perl-http-negotiate/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-http-negotiate
+pkgver=6.00
+pkgrel=0
+pkgdesc="HTTP::Negotiate perl module"
+url="http://search.cpan.org/dist/HTTP-Negotiate/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-http-message"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/HTTP-Negotiate-$pkgver.tar.gz"
+
+_builddir="$srcdir"/HTTP-Negotiate-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="f2d89957d1c4f62a86f18b08e07c2328 HTTP-Negotiate-6.00.tar.gz"
diff --git a/main/perl-image-exiftool/APKBUILD b/main/perl-image-exiftool/APKBUILD
new file mode 100644
index 0000000000..7875926b9d
--- /dev/null
+++ b/main/perl-image-exiftool/APKBUILD
@@ -0,0 +1,48 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-image-exiftool
+pkgver=8.49
+pkgrel=1
+pkgdesc="Perl module for editing exif meta info in files"
+url="http://www.sno.phy.queensu.ca/~phil/exiftool/"
+arch="noarch"
+license="Perl"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc exiftool"
+source="http://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Image-ExifTool-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+ find "$pkgdir" -name .packlist -delete
+}
+
+exiftool() {
+ pkgdesc="Tool for editing exif meta info in files"
+ depends="perl-image-exiftool"
+ mkdir -p "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="e95ee3d76a973e308d377b39a51fff6f Image-ExifTool-8.49.tar.gz"
diff --git a/main/perl-inline/APKBUILD b/main/perl-inline/APKBUILD
new file mode 100644
index 0000000000..210d698d88
--- /dev/null
+++ b/main/perl-inline/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-inline
+_realname=Inline
+pkgver=0.46
+pkgrel=1
+pkgdesc="Write Perl subroutines in other programming languages"
+url="http://search.cpan.org/~sisyphus/Inline-0.45/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SI/SISYPHUS/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="4c2f14829fbe83cb456e9c5c0dac06b3 Inline-0.46.tar.gz"
diff --git a/main/perl-io-compress/APKBUILD b/main/perl-io-compress/APKBUILD
new file mode 100644
index 0000000000..4664b81e09
--- /dev/null
+++ b/main/perl-io-compress/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-io-compress
+_realname=IO-Compress
+pkgver=2.035
+pkgrel=2
+pkgdesc="Perl compression library"
+url="http://search.cpan.org/~pmqs/IO-Compress-2.024/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl perl-compress-raw-bzip2 perl-compress-raw-zlib"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PM/PMQS/${_realname}-${pkgver}.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="716ebc25f63e6a5ca778cff023341c59 IO-Compress-2.035.tar.gz"
diff --git a/main/perl-io-multiplex/APKBUILD b/main/perl-io-multiplex/APKBUILD
new file mode 100644
index 0000000000..d3ceed0414
--- /dev/null
+++ b/main/perl-io-multiplex/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-io-multiplex
+_realname=IO-Multiplex
+pkgver=1.10
+pkgrel=2
+pkgdesc="Perl module to manage IO on many file handles"
+url="http://search.cpan.org/~bbb/IO-Multiplex-1.10/"
+arch="noarch"
+license="unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/B/BB/BBB/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="ce230ee0a4afbff59da66f0c42e0340b IO-Multiplex-1.10.tar.gz"
diff --git a/main/perl-io-socket-ssl/APKBUILD b/main/perl-io-socket-ssl/APKBUILD
new file mode 100644
index 0000000000..8511945d09
--- /dev/null
+++ b/main/perl-io-socket-ssl/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-io-socket-ssl
+_realname=IO-Socket-SSL
+pkgver=1.37
+pkgrel=1
+pkgdesc="Nearly transparent SSL encapsulation for IO::Socket::INET"
+url="http://search.cpan.org/dist/IO-Socket-SSL/"
+arch="noarch"
+license="GPL"
+depends="perl perl-net-ssleay"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SU/SULLR/IO-Socket-SSL-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="a75c962ce989865213ca4320766fdb77 IO-Socket-SSL-1.37.tar.gz"
diff --git a/main/perl-io-stringy/APKBUILD b/main/perl-io-stringy/APKBUILD
new file mode 100644
index 0000000000..fad50ab5b2
--- /dev/null
+++ b/main/perl-io-stringy/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-io-stringy
+_realname=IO-stringy
+pkgver=2.110
+pkgrel=2
+pkgdesc="A Perl module for I/O on in-core objects like strings and arrays"
+url="http://search.cpan.org/~dskoll/IO-stringy-2.110/"
+arch="noarch"
+license="unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DS/DSKOLL/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="2e6a976cfa5521e815c1fdf4006982de IO-stringy-2.110.tar.gz"
diff --git a/main/perl-ipc-run3/APKBUILD b/main/perl-ipc-run3/APKBUILD
new file mode 100644
index 0000000000..520b851e04
--- /dev/null
+++ b/main/perl-ipc-run3/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-ipc-run3
+pkgver=0.044
+pkgrel=0
+pkgdesc="IPC::Run3 perl module"
+url="http://search.cpan.org/dist/IPC-Run3/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/IPC-Run3-$pkgver.tar.gz"
+
+_builddir="$srcdir"/IPC-Run3-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="7df73a65d9efc7b9e7eb04075ff1fd8f IPC-Run3-0.044.tar.gz"
diff --git a/main/perl-javascript-minifier/APKBUILD b/main/perl-javascript-minifier/APKBUILD
new file mode 100644
index 0000000000..c514dae644
--- /dev/null
+++ b/main/perl-javascript-minifier/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-javascript-minifier
+_pkgreal=JavaScript-Minifier
+pkgver=1.05
+pkgrel=0
+pkgdesc="Perl extension for minifying JavaScript code"
+url="http://search.cpan.org/dist/JavaScript-Minifier/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PM/PMICHAUX/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="14c1fa2fcf76c97de4d0fe0d8d7fc145 JavaScript-Minifier-1.05.tar.gz"
diff --git a/main/perl-json/APKBUILD b/main/perl-json/APKBUILD
new file mode 100644
index 0000000000..3d105c1a77
--- /dev/null
+++ b/main/perl-json/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+pkgname=perl-json
+_pkgreal=JSON
+pkgver=2.51
+pkgrel=1
+pkgdesc="Perl module implementing a JSON encoder/decoder"
+url="http://search.cpan.org/dist/JSON/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends=
+depends_dev=
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MA/MAKAMAKA/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name perllocal.pod -delete
+ find "$pkgdir" -name .packlist -delete
+}
+
+md5sums="d0ead26851f1e84d122f34533c3809cc JSON-2.51.tar.gz"
diff --git a/main/perl-libwww/APKBUILD b/main/perl-libwww/APKBUILD
new file mode 100644
index 0000000000..8689e213f7
--- /dev/null
+++ b/main/perl-libwww/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-libwww
+_realname=libwww-perl
+pkgver=6.02
+pkgrel=2
+pkgdesc="Perl module - World Wide Web library"
+url="http://search.cpan.org/~gaas"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl perl-encode-locale perl-http-date perl-http-message
+ perl-lwp-mediatypes perl-uri perl-http-daemon perl-www-robotrules
+ perl-file-listing perl-http-cookies perl-net-http"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="4617dbc79a78992a8c8db263c170d8ec libwww-perl-6.02.tar.gz"
diff --git a/main/perl-list-moreutils/APKBUILD b/main/perl-list-moreutils/APKBUILD
new file mode 100644
index 0000000000..cade2866a8
--- /dev/null
+++ b/main/perl-list-moreutils/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-list-moreutils
+pkgver=0.32
+pkgrel=0
+pkgdesc="List::MoreUtils perl module"
+url="http://search.cpan.org/dist/List-MoreUtils/"
+arch="all"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AD/ADAMK/List-MoreUtils-$pkgver.tar.gz"
+
+_builddir="$srcdir"/List-MoreUtils-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ unset CFLAGS
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="5af56334f8261f4662bd5e2b3f5e4e62 List-MoreUtils-0.32.tar.gz"
diff --git a/main/perl-list-utilsby/APKBUILD b/main/perl-list-utilsby/APKBUILD
new file mode 100644
index 0000000000..cde433b47d
--- /dev/null
+++ b/main/perl-list-utilsby/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-list-utilsby
+_pkgreal=List-UtilsBy
+pkgver=0.07
+pkgrel=0
+pkgdesc="higher-order list utility functions"
+url="http://search.cpan.org/dist/List-UtilsBy/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PE/PEVANS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="2c39a8a2021bdf63ee4a8d7e0b0829a4 List-UtilsBy-0.07.tar.gz"
diff --git a/main/perl-locale-maketext-fuzzy/APKBUILD b/main/perl-locale-maketext-fuzzy/APKBUILD
new file mode 100644
index 0000000000..0f0bb0c1be
--- /dev/null
+++ b/main/perl-locale-maketext-fuzzy/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-locale-maketext-fuzzy
+pkgver=0.10
+pkgrel=0
+pkgdesc="Locale::Maketext::Fuzzy perl module"
+url="http://search.cpan.org/dist/Locale-Maketext-Fuzzy/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AU/AUDREYT/Locale-Maketext-Fuzzy-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Locale-Maketext-Fuzzy-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="ff5621abe3b6a632bdf91932b4b69513 Locale-Maketext-Fuzzy-0.10.tar.gz"
diff --git a/main/perl-locale-maketext-lexicon/APKBUILD b/main/perl-locale-maketext-lexicon/APKBUILD
new file mode 100644
index 0000000000..d5b82e4ee5
--- /dev/null
+++ b/main/perl-locale-maketext-lexicon/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-locale-maketext-lexicon
+pkgver=0.86
+pkgrel=0
+pkgdesc="Locale::Maketext::Lexicon perl module"
+url="http://search.cpan.org/dist/Locale-Maketext-Lexicon/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DRTECH/Locale-Maketext-Lexicon-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Locale-Maketext-Lexicon-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="c21d481b23f0848cdb92d1fb5aaf29ff Locale-Maketext-Lexicon-0.86.tar.gz"
diff --git a/main/perl-log-any/APKBUILD b/main/perl-log-any/APKBUILD
new file mode 100644
index 0000000000..27739a818d
--- /dev/null
+++ b/main/perl-log-any/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-log-any
+_pkgreal=Log-Any
+pkgver=0.12
+pkgrel=0
+pkgdesc="Bringing loggers and listeners together"
+url="http://search.cpan.org/dist/Log-Any/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JS/JSWARTZ/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="eaab5035d69af58eab72e19140c5f246 Log-Any-0.12.tar.gz"
diff --git a/main/perl-log-dispatch/APKBUILD b/main/perl-log-dispatch/APKBUILD
new file mode 100644
index 0000000000..00684f0b5d
--- /dev/null
+++ b/main/perl-log-dispatch/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-log-dispatch
+pkgver=2.27
+pkgrel=0
+pkgdesc="Dispatches messages to one or more outputs"
+url="http://search.cpan.org/dist/Log-Dispatch/"
+arch="noarch"
+license="Artistic 2.0"
+depends="perl perl-params-validate"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://www.cpan.org/authors/id/D/DR/DROLSKY/Log-Dispatch-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Log-Dispatch-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="6bd3420ef0df39f2e32fbbe6b57a1db8 Log-Dispatch-2.27.tar.gz"
diff --git a/main/perl-lwp-mediatypes/APKBUILD b/main/perl-lwp-mediatypes/APKBUILD
new file mode 100644
index 0000000000..ccad3f954b
--- /dev/null
+++ b/main/perl-lwp-mediatypes/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-lwp-mediatypes
+_realname=LWP-MediaTypes
+pkgver=6.01
+pkgrel=1
+pkgdesc="Perl module - guess media type for a file or a URL"
+url="http://search.cpan.org/~gaas"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+replaces="perl-libwww"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="3cd1ccb774867b5b20e672981b230db6 LWP-MediaTypes-6.01.tar.gz"
diff --git a/main/perl-lwp-useragent-determined/APKBUILD b/main/perl-lwp-useragent-determined/APKBUILD
new file mode 100644
index 0000000000..fb2f1aef44
--- /dev/null
+++ b/main/perl-lwp-useragent-determined/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-lwp-useragent-determined
+_pkgreal=LWP-UserAgent-Determined
+pkgver=1.05
+pkgrel=3
+pkgdesc="a virtual browser that retries errors"
+url="http://search.cpan.org/dist/LWP-UserAgent-Determined/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-libwww"
+cpanmakedepends=""
+depends="perl $cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JE/JESSE/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="4c7fe2e8f9f820e9288f198e46a0a55e LWP-UserAgent-Determined-1.05.tar.gz"
diff --git a/main/perl-mail-clamav/APKBUILD b/main/perl-mail-clamav/APKBUILD
new file mode 100644
index 0000000000..bb6d68008f
--- /dev/null
+++ b/main/perl-mail-clamav/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-mail-clamav
+_realname=Mail-ClamAV
+pkgver=0.29
+pkgrel=5
+pkgdesc="Perl extension for the clamav virus scanner"
+url="http://search.cpan.org/~converter/Mail-ClamAV-0.29/"
+arch="all"
+license="Unknown"
+depends="perl clamav"
+makedepends="perl-dev perl-inline perl-parse-recdescent clamav-dev zlib-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CO/CONVERTER/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ sed -i -e 's%\(clamav-config --version\)%sh /usr/bin/\1%' Makefile.PL || return 1
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ make -j1 || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+
+}
+
+md5sums="737ea1c041d9312cdcfe5b85eb45428e Mail-ClamAV-0.29.tar.gz"
diff --git a/main/perl-mail-dkim/APKBUILD b/main/perl-mail-dkim/APKBUILD
new file mode 100644
index 0000000000..229f1e5dcb
--- /dev/null
+++ b/main/perl-mail-dkim/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-mail-dkim
+_realname=Mail-DKIM
+pkgver=0.39
+pkgrel=0
+pkgdesc="Signs/verifies Internet mail with DKIM/DomainKey signatures"
+url="http://search.cpan.org/~jaslong/Mail-DKIM-0.36/"
+arch="noarch"
+license="unknown"
+depends="perl perl-net-dns perl-net-ip perl-mail-tools perl-crypt-openssl-rsa"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JA/JASLONG/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="0b62c91f855f47e818d96680746572ca Mail-DKIM-0.39.tar.gz"
diff --git a/main/perl-mail-domainkeys/APKBUILD b/main/perl-mail-domainkeys/APKBUILD
new file mode 100644
index 0000000000..25e95a76ca
--- /dev/null
+++ b/main/perl-mail-domainkeys/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-mail-domainkeys
+_realname=Mail-DomainKeys
+pkgver=1.0
+pkgrel=2
+pkgdesc="A perl implementation of DomainKeys"
+url="http://search.cpan.org/~anthonyu/Mail-DomainKeys-1.0/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AN/ANTHONYU/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="a4565f21ada263cf34c55f50d7eb9944 Mail-DomainKeys-1.0.tar.gz"
diff --git a/main/perl-mail-spamassassin/APKBUILD b/main/perl-mail-spamassassin/APKBUILD
new file mode 100644
index 0000000000..d770f85f04
--- /dev/null
+++ b/main/perl-mail-spamassassin/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-mail-spamassassin
+_realname=Mail-SpamAssassin
+pkgver=3.2.5
+pkgrel=4
+pkgdesc="Spam detector and markup engine"
+url="http://search.cpan.org/~jmason/Mail-SpamAssassin-3.2.5/"
+arch="all"
+license="unknown"
+depends="perl perl-digest-sha1 perl-html-parser perl-net-dns perl-db_file
+perl-mail-spf razor"
+makedepends="perl-dev zlib-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JM/JMASON/$_realname-$pkgver.tar.gz
+ spamassassin-3.2.5-DESTDIR.patch
+ "
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+ patch -p1 -i ../spamassassin-3.2.5-DESTDIR.patch || return 1
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="7fdc1651d0371c4a7f95ac9ae6f828a6 Mail-SpamAssassin-3.2.5.tar.gz
+45885134199c9427add4d9bcb46311cf spamassassin-3.2.5-DESTDIR.patch"
diff --git a/main/perl-mail-spamassassin/spamassassin-3.2.5-DESTDIR.patch b/main/perl-mail-spamassassin/spamassassin-3.2.5-DESTDIR.patch
new file mode 100644
index 0000000000..a9765fc55d
--- /dev/null
+++ b/main/perl-mail-spamassassin/spamassassin-3.2.5-DESTDIR.patch
@@ -0,0 +1,273 @@
+--- Mail-SpamAssassin-3.2.5/Makefile.PL.old 2009-10-21 23:25:18.000000000 +0200
++++ Mail-SpamAssassin-3.2.5/Makefile.PL 2009-10-21 23:31:28.000000000 +0200
+@@ -12,12 +12,12 @@
+
+ # avoid stupid 'Argument "6.30_01" isn't numeric in numeric ge (>=)' warnings;
+ # strip off the beta subversion noise that causes the trouble.
+ $mm_version =~ s/_\S+$//; # "6.30_01" => "6.30"
+
+-if ($mm_version+0 < 5.45) {
+- die "SpamAssassin Makefile.PL requires at least ExtUtils::MakeMaker v5.45";
++if ($mm_version < 6.17) {
++ die "SpamAssassin Makefile.PL requires at least ExtUtils::MakeMaker v6.17";
+ }
+
+ use constant RUNNING_ON_WINDOWS => ($^O =~ /^(mswin|dos|os2)/oi);
+ use constant HAS_DBI => eval { require DBI; };
+
+@@ -82,11 +82,10 @@
+ );
+
+
+ sub parse_arg {
+ my($val, $name) = (@_);
+-
+ if ($val =~ /^($name)=["']?(.*?)["']?$/) {
+ return $2;
+ } else {
+ return undef;
+ }
+@@ -107,53 +106,27 @@
+ return 'yes' if bool($val, $def);
+ return 'no';
+ }
+
+
+-
+ my %opt = (
+- 'build_spamc' => undef,
++ 'build_spamc' => undef,
+ 'enable_ssl' => undef,
+ 'contact_address' => undef,
+ 'destdir' => undef,
+ );
+ ARGV: foreach (@ARGV) {
+ foreach my $key (keys %opt) {
+- my $val;
+-
+- $val = parse_arg($_, uc($key));
++ my $val = parse_arg($_, uc($key));
+ if (defined $val) {
+ $opt{$key} = $val;
+ next ARGV;
+ }
+ }
+ }
+
+
+-# Gather some information about what EU::MM offers and/or needs
+-my(
+- $mm_knows_destdir,
+- $mm_has_destdir,
+- $mm_has_good_destdir,
+- $mm_needs_destdir,
+-);
+-
+-# MakeMaker prior to 6.11 doesn't support DESTDIR which is needed for
+-# packaging with builddir!=destdir. See bug 2388.
+-$mm_knows_destdir = $ExtUtils::MakeMaker::Recognized_Att_Keys{DESTDIR};
+-$mm_has_good_destdir = $mm_version >= 6.11;
+-# Add DESTDIR hack only if it's requested (and necessary)
+-$mm_needs_destdir = $opt{'destdir'} && !$mm_has_good_destdir;
+-$mm_has_destdir = $mm_knows_destdir || $mm_needs_destdir;
+-push(@ATT_KEYS, 'DESTDIR') if $mm_needs_destdir;
+-
+-# Now make EU::MM understand our extended vars
+-foreach my $key (@ATT_KEYS) {
+- $ExtUtils::MakeMaker::Recognized_Att_Keys{$key} = 1;
+-}
+-
+-
+ # Gather the rules files in the range 00-69; we do this in perl because
+ # it's more portable. Also, plugin .pm files.
+ my @datafiles = map { s,^rules/,,; $_ }
+ grep { -f $_ } (<rules/*.cf>, <rules/*.pm>);
+ my $datafiles = join(' ', (grep
+@@ -270,75 +243,27 @@
+
+ # We have only this Makefile.PL and this option keeps MakeMaker from
+ # asking all questions twice after a 'make dist*'.
+ 'NORECURS' => 1,
+
+- # bug 5074: perl 5.6.1 (with ExtUtils::MakeMaker 5.45) attempts to
+- # recurse anyway unless this is explicitly specified
+- 'DIR' => [ ],
+-
+ # Don't add META.yml to the MANIFEST for god's sake!
+ 'NO_META' => 1,
+ );
+
+ # rules/72_active.cf is built from "rulesrc", but *must* exist before
+ # WriteMakefile() is called due to shortcomings in MakeMaker.
+ my @FILES_THAT_MUST_EXIST = qw(
+ rules/72_active.cf
+ );
+
+-# That META.yml stuff was introduced with Perl 6.06_03, see
+-# <http://archive.develooper.com/makemaker@perl.org/msg00922.html>
+-# <http://archive.develooper.com/makemaker@perl.org/msg00984.html>
+-delete $makefile{'NO_META'} if $mm_version < 6.06_03;
+-
+ # make sure certain optional modules are up-to-date if they are installed
+ # also see PREREQ_PM above
+ my %CURRENT_PM = (
+ 'Net::DNS' => (RUNNING_ON_WINDOWS ? 0.46 : 0.34),
+ 'Razor2::Client::Agent' => 2.40,
+ );
+
+-if ($mm_needs_destdir) {
+- my $error = <<DESTDIR_HACK;
+-
+- ***********************************************************************
+- ExtUtils::MakeMaker ${mm_version} doesn't include support for DESTDIR,
+- so if you want to be on the safe side, you might want to upgrade your
+- ExtUtils::MakeMaker to version 6.11 or later. It is available via CPAN.
+-
+- You can use either the CPAN shell or go to
+- <http://search.cpan.org/search?module=ExtUtils::MakeMaker>
+- to get an up-to-date version.
+-
+- This should only be necessary if you are creating binary packages.
+- ***********************************************************************
+-
+-DESTDIR_HACK
+- $error =~ s/^ {4}//gm;
+- warn $error;
+-}
+-elsif ($opt{'destdir'} and !$mm_has_good_destdir) {
+- my $error = <<DESTDIR_BUG;
+-
+- ***********************************************************************
+- ExtUtils::MakeMaker ${mm_version} contains bugs that may cause problems
+- in the \"make\" process. It is recommended that you upgrade
+- ExtUtils::MakeMaker to version 6.11 or later. It is available via CPAN.
+-
+- You can use either the CPAN shell or go to
+- <http://search.cpan.org/search?module=ExtUtils::MakeMaker>
+- to get an up-to-date version.
+-
+- This should only be necessary if you are creating binary packages.
+- ***********************************************************************
+-
+-DESTDIR_BUG
+- $error =~ s/^ {4}//gm;
+- warn $error;
+-}
+-
+
+ # All the $(*MAN1*) stuff is empty/zero if Perl was Configured with -Dman1dir=none;
+ # however, support site/vendor man1 dirs (bug 5338)
+ unless($Config{installman1dir}
+ || $Config{installsiteman1dir}
+@@ -405,22 +330,19 @@
+
+ # Now finish the meta hash and dump the Makefile
+ $makefile{EXE_FILES} = [ values %{$makefile{EXE_FILES}} ];
+ $makefile{AUTHOR} =~ s/(<.+) at (.+>)/$1\@$2/;
+ WriteMakefile(%makefile);
+-print "Makefile written by ExtUtils::MakeMaker ${mm_version}\n";
++print "Makefile written by ExtUtils::MakeMaker $mm_version\n";
+
+ #######################################################################
+
+ package MY;
+
+-
+ use vars qw(
+ $MY_GLOBALS_ARE_SANE
+-
+ $RUNNING_ON_WINDOWS
+-
+ @REPOSITORIES
+
+ $MACRO_RE
+ $EQ_RE
+ $EQ
+@@ -906,19 +828,10 @@
+ init_MY_globals($self);
+
+ foreach (@code) {
+ # Add our install targets as a dependency to all top-level install targets
+ s/^(install(?:_[a-z]+)?\s*::?\s*.*)$/$1 conf__install data__install/;
+-
+- # Now do the DESTDIR hack, if necessary.
+- next if !$mm_needs_destdir;
+- # Write the correct path to perllocal.pod
+- next if /installed into/;
+-
+- # Replace all other $(INSTALL*) vars (except $(INSTALLDIRS) of course)
+- # with their $(DESTINSTALL*) counterparts
+- s/\Q$(\E(INSTALL(?!DIRS)${MACRO_RE})\Q)\E/\$(DEST$1)/g;
+ }
+
+ clean_MY_globals($self);
+ return join("\n", @code);
+ }
+@@ -956,32 +869,10 @@
+ set_macro($rprefix, macro_ref('PREFIX'));
+ $line .= "\n" . macro_def($rprefix);
+ }
+ }
+ }
+-
+- if (line_has_macro_def($line, 'MM_VERSION')) {
+- # These macros are just for debugging purposes.
+- $line = join("\n", $line,
+- macro_def(MM_HAS_DESTDIR => ::yesno($mm_has_destdir)),
+- macro_def(MM_HAS_GOOD_DESTDIR => ::yesno($mm_has_good_destdir)),
+- macro_def(MM_KNOWS_DESTDIR => ::yesno($mm_knows_destdir)),
+- macro_def(MM_NEEDS_DESTDIR => ::yesno($mm_needs_destdir)),
+- );
+- }
+-
+- # Add DESTDIR support if necessary
+- if ($mm_needs_destdir) {
+- if (line_has_macro_def($line, 'INSTALLDIRS')) {
+- $line .= "\n" . macro_def('DESTDIR');
+- }
+- elsif (line_has_macro_def($line, qr/INSTALL${MACRO_RE}/)) {
+- my $macro = get_macro_name_from_line($line);
+- $line .= "\n" . macro_def('DEST' . $macro,
+- macro_ref('DESTDIR') . macro_ref($macro));
+- }
+- }
+ }
+ push(@code, qq{});
+
+ # Add some additional target dirs
+ {
+@@ -1015,13 +906,11 @@
+ foreach my $r (@REPOSITORIES) {
+ my $macro = 'INSTALL' . repository($r) . $m;
+ # The INSTALL* macros.
+ push(@code, macro_def($macro));
+ # The DESTINSTALL* macros.
+- push(@code, macro_def('DEST' . $macro,
+- macro_ref('DESTDIR') . macro_ref($macro)))
+- if $mm_has_destdir;
++ push(@code, macro_def('DEST' . $macro, macro_ref('DESTDIR') . macro_ref($macro)));
+ }
+ }
+ }
+
+ # Set the PERL_* stuff
+@@ -1068,17 +957,12 @@
+ # SCRIPT macro is the same for all repositories.
+ foreach my $macro (qw(SCRIPT DATA CONF LIB)) {
+ push(@code, macro_def('I_' . $macro . 'DIR',
+ macro_ref('INSTALL' . repository($repository, $macro eq 'SCRIPT') . $macro)));
+
+- if ($mm_has_destdir) {
+- push(@code, macro_def('B_' . $macro . 'DIR',
+- macro_ref('DESTINSTALL' . repository($repository, $macro eq 'SCRIPT') . $macro)));
+- } else {
+- push(@code, macro_def('B_' . $macro . 'DIR',
+- macro_ref('I_' . $macro . 'DIR')));
+- }
++ push(@code, macro_def('B_' . $macro . 'DIR',
++ macro_ref('DESTINSTALL' . repository($repository, $macro eq 'SCRIPT') . $macro)));
+ }
+ }
+
+ clean_MY_globals($self);
+ return join("\n", @code);
diff --git a/main/perl-mail-spf/APKBUILD b/main/perl-mail-spf/APKBUILD
new file mode 100644
index 0000000000..9ef1e05021
--- /dev/null
+++ b/main/perl-mail-spf/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-mail-spf
+_realname=Mail-SPF
+pkgver=2.007
+pkgrel=2
+pkgdesc="An object-oriented implementation of Sender Policy Framework"
+url="http://search.cpan.org/~jmehnle/Mail-SPF-v2.006/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl perl-error perl-net-dns perl-uri-escape perl-netaddr-ip
+ perl-net-dns-resolver-programmable"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JM/JMEHNLE/mail-spf/$_realname-v$pkgver.tar.gz
+ build.patch"
+
+_builddir="$srcdir/$_realname-v$pkgver"
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="67dccdc91e3264679a0e17d493d3cc30 Mail-SPF-v2.007.tar.gz
+7a32f8edc2aee8c6db0d8c2c84a570aa build.patch"
diff --git a/main/perl-mail-spf/build.patch b/main/perl-mail-spf/build.patch
new file mode 100644
index 0000000000..0d88c2d1d8
--- /dev/null
+++ b/main/perl-mail-spf/build.patch
@@ -0,0 +1,62 @@
+commit 7fbde4f5cbf4d989ccd477e63a83d84ceccb2439
+Author: Todd Rinaldo <toddr@cpan.org>
+Date: Thu Feb 4 12:24:31 2010 -0600
+
+ Remove use of v and qv notation which breaks install of older perls
+
+diff --git a/Build.PL b/Build.PL
+index 15bb927..290c4ce 100644
+--- a/Build.PL
++++ b/Build.PL
+@@ -48,7 +48,7 @@ my $build = $class->new(
+ license => 'bsd',
+ requires => {
+ # Core requirements:
+- perl => 'v5.6',
++ perl => '5.006',
+ version => 0,
+ Error => 0,
+ NetAddr::IP => '4',
+@@ -63,7 +63,7 @@ my $build = $class->new(
+ Module::Build => '0.2805',
+ Test::More => 0,
+ Net::DNS::Resolver::Programmable
+- => 'v0.002.1',
++ => '0.002001',
+ },
+ script_files => [
+ 'bin/spfquery'
+diff --git a/CHANGES b/CHANGES
+index b7c4303..838d24a 100644
+--- a/CHANGES
++++ b/CHANGES
+@@ -4,6 +4,11 @@
+ # ! = Changed something significant, or removed a feature
+ # * = Fixed a bug, or made a minor improvement
+
++--- 2.008 (2010-02-04 12:00)
++
++ Miscellaneous:
++ * Fix version numbers to provide perl compaibility prior to 5.8
++
+ --- 2.007 (2009-10-31 21:00)
+
+ Mail::SPF:
+diff --git a/lib/Mail/SPF.pm b/lib/Mail/SPF.pm
+index 67d1e5c..4a62632 100644
+--- a/lib/Mail/SPF.pm
++++ b/lib/Mail/SPF.pm
+@@ -17,11 +17,11 @@ Mail::SPF - An object-oriented implementation of Sender Policy Framework
+
+ =head1 VERSION
+
+-2.007
++2.008
+
+ =cut
+
+-use version; our $VERSION = qv('2.007');
++use version; our $VERSION = '2.008';
+
+ use warnings;
+ use strict;
diff --git a/main/perl-mail-tools/APKBUILD b/main/perl-mail-tools/APKBUILD
new file mode 100644
index 0000000000..518d9e8132
--- /dev/null
+++ b/main/perl-mail-tools/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-mail-tools
+_realname=MailTools
+pkgver=2.07
+pkgrel=2
+pkgdesc="Manipulation of electronic mail addresses"
+url="http://search.cpan.org/~markov/MailTools-2.04/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl perl-time-date perl-test-pod"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MA/MARKOV/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="df861e05cbcf3a336ecebfb2c42529d0 MailTools-2.07.tar.gz"
diff --git a/main/perl-math-round/APKBUILD b/main/perl-math-round/APKBUILD
new file mode 100644
index 0000000000..e6532a17e7
--- /dev/null
+++ b/main/perl-math-round/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-math-round
+pkgver=0.06
+pkgrel=0
+pkgdesc="Math::Round perl module"
+url="http://search.cpan.org/dist/Math-Round/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GR/GROMMEL/Math-Round-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Math-Round-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="552cef2753b246f97a6e20d8dee66e7c Math-Round-0.06.tar.gz"
diff --git a/main/perl-mime-lite/APKBUILD b/main/perl-mime-lite/APKBUILD
new file mode 100644
index 0000000000..8686eea9e1
--- /dev/null
+++ b/main/perl-mime-lite/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-mime-lite
+_pkgreal=MIME-Lite
+pkgver=3.027
+pkgrel=3
+pkgdesc="low-calorie MIME generator"
+url="http://search.cpan.org/dist/MIME-Lite/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-mime-types perl-email-date-format perl-mail-tools"
+cpanmakedepends=""
+depends="perl $cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="e857febd66c45f2a5919b031fbe70aa7 MIME-Lite-3.027.tar.gz"
diff --git a/main/perl-mime-tools/APKBUILD b/main/perl-mime-tools/APKBUILD
new file mode 100644
index 0000000000..9644666d9d
--- /dev/null
+++ b/main/perl-mime-tools/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-mime-tools
+_realname=MIME-tools
+pkgver=5.500
+pkgrel=0
+pkgdesc="Perl modules for parsing (and creating!) MIME entities"
+url="http://search.cpan.org/~doneill/MIME-tools-5.427/"
+arch="noarch"
+license="PerlArtistic GPL"
+depends="perl perl-io-stringy perl-mail-tools perl-convert-binhex"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DO/DONEILL/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="e1d28e4fbaedc47ff44c87b91be7f404 MIME-tools-5.500.tar.gz"
diff --git a/main/perl-mime-types/APKBUILD b/main/perl-mime-types/APKBUILD
new file mode 100644
index 0000000000..c9726ed4b4
--- /dev/null
+++ b/main/perl-mime-types/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-mime-types
+_pkgreal=MIME-Types
+pkgver=1.31
+pkgrel=0
+pkgdesc="Definition of MIME types"
+url="http://search.cpan.org/dist/MIME-Types/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MA/MARKOV/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="d4435eb012e813682f94d285b40339ce MIME-Types-1.31.tar.gz"
diff --git a/main/perl-module-versions-report/APKBUILD b/main/perl-module-versions-report/APKBUILD
new file mode 100644
index 0000000000..2e0ff1c169
--- /dev/null
+++ b/main/perl-module-versions-report/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-module-versions-report
+pkgver=1.06
+pkgrel=0
+pkgdesc="Module::Versions::Report perl module"
+url="http://search.cpan.org/dist/Module-Versions-Report/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JE/JESSE/Module-Versions-Report-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Module-Versions-Report-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="9c7efaa4c3dd8eecceb8e5d17476479b Module-Versions-Report-1.06.tar.gz"
diff --git a/main/perl-net-cidr-lite/APKBUILD b/main/perl-net-cidr-lite/APKBUILD
new file mode 100644
index 0000000000..63b9c6fd8e
--- /dev/null
+++ b/main/perl-net-cidr-lite/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=perl-net-cidr-lite
+_realname=Net-CIDR-Lite
+pkgver=0.21
+pkgrel=2
+pkgdesc="Perl extension for merging IPv4 or IPv6 CIDR addresses"
+url="http://search.cpan.org/~dougw/Net-CIDR-Lite-0.21/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DO/DOUGW/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="12280b3754886b876918f03f53aee4f5 Net-CIDR-Lite-0.21.tar.gz"
diff --git a/main/perl-net-cidr/APKBUILD b/main/perl-net-cidr/APKBUILD
new file mode 100644
index 0000000000..1304a27463
--- /dev/null
+++ b/main/perl-net-cidr/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-net-cidr
+pkgver=0.14
+pkgrel=0
+pkgdesc="Manipulate IPv4/IPv6 netblocks in CIDR notation"
+url="http://search.cpan.org/dist/Net-CIDR/"
+arch="noarch"
+license="GPL+ or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MR/MRSAM/testing/Net-CIDR-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Net-CIDR-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="52081c62fe551a205127025c09698ec5 Net-CIDR-0.14.tar.gz"
diff --git a/main/perl-net-dns-resolver-programmable/APKBUILD b/main/perl-net-dns-resolver-programmable/APKBUILD
new file mode 100644
index 0000000000..cf01205207
--- /dev/null
+++ b/main/perl-net-dns-resolver-programmable/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-net-dns-resolver-programmable
+pkgver=0.003
+pkgrel=2
+pkgdesc="programmable DNS resolver perl class for offline emulation of DNS"
+url="http://search.cpan.org/search?query=Net::DNS::Resolver::Programmable&mode=all"
+arch="noarch"
+license="Perl Artistic"
+depends="perl perl-net-dns"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JM/JMEHNLE/net-dns-resolver-programmable/Net-DNS-Resolver-Programmable-v$pkgver.tar.gz"
+
+_builddir="$srcdir"/Net-DNS-Resolver-Programmable-v$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ find "$pkgdir" \( -name '.packlist' -o -name 'perllocal.pod' \) -delete
+}
+
+md5sums="8d44bf331d6115e7fb4ea21f6cf4b96b Net-DNS-Resolver-Programmable-v0.003.tar.gz"
diff --git a/main/perl-net-dns/APKBUILD b/main/perl-net-dns/APKBUILD
new file mode 100644
index 0000000000..b43e7a967e
--- /dev/null
+++ b/main/perl-net-dns/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-net-dns
+_realname=Net-DNS
+pkgver=0.66
+pkgrel=6
+pkgdesc="Perl interface to the DNS resolver"
+url="http://search.cpan.org/~olaf/Net-DNS-0.66"
+arch="all"
+license="unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/O/OL/OLAF/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="1635d876324e3c2f6e277d5778bfe94c Net-DNS-0.66.tar.gz"
diff --git a/main/perl-net-http/APKBUILD b/main/perl-net-http/APKBUILD
new file mode 100644
index 0000000000..a9a8091726
--- /dev/null
+++ b/main/perl-net-http/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-net-http
+pkgver=6.01
+pkgrel=1
+pkgdesc="Net::HTTP perl module"
+url="http://search.cpan.org/dist/Net-HTTP/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+replaces="perl-libwww"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/Net-HTTP-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Net-HTTP-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="d7ae2675fca351147adcd26f840b6993 Net-HTTP-6.01.tar.gz"
diff --git a/main/perl-net-ip/APKBUILD b/main/perl-net-ip/APKBUILD
new file mode 100644
index 0000000000..43268a93ef
--- /dev/null
+++ b/main/perl-net-ip/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-net-ip
+_realname=Net-IP
+pkgver=1.25
+pkgrel=2
+pkgdesc="Perl extension for manipulating IPv4/IPv6 addresses"
+url="http://search.cpan.org/~manu/Net-IP-1.25/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MA/MANU/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="a49c0b02a9b793ff60191cdafc0c202e Net-IP-1.25.tar.gz"
diff --git a/main/perl-net-rblclient/APKBUILD b/main/perl-net-rblclient/APKBUILD
new file mode 100644
index 0000000000..41b6bba293
--- /dev/null
+++ b/main/perl-net-rblclient/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=perl-net-rblclient
+_realname=Net-RBLClient
+pkgver=0.5
+pkgrel=2
+pkgdesc="Queries multiple Realtime Blackhole Lists in parallel"
+url="http://search.cpan.org/dist/Net-RBLClient/"
+arch="noarch"
+license="unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AB/ABLUM/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/RBLCLient-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/RBLCLient-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="1fb9961106cbb5a6eb2257762847e502 Net-RBLClient-0.5.tar.gz"
diff --git a/main/perl-net-server/APKBUILD b/main/perl-net-server/APKBUILD
new file mode 100644
index 0000000000..05a1cd2523
--- /dev/null
+++ b/main/perl-net-server/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-net-server
+_realname=Net-Server
+pkgver=0.99
+pkgrel=1
+pkgdesc="Extensible, general Perl server engine"
+url="http://search.cpan.org/~rhandom/Net-Server-0.97/"
+arch="noarch"
+license="unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RH/RHANDOM/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="1ae03dff8b1009216a2e5d8f4c9a47b1 Net-Server-0.99.tar.gz"
diff --git a/main/perl-net-smtp-ssl/APKBUILD b/main/perl-net-smtp-ssl/APKBUILD
new file mode 100644
index 0000000000..c8f979bcb8
--- /dev/null
+++ b/main/perl-net-smtp-ssl/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-net-smtp-ssl
+_realname=Net-SMTP-SSL
+pkgver=1.01
+pkgrel=2
+pkgdesc="SSL support for Net::SMTP"
+url="http://search.cpan.org/dist/Net-SMTP-SSL/"
+arch="noarch"
+license="GPL"
+depends="perl perl-io-socket-ssl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CW/CWEST/Net-SMTP-SSL-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="ba039288ebf7a343feecacd374da8c1a Net-SMTP-SSL-1.01.tar.gz"
diff --git a/main/perl-net-snpp/APKBUILD b/main/perl-net-snpp/APKBUILD
new file mode 100644
index 0000000000..9221bc6a56
--- /dev/null
+++ b/main/perl-net-snpp/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Jeff Bilyk <jbilyk@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-net-snpp
+_realname=Net-SNPP
+pkgver=1.17
+pkgrel=2
+pkgdesc="Perl Simple Network Pager Protocol Client"
+url="http://search.cpan.org/~tobeya/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages=""
+source="http://search.cpan.org/CPAN/authors/id/T/TO/TOBEYA/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+
+}
+
+md5sums="18f61a774906cd27ca14dcbf311e6bf0 Net-SNPP-1.17.tar.gz"
diff --git a/main/perl-net-ssleay/APKBUILD b/main/perl-net-ssleay/APKBUILD
new file mode 100644
index 0000000000..71d550e19a
--- /dev/null
+++ b/main/perl-net-ssleay/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-net-ssleay
+_realname=Net-SSLeay
+pkgver=1.36
+pkgrel=4
+pkgdesc="Perl extension for using OpenSSL"
+url="http://search.cpan.org/dist/Net-SSLeay/"
+arch="all"
+license="GPL"
+depends="perl"
+makedepends="perl-dev openssl-dev zlib-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/F/FL/FLORA/Net-SSLeay-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="54061638720dd6a325395331c77f21d8 Net-SSLeay-1.36.tar.gz"
diff --git a/main/perl-netaddr-ip/APKBUILD b/main/perl-netaddr-ip/APKBUILD
new file mode 100644
index 0000000000..bddc912e49
--- /dev/null
+++ b/main/perl-netaddr-ip/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-netaddr-ip
+_realname=NetAddr-IP
+pkgver=4.037
+pkgrel=1
+pkgdesc="Perl extension for managing IPv4 and IPv6 addresses and subnets"
+url="http://search.cpan.org/~miker/NetAddr-IP-$pkgver/"
+arch="all"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MI/MIKER/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ return 0
+}
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="d966eac6b5941af3f7c1fad839569cb4 NetAddr-IP-4.037.tar.gz"
diff --git a/main/perl-parallel-prefork/APKBUILD b/main/perl-parallel-prefork/APKBUILD
new file mode 100644
index 0000000000..d78ce27c2c
--- /dev/null
+++ b/main/perl-parallel-prefork/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-parallel-prefork
+_pkgreal=Parallel-Prefork
+pkgver=0.11
+pkgrel=0
+pkgdesc="A simple prefork server framework"
+url="http://search.cpan.org/dist/Parallel-Prefork/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-proc-wait3 perl-class-accessor-lite perl-list-moreutils perl-scope-guard"
+cpanmakedepends="perl-test-requires"
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/K/KA/KAZUHO/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="d4b9347c414e7f0d30708e14e05ee3a6 Parallel-Prefork-0.11.tar.gz"
diff --git a/main/perl-params-util/APKBUILD b/main/perl-params-util/APKBUILD
new file mode 100644
index 0000000000..2accecfdba
--- /dev/null
+++ b/main/perl-params-util/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-params-util
+pkgver=1.04
+pkgrel=0
+pkgdesc="Params::Util perl module"
+url="http://search.cpan.org/dist/Params-Util/"
+arch="all"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AD/ADAMK/Params-Util-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Params-Util-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ unset CFLAGS
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="84bfb0a16cff67f2077ece0e24408b0f Params-Util-1.04.tar.gz"
diff --git a/main/perl-params-validate/APKBUILD b/main/perl-params-validate/APKBUILD
new file mode 100644
index 0000000000..c6255564ce
--- /dev/null
+++ b/main/perl-params-validate/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-params-validate
+pkgver=0.99
+pkgrel=0
+pkgdesc="Params-Validate Perl module"
+url="http://search.cpan.org/dist/Params-Validate/"
+arch="all"
+license="GPL+ or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DR/DROLSKY/Params-Validate-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Params-Validate-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ unset CFLAGS
+ perl Build.PL installdirs=vendor || return 1
+ ./Build
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" create_packlist=0 || return 1
+}
+
+md5sums="218b0e970b3568eeddf83f65b24657f6 Params-Validate-0.99.tar.gz"
diff --git a/main/perl-parse-recdescent/APKBUILD b/main/perl-parse-recdescent/APKBUILD
new file mode 100644
index 0000000000..6671e30f41
--- /dev/null
+++ b/main/perl-parse-recdescent/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-parse-recdescent
+_realname=Parse-RecDescent
+pkgver=1.965001
+pkgrel=1
+pkgdesc="Generate Recursive-Descent Parsers"
+url="http://search.cpan.org/~dconway/Parse-RecDescent-1.96.0/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DC/DCONWAY/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="e91351ad179a3843fbe8e521b135acaf Parse-RecDescent-1.965001.tar.gz"
diff --git a/main/perl-parse-syslog/APKBUILD b/main/perl-parse-syslog/APKBUILD
new file mode 100644
index 0000000000..ef2ec280be
--- /dev/null
+++ b/main/perl-parse-syslog/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=perl-parse-syslog
+_realname=Parse-Syslog
+pkgver=1.10
+pkgrel=2
+pkgdesc="Parse Unix syslog files"
+url="http://search.cpan.org/~dschwei/Parse-Syslog-1.10/"
+arch="noarch"
+license="unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DS/DSCHWEI/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="e1c4c03aaa7cb8d2baa52f294dd9accc Parse-Syslog-1.10.tar.gz"
diff --git a/main/perl-php-serialization/APKBUILD b/main/perl-php-serialization/APKBUILD
new file mode 100644
index 0000000000..afe3edfc78
--- /dev/null
+++ b/main/perl-php-serialization/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-php-serialization
+_realname=PHP-Serialization
+pkgver=0.34
+pkgrel=1
+pkgdesc="Simple flexible means of converting the output of PHP's serialize() into the equivalent Perl memory structure, and vice versa."
+url="http://search.cpan.org/~bobtfish/PHP-Serialization-$pkgver"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/B/BO/BOBTFISH/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="333af0848ad79931875a35cc61dc22e0 PHP-Serialization-0.34.tar.gz"
diff --git a/main/perl-plack/APKBUILD b/main/perl-plack/APKBUILD
new file mode 100644
index 0000000000..6746ef0932
--- /dev/null
+++ b/main/perl-plack/APKBUILD
@@ -0,0 +1,50 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-plack
+pkgver=0.9979
+pkgrel=0
+pkgdesc="Plack perl module"
+url="http://search.cpan.org/dist/Plack/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl
+ perl-devel-stacktrace
+ perl-devel-stacktrace-ashtml
+ perl-file-sharedir
+ perl-filesys-notify-simple
+ perl-http-body
+ perl-test-tcp
+ perl-hash-multivalue
+ perl-libwww
+ perl-try-tiny
+ perl-uri
+ "
+makedepends="perl-dev perl-test-requires"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MI/MIYAGAWA/Plack-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Plack-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="8361de1b1b628b5e82f556429bba8095 Plack-0.9979.tar.gz"
diff --git a/main/perl-pod-coverage/APKBUILD b/main/perl-pod-coverage/APKBUILD
new file mode 100644
index 0000000000..0cf141704e
--- /dev/null
+++ b/main/perl-pod-coverage/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-pod-coverage
+_realname=Pod-Coverage
+pkgver=0.20
+pkgrel=3
+pkgdesc="Perl - Checks if the documentation of a module is comprehensive"
+url="http://search.cpan.org/~rclamp/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl perl-devel-symdump perl-test-pod"
+makedepends="perl-dev"
+install=
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RC/RCLAMP/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="292a5b8d3a93597af441d3e6467b8ad6 Pod-Coverage-0.20.tar.gz"
diff --git a/main/perl-proc-wait3/APKBUILD b/main/perl-proc-wait3/APKBUILD
new file mode 100644
index 0000000000..424e616e03
--- /dev/null
+++ b/main/perl-proc-wait3/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-proc-wait3
+_pkgreal=Proc-Wait3
+pkgver=0.04
+pkgrel=0
+pkgdesc="Perl extension for wait3 system call"
+url="http://search.cpan.org/dist/Proc-Wait3/"
+arch="all"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CT/CTILMES/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="d87ce5f3557eb86bfa5bafb9f2e028e3 Proc-Wait3-0.04.tar.gz"
diff --git a/main/perl-regexp-common-net-cidr/APKBUILD b/main/perl-regexp-common-net-cidr/APKBUILD
new file mode 100644
index 0000000000..087be7b534
--- /dev/null
+++ b/main/perl-regexp-common-net-cidr/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-regexp-common-net-cidr
+pkgver=0.02
+pkgrel=0
+pkgdesc="Regexp::Common::net::CIDR perl module"
+url="http://search.cpan.org/dist/Regexp-Common-net-CIDR/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-regexp-common"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RU/RUZ/Regexp-Common-net-CIDR-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Regexp-Common-net-CIDR-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="e109d32c7ed46956477cf94e54d1442a Regexp-Common-net-CIDR-0.02.tar.gz"
diff --git a/main/perl-regexp-common/APKBUILD b/main/perl-regexp-common/APKBUILD
new file mode 100644
index 0000000000..29055d826c
--- /dev/null
+++ b/main/perl-regexp-common/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-regexp-common
+pkgver=2011041701
+pkgrel=0
+pkgdesc="Regexp::Common perl module"
+url="http://search.cpan.org/dist/Regexp-Common/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AB/ABIGAIL/Regexp-Common-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Regexp-Common-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="7e6bef3eefff91ecb2f07b1e81217650 Regexp-Common-2011041701.tar.gz"
diff --git a/main/perl-regexp-ipv6/APKBUILD b/main/perl-regexp-ipv6/APKBUILD
new file mode 100644
index 0000000000..179fc4d351
--- /dev/null
+++ b/main/perl-regexp-ipv6/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-regexp-ipv6
+pkgver=0.03
+pkgrel=0
+pkgdesc="Regexp::IPv6 perl module"
+url="http://search.cpan.org/dist/Regexp-IPv6/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SA/SALVA/Regexp-IPv6-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Regexp-IPv6-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="892abe3f43eb0cc76283767f99a335e6 Regexp-IPv6-0.03.tar.gz"
diff --git a/main/perl-scope-guard/APKBUILD b/main/perl-scope-guard/APKBUILD
new file mode 100644
index 0000000000..bd47064304
--- /dev/null
+++ b/main/perl-scope-guard/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-scope-guard
+pkgver=0.20
+pkgrel=0
+pkgdesc="Scope::Guard perl module"
+url="http://search.cpan.org/dist/Scope-Guard/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CH/CHOCOLATE/Scope-Guard-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Scope-Guard-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="495d5ae16a2df8128fd068c386c9d4ac Scope-Guard-0.20.tar.gz"
diff --git a/main/perl-server-starter/APKBUILD b/main/perl-server-starter/APKBUILD
new file mode 100644
index 0000000000..e1613a863d
--- /dev/null
+++ b/main/perl-server-starter/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-server-starter
+_pkgreal=Server-Starter
+pkgver=0.11
+pkgrel=0
+pkgdesc="a superdaemon for hot-deploying server programs"
+url="http://search.cpan.org/dist/Server-Starter/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-proc-wait3 perl-list-moreutils perl-scope-guard"
+cpanmakedepends="perl-test-tcp"
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/K/KA/KAZUHO/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="037d75831a23ca76cd306d678b20332e Server-Starter-0.11.tar.gz"
diff --git a/main/perl-snmp-session/APKBUILD b/main/perl-snmp-session/APKBUILD
new file mode 100644
index 0000000000..a8d9435cea
--- /dev/null
+++ b/main/perl-snmp-session/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-snmp-session
+_name=SNMP_Session
+pkgver=1.13
+pkgrel=2
+pkgdesc="A SNMP Perl Module"
+url="http://code.google.com/p/snmp-session/"
+arch="noarch"
+license="PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+source="http://snmp-session.googlecode.com/files/$_name-$pkgver.tar.gz"
+
+build () {
+ cd "$srcdir"/$_name-$pkgver
+ perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make MAN1EXT=1p MAN3EXT=3pm || return 1
+}
+
+package() {
+ cd "$srcdir"/$_name-$pkgver
+ make install MAN1EXT=1p MAN3EXT=3pm DESTDIR="$pkgdir" || return 1
+ find "$pkgdir" -name perllocal.pod -delete
+ find "$pkgdir" -name .packlist -delete
+}
+md5sums="055e1065babf55f1f8606329c6bdb947 SNMP_Session-1.13.tar.gz"
diff --git a/main/perl-socket-getaddrinfo/APKBUILD b/main/perl-socket-getaddrinfo/APKBUILD
new file mode 100644
index 0000000000..e2c439fc71
--- /dev/null
+++ b/main/perl-socket-getaddrinfo/APKBUILD
@@ -0,0 +1,30 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-socket-getaddrinfo
+_pkgreal=Socket-GetAddrInfo
+pkgver=0.20
+pkgrel=1
+pkgdesc="Perl interface for get{addr,name}info(3)"
+url="http://search.cpan.org/dist/Socket-GetAddrInfo/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl-extutils-cchecker"
+makedepends="perl-dev"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PE/PEVANS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name .packlist -name perllocal.pod -delete
+}
+
+md5sums="6fd3dc7f0ce9ca20a540372711533472 Socket-GetAddrInfo-0.20.tar.gz"
diff --git a/main/perl-starlet/APKBUILD b/main/perl-starlet/APKBUILD
new file mode 100644
index 0000000000..991872f860
--- /dev/null
+++ b/main/perl-starlet/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-starlet
+_pkgreal=Starlet
+pkgver=0.13
+pkgrel=0
+pkgdesc="a simple, high-performance PSGI/Plack HTTP server"
+url="http://search.cpan.org/dist/Starlet/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-server-starter perl-plack perl-parallel-prefork"
+cpanmakedepends="perl-test-tcp"
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/K/KA/KAZUHO/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="222eff2e8e5d69a44a8a3935fb8837cd Starlet-0.13.tar.gz"
diff --git a/main/perl-sub-exporter/APKBUILD b/main/perl-sub-exporter/APKBUILD
new file mode 100644
index 0000000000..800fa31282
--- /dev/null
+++ b/main/perl-sub-exporter/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-sub-exporter
+pkgver=0.982
+pkgrel=0
+pkgdesc="Sub::Exporter perl module"
+url="http://search.cpan.org/dist/Sub-Exporter/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-data-optlist perl-sub-install"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/Sub-Exporter-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Sub-Exporter-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="db90a0d73a5ca2d185dd6c6d2fc848f0 Sub-Exporter-0.982.tar.gz"
diff --git a/main/perl-sub-install/APKBUILD b/main/perl-sub-install/APKBUILD
new file mode 100644
index 0000000000..6dc887b8c4
--- /dev/null
+++ b/main/perl-sub-install/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-sub-install
+pkgver=0.925
+pkgrel=0
+pkgdesc="Sub::Install perl module"
+url="http://search.cpan.org/dist/Sub-Install/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/Sub-Install-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Sub-Install-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="694aaec771c42280746a9a6279683263 Sub-Install-0.925.tar.gz"
diff --git a/main/perl-sub-uplevel/APKBUILD b/main/perl-sub-uplevel/APKBUILD
new file mode 100644
index 0000000000..dff6a14fcb
--- /dev/null
+++ b/main/perl-sub-uplevel/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-sub-uplevel
+_realname=Sub-Uplevel
+pkgver=0.22
+pkgrel=2
+pkgdesc="Perl - Apparently run a function in a higher stack frame"
+url="http://search.cpan.org/~dagolden/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl "
+makedepends="perl-dev"
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DA/DAGOLDEN/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="c166738a97c0424a0075ebe205d285db Sub-Uplevel-0.22.tar.gz"
diff --git a/main/perl-switch/APKBUILD b/main/perl-switch/APKBUILD
new file mode 100644
index 0000000000..0d43829d30
--- /dev/null
+++ b/main/perl-switch/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-switch
+pkgver=2.16
+pkgrel=0
+pkgdesc="A switch statement for Perl"
+url="http://search.cpan.org/~rgarcia/Switch-$pkgver/"
+arch="noarch"
+license="Perl"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RG/RGARCIA/Switch-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Switch-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="bf75dc7f171b4718a2118c3d6cbe6013 Switch-2.16.tar.gz"
diff --git a/main/perl-sys-hostname-long/APKBUILD b/main/perl-sys-hostname-long/APKBUILD
new file mode 100644
index 0000000000..154b961dbc
--- /dev/null
+++ b/main/perl-sys-hostname-long/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Jeff Bilyk <jbilyk@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-sys-hostname-long
+_realname=Sys-Hostname-Long
+pkgver=1.4
+pkgrel=2
+pkgdesc="Perl Module to get full hostname"
+url="http://search.cpan.org/~scott/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages=""
+source="http://search.cpan.org/CPAN/authors/id/S/SC/SCOTT/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+
+}
+
+md5sums="a5b3c23754cbcff10e283d16c42ec3d3 Sys-Hostname-Long-1.4.tar.gz"
diff --git a/main/perl-sys-mmap/APKBUILD b/main/perl-sys-mmap/APKBUILD
new file mode 100644
index 0000000000..4c9f89099a
--- /dev/null
+++ b/main/perl-sys-mmap/APKBUILD
@@ -0,0 +1,29 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-sys-mmap
+_realname=Sys-Mmap
+pkgver=0.15
+pkgrel=1
+pkgdesc="Uses mmap to map in a file as a Perl variable"
+url="http://search.cpan.org/~toddr/Sys-Mmap-0.14/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/T/TO/TODDR/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+md5sums="779453c3950a8370bae04aff1cfbaf90 Sys-Mmap-0.15.tar.gz"
diff --git a/main/perl-term-readkey/APKBUILD b/main/perl-term-readkey/APKBUILD
new file mode 100644
index 0000000000..5c39772bd1
--- /dev/null
+++ b/main/perl-term-readkey/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-term-readkey
+_pkgreal=TermReadKey
+pkgver=2.14
+pkgrel=0
+pkgdesc="Change terminal modes, and perform non-blocking reads"
+url="http://search.cpan.org/dist/TermReadKey/"
+arch="all"
+license="AS-IS"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/K/KJ/KJALB/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="d8ed4c533350c2e8724c70c103a1a01f TermReadKey-2.14.tar.gz"
diff --git a/main/perl-test-deep/APKBUILD b/main/perl-test-deep/APKBUILD
new file mode 100644
index 0000000000..353acb4748
--- /dev/null
+++ b/main/perl-test-deep/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-test-deep
+pkgver=0.108
+pkgrel=0
+pkgdesc="Test::Deep perl module"
+url="http://search.cpan.org/dist/Test-Deep/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-test-tester perl-test-nowarnings"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/Test-Deep-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Test-Deep-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="df17efafc31acb927cc1d950115f4178 Test-Deep-0.108.tar.gz"
diff --git a/main/perl-test-exception/APKBUILD b/main/perl-test-exception/APKBUILD
new file mode 100644
index 0000000000..df814f10f0
--- /dev/null
+++ b/main/perl-test-exception/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-test-exception
+_realname=Test-Exception
+pkgver=0.29
+pkgrel=2
+pkgdesc="Perl - Test exception based code"
+url="http://search.cpan.org/~adie/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl perl-sub-uplevel"
+makedepends="perl-dev"
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AD/ADIE/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="9aea475db531d4fd4ce40cf25a0acd14 Test-Exception-0.29.tar.gz"
diff --git a/main/perl-test-fatal/APKBUILD b/main/perl-test-fatal/APKBUILD
new file mode 100644
index 0000000000..8b86b49424
--- /dev/null
+++ b/main/perl-test-fatal/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+pkgname=perl-test-fatal
+_pkgreal=Test-Fatal
+pkgver=0.006
+pkgrel=0
+pkgdesc="incredibly simple helpers for testing code with exceptions"
+url="http://search.cpan.org/dist/Test-Fatal/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-try-tiny"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RJ/RJBS/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="a984aa4d4088892c0454cbfce35e54d9 Test-Fatal-0.006.tar.gz"
diff --git a/main/perl-test-inter/APKBUILD b/main/perl-test-inter/APKBUILD
new file mode 100644
index 0000000000..e7e48fe885
--- /dev/null
+++ b/main/perl-test-inter/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-test-inter
+_realname=Test-Inter
+pkgver=1.01
+pkgrel=2
+pkgdesc="Perl - Framework for more readable interactive test scripts"
+url="http://search.cpan.org/~sbeck/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl perl-test-pod perl-pod-coverage perl-test-pod-coverage"
+makedepends="perl-dev"
+install=
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SB/SBECK/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="445166a7472e609b96e4474d95552827 Test-Inter-1.01.tar.gz"
diff --git a/main/perl-test-longstring/APKBUILD b/main/perl-test-longstring/APKBUILD
new file mode 100644
index 0000000000..a3f895f12a
--- /dev/null
+++ b/main/perl-test-longstring/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-test-longstring
+pkgver=0.15
+pkgrel=0
+pkgdesc="Test::LongString perl module"
+url="http://search.cpan.org/dist/Test-LongString/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RG/RGARCIA/Test-LongString-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Test-LongString-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="e628d735b8e8f33d3992541f823491c3 Test-LongString-0.15.tar.gz"
diff --git a/main/perl-test-manifest/APKBUILD b/main/perl-test-manifest/APKBUILD
new file mode 100644
index 0000000000..28c5b353c7
--- /dev/null
+++ b/main/perl-test-manifest/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-test-manifest
+pkgver=1.23
+pkgrel=0
+pkgdesc="Test::Manifest perl module"
+url="http://search.cpan.org/dist/Test-Manifest/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages=
+source="http://search.cpan.org/CPAN/authors/id/B/BD/BDFOY/Test-Manifest-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Test-Manifest-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="81c8744987b67d35af05a74a3c7f1742 Test-Manifest-1.23.tar.gz"
diff --git a/main/perl-test-mockobject/APKBUILD b/main/perl-test-mockobject/APKBUILD
new file mode 100644
index 0000000000..6b01b5d376
--- /dev/null
+++ b/main/perl-test-mockobject/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Jeff Bilyk <jbilyk@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-test-mockobject
+_realname=Test-MockObject
+pkgver=1.09
+pkgrel=2
+pkgdesc="Perl Mock part of an object or class"
+url="http://search.cpan.org/~chromatic/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages=""
+source="http://search.cpan.org/CPAN/authors/id/C/CH/CHROMATIC/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+
+}
+
+md5sums="3c9c2842d40fa8c389563c227804d7d8 Test-MockObject-1.09.tar.gz"
diff --git a/main/perl-test-nowarnings/APKBUILD b/main/perl-test-nowarnings/APKBUILD
new file mode 100644
index 0000000000..8a99754550
--- /dev/null
+++ b/main/perl-test-nowarnings/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-test-nowarnings
+pkgver=1.02
+pkgrel=0
+pkgdesc="Test::NoWarnings perl module"
+url="http://search.cpan.org/dist/Test-NoWarnings/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-test-tester"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/A/AD/ADAMK/Test-NoWarnings-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Test-NoWarnings-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="6c5ae5613c66d6b5e4f0799085571a64 Test-NoWarnings-1.02.tar.gz"
diff --git a/main/perl-test-pod-coverage/APKBUILD b/main/perl-test-pod-coverage/APKBUILD
new file mode 100644
index 0000000000..d70d9f714a
--- /dev/null
+++ b/main/perl-test-pod-coverage/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-test-pod-coverage
+_realname=Test-Pod-Coverage
+pkgver=1.08
+pkgrel=3
+pkgdesc="Perl - Check for pod coverage in your distribution."
+url="http://search.cpan.org/~petdance/$_realname-$pkgver/"
+arch="noarch"
+license="Artistic GPL"
+depends="perl perl-pod-coverage perl-test-pod perl-devel-symdump"
+makedepends="perl-dev"
+install=
+#subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/P/PE/PETDANCE/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="33405cca7c75b7b89c06ba30eea66692 Test-Pod-Coverage-1.08.tar.gz"
diff --git a/main/perl-test-pod/APKBUILD b/main/perl-test-pod/APKBUILD
new file mode 100644
index 0000000000..5da9981e4f
--- /dev/null
+++ b/main/perl-test-pod/APKBUILD
@@ -0,0 +1,30 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-test-pod
+_realname=Test-Pod
+pkgver=1.44
+pkgrel=2
+pkgdesc="Check for POD errors in files"
+url="http://search.cpan.org/~petdance/Test-Pod-1.26/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DW/DWHEELER/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="02380af5539521524d5df17273a57ae7 Test-Pod-1.44.tar.gz"
diff --git a/main/perl-test-requires/APKBUILD b/main/perl-test-requires/APKBUILD
new file mode 100644
index 0000000000..d9b6ff2af6
--- /dev/null
+++ b/main/perl-test-requires/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-test-requires
+pkgver=0.06
+pkgrel=0
+pkgdesc="Test::Requires perl module"
+url="http://search.cpan.org/dist/Test-Requires/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/T/TO/TOKUHIROM/Test-Requires-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Test-Requires-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="6ce0da3cceadb6420d4c3c5bb69f64db Test-Requires-0.06.tar.gz"
diff --git a/main/perl-test-sharedfork/APKBUILD b/main/perl-test-sharedfork/APKBUILD
new file mode 100644
index 0000000000..ead065051e
--- /dev/null
+++ b/main/perl-test-sharedfork/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-test-sharedfork
+pkgver=0.16
+pkgrel=0
+pkgdesc="Test::SharedFork perl module"
+url="http://search.cpan.org/dist/Test-SharedFork/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/T/TO/TOKUHIROM/Test-SharedFork-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Test-SharedFork-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="ee0469b14d48bbd651f2ec5465f61a52 Test-SharedFork-0.16.tar.gz"
diff --git a/main/perl-test-tcp/APKBUILD b/main/perl-test-tcp/APKBUILD
new file mode 100644
index 0000000000..9f0518b1fb
--- /dev/null
+++ b/main/perl-test-tcp/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-test-tcp
+pkgver=1.13
+pkgrel=0
+pkgdesc="Test::TCP perl module"
+url="http://search.cpan.org/dist/Test-TCP/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-test-sharedfork"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/T/TO/TOKUHIROM/Test-TCP-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Test-TCP-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="fe152a1e66123b0de6779e0aa546ab34 Test-TCP-1.13.tar.gz"
diff --git a/main/perl-test-tester/APKBUILD b/main/perl-test-tester/APKBUILD
new file mode 100644
index 0000000000..bb541ce618
--- /dev/null
+++ b/main/perl-test-tester/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-test-tester
+pkgver=0.107
+pkgrel=0
+pkgdesc="Test::Tester perl module"
+url="http://search.cpan.org/dist/Test-Tester/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/F/FD/FDALY/Test-Tester-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Test-Tester-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="998a8abe241992faaa3e90f330800840 Test-Tester-0.107.tar.gz"
diff --git a/main/perl-test-warn/APKBUILD b/main/perl-test-warn/APKBUILD
new file mode 100644
index 0000000000..f10f53d995
--- /dev/null
+++ b/main/perl-test-warn/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-test-warn
+_pkgreal=Test-Warn
+pkgver=0.23
+pkgrel=0
+pkgdesc="Perl extension to test methods for warnings "
+url="http://search.cpan.org/dist/Test-Warn/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-tree-dag_node perl-sub-uplevel"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CH/CHORNY/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="96e224cba15bf69b7513c08e70496457 Test-Warn-0.23.tar.gz"
diff --git a/main/perl-text-autoformat/APKBUILD b/main/perl-text-autoformat/APKBUILD
new file mode 100644
index 0000000000..b0f086b74c
--- /dev/null
+++ b/main/perl-text-autoformat/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-text-autoformat
+pkgver=1.669002
+pkgrel=0
+pkgdesc="Text::Autoformat perl module"
+url="http://search.cpan.org/dist/Text-Autoformat/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-text-reform"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DC/DCONWAY/Text-Autoformat-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Text-Autoformat-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="c2c400207f49a769e32b5b1b660b07f7 Text-Autoformat-1.669002.tar.gz"
diff --git a/main/perl-text-csv/APKBUILD b/main/perl-text-csv/APKBUILD
new file mode 100644
index 0000000000..e3cdb0d70c
--- /dev/null
+++ b/main/perl-text-csv/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-text-csv
+pkgver=1.20
+pkgrel=1
+pkgdesc="Manipulate comma-separated value strings"
+url="http://search.cpan.org/dist/Text-CSV/"
+arch="noarch"
+license="PerlArtistic GPL"
+depends="perl"
+makedepends="perl-dev"
+source="http://search.cpan.org/CPAN/authors/id/M/MA/MAKAMAKA/Text-CSV-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Text-CSV-$pkgver
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '.packlist' -delete
+ find "$pkgdir" -name '*.pod' -delete
+}
+
+md5sums="8f20f60258ea0c8d5bbd029d03fe78b7 Text-CSV-1.20.tar.gz"
diff --git a/main/perl-text-password-pronounceable/APKBUILD b/main/perl-text-password-pronounceable/APKBUILD
new file mode 100644
index 0000000000..f0b96499fc
--- /dev/null
+++ b/main/perl-text-password-pronounceable/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-text-password-pronounceable
+pkgver=0.30
+pkgrel=0
+pkgdesc="Text::Password::Pronounceable perl module"
+url="http://search.cpan.org/dist/Text-Password-Pronounceable/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/T/TS/TSIBLEY/Text-Password-Pronounceable-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Text-Password-Pronounceable-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="2a6a3c9197dfb5912f763c0c4f285b48 Text-Password-Pronounceable-0.30.tar.gz"
diff --git a/main/perl-text-quoted/APKBUILD b/main/perl-text-quoted/APKBUILD
new file mode 100644
index 0000000000..f9d0dd3333
--- /dev/null
+++ b/main/perl-text-quoted/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-text-quoted
+pkgver=2.06
+pkgrel=0
+pkgdesc="Text::Quoted perl module"
+url="http://search.cpan.org/dist/Text-Quoted/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-text-autoformat"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RU/RUZ/Text-Quoted-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Text-Quoted-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="6ae8d3aa3a54c5f05bcd0c2313ebfa4d Text-Quoted-2.06.tar.gz"
diff --git a/main/perl-text-reform/APKBUILD b/main/perl-text-reform/APKBUILD
new file mode 100644
index 0000000000..79ce4e6152
--- /dev/null
+++ b/main/perl-text-reform/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-text-reform
+pkgver=1.20
+pkgrel=0
+pkgdesc="Text::Reform perl module"
+url="http://search.cpan.org/dist/Text-Reform/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CH/CHORNY/Text-Reform-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Text-Reform-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="f37f5834f3dc221eacd09bdfcfe40918 Text-Reform-1.20.tar.gz"
diff --git a/main/perl-text-template/APKBUILD b/main/perl-text-template/APKBUILD
new file mode 100644
index 0000000000..d777f62b27
--- /dev/null
+++ b/main/perl-text-template/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-text-template
+pkgver=1.45
+pkgrel=0
+pkgdesc="Text::Template perl module"
+url="http://search.cpan.org/dist/Text-Template/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MJ/MJD/Text-Template-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Text-Template-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="cd22441c1ab0870c012225c9a585e262 Text-Template-1.45.tar.gz"
diff --git a/main/perl-text-vfile-asdata/APKBUILD b/main/perl-text-vfile-asdata/APKBUILD
new file mode 100644
index 0000000000..dca99e37ba
--- /dev/null
+++ b/main/perl-text-vfile-asdata/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-text-vfile-asdata
+_pkgreal=Text-vFile-asData
+pkgver=0.07
+pkgrel=0
+pkgdesc="parse vFile formatted files into data structures"
+url="http://search.cpan.org/dist/Text-vFile-asData/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-class-accessor-chained"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RC/RCLAMP/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="1f0fc1fbef2111a936db3eb4678ddccc Text-vFile-asData-0.07.tar.gz"
diff --git a/main/perl-text-wikiformat/APKBUILD b/main/perl-text-wikiformat/APKBUILD
new file mode 100644
index 0000000000..9a9a096e05
--- /dev/null
+++ b/main/perl-text-wikiformat/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-text-wikiformat
+_pkgreal=Text-WikiFormat
+pkgver=0.79
+pkgrel=0
+pkgdesc="module for translating Wiki formatted text into other formats"
+url="http://search.cpan.org/dist/Text-WikiFormat/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-uri"
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CH/CHROMATIC/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="7f3e888ff898f67332216c4a25523f30 Text-WikiFormat-0.79.tar.gz"
diff --git a/main/perl-text-wrapper/APKBUILD b/main/perl-text-wrapper/APKBUILD
new file mode 100644
index 0000000000..5e17c6f10a
--- /dev/null
+++ b/main/perl-text-wrapper/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-text-wrapper
+pkgver=1.02
+pkgrel=0
+pkgdesc="Text::Wrapper perl module"
+url="http://search.cpan.org/dist/Text-Wrapper/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CJ/CJM/Text-Wrapper-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Text-Wrapper-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="a0cdfe6e9e9627db147b3970d3fcad4d Text-Wrapper-1.02.tar.gz"
diff --git a/main/perl-time-date/APKBUILD b/main/perl-time-date/APKBUILD
new file mode 100644
index 0000000000..25f2f44e30
--- /dev/null
+++ b/main/perl-time-date/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-time-date
+_realname=TimeDate
+pkgver=1.20
+pkgrel=2
+pkgdesc="Date formating subroutines"
+url="http://search.cpan.org/~gbarr/TimeDate-1.16/"
+arch="noarch"
+license="Unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GB/GBARR/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="7da7452bce4c684e4238e6d09b390200 TimeDate-1.20.tar.gz"
diff --git a/main/perl-time-hires/APKBUILD b/main/perl-time-hires/APKBUILD
new file mode 100644
index 0000000000..a2929fe152
--- /dev/null
+++ b/main/perl-time-hires/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-time-hires
+_realname=Time-HiRes
+pkgver=1.9721
+pkgrel=4
+pkgdesc="High resolution alarm, sleep, gettimeofday, interval timers"
+url="http://search.cpan.org/~jhi/Time-HiRes-${pkgver}/"
+arch="all"
+license="unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/J/JH/JHI/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd "$_builddir"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="bf09911a36b9481537c8e0d28fbb3aaf Time-HiRes-1.9721.tar.gz"
diff --git a/main/perl-time-modules/APKBUILD b/main/perl-time-modules/APKBUILD
new file mode 100644
index 0000000000..2946afe287
--- /dev/null
+++ b/main/perl-time-modules/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-time-modules
+_realname=Time-modules
+pkgver=2011.0517
+pkgrel=2
+pkgdesc="Timezone perl module"
+url="http://search.cpan.org/dist/Time-Modules/"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MU/MUIR/modules/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="67204ebc06211a877665765f91dc4e51 Time-modules-2011.0517.tar.gz"
diff --git a/main/perl-tree-dag_node/APKBUILD b/main/perl-tree-dag_node/APKBUILD
new file mode 100644
index 0000000000..07099fe1cc
--- /dev/null
+++ b/main/perl-tree-dag_node/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-tree-dag_node
+_pkgreal=Tree-DAG_Node
+pkgver=1.06
+pkgrel=0
+pkgdesc="(super)class for representing nodes in a tree"
+url="http://search.cpan.org/dist/Tree-DAG_Node/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends=""
+cpanmakedepends=""
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/C/CO/COGENT/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor
+}
+
+build() {
+ cd "$_builddir"
+ make && make test
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="3b006f128bd1d8961fc57c466ffa05f2 Tree-DAG_Node-1.06.tar.gz"
diff --git a/main/perl-tree-simple/APKBUILD b/main/perl-tree-simple/APKBUILD
new file mode 100644
index 0000000000..7b75973abe
--- /dev/null
+++ b/main/perl-tree-simple/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-tree-simple
+_pkgreal=Tree-Simple
+pkgver=1.18
+pkgrel=1
+pkgdesc="Tree::Simple Perl module"
+url="http://search.cpan.org/dist/Tree-Simple/"
+arch="noarch"
+license="GPL+ or Artistic"
+cpandepends="perl-test-exception"
+cpanmakedepends=""
+depends="perl $cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+install=""
+subpackages="$pkgname-doc"
+source="http://www.cpan.org/modules/by-module/Tree/Tree-Simple-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgreal-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="70462938108a8b8658b1b1d2f12dbeab Tree-Simple-1.18.tar.gz"
diff --git a/main/perl-try-tiny/APKBUILD b/main/perl-try-tiny/APKBUILD
new file mode 100644
index 0000000000..14e30fa9a1
--- /dev/null
+++ b/main/perl-try-tiny/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-try-tiny
+pkgver=0.09
+pkgrel=0
+pkgdesc="Try::Tiny perl module"
+url="http://search.cpan.org/dist/Try-Tiny/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/D/DO/DOY/Try-Tiny-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Try-Tiny-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="e526aa7d80cbc690c4a20925a592c13c Try-Tiny-0.09.tar.gz"
diff --git a/main/perl-universal-require/APKBUILD b/main/perl-universal-require/APKBUILD
new file mode 100644
index 0000000000..6abf1f7e25
--- /dev/null
+++ b/main/perl-universal-require/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-universal-require
+pkgver=0.13
+pkgrel=0
+pkgdesc="Require() modules from a variable"
+url="http://search.cpan.org/dist/UNIVERSAL-require/"
+arch="noarch"
+license="GPL+ or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MS/MSCHWERN/UNIVERSAL-require-$pkgver.tar.gz"
+
+_builddir="$srcdir"/UNIVERSAL-require-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="e6ea431fac9524077414d531a8cc203c UNIVERSAL-require-0.13.tar.gz"
diff --git a/main/perl-unix-syslog/APKBUILD b/main/perl-unix-syslog/APKBUILD
new file mode 100644
index 0000000000..855cb77e0c
--- /dev/null
+++ b/main/perl-unix-syslog/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-unix-syslog
+_realname=Unix-Syslog
+pkgver=1.1
+pkgrel=3
+pkgdesc="Perl interface to the UNIX syslog(3) calls"
+url="http://search.cpan.org/~mharnisch/Unix-Syslog-1.1/"
+arch="all"
+license="unknown"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/M/MH/MHARNISCH/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor \
+ || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="73d78e309fe9508ffc9a54d84d79aac9 Unix-Syslog-1.1.tar.gz"
diff --git a/main/perl-uri-escape/APKBUILD b/main/perl-uri-escape/APKBUILD
new file mode 100644
index 0000000000..8c31ab7037
--- /dev/null
+++ b/main/perl-uri-escape/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl-uri-escape
+_realname=URI
+pkgver=1.56
+pkgrel=3
+pkgdesc="Uniform Resource Identifiers (absolute and relative)"
+url="http://search.cpan.org/~gaas/URI-$pkgver"
+arch="noarch"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/$_realname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="5d60e6a7e6cdf8259a4082726fe2c92f URI-1.56.tar.gz"
diff --git a/main/perl-uri/APKBUILD b/main/perl-uri/APKBUILD
new file mode 100644
index 0000000000..409390ccad
--- /dev/null
+++ b/main/perl-uri/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-uri
+pkgver=1.58
+pkgrel=1
+pkgdesc="Perl Module: form Resource Identifiers (absolute and relative)"
+url="http://search.cpan.org/dist/URI/"
+arch="noarch"
+license="PerlArtistic"
+subpackages="$pkgname-doc"
+depends="perl"
+makedepends="perl-dev"
+source="http://www.cpan.org/authors/id/G/GA/GAAS/URI-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/URI-$pkgver
+ perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/URI-$pkgver
+ make install DESTDIR="$pkgdir" || return 1
+ find "$pkgdir" -name perllocal.pod -delete
+ find "$pkgdir" -name .packlist -delete
+}
+md5sums="540575aee18616ad9a21e0af7a1e7b18 URI-1.58.tar.gz"
diff --git a/main/perl-want/APKBUILD b/main/perl-want/APKBUILD
new file mode 100644
index 0000000000..d5d3e3a102
--- /dev/null
+++ b/main/perl-want/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-want
+pkgver=0.18
+pkgrel=0
+pkgdesc="Want perl module"
+url="http://search.cpan.org/dist/Want/"
+arch="all"
+license="GPLv2 or Artistic"
+depends="perl"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/R/RO/ROBIN/Want-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Want-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="b83e2d189781b10250133b4eb9e6ca28 Want-0.18.tar.gz"
diff --git a/main/perl-www-robotrules/APKBUILD b/main/perl-www-robotrules/APKBUILD
new file mode 100644
index 0000000000..6ab4253bfb
--- /dev/null
+++ b/main/perl-www-robotrules/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-www-robotrules
+pkgver=6.01
+pkgrel=1
+pkgdesc="WWW::RobotRules perl module"
+url="http://search.cpan.org/dist/WWW-RobotRules/"
+arch="noarch"
+license="GPLv2 or Artistic"
+depends="perl perl-uri"
+makedepends="perl-dev"
+install=""
+replaces="perl-libwww"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/G/GA/GAAS/WWW-RobotRules-$pkgver.tar.gz"
+
+_builddir="$srcdir"/WWW-RobotRules-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="b1252da49727320a1b5e20b3521d2499 WWW-RobotRules-6.01.tar.gz"
diff --git a/main/perl-x10/APKBUILD b/main/perl-x10/APKBUILD
new file mode 100644
index 0000000000..35c9421c7e
--- /dev/null
+++ b/main/perl-x10/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=perl-x10
+_realname=X10
+pkgver=0.03
+pkgrel=2
+pkgdesc="Perl module to control X10 devices"
+url="http://search.cpan.org/~robf/X10-0.03/"
+arch="noarch"
+license="unknown"
+depends="perl"
+makedepends="perl-dev perl-astro-suntime perl-time-modules
+ perl-device-serialport"
+install=
+subpackages=""
+source="http://search.cpan.org/CPAN/authors/id/R/RO/ROBF/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+build() {
+ cd $_builddir
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make && make test || return 1
+}
+
+package() {
+ cd $_builddir
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+
+}
+
+md5sums="056b3d98fab545865148b948de6784c7 X10-0.03.tar.gz"
diff --git a/main/perl-xml-parser/APKBUILD b/main/perl-xml-parser/APKBUILD
new file mode 100644
index 0000000000..33aff3878b
--- /dev/null
+++ b/main/perl-xml-parser/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-xml-parser
+_name=XML-Parser
+pkgver=2.40
+pkgrel=2
+pkgdesc="XML::Parser - an XML parser module for perl"
+url="http://search.cpan.org/dist/XML-Parser/"
+arch="all"
+license="GPL PerlArtistic"
+depends="perl"
+makedepends="expat-dev perl-dev"
+source="http://search.cpan.org/CPAN/authors/id/C/CH/CHORNY/${_name}-${pkgver}.tar.gz"
+
+build () {
+ cd "$srcdir"/$_name-$pkgver
+ perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make MAN1EXT=1p MAN3EXT=3pm || return 1
+}
+
+package() {
+ cd "$srcdir"/$_name-$pkgver
+ make install MAN1EXT=1p MAN3EXT=3pm DESTDIR="$pkgdir" || return 1
+ find "$pkgdir" -name perllocal.pod -delete
+ find "$pkgdir" -name .packlist -delete
+}
+md5sums="c66e9adba003d0667cc40115ccd837a5 XML-Parser-2.40.tar.gz"
diff --git a/main/perl-xml-rss/APKBUILD b/main/perl-xml-rss/APKBUILD
new file mode 100644
index 0000000000..e6e72d055c
--- /dev/null
+++ b/main/perl-xml-rss/APKBUILD
@@ -0,0 +1,37 @@
+# Automatically generated by apkbuild-cpan, template 1
+# Contributor: Timo Teräs <timo.teras@iki.fi>
+# Maintainer: Timo Teräs <timo.teras@iki.fi>
+pkgname=perl-xml-rss
+_pkgreal=XML-RSS
+pkgver=1.49
+pkgrel=0
+pkgdesc="creates and updates RSS files"
+url="http://search.cpan.org/dist/XML-RSS/"
+arch="noarch"
+license="GPL PerlArtistic"
+cpandepends="perl-datetime-format-mail perl-xml-parser perl-html-parser perl-datetime-format-w3cdtf perl-datetime"
+cpanmakedepends="perl-test-manifest"
+depends="$cpandepends"
+makedepends="perl-dev $cpanmakedepends"
+subpackages="$pkgname-doc"
+source="http://search.cpan.org/CPAN/authors/id/S/SH/SHLOMIF/$_pkgreal-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_pkgreal-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+ perl Build.PL installdirs=vendor || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./Build && ./Build test
+}
+
+package() {
+ cd "$_builddir"
+ ./Build install destdir="$pkgdir" || return 1
+ find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete
+}
+
+md5sums="b22c5ca9c226ca7b7698a9387f2f1908 XML-RSS-1.49.tar.gz"
diff --git a/main/perl-xml-simple/APKBUILD b/main/perl-xml-simple/APKBUILD
new file mode 100644
index 0000000000..0ebe336d81
--- /dev/null
+++ b/main/perl-xml-simple/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=perl-xml-simple
+pkgver=2.18
+pkgrel=2
+pkgdesc="Simple XML parser for perl"
+url="http://search.cpan.org/dist/XML-Simple/"
+arch="noarch"
+license="PerlArtistic"
+subpackages="$pkgname-doc"
+depends="perl-xml-parser perl"
+makedepends="perl-dev"
+source="ftp://ftp.cpan.org/pub/CPAN/authors/id/G/GR/GRANTM/XML-Simple-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/XML-Simple-$pkgver
+ perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/XML-Simple-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '.packlist' -delete
+ find "$pkgdir" -name 'perllocal.pod' -delete
+}
+md5sums="593aa8001e5c301cdcdb4bb3b63abc33 XML-Simple-2.18.tar.gz"
diff --git a/main/perl-yaml-syck/APKBUILD b/main/perl-yaml-syck/APKBUILD
new file mode 100644
index 0000000000..ffeecb1532
--- /dev/null
+++ b/main/perl-yaml-syck/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=perl-yaml-syck
+_realname=YAML-Syck
+pkgver=1.17
+pkgrel=0
+pkgdesc="Perl - Fast, lightweight YAML loader and dumper"
+url="http://search.cpan.org/~avar/YAML-Syck/"
+arch="all"
+license="Artistic GPL"
+depends="perl"
+makedepends="perl-dev"
+install=
+source="http://search.cpan.org/CPAN/authors/id/A/AV/AVAR/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="f788529ad4b2c2fd037ccdfd5e7a88ab YAML-Syck-1.17.tar.gz"
diff --git a/main/perl/APKBUILD b/main/perl/APKBUILD
new file mode 100644
index 0000000000..8d9b7b93a1
--- /dev/null
+++ b/main/perl/APKBUILD
@@ -0,0 +1,68 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+pkgname=perl
+pkgver=5.14.0
+pkgrel=0
+pkgdesc="Larry Wall's Practical Extraction and Report Language"
+url=http://www.perl.org
+arch="all"
+license="Artistic GPL-2"
+source="http://search.cpan.org/CPAN/authors/id/J/JE/JESSE/perl-$pkgver.tar.gz"
+depends=
+subpackages="$pkgname-dev $pkgname-doc miniperl"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd $_builddir
+ sed -i -e 's/less -R/less/g' ./Configure
+ sed -i -e 's/libswanted="\(.*\) nsl\(.*\)"/libswanted="\1\2"/g' ./Configure
+}
+
+build() {
+ cd $_builddir
+ ./Configure -des \
+ -Dcccdlflags='-fPIC' \
+ -Dcccdlflags='-fPIC' \
+ -Dccdlflags='-rdynamic' \
+ -Dprefix=/usr \
+ -Dprivlib=/usr/share/perl5/core_perl \
+ -Darchlib=/usr/lib/perl5/core_perl \
+ -Dvendorprefix=/usr \
+ -Dvendorlib=/usr/share/perl5/vendor_perl \
+ -Dvendorarch=/usr/lib/perl5/vendor_perl \
+ -Dsiteprefix=/usr/local \
+ -Dsitelib=/usr/local/share/perl5/site_perl \
+ -Dsitearch=/usr/local/lib/perl5/site_perl \
+ -Dlocincpth=' ' \
+ -Doptimize="${CFLAGS}" \
+ -Duselargefiles \
+ -Dusethreads \
+ -Duseshrplib \
+ -Dd_semctl_semun \
+ -Dman1dir=/usr/share/man/man1 \
+ -Dman3dir=/usr/share/man/man3 \
+ -Dinstallman1dir=/usr/share/man/man1 \
+ -Dinstallman3dir=/usr/share/man/man3 \
+ -Dman1ext='1' \
+ -Dman3ext='3pm' \
+ -Dinc_version_list="$inclist" \
+ -Dcf_by='Alpine' \
+ -Ud_csh \
+ -Dusenm \
+ || return 1
+ make
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make install DESTDIR="$pkgdir"
+}
+
+miniperl() {
+ pkgname=miniperl
+ mkdir -p "$subpkgdir"/usr/bin
+ cp "$srcdir/perl-$pkgver"/miniperl "$subpkgdir/usr/bin"
+}
+
+md5sums="e688b0ddad50bca9a6223693a85c439d perl-5.14.0.tar.gz"
diff --git a/main/pflogsumm/APKBUILD b/main/pflogsumm/APKBUILD
new file mode 100644
index 0000000000..6ba05c2525
--- /dev/null
+++ b/main/pflogsumm/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=pflogsumm
+pkgver=1.1.1
+pkgrel=2
+pkgdesc="Pflogsumm is a log analyzer for Postfix logs"
+url="http://jimsun.linxnet.com/postfix_contrib.html"
+arch="all"
+license="GPL-2"
+depends="perl perl-date-calc sysklogd"
+makedepends=""
+subpackages="$pkgname-doc"
+source="http://jimsun.linxnet.com/downloads/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -D -m644 pflogsumm.1 "$pkgdir"/usr/share/man/man1/pflogsumm.1
+ install -D -m755 pflogsumm.pl "$pkgdir"/usr/bin/pflogsumm
+}
+
+md5sums="2f570477b2e205f9dfc1df13f00b5c0d pflogsumm-1.1.1.tar.gz"
diff --git a/main/pgcluster/APKBUILD b/main/pgcluster/APKBUILD
new file mode 100644
index 0000000000..9d268f8ac5
--- /dev/null
+++ b/main/pgcluster/APKBUILD
@@ -0,0 +1,56 @@
+# Maintainer: Cameron Banta <cbanta@gmail.com>
+pkgname=pgcluster
+pkgver=1.9.0_rc5
+_myver=1.9.0rc5
+pkgrel=6
+pkgdesc="PostgreSQL with multi-master cluster/replication patch"
+url="http://pgfoundry.org/projects/pgcluster/"
+arch="all"
+license="BSD"
+depends=
+makedepends="readline-dev openssl-dev zlib-dev"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-libpq $pkgname-client"
+source="http://pgfoundry.org/frs/download.php/1705/$pkgname-$_myver.tar.gz
+ $pkgname.initd
+ $pkgname.confd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$_myver || return 1
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --with-docdir=/usr/share/doc \
+ --with-openssl \
+ || return 1
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$_myver || return 1
+ make DESTDIR="$pkgdir" install || return 1
+
+ install -D -m755 "$srcdir"/$pkgname.initd \
+ "$pkgdir"/etc/init.d/$pkgname
+ install -D -m644 "$srcdir"/$pkgname.confd \
+ "$pkgdir"/etc/conf.d/$pkgname || return 1
+}
+
+libpq() {
+ depends=
+ pkgdesc="PGCluster libraries"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libpq.so* "$subpkgdir"/usr/lib/
+}
+
+client() {
+ depends=
+ pkgdesc="PGCluster client"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/psql "$subpkgdir"/usr/bin/
+}
+
+
+md5sums="d2fe705e25a01c19c8f8daa1fbcc55d1 pgcluster-1.9.0rc5.tar.gz
+594be4c70a80fdd2d315d78793ef4421 pgcluster.initd
+503f94824fc7a385a831d7e55b74f9a0 pgcluster.confd"
diff --git a/main/pgcluster/pgcluster.confd b/main/pgcluster/pgcluster.confd
new file mode 100644
index 0000000000..9e1376eec7
--- /dev/null
+++ b/main/pgcluster/pgcluster.confd
@@ -0,0 +1,57 @@
+# PostgreSQL's Database Directory
+PGDATA="/var/lib/postgresql/pgcluster"
+
+# PostgreSQL User
+PGUSER="postgres"
+
+# PostgreSQL Group
+PGGROUP="postgres"
+
+# control what gets started by init script
+PG_START_DB="yes"
+PG_START_REPLICATE="yes"
+PG_START_LB="no"
+
+# Extra options to run postmaster with, e.g.:
+# -N is the maximal number of client connections
+# -B is the number of shared buffers and has to be at least 2x the value for -N
+# Please read the man-page to postmaster for more options. Many of these options
+# can be set directly in the configuration-file.
+#PGOPTS="-N 512 -B 1024"
+
+
+# SERVER SHUTDOWN:
+# The server will receive 3 signals in the worst case:
+# 1. SIGTERM
+# This signals the server to ignore new connections and to
+# wait for all clients to end their transactions before shutting down.
+# Use WAIT_FOR_DISCONNECT to control how much time the clients
+# should have until the next signal is being sent.
+# 2. SIGINT
+# Tell the server to forcefully disconnect all clients.
+# Terminating a client results in a rollback of the open transactions for this client.
+# Use WAIT_FOR_CLEANUP to determine how much time the server has
+# for cleanup.
+# 3. SIGQUIT
+# This will terminate the server immediately and results in a recovery run for the next start.
+
+# Wait for clients to disconnect
+WAIT_FOR_DISCONNECT=30
+
+# Time the server has to clean up
+WAIT_FOR_CLEANUP=60
+
+# Time the server has to quit (with a recover-run on next startup)
+# Set to 0 to deactivate it
+WAIT_FOR_QUIT=60
+
+# Comment this out if you don't want to wait for the server to
+# startup before continuing. For example, if this server is a
+# PITR log shipping based replication standby
+WAIT_FOR_START="-w"
+
+# If you have to export environment variables for the database process,
+# this can be done here.
+#
+# Example:
+# export R_HOME="/usr/lib/R"
diff --git a/main/pgcluster/pgcluster.initd b/main/pgcluster/pgcluster.initd
new file mode 100644
index 0000000000..28606a5815
--- /dev/null
+++ b/main/pgcluster/pgcluster.initd
@@ -0,0 +1,173 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-db/postgresql-server/files/postgresql.init-8.3,v 1.4 2008/09/28 22:53:02 caleb Exp $
+
+opts="${opts} reload setup"
+
+depend() {
+ use net
+ after firewall
+ provide postgresql
+}
+
+checkconfig() {
+ if [ ! -d "$PGDATA" ] ; then
+ eerror "Directory not found: $PGDATA"
+ eerror "Please make sure that PGDATA points to the right path."
+ eerror "You can run '/etc/init.d/pgcluster setup' to setup a new database cluster."
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+
+ #ebegin "Starting PostgreSQL"
+
+ if [ -f "$PGDATA/postmaster.pid" ] ; then
+ rm -f "$PGDATA/postmaster.pid"
+ fi
+
+ local retval
+
+ if [ ${PG_START_DB} == "yes" ]; then
+ ebegin "Starting PGCluster database instance"
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl start ${WAIT_FOR_START} -o '--silent-mode=true ${PGOPTS}'" >/dev/null
+ retval=$?
+ if [ $retval -ne 0 ]; then
+ eend $retval
+ else
+
+ # The following is to catch the case of an already running server
+ # in which pg_ctl doesn't know to which server it connected to and false reports the server as 'up'
+ sleep 2
+ if [ ! -f "$PGDATA/postmaster.pid" ] ; then
+ eerror "The pid-file doesn't exist but pg_ctl reported a running server."
+ eerror "Please check whether there is another server running on the same port or read the log-file."
+ eend 1
+ else
+ local pid=$(grep "^[0-9]\+" "$PGDATA/postmaster.pid")
+ test -d /proc/"${pid}"
+ eend $?
+ fi
+ fi
+ fi
+
+ if [ ${PG_START_REPLICATE} == "yes" ]; then
+ ebegin "Starting PGCluster replicate instance"
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pgreplicate -D ${PGDATA} -l" >/dev/null
+ retval=$?
+ sleep 1
+ if [ ! -f "$PGDATA/pgreplicate.pid" ] ; then
+ eerror "Where's the pid file?"
+ eend 1
+ else
+ local pid=$(grep "^[0-9]\+" "$PGDATA/pgreplicate.pid")
+ test -d /proc/"${pid}"
+ eend $?
+ fi
+ fi
+
+ if [ ${PG_START_LB} == "yes" ]; then
+ ebegin "Starting PGCluster load balancer instance"
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pglb -D ${PGDATA} -l" >/dev/null
+ retval=$?
+ sleep 1
+ if [ ! -f "$PGDATA/pglb.pid" ] ; then
+ eerror "Where's the pid file?"
+ eend 1
+ else
+ local pid=$(grep "^[0-9]\+" "$PGDATA/pglb.pid")
+ test -d /proc/"${pid}"
+ eend $?
+ fi
+ fi
+ return
+}
+
+stop() {
+ local retval
+
+ if [ ${PG_START_LB} == "yes" ]; then
+ ebegin "Stopping PGCluster Load Balancer instance"
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pglb -D ${PGDATA} -l stop" >/dev/null
+ eend $?
+ fi
+ if [ ${PG_START_REPLICATE} == "yes" ]; then
+ ebegin "Stopping PGCluster Replicate instance"
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pgreplicate -D ${PGDATA} -l stop" >/dev/null
+ eend $?
+ fi
+
+
+ if [ ${PG_START_DB} == "yes" ]; then
+ ebegin "Stopping PGCLuster database (this can take up to $(( ${WAIT_FOR_DISCONNECT} + ${WAIT_FOR_CLEANUP} )) seconds)"
+ if [ ! -f "$PGDATA/postmaster.pid" ] ; then
+ ewarn "$PGDATA/postmaster.pid not found. Was it running?"
+ eend 1
+ return 0
+ fi
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl stop -t ${WAIT_FOR_DISCONNECT} -m smart" >/dev/null
+
+ retval=$?
+ [ $retval -eq 0 ] && eend $retval && return $retval
+
+ ewarn "Some clients did not disconnect within ${WAIT_FOR_DISCONNECT} seconds."
+ ewarn "Going to shutdown the server anyway."
+
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl stop -m fast" >/dev/null
+
+ retval=$?
+ [ $retval -eq 0 ] && eend $retval && return $retval
+
+ if [ ${WAIT_FOR_QUIT} -eq 0 ] ; then
+ eerror "Server did not shut down and sending the SIGQUIT has been disabled."
+ eend $retval
+ return $retval
+ fi
+
+ ewarn "Shutting down the server gracefully failed."
+ ewarn "Forcing it to shutdown which leads to a recover-run on next startup."
+
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl stop -m immediate" >/dev/null
+
+ retval=$?
+ [ $retval -eq 0 ] && eend $retval && return $retval
+
+ eerror "Forced shutdown failed!!! Something is wrong with your system, please take care of it manually."
+ eend $?
+ fi
+}
+
+reload() {
+ ebegin "Reloading PostgreSQL configuration"
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl reload" >/dev/null
+ eend $?
+}
+
+setup() {
+ ebegin "Creating a new PGCluster database cluster"
+ if [ -d "${PGDATA}" ] ; then
+ eend 1 "${PGDATA} already exist"
+ return
+ fi
+ mkdir -p "${PGDATA}"
+ chown -Rf postgres:postgres "${PGDATA}"
+ chmod 0700 "${PGDATA}"
+ cd "${PGDATA}" # to avoid the: could not change directory to "/root"
+ su -c "/usr/bin/initdb --pgdata ${PGDATA}" postgres
+ einfo "You can use the '/etc/init.d/pgcluster' script to run PostgreSQL instead"
+ einfo "of 'pg_ctl'."
+ eend $?
+}
+
diff --git a/main/pgpool/APKBUILD b/main/pgpool/APKBUILD
new file mode 100644
index 0000000000..ed73776bc7
--- /dev/null
+++ b/main/pgpool/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Cameron <cbanta@gmail.com>
+# Maintainer: Cameron <cbanta@gmail.com>
+pkgname=pgpool
+_opkgname=pgpool-II
+pkgver=3.0.1
+pkgrel=1
+pkgdesc="Pgpool II is a connection pooling/replication server for PostgreSQL."
+url="http://pgfoundry.org/projects/pgpool/"
+arch="all"
+license="BSD"
+makedepends="postgresql-dev"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://pgfoundry.org/frs/download.php/2841/$_opkgname-$pkgver.tar.gz
+ $pkgname.initd"
+
+build() {
+ cd "$srcdir/$_opkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$_opkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+
+md5sums="86d8beff0396d11b6753dd2be31bcad7 pgpool-II-3.0.1.tar.gz
+6317aee51feaf9c5facb7765cddeec6b pgpool.initd"
diff --git a/main/pgpool/commit-queue b/main/pgpool/commit-queue
new file mode 100644
index 0000000000..96a68e3506
--- /dev/null
+++ b/main/pgpool/commit-queue
@@ -0,0 +1 @@
+pgpool
diff --git a/main/pgpool/pgpool.initd b/main/pgpool/pgpool.initd
new file mode 100644
index 0000000000..95ab0cd6bb
--- /dev/null
+++ b/main/pgpool/pgpool.initd
@@ -0,0 +1,25 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+depend() {
+ need net
+ after firewall
+ use postgresql
+}
+
+start() {
+ ebegin "Starting pgpool-II"
+ start-stop-daemon --start --quiet --exec /usr/bin/pgpool --f /etc/pgpool.conf -F /etc/pcp.conf
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping pgpool-II"
+ start-stop-daemon --stop --quiet --pidfile /var/run/pgpool.pid
+ result=$?
+ eend $result
+}
+
diff --git a/main/php-apc/APKBUILD b/main/php-apc/APKBUILD
new file mode 100644
index 0000000000..befc1d0557
--- /dev/null
+++ b/main/php-apc/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=php-apc
+pkgver=3.1.8
+_realver=$pkgver
+pkgrel=0
+pkgdesc="Alternative PHP Cache"
+url="http://pecl.php.net/package/APC"
+arch="all"
+license="PHP"
+depends="php"
+makedepends="php-dev autoconf pcre-dev"
+subpackages=""
+source="http://pecl.php.net/get/APC-${_realver}.tgz
+apc.ini"
+
+build() {
+ cd "$srcdir/APC-${_realver}"
+ phpize || return 1
+ ./configure --enable-apc \
+ --disable-apc-mmap \
+ --with-php-config=/usr/bin/php-config
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/APC-${_realver}"
+ make INSTALL_ROOT=$pkgdir install || return 1
+ install -D -m644 "$srcdir"/apc.ini "$pkgdir"/etc/php/conf.d/apc.ini
+}
+
+md5sums="bb1147933a61aa70ceffe53cc6f2920f APC-3.1.8.tgz
+1be423cbc197a302abd50cfd5834258b apc.ini"
diff --git a/main/php-apc/apc.ini b/main/php-apc/apc.ini
new file mode 100644
index 0000000000..eb8a7e8f2c
--- /dev/null
+++ b/main/php-apc/apc.ini
@@ -0,0 +1,11 @@
+;PHP suggest APC settings
+extension=apc.so
+;apc.enabled=1
+;apc.shm_segments=1
+;apc.shm_size=128
+;apc.ttl=7200
+;apc.user_ttl=7200
+;apc.num_files_hint=1024
+;apc.mmap_file_mask=/tmp/apc.XXXXXX
+;apc.enable_cli=1
+
diff --git a/main/php-mailparse/APKBUILD b/main/php-mailparse/APKBUILD
new file mode 100644
index 0000000000..7f112dea56
--- /dev/null
+++ b/main/php-mailparse/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=php-mailparse
+_realname=mailparse
+pkgver=2.1.5
+pkgrel=1
+pkgdesc="PHP Email message manipulation"
+url="http://pecl.php.net/package/mailparse"
+arch="all"
+license="PHP"
+depends=
+depends_dev="php-dev"
+makedepends="$depends_dev autoconf"
+install=""
+subpackages=""
+source="http://pecl.php.net/get/$_realname-$pkgver.tgz
+ mailparse.ini"
+
+_builddir="$srcdir/$_realname-$pkgver"
+
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ phpize || return 1
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make INSTALL_ROOT="$pkgdir/" install || return 1
+ install -D -m644 "$srcdir"/mailparse.ini \
+ "$pkgdir"/etc/php/conf.d/mailparse.ini || return 1
+}
+
+md5sums="0c0134fb6f5903c8fb6c9e2205263d2c mailparse-2.1.5.tgz
+9b8f5b99ee9d297ef1b439bacc2b3631 mailparse.ini"
diff --git a/main/php-mailparse/mailparse.ini b/main/php-mailparse/mailparse.ini
new file mode 100644
index 0000000000..cb7ebda6bd
--- /dev/null
+++ b/main/php-mailparse/mailparse.ini
@@ -0,0 +1 @@
+extension=mailparse.so
diff --git a/main/php-pear-mdb2/APKBUILD b/main/php-pear-mdb2/APKBUILD
new file mode 100644
index 0000000000..06dab5fa3e
--- /dev/null
+++ b/main/php-pear-mdb2/APKBUILD
@@ -0,0 +1,66 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=php-pear-mdb2
+_pkgname=MDB2
+pkgver=2.5.0b3
+_driver_ver=1.5.0b3
+pkgrel=1
+pkgdesc="PEAR MDB2 Database Abstraction Layer"
+url="http://pear.php.net/package/MDB2/"
+arch="noarch"
+license="BSD"
+depends="php-pear"
+depends_dev=
+makedepends="$depends_dev php-pear"
+install=""
+subpackages="
+ $pkgname-driver-mysql:driver_mysql
+ $pkgname-driver-mysqli:driver_mysqli
+ $pkgname-driver-pgsql:driver_pgsql
+ $pkgname-driver-sqlite:driver_sqlite
+ "
+source=""
+
+build() { return 0; }
+package() { _pear_install $_pkgname-$pkgver "$pkgdir" || return 1; }
+driver_mysql() { _do_driver mysql "mysql php-mysql" noarch; }
+driver_mysqli() { _do_driver mysqli "mysql php-mysqli" noarch; }
+driver_pgsql() { _do_driver pgsql "postgresql php-pgsql" noarch; }
+driver_sqlite() { _do_driver sqlite "php-sqlite" noarch; }
+
+
+_pear_install() {
+ local _pear_pkg=$1
+ local _pear_pkg_dir=$2
+
+ pear install --nodeps --packagingroot="$_pear_pkg_dir" $_pear_pkg \
+ || return 1
+
+ _cleanpaths="
+ usr/share/pear/.channels/
+ usr/share/pear/.depdb
+ usr/share/pear/.depdblock
+ usr/share/pear/.filemap
+ usr/share/pear/.lock
+ usr/share/pear/.registry/.channel.__uri/
+ usr/share/pear/.registry/.channel.doc.php.net/
+ usr/share/pear/.registry/.channel.pecl.php.net/
+ "
+ for _cleanpath in $_cleanpaths; do
+ rm -rf "$_pear_pkg_dir"/$_cleanpath || return 1
+ done
+}
+
+_do_driver() {
+ local _driver_name=$1
+
+ # driver dependencies
+ if [ -n "${2-}" ]; then
+ depends="${2-}"
+ fi
+ depends="${pkgname} ${depends}"
+ arch="${3-noarch}"
+
+ _pear_install ${_pkgname}_Driver_${_driver_name}-${_driver_ver} \
+ "$subpkgdir" || return 1
+}
diff --git a/main/php/APKBUILD b/main/php/APKBUILD
new file mode 100644
index 0000000000..032d5639dd
--- /dev/null
+++ b/main/php/APKBUILD
@@ -0,0 +1,452 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=php
+pkgver=5.3.6
+_suhosinver=5.3.6-0.9.10
+pkgrel=11
+pkgdesc="The PHP language runtime engine"
+url="http://www.php.net/"
+arch="all"
+license="PHP-3"
+depends="$pkgname-cgi"
+install="$pkgname.post-upgrade"
+makedepends="pcre-dev libxml2-dev libiconv-dev openssl-dev zlib-dev bzip2-dev
+ curl-dev libpng-dev jpeg-dev freetype-dev libmcrypt-dev mysql-dev
+ sqlite-dev libtool libltdl postgresql-dev db-dev unixodbc-dev icu-dev
+ gd-dev gmp-dev gettext-dev imap-dev aspell-dev
+ net-snmp-dev libxslt-dev openldap-dev pkgconfig
+ libgcrypt-dev apache2-dev apr-dev apr-util-dev libevent-dev
+ readline-dev enchant-dev gdbm-dev freetds-dev"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-common $pkgname-cgi
+ $pkgname-cli $pkgname-fpm $pkgname-apache2 $pkgname-embed
+ $pkgname-pear
+ $pkgname-bcmath
+ $pkgname-bz2
+ $pkgname-calendar
+ $pkgname-ctype
+ $pkgname-curl
+ $pkgname-dba
+ $pkgname-dom
+ $pkgname-enchant
+ $pkgname-exif
+ $pkgname-ftp
+ $pkgname-gd
+ $pkgname-gettext
+ $pkgname-gmp
+ $pkgname-iconv
+ $pkgname-imap
+ $pkgname-intl
+ $pkgname-json
+ $pkgname-ldap
+ $pkgname-mcrypt
+ $pkgname-mysql
+ $pkgname-mysqli
+ $pkgname-odbc
+ $pkgname-openssl
+ $pkgname-pdo
+ $pkgname-pdo_mysql
+ $pkgname-pdo_odbc
+ $pkgname-pdo_pgsql
+ $pkgname-pdo_sqlite
+ $pkgname-pgsql
+ $pkgname-phar
+ $pkgname-posix
+ $pkgname-pspell
+ $pkgname-shmop
+ $pkgname-snmp
+ $pkgname-soap
+ $pkgname-sockets
+ $pkgname-sqlite
+ $pkgname-sqlite3
+ $pkgname-sysvmsg
+ $pkgname-sysvsem
+ $pkgname-sysvshm
+ $pkgname-xml
+ $pkgname-xmlreader
+ $pkgname-xmlrpc
+ $pkgname-xsl
+ $pkgname-zip
+ $pkgname-zlib
+ $pkgname-mssql
+ $pkgname-pdo_dblib
+ "
+
+# http://download.suhosin.org/suhosin-patch-${_suhosinver}.patch.gz
+source="http://www.php.net/distributions/${pkgname}-${pkgver}.tar.bz2
+ php-install-pear-xml.patch
+ php-uclibc.patch
+ suhosin-patch-${_suhosinver}.patch
+ php-fpm.initd
+ php5-module.conf
+ "
+
+_apiver="20090626"
+_extdir="/usr/lib/php/$_apiver"
+_srcdir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_srcdir"
+ # beat the pear installer into using xml.so
+ patch -p1 -i "$srcdir"/php-install-pear-xml.patch || return 1
+ patch -p1 -i "$srcdir"/php-uclibc.patch || return 1
+
+ # apply suhosin patch
+ patch -p1 -i "${srcdir}"/suhosin-patch-${_suhosinver}.patch || return 1
+
+ # safty check for api changes
+ local vapi=$(sed -n '/#define PHP_API_VERSION/{s/.* //;p}' main/php.h)
+ if [ "$vapi" != "$_apiver" ]; then
+ error "Upstreram API version is now $vapi. Expecting $_vapi"
+ return 1
+ fi
+}
+
+_do_build() {
+ local _flavor="$1"
+ shift
+ local _builddir="$srcdir"/build-$_flavor
+ mkdir -p "$_builddir"
+ cd "$_builddir"
+ "$_srcdir"/configure $@ || return 1
+ sed -ri "s/^(EXTRA_LDFLAGS[ ]*\=.*)/\1 -lpthread/" Makefile # see #183
+ make || return 1
+}
+
+build() {
+ _phpconfig="--build=${CHOST:-i486-alpine-linux-uclibc} \
+ --prefix=/usr \
+ --sysconfdir=/etc/php \
+ --with-layout=GNU \
+ --with-config-file-path=/etc/php \
+ --with-config-file-scan-dir=/etc/php/conf.d \
+ --enable-inline-optimization \
+ --disable-debug \
+ --disable-rpath \
+ --disable-static \
+ --enable-shared \
+ --mandir=/usr/share/man \
+ --with-pic \
+ "
+
+ _phpextensions=" \
+ --enable-bcmath=shared \
+ --with-bz2=shared \
+ --enable-calendar=shared \
+ --with-cdb \
+ --enable-ctype=shared \
+ --with-curl=shared \
+ --with-curlwrappers \
+ --enable-dba=shared \
+ --with-db4=shared \
+ --enable-dom=shared \
+ --with-enchant=shared \
+ --enable-exif=shared \
+ --with-freetype-dir=shared,/usr \
+ --enable-ftp=shared \
+ --with-gd=shared,/usr \
+ --enable-gd-native-ttf \
+ --with-gdbm=shared \
+ --with-gettext=shared \
+ --with-gmp=shared \
+ --with-iconv=shared \
+ --with-icu-dir=/usr \
+ --with-imap=shared \
+ --with-imap-ssl=shared \
+ --enable-intl=shared \
+ --with-jpeg-dir=shared,/usr \
+ --enable-json=shared \
+ --with-ldap=shared \
+ --enable-libxml=shared \
+ --enable-mbregex \
+ --enable-mbstring=all \
+ --with-mcrypt=shared \
+ --with-mysql=shared,mysqlnd \
+ --with-mysql-sock=/var/run/mysqld/mysqld.sock \
+ --with-mysqli=shared,mysqlnd \
+ --with-openssl=shared \
+ --with-pcre-regex=/usr \
+ --enable-pdo=shared \
+ --with-pdo-mysql=shared,mysqlnd \
+ --with-pdo-odbc=shared,unixODBC,/usr \
+ --with-pdo-pgsql=shared \
+ --with-pdo-sqlite=shared,/usr \
+ --with-pgsql=shared \
+ --enable-phar=shared \
+ --with-png-dir=shared,/usr \
+ --enable-posix=shared \
+ --with-pspell=shared \
+ --with-regex=php \
+ --enable-session \
+ --enable-shmop=shared \
+ --with-snmp=shared \
+ --enable-soap=shared \
+ --enable-sockets=shared \
+ --with-sqlite=shared \
+ --enable-sqlite-utf8 \
+ --with-sqlite3=shared,/usr \
+ --enable-sysvmsg=shared \
+ --enable-sysvsem=shared \
+ --enable-sysvshm=shared \
+ --with-unixODBC=shared,/usr \
+ --enable-xml=shared \
+ --enable-xmlreader=shared \
+ --with-xmlrpc=shared \
+ --with-xsl=shared \
+ --enable-zip=shared \
+ --with-zlib=shared \
+ --without-db1 \
+ --without-db2 \
+ --without-db3 \
+ --without-qdbm \
+ --with-mssql=shared \
+ --with-pdo-dblib=shared \
+ --enable-mailparse \
+ "
+
+ # cgi, fcgi, cli, pear and extensions
+ _do_build cgi \
+ ${_phpconfig} \
+ --disable-cli \
+ --enable-cgi \
+ --enable-cli \
+ --with-pear \
+ ${_phpextensions} \
+ || return 1
+
+ # fpm
+ cp -a "$srcdir"/build-cgi "$srcdir"/build-fpm
+ _do_build fpm \
+ ${_phpconfig} \
+ --disable-cli \
+ --enable-fpm \
+ ${_phpextensions} \
+ || return 1
+
+ # apache2
+ cp -a "$srcdir"/build-cgi "$srcdir"/build-apache2
+ _do_build apache2 \
+ ${_phpconfig} \
+ --disable-cli \
+ --with-apxs2 \
+ ${_phpextensions} \
+ || return 1
+
+ # embed
+ cp -a "$srcdir"/build-cgi "$srcdir"/build-embed
+ _do_build embed \
+ ${_phpconfig} \
+ --disable-cli \
+ --enable-embed=shared \
+ ${_phpextensions} \
+ || return 1
+}
+
+package() {
+ cd "$srcdir"/build-cgi
+
+ # install php-cgi, cli, pear and modules
+ make -j1 install install-pear INSTALL_ROOT="$pkgdir" || return 1
+
+ # cleanup after pear
+ find "$pkgdir" -name '.*' | xargs rm -rf || return 1
+
+ # install fpm
+ install -D -m755 "$srcdir"/build-fpm/sapi/fpm/php-fpm \
+ "$pkgdir"/usr/bin/php-fpm || return 1
+ install -D -m644 "$srcdir"/build-fpm/sapi/fpm/php-fpm.conf \
+ "$pkgdir"/etc/php/php-fpm.conf || return 1
+ install -D -m755 "$srcdir"/php-fpm.initd "$pkgdir"/etc/init.d/php-fpm
+ # enable some default options
+ sed -ri -e "s~^;(error_log)(.*)~\1 = /var/log/php-fpm.log~" \
+ -e "s/^;(pm.start_servers)/\1/" \
+ -e "s/^;(pm.min_spare_servers)/\1/" \
+ -e "s/^;(pm.max_spare_servers)/\1/" \
+ "$pkgdir"/etc/php/php-fpm.conf || return 1
+
+ # install apache2
+ install -D -m755 "$srcdir"/build-apache2/libs/libphp5.so \
+ "$pkgdir"/usr/lib/apache2/libphp5.so || return 1
+ install -D -m644 "$srcdir"/php5-module.conf \
+ "$pkgdir"/etc/apache2/conf.d/php5-module.conf || return 1
+
+ # install embed
+ install -D -m755 "$srcdir"/build-embed/libs/libphp5.so \
+ "$pkgdir"/usr/lib/libphp5.so || return 1
+ install -D -m644 "$_srcdir"/sapi/embed/php_embed.h \
+ "$pkgdir"/usr/include/php/sapi/embed/php_embed.h || return 1
+}
+
+dev() {
+ default_dev
+ mkdir -p "$subpkgdir"/usr/lib/php
+ mv "$pkgdir"/usr/lib/php/build \
+ "$subpkgdir"/usr/lib/php/ || return 1
+}
+
+doc() {
+ # man pages
+ mkdir -p "$subpkgdir"/usr/share/man || return 1
+ mv "$pkgdir"/usr/share/man/man* "$subpkgdir"/usr/share/man/ \
+ || return 1
+
+ # doc files
+ _docs="CODING_STANDARDS CREDITS EXTENSIONS INSTALL LICENSE NEWS \
+ README.EXTENSIONS README.EXT_SKEL README.MAILINGLIST_RULES \
+ README.PARAMETER_PARSING_API README.PHP4-TO-PHP5-THIN-CHANGES \
+ README.REDIST.BINS README.RELEASE_PROCESS \
+ README.SELF-CONTAINED-EXTENSIONS README.STREAMS \
+ README.SUBMITTING_PATCH README.SVN-RULES README.TESTING \
+ README.TESTING2 README.UNIX-BUILD-SYSTEM README.Zeus \
+ README.input_filter README.namespaces TODO TODO-5.1 \
+ TODO-PHP5 UPGRADING UPGRADING.INTERNALS"
+ for _doc in $_docs; do
+ install -Dm644 "$srcdir"/$pkgname-$pkgver/$_doc \
+ "$subpkgdir"/usr/share/doc/$pkgname/$_doc || return 1
+ done
+}
+
+common() {
+ pkgdesc="PHP Common Files"
+ replaces="$pkgname"
+
+ cd "$srcdir"/$pkgname-$pkgver
+ install -D -m644 php.ini-production "$subpkgdir"/etc/php/php.ini
+ sed -i -e "s:^; extension_dir = \"./\":extension_dir = \"$_extdir\":" "$subpkgdir"/etc/php/php.ini
+ sed -ri 's/;(date.timezone =)/\1 UTC/' "$subpkgdir"/etc/php/php.ini
+ sed -ri "s~^([;]*cgi\.rfc2616_headers.*)$~\1\n\n\; If this is enabled, the PHP CGI binary can safely be placed outside of the\n; web tree and people will not be able to circumvent .htaccess security.\ncgi\.discard_path = 1~" "$subpkgdir"/etc/php/php.ini
+}
+
+cgi() {
+ pkgdesc="PHP Common Gateway Interface (CGI)"
+ replaces="php"
+ depends="php-common"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/php-cgi "$subpkgdir"/usr/bin/
+}
+
+cli() {
+ pkgdesc="PHP Command Line Interface (CLI)"
+ replaces="php-dev"
+ depends="php-common"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/php "$subpkgdir"/usr/bin/ || return 1
+ # provide phpize here instead of -dev due to pecl command
+ mv "$pkgdir"/usr/bin/phpize "$subpkgdir"/usr/bin/ || return 1
+}
+
+fpm() {
+ pkgdesc="PHP FastCGI Process Manager (FPM)"
+ depends="php-common"
+ mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/etc/php
+ mv "$pkgdir"/usr/bin/php-fpm "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/etc/init.d "$subpkgdir"/etc/ || return 1
+ mv "$pkgdir"/etc/php/php-fpm.conf "$subpkgdir"/etc/php/
+
+}
+
+apache2() {
+ pkgdesc="PHP Module for Apache2"
+ depends="php-common apache2"
+ mkdir -p "$subpkgdir"/usr/lib "$subpkgdir"/etc
+ mv "$pkgdir"/usr/lib/apache2 "$subpkgdir"/usr/lib/ &&\
+ mv "$pkgdir"/etc/apache2 "$subpkgdir"/etc
+}
+
+embed() {
+ pkgdesc="PHP Embed Library"
+ depends="php-common"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libphp5.so "$subpkgdir"/usr/lib/
+}
+
+pear() {
+ pkgdesc="PHP Extension and Application Repository (PEAR)"
+ depends="php-cli php-xml"
+ mkdir -p "$subpkgdir"/usr/share "$subpkgdir"/etc/php \
+ "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/pecl \
+ "$pkgdir"/usr/bin/pear \
+ "$pkgdir"/usr/bin/peardev \
+ "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/etc/php/pear.conf \
+ "$subpkgdir"/etc/php/ || return 1
+ mv "$pkgdir"/usr/share/pear \
+ "$subpkgdir"/usr/share/ || return 1
+}
+
+_mv_ext() {
+ local ext=$1
+ pkgdesc="${ext} extension for PHP"
+
+ # extension dependencies
+ if [ -n "${2-}" ]; then
+ depends="${2-}"
+ fi
+ depends="${pkgname} ${depends}"
+
+ mkdir -p "$subpkgdir"/$_extdir
+ mv "$pkgdir"/$_extdir/${ext}.so "$subpkgdir"/$_extdir/ || return 1
+ mkdir -p "$subpkgdir"/etc/php/conf.d
+ echo "extension=${ext}.so" > "$subpkgdir"/etc/php/conf.d/${ext}.ini
+}
+
+bcmath() { _mv_ext bcmath; }
+bz2() { _mv_ext bz2; }
+calendar() { _mv_ext calendar; }
+ctype() { _mv_ext ctype; }
+curl() { _mv_ext curl; }
+dba() { _mv_ext dba; }
+dom() { _mv_ext dom; }
+enchant() { _mv_ext enchant; }
+exif() { _mv_ext exif; }
+ftp() { _mv_ext ftp; }
+gd() { _mv_ext gd; }
+gettext() { _mv_ext gettext; }
+gmp() { _mv_ext gmp; }
+iconv() { _mv_ext iconv; }
+imap() { _mv_ext imap; }
+intl() { _mv_ext intl; }
+json() { _mv_ext json; }
+ldap() { _mv_ext ldap; }
+mcrypt() { _mv_ext mcrypt; }
+mysql() { _mv_ext mysql mysql; }
+mysqli() { _mv_ext mysqli mysql; }
+odbc() { _mv_ext odbc unixodbc; }
+openssl() { _mv_ext openssl; }
+pdo() { _mv_ext pdo; }
+pdo_mysql() { _mv_ext pdo_mysql "php-pdo mysql"; }
+pdo_odbc() { _mv_ext pdo_odbc "php-pdo unixodbc"; }
+pdo_pgsql() { _mv_ext pdo_pgsql "php-pdo postgresql"; }
+pdo_sqlite() { _mv_ext pdo_sqlite "php-pdo sqlite"; }
+pgsql() { _mv_ext pgsql postgresql; }
+phar() {
+ _mv_ext phar
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/phar* "$subpkgdir"/usr/bin/
+ }
+posix() { _mv_ext posix; }
+pspell() { _mv_ext pspell; }
+shmop() { _mv_ext shmop; }
+snmp() { _mv_ext snmp; }
+soap() { _mv_ext soap; }
+sockets() { _mv_ext sockets; }
+sqlite() { _mv_ext sqlite php-pdo_sqlite; }
+sqlite3() { _mv_ext sqlite3 sqlite; }
+sysvmsg() { _mv_ext sysvmsg; }
+sysvsem() { _mv_ext sysvsem; }
+sysvshm() { _mv_ext sysvshm; }
+xml() { _mv_ext xml; }
+xmlreader() { _mv_ext xmlreader php-dom; }
+xmlrpc() { _mv_ext xmlrpc php-xml; }
+xsl() { _mv_ext xsl php-dom; }
+zip() { _mv_ext zip; }
+zlib() { _mv_ext zlib; }
+mssql() { _mv_ext mssql; }
+pdo_dblib() { _mv_ext pdo_dblib "php-pdo freetds"; }
+
+md5sums="2286f5a82a6e8397955a0025c1c2ad98 php-5.3.6.tar.bz2
+5111e3be06d391f8772587c675240fab php-install-pear-xml.patch
+31458da0ca6cb4ca2cbdaa2d32ab386d php-uclibc.patch
+54d3a7830c103f0efe94ed44c40dfad5 suhosin-patch-5.3.6-0.9.10.patch
+8f2bb2b744a2de50025842cb51fb6a3a php-fpm.initd
+67719f428f44ec004da18705cbabe2ee php5-module.conf"
diff --git a/main/php/php-fpm.initd b/main/php/php-fpm.initd
new file mode 100644
index 0000000000..6b8337e8b8
--- /dev/null
+++ b/main/php/php-fpm.initd
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+
+PHP_FPM_CONF="/etc/php/php-fpm.conf"
+
+opts="depend start stop reload"
+
+depend() {
+ need net
+ use apache2 lighttpd nginx
+}
+
+start() {
+ ebegin "Starting PHP FastCGI server"
+ start-stop-daemon --start --exec /usr/bin/php-fpm -- -y "${PHP_FPM_CONF}"
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping PHP FastCGI server"
+ start-stop-daemon --stop --name php-fpm
+ eend $?
+}
diff --git a/main/php/php-install-pear-xml.patch b/main/php/php-install-pear-xml.patch
new file mode 100644
index 0000000000..f7a6fff58b
--- /dev/null
+++ b/main/php/php-install-pear-xml.patch
@@ -0,0 +1,15 @@
+--- ./pear/Makefile.frag.orig
++++ ./pear/Makefile.frag
+@@ -2,8 +2,11 @@
+
+ peardir=$(PEAR_INSTALLDIR)
+
++# help the built php to find xml extension so we can install pear
++PEAR_INSTALL_XML_FLAGS = -d extension_dir="$(top_builddir)/modules" -d extension=xml.so
++
+ # Skip all php.ini files altogether
+-PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dsafe_mode=0 -dopen_basedir= -derror_reporting=1803 -dmemory_limit=-1 -ddetect_unicode=0
++PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dsafe_mode=0 -dopen_basedir= -derror_reporting=1803 -dmemory_limit=-1 -ddetect_unicode=0 $(PEAR_INSTALL_XML_FLAGS)
+
+ WGET = `which wget 2>/dev/null`
+ FETCH = `which fetch 2>/dev/null`
diff --git a/main/php/php-uclibc.patch b/main/php/php-uclibc.patch
new file mode 100644
index 0000000000..ca6890e43d
--- /dev/null
+++ b/main/php/php-uclibc.patch
@@ -0,0 +1,11 @@
+--- ./ext/standard/php_crypt_r.c.orig
++++ ./ext/standard/php_crypt_r.c
+@@ -94,7 +94,7 @@
+ if (!initialized) {
+ #ifdef PHP_WIN32
+ InterlockedIncrement(&initialized);
+-#elif (defined(__GNUC__) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 2))
++#elif (defined(__GNUC__) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 2)) || defined(__UCLIBC__)
+ __sync_fetch_and_add(&initialized, 1);
+ #elif defined(HAVE_ATOMIC_H) /* Solaris 10 defines atomic API within */
+ membar_producer();
diff --git a/main/php/php.post-upgrade b/main/php/php.post-upgrade
new file mode 100644
index 0000000000..98c959958c
--- /dev/null
+++ b/main/php/php.post-upgrade
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+new=$1
+old=$2
+
+if [ "$(apk version -t $old 5.3)" = "<" ]; then
+ echo "*"
+ echo "* Please see migration notes here: http://php.net/migration53"
+ echo "*"
+fi
+
diff --git a/main/php/php5-module.conf b/main/php/php5-module.conf
new file mode 100644
index 0000000000..9dae61fa81
--- /dev/null
+++ b/main/php/php5-module.conf
@@ -0,0 +1,5 @@
+LoadModule php5_module modules/libphp5.so
+
+DirectoryIndex index.php index.html
+AddHandler application/x-httpd-php .php
+AddHandler application/x-httpd-php-source .phps
diff --git a/main/php/suhosin-patch-5.3.6-0.9.10.patch b/main/php/suhosin-patch-5.3.6-0.9.10.patch
new file mode 100644
index 0000000000..55062d8a42
--- /dev/null
+++ b/main/php/suhosin-patch-5.3.6-0.9.10.patch
@@ -0,0 +1,5776 @@
+diff -Nura php-5.3.6/configure suhosin-patch-5.3.6-0.9.10/configure
+--- php-5.3.6/configure 2011-03-17 08:55:56.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/configure 2011-03-19 10:48:33.810641898 +0100
+@@ -18979,6 +18979,9 @@
+
+ fi
+
++cat >> confdefs.h <<\EOF
++#define SUHOSIN_PATCH 1
++EOF
+
+ echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
+ echo "configure:18985: checking for declared timezone" >&5
+@@ -115340,7 +115343,7 @@
+ php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
+ strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
+ network.c php_open_temporary_file.c php_logos.c \
+- output.c getopt.c; do
++ output.c getopt.c suhosin_patch.c ; do
+
+ IFS=.
+ set $ac_src
+@@ -115544,7 +115547,7 @@
+ zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
+ zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
+ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
+- zend_closures.c zend_float.c; do
++ zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c ; do
+
+ IFS=.
+ set $ac_src
+diff -Nura php-5.3.6/configure.in suhosin-patch-5.3.6-0.9.10/configure.in
+--- php-5.3.6/configure.in 2011-03-17 08:48:29.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/configure.in 2011-03-19 10:48:33.810641898 +0100
+@@ -289,6 +289,7 @@
+ sinclude(TSRM/threads.m4)
+ sinclude(TSRM/tsrm.m4)
+
++sinclude(main/suhosin_patch.m4)
+
+ divert(2)
+
+@@ -1396,7 +1397,7 @@
+ php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
+ strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
+ network.c php_open_temporary_file.c php_logos.c \
+- output.c getopt.c)
++ output.c getopt.c suhosin_patch.c )
+
+ PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \
+ plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c \
+@@ -1424,7 +1425,7 @@
+ zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
+ zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
+ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
+- zend_closures.c zend_float.c)
++ zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c )
+
+ if test -r "$abs_srcdir/Zend/zend_objects.c"; then
+ PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
+diff -Nura php-5.3.6/ext/standard/dl.c suhosin-patch-5.3.6-0.9.10/ext/standard/dl.c
+--- php-5.3.6/ext/standard/dl.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/ext/standard/dl.c 2011-03-19 10:48:33.810641898 +0100
+@@ -254,6 +254,23 @@
+ return FAILURE;
+ }
+ }
++
++#if SUHOSIN_PATCH
++ if (strncmp("suhosin", module_entry->name, sizeof("suhosin")-1) == 0) {
++ void *log_func;
++ /* sucessfully loaded suhosin extension, now check for logging function replacement */
++ log_func = (void *) DL_FETCH_SYMBOL(handle, "suhosin_log");
++ if (log_func == NULL) {
++ log_func = (void *) DL_FETCH_SYMBOL(handle, "_suhosin_log");
++ }
++ if (log_func != NULL) {
++ zend_suhosin_log = log_func;
++ } else {
++ zend_suhosin_log(S_MISC, "could not replace logging function");
++ }
++ }
++#endif
++
+ return SUCCESS;
+ }
+ /* }}} */
+diff -Nura php-5.3.6/ext/standard/info.c suhosin-patch-5.3.6-0.9.10/ext/standard/info.c
+--- php-5.3.6/ext/standard/info.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/ext/standard/info.c 2011-03-19 10:48:33.810641898 +0100
+@@ -878,6 +878,33 @@
+
+ php_info_print_table_end();
+
++ /* Suhosin Patch */
++ php_info_print_box_start(0);
++ if (expose_php && !sapi_module.phpinfo_as_text) {
++ PUTS("<a href=\"http://www.suhosin.org\"><img border=\"0\" src=\"");
++ if (SG(request_info).request_uri) {
++ char *elem_esc = php_info_html_esc(SG(request_info).request_uri TSRMLS_CC);
++ PUTS(elem_esc);
++ efree(elem_esc);
++ }
++ PUTS("?="SUHOSIN_LOGO_GUID"\" alt=\"Suhosin logo\" /></a>\n");
++ }
++ PUTS("This server is protected with the Suhosin Patch ");
++ if (sapi_module.phpinfo_as_text) {
++ PUTS(SUHOSIN_PATCH_VERSION);
++ } else {
++ zend_html_puts(SUHOSIN_PATCH_VERSION, strlen(SUHOSIN_PATCH_VERSION) TSRMLS_CC);
++ }
++ PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
++ if (sapi_module.phpinfo_as_text) {
++ PUTS("Copyright (c) 2006-2007 Hardened-PHP Project\n");
++ PUTS("Copyright (c) 2007-2009 SektionEins GmbH\n");
++ } else {
++ PUTS("Copyright (c) 2006-2007 <a href=\"http://www.hardened-php.net/\">Hardened-PHP Project</a>\n");
++ PUTS("Copyright (c) 2007-2009 <a href=\"http://www.sektioneins.de/\">SektionEins GmbH</a>\n");
++ }
++ php_info_print_box_end();
++
+ /* Zend Engine */
+ php_info_print_box_start(0);
+ if (expose_php && !sapi_module.phpinfo_as_text) {
+diff -Nura php-5.3.6/ext/standard/syslog.c suhosin-patch-5.3.6-0.9.10/ext/standard/syslog.c
+--- php-5.3.6/ext/standard/syslog.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/ext/standard/syslog.c 2011-03-19 10:48:33.810641898 +0100
+@@ -42,6 +42,7 @@
+ */
+ PHP_MINIT_FUNCTION(syslog)
+ {
++#if !SUHOSIN_PATCH
+ /* error levels */
+ REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
+ REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
+@@ -97,6 +98,7 @@
+ /* AIX doesn't have LOG_PERROR */
+ REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
+ #endif
++#endif
+ BG(syslog_device)=NULL;
+
+ return SUCCESS;
+diff -Nura php-5.3.6/main/fopen_wrappers.c suhosin-patch-5.3.6-0.9.10/main/fopen_wrappers.c
+--- php-5.3.6/main/fopen_wrappers.c 2011-01-18 23:20:09.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/fopen_wrappers.c 2011-03-19 10:48:33.810641898 +0100
+@@ -85,13 +85,8 @@
+ PHPAPI ZEND_INI_MH(OnUpdateBaseDir)
+ {
+ char **p, *pathbuf, *ptr, *end;
+-#ifndef ZTS
+- char *base = (char *) mh_arg2;
+-#else
+- char *base = (char *) ts_resource(*((int *) mh_arg2));
+-#endif
+
+- p = (char **) (base + (size_t) mh_arg1);
++ p = &PG(open_basedir);
+
+ if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN || stage == PHP_INI_STAGE_ACTIVATE || stage == PHP_INI_STAGE_DEACTIVATE) {
+ /* We're in a PHP_INI_SYSTEM context, no restrictions */
+diff -Nura php-5.3.6/main/main.c suhosin-patch-5.3.6-0.9.10/main/main.c
+--- php-5.3.6/main/main.c 2011-02-08 22:40:51.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/main.c 2011-03-19 10:48:33.813975198 +0100
+@@ -90,6 +90,9 @@
+
+ #include "SAPI.h"
+ #include "rfc1867.h"
++#if SUHOSIN_PATCH
++#include "suhosin_globals.h"
++#endif
+
+ #if HAVE_SYS_MMAN_H
+ # include <sys/mman.h>
+@@ -490,7 +493,7 @@
+ STD_PHP_INI_ENTRY("extension_dir", PHP_EXTENSION_DIR, PHP_INI_SYSTEM, OnUpdateStringUnempty, extension_dir, php_core_globals, core_globals)
+ STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals)
+ PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout)
+- STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
++ PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir)
+ STD_PHP_INI_ENTRY("safe_mode_exec_dir", PHP_SAFE_MODE_EXEC_DIR, PHP_INI_SYSTEM, OnUpdateString, safe_mode_exec_dir, php_core_globals, core_globals)
+
+ STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
+@@ -1781,6 +1784,10 @@
+ }
+ #endif
+
++#if SUHOSIN_PATCH
++PHPAPI void suhosin_startup();
++#endif
++
+ /* {{{ php_module_startup
+ */
+ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
+@@ -1825,6 +1832,10 @@
+ tsrm_ls = ts_resource(0);
+ #endif
+
++#if SUHOSIN_PATCH
++ suhosin_startup();
++#endif
++
+ module_shutdown = 0;
+ module_startup = 1;
+ sapi_initialize_empty_request(TSRMLS_C);
+@@ -1944,7 +1955,11 @@
+ REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
+- REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
++#if SUHOSIN_PATCH
++ REGISTER_MAIN_LONG_CONSTANT("SUHOSIN_PATCH", 1, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_STRINGL_CONSTANT("SUHOSIN_PATCH_VERSION", SUHOSIN_PATCH_VERSION, sizeof(SUHOSIN_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
++#endif
++ REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);
+ #ifdef ZEND_MULTIBYTE
+diff -Nura php-5.3.6/main/php_config.h.in suhosin-patch-5.3.6-0.9.10/main/php_config.h.in
+--- php-5.3.6/main/php_config.h.in 2011-03-17 08:56:00.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/php_config.h.in 2011-03-19 10:48:33.813975198 +0100
+@@ -851,6 +851,9 @@
+ /* Define if the target system has /dev/urandom device */
+ #undef HAVE_DEV_URANDOM
+
++/* Suhosin-Patch for PHP */
++#undef SUHOSIN_PATCH
++
+ /* Whether you have AOLserver */
+ #undef HAVE_AOLSERVER
+
+diff -Nura php-5.3.6/main/php.h suhosin-patch-5.3.6-0.9.10/main/php.h
+--- php-5.3.6/main/php.h 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/php.h 2011-03-19 10:48:33.813975198 +0100
+@@ -453,6 +453,10 @@
+ #endif
+ #endif /* !XtOffsetOf */
+
++#if SUHOSIN_PATCH
++#include "suhosin_patch.h"
++#endif
++
+ #endif
+
+ /*
+diff -Nura php-5.3.6/main/php_logos.c suhosin-patch-5.3.6-0.9.10/main/php_logos.c
+--- php-5.3.6/main/php_logos.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/php_logos.c 2011-03-19 10:48:33.813975198 +0100
+@@ -50,6 +50,10 @@
+ return zend_hash_del(&phpinfo_logo_hash, logo_string, strlen(logo_string));
+ }
+
++#if SUHOSIN_PATCH
++#include "suhosin_logo.h"
++#endif
++
+ int php_init_info_logos(void)
+ {
+ if(zend_hash_init(&phpinfo_logo_hash, 0, NULL, NULL, 1)==FAILURE)
+@@ -58,7 +62,9 @@
+ php_register_info_logo(PHP_LOGO_GUID , "image/gif", php_logo , sizeof(php_logo));
+ php_register_info_logo(PHP_EGG_LOGO_GUID, "image/gif", php_egg_logo, sizeof(php_egg_logo));
+ php_register_info_logo(ZEND_LOGO_GUID , "image/gif", zend_logo , sizeof(zend_logo));
+-
++#if SUHOSIN_PATCH
++ php_register_info_logo(SUHOSIN_LOGO_GUID, "image/jpeg", suhosin_logo , sizeof(suhosin_logo));
++#endif
+ return SUCCESS;
+ }
+
+diff -Nura php-5.3.6/main/snprintf.c suhosin-patch-5.3.6-0.9.10/main/snprintf.c
+--- php-5.3.6/main/snprintf.c 2011-02-21 07:53:24.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/snprintf.c 2011-03-19 10:48:33.813975198 +0100
+@@ -780,6 +780,10 @@
+ */
+ switch (*fmt) {
+ case 'Z':
++#if SUHOSIN_PATCH
++ zend_suhosin_log(S_MISC, "'Z' specifier within format string");
++ goto skip_output;
++#else
+ zvp = (zval*) va_arg(ap, zval*);
+ zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
+ if (free_zcopy) {
+@@ -790,6 +794,7 @@
+ if (adjust_precision && precision < s_len) {
+ s_len = precision;
+ }
++#endif
+ break;
+ case 'u':
+ switch(modifier) {
+@@ -1091,7 +1096,11 @@
+
+
+ case 'n':
++#if SUHOSIN_PATCH
++ zend_suhosin_log(S_MISC, "'n' specifier within format string");
++#else
+ *(va_arg(ap, int *)) = cc;
++#endif
+ goto skip_output;
+
+ /*
+diff -Nura php-5.3.6/main/spprintf.c suhosin-patch-5.3.6-0.9.10/main/spprintf.c
+--- php-5.3.6/main/spprintf.c 2011-02-21 07:53:24.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/spprintf.c 2011-03-19 10:48:33.813975198 +0100
+@@ -388,6 +388,10 @@
+ */
+ switch (*fmt) {
+ case 'Z':
++#if SUHOSIN_PATCH
++ zend_suhosin_log(S_MISC, "'Z' specifier within format string");
++ goto skip_output;
++#else
+ zvp = (zval*) va_arg(ap, zval*);
+ zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
+ if (free_zcopy) {
+@@ -398,6 +402,7 @@
+ if (adjust_precision && precision < s_len) {
+ s_len = precision;
+ }
++#endif
+ break;
+ case 'u':
+ switch(modifier) {
+@@ -698,7 +703,11 @@
+
+
+ case 'n':
++#if SUHOSIN_PATCH
++ zend_suhosin_log(S_MISC, "'n' specifier within format string");
++#else
+ *(va_arg(ap, int *)) = xbuf->len;
++#endif
+ goto skip_output;
+
+ /*
+diff -Nura php-5.3.6/main/suhosin_globals.h suhosin-patch-5.3.6-0.9.10/main/suhosin_globals.h
+--- php-5.3.6/main/suhosin_globals.h 1970-01-01 01:00:00.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/suhosin_globals.h 2011-03-19 10:48:33.813975198 +0100
+@@ -0,0 +1,61 @@
++/*
++ +----------------------------------------------------------------------+
++ | Suhosin-Patch for PHP |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 2004-2009 Stefan Esser |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 2.02 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available at through the world-wide-web at |
++ | http://www.php.net/license/2_02.txt. |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
++ +----------------------------------------------------------------------+
++ */
++
++#ifndef SUHOSIN_GLOBALS_H
++#define SUHOSIN_GLOBALS_H
++
++typedef struct _suhosin_patch_globals suhosin_patch_globals_struct;
++
++#ifdef ZTS
++# define SPG(v) TSRMG(suhosin_patch_globals_id, suhosin_patch_globals_struct *, v)
++extern int suhosin_patch_globals_id;
++#else
++# define SPG(v) (suhosin_patch_globals.v)
++extern struct _suhosin_patch_globals suhosin_patch_globals;
++#endif
++
++
++struct _suhosin_patch_globals {
++ /* logging */
++ int log_syslog;
++ int log_syslog_facility;
++ int log_syslog_priority;
++ int log_sapi;
++ int log_script;
++ int log_phpscript;
++ char *log_scriptname;
++ char *log_phpscriptname;
++ zend_bool log_phpscript_is_safe;
++ zend_bool log_use_x_forwarded_for;
++
++ /* memory manager canary protection */
++ unsigned int canary_1;
++ unsigned int canary_2;
++ unsigned int canary_3;
++ unsigned int dummy;
++};
++
++
++#endif /* SUHOSIN_GLOBALS_H */
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ */
+diff -Nura php-5.3.6/main/suhosin_logo.h suhosin-patch-5.3.6-0.9.10/main/suhosin_logo.h
+--- php-5.3.6/main/suhosin_logo.h 1970-01-01 01:00:00.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/suhosin_logo.h 2011-03-19 10:48:33.813975198 +0100
+@@ -0,0 +1,178 @@
++static unsigned char suhosin_logo[] =
++ "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48"
++ "\x00\x48\x00\x00\xff\xe1\x00\x16\x45\x78\x69\x66\x00\x00\x4d\x4d"
++ "\x00\x2a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\xff\xdb\x00\x43"
++ "\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
++ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
++ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
++ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
++ "\x01\xff\xc0\x00\x0b\x08\x00\x27\x00\x71\x01\x01\x22\x00\xff\xc4"
++ "\x00\x1e\x00\x00\x02\x02\x02\x03\x01\x01\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x09\x06\x08\x05\x07\x02\x03\x0a\x01\x04\xff\xc4"
++ "\x00\x32\x10\x00\x01\x04\x03\x00\x02\x00\x05\x01\x05\x09\x01\x00"
++ "\x00\x00\x00\x05\x02\x03\x04\x06\x01\x07\x08\x00\x09\x11\x12\x13"
++ "\x14\x21\x15\x0a\x16\x31\x56\x96\x17\x18\x19\x23\x32\x41\x58\x98"
++ "\xd4\xd6\xff\xda\x00\x08\x01\x01\x00\x00\x3f\x00\xf4\xc1\xe1\xe5"
++ "\x69\xe9\x3e\xb9\xd1\x7c\x8a\x2e\x9d\x66\xe8\x3b\x29\x4d\x7f\x46"
++ "\xba\x58\x55\x54\x8d\xb1\x5f\xaa\xd9\x8d\x51\x2b\xb6\x27\x5a\x69"
++ "\xd1\x43\xaf\x16\x1a\xf0\xb2\xb1\xe9\x6d\x9f\xc2\xa4\x36\x18\xb5"
++ "\x85\x10\x41\xbe\xfc\x09\xac\x49\x29\x11\xd4\x32\x97\xec\x08\x13"
++ "\xc1\x2d\x20\xc3\x59\xeb\x26\x05\xd8\x6b\x76\x31\x43\x8f\x57\xcf"
++ "\x84\x9f\x14\xa8\x53\x81\x0b\xc3\x64\x80\xa3\x02\x0a\x41\x75\xf8"
++ "\x44\x85\x93\x81\x22\x3c\xd8\x13\xe1\xbe\xf4\x59\x91\x1f\x6a\x44"
++ "\x77\x5c\x69\xc4\x2f\x39\x5f\x0f\x2a\x8d\xeb\xba\xf8\xc3\x56\x6c"
++ "\x3b\x36\xa7\xda\xbd\x4d\xa1\xb5\x4e\xc6\xa7\xa4\x3a\xec\x15\x2d"
++ "\xa5\xb3\xea\x5a\xdc\xac\x46\xac\x01\x60\xd8\x43\xc8\x8e\x8b\xb1"
++ "\x40\x4c\x95\x8b\x34\x41\x28\x52\x91\x28\x43\xd3\xa3\xb6\xa7\x55"
++ "\x15\xe7\x5a\x96\xcb\xf1\xda\xe5\x55\xee\xfe\x1e\xbd\xd9\x41\xd3"
++ "\x28\xfd\x97\xca\x57\x2b\x85\x9c\xa4\x30\x95\xaa\xa5\x57\xa2\x35"
++ "\x15\x86\xcb\x61\x34\x41\xe4\xc7\x80\x20\x18\x21\x17\x09\x85\x0b"
++ "\x14\x9d\x21\x68\x62\x1c\x08\x11\x64\x4b\x92\xf2\xd2\xd3\x2d\x2d"
++ "\x6a\xc2\x73\x6b\x3c\x3c\x8b\x9e\xbc\x52\xaa\xa4\xab\x81\x6c\xf6"
++ "\xfa\xbd\x70\xc5\xc6\x7b\xc2\xaa\x22\x4f\x58\x04\x87\x25\x6a\x27"
++ "\x1d\xa4\x3d\x20\x75\x72\x01\x09\x71\xe5\x1c\x9e\xc3\x2e\x36\xf3"
++ "\xd0\xc6\x35\x2a\x43\x4d\x2d\x0e\x2d\xb4\xa1\x49\xce\x65\x1e\x52"
++ "\x9e\xa1\xf6\x09\xcc\xdc\x63\x66\xa8\x01\xe9\x3b\x0d\xd7\x5a\x85"
++ "\xbb\xc5\x65\xc0\x7b\x2e\x46\xa9\xd9\x56\x1d\x4c\x92\x72\x26\x4e"
++ "\x86\xd5\x68\xae\xc4\xaa\x55\xce\xd7\x83\x59\xb3\x81\xee\xce\x74"
++ "\x39\x39\x31\x9f\x8a\x25\xe8\xa5\xa5\xe5\x81\xf2\x11\x23\xcb\xa1"
++ "\x1e\x43\x12\xe3\xb1\x2a\x2b\xcd\xc8\x8d\x25\x96\xa4\x47\x7d\x95"
++ "\xa5\xc6\x9f\x61\xe4\x25\xc6\x5e\x69\xc4\xe7\x29\x5b\x6e\xb6\xa4"
++ "\xad\x0b\x4e\x72\x95\x25\x58\x56\x33\x9c\x67\xce\xef\x0f\x17\xbf"
++ "\x4c\x7b\x2d\xe6\xfe\x76\x35\x27\x5a\x07\x97\x67\xe8\xae\x8d\x71"
++ "\x0f\xb2\x13\x99\xb9\xbc\x14\xad\xb3\xb7\xe6\x11\x6f\xe0\xda\x58"
++ "\xb1\x08\xac\xa6\x6c\x2d\x7f\x05\xb7\x56\xd2\xe6\xcf\xbb\x4d\x0c"
++ "\xe3\x50\xb2\xec\x91\xf0\x4a\xb8\xd6\x22\xb8\xa7\xf6\x67\xaf\xcf"
++ "\x63\x7e\xd7\xe7\x42\xd8\xbd\xc3\x71\xa1\xf2\x7e\x9b\xa8\x97\x83"
++ "\x6e\xd1\xdc\x4b\x06\x11\x2d\xae\x26\x61\x98\x72\x10\xf4\x42\x5d"
++ "\x20\x4a\xa3\x73\xd7\xf2\xcd\x3c\x48\x32\xe4\x03\x9f\x80\x37\x08"
++ "\x36\x11\xd0\xcb\x97\x6c\x08\xed\x6d\x33\x24\xa2\x1b\xb4\x77\xdf"
++ "\x61\x5d\x5f\xc1\x43\xc2\x82\xeb\x0f\x5d\x84\x08\x68\xaa\xa4\x01"
++ "\xe1\x19\xdf\xbc\x31\x65\xfe\xd1\xf5\x7d\x7a\xb2\x2a\x33\x50\x21"
++ "\x2a\x56\x9d\xb1\x81\xab\xdb\x35\x78\x30\x83\xd9\x89\x1d\x31\xac"
++ "\x96\x14\x07\x61\xbc\x20\x68\x42\x85\x33\x19\xac\xbe\xdb\x34\x56"
++ "\xf1\xd5\xfd\x29\xa9\x28\xdb\xcb\x4c\x5a\x23\xdc\xf5\x96\xc5\x10"
++ "\xa3\x35\x5b\x14\x68\xd3\x61\x62\x64\x76\x26\xcb\x17\x3e\x34\x98"
++ "\x04\xa3\xc4\x20\x38\x90\x92\xe3\xc8\x07\x2c\x36\x74\x66\x26\x0e"
++ "\x29\x02\x64\x29\x2d\x21\xe6\x16\x9c\x6b\xce\xa3\x89\xd9\x4f\xd3"
++ "\xc4\xbd\xc5\x87\x79\x9c\x65\xf6\x39\x45\x60\xe8\xce\x9e\xab\x6d"
++ "\x13\x15\x22\xe1\x5e\x4b\x38\x42\xc4\x1e\xd5\x76\xe0\xc5\xeb\x85"
++ "\x07\x2d\x0f\xb8\xb6\xa6\xd6\x6d\x71\x0d\xa2\x43\x4c\x25\xea\xfa"
++ "\xa1\xae\x4c\xe4\x7d\xbd\x76\xa9\xfb\x06\xc2\x83\x42\xeb\xad\xe7"
++ "\xe9\x5f\x68\x6f\xba\xfb\x2f\x07\xce\xb8\x13\xc1\x9b\xeb\xb0\x76"
++ "\x45\x57\x28\x7b\xea\xbe\x0f\xf4\x30\x7b\xa0\xed\xe4\x22\x93\x21"
++ "\xfc\xbc\xe0\xb9\x75\xc1\x4f\xfc\xef\xb6\xfa\xa1\xfc\x64\xa1\x4a"
++ "\x82\xc7\x33\xad\x75\xed\x82\xbd\x3d\xdb\xf7\xa8\xbe\x5e\xbb\x36"
++ "\x62\x04\x9a\x2e\xc5\xd9\x9e\x9c\x3a\x0b\x98\x0b\x57\xac\xf1\x24"
++ "\x62\x58\x83\x15\x5b\xa6\xf2\xda\x34\x70\x03\xce\x0f\x93\x1b\x12"
++ "\xc7\xce\x54\x87\x33\x15\xd6\x53\x25\x1f\x2a\x90\x87\x12\xe3\x78"
++ "\xef\x55\x77\x4d\x4a\xd8\x7e\xef\xd2\xfd\xd1\xaf\x3a\xaf\x55\xdb"
++ "\x6a\x2d\x3d\x42\xac\x51\x79\xee\x91\xab\xe1\x05\x2d\x3c\x80\xa2"
++ "\x43\xad\x22\x2e\xd5\x33\x13\xa4\x9e\x00\xe0\x04\x10\x84\xc8\xf2"
++ "\x19\x30\x92\x1f\xaa\xc3\x28\xc9\x76\x30\x3f\xe9\x10\x61\x5e\x79"
++ "\xd5\xf7\xdf\xd0\x54\xdb\xae\xb6\xae\xfa\xe8\xa3\x57\xe0\x6c\x2d"
++ "\xf7\xbd\x49\xd6\x6e\x76\x79\xcc\x54\x0c\x5f\xff\x00\xbb\x06\x98"
++ "\xa6\x9e\x89\x61\xb4\x6f\xc3\xe3\x6a\xc2\x4f\x59\x03\xc9\x80\x2c"
++ "\x59\x24\x44\x70\x38\xd5\x96\x6a\x9e\x8b\x81\x64\xe5\xbc\xa0\x3c"
++ "\x33\xaf\x17\x9d\xff\x00\x71\x1a\xd1\x3a\x80\x66\xb3\xd9\x31\x77"
++ "\x0d\x12\xbd\xae\x29\xb5\x6a\xd6\xcf\x8d\x68\x87\x75\xcd\xe8\x65"
++ "\x5a\xbe\x3c\x04\x7b\x34\xdb\x54\x19\xa4\x63\x9c\x2a\x5d\x23\xbe"
++ "\xf4\xb1\x1c\x4d\x90\xec\x92\x2f\x49\x71\xf7\x14\xf2\x97\x9f\x15"
++ "\x57\xed\x13\x21\x2a\xf5\x33\xd1\x2a\x52\x52\xac\xb7\x62\xd1\xcb"
++ "\x46\x73\x8c\x67\x28\x56\x77\x86\xbf\x6f\x2a\x4e\x73\xfe\x95\x65"
++ "\x0b\x5a\x3e\x38\xfc\xfc\xaa\x56\x3f\x86\x73\xe3\xb9\x4a\x52\x84"
++ "\xa5\x08\x4e\x12\x94\x27\x09\x4a\x53\x8c\x61\x29\x4a\x71\xf0\x4a"
++ "\x53\x8c\x7e\x31\x8c\x63\x18\xc6\x31\x8f\xc6\x31\xf8\xc7\x9f\x7c"
++ "\xd5\xbb\xae\x5e\xe2\x1f\xab\x6e\x24\x34\x00\x8a\x25\x83\x70\x40"
++ "\x1c\xcc\xda\x45\x7f\x66\x4e\x30\x2e\x94\x7e\x74\x49\xf0\xe4\x4e"
++ "\x06\x5c\xa8\x2f\x89\x21\x2e\x98\x0e\xd9\x21\xc2\x0b\x21\x0f\xc4"
++ "\x16\x6e\x48\xd9\xe4\xe3\x4a\x19\x1e\x64\x67\x54\xff\x00\x3a\x6d"
++ "\x4f\x62\xb5\x00\x4a\xaa\x51\xfd\x2d\xe8\x0e\x6c\xaf\xc6\x7d\x6d"
++ "\xc8\x88\xc7\x67\xea\x8a\x58\x02\x73\xe3\x65\x4d\xc9\x24\xc0\x3d"
++ "\x57\xa3\x2e\x53\x16\x99\x4f\xe5\xe7\x19\x97\x3e\x3b\xcf\xc9\x4b"
++ "\x99\x7f\x33\x25\xa5\xdf\xba\x77\x2b\xd3\x3e\xc2\x7b\x8b\x94\x07"
++ "\xe9\x52\x5b\x43\x87\x34\x14\x86\x37\xcf\x41\x6b\x8e\x6a\xa5\x22"
++ "\xab\xdb\x96\xa2\xcf\x46\xd8\x9b\x45\x93\xef\xd6\xdf\x3e\x99\x9c"
++ "\x7e\x29\x10\x6b\x6c\xa2\xb8\x43\x05\x09\x44\x70\x8c\xb8\xaa\x54"
++ "\x7c\x30\x36\x5e\x1c\x5e\x5b\x9f\x6c\x0d\x81\xee\xa0\x93\x8d\x67"
++ "\x55\xf3\x87\xaf\xaa\x6b\x58\xf9\xbe\xb2\x36\x07\x42\x6e\xbd\x96"
++ "\xe3\x9f\x1f\x8f\xc9\xf4\x9d\xae\x6a\x7d\x4c\x96\xbe\x5f\xc7\xcd"
++ "\xf3\xb2\xf7\xcd\xf0\xcf\xc3\xe4\xf8\xfe\x37\x4f\x1c\x4d\xf6\x40"
++ "\xf1\x6b\x7c\x4e\xe0\xa6\x71\xad\x56\xa7\x1c\x5c\x15\x6b\xfc\xf3"
++ "\x01\x5d\xac\xf1\x75\x9a\x72\x6b\xaa\x28\xc5\x88\x6d\xfb\x33\x85"
++ "\xe0\x4e\x61\xab\xeb\x31\x2c\x71\x08\x73\x11\x3b\xfc\xb5\xc0\x96"
++ "\xcc\x87\x24\x44\xb5\x9b\x9e\xb3\x71\xba\xe9\xed\xb1\x4e\xd7\x76"
++ "\x6c\xd2\xb6\x05\xb7\x5a\xde\xeb\x34\x5b\x96\x16\xfb\x59\xa9\x5c"
++ "\x4f\x55\xca\x8a\xac\x59\xb0\xe4\x54\x39\x25\xbc\x81\x37\x2a\x09"
++ "\x5f\x9e\x3b\x6b\x7d\x1f\x69\xf3\x34\x85\x39\x84\xa7\x28\x0b\xd3"
++ "\xfd\xfb\x4b\x7a\xea\xe7\xd2\x3c\xd3\xda\x15\x68\xbc\x73\xd3\x22"
++ "\x6f\xd7\x72\x5b\x2b\x66\xee\xa8\x0d\x54\xe8\x5b\xf9\x92\x96\x92"
++ "\x93\xea\x97\x4a\xc7\x43\x10\x46\x35\xc5\xc0\x60\x8a\xe4\xc1\xb5"
++ "\x36\xc6\xae\xed\xf7\x70\xa5\x86\x99\x3d\x91\xf8\xfd\x4e\x53\xeb"
++ "\xbb\xbd\x6d\xec\x8f\xd7\x89\x3d\x31\x7f\xd7\x78\xba\x50\xbb\x74"
++ "\x9d\xf6\xac\x4e\xb9\x03\x9c\x79\xd5\xe1\xbd\x17\x68\xd9\x13\x0b"
++ "\x45\x75\x88\x00\x1d\x1f\xae\x73\x6a\x1d\x5c\x6e\x44\x9f\xa6\xfa"
++ "\x4e\xd8\x25\x8b\xc0\xbc\xb2\x99\xe3\x17\x24\xb3\x23\xe2\x48\x8b"
++ "\xfa\x22\xe7\x7e\x8f\xe6\x3f\x5f\x55\x0d\x75\xd3\x51\x0b\xd7\xed"
++ "\xd3\x6f\x97\x3b\x85\x42\x80\x7e\x5f\xdc\x1b\xd6\xba\xee\xc4\x80"
++ "\xce\x06\xa9\x15\x8c\x97\x5f\x40\x69\xb2\x4d\xc5\xb2\x5c\x1e\x01"
++ "\x87\x7e\xe0\x36\x6d\x78\x80\x4e\x3c\x02\xec\x90\x1d\x11\x81\x74"
++ "\xa5\x8b\xa4\xa0\x56\x06\xd5\x79\x72\x85\x57\x3b\xb2\x2e\xae\x90"
++ "\x18\x8d\x91\xb2\x0e\x44\x19\xaa\xb4\xcc\x08\xed\x46\xfa\xd7\x2b"
++ "\x78\x58\x72\x5d\xbb\x5e\x49\xe7\xee\xf3\x8a\x9d\x22\xa4\x19\xc8"
++ "\xe7\x08\xc3\x90\x9b\x35\x9a\xa4\x25\x8c\x4b\x9b\xa7\xf8\xbf\x81"
++ "\xf5\xdf\x22\x66\xf1\x7e\x9f\x66\x3d\xbb\xfa\x73\x73\x4d\xfd\x67"
++ "\x7b\xf4\xce\xc3\x62\x2e\x6f\xbb\x0c\xa2\xdc\x69\xfc\x8a\x17\x0e"
++ "\x3a\x9e\x83\x46\xd7\xe3\x5e\x65\x86\xc0\x51\x00\xbb\x91\xe3\xe1"
++ "\xc1\x16\xc4\xe9\x65\x5c\x14\x3e\x44\x6a\x6b\xd1\x1e\xb0\x36\xdd"
++ "\x0b\x7d\x8a\xeb\xaf\x58\x5b\x64\x3f\x38\xed\x52\x76\xe8\x46\xf7"
++ "\x86\x84\xb3\x93\xb1\x0b\xe5\xfd\xfd\x0d\xe9\x6d\xe4\xf1\x1b\x1d"
++ "\x56\xb4\x34\xe4\x6a\xf5\xa4\x9c\x2c\xc9\x64\x94\xc1\xf5\x79\x6d"
++ "\x12\x96\xf3\x47\xc5\x48\xa8\xdb\xd8\x95\x64\x29\xcf\xf6\x88\xf1"
++ "\x95\x7a\x98\xe8\xbc\x27\x19\xce\x73\x61\xd1\xb8\xc6\x31\x8c\xe7"
++ "\x39\xce\x77\x9e\xbc\xc6\x31\x8c\x63\xf3\x9c\xe7\x39\xc6\x31\x8f"
++ "\xf7\xce\x7e\x1e\x3b\x7f\x0f\x0f\x0f\x13\x57\xb9\x0a\xe1\x0b\x64"
++ "\x5f\x58\x40\xc6\xc7\x7a\x4b\xf2\x3d\xbc\x71\xf4\xa7\xd2\xca\x14"
++ "\xe2\x98\x1a\x30\x1e\xe0\x26\x5a\x6a\xf0\x9c\x67\x38\x66\x00\xb8"
++ "\x72\xe6\xbe\xac\xfe\x12\xd3\x0b\x56\x73\x8c\x63\xc7\x2b\xe1\xe2"
++ "\xe8\xdd\x7b\xff\x00\xd8\xe5\x23\x6c\xce\xa8\x69\xcf\x5e\x3a\xef"
++ "\x77\xea\xe5\xab\x0e\x82\xdb\xd9\xed\x7a\x9e\xb8\x6d\x51\x32\xdb"
++ "\x79\xc3\x36\x9a\x2d\xa3\x50\x39\x65\x0a\x63\x0e\xe5\xd4\x39\x12"
++ "\xbf\x8b\x98\xa4\xa1\x2d\xad\xb3\xcf\x65\x6a\x43\x78\xb3\x3b\x07"
++ "\xd8\xd5\xea\xae\x76\xad\x6f\xf5\xff\x00\xca\x93\xab\x96\xb0\x64"
++ "\xeb\xd6\x4a\xd5\x87\xba\xec\x24\x60\x97\x06\x76\x03\xe3\x4c\x07"
++ "\x29\x11\x8e\x34\x25\x02\x64\x29\xf0\x25\x48\x85\x3a\x33\x8b\x7a"
++ "\x3c\x86\x1e\x75\xa5\x61\xc6\x97\x9f\x8d\x25\xf5\xc9\xcd\xde\xc9"
++ "\x7d\x77\xf2\xc8\x7e\x70\xaf\x73\x5f\x2d\xec\xa2\x51\x2d\x96\xfb"
++ "\x89\xad\x80\x57\xb2\x36\x1d\x7d\x83\x45\xac\xf3\xdb\xcc\x6c\x31"
++ "\x4f\xcf\x30\x58\xd0\x12\x28\x90\x50\x42\x86\xfb\x48\x16\x3c\xc5"
++ "\x9c\xf8\xe7\xcc\x29\x88\xb3\x4a\x4b\x4e\x6c\xbc\xdb\xc7\xbb\xe9"
++ "\xb6\xa0\x8b\x11\xa1\x7d\x73\xd7\xe9\xbf\x7e\xc2\x6c\x10\x8d\xee"
++ "\x9d\xef\x63\x3a\xe0\xf5\xbe\x8c\x3e\xa1\xc7\xc5\xd1\x00\x44\x1e"
++ "\xf3\x51\xf2\xe2\xb0\xe3\xb5\x13\x7f\x32\xf1\x8c\xa6\x22\xfe\x1f"
++ "\x49\x4d\xbb\xcf\x3a\x5d\xed\x4c\xd2\xfc\x85\xed\x23\xd6\xc7\x50"
++ "\xb6\x5b\x3a\x16\x83\xb8\x6f\xfd\x32\x3f\xaa\x36\x34\xbb\xf5\x96"
++ "\xa9\xab\xcf\x9f\x8f\xac\xc3\xca\xd5\x8b\xd8\x48\x9e\x79\xaa\x30"
++ "\x87\xca\x58\x4d\x59\x96\xb9\x4f\xc5\x1b\x1c\xd2\xda\x5b\xe6\x57"
++ "\x29\xa1\x28\x7a\x2b\x5b\xff\x00\x12\x2f\x5e\x3f\xf3\xbb\x8e\x7f"
++ "\xec\xc6\x98\xff\x00\xed\x3c\xa6\xdd\xa9\xdc\x7e\xa0\xf7\xd6\x99"
++ "\x31\xa2\xf7\xaf\x6b\xe9\x82\x74\x4b\x3d\x8f\x5e\x58\x0b\x33\xab"
++ "\xef\xc3\xaf\x84\x64\xb9\xae\xb6\x25\x5f\x62\x8f\x1c\xe3\xf4\x51"
++ "\xb7\x96\xe3\x0e\x30\x42\xa9\x18\x39\xbf\x9e\x2a\x1f\x74\x19\x02"
++ "\x2d\x43\x93\x06\x63\xb1\xa7\x47\x6a\xfa\x9b\x6c\xeb\xbd\xe9\xae"
++ "\x6a\x7b\x6f\x53\x5a\x60\x5d\xb5\xcd\xe8\x67\xeb\x35\x3b\x48\xc6"
++ "\xa6\xb3\x04\xc8\xdf\xb8\x7e\x26\x64\xb0\xc9\x18\xb0\xa7\x33\xf2"
++ "\x4a\x8b\x22\x3b\x8d\x4b\x89\x1d\xf6\x9d\x65\xc4\x38\xd2\x54\x9c"
++ "\xe3\xcd\x89\xe1\xe1\xe6\x3e\x70\x81\x45\x1d\x18\xf9\x31\x83\xc8"
++ "\xbe\x14\x82\x4b\x87\x7a\x74\x28\xd2\xdd\x12\x55\x30\xe6\x0e\x49"
++ "\x31\x8e\x48\x69\xc5\xc0\x20\x91\xe4\x48\x41\x4c\xd8\xb9\x6a\x4e"
++ "\x21\xce\x99\x1b\x0e\xfd\x09\x4f\xa1\x79\x0f\x0f\x0f\x0f\x0f\x0f"
++ "\x0f\x3f\x3c\xb8\x71\x27\xc7\x72\x24\xe8\xb1\xa6\xc5\x7b\x18\xc3"
++ "\xb1\xa5\xb0\xd4\x98\xee\xe3\x19\xc6\x71\x87\x19\x79\x2b\x6d\x78"
++ "\xc6\x71\x8c\xe3\x0a\x4e\x71\x8c\xe3\x19\xfe\x38\xf2\x3b\xfb\x8b"
++ "\x48\xfe\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe1\xfb\x8b\x48\xfe"
++ "\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe4\x95\x86\x18\x8a\xcb\x31"
++ "\xa3\x32\xd4\x78\xf1\xdb\x43\x2c\x47\x61\xb4\x32\xcb\x2c\xb4\x9c"
++ "\x21\xb6\x99\x69\xbc\x25\xb6\xdb\x6d\x18\xc2\x10\xda\x12\x94\xa1"
++ "\x38\xc2\x53\x8c\x63\x18\xc7\x9d\xbe\x7f\xff\xd9"
++ ;
+diff -Nura php-5.3.6/main/suhosin_patch.c suhosin-patch-5.3.6-0.9.10/main/suhosin_patch.c
+--- php-5.3.6/main/suhosin_patch.c 1970-01-01 01:00:00.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/suhosin_patch.c 2011-03-19 10:48:33.813975198 +0100
+@@ -0,0 +1,470 @@
++/*
++ +----------------------------------------------------------------------+
++ | Suhosin Patch for PHP |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 2004-2010 Stefan Esser |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 2.02 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available at through the world-wide-web at |
++ | http://www.php.net/license/2_02.txt. |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Author: Stefan Esser <sesser@hardened-php.net> |
++ +----------------------------------------------------------------------+
++ */
++/* $Id: suhosin_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */
++
++#include "php.h"
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/mman.h>
++
++#if HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++#include "SAPI.h"
++#include "php_globals.h"
++
++#if SUHOSIN_PATCH
++
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++
++#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
++#undef AF_UNIX
++#endif
++
++#if defined(AF_UNIX)
++#include <sys/un.h>
++#endif
++
++#define SYSLOG_PATH "/dev/log"
++
++#ifdef PHP_WIN32
++static HANDLE log_source = 0;
++#endif
++
++#include "snprintf.h"
++
++#include "suhosin_patch.h"
++
++#ifdef ZTS
++#include "suhosin_globals.h"
++int suhosin_patch_globals_id;
++#else
++struct _suhosin_patch_globals suhosin_patch_globals;
++#endif
++
++static char *suhosin_config = NULL;
++
++static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
++
++static void php_security_log(int loglevel, char *fmt, ...);
++
++static void suhosin_patch_globals_ctor(suhosin_patch_globals_struct *suhosin_patch_globals TSRMLS_DC)
++{
++ memset(suhosin_patch_globals, 0, sizeof(*suhosin_patch_globals));
++}
++
++ZEND_API char suhosin_get_config(int element)
++{
++ return ((char *)SUHOSIN_MANGLE_PTR(suhosin_config))[element];
++}
++
++static void suhosin_set_config(int element, char value)
++{
++ ((char *)SUHOSIN_MANGLE_PTR(suhosin_config))[element] = value;
++}
++
++static void suhosin_read_configuration_from_environment()
++{
++ char *tmp;
++
++ /* check if canary protection should be activated or not */
++ tmp = getenv("SUHOSIN_MM_USE_CANARY_PROTECTION");
++ /* default to activated */
++ suhosin_set_config(SUHOSIN_MM_USE_CANARY_PROTECTION, 1);
++ if (tmp) {
++ int flag = zend_atoi(tmp, 0);
++ suhosin_set_config(SUHOSIN_MM_USE_CANARY_PROTECTION, flag);
++ }
++
++ /* check if free memory should be overwritten with 0xFF or not */
++ tmp = getenv("SUHOSIN_MM_DESTROY_FREE_MEMORY");
++ /* default to deactivated */
++ suhosin_set_config(SUHOSIN_MM_DESTROY_FREE_MEMORY, 0);
++ if (tmp) {
++ int flag = zend_atoi(tmp, 0);
++ suhosin_set_config(SUHOSIN_MM_DESTROY_FREE_MEMORY, flag);
++ }
++
++ /* check if canary violations should be ignored */
++ tmp = getenv("SUHOSIN_MM_IGNORE_CANARY_VIOLATION");
++ /* default to NOT ignore */
++ suhosin_set_config(SUHOSIN_MM_IGNORE_CANARY_VIOLATION, 0);
++ if (tmp) {
++ int flag = zend_atoi(tmp, 0);
++ suhosin_set_config(SUHOSIN_MM_IGNORE_CANARY_VIOLATION, flag);
++ }
++
++ /* check if invalid hashtable destructors should be ignored */
++ tmp = getenv("SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR");
++ /* default to NOT ignore */
++ suhosin_set_config(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR, 0);
++ if (tmp) {
++ int flag = zend_atoi(tmp, 0);
++ suhosin_set_config(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR, flag);
++ }
++
++ /* check if invalid linkedlist destructors should be ignored */
++ tmp = getenv("SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR");
++ /* default to NOT ignore */
++ suhosin_set_config(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR, 0);
++ if (tmp) {
++ int flag = zend_atoi(tmp, 0);
++ suhosin_set_config(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR, flag);
++ }
++
++ suhosin_set_config(SUHOSIN_CONFIG_SET, 1);
++}
++
++static void suhosin_write_protect_configuration()
++{
++ /* check return value of mprotect() to ensure memory is read only now */
++ if (mprotect(SUHOSIN_MANGLE_PTR(suhosin_config), sysconf(_SC_PAGESIZE), PROT_READ) != 0) {
++ perror("suhosin");
++ _exit(1);
++ }
++}
++
++PHPAPI void suhosin_startup()
++{
++#ifdef ZTS
++ ts_allocate_id(&suhosin_patch_globals_id, sizeof(suhosin_patch_globals_struct), (ts_allocate_ctor) suhosin_patch_globals_ctor, NULL);
++#else
++ suhosin_patch_globals_ctor(&suhosin_patch_globals TSRMLS_CC);
++#endif
++ zend_suhosin_log = php_security_log;
++
++ /* get the pointer guardian and ensure low 3 bits are 1 */
++ if (SUHOSIN_POINTER_GUARD == 0) {
++ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
++ SUHOSIN_POINTER_GUARD |= 7;
++ }
++
++ if (!suhosin_config) {
++#ifndef MAP_ANONYMOUS
++#define MAP_ANONYMOUS MAP_ANON
++#endif
++ suhosin_config = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
++ if (suhosin_config == MAP_FAILED) {
++ perror("suhosin");
++ _exit(1);
++ }
++ suhosin_config = SUHOSIN_MANGLE_PTR(suhosin_config);
++ }
++ if (!SUHOSIN_CONFIG(SUHOSIN_CONFIG_SET)) {
++ suhosin_read_configuration_from_environment();
++ suhosin_write_protect_configuration();
++ }
++}
++
++static char *loglevel2string(int loglevel)
++{
++ switch (loglevel) {
++ case S_FILES:
++ return "FILES";
++ case S_INCLUDE:
++ return "INCLUDE";
++ case S_MEMORY:
++ return "MEMORY";
++ case S_MISC:
++ return "MISC";
++ case S_SESSION:
++ return "SESSION";
++ case S_SQL:
++ return "SQL";
++ case S_EXECUTOR:
++ return "EXECUTOR";
++ case S_VARS:
++ return "VARS";
++ default:
++ return "UNKNOWN";
++ }
++}
++
++static void php_security_log(int loglevel, char *fmt, ...)
++{
++ int s, r, i=0;
++#if defined(AF_UNIX)
++ struct sockaddr_un saun;
++#endif
++#ifdef PHP_WIN32
++ LPTSTR strs[2];
++ unsigned short etype;
++ DWORD evid;
++#endif
++ char buf[4096+64];
++ char error[4096+100];
++ char *ip_address;
++ char *fname;
++ char *alertstring;
++ int lineno;
++ va_list ap;
++ TSRMLS_FETCH();
++
++ /*SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SPG(log_syslog), SPG(log_sapi), SPG(log_script));*/
++
++ if (SPG(log_use_x_forwarded_for)) {
++ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
++ if (ip_address == NULL) {
++ ip_address = "X-FORWARDED-FOR not set";
++ }
++ } else {
++ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
++ if (ip_address == NULL) {
++ ip_address = "REMOTE_ADDR not set";
++ }
++ }
++
++
++ va_start(ap, fmt);
++ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
++ va_end(ap);
++ while (error[i]) {
++ if (error[i] < 32) error[i] = '.';
++ i++;
++ }
++
++/* if (SPG(simulation)) {
++ alertstring = "ALERT-SIMULATION";
++ } else { */
++ alertstring = "ALERT";
++/* }*/
++
++ if (zend_is_executing(TSRMLS_C)) {
++ if (EG(current_execute_data)) {
++ lineno = EG(current_execute_data)->opline->lineno;
++ fname = EG(current_execute_data)->op_array->filename;
++ } else {
++ lineno = zend_get_executed_lineno(TSRMLS_C);
++ fname = zend_get_executed_filename(TSRMLS_C);
++ }
++ ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno);
++ } else {
++ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
++ if (fname==NULL) {
++ fname = "unknown";
++ }
++ ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname);
++ }
++
++ /* Syslog-Logging disabled? */
++ if (((SPG(log_syslog)|S_INTERNAL) & loglevel)==0) {
++ goto log_sapi;
++ }
++
++#if defined(AF_UNIX)
++ ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SPG(log_syslog_facility)|SPG(log_syslog_priority)),getpid(),buf);
++
++ s = socket(AF_UNIX, SOCK_DGRAM, 0);
++ if (s == -1) {
++ goto log_sapi;
++ }
++
++ memset(&saun, 0, sizeof(saun));
++ saun.sun_family = AF_UNIX;
++ strcpy(saun.sun_path, SYSLOG_PATH);
++ /*saun.sun_len = sizeof(saun);*/
++
++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
++ if (r) {
++ close(s);
++ s = socket(AF_UNIX, SOCK_STREAM, 0);
++ if (s == -1) {
++ goto log_sapi;
++ }
++
++ memset(&saun, 0, sizeof(saun));
++ saun.sun_family = AF_UNIX;
++ strcpy(saun.sun_path, SYSLOG_PATH);
++ /*saun.sun_len = sizeof(saun);*/
++
++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
++ if (r) {
++ close(s);
++ goto log_sapi;
++ }
++ }
++ send(s, error, strlen(error), 0);
++
++ close(s);
++#endif
++#ifdef PHP_WIN32
++ ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf);
++
++ switch (SPG(log_syslog_priority)) { /* translate UNIX type into NT type */
++ case 1: /*LOG_ALERT:*/
++ etype = EVENTLOG_ERROR_TYPE;
++ break;
++ case 6: /*LOG_INFO:*/
++ etype = EVENTLOG_INFORMATION_TYPE;
++ break;
++ default:
++ etype = EVENTLOG_WARNING_TYPE;
++ }
++ evid = loglevel;
++ strs[0] = error;
++ /* report the event */
++ if (log_source == NULL) {
++ log_source = RegisterEventSource(NULL, "Suhosin-Patch-" SUHOSIN_PATCH_VERSION);
++ }
++ ReportEvent(log_source, etype, (unsigned short) SPG(log_syslog_priority), evid, NULL, 1, 0, strs, NULL);
++
++#endif
++log_sapi:
++ /* SAPI Logging activated? */
++ /*SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SPG(log_syslog), SPG(log_sapi), SPG(log_script), SPG(log_phpscript));*/
++ if (((SPG(log_sapi)|S_INTERNAL) & loglevel)!=0) {
++ sapi_module.log_message(buf);
++ }
++
++/*log_script:*/
++ /* script logging activaed? */
++ if (((SPG(log_script) & loglevel)!=0) && SPG(log_scriptname)!=NULL) {
++ char cmd[8192], *cmdpos, *bufpos;
++ FILE *in;
++ int space;
++
++ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", SPG(log_scriptname), loglevel2string(loglevel));
++ space = sizeof(cmd) - strlen(cmd);
++ cmdpos = cmd + strlen(cmd);
++ bufpos = buf;
++ if (space <= 1) return;
++ while (space > 2 && *bufpos) {
++ if (*bufpos == '\'') {
++ if (space<=5) break;
++ *cmdpos++ = '\'';
++ *cmdpos++ = '\\';
++ *cmdpos++ = '\'';
++ *cmdpos++ = '\'';
++ bufpos++;
++ space-=4;
++ } else {
++ *cmdpos++ = *bufpos++;
++ space--;
++ }
++ }
++ *cmdpos++ = '\'';
++ *cmdpos = 0;
++
++ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
++ php_security_log(S_INTERNAL, "Unable to execute logging shell script: %s", SPG(log_scriptname));
++ return;
++ }
++ /* read and forget the result */
++ while (1) {
++ int readbytes = fread(cmd, 1, sizeof(cmd), in);
++ if (readbytes<=0) {
++ break;
++ }
++ }
++ pclose(in);
++ }
++/*log_phpscript:*/
++ if ((SPG(log_phpscript) & loglevel)!=0 && EG(in_execution) && SPG(log_phpscriptname) && SPG(log_phpscriptname)[0]) {
++ zend_file_handle file_handle;
++ zend_op_array *new_op_array;
++ zval *result = NULL;
++
++ /*long orig_execution_depth = SPG(execution_depth);*/
++ zend_bool orig_safe_mode = PG(safe_mode);
++ char *orig_basedir = PG(open_basedir);
++
++ char *phpscript = SPG(log_phpscriptname);
++/*SDEBUG("scriptname %s", SPG(log_phpscriptname));`*/
++#ifdef ZEND_ENGINE_2
++ if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) {
++#else
++ if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
++ file_handle.filename = phpscript;
++ file_handle.free_filename = 0;
++#endif
++ if (!file_handle.opened_path) {
++ file_handle.opened_path = estrndup(phpscript, strlen(phpscript));
++ }
++ new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
++ zend_destroy_file_handle(&file_handle TSRMLS_CC);
++ if (new_op_array) {
++ HashTable *active_symbol_table = EG(active_symbol_table);
++ zval *zerror, *zerror_class;
++
++ if (active_symbol_table == NULL) {
++ active_symbol_table = &EG(symbol_table);
++ }
++ EG(return_value_ptr_ptr) = &result;
++ EG(active_op_array) = new_op_array;
++
++ MAKE_STD_ZVAL(zerror);
++ MAKE_STD_ZVAL(zerror_class);
++ ZVAL_STRING(zerror, buf, 1);
++ ZVAL_LONG(zerror_class, loglevel);
++
++ zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL);
++ zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL);
++
++ /*SPG(execution_depth) = 0;*/
++ if (SPG(log_phpscript_is_safe)) {
++ PG(safe_mode) = 0;
++ PG(open_basedir) = NULL;
++ }
++
++ zend_execute(new_op_array TSRMLS_CC);
++
++ /*SPG(execution_depth) = orig_execution_depth;*/
++ PG(safe_mode) = orig_safe_mode;
++ PG(open_basedir) = orig_basedir;
++
++#ifdef ZEND_ENGINE_2
++ destroy_op_array(new_op_array TSRMLS_CC);
++#else
++ destroy_op_array(new_op_array);
++#endif
++ efree(new_op_array);
++#ifdef ZEND_ENGINE_2
++ if (!EG(exception))
++#endif
++ {
++ if (EG(return_value_ptr_ptr)) {
++ zval_ptr_dtor(EG(return_value_ptr_ptr));
++ EG(return_value_ptr_ptr) = NULL;
++ }
++ }
++ } else {
++ php_security_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SPG(log_phpscriptname));
++ return;
++ }
++ } else {
++ php_security_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SPG(log_phpscriptname));
++ return;
++ }
++ }
++
++}
++
++
++#endif
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim600: sw=4 ts=4 fdm=marker
++ * vim<600: sw=4 ts=4
++ */
+diff -Nura php-5.3.6/main/suhosin_patch.h suhosin-patch-5.3.6-0.9.10/main/suhosin_patch.h
+--- php-5.3.6/main/suhosin_patch.h 1970-01-01 01:00:00.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/suhosin_patch.h 2011-03-19 10:48:33.813975198 +0100
+@@ -0,0 +1,59 @@
++/*
++ +----------------------------------------------------------------------+
++ | Suhosin Patch for PHP |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 2004-2010 Stefan Esser |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 2.02 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available at through the world-wide-web at |
++ | http://www.php.net/license/2_02.txt. |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
++ +----------------------------------------------------------------------+
++ */
++
++#ifndef SUHOSIN_PATCH_H
++#define SUHOSIN_PATCH_H
++
++#if SUHOSIN_PATCH
++
++#include "zend.h"
++
++#define SUHOSIN_PATCH_VERSION "0.9.10"
++
++#define SUHOSIN_LOGO_GUID "SUHO8567F54-D428-14d2-A769-00DA302A5F18"
++
++#define SUHOSIN_CONFIG(idx) (suhosin_get_config(idx))
++
++#define SUHOSIN_MM_USE_CANARY_PROTECTION 0
++#define SUHOSIN_MM_DESTROY_FREE_MEMORY 1
++#define SUHOSIN_MM_IGNORE_CANARY_VIOLATION 2
++#define SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR 3
++#define SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR 4
++
++#define SUHOSIN_CONFIG_SET 100
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++
++#if defined(DARWIN)
++#include <mach/vm_param.h>
++#endif
++
++#define SUHOSIN_MANGLE_PTR(ptr) (ptr==NULL?NULL:((void *)((zend_intptr_t)(ptr)^SUHOSIN_POINTER_GUARD)))
++
++#endif
++
++#endif /* SUHOSIN_PATCH_H */
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ */
+diff -Nura php-5.3.6/main/suhosin_patch.m4 suhosin-patch-5.3.6-0.9.10/main/suhosin_patch.m4
+--- php-5.3.6/main/suhosin_patch.m4 1970-01-01 01:00:00.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/main/suhosin_patch.m4 2011-03-19 10:48:33.813975198 +0100
+@@ -0,0 +1,8 @@
++dnl
++dnl $Id: suhosin_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $
++dnl
++dnl This file contains Suhosin Patch for PHP specific autoconf functions.
++dnl
++
++AC_DEFINE(SUHOSIN_PATCH, 1, [Suhosin Patch])
++
+diff -Nura php-5.3.6/sapi/apache/mod_php5.c suhosin-patch-5.3.6-0.9.10/sapi/apache/mod_php5.c
+--- php-5.3.6/sapi/apache/mod_php5.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/sapi/apache/mod_php5.c 2011-03-19 10:48:33.813975198 +0100
+@@ -969,7 +969,11 @@
+ {
+ TSRMLS_FETCH();
+ if (PG(expose_php)) {
++#if SUHOSIN_PATCH
++ ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch");
++#else
+ ap_add_version_component("PHP/" PHP_VERSION);
++#endif
+ }
+ }
+ #endif
+diff -Nura php-5.3.6/sapi/apache2filter/sapi_apache2.c suhosin-patch-5.3.6-0.9.10/sapi/apache2filter/sapi_apache2.c
+--- php-5.3.6/sapi/apache2filter/sapi_apache2.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/sapi/apache2filter/sapi_apache2.c 2011-03-19 10:48:33.813975198 +0100
+@@ -583,7 +583,11 @@
+ {
+ TSRMLS_FETCH();
+ if (PG(expose_php)) {
++#if SUHOSIN_PATCH
++ ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch");
++#else
+ ap_add_version_component(p, "PHP/" PHP_VERSION);
++#endif
+ }
+ }
+
+diff -Nura php-5.3.6/sapi/apache2handler/sapi_apache2.c suhosin-patch-5.3.6-0.9.10/sapi/apache2handler/sapi_apache2.c
+--- php-5.3.6/sapi/apache2handler/sapi_apache2.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/sapi/apache2handler/sapi_apache2.c 2011-03-19 10:48:33.813975198 +0100
+@@ -407,7 +407,11 @@
+ {
+ TSRMLS_FETCH();
+ if (PG(expose_php)) {
++#if SUHOSIN_PATCH
++ ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch");
++#else
+ ap_add_version_component(p, "PHP/" PHP_VERSION);
++#endif
+ }
+ }
+
+diff -Nura php-5.3.6/sapi/apache_hooks/mod_php5.c suhosin-patch-5.3.6-0.9.10/sapi/apache_hooks/mod_php5.c
+--- php-5.3.6/sapi/apache_hooks/mod_php5.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/sapi/apache_hooks/mod_php5.c 2011-03-19 10:48:33.813975198 +0100
+@@ -1256,7 +1256,11 @@
+ {
+ TSRMLS_FETCH();
+ if (PG(expose_php)) {
++#if SUHOSIN_PATCH
++ ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch");
++#else
+ ap_add_version_component("PHP/" PHP_VERSION);
++#endif
+ }
+ }
+ #endif
+diff -Nura php-5.3.6/sapi/cgi/cgi_main.c suhosin-patch-5.3.6-0.9.10/sapi/cgi/cgi_main.c
+--- php-5.3.6/sapi/cgi/cgi_main.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/sapi/cgi/cgi_main.c 2011-03-19 10:48:33.813975198 +0100
+@@ -1929,10 +1929,18 @@
+ SG(headers_sent) = 1;
+ SG(request_info).no_headers = 1;
+ }
++#if SUHOSIN_PATCH
+ #if ZEND_DEBUG
+- php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ #else
+- php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++#endif
++#else
++ #if ZEND_DEBUG
++ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++ #else
++ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++ #endif
+ #endif
+ php_request_shutdown((void *) 0);
+ fcgi_shutdown();
+diff -Nura php-5.3.6/sapi/cli/php_cli.c suhosin-patch-5.3.6-0.9.10/sapi/cli/php_cli.c
+--- php-5.3.6/sapi/cli/php_cli.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/sapi/cli/php_cli.c 2011-03-19 10:48:33.813975198 +0100
+@@ -832,7 +832,11 @@
+ }
+
+ request_started = 1;
+- php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2011 The PHP Group\n%s",
++ php_printf("PHP %s "
++#if SUHOSIN_PATCH
++ "with Suhosin-Patch "
++#endif
++ "(%s) (built: %s %s) %s\nCopyright (c) 1997-2011 The PHP Group\n%s",
+ PHP_VERSION, sapi_module.name, __DATE__, __TIME__,
+ #if ZEND_DEBUG && defined(HAVE_GCOV)
+ "(DEBUG GCOV)",
+diff -Nura php-5.3.6/sapi/litespeed/lsapi_main.c suhosin-patch-5.3.6-0.9.10/sapi/litespeed/lsapi_main.c
+--- php-5.3.6/sapi/litespeed/lsapi_main.c 2010-12-10 23:51:08.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/sapi/litespeed/lsapi_main.c 2011-03-19 10:50:41.432696713 +0100
+@@ -710,11 +710,19 @@
+ break;
+ case 'v':
+ if (php_request_startup(TSRMLS_C) != FAILURE) {
++#if SUHOSIN_PATCH
++#if ZEND_DEBUG
++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++#else
++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++#endif
++#else
+ #if ZEND_DEBUG
+ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ #else
+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ #endif
++#endif
+ #ifdef PHP_OUTPUT_NEWAPI
+ php_output_end_all(TSRMLS_C);
+ #else
+diff -Nura php-5.3.6/sapi/milter/php_milter.c suhosin-patch-5.3.6-0.9.10/sapi/milter/php_milter.c
+--- php-5.3.6/sapi/milter/php_milter.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/sapi/milter/php_milter.c 2011-03-19 10:48:33.817308498 +0100
+@@ -1111,7 +1111,11 @@
+ }
+ SG(headers_sent) = 1;
+ SG(request_info).no_headers = 1;
++#if SUHOSIN_PATCH
++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++#else
+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
++#endif
+ php_end_ob_buffers(1 TSRMLS_CC);
+ exit(1);
+ break;
+diff -Nura php-5.3.6/win32/build/config.w32 suhosin-patch-5.3.6-0.9.10/win32/build/config.w32
+--- php-5.3.6/win32/build/config.w32 2011-03-02 19:35:10.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/win32/build/config.w32 2011-03-19 10:48:33.817308498 +0100
+@@ -328,7 +328,7 @@
+ zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \
+ zend_object_handlers.c zend_objects_API.c \
+ zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \
+- zend_float.c");
++ zend_float.c zend_canary.c zend_alloc_canary.c");
+
+ if (VCVERS == 1200) {
+ AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1);
+@@ -385,6 +385,7 @@
+
+ AC_DEFINE('HAVE_USLEEP', 1);
+ AC_DEFINE('HAVE_STRCOLL', 1);
++AC_DEFINE('SUHOSIN_PATCH', 1);
+
+ /* For snapshot builders, where can we find the additional
+ * files that make up the snapshot template? */
+diff -Nura php-5.3.6/win32/build/config.w32.h.in suhosin-patch-5.3.6-0.9.10/win32/build/config.w32.h.in
+--- php-5.3.6/win32/build/config.w32.h.in 2010-11-26 19:25:13.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/win32/build/config.w32.h.in 2011-03-19 10:48:33.817308498 +0100
+@@ -152,6 +152,9 @@
+ /* Win32 supports strcoll */
+ #define HAVE_STRCOLL 1
+
++/* Suhosin Patch support */
++#define SUHOSIN_PATCH 1
++
+ /* Win32 supports socketpair by the emulation in win32/sockets.c */
+ #define HAVE_SOCKETPAIR 1
+ #define HAVE_SOCKLEN_T 1
+diff -Nura php-5.3.6/Zend/Makefile.am suhosin-patch-5.3.6-0.9.10/Zend/Makefile.am
+--- php-5.3.6/Zend/Makefile.am 2009-03-18 11:18:10.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/Makefile.am 2011-03-19 10:48:33.790642098 +0100
+@@ -17,7 +17,7 @@
+ zend_objects_API.c zend_ts_hash.c zend_stream.c \
+ zend_default_classes.c \
+ zend_iterators.c zend_interfaces.c zend_exceptions.c \
+- zend_strtod.c zend_closures.c zend_float.c
++ zend_strtod.c zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c
+
+ libZend_la_LDFLAGS =
+ libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
+diff -Nura php-5.3.6/Zend/zend_alloc.c suhosin-patch-5.3.6-0.9.10/Zend/zend_alloc.c
+--- php-5.3.6/Zend/zend_alloc.c 2011-02-07 11:25:34.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_alloc.c 2011-03-19 10:48:33.793975398 +0100
+@@ -32,6 +32,10 @@
+ # include <unistd.h>
+ #endif
+
++#if SUHOSIN_PATCH
++#include "suhosin_patch.h"
++#endif
++
+ #ifdef ZEND_WIN32
+ # include <wincrypt.h>
+ # include <process.h>
+@@ -59,6 +63,7 @@
+ # define PTR_FMT "0x%0.8lx"
+ #endif
+
++#ifndef SUHOSIN_MM_CLONE_FILE
+ #if ZEND_DEBUG
+ void zend_debug_alloc_output(char *format, ...)
+ {
+@@ -76,6 +81,7 @@
+ #endif
+ }
+ #endif
++#endif
+
+ #if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
+ static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
+@@ -134,6 +140,8 @@
+ # endif
+ #endif
+
++static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
++
+ static zend_mm_storage* zend_mm_mem_dummy_init(void *params)
+ {
+ return malloc(sizeof(zend_mm_storage));
+@@ -332,13 +340,28 @@
+ #define MEM_BLOCK_GUARD 0x2A8FCC84
+ #define MEM_BLOCK_LEAK 0x6C5E8F2D
+
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++# define CANARY_SIZE sizeof(size_t)
++#else
++# define CANARY_SIZE 0
++#endif
++
+ /* mm block type */
+ typedef struct _zend_mm_block_info {
+ #if ZEND_MM_COOKIES
+ size_t _cookie;
+ #endif
+- size_t _size;
+- size_t _prev;
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++ size_t canary_1;
++#endif
++ size_t _size;
++ size_t _prev;
++#if SUHOSIN_PATCH
++ size_t size;
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++ size_t canary_2;
++#endif
++#endif
+ } zend_mm_block_info;
+
+ #if ZEND_DEBUG
+@@ -412,7 +435,7 @@
+ # define ZEND_MM_CACHE_STAT 0
+ #endif
+
+-struct _zend_mm_heap {
++typedef struct _zend_mm_heap {
+ int use_zend_alloc;
+ void *(*_malloc)(size_t);
+ void (*_free)(void*);
+@@ -447,6 +470,9 @@
+ int miss;
+ } cache_stat[ZEND_MM_NUM_BUCKETS+1];
+ #endif
++#if SUHOSIN_PATCH
++ size_t canary_1,canary_2,canary_3;
++#endif
+ };
+
+ #define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
+@@ -520,18 +546,31 @@
+ /* optimized access */
+ #define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size
+
++#ifndef ZEND_MM_ALIGNMENT
++# define ZEND_MM_ALIGNMENT 8
++# define ZEND_MM_ALIGNMENT_LOG2 3
++#elif ZEND_MM_ALIGNMENT < 4
++# undef ZEND_MM_ALIGNMENT
++# undef ZEND_MM_ALIGNMENT_LOG2
++# define ZEND_MM_ALIGNMENT 4
++# define ZEND_MM_ALIGNMENT_LOG2 2
++#endif
++
++#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1)
++
+ /* Aligned header size */
++#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK)
+ #define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block))
+ #define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block))
+-#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE)
++#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE + CANARY_SIZE)
+ #define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE)
+ #define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
+
+-#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)):0)
++#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)):0)
+
+ #define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<<ZEND_MM_ALIGNMENT_LOG2)+ZEND_MM_ALIGNED_MIN_HEADER_SIZE)
+
+-#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)))
++#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)))
+
+ #define ZEND_MM_BUCKET_INDEX(true_size) ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))
+
+@@ -593,6 +632,44 @@
+
+ #endif
+
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++
++# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) do { \
++ char *p = SUHOSIN_MM_END_CANARY_PTR(block); size_t check; \
++ if (((block)->info.canary_1 != heap->canary_1) || ((block)->info.canary_2 != heap->canary_2)) { \
++ canary_mismatch: \
++ zend_suhosin_log(S_MEMORY, "canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { (block)->info.canary_1 = heap->canary_1; (block)->info.canary_2 = heap->canary_2; }\
++ } \
++ memcpy(&check, p, CANARY_SIZE); \
++ if (check != heap->canary_3) { \
++ zend_suhosin_log(S_MEMORY, "end canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { memcpy(p, heap->canary_3, CANARY_SIZE); } \
++ } \
++ } while (0)
++
++# define SUHOSIN_MM_SET_CANARIES(block) do { \
++ (block)->info.canary_1 = heap->canary_1; \
++ (block)->info.canary_2 = heap->canary_2; \
++ } while (0)
++
++# define SUHOSIN_MM_END_CANARY_PTR(block) \
++ (char *)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block*)(block))->info.size + END_MAGIC_SIZE)
++
++# define SUHOSIN_MM_SET_END_CANARY(block) do { \
++ char *p = SUHOSIN_MM_END_CANARY_PTR(block); \
++ memcpy(p, &heap->canary_3, CANARY_SIZE); \
++ } while (0)
++
++#else
++
++# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION)
++# define SUHOSIN_MM_SET_CANARIES(block)
++# define SUHOSIN_MM_END_CANARY_PTR(block)
++# define SUHOSIN_MM_SET_END_CANARY(block)
++
++#endif
++
+
+ #if ZEND_MM_HEAP_PROTECTION
+
+@@ -715,7 +792,7 @@
+ #endif
+ }
+
+-static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
++static void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
+ {
+ zend_mm_free_block *prev, *next;
+
+@@ -725,14 +802,14 @@
+ mm_block->parent = NULL;
+ }
+
+- prev = heap->rest_buckets[0];
+- next = prev->next_free_block;
+- mm_block->prev_free_block = prev;
+- mm_block->next_free_block = next;
+- prev->next_free_block = next->prev_free_block = mm_block;
++ prev = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
++ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
+ }
+
+-static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
++static void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
+ {
+ size_t size;
+ size_t index;
+@@ -749,7 +826,7 @@
+ if (!*p) {
+ *p = mm_block;
+ mm_block->parent = p;
+- mm_block->prev_free_block = mm_block->next_free_block = mm_block;
++ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
+ heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
+ } else {
+ size_t m;
+@@ -762,15 +839,15 @@
+ if (!*p) {
+ *p = mm_block;
+ mm_block->parent = p;
+- mm_block->prev_free_block = mm_block->next_free_block = mm_block;
++ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
+ break;
+ }
+ } else {
+- zend_mm_free_block *next = prev->next_free_block;
++ zend_mm_free_block *next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
+
+- prev->next_free_block = next->prev_free_block = mm_block;
+- mm_block->next_free_block = next;
+- mm_block->prev_free_block = prev;
++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
+ mm_block->parent = NULL;
+ break;
+ }
+@@ -782,27 +859,33 @@
+ index = ZEND_MM_BUCKET_INDEX(size);
+
+ prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
+- if (prev->prev_free_block == prev) {
++ if (SUHOSIN_MANGLE_PTR(prev->prev_free_block) == prev) {
+ heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
+ }
+- next = prev->next_free_block;
++ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
+
+- mm_block->prev_free_block = prev;
+- mm_block->next_free_block = next;
+- prev->next_free_block = next->prev_free_block = mm_block;
++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
+ }
+ }
+
+-static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
++static void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
+ {
+- zend_mm_free_block *prev = mm_block->prev_free_block;
+- zend_mm_free_block *next = mm_block->next_free_block;
++ zend_mm_free_block *prev = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
++ zend_mm_free_block *next = SUHOSIN_MANGLE_PTR(mm_block->next_free_block);
+
+ ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
+
+ if (EXPECTED(prev == mm_block)) {
+ zend_mm_free_block **rp, **cp;
+
++#if SUHOSIN_PATCH
++ if (next != mm_block) {
++ zend_suhosin_log(S_MEMORY, "zend_mm_heap corrupted at %p", mm_block);
++ _exit(1);
++ }
++#endif
+ #if ZEND_MM_SAFE_UNLINKING
+ if (UNEXPECTED(next != mm_block)) {
+ zend_mm_panic("zend_mm_heap corrupted");
+@@ -841,14 +924,21 @@
+ }
+ } else {
+
++#if SUHOSIN_PATCH
++ if (SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block || SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block) {
++ zend_suhosin_log(S_MEMORY, "zend_mm_head corrupted at %p", mm_block);
++ _exit(1);
++ }
++#endif
++
+ #if ZEND_MM_SAFE_UNLINKING
+- if (UNEXPECTED(prev->next_free_block != mm_block) || UNEXPECTED(next->prev_free_block != mm_block)) {
++ if (UNEXPECTED(SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block) || UNEXPECTED(SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block)) {
+ zend_mm_panic("zend_mm_heap corrupted");
+ }
+ #endif
+
+- prev->next_free_block = next;
+- next->prev_free_block = prev;
++ prev->next_free_block = SUHOSIN_MANGLE_PTR(next);
++ next->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
+
+ if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
+ if (EXPECTED(prev == next)) {
+@@ -864,7 +954,7 @@
+ }
+ }
+
+-static inline void zend_mm_init(zend_mm_heap *heap)
++static void zend_mm_init(zend_mm_heap *heap)
+ {
+ zend_mm_free_block* p;
+ int i;
+@@ -882,12 +972,19 @@
+ #endif
+ p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
+- p->next_free_block = p;
+- p->prev_free_block = p;
++ p->next_free_block = SUHOSIN_MANGLE_PTR(p);
++ p->prev_free_block = SUHOSIN_MANGLE_PTR(p);
+ p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
+ heap->large_free_buckets[i] = NULL;
+ }
+- heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap);
++ heap->rest_buckets[0] = heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(heap));
++#if SUHOSIN_PATCH
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
++ zend_canary(&heap->canary_1, sizeof(heap->canary_1));
++ zend_canary(&heap->canary_2, sizeof(heap->canary_2));
++ zend_canary(&heap->canary_3, sizeof(heap->canary_3));
++ }
++#endif
+ }
+
+ static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment)
+@@ -908,12 +1005,13 @@
+ int i;
+
+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
++ /* NULL means NULL even MANGLED */
+ if (heap->cache[i]) {
+- zend_mm_free_block *mm_block = heap->cache[i];
++ zend_mm_free_block *mm_block = SUHOSIN_MANGLE_PTR(heap->cache[i]);
+
+ while (mm_block) {
+ size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
+- zend_mm_free_block *q = mm_block->prev_free_block;
++ zend_mm_free_block *q = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
+ zend_mm_block *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
+
+ heap->cached -= size;
+@@ -1009,14 +1107,20 @@
+ /* }}} */
+ #endif
+
++
+ /* Notes:
+ * - This function may alter the block_sizes values to match platform alignment
+ * - This function does *not* perform sanity checks on the arguments
+ */
+-ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++zend_mm_heap *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
++#else
++static zend_mm_heap *__zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
++#endif
+ {
+ zend_mm_storage *storage;
+ zend_mm_heap *heap;
++ zend_mm_free_block *tmp;
+
+ #if 0
+ int i;
+@@ -1050,6 +1154,12 @@
+ }
+ #endif
+
++ /* get the pointer guardian and ensure low 3 bits are 1 */
++ if (SUHOSIN_POINTER_GUARD == 0) {
++ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
++ SUHOSIN_POINTER_GUARD |= 7;
++ }
++
+ if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
+ fprintf(stderr, "'block_size' must be a power of two\n");
+ /* See http://support.microsoft.com/kb/190351 */
+@@ -1097,12 +1207,12 @@
+ heap->reserve = NULL;
+ heap->reserve_size = reserve_size;
+ if (reserve_size > 0) {
+- heap->reserve = _zend_mm_alloc_int(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++ heap->reserve = _zend_mm_alloc(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
+ }
+ if (internal) {
+ int i;
+ zend_mm_free_block *p, *q, *orig;
+- zend_mm_heap *mm_heap = _zend_mm_alloc_int(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++ zend_mm_heap *mm_heap = _zend_mm_alloc(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
+
+ *mm_heap = *heap;
+
+@@ -1110,22 +1220,22 @@
+ orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
+ q = p;
+- while (q->prev_free_block != orig) {
+- q = q->prev_free_block;
++ while (SUHOSIN_MANGLE_PTR(q->prev_free_block) != orig) {
++ q = SUHOSIN_MANGLE_PTR(q->prev_free_block);
+ }
+- q->prev_free_block = p;
++ q->prev_free_block = SUHOSIN_MANGLE_PTR(p);
+ q = p;
+- while (q->next_free_block != orig) {
+- q = q->next_free_block;
++ while (SUHOSIN_MANGLE_PTR(q->next_free_block) != orig) {
++ q = SUHOSIN_MANGLE_PTR(q->next_free_block);
+ }
+- q->next_free_block = p;
++ q->next_free_block = SUHOSIN_MANGLE_PTR(p);
+ p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
+ orig = (zend_mm_free_block*)((char*)orig + sizeof(zend_mm_free_block*) * 2);
+ if (mm_heap->large_free_buckets[i]) {
+ mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
+ }
+ }
+- mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(mm_heap);
++ mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(mm_heap));
+
+ free(heap);
+ heap = mm_heap;
+@@ -1133,7 +1243,11 @@
+ return heap;
+ }
+
+-ZEND_API zend_mm_heap *zend_mm_startup(void)
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++zend_mm_heap *__zend_mm_startup_canary(void)
++#else
++static zend_mm_heap *__zend_mm_startup(void)
++#endif
+ {
+ int i;
+ size_t seg_size;
+@@ -1203,6 +1317,27 @@
+ return heap;
+ }
+
++#ifndef SUHOSIN_MM_CLONE_FILE
++zend_mm_heap_canary *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params);
++zend_mm_heap_canary *__zend_mm_startup_canary(void);
++
++ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
++{
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
++ return (zend_mm_heap *)__zend_mm_startup_canary_ex(handlers, block_size, reserve_size, internal, params);
++ }
++ return __zend_mm_startup_ex(handlers, block_size, reserve_size, internal, params);
++}
++ZEND_API zend_mm_heap *zend_mm_startup(void)
++{
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
++ return (zend_mm_heap *)__zend_mm_startup_canary();
++ }
++ return __zend_mm_startup();
++}
++
++#endif
++
+ #if ZEND_DEBUG
+ static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block *b)
+ {
+@@ -1571,7 +1706,11 @@
+ }
+ #endif
+
+-ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++void __zend_mm_shutdown_canary(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
++#else
++static void __zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
++#endif
+ {
+ zend_mm_storage *storage;
+ zend_mm_segment *segment;
+@@ -1581,7 +1720,7 @@
+ if (heap->reserve) {
+ #if ZEND_DEBUG
+ if (!silent) {
+- _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++ _zend_mm_free(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
+ }
+ #endif
+ heap->reserve = NULL;
+@@ -1664,12 +1803,23 @@
+ heap->size = 0;
+ heap->peak = 0;
+ if (heap->reserve_size) {
+- heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++ heap->reserve = _zend_mm_alloc(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
+ }
+ heap->overflow = 0;
+ }
+ }
+
++#ifndef SUHOSIN_MM_CLONE_FILE
++ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
++{
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
++ __zend_mm_shutdown_canary(heap, full_shutdown, silent TSRMLS_CC);
++ return;
++ }
++ __zend_mm_shutdown(heap, full_shutdown, silent TSRMLS_CC);
++}
++#endif
++
+ static void zend_mm_safe_error(zend_mm_heap *heap,
+ const char *format,
+ size_t limit,
+@@ -1680,7 +1830,11 @@
+ size_t size)
+ {
+ if (heap->reserve) {
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++ _zend_mm_free_canary_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++#else
+ _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++#endif
+ heap->reserve = NULL;
+ }
+ if (heap->overflow == 0) {
+@@ -1755,7 +1909,7 @@
+ p = heap->large_free_buckets[index];
+ for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
+ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
+- return p->next_free_block;
++ return SUHOSIN_MANGLE_PTR(p->next_free_block);
+ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
+ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
+@@ -1779,7 +1933,7 @@
+
+ for (p = rst; p; p = p->child[p->child[0] != NULL]) {
+ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
+- return p->next_free_block;
++ return SUHOSIN_MANGLE_PTR(p->next_free_block);
+ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
+ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
+@@ -1788,7 +1942,7 @@
+ }
+
+ if (best_fit) {
+- return best_fit->next_free_block;
++ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
+ }
+ bitmap = bitmap >> 1;
+ if (!bitmap) {
+@@ -1804,9 +1958,12 @@
+ best_fit = p;
+ }
+ }
+- return best_fit->next_free_block;
++ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
+ }
+
++#if SUHOSIN_PATCH
++void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
++#endif
+ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ {
+ zend_mm_free_block *best_fit;
+@@ -1816,7 +1973,7 @@
+ size_t segment_size;
+ zend_mm_segment *segment;
+ int keep_rest = 0;
+-
++
+ if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
+ size_t index = ZEND_MM_BUCKET_INDEX(true_size);
+ size_t bitmap;
+@@ -1831,9 +1988,14 @@
+ heap->cache_stat[index].count--;
+ heap->cache_stat[index].hit++;
+ #endif
+- best_fit = heap->cache[index];
++ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
+ heap->cache[index] = best_fit->prev_free_block;
+ heap->cached -= true_size;
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(best_fit);
++ ((zend_mm_block*)best_fit)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(best_fit);
++#endif
+ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
+ return ZEND_MM_DATA_OF(best_fit);
+@@ -1847,7 +2009,7 @@
+ if (bitmap) {
+ /* Found some "small" free block that can be used */
+ index += zend_mm_low_bit(bitmap);
+- best_fit = heap->free_buckets[index*2];
++ best_fit = SUHOSIN_MANGLE_PTR(heap->free_buckets[index*2]);
+ #if ZEND_MM_CACHE_STAT
+ heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
+ #endif
+@@ -1862,7 +2024,7 @@
+ best_fit = zend_mm_search_large_block(heap, true_size);
+
+ if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
+- zend_mm_free_block *p = heap->rest_buckets[0];
++ zend_mm_free_block *p = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
+ size_t best_size = -1;
+
+ while (p != ZEND_MM_REST_BUCKET(heap)) {
+@@ -1874,7 +2036,7 @@
+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
+ best_fit = p;
+ }
+- p = p->prev_free_block;
++ p = SUHOSIN_MANGLE_PTR(p->prev_free_block);
+ }
+ }
+
+@@ -1973,13 +2135,19 @@
+
+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
+
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(best_fit);
++ ((zend_mm_block*)best_fit)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(best_fit);
++#endif
++
+ heap->size += true_size;
+ if (heap->peak < heap->size) {
+ heap->peak = heap->size;
+ }
+
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+-
++
+ return ZEND_MM_DATA_OF(best_fit);
+ }
+
+@@ -1996,19 +2164,26 @@
+
+ mm_block = ZEND_MM_HEADER_OF(p);
+ size = ZEND_MM_BLOCK_SIZE(mm_block);
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_CHECK_CANARIES(mm_block, "efree()");
++#endif
+ ZEND_MM_CHECK_PROTECTION(mm_block);
+
+ #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
+ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
+ #endif
+-
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_DESTROY_FREE_MEMORY))) {
++ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->info.size);
++ }
++#endif
+ #if ZEND_MM_CACHE
+ if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
+ size_t index = ZEND_MM_BUCKET_INDEX(size);
+ zend_mm_free_block **cache = &heap->cache[index];
+
+ ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
+- *cache = (zend_mm_free_block*)mm_block;
++ *cache = (zend_mm_free_block*)SUHOSIN_MANGLE_PTR(mm_block);
+ heap->cached += size;
+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
+ #if ZEND_MM_CACHE_STAT
+@@ -2044,6 +2219,9 @@
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ }
+
++#if SUHOSIN_PATCH
++void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
++#endif
+ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ {
+ zend_mm_block *mm_block = ZEND_MM_HEADER_OF(p);
+@@ -2053,11 +2231,18 @@
+ void *ptr;
+
+ if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
++#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
++ return _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#else
+ return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ }
+ mm_block = ZEND_MM_HEADER_OF(p);
+ true_size = ZEND_MM_TRUE_SIZE(size);
+ orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_CHECK_CANARIES(mm_block, "erealloc()");
++#endif
+ ZEND_MM_CHECK_PROTECTION(mm_block);
+
+ if (UNEXPECTED(true_size < size)) {
+@@ -2089,6 +2274,11 @@
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ }
+ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(mm_block);
++ ((zend_mm_block*)mm_block)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(mm_block);
++#endif
+ return p;
+ }
+
+@@ -2104,17 +2294,22 @@
+ heap->cache_stat[index].count--;
+ heap->cache_stat[index].hit++;
+ #endif
+- best_fit = heap->cache[index];
++ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
+ heap->cache[index] = best_fit->prev_free_block;
+ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
+- ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
+-
++ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(best_fit);
++ ((zend_mm_block*)best_fit)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(best_fit);
++#endif
++
+ ptr = ZEND_MM_DATA_OF(best_fit);
+
+ #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
+ memcpy(ptr, p, mm_block->debug.size);
+ #else
+- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
++ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
+ #endif
+
+ heap->cached -= true_size - orig_size;
+@@ -2123,14 +2318,13 @@
+ cache = &heap->cache[index];
+
+ ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
+- *cache = (zend_mm_free_block*)mm_block;
++ *cache = (zend_mm_free_block*)SUHOSIN_MANGLE_PTR(mm_block);
+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
+ #if ZEND_MM_CACHE_STAT
+ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
+ heap->cache_stat[index].max_count = heap->cache_stat[index].count;
+ }
+ #endif
+-
+ return ptr;
+ }
+ }
+@@ -2173,6 +2367,11 @@
+ heap->peak = heap->size;
+ }
+ HANDLE_UNBLOCK_INTERRUPTIONS();
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(mm_block);
++ ((zend_mm_block*)mm_block)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(mm_block);
++#endif
+ return p;
+ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
+@@ -2275,38 +2474,90 @@
+ }
+
+ HANDLE_UNBLOCK_INTERRUPTIONS();
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(mm_block);
++ ((zend_mm_block*)mm_block)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(mm_block);
++#endif
+ return ZEND_MM_DATA_OF(mm_block);
+ }
+
++#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
++ ptr = _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#else
+ ptr = _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
+ memcpy(ptr, p, mm_block->debug.size);
+ #else
+- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
++ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
+ #endif
++#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
++ _zend_mm_free_canary_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#else
+ _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ return ptr;
+ }
+
++#ifndef SUHOSIN_MM_CLONE_FILE
+ ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ {
+- return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
++#endif
++ return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ return _zend_mm_alloc_canary_int((zend_mm_heap_canary *)heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ }
+
+ ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ {
+- _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
++#endif
++ { _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; }
++#if SUHOSIN_PATCH
++ _zend_mm_free_canary_int((zend_mm_heap_canary *)heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ }
+
+ ZEND_API void *_zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ {
+- return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
++#endif
++ return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ return _zend_mm_realloc_canary_int((zend_mm_heap_canary *)heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ }
+
+ ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ {
+ zend_mm_block *mm_block;
+
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) != 0) {
++ return _zend_mm_block_size_canary((zend_mm_heap_canary *)heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++
++ if (!ZEND_MM_VALID_PTR(p)) {
++ return 0;
++ }
++ mm_block = ZEND_MM_HEADER_OF(p);
++ ZEND_MM_CHECK_PROTECTION(mm_block);
++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
++ return mm_block->debug.size;
++#else
++ return ZEND_MM_BLOCK_SIZE(mm_block);
++#endif
++}
++#else
++ZEND_API size_t _zend_mm_block_size_canary(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
++{
++ zend_mm_block *mm_block;
++
+ if (!ZEND_MM_VALID_PTR(p)) {
+ return 0;
+ }
+@@ -2319,6 +2570,8 @@
+ #endif
+ }
+
++#endif
++
+ /**********************/
+ /* Allocation Manager */
+ /**********************/
+@@ -2335,6 +2588,7 @@
+ static zend_alloc_globals alloc_globals;
+ #endif
+
++#ifndef SUHOSIN_MM_CLONE_FILE
+ ZEND_API int is_zend_mm(TSRMLS_D)
+ {
+ return AG(mm_heap)->use_zend_alloc;
+@@ -2347,7 +2601,13 @@
+ if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
+ return AG(mm_heap)->_malloc(size);
+ }
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
++#endif
+ return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ return _zend_mm_alloc_canary_int((zend_mm_heap_canary *)AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ }
+
+ ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+@@ -2358,7 +2618,13 @@
+ AG(mm_heap)->_free(ptr);
+ return;
+ }
+- _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
++#endif
++ { _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; }
++#if SUHOSIN_PATCH
++ _zend_mm_free_canary_int((zend_mm_heap_canary *)AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ }
+
+ ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+@@ -2368,7 +2634,13 @@
+ if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
+ return AG(mm_heap)->_realloc(ptr, size);
+ }
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
++#endif
+ return _zend_mm_realloc_int(AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ return _zend_mm_realloc_canary_int((zend_mm_heap_canary *)AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ }
+
+ ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+@@ -2376,8 +2648,15 @@
+ if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
+ return 0;
+ }
+- return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
++#endif
++ return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if SUHOSIN_PATCH
++ return _zend_mm_block_size_canary((zend_mm_heap_canary *)AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#endif
+ }
++#endif
+
+ #if defined(__GNUC__) && defined(i386)
+
+@@ -2448,7 +2727,7 @@
+ }
+ #endif
+
+-
++#ifndef SUHOSIN_MM_CLONE_FILE
+ ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+ {
+ return emalloc_rel(safe_address(nmemb, size, offset));
+@@ -2561,6 +2840,7 @@
+ {
+ zend_mm_shutdown(AG(mm_heap), full_shutdown, silent TSRMLS_CC);
+ }
++#endif
+
+ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC)
+ {
+@@ -2585,6 +2865,7 @@
+ }
+ #endif
+
++#ifndef SUHOSIN_MM_CLONE_FILE
+ ZEND_API void start_memory_manager(TSRMLS_D)
+ {
+ #ifdef ZTS
+@@ -2649,6 +2930,7 @@
+ zend_debug_alloc_output("------------------------------------------------\n");
+ }
+ #endif
++#endif
+
+ /*
+ * Local variables:
+diff -Nura php-5.3.6/Zend/zend_alloc_canary.c suhosin-patch-5.3.6-0.9.10/Zend/zend_alloc_canary.c
+--- php-5.3.6/Zend/zend_alloc_canary.c 1970-01-01 01:00:00.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_alloc_canary.c 2011-03-19 10:48:33.797308698 +0100
+@@ -0,0 +1,2498 @@
++/*
++ +----------------------------------------------------------------------+
++ | Suhosin-Patch for PHP |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 2004-2010 Stefan Esser |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 2.02 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available at through the world-wide-web at |
++ | http://www.php.net/license/2_02.txt. |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
++ +----------------------------------------------------------------------+
++ */
++/* $Id: zend_alloc_canary.c, $ */
++
++#include "zend.h"
++#include "zend_alloc.h"
++#include "zend_globals.h"
++#include "zend_operators.h"
++
++#ifdef HAVE_SIGNAL_H
++# include <signal.h>
++#endif
++#ifdef HAVE_UNISTD_H
++# include <unistd.h>
++#endif
++
++#if SUHOSIN_PATCH
++#include "suhosin_patch.h"
++#endif
++
++#ifdef ZEND_WIN32
++# include <wincrypt.h>
++# include <process.h>
++#endif
++
++#ifndef ZEND_MM_HEAP_PROTECTION
++# define ZEND_MM_HEAP_PROTECTION ZEND_DEBUG
++#endif
++
++#ifndef ZEND_MM_SAFE_UNLINKING
++# define ZEND_MM_SAFE_UNLINKING 1
++#endif
++
++#ifndef ZEND_MM_COOKIES
++# define ZEND_MM_COOKIES ZEND_DEBUG
++#endif
++
++#ifdef _WIN64
++# define PTR_FMT "0x%0.16I64x"
++/*
++#elif sizeof(long) == 8
++# define PTR_FMT "0x%0.16lx"
++*/
++#else
++# define PTR_FMT "0x%0.8lx"
++#endif
++
++#define SUHOSIN_MM_WITH_CANARY_PROTECTION 1
++
++#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
++static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
++#endif
++
++static void zend_mm_panic(const char *message)
++{
++ fprintf(stderr, "%s\n", message);
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
++#endif
++#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
++ kill(getpid(), SIGSEGV);
++#endif
++ exit(1);
++}
++
++/*******************/
++/* Storage Manager */
++/*******************/
++
++#ifdef ZEND_WIN32
++# define HAVE_MEM_WIN32 /* use VirtualAlloc() to allocate memory */
++#endif
++#define HAVE_MEM_MALLOC /* use malloc() to allocate segments */
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#if HAVE_LIMITS_H
++#include <limits.h>
++#endif
++#include <fcntl.h>
++#include <errno.h>
++
++#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
++# ifdef HAVE_MREMAP
++# ifndef _GNU_SOURCE
++# define _GNU_SOURCE
++# endif
++# ifndef __USE_GNU
++# define __USE_GNU
++# endif
++# endif
++# include <sys/mman.h>
++# ifndef MAP_ANON
++# ifdef MAP_ANONYMOUS
++# define MAP_ANON MAP_ANONYMOUS
++# endif
++# endif
++# ifndef MREMAP_MAYMOVE
++# define MREMAP_MAYMOVE 0
++# endif
++# ifndef MAP_FAILED
++# define MAP_FAILED ((void*)-1)
++# endif
++#endif
++
++static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
++
++static zend_mm_storage* zend_mm_mem_dummy_init(void *params)
++{
++ return malloc(sizeof(zend_mm_storage));
++}
++
++static void zend_mm_mem_dummy_dtor(zend_mm_storage *storage)
++{
++ free(storage);
++}
++
++static void zend_mm_mem_dummy_compact(zend_mm_storage *storage)
++{
++}
++
++#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
++
++static zend_mm_segment* zend_mm_mem_mmap_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size)
++{
++ zend_mm_segment *ret;
++#ifdef HAVE_MREMAP
++#if defined(__NetBSD__)
++ /* NetBSD 5 supports mremap but takes an extra newp argument */
++ ret = (zend_mm_segment*)mremap(segment, segment->size, segment, size, MREMAP_MAYMOVE);
++#else
++ ret = (zend_mm_segment*)mremap(segment, segment->size, size, MREMAP_MAYMOVE);
++#endif
++ if (ret == MAP_FAILED) {
++#endif
++ ret = storage->handlers->_alloc(storage, size);
++ if (ret) {
++ memcpy(ret, segment, size > segment->size ? segment->size : size);
++ storage->handlers->_free(storage, segment);
++ }
++#ifdef HAVE_MREMAP
++ }
++#endif
++ return ret;
++}
++
++static void zend_mm_mem_mmap_free(zend_mm_storage *storage, zend_mm_segment* segment)
++{
++ munmap((void*)segment, segment->size);
++}
++
++#endif
++
++#ifdef HAVE_MEM_MMAP_ANON
++
++static zend_mm_segment* zend_mm_mem_mmap_anon_alloc(zend_mm_storage *storage, size_t size)
++{
++ zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
++ if (ret == MAP_FAILED) {
++ ret = NULL;
++ }
++ return ret;
++}
++
++# define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
++
++#endif
++
++#ifdef HAVE_MEM_MMAP_ZERO
++
++static int zend_mm_dev_zero_fd = -1;
++
++static zend_mm_storage* zend_mm_mem_mmap_zero_init(void *params)
++{
++ if (zend_mm_dev_zero_fd != -1) {
++ zend_mm_dev_zero_fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
++ }
++ if (zend_mm_dev_zero_fd >= 0) {
++ return malloc(sizeof(zend_mm_storage));
++ } else {
++ return NULL;
++ }
++}
++
++static void zend_mm_mem_mmap_zero_dtor(zend_mm_storage *storage)
++{
++ close(zend_mm_dev_zero_fd);
++ free(storage);
++}
++
++static zend_mm_segment* zend_mm_mem_mmap_zero_alloc(zend_mm_storage *storage, size_t size)
++{
++ zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zend_mm_dev_zero_fd, 0);
++ if (ret == MAP_FAILED) {
++ ret = NULL;
++ }
++ return ret;
++}
++
++# define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
++
++#endif
++
++#ifdef HAVE_MEM_WIN32
++
++static zend_mm_storage* zend_mm_mem_win32_init(void *params)
++{
++ HANDLE heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
++ zend_mm_storage* storage;
++
++ if (heap == NULL) {
++ return NULL;
++ }
++ storage = (zend_mm_storage*)malloc(sizeof(zend_mm_storage));
++ storage->data = (void*) heap;
++ return storage;
++}
++
++static void zend_mm_mem_win32_dtor(zend_mm_storage *storage)
++{
++ HeapDestroy((HANDLE)storage->data);
++ free(storage);
++}
++
++static void zend_mm_mem_win32_compact(zend_mm_storage *storage)
++{
++ HeapDestroy((HANDLE)storage->data);
++ storage->data = (void*)HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
++}
++
++static zend_mm_segment* zend_mm_mem_win32_alloc(zend_mm_storage *storage, size_t size)
++{
++ return (zend_mm_segment*) HeapAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, size);
++}
++
++static void zend_mm_mem_win32_free(zend_mm_storage *storage, zend_mm_segment* segment)
++{
++ HeapFree((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment);
++}
++
++static zend_mm_segment* zend_mm_mem_win32_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size)
++{
++ return (zend_mm_segment*) HeapReAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment, size);
++}
++
++# define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free}
++
++#endif
++
++#ifdef HAVE_MEM_MALLOC
++
++static zend_mm_segment* zend_mm_mem_malloc_alloc(zend_mm_storage *storage, size_t size)
++{
++ return (zend_mm_segment*)malloc(size);
++}
++
++static zend_mm_segment* zend_mm_mem_malloc_realloc(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size)
++{
++ return (zend_mm_segment*)realloc(ptr, size);
++}
++
++static void zend_mm_mem_malloc_free(zend_mm_storage *storage, zend_mm_segment *ptr)
++{
++ free(ptr);
++}
++
++# define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free}
++
++#endif
++
++static const zend_mm_mem_handlers mem_handlers[] = {
++#ifdef HAVE_MEM_WIN32
++ ZEND_MM_MEM_WIN32_DSC,
++#endif
++#ifdef HAVE_MEM_MALLOC
++ ZEND_MM_MEM_MALLOC_DSC,
++#endif
++#ifdef HAVE_MEM_MMAP_ANON
++ ZEND_MM_MEM_MMAP_ANON_DSC,
++#endif
++#ifdef HAVE_MEM_MMAP_ZERO
++ ZEND_MM_MEM_MMAP_ZERO_DSC,
++#endif
++ {NULL, NULL, NULL, NULL, NULL, NULL}
++};
++
++# define ZEND_MM_STORAGE_DTOR() heap->storage->handlers->dtor(heap->storage)
++# define ZEND_MM_STORAGE_ALLOC(size) heap->storage->handlers->_alloc(heap->storage, size)
++# define ZEND_MM_STORAGE_REALLOC(ptr, size) heap->storage->handlers->_realloc(heap->storage, ptr, size)
++# define ZEND_MM_STORAGE_FREE(ptr) heap->storage->handlers->_free(heap->storage, ptr)
++
++/****************/
++/* Heap Manager */
++/****************/
++
++#define MEM_BLOCK_VALID 0x7312F8DC
++#define MEM_BLOCK_FREED 0x99954317
++#define MEM_BLOCK_CACHED 0xFB8277DC
++#define MEM_BLOCK_GUARD 0x2A8FCC84
++#define MEM_BLOCK_LEAK 0x6C5E8F2D
++
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++# define CANARY_SIZE sizeof(size_t)
++#else
++# define CANARY_SIZE 0
++#endif
++
++/* mm block type */
++typedef struct _zend_mm_block_info_canary {
++#if ZEND_MM_COOKIES
++ size_t _cookie;
++#endif
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++ size_t canary_1;
++#endif
++ size_t _size;
++ size_t _prev;
++#if SUHOSIN_PATCH
++ size_t size;
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++ size_t canary_2;
++#endif
++#endif
++} zend_mm_block_info_canary;
++
++#if ZEND_DEBUG
++
++typedef struct _zend_mm_debug_info_canary {
++ char *filename;
++ uint lineno;
++ char *orig_filename;
++ uint orig_lineno;
++ size_t size;
++#if ZEND_MM_HEAP_PROTECTION
++ unsigned int start_magic;
++#endif
++} zend_mm_debug_info_canary;
++
++#elif ZEND_MM_HEAP_PROTECTION
++
++typedef struct _zend_mm_debug_info_canary {
++ size_t size;
++ unsigned int start_magic;
++} zend_mm_debug_info_canary;
++
++#endif
++
++typedef struct _zend_mm_block_canary {
++ zend_mm_block_info_canary info;
++#if ZEND_DEBUG
++ unsigned int magic;
++# ifdef ZTS
++ THREAD_T thread_id;
++# endif
++ zend_mm_debug_info_canary debug;
++#elif ZEND_MM_HEAP_PROTECTION
++ zend_mm_debug_info_canary debug;
++#endif
++} zend_mm_block_canary;
++
++typedef struct _zend_mm_small_free_block_canary {
++ zend_mm_block_info_canary info;
++#if ZEND_DEBUG
++ unsigned int magic;
++# ifdef ZTS
++ THREAD_T thread_id;
++# endif
++#endif
++ struct _zend_mm_free_block_canary *prev_free_block;
++ struct _zend_mm_free_block_canary *next_free_block;
++} zend_mm_small_free_block_canary;
++
++typedef struct _zend_mm_free_block_canary {
++ zend_mm_block_info_canary info;
++#if ZEND_DEBUG
++ unsigned int magic;
++# ifdef ZTS
++ THREAD_T thread_id;
++# endif
++#endif
++ struct _zend_mm_free_block_canary *prev_free_block;
++ struct _zend_mm_free_block_canary *next_free_block;
++
++ struct _zend_mm_free_block_canary **parent;
++ struct _zend_mm_free_block_canary *child[2];
++} zend_mm_free_block_canary;
++
++#define ZEND_MM_NUM_BUCKETS (sizeof(size_t) << 3)
++
++#define ZEND_MM_CACHE 1
++#define ZEND_MM_CACHE_SIZE (ZEND_MM_NUM_BUCKETS * 4 * 1024)
++
++#ifndef ZEND_MM_CACHE_STAT
++# define ZEND_MM_CACHE_STAT 0
++#endif
++
++typedef struct _zend_mm_heap_canary {
++ int use_zend_alloc;
++ void *(*_malloc)(size_t);
++ void (*_free)(void*);
++ void *(*_realloc)(void*, size_t);
++ size_t free_bitmap;
++ size_t large_free_bitmap;
++ size_t block_size;
++ size_t compact_size;
++ zend_mm_segment *segments_list;
++ zend_mm_storage *storage;
++ size_t real_size;
++ size_t real_peak;
++ size_t limit;
++ size_t size;
++ size_t peak;
++ size_t reserve_size;
++ void *reserve;
++ int overflow;
++ int internal;
++#if ZEND_MM_CACHE
++ unsigned int cached;
++ zend_mm_free_block_canary *cache[ZEND_MM_NUM_BUCKETS];
++#endif
++ zend_mm_free_block_canary *free_buckets[ZEND_MM_NUM_BUCKETS*2];
++ zend_mm_free_block_canary *large_free_buckets[ZEND_MM_NUM_BUCKETS];
++ zend_mm_free_block_canary *rest_buckets[2];
++#if ZEND_MM_CACHE_STAT
++ struct {
++ int count;
++ int max_count;
++ int hit;
++ int miss;
++ } cache_stat[ZEND_MM_NUM_BUCKETS+1];
++#endif
++#if SUHOSIN_PATCH
++ size_t canary_1,canary_2,canary_3;
++#endif
++};
++
++#define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
++ (zend_mm_free_block_canary*) ((char*)&heap->free_buckets[index * 2] + \
++ sizeof(zend_mm_free_block_canary*) * 2 - \
++ sizeof(zend_mm_small_free_block_canary))
++
++#define ZEND_MM_REST_BUCKET(heap) \
++ (zend_mm_free_block_canary*)((char*)&heap->rest_buckets[0] + \
++ sizeof(zend_mm_free_block_canary*) * 2 - \
++ sizeof(zend_mm_small_free_block_canary))
++
++#if ZEND_MM_COOKIES
++
++static unsigned int _zend_mm_cookie = 0;
++
++# define ZEND_MM_COOKIE(block) \
++ (((size_t)(block)) ^ _zend_mm_cookie)
++# define ZEND_MM_SET_COOKIE(block) \
++ (block)->info._cookie = ZEND_MM_COOKIE(block)
++# define ZEND_MM_CHECK_COOKIE(block) \
++ if (UNEXPECTED((block)->info._cookie != ZEND_MM_COOKIE(block))) { \
++ zend_mm_panic("zend_mm_heap corrupted"); \
++ }
++#else
++# define ZEND_MM_SET_COOKIE(block)
++# define ZEND_MM_CHECK_COOKIE(block)
++#endif
++
++/* Default memory segment size */
++#define ZEND_MM_SEG_SIZE (256 * 1024)
++
++/* Reserved space for error reporting in case of memory overflow */
++#define ZEND_MM_RESERVE_SIZE (8*1024)
++
++#ifdef _WIN64
++# define ZEND_MM_LONG_CONST(x) (x##i64)
++#else
++# define ZEND_MM_LONG_CONST(x) (x##L)
++#endif
++
++#define ZEND_MM_TYPE_MASK ZEND_MM_LONG_CONST(0x3)
++
++#define ZEND_MM_FREE_BLOCK ZEND_MM_LONG_CONST(0x0)
++#define ZEND_MM_USED_BLOCK ZEND_MM_LONG_CONST(0x1)
++#define ZEND_MM_GUARD_BLOCK ZEND_MM_LONG_CONST(0x3)
++
++#define ZEND_MM_BLOCK(b, type, size) do { \
++ size_t _size = (size); \
++ (b)->info._size = (type) | _size; \
++ ZEND_MM_BLOCK_AT(b, _size)->info._prev = (type) | _size; \
++ ZEND_MM_SET_COOKIE(b); \
++ } while (0);
++#define ZEND_MM_LAST_BLOCK(b) do { \
++ (b)->info._size = ZEND_MM_GUARD_BLOCK | ZEND_MM_ALIGNED_HEADER_SIZE; \
++ ZEND_MM_SET_MAGIC(b, MEM_BLOCK_GUARD); \
++ } while (0);
++#define ZEND_MM_BLOCK_SIZE(b) ((b)->info._size & ~ZEND_MM_TYPE_MASK)
++#define ZEND_MM_IS_FREE_BLOCK(b) (!((b)->info._size & ZEND_MM_USED_BLOCK))
++#define ZEND_MM_IS_USED_BLOCK(b) ((b)->info._size & ZEND_MM_USED_BLOCK)
++#define ZEND_MM_IS_GUARD_BLOCK(b) (((b)->info._size & ZEND_MM_TYPE_MASK) == ZEND_MM_GUARD_BLOCK)
++
++#define ZEND_MM_NEXT_BLOCK(b) ZEND_MM_BLOCK_AT(b, ZEND_MM_BLOCK_SIZE(b))
++#define ZEND_MM_PREV_BLOCK(b) ZEND_MM_BLOCK_AT(b, -(int)((b)->info._prev & ~ZEND_MM_TYPE_MASK))
++
++#define ZEND_MM_PREV_BLOCK_IS_FREE(b) (!((b)->info._prev & ZEND_MM_USED_BLOCK))
++
++#define ZEND_MM_MARK_FIRST_BLOCK(b) ((b)->info._prev = ZEND_MM_GUARD_BLOCK)
++#define ZEND_MM_IS_FIRST_BLOCK(b) ((b)->info._prev == ZEND_MM_GUARD_BLOCK)
++
++/* optimized access */
++#define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size
++
++#ifndef ZEND_MM_ALIGNMENT
++# define ZEND_MM_ALIGNMENT 8
++# define ZEND_MM_ALIGNMENT_LOG2 3
++#elif ZEND_MM_ALIGNMENT < 4
++# undef ZEND_MM_ALIGNMENT
++# undef ZEND_MM_ALIGNMENT_LOG2
++# define ZEND_MM_ALIGNMENT 4
++# define ZEND_MM_ALIGNMENT_LOG2 2
++#endif
++
++#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1)
++
++/* Aligned header size */
++#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK)
++#define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block_canary))
++#define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block_canary))
++#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE + CANARY_SIZE)
++#define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE)
++#define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
++
++#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)):0)
++
++#define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<<ZEND_MM_ALIGNMENT_LOG2)+ZEND_MM_ALIGNED_MIN_HEADER_SIZE)
++
++#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)))
++
++#define ZEND_MM_BUCKET_INDEX(true_size) ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))
++
++#define ZEND_MM_SMALL_SIZE(true_size) (true_size < ZEND_MM_MAX_SMALL_SIZE)
++
++/* Memory calculations */
++#define ZEND_MM_BLOCK_AT(blk, offset) ((zend_mm_block_canary *) (((char *) (blk))+(offset)))
++#define ZEND_MM_DATA_OF(p) ((void *) (((char *) (p))+ZEND_MM_ALIGNED_HEADER_SIZE))
++#define ZEND_MM_HEADER_OF(blk) ZEND_MM_BLOCK_AT(blk, -(int)ZEND_MM_ALIGNED_HEADER_SIZE)
++
++/* Debug output */
++#if ZEND_DEBUG
++
++# ifdef ZTS
++# define ZEND_MM_SET_THREAD_ID(block) \
++ ((zend_mm_block_canary*)(block))->thread_id = tsrm_thread_id()
++# define ZEND_MM_BAD_THREAD_ID(block) ((block)->thread_id != tsrm_thread_id())
++# else
++# define ZEND_MM_SET_THREAD_ID(block)
++# define ZEND_MM_BAD_THREAD_ID(block) 0
++# endif
++
++# define ZEND_MM_VALID_PTR(block) \
++ zend_mm_check_ptr(heap, block, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)
++
++# define ZEND_MM_SET_MAGIC(block, val) do { \
++ (block)->magic = (val); \
++ } while (0)
++
++# define ZEND_MM_CHECK_MAGIC(block, val) do { \
++ if ((block)->magic != (val)) { \
++ zend_mm_panic("zend_mm_heap corrupted"); \
++ } \
++ } while (0)
++
++# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) do { \
++ ((zend_mm_block_canary*)(block))->debug.filename = __zend_filename; \
++ ((zend_mm_block_canary*)(block))->debug.lineno = __zend_lineno; \
++ ((zend_mm_block_canary*)(block))->debug.orig_filename = __zend_orig_filename; \
++ ((zend_mm_block_canary*)(block))->debug.orig_lineno = __zend_orig_lineno; \
++ ZEND_MM_SET_BLOCK_SIZE(block, __size); \
++ if (set_valid) { \
++ ZEND_MM_SET_MAGIC(block, MEM_BLOCK_VALID); \
++ } \
++ if (set_thread) { \
++ ZEND_MM_SET_THREAD_ID(block); \
++ } \
++ } while (0)
++
++#else
++
++# define ZEND_MM_VALID_PTR(ptr) EXPECTED(ptr != NULL)
++
++# define ZEND_MM_SET_MAGIC(block, val)
++
++# define ZEND_MM_CHECK_MAGIC(block, val)
++
++# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) ZEND_MM_SET_BLOCK_SIZE(block, __size)
++
++#endif
++
++#if SUHOSIN_MM_WITH_CANARY_PROTECTION
++
++# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) do { \
++ char *p = SUHOSIN_MM_END_CANARY_PTR(block); size_t check; \
++ if (((block)->info.canary_1 != heap->canary_1) || ((block)->info.canary_2 != heap->canary_2)) { \
++ canary_mismatch: \
++ zend_suhosin_log(S_MEMORY, "canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { (block)->info.canary_1 = heap->canary_1; (block)->info.canary_2 = heap->canary_2; }\
++ } \
++ memcpy(&check, p, CANARY_SIZE); \
++ if (check != heap->canary_3) { \
++ zend_suhosin_log(S_MEMORY, "end canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { memcpy(p, heap->canary_3, CANARY_SIZE); } \
++ } \
++ } while (0)
++
++# define SUHOSIN_MM_SET_CANARIES(block) do { \
++ (block)->info.canary_1 = heap->canary_1; \
++ (block)->info.canary_2 = heap->canary_2; \
++ } while (0)
++
++# define SUHOSIN_MM_END_CANARY_PTR(block) \
++ (char *)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block_canary*)(block))->info.size + END_MAGIC_SIZE)
++
++# define SUHOSIN_MM_SET_END_CANARY(block) do { \
++ char *p = SUHOSIN_MM_END_CANARY_PTR(block); \
++ memcpy(p, &heap->canary_3, CANARY_SIZE); \
++ } while (0)
++
++#else
++
++# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION)
++# define SUHOSIN_MM_SET_CANARIES(block)
++# define SUHOSIN_MM_END_CANARY_PTR(block)
++# define SUHOSIN_MM_SET_END_CANARY(block)
++
++#endif
++
++
++#if ZEND_MM_HEAP_PROTECTION
++
++# define ZEND_MM_CHECK_PROTECTION(block) \
++ do { \
++ if ((block)->debug.start_magic != _mem_block_start_magic || \
++ memcmp(ZEND_MM_END_MAGIC_PTR(block), &_mem_block_end_magic, END_MAGIC_SIZE) != 0) { \
++ zend_mm_panic("zend_mm_heap corrupted"); \
++ } \
++ } while (0)
++
++# define ZEND_MM_END_MAGIC_PTR(block) \
++ (((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block_canary*)(block))->debug.size)
++
++# define END_MAGIC_SIZE sizeof(unsigned int)
++
++# define ZEND_MM_SET_BLOCK_SIZE(block, __size) do { \
++ char *p; \
++ ((zend_mm_block_canary*)(block))->debug.size = (__size); \
++ p = ZEND_MM_END_MAGIC_PTR(block); \
++ ((zend_mm_block_canary*)(block))->debug.start_magic = _mem_block_start_magic; \
++ memcpy(p, &_mem_block_end_magic, END_MAGIC_SIZE); \
++ } while (0)
++
++static unsigned int _mem_block_start_magic = 0;
++static unsigned int _mem_block_end_magic = 0;
++
++#else
++
++# if ZEND_DEBUG
++# define ZEND_MM_SET_BLOCK_SIZE(block, _size) \
++ ((zend_mm_block_canary*)(block))->debug.size = (_size)
++# else
++# define ZEND_MM_SET_BLOCK_SIZE(block, _size)
++# endif
++
++# define ZEND_MM_CHECK_PROTECTION(block)
++
++# define END_MAGIC_SIZE 0
++
++#endif
++
++#if ZEND_MM_SAFE_UNLINKING
++# define ZEND_MM_CHECK_BLOCK_LINKAGE(block) \
++ if (UNEXPECTED((block)->info._size != ZEND_MM_BLOCK_AT(block, ZEND_MM_FREE_BLOCK_SIZE(block))->info._prev) || \
++ UNEXPECTED(!UNEXPECTED(ZEND_MM_IS_FIRST_BLOCK(block)) && \
++ UNEXPECTED(ZEND_MM_PREV_BLOCK(block)->info._size != (block)->info._prev))) { \
++ zend_mm_panic("zend_mm_heap corrupted"); \
++ }
++#define ZEND_MM_CHECK_TREE(block) \
++ if (UNEXPECTED(*((block)->parent) != (block))) { \
++ zend_mm_panic("zend_mm_heap corrupted"); \
++ }
++#else
++# define ZEND_MM_CHECK_BLOCK_LINKAGE(block)
++# define ZEND_MM_CHECK_TREE(block)
++#endif
++
++#define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S)
++
++void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
++void _zend_mm_free_canary_int(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
++void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
++
++
++static inline unsigned int zend_mm_high_bit(size_t _size)
++{
++#if defined(__GNUC__) && defined(i386)
++ unsigned int n;
++
++ __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size));
++ return n;
++#elif defined(__GNUC__) && defined(__x86_64__)
++ unsigned long n;
++
++ __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm" (_size));
++ return (unsigned int)n;
++#elif defined(_MSC_VER) && defined(_M_IX86)
++ __asm {
++ bsr eax, _size
++ }
++#else
++ unsigned int n = 0;
++ while (_size != 0) {
++ _size = _size >> 1;
++ n++;
++ }
++ return n-1;
++#endif
++}
++
++static inline unsigned int zend_mm_low_bit(size_t _size)
++{
++#if defined(__GNUC__) && defined(i386)
++ unsigned int n;
++
++ __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size));
++ return n;
++#elif defined(__GNUC__) && defined(__x86_64__)
++ unsigned long n;
++
++ __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm" (_size));
++ return (unsigned int)n;
++#elif defined(_MSC_VER) && defined(_M_IX86)
++ __asm {
++ bsf eax, _size
++ }
++#else
++ static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
++ unsigned int n;
++ unsigned int index = 0;
++
++ n = offset[_size & 15];
++ while (n == 4) {
++ _size >>= 4;
++ index += n;
++ n = offset[_size & 15];
++ }
++
++ return index + n;
++#endif
++}
++
++static void zend_mm_add_to_rest_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
++{
++ zend_mm_free_block_canary *prev, *next;
++
++ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
++
++ if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) {
++ mm_block->parent = NULL;
++ }
++
++ prev = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
++ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
++}
++
++static void zend_mm_add_to_free_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
++{
++ size_t size;
++ size_t index;
++
++ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
++
++ size = ZEND_MM_FREE_BLOCK_SIZE(mm_block);
++ if (EXPECTED(!ZEND_MM_SMALL_SIZE(size))) {
++ zend_mm_free_block_canary **p;
++
++ index = ZEND_MM_LARGE_BUCKET_INDEX(size);
++ p = &heap->large_free_buckets[index];
++ mm_block->child[0] = mm_block->child[1] = NULL;
++ if (!*p) {
++ *p = mm_block;
++ mm_block->parent = p;
++ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
++ heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
++ } else {
++ size_t m;
++
++ for (m = size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
++ zend_mm_free_block_canary *prev = *p;
++
++ if (ZEND_MM_FREE_BLOCK_SIZE(prev) != size) {
++ p = &prev->child[(m >> (ZEND_MM_NUM_BUCKETS-1)) & 1];
++ if (!*p) {
++ *p = mm_block;
++ mm_block->parent = p;
++ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
++ break;
++ }
++ } else {
++ zend_mm_free_block_canary *next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
++
++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
++ mm_block->parent = NULL;
++ break;
++ }
++ }
++ }
++ } else {
++ zend_mm_free_block_canary *prev, *next;
++
++ index = ZEND_MM_BUCKET_INDEX(size);
++
++ prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
++ if (SUHOSIN_MANGLE_PTR(prev->prev_free_block) == prev) {
++ heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
++ }
++ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
++
++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
++ }
++}
++
++static void zend_mm_remove_from_free_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
++{
++ zend_mm_free_block_canary *prev = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
++ zend_mm_free_block_canary *next = SUHOSIN_MANGLE_PTR(mm_block->next_free_block);
++
++ ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
++
++ if (EXPECTED(prev == mm_block)) {
++ zend_mm_free_block_canary **rp, **cp;
++
++#if SUHOSIN_PATCH
++ if (next != mm_block) {
++ zend_suhosin_log(S_MEMORY, "zend_mm_heap corrupted at %p", mm_block);
++ _exit(1);
++ }
++#endif
++#if ZEND_MM_SAFE_UNLINKING
++ if (UNEXPECTED(next != mm_block)) {
++ zend_mm_panic("zend_mm_heap corrupted");
++ }
++#endif
++
++ rp = &mm_block->child[mm_block->child[1] != NULL];
++ prev = *rp;
++ if (EXPECTED(prev == NULL)) {
++ size_t index = ZEND_MM_LARGE_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
++
++ ZEND_MM_CHECK_TREE(mm_block);
++ *mm_block->parent = NULL;
++ if (mm_block->parent == &heap->large_free_buckets[index]) {
++ heap->large_free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
++ }
++ } else {
++ while (*(cp = &(prev->child[prev->child[1] != NULL])) != NULL) {
++ prev = *cp;
++ rp = cp;
++ }
++ *rp = NULL;
++
++subst_block:
++ ZEND_MM_CHECK_TREE(mm_block);
++ *mm_block->parent = prev;
++ prev->parent = mm_block->parent;
++ if ((prev->child[0] = mm_block->child[0])) {
++ ZEND_MM_CHECK_TREE(prev->child[0]);
++ prev->child[0]->parent = &prev->child[0];
++ }
++ if ((prev->child[1] = mm_block->child[1])) {
++ ZEND_MM_CHECK_TREE(prev->child[1]);
++ prev->child[1]->parent = &prev->child[1];
++ }
++ }
++ } else {
++
++#if SUHOSIN_PATCH
++ if (SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block || SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block) {
++ zend_suhosin_log(S_MEMORY, "zend_mm_head corrupted at %p", mm_block);
++ _exit(1);
++ }
++#endif
++
++#if ZEND_MM_SAFE_UNLINKING
++ if (UNEXPECTED(SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block) || UNEXPECTED(SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block)) {
++ zend_mm_panic("zend_mm_heap corrupted");
++ }
++#endif
++
++ prev->next_free_block = SUHOSIN_MANGLE_PTR(next);
++ next->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
++
++ if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
++ if (EXPECTED(prev == next)) {
++ size_t index = ZEND_MM_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
++
++ if (EXPECTED(heap->free_buckets[index*2] == heap->free_buckets[index*2+1])) {
++ heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
++ }
++ }
++ } else if (UNEXPECTED(mm_block->parent != NULL)) {
++ goto subst_block;
++ }
++ }
++}
++
++static void zend_mm_init(zend_mm_heap_canary *heap)
++{
++ zend_mm_free_block_canary* p;
++ int i;
++
++ heap->free_bitmap = 0;
++ heap->large_free_bitmap = 0;
++#if ZEND_MM_CACHE
++ heap->cached = 0;
++ memset(heap->cache, 0, sizeof(heap->cache));
++#endif
++#if ZEND_MM_CACHE_STAT
++ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
++ heap->cache_stat[i].count = 0;
++ }
++#endif
++ p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
++ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
++ p->next_free_block = SUHOSIN_MANGLE_PTR(p);
++ p->prev_free_block = SUHOSIN_MANGLE_PTR(p);
++ p = (zend_mm_free_block_canary*)((char*)p + sizeof(zend_mm_free_block_canary*) * 2);
++ heap->large_free_buckets[i] = NULL;
++ }
++ heap->rest_buckets[0] = heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(heap));
++#if SUHOSIN_PATCH
++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
++ zend_canary(&heap->canary_1, sizeof(heap->canary_1));
++ zend_canary(&heap->canary_2, sizeof(heap->canary_2));
++ zend_canary(&heap->canary_3, sizeof(heap->canary_3));
++ }
++#endif
++}
++
++static void zend_mm_del_segment(zend_mm_heap_canary *heap, zend_mm_segment *segment)
++{
++ zend_mm_segment **p = &heap->segments_list;
++
++ while (*p != segment) {
++ p = &(*p)->next_segment;
++ }
++ *p = segment->next_segment;
++ heap->real_size -= segment->size;
++ ZEND_MM_STORAGE_FREE(segment);
++}
++
++#if ZEND_MM_CACHE
++static void zend_mm_free_cache(zend_mm_heap_canary *heap)
++{
++ int i;
++
++ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
++ /* SUHOSIN_MANGLE_PTR should NOT affect NULL pointers */
++ if (heap->cache[i]) {
++ zend_mm_free_block_canary *mm_block = SUHOSIN_MANGLE_PTR(heap->cache[i]);
++
++ while (mm_block) {
++ size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
++ zend_mm_free_block_canary *q = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
++ zend_mm_block_canary *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
++
++ heap->cached -= size;
++
++ if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
++ mm_block = (zend_mm_free_block_canary*)ZEND_MM_PREV_BLOCK(mm_block);
++ size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) mm_block);
++ }
++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
++ size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
++ }
++ ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
++
++ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
++ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_NEXT_BLOCK(mm_block))) {
++ zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
++ } else {
++ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) mm_block);
++ }
++
++ mm_block = q;
++ }
++ heap->cache[i] = NULL;
++#if ZEND_MM_CACHE_STAT
++ heap->cache_stat[i].count = 0;
++#endif
++ }
++ }
++}
++#endif
++
++#if ZEND_MM_HEAP_PROTECTION || ZEND_MM_COOKIES
++static void zend_mm_random(unsigned char *buf, size_t size) /* {{{ */
++{
++ size_t i = 0;
++ unsigned char t;
++
++#ifdef ZEND_WIN32
++ HCRYPTPROV hCryptProv;
++ int has_context = 0;
++
++ if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
++ /* Could mean that the key container does not exist, let try
++ again by asking for a new one */
++ if (GetLastError() == NTE_BAD_KEYSET) {
++ if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
++ has_context = 1;
++ }
++ }
++ } else {
++ has_context = 1;
++ }
++ if (has_context) {
++ do {
++ BOOL ret = CryptGenRandom(hCryptProv, size, buf);
++ CryptReleaseContext(hCryptProv, 0);
++ if (ret) {
++ while (i < size && buf[i] != 0) {
++ i++;
++ }
++ if (i == size) {
++ return;
++ }
++ }
++ } while (0);
++ }
++#elif defined(HAVE_DEV_URANDOM)
++ int fd = open("/dev/urandom", 0);
++
++ if (fd >= 0) {
++ if (read(fd, buf, size) == size) {
++ while (i < size && buf[i] != 0) {
++ i++;
++ }
++ if (i == size) {
++ close(fd);
++ return;
++ }
++ }
++ close(fd);
++ }
++#endif
++ t = (unsigned char)getpid();
++ while (i < size) {
++ do {
++ buf[i] = ((unsigned char)rand()) ^ t;
++ } while (buf[i] == 0);
++ t = buf[i++] << 1;
++ }
++}
++/* }}} */
++#endif
++
++
++/* Notes:
++ * - This function may alter the block_sizes values to match platform alignment
++ * - This function does *not* perform sanity checks on the arguments
++ */
++zend_mm_heap_canary *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
++{
++ zend_mm_storage *storage;
++ zend_mm_heap_canary *heap;
++ zend_mm_free_block_canary *tmp;
++
++#if 0
++ int i;
++
++ printf("ZEND_MM_ALIGNMENT=%d\n", ZEND_MM_ALIGNMENT);
++ printf("ZEND_MM_ALIGNMENT_LOG2=%d\n", ZEND_MM_ALIGNMENT_LOG2);
++ printf("ZEND_MM_MIN_SIZE=%d\n", ZEND_MM_MIN_SIZE);
++ printf("ZEND_MM_MAX_SMALL_SIZE=%d\n", ZEND_MM_MAX_SMALL_SIZE);
++ printf("ZEND_MM_ALIGNED_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_HEADER_SIZE);
++ printf("ZEND_MM_ALIGNED_FREE_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_FREE_HEADER_SIZE);
++ printf("ZEND_MM_MIN_ALLOC_BLOCK_SIZE=%d\n", ZEND_MM_MIN_ALLOC_BLOCK_SIZE);
++ printf("ZEND_MM_ALIGNED_MIN_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_MIN_HEADER_SIZE);
++ printf("ZEND_MM_ALIGNED_SEGMENT_SIZE=%d\n", ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ for (i = 0; i < ZEND_MM_MAX_SMALL_SIZE; i++) {
++ printf("%3d%c: %3ld %d %2ld\n", i, (i == ZEND_MM_MIN_SIZE?'*':' '), (long)ZEND_MM_TRUE_SIZE(i), ZEND_MM_SMALL_SIZE(ZEND_MM_TRUE_SIZE(i)), (long)ZEND_MM_BUCKET_INDEX(ZEND_MM_TRUE_SIZE(i)));
++ }
++ exit(0);
++#endif
++
++#if ZEND_MM_HEAP_PROTECTION
++ if (_mem_block_start_magic == 0) {
++ zend_mm_random((unsigned char*)&_mem_block_start_magic, sizeof(_mem_block_start_magic));
++ }
++ if (_mem_block_end_magic == 0) {
++ zend_mm_random((unsigned char*)&_mem_block_end_magic, sizeof(_mem_block_end_magic));
++ }
++#endif
++#if ZEND_MM_COOKIES
++ if (_zend_mm_cookie == 0) {
++ zend_mm_random((unsigned char*)&_zend_mm_cookie, sizeof(_zend_mm_cookie));
++ }
++#endif
++
++ /* get the pointer guardian and ensure low 3 bits are 1 */
++ if (SUHOSIN_POINTER_GUARD == 0) {
++ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
++ SUHOSIN_POINTER_GUARD |= 7;
++ }
++
++ if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
++ fprintf(stderr, "'block_size' must be a power of two\n");
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
++#endif
++ exit(255);
++ }
++ storage = handlers->init(params);
++ if (!storage) {
++ fprintf(stderr, "Cannot initialize zend_mm storage [%s]\n", handlers->name);
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
++#endif
++ exit(255);
++ }
++ storage->handlers = handlers;
++
++ heap = malloc(sizeof(struct _zend_mm_heap_canary));
++
++ heap->storage = storage;
++ heap->block_size = block_size;
++ heap->compact_size = 0;
++ heap->segments_list = NULL;
++ zend_mm_init(heap);
++# if ZEND_MM_CACHE_STAT
++ memset(heap->cache_stat, 0, sizeof(heap->cache_stat));
++# endif
++
++ heap->use_zend_alloc = 1;
++ heap->real_size = 0;
++ heap->overflow = 0;
++ heap->real_peak = 0;
++ heap->limit = ZEND_MM_LONG_CONST(1)<<(ZEND_MM_NUM_BUCKETS-2);
++ heap->size = 0;
++ heap->peak = 0;
++ heap->internal = internal;
++ heap->reserve = NULL;
++ heap->reserve_size = reserve_size;
++ if (reserve_size > 0) {
++ heap->reserve = _zend_mm_alloc((zend_mm_heap *)heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++ }
++ if (internal) {
++ int i;
++ zend_mm_free_block_canary *p, *q, *orig;
++ zend_mm_heap_canary *mm_heap = _zend_mm_alloc((zend_mm_heap *)heap, sizeof(zend_mm_heap_canary) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++
++ *mm_heap = *heap;
++
++ p = ZEND_MM_SMALL_FREE_BUCKET(mm_heap, 0);
++ orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
++ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
++ q = p;
++ while (SUHOSIN_MANGLE_PTR(q->prev_free_block) != orig) {
++ q = SUHOSIN_MANGLE_PTR(q->prev_free_block);
++ }
++ q->prev_free_block = SUHOSIN_MANGLE_PTR(p);
++ q = p;
++ while (SUHOSIN_MANGLE_PTR(q->next_free_block) != orig) {
++ q = SUHOSIN_MANGLE_PTR(q->next_free_block);
++ }
++ q->next_free_block = SUHOSIN_MANGLE_PTR(p);
++ p = (zend_mm_free_block_canary*)((char*)p + sizeof(zend_mm_free_block_canary*) * 2);
++ orig = (zend_mm_free_block_canary*)((char*)orig + sizeof(zend_mm_free_block_canary*) * 2);
++ if (mm_heap->large_free_buckets[i]) {
++ mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
++ }
++ }
++ mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(mm_heap));
++
++ free(heap);
++ heap = mm_heap;
++ }
++ return heap;
++}
++
++zend_mm_heap_canary *__zend_mm_startup_canary(void)
++{
++ int i;
++ size_t seg_size;
++ char *mem_type = getenv("ZEND_MM_MEM_TYPE");
++ char *tmp;
++ const zend_mm_mem_handlers *handlers;
++ zend_mm_heap_canary *heap;
++
++ if (mem_type == NULL) {
++ i = 0;
++ } else {
++ for (i = 0; mem_handlers[i].name; i++) {
++ if (strcmp(mem_handlers[i].name, mem_type) == 0) {
++ break;
++ }
++ }
++ if (!mem_handlers[i].name) {
++ fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type);
++ fprintf(stderr, " supported types:\n");
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
++#endif
++ for (i = 0; mem_handlers[i].name; i++) {
++ fprintf(stderr, " '%s'\n", mem_handlers[i].name);
++ }
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
++#endif
++ exit(255);
++ }
++ }
++ handlers = &mem_handlers[i];
++
++ tmp = getenv("ZEND_MM_SEG_SIZE");
++ if (tmp) {
++ seg_size = zend_atoi(tmp, 0);
++ if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) {
++ fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n");
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
++#endif
++ exit(255);
++ } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) {
++ fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n");
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
++#endif
++ exit(255);
++ }
++ } else {
++ seg_size = ZEND_MM_SEG_SIZE;
++ }
++
++ heap = __zend_mm_startup_canary_ex(handlers, seg_size, ZEND_MM_RESERVE_SIZE, 0, NULL);
++ if (heap) {
++ tmp = getenv("ZEND_MM_COMPACT");
++ if (tmp) {
++ heap->compact_size = zend_atoi(tmp, 0);
++ } else {
++ heap->compact_size = 2 * 1024 * 1024;
++ }
++ }
++ return heap;
++}
++
++#if ZEND_DEBUG
++static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block_canary *b)
++{
++ long leaks = 0;
++ zend_mm_block_canary *p, *q;
++
++ p = ZEND_MM_NEXT_BLOCK(b);
++ while (1) {
++ if (ZEND_MM_IS_GUARD_BLOCK(p)) {
++ ZEND_MM_CHECK_MAGIC(p, MEM_BLOCK_GUARD);
++ segment = segment->next_segment;
++ if (!segment) {
++ break;
++ }
++ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ continue;
++ }
++ q = ZEND_MM_NEXT_BLOCK(p);
++ if (q <= p ||
++ (char*)q > (char*)segment + segment->size ||
++ p->info._size != q->info._prev) {
++ zend_mm_panic("zend_mm_heap corrupted");
++ }
++ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
++ if (p->magic == MEM_BLOCK_VALID) {
++ if (p->debug.filename==b->debug.filename && p->debug.lineno==b->debug.lineno) {
++ ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
++ leaks++;
++ }
++#if ZEND_MM_CACHE
++ } else if (p->magic == MEM_BLOCK_CACHED) {
++ /* skip it */
++#endif
++ } else if (p->magic != MEM_BLOCK_LEAK) {
++ zend_mm_panic("zend_mm_heap corrupted");
++ }
++ }
++ p = q;
++ }
++ return leaks;
++}
++
++static void zend_mm_check_leaks(zend_mm_heap_canary *heap TSRMLS_DC)
++{
++ zend_mm_segment *segment = heap->segments_list;
++ zend_mm_block_canary *p, *q;
++ zend_uint total = 0;
++
++ if (!segment) {
++ return;
++ }
++ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ while (1) {
++ q = ZEND_MM_NEXT_BLOCK(p);
++ if (q <= p ||
++ (char*)q > (char*)segment + segment->size ||
++ p->info._size != q->info._prev) {
++ zend_mm_panic("zend_mm_heap corrupted");
++ }
++ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
++ if (p->magic == MEM_BLOCK_VALID) {
++ long repeated;
++ zend_leak_info leak;
++
++ ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
++
++ leak.addr = ZEND_MM_DATA_OF(p);
++ leak.size = p->debug.size;
++ leak.filename = p->debug.filename;
++ leak.lineno = p->debug.lineno;
++ leak.orig_filename = p->debug.orig_filename;
++ leak.orig_lineno = p->debug.orig_lineno;
++
++ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
++ zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
++ repeated = zend_mm_find_leaks(segment, p);
++ total += 1 + repeated;
++ if (repeated) {
++ zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
++ }
++#if ZEND_MM_CACHE
++ } else if (p->magic == MEM_BLOCK_CACHED) {
++ /* skip it */
++#endif
++ } else if (p->magic != MEM_BLOCK_LEAK) {
++ zend_mm_panic("zend_mm_heap corrupted");
++ }
++ }
++ if (ZEND_MM_IS_GUARD_BLOCK(q)) {
++ segment = segment->next_segment;
++ if (!segment) {
++ break;
++ }
++ q = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ }
++ p = q;
++ }
++ if (total) {
++ zend_message_dispatcher(ZMSG_MEMORY_LEAKS_GRAND_TOTAL, &total TSRMLS_CC);
++ }
++}
++
++static int zend_mm_check_ptr(zend_mm_heap_canary *heap, void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
++{
++ zend_mm_block_canary *p;
++ int no_cache_notice = 0;
++ int had_problems = 0;
++ int valid_beginning = 1;
++
++ if (silent==2) {
++ silent = 1;
++ no_cache_notice = 1;
++ } else if (silent==3) {
++ silent = 0;
++ no_cache_notice = 1;
++ }
++ if (!silent) {
++ TSRMLS_FETCH();
++
++ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
++ zend_debug_alloc_output("---------------------------------------\n");
++ zend_debug_alloc_output("%s(%d) : Block "PTR_FMT" status:\n" ZEND_FILE_LINE_RELAY_CC, ptr);
++ if (__zend_orig_filename) {
++ zend_debug_alloc_output("%s(%d) : Actual location (location was relayed)\n" ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ if (!ptr) {
++ zend_debug_alloc_output("NULL\n");
++ zend_debug_alloc_output("---------------------------------------\n");
++ return 0;
++ }
++ }
++
++ if (!ptr) {
++ if (silent) {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ }
++
++ p = ZEND_MM_HEADER_OF(ptr);
++
++#ifdef ZTS
++ if (ZEND_MM_BAD_THREAD_ID(p)) {
++ if (!silent) {
++ zend_debug_alloc_output("Invalid pointer: ((thread_id=0x%0.8X) != (expected=0x%0.8X))\n", (long)p->thread_id, (long)tsrm_thread_id());
++ had_problems = 1;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ }
++#endif
++
++ if (p->info._size != ZEND_MM_NEXT_BLOCK(p)->info._prev) {
++ if (!silent) {
++ zend_debug_alloc_output("Invalid pointer: ((size="PTR_FMT") != (next.prev="PTR_FMT"))\n", p->info._size, ZEND_MM_NEXT_BLOCK(p)->info._prev);
++ had_problems = 1;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ }
++ if (p->info._prev != ZEND_MM_GUARD_BLOCK &&
++ ZEND_MM_PREV_BLOCK(p)->info._size != p->info._prev) {
++ if (!silent) {
++ zend_debug_alloc_output("Invalid pointer: ((prev="PTR_FMT") != (prev.size="PTR_FMT"))\n", p->info._prev, ZEND_MM_PREV_BLOCK(p)->info._size);
++ had_problems = 1;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ }
++
++ if (had_problems) {
++ zend_debug_alloc_output("---------------------------------------\n");
++ return 0;
++ }
++
++ if (!silent) {
++ zend_debug_alloc_output("%10s\t","Beginning: ");
++ }
++
++ if (!ZEND_MM_IS_USED_BLOCK(p)) {
++ if (!silent) {
++ if (p->magic != MEM_BLOCK_FREED) {
++ zend_debug_alloc_output("Freed (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
++ } else {
++ zend_debug_alloc_output("Freed\n");
++ }
++ had_problems = 1;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ } else if (ZEND_MM_IS_GUARD_BLOCK(p)) {
++ if (!silent) {
++ if (p->magic != MEM_BLOCK_FREED) {
++ zend_debug_alloc_output("Guard (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
++ } else {
++ zend_debug_alloc_output("Guard\n");
++ }
++ had_problems = 1;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ } else {
++ switch (p->magic) {
++ case MEM_BLOCK_VALID:
++ case MEM_BLOCK_LEAK:
++ if (!silent) {
++ zend_debug_alloc_output("OK (allocated on %s:%d, %d bytes)\n", p->debug.filename, p->debug.lineno, (int)p->debug.size);
++ }
++ break; /* ok */
++ case MEM_BLOCK_CACHED:
++ if (!no_cache_notice) {
++ if (!silent) {
++ zend_debug_alloc_output("Cached\n");
++ had_problems = 1;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ }
++ case MEM_BLOCK_FREED:
++ if (!silent) {
++ zend_debug_alloc_output("Freed (invalid)\n");
++ had_problems = 1;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ break;
++ case MEM_BLOCK_GUARD:
++ if (!silent) {
++ zend_debug_alloc_output("Guard (invalid)\n");
++ had_problems = 1;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ break;
++ default:
++ if (!silent) {
++ zend_debug_alloc_output("Unknown (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_VALID);
++ had_problems = 1;
++ valid_beginning = 0;
++ } else {
++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ break;
++ }
++ }
++
++#if ZEND_MM_HEAP_PROTECTION
++ if (!valid_beginning) {
++ if (!silent) {
++ zend_debug_alloc_output("%10s\t", "Start:");
++ zend_debug_alloc_output("Unknown\n");
++ zend_debug_alloc_output("%10s\t", "End:");
++ zend_debug_alloc_output("Unknown\n");
++ }
++ } else {
++ char *end_magic = ZEND_MM_END_MAGIC_PTR(p);
++
++ if (p->debug.start_magic == _mem_block_start_magic) {
++ if (!silent) {
++ zend_debug_alloc_output("%10s\t", "Start:");
++ zend_debug_alloc_output("OK\n");
++ }
++ } else {
++ char *overflow_ptr, *magic_ptr=(char *) &_mem_block_start_magic;
++ int overflows=0;
++ int i;
++
++ if (silent) {
++ return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ had_problems = 1;
++ overflow_ptr = (char *) &p->debug.start_magic;
++ i = END_MAGIC_SIZE;
++ while (--i >= 0) {
++ if (overflow_ptr[i]!=magic_ptr[i]) {
++ overflows++;
++ }
++ }
++ zend_debug_alloc_output("%10s\t", "Start:");
++ zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", p->debug.start_magic, _mem_block_start_magic);
++ zend_debug_alloc_output("%10s\t","");
++ if (overflows >= END_MAGIC_SIZE) {
++ zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
++ } else {
++ zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
++ }
++ }
++ if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) {
++ if (!silent) {
++ zend_debug_alloc_output("%10s\t", "End:");
++ zend_debug_alloc_output("OK\n");
++ }
++ } else {
++ char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic;
++ int overflows=0;
++ int i;
++
++ if (silent) {
++ return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ had_problems = 1;
++ overflow_ptr = (char *) end_magic;
++
++ for (i=0; i < END_MAGIC_SIZE; i++) {
++ if (overflow_ptr[i]!=magic_ptr[i]) {
++ overflows++;
++ }
++ }
++
++ zend_debug_alloc_output("%10s\t", "End:");
++ zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", *end_magic, _mem_block_end_magic);
++ zend_debug_alloc_output("%10s\t","");
++ if (overflows >= END_MAGIC_SIZE) {
++ zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
++ } else {
++ zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
++ }
++ }
++ }
++#endif
++
++ if (!silent) {
++ zend_debug_alloc_output("---------------------------------------\n");
++ }
++ return ((!had_problems) ? 1 : 0);
++}
++
++static int zend_mm_check_heap(zend_mm_heap_canary *heap, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
++{
++ zend_mm_segment *segment = heap->segments_list;
++ zend_mm_block_canary *p, *q;
++ int errors = 0;
++
++ if (!segment) {
++ return 0;
++ }
++ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ while (1) {
++ q = ZEND_MM_NEXT_BLOCK(p);
++ if (q <= p ||
++ (char*)q > (char*)segment + segment->size ||
++ p->info._size != q->info._prev) {
++ zend_mm_panic("zend_mm_heap corrupted");
++ }
++ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
++ if (p->magic == MEM_BLOCK_VALID || p->magic == MEM_BLOCK_LEAK) {
++ if (!zend_mm_check_ptr(heap, ZEND_MM_DATA_OF(p), (silent?2:3) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)) {
++ errors++;
++ }
++#if ZEND_MM_CACHE
++ } else if (p->magic == MEM_BLOCK_CACHED) {
++ /* skip it */
++#endif
++ } else if (p->magic != MEM_BLOCK_LEAK) {
++ zend_mm_panic("zend_mm_heap corrupted");
++ }
++ }
++ if (ZEND_MM_IS_GUARD_BLOCK(q)) {
++ segment = segment->next_segment;
++ if (!segment) {
++ return errors;
++ }
++ q = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ }
++ p = q;
++ }
++}
++#endif
++
++void __zend_mm_shutdown_canary(zend_mm_heap_canary *heap, int full_shutdown, int silent TSRMLS_DC)
++{
++ zend_mm_storage *storage;
++ zend_mm_segment *segment;
++ zend_mm_segment *prev;
++ int internal;
++
++ if (heap->reserve) {
++#if ZEND_DEBUG
++ if (!silent) {
++ _zend_mm_free(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++ }
++#endif
++ heap->reserve = NULL;
++ }
++
++#if ZEND_MM_CACHE_STAT
++ if (full_shutdown) {
++ FILE *f;
++
++ f = fopen("zend_mm.log", "w");
++ if (f) {
++ int i,j;
++ size_t size, true_size, min_size, max_size;
++ int hit = 0, miss = 0;
++
++ fprintf(f, "\nidx min_size max_size true_size max_len hits misses\n");
++ size = 0;
++ while (1) {
++ true_size = ZEND_MM_TRUE_SIZE(size);
++ if (ZEND_MM_SMALL_SIZE(true_size)) {
++ min_size = size;
++ i = ZEND_MM_BUCKET_INDEX(true_size);
++ size++;
++ while (1) {
++ true_size = ZEND_MM_TRUE_SIZE(size);
++ if (ZEND_MM_SMALL_SIZE(true_size)) {
++ j = ZEND_MM_BUCKET_INDEX(true_size);
++ if (j > i) {
++ max_size = size-1;
++ break;
++ }
++ } else {
++ max_size = size-1;
++ break;
++ }
++ size++;
++ }
++ hit += heap->cache_stat[i].hit;
++ miss += heap->cache_stat[i].miss;
++ fprintf(f, "%2d %8d %8d %9d %8d %8d %8d\n", i, (int)min_size, (int)max_size, ZEND_MM_TRUE_SIZE(max_size), heap->cache_stat[i].max_count, heap->cache_stat[i].hit, heap->cache_stat[i].miss);
++ } else {
++ break;
++ }
++ }
++ fprintf(f, " %8d %8d\n", hit, miss);
++ fprintf(f, " %8d %8d\n", heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit, heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss);
++ fclose(f);
++ }
++ }
++#endif
++
++#if ZEND_DEBUG
++ if (!silent) {
++ zend_mm_check_leaks(heap TSRMLS_CC);
++ }
++#endif
++
++ internal = heap->internal;
++ storage = heap->storage;
++ segment = heap->segments_list;
++ while (segment) {
++ prev = segment;
++ segment = segment->next_segment;
++ ZEND_MM_STORAGE_FREE(prev);
++ }
++ if (full_shutdown) {
++ storage->handlers->dtor(storage);
++ if (!internal) {
++ free(heap);
++ }
++ } else {
++ if (heap->compact_size &&
++ heap->real_peak > heap->compact_size) {
++ storage->handlers->compact(storage);
++ }
++ heap->segments_list = NULL;
++ zend_mm_init(heap);
++ heap->real_size = 0;
++ heap->real_peak = 0;
++ heap->size = 0;
++ heap->peak = 0;
++ if (heap->reserve_size) {
++ heap->reserve = _zend_mm_alloc((zend_mm_heap *)heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++ }
++ heap->overflow = 0;
++ }
++}
++
++static void zend_mm_safe_error(zend_mm_heap_canary *heap,
++ const char *format,
++ size_t limit,
++#if ZEND_DEBUG
++ const char *filename,
++ uint lineno,
++#endif
++ size_t size)
++{
++ if (heap->reserve) {
++ _zend_mm_free_canary_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++ heap->reserve = NULL;
++ }
++ if (heap->overflow == 0) {
++ char *error_filename;
++ uint error_lineno;
++ TSRMLS_FETCH();
++ if (zend_is_compiling(TSRMLS_C)) {
++ error_filename = zend_get_compiled_filename(TSRMLS_C);
++ error_lineno = zend_get_compiled_lineno(TSRMLS_C);
++ } else if (EG(in_execution)) {
++ error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
++ error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
++ } else {
++ error_filename = NULL;
++ error_lineno = 0;
++ }
++ if (!error_filename) {
++ error_filename = "Unknown";
++ }
++ heap->overflow = 1;
++ zend_try {
++ zend_error_noreturn(E_ERROR,
++ format,
++ limit,
++#if ZEND_DEBUG
++ filename,
++ lineno,
++#endif
++ size);
++ } zend_catch {
++ if (heap->overflow == 2) {
++ fprintf(stderr, "\nFatal error: ");
++ fprintf(stderr,
++ format,
++ limit,
++#if ZEND_DEBUG
++ filename,
++ lineno,
++#endif
++ size);
++ fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno);
++ }
++/* See http://support.microsoft.com/kb/190351 */
++#ifdef PHP_WIN32
++ fflush(stderr);
++#endif
++ } zend_end_try();
++ } else {
++ heap->overflow = 2;
++ }
++ zend_bailout();
++}
++
++static zend_mm_free_block_canary *zend_mm_search_large_block(zend_mm_heap_canary *heap, size_t true_size)
++{
++ zend_mm_free_block_canary *best_fit;
++ size_t index = ZEND_MM_LARGE_BUCKET_INDEX(true_size);
++ size_t bitmap = heap->large_free_bitmap >> index;
++ zend_mm_free_block_canary *p;
++
++ if (bitmap == 0) {
++ return NULL;
++ }
++
++ if (UNEXPECTED((bitmap & 1) != 0)) {
++ /* Search for best "large" free block */
++ zend_mm_free_block_canary *rst = NULL;
++ size_t m;
++ size_t best_size = -1;
++
++ best_fit = NULL;
++ p = heap->large_free_buckets[index];
++ for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
++ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
++ return SUHOSIN_MANGLE_PTR(p->next_free_block);
++ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
++ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
++ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
++ best_fit = p;
++ }
++ if ((m & (ZEND_MM_LONG_CONST(1) << (ZEND_MM_NUM_BUCKETS-1))) == 0) {
++ if (p->child[1]) {
++ rst = p->child[1];
++ }
++ if (p->child[0]) {
++ p = p->child[0];
++ } else {
++ break;
++ }
++ } else if (p->child[1]) {
++ p = p->child[1];
++ } else {
++ break;
++ }
++ }
++
++ for (p = rst; p; p = p->child[p->child[0] != NULL]) {
++ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
++ return SUHOSIN_MANGLE_PTR(p->next_free_block);
++ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
++ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
++ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
++ best_fit = p;
++ }
++ }
++
++ if (best_fit) {
++ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
++ }
++ bitmap = bitmap >> 1;
++ if (!bitmap) {
++ return NULL;
++ }
++ index++;
++ }
++
++ /* Search for smallest "large" free block */
++ best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)];
++ while ((p = p->child[p->child[0] != NULL])) {
++ if (ZEND_MM_FREE_BLOCK_SIZE(p) < ZEND_MM_FREE_BLOCK_SIZE(best_fit)) {
++ best_fit = p;
++ }
++ }
++ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
++}
++
++void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
++{
++ zend_mm_free_block_canary *best_fit;
++ size_t true_size = ZEND_MM_TRUE_SIZE(size);
++ size_t block_size;
++ size_t remaining_size;
++ size_t segment_size;
++ zend_mm_segment *segment;
++ int keep_rest = 0;
++
++ if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
++ size_t index = ZEND_MM_BUCKET_INDEX(true_size);
++ size_t bitmap;
++
++ if (UNEXPECTED(true_size < size)) {
++ goto out_of_memory;
++ }
++#if ZEND_MM_CACHE
++ if (EXPECTED(heap->cache[index] != NULL)) {
++ /* Get block from cache */
++#if ZEND_MM_CACHE_STAT
++ heap->cache_stat[index].count--;
++ heap->cache_stat[index].hit++;
++#endif
++ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
++ heap->cache[index] = best_fit->prev_free_block;
++ heap->cached -= true_size;
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(best_fit);
++ ((zend_mm_block_canary*)best_fit)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(best_fit);
++#endif
++ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
++ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
++ return ZEND_MM_DATA_OF(best_fit);
++ }
++#if ZEND_MM_CACHE_STAT
++ heap->cache_stat[index].miss++;
++#endif
++#endif
++
++ bitmap = heap->free_bitmap >> index;
++ if (bitmap) {
++ /* Found some "small" free block that can be used */
++ index += zend_mm_low_bit(bitmap);
++ best_fit = SUHOSIN_MANGLE_PTR(heap->free_buckets[index*2]);
++#if ZEND_MM_CACHE_STAT
++ heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
++#endif
++ goto zend_mm_finished_searching_for_block;
++ }
++ }
++
++#if ZEND_MM_CACHE_STAT
++ heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss++;
++#endif
++
++ best_fit = zend_mm_search_large_block(heap, true_size);
++
++ if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
++ zend_mm_free_block_canary *p = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
++ size_t best_size = -1;
++
++ while (p != ZEND_MM_REST_BUCKET(heap)) {
++ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
++ best_fit = p;
++ goto zend_mm_finished_searching_for_block;
++ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
++ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
++ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
++ best_fit = p;
++ }
++ p = SUHOSIN_MANGLE_PTR(p->prev_free_block);
++ }
++ }
++
++ if (!best_fit) {
++ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
++ /* Make sure we add a memory block which is big enough,
++ segment must have header "size" and trailer "guard" block */
++ segment_size = true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE;
++ segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
++ keep_rest = 1;
++ } else {
++ segment_size = heap->block_size;
++ }
++
++ HANDLE_BLOCK_INTERRUPTIONS();
++
++ if (segment_size < true_size ||
++ heap->real_size + segment_size > heap->limit) {
++ /* Memory limit overflow */
++#if ZEND_MM_CACHE
++ zend_mm_free_cache(heap);
++#endif
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++#if ZEND_DEBUG
++ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size);
++#else
++ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size);
++#endif
++ }
++
++ segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size);
++
++ if (!segment) {
++ /* Storage manager cannot allocate memory */
++#if ZEND_MM_CACHE
++ zend_mm_free_cache(heap);
++#endif
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++out_of_memory:
++#if ZEND_DEBUG
++ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
++#else
++ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
++#endif
++ return NULL;
++ }
++
++ heap->real_size += segment_size;
++ if (heap->real_size > heap->real_peak) {
++ heap->real_peak = heap->real_size;
++ }
++
++ segment->size = segment_size;
++ segment->next_segment = heap->segments_list;
++ heap->segments_list = segment;
++
++ best_fit = (zend_mm_free_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ ZEND_MM_MARK_FIRST_BLOCK(best_fit);
++
++ block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
++
++ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(best_fit, block_size));
++
++ } else {
++zend_mm_finished_searching_for_block:
++ /* remove from free list */
++ HANDLE_BLOCK_INTERRUPTIONS();
++ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED);
++ ZEND_MM_CHECK_COOKIE(best_fit);
++ ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit);
++ zend_mm_remove_from_free_list(heap, best_fit);
++
++ block_size = ZEND_MM_FREE_BLOCK_SIZE(best_fit);
++ }
++
++ remaining_size = block_size - true_size;
++
++ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
++ true_size = block_size;
++ ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
++ } else {
++ zend_mm_free_block_canary *new_free_block;
++
++ /* prepare new free block */
++ ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
++ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(best_fit, true_size);
++ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
++
++ /* add the new free block to the free list */
++ if (EXPECTED(!keep_rest)) {
++ zend_mm_add_to_free_list(heap, new_free_block);
++ } else {
++ zend_mm_add_to_rest_list(heap, new_free_block);
++ }
++ }
++
++ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
++
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(best_fit);
++ ((zend_mm_block_canary*)best_fit)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(best_fit);
++#endif
++
++ heap->size += true_size;
++ if (heap->peak < heap->size) {
++ heap->peak = heap->size;
++ }
++
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++ return ZEND_MM_DATA_OF(best_fit);
++}
++
++
++void _zend_mm_free_canary_int(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
++{
++ zend_mm_block_canary *mm_block;
++ zend_mm_block_canary *next_block;
++ size_t size;
++
++ if (!ZEND_MM_VALID_PTR(p)) {
++ return;
++ }
++
++ mm_block = ZEND_MM_HEADER_OF(p);
++ size = ZEND_MM_BLOCK_SIZE(mm_block);
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_CHECK_CANARIES(mm_block, "efree()");
++#endif
++ ZEND_MM_CHECK_PROTECTION(mm_block);
++
++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
++ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
++#endif
++#if SUHOSIN_PATCH
++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_DESTROY_FREE_MEMORY))) {
++ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->info.size);
++ }
++#endif
++#if ZEND_MM_CACHE
++ if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
++ size_t index = ZEND_MM_BUCKET_INDEX(size);
++ zend_mm_free_block_canary **cache = &heap->cache[index];
++
++ ((zend_mm_free_block_canary*)mm_block)->prev_free_block = *cache;
++ *cache = (zend_mm_free_block_canary*)SUHOSIN_MANGLE_PTR(mm_block);
++ heap->cached += size;
++ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
++#if ZEND_MM_CACHE_STAT
++ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
++ heap->cache_stat[index].max_count = heap->cache_stat[index].count;
++ }
++#endif
++ return;
++ }
++#endif
++
++ HANDLE_BLOCK_INTERRUPTIONS();
++
++ heap->size -= size;
++
++ next_block = ZEND_MM_BLOCK_AT(mm_block, size);
++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
++ size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
++ }
++ if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
++ mm_block = ZEND_MM_PREV_BLOCK(mm_block);
++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) mm_block);
++ size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
++ }
++ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
++ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(mm_block, size))) {
++ zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
++ } else {
++ ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
++ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) mm_block);
++ }
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++}
++
++void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
++{
++ zend_mm_block_canary *mm_block = ZEND_MM_HEADER_OF(p);
++ zend_mm_block_canary *next_block;
++ size_t true_size;
++ size_t orig_size;
++ void *ptr;
++
++ if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
++ return _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ }
++ mm_block = ZEND_MM_HEADER_OF(p);
++ true_size = ZEND_MM_TRUE_SIZE(size);
++ orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_CHECK_CANARIES(mm_block, "erealloc()");
++#endif
++ ZEND_MM_CHECK_PROTECTION(mm_block);
++
++ if (UNEXPECTED(true_size < size)) {
++ goto out_of_memory;
++ }
++
++ if (true_size <= orig_size) {
++ size_t remaining_size = orig_size - true_size;
++
++ if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
++ zend_mm_free_block_canary *new_free_block;
++
++ HANDLE_BLOCK_INTERRUPTIONS();
++ next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
++ remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
++ }
++
++ /* prepare new free block */
++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
++ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
++
++ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
++
++ /* add the new free block to the free list */
++ zend_mm_add_to_free_list(heap, new_free_block);
++ heap->size += (true_size - orig_size);
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++ }
++ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(mm_block);
++ ((zend_mm_block_canary*)mm_block)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(mm_block);
++#endif
++ return p;
++ }
++
++#if ZEND_MM_CACHE
++ if (ZEND_MM_SMALL_SIZE(true_size)) {
++ size_t index = ZEND_MM_BUCKET_INDEX(true_size);
++
++ if (heap->cache[index] != NULL) {
++ zend_mm_free_block_canary *best_fit;
++ zend_mm_free_block_canary **cache;
++
++#if ZEND_MM_CACHE_STAT
++ heap->cache_stat[index].count--;
++ heap->cache_stat[index].hit++;
++#endif
++ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
++ heap->cache[index] = best_fit->prev_free_block;
++ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
++ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(best_fit);
++ ((zend_mm_block_canary*)best_fit)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(best_fit);
++#endif
++
++ ptr = ZEND_MM_DATA_OF(best_fit);
++
++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
++ memcpy(ptr, p, mm_block->debug.size);
++#else
++ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
++#endif
++
++ heap->cached -= true_size - orig_size;
++
++ index = ZEND_MM_BUCKET_INDEX(orig_size);
++ cache = &heap->cache[index];
++
++ ((zend_mm_free_block_canary*)mm_block)->prev_free_block = *cache;
++ *cache = (zend_mm_free_block_canary*)SUHOSIN_MANGLE_PTR(mm_block);
++ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
++#if ZEND_MM_CACHE_STAT
++ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
++ heap->cache_stat[index].max_count = heap->cache_stat[index].count;
++ }
++#endif
++ return ptr;
++ }
++ }
++#endif
++
++ next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
++
++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
++ ZEND_MM_CHECK_COOKIE(next_block);
++ ZEND_MM_CHECK_BLOCK_LINKAGE(next_block);
++ if (orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block) >= true_size) {
++ size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block);
++ size_t remaining_size = block_size - true_size;
++
++ HANDLE_BLOCK_INTERRUPTIONS();
++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
++
++ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
++ true_size = block_size;
++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
++ } else {
++ zend_mm_free_block_canary *new_free_block;
++
++ /* prepare new free block */
++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
++ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
++ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
++
++ /* add the new free block to the free list */
++ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
++ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(new_free_block, remaining_size))) {
++ zend_mm_add_to_rest_list(heap, new_free_block);
++ } else {
++ zend_mm_add_to_free_list(heap, new_free_block);
++ }
++ }
++ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
++ heap->size = heap->size + true_size - orig_size;
++ if (heap->peak < heap->size) {
++ heap->peak = heap->size;
++ }
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(mm_block);
++ ((zend_mm_block_canary*)mm_block)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(mm_block);
++#endif
++ return p;
++ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
++ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
++ HANDLE_BLOCK_INTERRUPTIONS();
++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
++ goto realloc_segment;
++ }
++ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(next_block)) {
++ zend_mm_segment *segment;
++ zend_mm_segment *segment_copy;
++ size_t segment_size;
++ size_t block_size;
++ size_t remaining_size;
++
++ HANDLE_BLOCK_INTERRUPTIONS();
++realloc_segment:
++ /* segment size, size of block and size of guard block */
++ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
++ segment_size = true_size+ZEND_MM_ALIGNED_SEGMENT_SIZE+ZEND_MM_ALIGNED_HEADER_SIZE;
++ segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
++ } else {
++ segment_size = heap->block_size;
++ }
++
++ segment_copy = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ if (segment_size < true_size ||
++ heap->real_size + segment_size - segment_copy->size > heap->limit) {
++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
++ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) next_block);
++ }
++#if ZEND_MM_CACHE
++ zend_mm_free_cache(heap);
++#endif
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++#if ZEND_DEBUG
++ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %ld bytes)", heap->limit, __zend_filename, __zend_lineno, size);
++#else
++ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %ld bytes)", heap->limit, size);
++#endif
++ return NULL;
++ }
++
++ segment = ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size);
++ if (!segment) {
++#if ZEND_MM_CACHE
++ zend_mm_free_cache(heap);
++#endif
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++out_of_memory:
++#if ZEND_DEBUG
++ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
++#else
++ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %ld bytes)", heap->real_size, size);
++#endif
++ return NULL;
++ }
++ heap->real_size += segment_size - segment->size;
++ if (heap->real_size > heap->real_peak) {
++ heap->real_peak = heap->real_size;
++ }
++
++ segment->size = segment_size;
++
++ if (segment != segment_copy) {
++ zend_mm_segment **seg = &heap->segments_list;
++ while (*seg != segment_copy) {
++ seg = &(*seg)->next_segment;
++ }
++ *seg = segment;
++ mm_block = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
++ ZEND_MM_MARK_FIRST_BLOCK(mm_block);
++ }
++
++ block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
++ remaining_size = block_size - true_size;
++
++ /* setup guard block */
++ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(mm_block, block_size));
++
++ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
++ true_size = block_size;
++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
++ } else {
++ zend_mm_free_block_canary *new_free_block;
++
++ /* prepare new free block */
++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
++ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
++ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
++
++ /* add the new free block to the free list */
++ zend_mm_add_to_rest_list(heap, new_free_block);
++ }
++
++ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 1, 1);
++
++ heap->size = heap->size + true_size - orig_size;
++ if (heap->peak < heap->size) {
++ heap->peak = heap->size;
++ }
++
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++#if SUHOSIN_PATCH
++ SUHOSIN_MM_SET_CANARIES(mm_block);
++ ((zend_mm_block_canary*)mm_block)->info.size = size;
++ SUHOSIN_MM_SET_END_CANARY(mm_block);
++#endif
++ return ZEND_MM_DATA_OF(mm_block);
++ }
++
++ ptr = _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
++ memcpy(ptr, p, mm_block->debug.size);
++#else
++ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
++#endif
++ _zend_mm_free_canary_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
++ return ptr;
++}
++
++ZEND_API size_t _zend_mm_block_size_canary(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
++{
++ zend_mm_block_canary *mm_block;
++
++ if (!ZEND_MM_VALID_PTR(p)) {
++ return 0;
++ }
++ mm_block = ZEND_MM_HEADER_OF(p);
++ ZEND_MM_CHECK_PROTECTION(mm_block);
++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
++ return mm_block->debug.size;
++#else
++ return ZEND_MM_BLOCK_SIZE(mm_block);
++#endif
++}
++
++#if defined(__GNUC__) && defined(i386)
++
++static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
++{
++ size_t res = nmemb;
++ unsigned long overflow = 0;
++
++ __asm__ ("mull %3\n\taddl %4,%0\n\tadcl %1,%1"
++ : "=&a"(res), "=&d" (overflow)
++ : "%0"(res),
++ "rm"(size),
++ "rm"(offset));
++
++ if (UNEXPECTED(overflow)) {
++ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ return 0;
++ }
++ return res;
++}
++
++#elif defined(__GNUC__) && defined(__x86_64__)
++
++static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
++{
++ size_t res = nmemb;
++ unsigned long overflow = 0;
++
++ __asm__ ("mulq %3\n\taddq %4,%0\n\tadcq %1,%1"
++ : "=&a"(res), "=&d" (overflow)
++ : "%0"(res),
++ "rm"(size),
++ "rm"(offset));
++
++ if (UNEXPECTED(overflow)) {
++ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ return 0;
++ }
++ return res;
++}
++
++#elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64)
++
++static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
++{
++ zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
++
++ if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
++ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ return 0;
++ }
++ return (size_t) res;
++}
++
++#else
++
++static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
++{
++ size_t res = nmemb * size + offset;
++ double _d = (double)nmemb * (double)size + (double)offset;
++ double _delta = (double)res - _d;
++
++ if (UNEXPECTED((_d + _delta ) != _d)) {
++ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++ return 0;
++ }
++ return res;
++}
++#endif
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * indent-tabs-mode: t
++ * End:
++ */
++
+diff -Nura php-5.3.6/Zend/zend_alloc.h suhosin-patch-5.3.6-0.9.10/Zend/zend_alloc.h
+--- php-5.3.6/Zend/zend_alloc.h 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_alloc.h 2011-03-19 10:48:33.793975398 +0100
+@@ -203,6 +203,8 @@
+
+ /* Heap functions */
+ typedef struct _zend_mm_heap zend_mm_heap;
++typedef struct _zend_mm_heap_canary zend_mm_heap_canary;
++
+
+ ZEND_API zend_mm_heap *zend_mm_startup(void);
+ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC);
+diff -Nura php-5.3.6/Zend/zend.c suhosin-patch-5.3.6-0.9.10/Zend/zend.c
+--- php-5.3.6/Zend/zend.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend.c 2011-03-19 10:48:33.790642098 +0100
+@@ -60,6 +60,10 @@
+ ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
+ ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
+
++#if SUHOSIN_PATCH
++ZEND_API void (*zend_suhosin_log)(int loglevel, char *fmt, ...);
++#endif
++
+ void (*zend_on_timeout)(int seconds TSRMLS_DC);
+
+ static void (*zend_message_dispatcher_p)(long message, void *data TSRMLS_DC);
+@@ -88,6 +92,74 @@
+ }
+ /* }}} */
+
++#if SUHOSIN_PATCH
++static ZEND_INI_MH(OnUpdateSuhosin_log_syslog)
++{
++ if (!new_value) {
++ SPG(log_syslog) = S_ALL & ~S_SQL | S_MEMORY;
++ } else {
++ SPG(log_syslog) = atoi(new_value) | S_MEMORY;
++ }
++ return SUCCESS;
++}
++static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_facility)
++{
++ if (!new_value) {
++ SPG(log_syslog_facility) = LOG_USER;
++ } else {
++ SPG(log_syslog_facility) = atoi(new_value);
++ }
++ return SUCCESS;
++}
++static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_priority)
++{
++ if (!new_value) {
++ SPG(log_syslog_priority) = LOG_ALERT;
++ } else {
++ SPG(log_syslog_priority) = atoi(new_value);
++ }
++ return SUCCESS;
++}
++static ZEND_INI_MH(OnUpdateSuhosin_log_sapi)
++{
++ if (!new_value) {
++ SPG(log_sapi) = S_ALL & ~S_SQL;
++ } else {
++ SPG(log_sapi) = atoi(new_value);
++ }
++ return SUCCESS;
++}
++static ZEND_INI_MH(OnUpdateSuhosin_log_script)
++{
++ if (!new_value) {
++ SPG(log_script) = S_ALL & ~S_MEMORY;
++ } else {
++ SPG(log_script) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
++ }
++ return SUCCESS;
++}
++static ZEND_INI_MH(OnUpdateSuhosin_log_scriptname)
++{
++ if (SPG(log_scriptname)) {
++ pefree(SPG(log_scriptname),1);
++ }
++ SPG(log_scriptname) = NULL;
++ if (new_value) {
++ SPG(log_scriptname) = pestrdup(new_value,1);
++ }
++ return SUCCESS;
++}
++static ZEND_INI_MH(OnUpdateSuhosin_log_phpscript)
++{
++ if (!new_value) {
++ SPG(log_phpscript) = S_ALL & ~S_MEMORY;
++ } else {
++ SPG(log_phpscript) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
++ }
++ return SUCCESS;
++}
++#endif
++
+ ZEND_INI_BEGIN()
+ ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
+ STD_ZEND_INI_BOOLEAN("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals)
+diff -Nura php-5.3.6/Zend/zend_canary.c suhosin-patch-5.3.6-0.9.10/Zend/zend_canary.c
+--- php-5.3.6/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_canary.c 2011-03-19 10:48:33.797308698 +0100
+@@ -0,0 +1,66 @@
++/*
++ +----------------------------------------------------------------------+
++ | Suhosin-Patch for PHP |
++ +----------------------------------------------------------------------+
++ | Copyright (c) 2004-2009 Stefan Esser |
++ +----------------------------------------------------------------------+
++ | This source file is subject to version 2.02 of the PHP license, |
++ | that is bundled with this package in the file LICENSE, and is |
++ | available at through the world-wide-web at |
++ | http://www.php.net/license/2_02.txt. |
++ | If you did not receive a copy of the PHP license and are unable to |
++ | obtain it through the world-wide-web, please send a note to |
++ | license@php.net so we can mail you a copy immediately. |
++ +----------------------------------------------------------------------+
++ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
++ +----------------------------------------------------------------------+
++ */
++/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */
++
++#include "zend.h"
++
++#include <stdio.h>
++#include <stdlib.h>
++
++
++#if SUHOSIN_PATCH
++
++static size_t last_canary = 0x73625123;
++
++/* will be replaced later with more compatible method */
++ZEND_API void zend_canary(void *buf, int len)
++{
++ time_t t;
++ size_t canary;
++ int fd;
++
++#ifndef PHP_WIN32
++ fd = open("/dev/urandom", 0);
++ if (fd != -1) {
++ int r = read(fd, buf, len);
++ close(fd);
++ if (r == len) {
++ return;
++ }
++ }
++#endif
++ /* not good but we never want to do this */
++ time(&t);
++ canary = *(unsigned int *)&t + getpid() << 16 + last_canary;
++ last_canary ^= (canary << 5) | (canary >> (32-5));
++ /* When we ensure full win32 compatibility in next version
++ we will replace this with the random number code from zend_alloc.c */
++ memcpy(buf, &canary, len);
++}
++
++#endif
++
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim600: sw=4 ts=4 fdm=marker
++ * vim<600: sw=4 ts=4
++ */
+diff -Nura php-5.3.6/Zend/zend_compile.c suhosin-patch-5.3.6-0.9.10/Zend/zend_compile.c
+--- php-5.3.6/Zend/zend_compile.c 2011-02-18 00:24:50.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_compile.c 2011-03-19 10:48:33.797308698 +0100
+@@ -73,6 +73,11 @@
+ }
+ /* }}} */
+
++#if SUHOSIN_PATCH
++void *suhosin_zend_destroy_property_info_internal = zend_destroy_property_info_internal;
++void *suhosin_zend_destroy_property_info = zend_destroy_property_info;
++#endif
++
+ static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
+ {
+ char char_pos_buf[32];
+diff -Nura php-5.3.6/Zend/zend_compile.h suhosin-patch-5.3.6-0.9.10/Zend/zend_compile.h
+--- php-5.3.6/Zend/zend_compile.h 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_compile.h 2011-03-19 10:48:33.797308698 +0100
+@@ -606,6 +606,11 @@
+ ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC);
+ ZEND_API size_t zend_dirname(char *path, size_t len);
+
++#if SUHOSIN_PATCH
++extern void *suhosin_zend_destroy_property_info_internal;
++extern void *suhosin_zend_destroy_property_info;
++#endif
++
+ int zendlex(znode *zendlval TSRMLS_DC);
+
+ /* BEGIN: OPCODES */
+diff -Nura php-5.3.6/Zend/zend_constants.c suhosin-patch-5.3.6-0.9.10/Zend/zend_constants.c
+--- php-5.3.6/Zend/zend_constants.c 2011-01-16 21:39:22.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_constants.c 2011-03-19 10:48:33.800641998 +0100
+@@ -113,6 +113,76 @@
+
+ REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
+
++#if SUHOSIN_PATCH
++ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_MAIL", S_MAIL, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_SESSION", S_SESSION, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS);
++ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
++
++ /* error levels */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
++ /* facility: type of program logging the message */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
++#ifdef LOG_NEWS
++ /* No LOG_NEWS on HP-UX */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
++#endif
++#ifdef LOG_UUCP
++ /* No LOG_UUCP on HP-UX */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
++#endif
++#ifdef LOG_CRON
++ /* apparently some systems don't have this one */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
++#endif
++#ifdef LOG_AUTHPRIV
++ /* AIX doesn't have LOG_AUTHPRIV */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
++#endif
++#ifndef PHP_WIN32
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
++#endif
++ /* options */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
++ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
++#ifdef LOG_NOWAIT
++ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
++#endif
++#ifdef LOG_PERROR
++ /* AIX doesn't have LOG_PERROR */
++ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
++#endif
++#endif
++
+ REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS);
+ /* true/false constants */
+diff -Nura php-5.3.6/Zend/Zend.dsp suhosin-patch-5.3.6-0.9.10/Zend/Zend.dsp
+--- php-5.3.6/Zend/Zend.dsp 2009-03-18 11:18:10.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/Zend.dsp 2011-03-19 10:48:33.790642098 +0100
+@@ -247,6 +247,14 @@
+ # End Source File
+ # Begin Source File
+
++SOURCE=.\zend_canary.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\zend_alloc_canary.c
++# End Source File
++# Begin Source File
++
+ SOURCE=.\zend_ts_hash.c
+ # End Source File
+ # Begin Source File
+diff -Nura php-5.3.6/Zend/zend_errors.h suhosin-patch-5.3.6-0.9.10/Zend/zend_errors.h
+--- php-5.3.6/Zend/zend_errors.h 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_errors.h 2011-03-19 10:48:33.800641998 +0100
+@@ -41,6 +41,20 @@
+ #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED)
+ #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
+
++#if SUHOSIN_PATCH
++#define S_MEMORY (1<<0L)
++#define S_MISC (1<<1L)
++#define S_VARS (1<<2L)
++#define S_FILES (1<<3L)
++#define S_INCLUDE (1<<4L)
++#define S_SQL (1<<5L)
++#define S_EXECUTOR (1<<6L)
++#define S_MAIL (1<<7L)
++#define S_SESSION (1<<8L)
++#define S_INTERNAL (1<<29L)
++#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MAIL | S_SESSION | S_MISC | S_SQL | S_EXECUTOR)
++#endif
++
+ #endif /* ZEND_ERRORS_H */
+
+ /*
+diff -Nura php-5.3.6/Zend/zend.h suhosin-patch-5.3.6-0.9.10/Zend/zend.h
+--- php-5.3.6/Zend/zend.h 2011-01-16 21:39:22.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend.h 2011-03-19 10:48:33.790642098 +0100
+@@ -627,6 +627,9 @@
+ extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
+ extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
+ extern ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
++#if SUHOSIN_PATCH
++extern ZEND_API void (*zend_suhosin_log)(int loglevel, char *fmt, ...);
++#endif
+
+ ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+
+@@ -774,6 +777,16 @@
+ #define DEBUG_BACKTRACE_PROVIDE_OBJECT (1<<0)
+ #define DEBUG_BACKTRACE_IGNORE_ARGS (1<<1)
+
++#if SUHOSIN_PATCH
++#include "suhosin_globals.h"
++#include "suhosin_patch.h"
++#include "php_syslog.h"
++
++ZEND_API void zend_canary(void *buf, int len);
++ZEND_API char suhosin_get_config(int element);
++
++#endif
++
+ #endif /* ZEND_H */
+
+ /*
+diff -Nura php-5.3.6/Zend/zend_hash.c suhosin-patch-5.3.6-0.9.10/Zend/zend_hash.c
+--- php-5.3.6/Zend/zend_hash.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_hash.c 2011-03-19 10:48:33.800641998 +0100
+@@ -20,6 +20,7 @@
+ /* $Id: zend_hash.c 306939 2011-01-01 02:19:59Z felipe $ */
+
+ #include "zend.h"
++#include "zend_compile.h"
+
+ #define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
+ (element)->pNext = (list_head); \
+@@ -136,6 +137,199 @@
+ }
+
+
++#if SUHOSIN_PATCH
++#ifdef ZTS
++static MUTEX_T zend_hash_dprot_mx_reader;
++static MUTEX_T zend_hash_dprot_mx_writer;
++static unsigned int zend_hash_dprot_reader;
++#endif
++static unsigned int zend_hash_dprot_counter;
++static unsigned int zend_hash_dprot_curmax;
++static dtor_func_t *zend_hash_dprot_table = NULL;
++
++static void zend_hash_dprot_begin_read()
++{
++#ifdef ZTS
++ tsrm_mutex_lock(zend_hash_dprot_mx_reader);
++ if ((++(zend_hash_dprot_reader)) == 1) {
++ tsrm_mutex_lock(zend_hash_dprot_mx_writer);
++ }
++ tsrm_mutex_unlock(zend_hash_dprot_mx_reader);
++#endif
++}
++
++static void zend_hash_dprot_end_read()
++{
++#ifdef ZTS
++ tsrm_mutex_lock(zend_hash_dprot_mx_reader);
++ if ((--(zend_hash_dprot_reader)) == 0) {
++ tsrm_mutex_unlock(zend_hash_dprot_mx_writer);
++ }
++ tsrm_mutex_unlock(zend_hash_dprot_mx_reader);
++#endif
++}
++
++static void zend_hash_dprot_begin_write()
++{
++#ifdef ZTS
++ tsrm_mutex_lock(zend_hash_dprot_mx_writer);
++#endif
++}
++
++static void zend_hash_dprot_end_write()
++{
++#ifdef ZTS
++ tsrm_mutex_unlock(zend_hash_dprot_mx_writer);
++#endif
++}
++
++/*ZEND_API void zend_hash_dprot_dtor()
++{
++#ifdef ZTS
++ tsrm_mutex_free(zend_hash_dprot_mx_reader);
++ tsrm_mutex_free(zend_hash_dprot_mx_writer);
++#endif
++ free(zend_hash_dprot_table);
++}*/
++
++static void zend_hash_add_destructor(dtor_func_t pDestructor)
++{
++ int left, right, mid;
++ zend_bool found = 0;
++ unsigned long value;
++
++ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR
++ || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) {
++ return;
++ }
++
++ if (zend_hash_dprot_table == NULL) {
++#ifdef ZTS
++ zend_hash_dprot_mx_reader = tsrm_mutex_alloc();
++ zend_hash_dprot_mx_writer = tsrm_mutex_alloc();
++ zend_hash_dprot_reader = 0;
++#endif
++ zend_hash_dprot_counter = 0;
++ zend_hash_dprot_curmax = 256;
++ zend_hash_dprot_table = (dtor_func_t *) malloc(256 * sizeof(dtor_func_t));
++ }
++
++ zend_hash_dprot_begin_write();
++
++ if (zend_hash_dprot_counter == 0) {
++ zend_hash_dprot_counter++;
++ zend_hash_dprot_table[0] = pDestructor;
++ } else {
++ value = (unsigned long) pDestructor;
++ left = 0;
++ right = zend_hash_dprot_counter-1;
++ mid = 0;
++
++ while (left < right) {
++ mid = (right - left) >> 1;
++ mid += left;
++ if ((unsigned long)zend_hash_dprot_table[mid] == value) {
++ found = 1;
++ break;
++ }
++ if (value < (unsigned long)zend_hash_dprot_table[mid]) {
++ right = mid-1;
++ } else {
++ left = mid+1;
++ }
++ }
++ if ((unsigned long)zend_hash_dprot_table[left] == value) {
++ found = 1;
++ }
++
++ if (!found) {
++
++ if (zend_hash_dprot_counter >= zend_hash_dprot_curmax) {
++ zend_hash_dprot_curmax += 256;
++ zend_hash_dprot_table = (dtor_func_t *) realloc(zend_hash_dprot_table, zend_hash_dprot_curmax * sizeof(dtor_func_t));
++ }
++
++ if ((unsigned long)zend_hash_dprot_table[left] < value) {
++ memmove(zend_hash_dprot_table+left+2, zend_hash_dprot_table+left+1, (zend_hash_dprot_counter-left-1)*sizeof(dtor_func_t));
++ zend_hash_dprot_table[left+1] = pDestructor;
++ } else {
++ memmove(zend_hash_dprot_table+left+1, zend_hash_dprot_table+left, (zend_hash_dprot_counter-left)*sizeof(dtor_func_t));
++ zend_hash_dprot_table[left] = pDestructor;
++ }
++
++ zend_hash_dprot_counter++;
++ }
++ }
++
++ zend_hash_dprot_end_write();
++}
++
++static void zend_hash_check_destructor(dtor_func_t pDestructor)
++{
++ unsigned long value;
++
++ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR
++#ifdef ZEND_ENGINE_2
++ || pDestructor == suhosin_zend_destroy_property_info_internal || pDestructor == suhosin_zend_destroy_property_info
++#endif
++ || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) {
++ return;
++ }
++
++ zend_hash_dprot_begin_read();
++
++ if (zend_hash_dprot_counter > 0) {
++ int left, right, mid;
++ zend_bool found = 0;
++
++ value = (unsigned long) pDestructor;
++ left = 0;
++ right = zend_hash_dprot_counter-1;
++
++ while (left < right) {
++ mid = (right - left) >> 1;
++ mid += left;
++ if ((unsigned long)zend_hash_dprot_table[mid] == value) {
++ found = 1;
++ break;
++ }
++ if (value < (unsigned long)zend_hash_dprot_table[mid]) {
++ right = mid-1;
++ } else {
++ left = mid+1;
++ }
++ }
++ if ((unsigned long)zend_hash_dprot_table[left] == value) {
++ found = 1;
++ }
++
++ if (!found) {
++ zend_hash_dprot_end_read();
++
++ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor");
++ if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) {
++ _exit(1);
++ }
++ return;
++ }
++
++ } else {
++ zend_hash_dprot_end_read();
++
++ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor");
++ if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) {
++ _exit(1);
++ }
++ return;
++ }
++
++ zend_hash_dprot_end_read();
++}
++
++#else
++#define zend_hash_add_destructor(pDestructor) do {} while(0)
++#define zend_hash_check_destructor(pDestructor) do {} while(0)
++#endif
+
+ ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
+ {
+@@ -156,6 +350,7 @@
+
+ ht->nTableMask = ht->nTableSize - 1;
+ ht->pDestructor = pDestructor;
++ zend_hash_add_destructor(pDestructor);
+ ht->arBuckets = NULL;
+ ht->pListHead = NULL;
+ ht->pListTail = NULL;
+@@ -233,6 +428,7 @@
+ return FAILURE;
+ }
+ #endif
++ zend_hash_check_destructor(ht->pDestructor);
+ if (ht->pDestructor) {
+ ht->pDestructor(p->pData);
+ }
+@@ -298,6 +494,7 @@
+ return FAILURE;
+ }
+ #endif
++ zend_hash_check_destructor(ht->pDestructor);
+ if (ht->pDestructor) {
+ ht->pDestructor(p->pData);
+ }
+@@ -373,6 +570,7 @@
+ return FAILURE;
+ }
+ #endif
++ zend_hash_check_destructor(ht->pDestructor);
+ if (ht->pDestructor) {
+ ht->pDestructor(p->pData);
+ }
+@@ -496,6 +694,7 @@
+ if (ht->pInternalPointer == p) {
+ ht->pInternalPointer = p->pListNext;
+ }
++ zend_hash_check_destructor(ht->pDestructor);
+ if (ht->pDestructor) {
+ ht->pDestructor(p->pData);
+ }
+@@ -522,6 +721,7 @@
+ SET_INCONSISTENT(HT_IS_DESTROYING);
+
+ p = ht->pListHead;
++ zend_hash_check_destructor(ht->pDestructor);
+ while (p != NULL) {
+ q = p;
+ p = p->pListNext;
+@@ -548,6 +748,7 @@
+ SET_INCONSISTENT(HT_CLEANING);
+
+ p = ht->pListHead;
++ zend_hash_check_destructor(ht->pDestructor);
+ while (p != NULL) {
+ q = p;
+ p = p->pListNext;
+@@ -610,6 +811,7 @@
+ ht->nNumOfElements--;
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+
++ zend_hash_check_destructor(ht->pDestructor);
+ if (ht->pDestructor) {
+ ht->pDestructor(p->pData);
+ }
+diff -Nura php-5.3.6/Zend/zend_llist.c suhosin-patch-5.3.6-0.9.10/Zend/zend_llist.c
+--- php-5.3.6/Zend/zend_llist.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_llist.c 2011-03-19 10:48:33.800641998 +0100
+@@ -23,6 +23,194 @@
+ #include "zend_llist.h"
+ #include "zend_qsort.h"
+
++#if SUHOSIN_PATCH
++#ifdef ZTS
++static MUTEX_T zend_llist_dprot_mx_reader;
++static MUTEX_T zend_llist_dprot_mx_writer;
++static unsigned int zend_llist_dprot_reader;
++#endif
++static unsigned int zend_llist_dprot_counter;
++static unsigned int zend_llist_dprot_curmax;
++static llist_dtor_func_t *zend_llist_dprot_table = NULL;
++
++static void zend_llist_dprot_begin_read()
++{
++#ifdef ZTS
++ tsrm_mutex_lock(zend_llist_dprot_mx_reader);
++ if ((++(zend_llist_dprot_reader)) == 1) {
++ tsrm_mutex_lock(zend_llist_dprot_mx_writer);
++ }
++ tsrm_mutex_unlock(zend_llist_dprot_mx_reader);
++#endif
++}
++
++static void zend_llist_dprot_end_read()
++{
++#ifdef ZTS
++ tsrm_mutex_lock(zend_llist_dprot_mx_reader);
++ if ((--(zend_llist_dprot_reader)) == 0) {
++ tsrm_mutex_unlock(zend_llist_dprot_mx_writer);
++ }
++ tsrm_mutex_unlock(zend_llist_dprot_mx_reader);
++#endif
++}
++
++static void zend_llist_dprot_begin_write()
++{
++#ifdef ZTS
++ tsrm_mutex_lock(zend_llist_dprot_mx_writer);
++#endif
++}
++
++static void zend_llist_dprot_end_write()
++{
++#ifdef ZTS
++ tsrm_mutex_unlock(zend_llist_dprot_mx_writer);
++#endif
++}
++
++/*ZEND_API void zend_llist_dprot_dtor()
++{
++#ifdef ZTS
++ tsrm_mutex_free(zend_llist_dprot_mx_reader);
++ tsrm_mutex_free(zend_llist_dprot_mx_writer);
++#endif
++ free(zend_llist_dprot_table);
++}*/
++
++static void zend_llist_add_destructor(llist_dtor_func_t pDestructor)
++{
++ int left, right, mid;
++ zend_bool found = 0;
++ unsigned long value;
++
++ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR) {
++ return;
++ }
++
++ if (zend_llist_dprot_table == NULL) {
++#ifdef ZTS
++ zend_llist_dprot_mx_reader = tsrm_mutex_alloc();
++ zend_llist_dprot_mx_writer = tsrm_mutex_alloc();
++ zend_llist_dprot_reader = 0;
++#endif
++ zend_llist_dprot_counter = 0;
++ zend_llist_dprot_curmax = 256;
++ zend_llist_dprot_table = (llist_dtor_func_t *) malloc(256 * sizeof(llist_dtor_func_t));
++ }
++
++ zend_llist_dprot_begin_write();
++
++ if (zend_llist_dprot_counter == 0) {
++ zend_llist_dprot_counter++;
++ zend_llist_dprot_table[0] = pDestructor;
++ } else {
++ value = (unsigned long) pDestructor;
++ left = 0;
++ right = zend_llist_dprot_counter-1;
++ mid = 0;
++
++ while (left < right) {
++ mid = (right - left) >> 1;
++ mid += left;
++ if ((unsigned long)zend_llist_dprot_table[mid] == value) {
++ found = 1;
++ break;
++ }
++ if (value < (unsigned long)zend_llist_dprot_table[mid]) {
++ right = mid-1;
++ } else {
++ left = mid+1;
++ }
++ }
++ if ((unsigned long)zend_llist_dprot_table[left] == value) {
++ found = 1;
++ }
++
++ if (!found) {
++
++ if (zend_llist_dprot_counter >= zend_llist_dprot_curmax) {
++ zend_llist_dprot_curmax += 256;
++ zend_llist_dprot_table = (llist_dtor_func_t *) realloc(zend_llist_dprot_table, zend_llist_dprot_curmax * sizeof(llist_dtor_func_t));
++ }
++
++ if ((unsigned long)zend_llist_dprot_table[left] < value) {
++ memmove(zend_llist_dprot_table+left+2, zend_llist_dprot_table+left+1, (zend_llist_dprot_counter-left-1)*sizeof(llist_dtor_func_t));
++ zend_llist_dprot_table[left+1] = pDestructor;
++ } else {
++ memmove(zend_llist_dprot_table+left+1, zend_llist_dprot_table+left, (zend_llist_dprot_counter-left)*sizeof(llist_dtor_func_t));
++ zend_llist_dprot_table[left] = pDestructor;
++ }
++
++ zend_llist_dprot_counter++;
++ }
++ }
++
++ zend_llist_dprot_end_write();
++}
++
++static void zend_llist_check_destructor(llist_dtor_func_t pDestructor)
++{
++ unsigned long value;
++
++ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR) {
++ return;
++ }
++
++ zend_llist_dprot_begin_read();
++
++ if (zend_llist_dprot_counter > 0) {
++ int left, right, mid;
++ zend_bool found = 0;
++
++ value = (unsigned long) pDestructor;
++ left = 0;
++ right = zend_llist_dprot_counter-1;
++
++ while (left < right) {
++ mid = (right - left) >> 1;
++ mid += left;
++ if ((unsigned long)zend_llist_dprot_table[mid] == value) {
++ found = 1;
++ break;
++ }
++ if (value < (unsigned long)zend_llist_dprot_table[mid]) {
++ right = mid-1;
++ } else {
++ left = mid+1;
++ }
++ }
++ if ((unsigned long)zend_llist_dprot_table[left] == value) {
++ found = 1;
++ }
++
++ if (!found) {
++ zend_llist_dprot_end_read();
++
++ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown llist destructor");
++ if (SUHOSIN_CONFIG(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR) == 0) {
++ _exit(1);
++ }
++ return;
++ }
++
++ } else {
++ zend_llist_dprot_end_read();
++
++ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown llist destructor");
++ if (SUHOSIN_CONFIG(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR) == 0) {
++ _exit(1);
++ }
++ return;
++ }
++
++ zend_llist_dprot_end_read();
++}
++#else
++#define zend_llist_add_destructor(pDestructor) do {} while(0)
++#define zend_llist_check_destructor(pDestructor) do {} while(0)
++#endif
++
+ ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
+ {
+ l->head = NULL;
+@@ -30,6 +218,7 @@
+ l->count = 0;
+ l->size = size;
+ l->dtor = dtor;
++ zend_llist_add_destructor(dtor);
+ l->persistent = persistent;
+ }
+
+@@ -81,6 +270,7 @@
+ } else {\
+ (l)->tail = (current)->prev;\
+ }\
++ zend_llist_check_destructor((l)->dtor); \
+ if ((l)->dtor) {\
+ (l)->dtor((current)->data);\
+ }\
+@@ -108,6 +298,7 @@
+ {
+ zend_llist_element *current=l->head, *next;
+
++ zend_llist_check_destructor(l->dtor);
+ while (current) {
+ next = current->next;
+ if (l->dtor) {
+@@ -133,6 +324,7 @@
+ zend_llist_element *old_tail;
+ void *data;
+
++ zend_llist_check_destructor((l)->dtor);
+ if ((old_tail = l->tail)) {
+ if (old_tail->prev) {
+ old_tail->prev->next = NULL;
+diff -Nura php-5.3.6/Zend/zend_operators.c suhosin-patch-5.3.6-0.9.10/Zend/zend_operators.c
+--- php-5.3.6/Zend/zend_operators.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_operators.c 2011-03-19 10:48:33.800641998 +0100
+@@ -153,9 +153,14 @@
+ case IS_STRING:
+ {
+ char *strval;
++ int strl;
+
+ strval = Z_STRVAL_P(op);
+- if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
++ strl = Z_STRLEN_P(op);
++#if SUHOSIN_PATCH
++ Z_STRLEN_P(op) = 0;
++#endif
++ if ((Z_TYPE_P(op)=is_numeric_string(strval, strl, &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
+ ZVAL_LONG(op, 0);
+ }
+ STR_FREE(strval);
+@@ -187,7 +192,8 @@
+ } else { \
+ switch (Z_TYPE_P(op)) { \
+ case IS_STRING: \
+- { \
++ { \
++ Z_STRLEN(holder) = 0; \
+ if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \
+ ZVAL_LONG(&(holder), 0); \
+ } \
+@@ -229,6 +235,7 @@
+ Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \
+ break; \
+ case IS_STRING: \
++ Z_STRLEN(holder) = 0; \
+ Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \
+ break; \
+ case IS_ARRAY: \
+@@ -271,6 +278,7 @@
+ Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \
+ break; \
+ case IS_STRING: \
++ Z_STRLEN(holder) = 0; \
+ if (Z_STRLEN_P(op) == 0 \
+ || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
+ Z_LVAL(holder) = 0; \
+@@ -356,6 +364,9 @@
+ {
+ char *strval = Z_STRVAL_P(op);
+
++#if SUHOSIN_PATCH
++ Z_STRLEN_P(op) = 0;
++#endif
+ Z_LVAL_P(op) = strtol(strval, NULL, base);
+ STR_FREE(strval);
+ }
+@@ -416,6 +427,9 @@
+ {
+ char *strval = Z_STRVAL_P(op);
+
++#if SUHOSIN_PATCH
++ Z_STRLEN_P(op) = 0;
++#endif
+ Z_DVAL_P(op) = zend_strtod(strval, NULL);
+ STR_FREE(strval);
+ }
+@@ -502,8 +516,14 @@
+
+ if (Z_STRLEN_P(op) == 0
+ || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
++#if SUHOSIN_PATCH
++ Z_STRLEN_P(op) = 0;
++#endif
+ Z_LVAL_P(op) = 0;
+ } else {
++#if SUHOSIN_PATCH
++ Z_STRLEN_P(op) = 0;
++#endif
+ Z_LVAL_P(op) = 1;
+ }
+ STR_FREE(strval);
+@@ -617,6 +637,9 @@
+ *entry = *op;
+ INIT_PZVAL(entry);
+
++#if SUHOSIN_PATCH
++ Z_STRLEN_P(op) = 0;
++#endif
+ switch (type) {
+ case IS_ARRAY:
+ ALLOC_HASHTABLE(Z_ARRVAL_P(op));
+diff -Nura php-5.3.6/Zend/ZendTS.dsp suhosin-patch-5.3.6-0.9.10/Zend/ZendTS.dsp
+--- php-5.3.6/Zend/ZendTS.dsp 2008-07-14 11:49:03.000000000 +0200
++++ suhosin-patch-5.3.6-0.9.10/Zend/ZendTS.dsp 2011-03-19 10:48:33.790642098 +0100
+@@ -277,6 +277,14 @@
+ # End Source File
+ # Begin Source File
+
++SOURCE=.\zend_canary.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\zend_alloc_canary.c
++# End Source File
++# Begin Source File
++
+ SOURCE=.\zend_ts_hash.c
+ # End Source File
+ # Begin Source File
+diff -Nura php-5.3.6/Zend/zend_variables.c suhosin-patch-5.3.6-0.9.10/Zend/zend_variables.c
+--- php-5.3.6/Zend/zend_variables.c 2011-01-01 03:19:59.000000000 +0100
++++ suhosin-patch-5.3.6-0.9.10/Zend/zend_variables.c 2011-03-19 10:48:33.800641998 +0100
+@@ -34,6 +34,9 @@
+ case IS_CONSTANT:
+ CHECK_ZVAL_STRING_REL(zvalue);
+ STR_FREE_REL(zvalue->value.str.val);
++#if SUHOSIN_PATCH
++ zvalue->value.str.len = 0;
++#endif
+ break;
+ case IS_ARRAY:
+ case IS_CONSTANT_ARRAY: {
+@@ -78,6 +81,9 @@
+ case IS_CONSTANT:
+ CHECK_ZVAL_STRING_REL(zvalue);
+ free(zvalue->value.str.val);
++#if SUHOSIN_PATCH
++ zvalue->value.str.len = 0;
++#endif
+ break;
+ case IS_ARRAY:
+ case IS_CONSTANT_ARRAY:
diff --git a/main/phpmyadmin/APKBUILD b/main/phpmyadmin/APKBUILD
new file mode 100644
index 0000000000..113a70de35
--- /dev/null
+++ b/main/phpmyadmin/APKBUILD
@@ -0,0 +1,88 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=phpmyadmin
+pkgver=3.3.10
+pkgrel=2
+pkgdesc="A Web-based PHP tool for administering MySQL"
+url="http://www.phpmyadmin.net/"
+arch="noarch"
+license="GPL"
+depends="php php-mysql php-zip php-zlib php-bz2 php-ctype php-gd php-mcrypt mysql"
+depends_dev=
+makedepends="$depends_dev"
+install="$pkgname.post-install"
+subpackages="$pkgname-doc"
+_fullpkgname=phpMyAdmin-$pkgver-all-languages
+source="http://downloads.sourceforge.net/$pkgname/$_fullpkgname.tar.gz
+ $pkgname.apache2.conf
+ "
+
+_builddir="$srcdir"/$_fullpkgname
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/share/webapps/$pkgname \
+ "$pkgdir"/etc/$pkgname \
+ || return 1
+
+ # copy phpmyadmin
+ cp -ra "$_builddir"/* "$pkgdir"/usr/share/webapps/$pkgname/ \
+ || return 1
+
+ # install the sample config
+ install -m660 \
+ "$pkgdir"/usr/share/webapps/$pkgname/config.sample.inc.php \
+ "$pkgdir"/etc/$pkgname/config.inc.php \
+ || return 1
+ ln -fs /etc/$pkgname/config.inc.php \
+ "$pkgdir"/usr/share/webapps/$pkgname/config.inc.php \
+ || return 1
+
+ # install the apache2 config
+ install -Dm644 "$srcdir"/$pkgname.apache2.conf \
+ "$pkgdir"/etc/apache2/conf.d/$pkgname.conf || return 1
+
+ # copy some contribs over
+ mkdir -p "$pkgdir"/usr/share/$pkgname/contrib || return 1
+ _contribs="htaccess swekey.sample.conf"
+ for _contrib in $_contribs; do
+ mv "$pkgdir"/usr/share/webapps/$pkgname/contrib/$_contrib \
+ "$pkgdir"/usr/share/$pkgname/contrib/ \
+ || return 1
+ done
+ rm -rf "$pkgdir"/usr/share/webapps/$pkgname/contrib || return 1
+
+ # copy sample config
+ mv "$pkgdir"/usr/share/webapps/$pkgname/config.sample.inc.php \
+ "$pkgdir"/usr/share/$pkgname/ || return 1
+}
+
+doc() {
+ cd "$_builddir"
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname || return 1
+
+ _docs="CREDITS ChangeLog Documentation.html Documentation.txt \
+ INSTALL LICENSE README README.VENDOR RELEASE-DATE-$pkgver \
+ TODO translators.html documentation-gsoc"
+ for _doc in $_docs; do
+ mv "$pkgdir"/usr/share/webapps/$pkgname/$_doc \
+ "$subpkgdir"/usr/share/doc/$pkgname/ \
+ || return 1
+ done
+}
+
+md5sums="2e93375a92a86ef36e561b0087f6b8e3 phpMyAdmin-3.3.10-all-languages.tar.gz
+2d144825122042b4a2536ad789d66e8e phpmyadmin.apache2.conf"
diff --git a/main/phpmyadmin/phpmyadmin.apache2.conf b/main/phpmyadmin/phpmyadmin.apache2.conf
new file mode 100644
index 0000000000..1c1a5f6498
--- /dev/null
+++ b/main/phpmyadmin/phpmyadmin.apache2.conf
@@ -0,0 +1,7 @@
+Alias /phpmyadmin "/usr/share/webapps/phpmyadmin"
+<Directory "/usr/share/webapps/phpmyadmin">
+ AllowOverride All
+ Options FollowSymlinks
+ Order allow,deny
+ Allow from all
+</Directory>
diff --git a/main/phpmyadmin/phpmyadmin.post-install b/main/phpmyadmin/phpmyadmin.post-install
new file mode 100644
index 0000000000..e3dbc3524a
--- /dev/null
+++ b/main/phpmyadmin/phpmyadmin.post-install
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+echo "*" >&2
+echo "* phpmyadmin has been installed to:" >&2
+echo "* /usr/share/webapps/phpmyadmin" >&2
+echo "* phpmyadmin config file has been installed to:" >&2
+echo "* /etc/phpmyadmin/config.inc.php" >&2
+echo "* If you use apache2:" >&2
+echo "* 1) Change the ownership of the config directory:" >&2
+echo "* chown -R apache:apache /etc/phpmyadmin" >&2
+echo "* 2) See if you need to modify the apache2 config:" >&2
+echo "* /etc/apache2/conf.d/phpmyadmin.conf" >&2
+echo "* 3) Restart apache2 when done." >&2
+echo "*" >&2
+
+exit 0
diff --git a/main/pianobar/APKBUILD b/main/pianobar/APKBUILD
new file mode 100644
index 0000000000..b55d0b672d
--- /dev/null
+++ b/main/pianobar/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=pianobar
+pkgver=2011.04.27
+pkgrel=0
+pkgdesc="commandline player for pandora webradio"
+url="https://github.com/PromyLOPh/pianobar"
+arch="all"
+license="MIT"
+depends=
+depends_dev="faad2-dev libmad-dev libao-dev"
+makedepends="$depends_dev wget"
+install=""
+subpackages="$pkgname-doc"
+source="saveas-https://github.com/PromyLOPh/pianobar/tarball/${pkgver}/pianobar-${pkgver}.tar.gz"
+
+_builddir="${srcdir}/PromyLOPh-pianobar-ab5b89a"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make CC='gcc -std=c99' PREFIX="/usr" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" PREFIX="/usr" install || return 1
+}
+
+md5sums="344d4c6957198357bf263629650f0597 pianobar-2011.04.27.tar.gz"
diff --git a/main/pidgin/APKBUILD b/main/pidgin/APKBUILD
new file mode 100644
index 0000000000..d32a2107a2
--- /dev/null
+++ b/main/pidgin/APKBUILD
@@ -0,0 +1,63 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pidgin
+pkgver=2.9.0
+pkgrel=0
+pkgdesc="graphical multi-protocol instant messaging client for X"
+url="http://pidgin.im/"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+-dev intltool libsm-dev startup-notification-dev gtkspell-dev
+ libxml2-dev gstreamer-dev libidn-dev dbus-glib-dev gnutls-dev
+ cyrus-sasl-dev ncurses-dev nss-dev"
+subpackages="$pkgname-dev $pkgname-doc finch libpurple"
+source="http://downloads.sourceforge.net/pidgin/pidgin-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-avahi \
+ --disable-doxygen \
+ --disable-gnutls \
+ --disable-meanwhile \
+ --disable-nm \
+ --disable-perl \
+ --disable-schemas-install \
+ --disable-screensaver \
+ --disable-tcl \
+ --disable-vv \
+ --enable-cyrus-sasl \
+ --enable-nss \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ find "$pkgdir" -name '*.la' -delete
+}
+
+finch() {
+ pkgdesc="text-based multi-protocol instant messaging client"
+ mkdir -p "$subpkgdir"/usr/lib "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/lib/gnt "$pkgdir"/usr/lib/libgnt.so.* \
+ "$pkgdir"/usr/lib/finch \
+ "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/bin/finch "$subpkgdir"/usr/bin/
+}
+
+libpurple() {
+ pkgdesc="multi-protocol instant messaging library"
+ mkdir -p "$subpkgdir"/usr/lib "$subpkgdir"/usr/share/sounds
+ mv "$pkgdir"/usr/lib/*purple* "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/share/purple "$pkgdir"/usr/share/sounds \
+ "$subpkgdir"/usr/share/
+}
+md5sums="2cd285c7a40f93b7a51bfe733971d3a6 pidgin-2.9.0.tar.bz2"
diff --git a/main/pinentry/APKBUILD b/main/pinentry/APKBUILD
new file mode 100644
index 0000000000..8bbcf541a4
--- /dev/null
+++ b/main/pinentry/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pinentry
+pkgver=0.8.1
+pkgrel=0
+pkgdesc="Collection of simple PIN or passphrase entry dialogs which utilize the Assuan protocol"
+url="http://www.gnupg.org/aegypten2"
+arch="all"
+license="GPL-2"
+depends=
+install="pinentry.post-install pinentry.post-deinstall"
+makedepends="ncurses-dev libcap-dev gtk+-dev"
+subpackages="$pkgname-doc $pkgname-gtk"
+source="ftp://ftp.gnupg.org/gcrypt/$pkgname/$pkgname-$pkgver.tar.gz
+ "
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-pinentry-gtk \
+ --enable-pinentry-gtk2 \
+ --disable-pinentry-qt \
+ --enable-pinentry-curses \
+ --enable-pinentry-gtk2 \
+ --enable-fallback-curses
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ # created by post install scripts so we can override with gtk version
+ rm -f "$pkgdir"/usr/bin/pinentry
+}
+
+gtk() {
+ install="pinentry-gtk.post-install pinentry-gtk.post-deinstall"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/pinentry-gtk* "$subpkgdir"/usr/bin/
+}
+
+md5sums="81f99904daee5331eb6738408bb024b6 pinentry-0.8.1.tar.gz"
diff --git a/main/pinentry/pinentry-gtk.post-deinstall b/main/pinentry/pinentry-gtk.post-deinstall
new file mode 100644
index 0000000000..887ef798ae
--- /dev/null
+++ b/main/pinentry/pinentry-gtk.post-deinstall
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+if [ -f /usr/bin/pinentry-curses ]; then
+ ln -sf pinentry-curses /usr/bin/pinentry
+else
+ rm -f /usr/bin/pinentry
+fi
+
diff --git a/main/pinentry/pinentry-gtk.post-install b/main/pinentry/pinentry-gtk.post-install
new file mode 100644
index 0000000000..8b51ca005f
--- /dev/null
+++ b/main/pinentry/pinentry-gtk.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+ln -sf pinentry-gtk-2 /usr/bin/pinentry
+
diff --git a/main/pinentry/pinentry.post-deinstall b/main/pinentry/pinentry.post-deinstall
new file mode 100644
index 0000000000..38939e5b49
--- /dev/null
+++ b/main/pinentry/pinentry.post-deinstall
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if ! [ -f /usr/bin/pinentry-gtk-2 ]; then
+ rm -f /usr/bin/pinentry
+fi
+
diff --git a/main/pinentry/pinentry.post-install b/main/pinentry/pinentry.post-install
new file mode 100644
index 0000000000..0dfd31e955
--- /dev/null
+++ b/main/pinentry/pinentry.post-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if ! [ -f /usr/bin/pinentry-gtk-2 ]; then
+ ln -sf pinentry-curses /usr/bin/pinentry
+fi
+
diff --git a/main/pingu/APKBUILD b/main/pingu/APKBUILD
new file mode 100644
index 0000000000..9101c42776
--- /dev/null
+++ b/main/pingu/APKBUILD
@@ -0,0 +1,25 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pingu
+pkgver=0.5
+pkgrel=2
+pkgdesc="Small daemon that pings hosts and executes a script when status change"
+url="http://git.alpinelinux.org/cgit/pingu"
+arch="all"
+license="GPL"
+depends=
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2
+ pingu.initd
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make || return 1
+ make BINDIR=/usr/sbin DESTDIR="$pkgdir" install
+ install -m644 -D pingu.conf "$pkgdir"/etc/pingu/pingu.conf
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+
+md5sums="cd3cba6df527528eb035691b513e4dd1 pingu-0.5.tar.bz2
+318110763cc8ba23a61455d16cb23f97 pingu.initd"
diff --git a/main/pingu/pingu.initd b/main/pingu/pingu.initd
new file mode 100644
index 0000000000..7f9518efce
--- /dev/null
+++ b/main/pingu/pingu.initd
@@ -0,0 +1,28 @@
+#!/sbin/runscript
+
+# Sample init.d file for alpine linux.
+
+NAME=pingu
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet \
+ --pidfile /var/run/${NAME}.pid \
+ --exec ${DAEMON} -- -d
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --exec ${DAEMON} \
+ --pidfile /var/run/${NAME}.pid
+ eend $?
+}
+
diff --git a/main/pixman/APKBUILD b/main/pixman/APKBUILD
new file mode 100644
index 0000000000..707a383a7c
--- /dev/null
+++ b/main/pixman/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pixman
+pkgver=0.22.0
+pkgrel=2
+pkgdesc="Pixman library"
+url="http://xorg.freedesktop.org"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev"
+depends=
+makedepends="perl"
+source="http://xorg.freedesktop.org/releases/individual/lib/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="307fe4d7dc83b1a558c362907097c0d0 pixman-0.22.0.tar.bz2"
diff --git a/main/pjproject/APKBUILD b/main/pjproject/APKBUILD
new file mode 100644
index 0000000000..a807ebf672
--- /dev/null
+++ b/main/pjproject/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pjproject
+pkgver=1.10
+pkgrel=0
+pkgdesc="CLI Softphone"
+url="http://www.pjsip.org/pjsua.htm"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev pth-dev"
+install=
+subpackages="$pkgname-dev pjsua"
+source="http://www.pjsip.org/release/$pkgver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --build=${CHOST:-i486-alpine-linux-uclibc} \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make -j1 dep || return 1
+ make -j1 all || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" prefix=/usr install
+}
+
+pjsua() {
+ pkgdesc="pjsua is an open source command line SIP user agent (softphone)"
+ cd "$srcdir/$pkgname-$pkgver"/pjsip-apps/bin/
+ install -D -m755 pjsua-${CHOST:-i486-alpine-linux-uclibc} \
+ "$subpkgdir"/usr/bin/pjsua
+}
+
+
+md5sums="e215d0637d3422d49a63c2cde6673951 pjproject-1.10.tar.bz2"
diff --git a/main/pkgconfig/APKBUILD b/main/pkgconfig/APKBUILD
new file mode 100644
index 0000000000..29c446d98a
--- /dev/null
+++ b/main/pkgconfig/APKBUILD
@@ -0,0 +1,20 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pkgconfig
+pkgver=0.23
+pkgrel=2
+pkgdesc="A system for managing library compile/link flags"
+url="http://pkgconfig.freedesktop.org/wiki/"
+arch="all"
+license="GPL"
+depends=
+source="http://$pkgname.freedesktop.org/releases/pkg-config-$pkgver.tar.gz"
+subpackages="$pkgname-doc"
+
+build ()
+{
+ cd "$srcdir"/pkg-config-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+ make DESTDIR="$pkgdir" install
+}
+md5sums="d922a88782b64441d06547632fd85744 pkg-config-0.23.tar.gz"
diff --git a/main/pllua/APKBUILD b/main/pllua/APKBUILD
new file mode 100644
index 0000000000..ed16427496
--- /dev/null
+++ b/main/pllua/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=pllua
+pkgver=0.3.1
+pkgrel=0
+pkgdesc="Procedural language for PostgreSQL using Lua"
+url="http://pgfoundry.org/projects/pllua"
+arch="all"
+license="GPL"
+depends="postgresql"
+makedepends="postgresql-dev lua-dev ccache"
+install=
+subpackages=""
+source="http://pgfoundry.org/frs/download.php/1722/$pkgname-$pkgver.tar.gz
+ pllua-01-0.3.1-include.patch"
+
+# append extra dependencies to -dev subpackage
+# remove if not used.
+# depends_dev="somepackage-dev"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in "$srcdir"/*.patch; do
+ msg "Applying ${i}"
+ patch -p1 -i $i || return 1
+ done
+
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+ # remove the 2 lines below (and this) if there is no init.d script
+ # install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ # install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="e57385bdf2d533ac73cd02401795cea8 pllua-0.3.1.tar.gz
+a47387e64b7dba8d58237c7dad0e2d61 pllua-01-0.3.1-include.patch"
diff --git a/main/pllua/pllua-01-0.3.1-include.patch b/main/pllua/pllua-01-0.3.1-include.patch
new file mode 100644
index 0000000000..afbf8a9845
--- /dev/null
+++ b/main/pllua/pllua-01-0.3.1-include.patch
@@ -0,0 +1,14 @@
+#most of fix from here http://postgis.refractions.net/pipermail/postgis-devel/2009-February/004879.html
+--- pllua-0.3.1/plluaapi.c.orig Thu Sep 17 15:34:07 2009
++++ pllua-0.3.1/plluaapi.c Thu Sep 17 15:34:18 2009
+@@ -7,6 +7,10 @@
+
+ #include "pllua.h"
+ #include "rowstamp.h"
++#include "utils/guc.h"
++extern Datum textout (PG_FUNCTION_ARGS);
++extern Datum bpcharout(PG_FUNCTION_ARGS);
++extern Datum varcharout(PG_FUNCTION_ARGS);
+
+ /* extended function info */
+ typedef struct luaP_Info {
diff --git a/main/pmacct/APKBUILD b/main/pmacct/APKBUILD
new file mode 100644
index 0000000000..88143df374
--- /dev/null
+++ b/main/pmacct/APKBUILD
@@ -0,0 +1,64 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=pmacct
+pkgver=0.12.5
+pkgrel=0
+pkgdesc="Measure, account, classify, aggregate and export IPv4 and IPv6 traffic"
+url="http://www.pmacct.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends="libpcap-dev libpq postgresql-dev zlib-dev"
+install="$pkgname.post-install $pkgname.post-deinstall"
+subpackages="$pkgname-doc"
+source="http://www.pmacct.net/$pkgname-$pkgver.tar.gz
+ pmacct.initd
+ pmacct.confd
+ pmacctd.conf
+ sfacctd.conf
+ nfacctd.conf
+ uacctd.conf"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+#prepare() {
+# cd "$_builddir"
+# apply patches here
+#}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-pgsql \
+ --enable-64bit \
+ --enable-threads \
+ --enable-ulog
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/pmacctd
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/pmacctd
+ install -m644 -D "$srcdir"/pmacctd.conf "$pkgdir"/etc/pmacctd.conf
+ install -m644 -D "$srcdir"/nfacctd.conf "$pkgdir"/etc/nfacctd.conf
+ install -m644 -D "$srcdir"/sfacctd.conf "$pkgdir"/etc/sfacctd.conf
+ install -m644 -D "$srcdir"/uacctd.conf "$pkgdir"/etc/uacctd.conf
+ mkdir -p $pkgdir/usr/share/doc/pmacct/examples
+ mkdir -p $pkgdir/usr/share/doc/pmacct/sql
+ cp examples/* $pkgdir/usr/share/doc/pmacct/examples
+ cp sql/README.* $pkgdir/usr/share/doc/pmacct
+ cp sql/* $pkgdir/usr/share/doc/pmacct/sql
+}
+
+md5sums="3d10f9301a17f034a0f221490a99a5d0 pmacct-0.12.5.tar.gz
+8ebf022a90bb795e6726fee4065bd386 pmacct.initd
+394bf0687572261e90eecd70c33c8ede pmacct.confd
+ecb85e4f9bcb1f6ef0ee1426f979be2b pmacctd.conf
+7a549e51959946805a0c1d094213f08c sfacctd.conf
+a3b1c231911f9bab7bfa73dbbcb308eb nfacctd.conf
+7a549e51959946805a0c1d094213f08c uacctd.conf"
diff --git a/main/pmacct/nfacctd.conf b/main/pmacct/nfacctd.conf
new file mode 100644
index 0000000000..47397d9076
--- /dev/null
+++ b/main/pmacct/nfacctd.conf
@@ -0,0 +1,11 @@
+! Sample default config file
+
+daemonize: true
+pidfile: /var/run/pmacctd.pid
+syslog: daemon
+
+! sql_host: localhost
+! sql_passwd:pmacct
+! sql_table_version: 7
+
+! plugins: pgsql
diff --git a/main/pmacct/pmacct.confd b/main/pmacct/pmacct.confd
new file mode 100644
index 0000000000..c6557c8074
--- /dev/null
+++ b/main/pmacct/pmacct.confd
@@ -0,0 +1,7 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-analyzer/pmacct/files/pmacctd-conf.d,v 1.3 2007/03/28 21:17:57 cedk Exp $
+
+# Other options to pass to pmacctd
+#OPTS=""
+
diff --git a/main/pmacct/pmacct.initd b/main/pmacct/pmacct.initd
new file mode 100644
index 0000000000..e6e6a3f651
--- /dev/null
+++ b/main/pmacct/pmacct.initd
@@ -0,0 +1,30 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-analyzer/pmacct/files/$SVCNAME-init.d,v 1.4 2009/06/01 09:48:41 pva Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+checkconfig() {
+ if [ ! -e /etc/$SVCNAME.conf ] ; then
+ eerror "You need an /etc/$SVCNAME.conf file to run $SVCNAME"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting $SVCNAME"
+ start-stop-daemon --start --pidfile /var/run/$SVCNAME.pid --exec /usr/sbin/$SVCNAME \
+ -- -D -f /etc/$SVCNAME.conf -F /var/run/$SVCNAME.pid ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping $SVCNAME"
+ start-stop-daemon --stop --pidfile /var/run/$SVCNAME.pid --exec /usr/sbin/$SVCNAME
+ eend $?
+}
diff --git a/main/pmacct/pmacct.post-deinstall b/main/pmacct/pmacct.post-deinstall
new file mode 100755
index 0000000000..327b1ce74c
--- /dev/null
+++ b/main/pmacct/pmacct.post-deinstall
@@ -0,0 +1,4 @@
+#!/bin/sh
+rm /etc/init.d/nfacctd &>/dev/null
+rm /etc/init.d/sfacctd &>/dev/null
+rm /etc/init.d/uacctd &>/dev/null
diff --git a/main/pmacct/pmacct.post-install b/main/pmacct/pmacct.post-install
new file mode 100644
index 0000000000..9fd02c4b10
--- /dev/null
+++ b/main/pmacct/pmacct.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+ln -s /etc/init.d/pmacctd /etc/init.d/nfacctd &>/dev/null
+ln -s /etc/init.d/pmacctd /etc/init.d/sfacctd &>/dev/null
+ln -s /etc/init.d/pmacctd /etc/init.d/uacctd &>/dev/null
diff --git a/main/pmacct/pmacctd.conf b/main/pmacct/pmacctd.conf
new file mode 100644
index 0000000000..d64189ede4
--- /dev/null
+++ b/main/pmacct/pmacctd.conf
@@ -0,0 +1,11 @@
+! Sample configuration file
+
+daemonize: true
+pidfile: /var/run/pmacctd.pid
+syslog: daemon
+
+! sql_host: localhost
+! sql_passwd:pmacct
+! sql_table_version: 7
+
+! plugins: pgsql
diff --git a/main/pmacct/sfacctd.conf b/main/pmacct/sfacctd.conf
new file mode 100644
index 0000000000..d175e31134
--- /dev/null
+++ b/main/pmacct/sfacctd.conf
@@ -0,0 +1,9 @@
+daemonize: true
+pidfile: /var/run/pmacctd.pid
+syslog: daemon
+
+! sql_host: localhost
+! sql_passwd:pmacct
+! sql_table_version: 7
+
+! plugins: pgsql
diff --git a/main/pmacct/uacctd.conf b/main/pmacct/uacctd.conf
new file mode 100644
index 0000000000..d175e31134
--- /dev/null
+++ b/main/pmacct/uacctd.conf
@@ -0,0 +1,9 @@
+daemonize: true
+pidfile: /var/run/pmacctd.pid
+syslog: daemon
+
+! sql_host: localhost
+! sql_passwd:pmacct
+! sql_table_version: 7
+
+! plugins: pgsql
diff --git a/main/policyd-spf-fs/APKBUILD b/main/policyd-spf-fs/APKBUILD
new file mode 100644
index 0000000000..a7da4cc835
--- /dev/null
+++ b/main/policyd-spf-fs/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=policyd-spf-fs
+pkgver=23
+pkgrel=2
+pkgdesc="Policy daemon for checking SPF records in postfix"
+url="http://www.freestone.net/software/policyd-spf-fs/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="libspf2-dev"
+install=
+subpackages=""
+source="http://www.freestone.net/ftp/policyd-spf-fs/${pkgname}_$pkgver.tar.gz
+ policyd-spf-fs-localpolicy-fix.patch"
+
+# append extra dependencies to -dev subpackage
+# remove if not used.
+# depends_dev="somepackage-dev"
+
+build() {
+ mv "$srcdir"/${pkgname}_$pkgver "$srcdir"/$pkgname-$pkgver
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Apply $i"
+ patch -p1 < $i || return 1
+ done
+ sed -i -e 's/-lnsl//' Makefile
+
+ make CFLAGS+=-DHAVE_NS_TYPE || return 1
+
+ mkdir -p "$pkgdir"/usr/bin
+ make PREFIX="$pkgdir"/usr install
+
+ # remove the 2 lines below (and this) if there is no init.d script
+ # install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ # install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="781552698358fa94dc2df7258177776d policyd-spf-fs_23.tar.gz
+3ec7873341af655ac940db3e62733060 policyd-spf-fs-localpolicy-fix.patch"
diff --git a/main/policyd-spf-fs/policyd-spf-fs-localpolicy-fix.patch b/main/policyd-spf-fs/policyd-spf-fs-localpolicy-fix.patch
new file mode 100644
index 0000000000..4d4d4bef5e
--- /dev/null
+++ b/main/policyd-spf-fs/policyd-spf-fs-localpolicy-fix.patch
@@ -0,0 +1,10 @@
+--- policyd-spf-fs_23/policyd-spf-fs.c Tue Sep 11 06:57:55 2007
++++ policyd-spf-fs-23.patched/policyd-spf-fs.c Mon Sep 21 12:09:33 2009
+@@ -624,6 +624,7 @@
+ FREE_RESPONSE(spf_response);
+
+ spf_request = SPF_request_new(spf_server);
++ spf_request->use_local_policy = 1;
+
+ if (SPF_request_set_ipv4_str(spf_request, req->ip) && SPF_request_set_ipv6_str(spf_request, req->ip)) {
+ syslog(LOG_WARNING, "Invalid IP address.\n" );
diff --git a/main/polkit/APKBUILD b/main/polkit/APKBUILD
new file mode 100644
index 0000000000..79bd394df5
--- /dev/null
+++ b/main/polkit/APKBUILD
@@ -0,0 +1,52 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=polkit
+_pkgname=PolicyKit
+pkgver=0.101
+pkgrel=2
+pkgdesc="Application development toolkit for controlling system-wide privileges"
+url="http://www.freedesktop.org/wiki/Software/PolicyKit"
+arch="all"
+license="LGPL"
+depends=
+makedepends="expat-dev glib-dev eggdbus-dev intltool dbus-glib-dev autoconf
+ libtool automake gtk-doc gobject-introspection-dev"
+depends_dev="eggdbus-dev dbus-glib-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://cgit.freedesktop.org/PolicyKit/snapshot/PolicyKit-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./autogen.sh --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --libexecdir=/usr/lib/polkit-1 \
+ --localstatedir=/var \
+ --disable-static \
+ --disable-nls \
+ --disable-introspection \
+ --with-authfw=shadow \
+ --with-os-type=alpine \
+ --disable-gtk-doc \
+ --disable-gtk-doc-html \
+ --disable-gtk-doc-pdf
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/polkit*/extensions/*.la
+}
+
+md5sums="dcacd0c68fc62d0199bd39e437ab4baf PolicyKit-0.101.tar.bz2"
diff --git a/main/poppler-gtk/APKBUILD b/main/poppler-gtk/APKBUILD
new file mode 100644
index 0000000000..0955b49d05
--- /dev/null
+++ b/main/poppler-gtk/APKBUILD
@@ -0,0 +1,58 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+# this aport only includes glib/gtk support in order to break the
+# circular make dependency: gtk <- cups <- poppler <- gtk
+
+# get the pkgver from poppler
+if [ -r ../poppler/APKBUILD ]; then
+ . ../poppler/APKBUILD
+fi
+
+pkgname=poppler-gtk
+_realname=poppler
+pkgver=$pkgver
+pkgrel=1
+pkgdesc="PDF rendering library based on xpdf 3.0"
+url="http://poppler.freedesktop.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="jpeg-dev cairo-dev libxml2-dev fontconfig-dev glib-dev gtk+-dev
+ poppler-dev lcms-dev"
+depends=
+replaces="poppler-glib"
+depends_dev="$makedepends"
+source="http://poppler.freedesktop.org/poppler-$pkgver.tar.gz"
+
+prepare() {
+ return 0
+}
+
+build() {
+ cd "$srcdir"/$_realname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-cairo-output \
+ --enable-xpdf-headers \
+ --enable-libjpeg \
+ --enable-zlib \
+ --enable-poppler-glib \
+ --enable-gdk \
+ --disable-poppler-qt4 \
+ --disable-poppler-qt \
+ --disable-utils \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$_realname-$pkgver
+ install -D -m644 poppler-glib.pc "$pkgdir"/usr/lib/pkgconfig/poppler-glib.pc
+ cd glib
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="2b6e0c26b77a943df3b9bb02d67ca236 poppler-0.16.5.tar.gz"
diff --git a/main/poppler/APKBUILD b/main/poppler/APKBUILD
new file mode 100644
index 0000000000..5c1823781e
--- /dev/null
+++ b/main/poppler/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+# this aport does not include glib/gtk support in order to break the
+# circular make dependency: gtk <- cups <- poppler <- gtk
+# So we build gtk support in poppler-gtk
+pkgname=poppler
+pkgver=0.16.5
+pkgrel=0
+pkgdesc="PDF rendering library based on xpdf 3.0"
+url="http://poppler.freedesktop.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-utils"
+makedepends="jpeg-dev cairo-dev libxml2-dev fontconfig-dev pkgconfig libiconv-dev"
+depends=
+depends_dev="cairo-dev"
+source="http://$pkgname.freedesktop.org/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-cairo-output \
+ --enable-xpdf-headers \
+ --enable-libjpeg \
+ --enable-zlib \
+ --disable-poppler-glib \
+ --disable-gdk \
+ --disable-poppler-qt4 \
+ --disable-poppler-qt \
+ || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+utils() {
+ pkgdesc="Poppler's xpdf-workalike command line utilities"
+ install -d "$subpkgdir"/usr
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="2b6e0c26b77a943df3b9bb02d67ca236 poppler-0.16.5.tar.gz"
diff --git a/main/popt/APKBUILD b/main/popt/APKBUILD
new file mode 100644
index 0000000000..8c028c9283
--- /dev/null
+++ b/main/popt/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=popt
+pkgver=1.16
+pkgrel=4
+pkgdesc="A commandline option parser"
+url="http://rpm5.org"
+arch="all"
+license="custom"
+depends=
+makedepends="!libiconv-dev"
+source="http://rpm5.org/files/$pkgname/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-doc $pkgname-dev"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --libdir=/lib \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR=$pkgdir install || return 1
+ rm -f "$pkgdir"/lib/*.la
+}
+
+dev() {
+ default_dev
+ mkdir -p "$subpkgdir"/lib/
+ mv "$pkgdir"/lib/*.a "$subpkgdir"/lib/
+}
+
+md5sums="3743beefa3dd6247a73f8f7a32c14c33 popt-1.16.tar.gz"
diff --git a/main/postfix-policyd-spf-perl/APKBUILD b/main/postfix-policyd-spf-perl/APKBUILD
new file mode 100644
index 0000000000..aba1b95db9
--- /dev/null
+++ b/main/postfix-policyd-spf-perl/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=postfix-policyd-spf-perl
+pkgver=2.007
+pkgrel=1
+pkgdesc="A Sender Policy Framework implementation"
+url="http://www.openspf.org/Software"
+arch="all"
+license="GPL"
+depends="perl perl-mail-spf perl-netaddr-ip"
+makedepends=""
+install=
+subpackages=""
+source="http://www.openspf.org/blobs/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ install -m755 -D "$srcdir"/$pkgname-$pkgver/$pkgname "$pkgdir"/usr/bin/$pkgname
+}
+
+md5sums="69b501012907236fd39975eadf29848a postfix-policyd-spf-perl-2.007.tar.gz"
diff --git a/main/postfix/0001-support-for-dynamic-maps.patch b/main/postfix/0001-support-for-dynamic-maps.patch
new file mode 100644
index 0000000000..a15a62bf11
--- /dev/null
+++ b/main/postfix/0001-support-for-dynamic-maps.patch
@@ -0,0 +1,1107 @@
+From 7e51893c53eca9bb0e952941e5f50163131c21eb Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Fri, 11 Mar 2011 15:33:18 +0000
+Subject: [PATCH] support for dynamic maps
+
+forward ported
+---
+ conf/postfix-files | 11 +++
+ src/dns/Makefile.in | 5 +-
+ src/global/Makefile.in | 44 +++++++++--
+ src/global/mail_conf.c | 6 ++
+ src/global/mail_dict.c | 2 +
+ src/global/mail_params.c | 4 +
+ src/global/mkmap_open.c | 11 +++-
+ src/master/Makefile.in | 6 +-
+ src/milter/Makefile.in | 6 +-
+ src/postconf/postconf.c | 10 +++
+ src/postmap/postmap.c | 51 +++++++++++--
+ src/tls/Makefile.in | 6 +-
+ src/util/Makefile.in | 29 +++++---
+ src/util/dict.h | 6 ++
+ src/util/dict_db.c | 6 ++
+ src/util/dict_dbm.c | 4 +
+ src/util/dict_open.c | 183 +++++++++++++++++++++++++++++++++++++++++++++-
+ src/util/load_lib.c | 135 ++++++++++++++++++++++++++++++++++
+ src/util/load_lib.h | 41 ++++++++++
+ 19 files changed, 520 insertions(+), 46 deletions(-)
+ create mode 100644 src/util/load_lib.c
+ create mode 100644 src/util/load_lib.h
+
+diff --git a/conf/postfix-files b/conf/postfix-files
+index d3911d6..7a7b619 100644
+--- a/conf/postfix-files
++++ b/conf/postfix-files
+@@ -65,6 +65,11 @@ $queue_directory/saved:d:$mail_owner:-:700:ucr
+ $queue_directory/trace:d:$mail_owner:-:700:ucr
+ $daemon_directory/anvil:f:root:-:755
+ $daemon_directory/bounce:f:root:-:755
++$daemon_directory/dict_ldap.so:f:root:-:755
++$daemon_directory/dict_pcre.so:f:root:-:755
++$daemon_directory/dict_mysql.so:f:root:-:755
++$daemon_directory/dict_pgsql.so:f:root:-:755
++$daemon_directory/dict_sqlite.so:f:root:-:755
+ $daemon_directory/cleanup:f:root:-:755
+ $daemon_directory/discard:f:root:-:755
+ $daemon_directory/dnsblog:f:root:-:755
+@@ -97,6 +102,11 @@ $daemon_directory/tlsmgr:f:root:-:755
+ $daemon_directory/trivial-rewrite:f:root:-:755
+ $daemon_directory/verify:f:root:-:755
+ $daemon_directory/virtual:f:root:-:755
++/usr/lib/libpostfix-dns.so.1:f:root:-:755
++/usr/lib/libpostfix-global.so.1:f:root:-:755
++/usr/lib/libpostfix-tls.so.1:f:root:-:755
++/usr/lib/libpostfix-master.so.1:f:root:-:755
++/usr/lib/libpostfix-util.so.1:f:root:-:755
+ $daemon_directory/nqmgr:h:$daemon_directory/qmgr
+ $daemon_directory/lmtp:h:$daemon_directory/smtp
+ $command_directory/postalias:f:root:-:755
+@@ -120,6 +130,7 @@ $config_directory/access:f:root:-:644:p1
+ $config_directory/aliases:f:root:-:644:p1
+ $config_directory/bounce.cf.default:f:root:-:644:1
+ $config_directory/canonical:f:root:-:644:p1
++$config_directory/dynamicmaps.cf:f:root:-:644:p
+ $config_directory/cidr_table:f:root:-:644:o
+ $config_directory/generic:f:root:-:644:p1
+ $config_directory/generics:f:root:-:644:o
+diff --git a/src/dns/Makefile.in b/src/dns/Makefile.in
+index bbc5e98..b71082e 100644
+--- a/src/dns/Makefile.in
++++ b/src/dns/Makefile.in
+@@ -14,7 +14,7 @@ LIBS = ../../lib/libutil.a
+ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+ all: $(LIB)
+
+@@ -32,11 +32,10 @@ root_tests:
+
+ $(LIB): $(OBJS)
+ $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-dns.so.1 -o $(LIB) $(OBJS) $(LIBS) $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+ update: $(LIB_DIR)/$(LIB) $(HDRS)
+ -for i in $(HDRS); \
+diff --git a/src/global/Makefile.in b/src/global/Makefile.in
+index 1a35114..bc4b643 100644
+--- a/src/global/Makefile.in
++++ b/src/global/Makefile.in
+@@ -35,8 +35,8 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
+ canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
+ clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
+ defer.o deliver_completed.o deliver_flock.o deliver_pass.o \
+- deliver_request.o dict_ldap.o dict_mysql.o dict_pgsql.o \
+- dict_proxy.o dict_sqlite.o domain_list.o dot_lockfile.o dot_lockfile_as.o \
++ deliver_request.o \
++ dict_proxy.o domain_list.o dot_lockfile.o dot_lockfile_as.o \
+ dsb_scan.o dsn.o dsn_buf.o dsn_mask.o dsn_print.o dsn_util.o \
+ ehlo_mask.o ext_prop.o file_id.o flush_clnt.o header_opts.o \
+ header_token.o input_transp.o int_filt.o is_header.o log_adhoc.o \
+@@ -106,10 +106,14 @@ LIBS = ../../lib/libutil.a
+ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+ MAKES =
++LDAPSO = dict_ldap.so
++MYSQLSO = dict_mysql.so
++PGSQLSO = dict_pgsql.so
++SQLITESO = dict_sqlite.so
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+-all: $(LIB)
++all: $(LIB) $(LDAPSO) $(MYSQLSO) $(PGSQLSO) $(SQLITESO)
+
+ $(OBJS): ../../conf/makedefs.out
+
+@@ -119,14 +123,36 @@ Makefile: Makefile.in
+ test: $(TESTPROG)
+
+ $(LIB): $(OBJS)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-global.so.1 -o $(LIB) $(OBJS) $(LIBS) $(SYSLIBS)
++
++$(LDAPSO): dict_ldap.o $(LIB) ../../lib/libglobal.a
++ $(CC) -shared -Wl,-soname,dict_ldap.so -o $@ $? -lldap -llber -L../../lib -lutil -L. -lglobal
++
++$(MYSQLSO): dict_mysql.o $(LIB) ../../lib/libglobal.a
++ $(CC) -shared -Wl,-soname,dict_mysql.so -o $@ $? -lmysqlclient -L. -lutil -lglobal
++
++$(PGSQLSO): dict_pgsql.o $(LIB) ../../lib/libglobal.a
++ $(CC) -shared -Wl,-soname,dict_pgsql.so -o $@ $? -lpq -L. -lutil -lglobal
++
++$(SQLITESO): dict_sqlite.o $(LIB) ../../lib/libglobal.a
++ $(CC) -shared -Wl,-soname,dict_sqlite.so -o $@ $? -lsqlite3 -L. -lutil -lglobal
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+-update: $(LIB_DIR)/$(LIB) $(HDRS)
++../../libexec/$(LDAPSO): $(LDAPSO)
++ cp $(LDAPSO) ../../libexec
++
++../../libexec/$(MYSQLSO): $(MYSQLSO)
++ cp $(MYSQLSO) ../../libexec
++
++../../libexec/$(PGSQLSO): $(PGSQLSO)
++ cp $(PGSQLSO) ../../libexec
++
++../../libexec/$(SQLITESO): $(SQLITESO)
++ cp $(SQLITESO) ../../libexec
++
++update: $(LIB_DIR)/$(LIB) ../../libexec/$(LDAPSO) ../../libexec/$(MYSQLSO) ../../libexec/$(PGSQLSO) ../../libexec/$(SQLITESO) $(HDRS)
+ -for i in $(HDRS); \
+ do \
+ cmp -s $$i $(INC_DIR)/$$i 2>/dev/null || cp $$i $(INC_DIR); \
+@@ -497,7 +523,7 @@ lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+ clean:
+- rm -f *.o $(LIB) *core $(TESTPROG) junk
++ rm -f *.o $(LIB) $(LDAPSO) $(MYSQLSO) $(PGSQLSO) $(SQLITESO) *core $(TESTPROG) junk
+ rm -rf printfck
+
+ tidy: clean
+diff --git a/src/global/mail_conf.c b/src/global/mail_conf.c
+index 1fc7847..2af757f 100644
+--- a/src/global/mail_conf.c
++++ b/src/global/mail_conf.c
+@@ -190,6 +190,12 @@ void mail_conf_suck(void)
+ path = concatenate(var_config_dir, "/", "main.cf", (char *) 0);
+ dict_load_file(CONFIG_DICT, path);
+ myfree(path);
++
++#ifndef NO_DYNAMIC_MAPS
++ path = concatenate(var_config_dir, "/", "dynamicmaps.cf", (char *) 0);
++ dict_open_dlinfo(path);
++ myfree(path);
++#endif
+ }
+
+ /* mail_conf_flush - discard configuration dictionary */
+diff --git a/src/global/mail_dict.c b/src/global/mail_dict.c
+index 337861d..663f90f 100644
+--- a/src/global/mail_dict.c
++++ b/src/global/mail_dict.c
+@@ -46,6 +46,7 @@ typedef struct {
+
+ static const DICT_OPEN_INFO dict_open_info[] = {
+ DICT_TYPE_PROXY, dict_proxy_open,
++#ifdef NO_DYNAMIC_MAPS
+ #ifdef HAS_LDAP
+ DICT_TYPE_LDAP, dict_ldap_open,
+ #endif
+@@ -58,6 +59,7 @@ static const DICT_OPEN_INFO dict_open_info[] = {
+ #ifdef HAS_SQLITE
+ DICT_TYPE_SQLITE, dict_sqlite_open,
+ #endif
++#endif /* NO_DYNAMIC_MAPS */
+ 0,
+ };
+
+diff --git a/src/global/mail_params.c b/src/global/mail_params.c
+index f5350a1..db33da1 100644
+--- a/src/global/mail_params.c
++++ b/src/global/mail_params.c
+@@ -79,6 +79,7 @@
+ /* char *var_export_environ;
+ /* char *var_debug_peer_list;
+ /* int var_debug_peer_level;
++/* int var_command_maxtime;
+ /* int var_in_flow_delay;
+ /* int var_fault_inj_code;
+ /* char *var_bounce_service;
+@@ -91,6 +92,7 @@
+ /* char *var_error_service;
+ /* char *var_flush_service;
+ /* char *var_verify_service;
++/* char *var_scache_service;
+ /* char *var_trace_service;
+ /* char *var_proxymap_service;
+ /* char *var_proxywrite_service;
+@@ -265,6 +267,7 @@ char *var_import_environ;
+ char *var_export_environ;
+ char *var_debug_peer_list;
+ int var_debug_peer_level;
++int var_command_maxtime;
+ int var_fault_inj_code;
+ char *var_bounce_service;
+ char *var_cleanup_service;
+@@ -276,6 +279,7 @@ char *var_showq_service;
+ char *var_error_service;
+ char *var_flush_service;
+ char *var_verify_service;
++char *var_scache_service;
+ char *var_trace_service;
+ char *var_proxymap_service;
+ char *var_proxywrite_service;
+diff --git a/src/global/mkmap_open.c b/src/global/mkmap_open.c
+index 69a0d57..eb8de71 100644
+--- a/src/global/mkmap_open.c
++++ b/src/global/mkmap_open.c
+@@ -81,7 +81,7 @@
+ * We use a different table (in dict_open.c) when querying maps.
+ */
+ typedef struct {
+- char *type;
++ const char *type;
+ MKMAP *(*before_open) (const char *);
+ } MKMAP_OPEN_INFO;
+
+@@ -156,7 +156,16 @@ MKMAP *mkmap_open(const char *type, const char *path,
+ */
+ for (mp = mkmap_types; /* void */ ; mp++) {
+ if (mp->type == 0)
++#ifndef NO_DYNAMIC_MAPS
++ {
++ static MKMAP_OPEN_INFO oi;
++ oi.before_open=(MKMAP*(*)(const char*))dict_mkmap_func(type);
++ oi.type=type;
++ mp=&oi;
++ }
++#else
+ msg_fatal("unsupported map type: %s", type);
++#endif
+ if (strcmp(type, mp->type) == 0)
+ break;
+ }
+diff --git a/src/master/Makefile.in b/src/master/Makefile.in
+index 53f65bd..6a562cf 100644
+--- a/src/master/Makefile.in
++++ b/src/master/Makefile.in
+@@ -20,7 +20,7 @@ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+ BIN_DIR = ../../libexec
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+ all: $(PROG) $(LIB)
+
+@@ -39,12 +39,10 @@ tests:
+ root_tests:
+
+ $(LIB): $(LIB_OBJ)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-master.so.1 -o $(LIB) $(LIB_OBJ) $(LIBS) $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)/$(LIB)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+ $(BIN_DIR)/$(PROG): $(PROG)
+ cp $(PROG) $(BIN_DIR)
+diff --git a/src/milter/Makefile.in b/src/milter/Makefile.in
+index c28263a..c475629 100644
+--- a/src/milter/Makefile.in
++++ b/src/milter/Makefile.in
+@@ -14,7 +14,7 @@ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+ MAKES =
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+ all: $(LIB)
+
+@@ -30,12 +30,10 @@ tests:
+ root_tests:
+
+ $(LIB): $(OBJS)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-milter.so.1 -o $(LIB) $(OBJS) $(LIBS) $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+ update: $(LIB_DIR)/$(LIB) $(HDRS)
+ -for i in $(HDRS); \
+diff --git a/src/postconf/postconf.c b/src/postconf/postconf.c
+index 82d8be0..e12baa9 100644
+--- a/src/postconf/postconf.c
++++ b/src/postconf/postconf.c
+@@ -1013,6 +1013,16 @@ static void show_maps(void)
+ {
+ ARGV *maps_argv;
+ int i;
++#ifndef NO_DYNAMIC_MAPS
++ char *path;
++ char *config_dir;
++
++ var_config_dir = mystrdup((config_dir = safe_getenv(CONF_ENV_PATH)) != 0 ?
++ config_dir : DEF_CONFIG_DIR); /* XXX */
++ path = concatenate(var_config_dir, "/", "dynamicmaps.cf", (char *) 0);
++ dict_open_dlinfo(path);
++ myfree(path);
++#endif
+
+ maps_argv = dict_mapnames();
+ for (i = 0; i < maps_argv->argc; i++)
+diff --git a/src/postmap/postmap.c b/src/postmap/postmap.c
+index e956aed..0981c7e 100644
+--- a/src/postmap/postmap.c
++++ b/src/postmap/postmap.c
+@@ -5,7 +5,7 @@
+ /* Postfix lookup table management
+ /* SYNOPSIS
+ /* .fi
+-/* \fBpostmap\fR [\fB-Nbfhimnoprsvw\fR] [\fB-c \fIconfig_dir\fR]
++/* \fBpostmap\fR [\fB-Nbfhimnoprsuvw\fR] [\fB-c \fIconfig_dir\fR]
+ /* [\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
+ /* [\fIfile_type\fR:]\fIfile_name\fR ...
+ /* DESCRIPTION
+@@ -151,6 +151,8 @@
+ /* .sp
+ /* This feature is available in Postfix version 2.2 and later,
+ /* and is not available for all database types.
++/* .IP \fB-u\fR
++/* Upgrade the database to the current version.
+ /* .IP \fB-v\fR
+ /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
+ /* options make the software increasingly verbose.
+@@ -723,6 +725,18 @@ static void postmap_seq(const char *map_type, const char *map_name,
+ dict_close(dict);
+ }
+
++/* postmap_upgrade - upgrade a map */
++
++static int postmap_upgrade(const char *map_type, const char *map_name)
++{
++ DICT *dict;
++
++ dict = dict_open3(map_type, map_name, O_RDWR,
++ DICT_FLAG_LOCK|DICT_FLAG_UPGRADE);
++ dict_close(dict);
++ return (dict != 0);
++}
++
+ /* usage - explain */
+
+ static NORETURN usage(char *myname)
+@@ -743,6 +757,7 @@ int main(int argc, char **argv)
+ int postmap_flags = POSTMAP_FLAG_AS_OWNER | POSTMAP_FLAG_SAVE_PERM;
+ int open_flags = O_RDWR | O_CREAT | O_TRUNC;
+ int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_FIX;
++ int upgrade = 0;
+ char *query = 0;
+ char *delkey = 0;
+ int sequence = 0;
+@@ -787,7 +802,7 @@ int main(int argc, char **argv)
+ /*
+ * Parse JCL.
+ */
+- while ((ch = GETOPT(argc, argv, "Nbc:d:fhimnopq:rsvw")) > 0) {
++ while ((ch = GETOPT(argc, argv, "Nbc:d:fhimnopq:rsuvw")) > 0) {
+ switch (ch) {
+ default:
+ usage(argv[0]);
+@@ -804,8 +819,8 @@ int main(int argc, char **argv)
+ msg_fatal("out of memory");
+ break;
+ case 'd':
+- if (sequence || query || delkey)
+- msg_fatal("specify only one of -s -q or -d");
++ if (sequence || query || delkey || upgrade)
++ msg_fatal("specify only one of -s -q -u or -d");
+ delkey = optarg;
+ break;
+ case 'f':
+@@ -831,8 +846,8 @@ int main(int argc, char **argv)
+ postmap_flags &= ~POSTMAP_FLAG_SAVE_PERM;
+ break;
+ case 'q':
+- if (sequence || query || delkey)
+- msg_fatal("specify only one of -s -q or -d");
++ if (sequence || query || delkey || upgrade)
++ msg_fatal("specify only one of -s -q -u or -d");
+ query = optarg;
+ break;
+ case 'r':
+@@ -840,10 +855,15 @@ int main(int argc, char **argv)
+ dict_flags |= DICT_FLAG_DUP_REPLACE;
+ break;
+ case 's':
+- if (query || delkey)
+- msg_fatal("specify only one of -s or -q or -d");
++ if (query || delkey || upgrade)
++ msg_fatal("specify only one of -s -q -u or -d");
+ sequence = 1;
+ break;
++ case 'u':
++ if (sequence || query || delkey || upgrade)
++ msg_fatal("specify only one of -s -q -u or -d");
++ upgrade=1;
++ break;
+ case 'v':
+ msg_verbose++;
+ break;
+@@ -914,6 +934,21 @@ int main(int argc, char **argv)
+ exit(0);
+ }
+ exit(1);
++ } else if (upgrade) { /* Upgrade the map(s) */
++ int success = 1;
++ if (optind + 1 > argc)
++ usage(argv[0]);
++ while (optind < argc) {
++ if ((path_name = split_at(argv[optind], ':')) != 0) {
++ success &= postmap_upgrade(argv[optind], path_name);
++ } else {
++ success &= postmap_upgrade(var_db_type, path_name);
++ }
++ if (!success)
++ exit(1);
++ optind++;
++ }
++ exit(0);
+ } else { /* create/update map(s) */
+ if (optind + 1 > argc)
+ usage(argv[0]);
+diff --git a/src/tls/Makefile.in b/src/tls/Makefile.in
+index 1dbe154..b952aa4 100644
+--- a/src/tls/Makefile.in
++++ b/src/tls/Makefile.in
+@@ -24,7 +24,7 @@ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+ MAKES =
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+ all: $(LIB)
+
+@@ -40,12 +40,10 @@ tests:
+ root_tests:
+
+ $(LIB): $(OBJS)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-tls.so.1 -o $(LIB) $(OBJS) $(LIBS) $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+ update: $(LIB_DIR)/$(LIB) $(HDRS)
+ -for i in $(HDRS); \
+diff --git a/src/util/Makefile.in b/src/util/Makefile.in
+index 4455fbf..481ec42 100644
+--- a/src/util/Makefile.in
++++ b/src/util/Makefile.in
+@@ -33,21 +33,22 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
+ allascii.c load_file.c killme_after.c vstream_tweak.c \
+ unix_pass_listen.c unix_pass_trigger.c edit_file.c inet_windowsize.c \
+ unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \
+- ip_match.c nbbio.c stream_pass_connect.c
++ ip_match.c nbbio.c stream_pass_connect.c load_lib.c
+ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
+ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
+ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
+ chroot_uid.o cidr_match.o clean_env.o close_on_exec.o concatenate.o \
+ ctable.o dict.o dict_alloc.o dict_cdb.o dict_cidr.o dict_db.o \
+ dict_dbm.o dict_debug.o dict_env.o dict_ht.o dict_ni.o dict_nis.o \
+- dict_nisplus.o dict_open.o dict_pcre.o dict_regexp.o dict_sdbm.o \
+- dict_static.o dict_tcp.o dict_unix.o dir_forest.o doze.o dummy_read.o \
++ dict_nisplus.o dict_open.o dict_regexp.o dict_sdbm.o \
++ dict_static.o dict_unix.o dir_forest.o doze.o dummy_read.o \
+ dummy_write.o duplex_pipe.o environ.o events.o exec_command.o \
+ fifo_listen.o fifo_trigger.o file_limit.o find_inet.o fsspace.o \
+ fullname.o get_domainname.o get_hostname.o hex_code.o hex_quote.o \
+ host_port.o htable.o inet_addr_host.o inet_addr_list.o \
+ inet_addr_local.o inet_connect.o inet_listen.o inet_proto.o \
+ inet_trigger.o line_wrap.o lowercase.o lstat_as.o mac_expand.o \
++ load_lib.o \
+ mac_parse.o make_dirs.o mask_addr.o match_list.o match_ops.o msg.o \
+ msg_output.o msg_syslog.o msg_vstream.o mvect.o myaddrinfo.o myflock.o \
+ mymalloc.o myrand.o mystrtok.o name_code.o name_mask.o netstring.o \
+@@ -89,13 +90,14 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
+ username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
+ vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
+ edit_file.h dict_cache.h dict_thash.h \
+- ip_match.h nbbio.h
++ ip_match.h nbbio.h load_lib.h
+ TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
+ stream_test.c dup2_pass_on_exec.c
+ DEFS = -I. -D$(SYSTYPE)
+ CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+ FILES = Makefile $(SRCS) $(HDRS)
+ INCL =
++PCRESO = dict_pcre.so
+ LIB = libutil.a
+ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
+ fifo_rdonly_bug fifo_rdwr_bug fifo_trigger fsspace fullname \
+@@ -111,10 +113,11 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
+
+ LIB_DIR = ../../lib
+ INC_DIR = ../../include
++LIBS = $(LIB_DIR)/$(LIB) $(PCRESO)
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+-all: $(LIB)
++all: $(LIB) $(PCRESO)
+
+ $(OBJS): ../../conf/makedefs.out
+
+@@ -123,15 +126,19 @@ Makefile: Makefile.in
+
+ test: $(TESTPROG)
+
++$(PCRESO): dict_pcre.o libutil.a
++ $(CC) -shared -Wl,-soname,dict_pcre.so -o $@ $? -lpcre -L. -lutil
++
+ $(LIB): $(OBJS)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-util.so.1 -o $(LIB) $(OBJS) -ldl $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+-update: $(LIB_DIR)/$(LIB) $(HDRS)
++../../libexec/$(PCRESO): $(PCRESO)
++ cp $(PCRESO) ../../libexec
++
++update: $(LIBS) $(HDRS) ../../libexec/$(PCRESO)
+ -for i in $(HDRS); \
+ do \
+ cmp -s $$i $(INC_DIR)/$$i 2>/dev/null || cp $$i $(INC_DIR); \
+@@ -153,7 +160,7 @@ lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+ clean:
+- rm -f *.o $(LIB) *core $(TESTPROG) junk $(MAKES) *.tmp
++ rm -f *.o $(LIB) $(PCRESO) *core $(TESTPROG) junk $(MAKES) *.tmp
+ rm -rf printfck
+
+ tidy: clean
+diff --git a/src/util/dict.h b/src/util/dict.h
+index 9829d28..d7dc53c 100644
+--- a/src/util/dict.h
++++ b/src/util/dict.h
+@@ -66,6 +66,7 @@ extern DICT *dict_debug(DICT *);
+ #define DICT_FLAG_NO_UNAUTH (1<<13) /* disallow unauthenticated data */
+ #define DICT_FLAG_FOLD_FIX (1<<14) /* case-fold key with fixed-case map */
+ #define DICT_FLAG_FOLD_MUL (1<<15) /* case-fold key with multi-case map */
++#define DICT_FLAG_UPGRADE (1<<30) /* Upgrade the db */
+ #define DICT_FLAG_FOLD_ANY (DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL)
+
+ /* IMPORTANT: Update the dict_mask[] table when the above changes */
+@@ -138,6 +139,11 @@ extern const char *dict_eval(const char *, const char *, int);
+ extern DICT *dict_open(const char *, int, int);
+ extern DICT *dict_open3(const char *, const char *, int, int);
+ extern void dict_open_register(const char *, DICT *(*) (const char *, int, int));
++#ifndef NO_DYNAMIC_MAPS
++extern void dict_open_dlinfo(const char *path);
++typedef void* (*dict_mkmap_func_t)(const char *);
++dict_mkmap_func_t dict_mkmap_func(const char *dict_type);
++#endif
+
+ #define dict_get(dp, key) ((const char *) (dp)->lookup((dp), (key)))
+ #define dict_put(dp, key, val) (dp)->update((dp), (key), (val))
+diff --git a/src/util/dict_db.c b/src/util/dict_db.c
+index c827b8d..e33fc24 100644
+--- a/src/util/dict_db.c
++++ b/src/util/dict_db.c
+@@ -676,6 +676,12 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
+ msg_fatal("set DB cache size %d: %m", dict_db_cache_size);
+ if (type == DB_HASH && db->set_h_nelem(db, DICT_DB_NELM) != 0)
+ msg_fatal("set DB hash element count %d: %m", DICT_DB_NELM);
++ if (dict_flags & DICT_FLAG_UPGRADE) {
++ if (msg_verbose)
++ msg_info("upgrading database %s",db_path);
++ if ((errno = db->upgrade(db,db_path,0)) != 0)
++ msg_fatal("upgrade of database %s: %m",db_path);
++ }
+ #if DB_VERSION_MAJOR == 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0)
+ if ((errno = db->open(db, 0, db_path, 0, type, db_flags, 0644)) != 0)
+ msg_fatal("open database %s: %m", db_path);
+diff --git a/src/util/dict_dbm.c b/src/util/dict_dbm.c
+index 3603e44..1958556 100644
+--- a/src/util/dict_dbm.c
++++ b/src/util/dict_dbm.c
+@@ -409,6 +409,10 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
+ char *dbm_path;
+ int lock_fd;
+
++#ifdef HAVE_GDBM
++ msg_fatal("%s: gdbm maps use locking that is incompatible with postfix. Use a hash map instead.",
++ path);
++#endif
+ /*
+ * Note: DICT_FLAG_LOCK is used only by programs that do fine-grained (in
+ * the time domain) locking while accessing individual database records.
+diff --git a/src/util/dict_open.c b/src/util/dict_open.c
+index 9e1358f..19e40bf 100644
+--- a/src/util/dict_open.c
++++ b/src/util/dict_open.c
+@@ -44,6 +44,8 @@
+ /* DICT *(*open) (const char *, int, int);
+ /*
+ /* ARGV *dict_mapnames()
++/*
++/* void (*)() dict_mkmap_func(const char *dict_type)
+ /* DESCRIPTION
+ /* This module implements a low-level interface to multiple
+ /* physical dictionary types.
+@@ -161,6 +163,9 @@
+ /*
+ /* dict_mapnames() returns a sorted list with the names of all available
+ /* dictionary types.
++/*
++/* dict_mkmap_func() returns a pointer to the mkmap setup function
++/* for the given map type, as given in /etc/dynamicmaps.cf
+ /* DIAGNOSTICS
+ /* Fatal error: open error, unsupported dictionary type, attempt to
+ /* update non-writable dictionary.
+@@ -185,6 +190,9 @@
+ #include <strings.h>
+ #endif
+
++#include <sys/stat.h>
++#include <unistd.h>
++
+ /* Utility library. */
+
+ #include <argv.h>
+@@ -211,6 +219,27 @@
+ #include <split_at.h>
+ #include <htable.h>
+
++#ifndef NO_DYNAMIC_MAPS
++#include <load_lib.h>
++#include <vstring.h>
++#include <vstream.h>
++#include <vstring_vstream.h>
++#include <mvect.h>
++
++ /*
++ * Interface for dynamic map loading.
++ */
++typedef struct {
++ const char *pattern;
++ const char *soname;
++ const char *openfunc;
++ const char *mkmapfunc;
++} DLINFO;
++
++static DLINFO *dict_dlinfo;
++static DLINFO *dict_open_dlfind(const char *type);
++#endif
++
+ /*
+ * lookup table for available map types.
+ */
+@@ -226,7 +255,9 @@ static const DICT_OPEN_INFO dict_open_info[] = {
+ DICT_TYPE_ENVIRON, dict_env_open,
+ DICT_TYPE_HT, dict_ht_open,
+ DICT_TYPE_UNIX, dict_unix_open,
++#ifdef NO_DYNAMIC_MAPS
+ DICT_TYPE_TCP, dict_tcp_open,
++#endif
+ #ifdef HAS_SDBM
+ DICT_TYPE_SDBM, dict_sdbm_open,
+ #endif
+@@ -246,9 +277,11 @@ static const DICT_OPEN_INFO dict_open_info[] = {
+ #ifdef HAS_NETINFO
+ DICT_TYPE_NETINFO, dict_ni_open,
+ #endif
++#ifdef NO_DYNAMIC_MAPS
+ #ifdef HAS_PCRE
+ DICT_TYPE_PCRE, dict_pcre_open,
+ #endif
++#endif /* NO_DYNAMIC_MAPS */
+ #ifdef HAS_POSIX_REGEXP
+ DICT_TYPE_REGEXP, dict_regexp_open,
+ #endif
+@@ -307,8 +340,31 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
+ dict_type, dict_name);
+ if (dict_open_hash == 0)
+ dict_open_init();
+- if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0)
+- msg_fatal("unsupported dictionary type: %s", dict_type);
++ if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) {
++#ifdef NO_DYNAMIC_MAPS
++ msg_fatal("%s: unsupported dictionary type: %s", myname, dict_type);
++#else
++ struct stat st;
++ LIB_FN fn[2];
++ DICT *(*open) (const char *, int, int);
++ DLINFO *dl=dict_open_dlfind(dict_type);
++ if (!dl)
++ msg_fatal("%s: unsupported dictionary type: %s: Is the postfix-%s package installed?", myname, dict_type, dict_type);
++ if (stat(dl->soname,&st) < 0) {
++ msg_fatal("%s: unsupported dictionary type: %s (%s not found. Is the postfix-%s package installed?)",
++ myname, dict_type, dl->soname, dict_type);
++ }
++ fn[0].name = dl->openfunc;
++ fn[0].ptr = (void**)&open;
++ fn[1].name = NULL;
++ load_library_symbols(dl->soname, fn, NULL);
++ dict_open_register(dict_type, open);
++ dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type);
++#endif
++ }
++ if (msg_verbose>1) {
++ msg_info("%s: calling %s open routine",myname,dict_type);
++ }
+ if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
+ msg_fatal("opening %s:%s %m", dict_type, dict_name);
+ if (msg_verbose)
+@@ -316,6 +372,36 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
+ return (dict);
+ }
+
++dict_mkmap_func_t dict_mkmap_func(const char *dict_type)
++{
++ char *myname="dict_mkmap_func";
++ struct stat st;
++ LIB_FN fn[2];
++ dict_mkmap_func_t mkmap;
++ DLINFO *dl;
++#ifndef NO_DYNAMIC_MAPS
++ if (!dict_dlinfo)
++ msg_fatal("dlinfo==NULL");
++ dl=dict_open_dlfind(dict_type);
++ if (!dl)
++ msg_fatal("%s: unsupported dictionary type: %s: Is the postfix-%s package installed?", myname, dict_type, dict_type);
++ if (stat(dl->soname,&st) < 0) {
++ msg_fatal("%s: unsupported dictionary type: %s (%s not found. Is the postfix-%s package installed?)",
++ myname, dict_type, dl->soname, dict_type);
++ }
++ if (!dl->mkmapfunc)
++ msg_fatal("%s: unsupported dictionary type: %s does not allow map creation.", myname, dict_type);
++
++ fn[0].name = dl->mkmapfunc;
++ fn[0].ptr = (void**)&mkmap;
++ fn[1].name = NULL;
++ load_library_symbols(dl->soname, fn, NULL);
++ return mkmap;
++#else
++ return (void(*)())NULL;
++#endif
++}
++
+ /* dict_open_register - register dictionary type */
+
+ void dict_open_register(const char *type,
+@@ -349,6 +435,9 @@ ARGV *dict_mapnames()
+ HTABLE_INFO **ht;
+ DICT_OPEN_INFO *dp;
+ ARGV *mapnames;
++#ifndef NO_DYNAMIC_MAPS
++ DLINFO *dlp;
++#endif
+
+ if (dict_open_hash == 0)
+ dict_open_init();
+@@ -357,6 +446,13 @@ ARGV *dict_mapnames()
+ dp = (DICT_OPEN_INFO *) ht[0]->value;
+ argv_add(mapnames, dp->type, ARGV_END);
+ }
++#ifndef NO_DYNAMIC_MAPS
++ if (!dict_dlinfo)
++ msg_fatal("dlinfo==NULL");
++ for (dlp=dict_dlinfo; dlp->pattern; dlp++) {
++ argv_add(mapnames, dlp->pattern, ARGV_END);
++ }
++#endif
+ qsort((void *) mapnames->argv, mapnames->argc, sizeof(mapnames->argv[0]),
+ dict_sort_alpha_cpp);
+ myfree((char *) ht_info);
+@@ -364,6 +460,89 @@ ARGV *dict_mapnames()
+ return mapnames;
+ }
+
++#ifndef NO_DYNAMIC_MAPS
++#define STREQ(x,y) (x == y || (x[0] == y[0] && strcmp(x,y) == 0))
++
++void dict_open_dlinfo(const char *path)
++{
++ char *myname="dict_open_dlinfo";
++ VSTREAM *conf_fp=vstream_fopen(path,O_RDONLY,0);
++ VSTRING *buf = vstring_alloc(100);
++ char *cp;
++ ARGV *argv;
++ MVECT vector;
++ int nelm=0;
++ int linenum=0;
++
++ dict_dlinfo=(DLINFO*)mvect_alloc(&vector,sizeof(DLINFO),3,NULL,NULL);
++
++ if (!conf_fp) {
++ msg_warn("%s: cannot open %s. No dynamic maps will be allowed.",
++ myname, path);
++ } else {
++ while (vstring_get_nonl(buf,conf_fp) != VSTREAM_EOF) {
++ cp = vstring_str(buf);
++ linenum++;
++ if (*cp == '#' || *cp == '\0')
++ continue;
++ argv = argv_split(cp, " \t");
++ if (argv->argc != 3 && argv->argc != 4) {
++ msg_fatal("%s: Expected \"pattern .so-name open-function [mkmap-function]\" at line %d",
++ myname, linenum);
++ }
++ if (STREQ(argv->argv[0],"*")) {
++ msg_warn("%s: wildcard dynamic map entry no longer supported.",
++ myname);
++ continue;
++ }
++ if (argv->argv[1][0] != '/') {
++ msg_fatal("%s: .so name must begin with a \"/\" at line %d",
++ myname, linenum);
++ }
++ if (nelm >= vector.nelm) {
++ dict_dlinfo=(DLINFO*)mvect_realloc(&vector,vector.nelm+3);
++ }
++ dict_dlinfo[nelm].pattern = mystrdup(argv->argv[0]);
++ dict_dlinfo[nelm].soname = mystrdup(argv->argv[1]);
++ dict_dlinfo[nelm].openfunc = mystrdup(argv->argv[2]);
++ if (argv->argc==4)
++ dict_dlinfo[nelm].mkmapfunc = mystrdup(argv->argv[3]);
++ else
++ dict_dlinfo[nelm].mkmapfunc = NULL;
++ nelm++;
++ argv_free(argv);
++ }
++ }
++ if (nelm >= vector.nelm) {
++ dict_dlinfo=(DLINFO*)mvect_realloc(&vector,vector.nelm+1);
++ }
++ dict_dlinfo[nelm].pattern = NULL;
++ dict_dlinfo[nelm].soname = NULL;
++ dict_dlinfo[nelm].openfunc = NULL;
++ dict_dlinfo[nelm].mkmapfunc = NULL;
++ if (conf_fp)
++ vstream_fclose(conf_fp);
++ vstring_free(buf);
++}
++
++static DLINFO *dict_open_dlfind(const char *type)
++{
++ DLINFO *dp;
++
++ if (!dict_dlinfo)
++ return NULL;
++
++ for (dp=dict_dlinfo; dp->pattern; dp++) {
++ if (STREQ(dp->pattern,type))
++ return dp;
++ }
++ return NULL;
++}
++
++#endif /* !NO_DYNAMIC_MAPS */
++
++
++
+ #ifdef TEST
+
+ /*
+diff --git a/src/util/load_lib.c b/src/util/load_lib.c
+new file mode 100644
+index 0000000..b6526ef
+--- /dev/null
++++ b/src/util/load_lib.c
+@@ -0,0 +1,135 @@
++/*++
++/* NAME
++/* load_lib 3
++/* SUMMARY
++/* library loading wrappers
++/* SYNOPSIS
++/* #include <load_lib.h>
++/*
++/* extern int load_library_symbols(const char *, LIB_FN *, LIB_FN *);
++/* const char *libname;
++/* LIB_FN *libfuncs;
++/* LIB_FN *libdata;
++/*
++/* DESCRIPTION
++/* This module loads functions from libraries, returnine pointers
++/* to the named functions.
++/*
++/* load_library_symbols() loads all of the desired functions, and
++/* returns zero for success, or exits via msg_fatal().
++/*
++/* SEE ALSO
++/* msg(3) diagnostics interface
++/* DIAGNOSTICS
++/* Problems are reported via the msg(3) diagnostics routines:
++/* library not found, symbols not found, other fatal errors.
++/* LICENSE
++/* .ad
++/* .fi
++/* The Secure Mailer license must be distributed with this software.
++/* AUTHOR(S)
++/* LaMont Jones
++/* Hewlett-Packard Company
++/* 3404 Harmony Road
++/* Fort Collins, CO 80528, USA
++/*
++/* Wietse Venema
++/* IBM T.J. Watson Research
++/* P.O. Box 704
++/* Yorktown Heights, NY 10598, USA
++/*--*/
++
++/* System libraries. */
++
++#include "sys_defs.h"
++#include <stdlib.h>
++#include <stddef.h>
++#include <string.h>
++#if defined(HAS_DLOPEN)
++#include <dlfcn.h>
++#elif defined(HAS_SHL_LOAD)
++#include <dl.h>
++#endif
++
++/* Application-specific. */
++
++#include "msg.h"
++#include "load_lib.h"
++
++extern int load_library_symbols(const char * libname, LIB_FN * libfuncs, LIB_FN * libdata)
++{
++ char *myname = "load_library_symbols";
++ LIB_FN *fn;
++
++#if defined(HAS_DLOPEN)
++ void *handle;
++ char *emsg;
++
++ handle=dlopen(libname,RTLD_NOW);
++ emsg=dlerror();
++ if (emsg) {
++ msg_fatal("%s: dlopen failure loading %s: %s", myname, libname, emsg);
++ }
++
++ if (libfuncs) {
++ for (fn=libfuncs; fn->name; fn++) {
++ *(fn->ptr) = dlsym(handle,fn->name);
++ emsg=dlerror();
++ if (emsg) {
++ msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname,
++ fn->name, libname, emsg);
++ }
++ if (msg_verbose>1) {
++ msg_info("loaded %s = %lx",fn->name, *((long*)(fn->ptr)));
++ }
++ }
++ }
++
++ if (libdata) {
++ for (fn=libdata; fn->name; fn++) {
++ *(fn->ptr) = dlsym(handle,fn->name);
++ emsg=dlerror();
++ if (emsg) {
++ msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname,
++ fn->name, libname, emsg);
++ }
++ if (msg_verbose>1) {
++ msg_info("loaded %s = %lx",fn->name, *((long*)(fn->ptr)));
++ }
++ }
++ }
++#elif defined(HAS_SHL_LOAD)
++ shl_t handle;
++
++ handle = shl_load(libname,BIND_IMMEDIATE,0);
++
++ if (libfuncs) {
++ for (fn=libfuncs; fn->name; fn++) {
++ if (shl_findsym(&handle,fn->name,TYPE_PROCEDURE,fn->ptr) != 0) {
++ msg_fatal("%s: shl_findsym failure looking up %s in %s: %m",
++ myname, fn->name, libname);
++ }
++ if (msg_verbose>1) {
++ msg_info("loaded %s = %x",fn->name, *((long*)(fn->ptr)));
++ }
++ }
++ }
++
++ if (libdata) {
++ for (fn=libdata; fn->name; fn++) {
++ if (shl_findsym(&handle,fn->name,TYPE_DATA,fn->ptr) != 0) {
++ msg_fatal("%s: shl_findsym failure looking up %s in %s: %m",
++ myname, fn->name, libname);
++ }
++ if (msg_verbose>1) {
++ msg_info("loaded %s = %x",fn->name, *((long*)(fn->ptr)));
++ }
++ }
++ }
++
++#else
++ msg_fatal("%s: need dlopen or shl_load support for dynamic libraries",
++ myname);
++#endif
++ return 0;
++}
+diff --git a/src/util/load_lib.h b/src/util/load_lib.h
+new file mode 100644
+index 0000000..adebd25
+--- /dev/null
++++ b/src/util/load_lib.h
+@@ -0,0 +1,41 @@
++#ifndef _LOAD_LIB_H_INCLUDED_
++#define _LOAD_LIB_H_INCLUDED_
++
++/*++
++/* NAME
++/* load_lib 3h
++/* SUMMARY
++/* library loading wrappers
++/* SYNOPSIS
++/* #include "load_lib.h"
++/* DESCRIPTION
++/* .nf
++
++ /*
++ * External interface.
++ */
++/* NULL name terminates list */
++typedef struct LIB_FN {
++ const char *name;
++ void **ptr;
++} LIB_FN;
++
++extern int load_library_symbols(const char *, LIB_FN *, LIB_FN *);
++
++/* LICENSE
++/* .ad
++/* .fi
++/* The Secure Mailer license must be distributed with this software.
++/* AUTHOR(S)
++/* LaMont Jones
++/* Hewlett-Packard Company
++/* 3404 Harmony Road
++/* Fort Collins, CO 80528, USA
++/*
++/* Wietse Venema
++/* IBM T.J. Watson Research
++/* P.O. Box 704
++/* Yorktown Heights, NY 10598, USA
++/*--*/
++
++#endif
+--
+1.7.4.1
+
diff --git a/main/postfix/APKBUILD b/main/postfix/APKBUILD
new file mode 100644
index 0000000000..cbcbe7a0f8
--- /dev/null
+++ b/main/postfix/APKBUILD
@@ -0,0 +1,163 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=postfix
+pkgver=2.8.3
+pkgrel=0
+pkgdesc="Secure and fast drop-in replacement for Sendmail (MTA)"
+url="http://www.postfix.org/"
+arch="all"
+license="IPL-1"
+depends=
+makedepends="db-dev pcre-dev openssl-dev postgresql-dev mysql-dev openldap-dev
+ cyrus-sasl-dev perl file sqlite-dev"
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages="$pkgname-doc $pkgname-ldap $pkgname-mysql $pkgname-pcre
+ $pkgname-pgsql $pkgname-sqlite"
+source="ftp://ftp.porcupine.org/mirrors/$pkgname-release/official/$pkgname-$pkgver.tar.gz
+ $pkgname.initd
+ 0001-support-for-dynamic-maps.patch
+ dynamicmaps.cf
+ postfix-ldap.post-install
+ postfix-mysql.post-install
+ postfix-pcre.post-install
+ postfix-pgsql.post-install
+ postfix-sqlite.post-install
+ "
+
+# the dynamic maps patch is taken from mandriva
+# http://svn.mandriva.com/cgi-bin/viewvc.cgi/packages/cooker/postfix/current/SOURCES
+
+_shared_libs() {
+ file --mime-type "$@" | \
+ awk '$2 == "application/x-sharedlib" {print $1}' | \
+ tr -d :
+}
+
+build () {
+ cd "$srcdir/$pkgname-$pkgver"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+ cp ../dynamicmaps.cf conf/
+
+ sed -i -e "s|#define HAS_NIS|//#define HAS_NIS|g" \
+ -e "/^#define ALIAS_DB_MAP/s|:/etc/aliases|:/etc/postfix/aliases|" \
+ src/util/sys_defs.h || return 1
+ sed -i -e "s:/usr/local/:/usr/:g" conf/master.cf || return 1
+
+ # needed for dynamic maps.
+ local ccargs="-DHAS_DLOPEN -DHAS_SHL_LOAD"
+ local auxlibs="$LDFLAGS -lpthread -lcrypt"
+
+ ccargs="$ccargs -DDEF_DAEMON_DIR=\\\"/usr/lib/postfix\\\""
+
+ # pcre
+ ccargs="$ccargs -DHAS_PCRE"
+ #auxlibs="$auxlibs -lpcre"
+
+ # ssl
+ ccargs="$ccargs -DUSE_TLS"
+ auxlibs="$auxlibs -lssl -lcrypto"
+
+ ## dovecot-sasl
+ #ccargs="$ccargs -DUSE_SASL_AUTH -DDEF_SERVER_SASL_TYPE=\\\"dovecot\\\""
+
+ # cyrus sasl
+ ccargs="$ccargs -DUSE_SASL_AUTH -DUSE_CYRUS_SASL -I/usr/include/sasl"
+ auxlibs="$auxlibs -lsasl2"
+
+ # postgresql
+ ccargs="$ccargs -DHAS_PGSQL -I$(pg_config --includedir)"
+ #auxlibs="$auxlibs -lpq -L$(pg_config --libdir)"
+
+ # mysql
+ ccargs="$ccargs -DHAS_MYSQL $(mysql_config --include)"
+ #auxlibs="$auxlibs -lmysqlclient -lm -lz"
+
+ # ldap
+ ccargs="$ccargs -DHAS_LDAP"
+ #auxlibs="$auxlibs -lldap -llber"
+
+ # ldap
+ ccargs="$ccargs -DHAS_SQLITE"
+
+ # compile
+ make DEBUG="" \
+ OPT="$CFLAGS" \
+ CCARGS="$ccargs" \
+ AUXLIBS="$auxlibs" \
+ makefiles || return 1
+
+ make OPT="$CFLAGS" || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ for i in $(_shared_libs lib/*.a); do
+ j=${i#lib/lib}
+ ln -s ${i#lib/} lib/libpostfix-${j%.a}.so.1
+ done
+
+ # install to pkgdir
+ LD_LIBRARY_PATH=$PWD/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} make \
+ non-interactive-package \
+ install_root="$pkgdir" \
+ config_directory=/usr/share/doc/$pkgname/defaults \
+ readme_directory=/usr/share/doc/$pkgname/readme \
+ manpage_directory=/usr/share/man \
+ || return 1
+
+ install -d "$pkgdir"/usr/lib
+ for i in $(_shared_libs lib/*.a); do
+ j=${i#lib/lib}
+ install $i "$pkgdir"/usr/lib/libpostfix-${j%.a}.so.1 || return 1
+ done
+
+ # fix permissions
+ for i in postdrop postqueue; do
+ chgrp postdrop "$pkgdir"/usr/sbin/$i
+ chmod g+s "$pkgdir"/usr/sbin/$i
+ done
+
+ mkdir -p "$pkgdir"/etc/postfix
+ mv "$pkgdir"/usr/share/doc/$pkgname/defaults/*.cf \
+ "$pkgdir"/usr/share/doc/$pkgname/defaults/aliases \
+ "$pkgdir"/usr/share/doc/$pkgname/defaults/canonical \
+ "$pkgdir"/usr/share/doc/$pkgname/defaults/generic \
+ "$pkgdir"/usr/share/doc/$pkgname/defaults/header_checks \
+ "$pkgdir"/usr/share/doc/$pkgname/defaults/relocated \
+ "$pkgdir"/usr/share/doc/$pkgname/defaults/transport \
+ "$pkgdir"/usr/share/doc/$pkgname/defaults/virtual \
+ "$pkgdir"/etc/postfix/ || return 1
+
+ install -d -o postfix -g postfix "$pkgdir"/var/spool/postfix
+ install -Dm755 "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/${pkgname}/LICENSE
+}
+
+_mv_dict() {
+ local m=$1
+ shift
+ pkgdesc="$m map support for postfix"
+ depends=
+ install="postfix-${m}.post-install"
+ mkdir -p "$subpkgdir"/usr/lib/postfix
+ mv "$pkgdir"/usr/lib/postfix/dict_${m}.so \
+ "$subpkgdir"/usr/lib/postfix/
+}
+
+ldap() { _mv_dict ldap ; }
+mysql() { _mv_dict mysql ;}
+pcre() { _mv_dict pcre ; }
+pgsql() { _mv_dict pgsql ; }
+sqlite() { _mv_dict sqlite ; }
+
+md5sums="b3922ededd3fd6051f759e58a4ada3ae postfix-2.8.3.tar.gz
+6bbabcd041aefaf40e1f3ee1fc1d6d7e postfix.initd
+632fce950f64aa0794f9c2af85d45423 0001-support-for-dynamic-maps.patch
+442efd1a95b0c061dfb8ab75456e0f24 dynamicmaps.cf
+2ebe51a882eb9d6d7866583eb6af3969 postfix-ldap.post-install
+2ebe51a882eb9d6d7866583eb6af3969 postfix-mysql.post-install
+fd16ec00b60269c4ede4a0a0a514cefa postfix-pcre.post-install
+2ebe51a882eb9d6d7866583eb6af3969 postfix-pgsql.post-install
+2ebe51a882eb9d6d7866583eb6af3969 postfix-sqlite.post-install"
diff --git a/main/postfix/dynamicmaps.cf b/main/postfix/dynamicmaps.cf
new file mode 100644
index 0000000000..dfe2110552
--- /dev/null
+++ b/main/postfix/dynamicmaps.cf
@@ -0,0 +1,16 @@
+# Postfix dynamic maps configuration file.
+#
+# The first match found is the one that is used. Wildcards are not
+# supported.
+#
+#type location of .so file name of open function
+#==== ============================= =====================
+#ldap /usr/lib/postfix/dict_ldap.so dict_ldap_open
+#mysql /usr/lib/postfix/dict_mysql.so dict_mysql_open
+#pcre /usr/lib/postfix/dict_pcre.so dict_pcre_open
+#regex /usr/lib/postfix/dict_pcre.so dict_pcre_open
+#pgsql /usr/lib/postfix/dict_pgsql.so dict_pgsql_open
+
+# apk tools will manage the lines below
+## AUTO BEGIN ##
+## AUTO END ##
diff --git a/main/postfix/postfix-ldap.post-install b/main/postfix/postfix-ldap.post-install
new file mode 100644
index 0000000000..b8d23833b6
--- /dev/null
+++ b/main/postfix/postfix-ldap.post-install
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# update the dynamicmaps.cf
+conf=/etc/postfix/dynamicmaps.cf
+
+sed -i -e '/\#\# AUTO BEGIN/,/\#\# AUTO END/d' $conf
+
+(
+echo '## AUTO BEGIN ##'
+if cd /usr/lib/postfix/; then
+ for i in *.so; do
+ m=${i#dict_}
+ m=${m%.so}
+ echo -e "$m\t/usr/lib/postfix/$i\tdict_${m}_open"
+ done
+fi
+
+echo '## AUTO END ##'
+) >> $conf
diff --git a/main/postfix/postfix-mysql.post-install b/main/postfix/postfix-mysql.post-install
new file mode 100644
index 0000000000..b8d23833b6
--- /dev/null
+++ b/main/postfix/postfix-mysql.post-install
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# update the dynamicmaps.cf
+conf=/etc/postfix/dynamicmaps.cf
+
+sed -i -e '/\#\# AUTO BEGIN/,/\#\# AUTO END/d' $conf
+
+(
+echo '## AUTO BEGIN ##'
+if cd /usr/lib/postfix/; then
+ for i in *.so; do
+ m=${i#dict_}
+ m=${m%.so}
+ echo -e "$m\t/usr/lib/postfix/$i\tdict_${m}_open"
+ done
+fi
+
+echo '## AUTO END ##'
+) >> $conf
diff --git a/main/postfix/postfix-pcre.post-install b/main/postfix/postfix-pcre.post-install
new file mode 100644
index 0000000000..f15b00cf75
--- /dev/null
+++ b/main/postfix/postfix-pcre.post-install
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# update the dynamicmaps.cf
+conf=/etc/postfix/dynamicmaps.cf
+
+sed -i -e '/\#\# AUTO BEGIN/,/\#\# AUTO END/d' $conf
+
+(
+echo '## AUTO BEGIN ##'
+if cd /usr/lib/postfix/; then
+ for i in *.so; do
+ m=${i#dict_}
+ m=${m%.so}
+ echo -e "$m\t/usr/lib/postfix/$i\tdict_${m}_open"
+ # pcre also handles regexp
+ if [ "$m" = "pcre" ]; then
+ echo -e "regex\t/usr/lib/postfix/$i\tdict_${m}_open"
+ fi
+
+ done
+fi
+
+echo '## AUTO END ##'
+) >> $conf
+
diff --git a/main/postfix/postfix-pgsql.post-install b/main/postfix/postfix-pgsql.post-install
new file mode 100644
index 0000000000..b8d23833b6
--- /dev/null
+++ b/main/postfix/postfix-pgsql.post-install
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# update the dynamicmaps.cf
+conf=/etc/postfix/dynamicmaps.cf
+
+sed -i -e '/\#\# AUTO BEGIN/,/\#\# AUTO END/d' $conf
+
+(
+echo '## AUTO BEGIN ##'
+if cd /usr/lib/postfix/; then
+ for i in *.so; do
+ m=${i#dict_}
+ m=${m%.so}
+ echo -e "$m\t/usr/lib/postfix/$i\tdict_${m}_open"
+ done
+fi
+
+echo '## AUTO END ##'
+) >> $conf
diff --git a/main/postfix/postfix-sqlite.post-install b/main/postfix/postfix-sqlite.post-install
new file mode 100644
index 0000000000..b8d23833b6
--- /dev/null
+++ b/main/postfix/postfix-sqlite.post-install
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# update the dynamicmaps.cf
+conf=/etc/postfix/dynamicmaps.cf
+
+sed -i -e '/\#\# AUTO BEGIN/,/\#\# AUTO END/d' $conf
+
+(
+echo '## AUTO BEGIN ##'
+if cd /usr/lib/postfix/; then
+ for i in *.so; do
+ m=${i#dict_}
+ m=${m%.so}
+ echo -e "$m\t/usr/lib/postfix/$i\tdict_${m}_open"
+ done
+fi
+
+echo '## AUTO END ##'
+) >> $conf
diff --git a/main/postfix/postfix.initd b/main/postfix/postfix.initd
new file mode 100644
index 0000000000..45f1b49ce0
--- /dev/null
+++ b/main/postfix/postfix.initd
@@ -0,0 +1,50 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/mail-mta/postfix/files/postfix.rc6.2.5,v 1.3 2008/08/18 14:18:40 falco Exp $
+
+# If you plan to simultaneously use several Postfix instances, don't forget
+# to specify your alternate_config_directories variable in your main main.cf file.
+# Then make a symlink from /etc/init.d/postfix to /etc/init.d/postfix.alt,
+# prepare your new /etc/postfix.alt environment, and at least change these working paths:
+# queue_directory = /var/spool/postfix.alt
+# data_directory = /var/lib/postfix.alt
+
+CONF_DIR="/etc/postfix"
+CONF_OPT="${SVCNAME##*.}"
+if [ -n ${CONF_OPT} -a ${SVCNAME} != "postfix" ]; then
+ CONF_DIR="${CONF_DIR}.${CONF_OPT}"
+fi
+
+opts="${opts} reload"
+
+depend() {
+ use logger dns ypbind amavisd mysql postgresql antivirus \
+ postfix_greylist net saslauthd
+ after firewall
+ if [ "${SVCNAME}" = "postfix" ]; then
+ provide mta
+ fi
+}
+
+start() {
+ ebegin "Starting postfix (${CONF_DIR})"
+ if [ ! -d ${CONF_DIR} ]; then
+ eend 1 "${CONF_DIR} does not exist"
+ return 1
+ fi
+ /usr/sbin/postfix -c ${CONF_DIR} start >/dev/null 2>&1
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping postfix (${CONF_DIR})"
+ /usr/sbin/postfix -c ${CONF_DIR} stop >/dev/null 2>&1
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading postfix (${CONF_DIR})"
+ /usr/sbin/postfix -c ${CONF_DIR} reload >/dev/null 2>&1
+ eend $?
+}
diff --git a/main/postfix/postfix.post-install b/main/postfix/postfix.post-install
new file mode 100644
index 0000000000..98e01db0bb
--- /dev/null
+++ b/main/postfix/postfix.post-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+chown postfix /var/spool/postfix/* /var/lib/postfix
+chgrp postdrop /var/spool/postfix/maildrop /var/spool/postfix/public
+
+exit 0
diff --git a/main/postfix/postfix.pre-install b/main/postfix/postfix.pre-install
new file mode 100644
index 0000000000..22414ef615
--- /dev/null
+++ b/main/postfix/postfix.pre-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+addgroup postfix 2>/dev/null
+addgroup postdrop 2>/dev/null
+adduser postfix -h /var/spool/postfix -G postfix,mail 2>/dev/null
+
+exit 0
diff --git a/main/postgresql/APKBUILD b/main/postgresql/APKBUILD
new file mode 100644
index 0000000000..9579e8b7d5
--- /dev/null
+++ b/main/postgresql/APKBUILD
@@ -0,0 +1,65 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=postgresql
+pkgver=9.0.4
+pkgrel=0
+pkgdesc="A sophisticated object-relational DBMS"
+url="http://www.postgresql.org/"
+arch="all"
+license="BSD"
+depends="bbsuid postgresql-client"
+install="$pkgname.pre-upgrade"
+depends_dev="readline-dev openssl-dev zlib-dev libxml2-dev"
+makedepends="$depends_dev"
+subpackages="$pkgname-dev $pkgname-doc libpq $pkgname-client"
+source="ftp://ftp.$pkgname.org/pub/source/v$pkgver/$pkgname-$pkgver.tar.bz2
+ $pkgname.initd
+ $pkgname.confd
+ pg-restore.initd
+ pg-restore.confd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver || return 1
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --with-docdir=/usr/share/doc \
+ --with-openssl \
+ || return 1
+
+ make world || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver || return 1
+ make DESTDIR="$pkgdir" install install-docs || return 1
+
+ install -D -m755 "$srcdir"/postgresql.initd \
+ "$pkgdir"/etc/init.d/postgresql || return 1
+ install -D -m644 "$srcdir"/postgresql.confd \
+ "$pkgdir"/etc/conf.d/postgresql || return 1
+ install -D -m755 "$srcdir"/pg-restore.initd \
+ "$pkgdir"/etc/init.d/pg-restore || return 1
+ install -D -m644 "$srcdir"/pg-restore.confd \
+ "$pkgdir"/etc/conf.d/pg-restore || return 1
+}
+
+libpq() {
+ depends=
+ pkgdesc="PostgreSQL libraries"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libpq.so* "$subpkgdir"/usr/lib/
+}
+
+client() {
+ depends=
+ pkgdesc="PostgreSQL client"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/psql "$subpkgdir"/usr/bin/
+}
+
+
+md5sums="80390514d568a7af5ab61db1cda27e29 postgresql-9.0.4.tar.bz2
+66c197b8186a6df0752fe2aed40c90c4 postgresql.initd
+c56a4db0c3757f5dc7f9d59132b428ba postgresql.confd
+7f8de63848c51c8a30c39bec6b1b1606 pg-restore.initd
+bf45384752b320b369f1425939763178 pg-restore.confd"
diff --git a/main/postgresql/pg-restore.confd b/main/postgresql/pg-restore.confd
new file mode 100644
index 0000000000..84a179f6cd
--- /dev/null
+++ b/main/postgresql/pg-restore.confd
@@ -0,0 +1,16 @@
+
+# Enable this to dump databases on shutdown and restore on boot
+#
+#PGDUMP="/var/lib/postgresql/backup/databases.pgdump"
+
+# The dump file will be deleted once restored unless KEEP_DUMP is set.
+# This is to avoid accidental restoring of running database. If you know what
+# you are doing and want keep the dump, then enable the KEEP_DUMP option
+# below.
+#
+#KEEP_DUMP=yes
+
+# If you enable KEEP_DUMP above you probably also want the --clean option
+# the the pg_dumpall command.
+#PG_DUMPALL_OPTS="--clean"
+
diff --git a/main/postgresql/pg-restore.initd b/main/postgresql/pg-restore.initd
new file mode 100644
index 0000000000..91c69d18f4
--- /dev/null
+++ b/main/postgresql/pg-restore.initd
@@ -0,0 +1,37 @@
+#!/sbin/runscript
+
+. /etc/conf.d/postgresql
+
+opts="${opts} dump restore"
+
+depend() {
+ need postgresql
+}
+
+restore() {
+ yesno "$PGDUMP" && return 0
+ ebegin "Restoring PostgreSQL $PGDUMP"
+ psql -U ${PG_USER:-postgres} ${PSQL_OPTS} -f "$PGDUMP" >/dev/null 2>/dev/null
+ yesno "$KEEP_DUMP" || rm -f "$PGDUMP"
+
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl reload " >/dev/null
+ eend $res
+}
+
+dump() {
+ yesno "$PGDUMP" && return 0
+ mkdir -p "$( dirname "$PGDUMP" )"
+ ebegin "Saving PostgreSQL databases to $PGDUMP"
+ pg_dumpall -U ${PG_USER:-postgres} ${PG_DUMPALL_OPTS} -f "$PGDUMP"
+ eend $?
+}
+
+start() {
+ restore
+}
+
+stop() {
+ dump
+}
+
diff --git a/main/postgresql/postgresql.confd b/main/postgresql/postgresql.confd
new file mode 100644
index 0000000000..942268c57a
--- /dev/null
+++ b/main/postgresql/postgresql.confd
@@ -0,0 +1,56 @@
+# PostgreSQL's Database Directory
+PGDATA="/var/lib/postgresql/9.0/data"
+
+# PostgreSQL User
+PGUSER="postgres"
+
+# PostgreSQL Group
+PGGROUP="postgres"
+
+# Extra options to run postmaster with, e.g.:
+# -N is the maximal number of client connections
+# -B is the number of shared buffers and has to be at least 2x the value for -N
+# Please read the man-page to postmaster for more options. Many of these options
+# can be set directly in the configuration-file.
+#PGOPTS="-N 512 -B 1024"
+
+
+# SERVER SHUTDOWN:
+# The server will receive 3 signals in the worst case:
+# 1. SIGTERM
+# This signals the server to ignore new connections and to
+# wait for all clients to end their transactions before shutting down.
+# Use WAIT_FOR_DISCONNECT to control how much time the clients
+# should have until the next signal is being sent.
+# 2. SIGINT
+# Tell the server to forcefully disconnect all clients.
+# Terminating a client results in a rollback of the open transactions for this client.
+# Use WAIT_FOR_CLEANUP to determine how much time the server has
+# for cleanup.
+# 3. SIGQUIT
+# This will terminate the server immediately and results in a recovery run for the next start.
+
+# Wait for clients to disconnect
+WAIT_FOR_DISCONNECT=30
+
+# Time the server has to clean up
+WAIT_FOR_CLEANUP=60
+
+# Time the server has to quit (with a recover-run on next startup)
+# Set to 0 to deactivate it
+WAIT_FOR_QUIT=60
+
+# Comment this out if you don't want to wait for the server to
+# startup before continuing. For example, if this server is a
+# PITR log shipping based replication standby
+WAIT_FOR_START="-w"
+
+# If you have to export environment variables for the database process,
+# this can be done here.
+#
+# Example:
+# export R_HOME="/usr/lib/R"
+
+# Automatically set up a new database if missing on startup
+AUTO_SETUP=yes
+
diff --git a/main/postgresql/postgresql.initd b/main/postgresql/postgresql.initd
new file mode 100644
index 0000000000..2de91d0df6
--- /dev/null
+++ b/main/postgresql/postgresql.initd
@@ -0,0 +1,138 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-db/postgresql-server/files/postgresql.init-8.3,v 1.4 2008/09/28 22:53:02 caleb Exp $
+# Modifications to support Alpine Linux pg-restore
+
+opts="${opts} reload setup"
+
+depend() {
+ use net
+ after firewall
+}
+
+checkconfig() {
+ [ -d "$PGDATA/base" ] && return 0
+ echo "checking config"
+
+ if [ -z "$AUTO_SETUP" ] ; then
+ eerror "Database not found at: $PGDATA"
+ eerror "Please make sure that PGDATA points to the right path."
+ eerror "You can run '/etc/init.d/postgresql setup' to setup a new database cluster."
+ return 1
+ fi
+ setup
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting PostgreSQL"
+
+ if [ -f "$PGDATA/postmaster.pid" ] ; then
+ rm -f "$PGDATA/postmaster.pid"
+ fi
+
+ local retval
+
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl start ${WAIT_FOR_START} -o '--silent-mode=true ${PGOPTS}'" >/dev/null
+ retval=$?
+ [ $retval -ne 0 ] && eend $retval && return $retval
+
+ # The following is to catch the case of an already running server
+ # in which pg_ctl doesn't know to which server it connected to and false reports the server as 'up'
+ sleep 2
+ if [ ! -f "$PGDATA/postmaster.pid" ] ; then
+ eerror "The pid-file doesn't exist but pg_ctl reported a running server."
+ eerror "Please check whether there is another server running on the same port or read the log-file."
+ eend 1
+ return 1
+ fi
+
+ local pid=$(grep "^[0-9]\+" "$PGDATA/postmaster.pid")
+ test -d /proc/"${pid}"
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping PostgreSQL (this can take up to $(( ${WAIT_FOR_DISCONNECT} + ${WAIT_FOR_CLEANUP} )) seconds)"
+
+ local retval
+
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl stop -t ${WAIT_FOR_DISCONNECT} -m smart" >/dev/null
+
+ retval=$?
+ [ $retval -eq 0 ] && eend $retval && return $retval
+
+ ewarn "Some clients did not disconnect within ${WAIT_FOR_DISCONNECT} seconds."
+ ewarn "Going to shutdown the server anyway."
+
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl stop -m fast" >/dev/null
+
+ retval=$?
+ [ $retval -eq 0 ] && eend $retval && return $retval
+
+ if [ ${WAIT_FOR_QUIT} -eq 0 ] ; then
+ eerror "Server did not shut down and sending the SIGQUIT has been disabled."
+ eend $retval
+ return $retval
+ fi
+
+ ewarn "Shutting down the server gracefully failed."
+ ewarn "Forcing it to shutdown which leads to a recover-run on next startup."
+
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl stop -m immediate" >/dev/null
+
+ retval=$?
+ [ $retval -eq 0 ] && eend $retval && return $retval
+
+ eerror "Forced shutdown failed!!! Something is wrong with your system, please take care of it manually."
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading PostgreSQL configuration"
+ su -l ${PGUSER} \
+ -c "env PGDATA=\"${PGDATA}\" /usr/bin/pg_ctl reload" >/dev/null
+ eend $?
+}
+
+setup() {
+ ebegin "Creating a new PostgreSQL database cluster"
+
+ if [ -d "${PGDATA}/base" ] ; then
+ eend 1 "${PGDATA}/base already exists"
+ return
+ fi
+
+ mkdir -p "${PGDATA}" 2>/dev/null
+
+ # If the pg_hba.conf and friends exist, move them
+ local tmpdir="$( dirname "$PGDATA" )/tmp"
+ mkdir -p "${tmpdir}" >/dev/null
+ echo mv "${PGDATA}"/* "${tmpdir}"
+ mv "${PGDATA}"/* "${tmpdir}" 2>/dev/null
+
+ rm -rf "${PGDATA}"/* 2>/dev/null
+ chown -Rf postgres:postgres "${PGDATA}"
+ chmod 0700 "${PGDATA}"
+ cd "${PGDATA}" # to avoid the: could not change directory to "/root"
+ su -c "/usr/bin/initdb --pgdata ${PGDATA}" postgres
+ einfo "You can use the '/etc/init.d/postgresql' script to run PostgreSQL instead"
+ einfo "of 'pg_ctl'."
+ local res=$?
+
+ # move the pg_hba.conf and friends
+ mv $tmpdir/* "$PGDATA" 2>/dev/null
+ rm -rf $tmpdir 2>/dev/null
+
+ # Do not send a SIGHUP to postmaster; its not necessary for a new database
+ # and allows pg-restore to do a blind restore of an old database
+
+ eend $res
+}
+
diff --git a/main/postgresql/postgresql.pre-upgrade b/main/postgresql/postgresql.pre-upgrade
new file mode 100644
index 0000000000..989e021673
--- /dev/null
+++ b/main/postgresql/postgresql.pre-upgrade
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+
+new="$1"
+old="$2"
+compare=$(apk version -t "$old" 8.4)
+
+# check if we upgrade from earlier than 8.4 and if it is running
+if [ "$compare" != "<" ] || ! /etc/init.d/postgresql --quiet status; then
+ exit 0
+fi
+
+if [ -f /etc/conf.d/postgresql ]; then
+ . /etc/conf.d/postgresql
+fi
+
+cat <<EOF
+* You are upgrading to postgres 8.4 wich is not compatible with the running
+* See: http://www.postgresql.org/docs/8.4/interactive/install-upgrading.html
+*
+* The corresponding steps for Alpine Linux is:
+*
+* pg_dumpall -U ${PGUSER:-postgres} > dumpfile
+* /etc/init.d/postgresql stop
+* apk add -u postgresql
+* /etc/init.d/postgresql setup
+* /etc/init.d/postgresql start
+* psql -U ${PGUSER:-postgres} -f dumpfile
+*
+EOF
+exit 1
diff --git a/main/postgrey/APKBUILD b/main/postgrey/APKBUILD
new file mode 100644
index 0000000000..1d215427fa
--- /dev/null
+++ b/main/postgrey/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=postgrey
+pkgver=1.33
+pkgrel=0
+pkgdesc="Postfix policy server implementing greylisting"
+url="http://postgrey.schweikert.ch/"
+arch="noarch"
+license="GPL"
+depends="perl perl-db perl-net-dns perl-net-server perl-io-multiplex
+ perl-net-rblclient perl-parse-syslog"
+pkgusers="postgrey"
+pkggroups="postgrey"
+makedepends=""
+install=postgrey.pre-install
+subpackages=""
+source="http://postgrey.schweikert.ch/pub/$pkgname-$pkgver.tar.gz
+ postgrey.confd
+ postgrey.initd"
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ install -m755 -D $pkgname "$pkgdir"/usr/sbin/$pkgname
+ mkdir -p "$pkgdir"/var/spool/postfix/$pkgname
+ chown postgrey:postgrey "$pkgdir"/var/spool/postfix/$pkgname
+ chmod 770 "$pkgdir"/var/spool/postfix/$pkgname
+ install -m755 -D contrib/postgreyreport "$pkgdir"/usr/bin/postgreyreport
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D postgrey_whitelist_clients "$pkgdir"/etc/postfix/postgrey_whitelist_clients
+ install -m644 -D postgrey_whitelist_recipients "$pkgdir"/etc/postfix/postgrey_whitelist_recipients
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="334c908bb9d34e9b87790d4b0b6db87e postgrey-1.33.tar.gz
+caaad5770ab07fb5af3bbd522a05b84f postgrey.confd
+d0611b244202c77ad7ad79862721a738 postgrey.initd"
diff --git a/main/postgrey/postgrey.confd b/main/postgrey/postgrey.confd
new file mode 100644
index 0000000000..7a6deb587f
--- /dev/null
+++ b/main/postgrey/postgrey.confd
@@ -0,0 +1,55 @@
+# Config file for /etc/init.d/postgrey
+
+# LISTEN TYPE
+# Set to 'inet' if you want to use a TCP socket.
+# Set to 'unix' if you want to use an UNIX socket.
+POSTGREY_TYPE="inet"
+
+# HOST
+# What IP should postgrey bind to?
+# Leave unchanged unless you know what you are doing.
+# (ignored if POSTGREY_TYPE is set to 'unix')
+POSTGREY_HOST="127.0.0.1"
+
+# PORT
+# What TCP port should postgrey listen on?
+# (ignored if POSTGREY_TYPE is set to 'unix')
+POSTGREY_PORT="10030"
+
+# SOCKET
+# Unix socket to listen on, if POSTGREY_TYPE is set to 'unix'.
+# Leave unchanged unless you know what you are doing.
+# (ignored if POSTGREY_TYPE is set to 'inet')
+POSTGREY_SOCKET="/var/spool/postfix/private/postgrey"
+
+# PID
+# Postgrey pid file.
+# Do not change, if you don't know what this is!
+POSTGREY_PID="/var/run/postgrey.pid"
+
+# DELAY
+# How long to delay mail that is greylisted in seconds.
+POSTGREY_DELAY=300
+
+# TEXT
+# The response we'll send back with delayed mail.
+POSTGREY_TEXT="Greylisted for %s seconds"
+
+# Additional Postgrey options
+#
+# -v, --verbose increase verbosity level
+# --max-age=N delete entries older than N days since the last time
+# that they have been seen (default: 30)
+# --retry-window=N allow only N days for the first retrial (default: 2)
+# append 'h' if you want to specify it in hours
+# --greylist-action=A if greylisted, return A to Postfix (default: DEFER_IF_PERMIT)
+# --lookup-by-subnet strip the last 8 bits from IP addresses (default)
+# --lookup-by-host do not strip the last 8 bits from IP addresses
+# --whitelist-clients=FILE default: /etc/postfix/postgrey_whitelist_clients
+# --whitelist-recipients=FILE default: /etc/postfix/postgrey_whitelist_recipients
+#
+# Note that the --whitelist-x options can be specified multiple times, and that
+# per default /etc/postfix/postgrey_whitelist_clients.local is also read, so
+# that you can put there local entries.
+#
+POSTGREY_OPTS=""
diff --git a/main/postgrey/postgrey.initd b/main/postgrey/postgrey.initd
new file mode 100644
index 0000000000..c9e51ceba9
--- /dev/null
+++ b/main/postgrey/postgrey.initd
@@ -0,0 +1,102 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/mail-filter/postgrey/files/postgrey.rc.new,v 1.10 2008/05/21 18:45:44 dertobi123 Exp $
+
+conf="/etc/conf.d/postgrey"
+
+opts="${opts} reload"
+
+depend() {
+ need net
+ after firewall
+ before postfix
+ provide postfix_greylist
+}
+
+conf_error() {
+ eerror "You need to setup ${conf} first"
+ return 1
+}
+
+checkconfig() {
+if [ -z "${POSTGREY_TYPE}" ]
+ then
+ einfo "You need to choose the server type you want"
+ einfo "by setting the POSTGREY_TYPE variable in ${conf}."
+ else
+ if [ "x${POSTGREY_TYPE}" = "xinet" ]
+ then
+ if [ -z "${POSTGREY_PORT}" ] || [ -z "${POSTGREY_HOST}" ]
+ then
+ einfo "The following entries are missing in ${conf}:"
+ [ -z "${POSTGREY_HOST}" ] && einfo " - POSTGREY_HOST"
+ [ -z "${POSTGREY_PORT}" ] && einfo " - POSTGREY_PORT"
+ conf_error
+ fi
+ POSTGREY_ADDR="${POSTGREY_TYPE}=${POSTGREY_HOST}:${POSTGREY_PORT}"
+ else
+ if [ -z "${POSTGREY_SOCKET}" ]
+ then
+ einfo "The following entries are missing in ${conf}:"
+ [ -z "${POSTGREY_SOCKET}" ] && einfo " - POSTGREY_SOCKET"
+ conf_error
+ fi
+ POSTGREY_ADDR="${POSTGREY_TYPE}=${POSTGREY_SOCKET}"
+ fi
+fi
+
+ if [ -z "${POSTGREY_PID}" ]
+ then
+ einfo "The following entries are missing in ${conf}:"
+ [ -z "${POSTGREY_PID}" ] && einfo " - POSTGREY_PID"
+ conf_error
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting Postgrey"
+
+ # HACK -- start a subshell and corrects perms on the socket...
+ ( if [ "x${POSTGREY_TYPE}" = "xunix" ]; then
+ rm -f ${POSTGREY_SOCKET};
+ while ! test -S ${POSTGREY_SOCKET}; do sleep 1; done;
+ chmod a+rw,a-x ${POSTGREY_SOCKET}; fi ) &
+
+ if [ -z ${POSTGREY_DELAY} ] ; then
+ POSTGREY_DELAY_ARG=""
+ else
+ POSTGREY_DELAY_ARG="--delay=${POSTGREY_DELAY}"
+ fi
+
+ if [ -z "${POSTGREY_TEXT}" ] ; then
+ POSTGREY_TEXT_ARG=""
+ else
+ POSTGREY_TEXT_ARG="--greylist-text=${POSTGREY_TEXT}"
+ fi
+
+ start-stop-daemon --start --quiet --background \
+ --pidfile=${POSTGREY_PID} \
+ --name postgrey \
+ --exec /usr/sbin/postgrey -- \
+ --${POSTGREY_ADDR} \
+ --daemonize \
+ --pidfile=${POSTGREY_PID} \
+ ${POSTGREY_DELAY_ARG} \
+ ${POSTGREY_OPTS} \
+ "${POSTGREY_TEXT_ARG}"
+ eend ${?}
+}
+
+stop() {
+ ebegin "Stopping Postgrey"
+ start-stop-daemon --stop --quiet --pidfile ${POSTGREY_PID}
+ eend ${?}
+}
+
+reload() {
+ ebegin "Reloading Postgrey"
+ start-stop-daemon --stop --signal HUP --oknodo --pidfile ${POSTGREY_PID}
+ eend $?
+}
diff --git a/main/postgrey/postgrey.pre-install b/main/postgrey/postgrey.pre-install
new file mode 100644
index 0000000000..3c34c3fd5f
--- /dev/null
+++ b/main/postgrey/postgrey.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+addgroup postgrey 2>/dev/null
+adduser -H -h /dev/null -s /bin/false -D postgrey 2>/dev/null
+
+exit 0
diff --git a/main/pound/APKBUILD b/main/pound/APKBUILD
new file mode 100644
index 0000000000..c76eae0ae8
--- /dev/null
+++ b/main/pound/APKBUILD
@@ -0,0 +1,41 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pound
+pkgver=2.5
+pkgrel=3
+pkgdesc="A reverse proxy, load balancer, and SSL wrapper"
+url="http://www.apsis.ch/pound/index_html"
+arch="all"
+license="GPL"
+depends=
+makedepends="pcre-dev openssl-dev"
+subpackages="$pkgname-doc"
+source="http://www.apsis.ch/$pkgname/Pound-$pkgver.tgz
+ pound.cfg
+ pound-2.5-openssl.patch
+ $pkgname.initd"
+
+_builddir="$srcdir"/Pound-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ patch -p1 -i "$i" || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --sysconfdir=/etc/pound
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir"/usr/sbin
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm755 "$srcdir"/pound.initd "$pkgdir"/etc/init.d/pound
+ install -Dm644 "$srcdir"/pound.cfg "$pkgdir"/etc/pound.cfg
+}
+md5sums="8a39f5902094619afcda7d12d9d8342c Pound-2.5.tgz
+736b12a47acbb7fc2802ed7f51e959d0 pound.cfg
+c2c48dc395ffc045f9d35394992292d0 pound-2.5-openssl.patch
+074fc58c89bb70e8fcd767ee70ebd0f0 pound.initd"
diff --git a/main/pound/pound-2.5-openssl.patch b/main/pound/pound-2.5-openssl.patch
new file mode 100644
index 0000000000..efefd54879
--- /dev/null
+++ b/main/pound/pound-2.5-openssl.patch
@@ -0,0 +1,290 @@
+diff -up Pound-2.5/config.c.openssl Pound-2.5/config.c
+--- Pound-2.5/config.c.openssl 2010-02-10 12:23:09.000000000 +0100
++++ Pound-2.5/config.c 2010-02-10 12:23:07.000000000 +0100
+@@ -431,14 +431,22 @@ t_hash(const TABNODE *e)
+ res = (res ^ *k++) * 16777619;
+ return res;
+ }
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++static IMPLEMENT_LHASH_HASH_FN(t, TABNODE)
++#else
+ static IMPLEMENT_LHASH_HASH_FN(t_hash, const TABNODE *)
++#endif
+
+ static int
+ t_cmp(const TABNODE *d1, const TABNODE *d2)
+ {
+ return strcmp(d1->key, d2->key);
+ }
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++static IMPLEMENT_LHASH_COMP_FN(t, TABNODE)
++#else
+ static IMPLEMENT_LHASH_COMP_FN(t_cmp, const TABNODE *)
++#endif
+
+ /*
+ * parse a service
+@@ -460,7 +468,11 @@ parse_service(const char *svc_name)
+ pthread_mutex_init(&res->mut, NULL);
+ if(svc_name)
+ strncpy(res->name, svc_name, KEY_SIZE);
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ if((res->sessions = LHM_lh_new(TABNODE, t)) == NULL)
++#else
+ if((res->sessions = lh_new(LHASH_HASH_FN(t_hash), LHASH_COMP_FN(t_cmp))) == NULL)
++#endif
+ conf_err("lh_new failed - aborted");
+ ign_case = ignore_case;
+ while(conf_fgets(lin, MAXBUF)) {
+diff -up Pound-2.5/pound.h.openssl Pound-2.5/pound.h
+--- Pound-2.5/pound.h.openssl 2010-02-02 12:49:02.000000000 +0100
++++ Pound-2.5/pound.h 2010-02-10 12:15:18.000000000 +0100
+@@ -322,6 +322,10 @@ typedef struct _tn {
+ /* maximal session key size */
+ #define KEY_SIZE 127
+
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++DECLARE_LHASH_OF(TABNODE);
++#endif
++
+ /* service definition */
+ typedef struct _service {
+ char name[KEY_SIZE + 1]; /* symbolic name */
+@@ -337,7 +341,11 @@ typedef struct _service {
+ int sess_ttl; /* session time-to-live */
+ regex_t sess_start; /* pattern to identify the session data */
+ regex_t sess_pat; /* pattern to match the session data */
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ LHASH_OF(TABNODE) *sessions; /* currently active sessions */
++#else
+ LHASH *sessions; /* currently active sessions */
++#endif
+ int dynscale; /* true if the back-ends should be dynamically rescaled */
+ int disabled; /* true if the service is disabled */
+ struct _service *next;
+diff -up Pound-2.5/svc.c.openssl Pound-2.5/svc.c
+--- Pound-2.5/svc.c.openssl 2010-02-02 12:49:02.000000000 +0100
++++ Pound-2.5/svc.c 2010-02-10 12:13:29.000000000 +0100
+@@ -27,12 +27,17 @@
+
+ #include "pound.h"
+
++#ifndef LHASH_OF
++#define LHASH_OF(x) LHASH
++#define CHECKED_LHASH_OF(type, h) h
++#endif
++
+ /*
+ * Add a new key/content pair to a hash table
+ * the table should be already locked
+ */
+ static void
+-t_add(LHASH *const tab, const char *key, const void *content, const size_t cont_len)
++t_add(LHASH_OF(TABNODE) *const tab, const char *key, const void *content, const size_t cont_len)
+ {
+ TABNODE *t, *old;
+
+@@ -53,7 +58,11 @@ t_add(LHASH *const tab, const char *key,
+ }
+ memcpy(t->content, content, cont_len);
+ t->last_acc = time(NULL);
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ if((old = LHM_lh_insert(TABNODE, tab, t)) != NULL) {
++#else
+ if((old = (TABNODE *)lh_insert(tab, t)) != NULL) {
++#endif
+ free(old->key);
+ free(old->content);
+ free(old);
+@@ -68,12 +77,16 @@ t_add(LHASH *const tab, const char *key,
+ * side-effect: update the time of last access
+ */
+ static void *
+-t_find(LHASH *const tab, char *const key)
++t_find(LHASH_OF(TABNODE) *const tab, char *const key)
+ {
+ TABNODE t, *res;
+
+ t.key = key;
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ if((res = LHM_lh_retrieve(TABNODE, tab, &t)) != NULL) {
++#else
+ if((res = (TABNODE *)lh_retrieve(tab, &t)) != NULL) {
++#endif
+ res->last_acc = time(NULL);
+ return res->content;
+ }
+@@ -84,12 +97,16 @@ t_find(LHASH *const tab, char *const key
+ * Delete a key
+ */
+ static void
+-t_remove(LHASH *const tab, char *const key)
++t_remove(LHASH_OF(TABNODE) *const tab, char *const key)
+ {
+ TABNODE t, *res;
+
+ t.key = key;
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ if((res = LHM_lh_delete(TABNODE, tab, &t)) != NULL) {
++#else
+ if((res = (TABNODE *)lh_delete(tab, &t)) != NULL) {
++#endif
+ free(res->key);
+ free(res->content);
+ free(res);
+@@ -98,59 +115,75 @@ t_remove(LHASH *const tab, char *const k
+ }
+
+ typedef struct {
+- LHASH *tab;
++ LHASH_OF(TABNODE) *tab;
+ time_t lim;
+ void *content;
+ int cont_len;
+ } ALL_ARG;
+
+ static void
+-t_old(TABNODE *t, void *arg)
++t_old_doall_arg(TABNODE *t, ALL_ARG *a)
+ {
+- ALL_ARG *a;
+-
+- a = (ALL_ARG *)arg;
+ if(t->last_acc < a->lim)
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ LHM_lh_delete(TABNODE, a->tab, t);
++#else
+ lh_delete(a->tab, t);
++#endif
+ return;
+ }
+-IMPLEMENT_LHASH_DOALL_ARG_FN(t_old, TABNODE *, void *)
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++IMPLEMENT_LHASH_DOALL_ARG_FN(t_old, TABNODE, ALL_ARG)
++#else
++#define t_old t_old_doall_arg
++IMPLEMENT_LHASH_DOALL_ARG_FN(t_old, TABNODE *, ALL_ARG *)
++#endif
+
+ /*
+ * Expire all old nodes
+ */
+ static void
+-t_expire(LHASH *const tab, const time_t lim)
++t_expire(LHASH_OF(TABNODE) *const tab, const time_t lim)
+ {
+ ALL_ARG a;
+ int down_load;
+
+ a.tab = tab;
+ a.lim = lim;
+- down_load = tab->down_load;
+- tab->down_load = 0;
++ down_load = CHECKED_LHASH_OF(TABNODE, tab)->down_load;
++ CHECKED_LHASH_OF(TABNODE, tab)->down_load = 0;
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ LHM_lh_doall_arg(TABNODE, tab, LHASH_DOALL_ARG_FN(t_old), ALL_ARG, &a);
++#else
+ lh_doall_arg(tab, LHASH_DOALL_ARG_FN(t_old), &a);
+- tab->down_load = down_load;
++#endif
++ CHECKED_LHASH_OF(TABNODE, tab)->down_load = down_load;
+ return;
+ }
+
+ static void
+-t_cont(TABNODE *t, void *arg)
++t_cont_doall_arg(TABNODE *t, ALL_ARG *a)
+ {
+- ALL_ARG *a;
+-
+- a = (ALL_ARG *)arg;
+ if(memcmp(t->content, a->content, a->cont_len) == 0)
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ LHM_lh_delete(TABNODE, a->tab, t);
++#else
+ lh_delete(a->tab, t);
++#endif
+ return;
+ }
+-IMPLEMENT_LHASH_DOALL_ARG_FN(t_cont, TABNODE *, void *)
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++IMPLEMENT_LHASH_DOALL_ARG_FN(t_cont, TABNODE, ALL_ARG)
++#else
++#define t_cont t_cont_doall_arg
++IMPLEMENT_LHASH_DOALL_ARG_FN(t_cont, TABNODE *, ALL_ARG *)
++#endif
+
+ /*
+ * Remove all nodes with the given content
+ */
+ static void
+-t_clean(LHASH *const tab, void *const content, const size_t cont_len)
++t_clean(LHASH_OF(TABNODE) *const tab, void *const content, const size_t cont_len)
+ {
+ ALL_ARG a;
+ int down_load;
+@@ -158,10 +191,14 @@ t_clean(LHASH *const tab, void *const co
+ a.tab = tab;
+ a.content = content;
+ a.cont_len = cont_len;
+- down_load = tab->down_load;
+- tab->down_load = 0;
++ down_load = CHECKED_LHASH_OF(TABNODE, tab)->down_load;
++ CHECKED_LHASH_OF(TABNODE, tab)->down_load = 0;
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ LHM_lh_doall_arg(TABNODE, tab, LHASH_DOALL_ARG_FN(t_cont), ALL_ARG, &a);
++#else
+ lh_doall_arg(tab, LHASH_DOALL_ARG_FN(t_cont), &a);
+- tab->down_load = down_load;
++#endif
++ CHECKED_LHASH_OF(TABNODE, tab)->down_load = down_load;
+ return;
+ }
+
+@@ -1410,13 +1447,11 @@ typedef struct {
+ } DUMP_ARG;
+
+ static void
+-t_dump(TABNODE *t, void *arg)
++t_dump_doall_arg(TABNODE *t, DUMP_ARG *a)
+ {
+- DUMP_ARG *a;
+ BACKEND *be, *bep;
+ int n_be, sz;
+
+- a = (DUMP_ARG *)arg;
+ memcpy(&bep, t->content, sizeof(bep));
+ for(n_be = 0, be = a->backends; be; be = be->next, n_be++)
+ if(be == bep)
+@@ -1432,19 +1467,28 @@ t_dump(TABNODE *t, void *arg)
+ return;
+ }
+
+-IMPLEMENT_LHASH_DOALL_ARG_FN(t_dump, TABNODE *, void *)
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++IMPLEMENT_LHASH_DOALL_ARG_FN(t_dump, TABNODE, DUMP_ARG)
++#else
++#define t_dump t_dump_doall_arg
++IMPLEMENT_LHASH_DOALL_ARG_FN(t_dump, TABNODE *, DUMP_ARG *)
++#endif
+
+ /*
+ * write sessions to the control socket
+ */
+ static void
+-dump_sess(const int control_sock, LHASH *const sess, BACKEND *const backends)
++dump_sess(const int control_sock, LHASH_OF(TABNODE) *const sess, BACKEND *const backends)
+ {
+ DUMP_ARG a;
+
+ a.control_sock = control_sock;
+ a.backends = backends;
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ LHM_lh_doall_arg(TABNODE, sess, LHASH_DOALL_ARG_FN(t_dump), DUMP_ARG, &a);
++#else
+ lh_doall_arg(sess, LHASH_DOALL_ARG_FN(t_dump), &a);
++#endif
+ return;
+ }
+
diff --git a/main/pound/pound.cfg b/main/pound/pound.cfg
new file mode 100644
index 0000000000..664ea53c9e
--- /dev/null
+++ b/main/pound/pound.cfg
@@ -0,0 +1,54 @@
+## Minimal sample pound.cfg
+##
+## see pound(8) for details
+
+
+######################################################################
+## global options:
+
+User "nobody"
+Group "nobody"
+#RootJail /chroot/pound
+
+## Logging: (goes to syslog by default)
+## 0 no logging
+## 1 normal
+## 2 extended
+## 3 Apache-style (common log format)
+LogLevel 1
+
+## check backend every X secs:
+Alive 30
+
+## use hardware-accelleration card supported by openssl(1):
+#SSLEngine <hw>
+
+
+######################################################################
+## listen, redirect and ... to:
+
+## redirect all requests on port 8888 ("ListenHTTP") to the local webserver see "UrlGroup" below):
+ListenHTTP
+Address 127.0.0.1
+Port 8888
+
+## allow PUT and DELETE also (by default only GET, POST and HEAD)?:
+xHTTP 0
+
+Service
+URL ".*"
+
+BackEnd
+Address 127.0.0.1
+Port 80
+Priority 1
+
+## End Backend
+End
+
+## End Service
+End
+
+## End listener
+End
+
diff --git a/main/pound/pound.initd b/main/pound/pound.initd
new file mode 100644
index 0000000000..135139404c
--- /dev/null
+++ b/main/pound/pound.initd
@@ -0,0 +1,26 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/www-servers/pound/files/pound.init-1.9,v 1.1 2005/07/07 15:45:08 mkennedy Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting pound"
+ if [ ! -f "/etc/pound.cfg" ]; then
+ eend 1 "configfile /etc/pound.cfg not found."
+ fi
+ start-stop-daemon --quiet --start --exec /usr/sbin/pound \
+ -- -f /etc/pound.cfg -p /var/run/pound.pid
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping pound"
+ start-stop-daemon --quiet --stop --pidfile /var/run/pound.pid
+ eend $?
+}
+
diff --git a/main/ppp/APKBUILD b/main/ppp/APKBUILD
new file mode 100644
index 0000000000..c3907106ca
--- /dev/null
+++ b/main/ppp/APKBUILD
@@ -0,0 +1,67 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ppp
+pkgver=2.4.5
+pkgrel=6
+pkgdesc="A daemon which implements the PPP protocol for dial-up networking"
+url="http://www.samba.org/ppp/"
+arch="all"
+license="custom:GPL/BSD"
+depends=
+makedepends="libpcap-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.samba.org/pub/$pkgname/$pkgname-$pkgver.tar.gz
+ options
+ pon
+ poff
+ plog
+ pon.1
+ ip-up
+ ip-down"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build () {
+ cd "$_builddir"
+
+ # fix CFLAGS
+ # -D_GNU_SOURCE is needed for IPv6 to work apparently
+ export CFLAGS="$CFLAGS -D_GNU_SOURCE"
+ sed -i "s:-O2 -pipe -Wall -g:${CFLAGS}:" pppd/Makefile.linux
+ sed -i "s:-g -O2:${CFLAGS}:" pppd/plugins/Makefile.linux
+ sed -i "s:-O2:${CFLAGS}:" pppstats/Makefile.linux
+ sed -i "s:-O2 -g -pipe:${CFLAGS}:" chat/Makefile.linux
+ sed -i "s:-O:${CFLAGS}:" pppdump/Makefile.linux
+ # enable active filter
+ sed -i "s:^#FILTER=y:FILTER=y:" pppd/Makefile.linux
+ # enable ipv6 support
+ sed -i "s:^#HAVE_INET6=y:HAVE_INET6=y:" pppd/Makefile.linux
+ # Enable Microsoft proprietary Callback Control Protocol
+ sed -i "s:^#CBCP=y:CBCP=y:" pppd/Makefile.linux
+ # Fix build error with recent kernels
+ rm include/linux/if_pppol2tp.h
+ ./configure --prefix=/usr
+ make COPTS="$CFLAGS" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make INSTROOT="$pkgdir" install
+
+ install -D -m644 "$srcdir"/options "$pkgdir"/etc/ppp/options
+ install -D -m755 "$srcdir"/ip-up "$pkgdir"/etc/ppp/ip-up
+ install -D -m755 "$srcdir"/ip-down "$pkgdir"/etc/ppp/ip-down
+ install -D -m755 "$srcdir"/pon "$pkgdir"/usr/bin/pon
+ install -D -m755 "$srcdir"/poff "$pkgdir"/usr/bin/poff
+ install -D -m755 "$srcdir"/plog "$pkgdir"/usr/sbin/plog
+ install -D -m600 etc.ppp/pap-secrets "$pkgdir"/etc/ppp/pap-secrets
+ install -D -m600 etc.ppp/chap-secrets "$pkgdir"/etc/ppp/chap-secrets
+ install -D -m644 "$srcdir"/pon.1 "$pkgdir"/usr/share/man/man1/pon.1
+ mkdir -p "$pkgdir"/etc/ppp/peers
+}
+md5sums="4621bc56167b6953ec4071043fe0ec57 ppp-2.4.5.tar.gz
+9185f645bb433b22a9951d9d12f79c35 options
+48c024f73a80c8b69c4def22f86902cc pon
+2d811f8470ccdea3b8c4505a438483e9 poff
+86cdaf133f7a79fb464f02d83afc7734 plog
+44cc662ba9aa61dd9add3ddd4c5ded57 pon.1
+fac0c773490371ea673f4be0977a230f ip-up
+a88b40b1bf91eb5cca3762b7195e4fe2 ip-down"
diff --git a/main/ppp/ip-down b/main/ppp/ip-down
new file mode 100644
index 0000000000..3a88c496b8
--- /dev/null
+++ b/main/ppp/ip-down
@@ -0,0 +1,4 @@
+#!/bin/sh
+#
+# This script is run by pppd after the connection has ended.
+#
diff --git a/main/ppp/ip-up b/main/ppp/ip-up
new file mode 100644
index 0000000000..57e09c0047
--- /dev/null
+++ b/main/ppp/ip-up
@@ -0,0 +1,4 @@
+#!/bin/sh
+#
+# This script is run by pppd when there's a successful ppp connection.
+#
diff --git a/main/ppp/options b/main/ppp/options
new file mode 100644
index 0000000000..0d3a80df00
--- /dev/null
+++ b/main/ppp/options
@@ -0,0 +1,356 @@
+# /etc/ppp/options
+#
+# Originally created by Jim Knoble <jmknoble@mercury.interpath.net>
+# Modified for Debian by alvar Bray <alvar@meiko.co.uk>
+# Modified for PPP Server setup by Christoph Lameter <clameter@debian.org>
+# Modified for ArchLinux by Manolis Tzanidakis <manolis@archlinux.org>
+#
+# To quickly see what options are active in this file, use this command:
+# egrep -v '#|^ *$' /etc/ppp/options
+
+# Specify which DNS Servers the incoming Win95 or WinNT Connection should use
+# Two Servers can be remotely configured
+# ms-dns 192.168.1.1
+# ms-dns 192.168.1.2
+
+# Specify which WINS Servers the incoming connection Win95 or WinNT should use
+# ms-wins 192.168.1.50
+# ms-wins 192.168.1.51
+
+# Run the executable or shell command specified after pppd has
+# terminated the link. This script could, for example, issue commands
+# to the modem to cause it to hang up if hardware modem control signals
+# were not available.
+#disconnect "chat -- \d+++\d\c OK ath0 OK"
+
+# async character map -- 32-bit hex; each bit is a character
+# that needs to be escaped for pppd to receive it. 0x00000001
+# represents '\x01', and 0x80000000 represents '\x1f'.
+asyncmap 0
+
+# Require the peer to authenticate itself before allowing network
+# packets to be sent or received.
+# Please do not disable this setting. It is expected to be standard in
+# future releases of pppd. Use the call option (see manpage) to disable
+# authentication for specific peers.
+auth
+
+# Use hardware flow control (i.e. RTS/CTS) to control the flow of data
+# on the serial port.
+crtscts
+
+# Use software flow control (i.e. XON/XOFF) to control the flow of data
+# on the serial port.
+#xonxoff
+
+# Specifies that certain characters should be escaped on transmission
+# (regardless of whether the peer requests them to be escaped with its
+# async control character map). The characters to be escaped are
+# specified as a list of hex numbers separated by commas. Note that
+# almost any character can be specified for the escape option, unlike
+# the asyncmap option which only allows control characters to be
+# specified. The characters which may not be escaped are those with hex
+# values 0x20 - 0x3f or 0x5e.
+#escape 11,13,ff
+
+# Don't use the modem control lines.
+#local
+
+# Specifies that pppd should use a UUCP-style lock on the serial device
+# to ensure exclusive access to the device.
+lock
+
+# Don't show the passwords when logging the contents of PAP packets.
+# This is the default.
+hide-password
+
+# When logging the contents of PAP packets, this option causes pppd to
+# show the password string in the log message.
+#show-password
+
+# Use the modem control lines. On Ultrix, this option implies hardware
+# flow control, as for the crtscts option. (This option is not fully
+# implemented.)
+modem
+
+# Set the MRU [Maximum Receive Unit] value to <n> for negotiation. pppd
+# will ask the peer to send packets of no more than <n> bytes. The
+# minimum MRU value is 128. The default MRU value is 1500. A value of
+# 296 is recommended for slow links (40 bytes for TCP/IP header + 256
+# bytes of data).
+#mru 542
+
+# Set the interface netmask to <n>, a 32 bit netmask in "decimal dot"
+# notation (e.g. 255.255.255.0).
+#netmask 255.255.255.0
+
+# Disables the default behaviour when no local IP address is specified,
+# which is to determine (if possible) the local IP address from the
+# hostname. With this option, the peer will have to supply the local IP
+# address during IPCP negotiation (unless it specified explicitly on the
+# command line or in an options file).
+#noipdefault
+
+# Enables the "passive" option in the LCP. With this option, pppd will
+# attempt to initiate a connection; if no reply is received from the
+# peer, pppd will then just wait passively for a valid LCP packet from
+# the peer (instead of exiting, as it does without this option).
+#passive
+
+# With this option, pppd will not transmit LCP packets to initiate a
+# connection until a valid LCP packet is received from the peer (as for
+# the "passive" option with old versions of pppd).
+#silent
+
+# Don't request or allow negotiation of any options for LCP and IPCP
+# (use default values).
+#-all
+
+# Disable Address/Control compression negotiation (use default, i.e.
+# address/control field disabled).
+#-ac
+
+# Disable asyncmap negotiation (use the default asyncmap, i.e. escape
+# all control characters).
+#-am
+
+# Don't fork to become a background process (otherwise pppd will do so
+# if a serial device is specified).
+#-detach
+
+# Fork to background once the ppp interface is up
+#updetach
+
+# Disable IP address negotiation (with this option, the remote IP
+# address must be specified with an option on the command line or in
+# an options file).
+#-ip
+
+# Disable IPCP negotiation and IP communication. This option should
+# only be required if the peer is buggy and gets confused by requests
+# from pppd for IPCP negotiation.
+#noip
+
+# Disable magic number negotiation. With this option, pppd cannot
+# detect a looped-back line.
+#-mn
+
+# Disable MRU [Maximum Receive Unit] negotiation (use default, i.e.
+# 1500).
+#-mru
+
+# Disable protocol field compression negotiation (use default, i.e.
+# protocol field compression disabled).
+#-pc
+
+# Require the peer to authenticate itself using PAP.
+#+pap
+
+# Don't agree to authenticate using PAP.
+#-pap
+
+# Require the peer to authenticate itself using CHAP [Cryptographic
+# Handshake Authentication Protocol] authentication.
+#+chap
+
+# Don't agree to authenticate using CHAP.
+#-chap
+
+# Disable negotiation of Van Jacobson style IP header compression (use
+# default, i.e. no compression).
+#-vj
+
+# Increase debugging level (same as -d). If this option is given, pppd
+# will log the contents of all control packets sent or received in a
+# readable form. The packets are logged through syslog with facility
+# daemon and level debug. This information can be directed to a file by
+# setting up /etc/syslog.conf appropriately (see syslog.conf(5)). (If
+# pppd is compiled with extra debugging enabled, it will log messages
+# using facility local2 instead of daemon).
+#debug
+
+# Append the domain name <d> to the local host name for authentication
+# purposes. For example, if gethostname() returns the name porsche,
+# but the fully qualified domain name is porsche.Quotron.COM, you would
+# use the domain option to set the domain name to Quotron.COM.
+#domain <d>
+
+# Enable debugging code in the kernel-level PPP driver. The argument n
+# is a number which is the sum of the following values: 1 to enable
+# general debug messages, 2 to request that the contents of received
+# packets be printed, and 4 to request that the contents of transmitted
+# packets be printed.
+#kdebug n
+
+# Set the MTU [Maximum Transmit Unit] value to <n>. Unless the peer
+# requests a smaller value via MRU negotiation, pppd will request that
+# the kernel networking code send data packets of no more than n bytes
+# through the PPP network interface.
+#mtu <n>
+
+# Set the name of the local system for authentication purposes to <n>.
+# This is a privileged option. With this option, pppd will use lines in the
+# secrets files which have <n> as the second field when looking for a
+# secret to use in authenticating the peer. In addition, unless overridden
+# with the user option, <n> will be used as the name to send to the peer
+# when authenticating the local system to the peer. (Note that pppd does
+# not append the domain name to <n>.)
+#name <n>
+
+# Enforce the use of the hostname as the name of the local system for
+# authentication purposes (overrides the name option).
+#usehostname
+
+# Set the assumed name of the remote system for authentication purposes
+# to <n>.
+#remotename <n>
+
+# Add an entry to this system's ARP [Address Resolution Protocol]
+# table with the IP address of the peer and the Ethernet address of this
+# system.
+proxyarp
+
+# Use the system password database for authenticating the peer using
+# PAP. Note: mgetty already provides this option. If this is specified
+# then dialin from users using a script under Linux to fire up ppp wont work.
+# login
+
+# If this option is given, pppd will send an LCP echo-request frame to the
+# peer every n seconds. Normally the peer should respond to the echo-request
+# by sending an echo-reply. This option can be used with the
+# lcp-echo-failure option to detect that the peer is no longer connected.
+lcp-echo-interval 30
+
+# If this option is given, pppd will presume the peer to be dead if n
+# LCP echo-requests are sent without receiving a valid LCP echo-reply.
+# If this happens, pppd will terminate the connection. Use of this
+# option requires a non-zero value for the lcp-echo-interval parameter.
+# This option can be used to enable pppd to terminate after the physical
+# connection has been broken (e.g., the modem has hung up) in
+# situations where no hardware modem control lines are available.
+lcp-echo-failure 4
+
+# Set the LCP restart interval (retransmission timeout) to <n> seconds
+# (default 3).
+#lcp-restart <n>
+
+# Set the maximum number of LCP terminate-request transmissions to <n>
+# (default 3).
+#lcp-max-terminate <n>
+
+# Set the maximum number of LCP configure-request transmissions to <n>
+# (default 10).
+#lcp-max-configure <n>
+
+# Set the maximum number of LCP configure-NAKs returned before starting
+# to send configure-Rejects instead to <n> (default 10).
+#lcp-max-failure <n>
+
+# Set the IPCP restart interval (retransmission timeout) to <n>
+# seconds (default 3).
+#ipcp-restart <n>
+
+# Set the maximum number of IPCP terminate-request transmissions to <n>
+# (default 3).
+#ipcp-max-terminate <n>
+
+# Set the maximum number of IPCP configure-request transmissions to <n>
+# (default 10).
+#ipcp-max-configure <n>
+
+# Set the maximum number of IPCP configure-NAKs returned before starting
+# to send configure-Rejects instead to <n> (default 10).
+#ipcp-max-failure <n>
+
+# Set the PAP restart interval (retransmission timeout) to <n> seconds
+# (default 3).
+#pap-restart <n>
+
+# Set the maximum number of PAP authenticate-request transmissions to
+# <n> (default 10).
+#pap-max-authreq <n>
+
+# Set the maximum time that pppd will wait for the peer to authenticate
+# itself with PAP to <n> seconds (0 means no limit).
+#pap-timeout <n>
+
+# Set the CHAP restart interval (retransmission timeout for
+# challenges) to <n> seconds (default 3).
+#chap-restart <n>
+
+# Set the maximum number of CHAP challenge transmissions to <n>
+# (default 10).
+#chap-max-challenge
+
+# If this option is given, pppd will rechallenge the peer every <n>
+# seconds.
+#chap-interval <n>
+
+# With this option, pppd will accept the peer's idea of our local IP
+# address, even if the local IP address was specified in an option.
+#ipcp-accept-local
+
+# With this option, pppd will accept the peer's idea of its (remote) IP
+# address, even if the remote IP address was specified in an option.
+#ipcp-accept-remote
+
+# Disable the IPXCP and IPX protocols.
+# To let pppd pass IPX packets comment this out --- you'll probably also
+# want to install ipxripd, and have the Internal IPX Network option enabled
+# in your kernel. /usr/doc/HOWTO/IPX-HOWTO.gz contains more info.
+noipx
+
+# Exit once a connection has been made and terminated. This is the default,
+# unless the `persist' or `demand' option has been specified.
+#nopersist
+
+# Do not exit after a connection is terminated; instead try to reopen
+# the connection.
+#persist
+
+# Terminate after n consecutive failed connection attempts.
+# A value of 0 means no limit. The default value is 10.
+#maxfail <n>
+maxfail 0
+
+# Initiate the link only on demand, i.e. when data traffic is present.
+# With this option, the remote IP address must be specified by the user on
+# the command line or in an options file. Pppd will initially configure
+# the interface and enable it for IP traffic without connecting to the peer.
+# When traffic is available, pppd will connect to the peer and perform
+# negotiation, authentication, etc. When this is completed, pppd will
+# commence passing data packets (i.e., IP packets) across the link.
+#demand
+
+# Specifies that pppd should disconnect if the link is idle for <n> seconds.
+# The link is idle when no data packets (i.e. IP packets) are being sent or
+# received. Note: it is not advisable to use this option with the persist
+# option without the demand option. If the active-filter option is given,
+# data packets which are rejected by the specified activity filter also
+# count as the link being idle.
+#idle <n>
+
+# Specifies how many seconds to wait before re-initiating the link after
+# it terminates. This option only has any effect if the persist or demand
+# option is used. The holdoff period is not applied if the link was
+# terminated because it was idle.
+#holdoff <n>
+
+# Wait for up n milliseconds after the connect script finishes for a valid
+# PPP packet from the peer. At the end of this time, or when a valid PPP
+# packet is received from the peer, pppd will commence negotiation by
+# sending its first LCP packet. The default value is 1000 (1 second).
+# This wait period only applies if the connect or pty option is used.
+#connect-delay <n>
+
+# Packet filtering: for more information, see pppd(8)
+# Any packets matching the filter expression will be interpreted as link
+# activity, and will cause a "demand" connection to be activated, and reset
+# the idle connection timer. (idle option)
+# The filter expression is akin to that of tcpdump(1)
+#active-filter <filter-expression>
+
+# uncomment the line below this if you use PPPoE
+#plugin /usr/lib/pppd/plugins/pppoe.so
+
+# ---<End of File>---
diff --git a/main/ppp/plog b/main/ppp/plog
new file mode 100644
index 0000000000..84d2c7340c
--- /dev/null
+++ b/main/ppp/plog
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ -s /var/log/ppp.log ]; then
+ exec tail "$@" /var/log/ppp.log
+else
+ exec tail "$@" /var/log/syslog | grep ' \(pppd\|chat\)\['
+fi
diff --git a/main/ppp/poff b/main/ppp/poff
new file mode 100644
index 0000000000..8b4dffc59e
--- /dev/null
+++ b/main/ppp/poff
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+# Written by John Hasler <john@dhh.gt.org> and based on work
+# by Phil Hands <phil@hands.com>. Distributed under the GNU GPL
+
+if [ -x /usr/bin/kill ]; then
+ KILL="/usr/bin/kill"
+else
+ KILL="/bin/kill"
+fi
+SIG=TERM
+DONE="stopped"
+MODE=""
+
+usage ()
+{
+ cat <<!EOF!
+usage: $0 [option] [provider]
+options:
+ -r Cause pppd to drop the line and redial.
+ -d Toggle the state of pppd's debug option.
+ -c Cause pppd to renegotiate compression.
+ -a Stop all pppd's. 'provider' will be ignored.
+ -h Print this help summary and exit.
+ -v Print version and exit.
+ none Stop pppd.
+
+Options may not be combined.
+
+If 'provider' is omitted pppd will be stopped or signalled if and only if
+there is exactly one running unless the '-a' option was given. If
+'provider' is supplied the pppd controlling the connection to that
+provider will be stopped or signalled.
+!EOF!
+}
+
+# Get option. If there are none replace the "?" that getopts puts in
+# FLAG on error with "null".
+getopts rdcavh FLAG
+if [ "$?" -ne 0 ]; then
+ FLAG="null"
+fi
+
+# Check for additional options. Should be none.
+getopts :rdcavh DUMMY
+if [ "$?" -eq 0 ]; then
+ echo "$0: Illegal option -- ${OPTARG}."
+ exit 1
+fi
+
+case $FLAG in
+ "r") SIG=HUP; DONE=signalled; shift ;;
+ "d") SIG=USR1; DONE=signalled; shift ;;
+ "c") SIG=USR2; DONE=signalled; shift ;;
+ "a") MODE="all"; shift ;;
+ "v") echo "$0$Revision: 1.1 $_TrickToPrint_RCS_Revision"; exit 0 ;;
+ "h") usage; exit 0 ;;
+ "?") exit 1;
+esac
+
+# Get the PIDs of all the pppds running. Could also get these from
+# /var/run, but pppd doesn't create .pid files until ppp is up.
+PIDS=`pidof pppd`
+
+# poff is pointless if pppd isn't running.
+if test -z "$PIDS"; then
+ echo "$0: No pppd is running. None ${DONE}."
+ exit 1
+fi
+
+# Find out how many pppd's are running.
+N=`echo "$PIDS" | wc -w`
+
+# If there are no arguments we can't do anything if there is more than one
+# pppd running.
+if test "$#" -eq 0 -a "$N" -gt 1 -a $FLAG != "a" ; then
+ echo "$0: More than one pppd running and no "-a" option and
+no arguments supplied. Nothing ${DONE}."
+ exit 1
+fi
+
+# If either there are no arguments or '-a' was specified kill all the
+# pppd's.
+if test "$#" -eq 0 -o "$MODE" = "all" ; then
+ $KILL -$SIG $PIDS || {
+ echo "$0: $KILL failed. None ${DONE}."
+ exit 1
+ }
+ exit 0
+fi
+
+# There is an argument, so kill the pppd started on that provider.
+PID=`ps axw | grep "[ /]pppd call $1 *\$" | awk '{print $1}'`
+if test -n "$PID" ; then
+ $KILL -$SIG $PID || {
+ echo "$0: $KILL failed. None ${DONE}."
+ exit 1
+ }
+else
+ echo "$0: I could not find a pppd process for provider '$1'. None ${DONE}."
+ exit 1
+fi
+exit 0
diff --git a/main/ppp/pon b/main/ppp/pon
new file mode 100644
index 0000000000..36885050b5
--- /dev/null
+++ b/main/ppp/pon
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+case "$1" in
+ -*) echo "
+Usage: pon [provider] [arguments]
+
+If you specify one argument, a PPP connection will be started using
+settings from the appropriate file in the /etc/ppp/peers/ directory, and
+any additional arguments supplied will be passed as extra arguments to
+pppd.
+"
+ exit 0
+ ;;
+esac
+
+if [ -z "$1" -a ! -f /etc/ppp/peers/provider ]; then
+ echo "
+Please configure /etc/ppp/peers/provider or use a command line argument to
+use another file in /etc/ppp/peers/ directory.
+"
+ exit 1
+fi
+
+if [ "$1" -a ! -f "/etc/ppp/peers/$1" ]; then
+ echo "
+The file /etc/ppp/peers/$1 does not exist.
+"
+ exit 1
+fi
+
+exec /usr/sbin/pppd call ${@:-provider}
+
diff --git a/main/ppp/pon.1 b/main/ppp/pon.1
new file mode 100644
index 0000000000..bb3220564b
--- /dev/null
+++ b/main/ppp/pon.1
@@ -0,0 +1,121 @@
+.\" This manual is published under the GPL.
+.\" All guidelines specified in the GPL apply here.
+.\" To get an ascii file:
+.\" groff -man -Tascii pon.1 > pon.txt
+.\"
+.TH PON 1 "July 2000" "Debian Project" "Debian PPPD"
+.SH NAME
+pon, poff, plog \- starts up, shuts down or lists the log of PPP connections
+.SH SYNOPSIS
+.B pon
+[ isp-name [ options ] ]
+.br
+.B poff
+[ -r ] [ -d ] [ -c ] [ -a ] [ -h ] [ isp-name ]
+.br
+.B plog
+[ arguments ]
+.SH DESCRIPTION
+This manual page describes the \fBpon\fP, \fBplog\fP and \fBpoff\fP
+scripts, which allow users to control PPP connections.
+..
+.SS pon
+\fBpon\fP, invoked without arguments, runs the \fI/etc/ppp/ppp_on_boot\fP
+file, if it exists and is executable. Otherwise, a PPP connection will be
+started using configuration from \fI/etc/ppp/peers/provider\fP.
+This is the default behaviour unless an \fBisp-name\fP argument is given.
+.PP
+For instance, to use ISP configuration "myisp" run:
+.IP
+pon myisp
+.PP
+\fBpon\fP will then use the options file \fI/etc/ppp/peers/myisp\fP.
+You can pass additional \fBoptions\fP after the ISP name, too.
+\fBpon\fP can be used to run multiple, simultaneous PPP connections.
+..
+.SS poff
+\fBpoff\fP closes a PPP connection. If more than one PPP connection exists,
+the one named in the argument to \fBpoff\fP will be killed, e.g.
+.IP
+poff myprovider2
+.PP
+will terminate the connection to myprovider2, and leave the PPP connections
+to e.g. "myprovider1" or "myprovider3" up and running.
+.PP
+\fBpoff\fP takes the following command line options:
+.RS
+.TP
+.B "\-r"
+causes the connection to be redialed after it is dropped.
+.TP
+.B "\-d"
+toggles the state of pppd's debug option.
+.TP
+.B "\-c"
+causes
+.BR pppd (8)
+to renegotiate compression.
+.TP
+.B "\-a"
+stops all running ppp connections. If the argument \fBisp-name\fP
+is given it will be ignored.
+.TP
+.B "\-h"
+displays help information.
+.TP
+.B "\-v"
+prints the version and exits.
+.PP
+If no argument is given, \fBpoff\fP will stop or signal pppd if and only
+if there is exactly one running. If more than one connection is active,
+it will exit with an error code of 1.
+..
+.SS plog
+\fBplog\fP shows you the last few lines of \fI/var/log/ppp.log\fP. If that
+file doesn't exist, it shows you the last few lines of your
+\fI/var/log/syslog\fP file, but excluding the lines not generated by pppd.
+This script makes use of the
+.BR tail (1)
+command, so arguments that can be passed to
+.BR tail (1)
+can also be passed to \fBplog\fP.
+.PP
+Note: the \fBplog\fP script can only be used by root or another system
+administrator in group "adm", due to security reasons. Also, to have all
+pppd-generated information in one logfile, that plog can show, you need the
+following line in your \fI/etc/syslog.conf\fP file:
+.PP
+local2.* -/var/log/ppp.log
+.RE
+.SH FILES
+.TP
+.I /etc/ppp/options
+PPPd system options file.
+.TP
+.I /etc/ppp/pap-secrets
+System PAP passwords file.
+.TP
+.I /etc/ppp/chap-secrets
+System CHAP passwords file.
+.TP
+.I /etc/ppp/peers/
+Directory holding the peer options files. The default file is called
+\fIprovider\fP.
+.TP
+.I /etc/chatscripts/provider
+The chat script invoked from the default \fI/etc/ppp/peers/provider\fP.
+.TP
+.I /var/log/ppp.log
+The default PPP log file.
+.SH AUTHORS
+The p-commands were written by Christoph Lameter <clameter@debian.org>.
+Updated and revised by Philip Hands <phil@hands.com>.
+.br
+This manual was written by Othmar Pasteka <othmar@tron.at>. Modified
+by Rob Levin <lilo@openprojects.net>, with some extensions taken from
+the old p-commands manual written by John Hasler <jhasler@debian.org>.
+.SH "SEE ALSO"
+.BR pppd (8),
+.BR chat (8),
+.BR tail (1).
+
diff --git a/main/printproto/APKBUILD b/main/printproto/APKBUILD
new file mode 100644
index 0000000000..dc1c0b415c
--- /dev/null
+++ b/main/printproto/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=printproto
+pkgver=1.0.5
+pkgrel=0
+pkgdesc="X11 print extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends=""
+depends_dev="util-macros"
+makedepends="$depends_dev"
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="99d0e25feea2fead7d8325b7000b41c3 printproto-1.0.5.tar.bz2"
diff --git a/main/privoxy/APKBUILD b/main/privoxy/APKBUILD
new file mode 100644
index 0000000000..c6a92ebe20
--- /dev/null
+++ b/main/privoxy/APKBUILD
@@ -0,0 +1,57 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=privoxy
+pkgver=3.0.17
+pkgrel=1
+pkgdesc="A web proxy with advanced filtering capabilities"
+url="http://www.privoxy.org"
+arch="all"
+license="GPL"
+pkgusers="privoxy"
+pkggroups="privoxy"
+depends=
+makedepends="autoconf automake pcre-dev zlib-dev coreutils"
+install="privoxy.pre-install"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/ijbswa/$pkgname-$pkgver-stable-src.tar.gz
+ $pkgname.initd
+ $pkgname.logrotate
+ privoxy-3.0.16-gentoo.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver-stable
+prepare() {
+ cd "$_builddir"
+ patch -p1 -i "$srcdir"/privoxy-3.0.16-gentoo.patch || return 1
+ aclocal && autoheader && autoconf
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --localstatedir=/var/ \
+ --enable-zlib \
+ --enable-dynamic-pcre \
+ --with-user=privoxy \
+ --with-group=privoxy \
+ --sysconfdir=/etc/privoxy \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm $pkgdir/var/log/privoxy/*
+ install -D -m755 "$srcdir"/privoxy.initd "$pkgdir"/etc/init.d/privoxy
+ install -D -m644 "$srcdir"/privoxy.logrotate \
+ "$pkgdir"/etc/logrotate.d/privoxy
+ find "$pkgdir"/etc/privoxy/ -type d | xargs chmod 770
+ find "$pkgdir"/etc/privoxy/ -type f | xargs chmod 660
+ chown -R privoxy:privoxy "$pkgdir"/var/log/privoxy \
+ "$pkgdir"/etc/privoxy
+}
+
+md5sums="9d363d738a3f3d73e774d6dfeafdb15f privoxy-3.0.17-stable-src.tar.gz
+170d5679e4c3504f07ef1a4c9859e9b8 privoxy.initd
+f2b6a652dbfbc65e5b89024a8ea3da7e privoxy.logrotate
+48cce19ecdcf8f17a021ac3aa8f837bc privoxy-3.0.16-gentoo.patch"
diff --git a/main/privoxy/privoxy-3.0.16-gentoo.patch b/main/privoxy/privoxy-3.0.16-gentoo.patch
new file mode 100644
index 0000000000..d445ec1b01
--- /dev/null
+++ b/main/privoxy/privoxy-3.0.16-gentoo.patch
@@ -0,0 +1,108 @@
+--- privoxy/GNUmakefile.in
++++ privoxy/GNUmakefile.in
+@@ -61,10 +61,10 @@
+ MAN_DIR = @mandir@
+ MAN_DEST = $(MAN_DIR)/man1
+ SHARE_DEST = @datadir@
+-DOC_DEST = $(SHARE_DEST)/doc/privoxy
++DOC_DEST = @docdir@
+-VAR_DEST = @localstatedir@
++VAR_DEST = /var
+ LOGS_DEST = $(VAR_DEST)/log/privoxy
+ PIDS_DEST = $(VAR_DEST)/run
+
+ # if $prefix = /usr/local then the default CONFDEST change from
+ # CONF_DEST = $(CONF_BASE) to CONF_DEST = $(CONF_BASE)/privoxy
+@@ -901,34 +901,8 @@
+ fi ;\
+ $(ECHO) Installing configuration files to $(DESTDIR)$(CONF_DEST);\
+ for i in $(CONFIGS); do \
+- if [ "$$i" = "default.action" ] || [ "$$i" = "default.filter" ] ; then \
+- $(RM) $(DESTDIR)$(CONF_DEST)/$$i ;\
+- $(ECHO) Installing fresh $$i;\
+ $(INSTALL) $$INSTALL_CONF $$i $(DESTDIR)$(CONF_DEST) || exit 1;\
+- elif [ -s "$(CONF_DEST)/$$i" ]; then \
+- $(ECHO) Installing $$i as $$i.new ;\
+- $(INSTALL) $$INSTALL_CONF $$i $(DESTDIR)$(CONF_DEST)/$$i.new || exit 1;\
+- NEW=1;\
+- else \
+- $(INSTALL) $$INSTALL_CONF $$i $(DESTDIR)$(CONF_DEST) || exit 1;\
+- fi ;\
+ done ;\
+- if [ -n "$$NEW" ]; then \
+- $(CHMOD) $(RWD_MODE) $(DESTDIR)$(CONF_DEST)/*.new || exit 1 ;\
+- $(ECHO) "Warning: Older config files are preserved. Check new versions for changes!" ;\
+- fi ;\
+- [ ! -f $(DESTDIR)$(LOG_DEST)/logfile ] && $(ECHO) Creating logfiles in $(DESTDIR)$(LOG_DEST) || \
+- $(ECHO) Checking logfiles in $(DESTDIR)$(LOG_DEST) ;\
+- $(TOUCH) $(DESTDIR)$(LOG_DEST)/logfile || exit 1 ;\
+- if [ x$$USER != x ]; then \
+- $(CHOWN) $$USER $(DESTDIR)$(LOG_DEST)/logfile || \
+- $(ECHO) "** WARNING ** current install user different from configured user. Logging may fail!!" ;\
+- fi ;\
+- if [ x$$GROUP_T != x ]; then \
+- $(CHGRP) $$GROUP_T $(DESTDIR)$(LOG_DEST)/logfile || \
+- $(ECHO) "** WARNING ** current install user different from configured user. Logging may fail!!" ;\
+- fi ;\
+- $(CHMOD) $(RWD_MODE) $(DESTDIR)$(LOG_DEST)/logfile || exit 1 ;\
+ if [ "$(prefix)" = "/usr/local" ] || [ "$(prefix)" = "/usr" ]; then \
+ if [ -f /etc/slackware-version ] && [ -d /etc/rc.d/ ] && [ -w /etc/rc.d/ ] ; then \
+ $(SED) 's+%PROGRAM%+$(PROGRAM)+' slackware/rc.privoxy.orig | \
+--- privoxy/config
++++ privoxy/config
+@@ -267,7 +267,7 @@
+ #
+ # No trailing "/", please.
+ #
+-confdir .
++confdir /etc/privoxy
+ #
+ #
+ # 2.2. templdir
+@@ -324,7 +324,7 @@
+ #
+ # No trailing "/", please.
+ #
+-logdir .
++logdir /var/log/privoxy
+ #
+ #
+ # 2.4. actionsfile
+@@ -464,7 +464,7 @@
+ # Any log files must be writable by whatever user Privoxy is
+ # being run as (on Unix, default user id is "privoxy").
+ #
+-logfile logfile
++logfile privoxy.log
+ #
+ #
+ # 2.7. trustfile
+--- privoxy/default.action.master
++++ privoxy/default.action.master
+@@ -564,7 +564,7 @@
+ { \
+ +change-x-forwarded-for{block} \
+ +hide-from-header{block} \
+-+set-image-blocker{pattern} \
+++set-image-blocker{blank} \
+ }
+ standard.Cautious
+
+@@ -584,7 +584,7 @@
+ +hide-from-header{block} \
+ +hide-referrer{conditional-block} \
+ +session-cookies-only \
+-+set-image-blocker{pattern} \
+++set-image-blocker{blank} \
+ }
+ standard.Medium
+
+@@ -623,7 +623,7 @@
+ +hide-referrer{conditional-block} \
+ +limit-connect{,} \
+ +overwrite-last-modified{randomize} \
+-+set-image-blocker{pattern} \
+++set-image-blocker{blank} \
+ }
+ standard.Advanced
+
diff --git a/main/privoxy/privoxy.initd b/main/privoxy/privoxy.initd
new file mode 100644
index 0000000000..ef984ea3df
--- /dev/null
+++ b/main/privoxy/privoxy.initd
@@ -0,0 +1,32 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-proxy/privoxy/files/privoxy.initd,v 1.2 2007/11/14 05:14:56 mrness Exp $
+
+CONFFILE=/etc/${SVCNAME}/config
+PIDFILE=/var/run/${SVCNAME}.pid
+
+depend() {
+ need net
+}
+
+start() {
+ if [ ! -f "${CONFFILE}" ]; then
+ eerror "Configuration file ${CONFFILE} not found!"
+ return 1
+ fi
+
+ ebegin "Starting privoxy"
+ start-stop-daemon --start --quiet --exec /usr/sbin/privoxy \
+ --pidfile "${PIDFILE}" \
+ -- \
+ --pidfile "${PIDFILE}" \
+ --user privoxy.privoxy "${CONFFILE}"
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping privoxy"
+ start-stop-daemon --stop --quiet --pidfile "${PIDFILE}"
+ eend $?
+}
diff --git a/main/privoxy/privoxy.logrotate b/main/privoxy/privoxy.logrotate
new file mode 100644
index 0000000000..aa7463bd57
--- /dev/null
+++ b/main/privoxy/privoxy.logrotate
@@ -0,0 +1,9 @@
+/var/log/privoxy/privoxy.log /var/log/privoxy/jarfile {
+ missingok
+ notifempty
+ create 0640 privoxy privoxy
+ sharedscripts
+ postrotate
+ killall -HUP privoxy 2>/dev/null || true
+ endscript
+}
diff --git a/main/privoxy/privoxy.pre-install b/main/privoxy/privoxy.pre-install
new file mode 100644
index 0000000000..38db002881
--- /dev/null
+++ b/main/privoxy/privoxy.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+addgroup privoxy 2>/dev/null
+adduser -S -G privoxy -h /var/log/privoxy -s /bin/false -D privoxy 2>/dev/null
+exit 0
+
diff --git a/main/procps/01-fix-install-options-for-busybox.patch b/main/procps/01-fix-install-options-for-busybox.patch
new file mode 100644
index 0000000000..792a78155b
--- /dev/null
+++ b/main/procps/01-fix-install-options-for-busybox.patch
@@ -0,0 +1,65 @@
+--- orig/procps-3.2.8/Makefile
++++ src/procps-3.2.8/Makefile
+@@ -27,7 +27,7 @@
+ ldconfig := ldconfig
+ ln_f := ln -f
+ ln_sf := ln -sf
+-install := install -D --owner 0 --group 0
++install := install -D -o 0 -g 0
+
+ # Lame x86-64 /lib64 and /usr/lib64 abomination:
+ lib64 := lib$(shell [ -d /lib64 ] && echo 64)
+@@ -222,10 +222,10 @@
+ ###### install
+
+ $(BINFILES) : all
+- $(install) --mode a=rx $(notdir $@) $@
++ $(install) -m a=rx $(notdir $@) $@
+
+ $(MANFILES) : all
+- $(install) --mode a=r $(notdir $@) $@
++ $(install) -m a=r $(notdir $@) $@
+
+ install: $(filter-out $(SKIP) $(addprefix $(DESTDIR),$(SKIP)),$(INSTALL))
+ cd $(usr/bin) && $(ln_f) skill snice
+--- orig/procps-3.2.8/proc/module.mk
++++ src/procps-3.2.8/proc/module.mk
+@@ -96,7 +96,7 @@
+ #################### install rules ###########################
+
+ $(lib)$(SOFILE) : proc/$(SONAME)
+- $(install) --mode a=rx $< $@
++ $(install) -m a=rx $< $@
+
+ ifneq ($(SOLINK),$(SOFILE))
+ .PHONY: $(lib)$(SOLINK)
+@@ -115,14 +115,14 @@
+ $(ldconfig)
+
+ $(usr/lib)$(ANAME) : proc/$(ANAME)
+- $(install) --mode a=r $< $@
++ $(install) -m a=r $< $@
+
+ # Junk anyway... supposed to go in /usr/include/$(NAME)
+ #INSTALL += $(addprefix $(include),$(HDRFILES))
+ #
+ #$(addprefix $(include),$(HDRFILES)): $(include)% : proc/%
+ #$(include)% : proc/%
+-# $(install) --mode a=r $< $@
++# $(install) -m a=r $< $@
+
+ ##################################################################
+
+--- orig/procps-3.2.8/ps/module.mk
++++ src/procps-3.2.8/ps/module.mk
+@@ -33,8 +33,8 @@
+
+
+ $(bin)ps: ps/ps
+- $(install) --mode a=rx $< $@
++ $(install) -m a=rx $< $@
+
+ $(man1)ps.1 : ps/ps.1
+- $(install) --mode a=r $< $@
++ $(install) -m a=r $< $@
+ -rm -f $(DESTDIR)/var/catman/cat1/ps.1.gz $(DESTDIR)/var/man/cat1/ps.1.gz
diff --git a/main/procps/APKBUILD b/main/procps/APKBUILD
new file mode 100644
index 0000000000..41a28c0fa9
--- /dev/null
+++ b/main/procps/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=procps
+pkgver=3.2.8
+pkgrel=2
+pkgdesc="Utilities for monitoring your system and processes on your system"
+url="http://procps.sourceforge.net/"
+arch="all"
+license="GPL LGPL"
+depends=
+# needs fancy install
+makedepends="ncurses-dev coreutils"
+subpackages="$pkgname-dev $pkgname-doc libproc"
+source="http://$pkgname.sourceforge.net/$pkgname-$pkgver.tar.gz
+ 01-fix-install-options-for-busybox.patch"
+
+prepare() {
+ cd "$srcdir"
+ patch -p1 -i "$srcdir"/01-fix-install-options-for-busybox.patch || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" ldconfig=true install="install -D" \
+ install || return 1
+ install -d "$pkgdir"/usr/include/proc || return 1
+ install -m644 proc/*.h "$pkgdir"/usr/include/proc/ || return 1
+}
+
+libproc() {
+ pkgdesc="Library for monitoring system and processes"
+ install -d "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libproc* "$subpkgdir"/lib/
+ ln -s libproc-$pkgver.so "$subpkgdir"/lib/libproc.so
+}
+
+md5sums="9532714b6846013ca9898984ba4cd7e0 procps-3.2.8.tar.gz
+2b821e841acd08620789d5ffd19d58e9 01-fix-install-options-for-busybox.patch"
diff --git a/main/psqlodbc/APKBUILD b/main/psqlodbc/APKBUILD
new file mode 100644
index 0000000000..e637231bbf
--- /dev/null
+++ b/main/psqlodbc/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=psqlodbc
+pkgver=09.00.0300
+pkgrel=0
+pkgdesc="PostgreSQL ODBC driver"
+url="http://www.postgresql.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="postgresql-dev unixodbc-dev openssl-dev libtool"
+subpackages=
+source="ftp://ftp2.it.postgresql.org/mirrors/postgres//odbc/versions/src/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="9b4897ac9ba63265fb4e149c94db8632 psqlodbc-09.00.0300.tar.gz"
diff --git a/main/pth/APKBUILD b/main/pth/APKBUILD
new file mode 100644
index 0000000000..7882289c43
--- /dev/null
+++ b/main/pth/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=pth
+pkgver=2.0.7
+pkgrel=4
+pkgdesc="The GNU Portable Threads."
+url="http://www.gnu.org/software/pth"
+arch="all"
+license="LGPL-2.1"
+depends=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz
+ pth-2.0.5-parallelfix.patch
+ pth-2.0.6-ldflags.patch
+ pth-2.0.6-sigstack.patch
+ "
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --mandir=/usr/share/man
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="9cb4a25331a4c4db866a31cbe507c793 pth-2.0.7.tar.gz
+7bbd4f3328807c740c86db94e93e48ad pth-2.0.5-parallelfix.patch
+942fa4be28117756cd579937b257b9cc pth-2.0.6-ldflags.patch
+04e43157d758a3dc7925c35e6dd1e39c pth-2.0.6-sigstack.patch"
diff --git a/main/pth/pth-2.0.5-parallelfix.patch b/main/pth/pth-2.0.5-parallelfix.patch
new file mode 100644
index 0000000000..1c8200a4cb
--- /dev/null
+++ b/main/pth/pth-2.0.5-parallelfix.patch
@@ -0,0 +1,15 @@
+--- a/Makefile.in 2005-11-08 05:58:55.000000000 +1100
++++ b/Makefile.in 2005-11-08 06:29:02.000000000 +1100
+@@ -148,10 +148,9 @@
+
+ # be aware of libtool when building the objects
+ .SUFFIXES:
+-.SUFFIXES: .c .o .lo
+-.c.o:
++%.o: %.c $(TARGET_PREQ)
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $<
+-.c.lo:
++%.lo: %.c $(TARGET_PREQ)
+ $(LIBTOOL) --mode=compile --quiet $(CC) -c $(CPPFLAGS) $(CFLAGS) $<
+
+ # the default target
diff --git a/main/pth/pth-2.0.6-ldflags.patch b/main/pth/pth-2.0.6-ldflags.patch
new file mode 100644
index 0000000000..7a4a5ab300
--- /dev/null
+++ b/main/pth/pth-2.0.6-ldflags.patch
@@ -0,0 +1,17 @@
+Index: pth-2.0.6/Makefile.in
+===================================================================
+--- pth-2.0.6.orig/Makefile.in
++++ pth-2.0.6/Makefile.in
+@@ -168,10 +168,10 @@ pth_p.h: $(S)pth_p.h.in
+
+ # build the static and possibly shared libraries
+ libpth.la: $(LOBJS)
+- $(LIBTOOL) --mode=link --quiet $(CC) -o libpth.la $(LOBJS) \
++ $(LIBTOOL) --mode=link --quiet $(CC) $(LDFLAGS) -o libpth.la $(LOBJS) \
+ -rpath $(libdir) -version-info `$(SHTOOL) version -lc -dlibtool $(_VERSION_FILE)`
+ libpthread.la: pthread.lo $(LOBJS)
+- $(LIBTOOL) --mode=link --quiet $(CC) -o libpthread.la pthread.lo $(LOBJS) \
++ $(LIBTOOL) --mode=link --quiet $(CC) $(LDFLAGS) -o libpthread.la pthread.lo $(LOBJS) \
+ -rpath $(libdir) -version-info `$(SHTOOL) version -lc -dlibtool $(_VERSION_FILE)`
+
+ # build the manual pages
diff --git a/main/pth/pth-2.0.6-sigstack.patch b/main/pth/pth-2.0.6-sigstack.patch
new file mode 100644
index 0000000000..3914dea7ac
--- /dev/null
+++ b/main/pth/pth-2.0.6-sigstack.patch
@@ -0,0 +1,22 @@
+diff -urNp pth-2.0.6.old/aclocal.m4 pth-2.0.6/aclocal.m4
+--- pth-2.0.6.old/aclocal.m4 2004-12-31 21:33:19.000000000 +0200
++++ pth-2.0.6/aclocal.m4 2006-09-20 14:46:59.000000000 +0300
+@@ -1522,6 +1522,7 @@ int main(int argc, char *argv[])
+ int sksize;
+ char result[1024];
+ int i;
++exit (1);
+ sksize = 32768;
+ skbuf = (char *)malloc(sksize*2+2*sizeof(union alltypes));
+ if (skbuf == NULL)
+diff -urNp pth-2.0.6.old/configure pth-2.0.6/configure
+--- pth-2.0.6.old/configure 2005-11-22 09:49:21.000000000 +0200
++++ pth-2.0.6/configure 2006-09-20 14:55:23.000000000 +0300
+@@ -24735,6 +24735,7 @@ int main(int argc, char *argv[])
+ int sksize;
+ char result[1024];
+ int i;
++exit (1);
+ sksize = 32768;
+ skbuf = (char *)malloc(sksize*2+2*sizeof(union alltypes));
+ if (skbuf == NULL)
diff --git a/main/putty/APKBUILD b/main/putty/APKBUILD
new file mode 100644
index 0000000000..69f4cb94ba
--- /dev/null
+++ b/main/putty/APKBUILD
@@ -0,0 +1,47 @@
+# Maintainer: Jeff Bilyk <jbilyk@alpinelinux.org>
+pkgname=putty
+pkgver=0.60
+pkgrel=0
+pkgdesc="SSH and telnet client"
+url="http://www.chiark.greenend.org.uk/~sgtatham/putty/"
+arch="all"
+license="custom"
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://the.earth.li/~sgtatham/putty/latest/putty-$pkgver.tar.gz"
+
+_builddir="$srcdir"/putty-$pkgver/unix
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+
+ # We only make all-cli, so no need to try to install these`
+ sed -i 's#$(INSTALL_PROGRAM) -m 755 pterm $(DESTDIR)$(bindir)/pterm##' Makefile.in
+ sed -i 's#$(INSTALL_PROGRAM) -m 755 putty $(DESTDIR)$(bindir)/putty##' Makefile.in
+ sed -i 's#$(INSTALL_PROGRAM) -m 755 puttytel $(DESTDIR)$(bindir)/puttytel##' Makefile.in
+
+ ./configure --prefix=/usr
+ make all-cli || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -dm755 $pkgdir/usr/bin
+ install -dm755 $pkgdir/usr/share/man/man1
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 ../LICENCE $pkgdir/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="07e65fd98b16d115ae38a180bfb242e2 putty-0.60.tar.gz"
diff --git a/main/pwgen/APKBUILD b/main/pwgen/APKBUILD
new file mode 100644
index 0000000000..0a70090b3c
--- /dev/null
+++ b/main/pwgen/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=pwgen
+pkgver=2.06
+pkgrel=1
+pkgdesc="Password Generator"
+url="http://sourceforge.net/projects/pwgen/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="935aebcbe610fbc9de8125e7b7d71297 pwgen-2.06.tar.gz"
diff --git a/main/py-boto/APKBUILD b/main/py-boto/APKBUILD
new file mode 100644
index 0000000000..a1c0a4ca19
--- /dev/null
+++ b/main/py-boto/APKBUILD
@@ -0,0 +1,51 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=py-boto
+_pkgname=boto
+pkgver=1.9b
+pkgrel=2
+pkgdesc="An integrated interface to current and future infrastructural services offered by Amazon Web Services."
+url="http://code.google.com/p/boto/"
+arch="noarch"
+license="MIT"
+depends="python"
+makedepends="python-dev py-setuptools"
+install=
+subpackages="$pkgname-doc"
+source="http://$_pkgname.googlecode.com/files/$_pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir"
+}
+
+doc() {
+ cd "$_builddir"
+
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname
+ install -Dm644 README "$subpkgdir"/usr/share/doc/$pkgname/README
+
+ # Note: The documentation in the 'docs' directory can only be generated
+ # (via sphinx-build from the py-sphinx package) once this package has
+ # been installed. Copying it off for the user.
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname/docs
+ cp -R ./docs/* "$subpkgdir"/usr/share/doc/$pkgname/docs/
+ chmod -R 644 "$subpkgdir"/usr/share/doc/$pkgname/docs/
+
+ # Fix subdir perms
+ find "$subpkgdir"/usr/share/doc/$pkgname/ -type d -exec chmod 755 '{}' \;
+}
+
+md5sums="4fc2fd7b70a971b1363f8465aafe7091 boto-1.9b.tar.gz"
diff --git a/main/py-cairo/APKBUILD b/main/py-cairo/APKBUILD
new file mode 100644
index 0000000000..c375476109
--- /dev/null
+++ b/main/py-cairo/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=py-cairo
+pkgver=1.8.10
+pkgrel=4
+pkgdesc="Python bindings for the cairo graphics library"
+url="http://cairographics.org/pycairo/"
+arch="all"
+license="GPL"
+depends=
+makedepends="python-dev cairo-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://cairographics.org/releases/py2cairo-$pkgver.tar.gz"
+
+
+_builddir="$srcdir"/pycairo-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm -f "$pkgdir"/usr/lib/python*/site-packages/cairo/_cairo.la
+}
+
+md5sums="87421a6a70304120555ba7ba238f3dc3 py2cairo-1.8.10.tar.gz"
diff --git a/main/py-dbus/APKBUILD b/main/py-dbus/APKBUILD
new file mode 100644
index 0000000000..34f29a802f
--- /dev/null
+++ b/main/py-dbus/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=py-dbus
+pkgver=0.83.1
+pkgrel=2
+pkgdesc="Python bindings for DBUS"
+url="http://www.freedesktop.org/wiki/Software/DBusBindings"
+arch="all"
+license="GPL LGPL"
+depends="python>=2.6.5"
+makedepends="pkgconfig dbus-glib-dev python-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://dbus.freedesktop.org/releases/dbus-python/dbus-python-$pkgver.tar.gz"
+
+_builddir="$srcdir"/dbus-python-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="5fdf3970aa0c00020289de7ba8f3be18 dbus-python-0.83.1.tar.gz"
diff --git a/main/py-docutils/APKBUILD b/main/py-docutils/APKBUILD
new file mode 100644
index 0000000000..29044a620c
--- /dev/null
+++ b/main/py-docutils/APKBUILD
@@ -0,0 +1,55 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=py-docutils
+_pkgname=docutils
+pkgver=0.7
+pkgrel=4
+pkgdesc="Documentation Utilities for Python"
+url="http://docutils.sourceforge.net/"
+arch="noarch"
+license="PublicDomain"
+depends="python py-imaging py-roman"
+makedepends="python-dev py-setuptools"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$_pkgname/$_pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir" || return 1
+}
+
+doc() {
+ cd "$_builddir"
+
+ for _docdir in docs licenses; do
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname/$_docdir \
+ || return 1
+ cp -R ./$_docdir/* "$subpkgdir"/usr/share/doc/$pkgname/$_docdir/ \
+ || return 1
+ chmod -R 644 "$subpkgdir"/usr/share/doc/$pkgname/$_docdir/ \
+ || return 1
+ done
+
+ for _doc in BUGS.txt COPYING.txt FAQ.txt HISTORY.txt README.txt RELEASE-NOTES.txt THANKS.txt; do
+ install -m644 -D $_doc "$subpkgdir"/usr/share/doc/$pkgname/ \
+ || return 1
+ done
+
+ # Fix subdir perms
+ find "$subpkgdir"/usr/share/doc/$pkgname/ -type d -exec chmod 755 '{}' \;
+}
+
+md5sums="9aec716baf15d06b5aa57cf8d5591c15 docutils-0.7.tar.gz"
diff --git a/main/py-genshi/APKBUILD b/main/py-genshi/APKBUILD
new file mode 100644
index 0000000000..5ca4543873
--- /dev/null
+++ b/main/py-genshi/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=py-genshi
+_realname=Genshi
+pkgver=0.6
+pkgrel=2
+pkgdesc="Python toolkit for stream-based generation of output for the web."
+url="http://genshi.edgewall.org/"
+arch="all"
+license="BSD"
+depends="python"
+makedepends="py-setuptools python-dev"
+install=
+source="http://ftp.edgewall.com/pub/genshi/$_realname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root="$pkgdir"
+}
+
+md5sums="604e8b23b4697655d36a69c2d8ef7187 Genshi-0.6.tar.gz"
diff --git a/main/py-gobject/APKBUILD b/main/py-gobject/APKBUILD
new file mode 100644
index 0000000000..7a6ed7fd8e
--- /dev/null
+++ b/main/py-gobject/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=py-gobject
+pkgver=2.28.4
+pkgrel=2
+pkgdesc="Python bindings for the GObject library"
+url="http://www.pygtk.org/"
+arch="all"
+license="GPL"
+depends=
+depends_dev="libffi-dev glib-dev"
+makedepends="$depends_dev python-dev py-cairo-dev gobject-introspection-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnome.org/pub/GNOME/sources/pygobject/${pkgver%.*}/pygobject-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/pygobject-$pkgver
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ find $pkgdir -name "*.la" -print0 | xargs -0 rm -f
+}
+
+md5sums="14e700d5f4b8af00a68a6bcdd65a8db9 pygobject-2.28.4.tar.bz2"
diff --git a/main/py-gst/APKBUILD b/main/py-gst/APKBUILD
new file mode 100644
index 0000000000..4a6d644fb7
--- /dev/null
+++ b/main/py-gst/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=py-gst
+pkgver=0.10.21
+pkgrel=1
+pkgdesc="python bindings for gstreamer"
+url="http://gstreamer.freedesktop.org/"
+arch="all"
+license="LGPL"
+depends="py-gtk py-gobject"
+makedepends="gstreamer-dev gst-plugins-base-dev py-gtk-dev py-gobject-dev"
+install=""
+subpackages=""
+source="http://gstreamer.freedesktop.org/src/gst-python/gst-python-$pkgver.tar.gz"
+
+_builddir="$srcdir"/gst-python-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="aa4f428c2e8d3664dca118b12d872429 gst-python-0.10.21.tar.gz"
diff --git a/main/py-gtk/APKBUILD b/main/py-gtk/APKBUILD
new file mode 100644
index 0000000000..ffa498bb56
--- /dev/null
+++ b/main/py-gtk/APKBUILD
@@ -0,0 +1,41 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=py-gtk
+pkgver=2.24.0
+pkgrel=2
+pkgdesc="Python bindings for the GTK widget set"
+url="http://www.pygtk.org/"
+arch="all"
+license="LGPL"
+depends="py-cairo py-gobject"
+makedepends="libglade-dev py-cairo-dev py-gobject-dev python-dev libffi-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/pygtk/${pkgver%.*}/pygtk-$pkgver.tar.bz2"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-demo"
+
+_builddir="$srcdir"/pygtk-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+dev() {
+ default_dev
+ rm -rf "$subpkgdir"/usr/lib/python*/site-packages/gtk-2.0/*.la \
+ "$subpkgdir"/usr/lib/python*/site-packages/gtk-2.0/gtk/*.la
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -m644 gtk/gtk-extrafuncs.defs ""$pkgdir"/usr/share/pygtk/2.0/defs/" || return 1
+}
+
+demo() {
+ pkgdesc="Demonstration of pygtk"
+ depends="py-gtk"
+ mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/usr/lib/pygtk/2.0
+ mv "$pkgdir"/usr/bin/pygtk-demo "$subpkgdir"/usr/bin/
+ mv "$pkgdir"/usr/lib/pygtk/2.0/*demo* \
+ "$subpkgdir"/usr/lib/pygtk/2.0/
+}
+md5sums="a1051d5794fd7696d3c1af6422d17a49 pygtk-2.24.0.tar.bz2"
diff --git a/main/py-imaging/APKBUILD b/main/py-imaging/APKBUILD
new file mode 100644
index 0000000000..b7f0d80077
--- /dev/null
+++ b/main/py-imaging/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+
+pkgname=py-imaging
+pkgver=1.1.7
+pkgrel=2
+pkgdesc="Python image manipulation library"
+url="http://pypi.python.org/pypi/PIL"
+arch="all"
+license="PSF"
+depends="python freetype"
+makedepends="python-dev freetype-dev"
+install=
+subpackages=""
+source="http://effbot.org/downloads/Imaging-$pkgver.tar.gz"
+
+_builddir="$srcdir"/Imaging-$pkgver
+build() {
+ cd "$_builddir"
+ python setup.py build
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root="$pkgdir"
+}
+
+md5sums="fc14a54e1ce02a0225be8854bfba478e Imaging-1.1.7.tar.gz"
diff --git a/main/py-jinja2/APKBUILD b/main/py-jinja2/APKBUILD
new file mode 100644
index 0000000000..2c20fb00e3
--- /dev/null
+++ b/main/py-jinja2/APKBUILD
@@ -0,0 +1,66 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=py-jinja2
+_pkgname=Jinja2
+pkgver=2.5.5
+pkgrel=3
+pkgdesc="A small but fast and easy to use stand-alone template engine written in pure python."
+url="http://jinja.pocoo.org/"
+arch="noarch"
+license="BSD"
+depends="python"
+makedepends="python-dev py-setuptools"
+install=
+subpackages="$pkgname-doc"
+source="http://pypi.python.org/packages/source/${_pkgname:0:1}/$_pkgname/$_pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir" || return 1
+}
+
+doc() {
+ cd "$_builddir"
+
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname || return 1
+ for _doc in AUTHORS CHANGES LICENSE; do
+ install -Dm644 $_doc "$subpkgdir"/usr/share/doc/$pkgname/$_doc \
+ || return 1
+ done
+
+ # Note: The documentation in the docs directory needs to be generated
+ # by py-sphinx, however, this package (py-jinja2) is a dependency of
+ # Sphinx itself!
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname/docs || return 1
+ cp -R ./docs/* "$subpkgdir"/usr/share/doc/$pkgname/docs/ || return 1
+ chmod -R 644 "$subpkgdir"/usr/share/doc/$pkgname/docs/ || return 1
+
+ mkdir -p "$subpkgdir"/usr/share/$pkgname || return 1
+ for _dir in artwork examples ext; do
+ mkdir -p "$subpkgdir"/usr/share/$pkgname/$_dir/ || return 1
+ cp -R ./$_dir/* "$subpkgdir"/usr/share/$pkgname/$_dir/ \
+ || return 1
+ chmod -R 644 "$subpkgdir"/usr/share/$pkgname/$_dir/ \
+ || return 1
+ done
+
+ # Fix subdir perms
+ find "$subpkgdir"/usr/share/doc/$pkgname/ -type d \
+ -exec chmod 755 '{}' \; || return 1
+ find "$subpkgdir"/usr/share/$pkgname/ -type d \
+ -exec chmod 755 '{}' \; || return 1
+}
+
+md5sums="83b20c1eeb31f49d8e6392efae91b7d5 Jinja2-2.5.5.tar.gz"
diff --git a/main/py-pygments/APKBUILD b/main/py-pygments/APKBUILD
new file mode 100644
index 0000000000..0003e5e3fd
--- /dev/null
+++ b/main/py-pygments/APKBUILD
@@ -0,0 +1,60 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=py-pygments
+_pkgname=Pygments
+pkgver=1.4
+pkgrel=2
+pkgdesc="Pygments is a syntax highlighting package written in Python."
+url="http://pygments.org/"
+arch="noarch"
+license="BSD"
+depends="python"
+makedepends="python-dev py-setuptools"
+install=
+subpackages="$pkgname-doc"
+source="http://pypi.python.org/packages/source/${_pkgname:0:1}/$_pkgname/$_pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir" || return 1
+}
+
+doc() {
+ cd "$_builddir"
+
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname || return 1
+ for _doc in AUTHORS CHANGES LICENSE TODO; do
+ install -Dm644 $_doc "$subpkgdir"/usr/share/doc/$pkgname/$_doc \
+ || return 1
+ done
+
+ install -Dm644 docs/pygmentize.1 \
+ "$subpkgdir"/usr/share/man/man1/pygmentize.1 || return 1
+ install -Dm644 docs/generate.py \
+ "$subpkgdir"/usr/share/doc/$pkgname/generate.py || return 1
+ for _dir in build src; do
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname/$_dir || return 1
+ cp -R ./docs/$_dir/* \
+ "$subpkgdir"/usr/share/doc/$pkgname/$_dir/ || return 1
+ chmod -R 644 "$subpkgdir"/usr/share/doc/$pkgname/$_dir/ \
+ || return 1
+ done
+
+ # Fix subdir perms
+ find "$subpkgdir"/usr/share/doc/$pkgname/ -type d \
+ -exec chmod 755 '{}' \; || return 1
+}
+
+md5sums="d77ac8c93a7fb27545f2522abe9cc462 Pygments-1.4.tar.gz"
diff --git a/main/py-roman/APKBUILD b/main/py-roman/APKBUILD
new file mode 100644
index 0000000000..1c48cbed28
--- /dev/null
+++ b/main/py-roman/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=py-roman
+_pkgname=roman
+pkgver=1.4.0
+pkgrel=3
+pkgdesc="Integer to Roman numerals converter"
+url="http://pypi.python.org/pypi/roman"
+arch="noarch"
+license="Python2.1.1"
+depends="python"
+makedepends="python-dev py-setuptools"
+install=
+subpackages=
+source="http://pypi.python.org/packages/source/${_pkgname:0:1}/$_pkgname/$_pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir" || return 1
+}
+
+md5sums="4f8832ed4108174b159c2afb4bd1d1dd roman-1.4.0.tar.gz"
diff --git a/main/py-setuptools/APKBUILD b/main/py-setuptools/APKBUILD
new file mode 100644
index 0000000000..6f23307c14
--- /dev/null
+++ b/main/py-setuptools/APKBUILD
@@ -0,0 +1,30 @@
+# Contributor: Andrew Manison <amanison@anselsystems.com>
+# Maintainer:
+pkgname=py-setuptools
+_pkgname=${pkgname#py-}
+pkgver=0.6c11
+pkgrel=3
+pkgdesc="setuptools is a collection of enhancements to the Python distutils"
+url="http://pypi.python.org/pypi/setuptools"
+arch="noarch"
+license="PSF"
+depends="python"
+makedepends="python-dev"
+install=
+subpackages=""
+source="http://pypi.python.org/packages/source/s/$_pkgname/$_pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$_pkgname-$pkgver
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$srcdir"/$_pkgname-$pkgver
+ python setup.py install --root="$pkgdir"
+ # we don't provide a non-suffixed easy_install
+ echo "Removing non-suffixed easy_install ( $pkgdir/usr/bin/easy_install)"
+ rm "$pkgdir"/usr/bin/easy_install
+}
+
+md5sums="7df2a529a074f613b509fb44feefe74e setuptools-0.6c11.tar.gz"
diff --git a/main/py-sphinx/APKBUILD b/main/py-sphinx/APKBUILD
new file mode 100644
index 0000000000..f475b27c77
--- /dev/null
+++ b/main/py-sphinx/APKBUILD
@@ -0,0 +1,56 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=py-sphinx
+_pkgname=Sphinx
+pkgver=1.0.7
+pkgrel=1
+pkgdesc="Python Documentation Generator"
+url="http://sphinx.pocoo.org/"
+arch="noarch"
+license="BSD"
+depends="python py-docutils py-jinja2 py-pygments"
+makedepends="python-dev py-setuptools"
+install=
+subpackages="$pkgname-doc"
+source="http://pypi.python.org/packages/source/${_pkgname:0:1}/$_pkgname/$_pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir" || return 1
+}
+
+doc() {
+ cd "$_builddir"
+
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname || return 1
+ for _doc in AUTHORS CHANGES EXAMPLES LICENSE README TODO; do
+ install -Dm644 $_doc "$subpkgdir"/usr/share/doc/$pkgname/ \
+ || return 1
+ done
+
+ # Note: Documentation in the 'doc' directory (below), needs to be built
+ # with sphinx-build once sphinx is installed (see README for details).
+ #
+ # Leaving as-is; will be up to the individual user that's interested.
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname/doc/ || return 1
+ cp -R ./doc/* "$subpkgdir"/usr/share/doc/$pkgname/doc/ || return 1
+ chmod -R 644 "$subpkgdir"/usr/share/doc/$pkgname/doc/ || return 1
+
+ # Fix subdir perms
+ find "$subpkgdir"/usr/share/doc/$pkgname/ -type d \
+ -exec chmod 755 '{}' \; || return 1
+}
+
+md5sums="42c722d48e52d4888193965dd473adb5 Sphinx-1.0.7.tar.gz"
diff --git a/main/py-sqlite/APKBUILD b/main/py-sqlite/APKBUILD
new file mode 100644
index 0000000000..8cc1307980
--- /dev/null
+++ b/main/py-sqlite/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=py-sqlite
+_realname=pysqlite
+pkgver=2.6.3
+pkgrel=1
+pkgdesc="A Python DB-API 2.0 interface for the SQLite embedded relational database engine"
+url="http://code.google.com/p/pysqlite/"
+arch="all"
+license="MIT"
+depends="python sqlite"
+makedepends="sqlite-dev python-dev"
+install=
+source="http://pysqlite.googlecode.com/files/${_realname}-${pkgver}.tar.gz"
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root="$pkgdir"
+}
+
+md5sums="711afa1062a1d2c4a67acdf02a33d86e pysqlite-2.6.3.tar.gz"
diff --git a/main/py-templayer/APKBUILD b/main/py-templayer/APKBUILD
new file mode 100644
index 0000000000..3e36fda0e7
--- /dev/null
+++ b/main/py-templayer/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=py-templayer
+_pkgname=templayer
+pkgver=1.5.1
+pkgrel=3
+pkgdesc="Templayer is a layered template library for Python and Django"
+url="http://excess.org/templayer/"
+arch="noarch"
+license="LGPL"
+depends="python"
+makedepends="python-dev py-setuptools"
+install=
+subpackages="$pkgname-doc"
+source="http://excess.org/$_pkgname/$_pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir" || return 1
+}
+
+doc() {
+ cd "$_builddir"
+
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname || return 1
+ for _doc in reference.html tutorial.html tutorial_examples.tar.gz; do
+ install -Dm644 ./docs/$_doc \
+ "$subpkgdir"/usr/share/doc/$pkgname/$_doc || return 1
+ done
+}
+
+md5sums="9d1a3aa0cece34a2492792278aad406d templayer-1.5.1.tar.gz"
diff --git a/main/py-urwid/APKBUILD b/main/py-urwid/APKBUILD
new file mode 100644
index 0000000000..4703f37d70
--- /dev/null
+++ b/main/py-urwid/APKBUILD
@@ -0,0 +1,50 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=py-urwid
+_pkgname=urwid
+pkgver=0.9.9.1
+pkgrel=3
+pkgdesc="Urwid is a console user interface library for Python"
+url="http://excess.org/urwid/"
+arch="all"
+license="LGPL"
+depends="python"
+makedepends="python-dev py-setuptools py-templayer"
+install=
+subpackages="$pkgname-doc"
+source="http://excess.org/$_pkgname/$_pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$_pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --root "$pkgdir"
+}
+
+doc() {
+ cd "$_builddir"
+
+ # generate tutorial examples, and copy documentation
+ python docgen_tutorial.py -s
+ mkdir -p "$subpkgdir"/usr/share/doc/$pkgname/tutorial_examples
+ cp -a example*.py "$subpkgdir"/usr/share/doc/$pkgname/tutorial_examples/
+
+ for doc in CHANGELOG reference.html tutorial.html; do
+ install -Dm644 $doc "$subpkgdir"/usr/share/doc/$pkgname/$doc
+ done
+
+ # Fix subdir perms
+ find "$subpkgdir"/usr/share/doc/$pkgname/ -type d -exec chmod 755 '{}' \;
+}
+
+md5sums="4722cdf898f711dcae1121aa80920152 urwid-0.9.9.1.tar.gz"
diff --git a/main/py-xml/APKBUILD b/main/py-xml/APKBUILD
new file mode 100644
index 0000000000..401efaa5a7
--- /dev/null
+++ b/main/py-xml/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=py-xml
+pkgver=0.8.4
+pkgrel=2
+pkgdesc="Python XML parsing library."
+url="http://pyxml.sourceforge.net/"
+arch="all"
+license="custom"
+depends=
+makedepends="python-dev"
+source="http://downloads.sourceforge.net/sourceforge/pyxml/PyXML-$pkgver.tar.gz
+ fix-python2.6.patch"
+
+_builddir="$srcdir"/PyXML-$pkgver
+build() {
+ cd "$_builddir"
+ patch -Np1 -i "$srcdir/fix-python2.6.patch" || return 1
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --prefix=/usr --root="$pkgdir" || return 1
+ install -D -m644 LICENCE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" || return 1
+}
+
+md5sums="1f7655050cebbb664db976405fdba209 PyXML-0.8.4.tar.gz
+4b652e0c866e3cca7e2386e8e383d5ba fix-python2.6.patch"
diff --git a/main/py-xml/fix-python2.6.patch b/main/py-xml/fix-python2.6.patch
new file mode 100644
index 0000000000..7bf1c46fc9
--- /dev/null
+++ b/main/py-xml/fix-python2.6.patch
@@ -0,0 +1,28 @@
+diff -ur a/xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py b/xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py
+--- a/xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py 2003-03-11 15:01:34.000000000 +0100
++++ b/xml/xpath/ParsedAbbreviatedAbsoluteLocationPath.py 2009-05-25 16:32:26.000000000 +0200
+@@ -24,8 +24,8 @@
+ self._rel = rel
+ nt = ParsedNodeTest.ParsedNodeTest('node', '')
+ ppl = ParsedPredicateList.ParsedPredicateList([])
+- as = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self')
+- self._step = ParsedStep.ParsedStep(as, nt, ppl)
++ asp = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self')
++ self._step = ParsedStep.ParsedStep(asp, nt, ppl)
+ return
+
+ def evaluate(self, context):
+diff -ur a/xml/xpath/ParsedAbbreviatedRelativeLocationPath.py b/xml/xpath/ParsedAbbreviatedRelativeLocationPath.py
+--- a/xml/xpath/ParsedAbbreviatedRelativeLocationPath.py 2003-03-11 15:01:34.000000000 +0100
++++ b/xml/xpath/ParsedAbbreviatedRelativeLocationPath.py 2009-05-25 16:27:55.000000000 +0200
+@@ -28,8 +28,8 @@
+ self._right = right
+ nt = ParsedNodeTest.ParsedNodeTest('node','')
+ ppl = ParsedPredicateList.ParsedPredicateList([])
+- as = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self')
+- self._middle = ParsedStep.ParsedStep(as, nt, ppl)
++ asp = ParsedAxisSpecifier.ParsedAxisSpecifier('descendant-or-self')
++ self._middle = ParsedStep.ParsedStep(asp, nt, ppl)
+
+ def evaluate(self, context):
+ res = []
diff --git a/main/python/APKBUILD b/main/python/APKBUILD
new file mode 100644
index 0000000000..35ab8ef088
--- /dev/null
+++ b/main/python/APKBUILD
@@ -0,0 +1,78 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=python
+pkgver=2.7.2
+_verbase=${pkgver%.*}
+pkgrel=1
+pkgdesc="A high-level scripting language"
+url="http://www.python.org"
+arch="all"
+license="custom"
+replaces="python-dev"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-tests
+ py-gdbm:gdbm
+ "
+depends=
+makedepends="expat-dev openssl-dev zlib-dev ncurses-dev bzip2-dev
+ gdbm-dev sqlite-dev libffi-dev"
+source="http://www.$pkgname.org/ftp/$pkgname/$pkgver/Python-$pkgver.tar.bz2
+ "
+
+prepare() {
+ cd "$srcdir/Python-$pkgver"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir/Python-$pkgver"
+ ./configure --prefix=/usr \
+ --enable-shared \
+ --with-threads \
+ --with-system-ffi \
+ --with-system-expat \
+ --enable-unicode=ucs4 \
+ || return 1
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/Python-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+ install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+ rm "$pkgdir/usr/bin/2to3" || return 1
+}
+
+_mv_files() {
+ local i
+ for i in "$@"; do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i || return 1
+ done
+}
+
+dev() {
+ # pyconfig.h is needed runtime so we move it back
+ default_dev
+ mkdir -p "$pkgdir"/usr/include/python$_verbase
+ mv "$subpkgdir"/usr/include/python$_verbase/pyconfig.h \
+ "$pkgdir"/usr/include/python$_verbase/
+}
+
+tests() {
+ pkgdesc="The test modules from the main python package"
+ cd "$pkgdir"
+ _mv_files usr/lib/python*/*/test \
+ usr/lib/python*/test
+}
+
+gdbm() {
+ pkgdesc="GNU dbm database support for Python"
+ cd "$pkgdir"
+ _mv_files $(find usr/lib -name '*gdbm*')
+}
+
+md5sums="ba7b2f11ffdbf195ee0d111b9455a5bd Python-2.7.2.tar.bz2"
diff --git a/main/qemu/80-kvm.rules b/main/qemu/80-kvm.rules
new file mode 100644
index 0000000000..e61b48ff32
--- /dev/null
+++ b/main/qemu/80-kvm.rules
@@ -0,0 +1 @@
+KERNEL=="kvm", GROUP="kvm", MODE="0666"
diff --git a/main/qemu/APKBUILD b/main/qemu/APKBUILD
new file mode 100644
index 0000000000..30cd47525a
--- /dev/null
+++ b/main/qemu/APKBUILD
@@ -0,0 +1,110 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=qemu
+pkgver=0.14.1
+pkgrel=0
+pkgdesc="QEMU is a generic machine emulator and virtualizer"
+url="http://www.nongnu.org/qemu/"
+arch="all"
+license="GPL-2 LGPL-2"
+makedepends="zlib-dev sdl-dev alsa-lib-dev gnutls-dev ncurses-dev"
+depends=
+install="qemu.pre-install"
+subpackages="
+$pkgname-arm
+$pkgname-cris
+$pkgname-m68k
+$pkgname-microblaze
+$pkgname-mips
+$pkgname-mips64
+$pkgname-mips64el
+$pkgname-mipsel
+$pkgname-ppc
+$pkgname-ppc64
+$pkgname-ppcemb
+$pkgname-sh4
+$pkgname-sh4eb
+$pkgname-sparc
+$pkgname-sparc64
+$pkgname-x86_64
+$pkgname-img
+"
+source="http://savannah.nongnu.org/download/$pkgname/$pkgname-$pkgver.tar.gz
+ qemu-libm.patch
+ 80-kvm.rules
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ # avoid fdt till an updated release appears
+ sed -i -e 's:fdt="yes":fdt="no":' configure
+ # prevent docs to get automatically installed
+ sed -i '/$(DESTDIR)$(docdir)/d' Makefile
+ # Alter target makefiles to accept CFLAGS
+ sed -i 's/^\(C\|OP_C\|HELPER_C\)FLAGS=/\1FLAGS+=/' \
+ Makefile Makefile.target tests/Makefile
+ sed -i 's/^VL_LDFLAGS=$/VL_LDFLAGS=-Wl,-z,execheap/' \
+ Makefile.target
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --audio-drv-list=oss,alsa,sdl \
+ --audio-card-list=ac97,sb16,es1370,adlib \
+ --disable-darwin-user \
+ --disable-bsd-user \
+ --disable-linux-user \
+ --cc="${CC:-gcc}"
+
+ make V=1 || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 "$srcdir"/80-kvm.rules \
+ "$pkgdir"/lib/udev/rules.d/80-kvm.rules
+}
+
+_subsys() {
+ pkgdesc="Qemu $1 system emulator"
+ depend="qemu"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/qemu-system-$1 "$subpkgdir"/usr/bin/
+}
+
+arm() { _subsys arm; }
+cris() { _subsys cris; }
+m68k() { _subsys m68k; }
+microblaze() { _subsys microblaze; }
+mips() { _subsys mips; }
+mips64() { _subsys mips64; }
+mips64el() { _subsys mips64el; }
+mipsel() { _subsys mipsel; }
+ppc() { _subsys ppc; }
+ppc64() { _subsys ppc64; }
+ppcemb() { _subsys ppcemb; }
+sh4() { _subsys sh4; }
+sh4eb() { _subsys sh4eb; }
+sparc() { _subsys sparc; }
+sparc64() { _subsys sparc64; }
+x86_64() { _subsys x86_64; }
+
+img() {
+ pkgdesc="QEMU command line tool for manipulating disk images"
+ replaces="qemu"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/qemu-img \
+ "$pkgdir"/usr/bin/qemu-io \
+ "$subpkgdir"/usr/bin/
+}
+
+md5sums="b6c713a8db638e173af53a62d5178640 qemu-0.14.1.tar.gz
+70a4336c31600ce00838b056f0d08452 qemu-libm.patch
+66660f143235201249dc0648b39b86ee 80-kvm.rules"
diff --git a/main/qemu/kqemu.c b/main/qemu/kqemu.c
new file mode 100644
index 0000000000..035d310ab9
--- /dev/null
+++ b/main/qemu/kqemu.c
@@ -0,0 +1,997 @@
+/*
+ * KQEMU support
+ *
+ * Copyright (c) 2005-2008 Fabrice Bellard
+ *
+ * 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 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ */
+#include "config.h"
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winioctl.h>
+#else
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#endif
+#ifdef HOST_SOLARIS
+#include <sys/ioccom.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "qemu-common.h"
+
+#ifdef USE_KQEMU
+
+#define DEBUG
+//#define PROFILE
+
+
+#ifdef DEBUG
+# define LOG_INT(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
+# define LOG_INT_STATE(env) log_cpu_state_mask(CPU_LOG_INT, (env), 0)
+#else
+# define LOG_INT(...) do { } while (0)
+# define LOG_INT_STATE(env) do { } while (0)
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include "kqemu.h"
+
+#ifdef _WIN32
+#define KQEMU_DEVICE "\\\\.\\kqemu"
+#else
+#define KQEMU_DEVICE "/dev/kqemu"
+#endif
+
+static void qpi_init(void);
+
+#ifdef _WIN32
+#define KQEMU_INVALID_FD INVALID_HANDLE_VALUE
+HANDLE kqemu_fd = KQEMU_INVALID_FD;
+#define kqemu_closefd(x) CloseHandle(x)
+#else
+#define KQEMU_INVALID_FD -1
+int kqemu_fd = KQEMU_INVALID_FD;
+#define kqemu_closefd(x) close(x)
+#endif
+
+/* 0 = not allowed
+ 1 = user kqemu
+ 2 = kernel kqemu
+*/
+int kqemu_allowed = 1;
+uint64_t *pages_to_flush;
+unsigned int nb_pages_to_flush;
+uint64_t *ram_pages_to_update;
+unsigned int nb_ram_pages_to_update;
+uint64_t *modified_ram_pages;
+unsigned int nb_modified_ram_pages;
+uint8_t *modified_ram_pages_table;
+int qpi_io_memory;
+uint32_t kqemu_comm_base; /* physical address of the QPI communication page */
+
+#define cpuid(index, eax, ecx, edx) \
+ asm volatile ("cpuid" \
+ : "=a" (eax), "=c" (ecx), "=d" (edx) \
+ : "0" (index))
+
+#ifdef __x86_64__
+static int is_cpuid_supported(void)
+{
+ return 1;
+}
+#else
+static int is_cpuid_supported(void)
+{
+ int v0, v1;
+ asm volatile ("pushf\n"
+ "popl %0\n"
+ "movl %0, %1\n"
+ "xorl $0x00200000, %0\n"
+ "pushl %0\n"
+ "popf\n"
+ "pushf\n"
+ "popl %0\n"
+ : "=a" (v0), "=d" (v1)
+ :
+ : "cc");
+ return (v0 != v1);
+}
+#endif
+
+static void kqemu_update_cpuid(CPUState *env)
+{
+ int critical_features_mask, features, ext_features, ext_features_mask;
+ uint32_t eax, ecx, edx;
+
+ /* the following features are kept identical on the host and
+ target cpus because they are important for user code. Strictly
+ speaking, only SSE really matters because the OS must support
+ it if the user code uses it. */
+ critical_features_mask =
+ CPUID_CMOV | CPUID_CX8 |
+ CPUID_FXSR | CPUID_MMX | CPUID_SSE |
+ CPUID_SSE2 | CPUID_SEP;
+ ext_features_mask = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR;
+ if (!is_cpuid_supported()) {
+ features = 0;
+ ext_features = 0;
+ } else {
+ cpuid(1, eax, ecx, edx);
+ features = edx;
+ ext_features = ecx;
+ }
+#ifdef __x86_64__
+ /* NOTE: on x86_64 CPUs, SYSENTER is not supported in
+ compatibility mode, so in order to have the best performances
+ it is better not to use it */
+ features &= ~CPUID_SEP;
+#endif
+ env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
+ (features & critical_features_mask);
+ env->cpuid_ext_features = (env->cpuid_ext_features & ~ext_features_mask) |
+ (ext_features & ext_features_mask);
+ /* XXX: we could update more of the target CPUID state so that the
+ non accelerated code sees exactly the same CPU features as the
+ accelerated code */
+}
+
+int kqemu_init(CPUState *env)
+{
+ struct kqemu_init kinit;
+ int ret, version;
+#ifdef _WIN32
+ DWORD temp;
+#endif
+
+ if (!kqemu_allowed)
+ return -1;
+
+#ifdef _WIN32
+ kqemu_fd = CreateFile(KQEMU_DEVICE, GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (kqemu_fd == KQEMU_INVALID_FD) {
+ fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated: %lu\n",
+ KQEMU_DEVICE, GetLastError());
+ return -1;
+ }
+#else
+ kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
+ if (kqemu_fd == KQEMU_INVALID_FD) {
+ fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated: %s\n",
+ KQEMU_DEVICE, strerror(errno));
+ return -1;
+ }
+#endif
+ version = 0;
+#ifdef _WIN32
+ DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
+ &version, sizeof(version), &temp, NULL);
+#else
+ ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
+#endif
+ if (version != KQEMU_VERSION) {
+ fprintf(stderr, "Version mismatch between kqemu module and qemu (%08x %08x) - disabling kqemu use\n",
+ version, KQEMU_VERSION);
+ goto fail;
+ }
+
+ pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH *
+ sizeof(uint64_t));
+ if (!pages_to_flush)
+ goto fail;
+
+ ram_pages_to_update = qemu_vmalloc(KQEMU_MAX_RAM_PAGES_TO_UPDATE *
+ sizeof(uint64_t));
+ if (!ram_pages_to_update)
+ goto fail;
+
+ modified_ram_pages = qemu_vmalloc(KQEMU_MAX_MODIFIED_RAM_PAGES *
+ sizeof(uint64_t));
+ if (!modified_ram_pages)
+ goto fail;
+ modified_ram_pages_table = qemu_mallocz(phys_ram_size >> TARGET_PAGE_BITS);
+ if (!modified_ram_pages_table)
+ goto fail;
+
+ memset(&kinit, 0, sizeof(kinit)); /* set the paddings to zero */
+ kinit.ram_base = phys_ram_base;
+ kinit.ram_size = phys_ram_size;
+ kinit.ram_dirty = phys_ram_dirty;
+ kinit.pages_to_flush = pages_to_flush;
+ kinit.ram_pages_to_update = ram_pages_to_update;
+ kinit.modified_ram_pages = modified_ram_pages;
+#ifdef _WIN32
+ ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &kinit, sizeof(kinit),
+ NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
+#else
+ ret = ioctl(kqemu_fd, KQEMU_INIT, &kinit);
+#endif
+ if (ret < 0) {
+ fprintf(stderr, "Error %d while initializing QEMU acceleration layer - disabling it for now\n", ret);
+ fail:
+ kqemu_closefd(kqemu_fd);
+ kqemu_fd = KQEMU_INVALID_FD;
+ return -1;
+ }
+ kqemu_update_cpuid(env);
+ env->kqemu_enabled = kqemu_allowed;
+ nb_pages_to_flush = 0;
+ nb_ram_pages_to_update = 0;
+
+ qpi_init();
+ return 0;
+}
+
+void kqemu_flush_page(CPUState *env, target_ulong addr)
+{
+ LOG_INT("kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
+ if (nb_pages_to_flush >= KQEMU_MAX_PAGES_TO_FLUSH)
+ nb_pages_to_flush = KQEMU_FLUSH_ALL;
+ else
+ pages_to_flush[nb_pages_to_flush++] = addr;
+}
+
+void kqemu_flush(CPUState *env, int global)
+{
+ LOG_INT("kqemu_flush:\n");
+ nb_pages_to_flush = KQEMU_FLUSH_ALL;
+}
+
+void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
+{
+ LOG_INT("kqemu_set_notdirty: addr=%08lx\n",
+ (unsigned long)ram_addr);
+ /* we only track transitions to dirty state */
+ if (phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] != 0xff)
+ return;
+ if (nb_ram_pages_to_update >= KQEMU_MAX_RAM_PAGES_TO_UPDATE)
+ nb_ram_pages_to_update = KQEMU_RAM_PAGES_UPDATE_ALL;
+ else
+ ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
+}
+
+static void kqemu_reset_modified_ram_pages(void)
+{
+ int i;
+ unsigned long page_index;
+
+ for(i = 0; i < nb_modified_ram_pages; i++) {
+ page_index = modified_ram_pages[i] >> TARGET_PAGE_BITS;
+ modified_ram_pages_table[page_index] = 0;
+ }
+ nb_modified_ram_pages = 0;
+}
+
+void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr)
+{
+ unsigned long page_index;
+ int ret;
+#ifdef _WIN32
+ DWORD temp;
+#endif
+
+ page_index = ram_addr >> TARGET_PAGE_BITS;
+ if (!modified_ram_pages_table[page_index]) {
+#if 0
+ printf("%d: modify_page=%08lx\n", nb_modified_ram_pages, ram_addr);
+#endif
+ modified_ram_pages_table[page_index] = 1;
+ modified_ram_pages[nb_modified_ram_pages++] = ram_addr;
+ if (nb_modified_ram_pages >= KQEMU_MAX_MODIFIED_RAM_PAGES) {
+ /* flush */
+#ifdef _WIN32
+ ret = DeviceIoControl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES,
+ &nb_modified_ram_pages,
+ sizeof(nb_modified_ram_pages),
+ NULL, 0, &temp, NULL);
+#else
+ ret = ioctl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES,
+ &nb_modified_ram_pages);
+#endif
+ kqemu_reset_modified_ram_pages();
+ }
+ }
+}
+
+void kqemu_set_phys_mem(uint64_t start_addr, ram_addr_t size,
+ ram_addr_t phys_offset)
+{
+ struct kqemu_phys_mem kphys_mem1, *kphys_mem = &kphys_mem1;
+ uint64_t end;
+ int ret, io_index;
+
+ end = (start_addr + size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+ start_addr &= TARGET_PAGE_MASK;
+ kphys_mem->phys_addr = start_addr;
+ kphys_mem->size = end - start_addr;
+ kphys_mem->ram_addr = phys_offset & TARGET_PAGE_MASK;
+ io_index = phys_offset & ~TARGET_PAGE_MASK;
+ switch(io_index) {
+ case IO_MEM_RAM:
+ kphys_mem->io_index = KQEMU_IO_MEM_RAM;
+ break;
+ case IO_MEM_ROM:
+ kphys_mem->io_index = KQEMU_IO_MEM_ROM;
+ break;
+ default:
+ if (qpi_io_memory == io_index) {
+ kphys_mem->io_index = KQEMU_IO_MEM_COMM;
+ } else {
+ kphys_mem->io_index = KQEMU_IO_MEM_UNASSIGNED;
+ }
+ break;
+ }
+#ifdef _WIN32
+ {
+ DWORD temp;
+ ret = DeviceIoControl(kqemu_fd, KQEMU_SET_PHYS_MEM,
+ kphys_mem, sizeof(*kphys_mem),
+ NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
+ }
+#else
+ ret = ioctl(kqemu_fd, KQEMU_SET_PHYS_MEM, kphys_mem);
+#endif
+ if (ret < 0) {
+ fprintf(stderr, "kqemu: KQEMU_SET_PHYS_PAGE error=%d: start_addr=0x%016" PRIx64 " size=0x%08lx phys_offset=0x%08lx\n",
+ ret, start_addr,
+ (unsigned long)size, (unsigned long)phys_offset);
+ }
+}
+
+struct fpstate {
+ uint16_t fpuc;
+ uint16_t dummy1;
+ uint16_t fpus;
+ uint16_t dummy2;
+ uint16_t fptag;
+ uint16_t dummy3;
+
+ uint32_t fpip;
+ uint32_t fpcs;
+ uint32_t fpoo;
+ uint32_t fpos;
+ uint8_t fpregs1[8 * 10];
+};
+
+struct fpxstate {
+ uint16_t fpuc;
+ uint16_t fpus;
+ uint16_t fptag;
+ uint16_t fop;
+ uint32_t fpuip;
+ uint16_t cs_sel;
+ uint16_t dummy0;
+ uint32_t fpudp;
+ uint16_t ds_sel;
+ uint16_t dummy1;
+ uint32_t mxcsr;
+ uint32_t mxcsr_mask;
+ uint8_t fpregs1[8 * 16];
+ uint8_t xmm_regs[16 * 16];
+ uint8_t dummy2[96];
+};
+
+static struct fpxstate fpx1 __attribute__((aligned(16)));
+
+static void restore_native_fp_frstor(CPUState *env)
+{
+ int fptag, i, j;
+ struct fpstate fp1, *fp = &fp1;
+
+ fp->fpuc = env->fpuc;
+ fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
+ fptag = 0;
+ for (i=7; i>=0; i--) {
+ fptag <<= 2;
+ if (env->fptags[i]) {
+ fptag |= 3;
+ } else {
+ /* the FPU automatically computes it */
+ }
+ }
+ fp->fptag = fptag;
+ j = env->fpstt;
+ for(i = 0;i < 8; i++) {
+ memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
+ j = (j + 1) & 7;
+ }
+ asm volatile ("frstor %0" : "=m" (*fp));
+}
+
+static void save_native_fp_fsave(CPUState *env)
+{
+ int fptag, i, j;
+ uint16_t fpuc;
+ struct fpstate fp1, *fp = &fp1;
+
+ asm volatile ("fsave %0" : : "m" (*fp));
+ env->fpuc = fp->fpuc;
+ env->fpstt = (fp->fpus >> 11) & 7;
+ env->fpus = fp->fpus & ~0x3800;
+ fptag = fp->fptag;
+ for(i = 0;i < 8; i++) {
+ env->fptags[i] = ((fptag & 3) == 3);
+ fptag >>= 2;
+ }
+ j = env->fpstt;
+ for(i = 0;i < 8; i++) {
+ memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
+ j = (j + 1) & 7;
+ }
+ /* we must restore the default rounding state */
+ fpuc = 0x037f | (env->fpuc & (3 << 10));
+ asm volatile("fldcw %0" : : "m" (fpuc));
+}
+
+static void restore_native_fp_fxrstor(CPUState *env)
+{
+ struct fpxstate *fp = &fpx1;
+ int i, j, fptag;
+
+ fp->fpuc = env->fpuc;
+ fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
+ fptag = 0;
+ for(i = 0; i < 8; i++)
+ fptag |= (env->fptags[i] << i);
+ fp->fptag = fptag ^ 0xff;
+
+ j = env->fpstt;
+ for(i = 0;i < 8; i++) {
+ memcpy(&fp->fpregs1[i * 16], &env->fpregs[j].d, 10);
+ j = (j + 1) & 7;
+ }
+ if (env->cpuid_features & CPUID_SSE) {
+ fp->mxcsr = env->mxcsr;
+ /* XXX: check if DAZ is not available */
+ fp->mxcsr_mask = 0xffff;
+ memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
+ }
+ asm volatile ("fxrstor %0" : "=m" (*fp));
+}
+
+static void save_native_fp_fxsave(CPUState *env)
+{
+ struct fpxstate *fp = &fpx1;
+ int fptag, i, j;
+ uint16_t fpuc;
+
+ asm volatile ("fxsave %0" : : "m" (*fp));
+ env->fpuc = fp->fpuc;
+ env->fpstt = (fp->fpus >> 11) & 7;
+ env->fpus = fp->fpus & ~0x3800;
+ fptag = fp->fptag ^ 0xff;
+ for(i = 0;i < 8; i++) {
+ env->fptags[i] = (fptag >> i) & 1;
+ }
+ j = env->fpstt;
+ for(i = 0;i < 8; i++) {
+ memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 16], 10);
+ j = (j + 1) & 7;
+ }
+ if (env->cpuid_features & CPUID_SSE) {
+ env->mxcsr = fp->mxcsr;
+ memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
+ }
+
+ /* we must restore the default rounding state */
+ asm volatile ("fninit");
+ fpuc = 0x037f | (env->fpuc & (3 << 10));
+ asm volatile("fldcw %0" : : "m" (fpuc));
+}
+
+static int do_syscall(CPUState *env,
+ struct kqemu_cpu_state *kenv)
+{
+ int selector;
+
+ selector = (env->star >> 32) & 0xffff;
+#ifdef TARGET_X86_64
+ if (env->hflags & HF_LMA_MASK) {
+ int code64;
+
+ env->regs[R_ECX] = kenv->next_eip;
+ env->regs[11] = env->eflags;
+
+ code64 = env->hflags & HF_CS64_MASK;
+
+ cpu_x86_set_cpl(env, 0);
+ cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
+ 0, 0xffffffff,
+ DESC_G_MASK | DESC_P_MASK |
+ DESC_S_MASK |
+ DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
+ cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
+ 0, 0xffffffff,
+ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+ DESC_S_MASK |
+ DESC_W_MASK | DESC_A_MASK);
+ env->eflags &= ~env->fmask;
+ if (code64)
+ env->eip = env->lstar;
+ else
+ env->eip = env->cstar;
+ } else
+#endif
+ {
+ env->regs[R_ECX] = (uint32_t)kenv->next_eip;
+
+ cpu_x86_set_cpl(env, 0);
+ cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
+ 0, 0xffffffff,
+ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+ DESC_S_MASK |
+ DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
+ cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
+ 0, 0xffffffff,
+ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+ DESC_S_MASK |
+ DESC_W_MASK | DESC_A_MASK);
+ env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
+ env->eip = (uint32_t)env->star;
+ }
+ return 2;
+}
+
+#ifdef CONFIG_PROFILER
+
+#define PC_REC_SIZE 1
+#define PC_REC_HASH_BITS 16
+#define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
+
+typedef struct PCRecord {
+ unsigned long pc;
+ int64_t count;
+ struct PCRecord *next;
+} PCRecord;
+
+static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
+static int nb_pc_records;
+
+static void kqemu_record_pc(unsigned long pc)
+{
+ unsigned long h;
+ PCRecord **pr, *r;
+
+ h = pc / PC_REC_SIZE;
+ h = h ^ (h >> PC_REC_HASH_BITS);
+ h &= (PC_REC_HASH_SIZE - 1);
+ pr = &pc_rec_hash[h];
+ for(;;) {
+ r = *pr;
+ if (r == NULL)
+ break;
+ if (r->pc == pc) {
+ r->count++;
+ return;
+ }
+ pr = &r->next;
+ }
+ r = malloc(sizeof(PCRecord));
+ r->count = 1;
+ r->pc = pc;
+ r->next = NULL;
+ *pr = r;
+ nb_pc_records++;
+}
+
+static int pc_rec_cmp(const void *p1, const void *p2)
+{
+ PCRecord *r1 = *(PCRecord **)p1;
+ PCRecord *r2 = *(PCRecord **)p2;
+ if (r1->count < r2->count)
+ return 1;
+ else if (r1->count == r2->count)
+ return 0;
+ else
+ return -1;
+}
+
+static void kqemu_record_flush(void)
+{
+ PCRecord *r, *r_next;
+ int h;
+
+ for(h = 0; h < PC_REC_HASH_SIZE; h++) {
+ for(r = pc_rec_hash[h]; r != NULL; r = r_next) {
+ r_next = r->next;
+ free(r);
+ }
+ pc_rec_hash[h] = NULL;
+ }
+ nb_pc_records = 0;
+}
+
+void kqemu_record_dump(void)
+{
+ PCRecord **pr, *r;
+ int i, h;
+ FILE *f;
+ int64_t total, sum;
+
+ pr = malloc(sizeof(PCRecord *) * nb_pc_records);
+ i = 0;
+ total = 0;
+ for(h = 0; h < PC_REC_HASH_SIZE; h++) {
+ for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
+ pr[i++] = r;
+ total += r->count;
+ }
+ }
+ qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
+
+ f = fopen("/tmp/kqemu.stats", "w");
+ if (!f) {
+ perror("/tmp/kqemu.stats");
+ exit(1);
+ }
+ fprintf(f, "total: %" PRId64 "\n", total);
+ sum = 0;
+ for(i = 0; i < nb_pc_records; i++) {
+ r = pr[i];
+ sum += r->count;
+ fprintf(f, "%08lx: %" PRId64 " %0.2f%% %0.2f%%\n",
+ r->pc,
+ r->count,
+ (double)r->count / (double)total * 100.0,
+ (double)sum / (double)total * 100.0);
+ }
+ fclose(f);
+ free(pr);
+
+ kqemu_record_flush();
+}
+#endif
+
+static inline void kqemu_load_seg(struct kqemu_segment_cache *ksc,
+ const SegmentCache *sc)
+{
+ ksc->selector = sc->selector;
+ ksc->flags = sc->flags;
+ ksc->limit = sc->limit;
+ ksc->base = sc->base;
+}
+
+static inline void kqemu_save_seg(SegmentCache *sc,
+ const struct kqemu_segment_cache *ksc)
+{
+ sc->selector = ksc->selector;
+ sc->flags = ksc->flags;
+ sc->limit = ksc->limit;
+ sc->base = ksc->base;
+}
+
+int kqemu_cpu_exec(CPUState *env)
+{
+ struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
+ int ret, cpl, i;
+#ifdef CONFIG_PROFILER
+ int64_t ti;
+#endif
+#ifdef _WIN32
+ DWORD temp;
+#endif
+
+#ifdef CONFIG_PROFILER
+ ti = profile_getclock();
+#endif
+ LOG_INT("kqemu: cpu_exec: enter\n");
+ LOG_INT_STATE(env);
+ for(i = 0; i < CPU_NB_REGS; i++)
+ kenv->regs[i] = env->regs[i];
+ kenv->eip = env->eip;
+ kenv->eflags = env->eflags;
+ for(i = 0; i < 6; i++)
+ kqemu_load_seg(&kenv->segs[i], &env->segs[i]);
+ kqemu_load_seg(&kenv->ldt, &env->ldt);
+ kqemu_load_seg(&kenv->tr, &env->tr);
+ kqemu_load_seg(&kenv->gdt, &env->gdt);
+ kqemu_load_seg(&kenv->idt, &env->idt);
+ kenv->cr0 = env->cr[0];
+ kenv->cr2 = env->cr[2];
+ kenv->cr3 = env->cr[3];
+ kenv->cr4 = env->cr[4];
+ kenv->a20_mask = env->a20_mask;
+ kenv->efer = env->efer;
+ kenv->tsc_offset = 0;
+ kenv->star = env->star;
+ kenv->sysenter_cs = env->sysenter_cs;
+ kenv->sysenter_esp = env->sysenter_esp;
+ kenv->sysenter_eip = env->sysenter_eip;
+#ifdef TARGET_X86_64
+ kenv->lstar = env->lstar;
+ kenv->cstar = env->cstar;
+ kenv->fmask = env->fmask;
+ kenv->kernelgsbase = env->kernelgsbase;
+#endif
+ if (env->dr[7] & 0xff) {
+ kenv->dr7 = env->dr[7];
+ kenv->dr0 = env->dr[0];
+ kenv->dr1 = env->dr[1];
+ kenv->dr2 = env->dr[2];
+ kenv->dr3 = env->dr[3];
+ } else {
+ kenv->dr7 = 0;
+ }
+ kenv->dr6 = env->dr[6];
+ cpl = (env->hflags & HF_CPL_MASK);
+ kenv->cpl = cpl;
+ kenv->nb_pages_to_flush = nb_pages_to_flush;
+ kenv->user_only = (env->kqemu_enabled == 1);
+ kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
+ nb_ram_pages_to_update = 0;
+ kenv->nb_modified_ram_pages = nb_modified_ram_pages;
+
+ kqemu_reset_modified_ram_pages();
+
+ if (env->cpuid_features & CPUID_FXSR)
+ restore_native_fp_fxrstor(env);
+ else
+ restore_native_fp_frstor(env);
+
+#ifdef _WIN32
+ if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,
+ kenv, sizeof(struct kqemu_cpu_state),
+ kenv, sizeof(struct kqemu_cpu_state),
+ &temp, NULL)) {
+ ret = kenv->retval;
+ } else {
+ ret = -1;
+ }
+#else
+ ioctl(kqemu_fd, KQEMU_EXEC, kenv);
+ ret = kenv->retval;
+#endif
+ if (env->cpuid_features & CPUID_FXSR)
+ save_native_fp_fxsave(env);
+ else
+ save_native_fp_fsave(env);
+
+ for(i = 0; i < CPU_NB_REGS; i++)
+ env->regs[i] = kenv->regs[i];
+ env->eip = kenv->eip;
+ env->eflags = kenv->eflags;
+ for(i = 0; i < 6; i++)
+ kqemu_save_seg(&env->segs[i], &kenv->segs[i]);
+ cpu_x86_set_cpl(env, kenv->cpl);
+ kqemu_save_seg(&env->ldt, &kenv->ldt);
+ env->cr[0] = kenv->cr0;
+ env->cr[4] = kenv->cr4;
+ env->cr[3] = kenv->cr3;
+ env->cr[2] = kenv->cr2;
+ env->dr[6] = kenv->dr6;
+#ifdef TARGET_X86_64
+ env->kernelgsbase = kenv->kernelgsbase;
+#endif
+
+ /* flush pages as indicated by kqemu */
+ if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {
+ tlb_flush(env, 1);
+ } else {
+ for(i = 0; i < kenv->nb_pages_to_flush; i++) {
+ tlb_flush_page(env, pages_to_flush[i]);
+ }
+ }
+ nb_pages_to_flush = 0;
+
+#ifdef CONFIG_PROFILER
+ kqemu_time += profile_getclock() - ti;
+ kqemu_exec_count++;
+#endif
+
+ if (kenv->nb_ram_pages_to_update > 0) {
+ cpu_tlb_update_dirty(env);
+ }
+
+ if (kenv->nb_modified_ram_pages > 0) {
+ for(i = 0; i < kenv->nb_modified_ram_pages; i++) {
+ unsigned long addr;
+ addr = modified_ram_pages[i];
+ tb_invalidate_phys_page_range(addr, addr + TARGET_PAGE_SIZE, 0);
+ }
+ }
+
+ /* restore the hidden flags */
+ {
+ unsigned int new_hflags;
+#ifdef TARGET_X86_64
+ if ((env->hflags & HF_LMA_MASK) &&
+ (env->segs[R_CS].flags & DESC_L_MASK)) {
+ /* long mode */
+ new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
+ } else
+#endif
+ {
+ /* legacy / compatibility case */
+ new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
+ >> (DESC_B_SHIFT - HF_CS32_SHIFT);
+ new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
+ >> (DESC_B_SHIFT - HF_SS32_SHIFT);
+ if (!(env->cr[0] & CR0_PE_MASK) ||
+ (env->eflags & VM_MASK) ||
+ !(env->hflags & HF_CS32_MASK)) {
+ /* XXX: try to avoid this test. The problem comes from the
+ fact that is real mode or vm86 mode we only modify the
+ 'base' and 'selector' fields of the segment cache to go
+ faster. A solution may be to force addseg to one in
+ translate-i386.c. */
+ new_hflags |= HF_ADDSEG_MASK;
+ } else {
+ new_hflags |= ((env->segs[R_DS].base |
+ env->segs[R_ES].base |
+ env->segs[R_SS].base) != 0) <<
+ HF_ADDSEG_SHIFT;
+ }
+ }
+ env->hflags = (env->hflags &
+ ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
+ new_hflags;
+ }
+ /* update FPU flags */
+ env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
+ ((env->cr[0] << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
+ if (env->cr[4] & CR4_OSFXSR_MASK)
+ env->hflags |= HF_OSFXSR_MASK;
+ else
+ env->hflags &= ~HF_OSFXSR_MASK;
+
+ LOG_INT("kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
+ if (ret == KQEMU_RET_SYSCALL) {
+ /* syscall instruction */
+ return do_syscall(env, kenv);
+ } else
+ if ((ret & 0xff00) == KQEMU_RET_INT) {
+ env->exception_index = ret & 0xff;
+ env->error_code = 0;
+ env->exception_is_int = 1;
+ env->exception_next_eip = kenv->next_eip;
+#ifdef CONFIG_PROFILER
+ kqemu_ret_int_count++;
+#endif
+ LOG_INT("kqemu: interrupt v=%02x:\n", env->exception_index);
+ LOG_INT_STATE(env);
+ return 1;
+ } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
+ env->exception_index = ret & 0xff;
+ env->error_code = kenv->error_code;
+ env->exception_is_int = 0;
+ env->exception_next_eip = 0;
+#ifdef CONFIG_PROFILER
+ kqemu_ret_excp_count++;
+#endif
+ LOG_INT("kqemu: exception v=%02x e=%04x:\n",
+ env->exception_index, env->error_code);
+ LOG_INT_STATE(env);
+ return 1;
+ } else if (ret == KQEMU_RET_INTR) {
+#ifdef CONFIG_PROFILER
+ kqemu_ret_intr_count++;
+#endif
+ LOG_INT_STATE(env);
+ return 0;
+ } else if (ret == KQEMU_RET_SOFTMMU) {
+#ifdef CONFIG_PROFILER
+ {
+ unsigned long pc = env->eip + env->segs[R_CS].base;
+ kqemu_record_pc(pc);
+ }
+#endif
+ LOG_INT_STATE(env);
+ return 2;
+ } else {
+ cpu_dump_state(env, stderr, fprintf, 0);
+ fprintf(stderr, "Unsupported return value: 0x%x\n", ret);
+ exit(1);
+ }
+ return 0;
+}
+
+void kqemu_cpu_interrupt(CPUState *env)
+{
+#if defined(_WIN32)
+ /* cancelling the I/O request causes KQEMU to finish executing the
+ current block and successfully returning. */
+ CancelIo(kqemu_fd);
+#endif
+}
+
+/*
+ QEMU paravirtualization interface. The current interface only
+ allows to modify the IF and IOPL flags when running in
+ kqemu.
+
+ At this point it is not very satisfactory. I leave it for reference
+ as it adds little complexity.
+*/
+
+#define QPI_COMM_PAGE_PHYS_ADDR 0xff000000
+
+static uint32_t qpi_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static uint32_t qpi_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static void qpi_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+}
+
+static void qpi_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+}
+
+static uint32_t qpi_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env;
+
+ env = cpu_single_env;
+ if (!env)
+ return 0;
+ return env->eflags & (IF_MASK | IOPL_MASK);
+}
+
+/* Note: after writing to this address, the guest code must make sure
+ it is exiting the current TB. pushf/popf can be used for that
+ purpose. */
+static void qpi_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ CPUState *env;
+
+ env = cpu_single_env;
+ if (!env)
+ return;
+ env->eflags = (env->eflags & ~(IF_MASK | IOPL_MASK)) |
+ (val & (IF_MASK | IOPL_MASK));
+}
+
+static CPUReadMemoryFunc *qpi_mem_read[3] = {
+ qpi_mem_readb,
+ qpi_mem_readw,
+ qpi_mem_readl,
+};
+
+static CPUWriteMemoryFunc *qpi_mem_write[3] = {
+ qpi_mem_writeb,
+ qpi_mem_writew,
+ qpi_mem_writel,
+};
+
+static void qpi_init(void)
+{
+ kqemu_comm_base = 0xff000000 | 1;
+ qpi_io_memory = cpu_register_io_memory(0,
+ qpi_mem_read,
+ qpi_mem_write, NULL);
+ cpu_register_physical_memory(kqemu_comm_base & ~0xfff,
+ 0x1000, qpi_io_memory);
+}
+#endif
diff --git a/main/qemu/qemu-libm.patch b/main/qemu/qemu-libm.patch
new file mode 100644
index 0000000000..c7f0db707b
--- /dev/null
+++ b/main/qemu/qemu-libm.patch
@@ -0,0 +1,11 @@
+--- ./Makefile.orig
++++ ./Makefile
+@@ -29,7 +29,7 @@
+
+ $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
+
+-LIBS+=-lz $(LIBS_TOOLS)
++LIBS+=-lm -lz $(LIBS_TOOLS)
+
+ ifdef BUILD_DOCS
+ DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
diff --git a/main/qemu/qemu.pre-install b/main/qemu/qemu.pre-install
new file mode 100644
index 0000000000..68d7043acc
--- /dev/null
+++ b/main/qemu/qemu.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if ! getent group kvm >/dev/null; then
+ addgroup -g 34 -S kvm
+fi
+
diff --git a/main/qt/APKBUILD b/main/qt/APKBUILD
new file mode 100644
index 0000000000..ed778191b6
--- /dev/null
+++ b/main/qt/APKBUILD
@@ -0,0 +1,236 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=qt
+pkgver=4.7.3
+pkgrel=3
+pkgdesc="A cross-platform application and UI framework"
+url="http://qt.nokia.com/"
+arch="all"
+license="GPL3 LGPL"
+depends="ca-certificates"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-assistant $pkgname-config
+ $pkgname-sqlite $pkgname-odbc $pkgname-postgresql $pkgname-mysql
+ $pkgname-webkit $pkgname-x11"
+
+depends_dev="mesa-dev libice-dev libsm-dev libx11-dev libxext-dev
+ libxrender-dev alsa-lib-dev openssl-dev fontconfig-dev freetype-dev
+ glib-dev libpng-dev zlib-dev sqlite-dev dbus-dev"
+makedepends="$depends_dev postgresql-dev mysql-dev unixodbc-dev cups-dev
+ gtk+-dev tiff-dev libmng-dev libxrandr-dev libxv-dev libxi-dev perl"
+install=
+source="ftp://ftp.qt.nokia.com/qt/source/qt-everywhere-opensource-src-$pkgver.tar.gz
+ assistant.desktop
+ designer.desktop
+ linguist.desktop
+ qtconfig.desktop
+ "
+
+_builddir="$srcdir"/qt-everywhere-opensource-src-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+ sed -i "s|-O2|$CXXFLAGS|" mkspecs/common/g++.conf
+ sed -i "/^QMAKE_RPATH/s| -Wl,-rpath,||g" mkspecs/common/g++.conf
+ sed -i "/^QMAKE_LFLAGS\s/s|+=|+= $LDFLAGS|g" mkspecs/common/g++.conf
+}
+
+build() {
+ cd "$_builddir"
+ unset QMAKESPEC
+ export QT4DIR="$_builddir"
+ export PATH="${QT4DIR}/bin:${PATH}"
+ export LD_LIBRARY_PATH=${QT4DIR}/lib:${LD_LIBRARY_PATH}
+ ./configure -confirm-license -opensource \
+ -prefix /usr \
+ -docdir /usr/share/doc/qt \
+ -plugindir /usr/lib/qt/plugins \
+ -importdir /usr/lib/qt/imports \
+ -datadir /usr/share/qt \
+ -translationdir /usr/share/qt/translations \
+ -sysconfdir /etc \
+ -examplesdir /usr/share/doc/qt/examples \
+ -demosdir /usr/share/doc/qt/demos \
+ -largefile \
+ -plugin-sql-psql \
+ -plugin-sql-mysql \
+ -plugin-sql-sqlite \
+ -plugin-sql-odbc \
+ -system-sqlite \
+ -xmlpatterns \
+ -no-phonon \
+ -no-phonon-backend \
+ -svg \
+ -webkit \
+ -script \
+ -scripttools \
+ -system-zlib \
+ -system-libtiff \
+ -system-libpng \
+ -system-libmng \
+ -system-libjpeg \
+ -nomake demos \
+ -nomake examples \
+ -nomake docs \
+ -no-rpath \
+ -openssl-linked \
+ -silent \
+ -optimized-qmake \
+ -dbus \
+ -reduce-relocations \
+ -no-separate-debug-info \
+ -gtkstyle \
+ -opengl \
+ -no-openvg \
+ -glib \
+ || return 1
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make INSTALL_ROOT="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+
+ # install missing icons and desktop files
+ for icon in tools/linguist/linguist/images/icons/linguist-*-32.png ; do
+ size=$(echo $(basename ${icon}) | cut -d- -f2)
+ install -p -D -m644 ${icon} "${pkgdir}"/usr/share/icons/hicolor/${size}x${size}/apps/linguist.png
+ done
+ install -p -Dm644 src/gui/dialogs/images/qtlogo-64.png \
+ "${pkgdir}"/usr/share/icons/hicolor/64x64/apps/qtlogo.png
+ install -p -Dm644 tools/assistant/tools/assistant/images/assistant.png \
+ "${pkgdir}"/usr/share/icons/hicolor/32x32/apps/assistant.png
+ install -p -Dm644 tools/designer/src/designer/images/designer.png \
+ "${pkgdir}"/usr/share/icons/hicolor/128x128/apps/designer.png
+ install -d ${pkgdir}/usr/share/applications
+ for i in linguist designer assistant qtconfig; do
+ install -m644 "${srcdir}"/$i.desktop \
+ "${pkgdir}"/usr/share/applications/ || return 1
+ done
+
+ # install license addition
+ install -D -m644 LGPL_EXCEPTION.txt \
+ "${pkgdir}"/usr/share/licenses/qt/LGPL_EXCEPTION.txt
+
+ # Fix wrong path in pkgconfig files
+ find "${pkgdir}"/usr/lib/pkgconfig -type f -name '*.pc' \
+ -exec perl -pi -e "s, -L${srcdir}/?\S+,,g" {} \; \
+ || return 1
+ # Fix wrong path in prl files
+ find "${pkgdir}"/usr/lib -type f -name '*.prl' -exec sed -i \
+ -e '/^QMAKE_PRL_BUILD_DIR/d;s/\(QMAKE_PRL_LIBS =\).*/\1/' {} \;\
+ || return 1
+}
+
+_mv_files() {
+ local i
+ for i in "$@"; do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i || return 1
+ done
+}
+
+dev() {
+ mkdir -p "$subpkgdir"/usr/share/qt \
+ "$subpkgdir"/usr/bin \
+ "$subpkgdir"/usr/lib \
+
+ mv "$pkgdir"/usr/share/qt/mkspecs \
+ "$pkgdir"/usr/share/qt/q3porting.xml \
+ "$subpkgdir"/usr/share/qt/ \
+ || return 1
+ default_dev
+
+ mv "$pkgdir"/usr/lib/*.prl "$subpkgdir"/usr/lib/ || return 1
+
+ cd "$pkgdir"/usr/bin
+ mv designer lconvert linguist lrelease lupdate moc pixeltool \
+ qcollectiongenerator qdbuscpp2xml qdbusxml2cpp qdoc3 \
+ qhelpconverter qhelpgenerator qmake qt3to4 qttracereplay \
+ rcc uic uic3 xmlpatterns xmlpatternsvalidator \
+ "$subpkgdir"/usr/bin/ || return 1
+
+ cd "$pkgdir"
+ _mv_files $(find * -name 'designer*') \
+ $(find * -name 'linguist*')
+}
+
+assistant() {
+ pkgdesc="Documentation browser for Qt"
+ cd "$pkgdir"
+ _mv_files $(find * -name 'assistant*') || return 1
+}
+
+config() {
+ pkgdesc="Graphical configuration tool for programs using Qt"
+ cd "$pkgdir"
+ _mv_files $(find * -name 'qt*config*') || return 1
+}
+
+sqlite() {
+ pkgdesc="SQLite driver for Qt's SQL classes"
+ cd "$pkgdir"
+ _mv_files usr/lib/qt/plugins/sqldrivers/libqsqlite*
+}
+
+odbc() {
+ pkgdesc="ODBC driver for Qt's SQL classes"
+ cd "$pkgdir"
+ _mv_files usr/lib/qt/plugins/sqldrivers/libqsqlodbc*
+}
+
+postgresql() {
+ pkgdesc="PostgreSQL driver for Qt's SQL classes"
+ cd "$pkgdir"
+ _mv_files usr/lib/qt/plugins/sqldrivers/libqsqlpsql*
+}
+
+mysql() {
+ pkgdesc="MySQL driver for Qt's SQL classes"
+ cd "$pkgdir"
+ _mv_files usr/lib/qt/plugins/sqldrivers/libqsqlmysql*
+}
+
+
+webkit() {
+ mkdir -p "$subpkgdir"/usr/lib/qt/imports
+ mv "$pkgdir"/usr/lib/libQtWebKit.so.* \
+ "$subpkgdir"/usr/lib/ || return 1
+ mv "$pkgdir"/usr/lib/qt/imports/QtWebKit \
+ "$subpkgdir"/usr/lib/qt/imports/ || return 1
+}
+
+x11() {
+ pkgdesc="Qt GUI-related libraries"
+ depends="hicolor-icon-theme"
+ cd "$pkgdir"
+ _mv_files \
+ usr/bin/qdbusviewer \
+ usr/bin/qmlviewer \
+ usr/lib/libQt3Support.so.* \
+ usr/lib/libQtCLucene.so.* \
+ usr/lib/libQtDesigner.so.* \
+ usr/lib/libQtDeclarative.so.* \
+ usr/lib/libQtDesignerComponents.so.* \
+ usr/lib/libQtGui.so.* \
+ usr/lib/libQtHelp.so.* \
+ usr/lib/libQtMultimedia.so.* \
+ usr/lib/libQtOpenGL.so.* \
+ usr/lib/libQtScriptTools.so.* \
+ usr/lib/libQtSvg.so.* \
+ usr/share/icons \
+ usr/lib/qt/imports \
+ usr/lib/qt/plugins
+}
+
+md5sums="49b96eefb1224cc529af6fe5608654fe qt-everywhere-opensource-src-4.7.3.tar.gz
+a445c6917086d80f1cfc1e40cb6b0132 assistant.desktop
+d457f0a0ad68a3861c3cadefe3b42ded designer.desktop
+668331d9798a0e2b94381efb7be4c513 linguist.desktop
+c29f2993d6a0f73d756d2fa36e130e1c qtconfig.desktop"
diff --git a/main/qt/PKGBUILD b/main/qt/PKGBUILD
new file mode 100644
index 0000000000..f39d13ee4f
--- /dev/null
+++ b/main/qt/PKGBUILD
@@ -0,0 +1,119 @@
+# $Id: PKGBUILD 94734 2010-10-10 14:30:15Z andrea $
+# Maintainer: Andrea Scarpino <andrea@archlinux.org>
+# Contributor: Pierre Schmitz <pierre@archlinux.de>
+
+pkgname=qt
+pkgver=4.7.0
+pkgrel=4
+pkgdesc='A cross-platform application and UI framework'
+arch=('i686' 'x86_64')
+url='http://qt.nokia.com/'
+license=('GPL3' 'LGPL')
+depends=('libtiff' 'libpng' 'libmng' 'sqlite3' 'ca-certificates' 'glib2' 'dbus'
+ 'fontconfig' 'libgl' 'libsm' 'libxrandr' 'libxv' 'libxi' 'alsa-lib'
+ 'xdg-utils' 'hicolor-icon-theme')
+optdepends=('postgresql-libs: PostgreSQL driver'
+ 'libmysqlclient: MySQL driver'
+ 'unixodbc: ODBC driver'
+ 'libxinerama: Xinerama support'
+ 'libxcursor: Xcursor support'
+ 'libxfixes: Xfixes support')
+makedepends=('mesa' 'postgresql-libs' 'mysql' 'unixodbc' 'cups' 'gtk2')
+install="${pkgname}.install"
+options=('!libtool')
+_pkgfqn="qt-everywhere-opensource-src-${pkgver}"
+source=("ftp://ftp.qt.nokia.com/qt/source/${_pkgfqn}.tar.gz"
+ 'assistant.desktop' 'designer.desktop' 'linguist.desktop' 'qtconfig.desktop'
+ 'fix-scroll-when-last-item-is-removed.patch'
+ 'fix-multisampling-with-ati-card.patch')
+md5sums=('3a2f25b9b115037277f4fb759194a7a5'
+ 'a445c6917086d80f1cfc1e40cb6b0132'
+ 'd457f0a0ad68a3861c3cadefe3b42ded'
+ '668331d9798a0e2b94381efb7be4c513'
+ 'c29f2993d6a0f73d756d2fa36e130e1c'
+ 'ef20c34afc5be5ed62f2935be66d9402'
+ 'b2e0f134bbb848ebef41134a45a36ee9')
+
+build() {
+ unset QMAKESPEC
+ export QT4DIR=$srcdir/$_pkgfqn
+ export PATH=${QT4DIR}/bin:${PATH}
+ export LD_LIBRARY_PATH=${QT4DIR}/lib:${LD_LIBRARY_PATH}
+
+ cd $srcdir/$_pkgfqn
+
+ # Already fixed in 4.7.1
+ patch -Np1 -i ${srcdir}/fix-scroll-when-last-item-is-removed.patch
+ patch -Np1 -i ${srcdir}/fix-multisampling-with-ati-card.patch
+
+ sed -i "s|-O2|$CXXFLAGS|" mkspecs/common/g++.conf
+ sed -i "/^QMAKE_RPATH/s| -Wl,-rpath,||g" mkspecs/common/g++.conf
+ sed -i "/^QMAKE_LFLAGS\s/s|+=|+= $LDFLAGS|g" mkspecs/common/g++.conf
+
+ ./configure -confirm-license -opensource \
+ -prefix /usr \
+ -docdir /usr/share/doc/qt \
+ -plugindir /usr/lib/qt/plugins \
+ -importdir /usr/lib/qt/imports \
+ -datadir /usr/share/qt \
+ -translationdir /usr/share/qt/translations \
+ -sysconfdir /etc \
+ -examplesdir /usr/share/doc/qt/examples \
+ -demosdir /usr/share/doc/qt/demos \
+ -largefile \
+ -plugin-sql-{psql,mysql,sqlite,odbc} \
+ -system-sqlite \
+ -xmlpatterns \
+ -no-phonon \
+ -no-phonon-backend \
+ -svg \
+ -webkit \
+ -script \
+ -scripttools \
+ -system-zlib \
+ -system-libtiff \
+ -system-libpng \
+ -system-libmng \
+ -system-libjpeg \
+ -nomake demos \
+ -nomake examples \
+ -nomake docs \
+ -no-rpath \
+ -openssl-linked \
+ -silent \
+ -optimized-qmake \
+ -dbus \
+ -reduce-relocations \
+ -no-separate-debug-info \
+ -gtkstyle \
+ -opengl \
+ -no-openvg \
+ -glib
+ make
+}
+
+package() {
+ cd $srcdir/$_pkgfqn
+ make INSTALL_ROOT=$pkgdir install
+
+ # install missing icons and desktop files
+ for icon in tools/linguist/linguist/images/icons/linguist-*-32.png ; do
+ size=$(echo $(basename ${icon}) | cut -d- -f2)
+ install -p -D -m644 ${icon} ${pkgdir}/usr/share/icons/hicolor/${size}x${size}/apps/linguist.png
+ done
+ install -p -D -m644 src/gui/dialogs/images/qtlogo-64.png ${pkgdir}/usr/share/icons/hicolor/64x64/apps/qtlogo.png
+ install -p -D -m644 tools/assistant/tools/assistant/images/assistant.png ${pkgdir}/usr/share/icons/hicolor/32x32/apps/assistant.png
+ install -p -D -m644 tools/designer/src/designer/images/designer.png ${pkgdir}/usr/share/icons/hicolor/128x128/apps/designer.png
+ install -d ${pkgdir}/usr/share/applications
+ install -m644 ${srcdir}/{linguist,designer,assistant,qtconfig}.desktop ${pkgdir}/usr/share/applications/
+
+ # install license addition
+ install -D -m644 LGPL_EXCEPTION.txt ${pkgdir}/usr/share/licenses/qt/LGPL_EXCEPTION.txt
+
+ # Fix wrong path in pkgconfig files
+ find ${pkgdir}/usr/lib/pkgconfig -type f -name '*.pc' \
+ -exec perl -pi -e "s, -L${srcdir}/?\S+,,g" {} \;
+ # Fix wrong path in prl files
+ find ${pkgdir}/usr/lib -type f -name '*.prl' \
+ -exec sed -i -e '/^QMAKE_PRL_BUILD_DIR/d;s/\(QMAKE_PRL_LIBS =\).*/\1/' {} \;
+}
diff --git a/main/qt/assistant.desktop b/main/qt/assistant.desktop
new file mode 100644
index 0000000000..1b9f0a7680
--- /dev/null
+++ b/main/qt/assistant.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Exec=/usr/bin/assistant
+Name=Qt Assistant
+GenericName=Qt Document Browser
+Icon=assistant
+Terminal=false
+Type=Application
+Categories=Qt;Development;Documentation
diff --git a/main/qt/designer.desktop b/main/qt/designer.desktop
new file mode 100644
index 0000000000..8f362731bf
--- /dev/null
+++ b/main/qt/designer.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Exec=/usr/bin/designer
+Name=Qt Designer
+GenericName=Interface Designer
+MimeType=application/x-designer
+Icon=designer
+Terminal=false
+Type=Application
+Categories=Qt;Development;GUIDesigner
diff --git a/main/qt/linguist.desktop b/main/qt/linguist.desktop
new file mode 100644
index 0000000000..94e92c1b08
--- /dev/null
+++ b/main/qt/linguist.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Exec=/usr/bin/linguist
+Name=Qt Linguist
+GenericName=Translation Tool
+MimeType=application/x-linguist
+Terminal=false
+Type=Application
+Icon=linguist
+Categories=Qt;Development;Translation
diff --git a/main/qt/qt.install b/main/qt/qt.install
new file mode 100644
index 0000000000..e70c054ec6
--- /dev/null
+++ b/main/qt/qt.install
@@ -0,0 +1,11 @@
+post_install() {
+ xdg-icon-resource forceupdate --theme hicolor &> /dev/null
+}
+
+post_upgrade() {
+ post_install
+}
+
+post_remove() {
+ post_install
+}
diff --git a/main/qt/qtconfig.desktop b/main/qt/qtconfig.desktop
new file mode 100644
index 0000000000..7c221e5f88
--- /dev/null
+++ b/main/qt/qtconfig.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=Qt Config
+Comment=Configure Qt behavior, styles, fonts
+Exec=/usr/bin/qtconfig
+Icon=qtlogo
+Terminal=false
+Type=Application
+Categories=Qt;Settings;
diff --git a/main/quagga/APKBUILD b/main/quagga/APKBUILD
new file mode 100644
index 0000000000..ed324b28ba
--- /dev/null
+++ b/main/quagga/APKBUILD
@@ -0,0 +1,80 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=quagga
+pkgver=0.99.18
+pkgrel=1
+pkgdesc="A free routing daemon replacing Zebra supporting RIP, OSPF and BGP."
+url="http://quagga.net/"
+arch="all"
+license="GPL-2"
+depends="iproute2"
+makedepends="readline-dev ncurses-dev gawk
+ autoconf automake libtool"
+install="$pkgname.pre-install $pkgname.post-install"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.quagga.net/download/$pkgname-$pkgver.tar.gz
+ $pkgname-0.99.11-link-libcap.patch
+ $pkgname-0.99.11-del-routes.patch
+ bgpd.initd
+ ospf6d.initd
+ ospfd.initd
+ ripd.initd
+ ripngd.initd
+ zebra.initd
+ zebra.confd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
+ msg "Running autotools..."
+ aclocal || return 1
+ autoconf || return 1
+ automake || return 1
+ libtoolize || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-static \
+ --enable-ipv6 \
+ --enable-ospf6d \
+ --enable-rtadv \
+ --enable-user=quagga \
+ --enable-group=quagga \
+ --enable-vty-group=quagga \
+ --enable-vtysh \
+ --sysconfdir=/etc/quagga \
+ --enable-exampledir=/usr/share/doc/quagga/ \
+ --localstatedir=/var/run/quagga \
+ || return 1
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ install -d "$pkgdir"/var/run/quagga
+ for i in zebra ripd ospfd bgpd ripngd ospf6d; do
+ install -Dm755 "$srcdir"/$i.initd "$pkgdir"/etc/init.d/$i
+ done
+ install -Dm644 "$srcdir/zebra.confd" "$pkgdir"/etc/conf.d/zebra
+}
+md5sums="59e306e93a4a1ce16760f20e9075d473 quagga-0.99.18.tar.gz
+8f99d41a8ed79e51704e8f655d255f29 quagga-0.99.11-link-libcap.patch
+1cbcf60a637b2577dee4d6df711e1247 quagga-0.99.11-del-routes.patch
+ec7ac8cc1103f023cf5b9482b26ece59 bgpd.initd
+92aba039c049050c48abf984c2db7e2b ospf6d.initd
+878328ead225e6eb5f5f77f05ab39106 ospfd.initd
+5945863133a0db33898c5c39ef23663c ripd.initd
+cda4115283d9f4a8304fec1b6881a7eb ripngd.initd
+172e5b0e3f169e2b3328123e73517084 zebra.initd
+34e06a1d2bc602ce691abc9ed169dd15 zebra.confd"
diff --git a/main/quagga/bgpd.initd b/main/quagga/bgpd.initd
new file mode 100644
index 0000000000..92ed536f3d
--- /dev/null
+++ b/main/quagga/bgpd.initd
@@ -0,0 +1,34 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/bgpd.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+ after firewall opennhrp
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/bgpd.conf ] ; then
+ eerror "You need to create /etc/quagga/bgpd.conf first."
+ eerror "An example can be found in /etc/quagga/samples/bgpd.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting bgpd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/bgpd \
+ -- -d -f /etc/quagga/bgpd.conf \
+ --pid_file /var/run/quagga/bgpd.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping bgpd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/bgpd.pid
+ result=$?
+ eend $result
+}
diff --git a/main/quagga/ospf6d.initd b/main/quagga/ospf6d.initd
new file mode 100644
index 0000000000..884a7e9818
--- /dev/null
+++ b/main/quagga/ospf6d.initd
@@ -0,0 +1,34 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/ospf6d.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+ after firewall
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/ospf6d.conf ] ; then
+ eerror "You need to create /etc/quagga/ospf6d.conf first."
+ eerror "An example can be found in /etc/quagga/samples/ospf6d.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ospf6d"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ospf6d \
+ -- -d -f /etc/quagga/ospf6d.conf \
+ --pid_file /var/run/quagga/ospf6d.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping ospf6d"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/ospf6d.pid
+ result=$?
+ eend $result
+}
diff --git a/main/quagga/ospfd.initd b/main/quagga/ospfd.initd
new file mode 100644
index 0000000000..5eeb44677f
--- /dev/null
+++ b/main/quagga/ospfd.initd
@@ -0,0 +1,34 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/ospfd.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+ after firewall
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/ospfd.conf ] ; then
+ eerror "You need to create /etc/quagga/ospfd.conf first."
+ eerror "An example can be found in /etc/quagga/samples/ospfd.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ospfd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ospfd \
+ -- -d -f /etc/quagga/ospfd.conf \
+ --pid_file /var/run/quagga/ospfd.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping ospfd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/ospfd.pid
+ result=$?
+ eend $result
+}
diff --git a/main/quagga/quagga-0.99.11-del-routes.patch b/main/quagga/quagga-0.99.11-del-routes.patch
new file mode 100644
index 0000000000..72ee89929c
--- /dev/null
+++ b/main/quagga/quagga-0.99.11-del-routes.patch
@@ -0,0 +1,44 @@
+From http://lists.quagga.net/pipermail/quagga-dev/2009-January/006362.html
+
+If there are two paralell PtP links to the same router:
+ C * 192.168.101.112/32 is directly connected, p1-4-19-4-20
+ C>* 192.168.101.112/32 is directly connected, p1-4-17-4-18
+and the cable is to one of the ppp links is pulled, Zebra
+deletes both routes instead of just the one that got yanked.
+This fixes it to only delete the route to the interface that
+got yanked.
+---
+This fix was suggested by lsorense at csclub.uwaterloo.ca (Lennart Sorensen)
+who had a similar problem. See [quagga-dev 6355]
+
+ zebra/zebra_rib.c | 9 ++++++++-
+ 1 files changed, 8 insertions(+), 1 deletions(-)
+
+diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
+index 90db932..7a37387 100644
+--- a/zebra/zebra_rib.c
++++ b/zebra/zebra_rib.c
+@@ -1896,6 +1896,13 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
+ inet_ntoa (*gate),
+ ifindex);
+
++ if (IS_ZEBRA_DEBUG_KERNEL && !gate)
++ zlog_debug ("rib_delete_ipv4(): route delete %s/%d directly, %s ifindex %d",
++ inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ),
++ p->prefixlen,
++ ifindex2ifname(ifindex),
++ ifindex);
++
+ /* Lookup route node. */
+ rn = route_node_lookup (table, (struct prefix *) p);
+ if (! rn)
+@@ -1942,7 +1949,7 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
+ break;
+ }
+ /* Make sure that the route found has the same gateway. */
+- else if (gate == NULL ||
++ else if (gate != NULL &&
+ ((nexthop = rib->nexthop) &&
+ (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
+ IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
+
diff --git a/main/quagga/quagga-0.99.11-link-libcap.patch b/main/quagga/quagga-0.99.11-link-libcap.patch
new file mode 100644
index 0000000000..2c1b868d15
--- /dev/null
+++ b/main/quagga/quagga-0.99.11-link-libcap.patch
@@ -0,0 +1,24 @@
+diff -ur quagga-0.99.11.orig/lib/Makefile.am quagga-0.99.11/lib/Makefile.am
+--- quagga-0.99.11.orig/lib/Makefile.am 2008-09-24 15:22:43.000000000 +0000
++++ quagga-0.99.11/lib/Makefile.am 2008-10-09 20:29:17.000000000 +0000
+@@ -18,7 +18,7 @@
+
+ libzebra_la_DEPENDENCIES = @LIB_REGEX@
+
+-libzebra_la_LIBADD = @LIB_REGEX@
++libzebra_la_LIBADD = @LIB_REGEX@ @LIBCAP@
+
+ pkginclude_HEADERS = \
+ buffer.h checksum.h command.h filter.h getopt.h hash.h \
+diff -ur quagga-0.99.11.orig/zebra/Makefile.am quagga-0.99.11/zebra/Makefile.am
+--- quagga-0.99.11.orig/zebra/Makefile.am 2008-09-05 14:27:26.000000000 +0000
++++ quagga-0.99.11/zebra/Makefile.am 2008-10-09 20:29:17.000000000 +0000
+@@ -39,7 +39,7 @@
+ connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
+ interface.h ipforward.h irdp.h router-id.h kernel_socket.h
+
+-zebra_LDADD = $(otherobj) $(LIBCAP) $(LIB_IPV6) ../lib/libzebra.la
++zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP) $(LIB_IPV6)
+
+ testzebra_LDADD = $(LIBCAP) $(LIB_IPV6) ../lib/libzebra.la
+
diff --git a/main/quagga/quagga.post-install b/main/quagga/quagga.post-install
new file mode 100644
index 0000000000..c1c670d201
--- /dev/null
+++ b/main/quagga/quagga.post-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+chown root:root var/empty
+chown quagga:quagga /var/run/quagga
+exit 0
+
diff --git a/main/quagga/quagga.pre-install b/main/quagga/quagga.pre-install
new file mode 100644
index 0000000000..2a80ab591c
--- /dev/null
+++ b/main/quagga/quagga.pre-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+adduser -H -h /var/empty -s /bin/false -D quagga 2>/dev/null
+mkdir -p var/empty
+chmod 755 /var/empty
+exit 0
+
diff --git a/main/quagga/ripd.initd b/main/quagga/ripd.initd
new file mode 100644
index 0000000000..54458c7238
--- /dev/null
+++ b/main/quagga/ripd.initd
@@ -0,0 +1,34 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/ripd.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+ after firewall
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/ripd.conf ] ; then
+ eerror "You need to create /etc/quagga/ripd.conf first."
+ eerror "An example can be found in /etc/quagga/samples/ripd.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ripd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ripd \
+ -- -d -f /etc/quagga/ripd.conf \
+ --pid_file /var/run/quagga/ripd.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping ripd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/ripd.pid
+ result=$?
+ eend $result
+}
diff --git a/main/quagga/ripngd.initd b/main/quagga/ripngd.initd
new file mode 100644
index 0000000000..00820e5250
--- /dev/null
+++ b/main/quagga/ripngd.initd
@@ -0,0 +1,34 @@
+#!/sbin/runscript
+# Copyright 1999-2003 DataCore GmbH, Amir Guindehi
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/ripngd.init,v 1.1 2005/09/14 11:11:08 mrness Exp $
+
+depend() {
+ need net zebra
+ after firewall
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/ripngd.conf ] ; then
+ eerror "You need to create /etc/quagga/ripngd.conf first."
+ eerror "An example can be found in /etc/quagga/samples/ripngd.conf.sample"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ripngd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ripngd \
+ -- -d -f /etc/quagga/ripngd.conf \
+ --pid_file /var/run/quagga/ripngd.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping ripngd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/ripngd.pid
+ result=$?
+ eend $result
+}
diff --git a/main/quagga/zebra.confd b/main/quagga/zebra.confd
new file mode 100644
index 0000000000..d2deb114e5
--- /dev/null
+++ b/main/quagga/zebra.confd
@@ -0,0 +1,7 @@
+# Additional command-line parameters to run zebra with:
+# -k, --keep_kernel Don't delete old routes which installed by zebra.
+# -A, --vty_addr addr Set vty's bind address
+# -P, --vty_port port Set vty's port number
+# -r, --retain When program terminates, retain added route by zebra.
+# -s, --nl-bufsize Set netlink receive buffer size
+ZEBRA_OPTS=""
diff --git a/main/quagga/zebra.initd b/main/quagga/zebra.initd
new file mode 100644
index 0000000000..2e2f2caa46
--- /dev/null
+++ b/main/quagga/zebra.initd
@@ -0,0 +1,42 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/net-misc/quagga/files/zebra.init,v 1.2 2007/02/25 09:57:18 mrness Exp $
+
+depend() {
+ need net
+ after firewall opennhrp
+}
+
+checkconfig() {
+ if [ ! -e /etc/quagga/zebra.conf ] ; then
+ eerror "You need to create /etc/quagga/zebra.conf first."
+ eerror "An example can be found in /etc/quagga/samples/zebra.conf.sample"
+ return 1
+ fi
+}
+
+cleanup() {
+ ebegin "Cleaning up stale zebra routes..."
+ ip route flush proto zebra
+ eend $?
+}
+
+start() {
+ checkconfig || return 1
+ cleanup
+
+ ebegin "Starting zebra"
+ start-stop-daemon --start --quiet --exec /usr/sbin/zebra \
+ -- -d -f /etc/quagga/zebra.conf ${ZEBRA_OPTS} \
+ --pid_file /var/run/quagga/zebra.pid
+ result=$?
+ eend $result
+}
+
+stop() {
+ ebegin "Stopping zebra"
+ start-stop-daemon --stop --quiet --pidfile /var/run/quagga/zebra.pid
+ result=$?
+ eend $result
+}
diff --git a/main/randrproto/APKBUILD b/main/randrproto/APKBUILD
new file mode 100644
index 0000000000..774a4b4add
--- /dev/null
+++ b/main/randrproto/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=randrproto
+pkgver=1.3.2
+pkgrel=0
+pkgdesc="X11 RandR extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -d -m755 "$pkgdir"/usr/share/licenses/$pkgname
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="597491c0d8055e2a66f11350c4985775 randrproto-1.3.2.tar.bz2"
diff --git a/main/rarian/APKBUILD b/main/rarian/APKBUILD
new file mode 100644
index 0000000000..2818f06a32
--- /dev/null
+++ b/main/rarian/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=rarian
+pkgver=0.8.1
+pkgrel=5
+pkgdesc="Documentation meta-data library, designed as a replacement for Scrollkeeper."
+url="http://rarian.freedesktop.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev"
+depends="bash"
+makedepends="libxslt-dev"
+source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/0.8/$pkgname-$pkgver.tar.bz2
+ user-segfault.patch"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p0 -i "$srcdir"/user-segfault.patch || return 1
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --enable-scrollkeeper-compat \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="75091185e13da67a0ff4279de1757b94 rarian-0.8.1.tar.bz2
+457e9827197009cfa360911fe49a5ad7 user-segfault.patch"
diff --git a/main/rarian/user-segfault.patch b/main/rarian/user-segfault.patch
new file mode 100644
index 0000000000..3311cecdd2
--- /dev/null
+++ b/main/rarian/user-segfault.patch
@@ -0,0 +1,14 @@
+--- util/rarian-sk-get-cl.cpp~ 2008-07-28 19:23:28.000000000 +0200
++++ util/rarian-sk-get-cl.cpp 2008-07-28 19:23:28.000000000 +0200
+@@ -160,6 +160,11 @@
+ {
+ char *filename = NULL;
+ char *user = getenv ("USERNAME");
++
++ if (user == NULL) {
++ user = getenv ("USER");
++ }
++
+ char *basepath = NULL;
+ int i=0;
+ int last = 0;
diff --git a/main/razor/APKBUILD b/main/razor/APKBUILD
new file mode 100644
index 0000000000..a0d951e71f
--- /dev/null
+++ b/main/razor/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=razor
+_realname=razor-agents
+pkgver=2.84
+pkgrel=3
+pkgdesc="Vipul's Razor is a distributed, collaborative spam detection and filtering network"
+url="http://razor.sourceforge.net/"
+arch="all"
+license="Artistic"
+depends="perl perl-digest-sha1 perl-getopt-long perl-uri-escape"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://garr.dl.sourceforge.net/sourceforge/razor/$_realname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="8b9a11a6ce020383c32c45d1530d77c2 razor-agents-2.84.tar.bz2"
diff --git a/main/rdesktop/APKBUILD b/main/rdesktop/APKBUILD
new file mode 100644
index 0000000000..2bfbcab9b0
--- /dev/null
+++ b/main/rdesktop/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=rdesktop
+pkgver=1.7.0
+pkgrel=0
+pkgdesc="rdesktop is used to connect to windows terminal servers"
+url="http://www.rdesktop.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=
+makedepends="libx11-dev libao-dev openssl-dev libsamplerate-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --with-sound=ao
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+md5sums="77fa93b21aa38837a85e81c00e757228 rdesktop-1.7.0.tar.gz"
diff --git a/main/rdiff-backup/APKBUILD b/main/rdiff-backup/APKBUILD
new file mode 100644
index 0000000000..13d6dfd939
--- /dev/null
+++ b/main/rdiff-backup/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Jeremy Thomerson <jeremy@thomersonfamily.com>
+# Maintainer: Jeremy Thomerson <jeremy@thomersonfamily.com>
+pkgname=rdiff-backup
+pkgver=1.2.8
+pkgrel=1
+pkgdesc="A backup utility that maintains extra reverse diffs so that files can be restored from previous backups."
+url="http://www.gnu.org/savannah-checkouts/non-gnu/rdiff-backup/"
+arch="all"
+license="GPL"
+depends="python"
+makedepends="librsync-dev python-dev"
+subpackages="$pkgname-doc"
+source="http://savannah.nongnu.org/download/rdiff-backup/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ python setup.py build || return 1
+}
+
+package() {
+ cd "$_builddir"
+ python setup.py install --prefix=/usr --root="$pkgdir" || return 1
+}
+
+md5sums="1a94dc537fcf74d6a3a80bd27808e77b rdiff-backup-1.2.8.tar.gz"
diff --git a/main/re2c/APKBUILD b/main/re2c/APKBUILD
new file mode 100644
index 0000000000..8d994b4373
--- /dev/null
+++ b/main/re2c/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Jeff Bilyk <jbilyk at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=re2c
+pkgver=0.13.5
+pkgrel=0
+pkgdesc="A tool for writing fast and flexible scanners in C from regular expressions"
+url="http://www.re2c.org"
+arch="all"
+license="Public Domain"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # As Gentoo build, fix perms
+ chmod -R u+rw .
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="4a97d8f77ed6d2c76c8bd840a43f5633 re2c-0.13.5.tar.gz"
diff --git a/main/readline/APKBUILD b/main/readline/APKBUILD
new file mode 100644
index 0000000000..7061eecc12
--- /dev/null
+++ b/main/readline/APKBUILD
@@ -0,0 +1,51 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=readline
+pkgver=6.2.001
+_myver=${pkgver%.*}
+_patchver=${pkgver##*.}
+_suff=${_myver%.*}${_myver#*.}
+pkgrel=0
+pkgdesc="GNU readline library"
+url="ftp://ftp.cwru.edu/pub/bash/"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://ftp.gnu.org/gnu/readline/readline-${_myver}.tar.gz
+ "
+
+# generate url's to patches. note: no forks allowed!
+_i=1
+while [ $_i -le $_patchver ]; do
+ source="$source http://ftp.gnu.org/gnu/readline/readline-$_myver-patches/readline$_suff-00$_i"
+ _i=$(( $_i + 1))
+done
+
+_builddir="$srcdir"/$pkgname-$_myver
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/readline$_suff-???; do
+ [ -r "$i" ] || continue
+ msg "Applying ${i##*/}"
+ patch -Np0 -i ${i} || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure \
+ --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+
+ make SHLIB_LIBS=-lncurses || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+
+}
+md5sums="67948acb2ca081f23359d0256e9a271c readline-6.2.tar.gz
+83287d52a482f790dfb30ec0a8746669 readline62-001"
diff --git a/main/recordmydesktop/APKBUILD b/main/recordmydesktop/APKBUILD
new file mode 100644
index 0000000000..6d07961b5e
--- /dev/null
+++ b/main/recordmydesktop/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=recordmydesktop
+pkgver=0.3.8.1
+pkgrel=1
+pkgdesc="Produces a OGG encapsulated Theora/Vorbis recording of your desktop"
+url="http://recordmydesktop.sourceforge.net"
+arch="all"
+license="GPL"
+depends=""
+makedepends="alsa-lib-dev zlib-dev libvorbis-dev libxdamage-dev libxext-dev
+ libtheora-dev libsm-dev"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/recordmydesktop/recordmydesktop-$pkgver.tar.gz
+ shmstr-to-shmproto.patch
+ recordmydesktop-bitrate.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ patch -p0 < $srcdir/shmstr-to-shmproto.patch
+ patch -p1 < $srcdir/recordmydesktop-bitrate.patch
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-jack \
+ || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="6998b165540598965499bd99d8aa0eef recordmydesktop-0.3.8.1.tar.gz
+211a1773f223b3f281520aa1056395e6 shmstr-to-shmproto.patch
+b0794a769efd287e9e8c5fb8c3299b35 recordmydesktop-bitrate.patch"
diff --git a/main/recordmydesktop/recordmydesktop-bitrate.patch b/main/recordmydesktop/recordmydesktop-bitrate.patch
new file mode 100644
index 0000000000..9b014486af
--- /dev/null
+++ b/main/recordmydesktop/recordmydesktop-bitrate.patch
@@ -0,0 +1,50 @@
+diff -ru recordmydesktop-0.3.8.1.old/src/rmd_initialize_data.c recordmydesktop-0.3.8.1/src/rmd_initialize_data.c
+--- recordmydesktop-0.3.8.1.old/src/rmd_initialize_data.c 2009-11-25 10:05:58.708779029 -0500
++++ recordmydesktop-0.3.8.1/src/rmd_initialize_data.c 2009-11-25 09:28:07.629507987 -0500
+@@ -224,7 +224,7 @@
+ args->channels = 1;
+ args->frequency = 22050;
+ args->buffsize = 4096;
+- args->v_bitrate = 45000;
++ args->v_bitrate = 0;
+ args->v_quality = 63;
+ args->s_quality = 10;
+
+diff -ru recordmydesktop-0.3.8.1.old/src/rmd_parseargs.c recordmydesktop-0.3.8.1/src/rmd_parseargs.c
+--- recordmydesktop-0.3.8.1.old/src/rmd_parseargs.c 2009-11-25 10:06:07.409777969 -0500
++++ recordmydesktop-0.3.8.1/src/rmd_parseargs.c 2009-11-25 09:39:32.786757292 -0500
+@@ -104,10 +104,10 @@
+ "Encoding Options\n"
+ "\t--on-the-fly-encoding\tEncode the audio-video data, while recording.\n"
+ "\t--v_quality n\t\tA number from 0 to 63 for"
+- " desired encoded video quality(default 63).\n"
++ " desired encoded video quality(default 63).\n\t (set quality to zero for bitrate controlled usage)\n"
+
+- "\t--v_bitrate n\t\tA number from 45000 to 2000000"
+- " for desired encoded video bitrate(default 45000).\n"
++ "\t--v_bitrate n\t\tA number from 0 to 200000000"
++ " for desired encoded video bitrate(default 0 = not rate controlled).\n"
+
+ "\t--s_quality n\t\tDesired audio quality(-1 to 10).\n\n"
+
+@@ -327,17 +327,17 @@
+ strcmp(argv[i], "-v_bitrate") == 0) {
+ if(i+1<argc){
+ int num=atoi(argv[i+1]);
+- if((num>=45000)&&(num<=2000000))
++ if((num>=0)&&(num<=200000000))
+ arg_return->v_bitrate=num;
+ else{
+ fprintf(stderr,"Argument Usage:"
+- " --v_bitrate n(number 45000-2000000)\n");
++ " --v_bitrate n(number 0-200000000)\n");
+ return FALSE;
+ }
+ }
+ else{
+ fprintf(stderr,"Argument Usage:"
+- " --v_bitrate n(number 45000-2000000)\n");
++ " --v_bitrate n(number 0-200000000)\n");
+ return FALSE;
+ }
+ i++;
diff --git a/main/recordmydesktop/shmstr-to-shmproto.patch b/main/recordmydesktop/shmstr-to-shmproto.patch
new file mode 100644
index 0000000000..6fc446e9a8
--- /dev/null
+++ b/main/recordmydesktop/shmstr-to-shmproto.patch
@@ -0,0 +1,20 @@
+--- src/rmd_getzpixmap.c 2008-12-13 17:04:10.000000000 +0100
++++ src/rmd_getzpixmap.c 2009-11-11 11:30:18.000000000 +0100
+@@ -32,7 +32,7 @@
+
+ #include <X11/Xlib.h>
+ #include <X11/Xlibint.h>
+-#include <X11/extensions/shmstr.h>
++#include <X11/extensions/shmproto.h>
+ #include <X11/extensions/XShm.h>
+
+
+--- src/rmd_update_image.c 2008-12-13 17:20:49.000000000 +0100
++++ src/rmd_update_image.c 2009-11-11 11:30:34.000000000 +0100
+@@ -32,7 +32,7 @@
+ #include "rmd_types.h"
+
+ #include <X11/Xlibint.h>
+-#include <X11/extensions/shmstr.h>
++#include <X11/extensions/shmproto.h>
+ #include <X11/extensions/XShm.h>
diff --git a/main/recordproto/APKBUILD b/main/recordproto/APKBUILD
new file mode 100644
index 0000000000..f978ea0456
--- /dev/null
+++ b/main/recordproto/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=recordproto
+pkgver=1.14.1
+pkgrel=0
+pkgdesc="X11 Record extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+md5sums="24541a30b399213def35f48efd926c63 recordproto-1.14.1.tar.bz2"
diff --git a/main/redmine/APKBUILD b/main/redmine/APKBUILD
new file mode 100644
index 0000000000..b3bd5a13f5
--- /dev/null
+++ b/main/redmine/APKBUILD
@@ -0,0 +1,85 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=redmine
+pkgver=1.2.0
+pkgrel=2
+pkgdesc="Project management web application written in Ruby"
+url="http://redmine.org"
+arch="noarch"
+license="GPL2"
+depends="ruby-rails ruby-fcgi ruby-rmagick ruby-i18n ruby-openid
+ lighttpd rubygems"
+depends_dev=
+makedepends="$depends_dev"
+install=""
+subpackages=""
+source="http://rubyforge.org/frs/download.php/74944/redmine-$pkgver.tar.gz
+ additional_environment.rb
+ configuration.yml
+ database.yml
+ lighttpd-virtual.conf"
+_webapps="usr/share/webapps"
+
+_builddir="$srcdir"/redmine-$pkgver
+
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ #nothing to do here
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir/$_webapps/$pkgname" \
+ "$pkgdir"/var/log \
+ "$pkgdir"/etc/lighttpd \
+ "$pkgdir"/var/www/localhost/htdocs
+ # move app to webapps dir
+ mv * "$pkgdir/$_webapps/$pkgname"
+ # install default config to /etc/redmine
+ install -m644 -D "$srcdir"/database.yml \
+ "$pkgdir"/etc/redmine/database.yml
+ install -m644 -D "$srcdir"/configuration.yml \
+ "$pkgdir"/etc/redmine/configuration.yml
+ install -m644 -D "$srcdir"/additional_environment.rb \
+ "$pkgdir"/etc/redmine/additional_environment.rb
+ # we use fcgi by default
+ cd "$pkgdir/$_webapps/$pkgname"/public
+ ln -s dispatch.fcgi.example dispatch.fcgi
+ cd "$pkgdir/$_webapps/$pkgname"/config
+ # link config to webapps dir
+ ln -s /etc/redmine/database.yml
+ ln -s /etc/redmine/configuration.yml
+ ln -s /etc/redmine/additional_environment.rb
+ # move redmine log to /var/log
+ cd "$pkgdir/$_webapps/$pkgname"
+ mv log "$pkgdir"/var/log/$pkgname
+ # symlink logs to var log
+ ln -s /var/log/redmine log
+ # symlink redmine to htdocs dir
+ ln -s "/$_webapps/$pkgname" \
+ "$pkgdir"/var/www/localhost/htdocs/"$pkgname"
+ # example lighttpd config for redmine virtual hosting
+ cp "$srcdir"/lighttpd-virtual.conf \
+ "$pkgdir"/etc/lighttpd/redmine-virtual.conf
+ # set correct permissions
+ chown -R lighttpd:lighttpd \
+ "$pkgdir/$_webapps/$pkgname" \
+ "$pkgdir"/var/log/"$pkgname" \
+ "$pkgdir"/etc/"$pkgname"
+}
+
+md5sums="9d9809a6137c75f754a7fb6c0acc1d6c redmine-1.2.0.tar.gz
+b9ca61be7418969188c74c110e3fe3a5 additional_environment.rb
+69243d1b5b9b111da631c7034d51ba71 configuration.yml
+4c4b10aadbc229ea75f309ff1fafcd7a database.yml
+f43ad7e5875b46b723c69b3a9b5e52f2 lighttpd-virtual.conf"
diff --git a/main/redmine/additional_environment.rb b/main/redmine/additional_environment.rb
new file mode 100644
index 0000000000..0d37f579d6
--- /dev/null
+++ b/main/redmine/additional_environment.rb
@@ -0,0 +1,16 @@
+# Copy this file to additional_environment.rb and add any statements
+# that need to be passed to the Rails::Initializer. `config` is
+# available in this context.
+#
+# Example:
+#
+# config.log_level = :debug
+# config.gem "example_plugin", :lib => false
+# config.gem "timesheet_plugin", :lib => false, :version => '0.5.0'
+# config.gem "aws-s3", :lib => "aws/s3"
+# ...
+#
+
+config.logger = Logger.new(config.log_path, 2, 1000000)
+config.logger.level = Logger::WARN
+
diff --git a/main/redmine/configuration.yml b/main/redmine/configuration.yml
new file mode 100644
index 0000000000..a729c60c7d
--- /dev/null
+++ b/main/redmine/configuration.yml
@@ -0,0 +1,147 @@
+# = Redmine configuration file
+#
+# Each environment has it's own configuration options. If you are only
+# running in production, only the production block needs to be configured.
+# Environment specific configuration options override the default ones.
+#
+# Note that this file needs to be a valid YAML file.
+#
+# == Outgoing email settings (email_delivery setting)
+#
+# === Common configurations
+#
+# ==== Sendmail command
+#
+# production:
+# email_delivery:
+# delivery_method: :sendmail
+#
+# ==== Simple SMTP server at localhost
+#
+# production:
+# email_delivery:
+# delivery_method: :smtp
+# smtp_settings:
+# address: "localhost"
+# port: 25
+#
+# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
+#
+# production:
+# email_delivery:
+# delivery_method: :smtp
+# smtp_settings:
+# address: "example.com"
+# port: 25
+# authentication: :login
+# domain: 'foo.com'
+# user_name: 'myaccount'
+# password: 'password'
+#
+# ==== SMTP server at example.com using PLAIN authentication
+#
+# production:
+# email_delivery:
+# delivery_method: :smtp
+# smtp_settings:
+# address: "example.com"
+# port: 25
+# authentication: :plain
+# domain: 'example.com'
+# user_name: 'myaccount'
+# password: 'password'
+#
+# ==== SMTP server at using TLS (GMail)
+#
+# This requires some additional configuration. See the article at:
+# http://redmineblog.com/articles/setup-redmine-to-send-email-using-gmail/
+#
+# production:
+# email_delivery:
+# delivery_method: :smtp
+# smtp_settings:
+# tls: true
+# address: "smtp.gmail.com"
+# port: 587
+# domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
+# authentication: :plain
+# user_name: "your_email@gmail.com"
+# password: "your_password"
+#
+#
+# === More configuration options
+#
+# See the "Configuration options" at the following website for a list of the
+# full options allowed:
+#
+# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
+
+
+# default configuration options for all environments
+default:
+ # Outgoing emails configuration (see examples above)
+ email_delivery:
+ delivery_method: :smtp
+ smtp_settings:
+ address: smtp.example.net
+ port: 25
+ domain: example.net
+ authentication: :login
+ user_name: "redmine@example.net"
+ password: "redmine"
+
+ # Absolute path to the directory where attachments are stored.
+ # The default is the 'files' directory in your Redmine instance.
+ # Your Redmine instance needs to have write permission on this
+ # directory.
+ # Examples:
+ # attachments_storage_path: /var/redmine/files
+ # attachments_storage_path: D:/redmine/files
+ attachments_storage_path:
+
+ # Configuration of the autologin cookie.
+ # autologin_cookie_name: the name of the cookie (default: autologin)
+ # autologin_cookie_path: the cookie path (default: /)
+ # autologin_cookie_secure: true sets the cookie secure flag (default: false)
+ autologin_cookie_name:
+ autologin_cookie_path:
+ autologin_cookie_secure:
+
+ # Configuration of SCM executable command.
+ # Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
+ # On Windows, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
+ # Examples:
+ # scm_subversion_command: svn # (default: svn)
+ # scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg)
+ # scm_git_command: /usr/local/bin/git # (default: git)
+ # scm_cvs_command: cvs # (default: cvs)
+ # scm_bazaar_command: bzr.exe # (default: bzr)
+ # scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs)
+ scm_subversion_command:
+ scm_mercurial_command:
+ scm_git_command:
+ scm_cvs_command:
+ scm_bazaar_command:
+ scm_darcs_command:
+
+ # Key used to encrypt sensitive data in the database (SCM and LDAP passwords).
+ # If you don't want to enable data encryption, just leave it blank.
+ # WARNING: losing/changing this key will make encrypted data unreadable.
+ #
+ # If you want to encrypt existing passwords in your database:
+ # * set the cipher key here in your configuration file
+ # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
+ #
+ # If you have encrypted data and want to change this key, you have to:
+ # * decrypt data using 'rake db:decrypt RAILS_ENV=production' first
+ # * change the cipher key here in your configuration file
+ # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
+ database_cipher_key:
+
+# specific configuration options for production environment
+# that overrides the default ones
+production:
+
+# specific configuration options for development environment
+# that overrides the default ones
+development:
diff --git a/main/redmine/database.yml b/main/redmine/database.yml
new file mode 100644
index 0000000000..eb934bf765
--- /dev/null
+++ b/main/redmine/database.yml
@@ -0,0 +1,10 @@
+# MySQL (default setup).
+
+production:
+ adapter: mysql
+ database: redmine
+ host: localhost
+ username: root
+ password:
+ encoding: utf8
+
diff --git a/main/redmine/lighttpd-virtual.conf b/main/redmine/lighttpd-virtual.conf
new file mode 100644
index 0000000000..be0c684b0c
--- /dev/null
+++ b/main/redmine/lighttpd-virtual.conf
@@ -0,0 +1,26 @@
+## copy this file to /etc/lighttpd to enable virtual hosting
+## make sure you set hostname correctly
+
+server.modules += ( "mod_simple_vhost" , "mod_fastcgi" )
+
+$HTTP["host"] =~ "^www\.example\.org$" {
+ server.document-root = "/var/www/localhost/htdocs/redmine/public/"
+ server.follow-symlink = "enable"
+ server.indexfiles = ( "dispatch.fcgi" )
+ server.error-handler-404 = "/dispatch.fcgi"
+
+ fastcgi.server = (
+ ".fcgi" => (
+ "redmine" => (
+ "bin-path" => "/usr/bin/ruby /var/www/localhost/htdocs/redmine/public/dispatch.fcgi",
+ "socket" => "/tmp/redmine.socket",
+ "min-procs" => 1,
+ "max-procs" => 4,
+ "idle-timeout" => 120,
+ "check-local" => "disable",
+ "bin-environment" => ( "RAILS_ENV" => "production" ),
+ )
+ )
+ )
+}
+
diff --git a/main/reiserfsprogs/APKBUILD b/main/reiserfsprogs/APKBUILD
new file mode 100644
index 0000000000..cb44e8bdbe
--- /dev/null
+++ b/main/reiserfsprogs/APKBUILD
@@ -0,0 +1,37 @@
+# Contributor:
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=reiserfsprogs
+pkgver=3.6.21
+pkgrel=0
+pkgdesc="Reiserfs Utilities"
+url="http://www.namesys.com"
+arch="all"
+license="GPL"
+depends=
+makedepends="e2fsprogs-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://www.kernel.org/pub/linux/utils/fs/reiserfs/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+#prepare() {
+# cd "$_builddir"
+# apply patches here
+#}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="0639cefac8f8150536cfa7531c2aa2d2 reiserfsprogs-3.6.21.tar.bz2"
diff --git a/main/remmina-plugins/APKBUILD b/main/remmina-plugins/APKBUILD
new file mode 100644
index 0000000000..b7a4b0b490
--- /dev/null
+++ b/main/remmina-plugins/APKBUILD
@@ -0,0 +1,37 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=remmina-plugins
+pkgver=0.9.2
+pkgrel=1
+pkgdesc="Remmina plugins"
+url="http://sourceforge.net/projects/remmina/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="perl remmina-dev freerdp-dev libxkbfile-dev gtk+-dev libssh-dev
+ jpeg-dev gnutls-dev"
+install=
+source="http://downloads.sourceforge.net/project/remmina/${pkgver%.*}/remmina-plugins-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build ()
+{
+ cd $srcdir/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --enable-ssh \
+ --enable-rdp \
+ --enable-vnc \
+ --enable-xdmcp \
+ --enable-nx \
+ --disable-telepathy \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ # remove *.a and *.la
+ rm "$pkgdir"/usr/lib/remmina/plugins/*.*a
+}
+
+md5sums="6f6b7cb18f7604f3f17eeda5173ede6a remmina-plugins-0.9.2.tar.gz"
diff --git a/main/remmina-xfce/APKBUILD b/main/remmina-xfce/APKBUILD
new file mode 100644
index 0000000000..a57ac5678c
--- /dev/null
+++ b/main/remmina-xfce/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=remmina-xfce
+pkgver=0.8.1
+pkgrel=2
+pkgdesc="Remmina XFCE panel applet"
+url="http://sourceforge.net/projects/remmina/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="remmina-dev libxfce4util-dev xfce4-panel-dev"
+install=
+source="http://downloads.sourceforge.net/project/remmina/${pkgver%.*}/remmina-xfce-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build ()
+{
+ cd $srcdir/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ # remove *.a and *.la
+ rm "$pkgdir"/usr/lib/xfce4/panel-plugins/*.*a
+}
+
+md5sums="7b95ed26f6518d26166904ef63d1b936 remmina-xfce-0.8.1.tar.gz"
diff --git a/main/remmina/APKBUILD b/main/remmina/APKBUILD
new file mode 100644
index 0000000000..c48edb475b
--- /dev/null
+++ b/main/remmina/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=remmina
+pkgver=0.9.3
+pkgrel=0
+pkgdesc="Remmina is a remote desktop client written in GTK+"
+url="http://remmina.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+-dev intltool zlib-dev jpeg-dev gnutls-dev vte-dev
+ libgcrypt-dev "
+install=
+subpackages="$pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="c87004a70ec62acbae732e8d47f71ba7 remmina-0.9.3.tar.gz"
diff --git a/main/renderproto/APKBUILD b/main/renderproto/APKBUILD
new file mode 100644
index 0000000000..03a3c186b6
--- /dev/null
+++ b/main/renderproto/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=renderproto
+pkgver=0.11.1
+pkgrel=1
+pkgdesc="X11 Render extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+subpackages="$pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="a914ccc1de66ddeb4b611c6b0686e274 renderproto-0.11.1.tar.bz2"
diff --git a/main/resourceproto/APKBUILD b/main/resourceproto/APKBUILD
new file mode 100644
index 0000000000..8061f59f26
--- /dev/null
+++ b/main/resourceproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=resourceproto
+pkgver=1.2.0
+pkgrel=0
+pkgdesc="X11 Resource extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org//releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="cfdb57dae221b71b2703f8e2980eaaf4 resourceproto-1.2.0.tar.bz2"
diff --git a/main/rgb/APKBUILD b/main/rgb/APKBUILD
new file mode 100644
index 0000000000..5d1cc8b828
--- /dev/null
+++ b/main/rgb/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=rgb
+pkgver=1.0.3
+pkgrel=2
+pkgdesc="X.org utility to display an rgb color-name database"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig xproto"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="44ea16cc3104de6401bc74035f642357 rgb-1.0.3.tar.bz2"
diff --git a/main/ristretto/APKBUILD b/main/ristretto/APKBUILD
new file mode 100644
index 0000000000..020137e62a
--- /dev/null
+++ b/main/ristretto/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ristretto
+pkgver=0.0.93
+pkgrel=0
+pkgdesc="Ristretto is a image viewer for Xfce"
+url="http://goodies.xfce.org/projects/applications/ristretto"
+arch="all"
+license="GPL-2"
+depends="desktop-file-utils hicolor-icon-theme"
+makedepends="libxfce4ui-dev dbus-glib-dev libexif-dev thunar-dev"
+install=
+source="http://archive.xfce.org/src/apps/ristretto/0.0/ristretto-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --enable-xfce-desktop \
+ --disable-static || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="74dcdf0fcbf7039852b817732a91fb6c ristretto-0.0.93.tar.bz2"
diff --git a/main/roundcubemail/APKBUILD b/main/roundcubemail/APKBUILD
new file mode 100644
index 0000000000..77ca2dd808
--- /dev/null
+++ b/main/roundcubemail/APKBUILD
@@ -0,0 +1,67 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=roundcubemail
+pkgver=0.5.3
+pkgrel=0
+pkgdesc="A PHP web-based mail client"
+url="http://www.roundcube.net"
+arch="noarch"
+license="GPL"
+install="$pkgname.post-upgrade"
+depends="php php-imap php-xml php-json php-dom"
+makedepends=""
+subpackages="$pkgname-installer"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.gz
+ fix-dirs.patch"
+
+_src="$srcdir"/roundcubemail-$pkgver
+
+prepare() {
+ cd "$_src"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ # fix permissions
+ find . -type f -print | xargs chmod a-x
+ # remove .htaccess
+ find . -name \.htaccess -print | xargs rm -f
+
+ # fixup paths to use the right paths
+ sed -i -e 's|temp/|/tmp/|' \
+ -e 's|config/|/etc/roundcube/|' \
+ -e 's|logs/|/var/log/roundcube/|' \
+ config/main.inc.php.dist || return 1
+
+ # cleanup
+ sed -i 's/\r//' SQL/mssql.initial.sql
+ rm -rf logs temp
+}
+
+build() {
+ return 0
+}
+
+package() {
+ _instdir="$pkgdir"/usr/share/webapps/roundcube
+ mkdir -p "${_instdir}"
+ cd "${_instdir}"
+ cp -rp "$srcdir"/roundcubemail-$pkgver/* .
+ # install config in /etc/roundcube so config files are not overwritten
+ # on upgrades
+ mkdir -p "$pkgdir"/etc/
+ mv config "$pkgdir"/etc/roundcube
+
+ install -d "$pkgdir"/var/log/roundcube
+}
+
+installer() {
+ pkgdesc="Roundcubemail installer script"
+ mkdir -p "$subpkgdir"/usr/share/webapps/roundcube
+ mv "$pkgdir"/usr/share/webapps/roundcube/installer \
+ "$subpkgdir"/usr/share/webapps/roundcube
+}
+
+md5sums="1575517c7d264439eb9f236e5e3e78d7 roundcubemail-0.5.3.tar.gz
+db71db7b5489ac2d0e8d80a0a8b993e0 fix-dirs.patch"
diff --git a/main/roundcubemail/fix-dirs.patch b/main/roundcubemail/fix-dirs.patch
new file mode 100644
index 0000000000..e6b8ea9954
--- /dev/null
+++ b/main/roundcubemail/fix-dirs.patch
@@ -0,0 +1,50 @@
+diff --git a/program/include/iniset.php b/program/include/iniset.php
+index 92a2d90..5f7c0ad 100755
+--- a/program/include/iniset.php
++++ b/program/include/iniset.php
+@@ -46,7 +46,7 @@ if (!defined('INSTALL_PATH')) {
+ }
+
+ if (!defined('RCMAIL_CONFIG_DIR')) {
+- define('RCMAIL_CONFIG_DIR', INSTALL_PATH . 'config');
++ define('RCMAIL_CONFIG_DIR', '/etc/roundcube');
+ }
+
+ // make sure path_separator is defined
+diff --git a/program/include/main.inc b/program/include/main.inc
+index 9206a62..85f9459 100644
+--- a/program/include/main.inc
++++ b/program/include/main.inc
+@@ -1178,7 +1178,7 @@ function write_log($name, $line)
+
+ // log_driver == 'file' is assumed here
+ if (empty($CONFIG['log_dir']))
+- $CONFIG['log_dir'] = INSTALL_PATH.'logs';
++ $CONFIG['log_dir'] = '/var/log/roundcube';
+
+ // try to open specific log file for writing
+ $logfile = $CONFIG['log_dir'].'/'.$name;
+diff --git a/program/include/rcube_config.php b/program/include/rcube_config.php
+index 19e1be3..d362487 100644
+--- a/program/include/rcube_config.php
++++ b/program/include/rcube_config.php
+@@ -66,7 +66,7 @@ class rcube_config
+
+ // fix paths
+ $this->prop['log_dir'] = $this->prop['log_dir'] ? realpath(unslashify($this->prop['log_dir'])) : INSTALL_PATH . 'logs';
+- $this->prop['temp_dir'] = $this->prop['temp_dir'] ? realpath(unslashify($this->prop['temp_dir'])) : INSTALL_PATH . 'temp';
++ $this->prop['temp_dir'] = $this->prop['temp_dir'] ? realpath(unslashify($this->prop['temp_dir'])) : '/tmp';
+
+ // fix default imap folders encoding
+ foreach (array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox') as $folder)
+--- ./installer/index.php.orig
++++ ./installer/index.php
+@@ -4,7 +4,7 @@
+ ini_set('display_errors', 1);
+
+ define('INSTALL_PATH', realpath(dirname(__FILE__) . '/../').'/');
+-define('RCMAIL_CONFIG_DIR', INSTALL_PATH . 'config');
++define('RCMAIL_CONFIG_DIR', '/etc/roundcube');
+
+ $include_path = INSTALL_PATH . 'program/lib' . PATH_SEPARATOR;
+ $include_path .= INSTALL_PATH . 'program' . PATH_SEPARATOR;
diff --git a/main/roundcubemail/roundcubemail.post-upgrade b/main/roundcubemail/roundcubemail.post-upgrade
new file mode 100644
index 0000000000..2f49d6cc7a
--- /dev/null
+++ b/main/roundcubemail/roundcubemail.post-upgrade
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# move existing config in /usr/share/webapps/roundcube/config to
+# /etc/roundcube and create a symlink in /usr/share/webapps/roundcube that
+# points to /etc/roundcube dir.
+
+# if we did this in pre-upgrade, apk would delete
+# /usr/share/webapps/roundcube/config/* which would actually point to
+# /etc/roundcube due to symlink. oups!
+
+if [ -L /usr/share/webapps/roundcube/config.apk-new ] && \
+ [ -d /usr/share/webapps/roundcube/config ]; then
+ mkdir -p /etc/roundcube
+ # if configs were unmodified they are deleted by apk
+ # so we check if they exist before trying to move anything
+ for i in /usr/share/webapps/roundcube/config/* \
+ /usr/share/webapps/roundcube/config/.[A-z]*; do
+ if [ -f "$i" ]; then
+ mv "$i" /etc/roundcube
+ fi
+ done
+ rmdir /usr/share/webapps/roundcube/config
+ mv /usr/share/webapps/roundcube/config.apk-new \
+ /usr/share/webapps/roundcube/config
+fi
+
+# logs and temp moved
+if [ -d /usr/share/webapps/roundcube/logs ]; then
+ mv /usr/share/webapps/roundcube/logs/* \
+ /var/log/roundcube/
+
+ # clone permissions
+ chown $(stat -c %U:%G /usr/share/webapps/roundcube/logs) \
+ /var/log/roundcube
+fi
+
+if [ -d /usr/share/webapps/roundcube/temp ]; then
+ mv /usr/share/webapps/roundcube/temp/* \
+ /tmp/
+fi
+
+# display info about upgrade
+echo "*" >&2
+echo "* Please remember to manually update your database schema:" >&2
+echo "*" >&2
+ls /usr/share/webapps/roundcube/SQL/*.up*.* >&2
+exit 0
diff --git a/main/roundcubemail/roundcubemail.pre-upgrade b/main/roundcubemail/roundcubemail.pre-upgrade
new file mode 100644
index 0000000000..1d44a87034
--- /dev/null
+++ b/main/roundcubemail/roundcubemail.pre-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ -d /usr/share/webapps/roundcube/config ]; then
+ mkdir -p /etc
+ mv /usr/share/webapps/roundcube/config /etc/roundcube
+fi
+
diff --git a/main/rpcbind/0001-uclibc-nss.patch b/main/rpcbind/0001-uclibc-nss.patch
new file mode 100644
index 0000000000..3685c03b66
--- /dev/null
+++ b/main/rpcbind/0001-uclibc-nss.patch
@@ -0,0 +1,28 @@
+From b8f0d7b7318ba344c25785d6f5cf3f8de98012d4 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue, 2 Feb 2010 09:36:03 +0000
+Subject: [PATCH 1/2] uclibc-nss
+
+---
+ src/rpcbind.c | 4 ++++
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+
+diff --git a/src/rpcbind.c b/src/rpcbind.c
+index 525ffba..1fe1a60 100644
+--- a/src/rpcbind.c
++++ b/src/rpcbind.c
+@@ -67,7 +67,11 @@
+ #include <pwd.h>
+ #include <string.h>
+ #include <errno.h>
++#if defined(__UCLIBC__)
++#define __nss_configure_lookup(x,y)
++#else
+ #include <nss.h>
++#endif
+ #include "config.h"
+ #include "rpcbind.h"
+
+--
+1.6.6.1
+
diff --git a/main/rpcbind/0002-uclibc-rpcsvc-defines.patch b/main/rpcbind/0002-uclibc-rpcsvc-defines.patch
new file mode 100644
index 0000000000..e394966f5c
--- /dev/null
+++ b/main/rpcbind/0002-uclibc-rpcsvc-defines.patch
@@ -0,0 +1,58 @@
+From 077add040c2e30d3ac507362f4afe350f47be027 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue, 2 Feb 2010 09:47:57 +0000
+Subject: [PATCH 2/2] uclibc-rpcsvc-defines
+
+---
+ src/security.c | 28 ++++++++++++++++++++++++++++
+ 1 files changed, 28 insertions(+), 0 deletions(-)
+
+diff --git a/src/security.c b/src/security.c
+index 0edeac6..e9fed55 100644
+--- a/src/security.c
++++ b/src/security.c
+@@ -20,6 +20,32 @@
+ /*
+ * XXX for special case checks in check_callit.
+ */
++#if defined(__UCLIBC__)
++
++#define MOUNTPROC_MNT 1
++#define MOUNTPROC_UMNT 3
++
++#define NFS_PROGRAM 100003
++#define YPPROG 100004
++#define MOUNTPROG 100005
++#define YPBINDPROG 100007
++#define YPPASSWDPROG 100009
++#define RQUOTAPROG 100011
++
++#define YPPROC_NULL 0
++#define YPPROC_DOMAIN 1
++#define YPPROC_DOMAIN_NONACK 2
++#define YPPROC_MATCH 3
++#define YPPROC_FIRST 4
++#define YPPROC_NEXT 5
++#define YPPROC_XFR 6
++#define YPPROC_CLEAR 7
++#define YPPROC_ALL 8
++
++#define YPBINDPROC_SETDOM 2
++
++#else
++
+ #include <rpcsvc/mount.h>
+ #include <rpcsvc/rquota.h>
+ #include <rpcsvc/nfs_prot.h>
+@@ -27,6 +53,8 @@
+ #include <rpcsvc/ypclnt.h>
+ #include <rpcsvc/yppasswd.h>
+
++#endif
++
+ #include "rpcbind.h"
+
+ #ifdef LIBWRAP
+--
+1.6.6.1
+
diff --git a/main/rpcbind/APKBUILD b/main/rpcbind/APKBUILD
new file mode 100644
index 0000000000..57e4d2031c
--- /dev/null
+++ b/main/rpcbind/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=rpcbind
+pkgver=0.2.0
+pkgrel=1
+pkgdesc="portmap replacement which supports RPC over various protocols"
+url="http://rpcbind.sourceforge.net"
+arch="all"
+license="custom"
+depends=
+makedepends="libtirpc-dev"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2
+ 0001-uclibc-nss.patch
+ 0002-uclibc-rpcsvc-defines.patch
+ rpcbind.initd
+ rpcbind.confd"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ patch -p1 -i "$i" || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr --bindir=/sbin
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm755 "$srcdir"/rpcbind.initd "$pkgdir"/etc/init.d/rpcbind
+ install -Dm644 "$srcdir"/rpcbind.confd "$pkgdir"/etc/conf.d/rpcbind
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/rpcbind/COPYING
+}
+md5sums="1a77ddb1aaea8099ab19c351eeb26316 rpcbind-0.2.0.tar.bz2
+6d9718d8bdab633ef7cf83225aaed367 0001-uclibc-nss.patch
+944234c5ef6902d25bd6dfc95f979ed6 0002-uclibc-rpcsvc-defines.patch
+381a2722c69b4597af532381f1ffeae0 rpcbind.initd
+1ad5c8dcf432c8f23ba740f4c32a7c60 rpcbind.confd"
diff --git a/main/rpcbind/rpcbind.confd b/main/rpcbind/rpcbind.confd
new file mode 100644
index 0000000000..ddc09172d1
--- /dev/null
+++ b/main/rpcbind/rpcbind.confd
@@ -0,0 +1,4 @@
+# /etc/conf.d/rpcbind
+
+# Options for `rpcbind`.
+#RPCBIND_OPTS="-l"
diff --git a/main/rpcbind/rpcbind.initd b/main/rpcbind/rpcbind.initd
new file mode 100644
index 0000000000..897e8e5a88
--- /dev/null
+++ b/main/rpcbind/rpcbind.initd
@@ -0,0 +1,25 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-nds/rpcbind/files/rpcbind.initd,v 1.1 2007/12/29 09:13:55 vapier Exp $
+
+depend() {
+ use net
+ before inetd xinetd
+ after firewall
+ provide portmap
+}
+
+start() {
+ ebegin "Starting rpcbind"
+ start-stop-daemon --start --quiet --exec /sbin/rpcbind \
+ -- ${RPCBIND_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping rpcbind"
+ start-stop-daemon --stop --quiet --exec /sbin/rpcbind
+ eend $?
+}
+
diff --git a/main/rrdtool/APKBUILD b/main/rrdtool/APKBUILD
new file mode 100644
index 0000000000..dd32d56808
--- /dev/null
+++ b/main/rrdtool/APKBUILD
@@ -0,0 +1,52 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=rrdtool
+pkgver=1.2.30
+pkgrel=8
+pkgdesc="Data logging and graphing application"
+url="http://www.rrdtool.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="libart-lgpl-dev libpng-dev freetype-dev perl-dev"
+subpackages="$pkgname-dev $pkgname-doc perl-rrd:perl_rrd"
+source="http://oss.oetiker.ch/$pkgname/pub/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-tcl \
+ --disable-python \
+ --disable-ruby \
+ --enable-rrdcgi \
+ --enable-perl-site-install \
+ --with-perl-options="INSTALLDIRS=vendor" \
+ || return 1
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ export INSTALLDIRS=vendor
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '.packlist' -delete
+ find "$pkgdir" -name 'perllocal.pod' -delete
+ find "$pkgdir" -name '*.la' -delete
+}
+
+dev() {
+ default_dev
+ mkdir -p "$subpkgdir"/usr/share/$pkgname
+ mv "$pkgdir"/usr/share/$pkgname/examples "$subpkgdir"/usr/share/$pkgname/
+}
+
+perl_rrd() {
+ pkgdesc="Perl interface for rrdtool"
+ mkdir -p "$subpkgdir"/usr/lib \
+ "$pkgdir"/usr/share
+ mv "$pkgdir"/usr/lib/perl* "$subpkgdir"/usr/lib/
+ mv "$pkgdir"/usr/share/perl* "$subpkgdir"/usr/share/
+}
+
+md5sums="19b24f7184a8dbf7b48c1bbb565ad9fb rrdtool-1.2.30.tar.gz"
diff --git a/main/rsync/APKBUILD b/main/rsync/APKBUILD
new file mode 100644
index 0000000000..05e1acedcf
--- /dev/null
+++ b/main/rsync/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=rsync
+pkgver=3.0.8
+pkgrel=0
+pkgdesc="A file transfer program to keep remote files in sync"
+url="http://samba.anu.edu.au/rsync/"
+arch="all"
+license="GPL3"
+depends=
+makedepends="perl"
+source="http://$pkgname.samba.org/ftp/$pkgname/$pkgname-$pkgver.tar.gz
+ rsyncd.initd
+ rsyncd.confd
+ rsyncd.conf
+ rsyncd.logrotate
+ "
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./prepare-source || return 1
+ ./configure --prefix=/usr \
+ --with-included-popt \
+ --disable-acl-support \
+ --disable-xattr-support || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m 755 ../rsyncd.initd ${pkgdir}/etc/init.d/rsyncd
+ install -D -m 644 ../rsyncd.conf ${pkgdir}/etc/rsyncd.conf
+ install -D -m 644 ../rsyncd.confd ${pkgdir}/etc/conf.d/rsyncd
+ install -D -m 644 ../rsyncd.logrotate ${pkgdir}/etc/logrotate.d/rsyncd
+}
+
+md5sums="0ee8346ce16bdfe4c88a236e94c752b4 rsync-3.0.8.tar.gz
+8c525f7c4222f90b3f01bb7f6a2684ab rsyncd.initd
+e5e62e8cef29e09c22e8ba8152ec1751 rsyncd.confd
+a99211a14af1766ba849035241cd5bb2 rsyncd.conf
+169cafc6907a4c3787bb0462e9d6a5c2 rsyncd.logrotate"
diff --git a/main/rsync/rsyncd.conf b/main/rsync/rsyncd.conf
new file mode 100644
index 0000000000..b6dd5994d4
--- /dev/null
+++ b/main/rsync/rsyncd.conf
@@ -0,0 +1,10 @@
+# /etc/rsyncd.conf
+
+# Minimal configuration file for rsync daemon
+# See rsync(1) and rsyncd.conf(5) man pages for help
+
+# This line is required by the /etc/init.d/rsyncd script
+pid file = /var/run/rsyncd.pid
+use chroot = yes
+read only = yes
+
diff --git a/main/rsync/rsyncd.confd b/main/rsync/rsyncd.confd
new file mode 100644
index 0000000000..c3d897ed2f
--- /dev/null
+++ b/main/rsync/rsyncd.confd
@@ -0,0 +1,5 @@
+# /etc/conf.d/rsyncd: config file for /etc/init.d/rsyncd
+
+# see man pages for rsync or run `rsync --help`
+# for valid cmdline options
+#RSYNC_OPTS=""
diff --git a/main/rsync/rsyncd.initd b/main/rsync/rsyncd.initd
new file mode 100644
index 0000000000..13d56733fc
--- /dev/null
+++ b/main/rsync/rsyncd.initd
@@ -0,0 +1,24 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/rsync/files/rsyncd.init.d,v 1.5 2007/02/23 11:33:59 uberlord Exp $
+
+depend() {
+ use net
+ after firewall
+}
+
+start() {
+ ebegin "Starting rsyncd"
+ start-stop-daemon --start --exec /usr/bin/rsync \
+ --pidfile /var/run/rsyncd.pid \
+ -- --daemon ${RSYNC_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping rsyncd"
+ start-stop-daemon --stop --exec /usr/bin/rsync \
+ --pidfile /var/run/rsyncd.pid
+ eend $?
+}
diff --git a/main/rsync/rsyncd.logrotate b/main/rsync/rsyncd.logrotate
new file mode 100644
index 0000000000..34bcf72d21
--- /dev/null
+++ b/main/rsync/rsyncd.logrotate
@@ -0,0 +1,9 @@
+/var/log/rsync.log {
+ compress
+ maxage 365
+ rotate 7
+ size=+1024k
+ notifempty
+ missingok
+ copytruncate
+}
diff --git a/main/rt4/APKBUILD b/main/rt4/APKBUILD
new file mode 100644
index 0000000000..8645d2916e
--- /dev/null
+++ b/main/rt4/APKBUILD
@@ -0,0 +1,127 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=rt4
+pkgver=4.0.1
+pkgrel=0
+pkgdesc="Request Tracker - issue and bug tracker"
+url="http://www.bestpractical.com/rt"
+arch="noarch"
+license="GPLv2+"
+depends="perl
+ perl-term-readkey
+ perl-cache-simple-timedexpiry
+ perl-class-accessor
+ perl-dbi
+ perl-dbd-pg
+ perl-dbd-mysql
+ perl-devel-globaldestruction
+ perl-devel-stacktrace
+ perl-digest-sha1
+ perl-email-address
+ perl-getopt-long
+ perl-locale-maketext-fuzzy
+ perl-locale-maketext-lexicon
+ perl-log-dispatch
+ perl-mime-tools
+ perl-net-cidr
+ perl-regexp-common-net-cidr
+ perl-sub-exporter
+ perl-text-password-pronounceable
+ perl-text-template
+ perl-text-wrapper
+ perl-time-hires
+ perl-time-modules
+ perl-tree-simple
+ perl-universal-require
+ perl-xml-rss
+ perl-text-wikiformat
+ perl-convert-color
+ perl-data-ical
+ perl-mime-types
+ perl-html-format
+ perl-html-rewriteattributes
+ perl-html-tree
+ perl-html-mason
+ perl-javascript-minifier
+ perl-cgi-psgi
+ perl-cgi-emulate-psgi
+ perl-html-mason-psgihandler
+ perl-apache-session
+ perl-starlet
+ perl-html-parser
+ perl-file-sharedir
+ perl-module-versions-report
+ perl-list-moreutils
+ perl-css-squish
+ perl-dbix-searchbuilder
+ perl-regexp-ipv6
+ perl-text-quoted
+ perl-html-scrubber
+ perl-html-quoted
+ perl-datetime-locale
+ perl-fcgi
+ perl-fcgi-procmanager
+ perl-datetime
+ perl-json
+ perl-ipc-run3
+ perl-plack
+ "
+
+makedepends="$depends"
+install=""
+subpackages=""
+source="http://www.bestpractical.com/pub/rt/release/rt-$pkgver.tar.gz"
+
+_builddir="$srcdir"/rt-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ cat <<'EOF' >> config.layout
+# Alpione directory layout.
+<Layout Alpine>
+ prefix: /usr
+ exec_prefix: ${prefix}
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/sbin
+ sysconfdir: /etc/rt4
+ mandir: ${prefix}/share/man
+ plugindir: ${prefix}/lib/rt4/plugins
+ libdir: ${prefix}/lib/rt4/
+ datadir: ${prefix}/share/rt4
+ htmldir: ${datadir}/html
+ fontdir: ${datadir}/fonts
+ lexdir: ${datadir}/po
+ manualdir: ${datadir}/doc
+ localstatedir: /var
+ logfiledir: ${localstatedir}/log
+ masonstatedir: ${localstatedir}/cache/mason_data
+ sessionstatedir: ${localstatedir}/cache/session_data
+ customdir: ${prefix}/local
+ custometcdir: ${customdir}/etc
+ customhtmldir: ${customdir}/html
+ customlexdir: ${customdir}/po
+ customlibdir: ${customdir}/lib
+ customplugindir: ${customdir}/plugins
+</Layout>
+EOF
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --enable-layout=Alpine \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="bde89fbdadf7b709fb13f32638848b9d rt-4.0.1.tar.gz"
diff --git a/main/rtmpdump/APKBUILD b/main/rtmpdump/APKBUILD
new file mode 100644
index 0000000000..70a0bc2d7f
--- /dev/null
+++ b/main/rtmpdump/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Carlo Landmetere
+# Maintainer:
+pkgname=rtmpdump
+pkgver=2.3
+pkgrel=1
+pkgdesc="A tool to download rtmp:// and rtmpe:// streams"
+url="http://rtmpdump.mplayerhq.hu/"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://mirrors.kernel.org/gentoo/distfiles/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ sed -i 's/^install_so.0:.*/& install_base/' librtmp/Makefile
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make prefix=/usr MANDIR="$pkgdir/usr/share/man" DESTDIR="$pkgdir" install
+
+}
+
+md5sums="eb961f31cd55f0acf5aad1a7b900ef59 rtmpdump-2.3.tgz"
diff --git a/main/rtpproxy/APKBUILD b/main/rtpproxy/APKBUILD
new file mode 100644
index 0000000000..30629c0a53
--- /dev/null
+++ b/main/rtpproxy/APKBUILD
@@ -0,0 +1,48 @@
+# Contributor: Jeff Bilyk <jbilyk@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=rtpproxy
+pkgver=1.2.1
+pkgrel=1
+pkgdesc="RTP proxy"
+url="http://www.rtpproxy.org"
+arch="all"
+license="BSD"
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install="$pkgname.pre-install"
+subpackages="$pkgname-doc"
+source="http://b2bua.org/chrome/site/$pkgname-$pkgver.tar.gz
+ rtpproxy.confd
+ rtpproxy.initd"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="b0b5d6cdce3f17cdbbac473c11a2d0e5 rtpproxy-1.2.1.tar.gz
+aee99ab9f380cd0b43754ae658f26c92 rtpproxy.confd
+b0f8894794b3f24af21ed050477851b1 rtpproxy.initd"
diff --git a/main/rtpproxy/rtpproxy.confd b/main/rtpproxy/rtpproxy.confd
new file mode 100644
index 0000000000..cb53e6d7c3
--- /dev/null
+++ b/main/rtpproxy/rtpproxy.confd
@@ -0,0 +1,8 @@
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+# Additional options to start rtpproxy with
+#
+# see "rtpproxy -h" for a list of options
+RTPPROXY_OPTS=""
diff --git a/main/rtpproxy/rtpproxy.initd b/main/rtpproxy/rtpproxy.initd
new file mode 100644
index 0000000000..5e53e51e88
--- /dev/null
+++ b/main/rtpproxy/rtpproxy.initd
@@ -0,0 +1,25 @@
+#!/sbin/runscript
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header$
+
+PIDFILE=/var/run/rtpproxy.pid
+
+depend() {
+ need net
+}
+
+start() {
+ ebegin "Starting rtpproxy"
+ start-stop-daemon --start --quiet --pidfile "${PIDFILE}" \
+ --exec /usr/bin/rtpproxy \
+ -- -urtpproxy:rtpproxy -p"${PIDFILE}" ${RTPPROXY_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping rtpproxy"
+ start-stop-daemon --stop --quiet --pidfile "${PIDFILE}"
+ eend $?
+}
+
diff --git a/main/rtpproxy/rtpproxy.pre-install b/main/rtpproxy/rtpproxy.pre-install
new file mode 100644
index 0000000000..498bedbd0b
--- /dev/null
+++ b/main/rtpproxy/rtpproxy.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup -S rtpproxy 2>/dev/null
+adduser -S -G rtpproxy -H -h /usr/share/rtpproxy -s /bin/false rtpproxy 2>/dev/null
+exit 0
diff --git a/main/ruby-actionmailer/APKBUILD b/main/ruby-actionmailer/APKBUILD
new file mode 100644
index 0000000000..b2909f4285
--- /dev/null
+++ b/main/ruby-actionmailer/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-actionmailer
+_realname=actionmailer
+pkgver=2.3.11
+pkgrel=0
+pkgdesc="Email on Rails"
+url="http://rubygems.org/gems/actionmailer"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev=
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-actionpack/APKBUILD b/main/ruby-actionpack/APKBUILD
new file mode 100644
index 0000000000..2839543d45
--- /dev/null
+++ b/main/ruby-actionpack/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-actionpack
+_realname=actionpack
+pkgver=2.3.11
+pkgrel=0
+pkgdesc="Eases web-request routing, handling, and response as a half-way front, half-way page controller"
+url="http://rubygems.org/gems/actionpack"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev=
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-activerecord/APKBUILD b/main/ruby-activerecord/APKBUILD
new file mode 100644
index 0000000000..4835e88409
--- /dev/null
+++ b/main/ruby-activerecord/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-activerecord
+_realname=activerecord
+pkgver=2.3.11
+pkgrel=0
+pkgdesc="Ruby ActiveRecord pattern (Fowler, PoEAA) for ORM"
+url="https://rubyforge.org/projects/activerecord/"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev=
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-activeresource/APKBUILD b/main/ruby-activeresource/APKBUILD
new file mode 100644
index 0000000000..ea766d6c06
--- /dev/null
+++ b/main/ruby-activeresource/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-activeresource
+_realname=activeresource
+pkgver=2.3.11
+pkgrel=0
+pkgdesc="REST on Rails"
+url="https://rubyforge.org/projects/activeresource/"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev=
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-activesupport/APKBUILD b/main/ruby-activesupport/APKBUILD
new file mode 100644
index 0000000000..24df309d59
--- /dev/null
+++ b/main/ruby-activesupport/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-activesupport
+_realname=activesupport
+pkgver=2.3.11
+pkgrel=0
+pkgdesc="Utility classes and extension to the standard library"
+url="https://rubyforge.org/projects/activesupport/"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev=
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-fcgi/APKBUILD b/main/ruby-fcgi/APKBUILD
new file mode 100644
index 0000000000..9bb0ea3016
--- /dev/null
+++ b/main/ruby-fcgi/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-fcgi
+_realname=fcgi
+pkgver=0.8.8
+pkgrel=0
+pkgdesc="Ruby fast CGI support"
+url="http://rubygems.org/gems/fcgi"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev="fcgi-dev ruby-dev"
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-i18n/APKBUILD b/main/ruby-i18n/APKBUILD
new file mode 100644
index 0000000000..a13e453a97
--- /dev/null
+++ b/main/ruby-i18n/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-i18n
+_realname=i18n
+pkgver=0.4.2
+pkgrel=0
+pkgdesc="Internationalization support for Ruby"
+url="http://rubygems.org/gems/i18n"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev=
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-mysql/APKBUILD b/main/ruby-mysql/APKBUILD
new file mode 100644
index 0000000000..ca2b184800
--- /dev/null
+++ b/main/ruby-mysql/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-mysql
+_realname=mysql
+pkgver=2.8.1
+pkgrel=0
+pkgdesc="MySQL API module for Ruby"
+url="http://rubygems.org/gems/mysql"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev="mysql-dev ruby-dev"
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-openid/APKBUILD b/main/ruby-openid/APKBUILD
new file mode 100644
index 0000000000..4c1366b3fd
--- /dev/null
+++ b/main/ruby-openid/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-openid
+_realname=openid
+pkgver=0.0.1
+pkgrel=0
+pkgdesc="OpenID support for Ruby"
+url="http://rubygems.org/gems/openid"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev=
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-pg/APKBUILD b/main/ruby-pg/APKBUILD
new file mode 100644
index 0000000000..4e5e14cd36
--- /dev/null
+++ b/main/ruby-pg/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-pg
+_realname=$pkgname
+pkgver=0.7.9.2008.01.28
+pkgrel=0
+pkgdesc="PostgreSQL API module for Ruby"
+url="http://rubygems.org/gems/ruby-pg"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev="postgresql-dev ruby-dev"
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-rack/APKBUILD b/main/ruby-rack/APKBUILD
new file mode 100644
index 0000000000..150aefc861
--- /dev/null
+++ b/main/ruby-rack/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=ruby-rack
+_realname=rack
+pkgver=1.1.2
+pkgrel=1
+pkgdesc="Rack is a Ruby Webserver Interface"
+url="http://rack.rubyforge.org/"
+arch="noarch"
+license="MIT"
+depends="ruby"
+depends_dev=""
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-rails/APKBUILD b/main/ruby-rails/APKBUILD
new file mode 100644
index 0000000000..020a9a3bc9
--- /dev/null
+++ b/main/ruby-rails/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-rails
+_realname=rails
+pkgver=2.3.11
+pkgrel=0
+pkgdesc="Ruby full-stack web framework"
+url="http://rubyonrails.org/"
+arch="all"
+license="GPL"
+depends="ruby ruby-actionmailer ruby-actionpack ruby-activerecord
+ ruby-activeresource ruby-activesupport ruby-rake ruby-rack"
+depends_dev=
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-rake/APKBUILD b/main/ruby-rake/APKBUILD
new file mode 100644
index 0000000000..197f776124
--- /dev/null
+++ b/main/ruby-rake/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=ruby-rake
+_realname=rake
+pkgver=0.9.2
+pkgrel=1
+pkgdesc="Rake is a Make-like program implemented in Ruby."
+url="http://rake.rubyforge.org/"
+arch="noarch"
+license="MIT"
+depends="ruby"
+depends_dev=""
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-rmagick/APKBUILD b/main/ruby-rmagick/APKBUILD
new file mode 100644
index 0000000000..53a4c61c2a
--- /dev/null
+++ b/main/ruby-rmagick/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Carlo Landmeter <clandmeter@alpinelinux.org>
+# Maintainer:
+pkgname=ruby-rmagick
+_realname=rmagick
+pkgver=2.13.1
+pkgrel=0
+pkgdesc="Ruby ImageMagick interface"
+url="http://rmagick.rubyforge.org"
+arch="all"
+license="custom"
+depends="ruby ghostscript-fonts"
+depends_dev="ruby-dev imagemagick-dev freetype-dev jpeg-dev zlib-dev"
+makedepends="$depends_dev ruby rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby-sqlite/APKBUILD b/main/ruby-sqlite/APKBUILD
new file mode 100644
index 0000000000..696c8956a9
--- /dev/null
+++ b/main/ruby-sqlite/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=ruby-sqlite
+_realname=sqlite3
+pkgver=1.3.3
+pkgrel=0
+pkgdesc="SQLite API module for Ruby"
+url="http://rubygems.org/gems/sqlite3"
+arch="all"
+license="GPL"
+depends="ruby"
+depends_dev="sqlite-dev ruby-dev"
+makedepends="$depends_dev rubygems"
+install=""
+subpackages=""
+source=""
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ mkdir -p "$_builddir" || return 1
+ local _gemdir="$(ruby -rubygems -e'puts Gem.default_dir')"
+ gem install $_realname -v $pkgver -i "$_builddir"$_gemdir \
+ --ignore-dependencies --verbose \
+ --no-rdoc --no-ri || return 1
+ rm -rf "$_builddir"$_gemdir/cache/
+}
+
+package() {
+ mkdir -p "$pkgdir" || return 1
+ cp -ra "$_builddir"/* "$pkgdir"/ || return 1
+}
diff --git a/main/ruby/APKBUILD b/main/ruby/APKBUILD
new file mode 100644
index 0000000000..6928002f6c
--- /dev/null
+++ b/main/ruby/APKBUILD
@@ -0,0 +1,56 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=ruby
+pkgver=1.8.7_p299
+_pkgver=1.8.7-p299
+pkgrel=1
+pkgdesc="An object-oriented language for quick and easy programming"
+url="http://www.ruby-lang.org/en/"
+arch="all"
+license="Ruby"
+depends=
+makedepends="zlib-dev openssl-dev libiconv-dev gdbm-dev db-dev readline-dev"
+subpackages="$pkgname-doc $pkgname-dev"
+source="ftp://ftp.ruby-lang.org/pub/ruby/1.8/${pkgname}-${_pkgver}.tar.bz2"
+#
+# maybe its a good idea to split dep libs to seperate pkg's.
+#
+
+_builddir="$srcdir/$pkgname-${_pkgver}"
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+
+ # -fomit-frame-pointer makes ruby segfault, see gentoo bug #150413
+ # In many places aliasing rules are broken; play it safe
+ # as it's risky with newer compilers to leave it as it is.
+ export CFLAGS="$CFLAGS -fno-omit-frame-pointer -fno-strict-aliasing"
+
+ # turn off distcc/ccache
+ # http://bugs.alpinelinux.org/issues/show/1
+ export CC=gcc
+
+ ./configure --build=${CHOST:-i486-alpine-linux-uclibc} \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-pthread \
+ --with-sitedir='/usr/local/lib/site_ruby' \
+ --with-extra-site-search-path='/usr/lib/site_ruby/$(ruby_ver)/i686-linux' \
+ --enable-shared
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ install -Dm644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}"/COPYING || return 1
+
+}
+
+md5sums="244439a87d75ab24170a9c2b451ce351 ruby-1.8.7-p299.tar.bz2"
diff --git a/main/rubygems/APKBUILD b/main/rubygems/APKBUILD
new file mode 100644
index 0000000000..285ad7d083
--- /dev/null
+++ b/main/rubygems/APKBUILD
@@ -0,0 +1,26 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=rubygems
+pkgver=1.3.5
+pkgrel=4
+pkgdesc="Ruby package manager"
+url="http://docs.rubygems.org"
+arch="all"
+license="GPL"
+depends="ruby"
+makedepends="ruby"
+source="http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ruby setup.rb --prefix="$pkgdir"/usr \
+ --verbose --no-rdoc --no-ri
+ mkdir -p "$pkgdir"/usr/lib/ruby/1.8
+ cd "$pkgdir"/usr/lib
+ mv rbconfig rubygems rubygems.rb ubygems.rb \
+ "$pkgdir"/usr/lib/ruby/1.8
+}
+
+md5sums="6e317335898e73beab15623cdd5f8cff rubygems-1.3.5.tgz"
diff --git a/main/run-parts/APKBUILD b/main/run-parts/APKBUILD
new file mode 100644
index 0000000000..ccc16132b0
--- /dev/null
+++ b/main/run-parts/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=run-parts
+pkgver=3.4.4
+pkgrel=0
+pkgdesc="run-parts from the debianutils package"
+url="http://packages.qa.debian.org/d/debianutils.html"
+arch="all"
+license="GPL"
+depends=
+subpackages="$pkgname-doc"
+source="http://ftp.de.debian.org/debian/pool/main/d/debianutils/debianutils_${pkgver}.tar.gz"
+
+build () {
+ cd $srcdir/debianutils-$pkgver
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd $srcdir/debianutils-$pkgver
+ install -D -m755 run-parts $pkgdir/usr/bin/run-parts
+ install -D -m644 run-parts.8 $pkgdir/usr/share/man/man8/run-parts.8
+}
+md5sums="52185225e696bb3c050c16a22aa79273 debianutils_3.4.4.tar.gz"
diff --git a/main/rxmtp/APKBUILD b/main/rxmtp/APKBUILD
new file mode 100644
index 0000000000..4a666743b3
--- /dev/null
+++ b/main/rxmtp/APKBUILD
@@ -0,0 +1,26 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=rxmtp
+pkgver=1.1.3
+pkgrel=2
+pkgdesc="Rewrite and eXchange smtp proxy"
+url="http://dev.alpinelinux.org/alpine/rxmtp"
+arch="x86"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages=""
+source="http://dev.alpinelinux.org/alpine/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make PREFIX=/usr || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make PREFIX=/usr DESTDIR="$pkgdir" install
+}
+
+md5sums="4b4fe71ed690251de6ee6ad58223d7a7 rxmtp-1.1.3.tar.gz"
diff --git a/main/samba/APKBUILD b/main/samba/APKBUILD
new file mode 100644
index 0000000000..9d134fde61
--- /dev/null
+++ b/main/samba/APKBUILD
@@ -0,0 +1,159 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=samba
+pkgver=3.5.9
+pkgrel=0
+pkgdesc="Tools to access a server's filespace and printers via SMB"
+url="http://www.samba.org"
+arch="all"
+license="GPL3"
+subpackages="$pkgname-dev $pkgname-doc winbind $pkgname-common
+ $pkgname-initscript tdb libsmbclient $pkgname-client"
+depends="samba-initscript samba-client"
+makedepends="popt-dev ncurses-dev openldap-dev heimdal-dev e2fsprogs-dev
+ libiconv-dev talloc-dev"
+source="http://us1.$pkgname.org/$pkgname/ftp/stable/$pkgname-$pkgver.tar.gz
+ samba.initd
+ samba.confd
+ samba.logrotate
+ samba-uclibc-fstab.patch
+ samba-maximum-number-of-winbindd-clients.patch
+ "
+pkggroups="winbind"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ patch -p1 -i "$i" || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"/source3
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/samba \
+ --with-configdir=/etc/samba \
+ --localstatedir=/var \
+ --with-fhs \
+ --with-lockdir=/var/cache/samba \
+ --with-piddir=/var/run/samba \
+ --with-logfilebase=/var/log/samba \
+ --without-pam \
+ --with-ads \
+ --with-krb5 \
+ --with-libsmbclient \
+ --with-shared-modules=idmap_rid,imap_ad \
+ --enable-external-libtalloc \
+ --disable-nss-wrapper \
+ --disable-dnssd \
+ --disable-swat
+ make everything || return 1
+}
+
+package() {
+ cd "$_builddir"/source3
+ make DESTDIR="$pkgdir" install
+
+ install -d "$pkgdir"/var/log/samba \
+ "$pkgdir"/usr/share/doc/samba
+ cd "$srcdir"/$pkgname-$pkgver
+ cp -r examples "$pkgdir"/usr/share/doc/samba/
+ install -D packaging/RHEL/setup/smbusers "$pkgdir"/etc/samba/smbusers
+ install -Dm644 ../samba.logrotate "$pkgdir"/etc/logrotate.d/samba
+}
+
+initscript() {
+ pkgdesc="Init script for Samba"
+ depends=""
+ install -Dm755 $srcdir/samba.initd "$subpkgdir"/etc/init.d/samba
+ install -Dm644 $srcdir/samba.confd "$subpkgdir"/etc/conf.d/samba
+}
+
+_mv_files() {
+ local i
+ for i in "$@"; do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i || return 1
+ done
+}
+
+winbind() {
+ pkgdesc="Samba user and group resolver"
+ depends=
+ install="winbind.pre-install winbind.pre-upgrade winbind.post-install
+ winbind.post-upgrade"
+ replaces="samba"
+ cd "$pkgdir"
+ _mv_files \
+ usr/bin/wbinfo \
+ usr/bin/ntlm_auth \
+ usr/sbin/winbindd \
+ usr/lib/samba/idmap
+ install -d -g winbind -m 750 \
+ "$subpkgdir"/var/cache/samba/winbindd_privileged
+}
+
+common() {
+ pkgdesc="Samba common files for both client an servers"
+ depends=
+ # we have moved libwbclient and libnetapi to samba-common
+ replaces="winbind samba"
+ cd "$pkgdir"
+ _mv_files \
+ usr/bin/net \
+ usr/bin/nmblookup \
+ usr/bin/smbpasswd \
+ usr/bin/testparm \
+ usr/lib/samba/*.dat \
+ usr/lib/libnetapi.so.* \
+ usr/lib/libwbclient* \
+ var/run/samba \
+ var/cache/samba \
+ var/log/samba
+}
+
+tdb() {
+ pkgdesc="Trivial database"
+ depends=
+ cd "$pkgdir"
+ _mv_files \
+ usr/lib/libtdb* \
+ usr/bin/tdb*
+}
+
+libsmbclient() {
+ pkgdesc="The SMB client library"
+ replaces="samba"
+ depends=
+ cd "$pkgdir"
+ _mv_files \
+ usr/lib/libsmbclient.so.* \
+ usr/lib/libsmbsharemodes.so.* \
+ || return 1
+}
+
+client() {
+ pkgdesc="Samba client program"
+ replaces="samba"
+ cd "$pkgdir"
+ _mv_files \
+ usr/bin/rpcclient \
+ usr/bin/smbcacls \
+ usr/bin/findsmb \
+ usr/bin/smbget \
+ usr/bin/smbclient \
+ usr/bin/smbcquotas \
+ usr/bin/smbspool \
+ usr/bin/smbtar \
+ usr/bin/smbtree \
+ usr/bin/sharesec \
+ || return 1
+}
+
+
+md5sums="fc3fe1103cf9d71abe12a8c604f31c76 samba-3.5.9.tar.gz
+c8a7f6ac5df2f73dbf023e25ea39927b samba.initd
+c150433426e18261e6e3eed3930e1a76 samba.confd
+b7cafabfb4fa5b3ab5f2e857d8d1c733 samba.logrotate
+811e5a3f570d0053cf27a73248be4ae6 samba-uclibc-fstab.patch
+a906d4049df6ca1a3c106e7df52d9925 samba-maximum-number-of-winbindd-clients.patch"
diff --git a/main/samba/samba-maximum-number-of-winbindd-clients.patch b/main/samba/samba-maximum-number-of-winbindd-clients.patch
new file mode 100644
index 0000000000..6e84bb413b
--- /dev/null
+++ b/main/samba/samba-maximum-number-of-winbindd-clients.patch
@@ -0,0 +1,134 @@
+From eeb24afd78a6448e808aaf96dbd7d5abf51bbd40 Mon Sep 17 00:00:00 2001
+From: Pierre Carrier <pcarrier@redhat.com>
+Date: Tue, 14 Sep 2010 16:43:39 -0700
+Subject: [PATCH] Allows changing the maximum number of simultaneous clients in winbindd through an smb.conf option.
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+---
+ docs-xml/smbdotconf/winbind/winbindmaxclients.xml | 14 ++++++++++++++
+ source3/include/local.h | 3 ---
+ source3/include/proto.h | 1 +
+ source3/param/loadparm.c | 13 ++++++++++++-
+ source3/winbindd/winbindd.c | 8 +++-----
+ 5 files changed, 30 insertions(+), 9 deletions(-)
+ create mode 100644 docs-xml/smbdotconf/winbind/winbindmaxclients.xml
+
+diff --git a/docs-xml/smbdotconf/winbind/winbindmaxclients.xml b/docs-xml/smbdotconf/winbind/winbindmaxclients.xml
+new file mode 100644
+index 0000000..ae49e45
+--- /dev/null
++++ b/docs-xml/smbdotconf/winbind/winbindmaxclients.xml
+@@ -0,0 +1,14 @@
++<samba:parameter name="winbind max clients"
++ context="G"
++ type="integer"
++ advanced="1" developer="1"
++ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
++<description>
++ <para>This parameter specifies the maximum number of clients
++ the <citerefentry><refentrytitle>winbindd</refentrytitle>
++ <manvolnum>8</manvolnum></citerefentry> daemon can connect with.
++ </para>
++</description>
++
++<value type="default">200</value>
++</samba:parameter>
+diff --git a/source3/include/local.h b/source3/include/local.h
+index a3baf64..93ec4cc 100644
+--- a/source3/include/local.h
++++ b/source3/include/local.h
+@@ -239,9 +239,6 @@
+ /* Number in seconds for winbindd to wait for the mutex. Make this 2 * smbd wait time. */
+ #define WINBIND_SERVER_MUTEX_WAIT_TIME (( ((NUM_CLI_AUTH_CONNECT_RETRIES) * ((CLI_AUTH_TIMEOUT)/1000)) + 5)*2)
+
+-/* Max number of simultaneous winbindd socket connections. */
+-#define WINBINDD_MAX_SIMULTANEOUS_CLIENTS 200
+-
+ /* Buffer size to use when printing backtraces */
+ #define BACKTRACE_STACK_SIZE 64
+
+diff --git a/source3/include/proto.h b/source3/include/proto.h
+index f089c69..e1751e8 100644
+--- a/source3/include/proto.h
++++ b/source3/include/proto.h
+@@ -3539,6 +3539,7 @@ int lp_smb_encrypt(int );
+ char lp_magicchar(const struct share_params *p );
+ int lp_winbind_cache_time(void);
+ int lp_winbind_reconnect_delay(void);
++int lp_winbind_max_clients(void);
+ const char **lp_winbind_nss_info(void);
+ int lp_algorithmic_rid_base(void);
+ int lp_name_cache_timeout(void);
+diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
+index e3fc2d8..bb6e132 100644
+--- a/source3/param/loadparm.c
++++ b/source3/param/loadparm.c
+@@ -262,7 +262,7 @@ struct global {
+ int oplock_break_wait_time;
+ int winbind_cache_time;
+ int winbind_reconnect_delay;
+- int winbind_max_idle_children;
++ int winbind_max_clients;
+ char **szWinbindNssInfo;
+ int iLockSpinTime;
+ char *szLdapMachineSuffix;
+@@ -4606,6 +4606,15 @@ static struct parm_struct parm_table[] = {
+ .flags = FLAG_ADVANCED,
+ },
+ {
++ .label = "winbind max clients",
++ .type = P_INTEGER,
++ .p_class = P_GLOBAL,
++ .ptr = &Globals.winbind_max_clients,
++ .special = NULL,
++ .enum_list = NULL,
++ .flags = FLAG_ADVANCED,
++ },
++ {
+ .label = "winbind enum users",
+ .type = P_BOOL,
+ .p_class = P_GLOBAL,
+@@ -5299,6 +5308,7 @@ static void init_globals(bool reinit_globals)
+
+ Globals.winbind_cache_time = 300; /* 5 minutes */
+ Globals.winbind_reconnect_delay = 30; /* 30 seconds */
++ Globals.winbind_max_clients = 200;
+ Globals.bWinbindEnumUsers = False;
+ Globals.bWinbindEnumGroups = False;
+ Globals.bWinbindUseDefaultDomain = False;
+@@ -5877,6 +5887,7 @@ FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt)
+ FN_LOCAL_CHAR(lp_magicchar, magic_char)
+ FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
+ FN_GLOBAL_INTEGER(lp_winbind_reconnect_delay, &Globals.winbind_reconnect_delay)
++FN_GLOBAL_INTEGER(lp_winbind_max_clients, &Globals.winbind_max_clients)
+ FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
+ FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
+ FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
+diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
+index 7a9ebb8..9c0a1fb 100644
+--- a/source3/winbindd/winbindd.c
++++ b/source3/winbindd/winbindd.c
+@@ -908,17 +908,15 @@ static void winbindd_listen_fde_handler(struct tevent_context *ev,
+ struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
+ struct winbindd_listen_state);
+
+- while (winbindd_num_clients() >
+- WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) {
++ while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
+ DEBUG(5,("winbindd: Exceeding %d client "
+ "connections, removing idle "
+- "connection.\n",
+- WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
++ "connection.\n", lp_winbind_max_clients()));
+ if (!remove_idle_client()) {
+ DEBUG(0,("winbindd: Exceeding %d "
+ "client connections, no idle "
+ "connection found\n",
+- WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
++ lp_winbind_max_clients()));
+ break;
+ }
+ }
+--
+1.7.0.4
+
diff --git a/main/samba/samba-uclibc-fstab.patch b/main/samba/samba-uclibc-fstab.patch
new file mode 100644
index 0000000000..3fdbc90308
--- /dev/null
+++ b/main/samba/samba-uclibc-fstab.patch
@@ -0,0 +1,15 @@
+--- ./client/mount.cifs.c.orig
++++ ./client/mount.cifs.c
+@@ -39,7 +39,11 @@
+ #include <mntent.h>
+ #include <fcntl.h>
+ #include <limits.h>
+-#include <fstab.h>
++#if defined(__UCLIBC__)
++ #define _PATH_FSTAB "/etc/fstab"
++#else
++ #include <fstab.h>
++#endif
+ #include "mount.h"
+
+ #define MOUNT_CIFS_VERSION_MAJOR "1"
diff --git a/main/samba/samba.confd b/main/samba/samba.confd
new file mode 100644
index 0000000000..3788c3c173
--- /dev/null
+++ b/main/samba/samba.confd
@@ -0,0 +1,6 @@
+# add "winbindd" to daemon_list if you want start winbind from here as well
+daemon_list="smbd nmbd"
+
+smbd_options="-D"
+nmbd_options="-D"
+#winbindd_options=""
diff --git a/main/samba/samba.initd b/main/samba/samba.initd
new file mode 100644
index 0000000000..f7290173f8
--- /dev/null
+++ b/main/samba/samba.initd
@@ -0,0 +1,65 @@
+#!/sbin/runscript
+
+opts="reload"
+
+DAEMON=${SVCNAME#samba.}
+if [ "$DAEMON" != "samba" ]; then
+ daemon_list=$DAEMON
+fi
+
+depend() {
+ need net
+ after firewall
+}
+
+start_smbd() {
+ start-stop-daemon --start --quiet --exec /usr/sbin/smbd -- \
+ ${smbd_options:-"-D"}
+}
+
+stop_smbd() {
+ start-stop-daemon --stop --quiet --pidfile /var/run/samba/smbd.pid
+}
+
+start_nmbd() {
+ start-stop-daemon --start --quiet --exec /usr/sbin/nmbd -- \
+ ${nmbd_options:-"-D"}
+}
+
+stop_nmbd() {
+ start-stop-daemon --stop --quiet --pidfile /var/run/samba/nmbd.pid
+}
+
+start_winbindd() {
+ start-stop-daemon --start --quiet --exec /usr/sbin/winbindd -- \
+ $winbindd_options
+}
+
+stop_winbindd() {
+ start-stop-daemon --stop --quiet --pidfile /var/run/samba/winbindd.pid
+}
+
+start() {
+ for i in $daemon_list; do
+ ebegin "Starting $i"
+ start_$i
+ eend $?
+ done
+}
+
+stop() {
+ for i in $daemon_list; do
+ ebegin "Stopping $i"
+ stop_$i
+ eend $?
+ done
+}
+
+reload() {
+ for i in $daemon_list; do
+ ebegin "Reloading $i"
+ killall -HUP $i
+ eend $?
+ done
+}
+
diff --git a/main/samba/samba.logrotate b/main/samba/samba.logrotate
new file mode 100644
index 0000000000..bf957bd747
--- /dev/null
+++ b/main/samba/samba.logrotate
@@ -0,0 +1,9 @@
+/var/log/samba/log.* /var/log/samba/*.log {
+ notifempty
+ missingok
+ sharedscripts
+ copytruncate
+ postrotate
+ /bin/kill -HUP `cat /var/run/samba/*.pid 2>/dev/null` 2>/dev/null || true
+ endscript
+}
diff --git a/main/samba/winbind.post-install b/main/samba/winbind.post-install
new file mode 100644
index 0000000000..59abe0ff92
--- /dev/null
+++ b/main/samba/winbind.post-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+chgrp winbind /var/cache/samba/winbindd_privileged
+chmod 750 /var/cache/samba/winbindd_privileged
+exit 0
+
diff --git a/main/samba/winbind.post-upgrade b/main/samba/winbind.post-upgrade
new file mode 120000
index 0000000000..398738a5e3
--- /dev/null
+++ b/main/samba/winbind.post-upgrade
@@ -0,0 +1 @@
+winbind.post-install \ No newline at end of file
diff --git a/main/samba/winbind.pre-install b/main/samba/winbind.pre-install
new file mode 100644
index 0000000000..792e73a803
--- /dev/null
+++ b/main/samba/winbind.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup winbind 2>/dev/null
+
+exit 0
diff --git a/main/samba/winbind.pre-upgrade b/main/samba/winbind.pre-upgrade
new file mode 120000
index 0000000000..b511f9595e
--- /dev/null
+++ b/main/samba/winbind.pre-upgrade
@@ -0,0 +1 @@
+winbind.pre-install \ No newline at end of file
diff --git a/main/screen/APKBUILD b/main/screen/APKBUILD
new file mode 100644
index 0000000000..eb4f2c525a
--- /dev/null
+++ b/main/screen/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer:
+pkgname=screen
+pkgver=4.0.3
+pkgrel=3
+pkgdesc="A window manager that multiplexes a physical terminal"
+url="http://ftp.gnu.org/gnu/screen/"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://ftp.gnu.org/gnu/screen/$pkgname-$pkgver.tar.gz
+ $pkgname-$pkgver.patch"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" install
+
+}
+
+md5sums="8506fd205028a96c741e4037de6e3c42 screen-4.0.3.tar.gz
+243e18daf4b2bbff898fdf0d772fad52 screen-4.0.3.patch"
diff --git a/main/screen/screen-4.0.3.patch b/main/screen/screen-4.0.3.patch
new file mode 100644
index 0000000000..4a90f49b91
--- /dev/null
+++ b/main/screen/screen-4.0.3.patch
@@ -0,0 +1,272 @@
+--- screen-4.0.3-orig/acls.h Mon Sep 8 14:23:38 2003
++++ screen-4.0.3/acls.h Fri Feb 27 18:32:07 2009
+@@ -20,6 +20,8 @@
+ *
+ ****************************************************************
+ */
++#ifndef _SCREEN_ACLS_H_
++#define _SCREEN_ACLS_H_
+
+ #ifdef MULTIUSER
+
+@@ -91,3 +93,4 @@
+
+ extern int DefaultEsc, DefaultMetaEsc;
+
++#endif /* define _SCREEN_ACLS_H_ */
+--- screen-4.0.3-orig/ansi.h Mon Feb 24 16:55:08 2003
++++ screen-4.0.3/ansi.h Fri Feb 27 18:32:49 2009
+@@ -21,6 +21,8 @@
+ ****************************************************************
+ * $Id: ansi.h,v 1.6 1994/05/31 12:31:28 mlschroe Exp $ FAU
+ */
++#ifndef _SCREEN_ANSI_H_
++#define _SCREEN_ANSI_H_
+
+ #define NATTR 6
+
+@@ -168,3 +170,5 @@
+ # define dw_left(ml, x, enc) 0
+ # define dw_right(ml, x, enc) 0
+ #endif
++
++#endif /* define _SCREEN_ANSI_H_ */
+--- screen-4.0.3-orig/braille.h Sat Apr 28 13:26:42 2001
++++ screen-4.0.3/braille.h Fri Feb 27 18:33:51 2009
+@@ -24,6 +24,8 @@
+ ****************************************************************
+ * $Id: braille.h,v 1.1 1995/09/06 15:51:18 jnweiger Exp jnweiger $ FAU
+ */
++#ifndef _SCREEN_BRAILLE_H_
++#define _SCREEN_BRAILLE_H_
+
+ #ifdef HAVE_BRAILLE
+
+@@ -81,3 +83,5 @@
+ #define BD_FORE bd.bd_dpy->d_fore
+
+ #endif
++
++#endif /* define _SCREEN_BRAILLE_H_ */
+--- screen-4.0.3-orig/display.h Tue Jul 1 14:01:42 2003
++++ screen-4.0.3/display.h Fri Feb 27 18:34:30 2009
+@@ -21,6 +21,8 @@
+ ****************************************************************
+ * $Id: display.h,v 1.9 1994/05/31 12:31:54 mlschroe Exp $ FAU
+ */
++#ifndef _SCREEN_DISPLAY_H_
++#define _SCREEN_DISPLAY_H_
+
+ #ifdef MAPKEYS
+
+@@ -343,3 +345,5 @@
+ #define HSTATUS_MESSAGE 2
+ #define HSTATUS_HS 3
+ #define HSTATUS_ALWAYS (1<<2)
++
++#endif /* define _SCREEN_DISPLAY_H_ */
+--- screen-4.0.3-orig/extern.h Fri Aug 22 12:27:57 2003
++++ screen-4.0.3/extern.h Fri Feb 27 18:35:17 2009
+@@ -21,6 +21,8 @@
+ ****************************************************************
+ * $Id: extern.h,v 1.18 1994/05/31 12:31:57 mlschroe Exp $ FAU
+ */
++#ifndef _SCREEN_EXTERN_H_
++#define _SCREEN_EXTERN_H_
+
+ #if !defined(__GNUC__) || __GNUC__ < 2
+ #undef __attribute__
+@@ -490,3 +492,5 @@
+ # endif
+ #endif
+ extern int EncodeChar __P((char *, int, int, int *));
++
++#endif /* define _SCREEN_EXTERN_H_ */
+--- screen-4.0.3-orig/image.h Fri Dec 5 13:45:41 2003
++++ screen-4.0.3/image.h Fri Feb 27 18:35:53 2009
+@@ -21,8 +21,9 @@
+ ****************************************************************
+ * $Id: image.h,v 1.9 1994/05/31 12:31:54 mlschroe Exp $ FAU
+ */
++#ifndef _SCREEN_IMAGE_H_
++#define _SCREEN_IMAGE_H_
+
+-
+ #undef IFFONT
+ #undef IFCOLOR
+
+@@ -161,3 +162,5 @@
+ # define cole2i(c) ((c) ^ 9)
+ # endif
+ #endif
++
++#endif /* define _SCREEN_IMAGE_H_ */
+--- screen-4.0.3-orig/layer.h Tue Jan 8 15:42:25 2002
++++ screen-4.0.3/layer.h Fri Feb 27 18:36:50 2009
+@@ -22,6 +22,9 @@
+ * $Id: overlay.h,v 1.3 1994/05/31 12:32:31 mlschroe Exp $ FAU
+ */
+
++#ifndef _SCREEN_LAYER_H_
++#define _SCREEN_LAYER_H_
++
+ /*
+ * This is the overlay structure. It is used to create a seperate
+ * layer over the current windows.
+@@ -103,3 +106,4 @@
+ display = olddisplay; \
+ } while(0)
+
++#endif /* define _SCREEN_LAYER_H_ */
+--- screen-4.0.3-orig/logfile.h Tue Jan 8 15:42:27 2002
++++ screen-4.0.3/logfile.h Fri Feb 27 18:37:29 2009
+@@ -22,6 +22,9 @@
+ * $Id: logfile.h,v 1.11 1994/05/31 12:33:27 jnweiger Exp $ FAU
+ */
+
++#ifndef _SCREEN_LOGFILE_H_
++#define _SCREEN_LOGFILE_H_
++
+ struct logfile
+ {
+ struct logfile *next;
+@@ -80,3 +83,5 @@
+ * It closes fd and opens wantfd to access whatever fd accessed.
+ */
+ int lf_move_fd __P((int fd, int wantfd));
++
++#endif /* define _SCREEN_LOGFILE_H_ */
+--- screen-4.0.3-orig/mark.h Tue Jan 8 15:42:30 2002
++++ screen-4.0.3/mark.h Fri Feb 27 18:38:02 2009
+@@ -21,6 +21,8 @@
+ ****************************************************************
+ * $Id: mark.h,v 1.1.1.1 1993/06/16 23:51:13 jnweiger Exp $ FAU
+ */
++#ifndef _SCREEN_MARK_H_
++#define _SCREEN_MARK_H_
+
+ struct markdata
+ {
+@@ -47,3 +49,4 @@
+ #define W2D(y) ((y) - markdata->hist_offset)
+ #define D2W(y) ((y) + markdata->hist_offset)
+
++#endif /* define _SCREEN_MARK_H_ */
+--- screen-4.0.3-orig/os.h Tue Jan 8 15:42:33 2002
++++ screen-4.0.3/os.h Fri Feb 27 18:39:09 2009
+@@ -21,6 +21,8 @@
+ ****************************************************************
+ * $Id: os.h,v 1.10 1994/05/31 12:32:22 mlschroe Exp $ FAU
+ */
++#ifndef _SCREEN_OS_H_
++#define _SCREEN_OS_H_
+
+ #include <stdio.h>
+ #include <errno.h>
+@@ -531,3 +533,4 @@
+ */
+ #define IOSIZE 4096
+
++#endif /* define _SCREEN_OS_H_ */
+--- screen-4.0.3-orig/osdef.h.in Sat Apr 28 13:26:43 2001
++++ screen-4.0.3/osdef.h.in Fri Feb 27 18:38:36 2009
+@@ -27,6 +27,8 @@
+ * mangled the screen source through 'gcc -Wall'.
+ ****************************************************************
+ */
++#ifndef _SCREEN_OSDEF_H_
++#define _SCREEN_OSDEF_H_
+
+ extern int printf __P((char *, ...));
+ extern int fprintf __P((FILE *, char *, ...));
+@@ -199,3 +201,4 @@
+ extern int getloadavg(double *, int);
+ #endif
+
++#endif /* define _SCREEN_OSDEF_H_ */
+--- screen-4.0.3-orig/patchlevel.h Mon Oct 23 13:04:11 2006
++++ screen-4.0.3/patchlevel.h Fri Feb 27 18:40:53 2009
+@@ -523,6 +523,8 @@
+ * (cstone & Rich Felker).
+ * -- DISTRIBUTED
+ */
++#ifndef _SCREEN_PATCHLEVEL_H_
++#define _SCREEN_PATCHLEVEL_H_
+
+ #define ORIGIN "FAU"
+ #define REV 4
+@@ -530,3 +532,5 @@
+ #define PATCHLEVEL 3
+ #define DATE "23-Oct-06"
+ #define STATE ""
++
++#endif /* define _SCREEN_PATCHLEVEL_H_ */
+--- screen-4.0.3-orig/pty.c Mon Sep 8 14:26:18 2003
++++ screen-4.0.3/pty.c Fri Feb 27 19:31:53 2009
+@@ -33,11 +33,6 @@
+ # include <sys/ioctl.h>
+ #endif
+
+-/* for solaris 2.1, Unixware (SVR4.2) and possibly others */
+-#ifdef HAVE_SVR4_PTYS
+-# include <sys/stropts.h>
+-#endif
+-
+ #if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL)
+ # include <sys/ttold.h>
+ #endif
+--- screen-4.0.3-orig/sched.h Tue Jan 8 15:42:43 2002
++++ screen-4.0.3/sched.h Fri Feb 27 19:39:49 2009
+@@ -21,6 +21,9 @@
+ ****************************************************************
+ * $Id: sched.h,v 1.1.1.1 1993/06/16 23:51:13 jnweiger Exp $ FAU
+ */
++#ifndef _SCREEN_SCHED_H_
++#define _SCREEN_SCHED_H_
++#include <sys/types.h>
+
+ struct event
+ {
+@@ -41,3 +44,5 @@
+ #define EV_READ 1
+ #define EV_WRITE 2
+ #define EV_ALWAYS 3
++
++#endif /* define _SCREEN_SCHED_H_ */
+--- screen-4.0.3-orig/screen.h Fri Aug 22 12:28:43 2003
++++ screen-4.0.3/screen.h Fri Feb 27 18:42:11 2009
+@@ -22,6 +22,9 @@
+ * $Id: screen.h,v 1.12 1994/05/31 12:32:54 mlschroe Exp $ FAU
+ */
+
++#ifndef _SCREEN_SCREEN_H_
++#define _SCREEN_SCREEN_H_
++
+ #include "os.h"
+
+ #if defined(__STDC__)
+@@ -293,3 +296,5 @@
+ */
+ #define WLIST_NUM 0
+ #define WLIST_MRU 1
++
++#endif /* define _SCREEN_SCREEN_H_ */
+--- screen-4.0.3-orig/window.h Thu Aug 21 14:57:30 2003
++++ screen-4.0.3/window.h Fri Feb 27 18:42:45 2009
+@@ -21,8 +21,9 @@
+ ****************************************************************
+ * $Id: window.h,v 1.11 1994/05/31 12:33:27 mlschroe Exp $ FAU
+ */
++#ifndef _SCREEN_WINDOW_H_
++#define _SCREEN_WINDOW_H_
+
+-
+ /* keep this in sync with the initialisations in window.c */
+ struct NewWindow
+ {
+@@ -315,3 +316,5 @@
+ : &fore->w_mlines[y - fore->w_histheight])
+
+ #define Layer2Window(l) ((struct win *)(l)->l_bottom->l_data)
++
++#endif /* define _SCREEN_WINDOW_H_ */
diff --git a/main/scrnsaverproto/APKBUILD b/main/scrnsaverproto/APKBUILD
new file mode 100644
index 0000000000..cb01d2e208
--- /dev/null
+++ b/main/scrnsaverproto/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=scrnsaverproto
+pkgver=1.2.1
+pkgrel=0
+pkgdesc="X11 Screen Saver extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org//releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -m755 -d "$pkgdir"/usr/share/licenses/$pkgname
+ install -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/ || return 1
+}
+md5sums="6af0f2e3369f5f74e69345e214f5fd0d scrnsaverproto-1.2.1.tar.bz2"
diff --git a/main/scrot/APKBUILD b/main/scrot/APKBUILD
new file mode 100644
index 0000000000..a11a79c2de
--- /dev/null
+++ b/main/scrot/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=scrot
+pkgver=0.8
+pkgrel=5
+pkgdesc="A simple command-line screenshot utility for X"
+url="http://linuxbrit.co.uk/scrot/"
+arch="all"
+license="MIT"
+subpackages="$pkgname-doc"
+depends=
+makedepends="giblib-dev imlib2-dev libx11-dev"
+source="http://linuxbrit.co.uk/downloads/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" docsdir=/usr/share/doc/scrot install || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+md5sums="ccae904d225609571bdd3b03445c1e88 scrot-0.8.tar.gz"
diff --git a/main/scstadmin/APKBUILD b/main/scstadmin/APKBUILD
new file mode 100644
index 0000000000..f67d53c46c
--- /dev/null
+++ b/main/scstadmin/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=scstadmin
+pkgver=2.0.0
+pkgrel=3
+pkgdesc="SCST administration tool written in perl"
+url="http://scst.sourceforge.net"
+arch="x86_64"
+license="GPL-2"
+depends="perl"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/scst/$pkgname-$pkgver.tar.gz
+ scst-init-ash-comapt.patch
+ "
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd "$_builddir"/scstadmin.sysfs/scst-0.9.00
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ cd "$_builddir"
+ patch -p1 < "$srcdir"/scst-init-ash-comapt.patch
+}
+
+package() {
+ cd "$_builddir"/scstadmin.sysfs/scst-0.9.00
+ make DESTDIR="$pkgdir" install || return 1
+
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/var/lib/scst/pr
+ install -Dm755 scstadmin.sysfs/scstadmin "$pkgdir"/usr/sbin/scstadmin || return 1
+ install -Dm755 init.d/scst.gentoo "$pkgdir"/etc/init.d/scstadmin || return 1
+}
+
+md5sums="ae94761148cc4eaade2973ba84387825 scstadmin-2.0.0.tar.gz
+061580b8ec84b5f7da0b1332601f505a scst-init-ash-comapt.patch"
diff --git a/main/scstadmin/scst-init-ash-comapt.patch b/main/scstadmin/scst-init-ash-comapt.patch
new file mode 100644
index 0000000000..67cd7adf17
--- /dev/null
+++ b/main/scstadmin/scst-init-ash-comapt.patch
@@ -0,0 +1,35 @@
+--- scstadmin/init.d/scst.gentoo
++++ scstadmin/init.d/scst.gentoo
+@@ -12,13 +12,11 @@
+ # Note: on most Linux distributions /bin/sh is a soft link to /bin/bash, while
+ # on a default Ubuntu setup /bin/sh is a soft link to /bin/dash !
+
+-opts="${opts} try-restart reload force-reload"
++opts="${opts} try_restart reload force_reload"
+ depend() {
+ use logger
+ }
+
+-PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin
+-
+ DEFAULTFILE="/etc/conf.d/scst"
+ SCST_CFG=/etc/scst.conf
+ MODPROBE="/sbin/modprobe"
+@@ -121,7 +119,7 @@
+ start
+ }
+
+-try-restart() {
++try_restart() {
+ ## Restart the service if the service is already running.
+ status >/dev/null 2>&1 && restart
+ }
+@@ -140,7 +138,7 @@
+ fi
+ }
+
+-force-reload() {
++force_reload() {
+ ## Cause the configuration to be reloaded if the service supports this,
+ ## otherwise restart the service if it is running.
+ einfo "Reloading SCST configuration"
diff --git a/main/sdl/APKBUILD b/main/sdl/APKBUILD
new file mode 100644
index 0000000000..1d0de3a6b4
--- /dev/null
+++ b/main/sdl/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sdl
+pkgver=1.2.14
+pkgrel=4
+pkgdesc="A library for portable low-level access to a video framebuffer, audio output, mouse, and keyboard"
+url="http://www.libsdl.org"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+depends_dev="libx11-dev libiconv-dev"
+makedepends="libxext-dev libxrender-dev libx11-dev libice-dev libsm-dev
+ libxrandr-dev mesa-dev alsa-lib-dev libiconv-dev"
+source="http://www.libsdl.org/release/SDL-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/SDL-$pkgver
+ ./configure --prefix=/usr \
+ --disable-nasm \
+ --disable-esd \
+ --enable-alsa \
+ --with-x \
+ --disable-rpath \
+ --disable-nls
+ make
+}
+
+package() {
+ cd "$srcdir"/SDL-$pkgver
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="e52086d1b508fa0b76c52ee30b55bec4 SDL-1.2.14.tar.gz"
diff --git a/main/sdl_image/APKBUILD b/main/sdl_image/APKBUILD
new file mode 100644
index 0000000000..bc95db1a60
--- /dev/null
+++ b/main/sdl_image/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sdl_image
+pkgver=1.2.10
+pkgrel=2
+pkgdesc="A simple library to load images of various formats as SDL surfaces"
+url="http://www.libsdl.org/projects/SDL_image/"
+arch="all"
+license="LGPL"
+depends=
+makedepends="sdl-dev libpng-dev jpeg-dev tiff-dev zlib-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://www.libsdl.org/projects/SDL_image/release/SDL_image-${pkgver}.tar.gz
+ sdl-image-1.2.10-libpng15.patch
+ "
+
+_builddir="$srcdir"/SDL_image-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+
+}
+
+md5sums="6c06584b31559e2b59f2b982d0d1f628 SDL_image-1.2.10.tar.gz
+53cb7b90cce2526570cfe0f8f80baa3e sdl-image-1.2.10-libpng15.patch"
diff --git a/main/sdl_image/sdl-image-1.2.10-libpng15.patch b/main/sdl_image/sdl-image-1.2.10-libpng15.patch
new file mode 100644
index 0000000000..d319045e0f
--- /dev/null
+++ b/main/sdl_image/sdl-image-1.2.10-libpng15.patch
@@ -0,0 +1,160 @@
+--- ./IMG_png.c
++++ ./IMG_png.c
+@@ -71,6 +71,10 @@
+ #endif
+ #include <png.h>
+
++/* Check for the older version of libpng */
++#if (PNG_LIBPNG_VER_MAJOR == 1) && (PNG_LIBPNG_VER_MINOR < 4)
++#define LIBPNG_VERSION_12
++#endif
+
+ static struct {
+ int loaded;
+@@ -80,6 +84,8 @@
+ void (*png_destroy_read_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr);
+ png_uint_32 (*png_get_IHDR) (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, int *interlace_method, int *compression_method, int *filter_method);
+ png_voidp (*png_get_io_ptr) (png_structp png_ptr);
++ png_byte (*png_get_channels) (png_structp png_ptr, png_infop info_ptr);
++ png_uint_32 (*png_get_PLTE) (png_structp png_ptr, png_infop info_ptr, png_colorp *palette, int *num_palette);
+ png_uint_32 (*png_get_tRNS) (png_structp png_ptr, png_infop info_ptr, png_bytep *trans, int *num_trans, png_color_16p *trans_values);
+ png_uint_32 (*png_get_valid) (png_structp png_ptr, png_infop info_ptr, png_uint_32 flag);
+ void (*png_read_image) (png_structp png_ptr, png_bytepp image);
+@@ -91,6 +97,9 @@
+ void (*png_set_read_fn) (png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn);
+ void (*png_set_strip_16) (png_structp png_ptr);
+ int (*png_sig_cmp) (png_bytep sig, png_size_t start, png_size_t num_to_check);
++#ifndef LIBPNG_VERSION_12
++ jmp_buf* (*png_set_longjmp_fn) (png_structp, png_longjmp_ptr, size_t);
++#endif
+ } lib;
+
+ #ifdef LOAD_PNG_DYNAMIC
+@@ -129,6 +138,13 @@
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
++ lib.png_get_channels =
++ (png_byte (*) (png_structp, png_infop))
++ SDL_LoadFunction(lib.handle, "png_get_channels");
++ if ( lib.png_get_channels == NULL ) {
++ SDL_UnloadObject(lib.handle);
++ return -1;
++ }
+ lib.png_get_io_ptr =
+ (png_voidp (*) (png_structp))
+ SDL_LoadFunction(lib.handle, "png_get_io_ptr");
+@@ -136,6 +152,13 @@
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
++ lib.png_get_PLTE =
++ (png_uint_32 (*) (png_structp, png_infop, png_colorp *, int *))
++ SDL_LoadFunction(lib.handle, "png_get_PLTE");
++ if ( lib.png_get_PLTE == NULL ) {
++ SDL_UnloadObject(lib.handle);
++ return -1;
++ }
+ lib.png_get_tRNS =
+ (png_uint_32 (*) (png_structp, png_infop, png_bytep *, int *, png_color_16p *))
+ SDL_LoadFunction(lib.handle, "png_get_tRNS");
+@@ -213,6 +236,15 @@
+ SDL_UnloadObject(lib.handle);
+ return -1;
+ }
++#ifndef LIBPNG_VERSION_12
++ lib.png_set_longjmp_fn =
++ (jmp_buf * (*) (png_structp, png_longjmp_ptr, size_t))
++ SDL_LoadFunction(lib.handle, "png_set_longjmp_fn");
++ if ( lib.png_set_longjmp_fn == NULL ) {
++ SDL_UnloadObject(lib.handle);
++ return -1;
++ }
++#endif
+ }
+ ++lib.loaded;
+
+@@ -236,7 +268,9 @@
+ lib.png_create_read_struct = png_create_read_struct;
+ lib.png_destroy_read_struct = png_destroy_read_struct;
+ lib.png_get_IHDR = png_get_IHDR;
++ lib.png_get_channels = png_get_channels;
+ lib.png_get_io_ptr = png_get_io_ptr;
++ lib.png_get_PLTE = png_get_PLTE;
+ lib.png_get_tRNS = png_get_tRNS;
+ lib.png_get_valid = png_get_valid;
+ lib.png_read_image = png_read_image;
+@@ -248,6 +282,9 @@
+ lib.png_set_read_fn = png_set_read_fn;
+ lib.png_set_strip_16 = png_set_strip_16;
+ lib.png_sig_cmp = png_sig_cmp;
++#ifndef LIBPNG_VERSION_12
++ lib.png_set_longjmp_fn = png_set_longjmp_fn;
++#endif
+ }
+ ++lib.loaded;
+
+@@ -347,7 +384,12 @@
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in png_create_read_struct() earlier.
+ */
+- if ( setjmp(png_ptr->jmpbuf) ) {
++#ifndef LIBPNG_VERSION_12
++ if ( setjmp(*lib.png_set_longjmp_fn(png_ptr, longjmp, sizeof (jmp_buf))) )
++#else
++ if ( setjmp(png_ptr->jmpbuf) )
++#endif
++ {
+ error = "Error reading the PNG file.";
+ goto done;
+ }
+@@ -416,9 +458,9 @@
+ Rmask = 0x000000FF;
+ Gmask = 0x0000FF00;
+ Bmask = 0x00FF0000;
+- Amask = (info_ptr->channels == 4) ? 0xFF000000 : 0;
++ Amask = (lib.png_get_channels(png_ptr, info_ptr) == 4) ? 0xFF000000 : 0;
+ } else {
+- int s = (info_ptr->channels == 4) ? 0 : 8;
++ int s = (lib.png_get_channels(png_ptr, info_ptr) == 4) ? 0 : 8;
+ Rmask = 0xFF000000 >> s;
+ Gmask = 0x00FF0000 >> s;
+ Bmask = 0x0000FF00 >> s;
+@@ -426,7 +468,7 @@
+ }
+ }
+ surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
+- bit_depth*info_ptr->channels, Rmask,Gmask,Bmask,Amask);
++ bit_depth*lib.png_get_channels(png_ptr, info_ptr), Rmask,Gmask,Bmask,Amask);
+ if ( surface == NULL ) {
+ error = "Out of memory";
+ goto done;
+@@ -467,6 +509,9 @@
+ /* Load the palette, if any */
+ palette = surface->format->palette;
+ if ( palette ) {
++ int png_num_palette;
++ png_colorp png_palette;
++ lib.png_get_PLTE(png_ptr, info_ptr, &png_palette, &png_num_palette);
+ if(color_type == PNG_COLOR_TYPE_GRAY) {
+ palette->ncolors = 256;
+ for(i = 0; i < 256; i++) {
+@@ -474,12 +519,12 @@
+ palette->colors[i].g = i;
+ palette->colors[i].b = i;
+ }
+- } else if (info_ptr->num_palette > 0 ) {
+- palette->ncolors = info_ptr->num_palette;
+- for( i=0; i<info_ptr->num_palette; ++i ) {
+- palette->colors[i].b = info_ptr->palette[i].blue;
+- palette->colors[i].g = info_ptr->palette[i].green;
+- palette->colors[i].r = info_ptr->palette[i].red;
++ } else if (png_num_palette > 0 ) {
++ palette->ncolors = png_num_palette;
++ for( i=0; i<png_num_palette; ++i ) {
++ palette->colors[i].b = png_palette[i].blue;
++ palette->colors[i].g = png_palette[i].green;
++ palette->colors[i].r = png_palette[i].red;
+ }
+ }
+ }
diff --git a/main/sdl_mixer/APKBUILD b/main/sdl_mixer/APKBUILD
new file mode 100644
index 0000000000..76767c36b9
--- /dev/null
+++ b/main/sdl_mixer/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sdl_mixer
+pkgver=1.2.11
+pkgrel=2
+pkgdesc="A simple multi-channel audio mixer"
+url="http://www.libsdl.org/projects/SDL_mixer/"
+arch="all"
+license="GPL"
+depends=
+makedepends="sdl-dev libvorbis-dev libmikmod-dev"
+install=
+subpackages="$pkgname-dev"
+source="http://www.libsdl.org/projects/SDL_mixer/release/SDL_mixer-${pkgver}.tar.gz"
+
+_builddir="$srcdir"/SDL_mixer-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ sed -e "/CONFIG_FILE_ETC/s/\/etc\/timidity.cfg/\/etc\/timidity++\/timidity.cfg/" \
+ -e "/DEFAULT_PATH/s/\/etc\/timidity/\/etc\/timidity++/" \
+ -e "/DEFAULT_PATH2/s/\/usr\/local\/lib\/timidity/\/usr\/lib\/timidity/" \
+ -i timidity/config.h
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-music-mod
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="65ada3d997fe85109191a5fb083f248c SDL_mixer-1.2.11.tar.gz"
diff --git a/main/sed/APKBUILD b/main/sed/APKBUILD
new file mode 100644
index 0000000000..26e2425273
--- /dev/null
+++ b/main/sed/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sed
+pkgver=4.2.1
+pkgrel=2
+subpackages="$pkgname-doc"
+pkgdesc="GNU stream editor"
+url="http://www.gnu.org/software/sed"
+arch="all"
+license="GPL"
+depends=
+makedepends=""
+install="$pkgname.post-deinstall"
+source="ftp://ftp.gnu.org/pub/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-i18n \
+ --disable-nls
+ make || return 1
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="f0fd4d7da574d4707e442285fd2d3b86 sed-4.2.1.tar.gz"
diff --git a/main/sed/sed.post-deinstall b/main/sed/sed.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/sed/sed.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/sems/APKBUILD b/main/sems/APKBUILD
new file mode 100644
index 0000000000..a37685b3ec
--- /dev/null
+++ b/main/sems/APKBUILD
@@ -0,0 +1,202 @@
+# Contributor: Francesco Colista <francesco.colista@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sems
+pkgver=1.4.1
+pkgrel=1
+pkgdesc="SIP Express Media Server, an extensible SIP media server"
+url="http://iptel.org/sems/"
+arch="all"
+license="GPLv2+"
+pkgusers="sems"
+pkggroups="sems"
+install="$pkgname.pre-install"
+makedepends="python-dev cmake bash openssl-dev
+ libsamplerate-dev spandsp-dev flite-dev gsm-dev speex-dev
+ "
+subpackages="$pkgname-doc $pkgname-conf_auth $pkgname-conference
+ $pkgname-diameter_client $pkgname-dsm $pkgname-early_announce
+ $pkgname-g722 $pkgname-gsm $pkgname-ivr $pkgname-mailbox
+ $pkgname-pin_collect $pkgname-speex $pkgname-xmlrpc2di"
+
+source="http://ftp.iptel.org/pub/sems/sems-$pkgver.tar.gz
+ sems-0001-Force-to-use-system-wide-GSM-includes.patch
+ sems-0002-Allow-rewrite-of-custom-makefiles-by-CMake.patch
+ sems-0003-Set-CFG_PREFIX-to-empty-string-by-default.patch
+
+ sems.initd
+ "
+# sems-0005-Add-sw_prepaid_sip-plugin-to-default-exclude-list-du.patch
+# sems-0006-last-minute-fix-proper-version.patch
+# sems-0008-Install-email-template.patch
+# sems-0009-Don-t-start-py_sems-by-default.patch
+
+# applied:
+# sems-0007-Fix-gateway-module-s-version-passing-in-CMake.patch
+# sems-0010-Move-CMake-defines.patch
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ rm -rf core/plug-in/gsm/gsm-1.0-pl10/
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+
+build() {
+ cd "$_builddir"
+ cmake \
+ -DSEMS_USE_SPANDSP=yes \
+ -DSEMS_USE_LIBSAMPLERATE=yes \
+ -DSEMS_USE_ZRTP=NO \
+ -DSEMS_USE_MP3=NO \
+ -DSEMS_USE_ILBC=NO \
+ -DSEMS_USE_TTS=yes \
+ -DSEMS_USE_OPENSSL=yes \
+ -DSEMS_USE_MONITORING=yes \
+ -DSEMS_USE_IPV6=NO \
+ -DSEMS_CFG_PREFIX= \
+ -DSEMS_AUDIO_PREFIX=/usr/share \
+ -DSEMS_EXEC_PREFIX=/usr \
+ -DSEMS_LIBDIR=lib \
+ || return 1
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make install DESTDIR="$pkgdir"
+ install -m755 -D "$srcdir"/$pkgname.initd \
+ "$pkgdir"/etc/init.d/$pkgname || return 1
+ # is empty
+ rm -f "$pkgdir"/etc/sems/etc/conf_auth.conf
+
+ install -o sems -g sems -d "$pkgdir"/var/spool/voicebox
+ install -d -o sems "$pkgdir"/var/run/sems
+}
+
+_mv_sub() {
+ local i
+ for i in "$@"; do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i
+ done
+}
+
+conf_auth() {
+ pkgdesc="Conference with authorization for SEMS"
+ depends="sems sems-ivr"
+ cd "$pkgdir"
+ _mv_sub usr/lib/sems/ivr/conf_auth*
+}
+
+conference() {
+ pkgdesc="Conferencing application for SEMS"
+ depends="sems"
+ cd "$pkgdir"
+ _mv_sub etc/sems/etc/conference.conf \
+ usr/lib/sems/plug-in/conference.so \
+ usr/share/sems/audio/conference
+}
+
+diameter_client() {
+ pkgdesc="A simple DIAMETER client implementation for SEMS"
+ depends="sems"
+ cd "$pkgdir"
+ _mv_sub usr/lib/sems/plug-in/diameter_client.so
+}
+
+dsm() {
+ pkgdesc="The state machine interpreter for SEMS"
+ depends="sems"
+ cd "$pkgdir"
+ _mv_sub etc/sems/etc/dsm* \
+ usr/lib/sems/plug-in/dsm.so \
+ usr/lib/sems/dsm
+}
+
+early_announce() {
+ pkgdesc="Early announce application for SEMS"
+ depends="sems"
+ cd "$pkgdir"
+ _mv_sub etc/sems/etc/early_announce.conf \
+ usr/lib/sems/plug-in/early_announce.so
+}
+
+g722() {
+ pkgdesc="G.722 support for SEMS"
+ depends="sems"
+ _mv_sub usr/lib/sems/plug-in/g722.so
+}
+
+#gateway() {
+# pkgdesc="ISDN gateway for SEMS"
+# depends="sems"
+#}
+
+gsm() {
+ pkgdesc="GSM support for SEMS"
+ depends="sems"
+ _mv_sub usr/lib/sems/plug-in/gsm.so
+}
+
+ivr() {
+ pkgdesc="IVR functionallity for SEMS"
+ depends="sems python"
+ cd "$pkgdir"
+ _mv_sub etc/sems/etc/ivr.conf \
+ usr/lib/sems/plug-in/ivr.so \
+ usr/lib/sems/ivr/log.*
+}
+
+mailbox() {
+ pkgdesc="Mailbox application for SEMS"
+ depends="sems sems-ivr"
+ cd "$pkgdir"
+ _mv_sub etc/sems/etc/mailbox*.conf \
+ usr/share/sems/audio/mailbox \
+ usr/lib/sems/plug-in/ivr.so \
+ usr/lib/sems/ivr/*mailbox*
+}
+
+pin_collect() {
+ pkgdesc="Collects a PIN for SEMS"
+ depends="sems sems-ivr"
+ cd "$pkgdir"
+ _mv_sub etc/sems/etc/pin_collect.conf \
+ usr/share/sems/audio/pin_collect \
+ usr/lib/sems/plug-in/ivr.so \
+ usr/lib/sems/ivr/pin_collect*
+}
+
+_python() {
+ pkgdesc="Python bindings for SEMS"
+ depends="python sems"
+ cd "$pkgdir"
+ _mv_sub \
+ usr/lib/sems/plug-in/py_sems*
+}
+
+speex() {
+ pkgdesc="Speex support for SEMS"
+ depends="sems"
+ _mv_sub usr/lib/sems/plug-in/speex.so
+}
+
+xmlrpc2di() {
+ pkgdesc="XMLRPC interface for SEMS"
+ depends="sems"
+ _mv_sub \
+ etc/sems/etc/xmlrpc2di.conf \
+ usr/lib/sems/plug-in/xmlrpc2di.so
+}
+
+
+md5sums="686ab348e06d8cac7c52080c8b056487 sems-1.4.1.tar.gz
+5b2fded836b44bda33f39adc37de4de7 sems-0001-Force-to-use-system-wide-GSM-includes.patch
+b8efd1a6415afa08f7c676f6976fca36 sems-0002-Allow-rewrite-of-custom-makefiles-by-CMake.patch
+331e7529833c906b4738006f32a65fde sems-0003-Set-CFG_PREFIX-to-empty-string-by-default.patch
+36c2f993ba874781f5d3974b4f4c1503 sems.initd"
diff --git a/main/sems/sems-0001-Force-to-use-system-wide-GSM-includes.patch b/main/sems/sems-0001-Force-to-use-system-wide-GSM-includes.patch
new file mode 100644
index 0000000000..d09b793395
--- /dev/null
+++ b/main/sems/sems-0001-Force-to-use-system-wide-GSM-includes.patch
@@ -0,0 +1,26 @@
+From de3c54f85f893e4ee985b1da93cc014b00456fa8 Mon Sep 17 00:00:00 2001
+From: Peter Lemenkov <lemenkov@gmail.com>
+Date: Wed, 31 Mar 2010 11:52:52 +0400
+Subject: [PATCH 01/11] Force to use system-wide GSM includes
+
+Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
+---
+ core/plug-in/gsm/gsm.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/core/plug-in/gsm/gsm.c b/core/plug-in/gsm/gsm.c
+index 286a989..3517e59 100644
+--- a/core/plug-in/gsm/gsm.c
++++ b/core/plug-in/gsm/gsm.c
+@@ -27,7 +27,7 @@
+
+ #include "amci.h"
+ #include "codecs.h"
+-#include "gsm-1.0-pl10/inc/gsm.h"
++#include <gsm.h>
+ #include "../../log.h"
+
+ #include <stdlib.h>
+--
+1.7.3.4
+
diff --git a/main/sems/sems-0002-Allow-rewrite-of-custom-makefiles-by-CMake.patch b/main/sems/sems-0002-Allow-rewrite-of-custom-makefiles-by-CMake.patch
new file mode 100644
index 0000000000..0cfeab8c83
--- /dev/null
+++ b/main/sems/sems-0002-Allow-rewrite-of-custom-makefiles-by-CMake.patch
@@ -0,0 +1,33 @@
+From 26929b6a7a62299b71bf7c99f17f75670a2040e2 Mon Sep 17 00:00:00 2001
+From: Peter Lemenkov <lemenkov@gmail.com>
+Date: Wed, 31 Mar 2010 11:53:48 +0400
+Subject: [PATCH 02/11] Allow rewrite of custom makefiles by CMake
+
+Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
+---
+ CMakeLists.txt | 9 ---------
+ 1 files changed, 0 insertions(+), 9 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index a6ff425..ef3934e 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -26,15 +26,6 @@ ELSE(IS_DEVEL)
+ ENDIF(IS_DEVEL)
+ MESSAGE(STATUS "Configuring ${CMAKE_PROJECT_NAME} v. ${SEMS_VERSION}")
+
+-IF(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE)
+- message(FATAL_ERROR "In-source builds are not allowed.
+-CMake would overwrite all makefiles distributed with SEMS.
+-Please create a directory and run cmake from there, passing the path
+-to this source directory as the last argument.
+-This process created the file `CMakeCache.txt' and the directory `CMakeFiles'.
+-Please delete them.")
+-ENDIF(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE)
+-
+ OPTION(SEMS_USE_SPANDSP "Build with spandsp" OFF)
+ OPTION(SEMS_USE_LIBSAMPLERATE "Build with libsamplerate" OFF)
+ OPTION(SEMS_USE_ZRTP "Build with ZRTP" OFF)
+--
+1.7.3.4
+
diff --git a/main/sems/sems-0003-Set-CFG_PREFIX-to-empty-string-by-default.patch b/main/sems/sems-0003-Set-CFG_PREFIX-to-empty-string-by-default.patch
new file mode 100644
index 0000000000..df0a5ad405
--- /dev/null
+++ b/main/sems/sems-0003-Set-CFG_PREFIX-to-empty-string-by-default.patch
@@ -0,0 +1,26 @@
+From e322f2e00e48b639b5d87ed06738aa24d99396bf Mon Sep 17 00:00:00 2001
+From: Peter Lemenkov <lemenkov@gmail.com>
+Date: Wed, 31 Mar 2010 18:56:39 +0400
+Subject: [PATCH 03/11] Set CFG_PREFIX to empty string by default
+
+Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
+---
+ CMakeLists.txt | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index ef3934e..c36ce62 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -48,7 +48,7 @@ ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} STREQUAL "2.4")
+ SET(CMAKE_DL_LIBS ${CMAKE_DL_LIBS} m pthread)
+
+ IF (NOT SEMS_CFG_PREFIX)
+- SET(SEMS_CFG_PREFIX "/usr/local")
++ SET(SEMS_CFG_PREFIX "")
+ ENDIF (NOT SEMS_CFG_PREFIX)
+ MESSAGE(STATUS "SEMS cfg prefix was set to: ${SEMS_CFG_PREFIX}")
+
+--
+1.7.3.4
+
diff --git a/main/sems/sems-0010-Move-CMake-defines.patch b/main/sems/sems-0010-Move-CMake-defines.patch
new file mode 100644
index 0000000000..be1b8be7a8
--- /dev/null
+++ b/main/sems/sems-0010-Move-CMake-defines.patch
@@ -0,0 +1,66 @@
+From c6fe28de4a05e33c317019261711f2babe98b95d Mon Sep 17 00:00:00 2001
+From: Peter Lemenkov <lemenkov@gmail.com>
+Date: Mon, 3 Jan 2011 22:16:24 +0300
+Subject: [PATCH 10/11] Move CMake defines
+
+Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
+---
+ CMakeLists.txt | 3 +++
+ core/CMakeLists.txt | 6 ------
+ 2 files changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 78a6dfb..fdc88f4 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -80,6 +80,7 @@ SET(CMAKE_VERBOSE_MAKEFILE ON)
+ # (which means that current debian and gentoo packages don't work)
+ IF(SEMS_USE_SPANDSP)
+ FIND_PACKAGE(Spandsp REQUIRED)
++ ADD_DEFINITIONS(-DUSE_SPANDSP -D__STDC_LIMIT_MACROS)
+ MESSAGE(STATUS "Using spandsp: YES")
+ ELSE(SEMS_USE_SPANDSP)
+ MESSAGE(STATUS "Using spandsp: NO (default)")
+@@ -89,6 +90,7 @@ ENDIF(SEMS_USE_SPANDSP)
+ # (see http://www.mega-nerd.com/SRC/)
+ IF(SEMS_USE_LIBSAMPLERATE)
+ FIND_PACKAGE(Libsamplerate REQUIRED)
++ ADD_DEFINITIONS(-DUSE_LIBSAMPLERATE)
+ MESSAGE(STATUS "Using libsamplerate: YES")
+ ELSE(SEMS_USE_LIBSAMPLERATE)
+ MESSAGE(STATUS "Using libsamplerate: NO (default)")
+@@ -128,6 +130,7 @@ ELSE(SEMS_USE_MONITORING)
+ ENDIF(SEMS_USE_MONITORING)
+
+ IF(SEMS_USE_IPV6)
++ ADD_DEFINITIONS(-DSUPPORT_IPV6)
+ MESSAGE(STATUS "Enable IPv6 support: YES")
+ ELSE(SEMS_USE_IPV6)
+ MESSAGE(STATUS "Enable IPv6 support: NO (default)")
+diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
+index 7bd1341..5f0fb3f 100644
+--- a/core/CMakeLists.txt
++++ b/core/CMakeLists.txt
+@@ -18,19 +18,13 @@ ENDIF(NOT MAX_RTP_SESSIONS)
+ ADD_DEFINITIONS(-DMAX_RTP_SESSIONS=${MAX_RTP_SESSIONS})
+
+ IF(SPANDSP_FOUND)
+- ADD_DEFINITIONS(-DUSE_SPANDSP -D__STDC_LIMIT_MACROS)
+ TARGET_LINK_LIBRARIES(sems ${CMAKE_DL_LIBS} spandsp)
+ ENDIF(SPANDSP_FOUND)
+
+ IF(LIBSAMPLERATE_FOUND)
+- ADD_DEFINITIONS(-DUSE_LIBSAMPLERATE)
+ TARGET_LINK_LIBRARIES(sems ${CMAKE_DL_LIBS} samplerate)
+ ENDIF(LIBSAMPLERATE_FOUND)
+
+-IF(SEMS_USE_IPV6)
+- ADD_DEFINITIONS(-DSUPPORT_IPV6)
+-ENDIF(SEMS_USE_IPV6)
+-
+ ADD_SUBDIRECTORY(plug-in)
+
+ # Create config-file from template
+--
+1.7.3.4
+
diff --git a/main/sems/sems.initd b/main/sems/sems.initd
new file mode 100755
index 0000000000..3b6973b55c
--- /dev/null
+++ b/main/sems/sems.initd
@@ -0,0 +1,48 @@
+#!/sbin/runscript
+# SIP Express Media Server configuration file
+# Follows Gentoo/AlpineLinux standards
+# GPL 2 License - N. Angelacos 2011
+
+SVC="${SVCNAME#*.}"
+SEMS_CFG_FILE=${SEMS_CFG_FILE:-/etc/sems/${SVC}.conf}
+SEMS_PIDDIR=/var/run/sems
+SEMS_PIDFILE=${SEMS_PIDFILE:-${SEMS_PIDDIR}/${SVC}.pid}
+SEMS_BINARY=${SEMS_BINARY:-/usr/sbin/sems}
+SEMS_USER=${SEMS_USER:-sems}
+SEMS_GROUP=${SEMS_GROUP:-sems}
+
+checkconfig() {
+ if [ ! -f "${SEMS_CFG_FILE}" ] ; then
+ eerror "You need a "${SEMS_CFG_FILE}" file to run sems"
+ return 1;
+ fi
+}
+
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ${SVCNAME}"
+ mkdir -p "${SEMS_PIDDIR}"
+ chown ${SEMS_USER}:${SEMS_GROUP} "${SEMS_PIDDIR}"
+
+ start-stop-daemon --start --exec "${SEMS_BINARY}" \
+ --pidfile "${SEMS_PIDFILE}" \
+ --wait ${SEMS_WAIT:-500} \
+ -- \
+ -f "${SEMS_CFG_FILE}" \
+ -P "${SEMS_PIDFILE}" \
+ -u "${SEMS_USER}" \
+ -g "${SEMS_GROUP}"
+ eend $?
+}
+
+stop() {
+ if [ "${RC_CMD}" = "restart" ] ; then
+ checkconfig || return 1
+ fi
+
+ ebegin "Stopping ${SVCNAME}"
+ start-stop-daemon --stop --exec "${SEMS_BINARY}" \
+ --pidfile "${SEMS_PIDFILE}" --quiet
+ eend $?
+}
diff --git a/main/sems/sems.pre-install b/main/sems/sems.pre-install
new file mode 100644
index 0000000000..f126694087
--- /dev/null
+++ b/main/sems/sems.pre-install
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if ! getent group sems >/dev/null; then
+ addgroup -S sems
+fi
+if ! getent passwd sems >/dev/null; then
+ adduser -S -H -h /var/empty -s /bin/false -D -G sems sems 2>/dev/null
+fi
+
+exit 0
diff --git a/main/sendpage/APKBUILD b/main/sendpage/APKBUILD
new file mode 100644
index 0000000000..10be074bec
--- /dev/null
+++ b/main/sendpage/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Jeff Bilyk <jbilyk@gmail.com>
+pkgname=sendpage
+pkgver=1.0.3
+_pkgver=1.000003
+pkgrel=4
+pkgdesc="SNPP server, client, queueing engine, modem control and TAP system"
+url="http://www.sendpage.org"
+arch="noarch"
+license="GPL"
+depends="perl-mail-tools perl-net-snpp perl-device-serialport
+ perl-dbi perl-sys-hostname-long perl-test-mockobject"
+makedepends="perl-dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$_pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$_pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ perl ./Makefile.PL \
+ PREFIX="/usr" \
+ INSTALLSITELIB="/usr/lib/perl5/vendor_perl" \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ # Remove useless folder, since it has nothing of value in it
+ rm -r "$pkgdir"/usr/local
+ # Prevent perl file collisions
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="586afe41d6cd82d045fdc34ccf99cab3 sendpage-1.000003.tar.gz"
diff --git a/main/sessreg/APKBUILD b/main/sessreg/APKBUILD
new file mode 100644
index 0000000000..68824d5d7e
--- /dev/null
+++ b/main/sessreg/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sessreg
+pkgver=1.0.5
+pkgrel=2
+pkgdesc="manage utmp/wtmp entries for non-init clients"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig xproto"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="00e834c3cbfd990e9d7d5ddc834242df sessreg-1.0.5.tar.bz2"
diff --git a/main/setxkbmap/APKBUILD b/main/setxkbmap/APKBUILD
new file mode 100644
index 0000000000..287586fd52
--- /dev/null
+++ b/main/setxkbmap/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=setxkbmap
+pkgver=1.1.0
+pkgrel=2
+pkgdesc="set the keyboard using the X Keyboard Extension"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig libxkbfile-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr || return 1
+ make || return 1
+ make DESTDIR=""$pkgdir"" install || return 1
+}
+md5sums="2f902e0a89aaf2b19e06e7f26c6efb3a setxkbmap-1.1.0.tar.bz2"
diff --git a/main/sfic/APKBUILD b/main/sfic/APKBUILD
new file mode 100644
index 0000000000..9ac867a902
--- /dev/null
+++ b/main/sfic/APKBUILD
@@ -0,0 +1,37 @@
+pkgdesc="Small and Simple File Integrity Checker"
+pkgname=sfic
+pkgver=0.1.7
+pkgrel=3
+depends=
+arch="all"
+license=GPL
+makedepends="autoconf automake samba-dev"
+depends=
+url=http://sfic.sourceforge.net
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ $pkgname-0.1.7-signal.patch"
+
+subpackages="$pkgname-doc"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 < ../$pkgname-0.1.7-signal.patch || return 1
+ sed -i -e 's/^ /\t/' src/Makefile.am || return 1
+ aclocal
+ autoconf
+ automake --add-missing || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make install DESTDIR="$pkgdir"
+}
+
+md5sums="6197f7a1e8b0fc4887d4573f67b7bb81 sfic-0.1.7.tar.gz
+e0c284f8b4e355b3ea52927fb02e163a sfic-0.1.7-signal.patch"
diff --git a/main/sfic/sfic-0.1.7-signal.patch b/main/sfic/sfic-0.1.7-signal.patch
new file mode 100644
index 0000000000..54538aac1a
--- /dev/null
+++ b/main/sfic/sfic-0.1.7-signal.patch
@@ -0,0 +1,10 @@
+--- sfic-0.1.7.orig/src/sfic.c 2009-04-13 13:25:49.000000000 +0000
++++ sfic-0.1.7/src/sfic.c 2009-04-13 13:26:14.000000000 +0000
+@@ -37,6 +37,7 @@
+ #include <dirent.h>
+ #include <stdarg.h>
+
++#include <signal.h>
+ #include <tdb.h>
+
+ #include "heap.h"
diff --git a/main/sg3_utils/APKBUILD b/main/sg3_utils/APKBUILD
new file mode 100644
index 0000000000..57eaa706ef
--- /dev/null
+++ b/main/sg3_utils/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Carlo Landmeter
+# Maintainer:
+pkgname=sg3_utils
+pkgver=1.30
+pkgrel=1
+pkgdesc="Generic SCSI utilities"
+url="http://sg.danny.cz/sg/sg3_utils.html"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://sg.danny.cz/sg/p/$pkgname-$pkgver.tgz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+md5sums="8acb9328abe17d012db8c5f95f1d7d75 sg3_utils-1.30.tgz"
diff --git a/main/shared-mime-info/APKBUILD b/main/shared-mime-info/APKBUILD
new file mode 100644
index 0000000000..b79e8817a9
--- /dev/null
+++ b/main/shared-mime-info/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=shared-mime-info
+pkgver=0.90
+pkgrel=1
+pkgdesc="Freedesktop.org Shared MIME Info"
+url="http://freedesktop.org/Software/shared-mime-info"
+arch="all"
+license="GPL"
+makedepends="libxml2-dev glib-dev intltool"
+depends=
+install="$pkgname.post-deinstall"
+triggers="$pkgname.trigger:/usr/share/mime"
+subpackages="$pkgname-doc"
+source="http://freedesktop.org/~hadess/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-update-mimedb || return 1
+ make -j1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install
+}
+md5sums="967d68d3890ba3994cfce3adf5b8f15b shared-mime-info-0.90.tar.bz2"
diff --git a/main/shared-mime-info/shared-mime-info.post-deinstall b/main/shared-mime-info/shared-mime-info.post-deinstall
new file mode 100644
index 0000000000..6c3172902d
--- /dev/null
+++ b/main/shared-mime-info/shared-mime-info.post-deinstall
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+cd /usr/share/mime
+rm -rf globs globs2 icons treemagic generic-icons types magic XMLnamespaces \
+ subclasses aliases mime.cache \
+ application audio image inode message model multipart text video \
+ x-content x-epoc
+rmdir /usr/share/mime 2>/dev/null
+
+exit 0
diff --git a/main/shared-mime-info/shared-mime-info.trigger b/main/shared-mime-info/shared-mime-info.trigger
new file mode 100644
index 0000000000..51a3e4953e
--- /dev/null
+++ b/main/shared-mime-info/shared-mime-info.trigger
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in "$@"; do
+ if [ -d "$i" ]; then
+ update-mime-database "$i" > /dev/null 2>&1
+ fi
+done
diff --git a/main/shorewall-common/APKBUILD b/main/shorewall-common/APKBUILD
new file mode 100644
index 0000000000..6843782a79
--- /dev/null
+++ b/main/shorewall-common/APKBUILD
@@ -0,0 +1,22 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=shorewall-common
+pkgver=4.2.10
+pkgrel=1
+pkgdesc="Shoreline Firewall is an iptables-based firewall for Linux."
+url="http://www.shorewall.net/"
+arch="all"
+license="GPL-2"
+depends="iptables iproute2"
+subpackages="$pkgname-doc"
+source="http://www1.shorewall.net/pub/shorewall/4.2/shorewall-$pkgver/shorewall-common-$pkgver.tar.bz2
+ shorewall.initd
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ PREFIX="${pkgdir}" ./install.sh || return 1
+ install -Dm755 "$srcdir"/shorewall.initd "$pkgdir"/etc/init.d/shorewall
+}
+md5sums="49bdbbae8dec65154c4e5538ed3c9865 shorewall-common-4.2.10.tar.bz2
+71fb6da1f50f5c6e9dd35b60b3629531 shorewall.initd"
diff --git a/main/shorewall-common/shorewall.initd b/main/shorewall-common/shorewall.initd
new file mode 100644
index 0000000000..9dda676c57
--- /dev/null
+++ b/main/shorewall-common/shorewall.initd
@@ -0,0 +1,80 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-firewall/shorewall-common/files/shorewall.initd,v 1.2 2008/05/04 13:16:40 pva Exp $
+
+opts="start stop restart clear reset refresh check"
+
+depend() {
+ need net
+ provide firewall
+ after ulogd
+}
+
+start() {
+ ebegin "Starting firewall"
+ /sbin/shorewall -f start 1>/dev/null
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping firewall"
+ /sbin/shorewall stop 1>/dev/null
+ eend $?
+}
+
+restart() {
+ # shorewall comes with its own control script that includes a
+ # restart function, so refrain from calling svc_stop/svc_start
+ # here. Note that this comment is required to fix bug 55576;
+ # runscript.sh greps this script... (09 Jul 2004 agriffis)
+ ebegin "Restarting firewall"
+ /sbin/shorewall status >/dev/null
+ if [ $? != 0 ] ; then
+ svc_start
+ else
+ if [ -f /var/lib/shorewall/restore ] ; then
+ /sbin/shorewall restore
+ else
+ /sbin/shorewall restart 1>/dev/null
+ fi
+ fi
+ eend $?
+}
+
+clear() {
+ # clear will remove all the rules and bring the system to an unfirewalled
+ # state. (21 Nov 2004 eldad)
+
+ ebegin "Clearing all firewall rules and setting policy to ACCEPT"
+ /sbin/shorewall clear
+ eend $?
+}
+
+reset() {
+ # reset the packet and byte counters in the firewall
+
+ ebegin "Resetting the packet and byte counters in the firewall"
+ /sbin/shorewall reset
+ eend $?
+}
+
+refresh() {
+ # refresh the rules involving the broadcast addresses of firewall
+ # interfaces, the black list, traffic control rules and
+ # ECN control rules
+
+ ebegin "Refreshing firewall rules"
+ /sbin/shorewall refresh
+ eend $?
+}
+
+check() {
+ # perform cursory validation of the zones, interfaces, hosts, rules
+ # and policy files. CAUTION: does not parse and validate the generated
+ # iptables commands.
+
+ ebegin "Checking configuration files"
+ /sbin/shorewall check
+ eend $?
+}
diff --git a/main/shorewall-lite/APKBUILD b/main/shorewall-lite/APKBUILD
new file mode 100644
index 0000000000..3c6cb54575
--- /dev/null
+++ b/main/shorewall-lite/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=shorewall-lite
+pkgver=4.2.10
+pkgrel=1
+pkgdesc="An iptables-based firewall whose config is handled by a normal Shorewall"
+url="http://www.shorewall.net/"
+arch="all"
+license="GPL-2"
+depends="iptables iproute2"
+#subpackages="$pkgname-doc"
+source="http://www1.shorewall.net/pub/shorewall/4.2/shorewall-$pkgver/$pkgname-$pkgver.tar.bz2
+ $pkgname.initd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ PREFIX="$pkgdir" ./install.sh || return 1
+ install -Dm755 "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+md5sums="ef5958819ba18801bacfe20e67184f2a shorewall-lite-4.2.10.tar.bz2
+17a37c934aeb601ce288f77000253e1e shorewall-lite.initd"
diff --git a/main/shorewall-lite/shorewall-lite.initd b/main/shorewall-lite/shorewall-lite.initd
new file mode 100755
index 0000000000..d2537e8a12
--- /dev/null
+++ b/main/shorewall-lite/shorewall-lite.initd
@@ -0,0 +1,65 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-firewall/shorewall-lite/files/shorewall-lite,v 1.1 2007/05/20 22:32:36 mjolnir Exp $
+
+opts="start stop restart clear reset refresh"
+
+depend() {
+ need net
+ provide firewall
+ after ulogd
+}
+
+start() {
+ ebegin "Starting firewall"
+ /sbin/shorewall-lite -f start 1>/dev/null
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping firewall"
+ /sbin/shorewall-lite stop 1>/dev/null
+ eend $?
+}
+
+restart() {
+ # shorewall comes with its own control script that includes a
+ # restart function, so refrain from calling svc_stop/svc_start
+ # here. Note that this comment is required to fix bug 55576;
+ # runscript.sh greps this script... (09 Jul 2004 agriffis)
+ ebegin "Restarting firewall"
+ if [ -f /var/lib/shorewall-lite/restore ] ; then
+ /sbin/shorewall-lite restore
+ else
+ /sbin/shorewall-lite restart 1>/dev/null
+ fi
+ eend $?
+}
+
+clear() {
+ # clear will remove all the rules and bring the system to an unfirewalled
+ # state. (21 Nov 2004 eldad)
+
+ ebegin "Clearing all firewall rules and setting policy to ACCEPT"
+ /sbin/shorewall-lite clear
+ eend $?
+}
+
+reset() {
+ # reset the packet and byte counters in the firewall
+
+ ebegin "Resetting the packet and byte counters in the firewall"
+ /sbin/shorewall-lite reset
+ eend $?
+}
+
+refresh() {
+ # refresh the rules involving the broadcast addresses of firewall
+ # interfaces, the black list, traffic control rules and
+ # ECN control rules
+
+ ebegin "Refreshing firewall rules"
+ /sbin/shorewall-lite refresh
+ eend $?
+}
diff --git a/main/shorewall-perl/APKBUILD b/main/shorewall-perl/APKBUILD
new file mode 100644
index 0000000000..985f4101e8
--- /dev/null
+++ b/main/shorewall-perl/APKBUILD
@@ -0,0 +1,17 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=shorewall-perl
+pkgver=4.2.10.5
+_v=4.2.10
+pkgrel=1
+pkgdesc="Shoreline Firewall Perl-based compiler"
+url="http://www.shorewall.net/"
+arch="all"
+license="GPL-2"
+depends="shorewall-common"
+source="http://www1.shorewall.net/pub/shorewall/${_v%.*}/shorewall-${_v}/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ PREFIX="$pkgdir" ./install.sh || return 1
+}
+md5sums="6c94db22ae3d131fbf10a130f59c50b0 shorewall-perl-4.2.10.5.tar.bz2"
diff --git a/main/shorewall-shell/APKBUILD b/main/shorewall-shell/APKBUILD
new file mode 100644
index 0000000000..2806e05715
--- /dev/null
+++ b/main/shorewall-shell/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=shorewall-shell
+_v=4.2.10
+pkgver=4.2.10
+pkgrel=2
+pkgdesc="Shoreline Firewall shell-based compiler."
+url="http://www.shorewall.net/"
+arch="all"
+license="GPL-2"
+depends="shorewall-common"
+#subpackages="$pkgname-doc"
+source="http://www.shorewall.net/pub/shorewall/${_v%.*}/shorewall-$_v/$pkgname-$pkgver.tar.bz2
+ shorewall-policyrouting.patch
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 -i $i || return 1
+ done
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ PREFIX="$pkgdir" ./install.sh || return 1
+}
+
+md5sums="d6f7cbc3c502c09921ede920547d5017 shorewall-shell-4.2.10.tar.bz2
+64c01bc4f57203fb877bb334994eac38 shorewall-policyrouting.patch"
diff --git a/main/shorewall-shell/shorewall-policyrouting.patch b/main/shorewall-shell/shorewall-policyrouting.patch
new file mode 100644
index 0000000000..26399108e3
--- /dev/null
+++ b/main/shorewall-shell/shorewall-policyrouting.patch
@@ -0,0 +1,47 @@
+--- old/lib.providers
++++ new/lib.providers
+@@ -141,7 +141,7 @@
+ # Add Provider $table ($number)
+ #
+ __EOF__
+- save_command "if interface_is_usable $interface; then"
++ save_command "if [ -n \"$interface\" ] && interface_is_usable \"$interface\"; then"
+ save_indent1="$INDENT"
+ INDENT="$INDENT "
+
+@@ -283,7 +283,14 @@
+ INDENT="$save_indent1"
+ save_command else
+
+- if [ -n "$optional" ]; then
++ if [ "${interface:--}" = "-" -a "${duplicate:--}" = "-" -a "${gateway:--}" = "-" -a "${options:--}" = "-" -a "${copy:--}" = "-" ]; then
++ indent >&3 << __EOF__
++
++progress_message " Provider $table ($number) Added"
++
++__EOF__
++
++ elif [ -n "$optional" ]; then
+ save_command " error_message \"WARNING: Interface $interface is not configured -- Provider $table ($number) not Added\""
+ save_command " ${iface}_up="
+ else
+@@ -316,10 +323,6 @@
+ [ "x$source" = x- ] && source=
+ [ "x$dest" = x- ] && dest= || dest="to $dest"
+
+- [ -n "${source}${dest}" ] || fatal_error "You must specify either the source or destination in an rt rule: \"$rule\""
+-
+- [ -n "${dest:=to 0.0.0.0/0}" ]
+-
+ if [ -n "$source" ]; then
+ case $source in
+ *:*)
+@@ -332,8 +335,6 @@
+ source="iif $source"
+ ;;
+ esac
+- else
+- source='from 0.0.0.0/0'
+ fi
+
+ case "$priority" in
diff --git a/main/shorewall/APKBUILD b/main/shorewall/APKBUILD
new file mode 100644
index 0000000000..f9d0d03de5
--- /dev/null
+++ b/main/shorewall/APKBUILD
@@ -0,0 +1,17 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=shorewall
+pkgver=4.2.10
+pkgrel=1
+pkgdesc="Meta package for shorewall"
+url="http://www.shorewall.net/"
+arch="all"
+license="GPL"
+depends="shorewall-shell"
+makedepends=""
+source=""
+
+build() {
+ mkdir -p "$pkgdir"
+}
+
diff --git a/main/shotwell/APKBUILD b/main/shotwell/APKBUILD
new file mode 100644
index 0000000000..c45d7aa73e
--- /dev/null
+++ b/main/shotwell/APKBUILD
@@ -0,0 +1,45 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=shotwell
+pkgver=0.10.1
+pkgrel=0
+pkgdesc="A digital photo organizer designed for the GNOME desktop environment"
+url="http://yorba.org/shotwell/"
+arch="all"
+license="LGPL2.1"
+install="shotwell.post-upgrade shotwell.post-install shotwell.pre-deinstall"
+depends=""
+makedepends="intltool vala libgee-dev libunique-dev webkit-dev libexif-dev
+ librsvg-dev sqlite-dev udev-dev dbus-glib-dev libgphoto2-dev
+ libgexiv2-dev libraw-dev librsvg-dev gconf-dev json-glib-dev
+ gnome-vfs-dev m4"
+install=
+source="http://yorba.org/download/shotwell/${pkgver%.*}/shotwell-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build ()
+{
+ cd $srcdir/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-schemas-install \
+ --disable-desktop-update \
+ --disable-icon-update
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="ef75923257e8554d14a6545c83406700 shotwell-0.10.1.tar.bz2"
diff --git a/main/shotwell/shotwell.post-install b/main/shotwell/shotwell.post-install
new file mode 100644
index 0000000000..e6135da045
--- /dev/null
+++ b/main/shotwell/shotwell.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in shotwell.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/shotwell/shotwell.post-upgrade b/main/shotwell/shotwell.post-upgrade
new file mode 100644
index 0000000000..e6135da045
--- /dev/null
+++ b/main/shotwell/shotwell.post-upgrade
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in shotwell.schemas; do
+ echo "Installing GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-install-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/shotwell/shotwell.pre-deinstall b/main/shotwell/shotwell.pre-deinstall
new file mode 100644
index 0000000000..9d3a000300
--- /dev/null
+++ b/main/shotwell/shotwell.pre-deinstall
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in shotwell.schemas; do
+ echo "Uninstalling GConf2 schema $i."
+ GCONF_CONFIG_SOURCE=`/usr/bin/gconftool-2 --get-default-source` \
+ /usr/bin/gconftool-2 --makefile-uninstall-rule /etc/gconf/schemas/$i >/dev/null
+done
diff --git a/main/sic/APKBUILD b/main/sic/APKBUILD
new file mode 100644
index 0000000000..ed6d403055
--- /dev/null
+++ b/main/sic/APKBUILD
@@ -0,0 +1,24 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sic
+pkgver=1.1
+pkgrel=0
+pkgdesc="an extremely simple IRC client"
+url="http://tools.suckless.org/sic"
+arch="all"
+license="GPL"
+depends=""
+subpackages="$pkgname-doc"
+source="http://dl.suckless.org/tools/sic-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make PREFIX=/usr || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" PREFIX=/usr install
+}
+
+md5sums="856d0e5faa151ae9602713ee7d34a2d5 sic-1.1.tar.gz"
diff --git a/main/sircbot/APKBUILD b/main/sircbot/APKBUILD
new file mode 100644
index 0000000000..95133dd5da
--- /dev/null
+++ b/main/sircbot/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sircbot
+pkgver=0.2
+pkgrel=3
+pkgdesc="Minimalistic IRC bot"
+url="http://git.alpinelinux.org/cgit/sircbot/"
+arch="all"
+license="GPL-2"
+pkgusers="sircbot"
+pkggroups="sircbot"
+depends=
+makedepends="lua-dev"
+install="$pkgname.pre-install"
+subpackages="lua-sircbot:luamod"
+source="http://git.alpinelinux.org/cgit/sircbot.git/snapshot/sircbot-$pkgver.tar.bz2
+ sircbot.initd
+ sircbot.confd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install DESTDIR="$pkgdir" prefix=/usr
+ install -o sircbot -g sircbot -d "$pkgdir"/var/run/sircbot
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+luamod() {
+ pkgdesc="Luamodule for sirbot client"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/lib "$subpkgdir"/usr/
+}
+
+md5sums="a9d16db48c97ebfa30e1c84f37e70838 sircbot-0.2.tar.bz2
+494717b7824e271093511a48955e4a14 sircbot.initd
+8443ac189030c7b8beb8e579dc16ebc7 sircbot.confd"
diff --git a/main/sircbot/sircbot.confd b/main/sircbot/sircbot.confd
new file mode 100644
index 0000000000..63f8590a72
--- /dev/null
+++ b/main/sircbot/sircbot.confd
@@ -0,0 +1,5 @@
+# example:
+# sircbot_opts="-n sircbot -s irc.freenode.net"
+
+sircbot_channels="#sircbot"
+sircbot_opts=""
diff --git a/main/sircbot/sircbot.initd b/main/sircbot/sircbot.initd
new file mode 100644
index 0000000000..045f7ee2aa
--- /dev/null
+++ b/main/sircbot/sircbot.initd
@@ -0,0 +1,35 @@
+#!/sbin/runscript
+
+daemon=/usr/bin/sircbot
+sircbot_user=${sircbot_user:-sircbot}
+sircbot_group=${sircbot_group:-sircbot}
+pidfile=/var/run/sircbot/sircbot.pid
+
+depends() {
+ need net
+ after firewall
+}
+
+checkconfig() {
+ if [ -z "$sircbot_channels" ]; then
+ eerror "Please specify sircbot_channels in /etc/conf.d/sircbot"
+ return 1
+ fi
+ return 0
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting sircbot"
+ start-stop-daemon --start --user $sircbot_user --group $sircbot_group \
+ --umask 0002 --pidfile "$pidfile" \
+ --exec $daemon -- $sircbot_opts $sircbot_channels
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping sircbot"
+ start-stop-daemon --stop --pidfile "$pidfile" --exec $daemon
+ eend $?
+}
+
diff --git a/main/sircbot/sircbot.pre-install b/main/sircbot/sircbot.pre-install
new file mode 100644
index 0000000000..36adc6cce3
--- /dev/null
+++ b/main/sircbot/sircbot.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup sircbot 2>/dev/null
+adduser -h /var/run/sircbot -G sircbot -S -D sircbot 2>/dev/null
+exit 0
diff --git a/main/slang/APKBUILD b/main/slang/APKBUILD
new file mode 100644
index 0000000000..f98a19cdbc
--- /dev/null
+++ b/main/slang/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=slang
+pkgver=2.2.4
+pkgrel=0
+pkgdesc="S-Lang is a powerful interpreted language"
+url="http://www.s-lang.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pcre-dev ncurses-dev"
+source="ftp://ftp.fu-berlin.de/pub/unix/misc/$pkgname/v${pkgver%.*}/$pkgname-$pkgver.tar.gz
+ slang-2.2.3-slsh-libs.patch
+ "
+
+prepare () {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ || return 1
+ make -j1 elf static || return 1
+ cd slsh && make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 install-all DESTDIR="$pkgdir" || return 1
+}
+md5sums="86cd8689cd71e281b4720fef8453ceeb slang-2.2.4.tar.gz
+7f67ad2059a7dd3cad289da97d547521 slang-2.2.3-slsh-libs.patch"
diff --git a/main/slang/slang-2.2.3-slsh-libs.patch b/main/slang/slang-2.2.3-slsh-libs.patch
new file mode 100644
index 0000000000..8f9ff468f5
--- /dev/null
+++ b/main/slang/slang-2.2.3-slsh-libs.patch
@@ -0,0 +1,11 @@
+--- ./slsh/Makefile.in
++++ ./slsh/Makefile.in
+@@ -80,7 +80,7 @@
+ $(OBJDIR)/slsh_exe: $(OBJDIR)/slsh.o $(OBJDIR)/readline.o
+ $(CC) $(CFLAGS) $(OBJDIR)/slsh.o $(OBJDIR)/readline.o -o $(OBJDIR)/slsh_exe $(LDFLAGS) $(SRC_LIBS)
+ $(OBJDIR)/slsh: $(OBJDIR)/slsh.o $(OBJDIR)/readline.o
+- $(CC) $(CFLAGS) $(OBJDIR)/slsh.o $(OBJDIR)/readline.o -o $(OBJDIR)/slsh $(LDFLAGS) $(INST_LIBS)
++ $(CC) $(CFLAGS) $(OBJDIR)/slsh.o $(OBJDIR)/readline.o -o $(OBJDIR)/slsh $(LDFLAGS) $(SRC_LIBS)
+ $(OBJDIR)/slsh.o: $(OBJDIR) slsh.c slsh.h config.h Makefile
+ cd $(OBJDIR) && $(CC) -c $(CFLAGS) $(SLANG_SRCINC) $(DEFS) $(SRCDIR)/slsh.c
+ $(OBJDIR)/readline.o: $(OBJDIR) readline.c slsh.h config.h Makefile
diff --git a/main/slim-themes/APKBUILD b/main/slim-themes/APKBUILD
new file mode 100644
index 0000000000..70c7074d15
--- /dev/null
+++ b/main/slim-themes/APKBUILD
@@ -0,0 +1,65 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=slim-themes
+pkgver=1.2.3
+pkgrel=2
+pkgdesc="Themes Pack for Simple Login Manager"
+url="http://slim.berlios.de"
+arch="all"
+license="GPL"
+depends="slim"
+makedepends=""
+options="!strip"
+source="http://download.berlios.de/slim/slim-$pkgver-themepack1a.tar.gz
+ http://download.berlios.de/slim/slim-lake.tar.gz
+ http://download.berlios.de/slim/slim-fingerprint.tar.gz
+ http://download.berlios.de/slim/slim-flat.tar.gz
+ http://download.berlios.de/slim/slim-lunar-0.4.tar.bz2
+ http://download.berlios.de/slim/slim-previous.tar.gz
+ http://download.berlios.de/slim/slim-rainbow.tar.gz
+ http://download.berlios.de/slim/slim-rear-window.tar.gz
+ http://download.berlios.de/slim/slim-scotland-road.tar.gz
+ http://download.berlios.de/slim/slim-subway.tar.gz
+ http://download.berlios.de/slim/slim-wave.tar.gz
+ http://download.berlios.de/slim/slim-zenwalk.tar.gz
+ http://download.berlios.de/slim/slim-debian-moreblue.tar.bz2
+ http://download.berlios.de/slim/slim-1.3.1.tar.gz"
+
+build ()
+{
+ mkdir -p "$pkgdir"/usr/share/slim/themes
+ cd "$srcdir"/
+ mv fingerprint "$pkgdir"/usr/share/slim/themes
+ mv flat "$pkgdir"/usr/share/slim/themes
+ mv previous "$pkgdir"/usr/share/slim/themes
+ mv lake "$pkgdir"/usr/share/slim/themes
+ mv rainbow "$pkgdir"/usr/share/slim/themes
+ mv rear-window "$pkgdir"/usr/share/slim/themes
+ mv scotland-road "$pkgdir"/usr/share/slim/themes
+ mv subway "$pkgdir"/usr/share/slim/themes
+ mv wave "$pkgdir"/usr/share/slim/themes
+ mv slim-lunar-0.4 "$pkgdir"/usr/share/slim/themes/lunar
+ mv Zenwalk "$pkgdir"/usr/share/slim/themes/zenwalk
+ mv parallel-dimensions "$pkgdir"/usr/share/slim/themes
+ mv capernoited "$pkgdir"/usr/share/slim/themes
+ mv mindlock "$pkgdir"/usr/share/slim/themes
+ mv flower2 "$pkgdir"/usr/share/slim/themes
+ mv debian-moreblue "$pkgdir"/usr/share/slim/themes
+ mv slim-1.3.1/themes/default "$pkgdir"/usr/share/slim/themes
+ cd "$pkgdir"/usr/share/slim/themes
+ find . -type f -exec chmod 644 {} \;
+}
+
+md5sums="fd1295d3a260849790dc17081da4a34f slim-1.2.3-themepack1a.tar.gz
+c0cef9e7b95bdf2df3fb303d155f8476 slim-lake.tar.gz
+2981627a5822a535f3ebd0e21dba9f76 slim-fingerprint.tar.gz
+34696aef39fad7092c80ccf7a38886a5 slim-flat.tar.gz
+6fe38013c6eed67dead507616667ae9a slim-lunar-0.4.tar.bz2
+6e846e8adafa70a7bd0e22d5bd06dc5f slim-previous.tar.gz
+631a00eb27c09b0daa50b88bd9606d07 slim-rainbow.tar.gz
+337876e05b2bdf4bd657d114464ad46a slim-rear-window.tar.gz
+fde18fb892bccc383c93fb7ed07fbe84 slim-scotland-road.tar.gz
+8417022e369be012f1b7a4ee04edf0f9 slim-subway.tar.gz
+c727aab888dde774acc04403c84b5b3b slim-wave.tar.gz
+7a0bd7a0736794e638668769b9c4c745 slim-zenwalk.tar.gz
+5f3818e01b0593d0e576fcd7e2c6bafa slim-debian-moreblue.tar.bz2
+727d0acb24c0fbf0751134c37a9c895f slim-1.3.1.tar.gz"
diff --git a/main/slim/APKBUILD b/main/slim/APKBUILD
new file mode 100644
index 0000000000..55ebe923b4
--- /dev/null
+++ b/main/slim/APKBUILD
@@ -0,0 +1,66 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=slim
+pkgver=1.3.2
+pkgrel=2
+pkgdesc="Desktop-independent graphical login manager for X11"
+url="http://slim.berlios.de/"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-doc"
+makedepends="libxmu-dev libpng-dev jpeg-dev libxft-dev"
+depends=
+install=
+source="http://download.berlios.de/$pkgname/$pkgname-$pkgver.tar.gz
+ http://dev.alpinelinux.org/~ncopa/alpine/slim-alpinelinux.tar.gz
+ $pkgname.logrotate
+ $pkgname.initd
+ slim-restart.patch
+ slim-png15.patch"
+
+prepare() {
+ cd "$srcdir/slim-$pkgver"
+ for i in ../*.patch; do
+ patch -p1 -i $i || return 1
+ done
+
+ #libpng 1.4.0
+ sed -i -e 's/png12/png15/g' Makefile || return 1
+
+ sed -i -e 's|#xserver_arguments.*|xserver_arguments -nolisten tcp vt07|'\
+ -e 's|/var/run/slim.lock|/var/lock/slim.lock|' \
+ -e 's|halt_cmd.*|halt_cmd /sbin/poweroff|'\
+ -e 's|reboot_cmd.*|reboot_cmd /sbin/reboot|'\
+ -e 's|console_cmd.*|console_cmd /usr/bin/terminal|'\
+ -e 's|login_cmd.*|login_cmd exec /bin/sh -l /etc/X11/xinit/xinitrc|' \
+ -e 's|screenshot_cmd.*|screenshot_cmd scrot /slim.png|' \
+ -e 's|imagemagick|scrot|' \
+ -e 's|current_theme.*|current_theme alpinelinux|' \
+ slim.conf || return 1
+}
+
+build() {
+ cd "$srcdir/slim-$pkgver"
+ make CXX="${CXX:-g++}" CC="${CC:-gcc}" || return 1
+}
+
+package() {
+ cd "$srcdir/slim-$pkgver"
+ make DESTDIR="$pkgdir" MANDIR=/usr/share/man install || return 1
+
+ install -D -m755 ../slim.initd "$pkgdir"/etc/init.d/slim || return 1
+ install -D -m644 ../slim.logrotate "$pkgdir"/etc/logrotate.d/slim
+
+ # install our default theme
+ cd "$srcdir"/slim-alpinelinux
+ install -d "$pkgdir"/usr/share/slim/themes/alpinelinux
+ cp background.png panel.png slim.theme \
+ "$pkgdir"/usr/share/slim/themes/alpinelinux/
+ rm -rf "$pkgdir"/usr/share/slim/themes/default
+}
+
+md5sums="ca1ae6120e6f4b4969f2d6cf94f47b42 slim-1.3.2.tar.gz
+cd63232c7770b0e67a009a94c2a46b82 slim-alpinelinux.tar.gz
+43da096480bf72c3ccec8ad8400f34f0 slim.logrotate
+6ee3a023e56052528295034be809cfc6 slim.initd
+648d871fe7d2a97b7d7b928019e2feee slim-restart.patch
+8f63afd7cd390cb8d65f10fb167d4a71 slim-png15.patch"
diff --git a/main/slim/slim-1.3.1-gcc4.4.patch b/main/slim/slim-1.3.1-gcc4.4.patch
new file mode 100644
index 0000000000..5708d70717
--- /dev/null
+++ b/main/slim/slim-1.3.1-gcc4.4.patch
@@ -0,0 +1,17 @@
+Patch to allow compilation with gcc-4.4
+
+Notified by Daniel J. - from Debian bug tracker
+
+http://bugs.gentoo.org/252745
+
+--- a/switchuser.h 2008-11-11 19:40:18.000000000 +0000
++++ b/switchuser.h 2008-11-11 19:40:28.000000000 +0000
+@@ -18,6 +18,7 @@
+ #include <pwd.h>
+ #include <grp.h>
+ #include <paths.h>
++#include <cstdio>
+ #include <iostream>
+ #include "const.h"
+ #include "cfg.h"
+
diff --git a/main/slim/slim-png15.patch b/main/slim/slim-png15.patch
new file mode 100644
index 0000000000..25caaed576
--- /dev/null
+++ b/main/slim/slim-png15.patch
@@ -0,0 +1,11 @@
+--- slim-1.3.2.orig/png.c
++++ slim-1.3.2/png.c
+@@ -57,7 +57,7 @@
+ return(0);
+ }
+
+- if (setjmp(png_ptr->jmpbuf))
++ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
+ fclose(infile);
diff --git a/main/slim/slim-restart.patch b/main/slim/slim-restart.patch
new file mode 100644
index 0000000000..1f9c02dfff
--- /dev/null
+++ b/main/slim/slim-restart.patch
@@ -0,0 +1,141 @@
+diff -ur slim-1.3.1.orig/app.cpp slim-1.3.1/app.cpp
+--- slim-1.3.1.orig/app.cpp 2008-09-26 02:54:15.000000000 +0200
++++ slim-1.3.1/app.cpp 2008-11-21 20:38:48.000000000 +0100
+@@ -102,6 +102,11 @@
+
+ extern App* LoginApp;
+
++int xioerror(Display *disp) {
++ LoginApp->RestartServer();
++ return 0;
++}
++
+ void CatchSignal(int sig) {
+ cerr << APPNAME << ": unexpected signal " << sig << endl;
+ LoginApp->StopServer();
+@@ -109,19 +114,6 @@
+ exit(ERR_EXIT);
+ }
+
+-
+-void AlarmSignal(int sig) {
+- int pid = LoginApp->GetServerPID();
+- if(waitpid(pid, NULL, WNOHANG) == pid) {
+- LoginApp->StopServer();
+- LoginApp->RemoveLock();
+- exit(OK_EXIT);
+- }
+- signal(sig, AlarmSignal);
+- alarm(2);
+-}
+-
+-
+ void User1Signal(int sig) {
+ signal(sig, User1Signal);
+ }
+@@ -267,7 +259,6 @@
+ signal(SIGHUP, CatchSignal);
+ signal(SIGPIPE, CatchSignal);
+ signal(SIGUSR1, User1Signal);
+- signal(SIGALRM, AlarmSignal);
+
+ #ifndef XNEST_DEBUG
+ OpenLog();
+@@ -287,7 +278,6 @@
+
+ CreateServerAuth();
+ StartServer();
+- alarm(2);
+ #endif
+
+ }
+@@ -603,6 +593,8 @@
+ int status;
+ while (wpid != pid) {
+ wpid = wait(&status);
++ if (wpid == ServerPID)
++ xioerror(Dpy); // Server died, simulate IO error
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status)) {
+ LoginPanel->Message("Failed to execute login command");
+@@ -648,9 +640,6 @@
+
+
+ void App::Reboot() {
+- // Stop alarm clock
+- alarm(0);
+-
+ #ifdef USE_PAM
+ try{
+ pam.end();
+@@ -673,9 +662,6 @@
+
+
+ void App::Halt() {
+- // Stop alarm clock
+- alarm(0);
+-
+ #ifdef USE_PAM
+ try{
+ pam.end();
+@@ -761,6 +747,7 @@
+
+ StopServer();
+ RemoveLock();
++ while (waitpid(-1, NULL, WNOHANG) > 0); // Collects all dead childrens
+ Run();
+ }
+
+@@ -831,6 +818,7 @@
+
+ for(cycles = 0; cycles < ncycles; cycles++) {
+ if((Dpy = XOpenDisplay(DisplayName))) {
++ XSetIOErrorHandler(xioerror);
+ return 1;
+ } else {
+ if(!ServerTimeout(1, (char *) "X server to begin accepting connections"))
+@@ -913,9 +901,6 @@
+ ServerPID = -1;
+ break;
+ }
+- alarm(15);
+- pause();
+- alarm(0);
+
+ // Wait for server to start up
+ if(WaitForServer() == 0) {
+@@ -948,15 +933,12 @@
+
+
+ void App::StopServer() {
+- // Stop alars clock and ignore signals
+- alarm(0);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGKILL, SIG_DFL);
+- signal(SIGALRM, SIG_DFL);
+
+ // Catch X error
+ XSetIOErrorHandler(IgnoreXIO);
+diff -ur slim-1.3.1.orig/app.h slim-1.3.1/app.h
+--- slim-1.3.1.orig/app.h 2008-09-26 02:54:15.000000000 +0200
++++ slim-1.3.1/app.h 2008-11-21 20:38:48.000000000 +0100
+@@ -34,6 +34,7 @@
+ ~App();
+ void Run();
+ int GetServerPID();
++ void RestartServer();
+ void StopServer();
+
+ // Lock functions
+@@ -48,7 +49,6 @@
+ void Console();
+ void Exit();
+ void KillAllClients(Bool top);
+- void RestartServer();
+ void ReadConfig();
+ void OpenLog();
+ void CloseLog();
diff --git a/main/slim/slim.initd b/main/slim/slim.initd
new file mode 100755
index 0000000000..4ab113b6b0
--- /dev/null
+++ b/main/slim/slim.initd
@@ -0,0 +1,18 @@
+#!/sbin/runscript
+
+depends() {
+ needs localmount
+}
+
+start() {
+ ebegin "Starting slim"
+ start-stop-daemon --start --quiet --exec /usr/bin/slim -- -d
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping slim"
+ start-stop-daemon --stop --quiet --exec /usr/bin/slim
+ eend $?
+}
+
diff --git a/main/slim/slim.install b/main/slim/slim.install
new file mode 100644
index 0000000000..45eb02fa13
--- /dev/null
+++ b/main/slim/slim.install
@@ -0,0 +1,7 @@
+post_install() {
+ cat << _EOF
+
+ Add slim to the DAEMONS array in /etc/rc.conf or update /etc/inittab.
+
+_EOF
+}
diff --git a/main/slim/slim.logrotate b/main/slim/slim.logrotate
new file mode 100644
index 0000000000..26ec3b0f42
--- /dev/null
+++ b/main/slim/slim.logrotate
@@ -0,0 +1,9 @@
+/var/log/slim.log {
+ compress
+ rotate 1
+ size 1024k
+ notifempty
+ missingok
+ copytruncate
+ noolddir
+}
diff --git a/main/smokeping/APKBUILD b/main/smokeping/APKBUILD
new file mode 100644
index 0000000000..827da56bf9
--- /dev/null
+++ b/main/smokeping/APKBUILD
@@ -0,0 +1,112 @@
+# Contributor: Jeff Bilyk <jbilyk at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=smokeping
+pkgver=2.4.2
+pkgrel=2
+pkgdesc="Smokeping network latency monitoring"
+pkgusers="smokeping"
+pkggroups="smokeping"
+install="$pkgname.pre-install"
+url="http://oss.oetiker.ch/smokeping/"
+source="http://oss.oetiker.ch/smokeping/pub/smokeping-$pkgver.tar.gz
+ smokeping.initd"
+depends="perl fping rrdtool perl-rrd
+ perl-uri-escape
+ perl-digest-hmac
+ perl-cgi-session
+ perl-libwww
+ perl-snmp-session
+ perl-net-dns
+ "
+arch="all"
+license="GPL"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+_vendorlib=/usr/share/perl5/vendor_perl
+
+prepare() {
+ cd "$_builddir"
+ # provided by perl-digest-hmac
+ rm -rf lib/Digest
+ # provided by perl-cgi-session
+ rm -rf lib/CGI
+ # provided by perl-snmp-session
+ rm -r lib/BER.pm lib/SNMP_Session.pm lib/SNMP_util.pm
+ rm -r qooxdoo/qooxdoolink
+}
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+
+ # create dirs
+ mkdir -p "$pkgdir"/etc/smokeping \
+ "$pkgdir"/usr/bin \
+ "$pkgdir"/usr/share/webapps/smokeping \
+ "$pkgdir"/$_vendorlib
+
+ # install libs
+ cp -ra "$_builddir"/lib/* "$pkgdir"/$_vendorlib
+
+ # install cgi scripts
+ for i in smokeping.cgi tr.cgi; do
+ sed -i -e 's:^use lib:#use lib:' \
+ -e 's:/home/oetiker.*/config.dist:/etc/smokeping/config:' \
+ -e '1s:.*:#!/usr/bin/perl:' \
+ htdocs/$i.dist || return 1
+ mv htdocs/$i.dist \
+ "$pkgdir"/usr/share/webapps/smokeping/$i \
+ || return 1
+ done
+
+ # install ajax scripts
+ mv "$_builddir/htdocs"/* "$pkgdir"/usr/share/webapps/smokeping
+
+ # install smokeping executables
+ for i in smokeping tSmoke; do
+ sed -e 's:^use lib:#use lib:g' \
+ -e 's:etc/config.dist:/etc/smokeping/config:' \
+ -i bin/$i.dist
+ install -m755 bin/$i.dist "$pkgdir"/usr/bin/$i
+ done
+
+ # config
+ sed -e '/^imgcache/{s:\(^imgcache[ \t]*=\).*:\1 /var/lib/smokeping/.simg:}' \
+ -e '/^imgurl/{s:\(^imgurl[ \t]*=\).*:\1 ../.simg:}' \
+ -e '/^datadir/{s:\(^datadir[ \t]*=\).*:\1 /var/lib/smokeping:}' \
+ -e '/^piddir/{s:\(^piddir[ \t]*=\).*:\1 /var/run/smokeping:}' \
+ -e '/^cgiurl/{s#\(^cgiurl[ \t]*=\).*#\1 http://some.place.xyz/perl/smokeping.pl#}' \
+ -e '/^smokemail/{s:\(^smokemail[ \t]*=\).*:\1 /etc/smokeping/smokemail:}' \
+ -e '/^tmail/{s:\(^tmail[ \t]*=\).*:\1 /etc/smokeping/tmail:}' \
+ -e '/^secrets/{s:\(^secrets[ \t]*=\).*:\1 /etc/smokeping/smokeping_secrets:}' \
+ -e '/^template/{s:\(^template[ \t]*=\).*:\1 /etc/smokeping/basepage.html:}' \
+ -e '/^sendmail/{s:usr/lib:usr/sbin:}' \
+ -i etc/config.dist || return 1
+
+ sed -e '/^<script/{s:cropper/:/cropper/:}' \
+ -i etc/basepage.html.dist \
+ || return 1
+
+ for i in etc/*; do
+ local f=${i##*/}
+ install -m644 "$i" "$pkgdir"/etc/smokeping/${f%.dist}
+ done
+
+ chmod 700 "$pkgdir"/etc/smokeping/smokeping_secrets
+
+ # initscript
+ install -Dm755 "$srcdir"/smokeping.initd "$pkgdir"/etc/init.d/smokeping\
+ || return 1
+
+ install -d -o smokeping -g smokeping -m755 \
+ "$pkgdir"/var/lib/smokeping \
+ "$pkgdir"/var/lib/smokeping/.simg \
+ "$pkgdir"/var/run/smokeping
+
+}
+
+md5sums="eb8e7679fcad35e59d7c51f2328250a2 smokeping-2.4.2.tar.gz
+550979e008f49299bf404aceeb81fe61 smokeping.initd"
diff --git a/main/smokeping/smokeping.initd b/main/smokeping/smokeping.initd
new file mode 100644
index 0000000000..068f33ff25
--- /dev/null
+++ b/main/smokeping/smokeping.initd
@@ -0,0 +1,77 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+opts="${opts} dump reload restore"
+
+depend() {
+ need net
+ use dns
+}
+
+checkconfig() {
+ if [ ! -f "/etc/smokeping/config" ] ; then
+ eerror "You need /etc/smokeping/config to run smokeping!"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+
+ if [ ! -d /var/run/smokeping/ ]; then
+ mkdir /var/run/smokeping/
+ fi
+ chown smokeping:smokeping /var/run/smokeping/
+
+ ebegin "Starting smokeping"
+ LC_ALL=C \
+ start-stop-daemon --start --name smokeping \
+ --pidfile /var/run/smokeping/smokeping.pid \
+ --exec /usr/bin/smokeping \
+ --chuid smokeping:smokeping
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping smokeping"
+ start-stop-daemon --stop \
+ --pidfile /var/run/smokeping/smokeping.pid
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading smokeping"
+ /usr/bin/smokeping --reload 1>/dev/null 2>&1
+ eend $?
+}
+
+dump() {
+ ebegin "Dumping smokeping rrd files to XML for backup or upgrade use"
+ if service_started "${myservice}" ; then
+ eerror "You need to stop smokeping before dumping files!"
+ return 1
+ fi
+ for f in `find /var/lib/smokeping -name '*.rrd' -print` ; do
+ f_xml=`dirname $f`/`basename $f .rrd`.xml
+ rrdtool dump "$f" > "${f_xml}"
+ chown root:0 "${f_xml}"
+ done
+ eend $?
+}
+
+restore() {
+ ebegin "Restoring smokeping rrd files from XML dump files"
+ if service_started "${myservice}" ; then
+ eerror "You need to stop smokeping before restoring files!"
+ return 1
+ fi
+ for f in `find /var/lib/smokeping -name '*.xml' -print` ; do
+ f_rrd=`dirname $f`/`basename $f .xml`.rrd
+ mv -f "${f_rrd}" "${f_rrd}.bak"
+ chown root:0 "${f_rrd}.bak"
+ rrdtool restore "$f" "${f_rrd}"
+ chown smokeping:smokeping "${f_rrd}"
+ done
+ eend $?
+}
diff --git a/main/smokeping/smokeping.pre-install b/main/smokeping/smokeping.pre-install
new file mode 100644
index 0000000000..236550f7c1
--- /dev/null
+++ b/main/smokeping/smokeping.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup smokeping 2>/dev/null
+adduser -h /var/lib/smokeping -S -D -G smokeping smokeping 2>/dev/null
+exit 0
diff --git a/main/snmptt/APKBUILD b/main/snmptt/APKBUILD
new file mode 100644
index 0000000000..a41719aa71
--- /dev/null
+++ b/main/snmptt/APKBUILD
@@ -0,0 +1,29 @@
+# Contributor: Jeff Bilyk <jbilyk at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=snmptt
+pkgver=1.3
+pkgrel=1
+pkgdesc="Translates traps received from snmptrapd into easy to understand messages"
+url="http://www.snmptt.org"
+arch="all"
+license="GPL"
+depends=perl
+makedepends=
+install=
+source="http://downloads.sourceforge.net/$pkgname/${pkgname}_$pkgver.tgz"
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$srcdir"/snmptt_${pkgver}
+ mkdir -p "$pkgdir"/var/log/snmptt
+ install -D -m755 snmptt "$pkgdir"/usr/bin/snmptt
+ install -D -m755 snmptthandler "$pkgdir"/usr/bin/snmptthandler
+ install -D -m755 snmpttconvert "$pkgdir"/usr/bin/snmpttconvert
+ install -D -m755 snmpttconvertmib "$pkgdir"/usr/bin/snmpttconvertmib
+ install -D -m644 snmptt.ini "$pkgdir"/etc/snmptt.ini
+}
+
+md5sums="ee8d8206d3e0d860fee126e09d8eb207 snmptt_1.3.tgz"
diff --git a/main/snort/APKBUILD b/main/snort/APKBUILD
new file mode 100644
index 0000000000..4f58dd625a
--- /dev/null
+++ b/main/snort/APKBUILD
@@ -0,0 +1,47 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=snort
+pkgver=2.9.0.5
+pkgrel=0
+pkgdesc="An open source network intrusion prevention and detection system"
+url="http://www.snort.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="pcre-dev libpcap-dev libnet-dev libdnet-dev daq-dev
+ autoconf automake libtool bison flex"
+install="$pkgname.pre-install"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://www.snort.org/dl/snort-current/snort-$pkgver.tar.gz
+ snort.initd
+ snort.confd
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ # fix parallel builds
+ sed -i -e 's/^all-local:.*/all-local: $(LTLIBRARIES)/' \
+ src/dynamic-preprocessors/*/Makefile.am || return 1
+ aclocal -I m4 && autoconf && automake --add-missing && libtoolize || return 1
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-ipv6 \
+ --enable-gre
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+
+ install -D -m 755 ../snort.initd "$pkgdir"/etc/init.d/snort
+ install -D -m 644 ../snort.confd "$pkgdir"/etc/conf.d/snort
+}
+
+md5sums="a7e6f0b013f767d09c99f8f91757e355 snort-2.9.0.5.tar.gz
+ffda56f7c20f5cea1c37c971e0f1d6c9 snort.initd
+446f8d2b3435b8a6be738da978670605 snort.confd"
diff --git a/main/snort/snort.confd b/main/snort/snort.confd
new file mode 100644
index 0000000000..d4d240ac96
--- /dev/null
+++ b/main/snort/snort.confd
@@ -0,0 +1,16 @@
+# Config file for /etc/init.d/snort
+
+# This tell snort which interface to listen on (any for every interface)
+IFACE=eth0
+
+# Make sure this matches your IFACE
+PIDFILE=/var/run/snort_$IFACE.pid
+
+# You probably don't want to change this, but in case you do
+LOGDIR="/var/log/snort"
+
+# Probably not this either
+CONF=/etc/snort/snort.conf
+
+# This pulls in the options above
+SNORT_OPTS="-D -u snort -i $IFACE -l $LOGDIR -c $CONF"
diff --git a/main/snort/snort.initd b/main/snort/snort.initd
new file mode 100644
index 0000000000..baed2dff2e
--- /dev/null
+++ b/main/snort/snort.initd
@@ -0,0 +1,32 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-analyzer/snort/files/snort.rc7,v 1.3 2007/04/22 06:21:15 dragonheart Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+checkconfig() {
+ if [ ! -e $CONF ] ; then
+ eerror "You need a configuration file to run snort"
+ eerror "There is an example config in /etc/snort/snort.conf.distrib"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting snort"
+ start-stop-daemon --start --quiet --exec /usr/bin/snort \
+ --pidfile ${PIDFILE} \
+ -- ${SNORT_OPTS} >/dev/null 2>&1
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping snort"
+ start-stop-daemon --stop --quiet --pidfile ${PIDFILE}
+ eend $?
+}
diff --git a/main/snort/snort.pre-install b/main/snort/snort.pre-install
new file mode 100644
index 0000000000..e1555163a7
--- /dev/null
+++ b/main/snort/snort.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -h /var/log/snort -s /bin/false -D snort 2>/dev/null
+exit 0
diff --git a/main/snowfox/APKBUILD b/main/snowfox/APKBUILD
new file mode 100644
index 0000000000..7d43938cf9
--- /dev/null
+++ b/main/snowfox/APKBUILD
@@ -0,0 +1,101 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=snowfox
+pkgver=4.0
+_pkgver=4.0
+_xulver=2.0
+pkgrel=0
+pkgdesc="firefox web browser (unofficial branding; patched)"
+url="http://www.firefox.com"
+arch="all"
+license="GPL LGPL MPL"
+depends="xulrunner"
+makedepends="xulrunner-dev>=${_xulver}
+
+ nspr-dev
+ nss-dev
+ gtk+-dev
+ dbus-glib-dev
+ alsa-lib-dev
+ libvorbis-dev
+ libogg-dev
+ libtheora-dev
+ wireless-tools-dev
+ libnotify-dev
+ libevent-dev
+ libxt-dev
+ jpeg-dev
+ bzip2-dev
+ hunspell-dev
+ startup-notification-dev
+ sqlite-dev
+ libidl-dev
+
+ autoconf2.13
+
+ python
+ zip
+ yasm
+
+ autoconf
+ automake
+ libtool"
+install=""
+subpackages=""
+source="http://releases.mozilla.org/pub/mozilla.org/${pkgname}/releases/${pkgver}/source/firefox-${_pkgver}.source.tar.bz2
+ mozconfig
+
+ firefox-restore-fx3-tab-behaviour-as-default.patch
+ firefox-restore-status-bar.patch
+ firefox-defaults.patch
+ firefox-version.patch
+
+ firefox.desktop
+ firefox-safe.desktop"
+
+_xulrunner_version="2.0"
+_builddir="${srcdir}/mozilla-${_xulrunner_version}"
+prepare() {
+ local i
+
+ cd "$_builddir"
+
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ cp "${srcdir}/mozconfig" .mozconfig
+}
+
+build() {
+ cd "$_builddir"
+
+ # mozilla's buildsystem is on drugs, so we just kill our CFLAGS and hope
+ # for the best. --nenolod
+ unset CFLAGS
+ unset CXXFLAGS
+
+ make -j1 -f client.mk build MOZ_MAKE_FLAGS="$MAKEFLAGS" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" -f client.mk install || return 1
+
+ install -m755 -d ${pkgdir}/usr/share/applications
+ install -m755 -d ${pkgdir}/usr/share/pixmaps
+ install -m644 ${srcdir}/mozilla-2.0/browser/branding/unofficial/default48.png ${pkgdir}/usr/share/pixmaps/firefox.png
+ install -m644 ${srcdir}/firefox.desktop ${pkgdir}/usr/share/applications/firefox.desktop
+ install -m644 ${srcdir}/firefox-safe.desktop ${pkgdir}/usr/share/applications/firefox-safe.desktop
+}
+
+md5sums="3468a2c463b4fc2788ba621e4b511c30 firefox-4.0.source.tar.bz2
+d1ec45f9d953a868483094cce2b3eff5 mozconfig
+7cddbb1c76b9038ad1d85311dda81c95 firefox-restore-fx3-tab-behaviour-as-default.patch
+a153133cfe74ce269e1e80925e48544c firefox-restore-status-bar.patch
+475a0870730c88f48158a4d4ca9812d0 firefox-defaults.patch
+0e296aabf8c2b5fd5ef5b3a989bab03a firefox-version.patch
+ba96924ece1d77453e462429037a2ce5 firefox.desktop
+6f38a5899034b7786cb1f75ad42032b8 firefox-safe.desktop"
diff --git a/main/snowfox/firefox-agent.patch b/main/snowfox/firefox-agent.patch
new file mode 100644
index 0000000000..299f327e24
--- /dev/null
+++ b/main/snowfox/firefox-agent.patch
@@ -0,0 +1,12 @@
+diff -Nur mozilla-1.9.2.orig/browser/app/profile/firefox.js mozilla-1.9.2/browser/app/profile/firefox.js
+--- mozilla-1.9.2.orig/browser/app/profile/firefox.js 2010-04-14 01:21:35.000000000 +0300
++++ mozilla-1.9.2/browser/app/profile/firefox.js 2010-04-21 00:16:59.673528609 +0300
+@@ -183,7 +183,7 @@
+
+ pref("general.useragent.locale", "@AB_CD@");
+ pref("general.skins.selectedSkin", "classic/1.0");
+-pref("general.useragent.extra.firefox", "@APP_UA_NAME@/@APP_VERSION@");
++pref("general.useragent.extra.firefox", "Firefox/@APP_VERSION@");
+
+ pref("general.smoothScroll", false);
+ #ifdef UNIX_BUT_NOT_MAC
diff --git a/main/snowfox/firefox-defaults.patch b/main/snowfox/firefox-defaults.patch
new file mode 100644
index 0000000000..cce60cd5de
--- /dev/null
+++ b/main/snowfox/firefox-defaults.patch
@@ -0,0 +1,22 @@
+diff -Nur mozilla-1.9.2.old//browser/branding/unofficial/pref/firefox-branding.js mozilla-1.9.2/browser/branding/unofficial/pref/firefox-branding.js
+--- mozilla-1.9.2.old//browser/branding/unofficial/pref/firefox-branding.js 2010-04-14 01:21:35.000000000 +0300
++++ mozilla-1.9.2/browser/branding/unofficial/pref/firefox-branding.js 2010-04-20 23:55:01.290102941 +0300
+@@ -1,5 +1,5 @@
+-pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
+-pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
++pref("startup.homepage_override_url","http://www.mozilla.com/%APP%/%VERSION%/whatsnew/");
++pref("startup.homepage_welcome_url","http://www.mozilla.com/%APP%/%VERSION%/firstrun/");
+ pref("browser.panorama.welcome_url", "http://www.mozilla.com/firefox/panorama/");
+ // The time interval between checks for a new version (in seconds)
+ // nightly=8 hours, official=24 hours
+@@ -14,7 +14,7 @@
+ pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
+
+ // Release notes and vendor URLs
+-pref("app.releaseNotesURL", "http://www.mozilla.org/projects/%APP%/%VERSION%/releasenotes/");
+-pref("app.vendorURL", "http://www.mozilla.org/projects/%APP%/");
++pref("app.releaseNotesURL", "http://www.mozilla.com/%APP%/%VERSION%/releasenotes/");
++pref("app.vendorURL", "http://www.mozilla.com/%APP%/");
+
+ // Search codes belong only in builds with official branding
+ pref("browser.search.param.yahoo-fr", "");
diff --git a/main/snowfox/firefox-restore-fx3-tab-behaviour-as-default.patch b/main/snowfox/firefox-restore-fx3-tab-behaviour-as-default.patch
new file mode 100644
index 0000000000..a9102a65ba
--- /dev/null
+++ b/main/snowfox/firefox-restore-fx3-tab-behaviour-as-default.patch
@@ -0,0 +1,11 @@
+--- mozilla-2.0.orig/browser/base/content/browser.xul
++++ mozilla-2.0/browser/base/content/browser.xul
+@@ -470,7 +470,7 @@
+ #else
+ iconsize="large"
+ #endif
+- tabsontop="true"
++ tabsontop="false"
+ persist="tabsontop">
+ <!-- Menu -->
+ <toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
diff --git a/main/snowfox/firefox-restore-status-bar.patch b/main/snowfox/firefox-restore-status-bar.patch
new file mode 100644
index 0000000000..f492abb59d
--- /dev/null
+++ b/main/snowfox/firefox-restore-status-bar.patch
@@ -0,0 +1,37 @@
+--- mozilla-2.0.orig/browser/base/content/browser.xul
++++ mozilla-2.0/browser/base/content/browser.xul
+@@ -992,12 +992,18 @@
+ contentcontextmenu="contentAreaContextMenu"
+ autocompletepopup="PopupAutoComplete"
+ onclick="return contentAreaClick(event, false);"/>
+- <statuspanel id="statusbar-display" label=""/>
+ </vbox>
+ <vbox id="browser-border-end" hidden="true" layer="true"/>
+ </hbox>
+
+ <vbox id="browser-bottombox" layer="true">
++ <statusbar id="status-bar" ordinal="1000"
++#ifdef WINCE
++ hidden="true"
++#endif
++ class="chromeclass-status">
++ <statusbarpanel id="statusbar-display" label=""/>
++ </statusbar>
+ <toolbar id="addon-bar"
+ toolbarname="&addonBarCmd.label;" accesskey="&addonBarCmd.accesskey;"
+ collapsed="true"
+@@ -1005,13 +1011,12 @@
+ context="toolbar-context-menu" toolboxid="navigator-toolbox"
+ mode="icons" iconsize="small" defaulticonsize="small"
+ lockiconsize="true"
+- defaultset="addonbar-closebutton,spring,status-bar"
++ defaultset="addonbar-closebutton,spring"
+ customizable="true"
+ key="key_toggleAddonBar">
+ <toolbarbutton id="addonbar-closebutton"
+ tooltiptext="&addonBarCloseButton.tooltip;"
+ oncommand="setToolbarVisibility(this.parentNode, false);"/>
+- <statusbar id="status-bar" ordinal="1000"/>
+ </toolbar>
+ </vbox>
+
diff --git a/main/snowfox/firefox-safe.desktop b/main/snowfox/firefox-safe.desktop
new file mode 100644
index 0000000000..1538fc6748
--- /dev/null
+++ b/main/snowfox/firefox-safe.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+Exec=firefox -safe-mode %u
+Icon=firefox
+Type=Application
+Terminal=false
+MultipleArgs=false
+Name=Firefox - Safe Mode
+GenericName=Web Browser - Safe Mode
+StartupNotify=false
+Categories=Network;WebBrowser;
diff --git a/main/snowfox/firefox-version.patch b/main/snowfox/firefox-version.patch
new file mode 100644
index 0000000000..2b1aeb41d3
--- /dev/null
+++ b/main/snowfox/firefox-version.patch
@@ -0,0 +1,11 @@
+--- mozilla-2.0.orig/browser/installer/Makefile.in 2009-07-18 13:32:35.000000000 +0200
++++ mozilla-2.0/browser/installer/Makefile.in 2009-07-18 13:33:12.000000000 +0200
+@@ -43,6 +43,8 @@
+
+ include $(DEPTH)/config/autoconf.mk
+
++MOZ_APP_VERSION="3.6"
++
+ include $(topsrcdir)/config/rules.mk
+
+ MOZ_PKG_REMOVALS = $(srcdir)/removed-files.in
diff --git a/main/snowfox/firefox.desktop b/main/snowfox/firefox.desktop
new file mode 100644
index 0000000000..d048ce46c3
--- /dev/null
+++ b/main/snowfox/firefox.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Exec=firefox %u
+Icon=firefox
+Type=Application
+Terminal=false
+Name=Firefox
+Name[bn]=ফায়ারফকà§à¦¸3
+Name[eo]=Fajrovulpo3
+Name[fi]=Firefox3
+Name[pa]=ਫਾਇਰਫੋਕਸ3
+Name[tg]=Рӯбоҳи оташин3
+GenericName=Web Browser
+GenericName[af]=Web Blaaier
+GenericName[ar]=متصÙØ­ ويب
+GenericName[az]=Veb Səyyahı
+GenericName[bg]=Браузър
+GenericName[bn]=ওয়েব বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°
+GenericName[br]=Furcher ar Gwiad
+GenericName[bs]=WWW Preglednik
+GenericName[ca]=Fullejador web
+GenericName[cs]=WWW prohlížeÄ
+GenericName[cy]=Porydd Gwe
+GenericName[da]=Browser
+GenericName[de]=Web-Browser
+GenericName[el]=ΠεÏιηγητής ΙστοÏ
+GenericName[eo]=TTT-legilo
+GenericName[es]=Navegador web
+GenericName[et]=Veebilehitseja
+GenericName[eu]=Web arakatzailea
+GenericName[fa]=مرورگر وب
+GenericName[fi]=WWW-selain
+GenericName[fo]=Alnótsfar
+GenericName[fr]=Navigateur web
+GenericName[gl]=Navegador Web
+GenericName[he]=דפדפן ×ינטרנט
+GenericName[hi]=वेब बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤°
+GenericName[hr]=Web preglednik
+GenericName[hu]=Webböngésző
+GenericName[is]=Vafri
+GenericName[it]=Browser Web
+GenericName[ja]=ウェブブラウザ
+GenericName[ko]=웹 브ë¼ìš°ì €
+GenericName[lo]=ເວັບບຣາວເຊີ
+GenericName[lt]=Žiniatinklio naršyklė
+GenericName[lv]=Web PÄrlÅ«ks
+GenericName[mk]=ПрелиÑтувач на Интернет
+GenericName[mn]=Веб-Хөтөч
+GenericName[nb]=Nettleser
+GenericName[nds]=Nettkieker
+GenericName[nl]=Webbrowser
+GenericName[nn]=Nettlesar
+GenericName[nso]=Seinyakisi sa Web
+GenericName[pa]=ਵੈਬ à¨à¨²à¨•à¨¾à¨°à¨¾
+GenericName[pl]=PrzeglÄ…darka WWW
+GenericName[pt]=Navegador Web
+GenericName[pt_BR]=Navegador Web
+GenericName[ro]=Navigator de web
+GenericName[ru]=Веб-браузер
+GenericName[se]=Fierpmádatlogan
+GenericName[sk]=Webový prehliadaÄ
+GenericName[sl]=Spletni brskalnik
+GenericName[sr]=Веб претраживач
+GenericName[sr@Latn]=Veb pretraživaÄ
+GenericName[ss]=Ibrawuza yeWeb
+GenericName[sv]=Webbläsare
+GenericName[ta]=வலை உலாவி
+GenericName[tg]=ТафÑиргари вÑб
+GenericName[th]=เว็บบราวเซอร์
+GenericName[tr]=Web Tarayıcı
+GenericName[uk]=Ðавігатор Тенет
+GenericName[uz]=Веб-браузер
+GenericName[ven]=Buronza ya Webu
+GenericName[vi]=Trình duyệt Web
+GenericName[wa]=Betchteu waibe
+GenericName[xh]=Umkhangeli zincwadi we Web
+GenericName[zh_CN]=网页æµè§ˆå™¨
+GenericName[zh_TW]=網é ç€è¦½å™¨
+GenericName[zu]=Umcingi we-Web
+MimeType=text/html;
+StartupNotify=true
+Categories=Network;WebBrowser;
diff --git a/main/snowfox/mozconfig b/main/snowfox/mozconfig
new file mode 100644
index 0000000000..e68be73fac
--- /dev/null
+++ b/main/snowfox/mozconfig
@@ -0,0 +1,36 @@
+. $topsrcdir/browser/config/mozconfig
+
+ac_add_options --prefix=/usr
+ac_add_options --libdir=/usr/lib
+ac_add_options --with-system-nspr
+ac_add_options --with-system-nss
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-zlib
+ac_add_options --with-pthreads
+ac_add_options --disable-tests
+ac_add_options --disable-debug
+ac_add_options --enable-optimize
+ac_add_options --disable-installer
+ac_add_options --enable-xinerama
+ac_add_options --enable-default-toolkit=cairo-gtk2
+ac_add_options --disable-xprint
+ac_add_options --enable-strip
+ac_add_options --enable-pango
+ac_add_options --enable-svg
+ac_add_options --enable-canvas
+ac_add_options --enable-startup-notification
+ac_add_options --enable-libxul
+ac_add_options --disable-crashreporter
+ac_add_options --disable-updater
+ac_add_options --with-libxul-sdk=/usr/lib/xulrunner-devel-1.9.2
+ac_add_options --enable-safe-browsing
+ac_add_options --with-branding=browser/branding/unofficial
+ac_add_options --enable-chrome-format=jar
+
+export BUILD_OFFICIAL=1
+export MOZILLA_OFFICIAL=1
+export USE_SHORT_LIBNAME=1
+
+mk_add_options BUILD_OFFICIAL=1
+mk_add_options MOZILLA_OFFICIAL=1
+mk_add_options USE_SHORT_LIBNAME=1
diff --git a/main/sntpc/APKBUILD b/main/sntpc/APKBUILD
new file mode 100644
index 0000000000..9c561a8984
--- /dev/null
+++ b/main/sntpc/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sntpc
+pkgver=0.9
+pkgrel=3
+pkgdesc="Simple NTP client"
+url="http://git.alpinelinux.org/cgit/sntpc"
+arch="all"
+license="GPL-2"
+depends=
+source="http://git.alpinelinux.org/cgit/sntpc.git/snapshot/sntpc-$pkgver.tar.bz2
+ sntpc.initd
+ sntpc.confd
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make || return 1
+ install -m755 -D sntpc "$pkgdir"/usr/sbin/sntpc
+ install -m755 -D "$srcdir"/sntpc.initd "$pkgdir"/etc/init.d/sntpc
+ install -m644 -D "$srcdir"/sntpc.confd "$pkgdir"/etc/conf.d/sntpc
+}
+
+md5sums="60c64d975daa3a6f371e9e81538e38db sntpc-0.9.tar.bz2
+1e542e12cf6eeff7140ddbd9dde1066a sntpc.initd
+4ea1ceee01f94080be86188bde8f9adc sntpc.confd"
diff --git a/main/sntpc/sntpc.confd b/main/sntpc/sntpc.confd
new file mode 100644
index 0000000000..a92e4be868
--- /dev/null
+++ b/main/sntpc/sntpc.confd
@@ -0,0 +1,9 @@
+#
+# Set time sync interval (in seconds) here.
+# Setting SNTPC_INTERVAL to 0 will make sntp run once and just exit
+#
+
+SNTPC_INTERVAL="0"
+
+# The NTP server to use as time source
+SNTPC_HOST=pool.ntp.org
diff --git a/main/sntpc/sntpc.initd b/main/sntpc/sntpc.initd
new file mode 100644
index 0000000000..a62c6d3527
--- /dev/null
+++ b/main/sntpc/sntpc.initd
@@ -0,0 +1,31 @@
+#!/sbin/runscript
+
+NAME=sntpc
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ local msg opts
+ if [ "$SNTPC_INTERVAL" = "0" ]; then
+ msg="Setting time from NTP source"
+ else
+ msg="Starting ${NAME}"
+ opts="-d"
+ fi
+ ebegin "$msg"
+ start-stop-daemon --start --quiet --name sntpc \
+ --exec ${DAEMON} -- \
+ -i ${SNTPC_INTERVAL} $opts ${SNTPC_HOST}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --exec ${DAEMON}
+ eend $?
+}
diff --git a/main/socat/APKBUILD b/main/socat/APKBUILD
new file mode 100644
index 0000000000..652bf808d6
--- /dev/null
+++ b/main/socat/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Kiyoshi Aman <kiyoshi.aman@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=socat
+pkgver=1.7.1.3
+pkgrel=1
+pkgdesc="Multipurpose relay for binary protocols"
+url="http://www.dest-unreach.org/socat/"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev readline-dev"
+subpackages="$pkgname-doc"
+source="http://www.dest-unreach.org/$pkgname/download/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+doc() {
+ default_doc
+ mkdir -p "$subpkgdir"/usr/share/socat/
+ install -m644 "$_builddir"/EXAMPLES "$_builddir"/doc/*.html "$_builddir"/doc/*.css "$subpkgdir"/usr/share/"$pkgname"/
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="2081987fb0cb0290b8105574058cb329 socat-1.7.1.3.tar.bz2"
diff --git a/main/sox/APKBUILD b/main/sox/APKBUILD
new file mode 100644
index 0000000000..f6c3e80828
--- /dev/null
+++ b/main/sox/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sox
+pkgver=14.3.2
+pkgrel=1
+pkgdesc="The Swiss Army knife of sound processing tools"
+url="http://sox.sourceforge.net/"
+arch="all"
+license="GPL LGPL"
+makedepends="ffmpeg-dev libao-dev libvorbis-dev libogg-dev lame-dev
+ libmad-dev bash alsa-lib-dev libsndfile-dev libsamplerate-dev
+ libtool file-dev libid3tag-dev flac-dev"
+depends=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.gz
+ sox-uclibc.patch
+ sox-ffmpeg-0.8.patch
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --with-dyn-default \
+ --with-distro="Alpine Linux" || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ ln -sf play "$pkgdir"/usr/bin/rec || return 1
+ ln -sf ../man1/sox.1.gz "$pkgdir"/usr/share/man/man7/soxeffect.7 || return 1
+ rm "$pkgdir"/usr/lib/*.la \
+ "$pkgdir"/usr/lib/sox/*.a \
+ "$pkgdir"/usr/lib/sox/*.la \
+}
+md5sums="e9d35cf3b0f8878596e0b7c49f9e8302 sox-14.3.2.tar.gz
+d8267f718ba6b4fb2f48c5104af31364 sox-uclibc.patch
+f99f0c37c31dd103921292a1d89ad266 sox-ffmpeg-0.8.patch"
diff --git a/main/sox/sox-ffmpeg-0.8.patch b/main/sox/sox-ffmpeg-0.8.patch
new file mode 100644
index 0000000000..74b8cacdff
--- /dev/null
+++ b/main/sox/sox-ffmpeg-0.8.patch
@@ -0,0 +1,38 @@
+--- ./src/ffmpeg.c.orig
++++ ./src/ffmpeg.c
+@@ -91,7 +91,7 @@
+
+ if (!codec || avcodec_open(enc, codec) < 0)
+ return -1;
+- if (enc->codec_type != CODEC_TYPE_AUDIO) {
++ if (enc->codec_type != AVMEDIA_TYPE_AUDIO) {
+ lsx_fail("ffmpeg CODEC %x is not an audio CODEC", enc->codec_type);
+ return -1;
+ }
+@@ -182,7 +182,7 @@
+ /* Find audio stream (FIXME: allow different stream to be selected) */
+ for (i = 0; (unsigned)i < ffmpeg->ctxt->nb_streams; i++) {
+ AVCodecContext *enc = ffmpeg->ctxt->streams[i]->codec;
+- if (enc->codec_type == CODEC_TYPE_AUDIO && ffmpeg->audio_index < 0) {
++ if (enc->codec_type == AVMEDIA_TYPE_AUDIO && ffmpeg->audio_index < 0) {
+ ffmpeg->audio_index = i;
+ break;
+ }
+@@ -273,7 +273,7 @@
+
+ c = st->codec;
+ c->codec_id = codec_id;
+- c->codec_type = CODEC_TYPE_AUDIO;
++ c->codec_type = AVMEDIA_TYPE_AUDIO;
+
+ /* put sample parameters */
+ c->bit_rate = 256000; /* FIXME: allow specification */
+@@ -423,7 +423,7 @@
+ av_init_packet(&pkt);
+ pkt.size = avcodec_encode_audio(c, ffmpeg->audio_buf_aligned, AVCODEC_MAX_AUDIO_FRAME_SIZE, ffmpeg->samples);
+ pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, ffmpeg->audio_st->time_base);
+- pkt.flags |= PKT_FLAG_KEY;
++ pkt.flags |= AV_PKT_FLAG_KEY;
+ pkt.stream_index = ffmpeg->audio_st->index;
+ pkt.data = ffmpeg->audio_buf_aligned;
+
diff --git a/main/sox/sox-uclibc.patch b/main/sox/sox-uclibc.patch
new file mode 100644
index 0000000000..fb78cd0968
--- /dev/null
+++ b/main/sox/sox-uclibc.patch
@@ -0,0 +1,22 @@
+diff --git a/src/formats.c b/src/formats.c
+index 556f611..6c2c5b0 100644
+--- a/src/formats.c
++++ b/src/formats.c
+@@ -395,7 +395,7 @@ static void UNUSED rewind_pipe(FILE * fp)
+ #if defined _NEWLIB_VERSION || defined __APPLE__
+ fp->_p -= AUTO_DETECT_SIZE;
+ fp->_r += AUTO_DETECT_SIZE;
+-#elif defined __GLIBC__
++#elif defined __GLIBC__ && ! defined __UCLIBC__
+ fp->_IO_read_ptr = fp->_IO_read_base;
+ #elif defined _MSC_VER || defined __MINGW_H || defined _ISO_STDIO_ISO_H
+ fp->_ptr = fp->_base;
+@@ -403,7 +403,7 @@ static void UNUSED rewind_pipe(FILE * fp)
+ /* To fix this #error, either simply remove the #error line and live without
+ * file-type detection with pipes, or add support for your compiler in the
+ * lines above. Test with cat monkey.au | ./sox --info - */
+- #error FIX NEEDED HERE
++/* #error FIX NEEDED HERE */
+ #define NO_REWIND_PIPE
+ (void)fp;
+ #endif
diff --git a/main/spamassassin/APKBUILD b/main/spamassassin/APKBUILD
new file mode 100644
index 0000000000..d062c8193a
--- /dev/null
+++ b/main/spamassassin/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=spamassassin
+_realname=Mail-SpamAssassin
+pkgver=3.3.1
+pkgrel=8
+pkgdesc="The Powerful #1 Open-Source Spam Filter"
+url="http://spamassassin.apache.org"
+arch="all"
+license="Apache"
+depends="gnupg perl perl-digest-sha1 perl-io-compress perl-time-hires
+ perl-netaddr-ip perl-mail-dkim perl-html-parser perl-net-dns
+ perl-db_file perl-libwww perl-uri"
+makedepends="perl-dev zlib-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://www.apache.org/dist/spamassassin/source/$_realname-$pkgver.tar.gz
+ spamassassin-3.3.1-PERL-5-12.patch"
+
+prepare() {
+ cd "$srcdir/$_realname-$pkgver"
+ patch -p2 < ../spamassassin-3.3.1-PERL-5-12.patch || return 1
+}
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make
+}
+
+package() {
+ cd "$srcdir/$_realname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ install -m755 -D ../../spamd.init $pkgdir/etc/init.d/spamd
+ install -m644 -D ../../spamd.conf $pkgdir/etc/conf.d/spamd.conf
+ mkdir $pkgdir/usr/sbin
+ mv $pkgdir/usr/bin/spamd $pkgdir/usr/sbin/spamd
+ # creates file collision among perl modules
+ find "$pkgdir" -name perllocal.pod -delete
+}
+
+md5sums="5a93f81fda315411560ff5da099382d2 Mail-SpamAssassin-3.3.1.tar.gz
+aea0b415deb2a827c50653dafb80d6e4 spamassassin-3.3.1-PERL-5-12.patch"
diff --git a/main/spamassassin/spamassassin-3.2.5-DESTDIR.patch b/main/spamassassin/spamassassin-3.2.5-DESTDIR.patch
new file mode 100644
index 0000000000..a9765fc55d
--- /dev/null
+++ b/main/spamassassin/spamassassin-3.2.5-DESTDIR.patch
@@ -0,0 +1,273 @@
+--- Mail-SpamAssassin-3.2.5/Makefile.PL.old 2009-10-21 23:25:18.000000000 +0200
++++ Mail-SpamAssassin-3.2.5/Makefile.PL 2009-10-21 23:31:28.000000000 +0200
+@@ -12,12 +12,12 @@
+
+ # avoid stupid 'Argument "6.30_01" isn't numeric in numeric ge (>=)' warnings;
+ # strip off the beta subversion noise that causes the trouble.
+ $mm_version =~ s/_\S+$//; # "6.30_01" => "6.30"
+
+-if ($mm_version+0 < 5.45) {
+- die "SpamAssassin Makefile.PL requires at least ExtUtils::MakeMaker v5.45";
++if ($mm_version < 6.17) {
++ die "SpamAssassin Makefile.PL requires at least ExtUtils::MakeMaker v6.17";
+ }
+
+ use constant RUNNING_ON_WINDOWS => ($^O =~ /^(mswin|dos|os2)/oi);
+ use constant HAS_DBI => eval { require DBI; };
+
+@@ -82,11 +82,10 @@
+ );
+
+
+ sub parse_arg {
+ my($val, $name) = (@_);
+-
+ if ($val =~ /^($name)=["']?(.*?)["']?$/) {
+ return $2;
+ } else {
+ return undef;
+ }
+@@ -107,53 +106,27 @@
+ return 'yes' if bool($val, $def);
+ return 'no';
+ }
+
+
+-
+ my %opt = (
+- 'build_spamc' => undef,
++ 'build_spamc' => undef,
+ 'enable_ssl' => undef,
+ 'contact_address' => undef,
+ 'destdir' => undef,
+ );
+ ARGV: foreach (@ARGV) {
+ foreach my $key (keys %opt) {
+- my $val;
+-
+- $val = parse_arg($_, uc($key));
++ my $val = parse_arg($_, uc($key));
+ if (defined $val) {
+ $opt{$key} = $val;
+ next ARGV;
+ }
+ }
+ }
+
+
+-# Gather some information about what EU::MM offers and/or needs
+-my(
+- $mm_knows_destdir,
+- $mm_has_destdir,
+- $mm_has_good_destdir,
+- $mm_needs_destdir,
+-);
+-
+-# MakeMaker prior to 6.11 doesn't support DESTDIR which is needed for
+-# packaging with builddir!=destdir. See bug 2388.
+-$mm_knows_destdir = $ExtUtils::MakeMaker::Recognized_Att_Keys{DESTDIR};
+-$mm_has_good_destdir = $mm_version >= 6.11;
+-# Add DESTDIR hack only if it's requested (and necessary)
+-$mm_needs_destdir = $opt{'destdir'} && !$mm_has_good_destdir;
+-$mm_has_destdir = $mm_knows_destdir || $mm_needs_destdir;
+-push(@ATT_KEYS, 'DESTDIR') if $mm_needs_destdir;
+-
+-# Now make EU::MM understand our extended vars
+-foreach my $key (@ATT_KEYS) {
+- $ExtUtils::MakeMaker::Recognized_Att_Keys{$key} = 1;
+-}
+-
+-
+ # Gather the rules files in the range 00-69; we do this in perl because
+ # it's more portable. Also, plugin .pm files.
+ my @datafiles = map { s,^rules/,,; $_ }
+ grep { -f $_ } (<rules/*.cf>, <rules/*.pm>);
+ my $datafiles = join(' ', (grep
+@@ -270,75 +243,27 @@
+
+ # We have only this Makefile.PL and this option keeps MakeMaker from
+ # asking all questions twice after a 'make dist*'.
+ 'NORECURS' => 1,
+
+- # bug 5074: perl 5.6.1 (with ExtUtils::MakeMaker 5.45) attempts to
+- # recurse anyway unless this is explicitly specified
+- 'DIR' => [ ],
+-
+ # Don't add META.yml to the MANIFEST for god's sake!
+ 'NO_META' => 1,
+ );
+
+ # rules/72_active.cf is built from "rulesrc", but *must* exist before
+ # WriteMakefile() is called due to shortcomings in MakeMaker.
+ my @FILES_THAT_MUST_EXIST = qw(
+ rules/72_active.cf
+ );
+
+-# That META.yml stuff was introduced with Perl 6.06_03, see
+-# <http://archive.develooper.com/makemaker@perl.org/msg00922.html>
+-# <http://archive.develooper.com/makemaker@perl.org/msg00984.html>
+-delete $makefile{'NO_META'} if $mm_version < 6.06_03;
+-
+ # make sure certain optional modules are up-to-date if they are installed
+ # also see PREREQ_PM above
+ my %CURRENT_PM = (
+ 'Net::DNS' => (RUNNING_ON_WINDOWS ? 0.46 : 0.34),
+ 'Razor2::Client::Agent' => 2.40,
+ );
+
+-if ($mm_needs_destdir) {
+- my $error = <<DESTDIR_HACK;
+-
+- ***********************************************************************
+- ExtUtils::MakeMaker ${mm_version} doesn't include support for DESTDIR,
+- so if you want to be on the safe side, you might want to upgrade your
+- ExtUtils::MakeMaker to version 6.11 or later. It is available via CPAN.
+-
+- You can use either the CPAN shell or go to
+- <http://search.cpan.org/search?module=ExtUtils::MakeMaker>
+- to get an up-to-date version.
+-
+- This should only be necessary if you are creating binary packages.
+- ***********************************************************************
+-
+-DESTDIR_HACK
+- $error =~ s/^ {4}//gm;
+- warn $error;
+-}
+-elsif ($opt{'destdir'} and !$mm_has_good_destdir) {
+- my $error = <<DESTDIR_BUG;
+-
+- ***********************************************************************
+- ExtUtils::MakeMaker ${mm_version} contains bugs that may cause problems
+- in the \"make\" process. It is recommended that you upgrade
+- ExtUtils::MakeMaker to version 6.11 or later. It is available via CPAN.
+-
+- You can use either the CPAN shell or go to
+- <http://search.cpan.org/search?module=ExtUtils::MakeMaker>
+- to get an up-to-date version.
+-
+- This should only be necessary if you are creating binary packages.
+- ***********************************************************************
+-
+-DESTDIR_BUG
+- $error =~ s/^ {4}//gm;
+- warn $error;
+-}
+-
+
+ # All the $(*MAN1*) stuff is empty/zero if Perl was Configured with -Dman1dir=none;
+ # however, support site/vendor man1 dirs (bug 5338)
+ unless($Config{installman1dir}
+ || $Config{installsiteman1dir}
+@@ -405,22 +330,19 @@
+
+ # Now finish the meta hash and dump the Makefile
+ $makefile{EXE_FILES} = [ values %{$makefile{EXE_FILES}} ];
+ $makefile{AUTHOR} =~ s/(<.+) at (.+>)/$1\@$2/;
+ WriteMakefile(%makefile);
+-print "Makefile written by ExtUtils::MakeMaker ${mm_version}\n";
++print "Makefile written by ExtUtils::MakeMaker $mm_version\n";
+
+ #######################################################################
+
+ package MY;
+
+-
+ use vars qw(
+ $MY_GLOBALS_ARE_SANE
+-
+ $RUNNING_ON_WINDOWS
+-
+ @REPOSITORIES
+
+ $MACRO_RE
+ $EQ_RE
+ $EQ
+@@ -906,19 +828,10 @@
+ init_MY_globals($self);
+
+ foreach (@code) {
+ # Add our install targets as a dependency to all top-level install targets
+ s/^(install(?:_[a-z]+)?\s*::?\s*.*)$/$1 conf__install data__install/;
+-
+- # Now do the DESTDIR hack, if necessary.
+- next if !$mm_needs_destdir;
+- # Write the correct path to perllocal.pod
+- next if /installed into/;
+-
+- # Replace all other $(INSTALL*) vars (except $(INSTALLDIRS) of course)
+- # with their $(DESTINSTALL*) counterparts
+- s/\Q$(\E(INSTALL(?!DIRS)${MACRO_RE})\Q)\E/\$(DEST$1)/g;
+ }
+
+ clean_MY_globals($self);
+ return join("\n", @code);
+ }
+@@ -956,32 +869,10 @@
+ set_macro($rprefix, macro_ref('PREFIX'));
+ $line .= "\n" . macro_def($rprefix);
+ }
+ }
+ }
+-
+- if (line_has_macro_def($line, 'MM_VERSION')) {
+- # These macros are just for debugging purposes.
+- $line = join("\n", $line,
+- macro_def(MM_HAS_DESTDIR => ::yesno($mm_has_destdir)),
+- macro_def(MM_HAS_GOOD_DESTDIR => ::yesno($mm_has_good_destdir)),
+- macro_def(MM_KNOWS_DESTDIR => ::yesno($mm_knows_destdir)),
+- macro_def(MM_NEEDS_DESTDIR => ::yesno($mm_needs_destdir)),
+- );
+- }
+-
+- # Add DESTDIR support if necessary
+- if ($mm_needs_destdir) {
+- if (line_has_macro_def($line, 'INSTALLDIRS')) {
+- $line .= "\n" . macro_def('DESTDIR');
+- }
+- elsif (line_has_macro_def($line, qr/INSTALL${MACRO_RE}/)) {
+- my $macro = get_macro_name_from_line($line);
+- $line .= "\n" . macro_def('DEST' . $macro,
+- macro_ref('DESTDIR') . macro_ref($macro));
+- }
+- }
+ }
+ push(@code, qq{});
+
+ # Add some additional target dirs
+ {
+@@ -1015,13 +906,11 @@
+ foreach my $r (@REPOSITORIES) {
+ my $macro = 'INSTALL' . repository($r) . $m;
+ # The INSTALL* macros.
+ push(@code, macro_def($macro));
+ # The DESTINSTALL* macros.
+- push(@code, macro_def('DEST' . $macro,
+- macro_ref('DESTDIR') . macro_ref($macro)))
+- if $mm_has_destdir;
++ push(@code, macro_def('DEST' . $macro, macro_ref('DESTDIR') . macro_ref($macro)));
+ }
+ }
+ }
+
+ # Set the PERL_* stuff
+@@ -1068,17 +957,12 @@
+ # SCRIPT macro is the same for all repositories.
+ foreach my $macro (qw(SCRIPT DATA CONF LIB)) {
+ push(@code, macro_def('I_' . $macro . 'DIR',
+ macro_ref('INSTALL' . repository($repository, $macro eq 'SCRIPT') . $macro)));
+
+- if ($mm_has_destdir) {
+- push(@code, macro_def('B_' . $macro . 'DIR',
+- macro_ref('DESTINSTALL' . repository($repository, $macro eq 'SCRIPT') . $macro)));
+- } else {
+- push(@code, macro_def('B_' . $macro . 'DIR',
+- macro_ref('I_' . $macro . 'DIR')));
+- }
++ push(@code, macro_def('B_' . $macro . 'DIR',
++ macro_ref('DESTINSTALL' . repository($repository, $macro eq 'SCRIPT') . $macro)));
+ }
+ }
+
+ clean_MY_globals($self);
+ return join("\n", @code);
diff --git a/main/spamassassin/spamassassin-3.3.1-PERL-5-12.patch b/main/spamassassin/spamassassin-3.3.1-PERL-5-12.patch
new file mode 100644
index 0000000000..5b4039c4d5
--- /dev/null
+++ b/main/spamassassin/spamassassin-3.3.1-PERL-5-12.patch
@@ -0,0 +1,240 @@
+diff -ur a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Dns.pm b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Dns.pm
+--- a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Dns.pm 2010-03-16 10:49:21.000000000 -0400
++++ b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Dns.pm 2010-07-20 15:54:23.000000000 -0400
+@@ -754,7 +754,7 @@
+ dbg("dns: entering helper-app run mode");
+ $self->{old_slash} = $/; # Razor pollutes this
+ %{$self->{old_env}} = ();
+- if ( defined %ENV ) {
++ if ( %ENV ) {
+ # undefined values in %ENV can result due to autovivification elsewhere,
+ # this prevents later possible warnings when we restore %ENV
+ while (my ($key, $value) = each %ENV) {
+Only in b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin: Dns.pm~
+diff -ur a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/HTML.pm b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/HTML.pm
+--- a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/HTML.pm 2010-03-16 10:49:21.000000000 -0400
++++ b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/HTML.pm 2010-07-20 15:52:50.000000000 -0400
+@@ -191,7 +191,7 @@
+ my $self = shift;
+ my %options = @_;
+
+- return join('', @{ $self->{text} }) unless keys %options;
++ return join('', @{ $self->{text} }) unless %options;
+
+ my $mask;
+ while (my ($k, $v) = each %options) {
+Only in b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin: HTML.pm~
+diff -ur a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/BodyEval.pm b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/BodyEval.pm
+--- a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/BodyEval.pm 2010-03-16 10:49:21.000000000 -0400
++++ b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/BodyEval.pm 2010-07-20 16:04:57.000000000 -0400
+@@ -119,7 +119,7 @@
+ }
+
+ # If there are no words, mark if there's at least 1 image ...
+- if (keys %html == 0 && exists $pms->{html}{inside}{img}) {
++ if (!%html && exists $pms->{html}{inside}{img}) {
+ # Use "\n" as the mark since it can't ever occur normally
+ $html{"\n"}=1;
+ }
+Only in b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin: BodyEval.pm~
+Only in b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin: check.patch
+diff -ur a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/Check.pm b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/Check.pm
+--- a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/Check.pm 2010-03-16 10:49:21.000000000 -0400
++++ b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/Check.pm 2010-07-20 16:03:00.000000000 -0400
+@@ -307,64 +307,51 @@
+ my $package_name = __PACKAGE__;
+ my $methodname = $package_name."::_".$ruletype."_tests_".$clean_priority;
+
+- if (defined &{$methodname} && !$doing_user_rules) {
+-run_compiled_method:
+- # dbg("rules: run_generic_tests - calling %s", $methodname);
+- my $t = Mail::SpamAssassin::Timeout->new({ deadline => $master_deadline });
+- my $err = $t->run(sub {
+- no strict "refs";
+- $methodname->($pms, @{$opts{args}});
+- });
+- if ($t->timed_out() && $master_deadline && time > $master_deadline) {
+- info("check: exceeded time limit in $methodname, skipping further tests");
+- $pms->{deadline_exceeded} = 1;
+- }
+- return;
+- }
++ if (!defined &{$methodname} || $doing_user_rules) {
+
+- # use %nopts for named parameter-passing; it's more friendly to future-proof
+- # subclassing, since new parameters can be added without breaking third-party
+- # subclassed implementations of this plugin.
+- my %nopts = (
+- ruletype => $ruletype,
+- doing_user_rules => $doing_user_rules,
+- priority => $priority,
+- clean_priority => $clean_priority
+- );
+-
+- # build up the eval string...
+- $self->{evalstr_methodname} = $methodname;
+- $self->{evalstr_chunk_current_methodname} = undef;
+- $self->{evalstr_chunk_methodnames} = [];
+- $self->{evalstr_chunk_prefix} = []; # stack (array) of source code sections
+- $self->{evalstr} = ''; $self->{evalstr_l} = 0;
+- $self->{evalstr2} = '';
+- $self->begin_evalstr_chunk($pms);
+-
+- $self->push_evalstr_prefix($pms, '
+- # start_rules_plugin_code '.$ruletype.' '.$priority.'
+- my $scoresptr = $self->{conf}->{scores};
+- ');
+- if (defined $opts{pre_loop_body}) {
+- $opts{pre_loop_body}->($self, $pms, $conf, %nopts);
+- }
+- $self->add_evalstr($pms,
+- $self->start_rules_plugin_code($ruletype, $priority) );
+- while (my($rulename, $test) = each %{$opts{testhash}->{$priority}}) {
+- $opts{loop_body}->($self, $pms, $conf, $rulename, $test, %nopts);
+- }
+- if (defined $opts{post_loop_body}) {
+- $opts{post_loop_body}->($self, $pms, $conf, %nopts);
+- }
++ # use %nopts for named parameter-passing; it's more friendly
++ # to future-proof subclassing, since new parameters can be added without
++ # breaking third-party subclassed implementations of this plugin.
++ my %nopts = (
++ ruletype => $ruletype,
++ doing_user_rules => $doing_user_rules,
++ priority => $priority,
++ clean_priority => $clean_priority
++ );
++
++ # build up the eval string...
++ $self->{evalstr_methodname} = $methodname;
++ $self->{evalstr_chunk_current_methodname} = undef;
++ $self->{evalstr_chunk_methodnames} = [];
++ $self->{evalstr_chunk_prefix} = []; # stack (array) of source code sections
++ $self->{evalstr} = ''; $self->{evalstr_l} = 0;
++ $self->{evalstr2} = '';
++ $self->begin_evalstr_chunk($pms);
++
++ $self->push_evalstr_prefix($pms, '
++ # start_rules_plugin_code '.$ruletype.' '.$priority.'
++ my $scoresptr = $self->{conf}->{scores};
++ ');
++ if (defined $opts{pre_loop_body}) {
++ $opts{pre_loop_body}->($self, $pms, $conf, %nopts);
++ }
++ $self->add_evalstr($pms,
++ $self->start_rules_plugin_code($ruletype, $priority) );
++ while (my($rulename, $test) = each %{$opts{testhash}->{$priority}}) {
++ $opts{loop_body}->($self, $pms, $conf, $rulename, $test, %nopts);
++ }
++ if (defined $opts{post_loop_body}) {
++ $opts{post_loop_body}->($self, $pms, $conf, %nopts);
++ }
+
+- $self->flush_evalstr($pms, 'run_generic_tests');
+- $self->free_ruleset_source($pms, $ruletype, $priority);
++ $self->flush_evalstr($pms, 'run_generic_tests');
++ $self->free_ruleset_source($pms, $ruletype, $priority);
+
+- # clear out a previous version of this method
+- undef &{$methodname};
++ # clear out a previous version of this method
++ undef &{$methodname};
+
+- # generate the loop that goes through each line...
+- my $evalstr = <<"EOT";
++ # generate the loop that goes through each line...
++ my $evalstr = <<"EOT";
+ {
+ package $package_name;
+
+@@ -373,40 +360,51 @@
+ sub $methodname {
+ EOT
+
+- for my $chunk_methodname (@{$self->{evalstr_chunk_methodnames}}) {
+- $evalstr .= " $chunk_methodname(\@_);\n";
+- }
++ for my $chunk_methodname (@{$self->{evalstr_chunk_methodnames}}) {
++ $evalstr .= " $chunk_methodname(\@_);\n";
++ }
+
+- $evalstr .= <<"EOT";
++ $evalstr .= <<"EOT";
+ }
+
+ 1;
+ }
+ EOT
+
+- delete $self->{evalstr}; # free up some RAM before we eval()
+- delete $self->{evalstr2};
+- delete $self->{evalstr_methodname};
+- delete $self->{evalstr_chunk_current_methodname};
+- delete $self->{evalstr_chunk_methodnames};
+- delete $self->{evalstr_chunk_prefix};
+-
+- dbg("rules: run_generic_tests - compiling eval code: %s, priority %s",
+- $ruletype, $priority);
+-# dbg("rules: eval code to compile: $evalstr");
+- my $eval_result;
+- { my $timer = $self->{main}->time_method('compile_gen');
+- $eval_result = eval($evalstr);
+- }
+- if (!$eval_result) {
+- my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
+- warn "rules: failed to compile $ruletype tests, skipping:\n".
+- "\t($eval_stat)\n";
+- $pms->{rule_errors}++;
+- }
+- else {
++ delete $self->{evalstr}; # free up some RAM before we eval()
++ delete $self->{evalstr2};
++ delete $self->{evalstr_methodname};
++ delete $self->{evalstr_chunk_current_methodname};
++ delete $self->{evalstr_chunk_methodnames};
++ delete $self->{evalstr_chunk_prefix};
++
++ dbg("rules: run_generic_tests - compiling eval code: %s, priority %s",
++ $ruletype, $priority);
++ # dbg("rules: eval code to compile: $evalstr");
++ my $eval_result;
++ { my $timer = $self->{main}->time_method('compile_gen');
++ $eval_result = eval($evalstr);
++ }
++ if (!$eval_result) {
++ my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
++ warn "rules: failed to compile $ruletype tests, skipping:\n".
++ "\t($eval_stat)\n";
++ $pms->{rule_errors}++;
++ return;
++ }
+ dbg("rules: compiled $ruletype tests");
+- goto run_compiled_method;
++ }
++
++#run_compiled_method:
++# dbg("rules: run_generic_tests - calling %s", $methodname);
++ my $t = Mail::SpamAssassin::Timeout->new({ deadline => $master_deadline });
++ my $err = $t->run(sub {
++ no strict "refs";
++ $methodname->($pms, @{$opts{args}});
++ });
++ if ($t->timed_out() && $master_deadline && time > $master_deadline) {
++ info("check: exceeded time limit in $methodname, skipping further tests");
++ $pms->{deadline_exceeded} = 1;
+ }
+ }
+
+diff -ur a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/MIMEEval.pm b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/MIMEEval.pm
+--- a/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/MIMEEval.pm 2010-03-16 10:49:21.000000000 -0400
++++ b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin/MIMEEval.pm 2010-07-20 16:06:47.000000000 -0400
+@@ -498,7 +498,7 @@
+ # perhaps just limit to test, and image?
+ next if ($ctype eq 'application/ics');
+
+- my $cte = lc $p->get_header('content-transfer-encoding') || '';
++ my $cte = lc($p->get_header('content-transfer-encoding') || '');
+ next if ($cte !~ /^base64$/);
+ foreach my $l ( @{$p->raw()} ) {
+ my $len = length $l;
+Only in b/Mail-SpamAssassin-3.3.1/lib/Mail/SpamAssassin/Plugin: MIMEEval.pm~
diff --git a/main/spamassassin/spamd.conf b/main/spamassassin/spamd.conf
new file mode 100644
index 0000000000..b6fca036f2
--- /dev/null
+++ b/main/spamassassin/spamd.conf
@@ -0,0 +1,46 @@
+# Config file for /etc/init.d/spamd
+
+
+# ***WARNING***
+# spamd was not designed to listed to an untrusted network. spamd
+# is vulnerable to DoS attacks (and eternal doom) if used to listen
+# to an untrusted network.
+#
+
+
+# Some options:
+#
+# -c to create a per user configuration file
+# -H [dir] to switch home dirs for helper apps, dir optional
+# -i [ip] to listen on the specified IP,
+# 127.0.0.1 if omitted,
+# 0.0.0.0 (ie. all) if given without value;
+# must be used in combination with -A to actually allow
+# connections from anybody but localhost
+# -m limit to set the number of children, default 5
+# -u user the user to run spamd as
+# -L if you want to run no net tests
+#
+# for more help look in man spamd
+#
+# Note: if you plan on using the -u flag to spamd you will need to
+# make sure the location of the PID file is writable by that user.
+# This can be done by making the directory /var/run/spamd and
+# changing the owner to the UID that runs spamd. You will then
+# need to edit $pidfile in /etc/init.d/spamd. This should fix the
+# problem with stop/restart in the init scripts.
+#
+# See http://bugs.gentoo.org/show_bug.cgi?id=70124 for a full
+# explanation.
+
+SPAMD_OPTS="-m 5 -c -H"
+
+# spamd stores its pid in this file. If you use the -u option to
+# run spamd under another user, you might need to adjust it.
+
+PIDFILE="/var/run/spamd.pid"
+
+# SPAMD_NICELEVEL lets you set the 'nice'ness of the running
+# spamd process
+
+# SPAMD_NICELEVEL=5
diff --git a/main/spamassassin/spamd.init b/main/spamassassin/spamd.init
new file mode 100644
index 0000000000..89723889f4
--- /dev/null
+++ b/main/spamassassin/spamd.init
@@ -0,0 +1,39 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/mail-filter/spamassassin/files/3.0.0-spamd.init,v 1.8 2008/05/14 21:25:56 sbriesen Exp $
+
+# NB: Config is in /etc/conf.d/spamd
+
+# Provide a default location if they haven't in /etc/conf.d/spamd
+PIDFILE=${PIDFILE:-/var/run/spamd.pid}
+
+opts="reload"
+
+depend() {
+ need net
+ before mta
+ use logger
+}
+
+start() {
+ ebegin "Starting spamd"
+ start-stop-daemon --start --quiet \
+ --name spamd \
+ --nicelevel ${SPAMD_NICELEVEL:-0} \
+ --exec /usr/sbin/spamd -- -d -r ${PIDFILE} \
+ ${SPAMD_OPTS}
+ eend $? "Failed to start spamd"
+}
+
+stop() {
+ ebegin "Stopping spamd"
+ start-stop-daemon --stop --quiet --pidfile ${PIDFILE}
+ eend $? "Failed to stop spamd"
+}
+
+reload() {
+ ebegin "Reloading configuration"
+ kill -HUP $(< ${PIDFILE})
+ eend $?
+}
diff --git a/main/spandsp/APKBUILD b/main/spandsp/APKBUILD
new file mode 100644
index 0000000000..9b1bb40c70
--- /dev/null
+++ b/main/spandsp/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=spandsp
+pkgver=0.0.6_pre18
+pkgrel=0
+pkgdesc="SpanDSP is a library of DSP functions for telephony"
+url="http://www.soft-switch.org/installing-spandsp.html"
+arch="all"
+license="GPL"
+depends=
+depends_dev="tiff-dev"
+makedepends="$depends_dev"
+install=
+subpackages="$pkgname-dev"
+source="http://www.soft-switch.org/downloads/spandsp/$pkgname-0.0.6pre17.tgz"
+
+_builddir="$srcdir"/$pkgname-0.0.6
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="cc860f77270cf3b881f8ccd42d2d0238 spandsp-0.0.6pre17.tgz"
diff --git a/main/speedometer/APKBUILD b/main/speedometer/APKBUILD
new file mode 100644
index 0000000000..bafa602727
--- /dev/null
+++ b/main/speedometer/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Matt Smith <mcs@darkregion.net>
+# Maintainer: Matt Smith <mcs@darkregion.net>
+pkgname=speedometer
+pkgver=2.7
+pkgrel=2
+pkgdesc="Measure and display the rate of data across a network connection or data being stored in a file"
+url="http://excess.org/speedometer/"
+arch="noarch"
+license="LGPL"
+depends="python py-urwid"
+makedepends=
+install=
+subpackages=
+source="http://excess.org/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -Dm755 speedometer.py "$pkgdir"/usr/bin/speedometer
+}
+
+md5sums="74605672694b4b617ea5a6b7ab8d6926 speedometer-2.7.tar.gz"
diff --git a/main/speex/APKBUILD b/main/speex/APKBUILD
new file mode 100644
index 0000000000..9c29dc84d3
--- /dev/null
+++ b/main/speex/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanel Copa <ncopa@alpinelinux.org>
+pkgname=speex
+pkgver=1.2_rc1
+_ver=${pkgver%_*}${pkgver#*_}
+pkgrel=2
+pkgdesc="an audio compression format designed for speech"
+url="http://www.speex.org/"
+arch="all"
+license="BSD"
+depends=
+makedepends="libogg-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc libspeex"
+source="http://downloads.xiph.org/releases/speex/speex-$_ver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$_ver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+
+libspeex() {
+ pkgdesc="$pkgdesc - libraries"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libspeex*.so.* "$subpkgdir"/usr/lib/
+}
+
+
+md5sums="c4438b22c08e5811ff10e2b06ee9b9ae speex-1.2rc1.tar.gz"
diff --git a/main/sqlite/APKBUILD b/main/sqlite/APKBUILD
new file mode 100644
index 0000000000..696295791e
--- /dev/null
+++ b/main/sqlite/APKBUILD
@@ -0,0 +1,78 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=sqlite
+pkgver=3.7.7.1
+_a=${pkgver%%.*}
+_b=${pkgver#${_a}.}
+_b=${_b%%.*}
+_c=${pkgver#${_a}.${_b}.}
+_c=${_c%%.*}
+_d=${pkgver##*.}
+case $pkgver in
+ *.*.*.*) _ver=${_a}0${_b}0${_c}0${_d};;
+ *.*.*) _ver=${_a}0${_b}0${_c}00;;
+esac
+pkgrel=0
+pkgdesc="A C library that implements an SQL database engine"
+url="http://www.sqlite.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends="tcl"
+source="http://www.sqlite.org/$pkgname-autoconf-$_ver.tar.gz
+ license.txt"
+
+subpackages="$pkgname-doc $pkgname-dev"
+
+_builddir="$srcdir"/$pkgname-autoconf-$_ver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ export LTLINK_EXTRAS="-ldl"
+ export CFLAGS="$CFLAGS -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_SECURE_DELETE -DSQLITE_ENABLE_UNLOCK_NOTIFY -Iext/fts3"
+ ./configure --prefix=/usr \
+ --enable-threadsafe \
+ --enable-load-extension \
+ --enable-threads-override-locks \
+ --enable-cross-thread-connections \
+ --disable-static \
+ --disable-tcl \
+ --disable-readline \
+ || return 1
+ # rpath removal
+ sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
+ sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
+ make || return 1
+}
+
+dev() {
+ local i= j=
+ depends="$pkgname $depends_dev"
+
+ cd "$pkgdir" || return 0
+ for i in usr/include usr/lib/pkgconfig; do
+ if [ -e "$pkgdir/$i" ] || [ -L "$pkgdir/$i" ]; then
+ d="$subpkgdir/${i%/*}" # dirname $i
+ mkdir -p "$d"
+ mv "$pkgdir/$i" "$d"
+ rmdir "$pkgdir/${i%/*}" 2>/dev/null
+ fi
+ done
+
+ return 0
+}
+
+package() {
+ replaces="sqlite-dev"
+
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+ install -Dm0644 sqlite3.1 ${pkgdir}/usr/share/man/man1/sqlite3.1
+ install -Dm644 ${srcdir}/license.txt ${pkgdir}/usr/share/licenses/${pkgname}/license.txt
+}
+
+md5sums="554026fe7fac47b1cf61c18d5fe43419 sqlite-autoconf-3070701.tar.gz
+c1cdbc5544034d9012e421e75a5e4890 license.txt"
diff --git a/main/sqlite/license.txt b/main/sqlite/license.txt
new file mode 100644
index 0000000000..118c5d5e60
--- /dev/null
+++ b/main/sqlite/license.txt
@@ -0,0 +1,33 @@
+SQLite Copyright
+SQLite is in the
+Public Domain
+
+
+All of the deliverable code in SQLite has been dedicated to the public domain by the authors. All code authors, and representatives of the companies they work for, have signed affidavits dedicating their contributions to the public domain and originals of those signed affidavits are stored in a firesafe at the main offices of Hwaci. Anyone is free to copy, modify, publish, use, compile, sell, or distribute the original SQLite code, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
+
+The previous paragraph applies to the deliverable code in SQLite - those parts of the SQLite library that you actually bundle and ship with a larger application. Portions of the documentation and some code used as part of the build process might fall under other licenses. The details here are unclear. We do not worry about the licensing of the documentation and build code so much because none of these things are part of the core deliverable SQLite library.
+
+All of the deliverable code in SQLite has been written from scratch. No code has been taken from other projects or from the open internet. Every line of code can be traced back to its original author, and all of those authors have public domain dedications on file. So the SQLite code base is clean and is uncontaminated with licensed code from other projects.
+Obtaining An Explicit License To Use SQLite
+
+Even though SQLite is in the public domain and does not require a license, some users want to obtain a license anyway. Some reasons for obtaining a license include:
+You are using SQLite in a jurisdiction that does not recognize the public domain.
+You are using SQLite in a jurisdiction that does not recognize the right of an author to dedicate their work to the public domain.
+You want to hold a tangible legal document as evidence that you have the legal right to use and distribute SQLite.
+Your legal department tells you that you have to purchase a license.
+
+If you feel like you really have to purchase a license for SQLite, Hwaci, the company that employs the architect and principal developers of SQLite, will sell you one.
+Contributed Code
+
+In order to keep SQLite completely free and unencumbered by copyright, all new contributors to the SQLite code base are asked to dedicate their contributions to the public domain. If you want to send a patch or enhancement for possible inclusion in the SQLite source tree, please accompany the patch with the following statement:
+The author or authors of this code dedicate any and all copyright interest in this code to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this code under copyright law.
+
+We are not able to accept patches or changes to SQLite that are not accompanied by a statement such as the above. In addition, if you make changes or enhancements as an employee, then a simple statement such as the above is insufficient. You must also send by surface mail a copyright release signed by a company officer. A signed original of the copyright release should be mailed to:
+Hwaci
+6200 Maple Cove Lane
+Charlotte, NC 28269
+USA
+
+A template copyright release is available in PDF or HTML. You can use this release to make future changes.
+
+see http://www.sqlite.org/copyright.html \ No newline at end of file
diff --git a/main/sqsh/APKBUILD b/main/sqsh/APKBUILD
new file mode 100644
index 0000000000..c424c42c1b
--- /dev/null
+++ b/main/sqsh/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Ashton Spencer <aspec.451@gmail.com>
+# Maintainer: Jeff Bilyk <jbilyk@gmail.com>
+pkgname=sqsh
+pkgver=2.1.7
+pkgrel=2
+pkgdesc="Sybase iSQL replacement"
+url="http://www.sqsh.org"
+arch="all"
+license="GPL"
+depends="freetds readline"
+depends_dev="freetds-dev"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ SYBASE=/usr
+ export SYBASE
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/doc \
+# --with-x \
+ --with-readline
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ make DESTDIR="$pkgdir" install.man || return 1
+}
+
+md5sums="ce929dc8e23cedccac98288d24785e2d sqsh-2.1.7.tar.gz"
diff --git a/main/squark/APKBUILD b/main/squark/APKBUILD
new file mode 100644
index 0000000000..56452833a1
--- /dev/null
+++ b/main/squark/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+pkgname=squark
+pkgver=0.2
+pkgrel=0
+pkgdesc="Squark - Squid User Authentication and Rating Kit"
+subpackages=
+depends="haserl lua"
+makedepends="net-snmp-dev cmph-dev lua-dev pkgconfig"
+source="http://git.alpinelinux.org/cgit/$pkgname.git/snapshot/$pkgname-$pkgver.tar.bz2
+ "
+url="http://git.alpinelinux.org/cgit/squark/"
+arch="all"
+license=GPL-2
+
+prepare() {
+ cd "$srcdir"
+ ln -s squark-master $pkgname-$pkgver
+ cd "$srcdir/$pkgname-$pkgver"
+ sed -i -e 's:-Werror::' Make.rules
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+ sed -i -e 's:lua5.1:lua:g' "$srcdir"/"$pkgname-$pkgver"/src/Makefile
+}
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make FULL_VERSION="$pkgver-r$pkgrel" || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make FULL_VERSION="$pkgver-r$pkgrel" DESTDIR="$pkgdir" install
+}
+
+md5sums="777ef0d595b12872e3ed6647ef50e98a squark-0.2.tar.bz2"
diff --git a/main/squashfs-tools/APKBUILD b/main/squashfs-tools/APKBUILD
new file mode 100644
index 0000000000..ab07d2fa95
--- /dev/null
+++ b/main/squashfs-tools/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=squashfs-tools
+pkgver=4.2
+pkgrel=0
+pkgdesc="Tools for squashfs, a highly compressed read-only filesystem for Linux."
+url="http://squashfs.sourceforge.net"
+arch="all"
+license="GPL"
+depends=
+makedepends="zlib-dev attr-dev"
+source="http://downloads.sourceforge.net/sourceforge/squashfs/squashfs$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/squashfs$pkgver/$pkgname
+ make
+}
+
+package() {
+ cd "$srcdir"/squashfs$pkgver/$pkgname
+ mkdir -p "$pkgdir"/sbin
+ cp -a mksquashfs unsquashfs "$pkgdir"/sbin
+}
+md5sums="1b7a781fb4cf8938842279bd3e8ee852 squashfs4.2.tar.gz"
diff --git a/main/squid/APKBUILD b/main/squid/APKBUILD
new file mode 100644
index 0000000000..27858362eb
--- /dev/null
+++ b/main/squid/APKBUILD
@@ -0,0 +1,304 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=squid
+pkgver=2.7.9
+_ver=2.7.STABLE9
+pkgrel=4
+pkgdesc="A full-featured Web proxy cache server."
+url="http://www.squid-cache.org"
+install="squid.pre-install squid.pre-upgrade squid.post-install"
+pkgusers="squid"
+pkggroups="squid"
+arch="all"
+license="GPL-2"
+depends="$pkgname-errors-english logrotate"
+makedepends="openssl-dev perl-dev autoconf automake heimdal-dev"
+subpackages="$pkgname-doc
+ squid_kerb_auth
+ $pkgname-errors-armenian:errors_armenian
+ $pkgname-errors-azerbaijani:errors_azerbaijani
+ $pkgname-errors-bulgarian:errors_bulgarian
+ $pkgname-errors-catalan:errors_catalan
+ $pkgname-errors-czech:errors_czech
+ $pkgname-errors-danish:errors_danish
+ $pkgname-errors-dutch:errors_dutch
+ $pkgname-errors-english:errors_english
+ $pkgname-errors-estonian:errors_estonian
+ $pkgname-errors-finnish:errors_finnish
+ $pkgname-errors-french:errors_french
+ $pkgname-errors-german:errors_german
+ $pkgname-errors-greek:errors_greek
+ $pkgname-errors-hebrew:errors_hebrew
+ $pkgname-errors-hungarian:errors_hungarian
+ $pkgname-errors-italian:errors_italian
+ $pkgname-errors-japanese:errors_japanese
+ $pkgname-errors-korean:errors_korean
+ $pkgname-errors-lithuanian:errors_lithuanian
+ $pkgname-errors-polish:errors_polish
+ $pkgname-errors-portuguese:errors_portuguese
+ $pkgname-errors-romanian:errors_romanian
+ $pkgname-errors-russian-1251:errors_russian_1251
+ $pkgname-errors-russian-koi8-r:errors_russian_koi8_r
+ $pkgname-errors-serbian:errors_serbian
+ $pkgname-errors-simplify_chinese:errors_simplify_chinese
+ $pkgname-errors-slovak:errors_slovak
+ $pkgname-errors-spanish:errors_spanish
+ $pkgname-errors-swedish:errors_swedish
+ $pkgname-errors-traditional_chinese:errors_traditional_chinese
+ $pkgname-errors-turkish:errors_turkish
+ $pkgname-errors-ukrainian-1251:errors_ukrainian_1251
+ $pkgname-errors-ukrainian-koi8-u:errors_ukrainian_koi8_u
+ $pkgname-errors-ukrainian-utf8:errors_ukrainian_utf8"
+
+source="http://www.squid-cache.org/Versions/v2/2.7/${pkgname}-${_ver}.tar.bz2
+ squid.initd
+ squid.confd
+ squid-2.7-gentoo.patch
+ squid-2-heimdal.patch
+ squid-2.7-ims-content-type.patch
+ squid-2.7-loggable-urlgroup.patch
+ $pkgname.logrotate
+ "
+pkgusers="squid"
+pkggroups="squid"
+
+build() {
+ cd "$srcdir/$pkgname-$_ver"
+
+ for i in "$srcdir"/*.patch; do
+ msg "Applying $i..."
+ patch -p1 -i $i || return 1
+ done
+
+ touch NEWS AUTHORS
+ aclocal && autoconf && automake -a || return 1
+
+ ./configure --prefix=/usr --datadir=/usr/share/squid \
+ --sysconfdir=/etc/squid --libexecdir=/usr/lib/squid \
+ --localstatedir=/var \
+ --enable-auth="basic,digest,ntlm,negotiate" \
+ --enable-removal-policies="lru,heap" \
+ --enable-digest-auth-helpers="password" \
+ --enable-storeio="aufs,ufs,diskd,coss,null" \
+ --enable-basic-auth-helpers="getpwnam,NCSA,SMB,MSNT,multi-domain-NTLM,squid_radius_auth" \
+ --enable-epoll \
+ --enable-external-acl-helpers="ip_user,unix_group,wbinfo_group" \
+ --enable-ntlm-auth-helpers="SMB,fakeauth,no_check" \
+ --enable-negotiate-auth-helpers="squid_kerb_auth" \
+ --enable-delay-pools --enable-arp-acl --enable-ssl \
+ --enable-linux-netfilter --enable-ident-lookups \
+ --enable-useragent-log --enable-cache-digests --enable-referer-log \
+ --enable-async-io --enable-truncate --enable-arp-acl \
+ --enable-htcp --enable-carp --enable-poll --with-maxfd=4096 \
+ --enable-follow-x-forwarded-for \
+ --with-large-files
+
+ make || return 1
+ make DESTDIR="$pkgdir" install
+
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.logrotate \
+ "$pkgdir"/etc/logrotate.d/squid
+
+ install -d -o squid -g squid \
+ "$pkgdir"/var/cache/squid \
+ "$pkgdir"/var/log/squid \
+ "$pkgdir"/var/run/squid
+ chmod +x "$pkgdir"/usr/lib/squid/*
+}
+
+squid_kerb_auth() {
+ pkgdesc="Squid kerberos authetication helper"
+ install -d "$subpkgdir"/usr/lib/squid
+ mv "$pkgdir"/usr/lib/squid/squid_kerb_auth "$subpkgdir"/usr/lib/squid/
+}
+
+_mv_error() {
+ local d=usr/share/squid/errors
+ mkdir -p "$subpkgdir/$d"
+ mv "$pkgdir/$d/${1}" "$subpkgdir/$d/" || return 1
+ # last one removed the dir
+ rmdir "$pkgdir/$d" 2>/dev/null
+ return 0
+}
+
+errors_armenian() {
+ depends="$pkgname"
+ _mv_error Armenian
+}
+
+errors_azerbaijani() {
+ depends="$pkgname"
+ _mv_error Azerbaijani
+}
+
+errors_bulgarian() {
+ depends="$pkgname"
+ _mv_error Bulgarian
+}
+
+errors_catalan() {
+ depends="$pkgname"
+ _mv_error Catalan
+}
+
+errors_czech() {
+ depends="$pkgname"
+ _mv_error Czech
+}
+
+errors_danish() {
+ depends="$pkgname"
+ _mv_error Danish
+}
+
+errors_dutch() {
+ depends="$pkgname"
+ _mv_error Dutch
+}
+
+errors_english() {
+ depends=
+ _mv_error English
+}
+
+errors_estonian() {
+ depends="$pkgname"
+ _mv_error Estonian
+}
+
+errors_finnish() {
+ depends="$pkgname"
+ _mv_error Finnish
+}
+
+errors_french() {
+ depends="$pkgname"
+ _mv_error French
+}
+
+errors_german() {
+ depends="$pkgname"
+ _mv_error German
+}
+
+errors_greek() {
+ depends="$pkgname"
+ _mv_error Greek
+}
+
+errors_hebrew() {
+ depends="$pkgname"
+ _mv_error Hebrew
+}
+
+errors_hungarian() {
+ depends="$pkgname"
+ _mv_error Hungarian
+}
+
+errors_italian() {
+ depends="$pkgname"
+ _mv_error Italian
+}
+
+errors_japanese() {
+ depends="$pkgname"
+ _mv_error Japanese
+}
+
+errors_korean() {
+ depends="$pkgname"
+ _mv_error Korean
+}
+
+errors_lithuanian() {
+ depends="$pkgname"
+ _mv_error Lithuanian
+}
+
+errors_polish() {
+ depends="$pkgname"
+ _mv_error Polish
+}
+
+errors_portuguese() {
+ depends="$pkgname"
+ _mv_error Portuguese
+}
+
+errors_romanian() {
+ depends="$pkgname"
+ _mv_error Romanian
+}
+
+errors_russian_1251() {
+ depends="$pkgname"
+ _mv_error Russian-1251
+}
+
+errors_russian_koi8_r() {
+ depends="$pkgname"
+ _mv_error Russian-koi8-r
+}
+
+errors_serbian() {
+ depends="$pkgname"
+ _mv_error Serbian
+}
+
+errors_simplify_chinese() {
+ depends="$pkgname"
+ _mv_error Simplify_Chinese
+}
+
+errors_slovak() {
+ depends="$pkgname"
+ _mv_error Slovak
+}
+
+errors_spanish() {
+ depends="$pkgname"
+ _mv_error Spanish
+}
+
+errors_swedish() {
+ depends="$pkgname"
+ _mv_error Swedish
+}
+
+errors_traditional_chinese() {
+ depends="$pkgname"
+ _mv_error Traditional_Chinese
+}
+
+errors_turkish() {
+ depends="$pkgname"
+ _mv_error Turkish
+}
+
+errors_ukrainian_1251() {
+ depends="$pkgname"
+ _mv_error Ukrainian-1251
+}
+
+errors_ukrainian_koi8_u() {
+ depends="$pkgname"
+ _mv_error Ukrainian-koi8-u
+}
+
+errors_ukrainian_utf8() {
+ depends="$pkgname"
+ _mv_error Ukrainian-utf8
+}
+
+
+md5sums="3c6642c85470b1079207d43bba25a819 squid-2.7.STABLE9.tar.bz2
+57fed05adc40acab6a5480ec7a014154 squid.initd
+44b052db7910f386ef88ddcf69c9ba4e squid.confd
+3827f71d940b47eb385a1a1d92a51d66 squid-2.7-gentoo.patch
+614b97126ad9eecf728095f2de63d33d squid-2-heimdal.patch
+549377b5a6b673bf19ea6c34003d122c squid-2.7-ims-content-type.patch
+d4efa24094b011e77bc7bf45291c0ee9 squid-2.7-loggable-urlgroup.patch
+58823e0b86bc2dc71d270208b7b284b4 squid.logrotate"
diff --git a/main/squid/squid-2-heimdal.patch b/main/squid/squid-2-heimdal.patch
new file mode 100644
index 0000000000..67500ae6a8
--- /dev/null
+++ b/main/squid/squid-2-heimdal.patch
@@ -0,0 +1,18 @@
+diff -Nru squid-2.7.STABLE6.orig/helpers/negotiate_auth/squid_kerb_auth/Makefile.am squid-2.7.STABLE6/helpers/negotiate_auth/squid_kerb_auth/Makefile.am
+--- squid-2.7.STABLE6.orig/helpers/negotiate_auth/squid_kerb_auth/Makefile.am 2007-05-14 23:36:29.000000000 +0000
++++ squid-2.7.STABLE6/helpers/negotiate_auth/squid_kerb_auth/Makefile.am 2009-02-16 23:26:28.000000000 +0000
+@@ -18,10 +18,10 @@
+ #-L$(top_builddir)/lib -lmiscutil $(XTRA_LIBS)
+
+ # HEIMDAL
+-#KERBINC = -DHEIMDAL -I/usr/include/heimdal
+-#KERBLIBS = -lgssapi -lkrb5 -lcom_err -lasn1 -lroken
++KERBINC = -DHEIMDAL -I/usr/include/heimdal
++KERBLIBS = -lgssapi -lkrb5 -lcom_err -lasn1 -lroken
+
+ # MIT
+-KERBINC =
+-KERBLIBS = -lgssapi_krb5 -lkrb5 -lcom_err
++#KERBINC =
++#KERBLIBS = -lgssapi_krb5 -lkrb5 -lcom_err
+
diff --git a/main/squid/squid-2.7-gentoo.patch b/main/squid/squid-2.7-gentoo.patch
new file mode 100644
index 0000000000..f9480a9900
--- /dev/null
+++ b/main/squid/squid-2.7-gentoo.patch
@@ -0,0 +1,298 @@
+Gentoo squid patch for 2.7.4
+
+http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-proxy/squid/files/squid-2.7.4-gentoo.patch?view=markup
+
+--- squid-2.7.STABLE6/configure.in Wed Feb 4 00:44:06 2009
++++ squid-2.7.STABLE6-patched/configure.in Mon Feb 16 11:56:34 2009
+@@ -18,9 +18,9 @@
+ PRESET_LDFLAGS="$LDFLAGS"
+
+ dnl Set default LDFLAGS
+-if test -z "$LDFLAGS"; then
+- LDFLAGS="-g"
+-fi
++dnl if test -z "$LDFLAGS"; then
++dnl LDFLAGS="-g"
++dnl fi
+
+ dnl Check for GNU cc
+ AC_PROG_CC
+--- squid-2.7.STABLE6/helpers/basic_auth/MSNT/confload.c Wed Jun 26 19:09:48 2002
++++ squid-2.7.STABLE6-patched/helpers/basic_auth/MSNT/confload.c Mon Feb 16 11:56:34 2009
+@@ -24,7 +24,7 @@
+
+ /* Path to configuration file */
+ #ifndef SYSCONFDIR
+-#define SYSCONFDIR "/usr/local/squid/etc"
++#define SYSCONFDIR "/etc/squid"
+ #endif
+ #define CONFIGFILE SYSCONFDIR "/msntauth.conf"
+
+--- squid-2.7.STABLE6/helpers/basic_auth/MSNT/msntauth.conf.default Wed Jun 26 18:44:28 2002
++++ squid-2.7.STABLE6-patched/helpers/basic_auth/MSNT/msntauth.conf.default Mon Feb 16 11:56:34 2009
+@@ -8,6 +8,6 @@
+ server other_PDC other_BDC otherdomain
+
+ # Denied and allowed users. Comment these if not needed.
+-#denyusers /usr/local/squid/etc/msntauth.denyusers
+-#allowusers /usr/local/squid/etc/msntauth.allowusers
++#denyusers /etc/squid/msntauth.denyusers
++#allowusers /etc/squid/msntauth.allowusers
+
+--- squid-2.7.STABLE6/helpers/basic_auth/SMB/Makefile.am Tue May 17 16:56:26 2005
++++ squid-2.7.STABLE6-patched/helpers/basic_auth/SMB/Makefile.am Mon Feb 16 11:56:34 2009
+@@ -14,7 +14,7 @@
+ ## FIXME: autoconf should test for the samba path.
+
+ SMB_AUTH_HELPER = smb_auth.sh
+-SAMBAPREFIX=/usr/local/samba
++SAMBAPREFIX=/usr
+ SMB_AUTH_HELPER_PATH = $(libexecdir)/$(SMB_AUTH_HELPER)
+
+ libexec_SCRIPTS = $(SMB_AUTH_HELPER)
+--- squid-2.7.STABLE6/helpers/basic_auth/SMB/smb_auth.sh Sun Jan 7 23:36:46 2001
++++ squid-2.7.STABLE6-patched/helpers/basic_auth/SMB/smb_auth.sh Mon Feb 16 11:56:34 2009
+@@ -24,7 +24,7 @@
+ read AUTHSHARE
+ read AUTHFILE
+ read SMBUSER
+-read SMBPASS
++read -r SMBPASS
+
+ # Find domain controller
+ echo "Domain name: $DOMAINNAME"
+@@ -47,7 +47,7 @@
+ addropt=""
+ fi
+ echo "Query address options: $addropt"
+-dcip=`$SAMBAPREFIX/bin/nmblookup $addropt "$PASSTHROUGH#1c" | awk '/^[0-9.]+ / { print $1 ; exit }'`
++dcip=`$SAMBAPREFIX/bin/nmblookup $addropt "$PASSTHROUGH#1c" | awk '/^[0-9.]+\..+ / { print $1 ; exit }'`
+ echo "Domain controller IP address: $dcip"
+ [ -n "$dcip" ] || exit 1
+
+--- squid-2.7.STABLE6/helpers/external_acl/session/squid_session.8 Sat Jan 6 17:28:35 2007
++++ squid-2.7.STABLE6-patched/helpers/external_acl/session/squid_session.8 Mon Feb 16 11:56:34 2009
+@@ -35,7 +35,7 @@
+ .P
+ Configuration example using the default automatic mode
+ .IP
+-external_acl_type session ttl=300 negative_ttl=0 children=1 concurrency=200 %LOGIN /usr/local/squid/libexec/squid_session
++external_acl_type session ttl=300 negative_ttl=0 children=1 concurrency=200 %LOGIN /usr/libexec/squid/squid_session
+ .IP
+ acl session external session
+ .IP
+--- squid-2.7.STABLE6/helpers/external_acl/unix_group/squid_unix_group.8 Sun May 14 15:07:24 2006
++++ squid-2.7.STABLE6-patched/helpers/external_acl/unix_group/squid_unix_group.8 Mon Feb 16 11:56:34 2009
+@@ -27,7 +27,7 @@
+ This squid.conf example defines two Squid acls. usergroup1 matches users in group1, and usergroup2
+ matches users in group2 or group3
+ .IP
+-external_acl_type unix_group %LOGIN /usr/local/squid/libexec/squid_unix_group -p
++external_acl_type unix_group %LOGIN /usr/libexec/squid/squid_unix_group -p
+ .IP
+ acl usergroup1 external unix_group group1
+ .IP
+--- squid-2.7.STABLE6/src/Makefile.am Wed Jan 2 15:50:39 2008
++++ squid-2.7.STABLE6-patched/src/Makefile.am Mon Feb 16 11:56:34 2009
+@@ -340,13 +340,13 @@
+ DEFAULT_CONFIG_FILE = $(sysconfdir)/squid.conf
+ DEFAULT_MIME_TABLE = $(sysconfdir)/mime.conf
+ DEFAULT_DNSSERVER = $(libexecdir)/`echo dnsserver | sed '$(transform);s/$$/$(EXEEXT)/'`
+-DEFAULT_LOG_PREFIX = $(localstatedir)/logs
++DEFAULT_LOG_PREFIX = $(localstatedir)/log/squid
+ DEFAULT_CACHE_LOG = $(DEFAULT_LOG_PREFIX)/cache.log
+ DEFAULT_ACCESS_LOG = $(DEFAULT_LOG_PREFIX)/access.log
+ DEFAULT_STORE_LOG = $(DEFAULT_LOG_PREFIX)/store.log
+-DEFAULT_PID_FILE = $(DEFAULT_LOG_PREFIX)/squid.pid
++DEFAULT_PID_FILE = $(localstatedir)/run/squid/squid.pid
+ DEFAULT_NETDB_FILE = $(DEFAULT_LOG_PREFIX)/netdb.state
+-DEFAULT_SWAP_DIR = $(localstatedir)/cache
++DEFAULT_SWAP_DIR = $(localstatedir)/cache/squid
+ DEFAULT_PINGER = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'`
+ DEFAULT_UNLINKD = $(libexecdir)/`echo unlinkd | sed '$(transform);s/$$/$(EXEEXT)/'`
+ DEFAULT_DISKD = $(libexecdir)/`echo diskd-daemon | sed '$(transform);s/$$/$(EXEEXT)/'`
+--- squid-2.7.STABLE6/src/access_log.c Tue Mar 18 02:48:43 2008
++++ squid-2.7.STABLE6-patched/src/access_log.c Mon Feb 16 11:56:34 2009
+@@ -1261,7 +1261,7 @@
+ LogfileStatus = LOG_ENABLE;
+ }
+ #if HEADERS_LOG
+- headerslog = logfileOpen("/usr/local/squid/logs/headers.log", MAX_URL << 1, 0);
++ headerslog = logfileOpen("/var/log/squid/headers.log", MAX_URL << 1, 0);
+ assert(NULL != headerslog);
+ #endif
+ #if FORW_VIA_DB
+--- squid-2.7.STABLE6/src/cf.data.pre Mon Feb 2 11:28:55 2009
++++ squid-2.7.STABLE6-patched/src/cf.data.pre Mon Feb 16 11:56:34 2009
+@@ -678,6 +678,8 @@
+ acl Safe_ports port 488 # gss-http
+ acl Safe_ports port 591 # filemaker
+ acl Safe_ports port 777 # multiling http
++acl Safe_ports port 901 # SWAT
++acl purge method PURGE
+ acl CONNECT method CONNECT
+ NOCOMMENT_END
+ DOC_END
+@@ -711,6 +713,9 @@
+ # Only allow cachemgr access from localhost
+ http_access allow manager localhost
+ http_access deny manager
++# Only allow purge requests from localhost
++http_access allow purge localhost
++http_access deny purge
+ # Deny requests to unknown ports
+ http_access deny !Safe_ports
+ # Deny CONNECT to other than SSL ports
+@@ -728,6 +733,9 @@
+ # from where browsing should be allowed
+ http_access allow localnet
+
++# Allow the localhost to have access by default
++http_access allow localhost
++
+ # And finally deny all other access to this proxy
+ http_access deny all
+ NOCOMMENT_END
+@@ -3754,11 +3762,11 @@
+
+ NAME: cache_mgr
+ TYPE: string
+-DEFAULT: webmaster
++DEFAULT: root
+ LOC: Config.adminEmail
+ DOC_START
+ Email-address of local cache manager who will receive
+- mail if the cache dies. The default is "webmaster".
++ mail if the cache dies. The default is "root".
+ DOC_END
+
+ NAME: mail_from
+@@ -3787,12 +3795,12 @@
+
+ NAME: cache_effective_user
+ TYPE: string
+-DEFAULT: nobody
++DEFAULT: squid
+ LOC: Config.effectiveUser
+ DOC_START
+ If you start Squid as root, it will change its effective/real
+ UID/GID to the user specified below. The default is to change
+- to UID to nobody. If you define cache_effective_user, but not
++ to UID to squid. If you define cache_effective_user, but not
+ cache_effective_group, Squid sets the GID to the effective
+ user's default group ID (taken from the password file) and
+ supplementary group list from the from groups membership of
+@@ -4429,12 +4437,12 @@
+ NAME: snmp_port
+ TYPE: ushort
+ LOC: Config.Port.snmp
+-DEFAULT: 3401
++DEFAULT: 0
+ IFDEF: SQUID_SNMP
+ DOC_START
+ Squid can now serve statistics and status information via SNMP.
+- By default it listens to port 3401 on the machine. If you don't
+- wish to use SNMP, set this to "0".
++ By default snmp_port is disabled. If you wish to use SNMP,
++ set this to "3401" (or any other number you like).
+ DOC_END
+
+ NAME: snmp_access
+@@ -4505,12 +4513,12 @@
+ NAME: htcp_port
+ IFDEF: USE_HTCP
+ TYPE: ushort
+-DEFAULT: 4827
++DEFAULT: 0
+ LOC: Config.Port.htcp
+ DOC_START
+ The port number where Squid sends and receives HTCP queries to
+- and from neighbor caches. Default is 4827. To disable use
+- "0".
++ and from neighbor caches. To turn it on you want to set it to
++ 4827. By default it is set to "0" (disabled).
+ DOC_END
+
+ NAME: log_icp_queries
+@@ -5407,6 +5415,9 @@
+ If you disable this, it will appear as
+
+ X-Forwarded-For: unknown
++NOCOMMENT_START
++forwarded_for off
++NOCOMMENT_END
+ DOC_END
+
+ NAME: cachemgr_passwd
+--- squid-2.7.STABLE6/src/client_side.c Mon Oct 6 21:27:44 2008
++++ squid-2.7.STABLE6-patched/src/client_side.c Mon Feb 16 11:56:34 2009
+@@ -4706,14 +4706,7 @@
+ debug(83, 2) ("clientNegotiateSSL: Session %p reused on FD %d (%s:%d)\n", SSL_get_session(ssl), fd, fd_table[fd].ipaddr, (int) fd_table[fd].remote_port);
+ } else {
+ if (do_debug(83, 4)) {
+- /* Write out the SSL session details.. actually the call below, but
+- * OpenSSL headers do strange typecasts confusing GCC.. */
+- /* PEM_write_SSL_SESSION(debug_log, SSL_get_session(ssl)); */
+-#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x00908000L
+- PEM_ASN1_write((i2d_of_void *) i2d_SSL_SESSION, PEM_STRING_SSL_SESSION, debug_log, (char *) SSL_get_session(ssl), NULL, NULL, 0, NULL, NULL);
+-#else
+ PEM_ASN1_write(i2d_SSL_SESSION, PEM_STRING_SSL_SESSION, debug_log, (char *) SSL_get_session(ssl), NULL, NULL, 0, NULL, NULL);
+-#endif
+ /* Note: This does not automatically fflush the log file.. */
+ }
+ debug(83, 2) ("clientNegotiateSSL: New session %p on FD %d (%s:%d)\n", SSL_get_session(ssl), fd, fd_table[fd].ipaddr, (int) fd_table[fd].remote_port);
+--- squid-2.7.STABLE6/src/defines.h Mon Sep 24 13:31:19 2007
++++ squid-2.7.STABLE6-patched/src/defines.h Mon Feb 16 11:56:34 2009
+@@ -259,7 +259,7 @@
+
+ /* were to look for errors if config path fails */
+ #ifndef DEFAULT_SQUID_ERROR_DIR
+-#define DEFAULT_SQUID_ERROR_DIR "/usr/local/squid/etc/errors"
++#define DEFAULT_SQUID_ERROR_DIR "/usr/share/squid/errors/English"
+ #endif
+
+ /* gb_type operations */
+--- squid-2.7.STABLE6/src/main.c Thu Sep 25 02:21:52 2008
++++ squid-2.7.STABLE6-patched/src/main.c Mon Feb 16 11:56:34 2009
+@@ -376,6 +376,22 @@
+ asnFreeMemory();
+ }
+
++#if USE_UNLINKD
++static int
++needUnlinkd(void)
++{
++ int i;
++ int r = 0;
++ for (i = 0; i < Config.cacheSwap.n_configured; i++) {
++ if (strcmp(Config.cacheSwap.swapDirs[i].type, "ufs") == 0 ||
++ strcmp(Config.cacheSwap.swapDirs[i].type, "aufs") == 0 ||
++ strcmp(Config.cacheSwap.swapDirs[i].type, "diskd") == 0)
++ r++;
++ }
++ return r;
++}
++#endif
++
+ static void
+ mainReconfigure(void)
+ {
+@@ -614,7 +630,7 @@
+
+ if (!configured_once) {
+ #if USE_UNLINKD
+- unlinkdInit();
++ if (needUnlinkd()) unlinkdInit();
+ #endif
+ urlInitialize();
+ cachemgrInit();
+@@ -636,6 +652,9 @@
+ #endif
+ #if USE_WCCPv2
+ wccp2Init();
++#endif
++#if USE_UNLINKD
++ if (needUnlinkd()) unlinkdInit();
+ #endif
+ serverConnectionsOpen();
+ neighbors_init();
diff --git a/main/squid/squid-2.7-ims-content-type.patch b/main/squid/squid-2.7-ims-content-type.patch
new file mode 100644
index 0000000000..8b66197e7c
--- /dev/null
+++ b/main/squid/squid-2.7-ims-content-type.patch
@@ -0,0 +1,11 @@
+--- a/src/HttpReply.c.orig Wed Oct 7 07:08:08 2009
++++ b/src/HttpReply.c Wed Oct 7 07:08:20 2009
+@@ -43,7 +43,7 @@
+ static http_hdr_type Denied304HeadersArr[] =
+ {
+ HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, HDR_CONTENT_LENGTH,
+- HDR_CONTENT_LOCATION, HDR_CONTENT_RANGE
++ HDR_CONTENT_LOCATION, HDR_CONTENT_RANGE, HDR_CONTENT_TYPE
+ };
+
+ /* local routines */
diff --git a/main/squid/squid-2.7-loggable-urlgroup.patch b/main/squid/squid-2.7-loggable-urlgroup.patch
new file mode 100644
index 0000000000..c2bc9e6d64
--- /dev/null
+++ b/main/squid/squid-2.7-loggable-urlgroup.patch
@@ -0,0 +1,33 @@
+Index: squid-2.7.STABLE9/src/access_log.c
+===================================================================
+--- squid-2.7.STABLE9.orig/src/access_log.c 2010-11-18 15:02:26.000000000 +0200
++++ squid-2.7.STABLE9/src/access_log.c 2010-11-18 15:07:34.000000000 +0200
+@@ -301,6 +301,7 @@
+ LFT_REQUEST_URLPATH,
+ /*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */
+ LFT_REQUEST_VERSION,
++ LFT_REQUEST_URLGROUP,
+
+ LFT_REQUEST_SIZE_TOTAL,
+ /*LFT_REQUEST_SIZE_LINE, */
+@@ -411,6 +412,7 @@
+ /* { "rq", LFT_REQUEST_QUERY }, * / / * the query-string, INCLUDING the leading ? */
+ {">v", LFT_REQUEST_VERSION},
+ {"rv", LFT_REQUEST_VERSION},
++ {"rG", LFT_REQUEST_URLGROUP},
+
+ {">st", LFT_REQUEST_SIZE_TOTAL},
+ /*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */
+@@ -544,6 +546,12 @@
+ quote = 1;
+ break;
+
++ case LFT_REQUEST_URLGROUP:
++ if (al->request)
++ out = al->request->urlgroup;
++ quote = 1;
++ break;
++
+ case LFT_REPLY_HEADER:
+ if (al->reply)
+ sb = httpHeaderGetByName(&al->reply->header, fmt->data.header.header);
diff --git a/main/squid/squid.confd b/main/squid/squid.confd
new file mode 100644
index 0000000000..14a9ee84bd
--- /dev/null
+++ b/main/squid/squid.confd
@@ -0,0 +1,15 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-proxy/squid/files/squid.confd,v 1.2 2008/11/30 19:20:44 mrness Exp $
+
+# Config file for /etc/init.d/squid
+
+SQUID_OPTS="-DYC"
+
+# Max. number of filedescriptors to use. You can increase this on a busy
+# cache to a maximum of (currently) 8192 filedescriptors. Default is 1024.
+SQUID_MAXFD=1024
+
+# Kerberos keytab file to use. This is required if you enable kerberos authentication.
+SQUID_KEYTAB=""
+
diff --git a/main/squid/squid.initd b/main/squid/squid.initd
new file mode 100644
index 0000000000..2eaf1dd2af
--- /dev/null
+++ b/main/squid/squid.initd
@@ -0,0 +1,115 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-proxy/squid/files/squid.initd,v 1.10 2008/11/30 19:20:44 mrness Exp $
+
+opts="${opts} reload rotate"
+
+conf=/etc/squid/squid.conf
+
+depend() {
+ need net
+ after firewall
+}
+
+# Try to increase the # of filedescriptors we can open.
+maxfds() {
+ [ -n "$SQUID_MAXFD" ] || return
+ [ -f /proc/sys/fs/file-max ] || return 0
+ [ $SQUID_MAXFD -le 8192 ] || SQUID_MAXFD=8192
+ local global_file_max=`cat /proc/sys/fs/file-max`
+ local minimal_file_max=$(($SQUID_MAXFD + 4096))
+ if [ "$global_file_max" -lt $minimal_file_max ]; then
+ echo $minimal_file_max > /proc/sys/fs/file-max
+ fi
+ ulimit -n $SQUID_MAXFD
+}
+
+checkconfig() {
+ maxfds
+
+ local CACHE_SWAP=$(awk '/^[ \t]*cache_dir[ \t]+/ { if ($2 == "coss" ) printf "%s/stripe ", $3 ; else printf "%s/00 ", $3; }' < $conf)
+ [ -z "$CACHE_SWAP" ] && CACHE_SWAP="/var/cache/squid/00"
+
+ local x
+ for x in $CACHE_SWAP ; do
+ if [ ! -e $x ] ; then
+ ebegin "Initializing cache directories"
+ local ORIG_UMASK=$(umask)
+ umask 027
+ local INIT_CACHE_RESPONSE="$(/usr/sbin/squid -z -N -D 2>&1)"
+ if [ $? != 0 ] || echo "$INIT_CACHE_RESPONSE" | grep -q "erminated abnormally" ; then
+ umask $ORIG_UMASK
+ eend 1
+ echo "$INIT_CACHE_RESPONSE"
+ return 1
+ fi
+ umask $ORIG_UMASK
+ eend 0
+ break
+ fi
+ done
+
+ squid -k parse
+}
+
+get_pidfile() {
+ PIDFILE=$(awk '/^[ \t]*pid_filename[ \t]+/ {print $2}' $conf)
+ [ -z "$PIDFILE" ] && PIDFILE=/var/run/squid/squid.pid
+}
+
+start() {
+ get_pidfile
+ checkconfig || return 1
+ ebegin "Starting squid"
+ start-stop-daemon --start --pidfile "$PIDFILE" \
+ --env KRB5_KTNAME="${SQUID_KEYTAB}" \
+ --exec /usr/sbin/squid -- ${SQUID_OPTS}
+ eend $? && sleep 1
+}
+
+stop() {
+ local rc=0 pid
+ ebegin "Stopping squid"
+ get_pidfile
+ /usr/sbin/squid -k shutdown
+
+ # Now we have to wait until squid has _really_ stopped.
+ if [ -f "$PIDFILE" ] ; then
+ pid=$(cat "$PIDFILE")
+ if [ -d /proc/$pid ]; then
+ einfon "Waiting for squid to shutdown ."
+ else
+ rm -f "$PIDFILE"
+ fi
+ cnt=0
+ while [ -f "$PIDFILE" ] ; do
+ cnt=$(expr $cnt + 1)
+ if [ $cnt -gt 60 ] ; then
+ # Waited 120 seconds now. Fail.
+ echo
+ rc=1
+ break
+ fi
+ sleep 2
+ echo -n "."
+ done
+ echo
+ fi
+ eend $rc
+}
+
+reload() {
+ checkconfig || return 1
+ ebegin "Reloading squid"
+ /usr/sbin/squid -k reconfigure
+ eend $?
+}
+
+rotate() {
+ service_started squid || return 1
+ ebegin "Rotating logs"
+ /usr/sbin/squid -k rotate
+ eend $?
+}
+
diff --git a/main/squid/squid.logrotate b/main/squid/squid.logrotate
new file mode 100644
index 0000000000..fb3279e013
--- /dev/null
+++ b/main/squid/squid.logrotate
@@ -0,0 +1,11 @@
+/var/log/squid/*.log {
+ daily
+ compress
+ rotate 5
+ missingok
+ nocreate
+ sharedscripts
+ postrotate
+ /usr/sbin/squid -k rotate
+ endscript
+}
diff --git a/main/squid/squid.post-install b/main/squid/squid.post-install
new file mode 100644
index 0000000000..88df6d26f9
--- /dev/null
+++ b/main/squid/squid.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+chown squid:squid /var/cache/squid /var/log/squid
+exit 0
+
diff --git a/main/squid/squid.pre-install b/main/squid/squid.pre-install
new file mode 100644
index 0000000000..322d21deab
--- /dev/null
+++ b/main/squid/squid.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+adduser -D squid -H /var/cache/squid 2>/dev/null
+addgroup winbind 2>/dev/null
+addgroup squid winbind
+exit 0
diff --git a/main/squid/squid.pre-upgrade b/main/squid/squid.pre-upgrade
new file mode 120000
index 0000000000..70437c5d9f
--- /dev/null
+++ b/main/squid/squid.pre-upgrade
@@ -0,0 +1 @@
+squid.pre-install \ No newline at end of file
diff --git a/main/sshfs/APKBUILD b/main/sshfs/APKBUILD
new file mode 100644
index 0000000000..e17ac1a222
--- /dev/null
+++ b/main/sshfs/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sshfs
+pkgver=2.2
+pkgrel=1
+pkgdesc="FUSE client based on the SSH File Transfer Protocol"
+url="http://fuse.sourceforge.net/sshfs.html"
+arch="all"
+license="GPL"
+depends="openssh-client"
+makedepends="pkgconfig fuse-dev glib-dev"
+source="http://downloads.sourceforge.net/sourceforge/fuse/sshfs-fuse-$pkgver.tar.gz"
+
+_builddir="$srcdir"/sshfs-fuse-$pkgver
+build ()
+{
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="26e9206eb5169e87e6f95f54bc005a4f sshfs-fuse-2.2.tar.gz"
diff --git a/main/ssmtp/APKBUILD b/main/ssmtp/APKBUILD
new file mode 100644
index 0000000000..73272de179
--- /dev/null
+++ b/main/ssmtp/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Natananael Copa <ncopa@alpinelinux.org>
+
+pkgname=ssmtp
+pkgver=2.64
+pkgrel=4
+pkgdesc="Extremely simple MTA to get mail off the system to a mail hub"
+subpackages="$pkgname-doc"
+arch="all"
+url="http://packages.debian.org/source/lenny/ssmtp"
+license="GPL-2"
+depends=
+makedepends="openssl-dev"
+install=
+source="http://ftp.debian.org/debian/pool/main/s/$pkgname/${pkgname}_${pkgver}.orig.tar.bz2
+ generate_config.patch
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch generate_config ../generate_config.patch || return 1
+ sed -i -e 's:$(CC) -o:$(CC) @LDFLAGS@ -o:' Makefile.in
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --sysconfdir=/etc \
+ --enable-ssl
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make prefix="$pkgdir"/usr \
+ etcdir="$pkgdir"/etc \
+ mandir="$pkgdir"/usr/share/man \
+ install
+ ln -s ssmtp "$pkgdir"/usr/sbin/sendmail
+}
+
+md5sums="65b4e0df4934a6cd08c506cabcbe584f ssmtp_2.64.orig.tar.bz2
+c70c395fe71589ca8b10b666455d5071 generate_config.patch"
diff --git a/main/ssmtp/CVE-2008-3962.patch b/main/ssmtp/CVE-2008-3962.patch
new file mode 100644
index 0000000000..fca144fa68
--- /dev/null
+++ b/main/ssmtp/CVE-2008-3962.patch
@@ -0,0 +1,14 @@
+--- ssmtp.orig/ssmtp.c
++++ ssmtp/ssmtp.c
+@@ -485,6 +485,11 @@ char *from_format(char *str, bool_t over
+ die("from_format() -- snprintf() failed");
+ }
+ }
++ else {
++ if(snprintf(buf, BUF_SZ, "%s", str) == -1) {
++ die("from_format() -- snprintf() failed");
++ }
++ }
+ }
+
+ #if 0
diff --git a/main/ssmtp/generate_config.patch b/main/ssmtp/generate_config.patch
new file mode 100644
index 0000000000..dd4baf9f8a
--- /dev/null
+++ b/main/ssmtp/generate_config.patch
@@ -0,0 +1,49 @@
+--- src/ssmtp/generate_config 2004-07-23 05:58:48.000000000 +0000
++++ generate_config 2009-01-27 10:09:11.000000000 +0000
+@@ -4,7 +4,7 @@
+ # Figure out the system's mailname
+ #
+
+-syshostname=`hostname --fqdn`
++syshostname="localhost"
+ if test -f /etc/mailname
+ then
+ mailname="`head -1 /etc/mailname`"
+@@ -15,23 +15,7 @@
+ mailname=$syshostname
+ fi
+
+-echo "Please enter the mail name of your system."
+-echo "This is the hostname portion of the address to be shown"
+-echo "on outgoing news and mail messages headers."
+-echo "The default is $syshostname, your system's host name."
+-echo
+-echo -n "Mail name [$syshostname]: "
+-read mailname
+-echo
+-
+-echo -n "Please enter the SMTP port number [25]: "
+-read smtpport
+-if test -z "$smtpport"
+-then
+- mailhub=$mailhub
+-else
+- mailhub="$mailhub:$smtpport"
+-fi
++mailhub="$mailhub:$smtpport"
+
+ #
+ # Generate configuration file
+@@ -56,11 +40,5 @@
+ # Where will the mail seem to come from?
+ #rewriteDomain=`echo -n $mailname`
+ # The full hostname
+-hostname=`hostname --fqdn`
++#hostname="localhost"
+ EOF
+-
+-echo
+-echo
+-echo "Please check the configuration file $1 for correctness."
+-echo
+-echo
diff --git a/main/startup-notification/APKBUILD b/main/startup-notification/APKBUILD
new file mode 100644
index 0000000000..af8187393d
--- /dev/null
+++ b/main/startup-notification/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=startup-notification
+pkgver=0.12
+pkgrel=1
+pkgdesc="Monitor and display application startup"
+url="http://www.freedesktop.org"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev"
+depends=
+makedepends="libx11-dev libsm-dev xcb-util-dev"
+source="http://www.freedesktop.org/software/$pkgname/releases/$pkgname-$pkgver.tar.gz"
+
+depends_dev="libsm-dev xcb-util-dev"
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --localstatedir=/var \
+ --sysconfdir=/etc \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.a "$pkgdir"/usr/lib/*.la
+}
+md5sums="2cd77326d4dcaed9a5a23a1232fb38e9 startup-notification-0.12.tar.gz"
diff --git a/main/strace/APKBUILD b/main/strace/APKBUILD
new file mode 100644
index 0000000000..eff517edcb
--- /dev/null
+++ b/main/strace/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=strace
+pkgver=4.6
+pkgrel=0
+pkgdesc="A useful diagnositic, instructional, and debugging tool"
+url="http://sourceforge.net/projects/strace/"
+arch="all"
+license="BSD"
+depends=
+makedepends=
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.xz"
+subpackages="$pkgname-doc"
+
+build ()
+{
+ cd "$srcdir/$pkgname-$pkgver"
+ #changes in kernel headers in 2.6.32
+ sed -i -e 's/include <linux\/socket.h>/include <sys\/socket.h>/g' \
+ configure
+ ./configure --prefix=/usr \
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make -j1 DESTDIR="$pkgdir" install
+}
+md5sums="e537b2b1afeec70c0e6e27a0d0fd671e strace-4.6.tar.xz"
diff --git a/main/subversion/APKBUILD b/main/subversion/APKBUILD
new file mode 100644
index 0000000000..e88e397686
--- /dev/null
+++ b/main/subversion/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=subversion
+pkgver=1.6.17
+pkgrel=1
+pkgdesc="Replacement for CVS, another versioning system (svn)"
+url="http://subversion.tigris.org/"
+arch="all"
+license="apache bsd"
+depends=
+makedepends="apr-dev apr-util-dev expat-dev neon-dev openssl-dev zlib-dev
+ e2fsprogs-dev sqlite-dev"
+install="$pkgname.pre-install"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://subversion.tigris.org/downloads/subversion-$pkgver.tar.bz2
+ svnserve.confd
+ svnserve.initd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-nls \
+ --without-apxs \
+ --disable-javahl \
+ --without-jdk
+
+ make external-all || return 1
+ make local-all || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ install -Dm755 "$srcdir"/svnserve.initd "$pkgdir"/etc/init.d/svnserve
+ install -Dm644 "$srcdir"/svnserve.confd "$pkgdir"/etc/conf.d/svnserve
+}
+md5sums="81e5dc5beee4b3fc025ac70c0b6caa14 subversion-1.6.17.tar.bz2
+d084a7558053784886bc858b94fa9186 svnserve.confd
+22c274fafb4817e31126f60f9d84039f svnserve.initd"
diff --git a/main/subversion/subversion.pre-install b/main/subversion/subversion.pre-install
new file mode 100644
index 0000000000..fb516ee5a0
--- /dev/null
+++ b/main/subversion/subversion.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+addgroup svnusers 2>/dev/null
+adduser svn -D -h /var/svn -G svnusers 2>/dev/null
+exit 0
+
diff --git a/main/subversion/svnserve.confd b/main/subversion/svnserve.confd
new file mode 100644
index 0000000000..b487a40975
--- /dev/null
+++ b/main/subversion/svnserve.confd
@@ -0,0 +1,10 @@
+# The commented variables in this file are the defaults that are used
+# in the init-script. You don't need to uncomment them except to
+# customize them to different values.
+
+# Options for svnserve
+#SVNSERVE_OPTS="--root=/var/svn"
+
+# User and group as which to run svnserve
+SVNSERVE_USER="svn"
+SVNSERVE_GROUP="svnusers"
diff --git a/main/subversion/svnserve.initd b/main/subversion/svnserve.initd
new file mode 100644
index 0000000000..f539a4e2c7
--- /dev/null
+++ b/main/subversion/svnserve.initd
@@ -0,0 +1,45 @@
+#!/sbin/runscript
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/dev-util/subversion/files/svnserve.initd,v 1.2 2005/08/25 13:59:48 pauldv Exp $
+
+opts="$opts setup"
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting svnserve"
+ # Ensure that we run from a readable working dir, and that we do not
+ # lock filesystems when being run from such a location.
+ cd /
+ start-stop-daemon --start --quiet --background --make-pidfile \
+ --pidfile /var/run/svnserve.pid --exec /usr/bin/svnserve \
+ --chuid ${SVNSERVE_USER:-apache}:${SVNSERVE_GROUP:-apache} -- \
+ --foreground --daemon ${SVNSERVE_OPTS:---root=/var/svn}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping svnserve"
+ start-stop-daemon --stop --quiet --pidfile /var/run/svnserve.pid
+ eend $?
+}
+
+setup() {
+ local root=${SVNSERVE_ROOT:-/var/svn}
+ ebeging "Setting up svnserve repositories in $root"
+ if [ -e "$root/repos" ]; then
+ eend 1 "$root/repos already exist"
+ return 1
+ fi
+
+ svnadmin create "$root"/repos
+ chown -Rf "${SVNSERVE_USER}:${SVNSERVE_GROUP}" "$root/repos"
+ mkdir -p "$root/conf"
+ chmod -Rf go-rwx "$root/conf"
+ chmod -Rf o-rwx "$root/repos"
+ eend $?
+}
diff --git a/main/sudo/APKBUILD b/main/sudo/APKBUILD
new file mode 100644
index 0000000000..ed49aeb0ec
--- /dev/null
+++ b/main/sudo/APKBUILD
@@ -0,0 +1,46 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sudo
+pkgver=1.8.1p1
+if [ "${pkgver%_*}" != "$pkgver" ]; then
+ _realver=${pkgver%_*}${pkgver#*_}
+else
+ _realver=$pkgver
+fi
+pkgrel=0
+pkgdesc="Give certain users the ability to run some commands as root"
+url="http://www.sudo.ws/sudo/"
+arch="all"
+license='custom ISC'
+makedepends=
+depends=
+subpackages="$pkgname-doc"
+source="ftp://ftp.sudo.ws/pub/sudo/$pkgname-$_realver.tar.gz
+ libcrypt.patch"
+
+_builddir="$srcdir"/$pkgname-$_realver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --with-env-editor \
+ --without-pam \
+ --without-skey \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="318337804d976c9419cf3004b707945c sudo-1.8.1p1.tar.gz
+429d9613091f1f3f19ce8def5b3032b3 libcrypt.patch"
diff --git a/main/sudo/libcrypt.patch b/main/sudo/libcrypt.patch
new file mode 100644
index 0000000000..0bab038632
--- /dev/null
+++ b/main/sudo/libcrypt.patch
@@ -0,0 +1,11 @@
+--- ./plugins/sudoers/Makefile.in.orig
++++ ./plugins/sudoers/Makefile.in
+@@ -45,7 +45,7 @@
+ # Libraries
+ LIBS = $(top_builddir)/common/libcommon.la $(top_builddir)/@ac_config_libobj_dir@/libreplace.la
+ NET_LIBS = @NET_LIBS@
+-SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(LIBS) $(NET_LIBS) @ZLIB@
++SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(LIBS) $(NET_LIBS) @ZLIB@ -lcrypt
+ REPLAY_LIBS = @REPLAY_LIBS@ @ZLIB@
+
+ # C preprocessor flags
diff --git a/main/swatch/APKBUILD b/main/swatch/APKBUILD
new file mode 100644
index 0000000000..cb915749cd
--- /dev/null
+++ b/main/swatch/APKBUILD
@@ -0,0 +1,59 @@
+# Contributor: Mika Havela <mika.havela@gmail.com>
+# Maintainer: Mika Havela <mika.havela@gmail.com>
+pkgname=swatch
+pkgver=3.2.3
+pkgrel=2
+pkgdesc="Logfile monitoring tool"
+url="http://sourceforge.net/projects/swatch/"
+arch="noarch"
+license="GPL"
+depends="perl perl-date-calc perl-date-format perl-date-manip perl-file-tail perl-carp-clan"
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ swatch.initd
+ swatch.confd
+ swatchrc"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor || return 1
+ make || return 1
+ make test || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ make realclean || return 1
+
+ # remove perllocal.pod and .packlist
+ find "$pkgdir" -name perllocal.pod -delete
+ find "$pkgdir" -name .packlist -delete
+
+
+#echo "pkdir= $pkgdir"
+#echo "srcdir= $srcdir"
+
+ mkdir -p "$pkgdir"/etc/init.d/
+ mkdir -p "$pkgdir"/etc/conf.d/
+ mkdir -p "$pkgdir"/etc/$pkgname/
+
+ cp "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ cp "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ cp "$srcdir"/${pkgname}rc "$pkgdir"/etc/$pkgname/${pkgname}rc
+
+ chmod 755 "$pkgdir"/etc/init.d/$pkgname
+}
+
+md5sums="1162f1024cf07fc750ed4960d61ac4e8 swatch-3.2.3.tar.gz
+cc99f0831b4a069f90fdedee82495523 swatch.initd
+a02a10a0266781a1ce16cc3b5e84968c swatch.confd
+8a92d37f96982030e0283dc7fe706da8 swatchrc"
diff --git a/main/swatch/swatch.confd b/main/swatch/swatch.confd
new file mode 100644
index 0000000000..5cbdc0a205
--- /dev/null
+++ b/main/swatch/swatch.confd
@@ -0,0 +1,8 @@
+## tail-args
+# Arguments for tail program
+tailargs="-n 0 -F"
+
+## script-dir
+# This switch causes the temporary watcher script to be written to a file in the specified directory rather than the user's home directory.
+# It is highly advised that you do NOT use directories that are writable by others such as /tmp.
+scriptdir="/tmp/swatch"
diff --git a/main/swatch/swatch.initd b/main/swatch/swatch.initd
new file mode 100755
index 0000000000..ec625e4026
--- /dev/null
+++ b/main/swatch/swatch.initd
@@ -0,0 +1,50 @@
+#!/sbin/runscript
+
+# swatch init.d file for alpine linux.
+
+name=swatch
+daemon=/usr/bin/$name
+configfile=/etc/${name}/swatchrc
+tailfile=/var/log/messages
+
+SVC="${SVCNAME#*.}"
+if [ -n "${SVC}" ] && [ "${SVCNAME}" != "${name}" ]; then
+ SVCPID="${name}.${SVC}.pid"
+ configfile="${configfile}.${SVC}"
+ tailfile=$(find /var/log -name "${SVC}" | head -1)
+ [ ! "${tailfile}" ] && tailfile="/var/log/${SVC}"
+else
+ SVCPID="${name}.pid"
+fi
+
+depend() {
+# need net
+ after syslog
+}
+
+start() {
+ ebegin "Starting ${name}"
+ einfo "Preparing to monitor ${tailfile}"
+ if [ ! -e "${tailfile}" ]; then
+ eerror "${tailfile} does not exist"
+ return 1
+ fi
+ if [ ! -e "${configfile}" ]; then
+ eerror "Configfile ${configfile} is missing"
+ return 1
+ fi
+ mkdir -p "${scriptdir}"
+ start-stop-daemon --start --quiet --background \
+ --make-pidfile --pidfile /var/run/${SVCPID} \
+ --exec ${daemon} -- \
+ --config-file="${configfile}" --script-dir="${scriptdir}" \
+ --tail-file="${tailfile}" --tail-args="${tailargs}"
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${name}"
+ kill $(ps | grep .swatch_script.$(cat /var/run/${SVCPID}) | grep -v 'grep' | awk '{ print $1}')
+ eend $?
+}
+
diff --git a/main/swatch/swatchrc b/main/swatch/swatchrc
new file mode 100644
index 0000000000..3ea2615a94
--- /dev/null
+++ b/main/swatch/swatchrc
@@ -0,0 +1,103 @@
+###############################################################################
+### Swatch example config
+#
+# The configuration file is used by the swatch(8) program to determine what
+# types of expression patterns to look for and what type of action(s) should be
+# taken when a pattern is matched.
+# Each line should contain a keyword and a, sometimes optional, value for that
+# keyword. The keyword and value are separated by a space or an equal (=) sign.
+#
+# watchfor regex
+# ignore regex
+#
+# echo [modes]
+# Echo the matched line. The text mode may be normal, bold, underscore,
+# blink, inverse, black, red, green, yellow, blue, magenta, cyan, white,
+# black_h, red_h, green_h, yellow_h, blue_h, magenta_h, cyan_h,
+# and/or white_h. The _h colors specify a highlighting color. The other
+# colors are assigned to the letters. Some modes may not work on some
+# terminals. Normal is the default.
+# bell [N]
+# Echo the matched line, and send a bell N times (default = 1).
+# exec command
+# Execute command. The command may contain variables which are substituted
+# with fields from the matched line. A $N will be replaced by the Nth field
+# in the line. A $0 or $* will be replaced by the entire line.
+# mail [addresses=address:address:...][,subject=your_text_here]
+# Send mail to address(es) containing the matched lines as they appear
+# (default address is the user who is running the program).
+# pipe command[,keep_open]
+# Pipe matched lines into command. Use the keep_open option to force the
+# pipe to stay open until a different pipe action is run or until swatch
+# exits.
+# write [user:user:...]
+# Use write(1) to send matched lines to user(s).
+# threshold track_by=key, type=<limit|threshold|both, count=number, seconds=number>
+# Thresholding can be done for the complete watchfor block and/or for
+# individual actions. Add ``threshold=on'' as an option along with the other
+# threshold options when thresholding an individual action.
+# track_by
+# The value of this should be something that is unique to the
+# watchfor regular expression. Tip: enclose unique parts of the
+# regular expression in parentheses, then use the sub matches as
+# part of the value (e.g. track_by=``$2:$4'').
+# type
+# There are three types of thresholding. They are as follows:
+# limit
+# Perform action(s) for the first "count`` matches during
+# the time interval specified by ''seconds", then ignore
+# events for the rest of the time interval (kind of like
+# throttle)
+# threshold
+# Perform action(s) on each match for up to count matches
+# during the time interval specified by seconds
+# both
+# Perform actions(s) once per time interval after "count``
+# matches occur, then ignore additional matches during the
+# time interval specified by ''seconds"
+# continue
+# Use this action to cause swatch to continue to try to match other
+# pattern/action groups after it is done with the current pattern/action
+# block.
+# quit
+# Use this action to cause swatch to clean up and quit immediately.
+###############################################################################
+
+## Successful SSH Login Attempts
+watchfor /sshd.*(: [aA]ccepted)(.*)( from )(.*)( port .*)$/
+ threshold track_by=$4,type=limit,count=1,seconds=60
+ echo bold green
+ #mail='receiver@foo.bar',SUBJECT=sshd: Accepted connection,MAILER=sendmail -t -S smtp.foo.bar -f sender\@foo.bar
+
+## Invalid SSH Login Attempts
+watchfor /sshd.*(: [iI]nvalid [uU]ser )(.*)( from )(.*)$/
+ threshold track_by=$4,type=both,count=3,seconds=60
+ echo bold red
+
+## Failed SSH Login Attempts
+watchfor /sshd.*(: [fF]ailed password for )(.*)( from )(.*)( port )(.*)$/
+ threshold track_by=$4,type=both,count=3,seconds=60
+ echo bold red
+
+## Failed SSH Login Attempts
+watchfor /([aA]uthentication [fF]ailure for [iI]llegal [uU]ser )(.*)( from )(.*)$/
+ threshold track_by=$4,type=both,count)3,seconds=60
+ echo bold red
+
+
+## Invalid sudo commands
+watchfor /sudo:.*[Cc]ommand not allowed/
+ echo bold red
+
+## File system full
+watchfor /file system full/
+ echo bold blue
+
+## System crashes and halts
+watchfor /(panic|halt)/
+ echo bold red
+
+## File system errors
+watchfor /[Mm]edia [Ee]rror/
+ echo bold yellow
+
diff --git a/main/swfdec-mozilla/APKBUILD b/main/swfdec-mozilla/APKBUILD
new file mode 100644
index 0000000000..c2855fae10
--- /dev/null
+++ b/main/swfdec-mozilla/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=swfdec-mozilla
+pkgver=0.8.2
+pkgrel=3
+pkgdesc="free plugin for Mozilla browsers that uses the Swfdec library for playing SWF files"
+url="http://swfdec.freedesktop.org"
+arch="all"
+license="LGPL"
+makedepends="swfdec-dev"
+depends=
+source="http://swfdec.freedesktop.org/download/$pkgname/0.8/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-static \
+ --with-plugin-dir=/usr/lib/mozilla/plugins/
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="716632e0d35b3c1582c180569ba30346 swfdec-mozilla-0.8.2.tar.gz"
diff --git a/main/swfdec/APKBUILD b/main/swfdec/APKBUILD
new file mode 100644
index 0000000000..01d79d47a1
--- /dev/null
+++ b/main/swfdec/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=swfdec
+pkgver=0.8.4
+pkgrel=5
+pkgdesc="free library for decoding and rendering Flash animations"
+url="http://swfdec.freedesktop.org"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="alsa-lib-dev liboil-dev gtk+-dev libsoup-dev gstreamer-dev
+ gst-plugins-base-dev"
+depends=
+depends_dev="glib-dev liboil-dev cairo-dev pango-dev gtk+-dev libsoup-dev
+ gstreamer-dev gst-plugins-base-dev alsa-lib-dev"
+source="http://$pkgname.freedesktop.org/download/$pkgname/0.8/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-static \
+ --enable-gtk \
+ --enable-gstreamer \
+ --enable-soup \
+ --with-audio=alsa
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="aece501d0e73f3e564200a44ec03c385 swfdec-0.8.4.tar.gz"
diff --git a/main/swig/APKBUILD b/main/swig/APKBUILD
new file mode 100644
index 0000000000..9b3363e0c9
--- /dev/null
+++ b/main/swig/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=swig
+pkgver=2.0.4
+pkgrel=0
+pkgdesc="SWIG is a compiler that makes it easy to integrate C and C++ code with scripting languages"
+url="http://www.swig.org/"
+arch="all"
+license="custom"
+depends="guile"
+makedepends="zlib-dev pcre-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ install -D -m644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+md5sums="4319c503ee3a13d2a53be9d828c3adc0 swig-2.0.4.tar.gz"
diff --git a/main/swish-e/APKBUILD b/main/swish-e/APKBUILD
new file mode 100644
index 0000000000..67cb9ec97b
--- /dev/null
+++ b/main/swish-e/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=swish-e
+pkgver=2.4.7
+pkgrel=4
+pkgdesc="Simple Web Indexing System for Humans - Enhanced"
+url="http://www.swish-e.org/"
+arch="all"
+license="GPL"
+depends=""
+makedepends="perl-dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.swish-e.org/distribution/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="736db7a65aed48bb3e2587c52833642d swish-e-2.4.7.tar.gz"
diff --git a/main/sylpheed/APKBUILD b/main/sylpheed/APKBUILD
new file mode 100644
index 0000000000..081579854d
--- /dev/null
+++ b/main/sylpheed/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sylpheed
+pkgver=3.1.0
+pkgrel=1
+pkgdesc="Lightweight and user-friendly e-mail client"
+url="http://sylpheed.sraoss.jp/en/"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+-dev openldap-dev openssl-dev"
+subpackages="$pkgname-dev"
+source="http://$pkgname.sraoss.jp/$pkgname/v${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/sylpheed-$pkgver"
+ ./configure --prefix=/usr \
+ --enable-ldap \
+ --disable-gtkspell || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/sylpheed-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="311847d73d0dda63a48e5ec107538424 sylpheed-3.1.0.tar.bz2"
diff --git a/main/sysfsutils/APKBUILD b/main/sysfsutils/APKBUILD
new file mode 100644
index 0000000000..e334e2bb64
--- /dev/null
+++ b/main/sysfsutils/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sysfsutils
+pkgver=2.1.0
+pkgrel=7
+pkgdesc="System Utilities Based on Sysfs"
+url="http://linux-diag.sourceforge.net/Sysfsutils.html"
+arch="all"
+license="GPL LGPL"
+depends=""
+makedepends=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://downloads.sourceforge.net/sourceforge/linux-diag/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir"/ install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="14e7dcd0436d2f49aa403f67e1ef7ddc sysfsutils-2.1.0.tar.gz"
diff --git a/main/sysklogd/APKBUILD b/main/sysklogd/APKBUILD
new file mode 100644
index 0000000000..28edde4028
--- /dev/null
+++ b/main/sysklogd/APKBUILD
@@ -0,0 +1,61 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sysklogd
+pkgver=1.5
+pkgrel=12
+pkgdesc="System and kernel log daemons"
+url="http://www.infodrom.org/projects/sysklogd/"
+arch="all"
+license="GPL BSD"
+subpackages="$pkgname-doc"
+depends=
+makedepends=""
+install="sysklogd.post-install sysklogd.pre-deinstall"
+source="http://www.infodrom.org/projects/$pkgname/download/$pkgname-$pkgver.tar.gz
+ sysklogd.logrotate
+ sysklogd.daily
+ sysklogd.initd
+ sysklogd.confd
+ sysklogd-1.4.2-caen-owl-klogd-drop-root.diff
+ sysklogd-1.4.2-caen-owl-syslogd-bind.diff
+ sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff
+ sysklogd-1.5-build.patch
+ ksym-fclose-fix.diff
+ syslog.conf
+ LICENSE"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+
+ for i in ../*.patch ../*.diff; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
+ export CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE"
+ make || return 1
+ install -d "$pkgdir"/usr/sbin
+ install -d "$pkgdir"/usr/share/man/man5
+ install -d "$pkgdir"/usr/share/man/man8
+ make INSTALL=install prefix="$pkgdir" install
+ install -D -m644 ../sysklogd.logrotate \
+ "$pkgdir"/etc/logrotate.d/sysklogd
+ install -D -m755 ../sysklogd.daily \
+ "$pkgdir"/etc/periodic/daily/sysklogd
+ install -D -m755 ../sysklogd.initd "$pkgdir"/etc/init.d/sysklogd
+ install -D -m644 ../sysklogd.confd "$pkgdir"/etc/conf.d/sysklogd
+ install -D -m644 ../syslog.conf "$pkgdir"/etc/syslog.conf
+ install -D -m644 ../LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+md5sums="e053094e8103165f98ddafe828f6ae4b sysklogd-1.5.tar.gz
+6bc1d1c65076b104a8f78d0fb4f21db7 sysklogd.logrotate
+dcda8ba997e79a90fdf4ab61f6e5a42b sysklogd.daily
+1ea1768fbfc6165e3a73490d98d47799 sysklogd.initd
+e25d7b583b7e4bd8be503b89e1771e90 sysklogd.confd
+3b7ba3aa6519f96f11165a7d5900a8b1 sysklogd-1.4.2-caen-owl-klogd-drop-root.diff
+4715e1dd2deb7a9ac137e004210e3154 sysklogd-1.4.2-caen-owl-syslogd-bind.diff
+6c0a416e40a678cf99c454b0e98185c9 sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff
+c71826d1a4f3f7e8ffa57adbfc24f1ce sysklogd-1.5-build.patch
+8e70cdf98cce9defae0c28a3d2db4410 ksym-fclose-fix.diff
+16019757e6af519be8cf3398b97e0f1b syslog.conf
+7930f7ff5038e1318511624e348581cc LICENSE"
diff --git a/main/sysklogd/LICENSE b/main/sysklogd/LICENSE
new file mode 100644
index 0000000000..7e9b5d59c3
--- /dev/null
+++ b/main/sysklogd/LICENSE
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
diff --git a/main/sysklogd/ksym-fclose-fix.diff b/main/sysklogd/ksym-fclose-fix.diff
new file mode 100644
index 0000000000..a1b3401e22
--- /dev/null
+++ b/main/sysklogd/ksym-fclose-fix.diff
@@ -0,0 +1,12 @@
+Index: sysklogd-1.5/ksym_mod.c
+===================================================================
+--- sysklogd-1.5.orig/ksym_mod.c 2009-08-04 09:47:53.000000000 +0300
++++ sysklogd-1.5/ksym_mod.c 2009-08-04 09:48:05.000000000 +0300
+@@ -189,7 +189,6 @@
+ else
+ Syslog(LOG_ERR, "Error loading kernel symbols " \
+ "- %s\n", strerror(errno));
+- fclose(ksyms);
+ return(0);
+ }
+
diff --git a/main/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff b/main/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff
new file mode 100644
index 0000000000..40b8817d4e
--- /dev/null
+++ b/main/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff
@@ -0,0 +1,162 @@
+http://cvsweb.openwall.com/cgi/cvsweb.cgi/~checkout~/Owl/packages/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff?rev=1.2;content-type=text%2Fplain
+diff -upk.orig sysklogd-1.4.2.orig/klogd.8 sysklogd-1.4.2/klogd.8
+--- sysklogd-1.4.2.orig/klogd.8 2005-03-11 16:12:09 +0000
++++ sysklogd-1.4.2/klogd.8 2005-08-18 14:37:47 +0000
+@@ -18,6 +19,12 @@ klogd \- Kernel Log Daemon
+ .RB [ " \-f "
+ .I fname
+ ]
++.RB [ " \-u "
++.I username
++]
++.RB [ " \-j "
++.I chroot_dir
++]
+ .RB [ " \-iI " ]
+ .RB [ " \-n " ]
+ .RB [ " \-o " ]
+@@ -53,6 +60,20 @@ stderr.
+ .BI "\-f " file
+ Log messages to the specified filename rather than to the syslog facility.
+ .TP
++.BI "\-u " username
++Tells klogd to become the specified user and drop root privileges before
++starting logging.
++.TP
++.BI "\-j " chroot_dir
++Tells klogd to
++.BR chroot (2)
++into this directory after initializing.
++This option is only valid if the \-u option is also used to run klogd
++without root privileges.
++Note that the use of this option will prevent \-i and \-I from working
++unless you set up the chroot directory in such a way that klogd can still
++read the kernel module symbols.
++.TP
+ .BI "\-i \-I"
+ Signal the currently executing klogd daemon. Both of these switches control
+ the loading/reloading of symbol information. The \-i switch signals the
+diff -upk.orig sysklogd-1.4.2.orig/klogd.c sysklogd-1.4.2/klogd.c
+--- sysklogd-1.4.2.orig/klogd.c 2005-08-18 12:29:52 +0000
++++ sysklogd-1.4.2/klogd.c 2005-08-18 14:37:47 +0000
+@@ -261,6 +261,8 @@
+ #include <stdarg.h>
+ #include <paths.h>
+ #include <stdlib.h>
++#include <pwd.h>
++#include <grp.h>
+ #include "klogd.h"
+ #include "ksyms.h"
+ #ifndef TESTING
+@@ -315,6 +317,9 @@ static enum LOGSRC {none, proc, kernel}
+ int debugging = 0;
+ int symbols_twice = 0;
+
++char *server_user = NULL;
++char *chroot_dir = NULL;
++int log_flags = 0;
+
+ /* Function prototypes. */
+ extern int ksyslog(int type, char *buf, int len);
+@@ -535,8 +540,9 @@ static enum LOGSRC GetKernelLogSrc(void)
+ * First do a stat to determine whether or not the proc based
+ * file system is available to get kernel messages from.
+ */
+- if ( use_syscall ||
+- ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) )
++ if (!server_user &&
++ (use_syscall ||
++ ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT))))
+ {
+ /* Initialize kernel logging. */
+ ksyslog(1, NULL, 0);
+@@ -983,6 +989,27 @@ static void LogProcLine(void)
+ }
+
+
++static int drop_root(void)
++{
++ struct passwd *pw;
++
++ if (!(pw = getpwnam(server_user))) return -1;
++
++ if (!pw->pw_uid) return -1;
++
++ if (chroot_dir) {
++ if (chdir(chroot_dir)) return -1;
++ if (chroot(".")) return -1;
++ }
++
++ if (setgroups(0, NULL)) return -1;
++ if (setgid(pw->pw_gid)) return -1;
++ if (setuid(pw->pw_uid)) return -1;
++
++ return 0;
++}
++
++
+ int main(argc, argv)
+
+ int argc;
+@@ -1000,7 +1027,7 @@ int main(argc, argv)
+ chdir ("/");
+ #endif
+ /* Parse the command-line. */
+- while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx2")) != EOF)
++ while ((ch = getopt(argc, argv, "c:df:u:j:iIk:nopsvx2")) != EOF)
+ switch((char)ch)
+ {
+ case '2': /* Print lines with symbols twice. */
+@@ -1022,6 +1049,10 @@ int main(argc, argv)
+ case 'I':
+ SignalDaemon(SIGUSR2);
+ return(0);
++ case 'j': /* chroot 'j'ail */
++ chroot_dir = optarg;
++ log_flags |= LOG_NDELAY;
++ break;
+ case 'k': /* Kernel symbol file. */
+ symfile = optarg;
+ break;
+@@ -1037,6 +1068,9 @@ int main(argc, argv)
+ case 's': /* Use syscall interface. */
+ use_syscall = 1;
+ break;
++ case 'u': /* Run as this user */
++ server_user = optarg;
++ break;
+ case 'v':
+ printf("klogd %s.%s\n", VERSION, PATCHLEVEL);
+ exit (1);
+@@ -1045,6 +1079,10 @@ int main(argc, argv)
+ break;
+ }
+
++ if (chroot_dir && !server_user) {
++ fputs("'-j' is only valid with '-u'\n", stderr);
++ exit(1);
++ }
+
+ /* Set console logging level. */
+ if ( log_level != (char *) 0 )
+@@ -1158,7 +1196,7 @@ int main(argc, argv)
+ }
+ }
+ else
+- openlog("kernel", 0, LOG_KERN);
++ openlog("kernel", log_flags, LOG_KERN);
+
+
+ /* Handle one-shot logging. */
+@@ -1191,6 +1229,11 @@ int main(argc, argv)
+ }
+ }
+
++ if (server_user && drop_root()) {
++ syslog(LOG_ALERT, "klogd: failed to drop root");
++ Terminate();
++ }
++
+ /* The main loop. */
+ while (1)
+ {
diff --git a/main/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff b/main/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff
new file mode 100644
index 0000000000..ad311a512c
--- /dev/null
+++ b/main/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff
@@ -0,0 +1,103 @@
+http://cvsweb.openwall.com/cgi/cvsweb.cgi/~checkout~/Owl/packages/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff?rev=1.1;content-type=text%2Fplain
+diff -upk.orig sysklogd-1.4.2.orig/sysklogd.8 sysklogd-1.4.2/sysklogd.8
+--- sysklogd-1.4.2.orig/sysklogd.8 2004-07-09 17:33:32 +0000
++++ sysklogd-1.4.2/sysklogd.8 2005-08-18 14:40:25 +0000
+@@ -15,6 +15,9 @@ sysklogd \- Linux system logging utiliti
+ .I config file
+ ]
+ .RB [ " \-h " ]
++.RB [ " \-i "
++.I IP address
++]
+ .RB [ " \-l "
+ .I hostlist
+ ]
+@@ -104,6 +107,13 @@ Specifying this switch on the command li
+ This can cause syslog loops that fill up hard disks quite fast and
+ thus needs to be used with caution.
+ .TP
++.BI "\-i " "IP address"
++If
++.B syslogd
++is configured to accept log input from a UDP port, specify an IP address
++to bind to, rather than the default of INADDR_ANY. The address must be in
++dotted quad notation, DNS host names are not allowed.
++.TP
+ .BI "\-l " "hostlist"
+ Specify a hostname that should be logged only with its simple hostname
+ and not the fqdn. Multiple hosts may be specified using the colon
+diff -upk.orig sysklogd-1.4.2.orig/syslogd.c sysklogd-1.4.2/syslogd.c
+--- sysklogd-1.4.2.orig/syslogd.c 2005-08-18 14:33:22 +0000
++++ sysklogd-1.4.2/syslogd.c 2005-08-18 14:40:25 +0000
+@@ -774,6 +774,8 @@ char **LocalHosts = NULL; /* these hosts
+ int NoHops = 1; /* Can we bounce syslog messages through an
+ intermediate host. */
+
++char *bind_addr = NULL; /* bind UDP port to this interface only */
++
+ extern int errno;
+
+ /* Function prototypes. */
+@@ -878,7 +880,7 @@ int main(argc, argv)
+ funix[i] = -1;
+ }
+
+- while ((ch = getopt(argc, argv, "a:dhf:l:m:np:rs:v")) != EOF)
++ while ((ch = getopt(argc, argv, "a:dhf:i:l:m:np:rs:v")) != EOF)
+ switch((char)ch) {
+ case 'a':
+ if (nfunix < MAXFUNIX)
+@@ -895,9 +897,17 @@ int main(argc, argv)
+ case 'h':
+ NoHops = 0;
+ break;
++ case 'i':
++ if (bind_addr) {
++ fprintf(stderr, "Only one -i argument allowed, "
++ "the first one is taken.\n");
++ break;
++ }
++ bind_addr = optarg;
++ break;
+ case 'l':
+ if (LocalHosts) {
+- fprintf (stderr, "Only one -l argument allowed," \
++ fprintf(stderr, "Only one -l argument allowed, "
+ "the first one is taken.\n");
+ break;
+ }
+@@ -1244,7 +1254,7 @@ int main(argc, argv)
+ int usage()
+ {
+ fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
+- " [-s domainlist] [-f conffile]\n");
++ " [-s domainlist] [-f conffile] [-i IP address]\n");
+ exit(1);
+ }
+
+@@ -1286,15 +1296,22 @@ static int create_inet_socket()
+ int fd, on = 1;
+ struct sockaddr_in sin;
+
++ memset(&sin, 0, sizeof(sin));
++ sin.sin_family = AF_INET;
++ sin.sin_port = LogPort;
++ if (bind_addr) {
++ if (!inet_aton(bind_addr, &sin.sin_addr)) {
++ logerror("syslog: not a valid IP address to bind to.");
++ return -1;
++ }
++ }
++
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ logerror("syslog: Unknown protocol, suspending inet service.");
+ return fd;
+ }
+
+- memset(&sin, 0, sizeof(sin));
+- sin.sin_family = AF_INET;
+- sin.sin_port = LogPort;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \
+ (char *) &on, sizeof(on)) < 0 ) {
+ logerror("setsockopt(REUSEADDR), suspending inet");
diff --git a/main/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff b/main/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff
new file mode 100644
index 0000000000..8c3f571f3c
--- /dev/null
+++ b/main/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff
@@ -0,0 +1,118 @@
+http://cvsweb.openwall.com/cgi/cvsweb.cgi/~checkout~/Owl/packages/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff?rev=1.1;content-type=text%2Fplain
+diff -upk.orig sysklogd-1.4.2.orig/sysklogd.8 sysklogd-1.4.2/sysklogd.8
+--- sysklogd-1.4.2.orig/sysklogd.8 2005-08-18 14:40:25 +0000
++++ sysklogd-1.4.2/sysklogd.8 2005-08-18 14:41:26 +0000
+@@ -32,6 +32,9 @@ sysklogd \- Linux system logging utiliti
+ .RB [ " \-s "
+ .I domainlist
+ ]
++.RB [ " \-u"
++.IB username
++]
+ .RB [ " \-v " ]
+ .LP
+ .SH DESCRIPTION
+@@ -161,6 +164,19 @@ is specified and the host logging resolv
+ no domain would be cut, you will have to specify two domains like:
+ .BR "\-s north.de:infodrom.north.de" .
+ .TP
++.BI "\-u " "username"
++This causes the
++.B syslogd
++daemon to become the named user before starting up logging.
++
++Note that when this option is in use,
++.B syslogd
++will open all log files as root when the daemon is first started;
++however, after a
++.B SIGHUP
++the files will be reopened as the non-privileged user. You should
++take this into account when deciding the ownership of the log files.
++.TP
+ .B "\-v"
+ Print version and exit.
+ .LP
+diff -upk.orig sysklogd-1.4.2.orig/syslogd.c sysklogd-1.4.2/syslogd.c
+--- sysklogd-1.4.2.orig/syslogd.c 2005-08-18 14:40:25 +0000
++++ sysklogd-1.4.2/syslogd.c 2005-08-18 14:41:26 +0000
+@@ -524,6 +524,10 @@ static char sccsid[] = "@(#)syslogd.c 5.
+ #include <arpa/nameser.h>
+ #include <arpa/inet.h>
+ #include <resolv.h>
++
++#include <pwd.h>
++#include <grp.h>
++
+ #ifndef TESTING
+ #include "pidfile.h"
+ #endif
+@@ -775,6 +779,7 @@ int NoHops = 1; /* Can we bounce syslog
+ intermediate host. */
+
+ char *bind_addr = NULL; /* bind UDP port to this interface only */
++char *server_user = NULL; /* user name to run server as */
+
+ extern int errno;
+
+@@ -827,6 +832,21 @@ static int set_nonblock_flag(int desc)
+ return fcntl(desc, F_SETFL, flags | O_NONBLOCK);
+ }
+
++static int drop_root(void)
++{
++ struct passwd *pw;
++
++ if (!(pw = getpwnam(server_user))) return -1;
++
++ if (!pw->pw_uid) return -1;
++
++ if (initgroups(server_user, pw->pw_gid)) return -1;
++ if (setgid(pw->pw_gid)) return -1;
++ if (setuid(pw->pw_uid)) return -1;
++
++ return 0;
++}
++
+ int main(argc, argv)
+ int argc;
+ char **argv;
+@@ -880,7 +900,7 @@ int main(argc, argv)
+ funix[i] = -1;
+ }
+
+- while ((ch = getopt(argc, argv, "a:dhf:i:l:m:np:rs:v")) != EOF)
++ while ((ch = getopt(argc, argv, "a:dhf:i:l:m:np:rs:u:v")) != EOF)
+ switch((char)ch) {
+ case 'a':
+ if (nfunix < MAXFUNIX)
+@@ -933,6 +953,9 @@ int main(argc, argv)
+ }
+ StripDomains = crunch_list(optarg);
+ break;
++ case 'u':
++ server_user = optarg;
++ break;
+ case 'v':
+ printf("syslogd %s.%s\n", VERSION, PATCHLEVEL);
+ exit (0);
+@@ -1100,6 +1123,11 @@ int main(argc, argv)
+ kill (ppid, SIGTERM);
+ #endif
+
++ if (server_user && drop_root()) {
++ dprintf("syslogd: failed to drop root\n");
++ exit(1);
++ }
++
+ /* Main loop begins here. */
+ for (;;) {
+ int nfds;
+@@ -1254,7 +1282,7 @@ int main(argc, argv)
+ int usage()
+ {
+ fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
+- " [-s domainlist] [-f conffile] [-i IP address]\n");
++ " [-s domainlist] [-f conffile] [-i IP address] [-u username]\n");
+ exit(1);
+ }
+
diff --git a/main/sysklogd/sysklogd-1.5-build.patch b/main/sysklogd/sysklogd-1.5-build.patch
new file mode 100644
index 0000000000..6175cdfe78
--- /dev/null
+++ b/main/sysklogd/sysklogd-1.5-build.patch
@@ -0,0 +1,20 @@
+respect env CC/CFLAGS/CPPFLAGS/LDFLAGS
+
+--- a/Makefile
++++ b/Makefile
+@@ -17,14 +17,12 @@
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+-CC= gcc
+ #SKFLAGS= -g -DSYSV -Wall
+ #LDFLAGS= -g
+-SKFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce
++SKFLAGS= $(CFLAGS) $(CPPFLAGS) -DSYSV -Wall -fno-strength-reduce
+ # -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+ # -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
+ # $(shell getconf LFS_SKFLAGS)
+-LDFLAGS= -s
+
+ # Look where your install program is.
+ INSTALL = /usr/bin/install
diff --git a/main/sysklogd/sysklogd.confd b/main/sysklogd/sysklogd.confd
new file mode 100644
index 0000000000..c973573911
--- /dev/null
+++ b/main/sysklogd/sysklogd.confd
@@ -0,0 +1,6 @@
+# Config file for /etc/init.d/sysklogd
+
+SYSLOGD="-m 0"
+# send warnings and above to the console
+KLOGD="-c 3 -2"
+
diff --git a/main/sysklogd/sysklogd.daily b/main/sysklogd/sysklogd.daily
new file mode 100755
index 0000000000..723413d4d5
--- /dev/null
+++ b/main/sysklogd/sysklogd.daily
@@ -0,0 +1,91 @@
+#!/bin/sh
+# This is a shell script replacement for the sysklogd's logrotate cron script
+# and syslogd-listfiles perl script.
+# Copyright (C) 2008 N. Angelacos for the Alpine Linux project - GPL2
+
+
+CONF="/etc/syslog.conf"
+
+
+syslogd_listfiles() {
+ # List the target files from syslog.conf
+
+ local skip=
+ [ "$1" = "--auth" ] && skip="!"
+
+ # the while loop joins lines that end in "\"
+ # the sed (in order)-
+ # strips comments;
+ # remove empty lines;
+ # collapses spaces/tabs to 1 space;
+ # deletes the "-" in front of the filename;
+ # deletes whitespace before ';'
+ # deletes lines that have/dont have the "auth" facility
+ # deletes the facility (leaving just the filename)
+ # deletes lines that are not filenames with leading "/"
+ # print it
+ while read a ; do echo "$a"; done < $CONF |\
+ sed -n -e "s/\#.*//" \
+ -e "/^[[:space:]]*$/D" \
+ -e "s/[[:space:]]\+/ /g" \
+ -e "s: -/: /:g" \
+ -e "s/ *; */;/" \
+ -e "/^.*\(auth\)[^ ]* /${skip}D" \
+ -e "s:^.* /:/:" \
+ -e "/^[^\\/]/D" \
+ -e "P" \
+ | sort | uniq
+}
+
+# dumb little savelog - no error checking here
+savelog () {
+ local group="adm"
+ local mode="644"
+ local user="root"
+ local cycle=2
+ local logfile=""
+
+ # parse args
+ while getopts "g:u:m:c:" opt; do
+ case $opt in
+ g) group=$OPTARG ;;
+ u) user=$OPTARG ;;
+ m) mode=$OPTARG ;;
+ c) cycle=$OPTARG ;;
+ *) echo "unknown option: $opt" >&2 && return 1;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+ logfile=$1
+
+ # Cycle the logs
+ while [ $cycle -ne 0 ]; do
+ p=$cycle
+ cycle=$(( $cycle - 1 ))
+ a=$logfile.$cycle*
+ b=$( echo $a | sed "s/\.$cycle/\.$p/")
+ [ -f $a ] && mv $a $b
+ done
+
+ # compress .1 and let .0 be uncompressed
+ [ -f $logfile.1 ] && gzip $logfile.1
+ [ -f $logfile ] && mv $logfile $logfile.0
+
+ # set permissions
+ chown $user:$group $logfile.* 2>/dev/null
+ chmod $mode $logfile.* 2>/dev/null
+}
+
+
+# Main script
+
+for LOG in $( syslogd_listfiles ); do
+ [ -f $LOG ] && savelog -g adm -m 640 -u root -c 7 $LOG
+done
+
+for LOG in $(syslogd_listfiles --auth); do
+ [ -f $LOG ] && savelog -g adm -m 640 -u root -c 7 $LOG
+done
+
+killall -HUP syslogd
+
diff --git a/main/sysklogd/sysklogd.initd b/main/sysklogd/sysklogd.initd
new file mode 100644
index 0000000000..96882b8d14
--- /dev/null
+++ b/main/sysklogd/sysklogd.initd
@@ -0,0 +1,80 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/app-admin/sysklogd/files/sysklogd.rc6,v 1.12 2007/05/01 12:49:04 uberlord Exp $
+
+opts="reload"
+
+depend() {
+ need clock hostname localmount
+ before net
+ provide logger
+}
+
+start_daemon() {
+ local retval=0
+ local daemon="$1"
+ local options="$2"
+
+ [ -z "${daemon}" ] && return 1
+
+ ebegin "sysklogd -> start: ${daemon}"
+ start-stop-daemon --start --exec /usr/sbin/"${daemon}" \
+ --pidfile /var/run/"${daemon}".pid -- ${options}
+ retval=$?
+ eend ${retval} "Failed to start ${daemon}"
+
+ return ${retval}
+}
+
+stop_daemon() {
+ local retval=0
+ local daemon="$1"
+
+ [ -z "${daemon}" ] && return 1
+
+ ebegin "sysklogd -> stop: ${daemon}"
+ # syslogd can be stubborn some times (--retry 15)...
+ start-stop-daemon --stop --retry 15 --quiet --pidfile /var/run/"${daemon}".pid
+ retval=$?
+ eend ${retval} "Failed to stop ${daemon}"
+
+ return ${retval}
+}
+
+start() {
+ start_daemon "syslogd" "${SYSLOGD}" || return 1
+
+ # vservers should not start klogd
+ [ "$RC_SYS" = "VSERVER" ] && return 0
+ # klogd do not always start proper if started too early
+ sleep 1
+
+ if ! start_daemon "klogd" "${KLOGD}" ; then
+ stop_daemon "syslogd"
+ return 1
+ fi
+
+ return 0
+}
+
+stop() {
+ if [ "$RC_SYS" != "VSERVER" ]; then
+ stop_daemon "klogd" || return 1
+ fi
+ stop_daemon "syslogd" || return 1
+ return 0
+}
+
+reload() {
+ local ret=0
+
+ ebegin "Reloading configuration"
+
+ start-stop-daemon --stop --oknodo --signal HUP --pidfile /var/run/syslogd.pid
+ ret=$((${ret} + $?))
+ start-stop-daemon --stop --oknodo --signal USR1 --pidfile /var/run/klogd.pid
+ ret=$((${ret} + $?))
+
+ eend ${ret}
+}
diff --git a/main/sysklogd/sysklogd.logrotate b/main/sysklogd/sysklogd.logrotate
new file mode 100644
index 0000000000..0fd0be2ff7
--- /dev/null
+++ b/main/sysklogd/sysklogd.logrotate
@@ -0,0 +1,6 @@
+# we do logrotatation in a separate cron script that parses syslog.conf
+# and rotates whatever user have configured.
+#
+# That is better than having users to maunally update this logrotate config
+# whenever they touch syslog.conf
+#
diff --git a/main/sysklogd/sysklogd.post-install b/main/sysklogd/sysklogd.post-install
new file mode 100644
index 0000000000..939886d383
--- /dev/null
+++ b/main/sysklogd/sysklogd.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+INIT=syslog
+RUNLEVEL=`rc-update show | grep $INIT | awk '{ print $3 }'`
+rc-update del $INIT $RUNLEVEL &>/dev/null
+rc-update add sysklogd $RUNLEVEL &>/dev/null
diff --git a/main/sysklogd/sysklogd.pre-deinstall b/main/sysklogd/sysklogd.pre-deinstall
new file mode 100644
index 0000000000..ce50a1b7f4
--- /dev/null
+++ b/main/sysklogd/sysklogd.pre-deinstall
@@ -0,0 +1,5 @@
+#!/bin/sh
+INIT=sysklogd
+RUNLEVEL=`rc-update show | grep $INIT | awk '{ print $3 }'`
+rc-update del $INIT $RUNLEVEL &>/dev/null
+rc-update add syslog $RUNLEVEL &>/dev/null
diff --git a/main/sysklogd/syslog.conf b/main/sysklogd/syslog.conf
new file mode 100644
index 0000000000..aead955ccf
--- /dev/null
+++ b/main/sysklogd/syslog.conf
@@ -0,0 +1,48 @@
+# /etc/syslog.conf Configuration file for syslogd.
+#
+# For more information see syslog.conf(5)
+# manpage.
+
+# First some standard logfiles. Log by facility.
+#
+
+auth,authpriv.* /var/log/auth.log
+*.*;auth,authpriv.none -/var/log/syslog
+cron.* /var/log/cron.log
+daemon.* -/var/log/daemon.log
+kern.* -/var/log/kern.log
+lpr.* -/var/log/lpr.log
+mail.* -/var/log/mail.log
+user.* -/var/log/user.log
+
+# Logging for the mail system. Split it up so that
+# it is easy to write scripts to parse these files.
+#
+#mail.info -/var/log/mail.info
+#mail.warning -/var/log/mail.warn
+#mail.err /var/log/mail.err
+
+# Some `catch-all' logfiles.
+#
+*.=debug;\
+ auth,authpriv.none;\
+ news.none;mail.none -/var/log/debug
+*.=info;*.=notice;*.=warning;\
+ auth,authpriv.none;\
+ cron,daemon.none;\
+ mail,news.none -/var/log/messages
+
+#
+# Emergencies are sent to everybody logged in.
+#
+*.emerg *
+
+#
+# I like to have messages displayed on the console, but only on a virtual
+# console I usually leave idle.
+#
+#daemon,mail.*;\
+# news.=crit;news.=err;news.=notice;\
+# *.=debug;*.=info;\
+# *.=notice;*.=warning /dev/tty8
+
diff --git a/main/syslinux/APKBUILD b/main/syslinux/APKBUILD
new file mode 100644
index 0000000000..1097c7e9f3
--- /dev/null
+++ b/main/syslinux/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=syslinux
+pkgver=4.04
+pkgrel=3
+pkgdesc="a boot loader for the Linux operating system which operates off an MS-DOS/Windows FAT filesystem."
+url="http://syslinux.org"
+arch="x86 x86_64"
+license="GPL"
+makedepends="nasm perl"
+depends="mtools blkid"
+triggers="syslinux.trigger:/boot"
+source="http://www.kernel.org/pub/linux/utils/boot/syslinux/${pkgver%%.*}.xx/$pkgname-$pkgver.tar.bz2
+ extlinux.conf
+ update-extlinux
+ "
+subpackages="$pkgname-doc"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ unset LDFLAGS
+ make installer || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make INSTALLROOT="$pkgdir" MANDIR=/usr/share/man local-install
+
+ mkdir -p "$pkgdir"/etc
+ cp "$srcdir"/extlinux.conf "$pkgdir"/etc/
+ cp "$srcdir"/update-extlinux "$pkgdir"/sbin/
+}
+
+md5sums="a3936208767eb7ced65320abe2e33a10 syslinux-4.04.tar.bz2
+37f8ae1cbb41b68241d6027abd828318 extlinux.conf
+0d769b8a7c01137535bbd26f130a0658 update-extlinux"
diff --git a/main/syslinux/extlinux.conf b/main/syslinux/extlinux.conf
new file mode 100644
index 0000000000..05bdcc935b
--- /dev/null
+++ b/main/syslinux/extlinux.conf
@@ -0,0 +1,26 @@
+# configuration for extlinux config builder
+
+# fancy_menu
+# use fancy vesa menu (vesamenu.c32) menus, won't work with serial
+fancy_menu=0
+
+# default_kernel_opts
+# default kernel options
+default_kernel_opts=quiet
+
+# modules
+# modules which should be loaded before pivot_root
+modules=sd-mod,usb-storage,ext3
+
+# root
+# root device - if not specified, will be guessed using
+# blkid -o export /dev/root
+root=
+
+# verbose
+# if set to non-zero, update-extlinux will be a lot more verbose.
+verbose=0
+
+# hidden
+# if set to non-zero, the boot menu will be hidden by default.
+hidden=1
diff --git a/main/syslinux/syslinux-3.86-nopie.patch b/main/syslinux/syslinux-3.86-nopie.patch
new file mode 100644
index 0000000000..262a4c15ca
--- /dev/null
+++ b/main/syslinux/syslinux-3.86-nopie.patch
@@ -0,0 +1,11 @@
+--- ./com32/MCONFIG.orig
++++ ./com32/MCONFIG
+@@ -25,6 +25,8 @@
+ $(call gcc_ok,-falign-loops=0,-malign-loops=0) \
+ $(call gcc_ok,-mpreferred-stack-boundary=2,) \
+ $(call gcc_ok,-mincoming-stack-boundary=2,) \
++ $(call gcc_ok,-nopie,) \
++ $(call gcc_ok,-fno-pie,) \
+ -march=i386 -Os -fomit-frame-pointer -mregparm=3 -DREGPARM=3
+
+ com32 = $(topdir)/com32
diff --git a/main/syslinux/syslinux.trigger b/main/syslinux/syslinux.trigger
new file mode 100644
index 0000000000..1e463cddae
--- /dev/null
+++ b/main/syslinux/syslinux.trigger
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+update-extlinux
diff --git a/main/syslinux/update-extlinux b/main/syslinux/update-extlinux
new file mode 100755
index 0000000000..25585334be
--- /dev/null
+++ b/main/syslinux/update-extlinux
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+default=0
+timeout=5
+verbose=0
+
+# read in extlinux settings
+source /etc/extlinux.conf
+
+everbose() {
+ if [ "$verbose" = "0" ]; then
+ return
+ fi
+
+ echo $*
+}
+
+everbose "Updating extlinux configuration."
+
+if [ "x$root" = "x" ]; then
+ everbose "WARNING: Root device not specified, determining automatically."
+ everbose -n "Root device is: "
+ export `blkid -o export /dev/root`
+ root=UUID=$UUID
+ everbose $root
+fi
+
+everbose "Installing mboot.c32 to /boot."
+cp /usr/share/syslinux/mboot.c32 /boot
+
+everbose "Installing menu.c32 to /boot."
+cp /usr/share/syslinux/menu.c32 /boot
+
+rtimeout=$((${timeout}\*10))
+# vesa menu has been requested?
+if [ "$fancy_menu" = "1" ]; then
+ everbose "Installing vesamenu.c32 to /boot."
+ cp /usr/share/syslinux/vesamenu.c32 /boot
+
+ echo "DEFAULT vesamenu.c32" > /boot/extlinux.conf.new
+ echo "PROMPT 0" >> /boot/extlinux.conf.new
+ echo "MENU TITLE Alpine/$(uname -s) Boot Menu" >> /boot/extlinux.conf.new
+ if [ "$hidden" = "1" ]; then
+ echo "MENU HIDDEN" >> /boot/extlinux.conf.new
+ fi
+ echo "MENU AUTOBOOT Alpine will be booted automatically in # seconds." >> /boot/extlinux.conf.new
+ echo "TIMEOUT $rtimeout" >> /boot/extlinux.conf.new
+else
+ echo "DEFAULT menu.c32" > /boot/extlinux.conf.new
+ echo "PROMPT 0" >> /boot/extlinux.conf.new
+ echo "MENU TITLE Alpine/$(uname -s) Boot Menu" >> /boot/extlinux.conf.new
+ if [ "$hidden" = "1" ]; then
+ echo "MENU HIDDEN" >> /boot/extlinux.conf.new
+ fi
+ echo "MENU AUTOBOOT Alpine will be booted automatically in # seconds." >> /boot/extlinux.conf.new
+ echo "TIMEOUT $rtimeout" >> /boot/extlinux.conf.new
+fi
+
+lst=0
+for kernel in $(find /boot -name vmlinuz-* -type f); do
+ tag=$(basename $kernel | cut -b9-)
+ everbose "Found kernel: $kernel"
+
+ if [ -f "/boot/initramfs-$tag" ]; then
+ everbose "Found initramfs: /boot/initramfs-$tag"
+ initramfs="initrd=initramfs-$tag"
+ fi
+
+ echo "LABEL $lst" >> /boot/extlinux.conf.new
+ if [ "$lst" = "$default" ]; then
+ echo " MENU DEFAULT" >> /boot/extlinux.conf.new
+ fi
+ echo " MENU LABEL Linux $tag" >> /boot/extlinux.conf.new
+ echo " KERNEL $(basename $kernel)" >> /boot/extlinux.conf.new
+ echo " APPEND $initramfs root=$root modules=$modules,$TYPE $default_kernel_opts" >> /boot/extlinux.conf.new
+ lst=$(($lst + 1))
+done
+
+if [ -f "/boot/memtest" ]; then
+ everbose "Found memtest86+: /boot/memtest"
+ echo "LABEL $lst" >> /boot/extlinux.conf.new
+ echo " MENU LABEL Memtest86+" >> /boot/extlinux.conf.new
+ echo " KERNEL memtest" >> /boot/extlinux.conf.new
+ lst=$(($lst + 1))
+fi
+
+everbose "$lst entries found."
+
+mv /boot/extlinux.conf.new /boot/extlinux.conf
diff --git a/main/sysstat/APKBUILD b/main/sysstat/APKBUILD
new file mode 100644
index 0000000000..e8a6113167
--- /dev/null
+++ b/main/sysstat/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sysstat
+pkgver=10.0.1
+pkgrel=0
+pkgdesc="Performance monitoring tools for Linux"
+url="http://pagesperso-orange.fr/sebastien.godard/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+subpackages="$pkgname-doc"
+source="http://pagesperso-orange.fr/sebastien.godard/sysstat-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="a8b12230452dc0e0b6cae5fd5ec3c579 sysstat-10.0.1.tar.gz"
diff --git a/main/taglib/APKBUILD b/main/taglib/APKBUILD
new file mode 100644
index 0000000000..19803f3666
--- /dev/null
+++ b/main/taglib/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=taglib
+pkgver=1.7
+pkgrel=1
+pkgdesc="library for reading and editing the meta-data of several popular audio formats."
+url="http://ktown.kde.org/~wheeler/taglib.html"
+arch="all"
+license="GPL2"
+makedepends="zlib-dev cmake"
+depends=
+source="http://ktown.kde.org/~wheeler/files/src/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-dev"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DWITH_ASF=ON -DWITH_MP4=ON || return 1
+ make VERBOSE=1 || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="6a7e312668f153fa905a81714aebc257 taglib-1.7.tar.gz"
diff --git a/main/talloc/APKBUILD b/main/talloc/APKBUILD
new file mode 100644
index 0000000000..1dacfa6625
--- /dev/null
+++ b/main/talloc/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=talloc
+pkgver=2.0.5
+pkgrel=2
+pkgdesc="memory pool management library"
+url="http://talloc.samba.org/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev=
+replaces="samba-common"
+makedepends="$depends_dev python"
+install=""
+subpackages="$pkgname-dev"
+source="http://samba.org/ftp/${pkgname}/${pkgname}-${pkgver}.tar.gz
+ always-libs.patch"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --disable-python \
+ --sysconfdir=/etc || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="6e3fdfbc43dde8ccba27b6af894b8fb2 talloc-2.0.5.tar.gz
+10304afbc3b00346238bf5a969227c68 always-libs.patch"
diff --git a/main/talloc/always-libs.patch b/main/talloc/always-libs.patch
new file mode 100644
index 0000000000..e9658d4b98
--- /dev/null
+++ b/main/talloc/always-libs.patch
@@ -0,0 +1,10 @@
+--- ./buildtools/wafsamba/samba_conftests.py.orig
++++ ./buildtools/wafsamba/samba_conftests.py
+@@ -186,6 +186,7 @@
+ msg = "rpath library support"
+ else:
+ msg = "building library support"
++ return True
+
+ dir = find_config_dir(conf)
+
diff --git a/main/tango-icon-theme/APKBUILD b/main/tango-icon-theme/APKBUILD
new file mode 100644
index 0000000000..ecc608f85b
--- /dev/null
+++ b/main/tango-icon-theme/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tango-icon-theme
+pkgver=0.8.90
+pkgrel=1
+pkgdesc="The Tango Desktop Project exists to create a consistent user experience"
+url="http://tango.freedesktop.org"
+arch="all"
+license="CCPL-Attribution-ShareAlike-2.5"
+depends=
+makedepends="pkgconfig intltool icon-naming-utils imagemagick-dev libiconv-dev"
+source="http://tango.freedesktop.org/releases/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build () {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -D COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="0795895d2f20eddcbd2bffe94ed431a6 tango-icon-theme-0.8.90.tar.gz"
diff --git a/main/tar/APKBUILD b/main/tar/APKBUILD
new file mode 100644
index 0000000000..1e54f4c30b
--- /dev/null
+++ b/main/tar/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=tar
+pkgver=1.26
+pkgrel=1
+pkgdesc="Utility used to store, backup, and transport files"
+url="http://www.gnu.org"
+arch="all"
+license='GPL'
+depends=
+install=
+makedepends=
+source="ftp://ftp.gnu.org/gnu/tar/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir/" install
+ mkdir "$pkgdir"/bin
+ mv "$pkgdir"/usr/bin/tar "$pkgdir"/bin/
+ ln -s /bin/tar "$pkgdir"/usr/bin/tar
+}
+
+md5sums="00d1e769c6af702c542cca54b728920d tar-1.26.tar.gz"
diff --git a/main/tcl/APKBUILD b/main/tcl/APKBUILD
new file mode 100644
index 0000000000..d557705656
--- /dev/null
+++ b/main/tcl/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=tcl
+pkgver=8.5.10
+pkgrel=0
+pkgdesc="The Tcl scripting language"
+url="http://tcl.sourceforge.net/"
+arch="all"
+license="custom"
+depends=
+makedepends=""
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname$pkgver-src.tar.gz"
+subpackages="$pkgname-doc $pkgname-dev"
+
+build ()
+{
+ cd "$srcdir"/tcl${pkgver}/unix
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --disable-64bit
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/tcl${pkgver}/unix
+ make INSTALL_ROOT="${pkgdir}" install install-private-headers
+ ln -sf tclsh8.5 "${pkgdir}"/usr/bin/tclsh
+ install -Dm644 ../license.terms ${pkgdir}/usr/share/licenses/${pkgname}/LICENSE
+ sed -i \
+ -e "s,^TCL_BUILD_LIB_SPEC='-L.*/unix,TCL_BUILD_LIB_SPEC='-L/usr/lib," \
+ -e "s,^TCL_SRC_DIR='.*',TCL_SRC_DIR='/usr/include'," \
+ -e "s,^TCL_BUILD_STUB_LIB_SPEC='-L.*/unix,TCL_BUILD_STUB_LIB_SPEC='-L/usr/lib," \
+ -e "s,^TCL_BUILD_STUB_LIB_PATH='.*/unix,TCL_BUILD_STUB_LIB_PATH='/usr/lib," \
+ -e "s,^TCL_LIB_FILE='libtcl8.5..TCL_DBGX..so',TCL_LIB_FILE=\"libtcl8.5\$\{TCL_DBGX\}.so\"," \
+ -e "s,^TCL_CC_SEARCH_FLAGS='\(.*\)',TCL_CC_SEARCH_FLAGS='\1:/usr/lib'," \
+ -e "s,^TCL_LD_SEARCH_FLAGS='\(.*\)',TCL_LD_SEARCH_FLAGS='\1:/usr/lib'," \
+ "${pkgdir}"/usr/lib/tclConfig.sh
+}
+md5sums="a08eaf8467c0631937067c1948dd326b tcl8.5.10-src.tar.gz"
diff --git a/main/tcpdump/APKBUILD b/main/tcpdump/APKBUILD
new file mode 100644
index 0000000000..b86328fbc5
--- /dev/null
+++ b/main/tcpdump/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tcpdump
+pkgver=4.1.1
+pkgrel=2
+pkgdesc="A tool for network monitoring and data acquisition"
+url="http://www.tcpdump.org"
+arch="all"
+license="BSD"
+depends=
+makedepends="libpcap-dev openssl-dev"
+source="http://www.$pkgname.org/release/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-doc"
+
+build ()
+{
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --enable-ipv6
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+ rm -f "$pkgdir"/usr/sbin/tcpdump.4*
+}
+
+md5sums="d0dd58bbd6cd36795e05c6f1f74420b0 tcpdump-4.1.1.tar.gz"
diff --git a/main/tcpflow/APKBUILD b/main/tcpflow/APKBUILD
new file mode 100644
index 0000000000..b5cdb8034f
--- /dev/null
+++ b/main/tcpflow/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tcpflow
+pkgver=0.21
+pkgrel=2
+pkgdesc="A Tool for monitoring, capturing and storing TCP connections flows"
+url="http://www.circlemud.org/~jelson/software/tcpflow/"
+arch="all"
+license="GPL"
+depends=
+makedepends="libpcap-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://www.circlemud.org/pub/jelson/tcpflow/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="45a5aef6f043312315b7f342afc4a9c5 tcpflow-0.21.tar.gz"
diff --git a/main/tcpproxy/APKBUILD b/main/tcpproxy/APKBUILD
new file mode 100644
index 0000000000..4c3e2d88f1
--- /dev/null
+++ b/main/tcpproxy/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+pkgname=tcpproxy
+pkgver=2.0.0_beta15
+_realver=2.0.0-beta15
+pkgrel=2
+pkgdesc="Transparent TCP Proxy"
+url="http://www.quietsche-entchen.de/cgi-bin/wiki.cgi/proxies/TcpProxy"
+arch="all"
+license="GPL"
+depends=
+makedepends="ctags"
+install=""
+subpackages=""
+source="http://www.quietsche-entchen.de/download/$pkgname-$_realver.tar.gz
+ tcpproxy.initd"
+
+build() {
+ cd "$srcdir/$pkgname-$_realver"
+
+ make || return 1
+
+ install -m755 -D "$pkgname" "$pkgdir"/usr/sbin/"$pkgname"
+ install -Dm 755 "$startdir"/$pkgname.initd $pkgdir/etc/init.d/$pkgname
+}
+
+md5sums="e946f807049d6296f54aa57b5c17f1c8 tcpproxy-2.0.0-beta15.tar.gz
+f13fccf076e24df1352dfb884aa7b880 tcpproxy.initd"
diff --git a/main/tcpproxy/tcpproxy.initd b/main/tcpproxy/tcpproxy.initd
new file mode 100644
index 0000000000..a7fd4292db
--- /dev/null
+++ b/main/tcpproxy/tcpproxy.initd
@@ -0,0 +1,14 @@
+#!/sbin/runscript
+
+DAEMON=/usr/sbin/tcpproxy
+start() {
+ ebegin "Starting tcpproxy"
+ start-stop-daemon -S -x $DAEMON -- $TCPPROXY_OPTS
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping tcpproxy"
+ start-stop-daemon -K -x $DAEMON
+ eend $?
+}
diff --git a/main/terminal/APKBUILD b/main/terminal/APKBUILD
new file mode 100644
index 0000000000..71a8eb238b
--- /dev/null
+++ b/main/terminal/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=terminal
+pkgver=0.4.8
+pkgrel=0
+pkgdesc="A modern terminal emulator primarly for the Xfce desktop environment"
+url="http://www.xfce.org/projects/terminal/"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-doc"
+depends="startup-notification hicolor-icon-theme"
+makedepends="pkgconfig exo-dev vte-dev dbus-glib-dev gettext-dev libiconv-dev
+ intltool ncurses-dev"
+install=
+source="http://archive.xfce.org/src/apps/${pkgname}/0.4/Terminal-${pkgver}.tar.bz2
+ "
+
+build() {
+ cd "$srcdir"/Terminal-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/Terminal-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="8dff62234da14e1a5e542fb56560ebe2 Terminal-0.4.8.tar.bz2"
diff --git a/main/terminal/terminal-dont-die-on-dbus-kill.patch b/main/terminal/terminal-dont-die-on-dbus-kill.patch
new file mode 100644
index 0000000000..3b0da17098
--- /dev/null
+++ b/main/terminal/terminal-dont-die-on-dbus-kill.patch
@@ -0,0 +1,10 @@
+--- a/terminal/terminal-dbus.c.orig 2007-01-23 22:25:12.000000000 +0000
++++ b/terminal/terminal-dbus.c 2007-01-23 22:25:50.000000000 +0000
+@@ -191,6 +191,7 @@ terminal_dbus_register_service (Terminal
+
+ /* register DBus connection with GLib main loop */
+ dbus_connection_setup_with_g_main (connection, NULL);
++ dbus_connection_set_exit_on_disconnect (connection, FALSE);
+
+ if (dbus_bus_request_name (connection, TERMINAL_DBUS_SERVICE, 0, &derror) < 0)
+ {
diff --git a/main/testdisk/APKBUILD b/main/testdisk/APKBUILD
new file mode 100644
index 0000000000..fad8dde909
--- /dev/null
+++ b/main/testdisk/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=testdisk
+pkgver=6.12
+pkgrel=0
+pkgdesc="A data recovery suite"
+url="http://www.cgsecurity.org/wiki/TestDisk"
+arch="all"
+license="GPL"
+depends=
+makedepends="e2fsprogs-dev ncurses-dev zlib-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://www.cgsecurity.org/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="6ef653301f309156f3a802233a3139c1 testdisk-6.12.tar.bz2"
diff --git a/main/texinfo/APKBUILD b/main/texinfo/APKBUILD
new file mode 100644
index 0000000000..1e5436c012
--- /dev/null
+++ b/main/texinfo/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=texinfo
+pkgver=4.13a
+pkgrel=3
+pkgdesc="Utilities to work with and produce manuals, ASCII text, and on-line documentation from a single source file"
+url="http://www.gnu.org/software/texinfo/"
+arch="all"
+license='GPL3'
+depends=
+makedepends="ncurses-dev"
+source="ftp://ftp.gnu.org/pub/gnu/${pkgname}/${pkgname}-${pkgver}.tar.gz"
+subpackages="$pkgname-doc"
+
+build() {
+ cd ${srcdir}/${pkgname}-4.13
+ ./configure --prefix=/usr || return 1
+ make || return 1
+ make DESTDIR=${pkgdir} install || return 1
+ rm -f ${pkgdir}/usr/share/info/dir
+ gzip ${pkgdir}/usr/share/info/*
+}
+
+md5sums="71ba711519209b5fb583fed2b3d86fcb texinfo-4.13a.tar.gz"
diff --git a/main/tftp-hpa/APKBUILD b/main/tftp-hpa/APKBUILD
new file mode 100644
index 0000000000..02106e049a
--- /dev/null
+++ b/main/tftp-hpa/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tftp-hpa
+pkgver=5.0
+pkgrel=2
+pkgdesc="Official tftp server"
+url="http://www.kernel.org/pub/software/network/tftp/"
+arch="all"
+license="BSD"
+depends=
+makedepends=
+subpackage="$pkgname-doc"
+source="http://www.kernel.org/pub/software/network/tftp/$pkgname-$pkgver.tar.gz
+ in.tftpd.initd
+ in.tftpd.confd
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make INSTALLROOT="$pkgdir" install || return 1
+ install -d "$pkgdir"/var/tftpboot
+ install -Dm755 ../in.tftpd.initd "$pkgdir"/etc/init.d/in.tftpd
+ install -Dm755 ../in.tftpd.confd "$pkgdir"/etc/conf.d/in.tftpd
+}
+md5sums="1ae813a94670f0d8c294aafa9f5ecf65 tftp-hpa-5.0.tar.gz
+3430e0b0e42c3321689d2c87e73d0749 in.tftpd.initd
+914b43dd531176a8bb58fdb23d900fef in.tftpd.confd"
diff --git a/main/tftp-hpa/in.tftpd.confd b/main/tftp-hpa/in.tftpd.confd
new file mode 100644
index 0000000000..5d74ac15fa
--- /dev/null
+++ b/main/tftp-hpa/in.tftpd.confd
@@ -0,0 +1,15 @@
+# /etc/init.d/in.tftpd
+
+# Path to server files from
+# Depending on your application you may have to change this.
+INTFTPD_PATH="/var/tftpboot/"
+#INTFTPD_PATH="/var/tftp/"
+#INTFTPD_PATH="/tftpboot/"
+#INTFTPD_PATH="/tftproot/"
+
+# For more options, see in.tftpd(8)
+# -R 4096:32767 solves problems with ARC firmware, and obsoletes
+# the /proc/sys/net/ipv4/ip_local_port_range hack.
+# -s causes $INTFTPD_PATH to be the root of the TFTP tree.
+# -l is passed by the init script in addition to these options.
+INTFTPD_OPTS="-R 4096:32767 -s ${INTFTPD_PATH}"
diff --git a/main/tftp-hpa/in.tftpd.initd b/main/tftp-hpa/in.tftpd.initd
new file mode 100644
index 0000000000..c8657634bf
--- /dev/null
+++ b/main/tftp-hpa/in.tftpd.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-ftp/tftp-hpa/files/in.tftpd.rc6,v 1.2 2005/07/30 06:29:14 vapier Exp $
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting tftpd"
+ /usr/sbin/in.tftpd -l ${INTFTPD_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping tftpd"
+ start-stop-daemon --stop --exec /usr/sbin/in.tftpd
+ eend $?
+}
diff --git a/main/thunar-archive-plugin/APKBUILD b/main/thunar-archive-plugin/APKBUILD
new file mode 100644
index 0000000000..7ad5fc5b3c
--- /dev/null
+++ b/main/thunar-archive-plugin/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=thunar-archive-plugin
+pkgver=0.3.0
+pkgrel=0
+pkgdesc="create and deflate archives in thunar"
+url="http://foo-projects.org/~benny/projects/thunar-archive-plugin/"
+arch="all"
+license="GPL2"
+depends=
+makedepends="gtk+-dev intltool thunar-dev exo-dev"
+install=
+source="http://archive.xfce.org/src/thunar-plugins/thunar-archive-plugin/${pkgver%.*}/thunar-archive-plugin-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ # dont want file-roller
+ rm -f "$pkgdir"/usr/lib/xfce4/thunar-archive-plugin/file-roller.tap
+}
+md5sums="afeb3f1c65a4529dbdadc6e7b349a712 thunar-archive-plugin-0.3.0.tar.bz2"
diff --git a/main/thunar/APKBUILD b/main/thunar/APKBUILD
new file mode 100644
index 0000000000..0b17f33961
--- /dev/null
+++ b/main/thunar/APKBUILD
@@ -0,0 +1,62 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=thunar
+pkgver=1.3.0
+pkgrel=1
+pkgdesc="File manager for Xfce"
+url="http://thunar.xfce.org"
+arch="all"
+license="GPL2 LGPL2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="desktop-file-utils hicolor-icon-theme shared-mime-info"
+makedepends="libexif-dev xfce4-panel-dev exo-dev pcre-dev udev-dev
+ libnotify-dev startup-notification-dev libxfce4ui-dev dbus-glib-dev"
+install=
+source="http://archive.xfce.org/src/xfce/thunar/${pkgver%.*}/Thunar-$pkgver.tar.bz2
+ thunar-sendto-audacious-playlist.desktop
+ thunar-sendto-bluetooth.desktop
+ "
+
+depends_dev="gtk+-dev glib-dev exo-dev"
+_builddir="$srcdir"/Thunar-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # fix icon in thunar-sendto-email.desktop
+ sed -i 's!internet-mail!mail-message-new!' \
+ plugins/thunar-sendto-email/thunar-sendto-email.desktop.in.in
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-exif \
+ --enable-pcre \
+ --enable-dbus \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ local f
+ make DESTDIR="$pkgdir" install || return 1
+ sed -i -e 's:x-directory/gnome-default-handler;::' \
+ "$pkgdir"/usr/share/applications/Thunar-folder-handler.desktop
+ for f in $source; do
+ case $f in
+ thunar-sendto*.desktop)
+ install -m644 "$srcdir"/$f \
+ "$pkgdir"/usr/share/Thunar/sendto/ || return 1
+ ;;
+ esac
+ done
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="ab6f728384c0d925b40afae2f41268f3 Thunar-1.3.0.tar.bz2
+5a1e2ed692f3f95113339f5646f83af3 thunar-sendto-audacious-playlist.desktop
+1131368b7360a0132d5b36ff2cae898a thunar-sendto-bluetooth.desktop"
diff --git a/main/thunar/thunar-sendto-audacious-playlist.desktop b/main/thunar/thunar-sendto-audacious-playlist.desktop
new file mode 100644
index 0000000000..97f9853180
--- /dev/null
+++ b/main/thunar/thunar-sendto-audacious-playlist.desktop
@@ -0,0 +1,14 @@
+[Desktop Entry]
+Version=1.0
+Name=Audacious Playlist
+Name[de]=Audacious Wiedergabeliste
+GenericName=Audio Playlist
+GenericName[de]= Wiedergabeliste
+Comment=Enque files to playlist
+Comment[de]=Dateien zur Wiedergabeliste hinzufügen
+Exec=audacious -e %F
+TryExec=audacious
+Icon=audacious
+MimeType=audio/prs.sid;audio/x-flac;audio/x-it;audio/x-mod;audio/x-ms-wma;audio/x-musepack;audio/x-s3m;audio/x-stm;audio/x-xm;application/ogg;audio/x-vorbis+ogg;inode/directory;
+Terminal=false
+Type=Application
diff --git a/main/thunar/thunar-sendto-bluetooth.desktop b/main/thunar/thunar-sendto-bluetooth.desktop
new file mode 100644
index 0000000000..98899f69ab
--- /dev/null
+++ b/main/thunar/thunar-sendto-bluetooth.desktop
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Version=1.0
+Name=Bluetooth OBEX Recipient
+Name[de]=Bluetooth OBEX Empfänger
+GenericName=Bluetooth Recipient
+GenericName[de]=Bluetooth Empfänger
+Comment=Send selected files via Bluetooth
+Comment[de]=Ausgewählte Dateien per Bluetooth senden
+Exec=bluetooth-sendto %F
+TryExec=bluetooth-sendto
+Icon=bluetooth
+Terminal=false
+Type=Application
diff --git a/main/thunar/thunar.post-deinstall b/main/thunar/thunar.post-deinstall
new file mode 120000
index 0000000000..b2d507f24a
--- /dev/null
+++ b/main/thunar/thunar.post-deinstall
@@ -0,0 +1 @@
+thunar.post-install \ No newline at end of file
diff --git a/main/thunar/thunar.post-install b/main/thunar/thunar.post-install
new file mode 100644
index 0000000000..591dfaf728
--- /dev/null
+++ b/main/thunar/thunar.post-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+update-desktop-database -q
+gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+
diff --git a/main/thunar/thunar.post-upgrade b/main/thunar/thunar.post-upgrade
new file mode 120000
index 0000000000..b2d507f24a
--- /dev/null
+++ b/main/thunar/thunar.post-upgrade
@@ -0,0 +1 @@
+thunar.post-install \ No newline at end of file
diff --git a/main/tiff/APKBUILD b/main/tiff/APKBUILD
new file mode 100644
index 0000000000..2764544fe3
--- /dev/null
+++ b/main/tiff/APKBUILD
@@ -0,0 +1,60 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=tiff
+pkgver=3.9.5
+pkgrel=0
+pkgdesc="Provides support for the Tag Image File Format or TIFF"
+url="http://www.libtiff.org/"
+arch="all"
+license="GPL"
+depends=
+depends_dev="zlib-dev jpeg-dev"
+makedepends="libtool autoconf automake $depends_dev"
+subpackages="$pkgname-doc $pkgname-dev $pkgname-tools"
+source="ftp://ftp.remotesensing.org/pub/libtiff/$pkgname-$pkgver.tar.gz
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ local _failed=
+ cd "$_builddir"
+
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || _failed="$_failed $i";;
+ esac
+ done
+
+ rm -f libtool.m4
+ libtoolize --force --copy \
+ && aclocal -I . -I m4 \
+ && automake --add-missing --copy \
+ && autoconf \
+ && autoheader
+}
+
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-cxx
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+tools() {
+ pkgdesc="Command-line utility programs for manipulating TIFF files"
+ mkdir -p "$subpkgdir"/usr/
+ mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
+}
+
+md5sums="8fc7ce3b4e1d0cc8a319336967815084 tiff-3.9.5.tar.gz"
diff --git a/main/tig/APKBUILD b/main/tig/APKBUILD
new file mode 100644
index 0000000000..7b82d72fc6
--- /dev/null
+++ b/main/tig/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer:
+pkgname=tig
+pkgver=0.17
+pkgrel=1
+pkgdesc="Text-mode interface for git"
+url="http://jonas.nitro.dk/tig/"
+arch="all"
+license="GPL"
+depends=
+depends_dev="libiconv-dev ncurses-dev"
+makedepends="$depends_dev asciidoc"
+install=""
+subpackages="$pkgname-doc"
+source="http://jonas.nitro.dk/tig/releases/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install install-doc || return 1
+
+}
+
+md5sums="f373343199422c59518776db448dec0e tig-0.17.tar.gz"
diff --git a/main/tinc/APKBUILD b/main/tinc/APKBUILD
new file mode 100644
index 0000000000..f2bf612ae0
--- /dev/null
+++ b/main/tinc/APKBUILD
@@ -0,0 +1,51 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tinc
+pkgver=1.0.13
+pkgrel=1
+pkgdesc="tinc is a Virtual Private Network (VPN) daemon"
+url="http://www.tinc-vpn.org/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="zlib-dev lzo-dev openssl-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://www.tinc-vpn.org/packages/tinc-$pkgver.tar.gz
+ tincd.initd
+ tincd.lo.initd
+ tinc.networks"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-jumbograms \
+ --enable-lzo \
+ --enable-zlib
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+
+ mkdir "$pkgdir"/etc/tinc
+ install -m755 -D "$srcdir"/tincd.initd "$pkgdir"/etc/init.d/tincd
+ install -m755 -D "$srcdir"/tincd.lo.initd \
+ "$pkgdir"/etc/init.d/tincd.lo
+ install -m644 -D "$srcdir"/tinc.networks \
+ "$pkgdir"/etc/conf.d/tinc.networks
+}
+
+md5sums="86263994d38c750431efd17e9a91a248 tinc-1.0.13.tar.gz
+89d104d38bab84d6f92d27464e48628d tincd.initd
+96d8778284637fa7790a4c6239a72070 tincd.lo.initd
+475d64d9aa410ec7e91f5b079800abc9 tinc.networks"
diff --git a/main/tinc/tinc.networks b/main/tinc/tinc.networks
new file mode 100644
index 0000000000..e1844ce2ba
--- /dev/null
+++ b/main/tinc/tinc.networks
@@ -0,0 +1,13 @@
+# file: /etc/conf.d/tinc.networks for /etc/init.d/tincd
+
+# In this file you define the tinc networks you want to connect to
+
+# USAGE:
+# you add a network to the init script by defining:
+# NETWORK: your_network_name
+#
+# if you want to connect to multiple VPN's just set them behind each other. e.g.
+# NETWORK: foo
+# NETWORK: bar
+#
+# this would join the network foo and the network bar.
diff --git a/main/tinc/tincd.initd b/main/tinc/tincd.initd
new file mode 100644
index 0000000000..452687dfb6
--- /dev/null
+++ b/main/tinc/tincd.initd
@@ -0,0 +1,64 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/tinc/files/tincd,v 1.5 2008/04/01 14:08:45 dragonheart Exp $
+
+opts="reload"
+
+depend() {
+ use logger dns
+ need net
+}
+
+checkconfig() {
+ if ! grep -q '^ *NETWORK:' /etc/conf.d/tinc.networks
+ then
+ eerror "No VPN networks configured in /etc/conf.d/tinc.networks"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting tinc VPN networks"
+ eend 0
+ awk '/^ *NETWORK:/ { print $2 }' /etc/conf.d/tinc.networks | while read TINCNET
+ do
+ if [ ! -f /etc/tinc/"$TINCNET"/tinc.conf ]
+ then
+ eerror "Cannot start network $TINCNET, /etc/tinc/$TINCNET/tinc.conf does not exist !"
+ else
+ ebegin "Starting tinc network $TINCNET"
+ /usr/sbin/tincd --net="$TINCNET" --logfile=/var/log/tinc.$TINCNET.log --pidfile=/var/run/tinc.$TINCNET.pid
+ eend $?
+ fi
+ done
+}
+
+stop() {
+ ebegin "Stopping tinc VPN networks"
+ eend 0
+ awk '/^ *NETWORK:/ { print $2 }' /etc/conf.d/tinc.networks | while read TINCNET
+ do
+ if [ -f /var/run/tinc."$TINCNET".pid ]
+ then
+ ebegin "Stopping tinc network $TINCNET"
+ /usr/sbin/tincd --kill --pidfile=/var/run/tinc."$TINCNET".pid
+ eend $?
+ fi
+ done
+}
+
+reload() {
+ ebegin "Reloading configuration for tinc VPN networks"
+ eend 0
+ awk '/^ *NETWORK:/ { print $2 }' /etc/conf.d/tinc.networks | while read TINCNET
+ do
+ if [ -f /var/run/tinc."$TINCNET".pid ]
+ then
+ ebegin "Reloading tinc network $TINCNET"
+ /usr/sbin/tincd --kill HUP --pidfile=/var/run/tinc."$TINCNET".pid
+ eend $?
+ fi
+ done
+}
diff --git a/main/tinc/tincd.lo.initd b/main/tinc/tincd.lo.initd
new file mode 100644
index 0000000000..79c185b381
--- /dev/null
+++ b/main/tinc/tincd.lo.initd
@@ -0,0 +1,46 @@
+#!/sbin/runscript
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/tinc/files/tincd.lo,v 1.1 2010/07/18 10:04:56 dragonheart Exp $
+
+opts="reload"
+
+depend()
+{
+ use logger dns
+ need net
+}
+
+start()
+{
+ TINCNET=${RC_SVCNAME#*.}
+ if [ -f /etc/tinc/"$TINCNET"/tinc.conf ] ; then
+ ebegin "Starting tinc network $TINCNET"
+ /usr/sbin/tincd --debug=1 --net="$TINCNET" --logfile=/var/log/tinc.$TINCNET.log --pidfile=/var/run/tinc.$TINCNET.pid
+ eend $?
+ else
+ eerror "Cannot start network $TINCNET, /etc/tinc/$TINCNET/tinc.conf does not exist !"
+ fi
+}
+
+stop()
+{
+ TINCNET=${RC_SVCNAME#*.}
+ if [ -f /var/run/tinc."$TINCNET".pid ] ; then
+ ebegin "Stopping tinc network $TINCNET"
+ /usr/sbin/tincd --kill --pidfile=/var/run/tinc."$TINCNET".pid
+ eend $?
+ else
+ eerror "Cannot start network $TINCNET, /etc/tinc/$TINCNET/tinc.conf does not exist !"
+ fi
+}
+
+reload()
+{
+ TINCNET=${RC_SVCNAME#*.}
+ if [ -f /var/run/tinc."$TINCNET".pid ] ; then
+ ebegin "Reloading configuration for tinc network $TINCNET"
+ /usr/sbin/tincd --kill HUP --pidfile=/var/run/tinc."$TINCNET".pid
+ eend $?
+ fi
+}
diff --git a/main/tinyproxy/APKBUILD b/main/tinyproxy/APKBUILD
new file mode 100644
index 0000000000..625a46d60b
--- /dev/null
+++ b/main/tinyproxy/APKBUILD
@@ -0,0 +1,41 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=tinyproxy
+pkgver=1.6.5
+pkgrel=6
+pkgdesc="Lightweight HTTP proxy"
+pkgusers="tinyproxy"
+pkggroups="tinyproxy"
+url="https://www.banu.com/tinyproxy/"
+arch="all"
+license="GPL"
+depends=
+makedepends=wget
+install="tinyproxy.pre-install tinyproxy.post-install"
+subpackages="$pkgname-doc"
+source="https://www.banu.com/pub/$pkgname/1.6/$pkgname-$pkgver.tar.gz
+ tinyproxy.initd
+ "
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ # set default user to tinyproxy:tinyproxy and correct pidfile
+ sed -i -e 's:^User.*:User tinyproxy:' \
+ -e 's:^Group.*:Group tinyproxy:' \
+ -e 's:^PidFile.*:PidFile "/var/run/tinyproxy/tinyproxy.pid":' \
+ doc/tinyproxy.conf
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+
+ make || return 1
+ make DESTDIR="$pkgdir" install
+ install -d -D -o tinyproxy -g tinyproxy "$pkgdir"/var/run/tinyproxy
+ install -Dm755 "$srcdir"/tinyproxy.initd "$pkgdir"/etc/init.d/tinyproxy
+}
+
+md5sums="2b2862ba33d2939e4572688d442ba415 tinyproxy-1.6.5.tar.gz
+ce2b2e3c79fa0e8491fe625bbb15710a tinyproxy.initd"
diff --git a/main/tinyproxy/tinyproxy.initd b/main/tinyproxy/tinyproxy.initd
new file mode 100644
index 0000000000..1037f9c288
--- /dev/null
+++ b/main/tinyproxy/tinyproxy.initd
@@ -0,0 +1,46 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-proxy/tinyproxy/files/tinyproxy.initd,v 1.1 2008/02/16 07:11:25 mrness Exp $
+
+CONFFILE="/etc/tinyproxy/${SVCNAME}.conf"
+
+depend() {
+ use logger dns
+ need net
+ after firewall
+}
+
+checkconfig() {
+ if [ ! -f "${CONFFILE}" ]; then
+ eerror "Configuration file ${CONFFILE} not found!"
+ return 1
+ fi
+
+ PIDFILE=$(sed -n -e 's/^[[:space:]]*PidFile[[:space:]]\+"\(.*\)"[[:space:]]*$/\1/p' "${CONFFILE}")
+ return 0
+}
+
+start() {
+ checkconfig || return 1
+
+ ebegin "Starting tinyproxy"
+ if [ -n "${PIDFILE}" ]; then
+ start-stop-daemon --start --pidfile "${PIDFILE}" --startas /usr/sbin/tinyproxy -- -c "${CONFFILE}"
+ else
+ start-stop-daemon --start --exec /usr/sbin/tinyproxy -- -c "${CONFFILE}"
+ fi
+ eend $?
+}
+
+stop() {
+ checkconfig || return 1
+
+ ebegin "Stopping tinyproxy"
+ if [ -n "${PIDFILE}" ]; then
+ start-stop-daemon --stop --pidfile "${PIDFILE}"
+ else
+ start-stop-daemon --stop --exec /usr/sbin/tinyproxy
+ fi
+ eend $?
+}
diff --git a/main/tinyproxy/tinyproxy.post-install b/main/tinyproxy/tinyproxy.post-install
new file mode 100755
index 0000000000..ef518c6162
--- /dev/null
+++ b/main/tinyproxy/tinyproxy.post-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+chown tinyproxy:tinyproxy /var/run/tinyproxy
+
+# return with success even if user already exist
+exit 0
diff --git a/main/tinyproxy/tinyproxy.pre-install b/main/tinyproxy/tinyproxy.pre-install
new file mode 100755
index 0000000000..d324b044e3
--- /dev/null
+++ b/main/tinyproxy/tinyproxy.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+adduser -h /dev/null -s /bin/false -D tinyproxy 2>/dev/null
+
+# return with success even if user already exist
+exit 0
diff --git a/main/tmux/APKBUILD b/main/tmux/APKBUILD
new file mode 100644
index 0000000000..fcc10dcb2e
--- /dev/null
+++ b/main/tmux/APKBUILD
@@ -0,0 +1,32 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tmux
+pkgver=1.4
+pkgrel=1
+pkgdesc="Tool to control multiple terminals from a single terminal"
+url="http://tmux.sourceforge.net/"
+arch="all"
+license="BSD"
+depends=""
+makedepends="ncurses-dev libevent-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" PREFIX=/usr install
+ # the configure script/makefile does not give us possibility to
+ # change mandir
+ mkdir "$pkgdir"/usr/share
+ mv "$pkgdir"/usr/man "$pkgdir"/usr/share/
+}
+
+md5sums="0bfc7dd9a5bab192406167589c716a21 tmux-1.4.tar.gz"
diff --git a/main/tolua++/APKBUILD b/main/tolua++/APKBUILD
new file mode 100644
index 0000000000..1a821aaeeb
--- /dev/null
+++ b/main/tolua++/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tolua++
+pkgver=1.0.93
+pkgrel=2
+pkgdesc="a tool to integrate C/C++ code with Lua"
+url="http://www.codenix.com/~tolua/"
+arch="all"
+license="MIT"
+depends=
+makedepends="lua-dev"
+install=
+subpackages=
+source="http://www.codenix.com/~tolua/tolua++-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"/src
+ # see http://lua-users.org/wiki/CompilingToluappWithoutScons
+ gcc -fPIC -c lib/*.c -I../include
+ ar rcsv libtolua++.a *.o
+ gcc bin/tolua.c bin/toluabind.c -I../include -L. -llua -ltolua++ \
+ -o tolua++
+}
+
+package() {
+ cd "$_builddir"/src
+ install -d "$pkgdir"/usr/lib/ "$pkgdir"/usr/bin "$pkgdir"/usr/include
+ install libtolua++.a "$pkgdir"/usr/lib/
+ install tolua++ "$pkgdir"/usr/bin/
+ install ../include/tolua++.h "$pkgdir"/usr/include/
+}
+
+md5sums="100aa6907b8108582080b37d79c0afd7 tolua++-1.0.93.tar.bz2"
diff --git a/main/trac/APKBUILD b/main/trac/APKBUILD
new file mode 100644
index 0000000000..c6cf392e40
--- /dev/null
+++ b/main/trac/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=trac
+_realname=Trac
+pkgver=0.12.2
+pkgrel=1
+pkgusers="tracd"
+pkggroups="tracd"
+pkgdesc="Trac is a minimalistic web-based project management, wiki and bug/issue tracking system."
+url="http://trac.edgewall.com/"
+arch="noarch"
+license="GPL"
+depends="python py-setuptools py-genshi"
+makedepends="python-dev"
+install="$pkgname.pre-install"
+source="ftp://ftp.edgewall.com/pub/$pkgname/$_realname-$pkgver.tar.gz
+ tracd.confd
+ tracd.initd"
+
+_builddir="$srcdir"/$_realname-$pkgver
+
+build() {
+ cd "$_builddir"
+ python setup.py install --prefix=/usr --root="$pkgdir"
+}
+
+package() {
+ cd "$_builddir"
+ install -d -o tracd -g tracd "$pkgdir"/var/lib/trac
+ install -m755 -D "$srcdir"/tracd.initd "$pkgdir"/etc/init.d/tracd
+ install -m644 -D "$srcdir"/tracd.confd "$pkgdir"/etc/conf.d/tracd
+}
+
+md5sums="f70c7676601f2592bcb7871319e62dd7 Trac-0.12.2.tar.gz
+95b1311ca65e1ffcd51a191542f45ba4 tracd.confd
+e53761b1e84c5d68c8e6c4b837e57008 tracd.initd"
diff --git a/main/trac/trac.pre-install b/main/trac/trac.pre-install
new file mode 100644
index 0000000000..05c659552b
--- /dev/null
+++ b/main/trac/trac.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup tracd 2>/dev/null
+adduser -s /bin/false -G tracd -D -H tracd 2>/dev/null
+exit 0
diff --git a/main/trac/tracd.confd b/main/trac/tracd.confd
new file mode 100644
index 0000000000..2cb9d292a7
--- /dev/null
+++ b/main/trac/tracd.confd
@@ -0,0 +1,13 @@
+# The commented variables in this file are the defaults that are used
+# in the init-script. You don't need to uncomment them except to
+# customize them to different values.
+
+# Port for tracd
+#TRACD_PORT="8000"
+
+# Options for tracd
+#TRACD_OPTS="--env-parent-dir /var/lib/trac/"
+
+# User and group as which to run tracd
+#TRACD_USER="tracd"
+#TRACD_GROUP="tracd"
diff --git a/main/trac/tracd.initd b/main/trac/tracd.initd
new file mode 100755
index 0000000000..83f84052d3
--- /dev/null
+++ b/main/trac/tracd.initd
@@ -0,0 +1,27 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/www-apps/trac/files/tracd.initd,v 1.4 2010/05/28 14:43:40 arfrever Exp $
+
+depend() {
+ need net
+}
+
+start() {
+ ebegin "Starting tracd"
+ # tracd fails to create pidfile if started as non-root user, thus we are asking
+ # s-s-d to do that. To have correct pid we avoid -d option of tracd and use
+ # --background option of s-s-d.
+ start-stop-daemon --start --chuid ${TRACD_USER:-tracd}:${TRACD_GROUP:-tracd} \
+ --pidfile /var/run/tracd.pid --make-pidfile --background \
+ --env PYTHON_EGG_CACHE="/var/lib/trac/egg-cache" \
+ --exec /usr/bin/python -- /usr/bin/tracd \
+ -p ${TRACD_PORT:-8000} ${TRACD_OPTS:---env-parent-dir /var/lib/trac/}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping tracd"
+ start-stop-daemon --stop --quiet --pidfile /var/run/tracd.pid
+ eend $?
+}
diff --git a/main/transmission/APKBUILD b/main/transmission/APKBUILD
new file mode 100644
index 0000000000..bb68ec724b
--- /dev/null
+++ b/main/transmission/APKBUILD
@@ -0,0 +1,68 @@
+# Maintainer:Carlo Landmeter
+pkgname=transmission
+pkgver=2.22
+pkgrel=0
+pkgdesc="Lightweight GTK BitTorrent client"
+url="http://www.tansmissionbt.com"
+install="$pkgname.pre-install"
+arch="all"
+license="MIT"
+depends=
+makedepends="openssl-dev pkgconfig curl-dev gtk+-dev intltool libevent-dev
+ libnotify-dev dbus-glib-dev autoconf automake"
+source="http://download.m0k.org/transmission/files/transmission-$pkgver.tar.bz2
+ transmission-daemon.initd
+ transmission-daemon.confd
+ "
+subpackages="$pkgname-cli $pkgname-daemon $pkgname-doc"
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+daemon() {
+ pkgdesc="Lightweight BitTorrent client (daemon and webinterface)"
+ install -d "$subpkgdir"/usr/share "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/transmission-daemon "$subpkgdir"/usr/bin/
+ mv "$pkgdir"/usr/share/transmission "$subpkgdir"/usr/share/
+ install -D -m755 "$srcdir"/transmission-daemon.initd \
+ "$subpkgdir"/etc/init.d/transmission-daemon
+ install -D -m644 "$srcdir"/transmission-daemon.confd \
+ "$subpkgdir"/etc/conf.d/transmission-daemon
+}
+
+cli() {
+ pkgdesc="Lightweight BitTorrent client (cli and remote)"
+ install -d "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/transmission-cli \
+ "$pkgdir"/usr/bin/transmission-create \
+ "$pkgdir"/usr/bin/transmission-edit \
+ "$pkgdir"/usr/bin/transmission-show \
+ "$subpkgdir"/usr/bin/
+}
+
+md5sums="6499986bf769276310b00bda1090090d transmission-2.22.tar.bz2
+f65b8ae46f8ac89b35844109b3aa0c18 transmission-daemon.initd
+89478a70fcd93463e1dd8d751da994da transmission-daemon.confd"
diff --git a/main/transmission/transmission-daemon.confd b/main/transmission/transmission-daemon.confd
new file mode 100644
index 0000000000..c1f338f07c
--- /dev/null
+++ b/main/transmission/transmission-daemon.confd
@@ -0,0 +1,18 @@
+#
+# transmission-daemon options
+#
+# -a --acl <list> Access Control List. (Default: +127.0.0.1)
+# -b --blocklist Enable peer blocklists
+# -B --no-blocklist Disable peer blocklists
+# -f --foreground Run in the foreground instead of daemonizing
+# -g --config-dir <path> Where to look for configuration files
+# -p --port <port> RPC port (Default: 9091)
+# -t --auth Require authentication
+# -T --no-auth Don't require authentication
+# -u --username <username> Set username for authentication
+# -v --password <password> Set password for authentication
+# -w --download-dir <path> Where to save downloaded data
+#
+# NOTE: webif does not work without the -f switch
+#
+TD_OPTS="-f -g /var/lib/transmission/.config -w /var/lib/transmission"
diff --git a/main/transmission/transmission-daemon.initd b/main/transmission/transmission-daemon.initd
new file mode 100644
index 0000000000..ecf3bdafef
--- /dev/null
+++ b/main/transmission/transmission-daemon.initd
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting transmission-daemon"
+ start-stop-daemon --start --quiet --background --make-pidfile \
+ --chuid transmission:transmission \
+ --pidfile /var/run/transmission-daemon.pid \
+ --exec /usr/bin/transmission-daemon -- ${TD_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping transmission-daemon"
+ start-stop-daemon --stop --quiet \
+ --pidfile /var/run/transmission-daemon.pid \
+ eend $?
+}
diff --git a/main/transmission/transmission.pre-install b/main/transmission/transmission.pre-install
new file mode 100644
index 0000000000..44a14760f6
--- /dev/null
+++ b/main/transmission/transmission.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -h /var/lib/transmission -s /bin/false -D transmission 2>/dev/null
+
+exit 0
diff --git a/main/ttf-dejavu/APKBUILD b/main/ttf-dejavu/APKBUILD
new file mode 100644
index 0000000000..e64d5c9c62
--- /dev/null
+++ b/main/ttf-dejavu/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ttf-dejavu
+pkgver=2.33
+pkgrel=0
+arch="noarch"
+pkgdesc="Font family based on the Bitstream Vera Fonts with a wider range of characters"
+url="http://dejavu.sourceforge.net/"
+license="custom"
+depends="fontconfig encodings mkfontdir mkfontscale"
+makedepends="pkgconfig font-util-dev"
+install=
+source="http://downloads.sourceforge.net/project/dejavu/dejavu/${pkgver}/dejavu-fonts-ttf-${pkgver}.tar.bz2
+ http://downloads.sourceforge.net/project/dejavu/dejavu/${pkgver}/dejavu-lgc-fonts-ttf-${pkgver}.tar.bz2
+ "
+
+build() {
+ return 0
+}
+
+package() {
+ mkdir -p "$pkgdir/usr/share/fonts/TTF" \
+ "$pkgdir"/etc/fonts/conf.avail \
+ || return 1
+ for i in dejavu-fonts-ttf-$pkgver dejavu-lgc-fonts-ttf-$pkgver; do
+ cd "$srcdir"/$i
+ install -m644 ttf/*.ttf "$pkgdir"/usr/share/fonts/TTF/ \
+ || return 1
+ install -m644 fontconfig/*.conf \
+ "$pkgdir"/etc/fonts/conf.avail/ || return 1
+ done
+ install -D -m644 LICENSE \
+ "$pkgdir/usr/share/licenses/ttf-dejavu/LICENSE" || return 1
+}
+
+md5sums="8b601e91725b6d69141b0fcf527948c0 dejavu-fonts-ttf-2.33.tar.bz2
+fde03af699ccf8833f09d7002e3060ef dejavu-lgc-fonts-ttf-2.33.tar.bz2"
diff --git a/main/ttf-freefont/APKBUILD b/main/ttf-freefont/APKBUILD
new file mode 100644
index 0000000000..6ec0683fbc
--- /dev/null
+++ b/main/ttf-freefont/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ttf-freefont
+pkgver=20100919
+pkgrel=0
+pkgdesc="A set of free high-quality TrueType fonts covering the UCS character set"
+url="http://www.nongnu.org/freefont/"
+arch="noarch"
+license="GPL"
+depends="fontconfig encodings mkfontdir mkfontscale"
+makedepends="pkgconfig font-util-dev"
+install=
+source="http://ftp.gnu.org/gnu/freefont/freefont-ttf-$pkgver.tar.gz"
+
+_builddir="$srcdir/freefont-$pkgver"
+build() {
+ return 0
+}
+
+package() {
+ cd "$_builddir"
+ install -d "$pkgdir/usr/share/fonts/TTF"
+ install -m644 *.ttf "$pkgdir/usr/share/fonts/TTF/"
+}
+
+md5sums="33d96c755d0a6f585bc917f08cbddf66 freefont-ttf-20100919.tar.gz"
diff --git a/main/ttf-linux-libertine/APKBUILD b/main/ttf-linux-libertine/APKBUILD
new file mode 100644
index 0000000000..b4445fc840
--- /dev/null
+++ b/main/ttf-linux-libertine/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ttf-linux-libertine
+pkgver=5.1.3
+_date="2011_06_15"
+pkgrel=0
+pkgdesc="Serif (Libertine) and Sans Serif (Biolinum) OpenType fonts with large Unicode coverage"
+url="http://linuxlibertine.sourceforge.net/"
+arch="noarch"
+license="GPL custom:OFL"
+makedepends=
+depends="fontconfig encodings mkfontdir mkfontscale"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/project/linuxlibertine/linuxlibertine/$pkgver/LinLibertineTTF-${pkgver}_$_date.tgz"
+
+_builddir="$srcdir"
+build () {
+ local f
+ # strip off the version numbers from the filenames.
+ cd "$_builddir"
+ for f in *.ttf; do
+ mv $f ${f%-[0-9]*}.ttf
+ done
+}
+
+package() {
+ cd "$_builddir"
+ install -d -m 755 "$pkgdir"/usr/share/fonts/TTF
+ install -m644 *.ttf "$pkgdir"/usr/share/fonts/TTF || return 1
+ install -D -m644 OFL.txt "$pkgdir"/usr/share/licenses/$pkgname/LICENSE || return 1
+ install -D -m644 LICENCE.txt "$pkgdir"/usr/share/licenses/$pkgname/README || return 1
+}
+md5sums="9164f5e202b1912015e43718fba94cc3 LinLibertineTTF-5.1.3_2011_06_15.tgz"
diff --git a/main/ttf-ubuntu-font-family/APKBUILD b/main/ttf-ubuntu-font-family/APKBUILD
new file mode 100644
index 0000000000..5c7fb17019
--- /dev/null
+++ b/main/ttf-ubuntu-font-family/APKBUILD
@@ -0,0 +1,29 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=ttf-ubuntu-font-family
+pkgver=0.70.1
+pkgrel=0
+pkgdesc="Ubuntu font family"
+url="http://font.ubuntu.com/"
+arch="noarch"
+license="Custom"
+depends=
+depends_dev=
+makedepends="$depends_dev zip"
+install=""
+subpackages=
+source="http://font.ubuntu.com/download/ubuntu-font-family-${pkgver}.zip"
+
+_builddir="${srcdir}/ubuntu-font-family-${pkgver}"
+package() {
+ cd "$_builddir"
+
+ install -d "$pkgdir/usr/share/fonts/TTF"
+ install -m644 *.ttf "$pkgdir/usr/share/fonts/TTF/"
+
+ install -m644 -D LICENCE.txt "$pkgdir"/usr/share/licenses/$pkgname/LICENCE.txt
+ install -m644 -D LICENCE-FAQ.txt "$pkgdir"/usr/share/licenses/$pkgname/LICENCE-FAQ.txt
+ install -m644 -D TRADEMARKS.txt "$pkgdir"/usr/share/licenses/$pkgname/TRADEMARKS.txt
+}
+
+md5sums="ec2e9b6535c74a654cc6bd2d935b5856 ubuntu-font-family-0.70.1.zip"
diff --git a/main/tumbler/APKBUILD b/main/tumbler/APKBUILD
new file mode 100644
index 0000000000..c1698b5613
--- /dev/null
+++ b/main/tumbler/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tumbler
+pkgver=0.1.21
+pkgrel=1
+pkgdesc="D-Bus service for applications to request thumbnails"
+url="http://git.xfce.org/apps/tumbler/"
+arch="all"
+license="GPL2"
+depends=
+makedepends="gtk+-dev dbus-glib-dev jpeg-dev poppler-gtk-dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://archive.xfce.org/src/apps/tumbler/${pkgver%.*}/tumbler-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/tumbler-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="2ef0d30750f95efe345de4655049d4f6 tumbler-0.1.21.tar.bz2"
diff --git a/main/tzdata/0001-posixtz-fix-up-lseek.patch b/main/tzdata/0001-posixtz-fix-up-lseek.patch
new file mode 100644
index 0000000000..1db3eba9eb
--- /dev/null
+++ b/main/tzdata/0001-posixtz-fix-up-lseek.patch
@@ -0,0 +1,27 @@
+From 5c4cd3cee03428636e8d7cc4ed644389a4d598b3 Mon Sep 17 00:00:00 2001
+From: William Pitcock <nenolod@dereferenced.org>
+Date: Thu, 28 Apr 2011 02:56:42 -0500
+Subject: [PATCH] posixtz: ensure the file offset we pass to lseek is off_t
+
+on 32-bit systems, sizeof(off_t) is 4, on 64-bit sizeof(off_t) is 8
+causing a word masking issue.
+---
+ posixtz.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/posixtz.c b/posixtz.c
+index cddcb3e..972ca31 100644
+--- a/posixtz-0.3/posixtz.c
++++ b/posixtz-0.3/posixtz.c
+@@ -36,7 +36,7 @@ char *posix_tz(const char *filename)
+ if (r != TZ_BUFLEN
+ || strncmp(buf, "TZif", 4) != 0
+ || (unsigned char)buf[4] < 2
+- || lseek(fd, -TZ_BUFLEN, SEEK_END) < 0
++ || lseek(fd, (off_t) -TZ_BUFLEN, SEEK_END) < 0
+ )
+ goto ERROR;
+
+--
+1.7.4.5
+
diff --git a/main/tzdata/APKBUILD b/main/tzdata/APKBUILD
new file mode 100644
index 0000000000..fbdf20749d
--- /dev/null
+++ b/main/tzdata/APKBUILD
@@ -0,0 +1,53 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tzdata
+pkgver=2011g
+_ptzver=0.3
+pkgrel=0
+pkgdesc="Timezone data"
+url="http://www.twinsun.com/tz/tz-link.htm"
+arch="all"
+license="Public Domain"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="ftp://elsie.nci.nih.gov/pub/tzcode$pkgver.tar.gz
+ ftp://elsie.nci.nih.gov/pub/tzdata$pkgver.tar.gz
+ http://git.alpinelinux.org/cgit/ncopa/posixtz.git/snapshot/posixtz-$_ptzver.tar.bz2
+ Makefile.patch
+ 0001-posixtz-fix-up-lseek.patch"
+
+_builddir="$srcdir"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+
+ cd "$srcdir"/posixtz-$_ptzver
+ make posixtz
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/share/zoneinfo/localtime
+
+ install -Dm755 "$srcdir"/posixtz-$_ptzver/posixtz \
+ "$pkgdir"/usr/bin/posixtz
+}
+
+md5sums="ecb564279b28c5b184421c525d997d6c tzcode2011g.tar.gz
+a068c27e7e426fdb12ab0c88506df20d tzdata2011g.tar.gz
+99efce32b3f870e1b071ce47f3a98a18 posixtz-0.3.tar.bz2
+a64ed97d1fc03c66ee8612c0d9f40507 Makefile.patch
+0b4d86d855f7daa3f79c9f28f04a48f9 0001-posixtz-fix-up-lseek.patch"
diff --git a/main/tzdata/Makefile.patch b/main/tzdata/Makefile.patch
new file mode 100644
index 0000000000..e88f9d9074
--- /dev/null
+++ b/main/tzdata/Makefile.patch
@@ -0,0 +1,140 @@
+diff -Naur src/Makefile src-p/Makefile
+--- src/Makefile 2007-08-20 16:47:41.000000000 +0200
++++ src-p/Makefile 2007-10-02 04:07:44.000000000 +0200
+@@ -34,17 +34,17 @@
+
+ # Everything gets put in subdirectories of. . .
+
+-TOPDIR= /usr/local
++TOPDIR= $(DESTDIR)/usr
+
+ # "Compiled" time zone information is placed in the "TZDIR" directory
+ # (and subdirectories).
+ # Use an absolute path name for TZDIR unless you're just testing the software.
+
+-TZDIR= $(TOPDIR)/etc/zoneinfo
++TZDIR= $(TOPDIR)/share/zoneinfo
+
+ # The "tzselect", "zic", and "zdump" commands get installed in. . .
+
+-ETCDIR= $(TOPDIR)/etc
++SBINDIR= $(TOPDIR)/sbin
+
+ # If you "make INSTALL", the "date" command gets installed in. . .
+
+@@ -52,7 +52,7 @@
+
+ # Manual pages go in subdirectories of. . .
+
+-MANDIR= $(TOPDIR)/man
++MANDIR= $(TOPDIR)/share/man
+
+ # Library functions are put in an archive in LIBDIR.
+
+@@ -83,7 +83,7 @@
+
+ # Non-default libraries needed to link.
+ # Add -lintl if you want to use `gettext' on Solaris.
+-LDLIBS=
++LDLIBS=$(LDFLAGS)
+
+ # Add the following to the end of the "CFLAGS=" line as needed.
+ # -Dconst= if `const' does not work (SunOS 4.x cc, OSF1 V5.0 cc)
+@@ -211,7 +211,7 @@
+ # before the first Monday in January when a "%V" format is used and January 1
+ # falls on a Friday, Saturday, or Sunday.
+
+-CFLAGS=
++CFLAGS += -std=gnu99
+
+ # If you want zic's -s option used when installing, uncomment the next line
+ # ZFLAGS= -s
+@@ -220,7 +220,7 @@
+ ZIC= $(zic) $(ZFLAGS)
+
+ # The name of a Posix-compliant `awk' on your system.
+-AWK= nawk
++AWK= awk
+
+ # The path where SGML DTDs are kept.
+ SGML_SEARCH_PATH= $(TOPDIR)/share/doc/sgml-lib/REC-html401-19991224/
+@@ -241,8 +241,10 @@
+
+ ###############################################################################
+
+-cc= cc
+-CC= $(cc) -DTZDIR=\"$(TZDIR)\"
++CC+= -DTZDIR=\"$(TZDIR)\"
++ifeq ($(NLS),1)
++CC += -DHAVE_GETTEXT=1 -DTZ_DOMAIN=\"libc\"
++endif
+
+ TZCSRCS= zic.c localtime.c asctime.c scheck.c ialloc.c
+ TZCOBJS= zic.o localtime.o asctime.o scheck.o ialloc.o
+@@ -282,14 +284,16 @@
+
+ ALL: all date
+
+-install: all $(DATA) $(REDO) $(TZLIB) $(MANS) $(TABDATA)
++install: all $(DATA) $(REDO) $(MANS) $(TABDATA)
+ $(ZIC) -y $(YEARISTYPE) \
+ -d $(TZDIR) -l $(LOCALTIME) -p $(POSIXRULES)
+ -rm -f $(TZDIR)/iso3166.tab $(TZDIR)/zone.tab
+ cp iso3166.tab zone.tab $(TZDIR)/.
+- -mkdir $(TOPDIR) $(ETCDIR)
+- cp tzselect zic zdump $(ETCDIR)/.
+- -mkdir $(TOPDIR) $(MANDIR) \
++ -mkdir -p $(TOPDIR) $(SBINDIR)
++ cp zic zdump $(SBINDIR)/.
++ -mkdir -p $(TOPDIR) $(BINDIR)
++ cp tzselect $(BINDIR)/.
++ -mkdir -p $(TOPDIR) $(MANDIR) \
+ $(MANDIR)/man3 $(MANDIR)/man5 $(MANDIR)/man8
+ -rm -f $(MANDIR)/man3/newctime.3 \
+ $(MANDIR)/man3/newtzset.3 \
+@@ -298,13 +302,11 @@
+ $(MANDIR)/man8/zdump.8 \
+ $(MANDIR)/man8/zic.8
+ cp newctime.3 newtzset.3 $(MANDIR)/man3/.
+- cp tzfile.5 $(MANDIR)/man5/.
+- cp tzselect.8 zdump.8 zic.8 $(MANDIR)/man8/.
+
+ INSTALL: ALL install date.1
+- -mkdir $(TOPDIR) $(BINDIR)
++ -mkdir -p $(TOPDIR) $(BINDIR)
+ cp date $(BINDIR)/.
+- -mkdir $(TOPDIR) $(MANDIR) $(MANDIR)/man1
++ -mkdir -p $(TOPDIR) $(MANDIR) $(MANDIR)/man1
+ -rm -f $(MANDIR)/man1/date.1
+ cp date.1 $(MANDIR)/man1/.
+
+@@ -334,9 +336,9 @@
+ # You must replace all of $(TZDIR) to switch from not using leap seconds
+ # to using them, or vice versa.
+ other_two: zic leapseconds $(TDATA)
+- $(ZIC) -y $(YEARISTYPE) -d $(TZDIR)-posix -L /dev/null $(TDATA)
++ $(ZIC) -y $(YEARISTYPE) -d $(TZDIR)/posix -L /dev/null $(TDATA)
+ $(ZIC) -y $(YEARISTYPE) \
+- -d $(TZDIR)-leaps -L leapseconds $(TDATA)
++ -d $(TZDIR)/right -L leapseconds $(TDATA)
+
+ posix_right: posix_only other_two
+
+@@ -367,7 +369,7 @@
+ <$? >$@
+ chmod +x $@
+
+-check: check_tables check_web
++check: check_tables
+
+ check_tables: checktab.awk $(PRIMARY_YDATA)
+ $(AWK) -f checktab.awk $(PRIMARY_YDATA)
+diff -Naur src/tzselect.ksh src-p/tzselect.ksh
+--- src/tzselect.ksh 2007-08-20 16:47:42.000000000 +0200
++++ src-p/tzselect.ksh 2007-10-02 04:07:44.000000000 +0200
+@@ -1,4 +1,4 @@
+-#! /bin/ksh
++#! /bin/bash
+
+ # '@(#)tzselect.ksh 8.1'
+
diff --git a/main/ucarp/APKBUILD b/main/ucarp/APKBUILD
new file mode 100644
index 0000000000..c32b9feec7
--- /dev/null
+++ b/main/ucarp/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer:
+pkgname=ucarp
+pkgver=1.5.2
+pkgrel=4
+pkgdesc="Share common IP and do fail over"
+url="http://www.ucarp.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="libpcap-dev"
+install=
+subpackages=""
+source="http://download.pureftpd.org/pub/ucarp/$pkgname-$pkgver.tar.gz
+ ucarp.initd
+ ucarp.confd"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+}
+
+md5sums="e3caa733316a32c09e5d3817617e9145 ucarp-1.5.2.tar.gz
+f73f9da77f874a3cd6b4e48ba6094363 ucarp.initd
+bf914f6ce4fe4fea33a45d4d5b2c1fff ucarp.confd"
diff --git a/main/ucarp/ucarp.confd b/main/ucarp/ucarp.confd
new file mode 100644
index 0000000000..824358b430
--- /dev/null
+++ b/main/ucarp/ucarp.confd
@@ -0,0 +1,13 @@
+# Things you can set here
+# REALIP - if not set, will be first addr on iface
+# VHID - Virtual Server ID
+# VIP - The Virtual IP
+# PASSWORD - The password for the carp announcements
+# EXTRA_ARGS - extra arguments
+
+REALIP=
+VHID=2
+VIP=127.0.0.1
+PASSWORD=SecretPassword
+#EXTRA_ARGS="--neutral --advbase=3"
+
diff --git a/main/ucarp/ucarp.initd b/main/ucarp/ucarp.initd
new file mode 100755
index 0000000000..cc09ad05e1
--- /dev/null
+++ b/main/ucarp/ucarp.initd
@@ -0,0 +1,67 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+
+# A simple script to start and stop a ucarp instance
+DAEMON=/usr/sbin/ucarp
+
+IFACE="${SVCNAME#*.}"
+if [ -n "$IFACE" ] && [ "${SVCNAME}" != "ucarp" ]; then
+ UP="/etc/ucarp/vip-up-$IFACE.sh"
+ DOWN="/etc/ucarp/vip-down-$IFACE.sh"
+ . /etc/conf.d/ucarp.$IFACE
+else
+ UP="/etc/ucarp/vip-up.sh"
+ DOWN="/etc/ucarp/vip-down.sh"
+fi
+
+
+# Get the primary ip address for a given interface
+get_first_ip() {
+ local foo=$( ip addr show $1 )
+ [ $? != 0 ] && foo=""
+ echo $( echo "$foo" | grep "inet " | head -n1 | \
+ sed "s+^.*inet ++g; s+/.*$++g" )
+}
+
+if [ -z "$REALIP" ]; then
+ REALIP=$( get_first_ip $IFACE )
+fi
+
+depend () {
+ need net
+ after firewall
+}
+
+start () {
+ ebegin "Starting ucarp $IFACE"
+ start-stop-daemon --start --exec $DAEMON \
+ --background -m -p /var/run/ucarp-$IFACE.pid -- \
+ -i $IFACE -s $REALIP -v $VHID -p $PASSWORD -a $VIP \
+ -u $UP -d $DOWN $EXTRA_ARGS -z
+ eend $?
+}
+
+status () {
+ ebegin "ucarp $IFACE is ..."
+ PIDS=$( pidof $( basename $DAEMON ))
+ PID=$( cat /var/run/ucarp-$IFACE.pid 2>/dev/null )
+ [ -n "$PID" ] && OK=$( echo "$PIDS" | grep "$PID" )
+ if [ -n "$OK" ]; then
+ echo "running"
+ exit 0
+ else
+ echo "not running"
+ exit 1
+ fi
+}
+
+stop () {
+ ebegin "Shutting down ucarp $IFACE"
+ start-stop-daemon --stop --exec $DAEMON \
+ -p /var/run/ucarp-$IFACE.pid
+ eend $?
+}
+
diff --git a/main/uclibc++/001-path_to_make.patch b/main/uclibc++/001-path_to_make.patch
new file mode 100644
index 0000000000..840dac3266
--- /dev/null
+++ b/main/uclibc++/001-path_to_make.patch
@@ -0,0 +1,30 @@
+diff -ur old/Makefile dev/Makefile
+--- old/Makefile Sat Oct 14 17:49:55 2006
++++ dev/Makefile Sat Oct 14 17:50:18 2006
+@@ -1,4 +1,3 @@
+-MAKE = make
+ SUBDIRS = bin include src
+
+ # User defines:
+@@ -43,10 +42,10 @@
+ #Menu configuration system
+
+ extra/config/conf:
+- make -C extra/config conf
++ $(MAKE) -C extra/config conf
+
+ extra/config/mconf:
+- make -C extra/config ncurses mconf
++ $(MAKE) -C extra/config ncurses mconf
+
+ menuconfig: extra/config/mconf
+ @./extra/config/mconf extra/Configs/Config.in
+@@ -71,7 +70,7 @@
+
+ include/system_configuration.h: .config
+ @if [ ! -x ./extra/config/conf ] ; then \
+- make -C extra/config conf; \
++ $(MAKE) -C extra/config conf; \
+ fi;
+ @./extra/config/conf -o extra/Configs/Config.in
+
diff --git a/main/uclibc++/002-no_bash.patch b/main/uclibc++/002-no_bash.patch
new file mode 100644
index 0000000000..69b2275a5c
--- /dev/null
+++ b/main/uclibc++/002-no_bash.patch
@@ -0,0 +1,12 @@
+diff -ur old/bin/Makefile dev/bin/Makefile
+--- old/bin/Makefile Sat Oct 14 17:49:54 2006
++++ dev/bin/Makefile Sat Oct 14 17:57:33 2006
+@@ -13,7 +13,7 @@
+ $(INSTALL) -m 755 $(WRAPPER) $(PREFIX)$(UCLIBCXX_RUNTIME_BINDIR)
+
+ $(WRAPPER):
+- echo "#!/bin/bash" > $(WRAPPER)
++ echo "#!/bin/sh" > $(WRAPPER)
+ echo "" >> $(WRAPPER)
+ echo 'WRAPPER_INCLUDEDIR="$${WRAPPER_INCLUDEDIR:=-I$(UCLIBCXX_RUNTIME_INCLUDEDIR)}"' >> $(WRAPPER)
+ echo 'WRAPPER_LIBDIR="$${WRAPPER_LIBDIR:=-L$(UCLIBCXX_RUNTIME_LIBDIR)}"' >> $(WRAPPER)
diff --git a/main/uclibc++/003-cp_command.patch b/main/uclibc++/003-cp_command.patch
new file mode 100644
index 0000000000..53d0ed7af9
--- /dev/null
+++ b/main/uclibc++/003-cp_command.patch
@@ -0,0 +1,19 @@
+diff -ur old/src/Makefile dev/src/Makefile
+--- old/src/Makefile Sat Oct 14 17:49:54 2006
++++ dev/src/Makefile Sat Oct 14 18:02:30 2006
+@@ -25,12 +25,14 @@
+
+ all: libgcc_eh libsupc $(EXOBJS) $(ALLBIN)
+
++CP = cp -fPR
++
+ install:
+ $(INSTALL) -d $(PREFIX)$(UCLIBCXX_RUNTIME_LIBDIR)
+ ifneq ($(BUILD_ONLY_STATIC_LIB),y)
+ $(INSTALL) -m 755 $(SHARED_FULLNAME) \
+ $(PREFIX)$(UCLIBCXX_RUNTIME_LIBDIR)
+- cp -fa $(SHARED_MAJORNAME) $(LIBNAME).so $(PREFIX)$(UCLIBCXX_RUNTIME_LIBDIR)
++ $(CP) $(SHARED_MAJORNAME) $(LIBNAME).so $(PREFIX)$(UCLIBCXX_RUNTIME_LIBDIR)
+ endif
+ ifeq ($(BUILD_STATIC_LIB),y)
+ $(INSTALL) -m 644 $(LIBNAME).a $(PREFIX)$(UCLIBCXX_RUNTIME_LIBDIR)
diff --git a/main/uclibc++/004-ccache_fixes.patch b/main/uclibc++/004-ccache_fixes.patch
new file mode 100644
index 0000000000..10ceb792ba
--- /dev/null
+++ b/main/uclibc++/004-ccache_fixes.patch
@@ -0,0 +1,24 @@
+diff -ruN uClibc++-0.2.2-old/src/abi/libgcc_eh/Makefile uClibc++-0.2.2-new/src/abi/libgcc_eh/Makefile
+--- uClibc++-0.2.2-old/src/abi/libgcc_eh/Makefile 2007-06-04 00:51:13.000000000 +0200
++++ uClibc++-0.2.2-new/src/abi/libgcc_eh/Makefile 2007-09-03 21:51:07.000000000 +0200
+@@ -16,7 +16,7 @@
+ #
+ #else
+ # echo Binary
+- $(AR) x $(shell CC=$(CC) $(TOPDIR)/scripts/find_libgcc_eh.sh)
++ $(AR) x $(shell CC="$(CC)" $(TOPDIR)/scripts/find_libgcc_eh.sh)
+ #endif
+ #endif
+
+diff -ruN uClibc++-0.2.2-old/src/abi/libsupc/Makefile uClibc++-0.2.2-new/src/abi/libsupc/Makefile
+--- uClibc++-0.2.2-old/src/abi/libsupc/Makefile 2007-06-04 00:51:13.000000000 +0200
++++ uClibc++-0.2.2-new/src/abi/libsupc/Makefile 2007-09-03 21:51:17.000000000 +0200
+@@ -14,7 +14,7 @@
+ #
+ #else
+ # echo Binary
+- $(AR) x $(shell CC=$(CC) $(TOPDIR)/scripts/find_libsupc.sh)
++ $(AR) x $(shell CC="$(CC)" $(TOPDIR)/scripts/find_libsupc.sh)
+ $(RM) -f new_op*.o del_op*.o pure.o new_handler.o eh_alloc.o eh_globals.o
+ #
+ #endif
diff --git a/main/uclibc++/005-wrapper.patch b/main/uclibc++/005-wrapper.patch
new file mode 100644
index 0000000000..b526a901f9
--- /dev/null
+++ b/main/uclibc++/005-wrapper.patch
@@ -0,0 +1,12 @@
+diff -ruN uClibc++-0.2.2-old/bin/Makefile uClibc++-0.2.2-new/bin/Makefile
+--- uClibc++-0.2.2-old/bin/Makefile 2007-09-23 13:46:10.000000000 +0200
++++ uClibc++-0.2.2-new/bin/Makefile 2007-09-23 13:47:03.000000000 +0200
+@@ -25,7 +25,7 @@
+ echo 'while [ -n "$$1" ]' >> $(WRAPPER)
+ echo 'do' >> $(WRAPPER)
+ echo ' WRAPPER_OPTIONS="$$WRAPPER_OPTIONS $$1"' >> $(WRAPPER)
+- echo ' if [ "$$1" = "-c" -o "$$1" = "-E" -o "$$1" = "-S" ]' >> $(WRAPPER)
++ echo ' if [ "$$1" = "-c" -o "$$1" = "-E" -o "$$1" = "-S" -o "$$1" = "-MF" ]' >> $(WRAPPER)
+ echo ' then' >> $(WRAPPER)
+ echo ' WRAPPER_INCLIB="N"' >> $(WRAPPER)
+ echo ' fi' >> $(WRAPPER)
diff --git a/main/uclibc++/006-eabi_fix.patch b/main/uclibc++/006-eabi_fix.patch
new file mode 100644
index 0000000000..bc970a7169
--- /dev/null
+++ b/main/uclibc++/006-eabi_fix.patch
@@ -0,0 +1,42 @@
+Index: uClibc++-0.2.2/include/typeinfo
+===================================================================
+--- uClibc++-0.2.2.orig/include/typeinfo 2008-02-13 00:37:04.000000000 +0100
++++ uClibc++-0.2.2/include/typeinfo 2008-02-13 00:37:34.000000000 +0100
+@@ -44,6 +44,7 @@
+ class __class_type_info;
+ } // namespace __cxxabiv1
+
++#ifndef __GXX_MERGED_TYPEINFO_NAMES
+ #if !__GXX_WEAK__
+ // If weak symbols are not supported, typeinfo names are not merged.
+ #define __GXX_MERGED_TYPEINFO_NAMES 0
+@@ -51,6 +52,7 @@
+ // On platforms that support weak symbols, typeinfo names are merged.
+ #define __GXX_MERGED_TYPEINFO_NAMES 1
+ #endif
++#endif
+
+ namespace std
+ {
+Index: uClibc++-0.2.2/include/unwind-cxx.h
+===================================================================
+--- uClibc++-0.2.2.orig/include/unwind-cxx.h 2008-02-13 00:38:04.000000000 +0100
++++ uClibc++-0.2.2/include/unwind-cxx.h 2008-02-13 00:40:32.000000000 +0100
+@@ -135,6 +135,7 @@
+
+ // This is the exception class we report -- "GNUCC++\0".
+ const _Unwind_Exception_Class __gxx_exception_class
++#ifndef __ARM_EABI_UNWINDER__
+ = ((((((((_Unwind_Exception_Class) 'G'
+ << 8 | (_Unwind_Exception_Class) 'N')
+ << 8 | (_Unwind_Exception_Class) 'U')
+@@ -143,6 +144,9 @@
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '\0');
++#else
++= "GNUC++";
++#endif
+
+ // GNU C++ personality routine, Version 0.
+ extern "C" _Unwind_Reason_Code __gxx_personality_v0
diff --git a/main/uclibc++/007-numeric_limits.patch b/main/uclibc++/007-numeric_limits.patch
new file mode 100644
index 0000000000..1ed7d6c6ec
--- /dev/null
+++ b/main/uclibc++/007-numeric_limits.patch
@@ -0,0 +1,66 @@
+Index: uClibc++-0.2.2/include/limits
+===================================================================
+--- uClibc++-0.2.2/include/limits (revision 1877)
++++ uClibc++-0.2.2/include/limits (revision 1878)
+@@ -143,6 +143,53 @@
+ static T signaling_NaN();
+ };
+
++template <> class numeric_limits<bool> {
++public:
++ typedef bool T;
++ // General -- meaningful for all specializations.
++ static const bool is_specialized = true;
++ static T min(){
++ return false;
++ }
++ static T max(){
++ return true;
++ }
++ static const int radix = 2;
++ static const int digits = 1;
++ static const int digits10 = 0;
++ static const bool is_signed = false;
++ static const bool is_integer = true;
++ static const bool is_exact = true;
++ static const bool traps = false;
++ static const bool is_modulo = false;
++ static const bool is_bounded = true;
++
++ // Floating point specific.
++
++ static T epsilon(){
++ return 0;
++ }
++ static T round_error(){
++ return 0;
++ }
++ static const int min_exponent10 = 0;
++ static const int max_exponent10 = 0;
++ static const int min_exponent = 0;
++
++ static const int max_exponent = 0;
++ static const bool has_infinity = false;
++ static const bool has_quiet_NaN = false;
++ static const bool has_signaling_NaN = false;
++ static const bool is_iec559 = false;
++ static const bool has_denorm = false;
++ static const bool tinyness_before = false;
++ static const float_round_style round_style = round_indeterminate;
++ static T denorm_min();
++ static T infinity();
++ static T quiet_NaN();
++ static T signaling_NaN();
++};
++
+ template <> class numeric_limits<unsigned char> {
+ public:
+ typedef unsigned char T;
+@@ -567,6 +614,7 @@
+ };
+
+ template <> class numeric_limits<double> {
++public:
+ typedef double numeric_type;
+
+ static const bool is_specialized = true;
diff --git a/main/uclibc++/008-integer_width.patch b/main/uclibc++/008-integer_width.patch
new file mode 100644
index 0000000000..c467e60114
--- /dev/null
+++ b/main/uclibc++/008-integer_width.patch
@@ -0,0 +1,314 @@
+Index: uClibc++-0.2.2/include/ostream
+===================================================================
+--- uClibc++-0.2.2/include/ostream (revision 708)
++++ uClibc++-0.2.2/include/ostream (revision 709)
+@@ -129,6 +129,18 @@
+ return *this;
+ }
+
++ _UCXXEXPORT void printout(const char_type* s, streamsize n)
++ {
++ int extra = ios::width() - n;
++ if ((ios::flags()&ios::adjustfield) == ios::right)
++ while (extra-- > 0)
++ put(ios::fill());
++ write(s, n);
++ if ((ios::flags()&ios::adjustfield) == ios::left)
++ while (extra-- > 0)
++ put(ios::fill());
++ }
++
+ protected:
+ basic_ostream(const basic_ostream<charT,traits> &){ }
+ basic_ostream<charT,traits> & operator=(const basic_ostream<charT,traits> &){ return *this; }
+@@ -142,15 +154,15 @@
+ sentry s(*this);
+ if( basic_ios<charT,traits>::flags() & ios_base::boolalpha){
+ if(n){
+- write("true", 4);
++ printout("true", 4);
+ }else{
+- write("false", 5);
++ printout("false", 5);
+ }
+ }else{
+ if(n){
+- write("1", 1);
++ printout("1", 1);
+ }else{
+- write("0", 1);
++ printout("0", 1);
+ }
+ }
+ if(basic_ios<charT,traits>::flags() & ios_base::unitbuf){
+@@ -219,7 +231,7 @@
+ template <class charT, class traits> _UCXXEXPORT basic_ostream<charT,traits>& basic_ostream<charT, traits>::operator<<(void* p){
+ sentry s(*this);
+ char buffer[20];
+- write(buffer, snprintf(buffer, 20, "%p", p) );
++ printout(buffer, snprintf(buffer, 20, "%p", p) );
+ if(basic_ios<charT,traits>::flags() & ios_base::unitbuf){
+ flush();
+ }
+@@ -356,7 +368,7 @@
+ operator<<(basic_ostream<charT,traits>& out, const charT* c)
+ {
+ typename basic_ostream<charT,traits>::sentry s(out);
+- out.write(c, traits::length(c) );
++ out.printout(c, traits::length(c) );
+ return out;
+ }
+
+@@ -364,7 +376,7 @@
+ operator<<(basic_ostream<charT,traits>& out, const char* c)
+ {
+ typename basic_ostream<charT,traits>::sentry s(out);
+- out.write(c, char_traits<char>::length(c) );
++ out.printout(c, char_traits<char>::length(c) );
+ return out;
+ }
+
+@@ -373,7 +385,7 @@
+ operator<<(basic_ostream<char,traits>& out, const char* c)
+ {
+ typename basic_ostream<char,traits>::sentry s(out);
+- out.write(c, traits::length(c));
++ out.printout(c, traits::length(c));
+ return out;
+ }
+
+@@ -389,7 +401,7 @@
+ temp[i] = out.widen(c[i]);
+ }
+
+- out.write(temp, numChars);
++ out.printout(temp, numChars);
+ return out;
+ }
+ #endif
+@@ -399,7 +411,7 @@
+ operator<<(basic_ostream<char,traits>& out, const signed char* c)
+ {
+ typename basic_ostream<char,traits>::sentry s(out);
+- out.write(reinterpret_cast<const char *>(c), traits::length( reinterpret_cast<const char *>(c)));
++ out.printout(reinterpret_cast<const char *>(c), traits::length( reinterpret_cast<const char *>(c)));
+ return out;
+ }
+
+@@ -407,7 +419,7 @@
+ operator<<(basic_ostream<char,traits>& out, const unsigned char* c)
+ {
+ typename basic_ostream<char,traits>::sentry s(out);
+- out.write(reinterpret_cast<const char *>(c), traits::length( reinterpret_cast<const char *>(c)));
++ out.printout(reinterpret_cast<const char *>(c), traits::length( reinterpret_cast<const char *>(c)));
+ return out;
+ }
+
+Index: uClibc++-0.2.2/include/ostream_helpers
+===================================================================
+--- uClibc++-0.2.2/include/ostream_helpers (revision 708)
++++ uClibc++-0.2.2/include/ostream_helpers (revision 709)
+@@ -88,7 +88,7 @@
+ }
+ }
+
+- stream.write(buffer, snprintf(buffer, 20, formatString, n) );
++ stream.printout(buffer, snprintf(buffer, 20, formatString, n) );
+
+ if(stream.flags() & ios_base::unitbuf){
+ stream.flush();
+@@ -135,7 +135,7 @@
+ }
+ }
+
+- stream.write(buffer, snprintf(buffer, 20, formatString, n));
++ stream.printout(buffer, snprintf(buffer, 20, formatString, n));
+ if(stream.flags() & ios_base::unitbuf){
+ stream.flush();
+ }
+@@ -182,7 +182,7 @@
+ }
+ }
+
+- stream.write(buffer, snprintf(buffer, 27, formatString, n) );
++ stream.printout(buffer, snprintf(buffer, 27, formatString, n) );
+
+ if(stream.flags() & ios_base::unitbuf){
+ stream.flush();
+@@ -228,7 +228,7 @@
+ }
+ }
+
+- stream.write(buffer, snprintf(buffer, 27, formatString, n) );
++ stream.printout(buffer, snprintf(buffer, 27, formatString, n) );
+
+ if(stream.flags() & ios_base::unitbuf){
+ stream.flush();
+@@ -256,7 +256,7 @@
+ } else {
+ length = snprintf(buffer, 32, "%*.*g",static_cast<int>(stream.width()),static_cast<int>(stream.precision()), f);
+ }
+- stream.write(buffer, length);
++ stream.printout(buffer, length);
+ if(stream.flags() & ios_base::unitbuf){
+ stream.flush();
+ }
+@@ -280,7 +280,7 @@
+ } else {
+ length = snprintf(buffer, 32, "%*.*Lg", static_cast<int>(stream.width()), static_cast<int>(stream.precision()), f);
+ }
+- stream.write(buffer, length);
++ stream.printout(buffer, length);
+ if(stream.flags() & ios_base::unitbuf){
+ stream.flush();
+ }
+@@ -295,25 +295,25 @@
+ {
+ wchar_t buffer[20];
+ if( stream.flags() & ios_base::dec){
+- stream.write(buffer, swprintf(buffer, 20, L"%ld", n));
++ stream.printout(buffer, swprintf(buffer, 20, L"%ld", n));
+ }else if( stream.flags() & ios_base::oct){
+ if( stream.flags() & ios_base::showbase){
+- stream.write(buffer, swprintf(buffer, 20, L"%#lo", n));
++ stream.printout(buffer, swprintf(buffer, 20, L"%#lo", n));
+ }else{
+- stream.write(buffer, swprintf(buffer, 20, L"%lo", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%lo", n) );
+ }
+ }else if (stream.flags() & ios_base::hex){
+ if(stream.flags() & ios_base::showbase){
+ if(stream.flags() & ios_base::uppercase){
+- stream.write(buffer, swprintf(buffer, 20, L"%#lX", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%#lX", n) );
+ }else{
+- stream.write(buffer, swprintf(buffer, 20, L"%#lx", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%#lx", n) );
+ }
+ }else{
+ if(stream.flags() & ios_base::uppercase){
+- stream.write(buffer, swprintf(buffer, 20, L"%lX", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%lX", n) );
+ }else{
+- stream.write(buffer, swprintf(buffer, 20, L"%lx", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%lx", n) );
+ }
+ }
+ }
+@@ -329,25 +329,25 @@
+ {
+ wchar_t buffer[20];
+ if( stream.flags() & ios_base::dec){
+- stream.write(buffer, swprintf(buffer, 20, L"%lu", n));
++ stream.printout(buffer, swprintf(buffer, 20, L"%lu", n));
+ }else if( stream.flags() & ios_base::oct){
+ if( stream.flags() & ios_base::showbase){
+- stream.write(buffer, swprintf(buffer, 20, L"%#lo", n));
++ stream.printout(buffer, swprintf(buffer, 20, L"%#lo", n));
+ }else{
+- stream.write(buffer, swprintf(buffer, 20, L"%lo", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%lo", n) );
+ }
+ }else if (stream.flags() & ios_base::hex){
+ if(stream.flags() & ios_base::showbase){
+ if(stream.flags() & ios_base::uppercase){
+- stream.write(buffer, swprintf(buffer, 20, L"%#lX", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%#lX", n) );
+ }else{
+- stream.write(buffer, swprintf(buffer, 20, L"%#lx", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%#lx", n) );
+ }
+ }else{
+ if(stream.flags() & ios_base::uppercase){
+- stream.write(buffer, swprintf(buffer, 20, L"%lX", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%lX", n) );
+ }else{
+- stream.write(buffer, swprintf(buffer, 20, L"%lx", n) );
++ stream.printout(buffer, swprintf(buffer, 20, L"%lx", n) );
+ }
+ }
+ }
+@@ -365,25 +365,25 @@
+ {
+ wchar_t buffer[28];
+ if( stream.flags() & ios_base::dec){
+- stream.write(buffer, swprintf(buffer, 27, L"%lld", n));
++ stream.printout(buffer, swprintf(buffer, 27, L"%lld", n));
+ }else if( stream.flags() & ios_base::oct){
+ if( stream.flags() & ios_base::showbase){
+- stream.write(buffer, swprintf(buffer, 27, L"%#llo", n));
++ stream.printout(buffer, swprintf(buffer, 27, L"%#llo", n));
+ }else{
+- stream.write(buffer, swprintf(buffer, 27, L"%llo", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%llo", n) );
+ }
+ }else if (stream.flags() & ios_base::hex){
+ if(stream.flags() & ios_base::showbase){
+ if(stream.flags() & ios_base::uppercase){
+- stream.write(buffer, swprintf(buffer, 27, L"%#llX", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%#llX", n) );
+ }else{
+- stream.write(buffer, swprintf(buffer, 27, L"%#llx", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%#llx", n) );
+ }
+ }else{
+ if(stream.flags() & ios_base::uppercase){
+- stream.write(buffer, swprintf(buffer, 27, L"%llX", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%llX", n) );
+ }else{
+- stream.write(buffer, swprintf(buffer, 27, L"%llx", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%llx", n) );
+ }
+ }
+ }
+@@ -399,25 +399,25 @@
+ {
+ wchar_t buffer[28];
+ if( stream.flags() & ios_base::dec){
+- stream.write(buffer, swprintf(buffer, 27, L"%llu", n));
++ stream.printout(buffer, swprintf(buffer, 27, L"%llu", n));
+ }else if( stream.flags() & ios_base::oct){
+ if( stream.flags() & ios_base::showbase){
+- stream.write(buffer, swprintf(buffer, 27, L"%#llo", n));
++ stream.printout(buffer, swprintf(buffer, 27, L"%#llo", n));
+ }else{
+- stream.write(buffer, swprintf(buffer, 27, L"%llo", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%llo", n) );
+ }
+ }else if (stream.flags() & ios_base::hex){
+ if(stream.flags() & ios_base::showbase){
+ if(stream.flags() & ios_base::uppercase){
+- stream.write(buffer, swprintf(buffer, 27, L"%#llX", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%#llX", n) );
+ }else{
+- stream.write(buffer, swprintf(buffer, 27, L"%#llx", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%#llx", n) );
+ }
+ }else{
+ if(stream.flags() & ios_base::uppercase){
+- stream.write(buffer, swprintf(buffer, 27, L"%llX", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%llX", n) );
+ }else{
+- stream.write(buffer, swprintf(buffer, 27, L"%llx", n) );
++ stream.printout(buffer, swprintf(buffer, 27, L"%llx", n) );
+ }
+ }
+ }
+@@ -447,7 +447,7 @@
+ } else {
+ swprintf(format_string, 32, L"%%%u.%ug", static_cast<int>(stream.width()), static_cast<unsigned int>(stream.precision()));
+ }
+- stream.write(buffer, swprintf(buffer, 32, format_string, f) );
++ stream.printout(buffer, swprintf(buffer, 32, format_string, f) );
+ if(stream.flags() & ios_base::unitbuf){
+ stream.flush();
+ }
+@@ -471,7 +471,7 @@
+ } else {
+ swprintf(format_string, 32, L"%%%u.%uLg", static_cast<unsigned int>(stream.width()), static_cast<unsigned int>(stream.precision()));
+ }
+- stream.write(buffer, swprintf(buffer, 32, format_string, f) );
++ stream.printout(buffer, swprintf(buffer, 32, format_string, f) );
+ if(stream.flags() & ios_base::unitbuf){
+ stream.flush();
+ }
diff --git a/main/uclibc++/900-dependent_exception.patch b/main/uclibc++/900-dependent_exception.patch
new file mode 100644
index 0000000000..3a5cb7dbca
--- /dev/null
+++ b/main/uclibc++/900-dependent_exception.patch
@@ -0,0 +1,68 @@
+--- a/src/eh_alloc.cpp 2007-06-03 23:51:13.000000000 +0100
++++ b/src/eh_alloc.cpp 2009-07-13 09:42:39.000000000 +0100
+@@ -42,4 +42,21 @@
+ free( (char *)(vptr) - sizeof(__cxa_exception) );
+ }
+
++#if __GNUC__ * 100 + __GNUC_MINOR__ >= 404
++extern "C" __cxa_dependent_exception* __cxa_allocate_dependent_exception() throw(){
++ __cxa_dependent_exception *retval;
++
++ retval = static_cast<__cxa_dependent_exception*>(malloc(sizeof(__cxa_dependent_exception)));
++ if(0 == retval){
++ std::terminate();
++ }
++ memset (retval, 0, sizeof(__cxa_dependent_exception));
++ return retval ;
++}
++
++extern "C" void __cxa_free_dependent_exception(__cxa_dependent_exception *vptr) throw(){
++ free( vptr );
++}
++#endif
++
+ }
+--- a/include/unwind-cxx.h 2009-07-13 10:01:11.000000000 +0100
++++ b/include/unwind-cxx.h 2009-07-13 10:14:08.000000000 +0100
+@@ -79,6 +79,41 @@
+ _Unwind_Exception unwindHeader;
+ };
+
++#if __GNUC__ * 100 + __GNUC_MINOR__ >= 404
++// A dependent C++ exception object consists of a wrapper around an unwind
++// object header with additional C++ specific information, containing a pointer
++// to a primary exception object.
++
++struct __cxa_dependent_exception
++{
++ // The primary exception this thing depends on.
++ void *primaryException;
++
++ // The C++ standard has entertaining rules wrt calling set_terminate
++ // and set_unexpected in the middle of the exception cleanup process.
++ std::unexpected_handler unexpectedHandler;
++ std::terminate_handler terminateHandler;
++
++ // The caught exception stack threads through here.
++ __cxa_exception *nextException;
++
++ // How many nested handlers have caught this exception. A negated
++ // value is a signal that this object has been rethrown.
++ int handlerCount;
++
++ // Cache parsed handler data from the personality routine Phase 1
++ // for Phase 2 and __cxa_call_unexpected.
++ int handlerSwitchValue;
++ const unsigned char *actionRecord;
++ const unsigned char *languageSpecificData;
++ _Unwind_Ptr catchTemp;
++ void *adjustedPtr;
++
++ // The generic exception header. Must be last.
++ _Unwind_Exception unwindHeader;
++};
++
++#endif
+ // Each thread in a C++ program has access to a __cxa_eh_globals object.
+ struct __cxa_eh_globals
+ {
diff --git a/main/uclibc++/APKBUILD b/main/uclibc++/APKBUILD
new file mode 100644
index 0000000000..20ff3a879e
--- /dev/null
+++ b/main/uclibc++/APKBUILD
@@ -0,0 +1,66 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=uclibc++
+pkgver=0.2.2
+pkgrel=7
+pkgdesc="Embedded C++ library"
+url="http://cxx.uclibc.org/"
+arch="all"
+license='GPL-2'
+depends=
+makedepends="bash"
+subpackages="$pkgname-dev"
+source="http://cxx.uclibc.org/src/uClibc++-$pkgver.tar.bz2
+ 001-path_to_make.patch
+ 002-no_bash.patch
+ 003-cp_command.patch
+ 004-ccache_fixes.patch
+ 005-wrapper.patch
+ 006-eabi_fix.patch
+ 007-numeric_limits.patch
+ 008-integer_width.patch
+ 900-dependent_exception.patch
+ associative_base.patch
+ uclibc++-gcc-4.3.patch
+ uclibc++config
+ "
+
+build() {
+ cd "$srcdir/uClibc++-$pkgver"
+ cp ../uclibc++config .config
+ make oldconfig
+
+ for i in ../*.patch; do
+ if ! patch -p1 < $i; then
+ error "failed to apply $i"
+ return 1
+ fi
+ done
+ sed -i -e 's:bin/bash:bin/sh:' bin/Makefile scripts/find_lib*
+ make || return 1
+ make DESTDIR="$pkgdir/" install
+}
+
+dev() {
+ depends="$pkgname g++"
+ mkdir -p "$subpkgdir"
+ # move everything to -dev package except *.so files
+ mv "$pkgdir"/* "$subpkgdir"/
+ mkdir -p "$pkgdir"/usr/lib/
+ mv "$subpkgdir"/usr/lib/*.so* \
+ "$pkgdir"/usr/lib/
+}
+
+
+md5sums="1ceef3209cca88be8f1bd9de99735954 uClibc++-0.2.2.tar.bz2
+ce1016fb83c23c83486f35f4cd1b64ab 001-path_to_make.patch
+2a9bee5e88bf94d3870517891d5129d6 002-no_bash.patch
+8068b394de053ed94a742d1ed9657b99 003-cp_command.patch
+363dc1cd86052f44212c2f3ac15926da 004-ccache_fixes.patch
+3689f8d77984ca66554e14cacbeb796c 005-wrapper.patch
+99e625748c0e6d5fc7cef8484cbac587 006-eabi_fix.patch
+d335b8f1c9d4682a220a082a371277e4 007-numeric_limits.patch
+2c431d4ad46a244f2f50baf40b85f7d2 008-integer_width.patch
+4e9c416c2a107f7d814f938fa57901a5 900-dependent_exception.patch
+5689baa3f3bf8488c0a5d27a690d30fa associative_base.patch
+4c7b499e4697225378acef25f6364e9b uclibc++-gcc-4.3.patch
+2f573c1e2a0c7a320ea4685cc3ce9e2a uclibc++config"
diff --git a/main/uclibc++/associative_base.patch b/main/uclibc++/associative_base.patch
new file mode 100644
index 0000000000..3453c996a4
--- /dev/null
+++ b/main/uclibc++/associative_base.patch
@@ -0,0 +1,13 @@
+--- a/include/associative_base.orig 2008-03-18 08:46:20 +0000
++++ b/include/associative_base 2008-03-18 08:46:56 +0000
+@@ -221,9 +221,9 @@
+ bool operator!=(const __base_associative & x){
+ return !(x.backing == backing);
+ }
++ void swap(__base_associative & x);
+
+ protected:
+- void swap(__base_associative & x);
+
+ Compare c;
+ std::list<value_type> backing;
diff --git a/main/uclibc++/uclibc++-gcc-4.3.patch b/main/uclibc++/uclibc++-gcc-4.3.patch
new file mode 100644
index 0000000000..37d45a5d5a
--- /dev/null
+++ b/main/uclibc++/uclibc++-gcc-4.3.patch
@@ -0,0 +1,73 @@
+diff -ru uClibc++-0.2.2.orig/include/associative_base uClibc++-0.2.2/include/associative_base
+--- uClibc++-0.2.2.orig/include/associative_base 2009-03-03 14:03:40.000000000 +0000
++++ uClibc++-0.2.2/include/associative_base 2009-03-03 14:03:52.000000000 +0000
+@@ -318,7 +318,7 @@
+ typedef std::list<ValueType> listtype;
+
+ typename listtype::iterator base_iter;
+- typedef _associative_citer<ValueType, Compare, Allocator> _associative_citer;
++ typedef _associative_citer<ValueType, Compare, Allocator> __associative_citer;
+
+
+ public:
+@@ -347,13 +347,13 @@
+ bool operator==(const _associative_iter & m) const{
+ return m.base_iter == base_iter;
+ }
+- bool operator==(const _associative_citer & m) const{
++ bool operator==(const __associative_citer & m) const{
+ return m.base_iter == base_iter;
+ }
+ bool operator!=(const _associative_iter & m) const{
+ return m.base_iter != base_iter;
+ }
+- bool operator!=(const _associative_citer & m) const{
++ bool operator!=(const __associative_citer & m) const{
+ return m.base_iter != base_iter;
+ }
+ _associative_iter & operator++(){
+@@ -378,8 +378,8 @@
+ --base_iter;
+ return temp;
+ }
+- operator _associative_citer() const{
+- return _associative_citer(base_iter);
++ operator __associative_citer() const{
++ return __associative_citer(base_iter);
+ }
+ typename listtype::iterator base_iterator(){
+ return base_iter;
+diff -ru uClibc++-0.2.2.orig/include/string uClibc++-0.2.2/include/string
+--- uClibc++-0.2.2.orig/include/string 2009-03-03 14:03:40.000000000 +0000
++++ uClibc++-0.2.2/include/string 2009-03-03 14:03:52.000000000 +0000
+@@ -1017,11 +1017,11 @@
+
+ template <> _UCXXEXPORT bool operator==(const string & lhs, const string & rhs);
+ template <> _UCXXEXPORT bool operator==(const char * lhs, const string & rhs);
+-template <> _UCXXEXPORT bool operator==(const string & rhs, const char * rhs);
++template <> _UCXXEXPORT bool operator==(const string & lhs, const char * rhs);
+
+ template <> _UCXXEXPORT bool operator!=(const string & lhs, const string & rhs);
+ template <> _UCXXEXPORT bool operator!=(const char * lhs, const string & rhs);
+-template <> _UCXXEXPORT bool operator!=(const string & rhs, const char * rhs);
++template <> _UCXXEXPORT bool operator!=(const string & lhs, const char * rhs);
+
+ template <> _UCXXEXPORT string operator+(const string & lhs, const char* rhs);
+ template <> _UCXXEXPORT string operator+(const char* lhs, const string & rhs);
+diff -ru uClibc++-0.2.2.orig/src/string.cpp uClibc++-0.2.2/src/string.cpp
+--- uClibc++-0.2.2.orig/src/string.cpp 2009-03-03 14:03:41.000000000 +0000
++++ uClibc++-0.2.2/src/string.cpp 2009-03-03 14:03:52.000000000 +0000
+@@ -76,11 +76,11 @@
+
+ template _UCXXEXPORT bool operator==(const string & lhs, const string & rhs);
+ template _UCXXEXPORT bool operator==(const char * lhs, const string & rhs);
+- template _UCXXEXPORT bool operator==(const string & rhs, const char * rhs);
++ template _UCXXEXPORT bool operator==(const string & lhs, const char * rhs);
+
+ template _UCXXEXPORT bool operator!=(const string & lhs, const string & rhs);
+ template _UCXXEXPORT bool operator!=(const char * lhs, const string & rhs);
+- template _UCXXEXPORT bool operator!=(const string & rhs, const char * rhs);
++ template _UCXXEXPORT bool operator!=(const string & lhs, const char * rhs);
+
+ template _UCXXEXPORT string operator+(const string & lhs, const char* rhs);
+ template _UCXXEXPORT string operator+(const char* lhs, const string & rhs);
diff --git a/main/uclibc++/uclibc++config b/main/uclibc++/uclibc++config
new file mode 100644
index 0000000000..181bd4e7cf
--- /dev/null
+++ b/main/uclibc++/uclibc++config
@@ -0,0 +1,54 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Target Features and Options
+#
+UCLIBCXX_HAS_FLOATS=y
+UCLIBCXX_HAS_LONG_DOUBLE=y
+# UCLIBCXX_HAS_TLS is not set
+WARNINGS="-Wall"
+BUILD_EXTRA_LIBRARIES=""
+HAVE_DOT_CONFIG=y
+
+#
+# String and I/O Stream Support
+#
+# UCLIBCXX_HAS_WCHAR is not set
+UCLIBCXX_IOSTREAM_BUFSIZE=32
+UCLIBCXX_HAS_LFS=y
+UCLIBCXX_SUPPORT_CDIR=y
+UCLIBCXX_SUPPORT_CIN=y
+UCLIBCXX_SUPPORT_COUT=y
+UCLIBCXX_SUPPORT_CERR=y
+# UCLIBCXX_SUPPORT_CLOG is not set
+
+#
+# STL and Code Expansion
+#
+UCLIBCXX_STL_BUFFER_SIZE=32
+UCLIBCXX_CODE_EXPANSION=y
+UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS=y
+UCLIBCXX_EXPAND_STRING_CHAR=y
+UCLIBCXX_EXPAND_VECTOR_BASIC=y
+UCLIBCXX_EXPAND_IOS_CHAR=y
+UCLIBCXX_EXPAND_STREAMBUF_CHAR=y
+UCLIBCXX_EXPAND_ISTREAM_CHAR=y
+UCLIBCXX_EXPAND_OSTREAM_CHAR=y
+UCLIBCXX_EXPAND_FSTREAM_CHAR=y
+UCLIBCXX_EXPAND_SSTREAM_CHAR=y
+
+#
+# Library Installation Options
+#
+UCLIBCXX_RUNTIME_PREFIX="/usr"
+UCLIBCXX_RUNTIME_INCLUDE_SUBDIR="/include"
+UCLIBCXX_RUNTIME_LIB_SUBDIR="/lib"
+UCLIBCXX_RUNTIME_BIN_SUBDIR="/bin"
+UCLIBCXX_EXCEPTION_SUPPORT=y
+IMPORT_LIBSUP=y
+IMPORT_LIBGCC_EH=y
+BUILD_STATIC_LIB=y
+# BUILD_ONLY_STATIC_LIB is not set
+# DODEBUG is not set
diff --git a/main/udev/APKBUILD b/main/udev/APKBUILD
new file mode 100644
index 0000000000..e1e3d12688
--- /dev/null
+++ b/main/udev/APKBUILD
@@ -0,0 +1,75 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=udev
+pkgver=171
+pkgrel=1
+pkgdesc="The userspace dev tools (udev)"
+url="http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc libudev libgudev"
+depends=
+makedepends="gobject-introspection-dev glib-dev gperf acl-dev libusb-compat-dev
+ usbutils pciutils-dev libtool"
+install=
+source="http://www.kernel.org/pub/linux/utils/kernel/hotplug/$pkgname-$pkgver.tar.bz2
+ write_root_link_rule
+ move_tmp_persistent_rules.sh
+ udev-mount.initd
+ udev-postmount.initd
+ udev.initd"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --sbindir=/sbin \
+ --libdir=/usr/lib \
+ --with-rootlibdir=/lib \
+ --libexecdir=/lib/udev \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+
+ mkdir -p "$pkgdir"/usr/lib/pkgconfig
+ chmod +x "$pkgdir"/lib/udev/write_*_rules
+ for _i in write_root_link_rule move_tmp_persistent_rules.sh; do
+ install -Dm755 ../$_i "$pkgdir"/lib/udev/$_i
+ done
+ for _i in udev udev-mount udev-postmount; do
+ install -Dm755 ../$_i.initd "$pkgdir"/etc/init.d/$_i
+ done
+ # provided by bluez
+ rm -f "$pkgdir"/lib/udev/hid2hci
+
+ # remove libtool archives
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+libudev() {
+ pkgdesc="Dynamic library to access udev device information"
+ replaces="udev"
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libudev.so.* "$subpkgdir"/lib/
+}
+
+libgudev() {
+ pkgdesc="A GObject wrapper of the library gudev"
+ replaces="udev"
+ mkdir -p "$subpkgdir"/lib/ \
+ "$subpkgdir"/usr/lib || return 1
+ mv "$pkgdir"/lib/libgudev* "$subpkgdir"/lib/ || return 1
+ mv "$pkgdir"/usr/lib/girepository-* \
+ "$subpkgdir"/usr/lib/
+}
+
+md5sums="bdf4617284be2ecac11767437417e209 udev-171.tar.bz2
+c9de7581099cdfdcd105666cd98a0f0a write_root_link_rule
+7bf11e11519117f743483c73e0767750 move_tmp_persistent_rules.sh
+884d7faaaa149a323b14e907ea1934f4 udev-mount.initd
+8f0a1b371804c7fa30f1a7bfde88e9ea udev-postmount.initd
+42b7e4ad49874e68851fc21153f41c4f udev.initd"
diff --git a/main/udev/move_tmp_persistent_rules.sh b/main/udev/move_tmp_persistent_rules.sh
new file mode 100755
index 0000000000..1a0259798b
--- /dev/null
+++ b/main/udev/move_tmp_persistent_rules.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+. /etc/init.d/functions.sh
+
+# store persistent-rules that got created while booting
+# when / was still read-only
+store_persistent_rules() {
+ local file dest
+
+ for file in /dev/.udev/tmp-rules--*; do
+ dest=${file##*tmp-rules--}
+ [ "$dest" = '*' ] && break
+ type=${dest##70-persistent-}
+ type=${type%%.rules}
+ ebegin "Saving udev persistent ${type} rules to /etc/udev/rules.d"
+ cat "$file" >> /etc/udev/rules.d/"$dest" && rm -f "$file"
+ eend $? "Failed moving persistent rules!"
+ done
+}
+
+store_persistent_rules
+
+# vim:ts=4
diff --git a/main/udev/udev-mount.initd b/main/udev/udev-mount.initd
new file mode 100644
index 0000000000..f0d8cc39f2
--- /dev/null
+++ b/main/udev/udev-mount.initd
@@ -0,0 +1,61 @@
+#!/sbin/runscript
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+description="Mount tmpfs on /dev"
+[ -e /etc/conf.d/udev ] && . /etc/conf.d/udev
+
+mount_dev_directory()
+{
+ if mountinfo -q /dev; then
+ einfo "/dev is already mounted"
+ return 0
+ fi
+
+ # No options are processed here as they should all be in /etc/fstab
+ ebegin "Mounting /dev"
+ if ! fstabinfo --mount /dev; then
+ # we mount devtmpfs if supported
+ local fs=tmpfs
+ grep -qs devtmpfs /proc/filesystems && fs=devtmpfs
+
+ # Some devices require exec, Bug #92921
+ mount -n -t "$fs" -o "exec,nosuid,mode=0755,size=10M" udev /dev
+ fi
+ eend $?
+}
+
+seed_dev()
+{
+ # Seed /dev with some things that we know we need
+
+ # creating /dev/console, /dev/tty and /dev/tty1 to be able to write
+ # to $CONSOLE with/without bootsplash before udevd creates it
+ [ -c /dev/console ] || mknod -m 600 /dev/console c 5 1
+ [ -c /dev/tty1 ] || mknod -m 620 /dev/tty1 c 4 1
+ [ -c /dev/tty ] || mknod -m 666 /dev/tty c 5 0
+
+ # udevd will dup its stdin/stdout/stderr to /dev/null
+ # and we do not want a file which gets buffered in ram
+ [ -c /dev/null ] || mknod -m 666 /dev/null c 1 3
+
+ # so udev can add its start-message to dmesg
+ [ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11
+
+ # Create problematic directories
+ mkdir -p /dev/pts /dev/shm
+ return 0
+}
+
+
+start()
+{
+ mount_dev_directory || return 1
+
+ # make sure it exists
+ mkdir -p /dev/.udev /dev/.udev/rules.d
+
+ seed_dev
+
+ return 0
+}
diff --git a/main/udev/udev-postmount.initd b/main/udev/udev-postmount.initd
new file mode 100644
index 0000000000..33a412ff87
--- /dev/null
+++ b/main/udev/udev-postmount.initd
@@ -0,0 +1,37 @@
+#!/sbin/runscript
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-fs/udev/files/161/udev-postmount.initd,v 1.1 2010/08/24 18:41:29 zzam Exp $
+
+depend() {
+ need localmount
+ after dbus # for trigger failed
+}
+
+dir_writeable()
+{
+ printf "" 2>/dev/null >"$1"/.test.$$ && rm "$1"/.test.$$
+}
+
+start() {
+ # check if this system uses udev
+ [ -d /dev/.udev/ ] || return 0
+
+ einfo "Doing udev cleanups"
+
+ # Run the events that failed at first udev trigger
+ udevadm trigger --type=failed -v
+
+ # only continue if rules-directory is writable
+ dir_writeable /etc/udev/rules.d || return 0
+
+ # store persistent-rules that got created while booting
+ # when / was still read-only
+ /lib/udev/move_tmp_persistent_rules.sh
+}
+
+stop() {
+ :
+}
+
+# vim:ts=4
diff --git a/main/udev/udev.confd b/main/udev/udev.confd
new file mode 100644
index 0000000000..7c3d3eb229
--- /dev/null
+++ b/main/udev/udev.confd
@@ -0,0 +1,64 @@
+# /etc/conf.d/udev: config file for udev
+
+# We discourage to disable persistent-net!!
+# this may lead to random interface naming
+
+# Disable adding new rules for persistent-net
+persistent_net_disable="no"
+
+# Disable adding new rules for persistent-cd
+# Disabling this will stop new cdrom devices to appear
+# as /dev/{cdrom,cdrw,dvd,dvdrw}
+persistent_cd_disable="no"
+
+# Set to "yes" if you want to save /dev to a tarball on shutdown
+# and restore it on startup. This is useful if you have a lot of
+# custom device nodes that udev does not handle/know about.
+#
+# As this option is fragile, we recommend you
+# to create your devices in /lib/udev/devices.
+# These will be copied to /dev on boot.
+#rc_device_tarball="NO"
+
+# udev can trigger coldplug events which cause services to start and
+# kernel modules to be loaded.
+# Services are deferred to start in the boot runlevel.
+# Set rc_coldplug="NO" if you don't want this.
+# If you want module coldplugging but not coldplugging of services then you
+# can disable service coldplugging in baselayout/openrc config files.
+# The setting is named different in different versions.
+# in /etc/rc.conf: rc_hotplug="!*" or
+# in /etc/conf.d/rc: rc_plug_services="!*"
+#rc_coldplug="YES"
+
+
+
+
+# Expert options:
+
+# Disable warning about unreliable kernel/udev combination
+#unreliable_kernel_warning="no"
+
+# Timeout in seconds to wait for processing of uevents at boot.
+# There should be no need to change this.
+#udev_settle_timeout="60"
+
+# Add extra command line options to udevd, use with care
+# udevd --help for possible values
+#udev_opts=""
+
+# Run udevd --debug and write output to /dev/.udev/udev.log
+# Should not be kept on as it fills diskspace slowly
+#udev_debug="YES"
+
+# Run udevadmin monitor to get a log of all events
+# in /dev/.udev/udevmonitor.log
+#udev_monitor="YES"
+
+# Keep udevmonitor running after populating /dev.
+#udev_monitor_keep_running="no"
+
+# Set cmdline options for udevmonitor.
+# could be some of --env --kernel --udev
+#udev_monitor_opts="--env"
+
diff --git a/main/udev/udev.initd b/main/udev/udev.initd
new file mode 100644
index 0000000000..e48ea9b675
--- /dev/null
+++ b/main/udev/udev.initd
@@ -0,0 +1,238 @@
+#!/sbin/runscript
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+description="Run udevd and create the device-nodes"
+
+[ -e /etc/udev/udev.conf ] && . /etc/udev/udev.conf
+
+rc_coldplug=${rc_coldplug:-${RC_COLDPLUG:-YES}}
+
+depend()
+{
+ provide dev
+ if yesno "${rc_device_tarball:-no}"; then
+ need sysfs udev-mount udev-dev-tarball
+ else
+ need sysfs udev-mount
+ fi
+ before checkfs fsck
+
+ # udev does not work inside vservers
+ keyword novserver nolxc noopenvz
+}
+
+cleanup()
+{
+ # fail more gracely and not leave udevd running
+ start-stop-daemon --stop --exec /sbin/udevd
+ exit 1
+}
+
+disable_hotplug_agent()
+{
+ if [ -e /proc/sys/kernel/hotplug ]; then
+ echo "" >/proc/sys/kernel/hotplug
+ fi
+}
+
+root_link()
+{
+ /lib/udev/write_root_link_rule
+}
+
+rules_disable_switch()
+{
+ # this function disables rules files
+ # by creating new files with the same name
+ # in a temp rules directory with higher priority
+ local f=/dev/.udev/rules.d/"$1" bname="$1" onoff="$2"
+
+ if yesno "${onoff}"; then
+ echo "# This file disables ${bname} due to /etc/conf.d/udev" \
+ > "${f}"
+ else
+ rm -f "${f}"
+ fi
+}
+
+start_udevd()
+{
+ # load unix domain sockets if built as module, Bug #221253
+ if [ -e /proc/modules ] ; then
+ modprobe -q unix 2>/dev/null
+ fi
+ local opts="${udev_opts}"
+
+ ebegin "Starting udevd"
+ if yesno "${udev_debug:-no}"; then
+ /sbin/udevd --daemon ${opts} --debug 2>/dev/.udev/udev.log
+ else
+ start-stop-daemon --start --exec /sbin/udevd -- --daemon ${opts}
+ fi
+
+ eend $?
+}
+
+# populate /dev with devices already found by the kernel
+populate_dev()
+{
+ if get_bootparam "nocoldplug" ; then
+ rc_coldplug="NO"
+ ewarn "Skipping udev coldplug as requested in kernel cmdline"
+ fi
+
+ ebegin "Populating /dev with existing devices through uevents"
+ udevadm control --property=STARTUP=1
+ if yesno "${rc_coldplug}"; then
+ udevadm trigger --action="add"
+ else
+ # Do not run any init-scripts, Bug #206518
+ udevadm control --property=do_not_run_plug_service=1
+
+ # only create device nodes
+ udevadm trigger --action="add" --attr-match=dev
+
+ # run persistent-net stuff, bug 191466
+ udevadm trigger --action="add" --subsystem-match=net
+ fi
+ eend $?
+
+ # we can speed up booting under these conditions:
+ # * using devtmpfs so kernel creates device nodes for us
+ # * only using kernel created device nodes at boot (in /etc/fstab and elsewhere)
+ #
+ ebegin "Waiting for uevents to be processed"
+ udevadm settle --timeout=${udev_settle_timeout:-60}
+ eend $?
+
+ udevadm control --property=do_not_run_plug_service=
+ udevadm control --property=STARTUP=
+ return 0
+}
+
+# for debugging
+start_udevmonitor()
+{
+ yesno "${udev_monitor:-no}" || return 0
+
+ udevmonitor_log=/dev/.udev/udevmonitor.log
+ udevmonitor_pid=/dev/.udev/udevmonitor.pid
+
+ einfo "udev: Running udevadm monitor ${udev_monitor_opts} to get a log of all events"
+ start-stop-daemon --start --stdout "${udevmonitor_log}" \
+ --make-pidfile --pidfile "${udevmonitor_pid}" \
+ --background --exec /sbin/udevadm -- monitor ${udev_monitor_opts}
+}
+
+stop_udevmonitor()
+{
+ yesno "${udev_monitor:-no}" || return 0
+
+ if yesno "${udev_monitor_keep_running:-no}"; then
+ ewarn "udev: udevmonitor is still running and writing into ${udevmonitor_log}"
+ else
+ einfo "udev: Stopping udevmonitor: Log is in ${udevmonitor_log}"
+ start-stop-daemon --stop --pidfile "${udevmonitor_pid}" --exec /sbin/udevadm
+ fi
+}
+
+display_hotplugged_services() {
+ local svcfile= svc= services=
+ for svcfile in "${RC_SVCDIR}"/hotplugged/*; do
+ svc="${svcfile##*/}"
+ [ -x "${svcfile}" ] || continue
+
+ services="${services} ${svc}"
+ done
+ [ -n "${services}" ] && einfo "Device initiated services:${HILITE}${services}${NORMAL}"
+}
+
+check_persistent_net()
+{
+ # check if there are problems with persistent-net
+ local syspath= devs= problem=false
+ for syspath in /sys/class/net/*_rename*; do
+ if [ -d "${syspath}" ]; then
+ devs="${devs} ${syspath##*/}"
+ problem=true
+ fi
+ done
+
+ ${problem} || return 0
+
+ eerror "UDEV: Your system has a problem assigning persistent names"
+ eerror "to these network interfaces: ${devs}"
+
+ einfo "Checking persistent-net rules:"
+ # the sed-expression lists all duplicate lines
+ # from the input, like "uniq -d" does, but uniq
+ # is installed into /usr/bin and not available at boot.
+ dups=$(
+ RULES_FILE='/etc/udev/rules.d/70-persistent-net.rules'
+ . /lib/udev/rule_generator.functions
+ find_all_rules 'NAME=' '.*' | \
+ tr ' ' '\n' | \
+ sort | \
+ sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'
+ )
+ if [ -n "${dups}" ]; then
+ ewarn "The rules create multiple entries assigning these names:"
+ eindent
+ ewarn "${dups}"
+ eoutdent
+ else
+ ewarn "Found no duplicate names in persistent-net rules,"
+ ewarn "there must be some other problem!"
+ fi
+ return 1
+}
+
+check_udev_works()
+{
+ # should exist on every system, else udev failed
+ if [ ! -e /dev/zero ]; then
+ eerror "Assuming udev failed somewhere, as /dev/zero does not exist."
+ return 1
+ fi
+ return 0
+}
+
+start()
+{
+ _start
+
+ display_hotplugged_services
+
+ return 0
+}
+
+_start()
+{
+ if [ ! -e /etc/runlevels/${RC_DEFAULTLEVEL:-default}/udev-postmount ]; then
+ ewarn "You should add udev-postmount service to your default runlevel."
+ fi
+
+ root_link
+ rules_disable_switch 75-persistent-net-generator.rules "${persistent_net_disable:-no}"
+ rules_disable_switch 75-cd-aliases-generator.rules ${persistent_cd_disable:-no}
+
+ disable_hotplug_agent
+ start_udevd || cleanup
+ start_udevmonitor
+ populate_dev || cleanup
+
+ check_persistent_net
+
+ check_udev_works || cleanup
+ stop_udevmonitor
+
+ return 0
+}
+
+stop() {
+ ebegin "Stopping udevd"
+ start-stop-daemon --stop --exec /sbin/udevd
+ eend $?
+}
+
diff --git a/main/udev/write_root_link_rule b/main/udev/write_root_link_rule
new file mode 100755
index 0000000000..8eaea11769
--- /dev/null
+++ b/main/udev/write_root_link_rule
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# This script should run before doing udevtrigger at boot.
+# It will create a rule matching the device directory / is on, and
+# creating /dev/root symlink pointing on its device node.
+#
+# This is especially useful for hal looking at /proc/mounts containing
+# a line listing /dev/root as device:
+# /dev/root / reiserfs rw 0 0
+#
+# 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 version 2 of the License.
+#
+# (c) 2007-2008 Matthias Schwarzott <zzam@gentoo.org>
+
+eval $(udevadm info --export --export-prefix="ROOT_" --device-id-of-file=/)
+
+[ $? = 0 ] || exit 0
+[ "$ROOT_MAJOR" = 0 ] && exit 0
+
+DIR=/dev/.udev/rules.d
+[ -d "$DIR" ] || mkdir -p "$DIR"
+RULES=$DIR/10-root-link.rules
+
+echo "# Created by /lib/udev/write_root_link_rule" > "${RULES}"
+echo "# This rule should create /dev/root as link to real root device." >> "${RULES}"
+echo "SUBSYSTEM==\"block\", ENV{MAJOR}==\"$ROOT_MAJOR\", ENV{MINOR}==\"$ROOT_MINOR\", SYMLINK+=\"root\"" >> "${RULES}"
+
diff --git a/main/udisks/APKBUILD b/main/udisks/APKBUILD
new file mode 100644
index 0000000000..c038595daf
--- /dev/null
+++ b/main/udisks/APKBUILD
@@ -0,0 +1,48 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=udisks
+pkgver=1.0.2
+pkgrel=2
+pkgdesc="Disk Management Service"
+url="http://www.freedesktop.org/wiki/Software/udisks"
+arch="all"
+license="GPL"
+depends=""
+makedepends="glib-dev polkit-dev parted-dev udev-dev sg3_utils-dev
+ dbus-dev dbus-glib-dev lvm2-dev pkgconfig libatasmart-dev
+ intltool eggdbus-dev expat-dev docbook-xsl libxslt"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://hal.freedesktop.org/releases/$pkgname-$pkgver.tar.gz
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --libexecdir=/usr/lib/udisks \
+ --localstatedir=/var \
+ --disable-static \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="f630eefa51b95d6485eb3246bc1bea9a udisks-1.0.2.tar.gz"
diff --git a/main/ulogd/APKBUILD b/main/ulogd/APKBUILD
new file mode 100644
index 0000000000..697b720384
--- /dev/null
+++ b/main/ulogd/APKBUILD
@@ -0,0 +1,59 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=ulogd
+pkgver=1.24
+pkgrel=4
+pkgdesc="A userspace logging daemon for netfilter/iptables related logging"
+url="http://netfilter.org/projects/ulogd/index.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="sqlite-dev postgresql-dev libpcap-dev libnfnetlink-dev
+libnetfilter_conntrack-dev pkgconfig openssl-dev"
+subpackages="$pkgname-sqlite $pkgname-pgsql $pkgname-doc"
+source="http://www.netfilter.org/projects/$pkgname/files/$pkgname-$pkgver.tar.bz2
+ ulogd.initd
+ ulogd.confd
+ ulogd.logrotate"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-pgsql \
+ --with-sqlite3 \
+ --with-pgsql-log-ip-as-string
+ make -j1|| return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ install -Dm644 ulogd.conf "$pkgdir"/etc/ulogd.conf
+ install -Dm644 ulogd.logrotate "$pkgdir"/etc/logrotate.d/ulogd
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ mkdir -p $pkgdir/usr/share/doc/$pkgname
+ cp doc/*table* doc/*.txt doc/*.html $pkgdir/usr/share/doc/$pkgname
+}
+
+sqlite() {
+ depends="$pkgname"
+ mkdir -p "$subpkgdir"/usr/lib/ulogd/
+ mv "$pkgdir"/usr/lib/ulogd/ulogd_SQLITE3.so "$subpkgdir"/usr/lib/ulogd/
+}
+
+pgsql() {
+ depends="$pkgname"
+ mkdir -p "$subpkgdir"/usr/lib/ulogd/
+ mv "$pkgdir"/usr/lib/ulogd/ulogd_PGSQL.so "$subpkgdir"/usr/lib/ulogd/
+}
+
+md5sums="05b4ed2926b9a22aaeaf642917bbf8ff ulogd-1.24.tar.bz2
+a9a4262961a9cf4b8dd34a91701dbb0a ulogd.initd
+b9b2fa217ee02211debee5a5dffdcda7 ulogd.confd
+836332074f6cbc19d2d0553e2076dab7 ulogd.logrotate"
diff --git a/main/ulogd/ulogd.confd b/main/ulogd/ulogd.confd
new file mode 100644
index 0000000000..ac035b24c9
--- /dev/null
+++ b/main/ulogd/ulogd.confd
@@ -0,0 +1,2 @@
+# Argument to be passed to ulog daemon
+ARGS="-d"
diff --git a/main/ulogd/ulogd.initd b/main/ulogd/ulogd.initd
new file mode 100644
index 0000000000..1b7e5edfca
--- /dev/null
+++ b/main/ulogd/ulogd.initd
@@ -0,0 +1,39 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/app-admin/ulogd/files/ulogd,v 1.2 2004/07/13 16:32:25 aliz Exp $
+
+opts="reload"
+
+depend() {
+ need net
+ before firewall
+}
+
+checkconfig() {
+ if [ ! -e /etc/ulogd.conf ]; then
+ eerror "You need /etc/ulogd.conf"
+ return 1
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ ebegin "Starting ulogd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ulogd -- \
+ $ARGS >/dev/null 2>&1
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ulogd"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/ulogd >/dev/null 2>&1
+ eend $?
+}
+
+reload() {
+ ebegin "Reloading ulogd.conf file"
+ killall -HUP ulogd &>/dev/null
+ eend $?
+}
+
diff --git a/main/ulogd/ulogd.logrotate b/main/ulogd/ulogd.logrotate
new file mode 100644
index 0000000000..6974d41b15
--- /dev/null
+++ b/main/ulogd/ulogd.logrotate
@@ -0,0 +1,12 @@
+/var/log/ulogd.log /var/log/ulog.syslogemu {
+ rotate 4
+ daily
+ missingok
+ notifempty
+ compress
+ delaycompress
+ sharedscripts
+ postrotate
+ /etc/init.d/ulogd reload &>/dev/null
+ endscript
+}
diff --git a/main/umix/APKBUILD b/main/umix/APKBUILD
new file mode 100644
index 0000000000..97062edfbb
--- /dev/null
+++ b/main/umix/APKBUILD
@@ -0,0 +1,31 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer: Michael Mason <ms13sp@gmail.com>
+pkgname=umix
+pkgver=1.0.2
+pkgrel=2
+pkgdesc="Program for adjusting soundcard volumes"
+url="http://umix.sf.net"
+arch="all"
+license="GPL"
+depends=
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="e38fc288273cc8b5b34f8769f06b32ee umix-1.0.2.tar.gz"
diff --git a/main/unarj/APKBUILD b/main/unarj/APKBUILD
new file mode 100644
index 0000000000..f43a41fea1
--- /dev/null
+++ b/main/unarj/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=unarj
+pkgver=2.63a
+pkgrel=2
+pkgdesc="Extracting, testing and viewing the contents of archives created with the ARJ archiver"
+url="http://www.arjsoftware.com"
+arch="all"
+license="custom"
+subpackages=""
+depends=""
+makedepends=""
+install=
+source="http://ibiblio.org/pub/Linux/utils/compress/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/${pkgname}-${pkgver}
+ make || return 1
+ install -D -m755 unarj $pkgdir/usr/bin/unarj || return 1
+ #install -D -m644 ../LICENSE ${pkgdir}/usr/share/licenses/${pkgname}/LICENSE
+}
+
+md5sums="a83d139c245f911f22cb1b611ec9768f unarj-2.63a.tar.gz"
diff --git a/main/unfs3/APKBUILD b/main/unfs3/APKBUILD
new file mode 100644
index 0000000000..d39d77347d
--- /dev/null
+++ b/main/unfs3/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=unfs3
+pkgver=0.9.22
+pkgrel=2
+pkgdesc="a user-space implementation of the NFSv3 server specification"
+url="http://unfs3.sourceforge.net/"
+arch="all"
+license='GPL'
+depends=""
+makedepends="flex"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
+subpackages="$pkgname-doc"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man
+ make -j1 || return 1
+ make DESTDIR="$pkgdir/" install
+}
+
+md5sums="ddf679a5d4d80096a59f3affc64f16e5 unfs3-0.9.22.tar.gz"
diff --git a/main/unixodbc/APKBUILD b/main/unixodbc/APKBUILD
new file mode 100644
index 0000000000..ee22bb6938
--- /dev/null
+++ b/main/unixodbc/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=unixodbc
+pkgver=2.3.0
+pkgrel=3
+pkgdesc="ODBC is an open specification to access Data Sources"
+url="http://www.unixodbc.org/"
+arch="all"
+license="GPL2"
+depends=
+makedepends="readline-dev"
+subpackages="$pkgname-dev"
+source="http://www.unixodbc.org/unixODBC-${pkgver}.tar.gz"
+
+_builddir="$srcdir/unixODBC-$pkgver"
+
+build() {
+ cd "$_builddir"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls \
+ --enable-gui=no
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+}
+
+md5sums="f2ad22cbdffe836c58987ed2332c2e99 unixODBC-2.3.0.tar.gz"
diff --git a/main/unrar/APKBUILD b/main/unrar/APKBUILD
new file mode 100644
index 0000000000..3a2e07904d
--- /dev/null
+++ b/main/unrar/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=unrar
+pkgver=4.0.7
+pkgrel=0
+pkgdesc="The RAR uncompression program"
+url="http://www.rarlab.com"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+subpackages="$pkgname-doc"
+source="http://www.rarlab.com/rar/unrarsrc-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname"
+ make -f makefile.unix || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname"
+ install -Dm755 unrar "$pkgdir"/usr/bin/unrar
+ install -Dm644 license.txt "$pkgdir/usr/share/licenses/$pkgname/license.txt"
+
+}
+
+md5sums="41b0a9bca945b4ae2608421afd8f606e unrarsrc-4.0.7.tar.gz"
diff --git a/main/upower/APKBUILD b/main/upower/APKBUILD
new file mode 100644
index 0000000000..0320c3948c
--- /dev/null
+++ b/main/upower/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=upower
+pkgver=0.9.11
+pkgrel=1
+pkgdesc="Power Management Services"
+url="http://upower.freedesktop.org"
+arch="all"
+license="GPL"
+depends=""
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="gtk+-dev udev-dev libusb-dev polkit-dev dbus-glib-dev libxslt
+ docbook-xsl"
+source="http://upower.freedesktop.org/releases/upower-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --libexecdir=/usr/lib/upower \
+ --disable-static
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="7782a4c5a53021cdfb0703b7ba96edf5 upower-0.9.11.tar.bz2"
diff --git a/main/usbutils/APKBUILD b/main/usbutils/APKBUILD
new file mode 100644
index 0000000000..ff72e441ea
--- /dev/null
+++ b/main/usbutils/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=usbutils
+pkgver=002
+pkgrel=0
+pkgdesc="USB Device Utilities"
+url="http://linux-usb.sourceforge.net/"
+arch="all"
+license="GPL"
+subpackags="$pkgname-doc"
+depends=
+makedepends="pkgconfig libusb-compat-dev"
+source="http://www.kernel.org/pub/linux/utils/usb/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ rm usb.ids
+ wget http://www.linux-usb.org/usb.ids
+ ./configure --prefix=/usr \
+ --datadir=/usr/share/hwdata \
+ --disable-zlib
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ mkdir -p "$pkgdir"/usr/lib/
+ mv "$pkgdir"/usr/share/pkgconfig \
+ "$pkgdir"/usr/lib/
+}
+
+md5sums="05610d15c3c8c8ada3d691c320ca784a usbutils-002.tar.gz"
diff --git a/main/util-linux-ng/APKBUILD b/main/util-linux-ng/APKBUILD
new file mode 100644
index 0000000000..7dcbc606c4
--- /dev/null
+++ b/main/util-linux-ng/APKBUILD
@@ -0,0 +1,105 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=util-linux-ng
+pkgver=2.19.1
+pkgrel=2
+pkgdesc="Random collection of Linux utilities"
+url="http://kernel.org/~kzak/util-linux/"
+arch="all"
+license="GPL-2 GPL Public Domain"
+depends=
+# use GNU sed til bb sed is fixed
+makedepends="zlib-dev sed ncurses-dev"
+install=
+source="http://www.kernel.org/pub/linux/utils/util-linux-ng/v${pkgver%.*}/util-linux-$pkgver.tar.gz
+ program-invocation.patch"
+subpackages="$pkgname-doc $pkgname-dev libuuid libblkid sfdisk cfdisk mcookie blkid"
+replaces="e2fsprogs"
+
+_builddir="$srcdir/util-linux-$pkgver"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ sed -e 's/versionsort/alphasort/g'\
+ -e 's/strverscmp.h/dirent.h/g' \
+ -i mount/lomount.c
+
+ ./configure --prefix=/usr \
+ --disable-uuidd \
+ --disable-nls \
+ --disable-tls \
+ --disable-kill \
+ --disable-init \
+ --with-ncurses \
+ --without-pam
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 install DESTDIR="$pkgdir"
+ # use pkg-config
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+dev() {
+ default_dev
+ replaces="e2fsprogs-dev"
+}
+
+blkid() {
+ pkgdesc="block device identificatio tool"
+ replaces="util-linux-ng"
+ depends=
+ mkdir -p "$subpkgdir"/sbin
+ mv "$pkgdir"/sbin/blkid "$subpkgdir"/sbin/
+}
+
+libuuid() {
+ pkgdesc="DCE compatible Universally Unique Identifier library"
+ depends=
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libuuid* "$subpkgdir"/lib/
+}
+
+libblkid() {
+ pkgdesc="Block device identification library from util-linux-ng"
+ depends=
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libblkid* "$subpkgdir"/lib/
+}
+
+sfdisk() {
+ pkgdesc="Partition table manipulator from util-linux-ng"
+ depends=
+ mkdir -p "$subpkgdir"/sbin
+ mv "$pkgdir"/sbin/sfdisk "$subpkgdir"/sbin/
+}
+
+
+cfdisk() {
+ pkgdesc="Curses based partition table manipulator from util-linux-ng"
+ depends=
+ mkdir -p "$subpkgdir"/sbin
+ mv "$pkgdir"/sbin/cfdisk "$subpkgdir"/sbin/
+}
+
+mcookie() {
+ pkgdesc="mcookie from util-linux-ng"
+ replaces="util-linux-ng"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/mcookie "$subpkgdir"/usr/bin/
+}
+
+md5sums="dd242eeb2ba76e4e55bf2237a50dd2b7 util-linux-2.19.1.tar.gz
+079dc713684e01ad48c7e0bb877dc51a program-invocation.patch"
diff --git a/main/util-linux-ng/program-invocation.patch b/main/util-linux-ng/program-invocation.patch
new file mode 100644
index 0000000000..c81f97e36a
--- /dev/null
+++ b/main/util-linux-ng/program-invocation.patch
@@ -0,0 +1,11 @@
+--- util-linux-2.19.1.orig/include/c.h
++++ util-linux-2.19.1/include/c.h
+@@ -115,7 +115,7 @@
+
+ #ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+ # ifdef HAVE___PROGNAME
+-extern char *__progname;
++extern const char *__progname;
+ # define program_invocation_short_name __progname
+ # else
+ # include <string.h>
diff --git a/main/util-macros/APKBUILD b/main/util-macros/APKBUILD
new file mode 100644
index 0000000000..dbd70f033f
--- /dev/null
+++ b/main/util-macros/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=util-macros
+pkgver=1.11.0
+pkgrel=0
+pkgdesc="X.Org Autotools macros"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/util/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="22d5cdff672450cb6902e0d68c200dcb util-macros-1.11.0.tar.bz2"
diff --git a/main/util-vserver/APKBUILD b/main/util-vserver/APKBUILD
new file mode 100644
index 0000000000..9fd6e1b397
--- /dev/null
+++ b/main/util-vserver/APKBUILD
@@ -0,0 +1,79 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=util-vserver
+pkgver=0.30.216_pre2981
+_realver=${pkgver%_*}-${pkgver#*_}
+pkgrel=0
+pkgdesc="Linux-VServer admin utilities"
+url="http://www.nongnu.org/util-vserver/"
+arch="all"
+license="GPL"
+install="$pkgname.post-install $pkgname.post-upgrade"
+makedepends="iptables-dev e2fsprogs-dev beecrypt-dev autoconf automake
+ pkgconfig libtool"
+depends="bash make"
+
+source="http://people.linux-vserver.org/~dhozac/t/uv-testing/util-vserver-$_realver.tar.bz2
+ chmod.patch
+ ensc_pathprog.patch
+ validate.patch
+ alpine.patch
+ bb-grep.patch
+ setup-vs-template
+ setup-vs-guest
+ "
+subpackages="$pkgname-doc $pkgname-dev"
+
+_builddir="$srcdir"/$pkgname-$_realver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ msg "Running autotools..."
+ aclocal -I m4 && autoconf && automake && libtoolize || return 1
+
+ # this is an ugly workaround
+ sed -i -e "s:as_echo=.*:as_echo=echo:g" configure
+
+ # issue 305
+ sed -i -e 's/^function //' gentoo/util-vserver
+}
+
+build() {
+ local i
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --sysconfdir=/etc \
+ --with-initscripts=gentoo \
+ --localstatedir=/var \
+ || return 1
+
+ # use busybox ionice rather than util-linux-ng
+ sed -i -e 's:/usr/bin/ionice:/bin/ionice:' Makefile
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir/" install install-distribution || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+
+ # obsolete and broken
+ rm -f "$pkgdir"/usr/sbin/vserver-copy
+
+ install -Dm755 ../setup-vs-template "$pkgdir"/usr/sbin/setup-vs-template
+ install -Dm755 ../setup-vs-guest "$pkgdir"/usr/sbin/setup-vs-guest
+}
+
+md5sums="b9064c39a5ee4bfd5f98c419f3e7edfb util-vserver-0.30.216-pre2981.tar.bz2
+73c7437dea6937a57cf38d166ef83c09 chmod.patch
+ff8f561f672524eb46fe633f584ef60e ensc_pathprog.patch
+da8b70c4fd40e68894b3903ffd121397 validate.patch
+04000261fd990a3963b0e98260b481bd alpine.patch
+3fc52e20d998f02995f21912738f5d36 bb-grep.patch
+49bca7969cc284adf68e0ef284c0660e setup-vs-template
+03e109447c2d500dfb27a3046170b92f setup-vs-guest"
diff --git a/main/util-vserver/alpine.patch b/main/util-vserver/alpine.patch
new file mode 100644
index 0000000000..eacc2cb624
--- /dev/null
+++ b/main/util-vserver/alpine.patch
@@ -0,0 +1,26 @@
+Index: distrib/alpine/initpost
+===================================================================
+--- a/distrib/alpine/initpost (revision 2855)
++++ b/distrib/alpine/initpost (working copy)
+@@ -1,6 +1,6 @@
+ #!/bin/bash
+
+-# Copyright (C) 2007 Natanael Copa <ncopa@alpinelinux.org>
++# Copyright (C) 2007, 2009 Natanael Copa <ncopa@alpinelinux.org>
+ #
+ # 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
+@@ -37,7 +37,12 @@
+ $_VSERVER "$vserver" stop &>/dev/null || true
+ $_VSERVER "$vserver" start --rescue --rescue-init /bin/busybox sh -c '
+ /bin/busybox --install -s
+- /sbin/rc_add -s 20 -k syslog
++ if [ -x /sbin/rc-update ]; then
++ /sbin/rc-update add syslog boot
++ /bin/rmdir /etc/rcL.d /etc/rcK.d
++ else
++ /sbin/rc_add -s 20 -k syslog
++ fi
+ '
+
+ # set up hostname
diff --git a/main/util-vserver/bb-grep.patch b/main/util-vserver/bb-grep.patch
new file mode 100644
index 0000000000..ce6c5f0459
--- /dev/null
+++ b/main/util-vserver/bb-grep.patch
@@ -0,0 +1,20 @@
+--- ./scripts/functions.orig
++++ ./scripts/functions
+@@ -553,7 +553,7 @@
+ for _ga_j in "${_ga_marks[@]}"; do
+ _ga_mark="$(echo "$_ga_j" | $_SED 's/^[!~]//')"
+ test "$_ga_j" = "$_ga_mark" || _ga_invert=true
+- test -s "$_ga_markfile" && $_GREP -qx "$_ga_mark" "$_ga_markfile" && \
++ test -s "$_ga_markfile" && $_GREP -q "^$_ga_mark\$" "$_ga_markfile" && \
+ _ga_f=true || :
+ done
+ test $_ga_f = $_ga_invert && \
+@@ -637,7 +637,7 @@
+ set -- $($_GREP '^Tasks:' "/proc/virtual/$1/status" 2>/dev/null)
+ _gp_procnr_cnt=$2
+ else
+- _gp_procnr_cnt=$($_VPS ax | $_AWK '{print $2}' | $_GREP -x "$1" | $_WC -l )
++ _gp_procnr_cnt=$($_VPS ax | $_AWK '{print $2}' | $_GREP "^$1\$" | $_WC -l )
+ fi
+
+ let _gp_procnr_cnt=_gp_procnr_cnt+0
diff --git a/main/util-vserver/chmod.patch b/main/util-vserver/chmod.patch
new file mode 100644
index 0000000000..53861e8932
--- /dev/null
+++ b/main/util-vserver/chmod.patch
@@ -0,0 +1,12 @@
+diff -ru a/Makefile.am b/Makefile.am
+--- a/Makefile.am 2009-09-29 13:48:10.000000000 +0000
++++ b/Makefile.am 2009-09-29 13:50:00.000000000 +0000
+@@ -149,7 +149,7 @@
+ @mkdir -p $$(dirname '$@')
+ @echo "$(SED) -e '...' $*.pathsubst >$*"
+ @$(SED) -e '$(pathsubst_RULES)' '$<' >'$@.tmp'
+- @-chmod --reference='$<' '$@.tmp'
++ @-chmod $$(stat -c %a '$<') '$@.tmp'
+ @if cmp -s '$@.tmp' '$*'; then \
+ echo "... no changes, reusing old version"; \
+ rm -f '$@.tmp'; \
diff --git a/main/util-vserver/ensc_pathprog.patch b/main/util-vserver/ensc_pathprog.patch
new file mode 100644
index 0000000000..e14c1f6dab
--- /dev/null
+++ b/main/util-vserver/ensc_pathprog.patch
@@ -0,0 +1,14 @@
+diff -ru a/m4/ensc_pathprog.m4 b/m4/ensc_pathprog.m4
+--- a/m4/ensc_pathprog.m4 2009-10-02 17:25:49.000000000 +0000
++++ b/m4/ensc_pathprog.m4 2009-10-02 17:31:28.000000000 +0000
+@@ -61,7 +61,9 @@
+
+ if test "x$5" = x; then
+ if test -h "${$1}"; then
+- $1=`readlink -f "${$1}"`
++ case `readlink "{$1}"` in
++ ../*) $1=`readlink -f "${$1}"`;;
++ esac
+ fi
+ fi
+
diff --git a/main/util-vserver/setup-vs-guest b/main/util-vserver/setup-vs-guest
new file mode 100644
index 0000000000..0de3069ba5
--- /dev/null
+++ b/main/util-vserver/setup-vs-guest
@@ -0,0 +1,306 @@
+#!/bin/sh
+
+# simple script to set up a new vserver guest
+
+# test the first argument against the remaining ones, return success on a match
+isin() {
+ local _a=$1 _b
+
+ shift
+ for _b; do
+ [ "$_a" = "$_b" ] && return 0
+ done
+ return 1
+}
+
+# remove all occurrences of first argument from list formed by
+# the remaining arguments
+rmel() {
+ local _a=$1 _b
+
+ shift
+ for _b; do
+ [ "$_a" != "$_b" ] && echo -n "$_b "
+ done
+}
+
+# Issue a read into the global variable $resp.
+_ask() {
+ local _redo=0
+
+ read resp
+ case "$resp" in
+ !) echo "Type 'exit' to return to setup."
+ sh
+ _redo=1
+ ;;
+ !*) eval "${resp#?}"
+ _redo=1
+ ;;
+ esac
+ return $_redo
+}
+
+# Ask for user input.
+#
+# $1 = the question to ask the user
+# $2 = the default answer
+#
+# Save the user input (or the default) in $resp.
+#
+# Allow the user to escape to shells ('!') or execute commands
+# ('!foo') before entering the input.
+ask() {
+ local _question=$1 _default=$2
+
+ while :; do
+ echo -n "$_question "
+ [ -z "$_default" ] || echo -n "[$_default] "
+ _ask && : ${resp:=$_default} && break
+ done
+}
+
+# Ask for user input until a non-empty reply is entered.
+#
+# $1 = the question to ask the user
+# $2 = the default answer
+#
+# Save the user input (or the default) in $resp.
+ask_until() {
+ resp=
+ while [ -z "$resp" ] ; do
+ ask "$1" "$2"
+ done
+}
+
+# Ask for the user to select one value from a list, or 'done'.
+#
+# $1 = name of the list items (disk, cd, etc.)
+# $2 = question to ask
+# $3 = list of valid choices
+# $4 = default choice, if it is not specified use the first item in $3
+#
+# N.B.! $3 and $4 will be "expanded" using eval, so be sure to escape them
+# if they contain spooky stuff
+#
+# At exit $resp holds selected item, or 'done'
+ask_which() {
+ local _name=$1 _query=$2 _list=$3 _def=$4 _dynlist _dyndef
+
+ while :; do
+ # Put both lines in ask prompt, rather than use a
+ # separate 'echo' to ensure the entire question is
+ # re-ask'ed after a '!' or '!foo' shell escape.
+ eval "_dynlist=\"$_list\""
+ eval "_dyndef=\"$_def\""
+
+ # Clean away whitespace and determine the default
+ set -o noglob
+ set -- $_dyndef; _dyndef="$1"
+ set -- $_dynlist; _dynlist="$*"
+ set +o noglob
+ [ $# -lt 1 ] && resp=done && return
+
+ : ${_dyndef:=$1}
+ echo "Available ${_name}s are: $_dynlist."
+ echo -n "Which one $_query? (or 'done') "
+ [ -n "$_dyndef" ] && echo -n "[$_dyndef] "
+ _ask || continue
+ [ -z "$resp" ] && resp="$_dyndef"
+
+ # Quote $resp to prevent user from confusing isin() by
+ # entering something like 'a a'.
+ isin "$resp" $_dynlist done && break
+ echo "'$resp' is not a valid choice."
+ done
+}
+
+# Ask for user input until a non-empty reply is entered.
+#
+# $1 = the question to ask the user
+# $2 = the default answer
+#
+# Save the user input (or the default) in $resp.
+ask_until() {
+ resp=
+ while [ -z "$resp" ] ; do
+ ask "$1" "$2"
+ done
+}
+
+# http://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
+valid_hostname() {
+ # check length
+ if [ $(echo "$1" | wc -c) -gt 63 ]; then
+ echo "Hostname '$1' is too long."
+ return 1
+ fi
+ # check that it only contains valid chars
+ if ! [ -z "$(echo $1 | sed 's/[0-9a-z-]//g')" ]; then
+ echo "Hostname must only contain letters (a-z), digits (0-9) or -"
+ return 1
+ fi
+ # must not start with -
+ case "$1" in
+ -*) echo "Hostname must not start with a '-'"; return 1;;
+ esac
+ return 0
+}
+
+# return last ipv4 address and mask
+#
+# $1 = interface
+#
+last_ipv4_addr_mask() {
+ local _iface=$1
+ ip addr show dev $_iface | awk '$1 == "inet" {print $2}' | tail -n1
+}
+
+valid_ip_and_prefix() {
+ [ "$1" ] || return 0
+ ipcalc -s -m $1 >/dev/null 2>&1 && ! ipcalc -s -m $1/0 >/dev/null 2>&1
+}
+
+# ask for hostname
+#
+# $1 = default
+#
+# retrusn hostname in global var $resp
+#
+ask_hostname() {
+ while true; do
+ ask "Hostname for new vserver:" $1
+ if [ -d /etc/vservers/$resp ]; then
+ echo "/etc/vservers/$resp already exist"
+ continue
+ fi
+ if [ -d /vservers/$resp ]; then
+ echo "/vservers/$resp already exist"
+ continue
+ fi
+ valid_hostname $resp && break
+ done
+}
+
+ask_ifaceopts() {
+ # get ip address(es)
+ resp=
+ local ifaceopts= _def= _iface=
+ local ifaces=$(ip addr | awk -F: '$1 ~ /^[0-9]/ {printf "%s" $2} END {printf "\n"}')
+ local last_iface=$(echo $ifaces | sed 's/.* //')
+ while [ "$resp" != "done" ]; do
+ if [ -z "$ifaces" ] || [ "$ifaces" = "lo " ] || [ -n "$ifaceopts" ]; then
+ _def="done"
+ else
+ _def=$(echo $ifaces | sed 's/.* //')
+ fi
+ ask_which "network interface" "to use for $_hostname" \
+ "$ifaces" $_def
+ [ "$resp" = "done" ] && break
+
+ _iface=$resp
+ ifaces=$(rmel $_iface $ifaces)
+ # suggested ip by last digit + 1
+ _last_ip_mask=$(last_ipv4_addr_mask $_iface)
+ _last_ip=${_last_ip_mask%/*}
+ _last_ip_digit=${_last_ip##*.}
+ _ip=${_last_ip%.*}.$((($_last_ip_digit + 1) % 256))
+ _mask=${_last_ip_mask#*/}
+ while true; do
+ ask "Enter IP address/mask for $_iface:" $_ip/$_mask
+ valid_ip_and_prefix "$resp" 2>&1 && break
+ echo "$resp is not a valid IPv4 address/mask"
+ done
+ _ip_mask=$resp
+ ifaceopts="$ifaceopts --interface $_iface:$_ip_mask"
+
+ # suggest context from last digit in first ip address
+ if [ -z "$_context" ]; then
+ _ip=${_ip_mask%/*}
+ _last_digit=${_ip##*.}
+ _context=$((10000 + $_last_digit))
+ fi
+ done
+ resp="$ifaceopts"
+}
+
+ask_context() {
+ # get context id
+ while true; do
+ ask "Enter context id for $_hostname:" $_context
+ if echo "$resp" | egrep -q "[0-9]+"; then
+ [ $resp -ge 0 ] && [ $resp -lt 65535 ] && break
+ fi
+ echo "Context id must be a 0-65534 number"
+ done
+}
+
+ask_template() {
+ local temp
+ # get template
+ while true; do
+ ask "Enter template file (or empty for generate a new):" \
+ $_template
+ if [ -z "$resp" ] || [ -r "$resp" ]; then
+ break
+ fi
+ echo "Can not read $resp"
+ done
+ temp=$resp
+ if [ -z "$temp" ]; then
+ temp=/vservers/template.tar.gz
+ echo "Generating template..."
+ if setup-vs-template -q -o $temp; then
+ echo "ok"
+ else
+ echo "Failed to create template"
+ exit 1
+ fi
+ fi
+ resp=$temp
+}
+
+usage() {
+ echo "Usage: ${0##*/} [-h] [HOSTNAME...]"
+ exit 1
+}
+
+while getopts "h" opt; do
+ case "$opt" in
+ h) usage;;
+ ?) usage;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+if [ "$(whoami)" != "root" ]; then
+ echo "Need to be root. Sorry."
+ exit 1
+fi
+
+while true; do
+ ask_hostname $1
+ _hostname=$resp
+
+ ask_ifaceopts
+ _ifaceopts=$resp
+
+ ask_context
+ _context=$resp
+
+ ask_template
+ _template=$resp
+
+ vserver $_hostname build \
+ --hostname $_hostname \
+ $_ifaceopts \
+ --context $_context \
+ -m template -- -t "$_template" -d alpine \
+ && cp /etc/resolv.conf /vservers/$_hostname/etc/ \
+ && cp /etc/apk/repositories /vservers/$_hostname/etc/apk/ \
+ || exit 1
+
+ shift
+ [ $# -le 0 ] && exit 0
+done
diff --git a/main/util-vserver/setup-vs-template b/main/util-vserver/setup-vs-template
new file mode 100644
index 0000000000..8ad7f3fae8
--- /dev/null
+++ b/main/util-vserver/setup-vs-template
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# create a vserver template
+PROG=$0
+
+usage() {
+ echo "usage: $PROG [-fhq] [-o OUTFILE] [-X repository] [packages...]"
+ exit $1
+}
+
+clean_exit() {
+ rm -rf "$tmpdir"
+ exit $1
+}
+
+outfile=template.tar.gz
+fakeroot=
+repos=
+while getopts "ho:qX:" opt; do
+ case "$opt" in
+ h) usage 0;;
+ o) outfile="$OPTARG";;
+ q) quiet=-q;;
+ X) repos="$repos --repository $OPTARG";;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+if [ "$(whoami)" != "root" ]; then
+ echo "Warning: you need root permissions" >&2
+fi
+
+tmpdir=$(mktemp -d ${TMPDIR:-/tmp}/setup-vs-template-XXXXXX)
+
+apk add --root "$tmpdir" --initdb --keys-dir /etc/apk/keys -U \
+ $quiet ${repos:---repositories-file /etc/apk/repositories} \
+ alpine-base $@ \
+ || clean_exit 1
+
+tar -czf "$outfile" -C "$tmpdir" $(ls "$tmpdir") || clean_exit 1
+
+[ -z "$quiet" ] && echo "Created $outfile"
+clean_exit 0
+
diff --git a/main/util-vserver/util-vserver.post-install b/main/util-vserver/util-vserver.post-install
new file mode 100644
index 0000000000..9c8aad1e4c
--- /dev/null
+++ b/main/util-vserver/util-vserver.post-install
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+if [ -f /etc/vservers/.defaults/rlimits/nproc ]; then
+ exit 0
+fi
+
+# calculate the nproc limit from amount of ram
+memtotal=$(awk '$1 == "MemTotal:" {print $2}' /proc/meminfo 2>/dev/null)
+nproc=$(( ${memtotal:-524288} / 256 ))
+
+# set a "sane" default nproc limit
+echo "Setting default nproc limit to $nproc"
+mkdir -p /etc/vservers/.defaults/rlimits
+echo $nproc > /etc/vservers/.defaults/rlimits/nproc
+
diff --git a/main/util-vserver/util-vserver.post-upgrade b/main/util-vserver/util-vserver.post-upgrade
new file mode 120000
index 0000000000..c5db4163fd
--- /dev/null
+++ b/main/util-vserver/util-vserver.post-upgrade
@@ -0,0 +1 @@
+util-vserver.post-install \ No newline at end of file
diff --git a/main/util-vserver/validate.patch b/main/util-vserver/validate.patch
new file mode 100644
index 0000000000..081dce5a31
--- /dev/null
+++ b/main/util-vserver/validate.patch
@@ -0,0 +1,10 @@
+diff -ru a/m4/validate.am b/m4/validate.am
+--- a/m4/validate.am 2009-10-02 17:57:03.000000000 +0000
++++ b/m4/validate.am 2009-10-02 17:58:15.000000000 +0000
+@@ -26,5 +26,5 @@
+ .%-up-to-date:
+ @rm -f .*-up-to-date
+ @$(MAKE) -s clean
+- @touch -t 197001020000 '$@'
++ @cp -a Makefile.am '$@'
+ @$(MAKE) -s $(BUILT_SOURCES)
diff --git a/main/uvncrepeater/APKBUILD b/main/uvncrepeater/APKBUILD
new file mode 100644
index 0000000000..e9ec39c251
--- /dev/null
+++ b/main/uvncrepeater/APKBUILD
@@ -0,0 +1,44 @@
+# Contributor:
+# Maintainer:
+pkgname=uvncrepeater
+pkgver=014
+pkgrel=3
+pkgdesc="VNC repeater based on ultravnc repeater"
+url="http://koti.mbnet.fi/jtko/"
+arch="all"
+license="GPL-2"
+depends="openrc>=0.6"
+makedepends=
+install="$pkgname.pre-install"
+subpackages=
+source="http://koti.mbnet.fi/jtko/uvncrepeater/repeater$pkgver.zip
+ uvncrepeater.confd
+ uvncrepeater.initd"
+
+_builddir="$srcdir"/Ver$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # respect our CXX and CFLAGS
+ sed -i -e 's/g++/$(CXX)/g' \
+ -e "/^CFLAGS/d" Makefile
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ install -Dm755 repeater "$pkgdir"/usr/bin/repeater
+ install -Dm644 uvncrepeater.ini "$pkgdir"/etc/uvncrepeater.ini
+ install -Dm755 "$srcdir"/uvncrepeater.initd \
+ "$pkgdir"/etc/init.d/uvncrepeater
+ install -Dm755 "$srcdir"/uvncrepeater.confd \
+ "$pkgdir"/etc/conf.d/uvncrepeater
+}
+
+md5sums="3005ebbb2f9442cbea4cbcaa71925dbf repeater014.zip
+9a789921340c123ea1c35d7e64563c64 uvncrepeater.confd
+a9c614f7bfeef4f68db7cd9d87a6bdf6 uvncrepeater.initd"
diff --git a/main/uvncrepeater/uvncrepeater.confd b/main/uvncrepeater/uvncrepeater.confd
new file mode 100644
index 0000000000..1d0b3ce89b
--- /dev/null
+++ b/main/uvncrepeater/uvncrepeater.confd
@@ -0,0 +1,4 @@
+# redirect debug logging to this file
+#
+# uvncrepeater_logfile=/var/log/uvncrepeater.log
+
diff --git a/main/uvncrepeater/uvncrepeater.initd b/main/uvncrepeater/uvncrepeater.initd
new file mode 100644
index 0000000000..655ade9240
--- /dev/null
+++ b/main/uvncrepeater/uvncrepeater.initd
@@ -0,0 +1,32 @@
+#!/sbin/runscript
+
+# Sample init.d file for alpine linux.
+
+name=repeater
+daemon=/usr/bin/$name
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting VNC ${name}"
+ start-stop-daemon --start --quiet \
+ --pidfile /var/run/${name}.pid \
+ --make-pidfile --background \
+ --wait ${uvncrepeater_wait:-500} \
+ --stderr ${uvncrepeater_logfile:-/dev/null} \
+ --stdout /dev/null \
+ --exec ${daemon} -- /etc/uvncrepeater.ini
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping VNC ${name}"
+ start-stop-daemon --stop --quiet \
+ --pidfile /var/run/$name.pid \
+ --exec ${daemon}
+ eend $?
+}
+
diff --git a/main/uvncrepeater/uvncrepeater.pre-install b/main/uvncrepeater/uvncrepeater.pre-install
new file mode 100644
index 0000000000..2e1e6730a7
--- /dev/null
+++ b/main/uvncrepeater/uvncrepeater.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+adduser -D -S uvncrep 2>/dev/null
+exit 0
+
diff --git a/main/v4l-utils/APKBUILD b/main/v4l-utils/APKBUILD
new file mode 100644
index 0000000000..887379ab0e
--- /dev/null
+++ b/main/v4l-utils/APKBUILD
@@ -0,0 +1,54 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Francesco Colista <francesco.colista@gmail.com>
+pkgname=v4l-utils
+pkgver=0.8.4
+pkgrel=1
+pkgdesc="Userspace tools and conversion library for Video 4 Linux"
+url="http://freshmeat.net/projects/libv4l"
+arch="all"
+license="LGPL"
+depends=""
+makedepends="qt-dev jpeg-dev"
+install=""
+subpackages="$pkgname-dev qv4l2"
+source="http://linuxtv.org/downloads/v4l-utils/$pkgname-$pkgver.tar.bz2
+ qv4l2.svg
+ qv4l2.desktop"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ sed -i 's|CFLAGS :=|CFLAGS ?=|' Make.rules
+ # TODO: make a proper patch insted of this hugly hack
+ # uclibc does not have argp.h
+ # http://www.spinics.net/lists/linux-media/msg28619.html
+ rm -rf utils/decode_tm6000 utils/keytable
+ sed -i 's/decode_tm6000 //g' utils/Makefile
+ sed -i 's/keytable //g' utils/Makefile
+}
+
+build() {
+ cd "$_builddir"
+ make PREFIX="/usr" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 PREFIX="/usr" DESTDIR="$pkgdir" install || return 1
+ install -Dm644 "$srcdir"/qv4l2.desktop \
+ "$pkgdir"/usr/share/applications/qv4l2.desktop || return 1
+ install -Dm644 "$srcdir"/qv4l2.svg \
+ "$pkgdir"/usr/share/icons/hicolor/scalable/apps/qv4l2.svg
+}
+
+qv4l2() {
+ pkgdesc="QT v4l2 test control and streaming test application"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/qv4l2 "$subpkgdir"/usr/bin/ || return 1
+ mv "$pkgdir"/usr/share "$subpkgdir"/usr/ || return 1
+}
+
+md5sums="f2ded401b9b8d77f5ec7fac4683cfadf v4l-utils-0.8.4.tar.bz2
+75ef594ddfe48e48df99c96c2af6b51e qv4l2.svg
+b2e51f9663cee1c38a1d99d76a6b529f qv4l2.desktop"
diff --git a/main/v4l-utils/qv4l2.desktop b/main/v4l-utils/qv4l2.desktop
new file mode 100644
index 0000000000..55e369c7c5
--- /dev/null
+++ b/main/v4l-utils/qv4l2.desktop
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=QT V4L2 test Utility
+Name[pt]=Utilitário de teste V4L2
+Comment=Allow testing Video4Linux devices
+Comment[pt]=Permite testar dispositivos Video4Linux
+Exec=qv4l2
+Icon=qv4l2
+Terminal=false
+Type=Application
+Categories=Application;AudioVideo;
+
diff --git a/main/v4l-utils/qv4l2.svg b/main/v4l-utils/qv4l2.svg
new file mode 100644
index 0000000000..3d4f375cc2
--- /dev/null
+++ b/main/v4l-utils/qv4l2.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" inkscape:version="0.47 r22583" version="1.1" id="svg2839" height="297mm" width="210mm" sodipodi:docname="Novo documento 3">
+ <defs id="defs2841">
+ <linearGradient id="linearGradient2963">
+ <stop style="stop-color: rgb(255, 236, 187); stop-opacity: 1;" offset="0" id="stop2965"/>
+ <stop id="stop2971" offset="1" style="stop-color: rgb(0, 0, 0); stop-opacity: 0.498039;"/>
+ </linearGradient>
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" id="perspective2847"/>
+ <inkscape:perspective id="perspective2935" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" inkscape:vp_z="1 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 0.5 : 1" sodipodi:type="inkscape:persp3d"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2963" id="linearGradient2969" x1="-719.14288" y1="494.69958" x2="-324.21902" y2="968.98529" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0512, 0, 0, 1.05137, 651.058, -25.2444)"/>
+ <inkscape:perspective id="perspective2992" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" inkscape:vp_z="1 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 0.5 : 1" sodipodi:type="inkscape:persp3d"/>
+ </defs>
+ <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.7" inkscape:cx="376.9721" inkscape:cy="468.42546" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="1513" inkscape:window-height="1044" inkscape:window-x="1941" inkscape:window-y="0" inkscape:window-maximized="0"/>
+ <metadata id="metadata2844">
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title/>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g inkscape:label="Camada 1" inkscape:groupmode="layer" id="layer1">
+ <rect style="fill: rgb(173, 160, 127); fill-opacity: 1;" id="rect2959" width="498.57132" height="402.52496" x="101.42867" y="345.21906" ry="15.848869"/>
+ <rect style="fill: rgb(214, 207, 189); fill-opacity: 1; fill-rule: evenodd; stroke: rgb(0, 0, 0); stroke-width: 1.09651px; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" id="rect2955" width="366.37466" height="268.80539" x="172.03215" y="409.8259" ry="24.860613"/>
+ <path style="fill: url(&quot;#linearGradient2969&quot;) rgb(0, 0, 0); fill-opacity: 1;" d="m 111.92284,745.80915 c -1.7443,-0.70488 -4.61634,-3.11878 -6.38231,-5.3642 l -3.21086,-4.08259 0,-189.14299 c 0,-136.34795 0.46823,-190.05871 1.67748,-192.42365 0.92263,-1.80438 3.11889,-4.44845 4.8806,-5.87571 3.00442,-2.43405 17.98923,-2.5971 241.57759,-2.62843 l 238.37448,-0.0334 4.90427,4.38251 4.90429,4.3825 0.39257,189.41161 c 0.43575,210.24489 1.09242,196.30432 -9.4544,200.71175 -4.34407,1.81535 -40.20923,2.12038 -239.80015,2.0394 -129.08065,-0.0523 -236.11926,-0.67193 -237.86356,-1.37681 z m 413.94314,-69.49552 c 4.39946,-2.22093 7.85143,-5.43895 10.06966,-9.38725 l 3.37535,-6.00784 -0.36571,-118.16973 c -0.36124,-116.72035 -0.4037,-118.22058 -3.46195,-122.31682 -4.69144,-6.28374 -10.15101,-9.79936 -17.39001,-11.19809 -8.54594,-1.65125 -316.90144,-1.65125 -325.4474,0 -7.68,1.48394 -13.16379,5.20817 -17.88452,12.146 l -3.40519,5.00442 0.40173,119.03503 c 0.39878,118.15286 0.42505,119.06645 3.54637,123.27494 1.72955,2.33195 5.7842,5.74954 9.01033,7.59462 l 5.8657,3.35471 164.49565,0.0248 164.49566,0.0246 6.69433,-3.3794 z" id="path2961"/>
+ <rect style="fill: rgb(25, 20, 8); fill-opacity: 1;" id="rect2980" width="63.072273" height="39.050926" x="499.38467" y="744.74005" ry="0"/>
+ <rect style="fill: rgb(25, 20, 8); fill-opacity: 1;" id="rect2980-1" width="63.072273" height="39.050926" x="130.56888" y="744.74005" ry="0"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/main/v86d/APKBUILD b/main/v86d/APKBUILD
new file mode 100644
index 0000000000..2a15f0159b
--- /dev/null
+++ b/main/v86d/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=v86d
+pkgver=0.1.10
+pkgrel=0
+pkgdesc="userspace helper for uvesafb that runs x86 code in an emulated environment"
+url="http://dev.gentoo.org/~spock/projects/uvesafb/"
+arch="all"
+license="GPL2"
+depends=""
+makedepends="bash"
+source="http://dev.gentoo.org/~spock/projects/uvesafb/archive/$pkgname-$pkgver.tar.bz2
+ modprobe.uvesafb"
+
+build ()
+{
+ cd "$srcdir"/v86d-$pkgver
+ ./configure --with-x86emu
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/v86d-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 "$srcdir"/modprobe.uvesafb "$pkgdir"/etc/modprobe.d/uvesafb || return 1
+}
+md5sums="51c792ba7b874ad8c43f0d3da4cfabe0 v86d-0.1.10.tar.bz2
+2d7cc8dc6a41916a13869212d0191147 modprobe.uvesafb"
diff --git a/main/v86d/modprobe.uvesafb b/main/v86d/modprobe.uvesafb
new file mode 100644
index 0000000000..5e46e10883
--- /dev/null
+++ b/main/v86d/modprobe.uvesafb
@@ -0,0 +1,10 @@
+#
+# This file sets the parameters for uvesafb module.
+# The following format should be used:
+# options uvesafb mode=<xres>x<yres>[-<bpp>][@<refresh>] scroll=<ywrap|ypan|redraw> ...
+#
+# For more details see:
+# http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/fb/uvesafb.txt
+#
+
+options uvesafb mode_option=1024x768-32 scroll=ywrap
diff --git a/main/vala/APKBUILD b/main/vala/APKBUILD
new file mode 100644
index 0000000000..26156c0bd1
--- /dev/null
+++ b/main/vala/APKBUILD
@@ -0,0 +1,40 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=vala
+pkgver=0.12.1
+pkgrel=1
+pkgdesc="Compiler for the GObject type system"
+url="http://live.gnome.org/Vala"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-doc"
+depends="glib-dev"
+makedepends="libxslt-dev bash glib-dev flex bison"
+source="http://download.gnome.org/sources/vala/${pkgver%.*}/vala-$pkgver.tar.bz2
+ version.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg "$i"; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --enable-vapigen || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="bf35262cc611de447147d01cbac33767 vala-0.12.1.tar.bz2
+99524c2de7df37c95f314709a041ac65 version.patch"
diff --git a/main/vala/version.patch b/main/vala/version.patch
new file mode 100644
index 0000000000..27c6799c92
--- /dev/null
+++ b/main/vala/version.patch
@@ -0,0 +1,17 @@
+diff --git a/build-aux/git-version-gen b/build-aux/git-version-gen
+index 0fa6faa..596203a 100755
+--- a/build-aux/git-version-gen
++++ b/build-aux/git-version-gen
+@@ -129,7 +129,11 @@ v=`echo "$v" |sed 's/^v//'`
+ # Don't declare a version "dirty" merely because a time stamp has changed.
+ git status > /dev/null 2>&1
+
+-dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
++if [ -d .git ]; then
++ dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
++else
++ dirty=
++fi
+ case "$dirty" in
+ '') ;;
+ *) # Append the suffix only if there isn't one already.
diff --git a/main/valgrind/APKBUILD b/main/valgrind/APKBUILD
new file mode 100644
index 0000000000..1f1ec11a70
--- /dev/null
+++ b/main/valgrind/APKBUILD
@@ -0,0 +1,62 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=valgrind
+pkgver=3.6.1
+pkgrel=1
+pkgdesc="A tool to help find memory-management problems in programs"
+url="http://valgrind.org/"
+arch="all"
+license="GPL"
+depends=""
+# it seems like busybox sed works but the configure script requires GNU sed
+makedepends="sed paxctl pax-utils perl bash"
+# from README_PACKAGERS:
+# Don't strip the debug info off lib/valgrind/$platform/vgpreload*.so
+# in the installation tree. Either Valgrind won't work at all, or it
+# will still work if you do, but will generate less helpful error
+# messages.
+options="!strip"
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://$pkgname.org/downloads/$pkgname-$pkgver.tar.bz2
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ local i
+ for i in "$srcdir"/*.patch; do
+ [ -f "$i" ] || continue
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+}
+
+build() {
+ cd "$_builddir"
+ # fails to build with ccache
+ export CC="gcc"
+ ./configure --prefix=/usr \
+ --without-mpicc \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+
+ # we have options=!strip above so we strip the /usr/bin/* manually
+ if [ -z "$DEBUG" ]; then
+ strip "$pkgdir"/usr/bin/valgrind \
+ "$pkgdir"/usr/bin/no_op_client_for_valgrind \
+ "$pkgdir"/usr/bin/valgrind-listener \
+ "$pkgdir"/usr/bin/cg_merge
+ fi
+
+ # pax causes some issues
+ # http://marc.info/?l=gentoo-hardened&m=119512627126298&w=2
+ if [ -x "$pkgdir"/usr/lib/valgrind/memcheck-amd64-linux ]; then
+ paxctl -c -m "$pkgdir"/usr/lib/valgrind/memcheck-amd64-linux
+ fi
+}
+
+md5sums="2c3aa122498baecc9d69194057ca88f5 valgrind-3.6.1.tar.bz2"
diff --git a/main/valgrind/valgrind-3.4.0-uclibc.patch b/main/valgrind/valgrind-3.4.0-uclibc.patch
new file mode 100644
index 0000000000..db6551996e
--- /dev/null
+++ b/main/valgrind/valgrind-3.4.0-uclibc.patch
@@ -0,0 +1,12 @@
+--- valgrind-3.4.0/drd/drd_pthread_intercepts.c.orig Thu Jan 22 14:37:52 2009
++++ valgrind-3.4.0/drd/drd_pthread_intercepts.c Thu Jan 22 14:38:12 2009
+@@ -122,9 +122,6 @@
+ /* PTHREAD_MUTEX_TIMED_NP */
+ /* PTHREAD_MUTEX_NORMAL */
+ case PTHREAD_MUTEX_DEFAULT:
+-#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
+- case PTHREAD_MUTEX_ADAPTIVE_NP:
+-#endif
+ return mutex_type_default_mutex;
+ }
+ return mutex_type_invalid_mutex;
diff --git a/main/vanessa_adt/APKBUILD b/main/vanessa_adt/APKBUILD
new file mode 100644
index 0000000000..b7c8ee6912
--- /dev/null
+++ b/main/vanessa_adt/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Leonardo Arena <rnalrd@alpinelinux.org>
+pkgname=vanessa_adt
+pkgver=0.0.8
+pkgrel=1
+pkgdesc="Library of abstract data types"
+url="http://horms.net/projects/perdition/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="vanessa_logger-dev"
+makedepends="$depends_dev"
+install=
+subpackages="$pkgname-dev"
+source="http://horms.net/projects/perdition/download/1.18/$pkgname-$pkgver.tar.bz2"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="d80b0d23efb484c7a6226acd424299b7 vanessa_adt-0.0.8.tar.bz2"
diff --git a/main/vanessa_logger/APKBUILD b/main/vanessa_logger/APKBUILD
new file mode 100644
index 0000000000..3fc1f8f4fe
--- /dev/null
+++ b/main/vanessa_logger/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Leonardo Arena <rnalrd@alpinelinux.org>
+pkgname=vanessa_logger
+pkgver=0.0.8
+pkgrel=1
+pkgdesc="Logging library"
+url="http://horms.net/projects/perdition/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev=""
+makedepends="$depends_dev"
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://horms.net/projects/perdition/download/1.18/$pkgname-$pkgver.tar.bz2"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="3b70c8b330d25fb97ef9d7f3fd71c0b0 vanessa_logger-0.0.8.tar.bz2"
diff --git a/main/vanessa_socket/APKBUILD b/main/vanessa_socket/APKBUILD
new file mode 100644
index 0000000000..4b62f179f6
--- /dev/null
+++ b/main/vanessa_socket/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Leonardo Arena <rnalrd@alpinelinux.org>
+pkgname=vanessa_socket
+pkgver=0.0.10
+pkgrel=1
+pkgdesc="User space TCP/IP pipe"
+url="http://horms.net/projects/perdition/"
+arch="all"
+license="LGPL"
+depends=
+depends_dev="popt-dev vanessa_logger-dev"
+makedepends="$depends_dev"
+install=
+subpackages="$pkgname-dev"
+source="http://horms.net/projects/perdition/download/1.18/$pkgname-$pkgver.tar.bz2"
+
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="fc351cde6b388fced8befeaff3912d3b vanessa_socket-0.0.10.tar.bz2"
diff --git a/main/vblade/APKBUILD b/main/vblade/APKBUILD
new file mode 100644
index 0000000000..383b15c199
--- /dev/null
+++ b/main/vblade/APKBUILD
@@ -0,0 +1,34 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=vblade
+pkgver=20
+pkgrel=0
+pkgdesc="virtual AoE blade server"
+url="http://aoetools.sourceforge.net/"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://downloads.sourceforge.net/aoetools/$pkgname-$pkgver.tgz"
+arch="all"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ mkdir -p "$pkgdir"/usr/sbin
+ mkdir -p "$pkgdir"/usr/share/man/man8
+ make sbindir="$pkgdir"/usr/sbin mandir="$pkgdir"/usr/share/man install
+}
+
+md5sums="3c80e4a6bc7d66ae0c235b88cb44bd59 vblade-20.tgz"
diff --git a/main/videoproto/APKBUILD b/main/videoproto/APKBUILD
new file mode 100644
index 0000000000..bbd3b9a351
--- /dev/null
+++ b/main/videoproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=videoproto
+pkgver=2.3.1
+pkgrel=0
+pkgdesc="X11 Video extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org//releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="c3b348c6e2031b72b11ae63fc7f805c2 videoproto-2.3.1.tar.bz2"
diff --git a/main/vim/APKBUILD b/main/vim/APKBUILD
new file mode 100644
index 0000000000..57862e5bad
--- /dev/null
+++ b/main/vim/APKBUILD
@@ -0,0 +1,272 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=vim
+pkgver=7.3.206
+_srcver=${pkgver%.*}
+_patchver=${pkgver##*.}
+pkgrel=1
+pkgdesc="advanced text editor"
+url="http://www.vim.org"
+arch="all"
+license='GPL'
+depends=
+makedepends="ncurses-dev lua-dev"
+subpackages="$pkgname-doc"
+
+# use "abuild patchlist >> APKBUILD" to generate the list of patches
+source="ftp://ftp.vim.org/pub/vim/unix/vim-${_srcver}.tar.bz2
+ vimrc
+ "
+
+# generate url's to patches. note: no forks allowed!
+_i=1
+_pad="00"
+while [ $_i -le $_patchver ]; do
+ [ $_i -ge 10 ] && _pad="0"
+ [ $_i -ge 100 ] && _pad=
+ source="$source http://ftp.vim.org/pub/vim/patches/$_srcver/$_srcver.$_pad$_i"
+ _i=$(( $_i + 1))
+done
+
+_builddir="$srcdir"/${pkgname}${_srcver/./}
+prepare() {
+ local i
+ cd "$_builddir"
+
+ for i in $source ; do
+ case $i in
+ *.patch|$_srcver.[0-9]*)
+ msg "Applying $i"
+ patch -p0 < $i || return 1
+ ;;
+ esac
+ done
+
+ # Read vimrc from /etc/vim
+ echo '#define SYS_VIMRC_FILE "/etc/vim/vimrc"' >> src/feature.h
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --enable-luainterp \
+ --without-x \
+ --disable-nls \
+ --enable-multibyte \
+ --enable-gui=no
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir/" install
+ install -D "$srcdir"/vimrc "$pkgdir"/etc/vim/vimrc
+}
+
+md5sums="5b9510a17074e2b37d8bb38ae09edbf2 vim-7.3.tar.bz2
+97aecde2ab504e543a96bec84b3b5638 vimrc
+aa5582d8289b43255f45d4bb6f62e140 7.3.001
+2949cbdfe86f533c487fd144c5935c7a 7.3.002
+9059db41cf3a468935745242cb9c0514 7.3.003
+9aaa4490d2fbf9a1e780a151fb41f279 7.3.004
+bf5b5fad8c4de23449fa7c7c01969369 7.3.005
+f53d95dfb1eee5f5f769594174d0e9d4 7.3.006
+a7a4c56110662bc3ba6fbb2fd645d94f 7.3.007
+be756a231afe754d004b6c8a9d12bb50 7.3.008
+f4ed2feff44e2c1898fd5e60f9f97b0d 7.3.009
+4fffed01d3683b0b8b23df600a0bada2 7.3.010
+4ee8f06dce300c0be029bf00b03ef093 7.3.011
+89faf7d5eef1d1d50b657fe34ee7c90b 7.3.012
+6a029d61f7d51c1bea55330732676319 7.3.013
+d0109c0c413c405fdb827ec20f3903d8 7.3.014
+4db0a869dbe00c360541ad2c1ca87a2d 7.3.015
+e0c634532a865d7ed47942080e371b3e 7.3.016
+f52aa5bc3df02c3bb4c75849b2b5f431 7.3.017
+02270ecbc1dc2f57de80441ac7cdd0f0 7.3.018
+5c1be1a0a107261e0a716c877c82fc97 7.3.019
+ef09917435a7cab9382abe3708cf5152 7.3.020
+53c90651baf1b4b28c99947de58deb91 7.3.021
+c4cb1bf3fa0a45d9cad997cd02fa9439 7.3.022
+1e34e216b0e419096f796d3511ce88da 7.3.023
+5c2ff27d8ce8d1aeb42ff16ca1cb89c2 7.3.024
+69b3e00a17230da16d3be4b96f125196 7.3.025
+687a80a82d05e8e91e9ee659b3e0dd67 7.3.026
+1994a0d1e52111b9fa1b999745da93b8 7.3.027
+2438a52f25cf167bbf5711fc8c7323d7 7.3.028
+302ca6aa621c215736f3db069f8c2285 7.3.029
+ceb0e12297907b13dd39fafffa731c62 7.3.030
+acb42f7f4545a63d35396360dc2799ff 7.3.031
+56c9d1681bfc9fe5e76c281b905f0ad8 7.3.032
+4a399b6f1bcde6d991088118f5a58222 7.3.033
+40580589a13a36cc72a600200b93b8d2 7.3.034
+8f7a617b0cf8fea46e4b1557bc286fda 7.3.035
+3ac58b7fe8347ad87f3628bfb4970f1b 7.3.036
+d83c7635e8b65db98a377f3cc7b72ce0 7.3.037
+a310c68726540ac1a0759ef12778bed1 7.3.038
+6b7243d85b86e03b4a782e4bf6d7646e 7.3.039
+8aa33a527433f1907b72ac7c514d455d 7.3.040
+979abe1512bc48dbaed028a23cb2f6cc 7.3.041
+984ce81978ef2b12b3a09986d37e4719 7.3.042
+27b2418128b4322c3cb92b13d577ad6c 7.3.043
+c29e637b242682dc6df544a0bc89abc4 7.3.044
+bd6ac17eecf226a2d6a31e4fb9069ded 7.3.045
+d97f518c548de06b11b5682f2ca4d9a9 7.3.046
+ae37e72299f02ea1b7f2bb59932ed306 7.3.047
+39aaaf13dfef317febb2442626f262f1 7.3.048
+6469fb212e95ad83c21aaaaf8aee0f3a 7.3.049
+e40dc723ef91adee9854faceaba1e201 7.3.050
+5611eda78907716863ebd6ebd19a000f 7.3.051
+01011da656094510c1cdabbc80c129b9 7.3.052
+faaf035020dcf22b57fa76c998e4553b 7.3.053
+90bd11788f022dc1107f93e702734a2a 7.3.054
+5b4fe73d1c47ab36a6b0a8f5ddd2fe65 7.3.055
+b53b7452e5b92bb1b91e9dd97e52dfcd 7.3.056
+bce5e42b7d2b7a91c332e39ed1f0eec8 7.3.057
+1c6054466398f4612a81289de764ef5c 7.3.058
+e2cf5697e8708390e106553de68ebb2b 7.3.059
+16da4369ed89f0305cf2c3ed1bf338fc 7.3.060
+cbed85cdfe0ad4a1b7b43efc64b1531c 7.3.061
+77f08258dbf30e12914475802eeb9b3d 7.3.062
+97c878554fec3d4f9caf934c0a0c227d 7.3.063
+5f74fee465073a3eb48565300636d9db 7.3.064
+a20ea56117d918b43f5109c9c06787ed 7.3.065
+7c51cfbd55673906035df7b274b247c4 7.3.066
+45625adbc8757b46ba9393dc136cc2e1 7.3.067
+49b340dc261ed455c97d955517264a89 7.3.068
+b423664733d7fd9d7de052dad8154643 7.3.069
+b9ef636a41df5500f8437d38ab3177e2 7.3.070
+1afcb15f38d1e4926918dbbe52356382 7.3.071
+132f122c3b8ac49c1ad56f54c8994e3a 7.3.072
+4a387415ce192506bcb7353cd8dda3c0 7.3.073
+e2b2af94486554c6818693fbf1e3c34e 7.3.074
+91acb2d1e70f6b7bff5e02460d4c3e62 7.3.075
+2627b860bed5c08cead6e48986577fed 7.3.076
+2a8c6197b193a16cb273606d8afcb6b5 7.3.077
+660b3e99b1433a4e992e087e66bc1567 7.3.078
+f69b91c3c55ef81df257178e0af1ca73 7.3.079
+bbe3b3aa56bde525cd4028e807014b33 7.3.080
+d4ce2f5eab7a74f8a51a352b05fde53f 7.3.081
+75b69fb091a12c588992dd282841bde0 7.3.082
+d6bc3caf366cc6735e35bb624701c52b 7.3.083
+c1056e5eac01e94b841ee0f6698bd996 7.3.084
+008cab55300e4aca60b10c5da48fa64b 7.3.085
+d3ce3330380068fc0bb71e1e46715cf8 7.3.086
+76ad849ed21f0f7ea55b5e45bf0ebb8e 7.3.087
+5fe24e8201c4a6bfb04cc1eba830c7d1 7.3.088
+e11e017a6ec88695ed4e68823c8519c8 7.3.089
+85b27ad24ccf7a0a35659104ad5d50a0 7.3.090
+30c533bfa3ce25d6d4ae69537ac6dc5c 7.3.091
+9583f16a6bc74a69848278648692dd0b 7.3.092
+dc1df531af4c8b457291ec3fe55df57d 7.3.093
+4f2fa0bc9ddb599ad5f202474d1baaa9 7.3.094
+527d8531d7d347784506508114eb436c 7.3.095
+07cc669cf0c531c4b9f6410350baad64 7.3.096
+ef918a856c94f9e1ac3732e967e99421 7.3.097
+f5d870f443d75a9849477e937774681b 7.3.098
+60fde4bc61ce362397d430b79856355b 7.3.099
+eb3795dd02ef74e825f0a41b3ae4d6d5 7.3.100
+44b023e4248395d2ccaaac9fda15407b 7.3.101
+f1a8bcdb44fee91a060b5ef4ea8721dc 7.3.102
+fca2fd799b4b76010b2df17e6b0e0c14 7.3.103
+bf17912c76b1bc930af41836899483ae 7.3.104
+2624889029aa8d780eea22c249d53691 7.3.105
+8c94d914a359a1aa81b41efd00f58486 7.3.106
+f91ca9cbbc54d8b9fca3c1884ddcce7a 7.3.107
+5963094fc8a07e5730f7557a9d8d1cf4 7.3.108
+bd660ce14300a3110ea7638c1e11eabd 7.3.109
+ee0dc9b0b38308aa235f0b2b3e5dcea5 7.3.110
+c91b1fb95f25fa9e0915b9e8cf613a49 7.3.111
+67f989ce99ce53c7ab6df5478ca3a90c 7.3.112
+4da7b00c8009a2ebcef6b9dac625bd5f 7.3.113
+5b4db3de0ecef5ca677cba0aedcdff89 7.3.114
+3aa1850a33864d0476104c12be96047d 7.3.115
+31c69a15462f16a6f7601a50a3eaf89b 7.3.116
+9c4c855111dc6acda7c05488da75c7b4 7.3.117
+0ef3f26f6ebd0ae418dae472eb6afcc1 7.3.118
+0010f602a56167a874739c1101da5255 7.3.119
+6cd06c54fe40ab1082fafa461174ab23 7.3.120
+7d4f0af28d817baea5e6c43bde1e1df2 7.3.121
+363a24bec321be90193b60b10e29587b 7.3.122
+7f31de4c9fffd8e504685eef84666dae 7.3.123
+642c96e6a15b67f38022131b5e46132a 7.3.124
+5fc1a25eaae81f91557672a2426b74e1 7.3.125
+6ff55983c952781418172f93374db783 7.3.126
+84ef6940f97c7c946d136dad4ac81d3b 7.3.127
+d56e9032d55d99d19ddb9dfd8f52ccf2 7.3.128
+4a7699f7db4032b1d67e52b3d384b647 7.3.129
+f1a33fe74ead0aaf7a440a7432480d6f 7.3.130
+bbf7bb68b777b831029082e0e865dc2d 7.3.131
+3f761bf7b71b038dc2f775781e6847e5 7.3.132
+7cc3bce20547604b0521be8383c9a6d0 7.3.133
+a34e3da262050d97cb9db46acdd4490b 7.3.134
+b75499f0b035962d7f19de1e2b866f35 7.3.135
+a3631062779f49ed4ab4bc7f87fd307c 7.3.136
+53a736c4dbf298fa465f01d06c15de0b 7.3.137
+a51e6c61c24303a90941571b6bd7753b 7.3.138
+8da651b02794bc7a34286e455e916a2f 7.3.139
+6312930f6a176305bd4f9838700605e6 7.3.140
+2c9665b8da67d1712db9d300b87fc07c 7.3.141
+613a153f1b0901b76f0026a51f19530e 7.3.142
+c3132b4cddda5fa3c11c048c5297e872 7.3.143
+cc8986b4f694b76cb348375c158034d6 7.3.144
+c919c2ea5b3e5b397a53eb8fcc4accde 7.3.145
+d3790014ac6c74d4691e64a839ac0d3a 7.3.146
+5816612acbb7e9862e71defb7e596243 7.3.147
+7610c456812aa93bacaedb8fb90a638b 7.3.148
+7f689222db2fbbc2a1c616b4e2eb6f50 7.3.149
+4ccdacef73da3c14360832393fd18956 7.3.150
+0322e8b82527503b08911c3436f4e5b7 7.3.151
+60e6111797abb558f9869b72892de126 7.3.152
+e791726fd04b11b9293f472fe9e3cb51 7.3.153
+1def37c933f7b1a0aaeb6bb8545e91de 7.3.154
+b1c84972297e04dead1c06c7976ebd69 7.3.155
+05a5584d72fa02708e12de57c1dd230d 7.3.156
+bcbe4f926d7c4ce7c33f2ee163f8e481 7.3.157
+5457a5d2d8e192662dafb4441d728b1a 7.3.158
+8a1b1e2b134e1ffe8058a1007b3f0244 7.3.159
+f8ad1c839a70db0fd67d9a91f2c5adfe 7.3.160
+b8e6b94818cdd5d824bb5bdd71845dcf 7.3.161
+640e4dab93c97e3fc591fa139f3626a0 7.3.162
+b718f9c84f0ef31746837aeb76584b9d 7.3.163
+3658977a1d6601e084001f4ca14990c2 7.3.164
+2a351662b4eb7546a13a697ce6c99e2c 7.3.165
+49be67f5a924f41efd02092d5a363ea2 7.3.166
+763d467cb7f52e65fa04abd47391c46f 7.3.167
+b03500932a593d8f8b503b7f4e597d27 7.3.168
+2bdead87e63f14c1ad94baa4ab83ea31 7.3.169
+55be8ac756a32da430a27684f9b8e1a8 7.3.170
+36cc61d0b91ef0c3a580e244e4062b1c 7.3.171
+38e90f8e7c56ea752ddeef1310854679 7.3.172
+9265e7ca265d58278475cdb4c981b8dd 7.3.173
+3e594ed292b1f2f19a5c9f4906c1479a 7.3.174
+acb7321db8f740b6671765185603a718 7.3.175
+6712e5eebfc7132b4d23044854c29cde 7.3.176
+687088eda45ccf1fdd83e0ce18cdbeb9 7.3.177
+44e37b259178bbea8de1aad8744b639c 7.3.178
+ef97eecd1643ae1375c2141b42ff2a8f 7.3.179
+85efa44de886e0e84914b13f7e356cd3 7.3.180
+a41871ead65ba67d0e91f46e4ed31d74 7.3.181
+a496deb8e705a15931566cc54de95b0e 7.3.182
+a5a93687afc2acb93caed156c5990507 7.3.183
+79db5edf359097848c50baa8e9f1de66 7.3.184
+5a466b6c01d84c6f3b58b409ec77147f 7.3.185
+2073073b84c308648bcc222a6e0e396b 7.3.186
+0aebb3a0fcf78937c8f4930de20fdb09 7.3.187
+665e541c24f5571bb07354a4a6441a28 7.3.188
+540131415452ba4cfa01332ab60571e4 7.3.189
+55d0ac5b715fabce51a05bf8380f6c01 7.3.190
+895a121a97504929ebd5a7a8eb67a2a3 7.3.191
+3b957b9de63a93a30e4c1ee7e9def7c9 7.3.192
+b37da657ae0b51f8181eb8a31d6cc4e8 7.3.193
+c911d5f14e34c8d0c1d3abea73bc830d 7.3.194
+dc09888cdc86f980789cd22889df0bcd 7.3.195
+fb396c9c2e57daf55fdba63635208985 7.3.196
+448eca99d96f5f5c4ddbe05e66ebf812 7.3.197
+d977fa831208ee16503b87a3a29673fe 7.3.198
+39028c76f0b15f9d014b050fb222d24a 7.3.199
+2dd2f0cd5b9af8f127fa02b3d838dd2f 7.3.200
+c1cd1bdaa61c6ab76a39dc59926781ef 7.3.201
+7bbc900208a99ba80a3e662827dba251 7.3.202
+ce69cdd4cff0f9a1ae208bb6a3c490d2 7.3.203
+07443373d2221a375988d58e25935599 7.3.204
+857f19149697b27088447bbac1dac8a2 7.3.205
+f6c7f47221c0459c7742a82163b875ec 7.3.206"
diff --git a/main/vim/vimrc b/main/vim/vimrc
new file mode 100644
index 0000000000..e301734245
--- /dev/null
+++ b/main/vim/vimrc
@@ -0,0 +1,15 @@
+set nocompatible " Use Vim defaults (much better!)
+set bs=2 " Allow backspacing over everything in insert mode
+set ai " Always set auto-indenting on
+set history=50 " keep 50 lines of command history
+set ruler " Show the cursor position all the time
+
+" Don't use Ex mode, use Q for formatting
+map Q gq
+
+" When doing tab completion, give the following files lower priority.
+set suffixes+=.info,.aux,.log,.dvi,.bbl,.out,.o,.lo
+
+set nomodeline
+syntax on
+autocmd BufRead APKBUILD set filetype=sh
diff --git a/main/virtinst/APKBUILD b/main/virtinst/APKBUILD
new file mode 100644
index 0000000000..a3e81a0a2d
--- /dev/null
+++ b/main/virtinst/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor:
+# Maintainer: Leonardo Arena <rnalrd@gmail.com>
+pkgname=virtinst
+pkgver=0.500.6
+pkgrel=1
+pkgdesc="CLI tool for provision operating systems into virtual machines"
+arch="noarch"
+url="http://virt-manager.et.redhat.com"
+license="GPL"
+depends="libvirt python"
+makedepends="gettext-dev libvirt-dev python-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://virt-manager.et.redhat.com/download/sources/$pkgname/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ return 0
+}
+
+build() {
+ cd "$_builddir"
+ python ./setup.py build
+}
+
+package() {
+ cd "$_builddir"
+ python ./setup.py install --root=$pkgdir
+}
+
+md5sums="5cad9ee9b8f64d700b3d1bbe644a58d3 virtinst-0.500.6.tar.gz"
diff --git a/main/vlc/APKBUILD b/main/vlc/APKBUILD
new file mode 100644
index 0000000000..fb8c9f1d84
--- /dev/null
+++ b/main/vlc/APKBUILD
@@ -0,0 +1,190 @@
+# Contributor: Leonardo Arena <rnalrd@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=vlc
+pkgver=1.1.10
+pkgrel=2
+pkgdesc="A multi-platform MPEG, VCD/DVD, and DivX player"
+url="http://www.videolan.org/vlc/"
+arch="all"
+license="GPL-2"
+triggers="$pkgname.trigger:/usr/lib/vlc/plugins"
+subpackages="$pkgname-dev $pkgname-doc $pkgname-xorg $pkgname-daemon"
+#depends="libnotify a52dec fluidsynth zvbi libdvbpsi lirc-utils libdca hal
+# libproxy sdl_image libdvdnav>=4.1.3 lua libxv libv4l libcddb smbclient
+# libmatroska taglib sysfsutils libmpcdec ffmpeg>=0.5 libshout libmad
+# qt fribidi libmpeg2 libmodplug avahi ttf-dejavu"
+depends="ttf-dejavu"
+makedepends="
+ a52dec-dev
+ alsa-lib-dev
+ automake
+ autoconf
+ libtool
+ dbus-dev
+ faad2-dev
+ ffmpeg-dev
+ flac-dev
+ fribidi-dev
+ gtk+-dev
+ libdc1394-dev
+ libdvbpsi-dev
+ libgcrypt-dev
+ libice-dev
+ libiconv-dev
+ libmad-dev
+ libmpeg2-dev
+ libnotify-dev
+ libogg-dev
+ libraw1394-dev
+ libshout-dev
+ libsm-dev
+ libtheora-dev
+ libvorbis-dev
+ libx11-dev
+ libxext-dev
+ libxv-dev
+ live-media-dev
+ lua-dev
+ ncurses-dev
+ mesa-dev
+ pkgconfig
+ sdl-dev
+ speex-dev
+ sysfsutils-dev
+ taglib-dev
+ v4l-utils-dev
+ x264-dev
+ xcb-util-renderutil-dev
+ xcb-util-keysyms-dev
+ "
+source="http://download.videolan.org/pub/videolan/$pkgname/$pkgver/$pkgname-$pkgver.tar.bz2
+ uclibc3.patch
+ uclibc-libcompat.patch
+ uclibc-inhibit-spawn.patch
+ vlc.trigger
+ vlc-1.1.7-disable-cache-gen.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac;
+ done
+ sed -i -e "/^SOURCES_xscreensaver/s/^/#/" modules/misc/Modules.am
+ ./bootstrap
+}
+
+build ()
+{
+ cd "$_builddir"
+ sed -i -e 's:/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf:/usr/share/fonts/TTF/DejaVuSerif-Bold.ttf:' modules/misc/freetype.c
+
+ export CFLAGS="$CFLAGS -D_GNU_SOURCE"
+
+ ./configure --prefix=/usr \
+ --disable-mmx \
+ --disable-nls \
+ --disable-optimizations \
+ --disable-qt4 --disable-skins2 \
+ --disable-rpath \
+ --enable-a52 \
+ --enable-avcodec \
+ --enable-avformat \
+ --enable-dbus \
+ --enable-dbus-control \
+ --enable-dc1394 \
+ --enable-dvbpsi \
+ --enable-faad \
+ --enable-flac \
+ --enable-httpd \
+ --enable-live555 \
+ --enable-merge-ffmpeg \
+ --enable-ncurses \
+ --enable-realrtsp \
+ --enable-sdl \
+ --enable-shout \
+ --enable-speex \
+ --enable-sout \
+ --enable-taglib \
+ --enable-theora \
+ --enable-v4l \
+ --enable-v4l2 \
+ --enable-vlm \
+ --enable-vorbis \
+ --enable-wma-fixed \
+ --enable-xvideo \
+ || return 1
+
+# --enable-dvdread \
+# --enable-dvdnav \
+# --enable-qt4 \
+# --enable-skins2 \
+# --enable-dvb \
+# --enable-snapshot \
+# --enable-hal \
+# --enable-lirc \
+# --enable-pvr \
+
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+# for res in 16 32 48 128; do
+# install -D -m644 share/vlc${res}x${res}.png \
+# "$pkgdir"/usr/share/icons/hicolor/${res}x${res}/apps/vlc.png || return 1
+# done
+ rm -rf "$pkgdir"/usr/lib/mozilla
+ find "$pkgdir" -name '*.la' -delete
+}
+
+_mv() {
+ local dir=${1%/*}
+ mkdir -p "$subpkgdir"/$dir
+ mv "$1" "$subpkgdir"/$dir/
+}
+
+xorg() {
+ pkgdesc="Video LAN X.org support"
+ triggers=
+ # scan for elf files that directly or indirectly depends on
+ # libX* libraries
+ cd "$pkgdir"
+ for i in $(find -type f ); do
+ if ldd $i 2>/dev/null | grep -q libX; then
+ echo $i | grep libavcodec_plugin.so || _mv "$i" || return 1
+ fi
+ done
+
+ mkdir -p "$subpkgdir"/usr/share/
+ mv "$pkgdir"/usr/share/applications \
+ "$pkgdir"/usr/share/icons \
+ "$subpkgdir"/usr/share/
+}
+
+daemon() {
+ pkgdesc="Support for running VLC as a daemon"
+ install="vlc-daemon.post-install"
+ triggers=
+ arch="noarch"
+ depends="vlc"
+
+ mkdir -p "$subpkgdir"
+ cd "$pkgdir"
+ install -D -m755 ../../vlc.initd $subpkgdir/etc/init.d/vlc
+ install -D -m664 ../../vlc.confd $subpkgdir/etc/conf.d/vlc
+}
+
+md5sums="066cb94b1e3aa848d828121354d6be4d vlc-1.1.10.tar.bz2
+ba24152286d98f8a367c7fd0cb8949f4 uclibc3.patch
+d718e22a7de9f38579f276f720b2f36a uclibc-libcompat.patch
+43bea31edd02de2b53075e5e883706db uclibc-inhibit-spawn.patch
+ddbd40bd72fedc1449be45588aea5d66 vlc.trigger
+e1ef2dec8e25f7ea6ba40e646c63e061 vlc-1.1.7-disable-cache-gen.patch"
diff --git a/main/vlc/uclibc-inhibit-spawn.patch b/main/vlc/uclibc-inhibit-spawn.patch
new file mode 100644
index 0000000000..1fe27fbab2
--- /dev/null
+++ b/main/vlc/uclibc-inhibit-spawn.patch
@@ -0,0 +1,32 @@
+--- a/modules/misc/inhibit/xdg.c.orig
++++ b/modules/misc/inhibit/xdg.c
+@@ -26,7 +26,12 @@
+ #include <vlc_plugin.h>
+ #include <vlc_inhibit.h>
+ #include <assert.h>
+-#include <spawn.h>
++#if !defined(_POSIX_SPAWN)
++# define _POSIX_SPAWN -1
++#else
++# include <spawn.h>
++#endif
++
+ #include <sys/wait.h>
+
+ static int Open (vlc_object_t *);
+@@ -137,7 +142,15 @@
+ pid_t pid;
+
+ vlc_mutex_unlock (&p_sys->lock);
++#if (_POSIX_SPAWN >= 0)
+ if (!posix_spawnp (&pid, "xdg-screensaver", NULL, NULL, argv, environ))
++#else
++ pid = fork();
++ if (pid == 0) {
++ execvp("xdg-screensaver", argv);
++ exit(1);
++ } else if (pid > 0)
++#endif
+ {
+ int status;
+
diff --git a/main/vlc/uclibc-libcompat.patch b/main/vlc/uclibc-libcompat.patch
new file mode 100644
index 0000000000..e4008002f4
--- /dev/null
+++ b/main/vlc/uclibc-libcompat.patch
@@ -0,0 +1,81 @@
+commit c605c09bbc29d88619264c55c371c9dcbc839eda
+Author: Natanael Copa <ncopa@alpinelinux.org>
+Date: Thu Jul 29 19:20:17 2010 +0000
+
+ build: libcompat fix in case there are no functions to replace
+
+ If the libc provides all the funcs in libcompat the libcompat.a will
+ never be created due to LIBOBJS is empty (normally it contains whatever
+ AC_REPLACE_FUNCS detects). This happens on uclibc.
+
+ Since Makefile.am have a hardcoded LDADD to ../compat/libcompat.la things
+ goes bad when there is no libcompat.a at all. We solve this by checking
+ if LIBOBJS is set by AC_REPLACE_FUNCS and add libcompat via LTLIBCOMPAT.
+
+ For alternative fixes see http://www.gnu.org/software/hello/manual/automake/LIBOBJS.html
+
+diff --git a/bin/Makefile.am b/bin/Makefile.am
+index 92e6879..a941d99 100644
+--- a/bin/Makefile.am
++++ b/bin/Makefile.am
+@@ -60,5 +60,5 @@ vlc_win32_rc.$(OBJEXT): vlc_win32_rc.rc
+ vlc_cache_gen_SOURCES = cachegen.c
+ vlc_cache_gen_LDADD = \
+ $(GNUGETOPT_LIBS) \
+- ../compat/libcompat.la \
++ $(LTLIBCOMPAT) \
+ ../src/libvlc.la ../src/libvlccore.la
+diff --git a/configure.ac b/configure.ac
+index 52e4830..b385100 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -547,6 +547,14 @@ need_libc=false
+ dnl Check for usual libc functions
+ AC_CHECK_FUNCS([ctime_r daemon fcntl fdopendir fstatvfs fork getenv getpwuid_r gettimeofday isatty lstat memalign openat posix_fadvise posix_madvise posix_memalign setenv setlocale stricmp strnicmp tdestroy uselocale])
+ AC_REPLACE_FUNCS([asprintf atof atoll getcwd getdelim getpid gmtime_r lldiv localtime_r nrand48 rewind strcasecmp strcasestr strdup strlcpy strncasecmp strndup strnlen strsep strtof strtok_r strtoll swab vasprintf])
++
++dnl Check that we actually need libcompat
++LTLIBCOMPAT=""
++if test "x${LIBOBJS}" != "x"; then
++ LTLIBCOMPAT="\$(top_builddir)/compat/libcompat.la"
++fi
++AC_SUBST(LTLIBCOMPAT)
++
+ AC_CHECK_FUNCS(fdatasync,,
+ [AC_DEFINE(fdatasync, fsync, [Alias fdatasync() to fsync() if missing.])
+ ])
+diff --git a/modules/common.am b/modules/common.am
+index 5e4d65f..9e2c739 100644
+--- a/modules/common.am
++++ b/modules/common.am
+@@ -24,7 +24,7 @@ AM_LDFLAGS = -rpath '$(libvlcdir)' \
+ -no-undefined \
+ `$(VLC_CONFIG) --ldflags plugin $@`
+ AM_LIBADD = `$(VLC_CONFIG) -libs plugin $@` \
+- $(LTLIBVLCCORE) $(top_builddir)/compat/libcompat.la
++ $(LTLIBVLCCORE) $(LTLIBCOMPAT)
+
+ include $(srcdir)/Modules.am
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index f46a154..6aad884 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -201,7 +201,7 @@ libvlccore_la_LDFLAGS = `$(VLC_CONFIG) --ldflags libvlccore` $(AM_LDFLAGS) \
+ -export-symbols $(srcdir)/libvlccore.sym \
+ -version-info 5:0:0
+ libvlccore_la_LIBADD = `$(VLC_CONFIG) -libs libvlccore` $(AM_LIBADD) \
+- $(LTLIBINTL) ../compat/libcompat.la
++ $(LTLIBINTL) $(LTLIBCOMPAT)
+ libvlccore_la_DEPENDENCIES = libvlccore.sym
+ if HAVE_WIN32
+ libvlccore_la_DEPENDENCIES += libvlc_win32_rc.$(OBJEXT)
+@@ -214,7 +214,7 @@ libvlc_win32_rc.$(OBJEXT): libvlc_win32_rc.rc
+ libvlc_la_SOURCES = $(SOURCES_libvlc_control)
+ nodist_libvlc_la_SOURCES = revision.c
+ libvlc_la_LIBADD = `$(VLC_CONFIG) -libs libvlc` \
+- libvlccore.la ../compat/libcompat.la
++ libvlccore.la $(LTLIBCOMPAT)
+ libvlc_la_CFLAGS = `$(VLC_CONFIG) --cflags libvlc`
+ libvlc_la_LDFLAGS = $(AM_LDFLAGS) `$(VLC_CONFIG) --ldflags libvlc` \
+ -version-info 6:0:1 \
diff --git a/main/vlc/uclibc3.patch b/main/vlc/uclibc3.patch
new file mode 100644
index 0000000000..bacad290a4
--- /dev/null
+++ b/main/vlc/uclibc3.patch
@@ -0,0 +1,36 @@
+diff --git a/src/control/vlm.c b/src/control/vlm.c
+index 05417e5..46fa957 100644
+--- a/src/control/vlm.c
++++ b/src/control/vlm.c
+@@ -25,6 +25,10 @@
+ # include <config.h>
+ #endif
+
++#ifdef HAVE_CONFIG_H
++# include "config.h"
++#endif
++
+ #include <vlc/libvlc.h>
+ #include <vlc/libvlc_vlm.h>
+ #include <vlc_es.h>
+diff --git a/src/misc/linux_specific.c b/src/misc/linux_specific.c
+index 1644ce6..1440e1c 100644
+--- a/src/misc/linux_specific.c
++++ b/src/misc/linux_specific.c
+@@ -83,14 +83,14 @@ static struct
+ unsigned refs;
+ } once = { VLC_STATIC_MUTEX, 0 };
+
+-#ifdef __GLIBC__
++#if defined(__GLIBC__) && !defined(__UCLIBC__)
+ # include <gnu/libc-version.h>
+ # include <stdlib.h>
+ #endif
+
+ void system_Init (libvlc_int_t *libvlc, int *argc, const char *argv[])
+ {
+-#ifdef __GLIBC__
++#if defined(__GLIBC__) && !defined(__UCLIBC__)
+ const char *glcv = gnu_get_libc_version ();
+
+ /* gettext in glibc 2.5-2.7 is not thread-safe. LibVLC keeps crashing,
diff --git a/main/vlc/vlc-1.1.7-disable-cache-gen.patch b/main/vlc/vlc-1.1.7-disable-cache-gen.patch
new file mode 100644
index 0000000000..b8a3dd9551
--- /dev/null
+++ b/main/vlc/vlc-1.1.7-disable-cache-gen.patch
@@ -0,0 +1,12 @@
+--- a/modules/Makefile.am
++++ b/modules/Makefile.am
+@@ -63,7 +63,8 @@
+
+ stamp-cache:
+ $(AM_V_GEN)if test "$(build)" = "$(host)"; then \
+- ../bin/vlc-cache-gen$(EXEEXT) . ; \
++ # ../bin/vlc-cache-gen$(EXEEXT) . ; \
++ echo "FIXME: vlc-cache-gen" ; \
+ else \
+ echo "Cross-compilation: cache generation skipped!" ; \
+ fi
diff --git a/main/vlc/vlc-daemon.post-install b/main/vlc/vlc-daemon.post-install
new file mode 100644
index 0000000000..e97c972c9e
--- /dev/null
+++ b/main/vlc/vlc-daemon.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+adduser -h /home/vlc -s /bin/sh -G audio -G video -D vlc &>/dev/null || true
+touch /var/log/vlc.log && chown vlc /var/log/vlc.log
diff --git a/main/vlc/vlc.confd b/main/vlc/vlc.confd
new file mode 100644
index 0000000000..3dc57ad8c4
--- /dev/null
+++ b/main/vlc/vlc.confd
@@ -0,0 +1,11 @@
+# Sample vlc params suitable for running as a daemon
+
+## --daemon detach from prompt
+## --file-logging enable file logging
+## --logfile logfile name/path
+## -vvv verbose logging
+## -I dummy disable X11 interface
+## --sout PARAMS encoding parameters
+## Do NOT quote 'PARAMS' otherwise shell expansions will broke vlc
+
+VLC_OPTS="-vvv -I dummy alsa://hw:0,0 --daemon --file-logging --logfile /var/log/vlc.log --sout #transcode{acodec=mp3,ab=48,channels=1,samplerate=22050}:std{access=http,mux=ogg,dst=:8080}"
diff --git a/main/vlc/vlc.initd b/main/vlc/vlc.initd
new file mode 100755
index 0000000000..2c431c90f0
--- /dev/null
+++ b/main/vlc/vlc.initd
@@ -0,0 +1,20 @@
+#!/sbin/runscript
+
+depend() {
+ need net
+}
+
+start() {
+ ebegin "Starting VLC"
+ start-stop-daemon --start --oknodo \
+ --pidfile /var/run/vlc.pid --chuid vlc \
+ --exec /usr/bin/vlc -- ${VLC_OPTS}
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping VLC"
+ start-stop-daemon --stop --oknodo --exec /usr/bin/vlc
+ eend $?
+}
+
diff --git a/main/vlc/vlc.trigger b/main/vlc/vlc.trigger
new file mode 100644
index 0000000000..def39b951a
--- /dev/null
+++ b/main/vlc/vlc.trigger
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+exec /usr/lib/vlc/vlc-cache-gen
+
diff --git a/main/vsftpd/APKBUILD b/main/vsftpd/APKBUILD
new file mode 100644
index 0000000000..212cbb2f85
--- /dev/null
+++ b/main/vsftpd/APKBUILD
@@ -0,0 +1,49 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=vsftpd
+pkgver=2.3.4
+pkgrel=0
+pkgdesc="Very secure ftpd"
+url="http://vsftpd.beasts.org"
+arch="all"
+license="GPL"
+depends=
+makedepends="openssl-dev libcap-dev"
+subpackages="$pkgname-doc"
+source="ftp://vsftpd.beasts.org/users/cevans/vsftpd-${pkgver}.tar.gz
+ vsftpd-enable-ssl.patch
+ vsftpd.initd
+ vsftpd.confd"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+
+prepare() {
+ cd $_builddir
+ #Enable SSL support
+ patch -p0 -i "$srcdir"/vsftpd-enable-ssl.patch || return 1
+ # we dont have libnsl
+ sed -i -e '/-lnsl/d' vsf_findlibs.sh || return 1
+ # Let abuild control stripping
+ sed -i '/^LINK[[:space:]]*=[[:space:]]*/ s/-Wl,-s//' Makefile
+}
+
+build() {
+ cd $_builddir
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ install -m755 -D vsftpd "$pkgdir"/usr/sbin/vsftpd
+ install -m644 -D vsftpd.8 "$pkgdir"/usr/share/man/man8/vsftpd.8
+ install -m644 -D vsftpd.conf.5 "$pkgdir"/usr/share/man/man5/vsftpd.conf.5
+ install -m644 -D vsftpd.conf "$pkgdir"/etc/vsftpd.conf
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
+ mkdir -p "$pkgdir"/usr/share/empty
+}
+
+md5sums="2ea5d19978710527bb7444d93b67767a vsftpd-2.3.4.tar.gz
+f3cbaf364cd3c46a2a03b00de9d7e184 vsftpd-enable-ssl.patch
+1a56bcc7698dba6490f0007f37c75e9b vsftpd.initd
+431dfe7403323e247a88b97beade5d78 vsftpd.confd"
diff --git a/main/vsftpd/vsftpd-enable-ssl.patch b/main/vsftpd/vsftpd-enable-ssl.patch
new file mode 100644
index 0000000000..22161907cd
--- /dev/null
+++ b/main/vsftpd/vsftpd-enable-ssl.patch
@@ -0,0 +1,11 @@
+--- builddefs.h.orig Sun Mar 1 15:18:09 2009
++++ builddefs.h Sun Mar 1 15:15:24 2009
+@@ -3,7 +3,7 @@
+
+ #undef VSF_BUILD_TCPWRAPPERS
+ #define VSF_BUILD_PAM
+-#undef VSF_BUILD_SSL
++#define VSF_BUILD_SSL
+
+ #endif /* VSF_BUILDDEFS_H */
+
diff --git a/main/vsftpd/vsftpd.confd b/main/vsftpd/vsftpd.confd
new file mode 100644
index 0000000000..0abb80c6e8
--- /dev/null
+++ b/main/vsftpd/vsftpd.confd
@@ -0,0 +1,9 @@
+# Sample conf.d file for alpine linux
+
+#
+# Specify daemon $OPTS here.
+#
+
+OPTS=""
+USER="nobody"
+GROUP="nobody"
diff --git a/main/vsftpd/vsftpd.initd b/main/vsftpd/vsftpd.initd
new file mode 100644
index 0000000000..52b6238779
--- /dev/null
+++ b/main/vsftpd/vsftpd.initd
@@ -0,0 +1,26 @@
+#!/sbin/runscript
+
+NAME=vsftpd
+DAEMON=/usr/sbin/$NAME
+
+depend() {
+ need net
+ after firewall
+}
+
+start() {
+ ebegin "Starting ${NAME}"
+ start-stop-daemon --start --quiet --background \
+ --make-pidfile --pidfile /var/run/${NAME}.pid \
+ --exec ${DAEMON} -- ${OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping ${NAME}"
+ start-stop-daemon --stop --quiet \
+ --exec ${DAEMON} \
+ --pidfile /var/run/${NAME}.pid \
+ eend $?
+}
+
diff --git a/main/vte/APKBUILD b/main/vte/APKBUILD
new file mode 100644
index 0000000000..389e7343db
--- /dev/null
+++ b/main/vte/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=vte
+pkgver=0.28.1
+pkgrel=0
+pkgdesc="Virtual Terminal Emulator library"
+url="http://www.gnome.org"
+arch="all"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig gtk+-dev intltool python ncurses-dev"
+source="http://ftp.gnome.org/pub/GNOME/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev pango-dev gtk+-dev"
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch)
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/vte \
+ --localstatedir=/var \
+ --disable-static \
+ || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ ln -sf /usr/share/vte/termcap-0.0 "$pkgdir"/usr/share/vte/termcap
+ find "$pkgdir" -name '*.la' -delete
+}
+md5sums="771ff368d4e5ac8e91be4f525b676292 vte-0.28.1.tar.bz2"
diff --git a/main/wavpack/APKBUILD b/main/wavpack/APKBUILD
new file mode 100644
index 0000000000..f9c850cdbc
--- /dev/null
+++ b/main/wavpack/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: Carlo Landmeter
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=wavpack
+pkgver=4.60.1
+pkgrel=2
+pkgdesc="Audio compression format with lossless, lossy, and hybrid compression modes"
+url="http://www.wavpack.com/"
+arch="all"
+license="custom"
+depends=
+makedepends=
+if [ "$ALPINE_LIBC" != eglibc ]; then
+ makedepends="$makdepends libiconv-dev"
+fi
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.wavpack.com/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-mmx \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ install -m755 -d ${pkgdir}/usr/share/licenses/${pkgname} || return 1
+ install -m644 license.txt ${pkgdir}/usr/share/licenses/${pkgname}/ || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="7bb1528f910e4d0003426c02db856063 wavpack-4.60.1.tar.bz2"
diff --git a/main/webkit/APKBUILD b/main/webkit/APKBUILD
new file mode 100644
index 0000000000..5d8a4f7752
--- /dev/null
+++ b/main/webkit/APKBUILD
@@ -0,0 +1,64 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=webkit
+pkgver=1.4.1
+pkgrel=2
+pkgdesc="portable web rendering engine WebKit for GTK+"
+url="http://webkitgtk.org/"
+arch="all"
+license="LGPL BSD"
+depends=
+makedepends="
+ libsoup-dev pango-dev gtk+-dev jpeg-dev libpng-dev libxml2-dev
+ gperf pkgconfig bison flex icu-dev cairo-dev atk-dev
+ gnutls-dev sqlite-dev libxslt-dev libxt-dev libiconv-dev gettext-dev
+ zlib-dev libgcrypt-dev libgpg-error-dev expat-dev e2fsprogs-dev
+ enchant-dev libxi-dev libxrandr-dev libxcursor-dev libxdamage-dev
+ libxcomposite-dev gstreamer-dev gst-plugins-base-dev
+ gobject-introspection-dev perl-switch
+ "
+install=
+subpackages="$pkgname-dev gtklauncher"
+source="http://webkitgtk.org/$pkgname-$pkgver.tar.gz
+ libpng-1.5.patch"
+
+depends_dev="gtk+-dev libsoup-dev gstreamer-dev"
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case "$i" in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/lib/*.la
+}
+
+gtklauncher() {
+ pkgdesc="Application to test WebKit"
+ depends=""
+ install=
+ install -Dm755 "$srcdir"/$pkgname-$pkgver/Programs/GtkLauncher \
+ "$subpkgdir"/usr/bin/GtkLauncher
+}
+
+md5sums="c1a4f732a77d6f8197437b50678d3dbc webkit-1.4.1.tar.gz
+e86d4770a37448eb508520b3ae766695 libpng-1.5.patch"
diff --git a/main/webkit/libpng-1.5.patch b/main/webkit/libpng-1.5.patch
new file mode 100644
index 0000000000..ecf533d6f1
--- /dev/null
+++ b/main/webkit/libpng-1.5.patch
@@ -0,0 +1,48 @@
+--- webkit-1.4.0.orig/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
++++ webkit-1.4.0/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+@@ -226,7 +226,7 @@
+ #ifdef PNG_iCCP_SUPPORTED
+ char* profileName;
+ int compressionType;
+- char* profile;
++ png_byte* profile;
+ png_uint_32 profileLength;
+ if (png_get_iCCP(png, info, &profileName, &compressionType, &profile, &profileLength)) {
+ ColorProfile colorProfile;
+@@ -241,11 +241,11 @@
+ {
+ png_structp png = m_reader->pngPtr();
+ png_infop info = m_reader->infoPtr();
+- png_uint_32 width = png->width;
+- png_uint_32 height = png->height;
++ png_uint_32 width = png_get_image_width(png, info);
++ png_uint_32 height = png_get_image_height(png, info);
+
+ // Protect against large images.
+- if (png->width > cMaxPNGSize || png->height > cMaxPNGSize) {
++ if (width > cMaxPNGSize || height > cMaxPNGSize) {
+ longjmp(JMPBUF(png), 1);
+ return;
+ }
+@@ -318,9 +318,9 @@
+ m_reader->setHasAlpha(channels == 4);
+
+ if (m_reader->decodingSizeOnly()) {
+- // If we only needed the size, halt the reader.
+- m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size);
+- png->buffer_size = 0;
++ // If we only needed the size, halt the reader.
++ // '0' argument to png_process_data_pause means: Do not cache unprocessed data.
++ m_reader->setReadOffset(m_reader->currentBufferSize() - png_process_data_pause(png, 0));
+ }
+ }
+
+@@ -343,7 +343,7 @@
+ // For PNGs, the frame always fills the entire image.
+ buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
+
+- if (m_reader->pngPtr()->interlaced)
++ if (png_get_interlace_type(m_reader->pngPtr(), m_reader->infoPtr()) != PNG_INTERLACE_NONE)
+ m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height());
+ }
+
diff --git a/main/wget/APKBUILD b/main/wget/APKBUILD
new file mode 100644
index 0000000000..4175d626a8
--- /dev/null
+++ b/main/wget/APKBUILD
@@ -0,0 +1,28 @@
+# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=wget
+pkgver=1.12
+pkgrel=4
+pkgdesc="A network utility to retrieve files from the Web"
+url="http://www.gnu.org/software/wget/wget.html"
+arch="all"
+license="GPL3"
+depends=
+makedepends="openssl-dev"
+subpackages="$pkgname-doc"
+install="wget.post-deinstall"
+source="ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --disable-nls
+ make || return 1
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="141461b9c04e454dc8933c9d1f2abf83 wget-1.12.tar.gz"
diff --git a/main/wget/wget.post-deinstall b/main/wget/wget.post-deinstall
new file mode 100644
index 0000000000..99b57c4635
--- /dev/null
+++ b/main/wget/wget.post-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+busybox --install -s
diff --git a/main/wine/APKBUILD b/main/wine/APKBUILD
new file mode 100644
index 0000000000..2e7e3304ec
--- /dev/null
+++ b/main/wine/APKBUILD
@@ -0,0 +1,52 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=wine
+pkgver=1.3.22
+pkgrel=0
+pkgdesc="A compatibility layer for running Windows programs"
+url="http://www.winehq.com"
+arch="x86"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="fontconfig-dev openldap-dev libxslt-dev libxxf86dga-dev
+ libxcursor-dev libxrandr-dev libxdamage-dev mesa-dev flex bison
+ libpng-dev jpeg-dev freetype-dev ncurses-dev openssl-dev
+ libxcomposite-dev libxrender-dev libxinerama-dev zlib-dev
+ fontconfig-dev cups-dev alsa-lib-dev lcms-dev libxml2-dev
+ gstreamer-dev gst-plugins-base-dev paxctl"
+source="http://ibiblio.org/pub/linux/system/emulators/$pkgname/$pkgname-$pkgver.tar.bz2
+ dn_skipname.patch
+ uclibc-fmaxf-fminf.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ sed -i '/^UPDATE_DESKTOP_DATABASE/s:=.*:=true:' tools/Makefile.in \
+ || return 1
+ sed -i '/^MimeType/d' tools/wine.desktop || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/wine \
+ --with-x
+ make depend && make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make prefix="$pkgdir"/usr install || return 1
+ mkdir -p "$pkgdir"/etc/wine
+ paxctl -c -psmre "$pkgdir"/usr/bin/wine-preloader \
+ "$pkgdir"/usr/bin/wine
+}
+
+md5sums="46f313013644d31ad37b8fc5c2c16467 wine-1.3.22.tar.bz2
+6ebeaa64eddf97be3267db236ce84b71 dn_skipname.patch
+1127b41caf4de8f567b9a3d0aff5277f uclibc-fmaxf-fminf.patch"
diff --git a/main/wine/dn_skipname.patch b/main/wine/dn_skipname.patch
new file mode 100644
index 0000000000..99ecf83158
--- /dev/null
+++ b/main/wine/dn_skipname.patch
@@ -0,0 +1,38 @@
+--- ./dlls/dnsapi/ns_parse.c.orig
++++ ./dlls/dnsapi/ns_parse.c
+@@ -69,6 +69,35 @@
+ } while (0)
+
+ /* Public. */
++#ifdef __UCLIBC__
++int
++dn_skipname(const u_char *comp_dn, const u_char *eom)
++{
++ const u_char *cp;
++ int n;
++
++ cp = comp_dn;
++ while (cp < eom && (n = *cp++)) {
++ /*
++ * check for indirection
++ */
++ switch (n & INDIR_MASK) {
++ case 0: /* normal case, n == len */
++ cp += n;
++ continue;
++ case INDIR_MASK: /* indirection */
++ cp++;
++ break;
++ default: /* illegal type */
++ return (-1);
++ }
++ break;
++ }
++ if (cp > eom)
++ return (-1);
++ return (cp - comp_dn);
++}
++#endif
+
+ static int
+ dns_ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
diff --git a/main/wine/uclibc-fmaxf-fminf.patch b/main/wine/uclibc-fmaxf-fminf.patch
new file mode 100644
index 0000000000..1f26cb8b96
--- /dev/null
+++ b/main/wine/uclibc-fmaxf-fminf.patch
@@ -0,0 +1,21 @@
+--- ./dlls/d3dx9_36/mesh.c.orig
++++ ./dlls/d3dx9_36/mesh.c
+@@ -40,6 +40,18 @@
+ #include "wine/list.h"
+ #include "d3dx9_36_private.h"
+
++#ifdef __UCLIBC__
++float fmaxf(float a, float b)
++{
++ return (a > b) ? a : b;
++}
++
++float fminf(float a, float b)
++{
++ return (a < b) ? a : b;
++}
++#endif
++
+ WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+
+ typedef struct ID3DXMeshImpl
diff --git a/main/wireless-tools/APKBUILD b/main/wireless-tools/APKBUILD
new file mode 100644
index 0000000000..288c8386bc
--- /dev/null
+++ b/main/wireless-tools/APKBUILD
@@ -0,0 +1,33 @@
+# Contributor: Michael Mason <ms13sp@gmail.com>
+# Maintainer:
+pkgname=wireless-tools
+pkgver=29
+pkgrel=4
+pkgdesc="Open Source wireless tools"
+url="http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html"
+arch="all"
+license="GPL"
+depends=
+makedepends=""
+install=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/wireless_tools.$pkgver.tar.gz
+ wireless-tools-29-asneeded.patch
+ "
+
+build() {
+ cd "$srcdir/wireless_tools.$pkgver"
+ patch -p1 -i ../wireless-tools-29-asneeded.patch || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/wireless_tools.$pkgver"
+ make INSTALL_DIR="$pkgdir"/usr/sbin \
+ INSTALL_LIB="$pkgdir"/usr/lib \
+ INSTALL_INC="$pkgdir"/usr/include \
+ INSTALL_MAN="$pkgdir"/usr/share/man install || return 1
+}
+
+md5sums="e06c222e186f7cc013fd272d023710cb wireless_tools.29.tar.gz
+9d979950e6965b31d3d136f570273d23 wireless-tools-29-asneeded.patch"
diff --git a/main/wireless-tools/wireless-tools-29-asneeded.patch b/main/wireless-tools/wireless-tools-29-asneeded.patch
new file mode 100644
index 0000000000..04f2d869b6
--- /dev/null
+++ b/main/wireless-tools/wireless-tools-29-asneeded.patch
@@ -0,0 +1,13 @@
+Index: wireless_tools.29/Makefile
+===================================================================
+--- wireless_tools.29.orig/Makefile
++++ wireless_tools.29/Makefile
+@@ -145,7 +145,7 @@ wireless.h:
+
+ # Compilation of the dynamic library
+ $(DYNAMIC): $(OBJS:.o=.so)
+- $(CC) -shared -o $@ -Wl,-soname,$@ $(STRIPFLAGS) $(LIBS) -lc $^
++ $(CC) $(LDFLAGS) -shared -o $@ -Wl,-soname,$@ $(STRIPFLAGS) $^ $(LIBS) -lc
+
+ # Compilation of the static library
+ $(STATIC): $(OBJS:.o=.so)
diff --git a/main/wireshark/APKBUILD b/main/wireshark/APKBUILD
new file mode 100644
index 0000000000..9e9940e6f3
--- /dev/null
+++ b/main/wireshark/APKBUILD
@@ -0,0 +1,81 @@
+# Contributor: Jeremy Thomerson <jeremy@thomersonfamily.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=wireshark
+pkgver=1.6.0
+pkgrel=1
+pkgdesc="network protocol analyzer - GTK version"
+url="http://www.wireshark.org"
+arch="all"
+license="GPLv2"
+depends="bash"
+makedepends="bison flex perl glib glib-dev pkgconfig libpcap-dev libcap-dev
+ gtk+-dev c-ares-dev pcre-dev openssl-dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-common tshark"
+source="http://www.wireshark.org/download/src/${pkgname}-${pkgver}.tar.bz2
+ wireshark.desktop
+ wireshark.png"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in "$source"; do
+ case "$i" in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$i" || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-ssl \
+ --disable-text2pcap \
+ --disable-idl2wrs \
+ --disable-dftest \
+ --disable-randpkt
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install
+ install -Dm644 "$srcdir"/wireshark.png \
+ "$pkgdir"/usr/share/icons/wireshark.png
+ install -Dm644 "$srcdir"/wireshark.desktop \
+ "$pkgdir"/usr/share/applications/wireshark.desktop
+ find "$pkgdir" -name '*.la' -delete
+}
+
+common() {
+ local i
+ pkgdesc="network protoccol analyzer - common files"
+ mkdir -p "$subpkgdir"/usr/lib "$subpkgdir"/usr/share \
+ "$subpkgdir"/usr/bin
+ mv "$pkgdir"/etc "$subpkgdir"/
+ mv "$pkgdir"/usr/share/wireshark "$subpkgdir"/usr/share/
+ mv "$pkgdir"/usr/lib/* "$subpkgdir"/usr/lib/
+ # move all bins except wireshark
+ for i in "$pkgdir"/usr/bin/*; do
+ case "$i" in
+ */tshark|*/wireshark) continue;;
+ esac
+ mv "$i" "$subpkgdir"/usr/bin/
+ done
+}
+
+tshark() {
+ pkgdesc="network protoccol analyzer - console version"
+ install -d "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/tshark "$subpkgdir"/usr/bin/tshark
+}
+
+md5sums="9f9314c89bf1c8b440a7909884838cfd wireshark-1.6.0.tar.bz2
+504ede44c02b2a52f6cbd3bffdf93b8d wireshark.desktop
+e771800a8c977fe223583a453bc27397 wireshark.png"
diff --git a/main/wireshark/wireshark-1.1.2--as-needed.patch b/main/wireshark/wireshark-1.1.2--as-needed.patch
new file mode 100644
index 0000000000..7da659c099
--- /dev/null
+++ b/main/wireshark/wireshark-1.1.2--as-needed.patch
@@ -0,0 +1,20 @@
+diff --git a/epan/Makefile.am b/epan/Makefile.am
+index b2a569d..717e233 100644
+--- a/epan/Makefile.am
++++ b/epan/Makefile.am
+@@ -130,6 +130,7 @@ libwireshark_la_LIBADD = \
+ dissectors/libdirtydissectors.la $(wslua_lib) @SOCKET_LIBS@ @NSL_LIBS@ \
+ @C_ARES_LIBS@ @ADNS_LIBS@ @LIBGCRYPT_LIBS@ @LIBGNUTLS_LIBS@ \
+ @KRB5_LIBS@ @SSL_LIBS@ @LIBSMI_LDFLAGS@ @GEOIP_LIBS@ \
++ ${top_builddir}/wiretap/libwiretap.la \
+ ${top_builddir}/wsutil/libwsutil.la -lm
+
+ libwireshark_la_DEPENDENCIES = \
+@@ -137,6 +138,7 @@ libwireshark_la_DEPENDENCIES = \
+ libwireshark_asmopt.la crypt/libairpdcap.la ftypes/libftypes.la \
+ dfilter/libdfilter.la dissectors/libdissectors.la \
+ dissectors/libdirtydissectors.la $(wslua_lib) \
++ ${top_builddir}/wiretap/libwiretap.la \
+ ${top_builddir}/wsutil/libwsutil.la
+
+ #EXTRA_PROGRAMS = reassemble_test
diff --git a/main/wireshark/wireshark.desktop b/main/wireshark/wireshark.desktop
new file mode 100644
index 0000000000..f4317f6d04
--- /dev/null
+++ b/main/wireshark/wireshark.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Encoding=UTF-8
+GenericName=Wireshark
+Comment=Network protocol analyzer
+Name=wireshark
+Exec=wireshark
+Icon=/usr/share/icons/wireshark.png
+Type=Application
+Terminal=false
+Categories=Application;Network;
diff --git a/main/wireshark/wireshark.png b/main/wireshark/wireshark.png
new file mode 100644
index 0000000000..4e40263042
--- /dev/null
+++ b/main/wireshark/wireshark.png
Binary files differ
diff --git a/main/wpa_supplicant/APKBUILD b/main/wpa_supplicant/APKBUILD
new file mode 100644
index 0000000000..d05f4c5f83
--- /dev/null
+++ b/main/wpa_supplicant/APKBUILD
@@ -0,0 +1,127 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=wpa_supplicant
+pkgver=0.7.3
+pkgrel=1
+pkgdesc="A utility providing key negotiation for WPA wireless networks"
+url="http://hostap.epitest.fi/wpa_supplicant"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends=
+makedepends="openssl-dev dbus-dev libnl-dev"
+source="http://hostap.epitest.fi/releases/$pkgname-$pkgver.tar.gz
+ wpa_supplicant.initd
+ wpa_supplicant.confd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver/$pkgname
+prepare() {
+ cd "$_builddir"
+ # Toolchain setup
+ echo "CC = ${CC:-gcc}" > .config
+
+ # Basic setup
+ echo "CONFIG_CTRL_IFACE=y" >> .config
+ echo "CONFIG_BACKEND=file" >> .config
+
+ # Basic authentication methods
+ # NOTE: we don't set GPSK or SAKE as they conflict
+ # with the below options
+ echo "CONFIG_EAP_GTC=y" >> .config
+ echo "CONFIG_EAP_MD5=y" >> .config
+ echo "CONFIG_EAP_OTP=y" >> .config
+ echo "CONFIG_EAP_PAX=y" >> .config
+ echo "CONFIG_EAP_PSK=y" >> .config
+ echo "CONFIG_EAP_TLV=y" >> .config
+ echo "CONFIG_IEEE8021X_EAPOL=y" >> .config
+ echo "CONFIG_PKCS12=y" >> .config
+ echo "CONFIG_PEERKEY=y" >> .config
+ echo "CONFIG_EAP_LEAP=y" >> .config
+ echo "CONFIG_EAP_MSCHAPV2=y" >> .config
+ echo "CONFIG_EAP_PEAP=y" >> .config
+ echo "CONFIG_EAP_TLS=y" >> .config
+ echo "CONFIG_EAP_TTLS=y" >> .config
+
+ # dbus support
+ echo "CONFIG_CTRL_IFACE_DBUS=y" >> .config
+
+ # debug
+ # echo "CONFIG_DEBUG_FILE=y" >> .config
+
+ # Smart card authentication
+ #echo "CONFIG_EAP_SIM=y" >> .config
+ #echo "CONFIG_EAP_AKA=y" >> .config
+ #echo "CONFIG_EAP_AKA_PRIME=y" >> .config
+ #echo "CONFIG_PCSC=y" >> .config
+
+ # readline/history support for wpa_cli
+ #echo "CONFIG_READLINE=y" >> .config
+
+ # SSL authentication methods
+ echo "CONFIG_TLS=openssl" >> .config
+ echo "CONFIG_SMARTCARD=y" >> .config
+ # use gnutls
+ # echo "CONFIG_TLS=gnutls" >> .config
+ # echo "CONFIG_GNUTLS_EXTRA=y" >> .config
+ #echo "CONFIG_TLS=internal" >> .config
+
+ # Linux specific drivers
+ echo "CONFIG_DRIVER_ATMEL=y" >> .config
+ #echo "CONFIG_DRIVER_BROADCOM=y" >> .config
+ #echo "CONFIG_DRIVER_HERMES=y" >> .config
+ echo "CONFIG_DRIVER_HOSTAP=y" >> .config
+ echo "CONFIG_DRIVER_IPW=y" >> .config
+ echo "CONFIG_DRIVER_NDISWRAPPER=y" >> .config
+ echo "CONFIG_DRIVER_NL80211=y" >> .config
+ #echo "CONFIG_DRIVER_PRISM54=y" >> .config
+ echo "CONFIG_DRIVER_RALINK=y" >> .config
+ echo "CONFIG_DRIVER_WEXT=y" >> .config
+ echo "CONFIG_DRIVER_WIRED=y" >> .config
+
+ # Add include path for madwifi-driver headers
+ #echo "CFLAGS += -I/usr/include/madwifi" >> .config
+ #echo "CONFIG_DRIVER_MADWIFI=y" >> .config
+
+ # Wi-Fi Protected Setup (WPS)
+ echo "CONFIG_WPS=y" >> .config
+
+ # Enable mitigation against certain attacks against TKIP
+ echo "CONFIG_DELAYED_MIC_ERROR_REPORT=y" >> .config
+}
+
+build() {
+ cd "$_builddir"
+ make LIBDIR=/lib BINDIR=/sbin || return 1
+ # comment out the network={ } stansas in config
+ sed -i -e '/^network=/,/}/s/^/#/' wpa_supplicant.conf
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" LIBDIR=/lib BINDIR=/sbin install || return 1
+ install -Dm644 wpa_supplicant.conf \
+ "$pkgdir"/etc/wpa_supplicant/wpa_supplicant.conf
+ install -Dm644 doc/docbook/wpa_supplicant.conf.5 \
+ "$pkgdir"/usr/share/man/man5/wpa_supplicant.conf.5 || return 1
+ for i in wpa_background wpa_cli wpa_passphrase wpa_supplicant; do
+ install -Dm644 doc/docbook/$i.8 \
+ "$pkgdir"/usr/share/man/man8/$i.8 || return 1
+ done
+
+ # dbus
+ cd dbus || return 1
+ install -d "$pkgdir"/etc/dbus-1/system.d
+ install dbus-wpa_supplicant.conf \
+ "$pkgdir"/etc/dbus-1/system.d/wpa_supplicant.conf || return 1
+ install -d "$pkgdir"/usr/share/dbus-1/system-services
+ install fi.epitest.hostap.WPASupplicant.service \
+ "$pkgdir"/usr/share/dbus-1/system-services || return 1
+ install -d "$pkgdir"/var/run/wpa_supplicant
+ install -Dm755 "$srcdir"/wpa_supplicant.initd \
+ "$pkgdir"/etc/init.d/wpa_supplicant || return 1
+ install -Dm755 "$srcdir"/wpa_supplicant.confd \
+ "$pkgdir"/etc/conf.d/wpa_supplicant || return 1
+}
+md5sums="f516f191384a9a546e3f5145c08addda wpa_supplicant-0.7.3.tar.gz
+55f853354f51ba947e4dd6ee2bb0d64a wpa_supplicant.initd
+bc117427f2c538439f3f1481a028ee06 wpa_supplicant.confd"
diff --git a/main/wpa_supplicant/wpa_supplicant.confd b/main/wpa_supplicant/wpa_supplicant.confd
new file mode 100644
index 0000000000..104b9dc5d8
--- /dev/null
+++ b/main/wpa_supplicant/wpa_supplicant.confd
@@ -0,0 +1,6 @@
+# conf.d file for wpa_supplicant
+#
+# Please check man 8 wpa_supplicant for more information about the options
+# wpa_supplicant accepts.
+#
+wpa_supplicant_args=""
diff --git a/main/wpa_supplicant/wpa_supplicant.initd b/main/wpa_supplicant/wpa_supplicant.initd
new file mode 100644
index 0000000000..7a9949b8be
--- /dev/null
+++ b/main/wpa_supplicant/wpa_supplicant.initd
@@ -0,0 +1,70 @@
+#!/sbin/runscript
+# Copyright (c) 2009 Roy Marples <roy@marples.name>
+# All rights reserved. Released under the 2-clause BSD license.
+
+command=/sbin/wpa_supplicant
+: ${wpa_supplicant_conf:=/etc/wpa_supplicant/wpa_supplicant.conf}
+wpa_supplicant_if=${wpa_supplicant_if:+-i}$wpa_supplicant_if
+command_args="$wpa_supplicant_args -B -c$wpa_supplicant_conf $wpa_supplicant_if"
+name="WPA Supplicant Daemon"
+
+depend()
+{
+ need localmount
+ use logger
+ after bootmisc modules
+ before dns dhcpcd net
+ keyword -shutdown
+}
+
+find_wireless()
+{
+ local iface=
+
+ case "$RC_UNAME" in
+ Linux)
+ for iface in /sys/class/net/*; do
+ if [ -e "$iface"/wireless -o \
+ -e "$iface"/phy80211 ]
+ then
+ echo "${iface##*/}"
+ return 0
+ fi
+ done
+ ;;
+ *)
+ for iface in /dev/net/* $(ifconfig -l 2>/dev/null); do
+ if ifconfig "${iface##*/}" 2>/dev/null | \
+ grep -q "[ ]*ssid "
+ then
+ echo "${iface##*/}"
+ return 0
+ fi
+ done
+ ;;
+ esac
+
+ return 1
+}
+
+append_wireless()
+{
+ local iface= i=
+
+ iface=$(find_wireless)
+ if [ -n "$iface" ]; then
+ for i in $iface; do
+ command_args="$command_args -i$i"
+ done
+ else
+ eerror "Could not find a wireless interface"
+ fi
+}
+
+start_pre()
+{
+ case " $command_args" in
+ *" -i"*) ;;
+ *) append_wireless;;
+ esac
+}
diff --git a/main/wv/APKBUILD b/main/wv/APKBUILD
new file mode 100644
index 0000000000..266640d22d
--- /dev/null
+++ b/main/wv/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=wv
+pkgver=1.2.7
+pkgrel=4
+pkgdesc="MSWord library can load and parse Word 2000, 97, 95 and 6 file formats"
+url="http://sourceforge.net/projects/wvware"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libgsf-dev libpng-dev bzip2-dev coreutils"
+source="http://www.abisource.com/downloads/wv/$pkgver/wv-$pkgver.tar.gz
+ fix-soname.patch
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 -i "$srcdir"/fix-soname.patch
+}
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="a6a3484745aa73897ff9c5a871482b4b wv-1.2.7.tar.gz
+10a6988f743346c2429e189cef4363bd fix-soname.patch"
diff --git a/main/wv/fix-soname.patch b/main/wv/fix-soname.patch
new file mode 100644
index 0000000000..81dff86e62
--- /dev/null
+++ b/main/wv/fix-soname.patch
@@ -0,0 +1,14 @@
+diff -ru wv-1.2.7.orig//configure wv-1.2.7//configure
+--- wv-1.2.7.orig//configure 2009-09-21 12:22:46.000000000 +0200
++++ wv-1.2.7//configure 2010-06-08 12:00:27.948857203 +0200
+@@ -2082,8 +2082,8 @@
+ WV_MAJOR_VERSION=1
+ WV_MINOR_VERSION=2
+ WV_MICRO_VERSION=7
+-WV_INTERFACE_AGE=3
+-WV_BINARY_AGE=3
++WV_INTERFACE_AGE=4
++WV_BINARY_AGE=4
+ WV_VERSION=$WV_MAJOR_VERSION.$WV_MINOR_VERSION.$WV_MICRO_VERSION
+
+
diff --git a/main/x264/APKBUILD b/main/x264/APKBUILD
new file mode 100644
index 0000000000..b983286e02
--- /dev/null
+++ b/main/x264/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=x264
+pkgver=20110621
+pkgrel=0
+pkgdesc="free library for encoding H264/AVC video streams"
+url="http://www.videolan.org/developers/x264.html"
+arch="all"
+license="GPL"
+depends=
+makedepends="libx11-dev bash"
+subpackages="$pkgname-dev"
+source="ftp://ftp.videolan.org/pub/x264/snapshots/x264-snapshot-$pkgver-2245-stable.tar.bz2"
+_builddir="$srcdir/$pkgname-snapshot-$pkgver-2245-stable"
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --enable-visualize \
+ --enable-shared \
+ --disable-asm \
+ --enable-pic || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" bindir=/usr/bin libdir=/usr/lib includedir=/usr/include install || return 1
+}
+md5sums="cecaaab3265cbdc46cc89920742d7339 x264-snapshot-20110621-2245-stable.tar.bz2"
diff --git a/main/xarchiver/APKBUILD b/main/xarchiver/APKBUILD
new file mode 100644
index 0000000000..9a662291ac
--- /dev/null
+++ b/main/xarchiver/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xarchiver
+pkgver=0.5.2
+pkgrel=3
+pkgdesc="GTK+ frontend to various command line archivers"
+url="http://xarchiver.xfce.org/"
+arch="all"
+license="GPL"
+depends="desktop-file-utils hicolor-icon-theme tar"
+makedepends="intltool gtk+-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2
+ xarchiver-0.5.2-stack-smash.patch"
+
+prepare() {
+ cd "$srcdir/xarchiver-$pkgver"
+ patch -p1 -i "$srcdir"/xarchiver-0.5.2-stack-smash.patch
+}
+
+build() {
+ cd "$srcdir/xarchiver-$pkgver"
+ ./configure --prefix=/usr \
+ --libexecdir=/usr/lib/xfce4 || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/xarchiver-$pkgver"
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="2bc7f06403cc6582dd4a8029ec9d038d xarchiver-0.5.2.tar.bz2
+74cdf6a77e91ac7b02270002c582cea1 xarchiver-0.5.2-stack-smash.patch"
diff --git a/main/xarchiver/xarchiver-0.5.2-stack-smash.patch b/main/xarchiver/xarchiver-0.5.2-stack-smash.patch
new file mode 100644
index 0000000000..66104822ea
--- /dev/null
+++ b/main/xarchiver/xarchiver-0.5.2-stack-smash.patch
@@ -0,0 +1,20 @@
+--- xarchiver-0.5.2-old/src/window.c 2008-11-11 09:31:45.000000000 +0100
++++ xarchiver-0.5.2/src/window.c 2009-01-25 16:26:07.000000000 +0100
+@@ -1447,7 +1447,7 @@
+ GtkTreeIter iter;
+ gint n_elem = 0,pos = 0,dirs = 0;
+ unsigned long int total_size = 0;
+- unsigned long int size = 0;
++ guint64 size = 0;
+ XEntry *entry = NULL;
+
+ path = gtk_tree_path_new_first();
+@@ -1517,7 +1517,7 @@
+ GtkTreeModel *model;
+ gint selected = 0,pos = 0,dirs = 0;
+ unsigned long int total_size = 0;
+- unsigned long int size = 0;
++ guint64 size = 0;
+ XEntry *entry;
+
+ switch (archive->type)
diff --git a/main/xauth/APKBUILD b/main/xauth/APKBUILD
new file mode 100644
index 0000000000..f5d8099216
--- /dev/null
+++ b/main/xauth/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xauth
+pkgver=1.0.4
+pkgrel=2
+pkgdesc="X.Org authorization settings program"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig libxau-dev libxext-dev libxmu-dev libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/xauth-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/xauth-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/xauth-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="fa00078c414c4a57cab7a6d89a0c8734 xauth-1.0.4.tar.bz2"
diff --git a/main/xbacklight/APKBUILD b/main/xbacklight/APKBUILD
new file mode 100644
index 0000000000..657ce84e5b
--- /dev/null
+++ b/main/xbacklight/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xbacklight
+pkgver=1.1
+pkgrel=3
+pkgdesc="Sets backlight level using the RandR 1.2 BACKLIGHT output property"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libx11-dev libxrandr-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="51b4a1c0ae2b3bd77417306fd78a3e94 xbacklight-1.1.tar.bz2"
diff --git a/main/xbitmaps/APKBUILD b/main/xbitmaps/APKBUILD
new file mode 100644
index 0000000000..d1450fe308
--- /dev/null
+++ b/main/xbitmaps/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xbitmaps
+pkgver=1.1.1
+pkgrel=0
+pkgdesc="X.org header files with bitmaps"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends="util-macros"
+makedepends="pkgconfig"
+source="http://xorg.freedesktop.org/releases/individual/data/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="7444bbbd999b53bec6a60608a5301f4c xbitmaps-1.1.1.tar.bz2"
diff --git a/main/xcb-proto/APKBUILD b/main/xcb-proto/APKBUILD
new file mode 100644
index 0000000000..70c9697186
--- /dev/null
+++ b/main/xcb-proto/APKBUILD
@@ -0,0 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xcb-proto
+pkgver=1.6
+pkgrel=2
+pkgdesc="XML-XCB protocol descriptions"
+url="http://xcb.freedesktop.org/"
+arch="all"
+license="custom"
+depends=
+makedepends="python"
+source="http://xcb.freedesktop.org/dist/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/${pkgname}-${pkgver}
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/${pkgname}-${pkgver}
+ make DESTDIR=${pkgdir} install || return 1
+ install -m755 -d ${pkgdir}/usr/share/licenses/${pkgname}
+ install -m644 COPYING ${pkgdir}/usr/share/licenses/${pkgname}/ || return 1
+}
+md5sums="04313e1d914b44d0e457f6c494fc178b xcb-proto-1.6.tar.bz2"
diff --git a/main/xcb-util-image/APKBUILD b/main/xcb-util-image/APKBUILD
new file mode 100644
index 0000000000..096e0a7eb4
--- /dev/null
+++ b/main/xcb-util-image/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xcb-util-image
+pkgver=0.3.8
+pkgrel=1
+pkgdesc="Utility libraries for XC Binding - image"
+url="http://xcb.freedesktop.org/"
+arch="all"
+license="MIT"
+depends=
+depends_dev="xcb-util-dev"
+makedepends="$depends_dev m4"
+install=""
+replaces="xcb-util"
+subpackages="$pkgname-dev"
+source="http://xcb.freedesktop.org/dist/xcb-util-image-$pkgver.tar.gz"
+
+_builddir="$srcdir"/xcb-util-image-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="b6d1359b5851ea319a81e15c18f34aeb xcb-util-image-0.3.8.tar.gz"
diff --git a/main/xcb-util-keysyms/APKBUILD b/main/xcb-util-keysyms/APKBUILD
new file mode 100644
index 0000000000..412c0437f5
--- /dev/null
+++ b/main/xcb-util-keysyms/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xcb-util-keysyms
+pkgver=0.3.8
+pkgrel=1
+pkgdesc="Utility libraries for XC Binding - keysyms"
+url="http://xcb.freedesktop.org/"
+arch="all"
+license="MIT"
+depends=
+depends_dev="xcb-util-dev"
+makedepends="$depends_dev m4"
+install=""
+replaces="xcb-util"
+subpackages="$pkgname-dev"
+source="http://xcb.freedesktop.org/dist/xcb-util-keysyms-$pkgver.tar.gz"
+
+_builddir="$srcdir"/xcb-util-keysyms-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="3d6608213de3b7581cfe64d68035a83f xcb-util-keysyms-0.3.8.tar.gz"
diff --git a/main/xcb-util-renderutil/APKBUILD b/main/xcb-util-renderutil/APKBUILD
new file mode 100644
index 0000000000..2e95f1d5d3
--- /dev/null
+++ b/main/xcb-util-renderutil/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xcb-util-renderutil
+pkgver=0.3.8
+pkgrel=1
+pkgdesc="Utility libraries for XC Binding - renderutil"
+url="http://xcb.freedesktop.org/"
+arch="all"
+license="MIT"
+depends=
+depends_dev="xcb-util-dev"
+makedepends="$depends_dev m4"
+install=""
+replaces="xcb-util"
+subpackages="$pkgname-dev"
+source="http://xcb.freedesktop.org/dist/xcb-util-renderutil-$pkgver.tar.gz"
+
+_builddir="$srcdir"/xcb-util-renderutil-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="8097c46659bb2cf60c6a8c72604b8524 xcb-util-renderutil-0.3.8.tar.gz"
diff --git a/main/xcb-util-wm/APKBUILD b/main/xcb-util-wm/APKBUILD
new file mode 100644
index 0000000000..50212eb3f2
--- /dev/null
+++ b/main/xcb-util-wm/APKBUILD
@@ -0,0 +1,46 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xcb-util-wm
+pkgver=0.3.8
+pkgrel=1
+pkgdesc="Utility libraries for XC Binding - wm"
+url="http://xcb.freedesktop.org/"
+arch="all"
+license="MIT"
+depends=
+depends_dev="xcb-util-dev"
+makedepends="$depends_dev m4"
+install=""
+replaces="xcb-util"
+subpackages="$pkgname-dev"
+source="http://xcb.freedesktop.org/dist/xcb-util-wm-$pkgver.tar.gz"
+
+_builddir="$srcdir"/xcb-util-wm-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+md5sums="5a6c17935e44c52a00af7d4355a88650 xcb-util-wm-0.3.8.tar.gz"
diff --git a/main/xcb-util/APKBUILD b/main/xcb-util/APKBUILD
new file mode 100644
index 0000000000..cc2731bafb
--- /dev/null
+++ b/main/xcb-util/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xcb-util
+pkgver=0.3.8
+pkgrel=2
+pkgdesc="Utility libraries for XC Binding"
+url="http://xcb.freedesktop.org"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev"
+depends=
+depends_dev="libxcb-dev"
+makedepends="m4 $depends_dev gperf pkgconfig"
+source="http://xcb.freedesktop.org/dist/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la || return 1
+}
+md5sums="8ce019c4bbf20dce246b98f177cfccff xcb-util-0.3.8.tar.bz2"
diff --git a/main/xchat/APKBUILD b/main/xchat/APKBUILD
new file mode 100644
index 0000000000..2b82e4d86f
--- /dev/null
+++ b/main/xchat/APKBUILD
@@ -0,0 +1,47 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xchat
+pkgver=2.8.8
+pkgrel=3
+pkgdesc="A GTK+ based IRC client"
+url="http://www.xchat.org/"
+arch="all"
+license="GPL"
+makedepends="pkgconfig gtk+-dev openssl-dev dbus-glib-dev perl-dev
+ libxext-dev"
+source="http://www.$pkgname.org/files/source/2.8/$pkgname-$pkgver.tar.bz2
+ midori.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg "$i"; patch -p1 -i "$srcdir"/$i || return 1 ;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-openssl \
+ --enable-dbus \
+ --disable-gnome \
+ --disable-textfe \
+ --disable-perl \
+ --disable-python \
+ --enable-ipv6 \
+ --enable-shm \
+ --enable-spell=static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="6775c44f38e84d06c06c336b32c4a452 xchat-2.8.8.tar.bz2
+759fd786be3a2546be33f7533632b5a2 midori.patch"
diff --git a/main/xchat/midori.patch b/main/xchat/midori.patch
new file mode 100644
index 0000000000..a9b4a08a44
--- /dev/null
+++ b/main/xchat/midori.patch
@@ -0,0 +1,15 @@
+diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c
+index 251a7d7..f427ad4 100644
+--- a/src/fe-gtk/fe-gtk.c
++++ b/src/fe-gtk/fe-gtk.c
+@@ -958,6 +958,10 @@ fe_open_url_inner (const char *url)
+ /* everything failed, what now? just try firefox */
+ if (try_browser ("firefox", NULL, url))
+ return;
++
++ /* try midori before giving up */
++ if (try_browser ("midori", NULL, url))
++ return;
+
+ /* fresh out of ideas... */
+ try_browser ("mozilla", NULL, url);
diff --git a/main/xcmiscproto/APKBUILD b/main/xcmiscproto/APKBUILD
new file mode 100644
index 0000000000..5788eabef9
--- /dev/null
+++ b/main/xcmiscproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xcmiscproto
+pkgver=1.2.1
+pkgrel=0
+pkgdesc="X11 XC-Miscellaneous extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org//releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="cd7372cd827bfd7ca7e9238f2ce274b1 xcmiscproto-1.2.1.tar.bz2"
diff --git a/main/xcmsdb/APKBUILD b/main/xcmsdb/APKBUILD
new file mode 100644
index 0000000000..1a7b9a94c1
--- /dev/null
+++ b/main/xcmsdb/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xcmsdb
+pkgver=1.0.2
+pkgrel=2
+pkgdesc="Device Color Characterization utility for X Color Management System"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="7f2bed9f4dd3301d18d83eb296c3be0d xcmsdb-1.0.2.tar.bz2"
diff --git a/main/xdelta3/APKBUILD b/main/xdelta3/APKBUILD
new file mode 100644
index 0000000000..0b1b21e4ab
--- /dev/null
+++ b/main/xdelta3/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xdelta3
+pkgver=3.0.0
+pkgrel=0
+pkgdesc="A diff utility which works with binary files"
+url="http://xdelta.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+source="http://xdelta.googlecode.com/files/${pkgname%3}$pkgver.tar.gz
+ "
+
+prepare() {
+ cd $srcdir/xdelta$pkgver
+}
+
+build() {
+ cd $srcdir/xdelta$pkgver
+ make CFLAGS="$CFLAGS" xdelta3 || return 1
+}
+
+package() {
+ cd $srcdir/xdelta$pkgver
+ install -D xdelta3 "$pkgdir"/usr/bin/xdelta3
+}
+md5sums="5fe038be3a266d2a7913e10d1cec6d88 xdelta3.0.0.tar.gz"
diff --git a/main/xdelta3/xdelta3-makefile.patch b/main/xdelta3/xdelta3-makefile.patch
new file mode 100644
index 0000000000..f7fc6a657d
--- /dev/null
+++ b/main/xdelta3/xdelta3-makefile.patch
@@ -0,0 +1,33 @@
+diff -Naur xdelta3.0v-old/Makefile xdelta3.0v/Makefile
+--- xdelta3.0v-old/Makefile 2009-03-12 01:44:51.000000000 +0000
++++ xdelta3.0v/Makefile 2009-03-14 17:02:33.000000000 +0000
+@@ -4,7 +4,7 @@
+ UNAME = $(shell uname)
+ CYGWIN = $(findstring CYGWIN, $(UNAME))
+ DARWIN = $(findstring Darwin, $(UNAME))
+-PYVER = 2.5
++PYVER = 2.6
+
+ ifeq ("$(CYGWIN)", "")
+ SWIGTGT = xdelta3module.so
+@@ -200,6 +200,9 @@
+ xdelta3.o: $(SOURCES)
+ $(CC) -O3 $(CFLAGS) -c xdelta3.c $(SWIG_FLAGS) -o xdelta3.o
+
++xdelta3_PIC.o: $(SOURCES)
++ $(CC) -O3 $(CFLAGS) -fPIC -c xdelta3.c $(SWIG_FLAGS) -o xdelta3_PIC.o
++
+ xdelta3_wrap.o: xdelta3_wrap.c
+ $(CC) -O3 $(CFLAGS) $(SWIG_FLAGS) \
+ -DHAVE_CONFIG_H \
+@@ -218,8 +221,8 @@
+ cp $(SWIGTGT) /usr/lib/python$(PYVER)/site-packages
+
+ ifeq ("$(DARWIN)", "")
+-xdelta3module.so: xdelta3_wrap.o xdelta3.o
+- ld -shared xdelta3.o xdelta3_wrap.o \
++xdelta3module.so: xdelta3_wrap.o xdelta3_PIC.o
++ cc -shared xdelta3_PIC.o xdelta3_wrap.o \
+ -o xdelta3module.so \
+ /usr/lib/libpython$(PYVER).so \
+ -lc
diff --git a/main/xdg-utils/APKBUILD b/main/xdg-utils/APKBUILD
new file mode 100644
index 0000000000..40478cb464
--- /dev/null
+++ b/main/xdg-utils/APKBUILD
@@ -0,0 +1,43 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xdg-utils
+pkgver=1.0.2
+pkgrel=1
+pkgdesc="Basic desktop integration functions"
+url="http://portland.freedesktop.org/wiki/"
+arch="noarch"
+license="MIT"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc"
+source="http://portland.freedesktop.org/download/xdg-utils-$pkgver.tgz
+ xfce.patch"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg "$i"; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="348a5b91dc66426505022c74a64b2940 xdg-utils-1.0.2.tgz
+328567c08a452bdbbedd2f1cca9ac116 xfce.patch"
diff --git a/main/xdg-utils/xfce.patch b/main/xdg-utils/xfce.patch
new file mode 100644
index 0000000000..3899a99a50
--- /dev/null
+++ b/main/xdg-utils/xfce.patch
@@ -0,0 +1,13 @@
+diff --git a/scripts/xdg-open b/scripts/xdg-open
+index 4cc18a8..e7ed9c3 100755
+--- a/scripts/xdg-open
++++ b/scripts/xdg-open
+@@ -303,7 +303,7 @@ detectDE()
+ {
+ if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
+ elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
+- elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
++ elif [ -x /usr/bin/exo-open ]; then DE=xfce;
+ fi
+ }
+
diff --git a/main/xdpyinfo/APKBUILD b/main/xdpyinfo/APKBUILD
new file mode 100644
index 0000000000..aacbf836b1
--- /dev/null
+++ b/main/xdpyinfo/APKBUILD
@@ -0,0 +1,22 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xdpyinfo
+pkgver=1.0.3
+pkgrel=2
+pkgdesc="display information utility for X"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+makedepends="pkgconfig libxtst-dev"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="b7cbab6cbcd12bf7ad65dbc12d86e104 xdpyinfo-1.0.3.tar.bz2"
diff --git a/main/xdriinfo/APKBUILD b/main/xdriinfo/APKBUILD
new file mode 100644
index 0000000000..0d77f1d6c1
--- /dev/null
+++ b/main/xdriinfo/APKBUILD
@@ -0,0 +1,22 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xdriinfo
+pkgver=1.0.2
+pkgrel=2
+pkgdesc="query configuration information of DRI drivers"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+makedepends="pkgconfig libx11-dev glproto mesa-dev"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="a5ec51ed9f0a55dc3462d90d52ff899c xdriinfo-1.0.2.tar.bz2"
diff --git a/main/xe-guest-utilities/APKBUILD b/main/xe-guest-utilities/APKBUILD
new file mode 100644
index 0000000000..8583a254c1
--- /dev/null
+++ b/main/xe-guest-utilities/APKBUILD
@@ -0,0 +1,62 @@
+# Contributor: Cedric Schieli <cschieli@gmail.com>
+# Maintainer: Cedric Schieli <cschieli@gmail.com>
+pkgname=xe-guest-utilities
+_major=5.5.0
+_minor=458
+pkgver=${_major}.${_minor}
+pkgrel=1
+pkgdesc="XenServer guest tools"
+url="http://www.citrix.com"
+arch="all"
+license="GPL"
+depends=
+makedepends=
+install=
+subpackages=
+source="http://updates.vmd.citrix.com/XenServer/${_major}/debian/pool/main/x/${pkgname}/${pkgname}_${_major}-${_minor}.tar.gz
+ $pkgname.initd
+ no_bash_dependency.patch
+ identify_alpine.patch
+ fix_cflags.patch
+ no_hard_links.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$_major
+
+prepare() {
+ cd "$_builddir"
+
+ msg "Unpacking xenstore-sources..."
+ tar xjf xenstore-sources.tar.bz2
+
+ for i in ../*.diff ../*.patch; do
+ [ -f $i ] || continue
+ msg "Applying $i..."
+ patch -s -p1 -N < $i || return 1
+ done
+
+ ln -s ../../xen/include/public uclibc-sources/tools/xenstore/xen
+ sed -i -e 's/-Werror//' uclibc-sources/tools/xenstore/Makefile
+}
+
+build() {
+ cd "$_builddir"/uclibc-sources/tools/xenstore
+ make XENSTORE_STATIC_CLIENTS=y clients
+}
+
+package() {
+ cd "$_builddir"
+ install -m755 -D "$_builddir"/xe-linux-distribution "$pkgdir"/usr/sbin/xe-linux-distribution
+ install -m755 -D "$_builddir"/xe-update-guest-attrs "$pkgdir"/usr/sbin/xe-update-guest-attrs
+ install -m755 -D "$_builddir"/xe-daemon "$pkgdir"/usr/sbin/xe-daemon
+ install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+ cd uclibc-sources/tools/xenstore
+ make DESTDIR="$pkgdir" client-install
+}
+
+md5sums="b15546f0b3883472140f35f5f8802a92 xe-guest-utilities_5.5.0-458.tar.gz
+d2eefda7fb55926dddbf87f17989b16e xe-guest-utilities.initd
+1fe4c6c4621982a87de97d897612eef7 no_bash_dependency.patch
+aa129940379b312783dc314497f62042 identify_alpine.patch
+cf32b9c90ce2e846d2221eaca0638929 fix_cflags.patch
+96e872ed89792f9d1b5cb51f8fdfd5f6 no_hard_links.patch"
diff --git a/main/xe-guest-utilities/fix_cflags.patch b/main/xe-guest-utilities/fix_cflags.patch
new file mode 100644
index 0000000000..866fa29fd3
--- /dev/null
+++ b/main/xe-guest-utilities/fix_cflags.patch
@@ -0,0 +1,43 @@
+--- xe-guest-utilities-5.5.0.orig/uclibc-sources/Config.mk
++++ xe-guest-utilities-5.5.0/uclibc-sources/Config.mk
+@@ -70,7 +70,6 @@
+ export XEN_ROOT
+ endef
+
+-CFLAGS += -g
+
+ CFLAGS += -fno-strict-aliasing
+
+--- xe-guest-utilities-5.5.0.orig/uclibc-sources/config/StdGNU.mk
++++ xe-guest-utilities-5.5.0/uclibc-sources/config/StdGNU.mk
+@@ -44,7 +44,6 @@
+ SHLIB_CFLAGS = -shared
+
+ ifneq ($(debug),y)
+-CFLAGS += -O2 -fomit-frame-pointer
+ else
+ # Less than -O1 produces bad code and large stack frames
+ CFLAGS += -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls
+--- xe-guest-utilities-5.5.0.orig/uclibc-sources/config/x86_32.mk
++++ xe-guest-utilities-5.5.0/uclibc-sources/config/x86_32.mk
+@@ -7,7 +7,6 @@
+ CONFIG_XCUTILS := y
+ CONFIG_IOEMU := n
+
+-CFLAGS += -m32 -march=i686
+
+ # Use only if calling $(LD) directly.
+ LDFLAGS_DIRECT_OpenBSD = _obsd
+--- xe-guest-utilities-5.5.0.orig/uclibc-sources/tools/Rules.mk
++++ xe-guest-utilities-5.5.0/uclibc-sources/tools/Rules.mk
+@@ -27,9 +27,7 @@
+ CFLAGS += -D__XEN_TOOLS__
+
+ # Enable implicit LFS support *and* explicit LFS names.
+-CFLAGS += $(shell getconf LFS_CFLAGS)
+-CFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+-LDFLAGS += $(shell getconf LFS_LDFLAGS)
++CFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+
+ # 32-bit x86 does not perform well with -ve segment accesses on Xen.
+ CFLAGS-$(CONFIG_X86_32) += $(call cc-option,$(CC),-mno-tls-direct-seg-refs)
diff --git a/main/xe-guest-utilities/identify_alpine.patch b/main/xe-guest-utilities/identify_alpine.patch
new file mode 100644
index 0000000000..d645c139ab
--- /dev/null
+++ b/main/xe-guest-utilities/identify_alpine.patch
@@ -0,0 +1,43 @@
+--- xe-guest-utilities-5.5.0.orig/xe-linux-distribution
++++ xe-guest-utilities-5.5.0/xe-linux-distribution
+@@ -248,6 +248,32 @@
+ write_to_output "${distro}" "${major}" "${minor}" "${description}"
+ }
+
++identify_alpine()
++{
++ alpine_release="$1"
++ local major
++ local minor
++
++ if [ ! -f "${alpine_release}" ] ; then
++ return 1
++ fi
++
++ eval $(sed -n \
++ -e 's/^.*-\([0-9]*\)\.\([0-9]*\)\.[0-9]* .*$/major=\1;minor=\2/gp;' \
++ -e 's/^.*-\([0-9]*\) .*$/major=\1;minor=/gp;' \
++ "${alpine_release}")
++
++ if [ -z "${major}" ] ; then
++ return 1
++ fi
++
++ if [ -z "${minor}" ] ; then
++ minor=0
++ fi
++
++ write_to_output "alpine" "${major}" "${minor}" "Alpinelinux $(head -n 1 $alpine_release)"
++}
++
+ if [ $# -eq 1 ] ; then
+ exec 1>"$1"
+ fi
+@@ -257,6 +283,7 @@
+ identify_sles /etc/SuSE-release && exit 0
+ identify_lsb lsb_release && exit 0
+ identify_debian /etc/debian_version && exit 0
++ identify_alpine /etc/alpine-release && exit 0
+
+ if [ $# -eq 1 ] ; then
+ rm -f "$1"
diff --git a/main/xe-guest-utilities/no_bash_dependency.patch b/main/xe-guest-utilities/no_bash_dependency.patch
new file mode 100644
index 0000000000..27d9af285b
--- /dev/null
+++ b/main/xe-guest-utilities/no_bash_dependency.patch
@@ -0,0 +1,8 @@
+--- xe-guest-utilities-5.5.0.orig/xe-daemon
++++ xe-guest-utilities-5.5.0/xe-daemon
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+
+ # Copyright (C) 2009 Citrix Systems Inc.
+ #
diff --git a/main/xe-guest-utilities/no_hard_links.patch b/main/xe-guest-utilities/no_hard_links.patch
new file mode 100644
index 0000000000..c10918f391
--- /dev/null
+++ b/main/xe-guest-utilities/no_hard_links.patch
@@ -0,0 +1,11 @@
+--- xe-guest-utilities-5.5.0.orig/uclibc-sources/tools/xenstore/Makefile
++++ xe-guest-utilities-5.5.0/uclibc-sources/tools/xenstore/Makefile
+@@ -97,7 +97,7 @@
+ $(INSTALL_DIR) $(DESTDIR)/usr/bin
+ $(INSTALL_PROG) xenstore $(DESTDIR)/usr/bin
+ set -e ; for c in $(CLIENTS) ; do \
+- ln -f $(DESTDIR)/usr/bin/xenstore $(DESTDIR)/usr/bin/$${c} ; \
++ ln -sf $(DESTDIR)/usr/bin/xenstore $(DESTDIR)/usr/bin/$${c} ; \
+ done
+
+ .PHONY: install
diff --git a/main/xe-guest-utilities/xe-guest-utilities.initd b/main/xe-guest-utilities/xe-guest-utilities.initd
new file mode 100644
index 0000000000..2d9c880da7
--- /dev/null
+++ b/main/xe-guest-utilities/xe-guest-utilities.initd
@@ -0,0 +1,50 @@
+#!/sbin/runscript
+
+XE_LINUX_DISTRIBUTION=/usr/sbin/xe-linux-distribution
+XE_LINUX_DISTRIBUTION_CACHE=/var/cache/xe-linux-distribution
+XE_DAEMON=/usr/sbin/xe-daemon
+XE_DAEMON_PIDFILE=/var/run/xe-daemon.pid
+
+name=xe-daemon
+daemon=/usr/sbin/$name
+
+depend() {
+ need localmount
+ after bootmisc
+}
+
+start() {
+ if [ ! -d /proc/xen ]; then
+ return
+ fi
+
+ ebegin "Detecting Linux distribution version"
+ ${XE_LINUX_DISTRIBUTION} ${XE_LINUX_DISTRIBUTION_CACHE}
+ eend $?
+
+ if [ ! -e /proc/xen/xenbus ] ; then
+ ebegin "Mounting xenfs on /proc/xen"
+ if [ ! -d /proc/xen ] ; then
+ /bin/false
+ else
+ mount -t xenfs none /proc/xen
+ fi
+ eend $?
+ fi
+
+ ebegin "Starting ${name}"
+ mkdir -p $(dirname ${XE_DAEMON_PIDFILE})
+ ( exec &>/dev/null ; ${XE_DAEMON} -p ${XE_DAEMON_PIDFILE} & )
+ eend $?
+}
+
+stop() {
+ if [ ! -d /proc/xen ]; then
+ return
+ fi
+
+ ebegin "Stopping ${name}"
+ kill -TERM $(cat ${XE_DAEMON_PIDFILE})
+ eend $?
+}
+
diff --git a/main/xen/APKBUILD b/main/xen/APKBUILD
new file mode 100644
index 0000000000..4df5c517e2
--- /dev/null
+++ b/main/xen/APKBUILD
@@ -0,0 +1,92 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=xen
+pkgver=4.1.0
+pkgrel=1
+pkgdesc="Xen hypervisor"
+url="http://www.xen.org/"
+license="GPL"
+depends="coreutils python sed gawk"
+makedepends="libgcrypt-dev gnutls-dev pciutils-dev texinfo wget mesa-dev sdl-dev zlib-dev openssl-dev util-linux-ng-dev python-dev gettext-dev ncurses-dev perl"
+install=
+subpackages="$pkgname-doc"
+source="http://bits.xensource.com/oss-xen/release/$pkgver/$pkgname-$pkgver.tar.gz
+ xen-blktap-uclibc.patch
+ xen-blktap2-uclibc.patch
+ xen-disable-firmware.patch
+ xen-dont-use-lib64.patch
+ xen-sed-is-broken-hack.patch
+ blktap-write.patch
+ xend.initd
+ xendomains.initd"
+arch="x86_64"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+
+ msg "Patching sources..."
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i..."
+ patch -s -p1 -N -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+ msg "Sources have been patched successfully."
+
+ # remove all -Werror
+ msg "Eradicating -Werror..."
+ find -name '*.mk' -o -name 'Make*' | xargs sed -i -e 's/-Werror//g'
+}
+
+build() {
+ cd "$_builddir"
+
+ # We unset $CFLAGS and $LDFLAGS because Xen's buildsystem does not
+ # like these values being set. Arguably this is a bug but I can't be
+ # bothered to track it down. --nenolod
+ unset CFLAGS
+ unset LDFLAGS
+
+ # If we provide no parameters it tries to build a kernel image. We
+ # definitely don't want that.
+ msg "Running preflight check..."
+ (cd tools/check; ./chk build) || return 1
+
+ msg "Building hypervisor..."
+ make -j1 xen || return 1
+
+ msg "Building tools..."
+ make -j1 tools || return 1
+
+ msg "Building stub domains..."
+ make -j1 stubdom || return 1
+}
+
+package() {
+ cd "$_builddir"
+
+ # We unset $CFLAGS and $LDFLAGS because Xen's buildsystem does not
+ # like these values being set. Arguably this is a bug but I can't be
+ # bothered to track it down. --nenolod
+ unset CFLAGS
+ unset LDFLAGS
+
+ make DESTDIR="$pkgdir" install-xen install-tools install-stubdom
+
+ install -m755 -D "$srcdir"/xend.initd "$pkgdir"/etc/init.d/xend
+ install -m755 -D "$srcdir"/xendomains.initd "$pkgdir"/etc/init.d/xendomains
+}
+
+md5sums="db3e1542b7719f375593b2b32b01a177 xen-4.1.0.tar.gz
+edb5c3e7fba8214702fac709f0e53124 xen-blktap-uclibc.patch
+1f7f847ae0baa915c7b52d0ed5869fe6 xen-blktap2-uclibc.patch
+a569f16a7e3c832ba3fab6154f657244 xen-disable-firmware.patch
+20ce621f3a2fc8ae78e74b9b72da775c xen-dont-use-lib64.patch
+0cec6a97de9e4bc178f3e71190495cc3 xen-sed-is-broken-hack.patch
+56af00443c8d40944082e26304452a5e blktap-write.patch
+1d81b04f8c8b919879a73f0e3d2fe80f xend.initd
+a2b5234483f1b5892d22e9315d9c307f xendomains.initd"
diff --git a/main/xen/blktap-write.patch b/main/xen/blktap-write.patch
new file mode 100644
index 0000000000..4b589daec2
--- /dev/null
+++ b/main/xen/blktap-write.patch
@@ -0,0 +1,24 @@
+--- ./tools/blktap2/include/blktaplib.h.orig
++++ ./tools/blktap2/include/blktaplib.h
+@@ -198,7 +198,9 @@
+ } msg_lock_t;
+
+ #define READ 0
++#ifndef WRITE
+ #define WRITE 1
++#endif
+
+ /*Control Messages between manager and tapdev*/
+ #define CTLMSG_PARAMS 1
+--- ./tools/blktap/lib/blktaplib.h.orig
++++ ./tools/blktap/lib/blktaplib.h
+@@ -196,7 +196,9 @@
+ } msg_pid_t;
+
+ #define READ 0
++#ifndef WRITE
+ #define WRITE 1
++#endif
+
+ /*Control Messages between manager and tapdev*/
+ #define CTLMSG_PARAMS 1
diff --git a/main/xen/xen-blktap-uclibc.patch b/main/xen/xen-blktap-uclibc.patch
new file mode 100644
index 0000000000..d8668ec19b
--- /dev/null
+++ b/main/xen/xen-blktap-uclibc.patch
@@ -0,0 +1,11 @@
+--- xen-4.0.1/tools/blktap/drivers/bswap.h
++++ xen-4.0.1.mod/tools/blktap/drivers/bswap.h
+@@ -15,6 +15,8 @@
+ #define bswap_64(x) swap64(x)
+ #else
+
++#define HAVE_BYTESWAP_H
++
+ #ifdef HAVE_BYTESWAP_H
+ #include <byteswap.h>
+ #else
diff --git a/main/xen/xen-blktap2-uclibc.patch b/main/xen/xen-blktap2-uclibc.patch
new file mode 100644
index 0000000000..7ce1dc0cfd
--- /dev/null
+++ b/main/xen/xen-blktap2-uclibc.patch
@@ -0,0 +1,22 @@
+--- xen-4.0.1/tools/blktap2/drivers/bswap.h
++++ xen-4.0.1.mod/tools/blktap2/drivers/bswap.h
+@@ -15,6 +15,8 @@
+ #define bswap_64(x) swap64(x)
+ #else
+
++#define HAVE_BYTESWAP_H
++
+ #ifdef HAVE_BYTESWAP_H
+ #include <byteswap.h>
+ #else
+--- xen-4.0.1/tools/blktap2/vhd/lib/Makefile
++++ xen-4.0.1.mod/tools/blktap2/vhd/lib/Makefile
+@@ -23,6 +23,8 @@
+ LIBS := -luuid
+ endif
+
++LIBS += -liconv
++
+ # Get gcc to generate the dependencies for us.
+ CFLAGS += -Wp,-MD,.$(@F).d
+ DEPS = .*.d
diff --git a/main/xen/xen-disable-firmware.patch b/main/xen/xen-disable-firmware.patch
new file mode 100644
index 0000000000..06e43d41c4
--- /dev/null
+++ b/main/xen/xen-disable-firmware.patch
@@ -0,0 +1,10 @@
+--- xen-4.0.1/tools/Makefile
++++ xen-4.0.1.mod/tools/Makefile
+@@ -13,7 +13,6 @@
+ SUBDIRS-y += hotplug
+ SUBDIRS-y += xentrace
+ SUBDIRS-$(CONFIG_XCUTILS) += xcutils
+-SUBDIRS-$(CONFIG_X86) += firmware
+ SUBDIRS-$(ACM_SECURITY) += security
+ SUBDIRS-y += console
+ SUBDIRS-y += xenmon
diff --git a/main/xen/xen-dont-use-lib64.patch b/main/xen/xen-dont-use-lib64.patch
new file mode 100644
index 0000000000..b14ff10164
--- /dev/null
+++ b/main/xen/xen-dont-use-lib64.patch
@@ -0,0 +1,11 @@
+--- xen-4.0.1/config/StdGNU.mk
++++ xen-4.0.1.mod/config/StdGNU.mk
+@@ -28,7 +28,7 @@
+ INCLUDEDIR = $(PREFIX)/include
+ LIBLEAFDIR = lib
+ LIBLEAFDIR_x86_32 = lib
+-LIBLEAFDIR_x86_64 ?= lib64
++LIBLEAFDIR_x86_64 ?= lib
+ LIBDIR = $(PREFIX)/$(LIBLEAFDIR)
+ LIBDIR_x86_32 = $(PREFIX)/$(LIBLEAFDIR_x86_32)
+ LIBDIR_x86_64 = $(PREFIX)/$(LIBLEAFDIR_x86_64)
diff --git a/main/xen/xen-sed-is-broken-hack.patch b/main/xen/xen-sed-is-broken-hack.patch
new file mode 100644
index 0000000000..4168f72060
--- /dev/null
+++ b/main/xen/xen-sed-is-broken-hack.patch
@@ -0,0 +1,11 @@
+--- xen-4.0.1/xen/arch/x86/boot/Makefile
++++ xen-4.0.1.mod/xen/arch/x86/boot/Makefile
+@@ -2,7 +2,7 @@
+
+ head.o: reloc.S
+
+-BOOT_TRAMPOLINE := $(shell sed -n 's,^\#define[[:space:]]\{1\,\}BOOT_TRAMPOLINE[[:space:]]\{1\,\},,p' $(BASEDIR)/include/asm-x86/config.h)
++BOOT_TRAMPOLINE := 0x7c000
+ %.S: %.c
+ RELOC=$(BOOT_TRAMPOLINE) XEN_BITSPERLONG=$(patsubst x86_%,%,$(TARGET_SUBARCH)) $(MAKE) -f build32.mk $@
+
diff --git a/main/xen/xend.initd b/main/xen/xend.initd
new file mode 100644
index 0000000000..6958c0479f
--- /dev/null
+++ b/main/xen/xend.initd
@@ -0,0 +1,38 @@
+#!/sbin/runscript
+
+depend() {
+ need net
+ before xendomains sshd ntp-client ntpd nfs nfsmount rsyncd portmap dhcp
+}
+
+is_privileged_domain() {
+ grep -qsE '^control_d$' /proc/xen/capabilities
+ return $?
+}
+
+start() {
+ if is_privileged_domain ; then
+ ebegin "Starting Xen daemons"
+ /usr/sbin/xend start
+ eend $?
+ else
+ eerror "Can't start xend - not a privileged domain"
+ return 1
+ fi
+}
+
+stop() {
+ ebegin "Stopping Xen control daemon"
+ /usr/sbin/xend stop
+ eend $?
+}
+
+restart() {
+ ebegin "Restarting Xen control daemon"
+ /usr/sbin/xend restart
+ eend $?
+}
+
+status() {
+ is_privileged_domain && /usr/sbin/xend status
+}
diff --git a/main/xen/xendomains.initd b/main/xen/xendomains.initd
new file mode 100644
index 0000000000..d12577c2b0
--- /dev/null
+++ b/main/xen/xendomains.initd
@@ -0,0 +1,63 @@
+#!/sbin/runscript
+
+depend() {
+ need xend
+ after dhcp
+}
+
+get_domname() {
+ local name_from_file=$(sed -rn 's/^name\W*=\W*\"?([[:alnum:]_\.-]+)\"?\W*;?/\1/p' "${1}" | tail -n 1)
+
+ if [[ -z ${name_from_file} ]] ; then
+ basename "${1}"
+ else
+ echo ${name_from_file}
+ fi
+}
+
+is_running() {
+ /usr/sbin/xm list "${1}" >/dev/null 2>&1
+}
+
+start() {
+ einfo "Starting Xen domains in ${AUTODIR:=/etc/xen/auto}"
+
+ for dom in $(ls "${AUTODIR:=/etc/xen/auto}/"* 2>/dev/null | sort); do
+ name=$(get_domname ${dom})
+ if ! is_running ${name} ; then
+ ebegin " Starting domain ${name}"
+ xm create --quiet ${dom}
+ eend $?
+ else
+ einfo " Not starting ${name} - already running."
+ fi
+ done
+}
+
+stop() {
+ einfo "Stopping Xen domains in ${AUTODIR:=/etc/xen/auto}"
+
+ for dom in $(ls "${AUTODIR:=/etc/xen/auto}/"* 2>/dev/null | sort); do
+ name=$(get_domname ${dom})
+ if is_running ${name} ; then
+ ebegin " Sending shutdown signal to ${name}"
+ xm shutdown ${name} >/dev/null
+ eend $?
+ fi
+ done
+
+ for dom in $(ls "${AUTODIR:=/etc/xen/auto}/"* 2>/dev/null | sort); do
+ name=$(get_domname ${dom})
+ if is_running ${name} ; then
+ ebegin " Waiting for domain ${name} to shutdown"
+ xm shutdown --wait ${name}
+ eend $?
+ else
+ einfo " Not stopping ${name} - not running."
+ fi
+ done
+}
+
+status() {
+ /usr/sbin/xm list
+}
diff --git a/main/xev/APKBUILD b/main/xev/APKBUILD
new file mode 100644
index 0000000000..b2c40357e7
--- /dev/null
+++ b/main/xev/APKBUILD
@@ -0,0 +1,22 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xev
+pkgver=1.0.3
+pkgrel=2
+pkgdesc="print contents of X events"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+makedepends="pkgconfig libx11-dev"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="a9532c3d1683c99bb5df1895cb3a60b1 xev-1.0.3.tar.bz2"
diff --git a/main/xextproto/APKBUILD b/main/xextproto/APKBUILD
new file mode 100644
index 0000000000..b9d32a6696
--- /dev/null
+++ b/main/xextproto/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xextproto
+pkgver=7.2.0
+pkgrel=0
+pkgdesc="X11 various extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR=""$pkgdir"" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="220732210ceffb01bf1caf970e3b1bfb xextproto-7.2.0.tar.bz2"
diff --git a/main/xf86-input-evdev/APKBUILD b/main/xf86-input-evdev/APKBUILD
new file mode 100644
index 0000000000..82b8077337
--- /dev/null
+++ b/main/xf86-input-evdev/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-input-evdev
+pkgver=2.6.0
+pkgrel=1
+pkgdesc="X.org evdev input driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxkbfile-dev xorg-server-dev libxi-dev libxrandr-dev"
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="f33fe9413bde68936d8909206a13e8a1 xf86-input-evdev-2.6.0.tar.bz2"
diff --git a/main/xf86-input-keyboard/APKBUILD b/main/xf86-input-keyboard/APKBUILD
new file mode 100644
index 0000000000..5c820e1b67
--- /dev/null
+++ b/main/xf86-input-keyboard/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-input-keyboard
+pkgver=1.6.0
+pkgrel=0
+pkgdesc="X.org keyboard input driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxkbfile-dev xorg-server-dev libxi-dev libxrandr-dev"
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="e2abe9f13e526a73cb68a7d257546eba xf86-input-keyboard-1.6.0.tar.bz2"
diff --git a/main/xf86-input-mouse/APKBUILD b/main/xf86-input-mouse/APKBUILD
new file mode 100644
index 0000000000..62bde5aae8
--- /dev/null
+++ b/main/xf86-input-mouse/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-input-mouse
+pkgver=1.7.0
+pkgrel=0
+pkgdesc="X.org mouse input driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxkbfile-dev xorg-server-dev libxi-dev libxrandr-dev"
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="7f31472689c15b6de62eff04d0fb57d7 xf86-input-mouse-1.7.0.tar.bz2"
diff --git a/main/xf86-input-synaptics/APKBUILD b/main/xf86-input-synaptics/APKBUILD
new file mode 100644
index 0000000000..34da857a6c
--- /dev/null
+++ b/main/xf86-input-synaptics/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-input-synaptics
+pkgver=1.4.0.901
+pkgrel=0
+pkgdesc="X.org synaptics input driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxkbfile-dev xorg-server-dev libxi-dev libxrandr-dev"
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="776d4905302c0a66dc284a79e81c9b4b xf86-input-synaptics-1.4.0.901.tar.bz2"
diff --git a/main/xf86-input-vmmouse/APKBUILD b/main/xf86-input-vmmouse/APKBUILD
new file mode 100644
index 0000000000..5c202ed16f
--- /dev/null
+++ b/main/xf86-input-vmmouse/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-input-vmmouse
+pkgver=12.7.0
+pkgrel=0
+pkgdesc="X.org VMware mouse input driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxkbfile-dev xorg-server-dev libxi-dev libxrandr-dev"
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="dc77181330f983c7d0ec1ea1592c2ca7 xf86-input-vmmouse-12.7.0.tar.bz2"
diff --git a/main/xf86-video-apm/APKBUILD b/main/xf86-video-apm/APKBUILD
new file mode 100644
index 0000000000..06ac73dbb3
--- /dev/null
+++ b/main/xf86-video-apm/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-apm
+pkgver=1.2.3
+pkgrel=1
+pkgdesc="Alliance ProMotion video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="a3743a971b3acb7de3d2eefc8b1a4834 xf86-video-apm-1.2.3.tar.bz2"
diff --git a/main/xf86-video-ark/APKBUILD b/main/xf86-video-ark/APKBUILD
new file mode 100644
index 0000000000..b9974076b8
--- /dev/null
+++ b/main/xf86-video-ark/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-ark
+pkgver=0.7.3
+pkgrel=1
+pkgdesc="X.Org driver for ark cards"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org//releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="ff0cb9cb0a7f36cc6f556deed7327798 xf86-video-ark-0.7.3.tar.bz2"
diff --git a/main/xf86-video-ast/APKBUILD b/main/xf86-video-ast/APKBUILD
new file mode 100644
index 0000000000..3eefac13d3
--- /dev/null
+++ b/main/xf86-video-ast/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-ast
+pkgver=0.91.10
+pkgrel=1
+pkgdesc="X.Org driver for ASpeedTech cards"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="65da53af3ebd1685149b6145976fdb2d xf86-video-ast-0.91.10.tar.bz2"
diff --git a/main/xf86-video-ati/APKBUILD b/main/xf86-video-ati/APKBUILD
new file mode 100644
index 0000000000..cc3b32f77e
--- /dev/null
+++ b/main/xf86-video-ati/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-ati
+pkgver=6.14.2
+pkgrel=0
+pkgdesc="ATI video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="mesa-dri-ati"
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto libdrm-dev xf86driproto glproto mesa-dev
+ xineramaproto udev-dev pixman-dev
+ "
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+
+ ./configure --prefix=/usr \
+ --enable-dri \
+ --enable-kms \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="111ec4aef32a4298df7e38afa8bef373 xf86-video-ati-6.14.2.tar.bz2"
diff --git a/main/xf86-video-chips/APKBUILD b/main/xf86-video-chips/APKBUILD
new file mode 100644
index 0000000000..c92985e41b
--- /dev/null
+++ b/main/xf86-video-chips/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-chips
+pkgver=1.2.4
+pkgrel=0
+pkgdesc="Chips and Technologies video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="7aed07116e56c0630f62d7d34d7526e1 xf86-video-chips-1.2.4.tar.bz2"
diff --git a/main/xf86-video-cirrus/APKBUILD b/main/xf86-video-cirrus/APKBUILD
new file mode 100644
index 0000000000..e45b037bf5
--- /dev/null
+++ b/main/xf86-video-cirrus/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-cirrus
+pkgver=1.3.2
+pkgrel=5
+pkgdesc="Cirrus Logic video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2
+ qemu.patch"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="8195d03ed0be0975c03441e66a9f53b3 xf86-video-cirrus-1.3.2.tar.bz2
+b3bd556766fcd0fee51ae0c286f75f05 qemu.patch"
diff --git a/main/xf86-video-cirrus/qemu.patch b/main/xf86-video-cirrus/qemu.patch
new file mode 100644
index 0000000000..444fb6010c
--- /dev/null
+++ b/main/xf86-video-cirrus/qemu.patch
@@ -0,0 +1,25 @@
+diff -up xf86-video-cirrus-1.2.0/src/alp_driver.c.jx xf86-video-cirrus-1.2.0/src/alp_driver.c
+--- xf86-video-cirrus-1.2.0/src/alp_driver.c.jx 2008-03-19 10:29:23.000000000 -0400
++++ xf86-video-cirrus-1.2.0/src/alp_driver.c 2009-02-27 10:59:27.000000000 -0500
+@@ -812,6 +812,20 @@ AlpPreInit(ScrnInfoPtr pScrn, int flags)
+ else
+ xf86SetDDCproperties(pScrn,xf86PrintEDID(
+ xf86DoEDID_DDC2(pScrn->scrnIndex,pCir->I2CPtr1)));
++#ifdef XSERVER_LIBPCIACCESS
++ if (!pScrn->monitor->DDC &&
++ ((pCir->PciInfo->subvendor_id & 0xffff) == 0x1af4)) {
++ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++ "Defaulting to 1024x768 for QEMU\n");
++ pScrn->monitor->nHsync = 1;
++ pScrn->monitor->hsync[0].lo = 31.5;
++ pScrn->monitor->hsync[0].hi = 48.0;
++ pScrn->monitor->nVrefresh = 1;
++ pScrn->monitor->vrefresh[0].lo = 56.0;
++ pScrn->monitor->vrefresh[0].hi = 60.1;
++ pScrn->monitor->maxPixClock = 65000;
++ }
++#endif
+
+ /* Probe the possible LCD display */
+ AlpProbeLCD(pScrn);
+
diff --git a/main/xf86-video-dummy/APKBUILD b/main/xf86-video-dummy/APKBUILD
new file mode 100644
index 0000000000..64bab7edc9
--- /dev/null
+++ b/main/xf86-video-dummy/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-dummy
+pkgver=0.3.4
+pkgrel=2
+pkgdesc="X.Org driver for dummy cards"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto xf86dgaproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="1cf99415c998994f2e88575f942b364c xf86-video-dummy-0.3.4.tar.bz2"
diff --git a/main/xf86-video-fbdev/APKBUILD b/main/xf86-video-fbdev/APKBUILD
new file mode 100644
index 0000000000..2f878aa686
--- /dev/null
+++ b/main/xf86-video-fbdev/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-fbdev
+pkgver=0.4.2
+pkgrel=3
+pkgdesc="video driver for framebuffer device"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="53a533d9e0c2da50962282526bace074 xf86-video-fbdev-0.4.2.tar.bz2"
diff --git a/main/xf86-video-geode/APKBUILD b/main/xf86-video-geode/APKBUILD
new file mode 100644
index 0000000000..4bdeba9dfd
--- /dev/null
+++ b/main/xf86-video-geode/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-geode
+pkgver=2.11.12
+pkgrel=1
+pkgdesc="AMD Geode GX and LX video driver"
+url="http://xorg.freedesktop.org/"
+arch="x86"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto xf86dgaproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="a99c521db731c2f1df309057a8465e4c xf86-video-geode-2.11.12.tar.bz2"
diff --git a/main/xf86-video-glint/APKBUILD b/main/xf86-video-glint/APKBUILD
new file mode 100644
index 0000000000..5c3d3ce81f
--- /dev/null
+++ b/main/xf86-video-glint/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-glint
+pkgver=1.2.5
+pkgrel=1
+pkgdesc="GLINT/Permedia video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto xf86dgaproto glproto libdrm-dev xf86driproto
+ mesa-dev"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="77313a32280bdfee6269e28eca144274 xf86-video-glint-1.2.5.tar.bz2"
diff --git a/main/xf86-video-i128/APKBUILD b/main/xf86-video-i128/APKBUILD
new file mode 100644
index 0000000000..80877a2761
--- /dev/null
+++ b/main/xf86-video-i128/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-i128
+pkgver=1.3.4
+pkgrel=1
+pkgdesc="Number 9 I128 video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="103316abb2dc466219c027afc5a71691 xf86-video-i128-1.3.4.tar.bz2"
diff --git a/main/xf86-video-i740/APKBUILD b/main/xf86-video-i740/APKBUILD
new file mode 100644
index 0000000000..4f302681b8
--- /dev/null
+++ b/main/xf86-video-i740/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-i740
+pkgver=1.3.2
+pkgrel=4
+pkgdesc="Intel i740 video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="4ac1318788f62159965f15131c869e7a xf86-video-i740-1.3.2.tar.bz2"
diff --git a/main/xf86-video-intel/APKBUILD b/main/xf86-video-intel/APKBUILD
new file mode 100644
index 0000000000..333f4ea9d9
--- /dev/null
+++ b/main/xf86-video-intel/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-intel
+pkgver=2.15.0
+pkgrel=2
+pkgdesc="X.Org driver for Intel cards"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="mesa-dri-intel"
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto glproto xineramaproto libdrm-dev xf86driproto
+ mesa-dev libxvmc-dev xcb-util-dev udev-dev"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr \
+ --enable-xvmc \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="ba56ae395a9769ada1fef2014468bee9 xf86-video-intel-2.15.0.tar.bz2"
diff --git a/main/xf86-video-mach64/APKBUILD b/main/xf86-video-mach64/APKBUILD
new file mode 100644
index 0000000000..743a2a6870
--- /dev/null
+++ b/main/xf86-video-mach64/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-mach64
+pkgver=6.8.2
+pkgrel=4
+pkgdesc="ATI Mach64 video driver"
+url="http://xorg.freedesktop.org/"
+arch=""
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="mesa-dri-mach64"
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto xineramaproto libdrm-dev xf86driproto glproto
+ mesa-dev
+ "
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="6c0522b2b72a0a47c48d718443616651 xf86-video-mach64-6.8.2.tar.bz2"
diff --git a/main/xf86-video-newport/APKBUILD b/main/xf86-video-newport/APKBUILD
new file mode 100644
index 0000000000..746efb92ed
--- /dev/null
+++ b/main/xf86-video-newport/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-newport
+pkgver=0.2.3
+pkgrel=3
+pkgdesc="Newport video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="923baa1ee0429f03ed19ec0be6a4f62b xf86-video-newport-0.2.3.tar.bz2"
diff --git a/main/xf86-video-nouveau/APKBUILD b/main/xf86-video-nouveau/APKBUILD
new file mode 100644
index 0000000000..84082e428f
--- /dev/null
+++ b/main/xf86-video-nouveau/APKBUILD
@@ -0,0 +1,39 @@
+# Contributor:
+# Maintainer:
+pkgname=xf86-video-nouveau
+_gitdate=20110607
+pkgver=0.0.16_git${_gitdate}
+pkgrel=1
+pkgdesc="Open-source X.org drivers for nVidia video cards"
+url="http://nouveau.freedesktop.org/"
+arch="all"
+license="MIT"
+depends=""
+depends_dev=
+makedepends="pkgconfig randrproto renderproto videoproto xextproto libdrm-dev xorg-server-dev util-macros libtool autoconf automake xf86driproto"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://dev.alpinelinux.org/~ncopa/xf86-video-nouveau-${_gitdate}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${_gitdate}"
+
+mksource() {
+ mkdir /tmp/${pkgname}-${_gitdate}
+ (cd /tmp/${pkgname}-${_gitdate};
+ git clone -v --depth 1 git://anongit.freedesktop.org/nouveau/xf86-video-nouveau;
+ cd xf86-video-nouveau;
+ git archive --prefix=xf86-video-nouveau-${_gitdate}/ --format=tar HEAD | bzip2 > /tmp/${pkgname}-${_gitdate}/${pkgname}-${_gitdate}.tar.bz2)
+}
+
+build() {
+ cd "$_builddir"
+ ./autogen.sh --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="063d9c044ed5fafac227080fb6e63932 xf86-video-nouveau-20110607.tar.bz2"
diff --git a/main/xf86-video-nv/APKBUILD b/main/xf86-video-nv/APKBUILD
new file mode 100644
index 0000000000..6edcc6e30b
--- /dev/null
+++ b/main/xf86-video-nv/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-nv
+pkgver=2.1.18
+pkgrel=1
+pkgdesc="Nvidia video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="b12f0b2114849d1a542d8084732573d3 xf86-video-nv-2.1.18.tar.bz2"
diff --git a/main/xf86-video-openchrome/APKBUILD b/main/xf86-video-openchrome/APKBUILD
new file mode 100644
index 0000000000..451b8d44be
--- /dev/null
+++ b/main/xf86-video-openchrome/APKBUILD
@@ -0,0 +1,50 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-openchrome
+pkgver=0.2.904
+pkgrel=8
+pkgdesc="X.Org driver for VIA/S3G cards"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev libxvmc-dev fontsproto glproto
+ randrproto videoproto renderproto xf86driproto mesa-dev
+ "
+
+source="http://www.openchrome.org/releases/xf86-video-openchrome-$pkgver.tar.bz2
+ openchrome-0.2.904-svn921.patch
+ openchrome-0.2.904-fix_tvout_flickering.patch
+ openchrome.xinf
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p0 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+ install -Dm644 "$srcdir"/openchrome.xinf \
+ "$pkgdir"/usr/share/hwdata/videoaliases/openchrome.xinf
+}
+
+md5sums="f2481d98ef54febf5bffbb88a2a2426d xf86-video-openchrome-0.2.904.tar.bz2
+aa6f900c695b4c0eac0e2ea448699971 openchrome-0.2.904-svn921.patch
+cde4ab7e4d154f21c1a8cba5c7ccdd11 openchrome-0.2.904-fix_tvout_flickering.patch
+d6906087f0e93ea2d98e553f4dfbcc97 openchrome.xinf"
diff --git a/main/xf86-video-openchrome/openchrome-0.2.904-fix_tvout_flickering.patch b/main/xf86-video-openchrome/openchrome-0.2.904-fix_tvout_flickering.patch
new file mode 100644
index 0000000000..0fab55e4fd
--- /dev/null
+++ b/main/xf86-video-openchrome/openchrome-0.2.904-fix_tvout_flickering.patch
@@ -0,0 +1,35 @@
+Index: src/via_vt162x.c
+===================================================================
+--- src/via_vt162x.c (revision 787)
++++ src/via_vt162x.c (revision 786)
+@@ -684,30 +650,11 @@ VT1622ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mo
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2B, Table.RGB[4]);
+ if (Table.RGB[5])
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2C, Table.RGB[5]);
+- if (pBIOSInfo->TVEncoder == VIA_VT1625) {
+- if (pBIOSInfo->TVType < TVTYPE_480P) {
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12);
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E);
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85);
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A);
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00);
+- } else {
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12);
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85);
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A);
+- }
+- }
+ } else if (pBIOSInfo->TVOutput == TVOUTPUT_YCBCR) {
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x03);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.YCbCr[0]);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.YCbCr[1]);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.YCbCr[2]);
+- if (pBIOSInfo->TVEncoder == VIA_VT1625) {
+- if (pBIOSInfo->TVType < TVTYPE_480P) {
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E);
+- xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00);
+- }
+- }
+ }
+
+ /* Configure flicker filter. */
diff --git a/main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch b/main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch
new file mode 100644
index 0000000000..a26382b608
--- /dev/null
+++ b/main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch
@@ -0,0 +1,4427 @@
+Index: ChangeLog
+===================================================================
+--- ChangeLog (revision 811)
++++ ChangeLog (working copy)
+@@ -1,3 +1,225 @@
++2011-05-04 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix XAA displaying issues
++
++ * src/via_accel.c: (viaInitXAA):
++
++2011-01-23 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Enable hardware cursor for VX900
++
++ * src/via_cursor.c: (viaHWCursorInit):
++ * src/via_mode.c: (ViaModeSet):
++
++2010-12-16 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Merge vx900_branch - initial VX900 support
++
++ * src/via_accel.c: (viaFlushPCI), (viaDisableVQ),
++ (viaInitialize2DEngine), (viaAccelSync), (viaPitchHelper),
++ (viaInitXAA):
++ * src/via_bandwidth.c: (ViaSetPrimaryFIFO), (ViaSetSecondaryFIFO):
++ * src/via_bios.h:
++ * src/via_crtc.c: (ViaFirstCRTCSetMode), (ViaSecondCRTCSetMode):
++ * src/via_cursor.c: (viaHWCursorInit), (viaCursorStore),
++ (viaCursorRestore), (viaShowCursor), (viaHideCursor),
++ (viaSetCursorPosition), (viaLoadCursorImage), (viaSetCursorColors):
++ * src/via_driver.c: (VIASetupDefaultOptions), (VIAPreInit),
++ (VIALeaveVT), (VIASave), (VIARestore), (ViaMMIOEnable),
++ (ViaMMIODisable), (VIAMapFB), (VIAWriteMode), (VIACloseScreen):
++ * src/via_driver.h:
++ * src/via_id.c:
++ * src/via_id.h:
++ * src/via_mode.c: (ViaDFPDetect), (ViaOutputsDetect),
++ (ViaOutputsSelect), (ViaGetMemoryBandwidth), (ViaSetDotclock),
++ (ViaModeSet):
++ * src/via_mode.h:
++ * src/via_panel.c: (ViaPanelScaleDisable), (ViaPanelPreInit),
++ (ViaPanelGetSizeFromDDC):
++ * src/via_video.c: (DecideOverlaySupport):
++ * src/via_xvmc.c: (ViaInitXVMC):
++
++2010-12-15 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Enable the new mode switch and panel support on K8M800 and VM800 chipsets
++
++ * src/via_driver.c: (VIASetupDefaultOptions), (VIAPreInit):
++ * src/via_mode.c: (ViaModeSet):
++
++2010-11-10 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Replace the deprecated functions
++ xalloc/xrealloc/xfree/xcalloc with
++ malloc/realloc/free/calloc.
++ Refer to "/xserver/include/os.h"
++
++ * src/via_accel.c: (viaSetupCBuffer), (viaTearDownCBuffer),
++ (viaInitExa), (viaExitAccel), (viaFinishInitAccel):
++ * src/via_dga.c: (VIASetupDGAMode):
++ * src/via_dri.c: (VIAInitVisualConfigs), (VIADRIScreenInit),
++ (VIADRICloseScreen):
++ * src/via_driver.c: (VIAFreeRec), (VIAProbe), (VIAPreInit),
++ (VIACloseScreen):
++ * src/via_memcpy.c: (viaVidCopyInit):
++ * src/via_swov.c: (Upd_Video):
++ * src/via_vbe.c: (ViaVbeSetMode):
++ * src/via_video.c: (viaExitVideo), (viaStopVideo),
++ (viaDmaBlitImage):
++ * src/via_xvmc.c: (cleanupViaXvMC), (ViaCleanupXVMC),
++ (ViaXvMCCreateContext), (ViaXvMCCreateSurface),
++ (ViaXvMCCreateSubpicture), (ViaXvMCDestroyContext),
++ (ViaXvMCDestroySurface), (ViaXvMCDestroySubpicture),
++ (viaXvMCInitXv):
++
++2010-10-24 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Siragon ML-6200 laptop support
++
++ * src/via_id.c:
++
++2010-06-24 Jon Nettleton <jon.nettleton@gmail.com>
++
++ PM800 also uses the CME Engine. Setup the hqv_cme_regs
++ for it.
++
++ * src/via_swov.c: (VIAVidHWDiffInit):
++
++2010-06-09 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix freeze on 64bit system for K8M800 chipset
++
++ * src/via_dri.c: (VIADRIAgpInit):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Re-enable the Virtual Queue for the VX800/VX855 chipsets.
++
++ * src/via_accel.c: (viaDisableVQ), (viaInitialize2DEngine):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Disable certain hardware clipping options for the VX855.
++ These cause the 2d engine to become unstable when in
++ 16-bit mode.
++
++ * src/via_accel.c: (viaInitXAA):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Add an undocumented option which allows certain I2C buses
++ to be probed at startup. This allows workarounds for custom
++ chipset makers that have used the VX855 I2C buses for other
++ purposes.
++
++ * src/via_bios.h:
++ * src/via_driver.c: (VIASetupDefaultOptions), (VIAPreInit):
++ * src/via_driver.h:
++ * src/via_i2c.c:
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Improve 2d performance on chipsets that don't have
++ AGP/PCIe support yet.
++
++ * src/via_accel.c: (viaSetupForScreenToScreenCopy),
++ (viaSetupForSolidFill), (viaSetupForMono8x8PatternFill),
++ (viaSetupForColor8x8PatternFill),
++ (viaSetupForCPUToScreenColorExpandFill),
++ (viaSubsequentScanlineCPUToScreenColorExpandFill),
++ (viaSetupForImageWrite), (viaSubsequentImageWriteRect),
++ (viaSetupForSolidLine), (viaSetupForDashedLine), (viaInitXAA):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Put timeouts on our while statements. These codepaths
++ should be interrupted by a hardware state change, but
++ if something goes wrong they loop forevere. Let's try
++ and behave a little by putting a timeout on these loops.
++
++ * src/via_swov.c: (viaWaitHQVFlip), (viaWaitHQVFlipClear),
++ (viaWaitHQVDone):
++ * src/via_video.c: (Flip):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Add XVideo support for the VX855 Chipset.
++ To support this chipset I have added HWDiff->HQVCmeRegs
++ that allows handling differing register values, and
++ HWDiff->dwNewScaleCtl which allows selection of a
++ new Video scaling engine needed for the VX800/VX855
++ chipsets.
++
++ * src/via.h:
++ * src/via_bandwidth.c: (ViaSetSecondaryFIFO):
++ * src/via_driver.h:
++ * src/via_swov.c: (SaveVideoRegister), (VIAVidHWDiffInit),
++ (viaOverlayHQVCalcZoomWidth), (viaOverlayHQVCalcZoomHeight),
++ (ViaSwovSurfaceCreate), (SetHQVFetch), (Upd_Video):
++ * src/via_swov.h:
++
++2010-04-21 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Replace RegionsEqual with REGION_EQUAL and use
++ the xf86XVFillKeyHelperDrawable instead of xf86XVFillKeyHelper
++
++ * src/via_video.c: (viaReputImage), (viaPutImage):
++
++2010-03-07 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix segfaults with EXA and XV (Ticket #359)
++ Tested on K8M890 and VN800
++
++ * src/via_video.c: (viaReputImage), (viaPutImage):
++
++2010-02-10 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix bug with suspend and VT switch on VX800 and 64bit systems
++
++ * src/via_driver.h:
++ * src/via_video.c: (viaResetVideo), (viaSaveVideo),
++ (viaRestoreVideo), (viaExitVideo):
++ * src/via_video.h:
++
++2010-01-24 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix starting address restore and save (initial 64-bit support)
++
++ * src/via_crtc.c: (ViaFirstCRTCSetMode),
++ (ViaFirstCRTCSetStartingAddress):
++ * src/via_dri.c: (VIADRIAgpInit):
++ * src/via_driver.c: (VIASave), (VIARestore):
++ * src/via_driver.h:
++
++2009-12-04 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Enable new mode switch for VM800 chipsets
++
++ * src/via_driver.c: (VIASetupDefaultOptions):
++
++2009-11-21 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Add option to enable unaccelerated RandR rotation ("SWRandR").
++ The accelerated option "HWRandR" is currently not implemented.
++
++ * src/openchrome.man:
++ * src/via_driver.c: (VIAPreInit):
++
++2009-11-20 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Enabled new mode switch for PM800 chipset,
++ to resolve many bugs with resolution detecting and changing
++ (eg. switching to console)
++
++ * src/via_driver.c: (VIASetupDefaultOptions), (VIAPreInit):
++
++2009-11-07 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Add more comments to ViaSetSecondaryFIFO, add panel scale support for
++ CLE266 and KM400, fix bug with malloc.
++
++ * src/via_bandwidth.c: (ViaSetSecondaryFIFO):
++ * src/via_panel.c: (ViaPanelScale), (ViaPanelGetNativeDisplayMode):
++
+ 2009-09-26 Bartosz Kosiorek <gang65@poczta.onet.pl>
+
+ Save/restore ECK Clock Synthesizer
+Index: src/via_panel.c
+===================================================================
+--- src/via_panel.c (revision 811)
++++ src/via_panel.c (working copy)
+@@ -45,17 +45,17 @@
+ {1280, 768},
+ {1280, 1024},
+ {1400, 1050},
+- {1600, 1200}, /* 0x6 Resolution 1440x900 */
++ {1600, 1200}, /* 0x6 */
+ {1280, 800}, /* 0x7 Resolution 1280x800 (Samsung NC20) */
+ {800, 480}, /* 0x8 For Quanta 800x480 */
+ {1024, 600}, /* 0x9 Resolution 1024x600 (for HP 2133) */
+ {1366, 768}, /* 0xA Resolution 1366x768 */
+ {1920, 1080},
+ {1920, 1200},
+- {1280, 1024}, /* 0xD Need to be fixed to 1920x1200 */
+- {1440, 900}, /* 0xE Need to be fixed to 640x240 */
++ {1280, 1024}, /* 0xD */
++ {1440, 900}, /* 0xE */
+ {1280, 720}, /* 0xF 480x640 */
+- {1200, 900}, /* 0x10 For Panasonic 1280x768 18bit Dual-Channel Panel */
++ {1200, 900}, /* 0x10 For OLPC 1.5 */
+ {1360, 768}, /* 0x11 Resolution 1360X768 */
+ {1024, 768}, /* 0x12 Resolution 1024x768 */
+ {800, 480} /* 0x13 General 8x4 panel use this setting */
+@@ -147,6 +147,9 @@
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ ViaCrtcMask(hwp, 0x79, 0x00, 0x01);
++ /* Disable VX900 down scaling */
++ if (pVia->Chipset == VIA_VX900)
++ ViaCrtcMask(hwp, 0x89, 0x00, 0x01);
+ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400)
+ ViaCrtcMask(hwp, 0xA2, 0x00, 0xC8);
+ }
+@@ -171,12 +174,18 @@
+ resWidth, resHeight, panelWidth, panelHeight));
+
+ if (resWidth < panelWidth) {
+- /* FIXME: It is different for chipset < K8M800 */
+- horScalingFactor = ((resWidth - 1) * 4096) / (panelWidth - 1);
++ /* Load Horizontal Scaling Factor */
++ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
++ horScalingFactor = ((resWidth - 1) * 4096) / (panelWidth - 1);
++
++ /* Horizontal scaling enabled */
++ cra2 = 0xC0;
++ cr9f = horScalingFactor & 0x0003; /* HSCaleFactor[1:0] at CR9F[1:0] */
++ } else {
++ /* TODO: Need testing */
++ horScalingFactor = ((resWidth - 1) * 1024) / (panelWidth - 1);
++ }
+
+- /* Horizontal scaling enabled */
+- cra2 = 0xC0;
+- cr9f = horScalingFactor & 0x0003; /* HSCaleFactor[1:0] at CR9F[1:0] */
+ cr77 = (horScalingFactor & 0x03FC) >> 2; /* HSCaleFactor[9:2] at CR77[7:0] */
+ cr79 = (horScalingFactor & 0x0C00) >> 10; /* HSCaleFactor[11:10] at CR79[5:4] */
+ cr79 <<= 4;
+@@ -184,11 +193,18 @@
+ }
+
+ if (resHeight < panelHeight) {
+- verScalingFactor = ((resHeight - 1) * 2048) / (panelHeight - 1);
++ /* Load Vertical Scaling Factor */
++ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
++ verScalingFactor = ((resHeight - 1) * 2048) / (panelHeight - 1);
+
+- /* Vertical scaling enabled */
+- cra2 |= 0x08;
+- cr79 |= ((verScalingFactor & 0x0001) << 3); /* VSCaleFactor[0] at CR79[3] */
++ /* Vertical scaling enabled */
++ cra2 |= 0x08;
++ cr79 |= ((verScalingFactor & 0x0001) << 3); /* VSCaleFactor[0] at CR79[3] */
++ } else {
++ /* TODO: Need testing */
++ verScalingFactor = ((resHeight - 1) * 1024) / (panelHeight - 1);
++ }
++
+ cr78 |= (verScalingFactor & 0x01FE) >> 1; /* VSCaleFactor[8:1] at CR78[7:0] */
+ cr79 |= ((verScalingFactor & 0x0600) >> 9) << 6; /* VSCaleFactor[10:9] at CR79[7:6] */
+ scaling = TRUE;
+@@ -203,13 +219,19 @@
+ ViaCrtcMask(hwp, 0x77, cr77, 0xFF);
+ ViaCrtcMask(hwp, 0x78, cr78, 0xFF);
+ ViaCrtcMask(hwp, 0x79, cr79, 0xF8);
+- ViaCrtcMask(hwp, 0x9F, cr9f, 0x03);
++ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
++ ViaCrtcMask(hwp, 0x9F, cr9f, 0x03);
++ }
+ ViaCrtcMask(hwp, 0x79, 0x03, 0x03);
+- } else
++ } else {
++ /* Disable panel scale */
+ ViaCrtcMask(hwp, 0x79, 0x00, 0x01);
++ }
++
++ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
++ ViaCrtcMask(hwp, 0xA2, cra2, 0xC8);
++ }
+
+- ViaCrtcMask(hwp, 0xA2, cra2, 0xC8);
+-
+ /* Horizontal scaling selection: interpolation */
+ // ViaCrtcMask(hwp, 0x79, 0x02, 0x02);
+ // else
+@@ -233,14 +255,14 @@
+
+ if (panelMode->Width && panelMode->Height) {
+
+- /* TODO: fix refresh rate and check malloc */
++ /* TODO: fix refresh rate */
+ DisplayModePtr p = malloc( sizeof(DisplayModeRec) ) ;
+- memset(p, 0, sizeof(DisplayModeRec));
++ if (p) {
++ memset(p, 0, sizeof(DisplayModeRec));
+
+- float refresh = 60.0f ;
++ float refresh = 60.0f ;
+
+- /* The following code is borrowed from xf86SetModeCrtc. */
+- if (p) {
++ /* The following code is borrowed from xf86SetModeCrtc. */
+ viaTimingCvt(p, panelMode->Width, panelMode->Height, refresh, FALSE, TRUE);
+ p->CrtcHDisplay = p->HDisplay;
+ p->CrtcHSyncStart = p->HSyncStart;
+@@ -256,9 +278,13 @@
+ p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+ p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+ p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+-
++
++ pVia->pBIOSInfo->Panel->NativeDisplayMode = p;
++ } else {
++ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
++ "Out of memory. Size: %d bytes\n", sizeof(DisplayModeRec));
+ }
+- pVia->pBIOSInfo->Panel->NativeDisplayMode = p;
++
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Invalid panel dimension (%dx%d)\n", panelMode->Width,
+@@ -282,10 +308,7 @@
+ Bool ret;
+
+ ret = ViaPanelGetSizeFromDDCv1(pScrn, &width, &height);
+-/*
+- if (!ret)
+- ret = ViaPanelGetSizeFromDDCv2(pScrn, &width);
+-*/
++
+ if (ret) {
+ panel->NativeModeIndex = ViaPanelLookUpModeIndex(width, height);
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelLookUpModeIndex, Width %d, Height %d, NativeModeIndex%d\n", width, height, panel->NativeModeIndex));
+@@ -333,28 +356,28 @@
+
+
+ /*
+- * Try to interprete EDID ourselves.
++ * Try to interpret EDID ourselves.
+ */
+ Bool
+ ViaPanelGetSizeFromEDID(ScrnInfoPtr pScrn, xf86MonPtr pMon,
+ int *width, int *height)
+ {
+- int i, max = 0, vsize;
++ int i, max_hsize = 0, vsize = 0;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAGetPanelSizeFromEDID\n"));
+
+ /* !!! Why are we not checking VESA modes? */
+
+ /* checking standard timings */
+- for (i = 0; i < 8; i++)
++ for (i = 0; i < STD_TIMINGS; i++)
+ if ((pMon->timings2[i].hsize > 256)
+- && (pMon->timings2[i].hsize > max)) {
+- max = pMon->timings2[i].hsize;
++ && (pMon->timings2[i].hsize > max_hsize)) {
++ max_hsize = pMon->timings2[i].hsize;
+ vsize = pMon->timings2[i].vsize;
+ }
+
+- if (max != 0) {
+- *width = max;
++ if (max_hsize != 0) {
++ *width = max_hsize;
+ *height = vsize;
+ return TRUE;
+ }
+@@ -369,14 +392,14 @@
+ struct detailed_timings timing = pMon->det_mon[i].section.d_timings;
+
+ /* ignore v_active for now */
+- if ((timing.clock > 15000000) && (timing.h_active > max)) {
+- max = timing.h_active;
++ if ((timing.clock > 15000000) && (timing.h_active > max_hsize)) {
++ max_hsize = timing.h_active;
+ vsize = timing.v_active;
+ }
+ }
+
+- if (max != 0) {
+- *width = max;
++ if (max_hsize != 0) {
++ *width = max_hsize;
+ *height = vsize;
+ return TRUE;
+ }
+@@ -386,7 +409,6 @@
+
+ Bool
+ ViaPanelGetSizeFromDDCv1(ScrnInfoPtr pScrn, int *width, int *height)
+-
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+ xf86MonPtr pMon;
+@@ -396,7 +418,7 @@
+ if (!xf86I2CProbeAddress(pVia->pI2CBus2, 0xA0))
+ return FALSE;
+
+- pMon = xf86DoEDID_DDC2(pScrn->scrnIndex, pVia->pI2CBus2);
++ pMon = xf86DoEEDID(pScrn->scrnIndex, pVia->pI2CBus2, TRUE);
+ if (!pMon)
+ return FALSE;
+
+Index: src/via_id.h
+===================================================================
+--- src/via_id.h (revision 811)
++++ src/via_id.h (working copy)
+@@ -39,6 +39,7 @@
+ VIA_P4M890,
+ VIA_VX800,
+ VIA_VX855,
++ VIA_VX900,
+ VIA_LAST
+ };
+
+@@ -56,6 +57,7 @@
+ #define PCI_CHIP_VT3327 0x3343 /* P4M890 */
+ #define PCI_CHIP_VT3353 0x1122 /* VX800 */
+ #define PCI_CHIP_VT3409 0x5122 /* VX855/VX875 */
++#define PCI_CHIP_VT3410 0x7122 /* VX900 */
+
+ /* There is some conflicting information about the two major revisions of
+ * the CLE266, often labelled Ax and Cx. The dividing line seems to be
+Index: src/via_video.c
+===================================================================
+--- src/via_video.c (revision 811)
++++ src/via_video.c (working copy)
+@@ -354,6 +354,14 @@
+ mClock = 333;
+ memEfficiency = (float)SINGLE_3205_133;
+ break;
++ case VIA_MEM_DDR800:
++ mClock = 400;
++ memEfficiency = (float)SINGLE_3205_133;
++ break;
++ case VIA_MEM_DDR1066:
++ mClock = 533;
++ memEfficiency = (float)SINGLE_3205_133;
++ break;
+ default:
+ /*Unknow DRAM Type */
+ DBG_DD(ErrorF("Unknow DRAM Type!\n"));
+@@ -426,7 +434,7 @@
+ DBG_DD(ErrorF(" via_video.c : totalBandwidth= %f : \n",
+ totalBandWidth));
+ if (needBandWidth < totalBandWidth)
+- return TRUE;
++ return TRUE;
+ }
+ return FALSE;
+ }
+@@ -466,8 +474,8 @@
+
+ viaVidEng->video1_ctl = 0;
+ viaVidEng->video3_ctl = 0;
+- viaVidEng->compose = 0x80000000;
+- viaVidEng->compose = 0x40000000;
++ viaVidEng->compose = V1_COMMAND_FIRE;
++ viaVidEng->compose = V3_COMMAND_FIRE;
+ viaVidEng->color_key = 0x821;
+ viaVidEng->snd_color_key = 0x821;
+
+@@ -479,16 +487,16 @@
+ VIAPtr pVia = VIAPTR(pScrn);
+ vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
+
++ DBG_DD(ErrorF(" via_video.c : viaSaveVideo : \n"));
+ /* Save video registers */
+- /* TODO: Identify which registers should be saved and restored */
+ memcpy(pVia->VideoRegs, (void*)viaVidEng, sizeof(video_via_regs));
+
+ pVia->dwV1 = ((vmmtr) viaVidEng)->video1_ctl;
+ pVia->dwV3 = ((vmmtr) viaVidEng)->video3_ctl;
+ viaVidEng->video1_ctl = 0;
+ viaVidEng->video3_ctl = 0;
+- viaVidEng->compose = 0x80000000;
+- viaVidEng->compose = 0x40000000;
++ viaVidEng->compose = V1_COMMAND_FIRE;
++ viaVidEng->compose = V3_COMMAND_FIRE;
+ }
+
+ void
+@@ -496,16 +504,66 @@
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+ vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
++ video_via_regs *localVidEng = pVia->VideoRegs;
++
+
++ DBG_DD(ErrorF(" via_video.c : viaRestoreVideo : \n"));
+ /* Restore video registers */
+- /* TODO: Identify which registers should be saved and restored */
+- memcpy((void*)viaVidEng, pVia->VideoRegs, sizeof(video_via_regs));
++ /* flush restored video engines' setting to VidMapBase */
++
++ viaVidEng->alphawin_hvstart = localVidEng->alphawin_hvstart;
++ viaVidEng->alphawin_size = localVidEng->alphawin_size;
++ viaVidEng->alphawin_ctl = localVidEng->alphawin_ctl;
++ viaVidEng->alphafb_stride = localVidEng->alphafb_stride;
++ viaVidEng->color_key = localVidEng->color_key;
++ viaVidEng->alphafb_addr = localVidEng->alphafb_addr;
++ viaVidEng->chroma_low = localVidEng->chroma_low;
++ viaVidEng->chroma_up = localVidEng->chroma_up;
++ viaVidEng->interruptflag = localVidEng->interruptflag;
+
++ if (pVia->ChipId != PCI_CHIP_VT3314)
++ {
++ /*VT3314 only has V3*/
++ viaVidEng->video1_ctl = localVidEng->video1_ctl;
++ viaVidEng->video1_fetch = localVidEng->video1_fetch;
++ viaVidEng->video1y_addr1 = localVidEng->video1y_addr1;
++ viaVidEng->video1_stride = localVidEng->video1_stride;
++ viaVidEng->video1_hvstart = localVidEng->video1_hvstart;
++ viaVidEng->video1_size = localVidEng->video1_size;
++ viaVidEng->video1y_addr2 = localVidEng->video1y_addr2;
++ viaVidEng->video1_zoom = localVidEng->video1_zoom;
++ viaVidEng->video1_mictl = localVidEng->video1_mictl;
++ viaVidEng->video1y_addr0 = localVidEng->video1y_addr0;
++ viaVidEng->video1_fifo = localVidEng->video1_fifo;
++ viaVidEng->video1y_addr3 = localVidEng->video1y_addr3;
++ viaVidEng->v1_source_w_h = localVidEng->v1_source_w_h ;
++ viaVidEng->video1_CSC1 = localVidEng->video1_CSC1;
++ viaVidEng->video1_CSC2 = localVidEng->video1_CSC2;
++ }
++ viaVidEng->snd_color_key = localVidEng->snd_color_key;
++ viaVidEng->v3alpha_prefifo = localVidEng->v3alpha_prefifo;
++ viaVidEng->v3alpha_fifo = localVidEng->v3alpha_fifo;
++ viaVidEng->video3_CSC2 = localVidEng->video3_CSC2;
++ viaVidEng->video3_CSC2 = localVidEng->video3_CSC2;
++ viaVidEng->v3_source_width = localVidEng->v3_source_width;
++ viaVidEng->video3_ctl = localVidEng->video3_ctl;
++ viaVidEng->video3_addr0 = localVidEng->video3_addr0;
++ viaVidEng->video3_addr1 = localVidEng->video3_addr1;
++ viaVidEng->video3_stride = localVidEng->video3_stride;
++ viaVidEng->video3_hvstart = localVidEng->video3_hvstart;
++ viaVidEng->video3_size = localVidEng->video3_size;
++ viaVidEng->v3alpha_fetch = localVidEng->v3alpha_fetch;
++ viaVidEng->video3_zoom = localVidEng->video3_zoom;
++ viaVidEng->video3_mictl = localVidEng->video3_mictl;
++ viaVidEng->video3_CSC1 = localVidEng->video3_CSC1;
++ viaVidEng->video3_CSC2 = localVidEng->video3_CSC2;
++ viaVidEng->compose = localVidEng->compose;
++
+ viaVidEng->video1_ctl = pVia->dwV1;
+ viaVidEng->video3_ctl = pVia->dwV3;
+- viaVidEng->compose = 0x80000000;
+- viaVidEng->compose = 0x40000000;
+-
++ if (pVia->ChipId != PCI_CHIP_VT3314)
++ viaVidEng->compose = V1_COMMAND_FIRE;
++ viaVidEng->compose = V3_COMMAND_FIRE;
+ }
+
+ void
+@@ -524,8 +582,8 @@
+
+ viaVidEng->video1_ctl = 0;
+ viaVidEng->video3_ctl = 0;
+- viaVidEng->compose = 0x80000000;
+- viaVidEng->compose = 0x40000000;
++ viaVidEng->compose = V1_COMMAND_FIRE;
++ viaVidEng->compose = V3_COMMAND_FIRE;
+
+ /*
+ * Free all adaptor info allocated in viaInitVideo.
+@@ -542,15 +600,15 @@
+ (viaPortPrivPtr) curAdapt->pPortPrivates->ptr + j,
+ TRUE);
+ }
+- xfree(curAdapt->pPortPrivates->ptr);
++ free(curAdapt->pPortPrivates->ptr);
+ }
+- xfree(curAdapt->pPortPrivates);
++ free(curAdapt->pPortPrivates);
+ }
+- xfree(curAdapt);
++ free(curAdapt);
+ }
+ }
+ if (allAdaptors)
+- xfree(allAdaptors);
++ free(allAdaptors);
+ }
+
+ void
+@@ -561,7 +619,7 @@
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors;
+ int num_adaptors, num_new;
+
+- DBG_DD(ErrorF(" via_video.c : viaInitVideo : \n"));
++ DBG_DD(ErrorF(" via_video.c : viaInitVideo, Screen[%d]\n", pScrn->scrnIndex));
+
+ allAdaptors = NULL;
+ newAdaptors = NULL;
+@@ -611,7 +669,7 @@
+
+ DBG_DD(ErrorF(" via_video.c : num_adaptors : %d\n", num_adaptors));
+ if (newAdaptors) {
+- allAdaptors = xalloc((num_adaptors + num_new) *
++ allAdaptors = malloc((num_adaptors + num_new) *
+ sizeof(XF86VideoAdaptorPtr *));
+ if (allAdaptors) {
+ if (num_adaptors)
+@@ -636,194 +694,6 @@
+ }
+ }
+
+-static Bool
+-RegionsEqual(RegionPtr A, RegionPtr B)
+-{
+- int *dataA, *dataB;
+- int num;
+-
+- num = REGION_NUM_RECTS(A);
+- if (num != REGION_NUM_RECTS(B))
+- return FALSE;
+-
+- if ((A->extents.x1 != B->extents.x1) ||
+- (A->extents.x2 != B->extents.x2) ||
+- (A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2))
+- return FALSE;
+-
+- dataA = (int *)REGION_RECTS(A);
+- dataB = (int *)REGION_RECTS(B);
+-
+- while (num--) {
+- if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+- return FALSE;
+- dataA += 2;
+- dataB += 2;
+- }
+-
+- return TRUE;
+-}
+-
+-static void
+-viaVideoFillPixmap(ScrnInfoPtr pScrn,
+- char *base,
+- unsigned long pitch,
+- int depth,
+- int x, int y, int w, int h,
+- unsigned long color)
+-{
+- int i;
+-
+- ErrorF("pitch %lu, depth %d, x %d, y %d, w %d, h %d, color 0x%08lx\n",
+- pitch, depth, x, y, w, h, color);
+-
+- depth = (depth + 7) >> 3;
+-
+- base += y*pitch + x*depth;
+-
+- switch(depth) {
+- case 4:
+- while(h--) {
+- register CARD32 *p = (CARD32 *)base;
+- for (i=0; i<w; ++i) {
+- *p++ = color;
+- }
+- base += pitch;
+- }
+- break;
+- case 2: {
+- register CARD16 col = color & 0x0000FFFF;
+- while(h--) {
+- register CARD16 *p = (CARD16 *)base;
+- for (i=0; i<w; ++i) {
+- *p++ = col;
+- }
+- base += pitch;
+- }
+- break;
+- }
+- case 1: {
+- register CARD8 col = color & 0xFF;
+- while(h--) {
+- register CARD8 *p = (CARD8 *)base;
+- for (i=0; i<w; ++i) {
+- *p++ = col;
+- }
+- base += pitch;
+- }
+- break;
+- }
+- default:
+- break;
+- }
+-}
+-
+-
+-
+-static int
+-viaPaintColorkey(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv, RegionPtr clipBoxes,
+- DrawablePtr pDraw)
+-{
+-
+- if (pDraw->type == DRAWABLE_WINDOW) {
+-
+- VIAPtr pVia = VIAPTR(pScrn);
+- PixmapPtr pPix = (pScrn->pScreen->GetWindowPixmap)((WindowPtr) pDraw);
+- unsigned long pitch = pPix->devKind;
+- long offset = (long) pPix->devPrivate.ptr - (long) pVia->FBBase;
+- int x,y;
+- BoxPtr pBox;
+- int nBox;
+-
+- REGION_TRANSLATE(pScrn->pScreen, clipBoxes, - pPix->screen_x,
+- - pPix->screen_y);
+-
+- nBox = REGION_NUM_RECTS(clipBoxes);
+- pBox = REGION_RECTS(clipBoxes);
+-
+- while(nBox--) {
+- if (pVia->NoAccel || offset < 0 ||
+- offset > pScrn->videoRam*1024) {
+- viaVideoFillPixmap(pScrn, pPix->devPrivate.ptr, pitch,
+- pDraw->bitsPerPixel, pBox->x1, pBox->y1,
+- pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
+- pPriv->colorKey);
+- } else {
+- viaAccelFillPixmap(pScrn, offset, pitch,
+- pDraw->bitsPerPixel, pBox->x1, pBox->y1,
+- pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
+- pPriv->colorKey);
+- }
+- pBox++;
+- }
+-
+- DamageDamageRegion(pPix, clipBoxes);
+- }
+-
+- return 0;
+-}
+-
+-
+-/*
+- * This one gets called, for example, on panning.
+- */
+-
+-static int
+-viaReputImage(ScrnInfoPtr pScrn,
+- short drw_x, short drw_y, RegionPtr clipBoxes, pointer data,
+- DrawablePtr pDraw)
+-{
+-
+- DDUPDATEOVERLAY UpdateOverlay_Video;
+- LPDDUPDATEOVERLAY lpUpdateOverlay = &UpdateOverlay_Video;
+- viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
+- VIAPtr pVia = VIAPTR(pScrn);
+-
+- if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
+- REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+- if (pPriv->autoPaint) {
+- if (pDraw->type == DRAWABLE_WINDOW) {
+- viaPaintColorkey(pScrn, pPriv, clipBoxes, pDraw);
+- } else {
+- xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey,
+- clipBoxes);
+- }
+- }
+- }
+-
+- if (drw_x == pPriv->old_drw_x &&
+- drw_y == pPriv->old_drw_y &&
+- pVia->swov.oldPanningX == pVia->swov.panning_x &&
+- pVia->swov.oldPanningY == pVia->swov.panning_y) {
+- viaXvError(pScrn, pPriv, xve_none);
+- return Success;
+- }
+-
+- lpUpdateOverlay->SrcLeft = pPriv->old_src_x;
+- lpUpdateOverlay->SrcTop = pPriv->old_src_y;
+- lpUpdateOverlay->SrcRight = pPriv->old_src_x + pPriv->old_src_w;
+- lpUpdateOverlay->SrcBottom = pPriv->old_src_y + pPriv->old_src_h;
+-
+- lpUpdateOverlay->DstLeft = drw_x;
+- lpUpdateOverlay->DstTop = drw_y;
+- lpUpdateOverlay->DstRight = drw_x + pPriv->old_drw_w;
+- lpUpdateOverlay->DstBottom = drw_y + pPriv->old_drw_h;
+- pPriv->old_drw_x = drw_x;
+- pPriv->old_drw_y = drw_y;
+-
+- lpUpdateOverlay->dwFlags = DDOVER_KEYDEST;
+-
+- if (pScrn->bitsPerPixel == 8)
+- lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey & 0xff;
+- else
+- lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
+-
+- VIAVidUpdateOverlay(pScrn, lpUpdateOverlay);
+-
+- viaXvError(pScrn, pPriv, xve_none);
+- return Success;
+-}
+-
+ static unsigned
+ viaSetupAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr ** adaptors)
+ {
+@@ -832,7 +702,7 @@
+ DevUnion *pdevUnion;
+ int i, j, usedPorts, numPorts;
+
+- DBG_DD(ErrorF(" via_video.c : viaSetupImageVideo: \n"));
++ DBG_DD(ErrorF(" via_video.c : viaSetupAdaptors (viaSetupImageVideo): \n"));
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+@@ -884,7 +754,7 @@
+ viaAdaptPtr[i]->GetPortAttribute = viaGetPortAttribute;
+ viaAdaptPtr[i]->SetPortAttribute = viaSetPortAttribute;
+ viaAdaptPtr[i]->PutImage = viaPutImage;
+- viaAdaptPtr[i]->ReputImage = viaReputImage;
++ viaAdaptPtr[i]->ReputImage = NULL;
+ viaAdaptPtr[i]->QueryImageAttributes = viaQueryImageAttributes;
+ for (j = 0; j < numPorts; ++j) {
+ viaPortPriv[j].dmaBounceBuffer = NULL;
+@@ -931,7 +801,7 @@
+ if (exit) {
+ ViaSwovSurfaceDestroy(pScrn, pPriv);
+ if (pPriv->dmaBounceBuffer)
+- xfree(pPriv->dmaBounceBuffer);
++ free(pPriv->dmaBounceBuffer);
+ pPriv->dmaBounceBuffer = 0;
+ pPriv->dmaBounceStride = 0;
+ pPriv->dmaBounceLines = 0;
+@@ -1042,6 +912,8 @@
+ }
+
+ } else {
++ DBG_DD(ErrorF(" via_video.c : viaGetPortAttribute : is not supported the attribute\n"));
++
+ /*return BadMatch */;
+ }
+ return Success;
+@@ -1070,6 +942,7 @@
+ unsigned long DisplayBufferIndex)
+ {
+ unsigned long proReg = 0;
++ unsigned count = 50000;
+
+ if (pVia->ChipId == PCI_CHIP_VT3259
+ && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
+@@ -1081,7 +954,8 @@
+ case FOURCC_RV15:
+ case FOURCC_RV16:
+ case FOURCC_RV32:
+- while ((VIDInD(HQV_CONTROL + proReg) & HQV_SW_FLIP));
++ while ((VIDInD(HQV_CONTROL + proReg) & HQV_SW_FLIP)
++ && --count);
+ VIDOutD(HQV_SRC_STARTADDR_Y + proReg,
+ pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
+ VIDOutD(HQV_CONTROL + proReg,
+@@ -1090,7 +964,8 @@
+ break;
+ case FOURCC_YV12:
+ default:
+- while ((VIDInD(HQV_CONTROL + proReg) & HQV_SW_FLIP));
++ while ((VIDInD(HQV_CONTROL + proReg) & HQV_SW_FLIP)
++ && --count);
+ VIDOutD(HQV_SRC_STARTADDR_Y + proReg,
+ pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
+ if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
+@@ -1174,7 +1049,7 @@
+ pPort->dmaBounceStride != bounceStride ||
+ pPort->dmaBounceLines != bounceLines) {
+ if (pPort->dmaBounceBuffer) {
+- xfree(pPort->dmaBounceBuffer);
++ free(pPort->dmaBounceBuffer);
+ pPort->dmaBounceBuffer = 0;
+ }
+ size = bounceStride * bounceLines + 16;
+@@ -1296,7 +1171,7 @@
+ unsigned long retCode;
+
+ # ifdef XV_DEBUG
+- ErrorF(" via_video.c : viaPutImage : called\n");
++ ErrorF(" via_video.c : viaPutImage : called, Screen[%d]\n", pScrn->scrnIndex);
+ ErrorF(" via_video.c : FourCC=0x%x width=%d height=%d sync=%d\n", id,
+ width, height, sync);
+ ErrorF
+@@ -1405,12 +1280,11 @@
+
+ lpUpdateOverlay->dwFlags = DDOVER_KEYDEST;
+
+- if (pScrn->bitsPerPixel == 8)
+- lpUpdateOverlay->dwColorSpaceLowValue =
+- pPriv->colorKey & 0xff;
+- else
+- lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
+-
++ if (pScrn->bitsPerPixel == 8) {
++ lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey & 0xff;
++ } else {
++ lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
++ }
+ /* If use extend FIFO mode */
+ if (pScrn->currentMode->HDisplay > 1024) {
+ dwUseExtendedFIFO = 1;
+@@ -1436,7 +1310,8 @@
+ && (pPriv->old_src_w == src_w) && (pPriv->old_src_h == src_h)
+ && (pVia->old_dwUseExtendedFIFO == dwUseExtendedFIFO)
+ && (pVia->VideoStatus & VIDEO_SWOV_ON) &&
+- RegionsEqual(&pPriv->clip, clipBoxes)) {
++ REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
++ DBG_DD(ErrorF(" via_video.c : don't do UpdateOverlay! \n"));
+ viaXvError(pScrn, pPriv, xve_none);
+ return Success;
+ }
+@@ -1454,16 +1329,18 @@
+ pVia->VideoStatus |= VIDEO_SWOV_ON;
+
+ /* BitBlt: Draw the colorkey rectangle */
+- if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
++ if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+ if (pPriv->autoPaint) {
+ if (pDraw->type == DRAWABLE_WINDOW) {
+- viaPaintColorkey(pScrn, pPriv, clipBoxes, pDraw);
++ xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes);
++ DamageDamageRegion(pDraw, clipBoxes);
+ } else {
+- xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey,
+- clipBoxes);
++ xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
+ }
+ }
++ } else {
++ DBG_DD(ErrorF(" via_video.c : // No need to draw Colorkey!! \n"));
+ }
+ /*
+ * Update video overlay
+@@ -1498,6 +1375,7 @@
+
+ DBG_DD(ErrorF(" via_video.c : viaQueryImageAttributes : FourCC=0x%x, ",
+ id));
++ DBG_DD(ErrorF(" via_video.c : Screen[%d], w=%d, h=%d\n", pScrn->scrnIndex, *w, *h));
+
+ if ((!w) || (!h))
+ return 0;
+Index: src/via_lvds.c
+===================================================================
+--- src/via_lvds.c (revision 811)
++++ src/via_lvds.c (working copy)
+@@ -42,7 +42,7 @@
+ 2^13 X 0.0698uSec [1/14.318MHz] = 8192 X 0.0698uSec =572.1uSec
+ Timer = Counter x 572 uSec
+ 2. Note:
+- 0.0698 uSec is too small to compute for hardware. So we multify a
++ 0.0698 uSec is too small to compute for hardware. So we multiply a
+ reference value(2^13) to make it big enough to compute for hardware.
+ 3. Note:
+ The meaning of the TD0~TD3 are count of the clock.
+Index: src/via_video.h
+===================================================================
+--- src/via_video.h (revision 811)
++++ src/via_video.h (working copy)
+@@ -44,6 +44,10 @@
+
+ #define VIDEO_BPP 2
+
++
++#define V1_COMMAND_FIRE 0x80000000 /* V1 commands fire */
++#define V3_COMMAND_FIRE 0x40000000 /* V3 commands fire */
++
+ typedef struct
+ {
+ CARD32 interruptflag; /* 200 */
+@@ -89,7 +93,7 @@
+ CARD32 video3_ctl; /* 2a0 */
+ CARD32 video3_addr0; /* 2a4 */
+ CARD32 video3_addr1; /* 2a8 */
+- CARD32 video3_stribe; /* 2ac */
++ CARD32 video3_stride; /* 2ac */
+ CARD32 video3_hvstart; /* 2b0 */
+ CARD32 video3_size; /* 2b4 */
+ CARD32 v3alpha_fetch; /* 2b8 */
+Index: src/via_mode.c
+===================================================================
+--- src/via_mode.c (revision 811)
++++ src/via_mode.c (working copy)
+@@ -308,11 +308,14 @@
+ xf86MonPtr monPtr = NULL;
+
+ if (pVia->pI2CBus2)
+- monPtr = xf86DoEDID_DDC2(pScrn->scrnIndex, pVia->pI2CBus2);
++ monPtr = xf86DoEEDID(pScrn->scrnIndex, pVia->pI2CBus2, TRUE);
+
+ if (monPtr) {
+ xf86PrintEDID(monPtr);
+ xf86SetDDCproperties(pScrn, monPtr);
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
++ "DDC pI2CBus2 detected a %s\n", DIGITAL(monPtr->features.input_type) ?
++ "DFP" : "CRT"));
+ return TRUE;
+ } else {
+ return FALSE;
+@@ -380,6 +383,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (ViaDFPDetect(pScrn)) {
+ pBIOSInfo->DfpPresent = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+@@ -514,6 +518,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ pVia->pBIOSInfo->Lvds->IsActive = TRUE ;
+ break;
+ }
+@@ -859,6 +864,9 @@
+ case VIA_MEM_DDR533:
+ case VIA_MEM_DDR667:
+ return VIA_BW_DDR667;
++ case VIA_MEM_DDR800:
++ case VIA_MEM_DDR1066:
++ return VIA_BW_DDR1066;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "ViaBandwidthAllowed: Unknown memory type: %d\n", pVia->MemClk);
+@@ -999,8 +1007,8 @@
+ dn = pll.params.dn;
+ dm = pll.params.dm;
+
+- /* The VX855 does not modify dm/dn, but earlier chipsets do. */
+- if (pVia->Chipset != VIA_VX855) {
++ /* The VX855 and VX900 do not modify dm/dn, but earlier chipsets do. */
++ if ((pVia->Chipset != VIA_VX855) && (pVia->Chipset != VIA_VX900)) {
+ dm -= 2;
+ dn -= 2;
+ }
+@@ -1078,7 +1086,7 @@
+ pBIOSInfo->Clock = Table.InitTb.LCDClk_12Bit;
+ else {
+ pBIOSInfo->Clock = Table.InitTb.VClk_12Bit;
+- /* for some reason still to be defined this is neccessary */
++ /* for some reason still to be defined this is necessary */
+ ViaSetSecondaryDotclock(pScrn, Table.InitTb.LCDClk_12Bit);
+ }
+ } else {
+@@ -1708,7 +1716,7 @@
+ ViaModeSecondCRTC(pScrn, mode);
+ ViaSecondDisplayChannelEnable(pScrn);
+ }
+-
++
+ if (pBIOSInfo->FirstCRTC->IsActive) {
+ if (pBIOSInfo->CrtActive) {
+ /* CRT on FirstCRTC */
+@@ -1734,6 +1742,15 @@
+ ViaDisplayDisableCRT(pScrn);
+ }
+
++ // Enable panel support on VM800, K8M800 and VX900 chipset
++ // See: https://bugs.launchpad.net/openchrome/+bug/186103
++ if (pBIOSInfo->Panel->IsActive &&
++ ((pVia->Chipset == VIA_VM800) ||
++ (pVia->Chipset == VIA_K8M800) ||
++ (pVia->Chipset == VIA_VX900) )) {
++ pBIOSInfo->FirstCRTC->IsActive=TRUE;
++ ViaModeFirstCRTC(pScrn, mode);
++ }
+ if (pBIOSInfo->Simultaneous->IsActive) {
+ ViaDisplayEnableSimultaneous(pScrn);
+ } else {
+Index: src/via_mode.h
+===================================================================
+--- src/via_mode.h (revision 811)
++++ src/via_mode.h (working copy)
+@@ -32,8 +32,9 @@
+ */
+ #define VIA_BW_MIN 74000000 /* > 640x480@60Hz@32bpp */
+ #define VIA_BW_DDR200 394000000
+-#define VIA_BW_DDR400 498000000 /* > 1920x1080@60Hz@32bpp */
++#define VIA_BW_DDR400 553000000 /* > 1920x1200@60Hz@32bpp */
+ #define VIA_BW_DDR667 922000000
++#define VIA_BW_DDR1066 922000000
+
+ union pllparams {
+ struct {
+@@ -54,50 +55,50 @@
+ CARD16 UniChrome;
+ union pllparams UniChromePro;
+ } ViaDotClocks[] = {
+- { 25200, 0x513C, /* 0xa79004 */ { 1, 4, 6, 169 } },
+- { 25312, 0xC763, /* 0xc49005 */ { 1, 4, 7, 198 } },
+- { 26591, 0x471A, /* 0xce9005 */ { 1, 4, 7, 208 } },
+- { 31500, 0xC558, /* 0xae9003 */ { 1, 4, 5, 176 } },
+- { 31704, 0x471F, /* 0xaf9002 */ { 1, 4, 4, 177 } },
+- { 32663, 0xC449, /* 0x479000 */ { 1, 4, 2, 73 } },
+- { 33750, 0x4721, /* 0x959002 */ { 1, 4, 4, 151 } },
+- { 35500, 0x5877, /* 0x759001 */ { 1, 4, 3, 119 } },
+- { 36000, 0x5879, /* 0x9f9002 */ { 1, 4, 4, 161 } },
+- { 39822, 0xC459, /* 0x578c02 */ { 1, 3, 4, 89 } },
+- { 40000, 0x515F, /* 0x848c04 */ { 1, 3, 6, 134 } },
+- { 41164, 0x4417, /* 0x2c8c00 */ { 1, 3, 2, 46 } },
+- { 46981, 0x5069, /* 0x678c02 */ { 1, 3, 4, 105 } },
+- { 49500, 0xC353, /* 0xa48c04 */ { 3, 3, 5, 138 } },
+- { 50000, 0xC354, /* 0x368c00 */ { 1, 3, 2, 56 } },
+- { 56300, 0x4F76, /* 0x3d8c00 */ { 1, 3, 2, 63 } },
+- { 57275, 0, /* 0x3e8c00 */ { 1, 3, 5, 157 } }, /* For XO 1.5 no need for a unichrome clock */
+- { 57284, 0x4E70, /* 0x3e8c00 */ { 1, 3, 2, 64 } },
+- { 64995, 0x0D3B, /* 0x6b8c01 */ { 1, 3, 3, 109 } },
+- { 65000, 0x0D3B, /* 0x6b8c01 */ { 1, 3, 3, 109 } }, /* Slightly unstable on PM800 */
+- { 65028, 0x866D, /* 0x6b8c01 */ { 1, 3, 3, 109 } },
+- { 74480, 0x156E, /* 0x288800 */ { 1, 2, 2, 42 } },
+- { 75000, 0x156E, /* 0x288800 */ { 1, 2, 2, 42 } },
+- { 78800, 0x442C, /* 0x2a8800 */ { 1, 2, 2, 44 } },
+- { 81135, 0x0622, /* 0x428801 */ { 1, 2, 3, 68 } },
+- { 81613, 0x4539, /* 0x708803 */ { 1, 2, 5, 114 } },
+- { 94500, 0x4542, /* 0x4d8801 */ { 1, 2, 3, 79 } },
+- { 108000, 0x0B53, /* 0x778802 */ { 1, 2, 4, 121 } },
+- { 108280, 0x4879, /* 0x778802 */ { 1, 2, 4, 121 } },
+- { 122000, 0x0D6F, /* 0x428800 */ { 1, 2, 2, 68 } },
+- { 122726, 0x073C, /* 0x878802 */ { 1, 2, 4, 137 } },
+- { 135000, 0x0742, /* 0x6f8801 */ { 1, 2, 3, 113 } },
+- { 148500, 0x0853, /* 0x518800 */ { 1, 2, 2, 83 } },
+- { 155800, 0x0857, /* 0x558402 */ { 1, 1, 4, 87 } },
+- { 157500, 0x422C, /* 0x2a8400 */ { 1, 1, 2, 44 } },
+- { 161793, 0x4571, /* 0x6f8403 */ { 1, 1, 5, 113 } },
+- { 162000, 0x0A71, /* 0x6f8403 */ { 1, 1, 5, 113 } },
+- { 175500, 0x4231, /* 0x2f8400 */ { 1, 1, 2, 49 } },
+- { 189000, 0x0542, /* 0x4d8401 */ { 1, 1, 3, 79 } },
+- { 202500, 0x0763, /* 0x6F8402 */ { 1, 1, 4, 113 } },
+- { 204800, 0x0764, /* 0x548401 */ { 1, 1, 3, 86 } },
+- { 218300, 0x043D, /* 0x3b8400 */ { 1, 1, 2, 61 } },
+- { 229500, 0x0660, /* 0x3e8400 */ { 1, 1, 2, 64 } }, /* Not tested on Pro } */
+- { 0, 0, { 0, 0, 0, 0 } }
++ { 25200, 0x513C, /* 0xa79004 */ { { 1, 4, 6, 169 } } },
++ { 25312, 0xC763, /* 0xc49005 */ { { 1, 4, 7, 198 } } },
++ { 26591, 0x471A, /* 0xce9005 */ { { 1, 4, 7, 208 } } },
++ { 31500, 0xC558, /* 0xae9003 */ { { 1, 4, 5, 176 } } },
++ { 31704, 0x471F, /* 0xaf9002 */ { { 1, 4, 4, 177 } } },
++ { 32663, 0xC449, /* 0x479000 */ { { 1, 4, 2, 73 } } },
++ { 33750, 0x4721, /* 0x959002 */ { { 1, 4, 4, 151 } } },
++ { 35500, 0x5877, /* 0x759001 */ { { 1, 4, 3, 119 } } },
++ { 36000, 0x5879, /* 0x9f9002 */ { { 1, 4, 4, 161 } } },
++ { 39822, 0xC459, /* 0x578c02 */ { { 1, 3, 4, 89 } } },
++ { 40000, 0x515F, /* 0x848c04 */ { { 1, 3, 6, 134 } } },
++ { 41164, 0x4417, /* 0x2c8c00 */ { { 1, 3, 2, 46 } } },
++ { 46981, 0x5069, /* 0x678c02 */ { { 1, 3, 4, 105 } } },
++ { 49500, 0xC353, /* 0xa48c04 */ { { 3, 3, 5, 138 } } },
++ { 50000, 0xC354, /* 0x368c00 */ { { 1, 3, 2, 56 } } },
++ { 56300, 0x4F76, /* 0x3d8c00 */ { { 1, 3, 2, 63 } } },
++ { 57275, 0, /* 0x3e8c00 */ { { 1, 3, 5, 157 } } }, /* For XO 1.5 no need for a unichrome clock */
++ { 57284, 0x4E70, /* 0x3e8c00 */ { { 1, 3, 2, 64 } } },
++ { 64995, 0x0D3B, /* 0x6b8c01 */ { { 1, 3, 3, 109 } } },
++ { 65000, 0x0D3B, /* 0x6b8c01 */ { { 1, 3, 3, 109 } } }, /* Slightly unstable on PM800 */
++ { 65028, 0x866D, /* 0x6b8c01 */ { { 1, 3, 3, 109 } } },
++ { 74480, 0x156E, /* 0x288800 */ { { 1, 2, 2, 42 } } },
++ { 75000, 0x156E, /* 0x288800 */ { { 1, 2, 2, 42 } } },
++ { 78800, 0x442C, /* 0x2a8800 */ { { 1, 2, 2, 44 } } },
++ { 81135, 0x0622, /* 0x428801 */ { { 1, 2, 3, 68 } } },
++ { 81613, 0x4539, /* 0x708803 */ { { 1, 2, 5, 114 } } },
++ { 94500, 0x4542, /* 0x4d8801 */ { { 1, 2, 3, 79 } } },
++ { 108000, 0x0B53, /* 0x778802 */ { { 1, 2, 4, 121 } } },
++ { 108280, 0x4879, /* 0x778802 */ { { 1, 2, 4, 121 } } },
++ { 122000, 0x0D6F, /* 0x428800 */ { { 1, 2, 2, 68 } } },
++ { 122726, 0x073C, /* 0x878802 */ { { 1, 2, 4, 137 } } },
++ { 135000, 0x0742, /* 0x6f8801 */ { { 1, 2, 3, 113 } } },
++ { 148500, 0x0853, /* 0x518800 */ { { 1, 2, 2, 83 } } },
++ { 155800, 0x0857, /* 0x558402 */ { { 1, 1, 4, 87 } } },
++ { 157500, 0x422C, /* 0x2a8400 */ { { 1, 1, 2, 44 } } },
++ { 161793, 0x4571, /* 0x6f8403 */ { { 1, 1, 5, 113 } } },
++ { 162000, 0x0A71, /* 0x6f8403 */ { { 1, 1, 5, 113 } } },
++ { 175500, 0x4231, /* 0x2f8400 */ { { 1, 1, 2, 49 } } },
++ { 189000, 0x0542, /* 0x4d8401 */ { { 1, 1, 3, 79 } } },
++ { 202500, 0x0763, /* 0x6F8402 */ { { 1, 1, 4, 113 } } },
++ { 204800, 0x0764, /* 0x548401 */ { { 1, 1, 3, 86 } } },
++ { 218300, 0x043D, /* 0x3b8400 */ { { 1, 1, 2, 61 } } },
++ { 229500, 0x0660, /* 0x3e8400 */ { { 1, 1, 2, 64 } } }, /* Not tested on Pro } */
++ { 0, 0, { { 0, 0, 0, 0 } } }
+ };
+
+ /*
+@@ -131,7 +132,7 @@
+ { MODEPREFIX("856x480"), 31704, 856, 872, 960, 1064, 0, 480, 480, 483, 497, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
+ { MODEPREFIX("1024x512"), 41164, 1024, 1056, 1160, 1296, 0, 512, 512, 515, 531, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
+ { MODEPREFIX("1024x576"), 46981, 1024, 1064, 1168, 1312, 0, 576, 576, 579, 597, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
+- { MODEPREFIX("1024x600"), 48960, 1024, 1064, 1168, 1312, 0, 600, 601, 604, 622, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
++ { MODEPREFIX("1024x600"), 48960, 1024, 1048, 1152, 1312, 0, 600, 601, 604, 630, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
+ { MODEPREFIX("1024x768"), 65028, 1024, 1048, 1184, 1344, 0, 768, 770, 776, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX },
+ { MODEPREFIX("1152x864"), 81613, 1152, 1216, 1336, 1520, 0, 864, 864, 867, 895, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX },
+ { MODEPREFIX("1280x768"), 81135, 1280, 1328, 1440, 1688, 0, 768, 770, 776, 802, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX },
+Index: src/via_memcpy.c
+===================================================================
+--- src/via_memcpy.c (revision 811)
++++ src/via_memcpy.c (working copy)
+@@ -581,12 +581,12 @@
+
+ if (VIAAllocLinear(&tmpFbBuffer, pScrn, alignSize + 31))
+ return libc_YUV42X;
+- if (NULL == (buf2 = (unsigned char *)xalloc(testSize))) {
++ if (NULL == (buf2 = (unsigned char *)malloc(testSize))) {
+ VIAFreeLinear(&tmpFbBuffer);
+ return libc_YUV42X;
+ }
+- if (NULL == (buf3 = (unsigned char *)xalloc(testSize))) {
+- xfree(buf2);
++ if (NULL == (buf3 = (unsigned char *)malloc(testSize))) {
++ free(buf2);
+ VIAFreeLinear(&tmpFbBuffer);
+ return libc_YUV42X;
+ }
+@@ -642,8 +642,8 @@
+ curData->mName);
+ }
+ }
+- xfree(buf3);
+- xfree(buf2);
++ free(buf3);
++ free(buf2);
+ VIAFreeLinear(&tmpFbBuffer);
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Using %s YUV42X copy for %s.\n",
+Index: src/via_driver.c
+===================================================================
+--- src/via_driver.c (revision 811)
++++ src/via_driver.c (working copy)
+@@ -143,6 +143,7 @@
+ VIA_DEVICE_MATCH (PCI_CHIP_VT3327, 0 ),
+ VIA_DEVICE_MATCH (PCI_CHIP_VT3353, 0 ),
+ VIA_DEVICE_MATCH (PCI_CHIP_VT3409, 0 ),
++ VIA_DEVICE_MATCH (PCI_CHIP_VT3410, 0 ),
+ { 0, 0, 0 },
+ };
+
+@@ -174,12 +175,13 @@
+ {VIA_K8M800, "K8M800/K8N800"},
+ {VIA_PM800, "PM800/PM880/CN400"},
+ {VIA_VM800, "VM800/P4M800Pro/VN800/CN700"},
++ {VIA_CX700, "CX700/VX700"},
+ {VIA_K8M890, "K8M890/K8N890"},
++ {VIA_P4M890, "P4M890"},
+ {VIA_P4M900, "P4M900/VN896/CN896"},
+- {VIA_CX700, "CX700/VX700"},
+- {VIA_P4M890, "P4M890"},
+- {VIA_VX800, "VX800"},
+- {VIA_VX855, "VX855"},
++ {VIA_VX800, "VX800/VX820"},
++ {VIA_VX855, "VX855/VX875"},
++ {VIA_VX900, "VX900"},
+ {-1, NULL }
+ };
+
+@@ -190,12 +192,13 @@
+ {VIA_K8M800, PCI_CHIP_VT3204, VIA_RES_SHARED},
+ {VIA_PM800, PCI_CHIP_VT3259, VIA_RES_SHARED},
+ {VIA_VM800, PCI_CHIP_VT3314, VIA_RES_SHARED},
++ {VIA_CX700, PCI_CHIP_VT3324, VIA_RES_SHARED},
+ {VIA_K8M890, PCI_CHIP_VT3336, VIA_RES_SHARED},
++ {VIA_P4M890, PCI_CHIP_VT3327, VIA_RES_SHARED},
+ {VIA_P4M900, PCI_CHIP_VT3364, VIA_RES_SHARED},
+- {VIA_CX700, PCI_CHIP_VT3324, VIA_RES_SHARED},
+- {VIA_P4M890, PCI_CHIP_VT3327, VIA_RES_SHARED},
+ {VIA_VX800, PCI_CHIP_VT3353, VIA_RES_SHARED},
+ {VIA_VX855, PCI_CHIP_VT3409, VIA_RES_SHARED},
++ {VIA_VX900, PCI_CHIP_VT3410, VIA_RES_SHARED},
+ {-1, -1, VIA_RES_UNDEF}
+ };
+
+@@ -215,9 +218,11 @@
+ OPTION_EXA_SCRATCH_SIZE,
+ OPTION_SWCURSOR,
+ OPTION_SHADOW_FB,
++ OPTION_ROTATION_TYPE,
+ OPTION_ROTATE,
+ OPTION_VIDEORAM,
+ OPTION_ACTIVEDEVICE,
++ OPTION_I2CDEVICES,
+ OPTION_BUSWIDTH,
+ OPTION_CENTER,
+ OPTION_PANELSIZE,
+@@ -253,6 +258,7 @@
+ {OPTION_EXA_SCRATCH_SIZE, "ExaScratchSize", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
++ {OPTION_ROTATION_TYPE, "RotationType", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_VIDEORAM, "VideoRAM", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_ACTIVEDEVICE, "ActiveDevice", OPTV_ANYSTR, {0}, FALSE},
+@@ -276,6 +282,7 @@
+ {OPTION_MODE_SWITCH_METHOD, "ModeSwitchMethod", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_MAX_DRIMEM, "MaxDRIMem", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_AGPMEM, "AGPMem", OPTV_INTEGER, {0}, FALSE},
++ {OPTION_I2CDEVICES, "I2CDevices", OPTV_ANYSTR, {0}, FALSE},
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+ };
+
+@@ -307,6 +314,7 @@
+ {
+ static Bool setupDone = FALSE;
+
++ /* Only be loaded once */
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&VIA, module,
+@@ -339,6 +347,7 @@
+ if (pScrn->driverPrivate)
+ return TRUE;
+
++ /* allocate VIARec */
+ pScrn->driverPrivate = xnfcalloc(sizeof(VIARec), 1);
+ VIAPtr pVia = ((VIARec *) (pScrn->driverPrivate));
+
+@@ -400,36 +409,36 @@
+
+ if (pBIOSInfo->Panel) {
+ if (pBIOSInfo->Panel->NativeMode)
+- xfree(pBIOSInfo->Panel->NativeMode);
++ free(pBIOSInfo->Panel->NativeMode);
+ if (pBIOSInfo->Panel->CenteredMode)
+- xfree(pBIOSInfo->Panel->CenteredMode);
+- xfree(pBIOSInfo->Panel);
++ free(pBIOSInfo->Panel->CenteredMode);
++ free(pBIOSInfo->Panel);
+ }
+
+ if (pBIOSInfo->FirstCRTC)
+- xfree(pBIOSInfo->FirstCRTC);
++ free(pBIOSInfo->FirstCRTC);
+ if (pBIOSInfo->SecondCRTC)
+- xfree(pBIOSInfo->SecondCRTC);
++ free(pBIOSInfo->SecondCRTC);
+ if (pBIOSInfo->Simultaneous)
+- xfree(pBIOSInfo->Simultaneous);
++ free(pBIOSInfo->Simultaneous);
+ if (pBIOSInfo->Lvds)
+- xfree(pBIOSInfo->Lvds);
++ free(pBIOSInfo->Lvds);
+ }
+
+ if (VIAPTR(pScrn)->pVbe)
+ vbeFree(VIAPTR(pScrn)->pVbe);
+
+ if (pVia->VideoRegs)
+- xfree(pVia->VideoRegs);
++ free(pVia->VideoRegs);
+
+ if (((VIARec *) (pScrn->driverPrivate))->pBIOSInfo->TVI2CDev)
+ xf86DestroyI2CDevRec((((VIARec *) (pScrn->driverPrivate))->pBIOSInfo->
+ TVI2CDev), TRUE);
+- xfree(((VIARec *) (pScrn->driverPrivate))->pBIOSInfo);
++ free(((VIARec *) (pScrn->driverPrivate))->pBIOSInfo);
+
+ VIAUnmapMem(pScrn);
+
+- xfree(pScrn->driverPrivate);
++ free(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+ } /* VIAFreeRec */
+
+@@ -455,7 +464,6 @@
+ {
+ ScrnInfoPtr scrn = NULL;
+ EntityInfoPtr entity;
+- DevUnion *private;
+
+ scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VIAPciChipsets,
+ NULL, NULL, NULL, NULL, NULL);
+@@ -513,7 +521,7 @@
+ numDevSections,
+ drv,
+ &usedChips);
+- xfree(devSections);
++ free(devSections);
+
+ if (numUsed <= 0)
+ return FALSE;
+@@ -588,11 +596,11 @@
+ }
+ instance++;
+ }
+- xfree(pEnt);
++ free(pEnt);
+ }
+ }
+
+- xfree(usedChips);
++ free(usedChips);
+
+ return foundScreen;
+
+@@ -652,6 +660,12 @@
+ vbeInfoPtr pVbe;
+
+ if (xf86LoadSubModule(pScrn, "vbe")) {
++ /* FIXME This line should be replaced with:
++
++ pVbe = VBEExtendedInit(NULL, index, 0);
++
++ for XF86 version > 4.2.99
++ */
+ pVbe = VBEInit(NULL, index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+@@ -664,7 +678,7 @@
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+- DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIASetupDefaultOptions\n"));
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIASetupDefaultOptions - Setting up default chipset options.\n"));
+
+ pVia->shadowFB = FALSE;
+ pVia->NoAccel = FALSE;
+@@ -684,10 +698,14 @@
+ pVia->maxDriSize = 0;
+ pVia->agpMem = AGP_SIZE / 1024;
+ pVia->ActiveDevice = 0x00;
++ pVia->I2CDevices = 0x00;
+ pVia->VideoEngine = VIDEO_ENGINE_CLE;
+ #ifdef HAVE_DEBUG
+ pVia->PrintVGARegs = FALSE;
+ #endif
++
++ /* Disable vertical interpolation because the size of */
++ /* line buffer (limited to 800) is too small to do interpolation. */
+ pVia->swov.maxWInterp = 800;
+ pVia->swov.maxHInterp = 600;
+ pVia->useLegacyVBE = TRUE;
+@@ -710,20 +728,30 @@
+ break;
+ case VIA_K8M800:
+ pVia->DRIIrqEnable = FALSE;
+- pVia->UseLegacyModeSwitch = TRUE;
+ break;
+ case VIA_PM800:
++ /* Use new mode switch to resolve many resolution and display bugs (switch to console) */
++ /* FIXME The video playing (XV) is not working correctly after turn on new mode switch */
+ pVia->VideoEngine = VIDEO_ENGINE_CME;
+- pVia->UseLegacyModeSwitch = TRUE;
+ break;
+ case VIA_VM800:
+- pVia->UseLegacyModeSwitch = TRUE;
++ /* New mode switch resolve bug with gamma set #282 */
++ /* and with Xv after hibernate #240 */
+ break;
++ case VIA_CX700:
++ pVia->VideoEngine = VIDEO_ENGINE_CME;
++ pVia->swov.maxWInterp = 1920;
++ pVia->swov.maxHInterp = 1080;
++ break;
+ case VIA_K8M890:
+ pVia->VideoEngine = VIDEO_ENGINE_CME;
+ pVia->agpEnable = FALSE;
+ pVia->dmaXV = FALSE;
+ break;
++ case VIA_P4M890:
++ pVia->VideoEngine = VIDEO_ENGINE_CME;
++ pVia->dmaXV = FALSE;
++ break;
+ case VIA_P4M900:
+ pVia->VideoEngine = VIDEO_ENGINE_CME;
+ pVia->agpEnable = FALSE;
+@@ -732,20 +760,13 @@
+ pVia->dmaXV = FALSE;
+ pBIOSInfo->TVDIPort = VIA_DI_PORT_DVP0;
+ break;
+- case VIA_CX700:
+- pVia->VideoEngine = VIDEO_ENGINE_CME;
+- pVia->swov.maxWInterp = 1920;
+- pVia->swov.maxHInterp = 1080;
+- break;
+- case VIA_P4M890:
+- pVia->VideoEngine = VIDEO_ENGINE_CME;
+- pVia->dmaXV = FALSE;
+- break;
++
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ pVia->VideoEngine = VIDEO_ENGINE_CME;
+- /* pVia->agpEnable = FALSE;
+- pVia->dmaXV = FALSE;*/
++ pVia->agpEnable = FALSE;
++ pVia->dmaXV = FALSE;
+ break;
+ }
+
+@@ -807,7 +828,7 @@
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ #ifndef XSERVER_LIBPCIACCESS
+ if (pEnt->resources) {
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+@@ -825,7 +846,7 @@
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gVIAEntityIndex);
+ pVIAEnt = pPriv->ptr;
+ if (pVIAEnt->BypassSecondary) {
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+@@ -848,6 +869,7 @@
+ pVIAEnt->HasSecondary = FALSE;
+ pVIAEnt->RestorePrimary = FALSE;
+ pVIAEnt->IsSecondaryRestored = FALSE;
++
+ }
+ } else {
+ pVia->sharedData = xnfcalloc(sizeof(ViaSharedRec), 1);
+@@ -866,7 +888,7 @@
+ */
+
+ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ } else {
+@@ -881,7 +903,7 @@
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this driver\n",
+ pScrn->depth);
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+@@ -897,7 +919,7 @@
+ rgb zeros = { 0, 0, 0 };
+
+ if (!xf86SetWeight(pScrn, zeros, zeros)) {
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ } else {
+@@ -914,7 +936,7 @@
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
+ " (%s) is not supported at depth %d.\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+@@ -979,7 +1001,7 @@
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset revision: %d\n", pVia->ChipRev);
+
+- xfree(pEnt);
++ free(pEnt);
+
+ /* Detect the amount of installed RAM */
+ from = X_PROBED;
+@@ -993,6 +1015,12 @@
+
+ switch (pVia->Chipset) {
+ case VIA_CLE266:
++#ifdef XSERVER_LIBPCIACCESS
++ pci_device_cfg_read_u8(bridge, &videoRam, 0xE1);
++#else
++ videoRam = pciReadByte(pciTag(0, 0, 0), 0xE1) & 0x70;
++#endif
++ pScrn->videoRam = (1 << ((videoRam & 0x70) >> 4)) << 10;
+ case VIA_KM400:
+ #ifdef XSERVER_LIBPCIACCESS
+ pci_device_cfg_read_u8(bridge, &videoRam, 0xE1);
+@@ -1000,6 +1028,12 @@
+ videoRam = pciReadByte(pciTag(0, 0, 0), 0xE1) & 0x70;
+ #endif
+ pScrn->videoRam = (1 << ((videoRam & 0x70) >> 4)) << 10;
++ /* Workaround for #177 (VRAM probing fail on P4M800) */
++ if (pScrn->videoRam < 16384) {
++ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++ "Memory size detection failed: using 16 MB.\n");
++ pScrn->videoRam = 16 << 10;
++ }
+ break;
+ case VIA_PM800:
+ case VIA_VM800:
+@@ -1017,6 +1051,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ #ifdef XSERVER_LIBPCIACCESS
+ pci_device_cfg_read_u8(vgaDevice, &videoRam, 0xA1);
+ #else
+@@ -1046,23 +1081,18 @@
+ }
+ }
+
+- if (from == X_PROBED)
++ if (from == X_PROBED) {
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Probed amount of VideoRAM = %d kB\n", pScrn->videoRam);
++ }
+
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Setting up default chipset options.\n");
+ if (!VIASetupDefaultOptions(pScrn)) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reading config file...\n");
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, VIAOptions);
+
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Starting to parse config file options...\n");
+-
+ if (xf86GetOptValInteger(VIAOptions, OPTION_VIDEORAM, &pScrn->videoRam))
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Setting amount of VideoRAM to %d kB\n", pScrn->videoRam);
+@@ -1100,6 +1130,31 @@
+ }
+
+ /* When rotating, switch shadow framebuffer on and acceleration off. */
++ if ((s = xf86GetOptValString(VIAOptions, OPTION_ROTATION_TYPE))) {
++ if (!xf86NameCmp(s, "SWRandR")) {
++ pVia->shadowFB = TRUE;
++ pVia->NoAccel = TRUE;
++ pVia->RandRRotation = TRUE;
++ pVia->rotate = RR_Rotate_0;
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen "
++ "RandR enabled, acceleration disabled\n");
++ } else if (!xf86NameCmp(s, "HWRandR")) {
++ pVia->shadowFB = TRUE;
++ pVia->NoAccel = TRUE;
++ pVia->RandRRotation = TRUE;
++ pVia->rotate = RR_Rotate_0;
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Hardware accelerated "
++ "rotating screen is not implemented. Using SW RandR.\n");
++ } else {
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
++ "value for Option \"RotationType\".\n", s);
++ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++ "Valid options are \"SWRandR\" and \"HWRandR\".\n");
++ }
++ }
++
++
++ /* When rotating, switch shadow framebuffer on and acceleration off. */
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_ROTATE))) {
+ if (!xf86NameCmp(s, "CW")) {
+ pVia->shadowFB = TRUE;
+@@ -1498,6 +1553,7 @@
+ }
+ }
+
++ /* Initialize the colormap */
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+ if (!xf86SetGamma(pScrn, zeros)) {
+ VIAFreeRec(pScrn);
+@@ -1523,6 +1579,17 @@
+
+ pVia->videoRambytes = pScrn->videoRam << 10;
+
++ /* I2CDevices Option for I2C Initialization */
++ //pVia->I2CDevices = 0x00;
++ if ((s = xf86GetOptValString(VIAOptions, OPTION_I2CDEVICES))) {
++ if (strstr(s, "Bus1"))
++ pVia->I2CDevices |= VIA_I2C_BUS1;
++ if (strstr(s, "Bus2"))
++ pVia->I2CDevices |= VIA_I2C_BUS2;
++ if (strstr(s, "Bus3"))
++ pVia->I2CDevices |= VIA_I2C_BUS3;
++ }
++
+ if (!xf86LoadSubModule(pScrn, "i2c")) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+@@ -1536,10 +1603,13 @@
+ } else {
+
+ if (pVia->pI2CBus1) {
+- pVia->DDC1 = xf86DoEDID_DDC2(pScrn->scrnIndex, pVia->pI2CBus1);
++ pVia->DDC1 = xf86DoEEDID(pScrn->scrnIndex, pVia->pI2CBus1, TRUE);
+ if (pVia->DDC1) {
+ xf86PrintEDID(pVia->DDC1);
+ xf86SetDDCproperties(pScrn, pVia->DDC1);
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
++ "DDC pI2CBus1 detected a %s\n", DIGITAL(pVia->DDC1->features.input_type) ?
++ "DFP" : "CRT"));
+ }
+ }
+ }
+@@ -1559,17 +1629,6 @@
+ ViaPanelPreInit(pScrn);
+ }
+
+- if (pBIOSInfo->Panel->IsActive &&
+- ((pVia->Chipset == VIA_K8M800) ||
+- (pVia->Chipset == VIA_PM800) ||
+- (pVia->Chipset == VIA_VM800))) {
+- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Panel on K8M800, PM800 and "
+- "VM800 is currently not supported.\n");
+- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+- "Using VBE to set modes to work around this.\n");
+- pVia->useVBEModes = TRUE;
+- }
+-
+ pVia->pVbe = NULL;
+ if (pVia->useVBEModes) {
+ /* VBE doesn't properly initialise int10 itself. */
+@@ -1593,6 +1652,7 @@
+ }
+
+ } else {
++ int max_pitch, max_height;
+ /* Add own modes. */
+ ViaModesAttach(pScrn, pScrn->monitor);
+
+@@ -1609,6 +1669,26 @@
+ clockRanges->interlaceAllowed = TRUE;
+ clockRanges->doubleScanAllowed = FALSE;
+
++ switch (pVia->Chipset) {
++ case VIA_CLE266:
++ case VIA_KM400:
++ case VIA_K8M800:
++ case VIA_PM800:
++ case VIA_VM800:
++ max_pitch = 3344;
++ max_height = 2508;
++ case VIA_CX700:
++ case VIA_K8M890:
++ case VIA_P4M890:
++ case VIA_P4M900:
++ max_pitch = 8192/(pScrn->bitsPerPixel >> 3)-1;
++ max_height = max_pitch;
++ break;
++ default:
++ max_pitch = 16384/(pScrn->bitsPerPixel >> 3)-1;
++ max_height = max_pitch;
++ }
++
+ /*
+ * xf86ValidateModes will check that the mode HTotal and VTotal values
+ * don't exceed the chipset's limit if pScrn->maxHValue and
+@@ -1621,7 +1701,7 @@
+ *
+ * CLE266A: primary AdjustFrame can use only 24 bits, so we are limited
+ * to 12x11 bits; 4080x2048 (~2:1), 3344x2508 (4:3), or 2896x2896 (1:1).
+- * Test CLE266Cx, KM400, KM400A, K8M800, PM800, CN400 please.
++ * TODO Test CLE266Cx, KM400, KM400A, K8M800, CN400 please.
+ *
+ * We should be able to limit the memory available for a mode to 32 MB,
+ * but xf86ValidateModes (or miScanLineWidth) fails to catch this
+@@ -1629,15 +1709,16 @@
+ */
+
+ /* Select valid modes from those available. */
+- i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, /* availModes */
+- pScrn->display->modes, /* modeNames */
+- clockRanges, /* list of clock ranges */
++ i = xf86ValidateModes(pScrn,
++ pScrn->monitor->Modes, /* List of modes available for the monitor */
++ pScrn->display->modes, /* List of mode names that the screen is requesting */
++ clockRanges, /* list of clock ranges */
+ NULL, /* list of line pitches */
+ 256, /* minimum line pitch */
+- 3344, /* maximum line pitch */
+- 32 * 8, /* pitch inc (bits) */
+- 128, /* min height */
+- 2508, /* max height */
++ max_pitch, /* maximum line pitch */
++ 16 * 8, /* pitch increment (in bits), we just want 16 bytes alignment */
++ 128, /* min virtual height */
++ max_height, /* maximum virtual height */
+ pScrn->display->virtualX, /* virtual width */
+ pScrn->display->virtualY, /* virtual height */
+ pVia->videoRambytes, /* apertureSize */
+@@ -1650,6 +1731,7 @@
+ return FALSE;
+ }
+
++ /* This function deletes modes in the modes field of the ScrnInfoRec that have been marked as invalid. */
+ xf86PruneDriverModes(pScrn);
+
+ if (i == 0 || pScrn->modes == NULL) {
+@@ -1662,9 +1744,17 @@
+ /* Set up screen parameters. */
+ pVia->Bpp = pScrn->bitsPerPixel >> 3;
+ pVia->Bpl = pScrn->displayWidth * pVia->Bpp;
++
++ /* This function fills in the Crtc fields for all the modes in the modes field of the ScrnInfoRec. */
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
++
++ /* Set the current mode to the first in the list */
+ pScrn->currentMode = pScrn->modes;
++
++ /* Print the list of modes being used */
+ xf86PrintModes(pScrn);
++
++ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ #ifdef USE_FB
+@@ -1822,6 +1912,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40);
+@@ -1935,7 +2026,9 @@
+ Regs->SR17 = hwp->readSeq(hwp, 0x17);
+ Regs->SR18 = hwp->readSeq(hwp, 0x18);
+ Regs->SR19 = hwp->readSeq(hwp, 0x19);
++ /* PCI Bus Control */
+ Regs->SR1A = hwp->readSeq(hwp, 0x1A);
++
+ Regs->SR1B = hwp->readSeq(hwp, 0x1B);
+ Regs->SR1C = hwp->readSeq(hwp, 0x1C);
+ Regs->SR1D = hwp->readSeq(hwp, 0x1D);
+@@ -1977,40 +2070,59 @@
+ Regs->SR4C = hwp->readSeq(hwp, 0x4C);
+ break;
+ }
+- DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Non-Primary Adapter! saving VGA_SR_MODE only !!\n"));
++
++ /* Save Preemptive Arbiter Control Register */
++ Regs->SR4D = hwp->readSeq(hwp, 0x4D);
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Crtc...\n"));
+
+ Regs->CR13 = hwp->readCrtc(hwp, 0x13);
+
+ Regs->CR32 = hwp->readCrtc(hwp, 0x32);
+ Regs->CR33 = hwp->readCrtc(hwp, 0x33);
+- Regs->CR34 = hwp->readCrtc(hwp, 0x34);
++
+ Regs->CR35 = hwp->readCrtc(hwp, 0x35);
+ Regs->CR36 = hwp->readCrtc(hwp, 0x36);
+
++
++
++ /* Starting Address */
++ /* Start Address High */
++ Regs->CR0C = hwp->readCrtc(hwp, 0x0C);
++ /* Start Address Low */
++ Regs->CR0D = hwp->readCrtc(hwp, 0x0D);
++ /* Starting Address Overflow Bits[28:24] */
+ Regs->CR48 = hwp->readCrtc(hwp, 0x48);
++ /* CR34 are fire bits. Must be written after CR0C CR0D CR48. */
++ /* Starting Address Overflow Bits[23:16] */
++ Regs->CR34 = hwp->readCrtc(hwp, 0x34);
++
++
+ Regs->CR49 = hwp->readCrtc(hwp, 0x49);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TVSave...\n"));
+ if (pBIOSInfo->TVI2CDev)
+ ViaTVSave(pScrn);
+
+- /* Save LCD control registers. */
++ /* Save LCD control registers (from CR 0x50 to 0x93). */
+ for (i = 0; i < 68; i++)
+ Regs->CRTCRegs[i] = hwp->readCrtc(hwp, i + 0x50);
+
+ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
+-
+- Regs->CRA0 = hwp->readCrtc(hwp, 0xA0);
+- Regs->CRA1 = hwp->readCrtc(hwp, 0xA1);
+- Regs->CRA2 = hwp->readCrtc(hwp, 0xA2);
+-
++ /* LVDS Channel 2 Function Select 0 / DVI Function Select */
+ Regs->CR97 = hwp->readCrtc(hwp, 0x97);
++ /* LVDS Channel 1 Function Select 0 */
+ Regs->CR99 = hwp->readCrtc(hwp, 0x99);
++ /* Digital Video Port 1 Function Select 0 */
+ Regs->CR9B = hwp->readCrtc(hwp, 0x9B);
++ /* Power Now Control 4 */
+ Regs->CR9F = hwp->readCrtc(hwp, 0x9F);
+
++ /* Horizontal Scaling Initial Value */
++ Regs->CRA0 = hwp->readCrtc(hwp, 0xA0);
++ /* Vertical Scaling Initial Value */
++ Regs->CRA1 = hwp->readCrtc(hwp, 0xA1);
++ /* Scaling Enable Bit */
++ Regs->CRA2 = hwp->readCrtc(hwp, 0xA2);
+ }
+
+ /* Save TMDS status */
+@@ -2018,6 +2130,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ Regs->CRD2 = hwp->readCrtc(hwp, 0xD2);
+ break;
+ }
+@@ -2045,15 +2158,15 @@
+ /* Unlock extended registers. */
+ hwp->writeSeq(hwp, 0x10, 0x01);
+
+- /*=* CR6A, CR6B, CR6C must be reset before restore
+- standard vga regs, or system will be hang. *=*/
++ /*=* CR6A, CR6B, CR6C must be reset before restoring
++ standard vga regs, or system will hang. *=*/
+ /*=* TODO Check is reset IGA2 channel before disable IGA2 channel
+- is neccesery or it may cause some line garbage. *=*/
++ is necessary or it may cause some line garbage. *=*/
+ hwp->writeCrtc(hwp, 0x6A, 0x00);
+ hwp->writeCrtc(hwp, 0x6B, 0x00);
+ hwp->writeCrtc(hwp, 0x6C, 0x00);
+
+- /* Gamma must disable before restore pallette */
++ /* Gamma must be disabled before restoring palette */
+ ViaGammaDisable(pScrn);
+
+ if (pBIOSInfo->TVI2CDev)
+@@ -2098,11 +2211,19 @@
+ hwp->writeSeq(hwp, 0x45, Regs->SR45);
+ hwp->writeSeq(hwp, 0x46, Regs->SR46);
+
++ /* Reset VCK PLL */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x02); /* Set SR40[1] to 1 */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & 0xFD); /* Set SR40[1] to 0 */
++
+ /* ECK Clock Synthesizer: */
+ hwp->writeSeq(hwp, 0x47, Regs->SR47);
+ hwp->writeSeq(hwp, 0x48, Regs->SR48);
+ hwp->writeSeq(hwp, 0x49, Regs->SR49);
+
++ /* Reset ECK PLL */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x01); /* Set SR40[0] to 1 */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & 0xFE); /* Set SR40[0] to 0 */
++
+ switch (pVia->Chipset) {
+ case VIA_CLE266:
+ case VIA_KM400:
+@@ -2112,9 +2233,22 @@
+ hwp->writeSeq(hwp, 0x4A, Regs->SR4A);
+ hwp->writeSeq(hwp, 0x4B, Regs->SR4B);
+ hwp->writeSeq(hwp, 0x4C, Regs->SR4C);
++
++ /* Reset LCK PLL */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x04); /* Set SR40[2] to 1 */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & 0xFB); /* Set SR40[2] to 0 */
+ break;
+ }
+
++ /* Restore Preemptive Arbiter Control Register
++ * VX800 and VX855 should restore this register too,
++ * but I don't do that for I don't want to affect any
++ * chips now.
++ */
++ if (pVia->Chipset == VIA_VX900) {
++ hwp->writeSeq(hwp, 0x4D, Regs->SR4D);
++ }
++
+ /* Reset dotclocks. */
+ ViaSeqMask(hwp, 0x40, 0x06, 0x06);
+ ViaSeqMask(hwp, 0x40, 0x00, 0x06);
+@@ -2127,14 +2261,23 @@
+ hwp->writeCrtc(hwp, 0x32, Regs->CR32);
+ /* HSYNCH Adjuster */
+ hwp->writeCrtc(hwp, 0x33, Regs->CR33);
+- /* Starting Address Overflow */
+- hwp->writeCrtc(hwp, 0x34, Regs->CR34);
+ /* Extended Overflow */
+ hwp->writeCrtc(hwp, 0x35, Regs->CR35);
+ /*Power Management 3 (Monitor Control) */
+ hwp->writeCrtc(hwp, 0x36, Regs->CR36);
+
++ /* Starting Address */
++ /* Start Address High */
++ hwp->writeCrtc(hwp, 0x0C, Regs->CR0C);
++ /* Start Address Low */
++ hwp->writeCrtc(hwp, 0x0D, Regs->CR0D);
++ /* Starting Address Overflow Bits[28:24] */
+ hwp->writeCrtc(hwp, 0x48, Regs->CR48);
++ /* CR34 are fire bits. Must be written after CR0C CR0D CR48. */
++ /* Starting Address Overflow Bits[23:16] */
++ hwp->writeCrtc(hwp, 0x34, Regs->CR34);
++
++
+ hwp->writeCrtc(hwp, 0x49, Regs->CR49);
+
+ /* Restore LCD control registers. */
+@@ -2160,6 +2303,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ /* LVDS Control Register */
+ hwp->writeCrtc(hwp, 0xD2, Regs->CRD2);
+ break;
+@@ -2189,6 +2333,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ ViaSeqMask(hwp, 0x1A, 0x08, 0x08);
+ break;
+ default:
+@@ -2212,6 +2357,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ ViaSeqMask(hwp, 0x1A, 0x00, 0x08);
+ break;
+ default:
+@@ -2328,10 +2474,18 @@
+ VIAPtr pVia = VIAPTR(pScrn);
+
+ #ifdef XSERVER_LIBPCIACCESS
+- pVia->FrameBufferBase = pVia->PciInfo->regions[0].base_addr;
++ if (pVia->Chipset == VIA_VX900) {
++ pVia->FrameBufferBase = pVia->PciInfo->regions[2].base_addr;
++ } else {
++ pVia->FrameBufferBase = pVia->PciInfo->regions[0].base_addr;
++ }
+ int err;
+ #else
+- pVia->FrameBufferBase = pVia->PciInfo->memBase[0];
++ if (pVia->Chipset == VIA_VX900) {
++ pVia->FrameBufferBase = pVia->PciInfo->memBase[2];
++ } else {
++ pVia->FrameBufferBase = pVia->PciInfo->memBase[0];
++ }
+ #endif
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAMapFB\n"));
+@@ -2453,7 +2607,6 @@
+ VIALoadRgbLut(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
+ VisualPtr pVisual)
+ {
+- VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ int i, j, index;
+@@ -2844,7 +2997,7 @@
+
+ if (pVia->shadowFB) {
+ pVia->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
+- pVia->ShadowPtr = xalloc(pVia->ShadowPitch * shadowHeight);
++ pVia->ShadowPtr = malloc(pVia->ShadowPitch * shadowHeight);
+ displayWidth = pVia->ShadowPitch / (pScrn->bitsPerPixel >> 3);
+ FBStart = pVia->ShadowPtr;
+ } else {
+@@ -2880,7 +3033,6 @@
+ VIAWriteMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+- VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAWriteMode\n"));
+
+@@ -2917,6 +3069,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ /*
+ * Since we are using virtual, we need to adjust
+ * the offset to match the framebuffer alignment.
+@@ -2963,6 +3116,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default :
+ hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40);
+@@ -2986,11 +3140,11 @@
+
+ viaExitAccel(pScreen);
+ if (pVia->ShadowPtr) {
+- xfree(pVia->ShadowPtr);
++ free(pVia->ShadowPtr);
+ pVia->ShadowPtr = NULL;
+ }
+ if (pVia->DGAModes) {
+- xfree(pVia->DGAModes);
++ free(pVia->DGAModes);
+ pVia->DGAModes = NULL;
+ }
+
+@@ -3033,9 +3187,7 @@
+ VIAAdjustFrame(int scrnIndex, int x, int y, int flags)
+ {
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+- vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+- CARD32 Base;
+
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIAAdjustFrame %dx%d\n", x, y));
+
+@@ -3173,7 +3325,6 @@
+ static void
+ VIADPMS(ScrnInfoPtr pScrn, int mode, int flags)
+ {
+- vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+Index: src/via_crtc.c
+===================================================================
+--- src/via_crtc.c (revision 811)
++++ src/via_crtc.c (working copy)
+@@ -174,6 +174,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ ViaSeqMask(hwp, 0x16, 0x08, 0xBF);
+@@ -234,8 +235,8 @@
+ /* Primary starting address -> 0x00, adjustframe does the rest */
+ hwp->writeCrtc(hwp, 0x0C, 0x00);
+ hwp->writeCrtc(hwp, 0x0D, 0x00);
++ ViaCrtcMask(hwp, 0x48, 0x00, 0x03); /* is this even possible on CLE266A ? */
+ hwp->writeCrtc(hwp, 0x34, 0x00);
+- ViaCrtcMask(hwp, 0x48, 0x00, 0x03); /* is this even possible on CLE266A ? */
+
+ /* vertical sync start : 2047 */
+ temp = mode->CrtcVSyncStart;
+@@ -278,6 +279,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ /* some leftovers */
+@@ -314,6 +316,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ /* some leftovers */
+@@ -331,15 +334,20 @@
+ CARD32 Base;
+ CARD32 tmp;
+
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaFirstCRTCSetStartingAddress\n"));
++
+ Base = (y * pScrn->displayWidth + x) * (pScrn->bitsPerPixel / 8);
+ Base = Base >> 1;
+
+ hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8);
+ hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
++ /* FIXME The proper starting address for CR48 is 0x1F - Bits[28:24] */
++ if (!(pVia->Chipset == VIA_CLE266 && CLE266_REV_IS_AX(pVia->ChipRev)))
++ ViaCrtcMask(hwp, 0x48, Base >> 24, 0x0F);
++ /* CR34 are fire bits. Must be written after CR0C CR0D CR48. */
+ hwp->writeCrtc(hwp, 0x34, (Base & 0xFF0000) >> 16);
+
+- if (!(pVia->Chipset == VIA_CLE266 && CLE266_REV_IS_AX(pVia->ChipRev)))
+- ViaCrtcMask(hwp, 0x48, Base >> 24, 0x0F);
++
+ }
+
+ void
+@@ -434,6 +442,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ ViaSeqMask(hwp, 0x16, 0x08, 0xBF);
+@@ -518,6 +527,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ /* some leftovers */
+Index: src/via_swov.c
+===================================================================
+--- src/via_swov.c (revision 811)
++++ src/via_swov.c (working copy)
+@@ -65,6 +65,31 @@
+ #define IN_VIDEO_DISPLAY (*((unsigned long volatile *)(pVia->VidMapBase+V_FLAGS))&VBI_STATUS)
+ #define VIA_FIRETIMEOUT 40000
+
++enum HQV_CME_Regs {
++ HQV_SDO_CTRL1,
++ HQV_SDO_CTRL2,
++ HQV_SDO_CTRL3,
++ HQV_SDO_CTRL4
++};
++
++/* register offsets for VT3553/VX800 */
++static const unsigned hqv_cme_regs[] = {
++ [HQV_SDO_CTRL1] = HQV_SRC_DATA_OFFSET_CONTROL1,
++ [HQV_SDO_CTRL2] = HQV_SRC_DATA_OFFSET_CONTROL2,
++ [HQV_SDO_CTRL3] = HQV_SRC_DATA_OFFSET_CONTROL3,
++ [HQV_SDO_CTRL4] = HQV_SRC_DATA_OFFSET_CONTROL4
++};
++
++/* register hqv offsets for new VT3409/VX855 */
++static const unsigned hqv_cme_regs_409[] = {
++ [HQV_SDO_CTRL1] = HQV_SRC_DATA_OFFSET_CTRL1_409,
++ [HQV_SDO_CTRL2] = HQV_SRC_DATA_OFFSET_CTRL2_409,
++ [HQV_SDO_CTRL3] = HQV_SRC_DATA_OFFSET_CTRL3_409,
++ [HQV_SDO_CTRL4] = HQV_SRC_DATA_OFFSET_CTRL4_409
++};
++
++#define HQV_CME_REG(HWDiff, name) (HWDiff)->HQVCmeRegs[name]
++
+ static void
+ viaWaitVideoCommandFire(VIAPtr pVia)
+ {
+@@ -88,6 +113,7 @@
+ {
+ unsigned long proReg = 0;
+ CARD32 volatile *pdwState;
++ unsigned count = 50000;
+
+ if (pVia->ChipId == PCI_CHIP_VT3259
+ && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
+@@ -96,10 +122,9 @@
+ pdwState = (CARD32 volatile *)(pVia->VidMapBase + (HQV_CONTROL + proReg));
+
+ if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
+- // while (*pdwState & (HQV_SUBPIC_FLIP | HQV_SW_FLIP)) ;
+- while (*pdwState & HQV_SUBPIC_FLIP);
++ while (--count && (*pdwState & HQV_SUBPIC_FLIP));
+ } else {
+- while (!(*pdwState & HQV_FLIP_STATUS)) ;
++ while (--count && !(*pdwState & HQV_FLIP_STATUS)) ;
+ }
+ }
+
+@@ -109,8 +134,9 @@
+ CARD32 volatile *pdwState =
+ (CARD32 volatile *)(pVia->VidMapBase + HQV_CONTROL);
+ *pdwState = dwData;
++ unsigned count = 50000;
+
+- while ((*pdwState & HQV_FLIP_STATUS)) {
++ while (--count && (*pdwState & HQV_FLIP_STATUS)) {
+ VIDOutD(HQV_CONTROL, *pdwState | HQV_FLIP_STATUS);
+ }
+ }
+@@ -126,6 +152,7 @@
+ {
+ CARD32 volatile *pdwState;
+ unsigned long proReg = 0;
++ unsigned count = 50000;
+
+ if (pVia->ChipId == PCI_CHIP_VT3259
+ && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
+@@ -133,7 +160,7 @@
+
+ pdwState = (CARD32 volatile *)(pVia->VidMapBase + (HQV_CONTROL + proReg));
+ if (pVia->swov.MPEG_ON) {
+- while ((*pdwState & HQV_SW_FLIP)) ;
++ while (--count && (*pdwState & HQV_SW_FLIP)) ;
+ }
+ }
+
+@@ -179,12 +206,14 @@
+ static void
+ SaveVideoRegister(VIAPtr pVia, CARD32 index, CARD32 data)
+ {
++ if (pVia->VidRegCursor >= VIDREG_BUFFER_SIZE) {
++ DBG_DD(ErrorF("SaveVideoRegister: Out of video register space flushing"));
++ FlushVidRegBuffer(pVia);
++ ResetVidRegBuffer(pVia);
++ }
++
+ pVia->VidRegBuffer[pVia->VidRegCursor++] = index;
+ pVia->VidRegBuffer[pVia->VidRegCursor++] = data;
+-
+- if (pVia->VidRegCursor > VIDREG_BUFFER_SIZE) {
+- DBG_DD(ErrorF("SaveVideoRegister: Out of video register space"));
+- }
+ }
+
+ /*
+@@ -224,6 +253,7 @@
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
+ }
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
+ break;
+ case VIA_KM400:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -232,6 +262,7 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
+ break;
+ case VIA_K8M800:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -240,6 +271,7 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
+ break;
+ case VIA_PM800:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -248,6 +280,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_VM800:
+ case VIA_P4M900:
+@@ -257,6 +291,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_K8M890:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -265,6 +301,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_TRUE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_P4M890:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -273,6 +311,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_CX700:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -281,8 +321,19 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_VX800:
++ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
++ HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
++ HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
++ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
++ HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
++ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
++ break;
+ case VIA_VX855:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+ HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
+@@ -290,6 +341,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs_409;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+@@ -509,10 +562,12 @@
+ unsigned long *pMiniCtl,
+ unsigned long *pHQVfilterCtl,
+ unsigned long *pHQVminiCtl,
++ unsigned long *pHQVscaleCtlH,
+ unsigned long *pHQVzoomflag)
+ {
+ unsigned long tmp, sw1, d, falign, mdiv;
+ Bool zoom_ok = TRUE;
++ VIAHWDiff *hwDiff = &pVia->HWDiff;
+
+ CARD32 HQVfilter[5] = { HQV_H_FILTER_DEFAULT, HQV_H_TAP4_121,
+ HQV_H_TAP4_121, HQV_H_TAP8_12221, HQV_H_TAP8_12221
+@@ -525,24 +580,57 @@
+ if (srcWidth == dstWidth) { /* No zoom */
+ *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
+ } else if (srcWidth < dstWidth) { /* Zoom in */
++ *pZoomCtl &= 0x0000FFFF;
++ tmp = srcWidth * 0x800 / dstWidth;
++ *pZoomCtl |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
++ *pMiniCtl |= V1_X_INTERPOLY;
++ zoom_ok = !(tmp > 0x7ff);
+
+- tmp = srcWidth * 0x800 / dstWidth;
+- *pZoomCtl = ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
+- *pMiniCtl |= V1_X_INTERPOLY;
+- zoom_ok = !(tmp > 0x7ff);
++ *pHQVzoomflag = 1;
++ *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
++ } else { /* srcWidth > dstWidth - Zoom out */
++ if (hwDiff->dwNewScaleCtl) {
++ if (srcWidth > (dstWidth << 3)) {
++ /*<1/8*/
++ /*FIXME!*/
++ if (dstWidth <= 32) {
++ dstWidth = 33;
++ }
++ if (srcWidth > (dstWidth << 5)) {
++ tmp = 1 * 0x1000 / 31;
++ } else {
++ tmp = (dstWidth * 0x1000) / srcWidth;
++ }
+
+- *pHQVzoomflag = 1;
+- *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
++ *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH;
++ } else if (srcWidth == (dstWidth << 3)) {
++ /*1/8*/
++ tmp = ((dstWidth - 1) * 0x1000) / srcWidth;
++ *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH;
++ } else if (srcWidth > (dstWidth << 2)) {
++ /*1/4 -1/8 zoom-out*/
++ tmp = (srcWidth * 0x1000) / dstWidth;
++ *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_EIGHTH;
++ } else {
++ /*1-1/4 zoom-out*/
++ /*setting :src/(destination+0.5)*/
++ tmp = (srcWidth * 0x2000) / ((dstWidth << 1) + 1);
++ *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_1;
++ }
+
+- } else { /* srcWidth > dstWidth - Zoom out */
++ /*rounding to nearest interger*/
++ tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0;
++ *pHQVscaleCtlH |= (tmp & 0x7fff) | HQV_H_SCALE_ENABLE;
++ } else {
++ /* HQV rounding patch, instead of:
++ * //tmp = dstWidth*0x0800 / srcWidth; */
++ tmp = dstWidth * 0x800 * 0x400 / srcWidth;
++ tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
+
+- /* HQV rounding patch, instead of:
+- * //tmp = dstWidth*0x0800 / srcWidth; */
+- tmp = dstWidth * 0x800 * 0x400 / srcWidth;
+- tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
++ *pHQVminiCtl = (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE | HQV_H_MINIFY_DOWN;
+
+- *pHQVminiCtl = (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE | HQV_H_MINIFY_DOWN;
+-
++ *pHQVminiCtl |= HQV_HDEBLOCK_FILTER;
++ }
+ /* Scale down the picture by a factor mdiv = (1 << d) = {2, 4, 8 or 16} */
+
+ sw1 = srcWidth;
+@@ -561,27 +649,25 @@
+ *pMiniCtl |= ((d << 1) - 1) << 24; /* <= {1,3,5,7} << 24 */
+
+ *pHQVfilterCtl |= HQVfilter[d];
+- /* *pHQVminiCtl = HQVmini[d]; */
+- *pHQVminiCtl |= HQV_HDEBLOCK_FILTER;
+
+- /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
++ /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
+
+- if (sw1 < dstWidth) {
+- /* CLE bug
+- *pZoomCtl = sw1 * 0x0800 / dstWidth;*/
+- *pZoomCtl = (sw1 - 2) * 0x0800 / dstWidth;
+- *pZoomCtl = ((*pZoomCtl & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
+- }
+- }
++ if (sw1 < dstWidth) {
++ /* CLE bug
++ *pZoomCtl = sw1 * 0x0800 / dstWidth;*/
++ *pZoomCtl = (sw1 - 2) * 0x0800 / dstWidth;
++ *pZoomCtl = ((*pZoomCtl & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
++ }
+
+- if (videoFlag & VIDEO_1_INUSE) {
+- pVia->swov.overlayRecordV1.dwFetchAlignment = falign;
+- pVia->swov.overlayRecordV1.dwminifyH = mdiv;
+- } else {
+- pVia->swov.overlayRecordV3.dwFetchAlignment = falign;
+- pVia->swov.overlayRecordV3.dwminifyH = mdiv;
+- }
++ if (videoFlag & VIDEO_1_INUSE) {
++ pVia->swov.overlayRecordV1.dwFetchAlignment = falign;
++ pVia->swov.overlayRecordV1.dwminifyH = mdiv;
++ } else {
++ pVia->swov.overlayRecordV3.dwFetchAlignment = falign;
++ pVia->swov.overlayRecordV3.dwminifyH = mdiv;
++ }
+
++ }
+ return zoom_ok;
+ }
+
+@@ -591,10 +677,12 @@
+ unsigned long *pZoomCtl, unsigned long *pMiniCtl,
+ unsigned long *pHQVfilterCtl,
+ unsigned long *pHQVminiCtl,
++ unsigned long *pHQVscaleCtlV,
+ unsigned long *pHQVzoomflag)
+ {
+ unsigned long tmp, sh1, d;
+ Bool zoom_ok = TRUE;
++ VIAHWDiff *hwDiff = &pVia->HWDiff;
+
+ CARD32 HQVfilter[5] = { HQV_V_TAP4_121, HQV_V_TAP4_121, HQV_V_TAP4_121,
+ HQV_V_TAP8_12221, HQV_V_TAP8_12221 };
+@@ -608,48 +696,58 @@
+ if (srcHeight == dstHeight) { /* No zoom */
+ *pHQVfilterCtl |= HQV_V_TAP4_121;
+ } else if (srcHeight < dstHeight) { /* Zoom in */
++ *pZoomCtl &= 0xFFFF0000;
++ tmp = srcHeight * 0x400 / dstHeight - 1;
++ *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
++ *pMiniCtl |= (V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY);
+
+- tmp = srcHeight * 0x0400 / dstHeight;
+- *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
+- *pMiniCtl |= (V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY);
+-
+- *pHQVzoomflag = 1;
+- *pHQVfilterCtl |= HQV_V_TAP4_121;
++ *pHQVzoomflag = 1;
++ *pHQVfilterCtl |= HQV_V_TAP4_121;
+ } else { /* srcHeight > dstHeight - Zoom out */
++ if (hwDiff->dwNewScaleCtl) {
++ /*setting :src/(destination+0.5)*/
++ tmp = srcHeight * 0x2000 / ((dstHeight << 1) + 1);
++ tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0;
++ if ((tmp & 0x1ffff) == 0) {
++ tmp = 0x1ffff;
++ }
+
+- /* HQV rounding patch, instead of:
+- * //tmp = dstHeight*0x0800 / srcHeight; */
+- tmp = dstHeight * 0x0800 * 0x400 / srcHeight;
+- tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
+- *pHQVminiCtl |= (((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE
+- | HQV_V_MINIFY_DOWN);
++ *pHQVscaleCtlV = (tmp & 0x1ffff) | HQV_V_SCALE_ENABLE| HQV_V_SCALE_DOWN;
++ } else {
++ /* HQV rounding patch, instead of:
++ * //tmp = dstHeight*0x0800 / srcHeight; */
++ tmp = dstHeight * 0x0800 * 0x400 / srcHeight;
++ tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
++ *pHQVminiCtl |= (((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE
++ | HQV_V_MINIFY_DOWN);
+
+- /* Scale down the picture by a factor (1 << d) = {2, 4, 8 or 16} */
++ /* Scale down the picture by a factor (1 << d) = {2, 4, 8 or 16} */
++
++ sh1 = srcHeight;
++ for (d = 1; d < 5; d++) {
++ sh1 >>= 1;
++ if (sh1 <= dstHeight)
++ break;
++ }
++ if (d == 5) { /* Too small. */
++ d = 4;
++ zoom_ok = FALSE;
++ }
+
+- sh1 = srcHeight;
+- for (d = 1; d < 5; d++) {
+- sh1 >>= 1;
+- if (sh1 <= dstHeight)
+- break;
+- }
+- if (d == 5) { /* Too small. */
+- d = 4;
+- zoom_ok = FALSE;
+- }
++ *pMiniCtl |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */
+
+- *pMiniCtl |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */
++ *pHQVfilterCtl |= HQVfilter[d];
++ /* *pHQVminiCtl |= HQVmini[d]; */
++ *pHQVminiCtl |= HQV_VDEBLOCK_FILTER;
+
+- *pHQVfilterCtl |= HQVfilter[d];
+- /* *pHQVminiCtl |= HQVmini[d]; */
+- *pHQVminiCtl |= HQV_VDEBLOCK_FILTER;
++ /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
+
+- /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
+-
+- if (sh1 < dstHeight) {
+- tmp = sh1 * 0x0400 / dstHeight;
+- *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
+- *pMiniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
+- }
++ if (sh1 < dstHeight) {
++ tmp = sh1 * 0x0400 / dstHeight;
++ *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
++ *pMiniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
++ }
++ }
+ }
+
+ return zoom_ok;
+@@ -1488,6 +1586,7 @@
+
+ if (videoFlag & VIDEO_1_INUSE) {
+ SaveVideoRegister(pVia, V_COLOR_KEY, keyLow);
++ SaveVideoRegister(pVia, SND_COLOR_KEY, keyLow);
+ } else {
+ if (pVia->HWDiff.dwSupportTwoColorKey) /*CLE_C0 */
+ SaveVideoRegister(pVia, V3_COLOR_KEY, keyLow);
+@@ -1561,8 +1660,9 @@
+ srcFetch >>= 3; /* fetch unit is 8 bytes */
+ }
+
+- SaveVideoRegister(pVia, HQV_SRC_FETCH_LINE + proReg,
+- ((srcFetch - 1) << 16) | (srcHeight - 1));
++ if (pVia->ChipId != PCI_CHIP_VT3409)
++ SaveVideoRegister(pVia, HQV_SRC_FETCH_LINE + proReg,
++ ((srcFetch - 1) << 16) | (srcHeight - 1));
+ }
+
+ static void
+@@ -1713,13 +1813,14 @@
+ unsigned long zoomCtl = 0, miniCtl = 0;
+ unsigned long hqvCtl = 0;
+ unsigned long hqvFilterCtl = 0, hqvMiniCtl = 0;
++ unsigned long hqvScaleCtlH = 0, hqvScaleCtlV = 0;
+ unsigned long haveHQVzoomH = 0, haveHQVzoomV = 0;
+ unsigned long hqvSrcWidth = 0, hqvDstWidth = 0;
+ unsigned long hqvSrcFetch = 0, hqvOffset = 0;
+ unsigned long dwOffset = 0, fetch = 0, tmp = 0;
+ unsigned long proReg = 0;
+
+- DBG_DD(ErrorF("videoflag=%p\n", videoFlag));
++ DBG_DD(ErrorF("videoflag=%ld\n", videoFlag));
+
+ if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
+ proReg = PRO_HQV1_OFFSET;
+@@ -1762,16 +1863,16 @@
+
+ /*
+ * FIXME:
+- * Enable video on secondary
++ * Enable video on secondary (change Panel to SecondCRTC?)
+ */
+ if ((pVia->VideoEngine == VIDEO_ENGINE_CME
+ || pVia->Chipset == VIA_VM800)
+ && pVia->pBIOSInfo->Panel->IsActive) {
+
+ /* V1_ON_SND_DISPLAY */
+- vidCtl |= 0x80000000;
++ vidCtl |= V1_ON_SND_DISPLAY;
+ /* SECOND_DISPLAY_COLOR_KEY_ENABLE */
+- compose |= 0x00010000 | 0x1;
++ compose |= SECOND_DISPLAY_COLOR_KEY_ENABLE | 0x1;
+ }
+
+ viaOverlayGetV1V3Format(pVia, (videoFlag & VIDEO_1_INUSE) ? 1 : 3,
+@@ -1925,7 +2026,7 @@
+
+ if (!viaOverlayHQVCalcZoomWidth(pVia, videoFlag, srcWidth, dstWidth,
+ &zoomCtl, &miniCtl, &hqvFilterCtl,
+- &hqvMiniCtl, &haveHQVzoomH)) {
++ &hqvMiniCtl, &hqvScaleCtlH, &haveHQVzoomH)) {
+ /* Need to scale (minify) too much - can't handle it. */
+ SetFetch(pVia, videoFlag, fetch);
+ FireVideoCommand(pVia, videoFlag, compose);
+@@ -1964,7 +2065,7 @@
+
+ if (!viaOverlayHQVCalcZoomHeight(pVia, srcHeight, dstHeight, &zoomCtl,
+ &miniCtl, &hqvFilterCtl, &hqvMiniCtl,
+- &haveHQVzoomV)) {
++ &hqvScaleCtlV, &haveHQVzoomV)) {
+ /* Need to scale (minify) too much - can't handle it. */
+ FireVideoCommand(pVia, videoFlag, compose);
+ FlushVidRegBuffer(pVia);
+@@ -2008,8 +2109,13 @@
+ hqvFilterCtl &= 0xfffdffff;
+ SetMiniAndZoom(pVia, videoFlag, 0, 0);
+ }
+- SaveVideoRegister(pVia, HQV_MINIFY_CONTROL + proReg, hqvMiniCtl);
+- SaveVideoRegister(pVia, HQV_FILTER_CONTROL + proReg, hqvFilterCtl);
++ if (hwDiff->dwNewScaleCtl) {
++ SaveVideoRegister(pVia, HQV_H_SCALE_CONTROL + proReg, hqvScaleCtlH);
++ SaveVideoRegister(pVia, HQV_V_SCALE_CONTROL + proReg, hqvScaleCtlV);
++ } else {
++ SaveVideoRegister(pVia, HQV_MINIFY_CONTROL + proReg, hqvMiniCtl);
++ }
++ SaveVideoRegister(pVia, HQV_FILTER_CONTROL + proReg, hqvFilterCtl);
+ } else
+ SetMiniAndZoom(pVia, videoFlag, miniCtl, zoomCtl);
+
+@@ -2022,11 +2128,24 @@
+ miniCtl, compose);
+
+ if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
+- VIDOutD(HQV_SRC_DATA_OFFSET_CONTROL1,0);
+- VIDOutD(HQV_SRC_DATA_OFFSET_CONTROL3,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL1),0);
++ SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL3),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
+ if (pVia->Chipset == VIA_VX800 || pVia->Chipset == VIA_VX855) {
+- VIDOutD(HQV_SRC_DATA_OFFSET_CONTROL2,0);
+- VIDOutD(HQV_SRC_DATA_OFFSET_CONTROL4,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL2),0);
++ SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL4),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ if (pVia->Chipset == VIA_VX855) {
++ SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL1,0);
++ SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL3,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL2,0);
++ SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL4,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_BACKGROUND_DATA_OFFSET,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_EXTENDED_CONTROL,0);
++ /*0x3e0*/
++ SaveVideoRegister(pVia, HQV_SUBP_HSCALE_CTRL,0);
++ /*0x3e8*/
++ SaveVideoRegister(pVia, HQV_SUBP_VSCALE_CTRL,0);
++ SaveVideoRegister(pVia, HQV_DEFAULT_VIDEO_COLOR, HQV_FIX_COLOR);
++ }
+ }
+ }
+
+@@ -2062,9 +2181,6 @@
+ usleep(1);
+ }
+
+- if (pVia->VideoEngine == VIDEO_ENGINE_CME)
+- hqvCtl |= HQV_GEN_IRQ;
+-
+ VIDOutD(HQV_CONTROL + proReg, hqvCtl & ~HQV_SW_FLIP);
+ VIDOutD(HQV_CONTROL + proReg, hqvCtl | HQV_SW_FLIP);
+
+Index: src/via_driver.h
+===================================================================
+--- src/via_driver.h (revision 811)
++++ src/via_driver.h (working copy)
+@@ -127,9 +127,10 @@
+ CARD8 SR27, SR28, SR29, SR2A,SR2B,SR2C,SR2D,SR2E;
+ CARD8 SR2F, SR30, SR31, SR32,SR33,SR34,SR40,SR41;
+ CARD8 SR42, SR43, SR44, SR45,SR46,SR47,SR48,SR49;
+- CARD8 SR4A, SR4B, SR4C;
++ CARD8 SR4A, SR4B, SR4C, SR4D;
+
+ /* extended CRTC registers */
++ CARD8 CR0C, CR0D;
+ CARD8 CR13, CR30, CR31, CR32, CR33, CR34, CR35, CR36;
+ CARD8 CR37, CR38, CR39, CR3A, CR40, CR41, CR42, CR43;
+ CARD8 CR44, CR45, CR46, CR47, CR48, CR49, CR4A;
+@@ -142,7 +143,7 @@
+ } VIARegRec, *VIARegPtr;
+
+ /*
+- * varables that need to be shared among different screens.
++ * variables that need to be shared among different screens.
+ */
+ typedef struct {
+ Bool b3DRegsInitialized;
+@@ -285,6 +286,7 @@
+ Bool agpDMA;
+ Bool nPOT[VIA_NUM_TEXUNITS];
+ const unsigned *TwodRegs;
++ const unsigned *HqvCmeRegs;
+ ExaDriverPtr exaDriverPtr;
+ ExaOffscreenArea *exa_scratch;
+ unsigned int exa_scratch_next;
+@@ -412,16 +414,18 @@
+ void *cursorMap;
+ CARD32 cursorOffset;
+
++ CARD8 I2CDevices; /* Option */
++
+ #ifdef HAVE_DEBUG
+ Bool disableXvBWCheck;
+ Bool DumpVGAROM;
+ Bool PrintVGARegs;
+ Bool PrintTVRegs;
+ Bool I2CScan;
++#endif /* HAVE_DEBUG */
+
+ Bool UseLegacyModeSwitch ;
+ video_via_regs* VideoRegs ;
+-#endif /* HAVE_DEBUG */
+ } VIARec, *VIAPtr;
+
+ #define VIAPTR(p) ((VIAPtr)((p)->driverPrivate))
+@@ -433,7 +437,7 @@
+ Bool HasSecondary;
+ Bool BypassSecondary;
+ /*These two registers are used to make sure the CRTC2 is
+- retored before CRTC_EXT, otherwise it could lead to blank screen.*/
++ restored before CRTC_EXT, otherwise it could lead to blank screen.*/
+ Bool IsSecondaryRestored;
+ Bool RestorePrimary;
+
+Index: src/via_bios.h
+===================================================================
+--- src/via_bios.h (revision 811)
++++ src/via_bios.h (working copy)
+@@ -82,6 +82,11 @@
+ #define VIA_DEVICE_TV 0x04
+ #define VIA_DEVICE_DFP 0x08
+
++#define VIA_I2C_NONE 0x00
++#define VIA_I2C_BUS1 0x01
++#define VIA_I2C_BUS2 0x02
++#define VIA_I2C_BUS3 0x04
++
+ /* System Memory CLK */
+ #define VIA_MEM_SDR66 0x00
+ #define VIA_MEM_SDR100 0x01
+@@ -92,7 +97,9 @@
+ #define VIA_MEM_DDR400 0x06
+ #define VIA_MEM_DDR533 0x07
+ #define VIA_MEM_DDR667 0x08
+-#define VIA_MEM_END 0x09
++#define VIA_MEM_DDR800 0x09
++#define VIA_MEM_DDR1066 0x0A
++#define VIA_MEM_END 0x0B
+ #define VIA_MEM_NONE 0xFF
+
+ /* Digital Output Bus Width */
+Index: src/via_swov.h
+===================================================================
+--- src/via_swov.h (revision 811)
++++ src/via_swov.h (working copy)
+@@ -53,7 +53,7 @@
+ {
+ unsigned long dwThreeHQVBuffer; /* Use Three HQV Buffers */
+ /* unsigned long dwV3SrcHeightSetting; *//* Set Video Source Width and Height */
+- /* unsigned long dwSupportExtendFIFO; *//* Support Extand FIFO */
++ /* unsigned long dwSupportExtendFIFO; *//* Support Extend FIFO */
+ unsigned long dwHQVFetchByteUnit; /* HQV Fetch Count unit is byte */
+ unsigned long dwHQVInitPatch; /* Initialize HQV Engine 2 times */
+ /*unsigned long dwSupportV3Gamma; *//* Support V3 Gamma */
+@@ -73,6 +73,8 @@
+ /*unsigned long dwV3FIFOPatch; *//* For CLE V3 FIFO Bug (srcWidth <= 8) */
+ unsigned long dwSupportTwoColorKey; /* Support two color key */
+ /* unsigned long dwCxColorSpace; *//* CLE_Cx ColorSpace */
++ unsigned dwNewScaleCtl; /* Use new HQV scale engine code */
++ const unsigned *HQVCmeRegs; /* Which set of CME regs to use for newer chipsets */
+ } VIAHWDiff;
+
+ void VIAVidHWDiffInit(ScrnInfoPtr pScrn);
+Index: src/via_bandwidth.c
+===================================================================
+--- src/via_bandwidth.c (revision 811)
++++ src/via_bandwidth.c (working copy)
+@@ -194,6 +194,7 @@
+ else
+ ViaSeqMask(hwp, 0x22, 0x00, 0x1F); /* 128/4 = overflow = 0 */
+ break;
++ /* PM800/PM880/CN400 */
+ case VIA_PM800:
+ hwp->writeSeq(hwp, 0x17, 0x5F); /* 95 */
+ ViaSeqMask(hwp, 0x16, 0x20, 0xBF); /* 32 */
+@@ -204,9 +205,10 @@
+ else
+ ViaSeqMask(hwp, 0x22, 0x1F, 0x1F); /* 31 */
+ break;
++ /* P4M800Pro/VN800/CN700 */
+ case VIA_VM800:
+ hwp->writeSeq(hwp, 0x17, 0x2F);
+- ViaSeqMask(hwp, 0x16, 0x14, 0xBF);
++ ViaSeqMask(hwp, 0x16, 0x14, 0xBF); /* 80/4 = 20 = 0x14 */
+ ViaSeqMask(hwp, 0x18, 0x08, 0xBF);
+
+ if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
+@@ -215,40 +217,60 @@
+ ViaSeqMask(hwp, 0x22, 0x00, 0x1F);
+ break;
+ case VIA_K8M890:
+- hwp->writeSeq(hwp, 0x16, 0x92);
+- hwp->writeSeq(hwp, 0x17, 0xB3);
+- hwp->writeSeq(hwp, 0x18, 0x8A);
++ /* depth location: {SR17,0,7} */
++ hwp->writeSeq(hwp, 0x17, 0xB3); /* 360/2-1 = 179 = 0xB3 */
++ /* Formula (x & 0x3F) | ((x & 0x40) << 1) */
++ /* threshold location: {SR16,0,5},{SR16,7,7} */
++ ViaSeqMask(hwp, 0x16, 0x92, 0xBF); /* 328/4 = 82 = 0x52 */
++ /* high threshold location: {SR18,0,5},{SR18,7,7} */
++ ViaSeqMask(hwp, 0x18, 0x8A, 0xBF); /* 296/4 = 74 = 0x4A */
++ /* display queue expire num location: {SR22,0,4}. */
++ ViaSeqMask(hwp, 0x22, 0x1F, 0x1F); /* 124/4 = 31 = 0x1F */
+ break;
+ case VIA_P4M900:
+- ViaSeqMask(hwp, 0x17, 0x2F, 0xFF);
+- ViaSeqMask(hwp, 0x16, 0x13, 0x3F);
+- ViaSeqMask(hwp, 0x16, 0x00, 0x80);
+- ViaSeqMask(hwp, 0x18, 0x13, 0x3F);
+- ViaSeqMask(hwp, 0x18, 0x00, 0x80);
++ /* location: {SR17,0,7} */
++ hwp->writeSeq(hwp, 0x17, 0x2F); /* 96/2-1 = 47 = 0x2F */
++ /* location: {SR16,0,5},{SR16,7,7} */
++ ViaSeqMask(hwp, 0x16, 0x13, 0xBF); /* 76/4 = 19 = 0x13 */
++ /* location: {SR18,0,5},{SR18,7,7} */
++ ViaSeqMask(hwp, 0x18, 0x13, 0xBF); /* 76/4 = 19 = 0x13 */
++ /* location: {SR22,0,4}. */
++ ViaSeqMask(hwp, 0x22, 0x08, 0x1F); /* 32/4 = 8 = 0x08 */
+ break;
+ case VIA_P4M890:
+- hwp->writeSeq(hwp, 0x16, 0x13);
+- hwp->writeSeq(hwp, 0x17, 0x2F);
+- hwp->writeSeq(hwp, 0x18, 0x53);
+- hwp->writeSeq(hwp, 0x22, 0x10);
++ hwp->writeSeq(hwp, 0x17, 0x2F); /* 96/2-1 = 47 = 0x2F */
++ ViaSeqMask(hwp, 0x16, 0x13, 0xBF); /* 76/4 = 19 = 0x13 */
++ ViaSeqMask(hwp, 0x18, 0x10, 0xBF); /* 64/4 = 16 = 0x10 */
++ ViaSeqMask(hwp, 0x22, 0x08, 0x1F); /* 32/4 = 8 = 0x08 */
+ break;
+ case VIA_CX700:
+- hwp->writeSeq(hwp, 0x16, 0x26);
+ hwp->writeSeq(hwp, 0x17, 0x5F);
+- hwp->writeSeq(hwp, 0x18, 0x66);
+- hwp->writeSeq(hwp, 0x22, 0x1F);
++ ViaSeqMask(hwp, 0x16, 0x20, 0xBF); /* 128/4 = 32 = 0x20 */
++ ViaSeqMask(hwp, 0x18, 0x20, 0xBF); /* 128/4 = 32 = 0x20 */
++ ViaSeqMask(hwp, 0x22, 0x1F, 0x1F); /* 124/4 = 31 = 0x1F */
+ break;
+ case VIA_VX800:
+- hwp->writeSeq(hwp, 0x16, 0x26); /* 152/4 = 38 */
+- hwp->writeSeq(hwp, 0x17, 0x5F); /* 192/2-1 = 95 */
++ hwp->writeSeq(hwp, 0x17, 0x5F); /* 192/2-1 = 95 = 0x5F */
++ hwp->writeSeq(hwp, 0x16, 0x26); /* 152/4 = 38 = 0x26 */
+ hwp->writeSeq(hwp, 0x18, 0x26); /* 152/4 = 38 */
+ hwp->writeSeq(hwp, 0x22, 0x10); /* 64/4 = 16 */
+ break;
+ case VIA_VX855:
+- hwp->writeSeq(hwp, 0x16, 0x50); /* 320/4 = 80 */
+- hwp->writeSeq(hwp, 0x17, 0xC7); /* 400/2-1 = 199 */
+- hwp->writeSeq(hwp, 0x18, 0x50); /* 320/4 = 80 */
+- hwp->writeSeq(hwp, 0x22, 0x28); /* 160/4 = 40 */
++ hwp->writeSeq(hwp, 0x17, 0xC7); /* 400/2-1 = 199 = 0xC7 */
++ /* Formula for {SR16,0,5},{SR16,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
++ hwp->writeSeq(hwp, 0x16, 0x90); /* 320/4 = 80 = 0x50 */
++ /* Formula for {SR18,0,5},{SR18,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
++ hwp->writeSeq(hwp, 0x18, 0x90); /* 320/4 = 80 = 0x50 */
++ hwp->writeSeq(hwp, 0x22, 0x28); /* 160/4 = 40 = 0x28 */
++ break;
++ case VIA_VX900:
++ hwp->writeSeq(hwp, 0x17, 0xC7); /* 400/2-1 = 199 = 0xC7 */
++ /* Formula for {SR16,0,5},{SR16,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
++ hwp->writeSeq(hwp, 0x16, 0x90); /* 320/4 = 80 = 0x50 */
++ /* Formula for {SR18,0,5},{SR18,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
++ hwp->writeSeq(hwp, 0x18, 0x90); /* 320/4 = 80 = 0x50 */
++ hwp->writeSeq(hwp, 0x22, 0x28); /* 160/4 = 40 = 0x28 */
++ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ViaSetPrimaryFIFO: "
+ "Chipset %d not implemented\n", pVia->Chipset);
+@@ -371,7 +393,38 @@
+ ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);
+ break;
+ case VIA_P4M890:
++ /* depth location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
++ ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0); /* 96/8-1 = 11 = 0x0B */
++ ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
++ ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
++
++ /* location: {CR68,0,3},{CR95,4,6} */
++ ViaCrtcMask(hwp, 0x68, 0x03, 0x0F); /* 76/4 = 19 = 0x13 */
++ ViaCrtcMask(hwp, 0x95, 0x10, 0x70);
++
++ /* location: {CR92,0,3},{CR95,0,2} */
++ ViaCrtcMask(hwp, 0x92, 0x00, 0x0F); /* 64/4 = 16 = 0x10 */
++ ViaCrtcMask(hwp, 0x95, 0x01, 0x07);
++
++ /* location: {CR94,0,6} */
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F); /* 32/4 = 8 = 0x08 */
++ break;
+ case VIA_K8M890:
++ /* Display Queue Depth, location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
++ ViaCrtcMask(hwp, 0x68, 0xC0, 0xF0); /* 360/8-1 = 44 = 0x2C; 0x2C << 4 = 0xC0 */
++ ViaCrtcMask(hwp, 0x94, 0x00, 0x80); /* 0x2C << 3 = 0x00 */
++ ViaCrtcMask(hwp, 0x95, 0x80, 0x80); /* 0x2C << 2 = 0x80 */
++
++ /* Display Queue Read Threshold 1, location: {CR68,0,3},{CR95,4,6} */
++ ViaCrtcMask(hwp, 0x68, 0x02, 0x0F); /* 328/4 = 82 = 0x52 */
++ ViaCrtcMask(hwp, 0x95, 0x50, 0x70);
++
++ /* location: {CR92,0,3},{CR95,0,2} */
++ ViaCrtcMask(hwp, 0x92, 0x0A, 0x0F); /* 296/4 = 74 = 0x4A */
++ ViaCrtcMask(hwp, 0x95, 0x04, 0x07); /* 0x4A >> 4 = 0x04 */
++
++ /* Display Expire Number Bits, location: {CR94,0,6} */
++ ViaCrtcMask(hwp, 0x94, 0x1F, 0x7F); /* 124/4 = 31 = 0x1F */
+ break;
+ case VIA_P4M900:
+ ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0);
+@@ -402,8 +455,8 @@
+ break;
+ case VIA_VX800:
+ /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 96/8-1 = 0x0B */
+- ViaCrtcMask(hwp, 0x68, 0xA0, 0xF0);
+- ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
++ ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0); /* ((0x0B & 0x0F) << 4)) = 0xB0 */
++ ViaCrtcMask(hwp, 0x94, 0x00, 0x80); /* ((0x0B & 0x10) << 3)) = 0x00 */
+ ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
+ /* {CR68,0,3},{CR95,4,6} : 64/4 = 0x10 */
+ ViaCrtcMask(hwp, 0x68, 0x04, 0x0F);
+@@ -418,7 +471,39 @@
+ ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);
+ break;
+ case VIA_VX855:
++ /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 200/8-1 = 24 = 0x18 */
++ ViaCrtcMask(hwp, 0x68, 0x80, 0xF0); /* ((0x18 & 0x0F) << 4)) = 0x80 */
++ ViaCrtcMask(hwp, 0x94, 0x80, 0x80); /* ((0x18 & 0x10) << 3)) = 0x80 */
++ ViaCrtcMask(hwp, 0x95, 0x00, 0x80); /* ((0x18 & 0x20) << 2)) = 0x00 */
++ /* {CR68,0,3},{CR95,4,6} : 160/4 = 0x28 */
++ ViaCrtcMask(hwp, 0x68, 0x08, 0x0F); /* (0x28 & 0x0F) = 0x08 */
++ ViaCrtcMask(hwp, 0x95, 0x20, 0x70); /* (0x28 & 0x70) = 0x20 */
++ /* {CR92,0,3},{CR95,0,2} : 160/4 = 0x28 */
++ ViaCrtcMask(hwp, 0x92, 0x08, 0x08); /* (0x28 & 0x0F) = 0x08 */
++ ViaCrtcMask(hwp, 0x95, 0x02, 0x07); /* ((0x28 & 0x70) >> 4)) = 0x02 */
++ /* {CR94,0,6} : 320/4 = 0x50 */
++ if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
++ else
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
+ break;
++ case VIA_VX900:
++ /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 192/8-1 = 23 = 0x17 */
++ ViaCrtcMask(hwp, 0x68, 0x70, 0xF0); /* ((0x17 & 0x0F) << 4)) = 0x70 */
++ ViaCrtcMask(hwp, 0x94, 0x80, 0x80); /* ((0x17 & 0x10) << 3)) = 0x80 */
++ ViaCrtcMask(hwp, 0x95, 0x00, 0x80); /* ((0x17 & 0x20) << 2)) = 0x00 */
++ /* {CR68,0,3},{CR95,4,6} : 160/4 = 0x28 */
++ ViaCrtcMask(hwp, 0x68, 0x08, 0x0F); /* (0x28 & 0x0F) = 0x08 */
++ ViaCrtcMask(hwp, 0x95, 0x20, 0x70); /* (0x28 & 0x70) = 0x20 */
++ /* {CR92,0,3},{CR95,0,2} : 160/4 = 0x28 */
++ ViaCrtcMask(hwp, 0x92, 0x08, 0x08); /* (0x28 & 0x0F) = 0x08 */
++ ViaCrtcMask(hwp, 0x95, 0x02, 0x07); /* ((0x28 & 0x70) >> 4)) = 0x2 */
++ /* {CR94,0,6} : 320/4 = 0x50 */
++ if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
++ else
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
++ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ViaSetSecondaryFIFO: "
+ "Chipset %d not implemented\n", pVia->Chipset);
+Index: src/via_accel.c
+===================================================================
+--- src/via_accel.c (revision 811)
++++ src/via_accel.c (working copy)
+@@ -196,6 +196,7 @@
+ switch (pVia->Chipset) {
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ while ((VIAGETREG(VIA_REG_STATUS) &
+ (VIA_CMD_RGTR_BUSY_H5 | VIA_2D_ENG_BUSY_H5))
+ && (loop++ < MAXLOOP)) ;
+@@ -287,7 +288,7 @@
+
+ buf->pScrn = pScrn;
+ buf->bufSize = ((size == 0) ? VIA_DMASIZE : size) >> 2;
+- buf->buf = (CARD32 *) xcalloc(buf->bufSize, sizeof(CARD32));
++ buf->buf = (CARD32 *) calloc(buf->bufSize, sizeof(CARD32));
+ if (!buf->buf)
+ return BadAlloc;
+ buf->waitFlags = 0;
+@@ -312,7 +313,7 @@
+ viaTearDownCBuffer(ViaCommandBuffer * buf)
+ {
+ if (buf && buf->buf)
+- xfree(buf->buf);
++ free(buf->buf);
+ buf->buf = NULL;
+ }
+
+@@ -417,6 +418,9 @@
+ switch (pVia->Chipset) {
+ case VIA_K8M890:
+ case VIA_P4M900:
++ case VIA_VX800:
++ case VIA_VX855:
++ case VIA_VX900:
+ VIASETREG(0x41c, 0x00100000);
+ VIASETREG(0x420, 0x74301000);
+ break;
+@@ -472,16 +476,25 @@
+ VIASETREG(i, 0x0);
+ }
+
+- if (pVia->Chipset == VIA_VX800 || pVia->Chipset == VIA_VX855) {
+- for (i = 0x44; i < 0x5c; i += 4) {
++ if (pVia->Chipset == VIA_VX800 ||
++ pVia->Chipset == VIA_VX855 ||
++ pVia->Chipset == VIA_VX900) {
++ for (i = 0x44; i <= 0x5c; i += 4) {
+ VIASETREG(i, 0x0);
+ }
+ }
+
++ if (pVia->Chipset == VIA_VX900)
++ {
++ /*410 redefine 0x30 34 38*/
++ VIASETREG(0x60, 0x0); /*already useable here*/
++ }
++
+ /* Make the VIA_REG() macro magic work */
+ switch (pVia->Chipset) {
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ pVia->TwodRegs = via_2d_regs_m1;
+ break;
+ default:
+@@ -492,6 +505,9 @@
+ switch (pVia->Chipset) {
+ case VIA_K8M890:
+ case VIA_P4M900:
++ case VIA_VX800:
++ case VIA_VX855:
++ case VIA_VX900:
+ viaInitPCIe(pVia);
+ break;
+ default:
+@@ -503,6 +519,9 @@
+ switch (pVia->Chipset) {
+ case VIA_K8M890:
+ case VIA_P4M900:
++ case VIA_VX800:
++ case VIA_VX855:
++ case VIA_VX900:
+ viaEnablePCIeVQ(pVia);
+ break;
+ default:
+@@ -530,6 +549,7 @@
+ switch (pVia->Chipset) {
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ while ((VIAGETREG(VIA_REG_STATUS) &
+ (VIA_CMD_RGTR_BUSY_H5 | VIA_2D_ENG_BUSY_H5 | VIA_3D_ENG_BUSY_H5))
+ && (loop++ < MAXLOOP)) ;
+@@ -582,7 +602,7 @@
+
+ /*
+ * This is a small helper to wrap around a PITCH register write
+- * to deal with the sublte differences of M1 and old 2D engine
++ * to deal with the subtle differences of M1 and old 2D engine
+ */
+ static void
+ viaPitchHelper(VIAPtr pVia, unsigned dstPitch, unsigned srcPitch)
+@@ -590,7 +610,9 @@
+ unsigned val = (dstPitch >> 3) << 16 | (srcPitch >> 3);
+ RING_VARS;
+
+- if (pVia->Chipset != VIA_VX800 && pVia->Chipset != VIA_VX855) {
++ if (pVia->Chipset != VIA_VX800 &&
++ pVia->Chipset != VIA_VX855 &&
++ pVia->Chipset != VIA_VX900) {
+ val |= VIA_PITCH_ENABLE;
+ }
+ OUT_RING_H1(VIA_REG(pVia, PITCH), val);
+@@ -759,6 +781,7 @@
+ tdc->cmd = cmd;
+ viaAccelTransparentHelper(pVia, (trans_color != -1) ? 0x4000 : 0x0000,
+ trans_color, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -796,6 +819,7 @@
+ tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(rop);
+ tdc->fgColor = color;
+ viaAccelTransparentHelper(pVia, 0x00, 0x00, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -852,6 +876,7 @@
+ tdc->pattern0 = pattern0;
+ tdc->pattern1 = pattern1;
+ viaAccelTransparentHelper(pVia, 0x00, 0x00, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -901,6 +926,7 @@
+ tdc->patternAddr = (patternx * pVia->Bpp + patterny * pVia->Bpl);
+ viaAccelTransparentHelper(pVia, (trans_color != -1) ? 0x4000 : 0x0000,
+ trans_color, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -962,9 +988,9 @@
+ tdc->fgColor = fg;
+ tdc->bgColor = bg;
+
++ viaAccelTransparentHelper(pVia, 0x0, 0x0, FALSE);
++
+ ADVANCE_RING;
+-
+- viaAccelTransparentHelper(pVia, 0x0, 0x0, FALSE);
+ }
+
+ static void
+@@ -991,7 +1017,7 @@
+ pScrn->fbOffset + sub * pVia->Bpl, tdc->mode,
+ pVia->Bpl, pVia->Bpl, tdc->cmd);
+
+- viaFlushPCI(cb);
++ ADVANCE_RING;
+ viaDisableClipping(pScrn);
+ }
+
+@@ -1005,9 +1031,9 @@
+ RING_VARS;
+
+ tdc->cmd = VIA_GEC_BLT | VIA_GEC_SRC_SYS | VIAACCELCOPYROP(rop);
+- ADVANCE_RING;
+ viaAccelTransparentHelper(pVia, (trans_color != -1) ? 0x4000 : 0x0000,
+ trans_color, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -1030,7 +1056,7 @@
+ pScrn->fbOffset + pVia->Bpl * sub, tdc->mode,
+ pVia->Bpl, pVia->Bpl, tdc->cmd);
+
+- viaFlushPCI(cb);
++ ADVANCE_RING;
+ viaDisableClipping(pScrn);
+ }
+
+@@ -1052,6 +1078,7 @@
+ OUT_RING_H1(VIA_REG(pVia, GEMODE), tdc->mode);
+ OUT_RING_H1(VIA_REG(pVia, MONOPAT0), 0xFF);
+ OUT_RING_H1(VIA_REG(pVia, MONOPATFGC), tdc->fgColor);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -1189,6 +1216,7 @@
+ OUT_RING_H1(VIA_REG(pVia, MONOPATFGC), tdc->fgColor);
+ OUT_RING_H1(VIA_REG(pVia, MONOPATBGC), tdc->bgColor);
+ OUT_RING_H1(VIA_REG(pVia, MONOPAT0), tdc->pattern0);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -1210,7 +1238,8 @@
+
+ /* General acceleration flags. */
+ xaaptr->Flags = (PIXMAP_CACHE |
+- OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER |
++ OFFSCREEN_PIXMAPS |
++ LINEAR_FRAMEBUFFER |
+ MICROSOFT_ZERO_LINE_BIAS | 0);
+
+ if (pScrn->bitsPerPixel == 8)
+@@ -1218,24 +1247,31 @@
+
+ xaaptr->SetClippingRectangle = viaSetClippingRectangle;
+ xaaptr->DisableClipping = viaDisableClipping;
+- xaaptr->ClippingFlags = (HARDWARE_CLIP_SOLID_FILL |
+- HARDWARE_CLIP_SOLID_LINE |
+- HARDWARE_CLIP_DASHED_LINE |
+- HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
++ xaaptr->ClippingFlags = (HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
+ HARDWARE_CLIP_MONO_8x8_FILL |
+ HARDWARE_CLIP_COLOR_8x8_FILL |
+ HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND | 0);
+
++ if (pVia->Chipset != VIA_VX800 &&
++ pVia->Chipset != VIA_VX855 &&
++ pVia->Chipset != VIA_VX900)
++ xaaptr->ClippingFlags |= (HARDWARE_CLIP_SOLID_FILL |
++ HARDWARE_CLIP_SOLID_LINE |
++ HARDWARE_CLIP_DASHED_LINE);
++
+ xaaptr->Sync = viaAccelSync;
+
++ /* ScreenToScreen copies */
+ xaaptr->SetupForScreenToScreenCopy = viaSetupForScreenToScreenCopy;
+ xaaptr->SubsequentScreenToScreenCopy = viaSubsequentScreenToScreenCopy;
+ xaaptr->ScreenToScreenCopyFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE;
+
++ /* Solid filled rectangles */
+ xaaptr->SetupForSolidFill = viaSetupForSolidFill;
+ xaaptr->SubsequentSolidFillRect = viaSubsequentSolidFillRect;
+ xaaptr->SolidFillFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE;
+
++ /* Mono 8x8 pattern fills */
+ xaaptr->SetupForMono8x8PatternFill = viaSetupForMono8x8PatternFill;
+ xaaptr->SubsequentMono8x8PatternFillRect =
+ viaSubsequentMono8x8PatternFillRect;
+@@ -1244,6 +1280,7 @@
+ HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
+ BIT_ORDER_IN_BYTE_MSBFIRST | 0);
+
++ /* Color 8x8 pattern fills */
+ xaaptr->SetupForColor8x8PatternFill = viaSetupForColor8x8PatternFill;
+ xaaptr->SubsequentColor8x8PatternFillRect =
+ viaSubsequentColor8x8PatternFillRect;
+@@ -1252,12 +1289,14 @@
+ HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_PROGRAMMED_ORIGIN | 0);
+
++ /* Solid lines */
+ xaaptr->SetupForSolidLine = viaSetupForSolidLine;
+ xaaptr->SubsequentSolidTwoPointLine = viaSubsequentSolidTwoPointLine;
+ xaaptr->SubsequentSolidHorVertLine = viaSubsequentSolidHorVertLine;
+ xaaptr->SolidBresenhamLineErrorTermBits = 14;
+ xaaptr->SolidLineFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE;
+
++ /* Dashed line */
+ xaaptr->SetupForDashedLine = viaSetupForDashedLine;
+ xaaptr->SubsequentDashedTwoPointLine = viaSubsequentDashedTwoPointLine;
+ xaaptr->DashPatternMaxLength = 8;
+@@ -1266,49 +1305,50 @@
+ LINE_PATTERN_POWER_OF_2_ONLY |
+ LINE_PATTERN_MSBFIRST_LSBJUSTIFIED | 0);
+
++ /* CPU to Screen color expansion */
+ xaaptr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
+- CPU_TRANSFER_PAD_DWORD |
+- SCANLINE_PAD_DWORD |
+- BIT_ORDER_IN_BYTE_MSBFIRST |
+- LEFT_EDGE_CLIPPING | ROP_NEEDS_SOURCE | 0;
++ CPU_TRANSFER_PAD_DWORD |
++ SCANLINE_PAD_DWORD |
++ BIT_ORDER_IN_BYTE_MSBFIRST |
++ LEFT_EDGE_CLIPPING |
++ ROP_NEEDS_SOURCE | 0;
+
+ xaaptr->SetupForScanlineCPUToScreenColorExpandFill =
+ viaSetupForCPUToScreenColorExpandFill;
+ xaaptr->SubsequentScanlineCPUToScreenColorExpandFill =
+ viaSubsequentScanlineCPUToScreenColorExpandFill;
+ xaaptr->ColorExpandBase = pVia->BltBase;
+- xaaptr->ColorExpandRange = VIA_MMIO_BLTSIZE;
++ if (pVia->Chipset == VIA_VX800 ||
++ pVia->Chipset == VIA_VX855 ||
++ pVia->Chipset == VIA_VX900)
++ xaaptr->ColorExpandRange = VIA_MMIO_BLTSIZE;
++ else
++ xaaptr->ColorExpandRange = (64 * 1024);
+
++ /* ImageWrite */
+ xaaptr->ImageWriteFlags = (NO_PLANEMASK |
+ CPU_TRANSFER_PAD_DWORD |
+ SCANLINE_PAD_DWORD |
+ BIT_ORDER_IN_BYTE_MSBFIRST |
+- LEFT_EDGE_CLIPPING | ROP_NEEDS_SOURCE | 0);
+- // SYNC_AFTER_IMAGE_WRITE | 0);
++ LEFT_EDGE_CLIPPING |
++ ROP_NEEDS_SOURCE |
++ NO_GXCOPY | 0);
+
+ /*
+ * Most Unichromes are much faster using processor-to-framebuffer writes
+ * than when using the 2D engine for this.
+- * test with x11perf -shmput500!
++ * test with "x11perf -shmput500"
++ * Example: K8M890 chipset; with GPU=86.3/sec; without GPU=132.0/sec
++ * TODO Check speed for other chipsets
+ */
+
+- switch (pVia->Chipset) {
+- case VIA_K8M800:
+- case VIA_K8M890:
+- case VIA_P4M900:
+- case VIA_VX800:
+- case VIA_VX855:
+- break;
+- default:
+- xaaptr->ImageWriteFlags |= NO_GXCOPY;
+- break;
+- }
+-
+ xaaptr->SetupForImageWrite = viaSetupForImageWrite;
+ xaaptr->SubsequentImageWriteRect = viaSubsequentImageWriteRect;
+ xaaptr->ImageWriteBase = pVia->BltBase;
+
+- if (pVia->Chipset == VIA_VX800 || pVia->Chipset == VIA_VX855)
++ if (pVia->Chipset == VIA_VX800 ||
++ pVia->Chipset == VIA_VX855 ||
++ pVia->Chipset == VIA_VX900)
+ xaaptr->ImageWriteRange = VIA_MMIO_BLTSIZE;
+ else
+ xaaptr->ImageWriteRange = (64 * 1024);
+@@ -2344,7 +2384,7 @@
+ }
+
+ if (!exaDriverInit(pScreen, pExa)) {
+- xfree(pExa);
++ free(pExa);
+ return NULL;
+ }
+
+@@ -2354,7 +2394,7 @@
+
+
+ /*
+- * Acceleration initializatuon function. Sets up offscreen memory disposition,
++ * Acceleration initialization function. Sets up offscreen memory disposition,
+ * and initializes engines and acceleration method.
+ */
+ Bool
+@@ -2542,7 +2582,7 @@
+ }
+ }
+ if (pVia->dBounce)
+- xfree(pVia->dBounce);
++ free(pVia->dBounce);
+ #endif /* XF86DRI */
+ if (pVia->scratchAddr) {
+ exaOffscreenFree(pScreen, pVia->scratchFBBuffer);
+@@ -2551,7 +2591,7 @@
+ if (pVia->exaDriverPtr) {
+ exaDriverFini(pScreen);
+ }
+- xfree(pVia->exaDriverPtr);
++ free(pVia->exaDriverPtr);
+ pVia->exaDriverPtr = NULL;
+ return;
+ }
+@@ -2577,7 +2617,7 @@
+
+ if (pVia->directRenderingEnabled && pVia->useEXA) {
+
+- pVia->dBounce = xcalloc(VIA_DMA_DL_SIZE * 2, 1);
++ pVia->dBounce = calloc(VIA_DMA_DL_SIZE * 2, 1);
+
+ if (!pVia->IsPCI) {
+
+Index: src/via_vt162x.c
+===================================================================
+--- src/via_vt162x.c (revision 811)
++++ src/via_vt162x.c (working copy)
+@@ -41,30 +41,42 @@
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+- /* External TV: */
+- switch(pVia->Chipset) {
+- case VIA_CX700:
+- case VIA_VX800:
+- if (pBIOSInfo->FirstCRTC->IsActive) {
+- if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
+- ViaCrtcMask(hwp, 0x6C, 0xB0, 0xF0);
+- else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
+- ViaCrtcMask(hwp, 0x6C, 0x90, 0xF0);
+- } else {
+- /* IGA2 */
+- if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
+- ViaCrtcMask(hwp, 0x6C, 0x0B, 0x0F);
+- else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
+- ViaCrtcMask(hwp, 0x6C, 0x09, 0x0F);
++ switch(pBIOSInfo->TVEncoder) {
++ case VIA_VT1625:
++ /* External TV: */
++ switch(pVia->Chipset) {
++ case VIA_CX700:
++ case VIA_VX800:
++ case VIA_VX855:
++ if (pBIOSInfo->FirstCRTC->IsActive) {
++ if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
++ ViaCrtcMask(hwp, 0x6C, 0xB0, 0xF0);
++ else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
++ ViaCrtcMask(hwp, 0x6C, 0x90, 0xF0);
++ } else {
++ /* IGA2 */
++ if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
++ ViaCrtcMask(hwp, 0x6C, 0x0B, 0x0F);
++ else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
++ ViaCrtcMask(hwp, 0x6C, 0x09, 0x0F);
++ }
++ break;
++ default:
++ if (pBIOSInfo->FirstCRTC->IsActive)
++ ViaCrtcMask(hwp, 0x6C, 0x21, 0x21);
++ else
++ ViaCrtcMask(hwp, 0x6C, 0xA1, 0xA1);
++ break;
+ }
+ break;
+ default:
+ if (pBIOSInfo->FirstCRTC->IsActive)
+- ViaCrtcMask(hwp, 0x6C, 0x21, 0x21);
++ ViaCrtcMask(hwp, 0x6C, 0x50, 0xF0);
+ else
+- ViaCrtcMask(hwp, 0x6C, 0xA1, 0xA1);
++ ViaCrtcMask(hwp, 0x6C, 0x05, 0x0F);
+ break;
+ }
++
+ }
+
+ static void
+Index: src/via_vbe.c
+===================================================================
+--- src/via_vbe.c (revision 811)
++++ src/via_vbe.c (working copy)
+@@ -230,7 +230,7 @@
+ /* Some cards do not like setting the clock. */
+ xf86ErrorF("...but worked OK without customized "
+ "refresh and dotclock.\n");
+- xfree(data->block);
++ free(data->block);
+ data->block = NULL;
+ data->mode &= ~(1 << 11);
+ } else {
+@@ -322,7 +322,7 @@
+ && (function == MODE_SAVE)) {
+ /* Do not rely on the memory not being touched. */
+ if (pVia->vbeMode.pstate == NULL)
+- pVia->vbeMode.pstate = xalloc(pVia->vbeMode.stateSize);
++ pVia->vbeMode.pstate = malloc(pVia->vbeMode.stateSize);
+ memcpy(pVia->vbeMode.pstate, pVia->vbeMode.state,
+ pVia->vbeMode.stateSize);
+ }
+Index: src/via_xvmc.c
+===================================================================
+--- src/via_xvmc.c (revision 811)
++++ src/via_xvmc.c (working copy)
+@@ -151,7 +151,7 @@
+ for (i = 0; i < VIA_XVMC_MAX_CONTEXTS; ++i) {
+ vXvMC->contexts[i] = 0;
+ if (vXvMC->cPrivs[i]) {
+- xfree(vXvMC->cPrivs[i]);
++ free(vXvMC->cPrivs[i]);
+ vXvMC->cPrivs[i] = 0;
+ }
+ }
+@@ -159,7 +159,7 @@
+ for (i = 0; i < VIA_XVMC_MAX_SURFACES; ++i) {
+ vXvMC->surfaces[i] = 0;
+ if (vXvMC->sPrivs[i]) {
+- xfree(vXvMC->sPrivs[i]);
++ free(vXvMC->sPrivs[i]);
+ vXvMC->sPrivs[i] = 0;
+ }
+ }
+@@ -270,7 +270,7 @@
+ /*
+ * Filling in the device dependent adaptor record.
+ * This is named "VIA Video Overlay" because this code falls under the
+- * XV extenstion, the name must match or it won't be used.
++ * XV extension, the name must match or it won't be used.
+ *
+ * For surface and subpicture, see above.
+ * The function pointers point to functions below.
+@@ -325,10 +325,11 @@
+
+ if ((pVia->Chipset == VIA_KM400) ||
+ (pVia->Chipset == VIA_CX700) ||
++ (pVia->Chipset == VIA_K8M890) ||
++ (pVia->Chipset == VIA_P4M900) ||
+ (pVia->Chipset == VIA_VX800) ||
+ (pVia->Chipset == VIA_VX855) ||
+- (pVia->Chipset == VIA_K8M890) ||
+- (pVia->Chipset == VIA_P4M900)) {
++ (pVia->Chipset == VIA_VX900)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "[XvMC] XvMC is not supported on this chipset.\n");
+ return;
+@@ -424,7 +425,7 @@
+ viaPortPrivPtr pPriv = XvAdaptors[i]->pPortPrivates[j].ptr;
+
+ if (pPriv->xvmc_priv)
+- xfree(pPriv->xvmc_priv);
++ free(pPriv->xvmc_priv);
+ }
+ }
+ pVia->XvMCEnabled = 0;
+@@ -460,7 +461,7 @@
+ return BadAlloc;
+ }
+
+- *priv = xcalloc(1, sizeof(ViaXvMCCreateContextRec));
++ *priv = calloc(1, sizeof(ViaXvMCCreateContextRec));
+ contextRec = (ViaXvMCCreateContextRec *) * priv;
+
+ if (!*priv) {
+@@ -475,12 +476,12 @@
+ break;
+ }
+
+- cPriv = (ViaXvMCContextPriv *) xcalloc(1, sizeof(ViaXvMCContextPriv));
++ cPriv = (ViaXvMCContextPriv *) calloc(1, sizeof(ViaXvMCContextPriv));
+
+ if (!cPriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] ViaXvMCCreateContext: Unable to allocate memory!\n");
+- xfree(*priv);
++ free(*priv);
+ *num_priv = 0;
+ return BadAlloc;
+ }
+@@ -532,7 +533,7 @@
+ return BadAlloc;
+ }
+
+- sPriv = (ViaXvMCSurfacePriv *) xcalloc(1, sizeof(ViaXvMCSurfacePriv));
++ sPriv = (ViaXvMCSurfacePriv *) calloc(1, sizeof(ViaXvMCSurfacePriv));
+
+ if (!sPriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+@@ -566,13 +567,13 @@
+ #endif
+ *num_priv = numBuffers + 2;
+
+- *priv = (INT32 *) xcalloc(*num_priv, sizeof(INT32));
++ *priv = (INT32 *) calloc(*num_priv, sizeof(INT32));
+
+ if (!*priv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] ViaXvMCCreateSurface: Unable to allocate memory!\n");
+ *num_priv = 0;
+- xfree(sPriv);
++ free(sPriv);
+ return BadAlloc;
+ }
+
+@@ -588,8 +589,8 @@
+ sPriv->memory_ref.pool = 0;
+ if (VIAAllocLinear(&(sPriv->memory_ref), pScrn,
+ numBuffers * bufSize + 32)) {
+- xfree(*priv);
+- xfree(sPriv);
++ free(*priv);
++ free(sPriv);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSurface: "
+ "Unable to allocate frambuffer memory!\n");
+ return BadAlloc;
+@@ -631,7 +632,7 @@
+ return BadAlloc;
+ }
+
+- sPriv = (ViaXvMCSurfacePriv *) xcalloc(1, sizeof(ViaXvMCSurfacePriv));
++ sPriv = (ViaXvMCSurfacePriv *) calloc(1, sizeof(ViaXvMCSurfacePriv));
+
+ if (!sPriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:"
+@@ -640,13 +641,13 @@
+ return BadAlloc;
+ }
+
+- *priv = (INT32 *) xcalloc(3, sizeof(INT32));
++ *priv = (INT32 *) calloc(3, sizeof(INT32));
+
+ if (!*priv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:"
+ " Unable to allocate memory!\n");
+ *num_priv = 0;
+- xfree(sPriv);
++ free(sPriv);
+ return BadAlloc;
+ }
+
+@@ -663,8 +664,8 @@
+ bufSize = size_xx44(ctx->width, ctx->height);
+ sPriv->memory_ref.pool = 0;
+ if (VIAAllocLinear(&(sPriv->memory_ref), pScrn, 1 * bufSize + 32)) {
+- xfree(*priv);
+- xfree(sPriv);
++ free(*priv);
++ free(sPriv);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:"
+ " Unable to allocate framebuffer memory!\n");
+ return BadAlloc;
+@@ -701,7 +702,7 @@
+ vx->ctxDisplaying = 0;
+ }
+
+- xfree(vXvMC->cPrivs[i]);
++ free(vXvMC->cPrivs[i]);
+ vXvMC->cPrivs[i] = 0;
+ vXvMC->nContexts--;
+ vXvMC->contexts[i] = 0;
+@@ -736,7 +737,7 @@
+ }
+
+ VIAFreeLinear(&(vXvMC->sPrivs[i]->memory_ref));
+- xfree(vXvMC->sPrivs[i]);
++ free(vXvMC->sPrivs[i]);
+ vXvMC->nSurfaces--;
+ vXvMC->sPrivs[i] = 0;
+ vXvMC->surfaces[i] = 0;
+@@ -778,7 +779,7 @@
+ }
+
+ VIAFreeLinear(&(vXvMC->sPrivs[i]->memory_ref));
+- xfree(vXvMC->sPrivs[i]);
++ free(vXvMC->sPrivs[i]);
+ vXvMC->nSurfaces--;
+ vXvMC->sPrivs[i] = 0;
+ vXvMC->surfaces[i] = 0;
+@@ -828,7 +829,7 @@
+ for (j = 0; j < XvAdapt->nPorts; ++j) {
+ pPriv = (viaPortPrivPtr) XvAdapt->pPortPrivates[j].ptr;
+
+- if (NULL == (pPriv->xvmc_priv = xcalloc(1, sizeof(ViaXvMCXVPriv))))
++ if (NULL == (pPriv->xvmc_priv = calloc(1, sizeof(ViaXvMCXVPriv))))
+ return BadAlloc;
+
+ for (i = 0; i < VIA_NUM_XVMC_ATTRIBUTES; ++i) {
+Index: src/via_cursor.c
+===================================================================
+--- src/via_cursor.c (revision 811)
++++ src/via_cursor.c (working copy)
+@@ -98,6 +98,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ pVia->CursorRegControl = VIA_REG_HI_CONTROL0;
+ pVia->CursorRegBase = VIA_REG_HI_BASE0;
+@@ -145,9 +146,12 @@
+ infoPtr->ShowCursor = viaShowCursor;
+ infoPtr->UseHWCursor = viaUseHWCursor;
+
++ /* ARGB Cursor init */
+ infoPtr->UseHWCursorARGB = viaUseHWCursorARGB;
+- if (pVia->CursorARGBSupported)
++ if (pVia->CursorARGBSupported) {
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HWCursor ARGB enabled\n"));
+ infoPtr->LoadCursorARGB = viaLoadCursorARGB;
++ }
+
+ /* Set cursor location in frame buffer. */
+ VIASETREG(VIA_REG_CURSOR_MODE, pVia->cursorOffset);
+@@ -166,6 +170,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ VIASETREG(VIA_REG_PRIM_HI_INVTCOLOR, 0x00FFFFFF);
+ VIASETREG(VIA_REG_V327_HI_INVTCOLOR, 0x00FFFFFF);
+@@ -225,6 +230,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ pVia->CursorPrimHiInvtColor = VIAGETREG(VIA_REG_PRIM_HI_INVTCOLOR);
+ pVia->CursorV327HiInvtColor = VIAGETREG(VIA_REG_V327_HI_INVTCOLOR);
+@@ -265,6 +271,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ VIASETREG(VIA_REG_PRIM_HI_INVTCOLOR, pVia->CursorPrimHiInvtColor);
+ VIASETREG(VIA_REG_V327_HI_INVTCOLOR, pVia->CursorV327HiInvtColor);
+@@ -284,7 +291,7 @@
+ }
+
+ /*
+- * ARGB Cursor
++ * display the current cursor
+ */
+
+ void
+@@ -298,6 +305,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ VIASETREG(VIA_REG_HI_CONTROL0, 0x36000005);
+ }
+@@ -319,13 +327,19 @@
+ */
+
+ /* Duoview */
+- if (pVia->CursorPipe)
++ if (pVia->CursorPipe) {
++ /* Mono Cursor Display Path [bit31]: Secondary */
++ /* FIXME For CLE266 and KM400 try to enable 32x32 cursor size [bit1] */
+ VIASETREG(VIA_REG_ALPHA_CONTROL, 0xF6000005);
+- else
++ } else {
++ /* Mono Cursor Display Path [bit31]: Primary */
+ VIASETREG(VIA_REG_ALPHA_CONTROL, 0x76000005);
++ }
+ }
+ }
+
++
++/* hide the current cursor */
+ void
+ viaHideCursor(ScrnInfoPtr pScrn)
+ {
+@@ -338,6 +352,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ temp = VIAGETREG(VIA_REG_HI_CONTROL0);
+ VIASETREG(VIA_REG_HI_CONTROL0, temp & 0xFFFFFFFA);
+@@ -350,10 +365,16 @@
+
+ default:
+ temp = VIAGETREG(VIA_REG_ALPHA_CONTROL);
++ /* Hardware cursor disable [bit0] */
+ VIASETREG(VIA_REG_ALPHA_CONTROL, temp & 0xFFFFFFFA);
+ }
+ }
+
++/*
++ Set the cursor position to (x,y). X and/or y may be negative
++ indicating that the cursor image is partially offscreen on
++ the left and/or top edges of the screen.
++*/
+ static void
+ viaSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+ {
+@@ -380,6 +401,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ VIASETREG(VIA_REG_HI_POS0, ((x << 16) | (y & 0x07ff)));
+ VIASETREG(VIA_REG_HI_OFFSET0, ((xoff << 16) | (yoff & 0x07ff)));
+@@ -409,6 +431,15 @@
+ && pCurs->bits->height <= pVia->CursorMaxHeight);
+ }
+
++/*
++ If the driver is unable to use a hardware cursor for reasons
++ other than the cursor being larger than the maximum specified
++ in the MaxWidth or MaxHeight field below, it can supply the
++ UseHWCursor function. If UseHWCursor is provided by the driver,
++ it will be called whenever the cursor shape changes or the video
++ mode changes. This is useful for when the hardware cursor cannot
++ be used in interlaced or doublescan modes.
++*/
+ static Bool
+ viaUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+ {
+@@ -423,8 +454,11 @@
+ && pCurs->bits->height <= pVia->CursorMaxHeight);
+ }
+
++/*
++ Load Mono Cursor Image
++*/
+ static void
+-viaLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *s)
++viaLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+ CARD32 temp;
+@@ -439,7 +473,7 @@
+ if (pVia->CursorARGBSupported) {
+ #define ARGB_PER_CHUNK (8 * sizeof (chunk) / 2)
+ for (i = 0; i < (pVia->CursorMaxWidth * pVia->CursorMaxHeight / ARGB_PER_CHUNK); i++) {
+- chunk = *s++;
++ chunk = *src++;
+ for (j = 0; j < ARGB_PER_CHUNK; j++, chunk >>= 2)
+ *dst++ = mono_cursor_color[chunk & 3];
+ }
+@@ -447,7 +481,7 @@
+ pVia->CursorFG = mono_cursor_color[3];
+ pVia->CursorBG = mono_cursor_color[2];
+ } else {
+- memcpy(dst, (CARD8*)s, pVia->CursorSize);
++ memcpy(dst, (CARD8*)src, pVia->CursorSize);
+ }
+ switch(pVia->Chipset) {
+ case VIA_CX700:
+@@ -455,6 +489,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ temp = VIAGETREG(VIA_REG_HI_CONTROL0);
+ VIASETREG(VIA_REG_HI_CONTROL0, temp & 0xFFFFFFFE);
+@@ -471,11 +506,17 @@
+ }
+ }
+
++/*
++ Set the cursor foreground and background colors. In 8bpp, fg and
++ bg are indices into the current colormap unless the
++ HARDWARE_CURSOR_TRUECOLOR_AT_8BPP flag is set. In that case
++ and in all other bpps the fg and bg are in 8-8-8 RGB format.
++*/
++
+ static void
+ viaSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+- CARD32 control = pVia->CursorRegControl;
+ CARD32 pixel;
+ CARD32 temp;
+ CARD32 *dst;
+@@ -487,12 +528,10 @@
+ fg |= 0xff000000;
+ bg |= 0xff000000;
+
++ /* Don't recolour the image if we don't have to. */
+ if (fg == pVia->CursorFG && bg == pVia->CursorBG)
+ return;
+
+- temp = VIAGETREG(control);
+- VIASETREG(control, temp & 0xFFFFFFFE);
+-
+ dst = (CARD32*)pVia->cursorMap;
+ for (i = 0; i < pVia->CursorMaxWidth * pVia->CursorMaxHeight; i++, dst++)
+ if ((pixel = *dst))
+@@ -507,6 +546,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ temp = VIAGETREG(VIA_REG_HI_CONTROL0);
+ VIASETREG(VIA_REG_HI_CONTROL0, temp & 0xFFFFFFFE);
+@@ -517,7 +557,8 @@
+ }
+ break;
+ default:
+- VIASETREG(control, temp);
++ temp = VIAGETREG(VIA_REG_ALPHA_CONTROL);
++ VIASETREG(VIA_REG_ALPHA_CONTROL, temp & 0xFFFFFFFE);
+ }
+ }
+
+Index: src/via_i2c.c
+===================================================================
+--- src/via_i2c.c (revision 811)
++++ src/via_i2c.c (working copy)
+@@ -365,9 +365,18 @@
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2CInit\n"));
+
+- pVia->pI2CBus1 = ViaI2CBus1Init(pScrn->scrnIndex);
+- pVia->pI2CBus2 = ViaI2CBus2Init(pScrn->scrnIndex);
+- pVia->pI2CBus3 = ViaI2CBus3Init(pScrn->scrnIndex);
++ if (!pVia->I2CDevices) {
++ pVia->pI2CBus1 = ViaI2CBus1Init(pScrn->scrnIndex);
++ pVia->pI2CBus2 = ViaI2CBus2Init(pScrn->scrnIndex);
++ pVia->pI2CBus3 = ViaI2CBus3Init(pScrn->scrnIndex);
++ } else {
++ if (pVia->I2CDevices & VIA_I2C_BUS1)
++ pVia->pI2CBus1 = ViaI2CBus1Init(pScrn->scrnIndex);
++ if (pVia->I2CDevices & VIA_I2C_BUS2)
++ pVia->pI2CBus2 = ViaI2CBus2Init(pScrn->scrnIndex);
++ if (pVia->I2CDevices & VIA_I2C_BUS3)
++ pVia->pI2CBus3 = ViaI2CBus3Init(pScrn->scrnIndex);
++ }
+
+ #ifdef HAVE_DEBUG
+ if (pVia->I2CScan) {
+Index: src/via_dri.c
+===================================================================
+--- src/via_dri.c (revision 811)
++++ src/via_dri.c (working copy)
+@@ -187,7 +187,7 @@
+ return FALSE;
+
+ /*
+- * Info frome code-snippet on DRI-DEVEL list; Erdi Chen.
++ * Info from code-snippet on DRI-DEVEL list; Erdi Chen.
+ */
+
+ switch (pVia->ChipId) {
+@@ -267,6 +267,7 @@
+ pVIADRI = pDRIInfo->devPrivate;
+ pVia->agpSize = 0;
+
++
+ if (drmAgpAcquire(pVia->drmFD) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed %d\n",
+ errno);
+@@ -431,17 +432,17 @@
+ if (pScrn->bitsPerPixel == 16 || pScrn->bitsPerPixel == 32) {
+ numConfigs = 12;
+ if (!(pConfigs = (__GLXvisualConfig *)
+- xcalloc(sizeof(__GLXvisualConfig), numConfigs)))
++ calloc(sizeof(__GLXvisualConfig), numConfigs)))
+ return FALSE;
+ if (!(pVIAConfigs = (VIAConfigPrivPtr)
+- xcalloc(sizeof(VIAConfigPrivRec), numConfigs))) {
+- xfree(pConfigs);
++ calloc(sizeof(VIAConfigPrivRec), numConfigs))) {
++ free(pConfigs);
+ return FALSE;
+ }
+ if (!(pVIAConfigPtrs = (VIAConfigPrivPtr *)
+- xcalloc(sizeof(VIAConfigPrivPtr), numConfigs))) {
+- xfree(pConfigs);
+- xfree(pVIAConfigs);
++ calloc(sizeof(VIAConfigPrivPtr), numConfigs))) {
++ free(pConfigs);
++ free(pVIAConfigs);
+ return FALSE;
+ }
+ for (i = 0; i < numConfigs; i++)
+@@ -593,23 +594,28 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ pDRIInfo->clientDriverName = "swrast";
+ break;
+ default:
+ pDRIInfo->clientDriverName = VIAClientDriverName;
+ break;
+ }
+- pDRIInfo->busIdString = xalloc(64);
+- sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
++ if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
++ pDRIInfo->busIdString = DRICreatePCIBusID(pVia->PciInfo);
++ } else {
++ pDRIInfo->busIdString = malloc(64);
++ sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
+ #ifdef XSERVER_LIBPCIACCESS
+- ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus),
+- pVia->PciInfo->dev, pVia->PciInfo->func
++ ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus),
++ pVia->PciInfo->dev, pVia->PciInfo->func
+ #else
+- ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum,
+- ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum,
+- ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum
++ ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum,
++ ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum,
++ ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum
+ #endif
+- );
++ );
++ }
+ pDRIInfo->ddxDriverMajorVersion = VIA_DRIDDX_VERSION_MAJOR;
+ pDRIInfo->ddxDriverMinorVersion = VIA_DRIDDX_VERSION_MINOR;
+ pDRIInfo->ddxDriverPatchVersion = VIA_DRIDDX_VERSION_PATCH;
+@@ -646,7 +652,7 @@
+ pDRIInfo->SAREASize = SAREA_MAX;
+ #endif
+
+- if (!(pVIADRI = (VIADRIPtr) xcalloc(sizeof(VIADRIRec), 1))) {
++ if (!(pVIADRI = (VIADRIPtr) calloc(sizeof(VIADRIRec), 1))) {
+ DRIDestroyInfoRec(pVia->pDRIInfo);
+ pVia->pDRIInfo = NULL;
+ return FALSE;
+@@ -665,7 +671,7 @@
+ if (!DRIScreenInit(pScreen, pDRIInfo, &pVia->drmFD)) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed. Disabling DRI.\n");
+- xfree(pDRIInfo->devPrivate);
++ free(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate = NULL;
+ DRIDestroyInfoRec(pVia->pDRIInfo);
+ pVia->pDRIInfo = NULL;
+@@ -748,7 +754,7 @@
+ if (pVia->pDRIInfo) {
+ if ((pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate)) {
+ VIADRIIrqExit(pScrn, pVIADRI);
+- xfree(pVIADRI);
++ free(pVIADRI);
+ pVia->pDRIInfo->devPrivate = NULL;
+ }
+ DRIDestroyInfoRec(pVia->pDRIInfo);
+@@ -756,11 +762,11 @@
+ }
+
+ if (pVia->pVisualConfigs) {
+- xfree(pVia->pVisualConfigs);
++ free(pVia->pVisualConfigs);
+ pVia->pVisualConfigs = NULL;
+ }
+ if (pVia->pVisualConfigsPriv) {
+- xfree(pVia->pVisualConfigsPriv);
++ free(pVia->pVisualConfigsPriv);
+ pVia->pVisualConfigsPriv = NULL;
+ }
+ }
+Index: src/via.h
+===================================================================
+--- src/via.h (revision 811)
++++ src/via.h (working copy)
+@@ -34,7 +34,7 @@
+
+ /* Video Engines */
+ #define VIDEO_ENGINE_UNK 0 /* Unknown video engine */
+-#define VIDEO_ENGINE_CLE 1 /* CLE First generaion video engine */
++#define VIDEO_ENGINE_CLE 1 /* CLE First generation video engine */
+ #define VIDEO_ENGINE_CME 2 /* CME Second generation video engine */
+
+ /* Video status flag */
+@@ -215,6 +215,9 @@
+ #define HQV_DST_STRIDE 0x1F4
+ #define HQV_SRC_STRIDE 0x1F8
+
++#define HQV_H_SCALE_CONTROL 0x1B0
++#define HQV_V_SCALE_CONTROL 0x1B4
++
+ #define PRO_HQV1_OFFSET 0x1000
+ /*
+ * Video command definition
+@@ -515,7 +518,23 @@
+ #define HQV_FIFO_STATUS 0x00001000
+ #define HQV_GEN_IRQ 0x00000080
+ #define HQV_FIFO_DEPTH_1 0x00010000
++/* for CME engine */
++#define HQV_SW_FLIP_QUEUE_ENABLE 0x00100000
+
++/* for hwDiff->dwNewScaleCtl */
++#define HQV_H_SCALE_ENABLE 0x80000000
++#define HQV_H_SCALE_UP 0x00000000
++#define HQV_H_SCALE_DOWN_FOURTH_TO_1 0x10000000
++#define HQV_H_SCALE_DOWN_FOURTH_TO_EIGHTH 0x20000000
++#define HQV_H_SCALE_DOWN_UNDER_EIGHTH 0x30000000
++
++#define HQV_V_SCALE_ENABLE 0x80000000
++#define HQV_V_SCALE_UP 0x00000000
++#define HQV_V_SCALE_DOWN 0x10000000
++
++/* HQV Default Vodeo Color 0x3B8 */
++#define HQV_FIX_COLOR 0x0643212c
++
+ /* HQV_FILTER_CONTROL 0x3E4 */
+ #define HQV_H_LOWPASS_2TAP 0x00000001
+ #define HQV_H_LOWPASS_4TAP 0x00000002
+@@ -575,6 +594,25 @@
+ #define HQV_VDEBLOCK_FILTER 0x80000000
+ #define HQV_HDEBLOCK_FILTER 0x00008000
+
++/* new added registers for VT3409.For some registers have different meanings
++ * but the same address,we add postfix _409 to distinguish */
++#define HQV_COLOR_ADJUSTMENT_PRE_CTRL1 0x160
++#define HQV_COLOR_ADJUSTMENT_PRE_CTRL2 0x164
++#define HQV_COLOR_ADJUSTMENT_PRE_CTRL3 0x168
++#define HQV_COLOR_ADJUSTMENT_PRE_CTRL4 0x16C
++#define HQV_SRC_DATA_OFFSET_CTRL1_409 0x170
++#define HQV_SRC_DATA_OFFSET_CTRL2_409 0x174
++#define HQV_SRC_DATA_OFFSET_CTRL3_409 0x178
++#define HQV_SRC_DATA_OFFSET_CTRL4_409 0x17C
++#define HQV_DST_DATA_OFFSET_CTRL1 0x180
++#define HQV_DST_DATA_OFFSET_CTRL2 0x184
++#define HQV_DST_DATA_OFFSET_CTRL3 0x188
++#define HQV_DST_DATA_OFFSET_CTRL4 0x18C
++#define HQV_RESIDUE_PIXEL_FRAME_STARTADDR 0x1BC
++#define HQV_BACKGROUND_DATA_OFFSET 0x1CC
++#define HQV_SUBP_HSCALE_CTRL 0x1E0
++#define HQV_SUBP_VSCALE_CTRL 0x1E8
++
+ /* Add new HQV Registers for VT3353: */
+ #define HQV_SRC_DATA_OFFSET_CONTROL1 0x180
+ #define HQV_SRC_DATA_OFFSET_CONTROL2 0x184
+@@ -588,6 +626,7 @@
+ #define HQV_COLOR_ADJUSTMENT_CONTROL2 0x1A4
+ #define HQV_COLOR_ADJUSTMENT_CONTROL3 0x1A8
+ #define HQV_COLOR_ADJUSTMENT_CONTROL5 0x1AC
++#define HQV_DEFAULT_VIDEO_COLOR 0x1B8
+
+ #define CHROMA_KEY_LOW 0x00FFFFFF
+ #define CHROMA_KEY_HIGH 0x00FFFFFF
+Index: man/openchrome.man
+===================================================================
+--- man/openchrome.man (.../tags/release_0_2_904) (revision 921)
++++ man/openchrome.man (.../trunk) (revision 921)
+@@ -22,7 +22,7 @@ The
+ .B openchrome
+ driver supports the following chipsets: CLE266, KM400/KN400/KM400A/P4M800,
+ CN400/PM800/PN800/PM880, K8M800, CN700/VM800/P4M800Pro, CX700, P4M890, K8M890,
+-P4M900/VN896/CN896, VX800 and VX855.
++P4M900/VN896/CN896, VX800, VX855 and VX900.
+ The driver includes 2D acceleration and Xv video overlay extensions.
+ Flat panel, TV, and VGA outputs are supported, depending on the hardware
+ configuration.
+@@ -59,16 +59,18 @@ are supported:
+ .BI "Option \*qAccelMethod\*q \*q" string \*q
+ The driver supports "XAA" and "EXA" acceleration methods. The default
+ method is XAA, since EXA is still experimental. Contrary to XAA, EXA
+-implements acceleration for screen uploads and downlads (if DRI is
++implements acceleration for screen uploads and downloads (if DRI is
+ enabled) and for the Render/Composite extension.
+ .TP
+ .BI "Option \*qActiveDevice\*q \*q" string \*q
+ Specifies the active device combination. Any string containing "CRT",
+ "LCD", "DFP", "TV" should be possible. "CRT" represents anything that
+-is connected to the VGA port, "LCD" and "DFP" are for laptop panels
+-(not TFT screens attached to the VGA port), "TV" is self-explanatory.
++is connected to the VGA port, "LCD" is for laptop panels (not TFT screens
++attached to the VGA port), "DFP" is for screens connected to the DVI port,
++"TV" is self-explanatory.
+ The default is to use what is detected. The driver is currently unable
+-to use LCD and TV simultaneously, and will favour the LCD.
++to use LCD and TV simultaneously, and will favour the LCD. The DVI port is
++not properly probed and needs to be enabled with this option.
+ .TP
+ .BI "Option \*qAGPMem\*q \*q" integer \*q
+ Sets the amount of AGP memory that is allocated at X server startup.
+@@ -81,7 +83,7 @@ EXA scratch area in AGP space, it will be allocate
+ no room for DRI textures, they will be allocated from the DRI part of
+ VRAM (see the option "MaxDRIMem"). The default amount of AGP is
+ 32768 kB. Note that the AGP aperture set in the BIOS must be able
+-to accomodate the amount of AGP memory specified here. Otherwise no
++to accommodate the amount of AGP memory specified here. Otherwise no
+ AGP memory will be available. It is safe to set a very large AGP
+ aperture in the BIOS.
+ .TP
+@@ -131,10 +133,10 @@ as possible to the EXA pixmap storage area.
+ .TP
+ .BI "Option \*qMigrationHeuristic\*q \*q" string \*q
+ Sets the heuristic for EXA pixmap migration. This is an EXA core
+-option, and on Xorg server versions after 1.1.0 this defaults to
+-"smart". The openchrome driver performs best with "greedy", so you
++option, and starting from __xservername__ server version 1.3.0 this defaults to
++"always". The openchrome driver performs best with "greedy", so you
+ should really add this option to your configuration file. The third
+-possibility is "always", which might become more useful in the future.
++possibility is "smart".
+ .TP
+ .BI "Option \*qNoAccel\*q \*q" boolean \*q
+ Disables the use of hardware acceleration. Acceleration is enabled
+@@ -159,9 +161,16 @@ Specifies the size (width x height) of the LCD pan
+ system. The sizes 640x480, 800x600, 1024x768, 1280x1024, and 1400x1050
+ are supported.
+ .TP
++.BI "Option \*qRotationType\*q \*q" string \*q
++Enabled rotation by using RandR. The driver only support unaccelerated
++RandR rotations "SWRandR". Hardware rotations "HWRandR" is currently
++unimplemented.
++.TP
+ .BI "Option \*qRotate\*q \*q" string \*q
+ Rotates the display either clockwise ("CW"), counterclockwise ("CCW") and
+-upside-down ("UD"). Rotation is only supported unaccelerated.
++upside-down ("UD"). Rotation is only supported unaccelerated. Adding
++option "Rotate", enables RandR rotation feature. The RandR allows
++clients to dynamically change X screens.
+ .TP
+ .BI "Option \*qShadowFB\*q \*q" boolean \*q
+ Enables the use of a shadow frame buffer. This is required when
+@@ -234,6 +243,6 @@ overscan). These modes are made available by the
+ provided in __xconfigfile__ will be ignored.
+
+ .SH "SEE ALSO"
+-__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
++__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__), EXA(__filemansuffix__), Xv(__filemansuffix__)
+ .SH AUTHORS
+ Authors include: ...
+Index: src/via_dga.c
+===================================================================
+--- src/via_dga.c (revision 811)
++++ src/via_dga.c (working copy)
+@@ -89,16 +89,16 @@
+ otherPitch = secondPitch ? secondPitch : pMode->HDisplay;
+
+ if (pMode->HDisplay != otherPitch) {
+- newmodes = xrealloc(modes, (*num + 2) * sizeof(DGAModeRec));
++ newmodes = realloc(modes, (*num + 2) * sizeof(DGAModeRec));
+ oneMore = TRUE;
+ }
+ else {
+- newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec));
++ newmodes = realloc(modes, (*num + 1) * sizeof(DGAModeRec));
+ oneMore = FALSE;
+ }
+
+ if (!newmodes) {
+- xfree(modes);
++ free(modes);
+ return NULL;
+ }
+
+Index: src/via_id.c
+===================================================================
+--- src/via_id.c (revision 811)
++++ src/via_id.c (working copy)
+@@ -63,6 +63,7 @@
+ {"Giga-byte 7VM400(A)M", VIA_KM400, 0x1458, 0xD000, VIA_DEVICE_CRT},
+ {"MSI KM4(A)M-V", VIA_KM400, 0x1462, 0x7061, VIA_DEVICE_CRT}, /* aka "DFI KM400-MLV" */
+ {"MSI PM8M2-V", VIA_KM400, 0x1462, 0x7071, VIA_DEVICE_CRT},
++ {"MSI PM8M-V", VIA_KM400, 0x1462, 0x7104, VIA_DEVICE_CRT},
+ {"MSI KM4(A)M-L", VIA_KM400, 0x1462, 0x7348, VIA_DEVICE_CRT},
+ {"Abit VA-10 (1)", VIA_KM400, 0x147B, 0x140B, VIA_DEVICE_CRT},
+ {"Abit VA-10 (2)", VIA_KM400, 0x147B, 0x140C, VIA_DEVICE_CRT},
+@@ -92,6 +93,7 @@
+ {"Shuttle FX21", VIA_K8M800, 0x1297, 0x3052, VIA_DEVICE_CRT},
+ {"Shuttle FX83", VIA_K8M800, 0x1297, 0xF683, VIA_DEVICE_CRT | VIA_DEVICE_TV},
+ {"Sharp Actius AL27", VIA_K8M800, 0x13BD, 0x1044, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Sharp Mebius PC-CS30H", VIA_K8M800, 0x13BD, 0x1047, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Sharp PC-AE30J", VIA_K8M800, 0x13BD, 0x104B, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Giga-byte GA-K8VM800M", VIA_K8M800, 0x1458, 0xD000, VIA_DEVICE_CRT},
+ {"MSI K8M Neo-V", VIA_K8M800, 0x1462, 0x0320, VIA_DEVICE_CRT},
+@@ -114,6 +116,7 @@
+ {"Packard Bell Easynote B3 800/B3340", VIA_K8M800, 0x1631, 0xC009, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Packard Bell Imedia 2097", VIA_K8M800, 0x1631, 0xD007, VIA_DEVICE_CRT},
+ {"Fujitsu-Siemens Amilo K7610", VIA_K8M800, 0x1734, 0x10B3, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Lenovo ThinkCenter E51 8714", VIA_K8M800, 0x17AA, 0x1008, VIA_DEVICE_CRT},
+ {"ASRock K8Upgrade-VM800", VIA_K8M800, 0x1849, 0x3108, VIA_DEVICE_CRT},
+ {"Axper XP-M8VM800", VIA_K8M800, 0x1940, 0xD000, VIA_DEVICE_CRT},
+
+@@ -138,6 +141,7 @@
+ {"Haier A60-440256080BD", VIA_VM800, 0x1019, 0x0F79, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"PCChips P23G", VIA_VM800, 0x1019, 0x1623, VIA_DEVICE_CRT},
+ {"ECS P4M800PRO-M", VIA_VM800, 0x1019, 0x2122, VIA_DEVICE_CRT},
++ {"ECS P4M800PRO-M2 (V2.0)", VIA_VM800, 0x1019, 0x2123, VIA_DEVICE_CRT},
+ {"ECS C7VCM", VIA_VM800, 0x1019, 0xAA2D, VIA_DEVICE_CRT},
+ {"PCChips V21G", VIA_VM800, 0x1019, 0xAA51, VIA_DEVICE_CRT},
+ {"Asustek P5VDC-MX", VIA_VM800, 0x1043, 0x3344, VIA_DEVICE_CRT},
+@@ -152,6 +156,7 @@
+ {"MSI PM8PM", VIA_VM800, 0x1462, 0x7222, VIA_DEVICE_CRT},
+ {"Twinhead M6", VIA_VM800, 0x14FF, 0xA007, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"RoverBook Partner W500", VIA_VM800, 0x1509, 0x4330, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"FIC PTM800Pro LF", VIA_VM800, 0x1509, 0x601A, VIA_DEVICE_CRT},
+ {"Clevo/RoverBook Voyager V511L", VIA_VM800, 0x1558, 0x0662, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Clevo M5xxS", VIA_VM800, 0x1558, 0x5406, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Biostar P4M80-M4 / P4VMA-M", VIA_VM800, 0x1565, 0x1202, VIA_DEVICE_CRT},
+@@ -170,6 +175,7 @@
+ {"Asustek M2V-MX SE", VIA_K8M890, 0x1043, 0x8297, VIA_DEVICE_CRT},
+ {"Foxconn K8M890M2MA-RS2H", VIA_K8M890, 0x105B, 0x0C84, VIA_DEVICE_CRT},
+ {"Shuttle FX22V1", VIA_K8M890, 0x1297, 0x3080, VIA_DEVICE_CRT},
++ {"MSI K8M890M2-V", VIA_K8M890, 0x1462, 0x7139, VIA_DEVICE_CRT},
+ {"MSI K9VGM-V", VIA_K8M890, 0x1462, 0x7253, VIA_DEVICE_CRT},
+ {"Averatec 226x", VIA_K8M890, 0x14FF, 0xA002, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Fujitsu/Siemens Amilo La 1703", VIA_K8M890, 0x1734, 0x10D9, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+@@ -183,12 +189,14 @@
+ {"Mitac 8515", VIA_P4M900, 0x1071, 0x8515, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Medion Notebook MD96483", VIA_P4M900, 0x1071, 0x8615, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Mitac 8624", VIA_P4M900, 0x1071, 0x8624, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+- {"VIA VT3364 (P4M900)", VIA_P4M900, 0x1106, 0x3371, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"VIA VB8001 Mini-ITX Board (P4M900)", VIA_P4M900, 0x1106, 0x3371, VIA_DEVICE_CRT},
+ {"Gigabyte GA-VM900M", VIA_P4M900, 0x1458, 0xD000, VIA_DEVICE_CRT},
+ {"MSI VR321", VIA_P4M900, 0x1462, 0x3355, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"MSI P4M900M / P4M900M2-F/L", VIA_P4M900, 0x1462, 0x7255, VIA_DEVICE_CRT},
+ {"MSI P4M900M3-L", VIA_P4M900, 0x1462, 0x7387, VIA_DEVICE_CRT},
+ {"Twinhead H12V", VIA_P4M900, 0x14FF, 0xA00F, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Twinhead K15V", VIA_P4M900, 0x14FF, 0xA012, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Semp Informática Notebook IS 1462", VIA_P4M900, 0x1509, 0x1D41, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Everex NC1501/NC1503", VIA_P4M900, 0x1509, 0x1E30, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Clevo M660SE", VIA_P4M900, 0x1558, 0x0664, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Clevo M660SR", VIA_P4M900, 0x1558, 0x0669, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+@@ -224,14 +232,23 @@
+
+ /*** VX800 ***/
+ {"VIA Epia M700", VIA_VX800, 0x1106, 0x1122, VIA_DEVICE_CRT},
++ {"Siragon ML-6200", VIA_VX800, 0x1106, 0x2211, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Guillemot-Hercules ECafe EC900B", VIA_VX800, 0x1106, 0x3349, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"VIA OpenBook", VIA_VX800, 0x1170, 0x0311, VIA_DEVICE_CRT | VIA_DEVICE_LCD}, /* VIA OpenBook eNote VBE8910 */
+ {"Samsung NC20", VIA_VX800, 0x144d, 0xc04e, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"FIC CE2A1", VIA_VX800, 0x1509, 0x3002, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Quanta DreamBook Light IL1", VIA_VX800, 0x152d, 0x0771, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Lenovo S12", VIA_VX800, 0x17aa, 0x388c, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+
+ /*** VX855 ***/
+ {"VIA VT8562C", VIA_VX855, 0x1106, 0x5122, VIA_DEVICE_CRT},
++ {"OLPC XO 1.5", VIA_VX855, 0x152D, 0x0833, VIA_DEVICE_LCD},
+
++ /*** VX900 ***/
++ {"Foxconn L740", VIA_VX900, 0x105B, 0x0CFD, VIA_DEVICE_LCD | VIA_DEVICE_CRT},
++ {"HP T5550 Thin Client", VIA_VX900, 0x1106, 0x7122, VIA_DEVICE_CRT},
++
++
+ /* keep this */
+ {NULL, VIA_UNKNOWN, 0x0000, 0x0000, VIA_DEVICE_NONE}
+ };
+Index: src/via_timing.h
+===================================================================
+--- src/via_timing.h (revision 811)
++++ src/via_timing.h (working copy)
+@@ -40,7 +40,7 @@
+ #define TIMING_CVT_WARN_REFRESH_RATE_NOT_RB 1 << 3
+
+ /**
+- * Geneartes a CVT modeline
++ * Generates a CVT modeline
+ * mode must not be null, if mode->name is null a new char* will be allocated.
+ *
+ */
diff --git a/main/xf86-video-openchrome/openchrome.xinf b/main/xf86-video-openchrome/openchrome.xinf
new file mode 100644
index 0000000000..7b15c911a9
--- /dev/null
+++ b/main/xf86-video-openchrome/openchrome.xinf
@@ -0,0 +1,39 @@
+# NOTE: Comments in openchrome 0.2.1 driver source indicate this device does not
+# exist in the wild, so it has been disabled for now.
+#alias pcivideo:v00001106d00003022sv*sd*bc*sc*i* openchrome
+
+# 1106:3108 - K8M800 (PCI_CHIP_VT3204)
+alias pcivideo:v00001106d00003108sv*sd*bc*sc*i* openchrome
+
+# 1106:3118 - PM800/PM880/CN400 (PCI_CHIP_VT3259)
+alias pcivideo:v00001106d00003118sv*sd*bc*sc*i* openchrome
+
+# 1106:3122 - CLE266 (PCI_CHIP_CLE3122)
+alias pcivideo:v00001106d00003122sv*sd*bc*sc*i* openchrome
+
+# 1106:7205 - KM400/KN400 (PCI_CHIP_VT3205)
+alias pcivideo:v00001106d00007205sv*sd*bc*sc*i* openchrome
+
+# 1106:3344 - VM800 (PCI_CHIP_VT3314)
+alias pcivideo:v00001106d00003344sv*sd*bc*sc*i* openchrome
+
+# 1106:3157 - CX700 (PCI_CHIP_VT3324)
+alias pcivideo:v00001106d00003157sv*sd*bc*sc*i* openchrome
+
+# 1106:3343 - P4M890 (PCI_CHIP_VT3327)
+alias pcivideo:v00001106d00003343sv*sd*bc*sc*i* openchrome
+
+# 1106:3230 - K8M890 (PCI_CHIP_VT3336)
+alias pcivideo:v00001106d00003230sv*sd*bc*sc*i* openchrome
+
+# 1106:3371 - P4M900 (PCI_CHIP_VT3364)
+alias pcivideo:v00001106d00003371sv*sd*bc*sc*i* openchrome
+
+# 1106:1122 - VX800 (PCI_CHIP_VT3353)
+alias pcivideo:v00001106d00001122sv*sd*bc*sc*i* openchrome
+
+# 1106:5122 - VX855 (PCI_CHIP_VT3409)
+alias pcivideo:v00001106d00005122sv*sd*bc*sc*i* openchrome
+
+# 1106:7122 - VX855 (PCI_CHIP_VT3410)
+alias pcivideo:v00001106d00007122sv*sd*bc*sc*i* openchrome
diff --git a/main/xf86-video-r128/APKBUILD b/main/xf86-video-r128/APKBUILD
new file mode 100644
index 0000000000..5bc079b5c7
--- /dev/null
+++ b/main/xf86-video-r128/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-r128
+pkgver=6.8.1
+pkgrel=5
+pkgdesc="ATI Rage128 video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="mesa-dri-r128"
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto xineramaproto libdrm-dev xf86driproto glproto
+ mesa-dev expat-dev
+ "
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr \
+ --enable-dri \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="2b90854a62a4d45d652062f582dc8d13 xf86-video-r128-6.8.1.tar.bz2"
diff --git a/main/xf86-video-radeonhd/APKBUILD b/main/xf86-video-radeonhd/APKBUILD
new file mode 100644
index 0000000000..c880232746
--- /dev/null
+++ b/main/xf86-video-radeonhd/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-radeonhd
+pkgver=1.3.0
+pkgrel=4
+pkgdesc="Experimental Radeon HD video driver."
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="7b6641aa9d836f1621b9b220ad6771b8 xf86-video-radeonhd-1.3.0.tar.bz2"
diff --git a/main/xf86-video-rendition/APKBUILD b/main/xf86-video-rendition/APKBUILD
new file mode 100644
index 0000000000..83c70e8015
--- /dev/null
+++ b/main/xf86-video-rendition/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-rendition
+pkgver=4.2.4
+pkgrel=2
+pkgdesc="Rendition video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="75cc28125077acb7344955294545553b xf86-video-rendition-4.2.4.tar.bz2"
diff --git a/main/xf86-video-s3/APKBUILD b/main/xf86-video-s3/APKBUILD
new file mode 100644
index 0000000000..5b0fae41a2
--- /dev/null
+++ b/main/xf86-video-s3/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-s3
+pkgver=0.6.3
+pkgrel=4
+pkgdesc="X.Org driver for s3 cards"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org//releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="5eb06d88533fb327d067928faeb20860 xf86-video-s3-0.6.3.tar.bz2"
diff --git a/main/xf86-video-s3virge/APKBUILD b/main/xf86-video-s3virge/APKBUILD
new file mode 100644
index 0000000000..bb07857d9b
--- /dev/null
+++ b/main/xf86-video-s3virge/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-s3virge
+pkgver=1.10.4
+pkgrel=3
+pkgdesc="S3 ViRGE video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="6517bbbf808c700502d51acdc44662f8 xf86-video-s3virge-1.10.4.tar.bz2"
diff --git a/main/xf86-video-savage/APKBUILD b/main/xf86-video-savage/APKBUILD
new file mode 100644
index 0000000000..451bb5fca3
--- /dev/null
+++ b/main/xf86-video-savage/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-savage
+pkgver=2.3.2
+pkgrel=0
+pkgdesc="S3 Savage video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="mesa-dri-savage"
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto libdrm-dev xf86driproto mesa-dev glproto
+ "
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="09782fc710a1ce5a81c27d71951234c2 xf86-video-savage-2.3.2.tar.bz2"
diff --git a/main/xf86-video-siliconmotion/APKBUILD b/main/xf86-video-siliconmotion/APKBUILD
new file mode 100644
index 0000000000..ab77d77b14
--- /dev/null
+++ b/main/xf86-video-siliconmotion/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-siliconmotion
+pkgver=1.7.5
+pkgrel=0
+pkgdesc="Silicon Motion video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="9ca392e16028a2f7c3ebc57f0aa4c1aa xf86-video-siliconmotion-1.7.5.tar.bz2"
diff --git a/main/xf86-video-sis/APKBUILD b/main/xf86-video-sis/APKBUILD
new file mode 100644
index 0000000000..f80f9382c4
--- /dev/null
+++ b/main/xf86-video-sis/APKBUILD
@@ -0,0 +1,34 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-sis
+pkgver=0.10.3
+pkgrel=2
+pkgdesc="X.org SiS video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev videoproto renderproto xproto
+ fontsproto xf86dgaproto xineramaproto randrproto xextproto mesa-dev
+ xf86driproto glproto libxi-dev"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="dd930928b5ed7fcf34e3be4d43202ec7 xf86-video-sis-0.10.3.tar.bz2"
diff --git a/main/xf86-video-sis/fix-bios-read-on-650-760.patch b/main/xf86-video-sis/fix-bios-read-on-650-760.patch
new file mode 100644
index 0000000000..c948c833a8
--- /dev/null
+++ b/main/xf86-video-sis/fix-bios-read-on-650-760.patch
@@ -0,0 +1,23 @@
+From 8370499d4035ec7a5c8e1f1b04d5a6c404883442 Mon Sep 17 00:00:00 2001
+From: Matteo Delfino <kendatsuba@gmail.com>
+Date: Wed, 21 Oct 2009 14:26:45 +0000
+Subject: Fix BIOS read on 650 and 760. (#19070)
+
+Signed-off-by: Matteo Delfino <kendatsuba@gmail.com>
+Signed-off-by: Adam Jackson <ajax@redhat.com>
+---
+diff --git a/src/sis_driver.c b/src/sis_driver.c
+index 994b02d..b19e7a9 100644
+--- a/src/sis_driver.c
++++ b/src/sis_driver.c
+@@ -4099,6 +4099,8 @@ SISPreInit(ScrnInfoPtr pScrn, int flags)
+ case SIS_315H:
+ case SIS_330:
+ case SIS_340:
++ case SIS_650:
++ case SIS_760:
+ case XGI_40: readpci = TRUE;
+ break;
+ case XGI_20: readpci = TRUE;
+--
+cgit v0.8.2
diff --git a/main/xf86-video-sunleo/APKBUILD b/main/xf86-video-sunleo/APKBUILD
new file mode 100644
index 0000000000..e2bfdaa9d2
--- /dev/null
+++ b/main/xf86-video-sunleo/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-sunleo
+pkgver=1.2.0
+pkgrel=5
+pkgdesc="Leo video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="14fe008620940a674981912fa02ae133 xf86-video-sunleo-1.2.0.tar.bz2"
diff --git a/main/xf86-video-tdfx/APKBUILD b/main/xf86-video-tdfx/APKBUILD
new file mode 100644
index 0000000000..662082f4ec
--- /dev/null
+++ b/main/xf86-video-tdfx/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-tdfx
+pkgver=1.4.3
+pkgrel=4
+pkgdesc="3Dfx video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="mesa-dri-tdfx"
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto libdrm-dev xf86driproto mesa-dev glproto
+ "
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="8161bbf2b100c21b609163f0010766b3 xf86-video-tdfx-1.4.3.tar.bz2"
diff --git a/main/xf86-video-tseng/APKBUILD b/main/xf86-video-tseng/APKBUILD
new file mode 100644
index 0000000000..c530152f05
--- /dev/null
+++ b/main/xf86-video-tseng/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-tseng
+pkgver=1.2.4
+pkgrel=2
+pkgdesc="Tseng Labs video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="fa441774f8bf516a5c6331d64231a39d xf86-video-tseng-1.2.4.tar.bz2"
diff --git a/main/xf86-video-v4l/APKBUILD b/main/xf86-video-v4l/APKBUILD
new file mode 100644
index 0000000000..acb14ed03a
--- /dev/null
+++ b/main/xf86-video-v4l/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-v4l
+pkgver=0.2.0
+pkgrel=5
+pkgdesc="video4linux driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="2251ae2a0a905764941cd7b098e85ad1 xf86-video-v4l-0.2.0.tar.bz2"
diff --git a/main/xf86-video-vesa/APKBUILD b/main/xf86-video-vesa/APKBUILD
new file mode 100644
index 0000000000..a6929748d9
--- /dev/null
+++ b/main/xf86-video-vesa/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-vesa
+pkgver=2.3.0
+pkgrel=3
+pkgdesc="X.org vesa video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev libxi-dev fontsproto randrproto
+ videoproto renderproto"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="07fa32958aff9b463dd3af5481ef6626 xf86-video-vesa-2.3.0.tar.bz2"
diff --git a/main/xf86-video-vmware/APKBUILD b/main/xf86-video-vmware/APKBUILD
new file mode 100644
index 0000000000..e2bd806be8
--- /dev/null
+++ b/main/xf86-video-vmware/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86-video-vmware
+pkgver=11.0.3
+pkgrel=1
+pkgdesc="X.org VMWare video driver"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig xorg-server-dev videoproto renderproto xproto libdrm-dev
+ fontsproto xf86dgaproto xineramaproto randrproto xextproto libxi-dev"
+
+source="http://xorg.freedesktop.org/releases/individual/driver/$pkgname-$pkgver.tar.bz2
+ abi2.patch"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -Np1 -i "$srcdir/abi2.patch" || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="579bee487309b1bdc8329bf627d43413 xf86-video-vmware-11.0.3.tar.bz2
+cbc8e0bef13ccec7ceac233cd09233da abi2.patch"
diff --git a/main/xf86-video-vmware/abi2.patch b/main/xf86-video-vmware/abi2.patch
new file mode 100644
index 0000000000..29e8ddeb19
--- /dev/null
+++ b/main/xf86-video-vmware/abi2.patch
@@ -0,0 +1,38 @@
+diff -up xf86-video-vmware-10.16.7/src/vmware.c.jx xf86-video-vmware-10.16.7/src/vmware.c
+--- xf86-video-vmware-10.16.7/src/vmware.c.jx 2009-08-07 16:31:33.000000000 -0400
++++ xf86-video-vmware-10.16.7/src/vmware.c 2009-08-07 16:32:10.000000000 -0400
+@@ -640,8 +640,6 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int fla
+ return FALSE;
+ }
+
+- xf86LoaderReqSymLists(vgahwSymbols, NULL);
+-
+ if (!vgaHWGetHWRec(pScrn)) {
+ return FALSE;
+ }
+@@ -959,7 +957,6 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int fla
+ VMWAREFreeRec(pScrn);
+ return FALSE;
+ }
+- xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL);
+
+ /* Need ramdac for hwcursor */
+ if (pVMWARE->hwCursor) {
+@@ -967,7 +964,6 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int fla
+ VMWAREFreeRec(pScrn);
+ return FALSE;
+ }
+- xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+
+ return TRUE;
+@@ -2051,9 +2047,6 @@ vmwareSetup(pointer module, pointer opts
+ setupDone = TRUE;
+ xf86AddDriver(&VMWARE, module, VMWARE_DRIVER_FUNC);
+
+- LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
+- shadowfbSymbols, NULL);
+-
+ return (pointer)1;
+ }
+ if (errmaj) {
diff --git a/main/xf86bigfontproto/APKBUILD b/main/xf86bigfontproto/APKBUILD
new file mode 100644
index 0000000000..ba577c9f8a
--- /dev/null
+++ b/main/xf86bigfontproto/APKBUILD
@@ -0,0 +1,19 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86bigfontproto
+pkgver=1.2.0
+pkgrel=1
+pkgdesc="X11 Big Fonts extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="120e226ede5a4687b25dd357cc9b8efe xf86bigfontproto-1.2.0.tar.bz2"
diff --git a/main/xf86dgaproto/APKBUILD b/main/xf86dgaproto/APKBUILD
new file mode 100644
index 0000000000..e29903cf14
--- /dev/null
+++ b/main/xf86dgaproto/APKBUILD
@@ -0,0 +1,20 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86dgaproto
+pkgver=2.1
+pkgrel=1
+pkgdesc="X11 Direct Graphics Access extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="a036dc2fcbf052ec10621fd48b68dbb1 xf86dgaproto-2.1.tar.bz2"
diff --git a/main/xf86driproto/APKBUILD b/main/xf86driproto/APKBUILD
new file mode 100644
index 0000000000..e5f2234ac6
--- /dev/null
+++ b/main/xf86driproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86driproto
+pkgver=2.1.1
+pkgrel=0
+pkgdesc="X11 DRI extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org//releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="1d716d0dac3b664e5ee20c69d34bc10e xf86driproto-2.1.1.tar.bz2"
diff --git a/main/xf86miscproto/APKBUILD b/main/xf86miscproto/APKBUILD
new file mode 100644
index 0000000000..c1fc9bfab3
--- /dev/null
+++ b/main/xf86miscproto/APKBUILD
@@ -0,0 +1,20 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86miscproto
+pkgver=0.9.3
+pkgrel=1
+pkgdesc="X11 XFree86-Miscellaneous extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org//releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="ca63bbb31cf5b7f37b2237e923ff257a xf86miscproto-0.9.3.tar.bz2"
diff --git a/main/xf86vidmodeproto/APKBUILD b/main/xf86vidmodeproto/APKBUILD
new file mode 100644
index 0000000000..e59b258479
--- /dev/null
+++ b/main/xf86vidmodeproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xf86vidmodeproto
+pkgver=2.3.1
+pkgrel=0
+pkgdesc="X11 Video Mode extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org//releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="e793ecefeaecfeabd1aed6a01095174e xf86vidmodeproto-2.3.1.tar.bz2"
diff --git a/main/xfce-utils/APKBUILD b/main/xfce-utils/APKBUILD
new file mode 100644
index 0000000000..d50ff0fe31
--- /dev/null
+++ b/main/xfce-utils/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce-utils
+pkgver=4.8.2
+pkgrel=0
+pkgdesc="Utilities for Xfce"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-doc"
+depends="hicolor-icon-theme"
+makedepends="libxfce4ui-dev"
+install=
+source="http://archive.xfce.org/src/xfce/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="7f48198f4bee3edf7869064c2922c609 xfce-utils-4.8.2.tar.bz2"
diff --git a/main/xfce4-appfinder/APKBUILD b/main/xfce4-appfinder/APKBUILD
new file mode 100644
index 0000000000..0232a3d651
--- /dev/null
+++ b/main/xfce4-appfinder/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-appfinder
+pkgver=4.8.0
+pkgrel=0
+pkgdesc="Xfce application finder"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+depends="hicolor-icon-theme"
+makedepends="thunar-dev gtk+-dev libxfce4ui-dev garcon-dev"
+install=
+source="http://archive.xfce.org/src/xfce/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="fb4797ef91b90d111b989e98c3e000e0 xfce4-appfinder-4.8.0.tar.bz2"
diff --git a/main/xfce4-battery-plugin/APKBUILD b/main/xfce4-battery-plugin/APKBUILD
new file mode 100644
index 0000000000..457d30e92b
--- /dev/null
+++ b/main/xfce4-battery-plugin/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-battery-plugin
+pkgver=1.0.0
+pkgrel=1
+pkgdesc="A battery monitor plugin for the Xfce panel"
+url="http://goodies.xfce.org/projects/panel-plugins/xfce4-battery-plugin"
+arch="all"
+license="GPL-2"
+makedepends="xfce4-panel-dev libxfcegui4-dev perl-xml-parser intltool"
+install=
+source="http://archive.xfce.org/src/panel-plugins/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2
+ sysfs-temp.patch
+ "
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+md5sums="2696307f34f6b9630fcaaea102004e78 xfce4-battery-plugin-1.0.0.tar.bz2
+8c797bdd29b431284377a7f08ddcd50e sysfs-temp.patch"
diff --git a/main/xfce4-battery-plugin/sysfs-temp.patch b/main/xfce4-battery-plugin/sysfs-temp.patch
new file mode 100644
index 0000000000..d20680ed8d
--- /dev/null
+++ b/main/xfce4-battery-plugin/sysfs-temp.patch
@@ -0,0 +1,66 @@
+From e33899de3205edfc0b2c330f43da6a4bc8141b85 Mon Sep 17 00:00:00 2001
+From: Florian Rivoal <frivoal@xfce.org>
+Date: Sat, 26 Feb 2011 13:53:09 +0000
+Subject: Add support for getting the temperature from sysfs
+
+Up to the linux kernel version 2.6.37, this information was available in
+the proc file system, but after that, it is only available from the sys
+file system.
+
+This fixes bug #7339.
+---
+diff --git a/panel-plugin/libacpi.c b/panel-plugin/libacpi.c
+index 838a760..0e368f4 100644
+--- a/panel-plugin/libacpi.c
++++ b/panel-plugin/libacpi.c
+@@ -1002,18 +1002,36 @@ const char *get_temperature(void)
+ #ifdef __linux__
+ FILE *fp;
+ char *proc_temperature="/proc/acpi/thermal_zone/*/temperature";
+- static char *p,line[256];
+-
+- if ( (fp=fopen_glob(proc_temperature, "r")) == NULL) return NULL;
+- fgets(line,255,fp);
+- fclose(fp);
+- p=strtok(line," ");
+- if (!p) return NULL;
+- p=p+strlen(p)+1;
+- while (p && *p ==' ') p++;
+- if (*p==0) return NULL;
+- if (strchr(p,'\n')) p=strtok(p,"\n");
+- return (const char *)p;
++ char *sys_temperature="/sys/class/thermal/thermal_zone*/temp";
++ static char *p,*p2,line[256];
++
++ if ( (fp=fopen_glob(proc_temperature, "r")) != NULL )
++ {
++ fgets(line,255,fp);
++ fclose(fp);
++ p=strtok(line," ");
++ if (!p) return NULL;
++ p=p+strlen(p)+1;
++ while (p && *p ==' ') p++;
++ if (*p==0) return NULL;
++ if (strchr(p,'\n')) p=strtok(p,"\n");
++ return (const char *)p;
++ }
++ else if ( (fp=fopen_glob(sys_temperature, "r")) != NULL )
++ {
++ fgets(line,255,fp);
++ fclose(fp);
++ p = line;
++ if (strchr(p,'\n')) *strchr(p,'\n') = 0;
++ if (strlen(p) <= 3) return NULL;
++ p2 = p + strlen(p) - 3;
++ strcpy(p2, " C");
++ return (const char *)p;
++ }
++ else
++ {
++ return NULL;
++ }
+ #else
+ #ifdef HAVE_SYSCTL
+ static char buf[BUFSIZ];
+--
+cgit v0.8.3.4
diff --git a/main/xfce4-cpufreq-plugin/APKBUILD b/main/xfce4-cpufreq-plugin/APKBUILD
new file mode 100644
index 0000000000..2e6800a390
--- /dev/null
+++ b/main/xfce4-cpufreq-plugin/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-cpufreq-plugin
+pkgver=1.0.0
+pkgrel=0
+pkgdesc="CPU frequency plugin for the Xfce4 panel"
+url="http://goodies.xfce.org/projects/panel-plugins/xfce4-cpufreq-plugin"
+arch="all"
+license="GPL2"
+depends=
+makedepends="xfce4-panel-dev libxfcegui4-dev"
+install=
+source="http://archive.xfce.org/src/panel-plugins/xfce4-cpufreq-plugin/${pkgver%.*}/xfce4-cpufreq-plugin-${pkgver}.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+md5sums="24cae9b8583cae82b715b4f72aa8e341 xfce4-cpufreq-plugin-1.0.0.tar.bz2"
diff --git a/main/xfce4-dev-tools/APKBUILD b/main/xfce4-dev-tools/APKBUILD
new file mode 100644
index 0000000000..54fc798e7c
--- /dev/null
+++ b/main/xfce4-dev-tools/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-dev-tools
+pkgver=4.8.0
+pkgrel=0
+pkgdesc="Xfce developer tools"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL2"
+depends="automake autoconf make intltool pkgconfig gtk-doc"
+makedepends=
+source="http://archive.xfce.org/src/xfce/xfce4-dev-tools/${pkgver%.*}/xfce4-dev-tools-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="9591299c49d92d00ba47974c42a735fa xfce4-dev-tools-4.8.0.tar.bz2"
diff --git a/main/xfce4-mixer/APKBUILD b/main/xfce4-mixer/APKBUILD
new file mode 100644
index 0000000000..19c44170cc
--- /dev/null
+++ b/main/xfce4-mixer/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-mixer
+pkgver=4.8.0
+pkgrel=0
+pkgdesc="The volume control plugin for the Xfce panel"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL2"
+depends="hicolor-icon-theme"
+makedepends="xfce4-panel-dev gstreamer-dev gst-plugins-base-dev libxfce4ui-dev"
+install=
+source="http://archive.xfce.org/src/apps/xfce4-mixer/${pkgver%.*}/xfce4-mixer-$pkgver.tar.bz2
+ "
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static \
+ --with-sound=alsa || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="3fa3a9973e18c04da26709a654e242ff xfce4-mixer-4.8.0.tar.bz2"
diff --git a/main/xfce4-notes-plugin/APKBUILD b/main/xfce4-notes-plugin/APKBUILD
new file mode 100644
index 0000000000..3cdb65ae65
--- /dev/null
+++ b/main/xfce4-notes-plugin/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor:
+# Maintainer:
+pkgname=xfce4-notes-plugin
+pkgver=1.7.7
+pkgrel=2
+pkgdesc="Notes plugin for the Xfce4 desktop"
+url="http://goodies.xfce.org/projects/panel-plugins/xfce4-notes-plugin"
+arch="all"
+license="GPL"
+depends=
+makedepends="xfce4-panel-dev libunique-dev libxfcegui4-dev"
+install=
+subpackages=
+source="http://archive.xfce.org/src/panel-plugins/xfce4-notes-plugin/1.7/xfce4-notes-plugin-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ # apply patches here
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="42b924b23f2fec6a1099e9b7a87db4a3 xfce4-notes-plugin-1.7.7.tar.bz2"
diff --git a/main/xfce4-notifyd/APKBUILD b/main/xfce4-notifyd/APKBUILD
new file mode 100644
index 0000000000..fa7d73f4d8
--- /dev/null
+++ b/main/xfce4-notifyd/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-notifyd
+pkgver=0.2.1
+pkgrel=0
+pkgdesc="notification daemon for the xfce desktop"
+url="http://spuriousinterrupt.org/projects/xfce4-notifyd"
+arch="all"
+license="GPL2"
+depends="hicolor-icon-theme"
+makedepends="gtk+-dev libxfce4util libxfce4ui-dev libsexy-dev xfconf-dev
+ dbus-glib-dev libglade-dev"
+install=
+source="http://archive.xfce.org/src/apps/xfce4-notifyd/${pkgver%.*}/xfce4-notifyd-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build () {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="0a63857901809887b587c73024d1089b xfce4-notifyd-0.2.1.tar.bz2"
diff --git a/main/xfce4-panel/APKBUILD b/main/xfce4-panel/APKBUILD
new file mode 100644
index 0000000000..28f5aba680
--- /dev/null
+++ b/main/xfce4-panel/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-panel
+pkgver=4.8.5
+pkgrel=0
+pkgdesc="Panel for the Xfce desktop environment"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends="hicolor-icon-theme"
+makedepends="libxfce4ui-dev exo-dev garcon-dev libwnck-dev"
+install=
+source="http://archive.xfce.org/src/xfce/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2
+ "
+
+depends_dev="libxfce4util-dev gtk+-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="3c00e92821709baa2a71b166a32d46a2 xfce4-panel-4.8.5.tar.bz2"
diff --git a/main/xfce4-power-manager/APKBUILD b/main/xfce4-power-manager/APKBUILD
new file mode 100644
index 0000000000..340962cc3e
--- /dev/null
+++ b/main/xfce4-power-manager/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-power-manager
+pkgver=1.0.10
+pkgrel=0
+pkgdesc="Power management for the Xfce desktop environment"
+url="http://goodies.xfce.org/projects/applications/xfce4-power-manager"
+arch="all"
+license="GPLv2+"
+depends="polkit"
+depends_dev="xfconf-dev xfce4-panel-dev dbus-glib-dev libnotify-dev
+ libxrandr-dev libxfce4ui-dev"
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-doc"
+source="http://archive.xfce.org/src/apps/xfce4-power-manager/1.0/xfce4-power-manager-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/xfce4-power-manager-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="38cbd272eb30e36ae538d9f38858bd38 xfce4-power-manager-1.0.10.tar.bz2"
diff --git a/main/xfce4-screenshooter/APKBUILD b/main/xfce4-screenshooter/APKBUILD
new file mode 100644
index 0000000000..0e3bd93157
--- /dev/null
+++ b/main/xfce4-screenshooter/APKBUILD
@@ -0,0 +1,32 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-screenshooter
+pkgver=1.7.9
+pkgrel=1
+pkgdesc="screenshot application for Xfce4"
+url="http://goodies.xfce.org/projects/applications/xfce4-screenshooter"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-doc"
+depends=
+makedepends="xfce4-panel-dev intltool hicolor-icon-theme libsm-dev
+ e2fsprogs-dev libsoup-dev libxext-dev libxfcegui4-dev"
+install="xfce4-screenshooter.post-install xfce4-screenshooter.post-upgrade
+ xfce4-screenshooter.post-deinstall"
+source="http://archive.xfce.org/src/apps/xfce4-screenshooter/${pkgver%.*}/xfce4-screenshooter-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="c01d1cf3830bf8d60e09c0cdd223034c xfce4-screenshooter-1.7.9.tar.bz2"
diff --git a/main/xfce4-screenshooter/xfce4-screenshooter.post-deinstall b/main/xfce4-screenshooter/xfce4-screenshooter.post-deinstall
new file mode 120000
index 0000000000..735306e31d
--- /dev/null
+++ b/main/xfce4-screenshooter/xfce4-screenshooter.post-deinstall
@@ -0,0 +1 @@
+xfce4-screenshooter.post-install \ No newline at end of file
diff --git a/main/xfce4-screenshooter/xfce4-screenshooter.post-install b/main/xfce4-screenshooter/xfce4-screenshooter.post-install
new file mode 100644
index 0000000000..c523d78da0
--- /dev/null
+++ b/main/xfce4-screenshooter/xfce4-screenshooter.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+
diff --git a/main/xfce4-screenshooter/xfce4-screenshooter.post-upgrade b/main/xfce4-screenshooter/xfce4-screenshooter.post-upgrade
new file mode 120000
index 0000000000..735306e31d
--- /dev/null
+++ b/main/xfce4-screenshooter/xfce4-screenshooter.post-upgrade
@@ -0,0 +1 @@
+xfce4-screenshooter.post-install \ No newline at end of file
diff --git a/main/xfce4-session/APKBUILD b/main/xfce4-session/APKBUILD
new file mode 100644
index 0000000000..d79baa82ba
--- /dev/null
+++ b/main/xfce4-session/APKBUILD
@@ -0,0 +1,49 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-session
+pkgver=4.8.1
+pkgrel=1
+pkgdesc="A session manager for Xfce"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL2"
+subpackages="$pkgname-dev $pkgname-doc"
+makedepends="libxfce4ui-dev libwnck-dev libice-dev xfce4-panel-dev"
+depends="hicolor-icon-theme iceauth"
+install=
+source="http://archive.xfce.org/src/xfce/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2
+ busybox-shutdown.patch"
+
+depends_dev="libxfcegui4-dev xfconf-dev"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 -i ../busybox-shutdown.patch || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-legacy-sm \
+ --disable-gnome \
+ --disable-session-screenshots \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ # tips doesnt work and i dont like them.
+ # just remove to save space
+ rm -f "$pkgdir"/etc/xdg/autostart/xfce4-tips-autostart.desktop \
+ "$pkgdir"/usr/bin/xfce4-tips
+ find "$pkgdir" -name '*.la' -delete
+}
+
+md5sums="478080ff666fdd36786a243829663efd xfce4-session-4.8.1.tar.bz2
+bfd9132f08f4a92efbe982fb911c511c busybox-shutdown.patch"
diff --git a/main/xfce4-session/busybox-shutdown.patch b/main/xfce4-session/busybox-shutdown.patch
new file mode 100644
index 0000000000..37423618f0
--- /dev/null
+++ b/main/xfce4-session/busybox-shutdown.patch
@@ -0,0 +1,13 @@
+--- a/xfsm-shutdown-helper/main.c Thu Nov 5 17:34:17 2009
++++ b/xfsm-shutdown-helper/main.c Thu Nov 5 17:36:56 2009
+@@ -64,8 +64,8 @@
+ #define POWEROFF_CMD "/usr/sbin/shutdown -i 5 -g 0 -y"
+ #define REBOOT_CMD "/usr/sbin/shutdown -i 6 -g 0 -y"
+ #else
+-#define POWEROFF_CMD "/sbin/shutdown -h now"
+-#define REBOOT_CMD "/sbin/shutdown -r now"
++#define POWEROFF_CMD "/sbin/poweroff"
++#define REBOOT_CMD "/sbin/reboot"
+ #endif
+
+
diff --git a/main/xfce4-session/xfce4-session.post-deinstall b/main/xfce4-session/xfce4-session.post-deinstall
new file mode 120000
index 0000000000..7242718fcb
--- /dev/null
+++ b/main/xfce4-session/xfce4-session.post-deinstall
@@ -0,0 +1 @@
+xfce4-session.post-install \ No newline at end of file
diff --git a/main/xfce4-session/xfce4-session.post-install b/main/xfce4-session/xfce4-session.post-install
new file mode 100644
index 0000000000..c523d78da0
--- /dev/null
+++ b/main/xfce4-session/xfce4-session.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+
diff --git a/main/xfce4-settings/APKBUILD b/main/xfce4-settings/APKBUILD
new file mode 100644
index 0000000000..e733e5fcb0
--- /dev/null
+++ b/main/xfce4-settings/APKBUILD
@@ -0,0 +1,47 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-settings
+pkgver=4.8.2
+pkgrel=0
+pkgdesc="Settings manager for xfce"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="libxfce4ui-dev exo-dev libxi-dev libxrandr-dev libxklavier-dev
+ libnotify-dev libxcursor-dev"
+source="http://archive.xfce.org/src/xfce/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in "$srcdir"/*.patch; do
+ [ -f "$i" ] || continue
+ msg "Applying ${i##*/}"
+ patch -p1 -i "$i" || return 1
+ done
+
+ # use tango as default icon set
+ sed -i -e 's/Rodent/Tango/g' xfsettingsd/xsettings.xml \
+ dialogs/appearance-settings/main.c || return 1
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-libxklavier \
+ --enable-xrandr \
+ --enable-sound-settings
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="a45420fea20f29265ab6785cb1d07377 xfce4-settings-4.8.2.tar.bz2"
diff --git a/main/xfce4-settings/xfce4-settings-4.7.1-libxklavier.patch b/main/xfce4-settings/xfce4-settings-4.7.1-libxklavier.patch
new file mode 100644
index 0000000000..142932c894
--- /dev/null
+++ b/main/xfce4-settings/xfce4-settings-4.7.1-libxklavier.patch
@@ -0,0 +1,27 @@
+diff -ur xfce4-settings-4.7.1.orig/configure.ac xfce4-settings-4.7.1/configure.ac
+--- xfce4-settings-4.7.1.orig/configure.ac 2010-01-23 13:48:05.000000000 +0200
++++ xfce4-settings-4.7.1/configure.ac 2010-02-15 14:20:55.000000000 +0200
+@@ -142,6 +142,8 @@
+ [libxklavier], [Keyboard layout selection])
+ XDT_CHECK_OPTIONAL_PACKAGE([LIBXKLAVIER4], [libxklavier], [4.0],
+ [libxklavier], [Keyboard layout selection])
++XDT_CHECK_OPTIONAL_PACKAGE([LIBXKLAVIER5], [libxklavier], [5.0],
++ [libxklavier], [Keyboard layout selection])
+
+ dnl ************************************
+ dnl *** Xsettings daemon is optional ***
+diff -ur xfce4-settings-4.7.1.orig/dialogs/keyboard-settings/xfce-keyboard-settings.c xfce4-settings-4.7.1/dialogs/keyboard-settings/xfce-keyboard-settings.c
+--- xfce4-settings-4.7.1.orig/dialogs/keyboard-settings/xfce-keyboard-settings.c 2010-01-23 13:48:05.000000000 +0200
++++ xfce4-settings-4.7.1/dialogs/keyboard-settings/xfce-keyboard-settings.c 2010-02-15 14:23:24.000000000 +0200
+@@ -395,7 +395,11 @@
+
+ #ifdef HAVE_LIBXKLAVIER
+ /* Stop xklavier engine */
++#ifdef HAVE_LIBXKLAVIER5
++ xkl_engine_stop_listen (settings->priv->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
++#else
+ xkl_engine_stop_listen (settings->priv->xkl_engine);
++#endif /* HAVE_LIBXKLAVIER5 */
+ #endif /* HAVE_LIBXKLAVIER */
+
+ g_object_unref (G_OBJECT (settings->priv->provider));
diff --git a/main/xfce4-taskmanager/APKBUILD b/main/xfce4-taskmanager/APKBUILD
new file mode 100644
index 0000000000..99dd54305c
--- /dev/null
+++ b/main/xfce4-taskmanager/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-taskmanager
+pkgver=1.0.0
+pkgrel=1
+pkgdesc="a simple taskmanager for the Xfce Desktop Environment"
+url="http://goodies.xfce.org/projects/applications/xfce4-taskmanager"
+arch="all"
+license="GPL-2"
+depends=
+makedepends="pkgconfig intltool libxfcegui4-dev"
+source="http://archive.xfce.org/src/apps/${pkgname}/1.0/${pkgname}-${pkgver}.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="cd205366ae771d2cbe72b5ca7b1257b0 xfce4-taskmanager-1.0.0.tar.bz2"
diff --git a/main/xfce4-vala/APKBUILD b/main/xfce4-vala/APKBUILD
new file mode 100644
index 0000000000..12e015252d
--- /dev/null
+++ b/main/xfce4-vala/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-vala
+pkgver=4.8.1
+pkgrel=0
+pkgdesc="Vala bindings for Xfce4"
+url="http://wiki.xfce.org/vala-bindings"
+arch="x86 x86_64"
+license="LGPL"
+depends="exo-dev libxfce4util-dev libxfce4menu-dev libxfce4ui-dev
+ xfce4-panel-dev xfconf-dev vala"
+makedepends=""
+install=
+subpackages=
+source="http://archive.xfce.org/src/bindings/xfce4-vala/${pkgver%.*}/xfce4-vala-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ local _p
+ cd "$_builddir"
+ for _p in $source; do
+ case $_p in
+ *.patch) msg $_p; patch -p1 -i "$srcdir"/$_p || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="33732067603818ac55e0fc7d0b99b033 xfce4-vala-4.8.1.tar.bz2"
diff --git a/main/xfce4-wavelan-plugin/APKBUILD b/main/xfce4-wavelan-plugin/APKBUILD
new file mode 100644
index 0000000000..4dd8240aff
--- /dev/null
+++ b/main/xfce4-wavelan-plugin/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-wavelan-plugin
+pkgver=0.5.6
+pkgrel=0
+pkgdesc="plugin to monitor wifi connectivity for the Xfce4 panel"
+url="http://goodies.xfce.org/projects/panel-plugins/xfce4-wavelan-plugin/"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig xfce4-panel-dev intltool libsm-dev libxfcegui4-dev"
+source="http://archive.xfce.org/src/panel-plugins/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+md5sums="b23a4c9c2a206242ee4db8186dd01801 xfce4-wavelan-plugin-0.5.6.tar.bz2"
diff --git a/main/xfce4-wavelan-plugin/tooltip.diff b/main/xfce4-wavelan-plugin/tooltip.diff
new file mode 100644
index 0000000000..f180f5694a
--- /dev/null
+++ b/main/xfce4-wavelan-plugin/tooltip.diff
@@ -0,0 +1,19 @@
+diff -Naur xfce4-wavelan-plugin-0.5.5.old/panel-plugin/wavelan.c xfce4-wavelan-plugin-0.5.5/panel-plugin/wavelan.c
+--- xfce4-wavelan-plugin-0.5.5.old/panel-plugin/wavelan.c 2009-10-09 14:42:54.427988584 +0200
++++ xfce4-wavelan-plugin-0.5.5/panel-plugin/wavelan.c 2009-10-09 14:45:24.351280223 +0200
+@@ -199,6 +199,14 @@
+ if ((wavelan->device = wi_open(wavelan->interface)) != NULL) {
+ /* register the update timer */
+ TRACE ("Opened device");
++ /* reduce the default tooltip timeout to be smaller than the update interval otherwise
++ * we won't see tooltips on GTK 2.16 or newer */
++ GtkSettings *settings;
++ settings = gtk_settings_get_default();
++ if (g_object_class_find_property(G_OBJECT_GET_CLASS(settings), "gtk-tooltip-timeout"))
++ g_object_set(settings, "gtk-tooltip-timeout",
++ 250 - 10, NULL);
++
+ wavelan->timer_id = g_timeout_add(250, wavelan_timer, wavelan);
+ }
+ }
+
diff --git a/main/xfce4-xkb-plugin/APKBUILD b/main/xfce4-xkb-plugin/APKBUILD
new file mode 100644
index 0000000000..8f05a7f1e3
--- /dev/null
+++ b/main/xfce4-xkb-plugin/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-xkb-plugin
+pkgver=0.5.4.1
+_maj=${pkgver%%.*}
+_min=${pkgver#${_maj}.}
+_min=${_min%%.*}
+_ver=${_maj}.${_min}
+pkgrel=0
+pkgdesc="plugin to switch keyboard layouts for the Xfce4 panel"
+url="http://goodies.xfce.org/projects/panel-plugins/xfce4-xkb-plugin"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="xfce4-panel-dev libxklavier-dev librsvg-dev intltool libwnck-dev
+ libxi-dev libxkbfile-dev libsm-dev libgsf-dev e2fsprogs-dev bzip2-dev libxfce4ui-dev"
+source="http://archive.xfce.org/src/panel-plugins/xfce4-xkb-plugin/$_ver/xfce4-xkb-plugin-$pkgver.tar.bz2"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+}
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="8512c0b180004e1150d8c05255c202d8 xfce4-xkb-plugin-0.5.4.1.tar.bz2"
diff --git a/main/xfce4/APKBUILD b/main/xfce4/APKBUILD
new file mode 100644
index 0000000000..1dfc2df6e9
--- /dev/null
+++ b/main/xfce4/APKBUILD
@@ -0,0 +1,42 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4
+pkgver=4.8
+pkgrel=0
+pkgdesc="XFCE 4 meta package"
+url="http://www.xfce.org"
+arch="noarch"
+license="GPL"
+depends="
+ thunar>=1.2.0
+ exo>=0.6.0
+ gtk-xfce-engine>=2.8.0
+ libxfce4ui>=4.8.0
+ libxfce4util>=4.8.0
+ xfce-utils>=4.8.0
+ xfce4-appfinder>=4.8.0
+ xfce4-panel>=4.8.0
+ xfce4-session>=4.8.0
+ xfce4-settings>=4.8.0
+ xfconf>=4.8.0
+ xfdesktop>=4.8.0
+ xfwm4>=4.8.0
+
+ garcon
+ mousepad
+ tango-icon-theme
+ terminal
+ ttf-dejavu
+ xfce4-mixer
+ "
+
+makedepends=
+install=
+subpackages=
+source=
+
+build() {
+ mkdir -p "$pkgdir"
+}
+
+md5sums="" #generate with 'abuild checksum'
diff --git a/main/xfconf/APKBUILD b/main/xfconf/APKBUILD
new file mode 100644
index 0000000000..e615a7477d
--- /dev/null
+++ b/main/xfconf/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfconf
+pkgver=4.8.0
+pkgrel=1
+pkgdesc="Hierarchical configuration system for Xfce"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="dbus-glib-dev libxfce4util-dev gettext-dev libiconv-dev
+ intltool"
+source="http://archive.xfce.org/src/xfce/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="glib-dev dbus-dev dbus-glib-dev"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+md5sums="0f11ed1ec7789c5c4c3fcc7cdb3c2940 xfconf-4.8.0.tar.bz2"
diff --git a/main/xfdesktop/APKBUILD b/main/xfdesktop/APKBUILD
new file mode 100644
index 0000000000..53e282acb0
--- /dev/null
+++ b/main/xfdesktop/APKBUILD
@@ -0,0 +1,41 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfdesktop
+pkgver=4.8.2
+pkgrel=1
+pkgdesc="A desktop manager for Xfce"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+subpackages="$pkgname-doc"
+depends="hicolor-icon-theme"
+makedepends="garcon-dev thunar-dev libxfce4ui-dev libwnck-dev libnotify-dev
+ exo-dev"
+install=
+source="http://archive.xfce.org/src/xfce/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="ed25d59f478afda552d121e96657d16f xfdesktop-4.8.2.tar.bz2"
diff --git a/main/xfsprogs/APKBUILD b/main/xfsprogs/APKBUILD
new file mode 100644
index 0000000000..b0f1eb3f8f
--- /dev/null
+++ b/main/xfsprogs/APKBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfsprogs
+pkgver=3.1.5
+pkgrel=1
+pkgdesc="XFS filesystem utilities"
+url="http://oss.sgi.com/projects/xfs/"
+arch="all"
+license="LGPL"
+depends="e2fsprogs"
+makedepends="e2fsprogs-dev bash"
+subpackages="$pkgname-dev $pkgname-doc"
+source="ftp://oss.sgi.com/projects/xfs/cmd_tars/${pkgname}-$pkgver.tar.gz
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ sed -i -e 's/--best//' Makefile doc/Makefile
+}
+
+build() {
+ cd "$_builddir"
+ export DEBUG=-DNDEBUG
+ export OPTIMIZER="$CFLAGS"
+
+ ac_cv_header_aio_h=yes ac_cv_lib_rt_lio_listio=yes \
+ ./configure --prefix=/usr \
+ --sbindir=/sbin \
+ --libexecdir=/usr/lib \
+ --enable-lib64=no \
+ --enable-gettext=no
+
+ make SHELL=/bin/bash || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DIST_ROOT="$pkgdir" install install-dev install-qa || return 1
+ rm "$pkgdir"/usr/lib/*.la "$pkgdir"/lib/*.la
+}
+md5sums="b1db37749e2b4149a0dd178abff956be xfsprogs-3.1.5.tar.gz"
diff --git a/main/xfwm4-themes/APKBUILD b/main/xfwm4-themes/APKBUILD
new file mode 100644
index 0000000000..44672c5f1d
--- /dev/null
+++ b/main/xfwm4-themes/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfwm4-themes
+pkgver=4.6.0
+pkgrel=1
+pkgdesc="A set of additionnal themes for the Xfce window manager"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL2"
+depends="xfwm4"
+makedepends="pkgconfig"
+options="!strip"
+source="http://archive.xfce.org/src/art/xfwm4-themes/4.6/xfwm4-themes-${pkgver}.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="4dc5cb29cbd40e3b9dece12a85e20854 xfwm4-themes-4.6.0.tar.bz2"
diff --git a/main/xfwm4/APKBUILD b/main/xfwm4/APKBUILD
new file mode 100644
index 0000000000..cb5c16e4f4
--- /dev/null
+++ b/main/xfwm4/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfwm4
+pkgver=4.8.1
+pkgrel=0
+pkgdesc="Xfce window manager, compatible with Gnome, Gnome2, KDE2, and KDE3"
+url="http://www.xfce.org/"
+arch="all"
+license="GPL-2"
+depends="hicolor-icon-theme"
+makedepends="libxfce4ui-dev libwnck-dev libxrandr-dev libxcomposite-dev
+ libxfixes-dev libxdamage-dev libxrender-dev"
+install=
+source="http://archive.xfce.org/src/xfce/xfwm4/${pkgver%.*}/xfwm4-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static \
+ --enable-compositor \
+ --enable-xsync || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="447433dca613180ebd6cfed4beb1c1c9 xfwm4-4.8.1.tar.bz2"
diff --git a/main/xfwm4/xfwm4.post-deinstall b/main/xfwm4/xfwm4.post-deinstall
new file mode 120000
index 0000000000..822a58d8cc
--- /dev/null
+++ b/main/xfwm4/xfwm4.post-deinstall
@@ -0,0 +1 @@
+xfwm4.post-install \ No newline at end of file
diff --git a/main/xfwm4/xfwm4.post-install b/main/xfwm4/xfwm4.post-install
new file mode 100644
index 0000000000..c523d78da0
--- /dev/null
+++ b/main/xfwm4/xfwm4.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+
diff --git a/main/xfwm4/xfwm4.post-upgrade b/main/xfwm4/xfwm4.post-upgrade
new file mode 120000
index 0000000000..822a58d8cc
--- /dev/null
+++ b/main/xfwm4/xfwm4.post-upgrade
@@ -0,0 +1 @@
+xfwm4.post-install \ No newline at end of file
diff --git a/main/xgamma/APKBUILD b/main/xgamma/APKBUILD
new file mode 100644
index 0000000000..731befccb2
--- /dev/null
+++ b/main/xgamma/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xgamma
+pkgver=1.0.3
+pkgrel=2
+pkgdesc="Alter a monitor's gamma correction through the X server"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libx11-dev libxxf86vm-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="e8a88bf1a18f35b724619849dca97f4f xgamma-1.0.3.tar.bz2"
diff --git a/main/xhost/APKBUILD b/main/xhost/APKBUILD
new file mode 100644
index 0000000000..f3635c1ee4
--- /dev/null
+++ b/main/xhost/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xhost
+pkgver=1.0.3
+pkgrel=2
+pkgdesc="Controls host and/or user access to a running X server."
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libx11-dev libxmu-dev libxau-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="c7f91b4a750d297f269c2a0a3206a1b2 xhost-1.0.3.tar.bz2"
diff --git a/main/xineramaproto/APKBUILD b/main/xineramaproto/APKBUILD
new file mode 100644
index 0000000000..b3aa563033
--- /dev/null
+++ b/main/xineramaproto/APKBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xineramaproto
+pkgver=1.2.1
+pkgrel=0
+pkgdesc="X11 Xinerama extension wire protocol"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org//releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="9959fe0bfb22a0e7260433b8d199590a xineramaproto-1.2.1.tar.bz2"
diff --git a/main/xinit/06_move_serverauthfile_into_tmp.patch b/main/xinit/06_move_serverauthfile_into_tmp.patch
new file mode 100644
index 0000000000..99e8a6754d
--- /dev/null
+++ b/main/xinit/06_move_serverauthfile_into_tmp.patch
@@ -0,0 +1,20 @@
+Move startx auth files in /tmp so they are removed on reboot.
+http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=357736
+The trap patch didn't seem to work on reboot.
+---
+ startx.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: xinit/startx.cpp
+===================================================================
+--- xinit.orig/startx.cpp
++++ xinit/startx.cpp
+@@ -273,7 +273,7 @@
+ dummy=0
+
+ XCOMM create a file with auth information for the server. ':0' is a dummy.
+- xserverauthfile=$HOME/.serverauth.$$
++ xserverauthfile=`mktemp -p /tmp serverauth.XXXXXXXXXX`
+ trap "rm -f '$xserverauthfile'" HUP INT QUIT ILL TRAP KILL BUS TERM
+ xauth -q -f "$xserverauthfile" << EOF
+ add :$dummy . $mcookie
diff --git a/main/xinit/APKBUILD b/main/xinit/APKBUILD
new file mode 100644
index 0000000000..8b809843fc
--- /dev/null
+++ b/main/xinit/APKBUILD
@@ -0,0 +1,48 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xinit
+pkgver=1.2.1
+pkgrel=3
+pkgdesc="X.Org initialisation program "
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-doc"
+depends="xauth mcookie"
+makedepends="pkgconfig libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/xinit-$pkgver.tar.bz2
+ 06_move_serverauthfile_into_tmp.patch
+ xinitrc
+ xsession
+ xserverrc"
+
+prepare() {
+ cd "$srcdir"/xinit-$pkgver
+ for i in $source; do
+ case $i in
+ *.patch) patch -p1 -i "$srcdir"/$i
+ esac
+ done
+}
+
+build() {
+ cd "$srcdir"/xinit-$pkgver
+ ./configure --prefix=/usr \
+ --with-xinitdir=/etc/X11/xinit \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/xinit-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ chmod +x "$pkgdir"/usr/bin/startx
+ install -m755 -d "$pkgdir"/etc/skel
+ install -m755 -D "$srcdir"/xinitrc "$pkgdir"/etc/X11/xinit/xinitrc
+ install -m755 "$srcdir"/xsession "$pkgdir"/etc/skel/.xsession || return 1
+ install -m755 "$srcdir"/xserverrc "$pkgdir"/etc/X11/xinit/xserverrc || return 1
+}
+md5sums="56f2d202b3dc10fcd21931a67bb270f7 xinit-1.2.1.tar.bz2
+abd072ec435ce084cf4e89c58f83d45c 06_move_serverauthfile_into_tmp.patch
+af322d72972d5722b7fc0a9e8f025b15 xinitrc
+4f04d2891ea87f50fde518267b7a1154 xsession
+4d29a1104997609e10206a4c1408237d xserverrc"
diff --git a/main/xinit/xinitrc b/main/xinit/xinitrc
new file mode 100644
index 0000000000..0055713592
--- /dev/null
+++ b/main/xinit/xinitrc
@@ -0,0 +1,49 @@
+#!/bin/sh
+# $Xorg: xinitrc.cpp,v 1.3 2000/08/17 19:54:30 cpqbld Exp $
+
+userresources=$HOME/.Xresources
+usermodmap=$HOME/.Xmodmap
+xinitdir=/etc/X11
+sysresources=$xinitdir/Xresources
+sysmodmap=$xinitdir/Xmodmap
+
+# merge in defaults and keymaps
+
+if [ -f $sysresources ]; then
+ xrdb -merge $sysresources
+fi
+
+if [ -f $sysmodmap ]; then
+ xmodmap $sysmodmap
+fi
+
+if [ -f $userresources ]; then
+ xrdb -merge $userresources
+fi
+
+if [ -f $usermodmap ]; then
+ xmodmap $usermodmap
+fi
+
+# First try ~/.xinitrc
+if [ -f "$HOME/.xinitrc" ]; then
+ XINITRC="$HOME/.xinitrc"
+ if [ -x $XINITRC ]; then
+ # if the x bit is set on .xinitrc
+ # it means the xinitrc is not a
+ # shell script but something else
+ exec $XINITRC "$@"
+ else
+ exec /bin/sh "$HOME/.xinitrc" "$@"
+ fi
+fi
+
+# If not present, try the system default
+exec startxfce4
+
+
+# Fall back to fluxbox
+exec startfluxbox
+
+# Start only terminal as last resort
+exec terminal || exec aterm
diff --git a/main/xinit/xserverrc b/main/xinit/xserverrc
new file mode 100644
index 0000000000..2537aedcbf
--- /dev/null
+++ b/main/xinit/xserverrc
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/bin/X -nolisten tcp
diff --git a/main/xinit/xsession b/main/xinit/xsession
new file mode 100644
index 0000000000..819c248cd5
--- /dev/null
+++ b/main/xinit/xsession
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+#
+# ~/.xsession
+#
+# Executed by xdm/gdm/kdm at login
+#
+
+/bin/sh -l ~/.xinitrc
+
diff --git a/main/xkbcomp/APKBUILD b/main/xkbcomp/APKBUILD
new file mode 100644
index 0000000000..da3bc4853a
--- /dev/null
+++ b/main/xkbcomp/APKBUILD
@@ -0,0 +1,29 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xkbcomp
+pkgver=1.1.1
+pkgrel=2
+pkgdesc="compile XKB keyboard description"
+url="http://xorg.freedesktop.org"
+arch="all"
+license="custom"
+depends=
+makedepends="pkgconfig libx11-dev libxkbfile-dev"
+subpackages="$pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="38c387bacdc01038c8ac280588792bcf xkbcomp-1.1.1.tar.bz2"
diff --git a/main/xkeyboard-config/APKBUILD b/main/xkeyboard-config/APKBUILD
new file mode 100644
index 0000000000..521d42ed88
--- /dev/null
+++ b/main/xkeyboard-config/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xkeyboard-config
+pkgver=2.2.1
+pkgrel=0
+pkgdesc="X keyboard configuration files"
+url="http://www.freedesktop.org/wiki/Software/XKeyboardConfig"
+arch="noarch"
+license="custom"
+depends=
+makedepends="xkbcomp intltool libx11-dev"
+source="http://www.x.org/releases/individual/data/xkeyboard-config/xkeyboard-config-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --with-xkb-base=/usr/share/X11/xkb \
+ --with-xkb-rules-symlink=xorg \
+ --enable-compat-rules=yes || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ rm -f "$pkgdir"/usr/share/X11/xkb/compiled || return 1
+ install -m755 -d "$pkgdir"/var/lib/xkb
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="1867472501d13594d5ca17e696cc09ca xkeyboard-config-2.2.1.tar.bz2"
diff --git a/main/xmodmap/APKBUILD b/main/xmodmap/APKBUILD
new file mode 100644
index 0000000000..2a44bfbe20
--- /dev/null
+++ b/main/xmodmap/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xmodmap
+pkgver=1.0.4
+pkgrel=2
+pkgdesc="utility for modifying keymaps and pointer button mappings in X"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="bbe021f812e0014a8ee3692317788119 xmodmap-1.0.4.tar.bz2"
diff --git a/main/xorg-server/APKBUILD b/main/xorg-server/APKBUILD
new file mode 100644
index 0000000000..bcc8085322
--- /dev/null
+++ b/main/xorg-server/APKBUILD
@@ -0,0 +1,157 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xorg-server
+pkgver=1.10.2
+pkgrel=0
+pkgdesc="X.Org X servers"
+url="http://xorg.freedesktop.org"
+arch="all"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc xfbdev xvfb"
+depends="
+ font-misc-misc
+ font-cursor-misc
+ xkeyboard-config
+ xkbcomp
+ xinit
+ "
+makedepends="
+ autoconf
+ automake
+ bigreqsproto
+ compositeproto
+ damageproto
+ dbus-dev
+ dri2proto
+ fixesproto
+ glproto
+ inputproto
+ libdrm-dev
+ libpciaccess-dev
+ libtool
+ libx11-dev
+ libxdamage-dev
+ libxfont-dev
+ libxinerama-dev
+ libxkbfile-dev
+ libxkbui-dev
+ libxv-dev
+ libxxf86dga-dev
+ libxxf86misc-dev
+ mesa-dev
+ openssl-dev
+ perl
+ pixman-dev
+ pkgconfig
+ randrproto
+ recordproto
+ renderproto
+ resourceproto
+ scrnsaverproto
+ udev-dev
+ util-macros
+ xcmiscproto
+ xextproto
+ xf86driproto
+ xineramaproto
+ xproto
+ xtrans
+ zlib-dev
+ "
+
+source="http://xorg.freedesktop.org/releases/individual/xserver/$pkgname-$pkgver.tar.bz2
+ xorg-redhat-die-ugly-pattern-die-die-die.patch
+ bg-none-revert.patch
+ xserver-1.10-pointer-barriers.patch
+
+"
+
+depends_dev="pixman-dev libpciaccess-dev xproto randrproto renderproto
+ xextproto inputproto kbproto fontsproto videoproto xineramaproto
+ dri2proto"
+
+prepare() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ # Fix dbus config path
+ sed -i -e 's/\$(sysconfdir)/\/etc/' config/Makefile.* || return 1
+}
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ # xorg modules does not work with the -z now and it seems like we
+ # cannot pass over the linker flag to .so files. so we tweak the
+ # gcc specs.
+ export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
+ _fontroot="/usr/share/fonts"
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/X11 \
+ --localstatedir=/var \
+ --with-fontrootdir=$_fontroot \
+ --with-default-font-path=${_fontroot}/misc,${_fontroot}/100dpi:unscaled,${_fontroot}/75dpi:unscaled,${_fontroot}/TTF,${_fontroot}/Type1 \
+ --with-xkb-path=/usr/share/X11/xkb \
+ --with-xkb-output=/var/lib/xkb \
+ --enable-composite \
+ --enable-config-udev \
+ --enable-dri \
+ --enable-dri2 \
+ --enable-ipv6 \
+ --enable-xfbdev \
+ --enable-kdrive \
+ --enable-xorg \
+ --enable-xv \
+ --enable-xres \
+ --enable-xace \
+ --disable-xephyr \
+ --disable-config-hal \
+ --disable-dmx \
+ --disable-tslib \
+ --disable-xnest \
+ --disable-aiglx \
+ --disable-config-dbus \
+ --enable-config-udev \
+ || return 1
+
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ chmod u+s "$pkgdir"/usr/bin/Xorg
+
+ install -m755 -d "$pkgdir"/etc/X11 || return 1
+ install -m755 -d "$pkgdir"/var/lib/xkb || return 1
+ install -m644 -D COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+
+xfbdev() {
+ pkgdesc="X.org server for framebuffer"
+ depends=
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/Xfbdev "$subpkgdir"/usr/bin/
+}
+
+xvfb() {
+ pkgdesc="Virtual Framebuffer 'fake' X server"
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/Xvfb "$subpkgdir"/usr/bin/
+}
+
+xephyr() {
+ pkgdesc="kdrive based X Server which targets a window on a host X Server as its framebuffer"
+ depends=
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$pkgdir"/usr/bin/Xephyr "$subpkgdir"/usr/bin/
+}
+
+md5sums="c9ba50bd44ea70da51f13100336a5484 xorg-server-1.10.2.tar.bz2
+222de594206d1148a90eddfda4f7a11a xorg-redhat-die-ugly-pattern-die-die-die.patch
+030dd3ec221b895de3057d7513d8c1d7 bg-none-revert.patch
+db48cea655c7bccec9171c5df1558a64 xserver-1.10-pointer-barriers.patch"
diff --git a/main/xorg-server/bg-none-revert.patch b/main/xorg-server/bg-none-revert.patch
new file mode 100644
index 0000000000..1a38f1f418
--- /dev/null
+++ b/main/xorg-server/bg-none-revert.patch
@@ -0,0 +1,58 @@
+From 3bc6ed2d8c9028ec28015d05b60af67a194f3694 Mon Sep 17 00:00:00 2001
+From: Adam Jackson <ajax@redhat.com>
+Date: Tue, 29 Mar 2011 14:09:46 +0000
+Subject: Revert "composite: Don't backfill non-bg-None windows"
+
+This reverts commit 6dd775f57d2f94f0ddaee324aeec33b9b66ed5bc.
+
+Bugzilla: https://bugs.freedesktop.org/34427
+
+Acked-by: Alex Deucher <alexdeucher@gmail.com>
+Signed-off-by: Adam Jackson <ajax@redhat.com>
+---
+diff --git a/composite/compalloc.c b/composite/compalloc.c
+index e4064f6..7164c0d 100644
+--- a/composite/compalloc.c
++++ b/composite/compalloc.c
+@@ -508,17 +508,6 @@ compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
+ return Success;
+ }
+
+-static int
+-bgNoneVisitWindow(WindowPtr pWin, void *null)
+-{
+- if (pWin->backgroundState != BackgroundPixmap)
+- return WT_WALKCHILDREN;
+- if (pWin->background.pixmap != None)
+- return WT_WALKCHILDREN;
+-
+- return WT_STOPWALKING;
+-}
+-
+ static PixmapPtr
+ compNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map)
+ {
+@@ -539,21 +528,6 @@ compNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map)
+ if (!map)
+ return pPixmap;
+
+- /*
+- * If there's no bg=None in the tree, we're done.
+- *
+- * We could optimize this more by collection the regions of all the
+- * bg=None subwindows and feeding that in as the clip for the
+- * CopyArea below, but since window trees are shallow these days it
+- * might not be worth the effort.
+- */
+- if (TraverseTree(pWin, bgNoneVisitWindow, NULL) == WT_NOMATCH)
+- return pPixmap;
+-
+- /*
+- * Copy bits from the parent into the new pixmap so that it will
+- * have "reasonable" contents in case for background None areas.
+- */
+ if (pParent->drawable.depth == pWin->drawable.depth)
+ {
+ GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen);
+--
+cgit v0.8.3-6-g21f6
diff --git a/main/xorg-server/xorg-redhat-die-ugly-pattern-die-die-die.patch b/main/xorg-server/xorg-redhat-die-ugly-pattern-die-die-die.patch
new file mode 100644
index 0000000000..3ca10647ce
--- /dev/null
+++ b/main/xorg-server/xorg-redhat-die-ugly-pattern-die-die-die.patch
@@ -0,0 +1,16 @@
+Remove the default root window grey stipple pattern, replacing it with
+blackness.
+
+--- Xserver/dix/window.c.die-ugly-pattern-die-die-die Tue Feb 12 16:33:04 2002
++++ Xserver/dix/window.c Tue Feb 12 16:45:32 2002
+@@ -119,8 +119,8 @@
+ *
+ ******/
+
+-static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11};
+-static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88};
++static unsigned char _back_lsb[4] = {0x00, 0x00, 0x00, 0x00};
++static unsigned char _back_msb[4] = {0x00, 0x00, 0x00, 0x00};
+
+ int screenIsSaved = SCREEN_SAVER_OFF;
+
diff --git a/main/xorg-server/xserver-1.10-pointer-barriers.patch b/main/xorg-server/xserver-1.10-pointer-barriers.patch
new file mode 100644
index 0000000000..0995654363
--- /dev/null
+++ b/main/xorg-server/xserver-1.10-pointer-barriers.patch
@@ -0,0 +1,1054 @@
+From 14f1112bec18ccece8e732fe6c200a56546230c7 Mon Sep 17 00:00:00 2001
+From: Adam Jackson <ajax@redhat.com>
+Date: Thu, 17 Mar 2011 13:56:17 -0400
+Subject: [PATCH] CRTC confine and pointer barriers
+
+---
+ dix/events.c | 7 +
+ dix/getevents.c | 12 +-
+ include/dix.h | 1 +
+ include/protocol-versions.h | 2 +-
+ mi/mipointer.c | 16 ++-
+ mi/mipointer.h | 6 +
+ randr/randr.c | 2 +
+ randr/randrstr.h | 4 +
+ randr/rrcrtc.c | 155 ++++++++++++++++
+ test/Makefile.am | 4 +-
+ xfixes/cursor.c | 408 ++++++++++++++++++++++++++++++++++++++++++-
+ xfixes/xfixes.c | 24 ++-
+ xfixes/xfixes.h | 17 ++
+ xfixes/xfixesint.h | 16 ++
+ 14 files changed, 658 insertions(+), 16 deletions(-)
+
+diff --git a/dix/events.c b/dix/events.c
+index 07f8b05..d2be84f 100644
+--- a/dix/events.c
++++ b/dix/events.c
+@@ -328,6 +328,13 @@ IsMaster(DeviceIntPtr dev)
+ return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
+ }
+
++Bool
++IsFloating(DeviceIntPtr dev)
++{
++ return GetMaster(dev, MASTER_KEYBOARD) == NULL;
++}
++
++
+ /**
+ * Max event opcode.
+ */
+diff --git a/dix/getevents.c b/dix/getevents.c
+index 794df42..c66e516 100644
+--- a/dix/getevents.c
++++ b/dix/getevents.c
+@@ -812,7 +812,11 @@ accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
+ * miPointerSetPosition() and then scale back into device coordinates (if
+ * needed). miPSP will change x/y if the screen was crossed.
+ *
++ * The coordinates provided are always absolute. The parameter mode whether
++ * it was relative or absolute movement that landed us at those coordinates.
++ *
+ * @param dev The device to be moved.
++ * @param mode Movement mode (Absolute or Relative)
+ * @param x Pointer to current x-axis value, may be modified.
+ * @param y Pointer to current y-axis value, may be modified.
+ * @param x_frac Fractional part of current x-axis value, may be modified.
+@@ -824,7 +828,8 @@ accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
+ * @param screeny_frac Fractional part of screen y coordinate, as above.
+ */
+ static void
+-positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
++positionSprite(DeviceIntPtr dev, int mode,
++ int *x, int *y, float x_frac, float y_frac,
+ ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
+ {
+ int old_screenx, old_screeny;
+@@ -863,7 +868,7 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
+ old_screeny = *screeny;
+ /* This takes care of crossing screens for us, as well as clipping
+ * to the current screen. */
+- miPointerSetPosition(dev, screenx, screeny);
++ _miPointerSetPosition(dev, mode, screenx, screeny);
+
+ if (dev->u.master) {
+ dev->u.master->last.valuators[0] = *screenx;
+@@ -1193,7 +1198,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
+
+ set_raw_valuators(raw, &mask, raw->valuators.data);
+
+- positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
++ positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
++ &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
+ updateHistory(pDev, &mask, ms);
+
+ /* Update the valuators with the true value sent to the client*/
+diff --git a/include/dix.h b/include/dix.h
+index 12e4b59..3f99098 100644
+--- a/include/dix.h
++++ b/include/dix.h
+@@ -570,6 +570,7 @@ extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
+ extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
+ extern Bool IsPointerEvent(InternalEvent *event);
+ extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
++extern _X_EXPORT Bool IsFloating(DeviceIntPtr dev);
+
+ extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
+ extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what);
+diff --git a/include/protocol-versions.h b/include/protocol-versions.h
+index 1d33bdd..1dc66ad 100644
+--- a/include/protocol-versions.h
++++ b/include/protocol-versions.h
+@@ -126,7 +126,7 @@
+ #define SERVER_XF86VIDMODE_MINOR_VERSION 2
+
+ /* Fixes */
+-#define SERVER_XFIXES_MAJOR_VERSION 4
++#define SERVER_XFIXES_MAJOR_VERSION 5
+ #define SERVER_XFIXES_MINOR_VERSION 0
+
+ /* X Input */
+diff --git a/mi/mipointer.c b/mi/mipointer.c
+index 554397a..85f1949 100644
+--- a/mi/mipointer.c
++++ b/mi/mipointer.c
+@@ -229,6 +229,10 @@ miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
+ SetupScreen (pScreen);
+
+ GenerateEvent = generateEvent;
++
++ if (pScreen->ConstrainCursorHarder)
++ pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
++
+ /* device dependent - must pend signal and call miPointerWarpCursor */
+ (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
+ if (!generateEvent)
+@@ -484,7 +488,7 @@ miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
+ }
+
+ void
+-miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
++_miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
+ {
+ miPointerScreenPtr pScreenPriv;
+ ScreenPtr pScreen;
+@@ -529,6 +533,9 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
+ if (*y >= pPointer->limits.y2)
+ *y = pPointer->limits.y2 - 1;
+
++ if (pScreen->ConstrainCursorHarder)
++ pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y);
++
+ if (pPointer->x == *x && pPointer->y == *y &&
+ pPointer->pScreen == pScreen)
+ return;
+@@ -536,6 +543,13 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
+ miPointerMoveNoEvent(pDev, pScreen, *x, *y);
+ }
+
++/* ABI hack */
++void
++miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
++{
++ _miPointerSetPosition(pDev, Absolute, x, y);
++}
++
+ void
+ miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
+ {
+diff --git a/mi/mipointer.h b/mi/mipointer.h
+index 3c86110..6b6010c 100644
+--- a/mi/mipointer.h
++++ b/mi/mipointer.h
+@@ -131,6 +131,12 @@ extern _X_EXPORT void miPointerGetPosition(
+
+ /* Moves the cursor to the specified position. May clip the co-ordinates:
+ * x and y are modified in-place. */
++extern _X_EXPORT void _miPointerSetPosition(
++ DeviceIntPtr pDev,
++ int mode,
++ int *x,
++ int *y);
++
+ extern _X_EXPORT void miPointerSetPosition(
+ DeviceIntPtr pDev,
+ int *x,
+diff --git a/randr/randr.c b/randr/randr.c
+index 6077705..d337129 100644
+--- a/randr/randr.c
++++ b/randr/randr.c
+@@ -270,6 +270,8 @@ Bool RRScreenInit(ScreenPtr pScreen)
+
+ wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
+
++ pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
++
+ pScrPriv->numOutputs = 0;
+ pScrPriv->outputs = NULL;
+ pScrPriv->numCrtcs = 0;
+diff --git a/randr/randrstr.h b/randr/randrstr.h
+index 7ea6080..d8dd37d 100644
+--- a/randr/randrstr.h
++++ b/randr/randrstr.h
+@@ -297,6 +297,7 @@ typedef struct _rrScrPriv {
+ int rate;
+ int size;
+ #endif
++ Bool discontiguous;
+ } rrScrPrivRec, *rrScrPrivPtr;
+
+ extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
+@@ -700,6 +701,9 @@ ProcRRGetPanning (ClientPtr client);
+ int
+ ProcRRSetPanning (ClientPtr client);
+
++void
++RRConstrainCursorHarder (DeviceIntPtr, ScreenPtr, int, int *, int *);
++
+ /* rrdispatch.c */
+ extern _X_EXPORT Bool
+ RRClientKnowsRates (ClientPtr pClient);
+diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
+index 98206a2..d4d8f2a 100644
+--- a/randr/rrcrtc.c
++++ b/randr/rrcrtc.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright © 2006 Keith Packard
++ * Copyright 2010 Red Hat, Inc
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+@@ -22,6 +23,7 @@
+
+ #include "randrstr.h"
+ #include "swaprep.h"
++#include "mipointer.h"
+
+ RESTYPE RRCrtcType;
+
+@@ -292,6 +294,92 @@ RRCrtcPendingProperties (RRCrtcPtr crtc)
+ return FALSE;
+ }
+
++static void
++crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom)
++{
++ *left = crtc->x;
++ *top = crtc->y;
++
++ switch (crtc->rotation) {
++ case RR_Rotate_0:
++ case RR_Rotate_180:
++ default:
++ *right = crtc->x + crtc->mode->mode.width;
++ *bottom = crtc->y + crtc->mode->mode.height;
++ return;
++ case RR_Rotate_90:
++ case RR_Rotate_270:
++ *right = crtc->x + crtc->mode->mode.height;
++ *bottom = crtc->y + crtc->mode->mode.width;
++ return;
++ }
++}
++
++/* overlapping counts as adjacent */
++static Bool
++crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b)
++{
++ /* left, right, top, bottom... */
++ int al, ar, at, ab;
++ int bl, br, bt, bb;
++ int cl, cr, ct, cb; /* the overlap, if any */
++
++ crtc_bounds(a, &al, &ar, &at, &ab);
++ crtc_bounds(b, &bl, &br, &bt, &bb);
++
++ cl = max(al, bl);
++ cr = min(ar, br);
++ ct = max(at, bt);
++ cb = min(ab, bb);
++
++ return (cl <= cr) && (ct <= cb);
++}
++
++/* Depth-first search and mark all CRTCs reachable from cur */
++static void
++mark_crtcs (rrScrPrivPtr pScrPriv, int *reachable, int cur)
++{
++ int i;
++ reachable[cur] = TRUE;
++ for (i = 0; i < pScrPriv->numCrtcs; ++i) {
++ if (reachable[i] || !pScrPriv->crtcs[i]->mode)
++ continue;
++ if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i]))
++ mark_crtcs(pScrPriv, reachable, i);
++ }
++}
++
++static void
++RRComputeContiguity (ScreenPtr pScreen)
++{
++ rrScrPriv(pScreen);
++ Bool discontiguous = TRUE;
++ int i, n = pScrPriv->numCrtcs;
++
++ int *reachable = calloc(n, sizeof(int));
++ if (!reachable)
++ goto out;
++
++ /* Find first enabled CRTC and start search for reachable CRTCs from it */
++ for (i = 0; i < n; ++i) {
++ if (pScrPriv->crtcs[i]->mode) {
++ mark_crtcs(pScrPriv, reachable, i);
++ break;
++ }
++ }
++
++ /* Check that all enabled CRTCs were marked as reachable */
++ for (i = 0; i < n; ++i)
++ if (pScrPriv->crtcs[i]->mode && !reachable[i])
++ goto out;
++
++ discontiguous = FALSE;
++
++out:
++ free(reachable);
++ pScrPriv->discontiguous = discontiguous;
++}
++
+ /*
+ * Request that the Crtc be reconfigured
+ */
+@@ -306,6 +394,7 @@ RRCrtcSet (RRCrtcPtr crtc,
+ {
+ ScreenPtr pScreen = crtc->pScreen;
+ Bool ret = FALSE;
++ Bool recompute = TRUE;
+ rrScrPriv(pScreen);
+
+ /* See if nothing changed */
+@@ -318,6 +407,7 @@ RRCrtcSet (RRCrtcPtr crtc,
+ !RRCrtcPendingProperties (crtc) &&
+ !RRCrtcPendingTransform (crtc))
+ {
++ recompute = FALSE;
+ ret = TRUE;
+ }
+ else
+@@ -381,6 +471,10 @@ RRCrtcSet (RRCrtcPtr crtc,
+ RRPostPendingProperties (outputs[o]);
+ }
+ }
++
++ if (recompute)
++ RRComputeContiguity(pScreen);
++
+ return ret;
+ }
+
+@@ -1349,3 +1443,64 @@ ProcRRGetCrtcTransform (ClientPtr client)
+ free(reply);
+ return Success;
+ }
++
++void
++RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, int *y)
++{
++ rrScrPriv (pScreen);
++ int i;
++
++ /* intentional dead space -> let it float */
++ if (pScrPriv->discontiguous)
++ return;
++
++ /* if we're moving inside a crtc, we're fine */
++ for (i = 0; i < pScrPriv->numCrtcs; i++) {
++ RRCrtcPtr crtc = pScrPriv->crtcs[i];
++
++ int left, right, top, bottom;
++
++ if (!crtc->mode)
++ continue;
++
++ crtc_bounds(crtc, &left, &right, &top, &bottom);
++
++ if ((*x >= left) && (*x <= right) && (*y >= top) && (*y <= bottom))
++ return;
++ }
++
++ /* if we're trying to escape, clamp to the CRTC we're coming from */
++ for (i = 0; i < pScrPriv->numCrtcs; i++) {
++ RRCrtcPtr crtc = pScrPriv->crtcs[i];
++ int nx, ny;
++ int left, right, top, bottom;
++
++ if (!crtc->mode)
++ continue;
++
++ crtc_bounds(crtc, &left, &right, &top, &bottom);
++ miPointerGetPosition(pDev, &nx, &ny);
++
++ if ((nx >= left) && (nx <= right) && (ny >= top) && (ny <= bottom)) {
++ if ((*x <= left) || (*x >= right)) {
++ int dx = *x - nx;
++
++ if (dx > 0)
++ *x = right;
++ else if (dx < 0)
++ *x = left;
++ }
++
++ if ((*y <= top) || (*y >= bottom)) {
++ int dy = *y - ny;
++
++ if (dy > 0)
++ *y = bottom;
++ else if (dy < 0)
++ *y = top;
++ }
++
++ return;
++ }
++ }
++}
+diff --git a/test/Makefile.am b/test/Makefile.am
+index 456221e..ccdb859 100644
+--- a/test/Makefile.am
++++ b/test/Makefile.am
+@@ -1,6 +1,6 @@
+ if UNITTESTS
+ SUBDIRS= . xi2
+-check_PROGRAMS = xkb input xtest
++check_PROGRAMS = xkb input xtest list fixes
+ check_LTLIBRARIES = libxservertest.la
+
+ TESTS=$(check_PROGRAMS)
+@@ -16,6 +16,8 @@ endif
+ xkb_LDADD=$(TEST_LDADD)
+ input_LDADD=$(TEST_LDADD)
+ xtest_LDADD=$(TEST_LDADD)
++list_LDADD=$(TEST_LDADD)
++fixes_LDADD=$(TEST_LDADD)
+
+ libxservertest_la_LIBADD = \
+ $(XSERVER_LIBS) \
+diff --git a/xfixes/cursor.c b/xfixes/cursor.c
+index fb608f6..5c55c95 100644
+--- a/xfixes/cursor.c
++++ b/xfixes/cursor.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright 2010 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+@@ -50,13 +51,16 @@
+ #include "cursorstr.h"
+ #include "dixevents.h"
+ #include "servermd.h"
++#include "mipointer.h"
+ #include "inputstr.h"
+ #include "windowstr.h"
+ #include "xace.h"
++#include "list.h"
+
+ static RESTYPE CursorClientType;
+ static RESTYPE CursorHideCountType;
+ static RESTYPE CursorWindowType;
++RESTYPE PointerBarrierType;
+ static CursorPtr CursorCurrent[MAXDEVICES];
+
+ static DevPrivateKeyRec CursorScreenPrivateKeyRec;
+@@ -107,6 +111,14 @@ typedef struct _CursorHideCountRec {
+ XID resource;
+ } CursorHideCountRec;
+
++typedef struct PointerBarrierClient *PointerBarrierClientPtr;
++
++struct PointerBarrierClient {
++ ScreenPtr screen;
++ struct PointerBarrier barrier;
++ struct list entry;
++};
++
+ /*
+ * Wrap DisplayCursor to catch cursor change events
+ */
+@@ -114,7 +126,9 @@ typedef struct _CursorHideCountRec {
+ typedef struct _CursorScreen {
+ DisplayCursorProcPtr DisplayCursor;
+ CloseScreenProcPtr CloseScreen;
++ ConstrainCursorHarderProcPtr ConstrainCursorHarder;
+ CursorHideCountPtr pCursorHideCounts;
++ struct list barriers;
+ } CursorScreenRec, *CursorScreenPtr;
+
+ #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
+@@ -184,9 +198,11 @@ CursorCloseScreen (int index, ScreenPtr pScreen)
+ Bool ret;
+ CloseScreenProcPtr close_proc;
+ DisplayCursorProcPtr display_proc;
++ ConstrainCursorHarderProcPtr constrain_proc;
+
+ Unwrap (cs, pScreen, CloseScreen, close_proc);
+ Unwrap (cs, pScreen, DisplayCursor, display_proc);
++ Unwrap (cs, pScreen, ConstrainCursorHarder, constrain_proc);
+ deleteCursorHideCountsForScreen(pScreen);
+ ret = (*pScreen->CloseScreen) (index, pScreen);
+ free(cs);
+@@ -1029,6 +1045,391 @@ CursorFreeWindow (pointer data, XID id)
+ return 1;
+ }
+
++static BOOL
++barrier_is_horizontal(const struct PointerBarrier *barrier)
++{
++ return barrier->y1 == barrier->y2;
++}
++
++static BOOL
++barrier_is_vertical(const struct PointerBarrier *barrier)
++{
++ return barrier->x1 == barrier->x2;
++}
++
++/**
++ * @return The set of barrier movement directions the movement vector
++ * x1/y1 → x2/y2 represents.
++ */
++int
++barrier_get_direction(int x1, int y1, int x2, int y2)
++{
++ int direction = 0;
++
++ /* which way are we trying to go */
++ if (x2 > x1)
++ direction |= BarrierPositiveX;
++ if (x2 < x1)
++ direction |= BarrierNegativeX;
++ if (y2 > y1)
++ direction |= BarrierPositiveY;
++ if (y2 < y1)
++ direction |= BarrierNegativeY;
++
++ return direction;
++}
++
++/**
++ * Test if the barrier may block movement in the direction defined by
++ * x1/y1 → x2/y2. This function only tests whether the directions could be
++ * blocked, it does not test if the barrier actually blocks the movement.
++ *
++ * @return TRUE if the barrier blocks the direction of movement or FALSE
++ * otherwise.
++ */
++BOOL
++barrier_is_blocking_direction(const struct PointerBarrier *barrier, int direction)
++{
++ /* Barriers define which way is ok, not which way is blocking */
++ return (barrier->directions & direction) != direction;
++}
++
++/**
++ * Test if the movement vector x1/y1 → x2/y2 is intersecting with the
++ * barrier. A movement vector with the startpoint or endpoint on the barrier
++ * itself counts as intersecting.
++ *
++ * @param x1 X start coordinate of movement vector
++ * @param y1 Y start coordinate of movement vector
++ * @param x2 X end coordinate of movement vector
++ * @param y2 Y end coordinate of movement vector
++ * @param[out] distance The distance between the start point and the
++ * intersection with the barrier (if applicable).
++ * @return TRUE if the barrier intersects with the given vector
++ */
++BOOL
++barrier_is_blocking(const struct PointerBarrier *barrier,
++ int x1, int y1, int x2, int y2,
++ double *distance)
++{
++ BOOL rc = FALSE;
++ float ua, ub, ud;
++ int dir = barrier_get_direction(x1, y1, x2, y2);
++
++ /* Algorithm below doesn't handle edge cases well, hence the extra
++ * checks. */
++ if (barrier_is_vertical(barrier)) {
++ /* handle immediate barrier adjacency, moving away */
++ if (dir & BarrierPositiveX && x1 == barrier->x1)
++ return FALSE;
++ if (dir & BarrierNegativeX && x1 == (barrier->x1 - 1))
++ return FALSE;
++ /* startpoint on barrier */
++ if (x1 == barrier->x1 && y1 >= barrier->y1 && y1 <= barrier->y2) {
++ *distance = 0;
++ return TRUE;
++ }
++ /* endpoint on barrier */
++ if (x2 == barrier->x1 && y2 >= barrier->y1 && y2 <= barrier->y2) {
++ *distance = abs(x2 - x1);
++ return TRUE;
++ }
++ } else {
++ /* handle immediate barrier adjacency, moving away */
++ if (dir & BarrierPositiveY && y1 == barrier->y1)
++ return FALSE;
++ if (dir & BarrierNegativeY && y1 == (barrier->y1 - 1))
++ return FALSE;
++ /* startpoint on barrier */
++ if (y1 == barrier->y1 && x1 >= barrier->x1 && x1 <= barrier->x2) {
++ *distance = 0;
++ return TRUE;
++ }
++ /* endpoint on barrier */
++ if (y2 == barrier->y1 && x2 >= barrier->x1 && x2 <= barrier->x2) {
++ *distance = abs(y2 - y1);
++ return TRUE;
++ }
++ }
++
++ /* not an edge case, compute distance */
++ ua = 0;
++ ud = (barrier->y2 - barrier->y1) * (x2 - x1) - (barrier->x2 - barrier->x1) * (y2 - y1);
++ if (ud != 0) {
++ ua = ((barrier->x2 - barrier->x1) * (y1 - barrier->y1) -
++ (barrier->y2 - barrier->y1) * (x1 - barrier->x1)) / ud;
++ ub = ((x2 - x1) * (y1 - barrier->y1) -
++ (y2 - y1) * (x1 - barrier->x1)) / ud;
++ if (ua < 0 || ua > 1 || ub < 0 || ub > 1)
++ ua = 0;
++ }
++
++ if (ua > 0 && ua <= 1)
++ {
++ double ix = barrier->x1 + ua * (barrier->x2 - barrier->x1);
++ double iy = barrier->y1 + ua * (barrier->y2 - barrier->y1);
++
++ *distance = sqrt(pow(x1 - ix, 2) + pow(y1 - iy, 2));
++ rc = TRUE;
++ }
++
++ return rc;
++}
++
++/**
++ * Find the nearest barrier that is blocking movement from x1/y1 to x2/y2.
++ *
++ * @param dir Only barriers blocking movement in direction dir are checked
++ * @param x1 X start coordinate of movement vector
++ * @param y1 Y start coordinate of movement vector
++ * @param x2 X end coordinate of movement vector
++ * @param y2 Y end coordinate of movement vector
++ * @return The barrier nearest to the movement origin that blocks this movement.
++ */
++static struct PointerBarrier*
++barrier_find_nearest(CursorScreenPtr cs, int dir,
++ int x1, int y1, int x2, int y2)
++{
++ struct PointerBarrierClient *c;
++ struct PointerBarrier *nearest = NULL;
++ double min_distance = INT_MAX; /* can't get higher than that in X anyway */
++
++ list_for_each_entry(c, &cs->barriers, entry) {
++ struct PointerBarrier *b = &c->barrier;
++ double distance;
++
++ if (!barrier_is_blocking_direction(b, dir))
++ continue;
++
++ if (barrier_is_blocking(b, x1, y1, x2, y2, &distance))
++ {
++ if (min_distance > distance)
++ {
++ min_distance = distance;
++ nearest = b;
++ }
++ }
++ }
++
++ return nearest;
++}
++
++/**
++ * Clamp to the given barrier given the movement direction specified in dir.
++ *
++ * @param barrier The barrier to clamp to
++ * @param dir The movement direction
++ * @param[out] x The clamped x coordinate.
++ * @param[out] y The clamped x coordinate.
++ */
++void
++barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y)
++{
++ if (barrier_is_vertical(barrier)) {
++ if ((dir & BarrierNegativeX) & ~barrier->directions)
++ *x = barrier->x1;
++ if ((dir & BarrierPositiveX) & ~barrier->directions)
++ *x = barrier->x1 - 1;
++ }
++ if (barrier_is_horizontal(barrier))
++ {
++ if ((dir & BarrierNegativeY) & ~barrier->directions)
++ *y = barrier->y1;
++ if ((dir & BarrierPositiveY) & ~barrier->directions)
++ *y = barrier->y1 - 1;
++ }
++}
++
++static void
++CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
++{
++ CursorScreenPtr cs = GetCursorScreen(screen);
++
++ if (!list_is_empty(&cs->barriers) && !IsFloating(dev) && mode == Relative) {
++ int ox, oy;
++ int dir;
++ struct PointerBarrier *nearest = NULL;
++
++ /* where are we coming from */
++ miPointerGetPosition(dev, &ox, &oy);
++
++ /* How this works:
++ * Given the origin and the movement vector, get the nearest barrier
++ * to the origin that is blocking the movement.
++ * Clamp to that barrier.
++ * Then, check from the clamped position to the original
++ * destination, again finding the nearest barrier and clamping.
++ */
++ dir = barrier_get_direction(ox, oy, *x, *y);
++
++ nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y);
++ if (nearest) {
++ barrier_clamp_to_barrier(nearest, dir, x, y);
++
++ if (barrier_is_vertical(nearest)) {
++ dir &= ~(BarrierNegativeX | BarrierPositiveX);
++ ox = *x;
++ } else if (barrier_is_horizontal(nearest)) {
++ dir &= ~(BarrierNegativeY | BarrierPositiveY);
++ oy = *y;
++ }
++
++ nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y);
++ if (nearest) {
++ barrier_clamp_to_barrier(nearest, dir, x, y);
++ }
++ }
++ }
++
++ if (cs->ConstrainCursorHarder) {
++ screen->ConstrainCursorHarder = cs->ConstrainCursorHarder;
++ screen->ConstrainCursorHarder(dev, screen, mode, x, y);
++ screen->ConstrainCursorHarder = CursorConstrainCursorHarder;
++ }
++}
++
++static struct PointerBarrierClient *
++CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client,
++ xXFixesCreatePointerBarrierReq *stuff)
++{
++ CursorScreenPtr cs = GetCursorScreen(screen);
++ struct PointerBarrierClient *ret = malloc(sizeof(*ret));
++
++ if (ret) {
++ ret->screen = screen;
++ ret->barrier.x1 = min(stuff->x1, stuff->x2);
++ ret->barrier.x2 = max(stuff->x1, stuff->x2);
++ ret->barrier.y1 = min(stuff->y1, stuff->y2);
++ ret->barrier.y2 = max(stuff->y1, stuff->y2);
++ ret->barrier.directions = stuff->directions & 0x0f;
++ if (barrier_is_horizontal(&ret->barrier))
++ ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
++ if (barrier_is_vertical(&ret->barrier))
++ ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY);
++ list_add(&ret->entry, &cs->barriers);
++ }
++
++ return ret;
++}
++
++int
++ProcXFixesCreatePointerBarrier (ClientPtr client)
++{
++ int err;
++ WindowPtr pWin;
++ struct PointerBarrierClient *barrier;
++ struct PointerBarrier b;
++ REQUEST (xXFixesCreatePointerBarrierReq);
++
++ REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
++ LEGAL_NEW_RESOURCE(stuff->barrier, client);
++
++ err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
++ if (err != Success) {
++ client->errorValue = stuff->window;
++ return err;
++ }
++
++ /* This sure does need fixing. */
++ if (stuff->num_devices)
++ return BadImplementation;
++
++ b.x1 = stuff->x1;
++ b.x2 = stuff->x2;
++ b.y1 = stuff->y1;
++ b.y2 = stuff->y2;
++
++ if (!barrier_is_horizontal(&b) && !barrier_is_vertical(&b))
++ return BadValue;
++
++ /* no 0-sized barriers */
++ if (barrier_is_horizontal(&b) && barrier_is_vertical(&b))
++ return BadValue;
++
++ if (!(barrier = CreatePointerBarrierClient(pWin->drawable.pScreen,
++ client, stuff)))
++ return BadAlloc;
++
++ if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier))
++ return BadAlloc;
++
++ return Success;
++}
++
++int
++SProcXFixesCreatePointerBarrier (ClientPtr client)
++{
++ int n;
++ REQUEST(xXFixesCreatePointerBarrierReq);
++
++ swaps(&stuff->length, n);
++ REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
++ swapl(&stuff->barrier, n);
++ swapl(&stuff->window, n);
++ swaps(&stuff->x1, n);
++ swaps(&stuff->y1, n);
++ swaps(&stuff->x2, n);
++ swaps(&stuff->y2, n);
++ swapl(&stuff->directions, n);
++ return ProcXFixesVector[stuff->xfixesReqType](client);
++}
++
++static int
++CursorFreeBarrier(void *data, XID id)
++{
++ struct PointerBarrierClient *b = NULL, *barrier;
++ ScreenPtr screen;
++ CursorScreenPtr cs;
++
++ barrier = container_of(data, struct PointerBarrierClient, barrier);
++ screen = barrier->screen;
++ cs = GetCursorScreen(screen);
++
++ /* find and unlink from the screen private */
++ list_for_each_entry(b, &cs->barriers, entry) {
++ if (b == barrier) {
++ list_del(&b->entry);
++ break;
++ }
++ }
++
++ free(barrier);
++ return Success;
++}
++
++int
++ProcXFixesDestroyPointerBarrier (ClientPtr client)
++{
++ int err;
++ void *barrier;
++ REQUEST (xXFixesDestroyPointerBarrierReq);
++
++ REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
++
++ err = dixLookupResourceByType((void **)&barrier, stuff->barrier,
++ PointerBarrierType, client,
++ DixDestroyAccess);
++ if (err != Success) {
++ client->errorValue = stuff->barrier;
++ return err;
++ }
++
++ FreeResource(stuff->barrier, RT_NONE);
++ return Success;
++}
++
++int
++SProcXFixesDestroyPointerBarrier (ClientPtr client)
++{
++ int n;
++ REQUEST(xXFixesDestroyPointerBarrierReq);
++
++ swaps(&stuff->length, n);
++ REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
++ swapl(&stuff->barrier, n);
++ return ProcXFixesVector[stuff->xfixesReqType](client);
++}
++
+ Bool
+ XFixesCursorInit (void)
+ {
+@@ -1048,8 +1449,10 @@ XFixesCursorInit (void)
+ cs = (CursorScreenPtr) calloc(1, sizeof (CursorScreenRec));
+ if (!cs)
+ return FALSE;
++ list_init(&cs->barriers);
+ Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
+ Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
++ Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
+ cs->pCursorHideCounts = NULL;
+ SetCursorScreen (pScreen, cs);
+ }
+@@ -1059,7 +1462,10 @@ XFixesCursorInit (void)
+ "XFixesCursorHideCount");
+ CursorWindowType = CreateNewResourceType(CursorFreeWindow,
+ "XFixesCursorWindow");
++ PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
++ "XFixesPointerBarrier");
+
+- return CursorClientType && CursorHideCountType && CursorWindowType;
++ return CursorClientType && CursorHideCountType && CursorWindowType &&
++ PointerBarrierType;
+ }
+
+diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c
+index e8c7bf1..a57884b 100644
+--- a/xfixes/xfixes.c
++++ b/xfixes/xfixes.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright 2010 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+@@ -47,10 +48,6 @@
+
+ #include "xfixesint.h"
+ #include "protocol-versions.h"
+-/*
+- * Must use these instead of the constants from xfixeswire.h. They advertise
+- * what we implement, not what the protocol headers define.
+- */
+
+ static unsigned char XFixesReqCode;
+ int XFixesEventBase;
+@@ -97,11 +94,12 @@ ProcXFixesQueryVersion(ClientPtr client)
+
+ /* Major version controls available requests */
+ static const int version_requests[] = {
+- X_XFixesQueryVersion, /* before client sends QueryVersion */
+- X_XFixesGetCursorImage, /* Version 1 */
+- X_XFixesChangeCursorByName, /* Version 2 */
+- X_XFixesExpandRegion, /* Version 3 */
+- X_XFixesShowCursor, /* Version 4 */
++ X_XFixesQueryVersion, /* before client sends QueryVersion */
++ X_XFixesGetCursorImage, /* Version 1 */
++ X_XFixesChangeCursorByName, /* Version 2 */
++ X_XFixesExpandRegion, /* Version 3 */
++ X_XFixesShowCursor, /* Version 4 */
++ X_XFixesDestroyPointerBarrier, /* Version 5 */
+ };
+
+ #define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
+@@ -142,6 +140,9 @@ int (*ProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
+ /*************** Version 4 ****************/
+ ProcXFixesHideCursor,
+ ProcXFixesShowCursor,
++/*************** Version 5 ****************/
++ ProcXFixesCreatePointerBarrier,
++ ProcXFixesDestroyPointerBarrier,
+ };
+
+ static int
+@@ -205,6 +206,9 @@ static int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
+ /*************** Version 4 ****************/
+ SProcXFixesHideCursor,
+ SProcXFixesShowCursor,
++/*************** Version 5 ****************/
++ SProcXFixesCreatePointerBarrier,
++ SProcXFixesDestroyPointerBarrier,
+ };
+
+ static int
+@@ -260,6 +264,8 @@ XFixesExtensionInit(void)
+ EventSwapVector[XFixesEventBase + XFixesCursorNotify] =
+ (EventSwapPtr) SXFixesCursorNotifyEvent;
+ SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion);
++ SetResourceTypeErrorValue(PointerBarrierType,
++ XFixesErrorBase + BadBarrier);
+ }
+ }
+
+diff --git a/xfixes/xfixes.h b/xfixes/xfixes.h
+index 1638350..5765e64 100644
+--- a/xfixes/xfixes.h
++++ b/xfixes/xfixes.h
+@@ -30,6 +30,7 @@
+ #include "resource.h"
+
+ extern _X_EXPORT RESTYPE RegionResType;
++extern _X_EXPORT RESTYPE PointerBarrierType;
+ extern _X_EXPORT int XFixesErrorBase;
+
+ #define VERIFY_REGION(pRegion, rid, client, mode) \
+@@ -51,5 +52,21 @@ extern _X_EXPORT int XFixesErrorBase;
+ extern _X_EXPORT RegionPtr
+ XFixesRegionCopy (RegionPtr pRegion);
+
++struct PointerBarrier {
++ CARD16 x1, x2, y1, y2;
++ CARD32 directions;
++};
++
++
++extern int
++barrier_get_direction(int, int, int, int);
++extern BOOL
++barrier_is_blocking(const struct PointerBarrier*, int, int, int, int, double*);
++extern BOOL
++barrier_is_blocking_direction(const struct PointerBarrier*, int);
++extern void
++barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y);
++
++
+
+ #endif /* _XFIXES_H_ */
+diff --git a/xfixes/xfixesint.h b/xfixes/xfixesint.h
+index d005369..6ba276e 100644
+--- a/xfixes/xfixesint.h
++++ b/xfixes/xfixesint.h
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright 2010 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+@@ -278,6 +279,21 @@ ProcXFixesShowCursor (ClientPtr client);
+ int
+ SProcXFixesShowCursor (ClientPtr client);
+
++/* Version 5 */
++
++int
++ProcXFixesCreatePointerBarrier (ClientPtr client);
++
++int
++SProcXFixesCreatePointerBarrier (ClientPtr client);
++
++int
++ProcXFixesDestroyPointerBarrier (ClientPtr client);
++
++int
++SProcXFixesDestroyPointerBarrier (ClientPtr client);
++
++/* Xinerama */
+ extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr);
+ void PanoramiXFixesInit (void);
+ void PanoramiXFixesReset (void);
+--
+1.7.4
+
diff --git a/main/xproto/APKBUILD b/main/xproto/APKBUILD
new file mode 100644
index 0000000000..00d27bb3df
--- /dev/null
+++ b/main/xproto/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xproto
+pkgver=7.0.21
+pkgrel=0
+pkgdesc="X11 core wire protocol and auxiliary headers"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+depends=""
+makedepends=""
+# only headers here so no need for subpkgs
+#subpackages="$pkgname-dev $pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 "$srcdir"/$pkgname-$pkgver/COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+md5sums="c5a93a69b701cf81925fab02b35b0d0e xproto-7.0.21.tar.bz2"
diff --git a/main/xrandr/APKBUILD b/main/xrandr/APKBUILD
new file mode 100644
index 0000000000..810e8e79f7
--- /dev/null
+++ b/main/xrandr/APKBUILD
@@ -0,0 +1,27 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xrandr
+pkgver=1.3.2
+pkgrel=2
+pkgdesc="primitive command line interface to RandR extension"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libxrandr-dev libxrender-dev libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2
+ $pkgname-1.3.0-clone-nameclash.patch"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 < ../$pkgname-1.3.0-clone-nameclash.patch || return 1
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="2cb19bb1c19ccf77c40032b03dbe06f0 xrandr-1.3.2.tar.bz2
+b938aad95a5ea71bce7a2529fd8f6866 xrandr-1.3.0-clone-nameclash.patch"
diff --git a/main/xrandr/xrandr-1.3.0-clone-nameclash.patch b/main/xrandr/xrandr-1.3.0-clone-nameclash.patch
new file mode 100644
index 0000000000..55af5590c4
--- /dev/null
+++ b/main/xrandr/xrandr-1.3.0-clone-nameclash.patch
@@ -0,0 +1,29 @@
+--- xrandr-1.3.0/xrandr.c.orig 2009-04-10 12:26:02.000000000 +0000
++++ xrandr-1.3.0/xrandr.c 2009-04-10 12:43:44.000000000 +0000
+@@ -209,7 +209,7 @@
+
+ #if HAS_RANDR_1_2
+ typedef enum _policy {
+- clone, extend
++ p_clone, extend
+ } policy_t;
+
+ typedef enum _relation {
+@@ -2027,7 +2027,7 @@
+ int ret = 0;
+ #if HAS_RANDR_1_2
+ output_t *output = NULL;
+- policy_t policy = clone;
++ policy_t policy = p_clone;
+ Bool setit_1_2 = False;
+ Bool query_1_2 = False;
+ Bool modeit = False;
+@@ -2401,7 +2401,7 @@
+ continue;
+ }
+ if (!strcmp ("--clone", argv[i])) {
+- policy = clone;
++ policy = p_clone;
+ setit_1_2 = True;
+ continue;
+ }
diff --git a/main/xrdb/APKBUILD b/main/xrdb/APKBUILD
new file mode 100644
index 0000000000..6819aac85f
--- /dev/null
+++ b/main/xrdb/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xrdb
+pkgver=1.0.9
+pkgrel=0
+pkgdesc="X server resource database utility"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libxmu-dev libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build () {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="ed2e48cf33584455d74615ad4bbe4246 xrdb-1.0.9.tar.bz2"
diff --git a/main/xrefresh/APKBUILD b/main/xrefresh/APKBUILD
new file mode 100644
index 0000000000..fd7dd669dc
--- /dev/null
+++ b/main/xrefresh/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xrefresh
+pkgver=1.0.3
+pkgrel=2
+pkgdesc="refresh all or part of an X screen"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="8f4fafcfb77b3c6972cc44bb3f1c899c xrefresh-1.0.3.tar.bz2"
diff --git a/main/xscreensaver/APKBUILD b/main/xscreensaver/APKBUILD
new file mode 100644
index 0000000000..0ab3f2a91e
--- /dev/null
+++ b/main/xscreensaver/APKBUILD
@@ -0,0 +1,40 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=xscreensaver
+pkgver=5.13
+pkgrel=1
+pkgdesc="screensavers for X11 environment"
+url="http://www.jwz.org/xscreensaver/"
+license="GPL"
+depends="bc"
+makedepends="gtk+-dev jpeg-dev mesa-dev gettext-dev libxmu-dev perl-dev
+ libxml2-dev libglade-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://www.jwz.org/$pkgname/$pkgname-$pkgver.tar.gz"
+arch="all"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ export LIBS="-lintl"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --with-gtk \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install_prefix="$pkgdir" install
+}
+
+md5sums="a1a55b763e17c5c83a2b7cb5ddf23560 xscreensaver-5.13.tar.gz"
diff --git a/main/xset/APKBUILD b/main/xset/APKBUILD
new file mode 100644
index 0000000000..105dbe4ac8
--- /dev/null
+++ b/main/xset/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xset
+pkgver=1.1.0
+pkgrel=2
+pkgdesc="X.Org xset application"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libxmu-dev libx11-dev libxext-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="eeb0d02f69c76bd40470dede99b4bd49 xset-1.1.0.tar.bz2"
diff --git a/main/xsetmode/APKBUILD b/main/xsetmode/APKBUILD
new file mode 100644
index 0000000000..8b11f54785
--- /dev/null
+++ b/main/xsetmode/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xsetmode
+pkgver=1.0.0
+pkgrel=3
+pkgdesc="set the mode for an X Input device"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libxi-dev libx11-dev"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="d074e79d380b031d2f60e4cd56538c93 xsetmode-1.0.0.tar.bz2"
diff --git a/main/xsetroot/APKBUILD b/main/xsetroot/APKBUILD
new file mode 100644
index 0000000000..e8a6d072af
--- /dev/null
+++ b/main/xsetroot/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xsetroot
+pkgver=1.0.3
+pkgrel=2
+pkgdesc="X.Org xsetroot application"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+depends=
+makedepends="pkgconfig libx11-dev libxmu-dev xbitmaps"
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr --mandir=/usr/share/man || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="cbda9b9b8da5af4614110883d5a276b8 xsetroot-1.0.3.tar.bz2"
diff --git a/main/xtables-addons-grsec/APKBUILD b/main/xtables-addons-grsec/APKBUILD
new file mode 100644
index 0000000000..898230188b
--- /dev/null
+++ b/main/xtables-addons-grsec/APKBUILD
@@ -0,0 +1,47 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+_flavor=${FLAVOR:-grsec}
+_realname=xtables-addons
+
+# source the kernel version
+if [ -f ../linux-$_flavor/APKBUILD ]; then
+ . ../linux-$_flavor/APKBUILD
+fi
+_kernelver=$pkgver-r$pkgrel
+_abi_release=$pkgver-${_flavor}
+_kpkgrel=$pkgrel
+
+pkgname=${_realname}-${_flavor}
+pkgver=${pkgver}
+_realver=1.36
+_mypkgrel=1
+pkgrel=$(($_kpkgrel + $_mypkgrel))
+pkgdesc="Iptables extensions kernel modules"
+url="http://xtables-addons.sourceforge.net/"
+arch="all"
+license="GPL"
+depends="linux-${_flavor}=${_kernelver}"
+makedepends="linux-${_flavor}-dev=${_kernelver} iptables-dev pkgconfig"
+install=
+subpackages=
+source="http://downloads.sourceforge.net/$_realname/$_realname-$_realver.tar.xz"
+
+# override kernel's prepare()
+prepare() {
+ :
+}
+
+build() {
+ cd "$srcdir/$_realname-$_realver"
+ ./configure --prefix=/usr \
+ --with-kbuild=/usr/src/linux-headers-${_abi_release}
+
+ cd extensions
+ make CC="${CC:-gcc}" modules || return 1
+}
+
+package() {
+ cd "$srcdir/$_realname-$_realver"/extensions
+ make DESTDIR="$pkgdir" modules_install
+}
+
+md5sums="2b976f502f626ed2245d276d83efc451 xtables-addons-1.36.tar.xz"
diff --git a/main/xtables-addons/APKBUILD b/main/xtables-addons/APKBUILD
new file mode 100644
index 0000000000..ab72e6a844
--- /dev/null
+++ b/main/xtables-addons/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xtables-addons
+pkgver=1.36
+pkgrel=0
+pkgdesc="Netfilter userspace extensions for iptables"
+url="http://xtables-addons.sourceforge.net/"
+arch="all"
+license="GPL"
+depends=
+makedepends="iptables-dev pkgconfig bash"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.xz"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ --without-kbuild
+
+ make CC="${CC-gcc}" kbuilddir=
+}
+
+package() {
+ cd "$srcdir/$pkgname-$pkgver"
+ make builddir= DESTDIR="$pkgdir" install
+}
+
+md5sums="2b976f502f626ed2245d276d83efc451 xtables-addons-1.36.tar.xz"
diff --git a/main/xtrans/APKBUILD b/main/xtrans/APKBUILD
new file mode 100644
index 0000000000..d052c2903a
--- /dev/null
+++ b/main/xtrans/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xtrans
+pkgver=1.2.6
+pkgrel=0
+pkgdesc="X transport library"
+url="http://xorg.freedesktop.org/"
+arch="noarch"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/lib/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="c66f9ffd2da4fb012220c6c40ebc7609 xtrans-1.2.6.tar.bz2"
diff --git a/main/xulrunner/APKBUILD b/main/xulrunner/APKBUILD
new file mode 100644
index 0000000000..7ee944d294
--- /dev/null
+++ b/main/xulrunner/APKBUILD
@@ -0,0 +1,111 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=xulrunner
+pkgver=2.0.1
+_ffoxver=4.0.1
+pkgrel=5
+pkgdesc="runtime environment for xul-based applications"
+url="http://developer.mozilla.org/en/XULRunner"
+arch="all"
+license="GPL LGPL MPL"
+depends=
+depends_dev="nspr-dev
+ nss-dev
+ gtk+-dev
+ dbus-glib-dev
+ alsa-lib-dev
+ libvorbis-dev
+ libogg-dev
+ libtheora-dev
+ wireless-tools-dev
+ libnotify-dev
+ libevent-dev
+ libxt-dev
+ jpeg-dev
+ bzip2-dev
+ hunspell-dev
+ startup-notification-dev
+ sqlite-dev
+ libidl-dev
+ fts-dev
+ mesa-dev"
+makedepends="$depends_dev
+
+ autoconf2.13
+
+ python
+ zip
+ yasm
+
+ autoconf
+ automake
+ libtool"
+install=""
+subpackages="$pkgname-dev"
+# http://releases.mozilla.org/pub/mozilla.org/xulrunner/releases/${pkgver}/source/${pkgname}-${pkgver}.source.tar.bz2
+source="http://releases.mozilla.org/pub/mozilla.org/firefox/releases/${_ffoxver}/source/firefox-${_ffoxver}.source.tar.bz2
+
+ mozconfig
+
+ fix-xulrunner-launcher.patch
+ mozilla-pkgconfig.patch
+
+ xulrunner-jemalloc-aslr.patch
+ xulrunner-mozalloc.patch
+
+ mozjs-c99math.patch
+ gecko-c99math.patch"
+
+_builddir="${srcdir}/mozilla-2.0"
+prepare() {
+ local i
+
+ cd "$_builddir"
+
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ cp "${srcdir}/mozconfig" .mozconfig
+}
+
+build() {
+ cd "$_builddir"
+
+ # mozilla's buildsystem is on drugs, so we just kill our CFLAGS and hope
+ # for the best. --nenolod
+ unset CFLAGS
+ unset CXXFLAGS
+
+ make -j1 -f client.mk build MOZ_MAKE_FLAGS="$MAKEFLAGS" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make -j1 DESTDIR="$pkgdir" -f client.mk install || return 1
+
+ msg "Setting up compatibility symlinks..."
+ ln -sf /usr/lib/xulrunner-${pkgver}/libxul.so "${pkgdir}"/usr/lib/libxul.so
+ ln -sf /usr/lib/xulrunner-${pkgver}/libxpcom.so "${pkgdir}"/usr/lib/libxpcom.so
+ ln -sf /usr/lib/xulrunner-${pkgver}/libmozalloc.so "${pkgdir}"/usr/lib/libmozalloc.so
+}
+
+dev() {
+ replaces="xulrunner"
+
+ mkdir -p "${subpkgdir}"/usr/lib
+ mv "${pkgdir}"/usr/lib/xulrunner-devel-${pkgver} "${subpkgdir}"/usr/lib
+ mv "${pkgdir}"/usr/lib/pkgconfig "${subpkgdir}"/usr/lib
+ mv "${pkgdir}"/usr/include "${subpkgdir}"/usr/include
+}
+
+md5sums="9abda7d23151e97913c8555a64c13f34 firefox-4.0.1.source.tar.bz2
+de64a11f40bb6e8800ba799d1b2b8d85 mozconfig
+86d33a17286131d9ef4cdfb35ee56f1f fix-xulrunner-launcher.patch
+02c23dc4ebd88e445533314716331818 mozilla-pkgconfig.patch
+30053b8b5811cc0676bfe7d7d7ffaa4a xulrunner-jemalloc-aslr.patch
+d38ecbb7bb31032d3e1ced8939e26abd xulrunner-mozalloc.patch
+b187440207e773e9be606594d2c99216 mozjs-c99math.patch
+aacbb29e1448f9af6697e8a885b9bbfa gecko-c99math.patch"
diff --git a/main/xulrunner/fix-xulrunner-launcher.patch b/main/xulrunner/fix-xulrunner-launcher.patch
new file mode 100644
index 0000000000..62af1ab308
--- /dev/null
+++ b/main/xulrunner/fix-xulrunner-launcher.patch
@@ -0,0 +1,23 @@
+--- a/xulrunner/stub/nsXULStub.cpp 2008-07-17 21:43:11.000000000 +0200
++++ b/xulrunner/stub/nsXULStub.cpp 2008-07-17 21:47:04.000000000 +0200
+@@ -208,8 +208,10 @@
+ // 3) give up
+
+ struct stat fileStat;
++ char *testp;
+
+- if (!realpath(argv[0], iniPath) || stat(iniPath, &fileStat)) {
++ testp = realpath(argv[0], iniPath);
++ if (!(testp != NULL && stat(iniPath, &fileStat) == 0 && S_ISREG(fileStat.st_mode) && fileStat.st_mode & S_IXUSR) || (testp != NULL && stat(iniPath, &fileStat))) {
+ const char *path = getenv("PATH");
+ if (!path)
+ return 1;
+@@ -222,7 +224,7 @@
+ char *token = strtok(pathdup, ":");
+ while (token) {
+ sprintf(tmpPath, "%s/%s", token, argv[0]);
+- if (realpath(tmpPath, iniPath) && stat(iniPath, &fileStat) == 0) {
++ if (realpath(tmpPath, iniPath) && stat(iniPath, &fileStat) == 0 && S_ISREG(fileStat.st_mode) && fileStat.st_mode & S_IXUSR) {
+ found = PR_TRUE;
+ break;
+ }
diff --git a/main/xulrunner/gecko-c99math.patch b/main/xulrunner/gecko-c99math.patch
new file mode 100644
index 0000000000..cdb846442b
--- /dev/null
+++ b/main/xulrunner/gecko-c99math.patch
@@ -0,0 +1,11 @@
+--- mozilla-2.0.orig/content/canvas/src/nsCanvasRenderingContext2D.cpp
++++ mozilla-2.0/content/canvas/src/nsCanvasRenderingContext2D.cpp
+@@ -159,7 +159,7 @@
+ // NOTE: '!!' casts an int to bool without spamming MSVC warning C4800.
+ return !!_finite(d);
+ #else
+- return finite(d);
++ return isfinite(d);
+ #endif
+ }
+
diff --git a/main/xulrunner/mozconfig b/main/xulrunner/mozconfig
new file mode 100644
index 0000000000..9bdde73f45
--- /dev/null
+++ b/main/xulrunner/mozconfig
@@ -0,0 +1,37 @@
+. $topsrcdir/xulrunner/config/mozconfig
+
+ac_add_options --prefix=/usr
+ac_add_options --libdir=/usr/lib
+ac_add_options --with-system-nspr
+ac_add_options --with-system-nss
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-zlib
+ac_add_options --with-system-bz2
+ac_add_options --with-system-libevent
+ac_add_options --enable-system-hunspell
+ac_add_options --enable-system-sqlite
+ac_add_options --enable-system-cairo
+ac_add_options --with-pthreads
+ac_add_options --enable-strip
+ac_add_options --disable-tests
+ac_add_options --disable-mochitest
+ac_add_options --disable-installer
+ac_add_options --disable-debug
+ac_add_options --enable-optimize
+ac_add_options --enable-default-toolkit=cairo-gtk2
+ac_add_options --enable-pango
+ac_add_options --enable-svg
+ac_add_options --enable-canvas
+ac_add_options --disable-javaxpcom
+ac_add_options --disable-crashreporter
+ac_add_options --enable-safe-browsing
+ac_add_options --enable-startup-notification
+ac_add_options --enable-extensions=default
+ac_add_options --enable-jemalloc
+
+export LIBS="-lfts -lubacktrace"
+export BUILD_OFFICIAL=1
+export MOZILLA_OFFICIAL=1
+
+mk_add_options BUILD_OFFICIAL=1
+mk_add_options MOZILLA_OFFICIAL=1
diff --git a/main/xulrunner/mozilla-pkgconfig.patch b/main/xulrunner/mozilla-pkgconfig.patch
new file mode 100644
index 0000000000..5c8bd0fd6e
--- /dev/null
+++ b/main/xulrunner/mozilla-pkgconfig.patch
@@ -0,0 +1,60 @@
+diff -Nur mozilla-1.9.2.orig/xulrunner/installer/libxul-embedding.pc.in mozilla-1.9.2/xulrunner/installer/libxul-embedding.pc.in
+--- mozilla-1.9.2.orig/xulrunner/installer/libxul-embedding.pc.in 2010-01-21 05:31:27.000000000 +0200
++++ mozilla-1.9.2/xulrunner/installer/libxul-embedding.pc.in 2010-01-21 22:27:17.000000000 +0200
+@@ -6,5 +6,6 @@
+ Name: libxul-embedding
+ Description: Static library for version-independent embedding of the Mozilla runtime
+ Version: %MOZILLA_VERSION%
++Requires: %NSPR_NAME% >= %NSPR_VERSION%
+ Libs: -L${sdkdir}/lib -lxpcomglue -ldl
+ Cflags: -DXPCOM_GLUE -I${includedir} %WCHAR_CFLAGS%
+diff -Nur mozilla-1.9.2.orig/xulrunner/installer/libxul.pc.in mozilla-1.9.2/xulrunner/installer/libxul.pc.in
+--- mozilla-1.9.2.orig/xulrunner/installer/libxul.pc.in 2010-01-21 05:31:27.000000000 +0200
++++ mozilla-1.9.2/xulrunner/installer/libxul.pc.in 2010-01-21 22:27:56.000000000 +0200
+@@ -1,5 +1,6 @@
+ prefix=%prefix%
+ sdkdir=%sdkdir%
++libdir=%libdir%
+ includedir=%includedir%
+ idldir=%idldir%
+
+diff -Nur mozilla-1.9.2.orig/xulrunner/installer/Makefile.in mozilla-1.9.2/xulrunner/installer/Makefile.in
+--- mozilla-1.9.2.orig/xulrunner/installer/Makefile.in 2010-01-21 05:31:27.000000000 +0200
++++ mozilla-1.9.2/xulrunner/installer/Makefile.in 2010-01-21 22:25:04.000000000 +0200
+@@ -121,6 +121,7 @@
+ -e "s|%includedir%|$(includedir)|" \
+ -e "s|%idldir%|$(idldir)|" \
+ -e "s|%sdkdir%|$(sdkdir)|" \
++ -e "s|%libdir%|$(installdir)|" \
+ -e "s|%MOZ_APP_NAME%|$(MOZ_APP_NAME)|" \
+ -e "s|%MOZILLA_VERSION%|$(MOZ_APP_VERSION)|" \
+ -e "s|%WCHAR_CFLAGS%|$(WCHAR_CFLAGS)|" \
+diff -Nur mozilla-1.9.2.orig/xulrunner/installer/mozilla-gtkmozembed-embedding.pc.in mozilla-1.9.2/xulrunner/installer/mozilla-gtkmozembed-embedding.pc.in
+--- mozilla-1.9.2.orig/xulrunner/installer/mozilla-gtkmozembed-embedding.pc.in 2010-01-21 05:31:27.000000000 +0200
++++ mozilla-1.9.2/xulrunner/installer/mozilla-gtkmozembed-embedding.pc.in 2010-01-21 22:28:15.000000000 +0200
+@@ -1,5 +1,6 @@
+ prefix=%prefix%
+ sdkdir=%sdkdir%
++libdir=%libdir%
+ includedir=%includedir%
+
+ Name: mozilla-gtkembedmoz
+diff -Nur mozilla-1.9.2.orig/xulrunner/installer/mozilla-gtkmozembed.pc.in mozilla-1.9.2/xulrunner/installer/mozilla-gtkmozembed.pc.in
+--- mozilla-1.9.2.orig/xulrunner/installer/mozilla-gtkmozembed.pc.in 2010-01-21 05:31:27.000000000 +0200
++++ mozilla-1.9.2/xulrunner/installer/mozilla-gtkmozembed.pc.in 2010-01-21 22:28:27.000000000 +0200
+@@ -1,5 +1,6 @@
+ prefix=%prefix%
+ sdkdir=%sdkdir%
++libdir=%libdir%
+ includedir=%includedir%
+
+ Name: mozilla-gtkembedmoz
+diff -Nur mozilla-1.9.2.orig/xulrunner/installer/mozilla-js.pc.in mozilla-1.9.2/xulrunner/installer/mozilla-js.pc.in
+--- mozilla-1.9.2.orig/xulrunner/installer/mozilla-js.pc.in 2010-01-21 05:31:27.000000000 +0200
++++ mozilla-1.9.2/xulrunner/installer/mozilla-js.pc.in 2010-01-21 22:29:30.000000000 +0200
+@@ -7,4 +7,4 @@
+ Version: %MOZILLA_VERSION%
+ Requires: %NSPR_NAME% >= %NSPR_VERSION%
+ Libs: -L${sdkdir}/lib %MOZ_JS_LINK%
+-Cflags: -I${includedir} -DXP_UNIX -DJS_THREADSAFE
++Cflags: -I${includedir} -I${includedir}/js -DXP_UNIX -DJS_THREADSAFE
diff --git a/main/xulrunner/mozjs-c99math.patch b/main/xulrunner/mozjs-c99math.patch
new file mode 100644
index 0000000000..fdf346e495
--- /dev/null
+++ b/main/xulrunner/mozjs-c99math.patch
@@ -0,0 +1,33 @@
+--- mozilla-1.9.2.orig/js/src/jsnum.h
++++ mozilla-1.9.2/js/src/jsnum.h
+@@ -98,7 +98,7 @@
+ #ifdef WIN32
+ return _finite(d);
+ #else
+- return finite(d);
++ return isfinite(d);
+ #endif
+ }
+
+--- mozilla-2.0.orig/js/src/ctypes/CTypes.cpp
++++ mozilla-2.0/js/src/ctypes/CTypes.cpp
+@@ -464,7 +464,7 @@
+ #ifdef WIN32
+ return _finite(f) != 0;
+ #else
+- return finite(f);
++ return isfinite(f);
+ #endif
+ }
+
+--- mozilla-2.0.orig/content/base/public/nsContentUtils.h
++++ mozilla-2.0/content/base/public/nsContentUtils.h
+@@ -1942,7 +1942,7 @@
+ #ifdef WIN32
+ return _finite(f);
+ #else
+- return finite(f);
++ return isfinite(f);
+ #endif
+ }
+
diff --git a/main/xulrunner/xulrunner-jemalloc-aslr.patch b/main/xulrunner/xulrunner-jemalloc-aslr.patch
new file mode 100644
index 0000000000..4a1579649d
--- /dev/null
+++ b/main/xulrunner/xulrunner-jemalloc-aslr.patch
@@ -0,0 +1,54 @@
+diff -r 9259fdc3570c memory/jemalloc/jemalloc.c
+--- a/memory/jemalloc/jemalloc.c Wed Jan 27 16:20:05 2010 -0800
++++ b/memory/jemalloc/jemalloc.c Wed Jan 27 23:03:56 2010 -0600
+@@ -373,7 +373,7 @@
+ static const bool __isthreaded = true;
+ #endif
+
+-#if defined(MOZ_MEMORY_SOLARIS) && defined(MAP_ALIGN) && !defined(JEMALLOC_NEVER_USES_MAP_ALIGN)
++#if defined(MOZ_MEMORY_SOLARIS) || defined(MOZ_MEMORY_LINUX) || defined(MOZ_MEMORY_BSD)
+ #define JEMALLOC_USES_MAP_ALIGN /* Required on Solaris 10. Might improve performance elsewhere. */
+ #endif
+
+@@ -2178,20 +2178,31 @@
+ * We don't use MAP_FIXED here, because it can cause the *replacement*
+ * of existing mappings, and we only want to create new mappings.
+ */
+-#ifdef MALLOC_PAGEFILE
+- if (pfd != -1) {
+- ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
+- MAP_NOSYNC | MAP_ALIGN, pfd, 0);
+- } else
+-#endif
+- {
+- ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
+- MAP_NOSYNC | MAP_ALIGN | MAP_ANON, -1, 0);
+- }
++ ret = mmap(NULL, size + alignment, PROT_READ | PROT_WRITE, MAP_PRIVATE |
++ MAP_NOSYNC| MAP_ANON, -1, 0);
+ assert(ret != NULL);
+
+ if (ret == MAP_FAILED)
+ ret = NULL;
++ else {
++ uintptr_t aligned_ret;
++ size_t extra_size;
++
++ aligned_ret = (uintptr_t)ret + alignment - 1;
++ aligned_ret &= ~(alignment - 1);
++ extra_size = aligned_ret - (uintptr_t)ret;
++ munmap(ret, extra_size);
++ munmap(ret + extra_size + size, alignment - extra_size);
++ ret = (void *)aligned_ret;
++#ifdef MALLOC_PAGEFILE
++ if (pfd != -1) {
++ ret = mmap(ret, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
++ MAP_NOSYNC | MAP_FIXED, pfd, 0);
++ }
++ if (ret == MAP_FAILED)
++ ret = NULL;
++#endif
++ }
+ return (ret);
+ }
+ #endif
diff --git a/main/xulrunner/xulrunner-mozalloc.patch b/main/xulrunner/xulrunner-mozalloc.patch
new file mode 100644
index 0000000000..31027a23e8
--- /dev/null
+++ b/main/xulrunner/xulrunner-mozalloc.patch
@@ -0,0 +1,11 @@
+--- mozilla-2.0.orig/memory/mozalloc/mozalloc.cpp
++++ mozilla-2.0/memory/mozalloc/mozalloc.cpp
+@@ -237,7 +237,7 @@
+ return 0;
+
+ #if defined(MOZ_MEMORY)
+- return malloc_usable_size(ptr);
++ return 0;
+ #elif defined(XP_MACOSX)
+ return malloc_size(ptr);
+ #elif defined(XP_WIN)
diff --git a/main/xvidcore/APKBUILD b/main/xvidcore/APKBUILD
new file mode 100644
index 0000000000..e3bbfa68f9
--- /dev/null
+++ b/main/xvidcore/APKBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xvidcore
+pkgver=1.3.2
+pkgrel=0
+pkgdesc="XviD is an open source MPEG-4 video codec"
+url="http://www.xvid.org/"
+arch="all"
+license="GPL"
+subpackages="$pkgname-dev"
+depends=
+makedepends="nasm"
+source="http://downloads.xvid.org/downloads/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname/build/generic
+ ./configure --prefix=/usr \
+ --disable-assembly
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/$pkgname/build/generic
+ make DESTDIR="$pkgdir" install
+ cd "$pkgdir"/usr/lib
+ mylib=$(basename libxvidcore.so.*)
+ ln -sf ${mylib} libxvidcore.so.4
+ ln -sf ${mylib} libxvidcore.so
+}
+md5sums="34389e980d4f849688f8b1e168f4e2f9 xvidcore-1.3.2.tar.bz2"
diff --git a/main/xvinfo/APKBUILD b/main/xvinfo/APKBUILD
new file mode 100644
index 0000000000..c4aea3448e
--- /dev/null
+++ b/main/xvinfo/APKBUILD
@@ -0,0 +1,22 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xvinfo
+pkgver=1.0.2
+pkgrel=2
+pkgdesc="Print out X-Video extension adaptor information"
+url="http://xorg.freedesktop.org/"
+arch="all"
+license="custom"
+subpackages="$pkgname-doc"
+makedepends="pkgconfig libxv-dev"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="e1e318436f49e2f0f3764593dadd9ad2 xvinfo-1.0.2.tar.bz2"
diff --git a/main/xwininfo/APKBUILD b/main/xwininfo/APKBUILD
new file mode 100644
index 0000000000..32313ccb8a
--- /dev/null
+++ b/main/xwininfo/APKBUILD
@@ -0,0 +1,35 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xwininfo
+pkgver=1.0.5
+pkgrel=2
+pkgdesc="Window information utility for X"
+url="http://cgit.freedesktop.org/xorg/app/xwininfo/"
+arch="all"
+license="custom"
+depends=
+makedepends="libx11-dev libxext-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://xorg.freedesktop.org/releases/individual/app/xwininfo-$pkgver.tar.bz2"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+
+md5sums="908f8bc3255f639effa9780fb1c19ea4 xwininfo-1.0.5.tar.bz2"
diff --git a/main/xz/APKBUILD b/main/xz/APKBUILD
new file mode 100644
index 0000000000..786a31ed38
--- /dev/null
+++ b/main/xz/APKBUILD
@@ -0,0 +1,38 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xz
+pkgver=5.0.3
+pkgrel=1
+pkgdesc="Library and command line tools for XZ and LZMA compressed files"
+url="http://tukaani.org/xz/"
+arch="all"
+license="GPL LGPL custom"
+depends=""
+makedepends=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-libs"
+source="http://tukaani.org/xz/xz-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build ()
+{
+ cd $srcdir/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-rpath \
+ --enable-werror
+ sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
+ sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
+ make
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+ rm "$pkgdir"/usr/lib/*.la
+}
+
+libs() {
+ pkgdesc="Libraries for decoding LZMA compression"
+ mkdir -p "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/lib*.so.* "$subpkgdir"/usr/lib/
+}
+
+md5sums="fefe52f9ecd521de2a8ce38c21a27574 xz-5.0.3.tar.gz"
diff --git a/main/yaboot/APKBUILD b/main/yaboot/APKBUILD
new file mode 100644
index 0000000000..b1e01df8f3
--- /dev/null
+++ b/main/yaboot/APKBUILD
@@ -0,0 +1,38 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer: William Pitcock <nenolod@dereferenced.org>
+pkgname=yaboot
+pkgver=1.3.16
+pkgrel=0
+pkgdesc="bootloader for openfirmware-based machines (new-world macintosh, as well as ibm rs/6000, pseries and openpower)"
+url="http://yaboot.ozlabs.org/"
+arch="powerpc"
+license=""
+depends=
+depends_dev=
+makedepends="$depends_dev"
+install=""
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://yaboot.ozlabs.org/releases/${pkgname}-${pkgver}.tar.gz"
+
+_builddir=
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ make PREFIX="/usr" || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make ROOT="$pkgdir" PREFIX="/usr" install || return 1
+}
+
+md5sums="dd8f436cf23d562c8a9f6ff513e1f435 yaboot-1.3.16.tar.gz"
diff --git a/main/yasm/APKBUILD b/main/yasm/APKBUILD
new file mode 100644
index 0000000000..5ec0ba6ecf
--- /dev/null
+++ b/main/yasm/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=yasm
+pkgver=1.1.0
+pkgrel=1
+pkgdesc="A rewrite of NASM to allow for multiple syntax supported (NASM, TASM, GAS, etc.)"
+url="http://www.tortall.net/projects/yasm/"
+arch="all"
+license="custom"
+depends=
+makedepends=
+subpackages="$pkgname-dev $pkgname-doc"
+source="http://www.tortall.net/projects/$pkgname/releases/$pkgname-$pkgver.tar.gz"
+
+_builddir="$srcdir"/$pkgname-$pkgver
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
+}
+md5sums="8392e5f2235c2c2a981e1a633f2698cb yasm-1.1.0.tar.gz"
diff --git a/main/zabbix/APKBUILD b/main/zabbix/APKBUILD
new file mode 100644
index 0000000000..a4d8b63b87
--- /dev/null
+++ b/main/zabbix/APKBUILD
@@ -0,0 +1,163 @@
+# Contributor: Jeff Bilyk <jbilyk at gmail>
+# Maintainer: Natanael Copa <natanael.copa@gmail.com>
+pkgname=zabbix
+pkgver=1.8.5
+pkgrel=0
+pkgdesc="Enterprise-class open source distributed monitoring"
+url="www.zabbix.com"
+arch="all"
+license="GPL"
+depends="fping"
+makedepends="postgresql-dev curl-dev libiconv-dev net-snmp-dev
+ sqlite-dev mysql-dev curl-dev"
+install="$pkgname.pre-install"
+pkgusers="zabbix"
+pkggroups="zabbix"
+subpackages="$pkgname-doc $pkgname-agent $pkgname-pgsql $pkgname-mysql
+ $pkgname-webif $pkgname-sqlite $pkgname-utils $pkgname-setup"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ zabbix_server.conf
+ zabbix_trapper.conf
+ zabbix_proxy.conf
+ zabbix_agentd.conf
+ zabbix-dn_skipname.patch
+ zabbix-getloadavg.patch
+ zabbix-server.initd
+ zabbix-agentd.initd
+ zabbix-proxy.initd
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+
+prepare() {
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch)
+ msg "Applying $i"
+ patch -p1 -i "$srcdir"/$i || return 1
+ ;;
+ esac
+ done
+}
+
+build() {
+ # set default configure flags
+ _configure="--prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-server \
+ --enable-agent \
+ --enable-proxy \
+ --enable-ipv6 \
+ --with-net-snmp \
+ --with-libcurl
+ "
+ # we run build for each db type
+ # make sure prepare is same for each db
+ for db in pgsql mysql sqlite3; do
+ cd "$srcdir"
+ msg "Building for $db"
+ cp -r "$pkgname-$pkgver" "$pkgname-$pkgver-$db"
+ cd "$_builddir-$db"
+ ./configure --with-$db \
+ $_configure
+ make || return 1
+ done
+}
+
+
+package() {
+ # doing manual install
+ for i in agentd proxy server; do
+ install -D -m755 "$_builddir"/man/zabbix_$i.man \
+ "$pkgdir"/usr/share/man/man8/zabbix_$i.8
+ done
+ for i in get sender; do
+ install -D -m755 "$_builddir"/man/zabbix_$i.man \
+ "$pkgdir"/usr/share/man/man1/zabbix_$i.1
+ done
+ install -d -m0750 -o zabbix -g zabbix \
+ "$pkgdir"/var/run/zabbix "$pkgdir"/var/log/zabbix
+ install -D -m0644 "$srcdir"/zabbix_server.conf \
+ "$pkgdir"/etc/zabbix/zabbix_server.conf
+ install -D -m0644 "$srcdir"/zabbix_trapper.conf \
+ "$pkgdir"/etc/zabbix/zabbix_trapper.conf
+ for i in server proxy; do
+ install -D -m0755 "$srcdir"/zabbix-$i.initd \
+ "$pkgdir"/etc/init.d/zabbix-$i || return 1
+ done
+}
+
+setup() {
+ pkgdesc="Zabbix images and sql files"
+ depends=
+ mkdir -p "$subpkgdir"/usr/share/zabbix/create
+ mv "$srcdir"/$pkgname-$pkgver/create/data \
+ "$subpkgdir"/usr/share/zabbix/create
+ mv "$srcdir"/$pkgname-$pkgver/create/schema \
+ "$subpkgdir"/usr/share/zabbix/create
+}
+
+_do_db() {
+ pkgdesc="Zabbix server with $1 database support"
+ depends=$pkgname
+ mkdir -p "$subpkgdir"/usr/sbin
+ mv "$_builddir-$1"/src/zabbix_server/zabbix_server \
+ "$subpkgdir"/usr/sbin/ || return 1
+ mv "$_builddir-$1"/src/zabbix_proxy/zabbix_proxy \
+ "$subpkgdir"/usr/sbin/ || return 1
+ return 0
+}
+
+pgsql() { _do_db pgsql; }
+mysql() { _do_db mysql; }
+sqlite() { _do_db sqlite3; }
+
+utils() {
+ pkgdesc="Zabbix client utilities"
+ depends=
+ mkdir -p "$subpkgdir"/usr/bin
+ mv "$_builddir-pgsql"/src/zabbix_get/zabbix_get \
+ "$subpkgdir"/usr/bin
+ mv "$_builddir-pgsql"/src/zabbix_sender/zabbix_sender \
+ "$subpkgdir"/usr/bin
+}
+
+webif() {
+ pkgdesc="Zabbix web-interface"
+ depends="php php-pgsql php-gd php-curl php-bcmath php-sockets php-iconv"
+ _wwwdir="$subpkgdir"/usr/share/webapps/zabbix
+ mkdir -p $_wwwdir
+ mv "$_builddir"/frontends/php/* "$_wwwdir"
+}
+
+agent() {
+ pkgdesc="Zabbix Network Monitoring Agent"
+ depends=
+ install="$subpkgname.pre-install"
+ install -d -m0750 -o zabbix -g zabbix \
+ "$subpkgdir"/var/run/zabbix "$subpkgdir"/var/log/zabbix
+ install -D -m0644 "$srcdir"/zabbix_agentd.conf \
+ "$subpkgdir"/etc/zabbix/zabbix_agentd.conf
+ install -D -m0755 "$srcdir"/zabbix-agentd.initd \
+ "$subpkgdir"/etc/init.d/zabbix-agentd
+ mkdir -p "$subpkgdir"/usr/sbin
+ mv "$_builddir-pgsql"/src/zabbix_agent/zabbix_agent \
+ "$subpkgdir"/usr/sbin/
+ mv "$_builddir-pgsql"/src/zabbix_agent/zabbix_agentd \
+ "$subpkgdir"/usr/sbin/
+
+}
+
+md5sums="58b9253fb0eace1e20b2fe5c1fce32a3 zabbix-1.8.5.tar.gz
+26b0401a83bdb1dce29338e5b2786620 zabbix_server.conf
+9832a81e134c8e2c11e2a06b7adbf88f zabbix_trapper.conf
+0310b92afb3f35c1075fff53db737212 zabbix_proxy.conf
+721c18077fa739f956340afca9f067f4 zabbix_agentd.conf
+a55a4d0b2e13c97c280006ba4bee0afa zabbix-dn_skipname.patch
+8d1d2e53479173aac0df0c38a4d6afda zabbix-getloadavg.patch
+e42394e798ab98a8ff4babe68e04633a zabbix-server.initd
+88374bba8a8fdfabfcfe9be6dd12095f zabbix-agentd.initd
+32abde1cc00c2eeccddb7e038117d0ab zabbix-proxy.initd"
diff --git a/main/zabbix/zabbix-agent.pre-install b/main/zabbix/zabbix-agent.pre-install
new file mode 100644
index 0000000000..c196223a7e
--- /dev/null
+++ b/main/zabbix/zabbix-agent.pre-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+addgroup zabbix 2>/dev/null
+adduser -S -H -h /dev/null -s /bin/false -D -G zabbix zabbix 2>/dev/null
+addgroup -g 30 zabbix 2>/dev/null
+exit 0
diff --git a/main/zabbix/zabbix-agentd.initd b/main/zabbix/zabbix-agentd.initd
new file mode 100644
index 0000000000..b14b5fe74b
--- /dev/null
+++ b/main/zabbix/zabbix-agentd.initd
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-analyzer/zabbix/files/1.6.6/init.d/zabbix-agentd,v 1.1 2009/10/05 15:55:23 patrick Exp $
+
+depend() {
+ need net
+ provide zabbix-agent
+ use zabbix-server
+}
+
+start() {
+ ebegin "Starting Zabbix agent"
+ start-stop-daemon --start -c zabbix:zabbix --exec /usr/sbin/zabbix_agentd
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping Zabbix agent"
+ start-stop-daemon --stop -u zabbix --pidfile /var/run/zabbix/zabbix_agentd.pid
+ eend $?
+}
diff --git a/main/zabbix/zabbix-dn_skipname.patch b/main/zabbix/zabbix-dn_skipname.patch
new file mode 100644
index 0000000000..5d20639713
--- /dev/null
+++ b/main/zabbix/zabbix-dn_skipname.patch
@@ -0,0 +1,44 @@
+diff --git a/src/libs/zbxsysinfo/common/net.c b/src/libs/zbxsysinfo/common/net.c
+index c8956a6..645fd8c 100644
+--- a/src/libs/zbxsysinfo/common/net.c
++++ b/src/libs/zbxsysinfo/common/net.c
+@@ -26,6 +26,39 @@
+
+ #include "net.h"
+
++#if defined(__UCLIBC__)
++/*
++ * Skip over a compressed domain name. Return the size or -1.
++ */
++int
++dn_skipname(const u_char *comp_dn, const u_char *eom)
++{
++ const u_char *cp;
++ int n;
++
++ cp = comp_dn;
++ while (cp < eom && (n = *cp++)) {
++ /*
++ * check for indirection
++ */
++ switch (n & INDIR_MASK) {
++ case 0: /* normal case, n == len */
++ cp += n;
++ continue;
++ case INDIR_MASK: /* indirection */
++ cp++;
++ break;
++ default: /* illegal type */
++ return (-1);
++ }
++ break;
++ }
++ if (cp > eom)
++ return (-1);
++ return (cp - comp_dn);
++}
++#endif
++
+ /*
+ * 0 - NOT OK
+ * 1 - OK
diff --git a/main/zabbix/zabbix-getloadavg.patch b/main/zabbix/zabbix-getloadavg.patch
new file mode 100644
index 0000000000..44706abeb8
--- /dev/null
+++ b/main/zabbix/zabbix-getloadavg.patch
@@ -0,0 +1,33 @@
+diff --git a/src/libs/zbxsysinfo/linux/cpu.c b/src/libs/zbxsysinfo/linux/cpu.c
+index a76e756..9f9031d 100644
+--- a/src/libs/zbxsysinfo/linux/cpu.c
++++ b/src/libs/zbxsysinfo/linux/cpu.c
+@@ -22,6 +22,28 @@
+ #include "sysinfo.h"
+ #include "stats.h"
+
++#ifndef HAVE_GETLOADAVG
++/*! \brief Alternative method of getting load avg on Linux only */
++int getloadavg(double *list, int nelem)
++{
++ FILE *LOADAVG;
++ double avg[3] = { 0.0, 0.0, 0.0 };
++ int i, res = -1;
++
++ if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
++ fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
++ res = 0;
++ fclose(LOADAVG);
++ }
++
++ for (i = 0; (i < nelem) && (i < 3); i++) {
++ list[i] = avg[i];
++ }
++
++ return res;
++}
++#endif
++
+ int SYSTEM_CPU_NUM(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
+ {
+ char mode[32];
diff --git a/main/zabbix/zabbix-proxy.initd b/main/zabbix/zabbix-proxy.initd
new file mode 100644
index 0000000000..8ac246eccd
--- /dev/null
+++ b/main/zabbix/zabbix-proxy.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-analyzer/zabbix/files/1.6.6/init.d/zabbix-proxy,v 1.1 2009/10/06 16:24:35 patrick Exp $
+
+depend() {
+ need net
+ #use mysql postgresql
+}
+
+start() {
+ ebegin "Starting Zabbix proxy"
+ start-stop-daemon --start -c zabbix:zabbix --exec /usr/sbin/zabbix_proxy
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping Zabbix proxy"
+ start-stop-daemon --stop -u zabbix --pidfile /var/run/zabbix/zabbix_proxy.pid
+ eend $?
+}
diff --git a/main/zabbix/zabbix-server.initd b/main/zabbix/zabbix-server.initd
new file mode 100644
index 0000000000..a661cd233d
--- /dev/null
+++ b/main/zabbix/zabbix-server.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-analyzer/zabbix/files/1.6.6/init.d/zabbix-server,v 1.1 2009/10/05 15:55:23 patrick Exp $
+
+depend() {
+ need net
+ use mysql postgresql
+}
+
+start() {
+ ebegin "Starting Zabbix server"
+ start-stop-daemon --start -c zabbix:zabbix --exec /usr/sbin/zabbix_server
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping Zabbix server"
+ start-stop-daemon --stop -u zabbix --pidfile /var/run/zabbix/zabbix_server.pid
+ eend $?
+}
diff --git a/main/zabbix/zabbix.pre-install b/main/zabbix/zabbix.pre-install
new file mode 100644
index 0000000000..8a9e5193c2
--- /dev/null
+++ b/main/zabbix/zabbix.pre-install
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+addgroup zabbix 2>/dev/null
+adduser -S -H -h /dev/null -s /bin/false -D -G zabbix zabbix 2>/dev/null
+exit 0
diff --git a/main/zabbix/zabbix_agentd.conf b/main/zabbix/zabbix_agentd.conf
new file mode 100644
index 0000000000..7fe21ec41c
--- /dev/null
+++ b/main/zabbix/zabbix_agentd.conf
@@ -0,0 +1,228 @@
+# This is a config file for Zabbix Agent (Unix)
+# To get more information about Zabbix, visit http://www.zabbix.com
+
+############ GENERAL PARAMETERS #################
+
+### Option: PidFile
+# Name of PID file.
+#
+# Mandatory: no
+# Default:
+PidFile=/var/run/zabbix/zabbix_agentd.pid
+
+### Option: LogFile
+# Name of log file.
+# If not set, syslog is used.
+#
+# Mandatory: no
+# Default:
+# LogFile=
+
+LogFile=/var/log/zabbix/zabbix_agentd.log
+
+### Option: LogFileSize
+# Maximum size of log file in MB.
+# 0 - disable automatic log rotation.
+#
+# Mandatory: no
+# Range: 0-1024
+# Default:
+# LogFileSize=1
+
+### Option: DebugLevel
+# Specifies debug level
+# 0 - no debug
+# 1 - critical information
+# 2 - error information
+# 3 - warnings
+# 4 - for debugging (produces lots of information)
+#
+# Mandatory: no
+# Range: 0-4
+# Default:
+# DebugLevel=3
+
+### Option: SourceIP
+# Source IP address for outgoing connections.
+#
+# Mandatory: no
+# Default:
+# SourceIP=
+
+### Option: EnableRemoteCommands
+# Whether remote commands from Zabbix server are allowed.
+# 0 - not allowed
+# 1 - allowed
+#
+# Mandatory: no
+# Default:
+# EnableRemoteCommands=0
+
+### Option: LogRemoteCommands
+# Enable logging of executed shell commands as warnings
+# 0 - disabled
+# 1 - enabled
+#
+# Mandatory: no
+# Default:
+# LogRemoteCommands=0
+
+##### Passive checks related
+
+### Option: Server
+# List of comma delimited IP addresses (or hostnames) of Zabbix servers.
+# No spaces allowed. First entry is used for receiving list of and sending active checks.
+# Note that hostnames must resolve hostname->IP address and IP address->hostname.
+# If IPv6 support is enabled then '127.0.0.1', '::127.0.0.1', '::ffff:127.0.0.1' are treated equally.
+#
+# Mandatory: yes
+# Default:
+# Server=
+
+Server=
+
+### Option: Hostname
+# Unique, case sensitive hostname.
+# Required for active checks and must match hostname as configured on the server.
+#
+# Default:
+# Hostname=system.uname
+
+### Option: ListenPort
+# Agent will listen on this port for connections from the server.
+#
+# Mandatory: no
+# Range: 1024-32767
+# Default:
+# ListenPort=10050
+
+### Option: ListenIP
+# List of comma delimited IP addresses that the agent should listen on.
+#
+# Mandatory: no
+# Default:
+# ListenIP=0.0.0.0
+
+# ListenIP=127.0.0.1
+
+### Option: DisablePassive
+# Disable passive checks. The agent will not listen on any TCP port.
+# Only active checks will be processed.
+# 0 - do not disable
+# 1 - disable
+#
+# Mandatory: no
+# Default:
+# DisablePassive=0
+
+##### Active checks related
+
+### Option: DisableActive
+# Disable active checks. The agent will work in passive mode listening for server.
+#
+# Mandatory: no
+# Default:
+# DisableActive=0
+
+# DisableActive=1
+
+### Option: ServerPort
+# Server port for retrieving list of and sending active checks.
+#
+# Mandatory: no
+# Default:
+# ServerPort=10051
+
+### Option: RefreshActiveChecks
+# How often list of active checks is refreshed, in seconds.
+#
+# Mandatory: no
+# Range: 60-3600
+# Default:
+# RefreshActiveChecks=120
+
+### Option: BufferSend
+# Do not keep data longer than N seconds in buffer.
+#
+# Mandatory: no
+# Range: 1-3600
+# Default:
+# BufferSend=5
+
+### Option: BufferSize
+# Maximum number of values in a memory buffer. The agent will send
+# all collected data to Zabbix Server or Proxy if the buffer is full.
+#
+# Mandatory: no
+# Range: 2-65535
+# Default:
+# BufferSize=100
+
+### Option: MaxLinesPerSecond
+# Maximum number of new lines the agent will send per second to Zabbix Server
+# or Proxy processing 'log' and 'logrt' active checks.
+# The provided value will be overridden by the parameter 'maxlines',
+# provided in 'log' or 'logrt' item keys.
+#
+# Mandatory: no
+# Range: 1-1000
+# Default:
+# MaxLinesPerSecond=100
+
+
+############ ADVANCED PARAMETERS #################
+
+### Option: StartAgents
+# Number of pre-forked instances of zabbix_agentd that process passive checks.
+#
+# Mandatory: no
+# Range: 1-16
+# Default:
+# StartAgents=3
+
+### Option: Timeout
+# Spend no more than Timeout seconds on processing
+#
+# Mandatory: no
+# Range: 1-30
+# Default:
+# Timeout=3
+
+### Option: Include
+# You may include individual files or all files in a directory in the configuration file.
+#
+# Mandatory: no
+# Default:
+# Include=
+
+# Include=/etc/zabbix/zabbix_agent.userparams.conf
+# Include=/etc/zabbix/zabbix_agentd/
+
+
+####### USER-DEFINED MONITORED PARAMETERS #######
+
+### Option: UnsafeUserParameters
+# Allow all characters to be passed in arguments to user-defined parameters.
+# 0 - do not allow
+# 1 - allow
+#
+# Mandatory: no
+# Range: 0-1
+# Default:
+# UnsafeUserParameters=0
+
+### Option: UserParameter
+# User-defined parameter to monitor. There can be several user-defined parameters.
+# Format: UserParameter=<key>,<shell command>
+# Note that shell command must not return empty string or EOL only.
+# Example: UserParameter=system.test,who|wc -l
+#UserParameter=system.test,who|wc -l
+### Set of parameters for monitoring MySQL server (v3.23.42 and later)
+### Change -u<username> and add -p<password> if required
+#UserParameter=mysql.ping,mysqladmin -uroot ping|grep alive|wc -l
+#UserParameter=mysql.uptime,mysqladmin -uroot status|cut -f2 -d":"|cut -f1 -d"T"
+#UserParameter=mysql.threads,mysqladmin -uroot status|cut -f3 -d":"|cut -f1 -d"Q"
+#UserParameter=mysql.questions,mysqladmin -uroot status|cut -f4 -d":"|cut -f1 -d"S"
+#UserParameter=mysql.slowqueries,mysqladmin -uroot status|cut -f5 -d":"|cut -f1 -d"O"
+#UserParameter=mysql.qps,mysqladmin -uroot status|cut -f9 -d":"
+#UserParameter=mysql.version,mysql -V
diff --git a/main/zabbix/zabbix_proxy.conf b/main/zabbix/zabbix_proxy.conf
new file mode 100644
index 0000000000..899fac2465
--- /dev/null
+++ b/main/zabbix/zabbix_proxy.conf
@@ -0,0 +1,175 @@
+# This is config file for ZABBIX server process
+# To get more information about ZABBIX,
+# go http://www.zabbix.com
+
+############ GENERAL PARAMETERS #################
+
+# IP address (or hostname) of ZABBIX servers.
+
+Server=127.0.0.1
+
+# Server port for sending active checks
+
+ServerPort=10051
+
+# Unique hostname.
+
+Hostname=proxy
+
+# Number of pre-forked instances of pollers
+# Default value is 5
+# This parameter must be between 0 and 255
+#StartPollers=5
+
+# Number of pre-forked instances of IPMI pollers
+# Default value is 0
+# This parameter must be between 0 and 255
+#StartIPMIPollers=0
+
+# Number of pre-forked instances of pollers for unreachable hosts
+# Default value is 1
+# This parameter must be between 0 and 255
+#StartPollersUnreachable=1
+
+# Number of pre-forked instances of trappers
+# Default value is 5
+# This parameter must be between 0 and 255
+#StartTrappers=5
+
+# Number of pre-forked instances of ICMP pingers
+# Default value is 1
+# This parameter must be between 0 and 255
+#StartPingers=1
+
+# Number of pre-forked instances of discoverers
+# Default value is 1
+# This parameter must be between 0 and 255
+#StartDiscoverers=1
+
+# Number of pre-forked instances of HTTP pollers
+# Default value is 1
+# This parameter must be between 0 and 255
+#StartHTTPPollers=1
+
+# Listen port for trapper. Default port number is 10051. This parameter
+# must be between 1024 and 32767
+#ListenPort=10051
+
+# Source IP address for outgouing connections
+#SourceIP=
+
+# Listen interface for trapper. Trapper will listen all network interfaces
+# if this parameter is missing.
+#ListenIP=127.0.0.1
+
+# How often ZABBIX will perform sending hearbeat message
+# (in seconds)
+# Default value is 60 seconds
+# Set to 0 to disable heartbeat messages
+# This parameter must be between 0 and 3600
+#HeartbeatFrequency=60
+
+# How often ZABBIX will perform sync configuration data
+# (in seconds)
+# Default value is 3600 seconds (1h)
+# This parameter must be between 1 and 604800 (1 week)
+#ConfigFrequency=3600
+
+# How often ZABBIX will perform housekeeping procedure
+# (in hours)
+# Default value is 1 hour
+# Housekeeping is removing unnecessary information from
+# tables history, alert, and alarms
+# This parameter must be between 1 and 24
+#HousekeepingFrequency=1
+
+# How often ZABBIX will try to send unsent alerts
+# (in seconds)
+# Default value is 30 seconds
+#SenderFrequency=30
+
+# Local bufer size in hours. Proxy will keep collected data N hours.
+# Default value is 0 hours
+#ProxyLocalBuffer=0
+
+# Offline buffer size in hours. It is used when server is not available.
+# Older data is removed.
+# Default value is 1 hours
+#ProxyOfflineBuffer=1
+
+# Specifies debug level
+# 0 - debug is not created
+# 1 - critical information
+# 2 - error information
+# 3 - warnings (default)
+# 4 - for debugging (produces lots of information)
+#DebugLevel=3
+
+# Specifies how long we wait for agent response (in sec)
+# Must be between 1 and 30
+Timeout=5
+
+# Specifies how many seconds trapper may spend processing new data
+# Must be between 1 and 30
+#TrapperTimeout=5
+
+# After how many seconds of unreachability treat a host as unavailable
+#UnreachablePeriod=45
+
+# How ofter check host for availability during the unreachability period
+#UnavailableDelay=15
+
+# How ofter check host for availability during the unavailability period
+#UnavailableDelay=60
+
+# Name of PID file
+PidFile=/var/run/zabbix/zabbix_proxy.pid
+
+# Name of log file
+# If not set, syslog is used
+LogFile=/var/log/zabbix/zabbix_proxy.log
+
+# Maximum size of log file in MB. Set to 0 to disable automatic log rotation.
+LogFileSize=1
+
+# Location for custom alert scripts
+AlertScriptsPath=/home/zabbix/bin/
+
+# Location of external scripts
+#ExternalScripts=/etc/zabbix/externalscripts
+
+# Location of 'fping. Default is /usr/sbin/fping
+# Make sure that fping binary has root permissions and SUID flag set
+#FpingLocation=/usr/sbin/fping
+
+# Location of fping6. Default is /usr/sbin/fping6
+# Make sure that fping binary has root permissions and SUID flag set
+#Fping6Location=/usr/sbin/fping6
+
+# Temporary directory. Default is /tmp
+#TmpDir=/tmp
+
+# Frequency of ICMP pings (item keys 'icmpping' and 'icmppingsec'). Defauls is 60 seconds.
+#PingerFrequency=60
+
+# Database host name
+# Default is localhost
+
+#DBHost=localhost
+
+# Database name
+# SQLite3 note: path to database file must be provided. DBUser and DBPassword are ignored.
+DBName=proxy
+
+# Database user
+
+DBUser=root
+
+# Database password
+# Comment this line if no password used
+
+#DBPassword=<password>
+
+# Connect to MySQL using Unix socket?
+
+#DBSocket=/tmp/mysql.sock
diff --git a/main/zabbix/zabbix_server.conf b/main/zabbix/zabbix_server.conf
new file mode 100644
index 0000000000..39c12ef0d9
--- /dev/null
+++ b/main/zabbix/zabbix_server.conf
@@ -0,0 +1,155 @@
+# This is config file for ZABBIX server process
+# To get more information about ZABBIX,
+# go http://www.zabbix.com
+
+############ GENERAL PARAMETERS #################
+
+# This defines unique NodeID in distributed setup,
+# Default value 0 (standalone server)
+# This parameter must be between 0 and 999
+#NodeID=0
+
+# Number of pre-forked instances of pollers
+# Default value is 5
+# This parameter must be between 0 and 255
+#StartPollers=5
+
+# Number of pre-forked instances of IPMI pollers
+# Default value is 0
+# This parameter must be between 0 and 255
+#StartIPMIPollers=0
+
+# Number of pre-forked instances of pollers for unreachable hosts
+# Default value is 1
+# This parameter must be between 0 and 255
+#StartPollersUnreachable=1
+
+# Number of pre-forked instances of trappers
+# Default value is 5
+# This parameter must be between 0 and 255
+#StartTrappers=5
+
+# Number of pre-forked instances of ICMP pingers
+# Default value is 1
+# This parameter must be between 0 and 255
+#StartPingers=1
+
+# Number of pre-forked instances of discoverers
+# Default value is 1
+# This parameter must be between 0 and 255
+#StartDiscoverers=1
+
+# Number of pre-forked instances of HTTP pollers
+# Default value is 1
+# This parameter must be between 0 and 255
+#StartHTTPPollers=1
+
+# Listen port for trapper. Default port number is 10051. This parameter
+# must be between 1024 and 32767
+
+#ListenPort=10051
+
+# Source IP address for outgouing connections
+#SourceIP=
+
+# Listen interface for trapper. Trapper will listen all network interfaces
+# if this parameter is missing.
+
+#ListenIP=127.0.0.1
+
+# How often ZABBIX will perform housekeeping procedure
+# (in hours)
+# Default value is 1 hour
+# Housekeeping is removing unnecessary information from
+# tables history, alert, and alarms
+# This parameter must be between 1 and 24
+
+#HousekeepingFrequency=1
+
+# How often ZABBIX will try to send unsent alerts
+# (in seconds)
+# Default value is 30 seconds
+SenderFrequency=30
+
+# Uncomment this line to disable housekeeping procedure
+#DisableHousekeeping=1
+
+# Specifies debug level
+# 0 - debug is not created
+# 1 - critical information
+# 2 - error information
+# 3 - warnings (default)
+# 4 - for debugging (produces lots of information)
+
+DebugLevel=3
+
+# Specifies how long we wait for agent response (in sec)
+# Must be between 1 and 30
+Timeout=5
+
+# Specifies how many seconds trapper may spend processing new data
+# Must be between 1 and 30
+#TrapperTimeout=5
+
+# After how many seconds of unreachability treat a host as unavailable
+#UnreachablePeriod=45
+
+# How ofter check host for availability during the unreachability period
+#UnavailableDelay=15
+
+# How ofter check host for availability during the unavailability period
+#UnavailableDelay=60
+
+# Name of PID file
+
+PidFile=/var/run/zabbix/zabbix_server.pid
+
+# Name of log file
+# If not set, syslog is used
+
+LogFile=/var/log/zabbix/zabbix_server.log
+
+# Maximum size of log file in MB. Set to 0 to disable automatic log rotation.
+LogFileSize=2
+
+# Location for custom alert scripts
+AlertScriptsPath=/home/zabbix/bin/
+
+# Location of external scripts
+#ExternalScripts=/etc/zabbix/externalscripts
+
+# Location of fping. Default is /usr/sbin/fping
+# Make sure that fping binary has root permissions and SUID flag set
+#FpingLocation=/usr/sbin/fping
+
+# Location of fping6. Default is /usr/sbin/fping6
+# Make sure that fping binary has root permissions and SUID flag set
+#Fping6Location=/usr/sbin/fping6
+
+# Temporary directory. Default is /tmp
+#TmpDir=/tmp
+
+# Frequency of ICMP pings (item keys 'icmpping' and 'icmppingsec'). Defauls is 60 seconds.
+#PingerFrequency=60
+
+# Database host name
+# Default is localhost
+
+#DBHost=localhost
+
+# Database name
+# SQLite3 note: path to database file must be provided. DBUser and DBPassword are ignored.
+DBName=zabbix
+
+# Database user
+
+DBUser=root
+
+# Database password
+# Comment this line if no password used
+
+#DBPassword=<password>
+
+# Connect to MySQL using Unix socket?
+
+#DBSocket=/tmp/mysql.sock
diff --git a/main/zabbix/zabbix_trapper.conf b/main/zabbix/zabbix_trapper.conf
new file mode 100644
index 0000000000..7f235f66bc
--- /dev/null
+++ b/main/zabbix/zabbix_trapper.conf
@@ -0,0 +1,44 @@
+# This is config file for zabbix_trapper
+# To get more information about ZABBIX,
+# go http://www.zabbix.com
+
+############ GENERAL PARAMETERS #################
+
+# Specifies debug level
+# 1 - critical information
+# 2 - warnings (default)
+# 3 - for debugging (produces lots of information)
+
+DebugLevel=2
+
+# Spend no more than Timeout seconds on processing
+# Must be between 1 and 30
+
+Timeout=3
+
+# Name of log file
+# If not set, syslog will be used
+
+LogFile=/var/log/zabbix/zabbix_trapper.log
+
+# Database host name
+# Default is localhost
+
+DBHost=localhost
+
+# Database name
+
+DBName=zabbix
+
+# Database user
+
+DBUser=zabbix
+
+# Database password
+# Comment this line if no password used
+
+DBPassword=zabbix
+
+# Connect to MySQL usig Unix socket?
+
+#DBSocket=/tmp/mysql.sock
diff --git a/main/zenity/APKBUILD b/main/zenity/APKBUILD
new file mode 100644
index 0000000000..e0a8aac16b
--- /dev/null
+++ b/main/zenity/APKBUILD
@@ -0,0 +1,47 @@
+# Contributor: William Pitcock <nenolod@dereferenced.org>
+# Maintainer:
+pkgname=zenity
+pkgver=2.32.1
+pkgrel=0
+pkgdesc="GTK+-based xdialog replacement"
+url="http://www.gnome.org/"
+arch="all"
+license="GPL"
+depends=
+makedepends="gtk+-dev intltool gnome-doc-utils libnotify-dev"
+install=""
+subpackages="$pkgname-doc"
+source="ftp://ftp.gnome.org/pub/GNOME/sources/${pkgname}/${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2"
+
+_builddir="${srcdir}/${pkgname}-${pkgver}"
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-scrollkeeper || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+doc() {
+ mkdir -p ${subpkgdir}/usr/share/gnome
+ mv ${pkgdir}/usr/share/gnome/help ${subpkgdir}/usr/share/gnome
+
+ return 0
+}
+
+md5sums="aa66ec35451b16e424519b4973082170 zenity-2.32.1.tar.bz2"
diff --git a/main/zip/10-zip-3.0-build.patch b/main/zip/10-zip-3.0-build.patch
new file mode 100644
index 0000000000..5ddad23b95
--- /dev/null
+++ b/main/zip/10-zip-3.0-build.patch
@@ -0,0 +1,36 @@
+respect build environment settings
+
+--- unix/configure Wed Jan 28 22:22:13 2009
++++ unix/configure Wed Jan 28 22:23:54 2009
+@@ -18,7 +18,7 @@
+
+ CC=${1-cc}
+ CFLAGS=${2-"-I. -DUNIX"}
+-LFLAGS1=''
++LFLAGS1="${LDFLAGS}"
+ LFLAGS2=''
+ LN="ln -s"
+
+@@ -118,7 +118,7 @@
+ fi
+
+ # optimization flags
+-if test -n "${CFLAGS_OPT}"; then
++if false; then
+ CFLAGS="${CFLAGS} ${CFLAGS_OPT}"
+ CFLAGS_BZ="${CFLAGS_BZ} ${CFLAGS_OPT}"
+ fi
+@@ -220,13 +220,6 @@
+ echo Check for the C preprocessor
+ # on SVR4, cc -E does not produce correct assembler files. Need /lib/cpp.
+ CPP="${CC} -E"
+-# solaris as(1) needs -P, maybe others as well ?
+-[ -f /usr/ccs/lib/cpp ] && CPP="/usr/ccs/lib/cpp -P"
+-[ -f /usr/lib/cpp ] && CPP=/usr/lib/cpp
+-[ -f /lib/cpp ] && CPP=/lib/cpp
+-[ -f /usr/bin/cpp ] && CPP=/usr/bin/cpp
+-[ -f /xenix ] && CPP="${CC} -E"
+-[ -f /lynx.os ] && CPP="${CC} -E"
+
+ echo "#include <stdio.h>" > conftest.c
+ $CPP conftest.c >/dev/null 2>/dev/null || CPP="${CC} -E"
diff --git a/main/zip/20-zip-3.0-exec-stack.patch b/main/zip/20-zip-3.0-exec-stack.patch
new file mode 100644
index 0000000000..d85fb117b0
--- /dev/null
+++ b/main/zip/20-zip-3.0-exec-stack.patch
@@ -0,0 +1,22 @@
+add proper GNU stack markings so we dont get the default: executable
+
+--- crc_i386.S Wed Jan 28 22:22:13 2009
++++ crc_i386.S Wed Jan 28 22:27:04 2009
+@@ -302,3 +302,7 @@
+ #endif /* i386 || _i386 || _I386 || __i386 */
+
+ #endif /* !USE_ZLIB && !CRC_TABLE_ONLY */
++
++#if defined __ELF__ && defined __linux__
++.section .note.GNU-stack,"",@progbits
++#endif
+--- match.S Wed Jan 28 22:22:13 2009
++++ match.S Wed Jan 28 22:27:04 2009
+@@ -405,3 +405,7 @@
+ #endif /* i386 || _I386 || _i386 || __i386 */
+
+ #endif /* !USE_ZLIB */
++
++#if defined __ELF__ && defined __linux__
++.section .note.GNU-stack,"",@progbits
++#endif
diff --git a/main/zip/30-zip-3.0-pic.patch b/main/zip/30-zip-3.0-pic.patch
new file mode 100644
index 0000000000..14a8821b04
--- /dev/null
+++ b/main/zip/30-zip-3.0-pic.patch
@@ -0,0 +1,15 @@
+if our toolchain generates PIC by default, then do not use the hand written
+assembly files as none of it is PIC friendly.
+
+--- unix/configure Wed Jan 28 22:23:54 2009
++++ unix/configure Wed Jan 28 22:29:51 2009
+@@ -228,6 +228,9 @@
+ echo Check if we can use asm code
+ OBJA=""
+ OCRCU8=""
++piclib="$(echo | $CPP -dM $CFLAGS - | grep -i __pic__)"
++echo "Checking if compiler wants to create pic code"
++[ "$piclib" == "" ] && \
+ if eval "$CPP match.S > _match.s 2>/dev/null"; then
+ if test ! -s _match.s || grep error < _match.s > /dev/null; then
+ :
diff --git a/main/zip/APKBUILD b/main/zip/APKBUILD
new file mode 100644
index 0000000000..48c56d2793
--- /dev/null
+++ b/main/zip/APKBUILD
@@ -0,0 +1,31 @@
+# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
+pkgname=zip
+pkgver=3.0
+pkgrel=3
+pkgdesc="Creates PKZIP-compatible .zip files"
+url="http://www.info-zip.org/pub/infozip/Zip.html"
+arch="all"
+license="AS IS"
+depends=""
+makedepends=""
+source="ftp://ftp.info-${pkgname}.org/pub/info${pkgname}/src/${pkgname}30.zip
+10-zip-3.0-build.patch
+20-zip-3.0-exec-stack.patch
+30-zip-3.0-pic.patch"
+subpackages="$pkgname-doc"
+
+build ()
+{
+ cd "${srcdir}/${pkgname}30"
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p0 < $i || return 1
+ done
+ make -f unix/Makefile LOCAL_ZIP="${CFLAGS} ${CPPFLAGS}" prefix=/usr generic || return 1
+ make -f unix/Makefile prefix=${pkgdir}/usr MANDIR=${pkgdir}/usr/share/man install
+}
+
+md5sums="e88492c8abd68fa9cfba72bc08757dba zip30.zip
+c86c527b6ad487aef02954bb1607ff07 10-zip-3.0-build.patch
+f6490facf87e501b5d0c7095949515a7 20-zip-3.0-exec-stack.patch
+f0b90de421d370f1b40b0f681d3829d8 30-zip-3.0-pic.patch"
diff --git a/main/zlib/APKBUILD b/main/zlib/APKBUILD
new file mode 100644
index 0000000000..a57073b5a2
--- /dev/null
+++ b/main/zlib/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=zlib
+pkgver=1.2.5
+pkgrel=2
+pkgdesc="A compression/decompression Library"
+arch="all"
+license=custom:zlib
+url="http://zlib.net"
+depends=
+source="http://zlib.net/$pkgname-$pkgver.tar.gz
+ zlib-1.2.5-lfs-decls.patch
+ "
+subpackages="$pkgname-dev $pkgname-doc"
+
+_builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ cd "$_builddir"
+ patch -p1 -i "$srcdir"/zlib-1.2.5-lfs-decls.patch
+}
+
+build() {
+ cd "$_builddir"
+ # we trade size for a little more speed.
+ export CFLAGS="$CFLAGS -O2"
+ CHOST="${CHOST}" ./configure --prefix=/usr --libdir=/lib --shared
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make install \
+ pkgconfigdir="/usr/lib/pkgconfig" \
+ DESTDIR="$pkgdir" || return 1
+}
+
+dev() {
+ default_dev
+ mkdir -p "$subpkgdir"/lib
+ mv "$pkgdir"/lib/libz.a "$subpkgdir"/lib/libz.a
+}
+
+md5sums="c735eab2d659a96e5a594c9e8541ad63 zlib-1.2.5.tar.gz
+4cb279ea3beab621f3526bf7b7ab99e5 zlib-1.2.5-lfs-decls.patch"
diff --git a/main/zlib/zlib-1.2.5-lfs-decls.patch b/main/zlib/zlib-1.2.5-lfs-decls.patch
new file mode 100644
index 0000000000..36e26af035
--- /dev/null
+++ b/main/zlib/zlib-1.2.5-lfs-decls.patch
@@ -0,0 +1,13 @@
+Index: zlib-1.2.5/zlib.h
+===================================================================
+--- zlib-1.2.5.orig/zlib.h
++++ zlib-1.2.5/zlib.h
+@@ -1578,7 +1578,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF(
+ # define gzoffset gzoffset64
+ # define adler32_combine adler32_combine64
+ # define crc32_combine crc32_combine64
+-# ifdef _LARGEFILE64_SOURCE
++# ifndef _LARGEFILE64_SOURCE
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
diff --git a/main/znc/APKBUILD b/main/znc/APKBUILD
new file mode 100644
index 0000000000..e793a5c846
--- /dev/null
+++ b/main/znc/APKBUILD
@@ -0,0 +1,109 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=znc
+pkgver=0.098
+pkgrel=2
+pkgdesc="An advanced IRC bouncer"
+url="http://znc.in"
+arch="all"
+license="GPLv2"
+depends=
+depends_dev=
+makedepends="perl-dev openssl-dev cyrus-sasl-dev python-dev c-ares-dev swig
+ libiconv-dev tcl-dev autoconf automake"
+install=""
+subpackages="$pkgname-dev $pkgname-doc $pkgname-extra $pkgname-modtcl
+ $pkgname-modperl"
+source="http://znc.in/releases/znc-$pkgver.tar.gz
+ libiconv.patch"
+
+_builddir="$srcdir"/znc-$pkgver
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+ aclocal && autoconf || return 1
+}
+
+build() {
+ cd "$_builddir"
+ export CHARSET=
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var \
+ --enable-extra \
+ --enable-perl \
+ --enable-sasl \
+ --enable-tcl \
+ || return 1
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+_mv_to_sub() {
+ local i
+ for i in "$@"; do
+ mkdir -p "$subpkgdir"/${i%/*}
+ mv "$pkgdir"/$i "$subpkgdir"/$i || return 1
+ done
+}
+
+_mv_mod() {
+ local i
+ for i in "$@"; do
+ _mv_to_sub usr/lib/znc/$i || return 1
+ done
+}
+
+dev() {
+ default_dev
+ _mv_to_sub usr/bin/znc-buildmod
+}
+
+extra() {
+ pkgdesc="Extra modules for ZNC"
+ _mv_mod antiidle.so \
+ autovoice.so \
+ block_motd.so \
+ charset.so \
+ clearbufferonmsg.so \
+ ctcpflood.so \
+ droproot.so \
+ email.so \
+ fakeonline.so \
+ flooddetach.so \
+ imapauth.so \
+ listsockets.so \
+ log.so \
+ motdfile.so \
+ notify_connect.so \
+ saslauth.so \
+ send_raw.so \
+ shell.so
+}
+
+modtcl() {
+ pkgdesc="TCL module for ZNC"
+ depends="znc"
+ _mv_mod modtcl.so
+ _mv_to_sub usr/share/znc/modtcl
+}
+
+modperl() {
+ pkgdesc="Perl module for ZNC"
+ depends="znc"
+ _mv_mod modperl modperl.so
+}
+
+md5sums="5667b4acb1f01309d6eded77abac700c znc-0.098.tar.gz
+90b3493803bf7a3aa224e6cbbd644bdf libiconv.patch"
diff --git a/main/znc/libiconv.patch b/main/znc/libiconv.patch
new file mode 100644
index 0000000000..0af3a21048
--- /dev/null
+++ b/main/znc/libiconv.patch
@@ -0,0 +1,16 @@
+--- ./configure.ac.orig
++++ ./configure.ac
+@@ -419,7 +419,12 @@
+ if test x"$EXTRA" = "xyes"
+ then
+ AC_CHECK_FUNC( iconv, CHARSET=1 )
+- AC_CHECK_LIB( iconv, iconv_open, LIBICONV=-liconv ; CHARSET=1 )
++ dnl On some systems iconv is in a separate library, and may actually
++ dnl be named libiconv.
++ AC_CHECK_LIB( iconv, libiconv_open, LIBICONV=-liconv ; CHARSET=1 )
++ if test $ac_cv_lib_iconv_libiconv = no; then
++ AC_CHECK_LIB( iconv, iconv_open, LIBICONV=-liconv ; CHARSET=1 )
++ fi
+ if test "x$CHARSET" = "x1"
+ then
+ AC_MSG_CHECKING([whether iconv expects a const second argument])
diff --git a/main/zonenotify/APKBUILD b/main/zonenotify/APKBUILD
new file mode 100644
index 0000000000..b99a3e7b77
--- /dev/null
+++ b/main/zonenotify/APKBUILD
@@ -0,0 +1,18 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=zonenotify
+pkgver=0.1
+pkgrel=2
+pkgdesc="Utility to send NS_NOTIFY packets to slave DNS servers"
+arch="all"
+url="http://www.morettoni.net/zonenotify.en.html"
+license='BSD'
+depends=""
+source="http://www.morettoni.net/bsd/$pkgname-$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir/$pkgname"
+ make || return 1
+ install -D zonenotify "$pkgdir"/usr/bin/zonenotify
+}
+
+md5sums="1cb15b505eaa22440c7a26ea34af2514 zonenotify-0.1.tar.gz"
diff --git a/main/zsh/APKBUILD b/main/zsh/APKBUILD
new file mode 100644
index 0000000000..f6acc28263
--- /dev/null
+++ b/main/zsh/APKBUILD
@@ -0,0 +1,45 @@
+# Contributor: <kalonji@gmail.com>
+# Maintainer: <ncopa@alpinelinux.org>
+pkgname=zsh
+pkgver=4.3.12
+pkgrel=0
+pkgdesc="A very advanced and programmable command interpreter (shell) for UNIX"
+url="http://www.zsh.org/"
+arch="all"
+license="custom"
+depends=
+makedepends=ncurses-dev
+install="zsh.post-install zsh.post-upgrade zsh.pre-deinstall"
+source="ftp://ftp.zsh.org/pub/${pkgname}-${pkgver}.tar.gz
+$install"
+_builddir="$srcdir"/$pkgname-$pkgver
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --bindir=/bin \
+ --enable-etcdir=/etc/zsh \
+ --enable-zshenv=/etc/zsh/zshenv \
+ --enable-zlogin=/etc/zsh/zlogin \
+ --enable-zlogout=/etc/zsh/zlogout \
+ --enable-zprofile=/etc/profile \
+ --enable-zshrc=/etc/zsh/zshrc \
+ --enable-multibyte \
+ --enable-function-subdirs \
+ --enable-zsh-secure-free \
+ --sysconfdir=/etc \
+ --with-tcsetpgrp \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="46ae7be975779b9b0ea24e8b30479a8b zsh-4.3.12.tar.gz
+aedff0460ef282937905223207ac702e zsh.post-install
+aedff0460ef282937905223207ac702e zsh.post-upgrade
+b48f79e2d4a29047f6152f5a9441f942 zsh.pre-deinstall"
diff --git a/main/zsh/zsh.post-install b/main/zsh/zsh.post-install
new file mode 100644
index 0000000000..46506fbee0
--- /dev/null
+++ b/main/zsh/zsh.post-install
@@ -0,0 +1,3 @@
+#!/bin/sh
+grep -q '/bin/zsh' /etc/shells || echo '/bin/zsh' >> /etc/shells
+exit 0
diff --git a/main/zsh/zsh.post-upgrade b/main/zsh/zsh.post-upgrade
new file mode 100644
index 0000000000..46506fbee0
--- /dev/null
+++ b/main/zsh/zsh.post-upgrade
@@ -0,0 +1,3 @@
+#!/bin/sh
+grep -q '/bin/zsh' /etc/shells || echo '/bin/zsh' >> /etc/shells
+exit 0
diff --git a/main/zsh/zsh.pre-deinstall b/main/zsh/zsh.pre-deinstall
new file mode 100644
index 0000000000..bd078e838c
--- /dev/null
+++ b/main/zsh/zsh.pre-deinstall
@@ -0,0 +1,3 @@
+#!/bin/sh
+sed -i '/^\/bin\/zsh/d' /etc/shells
+exit 0
diff --git a/main/zsnes/APKBUILD b/main/zsnes/APKBUILD
new file mode 100644
index 0000000000..72c3d7a1d5
--- /dev/null
+++ b/main/zsnes/APKBUILD
@@ -0,0 +1,55 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=zsnes
+pkgver=1.51
+pkgrel=4
+pkgdesc="Super Nintendo emulator"
+url="http://www.zsnes.com/"
+arch="x86"
+license="GPL"
+makedepends="sdl-dev libpng-dev ncurses-dev mesa-dev automake autoconf nasm"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/${pkgname}151src.tar.bz2
+ $pkgname.desktop
+ zsnes.patch
+ zsnes-1.51-CC-quotes.patch
+ zsnes-1.51-depbuild.patch
+ zsnes-libpng15.patch
+ zsnes_icon.png"
+
+build ()
+{
+ cd "$srcdir"/${pkgname}_${pkgver%.*}_${pkgver#*.}
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+
+ cd "$srcdir"/${pkgname}_${pkgver%.*}_${pkgver#*.}/src
+ aclocal && autoconf || return 1
+ export GCC_SPECS=/usr/share/gcc/hardenednopie.specs
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man \
+ x_libraries=/usr/lib \
+ force_arch=i486 \
+ --enable-release || return 1
+ make makefile.dep
+ make || return 1
+}
+
+package() {
+ cd "$srcdir"/${pkgname}_${pkgver%.*}_${pkgver#*.}/src
+ make DESTDIR="$pkgdir" install
+ install -Dm644 "$srcdir"/zsnes.desktop \
+ "$pkgdir"/usr/share/applications/zsnes.desktop
+ install -Dm644 "$srcdir"/zsnes_icon.png \
+ "$pkgdir"/usr/share/pixmaps/zsnes_icon.png
+ mv "$pkgdir"/usr/man "$pkgdir"/usr/share
+}
+md5sums="7071186bf80632ae88a153239498d8c9 zsnes151src.tar.bz2
+b100b2aa342c551167d7c5dcdcde9dd4 zsnes.desktop
+4df831b3d87a35949bcf3fd5547decb1 zsnes.patch
+69ca17611c0d4a21529a95eb37e05c2f zsnes-1.51-CC-quotes.patch
+994af091cbb8f17f82d78c0ca89ac549 zsnes-1.51-depbuild.patch
+c9962edc521df8876b714d061458b600 zsnes-libpng15.patch
+b5260c02adfc3b7ff725041214b00bfd zsnes_icon.png"
diff --git a/main/zsnes/zsnes-1.51-CC-quotes.patch b/main/zsnes/zsnes-1.51-CC-quotes.patch
new file mode 100644
index 0000000000..a871b62604
--- /dev/null
+++ b/main/zsnes/zsnes-1.51-CC-quotes.patch
@@ -0,0 +1,20 @@
+--- a/src/Makefile.in.orig 2009-02-25 18:13:40.000000000 +0100
++++ b/src/Makefile.in 2009-02-25 18:13:16.000000000 +0100
+@@ -95,7 +95,7 @@
+ %.o: %.cpp
+ @CXX@ @CXXFLAGS@ -o $@ -c $<
+ %.o %.h: %.psr $(PSR)
+- ./$(PSR) @PSRFLAGS@ -gcc @CC@ -compile -flags "@CFLAGS@ -O1" -cheader $*.h -fname $* $*.o $<
++ ./$(PSR) @PSRFLAGS@ -gcc "@CC@" -compile -flags "@CFLAGS@ -O1" -cheader $*.h -fname $* $*.o $<
+
+ default: main
+ all: main tools--- zsnes_1_51/src/Makefile.in.orig 2009-02-25 18:02:07.000000000 +0100
+@@ -133,7 +133,7 @@
+
+ include makefile.dep
+ makefile.dep: $(TOOL_D)/depbuild Makefile
+- $(TOOL_D)/depbuild @CC@ "@CFLAGS@" @NASMPATH@ "@NFLAGS@" $(Z_OBJS) > makefile.dep
++ $(TOOL_D)/depbuild "@CC@" "@CFLAGS@" @NASMPATH@ "@NFLAGS@" $(Z_OBJS) > makefile.dep
+
+ Makefile: Makefile.in config.status
+ ./config.status
diff --git a/main/zsnes/zsnes-1.51-depbuild.patch b/main/zsnes/zsnes-1.51-depbuild.patch
new file mode 100644
index 0000000000..e2cc0d86f6
--- /dev/null
+++ b/main/zsnes/zsnes-1.51-depbuild.patch
@@ -0,0 +1,34 @@
+--- a/src/tools/depbuild.cpp Fri Nov 13 18:41:24 2009
++++ b/src/tools/depbuild.cpp Fri Nov 13 19:04:09 2009
+@@ -24,6 +24,9 @@
+ #include <iostream>
+ #include <string>
+ #include <cstdio>
++#include <cstdlib>
++#include <unistd.h>
++
+ using namespace std;
+
+ #include "fileutil.h"
+@@ -130,7 +133,20 @@
+ void dependency_calculate_asm(const char *filename)
+ {
+ string command = nasm + " " + nflags + " -M " + filename;
+- system(command.c_str());
++ FILE *fp = popen(command.c_str(), "r");
++ if (fp)
++ {
++ char line[256];
++ while (fgets(line, sizeof(line), fp)) //Process all lines of output
++ {
++ cout << line;
++ }
++ pclose(fp);
++ }
++ else
++ {
++ cerr << "Failed on: " << filename << "\n";
++ }
+ }
+
+ void dependency_calculate_psr(const char *filename)
diff --git a/main/zsnes/zsnes-libpng15.patch b/main/zsnes/zsnes-libpng15.patch
new file mode 100644
index 0000000000..8f83171668
--- /dev/null
+++ b/main/zsnes/zsnes-libpng15.patch
@@ -0,0 +1,10 @@
+--- ./src/zip/zpng.c.orig
++++ ./src/zip/zpng.c
+@@ -129,7 +129,6 @@
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8,
+ PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+- info_ptr->color_type = PNG_COLOR_TYPE_RGB;
+
+ //Allocate an array of scanline pointers
+ row_pointers = (png_bytep*)malloc(height*sizeof(png_bytep));
diff --git a/main/zsnes/zsnes.desktop b/main/zsnes/zsnes.desktop
new file mode 100644
index 0000000000..db13ada4c6
--- /dev/null
+++ b/main/zsnes/zsnes.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=Zsnes
+Comment=Super Nintendo emulator
+Exec=/usr/bin/zsnes
+Icon=/usr/share/pixmaps/zsnes_icon.png
+Terminal=false
+Type=Application
+Categories=Application;Game
+StartupNotify=false
diff --git a/main/zsnes/zsnes.patch b/main/zsnes/zsnes.patch
new file mode 100644
index 0000000000..db07403845
--- /dev/null
+++ b/main/zsnes/zsnes.patch
@@ -0,0 +1,67 @@
+diff -cr zsnes_1_51/src/parsegen.cpp zsnes_1_51-patched/src/parsegen.cpp
+*** zsnes_1_51/src/parsegen.cpp 2007-10-31 01:30:26.000000000 -0300
+--- zsnes_1_51-patched/src/parsegen.cpp 2008-07-13 18:28:53.000000000 -0300
+***************
+*** 19,24 ****
+--- 19,27 ----
+ Config file handler creator by Nach (C) 2005-2007
+ */
+
++ #include <cstring>
++ #include <cstdlib>
++
+ #if !defined(__GNUC__) && !defined(_MSC_VER)
+ #error You are using an unsupported compiler
+ #endif
+***************
+*** 1822,1828 ****
+ }
+ }
+
+! int main(size_t argc, const char *const *const argv)
+ {
+ const char *cheader_file = 0;
+ bool compile = false;
+--- 1825,1831 ----
+ }
+ }
+
+! int main(int argc, const char *const *const argv)
+ {
+ const char *cheader_file = 0;
+ bool compile = false;
+diff -cr zsnes_1_51/src/tools/depbuild.cpp zsnes_1_51-patched/src/tools/depbuild.cpp
+*** zsnes_1_51/src/tools/depbuild.cpp 2006-12-27 08:04:05.000000000 -0300
+--- zsnes_1_51-patched/src/tools/depbuild.cpp 2008-07-13 18:30:46.000000000 -0300
+***************
+*** 183,189 ****
+ }
+ }
+
+! int main(size_t argc, const char *const *const argv)
+ {
+ if (argc < 5)
+ {
+--- 183,189 ----
+ }
+ }
+
+! int main(int argc, const char *const *const argv)
+ {
+ if (argc < 5)
+ {
+diff -cr zsnes_1_51/src/tools/strutil.h zsnes_1_51-patched/src/tools/strutil.h
+*** zsnes_1_51/src/tools/strutil.h 2006-12-27 08:04:05.000000000 -0300
+--- zsnes_1_51-patched/src/tools/strutil.h 2008-07-13 18:30:27.000000000 -0300
+***************
+*** 15,20 ****
+--- 15,23 ----
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
++ #include <cstring>
++ #include <cstdlib>
++
+ /*
+ This is part of a toolkit used to assist in ZSNES development
+ */
diff --git a/main/zsnes/zsnes_icon.png b/main/zsnes/zsnes_icon.png
new file mode 100644
index 0000000000..31608ba068
--- /dev/null
+++ b/main/zsnes/zsnes_icon.png
Binary files differ